xref: /netbsd-src/tests/lib/libcurses/director/testlang_parse.y (revision d25ffa98a4bfca1fe272f3c182496ec9934faac7)
1 %{
2 /*	$NetBSD: testlang_parse.y,v 1.7 2011/06/18 20:05:56 joerg Exp $	*/
3 
4 /*-
5  * Copyright 2009 Brett Lymn <blymn@NetBSD.org>
6  *
7  * All rights reserved.
8  *
9  * This code has been donated to The NetBSD Foundation by the Author.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. The name of the author may not be used to endorse or promote products
17  *    derived from this software withough specific prior written permission
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  *
31  */
32 #include <assert.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <err.h>
36 #include <unistd.h>
37 #include <poll.h>
38 #include <stdbool.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <sys/syslimits.h>
42 #include <time.h>
43 #include <vis.h>
44 #include "returns.h"
45 
46 #define YYDEBUG 1
47 
48 extern int verbose;
49 extern int cmdpipe[2];
50 extern int slvpipe[2];
51 extern int master;
52 extern struct pollfd readfd;
53 extern char *check_path;
54 extern char *cur_file;		/* from director.c */
55 
56 int yylex(void);
57 
58 size_t line;
59 
60 static int input_delay;
61 
62 /* time delay between inputs chars - default to 0.1ms minimum to prevent
63  * problems with input tests
64  */
65 #define DELAY_MIN 0.1
66 static struct timespec delay_spec = {0, 1000 * DELAY_MIN};
67 static char *input_str;	/* string to feed in as input */
68 static bool no_input;	/* don't need more input */
69 
70 #define READ_PIPE  0
71 #define WRITE_PIPE 1
72 
73 const char *returns_enum_names[] = {
74 	"unused", "numeric", "string", "byte", "ERR", "OK", "NULL", "not NULL",
75 	"variable", "reference", "returns count", "slave error"
76 };
77 
78 typedef enum {
79 	arg_static,
80 	arg_byte,
81 	arg_var,
82 	arg_null
83 } args_state_t;
84 
85 static const char *args_enum_names[] = {
86 	"static", "byte", "var", "NULL"
87 };
88 
89 typedef struct {
90 	args_state_t	arg_type;
91 	size_t		arg_len;
92 	char		*arg_string;
93 	int		var_index;
94 } args_t;
95 
96 typedef struct {
97 	char		*function;
98 	int		nrets;		/* number of returns */
99 	returns_t	*returns;	/* array of expected returns */
100 	int		nargs;		/* number of arguments */
101 	args_t		*args;		/* arguments for the call */
102 } cmd_line_t;
103 
104 static cmd_line_t	command;
105 
106 typedef struct {
107 	char *name;
108 	size_t len;
109 	returns_enum_t type;
110 	void *value;
111 } var_t;
112 
113 static size_t nvars; 		/* Number of declared variables */
114 static var_t *vars; 		/* Variables defined during the test. */
115 
116 static int	check_function_table(char *, const char *[], int);
117 static int	find_var_index(const char *);
118 static void 	assign_arg(args_state_t, void *);
119 static int	assign_var(char *);
120 void		init_parse_variables(int);
121 static void	validate(int, void *);
122 static void	validate_return(const char *, const char *, int);
123 static void	validate_variable(int, returns_enum_t, const void *, int, int);
124 static void	validate_byte(returns_t *, returns_t *, int);
125 static void	write_cmd_pipe(char *);
126 static void	write_cmd_pipe_args(args_state_t, void *);
127 static void	read_cmd_pipe(returns_t *);
128 static void	write_func_and_args(void);
129 static void	compare_streams(char *, bool);
130 static void	do_function_call(size_t);
131 static void	save_slave_output(bool);
132 static void	validate_type(returns_enum_t, returns_t *, int);
133 static void	set_var(returns_enum_t, char *, void *);
134 static void	validate_reference(int, void *);
135 static char	*numeric_or(char *, char *);
136 static char	*get_numeric_var(const char *);
137 
138 static const char *input_functions[] = {
139 	"inch", "getch", "getnstr", "getstr", "innstr", "instr", "mvgetnstr",
140 	"mvgetstr", "mvinchstr", "mvinchnstr", "mvgetnstr", "mvgetstr",
141 	"mvinchstr", "mvinchnstr", "winch", "wgetch", "wgetnstr", "wgetstr",
142 	"winchnstr", "winchstr", "winnstr", "winstr"
143 };
144 
145 static const unsigned ninput_functions =
146 	sizeof(input_functions) / sizeof(char *);
147 
148 saved_data_t saved_output;
149 
150 %}
151 
152 %union {
153 	char *string;
154 	returns_t *retval;
155 }
156 
157 %token <string> PATH
158 %token <string> STRING
159 %token <retval> BYTE
160 %token <string> VARNAME
161 %token <string> FILENAME
162 %token <string> VARIABLE
163 %token <string> REFERENCE
164 %token <string> NULL_RET
165 %token <string> NON_NULL
166 %token <string> ERR_RET
167 %token <string> OK_RET
168 %token <string> numeric
169 %token <string> DELAY
170 %token <string> INPUT
171 %token <string> COMPARE
172 %token <string> COMPAREND
173 %token <string> ASSIGN
174 %token EOL CALL CHECK NOINPUT OR LHB RHB
175 %token CALL2 CALL3 CALL4 DRAIN
176 
177 %nonassoc OR
178 
179 %%
180 
181 statement	:	/* empty */
182 		| assign statement
183 		| call statement
184 		| call2 statement
185 		| call3 statement
186 		| call4 statement
187 		| check statement
188 		| delay statement
189 		| input statement
190 		| noinput statement
191 		| compare statement
192 		| comparend statement
193 		| eol statement
194 		;
195 
196 assign		: ASSIGN VARNAME numeric {set_var(ret_number, $2, $3);} eol
197 		| ASSIGN VARNAME LHB expr RHB {set_var(ret_number, $2, $<string>4);} eol
198 		| ASSIGN VARNAME STRING {set_var(ret_string, $2, $3);} eol
199 		| ASSIGN VARNAME BYTE {set_var(ret_byte, $2, $3);} eol
200 		;
201 
202 call		: CALL result fn_name args eol {
203 	do_function_call(1);
204 }
205 		;
206 
207 call2		: CALL2 result result fn_name args eol {
208 	do_function_call(2);
209 }
210 		;
211 
212 call3		: CALL3 result result result fn_name args eol {
213 	do_function_call(3);
214 }
215 		;
216 
217 call4		: CALL4 result result result result fn_name args eol {
218 	do_function_call(4);
219  }
220 		;
221 
222 check		: CHECK var returns eol {
223 	returns_t retvar;
224 	var_t *vptr;
225 	if (command.returns[0].return_index == -1)
226 		err(1, "Undefined variable in check statement, line %zu"
227 		    " of file %s", line, cur_file);
228 
229 	if (verbose)
230 		fprintf(stderr, "Checking contents of variable %s for %s\n",
231 		    vars[command.returns[0].return_index].name,
232 		    returns_enum_names[command.returns[1].return_type]);
233 
234 	if (((command.returns[1].return_type == arg_byte) &&
235 	     (vars[command.returns[0].return_index].type != ret_byte)) ||
236 	    ((command.returns[1].return_type == arg_static) &&
237 	     (vars[command.returns[0].return_index].type != ret_string)))
238 		err(1, "Var type %s (%d) does not match return type %s (%d)",
239 		    returns_enum_names[vars[command.returns[0].return_index].type],
240 		    vars[command.returns[0].return_index].type,
241 		    returns_enum_names[command.returns[1].return_type],
242 		    command.returns[1].return_type);
243 
244 	switch (command.returns[1].return_type) {
245 	case ret_err:
246 		validate_variable(0, ret_string, "ERR",
247 				  command.returns[0].return_index, 0);
248 		break;
249 
250 	case ret_ok:
251 		validate_variable(0, ret_string, "OK",
252 				  command.returns[0].return_index, 0);
253 		break;
254 
255 	case ret_null:
256 		validate_variable(0, ret_string, "NULL",
257 				  command.returns[0].return_index, 0);
258 		break;
259 
260 	case ret_nonnull:
261 		validate_variable(0, ret_string, "NULL",
262 				  command.returns[0].return_index, 1);
263 		break;
264 
265 	case ret_string:
266 	case ret_number:
267 		if (verbose)
268 			fprintf(stderr, " %s == returned %s\n",
269 			    (const char *)command.returns[1].return_value,
270 			    (const char *)
271 			    vars[command.returns[0].return_index].value);
272 		validate_variable(0, ret_string,
273 		    command.returns[1].return_value,
274 		    command.returns[0].return_index, 0);
275 		break;
276 
277 	case ret_byte:
278 		vptr = &vars[command.returns[0].return_index];
279 		retvar.return_len = vptr->len;
280 		retvar.return_type = vptr->type;
281 		retvar.return_value = vptr->value;
282 		validate_byte(&retvar, &command.returns[1], 0);
283 		break;
284 
285 	default:
286 		err(1, "Malformed check statement at line %zu "
287 		    "of file %s", line, cur_file);
288 		break;
289 	}
290 
291 	init_parse_variables(0);
292  }
293 		;
294 
295 delay		: DELAY numeric eol {
296 	/* set the inter-character delay */
297 	if (sscanf($2, "%d", &input_delay) == 0)
298 		err(1, "delay specification %s could not be converted to "
299 		    "numeric at line %zu of file %s", $2, line, cur_file);
300 	if (verbose)
301 		fprintf(stderr, "Set input delay to %d ms\n", input_delay);
302 
303 	if (input_delay < DELAY_MIN)
304 		input_delay = 1000 * DELAY_MIN; /* ms to ns */
305 	/*
306 	 * Fill in the timespec structure now ready for use later.
307 	 * The delay is specified in milliseconds so convert to timespec
308 	 * values
309 	 */
310 	delay_spec.tv_sec = input_delay / 1000;
311 	delay_spec.tv_nsec = (input_delay - 1000 * delay_spec.tv_sec) * 1000;
312 
313 	init_parse_variables(0);
314  }
315 	;
316 
317 input		: INPUT STRING eol {
318 	if (input_str != NULL) {
319 		warnx("%s, %zu: Discarding unused input string",
320 		    cur_file, line);
321 		free(input_str);
322 	}
323 
324 	if ((input_str = malloc(strlen($2) + 1)) == NULL)
325 		err(2, "Cannot allocate memory for input string");
326 
327 	strlcpy(input_str, $2, strlen($2) + 1);
328 }
329 	;
330 
331 
332 noinput		: NOINPUT eol {
333 	if (input_str != NULL) {
334 		warnx("%s, %zu: Discarding unused input string",
335 		    cur_file, line);
336 		free(input_str);
337 	}
338 
339 	no_input = true;
340  }
341 
342 compare		: COMPARE PATH eol
343 		| COMPARE FILENAME eol
344 {
345 	compare_streams($2, true);
346 }
347 	;
348 
349 
350 comparend	: COMPAREND PATH eol
351 		| COMPAREND FILENAME eol
352 {
353 	compare_streams($2, false);
354 }
355 	;
356 
357 
358 result		: returns
359 		| var
360 		| reference
361 		;
362 
363 returns		: numeric { assign_rets(ret_number, $1); }
364 		| LHB expr RHB { assign_rets(ret_number, $<string>2); }
365 		| STRING { assign_rets(ret_string, $1); }
366 		| BYTE { assign_rets(ret_byte, (void *) $1); }
367 		| ERR_RET { assign_rets(ret_err, NULL); }
368 		| OK_RET { assign_rets(ret_ok, NULL); }
369 		| NULL_RET { assign_rets(ret_null, NULL); }
370 		| NON_NULL { assign_rets(ret_nonnull, NULL); }
371 		;
372 
373 var		: VARNAME {
374 	assign_rets(ret_var, $1);
375  }
376 		;
377 
378 reference	: VARIABLE {
379 	assign_rets(ret_ref, $1);
380  }
381 
382 fn_name		: VARNAME {
383 	if (command.function != NULL)
384 		free(command.function);
385 
386 	command.function = malloc(strlen($1) + 1);
387 	if (command.function == NULL)
388 		err(1, "Could not allocate memory for function name");
389 	strcpy(command.function, $1);
390  }
391 		;
392 
393 expr		: numeric
394 		| VARIABLE
395 			{ $<string>$ = get_numeric_var($1); }
396 		| expr OR expr
397 			{ $<string>$ = numeric_or($<string>1, $<string>3); }
398 		;
399 
400 args		: /* empty */
401 		| LHB expr RHB { assign_arg(arg_static, $<string>2); } args
402 		| numeric { assign_arg(arg_static, $1); } args
403 		| STRING { assign_arg(arg_static, $1); } args
404 		| BYTE { assign_arg(arg_byte, $1); } args
405 		| PATH { assign_arg(arg_static, $1); } args
406 		| FILENAME { assign_arg(arg_static, $1); } args
407 		| VARNAME { assign_arg(arg_static, $1); } args
408 		| VARIABLE  { assign_arg(arg_var, $1); } args
409 		| NULL_RET { assign_arg(arg_null, $1); } args
410 		;
411 
412 eol		: EOL
413 		;
414 
415 %%
416 
417 static void
418 excess(const char *fname, size_t lineno, const char *func, const char *comment,
419     const void *data, size_t datalen)
420 {
421 	size_t dstlen = datalen * 4 + 1;
422 	char *dst = malloc(dstlen);
423 
424 	if (dst == NULL)
425 		err(1, "malloc");
426 
427 	if (strnvisx(dst, dstlen, data, datalen, VIS_WHITE | VIS_OCTAL) == -1)
428 		err(1, "strnvisx");
429 
430 	warnx("%s, %zu: [%s] Excess %zu bytes%s [%s]",
431 	    fname, lineno, func, datalen, comment, dst);
432 	free(dst);
433 }
434 
435 /*
436  * Get the value of a variable, error if the variable has not been set or
437  * is not a numeric type.
438  */
439 static char *
440 get_numeric_var(const char *var)
441 {
442 	int i;
443 
444 	if ((i = find_var_index(var)) < 0)
445 		err(1, "Variable %s is undefined", var);
446 
447 	if (vars[i].type != ret_number)
448 		err(1, "Variable %s is not a numeric type", var);
449 
450 	return vars[i].value;
451 }
452 
453 /*
454  * Perform a bitwise OR on two numbers and return the result.
455  */
456 static char *
457 numeric_or(char *n1, char *n2)
458 {
459 	unsigned long i1, i2, result;
460 	char *ret;
461 
462 	i1 = strtoul(n1, NULL, 10);
463 	i2 = strtoul(n2, NULL, 10);
464 
465 	result = i1 | i2;
466 	asprintf(&ret, "%lu", result);
467 
468 	if (verbose)
469 		fprintf(stderr, "numeric or of 0x%lx (%s) and 0x%lx (%s)"
470 		    " results in 0x%lx (%s)\n",
471 		    i1, n1, i2, n2, result, ret);
472 
473 	return ret;
474 }
475 
476 /*
477  * Assign the value given to the named variable.
478  */
479 static void
480 set_var(returns_enum_t type, char *name, void *value)
481 {
482 	int i;
483 	char *number;
484 	returns_t *ret;
485 
486 	i = find_var_index(name);
487 	if (i < 0)
488 		i = assign_var(name);
489 
490 	vars[i].type = type;
491 	if ((type == ret_number) || (type == ret_string)) {
492 		number = value;
493 		vars[i].len = strlen(number) + 1;
494 		vars[i].value = malloc(vars[i].len + 1);
495 		if (vars[i].value == NULL)
496 			err(1, "Could not malloc memory for assign string");
497 		strcpy(vars[i].value, number);
498 	} else {
499 		/* can only be a byte value */
500 		ret = value;
501 		vars[i].len = ret->return_len;
502 		vars[i].value = malloc(vars[i].len);
503 		if (vars[i].value == NULL)
504 			err(1, "Could not malloc memory to assign byte string");
505 		memcpy(vars[i].value, ret->return_value, vars[i].len);
506 	}
507 }
508 
509 /*
510  * Add a new variable to the vars array, the value will be assigned later,
511  * when a test function call returns.
512  */
513 static int
514 assign_var(char *varname)
515 {
516 	var_t *temp;
517 	char *name;
518 
519 	if ((name = malloc(strlen(varname) + 1)) == NULL)
520 		err(1, "Alloc of varname failed");
521 
522 	if ((temp = (var_t *) realloc(vars, sizeof(var_t) * (nvars + 1)))
523 	    == NULL) {
524 		free(name);
525 		err(1, "Realloc of vars array failed");
526 	}
527 
528 	strcpy(name, varname);
529 	vars = temp;
530 	vars[nvars].name = name;
531 	vars[nvars].len = 0;
532 	vars[nvars].value = NULL;
533 	nvars++;
534 
535 	return (nvars - 1);
536 }
537 
538 /*
539  * Allocate and assign a new argument of the given type.
540  */
541 static void
542 assign_arg(args_state_t arg_type, void *arg)
543 {
544 	args_t *temp, cur;
545 	char *str = arg;
546 	returns_t *ret;
547 
548 	if (verbose)
549 		printf("function is >%s<, adding arg >%s< type %s\n",
550 		       command.function, str, args_enum_names[arg_type]);
551 
552 	cur.arg_type = arg_type;
553 	switch (arg_type) {
554 	case arg_var:
555 		cur.var_index = find_var_index(arg);
556 		if (cur.var_index < 0)
557 			err(1, "Invalid variable %s at line %zu of file %s",
558 			    str, line, cur_file);
559 		cur.arg_type = ret_string;
560 		break;
561 
562 	case arg_byte:
563 		ret = arg;
564 		cur.arg_len = ret->return_len;
565 		cur.arg_string = malloc(cur.arg_len);
566 		if (cur.arg_string == NULL)
567 			err(1, "Could not malloc memory for arg bytes");
568 		memcpy(cur.arg_string, ret->return_value, cur.arg_len);
569 		break;
570 
571 	case arg_null:
572 		cur.arg_len = 0;
573 		cur.arg_string = NULL;
574 		break;
575 
576 	default:
577 		cur.arg_len = strlen(str);
578 		cur.arg_string = malloc(cur.arg_len + 1);
579 		if (cur.arg_string == NULL)
580 			err(1, "Could not malloc memory for arg string");
581 		strcpy(cur.arg_string, arg);
582 	}
583 
584 	temp = realloc(command.args, sizeof(args_t) * (command.nargs + 1));
585 	if (temp == NULL)
586 		err(1, "Failed to reallocate args");
587 	command.args = temp;
588 	memcpy(&command.args[command.nargs], &cur, sizeof(args_t));
589 	command.nargs++;
590 }
591 
592 /*
593  * Allocate and assign a new return.
594  */
595 static void
596 assign_rets(returns_enum_t ret_type, void *ret)
597 {
598 	returns_t *temp, cur;
599 	char *ret_str;
600 	returns_t *ret_ret;
601 
602 	cur.return_type = ret_type;
603 	if (ret_type != ret_var) {
604 		if ((ret_type == ret_number) || (ret_type == ret_string)) {
605 			ret_str = ret;
606 			cur.return_len = strlen(ret_str) + 1;
607 			cur.return_value = malloc(cur.return_len + 1);
608 			if (cur.return_value == NULL)
609 				err(1,
610 				    "Could not malloc memory for arg string");
611 			strcpy(cur.return_value, ret_str);
612 		} else if (ret_type == ret_byte) {
613 			ret_ret = ret;
614 			cur.return_len = ret_ret->return_len;
615 			cur.return_value = malloc(cur.return_len);
616 			if (cur.return_value == NULL)
617 				err(1,
618 				    "Could not malloc memory for byte string");
619 			memcpy(cur.return_value, ret_ret->return_value,
620 			       cur.return_len);
621 		} else if (ret_type == ret_ref) {
622 			if ((cur.return_index = find_var_index(ret)) < 0)
623 				err(1, "Undefined variable reference");
624 		}
625 	} else {
626 		cur.return_index = find_var_index(ret);
627 		if (cur.return_index < 0)
628 			cur.return_index = assign_var(ret);
629 	}
630 
631 	temp = realloc(command.returns,
632 		       sizeof(returns_t) * (command.nrets + 1));
633 	if (temp == NULL)
634 		err(1, "Failed to reallocate returns");
635 	command.returns = temp;
636 	memcpy(&command.returns[command.nrets], &cur, sizeof(returns_t));
637 	command.nrets++;
638 }
639 
640 /*
641  * Find the given variable name in the var array and return the i
642  * return -1 if var is not found.
643  */
644 static int
645 find_var_index(const char *var_name)
646 {
647 	int result;
648 	size_t i;
649 
650 	result = -1;
651 
652 	for (i = 0; i < nvars; i++) {
653 		if (strcmp(var_name, vars[i].name) == 0) {
654 			result = i;
655 			break;
656 		}
657 	}
658 
659 	return result;
660 }
661 
662 /*
663  * Check the given function name in the given table of names, return 1 if
664  * there is a match.
665  */
666 static int check_function_table(char *function, const char *table[],
667 				int nfunctions)
668 {
669 	int i;
670 
671 	for (i = 0; i < nfunctions; i++) {
672 		if ((strlen(function) == strlen(table[i])) &&
673 		    (strcmp(function, table[i]) == 0))
674 			return 1;
675 	}
676 
677 	return 0;
678 }
679 
680 /*
681  * Compare the output from the slave against the given file and report
682  * any differences.
683  */
684 static void
685 compare_streams(char *filename, bool discard)
686 {
687 	char check_file[PATH_MAX], drain[100], ref, data;
688 	struct pollfd fds[2];
689 	int nfd, check_fd;
690 	ssize_t result;
691 
692 	/*
693 	 * Don't prepend check path iff check file has an absolute
694 	 * path.
695 	 */
696 	if (filename[0] != '/') {
697 		if (strlcpy(check_file, check_path, sizeof(check_file))
698 		    >= sizeof(check_file))
699 			err(2, "CHECK_PATH too long");
700 
701 		if (strlcat(check_file, "/", sizeof(check_file))
702 		    >= sizeof(check_file))
703 			err(2, "Could not append / to check file path");
704 	} else {
705 		check_file[0] = '\0';
706 	}
707 
708 	if (strlcat(check_file, filename, sizeof(check_file))
709 	    >= sizeof(check_file))
710 		err(2, "Path to check file path overflowed");
711 
712 	if ((check_fd = open(check_file, O_RDONLY, 0)) < 0)
713 		err(2, "failed to open file %s line %zu of file %s",
714 		    check_file, line, cur_file);
715 
716 	fds[0].fd = check_fd;
717 	fds[0].events = POLLIN;
718 	fds[0].revents = 0;
719 	fds[1].fd = master;
720 	fds[1].events = POLLIN;
721 	fds[1].revents = 0;
722 
723 	nfd = 2;
724 	/*
725 	 * if we have saved output then only check for data in the
726 	 * reference file since the slave data may already be drained.
727 	 */
728 	if (saved_output.count > 0)
729 		nfd = 1;
730 
731 	while (poll(&fds[0], nfd, 500) == nfd) {
732 		if ((result = read(check_fd, &ref, 1)) < 1) {
733 			if (result != 0) {
734 				err(2, "Bad read on file %s", check_file);
735 			} else {
736 				break;
737 			}
738 		}
739 
740 		if (saved_output.count > 0) {
741 			data = saved_output.data[saved_output.readp];
742 			saved_output.count--;
743 			saved_output.readp++;
744 			/* run out of saved data, switch to file */
745 			if (saved_output.count == 0)
746 				nfd = 2;
747 		} else {
748 			if (read(master, &data, 1) < 1)
749 				err(2, "Bad read on slave pty");
750 		}
751 
752 		if (verbose) {
753 			fprintf(stderr, "Comparing reference byte 0x%x (%c)"
754 				" against slave byte 0x%x (%c)\n", ref,
755 				(ref >= ' ')? ref : '-',
756 				data, (data >= ' ')? data : '-');
757 		}
758 
759 		if (ref != data) {
760 			warnx("%s, %zu: refresh data from slave does "
761 			    "not match expected from file %s",
762 			    cur_file, line, check_file);
763 
764 			if (!verbose)
765 				exit(2);
766 		}
767 
768 		fds[0].revents = 0;
769 		fds[1].revents = 0;
770 	}
771 
772 
773 	if (saved_output.count > 0)
774 		excess(cur_file, line, __func__, " from slave",
775 		    &saved_output.data[saved_output.readp], saved_output.count);
776 
777 	/* discard any excess saved output if required */
778 	if (discard) {
779 		saved_output.count = 0;
780 		saved_output.readp = 0;
781 	}
782 
783 	fds[0].revents = 0;
784 	fds[1].revents = 0;
785 	if ((result = poll(&fds[0], 2, 0)) != 0) {
786 		if (result == -1)
787 			err(2, "poll of file descriptors failed");
788 
789 		if ((fds[1].revents & POLLIN) == POLLIN) {
790 			save_slave_output(true);
791 		} else {
792 			/*
793 			 * handle excess in file if it exists.  Poll
794 			 * says there is data until EOF is read.
795 			 * Check next read is EOF, if it is not then
796 			 * the file really has more data than the
797 			 * slave produced so flag this as a warning.
798 			 */
799 			result = read(check_fd, drain, sizeof(drain));
800 			if (result == -1)
801 				err(1, "read of data file failed");
802 
803 			if (result > 0) {
804 				excess(check_file, 0, __func__, "", drain,
805 				    result);
806 				if (!verbose)
807 					exit(2);
808 			}
809 		}
810 	}
811 
812 	close(check_fd);
813 }
814 
815 /*
816  * Pass a function call and arguments to the slave and wait for the
817  * results.  The variable nresults determines how many returns we expect
818  * back from the slave.  These results will be validated against the
819  * expected returns or assigned to variables.
820  */
821 static void
822 do_function_call(size_t nresults)
823 {
824 #define MAX_RESULTS 4
825 	char *p;
826 	int do_input;
827 	size_t i;
828 	struct pollfd fds[3];
829 	returns_t response[MAX_RESULTS], returns_count;
830 
831 	assert(nresults <= MAX_RESULTS);
832 
833 	do_input = check_function_table(command.function, input_functions,
834 	    ninput_functions);
835 
836 	write_func_and_args();
837 
838 	/*
839 	 * We should get the number of returns back here, grab it before
840 	 * doing input otherwise it will confuse the input poll
841 	 */
842 	read_cmd_pipe(&returns_count);
843 	if (returns_count.return_type != ret_count)
844 		err(2, "expected return type of ret_count but received %s",
845 		    returns_enum_names[returns_count.return_type]);
846 
847 	if (verbose)
848 		fprintf(stderr, "Expect %zu results from slave, slave "
849 			"reported %zu\n", nresults, returns_count.return_len);
850 
851 	if ((no_input == false) && (do_input == 1)) {
852 		if (verbose)
853 			fprintf(stderr, "doing input with inputstr >%s<\n",
854 				input_str);
855 
856 		if (input_str == NULL)
857 			errx(2, "%s, %zu: Call to input function "
858 			    "but no input defined", cur_file, line);
859 
860 		fds[0].fd = slvpipe[READ_PIPE];
861 		fds[0].events = POLLIN;
862  		p = input_str;
863 		save_slave_output(false);
864 		while(*p != '\0') {
865 			if (verbose) {
866 				fprintf(stderr, "Writing char >%c< to slave\n",
867 					*p);
868 				fflush(stderr);
869 			}
870 
871 			nanosleep(&delay_spec, NULL);
872 
873 			write(master, p, 1);
874 			save_slave_output(false);
875 
876 			p++;
877 			fds[0].revents = 0;
878 
879 			/* check for slave function returning unexpectedly */
880 			if ((poll(&fds[0], 1, 10) > 0) && (*p != '\0')) {
881 				warnx("%s, %zu: Slave function "
882 				    "returned before end of input string",
883 				    cur_file, line);
884 				break;
885 			}
886 		}
887 
888 		if (verbose) {
889 			fprintf(stderr, "Input done.\n");
890 		}
891 
892 		/* done with the input string, free the resources */
893 		free(input_str);
894 		input_str = NULL;
895 	}
896 
897 	if (verbose) {
898 		fds[0].fd = slvpipe[READ_PIPE];
899 		fds[0].events = POLLIN;
900 		fds[0].revents = 0;
901 
902 		fds[1].fd = slvpipe[WRITE_PIPE];
903 		fds[1].events = POLLOUT;
904 		fds[1].revents = 0;
905 
906 		fds[2].fd = master;
907 		fds[2].events = POLLIN | POLLOUT;
908 		fds[2].revents = 0;
909 
910 		i = poll(&fds[0], 3, 1000);
911 		fprintf(stderr, "Poll returned %zu\n", i);
912 		for (i = 0; i < 3; i++) {
913 			fprintf(stderr, "revents for fd[%zu] = 0x%x\n",
914 				i, fds[i].revents);
915 		}
916 	}
917 
918 	/* drain any trailing output */
919 	save_slave_output(false);
920 
921 	for (i = 0; i < returns_count.return_len; i++) {
922 		read_cmd_pipe(&response[i]);
923 	}
924 
925 	/*
926 	 * Check for a slave error in the first return slot, if the
927 	 * slave errored then we may not have the number of returns we
928 	 * expect but in this case we should report the slave error
929 	 * instead of a return count mismatch.
930 	 */
931 	if ((returns_count.return_len > 0) &&
932 	    (response[0].return_type == ret_slave_error))
933 		err(2, "Slave returned error: %s",
934 		    (const char *)response[0].return_value);
935 
936 	if (returns_count.return_len != nresults)
937 		err(2, "Incorrect number of returns from slave, expected %zu "
938 		    "but received %zu", nresults, returns_count.return_len);
939 
940 	if (verbose) {
941 		for (i = 0; i < nresults; i++) {
942 			if ((response[i].return_type != ret_byte) &&
943 			    (response[i].return_type != ret_err) &&
944 			    (response[i].return_type != ret_ok))
945 				fprintf(stderr,
946 					"received response >%s< "
947 					"expected",
948 					(const char *)response[i].return_value);
949 			else
950 				fprintf(stderr, "received");
951 
952 			fprintf(stderr, " return_type %s\n",
953 			    returns_enum_names[command.returns[i].return_type]);
954 		}
955 	}
956 
957 	for (i = 0; i < nresults; i++) {
958 		if (command.returns[i].return_type != ret_var) {
959 			validate(i, &response[i]);
960 		} else {
961 			vars[command.returns[i].return_index].len =
962 				response[i].return_len;
963 			vars[command.returns[i].return_index].value =
964 				response[i].return_value;
965 			vars[command.returns[i].return_index].type =
966 				response[i].return_type;
967 		}
968 	}
969 #if 0
970 	if (saved_output.count > 0)
971 		excess(cur_file, line, __func__, " from slave",
972 		    &saved_output.data[saved_output.readp], saved_output.count);
973 #endif
974 
975 	init_parse_variables(0);
976 }
977 
978 /*
979  * Write the function and command arguments to the command pipe.
980  */
981 static void
982 write_func_and_args(void)
983 {
984 	int i;
985 
986 	if (verbose)
987 		fprintf(stderr, "calling function >%s<\n", command.function);
988 
989 	write_cmd_pipe(command.function);
990 	for (i = 0; i < command.nargs; i++) {
991 		if (command.args[i].arg_type == arg_var)
992 			write_cmd_pipe_args(command.args[i].arg_type,
993 					    &vars[command.args[i].var_index]);
994 		else
995 			write_cmd_pipe_args(command.args[i].arg_type,
996 					    &command.args[i]);
997 	}
998 
999 	write_cmd_pipe(NULL); /* signal end of arguments */
1000 }
1001 
1002 /*
1003  * Initialise the command structure - if initial is non-zero then just set
1004  * everything to sane values otherwise free any memory that was allocated
1005  * when building the structure.
1006  */
1007 void
1008 init_parse_variables(int initial)
1009 {
1010 	int i, result;
1011 	struct pollfd slave_pty;
1012 
1013 	if (initial == 0) {
1014 		free(command.function);
1015 		for (i = 0; i < command.nrets; i++) {
1016 			if (command.returns[i].return_type == ret_number)
1017 				free(command.returns[i].return_value);
1018 		}
1019 		free(command.returns);
1020 
1021 		for (i = 0; i < command.nargs; i++) {
1022 			if (command.args[i].arg_type != arg_var)
1023 				free(command.args[i].arg_string);
1024 		}
1025 		free(command.args);
1026 	} else {
1027 		line = 0;
1028 		input_delay = 0;
1029 		vars = NULL;
1030 		nvars = 0;
1031 		input_str = NULL;
1032 		saved_output.allocated = 0;
1033 		saved_output.count = 0;
1034 		saved_output.readp = 0;
1035 		saved_output.data = NULL;
1036 	}
1037 
1038 	no_input = false;
1039 	command.function = NULL;
1040 	command.nargs = 0;
1041 	command.args = NULL;
1042 	command.nrets = 0;
1043 	command.returns = NULL;
1044 
1045 	/*
1046 	 * Check the slave pty for stray output from the slave, at this
1047 	 * point we should not see any data as it should have been
1048 	 * consumed by the test functions.  If we see data then we have
1049 	 * either a bug or are not handling an output generating function
1050 	 * correctly.
1051 	 */
1052 	slave_pty.fd = master;
1053 	slave_pty.events = POLLIN;
1054 	slave_pty.revents = 0;
1055 	result = poll(&slave_pty, 1, 0);
1056 
1057 	if (result < 0)
1058 		err(2, "Poll of slave pty failed");
1059 	else if (result > 0)
1060 		warnx("%s, %zu: Unexpected data from slave", cur_file, line);
1061 }
1062 
1063 /*
1064  * Validate the response against the expected return.  The variable
1065  * i is the i into the rets array in command.
1066  */
1067 static void
1068 validate(int i, void *data)
1069 {
1070 	char *response;
1071 	returns_t *byte_response;
1072 
1073 	byte_response = data;
1074 	if ((command.returns[i].return_type != ret_byte) &&
1075 	    (command.returns[i].return_type != ret_err) &&
1076 	    (command.returns[i].return_type != ret_ok))
1077 		response = byte_response->return_value;
1078 
1079 	switch (command.returns[i].return_type) {
1080 	case ret_err:
1081 		validate_type(ret_err, byte_response, 0);
1082 		break;
1083 
1084 	case ret_ok:
1085 		validate_type(ret_ok, byte_response, 0);
1086 		break;
1087 
1088 	case ret_null:
1089 		validate_return("NULL", response, 0);
1090 		break;
1091 
1092 	case ret_nonnull:
1093 		validate_return("NULL", response, 1);
1094 		break;
1095 
1096 	case ret_string:
1097 	case ret_number:
1098 		validate_return(command.returns[i].return_value,
1099 				response, 0);
1100 		break;
1101 
1102 	case ret_ref:
1103 		validate_reference(i, response);
1104 		break;
1105 
1106 	case ret_byte:
1107 		validate_byte(&command.returns[i], byte_response, 0);
1108 		break;
1109 
1110 	default:
1111 		err(1, "Malformed statement at line %zu of file %s",
1112 		    line, cur_file);
1113 		break;
1114 	}
1115 }
1116 
1117 /*
1118  * Validate the return against the contents of a variable.
1119  */
1120 static void
1121 validate_reference(int i, void *data)
1122 {
1123 	char *response;
1124 	returns_t *byte_response;
1125 	var_t *varp;
1126 
1127 	varp = &vars[command.returns[i].return_index];
1128 
1129 	byte_response = data;
1130 	if (command.returns[i].return_type != ret_byte)
1131 		response = data;
1132 
1133 	if (verbose)
1134 		fprintf(stderr,
1135 			"validate_reference: return type of %s, value %s \n",
1136 			returns_enum_names[varp->type],
1137 			(const char *)varp->value);
1138 
1139 	switch (varp->type) {
1140 	case ret_string:
1141 	case ret_number:
1142 		validate_return(varp->value, response, 0);
1143 		break;
1144 
1145 	case ret_byte:
1146 		validate_byte(varp->value, byte_response, 0);
1147 		break;
1148 
1149 	default:
1150 		err(1,
1151 		    "Invalid return type for reference at line %zu of file %s",
1152 		    line, cur_file);
1153 		break;
1154 	}
1155 }
1156 
1157 /*
1158  * Validate the return type against the expected type, throw an error
1159  * if they don't match.
1160  */
1161 static void
1162 validate_type(returns_enum_t expected, returns_t *value, int check)
1163 {
1164 	if (((check == 0) && (expected != value->return_type)) ||
1165 	    ((check == 1) && (expected == value->return_type)))
1166 		err(1, "Validate expected type %s %s %s line %zu of file %s",
1167 		    returns_enum_names[expected],
1168 		    (check == 0)? "matching" : "not matching",
1169 		    returns_enum_names[value->return_type], line, cur_file);
1170 
1171 	if (verbose)
1172 		fprintf(stderr, "Validate expected type %s %s %s line %zu"
1173 			" of file %s\n",
1174 			returns_enum_names[expected],
1175 			(check == 0)? "matching" : "not matching",
1176 			returns_enum_names[value->return_type], line, cur_file);
1177 }
1178 
1179 /*
1180  * Validate the return value against the expected value, throw an error
1181  * if they don't match.
1182  */
1183 static void
1184 validate_return(const char *expected, const char *value, int check)
1185 {
1186 	if (((check == 0) && strcmp(expected, value) != 0) ||
1187 	    ((check == 1) && strcmp(expected, value) == 0))
1188 		err(1, "Validate expected %s %s %s line %zu of file %s",
1189 		    expected,
1190 		    (check == 0)? "matching" : "not matching", value,
1191 		    line, cur_file);
1192 	if (verbose)
1193 		fprintf(stderr, "Validated expected value %s %s %s "
1194 			"at line %zu of file %s\n", expected,
1195 			(check == 0)? "matches" : "does not match",
1196 			value, line, cur_file);
1197 }
1198 
1199 /*
1200  * Validate the return value against the expected value, throw an error
1201  * if they don't match expectations.
1202  */
1203 static void
1204 validate_byte(returns_t *expected, returns_t *value, int check)
1205 {
1206 	/*
1207 	 * No chance of a match if lengths differ...
1208 	 */
1209 	if ((check == 0) && (expected->return_len != value->return_len))
1210 	    err(1, "Byte validation failed, length mismatch");
1211 
1212 	/*
1213 	 * If check is 0 then we want to throw an error IFF the byte streams
1214 	 * do not match, if check is 1 then throw an error if the byte
1215 	 * streams match.
1216 	 */
1217 	if (((check == 0) && memcmp(expected->return_value, value->return_value,
1218 				    value->return_len) != 0) ||
1219 	    ((check == 1) && (expected->return_len == value->return_len) &&
1220 	     memcmp(expected->return_value, value->return_value,
1221 		    value->return_len) == 0))
1222 		err(1, "Validate expected %s byte stream at line %zu"
1223 		    "of file %s",
1224 		    (check == 0)? "matching" : "not matching", line, cur_file);
1225 	if (verbose)
1226 		fprintf(stderr, "Validated expected %s byte stream "
1227 			"at line %zu of file %s\n",
1228 			(check == 0)? "matching" : "not matching",
1229 			line, cur_file);
1230 }
1231 
1232 /*
1233  * Validate the variable at i against the expected value, throw an
1234  * error if they don't match, if check is non-zero then the match is
1235  * negated.
1236  */
1237 static void
1238 validate_variable(int ret, returns_enum_t type, const void *value, int i,
1239     int check)
1240 {
1241 	returns_t *retval;
1242 	var_t *varptr;
1243 
1244 	retval = &command.returns[ret];
1245 	varptr = &vars[command.returns[ret].return_index];
1246 
1247 	if (varptr->value == NULL)
1248 		err(1, "Variable %s has no value assigned to it", varptr->name);
1249 
1250 
1251 	if (varptr->type != type)
1252 		err(1, "Variable %s is not the expected type", varptr->name);
1253 
1254 	if (type != ret_byte) {
1255 		if ((((check == 0) && strcmp(value, varptr->value) != 0))
1256 		    || ((check == 1) && strcmp(value, varptr->value) == 0))
1257 			err(1, "Variable %s contains %s instead of %s"
1258 			    " value %s at line %zu of file %s",
1259 			    varptr->name, (const char *)varptr->value,
1260 			    (check == 0)? "expected" : "not matching",
1261 			    (const char *)value,
1262 			    line, cur_file);
1263 		if (verbose)
1264 			fprintf(stderr, "Variable %s contains %s value "
1265 				"%s at line %zu of file %s\n",
1266 				varptr->name,
1267 				(check == 0)? "expected" : "not matching",
1268 				(const char *)varptr->value, line, cur_file);
1269 	} else {
1270 		if ((check == 0) && (retval->return_len != varptr->len))
1271 			err(1, "Byte validation failed, length mismatch");
1272 
1273 		/*
1274 		 * If check is 0 then we want to throw an error IFF
1275 		 * the byte streams do not match, if check is 1 then
1276 		 * throw an error if the byte streams match.
1277 		 */
1278 		if (((check == 0) && memcmp(retval->return_value, varptr->value,
1279 					    varptr->len) != 0) ||
1280 		    ((check == 1) && (retval->return_len == varptr->len) &&
1281 		     memcmp(retval->return_value, varptr->value,
1282 			    varptr->len) == 0))
1283 			err(1, "Validate expected %s byte stream at line %zu"
1284 			    " of file %s",
1285 			    (check == 0)? "matching" : "not matching",
1286 			    line, cur_file);
1287 		if (verbose)
1288 			fprintf(stderr, "Validated expected %s byte stream "
1289 				"at line %zu of file %s\n",
1290 				(check == 0)? "matching" : "not matching",
1291 				line, cur_file);
1292 	}
1293 }
1294 
1295 /*
1296  * Write a string to the command pipe - we feed the number of bytes coming
1297  * down first to allow storage allocation and then follow up with the data.
1298  * If cmd is NULL then feed a -1 down the pipe to say the end of the args.
1299  */
1300 static void
1301 write_cmd_pipe(char *cmd)
1302 {
1303 	args_t arg;
1304 	size_t len;
1305 
1306 	if (cmd == NULL)
1307 		len = 0;
1308 	else
1309 		len = strlen(cmd);
1310 
1311 	arg.arg_type = arg_static;
1312 	arg.arg_len = len;
1313 	arg.arg_string = cmd;
1314 	write_cmd_pipe_args(arg.arg_type, &arg);
1315 
1316 }
1317 
1318 static void
1319 write_cmd_pipe_args(args_state_t type, void *data)
1320 {
1321 	var_t *var_data;
1322 	args_t *arg_data;
1323 	int len, send_type;
1324 	void *cmd;
1325 
1326 	arg_data = data;
1327 	switch (type) {
1328 	case arg_var:
1329 		var_data = data;
1330 		len = var_data->len;
1331 		cmd = var_data->value;
1332 		if (var_data->type == arg_byte)
1333 			send_type = ret_byte;
1334 		else
1335 			send_type = ret_string;
1336 		break;
1337 
1338 	case arg_null:
1339 		send_type = ret_null;
1340 		len = 0;
1341 		break;
1342 
1343 	default:
1344 		if ((arg_data->arg_len == 0) && (arg_data->arg_string == NULL))
1345 			len = -1;
1346 		else
1347 			len = arg_data->arg_len;
1348 		cmd = arg_data->arg_string;
1349 		if (type == arg_byte)
1350 			send_type = ret_byte;
1351 		else
1352 			send_type = ret_string;
1353 	}
1354 
1355 	if (verbose)
1356 		fprintf(stderr, "Writing type %s to command pipe\n",
1357 			returns_enum_names[send_type]);
1358 
1359 	if (write(cmdpipe[WRITE_PIPE], &send_type, sizeof(int)) < 0)
1360 		err(1, "command pipe write for type failed");
1361 
1362 	if (verbose)
1363 		fprintf(stderr, "Writing length %d to command pipe\n", len);
1364 
1365 	if (write(cmdpipe[WRITE_PIPE], &len, sizeof(int)) < 0)
1366 		err(1, "command pipe write for length failed");
1367 
1368 	if (len > 0) {
1369 		if (verbose)
1370 			fprintf(stderr, "Writing data >%s< to command pipe\n",
1371 				(const char *)cmd);
1372 		if (write(cmdpipe[WRITE_PIPE], cmd, len) < 0)
1373 			err(1, "command pipe write of data failed");
1374 	}
1375 }
1376 
1377 /*
1378  * Read a response from the command pipe, first we will receive the
1379  * length of the response then the actual data.
1380  */
1381 static void
1382 read_cmd_pipe(returns_t *response)
1383 {
1384 	int len, type;
1385 	struct pollfd rfd[2];
1386 	char *str;
1387 
1388 	/*
1389 	 * Check if there is data to read - just in case slave has died, we
1390 	 * don't want to block on the read and just hang.  We also check
1391 	 * output from the slave because the slave may be blocked waiting
1392 	 * for a flush on its stdout.
1393 	 */
1394 	rfd[0].fd = slvpipe[READ_PIPE];
1395 	rfd[0].events = POLLIN;
1396 	rfd[1].fd = master;
1397 	rfd[1].events = POLLIN;
1398 
1399 	do {
1400 		rfd[0].revents = 0;
1401 		rfd[1].revents = 0;
1402 
1403 		if (poll(rfd, 2, 4000) == 0)
1404 			errx(2, "%s, %zu: Command pipe read timeout",
1405 			    cur_file, line);
1406 
1407 		if ((rfd[1].revents & POLLIN) == POLLIN) {
1408 			if (verbose)
1409 				fprintf(stderr,
1410 					"draining output from slave\n");
1411 			save_slave_output(false);
1412 		}
1413 	}
1414 	while((rfd[1].revents & POLLIN) == POLLIN);
1415 
1416 	if (read(slvpipe[READ_PIPE], &type, sizeof(int)) < 0)
1417 		err(1, "command pipe read for type failed");
1418 	response->return_type = type;
1419 
1420 	if ((type != ret_ok) && (type != ret_err) && (type != ret_count)) {
1421 		if (read(slvpipe[READ_PIPE], &len, sizeof(int)) < 0)
1422 			err(1, "command pipe read for length failed");
1423 		response->return_len = len;
1424 
1425 		if (verbose)
1426 			fprintf(stderr,
1427 				"Reading %d bytes from command pipe\n", len);
1428 
1429 		if ((response->return_value = malloc(len + 1)) == NULL)
1430 			err(1, "Failed to alloc memory for cmd pipe read");
1431 
1432 		if (read(slvpipe[READ_PIPE], response->return_value, len) < 0)
1433 			err(1, "command pipe read of data failed");
1434 
1435 		if (response->return_type != ret_byte) {
1436 			str = response->return_value;
1437 			str[len] = '\0';
1438 
1439 			if (verbose)
1440 				fprintf(stderr, "Read data >%s< from pipe\n",
1441 					(const char *)response->return_value);
1442 		}
1443 	} else {
1444 		response->return_value = NULL;
1445 		if (type == ret_count) {
1446 			if (read(slvpipe[READ_PIPE], &len, sizeof(int)) < 0)
1447 				err(1, "command pipe read for number of "
1448 				       "returns failed");
1449 			response->return_len = len;
1450 		}
1451 
1452 		if (verbose)
1453 			fprintf(stderr, "Read type %s from pipe\n",
1454 				returns_enum_names[type]);
1455 	}
1456 }
1457 
1458 /*
1459  * Check for writes from the slave on the pty, save the output into a
1460  * buffer for later checking if discard is false.
1461  */
1462 #define MAX_DRAIN 256
1463 
1464 static void
1465 save_slave_output(bool discard)
1466 {
1467 	struct pollfd fd;
1468 	char *new_data, drain[MAX_DRAIN];
1469 	size_t to_allocate;
1470 	ssize_t result;
1471 	size_t i;
1472 
1473 	fd.fd = master;
1474 	fd.events = POLLIN;
1475 	fd.revents = 0;
1476 
1477 	result = 0;
1478 	while (1) {
1479 		if (result == -1)
1480 			err(2, "poll of slave pty failed");
1481 		result = MAX_DRAIN;
1482 		if ((result = read(master, &drain, result)) < 0) {
1483 			if (errno == EAGAIN)
1484 				break;
1485 			else
1486 				err(2, "draining slave pty failed");
1487 		}
1488 
1489 		fd.revents = 0;
1490 		if (!discard) {
1491 			if ((size_t)result >
1492 			    (saved_output.allocated - saved_output.count)) {
1493 				to_allocate = 1024 * ((result / 1024) + 1);
1494 
1495 				if ((new_data = realloc(saved_output.data,
1496 					saved_output.allocated + to_allocate))
1497 				    == NULL)
1498 					err(2, "Realloc of saved_output failed");
1499 				saved_output.data = new_data;
1500 				saved_output.allocated += to_allocate;
1501 			}
1502 
1503 			if (verbose) {
1504 				fprintf(stderr, "count = %zu, "
1505 				    "allocated = %zu\n", saved_output.count,
1506 				    saved_output.allocated);
1507 				for (i = 0; i < (size_t)result; i++) {
1508 					fprintf(stderr, "Saving slave output "
1509 					    "0x%x (%c)\n", drain[i],
1510 					    (drain[i] >= ' ')? drain[i] : '-');
1511 				}
1512 			}
1513 
1514 			memcpy(&saved_output.data[saved_output.count], drain,
1515 			       result);
1516 			saved_output.count += result;
1517 
1518 			if (verbose) {
1519 				fprintf(stderr, "count = %zu, "
1520 				    "allocated = %zu\n", saved_output.count,
1521 				    saved_output.allocated);
1522 			}
1523 		} else {
1524 			if (verbose) {
1525 				for (i=0; i < (size_t)result; i++) {
1526 					fprintf(stderr, "Discarding slave "
1527 					    "output 0x%x (%c)\n",
1528 					    drain[i],
1529 					    (drain[i] >= ' ')? drain[i] : '-');
1530 				}
1531 			}
1532 		}
1533 	}
1534 }
1535 
1536 static void
1537 yyerror(const char *msg)
1538 {
1539 	warnx("%s in line %zu of file %s", msg, line, cur_file);
1540 }
1541