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