home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / p / perl4036.zip / x2p / walk.c < prev   
C/C++ Source or Header  |  1993-02-08  |  49KB  |  2,084 lines

  1. /* $RCSfile: walk.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 17:33:46 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    walk.c,v $
  9.  * Revision 4.0.1.3  92/06/08  17:33:46  lwall
  10.  * patch20: in a2p, simplified the filehandle model
  11.  * patch20: in a2p, made RS="" translate to $/ = "\n\n"
  12.  * patch20: in a2p, do {...} while ... was missing some reconstruction code
  13.  * patch20: in a2p, getline should allow variable to be array element
  14.  * 
  15.  * Revision 4.0.1.2  91/11/05  19:25:09  lwall
  16.  * patch11: in a2p, split on whitespace produced extra null field
  17.  * 
  18.  * Revision 4.0.1.1  91/06/07  12:22:04  lwall
  19.  * patch4: new copyright notice
  20.  * patch4: a2p didn't correctly implement -n switch
  21.  * 
  22.  * Revision 4.0  91/03/20  01:58:36  lwall
  23.  * 4.0 baseline.
  24.  * 
  25.  */
  26.  
  27. #include "handy.h"
  28. #include "EXTERN.h"
  29. #include "util.h"
  30. #include "a2p.h"
  31.  
  32. bool exitval = FALSE;
  33. bool realexit = FALSE;
  34. bool saw_getline = FALSE;
  35. bool subretnum = FALSE;
  36. bool saw_FNR = FALSE;
  37. bool saw_argv0 = FALSE;
  38. bool saw_fh = FALSE;
  39. int maxtmp = 0;
  40. char *lparen;
  41. char *rparen;
  42. char *limit;
  43. STR *subs;
  44. STR *curargs = Nullstr;
  45.  
  46. STR *
  47. walk(useval,level,node,numericptr,minprec)
  48. int useval;
  49. int level;
  50. register int node;
  51. int *numericptr;
  52. int minprec;            /* minimum precedence without parens */
  53. {
  54.     register int len;
  55.     register STR *str;
  56.     register int type;
  57.     register int i;
  58.     register STR *tmpstr;
  59.     STR *tmp2str;
  60.     STR *tmp3str;
  61.     char *t;
  62.     char *d, *s;
  63.     int numarg;
  64.     int numeric = FALSE;
  65.     STR *fstr;
  66.     int prec = P_MAX;        /* assume no parens needed */
  67.     char *index();
  68.  
  69.     if (!node) {
  70.     *numericptr = 0;
  71.     return str_make("");
  72.     }
  73.     type = ops[node].ival;
  74.     len = type >> 8;
  75.     type &= 255;
  76.     switch (type) {
  77.     case OPROG:
  78.     arymax = 0;
  79.     if (namelist) {
  80.         while (isalpha(*namelist)) {
  81.         for (d = tokenbuf,s=namelist;
  82.           isalpha(*s) || isdigit(*s) || *s == '_';
  83.           *d++ = *s++) ;
  84.         *d = '\0';
  85.         while (*s && !isalpha(*s)) s++;
  86.         namelist = s;
  87.         nameary[++arymax] = savestr(tokenbuf);
  88.         }
  89.     }
  90.     if (maxfld < arymax)
  91.         maxfld = arymax;
  92.     opens = str_new(0);
  93.     subs = str_new(0);
  94.     str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  95.     if (do_split && need_entire && !absmaxfld)
  96.         split_to_array = TRUE;
  97.     if (do_split && split_to_array)
  98.         set_array_base = TRUE;
  99.     if (set_array_base) {
  100.         str_cat(str,"$[ = 1;\t\t\t# set array base to 1\n");
  101.     }
  102.     if (fswitch && !const_FS)
  103.         const_FS = fswitch;
  104.     if (saw_FS > 1 || saw_RS)
  105.         const_FS = 0;
  106.     if (saw_ORS && need_entire)
  107.         do_chop = TRUE;
  108.     if (fswitch) {
  109.         str_cat(str,"$FS = '");
  110.         if (index("*+?.[]()|^$\\",fswitch))
  111.         str_cat(str,"\\");
  112.         sprintf(tokenbuf,"%c",fswitch);
  113.         str_cat(str,tokenbuf);
  114.         str_cat(str,"';\t\t# field separator from -F switch\n");
  115.     }
  116.     else if (saw_FS && !const_FS) {
  117.         str_cat(str,"$FS = ' ';\t\t# set field separator\n");
  118.     }
  119.     if (saw_OFS) {
  120.         str_cat(str,"$, = ' ';\t\t# set output field separator\n");
  121.     }
  122.     if (saw_ORS) {
  123.         str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n");
  124.     }
  125.     if (saw_argv0) {
  126.         str_cat(str,"$ARGV0 = $0;\t\t# remember what we ran as\n");
  127.     }
  128.     if (str->str_cur > 20)
  129.         str_cat(str,"\n");
  130.     if (ops[node+2].ival) {
  131.         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  132.         str_free(fstr);
  133.         str_cat(str,"\n\n");
  134.     }
  135.     fstr = walk(0,level+1,ops[node+3].ival,&numarg,P_MIN);
  136.     if (*fstr->str_ptr) {
  137.         if (saw_line_op)
  138.         str_cat(str,"line: ");
  139.         str_cat(str,"while (<>) {\n");
  140.         tab(str,++level);
  141.         if (saw_FS && !const_FS)
  142.         do_chop = TRUE;
  143.         if (do_chop) {
  144.         str_cat(str,"chop;\t# strip record separator\n");
  145.         tab(str,level);
  146.         }
  147.         if (do_split)
  148.         emit_split(str,level);
  149.         str_scat(str,fstr);
  150.         str_free(fstr);
  151.         fixtab(str,--level);
  152.         str_cat(str,"}\n");
  153.         if (saw_FNR)
  154.         str_cat(str,"continue {\n    $FNRbase = $. if eof;\n}\n");
  155.     }
  156.     else
  157.         str_cat(str,"while (<>) { }        # (no line actions)\n");
  158.     if (ops[node+4].ival) {
  159.         realexit = TRUE;
  160.         str_cat(str,"\n");
  161.         tab(str,level);
  162.         str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
  163.         str_free(fstr);
  164.         str_cat(str,"\n");
  165.     }
  166.     if (exitval)
  167.         str_cat(str,"exit $ExitValue;\n");
  168.     if (subs->str_ptr) {
  169.         str_cat(str,"\n");
  170.         str_scat(str,subs);
  171.     }
  172.     if (saw_getline) {
  173.         for (len = 0; len < 4; len++) {
  174.         if (saw_getline & (1 << len)) {
  175.             sprintf(tokenbuf,"\nsub Getline%d {\n",len);
  176.             str_cat(str, tokenbuf);
  177.             if (len & 2) {
  178.             if (do_fancy_opens)
  179.                 str_cat(str,"    &Pick('',@_);\n");
  180.             else
  181.                 str_cat(str,"    ($fh) = @_;\n");
  182.             }
  183.             else {
  184.             if (saw_FNR)
  185.                 str_cat(str,"    $FNRbase = $. if eof;\n");
  186.             }
  187.             if (len & 1)
  188.             str_cat(str,"    local($_);\n");
  189.             if (len & 2)
  190.             str_cat(str,
  191.               "    if ($getline_ok = (($_ = <$fh>) ne ''))");
  192.             else
  193.             str_cat(str,
  194.               "    if ($getline_ok = (($_ = <>) ne ''))");
  195.             str_cat(str, " {\n");
  196.             level += 2;
  197.             tab(str,level);
  198.             i = 0;
  199.             if (do_chop) {
  200.             i++;
  201.             str_cat(str,"chop;\t# strip record separator\n");
  202.             tab(str,level);
  203.             }
  204.             if (do_split && !(len & 1)) {
  205.             i++;
  206.             emit_split(str,level);
  207.             }
  208.             if (!i)
  209.             str_cat(str,";\n");
  210.             fixtab(str,--level);
  211.             str_cat(str,"}\n    $_;\n}\n");
  212.             --level;
  213.         }
  214.         }
  215.     }
  216.     if (do_fancy_opens) {
  217.         str_cat(str,"\n\
  218. sub Pick {\n\
  219.     local($mode,$name,$pipe) = @_;\n\
  220.     $fh = $name;\n\
  221.     open($name,$mode.$name.$pipe) unless $opened{$name}++;\n\
  222. }\n\
  223. ");
  224.     }
  225.     break;
  226.     case OHUNKS:
  227.     str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  228.     str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  229.     str_free(fstr);
  230.     if (len == 3) {
  231.         str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
  232.         str_free(fstr);
  233.     }
  234.     else {
  235.     }
  236.     break;
  237.     case ORANGE:
  238.     prec = P_DOTDOT;
  239.     str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
  240.     str_cat(str," .. ");
  241.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  242.     str_free(fstr);
  243.     break;
  244.     case OPAT:
  245.     goto def;
  246.     case OREGEX:
  247.     str = str_new(0);
  248.     str_set(str,"/");
  249.     tmpstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  250.     /* translate \nnn to [\nnn] */
  251.     for (s = tmpstr->str_ptr, d = tokenbuf; *s; s++, d++) {
  252.         if (*s == '\\' && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])){
  253.         *d++ = '[';
  254.         *d++ = *s++;
  255.         *d++ = *s++;
  256.         *d++ = *s++;
  257.         *d++ = *s;
  258.         *d = ']';
  259.         }
  260.         else
  261.         *d = *s;
  262.     }
  263.     *d = '\0';
  264.     for (d=tokenbuf; *d; d++)
  265.         *d += 128;
  266.     str_cat(str,tokenbuf);
  267.     str_free(tmpstr);
  268.     str_cat(str,"/");
  269.     break;
  270.     case OHUNK:
  271.     if (len == 1) {
  272.         str = str_new(0);
  273.         str = walk(0,level,oper1(OPRINT,0),&numarg,P_MIN);
  274.         str_cat(str," if ");
  275.         str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
  276.         str_free(fstr);
  277.         str_cat(str,";");
  278.     }
  279.     else {
  280.         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  281.         if (*tmpstr->str_ptr) {
  282.         str = str_new(0);
  283.         str_set(str,"if (");
  284.         str_scat(str,tmpstr);
  285.         str_cat(str,") {\n");
  286.         tab(str,++level);
  287.         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  288.         str_free(fstr);
  289.         fixtab(str,--level);
  290.         str_cat(str,"}\n");
  291.         tab(str,level);
  292.         }
  293.         else {
  294.         str = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
  295.         }
  296.     }
  297.     break;
  298.     case OPPAREN:
  299.     str = str_new(0);
  300.     str_set(str,"(");
  301.     str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  302.     str_free(fstr);
  303.     str_cat(str,")");
  304.     break;
  305.     case OPANDAND:
  306.     prec = P_ANDAND;
  307.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  308.     str_cat(str," && ");
  309.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  310.     str_free(fstr);
  311.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  312.     str_free(fstr);
  313.     break;
  314.     case OPOROR:
  315.     prec = P_OROR;
  316.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  317.     str_cat(str," || ");
  318.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  319.     str_free(fstr);
  320.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  321.     str_free(fstr);
  322.     break;
  323.     case OPNOT:
  324.     prec = P_UNARY;
  325.     str = str_new(0);
  326.     str_set(str,"!");
  327.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
  328.     str_free(fstr);
  329.     break;
  330.     case OCOND:
  331.     prec = P_COND;
  332.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  333.     str_cat(str," ? ");
  334.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  335.     str_free(fstr);
  336.     str_cat(str," : ");
  337.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  338.     str_free(fstr);
  339.     break;
  340.     case OCPAREN:
  341.     str = str_new(0);
  342.     str_set(str,"(");
  343.     str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  344.     str_free(fstr);
  345.     numeric |= numarg;
  346.     str_cat(str,")");
  347.     break;
  348.     case OCANDAND:
  349.     prec = P_ANDAND;
  350.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  351.     numeric = 1;
  352.     str_cat(str," && ");
  353.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  354.     str_free(fstr);
  355.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  356.     str_free(fstr);
  357.     break;
  358.     case OCOROR:
  359.     prec = P_OROR;
  360.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  361.     numeric = 1;
  362.     str_cat(str," || ");
  363.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  364.     str_free(fstr);
  365.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  366.     str_free(fstr);
  367.     break;
  368.     case OCNOT:
  369.     prec = P_UNARY;
  370.     str = str_new(0);
  371.     str_set(str,"!");
  372.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
  373.     str_free(fstr);
  374.     numeric = 1;
  375.     break;
  376.     case ORELOP:
  377.     prec = P_REL;
  378.     str = walk(1,level,ops[node+2].ival,&numarg,prec+1);
  379.     numeric |= numarg;
  380.     tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  381.     tmp2str = walk(1,level,ops[node+3].ival,&numarg,prec+1);
  382.     numeric |= numarg;
  383.     if (!numeric ||
  384.      (!numarg && (*tmp2str->str_ptr == '"' || *tmp2str->str_ptr == '\''))) {
  385.         t = tmpstr->str_ptr;
  386.         if (strEQ(t,"=="))
  387.         str_set(tmpstr,"eq");
  388.         else if (strEQ(t,"!="))
  389.         str_set(tmpstr,"ne");
  390.         else if (strEQ(t,"<"))
  391.         str_set(tmpstr,"lt");
  392.         else if (strEQ(t,"<="))
  393.         str_set(tmpstr,"le");
  394.         else if (strEQ(t,">"))
  395.         str_set(tmpstr,"gt");
  396.         else if (strEQ(t,">="))
  397.         str_set(tmpstr,"ge");
  398.         if (!index(tmpstr->str_ptr,'\'') && !index(tmpstr->str_ptr,'"') &&
  399.           !index(tmp2str->str_ptr,'\'') && !index(tmp2str->str_ptr,'"') )
  400.         numeric |= 2;
  401.     }
  402.     if (numeric & 2) {
  403.         if (numeric & 1)        /* numeric is very good guess */
  404.         str_cat(str," ");
  405.         else
  406.         str_cat(str,"\377");
  407.         numeric = 1;
  408.     }
  409.     else
  410.         str_cat(str," ");
  411.     str_scat(str,tmpstr);
  412.     str_free(tmpstr);
  413.     str_cat(str," ");
  414.     str_scat(str,tmp2str);
  415.     str_free(tmp2str);
  416.     numeric = 1;
  417.     break;
  418.     case ORPAREN:
  419.     str = str_new(0);
  420.     str_set(str,"(");
  421.     str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  422.     str_free(fstr);
  423.     numeric |= numarg;
  424.     str_cat(str,")");
  425.     break;
  426.     case OMATCHOP:
  427.     prec = P_MATCH;
  428.     str = walk(1,level,ops[node+2].ival,&numarg,prec+1);
  429.     str_cat(str," ");
  430.     tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  431.     if (strEQ(tmpstr->str_ptr,"~"))
  432.         str_cat(str,"=~");
  433.     else {
  434.         str_scat(str,tmpstr);
  435.         str_free(tmpstr);
  436.     }
  437.     str_cat(str," ");
  438.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  439.     str_free(fstr);
  440.     numeric = 1;
  441.     break;
  442.     case OMPAREN:
  443.     str = str_new(0);
  444.     str_set(str,"(");
  445.     str_scat(str,
  446.       fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  447.     str_free(fstr);
  448.     numeric |= numarg;
  449.     str_cat(str,")");
  450.     break;
  451.     case OCONCAT:
  452.     prec = P_ADD;
  453.     type = ops[ops[node+1].ival].ival & 255;
  454.     str = walk(1,level,ops[node+1].ival,&numarg,prec+(type != OCONCAT));
  455.     str_cat(str," . ");
  456.     type = ops[ops[node+2].ival].ival & 255;
  457.     str_scat(str,
  458.       fstr=walk(1,level,ops[node+2].ival,&numarg,prec+(type != OCONCAT)));
  459.     str_free(fstr);
  460.     break;
  461.     case OASSIGN:
  462.     prec = P_ASSIGN;
  463.     str = walk(0,level,ops[node+2].ival,&numarg,prec+1);
  464.     str_cat(str," ");
  465.     tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  466.     str_scat(str,tmpstr);
  467.     if (str_len(tmpstr) > 1)
  468.         numeric = 1;
  469.     str_free(tmpstr);
  470.     str_cat(str," ");
  471.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec));
  472.     str_free(fstr);
  473.     numeric |= numarg;
  474.     if (strEQ(str->str_ptr,"$/ = ''"))
  475.         str_set(str, "$/ = \"\\n\\n\"");
  476.     break;
  477.     case OADD:
  478.     prec = P_ADD;
  479.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  480.     str_cat(str," + ");
  481.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  482.     str_free(fstr);
  483.     numeric = 1;
  484.     break;
  485.     case OSUBTRACT:
  486.     prec = P_ADD;
  487.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  488.     str_cat(str," - ");
  489.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  490.     str_free(fstr);
  491.     numeric = 1;
  492.     break;
  493.     case OMULT:
  494.     prec = P_MUL;
  495.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  496.     str_cat(str," * ");
  497.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  498.     str_free(fstr);
  499.     numeric = 1;
  500.     break;
  501.     case ODIV:
  502.     prec = P_MUL;
  503.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  504.     str_cat(str," / ");
  505.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  506.     str_free(fstr);
  507.     numeric = 1;
  508.     break;
  509.     case OPOW:
  510.     prec = P_POW;
  511.     str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
  512.     str_cat(str," ** ");
  513.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec));
  514.     str_free(fstr);
  515.     numeric = 1;
  516.     break;
  517.     case OMOD:
  518.     prec = P_MUL;
  519.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  520.     str_cat(str," % ");
  521.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
  522.     str_free(fstr);
  523.     numeric = 1;
  524.     break;
  525.     case OPOSTINCR:
  526.     prec = P_AUTO;
  527.     str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
  528.     str_cat(str,"++");
  529.     numeric = 1;
  530.     break;
  531.     case OPOSTDECR:
  532.     prec = P_AUTO;
  533.     str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
  534.     str_cat(str,"--");
  535.     numeric = 1;
  536.     break;
  537.     case OPREINCR:
  538.     prec = P_AUTO;
  539.     str = str_new(0);
  540.     str_set(str,"++");
  541.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
  542.     str_free(fstr);
  543.     numeric = 1;
  544.     break;
  545.     case OPREDECR:
  546.     prec = P_AUTO;
  547.     str = str_new(0);
  548.     str_set(str,"--");
  549.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
  550.     str_free(fstr);
  551.     numeric = 1;
  552.     break;
  553.     case OUMINUS:
  554.     prec = P_UNARY;
  555.     str = str_new(0);
  556.     str_set(str,"-");
  557.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
  558.     str_free(fstr);
  559.     numeric = 1;
  560.     break;
  561.     case OUPLUS:
  562.     numeric = 1;
  563.     goto def;
  564.     case OPAREN:
  565.     str = str_new(0);
  566.     str_set(str,"(");
  567.     str_scat(str,
  568.       fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
  569.     str_free(fstr);
  570.     str_cat(str,")");
  571.     numeric |= numarg;
  572.     break;
  573.     case OGETLINE:
  574.     str = str_new(0);
  575.     if (useval)
  576.         str_cat(str,"(");
  577.     if (len > 0) {
  578.         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  579.         if (!*fstr->str_ptr) {
  580.         str_cat(str,"$_");
  581.         len = 2;        /* a legal fiction */
  582.         }
  583.         str_free(fstr);
  584.     }
  585.     else
  586.         str_cat(str,"$_");
  587.     if (len > 1) {
  588.         tmpstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN);
  589.         fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  590.         if (!do_fancy_opens) {
  591.         t = tmpstr->str_ptr;
  592.         if (*t == '"' || *t == '\'')
  593.             t = cpytill(tokenbuf,t+1,*t);
  594.         else
  595.             fatal("Internal error: OGETLINE %s", t);
  596.         d = savestr(t);
  597.         s = savestr(tokenbuf);
  598.         for (t = tokenbuf; *t; t++) {
  599.             *t &= 127;
  600.             if (islower(*t))
  601.             *t = toupper(*t);
  602.             if (!isalpha(*t) && !isdigit(*t))
  603.             *t = '_';
  604.         }
  605.         if (!index(tokenbuf,'_'))
  606.             strcpy(t,"_FH");
  607.         tmp3str = hfetch(symtab,tokenbuf);
  608.         if (!tmp3str) {
  609.             do_opens = TRUE;
  610.             str_cat(opens,"open(");
  611.             str_cat(opens,tokenbuf);
  612.             str_cat(opens,", ");
  613.             d[1] = '\0';
  614.             str_cat(opens,d);
  615.             str_cat(opens,tmpstr->str_ptr+1);
  616.             opens->str_cur--;
  617.             if (*fstr->str_ptr == '|')
  618.             str_cat(opens,"|");
  619.             str_cat(opens,d);
  620.             if (*fstr->str_ptr == '|')
  621.             str_cat(opens,") || die 'Cannot pipe from \"");
  622.             else
  623.             str_cat(opens,") || die 'Cannot open file \"");
  624.             if (*d == '"')
  625.             str_cat(opens,"'.\"");
  626.             str_cat(opens,s);
  627.             if (*d == '"')
  628.             str_cat(opens,"\".'");
  629.             str_cat(opens,"\".';\n");
  630.             hstore(symtab,tokenbuf,str_make("x"));
  631.         }
  632.         safefree(s);
  633.         safefree(d);
  634.         str_set(tmpstr,"'");
  635.         str_cat(tmpstr,tokenbuf);
  636.         str_cat(tmpstr,"'");
  637.         }
  638.         if (*fstr->str_ptr == '|')
  639.         str_cat(tmpstr,", '|'");
  640.         str_free(fstr);
  641.     }
  642.     else
  643.         tmpstr = str_make("");
  644.     sprintf(tokenbuf," = &Getline%d(%s)",len,tmpstr->str_ptr);
  645.     str_cat(str,tokenbuf); 
  646.     str_free(tmpstr);
  647.     if (useval)
  648.         str_cat(str,",$getline_ok)");
  649.     saw_getline |= 1 << len;
  650.     break;
  651.     case OSPRINTF:
  652.     str = str_new(0);
  653.     str_set(str,"sprintf(");
  654.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  655.     str_free(fstr);
  656.     str_cat(str,")");
  657.     break;
  658.     case OSUBSTR:
  659.     str = str_new(0);
  660.     str_set(str,"substr(");
  661.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
  662.     str_free(fstr);
  663.     str_cat(str,", ");
  664.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
  665.     str_free(fstr);
  666.     str_cat(str,", ");
  667.     if (len == 3) {
  668.         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1));
  669.         str_free(fstr);
  670.     }
  671.     else
  672.         str_cat(str,"999999");
  673.     str_cat(str,")");
  674.     break;
  675.     case OSTRING:
  676.     str = str_new(0);
  677.     str_set(str,ops[node+1].cval);
  678.     break;
  679.     case OSPLIT:
  680.     str = str_new(0);
  681.     limit = ", 9999)";
  682.     numeric = 1;
  683.     tmpstr = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  684.     if (useval)
  685.         str_set(str,"(@");
  686.     else
  687.         str_set(str,"@");
  688.     str_scat(str,tmpstr);
  689.     str_cat(str," = split(");
  690.     if (len == 3) {
  691.         fstr = walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1);
  692.         if (str_len(fstr) == 3 && *fstr->str_ptr == '\'') {
  693.         i = fstr->str_ptr[1] & 127;
  694.         if (index("*+?.[]()|^$\\",i))
  695.             sprintf(tokenbuf,"/\\%c/",i);
  696.         else if (i == ' ')
  697.             sprintf(tokenbuf,"' '");
  698.         else
  699.             sprintf(tokenbuf,"/%c/",i);
  700.         str_cat(str,tokenbuf);
  701.         }
  702.         else
  703.         str_scat(str,fstr);
  704.         str_free(fstr);
  705.     }
  706.     else if (const_FS) {
  707.         sprintf(tokenbuf,"/[%c\\n]/",const_FS);
  708.         str_cat(str,tokenbuf);
  709.     }
  710.     else if (saw_FS)
  711.         str_cat(str,"$FS");
  712.     else {
  713.         str_cat(str,"' '");
  714.         limit = ")";
  715.     }
  716.     str_cat(str,", ");
  717.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
  718.     str_free(fstr);
  719.     str_cat(str,limit);
  720.     if (useval) {
  721.         str_cat(str,")");
  722.     }
  723.     str_free(tmpstr);
  724.     break;
  725.     case OINDEX:
  726.     str = str_new(0);
  727.     str_set(str,"index(");
  728.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
  729.     str_free(fstr);
  730.     str_cat(str,", ");
  731.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
  732.     str_free(fstr);
  733.     str_cat(str,")");
  734.     numeric = 1;
  735.     break;
  736.     case OMATCH:
  737.     str = str_new(0);
  738.     prec = P_ANDAND;
  739.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MATCH+1));
  740.     str_free(fstr);
  741.     str_cat(str," =~ ");
  742.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MATCH+1));
  743.     str_free(fstr);
  744.     str_cat(str," && ($RLENGTH = length($&), $RSTART = length($`)+1)");
  745.     numeric = 1;
  746.     break;
  747.     case OUSERDEF:
  748.     str = str_new(0);
  749.     subretnum = FALSE;
  750.     fstr=walk(1,level-1,ops[node+2].ival,&numarg,P_MIN);
  751.     curargs = str_new(0);
  752.     str_sset(curargs,fstr);
  753.     str_cat(curargs,",");
  754.     tmp2str=walk(1,level,ops[node+5].ival,&numarg,P_MIN);
  755.     str_free(curargs);
  756.     curargs = Nullstr;
  757.     level--;
  758.     subretnum |= numarg;
  759.     s = Nullch;
  760.     t = tmp2str->str_ptr;
  761.     while (t = instr(t,"return "))
  762.         s = t++;
  763.     if (s) {
  764.         i = 0;
  765.         for (t = s+7; *t; t++) {
  766.         if (*t == ';' || *t == '}')
  767.             i++;
  768.         }
  769.         if (i == 1) {
  770.         strcpy(s,s+7);
  771.         tmp2str->str_cur -= 7;
  772.         }
  773.     }
  774.     str_set(str,"\n");
  775.     tab(str,level);
  776.     str_cat(str,"sub ");
  777.     str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  778.     str_cat(str," {\n");
  779.     tab(str,++level);
  780.     if (fstr->str_cur) {
  781.         str_cat(str,"local(");
  782.         str_scat(str,fstr);
  783.         str_cat(str,") = @_;");
  784.     }
  785.     str_free(fstr);
  786.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
  787.     str_free(fstr);
  788.     fixtab(str,level);
  789.     str_scat(str,fstr=walk(1,level,ops[node+4].ival,&numarg,P_MIN));
  790.     str_free(fstr);
  791.     fixtab(str,level);
  792.     str_scat(str,tmp2str);
  793.     str_free(tmp2str);
  794.     fixtab(str,--level);
  795.     str_cat(str,"}\n");
  796.     tab(str,level);
  797.     str_scat(subs,str);
  798.     str_set(str,"");
  799.     str_cat(tmpstr,"(");
  800.     tmp2str = str_new(0);
  801.     if (subretnum)
  802.         str_set(tmp2str,"1");
  803.     hstore(symtab,tmpstr->str_ptr,tmp2str);
  804.     str_free(tmpstr);
  805.     level++;
  806.     break;
  807.     case ORETURN:
  808.     str = str_new(0);
  809.     if (len > 0) {
  810.         str_cat(str,"return ");
  811.         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_UNI+1));
  812.         str_free(fstr);
  813.         if (numarg)
  814.         subretnum = TRUE;
  815.     }
  816.     else
  817.         str_cat(str,"return");
  818.     break;
  819.     case OUSERFUN:
  820.     str = str_new(0);
  821.     str_set(str,"&");
  822.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  823.     str_free(fstr);
  824.     str_cat(str,"(");
  825.     tmpstr = hfetch(symtab,str->str_ptr+3);
  826.     if (tmpstr && tmpstr->str_ptr)
  827.         numeric |= atoi(tmpstr->str_ptr);
  828.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
  829.     str_free(fstr);
  830.     str_cat(str,")");
  831.     break;
  832.     case OGSUB:
  833.     case OSUB:
  834.     if (type == OGSUB)
  835.         s = "g";
  836.     else
  837.         s = "";
  838.     str = str_new(0);
  839.     tmpstr = str_new(0);
  840.     i = 0;
  841.     if (len == 3) {
  842.         tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MATCH+1);
  843.         if (strNE(tmpstr->str_ptr,"$_")) {
  844.         str_cat(tmpstr, " =~ s");
  845.         i++;
  846.         }
  847.         else
  848.         str_set(tmpstr, "s");
  849.     }
  850.     else
  851.         str_set(tmpstr, "s");
  852.     type = ops[ops[node+2].ival].ival;
  853.     len = type >> 8;
  854.     type &= 255;
  855.     tmp3str = str_new(0);
  856.     if (type == OSTR) {
  857.         tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg,P_MIN);
  858.         for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) {
  859.         if (*t == '&')
  860.             *d++ = '$' + 128;
  861.         else if (*t == '$')
  862.             *d++ = '\\' + 128;
  863.         *d = *t + 128;
  864.         }
  865.         *d = '\0';
  866.         str_set(tmp2str,tokenbuf);
  867.     }
  868.     else {
  869.         tmp2str=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  870.         str_set(tmp3str,"($s_ = '\"'.(");
  871.         str_scat(tmp3str,tmp2str);
  872.         str_cat(tmp3str,").'\"') =~ s/&/\\$&/g, ");
  873.         str_set(tmp2str,"eval $s_");
  874.         s = (*s == 'g' ? "ge" : "e");
  875.         i++;
  876.     }
  877.     type = ops[ops[node+1].ival].ival;
  878.     len = type >> 8;
  879.     type &= 255;
  880.     fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  881.     if (type == OREGEX) {
  882.         if (useval && i)
  883.         str_cat(str,"(");
  884.         str_scat(str,tmp3str);
  885.         str_scat(str,tmpstr);
  886.         str_scat(str,fstr);
  887.         str_scat(str,tmp2str);
  888.         str_cat(str,"/");
  889.         str_cat(str,s);
  890.     }
  891.     else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) {
  892.         if (useval && i)
  893.         str_cat(str,"(");
  894.         str_scat(str,tmp3str);
  895.         str_scat(str,tmpstr);
  896.         str_cat(str,"/");
  897.         str_scat(str,fstr);
  898.         str_cat(str,"/");
  899.         str_scat(str,tmp2str);
  900.         str_cat(str,"/");
  901.         str_cat(str,s);
  902.     }
  903.     else {
  904.         i++;
  905.         if (useval)
  906.         str_cat(str,"(");
  907.         str_cat(str,"$s = ");
  908.         str_scat(str,fstr);
  909.         str_cat(str,", ");
  910.         str_scat(str,tmp3str);
  911.         str_scat(str,tmpstr);
  912.         str_cat(str,"/$s/");
  913.         str_scat(str,tmp2str);
  914.         str_cat(str,"/");
  915.         str_cat(str,s);
  916.     }
  917.     if (useval && i)
  918.         str_cat(str,")");
  919.     str_free(fstr);
  920.     str_free(tmpstr);
  921.     str_free(tmp2str);
  922.     str_free(tmp3str);
  923.     numeric = 1;
  924.     break;
  925.     case ONUM:
  926.     str = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  927.     numeric = 1;
  928.     break;
  929.     case OSTR:
  930.     tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  931.     s = "'";
  932.     for (t = tmpstr->str_ptr, d=tokenbuf; *t; d++,t++) {
  933.         if (*t == '\'')
  934.         s = "\"";
  935.         else if (*t == '\\') {
  936.         s = "\"";
  937.         *d++ = *t++ + 128;
  938.         switch (*t) {
  939.         case '\\': case '"': case 'n': case 't': case '$':
  940.             break;
  941.         default:    /* hide this from perl */
  942.             *d++ = '\\' + 128;
  943.         }
  944.         }
  945.         *d = *t + 128;
  946.     }
  947.     *d = '\0';
  948.     str = str_new(0);
  949.     str_set(str,s);
  950.     str_cat(str,tokenbuf);
  951.     str_free(tmpstr);
  952.     str_cat(str,s);
  953.     break;
  954.     case ODEFINED:
  955.     prec = P_UNI;
  956.     str = str_new(0);
  957.     str_set(str,"defined $");
  958.     goto addvar;
  959.     case ODELETE:
  960.     str = str_new(0);
  961.     str_set(str,"delete $");
  962.     goto addvar;
  963.     case OSTAR:
  964.     str = str_new(0);
  965.     str_set(str,"*");
  966.     goto addvar;
  967.     case OVAR:
  968.     str = str_new(0);
  969.     str_set(str,"$");
  970.       addvar:
  971.     str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  972.     if (len == 1) {
  973.         tmp2str = hfetch(symtab,tmpstr->str_ptr);
  974.         if (tmp2str && atoi(tmp2str->str_ptr))
  975.         numeric = 2;
  976.         if (strEQ(str->str_ptr,"$FNR")) {
  977.         numeric = 1;
  978.         saw_FNR++;
  979.         str_set(str,"($.-$FNRbase)");
  980.         }
  981.         else if (strEQ(str->str_ptr,"$NR")) {
  982.         numeric = 1;
  983.         str_set(str,"$.");
  984.         }
  985.         else if (strEQ(str->str_ptr,"$NF")) {
  986.         numeric = 1;
  987.         str_set(str,"$#Fld");
  988.         }
  989.         else if (strEQ(str->str_ptr,"$0"))
  990.         str_set(str,"$_");
  991.         else if (strEQ(str->str_ptr,"$ARGC"))
  992.         str_set(str,"($#ARGV+1)");
  993.     }
  994.     else {
  995. #ifdef NOTDEF
  996.         if (curargs) {
  997.         sprintf(tokenbuf,"$%s,",tmpstr->str_ptr);
  998.     ???    if (instr(curargs->str_ptr,tokenbuf))
  999.             str_cat(str,"\377");    /* can't translate yet */
  1000.         }
  1001. #endif
  1002.         str_cat(tmpstr,"[]");
  1003.         tmp2str = hfetch(symtab,tmpstr->str_ptr);
  1004.         if (tmp2str && atoi(tmp2str->str_ptr))
  1005.         str_cat(str,"[");
  1006.         else
  1007.         str_cat(str,"{");
  1008.         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
  1009.         str_free(fstr);
  1010.         if (strEQ(str->str_ptr,"$ARGV[0")) {
  1011.         str_set(str,"$ARGV0");
  1012.         saw_argv0++;
  1013.         }
  1014.         else {
  1015.         if (tmp2str && atoi(tmp2str->str_ptr))
  1016.             strcpy(tokenbuf,"]");
  1017.         else
  1018.             strcpy(tokenbuf,"}");
  1019.         *tokenbuf += 128;
  1020.         str_cat(str,tokenbuf);
  1021.         }
  1022.     }
  1023.     str_free(tmpstr);
  1024.     break;
  1025.     case OFLD:
  1026.     str = str_new(0);
  1027.     if (split_to_array) {
  1028.         str_set(str,"$Fld");
  1029.         str_cat(str,"[");
  1030.         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1031.         str_free(fstr);
  1032.         str_cat(str,"]");
  1033.     }
  1034.     else {
  1035.         i = atoi(walk(1,level,ops[node+1].ival,&numarg,P_MIN)->str_ptr);
  1036.         if (i <= arymax)
  1037.         sprintf(tokenbuf,"$%s",nameary[i]);
  1038.         else
  1039.         sprintf(tokenbuf,"$Fld%d",i);
  1040.         str_set(str,tokenbuf);
  1041.     }
  1042.     break;
  1043.     case OVFLD:
  1044.     str = str_new(0);
  1045.     str_set(str,"$Fld[");
  1046.     i = ops[node+1].ival;
  1047.     if ((ops[i].ival & 255) == OPAREN)
  1048.         i = ops[i+1].ival;
  1049.     tmpstr=walk(1,level,i,&numarg,P_MIN);
  1050.     str_scat(str,tmpstr);
  1051.     str_free(tmpstr);
  1052.     str_cat(str,"]");
  1053.     break;
  1054.     case OJUNK:
  1055.     goto def;
  1056.     case OSNEWLINE:
  1057.     str = str_new(2);
  1058.     str_set(str,";\n");
  1059.     tab(str,level);
  1060.     break;
  1061.     case ONEWLINE:
  1062.     str = str_new(1);
  1063.     str_set(str,"\n");
  1064.     tab(str,level);
  1065.     break;
  1066.     case OSCOMMENT:
  1067.     str = str_new(0);
  1068.     str_set(str,";");
  1069.     tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1070.     for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
  1071.         *s += 128;
  1072.     str_scat(str,tmpstr);
  1073.     str_free(tmpstr);
  1074.     tab(str,level);
  1075.     break;
  1076.     case OCOMMENT:
  1077.     str = str_new(0);
  1078.     tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1079.     for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
  1080.         *s += 128;
  1081.     str_scat(str,tmpstr);
  1082.     str_free(tmpstr);
  1083.     tab(str,level);
  1084.     break;
  1085.     case OCOMMA:
  1086.     prec = P_COMMA;
  1087.     str = walk(1,level,ops[node+1].ival,&numarg,prec);
  1088.     str_cat(str,", ");
  1089.     str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
  1090.     str_free(fstr);
  1091.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
  1092.     str_free(fstr);
  1093.     break;
  1094.     case OSEMICOLON:
  1095.     str = str_new(1);
  1096.     str_set(str,";\n");
  1097.     tab(str,level);
  1098.     break;
  1099.     case OSTATES:
  1100.     str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1101.     str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1102.     str_free(fstr);
  1103.     break;
  1104.     case OSTATE:
  1105.     str = str_new(0);
  1106.     if (len >= 1) {
  1107.         str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
  1108.         str_free(fstr);
  1109.         if (len >= 2) {
  1110.         tmpstr = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
  1111.         if (*tmpstr->str_ptr == ';') {
  1112.             addsemi(str);
  1113.             str_cat(str,tmpstr->str_ptr+1);
  1114.         }
  1115.         str_free(tmpstr);
  1116.         }
  1117.     }
  1118.     break;
  1119.     case OCLOSE:
  1120.     str = str_make("close(");
  1121.     tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  1122.     if (!do_fancy_opens) {
  1123.         t = tmpstr->str_ptr;
  1124.         if (*t == '"' || *t == '\'')
  1125.         t = cpytill(tokenbuf,t+1,*t);
  1126.         else
  1127.         fatal("Internal error: OCLOSE %s",t);
  1128.         s = savestr(tokenbuf);
  1129.         for (t = tokenbuf; *t; t++) {
  1130.         *t &= 127;
  1131.         if (islower(*t))
  1132.             *t = toupper(*t);
  1133.         if (!isalpha(*t) && !isdigit(*t))
  1134.             *t = '_';
  1135.         }
  1136.         if (!index(tokenbuf,'_'))
  1137.         strcpy(t,"_FH");
  1138.         str_free(tmpstr);
  1139.         safefree(s);
  1140.         str_set(str,"close ");
  1141.         str_cat(str,tokenbuf);
  1142.     }
  1143.     else {
  1144.         sprintf(tokenbuf,"delete $opened{%s} && close(%s)",
  1145.            tmpstr->str_ptr, tmpstr->str_ptr);
  1146.         str_free(tmpstr);
  1147.         str_set(str,tokenbuf);
  1148.     }
  1149.     break;
  1150.     case OPRINTF:
  1151.     case OPRINT:
  1152.     lparen = "";    /* set to parens if necessary */
  1153.     rparen = "";
  1154.     str = str_new(0);
  1155.     if (len == 3) {        /* output redirection */
  1156.         tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MIN);
  1157.         tmp2str = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  1158.         if (!do_fancy_opens) {
  1159.         t = tmpstr->str_ptr;
  1160.         if (*t == '"' || *t == '\'')
  1161.             t = cpytill(tokenbuf,t+1,*t);
  1162.         else
  1163.             fatal("Internal error: OPRINT");
  1164.         d = savestr(t);
  1165.         s = savestr(tokenbuf);
  1166.         for (t = tokenbuf; *t; t++) {
  1167.             *t &= 127;
  1168.             if (islower(*t))
  1169.             *t = toupper(*t);
  1170.             if (!isalpha(*t) && !isdigit(*t))
  1171.             *t = '_';
  1172.         }
  1173.         if (!index(tokenbuf,'_'))
  1174.             strcpy(t,"_FH");
  1175.         tmp3str = hfetch(symtab,tokenbuf);
  1176.         if (!tmp3str) {
  1177.             str_cat(opens,"open(");
  1178.             str_cat(opens,tokenbuf);
  1179.             str_cat(opens,", ");
  1180.             d[1] = '\0';
  1181.             str_cat(opens,d);
  1182.             str_scat(opens,tmp2str);
  1183.             str_cat(opens,tmpstr->str_ptr+1);
  1184.             if (*tmp2str->str_ptr == '|')
  1185.             str_cat(opens,") || die 'Cannot pipe to \"");
  1186.             else
  1187.             str_cat(opens,") || die 'Cannot create file \"");
  1188.             if (*d == '"')
  1189.             str_cat(opens,"'.\"");
  1190.             str_cat(opens,s);
  1191.             if (*d == '"')
  1192.             str_cat(opens,"\".'");
  1193.             str_cat(opens,"\".';\n");
  1194.             hstore(symtab,tokenbuf,str_make("x"));
  1195.         }
  1196.         str_free(tmpstr);
  1197.         str_free(tmp2str);
  1198.         safefree(s);
  1199.         safefree(d);
  1200.         }
  1201.         else {
  1202.         sprintf(tokenbuf,"&Pick('%s', %s) &&\n",
  1203.            tmp2str->str_ptr, tmpstr->str_ptr);
  1204.         str_cat(str,tokenbuf);
  1205.         tab(str,level+1);
  1206.         strcpy(tokenbuf,"$fh");
  1207.         str_free(tmpstr);
  1208.         str_free(tmp2str);
  1209.         lparen = "(";
  1210.         rparen = ")";
  1211.         }
  1212.     }
  1213.     else
  1214.         strcpy(tokenbuf,"");
  1215.     str_cat(str,lparen);    /* may be null */
  1216.     if (type == OPRINTF)
  1217.         str_cat(str,"printf");
  1218.     else
  1219.         str_cat(str,"print");
  1220.     saw_fh = 0;
  1221.     if (len == 3 || do_fancy_opens) {
  1222.         if (*tokenbuf) {
  1223.         str_cat(str," ");
  1224.         saw_fh = 1;
  1225.         }
  1226.         str_cat(str,tokenbuf);
  1227.     }
  1228.     tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg,P_MIN);
  1229.     if (!*tmpstr->str_ptr && lval_field) {
  1230.         t = saw_OFS ? "$," : "' '";
  1231.         if (split_to_array) {
  1232.         sprintf(tokenbuf,"join(%s,@Fld)",t);
  1233.         str_cat(tmpstr,tokenbuf);
  1234.         }
  1235.         else {
  1236.         for (i = 1; i < maxfld; i++) {
  1237.             if (i <= arymax)
  1238.             sprintf(tokenbuf,"$%s, ",nameary[i]);
  1239.             else
  1240.             sprintf(tokenbuf,"$Fld%d, ",i);
  1241.             str_cat(tmpstr,tokenbuf);
  1242.         }
  1243.         if (maxfld <= arymax)
  1244.             sprintf(tokenbuf,"$%s",nameary[maxfld]);
  1245.         else
  1246.             sprintf(tokenbuf,"$Fld%d",maxfld);
  1247.         str_cat(tmpstr,tokenbuf);
  1248.         }
  1249.     }
  1250.     if (*tmpstr->str_ptr) {
  1251.         str_cat(str," ");
  1252.         if (!saw_fh && *tmpstr->str_ptr == '(') {
  1253.         str_cat(str,"(");
  1254.         str_scat(str,tmpstr);
  1255.         str_cat(str,")");
  1256.         }
  1257.         else
  1258.         str_scat(str,tmpstr);
  1259.     }
  1260.     else {
  1261.         str_cat(str," $_");
  1262.     }
  1263.     str_cat(str,rparen);    /* may be null */
  1264.     str_free(tmpstr);
  1265.     break;
  1266.     case ORAND:
  1267.     str = str_make("rand(1)");
  1268.     break;
  1269.     case OSRAND:
  1270.     str = str_make("srand(");
  1271.     goto maybe0;
  1272.     case OATAN2:
  1273.     str = str_make("atan2(");
  1274.     goto maybe0;
  1275.     case OSIN:
  1276.     str = str_make("sin(");
  1277.     goto maybe0;
  1278.     case OCOS:
  1279.     str = str_make("cos(");
  1280.     goto maybe0;
  1281.     case OSYSTEM:
  1282.     str = str_make("system(");
  1283.     goto maybe0;
  1284.     case OLENGTH:
  1285.     str = str_make("length(");
  1286.     goto maybe0;
  1287.     case OLOG:
  1288.     str = str_make("log(");
  1289.     goto maybe0;
  1290.     case OEXP:
  1291.     str = str_make("exp(");
  1292.     goto maybe0;
  1293.     case OSQRT:
  1294.     str = str_make("sqrt(");
  1295.     goto maybe0;
  1296.     case OINT:
  1297.     str = str_make("int(");
  1298.       maybe0:
  1299.     numeric = 1;
  1300.     if (len > 0)
  1301.         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
  1302.     else
  1303.         tmpstr = str_new(0);;
  1304.     if (!tmpstr->str_ptr || !*tmpstr->str_ptr) {
  1305.         if (lval_field) {
  1306.         t = saw_OFS ? "$," : "' '";
  1307.         if (split_to_array) {
  1308.             sprintf(tokenbuf,"join(%s,@Fld)",t);
  1309.             str_cat(tmpstr,tokenbuf);
  1310.         }
  1311.         else {
  1312.             sprintf(tokenbuf,"join(%s, ",t);
  1313.             str_cat(tmpstr,tokenbuf);
  1314.             for (i = 1; i < maxfld; i++) {
  1315.             if (i <= arymax)
  1316.                 sprintf(tokenbuf,"$%s,",nameary[i]);
  1317.             else
  1318.                 sprintf(tokenbuf,"$Fld%d,",i);
  1319.             str_cat(tmpstr,tokenbuf);
  1320.             }
  1321.             if (maxfld <= arymax)
  1322.             sprintf(tokenbuf,"$%s)",nameary[maxfld]);
  1323.             else
  1324.             sprintf(tokenbuf,"$Fld%d)",maxfld);
  1325.             str_cat(tmpstr,tokenbuf);
  1326.         }
  1327.         }
  1328.         else
  1329.         str_cat(tmpstr,"$_");
  1330.     }
  1331.     if (strEQ(tmpstr->str_ptr,"$_")) {
  1332.         if (type == OLENGTH && !do_chop) {
  1333.         str = str_make("(length(");
  1334.         str_cat(tmpstr,") - 1");
  1335.         }
  1336.     }
  1337.     str_scat(str,tmpstr);
  1338.     str_free(tmpstr);
  1339.     str_cat(str,")");
  1340.     break;
  1341.     case OBREAK:
  1342.     str = str_new(0);
  1343.     str_set(str,"last");
  1344.     break;
  1345.     case ONEXT:
  1346.     str = str_new(0);
  1347.     str_set(str,"next line");
  1348.     break;
  1349.     case OEXIT:
  1350.     str = str_new(0);
  1351.     if (realexit) {
  1352.         prec = P_UNI;
  1353.         str_set(str,"exit");
  1354.         if (len == 1) {
  1355.         str_cat(str," ");
  1356.         exitval = TRUE;
  1357.         str_scat(str,
  1358.           fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
  1359.         str_free(fstr);
  1360.         }
  1361.     }
  1362.     else {
  1363.         if (len == 1) {
  1364.         str_set(str,"$ExitValue = ");
  1365.         exitval = TRUE;
  1366.         str_scat(str,
  1367.           fstr=walk(1,level,ops[node+1].ival,&numarg,P_ASSIGN));
  1368.         str_free(fstr);
  1369.         str_cat(str,"; ");
  1370.         }
  1371.         str_cat(str,"last line");
  1372.     }
  1373.     break;
  1374.     case OCONTINUE:
  1375.     str = str_new(0);
  1376.     str_set(str,"next");
  1377.     break;
  1378.     case OREDIR:
  1379.     goto def;
  1380.     case OIF:
  1381.     str = str_new(0);
  1382.     str_set(str,"if (");
  1383.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1384.     str_free(fstr);
  1385.     str_cat(str,") ");
  1386.     str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1387.     str_free(fstr);
  1388.     if (len == 3) {
  1389.         i = ops[node+3].ival;
  1390.         if (i) {
  1391.         if ((ops[i].ival & 255) == OBLOCK) {
  1392.             i = ops[i+1].ival;
  1393.             if (i) {
  1394.             if ((ops[i].ival & 255) != OIF)
  1395.                 i = 0;
  1396.             }
  1397.         }
  1398.         else
  1399.             i = 0;
  1400.         }
  1401.         if (i) {
  1402.         str_cat(str,"els");
  1403.         str_scat(str,fstr=walk(0,level,i,&numarg,P_MIN));
  1404.         str_free(fstr);
  1405.         }
  1406.         else {
  1407.         str_cat(str,"else ");
  1408.         str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
  1409.         str_free(fstr);
  1410.         }
  1411.     }
  1412.     break;
  1413.     case OWHILE:
  1414.     str = str_new(0);
  1415.     str_set(str,"while (");
  1416.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1417.     str_free(fstr);
  1418.     str_cat(str,") ");
  1419.     str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1420.     str_free(fstr);
  1421.     break;
  1422.     case ODO:
  1423.     str = str_new(0);
  1424.     str_set(str,"do ");
  1425.     str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1426.     str_free(fstr);
  1427.     if (str->str_ptr[str->str_cur - 1] == '\n')
  1428.         --str->str_cur;;
  1429.     str_cat(str," while (");
  1430.     str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1431.     str_free(fstr);
  1432.     str_cat(str,");");
  1433.     break;
  1434.     case OFOR:
  1435.     str = str_new(0);
  1436.     str_set(str,"for (");
  1437.     str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1438.     i = numarg;
  1439.     if (i) {
  1440.         t = s = tmpstr->str_ptr;
  1441.         while (isalpha(*t) || isdigit(*t) || *t == '$' || *t == '_')
  1442.         t++;
  1443.         i = t - s;
  1444.         if (i < 2)
  1445.         i = 0;
  1446.     }
  1447.     str_cat(str,"; ");
  1448.     fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
  1449.     if (i && (t = index(fstr->str_ptr,0377))) {
  1450.         if (strnEQ(fstr->str_ptr,s,i))
  1451.         *t = ' ';
  1452.     }
  1453.     str_scat(str,fstr);
  1454.     str_free(fstr);
  1455.     str_free(tmpstr);
  1456.     str_cat(str,"; ");
  1457.     str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
  1458.     str_free(fstr);
  1459.     str_cat(str,") ");
  1460.     str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
  1461.     str_free(fstr);
  1462.     break;
  1463.     case OFORIN:
  1464.     tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1465.     d = index(tmpstr->str_ptr,'$');
  1466.     if (!d)
  1467.         fatal("Illegal for loop: %s",tmpstr->str_ptr);
  1468.     s = index(d,'{');
  1469.     if (!s)
  1470.         s = index(d,'[');
  1471.     if (!s)
  1472.         fatal("Illegal for loop: %s",d);
  1473.     *s++ = '\0';
  1474.     for (t = s; i = *t; t++) {
  1475.         i &= 127;
  1476.         if (i == '}' || i == ']')
  1477.         break;
  1478.     }
  1479.     if (*t)
  1480.         *t = '\0';
  1481.     str = str_new(0);
  1482.     str_set(str,d+1);
  1483.     str_cat(str,"[]");
  1484.     tmp2str = hfetch(symtab,str->str_ptr);
  1485.     if (tmp2str && atoi(tmp2str->str_ptr)) {
  1486.         sprintf(tokenbuf,
  1487.           "foreach %s ($[ .. $#%s) ",
  1488.           s,
  1489.           d+1);
  1490.     }
  1491.     else {
  1492.         sprintf(tokenbuf,
  1493.           "foreach %s (keys %%%s) ",
  1494.           s,
  1495.           d+1);
  1496.     }
  1497.     str_set(str,tokenbuf);
  1498.     str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1499.     str_free(fstr);
  1500.     str_free(tmpstr);
  1501.     break;
  1502.     case OBLOCK:
  1503.     str = str_new(0);
  1504.     str_set(str,"{");
  1505.     if (len >= 2 && ops[node+2].ival) {
  1506.         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
  1507.         str_free(fstr);
  1508.     }
  1509.     fixtab(str,++level);
  1510.     str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
  1511.     str_free(fstr);
  1512.     addsemi(str);
  1513.     fixtab(str,--level);
  1514.     str_cat(str,"}\n");
  1515.     tab(str,level);
  1516.     if (len >= 3) {
  1517.         str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
  1518.         str_free(fstr);
  1519.     }
  1520.     break;
  1521.     default:
  1522.       def:
  1523.     if (len) {
  1524.         if (len > 5)
  1525.         fatal("Garbage length in walk");
  1526.         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1527.         for (i = 2; i<= len; i++) {
  1528.         str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg,P_MIN));
  1529.         str_free(fstr);
  1530.         }
  1531.     }
  1532.     else {
  1533.         str = Nullstr;
  1534.     }
  1535.     break;
  1536.     }
  1537.     if (!str)
  1538.     str = str_new(0);
  1539.  
  1540.     if (useval && prec < minprec) {        /* need parens? */
  1541.     fstr = str_new(str->str_cur+2);
  1542.     str_nset(fstr,"(",1);
  1543.     str_scat(fstr,str);
  1544.     str_ncat(fstr,")",1);
  1545.     str_free(str);
  1546.     str = fstr;
  1547.     }
  1548.  
  1549.     *numericptr = numeric;
  1550. #ifdef DEBUGGING
  1551.     if (debug & 4) {
  1552.     printf("%3d %5d %15s %d %4d ",level,node,opname[type],len,str->str_cur);
  1553.     for (t = str->str_ptr; *t && t - str->str_ptr < 40; t++)
  1554.         if (*t == '\n')
  1555.         printf("\\n");
  1556.         else if (*t == '\t')
  1557.         printf("\\t");
  1558.         else
  1559.         putchar(*t);
  1560.     putchar('\n');
  1561.     }
  1562. #endif
  1563.     return str;
  1564. }
  1565.  
  1566. tab(str,lvl)
  1567. register STR *str;
  1568. register int lvl;
  1569. {
  1570.     while (lvl > 1) {
  1571.     str_cat(str,"\t");
  1572.     lvl -= 2;
  1573.     }
  1574.     if (lvl)
  1575.     str_cat(str,"    ");
  1576. }
  1577.  
  1578. fixtab(str,lvl)
  1579. register STR *str;
  1580. register int lvl;
  1581. {
  1582.     register char *s;
  1583.  
  1584.     /* strip trailing white space */
  1585.  
  1586.     s = str->str_ptr+str->str_cur - 1;
  1587.     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
  1588.     s--;
  1589.     s[1] = '\0';
  1590.     str->str_cur = s + 1 - str->str_ptr;
  1591.     if (s >= str->str_ptr && *s != '\n')
  1592.     str_cat(str,"\n");
  1593.  
  1594.     tab(str,lvl);
  1595. }
  1596.  
  1597. addsemi(str)
  1598. register STR *str;
  1599. {
  1600.     register char *s;
  1601.  
  1602.     s = str->str_ptr+str->str_cur - 1;
  1603.     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
  1604.     s--;
  1605.     if (s >= str->str_ptr && *s != ';' && *s != '}')
  1606.     str_cat(str,";");
  1607. }
  1608.  
  1609. emit_split(str,level)
  1610. register STR *str;
  1611. int level;
  1612. {
  1613.     register int i;
  1614.  
  1615.     if (split_to_array)
  1616.     str_cat(str,"@Fld");
  1617.     else {
  1618.     str_cat(str,"(");
  1619.     for (i = 1; i < maxfld; i++) {
  1620.         if (i <= arymax)
  1621.         sprintf(tokenbuf,"$%s,",nameary[i]);
  1622.         else
  1623.         sprintf(tokenbuf,"$Fld%d,",i);
  1624.         str_cat(str,tokenbuf);
  1625.     }
  1626.     if (maxfld <= arymax)
  1627.         sprintf(tokenbuf,"$%s)",nameary[maxfld]);
  1628.     else
  1629.         sprintf(tokenbuf,"$Fld%d)",maxfld);
  1630.     str_cat(str,tokenbuf);
  1631.     }
  1632.     if (const_FS) {
  1633.     sprintf(tokenbuf," = split(/[%c\\n]/, $_, 9999);\n",const_FS);
  1634.     str_cat(str,tokenbuf);
  1635.     }
  1636.     else if (saw_FS)
  1637.     str_cat(str," = split($FS, $_, 9999);\n");
  1638.     else
  1639.     str_cat(str," = split(' ', $_, 9999);\n");
  1640.     tab(str,level);
  1641. }
  1642.  
  1643. prewalk(numit,level,node,numericptr)
  1644. int numit;
  1645. int level;
  1646. register int node;
  1647. int *numericptr;
  1648. {
  1649.     register int len;
  1650.     register int type;
  1651.     register int i;
  1652.     char *t;
  1653.     char *d, *s;
  1654.     int numarg;
  1655.     int numeric = FALSE;
  1656.     STR *tmpstr;
  1657.     STR *tmp2str;
  1658.  
  1659.     if (!node) {
  1660.     *numericptr = 0;
  1661.     return 0;
  1662.     }
  1663.     type = ops[node].ival;
  1664.     len = type >> 8;
  1665.     type &= 255;
  1666.     switch (type) {
  1667.     case OPROG:
  1668.     prewalk(0,level,ops[node+1].ival,&numarg);
  1669.     if (ops[node+2].ival) {
  1670.         prewalk(0,level,ops[node+2].ival,&numarg);
  1671.     }
  1672.     ++level;
  1673.     prewalk(0,level,ops[node+3].ival,&numarg);
  1674.     --level;
  1675.     if (ops[node+3].ival) {
  1676.         prewalk(0,level,ops[node+4].ival,&numarg);
  1677.     }
  1678.     break;
  1679.     case OHUNKS:
  1680.     prewalk(0,level,ops[node+1].ival,&numarg);
  1681.     prewalk(0,level,ops[node+2].ival,&numarg);
  1682.     if (len == 3) {
  1683.         prewalk(0,level,ops[node+3].ival,&numarg);
  1684.     }
  1685.     break;
  1686.     case ORANGE:
  1687.     prewalk(1,level,ops[node+1].ival,&numarg);
  1688.     prewalk(1,level,ops[node+2].ival,&numarg);
  1689.     break;
  1690.     case OPAT:
  1691.     goto def;
  1692.     case OREGEX:
  1693.     prewalk(0,level,ops[node+1].ival,&numarg);
  1694.     break;
  1695.     case OHUNK:
  1696.     if (len == 1) {
  1697.         prewalk(0,level,ops[node+1].ival,&numarg);
  1698.     }
  1699.     else {
  1700.         i = prewalk(0,level,ops[node+1].ival,&numarg);
  1701.         if (i) {
  1702.         ++level;
  1703.         prewalk(0,level,ops[node+2].ival,&numarg);
  1704.         --level;
  1705.         }
  1706.         else {
  1707.         prewalk(0,level,ops[node+2].ival,&numarg);
  1708.         }
  1709.     }
  1710.     break;
  1711.     case OPPAREN:
  1712.     prewalk(0,level,ops[node+1].ival,&numarg);
  1713.     break;
  1714.     case OPANDAND:
  1715.     prewalk(0,level,ops[node+1].ival,&numarg);
  1716.     prewalk(0,level,ops[node+2].ival,&numarg);
  1717.     break;
  1718.     case OPOROR:
  1719.     prewalk(0,level,ops[node+1].ival,&numarg);
  1720.     prewalk(0,level,ops[node+2].ival,&numarg);
  1721.     break;
  1722.     case OPNOT:
  1723.     prewalk(0,level,ops[node+1].ival,&numarg);
  1724.     break;
  1725.     case OCPAREN:
  1726.     prewalk(0,level,ops[node+1].ival,&numarg);
  1727.     numeric |= numarg;
  1728.     break;
  1729.     case OCANDAND:
  1730.     prewalk(0,level,ops[node+1].ival,&numarg);
  1731.     numeric = 1;
  1732.     prewalk(0,level,ops[node+2].ival,&numarg);
  1733.     break;
  1734.     case OCOROR:
  1735.     prewalk(0,level,ops[node+1].ival,&numarg);
  1736.     numeric = 1;
  1737.     prewalk(0,level,ops[node+2].ival,&numarg);
  1738.     break;
  1739.     case OCNOT:
  1740.     prewalk(0,level,ops[node+1].ival,&numarg);
  1741.     numeric = 1;
  1742.     break;
  1743.     case ORELOP:
  1744.     prewalk(0,level,ops[node+2].ival,&numarg);
  1745.     numeric |= numarg;
  1746.     prewalk(0,level,ops[node+1].ival,&numarg);
  1747.     prewalk(0,level,ops[node+3].ival,&numarg);
  1748.     numeric |= numarg;
  1749.     numeric = 1;
  1750.     break;
  1751.     case ORPAREN:
  1752.     prewalk(0,level,ops[node+1].ival,&numarg);
  1753.     numeric |= numarg;
  1754.     break;
  1755.     case OMATCHOP:
  1756.     prewalk(0,level,ops[node+2].ival,&numarg);
  1757.     prewalk(0,level,ops[node+1].ival,&numarg);
  1758.     prewalk(0,level,ops[node+3].ival,&numarg);
  1759.     numeric = 1;
  1760.     break;
  1761.     case OMPAREN:
  1762.     prewalk(0,level,ops[node+1].ival,&numarg);
  1763.     numeric |= numarg;
  1764.     break;
  1765.     case OCONCAT:
  1766.     prewalk(0,level,ops[node+1].ival,&numarg);
  1767.     prewalk(0,level,ops[node+2].ival,&numarg);
  1768.     break;
  1769.     case OASSIGN:
  1770.     prewalk(0,level,ops[node+2].ival,&numarg);
  1771.     prewalk(0,level,ops[node+1].ival,&numarg);
  1772.     prewalk(0,level,ops[node+3].ival,&numarg);
  1773.     if (numarg || strlen(ops[ops[node+1].ival+1].cval) > 1) {
  1774.         numericize(ops[node+2].ival);
  1775.         if (!numarg)
  1776.         numericize(ops[node+3].ival);
  1777.     }
  1778.     numeric |= numarg;
  1779.     break;
  1780.     case OADD:
  1781.     prewalk(1,level,ops[node+1].ival,&numarg);
  1782.     prewalk(1,level,ops[node+2].ival,&numarg);
  1783.     numeric = 1;
  1784.     break;
  1785.     case OSUBTRACT:
  1786.     prewalk(1,level,ops[node+1].ival,&numarg);
  1787.     prewalk(1,level,ops[node+2].ival,&numarg);
  1788.     numeric = 1;
  1789.     break;
  1790.     case OMULT:
  1791.     prewalk(1,level,ops[node+1].ival,&numarg);
  1792.     prewalk(1,level,ops[node+2].ival,&numarg);
  1793.     numeric = 1;
  1794.     break;
  1795.     case ODIV:
  1796.     prewalk(1,level,ops[node+1].ival,&numarg);
  1797.     prewalk(1,level,ops[node+2].ival,&numarg);
  1798.     numeric = 1;
  1799.     break;
  1800.     case OPOW:
  1801.     prewalk(1,level,ops[node+1].ival,&numarg);
  1802.     prewalk(1,level,ops[node+2].ival,&numarg);
  1803.     numeric = 1;
  1804.     break;
  1805.     case OMOD:
  1806.     prewalk(1,level,ops[node+1].ival,&numarg);
  1807.     prewalk(1,level,ops[node+2].ival,&numarg);
  1808.     numeric = 1;
  1809.     break;
  1810.     case OPOSTINCR:
  1811.     prewalk(1,level,ops[node+1].ival,&numarg);
  1812.     numeric = 1;
  1813.     break;
  1814.     case OPOSTDECR:
  1815.     prewalk(1,level,ops[node+1].ival,&numarg);
  1816.     numeric = 1;
  1817.     break;
  1818.     case OPREINCR:
  1819.     prewalk(1,level,ops[node+1].ival,&numarg);
  1820.     numeric = 1;
  1821.     break;
  1822.     case OPREDECR:
  1823.     prewalk(1,level,ops[node+1].ival,&numarg);
  1824.     numeric = 1;
  1825.     break;
  1826.     case OUMINUS:
  1827.     prewalk(1,level,ops[node+1].ival,&numarg);
  1828.     numeric = 1;
  1829.     break;
  1830.     case OUPLUS:
  1831.     prewalk(1,level,ops[node+1].ival,&numarg);
  1832.     numeric = 1;
  1833.     break;
  1834.     case OPAREN:
  1835.     prewalk(0,level,ops[node+1].ival,&numarg);
  1836.     numeric |= numarg;
  1837.     break;
  1838.     case OGETLINE:
  1839.     break;
  1840.     case OSPRINTF:
  1841.     prewalk(0,level,ops[node+1].ival,&numarg);
  1842.     break;
  1843.     case OSUBSTR:
  1844.     prewalk(0,level,ops[node+1].ival,&numarg);
  1845.     prewalk(1,level,ops[node+2].ival,&numarg);
  1846.     if (len == 3) {
  1847.         prewalk(1,level,ops[node+3].ival,&numarg);
  1848.     }
  1849.     break;
  1850.     case OSTRING:
  1851.     break;
  1852.     case OSPLIT:
  1853.     numeric = 1;
  1854.     prewalk(0,level,ops[node+2].ival,&numarg);
  1855.     if (len == 3)
  1856.         prewalk(0,level,ops[node+3].ival,&numarg);
  1857.     prewalk(0,level,ops[node+1].ival,&numarg);
  1858.     break;
  1859.     case OINDEX:
  1860.     prewalk(0,level,ops[node+1].ival,&numarg);
  1861.     prewalk(0,level,ops[node+2].ival,&numarg);
  1862.     numeric = 1;
  1863.     break;
  1864.     case OMATCH:
  1865.     prewalk(0,level,ops[node+1].ival,&numarg);
  1866.     prewalk(0,level,ops[node+2].ival,&numarg);
  1867.     numeric = 1;
  1868.     break;
  1869.     case OUSERDEF:
  1870.     subretnum = FALSE;
  1871.     --level;
  1872.     tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
  1873.     ++level;
  1874.     prewalk(0,level,ops[node+2].ival,&numarg);
  1875.     prewalk(0,level,ops[node+4].ival,&numarg);
  1876.     prewalk(0,level,ops[node+5].ival,&numarg);
  1877.     --level;
  1878.     str_cat(tmpstr,"(");
  1879.     tmp2str = str_new(0);
  1880.     if (subretnum || numarg)
  1881.         str_set(tmp2str,"1");
  1882.     hstore(symtab,tmpstr->str_ptr,tmp2str);
  1883.     str_free(tmpstr);
  1884.     level++;
  1885.     break;
  1886.     case ORETURN:
  1887.     if (len > 0) {
  1888.         prewalk(0,level,ops[node+1].ival,&numarg);
  1889.         if (numarg)
  1890.         subretnum = TRUE;
  1891.     }
  1892.     break;
  1893.     case OUSERFUN:
  1894.     tmp2str = str_new(0);
  1895.     str_scat(tmp2str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
  1896.     fixrargs(tmpstr->str_ptr,ops[node+2].ival,0);
  1897.     str_free(tmpstr);
  1898.     str_cat(tmp2str,"(");
  1899.     tmpstr = hfetch(symtab,tmp2str->str_ptr);
  1900.     if (tmpstr && tmpstr->str_ptr)
  1901.         numeric |= atoi(tmpstr->str_ptr);
  1902.     prewalk(0,level,ops[node+2].ival,&numarg);
  1903.     str_free(tmp2str);
  1904.     break;
  1905.     case OGSUB:
  1906.     case OSUB:
  1907.     if (len >= 3)
  1908.         prewalk(0,level,ops[node+3].ival,&numarg);
  1909.     prewalk(0,level,ops[ops[node+2].ival+1].ival,&numarg);
  1910.     prewalk(0,level,ops[node+1].ival,&numarg);
  1911.     numeric = 1;
  1912.     break;
  1913.     case ONUM:
  1914.     prewalk(0,level,ops[node+1].ival,&numarg);
  1915.     numeric = 1;
  1916.     break;
  1917.     case OSTR:
  1918.     prewalk(0,level,ops[node+1].ival,&numarg);
  1919.     break;
  1920.     case ODEFINED:
  1921.     case ODELETE:
  1922.     case OSTAR:
  1923.     case OVAR:
  1924.     prewalk(0,level,ops[node+1].ival,&numarg);
  1925.     if (len == 1) {
  1926.         if (numit)
  1927.         numericize(node);
  1928.     }
  1929.     else {
  1930.         prewalk(0,level,ops[node+2].ival,&numarg);
  1931.     }
  1932.     break;
  1933.     case OFLD:
  1934.     prewalk(0,level,ops[node+1].ival,&numarg);
  1935.     break;
  1936.     case OVFLD:
  1937.     i = ops[node+1].ival;
  1938.     prewalk(0,level,i,&numarg);
  1939.     break;
  1940.     case OJUNK:
  1941.     goto def;
  1942.     case OSNEWLINE:
  1943.     break;
  1944.     case ONEWLINE:
  1945.     break;
  1946.     case OSCOMMENT:
  1947.     break;
  1948.     case OCOMMENT:
  1949.     break;
  1950.     case OCOMMA:
  1951.     prewalk(0,level,ops[node+1].ival,&numarg);
  1952.     prewalk(0,level,ops[node+2].ival,&numarg);
  1953.     prewalk(0,level,ops[node+3].ival,&numarg);
  1954.     break;
  1955.     case OSEMICOLON:
  1956.     break;
  1957.     case OSTATES:
  1958.     prewalk(0,level,ops[node+1].ival,&numarg);
  1959.     prewalk(0,level,ops[node+2].ival,&numarg);
  1960.     break;
  1961.     case OSTATE:
  1962.     if (len >= 1) {
  1963.         prewalk(0,level,ops[node+1].ival,&numarg);
  1964.         if (len >= 2) {
  1965.         prewalk(0,level,ops[node+2].ival,&numarg);
  1966.         }
  1967.     }
  1968.     break;
  1969.     case OCLOSE:
  1970.     prewalk(0,level,ops[node+1].ival,&numarg);
  1971.     break;
  1972.     case OPRINTF:
  1973.     case OPRINT:
  1974.     if (len == 3) {        /* output redirection */
  1975.         prewalk(0,level,ops[node+3].ival,&numarg);
  1976.         prewalk(0,level,ops[node+2].ival,&numarg);
  1977.     }
  1978.     prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg);
  1979.     break;
  1980.     case ORAND:
  1981.     break;
  1982.     case OSRAND:
  1983.     goto maybe0;
  1984.     case OATAN2:
  1985.     goto maybe0;
  1986.     case OSIN:
  1987.     goto maybe0;
  1988.     case OCOS:
  1989.     goto maybe0;
  1990.     case OSYSTEM:
  1991.     goto maybe0;
  1992.     case OLENGTH:
  1993.     goto maybe0;
  1994.     case OLOG:
  1995.     goto maybe0;
  1996.     case OEXP:
  1997.     goto maybe0;
  1998.     case OSQRT:
  1999.     goto maybe0;
  2000.     case OINT:
  2001.       maybe0:
  2002.     numeric = 1;
  2003.     if (len > 0)
  2004.         prewalk(type != OLENGTH && type != OSYSTEM,
  2005.           level,ops[node+1].ival,&numarg);
  2006.     break;
  2007.     case OBREAK:
  2008.     break;
  2009.     case ONEXT:
  2010.     break;
  2011.     case OEXIT:
  2012.     if (len == 1) {
  2013.         prewalk(1,level,ops[node+1].ival,&numarg);
  2014.     }
  2015.     break;
  2016.     case OCONTINUE:
  2017.     break;
  2018.     case OREDIR:
  2019.     goto def;
  2020.     case OIF:
  2021.     prewalk(0,level,ops[node+1].ival,&numarg);
  2022.     prewalk(0,level,ops[node+2].ival,&numarg);
  2023.     if (len == 3) {
  2024.         prewalk(0,level,ops[node+3].ival,&numarg);
  2025.     }
  2026.     break;
  2027.     case OWHILE:
  2028.     prewalk(0,level,ops[node+1].ival,&numarg);
  2029.     prewalk(0,level,ops[node+2].ival,&numarg);
  2030.     break;
  2031.     case OFOR:
  2032.     prewalk(0,level,ops[node+1].ival,&numarg);
  2033.     prewalk(0,level,ops[node+2].ival,&numarg);
  2034.     prewalk(0,level,ops[node+3].ival,&numarg);
  2035.     prewalk(0,level,ops[node+4].ival,&numarg);
  2036.     break;
  2037.     case OFORIN:
  2038.     prewalk(0,level,ops[node+2].ival,&numarg);
  2039.     prewalk(0,level,ops[node+1].ival,&numarg);
  2040.     break;
  2041.     case OBLOCK:
  2042.     if (len == 2) {
  2043.         prewalk(0,level,ops[node+2].ival,&numarg);
  2044.     }
  2045.     ++level;
  2046.     prewalk(0,level,ops[node+1].ival,&numarg);
  2047.     --level;
  2048.     break;
  2049.     default:
  2050.       def:
  2051.     if (len) {
  2052.         if (len > 5)
  2053.         fatal("Garbage length in prewalk");
  2054.         prewalk(0,level,ops[node+1].ival,&numarg);
  2055.         for (i = 2; i<= len; i++) {
  2056.         prewalk(0,level,ops[node+i].ival,&numarg);
  2057.         }
  2058.     }
  2059.     break;
  2060.     }
  2061.     *numericptr = numeric;
  2062.     return 1;
  2063. }
  2064.  
  2065. numericize(node)
  2066. register int node;
  2067. {
  2068.     register int len;
  2069.     register int type;
  2070.     register int i;
  2071.     STR *tmpstr;
  2072.     STR *tmp2str;
  2073.     int numarg;
  2074.  
  2075.     type = ops[node].ival;
  2076.     len = type >> 8;
  2077.     type &= 255;
  2078.     if (type == OVAR && len == 1) {
  2079.     tmpstr=walk(0,0,ops[node+1].ival,&numarg,P_MIN);
  2080.     tmp2str = str_make("1");
  2081.     hstore(symtab,tmpstr->str_ptr,tmp2str);
  2082.     }
  2083. }
  2084.