perl 3.0 beta kit [2/23]
Larry Wall
lwall at jato.Jpl.Nasa.Gov
Sun Sep 3 11:55:04 AEST 1989
#! /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('', at _);\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, at 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, at 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
More information about the Alt.sources
mailing list