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