hbase

heirloom base
git clone git://git.2f30.org/hbase
Log | Files | Refs | README

y2.c (39178B)


      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /* Copyright (c) 1988 AT&T */
     28 /* All Rights Reserved */
     29 
     30 /*	from OpenSolaris "y2.c	6.35	05/06/08 SMI"	*/
     31 
     32 /*
     33  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
     34  *
     35  * Sccsid @(#)y2.c	1.11 (gritter) 11/26/05
     36  */
     37 
     38 #include "dextern"
     39 #include "sgs.h"
     40 #include <wchar.h>
     41 #include <unistd.h>
     42 #define	IDENTIFIER 257
     43 
     44 #define	MARK 258
     45 #define	TERM 259
     46 #define	LEFT 260
     47 #define	RIGHT 261
     48 #define	BINARY 262
     49 #define	PREC 263
     50 #define	LCURLY 264
     51 #define	C_IDENTIFIER 265  /* name followed by colon */
     52 #define	NUMBER 266
     53 #define	START 267
     54 #define	TYPEDEF 268
     55 #define	TYPENAME 269
     56 #define	UNION 270
     57 #define	ENDFILE 0
     58 #define	LHS_TEXT_LEN		80	/* length of lhstext */
     59 #define	RHS_TEXT_LEN		640	/* length of rhstext */
     60 	/* communication variables between various I/O routines */
     61 
     62 #define	v_FLAG	0x01
     63 #define	d_FLAG	0x02
     64 #define	DEFAULT_PREFIX	"y"
     65 
     66 char *infile;				/* input file name 		*/
     67 static int numbval;			/* value of an input number 	*/
     68 static int toksize = NAMESIZE;
     69 static wchar_t *tokname;	/* input token name		*/
     70 char *parser = NULL;		/* location of common parser 	*/
     71 
     72 static void finact(void);
     73 static wchar_t *cstash(wchar_t *);
     74 static void defout(void);
     75 static void cpyunion(void);
     76 static void cpycode(void);
     77 static void cpyact(int);
     78 static void lhsfill(wchar_t *);
     79 static void rhsfill(wchar_t *);
     80 static void lrprnt(void);
     81 static void beg_debug(void);
     82 static void end_toks(void);
     83 static void end_debug(void);
     84 static void exp_tokname(void);
     85 static void exp_prod(void);
     86 static void exp_ntok(void);
     87 static void exp_nonterm(void);
     88 static int defin(int, wchar_t *);
     89 static int gettok(void);
     90 static int chfind(int, wchar_t *);
     91 static int skipcom(void);
     92 static int findchtok(int);
     93 static void put_prefix_define(char *);
     94 
     95 
     96 /* storage of names */
     97 
     98 /*
     99  * initial block to place token and
    100  * nonterminal names are stored
    101  * points to initial block - more space
    102  * is allocated as needed.
    103  */
    104 static wchar_t cnamesblk0[CNAMSZ];
    105 static wchar_t *cnames = cnamesblk0;
    106 
    107 /* place where next name is to be put in */
    108 static wchar_t *cnamp = cnamesblk0;
    109 
    110 /* number of defined symbols output */
    111 static int ndefout = 3;
    112 
    113 	/* storage of types */
    114 static int defunion = 0;	/* union of types defined? */
    115 static int ntypes = 0;		/* number of types defined */
    116 static wchar_t *typeset[NTYPES]; /* pointers to type tags */
    117 
    118 	/* symbol tables for tokens and nonterminals */
    119 
    120 int ntokens = 0;
    121 int ntoksz = NTERMS;
    122 TOKSYMB *tokset;
    123 int *toklev;
    124 
    125 int nnonter = -1;
    126 NTSYMB *nontrst;
    127 int nnontersz = NNONTERM;
    128 
    129 static int start;	/* start symbol */
    130 
    131 	/* assigned token type values */
    132 static int extval = 0;
    133 
    134 	/* input and output file descriptors */
    135 
    136 FILE *finput;		/* yacc input file */
    137 FILE *faction;		/* file for saving actions */
    138 FILE *fdefine;		/* file for # defines */
    139 FILE *ftable;		/* y.tab.c file */
    140 FILE *ftemp;		/* tempfile to pass 2 */
    141 FILE *fdebug;		/* where the strings for debugging are stored */
    142 FILE *foutput;		/* y.output file */
    143 
    144 	/* output string */
    145 
    146 static wchar_t *lhstext;
    147 static wchar_t *rhstext;
    148 
    149 	/* storage for grammar rules */
    150 
    151 int *mem0; /* production storage */
    152 int *mem;
    153 int *tracemem;
    154 extern int *optimmem;
    155 int new_memsize = MEMSIZE;
    156 int nprod = 1;	/* number of productions */
    157 int nprodsz = NPROD;
    158 
    159 int **prdptr;
    160 int *levprd;
    161 wchar_t *had_act;
    162 
    163 /* flag for generating the # line's default is yes */
    164 int gen_lines = 1;
    165 int act_lines = 0;
    166 
    167 /* flag for whether to include runtime debugging */
    168 static int gen_testing = 0;
    169 
    170 /* flag for version stamping--default turned off */
    171 static char *v_stmp = "n";
    172 
    173 int nmbchars = 0;	/* number of mb literals in mbchars */
    174 MBCLIT *mbchars = (MBCLIT *) 0; /* array of mb literals */
    175 int nmbcharsz = 0; /* allocated space for mbchars */
    176 
    177 void 
    178 setup(int argc, char *argv[])
    179 {	int ii, i, j, lev, t, ty;
    180 		/* ty is the sequencial number of token name in tokset */
    181 	int c;
    182 	int *p;
    183 	char *cp;
    184 	wchar_t actname[8];
    185 	unsigned int options = 0;
    186 	char *file_prefix = DEFAULT_PREFIX;
    187 	char *sym_prefix = "";
    188 #define	F_NAME_LENGTH	4096
    189 	char	fname[F_NAME_LENGTH+1];
    190 
    191 	foutput = NULL;
    192 	fdefine = NULL;
    193 	i = 1;
    194 
    195 	tokname = malloc(sizeof (wchar_t) * toksize);
    196 	tokset = malloc(sizeof (TOKSYMB) * ntoksz);
    197 	toklev = malloc(sizeof (int) * ntoksz);
    198 	nontrst = malloc(sizeof (NTSYMB) * nnontersz);
    199 	mem0 = malloc(sizeof (int) * new_memsize);
    200 	prdptr = malloc(sizeof (int *) * (nprodsz+2));
    201 	levprd = malloc(sizeof (int) * (nprodsz+2));
    202 	had_act = calloc(nprodsz + 2, sizeof (wchar_t));
    203 	lhstext = malloc(sizeof (wchar_t) * LHS_TEXT_LEN);
    204 	rhstext = malloc(sizeof (wchar_t) * RHS_TEXT_LEN);
    205 	aryfil(toklev, ntoksz, 0);
    206 	aryfil(levprd, nprodsz, 0);
    207 	for (ii = 0; ii < ntoksz; ++ii)
    208 		tokset[ii].value = 0;
    209 	for (ii = 0; ii < nnontersz; ++ii)
    210 		nontrst[ii].tvalue = 0;
    211 	aryfil(mem0, new_memsize, 0);
    212 	mem = mem0;
    213 	tracemem = mem0;
    214 
    215 	while ((c = getopt(argc, argv, "vVdltp:Q:Y:P:b:")) != EOF)
    216 		switch (c) {
    217 		case 'v':
    218 			options |= v_FLAG;
    219 			break;
    220 		case 'V':
    221 			fprintf(stderr, "yacc: %s , %s\n", pkg, rel);
    222 			break;
    223 		case 'Q':
    224 			v_stmp = optarg;
    225 			if (*v_stmp != 'y' && *v_stmp != 'n')
    226 				error("yacc: -Q should be followed by [y/n]");
    227 			break;
    228 		case 'd':
    229 			options |= d_FLAG;
    230 			break;
    231 		case 'l':
    232 			gen_lines = 0;	/* don't gen #lines */
    233 			break;
    234 		case 't':
    235 			gen_testing = 1;	/* set YYDEBUG on */
    236 			break;
    237 		case 'Y':
    238 			cp = malloc(strlen(optarg) + sizeof ("/yaccpar") + 1);
    239 			cp = strcpy(cp, optarg);
    240 			parser = strcat(cp, "/yaccpar");
    241 			break;
    242 		case 'P':
    243 			parser = optarg;
    244 			break;
    245 		case 'p':
    246 			if (strcmp(optarg, "yy") != 0)
    247 				sym_prefix = optarg;
    248 			else
    249 				sym_prefix = "";
    250 			break;
    251 		case 'b':
    252 			file_prefix = optarg;
    253 			break;
    254 		case '?':
    255 		default:
    256 			fprintf(stderr,
    257 "Usage: yacc [-vVdlt] [-Q(y/n)] [-P driver_file] file\n");
    258 			exit(1);
    259 		}
    260 	/*
    261 	 * Open y.output if -v is specified
    262 	 */
    263 	if (options & v_FLAG) {
    264 		strncpy(fname,
    265 			file_prefix,
    266 			F_NAME_LENGTH-strlen(".output"));
    267 		strcat(fname, ".output");
    268 		foutput = fopen(fname, "w");
    269 		if (foutput == NULL)
    270 			error("cannot open y.output");
    271 	}
    272 
    273 	/*
    274 	 * Open y.tab.h if -d is specified
    275 	 */
    276 	if (options & d_FLAG) {
    277 		strncpy(fname,
    278 			file_prefix,
    279 			F_NAME_LENGTH-strlen(".tab.h"));
    280 		strcat(fname, ".tab.h");
    281 		fdefine = fopen(fname, "w");
    282 		if (fdefine == NULL)
    283 			error("cannot open y.tab.h");
    284 	}
    285 
    286 	fdebug = fopen(DEBUGNAME, "w");
    287 	if (fdebug == NULL)
    288 		error("cannot open yacc.debug");
    289 	/*
    290 	 * Open y.tab.c
    291 	 */
    292 	strncpy(fname,
    293 		file_prefix,
    294 		F_NAME_LENGTH-strlen(".tab.c"));
    295 	strcat(fname, ".tab.c");
    296 	ftable = fopen(fname, "w");
    297 	if (ftable == NULL)
    298 		error("cannot open %s", fname);
    299 
    300 	ftemp = fopen(TEMPNAME, "w");
    301 	faction = fopen(ACTNAME, "w");
    302 	if (ftemp == NULL || faction == NULL)
    303 		error("cannot open temp file");
    304 
    305 	if ((finput = fopen(infile = argv[optind], "r")) == NULL)
    306 		error("cannot open input file");
    307 
    308 	lineno = 1;
    309 	cnamp = cnames;
    310 	defin(0, L"$end");
    311 	extval = 0400;
    312 	defin(0, L"error");
    313 	defin(1, L"$accept");
    314 	mem = mem0;
    315 	lev = 0;
    316 	ty = 0;
    317 	i = 0;
    318 	beg_debug();	/* initialize fdebug file */
    319 
    320 	/*
    321 	 * sorry -- no yacc parser here.....
    322 	 *	we must bootstrap somehow...
    323 	 */
    324 
    325 	t = gettok();
    326 	if (*v_stmp == 'y')
    327 		fprintf(ftable, "\
    328 #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4\n\
    329 #define	YYUSED	__attribute__ ((used))\n\
    330 #elif defined __GNUC__\n\
    331 #define	YYUSED	__attribute__ ((unused))\n\
    332 #else\n\
    333 #define	YYUSED\n\
    334 #endif\n\
    335 static const char yyident[] USED = \"yacc: %s\"\n", rel);
    336 	for (; t != MARK && t != ENDFILE; ) {
    337 		int tok_in_line;
    338 		switch (t) {
    339 
    340 		case L';':
    341 			t = gettok();
    342 			break;
    343 
    344 		case START:
    345 			if ((t = gettok()) != IDENTIFIER) {
    346 				error("bad %%start construction");
    347 				}
    348 			start = chfind(1, tokname);
    349 			t = gettok();
    350 			continue;
    351 
    352 		case TYPEDEF:
    353 			tok_in_line = 0;
    354 			if ((t = gettok()) != TYPENAME)
    355 				error("bad syntax in %%type");
    356 			ty = numbval;
    357 			for (;;) {
    358 				t = gettok();
    359 				switch (t) {
    360 
    361 				case IDENTIFIER:
    362 			/*
    363 			 * The following lines are idented to left.
    364 			 */
    365 			tok_in_line = 1;
    366 			if ((t = chfind(1, tokname)) < NTBASE) {
    367 				j = TYPE(toklev[t]);
    368 				if (j != 0 && j != ty) {
    369 					error("type redeclaration of token %ls",
    370 					tokset[t].name);
    371 					}
    372 				else
    373 					SETTYPE(toklev[t], ty);
    374 			} else {
    375 				j = nontrst[t-NTBASE].tvalue;
    376 				if (j != 0 && j != ty) {
    377 					error(
    378 					"type redeclaration of nonterminal %ls",
    379 						nontrst[t-NTBASE].name);
    380 					}
    381 				else
    382 					nontrst[t-NTBASE].tvalue = ty;
    383 				}
    384 			/* FALLTHRU */
    385 			/*
    386 			 * End Indentation
    387 			 */
    388 				case L',':
    389 					continue;
    390 
    391 				case L';':
    392 					t = gettok();
    393 					break;
    394 				default:
    395 					break;
    396 					}
    397 				if (!tok_in_line)
    398 					error(
    399 					"missing tokens or illegal tokens");
    400 				break;
    401 				}
    402 			continue;
    403 
    404 		case UNION:
    405 			/* copy the union declaration to the output */
    406 			cpyunion();
    407 			defunion = 1;
    408 			t = gettok();
    409 			continue;
    410 
    411 		case LEFT:
    412 		case BINARY:
    413 		case RIGHT:
    414 			i++;
    415 			/* FALLTHRU */
    416 		case TERM:
    417 			tok_in_line = 0;
    418 
    419 			/* nonzero means new prec. and assoc. */
    420 			lev = (t-TERM) | 04;
    421 			ty = 0;
    422 
    423 			/* get identifiers so defined */
    424 
    425 			t = gettok();
    426 			if (t == TYPENAME) { /* there is a type defined */
    427 				ty = numbval;
    428 				t = gettok();
    429 				}
    430 
    431 			for (;;) {
    432 				switch (t) {
    433 
    434 				case L',':
    435 					t = gettok();
    436 					continue;
    437 
    438 				case L';':
    439 					break;
    440 
    441 				case IDENTIFIER:
    442 					tok_in_line = 1;
    443 					j = chfind(0, tokname);
    444 					if (j > NTBASE) {
    445 						error("%ls is not a token.",
    446 						tokname);
    447 					}
    448 					if (lev & ~04) {
    449 						if (ASSOC(toklev[j]) & ~04)
    450 							error(
    451 				"redeclaration of precedence of %ls",
    452 						tokname);
    453 						SETASC(toklev[j], lev);
    454 						SETPLEV(toklev[j], i);
    455 					} else {
    456 						if (ASSOC(toklev[j]))
    457 						warning(1,
    458 				"redeclaration of precedence of %ls.",
    459 							tokname);
    460 						SETASC(toklev[j], lev);
    461 						}
    462 					if (ty) {
    463 						if (TYPE(toklev[j]))
    464 							error(
    465 						"redeclaration of type of %ls",
    466 							tokname);
    467 						SETTYPE(toklev[j], ty);
    468 						}
    469 					if ((t = gettok()) == NUMBER) {
    470 						tokset[j].value = numbval;
    471 						if (j < ndefout && j > 2) {
    472 							error(
    473 				"type number of %ls should be defined earlier",
    474 							tokset[j].name);
    475 							}
    476 						if (numbval >= -YYFLAG1) {
    477 							error(
    478 				"token numbers must be less than %d",
    479 							-YYFLAG1);
    480 							}
    481 						t = gettok();
    482 						}
    483 					continue;
    484 
    485 					}
    486 				if (!tok_in_line)
    487 					error(
    488 					"missing tokens or illegal tokens");
    489 				break;
    490 				}
    491 			continue;
    492 
    493 		case LCURLY:
    494 			defout();
    495 			cpycode();
    496 			t = gettok();
    497 			continue;
    498 
    499 		default:
    500 			error("syntax error");
    501 
    502 			}
    503 
    504 		}
    505 
    506 	if (t == ENDFILE) {
    507 		error("unexpected EOF before %%%%");
    508 		}
    509 
    510 	/* t is MARK */
    511 
    512 	defout();
    513 	end_toks();	/* all tokens dumped - get ready for reductions */
    514 
    515 	fprintf(ftable, "\n#ifdef __STDC__\n");
    516 	fprintf(ftable, "#include <stdlib.h>\n");
    517 	fprintf(ftable, "#include <string.h>\n");
    518 	fprintf(ftable, "#define	YYCONST	const\n");
    519 	fprintf(ftable, "#else\n");
    520 	fprintf(ftable, "#include <malloc.h>\n");
    521 	fprintf(ftable, "#include <memory.h>\n");
    522 	fprintf(ftable, "#define	YYCONST\n");
    523 	fprintf(ftable, "#endif\n");
    524 
    525 	if (sym_prefix[0] != '\0')
    526 		put_prefix_define(sym_prefix);
    527 
    528 	fprintf(ftable, "\n#if defined(__cplusplus) || defined(__STDC__)\n");
    529 	fprintf(ftable,
    530 	"\n#if defined(__cplusplus) && defined(__EXTERN_C__)\n");
    531 	fprintf(ftable, "extern \"C\" {\n");
    532 	fprintf(ftable, "#endif\n");
    533 	fprintf(ftable, "#ifndef yyerror\n");
    534 	fprintf(ftable, "#if defined(__cplusplus)\n");
    535 	fprintf(ftable, "	void yyerror(YYCONST char *);\n");
    536 	fprintf(ftable, "#endif\n");
    537 	fprintf(ftable, "#endif\n");
    538 	fprintf(ftable, "#ifndef yylex\n");
    539 	fprintf(ftable, "	int yylex(void);\n");
    540 	fprintf(ftable, "#endif\n");
    541 	fprintf(ftable, "	int yyparse(void);\n");
    542 	fprintf(ftable, "#if defined(__cplusplus) && defined(__EXTERN_C__)\n");
    543 	fprintf(ftable, "}\n");
    544 	fprintf(ftable, "#endif\n");
    545 	fprintf(ftable, "\n#endif\n\n");
    546 
    547 	fprintf(ftable, "#define yyclearin yychar = -1\n");
    548 	fprintf(ftable, "#define yyerrok yyerrflag = 0\n");
    549 	fprintf(ftable, "extern int yychar;\nextern int yyerrflag;\n");
    550 	if (!(defunion || ntypes))
    551 		fprintf(ftable,
    552 			"#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
    553 	fprintf(ftable, "YYSTYPE yylval;\n");
    554 	fprintf(ftable, "YYSTYPE yyval;\n");
    555 	fprintf(ftable, "typedef int yytabelem;\n");
    556 	fprintf(ftable,
    557 		"#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n");
    558 	fprintf(ftable, "#if YYMAXDEPTH > 0\n");
    559 	fprintf(ftable, "int yy_yys[YYMAXDEPTH], *yys = yy_yys;\n");
    560 	fprintf(ftable, "YYSTYPE yy_yyv[YYMAXDEPTH], *yyv = yy_yyv;\n");
    561 	fprintf(ftable, "#else	/* user does initial allocation */\n");
    562 	fprintf(ftable, "int *yys;\nYYSTYPE *yyv;\n#endif\n");
    563 	fprintf(ftable, "static int yymaxdepth = YYMAXDEPTH;\n");
    564 
    565 	prdptr[0] = mem;
    566 	/* added production */
    567 	*mem++ = NTBASE;
    568 
    569 	/* if start is 0, we will overwrite with the lhs of the first rule */
    570 	*mem++ = start;
    571 	*mem++ = 1;
    572 	*mem++ = 0;
    573 	prdptr[1] = mem;
    574 
    575 	while ((t = gettok()) == LCURLY)
    576 		cpycode();
    577 
    578 	if (t != C_IDENTIFIER)
    579 		error("bad syntax on first rule");
    580 
    581 	if (!start)
    582 		prdptr[0][1] = chfind(1, tokname);
    583 
    584 	/* read rules */
    585 
    586 	while (t != MARK && t != ENDFILE) {
    587 
    588 		/* process a rule */
    589 
    590 		if (t == L'|') {
    591 			rhsfill((wchar_t *)0); /* restart fill of rhs */
    592 			*mem = *prdptr[nprod-1];
    593 			if (++mem >= &tracemem[new_memsize])
    594 				exp_mem(1);
    595 		} else if (t == C_IDENTIFIER) {
    596 			*mem = chfind(1, tokname);
    597 			if (*mem < NTBASE)
    598 				error("illegal nonterminal in grammar rule");
    599 			if (++mem >= &tracemem[new_memsize])
    600 				exp_mem(1);
    601 			lhsfill(tokname);	/* new rule: restart strings */
    602 		} else
    603 			error("illegal rule: missing semicolon or | ?");
    604 
    605 		/* read rule body */
    606 
    607 
    608 		t = gettok();
    609 	more_rule:
    610 		while (t == IDENTIFIER) {
    611 			*mem = chfind(1, tokname);
    612 			if (*mem < NTBASE)
    613 				levprd[nprod] = toklev[*mem]& ~04;
    614 			if (++mem >= &tracemem[new_memsize])
    615 				exp_mem(1);
    616 			rhsfill(tokname);	/* add to rhs string */
    617 			t = gettok();
    618 			}
    619 
    620 		if (t == PREC) {
    621 			if (gettok() != IDENTIFIER)
    622 				error("illegal %%prec syntax");
    623 			j = chfind(2, tokname);
    624 			if (j >= NTBASE)
    625 				error("nonterminal %ls illegal after %%prec",
    626 				nontrst[j-NTBASE].name);
    627 			levprd[nprod] = toklev[j] & ~04;
    628 			t = gettok();
    629 			}
    630 
    631 		if (t == L'=') {
    632 			had_act[nprod] = 1;
    633 			levprd[nprod] |= ACTFLAG;
    634 			fprintf(faction, "\ncase %d:", nprod);
    635 			cpyact(mem-prdptr[nprod] - 1);
    636 			fprintf(faction, " break;");
    637 			if ((t = gettok()) == IDENTIFIER) {
    638 				/* action within rule... */
    639 
    640 				lrprnt();		/* dump lhs, rhs */
    641 				swprintf(actname, sizeof actname,
    642 						L"$$%d", nprod);
    643 				/*
    644 				 * make it nonterminal
    645 				 */
    646 				j = chfind(1, actname);
    647 
    648 				/*
    649 				 * the current rule will become rule
    650 				 * number nprod+1 move the contents down,
    651 				 * and make room for the null
    652 				 */
    653 
    654 				if (mem + 2 >= &tracemem[new_memsize])
    655 					exp_mem(1);
    656 				for (p = mem; p >= prdptr[nprod]; --p)
    657 					p[2] = *p;
    658 				mem += 2;
    659 
    660 				/* enter null production for action */
    661 
    662 				p = prdptr[nprod];
    663 
    664 				*p++ = j;
    665 				*p++ = -nprod;
    666 
    667 				/* update the production information */
    668 
    669 				levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
    670 				levprd[nprod] = ACTFLAG;
    671 
    672 				if (++nprod >= nprodsz)
    673 					exp_prod();
    674 				prdptr[nprod] = p;
    675 
    676 				/*
    677 				 * make the action appear in
    678 				 * the original rule
    679 				 */
    680 				*mem++ = j;
    681 				if (mem >= &tracemem[new_memsize])
    682 					exp_mem(1);
    683 				/* get some more of the rule */
    684 				goto more_rule;
    685 			}
    686 		}
    687 		while (t == L';')
    688 			t = gettok();
    689 		*mem++ = -nprod;
    690 		if (mem >= &tracemem[new_memsize])
    691 			exp_mem(1);
    692 
    693 		/* check that default action is reasonable */
    694 
    695 		if (ntypes && !(levprd[nprod] & ACTFLAG) &&
    696 				nontrst[*prdptr[nprod]-NTBASE].tvalue) {
    697 			/* no explicit action, LHS has value */
    698 			register int tempty;
    699 			tempty = prdptr[nprod][1];
    700 			if (tempty < 0)
    701 				error("must return a value, since LHS has a type");
    702 			else if (tempty >= NTBASE)
    703 				tempty = nontrst[tempty-NTBASE].tvalue;
    704 			else
    705 				tempty = TYPE(toklev[tempty]);
    706 			if (tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue) {
    707 				error(
    708 				"default action causes potential type clash");
    709 			}
    710 		}
    711 
    712 		if (++nprod >= nprodsz)
    713 			exp_prod();
    714 		prdptr[nprod] = mem;
    715 		levprd[nprod] = 0;
    716 		}
    717 	/* end of all rules */
    718 
    719 	end_debug();		/* finish fdebug file's input */
    720 	finact();
    721 	if (t == MARK) {
    722 		if (gen_lines)
    723 			fprintf(ftable, "\n# line %d \"%s\"\n",
    724 				lineno, infile);
    725 		while ((c = getwc(finput)) != EOF)
    726 			putwc(c, ftable);
    727 		}
    728 	fclose(finput);
    729 }
    730 
    731 static void 
    732 finact(void)
    733 {
    734 	/* finish action routine */
    735 	fclose(faction);
    736 	fprintf(ftable, "# define YYERRCODE %d\n", tokset[2].value);
    737 }
    738 
    739 static wchar_t *
    740 cstash(s)
    741 register wchar_t *s;
    742 {
    743 	wchar_t *temp;
    744 	static int used = 0;
    745 	static int used_save = 0;
    746 	static int exp_cname = CNAMSZ;
    747 	int len = wcslen(s);
    748 
    749 	/*
    750 	 * 2/29/88 -
    751 	 * Don't need to expand the table, just allocate new space.
    752 	 */
    753 	used_save = used;
    754 	while (len >= (exp_cname - used_save)) {
    755 		exp_cname += CNAMSZ;
    756 		if (!used)
    757 			free(cnames);
    758 		if ((cnames = malloc(sizeof (wchar_t)*exp_cname)) == NULL)
    759 			error("cannot expand string dump");
    760 		cnamp = cnames;
    761 		used = 0;
    762 	}
    763 
    764 	temp = cnamp;
    765 	do {
    766 		*cnamp++ = *s;
    767 	} while (*s++);
    768 	used += cnamp - temp;
    769 	return (temp);
    770 }
    771 
    772 static int
    773 defin(int t, register wchar_t *s)
    774 {
    775 	/* define s to be a terminal if t=0 or a nonterminal if t=1 */
    776 
    777 	register int val = 0;
    778 
    779 	if (t) {
    780 		if (++nnonter >= nnontersz)
    781 			exp_nonterm();
    782 		nontrst[nnonter].name = cstash(s);
    783 		return (NTBASE + nnonter);
    784 		}
    785 	/* must be a token */
    786 	if (++ntokens >= ntoksz)
    787 		exp_ntok();
    788 	tokset[ntokens].name = cstash(s);
    789 
    790 	/* establish value for token */
    791 
    792 	if (s[0] == L' ' && s[2] == 0) { /* single character literal */
    793 		val = findchtok(s[1]);
    794 	} else if (s[0] == L' ' && s[1] == L'\\') { /* escape sequence */
    795 		if (s[3] == 0) { /* single character escape sequence */
    796 			switch (s[2]) {
    797 				/* character which is escaped */
    798 			case L'a':
    799 				warning(1,
    800 		"\\a is ANSI C \"alert\" character");
    801 #if __STDC__ - 1 == 0
    802 				val = L'\a';
    803 				break;
    804 #else
    805 				val = L'\007';
    806 				break;
    807 #endif
    808 			case L'v': val = L'\v'; break;
    809 			case L'n': val = L'\n'; break;
    810 			case L'r': val = L'\r'; break;
    811 			case L'b': val = L'\b'; break;
    812 			case L't': val = L'\t'; break;
    813 			case L'f': val = L'\f'; break;
    814 			case L'\'': val = L'\''; break;
    815 			case L'"': val = L'"'; break;
    816 			case L'?': val = L'?'; break;
    817 			case L'\\': val = L'\\'; break;
    818 			default: error("invalid escape");
    819 			}
    820 		} else if (s[2] <= L'7' && s[2] >= L'0') { /* \nnn sequence */
    821 			int i = 3;
    822 			val = s[2] - L'0';
    823 			while (iswdigit(s[i]) && i <= 4) {
    824 				if (s[i] >= L'0' && s[i] <= L'7')
    825 					val = val * 8 + s[i] - L'0';
    826 				else
    827 					error("illegal octal number");
    828 				i++;
    829 			}
    830 			if (s[i] != 0)
    831 				error("illegal \\nnn construction");
    832 			if (val > 255)
    833 				error(
    834 "\\nnn exceed \\377; use \\xnnnnnnnn for wchar_t value of multibyte char");
    835 			if (val == 0 && i >= 4)
    836 				error("'\\000' is illegal");
    837 		} else if (s[2] == L'x') { /* hexadecimal \xnnn sequence */
    838 			int i = 3;
    839 			val = 0;
    840 			warning(1, "\\x is ANSI C hex escape");
    841 			if (iswxdigit(s[i]))
    842 				while (iswxdigit(s[i])) {
    843 					int tmpval;
    844 					if (iswdigit(s[i]))
    845 						tmpval = s[i] - L'0';
    846 					else if (s[i] >= L'a')
    847 						tmpval = s[i] - L'a' + 10;
    848 					else
    849 						tmpval = s[i] - L'A' + 10;
    850 					val = 16 * val + tmpval;
    851 					i++;
    852 				}
    853 			else
    854 				error("illegal hexadecimal number");
    855 			if (s[i] != 0)
    856 				error("illegal \\xnn construction");
    857 #define	LWCHAR_MAX	0x7fffffff
    858 			if ((unsigned)val > LWCHAR_MAX)
    859 			    error(" \\xnnnnnnnn exceed %#x", LWCHAR_MAX);
    860 			if (val == 0)
    861 				error("'\\x00' is illegal");
    862 			val = findchtok(val);
    863 		} else
    864 			error("invalid escape");
    865 	} else {
    866 		val = extval++;
    867 	}
    868 	tokset[ntokens].value = val;
    869 	toklev[ntokens] = 0;
    870 	return (ntokens);
    871 }
    872 
    873 static void 
    874 defout(void)
    875 {
    876 	/* write out the defines (at the end of the declaration section) */
    877 
    878 	register int i, c;
    879 	register wchar_t *cp;
    880 
    881 	for (i = ndefout; i <= ntokens; ++i) {
    882 
    883 		cp = tokset[i].name;
    884 		if (*cp == L' ')	/* literals */
    885 		{
    886 			fprintf(fdebug, "\t\"%ls\",\t%d,\n",
    887 				tokset[i].name + 1, tokset[i].value);
    888 			continue;	/* was cp++ */
    889 		}
    890 
    891 		for (; (c = *cp) != 0; ++cp) {
    892 			if (iswlower(c) || iswupper(c) ||
    893 				iswdigit(c) || c == L'_') /* EMPTY */;
    894 			else
    895 				goto nodef;
    896 			}
    897 
    898 		fprintf(fdebug, "\t\"%ls\",\t%d,\n", tokset[i].name,
    899 			tokset[i].value);
    900 		fprintf(ftable, "# define %ls %d\n", tokset[i].name,
    901 			tokset[i].value);
    902 		if (fdefine != NULL)
    903 			fprintf(fdefine, "# define %ls %d\n",
    904 				tokset[i].name,
    905 				tokset[i].value);
    906 
    907 	nodef:;
    908 	}
    909 	ndefout = ntokens+1;
    910 }
    911 
    912 static int
    913 gettok(void)
    914 {
    915 	register int i, base;
    916 	static int peekline; /* number of '\n' seen in lookahead */
    917 	register int c, match, reserve;
    918 begin:
    919 	reserve = 0;
    920 	lineno += peekline;
    921 	peekline = 0;
    922 	c = getwc(finput);
    923 	/*
    924 	 * while (c == ' ' || c == '\n' || c == '\t' || c == '\f') {
    925 	 */
    926 	while (iswspace(c)) {
    927 		if (c == L'\n')
    928 			++lineno;
    929 		c = getwc(finput);
    930 	}
    931 	if (c == L'/') { /* skip comment */
    932 		lineno += skipcom();
    933 		goto begin;
    934 	}
    935 
    936 	switch (c) {
    937 
    938 	case EOF:
    939 		return (ENDFILE);
    940 	case L'{':
    941 		ungetwc(c, finput);
    942 		return (L'=');  /* action ... */
    943 	case L'<':  /* get, and look up, a type name (union member name) */
    944 		i = 0;
    945 		while ((c = getwc(finput)) != L'>' &&
    946 				c != EOF && c != L'\n') {
    947 			tokname[i] = c;
    948 			if (++i >= toksize)
    949 				exp_tokname();
    950 			}
    951 		if (c != L'>')
    952 			error("unterminated < ... > clause");
    953 		tokname[i] = 0;
    954 		if (i == 0)
    955 			error("missing type name in < ... > clause");
    956 		for (i = 1; i <= ntypes; ++i) {
    957 			if (!wcscmp(typeset[i], tokname)) {
    958 				numbval = i;
    959 				return (TYPENAME);
    960 				}
    961 			}
    962 		typeset[numbval = ++ntypes] = cstash(tokname);
    963 		return (TYPENAME);
    964 
    965 	case L'"':
    966 	case L'\'':
    967 		match = c;
    968 		tokname[0] = L' ';
    969 		i = 1;
    970 		for (;;) {
    971 			c = getwc(finput);
    972 			if (c == L'\n' || c == EOF)
    973 				error("illegal or missing ' or \"");
    974 			if (c == L'\\') {
    975 				c = getwc(finput);
    976 				tokname[i] = L'\\';
    977 				if (++i >= toksize)
    978 					exp_tokname();
    979 			} else if (c == match) break;
    980 			tokname[i] = c;
    981 			if (++i >= toksize)
    982 				exp_tokname();
    983 			}
    984 		break;
    985 
    986 	case L'%':
    987 	case L'\\':
    988 
    989 		switch (c = getwc(finput)) {
    990 
    991 		case L'0':	return (TERM);
    992 		case L'<':	return (LEFT);
    993 		case L'2':	return (BINARY);
    994 		case L'>':	return (RIGHT);
    995 		case L'%':
    996 		case L'\\':	return (MARK);
    997 		case L'=':	return (PREC);
    998 		case L'{':	return (LCURLY);
    999 		default:	reserve = 1;
   1000 			}
   1001 
   1002 	default:
   1003 
   1004 		if (iswdigit(c)) { /* number */
   1005 			numbval = c - L'0';
   1006 			base = (c == L'0') ? 8 : 10;
   1007 			for (c = getwc(finput);
   1008 					iswdigit(c);
   1009 					c = getwc(finput)) {
   1010 				numbval = numbval*base + c - L'0';
   1011 				}
   1012 			ungetwc(c, finput);
   1013 			return (NUMBER);
   1014 		} else if (iswlower(c) || iswupper(c) ||
   1015 				c == L'_' || c == L'.' ||
   1016 				c == L'$') {
   1017 			i = 0;
   1018 			while (iswlower(c) || iswupper(c) ||
   1019 					iswdigit(c) || c == L'_' ||
   1020 					c == L'.' || c == L'$') {
   1021 				tokname[i] = c;
   1022 				if (reserve && iswupper(c))
   1023 					tokname[i] = towlower(c);
   1024 				if (++i >= toksize)
   1025 					exp_tokname();
   1026 				c = getwc(finput);
   1027 				}
   1028 			}
   1029 		else
   1030 			return (c);
   1031 
   1032 		ungetwc(c, finput);
   1033 		}
   1034 
   1035 	tokname[i] = 0;
   1036 
   1037 	if (reserve) { /* find a reserved word */
   1038 		if (!wcscmp(tokname, L"term"))
   1039 			return (TERM);
   1040 		if (!wcscmp(tokname, L"token"))
   1041 			return (TERM);
   1042 		if (!wcscmp(tokname, L"left"))
   1043 			return (LEFT);
   1044 		if (!wcscmp(tokname, L"nonassoc"))
   1045 			return (BINARY);
   1046 		if (!wcscmp(tokname, L"binary"))
   1047 			return (BINARY);
   1048 		if (!wcscmp(tokname, L"right"))
   1049 			return (RIGHT);
   1050 		if (!wcscmp(tokname, L"prec"))
   1051 			return (PREC);
   1052 		if (!wcscmp(tokname, L"start"))
   1053 			return (START);
   1054 		if (!wcscmp(tokname, L"type"))
   1055 			return (TYPEDEF);
   1056 		if (!wcscmp(tokname, L"union"))
   1057 			return (UNION);
   1058 		error("invalid escape, or illegal reserved word: %ls", tokname);
   1059 		}
   1060 
   1061 	/* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */
   1062 
   1063 	c = getwc(finput);
   1064 	/*
   1065 	 * while (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '/')
   1066 	 * {
   1067 	 */
   1068 	while (iswspace(c) || c == L'/') {
   1069 		if (c == L'\n') {
   1070 			++peekline;
   1071 		} else if (c == L'/') { /* look for comments */
   1072 			peekline += skipcom();
   1073 			}
   1074 		c = getwc(finput);
   1075 		}
   1076 	if (c == L':')
   1077 		return (C_IDENTIFIER);
   1078 	ungetwc(c, finput);
   1079 	return (IDENTIFIER);
   1080 }
   1081 
   1082 static int
   1083 fdtype(int t)
   1084 {
   1085 	/* determine the type of a symbol */
   1086 	register int v;
   1087 	if (t >= NTBASE)
   1088 		v = nontrst[t-NTBASE].tvalue;
   1089 	else
   1090 		v = TYPE(toklev[t]);
   1091 	if (v <= 0)
   1092 		error("must specify type for %ls",
   1093 			(t >= NTBASE) ? nontrst[t-NTBASE].name:
   1094 			tokset[t].name);
   1095 	return (v);
   1096 }
   1097 
   1098 static int
   1099 chfind(int t, register wchar_t *s)
   1100 {
   1101 	int i;
   1102 
   1103 	if (s[0] == ' ')
   1104 		t = 0;
   1105 	TLOOP(i) {
   1106 		if (!wcscmp(s, tokset[i].name)) {
   1107 			return (i);
   1108 		}
   1109 	}
   1110 	NTLOOP(i) {
   1111 		if (!wcscmp(s, nontrst[i].name)) {
   1112 			return (i + NTBASE);
   1113 		}
   1114 	}
   1115 	/* cannot find name */
   1116 	if (t > 1)
   1117 		error("%ls should have been defined earlier", s);
   1118 	return (defin(t, s));
   1119 }
   1120 
   1121 static void 
   1122 cpyunion(void)
   1123 {
   1124 	/*
   1125 	 * copy the union declaration to the output,
   1126 	 * and the define file if present
   1127 	 */
   1128 	int level, c;
   1129 	if (gen_lines)
   1130 		fprintf(ftable, "\n# line %d \"%s\"\n", lineno, infile);
   1131 	fprintf(ftable, "typedef union\n");
   1132 	if (fdefine)
   1133 		fprintf(fdefine, "\ntypedef union\n");
   1134 	fprintf(ftable, "#ifdef __cplusplus\n\tYYSTYPE\n#endif\n");
   1135 	if (fdefine)
   1136 		fprintf(fdefine, "#ifdef __cplusplus\n\tYYSTYPE\n#endif\n");
   1137 
   1138 	level = 0;
   1139 	for (;;) {
   1140 		if ((c = getwc(finput)) == EOF)
   1141 			error("EOF encountered while processing %%union");
   1142 		putwc(c, ftable);
   1143 		if (fdefine)
   1144 			putwc(c, fdefine);
   1145 
   1146 		switch (c) {
   1147 
   1148 		case L'\n':
   1149 			++lineno;
   1150 			break;
   1151 
   1152 		case L'{':
   1153 			++level;
   1154 			break;
   1155 
   1156 		case L'}':
   1157 			--level;
   1158 			if (level == 0) { /* we are finished copying */
   1159 				fprintf(ftable, " YYSTYPE;\n");
   1160 				if (fdefine)
   1161 					fprintf(fdefine,
   1162 					" YYSTYPE;\nextern YYSTYPE yylval;\n");
   1163 				return;
   1164 				}
   1165 			}
   1166 		}
   1167 }
   1168 
   1169 static void 
   1170 cpycode(void)
   1171 {
   1172 	/* copies code between \{ and \} */
   1173 
   1174 	int c;
   1175 	c = getwc(finput);
   1176 	if (c == L'\n') {
   1177 		c = getwc(finput);
   1178 		lineno++;
   1179 		}
   1180 	if (gen_lines)
   1181 		fprintf(ftable, "\n# line %d \"%s\"\n", lineno, infile);
   1182 	while (c != EOF) {
   1183 		if (c == L'\\') {
   1184 			if ((c = getwc(finput)) == L'}')
   1185 				return;
   1186 			else
   1187 				putwc(L'\\', ftable);
   1188 		} else if (c == L'%') {
   1189 			if ((c = getwc(finput)) == L'}')
   1190 				return;
   1191 			else
   1192 				putwc(L'%', ftable);
   1193 		}
   1194 		putwc(c, ftable);
   1195 		if (c == L'\n')
   1196 			++lineno;
   1197 		c = getwc(finput);
   1198 		}
   1199 	error("eof before %%}");
   1200 }
   1201 
   1202 static int
   1203 skipcom(void)
   1204 {
   1205 	/* skip over comments */
   1206 	register int c, i = 0;  /* i is the number of lines skipped */
   1207 
   1208 	/* skipcom is called after reading a / */
   1209 
   1210 	if (getwc(finput) != L'*')
   1211 		error("illegal comment");
   1212 	c = getwc(finput);
   1213 	while (c != EOF) {
   1214 		while (c == L'*') {
   1215 			if ((c = getwc(finput)) == L'/')
   1216 				return (i);
   1217 			}
   1218 		if (c == L'\n')
   1219 			++i;
   1220 		c = getwc(finput);
   1221 		}
   1222 	error("EOF inside comment");
   1223 	/* NOTREACHED */
   1224 	return 0;
   1225 }
   1226 
   1227 static void 
   1228 cpyact(int offset)
   1229 {
   1230 	/* copy C action to the next ; or closing } */
   1231 	int brac, c, match, i, t, j, s, tok, argument, m;
   1232 	wchar_t id_name[NAMESIZE+1];
   1233 	int id_idx = 0;
   1234 
   1235 	if (gen_lines) {
   1236 		fprintf(faction, "\n# line %d \"%s\"\n", lineno, infile);
   1237 		act_lines++;
   1238 	}
   1239 	brac = 0;
   1240 	id_name[0] = 0;
   1241 loop:
   1242 	c = getwc(finput);
   1243 swt:
   1244 	switch (c) {
   1245 	case L';':
   1246 		if (brac == 0) {
   1247 			putwc(c, faction);
   1248 			return;
   1249 		}
   1250 		goto lcopy;
   1251 	case L'{':
   1252 		brac++;
   1253 		goto lcopy;
   1254 	case L'$':
   1255 		s = 1;
   1256 		tok = -1;
   1257 		argument = 1;
   1258 		while ((c = getwc(finput)) == L' ' || c == L'\t') /* EMPTY */;
   1259 		if (c == L'<') { /* type description */
   1260 			ungetwc(c, finput);
   1261 			if (gettok() != TYPENAME)
   1262 				error("bad syntax on $<ident> clause");
   1263 			tok = numbval;
   1264 			c = getwc(finput);
   1265 		}
   1266 		if (c == L'$') {
   1267 			fprintf(faction, "yyval");
   1268 			if (ntypes) { /* put out the proper tag... */
   1269 				if (tok < 0)
   1270 					tok = fdtype(*prdptr[nprod]);
   1271 				fprintf(faction, ".%ls", typeset[tok]);
   1272 			}
   1273 			goto loop;
   1274 		}
   1275 		if (iswalpha(c)) {
   1276 			int same = 0;
   1277 			int id_sw = 0;
   1278 			ungetwc(c, finput);
   1279 			if (gettok() != IDENTIFIER)
   1280 				error("bad action format");
   1281 			/*
   1282 			 * Save the number of non-terminal
   1283 			 */
   1284 			id_sw = nnonter;
   1285 			t = chfind(1, tokname);
   1286 			/*
   1287 			 * Check if the identifier is added as a non-terminal
   1288 			 */
   1289 			if (id_sw != nnonter)
   1290 				id_sw = 1;
   1291 			else
   1292 				id_sw = 0;
   1293 			while ((c = getwc(finput)) == L' ' ||
   1294 				c == L'\t') /* EMPTY */;
   1295 			if (c == L'#') {
   1296 				while ((c = getwc(finput)) == L' ' ||
   1297 					c == L'\t') /* EMPTY */;
   1298 				if (iswdigit(c)) {
   1299 					m = 0;
   1300 					while (iswdigit(c)) {
   1301 						m = m*10+c-L'0';
   1302 						c = getwc(finput);
   1303 					}
   1304 					argument = m;
   1305 				} else
   1306 					error("illegal character \"#\"");
   1307 			}
   1308 			if (argument < 1)
   1309 				error("illegal action argument no.");
   1310 			for (i = 1; i <= offset; ++i)
   1311 				if (prdptr[nprod][i] == t)
   1312 					if (++same == argument) {
   1313 						fprintf(faction,
   1314 							"yypvt[-%d]", offset-i);
   1315 						if (ntypes) {
   1316 							if (tok < 0)
   1317 								tok =
   1318 								/* CSTYLED */
   1319 								fdtype(prdptr[nprod][i]);
   1320 							fprintf(faction,
   1321 							".%ls", typeset[tok]);
   1322 						}
   1323 						goto swt;
   1324 					}
   1325 			/*
   1326 			 * This used to be handled as error.
   1327 			 * Treat this as a valid C statement.
   1328 			 * (Likely id with $ in.)
   1329 			 * If non-terminal is added, remove it from the list.
   1330 			 */
   1331 			fprintf(faction, "$%ls", tokname);
   1332 			warning(1, 
   1333 	"Illegal character '$' in Ansi C symbol: %ls$%ls.",
   1334 				id_name, tokname);
   1335 
   1336 			if (id_sw == 1)
   1337 				--nnonter;
   1338 			goto swt;
   1339 		}
   1340 		if (c == '-') {
   1341 			s = -s;
   1342 			c = getwc(finput);
   1343 		}
   1344 		if (iswdigit(c)) {
   1345 			j = 0;
   1346 			while (iswdigit(c)) {
   1347 				j = j*10 + c - L'0';
   1348 				c = getwc(finput);
   1349 			}
   1350 			j = j*s - offset;
   1351 			if (j > 0) {
   1352 				error("Illegal use of $%d", j + offset);
   1353 			}
   1354 			fprintf(faction, "yypvt[-%d]", -j);
   1355 			if (ntypes) { /* put out the proper tag */
   1356 				if (j + offset <= 0 && tok < 0)
   1357 					error("must specify type of $%d",
   1358 					j + offset);
   1359 				if (tok < 0)
   1360 					tok = fdtype(prdptr[nprod][j+offset]);
   1361 				fprintf(faction,
   1362 					".%ls", typeset[tok]);
   1363 			}
   1364 			goto swt;
   1365 		}
   1366 		putwc(L'$', faction);
   1367 		if (s < 0)
   1368 			putwc(L'-', faction);
   1369 		goto swt;
   1370 	case L'}':
   1371 		if (--brac)
   1372 			goto lcopy;
   1373 		putwc(c, faction);
   1374 		return;
   1375 	case L'/':	/* look for comments */
   1376 		putwc(c, faction);
   1377 		c = getwc(finput);
   1378 		if (c != L'*')
   1379 			goto swt;
   1380 		/* it really is a comment */
   1381 		putwc(c, faction);
   1382 		c = getwc(finput);
   1383 		while (c != EOF) {
   1384 			while (c == L'*') {
   1385 				putwc(c, faction);
   1386 				if ((c = getwc(finput)) == L'/')
   1387 					goto lcopy;
   1388 			}
   1389 			putwc(c, faction);
   1390 			if (c == L'\n')
   1391 				++lineno;
   1392 			c = getwc(finput);
   1393 		}
   1394 		error("EOF inside comment");
   1395 		/* FALLTHRU */
   1396 	case L'\'':	/* character constant */
   1397 	case L'"':	/* character string */
   1398 		match = c;
   1399 		putwc(c, faction);
   1400 		while ((c = getwc(finput)) != EOF) {
   1401 			if (c == L'\\') {
   1402 				putwc(c, faction);
   1403 				c = getwc(finput);
   1404 				if (c == L'\n')
   1405 					++lineno;
   1406 			} else if (c == match)
   1407 				goto lcopy;
   1408 			else if (c == L'\n')
   1409 				error("newline in string or char. const.");
   1410 			putwc(c, faction);
   1411 		}
   1412 		error("EOF in string or character constant");
   1413 		/* FALLTHRU */
   1414 	case EOF:
   1415 		error("action does not terminate");
   1416 		/* FALLTHRU */
   1417 	case L'\n':
   1418 		++lineno;
   1419 		goto lcopy;
   1420 	}
   1421 lcopy:
   1422 	putwc(c, faction);
   1423 	/*
   1424 	 * Save the possible identifier name.
   1425 	 * Used to print out a warning message.
   1426 	 */
   1427 	if (id_idx >= NAMESIZE) {
   1428 		/*
   1429 		 * Error. Silently ignore.
   1430 		 */
   1431 		;
   1432 	}
   1433 	/*
   1434 	 * If c has a possibility to be a
   1435 	 * part of identifier, save it.
   1436 	 */
   1437 	else if (iswalnum(c) || c == L'_') {
   1438 		id_name[id_idx++] = c;
   1439 		id_name[id_idx] = 0;
   1440 	} else {
   1441 		id_idx = 0;
   1442 		id_name[id_idx] = 0;
   1443 	}
   1444 	goto loop;
   1445 }
   1446 
   1447 static void
   1448 lhsfill(s)	/* new rule, dump old (if exists), restart strings */
   1449 wchar_t *s;
   1450 {
   1451 	static int lhs_len = LHS_TEXT_LEN;
   1452 	int s_lhs = wcslen(s);
   1453 	if (s_lhs >= lhs_len) {
   1454 		lhs_len = s_lhs + 2;
   1455 		lhstext = realloc(lhstext, sizeof (wchar_t)*lhs_len);
   1456 		if (lhstext == NULL)
   1457 			error("couldn't expanded LHS length");
   1458 	}
   1459 	rhsfill(NULL);
   1460 	wcscpy(lhstext, s); /* don't worry about too long of a name */
   1461 }
   1462 
   1463 static void
   1464 rhsfill(wchar_t *s)	/* either name or 0 */
   1465 {
   1466 	static wchar_t *loc;	/* next free location in rhstext */
   1467 	static int rhs_len = RHS_TEXT_LEN;
   1468 	static int used = 0;
   1469 	int s_rhs = (s == NULL ? 0 : wcslen(s));
   1470 	register wchar_t *p;
   1471 
   1472 	if (!s)	/* print out and erase old text */
   1473 	{
   1474 		if (*lhstext)		/* there was an old rule - dump it */
   1475 			lrprnt();
   1476 		(loc = rhstext)[0] = 0;
   1477 		return;
   1478 	}
   1479 	/* add to stuff in rhstext */
   1480 	p = s;
   1481 
   1482 	used = loc - rhstext;
   1483 	if ((s_rhs + 3) >= (rhs_len - used)) {
   1484 		static wchar_t *textbase;
   1485 		textbase = rhstext;
   1486 		rhs_len += s_rhs + RHS_TEXT_LEN;
   1487 		rhstext = realloc(rhstext, sizeof (wchar_t)*rhs_len);
   1488 		if (rhstext == NULL)
   1489 			error("couldn't expanded RHS length");
   1490 		loc = loc - textbase + rhstext;
   1491 	}
   1492 
   1493 	*loc++ = L' ';
   1494 	if (*s == L' ') /* special quoted symbol */
   1495 	{
   1496 		*loc++ = L'\'';	/* add first quote */
   1497 		p++;
   1498 	}
   1499 	while (*loc = *p++)
   1500 		if (loc++ > &rhstext[ RHS_TEXT_LEN ] - 3)
   1501 			break;
   1502 
   1503 	if (*s == L' ')
   1504 		*loc++ = L'\'';
   1505 	*loc = 0;		/* terminate the string */
   1506 }
   1507 
   1508 static void 
   1509 lrprnt (void)	/* print out the left and right hand sides */
   1510 {
   1511 	wchar_t *rhs;
   1512 	wchar_t *m_rhs = NULL;
   1513 
   1514 	if (!*rhstext)		/* empty rhs - print usual comment */
   1515 		rhs = L" /* empty */";
   1516 	else {
   1517 		int idx1; /* tmp idx used to find if there are d_quotes */
   1518 		int idx2; /* tmp idx used to generate escaped string */
   1519 		wchar_t *p;
   1520 		/*
   1521 		 * Check if there are any double quote in RHS.
   1522 		 */
   1523 		for (idx1 = 0; rhstext[idx1] != 0; idx1++) {
   1524 			if (rhstext[idx1] == L'"') {
   1525 				/*
   1526 				 * A double quote is found.
   1527 				 */
   1528 				idx2 = wcslen(rhstext)*2;
   1529 				p = m_rhs = malloc((idx2 + 1)*sizeof (wchar_t));
   1530 				if (m_rhs == NULL)
   1531 					error(
   1532 					"Couldn't allocate memory for RHS.");
   1533 				/*
   1534 				 * Copy string
   1535 				 */
   1536 				for (idx2 = 0; rhstext[idx2] != 0; idx2++) {
   1537 					/*
   1538 					 * Check if this quote is escaped or not
   1539 					 */
   1540 					if (rhstext[idx2] == L'"') {
   1541 						int tmp_l = idx2-1;
   1542 						int cnt = 0;
   1543 						while (tmp_l >= 0 &&
   1544 						rhstext[tmp_l] == '\\') {
   1545 							cnt++;
   1546 							tmp_l--;
   1547 						}
   1548 						/*
   1549 						 * If quote is not escaped,
   1550 						 * then escape it.
   1551 						 */
   1552 						if (cnt%2 == 0)
   1553 							*p++ = L'\\';
   1554 					}
   1555 					*p++ = rhstext[idx2];
   1556 				}
   1557 				*p = 0;
   1558 				/*
   1559 				 * Break from the loop
   1560 				 */
   1561 				break;
   1562 			}
   1563 		}
   1564 		if (m_rhs == NULL)
   1565 			rhs = rhstext;
   1566 		else
   1567 			rhs = m_rhs;
   1568 	}
   1569 	fprintf(fdebug, "\t\"%ls :%ls\",\n", lhstext, rhs);
   1570 	if (m_rhs)
   1571 		free(m_rhs);
   1572 }
   1573 
   1574 
   1575 static void 
   1576 beg_debug (void)	/* dump initial sequence for fdebug file */
   1577 {
   1578 	fprintf(fdebug, "typedef struct\n");
   1579 	fprintf(fdebug, "#ifdef __cplusplus\n\tyytoktype\n");
   1580 	fprintf(fdebug, "#endif\n{\n");
   1581 	fprintf(fdebug, "#ifdef __cplusplus\nconst\n#endif\n");
   1582 	fprintf(fdebug, "char *t_name; int t_val; } yytoktype;\n");
   1583 	fprintf(fdebug, "#ifndef YYDEBUG\n#\tdefine YYDEBUG\t%d", gen_testing);
   1584 	fprintf(fdebug, "\t/*%sallow debugging */\n#endif\n\n",
   1585 		gen_testing ? " " : " don't ");
   1586 	fprintf(fdebug, "#if YYDEBUG\n\nyytoktype yytoks[] =\n{\n");
   1587 }
   1588 
   1589 
   1590 static void 
   1591 end_toks (void)	/* finish yytoks array, get ready for yyred's strings */
   1592 {
   1593 	fprintf(fdebug, "\t\"-unknown-\",\t-1\t/* ends search */\n");
   1594 	fprintf(fdebug, "};\n\n");
   1595 	fprintf(fdebug,
   1596 		"#ifdef __cplusplus\nconst\n#endif\n");
   1597 	fprintf(fdebug, "char * yyreds[] =\n{\n");
   1598 	fprintf(fdebug, "\t\"-no such reduction-\",\n");
   1599 }
   1600 
   1601 
   1602 static void 
   1603 end_debug (void)	/* finish yyred array, close file */
   1604 {
   1605 	lrprnt();		/* dump last lhs, rhs */
   1606 	fprintf(fdebug, "};\n#endif /* YYDEBUG */\n");
   1607 	fclose(fdebug);
   1608 }
   1609 
   1610 
   1611 /*
   1612  * 2/29/88 -
   1613  * The normal length for token sizes is NAMESIZE - If a token is
   1614  * seen that has a longer length, expand "tokname" by NAMESIZE.
   1615  */
   1616 static void 
   1617 exp_tokname(void)
   1618 {
   1619 	toksize += NAMESIZE;
   1620 	tokname = realloc(tokname, sizeof (wchar_t) * toksize);
   1621 }
   1622 
   1623 
   1624 /*
   1625  * 2/29/88 -
   1626  *
   1627  */
   1628 static void 
   1629 exp_prod(void)
   1630 {
   1631 	int i;
   1632 	nprodsz += NPROD;
   1633 
   1634 	prdptr = realloc(prdptr, sizeof (int *) * (nprodsz+2));
   1635 	levprd  = realloc(levprd, sizeof (int) * (nprodsz+2));
   1636 	had_act = realloc(had_act, sizeof (wchar_t) * (nprodsz+2));
   1637 	for (i = nprodsz-NPROD; i < nprodsz+2; ++i)
   1638 		had_act[i] = 0;
   1639 
   1640 	if ((*prdptr == NULL) || (levprd == NULL) || (had_act == NULL))
   1641 		error("couldn't expand productions");
   1642 }
   1643 
   1644 /*
   1645  * 2/29/88 -
   1646  * Expand the number of terminals.  Initially there are NTERMS;
   1647  * each time space runs out, the size is increased by NTERMS.
   1648  * The total size, however, cannot exceed MAXTERMS because of
   1649  * the way LOOKSETS(struct looksets) is set up.
   1650  * Tables affected:
   1651  *	tokset, toklev : increased to ntoksz
   1652  *
   1653  *	tables with initial dimensions of TEMPSIZE must be changed if
   1654  *	(ntoksz + NNONTERM) >= TEMPSIZE : temp1[]
   1655  */
   1656 static void 
   1657 exp_ntok(void)
   1658 {
   1659 	ntoksz += NTERMS;
   1660 
   1661 	tokset = realloc(tokset, sizeof (TOKSYMB) * ntoksz);
   1662 	toklev = realloc(toklev, sizeof (int) * ntoksz);
   1663 
   1664 	if ((tokset == NULL) || (toklev == NULL))
   1665 		error("couldn't expand NTERMS");
   1666 }
   1667 
   1668 
   1669 static void 
   1670 exp_nonterm(void)
   1671 {
   1672 	nnontersz += NNONTERM;
   1673 
   1674 	nontrst = realloc(nontrst, sizeof (TOKSYMB) * nnontersz);
   1675 	if (nontrst == NULL)
   1676 		error("couldn't expand NNONTERM");
   1677 }
   1678 
   1679 void 
   1680 exp_mem(int flag)
   1681 {
   1682 	int i;
   1683 	static int *membase;
   1684 	new_memsize += MEMSIZE;
   1685 
   1686 	membase = tracemem;
   1687 	tracemem = realloc(tracemem, sizeof (int) * new_memsize);
   1688 	if (tracemem == NULL)
   1689 		error("couldn't expand mem table");
   1690 	if (flag) {
   1691 		for (i = 0; i <= nprod; ++i)
   1692 			prdptr[i] = prdptr[i] - membase + tracemem;
   1693 		mem = mem - membase + tracemem;
   1694 	} else {
   1695 		size += MEMSIZE;
   1696 		temp1 = realloc(temp1, sizeof (int)*size);
   1697 		optimmem = optimmem - membase + tracemem;
   1698 	}
   1699 }
   1700 
   1701 static int 
   1702 findchtok(int chlit)
   1703 /*
   1704  * findchtok(chlit) returns the token number for a character literal
   1705  * chlit that is "bigger" than 255 -- the max char value that the
   1706  * original yacc was build for.  This yacc treate them as though
   1707  * an ordinary token.
   1708  */
   1709 {
   1710 	int	i;
   1711 
   1712 	if (chlit < 0xff)
   1713 		return (chlit); /* single-byte char */
   1714 	for (i = 0; i < nmbchars; ++i) {
   1715 		if (mbchars->character == chlit)
   1716 			return (mbchars->tvalue);
   1717 	}
   1718 
   1719 	/* Not found.  Register it! */
   1720 	if (++nmbchars > nmbcharsz) { /* Make sure there's enough space */
   1721 		nmbcharsz += NMBCHARSZ;
   1722 		mbchars = realloc(mbchars, sizeof (MBCLIT)*nmbcharsz);
   1723 		if (mbchars == NULL)
   1724 			error("too many character literals");
   1725 	}
   1726 	mbchars[nmbchars-1].character = chlit;
   1727 	return (mbchars[nmbchars-1].tvalue = extval++);
   1728 	/* Return the newly assigned token. */
   1729 }
   1730 
   1731 /*
   1732  * When -p is specified, symbol prefix for
   1733  *	yy{parse, lex, error}(),
   1734  *	yy{lval, val, char, debug, errflag, nerrs}
   1735  * are defined to the specified name.
   1736  */
   1737 static void
   1738 put_prefix_define(char *pre)
   1739 {
   1740 	char *syms[] = {
   1741 		/* Functions */
   1742 		"parse",
   1743 		"lex",
   1744 		"error",
   1745 		/* Variables */
   1746 		"lval",
   1747 		"val",
   1748 		"char",
   1749 		"debug",
   1750 		"errflag",
   1751 		"nerrs",
   1752 		NULL};
   1753 	int i;
   1754 
   1755 	for (i = 0; syms[i]; i++)
   1756 		fprintf(ftable, "#define\tyy%s\t%s%s\n",
   1757 			syms[i], pre, syms[i]);
   1758 }