📄 walk.c
字号:
/* $RCSfile: walk.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 17:33:46 $ * * Copyright (c) 1991, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * * $Log: walk.c,v $ * Revision 4.0.1.3 92/06/08 17:33:46 lwall * patch20: in a2p, simplified the filehandle model * patch20: in a2p, made RS="" translate to $/ = "\n\n" * patch20: in a2p, do {...} while ... was missing some reconstruction code * patch20: in a2p, getline should allow variable to be array element * * Revision 4.0.1.2 91/11/05 19:25:09 lwall * patch11: in a2p, split on whitespace produced extra null field * * Revision 4.0.1.1 91/06/07 12:22:04 lwall * patch4: new copyright notice * patch4: a2p didn't correctly implement -n switch * * Revision 4.0 91/03/20 01:58:36 lwall * 4.0 baseline. * */#include "handy.h"#include "EXTERN.h"#include "util.h"#include "a2p.h"bool exitval = FALSE;bool realexit = FALSE;bool saw_getline = FALSE;bool subretnum = FALSE;bool saw_FNR = FALSE;bool saw_argv0 = FALSE;bool saw_fh = FALSE;int maxtmp = 0;char *lparen;char *rparen;char *limit;STR *subs;STR *curargs = Nullstr;STR *walk(useval,level,node,numericptr,minprec)int useval;int level;register int node;int *numericptr;int minprec; /* minimum precedence without parens */{ register int len; register STR *str; register int type; register int i; register STR *tmpstr; STR *tmp2str; STR *tmp3str; char *t; char *d, *s; int numarg; int numeric = FALSE; STR *fstr; int prec = P_MAX; /* assume no parens needed */ char *index(); if (!node) { *numericptr = 0; return str_make(""); } type = ops[node].ival; len = type >> 8; type &= 255; switch (type) { case OPROG: arymax = 0; if (namelist) { while (isalpha(*namelist)) { for (d = tokenbuf,s=namelist; isalpha(*s) || isdigit(*s) || *s == '_'; *d++ = *s++) ; *d = '\0'; while (*s && !isalpha(*s)) s++; namelist = s; nameary[++arymax] = savestr(tokenbuf); } } if (maxfld < arymax) maxfld = arymax; opens = str_new(0); subs = str_new(0); str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); if (do_split && need_entire && !absmaxfld) split_to_array = TRUE; if (do_split && split_to_array) set_array_base = TRUE; if (set_array_base) { str_cat(str,"$[ = 1;\t\t\t# set array base to 1\n"); } if (fswitch && !const_FS) const_FS = fswitch; if (saw_FS > 1 || saw_RS) const_FS = 0; if (saw_ORS && need_entire) do_chop = TRUE; if (fswitch) { str_cat(str,"$FS = '"); if (index("*+?.[]()|^$\\",fswitch)) str_cat(str,"\\"); sprintf(tokenbuf,"%c",fswitch); str_cat(str,tokenbuf); str_cat(str,"';\t\t# field separator from -F switch\n"); } else if (saw_FS && !const_FS) { str_cat(str,"$FS = ' ';\t\t# set field separator\n"); } if (saw_OFS) { str_cat(str,"$, = ' ';\t\t# set output field separator\n"); } if (saw_ORS) { str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n"); } if (saw_argv0) { str_cat(str,"$ARGV0 = $0;\t\t# remember what we ran as\n"); } if (str->str_cur > 20) str_cat(str,"\n"); if (ops[node+2].ival) { str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,"\n\n"); } fstr = walk(0,level+1,ops[node+3].ival,&numarg,P_MIN); if (*fstr->str_ptr) { if (saw_line_op) str_cat(str,"line: "); str_cat(str,"while (<>) {\n"); tab(str,++level); if (saw_FS && !const_FS) do_chop = TRUE; if (do_chop) { str_cat(str,"chop;\t# strip record separator\n"); tab(str,level); } if (do_split) emit_split(str,level); str_scat(str,fstr); str_free(fstr); fixtab(str,--level); str_cat(str,"}\n"); if (saw_FNR) str_cat(str,"continue {\n $FNRbase = $. if eof;\n}\n"); } else str_cat(str,"while (<>) { } # (no line actions)\n"); if (ops[node+4].ival) { realexit = TRUE; str_cat(str,"\n"); tab(str,level); str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,"\n"); } if (exitval) str_cat(str,"exit $ExitValue;\n"); if (subs->str_ptr) { str_cat(str,"\n"); str_scat(str,subs); } if (saw_getline) { for (len = 0; len < 4; len++) { if (saw_getline & (1 << len)) { sprintf(tokenbuf,"\nsub Getline%d {\n",len); str_cat(str, tokenbuf); if (len & 2) { if (do_fancy_opens) str_cat(str," &Pick('',@_);\n"); else str_cat(str," ($fh) = @_;\n"); } else { if (saw_FNR) str_cat(str," $FNRbase = $. if eof;\n"); } if (len & 1) str_cat(str," local($_);\n"); if (len & 2) str_cat(str, " if ($getline_ok = (($_ = <$fh>) ne ''))"); else str_cat(str, " if ($getline_ok = (($_ = <>) ne ''))"); str_cat(str, " {\n"); level += 2; tab(str,level); i = 0; if (do_chop) { i++; str_cat(str,"chop;\t# strip record separator\n"); tab(str,level); } if (do_split && !(len & 1)) { i++; emit_split(str,level); } if (!i) str_cat(str,";\n"); fixtab(str,--level); str_cat(str,"}\n $_;\n}\n"); --level; } } } if (do_fancy_opens) { str_cat(str,"\n\sub Pick {\n\ local($mode,$name,$pipe) = @_;\n\ $fh = $name;\n\ open($name,$mode.$name.$pipe) unless $opened{$name}++;\n\}\n\"); } break; case OHUNKS: str = walk(0,level,ops[node+1].ival,&numarg,P_MIN); str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); if (len == 3) { str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN)); str_free(fstr); } else { } break; case ORANGE: prec = P_DOTDOT; str = walk(1,level,ops[node+1].ival,&numarg,prec+1); str_cat(str," .. "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); break; case OPAT: goto def; case OREGEX: str = str_new(0); str_set(str,"/"); tmpstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN); /* translate \nnn to [\nnn] */ for (s = tmpstr->str_ptr, d = tokenbuf; *s; s++, d++) { if (*s == '\\' && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])){ *d++ = '['; *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s; *d = ']'; } else *d = *s; } *d = '\0'; for (d=tokenbuf; *d; d++) *d += 128; str_cat(str,tokenbuf); str_free(tmpstr); str_cat(str,"/"); break; case OHUNK: if (len == 1) { str = str_new(0); str = walk(0,level,oper1(OPRINT,0),&numarg,P_MIN); str_cat(str," if "); str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,";"); } else { tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); if (*tmpstr->str_ptr) { str = str_new(0); str_set(str,"if ("); str_scat(str,tmpstr); str_cat(str,") {\n"); tab(str,++level); str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN)); str_free(fstr); fixtab(str,--level); str_cat(str,"}\n"); tab(str,level); } else { str = walk(0,level,ops[node+2].ival,&numarg,P_MIN); } } break; case OPPAREN: str = str_new(0); str_set(str,"("); str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); str_cat(str,")"); break; case OPANDAND: prec = P_ANDAND; str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," && "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OPOROR: prec = P_OROR; str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," || "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OPNOT: prec = P_UNARY; str = str_new(0); str_set(str,"!"); str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec)); str_free(fstr); break; case OCOND: prec = P_COND; str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," ? "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); str_cat(str," : "); str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OCPAREN: str = str_new(0); str_set(str,"("); str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); numeric |= numarg; str_cat(str,")"); break; case OCANDAND: prec = P_ANDAND; str = walk(1,level,ops[node+1].ival,&numarg,prec); numeric = 1; str_cat(str," && "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OCOROR: prec = P_OROR; str = walk(1,level,ops[node+1].ival,&numarg,prec); numeric = 1; str_cat(str," || "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); break; case OCNOT: prec = P_UNARY; str = str_new(0); str_set(str,"!"); str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec)); str_free(fstr); numeric = 1; break; case ORELOP: prec = P_REL; str = walk(1,level,ops[node+2].ival,&numarg,prec+1); numeric |= numarg; tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); tmp2str = walk(1,level,ops[node+3].ival,&numarg,prec+1); numeric |= numarg; if (!numeric || (!numarg && (*tmp2str->str_ptr == '"' || *tmp2str->str_ptr == '\''))) { t = tmpstr->str_ptr; if (strEQ(t,"==")) str_set(tmpstr,"eq"); else if (strEQ(t,"!=")) str_set(tmpstr,"ne"); else if (strEQ(t,"<")) str_set(tmpstr,"lt"); else if (strEQ(t,"<=")) str_set(tmpstr,"le"); else if (strEQ(t,">")) str_set(tmpstr,"gt"); else if (strEQ(t,">=")) str_set(tmpstr,"ge"); if (!index(tmpstr->str_ptr,'\'') && !index(tmpstr->str_ptr,'"') && !index(tmp2str->str_ptr,'\'') && !index(tmp2str->str_ptr,'"') ) numeric |= 2; } if (numeric & 2) { if (numeric & 1) /* numeric is very good guess */ str_cat(str," "); else str_cat(str,"\377"); numeric = 1; } else str_cat(str," "); str_scat(str,tmpstr); str_free(tmpstr); str_cat(str," "); str_scat(str,tmp2str); str_free(tmp2str); numeric = 1; break; case ORPAREN: str = str_new(0); str_set(str,"("); str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); numeric |= numarg; str_cat(str,")"); break; case OMATCHOP: prec = P_MATCH; str = walk(1,level,ops[node+2].ival,&numarg,prec+1); str_cat(str," "); tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); if (strEQ(tmpstr->str_ptr,"~")) str_cat(str,"=~"); else { str_scat(str,tmpstr); str_free(tmpstr); } str_cat(str," "); str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OMPAREN: str = str_new(0); str_set(str,"("); str_scat(str, fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN)); str_free(fstr); numeric |= numarg; str_cat(str,")"); break; case OCONCAT: prec = P_ADD; type = ops[ops[node+1].ival].ival & 255; str = walk(1,level,ops[node+1].ival,&numarg,prec+(type != OCONCAT)); str_cat(str," . "); type = ops[ops[node+2].ival].ival & 255; str_scat(str, fstr=walk(1,level,ops[node+2].ival,&numarg,prec+(type != OCONCAT))); str_free(fstr); break; case OASSIGN: prec = P_ASSIGN; str = walk(0,level,ops[node+2].ival,&numarg,prec+1); str_cat(str," "); tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN); str_scat(str,tmpstr); if (str_len(tmpstr) > 1) numeric = 1; str_free(tmpstr); str_cat(str," "); str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec)); str_free(fstr); numeric |= numarg; if (strEQ(str->str_ptr,"$/ = ''")) str_set(str, "$/ = \"\\n\\n\""); break; case OADD: prec = P_ADD; str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," + "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OSUBTRACT: prec = P_ADD; str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," - "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OMULT: prec = P_MUL; str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," * "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case ODIV: prec = P_MUL; str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," / "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1)); str_free(fstr); numeric = 1; break; case OPOW: prec = P_POW; str = walk(1,level,ops[node+1].ival,&numarg,prec+1); str_cat(str," ** "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec)); str_free(fstr); numeric = 1; break; case OMOD: prec = P_MUL; str = walk(1,level,ops[node+1].ival,&numarg,prec); str_cat(str," % "); str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -