--- old/usr/src/cmd/awk/awk.g.y	2013-05-11 15:20:42.459078744 +0000
+++ new/usr/src/cmd/awk/awk.g.y	2013-05-11 15:20:42.470468526 +0000
@@ -26,22 +26,42 @@
  * Use is subject to license terms.
  */
 
-/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
-/*	  All Rights Reserved  	*/
+/*
+ * Copyright (C) Lucent Technologies 1997
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name Lucent Technologies or any of
+ * its entities not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.
+ *
+ * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
 
 %{
-#ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 2.10	*/
 %}
 
 %{
 #include "awk.h"
 int yywrap(void) { return(1); }
-#ifndef	DEBUG
-#	define	PUTS(x)
-#endif
-Node	*beginloc = 0, *endloc = 0;
+
+Node	*beginloc = 0;
+Node	*endloc = 0;
 int	infunc	= 0;	/* = 1 if in arglist or body of func */
-uchar	*curfname = 0;
+int	inloop = 0;	/* = 1 if in while, for, do */
+uchar	*curfname = 0;	/* current function name */
 Node	*arglist = 0;	/* list of args for current function */
 static void	setfname(Cell *);
 static int	constnode(Node *);
@@ -61,25 +81,26 @@
 %token	<i>	NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
 %token	<i>	ARRAY
 %token	<i>	MATCH NOTMATCH MATCHOP
-%token	<i>	FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS
+%token	<i>	FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE
 %token	<i>	AND BOR APPEND EQ GE GT LE LT NE IN
-%token	<i>	ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC 
-%token	<i>	SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT
+%token	<i>	ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
+%token	<i>	SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE
 %token	<i>	ADD MINUS MULT DIVIDE MOD
 %token	<i>	ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
 %token	<i>	PRINT PRINTF SPRINTF
 %token	<p>	ELSE INTEST CONDEXPR
 %token	<i>	POSTINCR PREINCR POSTDECR PREDECR
-%token	<cp>	VAR IVAR VARNF CALL NUMBER STRING FIELD
+%token	<cp>	VAR IVAR VARNF CALL NUMBER STRING
 %token	<s>	REGEXPR
 
-%type	<p>	pas pattern ppattern plist pplist patlist prarg term
+%type	<p>	pas pattern ppattern plist pplist patlist prarg term re
 %type	<p>	pa_pat pa_stat pa_stats
 %type	<s>	reg_expr
 %type	<p>	simple_stmt opt_simple_stmt stmt stmtlist
 %type	<p>	var varname funcname varlist
-%type	<p>	for if while
-%type	<i>	pst opt_pst lbrace rparen comma nl opt_nl and bor
+%type	<p>	for if else while
+%type	<i>	do st
+%type	<i>	pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor
 %type	<i>	subop print
 
 %right	ASGNOP
@@ -89,7 +110,7 @@
 %left	AND
 %left	GETLINE
 %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
-%left	ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FIELD FUNC 
+%left	ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC
 %left	GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
 %left	PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
 %left	REGEXPR VAR VARNF IVAR WHILE '('
@@ -107,7 +128,7 @@
 program:
 	  pas	{ if (errorflag==0)
 			winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
-	| error	{ yyclearin; bracecheck(); ERROR "bailing out" SYNTAX; }
+	| error	{ yyclearin; bracecheck(); SYNTAX("bailing out"); }
 	;
 
 and:
@@ -131,12 +152,12 @@
 	;
 
 for:
-	  FOR '(' opt_simple_stmt ';' pattern ';' opt_simple_stmt rparen stmt
-		{ $$ = stat4(FOR, $3, notnull($5), $7, $9); }
-	| FOR '(' opt_simple_stmt ';'  ';' opt_simple_stmt rparen stmt
-		{ $$ = stat4(FOR, $3, NIL, $6, $8); }
-	| FOR '(' varname IN varname rparen stmt
-		{ $$ = stat3(IN, $3, makearr($5), $7); }
+	  FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
+		{ --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); }
+	| FOR '(' opt_simple_stmt ';'  ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
+		{ --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); }
+	| FOR '(' varname IN varname rparen {inloop++;} stmt
+		{ --inloop; $$ = stat3(IN, $3, makearr($5), $8); }
 	;
 
 funcname:
