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