Main Page | Class List | Directories | File List | Class Members | File Members

eval.c

Go to the documentation of this file.
00001 /*
00002  * eval.c - gawk parse tree interpreter 
00003  */
00004 
00005 /* 
00006  * Copyright (C) 1986, 1988, 1989, 1991-2003 the Free Software Foundation, Inc.
00007  * 
00008  * This file is part of GAWK, the GNU implementation of the
00009  * AWK Programming Language.
00010  * 
00011  * GAWK is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  * 
00016  * GAWK is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  * 
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
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;               /* used as a temporary in macros */
00047 #endif
00048 #ifdef MSDOS
00049 double _msc51bug;       /* to get around a bug in MSC 5.1 */
00050 #endif
00051 NODE *ret_node;
00052 int OFSlen;
00053 int ORSlen;
00054 int OFMTidx;
00055 int CONVFMTidx;
00056 
00057 /* Profiling stuff */
00058 #ifdef PROFILING
00059 #define INCREMENT(n)    n++
00060 #else
00061 #define INCREMENT(n)    /* nothing */
00062 #endif
00063 
00064 /* Macros and variables to save and restore function and loop bindings */
00065 /*
00066  * the val variable allows return/continue/break-out-of-context to be
00067  * caught and diagnosed
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;                /* always the current binding */
00073 static int loop_tag_valid = FALSE;      /* nonzero when loop_tag valid */
00074 static int func_tag_valid = FALSE;
00075 static jmp_buf func_tag;
00076 extern int exiting, exit_val;
00077 
00078 /* This rather ugly macro is for VMS C */
00079 #ifdef C
00080 #undef C
00081 #endif
00082 #define C(c) ((char)c)  
00083 /*
00084  * This table is used by the regexp routines to do case independant
00085  * matching. Basically, every ascii character maps to itself, except
00086  * uppercase letters map to lower case ones. This table has 256
00087  * entries, for ISO 8859-1. Note also that if the system this
00088  * is compiled on doesn't use 7-bit ascii, casetable[] should not be
00089  * defined to the linker, so gawk should not load.
00090  *
00091  * Do NOT make this array static, it is used in several spots, not
00092  * just in this file.
00093  */
00094 #if 'a' == 97   /* it's ascii */
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         /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
00105         '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
00106         /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
00107         '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
00108         /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
00109         '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
00110         /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
00111         '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
00112         /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
00113         '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
00114         /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
00115         '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
00116         /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
00117         '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
00118         /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
00119         '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
00120         /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
00121         '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
00122         /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
00123         '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
00124 
00125         /* Latin 1: */
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  * This table maps node types to strings for debugging.
00151  * KEEP IN SYNC WITH awk.h!!!!
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 /* nodetype2str --- convert a node type into a printable value */
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 /* flags2str --- make a flags value readable */
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 /* genflags2str --- general routine to convert a flag value to a string */
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                  * 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 }
00328 
00329 /*
00330  * interpret:
00331  * Tree is a bunch of rules to run. Returns zero if it hit an exit()
00332  * statement 
00333  */
00334 int
00335 interpret(register NODE *volatile tree)
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 == Node_var_new))
00785                         lintwarn(_("statement has no effect"));
00786                 INCREMENT(tree->exec_count);
00787                 t = tree_eval(tree);
00788                 if (t)  /* stopme() returns NULL */
00789                         free_temp(t);
00790                 break;
00791         }
00792         return 1;
00793 }
00794 
00795 /* r_tree_eval --- evaluate a subtree */
00796 
00797 NODE *
00798 r_tree_eval(register NODE *tree, int iscond)
00799 {
00800         register NODE *r, *t1, *t2;     /* return value & temporary subtrees */
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                 /* fall through */
00852         case Node_var_new:
00853                 tree->type = Node_var;
00854                 tree->var_value = Nnull_string;
00855                 /* fall through */
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                 /* Builtins */
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                 /* unary operations */
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                  * This is an efficiency hack for multiple adjacent string
00943                  * concatenations, to avoid recursion and string copies.
00944                  *
00945                  * Node_concat trees grow downward to the left, so
00946                  * descend to lowest (first) node, accumulating nodes
00947                  * to evaluate to strings as we go.
00948                  */
00949 
00950                 /*
00951                  * But first, no arbitrary limits. Count the number of
00952                  * nodes and malloc the treelist and strlist arrays.
00953                  * There will be alloc_count + 1 items to concatenate. We
00954                  * also leave room for an extra pointer at the end to
00955                  * use as a sentinel.  Thus, start alloc_count at 2.
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                 /* Now, here we go. */
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                  * Now, evaluate to strings in LIFO order, accumulating
00974                  * the string length, so we can do a single malloc at the
00975                  * end.
00976                  *
00977                  * Evaluate the expressions first, then get their
00978                  * lengthes, in case one of the expressions has a
00979                  * side effect that changes one of the others.
00980                  * See test/nasty.awk.
00981                  *
00982                  * dupnode the results a la do_print, to give us
00983                  * more predicable behavior; compare gawk 3.0.6 to
00984                  * nawk/mawk on test/nasty.awk.
00985                  */
00986                 strp = strlist;
00987                 supposed_len = len = 0;
00988                 while (treep >= treelist) {
00989                         NODE *n;
00990 
00991                         /* Here lies the wumpus's brother. R.I.P. */
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';   /* for good measure */
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         /* assignments */
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         /* other assignment types are easier because they are numeric */
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;  /* handled below */
01056         }
01057 
01058         /*
01059          * Evaluate subtrees in order to do binary operation, then keep going.
01060          * Use dupnode to make sure that these values don't disappear out
01061          * from under us during recursive subexpression evaluation.
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