Plan 9 from Bell Labs’s /usr/web/sources/contrib/yk/dist/9legacy/applied/awk.diff

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


--- /n/sources/plan9/sys/man/1/awk	Fri Apr 15 17:59:50 2011
+++ /sys/man/1/awk	Wed Feb 24 00:00:00 2016
@@ -11,14 +11,6 @@
 .B -d
 ]
 [
-.BI -mf
-.I n
-]
-[
-.B -mr
-.I n
-]
-[
 .B -safe
 ]
 [
@@ -87,27 +79,6 @@
 If
 .BR FS
 is null, the input line is split into one field per character.
-.PP
-To compensate for inadequate implementation of storage management,
-the 
-.B -mr
-option can be used to set the maximum size of the input record,
-and the
-.B -mf
-option to set the maximum number of fields.
-.PP
-The
-.B -safe
-option causes
-.I awk
-to run in 
-``safe mode,''
-in which it is not allowed to 
-run shell commands or open files
-and the environment is not made available
-in the 
-.B ENVIRON
-variable.
 .PP
 A pattern-action statement has the form
 .IP
diff -Nru /n/sources/plan9/sys/src/cmd/awk/awk.h /sys/src/cmd/awk/awk.h
--- /n/sources/plan9/sys/src/cmd/awk/awk.h	Sun Dec 12 01:06:43 1999
+++ /sys/src/cmd/awk/awk.h	Wed Feb 24 00:00:00 2016
@@ -10,8 +10,10 @@
 
 typedef	unsigned char uschar;
 
-#define	xfree(a)	{ if ((a) != NULL) { free((char *) a); a = NULL; } }
+#define	xfree(a)	{ if ((a) != NULL) { free((void *) (a)); (a) = NULL; } }
 
+#define	NN(p)	((p) ? (p) : "(null)")	/* guaranteed non-null for dprintf 
+*/
 #define	DEBUG
 #ifdef	DEBUG
 			/* uses have to be doubly parenthesized */
@@ -20,8 +22,6 @@
 #	define	dprintf(x)
 #endif
 
-extern	char	errbuf[];
-
 extern int	compile_time;	/* 1 if compiling, 0 if running */
 extern int	safe;		/* 0 => unsafe, 1 => safe */
 
@@ -166,8 +166,7 @@
 #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	isnextfile(n)	((n)->csub == JNEXTFILE)
+#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)
diff -Nru /n/sources/plan9/sys/src/cmd/awk/awkgram.c /sys/src/cmd/awk/awkgram.c
--- /n/sources/plan9/sys/src/cmd/awk/awkgram.c	Thu Sep 19 22:27:47 2013
+++ /sys/src/cmd/awk/awkgram.c	Thu Jan  1 00:00:00 1970
@@ -1,1620 +0,0 @@
-
-#line	26	"/sys/src/cmd/awk/awkgram.y"
-#include <stdio.h>
-#include <string.h>
-#include "awk.h"
-
-#define	makedfa(a,b)	compre(a)
-
-void checkdup(Node *list, Cell *item);
-int yywrap(void) { return(1); }
-
-Node	*beginloc = 0;
-Node	*endloc = 0;
-int	infunc	= 0;	/* = 1 if in arglist or body of func */
-int	inloop	= 0;	/* = 1 if in while, for, do */
-char	*curfname = 0;	/* current function name */
-Node	*arglist = 0;	/* list of args for current function */
-
-#line	43	"/sys/src/cmd/awk/awkgram.y"
-typedef union  {
-	Node	*p;
-	Cell	*cp;
-	int	i;
-	char	*s;
-} YYSTYPE;
-extern	int	yyerrflag;
-#ifndef	YYMAXDEPTH
-#define	YYMAXDEPTH	150
-#endif
-YYSTYPE	yylval;
-YYSTYPE	yyval;
-#define	FIRSTTOKEN	57346
-#define	PROGRAM	57347
-#define	PASTAT	57348
-#define	PASTAT2	57349
-#define	XBEGIN	57350
-#define	XEND	57351
-#define	NL	57352
-#define	ARRAY	57353
-#define	MATCH	57354
-#define	NOTMATCH	57355
-#define	MATCHOP	57356
-#define	FINAL	57357
-#define	DOT	57358
-#define	ALL	57359
-#define	CCL	57360
-#define	NCCL	57361
-#define	CHAR	57362
-#define	OR	57363
-#define	STAR	57364
-#define	QUEST	57365
-#define	PLUS	57366
-#define	AND	57367
-#define	BOR	57368
-#define	APPEND	57369
-#define	EQ	57370
-#define	GE	57371
-#define	GT	57372
-#define	LE	57373
-#define	LT	57374
-#define	NE	57375
-#define	IN	57376
-#define	ARG	57377
-#define	BLTIN	57378
-#define	BREAK	57379
-#define	CLOSE	57380
-#define	CONTINUE	57381
-#define	DELETE	57382
-#define	DO	57383
-#define	EXIT	57384
-#define	FOR	57385
-#define	FUNC	57386
-#define	SUB	57387
-#define	GSUB	57388
-#define	IF	57389
-#define	INDEX	57390
-#define	LSUBSTR	57391
-#define	MATCHFCN	57392
-#define	NEXT	57393
-#define	NEXTFILE	57394
-#define	ADD	57395
-#define	MINUS	57396
-#define	MULT	57397
-#define	DIVIDE	57398
-#define	MOD	57399
-#define	ASSIGN	57400
-#define	ASGNOP	57401
-#define	ADDEQ	57402
-#define	SUBEQ	57403
-#define	MULTEQ	57404
-#define	DIVEQ	57405
-#define	MODEQ	57406
-#define	POWEQ	57407
-#define	PRINT	57408
-#define	PRINTF	57409
-#define	SPRINTF	57410
-#define	ELSE	57411
-#define	INTEST	57412
-#define	CONDEXPR	57413
-#define	POSTINCR	57414
-#define	PREINCR	57415
-#define	POSTDECR	57416
-#define	PREDECR	57417
-#define	VAR	57418
-#define	IVAR	57419
-#define	VARNF	57420
-#define	CALL	57421
-#define	NUMBER	57422
-#define	STRING	57423
-#define	REGEXPR	57424
-#define	GETLINE	57425
-#define	RETURN	57426
-#define	SPLIT	57427
-#define	SUBSTR	57428
-#define	WHILE	57429
-#define	CAT	57430
-#define	NOT	57431
-#define	UMINUS	57432
-#define	POWER	57433
-#define	DECR	57434
-#define	INCR	57435
-#define	INDIRECT	57436
-#define	LASTTOKEN	57437
-#define YYEOFCODE 1
-#define YYERRCODE 2
-
-#line	447	"/sys/src/cmd/awk/awkgram.y"
-
-
-void setfname(Cell *p)
-{
-	if (isarr(p))
-		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;
-}
-
-int constnode(Node *p)
-{
-	return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON;
-}
-
-char *strnode(Node *p)
-{
-	return ((Cell *)(p->narg[0]))->sval;
-}
-
-Node *notnull(Node *n)
-{
-	switch (n->nobj) {
-	case LE: case LT: case EQ: case NE: case GT: case GE:
-	case BOR: case AND: case NOT:
-		return n;
-	default:
-		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;
-		}
-	}
-}
-short	yyexca[] =
-{-1, 0,
-	1, 28,
-	8, 28,
-	9, 28,
-	12, 28,
-	13, 28,
-	16, 28,
-	45, 28,
-	46, 28,
-	54, 28,
-	55, 28,
-	56, 28,
-	58, 28,
-	60, 28,
-	78, 28,
-	86, 28,
-	87, 28,
-	88, 28,
-	89, 28,
-	90, 28,
-	91, 28,
-	95, 28,
-	97, 28,
-	98, 28,
-	101, 28,
-	102, 28,
-	105, 28,
-	108, 28,
-	109, 28,
-	110, 28,
-	-2, 0,
--1, 1,
-	1, -1,
-	-2, 0,
--1, 157,
-	15, 30,
-	-2, 0,
--1, 176,
-	14, 0,
-	24, 0,
-	38, 0,
-	39, 0,
-	40, 0,
-	41, 0,
-	42, 0,
-	43, 0,
-	44, 0,
-	-2, 63,
--1, 177,
-	14, 0,
-	24, 0,
-	38, 0,
-	39, 0,
-	40, 0,
-	41, 0,
-	42, 0,
-	43, 0,
-	44, 0,
-	-2, 64,
--1, 178,
-	14, 0,
-	24, 0,
-	38, 0,
-	39, 0,
-	40, 0,
-	41, 0,
-	42, 0,
-	43, 0,
-	44, 0,
-	-2, 65,
--1, 179,
-	14, 0,
-	24, 0,
-	38, 0,
-	39, 0,
-	40, 0,
-	41, 0,
-	42, 0,
-	43, 0,
-	44, 0,
-	-2, 66,
--1, 180,
-	14, 0,
-	24, 0,
-	38, 0,
-	39, 0,
-	40, 0,
-	41, 0,
-	42, 0,
-	43, 0,
-	44, 0,
-	-2, 67,
--1, 181,
-	14, 0,
-	24, 0,
-	38, 0,
-	39, 0,
-	40, 0,
-	41, 0,
-	42, 0,
-	43, 0,
-	44, 0,
-	-2, 68,
--1, 183,
-	14, 0,
-	24, 0,
-	38, 0,
-	39, 0,
-	40, 0,
-	41, 0,
-	42, 0,
-	43, 0,
-	44, 0,
-	-2, 70,
--1, 290,
-	24, 0,
-	44, 0,
-	-2, 53,
--1, 334,
-	17, 30,
-	-2, 0,
--1, 356,
-	17, 30,
-	-2, 0,
-};
-#define	YYNPROD	185
-#define	YYPRIVATE 57344
-#define	YYLAST	4170
-short	yyact[] =
-{
-  17, 278, 254, 137, 244, 229, 102, 200,  53,  66,
-  24, 105,  42, 155, 103, 104, 100, 138, 112, 309,
-  54, 185, 215,  42, 100, 254, 100, 100, 100, 250,
- 224, 121, 122, 123,   9, 107,  82,  42, 315,  83,
- 162, 254, 107, 103, 104, 103, 104, 124, 253, 206,
-  42, 190, 245,  41,  22,  43, 113, 113, 279, 133,
- 317, 142,  10, 146,  41, 353,  43, 149, 150, 152,
- 153, 148, 352, 163, 136, 100,  42,  23,  41,  22,
-  43, 277, 147, 351, 132,  62, 156,  85, 168, 169,
-  11,  41,  22,  43, 322, 321,  50, 190,  79,  80,
- 100, 319,  23,  86, 182, 270, 259, 100, 100, 100,
- 100, 100, 100, 100, 134,  23, 276,  41, 233,  43,
- 108, 109, 110, 111, 332, 100, 112, 203, 205, 110,
- 111, 190, 190, 112, 140,  11, 211, 336, 325, 139,
- 212, 234, 100, 140, 235, 220, 100, 170, 311, 222,
- 190, 167, 100, 219, 136, 227, 279, 156, 190, 158,
- 190, 157, 190, 100, 285, 221, 266, 231, 261, 136,
- 130, 129, 100, 237, 100, 228, 100, 100, 100, 100,
- 100, 100, 100, 128, 100, 190, 252, 100, 100, 136,
- 136, 260, 190,   3, 100,   6, 127, 126, 188,  19,
-   7,   6, 100,  47, 313, 125,   7, 100,  48, 100,
- 100, 100, 120, 119, 100, 100,  51,  16,  16, 190,
- 217, 140, 275, 218, 143, 115, 271, 154, 272,   4,
- 144, 131, 318, 100, 100, 100, 100, 163,  49, 163,
- 163, 163, 163,  20, 274, 163, 348, 100, 294, 362,
- 239, 295, 289, 293, 365,   1, 100, 100,  72,  96,
-  39, 225,   5,  58,  67, 223, 240, 114,  61, 116,
- 117, 118, 164,  60, 301, 302, 249, 283,  81, 286,
- 287, 288, 290,   8, 100, 292, 159, 100, 100, 100,
- 310, 100, 136, 100, 156, 160, 314,   2, 100,   0,
- 100, 100,   0,   0, 100,   0, 100, 100, 100,   0,
-   0,   0,   0,   0, 335,   0, 165, 163,  96,   0,
-   0,   0,   0,   0,   0, 334,   0,   0, 342, 156,
- 343,   0,   0,   0, 100, 341,   0,   0,   0, 100,
- 347, 100,   0, 116, 231, 100, 100,   0, 349, 357,
-  96, 194, 195, 196, 197, 198, 199, 338,   0, 360,
- 356,   0, 361, 363, 156,   0, 231,   0, 207, 358,
- 136, 239,   0,   0, 239, 239, 239,   0, 239,   0,
- 239,   0,   0, 364,   0,  96, 366, 240,   0,  96,
- 240, 240, 240,   0, 240,  96, 240,   0,   0,   0,
- 258,   0,   0,   0, 339,   0, 243,   0,   0,   0,
-   0,   0,   0,   0,   0,  96,   0,  96,  21,  96,
-  96,  96,  96,  96,  96,  96, 239,  96,   0,   0,
-  96,  96,   0,   0,   0,   0, 164, 257, 164, 164,
- 164, 164, 240,   0, 164,  96,   0,   0,   0,   0,
- 262,   0,  96,  96,  96,   0,   0,  96,  96,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,  96, 280, 281, 282,
- 165,   0, 165, 165, 165, 165,   0,   0, 165,   0,
-  96,   0, 166,   0,   0,   0,   0,   0,   0,  96,
-  96,   0,   0,   0,   0,  74, 189, 191,   0,   0,
-  15,   0,   0, 184,   0,   0, 164,   0,   0,   0,
-   0,   0,   0,   0, 106,   0,   0, 243,   0,   0,
- 243, 243, 243,   0, 243,   0, 243,   0,   0,   0,
-   0,  96,   0,  96,  96,   0,   0,  96,   0,  96,
-  96,  96,   0,   0,   0,  15,   0,  15,   0,   0,
- 165, 236, 141,   0,   0, 145,   0,   0,   0,   0,
-   0, 151,   0,   0,   0,   0, 230,  96,   0,   0,
-   0,   0, 243,   0,  96,   0,   0,   0,  96,  96,
- 171, 173, 175, 176, 177, 178, 179, 180, 181, 183,
-   0,   0,   0,   0,   0,   0,   0, 186, 187, 263,
- 264, 265,   0, 267, 268, 269,   0,   0,   0, 201,
-   0,   0,   0,   0,   0, 201, 201,   0,   0,   0,
-   0, 208, 209, 210, 201, 213, 214,   0, 189,   0,
-   0,   0,   0,   0,   0,   0,   0, 101,   0,   0,
- 296,   0,   0,   0,   0,   0,   0,   0, 241,   0,
-   0, 291,   0,   0, 232,   0,   0, 106,   0,  98,
-  97,   0, 298, 246,   0,   0,   0,   0, 242,  42,
-  28,   0,   0,   0, 304,   0,   0,   0,   0,  45,
-  46,   0,  33,   0,  34, 255, 312, 256,   0,   0,
-   0,   0,   0,   0,   0, 324, 327, 329, 330,   0,
-   0,   0,  37,   0,   0, 189,   0,   0,   0,   0,
-  41,  22,  43,  29,  35,  38,   0, 238, 316,  32,
-   0,  36,  40,   0, 337,  27,  26,   0,   0,  99,
-   0,   0,  30,  31,  23,   0,   0,   0,   0,   0,
-   0, 201,   0,   0,   0,   0,   0, 297,   0,   0,
-   0,   0,   0,   0, 299,   0,   0,   0,   0, 300,
- 303,   0,   0, 305, 306, 307,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
- 106,   0,   0,   0,   0,   0,  75,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,  16,  18,   0,  68,
-  44,   0, 359,   0,   0,   0, 333,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
- 340,   0,   0,   0,   0,   0, 344,   0, 345,  42,
-  28,  55,  56,  57,  73,  69,  59,  70,   0,  45,
-  46,  71,  33,   0,  34,  63,  64,   0,   0,   0,
-   0,   0,   0,   0,   0,  75,   0,   0,   0,   0,
-  77,  78,  37,  52,   0,  16,  18,   0,  68,  44,
-  41,  22,  43,  29,  35,  38,   0,   0,   0,  32,
-  65,  36,  40,  76,   0,  27,  26,   0,   0,  25,
-   0,   0,  30,  31,  23,   0,   0,   0,  42,  28,
-  55,  56,  57,  73,  69,  59,  70,   0,  45,  46,
-  71,  33,   0,  34,  63,  64,   0,   0,   0,   0,
-   0,   0,  75,   0,   0,   0,   0,   0,   0,  77,
-  78,  37,  16,  18,   0,  68,  44,   0, 308,  41,
-  22,  43,  29,  35,  38,   0,   0,   0,  32,  65,
-  36,  40,  76,   0,  27,  26,   0,   0,  25,   0,
-   0,  30,  31,  23,   0,  42,  28,  55,  56,  57,
-  73,  69,  59,  70,   0,  45,  46,  71,  33,   0,
-  34,  63,  64,   0,   0,   0,   0,   0,   0,   0,
-   0,  75,   0,   0,   0,   0,  77,  78,  37, 273,
-   0,  16,  18,   0,  68,  44,  41,  22,  43,  29,
-  35,  38,   0,   0,   0,  32,  65,  36,  40,  76,
-   0,  27,  26,   0,   0,  25,   0,   0,  30,  31,
-  23,   0,   0,   0,  42,  28,  55,  56,  57,  73,
-  69,  59,  70,   0,  45,  46,  71,  33,   0,  34,
-  63,  64,   0,   0,   0,   0,   0,   0,  75,   0,
-   0,   0,   0,   0,   0,  77,  78,  37,  16,  18,
-   0,  68,  44,   0, 248,  41,  22,  43,  29,  35,
-  38,   0,   0,   0,  32,  65,  36,  40,  76,   0,
-  27,  26,   0,   0,  25,   0,   0,  30,  31,  23,
-   0,  42,  28,  55,  56,  57,  73,  69,  59,  70,
-   0,  45,  46,  71,  33,   0,  34,  63,  64,   0,
-   0,   0,   0,   0,   0,  75,   0,   0,   0,   0,
-   0,   0,  77,  78,  37,  16,  18,   0,  68,  44,
-   0, 247,  41,  22,  43,  29,  35,  38,   0,   0,
-   0,  32,  65,  36,  40,  76,   0,  27,  26,   0,
-   0,  25,   0,   0,  30,  31,  23,   0,  42,  28,
-  55,  56,  57,  73,  69,  59,  70,   0,  45,  46,
-  71,  33,   0,  34,  63,  64,   0,   0,   0,   0,
-   0,   0,  75,   0,   0,   0,   0,   0,   0,  77,
-  78,  37,  16,  18,   0,  68,  44,   0, 226,  41,
-  22,  43,  29,  35,  38,   0,   0,   0,  32,  65,
-  36,  40,  76,   0,  27,  26,   0,   0,  25,   0,
-   0,  30,  31,  23,   0,  42,  28,  55,  56,  57,
-  73,  69,  59,  70,   0,  45,  46,  71,  33,   0,
-  34,  63,  64,   0,   0,   0,   0,   0,   0,  75,
-   0,   0,   0,   0,   0,   0,  77,  78,  37,  16,
-  18,   0,  68,  44,   0, 216,  41,  22,  43,  29,
-  35,  38,   0,   0,   0,  32,  65,  36,  40,  76,
-   0,  27,  26,   0,   0,  25,   0,   0,  30,  31,
-  23,   0,  42,  28,  55,  56,  57,  73,  69,  59,
-  70,   0,  45,  46,  71,  33,   0,  34,  63,  64,
-   0,   0,   0,   0,   0,   0,  75,   0,   0,   0,
-   0,   0,   0,  77,  78,  37,  16,  18,   0,  68,
-  44,   0, 135,  41,  22,  43,  29,  35,  38,   0,
-   0,   0,  32,  65,  36,  40,  76,   0,  27,  26,
-   0,   0,  25,   0,   0,  30,  31,  23,   0,  42,
-  28,  55,  56,  57,  73,  69,  59,  70,   0,  45,
-  46,  71,  33,   0,  34,  63,  64,   0,   0,   0,
-   0,   0,   0,  75,   0,   0,   0,   0,   0,   0,
-  77,  78,  37,  16,  18,   0,  68,  44,   0,   0,
-  41,  22,  43,  29,  35,  38,   0,   0,   0,  32,
-  65,  36,  40,  76,   0,  27,  26,   0,   0,  25,
-   0,   0,  30,  31,  23,   0,  42,  28,  55,  56,
-  57,  73,  69,  59,  70,   0,  45,  46,  71,  33,
-   0,  34,  63,  64,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,  77,  78,  37,
-   0,   0,   0,   0,   0,   0,   0,  41,  22,  43,
-  29,  35,  38,   0,   0,   0,  32,  65,  36,  40,
-  76,   0,  27,  26,   0,   0,  25,   0,   0,  30,
-  31,  23, 190,   0, 101,  95,   0,   0, 331,   0,
-   0,   0,   0,   0,   0,  93,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,  98,  97,   0,  87,
-  88,  89,  90,  91,  92,  94,  42,  28,   0,   0,
-   0,   0,   0,   0,   0,   0,  45,  46,   0,  33,
-   0,  34,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,  37,
-   0,   0,   0,   0,   0,   0,   0,  41,  22,  43,
-  29,  35,  38,   0,  84,   0,  32,   0,  36,  40,
-   0,   0,  27,  26,   0,   0,  99,   0,   0,  30,
-  31,  23, 190,   0, 101,  95,   0,   0, 328,   0,
-   0,   0,   0,   0,   0,  93,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,  98,  97,   0,  87,
-  88,  89,  90,  91,  92,  94,  42,  28,   0,   0,
-   0,   0,   0,   0,   0,   0,  45,  46,   0,  33,
-   0,  34,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,  37,
-   0,   0,   0,   0,   0,   0,   0,  41,  22,  43,
-  29,  35,  38,   0,  84,   0,  32,   0,  36,  40,
-   0,   0,  27,  26,   0,   0,  99,   0,   0,  30,
-  31,  23, 190,   0, 101,  95,   0,   0, 326,   0,
-   0,   0,   0,   0,   0,  93,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,  98,  97,   0,  87,
-  88,  89,  90,  91,  92,  94,  42,  28,   0,   0,
-   0,   0,   0,   0,   0,   0,  45,  46,   0,  33,
-   0,  34,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,  37,
-   0,   0,   0,   0,   0,   0,   0,  41,  22,  43,
-  29,  35,  38,   0,  84,   0,  32,   0,  36,  40,
-   0,   0,  27,  26,   0,   0,  99,   0,   0,  30,
-  31,  23, 140,   0,   0, 101,  95, 139,   0,   0,
-   0,   0,   0,   0,   0,   0,  93,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,  98,  97,   0,
-  87,  88,  89,  90,  91,  92,  94,  42,  28,   0,
-   0,   0,   0,   0,   0,   0,   0,  45,  46,   0,
-  33,   0,  34,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  37,   0,   0,   0,   0,   0,   0,   0,  41,  22,
-  43,  29,  35,  38,   0,  84,   0,  32,   0,  36,
-  40,   0,   0,  27,  26,   0,   0,  99,   0,   0,
-  30,  31,  23, 190,   0, 101,  95,   0,   0, 192,
-   0,   0,   0,   0,   0,   0,  93,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,  98,  97,   0,
-  87,  88,  89,  90,  91,  92,  94,  42,  28,   0,
-   0,   0,   0,   0,   0,   0,   0,  45,  46,   0,
-  33,   0,  34,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  37,   0,   0,   0,   0,   0,   0,   0,  41,  22,
-  43,  29,  35,  38,   0,  84,   0,  32,   0,  36,
-  40,   0,   0,  27,  26, 101,  95,  99,   0, 355,
-  30,  31,  23,   0,   0,   0,  93,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,  98,  97,   0,
-  87,  88,  89,  90,  91,  92,  94,  42,  28,   0,
-   0,   0,   0,   0,   0,   0,   0,  45,  46,   0,
-  33,   0,  34,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  37,   0,   0,   0,   0,   0,   0,   0,  41,  22,
-  43,  29,  35,  38,   0,  84,   0,  32,   0,  36,
-  40,   0,   0,  27,  26, 101,  95,  99,   0, 354,
-  30,  31,  23,   0,   0,   0,  93,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,  98,  97,   0,
-  87,  88,  89,  90,  91,  92,  94,  42,  28,   0,
-   0,   0,   0,   0,   0,   0,   0,  45,  46,   0,
-  33,   0,  34,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  37,   0,   0,   0,   0,   0,   0,   0,  41,  22,
-  43,  29,  35,  38,   0,  84,   0,  32,   0,  36,
-  40,   0,   0,  27,  26, 101,  95,  99,   0, 350,
-  30,  31,  23,   0,   0,   0,  93,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,  98,  97,   0,
-  87,  88,  89,  90,  91,  92,  94,  42,  28,   0,
-   0,   0,   0,   0,   0,   0,   0,  45,  46,   0,
-  33,   0,  34,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  37,   0,   0,   0,   0,   0,   0,   0,  41,  22,
-  43,  29,  35,  38,   0,  84,   0,  32,   0,  36,
-  40,   0,   0,  27,  26,   0,   0,  99,   0,   0,
-  30,  31,  23, 101,  95, 346,   0,   0,   0,   0,
-   0,   0,   0,   0,  93,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,  98,  97,   0,  87,  88,
-  89,  90,  91,  92,  94,  42,  28,   0,   0,   0,
-   0,   0,   0,   0,   0,  45,  46,   0,  33,   0,
-  34,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  37,   0,
-   0,   0,   0,   0,   0,   0,  41,  22,  43,  29,
-  35,  38,   0,  84,   0,  32,   0,  36,  40,   0,
-   0,  27,  26, 101,  95,  99,   0, 323,  30,  31,
-  23,   0,   0,   0,  93,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,  98,  97,   0,  87,  88,
-  89,  90,  91,  92,  94,  42,  28,   0,   0,   0,
-   0,   0,   0,   0,   0,  45,  46,   0,  33,   0,
-  34,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  37,   0,
-   0,   0,   0,   0,   0,   0,  41,  22,  43,  29,
-  35,  38,   0,  84,   0,  32,   0,  36,  40,   0,
-   0,  27,  26, 101,  95,  99,   0, 320,  30,  31,
-  23,   0,   0,   0,  93,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,  98,  97,   0,  87,  88,
-  89,  90,  91,  92,  94,  42,  28,   0,   0,   0,
-   0,   0,   0,   0,   0,  45,  46,   0,  33,   0,
-  34,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  37,   0,
-   0,   0,   0,   0,   0,   0,  41,  22,  43,  29,
-  35,  38,   0,  84,   0,  32,   0,  36,  40,   0,
-   0,  27,  26, 101,  95,  99,   0, 279,  30,  31,
-  23,   0,   0,   0,  93,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,  98,  97,   0,  87,  88,
-  89,  90,  91,  92,  94,  42,  28,   0,   0,   0,
-   0,   0,   0,   0,   0,  45,  46,   0,  33,   0,
-  34,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  37,   0,
-   0,   0,   0,   0,   0,   0,  41,  22,  43,  29,
-  35,  38,   0,  84,   0,  32,   0,  36,  40,   0,
-   0,  27,  26,   0, 190,  99, 101,  95,  30,  31,
-  23,   0,   0,   0,   0,   0,   0,  93,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  98,  97,
-   0,  87,  88,  89,  90,  91,  92,  94,  42,  28,
-   0,   0,   0,   0,   0,   0,   0,   0,  45,  46,
-   0,  33,   0,  34,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,  37,   0,   0,   0,   0,   0,   0,   0,  41,
-  22,  43,  29,  35,  38,   0,  84,   0,  32,   0,
-  36,  40,   0,   0,  27,  26, 101,  95,  99,   0,
- 192,  30,  31,  23,   0,   0,   0,  93,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  98,  97,
-   0,  87,  88,  89,  90,  91,  92,  94,  42,  28,
-   0,   0,   0,   0,   0,   0,   0,   0,  45,  46,
-   0,  33,   0,  34,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,  37,   0,   0,   0,   0,   0,   0,   0,  41,
-  22,  43,  29,  35,  38,   0,  84,   0,  32,   0,
-  36,  40,   0,   0,  27,  26, 101,  95,  99,   0,
-   0,  30,  31,  23,   0,   0,   0,  93,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  98,  97,
-   0,  87,  88,  89,  90,  91,  92,  94,  42,  28,
-   0,   0,   0,   0,   0,   0,   0,   0,  45,  46,
-   0,  33,   0,  34,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,  37,   0,   0,   0,   0,   0,   0,   0,  41,
-  22,  43,  29,  35,  38,   0,  84, 251,  32,   0,
-  36,  40,   0,   0,  27,  26, 101,  95,  99,   0,
-   0,  30,  31,  23,   0,   0,   0,  93,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  98,  97,
-   0,  87,  88,  89,  90,  91,  92,  94,  42,  28,
-   0,   0,   0,   0,   0,   0,   0,   0,  45,  46,
-   0,  33,   0,  34,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,  37,   0,   0,   0,   0,   0,   0,   0,  41,
-  22,  43,  29,  35,  38,   0,  84,   0,  32,   0,
-  36,  40,   0,   0,  27,  26, 101,  95,  99,   0,
-   0,  30,  31,  23,   0,   0,   0,  93,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  98,   0,
-   0,  87,  88,  89,  90,  91,  92,  94,  42,  28,
-   0,   0,   0,   0,   0,   0,   0,   0,  45,  46,
-   0,  33,   0,  34,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,  37,   0,   0,   0,   0,   0,   0,   0,  41,
-  22,  43,  29,  35,  38, 101,  95,   0,  32,   0,
-  36,  40,   0,   0,  27,  26,  93,   0,  99,   0,
-   0,  30,  31,  23,   0,   0,   0,   0,   0,   0,
-  87,  88,  89,  90,  91,  92,  94,  42,  28,   0,
-   0,   0,   0,   0,   0,   0,   0,  45,  46,   0,
-  33,   0,  34,   0,   0,  75,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,  18,   0,   0,  44,
-  37,   0,   0,   0,   0,   0,   0,   0,  41,  22,
-  43,  29,  35,  38,   0,   0,   0,  32,   0,  36,
-  40,   0,   0,  27,  26,   0,   0,  99,  42,  28,
-  30,  31,  23,  73,   0,   0,   0,   0,  45,  46,
-   0,  33,   0,  34,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,  77,
-  78,  37,   0,   0, 101,   0,   0,   0,   0,  41,
-  22,  43,  29,  35,  38, 241,   0,   0,  32,   0,
-  36,  40,   0,   0,  27,  26,  98,  97,  25,   0,
-   0,  30,  31,  23,   0, 242,  42,  28,   0,   0,
-   0,   0,   0,   0,   0,   0,  45,  46,   0,  33,
-   0,  34,   0,   0,   0,   0,   0,  12,  13,   0,
-   0,  16,  18,   0,   0,  44,   0,   0,   0,  37,
-   0,   0,   0,   0,   0,   0,   0,  41,  22,  43,
-  29,  35,  38,   0, 238,   0,  32,   0,  36,  40,
-   0,   0,  27,  26,  42,  28,  99,   0,   0,  30,
-  31,  23,   0,  14,  45,  46,   0,  33,   0,  34,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,  37,   0,   0,
- 101,   0,   0,   0,   0,  41,  22,  43,  29,  35,
-  38, 241,   0,   0,  32,   0,  36,  40,   0,   0,
-  27,  26,  98,   0,  25,   0,   0,  30,  31,  23,
-   0, 242,  42,  28,   0,   0,   0,   0,   0,   0,
-   0,   0,  45,  46,   0,  33,   0,  34,   0,   0,
-   0,   0,   0,   0,   0, 140,   0,   0,  18,   0,
- 139,  44,   0,   0,   0,  37,   0,   0,   0,   0,
-   0,   0,   0,  41,  22,  43,  29,  35,  38,   0,
- 254,   0,  32,  18,  36,  40,  44,   0,  27,  26,
-  42,  28,  99,   0,   0,  30,  31,  23,   0,   0,
-  45,  46,   0,  33,   0,  34,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,  42,  28,   0,   0,   0,
-   0,   0,   0,  37,   0,  45,  46,   0,  33,   0,
-  34,  41,  22,  43,  29,  35,  38,   0,   0,   0,
-  32,   0,  36,  40,   0,   0,  27,  26,  37,   0,
-  25, 101,   0,  30,  31,  23,  41,  22,  43,  29,
-  35,  38, 241,   0,   0,  32,   0,  36,  40,   0,
-   0,  27,  26,   0,   0,  25,   0,   0,  30,  31,
-  23,   0, 242,  42,  28,   0,   0,   0,   0,   0,
-   0,   0,   0,  45,  46,   0,  33,   0,  34,   0,
-   0,   0,   0,   0,   0,   0, 174,   0,   0, 284,
-   0,   0,  44,   0,   0,   0,  37,   0,   0,   0,
-   0,   0,   0,   0,  41,  22,  43,  29,  35,  38,
-   0, 172,   0,  32, 284,  36,  40,  44,   0,  27,
-  26,  42,  28,  99,   0,   0,  30,  31,  23,   0,
-   0,  45,  46,   0,  33,   0,  34,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,  42,  28,   0,   0,
-   0,   0,   0,   0,  37,   0,  45,  46,   0,  33,
-   0,  34,  41,  22,  43,  29,  35,  38,   0, 254,
-   0,  32, 284,  36,  40,  44,   0,  27,  26,  37,
-   0,  25,   0,   0,  30,  31,  23,  41,  22,  43,
-  29,  35,  38,   0,   0,   0,  32,  18,  36,  40,
-  44, 204,  27,  26,  42,  28,  25,   0,   0,  30,
-  31,  23,   0,   0,  45,  46,   0,  33,   0,  34,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,  42,
-  28,   0,   0,   0,   0,   0,   0,  37,   0,  45,
-  46,   0,  33,   0,  34,  41,  22,  43,  29,  35,
-  38,   0,   0,   0,  32,  18,  36,  40,  44, 202,
-  27,  26,  37,   0,  25,   0,   0,  30,  31,  23,
-  41,  22,  43,  29,  35,  38,   0, 174,   0,  32,
-  18,  36,  40,  44,   0,  27,  26,  42,  28,  25,
-   0,   0,  30,  31,  23,   0,   0,  45,  46,   0,
-  33,   0,  34,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,  42,  28,   0,   0,   0,   0,   0,   0,
-  37,   0,  45,  46,   0,  33,   0,  34,  41,  22,
-  43,  29,  35,  38,   0, 172,   0,  32,  18,  36,
-  40,  44,   0,  27,  26,  37,   0,  25,   0,   0,
-  30,  31,  23,  41,  22,  43,  29,  35,  38,   0,
-   0,   0,  32,  18,  36,  40,  44,   0,  27,  26,
-  42,  28,  25,   0,   0,  30,  31,  23,   0,   0,
-  45,  46,   0,  33,   0,  34,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,  42,  28,   0,   0,   0,
-   0,   0,   0,  37,   0,  45,  46,   0,  33,   0,
-  34,  41,  22,  43,  29,  35,  38,   0,   0,   0,
-  32, 284,  36,  40,  44,   0,  27,  26,  37,   0,
-  25,   0,   0,  30,  31,  23,  41,  22,  43,  29,
-  35,  38,   0,   0,   0,  32, 101,  36,  40,   0,
-   0,  27,  26,  42,  28,  25,   0,   0,  30,  31,
-  23,   0,   0,  45,  46,   0,  33,   0,  34,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  42,  28,
-   0,   0,   0,   0,   0,   0,  37,   0,  45,  46,
-   0,  33,   0,  34,  41,  22,  43,  29,  35,  38,
-   0,   0, 193,  32, 161,  36,  40,  44,   0,  27,
-  26,  37,   0,  25,   0,   0,  30,  31,  23,  41,
-  22,  43,  29,  35,  38,   0,   0,   0,  32, 101,
-  36,  40,  44,   0,  27,  26,  42,  28,  99,   0,
-   0,  30,  31,  23,   0,   0,  45,  46,   0,  33,
-   0,  34,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,  42,  28,   0,   0,   0,   0,   0,   0,  37,
-   0,  45,  46,   0,  33,   0,  34,  41,  22,  43,
-  29,  35,  38,   0,   0,   0,  32, 101,  36,  40,
-   0,   0,  27,  26,  37,   0,  25,   0,   0,  30,
-  31,  23,  41,  22,  43,  29,  35,  38,   0,   0,
-   0,  32, 101,  36,  40,   0,   0,  27,  26,  42,
-  28,  25,   0,   0,  30,  31,  23,   0,   0,  45,
-  46,   0,  33,   0,  34,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,  42,  28,   0,   0,   0,   0,
-   0,   0,  37,   0,  45,  46,   0,  33,   0,  34,
-  41,  22,  43,  29,  35,  38,   0,   0,   0,  32,
-   0,  36,  40,   0,   0,  27,  26,  37,   0,  99,
-   0,   0,  30,  31,  23,  41,  22,  43,  29,  35,
-  38,   0,   0,   0,   0,   0,  36,  40,   0,   0,
-  27,  26,   0,   0,  99,   0,   0,  30,  31,  23
-};
-short	yypact[] =
-{
- 191,-1000,-1000,-1000,3259, 193,-1000,-1000, 185,-1000,
- 205, 863, 206, 206, -50,2903,-1000, -63,3810,-1000,
-  19,  38,-1000,4034,-1000,3976,4034,4034, 200, 199,
- -33, -33,   5, 192, 184,-1000, 183, 170,-1000, 158,
- 157,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,3259,
- 863,3810,-1000,1334,-1000, 124,3810, 124, 214,3385,
--1000,1401, 863, 124, 124,3385, 124,-1000, 211,-1000,
- 148, 146,3951, -22,2903,-1000, 138,-1000,-1000, 863,
- 863, 134,-1000,-1000,3810,3785,3727,3810,3810,3810,
-3810,3810,3810,3810, -22, -74,  19,-1000,-1000,4034,
- -94,3810,3810,-1000,-1000, 181,1902,3893,4034,4034,
-4034,4034,4034,3810,-1000,-1000, -89, -89, -89,3702,
-3644,-1000,-1000,   7,4034,3810,3810,3810,3810,3810,
-3810, -70,-1000,1267, 206,-1000,-1000,-1000, 213, 211,
--1000,1802,-1000,-1000,1401,1802,-1000, -49,1200,-1000,
--1000,1802,-1000,-1000,1401,-1000, 213,3133,3810, 104,
- 208,3810,3201, -65,-1000,  19,  33,3810,1133,1066,
- -57,2813,-1000,2993,-1000,3072,4059,4059,4059,4059,
-4059,4059,-1000,4059,-1000, -33,2723,2903,   4,3410,
--1000,3410,-1000,4034, -89,  26,  26, -89, -89, -89,
-  86,2903,-1000, 174,-1000, 151,4034,  19,2633,2633,
-2633, 149, 208,2633,2633,  89,-1000, 863,-1000,-1000,
--1000,-1000,-1000, 999,-1000, 212,-1000,-1000,-1000, 101,
-  37,-1000,2540,4034,4034,4034,3619, 147,3868,3561,
-3536,3868, -22,  19,3868,3810,2540,-1000,-1000, 139,
--1000,3810,-1000, -22,-1000,2903,2903,  19,3410,-1000,
--1000,-1000,  19,3410,3410,  31,-1000,3410,3410,3410,
--1000, 930, -80,-1000,-1000,-1000, 133, -22, 194,-1000,
-  19,  19,  19,3201,3810,  -6, 634,3327,3478,-1000,
-4059,-1000,3201,  40, 194, 194,  15,2903,-1000,2903,
-2450,  78,  77,2360, 121,1701,1601,1501,-1000, 111,
-3810, 211,  41,-1000, 120, -22,3868,-1000, 206,-1000,
--1000,-1000,-1000,-1000,3410,-1000,-1000,  -8,-1000,  -8,
-3410,-1000,3810,2270,3133, 194,  -6,-1000,3201, 863,
-2172,  66,  55,  48,2082,1992, 211,  41,1401, 794,
--1000,-1000,-1000,-1000,-1000, 124,3133, 194,-1000,-1000,
--1000,  41,1401, 194,-1000,1401,-1000
-};
-short	yypgo[] =
-{
-   0, 297, 505,  40,  11, 295,   7, 286, 243, 199,
-  62,  34, 283,  10,   9,   5,  20,   8,   0, 418,
- 278, 276, 273, 268, 265, 264, 263,   3, 262, 229,
-  85, 261,   1, 400,  17,  13, 103,  87, 260, 258,
- 255, 254, 249, 246, 232, 231, 230, 228, 227
-};
-short	yyr1[] =
-{
-   0,  40,  40,  36,  36,  37,  37,  33,  33,  26,
-  26,  24,  24,  41,  22,  42,  22,  43,  22,  20,
-  20,  23,  30,  30,  34,  34,  35,  35,  29,  29,
-  15,  15,   1,   1,  10,  11,  11,  11,  11,  11,
-  11,  11,  44,  11,  12,  12,   6,   6,   3,   3,
-   3,   3,   3,   3,   3,   3,   3,   3,   3,   2,
-   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-   2,   2,   2,   2,   2,   2,   2,   2,   4,   4,
-   5,   5,   7,   7,   7,  39,  39,  28,  28,  28,
-  28,  31,  31,   9,   9,  45,  13,  32,  32,  14,
-  14,  14,  14,  14,  14,  14,  14,  27,  27,  16,
-  16,  16,  46,  47,  16,  16,  16,  16,  16,  16,
-  16,  16,  16,  16,  16,  16,  48,  16,  16,  17,
-  17,  38,  38,   8,   8,   8,   8,   8,   8,   8,
-   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,
-   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,
-   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,
-   8,   8,   8,   8,  18,  18,  18,  18,  21,  21,
-  21,  19,  19,  19,  25
-};
-short	yyr2[] =
-{
-   0,   1,   1,   1,   2,   1,   2,   1,   2,   1,
-   2,   1,   2,   0,  12,   0,  10,   0,   8,   1,
-   1,   4,   1,   2,   1,   2,   0,   1,   0,   1,
-   0,   1,   1,   3,   1,   1,   4,   3,   6,   3,
-   4,   4,   0,   9,   1,   3,   1,   3,   3,   5,
-   3,   3,   3,   3,   3,   5,   2,   1,   1,   3,
-   5,   3,   3,   3,   3,   3,   3,   3,   3,   3,
-   3,   3,   5,   4,   3,   2,   1,   1,   3,   3,
-   1,   3,   0,   1,   3,   1,   1,   1,   1,   2,
-   2,   1,   2,   1,   2,   0,   4,   1,   2,   4,
-   4,   4,   2,   5,   2,   1,   1,   1,   2,   2,
-   3,   2,   0,   0,   9,   3,   2,   1,   4,   2,
-   3,   2,   2,   3,   2,   2,   0,   3,   2,   1,
-   2,   1,   1,   4,   3,   3,   3,   3,   3,   3,
-   2,   2,   2,   3,   4,   1,   3,   4,   2,   2,
-   2,   2,   4,   3,   2,   1,   6,   6,   3,   6,
-   6,   1,   8,   8,   6,   4,   1,   6,   6,   8,
-   8,   8,   6,   1,   1,   4,   1,   2,   0,   1,
-   3,   1,   1,   1,   4
-};
-short	yychk[] =
-{
--1000, -40,  -1,   2, -29, -28,  10,  15, -12, -11,
- -10, -30,   8,   9,  54,  -2,  12, -18,  13,  -9,
-  -8, -19,  87, 110, -13, 105, 102, 101,  46,  89,
- 108, 109,  95,  58,  60,  90,  97,  78,  91, -38,
-  98,  86,  45,  88,  16,  55,  56,  10,  15, -29,
- -30,  11,  10, -17, -16,  47,  48,  49, -26,  52,
- -22, -23, -30,  61,  62,  96, -14, -25,  15,  51,
-  53,  57, -39,  50,  -2,   2,  99,  76,  77, -30,
- -30, -20,  86,  89,  93, -37, -36,  38,  39,  40,
-  41,  42,  43,  24,  44,  14,  -8,  36,  35, 105,
- -18,  13,  69, 108, 109,  -4,  -2,  16, 101, 102,
- 103, 104, 107,  19,  -8,  -9,  -8,  -8,  -8,  13,
-  13, -18, -18, -18,  42,  13,  13,  13,  13,  13,
-  13, -45, -11, -17, -10,  18, -16, -27, -34,  15,
-  10,  -2, -27,  10, -46,  -2, -27, -16, -17, -27,
- -27,  -2, -27, -27, -48, -35, -34,  13,  13,  -7,
-  -5,  13,  -3, -18,  -9,  -8, -19,  13, -17, -17,
-  13,  -2,  10,  -2,  10,  -2,  -2,  -2,  -2,  -2,
-  -2,  -2, -13,  -2, -19,  95,  -2,  -2,  17, -33,
-  11, -33,  17,  69,  -8,  -8,  -8,  -8,  -8,  -8,
-  -6,  -2,  17,  -6,  17,  -6,  42,  -8,  -2,  -2,
-  -2,  -6, -13,  -2,  -2,  92,  18, -30,  10, -35,
- -27, -16, -27, -24,  79, -31,  18, -27, -16, -15,
- -19, -14,  -2,  14,  37,  40, -33,  -4,  93, -37,
- -36,  24,  44,  -8,  69,  19,  -2,  18,  18, -21,
-  86,  94, -18,  44,  10,  -2,  -2,  -8, -33,  20,
-  17,  17,  -8, -33, -33, -33,  17, -33, -33, -33,
-  16, -17, -47,  10, -16,  10,  15,  44, -32,  17,
-  -8,  -8,  -8,  -3,  13,  17,  -3,  -3,  -3, -13,
-  -3, -19,  -3,  -6, -32, -32, -33,  -2, -19,  -2,
-  -2, -13, -13,  -2, -19,  -2,  -2,  -2,  18,  99,
- -35,  15, -19,  10,  -4,  44,  94,  20, -44,  86,
-  17,  17,  17,  17, -33,  17,  17, -33,  17, -33,
- -33,  17,  13,  -2, -35, -32,  17, -19,  -3, -30,
-  -2, -13, -18, -18,  -2,  -2,  15, -15, -43, -17,
-  17,  17,  17,  17,  17,  17, -35, -32, -16,  18,
- -27, -15, -42, -32, -16, -41, -16
-};
-short	yydef[] =
-{
-  -2,  -2,   1,   2,  32,  29,  87,  88,  28,  44,
-  35,   0,   0,   0,   0,  34,  22, 173,   0,  76,
-  77, 174, 176,   0,  93,   0,   0,   0, 145,   0,
-   0,   0, 155,   0,   0, 161,   0,   0, 166,   0,
-   0, 181, 182, 183,  95, 131, 132,  89,  90,  33,
-   0,   0,  23,   0, 129,   0,   0,   0, 112,   0,
- 117,   0,   0,   0,   0,   0,   0, 126,  26,   9,
-   0,   0,  82,   0, 105, 106,   0,  85,  86,   0,
-   0,   0,  19,  20,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,  75,   5,   3,   0,
- 173,   0,   0, 150, 151,   0,   0,   0,   0,   0,
-   0,   0,   0,   0, 177,  94, 142, 140, 141,   0,
-   0, 148, 149, 154,   0,   0,   0,   0,   0,   0,
-   0,   0,  45,   0,  37,  39, 130, 109, 107,  26,
-  24,   0, 111,  10,   0,   0, 116, 119,   0, 121,
- 122,   0, 124, 125,   0, 128,  27,  -2,   0, 102,
-  83,   0,  80, 173,  57,  58, 104,   0,   0,   0,
- 178,   0,   6,  61,   4,  62,  -2,  -2,  -2,  -2,
-  -2,  -2,  69,  -2,  71,  74,   0,  59,   0,   0,
-   7,   0, 158,   0, 137, 134, 135, 136, 138, 139,
-   0,  46, 143,   0, 146,   0,   0, 153,   0,   0,
-   0,   0,  93,   0,   0,   0,  36,   0,  25, 108,
- 110, 113, 115,   0,  11, 120,  91, 123, 127,   0,
- 174,  31,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,  56,   0,   0,   0,  40,  41,   0,
- 179,   0,  73,   0,   8,  79,  78, 133,   0, 175,
- 144, 147, 152,   0,   0,   0, 165,   0,   0,   0,
-  96,   0,   0,  12, 118,  92,  26,   0,  21,  97,
-  99, 100, 101,  81,   0,  84,   0,  50,  51,  52,
-  -2,  54,  48,   0, 184,  42,   0,  60,  72,  47,
-   0,  93,  93,   0,   0,   0,   0,   0,  38,   0,
-   0,  26,   0,  98,   0,   0,   0, 103,   0, 180,
- 156, 157, 159, 160,   0, 164, 167,   0, 168,   0,
-   0, 172,   0,   0,  -2,  17,   0,  55,  49,   0,
-   0,  93,   0,   0,   0,   0,  26,   0,   0,   0,
- 162, 163, 169, 170, 171,   0,  -2,  15,  18,  43,
- 114,   0,   0,  13,  16,   0,  14
-};
-short	yytok1[] =
-{
-   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0, 104,   0,   0,
-  13,  17, 103, 101,  11, 102,   0,  16,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,  94,  15,
-   0,   0,   0,  93,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,  19,   0,  20,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,  12,  14,  18
-};
-short	yytok2[] =
-{
-   2,   3,   4,   5,   6,   7,   8,   9,  10,  21,
-  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
-  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
-  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,
-  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,
-  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,
-  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,
-  92,  95,  96,  97,  98,  99, 100, 105, 106, 107,
- 108, 109, 110, 111
-};
-long	yytok3[] =
-{
-   0
-};
-#define YYFLAG 		-1000
-#define YYERROR		goto yyerrlab
-#define YYACCEPT	return(0)
-#define YYABORT		return(1)
-#define	yyclearin	yychar = -1
-#define	yyerrok		yyerrflag = 0
-
-#ifdef	yydebug
-#include	"y.debug"
-#else
-#define	yydebug		0
-char*	yytoknames[1];		/* for debugging */
-char*	yystates[1];		/* for debugging */
-#endif
-
-/*	parser for yacc output	*/
-
-int	yynerrs = 0;		/* number of errors */
-int	yyerrflag = 0;		/* error recovery flag */
-
-char*
-yytokname(int yyc)
-{
-	static char x[16];
-
-	if(yyc > 0 && yyc <= sizeof(yytoknames)/sizeof(yytoknames[0]))
-	if(yytoknames[yyc-1])
-		return yytoknames[yyc-1];
-	sprintf(x, "<%d>", yyc);
-	return x;
-}
-
-char*
-yystatname(int yys)
-{
-	static char x[16];
-
-	if(yys >= 0 && yys < sizeof(yystates)/sizeof(yystates[0]))
-	if(yystates[yys])
-		return yystates[yys];
-	sprintf(x, "<%d>\n", yys);
-	return x;
-}
-
-long
-yylex1(void)
-{
-	long yychar;
-	long *t3p;
-	int c;
-
-	yychar = yylex();
-	if(yychar <= 0) {
-		c = yytok1[0];
-		goto out;
-	}
-	if(yychar < sizeof(yytok1)/sizeof(yytok1[0])) {
-		c = yytok1[yychar];
-		goto out;
-	}
-	if(yychar >= YYPRIVATE)
-		if(yychar < YYPRIVATE+sizeof(yytok2)/sizeof(yytok2[0])) {
-			c = yytok2[yychar-YYPRIVATE];
-			goto out;
-		}
-	for(t3p=yytok3;; t3p+=2) {
-		c = t3p[0];
-		if(c == yychar) {
-			c = t3p[1];
-			goto out;
-		}
-		if(c == 0)
-			break;
-	}
-	c = 0;
-
-out:
-	if(c == 0)
-		c = yytok2[1];	/* unknown char */
-	if(yydebug >= 3)
-		printf("lex %.4lX %s\n", yychar, yytokname(c));
-	return c;
-}
-
-int
-yyparse(void)
-{
-	struct
-	{
-		YYSTYPE	yyv;
-		int	yys;
-	} yys[YYMAXDEPTH], *yyp, *yypt;
-	short *yyxi;
-	int yyj, yym, yystate, yyn, yyg;
-	YYSTYPE save1, save2;
-	int save3, save4;
-	long yychar;
-
-	save1 = yylval;
-	save2 = yyval;
-	save3 = yynerrs;
-	save4 = yyerrflag;
-
-	yystate = 0;
-	yychar = -1;
-	yynerrs = 0;
-	yyerrflag = 0;
-	yyp = &yys[-1];
-	goto yystack;
-
-ret0:
-	yyn = 0;
-	goto ret;
-
-ret1:
-	yyn = 1;
-	goto ret;
-
-ret:
-	yylval = save1;
-	yyval = save2;
-	yynerrs = save3;
-	yyerrflag = save4;
-	return yyn;
-
-yystack:
-	/* put a state and value onto the stack */
-	if(yydebug >= 4)
-		printf("char %s in %s", yytokname(yychar), yystatname(yystate));
-
-	yyp++;
-	if(yyp >= &yys[YYMAXDEPTH]) {
-		yyerror("yacc stack overflow");
-		goto ret1;
-	}
-	yyp->yys = yystate;
-	yyp->yyv = yyval;
-
-yynewstate:
-	yyn = yypact[yystate];
-	if(yyn <= YYFLAG)
-		goto yydefault; /* simple state */
-	if(yychar < 0)
-		yychar = yylex1();
-	yyn += yychar;
-	if(yyn < 0 || yyn >= YYLAST)
-		goto yydefault;
-	yyn = yyact[yyn];
-	if(yychk[yyn] == yychar) { /* valid shift */
-		yychar = -1;
-		yyval = yylval;
-		yystate = yyn;
-		if(yyerrflag > 0)
-			yyerrflag--;
-		goto yystack;
-	}
-
-yydefault:
-	/* default state action */
-	yyn = yydef[yystate];
-	if(yyn == -2) {
-		if(yychar < 0)
-			yychar = yylex1();
-
-		/* look through exception table */
-		for(yyxi=yyexca;; yyxi+=2)
-			if(yyxi[0] == -1 && yyxi[1] == yystate)
-				break;
-		for(yyxi += 2;; yyxi += 2) {
-			yyn = yyxi[0];
-			if(yyn < 0 || yyn == yychar)
-				break;
-		}
-		yyn = yyxi[1];
-		if(yyn < 0)
-			goto ret0;
-	}
-	if(yyn == 0) {
-		/* error ... attempt to resume parsing */
-		switch(yyerrflag) {
-		case 0:   /* brand new error */
-			yyerror("syntax error");
-			if(yydebug >= 1) {
-				printf("%s", yystatname(yystate));
-				printf("saw %s\n", yytokname(yychar));
-			}
-yyerrlab:
-			yynerrs++;
-
-		case 1:
-		case 2: /* incompletely recovered error ... try again */
-			yyerrflag = 3;
-
-			/* find a state where "error" is a legal shift action */
-			while(yyp >= yys) {
-				yyn = yypact[yyp->yys] + YYERRCODE;
-				if(yyn >= 0 && yyn < YYLAST) {
-					yystate = yyact[yyn];  /* simulate a shift of "error" */
-					if(yychk[yystate] == YYERRCODE)
-						goto yystack;
-				}
-
-				/* the current yyp has no shift onn "error", pop stack */
-				if(yydebug >= 2)
-					printf("error recovery pops state %d, uncovers %d\n",
-						yyp->yys, (yyp-1)->yys );
-				yyp--;
-			}
-			/* there is no state on the stack with an error shift ... abort */
-			goto ret1;
-
-		case 3:  /* no shift yet; clobber input char */
-			if(yydebug >= YYEOFCODE)
-				printf("error recovery discards %s\n", yytokname(yychar));
-			if(yychar == YYEOFCODE)
-				goto ret1;
-			yychar = -1;
-			goto yynewstate;   /* try again in the same state */
-		}
-	}
-
-	/* reduction by production yyn */
-	if(yydebug >= 2)
-		printf("reduce %d in:\n\t%s", yyn, yystatname(yystate));
-
-	yypt = yyp;
-	yyp -= yyr2[yyn];
-	yyval = (yyp+1)->yyv;
-	yym = yyn;
-
-	/* consult goto table to find next state */
-	yyn = yyr1[yyn];
-	yyg = yypgo[yyn];
-	yyj = yyg + yyp->yys + 1;
-
-	if(yyj >= YYLAST || yychk[yystate=yyact[yyj]] != -yyn)
-		yystate = yyact[yyg];
-	switch(yym) {
-		
-case 1:
-#line	100	"/sys/src/cmd/awk/awkgram.y"
-{ if (errorflag==0)
-			winner = (Node *)stat3(PROGRAM, beginloc, yypt[-0].yyv.p, endloc); } break;
-case 2:
-#line	102	"/sys/src/cmd/awk/awkgram.y"
-{ yyclearin; bracecheck(); SYNTAX("bailing out"); } break;
-case 13:
-#line	126	"/sys/src/cmd/awk/awkgram.y"
-{inloop++;} break;
-case 14:
-#line	127	"/sys/src/cmd/awk/awkgram.y"
-{ --inloop; yyval.p = stat4(FOR, yypt[-9].yyv.p, notnull(yypt[-6].yyv.p), yypt[-3].yyv.p, yypt[-0].yyv.p); } break;
-case 15:
-#line	128	"/sys/src/cmd/awk/awkgram.y"
-{inloop++;} break;
-case 16:
-#line	129	"/sys/src/cmd/awk/awkgram.y"
-{ --inloop; yyval.p = stat4(FOR, yypt[-7].yyv.p, NIL, yypt[-3].yyv.p, yypt[-0].yyv.p); } break;
-case 17:
-#line	130	"/sys/src/cmd/awk/awkgram.y"
-{inloop++;} break;
-case 18:
-#line	131	"/sys/src/cmd/awk/awkgram.y"
-{ --inloop; yyval.p = stat3(IN, yypt[-5].yyv.p, makearr(yypt[-3].yyv.p), yypt[-0].yyv.p); } break;
-case 19:
-#line	135	"/sys/src/cmd/awk/awkgram.y"
-{ setfname(yypt[-0].yyv.cp); } break;
-case 20:
-#line	136	"/sys/src/cmd/awk/awkgram.y"
-{ setfname(yypt[-0].yyv.cp); } break;
-case 21:
-#line	140	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = notnull(yypt[-1].yyv.p); } break;
-case 26:
-#line	152	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.i = 0; } break;
-case 28:
-#line	157	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.i = 0; } break;
-case 30:
-#line	163	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = 0; } break;
-case 32:
-#line	168	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = 0; } break;
-case 33:
-#line	169	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = yypt[-1].yyv.p; } break;
-case 34:
-#line	173	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = notnull(yypt[-0].yyv.p); } break;
-case 35:
-#line	177	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat2(PASTAT, yypt[-0].yyv.p, stat2(PRINT, rectonode(), NIL)); } break;
-case 36:
-#line	178	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat2(PASTAT, yypt[-3].yyv.p, yypt[-1].yyv.p); } break;
-case 37:
-#line	179	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = pa2stat(yypt[-2].yyv.p, yypt[-0].yyv.p, stat2(PRINT, rectonode(), NIL)); } break;
-case 38:
-#line	180	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = pa2stat(yypt[-5].yyv.p, yypt[-3].yyv.p, yypt[-1].yyv.p); } break;
-case 39:
-#line	181	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat2(PASTAT, NIL, yypt[-1].yyv.p); } break;
-case 40:
-#line	183	"/sys/src/cmd/awk/awkgram.y"
-{ beginloc = linkum(beginloc, yypt[-1].yyv.p); yyval.p = 0; } break;
-case 41:
-#line	185	"/sys/src/cmd/awk/awkgram.y"
-{ endloc = linkum(endloc, yypt[-1].yyv.p); yyval.p = 0; } break;
-case 42:
-#line	186	"/sys/src/cmd/awk/awkgram.y"
-{infunc++;} break;
-case 43:
-#line	187	"/sys/src/cmd/awk/awkgram.y"
-{ infunc--; curfname=0; defn((Cell *)yypt[-7].yyv.p, yypt[-5].yyv.p, yypt[-1].yyv.p); yyval.p = 0; } break;
-case 45:
-#line	192	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = linkum(yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 47:
-#line	197	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = linkum(yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 48:
-#line	201	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(yypt[-1].yyv.i, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 49:
-#line	203	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(CONDEXPR, notnull(yypt[-4].yyv.p), yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 50:
-#line	205	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(BOR, notnull(yypt[-2].yyv.p), notnull(yypt[-0].yyv.p)); } break;
-case 51:
-#line	207	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(AND, notnull(yypt[-2].yyv.p), notnull(yypt[-0].yyv.p)); } break;
-case 52:
-#line	208	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(yypt[-1].yyv.i, NIL, yypt[-2].yyv.p, (Node*)makedfa(yypt[-0].yyv.s, 0)); } break;
-case 53:
-#line	210	"/sys/src/cmd/awk/awkgram.y"
-{ if (constnode(yypt[-0].yyv.p))
-			yyval.p = op3(yypt[-1].yyv.i, NIL, yypt[-2].yyv.p, (Node*)makedfa(strnode(yypt[-0].yyv.p), 0));
-		  else
-			yyval.p = op3(yypt[-1].yyv.i, (Node *)1, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 54:
-#line	214	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(INTEST, yypt[-2].yyv.p, makearr(yypt[-0].yyv.p)); } break;
-case 55:
-#line	215	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(INTEST, yypt[-3].yyv.p, makearr(yypt[-0].yyv.p)); } break;
-case 56:
-#line	216	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(CAT, yypt[-1].yyv.p, yypt[-0].yyv.p); } break;
-case 59:
-#line	222	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(yypt[-1].yyv.i, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 60:
-#line	224	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(CONDEXPR, notnull(yypt[-4].yyv.p), yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 61:
-#line	226	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(BOR, notnull(yypt[-2].yyv.p), notnull(yypt[-0].yyv.p)); } break;
-case 62:
-#line	228	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(AND, notnull(yypt[-2].yyv.p), notnull(yypt[-0].yyv.p)); } break;
-case 63:
-#line	229	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(yypt[-1].yyv.i, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 64:
-#line	230	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(yypt[-1].yyv.i, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 65:
-#line	231	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(yypt[-1].yyv.i, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 66:
-#line	232	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(yypt[-1].yyv.i, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 67:
-#line	233	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(yypt[-1].yyv.i, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 68:
-#line	234	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(yypt[-1].yyv.i, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 69:
-#line	235	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(yypt[-1].yyv.i, NIL, yypt[-2].yyv.p, (Node*)makedfa(yypt[-0].yyv.s, 0)); } break;
-case 70:
-#line	237	"/sys/src/cmd/awk/awkgram.y"
-{ if (constnode(yypt[-0].yyv.p))
-			yyval.p = op3(yypt[-1].yyv.i, NIL, yypt[-2].yyv.p, (Node*)makedfa(strnode(yypt[-0].yyv.p), 0));
-		  else
-			yyval.p = op3(yypt[-1].yyv.i, (Node *)1, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 71:
-#line	241	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(INTEST, yypt[-2].yyv.p, makearr(yypt[-0].yyv.p)); } break;
-case 72:
-#line	242	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(INTEST, yypt[-3].yyv.p, makearr(yypt[-0].yyv.p)); } break;
-case 73:
-#line	243	"/sys/src/cmd/awk/awkgram.y"
-{ 
-			if (safe) SYNTAX("cmd | getline is unsafe");
-			else yyval.p = op3(GETLINE, yypt[-0].yyv.p, itonp(yypt[-2].yyv.i), yypt[-3].yyv.p); } break;
-case 74:
-#line	246	"/sys/src/cmd/awk/awkgram.y"
-{ 
-			if (safe) SYNTAX("cmd | getline is unsafe");
-			else yyval.p = op3(GETLINE, (Node*)0, itonp(yypt[-1].yyv.i), yypt[-2].yyv.p); } break;
-case 75:
-#line	249	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(CAT, yypt[-1].yyv.p, yypt[-0].yyv.p); } break;
-case 78:
-#line	255	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = linkum(yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 79:
-#line	256	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = linkum(yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 81:
-#line	261	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = linkum(yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 82:
-#line	265	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = rectonode(); } break;
-case 84:
-#line	267	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = yypt[-1].yyv.p; } break;
-case 93:
-#line	284	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(MATCH, NIL, rectonode(), (Node*)makedfa(yypt[-0].yyv.s, 0)); } break;
-case 94:
-#line	285	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(NOT, notnull(yypt[-0].yyv.p)); } break;
-case 95:
-#line	289	"/sys/src/cmd/awk/awkgram.y"
-{startreg();} break;
-case 96:
-#line	289	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.s = yypt[-1].yyv.s; } break;
-case 99:
-#line	297	"/sys/src/cmd/awk/awkgram.y"
-{ 
-			if (safe) SYNTAX("print | is unsafe");
-			else yyval.p = stat3(yypt[-3].yyv.i, yypt[-2].yyv.p, itonp(yypt[-1].yyv.i), yypt[-0].yyv.p); } break;
-case 100:
-#line	300	"/sys/src/cmd/awk/awkgram.y"
-{
-			if (safe) SYNTAX("print >> is unsafe");
-			else yyval.p = stat3(yypt[-3].yyv.i, yypt[-2].yyv.p, itonp(yypt[-1].yyv.i), yypt[-0].yyv.p); } break;
-case 101:
-#line	303	"/sys/src/cmd/awk/awkgram.y"
-{
-			if (safe) SYNTAX("print > is unsafe");
-			else yyval.p = stat3(yypt[-3].yyv.i, yypt[-2].yyv.p, itonp(yypt[-1].yyv.i), yypt[-0].yyv.p); } break;
-case 102:
-#line	306	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat3(yypt[-1].yyv.i, yypt[-0].yyv.p, NIL, NIL); } break;
-case 103:
-#line	307	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat2(DELETE, makearr(yypt[-3].yyv.p), yypt[-1].yyv.p); } break;
-case 104:
-#line	308	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat2(DELETE, makearr(yypt[-0].yyv.p), 0); } break;
-case 105:
-#line	309	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = exptostat(yypt[-0].yyv.p); } break;
-case 106:
-#line	310	"/sys/src/cmd/awk/awkgram.y"
-{ yyclearin; SYNTAX("illegal statement"); } break;
-case 109:
-#line	319	"/sys/src/cmd/awk/awkgram.y"
-{ if (!inloop) SYNTAX("break illegal outside of loops");
-				  yyval.p = stat1(BREAK, NIL); } break;
-case 110:
-#line	321	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat1(CLOSE, yypt[-1].yyv.p); } break;
-case 111:
-#line	322	"/sys/src/cmd/awk/awkgram.y"
-{  if (!inloop) SYNTAX("continue illegal outside of loops");
-				  yyval.p = stat1(CONTINUE, NIL); } break;
-case 112:
-#line	324	"/sys/src/cmd/awk/awkgram.y"
-{inloop++;} break;
-case 113:
-#line	324	"/sys/src/cmd/awk/awkgram.y"
-{--inloop;} break;
-case 114:
-#line	325	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat2(DO, yypt[-6].yyv.p, notnull(yypt[-2].yyv.p)); } break;
-case 115:
-#line	326	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat1(EXIT, yypt[-1].yyv.p); } break;
-case 116:
-#line	327	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat1(EXIT, NIL); } break;
-case 118:
-#line	329	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat3(IF, yypt[-3].yyv.p, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 119:
-#line	330	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat3(IF, yypt[-1].yyv.p, yypt[-0].yyv.p, NIL); } break;
-case 120:
-#line	331	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = yypt[-1].yyv.p; } break;
-case 121:
-#line	332	"/sys/src/cmd/awk/awkgram.y"
-{ if (infunc)
-				SYNTAX("next is illegal inside a function");
-			  yyval.p = stat1(NEXT, NIL); } break;
-case 122:
-#line	335	"/sys/src/cmd/awk/awkgram.y"
-{ if (infunc)
-				SYNTAX("nextfile is illegal inside a function");
-			  yyval.p = stat1(NEXTFILE, NIL); } break;
-case 123:
-#line	338	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat1(RETURN, yypt[-1].yyv.p); } break;
-case 124:
-#line	339	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = stat1(RETURN, NIL); } break;
-case 126:
-#line	341	"/sys/src/cmd/awk/awkgram.y"
-{inloop++;} break;
-case 127:
-#line	341	"/sys/src/cmd/awk/awkgram.y"
-{ --inloop; yyval.p = stat2(WHILE, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 128:
-#line	342	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = 0; } break;
-case 130:
-#line	347	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = linkum(yypt[-1].yyv.p, yypt[-0].yyv.p); } break;
-case 133:
-#line	355	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(DIVEQ, yypt[-3].yyv.p, yypt[-0].yyv.p); } break;
-case 134:
-#line	356	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(ADD, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 135:
-#line	357	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(MINUS, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 136:
-#line	358	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(MULT, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 137:
-#line	359	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(DIVIDE, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 138:
-#line	360	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(MOD, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 139:
-#line	361	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(POWER, yypt[-2].yyv.p, yypt[-0].yyv.p); } break;
-case 140:
-#line	362	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(UMINUS, yypt[-0].yyv.p); } break;
-case 141:
-#line	363	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = yypt[-0].yyv.p; } break;
-case 142:
-#line	364	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(NOT, notnull(yypt[-0].yyv.p)); } break;
-case 143:
-#line	365	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(BLTIN, itonp(yypt[-2].yyv.i), rectonode()); } break;
-case 144:
-#line	366	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(BLTIN, itonp(yypt[-3].yyv.i), yypt[-1].yyv.p); } break;
-case 145:
-#line	367	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(BLTIN, itonp(yypt[-0].yyv.i), rectonode()); } break;
-case 146:
-#line	368	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(CALL, celltonode(yypt[-2].yyv.cp,CVAR), NIL); } break;
-case 147:
-#line	369	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(CALL, celltonode(yypt[-3].yyv.cp,CVAR), yypt[-1].yyv.p); } break;
-case 148:
-#line	370	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(PREDECR, yypt[-0].yyv.p); } break;
-case 149:
-#line	371	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(PREINCR, yypt[-0].yyv.p); } break;
-case 150:
-#line	372	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(POSTDECR, yypt[-1].yyv.p); } break;
-case 151:
-#line	373	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(POSTINCR, yypt[-1].yyv.p); } break;
-case 152:
-#line	374	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(GETLINE, yypt[-2].yyv.p, itonp(yypt[-1].yyv.i), yypt[-0].yyv.p); } break;
-case 153:
-#line	375	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(GETLINE, NIL, itonp(yypt[-1].yyv.i), yypt[-0].yyv.p); } break;
-case 154:
-#line	376	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(GETLINE, yypt[-0].yyv.p, NIL, NIL); } break;
-case 155:
-#line	377	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(GETLINE, NIL, NIL, NIL); } break;
-case 156:
-#line	379	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(INDEX, yypt[-3].yyv.p, yypt[-1].yyv.p); } break;
-case 157:
-#line	381	"/sys/src/cmd/awk/awkgram.y"
-{ SYNTAX("index() doesn't permit regular expressions");
-		  yyval.p = op2(INDEX, yypt[-3].yyv.p, (Node*)yypt[-1].yyv.s); } break;
-case 158:
-#line	383	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = yypt[-1].yyv.p; } break;
-case 159:
-#line	385	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(MATCHFCN, NIL, yypt[-3].yyv.p, (Node*)makedfa(yypt[-1].yyv.s, 1)); } break;
-case 160:
-#line	387	"/sys/src/cmd/awk/awkgram.y"
-{ if (constnode(yypt[-1].yyv.p))
-			yyval.p = op3(MATCHFCN, NIL, yypt[-3].yyv.p, (Node*)makedfa(strnode(yypt[-1].yyv.p), 1));
-		  else
-			yyval.p = op3(MATCHFCN, (Node *)1, yypt[-3].yyv.p, yypt[-1].yyv.p); } break;
-case 161:
-#line	391	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = celltonode(yypt[-0].yyv.cp, CCON); } break;
-case 162:
-#line	393	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op4(SPLIT, yypt[-5].yyv.p, makearr(yypt[-3].yyv.p), yypt[-1].yyv.p, (Node*)STRING); } break;
-case 163:
-#line	395	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op4(SPLIT, yypt[-5].yyv.p, makearr(yypt[-3].yyv.p), (Node*)makedfa(yypt[-1].yyv.s, 1), (Node *)REGEXPR); } break;
-case 164:
-#line	397	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op4(SPLIT, yypt[-3].yyv.p, makearr(yypt[-1].yyv.p), NIL, (Node*)STRING); } break;
-case 165:
-#line	398	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(yypt[-3].yyv.i, yypt[-1].yyv.p); } break;
-case 166:
-#line	399	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = celltonode(yypt[-0].yyv.cp, CCON); } break;
-case 167:
-#line	401	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op4(yypt[-5].yyv.i, NIL, (Node*)makedfa(yypt[-3].yyv.s, 1), yypt[-1].yyv.p, rectonode()); } break;
-case 168:
-#line	403	"/sys/src/cmd/awk/awkgram.y"
-{ if (constnode(yypt[-3].yyv.p))
-			yyval.p = op4(yypt[-5].yyv.i, NIL, (Node*)makedfa(strnode(yypt[-3].yyv.p), 1), yypt[-1].yyv.p, rectonode());
-		  else
-			yyval.p = op4(yypt[-5].yyv.i, (Node *)1, yypt[-3].yyv.p, yypt[-1].yyv.p, rectonode()); } break;
-case 169:
-#line	408	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op4(yypt[-7].yyv.i, NIL, (Node*)makedfa(yypt[-5].yyv.s, 1), yypt[-3].yyv.p, yypt[-1].yyv.p); } break;
-case 170:
-#line	410	"/sys/src/cmd/awk/awkgram.y"
-{ if (constnode(yypt[-5].yyv.p))
-			yyval.p = op4(yypt[-7].yyv.i, NIL, (Node*)makedfa(strnode(yypt[-5].yyv.p), 1), yypt[-3].yyv.p, yypt[-1].yyv.p);
-		  else
-			yyval.p = op4(yypt[-7].yyv.i, (Node *)1, yypt[-5].yyv.p, yypt[-3].yyv.p, yypt[-1].yyv.p); } break;
-case 171:
-#line	415	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(SUBSTR, yypt[-5].yyv.p, yypt[-3].yyv.p, yypt[-1].yyv.p); } break;
-case 172:
-#line	417	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op3(SUBSTR, yypt[-3].yyv.p, yypt[-1].yyv.p, NIL); } break;
-case 175:
-#line	423	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op2(ARRAY, makearr(yypt[-3].yyv.p), yypt[-1].yyv.p); } break;
-case 176:
-#line	424	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(INDIRECT, celltonode(yypt[-0].yyv.cp, CVAR)); } break;
-case 177:
-#line	425	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(INDIRECT, yypt[-0].yyv.p); } break;
-case 178:
-#line	429	"/sys/src/cmd/awk/awkgram.y"
-{ arglist = yyval.p = 0; } break;
-case 179:
-#line	430	"/sys/src/cmd/awk/awkgram.y"
-{ arglist = yyval.p = celltonode(yypt[-0].yyv.cp,CVAR); } break;
-case 180:
-#line	431	"/sys/src/cmd/awk/awkgram.y"
-{
-			checkdup(yypt[-2].yyv.p, yypt[-0].yyv.cp);
-			arglist = yyval.p = linkum(yypt[-2].yyv.p,celltonode(yypt[-0].yyv.cp,CVAR)); } break;
-case 181:
-#line	437	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = celltonode(yypt[-0].yyv.cp, CVAR); } break;
-case 182:
-#line	438	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(ARG, itonp(yypt[-0].yyv.i)); } break;
-case 183:
-#line	439	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = op1(VARNF, (Node *) yypt[-0].yyv.cp); } break;
-case 184:
-#line	444	"/sys/src/cmd/awk/awkgram.y"
-{ yyval.p = notnull(yypt[-1].yyv.p); } break;
-	}
-	goto yystack;  /* stack new state and value */
-}
diff -Nru /n/sources/plan9/sys/src/cmd/awk/awkgram.y /sys/src/cmd/awk/awkgram.y
--- /n/sources/plan9/sys/src/cmd/awk/awkgram.y	Sun Dec 12 01:06:43 1999
+++ /sys/src/cmd/awk/awkgram.y	Wed Feb 24 00:00:00 2016
@@ -52,7 +52,7 @@
 %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 NEXTFILE
@@ -176,8 +176,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; }
@@ -318,7 +318,6 @@
 stmt:
 	  BREAK st		{ if (!inloop) SYNTAX("break illegal outside of loops");
 				  $$ = stat1(BREAK, NIL); }
-	| CLOSE pattern st	{ $$ = stat1(CLOSE, $2); }
 	| CONTINUE st		{  if (!inloop) SYNTAX("continue illegal outside of loops");
 				  $$ = stat1(CONTINUE, NIL); }
 	| do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st
@@ -367,6 +366,7 @@
 	| 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); }
diff -Nru /n/sources/plan9/sys/src/cmd/awk/lex.c /sys/src/cmd/awk/lex.c
--- /n/sources/plan9/sys/src/cmd/awk/lex.c	Fri Mar 10 15:41:43 2006
+++ /sys/src/cmd/awk/lex.c	Wed Feb 24 00:00:00 2016
@@ -38,7 +38,7 @@
 int	parencnt = 0;
 
 typedef struct Keyword {
-	char	*word;
+	const char *word;
 	int	sub;
 	int	type;
 } Keyword;
@@ -90,12 +90,7 @@
 	{ "while",	WHILE,		WHILE },
 };
 
-#define DEBUG
-#ifdef	DEBUG
 #define	RET(x)	{ if(dbg)printf("lex %s\n", tokname(x)); return(x); }
-#else
-#define	RET(x)	return(x)
-#endif
 
 int peek(void)
 {
@@ -106,7 +101,7 @@
 
 int gettok(char **pbuf, int *psz)	/* get next input token */
 {
-	int c;
+	int c, retc;
 	char *buf = *pbuf;
 	int sz = *psz;
 	char *bp = buf;
@@ -123,7 +118,7 @@
 	if (isalpha(c) || c == '_') {	/* it's a varname */
 		for ( ; (c = input()) != 0; ) {
 			if (bp-buf >= sz)
-				if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
+				if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
 					FATAL( "out of space for name %.10s...", buf );
 			if (isalnum(c) || c == '_')
 				*bp++ = c;
@@ -133,12 +128,14 @@
 				break;
 			}
 		}
-	} else {	/* it's a number */
+		*bp = 0;
+		retc = 'a';	/* alphanumeric */
+	} else {	/* maybe it's a number, but could be . */
 		char *rem;
 		/* read input until can't be a number */
 		for ( ; (c = input()) != 0; ) {
 			if (bp-buf >= sz)
-				if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
+				if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, "gettok"))
 					FATAL( "out of space for number %.10s...", buf );
 			if (isdigit(c) || c == 'e' || c == 'E' 
 			  || c == '.' || c == '+' || c == '-')
@@ -150,12 +147,19 @@
 		}
 		*bp = 0;
 		strtod(buf, &rem);	/* parse the number */
-		unputstr(rem);		/* put rest back for later */
-		rem[0] = 0;
+		if (rem == buf) {	/* it wasn't a valid number at all */
+			buf[1] = 0;	/* return one character as token */
+			retc = buf[0];	/* character is its own type */
+			unputstr(rem+1); /* put rest back for later */
+		} else {	/* some prefix was a number */
+			unputstr(rem);	/* put rest back for later */
+			rem[0] = 0;	/* truncate buf after number part */
+			retc = '0';	/* type is number */
+		}
 	}
 	*pbuf = buf;
 	*psz = sz;
-	return buf[0];
+	return retc;
 }
 
 int	word(char *);
