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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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