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