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