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