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