y2.c revision 100:56ddb8295b81
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
60char *infile;				/* input file name 		*/
61static int numbval;			/* value of an input number 	*/
62static int toksize = NAMESIZE;
63static wchar_t *tokname;	/* input token name		*/
64char *parser = NULL;		/* location of common parser 	*/
65
66static void finact(void);
67static wchar_t *cstash(wchar_t *);
68static void defout(void);
69static void cpyunion(void);
70static void cpycode(void);
71static void cpyact(int);
72static void lhsfill(wchar_t *);
73static void rhsfill(wchar_t *);
74static void lrprnt(void);
75static void beg_debug(void);
76static void end_toks(void);
77static void end_debug(void);
78static void exp_tokname(void);
79static void exp_prod(void);
80static void exp_ntok(void);
81static void exp_nonterm(void);
82static int defin(int, wchar_t *);
83static int gettok(void);
84static int chfind(int, wchar_t *);
85static int skipcom(void);
86static int findchtok(int);
87static 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 */
98static wchar_t cnamesblk0[CNAMSZ];
99static wchar_t *cnames = cnamesblk0;
100
101/* place where next name is to be put in */
102static wchar_t *cnamp = cnamesblk0;
103
104/* number of defined symbols output */
105static int ndefout = 3;
106
107	/* storage of types */
108static int defunion = 0;	/* union of types defined? */
109static int ntypes = 0;		/* number of types defined */
110static wchar_t *typeset[NTYPES]; /* pointers to type tags */
111
112	/* symbol tables for tokens and nonterminals */
113
114int ntokens = 0;
115int ntoksz = NTERMS;
116TOKSYMB *tokset;
117int *toklev;
118
119int nnonter = -1;
120NTSYMB *nontrst;
121int nnontersz = NNONTERM;
122
123static int start;	/* start symbol */
124
125	/* assigned token type values */
126static int extval = 0;
127
128	/* input and output file descriptors */
129
130FILE *finput;		/* yacc input file */
131FILE *faction;		/* file for saving actions */
132FILE *fdefine;		/* file for # defines */
133FILE *ftable;		/* y.tab.c file */
134FILE *ftemp;		/* tempfile to pass 2 */
135FILE *fdebug;		/* where the strings for debugging are stored */
136FILE *foutput;		/* y.output file */
137
138	/* output string */
139
140static wchar_t *lhstext;
141static wchar_t *rhstext;
142
143	/* storage for grammar rules */
144
145int *mem0; /* production storage */
146int *mem;
147int *tracemem;
148extern int *optimmem;
149int new_memsize = MEMSIZE;
150int nprod = 1;	/* number of productions */
151int nprodsz = NPROD;
152
153int **prdptr;
154int *levprd;
155wchar_t *had_act;
156
157/* flag for generating the # line's default is yes */
158int gen_lines = 1;
159int act_lines = 0;
160
161/* flag for whether to include runtime debugging */
162static int gen_testing = 0;
163
164/* flag for version stamping--default turned off */
165static char *v_stmp = "n";
166
167int nmbchars = 0;	/* number of mb literals in mbchars */
168MBCLIT *mbchars = (MBCLIT *) 0; /* array of mb literals */
169int nmbcharsz = 0; /* allocated space for mbchars */
170
171void
172setup(argc, argv)
173int argc;
174char *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
844static void
845finact()
846{
847	/* finish action routine */
848	(void) fclose(faction);
849	(void) fprintf(ftable, "# define YYERRCODE %d\n", tokset[2].value);
850}
851
852static wchar_t *
853cstash(s)
854register 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
894static int
895defin(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
1055static void
1056defout()
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
1097static int
1098gettok()
1099{
1100	int i, base;
1101	static int peekline; /* number of '\n' seen in lookahead */
1102	int c, match, reserve;
1103begin:
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
1271static int
1272fdtype(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
1288static int
1289chfind(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
1312static void
1313cpyunion()
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
1368static void
1369cpycode()
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
1407static int
1408skipcom()
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
1439static void
1440cpyact(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;
1453loop:
1454	c = getwc(finput);
1455swt:
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	}
1685lcopy:
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
1711static void
1712lhsfill(s)	/* new rule, dump old (if exists), restart strings */
1713wchar_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
1734static void
1735rhsfill(s)
1736wchar_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
1787static void
1788lrprnt()	/* 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
1863static void
1864beg_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
1882static void
1883end_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
1894static void
1895end_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 */
1908static void
1909exp_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 */
1921static void
1922exp_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 */
1958static void
1959exp_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
1980static void
1981exp_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
2000void
2001exp_mem(flag)
2002int 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
2032static int
2033findchtok(chlit)
2034int 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 */
2071static void
2072put_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