1/* 2 * eval.c - gawk parse tree interpreter 3 */ 4 5/* 6 * Copyright (C) 1986, 1988, 1989, 1991-2003 the Free Software Foundation, Inc. 7 * 8 * This file is part of GAWK, the GNU implementation of the 9 * AWK Programming Language. 10 * 11 * GAWK is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * GAWK is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 24 */ 25 26#include "awk.h" 27 28extern double pow P((double x, double y)); 29extern double modf P((double x, double *yp)); 30extern double fmod P((double x, double y)); 31 32static int eval_condition P((NODE *tree)); 33static NODE *op_assign P((NODE *tree)); 34static NODE *func_call P((NODE *tree)); 35static NODE *match_op P((NODE *tree)); 36static void pop_forloop P((void)); 37static inline void pop_all_forloops P((void)); 38static void push_forloop P((const char *varname, NODE **elems, size_t nelems)); 39static void push_args P((int count, NODE *arglist, NODE **oldstack, 40 const char *func_name, char **varnames)); 41static inline void pop_fcall_stack P((void)); 42static void pop_fcall P((void)); 43static int comp_func P((const void *p1, const void *p2)); 44 45#if __GNUC__ < 2 46NODE *_t; /* used as a temporary in macros */ 47#endif 48#ifdef MSDOS 49double _msc51bug; /* to get around a bug in MSC 5.1 */ 50#endif 51NODE *ret_node; 52int OFSlen; 53int ORSlen; 54int OFMTidx; 55int CONVFMTidx; 56 57/* Profiling stuff */ 58#ifdef PROFILING 59#define INCREMENT(n) n++ 60#else 61#define INCREMENT(n) /* nothing */ 62#endif 63 64/* Macros and variables to save and restore function and loop bindings */ 65/* 66 * the val variable allows return/continue/break-out-of-context to be 67 * caught and diagnosed 68 */ 69#define PUSH_BINDING(stack, x, val) (memcpy((char *)(stack), (const char *)(x), sizeof(jmp_buf)), val++) 70#define RESTORE_BINDING(stack, x, val) (memcpy((char *)(x), (const char *)(stack), sizeof(jmp_buf)), val--) 71 72static jmp_buf loop_tag; /* always the current binding */ 73static int loop_tag_valid = FALSE; /* nonzero when loop_tag valid */ 74static int func_tag_valid = FALSE; 75static jmp_buf func_tag; 76extern int exiting, exit_val; 77 78/* This rather ugly macro is for VMS C */ 79#ifdef C 80#undef C 81#endif 82#define C(c) ((char)c) 83/* 84 * This table is used by the regexp routines to do case independant 85 * matching. Basically, every ascii character maps to itself, except 86 * uppercase letters map to lower case ones. This table has 256 87 * entries, for ISO 8859-1. Note also that if the system this 88 * is compiled on doesn't use 7-bit ascii, casetable[] should not be 89 * defined to the linker, so gawk should not load. 90 * 91 * Do NOT make this array static, it is used in several spots, not 92 * just in this file. 93 */ 94#if 'a' == 97 /* it's ascii */ 95const char casetable[] = { 96 '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', 97 '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', 98 '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', 99 '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', 100 /* ' ' '!' '"' '#' '$' '%' '&' ''' */ 101 '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', 102 /* '(' ')' '*' '+' ',' '-' '.' '/' */ 103 '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', 104 /* '0' '1' '2' '3' '4' '5' '6' '7' */ 105 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', 106 /* '8' '9' ':' ';' '<' '=' '>' '?' */ 107 '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', 108 /* '@' 'A' 'B' 'C' 'D' 'E' 'F' 'G' */ 109 '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 110 /* 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' */ 111 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 112 /* 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' */ 113 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 114 /* 'X' 'Y' 'Z' '[' '\' ']' '^' '_' */ 115 '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', 116 /* '`' 'a' 'b' 'c' 'd' 'e' 'f' 'g' */ 117 '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 118 /* 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' */ 119 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 120 /* 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' */ 121 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 122 /* 'x' 'y' 'z' '{' '|' '}' '~' */ 123 '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', 124 125 /* Latin 1: */ 126 C('\200'), C('\201'), C('\202'), C('\203'), C('\204'), C('\205'), C('\206'), C('\207'), 127 C('\210'), C('\211'), C('\212'), C('\213'), C('\214'), C('\215'), C('\216'), C('\217'), 128 C('\220'), C('\221'), C('\222'), C('\223'), C('\224'), C('\225'), C('\226'), C('\227'), 129 C('\230'), C('\231'), C('\232'), C('\233'), C('\234'), C('\235'), C('\236'), C('\237'), 130 C('\240'), C('\241'), C('\242'), C('\243'), C('\244'), C('\245'), C('\246'), C('\247'), 131 C('\250'), C('\251'), C('\252'), C('\253'), C('\254'), C('\255'), C('\256'), C('\257'), 132 C('\260'), C('\261'), C('\262'), C('\263'), C('\264'), C('\265'), C('\266'), C('\267'), 133 C('\270'), C('\271'), C('\272'), C('\273'), C('\274'), C('\275'), C('\276'), C('\277'), 134 C('\340'), C('\341'), C('\342'), C('\343'), C('\344'), C('\345'), C('\346'), C('\347'), 135 C('\350'), C('\351'), C('\352'), C('\353'), C('\354'), C('\355'), C('\356'), C('\357'), 136 C('\360'), C('\361'), C('\362'), C('\363'), C('\364'), C('\365'), C('\366'), C('\327'), 137 C('\370'), C('\371'), C('\372'), C('\373'), C('\374'), C('\375'), C('\376'), C('\337'), 138 C('\340'), C('\341'), C('\342'), C('\343'), C('\344'), C('\345'), C('\346'), C('\347'), 139 C('\350'), C('\351'), C('\352'), C('\353'), C('\354'), C('\355'), C('\356'), C('\357'), 140 C('\360'), C('\361'), C('\362'), C('\363'), C('\364'), C('\365'), C('\366'), C('\367'), 141 C('\370'), C('\371'), C('\372'), C('\373'), C('\374'), C('\375'), C('\376'), C('\377'), 142}; 143#else 144#include "You lose. You will need a translation table for your character set." 145#endif 146 147#undef C 148 149/* 150 * This table maps node types to strings for debugging. 151 * KEEP IN SYNC WITH awk.h!!!! 152 */ 153static const char *const nodetypes[] = { 154 "Node_illegal", 155 "Node_times", 156 "Node_quotient", 157 "Node_mod", 158 "Node_plus", 159 "Node_minus", 160 "Node_cond_pair", 161 "Node_subscript", 162 "Node_concat", 163 "Node_exp", 164 "Node_preincrement", 165 "Node_predecrement", 166 "Node_postincrement", 167 "Node_postdecrement", 168 "Node_unary_minus", 169 "Node_field_spec", 170 "Node_assign", 171 "Node_assign_times", 172 "Node_assign_quotient", 173 "Node_assign_mod", 174 "Node_assign_plus", 175 "Node_assign_minus", 176 "Node_assign_exp", 177 "Node_and", 178 "Node_or", 179 "Node_equal", 180 "Node_notequal", 181 "Node_less", 182 "Node_greater", 183 "Node_leq", 184 "Node_geq", 185 "Node_match", 186 "Node_nomatch", 187 "Node_not", 188 "Node_rule_list", 189 "Node_rule_node", 190 "Node_statement_list", 191 "Node_switch_body", 192 "Node_case_list", 193 "Node_if_branches", 194 "Node_expression_list", 195 "Node_param_list", 196 "Node_K_if", 197 "Node_K_switch", 198 "Node_K_case", 199 "Node_K_default", 200 "Node_K_while", 201 "Node_K_for", 202 "Node_K_arrayfor", 203 "Node_K_break", 204 "Node_K_continue", 205 "Node_K_print", 206 "Node_K_print_rec", 207 "Node_K_printf", 208 "Node_K_next", 209 "Node_K_exit", 210 "Node_K_do", 211 "Node_K_return", 212 "Node_K_delete", 213 "Node_K_delete_loop", 214 "Node_K_getline", 215 "Node_K_function", 216 "Node_K_nextfile", 217 "Node_redirect_output", 218 "Node_redirect_append", 219 "Node_redirect_pipe", 220 "Node_redirect_pipein", 221 "Node_redirect_input", 222 "Node_redirect_twoway", 223 "Node_var_new", 224 "Node_var", 225 "Node_var_array", 226 "Node_val", 227 "Node_builtin", 228 "Node_line_range", 229 "Node_in_array", 230 "Node_func", 231 "Node_func_call", 232 "Node_cond_exp", 233 "Node_regex", 234 "Node_dynregex", 235 "Node_hashnode", 236 "Node_ahash", 237 "Node_array_ref", 238 "Node_BINMODE", 239 "Node_CONVFMT", 240 "Node_FIELDWIDTHS", 241 "Node_FNR", 242 "Node_FS", 243 "Node_IGNORECASE", 244 "Node_LINT", 245 "Node_NF", 246 "Node_NR", 247 "Node_OFMT", 248 "Node_OFS", 249 "Node_ORS", 250 "Node_RS", 251 "Node_TEXTDOMAIN", 252 "Node_final --- this should never appear", 253 NULL 254}; 255 256/* nodetype2str --- convert a node type into a printable value */ 257 258const char * 259nodetype2str(NODETYPE type) 260{ 261 static char buf[40]; 262 263 if (type >= Node_illegal && type <= Node_final) 264 return nodetypes[(int) type]; 265 266 sprintf(buf, _("unknown nodetype %d"), (int) type); 267 return buf; 268} 269 270/* flags2str --- make a flags value readable */ 271 272const char * 273flags2str(int flagval) 274{ 275 static const struct flagtab values[] = { 276 { MALLOC, "MALLOC" }, 277 { TEMP, "TEMP" }, 278 { PERM, "PERM" }, 279 { STRING, "STRING" }, 280 { STRCUR, "STRCUR" }, 281 { NUMCUR, "NUMCUR" }, 282 { NUMBER, "NUMBER" }, 283 { MAYBE_NUM, "MAYBE_NUM" }, 284 { ARRAYMAXED, "ARRAYMAXED" }, 285 { FUNC, "FUNC" }, 286 { FIELD, "FIELD" }, 287 { INTLSTR, "INTLSTR" }, 288 { 0, NULL }, 289 }; 290 291 return genflags2str(flagval, values); 292} 293 294/* genflags2str --- general routine to convert a flag value to a string */ 295 296const char * 297genflags2str(int flagval, const struct flagtab *tab) 298{ 299 static char buffer[BUFSIZ]; 300 char *sp; 301 int i, space_left, space_needed; 302 303 sp = buffer; 304 space_left = BUFSIZ; 305 for (i = 0; tab[i].name != NULL; i++) { 306 /* 307 * note the trick, we want 1 or 0 for whether we need 308 * the '|' character. 309 */ 310 space_needed = (strlen(tab[i].name) + (sp != buffer)); 311 if (space_left < space_needed) 312 fatal(_("buffer overflow in genflags2str")); 313 314 if ((flagval & tab[i].val) != 0) { 315 if (sp != buffer) { 316 *sp++ = '|'; 317 space_left--; 318 } 319 strcpy(sp, tab[i].name); 320 /* note ordering! */ 321 space_left -= strlen(sp); 322 sp += strlen(sp); 323 } 324 } 325 326 return buffer; 327} 328 329/* 330 * interpret: 331 * Tree is a bunch of rules to run. Returns zero if it hit an exit() 332 * statement 333 */ 334int 335interpret(register NODE *volatile tree) 336{ 337 jmp_buf volatile loop_tag_stack; /* shallow binding stack for loop_tag */ 338 static jmp_buf rule_tag; /* tag the rule currently being run, for NEXT 339 * and EXIT statements. It is static because 340 * there are no nested rules */ 341 register NODE *volatile t = NULL; /* temporary */ 342 NODE **volatile lhs; /* lhs == Left Hand Side for assigns, etc */ 343 NODE *volatile stable_tree; 344 int volatile traverse = TRUE; /* True => loop thru tree (Node_rule_list) */ 345 346 /* avoid false source indications */ 347 source = NULL; 348 sourceline = 0; 349 350 if (tree == NULL) 351 return 1; 352 sourceline = tree->source_line; 353 source = tree->source_file; 354 switch (tree->type) { 355 case Node_rule_node: 356 traverse = FALSE; /* False => one for-loop iteration only */ 357 /* FALL THROUGH */ 358 case Node_rule_list: 359 for (t = tree; t != NULL; t = t->rnode) { 360 if (traverse) 361 tree = t->lnode; 362 sourceline = tree->source_line; 363 source = tree->source_file; 364 INCREMENT(tree->exec_count); 365 switch (setjmp(rule_tag)) { 366 case 0: /* normal non-jump */ 367 /* test pattern, if any */ 368 if (tree->lnode == NULL || 369 eval_condition(tree->lnode)) { 370 /* using the lnode exec_count is kludgey */ 371 if (tree->lnode != NULL) 372 INCREMENT(tree->lnode->exec_count); 373 (void) interpret(tree->rnode); 374 } 375 break; 376 case TAG_CONTINUE: /* NEXT statement */ 377 pop_all_forloops(); 378 pop_fcall_stack(); 379 return 1; 380 case TAG_BREAK: /* EXIT statement */ 381 pop_all_forloops(); 382 pop_fcall_stack(); 383 return 0; 384 default: 385 cant_happen(); 386 } 387 if (! traverse) /* case Node_rule_node */ 388 break; /* don't loop */ 389 } 390 break; 391 392 case Node_statement_list: 393 for (t = tree; t != NULL; t = t->rnode) 394 (void) interpret(t->lnode); 395 break; 396 397 case Node_K_if: 398 INCREMENT(tree->exec_count); 399 if (eval_condition(tree->lnode)) { 400 INCREMENT(tree->rnode->exec_count); 401 (void) interpret(tree->rnode->lnode); 402 } else { 403 (void) interpret(tree->rnode->rnode); 404 } 405 break; 406 407 case Node_K_switch: 408 { 409 NODE *switch_value; 410 NODE *switch_body; 411 NODE *case_list; 412 NODE *default_list; 413 NODE *case_stmt; 414 415 int match_found = FALSE; 416 417 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 418 INCREMENT(tree->exec_count); 419 stable_tree = tree; 420 421 switch_value = tree_eval(stable_tree->lnode); 422 switch_body = stable_tree->rnode; 423 case_list = switch_body->lnode; 424 default_list = switch_body->rnode; 425 426 for (; case_list != NULL; case_list = case_list->rnode) { 427 case_stmt = case_list->lnode; 428 429 /* 430 * Once a match is found, all cases will be processed as they fall through, 431 * so continue to execute statements until a break is reached. 432 */ 433 if (! match_found) { 434 if (case_stmt->type == Node_K_default) 435 ; /* do nothing */ 436 else if (case_stmt->lnode->type == Node_regex) { 437 NODE *t1; 438 Regexp *rp; 439 440 t1 = force_string(switch_value); 441 rp = re_update(case_stmt->lnode); 442 443 match_found = (research(rp, t1->stptr, 0, t1->stlen, FALSE) >= 0); 444 if (t1 != switch_value) 445 free_temp(t1); 446 } else { 447 match_found = (cmp_nodes(switch_value, case_stmt->lnode) == 0); 448 } 449 } 450 451 /* If a match was found, execute the statements associated with the case. */ 452 if (match_found) { 453 INCREMENT(case_stmt->exec_count); 454 switch (setjmp(loop_tag)) { 455 case 0: /* Normal non-jump */ 456 (void) interpret(case_stmt->rnode); 457 break; 458 case TAG_CONTINUE: /* continue statement */ 459 free_temp(switch_value); 460 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 461 longjmp(loop_tag, TAG_CONTINUE); 462 break; 463 case TAG_BREAK: /* break statement */ 464 free_temp(switch_value); 465 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 466 return 1; 467 default: 468 cant_happen(); 469 } 470 } 471 472 } 473 474 free_temp(switch_value); 475 476 /* 477 * If a default section was found, execute the statements associated with it 478 * and execute any trailing case statements if the default falls through. 479 */ 480 if (! match_found && default_list != NULL) { 481 for (case_list = default_list; 482 case_list != NULL; case_list = case_list->rnode) { 483 case_stmt = case_list->lnode; 484 485 INCREMENT(case_stmt->exec_count); 486 switch (setjmp(loop_tag)) { 487 case 0: /* Normal non-jump */ 488 (void) interpret(case_stmt->rnode); 489 break; 490 case TAG_CONTINUE: /* continue statement */ 491 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 492 longjmp(loop_tag, TAG_CONTINUE); 493 break; 494 case TAG_BREAK: /* break statement */ 495 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 496 return 1; 497 default: 498 cant_happen(); 499 } 500 } 501 } 502 503 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 504 } 505 break; 506 507 case Node_K_while: 508 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 509 510 stable_tree = tree; 511 while (eval_condition(stable_tree->lnode)) { 512 INCREMENT(stable_tree->exec_count); 513 switch (setjmp(loop_tag)) { 514 case 0: /* normal non-jump */ 515 (void) interpret(stable_tree->rnode); 516 break; 517 case TAG_CONTINUE: /* continue statement */ 518 break; 519 case TAG_BREAK: /* break statement */ 520 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 521 return 1; 522 default: 523 cant_happen(); 524 } 525 } 526 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 527 break; 528 529 case Node_K_do: 530 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 531 stable_tree = tree; 532 do { 533 INCREMENT(stable_tree->exec_count); 534 switch (setjmp(loop_tag)) { 535 case 0: /* normal non-jump */ 536 (void) interpret(stable_tree->rnode); 537 break; 538 case TAG_CONTINUE: /* continue statement */ 539 break; 540 case TAG_BREAK: /* break statement */ 541 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 542 return 1; 543 default: 544 cant_happen(); 545 } 546 } while (eval_condition(stable_tree->lnode)); 547 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 548 break; 549 550 case Node_K_for: 551 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 552 (void) interpret(tree->forloop->init); 553 stable_tree = tree; 554 while (eval_condition(stable_tree->forloop->cond)) { 555 INCREMENT(stable_tree->exec_count); 556 switch (setjmp(loop_tag)) { 557 case 0: /* normal non-jump */ 558 (void) interpret(stable_tree->lnode); 559 /* fall through */ 560 case TAG_CONTINUE: /* continue statement */ 561 (void) interpret(stable_tree->forloop->incr); 562 break; 563 case TAG_BREAK: /* break statement */ 564 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 565 return 1; 566 default: 567 cant_happen(); 568 } 569 } 570 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 571 break; 572 573 case Node_K_arrayfor: 574 { 575 Func_ptr after_assign = NULL; 576 NODE **list = NULL; 577 NODE *volatile array; 578 NODE *volatile save_array; 579 volatile size_t i, num_elems; 580 size_t j; 581 volatile int retval = 0; 582 int sort_indices = whiny_users; 583 584#define hakvar forloop->init 585#define arrvar forloop->incr 586 /* get the array */ 587 save_array = tree->arrvar; 588 array = get_array(save_array); 589 590 /* sanity: do nothing if empty */ 591 if (array->var_array == NULL || array->table_size == 0) 592 break; /* from switch */ 593 594 /* allocate space for array */ 595 num_elems = array->table_size; 596 emalloc(list, NODE **, num_elems * sizeof(NODE *), "for_loop"); 597 598 /* populate it */ 599 for (i = j = 0; i < array->array_size; i++) { 600 NODE *t = array->var_array[i]; 601 602 if (t == NULL) 603 continue; 604 605 for (; t != NULL; t = t->ahnext) { 606 list[j++] = dupnode(t); 607 assert(list[j-1] == t); 608 } 609 } 610 611 612 if (sort_indices) 613 qsort(list, num_elems, sizeof(NODE *), comp_func); /* shazzam! */ 614 615 /* now we can run the loop */ 616 push_forloop(array->vname, list, num_elems); 617 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 618 619 lhs = get_lhs(tree->hakvar, &after_assign, FALSE); 620 stable_tree = tree; 621 for (i = 0; i < num_elems; i++) { 622 INCREMENT(stable_tree->exec_count); 623 unref(*((NODE **) lhs)); 624 *lhs = make_string(list[i]->ahname_str, list[i]->ahname_len); 625 if (after_assign) 626 (*after_assign)(); 627 switch (setjmp(loop_tag)) { 628 case 0: 629 (void) interpret(stable_tree->lnode); 630 case TAG_CONTINUE: 631 break; 632 633 case TAG_BREAK: 634 retval = 1; 635 goto done; 636 637 default: 638 cant_happen(); 639 } 640 } 641 642 done: 643 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 644 pop_forloop(); 645 646 if (do_lint && num_elems != array->table_size) 647 lintwarn(_("for loop: array `%s' changed size from %ld to %ld during loop execution"), 648 array_vname(save_array), (long) num_elems, (long) array->table_size); 649 650 if (retval == 1) 651 return 1; 652 break; 653 } 654#undef hakvar 655#undef arrvar 656 657 case Node_K_break: 658 INCREMENT(tree->exec_count); 659 if (! loop_tag_valid) { 660 /* 661 * Old AT&T nawk treats break outside of loops like 662 * next. New ones catch it at parse time. Allow it if 663 * do_traditional is on, and complain if lint. 664 */ 665 static int warned = FALSE; 666 667 if (do_lint && ! warned) { 668 lintwarn(_("`break' outside a loop is not portable")); 669 warned = TRUE; 670 } 671 if (! do_traditional || do_posix) 672 fatal(_("`break' outside a loop is not allowed")); 673 longjmp(rule_tag, TAG_CONTINUE); 674 } else 675 longjmp(loop_tag, TAG_BREAK); 676 break; 677 678 case Node_K_continue: 679 INCREMENT(tree->exec_count); 680 if (! loop_tag_valid) { 681 /* 682 * Old AT&T nawk treats continue outside of loops like 683 * next. New ones catch it at parse time. Allow it if 684 * do_traditional is on, and complain if lint. 685 */ 686 static int warned = FALSE; 687 688 if (do_lint && ! warned) { 689 lintwarn(_("`continue' outside a loop is not portable")); 690 warned = TRUE; 691 } 692 if (! do_traditional || do_posix) 693 fatal(_("`continue' outside a loop is not allowed")); 694 longjmp(rule_tag, TAG_CONTINUE); 695 } else 696 longjmp(loop_tag, TAG_CONTINUE); 697 break; 698 699 case Node_K_print: 700 INCREMENT(tree->exec_count); 701 do_print(tree); 702 break; 703 704 case Node_K_print_rec: 705 INCREMENT(tree->exec_count); 706 do_print_rec(tree); 707 break; 708 709 case Node_K_printf: 710 INCREMENT(tree->exec_count); 711 do_printf(tree); 712 break; 713 714 case Node_K_delete: 715 INCREMENT(tree->exec_count); 716 do_delete(tree->lnode, tree->rnode); 717 break; 718 719 case Node_K_delete_loop: 720 INCREMENT(tree->exec_count); 721 do_delete_loop(tree->lnode, tree->rnode); 722 break; 723 724 case Node_K_next: 725 INCREMENT(tree->exec_count); 726 if (in_begin_rule) 727 fatal(_("`next' cannot be called from a BEGIN rule")); 728 else if (in_end_rule) 729 fatal(_("`next' cannot be called from an END rule")); 730 731 /* could add a lint check here for in a loop or function */ 732 longjmp(rule_tag, TAG_CONTINUE); 733 break; 734 735 case Node_K_nextfile: 736 INCREMENT(tree->exec_count); 737 if (in_begin_rule) 738 fatal(_("`nextfile' cannot be called from a BEGIN rule")); 739 else if (in_end_rule) 740 fatal(_("`nextfile' cannot be called from an END rule")); 741 742 /* could add a lint check here for in a loop or function */ 743 /* 744 * Have to do this cleanup here, since we don't longjump 745 * back to the main awk rule loop (rule_tag). 746 */ 747 pop_all_forloops(); 748 pop_fcall_stack(); 749 750 do_nextfile(); 751 break; 752 753 case Node_K_exit: 754 INCREMENT(tree->exec_count); 755 /* 756 * In A,K,&W, p. 49, it says that an exit statement "... 757 * causes the program to behave as if the end of input had 758 * occurred; no more input is read, and the END actions, if 759 * any are executed." This implies that the rest of the rules 760 * are not done. So we immediately break out of the main loop. 761 */ 762 exiting = TRUE; 763 if (tree->lnode != NULL) { 764 t = tree_eval(tree->lnode); 765 exit_val = (int) force_number(t); 766 free_temp(t); 767 } 768 longjmp(rule_tag, TAG_BREAK); 769 break; 770 771 case Node_K_return: 772 INCREMENT(tree->exec_count); 773 t = tree_eval(tree->lnode); 774 ret_node = dupnode(t); 775 free_temp(t); 776 longjmp(func_tag, TAG_RETURN); 777 break; 778 779 default: 780 /* 781 * Appears to be an expression statement. Throw away the 782 * value. 783 */ 784 if (do_lint && (tree->type == Node_var || tree->type == Node_var_new)) 785 lintwarn(_("statement has no effect")); 786 INCREMENT(tree->exec_count); 787 t = tree_eval(tree); 788 if (t) /* stopme() returns NULL */ 789 free_temp(t); 790 break; 791 } 792 return 1; 793} 794 795/* r_tree_eval --- evaluate a subtree */ 796 797NODE * 798r_tree_eval(register NODE *tree, int iscond) 799{ 800 register NODE *r, *t1, *t2; /* return value & temporary subtrees */ 801 register NODE **lhs; 802 register int di; 803 AWKNUM x, x1, x2; 804 long lx; 805#ifdef _CRAY 806 long lx2; 807#endif 808 809#ifndef TREE_EVAL_MACRO 810 if (tree == NULL) 811 return Nnull_string; 812 else if (tree->type == Node_val) { 813 if (tree->stref <= 0) 814 cant_happen(); 815 return ((tree->flags & INTLSTR) != 0 816 ? r_force_string(tree) 817 : tree); 818 } else if (tree->type == Node_var) { 819 if (tree->var_value->stref <= 0) 820 cant_happen(); 821 if (! var_uninitialized(tree)) 822 return tree->var_value; 823 } 824#endif 825 826 if (tree->type == Node_param_list) { 827 if ((tree->flags & FUNC) != 0) 828 fatal(_("can't use function name `%s' as variable or array"), 829 tree->vname); 830 831 tree = stack_ptr[tree->param_cnt]; 832 833 if (tree == NULL) { 834 if (do_lint) 835 lintwarn(_("reference to uninitialized argument `%s'"), 836 tree->vname); 837 return Nnull_string; 838 } 839 840 if (do_lint && var_uninitialized(tree)) 841 lintwarn(_("reference to uninitialized argument `%s'"), 842 tree->vname); 843 } 844 845 switch (tree->type) { 846 case Node_array_ref: 847 if (tree->orig_array->type == Node_var_array) 848 fatal(_("attempt to use array `%s' in a scalar context"), 849 array_vname(tree)); 850 tree->orig_array->type = Node_var; 851 /* fall through */ 852 case Node_var_new: 853 tree->type = Node_var; 854 tree->var_value = Nnull_string; 855 /* fall through */ 856 case Node_var: 857 if (do_lint && var_uninitialized(tree)) 858 lintwarn(_("reference to uninitialized variable `%s'"), 859 tree->vname); 860 return tree->var_value; 861 862 case Node_and: 863 return tmp_number((AWKNUM) (eval_condition(tree->lnode) 864 && eval_condition(tree->rnode))); 865 866 case Node_or: 867 return tmp_number((AWKNUM) (eval_condition(tree->lnode) 868 || eval_condition(tree->rnode))); 869 870 case Node_not: 871 return tmp_number((AWKNUM) ! eval_condition(tree->lnode)); 872 873 /* Builtins */ 874 case Node_builtin: 875 return (*tree->builtin)(tree->subnode); 876 877 case Node_K_getline: 878 return (do_getline(tree)); 879 880 case Node_in_array: 881 return tmp_number((AWKNUM) (in_array(tree->lnode, tree->rnode) != NULL)); 882 883 case Node_func_call: 884 return func_call(tree); 885 886 /* unary operations */ 887 case Node_NR: 888 case Node_FNR: 889 case Node_NF: 890 case Node_FIELDWIDTHS: 891 case Node_FS: 892 case Node_RS: 893 case Node_field_spec: 894 case Node_subscript: 895 case Node_IGNORECASE: 896 case Node_OFS: 897 case Node_ORS: 898 case Node_OFMT: 899 case Node_CONVFMT: 900 case Node_BINMODE: 901 case Node_LINT: 902 case Node_TEXTDOMAIN: 903 lhs = get_lhs(tree, (Func_ptr *) NULL, TRUE); 904 return *lhs; 905 906 case Node_var_array: 907 fatal(_("attempt to use array `%s' in a scalar context"), 908 array_vname(tree)); 909 910 case Node_unary_minus: 911 t1 = tree_eval(tree->subnode); 912 x = -force_number(t1); 913 free_temp(t1); 914 return tmp_number(x); 915 916 case Node_cond_exp: 917 if (eval_condition(tree->lnode)) 918 return tree_eval(tree->rnode->lnode); 919 return tree_eval(tree->rnode->rnode); 920 921 case Node_match: 922 case Node_nomatch: 923 case Node_regex: 924 case Node_dynregex: 925 return match_op(tree); 926 927 case Node_concat: 928 { 929 NODE **treelist; 930 NODE **strlist; 931 NODE *save_tree; 932 register NODE **treep; 933 register NODE **strp; 934 register size_t len; 935 register size_t supposed_len; 936 char *str; 937 register char *dest; 938 int alloc_count, str_count; 939 int i; 940 941 /* 942 * This is an efficiency hack for multiple adjacent string 943 * concatenations, to avoid recursion and string copies. 944 * 945 * Node_concat trees grow downward to the left, so 946 * descend to lowest (first) node, accumulating nodes 947 * to evaluate to strings as we go. 948 */ 949 950 /* 951 * But first, no arbitrary limits. Count the number of 952 * nodes and malloc the treelist and strlist arrays. 953 * There will be alloc_count + 1 items to concatenate. We 954 * also leave room for an extra pointer at the end to 955 * use as a sentinel. Thus, start alloc_count at 2. 956 */ 957 save_tree = tree; 958 for (alloc_count = 2; tree != NULL && tree->type == Node_concat; 959 tree = tree->lnode) 960 alloc_count++; 961 tree = save_tree; 962 emalloc(treelist, NODE **, sizeof(NODE *) * alloc_count, "tree_eval"); 963 emalloc(strlist, NODE **, sizeof(NODE *) * alloc_count, "tree_eval"); 964 965 /* Now, here we go. */ 966 treep = treelist; 967 while (tree != NULL && tree->type == Node_concat) { 968 *treep++ = tree->rnode; 969 tree = tree->lnode; 970 } 971 *treep = tree; 972 /* 973 * Now, evaluate to strings in LIFO order, accumulating 974 * the string length, so we can do a single malloc at the 975 * end. 976 * 977 * Evaluate the expressions first, then get their 978 * lengthes, in case one of the expressions has a 979 * side effect that changes one of the others. 980 * See test/nasty.awk. 981 * 982 * dupnode the results a la do_print, to give us 983 * more predicable behavior; compare gawk 3.0.6 to 984 * nawk/mawk on test/nasty.awk. 985 */ 986 strp = strlist; 987 supposed_len = len = 0; 988 while (treep >= treelist) { 989 NODE *n; 990 991 /* Here lies the wumpus's brother. R.I.P. */ 992 n = force_string(tree_eval(*treep--)); 993 *strp = dupnode(n); 994 free_temp(n); 995 supposed_len += (*strp)->stlen; 996 strp++; 997 } 998 *strp = NULL; 999 1000 str_count = strp - strlist; 1001 strp = strlist; 1002 for (i = 0; i < str_count; i++) { 1003 len += (*strp)->stlen; 1004 strp++; 1005 } 1006 if (do_lint && supposed_len != len) 1007 lintwarn(_("concatenation: side effects in one expression have changed the length of another!")); 1008 emalloc(str, char *, len+2, "tree_eval"); 1009 str[len] = str[len+1] = '\0'; /* for good measure */ 1010 dest = str; 1011 strp = strlist; 1012 while (*strp != NULL) { 1013 memcpy(dest, (*strp)->stptr, (*strp)->stlen); 1014 dest += (*strp)->stlen; 1015 unref(*strp); 1016 strp++; 1017 } 1018 r = make_str_node(str, len, ALREADY_MALLOCED); 1019 r->flags |= TEMP; 1020 1021 free(strlist); 1022 free(treelist); 1023 } 1024 return r; 1025 1026 /* assignments */ 1027 case Node_assign: 1028 { 1029 Func_ptr after_assign = NULL; 1030 1031 if (do_lint && iscond) 1032 lintwarn(_("assignment used in conditional context")); 1033 r = tree_eval(tree->rnode); 1034 lhs = get_lhs(tree->lnode, &after_assign, FALSE); 1035 1036 assign_val(lhs, r); 1037 if (after_assign) 1038 (*after_assign)(); 1039 return *lhs; 1040 } 1041 1042 /* other assignment types are easier because they are numeric */ 1043 case Node_preincrement: 1044 case Node_predecrement: 1045 case Node_postincrement: 1046 case Node_postdecrement: 1047 case Node_assign_exp: 1048 case Node_assign_times: 1049 case Node_assign_quotient: 1050 case Node_assign_mod: 1051 case Node_assign_plus: 1052 case Node_assign_minus: 1053 return op_assign(tree); 1054 default: 1055 break; /* handled below */ 1056 } 1057 1058 /* 1059 * Evaluate subtrees in order to do binary operation, then keep going. 1060 * Use dupnode to make sure that these values don't disappear out 1061 * from under us during recursive subexpression evaluation. 1062 */ 1063 t1 = dupnode(tree_eval(tree->lnode)); 1064 t2 = dupnode(tree_eval(tree->rnode)); 1065 1066 switch (tree->type) { 1067 case Node_geq: 1068 case Node_leq: 1069 case Node_greater: 1070 case Node_less: 1071 case Node_notequal: 1072 case Node_equal: 1073 di = cmp_nodes(t1, t2); 1074 unref(t1); 1075 unref(t2); 1076 switch (tree->type) { 1077 case Node_equal: 1078 return tmp_number((AWKNUM) (di == 0)); 1079 case Node_notequal: 1080 return tmp_number((AWKNUM) (di != 0)); 1081 case Node_less: 1082 return tmp_number((AWKNUM) (di < 0)); 1083 case Node_greater: 1084 return tmp_number((AWKNUM) (di > 0)); 1085 case Node_leq: 1086 return tmp_number((AWKNUM) (di <= 0)); 1087 case Node_geq: 1088 return tmp_number((AWKNUM) (di >= 0)); 1089 default: 1090 cant_happen(); 1091 } 1092 break; 1093 default: 1094 break; /* handled below */ 1095 } 1096 1097 x1 = force_number(t1); 1098 x2 = force_number(t2); 1099 unref(t1); 1100 unref(t2); 1101 switch (tree->type) { 1102 case Node_exp: 1103 if ((lx = x2) == x2 && lx >= 0) { /* integer exponent */ 1104 if (lx == 0) 1105 x = 1; 1106 else if (lx == 1) 1107 x = x1; 1108 else { 1109 /* doing it this way should be more precise */ 1110 for (x = x1; --lx; ) 1111 x *= x1; 1112 } 1113 } else 1114 x = pow((double) x1, (double) x2); 1115 return tmp_number(x); 1116 1117 case Node_times: 1118 return tmp_number(x1 * x2); 1119 1120 case Node_quotient: 1121 if (x2 == 0) 1122 fatal(_("division by zero attempted")); 1123#ifdef _CRAY 1124 /* special case for integer division, put in for Cray */ 1125 lx2 = x2; 1126 if (lx2 == 0) 1127 return tmp_number(x1 / x2); 1128 lx = (long) x1 / lx2; 1129 if (lx * x2 == x1) 1130 return tmp_number((AWKNUM) lx); 1131 else 1132#endif 1133 return tmp_number(x1 / x2); 1134 1135 case Node_mod: 1136 if (x2 == 0) 1137 fatal(_("division by zero attempted in `%%'")); 1138#ifdef HAVE_FMOD 1139 return tmp_number(fmod(x1, x2)); 1140#else /* ! HAVE_FMOD */ 1141 (void) modf(x1 / x2, &x); 1142 return tmp_number(x1 - x * x2); 1143#endif /* ! HAVE_FMOD */ 1144 1145 case Node_plus: 1146 return tmp_number(x1 + x2); 1147 1148 case Node_minus: 1149 return tmp_number(x1 - x2); 1150 1151 default: 1152 fatal(_("illegal type (%s) in tree_eval"), nodetype2str(tree->type)); 1153 } 1154 return 0; 1155} 1156 1157/* eval_condition --- is TREE true or false? Returns 0==false, non-zero==true */ 1158 1159static int 1160eval_condition(register NODE *tree) 1161{ 1162 register NODE *t1; 1163 register int ret; 1164 1165 if (tree == NULL) /* Null trees are the easiest kinds */ 1166 return TRUE; 1167 if (tree->type == Node_line_range) { 1168 /* 1169 * Node_line_range is kind of like Node_match, EXCEPT: the 1170 * lnode field (more properly, the condpair field) is a node 1171 * of a Node_cond_pair; whether we evaluate the lnode of that 1172 * node or the rnode depends on the triggered word. More 1173 * precisely: if we are not yet triggered, we tree_eval the 1174 * lnode; if that returns true, we set the triggered word. 1175 * If we are triggered (not ELSE IF, note), we tree_eval the 1176 * rnode, clear triggered if it succeeds, and perform our 1177 * action (regardless of success or failure). We want to be 1178 * able to begin and end on a single input record, so this 1179 * isn't an ELSE IF, as noted above. 1180 */ 1181 if (! tree->triggered) { 1182 if (! eval_condition(tree->condpair->lnode)) 1183 return FALSE; 1184 else 1185 tree->triggered = TRUE; 1186 } 1187 /* Else we are triggered */ 1188 if (eval_condition(tree->condpair->rnode)) 1189 tree->triggered = FALSE; 1190 return TRUE; 1191 } 1192 1193 /* 1194 * Could just be J.random expression. in which case, null and 0 are 1195 * false, anything else is true 1196 */ 1197 1198 t1 = m_tree_eval(tree, TRUE); 1199 if (t1->flags & MAYBE_NUM) 1200 (void) force_number(t1); 1201 if (t1->flags & NUMBER) 1202 ret = (t1->numbr != 0.0); 1203 else 1204 ret = (t1->stlen != 0); 1205 free_temp(t1); 1206 return ret; 1207} 1208 1209/* cmp_nodes --- compare two nodes, returning negative, 0, positive */ 1210 1211int 1212cmp_nodes(register NODE *t1, register NODE *t2) 1213{ 1214 register int ret; 1215 register size_t len1, len2; 1216 register int l; 1217 int ldiff; 1218 1219 if (t1 == t2) 1220 return 0; 1221 if (t1->flags & MAYBE_NUM) 1222 (void) force_number(t1); 1223 if (t2->flags & MAYBE_NUM) 1224 (void) force_number(t2); 1225 if ((t1->flags & NUMBER) && (t2->flags & NUMBER)) { 1226 if (t1->numbr == t2->numbr) 1227 return 0; 1228 /* don't subtract, in case one or both are infinite */ 1229 else if (t1->numbr < t2->numbr) 1230 return -1; 1231 else 1232 return 1; 1233 } 1234 (void) force_string(t1); 1235 (void) force_string(t2); 1236 len1 = t1->stlen; 1237 len2 = t2->stlen; 1238 ldiff = len1 - len2; 1239 if (len1 == 0 || len2 == 0) 1240 return ldiff; 1241 l = (ldiff <= 0 ? len1 : len2); 1242 if (IGNORECASE) { 1243 const unsigned char *cp1 = (const unsigned char *) t1->stptr; 1244 const unsigned char *cp2 = (const unsigned char *) t2->stptr; 1245 1246#ifdef MBS_SUPPORT 1247 if (gawk_mb_cur_max > 1) { 1248 mbstate_t mbs; 1249 memset(&mbs, 0, sizeof(mbstate_t)); 1250 ret = strncasecmpmbs((const char *) cp1, mbs, 1251 (const char *) cp2, mbs, l); 1252 } else 1253#endif 1254 for (ret = 0; l-- > 0 && ret == 0; cp1++, cp2++) 1255 ret = casetable[*cp1] - casetable[*cp2]; 1256 } else 1257 ret = memcmp(t1->stptr, t2->stptr, l); 1258 return (ret == 0 ? ldiff : ret); 1259} 1260 1261/* op_assign --- do +=, -=, etc. */ 1262 1263static NODE * 1264op_assign(register NODE *tree) 1265{ 1266 AWKNUM rval, lval; 1267 NODE **lhs; 1268 AWKNUM t1, t2; 1269 long ltemp; 1270 NODE *tmp; 1271 Func_ptr after_assign = NULL; 1272 int post = FALSE; 1273 1274 /* 1275 * For += etc, do the rhs first, since it can rearrange things, 1276 * and *then* get the lhs. 1277 */ 1278 if (tree->rnode != NULL) { 1279 tmp = tree_eval(tree->rnode); 1280 rval = force_number(tmp); 1281 free_temp(tmp); 1282 } else 1283 rval = (AWKNUM) 1.0; 1284 1285 lhs = get_lhs(tree->lnode, &after_assign, TRUE); 1286 lval = force_number(*lhs); 1287 unref(*lhs); 1288 1289 switch(tree->type) { 1290 case Node_postincrement: 1291 post = TRUE; 1292 /* fall through */ 1293 case Node_preincrement: 1294 case Node_assign_plus: 1295 *lhs = make_number(lval + rval); 1296 break; 1297 1298 case Node_postdecrement: 1299 post = TRUE; 1300 /* fall through */ 1301 case Node_predecrement: 1302 case Node_assign_minus: 1303 *lhs = make_number(lval - rval); 1304 break; 1305 1306 case Node_assign_exp: 1307 if ((ltemp = rval) == rval) { /* integer exponent */ 1308 if (ltemp == 0) 1309 *lhs = make_number((AWKNUM) 1); 1310 else if (ltemp == 1) 1311 *lhs = make_number(lval); 1312 else { 1313 /* doing it this way should be more precise */ 1314 for (t1 = t2 = lval; --ltemp; ) 1315 t1 *= t2; 1316 *lhs = make_number(t1); 1317 } 1318 } else 1319 *lhs = make_number((AWKNUM) pow((double) lval, (double) rval)); 1320 break; 1321 1322 case Node_assign_times: 1323 *lhs = make_number(lval * rval); 1324 break; 1325 1326 case Node_assign_quotient: 1327 if (rval == (AWKNUM) 0) 1328 fatal(_("division by zero attempted in `/='")); 1329#ifdef _CRAY 1330 /* special case for integer division, put in for Cray */ 1331 ltemp = rval; 1332 if (ltemp == 0) { 1333 *lhs = make_number(lval / rval); 1334 break; 1335 } 1336 ltemp = (long) lval / ltemp; 1337 if (ltemp * lval == rval) 1338 *lhs = make_number((AWKNUM) ltemp); 1339 else 1340#endif /* _CRAY */ 1341 *lhs = make_number(lval / rval); 1342 break; 1343 1344 case Node_assign_mod: 1345 if (rval == (AWKNUM) 0) 1346 fatal(_("division by zero attempted in `%%='")); 1347#ifdef HAVE_FMOD 1348 *lhs = make_number(fmod(lval, rval)); 1349#else /* ! HAVE_FMOD */ 1350 (void) modf(lval / rval, &t1); 1351 t2 = lval - rval * t1; 1352 *lhs = make_number(t2); 1353#endif /* ! HAVE_FMOD */ 1354 break; 1355 1356 default: 1357 cant_happen(); 1358 } 1359 1360 if (after_assign) 1361 (*after_assign)(); 1362 1363 /* for postincrement or postdecrement, return the old value */ 1364 return (post ? tmp_number(lval) : *lhs); 1365} 1366 1367/* 1368 * Avoiding memory leaks is difficult. In paticular, any of `next', 1369 * `nextfile', `break' or `continue' (when not in a loop), can longjmp 1370 * out to the outermost level. This leaks memory if it happens in a 1371 * called function. It also leaks memory if it happens in a 1372 * `for (iggy in foo)' loop, since such loops malloc an array of the 1373 * current array indices to loop over, which provides stability. 1374 * 1375 * The following code takes care of these problems. First comes the 1376 * array-loop management code. This can be a stack of arrays being looped 1377 * on at any one time. This stack serves for both mainline code and 1378 * function body code. As each loop starts and finishes, it pushes its 1379 * info onto this stack and off of it; whether the loop is in a function 1380 * body or not isn't relevant. 1381 * 1382 * Since the list of indices is created using dupnode(), when popping 1383 * this stack it should be safe to unref() things, and then memory 1384 * will get finally released when the function call stack is popped. 1385 * This means that the loop_stack should be popped first upon a `next'. 1386 */ 1387 1388static struct loop_info { 1389 const char *varname; /* variable name, for debugging */ 1390 NODE **elems; /* list of indices */ 1391 size_t nelems; /* how many there are */ 1392} *loop_stack = NULL; 1393size_t nloops = 0; /* how many slots there are in the stack */ 1394size_t nloops_active = 0; /* how many loops are actively stacked */ 1395 1396/* pop_forloop --- pop one for loop off the stack */ 1397 1398static void 1399pop_forloop() 1400{ 1401 int i, curloop; 1402 struct loop_info *loop; 1403 1404 assert(nloops_active > 0); 1405 1406 curloop = --nloops_active; /* 0-based indexing */ 1407 loop = & loop_stack[curloop]; 1408 1409 for (i = 0; i < loop->nelems; i++) 1410 unref(loop->elems[i]); 1411 1412 free(loop->elems); 1413 1414 loop->elems = NULL; 1415 loop->varname = NULL; 1416 loop->nelems = 0; 1417} 1418 1419/* pop_forloops --- pop the for loops stack all the way */ 1420 1421static inline void 1422pop_all_forloops() 1423{ 1424 while (nloops_active > 0) 1425 pop_forloop(); /* decrements nloops_active for us */ 1426} 1427 1428/* push_forloop --- add a single for loop to the stack */ 1429 1430static void 1431push_forloop(const char *varname, NODE **elems, size_t nelems) 1432{ 1433#define NLOOPS 4 /* seems like a good guess */ 1434 if (loop_stack == NULL) { 1435 /* allocate stack, set vars */ 1436 nloops = NLOOPS; 1437 emalloc(loop_stack, struct loop_info *, nloops * sizeof(struct loop_info), 1438 "push_forloop"); 1439 } else if (nloops_active == nloops) { 1440 /* grow stack, set vars */ 1441 nloops *= 2; 1442 erealloc(loop_stack, struct loop_info *, nloops * sizeof(struct loop_info), 1443 "push_forloop"); 1444 } 1445 1446 loop_stack[nloops_active].varname = varname; 1447 loop_stack[nloops_active].elems = elems; 1448 loop_stack[nloops_active].nelems = nelems; 1449 nloops_active++; 1450} 1451 1452static struct fcall { 1453 const char *fname; /* function name */ 1454 unsigned long count; /* how many args */ 1455 NODE *arglist; /* list thereof */ 1456 NODE **prevstack; /* function stack frame of previous function */ 1457 NODE **stack; /* function stack frame of current function */ 1458} *fcall_list = NULL; 1459 1460static long fcall_list_size = 0; 1461static long curfcall = -1; 1462 1463/* pop_fcall --- pop off a single function call */ 1464 1465static void 1466pop_fcall() 1467{ 1468 NODE *n, **sp; 1469 int count; 1470 struct fcall *f; 1471 1472 assert(curfcall >= 0); 1473 f = & fcall_list[curfcall]; 1474 stack_ptr = f->prevstack; 1475 1476 sp = f->stack; 1477 1478 for (count = f->count; count > 0; count--) { 1479 n = *sp++; 1480 if (n->type == Node_var) /* local variable */ 1481 unref(n->var_value); 1482 else if (n->type == Node_var_array) /* local array */ 1483 assoc_clear(n); 1484 freenode(n); 1485 } 1486 if (f->stack) 1487 free((char *) f->stack); 1488 /* memset(f, '\0', sizeof(struct fcall)); */ 1489 curfcall--; 1490} 1491 1492/* pop_fcall_stack --- pop off all function args, don't leak memory */ 1493 1494static inline void 1495pop_fcall_stack() 1496{ 1497 while (curfcall >= 0) 1498 pop_fcall(); 1499} 1500 1501/* push_args --- push function arguments onto the stack */ 1502 1503static void 1504push_args(int count, 1505 NODE *argp, 1506 NODE **oldstack, 1507 const char *func_name, 1508 char **varnames) 1509{ 1510 struct fcall *f; 1511 NODE *arg, *r, **sp; 1512 int i; 1513 1514 if (fcall_list_size == 0) { /* first time */ 1515 emalloc(fcall_list, struct fcall *, 10 * sizeof(struct fcall), 1516 "push_args"); 1517 fcall_list_size = 10; 1518 } 1519 1520 if (++curfcall >= fcall_list_size) { 1521 fcall_list_size *= 2; 1522 erealloc(fcall_list, struct fcall *, 1523 fcall_list_size * sizeof(struct fcall), "push_args"); 1524 } 1525 f = & fcall_list[curfcall]; 1526 1527 if (count > 0) 1528 emalloc(f->stack, NODE **, count*sizeof(NODE *), "push_args"); 1529 else 1530 f->stack = NULL; 1531 f->count = count; 1532 f->fname = func_name; /* not used, for debugging, just in case */ 1533 f->arglist = argp; 1534 f->prevstack = oldstack; 1535 1536 sp = f->stack; 1537 1538 /* for each calling arg. add NODE * on stack */ 1539 for (i = 0; i < count; i++) { 1540 getnode(r); 1541 *sp++ = r; 1542 if (argp == NULL) { 1543 /* local variable */ 1544 r->type = Node_var_new; 1545 r->vname = varnames[i]; 1546 continue; 1547 } 1548 arg = argp->lnode; 1549 /* call by reference for arrays; see below also */ 1550 if (arg->type == Node_param_list) { 1551 /* we must also reassign f here; see below */ 1552 f = & fcall_list[curfcall]; 1553 arg = f->prevstack[arg->param_cnt]; 1554 } 1555 if (arg->type == Node_var_array || arg->type == Node_var_new) { 1556 r->type = Node_array_ref; 1557 r->orig_array = arg; 1558 r->prev_array = arg; 1559 } else if (arg->type == Node_array_ref) { 1560 *r = *arg; 1561 r->prev_array = arg; 1562 } else { 1563 NODE *n = tree_eval(arg); 1564 1565 r->type = Node_var; 1566 r->lnode = dupnode(n); 1567 r->rnode = (NODE *) NULL; 1568 free_temp(n); 1569 } 1570 r->vname = varnames[i]; 1571 argp = argp->rnode; 1572 } 1573 1574 /* 1575 * We have to reassign f. Why, you may ask? It is possible that 1576 * other functions were called during the course of tree_eval()-ing 1577 * the arguments to this function. As a result of that, fcall_list 1578 * may have been realloc()'ed, with the result that f is now 1579 * pointing into free()'d space. This was a nasty one to track down. 1580 */ 1581 f = & fcall_list[curfcall]; 1582 1583 if (argp != NULL) { 1584 /* Left over calling args. */ 1585 warning( 1586 _("function `%s' called with more arguments than declared"), 1587 func_name); 1588 /* Evaluate them, they may have side effects: */ 1589 do { 1590 arg = argp->lnode; 1591 if (arg->type == Node_param_list) 1592 arg = f->prevstack[arg->param_cnt]; 1593 if (arg->type != Node_var_array && 1594 arg->type != Node_array_ref && 1595 arg->type != Node_var_new) 1596 free_temp(tree_eval(arg)); 1597 1598 /* reassign f, tree_eval could have moved it */ 1599 f = & fcall_list[curfcall]; 1600 } while ((argp = argp->rnode) != NULL); 1601 } 1602 1603 stack_ptr = f->stack; 1604} 1605 1606/* func_call --- call a function, call by reference for arrays */ 1607 1608NODE **stack_ptr; 1609 1610static NODE * 1611func_call(NODE *tree) 1612{ 1613 register NODE *r; 1614 NODE *name, *arg_list; 1615 NODE *f; 1616 jmp_buf volatile func_tag_stack; 1617 jmp_buf volatile loop_tag_stack; 1618 int volatile save_loop_tag_valid = FALSE; 1619 NODE *save_ret_node; 1620 extern NODE *ret_node; 1621 1622 /* tree->rnode is a Node_val giving function name */ 1623 /* tree->lnode is Node_expression_list of calling args. */ 1624 name = tree->rnode; 1625 arg_list = tree->lnode; 1626 1627 /* retrieve function definition node */ 1628 if (tree->funcbody != NULL) 1629 f = tree->funcbody; 1630 else { 1631 f = lookup(name->stptr); 1632 if (f == NULL || f->type != Node_func) 1633 fatal(_("function `%s' not defined"), name->stptr); 1634 1635 tree->funcbody = f; /* save for next call */ 1636 } 1637 1638#ifdef FUNC_TRACE 1639 fprintf(stderr, _("function %s called\n"), name->stptr); 1640#endif 1641 push_args(f->lnode->param_cnt, arg_list, stack_ptr, name->stptr, 1642 f->parmlist); 1643 1644 /* 1645 * Execute function body, saving context, as a return statement 1646 * will longjmp back here. 1647 * 1648 * Have to save and restore the loop_tag stuff so that a return 1649 * inside a loop in a function body doesn't scrog any loops going 1650 * on in the main program. We save the necessary info in variables 1651 * local to this function so that function nesting works OK. 1652 * We also only bother to save the loop stuff if we're in a loop 1653 * when the function is called. 1654 */ 1655 if (loop_tag_valid) { 1656 int junk = 0; 1657 1658 save_loop_tag_valid = (volatile int) loop_tag_valid; 1659 PUSH_BINDING(loop_tag_stack, loop_tag, junk); 1660 loop_tag_valid = FALSE; 1661 } 1662 PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid); 1663 save_ret_node = ret_node; 1664 ret_node = Nnull_string; /* default return value */ 1665 INCREMENT(f->exec_count); /* count function calls */ 1666 if (setjmp(func_tag) == 0) 1667 (void) interpret(f->rnode); 1668 1669 r = ret_node; 1670 ret_node = (NODE *) save_ret_node; 1671 RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid); 1672 pop_fcall(); 1673 1674 /* Restore the loop_tag stuff if necessary. */ 1675 if (save_loop_tag_valid) { 1676 int junk = 0; 1677 1678 loop_tag_valid = (int) save_loop_tag_valid; 1679 RESTORE_BINDING(loop_tag_stack, loop_tag, junk); 1680 } 1681 1682 if ((r->flags & PERM) == 0) 1683 r->flags |= TEMP; 1684 return r; 1685} 1686 1687#ifdef PROFILING 1688/* dump_fcall_stack --- print a backtrace of the awk function calls */ 1689 1690void 1691dump_fcall_stack(FILE *fp) 1692{ 1693 int i; 1694 1695 if (curfcall < 0) 1696 return; 1697 1698 fprintf(fp, _("\n\t# Function Call Stack:\n\n")); 1699 for (i = curfcall; i >= 0; i--) 1700 fprintf(fp, "\t# %3d. %s\n", i+1, fcall_list[i].fname); 1701 fprintf(fp, _("\t# -- main --\n")); 1702} 1703#endif /* PROFILING */ 1704 1705/* 1706 * r_get_lhs: 1707 * This returns a POINTER to a node pointer. get_lhs(ptr) is the current 1708 * value of the var, or where to store the var's new value 1709 * 1710 * For the special variables, don't unref their current value if it's 1711 * the same as the internal copy; perhaps the current one is used in 1712 * a concatenation or some other expression somewhere higher up in the 1713 * call chain. Ouch. 1714 */ 1715 1716NODE ** 1717r_get_lhs(register NODE *ptr, Func_ptr *assign, int reference) 1718{ 1719 register NODE **aptr = NULL; 1720 register NODE *n; 1721 1722 if (assign) 1723 *assign = NULL; /* for safety */ 1724 if (ptr->type == Node_param_list) { 1725 if ((ptr->flags & FUNC) != 0) 1726 fatal(_("can't use function name `%s' as variable or array"), ptr->vname); 1727 ptr = stack_ptr[ptr->param_cnt]; 1728 } 1729 1730 switch (ptr->type) { 1731 case Node_var_array: 1732 fatal(_("attempt to use array `%s' in a scalar context"), 1733 array_vname(ptr)); 1734 1735 /* 1736 * The following goop ensures that uninitialized variables 1737 * used as parameters eventually get their type set correctly 1738 * to scalar (i.e., Node_var). 1739 */ 1740 case Node_array_ref: 1741 if (ptr->orig_array->type == Node_var_array) 1742 fatal(_("attempt to use array `%s' in a scalar context"), 1743 array_vname(ptr)); 1744 ptr->orig_array->type = Node_var; 1745 /* fall through */ 1746 case Node_var_new: 1747 ptr->type = Node_var; 1748 ptr->var_value = Nnull_string; 1749 /* fall through */ 1750 case Node_var: 1751 if (do_lint && reference && var_uninitialized(ptr)) 1752 lintwarn(_("reference to uninitialized variable `%s'"), 1753 ptr->vname); 1754 1755 aptr = &(ptr->var_value); 1756#ifdef GAWKDEBUG 1757 if (ptr->var_value->stref <= 0) 1758 cant_happen(); 1759#endif 1760 break; 1761 1762 case Node_FIELDWIDTHS: 1763 aptr = &(FIELDWIDTHS_node->var_value); 1764 if (assign != NULL) 1765 *assign = set_FIELDWIDTHS; 1766 break; 1767 1768 case Node_RS: 1769 aptr = &(RS_node->var_value); 1770 if (assign != NULL) 1771 *assign = set_RS; 1772 break; 1773 1774 case Node_FS: 1775 aptr = &(FS_node->var_value); 1776 if (assign != NULL) 1777 *assign = set_FS; 1778 break; 1779 1780 case Node_FNR: 1781 if (FNR_node->var_value->numbr != FNR) { 1782 unref(FNR_node->var_value); 1783 FNR_node->var_value = make_number((AWKNUM) FNR); 1784 } 1785 aptr = &(FNR_node->var_value); 1786 if (assign != NULL) 1787 *assign = set_FNR; 1788 break; 1789 1790 case Node_NR: 1791 if (NR_node->var_value->numbr != NR) { 1792 unref(NR_node->var_value); 1793 NR_node->var_value = make_number((AWKNUM) NR); 1794 } 1795 aptr = &(NR_node->var_value); 1796 if (assign != NULL) 1797 *assign = set_NR; 1798 break; 1799 1800 case Node_NF: 1801 if (NF == -1 || NF_node->var_value->numbr != NF) { 1802 if (NF == -1) 1803 (void) get_field(HUGE-1, assign); /* parse record */ 1804 unref(NF_node->var_value); 1805 NF_node->var_value = make_number((AWKNUM) NF); 1806 } 1807 aptr = &(NF_node->var_value); 1808 if (assign != NULL) 1809 *assign = set_NF; 1810 break; 1811 1812 case Node_IGNORECASE: 1813 aptr = &(IGNORECASE_node->var_value); 1814 if (assign != NULL) 1815 *assign = set_IGNORECASE; 1816 break; 1817 1818 case Node_BINMODE: 1819 aptr = &(BINMODE_node->var_value); 1820 if (assign != NULL) 1821 *assign = set_BINMODE; 1822 break; 1823 1824 case Node_LINT: 1825 aptr = &(LINT_node->var_value); 1826 if (assign != NULL) 1827 *assign = set_LINT; 1828 break; 1829 1830 case Node_OFMT: 1831 aptr = &(OFMT_node->var_value); 1832 if (assign != NULL) 1833 *assign = set_OFMT; 1834 break; 1835 1836 case Node_CONVFMT: 1837 aptr = &(CONVFMT_node->var_value); 1838 if (assign != NULL) 1839 *assign = set_CONVFMT; 1840 break; 1841 1842 case Node_ORS: 1843 aptr = &(ORS_node->var_value); 1844 if (assign != NULL) 1845 *assign = set_ORS; 1846 break; 1847 1848 case Node_OFS: 1849 aptr = &(OFS_node->var_value); 1850 if (assign != NULL) 1851 *assign = set_OFS; 1852 break; 1853 1854 case Node_TEXTDOMAIN: 1855 aptr = &(TEXTDOMAIN_node->var_value); 1856 if (assign != NULL) 1857 *assign = set_TEXTDOMAIN; 1858 break; 1859 1860 case Node_field_spec: 1861 { 1862 int field_num; 1863 1864 n = tree_eval(ptr->lnode); 1865 if (do_lint) { 1866 if ((n->flags & NUMBER) == 0) { 1867 lintwarn(_("attempt to field reference from non-numeric value")); 1868 if (n->stlen == 0) 1869 lintwarn(_("attempt to reference from null string")); 1870 } 1871 } 1872 field_num = (int) force_number(n); 1873 free_temp(n); 1874 if (field_num < 0) 1875 fatal(_("attempt to access field %d"), field_num); 1876 if (field_num == 0 && field0_valid) { /* short circuit */ 1877 aptr = &fields_arr[0]; 1878 if (assign != NULL) 1879 *assign = reset_record; 1880 } else 1881 aptr = get_field(field_num, assign); 1882 if (do_lint && reference && (*aptr == Null_field || *aptr == Nnull_string)) 1883 lintwarn(_("reference to uninitialized field `$%d'"), 1884 field_num); 1885 break; 1886 } 1887 1888 case Node_subscript: 1889 n = get_array(ptr->lnode); 1890 aptr = assoc_lookup(n, concat_exp(ptr->rnode), reference); 1891 break; 1892 1893 case Node_builtin: 1894#if 1 1895 /* in gawk for a while */ 1896 fatal(_("assignment is not allowed to result of builtin function")); 1897#else 1898 /* 1899 * This is how Christos at Deshaw did it. 1900 * Does this buy us anything? 1901 */ 1902 if (ptr->builtin == NULL) 1903 fatal(_("assignment is not allowed to result of builtin function")); 1904 ptr->callresult = (*ptr->builtin)(ptr->subnode); 1905 aptr = &ptr->callresult; 1906 break; 1907#endif 1908 1909 default: 1910 fprintf(stderr, "type = %s\n", nodetype2str(ptr->type)); 1911 fflush(stderr); 1912 cant_happen(); 1913 } 1914 return aptr; 1915} 1916 1917/* match_op --- do ~ and !~ */ 1918 1919static NODE * 1920match_op(register NODE *tree) 1921{ 1922 register NODE *t1; 1923 register Regexp *rp; 1924 int i; 1925 int match = TRUE; 1926 1927 if (tree->type == Node_nomatch) 1928 match = FALSE; 1929 if (tree->type == Node_regex) 1930 t1 = *get_field(0, (Func_ptr *) 0); 1931 else { 1932 t1 = force_string(tree_eval(tree->lnode)); 1933 tree = tree->rnode; 1934 } 1935 rp = re_update(tree); 1936 i = research(rp, t1->stptr, 0, t1->stlen, FALSE); 1937 i = (i == -1) ^ (match == TRUE); 1938 free_temp(t1); 1939 return tmp_number((AWKNUM) i); 1940} 1941 1942/* set_IGNORECASE --- update IGNORECASE as appropriate */ 1943 1944void 1945set_IGNORECASE() 1946{ 1947 static int warned = FALSE; 1948 1949 if ((do_lint || do_traditional) && ! warned) { 1950 warned = TRUE; 1951 lintwarn(_("`IGNORECASE' is a gawk extension")); 1952 } 1953 if (do_traditional) 1954 IGNORECASE = FALSE; 1955 else if ((IGNORECASE_node->var_value->flags & (STRING|STRCUR)) != 0) { 1956 if ((IGNORECASE_node->var_value->flags & MAYBE_NUM) == 0) 1957 IGNORECASE = (force_string(IGNORECASE_node->var_value)->stlen > 0); 1958 else 1959 IGNORECASE = (force_number(IGNORECASE_node->var_value) != 0.0); 1960 } else if ((IGNORECASE_node->var_value->flags & (NUMCUR|NUMBER)) != 0) 1961 IGNORECASE = (force_number(IGNORECASE_node->var_value) != 0.0); 1962 else 1963 IGNORECASE = FALSE; /* shouldn't happen */ 1964 1965 set_RS(); /* set_RS() calls set_FS() if need be, for us */ 1966} 1967 1968/* set_BINMODE --- set translation mode (OS/2, DOS, others) */ 1969 1970void 1971set_BINMODE() 1972{ 1973 static int warned = FALSE; 1974 char *p, *cp, save; 1975 NODE *v; 1976 int digits = FALSE; 1977 1978 if ((do_lint || do_traditional) && ! warned) { 1979 warned = TRUE; 1980 lintwarn(_("`BINMODE' is a gawk extension")); 1981 } 1982 if (do_traditional) 1983 BINMODE = 0; 1984 else if ((BINMODE_node->var_value->flags & STRING) != 0) { 1985 v = BINMODE_node->var_value; 1986 p = v->stptr; 1987 save = p[v->stlen]; 1988 p[v->stlen] = '\0'; 1989 1990 for (cp = p; *cp != '\0'; cp++) { 1991 if (ISDIGIT(*cp)) { 1992 digits = TRUE; 1993 break; 1994 } 1995 } 1996 1997 if (! digits || (BINMODE_node->var_value->flags & MAYBE_NUM) == 0) { 1998 BINMODE = 0; 1999 if (strcmp(p, "r") == 0) 2000 BINMODE = 1; 2001 else if (strcmp(p, "w") == 0) 2002 BINMODE = 2; 2003 else if (strcmp(p, "rw") == 0 || strcmp(p, "wr") == 0) 2004 BINMODE = 3; 2005 2006 if (BINMODE == 0 && v->stlen != 0) { 2007 /* arbitrary string, assume both */ 2008 BINMODE = 3; 2009 warning("BINMODE: arbitary string value treated as \"rw\""); 2010 } 2011 } else 2012 BINMODE = (int) force_number(BINMODE_node->var_value); 2013 2014 p[v->stlen] = save; 2015 } else if ((BINMODE_node->var_value->flags & NUMBER) != 0) 2016 BINMODE = (int) force_number(BINMODE_node->var_value); 2017 else 2018 BINMODE = 0; /* shouldn't happen */ 2019} 2020 2021/* set_OFS --- update OFS related variables when OFS assigned to */ 2022 2023void 2024set_OFS() 2025{ 2026 OFS = force_string(OFS_node->var_value)->stptr; 2027 OFSlen = OFS_node->var_value->stlen; 2028 OFS[OFSlen] = '\0'; 2029} 2030 2031/* set_ORS --- update ORS related variables when ORS assigned to */ 2032 2033void 2034set_ORS() 2035{ 2036 ORS = force_string(ORS_node->var_value)->stptr; 2037 ORSlen = ORS_node->var_value->stlen; 2038 ORS[ORSlen] = '\0'; 2039} 2040 2041/* fmt_ok --- is the conversion format a valid one? */ 2042 2043NODE **fmt_list = NULL; 2044static int fmt_ok P((NODE *n)); 2045static int fmt_index P((NODE *n)); 2046 2047static int 2048fmt_ok(NODE *n) 2049{ 2050 NODE *tmp = force_string(n); 2051 const char *p = tmp->stptr; 2052 2053 if (*p++ != '%') 2054 return 0; 2055 while (*p && strchr(" +-#", *p) != NULL) /* flags */ 2056 p++; 2057 while (*p && ISDIGIT(*p)) /* width - %*.*g is NOT allowed */ 2058 p++; 2059 if (*p == '\0' || (*p != '.' && ! ISDIGIT(*p))) 2060 return 0; 2061 if (*p == '.') 2062 p++; 2063 while (*p && ISDIGIT(*p)) /* precision */ 2064 p++; 2065 if (*p == '\0' || strchr("efgEG", *p) == NULL) 2066 return 0; 2067 if (*++p != '\0') 2068 return 0; 2069 return 1; 2070} 2071 2072/* fmt_index --- track values of OFMT and CONVFMT to keep semantics correct */ 2073 2074static int 2075fmt_index(NODE *n) 2076{ 2077 register int ix = 0; 2078 static int fmt_num = 4; 2079 static int fmt_hiwater = 0; 2080 2081 if (fmt_list == NULL) 2082 emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), "fmt_index"); 2083 (void) force_string(n); 2084 while (ix < fmt_hiwater) { 2085 if (cmp_nodes(fmt_list[ix], n) == 0) 2086 return ix; 2087 ix++; 2088 } 2089 /* not found */ 2090 n->stptr[n->stlen] = '\0'; 2091 if (do_lint && ! fmt_ok(n)) 2092 lintwarn(_("bad `%sFMT' specification `%s'"), 2093 n == CONVFMT_node->var_value ? "CONV" 2094 : n == OFMT_node->var_value ? "O" 2095 : "", n->stptr); 2096 2097 if (fmt_hiwater >= fmt_num) { 2098 fmt_num *= 2; 2099 erealloc(fmt_list, NODE **, fmt_num * sizeof(*fmt_list), "fmt_index"); 2100 } 2101 fmt_list[fmt_hiwater] = dupnode(n); 2102 return fmt_hiwater++; 2103} 2104 2105/* set_OFMT --- track OFMT correctly */ 2106 2107void 2108set_OFMT() 2109{ 2110 OFMTidx = fmt_index(OFMT_node->var_value); 2111 OFMT = fmt_list[OFMTidx]->stptr; 2112} 2113 2114/* set_CONVFMT --- track CONVFMT correctly */ 2115 2116void 2117set_CONVFMT() 2118{ 2119 CONVFMTidx = fmt_index(CONVFMT_node->var_value); 2120 CONVFMT = fmt_list[CONVFMTidx]->stptr; 2121} 2122 2123/* set_LINT --- update LINT as appropriate */ 2124 2125void 2126set_LINT() 2127{ 2128#ifndef NO_LINT 2129 int old_lint = do_lint; 2130 2131 if ((LINT_node->var_value->flags & (STRING|STRCUR)) != 0) { 2132 if ((LINT_node->var_value->flags & MAYBE_NUM) == 0) { 2133 const char *lintval; 2134 size_t lintlen; 2135 2136 do_lint = (force_string(LINT_node->var_value)->stlen > 0); 2137 lintval = LINT_node->var_value->stptr; 2138 lintlen = LINT_node->var_value->stlen; 2139 if (do_lint) { 2140 do_lint = LINT_ALL; 2141 if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0) 2142 lintfunc = r_fatal; 2143 else if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0) 2144 do_lint = LINT_INVALID; 2145 else 2146 lintfunc = warning; 2147 } else 2148 lintfunc = warning; 2149 } else { 2150 if (force_number(LINT_node->var_value) != 0.0) 2151 do_lint = LINT_ALL; 2152 else 2153 do_lint = FALSE; 2154 lintfunc = warning; 2155 } 2156 } else if ((LINT_node->var_value->flags & (NUMCUR|NUMBER)) != 0) { 2157 if (force_number(LINT_node->var_value) != 0.0) 2158 do_lint = LINT_ALL; 2159 else 2160 do_lint = FALSE; 2161 lintfunc = warning; 2162 } else 2163 do_lint = FALSE; /* shouldn't happen */ 2164 2165 if (! do_lint) 2166 lintfunc = warning; 2167 2168 /* explicitly use warning() here, in case lintfunc == r_fatal */ 2169 if (old_lint != do_lint && old_lint && do_lint == FALSE) 2170 warning(_("turning off `--lint' due to assignment to `LINT'")); 2171#endif /* ! NO_LINT */ 2172} 2173 2174/* set_TEXTDOMAIN --- update TEXTDOMAIN variable when TEXTDOMAIN assigned to */ 2175 2176void 2177set_TEXTDOMAIN() 2178{ 2179 int len; 2180 2181 TEXTDOMAIN = force_string(TEXTDOMAIN_node->var_value)->stptr; 2182 len = TEXTDOMAIN_node->var_value->stlen; 2183 TEXTDOMAIN[len] = '\0'; 2184 /* 2185 * Note: don't call textdomain(); this value is for 2186 * the awk program, not for gawk itself. 2187 */ 2188} 2189 2190/* 2191 * assign_val --- do mechanics of assignment, for calling from multiple 2192 * places. 2193 */ 2194 2195NODE * 2196assign_val(NODE **lhs_p, NODE *rhs) 2197{ 2198 if (rhs != *lhs_p) { 2199 /* 2200 * Since we know that the nodes are different, 2201 * we can do the unref() before the dupnode(). 2202 */ 2203 unref(*lhs_p); 2204 *lhs_p = dupnode(rhs); 2205 } 2206 return *lhs_p; 2207} 2208 2209/* update_ERRNO --- update the value of ERRNO */ 2210 2211void 2212update_ERRNO() 2213{ 2214 char *cp; 2215 2216 cp = strerror(errno); 2217 cp = gettext(cp); 2218 unref(ERRNO_node->var_value); 2219 ERRNO_node->var_value = make_string(cp, strlen(cp)); 2220} 2221 2222/* comp_func --- array index comparison function for qsort */ 2223 2224static int 2225comp_func(const void *p1, const void *p2) 2226{ 2227 size_t len1, len2; 2228 const char *str1, *str2; 2229 const NODE *t1, *t2; 2230 int cmp1; 2231 2232 t1 = *((const NODE *const *) p1); 2233 t2 = *((const NODE *const *) p2); 2234 2235/* 2236 t1 = force_string(t1); 2237 t2 = force_string(t2); 2238*/ 2239 len1 = t1->ahname_len; 2240 str1 = t1->ahname_str; 2241 2242 len2 = t2->ahname_len; 2243 str2 = t2->ahname_str; 2244 2245 /* Array indexes are strings, compare as such, always! */ 2246 cmp1 = memcmp(str1, str2, len1 < len2 ? len1 : len2); 2247 /* if prefixes are equal, size matters */ 2248 return (cmp1 != 0 ? cmp1 : 2249 len1 < len2 ? -1 : (len1 > len2)); 2250} 2251