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