home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / gnu / gawk213s.lzh / GAWK213S / EVAL.C < prev    next >
C/C++ Source or Header  |  1993-07-29  |  29KB  |  1,184 lines

  1. /*
  2.  * eval.c - gawk parse tree interpreter 
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. extern double pow P((double x, double y));
  29. extern double modf P((double x, double *yp));
  30.  
  31. static int eval_condition P((NODE *tree));
  32. static NODE *op_assign P((NODE *tree));
  33. static NODE *func_call P((NODE *name, NODE *arg_list));
  34. static NODE *match_op P((NODE *tree));
  35.  
  36. NODE *_t;        /* used as a temporary in macros */
  37. #ifdef MSDOS
  38. double _msc51bug;    /* to get around a bug in MSC 5.1 */
  39. #endif
  40. NODE *ret_node;
  41. int OFSlen;
  42. int ORSlen;
  43. int OFMTidx;
  44. int CONVFMTidx;
  45.  
  46. /* Macros and variables to save and restore function and loop bindings */
  47. /*
  48.  * the val variable allows return/continue/break-out-of-context to be
  49.  * caught and diagnosed
  50.  */
  51. #define PUSH_BINDING(stack, x, val) (memcpy ((char *)(stack), (char *)(x), sizeof (jmp_buf)), val++)
  52. #define RESTORE_BINDING(stack, x, val) (memcpy ((char *)(x), (char *)(stack), sizeof (jmp_buf)), val--)
  53.  
  54. static jmp_buf loop_tag;    /* always the current binding */
  55. static int loop_tag_valid = 0;    /* nonzero when loop_tag valid */
  56. static int func_tag_valid = 0;
  57. static jmp_buf func_tag;
  58. extern int exiting, exit_val;
  59.  
  60. /*
  61.  * This table is used by the regexp routines to do case independant
  62.  * matching. Basically, every ascii character maps to itself, except
  63.  * uppercase letters map to lower case ones. This table has 256
  64.  * entries, which may be overkill. Note also that if the system this
  65.  * is compiled on doesn't use 7-bit ascii, casetable[] should not be
  66.  * defined to the linker, so gawk should not load.
  67.  *
  68.  * Do NOT make this array static, it is used in several spots, not
  69.  * just in this file.
  70.  */
  71. #if 'a' == 97    /* it's ascii */
  72. char casetable[] = {
  73.     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  74.     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  75.     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  76.     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  77.     /* ' '     '!'     '"'     '#'     '$'     '%'     '&'     ''' */
  78.     '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  79.     /* '('     ')'     '*'     '+'     ','     '-'     '.'     '/' */
  80.     '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  81.     /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
  82.     '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  83.     /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
  84.     '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  85.     /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
  86.     '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  87.     /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
  88.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  89.     /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
  90.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  91.     /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
  92.     '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  93.     /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
  94.     '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  95.     /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
  96.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  97.     /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
  98.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  99.     /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
  100.     '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  101.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  102.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  103.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  104.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  105.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  106.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  107.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  108.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  109.     '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
  110.     '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
  111.     '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
  112.     '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
  113.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  114.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  115.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  116.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  117. };
  118. #else
  119. #include "You lose. You will need a translation table for your character set."
  120. #endif
  121.  
  122. /*
  123.  * Tree is a bunch of rules to run. Returns zero if it hit an exit()
  124.  * statement 
  125.  */
  126. int
  127. interpret(tree)
  128. register NODE *tree;
  129. {
  130.     volatile jmp_buf loop_tag_stack; /* shallow binding stack for loop_tag */
  131.     static jmp_buf rule_tag;/* tag the rule currently being run, for NEXT
  132.                  * and EXIT statements.  It is static because
  133.                  * there are no nested rules */
  134.     register NODE *t = NULL;/* temporary */
  135.     volatile NODE **lhs;    /* lhs == Left Hand Side for assigns, etc */
  136.     volatile NODE *stable_tree;
  137.     int traverse = 1;       /* True => loop thru tree (Node_rule_list) */
  138.  
  139.     if (tree == NULL)
  140.         return 1;
  141.     sourceline = tree->source_line;
  142.     source = tree->source_file;
  143.     switch (tree->type) {
  144.     case Node_rule_node:
  145.         traverse = 0;   /* False => one for-loop iteration only */
  146.         /* FALL THROUGH */
  147.     case Node_rule_list:
  148.         for (t = tree; t != NULL; t = t->rnode) {
  149.             if (traverse)
  150.                 tree = t->lnode;
  151.             sourceline = tree->source_line;
  152.             source = tree->source_file;
  153.             switch (setjmp(rule_tag)) {
  154.             case 0:    /* normal non-jump */
  155.                 /* test pattern, if any */
  156.                 if (tree->lnode == NULL ||
  157.                     eval_condition(tree->lnode))
  158.                     (void) interpret(tree->rnode);
  159.                 break;
  160.             case TAG_CONTINUE:    /* NEXT statement */
  161.                 return 1;
  162.             case TAG_BREAK:
  163.                 return 0;
  164.             default:
  165.                 cant_happen();
  166.             }
  167.             if (!traverse)          /* case Node_rule_node */
  168.                 break;          /* don't loop */
  169.         }
  170.         break;
  171.  
  172.     case Node_statement_list:
  173.         for (t = tree; t != NULL; t = t->rnode)
  174.             (void) interpret(t->lnode);
  175.         break;
  176.  
  177.     case Node_K_if:
  178.         if (eval_condition(tree->lnode)) {
  179.             (void) interpret(tree->rnode->lnode);
  180.         } else {
  181.             (void) interpret(tree->rnode->rnode);
  182.         }
  183.         break;
  184.  
  185.     case Node_K_while:
  186.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  187.  
  188.         stable_tree = tree;
  189.         while (eval_condition(stable_tree->lnode)) {
  190.             switch (setjmp(loop_tag)) {
  191.             case 0:    /* normal non-jump */
  192.                 (void) interpret(stable_tree->rnode);
  193.                 break;
  194.             case TAG_CONTINUE:    /* continue statement */
  195.                 break;
  196.             case TAG_BREAK:    /* break statement */
  197.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  198.                 return 1;
  199.             default:
  200.                 cant_happen();
  201.             }
  202.         }
  203.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  204.         break;
  205.  
  206.     case Node_K_do:
  207.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  208.         stable_tree = tree;
  209.         do {
  210.             switch (setjmp(loop_tag)) {
  211.             case 0:    /* normal non-jump */
  212.                 (void) interpret(stable_tree->rnode);
  213.                 break;
  214.             case TAG_CONTINUE:    /* continue statement */
  215.                 break;
  216.             case TAG_BREAK:    /* break statement */
  217.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  218.                 return 1;
  219.             default:
  220.                 cant_happen();
  221.             }
  222.         } while (eval_condition(stable_tree->lnode));
  223.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  224.         break;
  225.  
  226.     case Node_K_for:
  227.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  228.         (void) interpret(tree->forloop->init);
  229.         stable_tree = tree;
  230.         while (eval_condition(stable_tree->forloop->cond)) {
  231.             switch (setjmp(loop_tag)) {
  232.             case 0:    /* normal non-jump */
  233.                 (void) interpret(stable_tree->lnode);
  234.                 /* fall through */
  235.             case TAG_CONTINUE:    /* continue statement */
  236.                 (void) interpret(stable_tree->forloop->incr);
  237.                 break;
  238.             case TAG_BREAK:    /* break statement */
  239.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  240.                 return 1;
  241.             default:
  242.                 cant_happen();
  243.             }
  244.         }
  245.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  246.         break;
  247.  
  248.     case Node_K_arrayfor:
  249.         {
  250.         volatile struct search l;    /* For array_for */
  251.         Func_ptr after_assign = NULL;
  252.  
  253. #define hakvar forloop->init
  254. #define arrvar forloop->incr
  255.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  256.         lhs = (volatile NODE **) get_lhs(tree->hakvar, &after_assign);
  257.         t = tree->arrvar;
  258.         if (t->type == Node_param_list)
  259.             t = stack_ptr[t->param_cnt];
  260.         stable_tree = tree;
  261.         for (assoc_scan(t, (struct search *)&l);
  262.              l.retval;
  263.              assoc_next((struct search *)&l)) {
  264.             unref(*((NODE **) lhs));
  265.             *lhs = dupnode(l.retval);
  266.             if (after_assign)
  267.                 (*after_assign)();
  268.             switch (setjmp(loop_tag)) {
  269.             case 0:
  270.                 (void) interpret(stable_tree->lnode);
  271.             case TAG_CONTINUE:
  272.                 break;
  273.  
  274.             case TAG_BREAK:
  275.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  276.                 return 1;
  277.             default:
  278.                 cant_happen();
  279.             }
  280.         }
  281.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  282.         break;
  283.         }
  284.  
  285.     case Node_K_break:
  286.         if (loop_tag_valid == 0)
  287.             fatal("unexpected break");
  288.         longjmp(loop_tag, TAG_BREAK);
  289.         break;
  290.  
  291.     case Node_K_continue:
  292.         if (loop_tag_valid == 0)
  293.             fatal("unexpected continue");
  294.         longjmp(loop_tag, TAG_CONTINUE);
  295.         break;
  296.  
  297.     case Node_K_print:
  298.         do_print(tree);
  299.         break;
  300.  
  301.     case Node_K_printf:
  302.         do_printf(tree);
  303.         break;
  304.  
  305.     case Node_K_delete:
  306.         do_delete(tree->lnode, tree->rnode);
  307.         break;
  308.  
  309.     case Node_K_next:
  310.         longjmp(rule_tag, TAG_CONTINUE);
  311.         break;
  312.  
  313.     case Node_K_exit:
  314.         /*
  315.          * In A,K,&W, p. 49, it says that an exit statement "...
  316.          * causes the program to behave as if the end of input had
  317.          * occurred; no more input is read, and the END actions, if
  318.          * any are executed." This implies that the rest of the rules
  319.          * are not done. So we immediately break out of the main loop.
  320.          */
  321.         exiting = 1;
  322.         if (tree) {
  323.             t = tree_eval(tree->lnode);
  324.             exit_val = (int) force_number(t);
  325.         }
  326.         free_temp(t);
  327.         longjmp(rule_tag, TAG_BREAK);
  328.         break;
  329.  
  330.     case Node_K_return:
  331.         t = tree_eval(tree->lnode);
  332.         ret_node = dupnode(t);
  333.         free_temp(t);
  334.         longjmp(func_tag, TAG_RETURN);
  335.         break;
  336.  
  337.     default:
  338.         /*
  339.          * Appears to be an expression statement.  Throw away the
  340.          * value. 
  341.          */
  342.         t = tree_eval(tree);
  343.         free_temp(t);
  344.         break;
  345.     }
  346.     return 1;
  347. }
  348.  
  349. /* evaluate a subtree */
  350.  
  351. NODE *
  352. r_tree_eval(tree)
  353. register NODE *tree;
  354. {
  355.     register NODE *r, *t1, *t2;    /* return value & temporary subtrees */
  356.     register NODE **lhs;
  357.     register int di;
  358.     AWKNUM x, x1, x2;
  359.     long lx;
  360. #ifdef CRAY
  361.     long lx2;
  362. #endif
  363.  
  364. #ifdef DEBUG
  365.     if (tree == NULL)
  366.         return Nnull_string;
  367.     if (tree->type == Node_val) {
  368.         if (tree->stref <= 0) cant_happen();
  369.         return tree;
  370.     }
  371.     if (tree->type == Node_var) {
  372.         if (tree->var_value->stref <= 0) cant_happen();
  373.         return tree->var_value;
  374.     }
  375.     if (tree->type == Node_param_list)
  376.         return (stack_ptr[(_t)->param_cnt])->var_value;
  377. #endif
  378.     switch (tree->type) {
  379.     case Node_and:
  380.         return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  381.                         && eval_condition(tree->rnode)));
  382.  
  383.     case Node_or:
  384.         return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  385.                         || eval_condition(tree->rnode)));
  386.  
  387.     case Node_not:
  388.         return tmp_number((AWKNUM) ! eval_condition(tree->lnode));
  389.  
  390.         /* Builtins */
  391.     case Node_builtin:
  392.         return ((*tree->proc) (tree->subnode));
  393.  
  394.     case Node_K_getline:
  395.         return (do_getline(tree));
  396.  
  397.     case Node_in_array:
  398.         return tmp_number((AWKNUM) in_array(tree->lnode, tree->rnode));
  399.  
  400.     case Node_func_call:
  401.         return func_call(tree->rnode, tree->lnode);
  402.  
  403.         /* unary operations */
  404.     case Node_NR:
  405.     case Node_FNR:
  406.     case Node_NF:
  407.     case Node_FIELDWIDTHS:
  408.     case Node_FS:
  409.     case Node_RS:
  410.     case Node_field_spec:
  411.     case Node_subscript:
  412.     case Node_IGNORECASE:
  413.     case Node_OFS:
  414.     case Node_ORS:
  415.     case Node_OFMT:
  416.     case Node_CONVFMT:
  417.         lhs = get_lhs(tree, (Func_ptr *)0);
  418.         return *lhs;
  419.  
  420.     case Node_unary_minus:
  421.         t1 = tree_eval(tree->subnode);
  422.         x = -force_number(t1);
  423.         free_temp(t1);
  424.         return tmp_number(x);
  425.  
  426.     case Node_cond_exp:
  427.         if (eval_condition(tree->lnode))
  428.             return tree_eval(tree->rnode->lnode);
  429.         return tree_eval(tree->rnode->rnode);
  430.  
  431.     case Node_match:
  432.     case Node_nomatch:
  433.     case Node_regex:
  434.         return match_op(tree);
  435.  
  436.     case Node_func:
  437.         fatal("function `%s' called with space between name and (,\n%s",
  438.             tree->lnode->param,
  439.             "or used in other expression context");
  440.  
  441.         /* assignments */
  442.     case Node_assign:
  443.         {
  444.         Func_ptr after_assign = NULL;
  445.  
  446.         r = tree_eval(tree->rnode);
  447.         lhs = get_lhs(tree->lnode, &after_assign);
  448.         unref(*lhs);
  449.         *lhs = dupnode(r);
  450.         free_temp(r);
  451.         if (after_assign)
  452.             (*after_assign)();
  453.         return *lhs;
  454.         }
  455.  
  456.     case Node_concat:
  457.         {
  458. #define    STACKSIZE    10
  459.         NODE *stack[STACKSIZE];
  460.         register NODE **sp;
  461.         register int len;
  462.         char *str;
  463.         register char *dest;
  464.  
  465.         sp = stack;
  466.         len = 0;
  467.         while (tree->type == Node_concat) {
  468.             *sp = force_string(tree_eval(tree->lnode));
  469.             tree = tree->rnode;
  470.             len += (*sp)->stlen;
  471.             if (++sp == &stack[STACKSIZE-2]) /* one more and NULL */
  472.                 break;
  473.         }
  474.         *sp = force_string(tree_eval(tree));
  475.         len += (*sp)->stlen;
  476.         *++sp = NULL;
  477.         emalloc(str, char *, len+2, "tree_eval");
  478.         dest = str;
  479.         sp = stack;
  480.         while (*sp) {
  481.             memcpy(dest, (*sp)->stptr, (*sp)->stlen);
  482.             dest += (*sp)->stlen;
  483.             free_temp(*sp);
  484.             sp++;
  485.         }
  486.         r = make_str_node(str, len, ALREADY_MALLOCED);
  487.         r->flags |= TEMP;
  488.         }
  489.         return r;
  490.  
  491.     /* other assignment types are easier because they are numeric */
  492.     case Node_preincrement:
  493.     case Node_predecrement:
  494.     case Node_postincrement:
  495.     case Node_postdecrement:
  496.     case Node_assign_exp:
  497.     case Node_assign_times:
  498.     case Node_assign_quotient:
  499.     case Node_assign_mod:
  500.     case Node_assign_plus:
  501.     case Node_assign_minus:
  502.         return op_assign(tree);
  503.     default:
  504.         break;    /* handled below */
  505.     }
  506.  
  507.     /* evaluate subtrees in order to do binary operation, then keep going */
  508.     t1 = tree_eval(tree->lnode);
  509.     t2 = tree_eval(tree->rnode);
  510.  
  511.     switch (tree->type) {
  512.     case Node_geq:
  513.     case Node_leq:
  514.     case Node_greater:
  515.     case Node_less:
  516.     case Node_notequal:
  517.     case Node_equal:
  518.         di = cmp_nodes(t1, t2);
  519.         free_temp(t1);
  520.         free_temp(t2);
  521.         switch (tree->type) {
  522.         case Node_equal:
  523.             return tmp_number((AWKNUM) (di == 0));
  524.         case Node_notequal:
  525.             return tmp_number((AWKNUM) (di != 0));
  526.         case Node_less:
  527.             return tmp_number((AWKNUM) (di < 0));
  528.         case Node_greater:
  529.             return tmp_number((AWKNUM) (di > 0));
  530.         case Node_leq:
  531.             return tmp_number((AWKNUM) (di <= 0));
  532.         case Node_geq:
  533.             return tmp_number((AWKNUM) (di >= 0));
  534.         default:
  535.             cant_happen();
  536.         }
  537.         break;
  538.     default:
  539.         break;    /* handled below */
  540.     }
  541.  
  542.     x1 = force_number(t1);
  543.     free_temp(t1);
  544.     x2 = force_number(t2);
  545.     free_temp(t2);
  546.     switch (tree->type) {
  547.     case Node_exp:
  548.         if ((lx = x2) == x2) {    /* integer exponent */
  549.             if (lx == 0)
  550.                 x = 1;
  551.             else if (lx == 1)
  552.                 x = x1;
  553.             else {
  554.                 /* doing it this way should be more precise */
  555.                 for (x = x1; --lx; )
  556.                     x *= x1;
  557.             }
  558.         } else
  559.             x = pow((double) x1, (double) x2);
  560.         return tmp_number(x);
  561.  
  562.     case Node_times:
  563.         return tmp_number(x1 * x2);
  564.  
  565.     case Node_quotient:
  566.         if (x2 == 0)
  567.             fatal("division by zero attempted");
  568. #ifdef _CRAY
  569.         /*
  570.          * special case for integer division, put in for Cray
  571.          */
  572.         lx2 = x2;
  573.         if (lx2 == 0)
  574.             return tmp_number(x1 / x2);
  575.         lx = (long) x1 / lx2;
  576.         if (lx * x2 == x1)
  577.             return tmp_number((AWKNUM) lx);
  578.         else
  579. #endif
  580.             return tmp_number(x1 / x2);
  581.  
  582.     case Node_mod:
  583.         if (x2 == 0)
  584.             fatal("division by zero attempted in mod");
  585.         (void) modf(x1 / x2, &x);
  586.         return tmp_number(x1 - x * x2);
  587.  
  588.     case Node_plus:
  589.         return tmp_number(x1 + x2);
  590.  
  591.     case Node_minus:
  592.         return tmp_number(x1 - x2);
  593.  
  594.     default:
  595.         fatal("illegal type (%d) in tree_eval", tree->type);
  596.     }
  597.     return 0;
  598. }
  599.  
  600. /* Is TREE true or false?  Returns 0==false, non-zero==true */
  601. static int
  602. eval_condition(tree)
  603. register NODE *tree;
  604. {
  605.     register NODE *t1;
  606.     register int ret;
  607.  
  608.     if (tree == NULL)    /* Null trees are the easiest kinds */
  609.         return 1;
  610.     if (tree->type == Node_line_range) {
  611.         /*
  612.          * Node_line_range is kind of like Node_match, EXCEPT: the
  613.          * lnode field (more properly, the condpair field) is a node
  614.          * of a Node_cond_pair; whether we evaluate the lnode of that
  615.          * node or the rnode depends on the triggered word.  More
  616.          * precisely:  if we are not yet triggered, we tree_eval the
  617.          * lnode; if that returns true, we set the triggered word. 
  618.          * If we are triggered (not ELSE IF, note), we tree_eval the
  619.          * rnode, clear triggered if it succeeds, and perform our
  620.          * action (regardless of success or failure).  We want to be
  621.          * able to begin and end on a single input record, so this
  622.          * isn't an ELSE IF, as noted above.
  623.          */
  624.         if (!tree->triggered)
  625.             if (!eval_condition(tree->condpair->lnode))
  626.                 return 0;
  627.             else
  628.                 tree->triggered = 1;
  629.         /* Else we are triggered */
  630.         if (eval_condition(tree->condpair->rnode))
  631.             tree->triggered = 0;
  632.         return 1;
  633.     }
  634.  
  635.     /*
  636.      * Could just be J.random expression. in which case, null and 0 are
  637.      * false, anything else is true 
  638.      */
  639.  
  640.     t1 = tree_eval(tree);
  641.     if (t1->flags & MAYBE_NUM)
  642.         (void) force_number(t1);
  643.     if (t1->flags & NUMERIC)
  644.         ret = t1->numbr != 0.0;
  645.     else
  646.         ret = t1->stlen != 0;
  647.     free_temp(t1);
  648.     return ret;
  649. }
  650.  
  651. /*
  652.  * compare two nodes, returning negative, 0, positive
  653.  */
  654. int
  655. cmp_nodes(t1, t2)
  656. register NODE *t1, *t2;
  657. {
  658.     AWKNUM diff;
  659.     register int ret;
  660.     register int len1, len2;
  661.     int donum;
  662.  
  663.     if (t1 == t2)
  664.         return 0;
  665.     if (t1->flags & MAYBE_NUM)
  666.         (void) force_number(t1);
  667.     if (t2->flags & MAYBE_NUM)
  668.         (void) force_number(t2);
  669. #ifdef maybe
  670.     if ((t1->flags & NUMERIC) && (t2->flags & NUMERIC)) {
  671. #else
  672.     donum = 0;
  673.     if ((t1->flags & NUMBER)) {
  674.         (void) force_number(t2);
  675.         if (t2->flags & NUMERIC)
  676.             donum = 1;
  677.     } else if ((t2->flags & NUMBER)) {
  678.         (void) force_number(t1);
  679.         if (t1->flags & NUMERIC)
  680.             donum = 1;
  681.     }
  682.     if (donum) {
  683. #endif
  684.         diff = t1->numbr - t2->numbr;
  685.         if (diff == 0) return 0;
  686.         else if (diff < 0) return -1;
  687.         else return 1;
  688.     }
  689.     (void) force_string(t1);
  690.     (void) force_string(t2);
  691.     len1 = t1->stlen;
  692.     len2 = t2->stlen;
  693.     if (len1 == 0 || len2 == 0)
  694.         return len1 - len2;
  695.     ret = memcmp(t1->stptr, t2->stptr, len1 <= len2 ? len1 : len2);
  696.     return ret == 0 ? len1-len2 : ret;
  697. }
  698.  
  699. static NODE *
  700. op_assign(tree)
  701. register NODE *tree;
  702. {
  703.     AWKNUM rval, lval;
  704.     NODE **lhs;
  705.     AWKNUM t1, t2;
  706.     long ltemp;
  707.     NODE *tmp;
  708.     Func_ptr after_assign = NULL;
  709.  
  710.     lhs = get_lhs(tree->lnode, &after_assign);
  711.     lval = force_number(*lhs);
  712.     unref(*lhs);
  713.  
  714.     switch(tree->type) {
  715.     case Node_preincrement:
  716.     case Node_predecrement:
  717.         *lhs = make_number(lval +
  718.                    (tree->type == Node_preincrement ? 1.0 : -1.0));
  719.         if (after_assign)
  720.             (*after_assign)();
  721.         return *lhs;
  722.  
  723.     case Node_postincrement:
  724.     case Node_postdecrement:
  725.         *lhs = make_number(lval +
  726.                    (tree->type == Node_postincrement ? 1.0 : -1.0));
  727.         if (after_assign)
  728.             (*after_assign)();
  729.         return tmp_number(lval);
  730.     default:
  731.         break;    /* handled below */
  732.     }
  733.  
  734.     tmp = tree_eval(tree->rnode);
  735.     rval = force_number(tmp);
  736.     free_temp(tmp);
  737.     switch(tree->type) {
  738.     case Node_assign_exp:
  739.         if ((ltemp = rval) == rval) {    /* integer exponent */
  740.             if (ltemp == 0)
  741.                 *lhs = make_number((AWKNUM) 1);
  742.             else if (ltemp == 1)
  743.                 *lhs = make_number(lval);
  744.             else {
  745.                 /* doing it this way should be more precise */
  746.                 for (t1 = t2 = lval; --ltemp; )
  747.                     t1 *= t2;
  748.                 *lhs = make_number(t1);
  749.             }
  750.         } else
  751.             *lhs = make_number((AWKNUM) pow((double) lval, (double) rval));
  752.         break;
  753.  
  754.     case Node_assign_times:
  755.         *lhs = make_number(lval * rval);
  756.         break;
  757.  
  758.     case Node_assign_quotient:
  759.         if (rval == (AWKNUM) 0)
  760.             fatal("division by zero attempted in /=");
  761. #ifdef _CRAY
  762.         /*
  763.          * special case for integer division, put in for Cray
  764.          */
  765.         ltemp = rval;
  766.         if (ltemp == 0) {
  767.             *lhs = make_number(lval / rval);
  768.             break;
  769.         }
  770.         ltemp = (long) lval / ltemp;
  771.         if (ltemp * lval == rval)
  772.             *lhs = make_number((AWKNUM) ltemp);
  773.         else
  774. #endif
  775.             *lhs = make_number(lval / rval);
  776.         break;
  777.  
  778.     case Node_assign_mod:
  779.         if (rval == (AWKNUM) 0)
  780.             fatal("division by zero attempted in %=");
  781.         (void) modf(lval / rval, &t1);
  782.         t2 = lval - rval * t1;
  783.         *lhs = make_number(t2);
  784.         break;
  785.  
  786.     case Node_assign_plus:
  787.         *lhs = make_number(lval + rval);
  788.         break;
  789.  
  790.     case Node_assign_minus:
  791.         *lhs = make_number(lval - rval);
  792.         break;
  793.     default:
  794.         cant_happen();
  795.     }
  796.     if (after_assign)
  797.         (*after_assign)();
  798.     return *lhs;
  799. }
  800.  
  801. NODE **stack_ptr;
  802.  
  803. static NODE *
  804. func_call(name, arg_list)
  805. NODE *name;        /* name is a Node_val giving function name */
  806. NODE *arg_list;        /* Node_expression_list of calling args. */
  807. {
  808.     register NODE *arg, *argp, *r;
  809.     NODE *n, *f;
  810.     volatile jmp_buf func_tag_stack;
  811.     volatile jmp_buf loop_tag_stack;
  812.     volatile int save_loop_tag_valid = 0;
  813.     volatile NODE **save_stack, *save_ret_node;
  814.     NODE **local_stack = NULL, **sp;
  815.     int count;
  816.     extern NODE *ret_node;
  817.  
  818.     /*
  819.      * retrieve function definition node
  820.      */
  821.     f = lookup(name->stptr);
  822.     if (!f || f->type != Node_func)
  823.         fatal("function `%s' not defined", name->stptr);
  824. #ifdef FUNC_TRACE
  825.     fprintf(stderr, "function %s called\n", name->stptr);
  826. #endif
  827.     count = f->lnode->param_cnt;
  828.     if (count)
  829.         emalloc(local_stack, NODE **, count*sizeof(NODE *), "func_call");
  830.     sp = local_stack;
  831.  
  832.     /*
  833.      * for each calling arg. add NODE * on stack
  834.      */
  835.     for (argp = arg_list; count && argp != NULL; argp = argp->rnode) {
  836.         arg = argp->lnode;
  837.         getnode(r);
  838.         r->type = Node_var;
  839.         /*
  840.          * call by reference for arrays; see below also
  841.          */
  842.         if (arg->type == Node_param_list)
  843.             arg = stack_ptr[arg->param_cnt];
  844.         if (arg->type == Node_var_array)
  845.             *r = *arg;
  846.         else {
  847.             n = tree_eval(arg);
  848.             r->lnode = dupnode(n);
  849.             r->rnode = (NODE *) NULL;
  850.             free_temp(n);
  851.           }
  852.         *sp++ = r;
  853.         count--;
  854.     }
  855.     if (argp != NULL)    /* left over calling args. */
  856.         warning(
  857.             "function `%s' called with more arguments than declared",
  858.             name->stptr);
  859.     /*
  860.      * add remaining params. on stack with null value
  861.      */
  862.     while (count-- > 0) {
  863.         getnode(r);
  864.         r->type = Node_var;
  865.         r->lnode = Nnull_string;
  866.         r->rnode = (NODE *) NULL;
  867.         *sp++ = r;
  868.     }
  869.  
  870.     /*
  871.      * Execute function body, saving context, as a return statement
  872.      * will longjmp back here.
  873.      *
  874.      * Have to save and restore the loop_tag stuff so that a return
  875.      * inside a loop in a function body doesn't scrog any loops going
  876.      * on in the main program.  We save the necessary info in variables
  877.      * local to this function so that function nesting works OK.
  878.      * We also only bother to save the loop stuff if we're in a loop
  879.      * when the function is called.
  880.      */
  881.     if (loop_tag_valid) {
  882.         int junk = 0;
  883.  
  884.         save_loop_tag_valid = (volatile int) loop_tag_valid;
  885.         PUSH_BINDING(loop_tag_stack, loop_tag, junk);
  886.         loop_tag_valid = 0;
  887.     }
  888.     save_stack = (volatile NODE **) stack_ptr;
  889.     stack_ptr = local_stack;
  890.     PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid);
  891.     save_ret_node = (volatile NODE *) ret_node;
  892.     ret_node = Nnull_string;    /* default return value */
  893.     if (setjmp(func_tag) == 0)
  894.         (void) interpret(f->rnode);
  895.  
  896.     r = ret_node;
  897.     ret_node = (NODE *) save_ret_node;
  898.     RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid);
  899.     stack_ptr = (NODE **) save_stack;
  900.  
  901.     /*
  902.      * here, we pop each parameter and check whether
  903.      * it was an array.  If so, and if the arg. passed in was
  904.      * a simple variable, then the value should be copied back.
  905.      * This achieves "call-by-reference" for arrays.
  906.      */
  907.     sp = local_stack;
  908.     count = f->lnode->param_cnt;
  909.     for (argp = arg_list; count > 0 && argp != NULL; argp = argp->rnode) {
  910.         arg = argp->lnode;
  911.         if (arg->type == Node_param_list)
  912.             arg = stack_ptr[arg->param_cnt];
  913.         n = *sp++;
  914.         if (arg->type == Node_var && n->type == Node_var_array) {
  915.             arg->var_array = n->var_array;
  916.             arg->type = Node_var_array;
  917.         }
  918.         unref(n->lnode);
  919.         freenode(n);
  920.         count--;
  921.     }
  922.     while (count-- > 0) {
  923.         n = *sp++;
  924.         unref(n->lnode);
  925.         freenode(n);
  926.     }
  927.     if (local_stack)
  928.         free((char *) local_stack);
  929.  
  930.     /* Restore the loop_tag stuff if necessary. */
  931.     if (save_loop_tag_valid) {
  932.         int junk = 0;
  933.  
  934.         loop_tag_valid = (int) save_loop_tag_valid;
  935.         RESTORE_BINDING(loop_tag_stack, loop_tag, junk);
  936.     }
  937.  
  938.     if (!(r->flags & PERM))
  939.         r->flags |= TEMP;
  940.     return r;
  941. }
  942.  
  943. /*
  944.  * This returns a POINTER to a node pointer. get_lhs(ptr) is the current
  945.  * value of the var, or where to store the var's new value 
  946.  */
  947.  
  948. NODE **
  949. get_lhs(ptr, assign)
  950. register NODE *ptr;
  951. Func_ptr *assign;
  952. {
  953.     register NODE **aptr = NULL;
  954.     register NODE *n;
  955.  
  956.     switch (ptr->type) {
  957.     case Node_var_array:
  958.         fatal("attempt to use an array in a scalar context");
  959.     case Node_var:
  960.         aptr = &(ptr->var_value);
  961. #ifdef DEBUG
  962.         if (ptr->var_value->stref <= 0)
  963.             cant_happen();
  964. #endif
  965.         break;
  966.  
  967.     case Node_FIELDWIDTHS:
  968.         aptr = &(FIELDWIDTHS_node->var_value);
  969.         if (assign)
  970.             *assign = set_FIELDWIDTHS;
  971.         break;
  972.  
  973.     case Node_RS:
  974.         aptr = &(RS_node->var_value);
  975.         if (assign)
  976.             *assign = set_RS;
  977.         break;
  978.  
  979.     case Node_FS:
  980.         aptr = &(FS_node->var_value);
  981.         if (assign)
  982.             *assign = set_FS;
  983.         break;
  984.  
  985.     case Node_FNR:
  986.         unref(FNR_node->var_value);
  987.         FNR_node->var_value = make_number((AWKNUM) FNR);
  988.         aptr = &(FNR_node->var_value);
  989.         if (assign)
  990.             *assign = set_FNR;
  991.         break;
  992.  
  993.     case Node_NR:
  994.         unref(NR_node->var_value);
  995.         NR_node->var_value = make_number((AWKNUM) NR);
  996.         aptr = &(NR_node->var_value);
  997.         if (assign)
  998.             *assign = set_NR;
  999.         break;
  1000.  
  1001.     case Node_NF:
  1002.         if (NF == -1)
  1003.             (void) get_field(HUGE-1, assign); /* parse record */
  1004.         unref(NF_node->var_value);
  1005.         NF_node->var_value = make_number((AWKNUM) NF);
  1006.         aptr = &(NF_node->var_value);
  1007.         if (assign)
  1008.             *assign = set_NF;
  1009.         break;
  1010.  
  1011.     case Node_IGNORECASE:
  1012.         unref(IGNORECASE_node->var_value);
  1013.         IGNORECASE_node->var_value = make_number((AWKNUM) IGNORECASE);
  1014.         aptr = &(IGNORECASE_node->var_value);
  1015.         if (assign)
  1016.             *assign = set_IGNORECASE;
  1017.         break;
  1018.  
  1019.     case Node_OFMT:
  1020.         aptr = &(OFMT_node->var_value);
  1021.         if (assign)
  1022.             *assign = set_OFMT;
  1023.         break;
  1024.  
  1025.     case Node_CONVFMT:
  1026.         aptr = &(CONVFMT_node->var_value);
  1027.         if (assign)
  1028.             *assign = set_CONVFMT;
  1029.         break;
  1030.  
  1031.     case Node_ORS:
  1032.         aptr = &(ORS_node->var_value);
  1033.         if (assign)
  1034.             *assign = set_ORS;
  1035.         break;
  1036.  
  1037.     case Node_OFS:
  1038.         aptr = &(OFS_node->var_value);
  1039.         if (assign)
  1040.             *assign = set_OFS;
  1041.         break;
  1042.  
  1043.     case Node_param_list:
  1044.         aptr = &(stack_ptr[ptr->param_cnt]->var_value);
  1045.         break;
  1046.  
  1047.     case Node_field_spec:
  1048.         {
  1049.         int field_num;
  1050.  
  1051.         n = tree_eval(ptr->lnode);
  1052.         field_num = (int) force_number(n);
  1053.         free_temp(n);
  1054.         if (field_num < 0)
  1055.             fatal("attempt to access field %d", field_num);
  1056.         if (field_num == 0 && field0_valid) {    /* short circuit */
  1057.             aptr = &fields_arr[0];
  1058.             if (assign)
  1059.                 *assign = reset_record;
  1060.             break;
  1061.         }
  1062.         aptr = get_field(field_num, assign);
  1063.         break;
  1064.         }
  1065.     case Node_subscript:
  1066.         n = ptr->lnode;
  1067.         if (n->type == Node_param_list)
  1068.             n = stack_ptr[n->param_cnt];
  1069.         aptr = assoc_lookup(n, concat_exp(ptr->rnode));
  1070.         break;
  1071.  
  1072.     case Node_func:
  1073.         fatal ("`%s' is a function, assignment is not allowed",
  1074.             ptr->lnode->param);
  1075.     default:
  1076.         cant_happen();
  1077.     }
  1078.     return aptr;
  1079. }
  1080.  
  1081. static NODE *
  1082. match_op(tree)
  1083. register NODE *tree;
  1084. {
  1085.     register NODE *t1;
  1086.     register Regexp *rp;
  1087.     int i;
  1088.     int match = 1;
  1089.  
  1090.     if (tree->type == Node_nomatch)
  1091.         match = 0;
  1092.     if (tree->type == Node_regex)
  1093.         t1 = *get_field(0, (Func_ptr *) 0);
  1094.     else {
  1095.         t1 = force_string(tree_eval(tree->lnode));
  1096.         tree = tree->rnode;
  1097.     }
  1098.     rp = re_update(tree);
  1099.     i = research(rp, t1->stptr, t1->stlen, 0);
  1100.     i = (i == -1) ^ (match == 1);
  1101.     free_temp(t1);
  1102.     return tmp_number((AWKNUM) i);
  1103. }
  1104.  
  1105. void
  1106. set_IGNORECASE()
  1107. {
  1108.     static int warned = 0;
  1109.  
  1110.     if ((do_lint || strict) && ! warned) {
  1111.         warned = 1;
  1112.         warning("IGNORECASE not supported in compatibility mode");
  1113.     }
  1114.     IGNORECASE = (force_number(IGNORECASE_node->var_value) != 0.0);
  1115. }
  1116.  
  1117. void
  1118. set_OFS()
  1119. {
  1120.     OFS = force_string(OFS_node->var_value)->stptr;
  1121.     OFSlen = OFS_node->var_value->stlen;
  1122.     OFS[OFSlen] = '\0';
  1123. }
  1124.  
  1125. void
  1126. set_ORS()
  1127. {
  1128.     ORS = force_string(ORS_node->var_value)->stptr;
  1129.     ORSlen = ORS_node->var_value->stlen;
  1130.     ORS[ORSlen] = '\0';
  1131. }
  1132.  
  1133. static NODE **fmt_list = NULL;
  1134.  
  1135. static int
  1136. fmt_ok(n)
  1137. NODE *n;
  1138. {
  1139.     /* to be done later */
  1140.     return 1;
  1141. }
  1142.  
  1143. static int
  1144. fmt_index(n)
  1145. NODE *n;
  1146. {
  1147.     register int ix = 0;
  1148.     static int fmt_num = 4;
  1149.     static int fmt_hiwater = 0;
  1150.  
  1151.     if (fmt_list == NULL)
  1152.         emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), "fmt_index");
  1153.     (void) force_string(n);
  1154.     while (ix < fmt_hiwater) {
  1155.         if (cmp_nodes(fmt_list[ix], n) == 0)
  1156.             return ix;
  1157.         ix++;
  1158.     }
  1159.     /* not found */
  1160.     n->stptr[n->stlen] = '\0';
  1161.     if (!fmt_ok(n))
  1162.         warning("bad FMT specification");
  1163.     if (fmt_hiwater >= fmt_num) {
  1164.         fmt_num *= 2;
  1165.         emalloc(fmt_list, NODE **, fmt_num, "fmt_index");
  1166.     }
  1167.     fmt_list[fmt_hiwater] = dupnode(n);
  1168.     return fmt_hiwater++;
  1169. }
  1170.  
  1171. void
  1172. set_OFMT()
  1173. {
  1174.     OFMTidx = fmt_index(OFMT_node->var_value);
  1175.     OFMT = fmt_list[OFMTidx]->stptr;
  1176. }
  1177.  
  1178. void
  1179. set_CONVFMT()
  1180. {
  1181.     CONVFMTidx = fmt_index(CONVFMT_node->var_value);
  1182.     CONVFMT = fmt_list[CONVFMTidx]->stptr;
  1183. }
  1184.