1/* Id: cpp.c,v 1.252 2016/02/06 09:39:21 ragge Exp */ 2/* $NetBSD: cpp.c,v 1.4 2016/02/09 20:37:32 plunky Exp $ */ 3 4/* 5 * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * The C preprocessor. 31 * This code originates from the V6 preprocessor with some additions 32 * from V7 cpp, and at last ansi/c99 support. 33 * 34 * - kfind() expands the input buffer onto XXX 35 * - exparg() expand one buffer into another. 36 * Recurses into submac() for fun-like macros. 37 * - submac() replaces the given macro. 38 * Recurses into subarg() for fun-like macros. 39 * - subarg() expands fun-like macros. 40 * Create strings, concats args, recurses into exparg. 41 */ 42 43#include "config.h" 44 45#include <sys/stat.h> 46 47#include <fcntl.h> 48#ifdef HAVE_UNISTD_H 49#include <unistd.h> 50#endif 51#include <stdio.h> 52#include <stdarg.h> 53#include <stdlib.h> 54#include <string.h> 55#include <time.h> 56 57#include "compat.h" 58#include "cpp.h" 59 60#ifndef S_ISDIR 61#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 62#endif 63 64#define SBSIZE 1000000 65 66static usch sbf[SBSIZE]; 67static int counter; 68/* C command */ 69 70int tflag; /* traditional cpp syntax */ 71#ifdef PCC_DEBUG 72int dflag; /* debug printouts */ 73//static void imp(const char *); 74static void prline(const usch *s); 75static void prrep(const usch *s); 76#define DPRINT(x) if (dflag) printf x 77#define DDPRINT(x) if (dflag > 1) printf x 78#define IMP(x) if (dflag > 1) imp(x) 79#else 80#define DPRINT(x) 81#define DDPRINT(x) 82#define IMP(x) 83#endif 84 85int Aflag, Cflag, Eflag, Mflag, dMflag, Pflag, MPflag, MMDflag; 86char *Mfile, *MPfile; 87struct initar *initar; 88char *Mxfile; 89int warnings, Mxlen; 90FILE *of; 91 92/* include dirs */ 93struct incs { 94 struct incs *next; 95 usch *dir; 96 dev_t dev; 97 ino_t ino; 98} *incdir[2]; 99 100static struct symtab *filloc; 101static struct symtab *linloc; 102static struct symtab *pragloc; 103static struct symtab *defloc; 104static struct symtab *ctrloc; 105int trulvl; 106int flslvl; 107int elflvl; 108int elslvl; 109usch *stringbuf = sbf; 110 111/* 112 * Macro replacement list syntax: 113 * - For object-type macros, replacement strings are stored as-is. 114 * - For function-type macros, macro args are substituted for the 115 * character WARN followed by the argument number. 116 * - The value element points to the beginning of the string. 117 * 118 * The first character in the replacement list is the number of arguments: 119 * VARG - ends with ellipsis, next char is argcount without ellips. 120 * OBJCT - object-type macro 121 * 0 - empty parenthesis, foo() 122 * 1-> - number of args. 123 * 124 * WARN is used: 125 * - in stored replacement lists to tell that an argument comes 126 * - When expanding replacement lists to tell that the list ended. 127 * 128 * To ensure that an already expanded identifier won't get expanded 129 * again a EBLOCK char + its number is stored directly before any 130 * expanded identifier. 131 */ 132 133/* args for lookup() */ 134#define FIND 0 135#define ENTER 1 136 137/* 138 * No-replacement array. If a macro is found and exists in this array 139 * then no replacement shall occur. 140 */ 141struct blocker { 142 struct blocker *next; 143 struct symtab *sp; 144}; 145struct blocker *blkidx[RECMAX]; 146int blkidp; 147 148static int readargs2(usch **, struct symtab *sp, const usch **args); 149static int readargs1(struct symtab *sp, const usch **args); 150static struct iobuf *exparg(int, struct iobuf *, struct iobuf *, struct blocker *); 151static struct iobuf *subarg(struct symtab *sp, const usch **args, int, struct blocker *); 152static void usage(void); 153static usch *xstrdup(const usch *str); 154static void addidir(char *idir, struct incs **ww); 155static void vsheap(const char *, va_list); 156static int skipws(struct iobuf *ib); 157static int getyp(usch *s); 158static void *xrealloc(void *p, int sz); 159static void *xmalloc(int sz); 160 161usch locs[] = 162 { FILLOC, LINLOC, PRAGLOC, DEFLOC, 163 'd','e','f','i','n','e','d',0, CTRLOC }; 164 165int 166main(int argc, char **argv) 167{ 168 struct initar *it; 169 register int ch; 170 const usch *fn1, *fn2; 171 172#ifdef TIMING 173 struct timeval t1, t2; 174 175 (void)gettimeofday(&t1, NULL); 176#endif 177 178 while ((ch = getopt(argc, argv, "ACD:d:EI:i:MPS:tU:Vvx:")) != -1) { 179 switch (ch) { 180 case 'A': /* assembler input */ 181 Aflag++; 182 break; 183 184 case 'C': /* Do not discard comments */ 185 Cflag++; 186 break; 187 188 case 'E': /* treat warnings as errors */ 189 Eflag++; 190 break; 191 192 case 'D': /* define something */ 193 case 'i': /* include */ 194 case 'U': /* undef */ 195 /* XXX should not need malloc() here */ 196 if ((it = xmalloc(sizeof(struct initar))) == NULL) 197 error("couldn't apply -%c %s", ch, optarg); 198 it->type = ch; 199 it->str = optarg; 200 it->next = initar; 201 initar = it; 202 break; 203 204 case 'd': 205 while (*optarg) { 206 switch(*optarg) { 207 case 'M': /* display macro definitions */ 208 dMflag = 1; 209 Mflag = 1; 210 break; 211 212 default: /* ignore others */ 213 break; 214 } 215 optarg++; 216 } 217 break; 218 219 case 'I': 220 case 'S': 221 addidir(optarg, &incdir[ch == 'I' ? INCINC : SYSINC]); 222 break; 223 224 case 'M': /* Generate dependencies for make */ 225 Mflag++; 226 break; 227 228 case 'P': /* Inhibit generation of line numbers */ 229 Pflag++; 230 break; 231 232 case 't': 233 tflag = 1; 234 break; 235 236#ifdef PCC_DEBUG 237 case 'V': 238 dflag++; 239 break; 240#endif 241 case 'v': 242 fprintf(stderr, "PCC preprocessor version "VERSSTR"\n"); 243 break; 244 245 case 'x': 246 if (strcmp(optarg, "MMD") == 0) { 247 MMDflag++; 248 } else if (strcmp(optarg, "MP") == 0) { 249 MPflag++; 250 } else if (strncmp(optarg, "MT,", 3) == 0 || 251 strncmp(optarg, "MQ,", 3) == 0) { 252 int l = strlen(optarg+3) + 2; 253 char *cp, *up; 254 255 if (optarg[1] == 'Q') 256 for (cp = optarg+3; *cp; cp++) 257 if (*cp == '$') 258 l++; 259 Mxlen += l; 260 Mxfile = cp = realloc(Mxfile, Mxlen); 261 for (up = Mxfile; *up; up++) 262 ; 263 if (up != Mxfile) 264 *up++ = ' '; 265 for (cp = optarg+3; *cp; cp++) { 266 *up++ = *cp; 267 if (optarg[1] == 'Q' && *cp == '$') 268 *up++ = *cp; 269 } 270 *up = 0; 271 } else 272 usage(); 273 break; 274 275 case '?': 276 default: 277 usage(); 278 } 279 } 280 281 argc -= optind; 282 argv += optind; 283 284 filloc = lookup((const usch *)"__FILE__", ENTER); 285 linloc = lookup((const usch *)"__LINE__", ENTER); 286 pragloc = lookup((const usch *)"_Pragma", ENTER); 287 defloc = lookup((const usch *)"defined", ENTER); 288 ctrloc = lookup((const usch *)"__COUNTER__", ENTER); 289 filloc->value = locs; 290 linloc->value = locs+1; 291 pragloc->value = locs+2; 292 defloc->value = locs+3; /* also have macro name here */ 293 ctrloc->value = locs+12; 294 295 if (Mflag && !dMflag) { 296 char *c; 297 298 if (argc < 1) 299 error("-M and no infile"); 300 if ((c = strrchr(argv[0], '/')) == NULL) 301 c = argv[0]; 302 else 303 c++; 304 Mfile = (char *)xstrdup((usch *)c); 305 if (MPflag) 306 MPfile = (char *)xstrdup((usch *)c); 307 if (Mxfile) 308 Mfile = Mxfile; 309 if ((c = strrchr(Mfile, '.')) == NULL) 310 error("-M and no extension: "); 311 c[1] = 'o'; 312 c[2] = 0; 313 } 314 315 if (argc == 2) { 316 if ((of = freopen(argv[1], "w", stdout)) == NULL) 317 error("Can't creat %s", argv[1]); 318 } else 319 of = stdout; 320 321 if (argc && strcmp(argv[0], "-")) { 322 fn1 = fn2 = (usch *)argv[0]; 323 } else { 324 fn1 = NULL; 325 fn2 = (const usch *)""; 326 } 327 if (pushfile(fn1, fn2, 0, NULL)) 328 error("cannot open %s", argv[0]); 329 330 fclose(of); 331#ifdef TIMING 332 (void)gettimeofday(&t2, NULL); 333 t2.tv_sec -= t1.tv_sec; 334 t2.tv_usec -= t1.tv_usec; 335 if (t2.tv_usec < 0) { 336 t2.tv_usec += 1000000; 337 t2.tv_sec -= 1; 338 } 339 fprintf(stderr, "cpp total time: %ld s %ld us\n", 340 (long)t2.tv_sec, (long)t2.tv_usec); 341#endif 342 if (Eflag && warnings > 0) 343 return 2; 344 345 return 0; 346} 347 348/* 349 * Write a character to an out buffer. 350 */ 351static void 352putob(struct iobuf *ob, int ch) 353{ 354 if (ob->cptr == ob->bsz) { 355 int sz = ob->bsz - ob->buf; 356 ob->buf = xrealloc(ob->buf, sz + BUFSIZ); 357 ob->cptr = ob->buf + sz; 358 ob->bsz = ob->buf + sz + BUFSIZ; 359 } 360// DDPRINT(("putob: iob %p pos %p ch %c (%d)\n", ob, ob->cptr, ch, ch)); 361 *ob->cptr++ = ch; 362} 363 364static int nbufused; 365/* 366 * Write a character to an out buffer. 367 */ 368static struct iobuf * 369getobuf(void) 370{ 371 struct iobuf *iob = xmalloc(sizeof(struct iobuf)); 372 373 nbufused++; 374 iob->buf = iob->cptr = xmalloc(BUFSIZ); 375 iob->bsz = iob->buf + BUFSIZ; 376 iob->ro = 0; 377 return iob; 378} 379 380/* 381 * Create a read-only input buffer. 382 */ 383static struct iobuf * 384mkrobuf(const usch *s) 385{ 386 struct iobuf *iob = xmalloc(sizeof(struct iobuf)); 387 388 nbufused++; 389 DPRINT(("mkrobuf %s\n", s)); 390 iob->buf = iob->cptr = (usch *)s; 391 iob->bsz = iob->buf + strlen((char *)iob->buf); 392 iob->ro = 1; 393 return iob; 394} 395 396/* 397 * Copy a string to a buffer. 398 */ 399static struct iobuf * 400strtobuf(usch *str, struct iobuf *iob) 401{ 402 DPRINT(("strtobuf iob %p buf %p str %s\n", iob, iob->buf, str)); 403 if (iob == NULL) 404 iob = getobuf(); 405 do { 406 putob(iob, *str); 407 } while (*str++); 408 iob->cptr--; 409 return iob; 410} 411 412static void 413bufree(struct iobuf *iob) 414{ 415 nbufused--; 416 if (iob->ro == 0) 417 free(iob->buf); 418 free(iob); 419} 420 421static void 422addidir(char *idir, struct incs **ww) 423{ 424 struct incs *w; 425 struct stat st; 426 427 if (stat(idir, &st) == -1 || !S_ISDIR(st.st_mode)) 428 return; /* ignore */ 429 if (*ww != NULL) { 430 for (w = *ww; w->next; w = w->next) { 431#ifdef _WIN32 432 if (strcmp(w->dir, idir) == 0) 433 return; 434#else 435 if (w->dev == st.st_dev && w->ino == st.st_ino) 436 return; 437#endif 438 } 439#ifdef _WIN32 440 if (strcmp(w->dir, idir) == 0) 441 return; 442#else 443 if (w->dev == st.st_dev && w->ino == st.st_ino) 444 return; 445#endif 446 ww = &w->next; 447 } 448 if ((w = calloc(sizeof(struct incs), 1)) == NULL) 449 error("couldn't add path %s", idir); 450 w->dir = (usch *)idir; 451 w->dev = st.st_dev; 452 w->ino = st.st_ino; 453 *ww = w; 454} 455 456void 457line(void) 458{ 459 struct symtab *nl; 460 int c, n, ln; 461 usch *cp; 462 463 cp = stringbuf; 464 c = skipws(0); 465 if (ISID0(c)) { /* expand macro */ 466 heapid(c); 467 stringbuf = cp; 468 if ((nl = lookup(cp, FIND)) == 0 || kfind(nl) == 0) 469 goto bad; 470 } else { 471 do { 472 savch(c); 473 } while (ISDIGIT(c = cinput())); 474 cunput(c); 475 savch(0); 476 } 477 478 stringbuf = cp; 479 n = 0; 480 while (ISDIGIT(*cp)) 481 n = n * 10 + *cp++ - '0'; 482 if (*cp != 0) 483 goto bad; 484 485 /* Can only be decimal number here between 1-2147483647 */ 486 if (n < 1 || n > 2147483647) 487 goto bad; 488 489 ln = n; 490 ifiles->escln = 0; 491 if ((c = skipws(NULL)) != '\n') { 492 if (c == 'L' || c == 'U' || c == 'u') { 493 n = c, c = cinput(); 494 if (n == 'u' && c == '8') 495 c = cinput(); 496 if (c == '\"') 497 warning("#line only allows character literals"); 498 } 499 if (c != '\"') 500 goto bad; 501 /* loses space on heap... does it matter? */ 502 ifiles->fname = stringbuf+1; 503 faststr(c, savch); 504 stringbuf--; 505 savch(0); 506 507 c = skipws(0); 508 } 509 if (c != '\n') 510 goto bad; 511 512 ifiles->lineno = ln; 513 prtline(1); 514 ifiles->lineno--; 515 cunput('\n'); 516 return; 517 518bad: error("bad #line"); 519} 520 521#ifdef MACHOABI 522 523/* 524 * Search for framework header file. 525 * Return 1 on success. 526 */ 527 528static int 529fsrch_macos_framework(const usch *fn, const usch *dir) 530{ 531 usch *saved_stringbuf = stringbuf; 532 usch *s = (usch *)strchr((const char*)fn, '/'); 533 usch *nm; 534 usch *p; 535 int len = s - fn; 536 537 if (s == NULL) 538 return 0; 539 540// fprintf(stderr, "searching for %s in %s\n", (const char *)fn, (const char *)dir); 541 542 nm = savstr(dir); 543 savch(0); 544 p = savstr(fn); 545 stringbuf = p + len; 546 savch(0); 547// fprintf(stderr, "comparing \"%s\" against \"%.*s\"\n", nm, len, fn); 548 p = (usch *)strstr((const char *)nm, (const char *)p); 549// fprintf(stderr, "p = %s\n", (const char *)p); 550 if (p != NULL) { 551 stringbuf = p; 552 savch(0); 553 return fsrch_macos_framework(fn, nm); 554 } 555 556 p = nm + strlen((char *)nm) - 1; 557 while (*p == '/') 558 p--; 559 while (*p != '/') 560 p--; 561 stringbuf = ++p; 562 savstr((const usch *)"Frameworks/"); 563 stringbuf = savstr(fn) + len; 564 savstr((const usch*)".framework/Headers"); 565 savstr(s); 566 savch(0); 567 568// fprintf(stderr, "nm: %s\n", nm); 569 570 if (pushfile(nm, fn, SYSINC, NULL) == 0) 571 return 1; 572// fprintf(stderr, "not found %s, continuing...\n", nm); 573 574 stringbuf = saved_stringbuf; 575 576 return 0; 577} 578 579#endif 580 581/* 582 * Search for and include next file. 583 * Return 1 on success. 584 */ 585static int 586fsrch(const usch *fn, int idx, struct incs *w) 587{ 588 int i; 589 590 for (i = idx; i < 2; i++) { 591 if (i > idx) 592 w = incdir[i]; 593 for (; w; w = w->next) { 594 usch *nm = stringbuf; 595 596 savstr(w->dir); savch('/'); 597 savstr(fn); savch(0); 598 if (pushfile(nm, fn, i, w->next) == 0) 599 return 1; 600 stringbuf = nm; 601 } 602 } 603 604#ifdef MACHOABI 605 /* 606 * On MacOS, we may have to do some clever stuff 607 * to resolve framework headers. 608 */ 609 { 610 usch *dir = stringbuf; 611 savstr(ifiles->orgfn); 612 stringbuf = (usch *)strrchr((char *)dir, '/'); 613 if (stringbuf != NULL) { 614 stringbuf++; 615 savch(0); 616 if (fsrch_macos_framework(fn, dir) == 1) 617 return 1; 618 } 619 stringbuf = dir; 620 621 if (fsrch_macos_framework(fn, (const usch *)"/Library/Frameworks/") == 1) 622 return 1; 623 624 if (fsrch_macos_framework(fn, (const usch *)"/System/Library/Frameworks/") == 1) 625 return 1; 626 } 627#endif 628 629 return 0; 630} 631 632static void 633prem(void) 634{ 635 error("premature EOF"); 636} 637 638static struct iobuf * 639incfn(void) 640{ 641 struct iobuf *ob; 642 struct symtab *nl; 643 usch *sb; 644 int c; 645 646 sb = stringbuf; 647 if (spechr[c = skipws(NULL)] & C_ID0) { 648 heapid(c); 649 if ((nl = lookup(sb, FIND)) == NULL) 650 return NULL; 651 652 stringbuf = sb; 653 if (kfind(nl) == 0) 654 return NULL; 655 ob = strtobuf(sb, NULL); 656 } else { 657 ob = getobuf(); 658 putob(ob, c); 659 while ((c = cinput()) && c != '\n') 660 putob(ob, c); 661 if (c != '\n') 662 return NULL; 663 cunput(c); 664 } 665 putob(ob, 0); 666 ob->cptr--; 667 668 /* now we have an (expanded?) filename in obuf */ 669 while (ob->buf < ob->cptr && ISWS(ob->cptr[-1])) 670 ob->cptr--; 671 672 if (ob->buf[0] != '\"' && ob->buf[0] != '<') 673 return NULL; 674 if (ob->cptr[-1] != '\"' && ob->cptr[-1] != '>') 675 return NULL; 676 ob->cptr[-1] = 0; 677 return ob; 678} 679 680/* 681 * Include a file. Include order: 682 * - For <...> files, first search -I directories, then system directories. 683 * - For "..." files, first search "current" dir, then as <...> files. 684 */ 685void 686include(void) 687{ 688 struct iobuf *ob; 689 usch *fn, *nm = NULL; 690 691 if (flslvl) 692 return; 693 694 if ((ob = incfn()) == NULL) /* get include file name in obuf */ 695 error("bad #include"); 696 697 fn = xstrdup(ob->buf) + 1; /* Save on string heap? */ 698 bufree(ob); 699 /* test absolute path first */ 700 if (fn[0] == '/' && pushfile(fn, fn, 0, NULL) == 0) 701 goto okret; 702 if (fn[-1] == '\"') { 703 /* nope, failed, try to create a path for it */ 704 if ((nm = (usch *)strrchr((char *)ifiles->orgfn, '/'))) { 705 ob = strtobuf((usch *)ifiles->orgfn, NULL); 706 ob->cptr = ob->buf + (nm - ifiles->orgfn) + 1; 707 strtobuf(fn, ob); 708 putob(ob, 0); 709 nm = xstrdup(ob->buf); 710 bufree(ob); 711 } else { 712 nm = xstrdup(fn); 713 } 714 if (pushfile(nm, nm, 0, NULL) == 0) { 715 free(fn-1); 716 goto okret; 717 } 718 } 719 if (fsrch(fn, 0, incdir[0])) 720 goto okret; 721 722 error("cannot find '%s'", fn); 723 /* error() do not return */ 724 725okret: 726 if (nm) 727 free(nm); 728 prtline(1); 729} 730 731void 732include_next(void) 733{ 734 struct iobuf *ob; 735 usch *nm; 736 737 if (flslvl) 738 return; 739 740 if ((ob = incfn()) == NULL) /* get include file name in obuf */ 741 error("bad #include_next"); 742 743 nm = xstrdup(ob->buf+1); 744 bufree(ob); 745 746 if (fsrch(nm, ifiles->idx, ifiles->incs) == 0) 747 error("cannot find '%s'", nm); 748 prtline(1); 749} 750 751/* 752 * Compare two replacement lists, taking in account comments etc. 753 */ 754static int 755cmprepl(const usch *o, const usch *n) 756{ 757 for (; *o; o++, n++) { 758 /* comment skip */ 759 if (*o == '/' && o[1] == '*') { 760 while (*o != '*' || o[1] != '/') 761 o++; 762 o += 2; 763 } 764 if (*n == '/' && n[1] == '*') { 765 while (*n != '*' || n[1] != '/') 766 n++; 767 n += 2; 768 } 769 while (*o == ' ' || *o == '\t') 770 o++; 771 while (*n == ' ' || *n == '\t') 772 n++; 773 if (*o != *n) 774 return 1; 775 } 776 return 0; 777} 778 779static int 780isell(void) 781{ 782 if (cinput() != '.' || cinput() != '.') 783 return 0; 784 return 1; 785} 786 787static int 788skipwscmnt(struct iobuf *ib) 789{ 790 /* XXX comment */ 791 return skipws(ib); 792} 793 794static int 795findarg(usch *s, usch **args, int narg) 796{ 797 int i; 798 799 for (i = 0; i < narg; i++) 800 if (strcmp((char *)s, (char *)args[i]) == 0) 801 return i; 802 return -1; 803} 804 805/* 806 * gcc extensions: 807 * #define e(a...) f(s, a) -> a works as __VA_ARGS__ 808 * #define e(fmt, ...) f(s, fmt , ##__VA_ARGS__) -> remove , if no args 809 */ 810void 811define(void) 812{ 813 struct symtab *np; 814 usch *args[MAXARGS+1], *sbeg, *bp, cc[2], *vararg; 815 int c, i, redef, oCflag, t; 816 int narg = -1; 817 int wascon; 818 819 if (flslvl) 820 return; 821 822 oCflag = Cflag, Cflag = 0; /* Ignore comments here */ 823 if (!ISID0(c = skipws(0))) 824 goto bad; 825 826 bp = heapid(c); 827 np = lookup(bp, ENTER); 828 if (np->value) { 829 stringbuf = bp; 830 redef = 1; 831 } else 832 redef = 0; 833 834 vararg = NULL; 835 sbeg = stringbuf++; 836 if ((c = cinput()) == '(') { 837 narg = 0; 838 /* function-like macros, deal with identifiers */ 839 c = skipws(0); 840 for (;;) { 841 switch (c) { 842 case ')': 843 break; 844 case '.': 845 if (isell() == 0 || (c = skipws(0)) != ')') 846 goto bad; 847 vararg = (usch *)"__VA_ARGS__"; 848 break; 849 default: 850 if (!ISID0(c)) 851 goto bad; 852 853 bp = heapid(c); 854 /* make sure there is no arg of same name */ 855 if (findarg(bp, args, narg) >= 0) 856 error("Duplicate parameter \"%s\"", bp); 857 if (narg == MAXARGS) 858 error("Too many macro args"); 859 args[narg++] = xstrdup(bp); 860 stringbuf = bp; 861 switch ((c = skipws(0))) { 862 case ',': break; 863 case ')': continue; 864 case '.': 865 if (isell() == 0 || skipws(0) != ')') 866 goto bad; 867 vararg = args[--narg]; 868 c = ')'; 869 continue; 870 default: 871 goto bad; 872 } 873 c = skipws(0); 874 } 875 if (c == ')') 876 break; 877 } 878 c = skipws(0); 879 } else if (c == '\n') { 880 /* #define foo */ 881 ; 882 } else if (c == 0) { 883 prem(); 884 } else if (!ISWS(c)) 885 goto bad; 886 887 Cflag = oCflag; /* Enable comments again */ 888 889 if (vararg) 890 stringbuf++; 891 892 if (ISWS(c)) 893 c = skipwscmnt(0); 894 895#define DELEWS() while (stringbuf > sbeg+1+(vararg!=NULL) && ISWS(stringbuf[-1])) stringbuf-- 896 897 /* parse replacement-list, substituting arguments */ 898 wascon = 0; 899 while (c != '\n') { 900 cc[0] = c, cc[1] = inc2(); 901 t = getyp(cc); 902 cunput(cc[1]); 903 904 switch (t) { 905 case ' ': 906 case '\t': 907 savch(' '); /* save only one space */ 908 while ((c = cinput()) == ' ' || c == '\t') 909 ; 910 continue; 911 912 case '#': 913 if (cc[1] == '#') { 914 /* concat op */ 915 (void)cinput(); /* eat # */ 916 DELEWS(); 917 savch(CONC); 918 if (ISID0(c = skipws(0)) && narg >= 0) 919 wascon = 1; 920 if (c == '\n') 921 goto bad; /* 6.10.3.3 p1 */ 922 continue; 923 } 924 925 if (narg < 0) { 926 /* no meaning in object-type macro */ 927 savch('#'); 928 break; 929 } 930 931 /* remove spaces between # and arg */ 932 savch(SNUFF); 933 c = skipws(0); /* whitespace, ignore */ 934 if (!ISID0(c)) 935 goto bad; 936 bp = heapid(c); 937 if (vararg && strcmp((char *)bp, (char *)vararg) == 0) { 938 stringbuf = bp; 939 savch(WARN); 940 savch(VARG); 941 savch(SNUFF); 942 break; 943 944 } 945 if ((i = findarg(bp, args, narg)) < 0) 946 goto bad; 947 stringbuf = bp; 948 savch(WARN); 949 savch(i); 950 savch(SNUFF); 951 break; 952 953 case NUMBER: 954 c = fastnum(c, savch); 955 continue; 956 957 case STRING: 958 if (c == 'L' || c == 'u' || c == 'U') { 959 savch(c); 960 if ((c = cinput()) == '8') { 961 savch(c); 962 c = cinput(); 963 } 964 } 965 if (tflag) 966 savch(c); 967 else 968 faststr(c, savch); 969 break; 970 971 case IDENT: 972 bp = heapid(c); 973 stringbuf--; /* remove \0 */ 974 if (narg < 0) 975 break; /* keep on heap */ 976 if (vararg && strcmp((char *)bp, (char *)vararg) == 0) { 977 stringbuf = bp; 978 savch(WARN); 979 savch(wascon ? GCCARG : VARG); 980 break; 981 } 982 983 /* check if its an argument */ 984 if ((i = findarg(bp, args, narg)) < 0) 985 break; 986 stringbuf = bp; 987 savch(WARN); 988 savch(i); 989 break; 990 991 case 0: 992 goto bad; 993 994 default: 995 savch(c); 996 break; 997 } 998 wascon = 0; 999 c = cinput(); 1000 } 1001 cunput(c); 1002 /* remove trailing whitespace */ 1003 DELEWS(); 1004 1005 if (sbeg[1+(vararg != 0)] == CONC) 1006 goto bad; /* 6.10.3.3 p1 */ 1007 1008 if (vararg) { 1009 sbeg[0] = VARG; 1010 sbeg[1] = narg; 1011 } else 1012 sbeg[0] = (narg < 0 ? OBJCT : narg); 1013 savch(0); 1014 1015 if (redef && ifiles->idx != SYSINC) { 1016 if (cmprepl(np->value, sbeg)) { /* not equal */ 1017 np->value = sbeg; 1018 warning("%s redefined (previously defined at \"%s\" line %d)", 1019 np->namep, np->file, np->line); 1020 } else 1021 stringbuf = sbeg; /* forget this space */ 1022 } else 1023 np->value = sbeg; 1024 1025#ifdef PCC_DEBUG 1026 if (dflag) { 1027 const usch *w = np->value; 1028 1029 printf("!define %s: ", np->namep); 1030 if (*w == OBJCT) 1031 printf("[object]"); 1032 else if (*w == VARG) 1033 printf("[VARG%d]", *++w); 1034 else 1035 printf("[%d]", *w); 1036 putchar('\''); 1037 prrep(++w); 1038 printf("\'\n"); 1039 } 1040#endif 1041 for (i = 0; i < narg; i++) 1042 free(args[i]); 1043 return; 1044 1045bad: error("bad #define"); 1046} 1047 1048void 1049warning(const char *fmt, ...) 1050{ 1051 va_list ap; 1052 1053 if (ifiles != NULL) 1054 fprintf(stderr, "%s:%d: warning: ", 1055 ifiles->fname, ifiles->lineno); 1056 1057 va_start(ap,fmt); 1058 vfprintf(stderr, fmt, ap); 1059 va_end(ap); 1060 fputc('\n', stderr); 1061 1062 warnings++; 1063} 1064 1065void 1066error(const char *fmt, ...) 1067{ 1068 va_list ap; 1069 1070 if (ifiles != NULL) 1071 fprintf(stderr, "%s:%d: error: ", 1072 ifiles->fname, ifiles->lineno); 1073 1074 va_start(ap, fmt); 1075 vfprintf(stderr, fmt, ap); 1076 va_end(ap); 1077 fputc('\n', stderr); 1078 exit(1); 1079} 1080 1081/* 1082 * store a character into the "define" buffer. 1083 */ 1084void 1085savch(int c) 1086{ 1087 if (stringbuf >= &sbf[SBSIZE]) 1088 error("out of macro space!"); 1089 1090 *stringbuf++ = (usch)c; 1091} 1092 1093static int 1094pragwin(struct iobuf *ib) 1095{ 1096 return ib ? *ib->cptr++ : cinput(); 1097} 1098 1099static int 1100skipws(struct iobuf *ib) 1101{ 1102 int t; 1103 1104 while ((t = pragwin(ib)) == ' ' || t == '\t') 1105 ; 1106 return t; 1107} 1108 1109/* 1110 * convert _Pragma() to #pragma for output. 1111 * Syntax is already correct. 1112 */ 1113static void 1114pragoper(struct iobuf *ib) 1115{ 1116 int t; 1117 usch *bp = stringbuf; 1118 1119 if (skipws(ib) != '(' || ((t = skipws(ib)) != '\"' && t != 'L')) 1120 goto err; 1121 if (t == 'L' && (t = pragwin(ib)) != '\"') 1122 goto err; 1123 savstr((const usch *)"\n#pragma "); 1124 while ((t = pragwin(ib)) != '\"') { 1125 if (t == BLKID) { 1126 pragwin(ib); 1127 continue; 1128 } 1129 if (t == '\"') 1130 continue; 1131 if (t == '\\') { 1132 if ((t = pragwin(ib)) != '\"' && t != '\\') 1133 savch('\\'); 1134 } 1135 savch(t); 1136 } 1137 sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname); 1138 putstr(bp); 1139 stringbuf = bp; 1140 if (skipws(ib) == ')') 1141 return; 1142 1143err: error("_Pragma() syntax error"); 1144} 1145 1146static int 1147expok(struct symtab *sp, int l) 1148{ 1149 struct blocker *w; 1150 1151 if (l == 0) 1152 return 1; 1153#ifdef PCC_DEBUG 1154if (dflag) { printf("expok blocked: "); for (w = blkidx[l]; w; w = w->next) printf("%s ", w->sp->namep); printf("\n"); } 1155#endif 1156 w = blkidx[l]; 1157 while (w) { 1158 if (w->sp == sp) 1159 return 0; 1160 w = w->next; 1161 } 1162 return 1; 1163} 1164 1165static int 1166expokb(struct symtab *sp, struct blocker *bl) 1167{ 1168 struct blocker *w; 1169 1170 if (bl == 0) 1171 return 1; 1172#ifdef PCC_DEBUG 1173if (dflag) { printf("expokb blocked: "); for (w = bl; w; w = w->next) printf("%s ", w->sp->namep); printf("\n"); } 1174#endif 1175 w = bl; 1176 while (w) { 1177 if (w->sp == sp) 1178 return 0; 1179 w = w->next; 1180 } 1181 return 1; 1182} 1183 1184static struct blocker * 1185blkget(struct symtab *sp, struct blocker *obl) 1186{ 1187 struct blocker *bl = calloc(sizeof(*obl), 1); 1188 1189 bl->sp = sp; 1190 bl->next = obl; 1191 return bl; 1192} 1193 1194static int 1195blkix(struct blocker *obl) 1196{ 1197 if (blkidp > 1 && blkidx[blkidp-1] == obl) 1198 return blkidp-1; 1199 if (blkidp == RECMAX) 1200 error("blkix"); 1201 blkidx[blkidp] = obl; 1202 return blkidp++; 1203} 1204 1205static struct blocker * 1206mergeadd(struct blocker *bl, int m) 1207{ 1208 struct blocker *w, *ww; 1209 1210 DPRINT(("mergeadd: %p %d\n", bl, m)); 1211 if (bl == 0) 1212 return blkidx[m]; 1213 if (m == 0) 1214 return bl; 1215 1216 blkidx[blkidp] = bl; 1217 for (w = blkidx[m]; w; w = w->next) { 1218 ww = calloc(sizeof(*w), 1); 1219 ww->sp = w->sp; 1220 ww->next = blkidx[blkidp]; 1221 blkidx[blkidp] = ww; 1222 } 1223 DPRINT(("mergeadd return: %d ", blkidp)); 1224#ifdef PCC_DEBUG 1225 if (dflag) { 1226 for (w = blkidx[blkidp]; w; w = w->next) 1227 printf("%s ", w->sp->namep); 1228 printf("\n"); 1229 } 1230#endif 1231 return blkidx[blkidp++]; 1232} 1233 1234static void 1235storeblk(int l, struct iobuf *ob) 1236{ 1237 DPRINT(("storeblk: %d\n", l)); 1238 putob(ob, BLKID); 1239 putob(ob, l); 1240} 1241 1242/* 1243 * Save filename on heap (with escaped chars). 1244 */ 1245static usch * 1246unfname(void) 1247{ 1248 usch *sb = stringbuf; 1249 const usch *bp = ifiles->fname; 1250 1251 savch('\"'); 1252 for (; *bp; bp++) { 1253 if (*bp == '\"' || *bp == '\'' || *bp == '\\') 1254 savch('\\'); 1255 savch(*bp); 1256 } 1257 savch('\"'); 1258 *stringbuf = 0; 1259 return sb; 1260} 1261 1262/* 1263 * Version of fastnum that reads from a string and saves in ob. 1264 * We know that it is a number before calling this routine. 1265 */ 1266static usch * 1267fstrnum(usch *s, struct iobuf *ob) 1268{ 1269 if (*s == '.') { 1270 /* not digit, dot. Next will be digit */ 1271 putob(ob, *s++); 1272 } 1273 for (;;) { 1274 putob(ob, *s++); 1275 if ((spechr[*s] & C_EP)) { 1276 if (s[1] != '-' && s[1] != '+') 1277 break; 1278 putob(ob, *s++); 1279 } else if ((*s != '.') && ((spechr[*s] & C_ID) == 0)) 1280 break; 1281 } 1282 return s; 1283} 1284 1285/* 1286 * get a string or character constant. 1287 * similar to faststr. 1288 */ 1289static usch * 1290fstrstr(usch *s, struct iobuf *ob) 1291{ 1292 int ch; 1293 1294 if (*s == 'L' || *s == 'U' || *s == 'u') 1295 putob(ob, *s++); 1296 if (*s == '8') 1297 putob(ob, *s++); 1298 ch = *s; 1299 putob(ob, *s++); 1300 while (*s != ch) { 1301 if (*s == '\\') 1302 putob(ob, *s++); 1303 putob(ob, *s++); 1304 } 1305 putob(ob, *s++); 1306 return s; 1307} 1308 1309/* 1310 * Save standard comments if found. 1311 */ 1312static usch * 1313fcmnt(usch *s, struct iobuf *ob) 1314{ 1315 putob(ob, *s++); /* / */ 1316 putob(ob, *s++); /* * */ 1317 for (;;s++) { 1318 putob(ob, *s); 1319 if (s[-1] == '*' && *s == '/') 1320 break; 1321 } 1322 return s+1; 1323} 1324 1325static int 1326getyp(usch *s) 1327{ 1328 1329 if (ISID0(*s)) return IDENT; 1330 if ((*s == 'L' || *s == 'U' || *s == 'u') && 1331 (s[1] == '\'' || s[1] == '\"')) return STRING; 1332 if (s[0] == 'u' && s[1] == 'U' && s[2] == '\"') return STRING; 1333 if (s[0] == '\'' || s[0] == '\"') return STRING; 1334 if (spechr[*s] & C_DIGIT) return NUMBER; 1335 if (*s == '.' && (spechr[s[1]] & C_DIGIT)) return NUMBER; 1336 if (*s == '/' && (s[1] == '/' || s[1] == '*')) return CMNT; 1337 return *s; 1338 1339} 1340 1341/* 1342 * Check ib and print out the symbols there. 1343 * If expandable symbols found recurse and expand them. 1344 * If last identifier on the input list is expandable return it. 1345 * Expect ib to be zero-terminated. 1346 */ 1347static struct symtab * 1348loopover(struct iobuf *ib) 1349{ 1350 struct iobuf *xb, *xob; 1351 struct symtab *sp; 1352 usch *cp; 1353 int l, c, t; 1354 1355 ib->cptr = ib->buf; /* start from beginning */ 1356#ifdef PCC_DEBUG 1357 if (dflag) { 1358 printf("loopover: '"); 1359 prline(ib->cptr); 1360 printf("'\n"); 1361 } 1362#endif 1363 1364 xb = getobuf(); 1365 while ((c = *ib->cptr)) { 1366 switch (t = getyp(ib->cptr)) { 1367 case CMNT: 1368 xb->cptr = xb->buf; 1369 ib->cptr = fcmnt(ib->cptr, xb); 1370 *xb->cptr = 0; 1371 savstr(xb->buf); 1372 continue; 1373 case NUMBER: 1374 xb->cptr = xb->buf; 1375 ib->cptr = fstrnum(ib->cptr, xb); 1376 *xb->cptr = 0; 1377 savstr(xb->buf); 1378 continue; 1379 case STRING: 1380 xb->cptr = xb->buf; 1381 ib->cptr = fstrstr(ib->cptr,xb); 1382 *xb->cptr = 0; 1383 for (cp = xb->buf; *cp; cp++) { 1384 if (*cp <= BLKID) { 1385 if (*cp == BLKID) 1386 cp++; 1387 continue; 1388 } 1389 savch(*cp); 1390 } 1391 continue; 1392 case BLKID: 1393 l = ib->cptr[1]; 1394 ib->cptr+=2; 1395 /* FALLTHROUGH */ 1396 case IDENT: 1397 if (t != BLKID) 1398 l = 0; 1399 /* 1400 * Tricky: if this is the last identifier 1401 * in the expanded list, and it is defined 1402 * as a function-like macro, then push it 1403 * back on the input stream and let fastscan 1404 * handle it as a new macro. 1405 * BUT: if this macro is blocked then this 1406 * should not be done. 1407 */ 1408 for (cp = ib->cptr; ISID(*ib->cptr); ib->cptr++) 1409 ; 1410 if ((sp = lookup(cp, FIND)) == NULL) { 1411sstr: for (; cp < ib->cptr; cp++) 1412 savch(*cp); 1413 continue; 1414 } 1415 if (expok(sp, l) == 0) { 1416 /* blocked */ 1417 goto sstr; 1418 } else { 1419 if (*sp->value != OBJCT) { 1420 cp = ib->cptr; 1421 while (ISWS(*ib->cptr)) 1422 ib->cptr++; 1423 if (*ib->cptr == 0) { 1424 bufree(xb); 1425 return sp; 1426 } 1427 ib->cptr = cp; 1428 } 1429newmac: if ((xob = submac(sp, 1, ib, NULL)) == NULL) { 1430 savstr(sp->namep); 1431 } else { 1432 sp = loopover(xob); 1433 bufree(xob); 1434 if (sp != NULL) 1435 goto newmac; 1436 } 1437 } 1438 continue; 1439 default: 1440 savch(c); 1441 } 1442 1443 ib->cptr++; 1444 } 1445 1446 bufree(xb); 1447 DPRINT(("loopover return 0\n")); 1448 return 0; 1449} 1450 1451/* 1452 * Handle defined macro keywords found on input stream. 1453 * When finished print out the full expanded line. 1454 * Input here is from the lex buffer. 1455 * Return 1 if success, 0 otherwise. fastscan restores stringbuf. 1456 * Scanned data is stored on heap. Last scan prints out the buffer. 1457 */ 1458int 1459kfind(struct symtab *sp) 1460{ 1461 extern int inexpr; 1462 struct blocker *bl; 1463 struct iobuf *ib, *ob; 1464 const usch *argary[MAXARGS+1], *sbp; 1465 int c, n = 0; 1466 1467 blkidp = 1; 1468 sbp = stringbuf; 1469 DPRINT(("%d:enter kfind(%s)\n",0,sp->namep)); 1470 switch (*sp->value) { 1471 case FILLOC: 1472 unfname(); 1473 return 1; 1474 1475 case LINLOC: 1476 sheap("%d", ifiles->lineno); 1477 return 1; 1478 1479 case PRAGLOC: 1480 pragoper(NULL); 1481 return 1; 1482 1483 case DEFLOC: 1484 case OBJCT: 1485 bl = blkget(sp, NULL); 1486 ib = mkrobuf(sp->value+1); 1487 ob = getobuf(); 1488 ob = exparg(1, ib, ob, bl); 1489 bufree(ib); 1490 break; 1491 1492 case CTRLOC: 1493 sheap("%d", counter++); 1494 return 1; 1495 1496 default: 1497 /* Search for '(' */ 1498 while (ISWSNL(c = cinput())) 1499 if (c == '\n') 1500 n++; 1501 if (c != '(') { 1502 if (inexpr == 0) 1503 putstr(sp->namep); 1504 if (n == 0) 1505 putch(' '); 1506 else for (ifiles->lineno += n; n; n--) 1507 putch('\n'); 1508 cunput(c); 1509 return 0; /* Failed */ 1510 } 1511 1512 /* fetch arguments */ 1513again: if (readargs1(sp, argary)) 1514 error("readargs"); 1515 1516 bl = blkget(sp, NULL); 1517 ib = subarg(sp, argary, 1, bl); 1518 ob = getobuf(); 1519 ob = exparg(1, ib, ob, bl); 1520 bufree(ib); 1521 break; 1522 } 1523 1524 /* 1525 * Loop over stringbuf, output the data and remove remaining 1526 * directives. Start with extracting the last keyword (if any). 1527 */ 1528 putob(ob, 0); /* XXX needed? */ 1529 1530 stringbuf = (usch *)sbp; /* XXX should check cleanup */ 1531 if ((sp = loopover(ob))) { 1532 /* Search for '(' */ 1533 while (ISWSNL(c = cinput())) 1534 if (c == '\n') 1535 n++; 1536 if (c == '(') { 1537 bufree(ob); 1538 goto again; 1539 } 1540 cunput(c); 1541 savstr(sp->namep); 1542 } 1543 bufree(ob); 1544 1545 for (ifiles->lineno += n; n; n--) 1546 savch('\n'); 1547 savch(0); 1548 stringbuf = (usch *)sbp; 1549 if (nbufused) 1550 error("lost buffer"); 1551 return 1; 1552} 1553 1554/* 1555 * Replace and push-back on input stream the eventual replaced macro. 1556 * The check for whether it can expand or not should already have been done. 1557 * Blocks for this identifier will be added via insblock() after expansion. 1558 * The same as kfind but read a string. 1559 */ 1560struct iobuf * 1561submac(struct symtab *sp, int lvl, struct iobuf *ib, struct blocker *obl) 1562{ 1563 struct blocker *bl; 1564 struct iobuf *ob; 1565 const usch *argary[MAXARGS+1]; 1566 usch *cp, *pr; 1567 1568 DPRINT(("%d:submac: trying '%s'\n", lvl, sp->namep)); 1569 switch (*sp->value) { 1570 case FILLOC: 1571 ob = strtobuf(unfname(), NULL); 1572 break; 1573 case LINLOC: 1574 ob = strtobuf(sheap("%d", ifiles->lineno), NULL); 1575 break; 1576 case PRAGLOC: 1577 pragoper(ib); 1578 ob = strtobuf((usch *)"", NULL); 1579 break; 1580 case OBJCT: 1581 bl = blkget(sp, obl); 1582 ib = mkrobuf(sp->value+1); 1583 ob = getobuf(); 1584 DPRINT(("%d:submac: calling exparg\n", lvl)); 1585 ob = exparg(lvl+1, ib, ob, bl); 1586 bufree(ib); 1587 DPRINT(("%d:submac: return exparg\n", lvl)); 1588 break; 1589 case CTRLOC: 1590 ob = strtobuf(sheap("%d", counter++), NULL); 1591 break; 1592 default: 1593 cp = ib->cptr; 1594 while (ISWSNL(*ib->cptr)) 1595 ib->cptr++; 1596 if (*ib->cptr != '(') { 1597 ib->cptr = cp; 1598 return 0; 1599 } 1600 cp = ib->cptr++; 1601 pr = stringbuf; 1602 if (readargs2(&ib->cptr, sp, argary)) { 1603 /* Bailed out in the middle of arg list */ 1604 ib->cptr = cp; /* XXX */ 1605 return 0; 1606 } 1607 bl = blkget(sp, obl); 1608 ib = subarg(sp, argary, lvl+1, bl); 1609 stringbuf = pr; 1610 1611 ob = getobuf(); 1612 DPRINT(("%d:submac(: calling exparg\n", lvl)); 1613 ob = exparg(lvl+1, ib, ob, bl); 1614 bufree(ib); 1615 DPRINT(("%d:submac(: return exparg\n", lvl)); 1616 break; 1617 } 1618 putob(ob, 0); 1619 ob->cptr--; 1620 1621 return ob; 1622} 1623 1624static int 1625isdir(void) 1626{ 1627 usch ch; 1628 1629 while ((ch = cinput()) == ' ' || ch == '\t') 1630 ; 1631 if (ch == '#') 1632 return 1; 1633 cunput(ch); 1634 return 0; 1635} 1636 1637/* 1638 * Deal with directives inside a macro. 1639 * Doing so is really ugly but gcc allows it, so... 1640 */ 1641static void 1642chkdir(void) 1643{ 1644 usch ch; 1645 1646 for (;;) { 1647 if (isdir()) { 1648#ifndef GCC_COMPAT 1649 warning("conditionals inside macro arg list"); 1650#endif 1651 ppdir(); 1652 } 1653 if (flslvl == 0) 1654 return; 1655 while ((ch = cinput()) != '\n') 1656 ; 1657 ifiles->lineno++; 1658 putch('\n'); 1659 } 1660} 1661 1662static int 1663ra1_wsnl(int sp) 1664{ 1665 int c; 1666 1667 while (ISWSNL(c = cinput())) { 1668 if (c == '\n') { 1669 putch('\n'); 1670 chkdir(); 1671 ifiles->lineno++; 1672 if (sp) savch(' '); 1673 } 1674 } 1675 return c; 1676} 1677 1678/* 1679 * Read arguments and put in argument array. 1680 * If EOF is encountered return 1, otherwise 0. 1681 */ 1682int 1683readargs1(struct symtab *sp, const usch **args) 1684{ 1685 const usch *vp = sp->value; 1686 int c, i, plev, narg, ellips = 0; 1687 1688 DPRINT(("readargs1\n")); 1689 narg = *vp++; 1690 if (narg == VARG) { 1691 narg = *vp++; 1692 ellips = 1; 1693 } 1694#ifdef PCC_DEBUG 1695 if (dflag > 1) { 1696 printf("narg %d varg %d: ", narg, ellips); 1697 prrep(vp); 1698 printf("\n"); 1699 } 1700#endif 1701 1702 /* 1703 * read arguments and store them on heap. 1704 */ 1705 c = '('; 1706 for (i = 0; i < narg && c != ')'; i++) { 1707 args[i] = stringbuf; 1708 plev = 0; 1709 1710 c = ra1_wsnl(0); 1711 for (;;) { 1712 if (plev == 0 && (c == ')' || c == ',')) 1713 break; 1714 if (c == '(') plev++; 1715 if (c == ')') plev--; 1716 if (c == 0) 1717 error("eof in macro"); 1718 else if (c == '/') Ccmnt(savch); 1719 else if (c == '\"' || c == '\'') faststr(c, savch); 1720 else if (ISID0(c)) { 1721 usch *bp = stringbuf; 1722 do { 1723 savch(c); 1724 } while ((spechr[c = cinput()] & C_ID)); 1725 if ((sp = lookup(bp, FIND)) != NULL) { 1726 if (sp == linloc) { 1727 stringbuf = bp; 1728 sheap("%d", ifiles->lineno); 1729 } else if (sp == ctrloc) { 1730 stringbuf = bp; 1731 sheap("%d", counter++); 1732 } 1733 } 1734 cunput(c); 1735 } else 1736 savch(c); 1737 if ((c = cinput()) == '\n') { 1738 chkdir(); 1739 ifiles->lineno++, putch(c), c = ' '; 1740 } 1741 } 1742 1743 while (args[i] < stringbuf && ISWSNL(stringbuf[-1])) 1744 stringbuf--; 1745 savch('\0'); 1746#ifdef PCC_DEBUG 1747 if (dflag) { 1748 printf("readargs: save arg %d '", i); 1749 prline(args[i]); 1750 printf("'\n"); 1751 } 1752#endif 1753 } 1754 1755 /* Handle varargs readin */ 1756 if (ellips) 1757 args[i] = (const usch *)""; 1758 if (ellips && c != ')') { 1759 args[i] = stringbuf; 1760 plev = 0; 1761 c = ra1_wsnl(0); 1762 for (;;) { 1763 if (plev == 0 && c == ')') 1764 break; 1765 if (c == '(') plev++; 1766 if (c == ')') plev--; 1767 if (c == '\"' || c == '\'') faststr(c, savch); 1768 else 1769 savch(c); 1770 if ((c = cinput()) == '\n') 1771 ifiles->lineno++, c = ' '; 1772 } 1773 while (args[i] < stringbuf && ISWSNL(stringbuf[-1])) 1774 stringbuf--; 1775 savch('\0'); 1776#ifdef PCC_DEBUG 1777 if (dflag) { 1778 printf("readargs: vararg arg %d '", i); 1779 prline(args[i]); 1780 printf("'\n"); 1781 } 1782#endif 1783 1784 } 1785 if (narg == 0 && ellips == 0) 1786 c = ra1_wsnl(0); 1787 1788 if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) 1789 error("wrong arg count"); 1790 return 0; 1791} 1792 1793static usch *raptr; 1794static int 1795raread(void) 1796{ 1797 int rv; 1798 1799 if (raptr) { 1800 if ((rv = *raptr)) 1801 raptr++; 1802 } else 1803 rv = cinput(); 1804 return rv; 1805} 1806 1807 1808/* 1809 * Read arguments and put in argument array. 1810 * If EOF is encountered return 1, otherwise 0. 1811 */ 1812int 1813readargs2(usch **inp, struct symtab *sp, const usch **args) 1814{ 1815 const usch *vp = sp->value; 1816 usch *bp; 1817 int c, i, plev, narg, ellips = 0; 1818 1819 DPRINT(("readargs2 %s '", sp->namep)); 1820#ifdef PCC_DEBUG 1821 if (dflag && inp) { 1822 prline(*inp); 1823 printf("'\n"); 1824 } 1825#endif 1826 raptr = inp ? *inp : 0; 1827 narg = *vp++; 1828 if (narg == VARG) { 1829 narg = *vp++; 1830 ellips = 1; 1831 } 1832#ifdef PCC_DEBUG 1833 if (dflag > 1) { 1834 prrep(vp); 1835 printf("\n"); 1836 } 1837#endif 1838 1839 1840 /* 1841 * read arguments and store them on heap. 1842 */ 1843 c = '('; 1844 for (i = 0; i < narg && c != ')'; i++) { 1845 args[i] = stringbuf; 1846 plev = 0; 1847 1848 while ((c = raread()) == ' ' || c == '\t') 1849 ; 1850 for (;;) { 1851 if (plev == 0 && (c == ')' || c == ',')) 1852 break; 1853 if (c == '(') plev++; 1854 if (c == ')') plev--; 1855 if (c == 0) { 1856 if (raptr) { 1857 *inp = raptr; 1858 raptr = 0; 1859 } else 1860 error("eof in macro"); 1861 } else if (c == BLKID) { 1862 savch(c), savch(raread()); 1863 } else if (c == '/') { 1864 if ((c = raread()) == '*') 1865 error("FIXME ccmnt"); 1866 savch('/'); 1867 continue; 1868 } else if (c == '\"' || c == '\'') { 1869 if (raptr) { 1870 struct iobuf *xob = getobuf(); 1871 raptr = fstrstr(raptr-1, xob); 1872 *xob->cptr = 0; 1873 savstr(xob->buf); 1874 bufree(xob); 1875 } else 1876 faststr(c, savch); 1877 } else if (ISID0(c)) { 1878 bp = stringbuf; 1879 do { 1880 savch(c); 1881 } while (ISID(c = raread())); 1882 *stringbuf = 0; 1883 if ((sp = lookup(bp, FIND)) && (sp == linloc)) { 1884 stringbuf = bp; 1885 sheap("%d", ifiles->lineno); 1886 } 1887 continue; 1888 } else 1889 savch(c); 1890 c = raread(); 1891 } 1892 1893 while (args[i] < stringbuf && ISWSNL(stringbuf[-1])) 1894 stringbuf--; 1895 savch('\0'); 1896#ifdef PCC_DEBUG 1897 if (dflag) { 1898 printf("readargs2: save arg %d '", i); 1899 prline(args[i]); 1900 printf("'\n"); 1901 } 1902#endif 1903 } 1904 1905 /* Handle varargs readin */ 1906 if (ellips) 1907 args[i] = (const usch *)""; 1908 if (ellips && c != ')') { 1909 args[i] = stringbuf; 1910 plev = 0; 1911 while ((c = raread()) == ' ' || c == '\t') 1912 ; 1913 for (;;) { 1914 if (plev == 0 && c == ')') 1915 break; 1916 if (c == '(') plev++; 1917 if (c == ')') plev--; 1918 if (c == '\"' || c == '\'') { 1919 if (raptr) { 1920 struct iobuf *xob = getobuf(); 1921 raptr = fstrstr(raptr-1, xob); 1922 *xob->cptr = 0; 1923 savstr(xob->buf); 1924 bufree(xob); 1925 } else 1926 faststr(c, savch); 1927 } else 1928 savch(c); 1929 c = raread(); 1930 } 1931 while (args[i] < stringbuf && ISWSNL(stringbuf[-1])) 1932 stringbuf--; 1933 savch('\0'); 1934 1935 } 1936 if (narg == 0 && ellips == 0) { 1937 while ((c = raread()) == ' ' || c == '\t') 1938 ; 1939 } 1940 1941 if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) 1942 error("wrong arg count"); 1943 if (raptr) 1944 *inp = raptr; 1945 return 0; 1946} 1947 1948/* 1949 * expand a function-like macro. 1950 * vp points to end of replacement-list 1951 * reads function arguments from input stream. 1952 * result is pushed-back for more scanning. 1953 */ 1954struct iobuf * 1955subarg(struct symtab *nl, const usch **args, int lvl, struct blocker *bl) 1956{ 1957 struct blocker *w; 1958 struct iobuf *ob, *cb, *nb; 1959 int narg, instr, snuff; 1960 const usch *sp, *bp, *ap, *vp, *tp; 1961 1962 DPRINT(("%d:subarg '%s'\n", lvl, nl->namep)); 1963 ob = getobuf(); 1964 vp = nl->value; 1965 narg = *vp++; 1966 if (narg == VARG) 1967 narg = *vp++; 1968 1969 sp = vp; 1970 instr = snuff = 0; 1971#ifdef PCC_DEBUG 1972 if (dflag>1) { 1973 printf("%d:subarg ARGlist for %s: '", lvl, nl->namep); 1974 prrep(vp); 1975 printf("' "); 1976 for (w = bl; w; w = w->next) 1977 printf("%s ", w->sp->namep); 1978 printf("\n"); 1979 } 1980#endif 1981 1982 /* 1983 * walk forward over replacement-list while replacing 1984 * arguments. Arguments are macro-expanded if required. 1985 */ 1986 while (*sp) { 1987 if (*sp == SNUFF) 1988 putob(ob, '\"'), snuff ^= 1; 1989 else if (*sp == CONC) 1990 ; 1991 else if (*sp == WARN) { 1992 1993 if (sp[1] == VARG) { 1994 bp = ap = args[narg]; 1995 sp++; 1996#ifdef GCC_COMPAT 1997 } else if (sp[1] == GCCARG) { 1998 /* XXX remove last , not add 0 */ 1999 ap = args[narg]; 2000 if (ap[0] == 0) 2001 ap = (const usch *)"0"; 2002 bp = ap; 2003 sp++; 2004#endif 2005 } else 2006 bp = ap = args[(int)*++sp]; 2007#ifdef PCC_DEBUG 2008 if (dflag>1){ 2009 printf("%d:subarg GOTwarn; arglist '", lvl); 2010 prline(bp); 2011 printf("'\n"); 2012 } 2013#endif 2014 if (sp[-2] != CONC && !snuff && sp[1] != CONC) { 2015 /* 2016 * Expand an argument; 6.10.3.1: 2017 * "A parameter in the replacement list, 2018 * is replaced by the corresponding argument 2019 * after all macros contained therein have 2020 * been expanded.". 2021 */ 2022 w = bl ? bl->next : NULL; 2023 cb = mkrobuf(bp); 2024 nb = getobuf(); 2025 DPRINT(("%d:subarg: calling exparg\n", lvl)); 2026 nb = exparg(lvl+1, cb, nb, w); 2027 DPRINT(("%d:subarg: return exparg\n", lvl)); 2028 bufree(cb); 2029 strtobuf(nb->buf, ob); 2030 bufree(nb); 2031 } else { 2032 while (*bp) { 2033 if (snuff && !instr && ISWS(*bp)) { 2034 while (ISWS(*bp)) 2035 bp++; 2036 putob(ob, ' '); 2037 } 2038 2039 if (snuff && 2040 (*bp == '\'' || *bp == '"')) { 2041 instr ^= 1; 2042 for (tp = bp - 1; *tp == '\\'; tp--) 2043 instr ^= 1; 2044 if (*bp == '"') 2045 putob(ob, '\\'); 2046 } 2047 if (snuff && instr && *bp == '\\') 2048 putob(ob, '\\'); 2049 putob(ob, *bp); 2050 bp++; 2051 } 2052 } 2053 } else if (ISID0(*sp)) { 2054 if (lookup(sp, FIND)) 2055 storeblk(blkix(bl), ob); 2056 while (ISID(*sp)) 2057 putob(ob, *sp++); 2058 sp--; 2059 } else 2060 putob(ob, *sp); 2061 sp++; 2062 } 2063 putob(ob, 0); 2064 ob->cptr = ob->buf; 2065 DPRINT(("%d:subarg retline %s\n", lvl, ob->buf)); 2066 return ob; 2067} 2068 2069/* 2070 * Do a (correct) expansion of a WARN-terminated buffer of tokens. 2071 * Data is read from the lex buffer, result on lex buffer, WARN-terminated. 2072 * Expansion blocking is not altered here unless when tokens are 2073 * concatenated, in which case they are removed. 2074 */ 2075struct iobuf * 2076exparg(int lvl, struct iobuf *ib, struct iobuf *ob, struct blocker *bl) 2077{ 2078 extern int inexpr; 2079 struct iobuf *nob; 2080 struct symtab *nl; 2081 int c, m; 2082 usch *cp, *bp, *sbp; 2083 2084 DPRINT(("%d:exparg: entry ib %s\n", lvl, ib->cptr)); 2085#ifdef PCC_DEBUG 2086 if (dflag > 1) { 2087 printf("exparg entry: full "); 2088 prline(ib->cptr); 2089 printf("\n"); 2090 } 2091#endif 2092 2093 while ((c = getyp(ib->cptr)) != 0) { 2094 ib->cptr++; 2095 2096 switch (c) { 2097 2098 case CMNT: 2099 ib->cptr = fcmnt(ib->cptr-1, ob); 2100 break; 2101 case NUMBER: 2102 ib->cptr = fstrnum(ib->cptr-1, ob); 2103 break; 2104 case STRING: 2105 ib->cptr = fstrstr(ib->cptr-1, ob); 2106 break; 2107 case BLKID: 2108 m = *ib->cptr++; 2109 ib->cptr++; 2110 /* FALLTHROUGH */ 2111 case IDENT: 2112 if (c != BLKID) 2113 m = 0; 2114 for (cp = ib->cptr-1; ISID(*cp); cp++) 2115 ; 2116#ifdef PCC_DEBUG 2117if (dflag) { printf("!! ident "); prline(ib->cptr-1); printf("\n"); } 2118#endif 2119 sbp = stringbuf; 2120 if (*cp == BLKID) { 2121 /* concatenation */ 2122 bp = stringbuf; 2123 for (cp = ib->cptr-1; 2124 ISID(*cp) || *cp == BLKID; cp++) { 2125 if (*cp == BLKID) { 2126 /* XXX add to block list */ 2127 cp++; 2128 } else 2129 savch(*cp); 2130 } 2131 ib->cptr = cp; 2132 cp = stringbuf; 2133 savch(0); 2134 } else { 2135 bp = ib->cptr-1; 2136 ib->cptr = cp; 2137 } 2138#ifdef PCC_DEBUG 2139if (dflag) { printf("!! ident2 "); prline(bp); printf("\n"); } 2140#endif 2141 if ((nl = lookup(bp, FIND)) == NULL) { 2142sstr: for (; bp < cp; bp++) 2143 putob(ob, *bp); 2144 stringbuf = sbp; 2145 break; 2146 } else if (inexpr && *nl->value == DEFLOC) { 2147 int gotlp = 0; 2148 while (ISWS(*ib->cptr)) ib->cptr++; 2149 if (*ib->cptr == '(') 2150 gotlp++, ib->cptr++; 2151 while (ISWS(*ib->cptr)) ib->cptr++; 2152 if (!ISID0(*ib->cptr)) 2153 error("bad defined"); 2154 putob(ob, lookup(ib->cptr, FIND) ? '1' : '0'); 2155 while (ISID(*ib->cptr)) ib->cptr++; 2156 while (ISWS(*ib->cptr)) ib->cptr++; 2157 if (gotlp && *ib->cptr != ')') 2158 error("bad defined"); 2159 ib->cptr++; 2160 break; 2161 } 2162 stringbuf = sbp; 2163 if (expokb(nl, bl) && expok(nl, m)) { 2164 if ((nob = submac(nl, lvl+1, ib, bl))) { 2165 if (nob->buf[0] == '-' || 2166 nob->buf[0] == '+') 2167 putob(ob, ' '); 2168 strtobuf(nob->buf, ob); 2169 if (ob->cptr[-1] == '-' || 2170 ob->cptr[-1] == '+') 2171 putob(ob, ' '); 2172 bufree(nob); 2173 } else { 2174 goto sblk; 2175 } 2176 } else { 2177 /* blocked */ 2178sblk: storeblk(blkix(mergeadd(bl, m)), ob); 2179 goto sstr; 2180 } 2181 break; 2182 2183 default: 2184 putob(ob, c); 2185 break; 2186 } 2187 } 2188 putob(ob, 0); 2189 ob->cptr--; 2190 DPRINT(("%d:exparg return: ob %s\n", lvl, ob->buf)); 2191#ifdef PCC_DEBUG 2192 if (dflag > 1) { 2193 printf("%d:exparg: full ", lvl); 2194 prline(ob->buf); 2195 printf("\n"); 2196 } 2197#endif 2198 return ob; 2199} 2200 2201#ifdef PCC_DEBUG 2202 2203static void 2204prrep(const usch *s) 2205{ 2206 while (*s) { 2207 switch (*s) { 2208 case WARN: 2209 if (s[1] == VARG) printf("<VARG>"); 2210 else if (s[1] == GCCARG) printf("<GCCARG>"); 2211 else printf("<ARG(%d)>", s[1]); 2212 s++; 2213 break; 2214 case CONC: printf("<CONC>"); break; 2215 case SNUFF: printf("<SNUFF>"); break; 2216 case BLKID: printf("<BLKID(%d)>",s[1]); s++; break; 2217 default: printf("%c", *s); break; 2218 } 2219 s++; 2220 } 2221} 2222 2223static void 2224prline(const usch *s) 2225{ 2226 while (*s) { 2227 switch (*s) { 2228 case BLKID: printf("<BLKID(%d)>", *++s); break; 2229 case WARN: printf("<WARN>"); break; 2230 case CONC: printf("<CONC>"); break; 2231 case SNUFF: printf("<SNUFF>"); break; 2232 case '\n': printf("<NL>"); break; 2233 default: 2234 if (*s > 0x7f) 2235 printf("<0x%x>", *s); 2236 else 2237 printf("%c", *s); 2238 break; 2239 } 2240 s++; 2241 } 2242} 2243#endif 2244 2245usch * 2246savstr(const usch *str) 2247{ 2248 usch *rv = stringbuf; 2249 2250 do { 2251 if (stringbuf >= &sbf[SBSIZE]) 2252 error("out of macro space!"); 2253 } while ((*stringbuf++ = *str++)); 2254 stringbuf--; 2255 return rv; 2256} 2257 2258void 2259putch(int ch) 2260{ 2261 if (Mflag) 2262 return; 2263 fputc(ch, stdout); 2264} 2265 2266void 2267putstr(const usch *s) 2268{ 2269 for (; *s; s++) { 2270 if (Mflag == 0) 2271 fputc(*s, stdout); 2272 } 2273} 2274 2275/* 2276 * convert a number to an ascii string. Store it on the heap. 2277 */ 2278static void 2279num2str(int num) 2280{ 2281 static usch buf[12]; 2282 usch *b = buf; 2283 int m = 0; 2284 2285 if (num < 0) 2286 num = -num, m = 1; 2287 do { 2288 *b++ = (usch)(num % 10 + '0'); 2289 num /= 10; 2290 } while (num); 2291 if (m) 2292 *b++ = '-'; 2293 while (b > buf) 2294 savch(*--b); 2295} 2296 2297/* 2298 * similar to sprintf, but only handles %c, %s and %d. 2299 * saves result on heap. 2300 */ 2301static void 2302vsheap(const char *fmt, va_list ap) 2303{ 2304 for (; *fmt; fmt++) { 2305 if (*fmt == '%') { 2306 fmt++; 2307 switch (*fmt) { 2308 case 's': 2309 savstr(va_arg(ap, usch *)); 2310 break; 2311 case 'd': 2312 num2str(va_arg(ap, int)); 2313 break; 2314 case 'c': 2315 savch(va_arg(ap, int)); 2316 break; 2317 default: 2318 error("bad sheap"); 2319 } 2320 } else 2321 savch(*fmt); 2322 } 2323 *stringbuf = 0; 2324} 2325 2326usch * 2327sheap(const char *fmt, ...) 2328{ 2329 va_list ap; 2330 usch *op = stringbuf; 2331 2332 va_start(ap, fmt); 2333 vsheap(fmt, ap); 2334 va_end(ap); 2335 2336 return op; 2337} 2338 2339static void 2340usage(void) 2341{ 2342 error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]"); 2343} 2344 2345#ifdef notyet 2346/* 2347 * Symbol table stuff. 2348 * The data structure used is a patricia tree implementation using only 2349 * bytes to store offsets. 2350 * The information stored is (lower address to higher): 2351 * 2352 * unsigned char bitno[2]; bit number in the string 2353 * unsigned char left[3]; offset from base to left element 2354 * unsigned char right[3]; offset from base to right element 2355 */ 2356#endif 2357 2358/* 2359 * This patricia implementation is more-or-less the same as 2360 * used in ccom for string matching. 2361 */ 2362struct tree { 2363 int bitno; 2364 struct tree *lr[2]; 2365}; 2366 2367#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF)) 2368#define LEFT_IS_LEAF 0x80000000 2369#define RIGHT_IS_LEAF 0x40000000 2370#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0) 2371#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0) 2372#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1 2373#define CHECKBITS 8 2374 2375static struct tree *sympole; 2376static int numsyms; 2377 2378static struct tree * 2379gtree(void) 2380{ 2381 static int ntrees; 2382 static struct tree *tp; 2383 2384 if (ntrees == 0) { 2385 tp = xmalloc(BUFSIZ); 2386 ntrees = BUFSIZ/sizeof(*tp); 2387 } 2388 return &tp[--ntrees]; 2389} 2390 2391/* 2392 * Allocate a symtab struct and store the string. 2393 */ 2394static struct symtab * 2395getsymtab(const usch *str) 2396{ 2397 static int nsyms; 2398 static struct symtab *spp; 2399 struct symtab *sp; 2400 2401 if (nsyms == 0) { 2402 spp = xmalloc(BUFSIZ); 2403 nsyms = BUFSIZ/sizeof(*sp); 2404 } 2405 sp = &spp[--nsyms]; 2406 2407 sp->namep = str; 2408 sp->value = NULL; 2409 sp->file = ifiles ? ifiles->orgfn : (const usch *)"<initial>"; 2410 sp->line = ifiles ? ifiles->lineno : 0; 2411 return sp; 2412} 2413 2414/* 2415 * Do symbol lookup in a patricia tree. 2416 * Only do full string matching, no pointer optimisations. 2417 */ 2418struct symtab * 2419lookup(const usch *key, int enterf) 2420{ 2421 struct symtab *sp; 2422 struct tree *w, *new, *last; 2423 int len, cix, bit, fbit, svbit, ix, bitno; 2424 const usch *k, *m; 2425 2426 /* Count full string length */ 2427 for (k = key, len = 0; ISID(*k) & C_ID; k++, len++) 2428 ; 2429 2430 switch (numsyms) { 2431 case 0: /* no symbols yet */ 2432 if (enterf != ENTER) 2433 return NULL; 2434 sympole = (struct tree *)getsymtab(key); 2435 numsyms++; 2436 return (struct symtab *)sympole; 2437 2438 case 1: 2439 w = sympole; 2440 svbit = 0; /* XXX gcc */ 2441 break; 2442 2443 default: 2444 w = sympole; 2445 bitno = len * CHECKBITS; 2446 for (;;) { 2447 bit = BITNO(w->bitno); 2448 fbit = bit >= bitno ? 0 : P_BIT(key, bit); 2449 svbit = fbit ? IS_RIGHT_LEAF(w->bitno) : 2450 IS_LEFT_LEAF(w->bitno); 2451 w = w->lr[fbit]; 2452 if (svbit) 2453 break; 2454 } 2455 } 2456 2457 sp = (struct symtab *)w; 2458 2459 m = sp->namep; 2460 k = key; 2461 2462 /* Check for correct string and return */ 2463 for (cix = 0; *m && ISID(*k) && *m == *k; m++, k++, cix += CHECKBITS) 2464 ; 2465 if (*m == 0 && ISID(*k) == 0) { 2466 if (enterf != ENTER && sp->value == NULL) 2467 return NULL; 2468 return sp; 2469 } 2470 2471 if (enterf != ENTER) 2472 return NULL; /* no string found and do not enter */ 2473 2474 ix = *m ^ *k; 2475 while ((ix & 1) == 0) 2476 ix >>= 1, cix++; 2477 2478 /* Create new node */ 2479 new = gtree(); 2480 bit = P_BIT(key, cix); 2481 new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); 2482 new->lr[bit] = (struct tree *)getsymtab(key); 2483 2484 if (numsyms++ == 1) { 2485 new->lr[!bit] = sympole; 2486 new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); 2487 sympole = new; 2488 return (struct symtab *)new->lr[bit]; 2489 } 2490 2491 w = sympole; 2492 last = NULL; 2493 for (;;) { 2494 fbit = w->bitno; 2495 bitno = BITNO(w->bitno); 2496 if (bitno == cix) 2497 error("bitno == cix"); 2498 if (bitno > cix) 2499 break; 2500 svbit = P_BIT(key, bitno); 2501 last = w; 2502 w = w->lr[svbit]; 2503 if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF)) 2504 break; 2505 } 2506 2507 new->lr[!bit] = w; 2508 if (last == NULL) { 2509 sympole = new; 2510 } else { 2511 last->lr[svbit] = new; 2512 last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); 2513 } 2514 if (bitno < cix) 2515 new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); 2516 return (struct symtab *)new->lr[bit]; 2517} 2518 2519static void * 2520xmalloc(int sz) 2521{ 2522 usch *rv; 2523 2524 if ((rv = (void *)malloc(sz)) == NULL) 2525 error("xmalloc: out of mem"); 2526 return rv; 2527} 2528 2529static void * 2530xrealloc(void *p, int sz) 2531{ 2532 usch *rv; 2533 2534 if ((rv = (void *)realloc(p, sz)) == NULL) 2535 error("xrealloc: out of mem"); 2536 return rv; 2537} 2538 2539static usch * 2540xstrdup(const usch *str) 2541{ 2542 usch *rv; 2543 2544 if ((rv = (usch *)strdup((const char *)str)) == NULL) 2545 error("xstrdup: out of mem"); 2546 return rv; 2547} 2548