@@ -168,7 +172,7 @@
 {
 	int c;
 	static char *buf = 0;
-	static int bufsize = 500;
+	static int bufsize = 5; /* BUG: setting this small causes core dump! */
 
 	if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL)
 		FATAL( "out of space in yylex" );
@@ -186,7 +190,7 @@
 			return 0;
 		if (isalpha(c) || c == '_')
 			return word(buf);
-		if (isdigit(c) || c == '.') {
+		if (isdigit(c)) {
 			yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab);
 			/* should this also have STR set? */
 			RET(NUMBER);
@@ -295,20 +299,25 @@
 				input(); yylval.i = POWEQ; RET(ASGNOP);
 			} else
 				RET(POWER);
-	
+
 		case '$':
 			/* BUG: awkward, if not wrong */
 			c = gettok(&buf, &bufsize);
-			if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
-				unputstr(buf);
-				RET(INDIRECT);
-			} else if (isalpha(c)) {
+			if (isalpha(c)) {
 				if (strcmp(buf, "NF") == 0) {	/* very special */
 					unputstr("(NF)");
 					RET(INDIRECT);
 				}
+				c = peek();
+				if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
+					unputstr(buf);
+					RET(INDIRECT);
+				}
 				yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
 				RET(IVAR);
+			} else if (c == 0) {	/*  */
+				SYNTAX( "unexpected end of input after $" );
+				RET(';');
 			} else {
 				unputstr(buf);
 				RET(INDIRECT);
@@ -356,7 +365,7 @@
 	if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
 		FATAL("out of space for strings");
 	for (bp = buf; (c = input()) != '"'; ) {
-		if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, 0))
+		if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string"))
 			FATAL("out of space for string %.10s...", buf);
 		switch (c) {
 		case '\n':
@@ -364,6 +373,8 @@
 		case 0:
 			SYNTAX( "non-terminated string %.10s...", buf );
 			lineno++;
+			if (c == 0)	/* hopeless */
+				FATAL( "giving up" );
 			break;
 		case '\\':
 			c = input();
@@ -401,7 +412,7 @@
 				}
 				*px = 0;
 				unput(c);
