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