lwall@jato.Jpl.Nasa.Gov (Larry Wall) (09/03/89)
#! /bin/sh # Make a new directory for the perl sources, cd to it, and run kits 1 # thru 23 through sh. When all 23 kits have been run, read README. echo "This is perl 3.0 kit 2 (of 23). If kit 2 is complete, the line" echo '"'"End of kit 2 (of 23)"'" will echo at the end.' echo "" export PATH || (echo "You didn't use sh, you clunch." ; kill $$) mkdir x2p 2>/dev/null echo Extracting x2p/walk.c sed >x2p/walk.c <<'!STUFFY!FUNK!' -e 's/X//' X/* $Header: walk.c,v 2.0.1.4 88/08/05 01:31:14 root Exp $ X * X * Copyright (c) 1989, Larry Wall X * X * You may distribute under the terms of the GNU General Public License X * as specified in the README file that comes with the perl 3.0 kit. X * X * $Log: walk.c,v $ X * Revision 2.0.1.4 88/08/05 01:31:14 root X * patch13: dumb typo in last patch X * X * Revision 2.0.1.3 88/08/03 22:54:39 root X * patch11: a2p was being really stupid about comparisons with literal strings X * patch11: a2p tried to make a local declaration on a null argument list X * patch11: fixed possible null pointer dereference X * patch11: comma didn't allow newline after it X * X * Revision 2.0.1.2 88/07/15 01:39:36 root X * patch9: gcc complained about "\$", so it's now "\\$" X * X * Revision 2.0.1.1 88/07/11 23:35:57 root X * patch2: changes to support translation of 1985 awk X * patch2: handles multiple opens to same file better X * patch2: now handles absence of line actions X * patch2: now takes advantage of perl's filehandle indirection X * patch2: now uses keys() instead of each() to protect against deletes in loop X * X * Revision 2.0 88/06/05 00:16:12 root X * Baseline version 2.0. X * X */ X X#include "handy.h" X#include "EXTERN.h" X#include "util.h" X#include "a2p.h" X Xbool exitval = FALSE; Xbool realexit = FALSE; Xbool saw_getline = FALSE; Xbool subretnum = FALSE; Xbool saw_FNR = FALSE; Xbool saw_argv0 = FALSE; Xint maxtmp = 0; Xchar *lparen; Xchar *rparen; XSTR *subs; XSTR *curargs = Nullstr; X XSTR * Xwalk(useval,level,node,numericptr,minprec) Xint useval; Xint level; Xregister int node; Xint *numericptr; Xint minprec; /* minimum precedence without parens */ X{ X register int len; X register STR *str; X register int type; X register int i; X register STR *tmpstr; X STR *tmp2str; X STR *tmp3str; X char *t; X char *d, *s; X int numarg; X int numeric = FALSE; X STR *fstr; X int prec = P_MAX; /* assume no parens needed */ X char *index(); X X if (!node) { X *numericptr = 0; X return str_make(""); X } X type = ops[node].ival; X len = type >> 8; X type &= 255; X switch (type) { X case OPROG: X opens = str_new(0); X subs = str_new(0); X str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X if (do_split && need_entire && !absmaxfld) X split_to_array = TRUE; X if (do_split && split_to_array) X set_array_base = TRUE; X if (set_array_base) { X str_cat(str,"$[ = 1;\t\t\t# set array base to 1\n"); X } X if (fswitch && !const_FS) X const_FS = fswitch; X if (saw_FS > 1 || saw_RS) X const_FS = 0; X if (saw_ORS && need_entire) X do_chop = TRUE; X if (fswitch) { X str_cat(str,"$FS = '"); X if (index("*+?.[]()|^$\\",fswitch)) X str_cat(str,"\\"); X sprintf(tokenbuf,"%c",fswitch); X str_cat(str,tokenbuf); X str_cat(str,"';\t\t# field separator from -F switch\n"); X } X else if (saw_FS && !const_FS) { X str_cat(str,"$FS = ' ';\t\t# set field separator\n"); X } X if (saw_OFS) { X str_cat(str,"$, = ' ';\t\t# set output field separator\n"); X } X if (saw_ORS) { X str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n"); X } X if (saw_argv0) { X str_cat(str,"$ARGV0 = $0;\t\t# remember what we ran as\n"); X } X if (str->str_cur > 20) X str_cat(str,"\n"); X if (ops[node+2].ival) { X str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,"\n\n"); X } X fstr = walk(0,level+1,ops[node+3].ival,&numarg,P_MIN); X if (*fstr->str_ptr) { X if (saw_line_op) X str_cat(str,"line: "); X str_cat(str,"while (<>) {\n"); X tab(str,++level); X if (saw_FS && !const_FS) X do_chop = TRUE; X if (do_chop) { X str_cat(str,"chop;\t# strip record separator\n"); X tab(str,level); X } X arymax = 0; X if (namelist) { X while (isalpha(*namelist)) { X for (d = tokenbuf,s=namelist; X isalpha(*s) || isdigit(*s) || *s == '_'; X *d++ = *s++) ; X *d = '\0'; X while (*s && !isalpha(*s)) s++; X namelist = s; X nameary[++arymax] = savestr(tokenbuf); X } X } X if (maxfld < arymax) X maxfld = arymax; X if (do_split) X emit_split(str,level); X str_scat(str,fstr); X str_free(fstr); X fixtab(str,--level); X str_cat(str,"}\n"); X if (saw_FNR) X str_cat(str,"continue {\n $FNRbase = $. if eof;\n}\n"); X } X else X str_cat(str,"# (no line actions)\n"); X if (ops[node+4].ival) { X realexit = TRUE; X str_cat(str,"\n"); X tab(str,level); X str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,"\n"); X } X if (exitval) X str_cat(str,"exit ExitValue;\n"); X if (subs->str_ptr) { X str_cat(str,"\n"); X str_scat(str,subs); X } X if (saw_getline) { X for (len = 0; len < 4; len++) { X if (saw_getline & (1 << len)) { X sprintf(tokenbuf,"\nsub Getline%d {\n",len); X str_cat(str, tokenbuf); X if (len & 2) { X if (do_fancy_opens) X str_cat(str," &Pick('',@_);\n"); X else X str_cat(str," ($fh) = @_;\n"); X } X else { X if (saw_FNR) X str_cat(str," $FNRbase = $. if eof;\n"); X } X if (len & 1) X str_cat(str," local($_)\n"); X if (len & 2) X str_cat(str, X " if ($getline_ok = (($_ = <$fh>) ne ''))"); X else X str_cat(str, X " if ($getline_ok = (($_ = <>) ne ''))"); X str_cat(str, " {\n"); X level += 2; X tab(str,level); X i = 0; X if (do_chop) { X i++; X str_cat(str,"chop;\t# strip record separator\n"); X tab(str,level); X } X if (do_split && !(len & 1)) { X i++; X emit_split(str,level); X } X if (!i) X str_cat(str,";\n"); X fixtab(str,--level); X str_cat(str,"}\n $_;\n}\n"); X --level; X } X } X } X if (do_fancy_opens) { X str_cat(str,"\n\ Xsub Pick {\n\ X local($mode,$name,$pipe) = @_;\n\ X $fh = $opened{$name};\n\ X if (!$fh) {\n\ X $fh = $opened{$name} = 'fh_' . ($nextfh++ + 0);\n\ X open($fh,$mode.$name.$pipe);\n\ X }\n\ X}\n\ X"); X } X break; X case OHUNKS: X str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X if (len == 3) { X str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN)); X str_free(fstr); X } X else { X } X break; X case ORANGE: X prec = P_DOTDOT; X str = walk(1,level,ops[node+1].ival,&numarg,prec+1); X str_cat(str," .. "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X break; X case OPAT: X goto def; X case OREGEX: X str = str_new(0); X str_set(str,"/"); X tmpstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN); X /* translate \nnn to [\nnn] */ X for (s = tmpstr->str_ptr, d = tokenbuf; *s; s++, d++) { X if (*s == '\\' && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])){ X *d++ = '['; X *d++ = *s++; X *d++ = *s++; X *d++ = *s++; X *d++ = *s; X *d = ']'; X } X else X *d = *s; X } X *d = '\0'; X for (d=tokenbuf; *d; d++) X *d += 128; X str_cat(str,tokenbuf); X str_free(tmpstr); X str_cat(str,"/"); X break; X case OHUNK: X if (len == 1) { X str = str_new(0); X str = walk(0,level,oper1(OPRINT,0),&numarg,P_MIN); X str_cat(str," if "); X str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,";"); X } X else { X tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X if (*tmpstr->str_ptr) { X str = str_new(0); X str_set(str,"if ("); X str_scat(str,tmpstr); X str_cat(str,") {\n"); X tab(str,++level); X str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X fixtab(str,--level); X str_cat(str,"}\n"); X tab(str,level); X } X else { X str = walk(0,level,ops[node+2].ival,&numarg,P_MIN); X } X } X break; X case OPPAREN: X str = str_new(0); X str_set(str,"("); X str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,")"); X break; X case OPANDAND: X prec = P_ANDAND; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X str_cat(str," && "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); X str_free(fstr); X break; X case OPOROR: X prec = P_OROR; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X str_cat(str," || "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); X str_free(fstr); X break; X case OPNOT: X prec = P_UNARY; X str = str_new(0); X str_set(str,"!"); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec)); X str_free(fstr); X break; X case OCPAREN: X str = str_new(0); X str_set(str,"("); X str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X numeric |= numarg; X str_cat(str,")"); X break; X case OCANDAND: X prec = P_ANDAND; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X numeric = 1; X str_cat(str," && "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); X str_free(fstr); X break; X case OCOROR: X prec = P_OROR; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X numeric = 1; X str_cat(str," || "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); X str_free(fstr); X break; X case OCNOT: X prec = P_UNARY; X str = str_new(0); X str_set(str,"!"); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec)); X str_free(fstr); X numeric = 1; X break; X case ORELOP: X prec = P_REL; X str = walk(1,level,ops[node+2].ival,&numarg,prec+1); X numeric |= numarg; X tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X tmp2str = walk(1,level,ops[node+3].ival,&numarg,prec+1); X numeric |= numarg; X if (!numeric || X (!numarg && (*tmp2str->str_ptr == '"' || *tmp2str->str_ptr == '\''))) { X t = tmpstr->str_ptr; X if (strEQ(t,"==")) X str_set(tmpstr,"eq"); X else if (strEQ(t,"!=")) X str_set(tmpstr,"ne"); X else if (strEQ(t,"<")) X str_set(tmpstr,"lt"); X else if (strEQ(t,"<=")) X str_set(tmpstr,"le"); X else if (strEQ(t,">")) X str_set(tmpstr,"gt"); X else if (strEQ(t,">=")) X str_set(tmpstr,"ge"); X if (!index(tmpstr->str_ptr,'\'') && !index(tmpstr->str_ptr,'"') && X !index(tmp2str->str_ptr,'\'') && !index(tmp2str->str_ptr,'"') ) X numeric |= 2; X } X if (numeric & 2) { X if (numeric & 1) /* numeric is very good guess */ X str_cat(str," "); X else X str_cat(str,"\377"); X numeric = 1; X } X else X str_cat(str," "); X str_scat(str,tmpstr); X str_free(tmpstr); X str_cat(str," "); X str_scat(str,tmp2str); X str_free(tmp2str); X numeric = 1; X break; X case ORPAREN: X str = str_new(0); X str_set(str,"("); X str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X numeric |= numarg; X str_cat(str,")"); X break; X case OMATCHOP: X prec = P_MATCH; X str = walk(1,level,ops[node+2].ival,&numarg,prec+1); X str_cat(str," "); X tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X if (strEQ(tmpstr->str_ptr,"~")) X str_cat(str,"=~"); X else { X str_scat(str,tmpstr); X str_free(tmpstr); X } X str_cat(str," "); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); X str_free(fstr); X numeric = 1; X break; X case OMPAREN: X str = str_new(0); X str_set(str,"("); X str_scat(str, X fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X numeric |= numarg; X str_cat(str,")"); X break; X case OCONCAT: X prec = P_ADD; X type = ops[ops[node+1].ival].ival & 255; X str = walk(1,level,ops[node+1].ival,&numarg,prec+(type != OCONCAT)); X str_cat(str," . "); X type = ops[ops[node+2].ival].ival & 255; X str_scat(str, X fstr=walk(1,level,ops[node+2].ival,&numarg,prec+(type != OCONCAT))); X str_free(fstr); X break; X case OASSIGN: X prec = P_ASSIGN; X str = walk(0,level,ops[node+2].ival,&numarg,prec+1); X str_cat(str," "); X tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X str_scat(str,tmpstr); X if (str_len(tmpstr) > 1) X numeric = 1; X str_free(tmpstr); X str_cat(str," "); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec)); X str_free(fstr); X numeric |= numarg; X break; X case OADD: X prec = P_ADD; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X str_cat(str," + "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X numeric = 1; X break; X case OSUBTRACT: X prec = P_ADD; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X str_cat(str," - "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X numeric = 1; X break; X case OMULT: X prec = P_MUL; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X str_cat(str," * "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X numeric = 1; X break; X case ODIV: X prec = P_MUL; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X str_cat(str," / "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X numeric = 1; X break; X case OPOW: X prec = P_POW; X str = walk(1,level,ops[node+1].ival,&numarg,prec+1); X str_cat(str," ** "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec)); X str_free(fstr); X numeric = 1; X break; X case OMOD: X prec = P_MUL; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X str_cat(str," % "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); X str_free(fstr); X numeric = 1; X break; X case OPOSTINCR: X prec = P_AUTO; X str = walk(1,level,ops[node+1].ival,&numarg,prec+1); X str_cat(str,"++"); X numeric = 1; X break; X case OPOSTDECR: X prec = P_AUTO; X str = walk(1,level,ops[node+1].ival,&numarg,prec+1); X str_cat(str,"--"); X numeric = 1; X break; X case OPREINCR: X prec = P_AUTO; X str = str_new(0); X str_set(str,"++"); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1)); X str_free(fstr); X numeric = 1; X break; X case OPREDECR: X prec = P_AUTO; X str = str_new(0); X str_set(str,"--"); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1)); X str_free(fstr); X numeric = 1; X break; X case OUMINUS: X prec = P_UNARY; X str = str_new(0); X str_set(str,"-"); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec)); X str_free(fstr); X numeric = 1; X break; X case OUPLUS: X numeric = 1; X goto def; X case OPAREN: X str = str_new(0); X str_set(str,"("); X str_scat(str, X fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,")"); X numeric |= numarg; X break; X case OGETLINE: X str = str_new(0); X if (useval) X str_cat(str,"("); X if (len > 0) { X str_cat(str,"$"); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X if (!*fstr->str_ptr) { X str_cat(str,"_"); X len = 2; /* a legal fiction */ X } X str_free(fstr); X } X else X str_cat(str,"$_"); X if (len > 1) { X tmpstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN); X fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN); X if (!do_fancy_opens) { X t = tmpstr->str_ptr; X if (*t == '"' || *t == '\'') X t = cpytill(tokenbuf,t+1,*t); X else X fatal("Internal error: OGETLINE %s", t); X d = savestr(t); X s = savestr(tokenbuf); X for (t = tokenbuf; *t; t++) { X *t &= 127; X if (!isalpha(*t) && !isdigit(*t)) X *t = '_'; X } X if (!index(tokenbuf,'_')) X strcpy(t,"_fh"); X tmp3str = hfetch(symtab,tokenbuf); X if (!tmp3str) { X do_opens = TRUE; X str_cat(opens,"open("); X str_cat(opens,tokenbuf); X str_cat(opens,", "); X d[1] = '\0'; X str_cat(opens,d); X str_cat(opens,tmpstr->str_ptr+1); X opens->str_cur--; X if (*fstr->str_ptr == '|') X str_cat(opens,"|"); X str_cat(opens,d); X if (*fstr->str_ptr == '|') X str_cat(opens,") || die 'Cannot pipe from \""); X else X str_cat(opens,") || die 'Cannot open file \""); X if (*d == '"') X str_cat(opens,"'.\""); X str_cat(opens,s); X if (*d == '"') X str_cat(opens,"\".'"); X str_cat(opens,"\".';\n"); X hstore(symtab,tokenbuf,str_make("x")); X } X safefree(s); X safefree(d); X str_set(tmpstr,"'"); X str_cat(tmpstr,tokenbuf); X str_cat(tmpstr,"'"); X } X if (*fstr->str_ptr == '|') X str_cat(tmpstr,", '|'"); X str_free(fstr); X } X else X tmpstr = str_make(""); X sprintf(tokenbuf," = &Getline%d(%s)",len,tmpstr->str_ptr); X str_cat(str,tokenbuf); X str_free(tmpstr); X if (useval) X str_cat(str,",$getline_ok)"); X saw_getline |= 1 << len; X break; X case OSPRINTF: X str = str_new(0); X str_set(str,"sprintf("); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,")"); X break; X case OSUBSTR: X str = str_new(0); X str_set(str,"substr("); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1)); X str_free(fstr); X str_cat(str,", "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1)); X str_free(fstr); X str_cat(str,", "); X if (len == 3) { X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1)); X str_free(fstr); X } X else X str_cat(str,"999999"); X str_cat(str,")"); X break; X case OSTRING: X str = str_new(0); X str_set(str,ops[node+1].cval); X break; X case OSPLIT: X str = str_new(0); X numeric = 1; X tmpstr = walk(1,level,ops[node+2].ival,&numarg,P_MIN); X if (useval) X str_set(str,"(@"); X else X str_set(str,"@"); X str_scat(str,tmpstr); X str_cat(str," = split("); X if (len == 3) { X fstr = walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1); X if (str_len(fstr) == 3 && *fstr->str_ptr == '\'') { X i = fstr->str_ptr[1] & 127; X if (index("*+?.[]()|^$\\",i)) X sprintf(tokenbuf,"/\\%c/",i); X else X sprintf(tokenbuf,"/%c/",i); X str_cat(str,tokenbuf); X } X else X str_scat(str,fstr); X str_free(fstr); X } X else if (const_FS) { X sprintf(tokenbuf,"/[%c\\n]/",const_FS); X str_cat(str,tokenbuf); X } X else if (saw_FS) X str_cat(str,"$FS"); X else X str_cat(str,"' '"); X str_cat(str,", "); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1)); X str_free(fstr); X str_cat(str,", 999)"); X if (useval) { X str_cat(str,")"); X } X str_free(tmpstr); X break; X case OINDEX: X str = str_new(0); X str_set(str,"index("); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1)); X str_free(fstr); X str_cat(str,", "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1)); X str_free(fstr); X str_cat(str,")"); X numeric = 1; X break; X case OMATCH: X str = str_new(0); X prec = P_ANDAND; X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MATCH+1)); X str_free(fstr); X str_cat(str," =~ "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MATCH+1)); X str_free(fstr); X str_cat(str," && ($RLENGTH = length($&), $RSTART = length($`)+1)"); X numeric = 1; X break; X case OUSERDEF: X str = str_new(0); X subretnum = FALSE; X fstr=walk(1,level-1,ops[node+2].ival,&numarg,P_MIN); X curargs = str_new(0); X str_sset(curargs,fstr); X str_cat(curargs,","); X tmp2str=walk(1,level,ops[node+5].ival,&numarg,P_MIN); X str_free(curargs); X curargs = Nullstr; X level--; X subretnum |= numarg; X s = Nullch; X t = tmp2str->str_ptr; X while (t = instr(t,"return ")) X s = t++; X if (s) { X i = 0; X for (t = s+7; *t; t++) { X if (*t == ';' || *t == '}') X i++; X } X if (i == 1) { X strcpy(s,s+7); X tmp2str->str_cur -= 7; X } X } X str_set(str,"\n"); X tab(str,level); X str_cat(str,"sub "); X str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X str_cat(str," {\n"); X tab(str,++level); X if (fstr->str_cur) { X str_cat(str,"local("); X str_scat(str,fstr); X str_cat(str,") = @_;"); X } X str_free(fstr); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN)); X str_free(fstr); X fixtab(str,level); X str_scat(str,fstr=walk(1,level,ops[node+4].ival,&numarg,P_MIN)); X str_free(fstr); X fixtab(str,level); X str_scat(str,tmp2str); X str_free(tmp2str); X fixtab(str,--level); X str_cat(str,"}\n"); X tab(str,level); X str_scat(subs,str); X str_set(str,""); X str_cat(tmpstr,"("); X tmp2str = str_new(0); X if (subretnum) X str_set(tmp2str,"1"); X hstore(symtab,tmpstr->str_ptr,tmp2str); X str_free(tmpstr); X level++; X break; X case ORETURN: X str = str_new(0); X if (len > 0) { X str_cat(str,"return "); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_UNI+1)); X str_free(fstr); X if (numarg) X subretnum = TRUE; X } X else X str_cat(str,"return"); X break; X case OUSERFUN: X str = str_new(0); X str_set(str,"&"); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,"("); X tmpstr = hfetch(symtab,str->str_ptr+3); X if (tmpstr && tmpstr->str_ptr) X numeric |= atoi(tmpstr->str_ptr); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,")"); X break; X case OGSUB: X case OSUB: X if (type == OGSUB) X s = "g"; X else X s = ""; X str = str_new(0); X tmpstr = str_new(0); X i = 0; X if (len == 3) { X tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MATCH+1); X if (strNE(tmpstr->str_ptr,"$_")) { X str_cat(tmpstr, " =~ s"); X i++; X } X else X str_set(tmpstr, "s"); X } X else X str_set(tmpstr, "s"); X type = ops[ops[node+2].ival].ival; X len = type >> 8; X type &= 255; X tmp3str = str_new(0); X if (type == OSTR) { X tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg,P_MIN); X for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) { X if (*t == '&') X *d++ = '$' + 128; X else if (*t == '$') X *d++ = '\\' + 128; X *d = *t + 128; X } X *d = '\0'; X str_set(tmp2str,tokenbuf); X } X else { X tmp2str=walk(1,level,ops[node+2].ival,&numarg,P_MIN); X str_set(tmp3str,"($s_ = '\"'.("); X str_scat(tmp3str,tmp2str); X str_cat(tmp3str,").'\"') =~ s/&/\\$&/g, "); X str_set(tmp2str,"eval $s_"); X s = (*s == 'g' ? "ge" : "e"); X i++; X } X type = ops[ops[node+1].ival].ival; X len = type >> 8; X type &= 255; X fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN); X if (type == OREGEX) { X if (useval && i) X str_cat(str,"("); X str_scat(str,tmp3str); X str_scat(str,tmpstr); X str_scat(str,fstr); X str_scat(str,tmp2str); X str_cat(str,"/"); X str_cat(str,s); X } X else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) { X if (useval && i) X str_cat(str,"("); X str_scat(str,tmp3str); X str_scat(str,tmpstr); X str_cat(str,"/"); X str_scat(str,fstr); X str_cat(str,"/"); X str_scat(str,tmp2str); X str_cat(str,"/"); X str_cat(str,s); X } X else { X i++; X if (useval) X str_cat(str,"("); X str_cat(str,"$s = "); X str_scat(str,fstr); X str_cat(str,", "); X str_scat(str,tmp3str); X str_scat(str,tmpstr); X str_cat(str,"/$s/"); X str_scat(str,tmp2str); X str_cat(str,"/"); X str_cat(str,s); X } X if (useval && i) X str_cat(str,")"); X str_free(fstr); X str_free(tmpstr); X str_free(tmp2str); X str_free(tmp3str); X numeric = 1; X break; X case ONUM: X str = walk(1,level,ops[node+1].ival,&numarg,P_MIN); X numeric = 1; X break; X case OSTR: X tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN); X s = "'"; X for (t = tmpstr->str_ptr, d=tokenbuf; *t; d++,t++) { X if (*t == '\'') X s = "\""; X else if (*t == '\\') { X s = "\""; X *d++ = *t++ + 128; X switch (*t) { X case '\\': case '"': case 'n': case 't': X break; X default: /* hide this from perl */ X *d++ = '\\' + 128; X } X } X *d = *t + 128; X } X *d = '\0'; X str = str_new(0); X str_set(str,s); X str_cat(str,tokenbuf); X str_free(tmpstr); X str_cat(str,s); X break; X case ODEFINED: X prec = P_UNI; X str = str_new(0); X str_set(str,"defined $"); X goto addvar; X case ODELETE: X str = str_new(0); X str_set(str,"delete $"); X goto addvar; X case OSTAR: X str = str_new(0); X str_set(str,"*"); X goto addvar; X case OVAR: X str = str_new(0); X str_set(str,"$"); X addvar: X str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X if (len == 1) { X tmp2str = hfetch(symtab,tmpstr->str_ptr); X if (tmp2str && atoi(tmp2str->str_ptr)) X numeric = 2; X if (strEQ(str->str_ptr,"$FNR")) { X numeric = 1; X saw_FNR++; X str_set(str,"($.-$FNRbase)"); X } X else if (strEQ(str->str_ptr,"$NR")) { X numeric = 1; X str_set(str,"$."); X } X else if (strEQ(str->str_ptr,"$NF")) { X numeric = 1; X str_set(str,"$#Fld"); X } X else if (strEQ(str->str_ptr,"$0")) X str_set(str,"$_"); X else if (strEQ(str->str_ptr,"$ARGC")) X str_set(str,"($#ARGV+1)"); X } X else { X#ifdef NOTDEF X if (curargs) { X sprintf(tokenbuf,"$%s,",tmpstr->str_ptr); X ??? if (instr(curargs->str_ptr,tokenbuf)) X str_cat(str,"\377"); /* can't translate yet */ X } X#endif X str_cat(tmpstr,"[]"); X tmp2str = hfetch(symtab,tmpstr->str_ptr); X if (tmp2str && atoi(tmp2str->str_ptr)) X str_cat(str,"["); X else X str_cat(str,"{"); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X if (strEQ(str->str_ptr,"$ARGV[0")) { X str_set(str,"$ARGV0"); X saw_argv0++; X } X else { X if (tmp2str && atoi(tmp2str->str_ptr)) X strcpy(tokenbuf,"]"); X else X strcpy(tokenbuf,"}"); X *tokenbuf += 128; X str_cat(str,tokenbuf); X } X } X str_free(tmpstr); X break; X case OFLD: X str = str_new(0); X if (split_to_array) { X str_set(str,"$Fld"); X str_cat(str,"["); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,"]"); X } X else { X i = atoi(walk(1,level,ops[node+1].ival,&numarg,P_MIN)->str_ptr); X if (i <= arymax) X sprintf(tokenbuf,"$%s",nameary[i]); X else X sprintf(tokenbuf,"$Fld%d",i); X str_set(str,tokenbuf); X } X break; X case OVFLD: X str = str_new(0); X str_set(str,"$Fld["); X i = ops[node+1].ival; X if ((ops[i].ival & 255) == OPAREN) X i = ops[i+1].ival; X tmpstr=walk(1,level,i,&numarg,P_MIN); X str_scat(str,tmpstr); X str_free(tmpstr); X str_cat(str,"]"); X break; X case OJUNK: X goto def; X case OSNEWLINE: X str = str_new(2); X str_set(str,";\n"); X tab(str,level); X break; X case ONEWLINE: X str = str_new(1); X str_set(str,"\n"); X tab(str,level); X break; X case OSCOMMENT: X str = str_new(0); X str_set(str,";"); X tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X for (s = tmpstr->str_ptr; *s && *s != '\n'; s++) X *s += 128; X str_scat(str,tmpstr); X str_free(tmpstr); X tab(str,level); X break; X case OCOMMENT: X str = str_new(0); X tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X for (s = tmpstr->str_ptr; *s && *s != '\n'; s++) X *s += 128; X str_scat(str,tmpstr); X str_free(tmpstr); X tab(str,level); X break; X case OCOMMA: X prec = P_COMMA; X str = walk(1,level,ops[node+1].ival,&numarg,prec); X str_cat(str,", "); X str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); X str_free(fstr); X break; X case OSEMICOLON: X str = str_new(1); X str_set(str,";\n"); X tab(str,level); X break; X case OSTATES: X str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X break; X case OSTATE: X str = str_new(0); X if (len >= 1) { X str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X if (len >= 2) { X tmpstr = walk(0,level,ops[node+2].ival,&numarg,P_MIN); X if (*tmpstr->str_ptr == ';') { X addsemi(str); X str_cat(str,tmpstr->str_ptr+1); X } X str_free(tmpstr); X } X } X break; X case OCLOSE: X str = str_make("close("); X tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN); X if (!do_fancy_opens) { X t = tmpstr->str_ptr; X if (*t == '"' || *t == '\'') X t = cpytill(tokenbuf,t+1,*t); X else X fatal("Internal error: OCLOSE %s",t); X s = savestr(tokenbuf); X for (t = tokenbuf; *t; t++) { X *t &= 127; X if (!isalpha(*t) && !isdigit(*t)) X *t = '_'; X } X if (!index(tokenbuf,'_')) X strcpy(t,"_fh"); X str_free(tmpstr); X safefree(s); X str_set(str,"close "); X str_cat(str,tokenbuf); X } X else { X sprintf(tokenbuf,"$fh = delete $opened{%s} && close($fh)", X tmpstr->str_ptr); X str_free(tmpstr); X str_set(str,tokenbuf); X } X break; X case OPRINTF: X case OPRINT: X lparen = ""; /* set to parens if necessary */ X rparen = ""; X str = str_new(0); X if (len == 3) { /* output redirection */ X tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MIN); X tmp2str = walk(1,level,ops[node+2].ival,&numarg,P_MIN); X if (!do_fancy_opens) { X t = tmpstr->str_ptr; X if (*t == '"' || *t == '\'') X t = cpytill(tokenbuf,t+1,*t); X else X fatal("Internal error: OPRINT"); X d = savestr(t); X s = savestr(tokenbuf); X for (t = tokenbuf; *t; t++) { X *t &= 127; X if (!isalpha(*t) && !isdigit(*t)) X *t = '_'; X } X if (!index(tokenbuf,'_')) X strcpy(t,"_fh"); X tmp3str = hfetch(symtab,tokenbuf); X if (!tmp3str) { X str_cat(opens,"open("); X str_cat(opens,tokenbuf); X str_cat(opens,", "); X d[1] = '\0'; X str_cat(opens,d); X str_scat(opens,tmp2str); X str_cat(opens,tmpstr->str_ptr+1); X if (*tmp2str->str_ptr == '|') X str_cat(opens,") || die 'Cannot pipe to \""); X else X str_cat(opens,") || die 'Cannot create file \""); X if (*d == '"') X str_cat(opens,"'.\""); X str_cat(opens,s); X if (*d == '"') X str_cat(opens,"\".'"); X str_cat(opens,"\".';\n"); X hstore(symtab,tokenbuf,str_make("x")); X } X str_free(tmpstr); X str_free(tmp2str); X safefree(s); X safefree(d); X } X else { X sprintf(tokenbuf,"&Pick('%s', %s) &&\n", X tmp2str->str_ptr, tmpstr->str_ptr); X str_cat(str,tokenbuf); X tab(str,level+1); X strcpy(tokenbuf,"$fh"); X str_free(tmpstr); X str_free(tmp2str); X lparen = "("; X rparen = ")"; X } X } X else X strcpy(tokenbuf,""); X str_cat(str,lparen); /* may be null */ X if (type == OPRINTF) X str_cat(str,"printf"); X else X str_cat(str,"print"); X if (len == 3 || do_fancy_opens) { X if (*tokenbuf) X str_cat(str," "); X str_cat(str,tokenbuf); X } X tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg,P_MIN); X if (!*tmpstr->str_ptr && lval_field) { X t = saw_OFS ? "$," : "' '"; X if (split_to_array) { X sprintf(tokenbuf,"join(%s,@Fld)",t); X str_cat(tmpstr,tokenbuf); X } X else { X for (i = 1; i < maxfld; i++) { X if (i <= arymax) X sprintf(tokenbuf,"$%s, ",nameary[i]); X else X sprintf(tokenbuf,"$Fld%d, ",i); X str_cat(tmpstr,tokenbuf); X } X if (maxfld <= arymax) X sprintf(tokenbuf,"$%s",nameary[maxfld]); X else X sprintf(tokenbuf,"$Fld%d",maxfld); X str_cat(tmpstr,tokenbuf); X } X } X if (*tmpstr->str_ptr) { X str_cat(str," "); X str_scat(str,tmpstr); X } X else { X str_cat(str," $_"); X } X str_cat(str,rparen); /* may be null */ X str_free(tmpstr); X break; X case ORAND: X str = str_make("rand(1)"); X break; X case OSRAND: X str = str_make("srand("); X goto maybe0; X case OATAN2: X str = str_make("atan2("); X goto maybe0; X case OSIN: X str = str_make("sin("); X goto maybe0; X case OCOS: X str = str_make("cos("); X goto maybe0; X case OSYSTEM: X str = str_make("system("); X goto maybe0; X case OLENGTH: X str = str_make("length("); X goto maybe0; X case OLOG: X str = str_make("log("); X goto maybe0; X case OEXP: X str = str_make("exp("); X goto maybe0; X case OSQRT: X str = str_make("sqrt("); X goto maybe0; X case OINT: X str = str_make("int("); X maybe0: X numeric = 1; X if (len > 0) X tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN); X else X tmpstr = str_new(0);; X if (!*tmpstr->str_ptr) { X if (lval_field) { X t = saw_OFS ? "$," : "' '"; X if (split_to_array) { X sprintf(tokenbuf,"join(%s,@Fld)",t); X str_cat(tmpstr,tokenbuf); X } X else { X sprintf(tokenbuf,"join(%s, ",t); X str_cat(tmpstr,tokenbuf); X for (i = 1; i < maxfld; i++) { X if (i <= arymax) X sprintf(tokenbuf,"$%s,",nameary[i]); X else X sprintf(tokenbuf,"$Fld%d,",i); X str_cat(tmpstr,tokenbuf); X } X if (maxfld <= arymax) X sprintf(tokenbuf,"$%s)",nameary[maxfld]); X else X sprintf(tokenbuf,"$Fld%d)",maxfld); X str_cat(tmpstr,tokenbuf); X } X } X else X str_cat(tmpstr,"$_"); X } X if (strEQ(tmpstr->str_ptr,"$_")) { X if (type == OLENGTH && !do_chop) { X str = str_make("(length("); X str_cat(tmpstr,") - 1"); X } X } X str_scat(str,tmpstr); X str_free(tmpstr); X str_cat(str,")"); X break; X case OBREAK: X str = str_new(0); X str_set(str,"last"); X break; X case ONEXT: X str = str_new(0); X str_set(str,"next line"); X break; X case OEXIT: X str = str_new(0); X if (realexit) { X prec = P_UNI; X str_set(str,"exit"); X if (len == 1) { X str_cat(str," "); X exitval = TRUE; X str_scat(str, X fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1)); X str_free(fstr); X } X } X else { X if (len == 1) { X str_set(str,"ExitValue = "); X exitval = TRUE; X str_scat(str, X fstr=walk(1,level,ops[node+1].ival,&numarg,P_ASSIGN)); X str_free(fstr); X str_cat(str,"; "); X } X str_cat(str,"last line"); X } X break; X case OCONTINUE: X str = str_new(0); X str_set(str,"next"); X break; X case OREDIR: X goto def; X case OIF: X str = str_new(0); X str_set(str,"if ("); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,") "); X str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X if (len == 3) { X i = ops[node+3].ival; X if (i) { X if ((ops[i].ival & 255) == OBLOCK) { X i = ops[i+1].ival; X if (i) { X if ((ops[i].ival & 255) != OIF) X i = 0; X } X } X else X i = 0; X } X if (i) { X str_cat(str,"els"); X str_scat(str,fstr=walk(0,level,i,&numarg,P_MIN)); X str_free(fstr); X } X else { X str_cat(str,"else "); X str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN)); X str_free(fstr); X } X } X break; X case OWHILE: X str = str_new(0); X str_set(str,"while ("); X str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,") "); X str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X break; X case OFOR: X str = str_new(0); X str_set(str,"for ("); X str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X i = numarg; X if (i) { X t = s = tmpstr->str_ptr; X while (isalpha(*t) || isdigit(*t) || *t == '$' || *t == '_') X t++; X i = t - s; X if (i < 2) X i = 0; X } X str_cat(str,"; "); X fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN); X if (i && (t = index(fstr->str_ptr,0377))) { X if (strnEQ(fstr->str_ptr,s,i)) X *t = ' '; X } X str_scat(str,fstr); X str_free(fstr); X str_free(tmpstr); X str_cat(str,"; "); X str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN)); X str_free(fstr); X str_cat(str,") "); X str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN)); X str_free(fstr); X break; X case OFORIN: X tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X d = index(tmpstr->str_ptr,'$'); X if (!d) X fatal("Illegal for loop: %s",tmpstr->str_ptr); X s = index(d,'{'); X if (!s) X s = index(d,'['); X if (!s) X fatal("Illegal for loop: %s",d); X *s++ = '\0'; X t = index(s,'}' + 128); X if (!t) X t = index(s,']' + 128); X if (t) X *t = '\0'; X str = str_new(0); X str_set(str,d+1); X str_cat(str,"[]"); X tmp2str = hfetch(symtab,str->str_ptr); X if (tmp2str && atoi(tmp2str->str_ptr)) { X sprintf(tokenbuf, X "foreach %s (@%s) ", X s, X d+1); X } X else { X sprintf(tokenbuf, X "foreach %s (keys %%%s) ", X s, X d+1); X } X str_set(str,tokenbuf); X str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X str_free(tmpstr); X break; X case OBLOCK: X str = str_new(0); X str_set(str,"{"); X if (len >= 2 && ops[node+2].ival) { X str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); X str_free(fstr); X } X fixtab(str,++level); X str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN)); X str_free(fstr); X addsemi(str); X fixtab(str,--level); X str_cat(str,"}\n"); X tab(str,level); X if (len >= 3) { X str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN)); X str_free(fstr); X } X break; X default: X def: X if (len) { X if (len > 5) X fatal("Garbage length in walk"); X str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X for (i = 2; i<= len; i++) { X str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg,P_MIN)); X str_free(fstr); X } X } X else { X str = Nullstr; X } X break; X } X if (!str) X str = str_new(0); X X if (useval && prec < minprec) { /* need parens? */ X fstr = str_new(str->str_cur+2); X str_nset(fstr,"(",1); X str_scat(fstr,str); X str_ncat(fstr,")",1); X str_free(str); X str = fstr; X } X X *numericptr = numeric; X#ifdef DEBUGGING X if (debug & 4) { X printf("%3d %5d %15s %d %4d ",level,node,opname[type],len,str->str_cur); X for (t = str->str_ptr; *t && t - str->str_ptr < 40; t++) X if (*t == '\n') X printf("\\n"); X else if (*t == '\t') X printf("\\t"); X else X putchar(*t); X putchar('\n'); X } X#endif X return str; X} X Xtab(str,lvl) Xregister STR *str; Xregister int lvl; X{ X while (lvl > 1) { X str_cat(str,"\t"); X lvl -= 2; X } X if (lvl) X str_cat(str," "); X} X Xfixtab(str,lvl) Xregister STR *str; Xregister int lvl; X{ X register char *s; X X /* strip trailing white space */ X X s = str->str_ptr+str->str_cur - 1; X while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n')) X s--; X s[1] = '\0'; X str->str_cur = s + 1 - str->str_ptr; X if (s >= str->str_ptr && *s != '\n') X str_cat(str,"\n"); X X tab(str,lvl); X} X Xaddsemi(str) Xregister STR *str; X{ X register char *s; X X s = str->str_ptr+str->str_cur - 1; X while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n')) X s--; X if (s >= str->str_ptr && *s != ';' && *s != '}') X str_cat(str,";"); X} X Xemit_split(str,level) Xregister STR *str; Xint level; X{ X register int i; X X if (split_to_array) X str_cat(str,"@Fld"); X else { X str_cat(str,"("); X for (i = 1; i < maxfld; i++) { X if (i <= arymax) X sprintf(tokenbuf,"$%s,",nameary[i]); X else X sprintf(tokenbuf,"$Fld%d,",i); X str_cat(str,tokenbuf); X } X if (maxfld <= arymax) X sprintf(tokenbuf,"$%s)",nameary[maxfld]); X else X sprintf(tokenbuf,"$Fld%d)",maxfld); X str_cat(str,tokenbuf); X } X if (const_FS) { X sprintf(tokenbuf," = split(/[%c\\n]/, $_, 999);\n",const_FS); X str_cat(str,tokenbuf); X } X else if (saw_FS) X str_cat(str," = split($FS, $_, 999);\n"); X else X str_cat(str," = split(' ', $_, 999);\n"); X tab(str,level); X} X Xprewalk(numit,level,node,numericptr) Xint numit; Xint level; Xregister int node; Xint *numericptr; X{ X register int len; X register int type; X register int i; X char *t; X char *d, *s; X int numarg; X int numeric = FALSE; X STR *tmpstr; X STR *tmp2str; X X if (!node) { X *numericptr = 0; X return 0; X } X type = ops[node].ival; X len = type >> 8; X type &= 255; X switch (type) { X case OPROG: X prewalk(0,level,ops[node+1].ival,&numarg); X if (ops[node+2].ival) { X prewalk(0,level,ops[node+2].ival,&numarg); X } X ++level; X prewalk(0,level,ops[node+3].ival,&numarg); X --level; X if (ops[node+3].ival) { X prewalk(0,level,ops[node+4].ival,&numarg); X } X break; X case OHUNKS: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X if (len == 3) { X prewalk(0,level,ops[node+3].ival,&numarg); X } X break; X case ORANGE: X prewalk(1,level,ops[node+1].ival,&numarg); X prewalk(1,level,ops[node+2].ival,&numarg); X break; X case OPAT: X goto def; X case OREGEX: X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case OHUNK: X if (len == 1) { X prewalk(0,level,ops[node+1].ival,&numarg); X } X else { X i = prewalk(0,level,ops[node+1].ival,&numarg); X if (i) { X ++level; X prewalk(0,level,ops[node+2].ival,&numarg); X --level; X } X else { X prewalk(0,level,ops[node+2].ival,&numarg); X } X } X break; X case OPPAREN: X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case OPANDAND: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X break; X case OPOROR: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X break; X case OPNOT: X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case OCPAREN: X prewalk(0,level,ops[node+1].ival,&numarg); X numeric |= numarg; X break; X case OCANDAND: X prewalk(0,level,ops[node+1].ival,&numarg); X numeric = 1; X prewalk(0,level,ops[node+2].ival,&numarg); X break; X case OCOROR: X prewalk(0,level,ops[node+1].ival,&numarg); X numeric = 1; X prewalk(0,level,ops[node+2].ival,&numarg); X break; X case OCNOT: X prewalk(0,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case ORELOP: X prewalk(0,level,ops[node+2].ival,&numarg); X numeric |= numarg; X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+3].ival,&numarg); X numeric |= numarg; X numeric = 1; X break; X case ORPAREN: X prewalk(0,level,ops[node+1].ival,&numarg); X numeric |= numarg; X break; X case OMATCHOP: X prewalk(0,level,ops[node+2].ival,&numarg); X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+3].ival,&numarg); X numeric = 1; X break; X case OMPAREN: X prewalk(0,level,ops[node+1].ival,&numarg); X numeric |= numarg; X break; X case OCONCAT: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X break; X case OASSIGN: X prewalk(0,level,ops[node+2].ival,&numarg); X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+3].ival,&numarg); X if (numarg || strlen(ops[ops[node+1].ival+1].cval) > 1) { X numericize(ops[node+2].ival); X if (!numarg) X numericize(ops[node+3].ival); X } X numeric |= numarg; X break; X case OADD: X prewalk(1,level,ops[node+1].ival,&numarg); X prewalk(1,level,ops[node+2].ival,&numarg); X numeric = 1; X break; X case OSUBTRACT: X prewalk(1,level,ops[node+1].ival,&numarg); X prewalk(1,level,ops[node+2].ival,&numarg); X numeric = 1; X break; X case OMULT: X prewalk(1,level,ops[node+1].ival,&numarg); X prewalk(1,level,ops[node+2].ival,&numarg); X numeric = 1; X break; X case ODIV: X prewalk(1,level,ops[node+1].ival,&numarg); X prewalk(1,level,ops[node+2].ival,&numarg); X numeric = 1; X break; X case OPOW: X prewalk(1,level,ops[node+1].ival,&numarg); X prewalk(1,level,ops[node+2].ival,&numarg); X numeric = 1; X break; X case OMOD: X prewalk(1,level,ops[node+1].ival,&numarg); X prewalk(1,level,ops[node+2].ival,&numarg); X numeric = 1; X break; X case OPOSTINCR: X prewalk(1,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case OPOSTDECR: X prewalk(1,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case OPREINCR: X prewalk(1,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case OPREDECR: X prewalk(1,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case OUMINUS: X prewalk(1,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case OUPLUS: X prewalk(1,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case OPAREN: X prewalk(0,level,ops[node+1].ival,&numarg); X numeric |= numarg; X break; X case OGETLINE: X break; X case OSPRINTF: X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case OSUBSTR: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(1,level,ops[node+2].ival,&numarg); X if (len == 3) { X prewalk(1,level,ops[node+3].ival,&numarg); X } X break; X case OSTRING: X break; X case OSPLIT: X numeric = 1; X prewalk(0,level,ops[node+2].ival,&numarg); X if (len == 3) X prewalk(0,level,ops[node+3].ival,&numarg); X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case OINDEX: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X numeric = 1; X break; X case OMATCH: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X numeric = 1; X break; X case OUSERDEF: X subretnum = FALSE; X --level; X tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); X ++level; X prewalk(0,level,ops[node+2].ival,&numarg); X prewalk(0,level,ops[node+4].ival,&numarg); X prewalk(0,level,ops[node+5].ival,&numarg); X --level; X str_cat(tmpstr,"("); X tmp2str = str_new(0); X if (subretnum || numarg) X str_set(tmp2str,"1"); X hstore(symtab,tmpstr->str_ptr,tmp2str); X str_free(tmpstr); X level++; X break; X case ORETURN: X if (len > 0) { X prewalk(0,level,ops[node+1].ival,&numarg); X if (numarg) X subretnum = TRUE; X } X break; X case OUSERFUN: X tmp2str = str_new(0); X str_scat(tmp2str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN)); X fixrargs(tmpstr->str_ptr,ops[node+2],0); X str_free(tmpstr); X str_cat(tmp2str,"("); X tmpstr = hfetch(symtab,tmp2str->str_ptr); X if (tmpstr && tmpstr->str_ptr) X numeric |= atoi(tmpstr->str_ptr); X prewalk(0,level,ops[node+2].ival,&numarg); X str_free(tmp2str); X break; X case OGSUB: X case OSUB: X if (len >= 3) X prewalk(0,level,ops[node+3].ival,&numarg); X prewalk(0,level,ops[ops[node+2].ival+1].ival,&numarg); X prewalk(0,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case ONUM: X prewalk(0,level,ops[node+1].ival,&numarg); X numeric = 1; X break; X case OSTR: X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case ODEFINED: X case ODELETE: X case OSTAR: X case OVAR: X prewalk(0,level,ops[node+1].ival,&numarg); X if (len == 1) { X if (numit) X numericize(node); X } X else { X prewalk(0,level,ops[node+2].ival,&numarg); X } X break; X case OFLD: X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case OVFLD: X i = ops[node+1].ival; X prewalk(0,level,i,&numarg); X break; X case OJUNK: X goto def; X case OSNEWLINE: X break; X case ONEWLINE: X break; X case OSCOMMENT: X break; X case OCOMMENT: X break; X case OCOMMA: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X prewalk(0,level,ops[node+3].ival,&numarg); X break; X case OSEMICOLON: X break; X case OSTATES: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X break; X case OSTATE: X if (len >= 1) { X prewalk(0,level,ops[node+1].ival,&numarg); X if (len >= 2) { X prewalk(0,level,ops[node+2].ival,&numarg); X } X } X break; X case OCLOSE: X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case OPRINTF: X case OPRINT: X if (len == 3) { /* output redirection */ X prewalk(0,level,ops[node+3].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X } X prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg); X break; X case ORAND: X break; X case OSRAND: X goto maybe0; X case OATAN2: X goto maybe0; X case OSIN: X goto maybe0; X case OCOS: X goto maybe0; X case OSYSTEM: X goto maybe0; X case OLENGTH: X goto maybe0; X case OLOG: X goto maybe0; X case OEXP: X goto maybe0; X case OSQRT: X goto maybe0; X case OINT: X maybe0: X numeric = 1; X if (len > 0) X prewalk(type != OLENGTH && type != OSYSTEM, X level,ops[node+1].ival,&numarg); X break; X case OBREAK: X break; X case ONEXT: X break; X case OEXIT: X if (len == 1) { X prewalk(1,level,ops[node+1].ival,&numarg); X } X break; X case OCONTINUE: X break; X case OREDIR: X goto def; X case OIF: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X if (len == 3) { X prewalk(0,level,ops[node+3].ival,&numarg); X } X break; X case OWHILE: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X break; X case OFOR: X prewalk(0,level,ops[node+1].ival,&numarg); X prewalk(0,level,ops[node+2].ival,&numarg); X prewalk(0,level,ops[node+3].ival,&numarg); X prewalk(0,level,ops[node+4].ival,&numarg); X break; X case OFORIN: X prewalk(0,level,ops[node+2].ival,&numarg); X prewalk(0,level,ops[node+1].ival,&numarg); X break; X case OBLOCK: X if (len == 2) { X prewalk(0,level,ops[node+2].ival,&numarg); X } X ++level; X prewalk(0,level,ops[node+1].ival,&numarg); X --level; X break; X default: X def: X if (len) { X if (len > 5) X fatal("Garbage length in prewalk"); X prewalk(0,level,ops[node+1].ival,&numarg); X for (i = 2; i<= len; i++) { X prewalk(0,level,ops[node+i].ival,&numarg); X } X } X break; X } X *numericptr = numeric; X return 1; X} X Xnumericize(node) Xregister int node; X{ X register int len; X register int type; X register int i; X STR *tmpstr; X STR *tmp2str; X int numarg; X X type = ops[node].ival; X len = type >> 8; X type &= 255; X if (type == OVAR && len == 1) { X tmpstr=walk(0,0,ops[node+1].ival,&numarg,P_MIN); X tmp2str = str_make("1"); X hstore(symtab,tmpstr->str_ptr,tmp2str); X } X} !STUFFY!FUNK! echo "" echo "End of kit 2 (of 23)" cat /dev/null >kit2isdone run='' config='' for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23; do if test -f kit${iskit}isdone; then run="$run $iskit" else todo="$todo $iskit" fi done case $todo in '') echo "You have run all your kits. Please read README and then type Configure." chmod 755 Configure ;; *) echo "You have run$run." echo "You still need to run$todo." ;; esac : Someone might mail this, so... exit