-	  			sscanf(xbuf, "%x", &n);
+	  			sscanf(xbuf, "%x", (unsigned int *) &n);
 				*bp++ = n;
 				break;
 			    }
@@ -448,12 +459,13 @@
 	int c, n;
 
 	n = binsearch(w, keywords, sizeof(keywords)/sizeof(keywords[0]));
+/* BUG: this ought to be inside the if; in theory could fault (daniel barrett) */
 	kp = keywords + n;
 	if (n != -1) {	/* found in table */
 		yylval.i = kp->sub;
 		switch (kp->type) {	/* special handling */
-		case FSYSTEM:
-			if (safe)
+		case BLTIN:
+			if (kp->sub == FSYSTEM && safe)
 				SYNTAX( "system is unsafe" );
 			RET(kp->type);
 		case FUNC:
@@ -485,7 +497,7 @@
 	}
 }
 
-void startreg(void)	/* next call to yyles will return a regular expression */
+void startreg(void)	/* next call to yylex will return a regular expression */
 {
 	reg = 1;
 }
@@ -501,7 +513,7 @@
 		FATAL("out of space for rex expr");
 	bp = buf;
 	for ( ; (c = input()) != '/' && c != 0; ) {
-		if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, 0))
+		if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr"))
 			FATAL("out of space for reg expr %.10s...", buf);
 		if (c == '\n') {
 			SYNTAX( "newline in regular expression %.10s...", buf ); 
@@ -515,6 +527,8 @@
 		}
 	}
 	*bp = 0;
