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