@@ -184,8 +205,8 @@
 pa_stat:
 	  pa_pat			{ $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
 	| pa_pat lbrace stmtlist '}'	{ $$ = stat2(PASTAT, $1, $3); }
-	| pa_pat ',' pa_pat		{ $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); }
-	| pa_pat ',' pa_pat lbrace stmtlist '}'	{ $$ = pa2stat($1, $3, $5); }
+	| pa_pat ',' opt_nl pa_pat		{ $$ = pa2stat($1, $4, stat2(PRINT, rectonode(), NIL)); }
+	| pa_pat ',' opt_nl pa_pat lbrace stmtlist '}'	{ $$ = pa2stat($1, $4, $6); }
 	| lbrace stmtlist '}'		{ $$ = stat2(PASTAT, NIL, $2); }
 	| XBEGIN lbrace stmtlist '}'
 		{ beginloc = linkum(beginloc, $3); $$ = 0; }
@@ -202,7 +223,7 @@
 
 patlist:
 	  pattern
-	| patlist comma pattern	{ $$ = linkum($1, $3); }
+	| patlist comma pattern		{ $$ = linkum($1, $3); }
 	;
 
 ppattern:
@@ -213,8 +234,6 @@
 		{ $$ = op2(BOR, notnull($1), notnull($3)); }
 	| ppattern and ppattern %prec AND
 		{ $$ = op2(AND, notnull($1), notnull($3)); }