+	if (c == 0)
+		SYNTAX("non-terminated regular expression %.10s...", buf);
 	yylval.s = tostring(buf);
 	unput('/');
 	RET(REGEXPR);
@@ -534,9 +548,9 @@
 	extern char *lexprog;
 
 	if (yysptr > yysbuf)
-		c = *--yysptr;
+		c = (uschar)*--yysptr;
 	else if (lexprog != NULL) {	/* awk '...' */
-		if ((c = *lexprog) != 0)
+		if ((c = (uschar)*lexprog) != 0)
 			lexprog++;
 	} else				/* awk -f ... */
 		c = pgetc();
@@ -560,7 +574,7 @@
 		ep = ebuf + sizeof(ebuf) - 1;
 }
 
-void unputstr(char *s)	/* put a string back on input */
+void unputstr(const char *s)	/* put a string back on input */
 {
 	int i;
 
diff -Nru /n/sources/plan9/sys/src/cmd/awk/lib.c /sys/src/cmd/awk/lib.c
--- /n/sources/plan9/sys/src/cmd/awk/lib.c	Thu Feb  9 15:43:33 2006
+++ /sys/src/cmd/awk/lib.c	Wed Feb 24 00:00:00 2016
@@ -42,7 +42,7 @@
 Cell	**fldtab;	/* pointers to Cells */
 char	inputFS[100] = " ";
 
-#define	MAXFLD	200
+#define	MAXFLD	2
 int	nfields	= MAXFLD;	/* last allocated slot for $i */
 
 int	donefld;	/* 1 = implies rec broken into fields */
@@ -57,12 +57,11 @@
 
 void recinit(unsigned int n)
 {
-	record = (char *) malloc(n);
-	fields = (char *) malloc(n);
-	fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *));
-	if (record == NULL || fields == NULL || fldtab == NULL)
+	if ( (record = (char *) malloc(n)) == NULL
+	  || (fields = (char *) malloc(n+1)) == 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] = (Cell *) malloc(sizeof (Cell));
 	*fldtab[0] = dollar0;
 	fldtab[0]->sval = record;
 	fldtab[0]->nval = tostring("0");
