X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=x2p%2Fa2py.c;h=df0a55cb21405b0f672a1328857dca59018f13ee;hb=34ba6322b644154d55680c95808981776852ae24;hp=3adbd65fd33e997182382461f8cef7ffabc4247b;hpb=378cc40b38293ffc7298c6a7ed3cd740ad79be52;p=p5sagit%2Fp5-mst-13.2.git diff --git a/x2p/a2py.c b/x2p/a2py.c index 3adbd65..df0a55c 100644 --- a/x2p/a2py.c +++ b/x2p/a2py.c @@ -1,40 +1,86 @@ -/* $Header: a2py.c,v 2.0 88/06/05 00:15:41 root Exp $ +/* a2py.c * - * $Log: a2py.c,v $ - * Revision 2.0 88/06/05 00:15:41 root - * Baseline version 2.0. - * + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + * 2000, 2001, 2002, by Larry Wall and others + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. */ +#if defined(OS2) || defined(WIN32) || defined(NETWARE) +#if defined(WIN32) +#include +#endif +#if defined(NETWARE) +#include "../netware/clibstuf.h" +#endif +#include "../patchlevel.h" +#endif #include "util.h" -char *index(); char *filename; +char *myname; int checkers = 0; -main(argc,argv,env) -register int argc; -register char **argv; -register char **env; +int oper0(int type); +int oper1(int type, int arg1); +int oper2(int type, int arg1, int arg2); +int oper3(int type, int arg1, int arg2, int arg3); +int oper4(int type, int arg1, int arg2, int arg3, int arg4); +int oper5(int type, int arg1, int arg2, int arg3, int arg4, int arg5); +STR *walk(int useval, int level, register int node, int *numericptr, int minprec); +#ifdef NETWARE +char *savestr(char *str); +char *cpy2(register char *to, register char *from, register int delim); +#endif + +#if defined(OS2) || defined(WIN32) || defined(NETWARE) +static void usage(void); + +static void +usage() +{ + printf("\nThis is the AWK to PERL translator, revision %d.0, version %d\n", PERL_REVISION, PERL_VERSION); + printf("\nUsage: %s [-D] [-F] [-n] [-] filename\n", myname); + printf("\n -D sets debugging flags." + "\n -F the awk script to translate is always invoked with" + "\n this -F switch." + "\n -n specifies the names of the input fields if input does" + "\n not have to be split into an array." + "\n - causes a2p to assume that input will always have that" + "\n many fields.\n"); + exit(1); +} +#endif + +#ifdef __osf__ +#pragma message disable (mainparm) /* We have the envp in main(). */ +#endif + +int +main(register int argc, register char **argv, register char **env) { register STR *str; - register char *s; int i; - STR *walk(); STR *tmpstr; + /* char *namelist; */ + + #ifdef NETWARE + fnInitGpfGlobals(); /* For importing the CLIB calls in place of Watcom calls */ + #endif /* NETWARE */ + myname = argv[0]; linestr = str_new(80); str = str_new(0); /* first used for -I flags */ for (argc--,argv++; argc; argc--,argv++) { if (argv[0][0] != '-' || !argv[0][1]) break; - reswitch: switch (argv[0][1]) { #ifdef DEBUGGING case 'D': debug = atoi(argv[0]+2); -#ifdef YYDEBUG +#if YYDEBUG yydebug = (debug & 1); #endif break; @@ -50,21 +96,36 @@ register char **env; case 'n': namelist = savestr(argv[0]+2); break; + case 'o': + old_awk = TRUE; + break; case '-': argc--,argv++; goto switch_end; case 0: break; default: +#if defined(OS2) || defined(WIN32) || defined(NETWARE) + fprintf(stderr, "Unrecognized switch: %s\n",argv[0]); + usage(); +#else fatal("Unrecognized switch: %s\n",argv[0]); +#endif } } switch_end: /* open script */ - if (argv[0] == Nullch) - argv[0] = "-"; + if (argv[0] == Nullch) { +#if defined(OS2) || defined(WIN32) || defined(NETWARE) + if ( isatty(fileno(stdin)) ) + usage(); +#endif + argv[0] = "-"; + } + filename = savestr(argv[0]); + filename = savestr(argv[0]); if (strEQ(filename,"-")) argv[0] = ""; @@ -79,6 +140,7 @@ register char **env; bufptr = str_get(linestr); symtab = hnew(); + curarghash = hnew(); /* now parse the report spec */ @@ -114,13 +176,16 @@ register char **env; /* second pass to produce new program */ - tmpstr = walk(0,0,root,&i); - str = str_make("#!/usr/bin/perl\neval \"exec /usr/bin/perl -S $0 $*\"\n\ + tmpstr = walk(0,0,root,&i,P_MIN); + str = str_make(STARTPERL); + str_cat(str, "\neval 'exec "); + str_cat(str, BIN); + str_cat(str, "/perl -S $0 ${1+\"$@\"}'\n\ if $running_under_some_shell;\n\ # this emulates #! processing on NIH machines.\n\ # (remove #! line above if indigestible)\n\n"); str_cat(str, - "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;\n"); + "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;\n"); str_cat(str, " # process any FOO=bar switches\n\n"); if (do_opens && opens) { @@ -143,26 +208,32 @@ register char **env; "The operation I've selected may be wrong for the operand types.\n"); } exit(0); + /* by ANSI specs return is needed. This also shuts up VC++ and his warnings */ + return(0); } #define RETURN(retval) return (bufptr = s,retval) #define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval) #define XOP(retval) return (expectterm = FALSE,bufptr = s,retval) -#define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,VAR) +#define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,idtype) + +int idtype; -yylex() +int +yylex(void) { register char *s = bufptr; register char *d; register int tmp; retry: -#ifdef YYDEBUG - if (yydebug) - if (index(s,'\n')) +#if YYDEBUG + if (yydebug) { + if (strchr(s,'\n')) fprintf(stderr,"Tokener at %s",s); else fprintf(stderr,"Tokener at %s\n",s); + } #endif switch (*s) { default: @@ -171,6 +242,12 @@ yylex() *s++,filename,line); goto retry; case '\\': + s++; + if (*s && *s != '\n') { + yyerror("Ignoring spurious backslash"); + goto retry; + } + /*FALLSTHROUGH*/ case 0: s = str_get(linestr); *s = '\0'; @@ -203,17 +280,25 @@ yylex() } XTERM(tmp); case '(': + tmp = *s++; + XTERM(tmp); case '{': case '[': case ')': case ']': + case '?': + case ':': tmp = *s++; XOP(tmp); +#ifdef EBCDIC + case 7: +#else case 127: +#endif s++; XTERM('}'); case '}': - for (d = s + 1; isspace(*d); d++) ; + for (d = s + 1; isSPACE(*d); d++) ; if (!*d) s = d - 1; *s = 127; @@ -237,9 +322,13 @@ yylex() /* FALL THROUGH */ case '*': case '%': + case '^': tmp = *s++; if (*s == '=') { - yylval = string(s-1,2); + if (tmp == '^') + yylval = string("**=",3); + else + yylval = string(s-1,2); s++; XTERM(ASGNOP); } @@ -257,7 +346,12 @@ yylex() if (tmp == '|') XTERM(OROR); s--; - XTERM('|'); + while (*s == ' ' || *s == '\t') + s++; + if (strnEQ(s,"getline",7)) + XTERM('p'); + else + XTERM('|'); case '=': s++; tmp = *s++; @@ -289,8 +383,7 @@ yylex() XTERM(RELOP); } s--; - yylval = string("<",1); - XTERM(RELOP); + XTERM('<'); case '>': s++; tmp = *s++; @@ -303,15 +396,18 @@ yylex() XTERM(RELOP); } s--; - yylval = string(">",1); - XTERM(RELOP); + XTERM('>'); #define SNARFWORD \ d = tokenbuf; \ - while (isalpha(*s) || isdigit(*s) || *s == '_') \ + while (isALPHA(*s) || isDIGIT(*s) || *s == '_') \ *d++ = *s++; \ *d = '\0'; \ - d = tokenbuf; + d = tokenbuf; \ + if (*s == '(') \ + idtype = USERFUN; \ + else \ + idtype = VAR; case '$': s++; @@ -319,18 +415,26 @@ yylex() s++; do_chop = TRUE; need_entire = TRUE; + idtype = VAR; ID("0"); } do_split = TRUE; - if (isdigit(*s)) { - for (d = s; isdigit(*s); s++) ; + if (isDIGIT(*s)) { + for (d = s; isDIGIT(*s); s++) ; yylval = string(d,s-d); tmp = atoi(d); if (tmp > maxfld) maxfld = tmp; XOP(FIELD); } + for (d = s; isALPHA(*s) || isDIGIT(*s) || *s == '_'; ) + s++; split_to_array = set_array_base = TRUE; + if (d != s) + { + yylval = string(d,s-d); + XTERM(SVFIELD); + } XOP(VFIELD); case '/': /* may either be division or pattern */ @@ -347,7 +451,7 @@ yylex() XTERM(tmp); case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': + case '5': case '6': case '7': case '8': case '9': case '.': s = scannum(s); XOP(NUMBER); case '"': @@ -361,6 +465,16 @@ yylex() case 'a': case 'A': SNARFWORD; + if (strEQ(d,"ARGC")) + set_array_base = TRUE; + if (strEQ(d,"ARGV")) { + yylval=numary(string("ARGV",0)); + XOP(VAR); + } + if (strEQ(d,"atan2")) { + yylval = OATAN2; + XTERM(FUNN); + } ID(d); case 'b': case 'B': SNARFWORD; @@ -373,9 +487,34 @@ yylex() SNARFWORD; if (strEQ(d,"continue")) XTERM(CONTINUE); + if (strEQ(d,"cos")) { + yylval = OCOS; + XTERM(FUN1); + } + if (strEQ(d,"close")) { + do_fancy_opens = 1; + yylval = OCLOSE; + XTERM(FUN1); + } + if (strEQ(d,"chdir")) + *d = toUPPER(*d); + else if (strEQ(d,"crypt")) + *d = toUPPER(*d); + else if (strEQ(d,"chop")) + *d = toUPPER(*d); + else if (strEQ(d,"chmod")) + *d = toUPPER(*d); + else if (strEQ(d,"chown")) + *d = toUPPER(*d); ID(d); case 'd': case 'D': SNARFWORD; + if (strEQ(d,"do")) + XTERM(DO); + if (strEQ(d,"delete")) + XTERM(DELETE); + if (strEQ(d,"die")) + *d = toUPPER(*d); ID(d); case 'e': case 'E': SNARFWORD; @@ -391,33 +530,67 @@ yylex() yylval = OEXP; XTERM(FUN1); } + if (strEQ(d,"elsif")) + *d = toUPPER(*d); + else if (strEQ(d,"eq")) + *d = toUPPER(*d); + else if (strEQ(d,"eval")) + *d = toUPPER(*d); + else if (strEQ(d,"eof")) + *d = toUPPER(*d); + else if (strEQ(d,"each")) + *d = toUPPER(*d); + else if (strEQ(d,"exec")) + *d = toUPPER(*d); ID(d); case 'f': case 'F': SNARFWORD; if (strEQ(d,"FS")) { saw_FS++; if (saw_FS == 1 && in_begin) { - for (d = s; *d && isspace(*d); d++) ; + for (d = s; *d && isSPACE(*d); d++) ; if (*d == '=') { - for (d++; *d && isspace(*d); d++) ; + for (d++; *d && isSPACE(*d); d++) ; if (*d == '"' && d[2] == '"') const_FS = d[1]; } } ID(tokenbuf); } - if (strEQ(d,"FILENAME")) - d = "ARGV"; if (strEQ(d,"for")) XTERM(FOR); + else if (strEQ(d,"function")) + XTERM(FUNCTION); + if (strEQ(d,"FILENAME")) + d = "ARGV"; + if (strEQ(d,"foreach")) + *d = toUPPER(*d); + else if (strEQ(d,"format")) + *d = toUPPER(*d); + else if (strEQ(d,"fork")) + *d = toUPPER(*d); + else if (strEQ(d,"fh")) + *d = toUPPER(*d); ID(d); case 'g': case 'G': SNARFWORD; if (strEQ(d,"getline")) XTERM(GETLINE); + if (strEQ(d,"gsub")) + XTERM(GSUB); + if (strEQ(d,"ge")) + *d = toUPPER(*d); + else if (strEQ(d,"gt")) + *d = toUPPER(*d); + else if (strEQ(d,"goto")) + *d = toUPPER(*d); + else if (strEQ(d,"gmtime")) + *d = toUPPER(*d); ID(d); case 'h': case 'H': SNARFWORD; + if (strEQ(d,"hex")) + *d = toUPPER(*d); ID(d); case 'i': case 'I': SNARFWORD; @@ -436,9 +609,15 @@ yylex() ID(d); case 'j': case 'J': SNARFWORD; + if (strEQ(d,"join")) + *d = toUPPER(*d); ID(d); case 'k': case 'K': SNARFWORD; + if (strEQ(d,"keys")) + *d = toUPPER(*d); + else if (strEQ(d,"kill")) + *d = toUPPER(*d); ID(d); case 'l': case 'L': SNARFWORD; @@ -450,32 +629,58 @@ yylex() yylval = OLOG; XTERM(FUN1); } + if (strEQ(d,"last")) + *d = toUPPER(*d); + else if (strEQ(d,"local")) + *d = toUPPER(*d); + else if (strEQ(d,"lt")) + *d = toUPPER(*d); + else if (strEQ(d,"le")) + *d = toUPPER(*d); + else if (strEQ(d,"locatime")) + *d = toUPPER(*d); + else if (strEQ(d,"link")) + *d = toUPPER(*d); ID(d); case 'm': case 'M': SNARFWORD; + if (strEQ(d,"match")) { + set_array_base = TRUE; + XTERM(MATCH); + } + if (strEQ(d,"m")) + *d = toUPPER(*d); ID(d); case 'n': case 'N': SNARFWORD; if (strEQ(d,"NF")) - do_split = split_to_array = set_array_base = TRUE; + do_chop = do_split = split_to_array = set_array_base = TRUE; if (strEQ(d,"next")) { saw_line_op = TRUE; XTERM(NEXT); } + if (strEQ(d,"ne")) + *d = toUPPER(*d); ID(d); case 'o': case 'O': SNARFWORD; if (strEQ(d,"ORS")) { saw_ORS = TRUE; - d = "$\\"; + d = "\\"; } if (strEQ(d,"OFS")) { saw_OFS = TRUE; - d = "$,"; + d = ","; } if (strEQ(d,"OFMT")) { - d = "$#"; + d = "#"; } + if (strEQ(d,"open")) + *d = toUPPER(*d); + else if (strEQ(d,"ord")) + *d = toUPPER(*d); + else if (strEQ(d,"oct")) + *d = toUPPER(*d); ID(d); case 'p': case 'P': SNARFWORD; @@ -485,6 +690,10 @@ yylex() if (strEQ(d,"printf")) { XTERM(PRINTF); } + if (strEQ(d,"push")) + *d = toUPPER(*d); + else if (strEQ(d,"pop")) + *d = toUPPER(*d); ID(d); case 'q': case 'Q': SNARFWORD; @@ -492,9 +701,21 @@ yylex() case 'r': case 'R': SNARFWORD; if (strEQ(d,"RS")) { - d = "$/"; + d = "/"; saw_RS = TRUE; } + if (strEQ(d,"rand")) { + yylval = ORAND; + XTERM(FUN1); + } + if (strEQ(d,"return")) + XTERM(RET); + if (strEQ(d,"reset")) + *d = toUPPER(*d); + else if (strEQ(d,"redo")) + *d = toUPPER(*d); + else if (strEQ(d,"rename")) + *d = toUPPER(*d); ID(d); case 's': case 'S': SNARFWORD; @@ -506,32 +727,104 @@ yylex() set_array_base = TRUE; XTERM(SUBSTR); } - if (strEQ(d,"sprintf")) - XTERM(SPRINTF); + if (strEQ(d,"sub")) + XTERM(SUB); + if (strEQ(d,"sprintf")) { + /* In old awk, { print sprintf("str%sg"),"in" } prints + * "string"; in new awk, "in" is not considered an argument to + * sprintf, so the statement breaks. To support both, the + * grammar treats arguments to SPRINTF_OLD like old awk, + * SPRINTF_NEW like new. Here we return the appropriate one. + */ + XTERM(old_awk ? SPRINTF_OLD : SPRINTF_NEW); + } if (strEQ(d,"sqrt")) { yylval = OSQRT; XTERM(FUN1); } + if (strEQ(d,"SUBSEP")) { + d = ";"; + } + if (strEQ(d,"sin")) { + yylval = OSIN; + XTERM(FUN1); + } + if (strEQ(d,"srand")) { + yylval = OSRAND; + XTERM(FUN1); + } + if (strEQ(d,"system")) { + yylval = OSYSTEM; + XTERM(FUN1); + } + if (strEQ(d,"s")) + *d = toUPPER(*d); + else if (strEQ(d,"shift")) + *d = toUPPER(*d); + else if (strEQ(d,"select")) + *d = toUPPER(*d); + else if (strEQ(d,"seek")) + *d = toUPPER(*d); + else if (strEQ(d,"stat")) + *d = toUPPER(*d); + else if (strEQ(d,"study")) + *d = toUPPER(*d); + else if (strEQ(d,"sleep")) + *d = toUPPER(*d); + else if (strEQ(d,"symlink")) + *d = toUPPER(*d); + else if (strEQ(d,"sort")) + *d = toUPPER(*d); ID(d); case 't': case 'T': SNARFWORD; + if (strEQ(d,"tr")) + *d = toUPPER(*d); + else if (strEQ(d,"tell")) + *d = toUPPER(*d); + else if (strEQ(d,"time")) + *d = toUPPER(*d); + else if (strEQ(d,"times")) + *d = toUPPER(*d); ID(d); case 'u': case 'U': SNARFWORD; + if (strEQ(d,"until")) + *d = toUPPER(*d); + else if (strEQ(d,"unless")) + *d = toUPPER(*d); + else if (strEQ(d,"umask")) + *d = toUPPER(*d); + else if (strEQ(d,"unshift")) + *d = toUPPER(*d); + else if (strEQ(d,"unlink")) + *d = toUPPER(*d); + else if (strEQ(d,"utime")) + *d = toUPPER(*d); ID(d); case 'v': case 'V': SNARFWORD; + if (strEQ(d,"values")) + *d = toUPPER(*d); ID(d); case 'w': case 'W': SNARFWORD; if (strEQ(d,"while")) XTERM(WHILE); + if (strEQ(d,"write")) + *d = toUPPER(*d); + else if (strEQ(d,"wait")) + *d = toUPPER(*d); ID(d); case 'x': case 'X': SNARFWORD; + if (strEQ(d,"x")) + *d = toUPPER(*d); ID(d); case 'y': case 'Y': SNARFWORD; + if (strEQ(d,"y")) + *d = toUPPER(*d); ID(d); case 'z': case 'Z': SNARFWORD; @@ -540,8 +833,7 @@ yylex() } char * -scanpat(s) -register char *s; +scanpat(register char *s) { register char *d; @@ -559,6 +851,8 @@ register char *s; *d++ = *s++; else if (s[1] == '\\') *d++ = *s++; + else if (s[1] == '[') + *d++ = *s++; } else if (*s == '[') { *d++ = *s++; @@ -583,16 +877,15 @@ register char *s; return s; } -yyerror(s) -char *s; +void +yyerror(char *s) { fprintf(stderr,"%s in file %s at line %d\n", s,filename,line); } char * -scannum(s) -register char *s; +scannum(register char *s) { register char *d; @@ -600,20 +893,24 @@ register char *s; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0' : case '.': d = tokenbuf; - while (isdigit(*s)) { + while (isDIGIT(*s)) { *d++ = *s++; } - if (*s == '.' && index("0123456789eE",s[1])) { - *d++ = *s++; - while (isdigit(*s)) { + if (*s == '.') { + if (isDIGIT(s[1])) { *d++ = *s++; + while (isDIGIT(*s)) { + *d++ = *s++; + } } + else + s++; } - if (index("eE",*s) && index("+-0123456789",s[1])) { + if (strchr("eE",*s) && strchr("+-0123456789",s[1])) { *d++ = *s++; if (*s == '+' || *s == '-') *d++ = *s++; - while (isdigit(*s)) + while (isDIGIT(*s)) *d++ = *s++; } *d = '\0'; @@ -623,34 +920,37 @@ register char *s; return s; } -string(ptr,len) -char *ptr; +int +string(char *ptr, int len) { int retval = mop; ops[mop++].ival = OSTRING + (1<<8); if (!len) len = strlen(ptr); - ops[mop].cval = safemalloc(len+1); + ops[mop].cval = (char *) safemalloc(len+1); strncpy(ops[mop].cval,ptr,len); ops[mop++].cval[len] = '\0'; + if (mop >= OPSMAX) + fatal("Recompile a2p with larger OPSMAX\n"); return retval; } -oper0(type) -int type; +int +oper0(int type) { int retval = mop; if (type > 255) fatal("type > 255 (%d)\n",type); ops[mop++].ival = type; + if (mop >= OPSMAX) + fatal("Recompile a2p with larger OPSMAX\n"); return retval; } -oper1(type,arg1) -int type; -int arg1; +int +oper1(int type, int arg1) { int retval = mop; @@ -658,13 +958,13 @@ int arg1; fatal("type > 255 (%d)\n",type); ops[mop++].ival = type + (1<<8); ops[mop++].ival = arg1; + if (mop >= OPSMAX) + fatal("Recompile a2p with larger OPSMAX\n"); return retval; } -oper2(type,arg1,arg2) -int type; -int arg1; -int arg2; +int +oper2(int type, int arg1, int arg2) { int retval = mop; @@ -673,14 +973,13 @@ int arg2; ops[mop++].ival = type + (2<<8); ops[mop++].ival = arg1; ops[mop++].ival = arg2; + if (mop >= OPSMAX) + fatal("Recompile a2p with larger OPSMAX\n"); return retval; } -oper3(type,arg1,arg2,arg3) -int type; -int arg1; -int arg2; -int arg3; +int +oper3(int type, int arg1, int arg2, int arg3) { int retval = mop; @@ -690,15 +989,13 @@ int arg3; ops[mop++].ival = arg1; ops[mop++].ival = arg2; ops[mop++].ival = arg3; + if (mop >= OPSMAX) + fatal("Recompile a2p with larger OPSMAX\n"); return retval; } -oper4(type,arg1,arg2,arg3,arg4) -int type; -int arg1; -int arg2; -int arg3; -int arg4; +int +oper4(int type, int arg1, int arg2, int arg3, int arg4) { int retval = mop; @@ -709,16 +1006,13 @@ int arg4; ops[mop++].ival = arg2; ops[mop++].ival = arg3; ops[mop++].ival = arg4; + if (mop >= OPSMAX) + fatal("Recompile a2p with larger OPSMAX\n"); return retval; } -oper5(type,arg1,arg2,arg3,arg4,arg5) -int type; -int arg1; -int arg2; -int arg3; -int arg4; -int arg5; +int +oper5(int type, int arg1, int arg2, int arg3, int arg4, int arg5) { int retval = mop; @@ -730,13 +1024,15 @@ int arg5; ops[mop++].ival = arg3; ops[mop++].ival = arg4; ops[mop++].ival = arg5; + if (mop >= OPSMAX) + fatal("Recompile a2p with larger OPSMAX\n"); return retval; } int depth = 0; -dump(branch) -int branch; +void +dump(int branch) { register int type; register int len; @@ -762,9 +1058,8 @@ int branch; } } -bl(arg,maybe) -int arg; -int maybe; +int +bl(int arg, int maybe) { if (!arg) return 0; @@ -776,8 +1071,8 @@ int maybe; return arg; } -fixup(str) -STR *str; +void +fixup(STR *str) { register char *s; register char *t; @@ -788,9 +1083,9 @@ STR *str; s++; } else if (*s == '\n') { - for (t = s+1; isspace(*t & 127); t++) ; + for (t = s+1; isSPACE(*t & 127); t++) ; t--; - while (isspace(*t & 127) && *t != '\n') t--; + while (isSPACE(*t & 127) && *t != '\n') t--; if (*t == '\n' && t-s > 1) { if (s[-1] == '{') s--; @@ -801,8 +1096,8 @@ STR *str; } } -putlines(str) -STR *str; +void +putlines(STR *str) { register char *d, *s, *t, *e; register int pos, newpos; @@ -823,7 +1118,7 @@ STR *str; if (pos > 78) { /* split a long line? */ *d-- = '\0'; newpos = 0; - for (t = tokenbuf; isspace(*t & 127); t++) { + for (t = tokenbuf; isSPACE(*t & 127); t++) { if (*t == '\t') newpos += 8; else @@ -855,7 +1150,10 @@ STR *str; d--; } if (d > t+3) { - *d = '\0'; + char save[2048]; + strcpy(save, d); + *d = '\n'; + d[1] = '\0'; putone(); putchar('\n'); if (d[-1] != ';' && !(newpos % 4)) { @@ -863,7 +1161,7 @@ STR *str; *t++ = ' '; newpos += 2; } - strcpy(t,d+1); + strcpy(t,save+1); newpos += strlen(t); d = t + strlen(t); pos = newpos; @@ -874,7 +1172,8 @@ STR *str; } } -putone() +void +putone(void) { register char *t; @@ -896,16 +1195,121 @@ putone() fputs(tokenbuf,stdout); } -numary(arg) -int arg; +int +numary(int arg) { STR *key; int dummy; - key = walk(0,0,arg,&dummy); + key = walk(0,0,arg,&dummy,P_MIN); str_cat(key,"[]"); hstore(symtab,key->str_ptr,str_make("1")); str_free(key); set_array_base = TRUE; return arg; } + +int +rememberargs(int arg) +{ + int type; + STR *str; + + if (!arg) + return arg; + type = ops[arg].ival & 255; + if (type == OCOMMA) { + rememberargs(ops[arg+1].ival); + rememberargs(ops[arg+3].ival); + } + else if (type == OVAR) { + str = str_new(0); + hstore(curarghash,ops[ops[arg+1].ival+1].cval,str); + } + else + fatal("panic: unknown argument type %d, line %d\n",type,line); + return arg; +} + +int +aryrefarg(int arg) +{ + int type = ops[arg].ival & 255; + STR *str; + + if (type != OSTRING) + fatal("panic: aryrefarg %d, line %d\n",type,line); + str = hfetch(curarghash,ops[arg+1].cval); + if (str) + str_set(str,"*"); + return arg; +} + +int +fixfargs(int name, int arg, int prevargs) +{ + int type; + STR *str; + int numargs = 0; + + if (!arg) + return prevargs; + type = ops[arg].ival & 255; + if (type == OCOMMA) { + numargs = fixfargs(name,ops[arg+1].ival,prevargs); + numargs = fixfargs(name,ops[arg+3].ival,numargs); + } + else if (type == OVAR) { + str = hfetch(curarghash,ops[ops[arg+1].ival+1].cval); + if (strEQ(str_get(str),"*")) { + char tmpbuf[128]; + + str_set(str,""); /* in case another routine has this */ + ops[arg].ival &= ~255; + ops[arg].ival |= OSTAR; + sprintf(tmpbuf,"%s:%d",ops[name+1].cval,prevargs); + fprintf(stderr,"Adding %s\n",tmpbuf); + str = str_new(0); + str_set(str,"*"); + hstore(curarghash,tmpbuf,str); + } + numargs = prevargs + 1; + } + else + fatal("panic: unknown argument type %d, arg %d, line %d\n", + type,prevargs+1,line); + return numargs; +} + +int +fixrargs(char *name, int arg, int prevargs) +{ + int type; + STR *str; + int numargs; + + if (!arg) + return prevargs; + type = ops[arg].ival & 255; + if (type == OCOMMA) { + numargs = fixrargs(name,ops[arg+1].ival,prevargs); + numargs = fixrargs(name,ops[arg+3].ival,numargs); + } + else { + char *tmpbuf = (char *) safemalloc(strlen(name) + (sizeof(prevargs) * 3) + 5); + sprintf(tmpbuf,"%s:%d",name,prevargs); + str = hfetch(curarghash,tmpbuf); + safefree(tmpbuf); + if (str && strEQ(str->str_ptr,"*")) { + if (type == OVAR || type == OSTAR) { + ops[arg].ival &= ~255; + ops[arg].ival |= OSTAR; + } + else + fatal("Can't pass expression by reference as arg %d of %s\n", + prevargs+1, name); + } + numargs = prevargs + 1; + } + return numargs; +}