home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gawk-2.15.6-base.tgz / gawk-2.15.6-base.tar / fsf / gawk / eval.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  33KB  |  1,304 lines

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