@@ -90,8 +89,13 @@
 	char *p;
 
 	for (i = 1; i < *ARGC; i++) {
-		if (!isclvar(p = getargv(i))) {	/* find 1st real filename */
-			setsval(lookup("FILENAME", symtab), getargv(i));
+		p = getargv(i); /* find 1st real filename */
+		if (p == NULL || *p == '\0') {  /* deleted or zapped */
+			argno++;
+			continue;
+		}
+		if (!isclvar(p)) {
+			setsval(lookup("FILENAME", symtab), p);
 			return;
 		}
 		setclvar(p);	/* a commandline assignment before filename */
@@ -100,12 +104,14 @@
 	infile = stdin;		/* no filenames, so use stdin */
 }
 
+static int firsttime = 1;
+
 int getrec(char **pbuf, int *pbufsize, int isrecord)	/* get next input record */
 {			/* note: cares whether buf == record */
 	int c;
-	static int firsttime = 1;
 	char *buf = *pbuf;
-	int bufsize = *pbufsize;
+	uschar saveb0;
+	int bufsize = *pbufsize, savebufsize = bufsize;
 
 	if (firsttime) {
 		firsttime = 0;
@@ -117,12 +123,13 @@
 		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;
 			}
@@ -163,14 +170,15 @@
 		infile = NULL;
 		argno++;
 	}
+	buf[0] = saveb0;
 	*pbuf = buf;
-	*pbufsize = bufsize;
+	*pbufsize = savebufsize;
 	return 0;	/* true end of file */
 }
 
 void nextfile(void)
 {
-	if (infile != stdin)
+	if (infile != NULL && infile != stdin)
 		fclose(infile);
 	infile = NULL;
 	argno++;
@@ -184,6 +192,7 @@
 
 	if (strlen(*FS) >= sizeof(inputFS))
 		FATAL("field separator %.10s... is too long", *FS);
+	/*fflush(stdout); avoids some buffering problem but makes it 25% slower*/
 	strcpy(inputFS, *FS);	/* for subsequent field splitting */
 	if ((sep = **RS) == 0) {
 		sep = '\n';
@@ -224,6 +233,8 @@
 	extern Array *ARGVtab;
 
 	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) );