-	| NOT ppattern
-		{ $$ = op1(NOT, notnull($2)); }
 	| ppattern MATCHOP reg_expr	{ $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
 	| ppattern MATCHOP ppattern
 		{ if (constnode($3))
@@ -224,8 +243,7 @@
 	| 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
 	;
 
@@ -237,8 +255,6 @@
 		{ $$ = op2(BOR, notnull($1), notnull($3)); }
 	| pattern and pattern %prec AND
 		{ $$ = op2(AND, notnull($1), notnull($3)); }
-	| NOT pattern
-		{ $$ = op1(NOT, op2(NE,$2,valtonode(lookup((uchar *)"$zero&null",symtab),CCON))); }
 	| pattern EQ pattern		{ $$ = op2($2, $1, $3); }
 	| pattern GE pattern		{ $$ = op2($2, $1, $3); }
 	| pattern GT pattern		{ $$ = op2($2, $1, $3); }
@@ -253,11 +269,14 @@
 			$$ = 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
 	;
 
@@ -288,6 +307,12 @@
 	  '}' | rbrace NL
 	;
 
+re:
+	   reg_expr
+		{ $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
+	| NOT re	{ $$ = op1(NOT, notnull($2)); }
+	;
+
 reg_expr:
 	  '/' {startreg();} REGEXPR '/'		{ $$ = $3; }
 	;
@@ -297,26 +322,36 @@
 	;
 
 simple_stmt:
-	  print prarg '|' term		{ $$ = stat3($1, $2, (Node *) $3, $4); }
-	| print prarg APPEND term	{ $$ = stat3($1, $2, (Node *) $3, $4); }
-	| print prarg GT term		{ $$ = stat3($1, $2, (Node *) $3, $4); }
+	  print prarg '|' term		{
+			if (safe) SYNTAX("print | is unsafe");
+			else $$ = stat3($1, $2, itonp($3), $4); }
+	| print prarg APPEND term	{
+			if (safe) SYNTAX("print >> is unsafe");
+			else $$ = stat3($1, $2, itonp($3), $4); }
+	| print prarg GT term		{
+			if (safe) SYNTAX("print > is unsafe");
+			else $$ = stat3($1, $2, itonp($3), $4); }
 	| print prarg			{ $$ = stat3($1, $2, NIL, NIL); }
 	| DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
-	| DELETE varname		{ yyclearin; ERROR "you can only delete array[element]" SYNTAX; $$ = stat1(DELETE, $2); }
+	| DELETE varname		{ $$ = stat2(DELETE, makearr($2), 0); }
 	| pattern			{ $$ = exptostat($1); }
-	| error				{ yyclearin; ERROR "illegal statement" SYNTAX; }
+	| error				{ yyclearin; SYNTAX("illegal statement"); }
 	;
 
 st:
-	  nl | ';' opt_nl
+	  nl
+	| ';' opt_nl
 	;
 
 stmt:
-	  BREAK st		{ $$ = stat1(BREAK, NIL); }
-	| CLOSE pattern st	{ $$ = stat1(CLOSE, $2); }
-	| CONTINUE st		{ $$ = stat1(CONTINUE, NIL); }
-	| do stmt WHILE '(' pattern ')' st
-		{ $$ = stat2(DO, $2, notnull($5)); }
+	  BREAK st		{
+			if (!inloop) SYNTAX("break illegal outside of loops");
+			$$ = stat1(BREAK, NIL); }
+	| CONTINUE st		{
+			if (!inloop) SYNTAX("continue illegal outside of loops");
+			 $$ = stat1(CONTINUE, NIL); }
+	| do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st
+		{ $$ = stat2(DO, $3, notnull($7)); }
 	| EXIT pattern st	{ $$ = stat1(EXIT, $2); }
 	| EXIT st		{ $$ = stat1(EXIT, NIL); }
 	| for
@@ -324,12 +359,15 @@
 	| if stmt		{ $$ = stat3(IF, $1, $2, NIL); }
 	| lbrace stmtlist rbrace { $$ = $2; }
 	| NEXT st	{ if (infunc)
-				ERROR "next is illegal inside a function" SYNTAX;
+				SYNTAX("next is illegal inside a function");
 			  $$ = stat1(NEXT, NIL); }
+	| NEXTFILE st	{ if (infunc)
+				SYNTAX("nextfile is illegal inside a function");
+			  $$ = stat1(NEXTFILE, NIL); }
 	| RETURN pattern st	{ $$ = stat1(RETURN, $2); }
 	| RETURN st		{ $$ = stat1(RETURN, NIL); }
 	| simple_stmt st
-	| while stmt		{ $$ = stat2(WHILE, $1, $2); }
+	| while {inloop++;} stmt		{ --inloop; $$ = stat2(WHILE, $1, $3); }
 	| ';' opt_nl		{ $$ = 0; }
 	;
 
@@ -343,7 +381,8 @@
 	;
 
 term:
-	  term '+' term			{ $$ = op2(ADD, $1, $3); }
+	  term '/' ASGNOP term		{ $$ = op2(DIVEQ, $1, $4); }
+	| term '+' term			{ $$ = op2(ADD, $1, $3); }
 	| term '-' term			{ $$ = op2(MINUS, $1, $3); }
 	| term '*' term			{ $$ = op2(MULT, $1, $3); }
 	| term '/' term			{ $$ = op2(DIVIDE, $1, $3); }
@@ -351,23 +390,26 @@
 	| term POWER term		{ $$ = op2(POWER, $1, $3); }
 	| '-' term %prec UMINUS		{ $$ = op1(UMINUS, $2); }
 	| '+' term %prec UMINUS		{ $$ = $2; }
-	| BLTIN '(' ')'			{ $$ = op2(BLTIN, (Node *) $1, rectonode()); }
-	| BLTIN '(' patlist ')'		{ $$ = op2(BLTIN, (Node *) $1, $3); }
-	| BLTIN				{ $$ = op2(BLTIN, (Node *) $1, rectonode()); }
-	| CALL '(' ')'			{ $$ = op2(CALL, valtonode($1,CVAR), NIL); }
-	| CALL '(' patlist ')'		{ $$ = op2(CALL, valtonode($1,CVAR), $3); }
+	| NOT term %prec UMINUS		{ $$ = op1(NOT, notnull($2)); }
+	| BLTIN '(' ')'			{ $$ = op2(BLTIN, itonp($1), rectonode()); }
+	| BLTIN '(' patlist ')'		{ $$ = op2(BLTIN, itonp($1), $3); }
+	| BLTIN				{ $$ = op2(BLTIN, itonp($1), rectonode()); }
+	| CALL '(' ')'			{ $$ = op2(CALL, celltonode($1,CVAR), NIL); }
+	| CALL '(' patlist ')'		{ $$ = op2(CALL, celltonode($1,CVAR), $3); }
+	| CLOSE term			{ $$ = op1(CLOSE, $2); }
 	| DECR var			{ $$ = op1(PREDECR, $2); }
 	| INCR var			{ $$ = op1(PREINCR, $2); }
 	| var DECR			{ $$ = op1(POSTDECR, $1); }
 	| var INCR			{ $$ = op1(POSTINCR, $1); }
-	| GETLINE var LT term		{ $$ = op3(GETLINE, $2, (Node *)$3, $4); }
-	| GETLINE LT term		{ $$ = op3(GETLINE, NIL, (Node *)$2, $3); }
+	| GETLINE var LT term		{ $$ = op3(GETLINE, $2, itonp($3), $4); }
+	| GETLINE LT term		{ $$ = op3(GETLINE, NIL, itonp($2), $3); }
 	| GETLINE var			{ $$ = op3(GETLINE, $2, NIL, NIL); }
 	| GETLINE			{ $$ = op3(GETLINE, NIL, NIL, NIL); }
 	| INDEX '(' pattern comma pattern ')'
 		{ $$ = op2(INDEX, $3, $5); }
 	| INDEX '(' pattern comma reg_expr ')'
-		{ ERROR "index() doesn't permit regular expressions" SYNTAX;
+		{ SYNTAX("index() doesn't permit regular expressions");
+		  /* LINTED align */
 		  $$ = op2(INDEX, $3, (Node*)$5); }
 	| '(' pattern ')'		{ $$ = $2; }
 	| MATCHFCN '(' pattern comma reg_expr ')'
@@ -377,7 +419,7 @@
 			$$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1));
 		  else
 			$$ = op3(MATCHFCN, (Node *)1, $3, $5); }
-	| NUMBER			{ $$ = valtonode($1, CCON); }
+	| NUMBER			{ $$ = celltonode($1, CCON); }
 	| SPLIT '(' pattern comma varname comma pattern ')'     /* string */
 		{ $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
 	| SPLIT '(' pattern comma varname comma reg_expr ')'    /* const /regexp/ */
@@ -385,7 +427,7 @@
 	| SPLIT '(' pattern comma varname ')'
 		{ $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); }  /* default */
 	| SPRINTF '(' patlist ')'	{ $$ = op1($1, $3); }
-	| STRING	 		{ $$ = valtonode($1, CCON); }
+	| STRING	 		{ $$ = celltonode($1, CCON); }
 	| subop '(' reg_expr comma pattern ')'
 		{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); }
 	| subop '(' pattern comma pattern ')'
