00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "awk.h"
00027
00028 extern double pow P((double x, double y));
00029 extern double modf P((double x, double *yp));
00030 extern double fmod P((double x, double y));
00031
00032 static int eval_condition P((NODE *tree));
00033 static NODE *op_assign P((NODE *tree));
00034 static NODE *func_call P((NODE *tree));
00035 static NODE *match_op P((NODE *tree));
00036 static void pop_forloop P((void));
00037 static inline void pop_all_forloops P((void));
00038 static void push_forloop P((const char *varname, NODE **elems, size_t nelems));
00039 static void push_args P((int count, NODE *arglist, NODE **oldstack,
00040 const char *func_name, char **varnames));
00041 static inline void pop_fcall_stack P((void));
00042 static void pop_fcall P((void));
00043 static int comp_func P((const void *p1, const void *p2));
00044
00045 #if __GNUC__ < 2
00046 NODE *_t;
00047 #endif
00048 #ifdef MSDOS
00049 double _msc51bug;
00050 #endif
00051 NODE *ret_node;
00052 int OFSlen;
00053 int ORSlen;
00054 int OFMTidx;
00055 int CONVFMTidx;
00056
00057
00058 #ifdef PROFILING
00059 #define INCREMENT(n) n++
00060 #else
00061 #define INCREMENT(n)
00062 #endif
00063
00064
00065
00066
00067
00068
00069 #define PUSH_BINDING(stack, x, val) (memcpy((char *)(stack), (const char *)(x), sizeof(jmp_buf)), val++)
00070 #define RESTORE_BINDING(stack, x, val) (memcpy((char *)(x), (const char *)(stack), sizeof(jmp_buf)), val--)
00071
00072 static jmp_buf loop_tag;
00073 static int loop_tag_valid = FALSE;
00074 static int func_tag_valid = FALSE;
00075 static jmp_buf func_tag;
00076 extern int exiting, exit_val;
00077
00078
00079 #ifdef C
00080 #undef C
00081 #endif
00082 #define C(c) ((char)c)
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #if 'a' == 97
00095 const char casetable[] = {
00096 '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
00097 '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
00098 '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
00099 '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
00100
00101 '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
00102
00103 '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
00104
00105 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
00106
00107 '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
00108
00109 '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
00110
00111 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
00112
00113 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
00114
00115 '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
00116
00117 '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
00118
00119 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
00120
00121 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
00122
00123 '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
00124
00125
00126 C('\200'), C('\201'), C('\202'), C('\203'), C('\204'), C('\205'), C('\206'), C('\207'),
00127 C('\210'), C('\211'), C('\212'), C('\213'), C('\214'), C('\215'), C('\216'), C('\217'),
00128 C('\220'), C('\221'), C('\222'), C('\223'), C('\224'), C('\225'), C('\226'), C('\227'),
00129 C('\230'), C('\231'), C('\232'), C('\233'), C('\234'), C('\235'), C('\236'), C('\237'),
00130 C('\240'), C('\241'), C('\242'), C('\243'), C('\244'), C('\245'), C('\246'), C('\247'),
00131 C('\250'), C('\251'), C('\252'), C('\253'), C('\254'), C('\255'), C('\256'), C('\257'),
00132 C('\260'), C('\261'), C('\262'), C('\263'), C('\264'), C('\265'), C('\266'), C('\267'),
00133 C('\270'), C('\271'), C('\272'), C('\273'), C('\274'), C('\275'), C('\276'), C('\277'),
00134 C('\340'), C('\341'), C('\342'), C('\343'), C('\344'), C('\345'), C('\346'), C('\347'),
00135 C('\350'), C('\351'), C('\352'), C('\353'), C('\354'), C('\355'), C('\356'), C('\357'),
00136 C('\360'), C('\361'), C('\362'), C('\363'), C('\364'), C('\365'), C('\366'), C('\327'),
00137 C('\370'), C('\371'), C('\372'), C('\373'), C('\374'), C('\375'), C('\376'), C('\337'),
00138 C('\340'), C('\341'), C('\342'), C('\343'), C('\344'), C('\345'), C('\346'), C('\347'),
00139 C('\350'), C('\351'), C('\352'), C('\353'), C('\354'), C('\355'), C('\356'), C('\357'),
00140 C('\360'), C('\361'), C('\362'), C('\363'), C('\364'), C('\365'), C('\366'), C('\367'),
00141 C('\370'), C('\371'), C('\372'), C('\373'), C('\374'), C('\375'), C('\376'), C('\377'),
00142 };
00143 #else
00144 #include "You lose. You will need a translation table for your character set."
00145 #endif
00146
00147 #undef C
00148
00149
00150
00151
00152
00153 static const char *const nodetypes[] = {
00154 "Node_illegal",
00155 "Node_times",
00156 "Node_quotient",
00157 "Node_mod",
00158 "Node_plus",
00159 "Node_minus",
00160 "Node_cond_pair",
00161 "Node_subscript",
00162 "Node_concat",
00163 "Node_exp",
00164 "Node_preincrement",
00165 "Node_predecrement",
00166 "Node_postincrement",
00167 "Node_postdecrement",
00168 "Node_unary_minus",
00169 "Node_field_spec",
00170 "Node_assign",
00171 "Node_assign_times",
00172 "Node_assign_quotient",
00173 "Node_assign_mod",
00174 "Node_assign_plus",
00175 "Node_assign_minus",
00176 "Node_assign_exp",
00177 "Node_and",
00178 "Node_or",
00179 "Node_equal",
00180 "Node_notequal",
00181 "Node_less",
00182 "Node_greater",
00183 "Node_leq",
00184 "Node_geq",
00185 "Node_match",
00186 "Node_nomatch",
00187 "Node_not",
00188 "Node_rule_list",
00189 "Node_rule_node",
00190 "Node_statement_list",
00191 "Node_switch_body",
00192 "Node_case_list",
00193 "Node_if_branches",
00194 "Node_expression_list",
00195 "Node_param_list",
00196 "Node_K_if",
00197 "Node_K_switch",
00198 "Node_K_case",
00199 "Node_K_default",
00200 "Node_K_while",
00201 "Node_K_for",
00202 "Node_K_arrayfor",
00203 "Node_K_break",
00204 "Node_K_continue",
00205 "Node_K_print",
00206 "Node_K_print_rec",
00207 "Node_K_printf",
00208 "Node_K_next",
00209 "Node_K_exit",
00210 "Node_K_do",
00211 "Node_K_return",
00212 "Node_K_delete",
00213 "Node_K_delete_loop",
00214 "Node_K_getline",
00215 "Node_K_function",
00216 "Node_K_nextfile",
00217 "Node_redirect_output",
00218 "Node_redirect_append",
00219 "Node_redirect_pipe",
00220 "Node_redirect_pipein",
00221 "Node_redirect_input",
00222 "Node_redirect_twoway",
00223 "Node_var_new",
00224 "Node_var",
00225 "Node_var_array",
00226 "Node_val",
00227 "Node_builtin",
00228 "Node_line_range",
00229 "Node_in_array",
00230 "Node_func",
00231 "Node_func_call",
00232 "Node_cond_exp",
00233 "Node_regex",
00234 "Node_dynregex",
00235 "Node_hashnode",
00236 "Node_ahash",
00237 "Node_array_ref",
00238 "Node_BINMODE",
00239 "Node_CONVFMT",
00240 "Node_FIELDWIDTHS",
00241 "Node_FNR",
00242 "Node_FS",
00243 "Node_IGNORECASE",
00244 "Node_LINT",
00245 "Node_NF",
00246 "Node_NR",
00247 "Node_OFMT",
00248 "Node_OFS",
00249 "Node_ORS",
00250 "Node_RS",
00251 "Node_TEXTDOMAIN",
00252 "Node_final --- this should never appear",
00253 NULL
00254 };
00255
00256
00257
00258 const char *
00259 nodetype2str(NODETYPE type)
00260 {
00261 static char buf[40];
00262
00263 if (type >= Node_illegal && type <= Node_final)
00264 return nodetypes[(int) type];
00265
00266 sprintf(buf, _("unknown nodetype %d"), (int) type);
00267 return buf;
00268 }
00269
00270
00271
00272 const char *
00273 flags2str(int flagval)
00274 {
00275 static const struct flagtab values[] = {
00276 { MALLOC, "MALLOC" },
00277 { TEMP, "TEMP" },
00278 { PERM, "PERM" },
00279 { STRING, "STRING" },
00280 { STRCUR, "STRCUR" },
00281 { NUMCUR, "NUMCUR" },
00282 { NUMBER, "NUMBER" },
00283 { MAYBE_NUM, "MAYBE_NUM" },
00284 { ARRAYMAXED, "ARRAYMAXED" },
00285 { FUNC, "FUNC" },
00286 { FIELD, "FIELD" },
00287 { INTLSTR, "INTLSTR" },
00288 { 0, NULL },
00289 };
00290
00291 return genflags2str(flagval, values);
00292 }
00293
00294
00295
00296 const char *
00297 genflags2str(int flagval, const struct flagtab *tab)
00298 {
00299 static char buffer[BUFSIZ];
00300 char *sp;
00301 int i, space_left, space_needed;
00302
00303 sp = buffer;
00304 space_left = BUFSIZ;
00305 for (i = 0; tab[i].name != NULL; i++) {
00306
00307
00308
00309
00310 space_needed = (strlen(tab[i].name) + (sp != buffer));
00311 if (space_left < space_needed)
00312 fatal(_("buffer overflow in genflags2str"));
00313
00314 if ((flagval & tab[i].val) != 0) {
00315 if (sp != buffer) {
00316 *sp++ = '|';
00317 space_left--;
00318 }
00319 strcpy(sp, tab[i].name);
00320
00321 space_left -= strlen(sp);
00322 sp += strlen(sp);
00323 }
00324 }
00325
00326 return buffer;
00327 }
00328
00329
00330
00331
00332
00333
00334 int
00335 interpret(register NODE *volatile tree)
00336 {
00337 jmp_buf volatile loop_tag_stack;
00338 static jmp_buf rule_tag;
00339
00340
00341 register NODE *volatile t = NULL;
00342 NODE **volatile lhs;
00343 NODE *volatile stable_tree;
00344 int volatile traverse = TRUE;
00345
00346
00347 source = NULL;
00348 sourceline = 0;
00349
00350 if (tree == NULL)
00351 return 1;
00352 sourceline = tree->source_line;
00353 source = tree->source_file;
00354 switch (tree->type) {
00355 case Node_rule_node:
00356 traverse = FALSE;
00357
00358 case Node_rule_list:
00359 for (t = tree; t != NULL; t = t->rnode) {
00360 if (traverse)
00361 tree = t->lnode;
00362 sourceline = tree->source_line;
00363 source = tree->source_file;
00364 INCREMENT(tree->exec_count);
00365 switch (setjmp(rule_tag)) {
00366 case 0:
00367
00368 if (tree->lnode == NULL ||
00369 eval_condition(tree->lnode)) {
00370
00371 if (tree->lnode != NULL)
00372 INCREMENT(tree->lnode->exec_count);
00373 (void) interpret(tree->rnode);
00374 }
00375 break;
00376 case TAG_CONTINUE:
00377 pop_all_forloops();
00378 pop_fcall_stack();
00379 return 1;
00380 case TAG_BREAK:
00381 pop_all_forloops();
00382 pop_fcall_stack();
00383 return 0;
00384 default:
00385 cant_happen();
00386 }
00387 if (! traverse)
00388 break;
00389 }
00390 break;
00391
00392 case Node_statement_list:
00393 for (t = tree; t != NULL; t = t->rnode)
00394 (void) interpret(t->lnode);
00395 break;
00396
00397 case Node_K_if:
00398 INCREMENT(tree->exec_count);
00399 if (eval_condition(tree->lnode)) {
00400 INCREMENT(tree->rnode->exec_count);
00401 (void) interpret(tree->rnode->lnode);
00402 } else {
00403 (void) interpret(tree->rnode->rnode);
00404 }
00405 break;
00406
00407 case Node_K_switch:
00408 {
00409 NODE *switch_value;
00410 NODE *switch_body;
00411 NODE *case_list;
00412 NODE *default_list;
00413 NODE *case_stmt;
00414
00415 int match_found = FALSE;
00416
00417 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00418 INCREMENT(tree->exec_count);
00419 stable_tree = tree;
00420
00421 switch_value = tree_eval(stable_tree->lnode);
00422 switch_body = stable_tree->rnode;
00423 case_list = switch_body->lnode;
00424 default_list = switch_body->rnode;
00425
00426 for (; case_list != NULL; case_list = case_list->rnode) {
00427 case_stmt = case_list->lnode;
00428
00429
00430
00431
00432
00433 if (! match_found) {
00434 if (case_stmt->type == Node_K_default)
00435 ;
00436 else if (case_stmt->lnode->type == Node_regex) {
00437 NODE *t1;
00438 Regexp *rp;
00439
00440 t1 = force_string(switch_value);
00441 rp = re_update(case_stmt->lnode);
00442
00443 match_found = (research(rp, t1->stptr, 0, t1->stlen, FALSE) >= 0);
00444 if (t1 != switch_value)
00445 free_temp(t1);
00446 } else {
00447 match_found = (cmp_nodes(switch_value, case_stmt->lnode) == 0);
00448 }
00449 }
00450
00451
00452 if (match_found) {
00453 INCREMENT(case_stmt->exec_count);
00454 switch (setjmp(loop_tag)) {
00455 case 0:
00456 (void) interpret(case_stmt->rnode);
00457 break;
00458 case TAG_CONTINUE:
00459 free_temp(switch_value);
00460 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00461 longjmp(loop_tag, TAG_CONTINUE);
00462 break;
00463 case TAG_BREAK:
00464 free_temp(switch_value);
00465 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00466 return 1;
00467 default:
00468 cant_happen();
00469 }
00470 }
00471
00472 }
00473
00474 free_temp(switch_value);
00475
00476
00477
00478
00479
00480 if (! match_found && default_list != NULL) {
00481 for (case_list = default_list;
00482 case_list != NULL; case_list = case_list->rnode) {
00483 case_stmt = case_list->lnode;
00484
00485 INCREMENT(case_stmt->exec_count);
00486 switch (setjmp(loop_tag)) {
00487 case 0:
00488 (void) interpret(case_stmt->rnode);
00489 break;
00490 case TAG_CONTINUE:
00491 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00492 longjmp(loop_tag, TAG_CONTINUE);
00493 break;
00494 case TAG_BREAK:
00495 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00496 return 1;
00497 default:
00498 cant_happen();
00499 }
00500 }
00501 }
00502
00503 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00504 }
00505 break;
00506
00507 case Node_K_while:
00508 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00509
00510 stable_tree = tree;
00511 while (eval_condition(stable_tree->lnode)) {
00512 INCREMENT(stable_tree->exec_count);
00513 switch (setjmp(loop_tag)) {
00514 case 0:
00515 (void) interpret(stable_tree->rnode);
00516 break;
00517 case TAG_CONTINUE:
00518 break;
00519 case TAG_BREAK:
00520 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00521 return 1;
00522 default:
00523 cant_happen();
00524 }
00525 }
00526 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00527 break;
00528
00529 case Node_K_do:
00530 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00531 stable_tree = tree;
00532 do {
00533 INCREMENT(stable_tree->exec_count);
00534 switch (setjmp(loop_tag)) {
00535 case 0:
00536 (void) interpret(stable_tree->rnode);
00537 break;
00538 case TAG_CONTINUE:
00539 break;
00540 case TAG_BREAK:
00541 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00542 return 1;
00543 default:
00544 cant_happen();
00545 }
00546 } while (eval_condition(stable_tree->lnode));
00547 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00548 break;
00549
00550 case Node_K_for:
00551 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00552 (void) interpret(tree->forloop->init);
00553 stable_tree = tree;
00554 while (eval_condition(stable_tree->forloop->cond)) {
00555 INCREMENT(stable_tree->exec_count);
00556 switch (setjmp(loop_tag)) {
00557 case 0:
00558 (void) interpret(stable_tree->lnode);
00559
00560 case TAG_CONTINUE:
00561 (void) interpret(stable_tree->forloop->incr);
00562 break;
00563 case TAG_BREAK:
00564 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00565 return 1;
00566 default:
00567 cant_happen();
00568 }
00569 }
00570 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00571 break;
00572
00573 case Node_K_arrayfor:
00574 {
00575 Func_ptr after_assign = NULL;
00576 NODE **list = NULL;
00577 NODE *volatile array;
00578 NODE *volatile save_array;
00579 volatile size_t i, num_elems;
00580 size_t j;
00581 volatile int retval = 0;
00582 int sort_indices = whiny_users;
00583
00584 #define hakvar forloop->init
00585 #define arrvar forloop->incr
00586
00587 save_array = tree->arrvar;
00588 array = get_array(save_array);
00589
00590
00591 if (array->var_array == NULL || array->table_size == 0)
00592 break;
00593
00594
00595 num_elems = array->table_size;
00596 emalloc(list, NODE **, num_elems * sizeof(NODE *), "for_loop");
00597
00598
00599 for (i = j = 0; i < array->array_size; i++) {
00600 NODE *t = array->var_array[i];
00601
00602 if (t == NULL)
00603 continue;
00604
00605 for (; t != NULL; t = t->ahnext) {
00606 list[j++] = dupnode(t);
00607 assert(list[j-1] == t);
00608 }
00609 }
00610
00611
00612 if (sort_indices)
00613 qsort(list, num_elems, sizeof(NODE *), comp_func);
00614
00615
00616 push_forloop(array->vname, list, num_elems);
00617 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00618
00619 lhs = get_lhs(tree->hakvar, &after_assign, FALSE);
00620 stable_tree = tree;
00621 for (i = 0; i < num_elems; i++) {
00622 INCREMENT(stable_tree->exec_count);
00623 unref(*((NODE **) lhs));
00624 *lhs = make_string(list[i]->ahname_str, list[i]->ahname_len);
00625 if (after_assign)
00626 (*after_assign)();
00627 switch (setjmp(loop_tag)) {
00628 case 0:
00629 (void) interpret(stable_tree->lnode);
00630 case TAG_CONTINUE:
00631 break;
00632
00633 case TAG_BREAK:
00634 retval = 1;
00635 goto done;
00636
00637 default:
00638 cant_happen();
00639 }
00640 }
00641
00642 done:
00643 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
00644 pop_forloop();
00645
00646 if (do_lint && num_elems != array->table_size)
00647 lintwarn(_("for loop: array `%s' changed size from %ld to %ld during loop execution"),
00648 array_vname(save_array), (long) num_elems, (long) array->table_size);
00649
00650 if (retval == 1)
00651 return 1;
00652 break;
00653 }
00654 #undef hakvar
00655 #undef arrvar
00656
00657 case Node_K_break:
00658 INCREMENT(tree->exec_count);
00659 if (! loop_tag_valid) {
00660
00661
00662
00663
00664
00665 static int warned = FALSE;
00666
00667 if (do_lint && ! warned) {
00668 lintwarn(_("`break' outside a loop is not portable"));
00669 warned = TRUE;
00670 }
00671 if (! do_traditional || do_posix)
00672 fatal(_("`break' outside a loop is not allowed"));
00673 longjmp(rule_tag, TAG_CONTINUE);
00674 } else
00675 longjmp(loop_tag, TAG_BREAK);
00676 break;
00677
00678 case Node_K_continue:
00679 INCREMENT(tree->exec_count);
00680 if (! loop_tag_valid) {
00681
00682
00683
00684
00685
00686 static int warned = FALSE;
00687
00688 if (do_lint && ! warned) {
00689 lintwarn(_("`continue' outside a loop is not portable"));
00690 warned = TRUE;
00691 }
00692 if (! do_traditional || do_posix)
00693 fatal(_("`continue' outside a loop is not allowed"));
00694 longjmp(rule_tag, TAG_CONTINUE);
00695 } else
00696 longjmp(loop_tag, TAG_CONTINUE);
00697 break;
00698
00699 case Node_K_print:
00700 INCREMENT(tree->exec_count);
00701 do_print(tree);
00702 break;
00703
00704 case Node_K_print_rec:
00705 INCREMENT(tree->exec_count);
00706 do_print_rec(tree);
00707 break;
00708
00709 case Node_K_printf:
00710 INCREMENT(tree->exec_count);
00711 do_printf(tree);
00712 break;
00713
00714 case Node_K_delete:
00715 INCREMENT(tree->exec_count);
00716 do_delete(tree->lnode, tree->rnode);
00717 break;
00718
00719 case Node_K_delete_loop:
00720 INCREMENT(tree->exec_count);
00721 do_delete_loop(tree->lnode, tree->rnode);
00722 break;
00723
00724 case Node_K_next:
00725 INCREMENT(tree->exec_count);
00726 if (in_begin_rule)
00727 fatal(_("`next' cannot be called from a BEGIN rule"));
00728 else if (in_end_rule)
00729 fatal(_("`next' cannot be called from an END rule"));
00730
00731
00732 longjmp(rule_tag, TAG_CONTINUE);
00733 break;
00734
00735 case Node_K_nextfile:
00736 INCREMENT(tree->exec_count);
00737 if (in_begin_rule)
00738 fatal(_("`nextfile' cannot be called from a BEGIN rule"));
00739 else if (in_end_rule)
00740 fatal(_("`nextfile' cannot be called from an END rule"));
00741
00742
00743
00744
00745
00746
00747 pop_all_forloops();
00748 pop_fcall_stack();
00749
00750 do_nextfile();
00751 break;
00752
00753 case Node_K_exit:
00754 INCREMENT(tree->exec_count);
00755
00756
00757
00758
00759
00760
00761
00762 exiting = TRUE;
00763 if (tree->lnode != NULL) {
00764 t = tree_eval(tree->lnode);
00765 exit_val = (int) force_number(t);
00766 free_temp(t);
00767 }
00768 longjmp(rule_tag, TAG_BREAK);
00769 break;
00770
00771 case Node_K_return:
00772 INCREMENT(tree->exec_count);
00773 t = tree_eval(tree->lnode);
00774 ret_node = dupnode(t);
00775 free_temp(t);
00776 longjmp(func_tag, TAG_RETURN);
00777 break;
00778
00779 default:
00780
00781
00782
00783
00784 if (do_lint && (tree->type == Node_var || tree->type == Node_var_new))
00785 lintwarn(_("statement has no effect"));
00786 INCREMENT(tree->exec_count);
00787 t = tree_eval(tree);
00788 if (t)
00789 free_temp(t);
00790 break;
00791 }
00792 return 1;
00793 }
00794
00795
00796
00797 NODE *
00798 r_tree_eval(register NODE *tree, int iscond)
00799 {
00800 register NODE *r, *t1, *t2;
00801 register NODE **lhs;
00802 register int di;
00803 AWKNUM x, x1, x2;
00804 long lx;
00805 #ifdef _CRAY
00806 long lx2;
00807 #endif
00808
00809 #ifndef TREE_EVAL_MACRO
00810 if (tree == NULL)
00811 return Nnull_string;
00812 else if (tree->type == Node_val) {
00813 if (tree->stref <= 0)
00814 cant_happen();
00815 return ((tree->flags & INTLSTR) != 0
00816 ? r_force_string(tree)
00817 : tree);
00818 } else if (tree->type == Node_var) {
00819 if (tree->var_value->stref <= 0)
00820 cant_happen();
00821 if (! var_uninitialized(tree))
00822 return tree->var_value;
00823 }
00824 #endif
00825
00826 if (tree->type == Node_param_list) {
00827 if ((tree->flags & FUNC) != 0)
00828 fatal(_("can't use function name `%s' as variable or array"),
00829 tree->vname);
00830
00831 tree = stack_ptr[tree->param_cnt];
00832
00833 if (tree == NULL) {
00834 if (do_lint)
00835 lintwarn(_("reference to uninitialized argument `%s'"),
00836 tree->vname);
00837 return Nnull_string;
00838 }
00839
00840 if (do_lint && var_uninitialized(tree))
00841 lintwarn(_("reference to uninitialized argument `%s'"),
00842 tree->vname);
00843 }
00844
00845 switch (tree->type) {
00846 case Node_array_ref:
00847 if (tree->orig_array->type == Node_var_array)
00848 fatal(_("attempt to use array `%s' in a scalar context"),
00849 array_vname(tree));
00850 tree->orig_array->type = Node_var;
00851
00852 case Node_var_new:
00853 tree->type = Node_var;
00854 tree->var_value = Nnull_string;
00855
00856 case Node_var:
00857 if (do_lint && var_uninitialized(tree))
00858 lintwarn(_("reference to uninitialized variable `%s'"),
00859 tree->vname);
00860 return tree->var_value;
00861
00862 case Node_and:
00863 return tmp_number((AWKNUM) (eval_condition(tree->lnode)
00864 && eval_condition(tree->rnode)));
00865
00866 case Node_or:
00867 return tmp_number((AWKNUM) (eval_condition(tree->lnode)
00868 || eval_condition(tree->rnode)));
00869
00870 case Node_not:
00871 return tmp_number((AWKNUM) ! eval_condition(tree->lnode));
00872
00873
00874 case Node_builtin:
00875 return (*tree->builtin)(tree->subnode);
00876
00877 case Node_K_getline:
00878 return (do_getline(tree));
00879
00880 case Node_in_array:
00881 return tmp_number((AWKNUM) (in_array(tree->lnode, tree->rnode) != NULL));
00882
00883 case Node_func_call:
00884 return func_call(tree);
00885
00886
00887 case Node_NR:
00888 case Node_FNR:
00889 case Node_NF:
00890 case Node_FIELDWIDTHS:
00891 case Node_FS:
00892 case Node_RS:
00893 case Node_field_spec:
00894 case Node_subscript:
00895 case Node_IGNORECASE:
00896 case Node_OFS:
00897 case Node_ORS:
00898 case Node_OFMT:
00899 case Node_CONVFMT:
00900 case Node_BINMODE:
00901 case Node_LINT:
00902 case Node_TEXTDOMAIN:
00903 lhs = get_lhs(tree, (Func_ptr *) NULL, TRUE);
00904 return *lhs;
00905
00906 case Node_var_array:
00907 fatal(_("attempt to use array `%s' in a scalar context"),
00908 array_vname(tree));
00909
00910 case Node_unary_minus:
00911 t1 = tree_eval(tree->subnode);
00912 x = -force_number(t1);
00913 free_temp(t1);
00914 return tmp_number(x);
00915
00916 case Node_cond_exp:
00917 if (eval_condition(tree->lnode))
00918 return tree_eval(tree->rnode->lnode);
00919 return tree_eval(tree->rnode->rnode);
00920
00921 case Node_match:
00922 case Node_nomatch:
00923 case Node_regex:
00924 case Node_dynregex:
00925 return match_op(tree);
00926
00927 case Node_concat:
00928 {
00929 NODE **treelist;
00930 NODE **strlist;
00931 NODE *save_tree;
00932 register NODE **treep;
00933 register NODE **strp;
00934 register size_t len;
00935 register size_t supposed_len;
00936 char *str;
00937 register char *dest;
00938 int alloc_count, str_count;
00939 int i;
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 save_tree = tree;
00958 for (alloc_count = 2; tree != NULL && tree->type == Node_concat;
00959 tree = tree->lnode)
00960 alloc_count++;
00961 tree = save_tree;
00962 emalloc(treelist, NODE **, sizeof(NODE *) * alloc_count, "tree_eval");
00963 emalloc(strlist, NODE **, sizeof(NODE *) * alloc_count, "tree_eval");
00964
00965
00966 treep = treelist;
00967 while (tree != NULL && tree->type == Node_concat) {
00968 *treep++ = tree->rnode;
00969 tree = tree->lnode;
00970 }
00971 *treep = tree;
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 strp = strlist;
00987 supposed_len = len = 0;
00988 while (treep >= treelist) {
00989 NODE *n;
00990
00991
00992 n = force_string(tree_eval(*treep--));
00993 *strp = dupnode(n);
00994 free_temp(n);
00995 supposed_len += (*strp)->stlen;
00996 strp++;
00997 }
00998 *strp = NULL;
00999
01000 str_count = strp - strlist;
01001 strp = strlist;
01002 for (i = 0; i < str_count; i++) {
01003 len += (*strp)->stlen;
01004 strp++;
01005 }
01006 if (do_lint && supposed_len != len)
01007 lintwarn(_("concatenation: side effects in one expression have changed the length of another!"));
01008 emalloc(str, char *, len+2, "tree_eval");
01009 str[len] = str[len+1] = '\0';
01010 dest = str;
01011 strp = strlist;
01012 while (*strp != NULL) {
01013 memcpy(dest, (*strp)->stptr, (*strp)->stlen);
01014 dest += (*strp)->stlen;
01015 unref(*strp);
01016 strp++;
01017 }
01018 r = make_str_node(str, len, ALREADY_MALLOCED);
01019 r->flags |= TEMP;
01020
01021 free(strlist);
01022 free(treelist);
01023 }
01024 return r;
01025
01026
01027 case Node_assign:
01028 {
01029 Func_ptr after_assign = NULL;
01030
01031 if (do_lint && iscond)
01032 lintwarn(_("assignment used in conditional context"));
01033 r = tree_eval(tree->rnode);
01034 lhs = get_lhs(tree->lnode, &after_assign, FALSE);
01035
01036 assign_val(lhs, r);
01037 if (after_assign)
01038 (*after_assign)();
01039 return *lhs;
01040 }
01041
01042
01043 case Node_preincrement:
01044 case Node_predecrement:
01045 case Node_postincrement:
01046 case Node_postdecrement:
01047 case Node_assign_exp:
01048 case Node_assign_times:
01049 case Node_assign_quotient:
01050 case Node_assign_mod:
01051 case Node_assign_plus:
01052 case Node_assign_minus:
01053 return op_assign(tree);
01054 default:
01055 break;
01056 }
01057
01058
01059
01060
01061
01062
01063 t1 = dupnode(tree_eval(tree->lnode));
01064 t2 = dupnode(tree_eval(tree->rnode));
01065
01066 switch (tree->type) {
01067 case Node_geq:
01068 case Node_leq:
01069 case Node_greater:
01070 case Node_less:
01071 case Node_notequal:
01072 case Node_equal:
01073 di = cmp_nodes(t1, t2);
01074 unref(t1);
01075 unref(t2);
01076 switch (tree->type) {
01077 case Node_equal:
01078 return tmp_number((AWKNUM) (di == 0));
01079 case Node_notequal:
01080 return tmp_number((AWKNUM) (di != 0));
01081 case