@@ -253,6 +264,7 @@
 {
 	/* 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, j, n;
@@ -265,12 +277,13 @@
 	n = strlen(r);
 	if (n > fieldssize) {
 		xfree(fields);
-		if ((fields = (char *) malloc(n+1)) == NULL)
+		if ((fields = (char *) malloc(n+2)) == NULL) /* possibly 2 final \0s */
 			FATAL("out of space for fields in fldbld %d", n);
 		fieldssize = n;
 	}
 	fr = fields;
 	i = 0;	/* number of fields accumulated here */
+	strcpy(inputFS, *FS);
 	if (strlen(inputFS) > 1) {	/* it's a regular expression */
 		i = refldbld(r, inputFS);
 	} else if ((sep = *inputFS) == ' ') {	/* default whitespace */
@@ -307,6 +320,13 @@
 		}
 		*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++;
 			if (i > nfields)
@@ -315,7 +335,7 @@
 				xfree(fldtab[i]->sval);
 			fldtab[i]->sval = fr;
 			fldtab[i]->tval = FLD | STR | DONTFREE;
-			while (*r != sep && *r != '\n' && *r != '\0')	/* \n is always a separator */
+			while (*r != sep && *r != rtest && *r != '\0')	/* \n is always a separator */
 				*fr++ = *r++;
 			*fr++ = 0;
 			if (*r++ == 0)
@@ -370,7 +390,7 @@
 Cell *fieldadr(int n)	/* get nth field */
 {
 	if (n < 0)
-		FATAL("trying to access field %d", n);
+		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]);
@@ -379,17 +399,22 @@
 void growfldtab(int n)	/* make new fields up to at least $n */
 {
 	int nf = 2 * nfields;
+	size_t s;
 
 	if (n > nf)
 		nf = n;
-	fldtab = (Cell **) realloc(fldtab, (nf+1) * (sizeof (struct Cell *)));
+	s = (nf+1) * (sizeof (struct Cell *));  /* freebsd: how much do we need? */
+	if (s / sizeof(struct 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;
 }
 
-int refldbld(char *rec, char *fs)	/* build fields from reg expr in FS */
+int refldbld(const char *rec, const char *fs)	/* build fields from reg expr in FS */
 {
 	/* this relies on having fields[] the same length as $0 */
 	/* the fields are all stored in this one array with \0's */
@@ -457,26 +482,26 @@
 	if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3"))
 		FATAL("built giant record `%.30s...'", record);
 	*r = '\0';
-	   dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
+	   dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, (void*)fldtab[0]) );
 
 	if (freeable(fldtab[0]))
 		xfree(fldtab[0]->sval);
 	fldtab[0]->tval = REC | STR | DONTFREE;
 	fldtab[0]->sval = record;
 
-	   dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
+	   dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, (void*)fldtab[0]) );
 	   dprintf( ("recbld = |%s|\n", record) );
 	donerec = 1;
 }
 
 int	errorflag	= 0;
 
-void yyerror(char *s)
+void yyerror(const char *s)
 {
-	SYNTAX(s);
+	SYNTAX("%s", s);
 }
 
-void SYNTAX(char *fmt, ...)
+void SYNTAX(const char *fmt, ...)
 {
 	extern char *cmdname, *curfname;
 	static int been_here = 0;
@@ -488,12 +513,11 @@
 	va_start(varg, fmt);
 	vfprintf(stderr, fmt, varg);
 	va_end(varg);
-	if(compile_time == 1 && cursource() != NULL)
-		fprintf(stderr, " at %s:%d", cursource(), lineno);
-	else
-		fprintf(stderr, " at line %d", lineno);
+	fprintf(stderr, " at source line %d", lineno);
 	if (curfname != NULL)
 		fprintf(stderr, " in function %s", curfname);
+	if (compile_time == 1 && cursource() != NULL)
+		fprintf(stderr, " source file %s", cursource());
 	fprintf(stderr, "\n");
 	errorflag = 2;
 	eprint();
@@ -532,7 +556,7 @@
 		fprintf(stderr, "\t%d extra %c's\n", -n, c2);
 }
 
-void FATAL(char *fmt, ...)
+void FATAL(const char *fmt, ...)
 {
 	extern char *cmdname;
 	va_list varg;
@@ -548,7 +572,7 @@
 	exit(2);
 }
 
-void WARNING(char *fmt, ...)
+void WARNING(const char *fmt, ...)
 {
 	extern char *cmdname;
 	va_list varg;
@@ -564,29 +588,20 @@
 void error()
 {
 	extern Node *curnode;
-	int line;
 
 	fprintf(stderr, "\n");
 	if (compile_time != 2 && NR && *NR > 0) {
+		fprintf(stderr, " input record number %d", (int) (*FNR));
 		if (strcmp(*FILENAME, "-") != 0)
-			fprintf(stderr, " input record %s:%d", *FILENAME, (int) (*FNR));
-		else
-			fprintf(stderr, " input record number %d", (int) (*FNR));
+			fprintf(stderr, ", file %s", *FILENAME);
 		fprintf(stderr, "\n");
 	}
 	if (compile_time != 2 && curnode)
-		line = curnode->lineno;
+		fprintf(stderr, " source line number %d", curnode->lineno);
 	else if (compile_time != 2 && lineno)
-		line = lineno;
-	else
-		line = -1;
-	if (compile_time == 1 && cursource() != NULL){
-		if(line >= 0)
-			fprintf(stderr, " source %s:%d", cursource(), line);
-		else
-			fprintf(stderr, " source file %s", cursource());
-	}else if(line >= 0)
-		fprintf(stderr, " source line %d", line);
+		fprintf(stderr, " source line number %d", lineno);
+	if (compile_time == 1 && cursource() != NULL)
+		fprintf(stderr, " source file %s", cursource());
 	fprintf(stderr, "\n");
 	eprint();
 }
@@ -639,7 +654,7 @@
 	}
 }
 
