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