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