summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/awk/DIVERGENCES5
-rw-r--r--usr/src/cmd/awk/Makefile2
-rw-r--r--usr/src/cmd/awk/awk.g.y109
-rw-r--r--usr/src/cmd/awk/awk.h57
-rw-r--r--usr/src/cmd/awk/b.c273
-rw-r--r--usr/src/cmd/awk/lex.c4
-rw-r--r--usr/src/cmd/awk/lib.c532
-rw-r--r--usr/src/cmd/awk/main.c77
-rw-r--r--usr/src/cmd/awk/maketab.c2
-rw-r--r--usr/src/cmd/awk/parse.c7
-rw-r--r--usr/src/cmd/awk/run.c653
-rw-r--r--usr/src/cmd/awk/tran.c288
-rw-r--r--usr/src/man/man1/nawk.1139
-rw-r--r--usr/src/pkg/manifests/system-test-utiltest.mf118
-rw-r--r--usr/src/test/util-tests/tests/awk/Makefile8
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/a-format.awk3
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/a-format.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/concat-assign-same.awk4
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/concat-assign-same.ok2
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/decr-NF.awk11
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/decr-NF.ok5
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/fs-overflow.awk13
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/fs-overflow.ok3
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/negative-nf.awk1
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/negative-nf.ok3
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/nf-self-assign.awk6
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/nf-self-assign.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-fs.awk5
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-fs.ok3
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-output-seps.awk8
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-output-seps.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-rs.awk6
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-rs.ok4
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-subsep.awk5
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/numeric-subsep.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/ofs-rebuild.awk17
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/ofs-rebuild.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/space.awk22
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/space.ok16
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/split-fs-from-array.awk5
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/split-fs-from-array.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/string-conv.awk13
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/string-conv.ok4
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/subsep-overflow.awk24
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/subsep-overflow.ok5
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/system-status.awk19
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/system-status.ok3
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/unary-plus.awk4
-rw-r--r--usr/src/test/util-tests/tests/awk/bugs-fixed/unary-plus.ok2
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/awk/t.delete0 (renamed from usr/src/test/util-tests/tests/awk/examples/awk/t.delete)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/awk/t.for38
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/awk/t.getline1 (renamed from usr/src/test/util-tests/tests/awk/examples/awk/t.getline)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/awk/t.redir1 (renamed from usr/src/test/util-tests/tests/awk/examples/awk/t.redir)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/awk/t.split1 (renamed from usr/src/test/util-tests/tests/awk/examples/awk/t.split)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/awk/t.split2a4
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/awk/t.split89
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/awk/t.sub0 (renamed from usr/src/test/util-tests/tests/awk/examples/awk/t.sub)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.NF498
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.arith4
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.be2
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.delete0 (renamed from usr/src/test/util-tests/tests/awk/examples/out/t.delete)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.for31290
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.getline1 (renamed from usr/src/test/util-tests/tests/awk/examples/out/t.getline)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.redir1 (renamed from usr/src/test/util-tests/tests/awk/examples/out/t.redir)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.split1 (renamed from usr/src/test/util-tests/tests/awk/examples/out/t.split)0
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.split2a1
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.split8725
-rw-r--r--usr/src/test/util-tests/tests/awk/examples/out/t.sub0 (renamed from usr/src/test/util-tests/tests/awk/examples/out/t.sub)0
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/arynocls.awk102
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/arynocls.data30
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/arynocls.ok4
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/back89.awk1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/back89.in2
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/back89.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/closebad.awk7
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/closebad.ok3
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/clsflnam.awk12
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/clsflnam.in3
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/clsflnam.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/concat3.awk1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/concat3.ok2
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/convfmt.awk10
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/convfmt.ok3
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/datanonl.awk3
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/datanonl.in1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/datanonl.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/delarprm.awk50
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/delarprm.ok0
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/fflush.ok15
-rwxr-xr-xusr/src/test/util-tests/tests/awk/gnu/fflush.sh25
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/fordel.awk65
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/fordel.ok0
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/gsubtst5.awk97
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/gsubtst5.in1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/gsubtst5.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/longwrds.awk27
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/longwrds.in200
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/longwrds.ok21
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/ofmta.awk30
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/ofmta.ok7
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/ofmtbig.awk126
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/ofmtbig.in3
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/ofmtbig.ok2
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/pipeio2.awk72
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/pipeio2.in8
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/pipeio2.ok14
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/rebrackloc.awk47
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/rebrackloc.in3
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/rebrackloc.ok18
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/regexprange.awk14
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/regexprange.ok52
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/splitarr.awk5
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/splitarr.ok1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/status-close.awk14
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/status-close.ok6
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/subsepnm.awk1
-rw-r--r--usr/src/test/util-tests/tests/awk/gnu/subsepnm.ok1
-rwxr-xr-xusr/src/test/util-tests/tests/awk/runtests.sh28
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/aryprm1.ok4
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/aryprm2.ok8
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/aryprm3.ok4
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/delfunc.ok2
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/funsmnam.awk6
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/funsmnam.ok3
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/nastyparm.ok4
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/nfneg.awk1
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/nfneg.ok2
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/paramdup.awk8
-rw-r--r--usr/src/test/util-tests/tests/awk/syn/paramdup.ok5
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.argv28
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.builtin10
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.close26
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.clv48
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.delete39
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.errmsg42
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.expr28
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.flags5
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.func6
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.gawk11
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.getline17
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.main5
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.misc76
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.nextfile103
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.overflow8
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.re101
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.recache50
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.split114
-rwxr-xr-xusr/src/test/util-tests/tests/awk/tests/T.sub5
148 files changed, 5914 insertions, 1033 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 22570a3ffd..b958093755 100644
--- a/usr/src/cmd/awk/Makefile
+++ b/usr/src/cmd/awk/Makefile
@@ -55,7 +55,7 @@ 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 y.tab.h
diff --git a/usr/src/cmd/awk/awk.g.y b/usr/src/cmd/awk/awk.g.y
index 872f452a12..3b5efb3d7d 100644
--- a/usr/src/cmd/awk/awk.g.y
+++ b/usr/src/cmd/awk/awk.g.y
@@ -55,11 +55,14 @@
%{
#include "awk.h"
+
+void checkdup(Node *list, Cell *item);
int yywrap(void) { return(1); }
Node *beginloc = NULL;
Node *endloc = NULL;
-int infunc = 0; /* = 1 if in arglist or body of func */
+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 *);
@@ -80,10 +83,10 @@ static Node *notnull(Node *);
%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> 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
@@ -92,13 +95,14 @@ static Node *notnull(Node *);
%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
@@ -115,7 +119,7 @@ static Node *notnull(Node *);
%left CAT
%left '+' '-'
%left '*' '/' '%'
-%left NOT UMINUS
+%left NOT UMINUS UPLUS
%right POWER
%right DECR INCR
%left INDIRECT
@@ -150,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:
@@ -203,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; }
@@ -232,8 +236,6 @@ ppattern:
{ $$ = 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))
@@ -243,8 +245,7 @@ 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
;
@@ -256,8 +257,6 @@ pattern:
{ $$ = op2(BOR, notnull($1), notnull($3)); }
| pattern and pattern %prec AND
{ $$ = op2(AND, notnull($1), notnull($3)); }
- | NOT pattern
- { $$ = op1(NOT, op2(NE,$2,celltonode(lookup("$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); }
@@ -272,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
;
@@ -308,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; }
;
@@ -317,12 +325,18 @@ 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; SYNTAX("you can only delete array[element]"); $$ = stat1(DELETE, $2); }
+ | DELETE varname { $$ = stat2(DELETE, makearr($2), 0); }
| pattern { $$ = exptostat($1); }
| error { yyclearin; SYNTAX("illegal statement"); }
;
@@ -333,11 +347,12 @@ st:
;
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
@@ -347,10 +362,13 @@ stmt:
| NEXT st { if (infunc)
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; }
;
@@ -372,12 +390,14 @@ term:
| term '%' term { $$ = op2(MOD, $1, $3); }
| term POWER term { $$ = op2(POWER, $1, $3); }
| '-' term %prec UMINUS { $$ = op1(UMINUS, $2); }
- | '+' term %prec UMINUS { $$ = $2; }
+ | '+' 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); }
@@ -439,7 +459,9 @@ var:
varlist:
/* nothing */ { arglist = $$ = 0; }
| VAR { arglist = $$ = celltonode($1,CVAR); }
- | varlist comma VAR { arglist = $$ = linkum($1,celltonode($3,CVAR)); }
+ | varlist comma VAR {
+ checkdup($1, $3);
+ arglist = $$ = linkum($1,celltonode($3,CVAR)); }
;
varname:
@@ -463,6 +485,7 @@ setfname(Cell *p)
else if (isfcn(p))
SYNTAX("you can't define function %s more than once", p->nval);
curfname = p->nval;
+ p->tval |= FCN;
}
static int
@@ -488,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 80e894ea6d..b1db39fadb 100644
--- a/usr/src/cmd/awk/awk.h
+++ b/usr/src/cmd/awk/awk.h
@@ -53,6 +53,7 @@
#ifndef AWK_H
#define AWK_H
+#include <assert.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
@@ -80,9 +81,12 @@ typedef unsigned char uschar;
#endif
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) \
@@ -118,8 +122,10 @@ typedef struct Cell {
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;
@@ -138,9 +144,15 @@ 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 *rstartloc; /* RSTART */
extern Cell *rlengthloc; /* RLENGTH */
+extern Cell *subseploc; /* SUBSEP */
+extern Cell *symtabloc; /* SYMTAB */
/* Cell.tval values: */
#define NUM 01 /* number value is valid */
@@ -151,24 +163,19 @@ 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);
extern Awkfloat getfval(Cell *);
-extern Awkfloat r_getfval(Cell *);
extern char *setsval(Cell *, const char *);
extern char *getsval(Cell *);
-extern char *r_getsval(Cell *);
+extern char *getpssval(Cell *); /* for print */
extern char *tostring(const char *);
extern char *tokname(int);
extern char *qstring(const char *, 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))
-
/* function types */
#define FLENGTH 1
#define FSQRT 2
@@ -183,6 +190,7 @@ extern char *qstring(const char *, 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 */
@@ -226,6 +234,7 @@ extern Node *nullnode;
#define JBREAK 23
#define JCONT 24
#define JRET 25
+#define JNEXTFILE 26
/* node types */
#define NVALUE 1
@@ -256,7 +265,7 @@ 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)
@@ -266,13 +275,22 @@ extern Node *makearr(Node *);
#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;
@@ -319,6 +337,7 @@ 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 int isclvar(const char *);
extern int is_number(const char *);
@@ -330,22 +349,21 @@ extern void syminit(void);
extern void yyerror(const char *);
extern void fldbld(void);
extern void recbld(void);
-extern int getrec(char **, 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, const char *);
extern void fpecatch(int);
-extern void init_buf(char **, size_t *, size_t);
-extern void adjust_buf(char **, size_t);
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 char *lexprog;
extern int compile_time;
-extern char radixpoint;
extern char *cursource(void);
extern int pgetc(void);
@@ -361,6 +379,7 @@ extern Awkfloat *ARGC;
/* run.c */
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);
diff --git a/usr/src/cmd/awk/b.c b/usr/src/cmd/awk/b.c
index d44372393b..adca0cb633 100644
--- a/usr/src/cmd/awk/b.c
+++ b/usr/src/cmd/awk/b.c
@@ -64,25 +64,27 @@
#define MAXLIN (3 * LINE_MAX)
#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;
@@ -104,7 +106,8 @@ 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(const char *);
@@ -117,20 +120,29 @@ 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((const char *)fatab[i]->restr, s) == 0) {
- fatab[i]->use++;
+ 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);
}
@@ -143,7 +155,7 @@ makedfa(const char *s, int anchor) /* returns dfa for reg expr s */
}
freefa(fatab[nuse]);
fatab[nuse] = pfa;
- pfa->use = 1;
+ pfa->use = now++;
return (pfa);
}
@@ -221,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));
@@ -246,6 +259,7 @@ static void
freetr(Node *p) /* free parse tree */
{
switch (type(p)) {
+ ELEAF
LEAF
xfree(p);
break;
@@ -265,6 +279,44 @@ freetr(Node *p) /* free parse tree */
}
}
+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 */
@@ -286,7 +338,9 @@ quoted(uschar **pp)
c = '\b';
else if (c == '\\')
c = '\\';
- else if (isoctdigit(c)) { /* \d \dd \ddd */
+ 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';
@@ -350,11 +404,11 @@ cclenter(const char *argp) /* add a character class */
*bp = '\0';
dprintf(("cclenter: in = |%s|, out = |%s|\n", op, buf));
xfree(op);
- return (char *)tostring((char *)buf);
+ return ((char *)tostring((char *)buf));
}
static void
-overflo(char *s)
+overflo(const char *s)
{
FATAL("regular expression too big: %.30s...", gettext((char *)s));
}
@@ -367,16 +421,20 @@ cfoll(fa *f, Node *v)
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)
@@ -403,15 +461,25 @@ cfoll(fa *f, Node *v)
static int
first(Node *p)
{
- 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 && (*(uschar *)right(p)) == '\0')
+ if (type(p) == CCL && (*(char *)right(p)) == '\0')
return (0); /* empty CCL */
else
return (1);
@@ -550,7 +618,7 @@ pmatch(fa *f, const char *p0) /* longest match, for sub */
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++)
@@ -608,7 +676,7 @@ nematch(fa *f, const char *p0) /* non-empty match, for sub */
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++)
@@ -626,11 +694,11 @@ nematch(fa *f, const char *p0) /* non-empty match, for sub */
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(const char *p)
{
- /* parses regular expression pointed to by p */
- /* uses relex() to scan regular expression */
Node *np;
dprintf(("reparse <%s>\n", p));
@@ -638,8 +706,9 @@ reparse(const char *p)
/* prestr points to string to be parsed */
lastre = prestr = (uschar *)p;
rtok = relex();
+ /* GNU compatibility: an empty regexp matches anything */
if (rtok == '\0') {
- FATAL("empty regular expression");
+ return (op2(EMPTYRE, NIL, NIL));
}
np = regexp();
if (rtok != '\0')
@@ -667,6 +736,9 @@ primary(void)
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)));
@@ -715,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);
@@ -750,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 */
{
- int c;
- uschar *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;
@@ -776,39 +891,76 @@ relex(void) /* lexical analyzer for reparse */
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((char **)&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') {
FATAL("nonterminated character class "
"%.20s...", lastre);
}
- cbuf[clen++] = c;
- } else if (clen == 0) {
- cbuf[clen++] = c;
+ *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;
+ }
+
+ 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 = (uschar *)tostring((char *)cbuf);
- free(cbuf);
+ *bp++ = '\0';
+ rlxstr = (uschar *)tostring((char *)buf);
if (cflag == 0)
return (CCL);
else
return (NCCL);
- } else if (c == '\n') {
- FATAL("newline in character class %s...",
- lastre);
- } else if (c == '\0') {
- FATAL("nonterminated character class %s",
- lastre);
} else
- cbuf[clen++] = c;
+ *bp++ = c;
}
/*NOTREACHED*/
}
@@ -821,6 +973,10 @@ cgoto(fa *f, int s, int c)
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;
@@ -828,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, (char *)f->re[p[i]].lval) ||
- k == NCCL &&
- !member(c, (char *)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;
@@ -901,8 +1061,11 @@ freefa(fa *f) /* free a finite automaton */
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
index 78954e3a49..ad0575f3cb 100644
--- a/usr/src/cmd/awk/lex.c
+++ b/usr/src/cmd/awk/lex.c
@@ -57,6 +57,7 @@ Keyword keywords[] = { /* keep sorted: binary searched */
{ "else", ELSE, ELSE },
{ "exit", EXIT, EXIT },
{ "exp", FEXP, BLTIN },
+ { "fflush", FFLUSH, BLTIN },
{ "for", FOR, FOR },
{ "func", FUNC, FUNC },
{ "function", FUNC, FUNC },
@@ -70,6 +71,7 @@ Keyword keywords[] = { /* keep sorted: binary searched */
{ "log", FLOG, BLTIN },
{ "match", MATCHFCN, MATCHFCN },
{ "next", NEXT, NEXT },
+ { "nextfile", NEXTFILE, NEXTFILE },
{ "print", PRINT, PRINT },
{ "printf", PRINTF, PRINTF },
{ "rand", FRAND, BLTIN },
@@ -511,6 +513,8 @@ word(char *w)
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)
diff --git a/usr/src/cmd/awk/lib.c b/usr/src/cmd/awk/lib.c
index 1f1649549c..ae60fde3f1 100644
--- a/usr/src/cmd/awk/lib.c
+++ b/usr/src/cmd/awk/lib.c
@@ -51,6 +51,9 @@
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
+/* Copyright (c) Lucent Technologies 1997 */
+/* All Rights Reserved */
+
#include <stdio.h>
#include <string.h>
#include <ctype.h>
@@ -63,24 +66,25 @@
static FILE *infile = NULL;
static char *file = "";
char *record;
-size_t recsize;
+size_t recsize = RECSIZE;
static char *fields;
-static size_t fieldssize = LINE_INCR;
-
-int donefld; /* 1 = implies rec broken into fields */
-int donerec; /* 1 = record is valid (no flds have changed) */
+static size_t fieldssize = 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 */
+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 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(const char *, const char *);
@@ -88,6 +92,36 @@ 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)
{
@@ -95,21 +129,34 @@ initgetrec(void)
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 */
}
+static int firsttime = 1;
+
+/*
+ * get next input record
+ * note: cares whether buf == record
+ */
int
-getrec(char **bufp, size_t *bufsizep)
+getrec(char **pbuf, size_t *pbufsize, int isrecord)
{
int c;
- static int firsttime = 1;
- char *buf, *nbuf;
- size_t len;
+ char *buf = *pbuf;
+ uschar saveb0;
+ size_t bufsize = *pbufsize, savebufsize = bufsize;
if (firsttime) {
firsttime = 0;
@@ -117,17 +164,23 @@ getrec(char **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;
+ }
+ 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;
@@ -136,22 +189,17 @@ getrec(char **bufp, size_t *bufsizep)
dprintf(("opening file %s\n", file));
if (*file == '-' && *(file+1) == '\0')
infile = stdin;
- else if ((infile = fopen(file, "r")) == NULL)
+ 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 (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 =
@@ -161,6 +209,8 @@ getrec(char **bufp, size_t *bufsizep)
}
(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 */
@@ -169,19 +219,33 @@ getrec(char **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++;
+}
+
int
-readrec(char **bufp, size_t *sizep, FILE *inf) /* read one record into buf */
+readrec(char **pbuf, size_t *pbufsize, FILE *inf) /* read one record into buf */
{
int sep, c;
- char *buf;
- int count;
- size_t bufsize;
-
- init_buf(&buf, &bufsize, LINE_INCR);
- if ((sep = **RS) == 0) {
+ char *rr, *buf = *pbuf;
+ size_t bufsize = *pbufsize;
+ char *rs = getsval(rsloc);
+
+ if (strlen(getsval(fsloc)) >= sizeof (inputFS))
+ FATAL("field separator %.10s... is too long", *FS);
+ (void) strcpy(inputFS, *FS); /* for subsequent field splitting */
+ if ((sep = *rs) == 0) {
sep = '\n';
/* skip leading \n's */
while ((c = getc(inf)) == '\n' && c != EOF)
@@ -189,26 +253,30 @@ readrec(char **bufp, size_t *sizep, FILE *inf) /* read one record into buf */
if (c != EOF)
(void) ungetc(c, inf);
}
- count = 0;
- for (;;) {
+ for (rr = buf; ; ) {
while ((c = getc(inf)) != sep && c != EOF) {
- expand_buf(&buf, &bufsize, count);
- buf[count++] = c;
+ if (rr-buf+1 > bufsize)
+ if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1"))
+ FATAL("input record `%.30s...' too long", buf);
+ *rr++ = c;
}
- if (**RS == sep || c == EOF)
+ if (*rs == sep || c == EOF)
break;
if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
break;
- expand_buf(&buf, &bufsize, count + 1);
- buf[count++] = '\n';
- buf[count++] = c;
+ if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2"))
+ FATAL("input record `%.30s...' too long", buf);
+ *rr++ = '\n';
+ *rr++ = c;
}
- buf[count] = '\0';
+ if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3"))
+ FATAL("input record `%.30s...' too long", buf);
+ *rr = '\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;
+ return (c == EOF && rr == buf ? 0 : 1);
}
/* get ARGV[n] */
@@ -220,6 +288,8 @@ getargv(int n)
extern Array *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));
@@ -249,62 +319,89 @@ setclvar(char *s) /* set var=value from s */
void
fldbld(void) /* create fields from current record */
{
+ /* this relies on having fields[] the same length as $0 */
+ /* the fields are all stored in this one array with \0's */
+ /* 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 (!isstr(recloc))
- (void) getsval(recloc);
- r = recloc->sval; /* was record! */
-
- /* make sure fields is always allocated */
- adjust_buf(&fields, fieldssize);
-
- /*
- * 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(r) + 1;
- expand_buf(&fields, &fieldssize, 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(*FS) > 1) { /* it's a regular expression */
- i = refldbld(r, *FS);
- } else if ((sep = **FS) == ' ') {
+ if (strlen(getsval(fsloc)) >= sizeof (inputFS))
+ FATAL("field separator %.10s... is too long", *FS);
+ (void) strcpy(inputFS, *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')
break;
i++;
- p = getfld(i);
- if (freeable(p))
- 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;
+ *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 */
+ /*
+ * 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 (freeable(p))
- 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;
/* \n is always a separator */
- while (*r != sep && *r != '\n' && *r != '\0')
+ while (*r != sep && *r != rtest && *r != '\0')
*fr++ = *r++;
*fr++ = '\0';
if (*r++ == '\0')
@@ -312,35 +409,39 @@ fldbld(void) /* create fields from current record */
}
*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(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)
{
Cell *p;
int i;
- for (i = n2; i > n1; i--) {
- p = getfld(i);
+ for (i = n1; i <= n2; i++) {
+ p = fldtab[i];
if (freeable(p))
xfree(p->sval);
p->sval = "";
@@ -349,121 +450,91 @@ cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */
}
void
-newfld(int n) /* add field n (after end) */
+newfld(int n) /* add field n after end of existing lastfld */
{
- if (n < 0)
- FATAL("accessing invalid field", record);
- (void) getfld(n);
- cleanfld(maxfld, n);
- maxfld = 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)
- FATAL("out of space in morefld");
-
- 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 = "";
- 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)
- FATAL("trying to access field %d", idx);
- 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 */
- FATAL("trying to access invalid field %d", idx);
+ 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 */
- FATAL("trying to access unknown field");
+ 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(const char *rec, const char *fs)
{
+ /* this relies on having fields[] the same length as $0 */
+ /* the fields are all stored in this one array with \0's */
char *fr;
- int i, tempstat;
+ int i, tempstat, n;
fa *pfa;
- Cell *p;
- size_t len;
- /* make sure fields is allocated */
- adjust_buf(&fields, fieldssize);
+ 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(rec) + 1;
- expand_buf(&fields, &fieldssize, 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 (freeable(p))
- 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; /* horrible coupling to b.c */
@@ -488,41 +559,34 @@ recbld(void) /* create $0 from $1..$NF if necessary */
int i;
char *p;
size_t cnt, len, olen;
+ char *sep = getsval(ofsloc);
if (donerec == 1)
return;
cnt = 0;
- olen = strlen(*OFS);
+ olen = strlen(sep);
for (i = 1; i <= *NF; i++) {
- p = getsval(getfld(i));
+ 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));
+ 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)
-{
- if (n < 0)
- FATAL("trying to access field %d", n);
- return (getfld(n));
-}
-
int errorflag = 0;
void
@@ -739,85 +803,25 @@ isclvar(const char *s) /* is s of form var=something ? */
return (0);
}
-#define MAXEXPON 38 /* maximum exponent for fp number */
-
+#include <math.h>
int
is_number(const char *s)
{
- int d1, d2;
- int point;
- const char *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(char **optr, size_t *sizep, size_t amt)
-{
- char *nptr = NULL;
-
- if ((nptr = malloc(amt)) == NULL)
- FATAL("out of space in init_buf");
- /* initial buffer should have NULL terminated */
- *nptr = '\0';
- if (sizep != NULL)
- *sizep = amt;
- *optr = nptr;
-}
-
-void
r_expand_buf(char **optr, size_t *sizep, size_t req)
{
char *nptr;
@@ -836,13 +840,3 @@ r_expand_buf(char **optr, size_t *sizep, size_t req)
*sizep += amt;
*optr = nptr;
}
-
-void
-adjust_buf(char **optr, size_t size)
-{
- char *nptr;
-
- if ((nptr = realloc(*optr, size)) == NULL)
- FATAL("out of space in adjust_buf");
- *optr = nptr;
-}
diff --git a/usr/src/cmd/awk/main.c b/usr/src/cmd/awk/main.c
index b07f2c5b0a..cb87917311 100644
--- a/usr/src/cmd/awk/main.c
+++ b/usr/src/cmd/awk/main.c
@@ -66,21 +66,22 @@
char *version = "version Oct 11, 1989";
int dbg = 0;
+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 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[])
{
const char *fs = NULL;
- char *nl_radix;
/*
* At this point, numbers are still scanned as in
* the POSIX locale.
@@ -100,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--;
@@ -110,15 +121,27 @@ 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)
- FATAL("no program filename");
- pfile = realloc(pfile, sizeof (char *) * (npfile + 1));
- if (pfile == NULL)
- FATAL("out of space in main");
- pfile[npfile++] = 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 */
@@ -142,9 +165,22 @@ main(int argc, char *argv[], char *envp[])
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((++argv)[1]))
- setclvar(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]);
@@ -171,11 +207,14 @@ main(int argc, char *argv[], char *envp[])
argc--;
argv++;
}
+ recinit(recsize);
+ syminit();
compile_time = 1;
argv[0] = cmdname; /* put prog name at front of arglist */
dprintf(("argc=%d, argv[0]=%s\n", argc, argv[0]));
arginit(argc, argv);
- envinit(envp);
+ if (!safe)
+ envinit(envp);
(void) yyparse();
if (fs)
*FS = qstring(fs, '\0');
@@ -184,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;
@@ -206,7 +242,7 @@ pgetc(void) /* get 1 character from awk program */
if (curpfile >= npfile)
return (EOF);
yyin = (strcmp(pfile[curpfile], "-") == 0) ?
- stdin : fopen(pfile[curpfile], "r");
+ stdin : fopen(pfile[curpfile], "rF");
if (yyin == NULL) {
FATAL("can't open file %s", pfile[curpfile]);
}
@@ -214,7 +250,8 @@ pgetc(void) /* get 1 character from awk program */
}
if ((c = getc(yyin)) != EOF)
return (c);
- (void) fclose(yyin);
+ if (yyin != stdin)
+ (void) fclose(yyin);
yyin = NULL;
curpfile++;
}
diff --git a/usr/src/cmd/awk/maketab.c b/usr/src/cmd/awk/maketab.c
index ff398f3593..9c625aabcc 100644
--- a/usr/src/cmd/awk/maketab.c
+++ b/usr/src/cmd/awk/maketab.c
@@ -91,6 +91,7 @@ struct xx {
{ DIVIDE, "arith", " / " },
{ MOD, "arith", " % " },
{ UMINUS, "arith", " -" },
+ { UPLUS, "arith", " +" },
{ POWER, "arith", " **" },
{ PREINCR, "incrdecr", "++" },
{ POSTINCR, "incrdecr", "++" },
@@ -122,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" },
diff --git a/usr/src/cmd/awk/parse.c b/usr/src/cmd/awk/parse.c
index c91550f310..2afcf1e78f 100644
--- a/usr/src/cmd/awk/parse.c
+++ b/usr/src/cmd/awk/parse.c
@@ -221,7 +221,8 @@ celltonode(Cell *a, int b)
Node *
rectonode(void) /* make $0 into a Node */
{
- return (celltonode(recloc, CFLD));
+ extern Cell *literal0;
+ return (op1(INDIRECT, celltonode(literal0, CUNK)));
}
Node *
@@ -285,6 +286,10 @@ defn(Cell *v, Node *vl, Node *st)
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 = (char *)st;
diff --git a/usr/src/cmd/awk/run.c b/usr/src/cmd/awk/run.c
index 29529bdb84..211ba8e39f 100644
--- a/usr/src/cmd/awk/run.c
+++ b/usr/src/cmd/awk/run.c
@@ -56,41 +56,41 @@
#include <setjmp.h>
#include <math.h>
#include <time.h>
+#include <sys/wait.h>
#include "awk.h"
#include "y.tab.h"
#define tempfree(x) if (istemp(x)) tfree(x)
-#ifndef FOPEN_MAX
-#define FOPEN_MAX 15 /* max number of open files, from ANSI std. */
-#endif
-
-
static jmp_buf env;
+extern Awkfloat srand_seed;
static Cell *execute(Node *);
static Cell *gettemp(void), *copycell(Cell *);
static FILE *openfile(int, const char *), *redirect(int, Node *);
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 };
+static Cell truecell = { OBOOL, BTRUE, NULL, NULL, 1.0, NUM, NULL };
Cell *True = &truecell;
-static Cell falsecell = { OBOOL, BFALSE, 0, 0, 0.0, NUM };
+static Cell falsecell = { OBOOL, BFALSE, NULL, NULL, 0.0, NUM, NULL };
Cell *False = &falsecell;
-static Cell breakcell = { OJUMP, JBREAK, 0, 0, 0.0, NUM };
+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 */
@@ -140,6 +140,9 @@ adjbuf(char **pbuf, size_t *psiz, size_t minlen, size_t quantum, char **pbptr,
void
run(Node *a) /* execution of parse tree starts here */
{
+ extern void stdinit(void);
+
+ stdinit();
(void) execute(a);
closeall();
}
@@ -198,13 +201,13 @@ program(Node **a, int n)
if (isexit(x))
return (True);
if (isjump(x)) {
- FATAL("illegal break, continue, or next from BEGIN");
+ FATAL("illegal break, continue, next or nextfile "
+ "from BEGIN");
}
tempfree(x);
}
-loop:
if (a[1] || a[2])
- while (getrec(&record, &recsize) > 0) {
+ while (getrec(&record, &recsize, 1) > 0) {
x = execute(a[1]);
if (isexit(x))
break;
@@ -215,10 +218,9 @@ ex:
goto ex1;
if (a[2]) { /* END */
x = execute(a[2]);
- if (iscont(x)) /* read some more */
- goto loop;
- if (isbreak(x) || isnext(x))
- FATAL("illegal break or next from END");
+ if (isbreak(x) || isnext(x) || iscont(x))
+ FATAL("illegal break, continue, next or nextfile "
+ "from END");
tempfree(x);
}
ex1:
@@ -232,7 +234,7 @@ struct Frame { /* stack frame for awk function calls */
Cell *retval; /* return value */
};
-#define NARGS 30 /* max args in a call */
+#define NARGS 50 /* max args in a call */
struct Frame *frame = NULL; /* base of stack frames; dynamically alloc'd */
int nframe = 0; /* number of frames allocated */
@@ -243,7 +245,7 @@ Cell *
call(Node **a, int n) /* function call. very kludgy and fragile */
{
static Cell newcopycell =
- { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
+ { 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;
@@ -324,6 +326,7 @@ call(Node **a, int n) /* function call. very kludgy and fragile */
if (i >= ncall) {
freesymtab(t);
t->csub = CTEMP;
+ tempfree(t);
} else {
oargs[i]->tval = t->tval;
oargs[i]->tval &= ~(STR|NUM|DONTFREE);
@@ -331,10 +334,13 @@ call(Node **a, int n) /* function call. very kludgy and fragile */
tempfree(t);
}
}
- } else {
+ } else if (t != y) { /* kludge to prevent freeing twice */
+ t->csub = CTEMP;
+ tempfree(t);
+ } else if (t == y && t->csub == CCOPY) {
t->csub = CTEMP;
tempfree(t);
- if (t == y) freed = 1;
+ freed = 1;
}
}
tempfree(fcn);
@@ -355,13 +361,18 @@ copycell(Cell *x) /* make a copy of a cell in a temp */
{
Cell *y;
+ /* 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);
}
@@ -412,6 +423,9 @@ jump(Node **a, int n) /* break, continue, next, nextfile, return */
return (jret);
case NEXT:
return (jnext);
+ case NEXTFILE:
+ nextfile();
+ return (jnextfile);
case BREAK:
return (jbreak);
case CONTINUE:
@@ -428,11 +442,14 @@ awkgetline(Node **a, int n) /* get next line from specific input */
{
/* a[0] is variable, a[1] is operator, a[2] is filename */
Cell *r, *x;
- char *buf;
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();
if (a[1] != NULL) { /* getline < file */
@@ -442,38 +459,36 @@ awkgetline(Node **a, int n) /* get next line from specific input */
mode = LE; /* arbitrary flag */
fp = openfile(mode, getsval(x));
tempfree(x);
- buf = NULL;
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, &recsize, 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, &recsize);
+ 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);
}
@@ -494,23 +509,26 @@ array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
char *s;
Node *np;
char *buf;
- size_t bsize, tlen, len, slen;
+ 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(*SUBSEP);
for (np = a[1]; np != NULL; np = np->nnext) {
y = execute(np); /* subscript */
s = getsval(y);
len = strlen(s);
- expand_buf(&buf, &bsize, tlen + len + slen);
+ 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);
@@ -538,33 +556,53 @@ awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
{
Cell *x, *y;
Node *np;
- char *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(*SUBSEP);
- for (np = a[1]; np != NULL; np = np->nnext) {
- y = execute(np); /* subscript */
- s = getsval(y);
- len = strlen(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);
}
@@ -576,26 +614,36 @@ intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
Node *p;
char *buf;
char *s;
- size_t bsize, tlen, slen, len;
+ size_t bufsz = recsize;
+ size_t nsub;
+ size_t tlen = 0, len;
ap = execute(a[1]); /* array name */
- if (!isarr(ap))
- FATAL("%s is not an array", ap->nval);
- init_buf(&buf, &bsize, LINE_INCR);
+ 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';
- tlen = 0;
- slen = strlen(*SUBSEP);
for (p = a[0]; p != NULL; p = p->nnext) {
x = execute(p); /* expr */
s = getsval(x);
len = strlen(s);
- expand_buf(&buf, &bsize, tlen + len + slen);
+ 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);
if (p->nnext) {
- (void) memcpy(&buf[tlen], *SUBSEP, slen);
- tlen += slen;
+ (void) memcpy(&buf[tlen], *SUBSEP, nsub);
+ tlen += nsub;
}
buf[tlen] = '\0';
}
@@ -755,14 +803,21 @@ gettemp(void) /* get a tempcell */
Cell *
indirect(Node **a, int n) /* $( a[0] ) */
{
+ 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! */
- FATAL("illegal field $(%s)", s);
+ FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
+ /* BUG: can x->nval ever be null??? */
tempfree(x);
x = fieldadr(m);
x->ctype = OCELL; /* BUG? why are these needed? */
@@ -848,20 +903,26 @@ sindex(Node **a, int nnn) /* index(a[0], a[1]) */
return (z);
}
-void
-format(char **bufp, char *s, Node *a)
+#define MAXNUMSIZE 50
+
+/* printf-like conversions */
+int
+format(char **pbuf, int *pbufsize, const char *s, Node *a)
{
char *fmt;
const char *os;
Cell *x;
- int flag = 0, len;
- char *buf;
- size_t bufsize, fmtsize, cnt, tcnt, ret;
+ 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;
- init_buf(&buf, &bufsize, LINE_INCR);
- init_buf(&fmt, &fmtsize, LINE_INCR);
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);
@@ -874,14 +935,24 @@ format(char **bufp, char *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((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) {
FATAL("not enough args in printf(%s) "
@@ -890,42 +961,50 @@ format(char **bufp, char *s, Node *a)
x = execute(a);
a = a->nnext;
tcnt--;
- expand_buf(&fmt, &fmtsize, tcnt + 12);
- ret = sprintf(&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);
}
}
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) {
+ if (flag == '?') {
len = strlen(fmt);
expand_buf(&buf, &bufsize, cnt + len);
(void) memcpy(&buf[cnt], fmt, len);
@@ -939,59 +1018,76 @@ format(char **bufp, char *s, Node *a)
}
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(&buf[cnt], len,
- fmt, getfval(x));
- break;
- case 2:
+ 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(&buf[cnt], len,
- fmt, (long)getfval(x));
+ fmt, getsval(x)[0]);
break;
- case 3:
+ }
+ if (getfval(x)) {
/*LINTED*/
ret = snprintf(&buf[cnt], len,
fmt, (int)getfval(x));
- break;
- case 4:
- /*LINTED*/
- ret = snprintf(&buf[cnt], len,
- fmt, getsval(x));
- break;
- case 5:
- if (isnum(x)) {
- /*LINTED*/
- ret = snprintf(&buf[cnt], len,
- fmt, (int)getfval(x));
- } else {
- /*LINTED*/
- ret = snprintf(&buf[cnt], len,
- fmt, getsval(x)[0]);
- }
- break;
- default:
- ret = 0;
+ } 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);
cnt += ret;
s++;
}
buf[cnt] = '\0';
+ free(fmt);
for (; a != NULL; a = a->nnext) /* evaluate any remaining args */
(void) execute(a);
- *bufp = tostring(buf);
- free(buf);
- free(fmt);
+ *pbuf = buf;
+ *pbufsize = bufsize;
+ return (cnt);
}
/*ARGSUSED*/
@@ -1001,10 +1097,14 @@ awksprintf(Node **a, int n) /* sprintf(a[0]) */
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);
+ 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;
@@ -1022,17 +1122,26 @@ awkprintf(Node **a, int n) /* printf */
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);
+ 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) fputs(buf, stdout);
+ (void) fwrite(buf, len, 1, stdout);
+ if (ferror(stdout))
+ FATAL("write error on stdout");
} else {
fp = redirect(ptoi(a[1]), a[2]);
- (void) fputs(buf, fp);
+ (void) fwrite(buf, len, 1, fp);
(void) fflush(fp);
+ if (ferror(fp))
+ FATAL("write error on %s", filename(fp));
}
free(buf);
return (True);
@@ -1048,7 +1157,7 @@ arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
x = execute(a[0]);
i = getfval(x);
tempfree(x);
- if (n != UMINUS) {
+ if (n != UMINUS && n != UPLUS) {
y = execute(a[1]);
j = getfval(y);
tempfree(y);
@@ -1078,6 +1187,8 @@ arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
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);
@@ -1138,7 +1249,13 @@ assign(Node **a, int n)
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;
@@ -1195,26 +1312,26 @@ cat(Node **a, int q) /* a[0] cat a[1] */
{
Cell *x, *y, *z;
int n1, n2;
- char *s;
+ 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(x->sval);
- n2 = strlen(y->sval);
- s = (char *)malloc(n1 + n2 + 1);
- if (s == NULL) {
- FATAL("out of space concatenating %.15s... and %.15s...",
- x->sval, y->sval);
- }
- (void) strcpy(s, x->sval);
- (void) strcpy(s + n1, y->sval);
+ 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;
+
return (z);
}
@@ -1273,20 +1390,22 @@ dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
Cell *
split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
{
- Cell *x, *y, *ap;
- char *s;
+ Cell *x = NULL, *y, *ap;
+ char *s, *origs;
+ char *fs, *origfs = NULL;
int sep;
- char *t, temp, num[50], *fs = NULL;
+ char *t, temp, num[50];
int n, tempstat, arg3type;
y = execute(a[0]); /* source string */
- s = getsval(y);
+ origs = s = tostring(getsval(y));
arg3type = ptoi(a[3]);
- if (a[2] == NULL) /* fs string */
- fs = *FS;
+ if (a[2] == NULL) /* fs string */
+ fs = getsval(fsloc);
else if (arg3type == STRING) { /* split(str,arr,"string") */
x = execute(a[2]);
- fs = getsval(x);
+ origfs = fs = tostring(getsval(x));
+ tempfree(x);
} else if (arg3type == REGEXPR)
fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
else
@@ -1300,6 +1419,15 @@ split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
ap->sval = (char *)makesymtab(NSYMTAB);
n = 0;
+ 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;
@@ -1338,6 +1466,9 @@ split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
goto spdone;
}
} while (nematch(pfa, s));
+ /* bwk: has to be here to reset */
+ /* cf gsub and refldbld */
+ pfa->initstat = tempstat;
}
n++;
(void) sprintf(num, "%d", n);
@@ -1380,6 +1511,23 @@ spdone:
if (*s != '\0')
s++;
}
+ } 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++;
@@ -1405,9 +1553,8 @@ spdone:
}
tempfree(ap);
tempfree(y);
- if (a[2] != NULL && arg3type == STRING) {
- tempfree(x);
- }
+ free(origs);
+ free(origfs);
x = gettemp();
x->tval = NUM;
x->fval = n;
@@ -1528,7 +1675,12 @@ instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
vp = execute(a[0]);
arrayp = execute(a[1]);
if (!isarr(arrayp)) {
- FATAL("%s is not an array", arrayp->nval);
+ 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;
@@ -1559,15 +1711,25 @@ bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
Cell *x, *y;
Awkfloat u;
int t;
+ Awkfloat tmp;
char *p, *buf;
Node *nextarg;
+ FILE *fp;
+ void flush_all(void);
+ int status = 0;
t = ptoi(a[0]);
x = execute(a[1]);
nextarg = a[1]->nnext;
switch (t) {
case FLENGTH:
- u = (Awkfloat)strlen(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:
@@ -1594,8 +1756,18 @@ bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
case FSYSTEM:
/* in case something is buffered already */
(void) fflush(stdout);
- /* 256 is unix-dep */
- u = (Awkfloat)system(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:
/* in principle, rand() returns something in 0..RAND_MAX */
@@ -1606,7 +1778,10 @@ bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
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:
@@ -1625,6 +1800,15 @@ bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
(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 */
FATAL("illegal function type %d", t);
break;
@@ -1654,15 +1838,17 @@ printstat(Node **a, int n) /* print a[0] */
fp = redirect(ptoi(a[1]), a[2]);
for (x = a[0]; x != NULL; x = x->nnext) {
y = execute(x);
- (void) fputs(getsval(y), fp);
+ (void) fputs(getpssval(y), fp);
tempfree(y);
if (x->nnext == NULL)
- (void) fputs(*ORS, fp);
+ (void) fputs(getsval(orsloc), fp);
else
- (void) fputs(*OFS, fp);
+ (void) fputs(getsval(ofsloc), fp);
}
if (a[1] != NULL)
(void) fflush(fp);
+ if (ferror(fp))
+ FATAL("write error on %s", filename(fp));
return (True);
}
@@ -1673,11 +1859,6 @@ nullproc(Node **a, int n)
return (0);
}
-struct {
- FILE *fp;
- char *fname;
- int mode; /* '|', 'a', 'w' */
-} files[FOPEN_MAX];
static FILE *
redirect(int a, Node *b) /* set up all i/o redirections */
@@ -1695,6 +1876,32 @@ redirect(int a, Node *b) /* set up all i/o redirections */
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, const char *s)
{
@@ -1703,34 +1910,47 @@ openfile(int a, const char *s)
if (*s == '\0')
FATAL("null file name in print or getline");
- for (i = 0; i < FOPEN_MAX; i++) {
+ 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)) {
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)
- FATAL("%s makes too many open files", s);
+ 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(s, "w");
+ fp = fopen(s, "wF");
} else if (a == APPEND) {
- fp = fopen(s, "a");
+ fp = fopen(s, "aF");
m = GT; /* so can mix > and >> */
} else if (a == '|') { /* output pipe */
- fp = popen(s, "w");
+ fp = popen(s, "wF");
} else if (a == LE) { /* input pipe */
- fp = popen(s, "r");
+ fp = popen(s, "rF");
} else if (a == LT) { /* getline <file */
fp = strcmp(s, "-") == 0 ?
- stdin : fopen(s, "r"); /* "-" is stdin */
+ stdin : fopen(s, "rF"); /* "-" is stdin */
} else /* can't happen */
FATAL("illegal redirection %d", a);
if (fp != NULL) {
@@ -1741,6 +1961,17 @@ openfile(int a, const char *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)
@@ -1750,7 +1981,8 @@ closefile(Node **a, int n)
x = execute(a[0]);
(void) getsval(x);
- for (i = 0; i < FOPEN_MAX; i++) {
+ stat = -1;
+ for (i = 0; i < nfiles; i++) {
if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
if (ferror(files[i].fp)) {
WARNING("i/o error occurred on %s",
@@ -1764,14 +1996,17 @@ closefile(Node **a, int n)
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);
- return (True);
+ x = gettemp();
+ (void) setfval(x, (Awkfloat) stat);
+ return (x);
}
static void
@@ -1779,7 +2014,7 @@ 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)) {
WARNING("i/o error occurred on %s",
@@ -1797,6 +2032,16 @@ closeall(void)
}
}
+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) /* substitute command */
@@ -1978,7 +2223,6 @@ gsub(Node **a, int nnn) /* global substitute */
done:
buf[cnt] = '\0';
(void) setsval(x, buf);
- free(buf);
pfa->initstat = tempstat;
}
tempfree(x);
@@ -1986,5 +2230,6 @@ gsub(Node **a, int nnn) /* global substitute */
x = gettemp();
x->tval = NUM;
x->fval = num;
+ free(buf);
return (x);
}
diff --git a/usr/src/cmd/awk/tran.c b/usr/src/cmd/awk/tran.c
index bbcc161347..012b90acf4 100644
--- a/usr/src/cmd/awk/tran.c
+++ b/usr/src/cmd/awk/tran.c
@@ -70,6 +70,7 @@ 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 */
@@ -80,58 +81,73 @@ 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 */
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; /* a guaranteed empty cell */
Node *nullnode; /* zero&null, converted into a node for comparisons */
+Cell *literal0;
static void rehash(Array *);
+static void
+setfree(Cell *vp)
+{
+ 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 */
{
- init_buf(&record, &recsize, LINE_INCR);
-
/* initialize $0 */
- recloc = getfld(0);
+ recloc = fieldadr(0);
recloc->nval = "$0";
recloc->sval = record;
recloc->tval = REC|STR|DONTFREE;
- symtab = makesymtab(NSYMTAB);
- (void) setsymtab("0", "0", 0.0,
- NUM|STR|CON|DONTFREE, symtab);
+ literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
/* this is used for if(x)... tests: */
nullloc = setsymtab("$zero&null", "", 0.0,
NUM|STR|CON|DONTFREE, symtab);
nullnode = celltonode(nullloc, CCON);
- FS = &setsymtab("FS", " ", 0.0,
- STR|DONTFREE, symtab)->sval;
- RS = &setsymtab("RS", "\n", 0.0,
- STR|DONTFREE, symtab)->sval;
- OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
- ORS = &setsymtab("ORS", "\n", 0.0,
- STR|DONTFREE, symtab)->sval;
- OFMT = &setsymtab("OFMT", "%.6g", 0.0,
- STR|DONTFREE, symtab)->sval;
- FILENAME = &setsymtab("FILENAME", "-", 0.0,
+ fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab);
+ FS = &fsloc->sval;
+ rsloc = setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab);
+ RS = &rsloc->sval;
+ 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;
+ FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
NF = &nfloc->fval;
nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
NR = &nrloc->fval;
fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
FNR = &fnrloc->fval;
- SUBSEP = &setsymtab("SUBSEP", "\034", 0.0,
- STR|DONTFREE, symtab)->sval;
+ subseploc = setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab);
+ SUBSEP = &subseploc->sval;
rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
RSTART = &rstartloc->fval;
rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
@@ -147,14 +163,6 @@ arginit(int ac, char **av) /* set up ARGV and ARGC */
int i;
char temp[50];
- /* first make FILENAME first real argument */
- for (i = 1; i < ac; i++) {
- if (!isclvar(av[i])) {
- (void) setsval(lookup("FILENAME", symtab),
- av[i]);
- break;
- }
- }
ARGC = &setsymtab("ARGC", "", (Awkfloat)ac, NUM, symtab)->fval;
cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
@@ -183,6 +191,8 @@ envinit(char **envp) /* set up ENVIRON variable */
for (; *envp; envp++) {
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(p),
@@ -287,7 +297,7 @@ setsymtab(const char *n, const char *s, Awkfloat f, unsigned int t, Array *tp)
p->fval = f;
p->tval = t;
p->csub = CUNK;
-
+ p->ctype = OCELL;
tp->nelem++;
if (tp->nelem > FULLTAB * tp->size)
rehash(tp);
@@ -349,22 +359,35 @@ lookup(const char *s, Array *tp) /* look for s in tp */
Awkfloat
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 (isfld(vp)) {
donerec = 0; /* mark $0 invalid */
- i = fldidx(vp);
- if (i > *NF)
- newfld(i);
- dprintf(("setting field %d to %g\n", i, f));
+ 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;
+ } 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 */
+ 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);
@@ -384,7 +407,9 @@ funnyvar(Cell *vp, const char *rw)
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));
@@ -392,29 +417,40 @@ setsval(Cell *vp, const char *s) /* set string val of a Cell */
funnyvar(vp, "assign to");
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));
+ 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;
+ } 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) /* get float val of a Cell */
+getfval(Cell *vp) /* get float val of a Cell */
{
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, "read value of");
@@ -427,15 +463,16 @@ r_getfval(Cell *vp) /* get float val of a Cell */
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, NN(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);
}
-char *
-r_getsval(Cell *vp)
+static char *
+get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
{
char s[256];
+ double dtemp;
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, "read value of");
@@ -443,27 +480,100 @@ r_getsval(Cell *vp)
fldbld();
else if (isrec(vp) && donerec == 0)
recbld();
+
+ /*
+ * 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) {
- if (freeable(vp))
- xfree(vp->sval);
- if ((long long)vp->fval == vp->fval) {
- (void) snprintf(s, sizeof (s),
- "%.20g", vp->fval);
+ /*LINTED*/
+ update_str_val(vp);
+ if (fmt == OFMT) {
+ vp->tval &= ~CONVC;
+ vp->tval |= CONVO;
} else {
- /*LINTED*/
- (void) snprintf(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;
}
+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);
}
char *
+getsval(Cell *vp) /* get string val of a Cell */
+{
+ return (get_str_val(vp, CONVFMT));
+}
+
+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);
@@ -473,32 +583,36 @@ tostring(const char *s) /* make a copy of string s */
}
char *
-qstring(const char *s, int delim) /* collect string up to delim */
+qstring(const char *is, int delim) /* collect string up to next delim */
{
- char *cbuf, *ret;
+ const char *os = is;
int c, n;
- size_t cbufsz, cnt;
+ uschar *s = (uschar *)is;
+ uschar *buf, *bp;
- init_buf(&cbuf, &cbufsz, LINE_INCR);
-
- 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') {
- SYNTAX("newline in string %.10s...", cbuf);
- } 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';
@@ -507,13 +621,11 @@ qstring(const char *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 457884e5ac..7734155f19 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
@@ -67,7 +68,6 @@ nawk \- pattern scanning and processing language
.fi
.SH DESCRIPTION
-.sp
.LP
The \fB/usr/bin/awk\fR, \fB/usr/bin/nawk\fR and \fB/usr/xpg4/bin/awk\fR
utilities execute
@@ -95,8 +95,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
@@ -136,8 +136,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
@@ -200,7 +210,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
@@ -237,8 +246,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
@@ -270,8 +279,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
@@ -295,9 +304,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
_
@@ -310,7 +319,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
_
@@ -326,20 +335,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
@@ -486,8 +495,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.
@@ -510,8 +519,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:
@@ -546,6 +555,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
@@ -651,7 +670,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.
@@ -692,22 +711,7 @@ The subscript separator string for multi-dimensional arrays. The default value
is \fB\e034\fR\&.
.RE
-.SS "/usr/xpg4/bin/awk"
-.sp
-.LP
-The following variable is supported for \fB/usr/xpg4/bin/awk\fR only:
-.sp
-.ne 2
-.na
-\fB\fBCONVFMT\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.
-.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
@@ -824,14 +828,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
@@ -855,23 +859,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
@@ -883,6 +887,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 ] .\|.\|. }
@@ -890,6 +895,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
@@ -907,6 +913,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
@@ -914,8 +926,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
@@ -1053,13 +1065,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
@@ -1151,7 +1163,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,
@@ -1183,12 +1194,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
@@ -1301,8 +1315,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
@@ -1320,6 +1334,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
@@ -1350,7 +1378,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
@@ -1360,7 +1388,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
@@ -1370,7 +1398,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
@@ -1392,7 +1420,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
@@ -1407,8 +1435,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:
@@ -1460,8 +1488,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
@@ -1476,8 +1504,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
@@ -1757,7 +1785,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
@@ -1776,7 +1803,6 @@ programs (including assignments in command-line arguments).
.RE
.SH EXIT STATUS
-.sp
.LP
The following exit values are returned:
.sp
@@ -1803,7 +1829,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),
@@ -1813,8 +1838,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
@@ -1824,8 +1849,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 0f6f005e2d..fc5c5a77ed 100644
--- a/usr/src/pkg/manifests/system-test-utiltest.mf
+++ b/usr/src/pkg/manifests/system-test-utiltest.mf
@@ -58,6 +58,40 @@ 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/runtests.sh 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
@@ -169,7 +203,7 @@ 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
@@ -188,6 +222,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
@@ -196,7 +231,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
@@ -247,7 +282,7 @@ file path=opt/util-tests/tests/awk/examples/awk/t.re4 mode=0444
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.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.reFS 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
@@ -259,17 +294,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
@@ -390,7 +427,7 @@ 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
@@ -409,6 +446,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
@@ -417,7 +455,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
@@ -468,7 +506,7 @@ file path=opt/util-tests/tests/awk/examples/out/t.re4 mode=0444
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.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.reFS 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
@@ -480,17 +518,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
@@ -520,6 +560,8 @@ 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.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
@@ -529,11 +571,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
@@ -544,11 +594,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
@@ -566,6 +625,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
@@ -575,6 +636,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
@@ -613,6 +676,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
@@ -645,6 +711,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
@@ -710,6 +779,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
@@ -739,6 +813,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/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/posix2008sub.awk mode=0444
file path=opt/util-tests/tests/awk/gnu/posix2008sub.ok mode=0444
file path=opt/util-tests/tests/awk/gnu/poundbang.ok mode=0444
@@ -763,6 +840,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
@@ -777,6 +857,8 @@ 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
@@ -823,6 +905,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
@@ -830,6 +914,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
@@ -844,6 +930,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
@@ -882,6 +970,7 @@ file path=opt/util-tests/tests/awk/gnu/zeroe0.awk mode=0444
file path=opt/util-tests/tests/awk/gnu/zeroe0.ok mode=0444
file path=opt/util-tests/tests/awk/gnu/zeroflag.awk mode=0444
file path=opt/util-tests/tests/awk/gnu/zeroflag.ok mode=0444
+file path=opt/util-tests/tests/awk/runtests.sh mode=0555
file path=opt/util-tests/tests/awk/syn/arrayparm.awk mode=0444
file path=opt/util-tests/tests/awk/syn/arrayparm.ok mode=0444
file path=opt/util-tests/tests/awk/syn/arryref3.awk mode=0444
@@ -916,14 +1005,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
@@ -954,6 +1049,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
@@ -965,8 +1061,10 @@ 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.split mode=0555
file path=opt/util-tests/tests/awk/tests/T.sub mode=0555
diff --git a/usr/src/test/util-tests/tests/awk/Makefile b/usr/src/test/util-tests/tests/awk/Makefile
index 4b58321805..4dc03bd9d1 100644
--- a/usr/src/test/util-tests/tests/awk/Makefile
+++ b/usr/src/test/util-tests/tests/awk/Makefile
@@ -20,6 +20,9 @@ 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.* chem.awk latin1 lilly.progs lsd1.p penicil.p res.p)
@@ -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
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..3a9b6cfad5
--- /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 12
+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..8daf563e6f
--- /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("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.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.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/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/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 bc4268be76..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 source file aryprm2.awk
- context is
- delete a >>>
- <<<
-$AWK: syntax error at source line 3 in function f source file aryprm2.awk
-$AWK: illegal statement at source line 3 in function f source file aryprm2.awk
+$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/delfunc.ok b/usr/src/test/util-tests/tests/awk/syn/delfunc.ok
index 9f9e74f6ae..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 source file delfunc.awk
+$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/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/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/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 268cee3908..ea77ded982 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 3c0d43fd4f..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,6 +39,18 @@ $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
/[[/
@@ -101,6 +113,12 @@ function x() { function g() {} }
return not in function
{ return }
+break illegal outside
+{ break }
+
+continue illegal outside
+{ continue }
+
non-terminated string
{ print "abc
}
@@ -115,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,
@@ -186,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:
@@ -205,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 afcfb496ef..a077a46cc9 100755
--- a/usr/src/test/util-tests/tests/awk/tests/T.gawk
+++ b/usr/src/test/util-tests/tests/awk/tests/T.gawk
@@ -335,6 +335,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.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 6909f4155e..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"
@@ -413,6 +432,12 @@ $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
@@ -437,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 8bf704d9bf..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,6 +49,10 @@ END {
exit ecode
}
' <<\!!!!
+ ~ a
+ aa
+ aaa
+ ""
a ~ a
ba
bab
@@ -169,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
@@ -192,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
@@ -204,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
@@ -266,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.split b/usr/src/test/util-tests/tests/awk/tests/T.split
index a22b514a75..045256e6a9 100755
--- a/usr/src/test/util-tests/tests/awk/tests/T.split
+++ b/usr/src/test/util-tests/tests/awk/tests/T.split
@@ -45,4 +45,118 @@ echo '0
4' > $TEMP2
diff $TEMP1 $TEMP2 || fail 'BAD: T.split 0.3'
+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<>