diff options
author | Cody Peter Mello <cody.mello@joyent.com> | 2019-08-22 18:30:18 -0700 |
---|---|---|
committer | Gordon Ross <gordon.w.ross@gmail.com> | 2019-08-23 22:54:33 -0400 |
commit | 3ee4fc2aa6b5136515cc3eed32d3c6ef33e37471 (patch) | |
tree | ccf629091e2a3bd2c701425a4eaebdfb577f367c /usr/src | |
parent | ac05f74f7be0e256003b8dd2492cf96ac4ecda1d (diff) | |
download | illumos-joyent-3ee4fc2aa6b5136515cc3eed32d3c6ef33e37471.tar.gz |
11552 Want a more modern nawk(1)
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Andy Fiddaman <andy@omniosce.org>
Approved by: Gordon Ross <gwr@nexenta.com>
Diffstat (limited to 'usr/src')
173 files changed, 9725 insertions, 2377 deletions
diff --git a/usr/src/cmd/awk/DIVERGENCES b/usr/src/cmd/awk/DIVERGENCES new file mode 100644 index 0000000000..ebc13cb036 --- /dev/null +++ b/usr/src/cmd/awk/DIVERGENCES @@ -0,0 +1,5 @@ +The illumos nawk(1) is slightly divergent from upstream: +- We allow an unlimited number of input program files +- We allow an unlimited number of "/pat/, /pat/" expressions +- Some of the code has been altered to track the length of strings + better so that we can avoid repeatedly calling strlen(3C) diff --git a/usr/src/cmd/awk/Makefile b/usr/src/cmd/awk/Makefile index c49c932558..046f0b739e 100644 --- a/usr/src/cmd/awk/Makefile +++ b/usr/src/cmd/awk/Makefile @@ -30,14 +30,13 @@ PROG= nawk -OBJ1= b.o lib.o main.o parse.o proctab.o run.o tran.o -OBJ2= awk.g.o awk.lx.o +OBJ1= b.o lib.o main.o parse.o proctab.o run.o tran.o lex.o +OBJ2= awk.g.o OBJS= $(OBJ2) $(OBJ1) SRCS= $(OBJ1:%.o=%.c) include ../Makefile.cmd -CERRWARN += -_gcc=-Wno-implicit-function-declaration CERRWARN += -_gcc=-Wno-unused-label CERRWARN += -_gcc=-Wno-parentheses CERRWARN += -_gcc=-Wno-unused-variable @@ -56,13 +55,13 @@ XGETFLAGS += -a -x awk.xcl CPPFLAGS += -D_FILE_OFFSET_BITS=64 YFLAGS += -d -LDLIBS += -lm +LDLIBS += -lm -lumem LINTFLAGS += -u -CLEANFILES= maketab proctab.c awk.g.c awk.lx.c y.tab.h +CLEANFILES= maketab proctab.c awk.g.c y.tab.h .KEEP_STATE: -all: $(PROG) +all: $(PROG) $(PROG): $(OBJS) $(LINK.c) $(OBJS) -o $@ $(LDLIBS) @@ -94,8 +93,6 @@ awk.g.c + y.tab.h: awk.g.y awk.g.o: awk.g.c -awk.lx.c: awk.lx.l - proctab.o: proctab.c $(COMPILE.c) proctab.c $(POST_PROCESS_O) diff --git a/usr/src/cmd/awk/awk.g.y b/usr/src/cmd/awk/awk.g.y index 21bc8b6dc8..3b5efb3d7d 100644 --- a/usr/src/cmd/awk/awk.g.y +++ b/usr/src/cmd/awk/awk.g.y @@ -1,5 +1,29 @@ %{ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -30,30 +54,28 @@ /* All Rights Reserved */ %{ -#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 2.10 */ -%} - -%{ #include "awk.h" + +void checkdup(Node *list, Cell *item); int yywrap(void) { return(1); } -#ifndef DEBUG -# define PUTS(x) -#endif -Node *beginloc = 0, *endloc = 0; -int infunc = 0; /* = 1 if in arglist or body of func */ -uchar *curfname = 0; -Node *arglist = 0; /* list of args for current function */ + +Node *beginloc = NULL; +Node *endloc = NULL; +int infunc = 0; /* = 1 if in arglist or body of func */ +int inloop = 0; /* = 1 if in while, for, do */ +char *curfname = NULL; /* current function name */ +Node *arglist = NULL; /* list of args for current function */ static void setfname(Cell *); static int constnode(Node *); -static uchar *strnode(Node *); -static Node *notnull(); +static char *strnode(Node *); +static Node *notnull(Node *); %} %union { Node *p; Cell *cp; int i; - uchar *s; + char *s; } %token <i> FIRSTTOKEN /* must be first */ @@ -61,25 +83,26 @@ static Node *notnull(); %token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']' %token <i> ARRAY %token <i> MATCH NOTMATCH MATCHOP -%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS +%token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE %token <i> AND BOR APPEND EQ GE GT LE LT NE IN -%token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC -%token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT +%token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC +%token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE %token <i> ADD MINUS MULT DIVIDE MOD %token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ %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 +%type <p> pas pattern ppattern plist pplist patlist prarg term re %type <p> pa_pat pa_stat pa_stats %type <s> reg_expr %type <p> simple_stmt opt_simple_stmt stmt stmtlist %type <p> var varname funcname varlist -%type <p> for if while -%type <i> pst opt_pst lbrace rparen comma nl opt_nl and bor +%type <p> for if else while +%type <i> do st +%type <i> pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor %type <i> subop print %right ASGNOP @@ -89,14 +112,14 @@ static Node *notnull(); %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 '(' %left CAT %left '+' '-' %left '*' '/' '%' -%left NOT UMINUS +%left NOT UMINUS UPLUS %right POWER %right DECR INCR %left INDIRECT @@ -107,7 +130,7 @@ static Node *notnull(); program: pas { if (errorflag==0) winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); } - | error { yyclearin; bracecheck(); ERROR "bailing out" SYNTAX; } + | error { yyclearin; bracecheck(); SYNTAX("bailing out"); } ; and: @@ -131,12 +154,12 @@ else: ; for: - FOR '(' opt_simple_stmt ';' pattern ';' opt_simple_stmt rparen stmt - { $$ = stat4(FOR, $3, notnull($5), $7, $9); } - | FOR '(' opt_simple_stmt ';' ';' opt_simple_stmt rparen stmt - { $$ = stat4(FOR, $3, NIL, $6, $8); } - | FOR '(' varname IN varname rparen stmt - { $$ = stat3(IN, $3, makearr($5), $7); } + FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt + { --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); } + | FOR '(' opt_simple_stmt ';' ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt + { --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); } + | FOR '(' varname IN varname rparen {inloop++;} stmt + { --inloop; $$ = stat3(IN, $3, makearr($5), $8); } ; funcname: @@ -184,8 +207,8 @@ pa_pat: pa_stat: pa_pat { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); } | pa_pat lbrace stmtlist '}' { $$ = stat2(PASTAT, $1, $3); } - | pa_pat ',' pa_pat { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); } - | pa_pat ',' pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $3, $5); } + | pa_pat ',' opt_nl pa_pat { $$ = pa2stat($1, $4, stat2(PRINT, rectonode(), NIL)); } + | pa_pat ',' opt_nl pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $4, $6); } | lbrace stmtlist '}' { $$ = stat2(PASTAT, NIL, $2); } | XBEGIN lbrace stmtlist '}' { beginloc = linkum(beginloc, $3); $$ = 0; } @@ -202,19 +225,17 @@ pa_stats: patlist: pattern - | patlist comma pattern { $$ = linkum($1, $3); } + | patlist comma pattern { $$ = linkum($1, $3); } ; ppattern: var ASGNOP ppattern { $$ = op2($2, $1, $3); } | ppattern '?' ppattern ':' ppattern %prec '?' - { $$ = op3(CONDEXPR, notnull($1), $3, $5); } + { $$ = op3(CONDEXPR, notnull($1), $3, $5); } | ppattern bor ppattern %prec BOR { $$ = op2(BOR, notnull($1), notnull($3)); } | ppattern and ppattern %prec AND { $$ = op2(AND, notnull($1), notnull($3)); } - | NOT ppattern - { $$ = op1(NOT, notnull($2)); } | ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); } | ppattern MATCHOP ppattern { if (constnode($3)) @@ -224,21 +245,18 @@ ppattern: | ppattern IN varname { $$ = op2(INTEST, $1, makearr($3)); } | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); } | ppattern term %prec CAT { $$ = op2(CAT, $1, $2); } - | reg_expr - { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); } + | re | term ; pattern: var ASGNOP pattern { $$ = op2($2, $1, $3); } | pattern '?' pattern ':' pattern %prec '?' - { $$ = op3(CONDEXPR, notnull($1), $3, $5); } + { $$ = op3(CONDEXPR, notnull($1), $3, $5); } | pattern bor pattern %prec BOR { $$ = op2(BOR, notnull($1), notnull($3)); } | pattern and pattern %prec AND { $$ = op2(AND, notnull($1), notnull($3)); } - | NOT pattern - { $$ = op1(NOT, op2(NE,$2,valtonode(lookup((uchar *)"$zero&null",symtab),CCON))); } | pattern EQ pattern { $$ = op2($2, $1, $3); } | pattern GE pattern { $$ = op2($2, $1, $3); } | pattern GT pattern { $$ = op2($2, $1, $3); } @@ -253,11 +271,14 @@ 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) SYNTAX("cmd | getline is unsafe"); + else $$ = op3(GETLINE, $4, itonp($2), $1); } + | pattern '|' GETLINE { + if (safe) SYNTAX("cmd | getline is unsafe"); + else $$ = op3(GETLINE, (Node*)0, itonp($2), $1); } | pattern term %prec CAT { $$ = op2(CAT, $1, $2); } - | reg_expr - { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); } + | re | term ; @@ -269,6 +290,7 @@ plist: pplist: ppattern | pplist comma ppattern { $$ = linkum($1, $3); } + ; prarg: /* empty */ { $$ = rectonode(); } @@ -288,6 +310,12 @@ rbrace: '}' | rbrace NL ; +re: + reg_expr + { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); } + | NOT re { $$ = op1(NOT, notnull($2)); } + ; + reg_expr: '/' {startreg();} REGEXPR '/' { $$ = $3; } ; @@ -297,26 +325,34 @@ 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) SYNTAX("print | is unsafe"); + else $$ = stat3($1, $2, itonp($3), $4); } + | print prarg APPEND term { + if (safe) SYNTAX("print >> is unsafe"); + else $$ = stat3($1, $2, itonp($3), $4); } + | print prarg GT term { + if (safe) SYNTAX("print > is unsafe"); + else $$ = stat3($1, $2, itonp($3), $4); } | print prarg { $$ = stat3($1, $2, NIL, NIL); } | DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); } - | DELETE varname { yyclearin; ERROR "you can only delete array[element]" SYNTAX; $$ = stat1(DELETE, $2); } + | DELETE varname { $$ = stat2(DELETE, makearr($2), 0); } | pattern { $$ = exptostat($1); } - | error { yyclearin; ERROR "illegal statement" SYNTAX; } + | error { yyclearin; SYNTAX("illegal statement"); } ; st: - nl | ';' opt_nl + nl + | ';' opt_nl ; stmt: - BREAK st { $$ = stat1(BREAK, NIL); } - | CLOSE pattern st { $$ = stat1(CLOSE, $2); } - | CONTINUE st { $$ = stat1(CONTINUE, NIL); } - | do stmt WHILE '(' pattern ')' st - { $$ = stat2(DO, $2, notnull($5)); } + BREAK st { if (!inloop) SYNTAX("break illegal outside of loops"); + $$ = stat1(BREAK, NIL); } + | CONTINUE st { if (!inloop) SYNTAX("continue illegal outside of loops"); + $$ = stat1(CONTINUE, NIL); } + | do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st + { $$ = stat2(DO, $3, notnull($7)); } | EXIT pattern st { $$ = stat1(EXIT, $2); } | EXIT st { $$ = stat1(EXIT, NIL); } | for @@ -324,12 +360,15 @@ stmt: | if stmt { $$ = stat3(IF, $1, $2, NIL); } | lbrace stmtlist rbrace { $$ = $2; } | NEXT st { if (infunc) - ERROR "next is illegal inside a function" SYNTAX; + SYNTAX("next is illegal inside a function"); $$ = stat1(NEXT, NIL); } + | NEXTFILE st { if (infunc) + SYNTAX("nextfile is illegal inside a function"); + $$ = stat1(NEXTFILE, NIL); } | RETURN pattern st { $$ = stat1(RETURN, $2); } | RETURN st { $$ = stat1(RETURN, NIL); } | simple_stmt st - | while stmt { $$ = stat2(WHILE, $1, $2); } + | while {inloop++;} stmt { --inloop; $$ = stat2(WHILE, $1, $3); } | ';' opt_nl { $$ = 0; } ; @@ -343,31 +382,34 @@ subop: ; term: - term '+' term { $$ = op2(ADD, $1, $3); } + term '/' ASGNOP term { $$ = op2(DIVEQ, $1, $4); } + | term '+' term { $$ = op2(ADD, $1, $3); } | term '-' term { $$ = op2(MINUS, $1, $3); } | term '*' term { $$ = op2(MULT, $1, $3); } | term '/' term { $$ = op2(DIVIDE, $1, $3); } | term '%' term { $$ = op2(MOD, $1, $3); } | term POWER term { $$ = op2(POWER, $1, $3); } | '-' term %prec UMINUS { $$ = op1(UMINUS, $2); } - | '+' term %prec UMINUS { $$ = $2; } - | 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); } + | '+' term %prec UMINUS { $$ = op1(UPLUS, $2); } + | NOT term %prec UMINUS { $$ = op1(NOT, notnull($2)); } + | BLTIN '(' ')' { $$ = op2(BLTIN, itonp($1), rectonode()); } + | BLTIN '(' patlist ')' { $$ = op2(BLTIN, itonp($1), $3); } + | BLTIN { $$ = op2(BLTIN, itonp($1), rectonode()); } + | CALL '(' ')' { $$ = op2(CALL, celltonode($1,CVAR), NIL); } + | CALL '(' patlist ')' { $$ = op2(CALL, celltonode($1,CVAR), $3); } + | CLOSE term { $$ = op1(CLOSE, $2); } | DECR var { $$ = op1(PREDECR, $2); } | INCR var { $$ = op1(PREINCR, $2); } | var DECR { $$ = op1(POSTDECR, $1); } | var INCR { $$ = op1(POSTINCR, $1); } - | GETLINE var LT term { $$ = op3(GETLINE, $2, (Node *)$3, $4); } - | GETLINE LT term { $$ = op3(GETLINE, NIL, (Node *)$2, $3); } + | GETLINE var LT term { $$ = op3(GETLINE, $2, itonp($3), $4); } + | GETLINE LT term { $$ = op3(GETLINE, NIL, itonp($2), $3); } | GETLINE var { $$ = op3(GETLINE, $2, NIL, NIL); } | GETLINE { $$ = op3(GETLINE, NIL, NIL, NIL); } | INDEX '(' pattern comma pattern ')' { $$ = op2(INDEX, $3, $5); } | INDEX '(' pattern comma reg_expr ')' - { ERROR "index() doesn't permit regular expressions" SYNTAX; + { SYNTAX("index() doesn't permit regular expressions"); $$ = op2(INDEX, $3, (Node*)$5); } | '(' pattern ')' { $$ = $2; } | MATCHFCN '(' pattern comma reg_expr ')' @@ -377,7 +419,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/ */ @@ -385,7 +427,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 ')' @@ -410,20 +452,21 @@ term: var: varname | varname '[' patlist ']' { $$ = op2(ARRAY, makearr($1), $3); } - | FIELD { $$ = valtonode($1, CFLD); } - | IVAR { $$ = op1(INDIRECT, valtonode($1, CVAR)); } - | INDIRECT term { $$ = op1(INDIRECT, $2); } - ; + | IVAR { $$ = op1(INDIRECT, celltonode($1, CVAR)); } + | INDIRECT term { $$ = op1(INDIRECT, $2); } + ; varlist: /* nothing */ { arglist = $$ = 0; } - | VAR { arglist = $$ = valtonode($1,CVAR); } - | varlist comma VAR { arglist = $$ = linkum($1,valtonode($3,CVAR)); } + | VAR { arglist = $$ = celltonode($1,CVAR); } + | varlist comma VAR { + checkdup($1, $3); + arglist = $$ = linkum($1,celltonode($3,CVAR)); } ; varname: - VAR { $$ = valtonode($1, CVAR); } - | ARG { $$ = op1(ARG, (Node *) $1); } + VAR { $$ = celltonode($1, CVAR); } + | ARG { $$ = op1(ARG, itonp($1)); } | VARNF { $$ = op1(VARNF, (Node *) $1); } ; @@ -438,20 +481,20 @@ static void setfname(Cell *p) { if (isarr(p)) - ERROR "%s is an array, not a function", p->nval SYNTAX; - else if (isfunc(p)) - ERROR "you can't define function %s more than once", p->nval SYNTAX; + SYNTAX("%s is an array, not a function", p->nval); + else if (isfcn(p)) + SYNTAX("you can't define function %s more than once", p->nval); curfname = p->nval; + p->tval |= FCN; } - static int constnode(Node *p) { - return p->ntype == NVALUE && ((Cell *) (p->narg[0]))->csub == CCON; + return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON; } -static uchar * +static char * strnode(Node *p) { return ((Cell *)(p->narg[0]))->sval; @@ -468,3 +511,15 @@ notnull(Node *n) return op2(NE, n, nullnode); } } + +void +checkdup(Node *vl, Cell *cp) /* check if name already in list */ +{ + char *s = cp->nval; + for (; vl; vl = vl->nnext) { + if (strcmp(s, ((Cell *)(vl->narg[0]))->nval) == 0) { + SYNTAX("duplicate argument %s", s); + break; + } + } +} diff --git a/usr/src/cmd/awk/awk.h b/usr/src/cmd/awk/awk.h index 987028fea2..dfbed45e9d 100644 --- a/usr/src/cmd/awk/awk.h +++ b/usr/src/cmd/awk/awk.h @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -29,6 +53,7 @@ #ifndef AWK_H #define AWK_H +#include <assert.h> #include <sys/types.h> #include <ctype.h> #include <stdio.h> @@ -38,10 +63,15 @@ #include <limits.h> typedef double Awkfloat; -typedef unsigned char uchar; -#define xfree(a) { if ((a) != NULL) { free(a); a = NULL; } } +/* unsigned char is more trouble than it's worth */ + +typedef unsigned char uschar; +#define xfree(a) { if ((a) != NULL) { free((void *)(a)); (a) = NULL; } } + +/* guaranteed non-null for dprintf */ +#define NN(p) ((p) ? (p) : "(null)") #define DEBUG #ifdef DEBUG /* uses have to be doubly parenthesized */ @@ -50,63 +80,56 @@ typedef unsigned char uchar; #define dprintf(x) #endif -extern char errbuf[200]; -extern void error(int, char *); -#define ERROR (void) snprintf(errbuf, sizeof (errbuf), -/*CSTYLED*/ -#define FATAL ), error(1, errbuf) -/*CSTYLED*/ -#define WARNING ), error(0, errbuf) -/*CSTYLED*/ -#define SYNTAX ), yyerror(errbuf) -/*CSTYLED*/ -#define CONT ) - extern int compile_time; /* 1 if compiling, 0 if running */ +extern int safe; /* 0 => unsafe, 1 => safe */ #define FLD_INCR 64 #define LINE_INCR 256 +#define RECSIZE (8 * 1024) /* sets limit on records, fields, etc., etc. */ +extern size_t recsize; /* size of current record, orig RECSIZE */ /* ensure that there is extra 1 byte in the buffer */ #define expand_buf(p, n, r) \ if (*(n) == 0 || (r) >= (*(n) - 1)) r_expand_buf(p, n, r) -extern uchar **FS; -extern uchar **RS; -extern uchar **ORS; -extern uchar **OFS; -extern uchar **OFMT; +extern char **FS; +extern char **RS; +extern char **ORS; +extern char **OFS; +extern char **OFMT; extern Awkfloat *NR; extern Awkfloat *FNR; extern Awkfloat *NF; -extern uchar **FILENAME; -extern uchar **SUBSEP; +extern char **FILENAME; +extern char **SUBSEP; extern Awkfloat *RSTART; extern Awkfloat *RLENGTH; -extern uchar *record; -extern size_t record_size; -extern int errorflag; +extern char *record; /* points to $0 */ +extern size_t recsize; +extern int errorflag; /* 1 if error has occurred */ extern int donefld; /* 1 if record broken into fields */ extern int donerec; /* 1 if record is valid (no fld has changed */ -extern uchar *patbeg; /* beginning of pattern matched */ -extern int patlen; /* length. set in b.c */ +extern char *patbeg; /* beginning of pattern matched */ +extern int patlen; /* length of pattern matched. set in b.c */ /* Cell: all information about a variable or constant */ typedef struct Cell { - uchar ctype; /* OCELL, OBOOL, OJUMP, etc. */ - uchar csub; /* CCON, CTEMP, CFLD, etc. */ - uchar *nval; /* name, for variables only */ - uchar *sval; /* string value */ + uschar ctype; /* OCELL, OBOOL, OJUMP, etc. */ + uschar csub; /* CCON, CTEMP, CFLD, etc. */ + char *nval; /* name, for variables only */ + char *sval; /* string value */ Awkfloat fval; /* value as number */ - unsigned tval; - /* type info: STR|NUM|ARR|FCN|FLD|CON|DONTFREE */ + int tval; + /* type info: STR|NUM|ARR|FCN|FLD|CON|DONTFREE|CONVC|CONVO */ + char *fmt; + /* CONVFMT/OFMT value used to convert from number */ 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 */ @@ -114,15 +137,23 @@ typedef struct { /* symbol table array */ #define NSYMTAB 50 /* initial size of a symbol table */ extern Array *symtab, *makesymtab(int); -extern Cell *setsymtab(uchar *, uchar *, Awkfloat, unsigned int, Array *); -extern Cell *lookup(uchar *, Array *); +extern Cell *setsymtab(const char *, const char *, Awkfloat, + unsigned int, Array *); +extern Cell *lookup(const char *, Array *); extern Cell *recloc; /* location of input record */ extern Cell *nrloc; /* NR */ extern Cell *fnrloc; /* FNR */ +extern Cell *fsloc; /* FS */ extern Cell *nfloc; /* NF */ +extern Cell *ofsloc; /* OFS */ +extern Cell *orsloc; /* ORS */ +extern Cell *rsloc; /* RS */ +extern Cell *rtloc; /* RT */ extern Cell *rstartloc; /* RSTART */ extern Cell *rlengthloc; /* RLENGTH */ +extern Cell *subseploc; /* SUBSEP */ +extern Cell *symtabloc; /* SYMTAB */ /* Cell.tval values: */ #define NUM 01 /* number value is valid */ @@ -133,17 +164,18 @@ extern Cell *rlengthloc; /* RLENGTH */ #define FCN 040 /* this is a function name */ #define FLD 0100 /* this is a field $1, $2, ... */ #define REC 0200 /* this is $0 */ +#define CONVC 0400 /* string was converted from number via CONVFMT */ +#define CONVO 01000 /* string was converted from number via OFMT */ -#define freeable(p) (!((p)->tval & DONTFREE)) -extern Awkfloat setfval(Cell *, Awkfloat), getfval(Cell *), r_getfval(Cell *); -extern uchar *setsval(Cell *, uchar *), *getsval(Cell *), *r_getsval(Cell *); -extern uchar *tostring(uchar *), *tokname(int), *qstring(uchar *, int); - -#define getfval(p) \ - (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p)) -#define getsval(p) \ - (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p)) +extern Awkfloat setfval(Cell *, Awkfloat); +extern Awkfloat getfval(Cell *); +extern char *setsval(Cell *, const char *); +extern char *getsval(Cell *); +extern char *getpssval(Cell *); /* for print */ +extern char *tostring(const char *); +extern char *tokname(int); +extern char *qstring(const char *, int); /* function types */ #define FLENGTH 1 @@ -159,15 +191,16 @@ extern uchar *tostring(uchar *), *tokname(int), *qstring(uchar *, int); #define FATAN 11 #define FTOUPPER 12 #define FTOLOWER 13 +#define FFLUSH 14 /* Node: parse tree is made of nodes, with Cell's at bottom */ typedef struct Node { int ntype; struct Node *nnext; - off_t lineno; + off_t lineno; int nobj; - struct Node *narg[1]; + struct Node *narg[1]; /* variable: actual size set by calling malloc */ } Node; @@ -190,6 +223,7 @@ extern Node *nullnode; #define CNAME 3 #define CVAR 2 #define CFLD 1 +#define CUNK 0 /* bool subtypes */ #define BTRUE 11 @@ -201,6 +235,7 @@ extern Node *nullnode; #define JBREAK 23 #define JCONT 24 #define JRET 25 +#define JNEXTFILE 26 /* node types */ #define NVALUE 1 @@ -210,7 +245,7 @@ extern Node *nullnode; extern Cell *(*proctab[])(Node **, int); extern Cell *nullproc(Node **, int); -extern int pairstack[], paircnt; +extern int *pairstack, paircnt; extern Node *stat1(int, Node *), *stat2(int, Node *, Node *); extern Node *stat3(int, Node *, Node *, Node *); @@ -219,7 +254,7 @@ extern Node *pa2stat(Node *, Node *, Node *); extern Node *op1(int, Node *), *op2(int, Node *, Node *); extern Node *op3(int, Node *, Node *, Node *); extern Node *op4(int, Node *, Node *, Node *, Node *); -extern Node *linkum(Node *, Node *), *valtonode(Cell *, int); +extern Node *linkum(Node *, Node *), *celltonode(Cell *, int); extern Node *rectonode(void), *exptostat(Node *); extern Node *makearr(Node *); @@ -231,89 +266,124 @@ extern Node *makearr(Node *); #define isexit(n) ((n)->csub == JEXIT) #define isbreak(n) ((n)->csub == JBREAK) #define iscont(n) ((n)->csub == JCONT) -#define isnext(n) ((n)->csub == JNEXT) +#define isnext(n) ((n)->csub == JNEXT || (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 freeable(p) (((p)->tval & (STR|DONTFREE)) == STR) + +/* structures used by regular expression matching machinery, mostly b.c: */ -#define NCHARS (256+1) +/* 256 handles 8-bit chars; 128 does 7-bit */ +/* watch out in match(), etc. */ +#define NCHARS (256+3) #define NSTATES 32 typedef struct rrow { - int ltype; - int lval; + long ltype; /* long avoids pointer warnings on 64-bit */ + union { + int i; + Node *np; + uschar *up; + } lval; /* because Al stores a pointer in it! */ int *lfollow; } rrow; typedef struct fa { - uchar *restr; + uschar gototab[NSTATES][NCHARS]; + uschar out[NSTATES]; + uschar *restr; + int *posns[NSTATES]; int anchor; int use; - uchar gototab[NSTATES][NCHARS]; - int *posns[NSTATES]; - uchar out[NSTATES]; int initstat; int curstat; int accept; int reset; + /* re is variable: actual size set by calling malloc */ struct rrow re[1]; } fa; +/* lex.c */ +extern int yylex(void); +extern void startreg(void); +extern int input(void); +extern void unput(int); +extern void unputstr(const char *); +extern int yylook(void); +extern int yyback(int *, int); +extern int yyinput(void); + +/* parse.c */ +extern void defn(Cell *, Node *, Node *); +extern int ptoi(void *); +extern Node *itonp(int); +extern int isarg(const char *); + /* b.c */ -extern fa *makedfa(uchar *, int); -extern int nematch(fa *, uchar *); -extern int match(fa *, uchar *); -extern int pmatch(fa *, uchar *); +extern fa *makedfa(const char *, int); +extern int nematch(fa *, const char *); +extern int match(fa *, const char *); +extern int pmatch(fa *, const char *); /* lib.c */ -extern int isclvar(uchar *); -extern int is_number(uchar *); -extern void setclvar(uchar *); -extern int readrec(uchar **, size_t *, FILE *); + +extern void SYNTAX(const char *, ...); +extern void FATAL(const char *, ...) __attribute__((__noreturn__)); +extern void WARNING(const char *, ...); +extern void error(void); +extern void nextfile(void); +extern void savefs(void); + +extern int isclvar(const char *); +extern int is_number(const char *); +extern void setclvar(char *); +extern int readrec(char **, size_t *, FILE *); extern void bracecheck(void); +extern void recinit(unsigned int n); extern void syminit(void); -extern void yyerror(char *); +extern void yyerror(const char *); extern void fldbld(void); extern void recbld(void); -extern int getrec(uchar **, size_t *); +extern int getrec(char **, size_t *, int); extern Cell *fieldadr(int); extern void newfld(int); -extern Cell *getfld(int); extern int fldidx(Cell *); -extern double errcheck(double, char *); +extern double errcheck(double, const char *); extern void fpecatch(int); -extern void init_buf(uchar **, size_t *, size_t); -extern void adjust_buf(uchar **, size_t); -extern void r_expand_buf(uchar **, size_t *, size_t); - -extern int donefld; -extern int donerec; -extern uchar *record; -extern size_t record_size; +extern void r_expand_buf(char **, size_t *, size_t); +extern void makefields(int, int); +extern void growfldtab(int n); +extern void setlastfld(int n); /* main.c */ extern int dbg; -extern uchar *cmdname; -extern uchar *lexprog; +extern char *lexprog; extern int compile_time; -extern char radixpoint; +extern char *cursource(void); +extern int pgetc(void); /* tran.c */ extern void syminit(void); -extern void arginit(int, uchar **); -extern void envinit(uchar **); +extern void arginit(int, char **); +extern void envinit(char **); extern void freesymtab(Cell *); -extern void freeelem(Cell *, uchar *); -extern void funnyvar(Cell *, char *); -extern int hash(uchar *, int); +extern void freeelem(Cell *, const char *); +extern void funnyvar(Cell *, const char *); +extern int hash(const char *, int); extern Awkfloat *ARGC; /* run.c */ -extern void run(Node *); +extern void run(Node *); +extern const char *filename(FILE *); +extern int adjbuf(char **pb, size_t *sz, size_t min, size_t q, + char **pbp, const char *what); extern int paircnt; extern Node *winner; @@ -336,7 +406,7 @@ extern Cell *substr(Node **, int); extern Cell *sub(Node **, int); extern Cell *gsub(Node **, int); extern Cell *sindex(Node **, int); -extern Cell *a_sprintf(Node **, int); +extern Cell *awksprintf(Node **, int); extern Cell *arith(Node **, int); extern Cell *incrdecr(Node **, int); extern Cell *cat(Node **, int); @@ -344,10 +414,10 @@ extern Cell *pastat(Node **, int); extern Cell *dopa2(Node **, int); extern Cell *matchop(Node **, int); extern Cell *intest(Node **, int); -extern Cell *aprintf(Node **, int); -extern Cell *print(Node **, int); +extern Cell *awkprintf(Node **, int); +extern Cell *printstat(Node **, int); extern Cell *closefile(Node **, int); -extern Cell *delete(Node **, int); +extern Cell *awkdelete(Node **, int); extern Cell *split(Node **, int); extern Cell *assign(Node **, int); extern Cell *condexpr(Node **, int); @@ -361,6 +431,6 @@ extern Cell *bltin(Node **, int); extern Cell *call(Node **, int); extern Cell *arg(Node **, int); extern Cell *getnf(Node **, int); -extern Cell *getaline(Node **, int); +extern Cell *awkgetline(Node **, int); #endif /* AWK_H */ diff --git a/usr/src/cmd/awk/awk.lx.l b/usr/src/cmd/awk/awk.lx.l deleted file mode 100644 index a7e8185832..0000000000 --- a/usr/src/cmd/awk/awk.lx.l +++ /dev/null @@ -1,306 +0,0 @@ -%{ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ -%} - -%{ -#pragma ident "%Z%%M% %I% %E% SMI" -%} - -%Start A str sc reg comment - -%{ - -#include <sys/types.h> -#include "awk.h" -#include "y.tab.h" - -#undef input /* defeat lex */ -#undef unput - -static void unput(int); -static void unputstr(char *); - -extern YYSTYPE yylval; -extern int infunc; - -off_t 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 - -/* - * The standards (SUSV2) requires that Record size be atleast LINE_MAX. - * LINE_MAX is a standard variable defined in limits.h. - * Though nawk is not standards compliant, we let RECSIZE - * grow with LINE_MAX instead of the magic number 1024. - */ -#define CBUFLEN (3 * LINE_MAX) - -#define CADD cbuf[clen++] = yytext[0]; \ - if (clen >= CBUFLEN-1) { \ - ERROR "string/reg expr %.10s... too long", cbuf SYNTAX; \ - BEGIN A; \ - } - -static uchar cbuf[CBUFLEN]; -static uchar *s; -static int clen, 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((uchar *)yytext+1, - (uchar *)"",0.0,STR|NUM,symtab); - RET(IVAR); - } - } -<A>"$" { RET(INDIRECT); } -<A>NF { yylval.cp = setsymtab((uchar *)yytext, (uchar *)"", 0.0, NUM, symtab); RET(VARNF); } - -<A>({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)? { - yylval.cp = setsymtab((uchar *)yytext, tostring((uchar *)yytext), atof(yytext), CON|NUM, symtab); - 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>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>{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((uchar *)yytext, - (uchar *)"",0.0,STR|NUM,symtab); - if (c == '(') { - RET(CALL); - } else { - RET(VAR); - } - } - } -<A>\" { BEGIN str; clen = 0; } - -<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>\\. { cbuf[clen++] = '\\'; cbuf[clen++] = yytext[1]; } -<reg>\n { ERROR "newline in regular expression %.10s...", cbuf SYNTAX; lineno++; BEGIN A; } -<reg>"/" { BEGIN A; - cbuf[clen] = 0; - yylval.s = tostring(cbuf); - unput('/'); - RET(REGEXPR); } -<reg>. { CADD; } - -<str>\" { BEGIN A; - cbuf[clen] = 0; s = tostring(cbuf); - cbuf[clen] = ' '; cbuf[++clen] = 0; - yylval.cp = setsymtab(cbuf, s, 0.0, CON|STR, symtab); - RET(STRING); } -<str>\n { ERROR "newline in string %.10s...", cbuf SYNTAX; lineno++; BEGIN A; } -<str>"\\\"" { cbuf[clen++] = '"'; } -<str>"\\"n { cbuf[clen++] = '\n'; } -<str>"\\"t { cbuf[clen++] = '\t'; } -<str>"\\"f { cbuf[clen++] = '\f'; } -<str>"\\"r { cbuf[clen++] = '\r'; } -<str>"\\"b { cbuf[clen++] = '\b'; } -<str>"\\"v { cbuf[clen++] = '\v'; } /* these ANSIisms may not be known by */ -<str>"\\"a { cbuf[clen++] = '\007'; } /* your compiler. hence 007 for bell */ -<str>"\\\\" { cbuf[clen++] = '\\'; } -<str>"\\"({O}{O}{O}|{O}{O}|{O}) { int n; - sscanf(yytext+1, "%o", &n); cbuf[clen++] = n; } -<str>"\\"x({H}+) { int n; /* ANSI permits any number! */ - sscanf(yytext+2, "%x", &n); cbuf[clen++] = n; } -<str>"\\". { cbuf[clen++] = yytext[1]; } -<str>. { CADD; } - -%% - -void -startreg() -{ - BEGIN reg; - clen = 0; -} - -/* 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. -*/ - -uchar ebuf[300]; -uchar *ep = ebuf; - -int -input(void) -{ - register int c; - extern uchar *lexprog; - - if (yysptr > yysbuf) - c = U(*--yysptr); - else if (lexprog != NULL) /* awk '...' */ - c = *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; -} - -static void -unput(int c) -{ - yytchar = c; - if (yytchar == '\n') - yylineno--; - *yysptr++ = yytchar; - if (--ep < ebuf) - ep = ebuf + sizeof(ebuf) - 1; -} - - -static void -unputstr(char *s) -{ - int i; - - for (i = strlen(s)-1; i >= 0; i--) - unput(s[i]); -} diff --git a/usr/src/cmd/awk/b.c b/usr/src/cmd/awk/b.c index 9caee4e9d3..adca0cb633 100644 --- a/usr/src/cmd/awk/b.c +++ b/usr/src/cmd/awk/b.c @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -28,6 +52,8 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ +/* lasciate ogne speranza, voi ch'intrate. */ + #define DEBUG #include "awk.h" @@ -37,74 +63,86 @@ /* NCHARS is 2**n */ #define MAXLIN (3 * LINE_MAX) -#define type(v) (v)->nobj +#define type(v) (v)->nobj /* badly overloaded here */ +#define info(v) (v)->ntype /* badly overloaded here */ #define left(v) (v)->narg[0] #define right(v) (v)->narg[1] #define parent(v) (v)->nnext #define LEAF case CCL: case NCCL: case CHAR: case DOT: case FINAL: case ALL: +#define ELEAF case EMPTYRE: /* empty string in regexp */ #define UNARY case STAR: case PLUS: case QUEST: /* * encoding in tree Nodes: - * leaf (CCL, NCCL, CHAR, DOT, FINAL, ALL): + * leaf (CCL, NCCL, CHAR, DOT, FINAL, ALL, EMPTYRE): * left is index, right contains value or pointer to value * unary (STAR, PLUS, QUEST): left is child, right is null * binary (CAT, OR): left and right are children * parent contains pointer to parent */ -int setvec[MAXLIN]; -int tmpset[MAXLIN]; -Node *point[MAXLIN]; +int *setvec; +int *tmpset; +int maxsetvec = 0; int rtok; /* next token in current re */ int rlxval; -uchar *rlxstr; -uchar *prestr; /* current position in current re */ -uchar *lastre; /* origin of last re */ +static uschar *rlxstr; +static uschar *prestr; /* current position in current re */ +static uschar *lastre; /* origin of last re */ static int setcnt; static int poscnt; -uchar *patbeg; +char *patbeg; int patlen; #define NFA 20 /* cache this many dynamic fa's */ fa *fatab[NFA]; int nfatab = 0; /* entries in fatab */ -static fa *mkdfa(uchar *, int); +static fa *mkdfa(const char *, int); static int makeinit(fa *, int); static void penter(Node *); static void freetr(Node *); -static void overflo(char *); +static void overflo(const char *); +static void growvec(const char *); static void cfoll(fa *, Node *); static void follow(Node *); -static Node *reparse(uchar *); +static Node *reparse(const char *); static int relex(void); static void freefa(fa *); static int cgoto(fa *, int, int); fa * -makedfa(uchar *s, int anchor) /* returns dfa for reg expr s */ +makedfa(const char *s, int anchor) /* returns dfa for reg expr s */ { int i, use, nuse; fa *pfa; + static int now = 1; + + if (setvec == NULL) { /* first time through any RE */ + maxsetvec = MAXLIN; + setvec = (int *)malloc(maxsetvec * sizeof (int)); + tmpset = (int *)malloc(maxsetvec * sizeof (int)); + if (setvec == NULL || tmpset == NULL) + overflo("out of space initializing makedfa"); + } if (compile_time) /* a constant for sure */ return (mkdfa(s, anchor)); for (i = 0; i < nfatab; i++) { /* is it there already? */ if (fatab[i]->anchor == anchor && - strcmp((char *)fatab[i]->restr, (char *)s) == 0) { - fatab[i]->use++; + strcmp((const char *)fatab[i]->restr, s) == 0) { + fatab[i]->use = now++; return (fatab[i]); } } pfa = mkdfa(s, anchor); if (nfatab < NFA) { /* room for another */ fatab[nfatab] = pfa; - fatab[nfatab]->use = 1; + fatab[nfatab]->use = now++; nfatab++; return (pfa); } @@ -117,13 +155,16 @@ makedfa(uchar *s, int anchor) /* returns dfa for reg expr s */ } freefa(fatab[nuse]); fatab[nuse] = pfa; - pfa->use = 1; + pfa->use = now++; return (pfa); } +/* + * does the real work of making a dfa + * anchor = 1 for anchored matches, else 0 + */ fa * -mkdfa(uchar *s, int anchor) /* does the real work of making a dfa */ - /* anchor = 1 for anchored matches, else 0 */ +mkdfa(const char *s, int anchor) { Node *p, *p1; fa *f; @@ -137,7 +178,7 @@ mkdfa(uchar *s, int anchor) /* does the real work of making a dfa */ poscnt = 0; penter(p1); /* enter parent pointers and leaf indices */ if ((f = (fa *)calloc(1, sizeof (fa) + poscnt * sizeof (rrow))) == NULL) - overflo("no room for fa"); + overflo("out of space for fa"); /* penter has computed number of positions in re */ f->accept = poscnt-1; cfoll(f, p1); /* set up follow sets */ @@ -151,14 +192,14 @@ mkdfa(uchar *s, int anchor) /* does the real work of making a dfa */ *f->posns[1] = 0; f->initstat = makeinit(f, anchor); f->anchor = anchor; - f->restr = tostring(s); + f->restr = (uschar *)tostring(s); return (f); } static int makeinit(fa *f, int anchor) { - register int i, k; + int i, k; f->curstat = 2; f->out[2] = 0; @@ -192,9 +233,10 @@ void penter(Node *p) /* set up parent pointers and leaf indices */ { switch (type(p)) { + ELEAF LEAF - left(p) = (Node *) poscnt; - point[poscnt++] = p; + info(p) = poscnt; + poscnt++; break; UNARY penter(left(p)); @@ -207,8 +249,8 @@ penter(Node *p) /* set up parent pointers and leaf indices */ parent(left(p)) = p; parent(right(p)) = p; break; - default: - ERROR "unknown type %d in penter", type(p) FATAL; + default: /* can't happen */ + FATAL("can't happen: unknown type %d in penter", type(p)); break; } } @@ -217,6 +259,7 @@ static void freetr(Node *p) /* free parse tree */ { switch (type(p)) { + ELEAF LEAF xfree(p); break; @@ -230,92 +273,168 @@ freetr(Node *p) /* free parse tree */ freetr(right(p)); xfree(p); break; - default: - ERROR "unknown type %d in freetr", type(p) FATAL; + default: /* can't happen */ + FATAL("can't happen: unknown type %d in freetr", type(p)); break; } } -uchar * -cclenter(uchar *p) +static void +growvec(const char *msg) +{ + maxsetvec *= 4; + setvec = (int *)realloc(setvec, maxsetvec * sizeof (int)); + tmpset = (int *)realloc(tmpset, maxsetvec * sizeof (int)); + if (setvec == NULL || tmpset == NULL) + overflo(msg); +} + +/* + * in the parsing of regular expressions, metacharacters like . have + * to be seen literally; \056 is not a metacharacter. + */ + +/* + * find and eval hex string at pp, return new p; only pick up one 8-bit + * byte (2 chars). + */ +int +hexstr(uschar **pp) +{ + uschar *p; + int n = 0; + int i; + + for (i = 0, p = (uschar *)*pp; i < 2 && isxdigit(*p); i++, p++) { + if (isdigit(*p)) + n = 16 * n + *p - '0'; + else if (*p >= 'a' && *p <= 'f') + n = 16 * n + *p - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') + n = 16 * n + *p - 'A' + 10; + } + *pp = (uschar *)p; + return (n); +} + +#define isoctdigit(c) ((c) >= '0' && (c) <= '7') + +/* pick up next thing after a \\ and increment *pp */ +int +quoted(uschar **pp) { - register int i, c; - uchar *op, *chars, *ret; - size_t bsize; + uschar *p = *pp; + int c; + + if ((c = *p++) == 't') + c = '\t'; + else if (c == 'n') + c = '\n'; + else if (c == 'f') + c = '\f'; + else if (c == 'r') + c = '\r'; + else if (c == 'b') + c = '\b'; + else if (c == '\\') + c = '\\'; + else if (c == 'x') { /* hexadecimal goo follows */ + c = hexstr(&p); /* this adds a null if number is invalid */ + } else if (isoctdigit(c)) { /* \d \dd \ddd */ + int n = c - '0'; + if (isoctdigit(*p)) { + n = 8 * n + *p++ - '0'; + if (isoctdigit(*p)) + n = 8 * n + *p++ - '0'; + } + c = n; + } /* else */ + /* c = c; */ + *pp = p; + return (c); +} + +char * +cclenter(const char *argp) /* add a character class */ +{ + int i, c, c2; + uschar *p = (uschar *)argp; + uschar *op, *bp; + static uschar *buf = NULL; + static size_t bufsz = 100; - init_buf(&chars, &bsize, LINE_INCR); op = p; - i = 0; - while ((c = *p++) != 0) { + if (buf == NULL && (buf = (uschar *)malloc(bufsz)) == NULL) + FATAL("out of space for character class [%.10s...] 1", p); + bp = buf; + for (i = 0; (c = *p++) != 0; ) { if (c == '\\') { - if ((c = *p++) == 't') - c = '\t'; - else if (c == 'n') - c = '\n'; - else if (c == 'f') - c = '\f'; - else if (c == 'r') - c = '\r'; - else if (c == 'b') - c = '\b'; - else if (c == '\\') - c = '\\'; - else if (isdigit(c)) { - int n = c - '0'; - if (isdigit(*p)) { - n = 8 * n + *p++ - '0'; - if (isdigit(*p)) - n = 8 * n + *p++ - '0'; - } - c = n; - } /* else */ - /* c = c; */ - } else if (c == '-' && i > 0 && chars[i-1] != 0) { + c = quoted(&p); + } else if (c == '-' && i > 0 && bp[-1] != 0) { if (*p != 0) { - c = chars[i-1]; - while ((uchar)c < *p) { /* fails if *p is \\ */ - expand_buf(&chars, &bsize, i); - chars[i++] = ++c; + c = bp[-1]; + c2 = *p++; + if (c2 == '\\') + c2 = quoted(&p); + if (c > c2) { /* empty; ignore */ + bp--; + i--; + continue; + } + while (c < c2) { + if (!adjbuf((char **)&buf, &bufsz, + bp-buf+2, 100, (char **)&bp, + "cclenter1")) { + FATAL( + "out of space for character class [%.10s...] 2", p); + } + *bp++ = ++c; + i++; } - p++; continue; } } - expand_buf(&chars, &bsize, i); - chars[i++] = c; + if (!adjbuf((char **)&buf, &bufsz, bp-buf+2, 100, (char **)&bp, + "cclenter2")) + FATAL( + "out of space for character class [%.10s...] 3", p); + *bp++ = c; + i++; } - chars[i++] = '\0'; - dprintf(("cclenter: in = |%s|, out = |%s|\n", op, chars)); + *bp = '\0'; + dprintf(("cclenter: in = |%s|, out = |%s|\n", op, buf)); xfree(op); - ret = tostring(chars); - free(chars); - return (ret); + return ((char *)tostring((char *)buf)); } static void -overflo(char *s) +overflo(const char *s) { - ERROR "regular expression too big: %s", gettext((char *)s) FATAL; + FATAL("regular expression too big: %.30s...", gettext((char *)s)); } /* enter follow set of each leaf of vertex v into lfollow[leaf] */ static void cfoll(fa *f, Node *v) { - register int i; - register int *p; + int i; + int *p; switch (type(v)) { + ELEAF LEAF - f->re[(int)left(v)].ltype = type(v); - f->re[(int)left(v)].lval = (int)right(v); + f->re[info(v)].ltype = type(v); + f->re[info(v)].lval.np = right(v); + while (f->accept >= maxsetvec) { /* guessing here! */ + growvec("out of space in cfoll()"); + } for (i = 0; i <= f->accept; i++) setvec[i] = 0; setcnt = 0; follow(v); /* computes setvec and setcnt */ if ((p = (int *)calloc(1, (setcnt+1) * sizeof (int))) == NULL) - overflo("follow set overflow"); - f->re[(int)left(v)].lfollow = p; + overflo("out of space building follow set"); + f->re[info(v)].lfollow = p; *p = setcnt; for (i = f->accept; i >= 0; i--) { if (setvec[i] == 1) @@ -330,8 +449,8 @@ cfoll(fa *f, Node *v) cfoll(f, left(v)); cfoll(f, right(v)); break; - default: - ERROR "unknown type %d in cfoll", type(v) FATAL; + default: /* can't happen */ + FATAL("can't happen: unknown type %d in cfoll", type(v)); } } @@ -342,15 +461,25 @@ cfoll(fa *f, Node *v) static int first(Node *p) { - register int b; + int b, lp; switch (type(p)) { + ELEAF LEAF - if (setvec[(int)left(p)] != 1) { - setvec[(int)left(p)] = 1; + lp = info(p); /* look for high-water mark of subscripts */ + while (setcnt >= maxsetvec || lp >= maxsetvec) { + /* guessing here! */ + growvec("out of space in first()"); + } + if (type(p) == EMPTYRE) { + setvec[lp] = 0; + return (0); + } + if (setvec[lp] != 1) { + setvec[lp] = 1; setcnt++; } - if (type(p) == CCL && (*(uchar *)right(p)) == '\0') + if (type(p) == CCL && (*(char *)right(p)) == '\0') return (0); /* empty CCL */ else return (1); @@ -372,8 +501,7 @@ first(Node *p) return (0); return (1); } - ERROR "unknown type %d in first", type(p) FATAL; - return (-1); + FATAL("can't happen: unknown type %d in first", type(p)); } /* collects leaves that can follow v into setvec */ @@ -407,14 +535,16 @@ follow(Node *v) follow(p); return; default: - ERROR "unknown type %d in follow", type(p) FATAL; + FATAL("unknown type %d in follow", type(p)); break; } } static int -member(uchar c, uchar *s) /* is c in s? */ +member(int c, const char *sarg) /* is c in s? */ { + uschar *s = (uschar *)sarg; + while (*s) if (c == *s++) return (1); @@ -423,9 +553,10 @@ member(uchar c, uchar *s) /* is c in s? */ int -match(fa *f, uchar *p) +match(fa *f, const char *p0) /* shortest match ? */ { - register int s, ns; + int s, ns; + uschar *p = (uschar *)p0; s = f->reset ? makeinit(f, 0) : f->initstat; if (f->out[s]) @@ -442,10 +573,11 @@ match(fa *f, uchar *p) } int -pmatch(fa *f, uchar *p) +pmatch(fa *f, const char *p0) /* longest match, for sub */ { - register int s, ns; - register uchar *q; + int s, ns; + uschar *p = (uschar *)p0; + uschar *q; int i, k; if (f->reset) { @@ -453,7 +585,7 @@ pmatch(fa *f, uchar *p) } else { s = f->initstat; } - patbeg = p; + patbeg = (char *)p; patlen = -1; do { q = p; @@ -466,16 +598,17 @@ pmatch(fa *f, uchar *p) s = cgoto(f, s, *q); if (s == 1) { /* no transition */ if (patlen >= 0) { - patbeg = p; + patbeg = (char *)p; return (1); - } else + } else { goto nextin; /* no match */ + } } } while (*q++ != 0); if (f->out[s]) patlen = q - p - 1; /* don't count $ */ if (patlen >= 0) { - patbeg = p; + patbeg = (char *)p; return (1); } nextin: @@ -485,7 +618,7 @@ pmatch(fa *f, uchar *p) xfree(f->posns[i]); k = *f->posns[0]; if ((f->posns[2] = - (int *)calloc(1, (k + 1) * sizeof (int))) == NULL) { + (int *)calloc(k + 1, sizeof (int))) == NULL) { overflo("out of space in pmatch"); } for (i = 0; i <= k; i++) @@ -500,10 +633,11 @@ pmatch(fa *f, uchar *p) } int -nematch(fa *f, uchar *p) +nematch(fa *f, const char *p0) /* non-empty match, for sub */ { - register int s, ns; - register uchar *q; + int s, ns; + uschar *p = (uschar *)p0; + uschar *q; int i, k; if (f->reset) { @@ -523,7 +657,7 @@ nematch(fa *f, uchar *p) s = cgoto(f, s, *q); if (s == 1) { /* no transition */ if (patlen > 0) { - patbeg = p; + patbeg = (char *)p; return (1); } else goto nnextin; /* no nonempty match */ @@ -532,7 +666,7 @@ nematch(fa *f, uchar *p) if (f->out[s]) patlen = q - p - 1; /* don't count $ */ if (patlen > 0) { - patbeg = p; + patbeg = (char *)p; return (1); } nnextin: @@ -542,7 +676,7 @@ nematch(fa *f, uchar *p) xfree(f->posns[i]); k = *f->posns[0]; if ((f->posns[2] = - (int *)calloc(1, (k + 1) * sizeof (int))) == NULL) { + (int *)calloc(k + 1, sizeof (int))) == NULL) { overflo("out of state space"); } for (i = 0; i <= k; i++) @@ -560,31 +694,31 @@ nematch(fa *f, uchar *p) static Node *regexp(void), *primary(void), *concat(Node *); static Node *alt(Node *), *unary(Node *); +/* parses regular expression pointed to by p */ +/* uses relex() to scan regular expression */ static Node * -reparse(uchar *p) +reparse(const char *p) { - /* parses regular expression pointed to by p */ - /* uses relex() to scan regular expression */ Node *np; dprintf(("reparse <%s>\n", p)); - lastre = prestr = p; /* prestr points to string to be parsed */ + + /* prestr points to string to be parsed */ + lastre = prestr = (uschar *)p; rtok = relex(); - if (rtok == '\0') - ERROR "empty regular expression" FATAL; - np = regexp(); + /* GNU compatibility: an empty regexp matches anything */ if (rtok == '\0') { - return (np); - } else { - ERROR "syntax error in regular expression %s at %s", - lastre, prestr FATAL; + return (op2(EMPTYRE, NIL, NIL)); } - /*NOTREACHED*/ - return (NULL); + np = regexp(); + if (rtok != '\0') + FATAL("syntax error in regular expression %s at %s", + lastre, prestr); + return (np); } static Node * -regexp(void) +regexp(void) /* top-level parse of reg expr */ { return (alt(concat(primary()))); } @@ -596,28 +730,31 @@ primary(void) switch (rtok) { case CHAR: - np = op2(CHAR, NIL, (Node *)rlxval); + np = op2(CHAR, NIL, itonp(rlxval)); rtok = relex(); return (unary(np)); case ALL: rtok = relex(); return (unary(op2(ALL, NIL, NIL))); + case EMPTYRE: + rtok = relex(); + return (unary(op2(ALL, NIL, NIL))); case DOT: rtok = relex(); return (unary(op2(DOT, NIL, NIL))); case CCL: /*LINTED align*/ - np = op2(CCL, NIL, (Node *)cclenter(rlxstr)); + np = op2(CCL, NIL, (Node *)cclenter((char *)rlxstr)); rtok = relex(); return (unary(np)); case NCCL: /*LINTED align*/ - np = op2(NCCL, NIL, (Node *)cclenter(rlxstr)); + np = op2(NCCL, NIL, (Node *)cclenter((char *)rlxstr)); rtok = relex(); return (unary(np)); case '^': rtok = relex(); - return (unary(op2(CHAR, NIL, (Node *)HAT))); + return (unary(op2(CHAR, NIL, itonp(HAT)))); case '$': rtok = relex(); return (unary(op2(CHAR, NIL, NIL))); @@ -627,20 +764,20 @@ primary(void) rtok = relex(); return (unary(op2(CCL, NIL, /*LINTED align*/ - (Node *)tostring((uchar *)"")))); + (Node *)tostring("")))); } np = regexp(); if (rtok == ')') { rtok = relex(); return (unary(np)); } else { - ERROR "syntax error in regular expression %s at %s", - lastre, prestr FATAL; + FATAL("syntax error in regular expression %s at %s", + lastre, prestr); } /* FALLTHROUGH */ default: - ERROR "illegal primary in regular expression %s at %s", - lastre, prestr FATAL; + FATAL("illegal primary in regular expression %s at %s", + lastre, prestr); } /*NOTREACHED*/ return (NULL); @@ -650,7 +787,14 @@ static Node * concat(Node *np) { switch (rtok) { - case CHAR: case DOT: case ALL: case CCL: case NCCL: case '$': case '(': + case EMPTYRE: + case CHAR: + case DOT: + case ALL: + case CCL: + case NCCL: + case '$': + case '(': return (concat(op2(CAT, np, primary()))); default: return (np); @@ -685,12 +829,48 @@ unary(Node *np) } } +/* + * Character class definitions conformant to the POSIX locale as + * defined in IEEE P1003.1 draft 7 of June 2001, assuming the source + * and operating character sets are both ASCII (ISO646) or supersets + * thereof. + * + * Note that to avoid overflowing the temporary buffer used in + * relex(), the expanded character class (prior to range expansion) + * must be less than twice the size of their full name. + */ + +struct charclass { + const char *cc_name; + int cc_namelen; + int (*cc_func)(int); +} charclasses[] = { + { "alnum", 5, isalnum }, + { "alpha", 5, isalpha }, + { "blank", 5, isblank }, + { "cntrl", 5, iscntrl }, + { "digit", 5, isdigit }, + { "graph", 5, isgraph }, + { "lower", 5, islower }, + { "print", 5, isprint }, + { "punct", 5, ispunct }, + { "space", 5, isspace }, + { "upper", 5, isupper }, + { "xdigit", 6, isxdigit }, + { NULL, 0, NULL }, +}; + + static int relex(void) /* lexical analyzer for reparse */ { - register int c; - uchar *cbuf; - int clen, cflag; + int c, n; + int cflag; + static uschar *buf = 0; + static size_t bufsz = 100; + uschar *bp; + struct charclass *cc; + int i; switch (c = *prestr++) { case '|': return OR; @@ -705,64 +885,82 @@ relex(void) /* lexical analyzer for reparse */ case ')': return (c); case '\\': - if ((c = *prestr++) == 't') - c = '\t'; - else if (c == 'n') - c = '\n'; - else if (c == 'f') - c = '\f'; - else if (c == 'r') - c = '\r'; - else if (c == 'b') - c = '\b'; - else if (c == '\\') - c = '\\'; - else if (isdigit(c)) { - int n = c - '0'; - if (isdigit(*prestr)) { - n = 8 * n + *prestr++ - '0'; - if (isdigit(*prestr)) - n = 8 * n + *prestr++ - '0'; - } - c = n; - } /* else it's now in c */ - rlxval = c; + rlxval = quoted(&prestr); return (CHAR); default: rlxval = c; return (CHAR); case '[': - clen = 0; + if (buf == NULL && (buf = (uschar *)malloc(bufsz)) == NULL) + FATAL("out of space in reg expr %.10s..", lastre); + bp = buf; if (*prestr == '^') { cflag = 1; prestr++; } else cflag = 0; - init_buf(&cbuf, NULL, strlen((char *)prestr) * 2 + 1); + n = 2 * strlen((const char *)prestr) + 1; + if (!adjbuf((char **)&buf, &bufsz, n, n, (char **)&bp, + "relex1")) + FATAL("out of space for reg expr %.10s...", lastre); for (;;) { if ((c = *prestr++) == '\\') { - cbuf[clen++] = '\\'; + *bp++ = '\\'; if ((c = *prestr++) == '\0') { - ERROR - "nonterminated character class %s", lastre FATAL; + FATAL("nonterminated character class " + "%.20s...", lastre); + } + *bp++ = c; + } else if (c == '[' && *prestr == ':') { + /* + * Handle POSIX character class names. + * Dag-Erling Smorgrav, des@ofug.org + */ + for (cc = charclasses; cc->cc_name; cc++) + if (strncmp((const char *)prestr + 1, + (const char *)cc->cc_name, + cc->cc_namelen) == 0) + break; + + if (cc->cc_name == NULL || + prestr[1 + cc->cc_namelen] != ':' || + prestr[2 + cc->cc_namelen] != ']') { + *bp++ = c; + continue; } - cbuf[clen++] = c; + + prestr += cc->cc_namelen + 3; + /* + * BUG: We begin at 1, instead of 0, since we + * would otherwise prematurely terminate the + * string for classes like [[:cntrl:]]. This + * means that we can't match the NUL character, + * not without first adapting the entire + * program to track each string's length. + */ + for (i = 1; i < NCHARS; i++) { + (void) adjbuf((char **)&buf, &bufsz, + bp - buf + 1, 100, (char **)&bp, + "relex2"); + if (cc->cc_func(i)) { + *bp++ = i; + n++; + } + } + } else if (c == '\0') { + FATAL("nonterminated character class %.20s", + lastre); + } else if (bp == buf) { /* 1st char is special */ + *bp++ = c; } else if (c == ']') { - cbuf[clen] = 0; - rlxstr = tostring(cbuf); - free(cbuf); + *bp++ = '\0'; + rlxstr = (uschar *)tostring((char *)buf); if (cflag == 0) return (CCL); else return (NCCL); - } else if (c == '\n') { - ERROR "newline in character class %s...", - lastre FATAL; - } else if (c == '\0') { - ERROR "nonterminated character class %s", - lastre FATAL; } else - cbuf[clen++] = c; + *bp++ = c; } /*NOTREACHED*/ } @@ -772,9 +970,13 @@ relex(void) /* lexical analyzer for reparse */ static int cgoto(fa *f, int s, int c) { - register int i, j, k; - register int *p, *q; + int i, j, k; + int *p, *q; + assert(c == HAT || c < NCHARS); + while (f->accept >= maxsetvec) { /* guessing here! */ + growvec("out of space in cgoto()"); + } for (i = 0; i <= f->accept; i++) setvec[i] = 0; setcnt = 0; @@ -782,16 +984,20 @@ cgoto(fa *f, int s, int c) p = f->posns[s]; for (i = 1; i <= *p; i++) { if ((k = f->re[p[i]].ltype) != FINAL) { - if (k == CHAR && c == f->re[p[i]].lval || - k == DOT && c != 0 && c != HAT || - k == ALL && c != 0 || - k == CCL && - member(c, (uchar *)f->re[p[i]].lval) || - k == NCCL && - !member(c, (uchar *)f->re[p[i]].lval) && - c != 0 && c != HAT) { + if ((k == CHAR && c == ptoi(f->re[p[i]].lval.np)) || + (k == DOT && c != 0 && c != HAT) || + (k == ALL && c != 0) || + (k == EMPTYRE && c != 0) || + (k == CCL && + member(c, (char *)f->re[p[i]].lval.up)) || + (k == NCCL && + !member(c, (char *)f->re[p[i]].lval.up) && + c != 0 && c != HAT)) { q = f->re[p[i]].lfollow; for (j = 1; j <= *q; j++) { + if (q[j] >= maxsetvec) { + growvec("cgoto overflow"); + } if (setvec[q[j]] == 0) { setcnt++; setvec[q[j]] = 1; @@ -847,17 +1053,19 @@ cgoto(fa *f, int s, int c) } static void -freefa(fa *f) +freefa(fa *f) /* free a finite automaton */ { - - register int i; + int i; if (f == NULL) return; for (i = 0; i <= f->curstat; i++) xfree(f->posns[i]); - for (i = 0; i <= f->accept; i++) + for (i = 0; i <= f->accept; i++) { xfree(f->re[i].lfollow); + if (f->re[i].ltype == CCL || f->re[i].ltype == NCCL) + xfree((f->re[i].lval.np)); + } xfree(f->restr); xfree(f); } diff --git a/usr/src/cmd/awk/lex.c b/usr/src/cmd/awk/lex.c new file mode 100644 index 0000000000..ad0575f3cb --- /dev/null +++ b/usr/src/cmd/awk/lex.c @@ -0,0 +1,637 @@ +/* + * 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 "y.tab.h" + +extern YYSTYPE yylval; +extern int infunc; + +off_t lineno = 1; +int bracecnt = 0; +int brackcnt = 0; +int parencnt = 0; + +typedef struct Keyword { + const 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 RET(x) { if (dbg) (void) printf("lex %s\n", tokname(x)); return (x); } + +int +peek(void) +{ + int c = input(); + unput(c); + return (c); +} + +int +gettok(char **pbuf, size_t *psz) /* get next input token */ +{ + int c, retc; + char *buf = *pbuf; + size_t 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 && + !adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok")) + FATAL("out of space for name %.10s...", buf); + if (isalnum(c) || c == '_') + *bp++ = c; + else { + *bp = 0; + unput(c); + break; + } + } + *bp = 0; + retc = 'a'; /* alphanumeric */ + } else { /* maybe it's a number, but could be . */ + char *rem; + /* read input until can't be a number */ + for (; (c = input()) != 0; ) { + if (bp-buf >= sz && + !adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok")) + FATAL("out of space for number %.10s...", buf); + if (isdigit(c) || c == 'e' || c == 'E' || + c == '.' || c == '+' || c == '-') + *bp++ = c; + else { + unput(c); + break; + } + } + *bp = 0; + (void) strtod(buf, &rem); /* parse the number */ + if (rem == buf) { /* it wasn't a valid number at all */ + buf[1] = 0; /* return one character as token */ + retc = buf[0]; /* character is its own type */ + unputstr(rem+1); /* put rest back for later */ + } else { /* some prefix was a number */ + unputstr(rem); /* put rest back for later */ + rem[0] = 0; /* truncate buf after number part */ + retc = '0'; /* type is number */ + } + } + *pbuf = buf; + *psz = sz; + return (retc); +} + +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(void) +{ + int c; + static char *buf = NULL; + /* BUG: setting this small causes core dump! */ + static size_t bufsize = 5; + + if (buf == NULL && (buf = (char *)malloc(bufsize)) == NULL) + FATAL("out of space in yylex"); + 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)) { + 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} */ + lineno++; + 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') { + (void) input(); + lineno++; + } else if (peek() == '\r') { + (void) input(); + (void) input(); /* BUG: check for \n */ + lineno++; + } else { + RET(c); + } + break; + case '&': + if (peek() == '&') { + (void) input(); + RET(AND); + } else + RET('&'); + case '|': + if (peek() == '|') { + (void) input(); + RET(BOR); + } else + RET('|'); + case '!': + if (peek() == '=') { + (void) input(); + yylval.i = NE; + RET(NE); + } else if (peek() == '~') { + (void) input(); + yylval.i = NOTMATCH; + RET(MATCHOP); + } else + RET(NOT); + case '~': + yylval.i = MATCH; + RET(MATCHOP); + case '<': + if (peek() == '=') { + (void) input(); + yylval.i = LE; + RET(LE); + } else { + yylval.i = LT; + RET(LT); + } + case '=': + if (peek() == '=') { + (void) input(); + yylval.i = EQ; + RET(EQ); + } else { + yylval.i = ASSIGN; + RET(ASGNOP); + } + case '>': + if (peek() == '=') { + (void) input(); + yylval.i = GE; + RET(GE); + } else if (peek() == '>') { + (void) input(); + yylval.i = APPEND; + RET(APPEND); + } else { + yylval.i = GT; + RET(GT); + } + case '+': + if (peek() == '+') { + (void) input(); + yylval.i = INCR; + RET(INCR); + } else if (peek() == '=') { + (void) input(); + yylval.i = ADDEQ; + RET(ASGNOP); + } else + RET('+'); + case '-': + if (peek() == '-') { + (void) input(); + yylval.i = DECR; + RET(DECR); + } else if (peek() == '=') { + (void) input(); + yylval.i = SUBEQ; + RET(ASGNOP); + } else + RET('-'); + case '*': + if (peek() == '=') { /* *= */ + (void) input(); + yylval.i = MULTEQ; + RET(ASGNOP); + } else if (peek() == '*') { /* ** or **= */ + (void) input(); /* eat 2nd * */ + if (peek() == '=') { + (void) input(); + yylval.i = POWEQ; + RET(ASGNOP); + } else { + RET(POWER); + } + } else + RET('*'); + case '/': + RET('/'); + case '%': + if (peek() == '=') { + (void) input(); + yylval.i = MODEQ; + RET(ASGNOP); + } else + RET('%'); + case '^': + if (peek() == '=') { + (void) input(); + yylval.i = POWEQ; + RET(ASGNOP); + } else + RET(POWER); + + case '$': + /* BUG: awkward, if not wrong */ + c = gettok(&buf, &bufsize); + if (isalpha(c)) { + if (strcmp(buf, "NF") == 0) { + /* very special */ + unputstr("(NF)"); + RET(INDIRECT); + } + c = peek(); + if (c == '(' || c == '[' || + (infunc && isarg(buf) >= 0)) { + unputstr(buf); + RET(INDIRECT); + } + yylval.cp = setsymtab( + buf, "", 0.0, STR|NUM, symtab); + RET(IVAR); + } else if (c == 0) { /* */ + SYNTAX("unexpected end of input after $"); + RET(';'); + } else { + unputstr(buf); + RET(INDIRECT); + } + + case '}': + if (--bracecnt < 0) + SYNTAX("extra }"); + sc = 1; + RET(';'); + case ']': + if (--brackcnt < 0) + SYNTAX("extra ]"); + RET(']'); + case ')': + if (--parencnt < 0) + SYNTAX("extra )"); + RET(')'); + case '{': + bracecnt++; + RET('{'); + case '[': + brackcnt++; + RET('['); + case '(': + parencnt++; + RET('('); + + case '"': + /* BUG: should be like tran.c ? */ + return (string()); + + default: + RET(c); + } + } +} + +int +string(void) +{ + int c, n; + char *s, *bp; + static char *buf = NULL; + static size_t bufsz = 500; + + if (buf == NULL && (buf = (char *)malloc(bufsz)) == NULL) + FATAL("out of space for strings"); + for (bp = buf; (c = input()) != '"'; ) { + if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string")) + FATAL("out of space for string %.10s...", buf); + switch (c) { + case '\n': + case '\r': + case 0: + *bp = '\0'; + SYNTAX("non-terminated string %.10s...", buf); + if (c == 0) /* hopeless */ + FATAL("giving up"); + 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++ = '\007'; 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; + px = xbuf; + while ((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); + (void) sscanf(xbuf, "%x", (unsigned int *)&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])); + if (n != -1) { /* found in table */ + kp = keywords + n; + yylval.i = kp->sub; + switch (kp->type) { /* special handling */ + case BLTIN: + if (kp->sub == FSYSTEM && safe) + SYNTAX("system is unsafe"); + RET(kp->type); + case FUNC: + if (infunc) + SYNTAX("illegal nested function"); + RET(kp->type); + case RETURN: + if (!infunc) + SYNTAX("return not in function"); + 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 yylex will return a regular expression */ +{ + reg = 1; +} + +int +regexpr(void) +{ + int c; + static char *buf = NULL; + static size_t bufsz = 500; + char *bp; + + if (buf == NULL && (buf = (char *)malloc(bufsz)) == NULL) + FATAL("out of space for rex expr"); + bp = buf; + for (; (c = input()) != '/' && c != 0; ) { + if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr")) + FATAL("out of space for reg expr %.10s...", buf); + if (c == '\n') { + *bp = '\0'; + SYNTAX("newline in regular expression %.10s...", buf); + unput('\n'); + break; + } else if (c == '\\') { + *bp++ = '\\'; + *bp++ = input(); + } else { + *bp++ = c; + } + } + *bp = 0; + if (c == 0) + SYNTAX("non-terminated regular expression %.10s...", buf); + 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 = NULL; + +int +input(void) /* get next lexical input character */ +{ + int c; + extern char *lexprog; + + if (yysptr > yysbuf) + c = (uschar)*--yysptr; + else if (lexprog != NULL) { /* awk '...' */ + if ((c = (uschar)*lexprog) != 0) + lexprog++; + } else /* awk -f ... */ + c = pgetc(); + if (c == EOF) + c = 0; + if (ep >= ebuf + sizeof (ebuf)) + ep = ebuf; + *ep = c; + if (c != 0) { + ep++; + } + return (c); +} + +void +unput(int c) /* put lexical character back on input */ +{ + if (yysptr >= yysbuf + sizeof (yysbuf)) + FATAL("pushed back too much: %.20s...", yysbuf); + *yysptr++ = c; + if (--ep < ebuf) + ep = ebuf + sizeof (ebuf) - 1; +} + +void +unputstr(const 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/src/cmd/awk/lib.c b/usr/src/cmd/awk/lib.c index ded064c6c3..fedd5d5137 100644 --- a/usr/src/cmd/awk/lib.c +++ b/usr/src/cmd/awk/lib.c @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -27,63 +51,131 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* Copyright (c) Lucent Technologies 1997 */ +/* All Rights Reserved */ +#include <stdio.h> +#include <string.h> +#include <ctype.h> #include <errno.h> +#include <stdlib.h> +#include <stdarg.h> #include "awk.h" #include "y.tab.h" -uchar *record; -size_t record_size; - -int donefld; /* 1 = implies rec broken into fields */ -int donerec; /* 1 = record is valid (no flds have changed) */ +static FILE *infile = NULL; +static char *file = ""; +char *record; +size_t recsize = RECSIZE; +static char *fields; +static size_t fieldssize = RECSIZE; +static char *rtbuf; +static size_t rtbufsize = RECSIZE; -static struct fldtab_chunk { - struct fldtab_chunk *next; - Cell fields[FLD_INCR]; -} *fldtab_head, *fldtab_tail; +Cell **fldtab; /* pointers to Cells */ +char inputFS[100] = " "; -static size_t fldtab_maxidx; +#define MAXFLD 2 +int nfields = MAXFLD; /* last allocated slot for $i */ -static FILE *infile = NULL; -static uchar *file = (uchar*) ""; -static uchar *fields; -static size_t fields_size = LINE_INCR; +int donefld; /* 1 = implies rec broken into fields */ +int donerec; /* 1 = record is valid (no flds have changed) */ -static int maxfld = 0; /* last used field */ +static int lastfld = 0; /* last used field */ static int argno = 1; /* current input argument number */ -static uchar *getargv(int); +static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE }; +static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; + +static char *getargv(int); static void cleanfld(int, int); -static int refldbld(uchar *, uchar *); +static int refldbld(const char *, const char *); static void bcheck2(int, int, int); static void eprint(void); static void bclass(int); +void +recinit(unsigned int n) +{ + if ((record = (char *)malloc(n)) == NULL || + (fields = (char *)malloc(n+2)) == NULL || + (fldtab = (Cell **)malloc((nfields+1) * sizeof (Cell *))) == NULL || + (fldtab[0] = (Cell *)malloc(sizeof (Cell))) == NULL) + FATAL("out of space for $0 and fields"); + *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 (Cell)); + if (fldtab[i] == NULL) + FATAL("out of space in makefields %d", i); + *fldtab[i] = dollar1; + (void) sprintf(temp, "%d", i); + fldtab[i]->nval = tostring(temp); + } +} + static void initgetrec(void) { int i; - uchar *p; + char *p; for (i = 1; i < *ARGC; i++) { - if (!isclvar(p = getargv(i))) /* find 1st real filename */ + p = getargv(i); /* find 1st real filename */ + if (p == NULL || *p == '\0') { /* deleted or zapped */ + argno++; + continue; + } + if (!isclvar(p)) { + (void) setsval(lookup("FILENAME", symtab), p); return; + } setclvar(p); /* a commandline assignment before filename */ argno++; } infile = stdin; /* no filenames, so use stdin */ - /* *FILENAME = file = (uchar*) "-"; */ } +/* + * POSIX specifies that fields are supposed to be evaluated as if they were + * split using the value of FS at the time that the record's value ($0) was + * read. + * + * Since field-splitting is done lazily, we save the current value of FS + * whenever a new record is read in (implicitly or via getline), or when + * a new value is assigned to $0. + */ +void +savefs(void) +{ + if (strlen(getsval(fsloc)) >= sizeof (inputFS)) + FATAL("field separator %.10s... is too long", *FS); + (void) strcpy(inputFS, *FS); +} + +static int firsttime = 1; + +/* + * get next input record + * note: cares whether buf == record + */ int -getrec(uchar **bufp, size_t *bufsizep) +getrec(char **pbuf, size_t *pbufsize, int isrecord) { int c; - static int firsttime = 1; - uchar_t *buf, *nbuf; - size_t len; + char *buf = *pbuf; + uschar saveb0; + size_t bufsize = *pbufsize, savebufsize = bufsize; if (firsttime) { firsttime = 0; @@ -91,17 +183,24 @@ getrec(uchar **bufp, size_t *bufsizep) } dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n", *RS, *FS, *ARGC, *FILENAME)); - donefld = 0; - donerec = 1; + if (isrecord) { + donefld = 0; + donerec = 1; + savefs(); + } + saveb0 = buf[0]; + buf[0] = '\0'; while (argno < *ARGC || infile == stdin) { 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 */ + if (file == NULL || *file == '\0') { + /* deleted or zapped */ argno++; continue; } - if (isclvar(file)) { /* a var=value arg */ + if (isclvar(file)) { + /* a var=value arg */ setclvar(file); argno++; continue; @@ -110,31 +209,28 @@ getrec(uchar **bufp, size_t *bufsizep) dprintf(("opening file %s\n", file)); if (*file == '-' && *(file+1) == '\0') infile = stdin; - else if ((infile = fopen((char *)file, "r")) == NULL) - ERROR "can't open file %s", file FATAL; + else if ((infile = fopen(file, "rF")) == NULL) + FATAL("can't open file %s", file); (void) setfval(fnrloc, 0.0); } - c = readrec(&nbuf, &len, infile); - expand_buf(bufp, bufsizep, len); - buf = *bufp; - (void) memcpy(buf, nbuf, len); - buf[len] = '\0'; - free(nbuf); + c = readrec(&buf, &bufsize, infile); if (c != 0 || buf[0] != '\0') { /* normal record */ - if (bufp == &record) { - if (!(recloc->tval & DONTFREE)) + if (isrecord) { + if (freeable(recloc)) xfree(recloc->sval); - recloc->sval = record; + recloc->sval = buf; /* buf == record */ recloc->tval = REC | STR | DONTFREE; if (is_number(recloc->sval)) { recloc->fval = - atof((const char *)recloc->sval); + atof(recloc->sval); recloc->tval |= NUM; } } (void) setfval(nrloc, nrloc->fval+1); (void) setfval(fnrloc, fnrloc->fval+1); + *pbuf = buf; + *pbufsize = bufsize; return (1); } /* EOF arrived on this file; set up next */ @@ -143,19 +239,39 @@ getrec(uchar **bufp, size_t *bufsizep) infile = NULL; argno++; } + buf[0] = saveb0; + *pbuf = buf; + *pbufsize = savebufsize; return (0); /* true end of file */ } +void +nextfile(void) +{ + if (infile != NULL && infile != stdin) + (void) fclose(infile); + infile = NULL; + argno++; +} + +/* + * read one record into buf + */ int -readrec(uchar **bufp, size_t *sizep, FILE *inf) /* read one record into buf */ +readrec(char **pbuf, size_t *pbufsize, FILE *inf) { int sep, c; - uchar *buf; - int count; - size_t bufsize; + char *rr, *rt, *buf = *pbuf; + size_t bufsize = *pbufsize; + char *rs = getsval(rsloc); + + if (rtbuf == NULL && (rtbuf = malloc(rtbufsize)) == NULL) + FATAL("out of memory in readrec"); - init_buf(&buf, &bufsize, LINE_INCR); - if ((sep = **RS) == 0) { + rr = buf; + rt = rtbuf; + + if ((sep = *rs) == '\0') { sep = '\n'; /* skip leading \n's */ while ((c = getc(inf)) == '\n' && c != EOF) @@ -163,47 +279,90 @@ readrec(uchar **bufp, size_t *sizep, FILE *inf) /* read one record into buf */ if (c != EOF) (void) ungetc(c, inf); } - count = 0; - for (;;) { - while ((c = getc(inf)) != sep && c != EOF) { - expand_buf(&buf, &bufsize, count); - buf[count++] = c; + while ((c = getc(inf)) != EOF) { + if (c != sep) { + if (rr-buf+1 > bufsize) { + (void) adjbuf(&buf, &bufsize, + 1+rr-buf, recsize, &rr, "readrec1"); + } + *rr++ = c; + continue; + } + + /* + * Ensure enough space for either a single separator + * character, or at least two '\n' chars (when RS is + * the empty string). + */ + (void) adjbuf(&rtbuf, &rtbufsize, + 2+rt-rtbuf, recsize, &rt, "readrec2"); + + if (*rs == sep) { + *rt++ = sep; + break; } - if (**RS == sep || c == EOF) + + if ((c = getc(inf)) == '\n') { /* 2 in a row */ + *rt++ = '\n'; + *rt++ = '\n'; + while ((c = getc(inf)) == '\n' && c != EOF) { + /* Read any further \n's and add them to RT. */ + (void) adjbuf(&rtbuf, &rtbufsize, + 1+rt-rtbuf, recsize, &rt, "readrec3"); + *rt++ = '\n'; + } + if (c != EOF) + (void) ungetc(c, inf); break; - if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ + } + + if (c == EOF) { + *rt++ = '\n'; break; - expand_buf(&buf, &bufsize, count + 1); - buf[count++] = '\n'; - buf[count++] = c; + } + + (void) adjbuf(&buf, &bufsize, + 2+rr-buf, recsize, &rr, "readrec4"); + *rr++ = '\n'; + *rr++ = c; } - buf[count] = '\0'; + (void) adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec5"); + (void) adjbuf(&rtbuf, &rtbufsize, 1+rt-rtbuf, recsize, &rt, "readrec6"); + *rr = '\0'; + *rt = '\0'; dprintf(("readrec saw <%s>, returns %d\n", - buf, c == EOF && count == 0 ? 0 : 1)); - *bufp = buf; - *sizep = count; - return (c == EOF && count == 0 ? 0 : 1); + buf, c == EOF && rr == buf ? 0 : 1)); + *pbuf = buf; + *pbufsize = bufsize; + if (c == EOF && rr == buf) { + return (0); + } else { + (void) setsval(rtloc, rtbuf); + return (1); + } } /* get ARGV[n] */ -static uchar * +static char * getargv(int n) { Cell *x; - uchar *s, temp[11]; + char *s, temp[50]; extern Array *ARGVtab; - (void) sprintf((char *)temp, "%d", n); - x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab); + (void) sprintf(temp, "%d", n); + if (lookup(temp, ARGVtab) == NULL) + return (NULL); + x = setsymtab(temp, "", 0.0, STR, ARGVtab); s = getsval(x); dprintf(("getargv(%d) returns |%s|\n", n, s)); return (s); } void -setclvar(uchar *s) /* set var=value from s */ +setclvar(char *s) /* set var=value from s */ { - uchar *p; + char *p; Cell *q; for (p = s; *p != '='; p++) @@ -213,7 +372,7 @@ setclvar(uchar *s) /* set var=value from s */ q = setsymtab(s, p, 0.0, STR, symtab); (void) setsval(q, p); if (is_number(q->sval)) { - q->fval = atof((const char *)q->sval); + q->fval = atof(q->sval); q->tval |= NUM; } dprintf(("command line set %s to |%s|\n", s, p)); @@ -221,236 +380,232 @@ setclvar(uchar *s) /* set var=value from s */ } void -fldbld(void) +fldbld(void) /* create fields from current record */ { - uchar *r, *fr, sep; + /* this relies on having fields[] the same length as $0 */ + /* the fields are all stored in this one array with \0's */ + /* possibly with a final trailing \0 not associated with any field */ + char *r, *fr, sep; Cell *p; - int i; - size_t len; + int i, j, n; if (donefld) return; - if (!(recloc->tval & STR)) - (void) getsval(recloc); - r = recloc->sval; /* was record! */ - - /* make sure fields is always allocated */ - adjust_buf(&fields, fields_size); - - /* - * make sure fields has enough size. We don't expand the buffer - * in the middle of the loop, since p->sval has already pointed - * the address in the fields. - */ - len = strlen((char *)r) + 1; - expand_buf(&fields, &fields_size, len); + if (!isstr(fldtab[0])) + (void) getsval(fldtab[0]); + r = fldtab[0]->sval; + n = strlen(r); + if (n > fieldssize) { + xfree(fields); + /* possibly 2 final \0s */ + if ((fields = (char *)malloc(n + 2)) == NULL) + FATAL("out of space for fields in fldbld %d", n); + fieldssize = n; + } fr = fields; i = 0; /* number of fields accumulated here */ - if (strlen((char *)*FS) > 1) { /* it's a regular expression */ - i = refldbld(r, *FS); - } else if ((sep = **FS) == ' ') { + if (strlen(inputFS) > 1) { /* it's a regular expression */ + i = refldbld(r, inputFS); + } else if ((sep = *inputFS) == ' ') { /* default whitespace */ for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; - if (*r == 0) + if (*r == '\0') break; i++; - p = getfld(i); - if (!(p->tval & DONTFREE)) - xfree(p->sval); - p->sval = fr; - p->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') ; - *fr++ = 0; + *fr++ = '\0'; + } + *fr = '\0'; + } else if ((sep = *inputFS) == '\0') { + /* new: FS="" => 1 char/field */ + for (i = 0; *r != '\0'; r++) { + char buf[2]; + i++; + 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; } - *fr = 0; - } else if (*r != 0) { /* if 0, it's a null field */ + *fr = '\0'; + } else if (*r != '\0') { /* if 0, it's a null field */ + /* + * subtlecase : if length(FS) == 1 && length(RS > 0) + * \n is NOT a field separator (cf awk book 61,84). + * this variable is tested in the inner while loop. + */ + int rtest = '\n'; /* normal case */ + if (strlen(*RS) > 0) + rtest = '\0'; for (;;) { i++; - p = getfld(i); - if (!(p->tval & DONTFREE)) - xfree(p->sval); - p->sval = fr; - p->tval = FLD | STR | DONTFREE; - /* \n always a separator */ - while (*r != sep && *r != '\n' && *r != '\0') + if (i > nfields) + growfldtab(i); + if (freeable(fldtab[i])) + xfree(fldtab[i]->sval); + fldtab[i]->sval = fr; + fldtab[i]->tval = FLD | STR | DONTFREE; + /* \n is always a separator */ + while (*r != sep && *r != rtest && *r != '\0') *fr++ = *r++; - *fr++ = 0; - if (*r++ == 0) + *fr++ = '\0'; + if (*r++ == '\0') break; } - *fr = 0; + *fr = '\0'; } + if (i > nfields) + FATAL("record `%.30s...' has too many fields; can't happen", r); /* clean out junk from previous record */ - cleanfld(i, maxfld); - maxfld = i; + cleanfld(i+1, lastfld); + lastfld = i; donefld = 1; - for (i = 1; i <= maxfld; i++) { - p = getfld(i); + for (j = 1; j <= lastfld; j++) { + p = fldtab[j]; if (is_number(p->sval)) { - p->fval = atof((const char *)p->sval); + p->fval = atof(p->sval); p->tval |= NUM; } } - - (void) setfval(nfloc, (Awkfloat) maxfld); + (void) setfval(nfloc, (Awkfloat)lastfld); + donerec = 1; /* restore */ if (dbg) { - for (i = 0; i <= maxfld; i++) { - p = getfld(i); - (void) printf("field %d: |%s|\n", i, p->sval); + for (j = 0; j <= lastfld; j++) { + p = fldtab[j]; + (void) printf("field %d (%s): |%s|\n", + j, p->nval, p->sval); } } } +/* clean out fields n1 .. n2 inclusive; nvals remain intact */ static void -cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */ +cleanfld(int n1, int n2) { - static uchar *nullstat = (uchar *) ""; Cell *p; - int i; + int i; - for (i = n2; i > n1; i--) { - p = getfld(i); - 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) */ +newfld(int n) /* add field n after end of existing lastfld */ { - if (n < 0) - ERROR "accessing invalid field", record FATAL; - (void) getfld(n); - cleanfld(maxfld, n); - maxfld = n; - (void) setfval(nfloc, (Awkfloat) n); + if (n > nfields) + growfldtab(n); + cleanfld(lastfld+1, n); + lastfld = n; + (void) setfval(nfloc, (Awkfloat)n); } -/* - * allocate field table. We don't reallocate the table since there - * might be somewhere recording the address of the table. - */ -static void -morefld(void) +void +setlastfld(int n) /* set lastfld cleaning fldtab cells if necessary */ { - int i; - struct fldtab_chunk *fldcp; - Cell *newfld; - - if ((fldcp = calloc(sizeof (struct fldtab_chunk), 1)) == NULL) - ERROR "out of space in morefld" FATAL; - - newfld = &fldcp->fields[0]; - for (i = 0; i < FLD_INCR; i++) { - newfld[i].ctype = OCELL; - newfld[i].csub = CFLD; - newfld[i].nval = NULL; - newfld[i].sval = (uchar *)""; - newfld[i].fval = 0.0; - newfld[i].tval = FLD|STR|DONTFREE; - newfld[i].cnext = NULL; - } - /* - * link this field chunk - */ - if (fldtab_head == NULL) - fldtab_head = fldcp; + if (n < 0) + FATAL("cannot set NF to a negative value"); + if (n > nfields) + growfldtab(n); + + if (lastfld < n) + cleanfld(lastfld+1, n); else - fldtab_tail->next = fldcp; - fldtab_tail = fldcp; - fldcp->next = NULL; + cleanfld(n+1, lastfld); - fldtab_maxidx += FLD_INCR; + lastfld = n; } Cell * -getfld(int idx) +fieldadr(int n) /* get nth field */ { - struct fldtab_chunk *fldcp; - int cbase; - - if (idx < 0) - ERROR "trying to access field %d", idx FATAL; - while (idx >= fldtab_maxidx) - morefld(); - cbase = 0; - for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) { - if (idx < (cbase + FLD_INCR)) - return (&fldcp->fields[idx - cbase]); - cbase += FLD_INCR; - } - /* should never happen */ - ERROR "trying to access invalid field %d", idx FATAL; - return (NULL); + if (n < 0) + FATAL("trying to access out of range field %d", n); + if (n > nfields) /* fields after NF are empty */ + growfldtab(n); /* but does not increase NF */ + return (fldtab[n]); } -int -fldidx(Cell *vp) +void +growfldtab(int n) /* make new fields up to at least $n */ { - struct fldtab_chunk *fldcp; - Cell *tbl; - int cbase; - - cbase = 0; - for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) { - tbl = &fldcp->fields[0]; - if (vp >= tbl && vp < (tbl + FLD_INCR)) - return (cbase + (vp - tbl)); - cbase += FLD_INCR; - } - /* should never happen */ - ERROR "trying to access unknown field" FATAL; - return (0); + int nf = 2 * nfields; + size_t s; + + if (n > nf) + nf = n; + s = (nf+1) * (sizeof (Cell *)); /* freebsd: how much do we need? */ + if (s / sizeof (Cell *) - 1 == nf) /* didn't overflow */ + fldtab = (Cell **)realloc(fldtab, s); + else /* overflow sizeof int */ + xfree(fldtab); /* make it null */ + if (fldtab == NULL) + FATAL("out of space creating %d fields", nf); + makefields(nfields+1, nf); + nfields = nf; } +/* build fields from reg expr in FS */ static int -refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */ +refldbld(const char *rec, const char *fs) { - uchar *fr; - int i, tempstat; + /* 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, n; fa *pfa; - Cell *p; - size_t len; - /* make sure fields is allocated */ - adjust_buf(&fields, fields_size); + n = strlen(rec); + if (n > fieldssize) { + xfree(fields); + if ((fields = (char *)malloc(n+1)) == NULL) + FATAL("out of space for fields in refldbld %d", n); + fieldssize = n; + } fr = fields; *fr = '\0'; if (*rec == '\0') return (0); - - len = strlen((char *)rec) + 1; - expand_buf(&fields, &fields_size, len); - fr = fields; - pfa = makedfa(fs, 1); dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs)); tempstat = pfa->initstat; for (i = 1; ; i++) { - p = getfld(i); - if (!(p->tval & DONTFREE)) - xfree(p->sval); - p->tval = FLD | STR | DONTFREE; - p->sval = fr; + 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; + pfa->initstat = 2; /* horrible coupling to b.c */ dprintf(("match %s (%d chars)\n", patbeg, patlen)); - (void) strncpy((char *)fr, (char *)rec, patbeg-rec); + (void) strncpy(fr, rec, patbeg-rec); fr += patbeg - rec + 1; *(fr-1) = '\0'; rec = patbeg + patlen; } else { dprintf(("no match %s\n", rec)); - (void) strcpy((char *)fr, (char *)rec); + (void) strcpy(fr, rec); pfa->initstat = tempstat; break; } @@ -459,71 +614,74 @@ refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */ } void -recbld(void) +recbld(void) /* create $0 from $1..$NF if necessary */ { int i; - uchar *p; + char *p; size_t cnt, len, olen; + char *sep = getsval(ofsloc); if (donerec == 1) return; cnt = 0; - olen = strlen((char *)*OFS); + olen = strlen(sep); for (i = 1; i <= *NF; i++) { - p = getsval(getfld(i)); - len = strlen((char *)p); - expand_buf(&record, &record_size, cnt + len + olen); + p = getsval(fldtab[i]); + len = strlen(p); + expand_buf(&record, &recsize, cnt + len + olen); (void) memcpy(&record[cnt], p, len); cnt += len; if (i < *NF) { - (void) memcpy(&record[cnt], *OFS, olen); + (void) memcpy(&record[cnt], sep, olen); cnt += olen; } } record[cnt] = '\0'; - dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc)); - if (!(recloc->tval & DONTFREE)) + dprintf(("in recbld inputFS=%s, recloc=%p\n", inputFS, (void *)recloc)); + if (freeable(recloc)) xfree(recloc->sval); recloc->tval = REC | STR | DONTFREE; recloc->sval = record; - dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc)); + dprintf(("in recbld inputFS=%s, recloc=%p\n", inputFS, (void *)recloc)); dprintf(("recbld = |%s|\n", record)); donerec = 1; } -Cell * -fieldadr(int n) +int errorflag = 0; + +void +yyerror(const char *s) { - if (n < 0) - ERROR "trying to access field %d", n FATAL; - return (getfld(n)); + SYNTAX("%s", s); } -int errorflag = 0; -char errbuf[200]; - void -yyerror(char *s) +SYNTAX(const char *fmt, ...) { - extern uchar *cmdname, *curfname; + extern char *cmdname, *curfname; static int been_here = 0; + va_list varg; if (been_here++ > 2) return; - (void) fprintf(stderr, "%s: %s", cmdname, s); - (void) fprintf(stderr, gettext(" at source line %lld"), lineno); + (void) fprintf(stderr, "%s: ", cmdname); + va_start(varg, fmt); + (void) vfprintf(stderr, fmt, varg); + va_end(varg); + (void) fprintf(stderr, " at source line %lld", lineno); if (curfname != NULL) - (void) fprintf(stderr, gettext(" in function %s"), curfname); + (void) fprintf(stderr, " in function %s", curfname); + if (compile_time == 1 && cursource() != NULL) + (void) fprintf(stderr, " source file %s", cursource()); (void) fprintf(stderr, "\n"); errorflag = 2; eprint(); } -/*ARGSUSED*/ void -fpecatch(int sig) +fpecatch(int n) { - ERROR "floating point exception" FATAL; + FATAL("floating point exception %d", n); } extern int bracecnt, brackcnt, parencnt; @@ -558,47 +716,74 @@ bcheck2(int n, int c1, int c2) } void -error(int f, char *s) +FATAL(const char *fmt, ...) { - extern Node *curnode; - extern uchar *cmdname; + extern char *cmdname; + va_list varg; + + (void) fflush(stdout); + (void) fprintf(stderr, "%s: ", cmdname); + va_start(varg, fmt); + (void) vfprintf(stderr, fmt, varg); + va_end(varg); + error(); + if (dbg > 1) /* core dump if serious debugging on */ + abort(); + exit(2); +} + +void +WARNING(const char *fmt, ...) +{ + extern char *cmdname; + va_list varg; (void) fflush(stdout); (void) fprintf(stderr, "%s: ", cmdname); - (void) fprintf(stderr, "%s", s); + va_start(varg, fmt); + (void) vfprintf(stderr, fmt, varg); + va_end(varg); + error(); +} + +void +error(void) +{ + extern Node *curnode; + (void) fprintf(stderr, "\n"); if (compile_time != 2 && NR && *NR > 0) { (void) fprintf(stderr, gettext(" input record number %g"), *FNR); - if (strcmp((char *)*FILENAME, "-") != 0) + if (strcmp(*FILENAME, "-") != 0) (void) fprintf(stderr, gettext(", file %s"), *FILENAME); (void) fprintf(stderr, "\n"); } if (compile_time != 2 && curnode) - (void) fprintf(stderr, gettext(" source line number %lld\n"), + (void) fprintf(stderr, gettext(" source line number %lld"), curnode->lineno); else if (compile_time != 2 && lineno) { (void) fprintf(stderr, - gettext(" source line number %lld\n"), lineno); + gettext(" source line number %lld"), lineno); } + if (compile_time == 1 && cursource() != NULL) + (void) fprintf(stderr, gettext(" source file %s"), cursource()); + (void) fprintf(stderr, "\n"); eprint(); - if (f) { - if (dbg) - abort(); - exit(2); - } } static void eprint(void) /* try to print context around error */ { - uchar *p, *q; + char *p, *q; int c; static int been_here = 0; - extern uchar ebuf[300], *ep; + extern char ebuf[], *ep; if (compile_time == 2 || compile_time == 0 || been_here++ > 0) return; + if (ebuf == ep) + return; p = ep - 1; if (p > ebuf && *p == '\n') p--; @@ -640,30 +825,22 @@ bclass(int c) } double -errcheck(double x, char *s) +errcheck(double x, const char *s) { - extern int errno; - if (errno == EDOM) { errno = 0; - ERROR "%s argument out of domain", s WARNING; + WARNING("%s argument out of domain", s); x = 1; } else if (errno == ERANGE) { errno = 0; - ERROR "%s result out of range", s WARNING; + WARNING("%s result out of range", s); x = 1; } return (x); } -void -PUTS(uchar *s) -{ - dprintf(("%s\n", s)); -} - int -isclvar(uchar *s) /* is s of form var=something? */ +isclvar(const char *s) /* is s of form var=something ? */ { if (s != NULL) { @@ -686,88 +863,28 @@ isclvar(uchar *s) /* is s of form var=something? */ return (0); } -#define MAXEXPON 38 /* maximum exponent for fp number */ - +#include <math.h> int -is_number(uchar *s) +is_number(const char *s) { - int d1, d2; - int point; - uchar *es; - extern char radixpoint; - - d1 = d2 = point = 0; - while (*s == ' ' || *s == '\t' || *s == '\n') - s++; - if (*s == '\0') - return (0); /* empty stuff isn't number */ - if (*s == '+' || *s == '-') - s++; - if (!isdigit(*s) && *s != radixpoint) - return (0); - if (isdigit(*s)) { - do { - d1++; - s++; - } while (isdigit(*s)); - } - if (d1 >= MAXEXPON) - return (0); /* too many digits to convert */ - if (*s == radixpoint) { - point++; - s++; - } - if (isdigit(*s)) { - d2++; - do { - s++; - } while (isdigit(*s)); - } - if (!(d1 || point && d2)) + double r; + char *ep; + errno = 0; + r = strtod(s, &ep); + if (ep == s || r == HUGE_VAL || errno == ERANGE) 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') + while (*ep == ' ' || *ep == '\t' || *ep == '\n') + ep++; + if (*ep == '\0') return (1); else return (0); } void -init_buf(uchar **optr, size_t *sizep, size_t amt) +r_expand_buf(char **optr, size_t *sizep, size_t req) { - uchar *nptr = NULL; - - if ((nptr = malloc(amt)) == NULL) - ERROR "out of space in init_buf" FATAL; - /* initial buffer should have NULL terminated */ - *nptr = '\0'; - if (sizep != NULL) - *sizep = amt; - *optr = nptr; -} - -void -r_expand_buf(uchar **optr, size_t *sizep, size_t req) -{ - uchar *nptr; + char *nptr; size_t amt, size = *sizep; if (size != 0 && req < (size - 1)) @@ -776,20 +893,10 @@ r_expand_buf(uchar **optr, size_t *sizep, size_t req) amt = (amt / LINE_INCR + 1) * LINE_INCR; if ((nptr = realloc(*optr, size + amt)) == NULL) - ERROR "out of space in expand_buf" FATAL; + FATAL("out of space in expand_buf"); /* initial buffer should have NULL terminated */ if (size == 0) *nptr = '\0'; *sizep += amt; *optr = nptr; } - -void -adjust_buf(uchar **optr, size_t size) -{ - uchar *nptr; - - if ((nptr = realloc(*optr, size)) == NULL) - ERROR "out of space in adjust_buf" FATAL; - *optr = nptr; -} diff --git a/usr/src/cmd/awk/main.c b/usr/src/cmd/awk/main.c index b0c9d5ae98..ff004daf65 100644 --- a/usr/src/cmd/awk/main.c +++ b/usr/src/cmd/awk/main.c @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -39,24 +63,25 @@ #include "awk.h" #include "y.tab.h" -char *version = "version Oct 11, 1989"; +char *version = "version Aug 27, 2018"; int dbg = 0; -uchar *cmdname; /* gets argv[0] for error messages */ -uchar *lexprog; /* points to program argument if it exists */ +Awkfloat srand_seed = 1; +char *cmdname; /* gets argv[0] for error messages */ +char *lexprog; /* points to program argument if it exists */ int compile_time = 2; /* for error printing: */ /* 2 = cmdline, 1 = compile, 0 = running */ -char radixpoint = '.'; -static uchar **pfile = NULL; /* program filenames from -f's */ +static char **pfile = NULL; /* program filenames from -f's */ static int npfile = 0; /* number of filenames */ static int curpfile = 0; /* current filename */ +int safe = 0; /* 1 => "safe" mode */ + int main(int argc, char *argv[], char *envp[]) { - uchar *fs = NULL; - char *nl_radix; + const char *fs = NULL; /* * At this point, numbers are still scanned as in * the POSIX locale. @@ -68,7 +93,7 @@ main(int argc, char *argv[], char *envp[]) #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); - cmdname = (uchar *)argv[0]; + cmdname = argv[0]; if (argc == 1) { (void) fprintf(stderr, gettext( "Usage: %s [-f programfile | 'program'] [-Ffieldsep] " @@ -76,9 +101,19 @@ main(int argc, char *argv[], char *envp[]) exit(1); } (void) signal(SIGFPE, fpecatch); + + srand_seed = 1; + srand((unsigned int)srand_seed); + yyin = NULL; - syminit(); + symtab = makesymtab(NSYMTAB/NSYMTAB); while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') { + if (strcmp(argv[1], "-version") == 0 || + strcmp(argv[1], "--version") == 0) { + (void) printf("awk %s\n", version); + exit(0); + break; + } if (strcmp(argv[1], "--") == 0) { /* explicit end of args */ argc--; @@ -86,41 +121,66 @@ main(int argc, char *argv[], char *envp[]) 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++; - if (argc <= 1) - ERROR "no program filename" FATAL; - pfile = realloc(pfile, sizeof (uchar *) * (npfile + 1)); - if (pfile == NULL) - ERROR "out of space in main" FATAL; - pfile[npfile++] = (uchar *)argv[1]; + if (argv[1][2] != 0) { /* arg is -fsomething */ + pfile = realloc(pfile, + sizeof (char *) * (npfile + 1)); + if (pfile == NULL) + FATAL("out of space in main"); + pfile[npfile++] = &argv[1][2]; + } else { /* arg is -f something */ + argc--; argv++; + if (argc <= 1) + FATAL("no program filename"); + pfile = realloc(pfile, + sizeof (char *) * (npfile + 1)); + if (pfile == NULL) + FATAL("out of space in main"); + pfile[npfile++] = argv[1]; + } break; case 'F': /* set field separator */ if (argv[1][2] != 0) { /* arg is -Fsomething */ /* wart: t=>\t */ if (argv[1][2] == 't' && argv[1][3] == 0) - fs = (uchar *) "\t"; + fs = "\t"; else if (argv[1][2] != 0) - fs = (uchar *)&argv[1][2]; + fs = &argv[1][2]; } else { /* arg is -F something */ argc--; argv++; if (argc > 1) { /* wart: t=>\t */ if (argv[1][0] == 't' && argv[1][1] == 0) - fs = (uchar *) "\t"; + fs = "\t"; else if (argv[1][0] != 0) - fs = (uchar *)&argv[1][0]; + fs = &argv[1][0]; } } if (fs == NULL || *fs == '\0') - ERROR "field separator FS is empty" WARNING; + WARNING("field separator FS is empty"); break; case 'v': /* -v a=1 to be done NOW. one -v for each */ - if (argv[1][2] == '\0' && --argc > 1 && - isclvar((uchar *)(++argv)[1])) - setclvar((uchar *)argv[1]); + if (argv[1][2] != 0) { /* arg is -vsomething */ + if (isclvar(&argv[1][2])) + setclvar(&argv[1][2]); + else + FATAL("invalid -v option argument: %s", + &argv[1][2]); + } else { /* arg is -v something */ + argc--; argv++; + if (argc <= 1) + FATAL("no variable name"); + if (isclvar(argv[1])) + setclvar(argv[1]); + else + FATAL("invalid -v option argument: %s", + argv[1]); + } break; case 'd': dbg = atoi(&argv[1][2]); @@ -129,7 +189,7 @@ main(int argc, char *argv[], char *envp[]) (void) printf("awk %s\n", version); break; default: - ERROR "unknown option %s ignored", argv[1] WARNING; + WARNING("unknown option %s ignored", argv[1]); break; } argc--; @@ -140,18 +200,21 @@ main(int argc, char *argv[], char *envp[]) if (argc <= 1) { if (dbg) exit(0); - ERROR "no program given" FATAL; + FATAL("no program given"); } dprintf(("program = |%s|\n", argv[1])); - lexprog = (uchar *)argv[1]; + lexprog = argv[1]; argc--; argv++; } + recinit(recsize); + syminit(); compile_time = 1; - argv[0] = (char *)cmdname; /* put prog name at front of arglist */ + argv[0] = cmdname; /* put prog name at front of arglist */ dprintf(("argc=%d, argv[0]=%s\n", argc, argv[0])); - arginit(argc, (uchar **)argv); - envinit((uchar **)envp); + arginit(argc, argv); + if (!safe) + envinit(envp); (void) yyparse(); if (fs) *FS = qstring(fs, '\0'); @@ -160,9 +223,6 @@ main(int argc, char *argv[], char *envp[]) * done parsing, so now activate the LC_NUMERIC */ (void) setlocale(LC_ALL, ""); - nl_radix = nl_langinfo(RADIXCHAR); - if (nl_radix) - radixpoint = *nl_radix; if (errorflag == 0) { compile_time = 0; @@ -173,7 +233,7 @@ main(int argc, char *argv[], char *envp[]) } int -pgetc(void) /* get program character */ +pgetc(void) /* get 1 character from awk program */ { int c; @@ -181,17 +241,27 @@ pgetc(void) /* get program character */ if (yyin == NULL) { if (curpfile >= npfile) return (EOF); - yyin = (strcmp((char *)pfile[curpfile], "-") == 0) ? - stdin : fopen((char *)pfile[curpfile], "r"); + yyin = (strcmp(pfile[curpfile], "-") == 0) ? + stdin : fopen(pfile[curpfile], "rF"); if (yyin == NULL) { - ERROR "can't open file %s", - pfile[curpfile] FATAL; + FATAL("can't open file %s", pfile[curpfile]); } + lineno = 1; } if ((c = getc(yyin)) != EOF) return (c); - (void) fclose(yyin); + if (yyin != stdin) + (void) fclose(yyin); yyin = NULL; curpfile++; } } + +char * +cursource(void) /* current source file name */ +{ + if (curpfile < npfile) + return (pfile[curpfile]); + else + return (NULL); +} diff --git a/usr/src/cmd/awk/maketab.c b/usr/src/cmd/awk/maketab.c index 5c7d8601ea..9c625aabcc 100644 --- a/usr/src/cmd/awk/maketab.c +++ b/usr/src/cmd/awk/maketab.c @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -26,6 +50,12 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ +/* + * 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 ytab.h, produced by yacc. + */ + #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -35,8 +65,8 @@ struct xx { int token; - char *name; - char *pname; + const char *name; + const char *pname; } proc[] = { { PROGRAM, "program", NULL }, { BOR, "boolop", " || " }, @@ -54,13 +84,14 @@ struct xx { { SUB, "sub", "sub" }, { GSUB, "gsub", "gsub" }, { INDEX, "sindex", "sindex" }, - { SPRINTF, "a_sprintf", "sprintf " }, + { SPRINTF, "awksprintf", "sprintf " }, { ADD, "arith", " + " }, { MINUS, "arith", " - " }, { MULT, "arith", " * " }, { DIVIDE, "arith", " / " }, { MOD, "arith", " % " }, { UMINUS, "arith", " -" }, + { UPLUS, "arith", " +" }, { POWER, "arith", " **" }, { PREINCR, "incrdecr", "++" }, { POSTINCR, "incrdecr", "++" }, @@ -73,10 +104,10 @@ struct xx { { NOTMATCH, "matchop", " !~ " }, { MATCHFCN, "matchop", "matchop" }, { INTEST, "intest", "intest" }, - { PRINTF, "aprintf", "printf" }, - { PRINT, "print", "print" }, + { PRINTF, "awkprintf", "printf" }, + { PRINT, "printstat", "print" }, { CLOSE, "closefile", "closefile" }, - { DELETE, "delete", "delete" }, + { DELETE, "awkdelete", "awkdelete" }, { SPLIT, "split", "split" }, { ASSIGN, "assign", " = " }, { ADDEQ, "assign", " += " }, @@ -92,6 +123,7 @@ struct xx { { DO, "dostat", "do" }, { IN, "instat", "instat" }, { NEXT, "jump", "next" }, + { NEXTFILE, "jump", "nextfile" }, { EXIT, "jump", "exit" }, { BREAK, "jump", "break" }, { CONTINUE, "jump", "continue" }, @@ -100,23 +132,24 @@ struct xx { { CALL, "call", "call" }, { ARG, "arg", "arg" }, { VARNF, "getnf", "NF" }, - { GETLINE, "getaline", "getline" }, + { GETLINE, "awkgetline", "getline" }, { 0, "", "" }, }; -#define SIZE LASTTOKEN - FIRSTTOKEN + 1 -char *table[SIZE]; +#define SIZE (LASTTOKEN - FIRSTTOKEN + 1) +const char *table[SIZE]; char *names[SIZE]; int -main() +main(int argc, char *argv[]) { - struct xx *p; + const struct xx *p; int i, n, tok; char c; FILE *fp; - char buf[100], name[100], def[100]; + char buf[200], name[200], def[200]; + printf("#include <stdio.h>\n"); printf("#include \"awk.h\"\n"); printf("#include \"y.tab.h\"\n\n"); @@ -124,28 +157,29 @@ main() fprintf(stderr, gettext("maketab can't open y.tab.h!\n")); exit(1); } - printf("static uchar *printname[%d] = {\n", SIZE); + printf("static char *printname[%d] = {\n", SIZE); i = 0; while (fgets(buf, sizeof (buf), fp) != NULL) { n = sscanf(buf, "%1c %s %s %d", &c, def, name, &tok); - /* not a valid #define? */ - if (c != '#' || n != 4 && strcmp(def, "define") != 0) + if (c != '#' || (n != 4 && strcmp(def, "define") != 0)) { + /* not a valid #define */ continue; + } if (tok < FIRSTTOKEN || tok > LASTTOKEN) { fprintf(stderr, gettext("maketab funny token %d %s\n"), tok, buf); exit(1); } - names[tok-FIRSTTOKEN] = malloc(strlen(name)+1); + names[tok-FIRSTTOKEN] = (char *)malloc(strlen(name)+1); strcpy(names[tok-FIRSTTOKEN], name); - printf("\t(uchar *) \"%s\",\t/* %d */\n", name, tok); + printf("\t(char *) \"%s\",\t/* %d */\n", name, tok); i++; } printf("};\n\n"); for (p = proc; p->token != 0; p++) table[p->token-FIRSTTOKEN] = p->name; - printf("\nCell *(*proctab[%d])() = {\n", SIZE); + printf("\nCell *(*proctab[%d])(Node **, int) = {\n", SIZE); for (i = 0; i < SIZE; i++) if (table[i] == 0) printf("\tnullproc,\t/* %s */\n", names[i]); @@ -153,14 +187,14 @@ main() printf("\t%s,\t/* %s */\n", table[i], names[i]); printf("};\n\n"); - printf("uchar *\ntokname(int n)\n"); /* print a tokname() function */ + printf("char *\ntokname(int n)\n"); /* print a tokname() function */ printf("{\n"); printf(" static char buf[100];\n\n"); printf(" if (n < FIRSTTOKEN || n > LASTTOKEN) {\n"); printf(" (void) sprintf(buf, \"token %%d\", n);\n"); - printf(" return ((uchar *)buf);\n"); + printf(" return (buf);\n"); printf(" }\n"); - printf(" return printname[n-257];\n"); + printf(" return printname[n-FIRSTTOKEN];\n"); printf("}\n"); - exit(0); + return (0); } diff --git a/usr/src/cmd/awk/parse.c b/usr/src/cmd/awk/parse.c index 909977f10f..2afcf1e78f 100644 --- a/usr/src/cmd/awk/parse.c +++ b/usr/src/cmd/awk/parse.c @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -28,8 +52,6 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #define DEBUG #include "awk.h" #include "y.tab.h" @@ -37,11 +59,11 @@ Node * nodealloc(int n) { - register Node *x; + Node *x; x = (Node *)malloc(sizeof (Node) + (n - 1) * sizeof (Node *)); if (x == NULL) - ERROR "out of space in nodealloc" FATAL; + FATAL("out of space in nodealloc"); x->nnext = NULL; x->lineno = lineno; return (x); @@ -57,7 +79,7 @@ exptostat(Node *a) Node * node1(int a, Node *b) { - register Node *x; + Node *x; x = nodealloc(1); x->nobj = a; @@ -68,7 +90,7 @@ node1(int a, Node *b) Node * node2(int a, Node *b, Node *c) { - register Node *x; + Node *x; x = nodealloc(2); x->nobj = a; @@ -80,7 +102,7 @@ node2(int a, Node *b, Node *c) Node * node3(int a, Node *b, Node *c, Node *d) { - register Node *x; + Node *x; x = nodealloc(3); x->nobj = a; @@ -93,7 +115,8 @@ node3(int a, Node *b, Node *c, Node *d) Node * node4(int a, Node *b, Node *c, Node *d, Node *e) { - register Node *x; + Node *x; + x = nodealloc(4); x->nobj = a; x->narg[0] = b; @@ -104,89 +127,89 @@ node4(int a, Node *b, Node *c, Node *d, Node *e) } Node * -stat3(int a, Node *b, Node *c, Node *d) +stat1(int a, Node *b) { - register Node *x; + Node *x; - x = node3(a, b, c, d); + x = node1(a, b); x->ntype = NSTAT; return (x); } Node * -op2(int a, Node *b, Node *c) +stat2(int a, Node *b, Node *c) { - register Node *x; + Node *x; x = node2(a, b, c); - x->ntype = NEXPR; + x->ntype = NSTAT; return (x); } Node * -op1(int a, Node *b) +stat3(int a, Node *b, Node *c, Node *d) { - register Node *x; + Node *x; - x = node1(a, b); - x->ntype = NEXPR; + x = node3(a, b, c, d); + x->ntype = NSTAT; return (x); } Node * -stat1(int a, Node *b) +stat4(int a, Node *b, Node *c, Node *d, Node *e) { - register Node *x; + Node *x; - x = node1(a, b); + x = node4(a, b, c, d, e); x->ntype = NSTAT; return (x); } Node * -op3(int a, Node *b, Node *c, Node *d) +op1(int a, Node *b) { - register Node *x; + Node *x; - x = node3(a, b, c, d); + x = node1(a, b); x->ntype = NEXPR; return (x); } Node * -op4(int a, Node *b, Node *c, Node *d, Node *e) +op2(int a, Node *b, Node *c) { - register Node *x; + Node *x; - x = node4(a, b, c, d, e); + x = node2(a, b, c); x->ntype = NEXPR; return (x); } Node * -stat2(int a, Node *b, Node *c) +op3(int a, Node *b, Node *c, Node *d) { - register Node *x; + Node *x; - x = node2(a, b, c); - x->ntype = NSTAT; + x = node3(a, b, c, d); + x->ntype = NEXPR; return (x); } Node * -stat4(int a, Node *b, Node *c, Node *d, Node *e) +op4(int a, Node *b, Node *c, Node *d, Node *e) { - register Node *x; + Node *x; x = node4(a, b, c, d, e); - x->ntype = NSTAT; + x->ntype = NEXPR; return (x); } Node * -valtonode(Cell *a, int b) +celltonode(Cell *a, int b) { - register Node *x; + Node *x; a->ctype = OCELL; a->csub = b; @@ -196,10 +219,10 @@ valtonode(Cell *a, int b) } Node * -rectonode(void) +rectonode(void) /* make $0 into a Node */ { - /* return valtonode(lookup("$0", symtab), CFLD); */ - return (valtonode(recloc, CFLD)); + extern Cell *literal0; + return (op1(INDIRECT, celltonode(literal0, CUNK))); } Node * @@ -209,23 +232,26 @@ makearr(Node *p) if (isvalue(p)) { cp = (Cell *)(p->narg[0]); - if (isfunc(cp)) - ERROR "%s is a function, not an array", cp->nval SYNTAX; + if (isfcn(cp)) + SYNTAX("%s is a function, not an array", cp->nval); else if (!isarr(cp)) { xfree(cp->sval); - cp->sval = (uchar *)makesymtab(NSYMTAB); + cp->sval = (char *)makesymtab(NSYMTAB); cp->tval = ARR; } } return (p); } +int paircnt; /* number of them in use */ +int *pairstack; /* state of each pat,pat */ + Node * -pa2stat(Node *a, Node *b, Node *c) +pa2stat(Node *a, Node *b, Node *c) /* pat, pat {...} */ { - register Node *x; + Node *x; - x = node4(PASTAT2, a, b, c, (Node *)paircnt); + x = node4(PASTAT2, a, b, c, itonp(paircnt)); paircnt++; x->ntype = NSTAT; return (x); @@ -234,7 +260,7 @@ pa2stat(Node *a, Node *b, Node *c) Node * linkum(Node *a, Node *b) { - register Node *c; + Node *c; if (errorflag) /* don't link things that are wrong */ return (a); @@ -248,38 +274,55 @@ linkum(Node *a, Node *b) return (a); } +/* turn on FCN bit in definition, */ +/* body of function, arglist */ void -defn(Cell *v, Node *vl, Node *st) /* turn on FCN bit in definition */ +defn(Cell *v, Node *vl, Node *st) { Node *p; int n; if (isarr(v)) { - ERROR "`%s' is an array name and a function name", - v->nval SYNTAX; + SYNTAX("`%s' is an array name and a function name", v->nval); + return; + } + if (isarg(v->nval) != -1) { + SYNTAX("`%s' is both function name and argument name", v->nval); return; } + v->tval = FCN; - v->sval = (uchar *)st; + v->sval = (char *)st; n = 0; /* count arguments */ - for (p = vl; p; p = p->nnext) + for (p = vl; p != NULL; p = p->nnext) n++; v->fval = n; dprintf(("defining func %s (%d args)\n", v->nval, n)); } +/* is s in argument list for current function? */ +/* return -1 if not, otherwise arg # */ int -isarg(uchar *s) /* is s in argument list for current function? */ +isarg(const char *s) { extern Node *arglist; Node *p = arglist; int n; - for (n = 0; p != 0; p = p->nnext, n++) { - if (strcmp((char *)((Cell *)(p->narg[0]))->nval, - (char *)s) == 0) { + for (n = 0; p != NULL; p = p->nnext, n++) + if (strcmp(((Cell *)(p->narg[0]))->nval, s) == 0) return (n); - } - } return (-1); } + +int +ptoi(void *p) /* convert pointer to integer */ +{ + return ((int)(long)p); /* swearing that p fits, of course */ +} + +Node * +itonp(int i) /* and vice versa */ +{ + return ((Node *)(long)i); +} diff --git a/usr/src/cmd/awk/run.c b/usr/src/cmd/awk/run.c index 3cc8341d84..5226d43ed2 100644 --- a/usr/src/cmd/awk/run.c +++ b/usr/src/cmd/awk/run.c @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -26,178 +50,221 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#define tempfree(x, s) if (istemp(x)) tfree(x, s) - -#define execute(p) r_execute(p) - #define DEBUG -#include "awk.h" -#include <math.h> -#include "y.tab.h" #include <stdio.h> #include <ctype.h> #include <setjmp.h> +#include <math.h> #include <time.h> +#include <sys/wait.h> +#include "awk.h" +#include "y.tab.h" -#ifndef FOPEN_MAX -#define FOPEN_MAX 15 /* max number of open files, from ANSI std. */ -#endif - +#define tempfree(x) if (istemp(x)) tfree(x) static jmp_buf env; +extern Awkfloat srand_seed; -static Cell *r_execute(Node *); -static Cell *gettemp(char *), *copycell(Cell *); -static FILE *openfile(int, uchar *), *redirect(int, Node *); - -int paircnt; -Node *winner = NULL; +static Cell *execute(Node *); +static Cell *gettemp(void), *copycell(Cell *); +static FILE *openfile(int, const char *), *redirect(int, Node *); -static Cell *tmps; +Node *winner = NULL; /* root of parse tree */ +static Cell *tmps; /* free temporary cells for execution */ -static Cell truecell = { OBOOL, BTRUE, 0, 0, 1.0, NUM }; -Cell *true = &truecell; -static Cell falsecell = { OBOOL, BFALSE, 0, 0, 0.0, NUM }; -Cell *false = &falsecell; -static Cell breakcell = { OJUMP, JBREAK, 0, 0, 0.0, NUM }; +static Cell truecell = { OBOOL, BTRUE, NULL, NULL, 1.0, NUM, NULL }; +Cell *True = &truecell; +static Cell falsecell = { OBOOL, BFALSE, NULL, NULL, 0.0, NUM, NULL }; +Cell *False = &falsecell; +static Cell breakcell = { OJUMP, JBREAK, NULL, NULL, 0.0, NUM, NULL }; Cell *jbreak = &breakcell; -static Cell contcell = { OJUMP, JCONT, 0, 0, 0.0, NUM }; +static Cell contcell = { OJUMP, JCONT, NULL, NULL, 0.0, NUM, NULL }; Cell *jcont = &contcell; -static Cell nextcell = { OJUMP, JNEXT, 0, 0, 0.0, NUM }; +static Cell nextcell = { OJUMP, JNEXT, NULL, NULL, 0.0, NUM, NULL }; Cell *jnext = &nextcell; -static Cell exitcell = { OJUMP, JEXIT, 0, 0, 0.0, NUM }; +static Cell nextfilecell = { OJUMP, JNEXTFILE, NULL, NULL, 0.0, + NUM, NULL }; +Cell *jnextfile = &nextfilecell; +static Cell exitcell = { OJUMP, JEXIT, NULL, NULL, 0.0, NUM, NULL }; Cell *jexit = &exitcell; -static Cell retcell = { OJUMP, JRET, 0, 0, 0.0, NUM }; +static Cell retcell = { OJUMP, JRET, NULL, NULL, 0.0, NUM, NULL }; Cell *jret = &retcell; -static Cell tempcell = { OCELL, CTEMP, 0, 0, 0.0, NUM }; +static Cell tempcell = { OCELL, CTEMP, NULL, "", 0.0, + NUM|STR|DONTFREE, NULL }; Node *curnode = NULL; /* the node being executed, for debugging */ -static void tfree(Cell *, char *); +static void tfree(Cell *); static void closeall(void); static double ipow(double, int); +static void backsub(char **pb_ptr, char **sptr_ptr); + + +/* + * buffer memory management + * + * 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 + */ +int +adjbuf(char **pbuf, size_t *psiz, size_t minlen, size_t quantum, char **pbptr, + const char *whatrtn) +{ + 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 = (char *)realloc(*pbuf, minlen); + dprintf(("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, + *psiz, minlen, (void *)*pbuf, (void *)tbuf)); + if (tbuf == NULL) { + if (whatrtn) + FATAL("out of memory in %s", whatrtn); + return (0); + } + *pbuf = tbuf; + *psiz = minlen; + if (pbptr) + *pbptr = tbuf + boff; + } + return (1); +} void -run(Node *a) +run(Node *a) /* execution of parse tree starts here */ { + extern void stdinit(void); + + stdinit(); (void) execute(a); closeall(); } static Cell * -r_execute(Node *u) +execute(Node *u) /* execute a node of the parse tree */ { - register Cell *(*proc)(); - register Cell *x; - register Node *a; + Cell *(*proc)(Node **, int); + Cell *x; + Node *a; if (u == NULL) - return (true); + return (True); for (a = u; ; a = a->nnext) { 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); } /* probably a Cell* but too risky to print */ if (notlegal(a->nobj)) - ERROR "illegal statement" FATAL; + FATAL("illegal statement"); 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); /* a statement, goto next statement */ if (isjump(x)) return (x); - if (a->nnext == (Node *)NULL) + if (a->nnext == NULL) return (x); - tempfree(x, "execute"); + tempfree(x); } } +/* execute an awk program */ +/* a[0] = BEGIN, a[1] = body, a[2] = END */ /*ARGSUSED*/ Cell * program(Node **a, int n) { - register Cell *x; + Cell *x; if (setjmp(env) != 0) goto ex; if (a[0]) { /* BEGIN */ x = execute(a[0]); if (isexit(x)) - return (true); + return (True); if (isjump(x)) { - ERROR "illegal break, continue or next from BEGIN" - FATAL; + FATAL("illegal break, continue, next or nextfile " + "from BEGIN"); } - tempfree(x, ""); + tempfree(x); } -loop: if (a[1] || a[2]) - while (getrec(&record, &record_size) > 0) { + while (getrec(&record, &recsize, 1) > 0) { x = execute(a[1]); if (isexit(x)) break; - tempfree(x, ""); + tempfree(x); } ex: - if (setjmp(env) != 0) + if (setjmp(env) != 0) /* handles exit within END */ goto ex1; if (a[2]) { /* END */ x = execute(a[2]); - if (iscont(x)) /* read some more */ - goto loop; - if (isbreak(x) || isnext(x)) - ERROR "illegal break or next from END" FATAL; - tempfree(x, ""); + if (isbreak(x) || isnext(x) || iscont(x)) + FATAL("illegal break, continue, next or nextfile " + "from END"); + tempfree(x); } ex1: - return (true); + return (True); } -struct Frame { +struct Frame { /* stack frame for awk function calls */ int nargs; /* number of arguments in this call */ Cell *fcncell; /* pointer to Cell for function */ Cell **args; /* pointer to array of arguments after execute */ Cell *retval; /* return value */ }; -#define NARGS 30 +#define NARGS 50 /* max args in a call */ -struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */ +struct Frame *frame = NULL; /* base of stack frames; dynamically alloc'd */ int nframe = 0; /* number of frames allocated */ struct Frame *fp = NULL; /* frame pointer. bottom level unused */ /*ARGSUSED*/ Cell * -call(Node **a, int n) +call(Node **a, int n) /* function call. very kludgy and fragile */ { static Cell newcopycell = - { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE }; - int i, ncall, ndef, freed = 0; + { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE, NULL }; + int i, ncall, ndef; + /* handles potential double freeing when fcn & param share a tempcell */ + int freed = 0; Node *x; - Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn; - uchar *s; + 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)) - ERROR "calling undefined function %s", s FATAL; + if (!isfcn(fcn)) + FATAL("calling undefined function %s", s); if (frame == NULL) { fp = frame = (struct Frame *)calloc(nframe += 100, sizeof (struct Frame)); if (frame == NULL) { - ERROR "out of space for stack frames calling %s", - s FATAL; + FATAL("out of space for stack frames calling %s", s); } } for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ @@ -206,12 +273,12 @@ call(Node **a, int n) 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; + WARNING("function %s called with %d args, uses only %d", + s, ncall, ndef); } if (ncall + ndef > NARGS) { - ERROR "function %s has %d arguments, limit %d", - s, ncall+ndef, NARGS FATAL; + FATAL("function %s has %d arguments, limit %d", + s, ncall+ndef, NARGS); } for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ @@ -219,20 +286,20 @@ call(Node **a, int n) 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)) { - ERROR "can't use function %s as argument in %s", - y->nval, s FATAL; + i, NN(y->nval), y->fval, + isarr(y) ? "(array)" : NN(y->sval), y->tval)); + if (isfcn(y)) { + FATAL("can't use function %s as argument in %s", + y->nval, s); } if (isarr(y)) args[i] = y; /* arrays by ref */ else args[i] = copycell(y); - tempfree(y, "callargs"); + tempfree(y); } - for (; i < ndef; i++) { /* add null args for ones not provided */ - args[i] = gettemp("nullargs"); + for (; i < ndef; i++) { /* add null args for ones not provided */ + args[i] = gettemp(); *args[i] = newcopycell; } fp++; /* now ok to up frame */ @@ -241,13 +308,13 @@ call(Node **a, int n) frame = (struct Frame *) realloc(frame, (nframe += 100) * sizeof (struct Frame)); if (frame == NULL) - ERROR "out of space for stack frames in %s", s FATAL; + FATAL("out of space for stack frames in %s", s); fp = frame + dfp; } fp->fcncell = fcn; fp->args = args; fp->nargs = ndef; /* number defined with (excess are locals) */ - fp->retval = gettemp("retval"); + fp->retval = gettemp(); dprintf(("start exec of %s, fp=%d\n", s, fp-frame)); /*LINTED align*/ @@ -261,24 +328,29 @@ call(Node **a, int n) if (i >= ncall) { freesymtab(t); t->csub = CTEMP; + tempfree(t); } else { oargs[i]->tval = t->tval; oargs[i]->tval &= ~(STR|NUM|DONTFREE); oargs[i]->sval = t->sval; - tempfree(t, "oargsarr"); + tempfree(t); } } - } else { + } else if (t != y) { /* kludge to prevent freeing twice */ t->csub = CTEMP; - tempfree(t, "fp->args"); - if (t == y) freed = 1; + tempfree(t); + } else if (t == y && t->csub == CCOPY) { + t->csub = CTEMP; + tempfree(t); + freed = 1; } } - tempfree(fcn, "call.fcn"); + tempfree(fcn); if (isexit(y) || isnext(y)) return (y); - if (!freed) - tempfree(y, "fcn ret"); /* this can free twice! */ + if (freed == 0) { + tempfree(y); /* don't free twice! */ + } z = fp->retval; /* return value */ dprintf(("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval)); @@ -291,42 +363,47 @@ copycell(Cell *x) /* make a copy of a cell in a temp */ { Cell *y; - y = gettemp("copycell"); + /* copy is not constant or field */ + + y = gettemp(); + y->tval = x->tval & ~(CON|FLD|REC); y->csub = CCOPY; /* prevents freeing until call is over */ - y->nval = x->nval; - y->sval = x->sval ? tostring(x->sval) : NULL; + y->nval = x->nval; /* BUG? */ + if (isstr(x)) { + y->sval = tostring(x->sval); + y->tval &= ~DONTFREE; + } else + y->tval |= DONTFREE; y->fval = x->fval; - /* copy is not constant or field is DONTFREE right? */ - y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); return (y); } /*ARGSUSED*/ Cell * -arg(Node **a, int nnn) +arg(Node **a, int nnn) /* nth argument of a function */ { int n; - n = (int)a[0]; /* argument number, counting from 0 */ + n = ptoi(a[0]); /* argument number, counting from 0 */ 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; + FATAL("argument #%d of function %s was not supplied", + n+1, fp->fcncell->nval); } return (fp->args[n]); } Cell * -jump(Node **a, int n) +jump(Node **a, int n) /* break, continue, next, nextfile, return */ { - register Cell *y; + Cell *y; switch (n) { case EXIT: if (a[0] != NULL) { y = execute(a[0]); errorflag = (int)getfval(y); - tempfree(y, ""); + tempfree(y); } longjmp(env, 1); /*NOTREACHED*/ @@ -341,77 +418,85 @@ jump(Node **a, int n) (void) setsval(fp->retval, getsval(y)); else if (y->tval & NUM) (void) setfval(fp->retval, getfval(y)); - tempfree(y, ""); + else /* can't happen */ + FATAL("bad type variable %d", y->tval); + tempfree(y); } return (jret); case NEXT: return (jnext); + case NEXTFILE: + nextfile(); + return (jnextfile); case BREAK: return (jbreak); case CONTINUE: return (jcont); default: /* can't happen */ - ERROR "illegal jump type %d", n FATAL; + FATAL("illegal jump type %d", n); } /*NOTREACHED*/ return (NULL); } Cell * -getaline(Node **a, int n) +awkgetline(Node **a, int n) /* get next line from specific input */ { /* a[0] is variable, a[1] is operator, a[2] is filename */ - register Cell *r, *x; - uchar *buf; + Cell *r, *x; FILE *fp; - size_t len; + char *buf; + size_t bufsize = recsize; + int mode; + + if ((buf = (char *)malloc(bufsize)) == NULL) + FATAL("out of memory in getline"); (void) fflush(stdout); /* in case someone is waiting for a prompt */ - r = gettemp(""); + r = gettemp(); if (a[1] != NULL) { /* getline < file */ x = execute(a[2]); /* filename */ - if ((int)a[1] == '|') /* input pipe */ - a[1] = (Node *)LE; /* arbitrary flag */ - fp = openfile((int)a[1], getsval(x)); - tempfree(x, ""); - buf = NULL; + mode = ptoi(a[1]); + if (mode == '|') /* input pipe */ + mode = LE; /* arbitrary flag */ + fp = openfile(mode, getsval(x)); + tempfree(x); if (fp == NULL) n = -1; else - n = readrec(&buf, &len, fp); - if (n > 0) { - if (a[0] != NULL) { /* getline var <file */ - (void) setsval(execute(a[0]), buf); - } else { /* getline <file */ - if (!(recloc->tval & DONTFREE)) - xfree(recloc->sval); - expand_buf(&record, &record_size, len); - (void) memcpy(record, buf, len); - record[len] = '\0'; - recloc->sval = record; - recloc->tval = REC | STR | DONTFREE; - donerec = 1; donefld = 0; + n = readrec(&buf, &bufsize, fp); + /*LINTED if*/ + if (n <= 0) { + ; + } else if (a[0] != NULL) { /* getline var <file */ + x = execute(a[0]); + (void) setsval(x, buf); + tempfree(x); + } else { /* getline <file */ + (void) setsval(recloc, buf); + if (is_number(recloc->sval)) { + recloc->fval = atof(recloc->sval); + recloc->tval |= NUM; } } - if (buf != NULL) - free(buf); } else { /* bare getline; use current input */ if (a[0] == NULL) /* getline */ - n = getrec(&record, &record_size); + n = getrec(&record, &recsize, 1); else { /* getline var */ - init_buf(&buf, &len, LINE_INCR); - n = getrec(&buf, &len); - (void) setsval(execute(a[0]), buf); - free(buf); + n = getrec(&buf, &bufsize, 0); + x = execute(a[0]); + (void) setsval(x, buf); + tempfree(x); } } (void) setfval(r, (Awkfloat)n); + free(buf); return (r); } /*ARGSUSED*/ Cell * -getnf(Node **a, int n) +getnf(Node **a, int n) /* get NF */ { if (donefld == 0) fldbld(); @@ -420,208 +505,241 @@ getnf(Node **a, int n) /*ARGSUSED*/ Cell * -array(Node **a, int n) +array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { - register Cell *x, *y, *z; - register uchar *s; - register Node *np; - uchar *buf; - size_t bsize, tlen, len, slen; + Cell *x, *y, *z; + char *s; + Node *np; + char *buf; + size_t bufsz = recsize; + size_t tlen = 0, len, nsub; + + if ((buf = (char *)malloc(bufsz)) == NULL) + FATAL("out of memory in array"); x = execute(a[0]); /* Cell* for symbol table */ - init_buf(&buf, &bsize, LINE_INCR); buf[0] = '\0'; - tlen = 0; - slen = strlen((char *)*SUBSEP); - for (np = a[1]; np; np = np->nnext) { + for (np = a[1]; np != NULL; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); - len = strlen((char *)s); - expand_buf(&buf, &bsize, tlen + len + slen); + len = strlen(s); + nsub = strlen(getsval(subseploc)); + (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1, + recsize, 0, "array"); (void) memcpy(&buf[tlen], s, len); tlen += len; if (np->nnext) { - (void) memcpy(&buf[tlen], *SUBSEP, slen); - tlen += slen; + (void) memcpy(&buf[tlen], *SUBSEP, nsub); + tlen += nsub; } buf[tlen] = '\0'; - tempfree(y, ""); + tempfree(y); } if (!isarr(x)) { - dprintf(("making %s into an array\n", x->nval)); + dprintf(("making %s into an array\n", NN(x->nval))); if (freeable(x)) xfree(x->sval); x->tval &= ~(STR|NUM|DONTFREE); x->tval |= ARR; - x->sval = (uchar *) makesymtab(NSYMTAB); + x->sval = (char *)makesymtab(NSYMTAB); } /*LINTED align*/ - z = setsymtab(buf, (uchar *)"", 0.0, STR|NUM, (Array *)x->sval); + z = setsymtab(buf, "", 0.0, STR|NUM, (Array *)x->sval); z->ctype = OCELL; z->csub = CVAR; - tempfree(x, ""); + tempfree(x); free(buf); return (z); } /*ARGSUSED*/ Cell * -delete(Node **a, int n) +awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { Cell *x, *y; Node *np; - uchar *buf, *s; - size_t bsize, tlen, slen, len; + char *s; + size_t nsub; + size_t tlen = 0, len; x = execute(a[0]); /* Cell* for symbol table */ - if (!isarr(x)) - return (true); - init_buf(&buf, &bsize, LINE_INCR); - buf[0] = '\0'; - tlen = 0; - slen = strlen((char *)*SUBSEP); - for (np = a[1]; np; np = np->nnext) { - y = execute(np); /* subscript */ - s = getsval(y); - len = strlen((char *)s); - expand_buf(&buf, &bsize, tlen + len + slen); - (void) memcpy(&buf[tlen], s, len); - tlen += len; - if (np->nnext) { - (void) memcpy(&buf[tlen], *SUBSEP, slen); - tlen += slen; + if (x == symtabloc) { + FATAL("cannot delete SYMTAB or its elements"); + } + if (!isarr(x)) { + dprintf(("making %s into an array\n", x->nval)); + if (freeable(x)) + xfree(x->sval); + x->tval &= ~(STR|NUM|DONTFREE); + x->tval |= ARR; + x->sval = (char *)makesymtab(NSYMTAB); + } + if (a[1] == NULL) { /* delete the elements, not the table */ + freesymtab(x); + x->tval &= ~STR; + x->tval |= ARR; + x->sval = (char *)makesymtab(NSYMTAB); + } else { + size_t bufsz = recsize; + char *buf; + if ((buf = (char *)malloc(bufsz)) == NULL) + FATAL("out of memory in awkdelete"); + buf[0] = '\0'; + for (np = a[1]; np != NULL; np = np->nnext) { + y = execute(np); /* subscript */ + s = getsval(y); + len = strlen(s); + nsub = strlen(getsval(subseploc)); + (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1, + recsize, 0, "awkdelete"); + (void) memcpy(&buf[tlen], s, len); + tlen += len; + if (np->nnext) { + (void) memcpy(&buf[tlen], *SUBSEP, nsub); + tlen += nsub; + } + buf[tlen] = '\0'; + tempfree(y); } - buf[tlen] = '\0'; - tempfree(y, ""); + freeelem(x, buf); + free(buf); } - freeelem(x, buf); - tempfree(x, ""); - free(buf); - return (true); + tempfree(x); + return (True); } /*ARGSUSED*/ Cell * -intest(Node **a, int n) +intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ { - register Cell *x, *ap, *k; + Cell *x, *ap, *k; Node *p; - uchar *buf; - uchar *s; - size_t bsize, tlen, slen, len; + char *buf; + char *s; + size_t bufsz = recsize; + size_t nsub; + size_t tlen = 0, len; ap = execute(a[1]); /* array name */ - if (!isarr(ap)) - ERROR "%s is not an array", ap->nval FATAL; - init_buf(&buf, &bsize, LINE_INCR); - buf[0] = 0; - tlen = 0; - slen = strlen((char *)*SUBSEP); - for (p = a[0]; p; p = p->nnext) { + if (!isarr(ap)) { + 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 = (char *)malloc(bufsz)) == NULL) { + FATAL("out of memory in intest"); + } + buf[0] = '\0'; + for (p = a[0]; p != NULL; p = p->nnext) { x = execute(p); /* expr */ s = getsval(x); - len = strlen((char *)s); - expand_buf(&buf, &bsize, tlen + len + slen); + len = strlen(s); + nsub = strlen(getsval(subseploc)); + (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1, + recsize, 0, "intest"); (void) memcpy(&buf[tlen], s, len); tlen += len; - tempfree(x, ""); + tempfree(x); if (p->nnext) { - (void) memcpy(&buf[tlen], *SUBSEP, slen); - tlen += slen; + (void) memcpy(&buf[tlen], *SUBSEP, nsub); + tlen += nsub; } buf[tlen] = '\0'; } /*LINTED align*/ k = lookup(buf, (Array *)ap->sval); - tempfree(ap, ""); + tempfree(ap); free(buf); if (k == NULL) - return (false); + return (False); else - return (true); + return (True); } Cell * -matchop(Node **a, int n) +matchop(Node **a, int n) /* ~ and match() */ { - register Cell *x, *y; - register uchar *s, *t; - register int i; + Cell *x, *y; + char *s, *t; + int i; fa *pfa; - int (*mf)() = match, mode = 0; + int (*mf)(fa *, const char *) = match, mode = 0; if (n == MATCHFCN) { mf = pmatch; mode = 1; } - x = execute(a[1]); + x = execute(a[1]); /* a[1] = target text */ s = getsval(x); - if (a[0] == 0) - i = (*mf)(a[2], s); + if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */ + i = (*mf)((fa *)a[2], s); else { - y = execute(a[2]); + y = execute(a[2]); /* a[2] = regular expr */ t = getsval(y); pfa = makedfa(t, mode); i = (*mf)(pfa, s); - tempfree(y, ""); + tempfree(y); } - tempfree(x, ""); + tempfree(x); if (n == MATCHFCN) { int start = patbeg - s + 1; if (patlen < 0) start = 0; (void) setfval(rstartloc, (Awkfloat)start); (void) setfval(rlengthloc, (Awkfloat)patlen); - x = gettemp(""); + x = gettemp(); x->tval = NUM; x->fval = start; return (x); - } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0) - return (true); + } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0)) + return (True); else - return (false); + return (False); } Cell * -boolop(Node **a, int n) +boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */ { - register Cell *x, *y; - register int i; + Cell *x, *y; + int i; x = execute(a[0]); i = istrue(x); - tempfree(x, ""); + tempfree(x); switch (n) { case BOR: if (i) - return (true); + return (True); y = execute(a[1]); i = istrue(y); - tempfree(y, ""); - return (i ? true : false); + tempfree(y); + return (i ? True : False); case AND: if (!i) - return (false); + return (False); y = execute(a[1]); i = istrue(y); - tempfree(y, ""); - return (i ? true : false); + tempfree(y); + return (i ? True : False); case NOT: - return (i ? false : true); + return (i ? False : True); default: /* can't happen */ - ERROR "unknown boolean operator %d", n FATAL; + FATAL("unknown boolean operator %d", n); } /*NOTREACHED*/ return (NULL); } Cell * -relop(Node **a, int n) +relop(Node **a, int n) /* a[0] < a[1], etc. */ { - register int i; - register Cell *x, *y; + int i; + Cell *x, *y; Awkfloat j; x = execute(a[0]); @@ -630,102 +748,108 @@ relop(Node **a, int n) j = x->fval - y->fval; i = j < 0 ? -1: (j > 0 ? 1: 0); } else { - i = strcmp((char *)getsval(x), (char *)getsval(y)); + i = strcmp(getsval(x), getsval(y)); } - tempfree(x, ""); - tempfree(y, ""); + tempfree(x); + tempfree(y); switch (n) { - case LT: return (i < 0 ? true : false); - case LE: return (i <= 0 ? true : false); - case NE: return (i != 0 ? true : false); - case EQ: return (i == 0 ? true : false); - case GE: return (i >= 0 ? true : false); - case GT: return (i > 0 ? true : false); + case LT: return (i < 0 ? True : False); + case LE: return (i <= 0 ? True : False); + case NE: return (i != 0 ? True : False); + case EQ: return (i == 0 ? True : False); + case GE: return (i >= 0 ? True : False); + case GT: return (i > 0 ? True : False); default: /* can't happen */ - ERROR "unknown relational operator %d", n FATAL; + FATAL("unknown relational operator %d", n); } /*NOTREACHED*/ - return (false); + return (False); } static void -tfree(Cell *a, char *s) +tfree(Cell *a) /* free a tempcell */ { - if (dbg > 1) { - (void) printf("## tfree %.8s %06lo %s\n", - s, (ulong_t)a, a->sval ? a->sval : (uchar *)""); - } - if (freeable(a)) + if (freeable(a)) { + dprintf(("freeing %s %s %o\n", + NN(a->nval), NN(a->sval), a->tval)); xfree(a->sval); + } if (a == tmps) - ERROR "tempcell list is curdled" FATAL; + FATAL("tempcell list is curdled"); a->cnext = tmps; tmps = a; } static Cell * -gettemp(char *s) +gettemp(void) /* get a tempcell */ { int i; - register Cell *x; + Cell *x; if (!tmps) { tmps = (Cell *)calloc(100, sizeof (Cell)); if (!tmps) - ERROR "no space for temporaries" FATAL; + FATAL("out of space for temporaries"); for (i = 1; i < 100; i++) tmps[i-1].cnext = &tmps[i]; - tmps[i-1].cnext = 0; + tmps[i-1].cnext = NULL; } x = tmps; tmps = x->cnext; *x = tempcell; - if (dbg > 1) - (void) printf("## gtemp %.8s %06lo\n", s, (ulong_t)x); + dprintf(("gtemp %.8s %06lo\n", NN(x->nval), (ulong_t)x)); return (x); } /*ARGSUSED*/ Cell * -indirect(Node **a, int n) +indirect(Node **a, int n) /* $( a[0] ) */ { - register Cell *x; - register int m; - register uchar *s; + Awkfloat val; + Cell *x; + int m; + char *s; x = execute(a[0]); - m = (int)getfval(x); + + /* freebsd: defend against super large field numbers */ + val = getfval(x); + if ((Awkfloat)INT_MAX < val) + FATAL("trying to access out of range field %s", x->nval); + m = (int)val; if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */ - ERROR "illegal field $(%s)", s FATAL; - tempfree(x, ""); + FATAL("illegal field $(%s), name \"%s\"", s, x->nval); + /* 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); } /*ARGSUSED*/ Cell * -substr(Node **a, int nnn) +substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ { - register int k, m, n; - register uchar *s; + int k, m, n; + char *s; int temp; - register Cell *x, *y, *z; + Cell *x, *y, *z = NULL; x = execute(a[0]); y = execute(a[1]); - if (a[2] != 0) + if (a[2] != NULL) z = execute(a[2]); s = getsval(x); - k = strlen((char *)s) + 1; + k = strlen(s) + 1; if (k <= 1) { - tempfree(x, ""); - tempfree(y, ""); - if (a[2] != 0) - tempfree(z, ""); - x = gettemp(""); - (void) setsval(x, (uchar *)""); + tempfree(x); + tempfree(y); + if (a[2] != NULL) { + tempfree(z); + } + x = gettemp(); + (void) setsval(x, ""); return (x); } m = (int)getfval(y); @@ -733,10 +857,10 @@ substr(Node **a, int nnn) m = 1; else if (m > k) m = k; - tempfree(y, ""); - if (a[2] != 0) { + tempfree(y); + if (a[2] != NULL) { n = (int)getfval(z); - tempfree(z, ""); + tempfree(z); } else n = k - 1; if (n < 0) @@ -744,21 +868,21 @@ substr(Node **a, int nnn) else if (n > k - m) n = k - m; dprintf(("substr: m=%d, n=%d, s=%s\n", m, n, s)); - y = gettemp(""); + y = gettemp(); temp = s[n + m - 1]; /* with thanks to John Linderman */ s[n + m - 1] = '\0'; (void) setsval(y, s + m - 1); s[n + m - 1] = temp; - tempfree(x, ""); + tempfree(x); return (y); } /*ARGSUSED*/ Cell * -sindex(Node **a, int nnn) +sindex(Node **a, int nnn) /* index(a[0], a[1]) */ { - register Cell *x, *y, *z; - register uchar *s1, *s2, *p1, *p2, *q; + Cell *x, *y, *z; + char *s1, *s2, *p1, *p2, *q; Awkfloat v = 0.0; x = execute(a[0]); @@ -766,7 +890,7 @@ sindex(Node **a, int nnn) y = execute(a[1]); s2 = getsval(y); - z = gettemp(""); + z = gettemp(); for (p1 = s1; *p1 != '\0'; p1++) { for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++) ; @@ -775,26 +899,32 @@ sindex(Node **a, int nnn) break; } } - tempfree(x, ""); - tempfree(y, ""); + tempfree(x); + tempfree(y); (void) setfval(z, v); return (z); } -void -format(uchar **bufp, uchar *s, Node *a) +#define MAXNUMSIZE 50 + +/* printf-like conversions */ +int +format(char **pbuf, int *pbufsize, const char *s, Node *a) { - uchar *fmt; - register uchar *os; - register Cell *x; - int flag = 0, len; - uchar_t *buf; - size_t bufsize, fmtsize, cnt, tcnt, ret; - - init_buf(&buf, &bufsize, LINE_INCR); - init_buf(&fmt, &fmtsize, LINE_INCR); + char *fmt; + const char *os; + Cell *x; + int flag = 0, n, len; + int fmtwd; /* format width */ + char *buf = *pbuf; + size_t bufsize = *pbufsize; + size_t fmtsz = recsize; + size_t cnt, tcnt, ret; + os = s; cnt = 0; + if ((fmt = (char *)malloc(fmtsz)) == NULL) + FATAL("out of memory in format()"); while (*s) { if (*s != '%') { expand_buf(&buf, &bufsize, cnt); @@ -807,58 +937,77 @@ format(uchar **bufp, uchar *s, Node *a) s += 2; continue; } + /* + * have to be real careful in case this is a huge number, + * eg, "%100000d". + */ + fmtwd = atoi(s+1); + if (fmtwd < 0) + fmtwd = -fmtwd; for (tcnt = 0; ; s++) { - expand_buf(&fmt, &fmtsize, tcnt); + expand_buf(&fmt, &fmtsz, tcnt); fmt[tcnt++] = *s; if (*s == '\0') break; - if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') + if (isalpha((uschar)*s) && + *s != 'l' && *s != 'h' && *s != 'L') break; /* the ansi panoply */ + if (*s == '$') { + FATAL("'$' not permitted in awk formats"); + } if (*s == '*') { if (a == NULL) { - ERROR - "not enough args in printf(%s) or sprintf(%s)", os, os FATAL; + FATAL("not enough args in printf(%s) " + "or sprintf(%s)", os, os); } x = execute(a); a = a->nnext; tcnt--; - expand_buf(&fmt, &fmtsize, tcnt + 12); - ret = sprintf((char *)&fmt[tcnt], "%d", - (int)getfval(x)); + expand_buf(&fmt, &fmtsz, tcnt + 12); + fmtwd = (int)getfval(x); + ret = sprintf(&fmt[tcnt], "%d", fmtwd); + if (fmtwd < 0) + fmtwd = -fmtwd; tcnt += ret; - tempfree(x, ""); + tempfree(x); } } fmt[tcnt] = '\0'; + if (fmtwd < 0) + fmtwd = -fmtwd; switch (*s) { + case 'a': case 'A': + flag = *s; + break; case 'f': case 'e': case 'g': case 'E': case 'G': - flag = 1; + flag = 'f'; break; case 'd': case 'i': - flag = 2; + flag = 'd'; if (*(s-1) == 'l') break; fmt[tcnt - 1] = 'l'; - expand_buf(&fmt, &fmtsize, tcnt); + expand_buf(&fmt, &fmtsz, tcnt); fmt[tcnt++] = 'd'; fmt[tcnt] = '\0'; break; case 'o': case 'x': case 'X': case 'u': - flag = *(s-1) == 'l' ? 2 : 3; + flag = *(s-1) == 'l' ? 'd' : 'u'; break; case 's': - flag = 4; + flag = 's'; break; case 'c': - flag = 5; + flag = 'c'; break; default: - flag = 0; + WARNING("weird printf conversion %s", fmt); + flag = '?'; break; } - if (flag == 0) { - len = strlen((char *)fmt); + if (flag == '?') { + len = strlen(fmt); expand_buf(&buf, &bufsize, cnt + len); (void) memcpy(&buf[cnt], fmt, len); cnt += len; @@ -866,79 +1015,100 @@ format(uchar **bufp, uchar *s, Node *a) continue; } if (a == NULL) { - ERROR - "not enough args in printf(%s) or sprintf(%s)", os, os FATAL; + FATAL("not enough args in printf(%s) " + "or sprintf(%s)", os, os); } x = execute(a); a = a->nnext; - for (;;) { - /* make sure we have at least 1 byte space */ - expand_buf(&buf, &bufsize, cnt + 1); - len = bufsize - cnt; - switch (flag) { - case 1: - /*LINTED*/ - ret = snprintf((char *)&buf[cnt], len, - (char *)fmt, getfval(x)); - break; - case 2: - /*LINTED*/ - ret = snprintf((char *)&buf[cnt], len, - (char *)fmt, (long)getfval(x)); - break; - case 3: + n = MAXNUMSIZE; + if (fmtwd > n) + n = fmtwd; +retry: + /* make sure we have at least 1 byte space */ + (void) adjbuf(&buf, &bufsize, 1 + n + cnt, + recsize, NULL, "format5"); + len = bufsize - cnt; + switch (flag) { + case 'a': + case 'A': + case 'f': + /*LINTED*/ + ret = snprintf(&buf[cnt], len, + fmt, getfval(x)); + break; + case 'd': + /*LINTED*/ + ret = snprintf(&buf[cnt], len, + fmt, (long)getfval(x)); + break; + case 'u': + /*LINTED*/ + ret = snprintf(&buf[cnt], len, + fmt, (int)getfval(x)); + break; + case 's': + /*LINTED*/ + ret = snprintf(&buf[cnt], len, + fmt, getsval(x)); + break; + case 'c': + if (!isnum(x)) { /*LINTED*/ - ret = snprintf((char *)&buf[cnt], len, - (char *)fmt, (int)getfval(x)); + ret = snprintf(&buf[cnt], len, + fmt, getsval(x)[0]); break; - case 4: + } + if (getfval(x)) { /*LINTED*/ - ret = snprintf((char *)&buf[cnt], len, - (char *)fmt, getsval(x)); - break; - case 5: - if (isnum(x)) { - /*LINTED*/ - ret = snprintf((char *)&buf[cnt], len, - (char *)fmt, (int)getfval(x)); - } else { - /*LINTED*/ - ret = snprintf((char *)&buf[cnt], len, - (char *)fmt, getsval(x)[0]); - } - break; - default: - ret = 0; + ret = snprintf(&buf[cnt], len, + fmt, (int)getfval(x)); + } else { + /* explicit null byte */ + buf[cnt] = '\0'; + /* next output will start here */ + buf[cnt + 1] = '\0'; + ret = 1; } - if (ret < len) - break; - expand_buf(&buf, &bufsize, cnt + ret); + break; + default: + FATAL("can't happen: " + "bad conversion %c in format()", flag); + } + if (ret >= len) { + (void) adjbuf(&buf, &bufsize, cnt + ret + 1, + recsize, NULL, "format6"); + goto retry; } - tempfree(x, ""); + tempfree(x); cnt += ret; s++; } buf[cnt] = '\0'; - for (; a; a = a->nnext) /* evaluate any remaining args */ - (void) execute(a); - *bufp = tostring(buf); - free(buf); free(fmt); + for (; a != NULL; a = a->nnext) /* evaluate any remaining args */ + (void) execute(a); + *pbuf = buf; + *pbufsize = bufsize; + return (cnt); } /*ARGSUSED*/ Cell * -a_sprintf(Node **a, int n) +awksprintf(Node **a, int n) /* sprintf(a[0]) */ { - register Cell *x; - register Node *y; - uchar *buf; + Cell *x; + Node *y; + char *buf; + int bufsz = 3 * recsize; + if ((buf = (char *)malloc(bufsz)) == NULL) + FATAL("out of memory in awksprintf"); y = a[0]->nnext; x = execute(a[0]); - format(&buf, getsval(x), y); - tempfree(x, ""); - x = gettemp(""); + if (format(&buf, &bufsz, getsval(x), y) == -1) + FATAL("sprintf string %.30s... too long. can't happen.", buf); + tempfree(x); + x = gettemp(); x->sval = buf; x->tval = STR; return (x); @@ -946,44 +1116,55 @@ a_sprintf(Node **a, int n) /*ARGSUSED*/ Cell * -aprintf(Node **a, int n) +awkprintf(Node **a, int n) /* printf */ { + /* a[0] is list of args, starting with format string */ + /* a[1] is redirection operator, a[2] is redirection file */ FILE *fp; - register Cell *x; - register Node *y; - uchar *buf; + Cell *x; + Node *y; + char *buf; + int len; + int bufsz = 3 * recsize; + if ((buf = (char *)malloc(bufsz)) == NULL) + FATAL("out of memory in awkprintf"); y = a[0]->nnext; x = execute(a[0]); - format(&buf, getsval(x), y); - tempfree(x, ""); - if (a[1] == NULL) - (void) fputs((char *)buf, stdout); - else { - fp = redirect((int)a[1], a[2]); - (void) fputs((char *)buf, fp); + if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) + FATAL("printf string %.30s... too long. can't happen.", buf); + tempfree(x); + if (a[1] == NULL) { + (void) fwrite(buf, len, 1, stdout); + if (ferror(stdout)) + FATAL("write error on stdout"); + } else { + fp = redirect(ptoi(a[1]), a[2]); + (void) fwrite(buf, len, 1, fp); (void) fflush(fp); + if (ferror(fp)) + FATAL("write error on %s", filename(fp)); } free(buf); - return (true); + return (True); } Cell * -arith(Node **a, int n) +arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ { - Awkfloat i, j; + Awkfloat i, j = 0; double v; - register Cell *x, *y, *z; + Cell *x, *y, *z; x = execute(a[0]); i = getfval(x); - tempfree(x, ""); - if (n != UMINUS) { + tempfree(x); + if (n != UMINUS && n != UPLUS) { y = execute(a[1]); j = getfval(y); - tempfree(y, ""); + tempfree(y); } - z = gettemp(""); + z = gettemp(); switch (n) { case ADD: i += j; @@ -996,18 +1177,20 @@ arith(Node **a, int n) break; case DIVIDE: if (j == 0) - ERROR "division by zero" FATAL; + FATAL("division by zero"); i /= j; break; case MOD: if (j == 0) - ERROR "division by zero in mod" FATAL; + FATAL("division by zero in mod"); (void) modf(i/j, &v); i = i - j * v; break; case UMINUS: i = -i; break; + case UPLUS: /* handled by getfval(), above */ + break; case POWER: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ i = ipow(i, (int)j); @@ -1015,14 +1198,14 @@ arith(Node **a, int n) i = errcheck(pow(i, j), "pow"); break; default: /* can't happen */ - ERROR "illegal arithmetic operator %d", n FATAL; + FATAL("illegal arithmetic operator %d", n); } (void) setfval(z, i); return (z); } static double -ipow(double x, int n) +ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */ { double v; @@ -1036,10 +1219,10 @@ ipow(double x, int n) } Cell * -incrdecr(Node **a, int n) +incrdecr(Node **a, int n) /* a[0]++, etc. */ { - register Cell *x, *z; - register int k; + Cell *x, *z; + int k; Awkfloat xf; x = execute(a[0]); @@ -1049,34 +1232,42 @@ incrdecr(Node **a, int n) (void) setfval(x, xf + k); return (x); } - z = gettemp(""); + z = gettemp(); (void) setfval(z, xf); (void) setfval(x, xf + k); - tempfree(x, ""); + tempfree(x); return (z); } +/* a[0] = a[1], a[0] += a[1], etc. */ +/* this is subtle; don't muck with it. */ Cell * assign(Node **a, int n) { - register Cell *x, *y; + Cell *x, *y; Awkfloat xf, yf; double v; y = execute(a[1]); x = execute(a[0]); /* order reversed from before... */ if (n == ASSIGN) { /* ordinary assignment */ - if ((y->tval & (STR|NUM)) == (STR|NUM)) { + /*LINTED if*/ + if (x == y && !(x->tval & (FLD|REC)) && x != nfloc) { + /* + * If this is a self-assignment, we leave things alone, + * unless it's a field or NF. + */ + } else if ((y->tval & (STR|NUM)) == (STR|NUM)) { (void) setsval(x, getsval(y)); x->fval = getfval(y); x->tval |= NUM; - } else if (y->tval & STR) + } else if (isstr(y)) (void) setsval(x, getsval(y)); - else if (y->tval & NUM) + else if (isnum(y)) (void) setfval(x, getfval(y)); else funnyvar(y, "read value of"); - tempfree(y, ""); + tempfree(y); return (x); } xf = getfval(x); @@ -1093,12 +1284,12 @@ assign(Node **a, int n) break; case DIVEQ: if (yf == 0) - ERROR "division by zero in /=" FATAL; + FATAL("division by zero in /="); xf /= yf; break; case MODEQ: if (yf == 0) - ERROR "division by zero in %%=" FATAL; + FATAL("division by zero in %%="); (void) modf(xf/yf, &v); xf = xf - yf * v; break; @@ -1109,55 +1300,55 @@ assign(Node **a, int n) xf = errcheck(pow(xf, yf), "pow"); break; default: - ERROR "illegal assignment operator %d", n FATAL; + FATAL("illegal assignment operator %d", n); break; } - tempfree(y, ""); + tempfree(y); (void) setfval(x, xf); return (x); } /*ARGSUSED*/ Cell * -cat(Node **a, int q) +cat(Node **a, int q) /* a[0] cat a[1] */ { - register Cell *x, *y, *z; - register int n1, n2; - register uchar *s; + Cell *x, *y, *z; + int n1, n2; + char *s = NULL; + size_t ssz = 0; x = execute(a[0]); + n1 = strlen(getsval(x)); + (void) adjbuf(&s, &ssz, n1 + 1, recsize, 0, "cat1"); + (void) strncpy(s, x->sval, ssz); + y = execute(a[1]); - (void) getsval(x); - (void) getsval(y); - n1 = strlen((char *)x->sval); - n2 = strlen((char *)y->sval); - s = (uchar *)malloc(n1 + n2 + 1); - if (s == NULL) { - ERROR "out of space concatenating %.15s and %.15s", - x->sval, y->sval FATAL; - } - (void) strcpy((char *)s, (char *)x->sval); - (void) strcpy((char *)s + n1, (char *)y->sval); - tempfree(y, ""); - z = gettemp(""); + n2 = strlen(getsval(y)); + (void) adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat2"); + (void) strncpy(s + n1, y->sval, ssz - n1); + + tempfree(x); + tempfree(y); + + z = gettemp(); z->sval = s; z->tval = STR; - tempfree(x, ""); + return (z); } /*ARGSUSED*/ Cell * -pastat(Node **a, int n) +pastat(Node **a, int n) /* a[0] { a[1] } */ { - register Cell *x; + Cell *x; - if (a[0] == 0) + if (a[0] == NULL) x = execute(a[1]); else { x = execute(a[0]); if (istrue(x)) { - tempfree(x, ""); + tempfree(x); x = execute(a[1]); } } @@ -1166,73 +1357,83 @@ pastat(Node **a, int n) /*ARGSUSED*/ Cell * -dopa2(Node **a, int n) +dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ { Cell *x; int pair; - static int *pairstack = NULL; if (!pairstack) { /* first time */ dprintf(("paircnt: %d\n", paircnt)); - pairstack = (int *)malloc(sizeof (int) * paircnt); - if (!pairstack) - ERROR "out of space in dopa2" FATAL; - (void) memset(pairstack, 0, sizeof (int) * paircnt); + pairstack = (int *)calloc(paircnt, sizeof (int)); + if (pairstack == NULL) + FATAL("out of space in dopa2"); } - pair = (int)a[3]; + pair = ptoi(a[3]); if (pairstack[pair] == 0) { x = execute(a[0]); if (istrue(x)) pairstack[pair] = 1; - tempfree(x, ""); + tempfree(x); } if (pairstack[pair] == 1) { x = execute(a[1]); if (istrue(x)) pairstack[pair] = 0; - tempfree(x, ""); + tempfree(x); x = execute(a[2]); return (x); } - return (false); + return (False); } /*ARGSUSED*/ Cell * -split(Node **a, int nnn) +split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ { - Cell *x, *y, *ap; - register uchar *s; - register int sep; - uchar *t, temp, num[11], *fs; - int n, tempstat; + Cell *x = NULL, *y, *ap; + char *s, *origs; + char *fs, *origfs = NULL; + int sep; + char *t, temp, num[50]; + int n, tempstat, arg3type; y = execute(a[0]); /* source string */ - s = getsval(y); - if (a[2] == 0) /* fs string */ - fs = *FS; - else if ((int)a[3] == STRING) { /* split(str,arr,"string") */ + origs = s = tostring(getsval(y)); + arg3type = ptoi(a[3]); + if (a[2] == NULL) /* fs string */ + fs = getsval(fsloc); + else if (arg3type == STRING) { /* split(str,arr,"string") */ x = execute(a[2]); - fs = getsval(x); - } else if ((int)a[3] == REGEXPR) - fs = (uchar *)"(regexpr)"; /* split(str,arr,/regexpr/) */ + origfs = fs = tostring(getsval(x)); + tempfree(x); + } else if (arg3type == REGEXPR) + fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ else - ERROR "illegal type of split()" FATAL; + FATAL("illegal type of split"); 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, NN(ap->nval), fs)); ap->tval &= ~STR; ap->tval |= ARR; - ap->sval = (uchar *)makesymtab(NSYMTAB); + ap->sval = (char *)makesymtab(NSYMTAB); n = 0; - if (*s != '\0' && strlen((char *)fs) > 1 || (int)a[3] == REGEXPR) { + if (arg3type == REGEXPR && strlen((char *)((fa*)a[2])->restr) == 0) { + /* + * split(s, a, //); have to arrange things such that it looks + * like an empty separator. + */ + arg3type = 0; + fs = ""; + sep = 0; + } + if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */ fa *pfa; - if ((int)a[3] == REGEXPR) { /* it's ready already */ + if (arg3type == REGEXPR) { /* it's ready already */ pfa = (fa *)a[2]; } else { pfa = makedfa(fs, 1); @@ -1242,12 +1443,12 @@ split(Node **a, int nnn) pfa->initstat = 2; do { n++; - (void) sprintf((char *)num, "%d", n); + (void) sprintf(num, "%d", n); temp = *patbeg; *patbeg = '\0'; if (is_number(s)) { (void) setsymtab(num, s, - atof((char *)s), + atof(s), /*LINTED align*/ STR|NUM, (Array *)ap->sval); } else { @@ -1259,19 +1460,22 @@ split(Node **a, int nnn) s = patbeg + patlen; if (*(patbeg+patlen-1) == 0 || *s == 0) { n++; - (void) sprintf((char *)num, "%d", n); - (void) setsymtab(num, (uchar *)"", 0.0, + (void) sprintf(num, "%d", n); + (void) setsymtab(num, "", 0.0, /*LINTED align*/ STR, (Array *)ap->sval); pfa->initstat = tempstat; goto spdone; } } while (nematch(pfa, s)); + /* bwk: has to be here to reset */ + /* cf gsub and refldbld */ + pfa->initstat = tempstat; } n++; - (void) sprintf((char *)num, "%d", n); + (void) sprintf(num, "%d", n); if (is_number(s)) { - (void) setsymtab(num, s, atof((char *)s), + (void) setsymtab(num, s, atof(s), /*LINTED align*/ STR|NUM, (Array *)ap->sval); } else { @@ -1284,7 +1488,7 @@ spdone: for (n = 0; ; ) { while (*s == ' ' || *s == '\t' || *s == '\n') s++; - if (*s == 0) + if (*s == '\0') break; n++; t = s; @@ -1295,9 +1499,9 @@ spdone: ; temp = *s; *s = '\0'; - (void) sprintf((char *)num, "%d", n); + (void) sprintf(num, "%d", n); if (is_number(t)) { - (void) setsymtab(num, t, atof((char *)t), + (void) setsymtab(num, t, atof(t), /*LINTED align*/ STR|NUM, (Array *)ap->sval); } else { @@ -1306,10 +1510,27 @@ spdone: STR, (Array *)ap->sval); } *s = temp; - if (*s != 0) + if (*s != '\0') s++; } - } else if (*s != 0) { + } else if (sep == '\0') { /* split(s, a, "") => 1 char/elem */ + for (n = 0; *s != 0; s++) { + char buf[2]; + n++; + (void) sprintf(num, "%d", n); + buf[0] = *s; + buf[1] = '\0'; + if (isdigit((uschar)buf[0])) { + (void) setsymtab(num, buf, atof(buf), + /*LINTED align*/ + STR|NUM, (Array *)ap->sval); + } else { + (void) setsymtab(num, buf, 0.0, + /*LINTED align*/ + STR, (Array *)ap->sval); + } + } + } else if (*s != '\0') { for (;;) { n++; t = s; @@ -1317,9 +1538,9 @@ spdone: s++; temp = *s; *s = '\0'; - (void) sprintf((char *)num, "%d", n); + (void) sprintf(num, "%d", n); if (is_number(t)) { - (void) setsymtab(num, t, atof((char *)t), + (void) setsymtab(num, t, atof(t), /*LINTED align*/ STR|NUM, (Array *)ap->sval); } else { @@ -1328,15 +1549,15 @@ spdone: STR, (Array *)ap->sval); } *s = temp; - if (*s++ == 0) + if (*s++ == '\0') break; } } - tempfree(ap, ""); - tempfree(y, ""); - if (a[2] != 0 && (int)a[3] == STRING) - tempfree(x, ""); - x = gettemp(""); + tempfree(ap); + tempfree(y); + free(origs); + free(origfs); + x = gettemp(); x->tval = NUM; x->fval = n; return (x); @@ -1344,16 +1565,16 @@ spdone: /*ARGSUSED*/ Cell * -condexpr(Node **a, int n) +condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ { - register Cell *x; + Cell *x; x = execute(a[0]); if (istrue(x)) { - tempfree(x, ""); + tempfree(x); x = execute(a[1]); } else { - tempfree(x, ""); + tempfree(x); x = execute(a[2]); } return (x); @@ -1361,16 +1582,16 @@ condexpr(Node **a, int n) /*ARGSUSED*/ Cell * -ifstat(Node **a, int n) +ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ { - register Cell *x; + Cell *x; x = execute(a[0]); if (istrue(x)) { - tempfree(x, ""); + tempfree(x); x = execute(a[1]); - } else if (a[2] != 0) { - tempfree(x, ""); + } else if (a[2] != NULL) { + tempfree(x); x = execute(a[2]); } return (x); @@ -1378,123 +1599,139 @@ ifstat(Node **a, int n) /*ARGSUSED*/ Cell * -whilestat(Node **a, int n) +whilestat(Node **a, int n) /* while (a[0]) a[1] */ { - register Cell *x; + Cell *x; for (;;) { x = execute(a[0]); if (!istrue(x)) return (x); - tempfree(x, ""); + tempfree(x); x = execute(a[1]); if (isbreak(x)) { - x = true; + x = True; return (x); } if (isnext(x) || isexit(x) || isret(x)) return (x); - tempfree(x, ""); + tempfree(x); } } /*ARGSUSED*/ Cell * -dostat(Node **a, int n) +dostat(Node **a, int n) /* do a[0]; while(a[1]) */ { - register Cell *x; + Cell *x; for (;;) { x = execute(a[0]); if (isbreak(x)) - return (true); + return (True); if (isnext(x) || isexit(x) || isret(x)) return (x); - tempfree(x, ""); + tempfree(x); x = execute(a[1]); if (!istrue(x)) return (x); - tempfree(x, ""); + tempfree(x); } } /*ARGSUSED*/ Cell * -forstat(Node **a, int n) +forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ { - register Cell *x; + Cell *x; x = execute(a[0]); - tempfree(x, ""); + tempfree(x); for (;;) { - if (a[1] != 0) { + if (a[1] != NULL) { x = execute(a[1]); if (!istrue(x)) return (x); else - tempfree(x, ""); + tempfree(x); } x = execute(a[3]); if (isbreak(x)) /* turn off break */ - return (true); + return (True); if (isnext(x) || isexit(x) || isret(x)) return (x); - tempfree(x, ""); + tempfree(x); x = execute(a[2]); - tempfree(x, ""); + tempfree(x); } } /*ARGSUSED*/ Cell * -instat(Node **a, int n) +instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ { - register Cell *x, *vp, *arrayp, *cp, *ncp; + Cell *x, *vp, *arrayp, *cp, *ncp; Array *tp; int i; vp = execute(a[0]); arrayp = execute(a[1]); - if (!isarr(arrayp)) - ERROR "%s is not an array", arrayp->nval FATAL; + if (!isarr(arrayp)) { + dprintf(("making %s into an array\n", arrayp->nval)); + if (freeable(arrayp)) + xfree(arrayp->sval); + arrayp->tval &= ~(STR|NUM|DONTFREE); + arrayp->tval |= ARR; + arrayp->sval = (char *)makesymtab(NSYMTAB); + } /*LINTED align*/ tp = (Array *)arrayp->sval; - tempfree(arrayp, ""); + tempfree(arrayp); for (i = 0; i < tp->size; i++) { /* this routine knows too much */ for (cp = tp->tab[i]; cp != NULL; cp = ncp) { (void) setsval(vp, cp->nval); ncp = cp->cnext; x = execute(a[2]); if (isbreak(x)) { - tempfree(vp, ""); - return (true); + tempfree(vp); + return (True); } if (isnext(x) || isexit(x) || isret(x)) { - tempfree(vp, ""); + tempfree(vp); return (x); } - tempfree(x, ""); + tempfree(x); } } - return (true); + return (True); } /*ARGSUSED*/ Cell * -bltin(Node **a, int n) +bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ { - register Cell *x, *y; + Cell *x, *y; Awkfloat u; - register int t; - uchar *p, *buf; + int t; + Awkfloat tmp; + char *p, *buf; Node *nextarg; + FILE *fp; + void flush_all(void); + int status = 0; - t = (int)a[0]; + t = ptoi(a[0]); x = execute(a[1]); nextarg = a[1]->nnext; switch (t) { case FLENGTH: - u = (Awkfloat)strlen((char *)getsval(x)); break; + if (isarr(x)) { + /* LINTED align */ + u = ((Array *)x->sval)->nelem; + } else { + u = strlen(getsval(x)); + } + break; case FLOG: u = errcheck(log(getfval(x)), "log"); break; case FINT: @@ -1508,60 +1745,82 @@ bltin(Node **a, int n) case FCOS: u = cos(getfval(x)); break; case FATAN: - if (nextarg == 0) { - ERROR "atan2 requires two arguments; returning 1.0" - WARNING; + if (nextarg == NULL) { + WARNING("atan2 requires two arguments; returning 1.0"); u = 1.0; } else { y = execute(a[1]->nnext); u = atan2(getfval(x), getfval(y)); - tempfree(y, ""); + tempfree(y); nextarg = nextarg->nnext; } break; case FSYSTEM: /* in case something is buffered already */ (void) fflush(stdout); - /* 256 is unix-dep */ - u = (Awkfloat)system((char *)getsval(x)) / 256; + status = system(getsval(x)); + u = status; + if (status != -1) { + if (WIFEXITED(status)) { + u = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + u = WTERMSIG(status) + 256; + if (WCOREDUMP(status)) + u += 256; + } else /* something else?!? */ + u = 0; + } break; case FRAND: - u = (Awkfloat)(rand() % 32767) / 32767.0; + /* 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); - srand((int)u); u = (int)u; + tmp = u; + srand((unsigned int) u); + u = srand_seed; + srand_seed = tmp; break; case FTOUPPER: case FTOLOWER: buf = tostring(getsval(x)); if (t == FTOUPPER) { for (p = buf; *p; p++) - if (islower(*p)) - *p = toupper(*p); + if (islower((uschar)*p)) + *p = toupper((uschar)*p); } else { for (p = buf; *p; p++) - if (isupper(*p)) - *p = tolower(*p); + if (isupper((uschar)*p)) + *p = tolower((uschar)*p); } - tempfree(x, ""); - x = gettemp(""); + tempfree(x); + x = gettemp(); (void) setsval(x, buf); free(buf); return (x); + case FFLUSH: + if (isrec(x) || strlen(getsval(x)) == 0) { + flush_all(); /* fflush() or fflush("") -> all */ + u = 0; + } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL) + u = EOF; + else + u = fflush(fp); + break; default: /* can't happen */ - ERROR "illegal function type %d", t FATAL; + FATAL("illegal function type %d", t); break; } - tempfree(x, ""); - x = gettemp(""); + tempfree(x); + x = gettemp(); (void) setfval(x, u); - if (nextarg != 0) { - ERROR "warning: function has too many arguments" WARNING; - for (; nextarg; nextarg = nextarg->nnext) + if (nextarg != NULL) { + WARNING("warning: function has too many arguments"); + for (; nextarg != NULL; nextarg = nextarg->nnext) (void) execute(nextarg); } return (x); @@ -1569,28 +1828,30 @@ bltin(Node **a, int n) /*ARGSUSED*/ Cell * -print(Node **a, int n) +printstat(Node **a, int n) /* print a[0] */ { - register Node *x; - register Cell *y; + Node *x; + Cell *y; FILE *fp; - if (a[1] == 0) + if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */ fp = stdout; else - fp = redirect((int)a[1], a[2]); + fp = redirect(ptoi(a[1]), a[2]); for (x = a[0]; x != NULL; x = x->nnext) { y = execute(x); - (void) fputs((char *)getsval(y), fp); - tempfree(y, ""); + (void) fputs(getpssval(y), fp); + tempfree(y); if (x->nnext == NULL) - (void) fputs((char *)*ORS, fp); + (void) fputs(getsval(orsloc), fp); else - (void) fputs((char *)*OFS, fp); + (void) fputs(getsval(ofsloc), fp); } - if (a[1] != 0) + if (a[1] != NULL) (void) fflush(fp); - return (true); + if (ferror(fp)) + FATAL("write error on %s", filename(fp)); + return (True); } /*ARGSUSED*/ @@ -1600,67 +1861,100 @@ nullproc(Node **a, int n) return (0); } -struct { - FILE *fp; - uchar *fname; - int mode; /* '|', 'a', 'w' */ -} files[FOPEN_MAX]; static FILE * -redirect(int a, Node *b) +redirect(int a, Node *b) /* set up all i/o redirections */ { FILE *fp; Cell *x; - uchar *fname; + char *fname; x = execute(b); fname = getsval(x); fp = openfile(a, fname); if (fp == NULL) - ERROR "can't open file %s", fname FATAL; - tempfree(x, ""); + FATAL("can't open file %s", fname); + tempfree(x); return (fp); } +struct files { + FILE *fp; + const char *fname; + int mode; /* '|', 'a', 'w' => LE/LT, GT */ +} *files; + +int nfiles; + +void +stdinit(void) /* in case stdin, etc., are not constants */ +{ + nfiles = FOPEN_MAX; + files = calloc(nfiles, sizeof (*files)); + if (files == NULL) + FATAL("can't allocate file memory for %u files", nfiles); + files[0].fp = stdin; + files[0].fname = "/dev/stdin"; + files[0].mode = LT; + files[1].fp = stdout; + files[1].fname = "/dev/stdout"; + files[1].mode = GT; + files[2].fp = stderr; + files[2].fname = "/dev/stderr"; + files[2].mode = GT; +} + static FILE * -openfile(int a, uchar *s) +openfile(int a, const char *s) { - register int i, m; - register FILE *fp; + int i, m; + FILE *fp = NULL; if (*s == '\0') - ERROR "null file name in print or getline" FATAL; - for (i = 0; i < FOPEN_MAX; i++) { - if (files[i].fname && - strcmp((char *)s, (char *)files[i].fname) == 0) { + FATAL("null file name in print or getline"); + for (i = 0; i < nfiles; i++) { + if (files[i].fname && strcmp(s, files[i].fname) == 0) { if (a == files[i].mode || - a == APPEND && files[i].mode == GT) { + (a == APPEND && files[i].mode == GT)) { return (files[i].fp); } + if (a == FFLUSH) + return (files[i].fp); } } - for (i = 0; i < FOPEN_MAX; i++) { + if (a == FFLUSH) /* didn't find it, so don't create it! */ + return (NULL); + + for (i = 0; i < nfiles; i++) { if (files[i].fp == 0) break; } - if (i >= FOPEN_MAX) - ERROR "%s makes too many open files", s FATAL; + if (i >= nfiles) { + struct files *nf; + int nnf = nfiles + FOPEN_MAX; + nf = realloc(files, nnf * sizeof (*nf)); + if (nf == NULL) + FATAL("cannot grow files for %s and %d files", s, nnf); + (void) memset(&nf[nfiles], 0, FOPEN_MAX * sizeof (*nf)); + nfiles = nnf; + files = nf; + } (void) fflush(stdout); /* force a semblance of order */ m = a; if (a == GT) { - fp = fopen((char *)s, "w"); + fp = fopen(s, "wF"); } else if (a == APPEND) { - fp = fopen((char *)s, "a"); + fp = fopen(s, "aF"); m = GT; /* so can mix > and >> */ } else if (a == '|') { /* output pipe */ - fp = popen((char *)s, "w"); + fp = popen(s, "wF"); } else if (a == LE) { /* input pipe */ - fp = popen((char *)s, "r"); + fp = popen(s, "rF"); } else if (a == LT) { /* getline <file */ - fp = strcmp((char *)s, "-") == 0 ? - stdin : fopen((char *)s, "r"); /* "-" is stdin */ + fp = strcmp(s, "-") == 0 ? + stdin : fopen(s, "rF"); /* "-" is stdin */ } else /* can't happen */ - ERROR "illegal redirection" FATAL; + FATAL("illegal redirection %d", a); if (fp != NULL) { files[i].fname = tostring(s); files[i].fp = fp; @@ -1669,38 +1963,52 @@ openfile(int a, uchar *s) return (fp); } +const char * +filename(FILE *fp) +{ + int i; + + for (i = 0; i < nfiles; i++) + if (fp == files[i].fp) + return (files[i].fname); + return ("???"); +} + /*ARGSUSED*/ Cell * closefile(Node **a, int n) { - register Cell *x; + Cell *x; int i, stat; x = execute(a[0]); (void) getsval(x); - for (i = 0; i < FOPEN_MAX; i++) { - if (files[i].fname && - strcmp((char *)x->sval, (char *)files[i].fname) == 0) { + stat = -1; + for (i = 0; i < nfiles; i++) { + if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { if (ferror(files[i].fp)) { - ERROR "i/o error occurred on %s", - files[i].fname WARNING; + WARNING("i/o error occurred on %s", + files[i].fname); } if (files[i].mode == '|' || files[i].mode == LE) stat = pclose(files[i].fp); else stat = fclose(files[i].fp); if (stat == EOF) { - ERROR "i/o error occurred closing %s", - files[i].fname WARNING; + WARNING("i/o error occurred closing %s", + files[i].fname); } - xfree(files[i].fname); + if (i > 2) /* don't do /dev/std... */ + xfree(files[i].fname); /* watch out for ref thru this */ files[i].fname = NULL; files[i].fp = NULL; } } - tempfree(x, "close"); - return (true); + tempfree(x); + x = gettemp(); + (void) setfval(x, (Awkfloat) stat); + return (x); } static void @@ -1708,197 +2016,257 @@ closeall(void) { int i, stat; - for (i = 0; i < FOPEN_MAX; i++) { + for (i = 0; i < nfiles; i++) { if (files[i].fp) { if (ferror(files[i].fp)) { - ERROR "i/o error occurred on %s", - files[i].fname WARNING; + WARNING("i/o error occurred on %s", + files[i].fname); } if (files[i].mode == '|' || files[i].mode == LE) stat = pclose(files[i].fp); else stat = fclose(files[i].fp); if (stat == EOF) { - ERROR "i/o error occurred while closing %s", - files[i].fname WARNING; + WARNING("i/o error occurred while closing %s", + files[i].fname); } } } } +void +flush_all(void) +{ + int i; + + for (i = 0; i < nfiles; i++) + if (files[i].fp) + (void) fflush(files[i].fp); +} + /*ARGSUSED*/ Cell * -sub(Node **a, int nnn) +sub(Node **a, int nnn) /* substitute command */ { - register uchar *sptr; - register Cell *x, *y, *result; - uchar *buf, *t; + char *sptr, *pb, *q; + Cell *x, *y, *result; + char *t, *buf; fa *pfa; - size_t bsize, cnt, len; + size_t bufsz = recsize; + if ((buf = (char *)malloc(bufsz)) == NULL) + FATAL("out of memory in sub"); x = execute(a[3]); /* target string */ t = getsval(x); - if (a[0] == 0) + if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */ pfa = (fa *)a[1]; /* regular expression */ else { y = execute(a[1]); pfa = makedfa(getsval(y), 1); - tempfree(y, ""); + tempfree(y); } y = execute(a[2]); /* replacement string */ - result = false; + result = False; if (pmatch(pfa, t)) { - init_buf(&buf, &bsize, LINE_INCR); - cnt = 0; sptr = t; - len = patbeg - sptr; - if (len > 0) { - expand_buf(&buf, &bsize, cnt + len); - (void) memcpy(buf, sptr, len); - cnt += len; - } + (void) adjbuf(&buf, &bufsz, + 1 + patbeg - sptr, recsize, 0, "sub"); + pb = buf; + while (sptr < patbeg) + *pb++ = *sptr++; sptr = getsval(y); - while (*sptr != 0) { - expand_buf(&buf, &bsize, cnt); - if (*sptr == '\\' && - (*(sptr+1) == '&' || *(sptr+1) == '\\')) { - sptr++; /* skip \, */ - buf[cnt++] = *sptr++; /* add & or \ */ + while (*sptr != '\0') { + (void) adjbuf(&buf, &bufsz, 5 + pb - buf, + recsize, &pb, "sub"); + if (*sptr == '\\') { + backsub(&pb, &sptr); } else if (*sptr == '&') { - expand_buf(&buf, &bsize, cnt + patlen); sptr++; - (void) memcpy(&buf[cnt], patbeg, patlen); - cnt += patlen; + (void) adjbuf(&buf, &bufsz, + 1 + patlen + pb - buf, recsize, &pb, "sub"); + for (q = patbeg; q < patbeg+patlen; ) + *pb++ = *q++; } else { - buf[cnt++] = *sptr++; + *pb++ = *sptr++; } } + *pb = '\0'; + if (pb > buf + bufsz) + FATAL("sub result1 %.30s too big; can't happen", buf); sptr = patbeg + patlen; if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { - len = strlen((char *)sptr); - expand_buf(&buf, &bsize, cnt + len); - (void) memcpy(&buf[cnt], sptr, len); - cnt += len; + (void) adjbuf(&buf, &bufsz, + 1 + strlen(sptr) + pb - buf, 0, &pb, "sub"); + while ((*pb++ = *sptr++) != '\0') + ; } - buf[cnt] = '\0'; - (void) setsval(x, buf); - free(buf); - result = true; + if (pb > buf + bufsz) + FATAL("sub result2 %.30s too big; can't happen", buf); + (void) setsval(x, buf); /* BUG: should be able to avoid copy */ + result = True; } - tempfree(x, ""); - tempfree(y, ""); + tempfree(x); + tempfree(y); + free(buf); return (result); } /*ARGSUSED*/ Cell * -gsub(Node **a, int nnn) +gsub(Node **a, int nnn) /* global substitute */ { - register Cell *x, *y; - register uchar *rptr, *sptr, *t; - uchar *buf; - register fa *pfa; + Cell *x, *y; + char *rptr, *sptr, *t, *pb, *q; + char *buf; + fa *pfa; int mflag, tempstat, num; - size_t bsize, cnt, len; + size_t bufsz = recsize; + if ((buf = (char *)malloc(bufsz)) == NULL) + FATAL("out of memory in gsub"); mflag = 0; /* if mflag == 0, can replace empty string */ num = 0; x = execute(a[3]); /* target string */ t = getsval(x); - if (a[0] == 0) - pfa = (fa *) a[1]; /* regular expression */ + if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */ + pfa = (fa *)a[1]; /* regular expression */ else { y = execute(a[1]); pfa = makedfa(getsval(y), 1); - tempfree(y, ""); + tempfree(y); } y = execute(a[2]); /* replacement string */ if (pmatch(pfa, t)) { tempstat = pfa->initstat; pfa->initstat = 2; - init_buf(&buf, &bsize, LINE_INCR); + pb = buf; rptr = getsval(y); - cnt = 0; do { - if (patlen == 0 && *patbeg != 0) { + if (patlen == 0 && *patbeg != '\0') { /* matched empty string */ if (mflag == 0) { /* can replace empty */ num++; sptr = rptr; - while (*sptr != 0) { - expand_buf(&buf, &bsize, cnt); - if (*sptr == '\\' && - (*(sptr+1) == '&' || - *(sptr+1) == '\\')) { - sptr++; - buf[cnt++] = *sptr++; + while (*sptr != '\0') { + (void) adjbuf(&buf, &bufsz, + 5 + pb - buf, recsize, + &pb, "gsub"); + if (*sptr == '\\') { + backsub(&pb, &sptr); } else if (*sptr == '&') { - expand_buf(&buf, - &bsize, - cnt + patlen); sptr++; - (void) memcpy(&buf[cnt], - patbeg, patlen); - cnt += patlen; + (void) adjbuf(&buf, + &bufsz, + 1+patlen+pb-buf, + recsize, + &pb, "gsub"); + for ( + q = patbeg; + q < patbeg+patlen; + *pb++ = *q++) + ; } else { - buf[cnt++] = *sptr++; + *pb++ = *sptr++; } } } - if (*t == 0) /* at end */ + if (*t == '\0') /* at end */ goto done; - expand_buf(&buf, &bsize, cnt); - buf[cnt++] = *t++; + (void) adjbuf(&buf, &bufsz, + 2 + pb - buf, recsize, &pb, "gsub"); + *pb++ = *t++; + /* BUG: not sure of this test */ + if (pb > buf + bufsz) + FATAL("gsub result0 %.30s too big; " + "can't happen", buf); mflag = 0; } else { /* matched nonempty string */ num++; sptr = t; - len = patbeg - sptr; - if (len > 0) { - expand_buf(&buf, &bsize, cnt + len); - (void) memcpy(&buf[cnt], sptr, len); - cnt += len; - } + (void) adjbuf(&buf, &bufsz, + 1 + (patbeg - sptr) + pb - buf, + recsize, &pb, "gsub"); + while (sptr < patbeg) + *pb++ = *sptr++; sptr = rptr; - while (*sptr != 0) { - expand_buf(&buf, &bsize, cnt); - if (*sptr == '\\' && - (*(sptr+1) == '&' || - *(sptr+1) == '\\')) { - sptr++; - buf[cnt++] = *sptr++; + while (*sptr != '\0') { + (void) adjbuf(&buf, &bufsz, + 5 + pb - buf, recsize, &pb, "gsub"); + if (*sptr == '\\') { + backsub(&pb, &sptr); } else if (*sptr == '&') { - expand_buf(&buf, &bsize, - cnt + patlen); sptr++; - (void) memcpy(&buf[cnt], - patbeg, patlen); - cnt += patlen; + (void) adjbuf(&buf, &bufsz, + 1 + patlen + pb - buf, + recsize, &pb, "gsub"); + for ( + q = patbeg; + q < patbeg+patlen; + *pb++ = *q++) + ; } else { - buf[cnt++] = *sptr++; + *pb++ = *sptr++; } } t = patbeg + patlen; - if ((*(t-1) == 0) || (*t == 0)) + if (patlen == 0 || *(t-1) == '\0' || *t == '\0') goto done; + if (pb > buf + bufsz) + FATAL("gsub result1 %.30s too big; " + "can't happen", buf); mflag = 1; } } while (pmatch(pfa, t)); sptr = t; - len = strlen((char *)sptr); - expand_buf(&buf, &bsize, len + cnt); - (void) memcpy(&buf[cnt], sptr, len); - cnt += len; + (void) adjbuf(&buf, &bufsz, + 1 + strlen(sptr) + pb - buf, 0, &pb, "gsub"); + while ((*pb++ = *sptr++) != '\0') + ; done: - buf[cnt] = '\0'; + if (pb < buf + bufsz) + *pb = '\0'; + else if (*(pb-1) != '\0') + FATAL("gsub result2 %.30s truncated; " + "can't happen", buf); + /* BUG: should be able to avoid copy + free */ (void) setsval(x, buf); - free(buf); pfa->initstat = tempstat; } - tempfree(x, ""); - tempfree(y, ""); - x = gettemp(""); + tempfree(x); + tempfree(y); + x = gettemp(); x->tval = NUM; x->fval = num; + free(buf); return (x); } + +/* + * handle \\& variations; sptr[0] == '\\' + */ +static void +backsub(char **pb_ptr, char **sptr_ptr) +{ + 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/src/cmd/awk/tran.c b/usr/src/cmd/awk/tran.c index e8e42d780e..ba9a685d93 100644 --- a/usr/src/cmd/awk/tran.c +++ b/usr/src/cmd/awk/tran.c @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -27,13 +51,12 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #define DEBUG #include <stdio.h> -#include <stdlib.h> +#include <math.h> #include <ctype.h> #include <string.h> +#include <stdlib.h> #include "awk.h" #include "y.tab.h" @@ -42,107 +65,114 @@ Array *symtab; /* main symbol table */ -uchar **FS; /* initial field sep */ -uchar **RS; /* initial record sep */ -uchar **OFS; /* output field sep */ -uchar **ORS; /* output record sep */ -uchar **OFMT; /* output format for numbers */ +char **FS; /* initial field sep */ +char **RS; /* initial record sep */ +char **OFS; /* output field sep */ +char **ORS; /* output record sep */ +char **OFMT; /* output format for numbers */ +char **CONVFMT; /* format for conversions in getsval */ Awkfloat *NF; /* number of fields in current record */ Awkfloat *NR; /* number of current record */ Awkfloat *FNR; /* number of current record in current file */ -uchar **FILENAME; /* current filename argument */ +char **FILENAME; /* current filename argument */ Awkfloat *ARGC; /* number of arguments from command line */ -uchar **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */ +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 *fsloc; /* FS */ Cell *nrloc; /* NR */ Cell *nfloc; /* NF */ Cell *fnrloc; /* FNR */ +Cell *ofsloc; /* OFS */ +Cell *orsloc; /* ORS */ +Cell *rsloc; /* RS */ +Cell *rtloc; /* RT */ Array *ARGVtab; /* symbol table containing ARGV[...] */ Array *ENVtab; /* symbol table containing ENVIRON[...] */ Cell *rstartloc; /* RSTART */ Cell *rlengthloc; /* RLENGTH */ +Cell *subseploc; /* SUBSEP */ Cell *symtabloc; /* SYMTAB */ -Cell *nullloc; +Cell *nullloc; /* a guaranteed empty cell */ Node *nullnode; /* zero&null, converted into a node for comparisons */ +Cell *literal0; static void rehash(Array *); -void -syminit(void) +static void +setfree(Cell *vp) { - init_buf(&record, &record_size, LINE_INCR); + if (&vp->sval == FS || &vp->sval == RS || + &vp->sval == OFS || &vp->sval == ORS || + &vp->sval == OFMT || &vp->sval == CONVFMT || + &vp->sval == FILENAME || &vp->sval == SUBSEP) + vp->tval |= DONTFREE; + else + vp->tval &= ~DONTFREE; +} +void +syminit(void) /* initialize symbol table with builtin vars */ +{ /* initialize $0 */ - recloc = getfld(0); - recloc->nval = (uchar *)"$0"; + recloc = fieldadr(0); + recloc->nval = "$0"; recloc->sval = record; recloc->tval = REC|STR|DONTFREE; - symtab = makesymtab(NSYMTAB); - (void) setsymtab((uchar *)"0", (uchar *)"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((uchar *)"$zero&null", (uchar *)"", 0.0, + nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab); - nullnode = valtonode(nullloc, CCON); - FS = &setsymtab((uchar *)"FS", (uchar *)" ", 0.0, - STR|DONTFREE, symtab)->sval; - RS = &setsymtab((uchar *)"RS", (uchar *)"\n", 0.0, - STR|DONTFREE, symtab)->sval; - OFS = &setsymtab((uchar *)"OFS", (uchar *)" ", 0.0, - STR|DONTFREE, symtab)->sval; - ORS = &setsymtab((uchar *)"ORS", (uchar *)"\n", 0.0, + nullnode = celltonode(nullloc, CCON); + + fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab); + FS = &fsloc->sval; + rsloc = setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab); + RS = &rsloc->sval; + rtloc = setsymtab("RT", "", 0.0, STR|DONTFREE, symtab); + ofsloc = setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab); + OFS = &ofsloc->sval; + orsloc = setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab); + ORS = &orsloc->sval; + OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; + CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; - OFMT = &setsymtab((uchar *)"OFMT", (uchar *)"%.6g", 0.0, - STR|DONTFREE, symtab)->sval; - FILENAME = &setsymtab((uchar *)"FILENAME", (uchar *)"-", 0.0, - STR|DONTFREE, symtab)->sval; - nfloc = setsymtab((uchar *)"NF", (uchar *)"", 0.0, NUM, symtab); + FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval; + nfloc = setsymtab("NF", "", 0.0, NUM, symtab); NF = &nfloc->fval; - nrloc = setsymtab((uchar *)"NR", (uchar *)"", 0.0, NUM, symtab); + nrloc = setsymtab("NR", "", 0.0, NUM, symtab); NR = &nrloc->fval; - fnrloc = setsymtab((uchar *)"FNR", (uchar *)"", 0.0, NUM, symtab); + fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab); FNR = &fnrloc->fval; - SUBSEP = &setsymtab((uchar *)"SUBSEP", (uchar *)"\034", 0.0, - STR|DONTFREE, symtab)->sval; - rstartloc = setsymtab((uchar *)"RSTART", (uchar *)"", 0.0, - NUM, symtab); + subseploc = setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab); + SUBSEP = &subseploc->sval; + rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab); RSTART = &rstartloc->fval; - rlengthloc = setsymtab((uchar *)"RLENGTH", (uchar *)"", 0.0, - NUM, symtab); + rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab); RLENGTH = &rlengthloc->fval; - symtabloc = setsymtab((uchar *)"SYMTAB", (uchar *)"", 0.0, ARR, symtab); - symtabloc->sval = (uchar *)symtab; + symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab); + symtabloc->sval = (char *)symtab; } void -arginit(int ac, uchar *av[]) +arginit(int ac, char **av) /* set up ARGV and ARGC */ { Cell *cp; int i; - uchar temp[11]; - - /* first make FILENAME first real argument */ - for (i = 1; i < ac; i++) { - if (!isclvar(av[i])) { - (void) setsval(lookup((uchar *)"FILENAME", symtab), - av[i]); - break; - } - } - ARGC = &setsymtab((uchar *)"ARGC", (uchar *)"", (Awkfloat)ac, - NUM, symtab)->fval; - cp = setsymtab((uchar *)"ARGV", (uchar *)"", 0.0, ARR, symtab); + 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 = (uchar *) ARGVtab; + cp->sval = (char *)ARGVtab; for (i = 0; i < ac; i++) { - (void) sprintf((char *)temp, "%d", i); + (void) sprintf(temp, "%d", i); if (is_number(*av)) { - (void) setsymtab(temp, *av, atof((const char *)*av), + (void) setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab); } else { (void) setsymtab(temp, *av, 0.0, STR, ARGVtab); @@ -152,20 +182,22 @@ arginit(int ac, uchar *av[]) } void -envinit(uchar *envp[]) +envinit(char **envp) /* set up ENVIRON variable */ { Cell *cp; - uchar *p; + char *p; - cp = setsymtab((uchar *)"ENVIRON", (uchar *)"", 0.0, ARR, symtab); + cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab); ENVtab = makesymtab(NSYMTAB); - cp->sval = (uchar *) ENVtab; + cp->sval = (char *)ENVtab; for (; *envp; envp++) { - if ((p = (uchar *)strchr((char *)*envp, '=')) == NULL) + if ((p = strchr(*envp, '=')) == NULL) + continue; + if (p == *envp) /* no left hand side name in env string */ continue; *p++ = 0; /* split into two strings at = */ if (is_number(p)) { - (void) setsymtab(*envp, p, atof((const char *)p), + (void) setsymtab(*envp, p, atof(p), STR|NUM, ENVtab); } else { (void) setsymtab(*envp, p, 0.0, STR, ENVtab); @@ -176,7 +208,7 @@ envinit(uchar *envp[]) } Array * -makesymtab(int n) +makesymtab(int n) /* make a new symbol table */ { Array *ap; Cell **tp; @@ -184,7 +216,7 @@ makesymtab(int n) ap = (Array *)malloc(sizeof (Array)); tp = (Cell **)calloc(n, sizeof (Cell *)); if (ap == NULL || tp == NULL) - ERROR "out of space in makesymtab" FATAL; + FATAL("out of space in makesymtab"); ap->nelem = 0; ap->size = n; ap->tab = tp; @@ -192,9 +224,9 @@ makesymtab(int n) } void -freesymtab(Cell *ap) /* free symbol table */ +freesymtab(Cell *ap) /* free a symbol table */ { - Cell *cp, *next; + Cell *cp, *temp; Array *tp; int i; @@ -205,20 +237,26 @@ freesymtab(Cell *ap) /* free symbol table */ if (tp == NULL) return; for (i = 0; i < tp->size; i++) { - for (cp = tp->tab[i]; cp != NULL; cp = next) { - next = cp->cnext; + for (cp = tp->tab[i]; cp != NULL; cp = temp) { xfree(cp->nval); if (freeable(cp)) xfree(cp->sval); + temp = cp->cnext; /* avoids freeing then using */ free(cp); + tp->nelem--; } + tp->tab[i] = 0; + } + if (tp->nelem != 0) { + WARNING("can't happen: inconsistent element count freeing %s", + ap->nval); } free(tp->tab); free(tp); } void -freeelem(Cell *ap, uchar *s) /* free elem s from ap (i.e., ap["s"] */ +freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */ { Array *tp; Cell *p, *prev = NULL; @@ -228,7 +266,7 @@ freeelem(Cell *ap, uchar *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 */ @@ -243,41 +281,40 @@ freeelem(Cell *ap, uchar *s) /* free elem s from ap (i.e., ap["s"] */ } Cell * -setsymtab(uchar *n, uchar *s, Awkfloat f, unsigned int t, Array *tp) +setsymtab(const char *n, const char *s, Awkfloat f, unsigned int t, Array *tp) { - register int h; - register Cell *p; + int h; + Cell *p; if (n != NULL && (p = lookup(n, tp)) != NULL) { - dprintf(("setsymtab found %p: n=%s", (void *)p, p->nval)); - dprintf((" s=\"%s\" f=%g t=%p\n", - p->sval, p->fval, (void *)p->tval)); + dprintf(("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n", + (void *)p, NN(p->nval), NN(p->sval), p->fval, p->tval)); return (p); } p = (Cell *)malloc(sizeof (Cell)); if (p == NULL) - ERROR "symbol table overflow at %s", n FATAL; + FATAL("out of space for symbol table at %s", n); p->nval = tostring(n); - p->sval = s ? tostring(s) : tostring((uchar *)""); + p->sval = s ? tostring(s) : tostring(""); p->fval = f; p->tval = t; - p->csub = 0; - + p->csub = CUNK; + p->ctype = OCELL; tp->nelem++; if (tp->nelem > FULLTAB * tp->size) rehash(tp); h = hash(n, tp->size); p->cnext = tp->tab[h]; tp->tab[h] = p; - dprintf(("setsymtab set %p: n=%s", (void *)p, p->nval)); - dprintf((" s=\"%s\" f=%g t=%p\n", p->sval, p->fval, (void *)p->tval)); + dprintf(("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n", + (void *)p, p->nval, p->sval, p->fval, p->tval)); return (p); } int -hash(uchar *s, int n) /* form hash value for string s */ +hash(const char *s, int n) /* form hash value for string s */ { - register unsigned hashval; + unsigned int hashval; for (hashval = 0; *s != '\0'; s++) hashval = (*s + 31 * hashval); @@ -292,10 +329,10 @@ rehash(Array *tp) /* rehash items in small table into big one */ nsz = GROWTAB * tp->size; np = (Cell **)calloc(nsz, sizeof (Cell *)); - if (np == NULL) - ERROR "out of space in rehash" FATAL; + if (np == NULL) /* can't do it, but can keep running. */ + return; /* someone else will run out later. */ for (i = 0; i < tp->size; i++) { - for (cp = tp->tab[i]; cp; cp = op) { + for (cp = tp->tab[i]; cp != NULL; cp = op) { op = cp->cnext; nh = hash(cp->nval, nsz); cp->cnext = np[nh]; @@ -308,177 +345,278 @@ rehash(Array *tp) /* rehash items in small table into big one */ } Cell * -lookup(uchar *s, Array *tp) /* look for s in tp */ +lookup(const char *s, Array *tp) /* look for s in tp */ { - register Cell *p; + Cell *p; int h; h = hash(s, tp->size); for (p = tp->tab[h]; p != NULL; 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) +setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */ { - int i; + int fldno; + f += 0.0; /* normalise negative zero to positive zero */ if ((vp->tval & (NUM | STR)) == 0) funnyvar(vp, "assign to"); - if (vp->tval & FLD) { + if (isfld(vp)) { donerec = 0; /* mark $0 invalid */ - i = fldidx(vp); - if (i > *NF) - newfld(i); - dprintf(("setting field %d to %g\n", i, 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 (&vp->fval == NF) { + donerec = 0; /* mark $0 invalid */ + setlastfld((int)f); + dprintf(("setting NF to %g\n", f)); + } else if (isrec(vp)) { donefld = 0; /* mark $1... invalid */ donerec = 1; + savefs(); + } else if (vp == ofsloc) { + if (donerec == 0) + recbld(); } - vp->tval &= ~STR; /* mark string invalid */ + if (freeable(vp)) + xfree(vp->sval); /* free any previous string */ + vp->tval &= ~(STR|CONVC|CONVO); /* mark string invalid */ + vp->fmt = NULL; vp->tval |= NUM; /* mark number ok */ - dprintf(("setfval %p: %s = %g, t=%p\n", (void *)vp, - vp->nval ? vp->nval : (unsigned char *)"NULL", - f, (void *)vp->tval)); + if (f == -0) /* who would have thought this possible? */ + f = 0; + dprintf(("setfval %p: %s = %g, t=%o\n", (void *)vp, + NN(vp->nval), f, vp->tval)); return (vp->fval = f); } void -funnyvar(Cell *vp, char *rw) +funnyvar(Cell *vp, const char *rw) { - if (vp->tval & ARR) - 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; - ERROR "funny variable %o: n=%s s=\"%s\" f=%g t=%o", - vp, vp->nval, vp->sval, vp->fval, vp->tval CONT; + if (isarr(vp)) + FATAL("can't %s %s; it's an array name.", rw, vp->nval); + if (isfcn(vp)) + FATAL("can't %s %s; it's a function.", rw, vp->nval); + WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o", + vp, vp->nval, vp->sval, vp->fval, vp->tval); } -uchar * -setsval(Cell *vp, uchar *s) +char * +setsval(Cell *vp, const char *s) /* set string val of a Cell */ { - int i; + char *t; + int fldno; + Awkfloat f; + dprintf(("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n", + (void *)vp, NN(vp->nval), s, vp->tval, donerec, donefld)); if ((vp->tval & (NUM | STR)) == 0) funnyvar(vp, "assign to"); - if (vp->tval & FLD) { + if (isfld(vp)) { donerec = 0; /* mark $0 invalid */ - i = fldidx(vp); - if (i > *NF) - newfld(i); - dprintf(("setting field %d to %s\n", i, 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, (void *)s)); + } else if (isrec(vp)) { donefld = 0; /* mark $1... invalid */ donerec = 1; + savefs(); + } else if (vp == ofsloc) { + if (donerec == 0) + recbld(); } - vp->tval &= ~NUM; - vp->tval |= STR; + t = s ? tostring(s) : tostring(""); /* in case it's self-assign */ if (freeable(vp)) xfree(vp->sval); - vp->tval &= ~DONTFREE; - dprintf(("setsval %p: %s = \"%s\", t=%p\n", - (void *)vp, - vp->nval ? (char *)vp->nval : "", - s, - (void *)(vp->tval ? (char *)vp->tval : ""))); - return (vp->sval = tostring(s)); + vp->tval &= ~(NUM|CONVC|CONVO); + vp->tval |= STR; + vp->fmt = NULL; + setfree(vp); + dprintf(("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n", + (void *)vp, NN(vp->nval), t, (void *)t, + vp->tval, donerec, donefld)); + vp->sval = t; + if (&vp->fval == NF) { + donerec = 0; /* mark $0 invalid */ + f = getfval(vp); + setlastfld((int)f); + dprintf(("setting NF to %g\n", f)); + } + + return (vp->sval); } Awkfloat -r_getfval(Cell *vp) +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((const char *)vp->sval); /* best guess */ + vp->fval = atof(vp->sval); /* best guess */ if (is_number(vp->sval) && !(vp->tval&CON)) vp->tval |= NUM; /* make NUM only sparingly */ } - dprintf(("getfval %p: %s = %g, t=%p\n", - (void *)vp, vp->nval, vp->fval, (void *)vp->tval)); + dprintf(("getfval %p: %s = %g, t=%o\n", + (void *)vp, NN(vp->nval), vp->fval, vp->tval)); return (vp->fval); } -uchar * -r_getsval(Cell *vp) +static char * +get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */ { - uchar s[256]; + char s[256]; + 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)) - xfree(vp->sval); - if ((long long)vp->fval == vp->fval) { - (void) snprintf((char *)s, sizeof (s), - "%.20g", vp->fval); + + /* + * ADR: This is complicated and more fragile than is desirable. + * Retrieving a string value for a number associates the string + * value with the scalar. Previously, the string value was + * sticky, meaning if converted via OFMT that became the value + * (even though POSIX wants it to be via CONVFMT). Or if CONVFMT + * changed after a string value was retrieved, the original value + * was maintained and used. Also not per POSIX. + * + * We work around this design by adding two additional flags, + * CONVC and CONVO, indicating how the string value was + * obtained (via CONVFMT or OFMT) and _also_ maintaining a copy + * of the pointer to the xFMT format string used for the + * conversion. This pointer is only read, **never** dereferenced. + * The next time we do a conversion, if it's coming from the same + * xFMT as last time, and the pointer value is different, we + * know that the xFMT format string changed, and we need to + * redo the conversion. If it's the same, we don't have to. + * + * There are also several cases where we don't do a conversion, + * such as for a field (see the checks below). + */ + + /* Don't duplicate the code for actually updating the value */ +#define update_str_val(vp) \ + { \ + if (freeable(vp)) \ + xfree(vp->sval); \ + if (modf(vp->fval, &dtemp) == 0) /* it's integral */ \ + (void) snprintf(s, sizeof (s), "%.30g", vp->fval); \ + else \ + (void) snprintf(s, sizeof (s), *fmt, vp->fval); \ + vp->sval = tostring(s); \ + vp->tval &= ~DONTFREE; \ + vp->tval |= STR; \ + } + + if (isstr(vp) == 0) { + /*LINTED*/ + update_str_val(vp); + if (fmt == OFMT) { + vp->tval &= ~CONVC; + vp->tval |= CONVO; } else { - /*LINTED*/ - (void) snprintf((char *)s, sizeof (s), - (char *)*OFMT, vp->fval); + /* CONVFMT */ + vp->tval &= ~CONVO; + vp->tval |= CONVC; + } + vp->fmt = *fmt; + } else if ((vp->tval & DONTFREE) != 0 || !isnum(vp) || isfld(vp)) { + goto done; + } else if (isstr(vp)) { + if (fmt == OFMT) { + if ((vp->tval & CONVC) != 0 || + ((vp->tval & CONVO) != 0 && vp->fmt != *fmt)) { + /*LINTED*/ + update_str_val(vp); + vp->tval &= ~CONVC; + vp->tval |= CONVO; + vp->fmt = *fmt; + } + } else { + /* CONVFMT */ + if ((vp->tval & CONVO) != 0 || + ((vp->tval & CONVC) != 0 && vp->fmt != *fmt)) { + /*LINTED*/ + update_str_val(vp); + vp->tval &= ~CONVO; + vp->tval |= CONVC; + vp->fmt = *fmt; + } } - vp->sval = tostring(s); - vp->tval &= ~DONTFREE; - vp->tval |= STR; } - dprintf(("getsval %p: %s = \"%s\", t=%p\n", - (void *)vp, - vp->nval ? (char *)vp->nval : "", - vp->sval ? (char *)vp->sval : "", - (void *)vp->tval)); +done: + dprintf(("getsval %p: %s = \"%s (%p)\", t=%o\n", + (void *)vp, NN(vp->nval), vp->sval, (void *)vp->sval, vp->tval)); return (vp->sval); } -uchar * -tostring(uchar *s) +char * +getsval(Cell *vp) /* get string val of a Cell */ { - register uchar *p; + return (get_str_val(vp, CONVFMT)); +} - p = (uchar *)malloc(strlen((char *)s)+1); +char * +getpssval(Cell *vp) /* get string val of a Cell for print */ +{ + return (get_str_val(vp, OFMT)); +} + + +char * +tostring(const char *s) /* make a copy of string s */ +{ + char *p = strdup(s); if (p == NULL) - ERROR "out of space in tostring on %s", s FATAL; - (void) strcpy((char *)p, (char *)s); + FATAL("out of space in tostring on %s", s); return (p); } -uchar * -qstring(uchar *s, int delim) /* collect string up to delim */ +char * +qstring(const char *is, int delim) /* collect string up to next delim */ { - uchar *cbuf, *ret; + const char *os = is; int c, n; - size_t cbufsz, cnt; - - init_buf(&cbuf, &cbufsz, LINE_INCR); + uschar *s = (uschar *)is; + uschar *buf, *bp; - for (cnt = 0; (c = *s) != delim; s++) { + if ((buf = (uschar *)malloc(strlen(is)+3)) == NULL) + FATAL("out of space in qstring(%s)", s); + for (bp = buf; (c = *s) != delim; s++) { if (c == '\n') { - ERROR "newline in string %.10s...", cbuf SYNTAX; - } else if (c != '\\') { - expand_buf(&cbuf, &cbufsz, cnt); - cbuf[cnt++] = c; - } else { /* \something */ - expand_buf(&cbuf, &cbufsz, cnt); - switch (c = *++s) { - case '\\': cbuf[cnt++] = '\\'; break; - case 'n': cbuf[cnt++] = '\n'; break; - case 't': cbuf[cnt++] = '\t'; break; - case 'b': cbuf[cnt++] = '\b'; break; - case 'f': cbuf[cnt++] = '\f'; break; - case 'r': cbuf[cnt++] = '\r'; break; + SYNTAX("newline in string %.20s...", os); + } else if (c != '\\') + *bp++ = c; + else { /* \something */ + c = *++s; + if (c == 0) { /* \ at end */ + *bp++ = '\\'; + break; /* for loop */ + } + switch (c) { + 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)) { - cbuf[cnt++] = c; + *bp++ = c; break; } n = c - '0'; @@ -487,13 +625,11 @@ qstring(uchar *s, int delim) /* collect string up to delim */ if (isdigit(s[1])) n = 8 * n + *++s - '0'; } - cbuf[cnt++] = n; + *bp++ = n; break; } } } - cbuf[cnt] = '\0'; - ret = tostring(cbuf); - free(cbuf); - return (ret); + *bp++ = 0; + return ((char *)buf); } diff --git a/usr/src/man/man1/nawk.1 b/usr/src/man/man1/nawk.1 index 4b321c6bd6..b2d06fbea9 100644 --- a/usr/src/man/man1/nawk.1 +++ b/usr/src/man/man1/nawk.1 @@ -43,8 +43,9 @@ .\" Copyright 1989 AT&T .\" Copyright 1992, X/Open Company Limited All Rights Reserved .\" Portions Copyright (c) 2005, 2006 Sun Microsystems, Inc. All Rights Reserved +.\" Copyright 2018, Joyent, Inc. .\" -.TH NAWK 1 "May 24, 2006" +.TH NAWK 1 "Nov 9, 2018" .SH NAME nawk \- pattern scanning and processing language .SH SYNOPSIS @@ -61,7 +62,6 @@ nawk \- pattern scanning and processing language .fi .SH DESCRIPTION -.sp .LP The \fB/usr/bin/nawk\fR and \fB/usr/xpg4/bin/awk\fR utilities execute \fIprogram\fRs written in the \fBnawk\fR programming language, which is @@ -88,8 +88,8 @@ utility denotes the first field in a record \fB$1\fR, the second \fB$2\fR, and so forth. The symbol \fB$0\fR refers to the entire record; setting any other field causes the reevaluation of \fB$0\fR. Assigning to \fB$0\fR resets the values of all fields and the \fBNF\fR built-in variable. + .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -129,8 +129,18 @@ before executing the \fBnawk\fR program, including the actions associated with specified. .RE -.SH OPERANDS .sp +.ne 2 +.na +\fB\fB-safe\fR\fR +.ad +.RS 17n +When passed to \fBnawk\fR, this flag will prevent the program from opening new +files or running child processes. The \fBENVIRON\fR array will also not be +initialized. +.RE + +.SH OPERANDS .LP The following operands are supported: .sp @@ -193,7 +203,6 @@ assignments are executed before processing the standard input. .RE .SH INPUT FILES -.sp .LP Input files to the \fBnawk\fR program from any of the following sources: .RS +4 @@ -230,8 +239,8 @@ program. .LP The standard input are used only if no \fIfile\fR operands are specified, or if a \fIfile\fR operand is \fB\(mi\fR\&. + .SH EXTENDED DESCRIPTION -.sp .LP A \fBnawk\fR program is composed of pairs of the form: .sp @@ -263,8 +272,8 @@ program in the order of occurrence, and executing the action associated with each pattern that matches the current record. The action for a matching pattern is executed before evaluating subsequent patterns. Last, the actions associated with all \fBEND\fR patterns is executed in the order they occur in the program. + .SS "Expressions in nawk" -.sp .LP Expressions describe computations used in \fIpatterns\fR and \fIactions\fR. In the following table, valid expression operations are given in groups from @@ -288,9 +297,9 @@ _ $\fIexpr\fR Field reference string n/a _ ++ \fIlvalue\fR Pre-increment numeric n/a - \(mi\(mi\fIlvalue\fR Pre-decrement numeric n/a +\(mi\(mi \fIlvalue\fR Pre-decrement numeric n/a \fIlvalue\fR ++ Post-increment numeric n/a -\fIlvalue\fR \(mi\(mi Post-decrement numeric n/a +\fIlvalue\fR \(mi\(mi Post-decrement numeric n/a _ \fIexpr\fR ^ \fIexpr\fR Exponentiation numeric right _ @@ -303,7 +312,7 @@ _ \fIexpr\fR % \fIexpr\fR Modulus numeric left _ \fIexpr\fR + \fIexpr\fR Addition numeric left -\fIexpr\fR \(mi \fIexpr\fR Subtraction numeric left +\fIexpr\fR \(mi \fIexpr\fR Subtraction numeric left _ \fIexpr\fR \fIexpr\fR String concatenation string left _ @@ -319,20 +328,20 @@ _ _ \fIexpr\fR in array Array membership numeric left ( \fIindex\fR ) in Multi-dimension array numeric left - \fIarray\fR membership + \fIarray\fR membership _ \fBexpr\fR && \fIexpr\fR Logical AND numeric left _ \fBexpr\fR |\|| \fIexpr\fR Logical OR numeric left _ \fIexpr1\fR ? \fIexpr2\fR Conditional expression type of selected right - : \fIexpr3\fR \fIexpr2\fR or \fIexpr3\fR + : \fIexpr3\fR \fIexpr2\fR or \fIexpr3\fR _ \fIlvalue\fR ^= \fIexpr\fR Exponentiation numeric right - assignment + assignment \fIlvalue\fR %= \fIexpr\fR Modulus assignment numeric right \fIlvalue\fR *= \fIexpr\fR Multiplication numeric right - assignment + assignment \fIlvalue\fR /= \fIexpr\fR Division assignment numeric right \fIlvalue\fR += \fIexpr\fR Addition assignment numeric right \fIlvalue\fR \(mi= \fIexpr\fR Subtraction assignment numeric right @@ -479,8 +488,8 @@ A multi-dimensioned \fIindex\fR used with the \fBin\fR operator must be put in parentheses. The \fBin\fR operator, which tests for the existence of a particular array element, does not create the element if it does not exist. Any other reference to a non-existent array element automatically creates it. + .SS "Variables and Special Variables" -.sp .LP Variables can be used in an \fBnawk\fR program by referencing them. With the exception of function parameters, they are not explicitly declared. @@ -503,8 +512,8 @@ occurrence of the decimal-point character from the current locale changed to a period character, is considered a \fInumeric string\fR (see \fBExpressions in nawk\fR above), the field variable also has the numeric value of the \fInumeric string\fR. + .SS "/usr/bin/nawk, /usr/xpg4/bin/awk" -.sp .LP \fBnawk\fR sets the following special variables that are supported by both \fB/usr/bin/nawk\fR and \fB/usr/xpg4/bin/awk\fR: @@ -539,6 +548,16 @@ argument. .sp .ne 2 .na +\fB\fBCONVFMT\fR\fR +.ad +.RS 12n +The \fBprintf\fR format for converting numbers to strings (except for output +statements, where \fBOFMT\fR is used). The default is \fB%.6g\fR. +.RE + +.sp +.ne 2 +.na \fB\fBENVIRON\fR\fR .ad .RS 12n @@ -644,7 +663,7 @@ The \fBprint\fR output record separator; a newline character by default. .sp .ne 2 .na -\fB\fBLENGTH\fR\fR +\fB\fBRLENGTH\fR\fR .ad .RS 12n The length of the string matched by the \fBmatch\fR function. @@ -685,22 +704,21 @@ The subscript separator string for multi-dimensional arrays. The default value is \fB\e034\fR\&. .RE -.SS "/usr/xpg4/bin/awk" -.sp +.SS "/usr/bin/nawk" .LP -The following variable is supported for \fB/usr/xpg4/bin/awk\fR only: +The following variable is supported for \fB/usr/bin/nawk\fR only: .sp .ne 2 .na -\fB\fBCONVFMT\fR\fR +\fB\fBRT\fR\fR .ad -.RS 11n -The \fBprintf\fR format for converting numbers to strings (except for output -statements, where \fBOFMT\fR is used). The default is \fB%.6g\fR. +.RS 12n +The record terminator for the most recent record read. For most records this +will be the same value as \fBRS\fR. At the end of a file with no trailing +separator value, though, this will be set to the empty string (\fB""\fR). .RE .SS "Regular Expressions" -.sp .LP The \fBnawk\fR utility makes use of the extended regular expression notation (see \fBregex\fR(5)) except that it allows the use of C-language conventions to @@ -817,14 +835,14 @@ character and the record separator) can be embedded in the pattern and an appropriate pattern matches any character. However, in all \fBnawk\fR regular expression matching, the use of one or more NULL characters in the pattern, input record or text string produces undefined results. + .SS "Patterns" -.sp .LP A \fIpattern\fR is any valid \fIexpression,\fR a range specified by two expressions separated by comma, or one of the two special patterns \fBBEGIN\fR or \fBEND\fR. + .SS "Special Patterns" -.sp .LP The \fBnawk\fR utility recognizes two special patterns, \fBBEGIN\fR and \fBEND\fR. Each \fBBEGIN\fR pattern is matched once and its associated action @@ -848,23 +866,23 @@ without reading its input when the last statement in the last \fBBEGIN\fR action is executed. If an \fBnawk\fR program consists of only actions with the pattern \fBEND\fR or only actions with the patterns \fBBEGIN\fR and \fBEND\fR, the input is read before the statements in the \fBEND\fR actions are executed. + .SS "Expression Patterns" -.sp .LP An expression pattern is evaluated as if it were an expression in a Boolean context. If the result is true, the pattern is considered to match, and the associated action (if any) is executed. If the result is false, the action is not executed. + .SS "Pattern Ranges" -.sp .LP A pattern range consists of two expressions separated by a comma. In this case, the action is performed for all records between a match of the first expression and the following match of the second expression, inclusive. At this point, the pattern range can be repeated starting at input records subsequent to the end of the matched range. + .SS "Actions" -.sp .LP An action is a sequence of statements. A statement can be one of the following: .sp @@ -876,6 +894,7 @@ do \fIstatement\fR while ( \fIexpression\fR ) for ( \fIexpression\fR ; \fIexpression\fR ; \fIexpression\fR ) \fIstatement\fR for ( \fIvar\fR in \fIarray\fR ) \fIstatement\fR delete \fIarray\fR[\fIsubscript\fR] #delete an array element +delete \fIarray\fR #delete all elements within an array break continue { [ \fIstatement\fR ] .\|.\|. } @@ -883,6 +902,7 @@ continue print [ \fIexpression-list\fR ] [ >\fIexpression\fR ] printf format [ ,\fIexpression-list\fR ] [ >\fIexpression\fR ] next # skip remaining patterns on this input line +nextfile # skip remaining patterns on this input file exit [expr] # skip the rest of the input; exit status is expr return [expr] .fi @@ -900,6 +920,12 @@ record to be abandoned. The behavior is undefined if a \fBnext\fR statement appears or is invoked in a \fBBEGIN\fR or \fBEND\fR action. .sp .LP +The \fBnextfile\fR statement is similar to \fBnext\fR, but also skips all other +records in the current file, and moves on to processing the next input file if +available (or exits the program if there are none). (Note that this keyword is +not supported by \fB/usr/xpg4/bin/awk\fR.) +.sp +.LP The \fBexit\fR statement invokes all \fBEND\fR actions in the order in which they occur in the program source and then terminate the program without reading further input. An \fBexit\fR statement inside an \fBEND\fR action terminates @@ -907,8 +933,8 @@ the program without further execution of \fBEND\fR actions. If an expression is specified in an \fBexit\fR statement, its numeric value is the exit status of \fBnawk\fR, unless subsequent errors are encountered or a subsequent \fBexit\fR statement with an expression is executed. + .SS "Output Statements" -.sp .LP Both \fBprint\fR and \fBprintf\fR statements write to standard output by default. The output is written to the location specified by @@ -1046,13 +1072,13 @@ unspecified. .sp .LP Both \fBprint\fR and \fBprintf\fR can output at least \fB{LINE_MAX}\fR bytes. + .SS "Functions" -.sp .LP The \fBnawk\fR language has a variety of built-in functions: arithmetic, string, input/output and general. + .SS "Arithmetic Functions" -.sp .LP The arithmetic functions, except for \fBint\fR, are based on the \fBISO\fR \fBC\fR standard. The behavior is undefined in cases where the \fBISO\fR @@ -1144,7 +1170,6 @@ Set the seed value for \fBrand\fR to \fIexpr\fR or use the time of day if .RE .SS "String Functions" -.sp .LP The string functions in the following list shall be supported. Although the grammar permits built-in functions to appear with no arguments or parentheses, @@ -1176,12 +1201,15 @@ string \fIt\fR first occurs, or zero if it does not occur at all. .sp .ne 2 .na -\fB\fBlength\fR[([\fIs\fR])]\fR +\fB\fBlength\fR[([\fIv\fR])]\fR .ad .sp .6 .RS 4n -Return the length, in characters, of its argument taken as a string, or of the -whole record, \fB$0\fR, if there is no argument. +Given no argument, this function returns the length of the whole record, +\fB$0\fR. If given an array as an argument (and using \fB/usr/bin/nawk\fR), +then this returns the number of elements it contains. Otherwise, this function +interprets the argument as a string (performing any needed conversions) and +returns its length in characters. .RE .sp @@ -1294,8 +1322,8 @@ string by the upper-case letter specified by the mapping. Other characters in All of the preceding functions that take \fIERE\fR as a parameter expect a pattern or a string valued expression that is a regular expression as defined below. + .SS "Input/Output and General Functions" -.sp .LP The input/output and general functions are: .sp @@ -1313,6 +1341,20 @@ non-zero. .sp .ne 2 .na +\fB\fBfflush(\fR\fIexpression\fR)\fR +.ad +.RS 27n +Flush any buffered output for the file or pipe opened by a \fBprint\fR or +\fBprintf\fR statement or a call to \fBgetline\fR with the same string-valued +\fIexpression\fR. If the flush was successful, the function returns \fB0\fR; +otherwise, it returns \fBEOF\fR. If no arguments or the empty string +(\fB""\fR) are given, then all open files will be flushed. (Note that +\fBfflush\fR is supported in \fB/usr/bin/nawk\fR only.) +.RE + +.sp +.ne 2 +.na \fB\fIexpression\fR|\fBgetline\fR[\fIvar\fR]\fR .ad .RS 27n @@ -1343,7 +1385,7 @@ parentheses properly. .na \fB\fBgetline\fR\fR .ad -.RS 30n +.RS 27n Set \fB$0\fR to the next input record from the current input file. This form of \fBgetline\fR sets the \fBNF\fR, \fBNR\fR, and \fBFNR\fR variables. .RE @@ -1353,7 +1395,7 @@ Set \fB$0\fR to the next input record from the current input file. This form of .na \fB\fBgetline\fR \fIvar\fR\fR .ad -.RS 30n +.RS 27n Set variable \fIvar\fR to the next input record from the current input file. This form of \fBgetline\fR sets the \fBFNR\fR and \fBNR\fR variables. .RE @@ -1363,7 +1405,7 @@ This form of \fBgetline\fR sets the \fBFNR\fR and \fBNR\fR variables. .na \fB\fBgetline\fR [\fIvar\fR] \fB<\fR \fIexpression\fR\fR .ad -.RS 30n +.RS 27n Read the next record of input from a named file. The \fIexpression\fR is evaluated to produce a string that is used as a full pathname. If the file of that name is not currently open, it is opened. As long as the stream remains @@ -1385,7 +1427,7 @@ portable applications must be put in parentheses properly. .na \fB\fBsystem\fR(\fIexpression\fR)\fR .ad -.RS 30n +.RS 27n Execute the command given by \fIexpression\fR in a manner equivalent to the \fBsystem\fR(3C) function and return the exit status of the command. .RE @@ -1400,8 +1442,8 @@ Where strings are used as the name of a file or pipeline, the strings must be textually identical. The terminology ``same string value'' implies that ``equivalent strings'', even those that differ only by space characters, represent different files. + .SS "User-defined Functions" -.sp .LP The \fBnawk\fR language also provides user-defined functions. Such functions can be defined as: @@ -1453,8 +1495,8 @@ outside of a function definition, the behavior is undefined. In the function definition, newline characters are optional before the opening brace and after the closing brace. Function definitions can appear anywhere in the program where a \fIpattern-action\fR pair is allowed. + .SH USAGE -.sp .LP The \fBindex\fR, \fBlength\fR, \fBmatch\fR, and \fBsubstr\fR functions should not be confused with similar functions in the \fBISO C\fR standard; the @@ -1469,8 +1511,8 @@ enforce the proper evaluation precedence. .LP See \fBlargefile\fR(5) for the description of the behavior of \fBnawk\fR when encountering files greater than or equal to 2 Gbyte (2^31 bytes). + .SH EXAMPLES -.sp .LP The \fBnawk\fR program specified in the command line is most easily specified within single-quotes (for example, \fB\&'\fR\fIprogram\fR\fB\&'\fR) for @@ -1750,7 +1792,6 @@ then the command line prints the file \fBinput\fR, filling in page numbers starting at 5. .SH ENVIRONMENT VARIABLES -.sp .LP See \fBenviron\fR(5) for descriptions of the following environment variables that affect execution: \fBLC_COLLATE\fR, \fBLC_CTYPE\fR, \fBLC_MESSAGES\fR, and @@ -1769,7 +1810,6 @@ programs (including assignments in command-line arguments). .RE .SH EXIT STATUS -.sp .LP The following exit values are returned: .sp @@ -1796,7 +1836,6 @@ The exit status can be altered within the program by using an \fBexit\fR expression. .SH SEE ALSO -.sp .LP \fBawk\fR(1), \fBed\fR(1), \fBegrep\fR(1), \fBgrep\fR(1), \fBlex\fR(1), \fBsed\fR(1), \fBpopen\fR(3C), \fBprintf\fR(3C), \fBsystem\fR(3C), @@ -1806,8 +1845,8 @@ expression. .LP Aho, A. V., B. W. Kernighan, and P. J. Weinberger, \fIThe AWK Programming Language\fR, Addison-Wesley, 1988. + .SH DIAGNOSTICS -.sp .LP If any \fIfile\fR operand is specified and the named file cannot be accessed, \fBnawk\fR writes a diagnostic message to standard error and terminate without @@ -1817,8 +1856,8 @@ any further action. If the program specified by either the \fIprogram\fR operand or a \fIprogfile\fR operand is not a valid \fBnawk\fR program (as specified in \fBEXTENDED DESCRIPTION\fR), the behavior is undefined. + .SH NOTES -.sp .LP Input white space is not preserved on output if fields are involved. .sp diff --git a/usr/src/pkg/manifests/system-test-utiltest.mf b/usr/src/pkg/manifests/system-test-utiltest.mf index 2cf7b04e9e..118c1e2c6d 100644 --- a/usr/src/pkg/manifests/system-test-utiltest.mf +++ b/usr/src/pkg/manifests/system-test-utiltest.mf @@ -29,6 +29,7 @@ dir path=opt/util-tests/bin dir path=opt/util-tests/runfiles dir path=opt/util-tests/tests dir path=opt/util-tests/tests/awk +dir path=opt/util-tests/tests/awk/bugs-fixed dir path=opt/util-tests/tests/awk/data dir path=opt/util-tests/tests/awk/examples dir path=opt/util-tests/tests/awk/examples/awk @@ -57,6 +58,42 @@ file path=opt/util-tests/bin/print_json mode=0555 file path=opt/util-tests/bin/utiltest mode=0555 file path=opt/util-tests/runfiles/default.run mode=0444 file path=opt/util-tests/tests/allowed-ips mode=0555 +file path=opt/util-tests/tests/awk/bugs-fixed/a-format.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/a-format.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/concat-assign-same.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/concat-assign-same.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/decr-NF.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/decr-NF.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/fs-overflow.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/fs-overflow.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/negative-nf.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/negative-nf.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/nf-self-assign.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/nf-self-assign.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/numeric-fs.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/numeric-fs.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/numeric-output-seps.awk \ + mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/numeric-output-seps.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/numeric-rs.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/numeric-rs.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/numeric-subsep.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/numeric-subsep.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/ofs-rebuild.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/ofs-rebuild.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/space.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/space.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/split-fs-from-array.awk \ + mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/split-fs-from-array.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/string-conv.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/string-conv.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/subsep-overflow.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/subsep-overflow.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/system-status.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/system-status.ok mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/unary-plus.awk mode=0444 +file path=opt/util-tests/tests/awk/bugs-fixed/unary-plus.ok mode=0444 file path=opt/util-tests/tests/awk/data/test.countries mode=0444 file path=opt/util-tests/tests/awk/data/test.data mode=0444 file path=opt/util-tests/tests/awk/examples/awk/p.1 mode=0444 @@ -166,9 +203,10 @@ file path=opt/util-tests/tests/awk/examples/awk/t.concat mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.cond mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.contin mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.count mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.crlf mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.cum mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.d.x mode=0444 -file path=opt/util-tests/tests/awk/examples/awk/t.delete mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.delete0 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.delete1 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.delete2 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.delete3 mode=0444 @@ -187,6 +225,7 @@ file path=opt/util-tests/tests/awk/examples/awk/t.f4 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.for mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.for1 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.for2 mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.for3 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.format4 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.fun mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.fun0 mode=0444 @@ -195,7 +234,7 @@ file path=opt/util-tests/tests/awk/examples/awk/t.fun2 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.fun3 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.fun4 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.fun5 mode=0444 -file path=opt/util-tests/tests/awk/examples/awk/t.getline mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.getline1 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.getval mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.gsub mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.gsub1 mode=0444 @@ -246,7 +285,7 @@ file path=opt/util-tests/tests/awk/examples/awk/t.re5 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.re7 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.reFS mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.rec mode=0444 -file path=opt/util-tests/tests/awk/examples/awk/t.redir mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.redir1 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.reg mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.roff mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.sep mode=0444 @@ -257,17 +296,19 @@ file path=opt/util-tests/tests/awk/examples/awk/t.set0b mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.set1 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.set2 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.set3 mode=0444 -file path=opt/util-tests/tests/awk/examples/awk/t.split mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.split1 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.split2 mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.split2a mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.split3 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.split4 mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.split8 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.split9 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.split9a mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.stately mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.strcmp mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.strcmp1 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.strnum mode=0444 -file path=opt/util-tests/tests/awk/examples/awk/t.sub mode=0444 +file path=opt/util-tests/tests/awk/examples/awk/t.sub0 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.sub1 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.sub2 mode=0444 file path=opt/util-tests/tests/awk/examples/awk/t.sub3 mode=0444 @@ -386,9 +427,10 @@ file path=opt/util-tests/tests/awk/examples/out/t.concat mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.cond mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.contin mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.count mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.crlf mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.cum mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.d.x mode=0444 -file path=opt/util-tests/tests/awk/examples/out/t.delete mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.delete0 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.delete1 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.delete2 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.delete3 mode=0444 @@ -407,6 +449,7 @@ file path=opt/util-tests/tests/awk/examples/out/t.f4 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.for mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.for1 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.for2 mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.for3 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.format4 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.fun mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.fun0 mode=0444 @@ -415,7 +458,7 @@ file path=opt/util-tests/tests/awk/examples/out/t.fun2 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.fun3 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.fun4 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.fun5 mode=0444 -file path=opt/util-tests/tests/awk/examples/out/t.getline mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.getline1 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.getval mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.gsub mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.gsub1 mode=0444 @@ -466,7 +509,7 @@ file path=opt/util-tests/tests/awk/examples/out/t.re5 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.re7 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.reFS mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.rec mode=0444 -file path=opt/util-tests/tests/awk/examples/out/t.redir mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.redir1 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.reg mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.roff mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.sep mode=0444 @@ -477,17 +520,19 @@ file path=opt/util-tests/tests/awk/examples/out/t.set0b mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.set1 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.set2 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.set3 mode=0444 -file path=opt/util-tests/tests/awk/examples/out/t.split mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.split1 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.split2 mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.split2a mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.split3 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.split4 mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.split8 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.split9 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.split9a mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.stately mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.strcmp mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.strcmp1 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.strnum mode=0444 -file path=opt/util-tests/tests/awk/examples/out/t.sub mode=0444 +file path=opt/util-tests/tests/awk/examples/out/t.sub0 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.sub1 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.sub2 mode=0444 file path=opt/util-tests/tests/awk/examples/out/t.sub3 mode=0444 @@ -517,6 +562,9 @@ file path=opt/util-tests/tests/awk/gnu/arrymem1.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/arrymem1.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/arynasty.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/arynasty.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/arynocls.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/arynocls.data mode=0444 +file path=opt/util-tests/tests/awk/gnu/arynocls.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/aryprm9.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/aryprm9.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/arysubnm.awk mode=0444 @@ -526,11 +574,19 @@ file path=opt/util-tests/tests/awk/gnu/aryunasgn.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/asgext.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/asgext.in mode=0444 file path=opt/util-tests/tests/awk/gnu/asgext.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/back89.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/back89.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/back89.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/childin.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/childin.in mode=0444 file path=opt/util-tests/tests/awk/gnu/childin.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/clobber.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/clobber.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/closebad.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/closebad.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/clsflnam.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/clsflnam.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/clsflnam.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/compare.in mode=0444 file path=opt/util-tests/tests/awk/gnu/compare.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/compare.sh mode=0555 @@ -541,11 +597,20 @@ file path=opt/util-tests/tests/awk/gnu/concat1.in mode=0444 file path=opt/util-tests/tests/awk/gnu/concat1.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/concat2.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/concat2.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/concat3.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/concat3.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/concat4.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/concat4.in mode=0444 file path=opt/util-tests/tests/awk/gnu/concat4.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/concat5.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/concat5.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/convfmt.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/convfmt.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/datanonl.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/datanonl.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/datanonl.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/delarprm.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/delarprm.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/dfastress.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/dfastress.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/dynlj.awk mode=0444 @@ -563,6 +628,8 @@ file path=opt/util-tests/tests/awk/gnu/fcall_exit.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/fcall_exit2.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/fcall_exit2.in mode=0444 file path=opt/util-tests/tests/awk/gnu/fcall_exit2.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/fflush.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/fflush.sh mode=0555 file path=opt/util-tests/tests/awk/gnu/fldchg.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/fldchg.in mode=0444 file path=opt/util-tests/tests/awk/gnu/fldchg.ok mode=0444 @@ -572,6 +639,8 @@ file path=opt/util-tests/tests/awk/gnu/fldchgnf.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/fldterm.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/fldterm.in mode=0444 file path=opt/util-tests/tests/awk/gnu/fldterm.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/fordel.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/fordel.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/forsimp.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/forsimp.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/fsbs.awk mode=0444 @@ -591,6 +660,8 @@ file path=opt/util-tests/tests/awk/gnu/funsemnl.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/funstack.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/funstack.in mode=0444 file path=opt/util-tests/tests/awk/gnu/funstack.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/gawksub.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/gawksub.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/getline2.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/getline2.sh mode=0555 file path=opt/util-tests/tests/awk/gnu/getline3.awk mode=0444 @@ -610,6 +681,9 @@ file path=opt/util-tests/tests/awk/gnu/gsubtest.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/gsubtest.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/gsubtst2.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/gsubtst2.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/gsubtst5.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/gsubtst5.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/gsubtst5.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/gsubtst7.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/gsubtst7.in mode=0444 file path=opt/util-tests/tests/awk/gnu/gsubtst7.ok mode=0444 @@ -642,6 +716,9 @@ file path=opt/util-tests/tests/awk/gnu/localenl.sh mode=0555 file path=opt/util-tests/tests/awk/gnu/longsub.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/longsub.in mode=0444 file path=opt/util-tests/tests/awk/gnu/longsub.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/longwrds.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/longwrds.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/longwrds.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/manglprm.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/manglprm.in mode=0444 file path=opt/util-tests/tests/awk/gnu/manglprm.ok mode=0444 @@ -707,6 +784,11 @@ file path=opt/util-tests/tests/awk/gnu/octsub.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/ofmt.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/ofmt.in mode=0444 file path=opt/util-tests/tests/awk/gnu/ofmt.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/ofmta.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/ofmta.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/ofmtbig.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/ofmtbig.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/ofmtbig.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/ofmtfidl.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/ofmtfidl.in mode=0444 file path=opt/util-tests/tests/awk/gnu/ofmtfidl.ok mode=0444 @@ -736,8 +818,9 @@ file path=opt/util-tests/tests/awk/gnu/pcntplus.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/pcntplus.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/pipeio1.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/pipeio1.ok mode=0444 -file path=opt/util-tests/tests/awk/gnu/posix2008sub.awk mode=0444 -file path=opt/util-tests/tests/awk/gnu/posix2008sub.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/pipeio2.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/pipeio2.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/pipeio2.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/poundbang.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/poundbang.sh mode=0555 file path=opt/util-tests/tests/awk/gnu/prdupval.awk mode=0444 @@ -760,6 +843,9 @@ file path=opt/util-tests/tests/awk/gnu/randtest.sh mode=0555 file path=opt/util-tests/tests/awk/gnu/range1.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/range1.in mode=0444 file path=opt/util-tests/tests/awk/gnu/range1.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/rebrackloc.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/rebrackloc.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/rebrackloc.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/rebt8b1.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/rebt8b1.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/rebuild.awk mode=0444 @@ -768,9 +854,14 @@ file path=opt/util-tests/tests/awk/gnu/rebuild.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/redfilnm.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/redfilnm.in mode=0444 file path=opt/util-tests/tests/awk/gnu/redfilnm.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/regeq.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/regeq.in mode=0444 +file path=opt/util-tests/tests/awk/gnu/regeq.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/regexpbrack2.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/regexpbrack2.in mode=0444 file path=opt/util-tests/tests/awk/gnu/regexpbrack2.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/regexprange.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/regexprange.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/reparse.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/reparse.in mode=0444 file path=opt/util-tests/tests/awk/gnu/reparse.ok mode=0444 @@ -817,6 +908,8 @@ file path=opt/util-tests/tests/awk/gnu/sigpipe1.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/splitargv.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/splitargv.in mode=0444 file path=opt/util-tests/tests/awk/gnu/splitargv.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/splitarr.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/splitarr.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/splitdef.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/splitdef.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/splitvar.awk mode=0444 @@ -824,6 +917,8 @@ file path=opt/util-tests/tests/awk/gnu/splitvar.in mode=0444 file path=opt/util-tests/tests/awk/gnu/splitvar.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/splitwht.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/splitwht.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/status-close.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/status-close.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/strcat1.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/strcat1.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/strnum1.awk mode=0444 @@ -838,6 +933,8 @@ file path=opt/util-tests/tests/awk/gnu/subamp.in mode=0444 file path=opt/util-tests/tests/awk/gnu/subamp.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/subi18n.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/subi18n.ok mode=0444 +file path=opt/util-tests/tests/awk/gnu/subsepnm.awk mode=0444 +file path=opt/util-tests/tests/awk/gnu/subsepnm.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/subslash.awk mode=0444 file path=opt/util-tests/tests/awk/gnu/subslash.ok mode=0444 file path=opt/util-tests/tests/awk/gnu/substr.awk mode=0444 @@ -911,14 +1008,20 @@ file path=opt/util-tests/tests/awk/syn/fnaryscl.awk mode=0444 file path=opt/util-tests/tests/awk/syn/fnaryscl.ok mode=0444 file path=opt/util-tests/tests/awk/syn/fnmisc.awk mode=0444 file path=opt/util-tests/tests/awk/syn/fnmisc.ok mode=0444 +file path=opt/util-tests/tests/awk/syn/funsmnam.awk mode=0444 +file path=opt/util-tests/tests/awk/syn/funsmnam.ok mode=0444 file path=opt/util-tests/tests/awk/syn/gsubasgn.awk mode=0444 file path=opt/util-tests/tests/awk/syn/gsubasgn.ok mode=0444 file path=opt/util-tests/tests/awk/syn/nastyparm.awk mode=0444 file path=opt/util-tests/tests/awk/syn/nastyparm.ok mode=0444 +file path=opt/util-tests/tests/awk/syn/nfneg.awk mode=0444 +file path=opt/util-tests/tests/awk/syn/nfneg.ok mode=0444 file path=opt/util-tests/tests/awk/syn/noparms.awk mode=0444 file path=opt/util-tests/tests/awk/syn/noparms.ok mode=0444 file path=opt/util-tests/tests/awk/syn/nulinsrc.awk mode=0444 file path=opt/util-tests/tests/awk/syn/nulinsrc.ok mode=0444 +file path=opt/util-tests/tests/awk/syn/paramdup.awk mode=0444 +file path=opt/util-tests/tests/awk/syn/paramdup.ok mode=0444 file path=opt/util-tests/tests/awk/syn/parseme.awk mode=0444 file path=opt/util-tests/tests/awk/syn/parseme.ok mode=0444 file path=opt/util-tests/tests/awk/syn/readbuf.awk mode=0444 @@ -943,6 +1046,7 @@ file path=opt/util-tests/tests/awk/tests/T.builtin mode=0555 file path=opt/util-tests/tests/awk/tests/T.chem mode=0555 file path=opt/util-tests/tests/awk/tests/T.close mode=0555 file path=opt/util-tests/tests/awk/tests/T.clv mode=0555 +file path=opt/util-tests/tests/awk/tests/T.delete mode=0555 file path=opt/util-tests/tests/awk/tests/T.errmsg mode=0555 file path=opt/util-tests/tests/awk/tests/T.expr mode=0555 file path=opt/util-tests/tests/awk/tests/T.exprconv mode=0555 @@ -951,16 +1055,22 @@ file path=opt/util-tests/tests/awk/tests/T.func mode=0555 file path=opt/util-tests/tests/awk/tests/T.gawk mode=0555 file path=opt/util-tests/tests/awk/tests/T.getline mode=0555 file path=opt/util-tests/tests/awk/tests/T.latin1 mode=0555 +file path=opt/util-tests/tests/awk/tests/T.lilly mode=0555 file path=opt/util-tests/tests/awk/tests/T.main mode=0555 file path=opt/util-tests/tests/awk/tests/T.misc mode=0555 +file path=opt/util-tests/tests/awk/tests/T.nextfile mode=0555 file path=opt/util-tests/tests/awk/tests/T.overflow mode=0555 file path=opt/util-tests/tests/awk/tests/T.re mode=0555 +file path=opt/util-tests/tests/awk/tests/T.recache mode=0555 file path=opt/util-tests/tests/awk/tests/T.redir mode=0555 +file path=opt/util-tests/tests/awk/tests/T.rt mode=0555 file path=opt/util-tests/tests/awk/tests/T.split mode=0555 file path=opt/util-tests/tests/awk/tests/T.sub mode=0555 file path=opt/util-tests/tests/awk/tests/T.system mode=0555 file path=opt/util-tests/tests/awk/tests/chem.awk mode=0444 file path=opt/util-tests/tests/awk/tests/latin1 mode=0444 +file path=opt/util-tests/tests/awk/tests/lilly.ok mode=0444 +file path=opt/util-tests/tests/awk/tests/lilly.progs mode=0444 file path=opt/util-tests/tests/awk/tests/lsd1.ok mode=0444 file path=opt/util-tests/tests/awk/tests/lsd1.p mode=0444 file path=opt/util-tests/tests/awk/tests/penicil.ok mode=0444 diff --git a/usr/src/test/util-tests/tests/awk/Makefile b/usr/src/test/util-tests/tests/awk/Makefile index e26511c9f8..cea57235c7 100644 --- a/usr/src/test/util-tests/tests/awk/Makefile +++ b/usr/src/test/util-tests/tests/awk/Makefile @@ -20,9 +20,12 @@ DATA_FILES = \ test.countries \ test.data +BUGS_AWK :sh= (cd bugs-fixed; print *.awk) +BUGS_FILES = $(BUGS_AWK) $(BUGS_AWK:%.awk=%.ok) + EXAMPLES_FILES :sh= (cd examples/awk; print p.* t.*) -TESTS_FILES :sh= (cd tests; print T.* *.p *.ok chem.awk latin1) +TESTS_FILES :sh= (cd tests; print T.* *.p *.ok chem.awk latin1 lilly.progs) GNU_AWK :sh= (cd gnu; print *.awk) GNU_KSH :sh= (cd gnu; print *.sh) @@ -42,11 +45,12 @@ GNU_FILES = \ $(GNU_AWK) $(GNU_AWK:%.awk=%.ok) \ $(GNU_KSH) $(GNU_KSH:%.sh=%.ok) \ $(GNU_IN) $(GNU_KSH:%.in=%.awk) \ - out1.ok out2.ok out3.ok # Used by messages.sh + arynocls.data out1.ok out2.ok out3.ok # arynocls.awk & messages.sh data SYN_FILES :sh= (cd syn; print *.awk) ROOTFILES = \ + $(BUGS_FILES:%=$(TESTDIR)/bugs-fixed/%) \ $(DATA_FILES:%=$(TESTDIR)/data/%) \ $(EXAMPLES_FILES:%=$(TESTDIR)/examples/awk/%) \ $(EXAMPLES_FILES:%=$(TESTDIR)/examples/out/%) \ @@ -56,7 +60,7 @@ ROOTFILES = \ $(SYN_FILES:%.awk=$(TESTDIR)/syn/%.ok) \ $(TESTDIR)/runtests.sh -SUBDIRS = data examples/awk examples/out gnu syn tests +SUBDIRS = bugs-fixed data examples/awk examples/out gnu syn tests ROOTOPTPKG = $(ROOT)/opt/util-tests TESTDIR = $(ROOTOPTPKG)/tests/awk @@ -74,6 +78,7 @@ $(TESTDIR)/%.in := FILEMODE=0444 $(TESTDIR)/%.ok := FILEMODE=0444 $(TESTDIR)/%.sh := FILEMODE=0555 +$(TESTDIR)/tests/lilly.progs := FILEMODE=0444 $(TESTDIR)/tests/latin1 := FILEMODE=0444 $(TESTDIR)/tests/T.% := FILEMODE=0555 $(TESTDIR)/tests/%.p := FILEMODE=0444 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/a-format.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/a-format.awk new file mode 100644 index 0000000000..67a11222c8 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/a-format.awk @@ -0,0 +1,3 @@ +BEGIN { + printf("%.1a\n", 42) +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/a-format.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/a-format.ok new file mode 100644 index 0000000000..e421e2d01b --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/a-format.ok @@ -0,0 +1 @@ +0x1.5p+5 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/concat-assign-same.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/concat-assign-same.awk new file mode 100644 index 0000000000..ed19f35ca8 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/concat-assign-same.awk @@ -0,0 +1,4 @@ +BEGIN { + print (a = 1) (a = 2) (a = 3) (a = 4) (a = 5); + print (a = 1), (a = 2), (a = 3), (a = 4), (a = 5); +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/concat-assign-same.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/concat-assign-same.ok new file mode 100644 index 0000000000..447505259d --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/concat-assign-same.ok @@ -0,0 +1,2 @@ +12345 +1 2 3 4 5 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/decr-NF.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/decr-NF.awk new file mode 100644 index 0000000000..7474991d19 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/decr-NF.awk @@ -0,0 +1,11 @@ +BEGIN { + $0 = "a b c d e f" + print NF + OFS = ":" + NF-- + print $0 + print NF + NF++ + print $0 + print NF +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/decr-NF.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/decr-NF.ok new file mode 100644 index 0000000000..3359cf2312 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/decr-NF.ok @@ -0,0 +1,5 @@ +6 +a:b:c:d:e +5 +a:b:c:d:e: +6 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/fs-overflow.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/fs-overflow.awk new file mode 100644 index 0000000000..be10f5a46f --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/fs-overflow.awk @@ -0,0 +1,13 @@ +function foo() { + a = ""; + for (i = 0; i < 10000; i++) { + a = a "c"; + } + return a; +} + +BEGIN { + FS = foo(); + $0="foo"; + print $1; +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/fs-overflow.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/fs-overflow.ok new file mode 100644 index 0000000000..6c1b534bcb --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/fs-overflow.ok @@ -0,0 +1,3 @@ +$AWK: field separator cccccccccc... is too long + source line number 11 +EXIT CODE: 2 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/negative-nf.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/negative-nf.awk new file mode 100644 index 0000000000..6caeee4602 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/negative-nf.awk @@ -0,0 +1 @@ +BEGIN { NF = -5; } diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/negative-nf.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/negative-nf.ok new file mode 100644 index 0000000000..efa0b60876 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/negative-nf.ok @@ -0,0 +1,3 @@ +$AWK: cannot set NF to a negative value + source line number 1 +EXIT CODE: 2 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/nf-self-assign.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/nf-self-assign.awk new file mode 100644 index 0000000000..6ae29eef91 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/nf-self-assign.awk @@ -0,0 +1,6 @@ +BEGIN { + $0="a b c"; + OFS=","; + NF = NF; + print; +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/nf-self-assign.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/nf-self-assign.ok new file mode 100644 index 0000000000..b2ffb02521 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/nf-self-assign.ok @@ -0,0 +1 @@ +a,b,c diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-fs.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-fs.awk new file mode 100644 index 0000000000..01e438d4aa --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-fs.awk @@ -0,0 +1,5 @@ +BEGIN { + FS = 0; split("20202", a); print a[1]; + FS = 1; $0="31313"; print $1; + FS = 2; "echo 42424" | getline; print $1; +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-fs.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-fs.ok new file mode 100644 index 0000000000..dcf37cd5e2 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-fs.ok @@ -0,0 +1,3 @@ +2 +3 +4 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-output-seps.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-output-seps.awk new file mode 100644 index 0000000000..daa0f72aa6 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-output-seps.awk @@ -0,0 +1,8 @@ +BEGIN { + $0 = "a b c"; + OFS = 1; + ORS = 2; + NF = 2; + print; + print "d", "e"; +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-output-seps.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-output-seps.ok new file mode 100644 index 0000000000..de6b2026e5 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-output-seps.ok @@ -0,0 +1 @@ +a1b2d1e2
\ No newline at end of file diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-rs.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-rs.awk new file mode 100644 index 0000000000..cc7a0a0c08 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-rs.awk @@ -0,0 +1,6 @@ +BEGIN { + RS = 1; + while ("echo a1b1c1d" | getline > 0) { + print $1; + } +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-rs.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-rs.ok new file mode 100644 index 0000000000..d68dd4031d --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-rs.ok @@ -0,0 +1,4 @@ +a +b +c +d diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-subsep.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-subsep.awk new file mode 100644 index 0000000000..1252e4a996 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-subsep.awk @@ -0,0 +1,5 @@ +BEGIN { + SUBSEP = 123.456; + a["hello", "world"] = "foo"; + print a["hello" SUBSEP "world"]; +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-subsep.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-subsep.ok new file mode 100644 index 0000000000..257cc5642c --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-subsep.ok @@ -0,0 +1 @@ +foo diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/ofs-rebuild.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/ofs-rebuild.awk new file mode 100644 index 0000000000..dd27000315 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/ofs-rebuild.awk @@ -0,0 +1,17 @@ +# The bug here is that nawk should use the value of OFS that +# was current when $0 became invalid to rebuild the record. + +BEGIN { + OFS = ":" + $0 = "a b c d e f g" + $3 = "3333" + # Conceptually, $0 should now be "a:b:3333:d:e:f:g" + + # Change OFS after (conceptually) rebuilding the record + OFS = "<>" + + # Unmodifed nawk prints "a<>b<>3333<>d<>e<>f<>g" because + # it delays rebuilding $0 until it's needed, and then it uses + # the current value of OFS. Oops. + print +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/ofs-rebuild.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/ofs-rebuild.ok new file mode 100644 index 0000000000..26892181f9 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/ofs-rebuild.ok @@ -0,0 +1 @@ +a:b:3333:d:e:f:g diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/space.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/space.awk new file mode 100644 index 0000000000..6aa87d2e62 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/space.awk @@ -0,0 +1,22 @@ +BEGIN { + c[" "] = "\" \"" + c["\a"] = "\\a" + c["\b"] = "\\b" + c["\f"] = "\\f" + c["\n"] = "\\n" + c["\r"] = "\\r" + c["\t"] = "\\t" + c["\v"] = "\\v" + + sort = "LC_ALL=C sort" + + for (i in c) + printf("%s %s [[:space:]]\n", c[i], + i ~ /[[:space:]]/ ? "~" : "!~") | sort + + for (i in c) + printf("%s %s [[:blank:]]\n", c[i], + i ~ /[[:blank:]]/ ? "~" : "!~") | sort + + close(sort) +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/space.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/space.ok new file mode 100644 index 0000000000..4278c5c9df --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/space.ok @@ -0,0 +1,16 @@ +" " ~ [[:blank:]] +" " ~ [[:space:]] +\a !~ [[:blank:]] +\a !~ [[:space:]] +\b !~ [[:blank:]] +\b !~ [[:space:]] +\f !~ [[:blank:]] +\f ~ [[:space:]] +\n !~ [[:blank:]] +\n ~ [[:space:]] +\r !~ [[:blank:]] +\r ~ [[:space:]] +\t ~ [[:blank:]] +\t ~ [[:space:]] +\v !~ [[:blank:]] +\v ~ [[:space:]] diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/split-fs-from-array.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/split-fs-from-array.awk new file mode 100644 index 0000000000..fce1607c2a --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/split-fs-from-array.awk @@ -0,0 +1,5 @@ +BEGIN { + a[1] = "elephantie" + a[2] = "e" + print split(a[1],a,a[2]), a[2], a[3], split(a[2],a,a[2]) +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/split-fs-from-array.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/split-fs-from-array.ok new file mode 100644 index 0000000000..9402b94f4f --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/split-fs-from-array.ok @@ -0,0 +1 @@ +4 l phanti 2 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/string-conv.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/string-conv.awk new file mode 100644 index 0000000000..a1f04aba35 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/string-conv.awk @@ -0,0 +1,13 @@ +BEGIN { + OFMT = ">>%.6g<<" + a = 12.1234 + print "a =", a + b = a "" + print "1 ->", b + CONVFMT = "%2.2f" + b = a "" + print "2 ->", b + CONVFMT = "%.12g" + b = a "" + print "3 ->", b +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/string-conv.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/string-conv.ok new file mode 100644 index 0000000000..7c09711320 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/string-conv.ok @@ -0,0 +1,4 @@ +a = >>12.1234<< +1 -> 12.1234 +2 -> 12.12 +3 -> 12.1234 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/subsep-overflow.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/subsep-overflow.awk new file mode 100644 index 0000000000..66c7c24db0 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/subsep-overflow.awk @@ -0,0 +1,24 @@ +function foo(c, n) { + s = ""; + for (i = 0; i < n; i++) { + s = s c; + } + return s; +} + +BEGIN { + str1 = foo("a", 4500); + str2 = foo("b", 9000); + + a[(SUBSEP = str1), (SUBSEP = str2), "c"] = 1; + + for (k in a) { + print length(k); + } + + print (((SUBSEP = str1), (SUBSEP = str2), "c") in a); + print (((SUBSEP = str1) SUBSEP (SUBSEP = str2) SUBSEP "c") in a); + delete a[(SUBSEP = str1), (SUBSEP = str2), "c"]; + print (((SUBSEP = str1), (SUBSEP = str2), "c") in a); + print (((SUBSEP = str1) SUBSEP (SUBSEP = str2) SUBSEP "c") in a); +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/subsep-overflow.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/subsep-overflow.ok new file mode 100644 index 0000000000..ddbbd78707 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/subsep-overflow.ok @@ -0,0 +1,5 @@ +27001 +1 +1 +0 +0 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/system-status.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/system-status.awk new file mode 100644 index 0000000000..25b92c0492 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/system-status.awk @@ -0,0 +1,19 @@ +# Unmodified nawk prints the 16 bit exit status divided by 256, but +# does so using floating point arithmetic, yielding strange results. +# +# The fix is to use the various macros defined for wait(2) and to +# use the signal number + 256 for death by signal, or signal number + 512 +# for death by signal with core dump. + +BEGIN { + status = system("exit 42") + print "normal status", status + + status = system("kill -HUP $$") + print "death by signal status", status + + status = system("cd $WORKDIR && kill -ABRT $$") + print "death by signal with core dump status", status + + system("rm -f core*") +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/system-status.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/system-status.ok new file mode 100644 index 0000000000..737828f5ed --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/system-status.ok @@ -0,0 +1,3 @@ +normal status 42 +death by signal status 257 +death by signal with core dump status 518 diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/unary-plus.awk b/usr/src/test/util-tests/tests/awk/bugs-fixed/unary-plus.awk new file mode 100644 index 0000000000..ba6185b967 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/unary-plus.awk @@ -0,0 +1,4 @@ +BEGIN { + print +"q" + print +"43.12345678912345678" +} diff --git a/usr/src/test/util-tests/tests/awk/bugs-fixed/unary-plus.ok b/usr/src/test/util-tests/tests/awk/bugs-fixed/unary-plus.ok new file mode 100644 index 0000000000..90f97afc5c --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/bugs-fixed/unary-plus.ok @@ -0,0 +1,2 @@ +0 +43.1235 diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.crlf b/usr/src/test/util-tests/tests/awk/examples/awk/t.crlf new file mode 100644 index 0000000000..c5f51ae0fc --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.crlf @@ -0,0 +1,4 @@ +# checks whether lines with crlf are parsed ok + +{print \
+ } diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.delete b/usr/src/test/util-tests/tests/awk/examples/awk/t.delete0 index ac5b9ca9e2..ac5b9ca9e2 100644 --- a/usr/src/test/util-tests/tests/awk/examples/awk/t.delete +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.delete0 diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.for3 b/usr/src/test/util-tests/tests/awk/examples/awk/t.for3 new file mode 100644 index 0000000000..96d581800a --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.for3 @@ -0,0 +1,8 @@ +{ for (i = 1; length($i) > 0; i++) + print i, $i +} +{ for (i = 1; + length($i) > 0; + i++) + print $i +} diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.getline b/usr/src/test/util-tests/tests/awk/examples/awk/t.getline1 index d85fe9bf46..d85fe9bf46 100644 --- a/usr/src/test/util-tests/tests/awk/examples/awk/t.getline +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.getline1 diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.redir b/usr/src/test/util-tests/tests/awk/examples/awk/t.redir1 index 335c4a3a56..335c4a3a56 100644 --- a/usr/src/test/util-tests/tests/awk/examples/awk/t.redir +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.redir1 diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.split b/usr/src/test/util-tests/tests/awk/examples/awk/t.split1 index f1c3bb593a..f1c3bb593a 100644 --- a/usr/src/test/util-tests/tests/awk/examples/awk/t.split +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.split1 diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.split2a b/usr/src/test/util-tests/tests/awk/examples/awk/t.split2a new file mode 100644 index 0000000000..d3a2140dda --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.split2a @@ -0,0 +1,4 @@ +BEGIN { + a[1]="a b" + print split(a[1],a),a[1],a[2] +} diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.split8 b/usr/src/test/util-tests/tests/awk/examples/awk/t.split8 new file mode 100644 index 0000000000..e967bddb12 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.split8 @@ -0,0 +1,9 @@ +{ + n = split ($0, x, /[ ]+/) + print n + if (n != NF) + print "split botch at ", NR, n, NF + for (i=1; i<=n; i++) + if ($i != x[i]) + print "different element at ", i, x[i], $i +} diff --git a/usr/src/test/util-tests/tests/awk/examples/awk/t.sub b/usr/src/test/util-tests/tests/awk/examples/awk/t.sub0 index 79f50133f0..79f50133f0 100644 --- a/usr/src/test/util-tests/tests/awk/examples/awk/t.sub +++ b/usr/src/test/util-tests/tests/awk/examples/awk/t.sub0 diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.NF b/usr/src/test/util-tests/tests/awk/examples/out/t.NF index 8c370eed8c..4480cd9e30 100644 --- a/usr/src/test/util-tests/tests/awk/examples/out/t.NF +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.NF @@ -1,995 +1,995 @@ 1 2 -/dev/rrp3: +/dev/rrp3:| 5 /dev/rrp3:||||five 0 2 - +| 5 ||||five 2 2 -17379 mel +17379|mel 5 17379|mel|||five 3 2 -16693 bwk me +16693|bwk 5 -16693|bwk|me||five +16693|bwk|||five 5 2 -16116 ken him someone else +16116|ken 5 -16116|ken|him|someone|five +16116|ken|||five 2 2 -15713 srb +15713|srb 5 15713|srb|||five 2 2 -11895 lem +11895|lem 5 11895|lem|||five 2 2 -10409 scj +10409|scj 5 10409|scj|||five 2 2 -10252 rhm +10252|rhm 5 10252|rhm|||five 2 2 - 9853 shen +9853|shen 5 9853|shen|||five 2 2 - 9748 a68 +9748|a68 5 9748|a68|||five 2 2 - 9492 sif +9492|sif 5 9492|sif|||five 2 2 - 9190 pjw +9190|pjw 5 9190|pjw|||five 2 2 - 8912 nls +8912|nls 5 8912|nls|||five 2 2 - 8895 dmr +8895|dmr 5 8895|dmr|||five 2 2 - 8491 cda +8491|cda 5 8491|cda|||five 2 2 - 8372 bs +8372|bs 5 8372|bs|||five 2 2 - 8252 llc +8252|llc 5 8252|llc|||five 2 2 - 7450 mb +7450|mb 5 7450|mb|||five 2 2 - 7360 ava +7360|ava 5 7360|ava|||five 2 2 - 7273 jrv +7273|jrv 5 7273|jrv|||five 2 2 - 7080 bin +7080|bin 5 7080|bin|||five 2 2 - 7063 greg +7063|greg 5 7063|greg|||five 2 2 - 6567 dict +6567|dict 5 6567|dict|||five 2 2 - 6462 lck +6462|lck 5 6462|lck|||five 2 2 - 6291 rje +6291|rje 5 6291|rje|||five 2 2 - 6211 lwf +6211|lwf 5 6211|lwf|||five 2 2 - 5671 dave +5671|dave 5 5671|dave|||five 2 2 - 5373 jhc +5373|jhc 5 5373|jhc|||five 2 2 - 5220 agf +5220|agf 5 5220|agf|||five 2 2 - 5167 doug +5167|doug 5 5167|doug|||five 2 2 - 5007 valerie +5007|valerie 5 5007|valerie|||five 2 2 - 3963 jca +3963|jca 5 3963|jca|||five 2 2 - 3895 bbs +3895|bbs 5 3895|bbs|||five 2 2 - 3796 moh +3796|moh 5 3796|moh|||five 2 2 - 3481 xchar +3481|xchar 5 3481|xchar|||five 2 2 - 3200 tbl +3200|tbl 5 3200|tbl|||five 2 2 - 2845 s +2845|s 5 2845|s|||five 2 2 - 2774 tgs +2774|tgs 5 2774|tgs|||five 2 2 - 2641 met +2641|met 5 2641|met|||five 2 2 - 2566 jck +2566|jck 5 2566|jck|||five 2 2 - 2511 port +2511|port 5 2511|port|||five 2 2 - 2479 sue +2479|sue 5 2479|sue|||five 2 2 - 2127 root +2127|root 5 2127|root|||five 2 2 - 1989 bsb +1989|bsb 5 1989|bsb|||five 2 2 - 1989 jeg +1989|jeg 5 1989|jeg|||five 2 2 - 1933 eag +1933|eag 5 1933|eag|||five 2 2 - 1801 pdj +1801|pdj 5 1801|pdj|||five 2 2 - 1590 tpc +1590|tpc 5 1590|tpc|||five 2 2 - 1385 cvw +1385|cvw 5 1385|cvw|||five 2 2 - 1370 rwm +1370|rwm 5 1370|rwm|||five 2 2 - 1316 avg +1316|avg 5 1316|avg|||five 2 2 - 1205 eg +1205|eg 5 1205|eg|||five 2 2 - 1194 jam +1194|jam 5 1194|jam|||five 2 2 - 1153 dl +1153|dl 5 1153|dl|||five 2 2 - 1150 lgm +1150|lgm 5 1150|lgm|||five 2 2 - 1031 cmb +1031|cmb 5 1031|cmb|||five 2 2 - 1018 jwr +1018|jwr 5 1018|jwr|||five 2 2 - 950 gdb +950|gdb 5 950|gdb|||five 2 2 - 931 marc +931|marc 5 931|marc|||five 2 2 - 898 usg +898|usg 5 898|usg|||five 2 2 - 865 ggr +865|ggr 5 865|ggr|||five 2 2 - 822 daemon +822|daemon 5 822|daemon|||five 2 2 - 803 mihalis +803|mihalis 5 803|mihalis|||five 2 2 - 700 honey +700|honey 5 700|honey|||five 2 2 - 624 tad +624|tad 5 624|tad|||five 2 2 - 559 acs +559|acs 5 559|acs|||five 2 2 - 541 uucp +541|uucp 5 541|uucp|||five 2 2 - 523 raf +523|raf 5 523|raf|||five 2 2 - 495 adh +495|adh 5 495|adh|||five 2 2 - 456 kec +456|kec 5 456|kec|||five 2 2 - 414 craig +414|craig 5 414|craig|||five 2 2 - 386 donmac +386|donmac 5 386|donmac|||five 2 2 - 375 jj +375|jj 5 375|jj|||five 2 2 - 348 ravi +348|ravi 5 348|ravi|||five 2 2 - 344 drw +344|drw 5 344|drw|||five 2 2 - 327 stars +327|stars 5 327|stars|||five 2 2 - 288 mrg +288|mrg 5 288|mrg|||five 2 2 - 272 jcb +272|jcb 5 272|jcb|||five 2 2 - 263 ralph +263|ralph 5 263|ralph|||five 2 2 - 253 tom +253|tom 5 253|tom|||five 2 2 - 251 sjb +251|sjb 5 251|sjb|||five 2 2 - 248 haight +248|haight 5 248|haight|||five 2 2 - 224 sharon +224|sharon 5 224|sharon|||five 2 2 - 222 chuck +222|chuck 5 222|chuck|||five 2 2 - 213 dsj +213|dsj 5 213|dsj|||five 2 2 - 201 bill +201|bill 5 201|bill|||five 2 2 - 184 god +184|god 5 184|god|||five 2 2 - 176 sys +176|sys 5 176|sys|||five 2 2 - 166 meh +166|meh 5 166|meh|||five 2 2 - 163 jon +163|jon 5 163|jon|||five 2 2 - 144 dan +144|dan 5 144|dan|||five 2 2 - 143 fox +143|fox 5 143|fox|||five 2 2 - 123 dale +123|dale 5 123|dale|||five 2 2 - 116 kab +116|kab 5 116|kab|||five 2 2 - 95 buz +95|buz 5 95|buz|||five 2 2 - 80 asc +80|asc 5 80|asc|||five 2 2 - 79 jas +79|jas 5 79|jas|||five 2 2 - 79 trt +79|trt 5 79|trt|||five 2 2 - 64 wsb +64|wsb 5 64|wsb|||five 2 2 - 62 dwh +62|dwh 5 62|dwh|||five 2 2 - 56 ktf +56|ktf 5 56|ktf|||five 2 2 - 54 lr +54|lr 5 54|lr|||five 2 2 - 47 dlc +47|dlc 5 47|dlc|||five 2 2 - 45 dls +45|dls 5 45|dls|||five 2 2 - 45 jwf +45|jwf 5 45|jwf|||five 2 2 - 44 mash +44|mash 5 44|mash|||five 2 2 - 43 ars +43|ars 5 43|ars|||five 2 2 - 43 vgl +43|vgl 5 43|vgl|||five 2 2 - 37 jfo +37|jfo 5 37|jfo|||five 2 2 - 32 rab +32|rab 5 32|rab|||five 2 2 - 31 pd +31|pd 5 31|pd|||five 2 2 - 29 jns +29|jns 5 29|jns|||five 2 2 - 25 spm +25|spm 5 25|spm|||five 2 2 - 22 rob +22|rob 5 22|rob|||five 2 2 - 15 egb +15|egb 5 15|egb|||five 2 2 - 10 hm +10|hm 5 10|hm|||five 2 2 - 10 mhb +10|mhb 5 10|mhb|||five 2 2 - 6 aed +6|aed 5 6|aed|||five 2 2 - 6 cpb +6|cpb 5 6|cpb|||five 2 2 - 5 evp +5|evp 5 5|evp|||five 2 2 - 4 ber +4|ber 5 4|ber|||five 2 2 - 4 men +4|men 5 4|men|||five 2 2 - 4 mitch +4|mitch 5 4|mitch|||five 2 2 - 3 ast +3|ast 5 3|ast|||five 2 2 - 3 jfr +3|jfr 5 3|jfr|||five 2 2 - 3 lax +3|lax 5 3|lax|||five 2 2 - 3 nel +3|nel 5 3|nel|||five 2 2 - 2 blue +2|blue 5 2|blue|||five 2 2 - 2 jfk +2|jfk 5 2|jfk|||five 2 2 - 2 njas +2|njas 5 2|njas|||five 2 2 - 1 122sec +1|122sec 5 1|122sec|||five 2 2 - 1 ddwar +1|ddwar 5 1|ddwar|||five 2 2 - 1 gopi +1|gopi 5 1|gopi|||five 2 2 - 1 jk +1|jk 5 1|jk|||five 2 2 - 1 learn +1|learn 5 1|learn|||five 2 2 - 1 low +1|low 5 1|low|||five 2 2 - 1 nac +1|nac 5 1|nac|||five 2 2 - 1 sidor +1|sidor 5 1|sidor|||five 1 2 -1root:EMpNB8Zp56:0:0:Super-User,,,,,,,:/:/bin/sh +1root:EMpNB8Zp56:0:0:Super-User,,,,,,,:/:/bin/sh| 5 1root:EMpNB8Zp56:0:0:Super-User,,,,,,,:/:/bin/sh||||five 4 2 -2roottcsh:*:0:0:Super-User running tcsh [cbm]:/:/bin/tcsh +2roottcsh:*:0:0:Super-User|running 5 -2roottcsh:*:0:0:Super-User|running|tcsh|[cbm]:/:/bin/tcsh|five +2roottcsh:*:0:0:Super-User|running|||five 3 2 -3sysadm:*:0:0:System V Administration:/usr/admin:/bin/sh +3sysadm:*:0:0:System|V 5 -3sysadm:*:0:0:System|V|Administration:/usr/admin:/bin/sh||five +3sysadm:*:0:0:System|V|||five 2 2 -4diag:*:0:996:Hardware Diagnostics:/usr/diags:/bin/csh +4diag:*:0:996:Hardware|Diagnostics:/usr/diags:/bin/csh 5 4diag:*:0:996:Hardware|Diagnostics:/usr/diags:/bin/csh|||five 1 2 -5daemon:*:1:1:daemons:/:/bin/sh +5daemon:*:1:1:daemons:/:/bin/sh| 5 5daemon:*:1:1:daemons:/:/bin/sh||||five 3 2 -6bin:*:2:2:System Tools Owner:/bin:/dev/null +6bin:*:2:2:System|Tools 5 -6bin:*:2:2:System|Tools|Owner:/bin:/dev/null||five +6bin:*:2:2:System|Tools|||five 1 2 -7nuucp:BJnuQbAo:6:10:UUCP.Admin:/usr/spool/uucppublic:/usr/lib/uucp/uucico +7nuucp:BJnuQbAo:6:10:UUCP.Admin:/usr/spool/uucppublic:/usr/lib/uucp/uucico| 5 7nuucp:BJnuQbAo:6:10:UUCP.Admin:/usr/spool/uucppublic:/usr/lib/uucp/uucico||||five 1 2 -8uucp:*:3:5:UUCP.Admin:/usr/lib/uucp: +8uucp:*:3:5:UUCP.Admin:/usr/lib/uucp:| 5 8uucp:*:3:5:UUCP.Admin:/usr/lib/uucp:||||five 3 2 -9sys:*:4:0:System Activity Owner:/usr/adm:/bin/sh +9sys:*:4:0:System|Activity 5 -9sys:*:4:0:System|Activity|Owner:/usr/adm:/bin/sh||five +9sys:*:4:0:System|Activity|||five 3 2 -10adm:*:5:3:Accounting Files Owner:/usr/adm:/bin/sh +10adm:*:5:3:Accounting|Files 5 -10adm:*:5:3:Accounting|Files|Owner:/usr/adm:/bin/sh||five +10adm:*:5:3:Accounting|Files|||five 3 2 -11lp:*:9:9:Print Spooler Owner:/var/spool/lp:/bin/sh +11lp:*:9:9:Print|Spooler 5 -11lp:*:9:9:Print|Spooler|Owner:/var/spool/lp:/bin/sh||five +11lp:*:9:9:Print|Spooler|||five 3 2 -12auditor:*:11:0:Audit Activity Owner:/auditor:/bin/sh +12auditor:*:11:0:Audit|Activity 5 -12auditor:*:11:0:Audit|Activity|Owner:/auditor:/bin/sh||five +12auditor:*:11:0:Audit|Activity|||five 3 2 -13dbadmin:*:12:0:Security Database Owner:/dbadmin:/bin/sh +13dbadmin:*:12:0:Security|Database 5 -13dbadmin:*:12:0:Security|Database|Owner:/dbadmin:/bin/sh||five +13dbadmin:*:12:0:Security|Database|||five 5 2 -14bootes:dcon:50:1:Tom Killian (DO NOT REMOVE):/tmp: +14bootes:dcon:50:1:Tom|Killian 5 -14bootes:dcon:50:1:Tom|Killian|(DO|NOT|five +14bootes:dcon:50:1:Tom|Killian|||five 5 2 -15cdjuke:dcon:51:1:Tom Killian (DO NOT REMOVE):/tmp: +15cdjuke:dcon:51:1:Tom|Killian 5 -15cdjuke:dcon:51:1:Tom|Killian|(DO|NOT|five +15cdjuke:dcon:51:1:Tom|Killian|||five 4 2 -16rfindd:*:66:1:Rfind Daemon and Fsdump:/var/rfindd:/bin/sh +16rfindd:*:66:1:Rfind|Daemon 5 -16rfindd:*:66:1:Rfind|Daemon|and|Fsdump:/var/rfindd:/bin/sh|five +16rfindd:*:66:1:Rfind|Daemon|||five 2 2 -17EZsetup:*:992:998:System Setup:/var/sysadmdesktop/EZsetup:/bin/csh +17EZsetup:*:992:998:System|Setup:/var/sysadmdesktop/EZsetup:/bin/csh 5 17EZsetup:*:992:998:System|Setup:/var/sysadmdesktop/EZsetup:/bin/csh|||five 2 2 -18demos:*:993:997:Demonstration User:/usr/demos:/bin/csh +18demos:*:993:997:Demonstration|User:/usr/demos:/bin/csh 5 18demos:*:993:997:Demonstration|User:/usr/demos:/bin/csh|||five 2 2 -19tutor:*:994:997:Tutorial User:/usr/tutor:/bin/csh +19tutor:*:994:997:Tutorial|User:/usr/tutor:/bin/csh 5 19tutor:*:994:997:Tutorial|User:/usr/tutor:/bin/csh|||five 3 2 -20tour:*:995:997:IRIS Space Tour:/usr/people/tour:/bin/csh +20tour:*:995:997:IRIS|Space 5 -20tour:*:995:997:IRIS|Space|Tour:/usr/people/tour:/bin/csh||five +20tour:*:995:997:IRIS|Space|||five 2 2 -21guest:nfP4/Wpvio/Rw:998:998:Guest Account:/usr/people/guest:/bin/csh +21guest:nfP4/Wpvio/Rw:998:998:Guest|Account:/usr/people/guest:/bin/csh 5 21guest:nfP4/Wpvio/Rw:998:998:Guest|Account:/usr/people/guest:/bin/csh|||five 2 2 -224Dgifts:0nWRTZsOMt.:999:998:4Dgifts Account:/usr/people/4Dgifts:/bin/csh +224Dgifts:0nWRTZsOMt.:999:998:4Dgifts|Account:/usr/people/4Dgifts:/bin/csh 5 224Dgifts:0nWRTZsOMt.:999:998:4Dgifts|Account:/usr/people/4Dgifts:/bin/csh|||five 3 2 -23nobody:*:60001:60001:SVR4 nobody uid:/dev/null:/dev/null +23nobody:*:60001:60001:SVR4|nobody 5 -23nobody:*:60001:60001:SVR4|nobody|uid:/dev/null:/dev/null||five +23nobody:*:60001:60001:SVR4|nobody|||five 3 2 -24noaccess:*:60002:60002:uid no access:/dev/null:/dev/null +24noaccess:*:60002:60002:uid|no 5 -24noaccess:*:60002:60002:uid|no|access:/dev/null:/dev/null||five +24noaccess:*:60002:60002:uid|no|||five 3 2 -25nobody:*:-2:-2:original nobody uid:/dev/null:/dev/null +25nobody:*:-2:-2:original|nobody 5 -25nobody:*:-2:-2:original|nobody|uid:/dev/null:/dev/null||five +25nobody:*:-2:-2:original|nobody|||five 2 2 -26rje:*:8:8:RJE Owner:/usr/spool/rje: +26rje:*:8:8:RJE|Owner:/usr/spool/rje: 5 26rje:*:8:8:RJE|Owner:/usr/spool/rje:|||five 3 2 -27changes:*:11:11:system change log:/: +27changes:*:11:11:system|change 5 -27changes:*:11:11:system|change|log:/:||five +27changes:*:11:11:system|change|||five 2 2 -28dist:sorry:9999:4:file distributions:/v/adm/dist:/v/bin/sh +28dist:sorry:9999:4:file|distributions:/v/adm/dist:/v/bin/sh 5 28dist:sorry:9999:4:file|distributions:/v/adm/dist:/v/bin/sh|||five 3 2 -29man:*:99:995:On-line Manual Owner:/: +29man:*:99:995:On-line|Manual 5 -29man:*:99:995:On-line|Manual|Owner:/:||five +29man:*:99:995:On-line|Manual|||five 4 2 -30phoneca:*:991:991:phone call log [tom]:/v/adm/log:/v/bin/sh +30phoneca:*:991:991:phone|call 5 -30phoneca:*:991:991:phone|call|log|[tom]:/v/adm/log:/v/bin/sh|five +30phoneca:*:991:991:phone|call|||five 8 2 -1r oot EMpNB8Zp56 0 0 Super-User,,,,,,, / /bin/sh +1r|oot 5 -1r|oot|EMpNB8Zp56|0|five +1r|oot|||five 11 2 -2r oottcsh * 0 0 Super-User running tcsh [cbm] / /bin/tcsh +2r|oottcsh 5 -2r|oottcsh|*|0|five +2r|oottcsh|||five 10 2 -3s ysadm * 0 0 System V Administration /usr/admin /bin/sh +3s|ysadm 5 -3s|ysadm|*|0|five +3s|ysadm|||five 9 2 -4d iag * 0 996 Hardware Diagnostics /usr/diags /bin/csh +4d|iag 5 -4d|iag|*|0|five +4d|iag|||five 8 2 -5d aemon * 1 1 daemons / /bin/sh +5d|aemon 5 -5d|aemon|*|1|five +5d|aemon|||five 10 2 -6b in * 2 2 System Tools Owner /bin /dev/null +6b|in 5 -6b|in|*|2|five +6b|in|||five 8 2 -7n uucp BJnuQbAo 6 10 UUCP.Admin /usr/spool/uucppublic /usr/lib/uucp/uucico +7n|uucp 5 -7n|uucp|BJnuQbAo|6|five +7n|uucp|||five 7 2 -8u ucp * 3 5 UUCP.Admin /usr/lib/uucp +8u|ucp 5 -8u|ucp|*|3|five +8u|ucp|||five 10 2 -9s ys * 4 0 System Activity Owner /usr/adm /bin/sh +9s|ys 5 -9s|ys|*|4|five +9s|ys|||five 10 2 -10 adm * 5 3 Accounting Files Owner /usr/adm /bin/sh +10|adm 5 -10|adm|*|5|five +10|adm|||five 10 2 -11 lp * 9 9 Print Spooler Owner /var/spool/lp /bin/sh +11|lp 5 -11|lp|*|9|five +11|lp|||five 10 2 -12 auditor * 11 0 Audit Activity Owner /auditor /bin/sh +12|auditor 5 -12|auditor|*|11|five +12|auditor|||five 10 2 -13 dbadmin * 12 0 Security Database Owner /dbadmin /bin/sh +13|dbadmin 5 -13|dbadmin|*|12|five +13|dbadmin|||five 11 2 -14 bootes dcon 50 1 Tom Killian (DO NOT REMOVE) /tmp +14|bootes 5 -14|bootes|dcon|50|five +14|bootes|||five 11 2 -15 cdjuke dcon 51 1 Tom Killian (DO NOT REMOVE) /tmp +15|cdjuke 5 -15|cdjuke|dcon|51|five +15|cdjuke|||five 11 2 -16 rfindd * 66 1 Rfind Daemon and Fsdump /var/rfindd /bin/sh +16|rfindd 5 -16|rfindd|*|66|five +16|rfindd|||five 9 2 -17 EZsetup * 992 998 System Setup /var/sysadmdesktop/EZsetup /bin/csh +17|EZsetup 5 -17|EZsetup|*|992|five +17|EZsetup|||five 9 2 -18 demos * 993 997 Demonstration User /usr/demos /bin/csh +18|demos 5 -18|demos|*|993|five +18|demos|||five 9 2 -19 tutor * 994 997 Tutorial User /usr/tutor /bin/csh +19|tutor 5 -19|tutor|*|994|five +19|tutor|||five 10 2 -20 tour * 995 997 IRIS Space Tour /usr/people/tour /bin/csh +20|tour 5 -20|tour|*|995|five +20|tour|||five 9 2 -21 guest nfP4/Wpvio/Rw 998 998 Guest Account /usr/people/guest /bin/csh +21|guest 5 -21|guest|nfP4/Wpvio/Rw|998|five +21|guest|||five 9 2 -22 4Dgifts 0nWRTZsOMt. 999 998 4Dgifts Account /usr/people/4Dgifts /bin/csh +22|4Dgifts 5 -22|4Dgifts|0nWRTZsOMt.|999|five +22|4Dgifts|||five 10 2 -23 nobody * 60001 60001 SVR4 nobody uid /dev/null /dev/null +23|nobody 5 -23|nobody|*|60001|five +23|nobody|||five 10 2 -24 noaccess * 60002 60002 uid no access /dev/null /dev/null +24|noaccess 5 -24|noaccess|*|60002|five +24|noaccess|||five 10 2 -25 nobody * -2 -2 original nobody uid /dev/null /dev/null +25|nobody 5 -25|nobody|*|-2|five +25|nobody|||five 8 2 -26 rje * 8 8 RJE Owner /usr/spool/rje +26|rje 5 -26|rje|*|8|five +26|rje|||five 9 2 -27 changes * 11 11 system change log / +27|changes 5 -27|changes|*|11|five +27|changes|||five 9 2 -28 dist sorry 9999 4 file distributions /v/adm/dist /v/bin/sh +28|dist 5 -28|dist|sorry|9999|five +28|dist|||five 9 2 -29 man * 99 995 On-line Manual Owner / +29|man 5 -29|man|*|99|five +29|man|||five 11 2 -30 phoneca * 991 991 phone call log [tom] /v/adm/log /v/bin/sh +30|phoneca 5 -30|phoneca|*|991|five +30|phoneca|||five diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.arith b/usr/src/test/util-tests/tests/awk/examples/out/t.arith index 364bffcc35..589b9b31d5 100644 --- a/usr/src/test/util-tests/tests/awk/examples/out/t.arith +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.arith @@ -1,9 +1,9 @@ 1 /dev/rrp3: 0 0 0 1 0 0 -1 -0 +1 0 2 0 0 0 2 0 0 -2 -0 +2 0 3 17379 34758 0 302029641 3 5793 0 3 -17379 diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.be b/usr/src/test/util-tests/tests/awk/examples/out/t.be index 1a5fd3a6af..7c0bfd2e17 100644 --- a/usr/src/test/util-tests/tests/awk/examples/out/t.be +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.be @@ -1,2 +1,2 @@ -data/test.data + 199 diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.crlf b/usr/src/test/util-tests/tests/awk/examples/out/t.crlf new file mode 100644 index 0000000000..be3dbf6155 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.crlf @@ -0,0 +1,199 @@ +/dev/rrp3: + +17379 mel +16693 bwk me +16116 ken him someone else +15713 srb +11895 lem +10409 scj +10252 rhm + 9853 shen + 9748 a68 + 9492 sif + 9190 pjw + 8912 nls + 8895 dmr + 8491 cda + 8372 bs + 8252 llc + 7450 mb + 7360 ava + 7273 jrv + 7080 bin + 7063 greg + 6567 dict + 6462 lck + 6291 rje + 6211 lwf + 5671 dave + 5373 jhc + 5220 agf + 5167 doug + 5007 valerie + 3963 jca + 3895 bbs + 3796 moh + 3481 xchar + 3200 tbl + 2845 s + 2774 tgs + 2641 met + 2566 jck + 2511 port + 2479 sue + 2127 root + 1989 bsb + 1989 jeg + 1933 eag + 1801 pdj + 1590 tpc + 1385 cvw + 1370 rwm + 1316 avg + 1205 eg + 1194 jam + 1153 dl + 1150 lgm + 1031 cmb + 1018 jwr + 950 gdb + 931 marc + 898 usg + 865 ggr + 822 daemon + 803 mihalis + 700 honey + 624 tad + 559 acs + 541 uucp + 523 raf + 495 adh + 456 kec + 414 craig + 386 donmac + 375 jj + 348 ravi + 344 drw + 327 stars + 288 mrg + 272 jcb + 263 ralph + 253 tom + 251 sjb + 248 haight + 224 sharon + 222 chuck + 213 dsj + 201 bill + 184 god + 176 sys + 166 meh + 163 jon + 144 dan + 143 fox + 123 dale + 116 kab + 95 buz + 80 asc + 79 jas + 79 trt + 64 wsb + 62 dwh + 56 ktf + 54 lr + 47 dlc + 45 dls + 45 jwf + 44 mash + 43 ars + 43 vgl + 37 jfo + 32 rab + 31 pd + 29 jns + 25 spm + 22 rob + 15 egb + 10 hm + 10 mhb + 6 aed + 6 cpb + 5 evp + 4 ber + 4 men + 4 mitch + 3 ast + 3 jfr + 3 lax + 3 nel + 2 blue + 2 jfk + 2 njas + 1 122sec + 1 ddwar + 1 gopi + 1 jk + 1 learn + 1 low + 1 nac + 1 sidor +1root:EMpNB8Zp56:0:0:Super-User,,,,,,,:/:/bin/sh +2roottcsh:*:0:0:Super-User running tcsh [cbm]:/:/bin/tcsh +3sysadm:*:0:0:System V Administration:/usr/admin:/bin/sh +4diag:*:0:996:Hardware Diagnostics:/usr/diags:/bin/csh +5daemon:*:1:1:daemons:/:/bin/sh +6bin:*:2:2:System Tools Owner:/bin:/dev/null +7nuucp:BJnuQbAo:6:10:UUCP.Admin:/usr/spool/uucppublic:/usr/lib/uucp/uucico +8uucp:*:3:5:UUCP.Admin:/usr/lib/uucp: +9sys:*:4:0:System Activity Owner:/usr/adm:/bin/sh +10adm:*:5:3:Accounting Files Owner:/usr/adm:/bin/sh +11lp:*:9:9:Print Spooler Owner:/var/spool/lp:/bin/sh +12auditor:*:11:0:Audit Activity Owner:/auditor:/bin/sh +13dbadmin:*:12:0:Security Database Owner:/dbadmin:/bin/sh +14bootes:dcon:50:1:Tom Killian (DO NOT REMOVE):/tmp: +15cdjuke:dcon:51:1:Tom Killian (DO NOT REMOVE):/tmp: +16rfindd:*:66:1:Rfind Daemon and Fsdump:/var/rfindd:/bin/sh +17EZsetup:*:992:998:System Setup:/var/sysadmdesktop/EZsetup:/bin/csh +18demos:*:993:997:Demonstration User:/usr/demos:/bin/csh +19tutor:*:994:997:Tutorial User:/usr/tutor:/bin/csh +20tour:*:995:997:IRIS Space Tour:/usr/people/tour:/bin/csh +21guest:nfP4/Wpvio/Rw:998:998:Guest Account:/usr/people/guest:/bin/csh +224Dgifts:0nWRTZsOMt.:999:998:4Dgifts Account:/usr/people/4Dgifts:/bin/csh +23nobody:*:60001:60001:SVR4 nobody uid:/dev/null:/dev/null +24noaccess:*:60002:60002:uid no access:/dev/null:/dev/null +25nobody:*:-2:-2:original nobody uid:/dev/null:/dev/null +26rje:*:8:8:RJE Owner:/usr/spool/rje: +27changes:*:11:11:system change log:/: +28dist:sorry:9999:4:file distributions:/v/adm/dist:/v/bin/sh +29man:*:99:995:On-line Manual Owner:/: +30phoneca:*:991:991:phone call log [tom]:/v/adm/log:/v/bin/sh +1r oot EMpNB8Zp56 0 0 Super-User,,,,,,, / /bin/sh +2r oottcsh * 0 0 Super-User running tcsh [cbm] / /bin/tcsh +3s ysadm * 0 0 System V Administration /usr/admin /bin/sh +4d iag * 0 996 Hardware Diagnostics /usr/diags /bin/csh +5d aemon * 1 1 daemons / /bin/sh +6b in * 2 2 System Tools Owner /bin /dev/null +7n uucp BJnuQbAo 6 10 UUCP.Admin /usr/spool/uucppublic /usr/lib/uucp/uucico +8u ucp * 3 5 UUCP.Admin /usr/lib/uucp +9s ys * 4 0 System Activity Owner /usr/adm /bin/sh +10 adm * 5 3 Accounting Files Owner /usr/adm /bin/sh +11 lp * 9 9 Print Spooler Owner /var/spool/lp /bin/sh +12 auditor * 11 0 Audit Activity Owner /auditor /bin/sh +13 dbadmin * 12 0 Security Database Owner /dbadmin /bin/sh +14 bootes dcon 50 1 Tom Killian (DO NOT REMOVE) /tmp +15 cdjuke dcon 51 1 Tom Killian (DO NOT REMOVE) /tmp +16 rfindd * 66 1 Rfind Daemon and Fsdump /var/rfindd /bin/sh +17 EZsetup * 992 998 System Setup /var/sysadmdesktop/EZsetup /bin/csh +18 demos * 993 997 Demonstration User /usr/demos /bin/csh +19 tutor * 994 997 Tutorial User /usr/tutor /bin/csh +20 tour * 995 997 IRIS Space Tour /usr/people/tour /bin/csh +21 guest nfP4/Wpvio/Rw 998 998 Guest Account /usr/people/guest /bin/csh +22 4Dgifts 0nWRTZsOMt. 999 998 4Dgifts Account /usr/people/4Dgifts /bin/csh +23 nobody * 60001 60001 SVR4 nobody uid /dev/null /dev/null +24 noaccess * 60002 60002 uid no access /dev/null /dev/null +25 nobody * -2 -2 original nobody uid /dev/null /dev/null +26 rje * 8 8 RJE Owner /usr/spool/rje +27 changes * 11 11 system change log / +28 dist sorry 9999 4 file distributions /v/adm/dist /v/bin/sh +29 man * 99 995 On-line Manual Owner / +30 phoneca * 991 991 phone call log [tom] /v/adm/log /v/bin/sh diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.delete b/usr/src/test/util-tests/tests/awk/examples/out/t.delete0 index e69de29bb2..e69de29bb2 100644 --- a/usr/src/test/util-tests/tests/awk/examples/out/t.delete +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.delete0 diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.for3 b/usr/src/test/util-tests/tests/awk/examples/out/t.for3 new file mode 100644 index 0000000000..ade43787c8 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.for3 @@ -0,0 +1,1290 @@ +1 /dev/rrp3: +/dev/rrp3: +1 17379 +2 mel +17379 +mel +1 16693 +2 bwk +3 me +16693 +bwk +me +1 16116 +2 ken +3 him +4 someone +5 else +16116 +ken +him +someone +else +1 15713 +2 srb +15713 +srb +1 11895 +2 lem +11895 +lem +1 10409 +2 scj +10409 +scj +1 10252 +2 rhm +10252 +rhm +1 9853 +2 shen +9853 +shen +1 9748 +2 a68 +9748 +a68 +1 9492 +2 sif +9492 +sif +1 9190 +2 pjw +9190 +pjw +1 8912 +2 nls +8912 +nls +1 8895 +2 dmr +8895 +dmr +1 8491 +2 cda +8491 +cda +1 8372 +2 bs +8372 +bs +1 8252 +2 llc +8252 +llc +1 7450 +2 mb +7450 +mb +1 7360 +2 ava +7360 +ava +1 7273 +2 jrv +7273 +jrv +1 7080 +2 bin +7080 +bin +1 7063 +2 greg +7063 +greg +1 6567 +2 dict +6567 +dict +1 6462 +2 lck +6462 +lck +1 6291 +2 rje +6291 +rje +1 6211 +2 lwf +6211 +lwf +1 5671 +2 dave +5671 +dave +1 5373 +2 jhc +5373 +jhc +1 5220 +2 agf +5220 +agf +1 5167 +2 doug +5167 +doug +1 5007 +2 valerie +5007 +valerie +1 3963 +2 jca +3963 +jca +1 3895 +2 bbs +3895 +bbs +1 3796 +2 moh +3796 +moh +1 3481 +2 xchar +3481 +xchar +1 3200 +2 tbl +3200 +tbl +1 2845 +2 s +2845 +s +1 2774 +2 tgs +2774 +tgs +1 2641 +2 met +2641 +met +1 2566 +2 jck +2566 +jck +1 2511 +2 port +2511 +port +1 2479 +2 sue +2479 +sue +1 2127 +2 root +2127 +root +1 1989 +2 bsb +1989 +bsb +1 1989 +2 jeg +1989 +jeg +1 1933 +2 eag +1933 +eag +1 1801 +2 pdj +1801 +pdj +1 1590 +2 tpc +1590 +tpc +1 1385 +2 cvw +1385 +cvw +1 1370 +2 rwm +1370 +rwm +1 1316 +2 avg +1316 +avg +1 1205 +2 eg +1205 +eg +1 1194 +2 jam +1194 +jam +1 1153 +2 dl +1153 +dl +1 1150 +2 lgm +1150 +lgm +1 1031 +2 cmb +1031 +cmb +1 1018 +2 jwr +1018 +jwr +1 950 +2 gdb +950 +gdb +1 931 +2 marc +931 +marc +1 898 +2 usg +898 +usg +1 865 +2 ggr +865 +ggr +1 822 +2 daemon +822 +daemon +1 803 +2 mihalis +803 +mihalis +1 700 +2 honey +700 +honey +1 624 +2 tad +624 +tad +1 559 +2 acs +559 +acs +1 541 +2 uucp +541 +uucp +1 523 +2 raf +523 +raf +1 495 +2 adh +495 +adh +1 456 +2 kec +456 +kec +1 414 +2 craig +414 +craig +1 386 +2 donmac +386 +donmac +1 375 +2 jj +375 +jj +1 348 +2 ravi +348 +ravi +1 344 +2 drw +344 +drw +1 327 +2 stars +327 +stars +1 288 +2 mrg +288 +mrg +1 272 +2 jcb +272 +jcb +1 263 +2 ralph +263 +ralph +1 253 +2 tom +253 +tom +1 251 +2 sjb +251 +sjb +1 248 +2 haight +248 +haight +1 224 +2 sharon +224 +sharon +1 222 +2 chuck +222 +chuck +1 213 +2 dsj +213 +dsj +1 201 +2 bill +201 +bill +1 184 +2 god +184 +god +1 176 +2 sys +176 +sys +1 166 +2 meh +166 +meh +1 163 +2 jon +163 +jon +1 144 +2 dan +144 +dan +1 143 +2 fox +143 +fox +1 123 +2 dale +123 +dale +1 116 +2 kab +116 +kab +1 95 +2 buz +95 +buz +1 80 +2 asc +80 +asc +1 79 +2 jas +79 +jas +1 79 +2 trt +79 +trt +1 64 +2 wsb +64 +wsb +1 62 +2 dwh +62 +dwh +1 56 +2 ktf +56 +ktf +1 54 +2 lr +54 +lr +1 47 +2 dlc +47 +dlc +1 45 +2 dls +45 +dls +1 45 +2 jwf +45 +jwf +1 44 +2 mash +44 +mash +1 43 +2 ars +43 +ars +1 43 +2 vgl +43 +vgl +1 37 +2 jfo +37 +jfo +1 32 +2 rab +32 +rab +1 31 +2 pd +31 +pd +1 29 +2 jns +29 +jns +1 25 +2 spm +25 +spm +1 22 +2 rob +22 +rob +1 15 +2 egb +15 +egb +1 10 +2 hm +10 +hm +1 10 +2 mhb +10 +mhb +1 6 +2 aed +6 +aed +1 6 +2 cpb +6 +cpb +1 5 +2 evp +5 +evp +1 4 +2 ber +4 +ber +1 4 +2 men +4 +men +1 4 +2 mitch +4 +mitch +1 3 +2 ast +3 +ast +1 3 +2 jfr +3 +jfr +1 3 +2 lax +3 +lax +1 3 +2 nel +3 +nel +1 2 +2 blue +2 +blue +1 2 +2 jfk +2 +jfk +1 2 +2 njas +2 +njas +1 1 +2 122sec +1 +122sec +1 1 +2 ddwar +1 +ddwar +1 1 +2 gopi +1 +gopi +1 1 +2 jk +1 +jk +1 1 +2 learn +1 +learn +1 1 +2 low +1 +low +1 1 +2 nac +1 +nac +1 1 +2 sidor +1 +sidor +1 1root:EMpNB8Zp56:0:0:Super-User,,,,,,,:/:/bin/sh +1root:EMpNB8Zp56:0:0:Super-User,,,,,,,:/:/bin/sh +1 2roottcsh:*:0:0:Super-User +2 running +3 tcsh +4 [cbm]:/:/bin/tcsh +2roottcsh:*:0:0:Super-User +running +tcsh +[cbm]:/:/bin/tcsh +1 3sysadm:*:0:0:System +2 V +3 Administration:/usr/admin:/bin/sh +3sysadm:*:0:0:System +V +Administration:/usr/admin:/bin/sh +1 4diag:*:0:996:Hardware +2 Diagnostics:/usr/diags:/bin/csh +4diag:*:0:996:Hardware +Diagnostics:/usr/diags:/bin/csh +1 5daemon:*:1:1:daemons:/:/bin/sh +5daemon:*:1:1:daemons:/:/bin/sh +1 6bin:*:2:2:System +2 Tools +3 Owner:/bin:/dev/null +6bin:*:2:2:System +Tools +Owner:/bin:/dev/null +1 7nuucp:BJnuQbAo:6:10:UUCP.Admin:/usr/spool/uucppublic:/usr/lib/uucp/uucico +7nuucp:BJnuQbAo:6:10:UUCP.Admin:/usr/spool/uucppublic:/usr/lib/uucp/uucico +1 8uucp:*:3:5:UUCP.Admin:/usr/lib/uucp: +8uucp:*:3:5:UUCP.Admin:/usr/lib/uucp: +1 9sys:*:4:0:System +2 Activity +3 Owner:/usr/adm:/bin/sh +9sys:*:4:0:System +Activity +Owner:/usr/adm:/bin/sh +1 10adm:*:5:3:Accounting +2 Files +3 Owner:/usr/adm:/bin/sh +10adm:*:5:3:Accounting +Files +Owner:/usr/adm:/bin/sh +1 11lp:*:9:9:Print +2 Spooler +3 Owner:/var/spool/lp:/bin/sh +11lp:*:9:9:Print +Spooler +Owner:/var/spool/lp:/bin/sh +1 12auditor:*:11:0:Audit +2 Activity +3 Owner:/auditor:/bin/sh +12auditor:*:11:0:Audit +Activity +Owner:/auditor:/bin/sh +1 13dbadmin:*:12:0:Security +2 Database +3 Owner:/dbadmin:/bin/sh +13dbadmin:*:12:0:Security +Database +Owner:/dbadmin:/bin/sh +1 14bootes:dcon:50:1:Tom +2 Killian +3 (DO +4 NOT +5 REMOVE):/tmp: +14bootes:dcon:50:1:Tom +Killian +(DO +NOT +REMOVE):/tmp: +1 15cdjuke:dcon:51:1:Tom +2 Killian +3 (DO +4 NOT +5 REMOVE):/tmp: +15cdjuke:dcon:51:1:Tom +Killian +(DO +NOT +REMOVE):/tmp: +1 16rfindd:*:66:1:Rfind +2 Daemon +3 and +4 Fsdump:/var/rfindd:/bin/sh +16rfindd:*:66:1:Rfind +Daemon +and +Fsdump:/var/rfindd:/bin/sh +1 17EZsetup:*:992:998:System +2 Setup:/var/sysadmdesktop/EZsetup:/bin/csh +17EZsetup:*:992:998:System +Setup:/var/sysadmdesktop/EZsetup:/bin/csh +1 18demos:*:993:997:Demonstration +2 User:/usr/demos:/bin/csh +18demos:*:993:997:Demonstration +User:/usr/demos:/bin/csh +1 19tutor:*:994:997:Tutorial +2 User:/usr/tutor:/bin/csh +19tutor:*:994:997:Tutorial +User:/usr/tutor:/bin/csh +1 20tour:*:995:997:IRIS +2 Space +3 Tour:/usr/people/tour:/bin/csh +20tour:*:995:997:IRIS +Space +Tour:/usr/people/tour:/bin/csh +1 21guest:nfP4/Wpvio/Rw:998:998:Guest +2 Account:/usr/people/guest:/bin/csh +21guest:nfP4/Wpvio/Rw:998:998:Guest +Account:/usr/people/guest:/bin/csh +1 224Dgifts:0nWRTZsOMt.:999:998:4Dgifts +2 Account:/usr/people/4Dgifts:/bin/csh +224Dgifts:0nWRTZsOMt.:999:998:4Dgifts +Account:/usr/people/4Dgifts:/bin/csh +1 23nobody:*:60001:60001:SVR4 +2 nobody +3 uid:/dev/null:/dev/null +23nobody:*:60001:60001:SVR4 +nobody +uid:/dev/null:/dev/null +1 24noaccess:*:60002:60002:uid +2 no +3 access:/dev/null:/dev/null +24noaccess:*:60002:60002:uid +no +access:/dev/null:/dev/null +1 25nobody:*:-2:-2:original +2 nobody +3 uid:/dev/null:/dev/null +25nobody:*:-2:-2:original +nobody +uid:/dev/null:/dev/null +1 26rje:*:8:8:RJE +2 Owner:/usr/spool/rje: +26rje:*:8:8:RJE +Owner:/usr/spool/rje: +1 27changes:*:11:11:system +2 change +3 log:/: +27changes:*:11:11:system +change +log:/: +1 28dist:sorry:9999:4:file +2 distributions:/v/adm/dist:/v/bin/sh +28dist:sorry:9999:4:file +distributions:/v/adm/dist:/v/bin/sh +1 29man:*:99:995:On-line +2 Manual +3 Owner:/: +29man:*:99:995:On-line +Manual +Owner:/: +1 30phoneca:*:991:991:phone +2 call +3 log +4 [tom]:/v/adm/log:/v/bin/sh +30phoneca:*:991:991:phone +call +log +[tom]:/v/adm/log:/v/bin/sh +1 1r +2 oot +3 EMpNB8Zp56 +4 0 +5 0 +6 Super-User,,,,,,, +7 / +8 /bin/sh +1r +oot +EMpNB8Zp56 +0 +0 +Super-User,,,,,,, +/ +/bin/sh +1 2r +2 oottcsh +3 * +4 0 +5 0 +6 Super-User +7 running +8 tcsh +9 [cbm] +10 / +11 /bin/tcsh +2r +oottcsh +* +0 +0 +Super-User +running +tcsh +[cbm] +/ +/bin/tcsh +1 3s +2 ysadm +3 * +4 0 +5 0 +6 System +7 V +8 Administration +9 /usr/admin +10 /bin/sh +3s +ysadm +* +0 +0 +System +V +Administration +/usr/admin +/bin/sh +1 4d +2 iag +3 * +4 0 +5 996 +6 Hardware +7 Diagnostics +8 /usr/diags +9 /bin/csh +4d +iag +* +0 +996 +Hardware +Diagnostics +/usr/diags +/bin/csh +1 5d +2 aemon +3 * +4 1 +5 1 +6 daemons +7 / +8 /bin/sh +5d +aemon +* +1 +1 +daemons +/ +/bin/sh +1 6b +2 in +3 * +4 2 +5 2 +6 System +7 Tools +8 Owner +9 /bin +10 /dev/null +6b +in +* +2 +2 +System +Tools +Owner +/bin +/dev/null +1 7n +2 uucp +3 BJnuQbAo +4 6 +5 10 +6 UUCP.Admin +7 /usr/spool/uucppublic +8 /usr/lib/uucp/uucico +7n +uucp +BJnuQbAo +6 +10 +UUCP.Admin +/usr/spool/uucppublic +/usr/lib/uucp/uucico +1 8u +2 ucp +3 * +4 3 +5 5 +6 UUCP.Admin +7 /usr/lib/uucp +8u +ucp +* +3 +5 +UUCP.Admin +/usr/lib/uucp +1 9s +2 ys +3 * +4 4 +5 0 +6 System +7 Activity +8 Owner +9 /usr/adm +10 /bin/sh +9s +ys +* +4 +0 +System +Activity +Owner +/usr/adm +/bin/sh +1 10 +2 adm +3 * +4 5 +5 3 +6 Accounting +7 Files +8 Owner +9 /usr/adm +10 /bin/sh +10 +adm +* +5 +3 +Accounting +Files +Owner +/usr/adm +/bin/sh +1 11 +2 lp +3 * +4 9 +5 9 +6 Print +7 Spooler +8 Owner +9 /var/spool/lp +10 /bin/sh +11 +lp +* +9 +9 +Print +Spooler +Owner +/var/spool/lp +/bin/sh +1 12 +2 auditor +3 * +4 11 +5 0 +6 Audit +7 Activity +8 Owner +9 /auditor +10 /bin/sh +12 +auditor +* +11 +0 +Audit +Activity +Owner +/auditor +/bin/sh +1 13 +2 dbadmin +3 * +4 12 +5 0 +6 Security +7 Database +8 Owner +9 /dbadmin +10 /bin/sh +13 +dbadmin +* +12 +0 +Security +Database +Owner +/dbadmin +/bin/sh +1 14 +2 bootes +3 dcon +4 50 +5 1 +6 Tom +7 Killian +8 (DO +9 NOT +10 REMOVE) +11 /tmp +14 +bootes +dcon +50 +1 +Tom +Killian +(DO +NOT +REMOVE) +/tmp +1 15 +2 cdjuke +3 dcon +4 51 +5 1 +6 Tom +7 Killian +8 (DO +9 NOT +10 REMOVE) +11 /tmp +15 +cdjuke +dcon +51 +1 +Tom +Killian +(DO +NOT +REMOVE) +/tmp +1 16 +2 rfindd +3 * +4 66 +5 1 +6 Rfind +7 Daemon +8 and +9 Fsdump +10 /var/rfindd +11 /bin/sh +16 +rfindd +* +66 +1 +Rfind +Daemon +and +Fsdump +/var/rfindd +/bin/sh +1 17 +2 EZsetup +3 * +4 992 +5 998 +6 System +7 Setup +8 /var/sysadmdesktop/EZsetup +9 /bin/csh +17 +EZsetup +* +992 +998 +System +Setup +/var/sysadmdesktop/EZsetup +/bin/csh +1 18 +2 demos +3 * +4 993 +5 997 +6 Demonstration +7 User +8 /usr/demos +9 /bin/csh +18 +demos +* +993 +997 +Demonstration +User +/usr/demos +/bin/csh +1 19 +2 tutor +3 * +4 994 +5 997 +6 Tutorial +7 User +8 /usr/tutor +9 /bin/csh +19 +tutor +* +994 +997 +Tutorial +User +/usr/tutor +/bin/csh +1 20 +2 tour +3 * +4 995 +5 997 +6 IRIS +7 Space +8 Tour +9 /usr/people/tour +10 /bin/csh +20 +tour +* +995 +997 +IRIS +Space +Tour +/usr/people/tour +/bin/csh +1 21 +2 guest +3 nfP4/Wpvio/Rw +4 998 +5 998 +6 Guest +7 Account +8 /usr/people/guest +9 /bin/csh +21 +guest +nfP4/Wpvio/Rw +998 +998 +Guest +Account +/usr/people/guest +/bin/csh +1 22 +2 4Dgifts +3 0nWRTZsOMt. +4 999 +5 998 +6 4Dgifts +7 Account +8 /usr/people/4Dgifts +9 /bin/csh +22 +4Dgifts +0nWRTZsOMt. +999 +998 +4Dgifts +Account +/usr/people/4Dgifts +/bin/csh +1 23 +2 nobody +3 * +4 60001 +5 60001 +6 SVR4 +7 nobody +8 uid +9 /dev/null +10 /dev/null +23 +nobody +* +60001 +60001 +SVR4 +nobody +uid +/dev/null +/dev/null +1 24 +2 noaccess +3 * +4 60002 +5 60002 +6 uid +7 no +8 access +9 /dev/null +10 /dev/null +24 +noaccess +* +60002 +60002 +uid +no +access +/dev/null +/dev/null +1 25 +2 nobody +3 * +4 -2 +5 -2 +6 original +7 nobody +8 uid +9 /dev/null +10 /dev/null +25 +nobody +* +-2 +-2 +original +nobody +uid +/dev/null +/dev/null +1 26 +2 rje +3 * +4 8 +5 8 +6 RJE +7 Owner +8 /usr/spool/rje +26 +rje +* +8 +8 +RJE +Owner +/usr/spool/rje +1 27 +2 changes +3 * +4 11 +5 11 +6 system +7 change +8 log +9 / +27 +changes +* +11 +11 +system +change +log +/ +1 28 +2 dist +3 sorry +4 9999 +5 4 +6 file +7 distributions +8 /v/adm/dist +9 /v/bin/sh +28 +dist +sorry +9999 +4 +file +distributions +/v/adm/dist +/v/bin/sh +1 29 +2 man +3 * +4 99 +5 995 +6 On-line +7 Manual +8 Owner +9 / +29 +man +* +99 +995 +On-line +Manual +Owner +/ +1 30 +2 phoneca +3 * +4 991 +5 991 +6 phone +7 call +8 log +9 [tom] +10 /v/adm/log +11 /v/bin/sh +30 +phoneca +* +991 +991 +phone +call +log +[tom] +/v/adm/log +/v/bin/sh diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.getline b/usr/src/test/util-tests/tests/awk/examples/out/t.getline1 index ad14b7c8ad..ad14b7c8ad 100644 --- a/usr/src/test/util-tests/tests/awk/examples/out/t.getline +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.getline1 diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.redir b/usr/src/test/util-tests/tests/awk/examples/out/t.redir1 index e69de29bb2..e69de29bb2 100644 --- a/usr/src/test/util-tests/tests/awk/examples/out/t.redir +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.redir1 diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.split b/usr/src/test/util-tests/tests/awk/examples/out/t.split1 index 00049a59ee..00049a59ee 100644 --- a/usr/src/test/util-tests/tests/awk/examples/out/t.split +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.split1 diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.split2a b/usr/src/test/util-tests/tests/awk/examples/out/t.split2a new file mode 100644 index 0000000000..e71254b5f5 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.split2a @@ -0,0 +1 @@ +2 a b diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.split8 b/usr/src/test/util-tests/tests/awk/examples/out/t.split8 new file mode 100644 index 0000000000..a687a17a6f --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.split8 @@ -0,0 +1,725 @@ +1 +0 +2 +3 +5 +2 +2 +2 +2 +3 +split botch at 10 3 2 +different element at 1 9853 +different element at 2 9853 shen +different element at 3 shen +3 +split botch at 11 3 2 +different element at 1 9748 +different element at 2 9748 a68 +different element at 3 a68 +3 +split botch at 12 3 2 +different element at 1 9492 +different element at 2 9492 sif +different element at 3 sif +3 +split botch at 13 3 2 +different element at 1 9190 +different element at 2 9190 pjw +different element at 3 pjw +3 +split botch at 14 3 2 +different element at 1 8912 +different element at 2 8912 nls +different element at 3 nls +3 +split botch at 15 3 2 +different element at 1 8895 +different element at 2 8895 dmr +different element at 3 dmr +3 +split botch at 16 3 2 +different element at 1 8491 +different element at 2 8491 cda +different element at 3 cda +3 +split botch at 17 3 2 +different element at 1 8372 +different element at 2 8372 bs +different element at 3 bs +3 +split botch at 18 3 2 +different element at 1 8252 +different element at 2 8252 llc +different element at 3 llc +3 +split botch at 19 3 2 +different element at 1 7450 +different element at 2 7450 mb +different element at 3 mb +3 +split botch at 20 3 2 +different element at 1 7360 +different element at 2 7360 ava +different element at 3 ava +3 +split botch at 21 3 2 +different element at 1 7273 +different element at 2 7273 jrv +different element at 3 jrv +3 +split botch at 22 3 2 +different element at 1 7080 +different element at 2 7080 bin +different element at 3 bin +3 +split botch at 23 3 2 +different element at 1 7063 +different element at 2 7063 greg +different element at 3 greg +3 +split botch at 24 3 2 +different element at 1 6567 +different element at 2 6567 dict +different element at 3 dict +3 +split botch at 25 3 2 +different element at 1 6462 +different element at 2 6462 lck +different element at 3 lck +3 +split botch at 26 3 2 +different element at 1 6291 +different element at 2 6291 rje +different element at 3 rje +3 +split botch at 27 3 2 +different element at 1 6211 +different element at 2 6211 lwf +different element at 3 lwf +3 +split botch at 28 3 2 +different element at 1 5671 +different element at 2 5671 dave +different element at 3 dave +3 +split botch at 29 3 2 +different element at 1 5373 +different element at 2 5373 jhc +different element at 3 jhc +3 +split botch at 30 3 2 +different element at 1 5220 +different element at 2 5220 agf +different element at 3 agf +3 +split botch at 31 3 2 +different element at 1 5167 +different element at 2 5167 doug +different element at 3 doug +3 +split botch at 32 3 2 +different element at 1 5007 +different element at 2 5007 valerie +different element at 3 valerie +3 +split botch at 33 3 2 +different element at 1 3963 +different element at 2 3963 jca +different element at 3 jca +3 +split botch at 34 3 2 +different element at 1 3895 +different element at 2 3895 bbs +different element at 3 bbs +3 +split botch at 35 3 2 +different element at 1 3796 +different element at 2 3796 moh +different element at 3 moh +3 +split botch at 36 3 2 +different element at 1 3481 +different element at 2 3481 xchar +different element at 3 xchar +3 +split botch at 37 3 2 +different element at 1 3200 +different element at 2 3200 tbl +different element at 3 tbl +3 +split botch at 38 3 2 +different element at 1 2845 +different element at 2 2845 s +different element at 3 s +3 +split botch at 39 3 2 +different element at 1 2774 +different element at 2 2774 tgs +different element at 3 tgs +3 +split botch at 40 3 2 +different element at 1 2641 +different element at 2 2641 met +different element at 3 met +3 +split botch at 41 3 2 +different element at 1 2566 +different element at 2 2566 jck +different element at 3 jck +3 +split botch at 42 3 2 +different element at 1 2511 +different element at 2 2511 port +different element at 3 port +3 +split botch at 43 3 2 +different element at 1 2479 +different element at 2 2479 sue +different element at 3 sue +3 +split botch at 44 3 2 +different element at 1 2127 +different element at 2 2127 root +different element at 3 root +3 +split botch at 45 3 2 +different element at 1 1989 +different element at 2 1989 bsb +different element at 3 bsb +3 +split botch at 46 3 2 +different element at 1 1989 +different element at 2 1989 jeg +different element at 3 jeg +3 +split botch at 47 3 2 +different element at 1 1933 +different element at 2 1933 eag +different element at 3 eag +3 +split botch at 48 3 2 +different element at 1 1801 +different element at 2 1801 pdj +different element at 3 pdj +3 +split botch at 49 3 2 +different element at 1 1590 +different element at 2 1590 tpc +different element at 3 tpc +3 +split botch at 50 3 2 +different element at 1 1385 +different element at 2 1385 cvw +different element at 3 cvw +3 +split botch at 51 3 2 +different element at 1 1370 +different element at 2 1370 rwm +different element at 3 rwm +3 +split botch at 52 3 2 +different element at 1 1316 +different element at 2 1316 avg +different element at 3 avg +3 +split botch at 53 3 2 +different element at 1 1205 +different element at 2 1205 eg +different element at 3 eg +3 +split botch at 54 3 2 +different element at 1 1194 +different element at 2 1194 jam +different element at 3 jam +3 +split botch at 55 3 2 +different element at 1 1153 +different element at 2 1153 dl +different element at 3 dl +3 +split botch at 56 3 2 +different element at 1 1150 +different element at 2 1150 lgm +different element at 3 lgm +3 +split botch at 57 3 2 +different element at 1 1031 +different element at 2 1031 cmb +different element at 3 cmb +3 +split botch at 58 3 2 +different element at 1 1018 +different element at 2 1018 jwr +different element at 3 jwr +3 +split botch at 59 3 2 +different element at 1 950 +different element at 2 950 gdb +different element at 3 gdb +3 +split botch at 60 3 2 +different element at 1 931 +different element at 2 931 marc +different element at 3 marc +3 +split botch at 61 3 2 +different element at 1 898 +different element at 2 898 usg +different element at 3 usg +3 +split botch at 62 3 2 +different element at 1 865 +different element at 2 865 ggr +different element at 3 ggr +3 +split botch at 63 3 2 +different element at 1 822 +different element at 2 822 daemon +different element at 3 daemon +3 +split botch at 64 3 2 +different element at 1 803 +different element at 2 803 mihalis +different element at 3 mihalis +3 +split botch at 65 3 2 +different element at 1 700 +different element at 2 700 honey +different element at 3 honey +3 +split botch at 66 3 2 +different element at 1 624 +different element at 2 624 tad +different element at 3 tad +3 +split botch at 67 3 2 +different element at 1 559 +different element at 2 559 acs +different element at 3 acs +3 +split botch at 68 3 2 +different element at 1 541 +different element at 2 541 uucp +different element at 3 uucp +3 +split botch at 69 3 2 +different element at 1 523 +different element at 2 523 raf +different element at 3 raf +3 +split botch at 70 3 2 +different element at 1 495 +different element at 2 495 adh +different element at 3 adh +3 +split botch at 71 3 2 +different element at 1 456 +different element at 2 456 kec +different element at 3 kec +3 +split botch at 72 3 2 +different element at 1 414 +different element at 2 414 craig +different element at 3 craig +3 +split botch at 73 3 2 +different element at 1 386 +different element at 2 386 donmac +different element at 3 donmac +3 +split botch at 74 3 2 +different element at 1 375 +different element at 2 375 jj +different element at 3 jj +3 +split botch at 75 3 2 +different element at 1 348 +different element at 2 348 ravi +different element at 3 ravi +3 +split botch at 76 3 2 +different element at 1 344 +different element at 2 344 drw +different element at 3 drw +3 +split botch at 77 3 2 +different element at 1 327 +different element at 2 327 stars +different element at 3 stars +3 +split botch at 78 3 2 +different element at 1 288 +different element at 2 288 mrg +different element at 3 mrg +3 +split botch at 79 3 2 +different element at 1 272 +different element at 2 272 jcb +different element at 3 jcb +3 +split botch at 80 3 2 +different element at 1 263 +different element at 2 263 ralph +different element at 3 ralph +3 +split botch at 81 3 2 +different element at 1 253 +different element at 2 253 tom +different element at 3 tom +3 +split botch at 82 3 2 +different element at 1 251 +different element at 2 251 sjb +different element at 3 sjb +3 +split botch at 83 3 2 +different element at 1 248 +different element at 2 248 haight +different element at 3 haight +3 +split botch at 84 3 2 +different element at 1 224 +different element at 2 224 sharon +different element at 3 sharon +3 +split botch at 85 3 2 +different element at 1 222 +different element at 2 222 chuck +different element at 3 chuck +3 +split botch at 86 3 2 +different element at 1 213 +different element at 2 213 dsj +different element at 3 dsj +3 +split botch at 87 3 2 +different element at 1 201 +different element at 2 201 bill +different element at 3 bill +3 +split botch at 88 3 2 +different element at 1 184 +different element at 2 184 god +different element at 3 god +3 +split botch at 89 3 2 +different element at 1 176 +different element at 2 176 sys +different element at 3 sys +3 +split botch at 90 3 2 +different element at 1 166 +different element at 2 166 meh +different element at 3 meh +3 +split botch at 91 3 2 +different element at 1 163 +different element at 2 163 jon +different element at 3 jon +3 +split botch at 92 3 2 +different element at 1 144 +different element at 2 144 dan +different element at 3 dan +3 +split botch at 93 3 2 +different element at 1 143 +different element at 2 143 fox +different element at 3 fox +3 +split botch at 94 3 2 +different element at 1 123 +different element at 2 123 dale +different element at 3 dale +3 +split botch at 95 3 2 +different element at 1 116 +different element at 2 116 kab +different element at 3 kab +3 +split botch at 96 3 2 +different element at 1 95 +different element at 2 95 buz +different element at 3 buz +3 +split botch at 97 3 2 +different element at 1 80 +different element at 2 80 asc +different element at 3 asc +3 +split botch at 98 3 2 +different element at 1 79 +different element at 2 79 jas +different element at 3 jas +3 +split botch at 99 3 2 +different element at 1 79 +different element at 2 79 trt +different element at 3 trt +3 +split botch at 100 3 2 +different element at 1 64 +different element at 2 64 wsb +different element at 3 wsb +3 +split botch at 101 3 2 +different element at 1 62 +different element at 2 62 dwh +different element at 3 dwh +3 +split botch at 102 3 2 +different element at 1 56 +different element at 2 56 ktf +different element at 3 ktf +3 +split botch at 103 3 2 +different element at 1 54 +different element at 2 54 lr +different element at 3 lr +3 +split botch at 104 3 2 +different element at 1 47 +different element at 2 47 dlc +different element at 3 dlc +3 +split botch at 105 3 2 +different element at 1 45 +different element at 2 45 dls +different element at 3 dls +3 +split botch at 106 3 2 +different element at 1 45 +different element at 2 45 jwf +different element at 3 jwf +3 +split botch at 107 3 2 +different element at 1 44 +different element at 2 44 mash +different element at 3 mash +3 +split botch at 108 3 2 +different element at 1 43 +different element at 2 43 ars +different element at 3 ars +3 +split botch at 109 3 2 +different element at 1 43 +different element at 2 43 vgl +different element at 3 vgl +3 +split botch at 110 3 2 +different element at 1 37 +different element at 2 37 jfo +different element at 3 jfo +3 +split botch at 111 3 2 +different element at 1 32 +different element at 2 32 rab +different element at 3 rab +3 +split botch at 112 3 2 +different element at 1 31 +different element at 2 31 pd +different element at 3 pd +3 +split botch at 113 3 2 +different element at 1 29 +different element at 2 29 jns +different element at 3 jns +3 +split botch at 114 3 2 +different element at 1 25 +different element at 2 25 spm +different element at 3 spm +3 +split botch at 115 3 2 +different element at 1 22 +different element at 2 22 rob +different element at 3 rob +3 +split botch at 116 3 2 +different element at 1 15 +different element at 2 15 egb +different element at 3 egb +3 +split botch at 117 3 2 +different element at 1 10 +different element at 2 10 hm +different element at 3 hm +3 +split botch at 118 3 2 +different element at 1 10 +different element at 2 10 mhb +different element at 3 mhb +3 +split botch at 119 3 2 +different element at 1 6 +different element at 2 6 aed +different element at 3 aed +3 +split botch at 120 3 2 +different element at 1 6 +different element at 2 6 cpb +different element at 3 cpb +3 +split botch at 121 3 2 +different element at 1 5 +different element at 2 5 evp +different element at 3 evp +3 +split botch at 122 3 2 +different element at 1 4 +different element at 2 4 ber +different element at 3 ber +3 +split botch at 123 3 2 +different element at 1 4 +different element at 2 4 men +different element at 3 men +3 +split botch at 124 3 2 +different element at 1 4 +different element at 2 4 mitch +different element at 3 mitch +3 +split botch at 125 3 2 +different element at 1 3 +different element at 2 3 ast +different element at 3 ast +3 +split botch at 126 3 2 +different element at 1 3 +different element at 2 3 jfr +different element at 3 jfr +3 +split botch at 127 3 2 +different element at 1 3 +different element at 2 3 lax +different element at 3 lax +3 +split botch at 128 3 2 +different element at 1 3 +different element at 2 3 nel +different element at 3 nel +3 +split botch at 129 3 2 +different element at 1 2 +different element at 2 2 blue +different element at 3 blue +3 +split botch at 130 3 2 +different element at 1 2 +different element at 2 2 jfk +different element at 3 jfk +3 +split botch at 131 3 2 +different element at 1 2 +different element at 2 2 njas +different element at 3 njas +3 +split botch at 132 3 2 +different element at 1 1 +different element at 2 1 122sec +different element at 3 122sec +3 +split botch at 133 3 2 +different element at 1 1 +different element at 2 1 ddwar +different element at 3 ddwar +3 +split botch at 134 3 2 +different element at 1 1 +different element at 2 1 gopi +different element at 3 gopi +3 +split botch at 135 3 2 +different element at 1 1 +different element at 2 1 jk +different element at 3 jk +3 +split botch at 136 3 2 +different element at 1 1 +different element at 2 1 learn +different element at 3 learn +3 +split botch at 137 3 2 +different element at 1 1 +different element at 2 1 low +different element at 3 low +3 +split botch at 138 3 2 +different element at 1 1 +different element at 2 1 nac +different element at 3 nac +3 +split botch at 139 3 2 +different element at 1 1 +different element at 2 1 sidor +different element at 3 sidor +1 +4 +3 +2 +1 +3 +1 +1 +3 +3 +3 +3 +3 +5 +5 +4 +2 +2 +2 +3 +2 +2 +3 +3 +3 +2 +3 +2 +3 +4 +8 +11 +10 +9 +8 +10 +8 +8 +split botch at 177 8 7 +10 +10 +10 +10 +10 +12 +split botch at 183 12 11 +12 +split botch at 184 12 11 +11 +9 +9 +9 +10 +9 +9 +10 +10 +10 +9 +split botch at 195 9 8 +10 +split botch at 196 10 9 +9 +10 +split botch at 198 10 9 +11 diff --git a/usr/src/test/util-tests/tests/awk/examples/out/t.sub b/usr/src/test/util-tests/tests/awk/examples/out/t.sub0 index e334b996ae..e334b996ae 100644 --- a/usr/src/test/util-tests/tests/awk/examples/out/t.sub +++ b/usr/src/test/util-tests/tests/awk/examples/out/t.sub0 diff --git a/usr/src/test/util-tests/tests/awk/gnu/arynocls.awk b/usr/src/test/util-tests/tests/awk/gnu/arynocls.awk new file mode 100644 index 0000000000..041fe38577 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/arynocls.awk @@ -0,0 +1,102 @@ +#To: bug-gnu-utils@gnu.org +#From: Kristján Jónasson <kristjan@decode.is> +#Subject: Gawk bug +#Cc: arnold@gnu.org +# +#Hi! +# +#The following seems to be a bug in gawk. I have tried as I could to +#minimize the bug-causing program, so of course it does not seem to do +#anything useful in its present form. The error message received is: +# +#gawk: test.awk:15: fatal error: internal error +#Aborted +# +#Note that there is an attached file that the program reads, called "a". I +#played with the program a fair bit and my feeling is that the error is +#related with the delete statement, and not the reading of the file and the +#close statement. At one point I was able to remove the file reading and +#still obtain the error. If, for example, I remove the close statement and +#make two copies of the file instead, (reading one copy in sub1 and the +#other in sub2), the error still occurs. +# +#The operating system is Red Hat Linux, version 6.0, the gawk is version +#3.0.4, and the gawk was obtained from an rpm file gawk-3.0.4-1.i386.rpm. +# +#The program is: +# + +# Wed Mar 8 13:41:34 IST 2000 +# ADR: modified to use INPUT, so can set it from command line. +# When run, no output is produced, but it shouldn't core +# dump, either. +# +# The program bug is to not close the file in sub2. + +function sub1(x) { +# while (getline < "a" == 1) i++ + while (getline < INPUT == 1) i++ +# close("a") + close(INPUT) +} + +function sub2(x) { + i=0 + delete y +# while (getline < "a" == 1) z[++i] = $1 + while (getline < INPUT == 1) z[++i] = $1 + for(i in z) y[i] = x[i] + z[i] +} + +function sub3(x, y, z) { + sub2(x) + for(i=1; i<=4; i++) z[i] = y[i] +} + +BEGIN { + # Changes for illumos: + # - Set INPUT + # - Print out z, so that we know we read the right data. + INPUT = "arynocls.data" + + sub1(x) + sub2(x) + sub3(x, y, z) + + for(i=1; i<=4; i++) print z[i] +} +# +#And the data file is: +# +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# 32.440 3.830 3.383700000000000 10.08 298 865 +# +# diff --git a/usr/src/test/util-tests/tests/awk/gnu/arynocls.data b/usr/src/test/util-tests/tests/awk/gnu/arynocls.data new file mode 100644 index 0000000000..8f4712c5c2 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/arynocls.data @@ -0,0 +1,30 @@ + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 + 32.440 3.830 3.383700000000000 10.08 298 865 diff --git a/usr/src/test/util-tests/tests/awk/gnu/arynocls.ok b/usr/src/test/util-tests/tests/awk/gnu/arynocls.ok new file mode 100644 index 0000000000..3d936e3279 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/arynocls.ok @@ -0,0 +1,4 @@ +32.44 +32.44 +32.44 +32.44 diff --git a/usr/src/test/util-tests/tests/awk/gnu/back89.awk b/usr/src/test/util-tests/tests/awk/gnu/back89.awk new file mode 100644 index 0000000000..0da3362576 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/back89.awk @@ -0,0 +1 @@ +/a\8b/ diff --git a/usr/src/test/util-tests/tests/awk/gnu/back89.in b/usr/src/test/util-tests/tests/awk/gnu/back89.in new file mode 100644 index 0000000000..b0a88f248e --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/back89.in @@ -0,0 +1,2 @@ +a8b +a\8b diff --git a/usr/src/test/util-tests/tests/awk/gnu/back89.ok b/usr/src/test/util-tests/tests/awk/gnu/back89.ok new file mode 100644 index 0000000000..e9ea4d5f00 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/back89.ok @@ -0,0 +1 @@ +a8b diff --git a/usr/src/test/util-tests/tests/awk/gnu/closebad.awk b/usr/src/test/util-tests/tests/awk/gnu/closebad.awk new file mode 100644 index 0000000000..83133ae86a --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/closebad.awk @@ -0,0 +1,7 @@ +BEGIN { + f = "/no/such/file/1" + print (getline junk < f) + print close(f) + f = "/no/such/file/2" + print close(f) +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/closebad.ok b/usr/src/test/util-tests/tests/awk/gnu/closebad.ok new file mode 100644 index 0000000000..64861d87da --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/closebad.ok @@ -0,0 +1,3 @@ +-1 +-1 +-1 diff --git a/usr/src/test/util-tests/tests/awk/gnu/clsflnam.awk b/usr/src/test/util-tests/tests/awk/gnu/clsflnam.awk new file mode 100644 index 0000000000..0ba601f04f --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/clsflnam.awk @@ -0,0 +1,12 @@ +#! /usr/bin/awk -f +BEGIN { + getline +# print ("FILENAME =", FILENAME) > "/dev/stderr" + #Rewind the file + if (close(FILENAME)) { + print "Error `" ERRNO "' closing input file" > "/dev/stderr"; + exit; + } +} +{ print "Analysing ", $0 } + diff --git a/usr/src/test/util-tests/tests/awk/gnu/clsflnam.in b/usr/src/test/util-tests/tests/awk/gnu/clsflnam.in new file mode 100644 index 0000000000..a92d664bc2 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/clsflnam.in @@ -0,0 +1,3 @@ +line 1 +line 2 +line 3 diff --git a/usr/src/test/util-tests/tests/awk/gnu/clsflnam.ok b/usr/src/test/util-tests/tests/awk/gnu/clsflnam.ok new file mode 100644 index 0000000000..cefd250f80 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/clsflnam.ok @@ -0,0 +1 @@ +Error `' closing input file diff --git a/usr/src/test/util-tests/tests/awk/gnu/concat3.awk b/usr/src/test/util-tests/tests/awk/gnu/concat3.awk new file mode 100644 index 0000000000..7edc086477 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/concat3.awk @@ -0,0 +1 @@ +BEGIN { d = a; a = a (b "c"); print a; print b } diff --git a/usr/src/test/util-tests/tests/awk/gnu/concat3.ok b/usr/src/test/util-tests/tests/awk/gnu/concat3.ok new file mode 100644 index 0000000000..880233128b --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/concat3.ok @@ -0,0 +1,2 @@ +c + diff --git a/usr/src/test/util-tests/tests/awk/gnu/convfmt.awk b/usr/src/test/util-tests/tests/awk/gnu/convfmt.awk new file mode 100644 index 0000000000..90fd204b2f --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/convfmt.awk @@ -0,0 +1,10 @@ +BEGIN { + CONVFMT = "%2.2f" + a = 123.456 + b = a "" # give `a' string value also + printf "a = %s\n", a + CONVFMT = "%.6g" + printf "a = %s\n", a + a += 0 # make `a' numeric only again + printf "a = %s\n", a # use `a' as string +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/convfmt.ok b/usr/src/test/util-tests/tests/awk/gnu/convfmt.ok new file mode 100644 index 0000000000..a7b66f7857 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/convfmt.ok @@ -0,0 +1,3 @@ +a = 123.46 +a = 123.456 +a = 123.456 diff --git a/usr/src/test/util-tests/tests/awk/gnu/datanonl.awk b/usr/src/test/util-tests/tests/awk/gnu/datanonl.awk new file mode 100644 index 0000000000..1d5825878b --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/datanonl.awk @@ -0,0 +1,3 @@ +# example program from alex@bofh.torun.pl +# BEGIN { IGNORECASE=1 } +/[[:alnum:]]+@([[:alnum:]]+\.)+[[:alnum:]]+[[:blank:]]+/ {print $0} diff --git a/usr/src/test/util-tests/tests/awk/gnu/datanonl.in b/usr/src/test/util-tests/tests/awk/gnu/datanonl.in new file mode 100644 index 0000000000..5340d7bab3 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/datanonl.in @@ -0,0 +1 @@ +bleble@foo1.bh.pl deny
\ No newline at end of file diff --git a/usr/src/test/util-tests/tests/awk/gnu/datanonl.ok b/usr/src/test/util-tests/tests/awk/gnu/datanonl.ok new file mode 100644 index 0000000000..7b0fcafcd3 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/datanonl.ok @@ -0,0 +1 @@ +bleble@foo1.bh.pl deny diff --git a/usr/src/test/util-tests/tests/awk/gnu/delarprm.awk b/usr/src/test/util-tests/tests/awk/gnu/delarprm.awk new file mode 100644 index 0000000000..d59de31f77 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/delarprm.awk @@ -0,0 +1,50 @@ +# From dragon!unagi.cis.upenn.edu!sjanet Tue Mar 25 17:12:20 1997 +# Return-Path: <dragon!unagi.cis.upenn.edu!sjanet> +# Received: by skeeve.atl.ga.us (/\==/\ Smail3.1.22.1 #22.1) +# id <m0w9eS4-000GWyC@skeeve.atl.ga.us>; Tue, 25 Mar 97 17:12 EST +# Received: by vecnet.com (DECUS UUCP /2.0/2.0/2.0/); +# Tue, 25 Mar 97 16:58:36 EDT +# Received: from gnu-life.ai.mit.edu by antaries.vec.net (MX V4.2 VAX) with SMTP; +# Tue, 25 Mar 1997 16:58:26 EST +# Received: from linc.cis.upenn.edu by gnu-life.ai.mit.edu (8.8.5/8.6.12GNU) with +# ESMTP id QAA24350 for <bug-gnu-utils@prep.ai.mit.edu>; Tue, 25 Mar +# 1997 16:56:59 -0500 (EST) +# Received: from unagi.cis.upenn.edu (UNAGI.CIS.UPENN.EDU [158.130.8.153]) by +# linc.cis.upenn.edu (8.8.5/8.8.5) with ESMTP id QAA09424; Tue, 25 Mar +# 1997 16:56:54 -0500 (EST) +# Received: (from sjanet@localhost) by unagi.cis.upenn.edu (8.8.5/8.8.5) id +# QAA03969; Tue, 25 Mar 1997 16:56:50 -0500 (EST) +# Date: Tue, 25 Mar 1997 16:56:50 -0500 (EST) +# From: Stan Janet <sjanet@unagi.cis.upenn.edu> +# Message-ID: <199703252156.QAA03969@unagi.cis.upenn.edu> +# To: bug-gnu-utils@prep.ai.mit.edu +# CC: arnold@gnu.ai.mit.edu +# Subject: GNU awk 3.0.2 bug: fatal error deleting local array inside function +# Status: ORf +# +# Version: GNU Awk 3.0.2 +# Platforms: SunOS 4.1.1 (compiled with Sun cc) +# IRIX 5.3 (compiled with SGI cc) +# Problem: Deleting local array inside function causes fatal internal error (and +# core dump. The error does not occur when the variable "x", unused in +# the example, is removed or when the function is declared foo(x,p). +# When the function is declared foo(p,x), adding a dummy line that uses +# "x", e.g. "x=1" does not prevent the error. If "p" is not deleted, +# there is no error. If "p[1]" is used to delete the lone element, there +# is no error. +# +# ==== The program x.gawk ==== + +function foo(p,x) { + p[1]="bar" + delete p + return 0 +} + +BEGIN { + foo() +} + +# ==== The output for "gawk -f x.gawk" (SunOS) ==== +# +# gawk: x.gawk:4: fatal error: internal error diff --git a/usr/src/test/util-tests/tests/awk/gnu/delarprm.ok b/usr/src/test/util-tests/tests/awk/gnu/delarprm.ok new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/delarprm.ok diff --git a/usr/src/test/util-tests/tests/awk/gnu/fflush.ok b/usr/src/test/util-tests/tests/awk/gnu/fflush.ok new file mode 100644 index 0000000000..1c0450a26b --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/fflush.ok @@ -0,0 +1,15 @@ +1st +2nd +1st +2nd +1st +1st +2nd +1st +2nd +1st +2nd +1st +2nd +1st +2nd diff --git a/usr/src/test/util-tests/tests/awk/gnu/fflush.sh b/usr/src/test/util-tests/tests/awk/gnu/fflush.sh new file mode 100755 index 0000000000..8b03a40991 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/fflush.sh @@ -0,0 +1,25 @@ +#! /bin/sh + +if [ -z "$AWK" ]; then + printf '$AWK must be set\n' >&2 + exit 1 +fi + +$AWK 'BEGIN{print "1st";fflush("/dev/stdout");print "2nd"|"cat"}' + +$AWK 'BEGIN{print "1st";fflush("/dev/stdout");print "2nd"|"cat"}'|cat + +# gawk and nawk differ here: nawk will close stdout, and future writes (by nawk +# or by the cat child) will fail. gawk's child will print "2nd" here, and also +# allow other print statements to succeed. +$AWK 'BEGIN{print "1st";fflush("/dev/stdout");close("/dev/stdout");print "2nd"|"cat"}'|cat + +$AWK 'BEGIN{print "1st";fflush("/dev/stdout");print "2nd"|"cat";close("cat")}'|cat + +$AWK 'BEGIN{print "1st";fflush("/dev/stdout");print "2nd"|"cat";close("cat")}'|cat + +$AWK 'BEGIN{print "1st";fflush("/dev/stdout");print "2nd"|"cat";close("cat")}'|cat + +$AWK 'BEGIN{print "1st";fflush("/dev/stdout");print "2nd"|"sort"}'|cat + +$AWK 'BEGIN{print "1st";fflush("/dev/stdout");print "2nd"|"sort";close("sort")}'|cat diff --git a/usr/src/test/util-tests/tests/awk/gnu/fordel.awk b/usr/src/test/util-tests/tests/awk/gnu/fordel.awk new file mode 100644 index 0000000000..58ede20fbd --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/fordel.awk @@ -0,0 +1,65 @@ +#Date: Mon, 7 Jun 2004 10:40:28 -0500 +#From: mary1john8@earthlink.net +#To: arnold@skeeve.com +#Subject: gawk internal errors +#Message-ID: <20040607154028.GA2457@apollo> +# +#Hello, +# +# gawk-3.1.3i internal errors: +# +#[1] +# +#$> ./gawk 'BEGIN { for (i in a) delete a; }' +BEGIN { for (i in a) delete a; } +#gawk: fatal error: internal error +#Aborted +# +#------------------------------------------------------------------ +#--- awkgram.y.orig 2004-06-07 09:42:14.000000000 -0500 +#+++ awkgram.y 2004-06-07 09:45:58.000000000 -0500 +#@@ -387,7 +387,7 @@ +# * Check that the body is a `delete a[i]' statement, +# * and that both the loop var and array names match. +# */ +#- if ($8 != NULL && $8->type == Node_K_delete) { +#+ if ($8 != NULL && $8->type == Node_K_delete && $8->rnode != NULL) { +# NODE *arr, *sub; +# +# assert($8->rnode->type == Node_expression_list); +#------------------------------------------------------------------ +# +# +#[2] +# +#$> ./gawk 'BEGIN { printf("%3$*10$.*1$s\n", 20, 10, "hello"); }' +#gawk: fatal error: internal error +#Aborted +# +#------------------------------------------------------------------ +#--- builtin.c.orig 2004-06-07 10:04:20.000000000 -0500 +#+++ builtin.c 2004-06-07 10:06:08.000000000 -0500 +#@@ -780,7 +780,10 @@ +# s1++; +# n0--; +# } +#- +#+ if (val >= num_args) { +#+ toofew = TRUE; +#+ break; +#+ } +# arg = the_args[val]; +# } else { +# parse_next_arg(); +#------------------------------------------------------------------ +# +# +# Finally, a test for the rewritten get_src_buf(): +# +#$> AWKBUFSIZE=2 make check +# +#I get 3 failed tests. Not sure this is of any interest. +# +# +#Thanks, +#John diff --git a/usr/src/test/util-tests/tests/awk/gnu/fordel.ok b/usr/src/test/util-tests/tests/awk/gnu/fordel.ok new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/fordel.ok diff --git a/usr/src/test/util-tests/tests/awk/gnu/posix2008sub.awk b/usr/src/test/util-tests/tests/awk/gnu/gawksub.awk index 3c7c9b7721..3c7c9b7721 100644 --- a/usr/src/test/util-tests/tests/awk/gnu/posix2008sub.awk +++ b/usr/src/test/util-tests/tests/awk/gnu/gawksub.awk diff --git a/usr/src/test/util-tests/tests/awk/gnu/posix2008sub.ok b/usr/src/test/util-tests/tests/awk/gnu/gawksub.ok index 4d4406a4fc..d6b89ee494 100644 --- a/usr/src/test/util-tests/tests/awk/gnu/posix2008sub.ok +++ b/usr/src/test/util-tests/tests/awk/gnu/gawksub.ok @@ -1,2 +1,2 @@ orig = "here is some text", repl = "<FOO&BAR \q \ \\ \& \\& \\\&>" -result is "here is <FOOsomeBAR \q \ \ & \some \&> text" +result is "here is <FOOsomeBAR \q \ \\ & \some \&> text" diff --git a/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.awk b/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.awk new file mode 100644 index 0000000000..4bef854fbe --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.awk @@ -0,0 +1,97 @@ +# From jose@monkey.org Thu Jun 5 11:48:35 2003 +# Return-Path: <jose@monkey.org> +# Received: from localhost (skeeve [127.0.0.1]) +# by skeeve.com (8.12.5/8.12.5) with ESMTP id h558eVvA012655 +# for <arnold@localhost>; Thu, 5 Jun 2003 11:48:35 +0300 +# Received: from actcom.co.il [192.114.47.1] +# by localhost with POP3 (fetchmail-5.9.0) +# for arnold@localhost (single-drop); Thu, 05 Jun 2003 11:48:35 +0300 (IDT) +# Received: by actcom.co.il (mbox arobbins) +# (with Cubic Circle's cucipop (v1.31 1998/05/13) Thu Jun 5 11:47:59 2003) +# X-From_: jose@monkey.org Thu Jun 5 07:14:45 2003 +# Received: from smtp1.actcom.net.il by actcom.co.il with ESMTP +# (8.11.6/actcom-0.2) id h554EdY08108 for <arobbins@actcom.co.il>; +# Thu, 5 Jun 2003 07:14:41 +0300 (EET DST) +# (rfc931-sender: smtp.actcom.co.il [192.114.47.13]) +# Received: from f7.net (consort.superb.net [209.61.216.22]) +# by smtp1.actcom.net.il (8.12.8/8.12.8) with ESMTP id h554G3To008304 +# for <arobbins@actcom.co.il>; Thu, 5 Jun 2003 07:16:05 +0300 +# Received: from fencepost.gnu.org (fencepost.gnu.org [199.232.76.164]) +# by f7.net (8.11.7/8.11.6) with ESMTP id h554Ean08172 +# for <arnold@skeeve.com>; Thu, 5 Jun 2003 00:14:36 -0400 +# Received: from monty-python.gnu.org ([199.232.76.173]) +# by fencepost.gnu.org with esmtp (Exim 4.20) +# id 19Nm96-0001xE-1i +# for arnold@gnu.ai.mit.edu; Thu, 05 Jun 2003 00:14:36 -0400 +# Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.20) +# id 19Nm8x-0005ge-Dz +# for arnold@gnu.ai.mit.edu; Thu, 05 Jun 2003 00:14:28 -0400 +# Received: from naughty.monkey.org ([66.93.9.164]) +# by monty-python.gnu.org with esmtp (Exim 4.20) +# id 19Nm8w-0005VM-Ko +# for arnold@gnu.ai.mit.edu; Thu, 05 Jun 2003 00:14:26 -0400 +# Received: by naughty.monkey.org (Postfix, from userid 1203) +# id C15511BA97B; Thu, 5 Jun 2003 00:14:19 -0400 (EDT) +# Received: from localhost (localhost [127.0.0.1]) +# by naughty.monkey.org (Postfix) with ESMTP +# id BF9821BA969; Thu, 5 Jun 2003 00:14:19 -0400 (EDT) +# Date: Thu, 5 Jun 2003 00:14:19 -0400 (EDT) +# From: Jose Nazario <jose@monkey.org> +# To: bug-gnu-utils@prep.ai.mit.edu, arnold@gnu.ai.mit.edu, +# netbsd-bugs@netbsd.org +# Subject: bug in gawk/gsub() (not present in nawk) +# Message-ID: <Pine.BSO.4.51.0306050007160.31577@naughty.monkey.org> +# MIME-Version: 1.0 +# Content-Type: TEXT/PLAIN; charset=US-ASCII +# X-Spam-Status: No, hits=-1.2 required=5.0 +# tests=SPAM_PHRASE_00_01,USER_AGENT_PINE +# version=2.41 +# X-Spam-Level: +# X-SpamBouncer: 1.4 (10/07/01) +# X-SBClass: OK +# Status: R +# +# while playing with some tools in data massaging, i had to migrate from an +# openbsd/nawk system to a netbsd/gawk system. i found the folllowing +# behavior, which seems to be a bug. +# +# the following gsub() pattern has a strange effect under gawk which is not +# visible in nawk (at least as compiled on openbsd). the intention is to +# take a string like "This Is a Title: My Title?" and turn it into a +# normalized string: "ThisIsaTitleMyTitle". to do this, i wrote the +# following gross gsub line in an awk script: +# +# gsub(/[\ \"-\/\\:;\[\]\@\?\.\,\$]/, "", $2) +# print $2 +# +# in gawk, as found in netbsd-macppc/1.5.2, this will drop the first letter +# of every word. the resulting string will be "hissitleyitle", while in nawk +# as built on openbsd-3.3 this will get it correct. +# +# any insights? the inconsistency with this relatively naive pattern seems a +# bit odd. (i would up installing nawk built from openbsd sources.) +# +# thanks. sorry i didn't send a better bug report, netbsd folks, i'm not +# much of a netbsd user, and i dont have send-pr set up. yes, this is a +# slightly older version of netbsd and gawk: +# +# $ uname -a +# NetBSD entropy 1.5.2 NetBSD 1.5.2 (GENERIC) #0: Sun Feb 10 02:00:04 EST +# 2002 jose@entropy:/usr/src/sys/arch/macppc/compile/GENERIC macppc +# $ awk --version +# GNU Awk 3.0.3 +# Copyright (C) 1989, 1991-1997 Free Software Foundation. +# +# +# +# thanks. +# +# ___________________________ +# jose nazario, ph.d. jose@monkey.org +# http://monkey.org/~jose/ +# +# +{ + gsub(/[\ \"-\/\\:;\[\]\@\?\.\,\$]/, "") + print +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.in b/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.in new file mode 100644 index 0000000000..5d1f1a9763 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.in @@ -0,0 +1 @@ +This Is a Title: My Title? diff --git a/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.ok b/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.ok new file mode 100644 index 0000000000..b038c8af4e --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/gsubtst5.ok @@ -0,0 +1 @@ +ThisIsaTitleMyTitle diff --git a/usr/src/test/util-tests/tests/awk/gnu/longwrds.awk b/usr/src/test/util-tests/tests/awk/gnu/longwrds.awk new file mode 100644 index 0000000000..77654bb0c4 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/longwrds.awk @@ -0,0 +1,27 @@ +# From Gawk Manual modified by bug fix and removal of punctuation + +# Invoker can customize sort command if necessary. +BEGIN { + if (!SORT) SORT = "LC_ALL=C sort" +} + +# Record every word which is used at least once +{ + for (i = 1; i <= NF; i++) { + tmp = tolower($i) + if (0 != (pos = match(tmp, /([[:lower:]]|-)+/))) + used[substr(tmp, pos, RLENGTH)] = 1 + } +} + +#Find a number of distinct words longer than 10 characters +END { + num_long_words = 0 + for (x in used) + if (length(x) > 10) { + ++num_long_words + print x | SORT + } + print(num_long_words, "long words") | SORT + close(SORT) +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/longwrds.in b/usr/src/test/util-tests/tests/awk/gnu/longwrds.in new file mode 100644 index 0000000000..09c39485c6 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/longwrds.in @@ -0,0 +1,200 @@ +.ds PX \s-1POSIX\s+1 +.ds UX \s-1UNIX\s+1 +.ds AN \s-1ANSI\s+1 +.TH GAWK 1 "May 28 1991" "Free Software Foundation" "Utility Commands" +.SH NAME +gawk \- pattern scanning and processing language +.SH SYNOPSIS +.B gawk +[ +.B \-W +.I gawk-options +] [ +.BI \-F\^ fs +] [ +.B \-v +.IR var = val +] +.B \-f +.I program-file +[ +.B \-\^\- +] file .\^.\^. +.br +.B gawk +[ +.B \-W +.I gawk-options +] [ +.BI \-F\^ fs +] [ +.B \-v +.IR var = val +] [ +.B \-\^\- +] +.I program-text +file .\^.\^. +.SH DESCRIPTION +.I Gawk +is the GNU Project's implementation of the AWK programming language. +It conforms to the definition of the language in +the \*(PX 1003.2 Command Language And Utilities Standard +(draft 11). +This version in turn is based on the description in +.IR "The AWK Programming Language" , +by Aho, Kernighan, and Weinberger, +with the additional features defined in the System V Release 4 version +of \*(UX +.IR awk . +.I Gawk +also provides some GNU-specific extensions. +.PP +The command line consists of options to +.I gawk +itself, the AWK program text (if not supplied via the +.B \-f +option), and values to be made +available in the +.B ARGC +and +.B ARGV +pre-defined AWK variables. +.SH OPTIONS +.PP +.I Gawk +accepts the following options, which should be available on any implementation +of the AWK language. +.TP +.BI \-F fs +Use +.I fs +for the input field separator (the value of the +.B FS +predefined +variable). +.TP +\fB\-v\fI var\fR\^=\^\fIval\fR +Assign the value +.IR val , +to the variable +.IR var , +before execution of the program begins. +Such variable values are available to the +.B BEGIN +block of an AWK program. +.TP +.BI \-f " program-file" +Read the AWK program source from the file +.IR program-file , +instead of from the first command line argument. +Multiple +.B \-f +options may be used. +.TP +.B \-\^\- +Signal the end of options. This is useful to allow further arguments to the +AWK program itself to start with a ``\-''. +This is mainly for consistency with the argument parsing convention used +by most other \*(PX programs. +.PP +Following the \*(PX standard, +.IR gawk -specific +options are supplied via arguments to the +.B \-W +option. Multiple +.B \-W +options may be supplied, or multiple arguments may be supplied together +if they are separated by commas, or enclosed in quotes and separated +by white space. +Case is ignored in arguments to the +.B \-W +option. +.PP +The +.B \-W +option accepts the following arguments: +.TP \w'\fBcopyright\fR'u+1n +.B compat +Run in +.I compatibility +mode. In compatibility mode, +.I gawk +behaves identically to \*(UX +.IR awk ; +none of the GNU-specific extensions are recognized. +.TP +.PD 0 +.B copyleft +.TP +.PD +.B copyright +Print the short version of the GNU copyright information message on +the error output. +.TP +.B lint +Provide warnings about constructs that are +dubious or non-portable to other AWK implementations. +.TP +.B posix +This turns on +.I compatibility +mode, with the following additional restrictions: +.RS +.TP \w'\(bu'u+1n +\(bu +.B \ex +escape sequences are not recognized. +.TP +\(bu +The synonym +.B func +for the keyword +.B function +is not recognized. +.TP +\(bu +The operators +.B ** +and +.B **= +cannot be used in place of +.B ^ +and +.BR ^= . +.RE +.TP +.B version +Print version information for this particular copy of +.I gawk +on the error output. +This is useful mainly for knowing if the current copy of +.I gawk +on your system +is up to date with respect to whatever the Free Software Foundation +is distributing. +.PP +Any other options are flagged as illegal, but are otherwise ignored. +.SH AWK PROGRAM EXECUTION +.PP +An AWK program consists of a sequence of pattern-action statements +and optional function definitions. +.RS +.PP +\fIpattern\fB { \fIaction statements\fB }\fR +.br +\fBfunction \fIname\fB(\fIparameter list\fB) { \fIstatements\fB }\fR +.RE +.PP +.I Gawk +first reads the program source from the +.IR program-file (s) +if specified, or from the first non-option argument on the command line. +The +.B \-f +option may be used multiple times on the command line. +.I Gawk +will read the program text as if all the +.IR program-file s +had been concatenated together. This is useful for building libraries +of AWK functions, without having to include them in each new AWK diff --git a/usr/src/test/util-tests/tests/awk/gnu/longwrds.ok b/usr/src/test/util-tests/tests/awk/gnu/longwrds.ok new file mode 100644 index 0000000000..01faa84717 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/longwrds.ok @@ -0,0 +1,21 @@ +20 long words +compatibility +concatenated +consistency +definitions +description +distributing +fistatements +gawk-options +gnu-specific +identically +implementation +implementations +information +non-portable +pattern-action +pre-defined +program-file +program-text +programming +restrictions diff --git a/usr/src/test/util-tests/tests/awk/gnu/ofmta.awk b/usr/src/test/util-tests/tests/awk/gnu/ofmta.awk new file mode 100644 index 0000000000..8f3bc6e84c --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/ofmta.awk @@ -0,0 +1,30 @@ +# Date: Thu, 14 Apr 2011 08:18:55 -0500 +# From: j.eh@mchsi.com +# To: arnold@skeeve.com +# Subject: CONVFMT test for the test suite +# Message-ID: <20110414131855.GA1801@apollo> +# +# Hi, +# +# Please consider adding this to the test suite. 3.1.8 segfaults +# with this. +# +# Thanks, +# +# John +# +# +BEGIN { + i=1.2345 + i=3+i + a[i]="hi" + OFMT="%.1f" + print i + for (x in a) print x, a[x] + print a[i] + print "--------" + CONVFMT=OFMT="%.3f" + print i + for (x in a) print x, a[x] + print a[i] +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/ofmta.ok b/usr/src/test/util-tests/tests/awk/gnu/ofmta.ok new file mode 100644 index 0000000000..f050dc0e1e --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/ofmta.ok @@ -0,0 +1,7 @@ +4.2 +4.2345 hi +hi +-------- +4.234 +4.2345 hi + diff --git a/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.awk b/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.awk new file mode 100644 index 0000000000..df4f9bb0bb --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.awk @@ -0,0 +1,126 @@ +# +# [USEMAP] +# +# Problem Report gnu/7821 +# +# awk in free(): warning: chunk is already free. +# +# Confidential +# no +# +# Severity +# serious +# +# Priority +# medium +# +# Responsible +# freebsd-bugs@freebsd.org +# +# State +# suspended +# +# Class +# sw-bug +# +# Submitter-Id +# current-users +# +# Arrival-Date +# Thu Sep 3 10:30:00 PDT 1998 +# +# Last-Modified +# Thu Sep 17 02:04:26 PDT 1998 +# +# Originator +# Alexander Litvin archer@lucky.net +# +# Organization +# +# +#Lucky Net ltd. +# +# Release +# FreeBSD 3.0-CURRENT i386 +# +# Environment +# +# +#FreeBSD grape.carrier.kiev.ua 3.0-CURRENT FreeBSD 3.0-CURRENT #121: Thu Sep 3 +#1 +#1:21:44 EEST 1998 archer@grape.carrier.kiev.ua:/usr/src/sys/compile/GRAPE +#i +#386 +# +# Description +# +# +#The problem first appeared when GNU awk in 3.0-CURRENT was apgraded to +#3.0.3. I run C-News, which uses awk extensively. After awk apgrade C-News +#expire stopped to work. It appeared that some GNU awk 3.0.3 programms when +#given absolutely legitimate input fail, giving out a number of messages: +# +#awk in free(): warning: chunk is already free. +# +# How-To-Repeat +# +# +#Run the following awk program (it is cut out of C-News expire scripts). +#I was not able to cut it down more -- omitting some portions of the +#code (e.g. OFMT line), make error go away in this case, though it +#certainly does not fix awk. +# +#----------------cut-here---------------- +#!/usr/bin/awk -f +BEGIN { + OFMT = "%.12g" + big = 99999999999 + lowest = big + small = 0 + highest = small +} + +$0 ~ /^[0-9]+$/ { + if ($1 < lowest) + lowest = $1 + if ($1 > highest) + highest = $1 + next +} + +# $0 ~ /^[a-z]+/ { +$0 ~ /^[[:lower:]]+/ { + print dir, highest, lowest + dir = $0 + lowest = big + highest = small +} +#----------------cut-here---------------- +# +#To get the error, just give this script the following input: +#----------------cut-here---------------- +#a +#1 +#b +#----------------cut-here---------------- +# +# Fix +# +# +#I was not able to track the error in awk sources. As a workaround, +#I just reverted to GNU awk 2.15.5. +# +# Audit-Trail +# +# +#State-Changed-From-To: open-suspended +#State-Changed-By: phk +#State-Changed-When: Thu Sep 17 02:04:08 PDT 1998 +#State-Changed-Why: +#reported to GNU maintainer. +# +# Submit Followup +# _________________________________________________________________ +# +# +# www@freebsd.org diff --git a/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.in b/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.in new file mode 100644 index 0000000000..f1e80ce43f --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.in @@ -0,0 +1,3 @@ +a +1 +b diff --git a/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.ok b/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.ok new file mode 100644 index 0000000000..0fe9251df8 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/ofmtbig.ok @@ -0,0 +1,2 @@ + 0 99999999999 +a 1 1 diff --git a/usr/src/test/util-tests/tests/awk/gnu/pipeio2.awk b/usr/src/test/util-tests/tests/awk/gnu/pipeio2.awk new file mode 100644 index 0000000000..9c18d5f72d --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/pipeio2.awk @@ -0,0 +1,72 @@ +# From: megaadm@rina.quantum.de +# Subject: Bug report - closing down pipes which read from shell com +# To: bug-gnu-utils@prep.ai.mit.edu +# Date: Thu, 27 Feb 1997 23:19:16 +0100 (CET) +# CC: arnold@gnu.ai.mit.edu +# +# Hello people, +# +# i think i found a bug or something mysterious behaviour in +# gawk Version 3.0 patchlevel 0. +# +# I am running on linux 2.0.25 under bash. +# +# Could you please have a look at the following awk program +# an let me please know, if this is what i expect it to, +# namely a bug. +# +# ----------- cut here -------------------------------------------- +BEGIN { + # OS is linux 2.0.25 + # shell is bash + # Gnu Awk (gawk) 3.0, patchlevel 0 + # The command i typed on the shell was "gawk -f <this_prog> -" + + #com = "cal 01 1997" + com = ("cat pipeio2.in") + + # Don't use empty lines, because Windows ECHO does + # something different when invoked without arguments + while ((com | getline fnam) > 0 && fnam != "") { + +# com_tr = "echo " fnam " | tr [0-9]. ..........." +# com_tr = "echo " fnam " | sed 's/[0-9]/./g'" + com_tr = "echo " fnam " | sed \"s/[0-9]/./g\"" + # print "\'" com_tr "\'" + print "'" com_tr "'" + + com_tr | getline nam + print nam + + # please run that program and take a look at the + # output. I think this is what was expected. + + # Then comment in the following 4 lines and see + # what happens. I expect the first pipe "com | getline" + # not to be close, but i think this is exactly what happens + # So, is this ok ? + + if (close(com_tr) < 0) { + print ERRNO + break + } + } + + close(com) + } +# ----------- cut here -------------------------------------------- +# +# There is another thing i do not understand. +# Why doesn't the awk - command "close" reports an +# error, if i would say close("abc") which i had never +# openend ? +# +# Regards, +# Ulrich Gvbel +# -- +# /********************************************************\ +# * Ulrich Gvbel, goebel@quantum.de * +# * Quantum Gesellschaft f|r Software mbH, Dortmund * +# * phone : +49-231-9749-201 fax: +49-231-9749-3 * +# * private: +49-231-803994 fax: +49-231-803994 * +# \********************************************************/ diff --git a/usr/src/test/util-tests/tests/awk/gnu/pipeio2.in b/usr/src/test/util-tests/tests/awk/gnu/pipeio2.in new file mode 100644 index 0000000000..2652b0ef4b --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/pipeio2.in @@ -0,0 +1,8 @@ + January 1997 + S M Tu W Th F S + 1 2 3 4 + 5 6 7 8 9 10 11 +12 13 14 15 16 17 18 +19 20 21 22 23 24 25 +26 27 28 29 30 31 + diff --git a/usr/src/test/util-tests/tests/awk/gnu/pipeio2.ok b/usr/src/test/util-tests/tests/awk/gnu/pipeio2.ok new file mode 100644 index 0000000000..4514fbb316 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/pipeio2.ok @@ -0,0 +1,14 @@ +'echo January 1997 | sed "s/[0-9]/./g"' +January .... +'echo S M Tu W Th F S | sed "s/[0-9]/./g"' +S M Tu W Th F S +'echo 1 2 3 4 | sed "s/[0-9]/./g"' +. . . . +'echo 5 6 7 8 9 10 11 | sed "s/[0-9]/./g"' +. . . . . .. .. +'echo 12 13 14 15 16 17 18 | sed "s/[0-9]/./g"' +.. .. .. .. .. .. .. +'echo 19 20 21 22 23 24 25 | sed "s/[0-9]/./g"' +.. .. .. .. .. .. .. +'echo 26 27 28 29 30 31 | sed "s/[0-9]/./g"' +.. .. .. .. .. .. diff --git a/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.awk b/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.awk new file mode 100644 index 0000000000..6a902de232 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.awk @@ -0,0 +1,47 @@ +# The third argument to match() is a GNU-specific extension, so the +# two following tests have been replaced with similar ones that use +# RSTART and RLENGTH: +# +# match($0, /([Nn]ew) Value +[\([]? *([[:upper:]]+)/, f) { +# print "re1", NR, f[1], f[2] +# } +# +# match($0, /([][])/, f) { +# print "re2", NR, f[1] +# } + +match($0, /([Nn]ew)/) { + print "re1.1", NR, substr($0, RSTART, RLENGTH) +} + +match($0, /[\([] *([[:upper:]]+)/) { + print "re1.2", NR, substr($0, RSTART+1, RLENGTH-1) +} + +match($0, /([][])/) { + print "re2", NR, substr($0, RSTART, RLENGTH) +} + +/[]]/ { + print "re3", NR, $0 +} + +/[\[]/ { + print "re4", NR, $0 +} + +/[[]/ { + print "re5", NR, $0 +} + +/[][]/ { + print "re6", NR, $0 +} + +/[\([][[:upper:]]*/ { + print "re7", NR, $0 +} + +/[\([]/ { + print "re8", NR, $0 +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.in b/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.in new file mode 100644 index 0000000000..d82369b6e0 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.in @@ -0,0 +1,3 @@ +New Value [XYZ] +[ +] diff --git a/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.ok b/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.ok new file mode 100644 index 0000000000..06827391b3 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/rebrackloc.ok @@ -0,0 +1,18 @@ +re1.1 1 New +re1.2 1 XYZ +re2 1 [ +re3 1 New Value [XYZ] +re4 1 New Value [XYZ] +re5 1 New Value [XYZ] +re6 1 New Value [XYZ] +re7 1 New Value [XYZ] +re8 1 New Value [XYZ] +re2 2 [ +re4 2 [ +re5 2 [ +re6 2 [ +re7 2 [ +re8 2 [ +re2 3 ] +re3 3 ] +re6 3 ] diff --git a/usr/src/test/util-tests/tests/awk/gnu/regeq.awk b/usr/src/test/util-tests/tests/awk/gnu/regeq.awk new file mode 100644 index 0000000000..0208eb24cf --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/regeq.awk @@ -0,0 +1,29 @@ +#Date: Sat, 8 May 1999 17:42:20 +0200 +#From: Iva Cabric <ivac@fly.srk.fer.hr> +#To: bug-gnu-utils@gnu.org +#Cc: arnold@gnu.org +#Subject: Problem in gawk with match +# +#Hello, +# +#gawk reports fatal error in match when first character in regexp is "=" : +# +#$ gawk '{ where = match($0, /=a/); print where}' +#gawk: cmd. line:1: { where = match($0, /=a/); print where} +#gawk: cmd. line:1: ^ parse error +#gawk: cmd. line:1: fatal: match() cannot have 0 arguments +# +#Using "\=" instead "=" works without problems : +# +#$ gawk '{ where = match($0, /\=a/); print where}' +#sdgfa +#0 +#asdfds=a +#7 +# +#Other versions of awk have no problems with "/=/" (except oawk on SunOS). +# +#-- +# @ +# +{ where = match($0, /=a/); print where} diff --git a/usr/src/test/util-tests/tests/awk/gnu/regeq.in b/usr/src/test/util-tests/tests/awk/gnu/regeq.in new file mode 100644 index 0000000000..2428df3aa7 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/regeq.in @@ -0,0 +1,2 @@ +sdgfa +asdfds=a diff --git a/usr/src/test/util-tests/tests/awk/gnu/regeq.ok b/usr/src/test/util-tests/tests/awk/gnu/regeq.ok new file mode 100644 index 0000000000..4596f886c3 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/regeq.ok @@ -0,0 +1,2 @@ +0 +7 diff --git a/usr/src/test/util-tests/tests/awk/gnu/regexprange.awk b/usr/src/test/util-tests/tests/awk/gnu/regexprange.awk new file mode 100644 index 0000000000..861e5ee573 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/regexprange.awk @@ -0,0 +1,14 @@ +BEGIN { + range = "[a-dx-z]" + + split("ABCDEFGHIJKLMNOPQRSTUVWXYZ", upper, "") + split("abcdefghijklmnopqrstuvwxyz", lower, "") + + for (i = 1; i in upper; i++) + printf("%s ~ %s ---> %s\n", + upper[i], range, (upper[i] ~ range) ? "true" : "false") + + for (i = 1; i in lower; i++) + printf("%s ~ %s ---> %s\n", + lower[i], range, (lower[i] ~ range) ? "true" : "false") +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/regexprange.ok b/usr/src/test/util-tests/tests/awk/gnu/regexprange.ok new file mode 100644 index 0000000000..dbf5d35ae1 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/regexprange.ok @@ -0,0 +1,52 @@ +A ~ [a-dx-z] ---> false +B ~ [a-dx-z] ---> false +C ~ [a-dx-z] ---> false +D ~ [a-dx-z] ---> false +E ~ [a-dx-z] ---> false +F ~ [a-dx-z] ---> false +G ~ [a-dx-z] ---> false +H ~ [a-dx-z] ---> false +I ~ [a-dx-z] ---> false +J ~ [a-dx-z] ---> false +K ~ [a-dx-z] ---> false +L ~ [a-dx-z] ---> false +M ~ [a-dx-z] ---> false +N ~ [a-dx-z] ---> false +O ~ [a-dx-z] ---> false +P ~ [a-dx-z] ---> false +Q ~ [a-dx-z] ---> false +R ~ [a-dx-z] ---> false +S ~ [a-dx-z] ---> false +T ~ [a-dx-z] ---> false +U ~ [a-dx-z] ---> false +V ~ [a-dx-z] ---> false +W ~ [a-dx-z] ---> false +X ~ [a-dx-z] ---> false +Y ~ [a-dx-z] ---> false +Z ~ [a-dx-z] ---> false +a ~ [a-dx-z] ---> true +b ~ [a-dx-z] ---> true +c ~ [a-dx-z] ---> true +d ~ [a-dx-z] ---> true +e ~ [a-dx-z] ---> false +f ~ [a-dx-z] ---> false +g ~ [a-dx-z] ---> false +h ~ [a-dx-z] ---> false +i ~ [a-dx-z] ---> false +j ~ [a-dx-z] ---> false +k ~ [a-dx-z] ---> false +l ~ [a-dx-z] ---> false +m ~ [a-dx-z] ---> false +n ~ [a-dx-z] ---> false +o ~ [a-dx-z] ---> false +p ~ [a-dx-z] ---> false +q ~ [a-dx-z] ---> false +r ~ [a-dx-z] ---> false +s ~ [a-dx-z] ---> false +t ~ [a-dx-z] ---> false +u ~ [a-dx-z] ---> false +v ~ [a-dx-z] ---> false +w ~ [a-dx-z] ---> false +x ~ [a-dx-z] ---> true +y ~ [a-dx-z] ---> true +z ~ [a-dx-z] ---> true diff --git a/usr/src/test/util-tests/tests/awk/gnu/splitarr.awk b/usr/src/test/util-tests/tests/awk/gnu/splitarr.awk new file mode 100644 index 0000000000..c1185a4d80 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/splitarr.awk @@ -0,0 +1,5 @@ +BEGIN { + a[1] = "elephantie" + a[2] = "e" + print split(a[1],a,a[2]), a[2], a[3], split(a[2],a,a[2]) +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/splitarr.ok b/usr/src/test/util-tests/tests/awk/gnu/splitarr.ok new file mode 100644 index 0000000000..9402b94f4f --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/splitarr.ok @@ -0,0 +1 @@ +4 l phanti 2 diff --git a/usr/src/test/util-tests/tests/awk/gnu/status-close.awk b/usr/src/test/util-tests/tests/awk/gnu/status-close.awk new file mode 100644 index 0000000000..345bea4972 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/status-close.awk @@ -0,0 +1,14 @@ +BEGIN { + cat = "cat ; exit 3" + print system("echo xxx | (cat ; exit 4)") + + print "YYY" | cat + + print close(cat) + + echo = "echo boo ; exit 5" + echo | getline boo + print "got", boo + + print close(echo) +} diff --git a/usr/src/test/util-tests/tests/awk/gnu/status-close.ok b/usr/src/test/util-tests/tests/awk/gnu/status-close.ok new file mode 100644 index 0000000000..397f57028a --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/status-close.ok @@ -0,0 +1,6 @@ +xxx +4 +YYY +768 +got boo +1280 diff --git a/usr/src/test/util-tests/tests/awk/gnu/subsepnm.awk b/usr/src/test/util-tests/tests/awk/gnu/subsepnm.awk new file mode 100644 index 0000000000..976eef96e1 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/subsepnm.awk @@ -0,0 +1 @@ +BEGIN { SUBSEP = 10; a[1, 1] = 100 ; print a[1 SUBSEP 1] } diff --git a/usr/src/test/util-tests/tests/awk/gnu/subsepnm.ok b/usr/src/test/util-tests/tests/awk/gnu/subsepnm.ok new file mode 100644 index 0000000000..29d6383b52 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/gnu/subsepnm.ok @@ -0,0 +1 @@ +100 diff --git a/usr/src/test/util-tests/tests/awk/runtests.sh b/usr/src/test/util-tests/tests/awk/runtests.sh index 0bc46c4592..28d127dc3c 100755 --- a/usr/src/test/util-tests/tests/awk/runtests.sh +++ b/usr/src/test/util-tests/tests/awk/runtests.sh @@ -1,4 +1,4 @@ -#! /usr/bin/ksh +#! /usr/bin/ksh93 # # # This file and its contents are supplied under the terms of the @@ -21,6 +21,13 @@ WORKDIR=$(mktemp -d /tmp/nawktest.XXXXXX) SUCCESSES=0 TOTAL=0 +function proctemplate { + bash <<-EOF + IFS= read -rd '' OUTPUT < $1; + printf "%s" "\${OUTPUT//\\\$AWK/\$AWK}"; + EOF +} + while [[ $# -gt 0 ]]; do case $1 in -o) @@ -59,6 +66,7 @@ fi export AWK export WORKDIR +export UMEM_DEBUG="default" mkdir -p $WORKDIR @@ -90,6 +98,22 @@ for script in examples/awk/t.*; do fi done +cd bugs-fixed || exit 1 +for PROG in *.awk; do + ((TOTAL+=1)) + export LANG=C + printf "$PROG... " + $AWK -f $PROG > $WORKDIR/test.temp.out 2>&1 || \ + echo EXIT CODE: $? >> $WORKDIR/test.temp.out + if diff $WORKDIR/test.temp.out <(proctemplate ${PROG/.awk/.ok}); then + printf "ok\n" + ((SUCCESSES+=1)) + else + printf "failed\n" + fi +done +cd $TOP + # Run the test programs printf '\n# One True AWK Test Programs\n\n' @@ -156,7 +180,7 @@ for PROG in *.awk; do continue fi - if diff $WORKDIR/test.temp.out <(sed "s|\$AWK|$AWK|g" ${PROG/.awk/.ok}); then + if diff $WORKDIR/test.temp.out <(proctemplate ${PROG/.awk/.ok}); then printf "ok\n" ((SUCCESSES+=1)) else diff --git a/usr/src/test/util-tests/tests/awk/syn/aryprm1.ok b/usr/src/test/util-tests/tests/awk/syn/aryprm1.ok index 091f55202e..2cea0f0131 100644 --- a/usr/src/test/util-tests/tests/awk/syn/aryprm1.ok +++ b/usr/src/test/util-tests/tests/awk/syn/aryprm1.ok @@ -1,2 +1,2 @@ -$AWK: arr is not an array - source line number 2 +$AWK: can't assign to arr; it's an array name. + source line number 4 diff --git a/usr/src/test/util-tests/tests/awk/syn/aryprm2.ok b/usr/src/test/util-tests/tests/awk/syn/aryprm2.ok index e1974ff31d..a2e6ba6309 100644 --- a/usr/src/test/util-tests/tests/awk/syn/aryprm2.ok +++ b/usr/src/test/util-tests/tests/awk/syn/aryprm2.ok @@ -1,6 +1,2 @@ -$AWK: you can only delete array[element] at source line 3 in function f - context is - delete a >>> - <<< -$AWK: syntax error at source line 3 in function f -$AWK: illegal statement at source line 3 in function f +$AWK: can't read value of arr; it's an array name. + source line number 3 diff --git a/usr/src/test/util-tests/tests/awk/syn/aryprm3.ok b/usr/src/test/util-tests/tests/awk/syn/aryprm3.ok index 091f55202e..ae0d9f46bb 100644 --- a/usr/src/test/util-tests/tests/awk/syn/aryprm3.ok +++ b/usr/src/test/util-tests/tests/awk/syn/aryprm3.ok @@ -1,2 +1,2 @@ -$AWK: arr is not an array - source line number 2 +$AWK: can't read value of arr; it's an array name. + source line number 4 diff --git a/usr/src/test/util-tests/tests/awk/syn/badassign1.ok b/usr/src/test/util-tests/tests/awk/syn/badassign1.ok index 63195088bc..43494bce4b 100644 --- a/usr/src/test/util-tests/tests/awk/syn/badassign1.ok +++ b/usr/src/test/util-tests/tests/awk/syn/badassign1.ok @@ -1,4 +1,4 @@ -$AWK: syntax error at source line 1 +$AWK: syntax error at source line 1 source file badassign1.awk context is BEGIN { $i++ >>> = <<< 3 ; print i } -$AWK: illegal statement at source line 1 +$AWK: illegal statement at source line 1 source file badassign1.awk diff --git a/usr/src/test/util-tests/tests/awk/syn/badbuild.ok b/usr/src/test/util-tests/tests/awk/syn/badbuild.ok index bebca97297..230134520d 100644 --- a/usr/src/test/util-tests/tests/awk/syn/badbuild.ok +++ b/usr/src/test/util-tests/tests/awk/syn/badbuild.ok @@ -1,4 +1,4 @@ -$AWK: syntax error at source line 1 +$AWK: syntax error at source line 1 source file badbuild.awk context is $1 == $2 >>> == <<< $AWK: bailing out at source line 1 diff --git a/usr/src/test/util-tests/tests/awk/syn/delfunc.ok b/usr/src/test/util-tests/tests/awk/syn/delfunc.ok index 52bdbc462d..175538b481 100644 --- a/usr/src/test/util-tests/tests/awk/syn/delfunc.ok +++ b/usr/src/test/util-tests/tests/awk/syn/delfunc.ok @@ -1,4 +1,4 @@ -$AWK: you can only delete array[element] at source line 5 in function f +$AWK: f is a function, not an array at source line 5 in function f source file delfunc.awk context is delete f >>> <<< diff --git a/usr/src/test/util-tests/tests/awk/syn/fnarray.ok b/usr/src/test/util-tests/tests/awk/syn/fnarray.ok index 2575d2591f..aec63d5d7a 100644 --- a/usr/src/test/util-tests/tests/awk/syn/fnarray.ok +++ b/usr/src/test/util-tests/tests/awk/syn/fnarray.ok @@ -1,3 +1,3 @@ -$AWK: foo is a function, not an array at source line 5 +$AWK: foo is a function, not an array at source line 5 source file fnarray.awk context is Num = >>> foo[c] <<< diff --git a/usr/src/test/util-tests/tests/awk/syn/fnmisc.ok b/usr/src/test/util-tests/tests/awk/syn/fnmisc.ok index 7f9d5e7e6d..906113aaa7 100644 --- a/usr/src/test/util-tests/tests/awk/syn/fnmisc.ok +++ b/usr/src/test/util-tests/tests/awk/syn/fnmisc.ok @@ -1,4 +1,4 @@ -$AWK: syntax error at source line 11 +$AWK: syntax error at source line 11 source file fnmisc.awk context is function >>> split <<< (x) { return x } $AWK: bailing out at source line 11 diff --git a/usr/src/test/util-tests/tests/awk/syn/funsmnam.awk b/usr/src/test/util-tests/tests/awk/syn/funsmnam.awk new file mode 100644 index 0000000000..1e8ca50650 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/syn/funsmnam.awk @@ -0,0 +1,6 @@ +function foo( \ + foo) +{ + print foo +} +{ foo() } diff --git a/usr/src/test/util-tests/tests/awk/syn/funsmnam.ok b/usr/src/test/util-tests/tests/awk/syn/funsmnam.ok new file mode 100644 index 0000000000..f561265977 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/syn/funsmnam.ok @@ -0,0 +1,3 @@ +$AWK: `foo' is both function name and argument name at source line 5 source file funsmnam.awk + context is + >>> } <<< diff --git a/usr/src/test/util-tests/tests/awk/syn/nastyparm.ok b/usr/src/test/util-tests/tests/awk/syn/nastyparm.ok index 763d89fef9..40438c4157 100644 --- a/usr/src/test/util-tests/tests/awk/syn/nastyparm.ok +++ b/usr/src/test/util-tests/tests/awk/syn/nastyparm.ok @@ -1,2 +1,2 @@ -$AWK: can't read value of a; it's an array name. - source line number 8 +$AWK: can't read value of b; it's an array name. + source line number 3 diff --git a/usr/src/test/util-tests/tests/awk/syn/nfneg.awk b/usr/src/test/util-tests/tests/awk/syn/nfneg.awk new file mode 100644 index 0000000000..6d54ee0c4c --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/syn/nfneg.awk @@ -0,0 +1 @@ +BEGIN { NF -= 2 ; print } diff --git a/usr/src/test/util-tests/tests/awk/syn/nfneg.ok b/usr/src/test/util-tests/tests/awk/syn/nfneg.ok new file mode 100644 index 0000000000..b1bdbdff27 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/syn/nfneg.ok @@ -0,0 +1,2 @@ +$AWK: cannot set NF to a negative value + source line number 1 diff --git a/usr/src/test/util-tests/tests/awk/syn/noparms.ok b/usr/src/test/util-tests/tests/awk/syn/noparms.ok index 6d523bf86e..ca7fa3085f 100644 --- a/usr/src/test/util-tests/tests/awk/syn/noparms.ok +++ b/usr/src/test/util-tests/tests/awk/syn/noparms.ok @@ -1,4 +1,4 @@ -$AWK: syntax error at source line 1 in function x +$AWK: syntax error at source line 1 in function x source file noparms.awk context is function x(a, b, c , >>> , <<< $AWK: bailing out at source line 1 in function x diff --git a/usr/src/test/util-tests/tests/awk/syn/nulinsrc.ok b/usr/src/test/util-tests/tests/awk/syn/nulinsrc.ok index d0b7cb139a..605a39fc6b 100644 --- a/usr/src/test/util-tests/tests/awk/syn/nulinsrc.ok +++ b/usr/src/test/util-tests/tests/awk/syn/nulinsrc.ok @@ -1,4 +1,3 @@ -$AWK: syntax error at source line 1 +$AWK: non-terminated regular expression \... at source line 1 context is >>> /\ <<< -$AWK: bailing out at source line 1 diff --git a/usr/src/test/util-tests/tests/awk/syn/paramdup.awk b/usr/src/test/util-tests/tests/awk/syn/paramdup.awk new file mode 100644 index 0000000000..1f1cc7a455 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/syn/paramdup.awk @@ -0,0 +1,8 @@ +BEGIN { foo(0, 1, 2) } + +function foo(a, b, c, b, a) +{ + print "a =", a + print "b =", b + print "c =", c +} diff --git a/usr/src/test/util-tests/tests/awk/syn/paramdup.ok b/usr/src/test/util-tests/tests/awk/syn/paramdup.ok new file mode 100644 index 0000000000..ec67f0f924 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/syn/paramdup.ok @@ -0,0 +1,5 @@ +$AWK: duplicate argument b at source line 3 in function foo source file paramdup.awk + context is + function foo(a, b, c, >>> b <<< , a) +$AWK: syntax error at source line 3 in function foo source file paramdup.awk +$AWK: bailing out at source line 3 in function foo diff --git a/usr/src/test/util-tests/tests/awk/syn/parseme.ok b/usr/src/test/util-tests/tests/awk/syn/parseme.ok index 1b517e1eca..00fc855b10 100644 --- a/usr/src/test/util-tests/tests/awk/syn/parseme.ok +++ b/usr/src/test/util-tests/tests/awk/syn/parseme.ok @@ -1,5 +1,5 @@ -$AWK: syntax error at source line 1 +$AWK: syntax error at source line 1 source file parseme.awk context is BEGIN { >>> toupper(substr* <<< line,1,12)) } -$AWK: illegal statement at source line 1 +$AWK: illegal statement at source line 1 source file parseme.awk extra ) diff --git a/usr/src/test/util-tests/tests/awk/syn/synerr1.ok b/usr/src/test/util-tests/tests/awk/syn/synerr1.ok index ef8e46dac5..9201971c04 100644 --- a/usr/src/test/util-tests/tests/awk/syn/synerr1.ok +++ b/usr/src/test/util-tests/tests/awk/syn/synerr1.ok @@ -1,4 +1,4 @@ -$AWK: syntax error at source line 4 +$AWK: syntax error at source line 4 source file synerr1.awk context is >>> print <<< "hi" $AWK: bailing out at source line 4 diff --git a/usr/src/test/util-tests/tests/awk/syn/synerr2.ok b/usr/src/test/util-tests/tests/awk/syn/synerr2.ok index 7b778e2e5b..1eb51dd0ac 100644 --- a/usr/src/test/util-tests/tests/awk/syn/synerr2.ok +++ b/usr/src/test/util-tests/tests/awk/syn/synerr2.ok @@ -1,4 +1,4 @@ -$AWK: syntax error at source line 47 +$AWK: syntax error at source line 47 source file synerr2.awk context is BEGIN { sprintf("%s", >>> $) <<< } -$AWK: illegal statement at source line 47 +$AWK: illegal statement at source line 47 source file synerr2.awk diff --git a/usr/src/test/util-tests/tests/awk/syn/tradanch1.ok b/usr/src/test/util-tests/tests/awk/syn/tradanch1.ok index 8d07ab4dfb..194330a35e 100644 --- a/usr/src/test/util-tests/tests/awk/syn/tradanch1.ok +++ b/usr/src/test/util-tests/tests/awk/syn/tradanch1.ok @@ -1,4 +1,4 @@ $AWK: syntax error in regular expression foo^bar at bar - source line number 1 + source line number 1 source file tradanch1.awk context is >>> /foo^bar/ <<< diff --git a/usr/src/test/util-tests/tests/awk/syn/unterm.ok b/usr/src/test/util-tests/tests/awk/syn/unterm.ok index 4c32fcf95b..393b31b74a 100644 --- a/usr/src/test/util-tests/tests/awk/syn/unterm.ok +++ b/usr/src/test/util-tests/tests/awk/syn/unterm.ok @@ -1,5 +1,5 @@ -$AWK: syntax error at source line 1 +$AWK: non-terminated string ............. at source line 1 context is >>> BEGIN{x=".........................................................................................................................................................................................................................................................} <<< -$AWK: illegal statement at source line 1 - missing } +$AWK: giving up + source line number 1 diff --git a/usr/src/test/util-tests/tests/awk/tests/T.-f-f b/usr/src/test/util-tests/tests/awk/tests/T.-f-f index 57679a6f8b..73f0bcdcb1 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.-f-f +++ b/usr/src/test/util-tests/tests/awk/tests/T.-f-f @@ -20,6 +20,7 @@ TEMP2=$WORKDIR/test.temp.2 TEMP3=$WORKDIR/test.temp.3 TEMP4=$WORKDIR/test.temp.4 TEMP5=$WORKDIR/test.temp.5 +TEMP6=$WORKDIR/test.temp.6 echo 'begin end' > $TEMP0 @@ -41,4 +42,15 @@ echo '}' > $TEMP4 $AWK -f $TEMP2 -f $TEMP3 -f $TEMP4 /etc/passwd > $TEMP5 diff $TEMP1 $TEMP5 || fail 'BAD: T.-f-f 3 files' + +echo '/./ {' > $TEMP2 +echo 'print' > $TEMP3 +echo ' + + + +]' > $TEMP4 +$AWK -f $TEMP2 -f $TEMP3 -f $TEMP4 /etc/passwd > $TEMP5 2> $TEMP6 +grep "syntax error.*file $TEMP4" $TEMP6 >/dev/null 2>&1 || fail 'BAD: T.-f-f source file name' + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.argv b/usr/src/test/util-tests/tests/awk/tests/T.argv index f80cded5c5..f47eb37098 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.argv +++ b/usr/src/test/util-tests/tests/awk/tests/T.argv @@ -134,4 +134,32 @@ echo 'test.temp.1 test.temp.3' > $TEMP5 diff $TEMP4 $TEMP5 || fail 'BAD: T.argv zap ARGV[2]' +echo hi > $TEMP1 ; mv $TEMP1 $TEMP2 +$AWK 'BEGIN { ARGV[1] = "'$TEMP2'" ; print FILENAME } + { print FILENAME }' $TEMP1 > $TEMP3 +echo " +$TEMP2" > $TEMP4 +diff $TEMP3 $TEMP4 || fail 'BAD: T.argv startup FILENAME' + # assumes that startup FILENAME is "" + + +# test data balanced on pinhead... +echo "ARGV[3] is /dev/null +ARGV[0] is $AWK +ARGV[1] is /dev/null" > $TEMP1 + +$AWK 'BEGIN { # this is a variant of arnolds original example + ARGV[1] = "/dev/null" + ARGV[2] = "glotch" # file open must skipped deleted argv + ARGV[3] = "/dev/null" + ARGC = 4 + delete ARGV[2] +} +# note that input is read here +END { + for (i in ARGV) + printf("ARGV[%d] is %s\n", i, ARGV[i]) +}' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.argv delete ARGV[2]' + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.builtin b/usr/src/test/util-tests/tests/awk/tests/T.builtin index 15319675e7..1d8fae810b 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.builtin +++ b/usr/src/test/util-tests/tests/awk/tests/T.builtin @@ -5,6 +5,7 @@ if [[ -z "$AWK" || -z "$WORKDIR" ]]; then exit 1 fi +TEMP0=$WORKDIR/test.temp.0 TEMP1=$WORKDIR/test.temp.1 TEMP2=$WORKDIR/test.temp.2 @@ -69,4 +70,13 @@ $AWK 'BEGIN { }' 2> $TEMP1 grep 'too many arg' $TEMP1 >/dev/null || fail 'T.bad: too many args not caught' +echo 'a +a b +a b c' > $TEMP0 +echo '1 +2 +3' > $TEMP1 +$AWK '{ n = split($0, x); print length(x) }' < $TEMP0 > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.builtin length array' + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.close b/usr/src/test/util-tests/tests/awk/tests/T.close index 14b36f8bf6..0651c8f6ea 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.close +++ b/usr/src/test/util-tests/tests/awk/tests/T.close @@ -18,7 +18,7 @@ fail() { echo T.close: test close built-in -rm -f test.temp +rm -f $TEMP0 $AWK '{ print >>"'$TEMP0'"; close("'$TEMP0'") }' /etc/passwd diff /etc/passwd $TEMP0 || fail 'BAD: T.close (1)' @@ -27,4 +27,28 @@ tail -1 $TEMP0 > $TEMP1 $AWK '{ print >"'$TEMP2'"; close("'$TEMP2'") }' $TEMP0 diff $TEMP1 $TEMP2 || fail 'BAD: T.close (2)' +echo 0 > $TEMP1 +$AWK ' # non-accessible file + BEGIN { getline <"/etc/passwd"; print close("/etc/passwd"); } +' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.close (3)' + +echo -1 > $TEMP1 +$AWK ' # file not opened + BEGIN { print close("glotch"); } +' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.close (4)' + +echo 0 > $TEMP1 +$AWK ' # normal close + BEGIN { print "hello" > "'$TEMP0'"; print close("'$TEMP0'"); } +' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.close (5)' + +echo 0 > $TEMP1 +$AWK ' # normal close + BEGIN { print "hello" | "cat > '$TEMP0'"; print close("cat > '$TEMP0'"); } +' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.close (6)' + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.clv b/usr/src/test/util-tests/tests/awk/tests/T.clv index 065555d1c3..71f4e9cd7c 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.clv +++ b/usr/src/test/util-tests/tests/awk/tests/T.clv @@ -101,11 +101,19 @@ echo 123 > $TEMP1 $AWK -v x=123 'BEGIN { print x }' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=11)' +echo 123 > $TEMP1 +$AWK -vx=123 'BEGIN { print x }' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=11a)' + echo 123 abc 10.99 > $TEMP1 $AWK -v x=123 -v y=abc -v z1=10.99 'BEGIN { print x, y, z1 }' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=12)' echo 123 abc 10.99 > $TEMP1 +$AWK -vx=123 -vy=abc -vz1=10.99 'BEGIN { print x, y, z1 }' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=12a)' + +echo 123 abc 10.99 > $TEMP1 $AWK -v x=123 -v y=abc -v z1=10.99 -- 'BEGIN { print x, y, z1 }' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=12a)' @@ -116,9 +124,19 @@ diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=13)' echo 'BEGIN { print x, y, z1 }' > $TEMP0 echo 123 abc 10.99 > $TEMP1 +$AWK -vx=123 -vy=abc -f $TEMP0 -vz1=10.99 > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=13a)' + +echo 'BEGIN { print x, y, z1 }' > $TEMP0 +echo 123 abc 10.99 > $TEMP1 $AWK -f $TEMP0 -v x=123 -v y=abc -v z1=10.99 > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=14)' +echo 'BEGIN { print x, y, z1 }' > $TEMP0 +echo 123 abc 10.99 > $TEMP1 +$AWK -f $TEMP0 -vx=123 -vy=abc -vz1=10.99 > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=14a)' + echo 'BEGIN { print x, y, z1 } END { print x }' > $TEMP0 echo '123 abc 10.99 @@ -127,12 +145,28 @@ $AWK -f $TEMP0 -v x=123 -v y=abc -v z1=10.99 /dev/null x=4567 /dev/null > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=15)' echo 'BEGIN { print x, y, z1 } +END { print x }' > $TEMP0 +echo '123 abc 10.99 +4567' > $TEMP1 +$AWK -f $TEMP0 -vx=123 -vy=abc -vz1=10.99 /dev/null x=4567 /dev/null > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=15a)' + +echo 'BEGIN { print x, y, z1 } NR==1 { print x }' > $TEMP0 echo '123 abc 10.99 4567' > $TEMP1 $AWK -v x=123 -v y=abc -v z1=10.99 -f $TEMP0 x=4567 /etc/passwd > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=16)' +echo 'BEGIN { print x, y, z1 } +NR==1 { print x }' > $TEMP0 +echo '123 abc 10.99 +4567' > $TEMP1 +$AWK -vx=123 -vy=abc -vz1=10.99 -f $TEMP0 x=4567 /etc/passwd > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=16a)' + + + # special chars in commandline assigned value; # have to use local echo to avoid quoting problems. @@ -150,4 +184,18 @@ $AWK 'BEGIN { printf("a%c%c%cz\n", "\b", "\r", "\f") }' > $TEMP1 echo 'hello' | $AWK '{print x}' x='a\b\r\fz' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=19)' +echo '\' > $TEMP1 +$AWK -v 'x=\' 'BEGIN { print x; }' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.clv (x=\)' + +### newer -v tests + + +$AWK -vx 'BEGIN {print x}' > $TEMP1 2>&1 +grep 'invalid -v option argument: x' $TEMP1 >/dev/null || fail 'BAD: T.clv (x=20)' + +$AWK -v x 'BEGIN {print x}' > $TEMP1 2>&1 +grep 'invalid -v option argument: x' $TEMP1 >/dev/null || fail 'BAD: T.clv (x=20a)' + + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.delete b/usr/src/test/util-tests/tests/awk/tests/T.delete new file mode 100755 index 0000000000..3ef4e50585 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/tests/T.delete @@ -0,0 +1,39 @@ +#!/bin/bash + +if [[ -z "$AWK" || -z "$WORKDIR" ]]; then + printf '$AWK and $WORKDIR must be set\n' >&2 + exit 1 +fi + +TEMP0=$WORKDIR/test.temp.0 +TEMP1=$WORKDIR/test.temp.1 +TEMP2=$WORKDIR/test.temp.2 + +RESULT=0 + +fail() { + echo "$1" >&2 + RESULT=1 +} + +echo T.delete: misc tests of array deletion + +echo '1 2 3 4 +1 2 3 +1 +' > $TEMP0 +echo '4 3 0 +3 2 0 +1 0 0 +0 0 0' > $TEMP2 +$AWK ' +{ n = split($0, x) + delete x[1] + n1 = 0; for (i in x) n1++ + delete x; + n2 = 0; for (i in x) n2++ + print n, n1, n2 +}' $TEMP0 > $TEMP1 +diff $TEMP1 $TEMP2 || fail 'BAD: T.delete (1)' + +exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.errmsg b/usr/src/test/util-tests/tests/awk/tests/T.errmsg index 7bcae73d51..66e14ff9f8 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.errmsg +++ b/usr/src/test/util-tests/tests/awk/tests/T.errmsg @@ -39,10 +39,28 @@ $1 ~ /^#/ { illegal primary in regular expression /(/ +illegal break, continue, next or nextfile from BEGIN +BEGIN { nextfile } + +illegal break, continue, next or nextfile from END +END { nextfile } + +nextfile is illegal inside a function +function foo() { nextfile } + +duplicate argument +function f(i,j,i) { return i } + nonterminated character class /[[/ nonterminated character class +/[]/ + +nonterminated character class +/[\ + +nonterminated character class BEGIN { s = "[x"; if (1 ~ s) print "foo"} syntax error in regular expression @@ -95,6 +113,16 @@ function x() { function g() {} } return not in function { return } +break illegal outside +{ break } + +continue illegal outside +{ continue } + +non-terminated string +{ print "abc +} + illegal field $(foo) BEGIN { print $"foo" } @@ -105,6 +133,9 @@ function f() { next } not enough args in printf(%s) BEGIN { printf("%s") } +weird printf conversion +BEGIN { printf("%z", "foo")} + function f has .* arguments, limit .* function f(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10, c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10, @@ -176,6 +207,12 @@ BEGIN { length("abc", "def") } calling undefined function foo BEGIN { foo() } +cannot delete SYMTAB or its elements +BEGIN { delete SYMTAB } + +cannot delete SYMTAB or its elements +BEGIN { delete SYMTAB["OFS"] } + # I am pretty certain that this test is _meant_ to fail, # to allow checking whether anything is happening. Uncomment # below to check whether the script then fails: @@ -195,4 +232,19 @@ $AWK '{print x}' x='a b' $TEMP0 > $TEMP1 2> $TEMP2 grep 'newline in string' $TEMP2 >/dev/null || fail 'BAD: T.errmsg newline in string' +$AWK -safe 'BEGIN{"date" | getline}' > $TEMP0 2> $TEMP2 +grep 'cmd | getline is unsafe' $TEMP2 >/dev/null || fail 'BAD: T.errmsg cmd|getline unsafe' + +$AWK -safe 'BEGIN{print >"'$TEMP0'"}' > $TEMP0 2> $TEMP2 +grep 'print > is unsafe' $TEMP2 >/dev/null || fail 'BAD: T.errmsg print > unsafe' + +$AWK -safe 'BEGIN{print >> "'$TEMP0'"}' > $TEMP0 2> $TEMP2 +grep 'print >> is unsafe' $TEMP2 >/dev/null || fail 'BAD: T.errmsg print >> unsafe' + +$AWK -safe 'BEGIN{print | "'$TEMP0'"}' > $TEMP0 2> $TEMP2 +grep 'print | is unsafe' $TEMP2 >/dev/null || fail 'BAD: T.errmsg print | unsafe' + +$AWK -safe 'BEGIN {system("date")}' > $TEMP0 2> $TEMP2 +grep 'system is unsafe' $TEMP2 >/dev/null || fail 'BAD: T.errmsg system unsafe' + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.expr b/usr/src/test/util-tests/tests/awk/tests/T.expr index 0c3ad6d21c..3efb71abf2 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.expr +++ b/usr/src/test/util-tests/tests/awk/tests/T.expr @@ -110,6 +110,25 @@ abc abc try { x = $1++++$2; print $1, x } 1 3 2 14 +# do we get the precedence of ! right? +try $1 !$2 +0 0 0\t0 +0 1 0\t1 +1 0 1\t0 +1 1 1\t1 + +# another ava special +try { print ($1~/abc/ !$2) } +0 0 01 +0 1 00 +abc 0 11 +xabcd 1 10 + +try { print !$1 + $2 } +1 3 3 +0 3 4 +-1 3 3 + # aside: !$1 = $2 is now a syntax error # the definition of "number" changes with isnumber. @@ -129,6 +148,7 @@ try { print ($1 == $2) } 2e-10 2e-10 1 2e10 2e-10 0 2e10 20e9 1 +2e100 2.000e100 1 2e1000 2.0e1000 0 # this one (3 & 4) may "fail" if a negative 0 is printed as -0, @@ -137,6 +157,8 @@ try { print ($1 == $2) } try { print $1, +$1, -$1, - -$1 } 1 1 1 -1 1 -1 -1 -1 1 -1 +0 0 0 0 0 +x x 0 0 0 try { printf("a%*sb\n", $1, $2) } 1 x axb @@ -171,20 +193,26 @@ try { printf("%x %lx\n", $1, $1) } try { if ($1 ~ $2) print 1; else print 0 } a \141 1 a \142 0 +a \x61 1 a \x061 0 a \x62 0 0 \060 1 0 \60 1 0 \0060 0 +Z \x5a 1 +Z \x5A 1 try { print $1 ~ $2 } a \141 1 a \142 0 +a \x61 1 a \x061 0 a \x62 0 0 \060 1 0 \60 1 0 \0060 0 +Z \x5a 1 +Z \x5A 1 try { print $1 || $2 } 0 diff --git a/usr/src/test/util-tests/tests/awk/tests/T.flags b/usr/src/test/util-tests/tests/awk/tests/T.flags index 48baf24852..2bc80a8018 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.flags +++ b/usr/src/test/util-tests/tests/awk/tests/T.flags @@ -1,7 +1,7 @@ #!/bin/bash if [[ -z "$AWK" || -z "$WORKDIR" ]]; then - printf '$AWK must be set\n' >&2 + printf '$AWK and $WORKDIR must be set\n' >&2 exit 1 fi @@ -25,6 +25,9 @@ grep 'no program' $TEMP1 >/dev/null || fail 'T.flags: bad no program' $AWK -f glop/glop > $TEMP1 2>&1 grep 'can.t open' $TEMP1 >/dev/null || fail 'T.flags: bad can.t open program' +$AWK -fglop/glop > $TEMP1 2>&1 +grep 'can.t open' $TEMP1 >/dev/null || fail 'T.flags: bad can.t open program 2' + $AWK -zz 'BEGIN{}' > $TEMP1 2>&1 grep 'unknown option' $TEMP1 >/dev/null || fail 'T.flags: bad unknown option' diff --git a/usr/src/test/util-tests/tests/awk/tests/T.func b/usr/src/test/util-tests/tests/awk/tests/T.func index e5d0ec37d1..49bd3f0859 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.func +++ b/usr/src/test/util-tests/tests/awk/tests/T.func @@ -204,4 +204,10 @@ BEGIN { n = 10 ' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.func (multi-dim subscript)' +echo '<> 0' > $TEMP1 +$AWK ' +function foo() { i = 0 } + BEGIN { x = foo(); printf "<%s> %d\n", x, x }' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.func (fall off end)' + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.gawk b/usr/src/test/util-tests/tests/awk/tests/T.gawk index a30f2c3c0b..a1c778b145 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.gawk +++ b/usr/src/test/util-tests/tests/awk/tests/T.gawk @@ -59,6 +59,28 @@ $AWK '{ x = y = $0 diff $TEMP1 $TEMP2 || fail 'BAD: T.gawk backgsub' +# backgsub2: +cat <<< 'x\y +x\\y +x\\\y' > $TEMP0 +cat <<< ' x\y + x\y + x\y + x\y + x\\y + x\\\y + x\\y + x\\\y + x\\\\y' > $TEMP1 +$AWK '{ w = x = y = z = $0 + gsub( /\\\\/, "\\", w); print " " w + gsub( /\\\\/, "\\\\", x); print " " x + gsub( /\\\\/, "\\\\\\", y); print " " y +} +' $TEMP0 > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.gawk backgsub2' + + # backgsub3: cat <<< 'xax xaax' > $TEMP0 @@ -113,6 +135,21 @@ $AWK '{ w = x = y = z = z1 = z2 = $0 diff $TEMP1 $TEMP2 || fail 'BAD: T.gawk backsub3' +# backsub: +cat <<< 'x\y +x\\y' > $TEMP0 +cat <<< 'x\y +x\\y +x\\y +x\\\y' > $TEMP1 +$AWK '{ x = y = $0 + sub( /\\\\/, "\\\\", x); print x + sub( "\\\\", "\\\\", y); print y +}' $TEMP0 > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.gawk backsub' + + + # dynlj: echo 'hello world' > $TEMP1 @@ -335,6 +372,17 @@ echo 'a::c:d $AWK '{ OFS = ":"; $2 = ""; print $0; print NF }' $TEMP0 > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.gawk fldchgnf' +# OFMT from arnold robbins 6/02: +# 5.7 with OFMT = %0.f is 6 +echo '6' > $TEMP1 +$AWK 'BEGIN { + OFMT = "%.0f" + print 5.7 +}' > $TEMP2 +cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.gawk ofmt' + + +### don't know what this is supposed to do now. ### # convfmt: ### echo 'a = 123.46 ### a = 123.456 diff --git a/usr/src/test/util-tests/tests/awk/tests/T.getline b/usr/src/test/util-tests/tests/awk/tests/T.getline index 45fce166ff..1de6e11d43 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.getline +++ b/usr/src/test/util-tests/tests/awk/tests/T.getline @@ -95,4 +95,21 @@ $AWK ' BEGIN { print getline <"/glop/glop/glop" } ' > $TEMP1 echo '-1' > $TEMP2 cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.getline (non-existent file)' +echo 'false false equal' > $TEMP1 +$AWK 'BEGIN { + "echo 0" | getline + if ($0) printf "true " + else printf "false " + if ($1) printf "true " + else printf "false " + if ($0==$1) printf "equal\n" + else printf "not equal\n" +}' > $TEMP2 +cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.getline bad $0 type in cmd|getline' + +echo 'L1 +L2' | $AWK 'BEGIN { $0="old stuff"; $1="new"; getline x; print}' > $TEMP1 +echo 'new stuff' > $TEMP2 +cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.getline bad update $0' + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.latin1 b/usr/src/test/util-tests/tests/awk/tests/T.latin1 index 792578212c..84f87e8ad0 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.latin1 +++ b/usr/src/test/util-tests/tests/awk/tests/T.latin1 @@ -32,6 +32,10 @@ $AWK '{ gsub(/\351/, "\370"); print }' latin1 > $TEMP0 $AWK '{ gsub(/é/, "ø"); print }' latin1 > $TEMP1 diff $TEMP0 $TEMP1 || fail 'BAD: T.latin1 3' +$AWK '{ gsub(/[^\300-\370]/, ""); print }' latin1 > $TEMP0 +$AWK '{ gsub(/[^À-ø]/, ""); print } ' latin1 > $TEMP1 +diff $TEMP0 $TEMP1 || fail 'BAD: T.latin1 4' + echo '/á/' > $TEMP1 $AWK -f $TEMP1 $TEMP1 > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.latin1 5' diff --git a/usr/src/test/util-tests/tests/awk/tests/T.lilly b/usr/src/test/util-tests/tests/awk/tests/T.lilly new file mode 100755 index 0000000000..eb7373433e --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/tests/T.lilly @@ -0,0 +1,54 @@ +#!/bin/bash + +if [[ -z "$AWK" || -z "$WORKDIR" ]]; then + printf '$AWK and $WORKDIR must be set\n' >&2 + exit 1 +fi + +TEMP0=$WORKDIR/test.temp.0 +TEMP1=$WORKDIR/test.temp.1 +TEMP2=$WORKDIR/test.temp.2 +TEMP3=$WORKDIR/test.temp.3 + +RESULT=0 + +fail() { + echo "$1" >&2 + RESULT=1 +} + +echo T.lilly: miscellaneous RE tests from Bruce Lilly + +cat > $TEMP0 <<EOF +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +EOF + +rm -f $TEMP2 +$AWK ' +/./ { + print $0 >"'$TEMP2'" + print "###", NR, $0 + system(ENVIRON["AWK"] " -f '$TEMP2' <\"'$TEMP0'\" ") + close "'$TEMP2'" +}' < lilly.progs > $TEMP1 2>&1 + +echo `wc -l lilly.progs` tests + +diff $TEMP1 lilly.ok > $WORKDIR/lilly.diff || fail 'bad: T.lilly is different' + +exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.main b/usr/src/test/util-tests/tests/awk/tests/T.main index 555e4a25be..f6574c7a60 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.main +++ b/usr/src/test/util-tests/tests/awk/tests/T.main @@ -42,6 +42,11 @@ $AWK -F t '{print NF}' $TEMP0 > $TEMP1 echo '3' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'bad: awk -F (tab)' +echo 'a b c' > $TEMP0 +$AWK -Ft '{print NF}' $TEMP0 > $TEMP1 +echo '3' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'bad: awk -F (tab 2)' + echo 'atabbtabc' > $TEMP0 $AWK -F tab '{print NF}' $TEMP0 > $TEMP1 echo '3' > $TEMP2 diff --git a/usr/src/test/util-tests/tests/awk/tests/T.misc b/usr/src/test/util-tests/tests/awk/tests/T.misc index 748705c60d..50978e0048 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.misc +++ b/usr/src/test/util-tests/tests/awk/tests/T.misc @@ -60,9 +60,10 @@ echo '3 cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc bad field increment' # makes sure that fields are recomputed even if self-assignment +# take into account that subtracting from NF now rebuilds the record echo 'a b c s p q r -x y' > $TEMP0 +x y z' > $TEMP0 echo 'a s p x' > $TEMP1 @@ -92,6 +93,18 @@ $AWK 'BEGIN { FILENAME = "/etc/passwd" } { print $0 }' >/dev/null if [[ $? -eq 139 ]]; then fail "BAD: T.misc /etc/passwd dropped core"; fi +echo hello | +$AWK ' function foo(foo) { + foo = 1 + foo() + } + { foo(bar) } +' >/dev/null 2>&1 +if [[ $? -eq 139 ]]; then + fail "BAD: T.misc function foo(foo) dropped core" + rm -f core +fi + echo '2 10' | $AWK '{ x[NR] = $0 } # test whether $0 is NUM as well as STR @@ -138,6 +151,12 @@ function bug2(arg) { grep "can.t assign to foo" $TEMP0 >/dev/null || fail "BAD: T.misc foo bug" +# This should be a syntax error +$AWK ' +!x = y +' 2> $TEMP0 +grep "syntax error" $TEMP0 >/dev/null || fail "BAD: T.misc syntax error !x=y fails" + # This should print bbb $AWK ' BEGIN { up[1] = "a" @@ -401,6 +420,29 @@ $AWK .++. 2> $TEMP0 grep "syntax error" $TEMP0 >/dev/null || fail "BAD: T.misc syntax error .++. fails" + +# These should be syntax errors +$AWK '$' 2> $TEMP0 +grep "unexpected" $TEMP0 >/dev/null || fail "BAD: T.misc syntax error $ fails" + +$AWK '{print $' 2> $TEMP0 +grep "unexpected" $TEMP0 >/dev/null || fail "BAD: T.misc syntax error \$2 fails" + +$AWK '"' 2> $TEMP0 +grep "non-terminated" $TEMP0 >/dev/null || fail "BAD: T.misc bare quote fails" + + +# %c of 0 is explicit null byte + +echo '3' > $TEMP1 +$AWK 'BEGIN {printf("%c%c\n", 0, 0) }' | wc | $AWK '{print $3}' > $TEMP2 +cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc null byte' + +# non-terminated RE + +$AWK /xyz > $TEMP0 2>&1 +grep "non-terminated" $TEMP0 >/dev/null || fail "BAD: T.misc non-terminated RE" + # next several were infinite loops, found by brian tsang. # this is his example: @@ -420,9 +462,58 @@ grep "illegal statement" $TEMP0 >/dev/null || fail "BAD: T.misc looping syntax $AWK 'BEGIN { s { c /../ } }' > $TEMP0 2>&1 grep "illegal statement" $TEMP0 >/dev/null || fail "BAD: T.misc looping syntax error 3" +$AWK 'BEGIN {printf "%2$s %1$s\n", "a", "b"}' >$TEMP0 2>&1 +grep "'$' not permitted in awk formats" $TEMP0 >/dev/null || fail "BAD: T.misc '$' not permitted in formats" + +echo 'a +b c +de fg hi' > $TEMP0 +$AWK 'END { print NF, $0 }' $TEMP0 > $TEMP1 +awk '{ print NF, $0 }' $TEMP0| tail -1 > $TEMP2 +cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc END must preserve $0' + +echo 'fg hi' > $TEMP0 +$AWK 'END { print NF, $0 }' $TEMP0 > $TEMP1 +awk '{ print NF, $0 }' $TEMP0| tail -1 > $TEMP2 +cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc END must preserve $0' + echo '' > $TEMP0 $AWK 'END { print NF, $0 }' $TEMP0 > $TEMP1 awk '{ print NF, $0 }' $TEMP0| tail -1 > $TEMP2 cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc END must preserve $0' + +LC_NUMERIC=ru_RU.ISO8859-5 $AWK 'BEGIN { + "echo 1,200" | getline; + if ($1 == 1.2) { + printf "good "; + } else { + printf "bad "; + } + n = 2.3; + print ($1 + 0.1), (n + 0.1); +}' > $TEMP1 +echo 'good 1,3 2,4' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.misc LC_NUMERIC should change radix' + +$AWK 'function foo(q) { + return (q = q); +} +BEGIN { print foo("h"); }' > $TEMP1 +echo 'h' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.misc return tempcell' + +$AWK -v RECSIZE=8192 'BEGIN { + for (c = 0; c < 3; c++) { + a = (RECSIZE % 2 > 0 ? "5" : "55"); + while (length(a) < RECSIZE + c) { + a = a " 5"; + } + $0 = a; + print $2; + } +}' > $TEMP1 +printf '5\n5\n5\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.misc initial fields overflow' + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.nextfile b/usr/src/test/util-tests/tests/awk/tests/T.nextfile new file mode 100755 index 0000000000..48b4d01ea1 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/tests/T.nextfile @@ -0,0 +1,103 @@ +#!/bin/bash + +if [[ -z "$AWK" || -z "$WORKDIR" ]]; then + printf '$AWK and $WORKDIR must be set\n' >&2 + exit 1 +fi + +TEMP0=$WORKDIR/test.temp.0 +TEMP1=$WORKDIR/test.temp.1 + +RESULT=0 + +fail() { + echo "$1" >&2 + RESULT=1 +} + +echo T.nextfile: tests of nextfile command + +# 1st lines of some files +rm -f $TEMP0 +for i in T.* +do + sed 1q $i >> $TEMP0 +done + +$AWK ' +{ print $0; nextfile } # print first line, quit +' T.* > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.nextfile 1' + +$AWK ' # same test but in a for loop +{ print $0; + for (i = 1; i < 10; i++) + if (i == 1) + nextfile + print "nextfile for error" +} # print first line, quit +' T.* > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.nextfile 1f' + +$AWK ' # same test but in a while loop +{ print $0; + i = 1 + while (i < 10) + if (i++ == 1) + nextfile + print "nextfile while error" +} # print first line, quit +' T.* > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.nextfile 1w' + +$AWK ' # same test but in a do loop +{ print $0; + i = 1 + do { + if (i++ == 1) + nextfile # print first line, quit + } while (i < 10) + print "nextfile do error" +} +' T.* > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.nextfile 1d' + + +# 100 lines of some files +rm -f $TEMP0 +for i in T.* +do + sed 100q $i >> $TEMP0 +done + +$AWK ' +{ print } +FNR == 100 { nextfile } # print first line, quit +' T.* > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.nextfile 2' + + +> $TEMP0 # empty +$AWK ' { nextfile; print $0 }' T.* > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.nextfile 3' + +# skip weird args +rm -f $TEMP0 +for i in T.* +do + sed 1q $i >> $TEMP0 +done + +$AWK ' +{ print $0; nextfile } # print first line, quit +' T.* > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.nextfile 4' + +exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.overflow b/usr/src/test/util-tests/tests/awk/tests/T.overflow index e557c6bf4d..7192141967 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.overflow +++ b/usr/src/test/util-tests/tests/awk/tests/T.overflow @@ -93,4 +93,12 @@ BEGIN { }' > $TEMP2 cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.overflow big array' +echo x > $TEMP1 +$AWK '{print $40000000000000}' < $TEMP1 > $TEMP2 2> $TEMP0 +grep "out of range field" $TEMP0 >/dev/null || fail "BAD: T.overflow \$400000" + +rm -rf /tmp/awktestfoo* +$AWK 'BEGIN { for (i=1; i <= 1000; i++) print i >("/tmp/awktestfoo" i) }' +ls /tmp/awktestfoo* | grep '1000' >/dev/null || fail "BAD: T.overflow openfiles" + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.re b/usr/src/test/util-tests/tests/awk/tests/T.re index 54b5a60ac3..cad0756523 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.re +++ b/usr/src/test/util-tests/tests/awk/tests/T.re @@ -49,12 +49,22 @@ END { exit ecode } ' <<\!!!! + ~ a + aa + aaa + "" a ~ a ba bab !~ "" x xxxxx += ~ = + b= + b=b + !~ "" + x + xxxxx . ~ x xxx !~ "" @@ -163,6 +173,71 @@ a?b?c? ~ "" 4 7 8 +[[:lower:]] ~ a + b + z + !~ A + Z + 1 + : + [ + ] +[[:upper:]] ~ A + B + Z + !~ a + z + 1 + : + [ + ] +[[:lower:][:upper:]] ~ A + B + Z + a + b + z + !~ 1 + : + [ + ] +[[:digit:]] ~ 0 + 1 + 9 + !~ d + : + [ + ] +[[:xdigit:]] ~ 0 + 1 + 9 + a + d + f + !~ g + z + : + [ + ] +[[:cntrl:]] ~ + + + + !~ . + Z + G + [ + ] +[[:punct:]] ~ : + , + - + * + @ + !~ a + 1 + U + + x[0-9]+y ~ x0y x23y x12345y @@ -186,6 +261,11 @@ x[[-a]y ~ x[y !~ xy x[[]y x-y +x[]-a]y ~ x]y + xay + !~ xy + x[y + x-y x[]]y ~ x]y !~ xy x[]]y @@ -198,6 +278,17 @@ x[-]y ~ x-y x[^-]y ~ x+y !~ x-y xy +x[][]y ~ x[y + x]y + !~ xy + x][y + x[]y +x[z-a]y ~ xy + !~ x + y + xay + xzy + x-y [0\-9] ~ 0 - 9 @@ -260,24 +351,40 @@ x\056y ~ x.y 5 6 9 + !~ 3 + 4 + 7 + 8 [\60-2\65-6\71] ~ 0 1 2 5 6 9 + !~ 3 + 4 + 7 + 8 [\x30-\x32\x35-6\71] ~ 0 1 2 5 6 9 + !~ 3 + 4 + 7 + 8 [\x30-2\x35-6\x39] ~ 0 1 2 5 6 9 + !~ 3 + 4 + 7 + 8 \f !~ x \b !~ x \r !~ x diff --git a/usr/src/test/util-tests/tests/awk/tests/T.recache b/usr/src/test/util-tests/tests/awk/tests/T.recache new file mode 100755 index 0000000000..63e40c99b5 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/tests/T.recache @@ -0,0 +1,50 @@ +#!/bin/bash + +if [[ -z "$AWK" || -z "$WORKDIR" ]]; then + printf '$AWK and $WORKDIR must be set\n' >&2 + exit 1 +fi + +TEMP1=$WORKDIR/test.temp.1 +TEMP2=$WORKDIR/test.temp.2 + +RESULT=0 + +fail() { + echo "$1" >&2 + RESULT=1 +} + +echo T.recache: test re cache in b.c + # thanks to ross ridge for this horror + +echo b > $TEMP1 +$AWK ' +BEGIN { + # + # Fill up DFA cache with run-time REs that have all been + # used twice. + # + CACHE_SIZE=64 + for(i = 0; i < CACHE_SIZE; i++) { + for(j = 0; j < 2; j++) { + "" ~ i ""; + } + } + # + # Now evalutate an expression that uses two run-time REs + # that have never been used before. The second RE will + # push the first out of the cache while the first RE is + # still needed. + # + x = "a" + reg1 = "[Aa]" + reg2 = "A" + sub(reg1, x ~ reg2 ? "B" : "b", x) + + print x +} +' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.recache' + +exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.rt b/usr/src/test/util-tests/tests/awk/tests/T.rt new file mode 100755 index 0000000000..585f3ca3e1 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/tests/T.rt @@ -0,0 +1,99 @@ +#!/bin/bash + +if [[ -z "$AWK" || -z "$WORKDIR" ]]; then + printf '$AWK and $WORKDIR must be set\n' >&2 + exit 1 +fi + +TEMP0=$WORKDIR/test.temp.0 +TEMP1=$WORKDIR/test.temp.1 +TEMP2=$WORKDIR/test.temp.2 + +RESULT=0 + +fail() { + echo "$1" >&2 + RESULT=1 +} + +echo T.rt: tests for the RT variable + +$AWK 'BEGIN { print (RT == "" ? "true" : "false"); }' > $TEMP1 +printf 'true\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "" in BEGIN' + +printf 'a\n' > $TEMP0 +$AWK '{ print (RT == "\n" ? "true" : "false"); }' $TEMP0 > $TEMP1 +printf 'true\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "\n"' + +printf 'a' > $TEMP0 +$AWK '{ print (RT == "" ? "true" : "false"); }' $TEMP0 > $TEMP1 +printf 'true\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to ""' + +$AWK 'BEGIN { "echo hello" | getline; print (RT == "\n" ? "true" : "false"); }' > $TEMP1 +printf 'true\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "\n" (getline)' + +$AWK 'BEGIN { "printf a" | getline; print (RT == "" ? "true" : "false"); }' > $TEMP1 +printf 'true\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "" (getline)' + +$AWK 'BEGIN { "echo hello" | getline v; print (RT == "\n" ? "true" : "false"); }' > $TEMP1 +printf 'true\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "\n" (getline var)' + +$AWK 'BEGIN { + RT = "foo"; + getline < "/etc/passwd"; + print (RT == "\n" ? "true" : "false"); +}' > $TEMP1 +printf 'true\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "\n" (getline < file)' + +$AWK 'BEGIN { + RT = "foo"; + getline v < "/etc/passwd"; + print (RT == "\n" ? "true" : "false"); +}' > $TEMP1 +printf 'true\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "\n" (getline var < file)' + +# Single newline at end +printf '\n\n\n\n\na\n\na b\na b c d\nq r s t u\n\n\n\n\nv w x y z\n' > $TEMP0 +$AWK 'BEGIN { RS = ""; } { print NF, length(RT); }' $TEMP0 > $TEMP1 +printf '1 2\n11 5\n5 1\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt empty RS variable (1 newline at end)' + +# Two newlines at end +printf '\n\n\n\n\na\n\na b\na b c d\nq r s t u\n\n\n\n\nv w x y z\n\n' > $TEMP0 +$AWK 'BEGIN { RS = ""; } { print NF, length(RT); }' $TEMP0 > $TEMP1 +printf '1 2\n11 5\n5 2\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt empty RS variable (2 newlines at end)' + +# Multiple newlines at end +printf 'a\n\na b\na b c d\nq r s t u\n\n\n\n\nv w x y z\n\n\n\n' > $TEMP0 +$AWK 'BEGIN { RS = ""; } { print NF, length(RT); }' $TEMP0 > $TEMP1 +printf '1 2\n11 5\n5 4\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt empty RS variable (many newlines at end)' + +# No newlines at end +printf 'a\n\na b\na b c d\nq r s t u\n\n\n\n\nv w x y z' > $TEMP0 +$AWK 'BEGIN { RS = ""; } { print NF, length(RT); }' $TEMP0 > $TEMP1 +printf '1 2\n11 5\n5 0\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt empty RS variable (no ending newline)' + +# Non-newline separators + +printf 'a\036' > $TEMP0 +$AWK 'BEGIN { RS="\036" } { print (RT == "\036" ? "true" : "false"), length(RS); }' $TEMP0 > $TEMP1 +printf 'true 1\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "\036" (RS="\036")' + +printf 'a' > $TEMP0 +$AWK 'BEGIN { RS="\036" } { print (RT == "" ? "true" : "false"), length(RS); }' $TEMP0 > $TEMP1 +printf 'true 1\n' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.rt RT is set to "" (RS="\036")' + +exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.split b/usr/src/test/util-tests/tests/awk/tests/T.split index a22b514a75..5444561993 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.split +++ b/usr/src/test/util-tests/tests/awk/tests/T.split @@ -18,14 +18,31 @@ fail() { echo T.split: misc tests of field splitting and split command -echo a:bc:def > $TEMP0 -echo a > $TEMP1 -$AWK '{ FS = ":"; print $1 }' $TEMP0 > $TEMP2 +$AWK 'BEGIN { + # Assign string to $0, then change FS. + FS = ":"; + $0="a:bc:def"; + FS = "-"; + print FS, $1, NF; + + # Assign number to $0, then change FS. + FS = "2"; + $0=1212121; + FS="3"; + print FS, $1, NF; +}' > $TEMP1 +echo '- a 3 +3 1 4' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.split 0.1' -echo a:bc:def > $TEMP0 -echo 3 > $TEMP1 -$AWK '{ FS = ":"; print NF }' $TEMP0 > $TEMP2 +$AWK 'BEGIN { + # FS changes after getline. + FS = ":"; + "echo a:bc:def" | getline; + FS = "-"; + print FS, $1, NF; +}' > $TEMP1 +echo '- a 3' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.split 0.2' echo ' @@ -45,4 +62,164 @@ echo '0 4' > $TEMP2 diff $TEMP1 $TEMP2 || fail 'BAD: T.split 0.3' +# getline var shouldn't impact fields. + +echo 'f b a' > $TEMP0 +$AWK '{ + FS = ":"; + getline a < "/etc/passwd"; + print $1; +}' $TEMP0 > $TEMP1 +echo 'f' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.split 0.4' + +echo 'a b c d +foo +e f g h i +bar' > $TEMP0 +$AWK '{ + FS=":"; + getline v; + print $2, NF; + FS=" "; +}' $TEMP0 > $TEMP1 +echo 'b 4 +f 5' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.split 0.5' + +echo 'a.b.c=d.e.f +g.h.i=j.k.l +m.n.o=p.q.r' > $TEMP0 +echo 'b +h +n' > $TEMP1 +$AWK 'BEGIN { FS="=" } { FS="."; $0=$1; print $2; FS="="; }' $TEMP0 > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.split (record assignment 1)' + +echo 'a.b.c=d.e.f +g.h.i=j.k.l +m.n.o=p.q.r' > $TEMP0 +echo 'd.e.f +b +j.k.l +h +p.q.r +n' > $TEMP1 +$AWK 'BEGIN { FS="=" } { print $2; FS="."; $0=$1; print $2; FS="="; }' $TEMP0 > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.split (record assignment 2)' + +echo 'abc +de +f + + ' > $TEMP0 +who | sed 10q >> $TEMP0 +sed 10q /etc/passwd >> $TEMP0 + +$AWK ' +{ n = split($0, x, "") + m = length($0) + if (m != n) print "error 1", NR + s = "" + for (i = 1; i <= m; i++) + s = s x[i] + if (s != $0) print "error 2", NR + print s +}' $TEMP0 > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.split 1' + +# assumes same test.temp.0! bad design + + +$AWK ' +{ n = split($0, x, //) + m = length($0) + if (m != n) print "error 1", NR + s = "" + for (i = 1; i <= m; i++) + s = s x[i] + if (s != $0) print "error 2", NR + print s +}' $TEMP0 > $TEMP1 + +diff $TEMP0 $TEMP1 || fail 'BAD: T.split //' + +$AWK ' +BEGIN { FS = "" } +{ n = split($0, x) # will be split with FS + m = length($0) + if (m != n) print "error 1", NR + s = "" + for (i = 1; i <= m; i++) + s = s x[i] + if (s != $0) print "error 2", NR + print s +}' $TEMP0 > $TEMP2 + +diff $TEMP0 $TEMP2 || fail 'BAD: T.split 2' + +# assumes same test.temp.0! + +$AWK ' +BEGIN { FS = "" } +{ n = NF + m = length($0) + if (m != n) print "error 1", NR + s = "" + for (i = 1; i <= m; i++) + s = s $i + if (s != $0) print "error 2", NR + print s +}' $TEMP0 > $TEMP2 + +diff $TEMP0 $TEMP2 || fail 'BAD: T.split 3' + + +$AWK ' +{ n = split( $0, temp, /^@@@ +/ ) + print n +}' > $TEMP1 <<XXX +@@@ xxx +@@@ xxx +@@@ xxx +XXX +echo '2 +2 +2' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.split 4' + +rm -f $WORKDIR/test.temp* + +echo ' +a +bc +def' > $TEMP0 +$AWK ' +{ print split($0, x, "") +}' $TEMP0 > $TEMP1 +echo '0 +1 +2 +3' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.split null 3rd arg' + +rm -f $WORKDIR/test.temp* +$AWK 'BEGIN { + a[1]="a b" + print split(a[1],a),a[1],a[2] +}' > $TEMP1 + +echo '2 a b' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.split(a[1],a)' + +$AWK 'BEGIN { + a = "cat\n\n\ndog"; + split(a, b, "[\r\n]+"); + print b[1], b[2]; +}' > $TEMP1 +echo 'cat dog' > $TEMP2 +diff $TEMP1 $TEMP2 || fail 'BAD: T.split(a, b, "[\r\n]+")' + + exit $RESULT diff --git a/usr/src/test/util-tests/tests/awk/tests/T.sub b/usr/src/test/util-tests/tests/awk/tests/T.sub index a954b7a054..117980724b 100755 --- a/usr/src/test/util-tests/tests/awk/tests/T.sub +++ b/usr/src/test/util-tests/tests/awk/tests/T.sub @@ -200,6 +200,11 @@ a?b?c? x "" x x pq xyzpq xyzpxyzqxyz "" xyz xyz +"" <&> abc <>abc <>a<>b<>c<> fixed 2/07, we think +"" <\&> abc <&>abc <&>a<&>b<&>c<&> +"" <&&> abc <>abc <>a<>b<>c<> +"" <&> "" <> <> + d?abc <&> abc <abc> <abc> d? <&> abc <>abc <>a<>b<>c<> diff --git a/usr/src/test/util-tests/tests/awk/tests/lilly.ok b/usr/src/test/util-tests/tests/awk/tests/lilly.ok new file mode 100644 index 0000000000..7583e9bba4 --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/tests/lilly.ok @@ -0,0 +1,974 @@ +### 1 BEGIN{foo=6;print foo/2} +3 +### 2 BEGIN{foo=10;foo/=2;print foo} +5 +### 3 /=/ {print $0} +foo=bar +foo==bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo=bar=fribble +=foo=bar +### 4 /==/ {print $0} +foo==bar +### 5 /\+=/ {print $0} +foo+=bar +### 6 /\*=/ {print $0} +foo*=bar +### 7 /-=/ {print $0} +foo-=bar +### 8 /\/=/ {print $0} +foo/=bar +### 9 /%=/ {print $0} +foo%=bar +### 10 /^=/ {print $0} +=foo=bar +### 11 /!=/ {print $0} +foo!=bar +### 12 /<=/ {print $0} +foo<=bar +### 13 />=/ {print $0} +foo>=bar +### 14 !/=/ {print $0} +foo+bar +foo bar +foo/bar +### 15 !/==/ {print $0} +foo=bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 16 !/\+=/ {print $0} +foo=bar +foo==bar +foo+bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 17 !/\*=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 18 !/-=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 19 !/\/=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 20 !/%=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 21 !/^=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +### 22 !/!=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 23 !/<=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 24 !/>=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 25 $0~/=/ {print $0} +foo=bar +foo==bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo=bar=fribble +=foo=bar +### 26 $0~/==/ {print $0} +foo==bar +### 27 $0~/\+=/ {print $0} +foo+=bar +### 28 $0~/\*=/ {print $0} +foo*=bar +### 29 $0~/-=/ {print $0} +foo-=bar +### 30 $0~/\/=/ {print $0} +foo/=bar +### 31 $0~/%=/ {print $0} +foo%=bar +### 32 $0~/^=/ {print $0} +=foo=bar +### 33 $0~/!=/ {print $0} +foo!=bar +### 34 $0~/<=/ {print $0} +foo<=bar +### 35 $0~/>=/ {print $0} +foo>=bar +### 36 $0!~/=/ {print $0} +foo+bar +foo bar +foo/bar +### 37 $0!~/==/ {print $0} +foo=bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 38 $0!~/\+=/ {print $0} +foo=bar +foo==bar +foo+bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 39 $0!~/\*=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 40 $0!~/-=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 41 $0!~/%=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 42 $0!~/^=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +### 43 $0!~/!=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 44 $0!~/<=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 45 $0!~/>=/ {print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 46 {if(match($0,/=/))print $0} +foo=bar +foo==bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo=bar=fribble +=foo=bar +### 47 {if(match($0,/\=/))print $0} +foo=bar +foo==bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo=bar=fribble +=foo=bar +### 48 {if(match($0,/==/))print $0} +foo==bar +### 49 {if(match($0,/\+=/))print $0} +foo+=bar +### 50 {if(match($0,/\*=/))print $0} +foo*=bar +### 51 {if(match($0,/-=/))print $0} +foo-=bar +### 52 {if(match($0,/%=/))print $0} +foo%=bar +### 53 {if(match($0,/^=/))print $0} +=foo=bar +### 54 {if(match($0,/!=/))print $0} +foo!=bar +### 55 {if(match($0,/<=/))print $0} +foo<=bar +### 56 {if(match($0,/>=/))print $0} +foo>=bar +### 57 {if(!match($0,/=/))print $0} +foo+bar +foo bar +foo/bar +### 58 {if(!match($0,/==/))print $0} +foo=bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 59 {if(!match($0,/\+=/))print $0} +foo=bar +foo==bar +foo+bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 60 {if(!match($0,/\*=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 61 {if(!match($0,/-=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 62 {if(!match($0,/%=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 63 {if(!match($0,/^=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +### 64 {if(!match($0,/!=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 65 {if(!match($0,/<=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 66 {if(!match($0,/>=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 67 {if(split($0,foo,/=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 68 {if(split($0,foo,/\=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 69 {if(split($0,foo,/==/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 70 {if(split($0,foo,/\+=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 71 {if(split($0,foo,/\*=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 72 {if(split($0,foo,/-=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 73 {if(split($0,foo,/\/=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 74 {if(split($0,foo,/%=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 75 {if(split($0,foo,/^=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 76 {if(split($0,foo,/!=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 77 {if(split($0,foo,/<=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 78 {if(split($0,foo,/>=/))print $0} +foo=bar +foo==bar +foo+bar +foo+=bar +foo-=bar +foo*=bar +foo/=bar +foo^=bar +foo%=bar +foo!=bar +foo<=bar +foo>=bar +foo bar +foo/bar +foo=bar=fribble +=foo=bar +### 79 {if(sub(/=/,"#"))print $0} +foo#bar +foo#=bar +foo+#bar +foo-#bar +foo*#bar +foo/#bar +foo^#bar +foo%#bar +foo!#bar +foo<#bar +foo>#bar +foo#bar=fribble +#foo=bar +### 80 {if(sub(/\=/,"#"))print $0} +foo#bar +foo#=bar +foo+#bar +foo-#bar +foo*#bar +foo/#bar +foo^#bar +foo%#bar +foo!#bar +foo<#bar +foo>#bar +foo#bar=fribble +#foo=bar +### 81 {if(sub(/==/,"#"))print $0} +foo#bar +### 82 {if(sub(/\+=/,"#"))print $0} +foo#bar +### 83 {if(sub(/\*=/,"#"))print $0} +foo#bar +### 84 {if(sub(/-=/,"#"))print $0} +foo#bar +### 85 {if(sub(/\/=/,"#"))print $0} +foo#bar +### 86 {if(sub(/%=/,"#"))print $0} +foo#bar +### 87 {if(sub(/^=/,"#"))print $0} +#foo=bar +### 88 {if(sub(/!=/,"#"))print $0} +foo#bar +### 89 {if(sub(/<=/,"#"))print $0} +foo#bar +### 90 {if(sub(/>=/,"#"))print $0} +foo#bar +### 91 {if(gsub(/=/,"#"))print $0} +foo#bar +foo##bar +foo+#bar +foo-#bar +foo*#bar +foo/#bar +foo^#bar +foo%#bar +foo!#bar +foo<#bar +foo>#bar +foo#bar#fribble +#foo#bar +### 92 {if(gsub(/\=/,"#"))print $0} +foo#bar +foo##bar +foo+#bar +foo-#bar +foo*#bar +foo/#bar +foo^#bar +foo%#bar +foo!#bar +foo<#bar +foo>#bar +foo#bar#fribble +#foo#bar +### 93 {if(gsub(/==/,"#"))print $0} +foo#bar +### 94 {if(gsub(/\+=/,"#"))print $0} +foo#bar +### 95 {if(gsub(/\*=/,"#"))print $0} +foo#bar +### 96 {if(gsub(/-=/,"#"))print $0} +foo#bar +### 97 {if(gsub(/\/=/,"#"))print $0} +foo#bar +### 98 {if(gsub(/%=/,"#"))print $0} +foo#bar +### 99 {if(gsub(/^=/,"#"))print $0} +#foo=bar +### 100 {if(gsub(/!=/,"#"))print $0} +foo#bar +### 101 {if(gsub(/<=/,"#"))print $0} +foo#bar +### 102 {if(gsub(/>=/,"#"))print $0} +foo#bar +### 103 {if(sub(/=/,"#",$0))print $0} +foo#bar +foo#=bar +foo+#bar +foo-#bar +foo*#bar +foo/#bar +foo^#bar +foo%#bar +foo!#bar +foo<#bar +foo>#bar +foo#bar=fribble +#foo=bar +### 104 {if(sub(/\=/,"#",$0))print $0} +foo#bar +foo#=bar +foo+#bar +foo-#bar +foo*#bar +foo/#bar +foo^#bar +foo%#bar +foo!#bar +foo<#bar +foo>#bar +foo#bar=fribble +#foo=bar +### 105 {if(sub(/==/,"#",$0))print $0} +foo#bar +### 106 {if(sub(/\+=/,"#",$0))print $0} +foo#bar +### 107 {if(sub(/\*=/,"#",$0))print $0} +foo#bar +### 108 {if(sub(/-=/,"#",$0))print $0} +foo#bar +### 109 {if(sub(/\/=/,"#",$0))print $0} +foo#bar +### 110 {if(sub(/%=/,"#",$0))print $0} +foo#bar +### 111 {if(sub(/^=/,"#",$0))print $0} +#foo=bar +### 112 {if(sub(/!=/,"#",$0))print $0} +foo#bar +### 113 {if(sub(/<=/,"#",$0))print $0} +foo#bar +### 114 {if(sub(/>=/,"#",$0))print $0} +foo#bar +### 115 {if(sub(/=/,"#",$0))print $0} +foo#bar +foo#=bar +foo+#bar +foo-#bar +foo*#bar +foo/#bar +foo^#bar +foo%#bar +foo!#bar +foo<#bar +foo>#bar +foo#bar=fribble +#foo=bar +### 116 {if(gsub(/\=/,"#",$0))print $0} +foo#bar +foo##bar +foo+#bar +foo-#bar +foo*#bar +foo/#bar +foo^#bar +foo%#bar +foo!#bar +foo<#bar +foo>#bar +foo#bar#fribble +#foo#bar +### 117 {if(gsub(/==/,"#",$0))print $0} +foo#bar +### 118 {if(gsub(/\+=/,"#",$0))print $0} +foo#bar +### 119 {if(gsub(/\*=/,"#",$0))print $0} +foo#bar +### 120 {if(gsub(/-=/,"#",$0))print $0} +foo#bar +### 121 {if(gsub(/\/=/,"#",$0))print $0} +foo#bar +### 122 {if(gsub(/%=/,"#",$0))print $0} +foo#bar +### 123 {if(gsub(/^=/,"#",$0))print $0} +#foo=bar +### 124 {if(gsub(/!=/,"#",$0))print $0} +foo#bar +### 125 {if(gsub(/<=/,"#",$0))print $0} +foo#bar +### 126 {if(gsub(/>=/,"#",$0))print $0} +foo#bar diff --git a/usr/src/test/util-tests/tests/awk/tests/lilly.progs b/usr/src/test/util-tests/tests/awk/tests/lilly.progs new file mode 100644 index 0000000000..ba669c92ac --- /dev/null +++ b/usr/src/test/util-tests/tests/awk/tests/lilly.progs @@ -0,0 +1,126 @@ +BEGIN{foo=6;print foo/2} +BEGIN{foo=10;foo/=2;print foo} +/=/ {print $0} +/==/ {print $0} +/\+=/ {print $0} +/\*=/ {print $0} +/-=/ {print $0} +/\/=/ {print $0} +/%=/ {print $0} +/^=/ {print $0} +/!=/ {print $0} +/<=/ {print $0} +/>=/ {print $0} +!/=/ {print $0} +!/==/ {print $0} +!/\+=/ {print $0} +!/\*=/ {print $0} +!/-=/ {print $0} +!/\/=/ {print $0} +!/%=/ {print $0} +!/^=/ {print $0} +!/!=/ {print $0} +!/<=/ {print $0} +!/>=/ {print $0} +$0~/=/ {print $0} +$0~/==/ {print $0} +$0~/\+=/ {print $0} +$0~/\*=/ {print $0} +$0~/-=/ {print $0} +$0~/\/=/ {print $0} +$0~/%=/ {print $0} +$0~/^=/ {print $0} +$0~/!=/ {print $0} +$0~/<=/ {print $0} +$0~/>=/ {print $0} +$0!~/=/ {print $0} +$0!~/==/ {print $0} +$0!~/\+=/ {print $0} +$0!~/\*=/ {print $0} +$0!~/-=/ {print $0} +$0!~/%=/ {print $0} +$0!~/^=/ {print $0} +$0!~/!=/ {print $0} +$0!~/<=/ {print $0} +$0!~/>=/ {print $0} +{if(match($0,/=/))print $0} +{if(match($0,/\=/))print $0} +{if(match($0,/==/))print $0} +{if(match($0,/\+=/))print $0} +{if(match($0,/\*=/))print $0} +{if(match($0,/-=/))print $0} +{if(match($0,/%=/))print $0} +{if(match($0,/^=/))print $0} +{if(match($0,/!=/))print $0} +{if(match($0,/<=/))print $0} +{if(match($0,/>=/))print $0} +{if(!match($0,/=/))print $0} +{if(!match($0,/==/))print $0} +{if(!match($0,/\+=/))print $0} +{if(!match($0,/\*=/))print $0} +{if(!match($0,/-=/))print $0} +{if(!match($0,/%=/))print $0} +{if(!match($0,/^=/))print $0} +{if(!match($0,/!=/))print $0} +{if(!match($0,/<=/))print $0} +{if(!match($0,/>=/))print $0} +{if(split($0,foo,/=/))print $0} +{if(split($0,foo,/\=/))print $0} +{if(split($0,foo,/==/))print $0} +{if(split($0,foo,/\+=/))print $0} +{if(split($0,foo,/\*=/))print $0} +{if(split($0,foo,/-=/))print $0} +{if(split($0,foo,/\/=/))print $0} +{if(split($0,foo,/%=/))print $0} +{if(split($0,foo,/^=/))print $0} +{if(split($0,foo,/!=/))print $0} +{if(split($0,foo,/<=/))print $0} +{if(split($0,foo,/>=/))print $0} +{if(sub(/=/,"#"))print $0} +{if(sub(/\=/,"#"))print $0} +{if(sub(/==/,"#"))print $0} +{if(sub(/\+=/,"#"))print $0} +{if(sub(/\*=/,"#"))print $0} +{if(sub(/-=/,"#"))print $0} +{if(sub(/\/=/,"#"))print $0} +{if(sub(/%=/,"#"))print $0} +{if(sub(/^=/,"#"))print $0} +{if(sub(/!=/,"#"))print $0} +{if(sub(/<=/,"#"))print $0} +{if(sub(/>=/,"#"))print $0} +{if(gsub(/=/,"#"))print $0} +{if(gsub(/\=/,"#"))print $0} +{if(gsub(/==/,"#"))print $0} +{if(gsub(/\+=/,"#"))print $0} +{if(gsub(/\*=/,"#"))print $0} +{if(gsub(/-=/,"#"))print $0} +{if(gsub(/\/=/,"#"))print $0} +{if(gsub(/%=/,"#"))print $0} +{if(gsub(/^=/,"#"))print $0} +{if(gsub(/!=/,"#"))print $0} +{if(gsub(/<=/,"#"))print $0} +{if(gsub(/>=/,"#"))print $0} +{if(sub(/=/,"#",$0))print $0} +{if(sub(/\=/,"#",$0))print $0} +{if(sub(/==/,"#",$0))print $0} +{if(sub(/\+=/,"#",$0))print $0} +{if(sub(/\*=/,"#",$0))print $0} +{if(sub(/-=/,"#",$0))print $0} +{if(sub(/\/=/,"#",$0))print $0} +{if(sub(/%=/,"#",$0))print $0} +{if(sub(/^=/,"#",$0))print $0} +{if(sub(/!=/,"#",$0))print $0} +{if(sub(/<=/,"#",$0))print $0} +{if(sub(/>=/,"#",$0))print $0} +{if(sub(/=/,"#",$0))print $0} +{if(gsub(/\=/,"#",$0))print $0} +{if(gsub(/==/,"#",$0))print $0} +{if(gsub(/\+=/,"#",$0))print $0} +{if(gsub(/\*=/,"#",$0))print $0} +{if(gsub(/-=/,"#",$0))print $0} +{if(gsub(/\/=/,"#",$0))print $0} +{if(gsub(/%=/,"#",$0))print $0} +{if(gsub(/^=/,"#",$0))print $0} +{if(gsub(/!=/,"#",$0))print $0} +{if(gsub(/<=/,"#",$0))print $0} +{if(gsub(/>=/,"#",$0))print $0} |