#include "awk.h"#include "You lose. You will need a translation table for your character set."Go to the source code of this file.
Classes | |
| struct | loop_info |
| struct | fcall |
Defines | |
| #define | INCREMENT(n) |
| #define | PUSH_BINDING(stack, x, val) (memcpy((char *)(stack), (const char *)(x), sizeof(jmp_buf)), val++) |
| #define | RESTORE_BINDING(stack, x, val) (memcpy((char *)(x), (const char *)(stack), sizeof(jmp_buf)), val--) |
| #define | C(c) ((char)c) |
| #define | hakvar forloop->init |
| #define | arrvar forloop->incr |
| #define | NLOOPS 4 |
Functions | |
| double pow | P ((double x, double y)) |
| const char * | nodetype2str (NODETYPE type) |
| const char * | flags2str (int flagval) |
| const char * | genflags2str (int flagval, const struct flagtab *tab) |
| int | interpret (register NODE *volatile tree) |
| NODE * | r_tree_eval (register NODE *tree, int iscond) |
| static int | eval_condition (register NODE *tree) |
| int | cmp_nodes (register NODE *t1, register NODE *t2) |
| static NODE * | op_assign (register NODE *tree) |
| static void | pop_forloop () |
| static void | pop_all_forloops () |
| static void | push_forloop (const char *varname, NODE **elems, size_t nelems) |
| static void | pop_fcall () |
| static void | pop_fcall_stack () |
| static void | push_args (int count, NODE *argp, NODE **oldstack, const char *func_name, char **varnames) |
| static NODE * | func_call (NODE *tree) |
| NODE ** | r_get_lhs (register NODE *ptr, Func_ptr *assign, int reference) |
| static NODE * | match_op (register NODE *tree) |
| void | set_IGNORECASE () |
| void | set_BINMODE () |
| void | set_OFS () |
| void | set_ORS () |
| static int | fmt_ok (NODE *n) |
| static int | fmt_index (NODE *n) |
| void | set_OFMT () |
| void | set_CONVFMT () |
| void | set_LINT () |
| void | set_TEXTDOMAIN () |
| NODE * | assign_val (NODE **lhs_p, NODE *rhs) |
| void | update_ERRNO () |
| static int | comp_func (const void *p1, const void *p2) |
Variables | |
| NODE * | _t |
| NODE * | ret_node |
| int | OFSlen |
| int | ORSlen |
| int | OFMTidx |
| int | CONVFMTidx |
| static jmp_buf | loop_tag |
| static int | loop_tag_valid = FALSE |
| static int | func_tag_valid = FALSE |
| static jmp_buf | func_tag |
| int | exiting |
| int | exit_val |
| static const char *const | nodetypes [] |
| static struct loop_info * | loop_stack |
| size_t | nloops_active = 0 |
| static struct fcall * | fcall_list |
| static long | fcall_list_size = 0 |
| static long | curfcall = -1 |
| NODE ** | stack_ptr |
| NODE ** | fmt_list = NULL |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Referenced by push_forloop(). |
|
|
Definition at line 69 of file eval.c. Referenced by func_call(), and interpret(). |
|
|
Definition at line 70 of file eval.c. Referenced by func_call(), and interpret(). |
|
||||||||||||
|
Definition at line 2196 of file eval.c. References dupnode, and unref(). Referenced by r_tree_eval(), and update_PROCINFO(). 02197 { 02198 if (rhs != *lhs_p) { 02199 /* 02200 * Since we know that the nodes are different, 02201 * we can do the unref() before the dupnode(). 02202 */ 02203 unref(*lhs_p); 02204 *lhs_p = dupnode(rhs); 02205 } 02206 return *lhs_p; 02207 }
|
|
||||||||||||
|
Definition at line 1212 of file eval.c. References force_number, force_string, IGNORECASE, MAYBE_NUM, memcmp(), memset(), and NUMBER. Referenced by fmt_index(), interpret(), merge(), r_tree_eval(), and re_update(). 01213 { 01214 register int ret; 01215 register size_t len1, len2; 01216 register int l; 01217 int ldiff; 01218 01219 if (t1 == t2) 01220 return 0; 01221 if (t1->flags & MAYBE_NUM) 01222 (void) force_number(t1); 01223 if (t2->flags & MAYBE_NUM) 01224 (void) force_number(t2); 01225 if ((t1->flags & NUMBER) && (t2->flags & NUMBER)) { 01226 if (t1->numbr == t2->numbr) 01227 return 0; 01228 /* don't subtract, in case one or both are infinite */ 01229 else if (t1->numbr < t2->numbr) 01230 return -1; 01231 else 01232 return 1; 01233 } 01234 (void) force_string(t1); 01235 (void) force_string(t2); 01236 len1 = t1->stlen; 01237 len2 = t2->stlen; 01238 ldiff = len1 - len2; 01239 if (len1 == 0 || len2 == 0) 01240 return ldiff; 01241 l = (ldiff <= 0 ? len1 : len2); 01242 if (IGNORECASE) { 01243 const unsigned char *cp1 = (const unsigned char *) t1->stptr; 01244 const unsigned char *cp2 = (const unsigned char *) t2->stptr; 01245 01246 #ifdef MBS_SUPPORT 01247 if (gawk_mb_cur_max > 1) { 01248 mbstate_t mbs; 01249 memset(&mbs, 0, sizeof(mbstate_t)); 01250 ret = strncasecmpmbs((const char *) cp1, mbs, 01251 (const char *) cp2, mbs, l); 01252 } else 01253 #endif 01254 for (ret = 0; l-- > 0 && ret == 0; cp1++, cp2++) 01255 ret = casetable[*cp1] - casetable[*cp2]; 01256 } else 01257 ret = memcmp(t1->stptr, t2->stptr, l); 01258 return (ret == 0 ? ldiff : ret); 01259 }
|
|
||||||||||||
|
Definition at line 2225 of file eval.c. References memcmp(). Referenced by interpret(). 02226 { 02227 size_t len1, len2; 02228 const char *str1, *str2; 02229 const NODE *t1, *t2; 02230 int cmp1; 02231 02232 t1 = *((const NODE *const *) p1); 02233 t2 = *((const NODE *const *) p2); 02234 02235 /* 02236 t1 = force_string(t1); 02237 t2 = force_string(t2); 02238 */ 02239 len1 = t1->ahname_len; 02240 str1 = t1->ahname_str; 02241 02242 len2 = t2->ahname_len; 02243 str2 = t2->ahname_str; 02244 02245 /* Array indexes are strings, compare as such, always! */ 02246 cmp1 = memcmp(str1, str2, len1 < len2 ? len1 : len2); 02247 /* if prefixes are equal, size matters */ 02248 return (cmp1 != 0 ? cmp1 : 02249 len1 < len2 ? -1 : (len1 > len2)); 02250 }
|
|
|
Definition at line 1160 of file eval.c. References FALSE, exp_node::flags, force_number, free_temp, m_tree_eval, MAYBE_NUM, Node_line_range, NULL, NUMBER, and TRUE. Referenced by eval_condition(), interpret(), pprint(), r_tree_eval(), and tree_eval(). 01161 { 01162 register NODE *t1; 01163 register int ret; 01164 01165 if (tree == NULL) /* Null trees are the easiest kinds */ 01166 return TRUE; 01167 if (tree->type == Node_line_range) { 01168 /* 01169 * Node_line_range is kind of like Node_match, EXCEPT: the 01170 * lnode field (more properly, the condpair field) is a node 01171 * of a Node_cond_pair; whether we evaluate the lnode of that 01172 * node or the rnode depends on the triggered word. More 01173 * precisely: if we are not yet triggered, we tree_eval the 01174 * lnode; if that returns true, we set the triggered word. 01175 * If we are triggered (not ELSE IF, note), we tree_eval the 01176 * rnode, clear triggered if it succeeds, and perform our 01177 * action (regardless of success or failure). We want to be 01178 * able to begin and end on a single input record, so this 01179 * isn't an ELSE IF, as noted above. 01180 */ 01181 if (! tree->triggered) { 01182 if (! eval_condition(tree->condpair->lnode)) 01183 return FALSE; 01184 else 01185 tree->triggered = TRUE; 01186 } 01187 /* Else we are triggered */ 01188 if (eval_condition(tree->condpair->rnode)) 01189 tree->triggered = FALSE; 01190 return TRUE; 01191 } 01192 01193 /* 01194 * Could just be J.random expression. in which case, null and 0 are 01195 * false, anything else is true 01196 */ 01197 01198 t1 = m_tree_eval(tree, TRUE); 01199 if (t1->flags & MAYBE_NUM) 01200 (void) force_number(t1); 01201 if (t1->flags & NUMBER) 01202 ret = (t1->numbr != 0.0); 01203 else 01204 ret = (t1->stlen != 0); 01205 free_temp(t1); 01206 return ret; 01207 }
|
|
|
Definition at line 273 of file eval.c. References ARRAYMAXED, FIELD, FUNC, genflags2str(), INTLSTR, MALLOC, MAYBE_NUM, NULL, NUMBER, NUMCUR, PERM, STRCUR, STRING, and TEMP. Referenced by valinfo(). 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 }
|
|
|
Definition at line 2075 of file eval.c. References _, cmp_nodes(), CONVFMT_node, do_lint, dupnode, emalloc, erealloc, fmt_ok(), force_string, lintwarn, NULL, and OFMT_node. Referenced by set_CONVFMT(), and set_OFMT(). 02076 { 02077 register int ix = 0; 02078 static int fmt_num = 4; 02079 static int fmt_hiwater = 0; 02080 02081 if (fmt_list == NULL) 02082 emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), "fmt_index"); 02083 (void) force_string(n); 02084 while (ix < fmt_hiwater) { 02085 if (cmp_nodes(fmt_list[ix], n) == 0) 02086 return ix; 02087 ix++; 02088 } 02089 /* not found */ 02090 n->stptr[n->stlen] = '\0'; 02091 if (do_lint && ! fmt_ok(n)) 02092 lintwarn(_("bad `%sFMT' specification `%s'"), 02093 n == CONVFMT_node->var_value ? "CONV" 02094 : n == OFMT_node->var_value ? "O" 02095 : "", n->stptr); 02096 02097 if (fmt_hiwater >= fmt_num) { 02098 fmt_num *= 2; 02099 erealloc(fmt_list, NODE **, fmt_num * sizeof(*fmt_list), "fmt_index"); 02100 } 02101 fmt_list[fmt_hiwater] = dupnode(n); 02102 return fmt_hiwater++; 02103 }
|
|
|
Definition at line 2048 of file eval.c. References force_string, ISDIGIT, NULL, and strchr(). Referenced by fmt_index(). 02049 { 02050 NODE *tmp = force_string(n); 02051 const char *p = tmp->stptr; 02052 02053 if (*p++ != '%') 02054 return 0; 02055 while (*p && strchr(" +-#", *p) != NULL) /* flags */ 02056 p++; 02057 while (*p && ISDIGIT(*p)) /* width - %*.*g is NOT allowed */ 02058 p++; 02059 if (*p == '\0' || (*p != '.' && ! ISDIGIT(*p))) 02060 return 0; 02061 if (*p == '.') 02062 p++; 02063 while (*p && ISDIGIT(*p)) /* precision */ 02064 p++; 02065 if (*p == '\0' || strchr("efgEG", *p) == NULL) 02066 return 0; 02067 if (*++p != '\0') 02068 return 0; 02069 return 1; 02070 }
|
|
|
Definition at line 1611 of file eval.c. References _, FALSE, fatal, exp_node::flags, INCREMENT, interpret(), lookup(), name, Nnull_string, Node_func, NULL, PERM, pop_fcall(), push_args(), PUSH_BINDING, RESTORE_BINDING, TEMP, and exp_node::type. Referenced by r_tree_eval(). 01612 { 01613 register NODE *r; 01614 NODE *name, *arg_list; 01615 NODE *f; 01616 jmp_buf volatile func_tag_stack; 01617 jmp_buf volatile loop_tag_stack; 01618 int volatile save_loop_tag_valid = FALSE; 01619 NODE *save_ret_node; 01620 extern NODE *ret_node; 01621 01622 /* tree->rnode is a Node_val giving function name */ 01623 /* tree->lnode is Node_expression_list of calling args. */ 01624 name = tree->rnode; 01625 arg_list = tree->lnode; 01626 01627 /* retrieve function definition node */ 01628 if (tree->funcbody != NULL) 01629 f = tree->funcbody; 01630 else { 01631 f = lookup(name->stptr); 01632 if (f == NULL || f->type != Node_func) 01633 fatal(_("function `%s' not defined"), name->stptr); 01634 01635 tree->funcbody = f; /* save for next call */ 01636 } 01637 01638 #ifdef FUNC_TRACE 01639 fprintf(stderr, _("function %s called\n"), name->stptr); 01640 #endif 01641 push_args(f->lnode->param_cnt, arg_list, stack_ptr, name->stptr, 01642 f->parmlist); 01643 01644 /* 01645 * Execute function body, saving context, as a return statement 01646 * will longjmp back here. 01647 * 01648 * Have to save and restore the loop_tag stuff so that a return 01649 * inside a loop in a function body doesn't scrog any loops going 01650 * on in the main program. We save the necessary info in variables 01651 * local to this function so that function nesting works OK. 01652 * We also only bother to save the loop stuff if we're in a loop 01653 * when the function is called. 01654 */ 01655 if (loop_tag_valid) { 01656 int junk = 0; 01657 01658 save_loop_tag_valid = (volatile int) loop_tag_valid; 01659 PUSH_BINDING(loop_tag_stack, loop_tag, junk); 01660 loop_tag_valid = FALSE; 01661 } 01662 PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid); 01663 save_ret_node = ret_node; 01664 ret_node = Nnull_string; /* default return value */ 01665 INCREMENT(f->exec_count); /* count function calls */ 01666 if (setjmp(func_tag) == 0) 01667 (void) interpret(f->rnode); 01668 01669 r = ret_node; 01670 ret_node = (NODE *) save_ret_node; 01671 RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid); 01672 pop_fcall(); 01673 01674 /* Restore the loop_tag stuff if necessary. */ 01675 if (save_loop_tag_valid) { 01676 int junk = 0; 01677 01678 loop_tag_valid = (int) save_loop_tag_valid; 01679 RESTORE_BINDING(loop_tag_stack, loop_tag, junk); 01680 } 01681 01682 if ((r->flags & PERM) == 0) 01683 r->flags |= TEMP; 01684 return r; 01685 }
|
|
||||||||||||
|
Definition at line 297 of file eval.c. References _, fatal, i, name, NULL, and flagtab::val. Referenced by flags2str(), iopflags2str(), redflags2str(), and reflags2str(). 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 * note the trick, we want 1 or 0 for whether we need 00308 * the '|' character. 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 /* note ordering! */ 00321 space_left -= strlen(sp); 00322 sp += strlen(sp); 00323 } 00324 } 00325 00326 return buffer; 00327 }
|
|
|
Definition at line 335 of file eval.c. References _, ahname_len, ahname_str, array_size, array_vname(), cant_happen, cmp_nodes(), comp_func(), do_delete(), do_delete_loop(), do_lint, do_nextfile(), do_posix, do_print(), do_print_rec(), do_printf(), do_traditional, dupnode, emalloc, eval_condition(), FALSE, fatal, force_number, force_string, free_temp, get_array, get_lhs, i, in_begin_rule, in_end_rule, INCREMENT, lintwarn, make_string, Node_K_arrayfor, Node_K_break, Node_K_continue, Node_K_default, Node_K_delete, Node_K_delete_loop, Node_K_do, Node_K_exit, Node_K_for, Node_K_if, Node_K_next, Node_K_nextfile, Node_K_print, Node_K_print_rec, Node_K_printf, Node_K_return, Node_K_switch, Node_K_while, Node_regex, Node_rule_list, Node_rule_node, Node_statement_list, Node_var, Node_var_new, NULL, pop_all_forloops(), pop_fcall_stack(), pop_forloop(), PUSH_BINDING, push_forloop(), re_update(), research(), RESTORE_BINDING, source, sourceline, TAG_BREAK, TAG_CONTINUE, TAG_RETURN, tree_eval, TRUE, exp_node::type, unref(), and whiny_users. Referenced by do_input(), func_call(), and main(). 00336 { 00337 jmp_buf volatile loop_tag_stack; /* shallow binding stack for loop_tag */ 00338 static jmp_buf rule_tag; /* tag the rule currently being run, for NEXT 00339 * and EXIT statements. It is static because 00340 * there are no nested rules */ 00341 register NODE *volatile t = NULL; /* temporary */ 00342 NODE **volatile lhs; /* lhs == Left Hand Side for assigns, etc */ 00343 NODE *volatile stable_tree; 00344 int volatile traverse = TRUE; /* True => loop thru tree (Node_rule_list) */ 00345 00346 /* avoid false source indications */ 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; /* False => one for-loop iteration only */ 00357 /* FALL THROUGH */ 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: /* normal non-jump */ 00367 /* test pattern, if any */ 00368 if (tree->lnode == NULL || 00369 eval_condition(tree->lnode)) { 00370 /* using the lnode exec_count is kludgey */ 00371 if (tree->lnode != NULL) 00372 INCREMENT(tree->lnode->exec_count); 00373 (void) interpret(tree->rnode); 00374 } 00375 break; 00376 case TAG_CONTINUE: /* NEXT statement */ 00377 pop_all_forloops(); 00378 pop_fcall_stack(); 00379 return 1; 00380 case TAG_BREAK: /* EXIT statement */ 00381 pop_all_forloops(); 00382 pop_fcall_stack(); 00383 return 0; 00384 default: 00385 cant_happen(); 00386 } 00387 if (! traverse) /* case Node_rule_node */ 00388 break; /* don't loop */ 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 * Once a match is found, all cases will be processed as they fall through, 00431 * so continue to execute statements until a break is reached. 00432 */ 00433 if (! match_found) { 00434 if (case_stmt->type == Node_K_default) 00435 ; /* do nothing */ 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 /* If a match was found, execute the statements associated with the case. */ 00452 if (match_found) { 00453 INCREMENT(case_stmt->exec_count); 00454 switch (setjmp(loop_tag)) { 00455 case 0: /* Normal non-jump */ 00456 (void) interpret(case_stmt->rnode); 00457 break; 00458 case TAG_CONTINUE: /* continue statement */ 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: /* break statement */ 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 * If a default section was found, execute the statements associated with it 00478 * and execute any trailing case statements if the default falls through. 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: /* Normal non-jump */ 00488 (void) interpret(case_stmt->rnode); 00489 break; 00490 case TAG_CONTINUE: /* continue statement */ 00491 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid); 00492 longjmp(loop_tag, TAG_CONTINUE); 00493 break; 00494 case TAG_BREAK: /* break statement */ 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: /* normal non-jump */ 00515 (void) interpret(stable_tree->rnode); 00516 break; 00517 case TAG_CONTINUE: /* continue statement */ 00518 break; 00519 case TAG_BREAK: /* break statement */ 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: /* normal non-jump */ 00536 (void) interpret(stable_tree->rnode); 00537 break; 00538 case TAG_CONTINUE: /* continue statement */ 00539 break; 00540 case TAG_BREAK: /* break statement */ 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: /* normal non-jump */ 00558 (void) interpret(stable_tree->lnode); 00559 /* fall through */ 00560 case TAG_CONTINUE: /* continue statement */ 00561 (void) interpret(stable_tree->forloop->incr); 00562 break; 00563 case TAG_BREAK: /* break statement */ 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 /* get the array */ 00587 save_array = tree->arrvar; 00588 array = get_array(save_array); 00589 00590 /* sanity: do nothing if empty */ 00591 if (array->var_array == NULL || array->table_size == 0) 00592 break; /* from switch */ 00593 00594 /* allocate space for array */ 00595 num_elems = array->table_size; 00596 emalloc(list, NODE **, num_elems * sizeof(NODE *), "for_loop"); 00597 00598 /* populate it */ 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); /* shazzam! */ 00614 00615 /* now we can run the loop */ 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 * Old AT&T nawk treats break outside of loops like 00662 * next. New ones catch it at parse time. Allow it if 00663 * do_traditional is on, and complain if lint. 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 * Old AT&T nawk treats continue outside of loops like 00683 * next. New ones catch it at parse time. Allow it if 00684 * do_traditional is on, and complain if lint. 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 /* could add a lint check here for in a loop or function */ 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 /* could add a lint check here for in a loop or function */ 00743 /* 00744 * Have to do this cleanup here, since we don't longjump 00745 * back to the main awk rule loop (rule_tag). 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 * In A,K,&W, p. 49, it says that an exit statement "... 00757 * causes the program to behave as if the end of input had 00758 * occurred; no more input is read, and the END actions, if 00759 * any are executed." This implies that the rest of the rules 00760 * are not done. So we immediately break out of the main loop. 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 * Appears to be an expression statement. Throw away the 00782 * value. 00783 */ 00784 if (do_lint && (tree->type == Node_var || tree->type == |