-double errcheck(double x, char *s)
+double errcheck(double x, const char *s)
 {
 
 	if (errno == EDOM) {
@@ -654,22 +669,24 @@
 	return x;
 }
 
-int isclvar(char *s)	/* is s of form var=something ? */
+int isclvar(const char *s)	/* is s of form var=something ? */
 {
-	char *os = s;
+	const char *os = s;
 
-	if (!isalpha(*s) && *s != '_')
+	if (!isalpha((uschar) *s) && *s != '_')
 		return 0;
 	for ( ; *s; s++)
-		if (!(isalnum(*s) || *s == '_'))
+		if (!(isalnum((uschar) *s) || *s == '_'))
 			break;
 	return *s == '=' && s > os && *(s+1) != '=';
 }
 
 /* strtod is supposed to be a proper test of what's a valid number */
+/* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */
+/* wrong: violates 4.10.1.4 of ansi C standard */
 
 #include <math.h>
-int is_number(char *s)
+int is_number(const char *s)
 {
 	double r;
 	char *ep;
diff -Nru /n/sources/plan9/sys/src/cmd/awk/main.c /sys/src/cmd/awk/main.c
--- /n/sources/plan9/sys/src/cmd/awk/main.c	Sat Dec 10 16:44:21 2005
+++ /sys/src/cmd/awk/main.c	Wed Feb 24 00:00:00 2016
@@ -22,11 +22,12 @@
 THIS SOFTWARE.
 ****************************************************************/
 
-char	*version = "version 19990602";
+const char	*version = "version 20121220";
 
 #define DEBUG
 #include <stdio.h>
 #include <ctype.h>
+#include <locale.h>
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
@@ -37,6 +38,7 @@
 extern	int	nfields;
 
 int	dbg	= 0;
+Awkfloat	srand_seed = 1;
 char	*cmdname;	/* gets argv[0] for error messages */
 extern	FILE	*yyin;	/* lex input file */
 char	*lexprog;	/* points to program argument if it exists */
@@ -44,7 +46,9 @@
 int	compile_time = 2;	/* for error printing: */
 				/* 2 = cmdline, 1 = compile, 0 = running */
 
-char	*pfile[20];	/* program filenames from -f's */
+#define	MAX_PFILE	20	/* max number of -f's */
+
+char	*pfile[MAX_PFILE];	/* program filenames from -f's */
 int	npfile = 0;	/* number of filenames */
 int	curpfile = 0;	/* current filename */
 
@@ -52,19 +56,31 @@
 
 int main(int argc, char *argv[])
 {
-	char *fs = NULL, *marg;
-	int temp;
+	const char *fs = NULL;
 
+	setlocale(LC_CTYPE, "");
+	setlocale(LC_NUMERIC, "C"); /* for parsing cmdline & prog */
 	cmdname = argv[0];
 	if (argc == 1) {
-		fprintf(stderr, "Usage: %s [-F fieldsep] [-mf n] [-mr n] [-v var=value] [-f programfile | 'program'] [file ...]\n", cmdname);
+		fprintf(stderr, 
+		  "usage: %s [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]\n", 
+		  cmdname);
 		exit(1);
 	}
 	signal(SIGFPE, fpecatch);
+
+	srand_seed = 1;
+	srand(srand_seed);
+
 	yyin = NULL;
-	symtab = makesymtab(NSYMTAB);
+	symtab = makesymtab(NSYMTAB/NSYMTAB);
 	while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
-		if (strcmp(argv[1], "--") == 0) {	/* explicit end of args */
+		if (strcmp(argv[1],"-version") == 0 || strcmp(argv[1],"--version") == 0) {
+			printf("awk %s\n", version);
+			exit(0);
+			break;
+		}
+		if (strncmp(argv[1], "--", 2) == 0) {	/* explicit end of args */
 			argc--;
 			argv++;
 			break;
@@ -75,11 +91,18 @@
 				safe = 1;
 			break;
 		case 'f':	/* next argument is program filename */
-			argc--;
-			argv++;
-			if (argc <= 1)
-				FATAL("no program filename");
-			pfile[npfile++] = argv[1];
+			if (argv[1][2] != 0) {  /* arg is -fsomething */
+				if (npfile >= MAX_PFILE - 1)
+					FATAL("too many -f options"); 
+				pfile[npfile++] = &argv[1][2];
+			} else {		/* arg is -f something */
+				argc--; argv++;
+				if (argc <= 1)
+					FATAL("no program filename");
+				if (npfile >= MAX_PFILE - 1)
+					FATAL("too many -f options"); 
+				pfile[npfile++] = argv[1];
+			}
 			break;
 		case 'F':	/* set field separator */
 			if (argv[1][2] != 0) {	/* arg is -Fsomething */
@@ -98,22 +121,19 @@
 				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]);
-			break;
-		case 'm':	/* more memory: -mr=record, -mf=fields */
-				/* no longer needed */
-			marg = argv[1];
-			if (argv[1][3])
-				temp = atoi(&argv[1][3]);
-			else {
-				argv++; argc--;
-				temp = atoi(&argv[1][0]);
-			}
-			switch (marg[2]) {
-			case 'r':	recsize = temp; break;
-			case 'f':	nfields = temp; break;
-			default: FATAL("unknown option %s\n", marg);
+			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':
@@ -122,10 +142,6 @@
 				dbg = 1;
 			printf("awk %s\n", version);
 			break;
-		case 'V':	/* added for exptools "standard" */
-			printf("awk %s\n", version);
-			exit(0);
-			break;
 		default:
 			WARNING("unknown option %s ignored", argv[1]);
 			break;
@@ -154,6 +170,7 @@
 	if (!safe)
 		envinit(environ);
 	yyparse();
+	setlocale(LC_NUMERIC, ""); /* back to whatever it is locally */
 	if (fs)
 		*FS = qstring(fs, '\0');
 	   dprintf( ("errorflag=%d\n", errorflag) );
diff -Nru /n/sources/plan9/sys/src/cmd/awk/maketab.c /sys/src/cmd/awk/maketab.c
--- /n/sources/plan9/sys/src/cmd/awk/maketab.c	Sun Dec 12 01:06:42 1999
+++ /sys/src/cmd/awk/maketab.c	Wed Feb 24 00:00:00 2016
@@ -36,8 +36,8 @@
 
 struct xx
 {	int token;
-	char *name;
-	char *pname;
+	const char *name;
+	const char *pname;
 } proc[] = {
 	{ PROGRAM, "program", NULL },
 	{ BOR, "boolop", " || " },
@@ -102,17 +102,17 @@
 	{ CALL, "call", "call" },
 	{ ARG, "arg", "arg" },
 	{ VARNF, "getnf", "NF" },
-	{ GETLINE, "getline", "getline" },
+	{ GETLINE, "awkgetline", "getline" },
 	{ 0, "", "" },
 };
 
 #define SIZE	(LASTTOKEN - FIRSTTOKEN + 1)
-char *table[SIZE];
+const char *table[SIZE];
 char *names[SIZE];
 
 int main(int argc, char *argv[])
 {
-	struct xx *p;
+	const struct xx *p;
 	int i, n, tok;
 	char c;
 	FILE *fp;
@@ -135,8 +135,8 @@
 		if (c != '#' || (n != 4 && strcmp(def,"define") != 0))	/* not a valid #define */
 			continue;
 		if (tok < FIRSTTOKEN || tok > LASTTOKEN) {
-			fprintf(stderr, "maketab funny token %d %s\n", tok, buf);
-			exit(1);
+			/* fprintf(stderr, "maketab funny token %d %s ignored\n", tok, buf); */
+			continue;
 		}
 		names[tok-FIRSTTOKEN] = (char *) malloc(strlen(name)+1);
 		strcpy(names[tok-FIRSTTOKEN], name);
diff -Nru /n/sources/plan9/sys/src/cmd/awk/parse.c /sys/src/cmd/awk/parse.c
--- /n/sources/plan9/sys/src/cmd/awk/parse.c	Sun Dec 12 01:06:42 1999
+++ /sys/src/cmd/awk/parse.c	Wed Feb 24 00:00:00 2016
@@ -239,6 +239,11 @@
 		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;
 	n = 0;	/* count arguments */
@@ -248,7 +253,7 @@
 	dprintf( ("defining func %s (%d args)\n", v->nval, n) );
 }
 
-int isarg(char *s)		/* is s in argument list for current function? */
+int isarg(const char *s)		/* is s in argument list for current function? */
 {			/* return -1 if not, otherwise arg # */
 	extern Node *arglist;
 	Node *p = arglist;
diff -Nru /n/sources/plan9/sys/src/cmd/awk/proctab.c /sys/src/cmd/awk/proctab.c
--- /n/sources/plan9/sys/src/cmd/awk/proctab.c	Thu Sep 19 22:27:48 2013
+++ /sys/src/cmd/awk/proctab.c	Wed Feb 24 00:00:00 2016
@@ -2,7 +2,7 @@
 #include "awk.h"
 #include "y.tab.h"
 
-static char *printname[92] = {
+static char *printname[93] = {
 	(char *) "FIRSTTOKEN",	/* 57346 */
 	(char *) "PROGRAM",	/* 57347 */
 	(char *) "PASTAT",	/* 57348 */
@@ -24,81 +24,82 @@
 	(char *) "STAR",	/* 57364 */
 	(char *) "QUEST",	/* 57365 */
 	(char *) "PLUS",	/* 57366 */
-	(char *) "AND",	/* 57367 */
-	(char *) "BOR",	/* 57368 */
-	(char *) "APPEND",	/* 57369 */
-	(char *) "EQ",	/* 57370 */
-	(char *) "GE",	/* 57371 */
-	(char *) "GT",	/* 57372 */
-	(char *) "LE",	/* 57373 */
-	(char *) "LT",	/* 57374 */
-	(char *) "NE",	/* 57375 */
-	(char *) "IN",	/* 57376 */
-	(char *) "ARG",	/* 57377 */
-	(char *) "BLTIN",	/* 57378 */
-	(char *) "BREAK",	/* 57379 */
-	(char *) "CLOSE",	/* 57380 */
-	(char *) "CONTINUE",	/* 57381 */
-	(char *) "DELETE",	/* 57382 */
-	(char *) "DO",	/* 57383 */
-	(char *) "EXIT",	/* 57384 */
-	(char *) "FOR",	/* 57385 */
-	(char *) "FUNC",	/* 57386 */
-	(char *) "SUB",	/* 57387 */
-	(char *) "GSUB",	/* 57388 */
-	(char *) "IF",	/* 57389 */
-	(char *) "INDEX",	/* 57390 */
-	(char *) "LSUBSTR",	/* 57391 */
-	(char *) "MATCHFCN",	/* 57392 */
-	(char *) "NEXT",	/* 57393 */
-	(char *) "NEXTFILE",	/* 57394 */
-	(char *) "ADD",	/* 57395 */
-	(char *) "MINUS",	/* 57396 */
-	(char *) "MULT",	/* 57397 */
-	(char *) "DIVIDE",	/* 57398 */
-	(char *) "MOD",	/* 57399 */
-	(char *) "ASSIGN",	/* 57400 */
-	(char *) "ASGNOP",	/* 57401 */
-	(char *) "ADDEQ",	/* 57402 */
-	(char *) "SUBEQ",	/* 57403 */
-	(char *) "MULTEQ",	/* 57404 */
-	(char *) "DIVEQ",	/* 57405 */
-	(char *) "MODEQ",	/* 57406 */
-	(char *) "POWEQ",	/* 57407 */
-	(char *) "PRINT",	/* 57408 */
-	(char *) "PRINTF",	/* 57409 */
-	(char *) "SPRINTF",	/* 57410 */
-	(char *) "ELSE",	/* 57411 */
-	(char *) "INTEST",	/* 57412 */
-	(char *) "CONDEXPR",	/* 57413 */
-	(char *) "POSTINCR",	/* 57414 */
-	(char *) "PREINCR",	/* 57415 */
-	(char *) "POSTDECR",	/* 57416 */
-	(char *) "PREDECR",	/* 57417 */
-	(char *) "VAR",	/* 57418 */
-	(char *) "IVAR",	/* 57419 */
-	(char *) "VARNF",	/* 57420 */
-	(char *) "CALL",	/* 57421 */
-	(char *) "NUMBER",	/* 57422 */
-	(char *) "STRING",	/* 57423 */
-	(char *) "REGEXPR",	/* 57424 */
-	(char *) "GETLINE",	/* 57425 */
-	(char *) "RETURN",	/* 57426 */
-	(char *) "SPLIT",	/* 57427 */
-	(char *) "SUBSTR",	/* 57428 */
-	(char *) "WHILE",	/* 57429 */
-	(char *) "CAT",	/* 57430 */
-	(char *) "NOT",	/* 57431 */
-	(char *) "UMINUS",	/* 57432 */
-	(char *) "POWER",	/* 57433 */
-	(char *) "DECR",	/* 57434 */
-	(char *) "INCR",	/* 57435 */
-	(char *) "INDIRECT",	/* 57436 */
-	(char *) "LASTTOKEN",	/* 57437 */
+	(char *) "EMPTYRE",	/* 57367 */
+	(char *) "AND",	/* 57368 */
+	(char *) "BOR",	/* 57369 */
+	(char *) "APPEND",	/* 57370 */
+	(char *) "EQ",	/* 57371 */
+	(char *) "GE",	/* 57372 */
+	(char *) "GT",	/* 57373 */
+	(char *) "LE",	/* 57374 */
+	(char *) "LT",	/* 57375 */
+	(char *) "NE",	/* 57376 */
+	(char *) "IN",	/* 57377 */
+	(char *) "ARG",	/* 57378 */
+	(char *) "BLTIN",	/* 57379 */
+	(char *) "BREAK",	/* 57380 */
+	(char *) "CLOSE",	/* 57381 */
+	(char *) "CONTINUE",	/* 57382 */
+	(char *) "DELETE",	/* 57383 */
+	(char *) "DO",	/* 57384 */
+	(char *) "EXIT",	/* 57385 */
+	(char *) "FOR",	/* 57386 */
+	(char *) "FUNC",	/* 57387 */
+	(char *) "SUB",	/* 57388 */
+	(char *) "GSUB",	/* 57389 */
+	(char *) "IF",	/* 57390 */
+	(char *) "INDEX",	/* 57391 */
+	(char *) "LSUBSTR",	/* 57392 */
+	(char *) "MATCHFCN",	/* 57393 */
+	(char *) "NEXT",	/* 57394 */
+	(char *) "NEXTFILE",	/* 57395 */
+	(char *) "ADD",	/* 57396 */
+	(char *) "MINUS",	/* 57397 */
+	(char *) "MULT",	/* 57398 */
+	(char *) "DIVIDE",	/* 57399 */
+	(char *) "MOD",	/* 57400 */
+	(char *) "ASSIGN",	/* 57401 */
+	(char *) "ASGNOP",	/* 57402 */
+	(char *) "ADDEQ",	/* 57403 */
+	(char *) "SUBEQ",	/* 57404 */
+	(char *) "MULTEQ",	/* 57405 */
+	(char *) "DIVEQ",	/* 57406 */
+	(char *) "MODEQ",	/* 57407 */
+	(char *) "POWEQ",	/* 57408 */
+	(char *) "PRINT",	/* 57409 */
+	(char *) "PRINTF",	/* 57410 */
+	(char *) "SPRINTF",	/* 57411 */
+	(char *) "ELSE",	/* 57412 */
+	(char *) "INTEST",	/* 57413 */
+	(char *) "CONDEXPR",	/* 57414 */
+	(char *) "POSTINCR",	/* 57415 */
+	(char *) "PREINCR",	/* 57416 */
+	(char *) "POSTDECR",	/* 57417 */
+	(char *) "PREDECR",	/* 57418 */
+	(char *) "VAR",	/* 57419 */
+	(char *) "IVAR",	/* 57420 */
+	(char *) "VARNF",	/* 57421 */
+	(char *) "CALL",	/* 57422 */
+	(char *) "NUMBER",	/* 57423 */
+	(char *) "STRING",	/* 57424 */
+	(char *) "REGEXPR",	/* 57425 */
+	(char *) "GETLINE",	/* 57426 */
+	(char *) "RETURN",	/* 57427 */
+	(char *) "SPLIT",	/* 57428 */
+	(char *) "SUBSTR",	/* 57429 */
+	(char *) "WHILE",	/* 57430 */
+	(char *) "CAT",	/* 57431 */
+	(char *) "NOT",	/* 57432 */
+	(char *) "UMINUS",	/* 57433 */
+	(char *) "POWER",	/* 57434 */
+	(char *) "DECR",	/* 57435 */
+	(char *) "INCR",	/* 57436 */
+	(char *) "INDIRECT",	/* 57437 */
+	(char *) "LASTTOKEN",	/* 57438 */
 };
 
 
-Cell *(*proctab[92])(Node **, int) = {
+Cell *(*proctab[93])(Node **, int) = {
 	nullproc,	/* FIRSTTOKEN */
 	program,	/* PROGRAM */
 	pastat,	/* PASTAT */
@@ -120,6 +121,7 @@
 	nullproc,	/* STAR */
 	nullproc,	/* QUEST */
 	nullproc,	/* PLUS */
+	nullproc,	/* EMPTYRE */
 	boolop,	/* AND */
 	boolop,	/* BOR */
 	nullproc,	/* APPEND */
@@ -178,7 +180,7 @@
 	nullproc,	/* NUMBER */
 	nullproc,	/* STRING */
 	nullproc,	/* REGEXPR */
-	getline,	/* GETLINE */
+	awkgetline,	/* GETLINE */
 	jump,	/* RETURN */
 	split,	/* SPLIT */
 	substr,	/* SUBSTR */
diff -Nru /n/sources/plan9/sys/src/cmd/awk/proto.h /sys/src/cmd/awk/proto.h
--- /n/sources/plan9/sys/src/cmd/awk/proto.h	Sun Dec 12 01:06:42 1999
+++ /sys/src/cmd/awk/proto.h	Wed Feb 24 00:00:00 2016
@@ -33,7 +33,7 @@
 extern	void	startreg(void);
 extern	int	input(void);
 extern	void	unput(int);
-extern	void	unputstr(char *);
+extern	void	unputstr(const char *);
 extern	int	yylook(void);
 extern	int	yyback(int *, int);
 extern	int	yyinput(void);
@@ -70,7 +70,7 @@
 extern	Node	*pa2stat(Node *, Node *, Node *);
 extern	Node	*linkum(Node *, Node *);
 extern	void	defn(Cell *, Node *, Node *);
-extern	int	isarg(char *);
+extern	int	isarg(const char *);
 extern	char	*tokname(int);
 extern	Cell	*(*proctab[])(Node **, int);
 extern	int	ptoi(void *);
@@ -81,18 +81,19 @@
 extern	void	envinit(char **);
 extern	Array	*makesymtab(int);
 extern	void	freesymtab(Cell *);
-extern	void	freeelem(Cell *, char *);
-extern	Cell	*setsymtab(char *, char *, double, unsigned int, Array *);
-extern	int	hash(char *, int);
+extern	void	freeelem(Cell *, const char *);
+extern	Cell	*setsymtab(const char *, const char *, double, unsigned int, Array *);
+extern	int	hash(const char *, int);
 extern	void	rehash(Array *);
-extern	Cell	*lookup(char *, Array *);
+extern	Cell	*lookup(const char *, Array *);
 extern	double	setfval(Cell *, double);
-extern	void	funnyvar(Cell *, char *);
-extern	char	*setsval(Cell *, char *);
+extern	void	funnyvar(Cell *, const char *);
+extern	char	*setsval(Cell *, const char *);
 extern	double	getfval(Cell *);
 extern	char	*getsval(Cell *);
-extern	char	*tostring(char *);
-extern	char	*qstring(char *, int);
+extern	char	*getpssval(Cell *);     /* for print */
+extern	char	*tostring(const char *);
+extern	char	*qstring(const char *, int);
 
 extern	void	recinit(unsigned int);
 extern	void	initgetrec(void);
@@ -106,24 +107,24 @@
 extern	void	fldbld(void);
 extern	void	cleanfld(int, int);
 extern	void	newfld(int);
-extern	int	refldbld(char *, char *);
+extern	int	refldbld(const char *, const char *);
 extern	void	recbld(void);
 extern	Cell	*fieldadr(int);
-extern	void	yyerror(char *);
+extern	void	yyerror(const char *);
 extern	void	fpecatch(int);
 extern	void	bracecheck(void);
 extern	void	bcheck2(int, int, int);
-extern	void	SYNTAX(char *, ...);
-extern	void	FATAL(char *, ...);
-extern	void	WARNING(char *, ...);
+extern	void	SYNTAX(const char *, ...);
+extern	void	FATAL(const char *, ...);
+extern	void	WARNING(const char *, ...);
 extern	void	error(void);
 extern	void	eprint(void);
 extern	void	bclass(int);
-extern	double	errcheck(double, char *);
-extern	int	isclvar(char *);
-extern	int	is_number(char *);
+extern	double	errcheck(double, const char *);
+extern	int	isclvar(const char *);
+extern	int	is_number(const char *);
 
-extern	int	adjbuf(char **pb, int *sz, int min, int q, char **pbp, char *what);
+extern	int	adjbuf(char **pb, int *sz, int min, int q, char **pbp, const char *what);
 extern	void	run(Node *);
 extern	Cell	*execute(Node *);
 extern	Cell	*program(Node **, int);
@@ -131,7 +132,7 @@
 extern	Cell	*copycell(Cell *);
 extern	Cell	*arg(Node **, int);
 extern	Cell	*jump(Node **, int);
-extern	Cell	*getline(Node **, int);
+extern	Cell	*awkgetline(Node **, int);
 extern	Cell	*getnf(Node **, int);
 extern	Cell	*array(Node **, int);
 extern	Cell	*awkdelete(Node **, int);
@@ -145,7 +146,7 @@
 extern	Cell	*indirect(Node **, int);
 extern	Cell	*substr(Node **, int);
 extern	Cell	*sindex(Node **, int);
-extern	int	format(char **, int *, char *, Node *);
+extern	int	format(char **, int *, const char *, Node *);
 extern	Cell	*awksprintf(Node **, int);
 extern	Cell	*awkprintf(Node **, int);
 extern	Cell	*arith(Node **, int);
@@ -166,8 +167,8 @@
 extern	Cell	*printstat(Node **, int);
 extern	Cell	*nullproc(Node **, int);
 extern	FILE	*redirect(int, Node *);
-extern	FILE	*openfile(int, char *);
-extern	char	*filename(FILE *);
+extern	FILE	*openfile(int, const char *);
+extern	const char	*filename(FILE *);
 extern	Cell	*closefile(Node **, int);
 extern	void	closeall(void);
 extern	Cell	*sub(Node **, int);
diff -Nru /n/sources/plan9/sys/src/cmd/awk/run.c /sys/src/cmd/awk/run.c
--- /n/sources/plan9/sys/src/cmd/awk/run.c	Wed Feb  4 15:53:08 2009
+++ /sys/src/cmd/awk/run.c	Wed Feb 24 00:00:00 2016
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <setjmp.h>
+#include <limits.h>
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>
@@ -49,22 +50,24 @@
 }
 */
 
-#ifdef _NFILE
-#ifndef FOPEN_MAX
-#define FOPEN_MAX _NFILE
-#endif
-#endif
-
-#ifndef	FOPEN_MAX
-#define	FOPEN_MAX	40	/* max number of open files */
-#endif
-
-#ifndef RAND_MAX
-#define RAND_MAX	32767	/* all that ansi guarantees */
-#endif
+/* do we really need these? */
+/* #ifdef _NFILE */
+/* #ifndef FOPEN_MAX */
+/* #define FOPEN_MAX _NFILE */
+/* #endif */
+/* #endif */
+/*  */
+/* #ifndef	FOPEN_MAX */
+/* #define	FOPEN_MAX	40 */	/* max number of open files */
+/* #endif */
+/*  */
+/* #ifndef RAND_MAX */
+/* #define RAND_MAX	32767 */	/* all that ansi guarantees */
+/* #endif */
 
 jmp_buf env;
 extern	int	pairstack[];
+extern	Awkfloat	srand_seed;
 
 Node	*winner = NULL;	/* root of parse tree */
 Cell	*tmps;		/* free temporary cells for execution */
@@ -91,7 +94,7 @@
 
 /* buffer memory management */
 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
-	char *whatrtn)
+	const char *whatrtn)
 /* pbuf:    address of pointer to buffer being managed
  * psiz:    address of buffer size variable
  * minlen:  minimum length of buffer needed
@@ -110,6 +113,7 @@
 		if (rminlen)
 			minlen += quantum - rminlen;
 		tbuf = (char *) realloc(*pbuf, minlen);
+		dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
 		if (tbuf == NULL) {
 			if (whatrtn)
 				FATAL("out of memory in %s", whatrtn);
@@ -222,6 +226,7 @@
 {
 	static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
 	int i, ncall, ndef;
+	int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
 	Node *x;
 	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
 	Cell *y, *z, *fcn;
@@ -250,7 +255,7 @@
 		y = execute(x);
 		oargs[i] = y;
 		   dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
-			   i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) );
+			   i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
 		if (isfcn(y))
 			FATAL("can't use function %s as argument in %s", y->nval, s);
 		if (isarr(y))
@@ -299,12 +304,18 @@
 		} 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);
+			freed = 1;
 		}
 	}
 	tempfree(fcn);
-	if (isexit(y) || isnext(y) || isnextfile(y))
+	if (isexit(y) || isnext(y))
 		return y;
-	tempfree(y);		/* this can free twice! */
+	if (freed == 0) {
+		tempfree(y);	/* don't free twice! */
+	}
 	z = fp->retval;			/* return value */
 	   dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
 	fp--;
@@ -318,7 +329,8 @@
 	y = gettemp();
 	y->csub = CCOPY;	/* prevents freeing until call is over */
 	y->nval = x->nval;	/* BUG? */
-	y->sval = x->sval ? tostring(x->sval) : NULL;
+	if (isstr(x))
+		y->sval = tostring(x->sval);
 	y->fval = x->fval;
 	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */
 							/* is DONTFREE right? */
@@ -380,7 +392,7 @@
 	return 0;	/* not reached */
 }
 
-Cell *getline(Node **a, int n)	/* get next line from specific input */
+Cell *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;
 	extern Cell **fldtab;
@@ -457,7 +469,7 @@
 	for (np = a[1]; np; np = np->nnext) {
 		y = execute(np);	/* subscript */
 		s = getsval(y);
-		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
+		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
 			FATAL("out of memory for %s[%s...]", x->nval, buf);
 		strcat(buf, s);
 		if (np->nnext)
@@ -465,7 +477,7 @@
 		tempfree(y);
 	}
 	if (!isarr(x)) {
-		   dprintf( ("making %s into an array\n", x->nval) );
+		   dprintf( ("making %s into an array\n", NN(x->nval)) );
 		if (freeable(x))
 			xfree(x->sval);
 		x->tval &= ~(STR|NUM|DONTFREE);
@@ -504,7 +516,7 @@
 		for (np = a[1]; np; np = np->nnext) {
 			y = execute(np);	/* subscript */
 			s = getsval(y);
-			if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
+			if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
 				FATAL("out of memory deleting %s[%s...]", x->nval, buf);
 			strcat(buf, s);	
 			if (np->nnext)
@@ -543,7 +555,7 @@
 	for (p = a[0]; p; p = p->nnext) {
 		x = execute(p);	/* expr */
 		s = getsval(x);
-		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
+		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
 			FATAL("out of memory deleting %s[%s...]", x->nval, buf);
 		strcat(buf, s);
 		tempfree(x);
@@ -669,7 +681,7 @@
 void tfree(Cell *a)	/* free a tempcell */
 {
 	if (freeable(a)) {
-		   dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) );
+		   dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
 		xfree(a->sval);
 	}
 	if (a == tmps)
@@ -698,12 +710,16 @@
 
 Cell *indirect(Node **a, int n)	/* $( a[0] ) */
 {
+	Awkfloat val;
 	Cell *x;
 	int m;
 	char *s;
 
 	x = execute(a[0]);
-	m = (int) getfval(x);
+	val = getfval(x);	/* freebsd: defend against super large field numbers */
+	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), name \"%s\"", s, x->nval);
 		/* BUG: can x->nval ever be null??? */
@@ -717,7 +733,7 @@
 Cell *substr(Node **a, int nnn)		/* substr(a[0], a[1], a[2]) */
 {
 	int k, m, n;
-	char *s, *p;
+	char *s;
 	int temp;
 	Cell *x, *y, *z = 0;
 
@@ -726,12 +742,13 @@
 	if (a[2] != 0)
 		z = execute(a[2]);
 	s = getsval(x);
-	k = countposn(s, strlen(s)) + 1;
+	k = strlen(s) + 1;
 	if (k <= 1) {
 		tempfree(x);
 		tempfree(y);
-		if (a[2] != 0)
+		if (a[2] != 0) {
 			tempfree(z);
+		}
 		x = gettemp();
 		setsval(x, "");
 		return(x);
@@ -753,14 +770,10 @@
 		n = k - m;
 	   dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
 	y = gettemp();
-	while (*s && --m)
-		 s += mblen(s, k);
-	for (p = s; *p && n--; p += mblen(p, k))
-			;
-	temp = *p;	/* with thanks to John Linderman */
-	*p = '\0';
-	setsval(y, s);
-	*p = temp;
+	temp = s[n+m-1];	/* with thanks to John Linderman */
+	s[n+m-1] = '\0';
+	setsval(y, s + m - 1);
+	s[n+m-1] = temp;
 	tempfree(x);
 	return(y);
 }
@@ -781,7 +794,7 @@
 		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
 			;
 		if (*p2 == '\0') {
-			v = (Awkfloat) countposn(s1, p1-s1) + 1;	/* origin 1 */
+			v = (Awkfloat) (p1 - s1 + 1);	/* origin 1 */
 			break;
 		}
 	}
@@ -793,10 +806,11 @@
 
 #define	MAXNUMSIZE	50
 
-int format(char **pbuf, int *pbufsize, char *s, Node *a)	/* printf-like conversions */
+int format(char **pbuf, int *pbufsize, const char *s, Node *a)	/* printf-like conversions */
 {
 	char *fmt;
-	char *p, *t, *os;
+	char *p, *t;
+	const char *os;
 	Cell *x;
 	int flag = 0, n;
 	int fmtwd; /* format width */
@@ -809,7 +823,7 @@
 	if ((fmt = (char *) malloc(fmtsz)) == NULL)
 		FATAL("out of memory in format()");
 	while (*s) {
-		adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format");
+		adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
 		if (*s != '%') {
 			*p++ = *s++;
 			continue;
@@ -823,11 +837,11 @@
 		fmtwd = atoi(s+1);
 		if (fmtwd < 0)
 			fmtwd = -fmtwd;
-		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
+		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
 		for (t = fmt; (*t++ = *s) != '\0'; s++) {
-			if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0))
+			if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
 				FATAL("format item %.30s... ran format() out of memory", os);
-			if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
+			if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
 				break;	/* the ansi panoply */
 			if (*s == '*') {
 				x = execute(a);
@@ -843,31 +857,31 @@
 		*t = '\0';
 		if (fmtwd < 0)
 			fmtwd = -fmtwd;
-		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
+		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
 
 		switch (*s) {
 		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;
 			*(t-1) = 'l';
 			*t = 'd';
 			*++t = '\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:
 			WARNING("weird printf conversion %s", fmt);
-			flag = 0;
+			flag = '?';
 			break;
 		}
 		if (a == NULL)
@@ -877,40 +891,42 @@
 		n = MAXNUMSIZE;
 		if (fmtwd > n)
 			n = fmtwd;
-		adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format");
+		adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
 		switch (flag) {
-		case 0:	sprintf(p, "%s", fmt);	/* unknown, so dump it too */
+		case '?':	sprintf(p, "%s", fmt);	/* unknown, so dump it too */
 			t = getsval(x);
 			n = strlen(t);
 			if (fmtwd > n)
 				n = fmtwd;
-			adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format");
+			adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
 			p += strlen(p);
 			sprintf(p, "%s", t);
 			break;
-		case 1:	sprintf(p, fmt, getfval(x)); break;
-		case 2:	sprintf(p, fmt, (long) getfval(x)); break;
-		case 3:	sprintf(p, fmt, (int) getfval(x)); break;
-		case 4:
+		case 'f':	sprintf(p, fmt, getfval(x)); break;
+		case 'd':	sprintf(p, fmt, (long) getfval(x)); break;
+		case 'u':	sprintf(p, fmt, (int) getfval(x)); break;
+		case 's':
 			t = getsval(x);
 			n = strlen(t);
 			if (fmtwd > n)
 				n = fmtwd;
-			if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0))
+			if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
 				FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
 			sprintf(p, fmt, t);
 			break;
-		case 5:
+		case 'c':
 			if (isnum(x)) {
 				if (getfval(x))
 					sprintf(p, fmt, (int) getfval(x));
-				else{
-					*p++ = '\0';
-					*p = '\0';
+				else {
+					*p++ = '\0'; /* explicit null byte */
+					*p = '\0';   /* next output will start here */
 				}
 			} else
 				sprintf(p, fmt, getsval(x)[0]);
 			break;
+		default:
+			FATAL("can't happen: bad conversion %c in format()", flag);
 		}
 		tempfree(x);
 		p += strlen(p);
@@ -1145,11 +1161,11 @@
 			x->sval, y->sval);
 	strcpy(s, x->sval);
 	strcpy(s+n1, y->sval);
+	tempfree(x);
 	tempfree(y);
 	z = gettemp();
 	z->sval = s;
 	z->tval = STR;
-	tempfree(x);
 	return(z);
 }
 
@@ -1313,8 +1329,9 @@
 	}
 	tempfree(ap);
 	tempfree(y);
-	if (a[2] != 0 && arg3type == STRING)
+	if (a[2] != 0 && arg3type == STRING) {
 		tempfree(x);
+	}
 	x = gettemp();
 	x->tval = NUM;
 	x->fval = n;
@@ -1379,7 +1396,7 @@
 		x = execute(a[0]);
 		if (isbreak(x))
 			return True;
-		if (isnext(x) || isnextfile(x) || isexit(x) || isret(x))
+		if (isnext(x) || isexit(x) || isret(x))
 			return(x);
 		tempfree(x);
 		x = execute(a[1]);
@@ -1449,6 +1466,7 @@
 	Cell *x, *y;
 	Awkfloat u;
 	int t;
+	Awkfloat tmp;
 	wchar_t wc;
 	char *p, *buf;
 	char mbc[50];
@@ -1462,11 +1480,9 @@
 	switch (t) {
 	case FLENGTH:
 		if (isarr(x))
-			u = ((Array *) x->sval)->nelem;	/* GROT. should be function*/
-		else {
-			p = getsval(x);
-			u = (Awkfloat) countposn(p, strlen(p));
-		}
+			u = ((Array *) x->sval)->nelem;	/* GROT.  should be function*/
+		else
+			u = strlen(getsval(x));
 		break;
 	case FLOG:
 		u = errcheck(log(getfval(x)), "log"); break;
@@ -1504,19 +1520,22 @@
 			u = time((time_t *)0);
 		else
 			u = getfval(x);
+		tmp = u;
 		srand((unsigned int) u);
+		u = srand_seed;
+		srand_seed = tmp;
 		break;
 	case FTOUPPER:
 	case FTOLOWER:
 		buf = tostring(getsval(x));
 		if (t == FTOUPPER) {
 			for (p = buf; *p; p++)
-				if (islower(*p))
-					*p = toupper(*p);
+				if (islower((uschar) *p))
+					*p = toupper((uschar)*p);
 		} else {
 			for (p = buf; *p; p++)
-				if (isupper(*p))
-					*p = tolower(*p);
+				if (isupper((uschar) *p))
+					*p = tolower((uschar)*p);
 		}
 		tempfree(x);
 		x = gettemp();
@@ -1607,30 +1626,38 @@
 
 struct files {
 	FILE	*fp;
-	char	*fname;
+	const char	*fname;
 	int	mode;	/* '|', 'a', 'w' => LE/LT, GT */
-} files[FOPEN_MAX] ={
-	{ NULL,  "/dev/stdin",  LT },	/* watch out: don't free this! */
-	{ NULL, "/dev/stdout", GT },
-	{ NULL, "/dev/stderr", GT }
-};
+} *files;
+
+int nfiles;
 
 void stdinit(void)	/* in case stdin, etc., are not constants */
 {
-	files[0].fp = stdin;
-	files[1].fp = stdout;
-	files[2].fp = stderr;
+	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;
 }
 
-FILE *openfile(int a, char *us)
+FILE *openfile(int a, const char *us)
 {
-	char *s = us;
+	const char *s = us;
 	int i, m;
 	FILE *fp = 0;
 
 	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;
@@ -1640,11 +1667,19 @@
 	if (a == FFLUSH)	/* didn't find it, so don't create it! */
 		return NULL;
 
-	for (i=0; i < FOPEN_MAX; i++)
+	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);
+		memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
+		nfiles = nnf;
+		files = nf;
+	}
 	fflush(stdout);	/* force a semblance of order */
 	m = a;
 	if (a == GT) {
@@ -1668,11 +1703,11 @@
 	return fp;
 }
 
-char *filename(FILE *fp)
+const char *filename(FILE *fp)
 {
 	int i;
 
-	for (i = 0; i < FOPEN_MAX; i++)
+	for (i = 0; i < nfiles; i++)
 		if (fp == files[i].fp)
 			return files[i].fname;
 	return "???";
@@ -1686,7 +1721,8 @@
 	n = n;
 	x = execute(a[0]);
 	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", files[i].fname );
@@ -1701,15 +1737,18 @@
 			files[i].fname = NULL;	/* watch out for ref thru this */
 			files[i].fp = NULL;
 		}
+	}
 	tempfree(x);
-	return(True);
+	x = gettemp();
+	setfval(x, (Awkfloat) stat);
+	return(x);
 }
 
 void closeall(void)
 {
 	int i, stat;
 
-	for (i = 0; i < FOPEN_MAX; i++)
+	for (i = 0; i < FOPEN_MAX; i++) {
 		if (files[i].fp) {
 			if (ferror(files[i].fp))
 				WARNING( "i/o error occurred on %s", files[i].fname );
@@ -1720,13 +1759,14 @@
 			if (stat == EOF)
 				WARNING( "i/o error occurred while closing %s", files[i].fname );
 		}
+	}
 }
 
 void flush_all(void)
 {
 	int i;
 
-	for (i = 0; i < FOPEN_MAX; i++)
+	for (i = 0; i < nfiles; i++)
 		if (files[i].fp)
 			fflush(files[i].fp);
 }
@@ -1802,7 +1842,7 @@
 	int mflag, num;
 	int bufsz = recsize;
 
-	if ((buf = (char *)malloc(bufsz)) == NULL)
+	if ((buf = (char *) malloc(bufsz)) == NULL)
 		FATAL("out of memory in gsub");
 	mflag = 0;	/* if mflag == 0, can replace empty string */
 	num = 0;
@@ -1878,9 +1918,10 @@
 		adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
 		while ((*pb++ = *sptr++) != 0)
 			;
-	done:	if (pb > buf + bufsz)
-			FATAL("gsub result2 %.30s too big; can't happen", buf);
-		*pb = '\0';
+	done:	if (pb < buf + bufsz)
+			*pb = '\0';
+		else if (*(pb-1) != '\0')
+			FATAL("gsub result2 %.30s truncated; can't happen", buf);
 		setsval(x, buf);	/* BUG: should be able to avoid copy + free */
 	}
 	tempfree(x);
diff -Nru /n/sources/plan9/sys/src/cmd/awk/tran.c /sys/src/cmd/awk/tran.c
--- /n/sources/plan9/sys/src/cmd/awk/tran.c	Sun Dec 12 01:06:42 1999
+++ /sys/src/cmd/awk/tran.c	Wed Feb 24 00:00:00 2016
@@ -51,6 +51,7 @@
 Awkfloat *RSTART;	/* start of re matched with ~; origin 1 (!) */
 Awkfloat *RLENGTH;	/* length of same */
 
+Cell	*fsloc;		/* FS */
 Cell	*nrloc;		/* NR */
 Cell	*nfloc;		/* NF */
 Cell	*fnrloc;	/* FNR */
@@ -73,7 +74,8 @@
 	nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
 	nullnode = celltonode(nullloc, CCON);
 
-	FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
+	fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab);
+	FS = &fsloc->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;
@@ -126,6 +128,8 @@
 	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))
 			setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
