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