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