@@ -168,14 +172,17 @@
 				xfree(cp->sval);
 			temp = cp->cnext;	/* avoids freeing then using */
 			free(cp); 
+			tp->nelem--;
 		}
 		tp->tab[i] = 0;
 	}
+	if (tp->nelem != 0)
+		WARNING("can't happen: inconsistent element count freeing %s", ap->nval);
 	free(tp->tab);
 	free(tp);
 }
 
-void freeelem(Cell *ap, char *s)	/* free elem s from ap (i.e., ap["s"] */
+void freeelem(Cell *ap, const char *s)	/* free elem s from ap (i.e., ap["s"] */
 {
 	Array *tp;
 	Cell *p, *prev = NULL;
@@ -198,14 +205,14 @@
 		}
 }
 
-Cell *setsymtab(char *n, char *s, Awkfloat f, unsigned t, Array *tp)
+Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp)
 {
 	int h;
 	Cell *p;
 
 	if (n != NULL && (p = lookup(n, tp)) != NULL) {
 		   dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
-			p, p->nval, p->sval, p->fval, p->tval) );
+			(void*)p, NN(p->nval), NN(p->sval), p->fval, p->tval) );
 		return(p);
 	}
 	p = (Cell *) malloc(sizeof(Cell));
@@ -224,11 +231,11 @@
 	p->cnext = tp->tab[h];
 	tp->tab[h] = p;
 	   dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n",
-		p, p->nval, p->sval, p->fval, p->tval) );
+		(void*)p, p->nval, p->sval, p->fval, p->tval) );
 	return(p);
 }
 
-int hash(char *s, int n)	/* form hash value for string s */
+int hash(const char *s, int n)	/* form hash value for string s */
 {
 	unsigned hashval;
 
@@ -259,7 +266,7 @@
 	tp->size = nsz;
 }
 
-Cell *lookup(char *s, Array *tp)	/* look for s in tp */
+Cell *lookup(const char *s, Array *tp)	/* look for s in tp */
 {
 	Cell *p;
 	int h;
@@ -291,11 +298,13 @@
 		xfree(vp->sval); /* free any previous string */
 	vp->tval &= ~STR;	/* mark string invalid */
 	vp->tval |= NUM;	/* mark number ok */
-	   dprintf( ("setfval %p: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) );
+	if (f == -0)  /* who would have thought this possible? */
+		f = 0;
+	   dprintf( ("setfval %p: %s = %g, t=%o\n", (void*)vp, NN(vp->nval), f, vp->tval) );
 	return vp->fval = f;
 }
 
-void funnyvar(Cell *vp, char *rw)
+void funnyvar(Cell *vp, const char *rw)
 {
 	if (isarr(vp))
 		FATAL("can't %s %s; it's an array name.", rw, vp->nval);
@@ -305,12 +314,13 @@
 		vp, vp->nval, vp->sval, vp->fval, vp->tval);
 }
 
-char *setsval(Cell *vp, char *s)	/* set string val of a Cell */
+char *setsval(Cell *vp, const char *s)	/* set string val of a Cell */
 {
 	char *t;
 	int fldno;
 
-	   dprintf( ("starting setsval %p: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) );
+	   dprintf( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n", 
+		(void*)vp, NN(vp->nval), s, vp->tval, donerec, donefld) );
 	if ((vp->tval & (NUM | STR)) == 0)
 		funnyvar(vp, "assign to");
 	if (isfld(vp)) {
@@ -324,12 +334,13 @@
 		donerec = 1;
 	}
 	t = tostring(s);	/* in case it's self-assign */
-	vp->tval &= ~NUM;
-	vp->tval |= STR;
 	if (freeable(vp))
 		xfree(vp->sval);
+	vp->tval &= ~NUM;
+	vp->tval |= STR;
 	vp->tval &= ~DONTFREE;
-	   dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, t,t, vp->tval) );
+	   dprintf( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n", 
+		(void*)vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) );
 	return(vp->sval = t);
 }
 
@@ -346,11 +357,12 @@
 		if (is_number(vp->sval) && !(vp->tval&CON))
 			vp->tval |= NUM;	/* make NUM only sparingly */
 	}
-	   dprintf( ("getfval %p: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) );
+	   dprintf( ("getfval %p: %s = %g, t=%o\n",
+		(void*)vp, NN(vp->nval), vp->fval, vp->tval) );
 	return(vp->fval);
 }
 
-char *getsval(Cell *vp)	/* get string val of a Cell */
+static char *get_str_val(Cell *vp, char **fmt)        /* get string val of a Cell */
 {
 	char s[100];	/* BUG: unchecked */
 	double dtemp;
@@ -367,16 +379,28 @@
 		if (modf(vp->fval, &dtemp) == 0)	/* it's integral */
 			sprintf(s, "%.30g", vp->fval);
 		else
-			sprintf(s, *CONVFMT, vp->fval);
+			sprintf(s, *fmt, vp->fval);
 		vp->sval = tostring(s);
 		vp->tval &= ~DONTFREE;
 		vp->tval |= STR;
 	}
-	   dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, vp->sval, vp->sval, vp->tval) );
+	   dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n",
+		(void*)vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) );
 	return(vp->sval);
 }
 
-char *tostring(char *s)	/* make a copy of string s */
+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;
 
@@ -387,13 +411,14 @@
 	return(p);
 }
 
-char *qstring(char *s, int delim)	/* collect string up to next delim */
+char *qstring(const char *is, int delim)	/* collect string up to next delim */
 {
-	char *os = s;
+	const char *os = is;
 	int c, n;
-	char *buf, *bp;
+	uschar *s = (uschar *) is;
+	uschar *buf, *bp;
 
-	if ((buf = (char *) malloc(strlen(s)+3)) == NULL)
+	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')
@@ -430,5 +455,5 @@
 		}
 	}
 	*bp++ = 0;
-	return buf;
+	return (char *) buf;
 }

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.