diff options
author | kstailey <kstailey@cvs.openbsd.org> | 1997-08-25 16:17:15 +0000 |
---|---|---|
committer | kstailey <kstailey@cvs.openbsd.org> | 1997-08-25 16:17:15 +0000 |
commit | c1a12065492ecafe5bd1c4d09bd507f692624839 (patch) | |
tree | 807c1f8e2f4da44ce9e68bde04d631cb316e4b5f /usr.bin | |
parent | 73138c6a805b3d20f0625381b3f31c910da81d50 (diff) |
August 1997 version of "the one true awk"
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/awk/FIXES | 101 | ||||
-rw-r--r-- | usr.bin/awk/Makefile | 21 | ||||
-rw-r--r-- | usr.bin/awk/OpenBSD-PATCHES | 18 | ||||
-rw-r--r-- | usr.bin/awk/README | 90 | ||||
-rw-r--r-- | usr.bin/awk/awk.h | 61 | ||||
-rw-r--r-- | usr.bin/awk/awkgram.y | 72 | ||||
-rw-r--r-- | usr.bin/awk/awklex.l | 332 | ||||
-rw-r--r-- | usr.bin/awk/b.c | 97 | ||||
-rw-r--r-- | usr.bin/awk/lex.c | 572 | ||||
-rw-r--r-- | usr.bin/awk/lexyy.c | 2031 | ||||
-rw-r--r-- | usr.bin/awk/lib.c | 456 | ||||
-rw-r--r-- | usr.bin/awk/main.c | 62 | ||||
-rw-r--r-- | usr.bin/awk/maketab.c | 37 | ||||
-rw-r--r-- | usr.bin/awk/parse.c | 45 | ||||
-rw-r--r-- | usr.bin/awk/proto.h | 38 | ||||
-rw-r--r-- | usr.bin/awk/run.c | 539 | ||||
-rw-r--r-- | usr.bin/awk/tran.c | 158 |
17 files changed, 1583 insertions, 3147 deletions
diff --git a/usr.bin/awk/FIXES b/usr.bin/awk/FIXES index 8e8cc6047df..20ab0d20d41 100644 --- a/usr.bin/awk/FIXES +++ b/usr.bin/awk/FIXES @@ -1,6 +1,6 @@ -/* $OpenBSD: FIXES,v 1.5 1997/01/24 23:43:09 kstailey Exp $ */ +/* $OpenBSD: FIXES,v 1.6 1997/08/25 16:17:07 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -8,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ This file lists all bug fixes, changes, etc., made since the AWK book @@ -476,5 +476,72 @@ Jun 29, 1996: fixed awful bug in new field splitting; didn't get all the places where input was done. -Jan 21, 1997 - Fixed %c: works if the value is 0 -- now prints \0. +Jul 8, 1996: + fixed long-standing bug in sub, gsub(/a/, "\\\\&"); thanks to + ralph corderoy. + +Jun 17, 1997: + replaced several fixed-size arrays by dynamically-created ones + in run.c; added overflow tests to some previously unchecked cases. + getline, toupper, tolower. + + getline code is still broken in that recursive calls may wind + up using the same space. [fixed later] + + increased RECSIZE to 8192 to push problems further over the horizon. + + added \r to \n as input line separator for programs, not data. + damn CRLFs. + + modified format() to permit explicit printf("%c", 0) to include + a null byte in output. thanks to ken stailey for the fix. + + added a "-safe" argument that disables file output (print >, + print >>), process creation (cmd|getline, print |, system), and + access to the environment (ENVIRON). this is a first approximation + to a "safe" version of awk, but don't rely on it too much. thanks + to joan feigenbaum and matt blaze for the inspiration long ago. + +Jul 23, 1997: + falling off the end of a function returns "" and 0, not 0. + thanks to arnold robbins. + +Jul 30, 1997: + using code provided by dan levy (to whom profuse thanks), replaced + fixed-size arrays and awkward kludges by a fairly uniform mechanism + to grow arrays as needed for printf, sub, gsub, etc. + +Aug 4, 1997: + with some trepidation, replaced the ancient code that managed + fields and $0 in fixed-size arrays with arrays that grow on + demand. there is still some tension between trying to make this + run fast and making it clean; not sure it's right yet. + + the ill-conceived -mr and -mf arguments are now useful only + for debugging. previous dynamic string code removed. + + numerous other minor cleanups along the way. + +Aug 9, 1997: + somewhat regretfully, replaced the ancient lex-based lexical + analyzer with one written in C. it's longer, generates less code, + and more portable; the old one depended too much on mysterious + properties of lex that were not preserved in other environments. + in theory these recognize the same language. + + now using strtod to test whether a string is a number, instead of + the convoluted original function. should be more portable and + reliable if strtod is implemented right. + + removed now-pointless optimization in makefile that tries to avoid + recompilation when awkgram.y is changed but symbols are not. + + removed most fixed-size arrays, though a handful remain, some + of which are unchecked. you have been warned. + +Aug 21, 1997: + fixed some bugs in sub and gsub when replacement includes \\. + this is a dark, horrible corner, but at least now i believe that + the behavior is the same as gawk and the intended posix standard. + thanks to arnold robbins for advice here. + diff --git a/usr.bin/awk/Makefile b/usr.bin/awk/Makefile index 4cac064ba52..49f718d1d42 100644 --- a/usr.bin/awk/Makefile +++ b/usr.bin/awk/Makefile @@ -1,24 +1,23 @@ -# $OpenBSD: Makefile,v 1.4 1997/01/24 23:11:29 millert Exp $ +# $OpenBSD: Makefile,v 1.5 1997/08/25 16:17:08 kstailey Exp $ PROG= awk LINKS= ${BINDIR}/awk ${BINDIR}/nawk -SRCS= awkgram.c lexyy.c b.c main.c parse.c proctab.c tran.c lib.c run.c -LDADD= -ll -lm -DPADD= ${LIBL} ${LIBM} -CLEANFILES+=awkgram.c awkgram.h proctab.c maketab prevawkgram.h +SRCS= ytab.c lex.c b.c main.c parse.c proctab.c tran.c lib.c run.c +LDADD= -lm +DPADD= ${LIBM} +CLEANFILES+=proctab.c maketab ytab.c ytab.h CFLAGS+=-I. -I${.CURDIR} MLINKS= awk.1 nawk.1 -awkgram.c awkgram.h prevawkgram.h: awkgram.y - ${YACC} -d ${.IMPSRC} - mv y.tab.c awkgram.c - mv y.tab.h awkgram.h - cmp -s awkgram.h prevawkgram.h || cp awkgram.h prevawkgram.h +ytab.c ytab.h: awkgram.y + ${YACC} -d ${.CURDIR}/awkgram.y + mv y.tab.c ytab.c + mv y.tab.h ytab.h proctab.c: maketab ./maketab >proctab.c -maketab: prevawkgram.h +maketab: ytab.h maketab.c ${HOSTCC} ${CFLAGS} ${.CURDIR}/maketab.c -o $@ .include <bsd.prog.mk> diff --git a/usr.bin/awk/OpenBSD-PATCHES b/usr.bin/awk/OpenBSD-PATCHES index b011fb71ed0..ca34ad04f60 100644 --- a/usr.bin/awk/OpenBSD-PATCHES +++ b/usr.bin/awk/OpenBSD-PATCHES @@ -1,3 +1,19 @@ +/* $OpenBSD: OpenBSD-PATCHES,v 1.2 1997/08/25 16:17:08 kstailey Exp $ */ + +I merged the August 1997 version of the "one true awk" from Brian Kernighan's +web page http://cm.bell-labs.com/who/bwk/ + +Mods to the distribution sources: +1) OpenBSD tags in all files. +2) setlocate(3) call added to main(). +3) slashes in argv[0] stripped from program name in main(). +4) left out win95 bits, distribution makefile, backup copies of yacc generated + files. + + +Start of historical section: + +-------------------------------------------------------------- These are the changes made from Research Awk to allow it to build on OpenBSD with flex. Below is the inof that came with the original set of diffs (from 4.4BSD). ytab.* was @@ -22,7 +38,7 @@ Let me know if you find more problems. --- /home/millert/tmp/awk/awk.1 Sun Jan 19 18:06:25 1997 +++ awk.1 Sun Jan 19 17:51:39 1997 @@ -1,3 +1,4 @@ -+.\" $OpenBSD: OpenBSD-PATCHES,v 1.1 1997/01/20 19:43:16 millert Exp $ ++.\" $OpenBSD: OpenBSD-PATCHES,v 1.2 1997/08/25 16:17:08 kstailey Exp $ .de EX .nf .ft CW diff --git a/usr.bin/awk/README b/usr.bin/awk/README index ffb736b6b48..cd45a87bbe2 100644 --- a/usr.bin/awk/README +++ b/usr.bin/awk/README @@ -1,5 +1,6 @@ +/* $OpenBSD: README,v 1.2 1997/08/25 16:17:08 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,24 +8,25 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ This is the version of awk described in "The AWK Programming Language", -by A. V. Aho, B. W. Kernighan, and P. J. Weinberger +by Al Aho, Brian Kernighan, and Peter Weinberger (Addison-Wesley, 1988, ISBN 0-201-07981-X). + Changes, mostly bug fixes and occasional enhancements, are listed in FIXES. If you distribute this code further, please please please distribute FIXES with it. If you find errors, please report them @@ -32,38 +34,46 @@ to bwk@bell-labs.com. Thanks. The program itself is created by make -which should produce a longish sequence of messages roughly like this: +which should produce a sequence of messages roughly like this: - yacc -d awkgram.y + yacc -d awkgram.y -conflicts: 43 shift/reduce, 85 reduce/reduce - mv y.tab.c ytab.c - mv y.tab.h ytab.h - cc -O -c ytab.c - cmp -s ytab.h prevytab.h || (cp ytab.h prevytab.h; echo change maketab) -change maketab - cc -O -c b.c - cc -O -c main.c - cc -O -c parse.c - cc -O maketab.c -o maketab - ./maketab >proctab.c - cc -O -c proctab.c - cc -O -c tran.c - cc -O -c lib.c - cc -O -c run.c - lex awklex.l - mv lex.yy.c lexyy.c - cc -O -c lexyy.c - cc -O ytab.o lexyy.o b.o main.o parse.o proctab.o tran.o lib.o run.o -lm +conflicts: 42 shift/reduce, 83 reduce/reduce + mv y.tab.c ytab.c + mv y.tab.h ytab.h + cc -O -c ytab.c + cc -O -c b.c + cc -O -c main.c + cc -O -c parse.c + cc -O maketab.c -o maketab + ./maketab >proctab.c + cc -O -c proctab.c + cc -O -c tran.c + cc -O -c lib.c + cc -O -c run.c + cc -O -c lex.c + cc -O ytab.o b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o -lm This produces an executable a.out; you will eventually want to move this to some place like /usr/bin/awk. -If your system is missing some of the components, e.g., yacc or lex, -you should be able to compile the pieces manually. We have included -yacc output in ytab.c and ytab.h, and lex output in lexyy.c. +If your system is does not have yacc or bison (the GNU +equivalent), you must compile the pieces manually. We have +included yacc output in ytab.c and ytab.h, and backup copies in +case you overwrite them. + +NOTE: This version uses ANSI C, as you should also. We have +compiled this without any changes using gcc -Wall and/or local C +compilers on a variety of systems, but new systems or compilers +may raise some new complaint; reports of difficulties are +welcome. -NOTE: This version uses ANSI C, as you should also. +This also compiles with Visual C++ 4.1 on Windows 95 and +presumably Windows NT, *if* you provide versions of popen and +pclose. The file missing95.c contains do-nothing versions that +can be used to get started with. It is too much trouble to +figure out how to make these work for real. -The version of malloc that comes with some systems (e.g., IRIX) is +The version of malloc that comes with some systems is sometimes astonishly slow. If awk seems slow, you might try fixing that. + diff --git a/usr.bin/awk/awk.h b/usr.bin/awk/awk.h index 213e43302c8..3a391239334 100644 --- a/usr.bin/awk/awk.h +++ b/usr.bin/awk/awk.h @@ -1,5 +1,6 @@ +/* $OpenBSD: awk.h,v 1.5 1997/08/25 16:17:09 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ typedef double Awkfloat; @@ -38,16 +39,17 @@ typedef unsigned char uschar; # define dprintf(x) #endif -extern char errbuf[200]; +extern char errbuf[]; #define ERROR sprintf(errbuf, #define FATAL ), error(1, errbuf) #define WARNING ), error(0, errbuf) #define SYNTAX ), yyerror(errbuf) extern int compile_time; /* 1 if compiling, 0 if running */ +extern int safe; /* 0 => unsafe, 1 => safe */ -#define RECSIZE (3 * 1024) /* sets limit on records, fields, etc., etc. */ -extern int recsize; /* variable version */ +#define RECSIZE (8 * 1024) /* sets limit on records, fields, etc., etc. */ +extern int recsize; /* size of current record, orig RECSIZE */ extern char **FS; extern char **RS; @@ -71,20 +73,6 @@ extern char inputFS[]; /* FS at time of input, for field splitting */ extern int dbg; -typedef struct { - char *cbuf; - int clen; - int cmax; -} Gstring; /* a string that grows */ - -extern Gstring *newGstring(void); /* constructor */ -extern void delGstring(Gstring *); /* destructor */ -extern char *cadd(Gstring *gs, int c); /* function to grow with */ -extern void caddreset(Gstring *gs); /* set cbuf empty */ -extern void cunadd(Gstring *gs); /* back up one char in cbuf */ - -extern Gstring *gs; /* used by lex */ - extern char *patbeg; /* beginning of pattern matched */ extern int patlen; /* length of pattern matched. set in b.c */ @@ -100,7 +88,7 @@ typedef struct Cell { struct Cell *cnext; /* ptr to next if chained */ } Cell; -typedef struct { /* symbol table array */ +typedef struct Array { /* symbol table array */ int nelem; /* elements in table right now */ int size; /* size of tab */ Cell **tab; /* hash table pointers */ @@ -109,7 +97,6 @@ typedef struct { /* symbol table array */ #define NSYMTAB 50 /* initial size of a symbol table */ extern Array *symtab; -extern Cell *recloc; /* location of input record */ extern Cell *nrloc; /* NR */ extern Cell *fnrloc; /* FNR */ extern Cell *nfloc; /* NF */ @@ -190,7 +177,6 @@ extern Node *nullnode; #define NVALUE 1 #define NSTAT 2 #define NEXPR 3 -#define NFIELD 4 extern int pairstack[], paircnt; @@ -205,14 +191,17 @@ extern int pairstack[], paircnt; #define isnext(n) ((n)->csub == JNEXT) #define isnextfile(n) ((n)->csub == JNEXTFILE) #define isret(n) ((n)->csub == JRET) +#define isrec(n) ((n)->tval & REC) +#define isfld(n) ((n)->tval & FLD) #define isstr(n) ((n)->tval & STR) #define isnum(n) ((n)->tval & NUM) #define isarr(n) ((n)->tval & ARR) -#define isfunc(n) ((n)->tval & FCN) +#define isfcn(n) ((n)->tval & FCN) #define istrue(n) ((n)->csub == BTRUE) #define istemp(n) ((n)->csub == CTEMP) #define isargument(n) ((n)->nobj == ARG) -#define freeable(p) (!((p)->tval & DONTFREE)) +/* #define freeable(p) (!((p)->tval & DONTFREE)) */ +#define freeable(p) ( ((p)->tval & (STR|DONTFREE)) == STR ) /* structures used by regular expression matching machinery, mostly b.c: */ diff --git a/usr.bin/awk/awkgram.y b/usr.bin/awk/awkgram.y index e1cb9f6e6fe..bd751e3e8f7 100644 --- a/usr.bin/awk/awkgram.y +++ b/usr.bin/awk/awkgram.y @@ -1,5 +1,6 @@ +/* $OpenBSD: awkgram.y,v 1.4 1997/08/25 16:17:09 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ %{ @@ -59,7 +60,7 @@ Node *arglist = 0; /* list of args for current function */ %token <i> PRINT PRINTF SPRINTF %token <p> ELSE INTEST CONDEXPR %token <i> POSTINCR PREINCR POSTDECR PREDECR -%token <cp> VAR IVAR VARNF CALL NUMBER STRING FIELD +%token <cp> VAR IVAR VARNF CALL NUMBER STRING %token <s> REGEXPR %type <p> pas pattern ppattern plist pplist patlist prarg term re @@ -79,7 +80,7 @@ Node *arglist = 0; /* list of args for current function */ %left AND %left GETLINE %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|' -%left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FIELD FUNC +%left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC %left GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER %left PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR %left REGEXPR VAR VARNF IVAR WHILE '(' @@ -238,8 +239,12 @@ pattern: $$ = op3($2, (Node *)1, $1, $3); } | pattern IN varname { $$ = op2(INTEST, $1, makearr($3)); } | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); } - | pattern '|' GETLINE var { $$ = op3(GETLINE, $4, (Node*)$2, $1); } - | pattern '|' GETLINE { $$ = op3(GETLINE, (Node*)0, (Node*)$2, $1); } + | pattern '|' GETLINE var { + if (safe) ERROR "cmd | getline is unsafe" SYNTAX; + else $$ = op3(GETLINE, $4, (Node*)$2, $1); } + | pattern '|' GETLINE { + if (safe) ERROR "cmd | getline is unsafe" SYNTAX; + else $$ = op3(GETLINE, (Node*)0, (Node*)$2, $1); } | pattern term %prec CAT { $$ = op2(CAT, $1, $2); } | re | term @@ -288,9 +293,15 @@ rparen: ; simple_stmt: - print prarg '|' term { $$ = stat3($1, $2, (Node *) $3, $4); } - | print prarg APPEND term { $$ = stat3($1, $2, (Node *) $3, $4); } - | print prarg GT term { $$ = stat3($1, $2, (Node *) $3, $4); } + print prarg '|' term { + if (safe) ERROR "print | is unsafe" SYNTAX; + else $$ = stat3($1, $2, (Node *) $3, $4); } + | print prarg APPEND term { + if (safe) ERROR "print >> is unsafe" SYNTAX; + else $$ = stat3($1, $2, (Node *) $3, $4); } + | print prarg GT term { + if (safe) ERROR "print > is unsafe" SYNTAX; + else $$ = stat3($1, $2, (Node *) $3, $4); } | print prarg { $$ = stat3($1, $2, NIL, NIL); } | DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); } | DELETE varname { $$ = stat2(DELETE, makearr($2), 0); } @@ -352,8 +363,8 @@ term: | BLTIN '(' ')' { $$ = op2(BLTIN, (Node *) $1, rectonode()); } | BLTIN '(' patlist ')' { $$ = op2(BLTIN, (Node *) $1, $3); } | BLTIN { $$ = op2(BLTIN, (Node *) $1, rectonode()); } - | CALL '(' ')' { $$ = op2(CALL, valtonode($1,CVAR), NIL); } - | CALL '(' patlist ')' { $$ = op2(CALL, valtonode($1,CVAR), $3); } + | CALL '(' ')' { $$ = op2(CALL, celltonode($1,CVAR), NIL); } + | CALL '(' patlist ')' { $$ = op2(CALL, celltonode($1,CVAR), $3); } | DECR var { $$ = op1(PREDECR, $2); } | INCR var { $$ = op1(PREINCR, $2); } | var DECR { $$ = op1(POSTDECR, $1); } @@ -375,7 +386,7 @@ term: $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1)); else $$ = op3(MATCHFCN, (Node *)1, $3, $5); } - | NUMBER { $$ = valtonode($1, CCON); } + | NUMBER { $$ = celltonode($1, CCON); } | SPLIT '(' pattern comma varname comma pattern ')' /* string */ { $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); } | SPLIT '(' pattern comma varname comma reg_expr ')' /* const /regexp/ */ @@ -383,7 +394,7 @@ term: | SPLIT '(' pattern comma varname ')' { $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); } /* default */ | SPRINTF '(' patlist ')' { $$ = op1($1, $3); } - | STRING { $$ = valtonode($1, CCON); } + | STRING { $$ = celltonode($1, CCON); } | subop '(' reg_expr comma pattern ')' { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); } | subop '(' pattern comma pattern ')' @@ -408,21 +419,20 @@ term: var: varname | varname '[' patlist ']' { $$ = op2(ARRAY, makearr($1), $3); } - | FIELD { $$ = valtonode($1, CFLD); } - | IVAR { $$ = op1(INDIRECT, valtonode($1, CVAR)); } + | IVAR { $$ = op1(INDIRECT, celltonode($1, CVAR)); } | INDIRECT term { $$ = op1(INDIRECT, $2); } ; varlist: /* nothing */ { arglist = $$ = 0; } - | VAR { arglist = $$ = valtonode($1,CVAR); } + | VAR { arglist = $$ = celltonode($1,CVAR); } | varlist comma VAR { checkdup($1, $3); - arglist = $$ = linkum($1,valtonode($3,CVAR)); } + arglist = $$ = linkum($1,celltonode($3,CVAR)); } ; varname: - VAR { $$ = valtonode($1, CVAR); } + VAR { $$ = celltonode($1, CVAR); } | ARG { $$ = op1(ARG, (Node *) $1); } | VARNF { $$ = op1(VARNF, (Node *) $1); } ; @@ -438,7 +448,7 @@ void setfname(Cell *p) { if (isarr(p)) ERROR "%s is an array, not a function", p->nval SYNTAX; - else if (isfunc(p)) + else if (isfcn(p)) ERROR "you can't define function %s more than once", p->nval SYNTAX; curfname = p->nval; } diff --git a/usr.bin/awk/awklex.l b/usr.bin/awk/awklex.l deleted file mode 100644 index 62b1f0488c6..00000000000 --- a/usr.bin/awk/awklex.l +++ /dev/null @@ -1,332 +0,0 @@ -%Start A str sc reg comment - -%{ -/**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. -****************************************************************/ - -/* some of this depends on behavior of lex that - may not be preserved in other implementations of lex. -*/ - -#undef input /* defeat lex */ -#undef unput - -#include <stdlib.h> -#include <string.h> -#include "awk.h" -#include "ytab.h" - -extern YYSTYPE yylval; -extern int infunc; - -int lineno = 1; -int bracecnt = 0; -int brackcnt = 0; -int parencnt = 0; - -#define DEBUG -#ifdef DEBUG -# define RET(x) {if(dbg)printf("lex %s [%s]\n", tokname(x), yytext); return(x); } -#else -# define RET(x) return(x) -#endif - -#define CADD if (cadd(gs, yytext[0]) == 0) { \ - ERROR "string/reg expr %.30s... too long", gs->cbuf SYNTAX; \ - BEGIN A; \ - } - -char *s; -Gstring *gs = 0; /* initialized in main() */ -int cflag; -%} - -A [a-zA-Z_] -B [a-zA-Z0-9_] -D [0-9] -O [0-7] -H [0-9a-fA-F] -WS [ \t] - -%% - switch (yybgin-yysvec-1) { /* witchcraft */ - case 0: - BEGIN A; - break; - case sc: - BEGIN A; - RET('}'); - } - -<A>\n { lineno++; RET(NL); } -<A>#.* { ; } /* strip comments */ -<A>{WS}+ { ; } -<A>; { RET(';'); } - -<A>"\\"\n { lineno++; } -<A>BEGIN { RET(XBEGIN); } -<A>END { RET(XEND); } -<A>func(tion)? { if (infunc) ERROR "illegal nested function" SYNTAX; RET(FUNC); } -<A>return { if (!infunc) ERROR "return not in function" SYNTAX; RET(RETURN); } -<A>"&&" { RET(AND); } -<A>"||" { RET(BOR); } -<A>"!" { RET(NOT); } -<A>"!=" { yylval.i = NE; RET(NE); } -<A>"~" { yylval.i = MATCH; RET(MATCHOP); } -<A>"!~" { yylval.i = NOTMATCH; RET(MATCHOP); } -<A>"<" { yylval.i = LT; RET(LT); } -<A>"<=" { yylval.i = LE; RET(LE); } -<A>"==" { yylval.i = EQ; RET(EQ); } -<A>">=" { yylval.i = GE; RET(GE); } -<A>">" { yylval.i = GT; RET(GT); } -<A>">>" { yylval.i = APPEND; RET(APPEND); } -<A>"++" { yylval.i = INCR; RET(INCR); } -<A>"--" { yylval.i = DECR; RET(DECR); } -<A>"+=" { yylval.i = ADDEQ; RET(ASGNOP); } -<A>"-=" { yylval.i = SUBEQ; RET(ASGNOP); } -<A>"*=" { yylval.i = MULTEQ; RET(ASGNOP); } -<A>"/=" { yylval.i = DIVEQ; RET(ASGNOP); } -<A>"%=" { yylval.i = MODEQ; RET(ASGNOP); } -<A>"^=" { yylval.i = POWEQ; RET(ASGNOP); } -<A>"**=" { yylval.i = POWEQ; RET(ASGNOP); } -<A>"=" { yylval.i = ASSIGN; RET(ASGNOP); } -<A>"**" { RET(POWER); } -<A>"^" { RET(POWER); } - -<A>"$"{D}+ { yylval.cp = fieldadr(atoi(yytext+1)); RET(FIELD); } -<A>"$NF" { unputstr("(NF)"); return(INDIRECT); } -<A>"$"{A}{B}* { int c, n; - c = input(); unput(c); - if (c == '(' || c == '[' || (infunc && (n=isarg(yytext+1)) >= 0)) { - unputstr(yytext+1); - return(INDIRECT); - } else { - yylval.cp = setsymtab(yytext+1, "", 0.0, STR|NUM, symtab); - RET(IVAR); - } - } -<A>"$" { RET(INDIRECT); } -<A>NF { yylval.cp = setsymtab(yytext, "", 0.0, NUM, symtab); RET(VARNF); } - -<A>({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)? { - yylval.cp = setsymtab(yytext, tostring(yytext), atof(yytext), CON|NUM, symtab); - /* should this also have STR set? */ - RET(NUMBER); } - -<A>while { RET(WHILE); } -<A>for { RET(FOR); } -<A>do { RET(DO); } -<A>if { RET(IF); } -<A>else { RET(ELSE); } -<A>next { RET(NEXT); } -<A>nextfile { RET(NEXTFILE); } -<A>exit { RET(EXIT); } -<A>break { RET(BREAK); } -<A>continue { RET(CONTINUE); } -<A>print { yylval.i = PRINT; RET(PRINT); } -<A>printf { yylval.i = PRINTF; RET(PRINTF); } -<A>sprintf { yylval.i = SPRINTF; RET(SPRINTF); } -<A>split { yylval.i = SPLIT; RET(SPLIT); } -<A>substr { RET(SUBSTR); } -<A>sub { yylval.i = SUB; RET(SUB); } -<A>gsub { yylval.i = GSUB; RET(GSUB); } -<A>index { RET(INDEX); } -<A>match { RET(MATCHFCN); } -<A>in { RET(IN); } -<A>getline { RET(GETLINE); } -<A>close { RET(CLOSE); } -<A>delete { RET(DELETE); } -<A>length { yylval.i = FLENGTH; RET(BLTIN); } -<A>log { yylval.i = FLOG; RET(BLTIN); } -<A>int { yylval.i = FINT; RET(BLTIN); } -<A>exp { yylval.i = FEXP; RET(BLTIN); } -<A>sqrt { yylval.i = FSQRT; RET(BLTIN); } -<A>sin { yylval.i = FSIN; RET(BLTIN); } -<A>cos { yylval.i = FCOS; RET(BLTIN); } -<A>atan2 { yylval.i = FATAN; RET(BLTIN); } -<A>system { yylval.i = FSYSTEM; RET(BLTIN); } -<A>rand { yylval.i = FRAND; RET(BLTIN); } -<A>srand { yylval.i = FSRAND; RET(BLTIN); } -<A>toupper { yylval.i = FTOUPPER; RET(BLTIN); } -<A>tolower { yylval.i = FTOLOWER; RET(BLTIN); } -<A>fflush { yylval.i = FFLUSH; RET(BLTIN); } - -<A>{A}{B}* { int n, c; - c = input(); unput(c); /* look for '(' */ - if (c != '(' && infunc && (n=isarg(yytext)) >= 0) { - yylval.i = n; - RET(ARG); - } else { - yylval.cp = setsymtab(yytext, "", 0.0, STR|NUM, symtab); - if (c == '(') { - RET(CALL); - } else { - RET(VAR); - } - } - } -<A>\" { BEGIN str; caddreset(gs); } - -<A>"}" { if (--bracecnt < 0) ERROR "extra }" SYNTAX; BEGIN sc; RET(';'); } -<A>"]" { if (--brackcnt < 0) ERROR "extra ]" SYNTAX; RET(']'); } -<A>")" { if (--parencnt < 0) ERROR "extra )" SYNTAX; RET(')'); } - -<A>. { if (yytext[0] == '{') bracecnt++; - else if (yytext[0] == '[') brackcnt++; - else if (yytext[0] == '(') parencnt++; - RET(yylval.i = yytext[0]); /* everything else */ } - -<reg>\\. { cadd(gs, '\\'); cadd(gs, yytext[1]); } -<reg>\n { ERROR "newline in regular expression %.10s...", gs->cbuf SYNTAX; lineno++; BEGIN A; } -<reg>"/" { BEGIN A; - cadd(gs, 0); - yylval.s = tostring(gs->cbuf); - unput('/'); - RET(REGEXPR); } -<reg>. { CADD; } - -<str>\" { BEGIN A; - cadd(gs, 0); s = tostring(gs->cbuf); - cunadd(gs); - cadd(gs, ' '); cadd(gs, 0); - yylval.cp = setsymtab(gs->cbuf, s, 0.0, CON|STR, symtab); - RET(STRING); } -<str>\n { ERROR "newline in string %.10s...", gs->cbuf SYNTAX; lineno++; BEGIN A; } -<str>"\\\"" { cadd(gs, '"'); } -<str>"\\"n { cadd(gs, '\n'); } -<str>"\\"t { cadd(gs, '\t'); } -<str>"\\"f { cadd(gs, '\f'); } -<str>"\\"r { cadd(gs, '\r'); } -<str>"\\"b { cadd(gs, '\b'); } -<str>"\\"v { cadd(gs, '\v'); } /* these ANSIisms may not be known by */ -<str>"\\"a { cadd(gs, '\007'); } /* your compiler. hence 007 for bell */ -<str>"\\\\" { cadd(gs, '\\'); } -<str>"\\"({O}{O}{O}|{O}{O}|{O}) { int n; - sscanf(yytext+1, "%o", &n); cadd(gs, n); } -<str>"\\"x({H}+) { int n; /* ANSI permits any number! */ - sscanf(yytext+2, "%x", &n); cadd(gs, n); } -<str>"\\". { cadd(gs, yytext[1]); } -<str>. { CADD; } - -%% - -void startreg(void) /* start parsing a regular expression */ -{ - BEGIN reg; - caddreset(gs); -} - -/* input() and unput() are transcriptions of the standard lex - macros for input and output with additions for error message - printing. God help us all if someone changes how lex works. -*/ - -char ebuf[300]; -char *ep = ebuf; - -int input(void) /* get next lexical input character */ -{ - int c; - extern char *lexprog; - - if (yysptr > yysbuf) - c = U(*--yysptr); - else if (lexprog != NULL) { /* awk '...' */ - if ((c = *lexprog) != 0) - lexprog++; - } else /* awk -f ... */ - c = pgetc(); - if (c == '\n') - yylineno++; - else if (c == EOF) - c = 0; - if (ep >= ebuf + sizeof ebuf) - ep = ebuf; - return *ep++ = c; -} - -void unput(int c) /* put lexical character back on input */ -{ - yytchar = c; - if (yytchar == '\n') - yylineno--; - *yysptr++ = yytchar; - if (--ep < ebuf) - ep = ebuf + sizeof(ebuf) - 1; -} - - -void unputstr(char *s) /* put a string back on input */ -{ - int i; - - for (i = strlen(s)-1; i >= 0; i--) - unput(s[i]); -} - -/* growing-string code */ - -const int CBUFLEN = 400; - -Gstring *newGstring() -{ - Gstring *gs = (Gstring *) malloc(sizeof(Gstring)); - char *cp = (char *) malloc(CBUFLEN); - - if (gs == 0 || cp == 0) - ERROR "Out of space for strings" FATAL; - gs->cbuf = cp; - gs->cmax = CBUFLEN; - gs->clen = 0; - return gs; -} - -char *cadd(Gstring *gs, int c) /* add one char to gs->cbuf, grow as needed */ -{ - if (gs->clen >= gs->cmax) { /* need to grow */ - gs->cmax *= 4; - gs->cbuf = (char *) realloc((void *) gs->cbuf, gs->cmax); - - } - if (gs->cbuf != 0) - gs->cbuf[gs->clen++] = c; - return gs->cbuf; -} - -void caddreset(Gstring *gs) -{ - gs->clen = 0; -} - -void cunadd(Gstring *gs) -{ - if (gs->clen > 0) - gs->clen--; -} - -void delGstring(Gstring *gs) -{ - free((void *) gs->cbuf); - free((void *) gs); -} diff --git a/usr.bin/awk/b.c b/usr.bin/awk/b.c index 9952d94ed35..8778c980d18 100644 --- a/usr.bin/awk/b.c +++ b/usr.bin/awk/b.c @@ -1,5 +1,6 @@ +/* $OpenBSD: b.c,v 1.5 1997/08/25 16:17:10 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ /* lasciate ogne speranza, voi ch'entrate. */ @@ -31,7 +32,7 @@ USE OR PERFORMANCE OF THIS SOFTWARE. #include <string.h> #include <stdlib.h> #include "awk.h" -#include "awkgram.h" +#include "ytab.h" #define HAT (NCHARS-1) /* matches ^ in regular expr */ /* NCHARS is 2**n */ @@ -283,42 +284,46 @@ int quoted(char **pp) /* pick up next thing after a \\ */ char *cclenter(char *p) /* add a character class */ { int i, c, c2; - char *op; - static Gstring *cgp = 0; + char *op, *bp; + static char *buf = 0; + static int bufsz = 100; op = p; - if (cgp == 0) - cgp = newGstring(); - caddreset(cgp); - i = 0; - while ((c = *p++) != 0) { + if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL) + ERROR "out of space for character class [%.10s...] 1", p FATAL; + bp = buf; + for (i = 0; (c = *p++) != 0; ) { if (c == '\\') { c = quoted(&p); - } else if (c == '-' && i > 0 && cgp->cbuf[i-1] != 0) { + } else if (c == '-' && i > 0 && bp[-1] != 0) { if (*p != 0) { - c = cgp->cbuf[i-1]; + c = bp[-1]; c2 = *p++; if (c2 == '\\') c2 = quoted(&p); if (c > c2) { /* empty; ignore */ - cunadd(cgp); + bp--; i--; continue; } while (c < c2) { - cadd(cgp, ++c); + if (!adjbuf(&buf, &bufsz, bp-buf+2, 100, &bp, 0)) + ERROR "out of space for character class [%.10s...] 2", p FATAL; + *bp++ = ++c; i++; } continue; } } - cadd(cgp, c); + if (!adjbuf(&buf, &bufsz, bp-buf+2, 100, &bp, 0)) + ERROR "out of space for character class [%.10s...] 3", p FATAL; + *bp++ = c; i++; } - cadd(cgp, 0); - dprintf( ("cclenter: in = |%s|, out = |%s|\n", op, cgp->cbuf) ); + *bp = 0; + dprintf( ("cclenter: in = |%s|, out = |%s|\n", op, buf) ); xfree(op); - return(tostring(cgp->cbuf)); + return(tostring(buf)); } void overflo(char *s) @@ -339,9 +344,8 @@ void cfoll(fa *f, Node *v) /* enter follow set of each leaf of vertex v into lfo maxsetvec *= 4; setvec = (int *) realloc(setvec, maxsetvec * sizeof(int)); tmpset = (int *) realloc(tmpset, maxsetvec * sizeof(int)); - if (setvec == 0 || tmpset == 0) { abort(); + if (setvec == 0 || tmpset == 0) overflo("out of space in cfoll()"); -} } for (i = 0; i <= f->accept; i++) setvec[i] = 0; @@ -676,9 +680,11 @@ Node *unary(Node *np) int relex(void) /* lexical analyzer for reparse */ { - int c; + int c, n; int cflag; - static Gstring *gp = 0; + static char *buf = 0; + static int bufsz = 100; + char *bp; switch (c = *prestr++) { case '|': return OR; @@ -699,36 +705,39 @@ int relex(void) /* lexical analyzer for reparse */ rlxval = c; return CHAR; case '[': - if (gp == 0) - gp = newGstring(); - caddreset(gp); + if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL) + ERROR "out of space in reg expr %.10s..", lastre FATAL; + bp = buf; if (*prestr == '^') { cflag = 1; prestr++; } else cflag = 0; + n = 2 * strlen(prestr)+1; + if (!adjbuf(&buf, &bufsz, n, n, &bp, 0)) + ERROR "out of space for reg expr %.10s...", lastre FATAL; for (; ; ) { if ((c = *prestr++) == '\\') { - cadd(gp, '\\'); + *bp++ = '\\'; if ((c = *prestr++) == '\0') ERROR "nonterminated character class %.20s...", lastre FATAL; - cadd(gp, c); + *bp++ = c; } else if (c == '\n') { ERROR "newline in character class %.20s...", lastre FATAL; } else if (c == '\0') { ERROR "nonterminated character class %.20s", lastre FATAL; - } else if (gp->clen == 0) { /* 1st char is special */ - cadd(gp, c); + } else if (bp == buf) { /* 1st char is special */ + *bp++ = c; } else if (c == ']') { - cadd(gp, 0); - rlxstr = tostring(gp->cbuf); + *bp++ = 0; + rlxstr = tostring(buf); if (cflag == 0) return CCL; else return NCCL; } else - cadd(gp, c); + *bp++ = c; } } } diff --git a/usr.bin/awk/lex.c b/usr.bin/awk/lex.c new file mode 100644 index 00000000000..cb89504c0c5 --- /dev/null +++ b/usr.bin/awk/lex.c @@ -0,0 +1,572 @@ +/* $OpenBSD: lex.c,v 1.1 1997/08/25 16:17:11 kstailey Exp $ */ +/**************************************************************** +Copyright (C) Lucent Technologies 1997 +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +****************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "awk.h" +#include "ytab.h" + +extern YYSTYPE yylval; +extern int infunc; + +int lineno = 1; +int bracecnt = 0; +int brackcnt = 0; +int parencnt = 0; + +typedef struct Keyword { + char *word; + int sub; + int type; +} Keyword; + +Keyword keywords[] ={ /* keep sorted: binary searched */ + { "BEGIN", XBEGIN, XBEGIN }, + { "END", XEND, XEND }, + { "NF", VARNF, VARNF }, + { "atan2", FATAN, BLTIN }, + { "break", BREAK, BREAK }, + { "close", CLOSE, CLOSE }, + { "continue", CONTINUE, CONTINUE }, + { "cos", FCOS, BLTIN }, + { "delete", DELETE, DELETE }, + { "do", DO, DO }, + { "else", ELSE, ELSE }, + { "exit", EXIT, EXIT }, + { "exp", FEXP, BLTIN }, + { "fflush", FFLUSH, BLTIN }, + { "for", FOR, FOR }, + { "func", FUNC, FUNC }, + { "function", FUNC, FUNC }, + { "getline", GETLINE, GETLINE }, + { "gsub", GSUB, GSUB }, + { "if", IF, IF }, + { "in", IN, IN }, + { "index", INDEX, INDEX }, + { "int", FINT, BLTIN }, + { "length", FLENGTH, BLTIN }, + { "log", FLOG, BLTIN }, + { "match", MATCHFCN, MATCHFCN }, + { "next", NEXT, NEXT }, + { "nextfile", NEXTFILE, NEXTFILE }, + { "print", PRINT, PRINT }, + { "printf", PRINTF, PRINTF }, + { "rand", FRAND, BLTIN }, + { "return", RETURN, RETURN }, + { "sin", FSIN, BLTIN }, + { "split", SPLIT, SPLIT }, + { "sprintf", SPRINTF, SPRINTF }, + { "sqrt", FSQRT, BLTIN }, + { "srand", FSRAND, BLTIN }, + { "sub", SUB, SUB }, + { "substr", SUBSTR, SUBSTR }, + { "system", FSYSTEM, BLTIN }, + { "tolower", FTOLOWER, BLTIN }, + { "toupper", FTOUPPER, BLTIN }, + { "while", WHILE, WHILE }, +}; + +#define DEBUG +#ifdef DEBUG +#define RET(x) { if(dbg)printf("lex %s\n", tokname(x)); return(x); } +#else +#define RET(x) return(x) +#endif + +int peek() +{ + int c = input(); + unput(c); + return c; +} + +int gettok(char **pbuf, int *psz) /* get next input token */ +{ + int c; + char *buf = *pbuf; + int sz = *psz; + char *bp = buf; + + c = input(); + if (c == 0) + return 0; + buf[0] = c; + buf[1] = 0; + if (!isalnum(c) && c != '.' && c != '_') + return c; + + *bp++ = c; + if (isalpha(c) || c == '_') { /* it's a varname */ + for ( ; (c = input()) != 0; ) { + if (bp-buf >= sz) + if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0)) + ERROR "out of space for name %.10s...", buf FATAL; + if (isalnum(c) || c == '_') + *bp++ = c; + else { + *bp = 0; + unput(c); + break; + } + } + } else { /* it's a number */ + char *rem; + /* read input until can't be a number */ + for ( ; (c = input()) != 0; ) { + if (bp-buf >= sz) + if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0)) + ERROR "out of space for number %.10s...", buf FATAL; + if (isdigit(c) || c == 'e' || c == 'E' + || c == '.' || c == '+' || c == '-') + *bp++ = c; + else { + *bp = 0; + unput(c); + break; + } + } + strtod(buf, &rem); /* parse the number */ + unputstr(rem); /* put rest back for later */ + rem[0] = 0; + } + *pbuf = buf; + *psz = sz; + return buf[0]; +} + +int word(char *); +int string(void); +int regexpr(void); +int sc = 0; /* 1 => return a } right now */ +int reg = 0; /* 1 => return a REGEXPR now */ + +int yylex() +{ + int c, n; + static char *buf = 0; + static int bufsize = 500; + + if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL) + ERROR "out of space in yylex" FATAL; + if (sc) { + sc = 0; + RET('}'); + } + if (reg) { + reg = 0; + return regexpr(); + } + for (;;) { + c = gettok(&buf, &bufsize); + if (c == 0) + return 0; + if (isalpha(c) || c == '_') + return word(buf); + if (isdigit(c) || c == '.') { + yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab); + /* should this also have STR set? */ + RET(NUMBER); + } + + yylval.i = c; + switch (c) { + case '\n': /* {EOL} */ + RET(NL); + case '\r': /* assume \n is coming */ + case ' ': /* {WS}+ */ + case '\t': + break; + case '#': /* #.* strip comments */ + while ((c = input()) != '\n' && c != 0) + ; + unput(c); + break; + case ';': + RET(';'); + case '\\': + if (peek() == '\n') { + input(); lineno++; + } else if (peek() == '\r') { + input(); input(); /* \n */ + lineno++; + } else { + RET(c); + } + break; + case '&': + if (peek() == '&') { + input(); RET(AND); + } else + RET('&'); + case '|': + if (peek() == '|') { + input(); RET(BOR); + } else + RET('|'); + case '!': + if (peek() == '=') { + input(); yylval.i = NE; RET(NE); + } else if (peek() == '~') { + input(); yylval.i = NOTMATCH; RET(MATCHOP); + } else + RET(NOT); + case '~': + yylval.i = MATCH; + RET(MATCHOP); + case '<': + if (peek() == '=') { + input(); yylval.i = LE; RET(LE); + } else { + yylval.i = LT; RET(LT); + } + case '=': + if (peek() == '=') { + input(); yylval.i = EQ; RET(EQ); + } else { + yylval.i = ASSIGN; RET(ASGNOP); + } + case '>': + if (peek() == '=') { + input(); yylval.i = GE; RET(GE); + } else if (peek() == '>') { + input(); yylval.i = APPEND; RET(APPEND); + } else { + yylval.i = GT; RET(GT); + } + case '+': + if (peek() == '+') { + input(); yylval.i = INCR; RET(INCR); + } else if (peek() == '=') { + input(); yylval.i = ADDEQ; RET(ASGNOP); + } else + RET('+'); + case '-': + if (peek() == '-') { + input(); yylval.i = DECR; RET(DECR); + } else if (peek() == '=') { + input(); yylval.i = SUBEQ; RET(ASGNOP); + } else + RET('-'); + case '*': + if (peek() == '=') { /* *= */ + input(); yylval.i = MULTEQ; RET(ASGNOP); + } else if (peek() == '*') { /* ** or **= */ + input(); /* eat 2nd * */ + if (peek() == '=') { + input(); yylval.i = POWEQ; RET(ASGNOP); + } else { + RET(POWER); + } + } else + RET('*'); + case '/': + if (peek() == '=') { + input(); yylval.i = DIVEQ; RET(ASGNOP); + } else + RET('/'); + case '%': + if (peek() == '=') { + input(); yylval.i = MODEQ; RET(ASGNOP); + } else + RET('%'); + case '^': + if (peek() == '=') { + input(); yylval.i = POWEQ; RET(ASGNOP); + } else + RET(POWER); + + case '$': + /* BUG: awkward, if not wrong */ + c = gettok(&buf, &bufsize); + if (c == '(' || c == '[' || (infunc && (n=isarg(buf)) >= 0)) { + unputstr(buf); + RET(INDIRECT); + } else if (isalpha(c)) { + if (strcmp(buf, "NF") == 0) { /* very special */ + unputstr("(NF)"); + RET(INDIRECT); + } + yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab); + RET(IVAR); + } else { + unputstr(buf); + RET(INDIRECT); + } + + case '}': + if (--bracecnt < 0) + ERROR "extra }" SYNTAX; + sc = 1; + RET(';'); + case ']': + if (--brackcnt < 0) + ERROR "extra ]" SYNTAX; + RET(']'); + case ')': + if (--parencnt < 0) + ERROR "extra )" SYNTAX; + RET(')'); + case '{': + bracecnt++; + RET('{'); + case '[': + brackcnt++; + RET('['); + case '(': + parencnt++; + RET('('); + + case '"': + return string(); /* BUG: should be like tran.c ? */ + + default: + RET(c); + } + } +} + +int string() +{ + int c, n; + char *s, *bp; + static char *buf = 0; + static int bufsz = 500; + + if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL) + ERROR "out of space for strings" FATAL; + for (bp = buf; (c = input()) != '"'; ) { + if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, 0)) + ERROR "out of space for string %.10s...", buf FATAL; + switch (c) { + case '\n': + case '\r': + case 0: + ERROR "non-terminated string %.10s...", buf SYNTAX; + lineno++; + break; + case '\\': + c = input(); + switch (c) { + case '"': *bp++ = '"'; break; + case 'n': *bp++ = '\n'; break; + case 't': *bp++ = '\t'; break; + case 'f': *bp++ = '\f'; break; + case 'r': *bp++ = '\r'; break; + case 'b': *bp++ = '\b'; break; + case 'v': *bp++ = '\v'; break; + case 'a': *bp++ = '\a'; break; + case '\\': *bp++ = '\\'; break; + + case '0': case '1': case '2': /* octal: \d \dd \ddd */ + case '3': case '4': case '5': case '6': case '7': + n = c - '0'; + if ((c = peek()) >= '0' && c < '8') { + n = 8 * n + input() - '0'; + if ((c = peek()) >= '0' && c < '8') + n = 8 * n + input() - '0'; + } + *bp++ = n; + break; + + case 'x': /* hex \x0-9a-fA-F + */ + { char xbuf[100], *px; + for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) { + if (isdigit(c) + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F')) + *px++ = c; + else + break; + } + *px = 0; + unput(c); + sscanf(xbuf, "%x", &n); + *bp++ = n; + break; + } + + default: + *bp++ = c; + break; + } + break; + default: + *bp++ = c; + break; + } + } + *bp = 0; + s = tostring(buf); + *bp++ = ' '; *bp++ = 0; + yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab); + RET(STRING); +} + + +int binsearch(char *w, Keyword *kp, int n) +{ + int cond, low, mid, high; + + low = 0; + high = n - 1; + while (low <= high) { + mid = (low + high) / 2; + if ((cond = strcmp(w, kp[mid].word)) < 0) + high = mid - 1; + else if (cond > 0) + low = mid + 1; + else + return mid; + } + return -1; +} + +int word(char *w) +{ + Keyword *kp; + int c, n; + + n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0])); + kp = keywords + n; + if (n != -1) { /* found in table */ + yylval.i = kp->sub; + switch (kp->type) { /* special handling */ + case FSYSTEM: + if (safe) + ERROR "system is unsafe" SYNTAX; + RET(kp->type); + case FUNC: + if (infunc) + ERROR "illegal nested function" SYNTAX; + RET(kp->type); + case RETURN: + if (!infunc) + ERROR "return not in function" SYNTAX; + RET(kp->type); + case VARNF: + yylval.cp = setsymtab("NF", "", 0.0, NUM, symtab); + RET(VARNF); + default: + RET(kp->type); + } + } + c = peek(); /* look for '(' */ + if (c != '(' && infunc && (n=isarg(w)) >= 0) { + yylval.i = n; + RET(ARG); + } else { + yylval.cp = setsymtab(w, "", 0.0, STR|NUM|DONTFREE, symtab); + if (c == '(') { + RET(CALL); + } else { + RET(VAR); + } + } +} + +void startreg(void) /* next call to yyles will return a regular expression */ +{ + reg = 1; +} + +int regexpr() +{ + int c; + static char *buf = 0; + static int bufsz = 500; + char *bp; + + if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL) + ERROR "out of space for rex expr" FATAL; + bp = buf; + for ( ; (c = input()) != '/' && c != 0; ) { + if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, 0)) + ERROR "out of space for reg expr %.10s...", buf FATAL; + if (c == '\n') { + ERROR "newline in regular expression %.10s...", buf SYNTAX; + unput('\n'); + break; + } else if (c == '\\') { + *bp++ = '\\'; + *bp++ = input(); + } else { + *bp++ = c; + } + } + *bp = 0; + yylval.s = tostring(buf); + unput('/'); + RET(REGEXPR); +} + +/* low-level lexical stuff, sort of inherited from lex */ + +char ebuf[300]; +char *ep = ebuf; +char yysbuf[100]; /* pushback buffer */ +char *yysptr = yysbuf; +FILE *yyin = 0; + +int input(void) /* get next lexical input character */ +{ + int c; + extern char *lexprog; + + if (yysptr > yysbuf) + c = *--yysptr; + else if (lexprog != NULL) { /* awk '...' */ + if ((c = *lexprog) != 0) + lexprog++; + } else /* awk -f ... */ + c = pgetc(); + if (c == '\n') + lineno++; + else if (c == EOF) + c = 0; + if (ep >= ebuf + sizeof ebuf) + ep = ebuf; + return *ep++ = c; +} + +void unput(int c) /* put lexical character back on input */ +{ + if (c == '\n') + lineno--; + if (yysptr >= yysbuf + sizeof(yysbuf)) + ERROR "pushed back too much: %.20s...", yysbuf FATAL; + *yysptr++ = c; + if (--ep < ebuf) + ep = ebuf + sizeof(ebuf) - 1; +} + +void unputstr(char *s) /* put a string back on input */ +{ + int i; + + for (i = strlen(s)-1; i >= 0; i--) + unput(s[i]); +} diff --git a/usr.bin/awk/lexyy.c b/usr.bin/awk/lexyy.c deleted file mode 100644 index e58761ae0f9..00000000000 --- a/usr.bin/awk/lexyy.c +++ /dev/null @@ -1,2031 +0,0 @@ -typedef unsigned char Uchar; -# include <stdio.h> -# define U(x) x -# define NLSTATE yyprevious=YYNEWLINE -# define BEGIN yybgin = yysvec + 1 + -# define INITIAL 0 -# define YYLERR yysvec -# define YYSTATE (yyestate-yysvec-1) -# define YYOPTIM 1 -# define YYLMAX 200 -# define output(c) putc(c,yyout) -# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) -# define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} -# define yymore() (yymorfg=1) -# define ECHO fprintf(yyout, "%s",yytext) -# define REJECT { nstr = yyreject(); goto yyfussy;} -int yyleng; extern char yytext[]; -int yymorfg; -extern Uchar *yysptr, yysbuf[]; -int yytchar; -FILE *yyin = {stdin}, *yyout = {stdout}; -extern int yylineno; -struct yysvf { - struct yywork *yystoff; - struct yysvf *yyother; - int *yystops;}; -struct yysvf *yyestate; -extern struct yysvf yysvec[], *yybgin; -int yylook(void), yywrap(void), yyback(int *, int); -#define A 2 -#define str 4 -#define sc 6 -#define reg 8 -#define comment 10 -/**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. -****************************************************************/ - -/* some of this depends on behavior of lex that - may not be preserved in other implementations of lex. -*/ - -#undef input /* defeat lex */ -#undef unput - -#include <stdlib.h> -#include <string.h> -#include "awk.h" -#include "awkgram.h" - -extern YYSTYPE yylval; -extern int infunc; - -int lineno = 1; -int bracecnt = 0; -int brackcnt = 0; -int parencnt = 0; - -#define DEBUG -#ifdef DEBUG -# define RET(x) {if(dbg)printf("lex %s [%s]\n", tokname(x), yytext); return(x); } -#else -# define RET(x) return(x) -#endif - -#define CADD if (cadd(gs, yytext[0]) == 0) { \ - ERROR "string/reg expr %.30s... too long", gs->cbuf SYNTAX; \ - BEGIN A; \ - } - -char *s; -Gstring *gs = 0; /* initialized in main() */ -int cflag; -#define YYNEWLINE 10 -yylex(void){ -int nstr; extern int yyprevious; -switch (yybgin-yysvec-1) { /* witchcraft */ - case 0: - BEGIN A; - break; - case sc: - BEGIN A; - RET('}'); - } -while((nstr = yylook()) >= 0) -yyfussy: switch(nstr){ -case 0: -if(yywrap()) return(0); break; -case 1: - { lineno++; RET(NL); } -break; -case 2: - { ; } -break; -case 3: -{ ; } -break; -case 4: - { RET(';'); } -break; -case 5: -{ lineno++; } -break; -case 6: -{ RET(XBEGIN); } -break; -case 7: - { RET(XEND); } -break; -case 8: -{ if (infunc) ERROR "illegal nested function" SYNTAX; RET(FUNC); } -break; -case 9: -{ if (!infunc) ERROR "return not in function" SYNTAX; RET(RETURN); } -break; -case 10: - { RET(AND); } -break; -case 11: - { RET(BOR); } -break; -case 12: - { RET(NOT); } -break; -case 13: - { yylval.i = NE; RET(NE); } -break; -case 14: - { yylval.i = MATCH; RET(MATCHOP); } -break; -case 15: - { yylval.i = NOTMATCH; RET(MATCHOP); } -break; -case 16: - { yylval.i = LT; RET(LT); } -break; -case 17: - { yylval.i = LE; RET(LE); } -break; -case 18: - { yylval.i = EQ; RET(EQ); } -break; -case 19: - { yylval.i = GE; RET(GE); } -break; -case 20: - { yylval.i = GT; RET(GT); } -break; -case 21: - { yylval.i = APPEND; RET(APPEND); } -break; -case 22: - { yylval.i = INCR; RET(INCR); } -break; -case 23: - { yylval.i = DECR; RET(DECR); } -break; -case 24: - { yylval.i = ADDEQ; RET(ASGNOP); } -break; -case 25: - { yylval.i = SUBEQ; RET(ASGNOP); } -break; -case 26: - { yylval.i = MULTEQ; RET(ASGNOP); } -break; -case 27: - { yylval.i = DIVEQ; RET(ASGNOP); } -break; -case 28: - { yylval.i = MODEQ; RET(ASGNOP); } -break; -case 29: - { yylval.i = POWEQ; RET(ASGNOP); } -break; -case 30: -{ yylval.i = POWEQ; RET(ASGNOP); } -break; -case 31: - { yylval.i = ASSIGN; RET(ASGNOP); } -break; -case 32: - { RET(POWER); } -break; -case 33: - { RET(POWER); } -break; -case 34: -{ yylval.cp = fieldadr(atoi(yytext+1)); RET(FIELD); } -break; -case 35: -{ unputstr("(NF)"); return(INDIRECT); } -break; -case 36: -{ int c, n; - c = input(); unput(c); - if (c == '(' || c == '[' || (infunc && (n=isarg(yytext+1)) >= 0)) { - unputstr(yytext+1); - return(INDIRECT); - } else { - yylval.cp = setsymtab(yytext+1, "", 0.0, STR|NUM, symtab); - RET(IVAR); - } - } -break; -case 37: - { RET(INDIRECT); } -break; -case 38: - { yylval.cp = setsymtab(yytext, "", 0.0, NUM, symtab); RET(VARNF); } -break; -case 39: -{ - yylval.cp = setsymtab(yytext, tostring(yytext), atof(yytext), CON|NUM, symtab); - /* should this also have STR set? */ - RET(NUMBER); } -break; -case 40: -{ RET(WHILE); } -break; -case 41: - { RET(FOR); } -break; -case 42: - { RET(DO); } -break; -case 43: - { RET(IF); } -break; -case 44: - { RET(ELSE); } -break; -case 45: - { RET(NEXT); } -break; -case 46: -{ RET(NEXTFILE); } -break; -case 47: - { RET(EXIT); } -break; -case 48: -{ RET(BREAK); } -break; -case 49: -{ RET(CONTINUE); } -break; -case 50: -{ yylval.i = PRINT; RET(PRINT); } -break; -case 51: -{ yylval.i = PRINTF; RET(PRINTF); } -break; -case 52: -{ yylval.i = SPRINTF; RET(SPRINTF); } -break; -case 53: -{ yylval.i = SPLIT; RET(SPLIT); } -break; -case 54: -{ RET(SUBSTR); } -break; -case 55: - { yylval.i = SUB; RET(SUB); } -break; -case 56: - { yylval.i = GSUB; RET(GSUB); } -break; -case 57: -{ RET(INDEX); } -break; -case 58: -{ RET(MATCHFCN); } -break; -case 59: - { RET(IN); } -break; -case 60: -{ RET(GETLINE); } -break; -case 61: -{ RET(CLOSE); } -break; -case 62: -{ RET(DELETE); } -break; -case 63: -{ yylval.i = FLENGTH; RET(BLTIN); } -break; -case 64: - { yylval.i = FLOG; RET(BLTIN); } -break; -case 65: - { yylval.i = FINT; RET(BLTIN); } -break; -case 66: - { yylval.i = FEXP; RET(BLTIN); } -break; -case 67: - { yylval.i = FSQRT; RET(BLTIN); } -break; -case 68: - { yylval.i = FSIN; RET(BLTIN); } -break; -case 69: - { yylval.i = FCOS; RET(BLTIN); } -break; -case 70: -{ yylval.i = FATAN; RET(BLTIN); } -break; -case 71: -{ yylval.i = FSYSTEM; RET(BLTIN); } -break; -case 72: - { yylval.i = FRAND; RET(BLTIN); } -break; -case 73: -{ yylval.i = FSRAND; RET(BLTIN); } -break; -case 74: -{ yylval.i = FTOUPPER; RET(BLTIN); } -break; -case 75: -{ yylval.i = FTOLOWER; RET(BLTIN); } -break; -case 76: -{ yylval.i = FFLUSH; RET(BLTIN); } -break; -case 77: -{ int n, c; - c = input(); unput(c); /* look for '(' */ - if (c != '(' && infunc && (n=isarg(yytext)) >= 0) { - yylval.i = n; - RET(ARG); - } else { - yylval.cp = setsymtab(yytext, "", 0.0, STR|NUM, symtab); - if (c == '(') { - RET(CALL); - } else { - RET(VAR); - } - } - } -break; -case 78: - { BEGIN str; caddreset(gs); } -break; -case 79: - { if (--bracecnt < 0) ERROR "extra }" SYNTAX; BEGIN sc; RET(';'); } -break; -case 80: - { if (--brackcnt < 0) ERROR "extra ]" SYNTAX; RET(']'); } -break; -case 81: - { if (--parencnt < 0) ERROR "extra )" SYNTAX; RET(')'); } -break; -case 82: - { if (yytext[0] == '{') bracecnt++; - else if (yytext[0] == '[') brackcnt++; - else if (yytext[0] == '(') parencnt++; - RET(yylval.i = yytext[0]); /* everything else */ } -break; -case 83: -{ cadd(gs, '\\'); cadd(gs, yytext[1]); } -break; -case 84: - { ERROR "newline in regular expression %.10s...", gs->cbuf SYNTAX; lineno++; BEGIN A; } -break; -case 85: -{ BEGIN A; - cadd(gs, 0); - yylval.s = tostring(gs->cbuf); - unput('/'); - RET(REGEXPR); } -break; -case 86: - { CADD; } -break; -case 87: - { BEGIN A; - cadd(gs, 0); s = tostring(gs->cbuf); - cunadd(gs); - cadd(gs, ' '); cadd(gs, 0); - yylval.cp = setsymtab(gs->cbuf, s, 0.0, CON|STR, symtab); - RET(STRING); } -break; -case 88: - { ERROR "newline in string %.10s...", gs->cbuf SYNTAX; lineno++; BEGIN A; } -break; -case 89: -{ cadd(gs, '"'); } -break; -case 90: -{ cadd(gs, '\n'); } -break; -case 91: -{ cadd(gs, '\t'); } -break; -case 92: -{ cadd(gs, '\f'); } -break; -case 93: -{ cadd(gs, '\r'); } -break; -case 94: -{ cadd(gs, '\b'); } -break; -case 95: -{ cadd(gs, '\v'); } -break; -case 96: -{ cadd(gs, '\007'); } -break; -case 97: -{ cadd(gs, '\\'); } -break; -case 98: -{ int n; - sscanf(yytext+1, "%o", &n); cadd(gs, n); } -break; -case 99: -{ int n; /* ANSI permits any number! */ - sscanf(yytext+2, "%x", &n); cadd(gs, n); } -break; -case 100: -{ cadd(gs, yytext[1]); } -break; -case 101: - { CADD; } -break; -case -1: -break; -default: -fprintf(yyout,"bad switch yylook %d",nstr); -} return(0); } -/* end of yylex */ - -void startreg(void) /* start parsing a regular expression */ -{ - BEGIN reg; - caddreset(gs); -} - -/* input() and unput() are transcriptions of the standard lex - macros for input and output with additions for error message - printing. God help us all if someone changes how lex works. -*/ - -char ebuf[300]; -char *ep = ebuf; - -int input(void) /* get next lexical input character */ -{ - int c; - extern char *lexprog; - - if (yysptr > yysbuf) - c = U(*--yysptr); - else if (lexprog != NULL) { /* awk '...' */ - if ((c = *lexprog) != 0) - lexprog++; - } else /* awk -f ... */ - c = pgetc(); - if (c == '\n') - yylineno++; - else if (c == EOF) - c = 0; - if (ep >= ebuf + sizeof ebuf) - ep = ebuf; - return *ep++ = c; -} - -void unput(int c) /* put lexical character back on input */ -{ - yytchar = c; - if (yytchar == '\n') - yylineno--; - *yysptr++ = yytchar; - if (--ep < ebuf) - ep = ebuf + sizeof(ebuf) - 1; -} - - -void unputstr(char *s) /* put a string back on input */ -{ - int i; - - for (i = strlen(s)-1; i >= 0; i--) - unput(s[i]); -} - -/* growing-string code */ - -const int CBUFLEN = 400; - -Gstring *newGstring() -{ - Gstring *gs = (Gstring *) malloc(sizeof(Gstring)); - char *cp = (char *) malloc(CBUFLEN); - - if (gs == 0 || cp == 0) - ERROR "Out of space for strings" FATAL; - gs->cbuf = cp; - gs->cmax = CBUFLEN; - gs->clen = 0; - return gs; -} - -char *cadd(Gstring *gs, int c) /* add one char to gs->cbuf, grow as needed */ -{ - if (gs->clen >= gs->cmax) { /* need to grow */ - gs->cmax *= 4; - gs->cbuf = (char *) realloc((void *) gs->cbuf, gs->cmax); - - } - if (gs->cbuf != 0) - gs->cbuf[gs->clen++] = c; - return gs->cbuf; -} - -void caddreset(Gstring *gs) -{ - gs->clen = 0; -} - -void cunadd(Gstring *gs) -{ - if (gs->clen > 0) - gs->clen--; -} - -void delGstring(Gstring *gs) -{ - free((void *) gs->cbuf); - free((void *) gs); -} -int yyvstop[] = { -0, - -82, -0, - -3, -82, -0, - -1, -0, - -12, -82, -0, - -78, -82, -0, - -2, -82, -0, - -37, -82, -0, - -82, -0, - -82, -0, - -81, -82, -0, - -82, -0, - -82, -0, - -82, -0, - -82, -0, - -82, -0, - -39, -82, -0, - -4, -82, -0, - -16, -82, -0, - -31, -82, -0, - -20, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -82, -0, - -80, -82, -0, - -33, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -77, -82, -0, - -82, -0, - -79, -82, -0, - -14, -82, -0, - -101, -0, - -88, -0, - -87, -101, -0, - -101, -0, - -86, -0, - -84, -0, - -85, -86, -0, - -86, -0, - -3, -0, - -13, -0, - -15, -0, - -2, -0, - -34, -0, - -36, -0, - -36, -0, - -28, -0, - -10, -0, - -32, -0, - -26, -0, - -22, -0, - -24, -0, - -23, -0, - -25, -0, - -39, -0, - -27, -0, - -39, -0, - -39, -0, - -17, -0, - -18, -0, - -19, -0, - -21, -0, - -77, -0, - -77, -0, - -77, -0, - -38, -77, -0, - -5, -0, - -29, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -42, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -43, -77, -0, - -59, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -11, -0, - -100, -0, - -89, -100, -0, - -98, -100, -0, - -97, -100, -0, - -96, -100, -0, - -94, -100, -0, - -92, -100, -0, - -90, -100, -0, - -93, -100, -0, - -91, -100, -0, - -95, -100, -0, - -100, -0, - -83, -0, - -35, -36, -0, - -30, -0, - -39, -0, - -77, -0, - -7, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -69, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -66, -77, -0, - -77, -0, - -41, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -65, -77, -0, - -77, -0, - -64, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -68, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -55, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -98, -0, - -99, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -44, -77, -0, - -47, -77, -0, - -77, -0, - -8, -77, -0, - -77, -0, - -56, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -45, -77, -0, - -77, -0, - -72, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -67, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -98, -0, - -6, -77, -0, - -70, -77, -0, - -48, -77, -0, - -61, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -57, -77, -0, - -77, -0, - -58, -77, -0, - -77, -0, - -50, -77, -0, - -77, -0, - -53, -77, -0, - -77, -0, - -73, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -40, -77, -0, - -77, -0, - -62, -77, -0, - -76, -77, -0, - -77, -0, - -77, -0, - -63, -77, -0, - -77, -0, - -51, -77, -0, - -9, -77, -0, - -77, -0, - -54, -77, -0, - -71, -77, -0, - -77, -0, - -77, -0, - -77, -0, - -77, -0, - -60, -77, -0, - -77, -0, - -52, -77, -0, - -75, -77, -0, - -74, -77, -0, - -49, -77, -0, - -8, -77, -0, - -46, -77, -0, -0}; -# define YYTYPE int -struct yywork { YYTYPE verify, advance; } yycrank[] = { -0,0, 0,0, 3,13, 0,0, -0,0, 0,0, 0,0, 0,0, -0,0, 0,0, 3,14, 3,15, -0,0, 0,0, 0,0, 0,0, -0,0, 14,67, 0,0, 0,0, -0,0, 5,59, 0,0, 0,0, -0,0, 0,0, 0,0, 0,0, -0,0, 5,59, 5,60, 0,0, -0,0, 0,0, 3,16, 3,17, -3,18, 3,19, 3,20, 3,21, -14,67, 37,95, 3,22, 3,23, -3,24, 70,0, 3,25, 3,26, -3,27, 3,28, 6,61, 0,0, -0,0, 0,0, 5,61, 0,0, -0,0, 3,28, 0,0, 0,0, -3,29, 3,30, 3,31, 3,32, -0,0, 21,75, 3,33, 3,34, -5,59, 10,65, 3,35, 23,76, -3,33, 0,0, 16,68, 0,0, -5,59, 0,0, 0,0, 3,36, -0,0, 0,0, 0,0, 0,0, -0,0, 5,59, 0,0, 24,78, -9,63, 20,74, 23,77, 5,59, -27,83, 3,37, 3,38, 3,39, -9,63, 9,64, 3,40, 3,41, -3,42, 3,43, 3,44, 3,45, -3,46, 24,79, 3,47, 25,80, -6,62, 3,48, 3,49, 3,50, -5,62, 3,51, 10,66, 3,52, -3,53, 3,54, 30,87, 31,88, -3,55, 32,89, 32,90, 25,81, -34,92, 3,56, 3,57, 3,58, -4,16, 4,17, 4,18, 4,19, -4,20, 4,21, 9,65, 9,63, -4,22, 4,23, 4,24, 16,69, -4,25, 4,26, 4,27, 9,63, -35,93, 36,94, 39,96, 40,97, -41,98, 43,101, 42,99, 44,103, -9,63, 42,100, 4,29, 4,30, -4,31, 4,32, 9,63, 43,102, -45,105, 4,34, 47,110, 44,104, -4,35, 49,114, 46,108, 50,115, -18,70, 45,106, 47,111, 48,112, -51,116, 4,36, 52,117, 45,107, -18,70, 18,0, 52,118, 9,66, -46,109, 48,113, 54,125, 55,126, -56,127, 76,142, 82,86, 4,37, -4,38, 4,39, 92,145, 93,146, -4,40, 4,41, 4,42, 4,43, -4,44, 4,45, 4,46, 97,147, -4,47, 98,148, 99,149, 4,48, -4,49, 4,50, 101,152, 4,51, -100,150, 4,52, 4,53, 4,54, -103,153, 100,151, 4,55, 18,70, -105,156, 53,119, 82,86, 4,56, -4,57, 4,58, 106,157, 18,70, -53,120, 53,121, 53,122, 104,154, -107,158, 53,123, 108,159, 109,160, -18,70, 53,124, 104,155, 111,161, -112,163, 113,164, 18,70, 19,71, -19,71, 19,71, 19,71, 19,71, -19,71, 19,71, 19,71, 19,71, -19,71, 114,165, 115,166, 111,162, -116,167, 117,168, 118,169, 119,170, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,73, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 121,173, 122,174, -123,175, 124,176, 19,72, 126,179, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 19,72, 19,72, -19,72, 19,72, 26,82, 26,82, -26,82, 26,82, 26,82, 26,82, -26,82, 26,82, 26,82, 26,82, -28,84, 145,182, 28,85, 28,85, -28,85, 28,85, 28,85, 28,85, -28,85, 28,85, 28,85, 28,85, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 120,171, 28,86, -147,183, 148,184, 149,185, 150,186, -120,172, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 28,86, -152,187, 153,188, 154,189, 33,91, -156,190, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 33,91, -33,91, 33,91, 33,91, 62,128, -158,191, 66,140, 159,192, 160,193, -161,194, 163,195, 165,196, 62,128, -62,0, 66,140, 66,0, 71,71, -71,71, 71,71, 71,71, 71,71, -71,71, 71,71, 71,71, 71,71, -71,71, 72,72, 72,72, 72,72, -72,72, 72,72, 72,72, 72,72, -72,72, 72,72, 72,72, 166,197, -62,129, 167,198, 168,199, 169,200, -73,72, 73,72, 73,72, 73,72, -73,72, 73,72, 73,72, 73,72, -73,72, 73,72, 62,130, 171,201, -66,140, 172,202, 125,177, 72,72, -173,203, 174,204, 62,128, 175,205, -66,140, 176,206, 73,141, 125,178, -177,207, 178,208, 179,209, 62,128, -182,211, 66,140, 73,72, 183,212, -184,213, 62,128, 185,214, 66,140, -84,84, 84,84, 84,84, 84,84, -84,84, 84,84, 84,84, 84,84, -84,84, 84,84, 130,180, 130,180, -130,180, 130,180, 130,180, 130,180, -130,180, 130,180, 62,131, 186,215, -187,216, 84,86, 190,217, 62,132, -62,133, 191,218, 192,219, 194,220, -62,134, 195,221, 196,222, 197,223, -198,224, 200,225, 201,226, 202,227, -62,135, 204,228, 205,229, 206,230, -62,136, 207,231, 62,137, 208,232, -62,138, 209,233, 62,139, 215,234, -216,235, 86,143, 217,236, 86,143, -218,237, 84,86, 86,144, 86,144, -86,144, 86,144, 86,144, 86,144, -86,144, 86,144, 86,144, 86,144, -139,181, 139,181, 139,181, 139,181, -139,181, 139,181, 139,181, 139,181, -139,181, 139,181, 219,238, 221,239, -223,240, 224,241, 225,242, 227,243, -229,244, 139,181, 139,181, 139,181, -139,181, 139,181, 139,181, 230,245, -231,246, 141,72, 141,72, 141,72, -141,72, 141,72, 141,72, 141,72, -141,72, 141,72, 141,72, 143,144, -143,144, 143,144, 143,144, 143,144, -143,144, 143,144, 143,144, 143,144, -143,144, 232,247, 234,248, 237,249, -238,250, 139,181, 139,181, 139,181, -139,181, 139,181, 139,181, 141,72, -180,210, 180,210, 180,210, 180,210, -180,210, 180,210, 180,210, 180,210, -240,251, 243,252, 246,253, 247,254, -248,255, 249,256, 251,257, 0,0, -0,0}; -struct yysvf yysvec[] = { -0, 0, 0, -yycrank+0, 0, 0, -yycrank+0, 0, 0, -yycrank+-1, 0, 0, -yycrank+-95, yysvec+3, 0, -yycrank+-20, 0, 0, -yycrank+-16, yysvec+5, 0, -yycrank+0, 0, 0, -yycrank+0, 0, 0, -yycrank+-87, 0, 0, -yycrank+-22, yysvec+9, 0, -yycrank+0, 0, 0, -yycrank+0, 0, 0, -yycrank+0, 0, yyvstop+1, -yycrank+8, 0, yyvstop+3, -yycrank+0, 0, yyvstop+6, -yycrank+13, 0, yyvstop+8, -yycrank+0, 0, yyvstop+11, -yycrank+-167, 0, yyvstop+14, -yycrank+191, 0, yyvstop+17, -yycrank+28, 0, yyvstop+20, -yycrank+27, 0, yyvstop+22, -yycrank+0, 0, yyvstop+24, -yycrank+29, 0, yyvstop+27, -yycrank+44, 0, yyvstop+29, -yycrank+62, 0, yyvstop+31, -yycrank+266, 0, yyvstop+33, -yycrank+31, 0, yyvstop+35, -yycrank+278, 0, yyvstop+37, -yycrank+0, 0, yyvstop+40, -yycrank+57, 0, yyvstop+43, -yycrank+58, 0, yyvstop+46, -yycrank+60, 0, yyvstop+49, -yycrank+288, 0, yyvstop+52, -yycrank+55, yysvec+33, yyvstop+55, -yycrank+66, yysvec+33, yyvstop+58, -yycrank+75, yysvec+33, yyvstop+61, -yycrank+31, 0, yyvstop+64, -yycrank+0, 0, yyvstop+66, -yycrank+85, 0, yyvstop+69, -yycrank+31, yysvec+33, yyvstop+72, -yycrank+34, yysvec+33, yyvstop+75, -yycrank+42, yysvec+33, yyvstop+78, -yycrank+48, yysvec+33, yyvstop+81, -yycrank+43, yysvec+33, yyvstop+84, -yycrank+58, yysvec+33, yyvstop+87, -yycrank+65, yysvec+33, yyvstop+90, -yycrank+60, yysvec+33, yyvstop+93, -yycrank+70, yysvec+33, yyvstop+96, -yycrank+68, yysvec+33, yyvstop+99, -yycrank+66, yysvec+33, yyvstop+102, -yycrank+58, yysvec+33, yyvstop+105, -yycrank+77, yysvec+33, yyvstop+108, -yycrank+112, yysvec+33, yyvstop+111, -yycrank+71, yysvec+33, yyvstop+114, -yycrank+79, yysvec+33, yyvstop+117, -yycrank+60, 0, yyvstop+120, -yycrank+0, 0, yyvstop+122, -yycrank+0, 0, yyvstop+125, -yycrank+0, 0, yyvstop+128, -yycrank+0, 0, yyvstop+130, -yycrank+0, 0, yyvstop+132, -yycrank+-410, 0, yyvstop+135, -yycrank+0, 0, yyvstop+137, -yycrank+0, 0, yyvstop+139, -yycrank+0, 0, yyvstop+141, -yycrank+-412, 0, yyvstop+144, -yycrank+0, yysvec+14, yyvstop+146, -yycrank+0, 0, yyvstop+148, -yycrank+0, 0, yyvstop+150, -yycrank+-35, yysvec+18, yyvstop+152, -yycrank+375, 0, yyvstop+154, -yycrank+385, yysvec+19, yyvstop+156, -yycrank+400, yysvec+19, yyvstop+158, -yycrank+0, 0, yyvstop+160, -yycrank+0, 0, yyvstop+162, -yycrank+124, 0, yyvstop+164, -yycrank+0, 0, yyvstop+166, -yycrank+0, 0, yyvstop+168, -yycrank+0, 0, yyvstop+170, -yycrank+0, 0, yyvstop+172, -yycrank+0, 0, yyvstop+174, -yycrank+117, yysvec+26, yyvstop+176, -yycrank+0, 0, yyvstop+178, -yycrank+436, 0, yyvstop+180, -yycrank+0, yysvec+28, yyvstop+182, -yycrank+490, 0, 0, -yycrank+0, 0, yyvstop+184, -yycrank+0, 0, yyvstop+186, -yycrank+0, 0, yyvstop+188, -yycrank+0, 0, yyvstop+190, -yycrank+0, yysvec+33, yyvstop+192, -yycrank+119, yysvec+33, yyvstop+194, -yycrank+123, yysvec+33, yyvstop+196, -yycrank+0, yysvec+33, yyvstop+198, -yycrank+0, 0, yyvstop+201, -yycrank+0, 0, yyvstop+203, -yycrank+102, yysvec+33, yyvstop+205, -yycrank+100, yysvec+33, yyvstop+207, -yycrank+91, yysvec+33, yyvstop+209, -yycrank+98, yysvec+33, yyvstop+211, -yycrank+98, yysvec+33, yyvstop+213, -yycrank+0, yysvec+33, yyvstop+215, -yycrank+97, yysvec+33, yyvstop+218, -yycrank+122, yysvec+33, yyvstop+220, -yycrank+108, yysvec+33, yyvstop+222, -yycrank+108, yysvec+33, yyvstop+224, -yycrank+118, yysvec+33, yyvstop+226, -yycrank+114, yysvec+33, yyvstop+228, -yycrank+114, yysvec+33, yyvstop+230, -yycrank+0, yysvec+33, yyvstop+232, -yycrank+135, yysvec+33, yyvstop+235, -yycrank+126, yysvec+33, yyvstop+238, -yycrank+134, yysvec+33, yyvstop+240, -yycrank+133, yysvec+33, yyvstop+242, -yycrank+130, yysvec+33, yyvstop+244, -yycrank+147, yysvec+33, yyvstop+246, -yycrank+143, yysvec+33, yyvstop+248, -yycrank+138, yysvec+33, yyvstop+250, -yycrank+145, yysvec+33, yyvstop+252, -yycrank+238, yysvec+33, yyvstop+254, -yycrank+168, yysvec+33, yyvstop+256, -yycrank+186, yysvec+33, yyvstop+258, -yycrank+186, yysvec+33, yyvstop+260, -yycrank+170, yysvec+33, yyvstop+262, -yycrank+354, yysvec+33, yyvstop+264, -yycrank+182, yysvec+33, yyvstop+266, -yycrank+0, 0, yyvstop+268, -yycrank+0, 0, yyvstop+270, -yycrank+0, 0, yyvstop+272, -yycrank+446, 0, yyvstop+275, -yycrank+0, 0, yyvstop+278, -yycrank+0, 0, yyvstop+281, -yycrank+0, 0, yyvstop+284, -yycrank+0, 0, yyvstop+287, -yycrank+0, 0, yyvstop+290, -yycrank+0, 0, yyvstop+293, -yycrank+0, 0, yyvstop+296, -yycrank+0, 0, yyvstop+299, -yycrank+500, 0, yyvstop+302, -yycrank+0, 0, yyvstop+304, -yycrank+525, yysvec+19, yyvstop+306, -yycrank+0, 0, yyvstop+309, -yycrank+535, 0, 0, -yycrank+0, yysvec+143, yyvstop+311, -yycrank+252, yysvec+33, yyvstop+313, -yycrank+0, yysvec+33, yyvstop+315, -yycrank+238, yysvec+33, yyvstop+318, -yycrank+252, yysvec+33, yyvstop+320, -yycrank+235, yysvec+33, yyvstop+322, -yycrank+235, yysvec+33, yyvstop+324, -yycrank+0, yysvec+33, yyvstop+326, -yycrank+279, yysvec+33, yyvstop+329, -yycrank+280, yysvec+33, yyvstop+331, -yycrank+266, yysvec+33, yyvstop+333, -yycrank+0, yysvec+33, yyvstop+335, -yycrank+267, yysvec+33, yyvstop+338, -yycrank+0, yysvec+33, yyvstop+340, -yycrank+313, yysvec+33, yyvstop+343, -yycrank+306, yysvec+33, yyvstop+345, -yycrank+317, yysvec+33, yyvstop+347, -yycrank+315, yysvec+33, yyvstop+349, -yycrank+0, yysvec+33, yyvstop+351, -yycrank+314, yysvec+33, yyvstop+354, -yycrank+0, yysvec+33, yyvstop+356, -yycrank+319, yysvec+33, yyvstop+359, -yycrank+327, yysvec+33, yyvstop+361, -yycrank+335, yysvec+33, yyvstop+363, -yycrank+346, yysvec+33, yyvstop+365, -yycrank+330, yysvec+33, yyvstop+367, -yycrank+0, yysvec+33, yyvstop+369, -yycrank+354, yysvec+33, yyvstop+372, -yycrank+356, yysvec+33, yyvstop+374, -yycrank+348, yysvec+33, yyvstop+376, -yycrank+355, yysvec+33, yyvstop+378, -yycrank+352, yysvec+33, yyvstop+380, -yycrank+353, yysvec+33, yyvstop+383, -yycrank+361, yysvec+33, yyvstop+385, -yycrank+361, yysvec+33, yyvstop+387, -yycrank+366, yysvec+33, yyvstop+389, -yycrank+556, 0, yyvstop+391, -yycrank+0, yysvec+139, yyvstop+393, -yycrank+398, yysvec+33, yyvstop+395, -yycrank+429, yysvec+33, yyvstop+397, -yycrank+373, yysvec+33, yyvstop+399, -yycrank+381, yysvec+33, yyvstop+401, -yycrank+398, yysvec+33, yyvstop+403, -yycrank+388, yysvec+33, yyvstop+405, -yycrank+0, yysvec+33, yyvstop+407, -yycrank+0, yysvec+33, yyvstop+410, -yycrank+391, yysvec+33, yyvstop+413, -yycrank+393, yysvec+33, yyvstop+415, -yycrank+405, yysvec+33, yyvstop+418, -yycrank+0, yysvec+33, yyvstop+420, -yycrank+391, yysvec+33, yyvstop+423, -yycrank+397, yysvec+33, yyvstop+425, -yycrank+410, yysvec+33, yyvstop+427, -yycrank+413, yysvec+33, yyvstop+429, -yycrank+400, yysvec+33, yyvstop+432, -yycrank+0, yysvec+33, yyvstop+434, -yycrank+403, yysvec+33, yyvstop+437, -yycrank+402, yysvec+33, yyvstop+439, -yycrank+409, yysvec+33, yyvstop+441, -yycrank+0, yysvec+33, yyvstop+443, -yycrank+421, yysvec+33, yyvstop+446, -yycrank+406, yysvec+33, yyvstop+448, -yycrank+422, yysvec+33, yyvstop+450, -yycrank+406, yysvec+33, yyvstop+452, -yycrank+415, yysvec+33, yyvstop+454, -yycrank+428, yysvec+33, yyvstop+456, -yycrank+0, 0, yyvstop+458, -yycrank+0, yysvec+33, yyvstop+460, -yycrank+0, yysvec+33, yyvstop+463, -yycrank+0, yysvec+33, yyvstop+466, -yycrank+0, yysvec+33, yyvstop+469, -yycrank+421, yysvec+33, yyvstop+472, -yycrank+431, yysvec+33, yyvstop+474, -yycrank+430, yysvec+33, yyvstop+476, -yycrank+431, yysvec+33, yyvstop+478, -yycrank+448, yysvec+33, yyvstop+480, -yycrank+0, yysvec+33, yyvstop+482, -yycrank+455, yysvec+33, yyvstop+485, -yycrank+0, yysvec+33, yyvstop+487, -yycrank+455, yysvec+33, yyvstop+490, -yycrank+459, yysvec+33, yyvstop+492, -yycrank+452, yysvec+33, yyvstop+495, -yycrank+0, yysvec+33, yyvstop+497, -yycrank+447, yysvec+33, yyvstop+500, -yycrank+0, yysvec+33, yyvstop+502, -yycrank+450, yysvec+33, yyvstop+505, -yycrank+462, yysvec+33, yyvstop+507, -yycrank+471, yysvec+33, yyvstop+509, -yycrank+492, yysvec+33, yyvstop+511, -yycrank+0, yysvec+33, yyvstop+513, -yycrank+477, yysvec+33, yyvstop+516, -yycrank+0, yysvec+33, yyvstop+518, -yycrank+0, yysvec+33, yyvstop+521, -yycrank+484, yysvec+33, yyvstop+524, -yycrank+495, yysvec+33, yyvstop+526, -yycrank+0, yysvec+33, yyvstop+528, -yycrank+504, yysvec+33, yyvstop+531, -yycrank+0, yysvec+33, yyvstop+533, -yycrank+0, yysvec+33, yyvstop+536, -yycrank+511, yysvec+33, yyvstop+539, -yycrank+0, yysvec+33, yyvstop+541, -yycrank+0, yysvec+33, yyvstop+544, -yycrank+500, yysvec+33, yyvstop+547, -yycrank+501, yysvec+33, yyvstop+549, -yycrank+515, yysvec+33, yyvstop+551, -yycrank+507, yysvec+33, yyvstop+553, -yycrank+0, yysvec+33, yyvstop+555, -yycrank+517, yysvec+33, yyvstop+558, -yycrank+0, yysvec+33, yyvstop+560, -yycrank+0, yysvec+33, yyvstop+563, -yycrank+0, yysvec+33, yyvstop+566, -yycrank+0, yysvec+33, yyvstop+569, -yycrank+0, yysvec+33, yyvstop+572, -yycrank+0, yysvec+33, yyvstop+575, -0, 0, 0}; -struct yywork *yytop = yycrank+618; -struct yysvf *yybgin = yysvec+1; -Uchar yymatch[] = { -00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -011 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , -'8' ,'8' ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'G' , -'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' , -'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' , -'G' ,'G' ,'G' ,01 ,01 ,01 ,01 ,'G' , -01 ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'G' , -'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' , -'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' , -'G' ,'G' ,'G' ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , -0}; -Uchar yyextra[] = { -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0}; -int yylineno =1; -# define YYU(x) x -char yytext[YYLMAX]; -struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; -Uchar yysbuf[YYLMAX]; -Uchar *yysptr = yysbuf; -int *yyfnd; -extern struct yysvf *yyestate; -int yyprevious = YYNEWLINE; -# ifdef LEXDEBUG -extern void allprint(char); -# endif -yylook(void){ - struct yysvf *yystate, **lsp; - struct yywork *yyt; - struct yysvf *yyz; - int yych; - struct yywork *yyr; -# ifdef LEXDEBUG - int debug; -# endif - Uchar *yylastch; - /* start off machines */ -# ifdef LEXDEBUG - debug = 0; -# endif - if (!yymorfg) - yylastch = (Uchar*)yytext; - else { - yymorfg=0; - yylastch = (Uchar*)yytext+yyleng; - } - for(;;){ - lsp = yylstate; - yyestate = yystate = yybgin; - if (yyprevious==YYNEWLINE) yystate++; - for (;;){ -# ifdef LEXDEBUG - if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); -# endif - yyt = yystate->yystoff; - if(yyt == yycrank){ /* may not be any transitions */ - yyz = yystate->yyother; - if(yyz == 0)break; - if(yyz->yystoff == yycrank)break; - } - *yylastch++ = yych = input(); - tryagain: -# ifdef LEXDEBUG - if(debug){ - fprintf(yyout,"char "); - allprint(yych); - putchar('\n'); - } -# endif - yyr = yyt; - if ( (int)yyt > (int)yycrank){ - yyt = yyr + yych; - if (yyt <= yytop && yyt->verify+yysvec == yystate){ - if(yyt->advance+yysvec == YYLERR) /* error transitions */ - {unput(*--yylastch);break;} - *lsp++ = yystate = yyt->advance+yysvec; - goto contin; - } - } -# ifdef YYOPTIM - else if((int)yyt < (int)yycrank) { /* r < yycrank */ - yyt = yyr = yycrank+(yycrank-yyt); -# ifdef LEXDEBUG - if(debug)fprintf(yyout,"compressed state\n"); -# endif - yyt = yyt + yych; - if(yyt <= yytop && yyt->verify+yysvec == yystate){ - if(yyt->advance+yysvec == YYLERR) /* error transitions */ - {unput(*--yylastch);break;} - *lsp++ = yystate = yyt->advance+yysvec; - goto contin; - } - yyt = yyr + YYU(yymatch[yych]); -# ifdef LEXDEBUG - if(debug){ - fprintf(yyout,"try fall back character "); - allprint(YYU(yymatch[yych])); - putchar('\n'); - } -# endif - if(yyt <= yytop && yyt->verify+yysvec == yystate){ - if(yyt->advance+yysvec == YYLERR) /* error transition */ - {unput(*--yylastch);break;} - *lsp++ = yystate = yyt->advance+yysvec; - goto contin; - } - } - if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ -# ifdef LEXDEBUG - if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); -# endif - goto tryagain; - } -# endif - else - {unput(*--yylastch);break;} - contin: -# ifdef LEXDEBUG - if(debug){ - fprintf(yyout,"state %d char ",yystate-yysvec-1); - allprint(yych); - putchar('\n'); - } -# endif - ; - } -# ifdef LEXDEBUG - if(debug){ - fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); - allprint(yych); - putchar('\n'); - } -# endif - while (lsp-- > yylstate){ - *yylastch-- = 0; - if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ - yyolsp = lsp; - if(yyextra[*yyfnd]){ /* must backup */ - while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ - lsp--; - unput(*yylastch--); - } - } - yyprevious = YYU(*yylastch); - yylsp = lsp; - yyleng = yylastch-(Uchar*)yytext+1; - yytext[yyleng] = 0; -# ifdef LEXDEBUG - if(debug){ - fprintf(yyout,"\nmatch '%s'", yytext); - fprintf(yyout," action %d\n",*yyfnd); - } -# endif - return(*yyfnd++); - } - unput(*yylastch); - } - if (yytext[0] == 0 /* && feof(yyin) */) - { - yysptr=yysbuf; - return(0); - } - yyprevious = input(); - yytext[0] = yyprevious; - if (yyprevious>0) - output(yyprevious); - yylastch = (Uchar*)yytext; -# ifdef LEXDEBUG - if(debug)putchar('\n'); -# endif - } - return(0); /* shut up the compiler; i have no idea what should be returned */ - } -yyback(int *p, int m) -{ -if (p==0) return(0); -while (*p) - { - if (*p++ == m) - return(1); - } -return(0); -} - /* the following are only used in the lex library */ -yyinput(void){ - return(input()); -} -void -yyoutput(int c) -{ - output(c); -} -void -yyunput(int c) -{ - unput(c); -} diff --git a/usr.bin/awk/lib.c b/usr.bin/awk/lib.c index 13384ef8d86..6d32b05ff07 100644 --- a/usr.bin/awk/lib.c +++ b/usr.bin/awk/lib.c @@ -1,5 +1,6 @@ +/* $OpenBSD: lib.c,v 1.4 1997/08/25 16:17:11 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ #define DEBUG @@ -29,44 +30,59 @@ USE OR PERFORMANCE OF THIS SOFTWARE. #include <errno.h> #include <stdlib.h> #include "awk.h" -#include "awkgram.h" +#include "ytab.h" FILE *infile = NULL; char *file = ""; -int recsize = RECSIZE; -char *recdata; char *record; +int recsize = RECSIZE; char *fields; -Cell *fldtab; -char inputFS[100]; /* BUG: unchecked */ +int fieldssize = RECSIZE; + +Cell **fldtab; /* pointers to Cells */ +char inputFS[100]; #define MAXFLD 200 -int nfields = MAXFLD; /* can be set from commandline in main */ +int nfields = MAXFLD; /* last allocated slot for $i */ int donefld; /* 1 = implies rec broken into fields */ int donerec; /* 1 = record is valid (no flds have changed) */ -int maxfld = 0; /* last used field */ +int lastfld = 0; /* last used field */ int argno = 1; /* current input argument number */ extern Awkfloat *ARGC; +static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE }; +static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; + void recinit(unsigned int n) { - static Cell dollar0 = { - OCELL, CFLD, "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE }; - static Cell dollar1 = { - OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; - int i; - - record = recdata = (char *) malloc(n); + record = (char *) malloc(n); fields = (char *) malloc(n); - fldtab = (Cell *) malloc(nfields * sizeof(Cell)); - if (recdata == NULL || fields == NULL || fldtab == NULL) + fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *)); + if (record == NULL || fields == NULL || fldtab == NULL) ERROR "out of space for $0 and fields" FATAL; - fldtab[0] = dollar0; - fldtab[0].sval = recdata; - for (i = 1; i < nfields; i++) - fldtab[i] = dollar1; + + fldtab[0] = (Cell *) malloc(sizeof (Cell)); + *fldtab[0] = dollar0; + fldtab[0]->sval = record; + fldtab[0]->nval = tostring("0"); + makefields(1, nfields); +} + +void makefields(int n1, int n2) /* create $n1..$n2 inclusive */ +{ + char temp[50]; + int i; + + for (i = n1; i <= n2; i++) { + fldtab[i] = (Cell *) malloc(sizeof (struct Cell)); + if (fldtab[i] == NULL) + ERROR "out of space in makefields %d", i FATAL; + *fldtab[i] = dollar1; + sprintf(temp, "%d", i); + fldtab[i]->nval = tostring(temp); + } } void initgetrec(void) @@ -85,22 +101,24 @@ void initgetrec(void) infile = stdin; /* no filenames, so use stdin */ } -int getrec(char *buf) /* get next input record from whatever source */ -{ /* note: tests whether buf == record */ +int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */ +{ /* note: cares whether buf == record */ int c; static int firsttime = 1; + char *buf = *pbuf; + int bufsize = *pbufsize; if (firsttime) { firsttime = 0; initgetrec(); } - dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", + dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", *RS, *FS, *ARGC, *FILENAME) ); donefld = 0; donerec = 1; buf[0] = 0; while (argno < *ARGC || infile == stdin) { - dprintf( ("argno=%d, file=|%s|\n", argno, file) ); + dprintf( ("argno=%d, file=|%s|\n", argno, file) ); if (infile == NULL) { /* have to open a new file */ file = getargv(argno); if (*file == '\0') { /* it's been zapped */ @@ -113,27 +131,29 @@ int getrec(char *buf) /* get next input record from whatever source */ continue; } *FILENAME = file; - dprintf( ("opening file %s\n", file) ); + dprintf( ("opening file %s\n", file) ); if (*file == '-' && *(file+1) == '\0') infile = stdin; - else if ((infile = fopen((char *)file, "r")) == NULL) + else if ((infile = fopen(file, "r")) == NULL) ERROR "can't open file %s", file FATAL; setfval(fnrloc, 0.0); } - c = readrec(buf, recsize, infile); + c = readrec(&buf, &bufsize, infile); if (c != 0 || buf[0] != '\0') { /* normal record */ - if (buf == record) { - if (!(recloc->tval & DONTFREE)) - xfree(recloc->sval); - recloc->sval = record; - recloc->tval = REC | STR | DONTFREE; - if (isnumber(recloc->sval)) { - recloc->fval = atof(recloc->sval); - recloc->tval |= NUM; + if (isrecord) { + if (freeable(fldtab[0])) + xfree(fldtab[0]->sval); + fldtab[0]->sval = buf; /* buf == record */ + fldtab[0]->tval = REC | STR | DONTFREE; + if (isnumber(fldtab[0]->sval)) { + fldtab[0]->fval = atof(fldtab[0]->sval); + fldtab[0]->tval |= NUM; } } setfval(nrloc, nrloc->fval+1); setfval(fnrloc, fnrloc->fval+1); + *pbuf = buf; + *pbufsize = bufsize; return 1; } /* EOF arrived on this file; set up next */ @@ -142,6 +162,8 @@ int getrec(char *buf) /* get next input record from whatever source */ infile = NULL; argno++; } + *pbuf = buf; + *pbufsize = bufsize; return 0; /* true end of file */ } @@ -153,12 +175,14 @@ void nextfile(void) argno++; } -int readrec(char *buf, int bufsize, FILE *inf) /* read one record into buf */ +int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */ { int sep, c; - char *rr; - int nrr; + char *rr, *buf = *pbuf; + int bufsize = *pbufsize; + if (strlen(*FS) >= sizeof(inputFS)) + ERROR "field separator %.10s... is too long", *FS FATAL; strcpy(inputFS, *FS); /* for subsequent field splitting */ if ((sep = **RS) == 0) { sep = '\n'; @@ -167,34 +191,41 @@ int readrec(char *buf, int bufsize, FILE *inf) /* read one record into buf */ if (c != EOF) ungetc(c, inf); } - for (rr = buf, nrr = bufsize; ; ) { - for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c) - if (--nrr < 0) - ERROR "input record `%.30s...' too long; try -mr n", buf FATAL; + for (rr = buf; ; ) { + for (; (c=getc(inf)) != sep && c != EOF; ) { + if (rr-buf+1 > bufsize) + if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1")) + ERROR "input record `%.30s...' too long", buf FATAL; + *rr++ = c; + } if (**RS == sep || c == EOF) break; if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ break; + if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2")) + ERROR "input record `%.30s...' too long", buf FATAL; *rr++ = '\n'; *rr++ = c; } - if (rr > buf + bufsize) - ERROR "input record `%.30s...' too long; try -mr n", buf FATAL; + if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3")) + ERROR "input record `%.30s...' too long", buf FATAL; *rr = 0; - dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) ); + dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) ); + *pbuf = buf; + *pbufsize = bufsize; return c == EOF && rr == buf ? 0 : 1; } char *getargv(int n) /* get ARGV[n] */ { Cell *x; - char *s, temp[10]; + char *s, temp[50]; extern Array *ARGVtab; sprintf(temp, "%d", n); x = setsymtab(temp, "", 0.0, STR, ARGVtab); s = getsval(x); - dprintf( ("getargv(%d) returns |%s|\n", n, s) ); + dprintf( ("getargv(%d) returns |%s|\n", n, s) ); return s; } @@ -213,21 +244,30 @@ void setclvar(char *s) /* set var=value from s */ q->fval = atof(q->sval); q->tval |= NUM; } - dprintf( ("command line set %s to |%s|\n", s, p) ); + dprintf( ("command line set %s to |%s|\n", s, p) ); } void fldbld(void) /* create fields from current record */ { + /* this relies on having fields[] the same length as $0 */ + /* the fields are all stored in this one array with \0's */ char *r, *fr, sep; Cell *p; - int i; + int i, j, n; if (donefld) return; - if (!(recloc->tval & STR)) - getsval(recloc); - r = recloc->sval; + if (!isstr(fldtab[0])) + getsval(fldtab[0]); + r = fldtab[0]->sval; + n = strlen(r); + if (n > fieldssize) { + xfree(fields); + if ((fields = (char *) malloc(n+1)) == NULL) + ERROR "out of space for fields in fldbld %d", n FATAL; + fieldssize = n; + } fr = fields; i = 0; /* number of fields accumulated here */ if (strlen(inputFS) > 1) { /* it's a regular expression */ @@ -239,12 +279,12 @@ void fldbld(void) /* create fields from current record */ if (*r == 0) break; i++; - if (i >= nfields) - break; - if (!(fldtab[i].tval & DONTFREE)) - xfree(fldtab[i].sval); - fldtab[i].sval = fr; - fldtab[i].tval = FLD | STR | DONTFREE; + if (i > nfields) + growfldtab(i); + if (freeable(fldtab[i])) + xfree(fldtab[i]->sval); + fldtab[i]->sval = fr; + fldtab[i]->tval = FLD | STR | DONTFREE; do *fr++ = *r++; while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); @@ -255,25 +295,25 @@ void fldbld(void) /* create fields from current record */ for (i = 0; *r != 0; r++) { char buf[2]; i++; - if (i >= nfields) - break; - if (!(fldtab[i].tval & DONTFREE)) - xfree(fldtab[i].sval); + if (i > nfields) + growfldtab(i); + if (freeable(fldtab[i])) + xfree(fldtab[i]->sval); buf[0] = *r; buf[1] = 0; - fldtab[i].sval = tostring(buf); - fldtab[i].tval = FLD | STR; + fldtab[i]->sval = tostring(buf); + fldtab[i]->tval = FLD | STR; } *fr = 0; } else if (*r != 0) { /* if 0, it's a null field */ for (;;) { i++; - if (i >= nfields) - break; - if (!(fldtab[i].tval & DONTFREE)) - xfree(fldtab[i].sval); - fldtab[i].sval = fr; - fldtab[i].tval = FLD | STR | DONTFREE; + if (i > nfields) + growfldtab(i); + if (freeable(fldtab[i])) + xfree(fldtab[i]->sval); + fldtab[i]->sval = fr; + fldtab[i]->tval = FLD | STR | DONTFREE; while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */ *fr++ = *r++; *fr++ = 0; @@ -282,74 +322,111 @@ void fldbld(void) /* create fields from current record */ } *fr = 0; } - if (i >= nfields) - ERROR "record `%.30s...' has too many fields; try -mf n", record FATAL; - /* clean out junk from previous record */ - cleanfld(i, maxfld); - maxfld = i; + if (i > nfields) + ERROR "record `%.30s...' has too many fields; can't happen", r FATAL; + cleanfld(i+1, lastfld); /* clean out junk from previous record */ + lastfld = i; donefld = 1; - for (p = fldtab+1; p <= fldtab+maxfld; p++) { + for (j = 1; j <= lastfld; j++) { + p = fldtab[j]; if(isnumber(p->sval)) { p->fval = atof(p->sval); p->tval |= NUM; } } - setfval(nfloc, (Awkfloat) maxfld); - if (dbg) - for (p = fldtab; p <= fldtab+maxfld; p++) - printf("field %d: |%s|\n", p-fldtab, p->sval); + setfval(nfloc, (Awkfloat) lastfld); + if (dbg) { + for (j = 0; j <= lastfld; j++) { + p = fldtab[j]; + printf("field %d (%s): |%s|\n", j, p->nval, p->sval); + } + } } -void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */ -{ - static char *nullstat = ""; - Cell *p, *q; +void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */ +{ /* nvals remain intact */ + Cell *p; + int i; - for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) { - if (!(p->tval & DONTFREE)) + for (i = n1; i <= n2; i++) { + p = fldtab[i]; + if (freeable(p)) xfree(p->sval); + p->sval = ""; p->tval = FLD | STR | DONTFREE; - p->sval = nullstat; } } -void newfld(int n) /* add field n (after end) */ +void newfld(int n) /* add field n after end of existing lastfld */ { - if (n >= nfields) - ERROR "creating too many fields (%d); try -mf n", n FATAL; - cleanfld(maxfld, n); - maxfld = n; + if (n > nfields) + growfldtab(n); + cleanfld(lastfld+1, n); + lastfld = n; setfval(nfloc, (Awkfloat) n); } +Cell *fieldadr(int n) /* get nth field */ +{ + if (n < 0) + ERROR "trying to access field %d", n FATAL; + if (n > nfields) /* fields after NF are empty */ + growfldtab(n); /* but does not increase NF */ + return(fldtab[n]); +} + +void growfldtab(int n) /* make new fields up to at least $n */ +{ + int nf = 2 * nfields; + + if (n > nf) + nf = n; + fldtab = (Cell **) realloc(fldtab, (nf+1) * (sizeof (struct Cell *))); + if (fldtab == NULL) + ERROR "out of space creating %d fields", nf FATAL; + makefields(nfields+1, nf); + nfields = nf; +} + int refldbld(char *rec, char *fs) /* build fields from reg expr in FS */ { + /* this relies on having fields[] the same length as $0 */ + /* the fields are all stored in this one array with \0's */ char *fr; - int i, tempstat; + int i, tempstat, n; fa *pfa; + n = strlen(rec); + if (n > fieldssize) { + xfree(fields); + if ((fields = (char *) malloc(n+1)) == NULL) + ERROR "out of space for fields in refldbld %d", n FATAL; + fieldssize = n; + } fr = fields; *fr = '\0'; if (*rec == '\0') return 0; pfa = makedfa(fs, 1); - dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) ); + dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) ); tempstat = pfa->initstat; - for (i = 1; i < nfields; i++) { - if (!(fldtab[i].tval & DONTFREE)) - xfree(fldtab[i].sval); - fldtab[i].tval = FLD | STR | DONTFREE; - fldtab[i].sval = fr; - dprintf( ("refldbld: i=%d\n", i) ); + for (i = 1; ; i++) { + if (i > nfields) + growfldtab(i); + if (freeable(fldtab[i])) + xfree(fldtab[i]->sval); + fldtab[i]->tval = FLD | STR | DONTFREE; + fldtab[i]->sval = fr; + dprintf( ("refldbld: i=%d\n", i) ); if (nematch(pfa, rec)) { - pfa->initstat = 2; /* horrible coupling */ - dprintf( ("match %s (%d chars)\n", patbeg, patlen) ); + pfa->initstat = 2; /* horrible coupling to b.c */ + dprintf( ("match %s (%d chars)\n", patbeg, patlen) ); strncpy(fr, rec, patbeg-rec); fr += patbeg - rec + 1; *(fr-1) = '\0'; rec = patbeg + patlen; } else { - dprintf( ("no match %s\n", rec) ); + dprintf( ("no match %s\n", rec) ); strcpy(fr, rec); pfa->initstat = tempstat; break; @@ -362,44 +439,46 @@ void recbld(void) /* create $0 from $1..$NF if necessary */ { int i; char *r, *p; - static char *rec = 0; + char *buf = record; + int bufsize = recsize; if (donerec == 1) return; - if (rec == 0) { - rec = (char *) malloc(recsize); - if (rec == 0) - ERROR "out of space building $0, record size %d", recsize FATAL; - } - r = rec; + r = buf; for (i = 1; i <= *NF; i++) { - p = getsval(&fldtab[i]); - while (r < rec+recsize-1 && (*r = *p++)) + p = getsval(fldtab[i]); + if (!adjbuf(&buf, &bufsize, 1+strlen(p)+r-buf, recsize, &r, "recbld 1")) + ERROR "created $0 `%.30s...' too long", buf FATAL; + while ((*r = *p++) != 0) r++; - if (i < *NF) - for (p = *OFS; r < rec+recsize-1 && (*r = *p++); ) + if (i < *NF) { + if (!adjbuf(&buf, &bufsize, 2+strlen(*OFS)+r-buf, recsize, &r, "recbld 2")) + ERROR "created $0 `%.30s...' too long", buf FATAL; + for (p = *OFS; (*r = *p++) != 0; ) r++; + } } - if (r > rec + recsize - 1) - ERROR "built giant record `%.30s...'; try -mr n", record FATAL; + if (!adjbuf(&buf, &bufsize, 2+r-buf, recsize, &r, "recbld 3")) + ERROR "built giant record `%.30s...'", buf FATAL; *r = '\0'; - dprintf( ("in recbld inputFS=%s, recloc=%p\n", inputFS, recloc) ); - recloc->tval = REC | STR | DONTFREE; - recloc->sval = record = rec; - dprintf( ("in recbld inputFS=%s, recloc=%p\n", inputFS, recloc) ); - dprintf( ("recbld = |%s|\n", record) ); - donerec = 1; -} + dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) ); -Cell *fieldadr(int n) -{ - if (n < 0 || n >= nfields) - ERROR "trying to access field %d; try -mf n", n FATAL; - return(&fldtab[n]); + if (buf != record) { /* increased size of record */ + record = buf; /* BUG? memory leak? */ + recsize = bufsize; + } + if (freeable(fldtab[0])) + xfree(fldtab[0]->sval); + fldtab[0]->tval = REC | STR | DONTFREE; + fldtab[0]->sval = record; + + dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) ); + dprintf( ("recbld = |%s|\n", record) ); + donerec = 1; } int errorflag = 0; -char errbuf[200]; +char errbuf[300]; /* used by ERROR macro */ void yyerror(char *s) { @@ -553,84 +632,21 @@ int isclvar(char *s) /* is s of form var=something ? */ return *s == '=' && s > os && *(s+1) != '='; } -#define MAXEXPON 38 /* maximum exponent for fp number. should be IEEE */ +/* strtod is supposed to be a proper test of what's a valid number */ -int isnumber(char *s) /* should be done by a library function */ +#include <math.h> +int isnumber(char *s) { - int d1, d2; - int point; - char *es; - - d1 = d2 = point = 0; - while (*s == ' ' || *s == '\t' || *s == '\n') - s++; - if (*s == '\0') - return(0); /* empty stuff isn't a number */ - if (*s == '+' || *s == '-') - s++; - if (!isdigit(*s) && *s != '.') - return(0); - if (isdigit(*s)) { - do { - d1++; - s++; - } while (isdigit(*s)); - } - if (*s == '.') { - point++; - s++; - } - if (isdigit(*s)) { - d2++; - do { - s++; - } while (isdigit(*s)); - } - if (!(d1 || (point && d2))) - return(0); - if (*s == 'e' || *s == 'E') { - s++; - if (*s == '+' || *s == '-') - s++; - if (!isdigit(*s)) - return(0); - es = s; - do { - s++; - } while (isdigit(*s)); - if (s - es > 2) - return(0); - else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) - return(0); - } - while (*s == ' ' || *s == '\t' || *s == '\n') - s++; - if (*s == '\0') - return(1); + double r; + char *ep; + errno = 0; + r = strtod(s, &ep); + if (ep == s || r == HUGE_VAL || errno == ERANGE) + return 0; + while (*ep == ' ' || *ep == '\t' || *ep == '\n') + ep++; + if (*ep == '\0') + return 1; else - return(0); + return 0; } - -#if 0 - /* THIS IS AN EXPERIMENT THAT'S NOT DONE. */ - /* strtod ought to provide a better test of what's */ - /* a valid number, but it doesn't work according to */ - /* the standard on any machine near me! */ - - #include <math.h> - isnumber(char *s) - { - double r; - char *ep; - errno = 0; - r = strtod(s, &ep); - if (r == HUGE_VAL || errno == ERANGE) - return 0; - while (*ep == ' ' || *ep == '\t' || *ep == '\n') - ep++; - if (*ep == '\0') - return 1; - else - return 0; - } -#endif diff --git a/usr.bin/awk/main.c b/usr.bin/awk/main.c index c9bfda2bd39..e0cbcca13ba 100644 --- a/usr.bin/awk/main.c +++ b/usr.bin/awk/main.c @@ -1,5 +1,6 @@ +/* $OpenBSD: main.c,v 1.4 1997/08/25 16:17:12 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,22 +8,22 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ -char *version = "version June 29, 1996"; +char *version = "version 970821"; #define DEBUG #include <stdio.h> @@ -32,7 +33,7 @@ char *version = "version June 29, 1996"; #include <string.h> #include <signal.h> #include "awk.h" -#include "awkgram.h" +#include "ytab.h" extern char **environ; extern int nfields; @@ -49,6 +50,8 @@ char *pfile[20]; /* program filenames from -f's */ int npfile = 0; /* number of filenames */ int curpfile = 0; /* current filename */ +int safe = 0; /* 1 => "safe" mode */ + int main(int argc, char *argv[]) { char *fs = NULL, *marg; @@ -61,20 +64,23 @@ int main(int argc, char *argv[]) else cmdname = argv[0]; if (argc == 1) { - fprintf(stderr, "Usage: %s [-f programfile | 'program'] [-Ffieldsep] [-v var=value] [-mf n] [-mr n] [files]\n", cmdname); + fprintf(stderr, "Usage: %s [-f programfile | 'program'] [-Ffieldsep] [-v var=value] [files]\n", cmdname); exit(1); } - gs = newGstring(); /* for lex */ signal(SIGFPE, fpecatch); yyin = NULL; symtab = makesymtab(NSYMTAB); while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') { - if (strcmp((char *) argv[1], "--") == 0) { /* explicit end of args */ + if (strcmp(argv[1], "--") == 0) { /* explicit end of args */ argc--; argv++; break; } switch (argv[1][1]) { + case 's': + if (strcmp(argv[1], "-safe") == 0) + safe = 1; + break; case 'f': /* next argument is program filename */ argc--; argv++; @@ -85,13 +91,13 @@ int main(int argc, char *argv[]) case 'F': /* set field separator */ if (argv[1][2] != 0) { /* arg is -Fsomething */ if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */ - fs = (char *) "\t"; + fs = "\t"; else if (argv[1][2] != 0) fs = &argv[1][2]; } else { /* arg is -F something */ argc--; argv++; if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0) /* wart: t=>\t */ - fs = (char *) "\t"; + fs = "\t"; else if (argc > 1 && argv[1][0] != 0) fs = &argv[1][0]; } @@ -103,6 +109,7 @@ int main(int argc, char *argv[]) setclvar(argv[1]); break; case 'm': /* more memory: -mr=record, -mf=fields */ + /* no longer needed */ marg = argv[1]; if (argv[1][3]) temp = atoi(&argv[1][3]); @@ -136,7 +143,7 @@ int main(int argc, char *argv[]) exit(0); ERROR "no program given" FATAL; } - dprintf( ("program = |%s|\n", argv[1]) ); + dprintf( ("program = |%s|\n", argv[1]) ); lexprog = argv[1]; argc--; argv++; @@ -145,13 +152,14 @@ int main(int argc, char *argv[]) syminit(); compile_time = 1; argv[0] = cmdname; /* put prog name at front of arglist */ - dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) ); + dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) ); arginit(argc, argv); - envinit(environ); + if (!safe) + envinit(environ); yyparse(); if (fs) - *FS = tostring(qstring(fs, '\0')); - dprintf( ("errorflag=%d\n", errorflag) ); + *FS = qstring(fs, '\0'); + dprintf( ("errorflag=%d\n", errorflag) ); if (errorflag == 0) { compile_time = 0; run(winner); @@ -168,9 +176,9 @@ int pgetc(void) /* get 1 character from awk program */ if (yyin == NULL) { if (curpfile >= npfile) return EOF; - if (strcmp((char *) pfile[curpfile], "-") == 0) + if (strcmp(pfile[curpfile], "-") == 0) yyin = stdin; - else if ((yyin = fopen((char *) pfile[curpfile], "r")) == NULL) + else if ((yyin = fopen(pfile[curpfile], "r")) == NULL) ERROR "can't open file %s", pfile[curpfile] FATAL; } if ((c = getc(yyin)) != EOF) diff --git a/usr.bin/awk/maketab.c b/usr.bin/awk/maketab.c index 05dfbf4ada4..6d00aa055ef 100644 --- a/usr.bin/awk/maketab.c +++ b/usr.bin/awk/maketab.c @@ -1,5 +1,6 @@ +/* $OpenBSD: maketab.c,v 1.2 1997/08/25 16:17:12 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,32 +8,32 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ /* * this program makes the table to link function names * and type indices that is used by execute() in run.c. - * it finds the indices in awkgram.h, produced by yacc. + * it finds the indices in ytab.h, produced by yacc. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "awk.h" -#include "awkgram.h" +#include "ytab.h" struct xx { int token; @@ -120,12 +121,12 @@ int main(int argc, char *argv[]) printf("#include <stdio.h>\n"); printf("#include \"awk.h\"\n"); - printf("#include \"awkgram.h\"\n\n"); + printf("#include \"ytab.h\"\n\n"); for (i = SIZE; --i >= 0; ) names[i] = ""; - if ((fp = fopen("awkgram.h", "r")) == NULL) { - fprintf(stderr, "maketab can't open awkgram.h!\n"); + if ((fp = fopen("ytab.h", "r")) == NULL) { + fprintf(stderr, "maketab can't open ytab.h!\n"); exit(1); } printf("static char *printname[%d] = {\n", SIZE); diff --git a/usr.bin/awk/parse.c b/usr.bin/awk/parse.c index e4b005c8dac..0fbe00d3e3d 100644 --- a/usr.bin/awk/parse.c +++ b/usr.bin/awk/parse.c @@ -1,5 +1,6 @@ +/* $OpenBSD: parse.c,v 1.2 1997/08/25 16:17:13 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ #define DEBUG @@ -27,7 +28,7 @@ USE OR PERFORMANCE OF THIS SOFTWARE. #include <string.h> #include <stdlib.h> #include "awk.h" -#include "awkgram.h" +#include "ytab.h" Node *nodealloc(int n) { @@ -165,7 +166,7 @@ Node *op4(int a, Node *b, Node *c, Node *d, Node *e) return(x); } -Node *valtonode(Cell *a, int b) +Node *celltonode(Cell *a, int b) { Node *x; @@ -178,7 +179,8 @@ Node *valtonode(Cell *a, int b) Node *rectonode(void) /* make $0 into a Node */ { - return valtonode(recloc, CFLD); + extern Cell *literal0; + return op1(INDIRECT, celltonode(literal0, CUNK)); } Node *makearr(Node *p) @@ -187,7 +189,7 @@ Node *makearr(Node *p) if (isvalue(p)) { cp = (Cell *) (p->narg[0]); - if (isfunc(cp)) + if (isfcn(cp)) ERROR "%s is a function, not an array", cp->nval SYNTAX; else if (!isarr(cp)) { xfree(cp->sval); @@ -198,12 +200,17 @@ Node *makearr(Node *p) return p; } +#define PA2NUM 50 /* max number of pat,pat patterns allowed */ +int paircnt; /* number of them in use */ +int pairstack[PA2NUM]; /* state of each pat,pat */ + Node *pa2stat(Node *a, Node *b, Node *c) /* pat, pat {...} */ { Node *x; x = node4(PASTAT2, a, b, c, (Node *) paircnt); - paircnt++; + if (paircnt++ >= PA2NUM) + ERROR "limited to %d pat,pat statements", PA2NUM SYNTAX; x->ntype = NSTAT; return(x); } diff --git a/usr.bin/awk/proto.h b/usr.bin/awk/proto.h index ead4e2ba6b4..183fcffc602 100644 --- a/usr.bin/awk/proto.h +++ b/usr.bin/awk/proto.h @@ -1,5 +1,6 @@ +/* $OpenBSD: proto.h,v 1.3 1997/08/25 16:17:13 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ extern int yywrap(void); @@ -80,7 +81,7 @@ extern Node *op3(int, Node *, Node *, Node *); extern Node *op4(int, Node *, Node *, Node *, Node *); extern Node *stat2(int, Node *, Node *); extern Node *stat4(int, Node *, Node *, Node *, Node *); -extern Node *valtonode(Cell *, int); +extern Node *celltonode(Cell *, int); extern Node *rectonode(void); extern Node *makearr(Node *); extern Node *pa2stat(Node *, Node *, Node *); @@ -110,9 +111,11 @@ extern char *qstring(char *, int); extern void recinit(unsigned int); extern void initgetrec(void); -extern int getrec(char *); +extern void makefields(int, int); +extern void growfldtab(int n); +extern int getrec(char **, int *, int); extern void nextfile(void); -extern int readrec(char *buf, int bufsize, FILE *inf); +extern int readrec(char **buf, int *bufsize, FILE *inf); extern char *getargv(int); extern void setclvar(char *); extern void fldbld(void); @@ -132,6 +135,7 @@ extern double errcheck(double, char *); extern int isclvar(char *); extern int isnumber(char *); +extern int adjbuf(char **pb, int *sz, int min, int q, char **pbp, char *what); extern void run(Node *); extern Cell *execute(Node *); extern Cell *program(Node **, int); @@ -153,7 +157,7 @@ extern Cell *field(Node **, int); extern Cell *indirect(Node **, int); extern Cell *substr(Node **, int); extern Cell *sindex(Node **, int); -extern int format(char *, int, char *, Node *); +extern int format(char **, int *, char *, Node *); extern Cell *awksprintf(Node **, int); extern Cell *awkprintf(Node **, int); extern Cell *arith(Node **, int); diff --git a/usr.bin/awk/run.c b/usr.bin/awk/run.c index 0cc0dc192bc..56444eca3e9 100644 --- a/usr.bin/awk/run.c +++ b/usr.bin/awk/run.c @@ -1,6 +1,6 @@ -/* $OpenBSD: run.c,v 1.12 1997/04/07 15:59:56 millert Exp $ */ +/* $OpenBSD: run.c,v 1.13 1997/08/25 16:17:14 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -8,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ #define DEBUG @@ -32,7 +32,7 @@ USE OR PERFORMANCE OF THIS SOFTWARE. #include <stdlib.h> #include <time.h> #include "awk.h" -#include "awkgram.h" +#include "ytab.h" #define tempfree(x) if (istemp(x)) tfree(x); else @@ -64,10 +64,7 @@ void tempfree(Cell *p) { #endif jmp_buf env; - -#define PA2NUM 29 /* max number of pat,pat patterns allowed */ -int paircnt; /* number of them in use */ -int pairstack[PA2NUM]; /* state of each pat,pat */ +extern int pairstack[]; Node *winner = NULL; /* root of parse tree */ Cell *tmps; /* free temporary cells for execution */ @@ -88,10 +85,44 @@ static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM }; Cell *jexit = &exitcell; static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM }; Cell *jret = &retcell; -static Cell tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM }; +static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE }; Node *curnode = NULL; /* the node being executed, for debugging */ +/* buffer memory management */ +int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, + char *whatrtn) +/* pbuf: address of pointer to buffer being managed + * psiz: address of buffer size variable + * minlen: minimum length of buffer needed + * quantum: buffer size quantum + * pbptr: address of movable pointer into buffer, or 0 if none + * whatrtn: name of the calling routine if failure should cause fatal error + * + * return 0 for realloc failure, !=0 for success + */ +{ + if (minlen > *psiz) { + char *tbuf; + int rminlen = quantum ? minlen % quantum : 0; + int boff = pbptr ? *pbptr - *pbuf : 0; + /* round up to next multiple of quantum */ + if (rminlen) + minlen += quantum - rminlen; + tbuf = realloc(*pbuf, minlen); + if (tbuf == NULL) { + if (whatrtn) + ERROR "out of memory in %s", whatrtn FATAL; + return 0; + } + *pbuf = tbuf; + *psiz = minlen; + if (pbptr) + *pbptr = tbuf + boff; + } + return 1; +} + void run(Node *a) /* execution of parse tree starts here */ { execute(a); @@ -110,9 +141,9 @@ Cell *execute(Node *u) /* execute a node of the parse tree */ curnode = a; if (isvalue(a)) { x = (Cell *) (a->narg[0]); - if ((x->tval & FLD) && !donefld) + if (isfld(x) && !donefld) fldbld(); - else if ((x->tval & REC) && !donerec) + else if (isrec(x) && !donerec) recbld(); return(x); } @@ -120,9 +151,9 @@ Cell *execute(Node *u) /* execute a node of the parse tree */ ERROR "illegal statement" FATAL; proc = proctab[a->nobj-FIRSTTOKEN]; x = (*proc)(a->narg, a->nobj); - if ((x->tval & FLD) && !donefld) + if (isfld(x) && !donefld) fldbld(); - else if ((x->tval & REC) && !donerec) + else if (isrec(x) && !donerec) recbld(); if (isexpr(a)) return(x); @@ -150,7 +181,7 @@ Cell *program(Node **a, int n) /* execute an awk program */ tempfree(x); } if (a[1] || a[2]) - while (getrec(record) > 0) { + while (getrec(&record, &recsize, 1) > 0) { x = execute(a[1]); if (isexit(x)) break; @@ -184,15 +215,16 @@ struct Frame *fp = NULL; /* frame pointer. bottom level unused */ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ { - static Cell newcopycell = { OCELL, CCOPY, 0, (char *) "", 0.0, NUM|STR|DONTFREE }; + static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE }; int i, ncall, ndef; Node *x; - Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn; + Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */ + Cell *y, *z, *fcn; char *s; fcn = execute(a[0]); /* the function itself */ s = fcn->nval; - if (!isfunc(fcn)) + if (!isfcn(fcn)) ERROR "calling undefined function %s", s FATAL; if (frame == NULL) { fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame)); @@ -202,19 +234,19 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ ncall++; ndef = (int) fcn->fval; /* args in defn */ - dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame) ); + dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame) ); if (ncall > ndef) ERROR "function %s called with %d args, uses only %d", s, ncall, ndef WARNING; if (ncall + ndef > NARGS) ERROR "function %s has %d arguments, limit %d", s, ncall+ndef, NARGS FATAL; for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ - dprintf( ("evaluate args[%d], fp=%d:\n", i, fp-frame) ); + dprintf( ("evaluate args[%d], fp=%d:\n", i, fp-frame) ); y = execute(x); oargs[i] = y; - dprintf( ("args[%d]: %s %f <%s>, t=%o\n", - i, y->nval, y->fval, isarr(y) ? "(array)" : (char*) y->sval, y->tval) ); - if (isfunc(y)) + dprintf( ("args[%d]: %s %f <%s>, t=%o\n", + i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) ); + if (isfcn(y)) ERROR "can't use function %s as argument in %s", y->nval, s FATAL; if (isarr(y)) args[i] = y; /* arrays by ref */ @@ -240,9 +272,9 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ fp->nargs = ndef; /* number defined with (excess are locals) */ fp->retval = gettemp(); - dprintf( ("start exec of %s, fp=%d\n", s, fp-frame) ); + dprintf( ("start exec of %s, fp=%d\n", s, fp-frame) ); y = execute((Node *)(fcn->sval)); /* execute body */ - dprintf( ("finished exec of %s, fp=%d\n", s, fp-frame) ); + dprintf( ("finished exec of %s, fp=%d\n", s, fp-frame) ); for (i = 0; i < ndef; i++) { Cell *t = fp->args[i]; @@ -268,7 +300,7 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ return y; tempfree(y); /* this can free twice! */ z = fp->retval; /* return value */ - dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); + dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); fp--; return(z); } @@ -279,7 +311,7 @@ Cell *copycell(Cell *x) /* make a copy of a cell in a temp */ y = gettemp(); y->csub = CCOPY; /* prevents freeing until call is over */ - y->nval = x->nval; + y->nval = x->nval; /* BUG? */ y->sval = x->sval ? tostring(x->sval) : NULL; y->fval = x->fval; y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */ @@ -291,7 +323,7 @@ Cell *arg(Node **a, int n) /* nth argument of a function */ { n = (int) a[0]; /* argument number, counting from 0 */ - dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); + dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); if (n+1 > fp->nargs) ERROR "argument #%d of function %s was not supplied", n+1, fp->fcncell->nval FATAL; @@ -345,46 +377,51 @@ Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */ Cell *getline(Node **a, int n) /* get next line from specific input */ { /* a[0] is variable, a[1] is operator, a[2] is filename */ Cell *r, *x; - char buf[RECSIZE]; + extern Cell **fldtab; FILE *fp; + char *buf; + int bufsize = recsize; + + if ((buf = (char *) malloc(bufsize)) == NULL) + ERROR "out of memory in getline" FATAL; fflush(stdout); /* in case someone is waiting for a prompt */ r = gettemp(); if (a[1] != NULL) { /* getline < file */ x = execute(a[2]); /* filename */ - if ((int) a[1] == '|') /* input pipe */ + if ((int) a[1] == '|') /* input pipe */ a[1] = (Node *) LE; /* arbitrary flag */ fp = openfile((int) a[1], getsval(x)); tempfree(x); if (fp == NULL) n = -1; else - n = readrec(buf, sizeof(buf), fp); + n = readrec(&buf, &bufsize, fp); if (n <= 0) { ; } else if (a[0] != NULL) { /* getline var <file */ - setsval(execute(a[0]), buf); + x = execute(a[0]); + setsval(x, buf); + tempfree(x); } else { /* getline <file */ - if (!(recloc->tval & DONTFREE)) - xfree(recloc->sval); - strcpy(record, buf); - recloc->sval = record; - recloc->tval = REC | STR | DONTFREE; - if (isnumber(recloc->sval)) { - recloc->fval = atof(recloc->sval); - recloc->tval |= NUM; + setsval(fldtab[0], buf); + if (isnumber(fldtab[0]->sval)) { + fldtab[0]->fval = atof(fldtab[0]->sval); + fldtab[0]->tval |= NUM; } - donerec = 1; donefld = 0; } } else { /* bare getline; use current input */ if (a[0] == NULL) /* getline */ - n = getrec(record); + n = getrec(&record, &recsize, 1); else { /* getline var */ - n = getrec(buf); - setsval(execute(a[0]), buf); + n = getrec(&buf, &bufsize, 0); + x = execute(a[0]); + setsval(x, buf); + tempfree(x); } } setfval(r, (Awkfloat) n); + free(buf); return r; } @@ -400,20 +437,27 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ Cell *x, *y, *z; char *s; Node *np; - char buf[RECSIZE]; + char *buf; + int bufsz = recsize; + int nsub = strlen(*SUBSEP); + + if ((buf = malloc(bufsz)) == NULL) + ERROR "out of memory in array" FATAL; x = execute(a[0]); /* Cell* for symbol table */ buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); - strcat(buf, s); /* BUG: unchecked! */ + if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0)) + ERROR "out of memory for %s[%s...]", x->nval, buf FATAL; + strcat(buf, s); if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } if (!isarr(x)) { - dprintf( ("making %s into an array\n", x->nval) ); + dprintf( ("making %s into an array\n", x->nval) ); if (freeable(x)) xfree(x->sval); x->tval &= ~(STR|NUM|DONTFREE); @@ -424,6 +468,7 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ z->ctype = OCELL; z->csub = CVAR; tempfree(x); + free(buf); return(z); } @@ -431,7 +476,8 @@ Cell *adelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { Cell *x, *y; Node *np; - char buf[RECSIZE], *s; + char *s; + int nsub = strlen(*SUBSEP); x = execute(a[0]); /* Cell* for symbol table */ if (!isarr(x)) @@ -442,16 +488,23 @@ Cell *adelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ x->tval |= ARR; x->sval = (char *) makesymtab(NSYMTAB); } else { + int bufsz = recsize; + char *buf; + if ((buf = malloc(bufsz)) == NULL) + ERROR "out of memory in adelete" FATAL; buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); - strcat(buf, s); + if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0)) + ERROR "out of memory deleting %s[%s...]", x->nval, buf FATAL; + strcat(buf, s); if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } freeelem(x, buf); + free(buf); } tempfree(x); return true; @@ -461,22 +514,29 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ { Cell *x, *ap, *k; Node *p; - char buf[RECSIZE]; + char *buf; char *s; + int bufsz = recsize; + int nsub = strlen(*SUBSEP); ap = execute(a[1]); /* array name */ if (!isarr(ap)) { - dprintf( ("making %s into an array\n", ap->nval) ); + dprintf( ("making %s into an array\n", ap->nval) ); if (freeable(ap)) xfree(ap->sval); ap->tval &= ~(STR|NUM|DONTFREE); ap->tval |= ARR; ap->sval = (char *) makesymtab(NSYMTAB); } + if ((buf = malloc(bufsz)) == NULL) { + ERROR "out of memory in intest" FATAL; + } buf[0] = 0; for (p = a[0]; p; p = p->nnext) { x = execute(p); /* expr */ s = getsval(x); + if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0)) + ERROR "out of memory deleting %s[%s...]", x->nval, buf FATAL; strcat(buf, s); tempfree(x); if (p->nnext) @@ -484,6 +544,7 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ } k = lookup(buf, (Array *) ap->sval); tempfree(ap); + free(buf); if (k == NULL) return(false); else @@ -601,8 +662,10 @@ Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */ void tfree(Cell *a) /* free a tempcell */ { - if (freeable(a)) + if (freeable(a)) { + dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) ); xfree(a->sval); + } if (a == tmps) ERROR "tempcell list is curdled" FATAL; a->cnext = tmps; @@ -637,11 +700,10 @@ Cell *indirect(Node **a, int n) /* $( a[0] ) */ m = getfval(x); if (m == 0 && !isnumber(s = getsval(x))) /* suspicion! */ ERROR "illegal field $(%s), name \"%s\"", s, x->nval FATAL; - /* can x->nval ever be null??? */ - /* ERROR "illegal field $(%s)", s FATAL; */ + /* BUG: can x->nval ever be null??? */ tempfree(x); x = fieldadr(m); - x->ctype = OCELL; + x->ctype = OCELL; /* BUG? why are these needed? */ x->csub = CFLD; return(x); } @@ -683,7 +745,7 @@ Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ n = 0; else if (n > k - m) n = k - m; - dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); + dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); y = gettemp(); temp = s[n+m-1]; /* with thanks to John Linderman */ s[n+m-1] = '\0'; @@ -719,22 +781,25 @@ Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */ return(z); } -/* - * printf-like conversions - * returns len of buf or -1 on error - */ -int format(char *buf, int bufsize, char *s, Node *a) +#define MAXNUMSIZE 50 + +int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */ { - char fmt[RECSIZE]; + char *fmt; char *p, *t, *os; Cell *x; int flag = 0, n; + int fmtwd; /* format width */ + int fmtsz = recsize; + char *buf = *pbuf; + int bufsize = *pbufsize; os = s; p = buf; + if ((fmt = malloc(fmtsz)) == NULL) + ERROR "out of memory in format()" FATAL; while (*s) { - if (p - buf >= bufsize) - return -1; + adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format"); if (*s != '%') { *p++ = *s++; continue; @@ -744,20 +809,32 @@ int format(char *buf, int bufsize, char *s, Node *a) s += 2; continue; } - for (t=fmt; (*t++ = *s) != '\0'; s++) { + /* have to be real careful in case this is a huge number, eg, %100000d */ + fmtwd = atoi(s+1); + if (fmtwd < 0) + fmtwd = -fmtwd; + adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); + for (t = fmt; (*t++ = *s) != '\0'; s++) { + if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0)) + ERROR "format item %.30s... ran format() out of memory", os FATAL; if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') break; /* the ansi panoply */ if (*s == '*') { x = execute(a); a = a->nnext; - sprintf((char *)t-1, "%d", (int) getfval(x)); + sprintf(t-1, "%d", fmtwd=(int) getfval(x)); + if (fmtwd < 0) + fmtwd = -fmtwd; + adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); t = fmt + strlen(fmt); tempfree(x); } } *t = '\0'; - if (t >= fmt + sizeof(fmt)) - ERROR "format item %.30s... too long", os FATAL; + if (fmtwd < 0) + fmtwd = -fmtwd; + adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); + switch (*s) { case 'f': case 'e': case 'g': case 'E': case 'G': flag = 1; @@ -787,28 +864,40 @@ int format(char *buf, int bufsize, char *s, Node *a) ERROR "not enough args in printf(%s)", os FATAL; x = execute(a); a = a->nnext; + n = MAXNUMSIZE; + if (fmtwd > n) + n = fmtwd; + adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format"); switch (flag) { - case 0: sprintf((char *)p, "%s", fmt); /* unknown, so dump it too */ + case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */ + t = getsval(x); + n = strlen(t); + if (fmtwd > n) + n = fmtwd; + adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format"); p += strlen(p); - sprintf((char *)p, "%s", getsval(x)); + sprintf(p, "%s", t); break; - case 1: sprintf((char *)p, (char *)fmt, getfval(x)); break; - case 2: sprintf((char *)p, (char *)fmt, (long) getfval(x)); break; - case 3: sprintf((char *)p, (char *)fmt, (int) getfval(x)); break; + case 1: sprintf(p, fmt, getfval(x)); break; + case 2: sprintf(p, fmt, (long) getfval(x)); break; + case 3: sprintf(p, fmt, (int) getfval(x)); break; case 4: t = getsval(x); n = strlen(t); - if (n >= bufsize) - ERROR "huge string (%d chars) in printf %.30s...", - n, t FATAL; - sprintf((char *)p, (char *)fmt, t); + if (fmtwd > n) + n = fmtwd; + if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0)) + ERROR "huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t FATAL; + sprintf(p, fmt, t); break; case 5: - isnum(x) ? - (getfval(x) ? - sprintf((char *)p, (char *)fmt, (int) getfval(x)) - : (*p++ = '\0')) - : sprintf((char *)p, (char *)fmt, getsval(x)[0]); + if (isnum(x)) { + if (getfval(x)) + sprintf(p, fmt, (int) getfval(x)); + else + *p++ = '\0'; + } else + sprintf(p, fmt, getsval(x)[0]); break; } tempfree(x); @@ -816,24 +905,30 @@ int format(char *buf, int bufsize, char *s, Node *a) s++; } *p = '\0'; + free(fmt); for ( ; a; a = a->nnext) /* evaluate any remaining args */ execute(a); - return ((int)(p - buf)); + *pbuf = buf; + *pbufsize = bufsize; + return p - buf; } Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */ { Cell *x; Node *y; - char buf[3*RECSIZE]; + char *buf; + int bufsz=3*recsize; + if ((buf=malloc(bufsz)) == NULL) + ERROR "out of memory in awksprintf" FATAL; y = a[0]->nnext; x = execute(a[0]); - if (format(buf, sizeof buf, getsval(x), y) == -1) - ERROR "sprintf string %.30s... too long", buf FATAL; + if (format(&buf, &bufsz, getsval(x), y) == -1) + ERROR "sprintf string %.30s... too long. can't happen.", buf FATAL; tempfree(x); x = gettemp(); - x->sval = tostring(buf); + x->sval = buf; x->tval = STR; return(x); } @@ -844,25 +939,31 @@ Cell *awkprintf(Node **a, int n) /* printf */ FILE *fp; Cell *x; Node *y; - char buf[3*RECSIZE]; + char *buf; int len; + int bufsz=3*recsize; + if ((buf=malloc(bufsz)) == NULL) + ERROR "out of memory in awkprintf" FATAL; y = a[0]->nnext; x = execute(a[0]); - if ((len = format(buf, sizeof buf, getsval(x), y)) == -1) - ERROR "printf string %.30s... too long", buf FATAL; + if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) + ERROR "printf string %.30s... too long. can't happen.", buf FATAL; tempfree(x); if (a[1] == NULL) { + /* fputs(buf, stdout); */ fwrite(buf, len, 1, stdout); if (ferror(stdout)) ERROR "write error on stdout" FATAL; } else { fp = redirect((int)a[1], a[2]); + /* fputs(buf, fp); */ fwrite(buf, len, 1, fp); fflush(fp); if (ferror(fp)) ERROR "write error on %s", filename(fp) FATAL; } + free(buf); return(true); } @@ -967,9 +1068,9 @@ Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ x->fval = getfval(y); x->tval |= NUM; } - else if (y->tval & STR) + else if (isstr(y)) setsval(x, getsval(y)); - else if (y->tval & NUM) + else if (isnum(y)) setfval(x, getfval(y)); else funnyvar(y, "read value of"); @@ -1084,7 +1185,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ Cell *x = 0, *y, *ap; char *s; int sep; - char *t, temp, num[10], *fs = 0; + char *t, temp, num[50], *fs = 0; int n, tempstat; y = execute(a[0]); /* source string */ @@ -1095,13 +1196,13 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ x = execute(a[2]); fs = getsval(x); } else if ((int) a[3] == REGEXPR) - fs = (char*) "(regexpr)"; /* split(str,arr,/regexpr/) */ + fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ else - ERROR "illegal type of split()" FATAL; + ERROR "illegal type of split" FATAL; sep = *fs; ap = execute(a[1]); /* array name */ freesymtab(ap); - dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); + dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); ap->tval &= ~STR; ap->tval |= ARR; ap->sval = (char *) makesymtab(NSYMTAB); @@ -1119,18 +1220,18 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ pfa->initstat = 2; do { n++; - sprintf((char *)num, "%d", n); + sprintf(num, "%d", n); temp = *patbeg; *patbeg = '\0'; if (isnumber(s)) - setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval); + setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); else setsymtab(num, s, 0.0, STR, (Array *) ap->sval); *patbeg = temp; s = patbeg + patlen; if (*(patbeg+patlen-1) == 0 || *s == 0) { n++; - sprintf((char *)num, "%d", n); + sprintf(num, "%d", n); setsymtab(num, "", 0.0, STR, (Array *) ap->sval); pfa->initstat = tempstat; goto spdone; @@ -1138,9 +1239,9 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ } while (nematch(pfa,s)); } n++; - sprintf((char *)num, "%d", n); + sprintf(num, "%d", n); if (isnumber(s)) - setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval); + setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); else setsymtab(num, s, 0.0, STR, (Array *) ap->sval); spdone: @@ -1158,9 +1259,9 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); temp = *s; *s = '\0'; - sprintf((char *)num, "%d", n); + sprintf(num, "%d", n); if (isnumber(t)) - setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); + setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); *s = temp; @@ -1171,7 +1272,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ for (n = 0; *s != 0; s++) { char buf[2]; n++; - sprintf((char *)num, "%d", n); + sprintf(num, "%d", n); buf[0] = *s; buf[1] = 0; if (isdigit(buf[0])) @@ -1187,9 +1288,9 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ s++; temp = *s; *s = '\0'; - sprintf((char *)num, "%d", n); + sprintf(num, "%d", n); if (isnumber(t)) - setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); + setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); *s = temp; @@ -1330,68 +1431,12 @@ Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ return true; } -#if 0 - /* if someone ever wants to run over the arrays in sorted order, */ - /* here it is. but it will likely run slower, not faster. */ - - int qstrcmp(p, q) - char **p, **q; - { - return strcmp(*p, *q); - } - - Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ - { - Cell *x, *vp, *arrayp, *cp, *ncp, *ret; - Array *tp; - int i, ne; - #define BIGENOUGH 1000 - char *elems[BIGENOUGH], **ep; - - vp = execute(a[0]); - arrayp = execute(a[1]); - if (!isarr(arrayp)) - ERROR "%s is not an array", arrayp->nval FATAL; - tp = (Array *) arrayp->sval; - tempfree(arrayp); - ep = elems; - ret = true; - if (tp->nelem >= BIGENOUGH) - ep = (char **) malloc(tp->nelem * sizeof(char *)); - - for (i = ne = 0; i < tp->size; i++) - for (cp = tp->tab[i]; cp != NULL; cp = cp->cnext) - ep[ne++] = cp->nval; - if (ne != tp->nelem) - ERROR "can't happen: lost elems %d vs. %d", ne, tp->nelem FATAL; - qsort(ep, ne, sizeof(char *), qstrcmp); - for (i = 0; i < ne; i++) { - setsval(vp, ep[i]); - x = execute(a[2]); - if (isbreak(x)) { - tempfree(vp); - break; - } - if (isnext(x) || isnextfile(x) || isexit(x) || isret(x)) { - tempfree(vp); - ret = x; - break; - } - tempfree(x); - } - if (ep != elems) - free(ep); - return ret; - } -#endif - - Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ { Cell *x, *y; Awkfloat u; int t; - char *p, buf[RECSIZE]; + char *p, *buf; Node *nextarg; FILE *fp; @@ -1426,14 +1471,14 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis break; case FSYSTEM: fflush(stdout); /* in case something is buffered already */ - u = (Awkfloat) system((char *)getsval(x)) / 256; /* 256 is unix-dep */ + u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */ break; case FRAND: /* in principle, rand() returns something in 0..RAND_MAX */ u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; break; case FSRAND: - if (x->tval & REC) /* no argument provided */ + if (isrec(x)) /* no argument provided */ u = time((time_t *)0); else u = getfval(x); @@ -1441,7 +1486,7 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis break; case FTOUPPER: case FTOLOWER: - strcpy(buf, getsval(x)); + buf = tostring(getsval(x)); if (t == FTOUPPER) { for (p = buf; *p; p++) if (islower(*p)) @@ -1454,9 +1499,10 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis tempfree(x); x = gettemp(); setsval(x, buf); + free(buf); return x; case FFLUSH: - if ((fp = openfile(GT, getsval(x))) == NULL) + if ((fp = openfile(FFLUSH, getsval(x))) == NULL) u = EOF; else u = fflush(fp); @@ -1488,12 +1534,12 @@ Cell *printstat(Node **a, int n) /* print a[0] */ fp = redirect((int)a[1], a[2]); for (x = a[0]; x != NULL; x = x->nnext) { y = execute(x); - fputs((char *)getsval(y), fp); + fputs(getsval(y), fp); tempfree(y); if (x->nnext == NULL) - fputs((char *)*ORS, fp); + fputs(*ORS, fp); else - fputs((char *)*OFS, fp); + fputs(*OFS, fp); } if (a[1] != 0) fflush(fp); @@ -1544,9 +1590,15 @@ FILE *openfile(int a, char *us) if (*s == '\0') ERROR "null file name in print or getline" FATAL; for (i=0; i < FOPEN_MAX; i++) - if (files[i].fname && strcmp(s, files[i].fname) == 0) + if (files[i].fname && strcmp(s, files[i].fname) == 0) { if (a == files[i].mode || (a==APPEND && files[i].mode==GT)) return files[i].fp; + if (a == FFLUSH) + return files[i].fp; + } + if (a == FFLUSH) /* didn't find it, so don't create it! */ + return NULL; + for (i=0; i < FOPEN_MAX; i++) if (files[i].fp == 0) break; @@ -1629,15 +1681,18 @@ void closeall(void) } } -#define SUBSIZE (20 * RECSIZE) +void backsub(char **pb_ptr, char **sptr_ptr); Cell *sub(Node **a, int nnn) /* substitute command */ { char *sptr, *pb, *q; Cell *x, *y, *result; - char buf[SUBSIZE], *t; + char *t, *buf; fa *pfa; + int bufsz = recsize; + if ((buf=malloc(bufsz)) == NULL) + ERROR "out of memory in sub" FATAL; x = execute(a[3]); /* target string */ t = getsval(x); if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ @@ -1650,46 +1705,55 @@ Cell *sub(Node **a, int nnn) /* substitute command */ y = execute(a[2]); /* replacement string */ result = false; if (pmatch(pfa, t)) { - pb = buf; sptr = t; + adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub"); + pb = buf; while (sptr < patbeg) *pb++ = *sptr++; sptr = getsval(y); - while (*sptr != 0 && pb < buf + SUBSIZE - 1) - if (*sptr == '\\' && *(sptr+1) == '&') { - sptr++; /* skip \, */ - *pb++ = *sptr++; /* add & */ + while (*sptr != 0) { + adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); + if (*sptr == '\\') { + backsub(&pb, &sptr); } else if (*sptr == '&') { sptr++; + adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub"); for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; + } *pb = '\0'; - if (pb >= buf + SUBSIZE) - ERROR "sub() result %.30s too big", buf FATAL; + if (pb > buf + bufsz) + ERROR "sub result1 %.30s too big; can't happen", buf FATAL; sptr = patbeg + patlen; - if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) + if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { + adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); while ((*pb++ = *sptr++) != 0) ; - if (pb >= buf + SUBSIZE) - ERROR "sub() result %.30s too big", buf FATAL; - setsval(x, buf); + } + if (pb > buf + bufsz) + ERROR "sub result2 %.30s too big; can't happen", buf FATAL; + setsval(x, buf); /* BUG: should be able to avoid copy */ result = true;; } tempfree(x); tempfree(y); + free(buf); return result; } Cell *gsub(Node **a, int nnn) /* global substitute */ { Cell *x, *y; - char *rptr, *sptr, *t, *pb; - char buf[SUBSIZE]; + char *rptr, *sptr, *t, *pb, *q; + char *buf; fa *pfa; int mflag, tempstat, num; + int bufsz = recsize; + if ((buf=malloc(bufsz)) == NULL) + ERROR "out of memory in gsub" FATAL; mflag = 0; /* if mflag == 0, can replace empty string */ num = 0; x = execute(a[3]); /* target string */ @@ -1708,74 +1772,66 @@ Cell *gsub(Node **a, int nnn) /* global substitute */ pb = buf; rptr = getsval(y); do { - /* - char *p; - int i; - printf("target string: %s, *patbeg = %o, patlen = %d\n", - t, *patbeg, patlen); - printf(" match found: "); - p=patbeg; - for (i=0; i<patlen; i++) - printf("%c", *p++); - printf("\n"); - */ if (patlen == 0 && *patbeg != 0) { /* matched empty string */ if (mflag == 0) { /* can replace empty */ num++; sptr = rptr; - while (*sptr != 0 && pb < buf + SUBSIZE-1) - if (*sptr == '\\' && *(sptr+1) == '&') { - sptr++; - *pb++ = *sptr++; + while (*sptr != 0) { + adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); + if (*sptr == '\\') { + backsub(&pb, &sptr); } else if (*sptr == '&') { - char *q; sptr++; + adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; + } } if (*t == 0) /* at end */ goto done; + adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); *pb++ = *t++; - if (pb >= buf + SUBSIZE-1) - ERROR "gsub() result %.30s too big", buf FATAL; + if (pb > buf + bufsz) /* BUG: not sure of this test */ + ERROR "gsub result0 %.30s too big; can't happen", buf FATAL; mflag = 0; } else { /* matched nonempty string */ num++; - /* if (patlen <= 0) - ERROR "4: buf=%s, patlen %d, t=%s, patbeg=%s", buf, patlen, t, patbeg WARNING; */ sptr = t; - while (sptr < patbeg && pb < buf + SUBSIZE-1) + adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub"); + while (sptr < patbeg) *pb++ = *sptr++; sptr = rptr; - while (*sptr != 0 && pb < buf + SUBSIZE-1) - if (*sptr == '\\' && *(sptr+1) == '&') { - sptr++; - *pb++ = *sptr++; + while (*sptr != 0) { + adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); + if (*sptr == '\\') { + backsub(&pb, &sptr); } else if (*sptr == '&') { - char *q; sptr++; + adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); for (q = patbeg; q < patbeg+patlen; ) *pb++ = *q++; } else *pb++ = *sptr++; + } t = patbeg + patlen; if (patlen == 0 || *t == 0 || *(t-1) == 0) goto done; - if (pb >= buf + SUBSIZE-1) - ERROR "gsub() result %.30s too big", buf FATAL; + if (pb > buf + bufsz) + ERROR "gsub result1 %.30s too big; can't happen", buf FATAL; mflag = 1; } } while (pmatch(pfa,t)); sptr = t; + adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); while ((*pb++ = *sptr++) != 0) ; - done: if (pb >= buf + SUBSIZE-1) - ERROR "gsub() result %.30s too big", buf FATAL; + done: if (pb > buf + bufsz) + ERROR "gsub result2 %.30s too big; can't happen", buf FATAL; *pb = '\0'; - setsval(x, buf); + setsval(x, buf); /* BUG: should be able to avoid copy + free */ pfa->initstat = tempstat; } tempfree(x); @@ -1783,5 +1839,32 @@ Cell *gsub(Node **a, int nnn) /* global substitute */ x = gettemp(); x->tval = NUM; x->fval = num; + free(buf); return(x); } + +void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */ +{ /* sptr[0] == '\\' */ + char *pb = *pb_ptr, *sptr = *sptr_ptr; + + if (sptr[1] == '\\') { + if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ + *pb++ = '\\'; + *pb++ = '&'; + sptr += 4; + } else if (sptr[2] == '&') { /* \\& -> \ + matched */ + *pb++ = '\\'; + sptr += 2; + } else { /* \\x -> \\x */ + *pb++ = *sptr++; + *pb++ = *sptr++; + } + } else if (sptr[1] == '&') { /* literal & */ + sptr++; + *pb++ = *sptr++; + } else /* literal \ */ + *pb++ = *sptr++; + + *pb_ptr = pb; + *sptr_ptr = sptr; +} diff --git a/usr.bin/awk/tran.c b/usr.bin/awk/tran.c index 86ca9ead221..ec26449be42 100644 --- a/usr.bin/awk/tran.c +++ b/usr.bin/awk/tran.c @@ -1,5 +1,6 @@ +/* $OpenBSD: tran.c,v 1.3 1997/08/25 16:17:14 kstailey Exp $ */ /**************************************************************** -Copyright (C) AT&T and Lucent Technologies 1996 +Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and @@ -7,19 +8,19 @@ its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting -documentation, and that the names of AT&T or Lucent Technologies -or any of their entities not be used in advertising or publicity -pertaining to distribution of the software without specific, -written prior permission. - -AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR -ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. ****************************************************************/ #define DEBUG @@ -29,7 +30,7 @@ USE OR PERFORMANCE OF THIS SOFTWARE. #include <string.h> #include <stdlib.h> #include "awk.h" -#include "awkgram.h" +#include "ytab.h" #define FULLTAB 2 /* rehash when table gets this x full */ #define GROWTAB 4 /* grow table by this factor */ @@ -51,7 +52,6 @@ char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */ Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */ Awkfloat *RLENGTH; /* length of same */ -Cell *recloc; /* location of record */ Cell *nrloc; /* NR */ Cell *nfloc; /* NF */ Cell *fnrloc; /* FNR */ @@ -63,19 +63,17 @@ Cell *symtabloc; /* SYMTAB */ Cell *nullloc; /* a guaranteed empty cell */ Node *nullnode; /* zero&null, converted into a node for comparisons */ +Cell *literal0; -extern Cell *fldtab; +extern Cell **fldtab; void syminit(void) /* initialize symbol table with builtin vars */ { - setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab); + literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab); /* this is used for if(x)... tests: */ nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab); - nullnode = valtonode(nullloc, CCON); + nullnode = celltonode(nullloc, CCON); - /* recloc = setsymtab("$0", record, 0.0, REC|STR|DONTFREE, symtab); */ - /* has been done elsewhere */ - recloc = &fldtab[0]; FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval; RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval; OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval; @@ -98,18 +96,18 @@ void syminit(void) /* initialize symbol table with builtin vars */ symtabloc->sval = (char *) symtab; } -void arginit(int ac, char *av[]) /* set up ARGV and ARGC */ +void arginit(int ac, char **av) /* set up ARGV and ARGC */ { Cell *cp; int i; - char temp[5]; + char temp[50]; ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval; cp = setsymtab("ARGV", "", 0.0, ARR, symtab); ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */ cp->sval = (char *) ARGVtab; for (i = 0; i < ac; i++) { - sprintf((char *)temp, "%d", i); + sprintf(temp, "%d", i); if (isnumber(*av)) setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab); else @@ -127,7 +125,7 @@ void envinit(char **envp) /* set up ENVIRON variable */ ENVtab = makesymtab(NSYMTAB); cp->sval = (char *) ENVtab; for ( ; *envp; envp++) { - if ((p = (char *) strchr((char *) *envp, '=')) == NULL) + if ((p = strchr(*envp, '=')) == NULL) continue; *p++ = 0; /* split into two strings at = */ if (isnumber(p)) @@ -170,12 +168,12 @@ void freesymtab(Cell *ap) /* free a symbol table */ if (freeable(cp)) xfree(cp->sval); temp = cp->cnext; /* avoids freeing then using */ - free((char *) cp); + free(cp); } tp->tab[i] = 0; } - free((char *) (tp->tab)); - free((char *) tp); + free(tp->tab); + free(tp); } void freeelem(Cell *ap, char *s) /* free elem s from ap (i.e., ap["s"] */ @@ -187,7 +185,7 @@ void freeelem(Cell *ap, char *s) /* free elem s from ap (i.e., ap["s"] */ tp = (Array *) ap->sval; h = hash(s, tp->size); for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) - if (strcmp((char *) s, (char *) p->nval) == 0) { + if (strcmp(s, p->nval) == 0) { if (prev == NULL) /* 1st one */ tp->tab[h] = p->cnext; else /* middle somewhere */ @@ -195,7 +193,7 @@ void freeelem(Cell *ap, char *s) /* free elem s from ap (i.e., ap["s"] */ if (freeable(p)) xfree(p->sval); free(p->nval); - free((char *) p); + free(p); tp->nelem--; return; } @@ -207,7 +205,7 @@ Cell *setsymtab(char *n, char *s, Awkfloat f, unsigned t, Array *tp) Cell *p; if (n != NULL && (p = lookup(n, tp)) != NULL) { - dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n", + dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n", p, p->nval, p->sval, p->fval, p->tval) ); return(p); } @@ -226,7 +224,7 @@ Cell *setsymtab(char *n, char *s, Awkfloat f, unsigned t, Array *tp) h = hash(n, tp->size); p->cnext = tp->tab[h]; tp->tab[h] = p; - dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n", + dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n", p, p->nval, p->sval, p->fval, p->tval) ); return(p); } @@ -257,7 +255,7 @@ void rehash(Array *tp) /* rehash items in small table into big one */ np[nh] = cp; } } - free((char *) (tp->tab)); + free(tp->tab); tp->tab = np; tp->size = nsz; } @@ -269,33 +267,36 @@ Cell *lookup(char *s, Array *tp) /* look for s in tp */ h = hash(s, tp->size); for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) - if (strcmp((char *) s, (char *) p->nval) == 0) + if (strcmp(s, p->nval) == 0) return(p); /* found it */ return(NULL); /* not found */ } Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */ { + int fldno; + if ((vp->tval & (NUM | STR)) == 0) funnyvar(vp, "assign to"); - if (vp->tval & FLD) { + if (isfld(vp)) { donerec = 0; /* mark $0 invalid */ - if (vp-fldtab > *NF) - newfld(vp-fldtab); - dprintf( ("setting field %d to %g\n", vp-fldtab, f) ); - } else if (vp->tval & REC) { + fldno = atoi(vp->nval); + if (fldno > *NF) + newfld(fldno); + dprintf( ("setting field %d to %g\n", fldno, f) ); + } else if (isrec(vp)) { donefld = 0; /* mark $1... invalid */ donerec = 1; } vp->tval &= ~STR; /* mark string invalid */ vp->tval |= NUM; /* mark number ok */ - dprintf( ("setfval %p: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) ); + dprintf( ("setfval %p: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) ); return vp->fval = f; } void funnyvar(Cell *vp, char *rw) { - if (vp->tval & ARR) + if (isarr(vp)) ERROR "can't %s %s; it's an array name.", rw, vp->nval FATAL; if (vp->tval & FCN) ERROR "can't %s %s; it's a function.", rw, vp->nval FATAL; @@ -306,15 +307,18 @@ void funnyvar(Cell *vp, char *rw) char *setsval(Cell *vp, char *s) /* set string val of a Cell */ { char *t; + int fldno; + dprintf( ("starting setsval %p: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) ); if ((vp->tval & (NUM | STR)) == 0) funnyvar(vp, "assign to"); - if (vp->tval & FLD) { + if (isfld(vp)) { donerec = 0; /* mark $0 invalid */ - if (vp-fldtab > *NF) - newfld(vp-fldtab); - dprintf( ("setting field %d to %s (%p)\n", vp-fldtab, s, s) ); - } else if (vp->tval & REC) { + fldno = atoi(vp->nval); + if (fldno > *NF) + newfld(fldno); + dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) ); + } else if (isrec(vp)) { donefld = 0; /* mark $1... invalid */ donerec = 1; } @@ -324,7 +328,7 @@ char *setsval(Cell *vp, char *s) /* set string val of a Cell */ if (freeable(vp)) xfree(vp->sval); vp->tval &= ~DONTFREE; - dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, t,t, vp->tval) ); + dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, t,t, vp->tval) ); return(vp->sval = t); } @@ -332,42 +336,42 @@ Awkfloat getfval(Cell *vp) /* get float val of a Cell */ { if ((vp->tval & (NUM | STR)) == 0) funnyvar(vp, "read value of"); - if ((vp->tval & FLD) && donefld == 0) + if (isfld(vp) && donefld == 0) fldbld(); - else if ((vp->tval & REC) && donerec == 0) + else if (isrec(vp) && donerec == 0) recbld(); if (!isnum(vp)) { /* not a number */ vp->fval = atof(vp->sval); /* best guess */ if (isnumber(vp->sval) && !(vp->tval&CON)) vp->tval |= NUM; /* make NUM only sparingly */ } - dprintf( ("getfval %p: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) ); + dprintf( ("getfval %p: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) ); return(vp->fval); } char *getsval(Cell *vp) /* get string val of a Cell */ { - char s[100]; + char s[100]; /* BUG: unchecked */ double dtemp; if ((vp->tval & (NUM | STR)) == 0) funnyvar(vp, "read value of"); - if ((vp->tval & FLD) && donefld == 0) + if (isfld(vp) && donefld == 0) fldbld(); - else if ((vp->tval & REC) && donerec == 0) + else if (isrec(vp) && donerec == 0) recbld(); - if ((vp->tval & STR) == 0) { - if (!(vp->tval&DONTFREE)) + if (isstr(vp) == 0) { + if (freeable(vp)) xfree(vp->sval); if (modf(vp->fval, &dtemp) == 0) /* it's integral */ - sprintf((char *)s, "%.20g", vp->fval); + sprintf(s, "%.30g", vp->fval); else - sprintf((char *)s, (char *)*CONVFMT, vp->fval); + sprintf(s, *CONVFMT, vp->fval); vp->sval = tostring(s); vp->tval &= ~DONTFREE; vp->tval |= STR; } - dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, vp->sval, vp->sval, vp->tval) ); + dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, vp->sval, vp->sval, vp->tval) ); return(vp->sval); } @@ -375,33 +379,36 @@ char *tostring(char *s) /* make a copy of string s */ { char *p; - p = (char *) malloc(strlen((char *) s)+1); + p = (char *) malloc(strlen(s)+1); if (p == NULL) ERROR "out of space in tostring on %s", s FATAL; - strcpy((char *) p, (char *) s); + strcpy(p, s); return(p); } char *qstring(char *s, int delim) /* collect string up to next delim */ { int c, n; + char *buf = 0, *bp; - for (caddreset(gs); (c = *s) != delim; s++) { + if ((buf = (char *) malloc(strlen(s)+3)) == NULL) + ERROR "out of space in qstring(%s)", s); + for (bp = buf; (c = *s) != delim; s++) { if (c == '\n') - ERROR "newline in string %.10s...", gs->cbuf SYNTAX; + ERROR "newline in string %.10s...", buf SYNTAX; else if (c != '\\') - cadd(gs, c); - else /* \something */ + *bp++ = c; + else { /* \something */ switch (c = *++s) { - case '\\': cadd(gs, '\\'); break; - case 'n': cadd(gs, '\n'); break; - case 't': cadd(gs, '\t'); break; - case 'b': cadd(gs, '\b'); break; - case 'f': cadd(gs, '\f'); break; - case 'r': cadd(gs, '\r'); break; + case '\\': *bp++ = '\\'; break; + case 'n': *bp++ = '\n'; break; + case 't': *bp++ = '\t'; break; + case 'b': *bp++ = '\b'; break; + case 'f': *bp++ = '\f'; break; + case 'r': *bp++ = '\r'; break; default: if (!isdigit(c)) { - cadd(gs, c); + *bp++ = c; break; } n = c - '0'; @@ -410,10 +417,11 @@ char *qstring(char *s, int delim) /* collect string up to next delim */ if (isdigit(s[1])) n = 8 * n + *++s - '0'; } - cadd(gs, n); + *bp++ = n; break; } + } } - cadd(gs, 0); - return gs->cbuf; + *bp++ = 0; + return buf; } |