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