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