X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=x2p%2Fwalk.c;h=de1263fc16bfb4b02eea79389e81ce191e33f777;hb=41c686de0da47eeb5df94342ffc739979e9aa57d;hp=04d133b9c4fa0a7f171b0a05b120f1b34cb95674;hpb=8d063cd8450e59ea1c611a2f4f5a21059a2804f1;p=p5sagit%2Fp5-mst-13.2.git diff --git a/x2p/walk.c b/x2p/walk.c index 04d133b..de1263f 100644 --- a/x2p/walk.c +++ b/x2p/walk.c @@ -1,26 +1,46 @@ -/* $Header: walk.c,v 1.0 87/12/18 13:07:40 root Exp $ +/* walk.c * - * $Log: walk.c,v $ - * Revision 1.0 87/12/18 13:07:40 root - * Initial revision - * + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1997, 1998, 1999, + * 2000, 2001, 2002, 2005 by Larry Wall and others + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. */ -#include "handy.h" #include "EXTERN.h" -#include "util.h" #include "a2p.h" +#include "util.h" bool exitval = FALSE; bool realexit = FALSE; +bool saw_getline = FALSE; +bool subretnum = FALSE; +bool saw_FNR = FALSE; +bool saw_argv0 = FALSE; +bool saw_fh = FALSE; int maxtmp = 0; +char *lparen; +char *rparen; +char *limit; +STR *subs; +STR *curargs = Nullstr; + +static void addsemi ( STR *str ); +static void emit_split ( STR *str, int level ); +static void fixtab ( STR *str, int lvl ); +static void numericize ( int node ); +static void tab ( STR *str, int lvl ); + +int prewalk ( int numit, int level, int node, int *numericptr ); +STR * walk ( int useval, int level, int node, int *numericptr, int minprec ); +#ifdef NETWARE +char *savestr(char *str); +char *cpytill(register char *to, register char *from, register int delim); +char *instr(char *big, char *little); +#endif STR * -walk(useval,level,node,numericptr) -int useval; -int level; -register int node; -int *numericptr; +walk(int useval, int level, register int node, int *numericptr, int minprec) { register int len; register STR *str; @@ -28,12 +48,13 @@ int *numericptr; register int i; register STR *tmpstr; STR *tmp2str; + STR *tmp3str; char *t; char *d, *s; int numarg; int numeric = FALSE; STR *fstr; - char *index(); + int prec = P_MAX; /* assume no parens needed */ if (!node) { *numericptr = 0; @@ -44,8 +65,23 @@ int *numericptr; type &= 255; switch (type) { case OPROG: - str = walk(0,level,ops[node+1].ival,&numarg); + arymax = 0; + if (namelist) { + while (isALPHA(*namelist)) { + for (d = tokenbuf,s=namelist; + isALPHA(*s) || isDIGIT(*s) || *s == '_'; + *d++ = *s++) ; + *d = '\0'; + while (*s && !isALPHA(*s)) s++; + namelist = s; + nameary[++arymax] = savestr(tokenbuf); + } + } + if (maxfld < arymax) + maxfld = arymax; opens = str_new(0); + subs = str_new(0); + str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); if (do_split && need_entire && !absmaxfld) split_to_array = TRUE; if (do_split && split_to_array) @@ -61,106 +97,138 @@ int *numericptr; do_chop = TRUE; if (fswitch) { str_cat(str,"$FS = '"); - if (index("*+?.[]()|^$\\",fswitch)) + if (strchr("*+?.[]()|^$\\",fswitch)) str_cat(str,"\\"); sprintf(tokenbuf,"%c",fswitch); str_cat(str,tokenbuf); str_cat(str,"';\t\t# field separator from -F switch\n"); } else if (saw_FS && !const_FS) { - str_cat(str,"$FS = '[ \\t\\n]+';\t\t# default field separator\n"); + str_cat(str,"$FS = ' ';\t\t# set field separator\n"); } if (saw_OFS) { - str_cat(str,"$, = ' ';\t\t# default output field separator\n"); + str_cat(str,"$, = ' ';\t\t# set output field separator\n"); } if (saw_ORS) { - str_cat(str,"$\\ = \"\\n\";\t\t# default output record separator\n"); + str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n"); + } + if (saw_argv0) { + str_cat(str,"$ARGV0 = $0;\t\t# remember what we ran as\n"); } if (str->str_cur > 20) str_cat(str,"\n"); if (ops[node+2].ival) { - str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,"\n\n"); } - if (saw_line_op) - str_cat(str,"line: "); - str_cat(str,"while (<>) {\n"); - tab(str,++level); - if (saw_FS && !const_FS) - do_chop = TRUE; - if (do_chop) { - str_cat(str,"chop;\t# strip record separator\n"); - tab(str,level); - } - arymax = 0; - if (namelist) { - while (isalpha(*namelist)) { - for (d = tokenbuf,s=namelist; - isalpha(*s) || isdigit(*s) || *s == '_'; - *d++ = *s++) ; - *d = '\0'; - while (*s && !isalpha(*s)) s++; - namelist = s; - nameary[++arymax] = savestr(tokenbuf); + fstr = walk(0,level+1,ops[node+3].ival,&numarg,P_MIN); + if (*fstr->str_ptr) { + if (saw_line_op) + str_cat(str,"line: "); + str_cat(str,"while (<>) {\n"); + tab(str,++level); + if (saw_FS && !const_FS) + do_chop = TRUE; + if (do_chop) { + str_cat(str,"chomp;\t# strip record separator\n"); + tab(str,level); } + if (do_split) + emit_split(str,level); + str_scat(str,fstr); + str_free(fstr); + fixtab(str,--level); + str_cat(str,"}\n"); + if (saw_FNR) + str_cat(str,"continue {\n $FNRbase = $. if eof;\n}\n"); } - if (maxfld < arymax) - maxfld = arymax; - if (do_split) - emit_split(str,level); - str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg)); - str_free(fstr); - fixtab(str,--level); - str_cat(str,"}\n"); + else if (old_awk) + str_cat(str,"while (<>) { } # (no line actions)\n"); if (ops[node+4].ival) { realexit = TRUE; str_cat(str,"\n"); tab(str,level); - str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,"\n"); } if (exitval) - str_cat(str,"exit ExitValue;\n"); + str_cat(str,"exit $ExitValue;\n"); + if (subs->str_ptr) { + str_cat(str,"\n"); + str_scat(str,subs); + } + if (saw_getline) { + for (len = 0; len < 4; len++) { + if (saw_getline & (1 << len)) { + sprintf(tokenbuf,"\nsub Getline%d {\n",len); + str_cat(str, tokenbuf); + if (len & 2) { + if (do_fancy_opens) + str_cat(str," &Pick('',@_);\n"); + else + str_cat(str," ($fh) = @_;\n"); + } + else { + if (saw_FNR) + str_cat(str," $FNRbase = $. if eof;\n"); + } + if (len & 1) + str_cat(str," local($_);\n"); + if (len & 2) + str_cat(str, + " if ($getline_ok = (($_ = <$fh>) ne ''))"); + else + str_cat(str, + " if ($getline_ok = (($_ = <>) ne ''))"); + str_cat(str, " {\n"); + level += 2; + tab(str,level); + i = 0; + if (do_chop) { + i++; + str_cat(str,"chomp;\t# strip record separator\n"); + tab(str,level); + } + if (do_split && !(len & 1)) { + i++; + emit_split(str,level); + } + if (!i) + str_cat(str,";\n"); + fixtab(str,--level); + str_cat(str,"}\n $_;\n}\n"); + --level; + } + } + } if (do_fancy_opens) { str_cat(str,"\n\ sub Pick {\n\ - ($name) = @_;\n\ - $fh = $opened{$name};\n\ - if (!$fh) {\n\ - $nextfh == 0 && open(fh_0,$name);\n\ - $nextfh == 1 && open(fh_1,$name);\n\ - $nextfh == 2 && open(fh_2,$name);\n\ - $nextfh == 3 && open(fh_3,$name);\n\ - $nextfh == 4 && open(fh_4,$name);\n\ - $nextfh == 5 && open(fh_5,$name);\n\ - $nextfh == 6 && open(fh_6,$name);\n\ - $nextfh == 7 && open(fh_7,$name);\n\ - $nextfh == 8 && open(fh_8,$name);\n\ - $nextfh == 9 && open(fh_9,$name);\n\ - $fh = $opened{$name} = 'fh_' . $nextfh++;\n\ - }\n\ - select($fh);\n\ + local($mode,$name,$pipe) = @_;\n\ + $fh = $name;\n\ + open($name,$mode.$name.$pipe) unless $opened{$name}++;\n\ }\n\ "); } break; case OHUNKS: - str = walk(0,level,ops[node+1].ival,&numarg); - str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg)); + str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); if (len == 3) { - str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN)); str_free(fstr); } else { } break; case ORANGE: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_DOTDOT; + str = walk(1,level,ops[node+1].ival,&numarg,prec+1); str_cat(str," .. "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); break; case OPAT: @@ -168,10 +236,10 @@ sub Pick {\n\ case OREGEX: str = str_new(0); str_set(str,"/"); - tmpstr=walk(0,level,ops[node+1].ival,&numarg); + tmpstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN); /* translate \nnn to [\nnn] */ for (s = tmpstr->str_ptr, d = tokenbuf; *s; s++, d++) { - if (*s == '\\' && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])) { + if (*s == '\\' && isDIGIT(s[1]) && isDIGIT(s[2]) && isDIGIT(s[3])){ *d++ = '['; *d++ = *s++; *d++ = *s++; @@ -183,6 +251,8 @@ sub Pick {\n\ *d = *s; } *d = '\0'; + for (d=tokenbuf; *d; d++) + *d += (char)128; str_cat(str,tokenbuf); str_free(tmpstr); str_cat(str,"/"); @@ -190,92 +260,118 @@ sub Pick {\n\ case OHUNK: if (len == 1) { str = str_new(0); - str = walk(0,level,oper1(OPRINT,0),&numarg); + str = walk(0,level,oper1(OPRINT,0),&numarg,P_MIN); str_cat(str," if "); - str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,";"); } else { - tmpstr = walk(0,level,ops[node+1].ival,&numarg); + tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); if (*tmpstr->str_ptr) { str = str_new(0); str_set(str,"if ("); str_scat(str,tmpstr); str_cat(str,") {\n"); tab(str,++level); - str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); fixtab(str,--level); str_cat(str,"}\n"); tab(str,level); } else { - str = walk(0,level,ops[node+2].ival,&numarg); + str = walk(0,level,ops[node+2].ival,&numarg,P_MIN); } } break; case OPPAREN: str = str_new(0); str_set(str,"("); - str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,")"); break; case OPANDAND: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_ANDAND; + str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," && "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); + str_free(fstr); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OPOROR: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_OROR; + str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," || "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); + str_free(fstr); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OPNOT: + prec = P_UNARY; str = str_new(0); str_set(str,"!"); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec)); + str_free(fstr); + break; + case OCOND: + prec = P_COND; + str = walk(1,level,ops[node+1].ival,&numarg,prec); + str_cat(str," ? "); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); + str_free(fstr); + str_cat(str," : "); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OCPAREN: str = str_new(0); str_set(str,"("); - str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); numeric |= numarg; str_cat(str,")"); break; case OCANDAND: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_ANDAND; + str = walk(1,level,ops[node+1].ival,&numarg,prec); numeric = 1; str_cat(str," && "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); + str_free(fstr); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OCOROR: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_OROR; + str = walk(1,level,ops[node+1].ival,&numarg,prec); numeric = 1; str_cat(str," || "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); + str_free(fstr); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OCNOT: + prec = P_UNARY; str = str_new(0); str_set(str,"!"); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec)); str_free(fstr); numeric = 1; break; case ORELOP: - str = walk(1,level,ops[node+2].ival,&numarg); + prec = P_REL; + str = walk(1,level,ops[node+2].ival,&numarg,prec+1); numeric |= numarg; - tmpstr = walk(0,level,ops[node+1].ival,&numarg); - tmp2str = walk(1,level,ops[node+3].ival,&numarg); + tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); + tmp2str = walk(1,level,ops[node+3].ival,&numarg,prec+1); numeric |= numarg; - if (!numeric) { + if (!numeric || + (!numarg && (*tmp2str->str_ptr == '"' || *tmp2str->str_ptr == '\''))) { t = tmpstr->str_ptr; if (strEQ(t,"==")) str_set(tmpstr,"eq"); @@ -289,8 +385,8 @@ sub Pick {\n\ str_set(tmpstr,"gt"); else if (strEQ(t,">=")) str_set(tmpstr,"ge"); - if (!index(tmpstr->str_ptr,'\'') && !index(tmpstr->str_ptr,'"') && - !index(tmp2str->str_ptr,'\'') && !index(tmp2str->str_ptr,'"') ) + if (!strchr(tmpstr->str_ptr,'\'') && !strchr(tmpstr->str_ptr,'"') && + !strchr(tmp2str->str_ptr,'\'') && !strchr(tmp2str->str_ptr,'"') ) numeric |= 2; } if (numeric & 2) { @@ -312,15 +408,16 @@ sub Pick {\n\ case ORPAREN: str = str_new(0); str_set(str,"("); - str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); numeric |= numarg; str_cat(str,")"); break; case OMATCHOP: - str = walk(1,level,ops[node+2].ival,&numarg); + prec = P_MATCH; + str = walk(1,level,ops[node+2].ival,&numarg,prec+1); str_cat(str," "); - tmpstr = walk(0,level,ops[node+1].ival,&numarg); + tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); if (strEQ(tmpstr->str_ptr,"~")) str_cat(str,"=~"); else { @@ -328,102 +425,126 @@ sub Pick {\n\ str_free(tmpstr); } str_cat(str," "); - str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OMPAREN: str = str_new(0); str_set(str,"("); - str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg)); + str_scat(str, + fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); numeric |= numarg; str_cat(str,")"); break; case OCONCAT: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_ADD; + type = ops[ops[node+1].ival].ival & 255; + str = walk(1,level,ops[node+1].ival,&numarg,prec+(type != OCONCAT)); str_cat(str," . "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + type = ops[ops[node+2].ival].ival & 255; + str_scat(str, + fstr=walk(1,level,ops[node+2].ival,&numarg,prec+(type != OCONCAT))); str_free(fstr); break; case OASSIGN: - str = walk(0,level,ops[node+2].ival,&numarg); + prec = P_ASSIGN; + str = walk(0,level,ops[node+2].ival,&numarg,prec+1); str_cat(str," "); - tmpstr = walk(0,level,ops[node+1].ival,&numarg); + tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); str_scat(str,tmpstr); if (str_len(tmpstr) > 1) numeric = 1; str_free(tmpstr); str_cat(str," "); - str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec)); str_free(fstr); numeric |= numarg; - if (strEQ(str->str_ptr,"$FS = '\240'")) - str_set(str,"$FS = '[\240\\n\\t]+'"); + if (strEQ(str->str_ptr,"$/ = ''")) + str_set(str, "$/ = \"\\n\\n\""); break; case OADD: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_ADD; + str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," + "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; - case OSUB: - str = walk(1,level,ops[node+1].ival,&numarg); + case OSUBTRACT: + prec = P_ADD; + str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," - "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OMULT: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_MUL; + str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," * "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case ODIV: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_MUL; + str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," / "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); + str_free(fstr); + numeric = 1; + break; + case OPOW: + prec = P_POW; + str = walk(1,level,ops[node+1].ival,&numarg,prec+1); + str_cat(str," ** "); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec)); str_free(fstr); numeric = 1; break; case OMOD: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_MUL; + str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," % "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OPOSTINCR: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_AUTO; + str = walk(1,level,ops[node+1].ival,&numarg,prec+1); str_cat(str,"++"); numeric = 1; break; case OPOSTDECR: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_AUTO; + str = walk(1,level,ops[node+1].ival,&numarg,prec+1); str_cat(str,"--"); numeric = 1; break; case OPREINCR: + prec = P_AUTO; str = str_new(0); str_set(str,"++"); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OPREDECR: + prec = P_AUTO; str = str_new(0); str_set(str,"--"); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OUMINUS: + prec = P_UNARY; str = str_new(0); str_set(str,"-"); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec)); str_free(fstr); numeric = 1; break; @@ -433,44 +554,110 @@ sub Pick {\n\ case OPAREN: str = str_new(0); str_set(str,"("); - str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg)); + str_scat(str, + fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,")"); numeric |= numarg; break; case OGETLINE: str = str_new(0); - str_set(str,"$_ = <>;\n"); - tab(str,level); - if (do_chop) { - str_cat(str,"chop;\t# strip record separator\n"); - tab(str,level); + if (useval) + str_cat(str,"("); + if (len > 0) { + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); + if (!*fstr->str_ptr) { + str_cat(str,"$_"); + len = 2; /* a legal fiction */ + } + str_free(fstr); + } + else + str_cat(str,"$_"); + if (len > 1) { + tmpstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN); + fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN); + if (!do_fancy_opens) { + t = tmpstr->str_ptr; + if (*t == '"' || *t == '\'') + t = cpytill(tokenbuf,t+1,*t); + else + fatal("Internal error: OGETLINE %s", t); + d = savestr(t); + s = savestr(tokenbuf); + for (t = tokenbuf; *t; t++) { + *t &= 127; + if (isLOWER(*t)) + *t = toUPPER(*t); + if (!isALPHA(*t) && !isDIGIT(*t)) + *t = '_'; + } + if (!strchr(tokenbuf,'_')) + strcpy(t,"_FH"); + tmp3str = hfetch(symtab,tokenbuf); + if (!tmp3str) { + do_opens = TRUE; + str_cat(opens,"open("); + str_cat(opens,tokenbuf); + str_cat(opens,", "); + d[1] = '\0'; + str_cat(opens,d); + str_cat(opens,tmpstr->str_ptr+1); + opens->str_cur--; + if (*fstr->str_ptr == '|') + str_cat(opens,"|"); + str_cat(opens,d); + if (*fstr->str_ptr == '|') + str_cat(opens,") || die 'Cannot pipe from \""); + else + str_cat(opens,") || die 'Cannot open file \""); + if (*d == '"') + str_cat(opens,"'.\""); + str_cat(opens,s); + if (*d == '"') + str_cat(opens,"\".'"); + str_cat(opens,"\".';\n"); + hstore(symtab,tokenbuf,str_make("x")); + } + safefree(s); + safefree(d); + str_set(tmpstr,"'"); + str_cat(tmpstr,tokenbuf); + str_cat(tmpstr,"'"); + } + if (*fstr->str_ptr == '|') + str_cat(tmpstr,", '|'"); + str_free(fstr); } - if (do_split) - emit_split(str,level); + else + tmpstr = str_make(""); + sprintf(tokenbuf," = &Getline%d(%s)",len,tmpstr->str_ptr); + str_cat(str,tokenbuf); + str_free(tmpstr); + if (useval) + str_cat(str,",$getline_ok)"); + saw_getline |= 1 << len; break; case OSPRINTF: str = str_new(0); str_set(str,"sprintf("); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,")"); break; case OSUBSTR: str = str_new(0); str_set(str,"substr("); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1)); str_free(fstr); str_cat(str,", "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1)); str_free(fstr); - str_cat(str,", "); if (len == 3) { - str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg)); + str_cat(str,", "); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1)); str_free(fstr); } - else - str_cat(str,"999999"); str_cat(str,")"); break; case OSTRING: @@ -479,8 +666,9 @@ sub Pick {\n\ break; case OSPLIT: str = str_new(0); + limit = ", -1)"; numeric = 1; - tmpstr = walk(1,level,ops[node+2].ival,&numarg); + tmpstr = walk(1,level,ops[node+2].ival,&numarg,P_MIN); if (useval) str_set(str,"(@"); else @@ -488,11 +676,13 @@ sub Pick {\n\ str_scat(str,tmpstr); str_cat(str," = split("); if (len == 3) { - fstr = walk(1,level,ops[node+3].ival,&numarg); + fstr = walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1); if (str_len(fstr) == 3 && *fstr->str_ptr == '\'') { i = fstr->str_ptr[1] & 127; - if (index("*+?.[]()|^$\\",i)) + if (strchr("*+?.[]()|^$\\",i)) sprintf(tokenbuf,"/\\%c/",i); + else if (i == ' ') + sprintf(tokenbuf,"' '"); else sprintf(tokenbuf,"/%c/",i); str_cat(str,tokenbuf); @@ -507,12 +697,14 @@ sub Pick {\n\ } else if (saw_FS) str_cat(str,"$FS"); - else - str_cat(str,"/[ \\t\\n]+/"); + else { + str_cat(str,"' '"); + limit = ")"; + } str_cat(str,", "); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1)); str_free(fstr); - str_cat(str,")"); + str_cat(str,limit); if (useval) { str_cat(str,")"); } @@ -521,41 +713,253 @@ sub Pick {\n\ case OINDEX: str = str_new(0); str_set(str,"index("); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1)); str_free(fstr); str_cat(str,", "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1)); str_free(fstr); str_cat(str,")"); numeric = 1; break; + case OMATCH: + str = str_new(0); + prec = P_ANDAND; + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MATCH+1)); + str_free(fstr); + str_cat(str," =~ "); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MATCH+1)); + str_free(fstr); + str_cat(str," && ($RLENGTH = length($&), $RSTART = length($`)+1)"); + numeric = 1; + break; + case OUSERDEF: + str = str_new(0); + subretnum = FALSE; + fstr=walk(1,level-1,ops[node+2].ival,&numarg,P_MIN); + curargs = str_new(0); + str_sset(curargs,fstr); + str_cat(curargs,","); + tmp2str=walk(1,level,ops[node+5].ival,&numarg,P_MIN); + str_free(curargs); + curargs = Nullstr; + level--; + subretnum |= numarg; + s = Nullch; + t = tmp2str->str_ptr; + while ((t = instr(t,"return "))) + s = t++; + if (s) { + i = 0; + for (t = s+7; *t; t++) { + if (*t == ';' || *t == '}') + i++; + } + if (i == 1) { + strcpy(s,s+7); + tmp2str->str_cur -= 7; + } + } + str_set(str,"\n"); + tab(str,level); + str_cat(str,"sub "); + str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); + str_cat(str," {\n"); + tab(str,++level); + if (fstr->str_cur) { + str_cat(str,"local("); + str_scat(str,fstr); + str_cat(str,") = @_;"); + } + str_free(fstr); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN)); + str_free(fstr); + fixtab(str,level); + str_scat(str,fstr=walk(1,level,ops[node+4].ival,&numarg,P_MIN)); + str_free(fstr); + fixtab(str,level); + str_scat(str,tmp2str); + str_free(tmp2str); + fixtab(str,--level); + str_cat(str,"}\n"); + tab(str,level); + str_scat(subs,str); + str_set(str,""); + str_cat(tmpstr,"("); + tmp2str = str_new(0); + if (subretnum) + str_set(tmp2str,"1"); + hstore(symtab,tmpstr->str_ptr,tmp2str); + str_free(tmpstr); + level++; + break; + case ORETURN: + str = str_new(0); + if (len > 0) { + str_cat(str,"return "); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_UNI+1)); + str_free(fstr); + if (numarg) + subretnum = TRUE; + } + else + str_cat(str,"return"); + break; + case OUSERFUN: + str = str_new(0); + str_set(str,"&"); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); + str_free(fstr); + str_cat(str,"("); + tmpstr = hfetch(symtab,str->str_ptr+3); + if (tmpstr && tmpstr->str_ptr) + numeric |= atoi(tmpstr->str_ptr); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN)); + str_free(fstr); + str_cat(str,")"); + break; + case OGSUB: + case OSUB: { + int gsub = type == OGSUB ? 1 : 0; + str = str_new(0); + tmpstr = str_new(0); + i = 0; + if (len == 3) { + tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MATCH+1); + if (strNE(tmpstr->str_ptr,"$_")) { + str_cat(tmpstr, " =~ s"); + i++; + } + else + str_set(tmpstr, "s"); + } + else + str_set(tmpstr, "s"); + type = ops[ops[node+2].ival].ival; + len = type >> 8; + type &= 255; + tmp3str = str_new(0); + if (type == OSTR) { + tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg,P_MIN); + for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) { + if (*t == '&') + *d++ = '$' + (char)128; + else if (*t == '$') + *d++ = '\\' + (char)128; + *d = *t + 128; + } + *d = '\0'; + str_set(tmp2str,tokenbuf); + s = (char *) (gsub ? "/g" : "/"); + } + else { + tmp2str=walk(1,level,ops[node+2].ival,&numarg,P_MIN); + str_set(tmp3str,"($s_ = '\"'.("); + str_scat(tmp3str,tmp2str); + str_cat(tmp3str,").'\"') =~ s/&/\\$&/g, "); + str_set(tmp2str,"eval $s_"); + s = (char *) (gsub ? "/ge" : "/e"); + i++; + } + str_cat(tmp2str,s); + type = ops[ops[node+1].ival].ival; + len = type >> 8; + type &= 255; + fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN); + if (type == OREGEX) { + if (useval && i) + str_cat(str,"("); + str_scat(str,tmp3str); + str_scat(str,tmpstr); + str_scat(str,fstr); + str_scat(str,tmp2str); + } + else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) { + if (useval && i) + str_cat(str,"("); + str_scat(str,tmp3str); + str_scat(str,tmpstr); + str_cat(str,"/"); + str_scat(str,fstr); + str_cat(str,"/"); + str_scat(str,tmp2str); + } + else { + i++; + if (useval) + str_cat(str,"("); + str_cat(str,"$s = "); + str_scat(str,fstr); + str_cat(str,", "); + str_scat(str,tmp3str); + str_scat(str,tmpstr); + str_cat(str,"/$s/"); + str_scat(str,tmp2str); + } + if (useval && i) + str_cat(str,")"); + str_free(fstr); + str_free(tmpstr); + str_free(tmp2str); + str_free(tmp3str); + numeric = 1; + break; } case ONUM: - str = walk(1,level,ops[node+1].ival,&numarg); + str = walk(1,level,ops[node+1].ival,&numarg,P_MIN); numeric = 1; break; case OSTR: - tmpstr = walk(1,level,ops[node+1].ival,&numarg); + tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN); s = "'"; - for (t = tmpstr->str_ptr; *t; t++) { - if (*t == '\\' || *t == '\'') + for (t = tmpstr->str_ptr, d=tokenbuf; *t; d++,t++) { + if (*t == '\'') + s = "\""; + else if (*t == '\\') { s = "\""; - *t += 128; + *d++ = *t++ + 128; + switch (*t) { + case '\\': case '"': case 'n': case 't': case '$': + break; + default: /* hide this from perl */ + *d++ = '\\' + (char)128; + } + } + *d = *t + 128; } + *d = '\0'; str = str_new(0); str_set(str,s); - str_scat(str,tmpstr); + str_cat(str,tokenbuf); str_free(tmpstr); str_cat(str,s); break; + case ODEFINED: + prec = P_UNI; + str = str_new(0); + str_set(str,"defined $"); + goto addvar; + case ODELETE: + str = str_new(0); + str_set(str,"delete $"); + goto addvar; + case OSTAR: + str = str_new(0); + str_set(str,"*"); + goto addvar; case OVAR: str = str_new(0); str_set(str,"$"); - str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg)); + addvar: + str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); if (len == 1) { tmp2str = hfetch(symtab,tmpstr->str_ptr); if (tmp2str && atoi(tmp2str->str_ptr)) numeric = 2; - if (strEQ(str->str_ptr,"$NR")) { + if (strEQ(str->str_ptr,"$FNR")) { + numeric = 1; + saw_FNR++; + str_set(str,"($.-$FNRbase)"); + } + else if (strEQ(str->str_ptr,"$NR")) { numeric = 1; str_set(str,"$."); } @@ -565,22 +969,37 @@ sub Pick {\n\ } else if (strEQ(str->str_ptr,"$0")) str_set(str,"$_"); + else if (strEQ(str->str_ptr,"$ARGC")) + str_set(str,"($#ARGV+1)"); } else { +#ifdef NOTDEF + if (curargs) { + sprintf(tokenbuf,"$%s,",tmpstr->str_ptr); + ??? if (instr(curargs->str_ptr,tokenbuf)) + str_cat(str,"\377"); /* can't translate yet */ + } +#endif str_cat(tmpstr,"[]"); tmp2str = hfetch(symtab,tmpstr->str_ptr); if (tmp2str && atoi(tmp2str->str_ptr)) str_cat(str,"["); else str_cat(str,"{"); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); - if (tmp2str && atoi(tmp2str->str_ptr)) - strcpy(tokenbuf,"]"); - else - strcpy(tokenbuf,"}"); - *tokenbuf += 128; - str_cat(str,tokenbuf); + if (strEQ(str->str_ptr,"$ARGV[0")) { + str_set(str,"$ARGV0"); + saw_argv0++; + } + else { + if (tmp2str && atoi(tmp2str->str_ptr)) + strcpy(tokenbuf,"]"); + else + strcpy(tokenbuf,"}"); + *tokenbuf += (char)128; + str_cat(str,tokenbuf); + } } str_free(tmpstr); break; @@ -589,12 +1008,12 @@ sub Pick {\n\ if (split_to_array) { str_set(str,"$Fld"); str_cat(str,"["); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,"]"); } else { - i = atoi(walk(1,level,ops[node+1].ival,&numarg)->str_ptr); + i = atoi(walk(1,level,ops[node+1].ival,&numarg,P_MIN)->str_ptr); if (i <= arymax) sprintf(tokenbuf,"$%s",nameary[i]); else @@ -608,7 +1027,7 @@ sub Pick {\n\ i = ops[node+1].ival; if ((ops[i].ival & 255) == OPAREN) i = ops[i+1].ival; - tmpstr=walk(1,level,i,&numarg); + tmpstr=walk(1,level,i,&numarg,P_MIN); str_scat(str,tmpstr); str_free(tmpstr); str_cat(str,"]"); @@ -628,44 +1047,48 @@ sub Pick {\n\ case OSCOMMENT: str = str_new(0); str_set(str,";"); - tmpstr = walk(0,level,ops[node+1].ival,&numarg); + tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); for (s = tmpstr->str_ptr; *s && *s != '\n'; s++) - *s += 128; + *s += (char)128; str_scat(str,tmpstr); str_free(tmpstr); tab(str,level); break; case OCOMMENT: str = str_new(0); - tmpstr = walk(0,level,ops[node+1].ival,&numarg); + tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); for (s = tmpstr->str_ptr; *s && *s != '\n'; s++) - *s += 128; + *s += (char)128; str_scat(str,tmpstr); str_free(tmpstr); tab(str,level); break; case OCOMMA: - str = walk(1,level,ops[node+1].ival,&numarg); + prec = P_COMMA; + str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str,", "); - str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN)); + str_free(fstr); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OSEMICOLON: str = str_new(1); - str_set(str,"; "); + str_set(str,";\n"); + tab(str,level); break; case OSTATES: - str = walk(0,level,ops[node+1].ival,&numarg); - str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg)); + str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); break; case OSTATE: str = str_new(0); if (len >= 1) { - str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); if (len >= 2) { - tmpstr = walk(0,level,ops[node+2].ival,&numarg); + tmpstr = walk(0,level,ops[node+2].ival,&numarg,P_MIN); if (*tmpstr->str_ptr == ';') { addsemi(str); str_cat(str,tmpstr->str_ptr+1); @@ -674,12 +1097,45 @@ sub Pick {\n\ } } break; + case OCLOSE: + str = str_make("close("); + tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN); + if (!do_fancy_opens) { + t = tmpstr->str_ptr; + if (*t == '"' || *t == '\'') + t = cpytill(tokenbuf,t+1,*t); + else + fatal("Internal error: OCLOSE %s",t); + s = savestr(tokenbuf); + for (t = tokenbuf; *t; t++) { + *t &= 127; + if (isLOWER(*t)) + *t = toUPPER(*t); + if (!isALPHA(*t) && !isDIGIT(*t)) + *t = '_'; + } + if (!strchr(tokenbuf,'_')) + strcpy(t,"_FH"); + str_free(tmpstr); + safefree(s); + str_set(str,"close "); + str_cat(str,tokenbuf); + } + else { + sprintf(tokenbuf,"delete $opened{%s} && close(%s)", + tmpstr->str_ptr, tmpstr->str_ptr); + str_free(tmpstr); + str_set(str,tokenbuf); + } + break; case OPRINTF: case OPRINT: + lparen = ""; /* set to parens if necessary */ + rparen = ""; str = str_new(0); if (len == 3) { /* output redirection */ - tmpstr = walk(1,level,ops[node+3].ival,&numarg); - tmp2str = walk(1,level,ops[node+2].ival,&numarg); + tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MIN); + tmp2str = walk(1,level,ops[node+2].ival,&numarg,P_MIN); if (!do_fancy_opens) { t = tmpstr->str_ptr; if (*t == '"' || *t == '\'') @@ -690,57 +1146,69 @@ sub Pick {\n\ s = savestr(tokenbuf); for (t = tokenbuf; *t; t++) { *t &= 127; - if (!isalpha(*t) && !isdigit(*t)) + if (isLOWER(*t)) + *t = toUPPER(*t); + if (!isALPHA(*t) && !isDIGIT(*t)) *t = '_'; } - if (!index(tokenbuf,'_')) - strcpy(t,"_fh"); - str_cat(opens,"open("); - str_cat(opens,tokenbuf); - str_cat(opens,", "); - d[1] = '\0'; - str_cat(opens,d); - str_scat(opens,tmp2str); - str_cat(opens,tmpstr->str_ptr+1); - if (*tmp2str->str_ptr == '|') - str_cat(opens,") || die 'Cannot pipe to \""); - else - str_cat(opens,") || die 'Cannot create file \""); - if (*d == '"') - str_cat(opens,"'.\""); - str_cat(opens,s); - if (*d == '"') - str_cat(opens,"\".'"); - str_cat(opens,"\".';\n"); + if (!strchr(tokenbuf,'_')) + strcpy(t,"_FH"); + tmp3str = hfetch(symtab,tokenbuf); + if (!tmp3str) { + str_cat(opens,"open("); + str_cat(opens,tokenbuf); + str_cat(opens,", "); + d[1] = '\0'; + str_cat(opens,d); + str_scat(opens,tmp2str); + str_cat(opens,tmpstr->str_ptr+1); + if (*tmp2str->str_ptr == '|') + str_cat(opens,") || die 'Cannot pipe to \""); + else + str_cat(opens,") || die 'Cannot create file \""); + if (*d == '"') + str_cat(opens,"'.\""); + str_cat(opens,s); + if (*d == '"') + str_cat(opens,"\".'"); + str_cat(opens,"\".';\n"); + hstore(symtab,tokenbuf,str_make("x")); + } str_free(tmpstr); str_free(tmp2str); safefree(s); safefree(d); } else { - sprintf(tokenbuf,"do Pick('%s' . (%s)) &&\n", + sprintf(tokenbuf,"&Pick('%s', %s) &&\n", tmp2str->str_ptr, tmpstr->str_ptr); str_cat(str,tokenbuf); tab(str,level+1); - *tokenbuf = '\0'; + strcpy(tokenbuf,"$fh"); str_free(tmpstr); str_free(tmp2str); + lparen = "("; + rparen = ")"; } } else - strcpy(tokenbuf,"stdout"); + strcpy(tokenbuf,""); + str_cat(str,lparen); /* may be null */ if (type == OPRINTF) str_cat(str,"printf"); else str_cat(str,"print"); + saw_fh = 0; if (len == 3 || do_fancy_opens) { - if (*tokenbuf) + if (*tokenbuf) { str_cat(str," "); + saw_fh = 1; + } str_cat(str,tokenbuf); } - tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg); + tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg,P_MIN); if (!*tmpstr->str_ptr && lval_field) { - t = saw_OFS ? "$," : "' '"; + t = (char*)(saw_OFS ? "$," : "' '"); if (split_to_array) { sprintf(tokenbuf,"join(%s,@Fld)",t); str_cat(tmpstr,tokenbuf); @@ -762,13 +1230,38 @@ sub Pick {\n\ } if (*tmpstr->str_ptr) { str_cat(str," "); - str_scat(str,tmpstr); + if (!saw_fh && *tmpstr->str_ptr == '(') { + str_cat(str,"("); + str_scat(str,tmpstr); + str_cat(str,")"); + } + else + str_scat(str,tmpstr); } else { str_cat(str," $_"); } + str_cat(str,rparen); /* may be null */ str_free(tmpstr); break; + case ORAND: + str = str_make("rand(1)"); + break; + case OSRAND: + str = str_make("srand("); + goto maybe0; + case OATAN2: + str = str_make("atan2("); + goto maybe0; + case OSIN: + str = str_make("sin("); + goto maybe0; + case OCOS: + str = str_make("cos("); + goto maybe0; + case OSYSTEM: + str = str_make("system("); + goto maybe0; case OLENGTH: str = str_make("length("); goto maybe0; @@ -786,12 +1279,12 @@ sub Pick {\n\ maybe0: numeric = 1; if (len > 0) - tmpstr = walk(1,level,ops[node+1].ival,&numarg); + tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN); else - tmpstr = str_new(0);; - if (!*tmpstr->str_ptr) { + tmpstr = str_new(0); + if (!tmpstr->str_ptr || !*tmpstr->str_ptr) { if (lval_field) { - t = saw_OFS ? "$," : "' '"; + t = (char*)(saw_OFS ? "$," : "' '"); if (split_to_array) { sprintf(tokenbuf,"join(%s,@Fld)",t); str_cat(tmpstr,tokenbuf); @@ -837,19 +1330,22 @@ sub Pick {\n\ case OEXIT: str = str_new(0); if (realexit) { + prec = P_UNI; str_set(str,"exit"); if (len == 1) { str_cat(str," "); exitval = TRUE; - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str, + fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1)); str_free(fstr); } } else { if (len == 1) { - str_set(str,"ExitValue = "); + str_set(str,"$ExitValue = "); exitval = TRUE; - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str, + fstr=walk(1,level,ops[node+1].ival,&numarg,P_ASSIGN)); str_free(fstr); str_cat(str,"; "); } @@ -865,10 +1361,10 @@ sub Pick {\n\ case OIF: str = str_new(0); str_set(str,"if ("); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,") "); - str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); if (len == 3) { i = ops[node+3].ival; @@ -885,12 +1381,12 @@ sub Pick {\n\ } if (i) { str_cat(str,"els"); - str_scat(str,fstr=walk(0,level,i,&numarg)); + str_scat(str,fstr=walk(0,level,i,&numarg,P_MIN)); str_free(fstr); } else { str_cat(str,"else "); - str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN)); str_free(fstr); } } @@ -898,28 +1394,40 @@ sub Pick {\n\ case OWHILE: str = str_new(0); str_set(str,"while ("); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,") "); - str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); break; + case ODO: + str = str_new(0); + str_set(str,"do "); + str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); + str_free(fstr); + if (str->str_ptr[str->str_cur - 1] == '\n') + --str->str_cur; + str_cat(str," while ("); + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); + str_free(fstr); + str_cat(str,");"); + break; case OFOR: str = str_new(0); str_set(str,"for ("); - str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg)); + str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); i = numarg; if (i) { t = s = tmpstr->str_ptr; - while (isalpha(*t) || isdigit(*t) || *t == '$' || *t == '_') + while (isALPHA(*t) || isDIGIT(*t) || *t == '$' || *t == '_') t++; i = t - s; if (i < 2) i = 0; } str_cat(str,"; "); - fstr=walk(1,level,ops[node+2].ival,&numarg); - if (i && (t = index(fstr->str_ptr,0377))) { + fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN); + if (i && (t = strchr(fstr->str_ptr,0377))) { if (strnEQ(fstr->str_ptr,s,i)) *t = ' '; } @@ -927,71 +1435,78 @@ sub Pick {\n\ str_free(fstr); str_free(tmpstr); str_cat(str,"; "); - str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg)); + str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,") "); - str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN)); str_free(fstr); break; case OFORIN: - tmpstr=walk(0,level,ops[node+2].ival,&numarg); + tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); + d = strchr(tmpstr->str_ptr,'$'); + if (!d) + fatal("Illegal for loop: %s",tmpstr->str_ptr); + s = strchr(d,'{'); + if (!s) + s = strchr(d,'['); + if (!s) + fatal("Illegal for loop: %s",d); + *s++ = '\0'; + for (t = s; (i = *t); t++) { + i &= 127; + if (i == '}' || i == ']') + break; + } + if (*t) + *t = '\0'; str = str_new(0); - str_sset(str,tmpstr); + str_set(str,d+1); str_cat(str,"[]"); tmp2str = hfetch(symtab,str->str_ptr); if (tmp2str && atoi(tmp2str->str_ptr)) { - maxtmp++; - fstr=walk(1,level,ops[node+1].ival,&numarg); sprintf(tokenbuf, - "for ($T_%d = 1; ($%s = $%s[$T_%d]) || $T_%d <= $#%s; $T_%d++)%c", - maxtmp, - fstr->str_ptr, - tmpstr->str_ptr, - maxtmp, - maxtmp, - tmpstr->str_ptr, - maxtmp, - 0377); - str_set(str,tokenbuf); - str_free(fstr); - str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg)); - str_free(fstr); + "foreach %s ($[ .. $#%s) ", + s, + d+1); } else { - str_set(str,"while (($junkkey,$"); - str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg)); - str_free(fstr); - str_cat(str,") = each("); - str_scat(str,tmpstr); - str_cat(str,")) "); - str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg)); - str_free(fstr); + sprintf(tokenbuf, + "foreach %s (keys %%%s) ", + s, + d+1); } + str_set(str,tokenbuf); + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); + str_free(fstr); str_free(tmpstr); break; case OBLOCK: str = str_new(0); str_set(str,"{"); - if (len == 2) { - str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg)); + if (len >= 2 && ops[node+2].ival) { + str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); } fixtab(str,++level); - str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); addsemi(str); fixtab(str,--level); str_cat(str,"}\n"); tab(str,level); + if (len >= 3) { + str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN)); + str_free(fstr); + } break; default: def: if (len) { if (len > 5) fatal("Garbage length in walk"); - str = walk(0,level,ops[node+1].ival,&numarg); + str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); for (i = 2; i<= len; i++) { - str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg)); + str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg,P_MIN)); str_free(fstr); } } @@ -1002,6 +1517,16 @@ sub Pick {\n\ } if (!str) str = str_new(0); + + if (useval && prec < minprec) { /* need parens? */ + fstr = str_new(str->str_cur+2); + str_nset(fstr,"(",1); + str_scat(fstr,str); + str_ncat(fstr,")",1); + str_free(str); + str = fstr; + } + *numericptr = numeric; #ifdef DEBUGGING if (debug & 4) { @@ -1019,9 +1544,8 @@ sub Pick {\n\ return str; } -tab(str,lvl) -register STR *str; -register int lvl; +static void +tab(register STR *str, register int lvl) { while (lvl > 1) { str_cat(str,"\t"); @@ -1031,16 +1555,15 @@ register int lvl; str_cat(str," "); } -fixtab(str,lvl) -register STR *str; -register int lvl; +static void +fixtab(register STR *str, register int lvl) { register char *s; /* strip trailing white space */ s = str->str_ptr+str->str_cur - 1; - while (s >= str->str_ptr && (*s == ' ' || *s == '\t')) + while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n')) s--; s[1] = '\0'; str->str_cur = s + 1 - str->str_ptr; @@ -1050,8 +1573,8 @@ register int lvl; tab(str,lvl); } -addsemi(str) -register STR *str; +static void +addsemi(register STR *str) { register char *s; @@ -1062,9 +1585,8 @@ register STR *str; str_cat(str,";"); } -emit_split(str,level) -register STR *str; -int level; +static void +emit_split(register STR *str, int level) { register int i; @@ -1086,29 +1608,26 @@ int level; str_cat(str,tokenbuf); } if (const_FS) { - sprintf(tokenbuf," = split(/[%c\\n]/);\n",const_FS); + sprintf(tokenbuf," = split(/[%c\\n]/, $_, -1);\n",const_FS); str_cat(str,tokenbuf); } else if (saw_FS) - str_cat(str," = split($FS);\n"); + str_cat(str," = split($FS, $_, -1);\n"); else - str_cat(str," = split;\n"); + str_cat(str," = split(' ', $_, -1);\n"); tab(str,level); } -prewalk(numit,level,node,numericptr) -int numit; -int level; -register int node; -int *numericptr; +int +prewalk(int numit, int level, register int node, int *numericptr) { register int len; register int type; register int i; - char *t; - char *d, *s; int numarg; int numeric = FALSE; + STR *tmpstr; + STR *tmp2str; if (!node) { *numericptr = 0; @@ -1224,7 +1743,7 @@ int *numericptr; prewalk(0,level,ops[node+2].ival,&numarg); prewalk(0,level,ops[node+1].ival,&numarg); prewalk(0,level,ops[node+3].ival,&numarg); - if (numarg || strlen(ops[ops[node+1].ival+1].cval) > 1) { + if (numarg || strlen(ops[ops[node+1].ival+1].cval) > (Size_t)1) { numericize(ops[node+2].ival); if (!numarg) numericize(ops[node+3].ival); @@ -1236,7 +1755,7 @@ int *numericptr; prewalk(1,level,ops[node+2].ival,&numarg); numeric = 1; break; - case OSUB: + case OSUBTRACT: prewalk(1,level,ops[node+1].ival,&numarg); prewalk(1,level,ops[node+2].ival,&numarg); numeric = 1; @@ -1251,6 +1770,11 @@ int *numericptr; prewalk(1,level,ops[node+2].ival,&numarg); numeric = 1; break; + case OPOW: + prewalk(1,level,ops[node+1].ival,&numarg); + prewalk(1,level,ops[node+2].ival,&numarg); + numeric = 1; + break; case OMOD: prewalk(1,level,ops[node+1].ival,&numarg); prewalk(1,level,ops[node+2].ival,&numarg); @@ -1310,6 +1834,55 @@ int *numericptr; prewalk(0,level,ops[node+2].ival,&numarg); numeric = 1; break; + case OMATCH: + prewalk(0,level,ops[node+1].ival,&numarg); + prewalk(0,level,ops[node+2].ival,&numarg); + numeric = 1; + break; + case OUSERDEF: + subretnum = FALSE; + --level; + tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); + ++level; + prewalk(0,level,ops[node+2].ival,&numarg); + prewalk(0,level,ops[node+4].ival,&numarg); + prewalk(0,level,ops[node+5].ival,&numarg); + --level; + str_cat(tmpstr,"("); + tmp2str = str_new(0); + if (subretnum || numarg) + str_set(tmp2str,"1"); + hstore(symtab,tmpstr->str_ptr,tmp2str); + str_free(tmpstr); + level++; + break; + case ORETURN: + if (len > 0) { + prewalk(0,level,ops[node+1].ival,&numarg); + if (numarg) + subretnum = TRUE; + } + break; + case OUSERFUN: + tmp2str = str_new(0); + str_scat(tmp2str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); + fixrargs(tmpstr->str_ptr,ops[node+2].ival,0); + str_free(tmpstr); + str_cat(tmp2str,"("); + tmpstr = hfetch(symtab,tmp2str->str_ptr); + if (tmpstr && tmpstr->str_ptr) + numeric |= atoi(tmpstr->str_ptr); + prewalk(0,level,ops[node+2].ival,&numarg); + str_free(tmp2str); + break; + case OGSUB: + case OSUB: + if (len >= 3) + prewalk(0,level,ops[node+3].ival,&numarg); + prewalk(0,level,ops[ops[node+2].ival+1].ival,&numarg); + prewalk(0,level,ops[node+1].ival,&numarg); + numeric = 1; + break; case ONUM: prewalk(0,level,ops[node+1].ival,&numarg); numeric = 1; @@ -1317,6 +1890,9 @@ int *numericptr; case OSTR: prewalk(0,level,ops[node+1].ival,&numarg); break; + case ODEFINED: + case ODELETE: + case OSTAR: case OVAR: prewalk(0,level,ops[node+1].ival,&numarg); if (len == 1) { @@ -1347,6 +1923,7 @@ int *numericptr; case OCOMMA: prewalk(0,level,ops[node+1].ival,&numarg); prewalk(0,level,ops[node+2].ival,&numarg); + prewalk(0,level,ops[node+3].ival,&numarg); break; case OSEMICOLON: break; @@ -1362,6 +1939,9 @@ int *numericptr; } } break; + case OCLOSE: + prewalk(0,level,ops[node+1].ival,&numarg); + break; case OPRINTF: case OPRINT: if (len == 3) { /* output redirection */ @@ -1370,6 +1950,18 @@ int *numericptr; } prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg); break; + case ORAND: + break; + case OSRAND: + goto maybe0; + case OATAN2: + goto maybe0; + case OSIN: + goto maybe0; + case OCOS: + goto maybe0; + case OSYSTEM: + goto maybe0; case OLENGTH: goto maybe0; case OLOG: @@ -1382,7 +1974,8 @@ int *numericptr; maybe0: numeric = 1; if (len > 0) - prewalk(type != OLENGTH,level,ops[node+1].ival,&numarg); + prewalk(type != OLENGTH && type != OSYSTEM, + level,ops[node+1].ival,&numarg); break; case OBREAK: break; @@ -1417,7 +2010,6 @@ int *numericptr; case OFORIN: prewalk(0,level,ops[node+2].ival,&numarg); prewalk(0,level,ops[node+1].ival,&numarg); - prewalk(0,level,ops[node+3].ival,&numarg); break; case OBLOCK: if (len == 2) { @@ -1443,12 +2035,11 @@ int *numericptr; return 1; } -numericize(node) -register int node; +static void +numericize(register int node) { register int len; register int type; - register int i; STR *tmpstr; STR *tmp2str; int numarg; @@ -1457,7 +2048,7 @@ register int node; len = type >> 8; type &= 255; if (type == OVAR && len == 1) { - tmpstr=walk(0,0,ops[node+1].ival,&numarg); + tmpstr=walk(0,0,ops[node+1].ival,&numarg,P_MIN); tmp2str = str_make("1"); hstore(symtab,tmpstr->str_ptr,tmp2str); }