@@ -410,20 +452,21 @@
 var:
 	  varname
 	| varname '[' patlist ']'	{ $$ = op2(ARRAY, makearr($1), $3); }
-	| FIELD				{ $$ = valtonode($1, CFLD); }
-	| IVAR				{ $$ = op1(INDIRECT, valtonode($1, CVAR)); }
+	| IVAR				{ $$ = op1(INDIRECT, celltonode($1, CVAR)); }
 	| INDIRECT term	 		{ $$ = op1(INDIRECT, $2); }
 	;	
 
 varlist:
 	  /* nothing */		{ arglist = $$ = 0; }
-	| VAR			{ arglist = $$ = valtonode($1,CVAR); }
-	| varlist comma VAR	{ arglist = $$ = linkum($1,valtonode($3,CVAR)); }
+	| VAR			{ arglist = $$ = celltonode($1,CVAR); }
+	| varlist comma VAR	{
+			checkdup($1, $3);
+			arglist = $$ = linkum($1,celltonode($3,CVAR)); }
 	;
 
 varname:
-	  VAR			{ $$ = valtonode($1, CVAR); }
-	| ARG 			{ $$ = op1(ARG, (Node *) $1); }
+	  VAR			{ $$ = celltonode($1, CVAR); }
+	| ARG 			{ $$ = op1(ARG, itonp($1)); }
 	| VARNF			{ $$ = op1(VARNF, (Node *) $1); }
 	;
 
@@ -438,9 +481,9 @@
 setfname(Cell *p)
 {
 	if (isarr(p))
-		ERROR "%s is an array, not a function", p->nval SYNTAX;
-	else if (isfunc(p))
-		ERROR "you can't define function %s more than once", p->nval SYNTAX;
+		SYNTAX("%s is an array, not a function", p->nval);
+	else if (isfcn(p))
+		SYNTAX("you can't define function %s more than once", p->nval);
 	curfname = p->nval;
 }
 
@@ -448,13 +491,13 @@
 static int
 constnode(Node *p)
 {
-	return p->ntype == NVALUE && ((Cell *) (p->narg[0]))->csub == CCON;
+	return (isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON);
 }
 
 static uchar *
 strnode(Node *p)
 {
-	return ((Cell *)(p->narg[0]))->sval;
+	return (((Cell *)(p->narg[0]))->sval);
 }
 
 static Node *
@@ -463,8 +506,21 @@
 	switch (n->nobj) {
 	case LE: case LT: case EQ: case NE: case GT: case GE:
 	case BOR: case AND: case NOT:
-		return n;
+		return (n);
 	default:
-		return op2(NE, n, nullnode);
+		return (op2(NE, n, nullnode));
+	}
+}
+
+static void
+checkdup(Node *vl, Cell *cp)	/* check if name already in list */
+{
+	uchar *s = cp->nval;
+
+	for (; vl; vl = vl->nnext) {
+		if (strcmp((char *)s, (char *)((Cell *)(vl->narg[0]))->nval) == 0) {
+			SYNTAX("duplicate argument %s", s);
+			break;
+		}
 	}
 }
