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