1139804Simp/* Id: cpp.c,v 1.252 2016/02/06 09:39:21 ragge Exp */ 2185435Sbz/* $NetBSD: cpp.c,v 1.4 2016/02/09 20:37:32 plunky Exp $ */ 3185435Sbz 4191673Sjamie/* 5185435Sbz * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). 6190466Sjamie * All rights reserved. 7185404Sbz * 8185404Sbz * Redistribution and use in source and binary forms, with or without 9185404Sbz * modification, are permitted provided that the following conditions 10185404Sbz * are met: 11185404Sbz * 1. Redistributions of source code must retain the above copyright 12185404Sbz * notice, this list of conditions and the following disclaimer. 13185404Sbz * 2. Redistributions in binary form must reproduce the above copyright 14185404Sbz * notice, this list of conditions and the following disclaimer in the 15185404Sbz * documentation and/or other materials provided with the distribution. 16185404Sbz * 17185404Sbz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18185404Sbz * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19185404Sbz * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20185404Sbz * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21185404Sbz * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22185404Sbz * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23185404Sbz * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24185404Sbz * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25185404Sbz * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26185404Sbz * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2746197Sphk */ 2846155Sphk 29116182Sobrien/* 30116182Sobrien * The C preprocessor. 31116182Sobrien * This code originates from the V6 preprocessor with some additions 32193066Sjamie * from V7 cpp, and at last ansi/c99 support. 33185435Sbz * 34185435Sbz * - kfind() expands the input buffer onto XXX 35185435Sbz * - exparg() expand one buffer into another. 36131177Spjd * Recurses into submac() for fun-like macros. 3746155Sphk * - submac() replaces the given macro. 3846155Sphk * Recurses into subarg() for fun-like macros. 3946155Sphk * - subarg() expands fun-like macros. 4046155Sphk * Create strings, concats args, recurses into exparg. 4146155Sphk */ 4246155Sphk 4346155Sphk#include "config.h" 44192895Sjamie 45164032Srwatson#include <sys/stat.h> 4646155Sphk 47124882Srwatson#include <fcntl.h> 48177785Skib#ifdef HAVE_UNISTD_H 4946155Sphk#include <unistd.h> 5087275Srwatson#endif 5187275Srwatson#include <stdio.h> 52168401Spjd#include <stdarg.h> 53193066Sjamie#include <stdlib.h> 54113275Smike#include <string.h> 55147185Spjd#include <time.h> 56113275Smike 5746155Sphk#include "compat.h" 58113275Smike#include "cpp.h" 5957163Srwatson 60113275Smike#ifndef S_ISDIR 61196019Srwatson#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 6246155Sphk#endif 63196019Srwatson 64196019Srwatson#define SBSIZE 1000000 6546155Sphk 66196019Srwatsonstatic usch sbf[SBSIZE]; 67185435Sbzstatic int counter; 68185435Sbz/* C command */ 69185435Sbz 70185435Sbzint tflag; /* traditional cpp syntax */ 71185435Sbz#ifdef PCC_DEBUG 72185435Sbzint dflag; /* debug printouts */ 7346155Sphk//static void imp(const char *); 74163606Srwatsonstatic void prline(const usch *s); 75163606Srwatsonstatic void prrep(const usch *s); 76195944Sjamie#define DPRINT(x) if (dflag) printf x 77195944Sjamie#define DDPRINT(x) if (dflag > 1) printf x 7846155Sphk#define IMP(x) if (dflag > 1) imp(x) 7946155Sphk#else 80192895Sjamie#define DPRINT(x) 81192895Sjamie#define DDPRINT(x) 82192895Sjamie#define IMP(x) 83192895Sjamie#endif 84192895Sjamie 85192895Sjamieint Aflag, Cflag, Eflag, Mflag, dMflag, Pflag, MPflag, MMDflag; 86192895Sjamiechar *Mfile, *MPfile; 87192895Sjamiestruct initar *initar; 88194762Sjamiechar *Mxfile; 89195944Sjamieint warnings, Mxlen; 90201145SantoineFILE *of; 91196176Sbz 92196176Sbz/* include dirs */ 93196176Sbzstruct incs { 94193066Sjamie struct incs *next; 95196176Sbz usch *dir; 96192895Sjamie dev_t dev; 97192895Sjamie ino_t ino; 98192895Sjamie} *incdir[2]; 9957163Srwatson 100192895Sjamiestatic struct symtab *filloc; 101168401Spjdstatic struct symtab *linloc; 102191673Sjamiestatic struct symtab *pragloc; 103191673Sjamiestatic struct symtab *defloc; 104179881Sdelphijstatic struct symtab *ctrloc; 105113275Smikeint trulvl; 106191673Sjamieint flslvl; 107190466Sjamieint elflvl; 108191673Sjamieint elslvl; 109192895Sjamieusch *stringbuf = sbf; 110192895Sjamie 111185435Sbz/* 112190466Sjamie * Macro replacement list syntax: 113192895Sjamie * - For object-type macros, replacement strings are stored as-is. 114185435Sbz * - For function-type macros, macro args are substituted for the 115185435Sbz * character WARN followed by the argument number. 116190466Sjamie * - The value element points to the beginning of the string. 117192895Sjamie * 118185435Sbz * The first character in the replacement list is the number of arguments: 119113275Smike * VARG - ends with ellipsis, next char is argcount without ellips. 120191673Sjamie * OBJCT - object-type macro 121191673Sjamie * 0 - empty parenthesis, foo() 122191673Sjamie * 1-> - number of args. 123191673Sjamie * 124191673Sjamie * WARN is used: 125191673Sjamie * - in stored replacement lists to tell that an argument comes 126113275Smike * - When expanding replacement lists to tell that the list ended. 127192895Sjamie * 128192895Sjamie * To ensure that an already expanded identifier won't get expanded 129192895Sjamie * again a EBLOCK char + its number is stored directly before any 130192895Sjamie * expanded identifier. 131192895Sjamie */ 132192895Sjamie 133192895Sjamie/* args for lookup() */ 134192895Sjamie#define FIND 0 135192895Sjamie#define ENTER 1 136195870Sjamie 137195870Sjamie/* 138195870Sjamie * No-replacement array. If a macro is found and exists in this array 139195870Sjamie * then no replacement shall occur. 140195870Sjamie */ 141195870Sjamiestruct blocker { 142195870Sjamie struct blocker *next; 143195870Sjamie struct symtab *sp; 144195870Sjamie}; 145195870Sjamiestruct blocker *blkidx[RECMAX]; 146195870Sjamieint blkidp; 147192895Sjamie 148195870Sjamiestatic int readargs2(usch **, struct symtab *sp, const usch **args); 149192895Sjamiestatic int readargs1(struct symtab *sp, const usch **args); 150192895Sjamiestatic struct iobuf *exparg(int, struct iobuf *, struct iobuf *, struct blocker *); 151195870Sjamiestatic struct iobuf *subarg(struct symtab *sp, const usch **args, int, struct blocker *); 152192895Sjamiestatic void usage(void); 153192895Sjamiestatic usch *xstrdup(const usch *str); 154192895Sjamiestatic void addidir(char *idir, struct incs **ww); 155192895Sjamiestatic void vsheap(const char *, va_list); 156192895Sjamiestatic int skipws(struct iobuf *ib); 157192895Sjamiestatic int getyp(usch *s); 158192895Sjamiestatic void *xrealloc(void *p, int sz); 159192895Sjamiestatic void *xmalloc(int sz); 160192895Sjamie 161192895Sjamieusch locs[] = 162192895Sjamie { FILLOC, LINLOC, PRAGLOC, DEFLOC, 163192895Sjamie 'd','e','f','i','n','e','d',0, CTRLOC }; 164192895Sjamie 165192895Sjamieint 166192895Sjamiemain(int argc, char **argv) 167192895Sjamie{ 168192895Sjamie struct initar *it; 169192895Sjamie register int ch; 170192895Sjamie const usch *fn1, *fn2; 171192895Sjamie 172192895Sjamie#ifdef TIMING 173192895Sjamie struct timeval t1, t2; 174192895Sjamie 175196002Sjamie (void)gettimeofday(&t1, NULL); 176196002Sjamie#endif 177192895Sjamie 178196002Sjamie while ((ch = getopt(argc, argv, "ACD:d:EI:i:MPS:tU:Vvx:")) != -1) { 179192895Sjamie switch (ch) { 180193865Sjamie case 'A': /* assembler input */ 181192895Sjamie Aflag++; 182192895Sjamie break; 183192895Sjamie 184185435Sbz case 'C': /* Do not discard comments */ 185185435Sbz Cflag++; 186185435Sbz break; 187185435Sbz 188185435Sbz case 'E': /* treat warnings as errors */ 189185435Sbz Eflag++; 190185435Sbz break; 191185435Sbz 192185435Sbz case 'D': /* define something */ 193185435Sbz case 'i': /* include */ 194185435Sbz case 'U': /* undef */ 195185435Sbz /* XXX should not need malloc() here */ 196185435Sbz if ((it = xmalloc(sizeof(struct initar))) == NULL) 197185435Sbz error("couldn't apply -%c %s", ch, optarg); 198185435Sbz it->type = ch; 199185435Sbz it->str = optarg; 200185435Sbz it->next = initar; 201185435Sbz initar = it; 202185435Sbz break; 203185435Sbz 204185435Sbz case 'd': 205185435Sbz while (*optarg) { 206185435Sbz switch(*optarg) { 207185435Sbz case 'M': /* display macro definitions */ 208185435Sbz dMflag = 1; 209185435Sbz Mflag = 1; 210185435Sbz break; 211185435Sbz 212185435Sbz default: /* ignore others */ 213185435Sbz break; 214185435Sbz } 215185435Sbz optarg++; 216185435Sbz } 217185435Sbz break; 218185435Sbz 219185435Sbz case 'I': 220185435Sbz case 'S': 221190466Sjamie addidir(optarg, &incdir[ch == 'I' ? INCINC : SYSINC]); 222185435Sbz break; 223185435Sbz 224185435Sbz case 'M': /* Generate dependencies for make */ 225185435Sbz Mflag++; 226185435Sbz break; 227185435Sbz 228185435Sbz case 'P': /* Inhibit generation of line numbers */ 229185435Sbz Pflag++; 230185435Sbz break; 231191673Sjamie 232191673Sjamie case 't': 233191673Sjamie tflag = 1; 234191673Sjamie break; 235191673Sjamie 236191673Sjamie#ifdef PCC_DEBUG 237191673Sjamie case 'V': 238185435Sbz dflag++; 239191673Sjamie break; 240191673Sjamie#endif 241192895Sjamie case 'v': 242185435Sbz fprintf(stderr, "PCC preprocessor version "VERSSTR"\n"); 243191673Sjamie break; 244191673Sjamie 245191673Sjamie case 'x': 246185435Sbz if (strcmp(optarg, "MMD") == 0) { 247191673Sjamie MMDflag++; 248191673Sjamie } else if (strcmp(optarg, "MP") == 0) { 249191673Sjamie MPflag++; 250191673Sjamie } else if (strncmp(optarg, "MT,", 3) == 0 || 251185435Sbz strncmp(optarg, "MQ,", 3) == 0) { 252192895Sjamie int l = strlen(optarg+3) + 2; 253192895Sjamie char *cp, *up; 254191673Sjamie 255191673Sjamie if (optarg[1] == 'Q') 256191673Sjamie for (cp = optarg+3; *cp; cp++) 257192895Sjamie if (*cp == '$') 258192895Sjamie l++; 259192895Sjamie Mxlen += l; 260192895Sjamie Mxfile = cp = realloc(Mxfile, Mxlen); 261191673Sjamie for (up = Mxfile; *up; up++) 262191673Sjamie ; 263191673Sjamie if (up != Mxfile) 264191673Sjamie *up++ = ' '; 265185435Sbz for (cp = optarg+3; *cp; cp++) { 266191673Sjamie *up++ = *cp; 267191673Sjamie if (optarg[1] == 'Q' && *cp == '$') 268185435Sbz *up++ = *cp; 269191673Sjamie } 270185435Sbz *up = 0; 271191673Sjamie } else 272191673Sjamie usage(); 273191673Sjamie break; 274191673Sjamie 275191673Sjamie case '?': 276192895Sjamie default: 277192895Sjamie usage(); 278192895Sjamie } 279192895Sjamie } 280192895Sjamie 281192895Sjamie argc -= optind; 282192895Sjamie argv += optind; 283192895Sjamie 284192895Sjamie filloc = lookup((const usch *)"__FILE__", ENTER); 285192895Sjamie linloc = lookup((const usch *)"__LINE__", ENTER); 286192895Sjamie pragloc = lookup((const usch *)"_Pragma", ENTER); 287192895Sjamie defloc = lookup((const usch *)"defined", ENTER); 288193865Sjamie ctrloc = lookup((const usch *)"__COUNTER__", ENTER); 289193865Sjamie filloc->value = locs; 290193865Sjamie linloc->value = locs+1; 291193865Sjamie pragloc->value = locs+2; 292193865Sjamie defloc->value = locs+3; /* also have macro name here */ 293193865Sjamie ctrloc->value = locs+12; 294193865Sjamie 295193865Sjamie if (Mflag && !dMflag) { 296193865Sjamie char *c; 297192895Sjamie 298192895Sjamie if (argc < 1) 299185435Sbz error("-M and no infile"); 300193865Sjamie if ((c = strrchr(argv[0], '/')) == NULL) 301192895Sjamie c = argv[0]; 302192895Sjamie else 303192895Sjamie c++; 304192895Sjamie Mfile = (char *)xstrdup((usch *)c); 305192895Sjamie if (MPflag) 306192895Sjamie MPfile = (char *)xstrdup((usch *)c); 307192895Sjamie if (Mxfile) 308192895Sjamie Mfile = Mxfile; 309192895Sjamie if ((c = strrchr(Mfile, '.')) == NULL) 310192895Sjamie error("-M and no extension: "); 311192895Sjamie c[1] = 'o'; 312192895Sjamie c[2] = 0; 313192895Sjamie } 314192895Sjamie 315192895Sjamie if (argc == 2) { 316192895Sjamie if ((of = freopen(argv[1], "w", stdout)) == NULL) 317192895Sjamie error("Can't creat %s", argv[1]); 318192895Sjamie } else 319192895Sjamie of = stdout; 320192895Sjamie 321192895Sjamie if (argc && strcmp(argv[0], "-")) { 322192895Sjamie fn1 = fn2 = (usch *)argv[0]; 323192895Sjamie } else { 324192895Sjamie fn1 = NULL; 325192895Sjamie fn2 = (const usch *)""; 326192895Sjamie } 327192895Sjamie if (pushfile(fn1, fn2, 0, NULL)) 328192895Sjamie error("cannot open %s", argv[0]); 329192895Sjamie 330192895Sjamie fclose(of); 331192895Sjamie#ifdef TIMING 332192895Sjamie (void)gettimeofday(&t2, NULL); 333192895Sjamie t2.tv_sec -= t1.tv_sec; 334192895Sjamie t2.tv_usec -= t1.tv_usec; 335192895Sjamie if (t2.tv_usec < 0) { 336192895Sjamie t2.tv_usec += 1000000; 337192895Sjamie t2.tv_sec -= 1; 338192895Sjamie } 339192895Sjamie fprintf(stderr, "cpp total time: %ld s %ld us\n", 340192895Sjamie (long)t2.tv_sec, (long)t2.tv_usec); 341192895Sjamie#endif 342192895Sjamie if (Eflag && warnings > 0) 343192895Sjamie return 2; 344191673Sjamie 345192895Sjamie return 0; 346192895Sjamie} 347191673Sjamie 348191673Sjamie/* 349192895Sjamie * Write a character to an out buffer. 350192895Sjamie */ 351192895Sjamiestatic void 352191673Sjamieputob(struct iobuf *ob, int ch) 353192895Sjamie{ 354192895Sjamie if (ob->cptr == ob->bsz) { 355191673Sjamie int sz = ob->bsz - ob->buf; 356192895Sjamie ob->buf = xrealloc(ob->buf, sz + BUFSIZ); 357192895Sjamie ob->cptr = ob->buf + sz; 358192895Sjamie ob->bsz = ob->buf + sz + BUFSIZ; 359191673Sjamie } 360192895Sjamie// DDPRINT(("putob: iob %p pos %p ch %c (%d)\n", ob, ob->cptr, ch, ch)); 361191673Sjamie *ob->cptr++ = ch; 362191673Sjamie} 363191673Sjamie 364192895Sjamiestatic int nbufused; 365191673Sjamie/* 366192895Sjamie * Write a character to an out buffer. 367191673Sjamie */ 368191673Sjamiestatic struct iobuf * 369192895Sjamiegetobuf(void) 370192895Sjamie{ 371192895Sjamie struct iobuf *iob = xmalloc(sizeof(struct iobuf)); 372192895Sjamie 373192895Sjamie nbufused++; 374192895Sjamie iob->buf = iob->cptr = xmalloc(BUFSIZ); 375192895Sjamie iob->bsz = iob->buf + BUFSIZ; 376192895Sjamie iob->ro = 0; 377192895Sjamie return iob; 378192895Sjamie} 379192895Sjamie 380192895Sjamie/* 381192895Sjamie * Create a read-only input buffer. 382192895Sjamie */ 383192895Sjamiestatic struct iobuf * 384192895Sjamiemkrobuf(const usch *s) 385192895Sjamie{ 386192895Sjamie struct iobuf *iob = xmalloc(sizeof(struct iobuf)); 387192895Sjamie 388192895Sjamie nbufused++; 389192895Sjamie DPRINT(("mkrobuf %s\n", s)); 390192895Sjamie iob->buf = iob->cptr = (usch *)s; 391192895Sjamie iob->bsz = iob->buf + strlen((char *)iob->buf); 392192895Sjamie iob->ro = 1; 393192895Sjamie return iob; 394192895Sjamie} 395192895Sjamie 396192895Sjamie/* 397192895Sjamie * Copy a string to a buffer. 398191673Sjamie */ 399191673Sjamiestatic struct iobuf * 400191673Sjamiestrtobuf(usch *str, struct iobuf *iob) 401191673Sjamie{ 402192895Sjamie DPRINT(("strtobuf iob %p buf %p str %s\n", iob, iob->buf, str)); 403192895Sjamie if (iob == NULL) 404191673Sjamie iob = getobuf(); 405192895Sjamie do { 406192895Sjamie putob(iob, *str); 407192895Sjamie } while (*str++); 408192895Sjamie iob->cptr--; 409192895Sjamie return iob; 410192895Sjamie} 411192895Sjamie 412192895Sjamiestatic void 413192895Sjamiebufree(struct iobuf *iob) 414191673Sjamie{ 415191673Sjamie nbufused--; 416191673Sjamie if (iob->ro == 0) 417191673Sjamie free(iob->buf); 418192895Sjamie free(iob); 419192895Sjamie} 420185435Sbz 421185435Sbzstatic void 422192895Sjamieaddidir(char *idir, struct incs **ww) 423192895Sjamie{ 424192895Sjamie struct incs *w; 425192895Sjamie struct stat st; 426192895Sjamie 427192895Sjamie if (stat(idir, &st) == -1 || !S_ISDIR(st.st_mode)) 428192895Sjamie return; /* ignore */ 429192895Sjamie if (*ww != NULL) { 430192895Sjamie for (w = *ww; w->next; w = w->next) { 431192895Sjamie#ifdef _WIN32 432192895Sjamie if (strcmp(w->dir, idir) == 0) 433185435Sbz return; 434192895Sjamie#else 435192895Sjamie if (w->dev == st.st_dev && w->ino == st.st_ino) 436191673Sjamie return; 437191673Sjamie#endif 438191673Sjamie } 439185435Sbz#ifdef _WIN32 440185435Sbz if (strcmp(w->dir, idir) == 0) 441192895Sjamie return; 442191673Sjamie#else 443191673Sjamie if (w->dev == st.st_dev && w->ino == st.st_ino) 444191673Sjamie return; 445191673Sjamie#endif 446191673Sjamie ww = &w->next; 447191673Sjamie } 448191673Sjamie if ((w = calloc(sizeof(struct incs), 1)) == NULL) 449191673Sjamie error("couldn't add path %s", idir); 450191673Sjamie w->dir = (usch *)idir; 451185435Sbz w->dev = st.st_dev; 452191673Sjamie w->ino = st.st_ino; 453191673Sjamie *ww = w; 454191673Sjamie} 455191673Sjamie 456191673Sjamievoid 457191673Sjamieline(void) 458191673Sjamie{ 459191673Sjamie struct symtab *nl; 460191673Sjamie int c, n, ln; 461191673Sjamie usch *cp; 462191673Sjamie 463191673Sjamie cp = stringbuf; 464191673Sjamie c = skipws(0); 465191673Sjamie if (ISID0(c)) { /* expand macro */ 466191673Sjamie heapid(c); 467191673Sjamie stringbuf = cp; 468191673Sjamie if ((nl = lookup(cp, FIND)) == 0 || kfind(nl) == 0) 469191673Sjamie goto bad; 470191673Sjamie } else { 471185435Sbz do { 472190466Sjamie savch(c); 473185435Sbz } while (ISDIGIT(c = cinput())); 474185435Sbz cunput(c); 475185435Sbz savch(0); 476185435Sbz } 477191673Sjamie 478191673Sjamie stringbuf = cp; 479196135Sbz n = 0; 480191673Sjamie while (ISDIGIT(*cp)) 481196835Sjamie n = n * 10 + *cp++ - '0'; 482192895Sjamie if (*cp != 0) 483196135Sbz goto bad; 484191673Sjamie 485192895Sjamie /* Can only be decimal number here between 1-2147483647 */ 486193066Sjamie if (n < 1 || n > 2147483647) 487192895Sjamie goto bad; 488192895Sjamie 489195870Sjamie ln = n; 490195870Sjamie ifiles->escln = 0; 491194762Sjamie if ((c = skipws(NULL)) != '\n') { 492191673Sjamie if (c == 'L' || c == 'U' || c == 'u') { 493192895Sjamie n = c, c = cinput(); 494191673Sjamie if (n == 'u' && c == '8') 495191673Sjamie c = cinput(); 496195974Sjamie if (c == '\"') 497191673Sjamie warning("#line only allows character literals"); 498191673Sjamie } 499195974Sjamie if (c != '\"') 500191673Sjamie goto bad; 501191673Sjamie /* loses space on heap... does it matter? */ 502192895Sjamie ifiles->fname = stringbuf+1; 503191673Sjamie faststr(c, savch); 504185435Sbz stringbuf--; 505191673Sjamie savch(0); 506191673Sjamie 507191673Sjamie c = skipws(0); 508191673Sjamie } 509191673Sjamie if (c != '\n') 510192895Sjamie goto bad; 511194762Sjamie 512192895Sjamie ifiles->lineno = ln; 513191673Sjamie prtline(1); 514191673Sjamie ifiles->lineno--; 515191673Sjamie cunput('\n'); 516185435Sbz return; 517191673Sjamie 518191673Sjamiebad: error("bad #line"); 519191673Sjamie} 520191673Sjamie 521185435Sbz#ifdef MACHOABI 522191673Sjamie 523191673Sjamie/* 524191673Sjamie * Search for framework header file. 525185435Sbz * Return 1 on success. 526191673Sjamie */ 527191673Sjamie 528191673Sjamiestatic int 529185435Sbzfsrch_macos_framework(const usch *fn, const usch *dir) 530185435Sbz{ 531185435Sbz usch *saved_stringbuf = stringbuf; 532185435Sbz usch *s = (usch *)strchr((const char*)fn, '/'); 533185435Sbz usch *nm; 534185435Sbz usch *p; 535191673Sjamie int len = s - fn; 536191673Sjamie 537191673Sjamie if (s == NULL) 538191673Sjamie return 0; 539191673Sjamie 540191673Sjamie// fprintf(stderr, "searching for %s in %s\n", (const char *)fn, (const char *)dir); 541191673Sjamie 542191673Sjamie nm = savstr(dir); 543191673Sjamie savch(0); 544191673Sjamie p = savstr(fn); 545191673Sjamie stringbuf = p + len; 546191673Sjamie savch(0); 547191673Sjamie// fprintf(stderr, "comparing \"%s\" against \"%.*s\"\n", nm, len, fn); 548191673Sjamie p = (usch *)strstr((const char *)nm, (const char *)p); 549191673Sjamie// fprintf(stderr, "p = %s\n", (const char *)p); 550194762Sjamie if (p != NULL) { 551194762Sjamie stringbuf = p; 552194762Sjamie savch(0); 553194762Sjamie return fsrch_macos_framework(fn, nm); 554194762Sjamie } 555194762Sjamie 556194762Sjamie p = nm + strlen((char *)nm) - 1; 557194762Sjamie while (*p == '/') 558194762Sjamie p--; 559192895Sjamie while (*p != '/') 560192895Sjamie p--; 561192895Sjamie stringbuf = ++p; 562192895Sjamie savstr((const usch *)"Frameworks/"); 563192895Sjamie stringbuf = savstr(fn) + len; 564192895Sjamie savstr((const usch*)".framework/Headers"); 565192895Sjamie savstr(s); 566192895Sjamie savch(0); 567191673Sjamie 568192895Sjamie// fprintf(stderr, "nm: %s\n", nm); 569192895Sjamie 570192895Sjamie if (pushfile(nm, fn, SYSINC, NULL) == 0) 571192895Sjamie return 1; 572192895Sjamie// fprintf(stderr, "not found %s, continuing...\n", nm); 573192895Sjamie 574192895Sjamie stringbuf = saved_stringbuf; 575191673Sjamie 576195870Sjamie return 0; 577195870Sjamie} 578195870Sjamie 579195870Sjamie#endif 580195870Sjamie 581195870Sjamie/* 582195870Sjamie * Search for and include next file. 583195870Sjamie * Return 1 on success. 584195870Sjamie */ 585195870Sjamiestatic int 586195870Sjamiefsrch(const usch *fn, int idx, struct incs *w) 587195870Sjamie{ 588195870Sjamie int i; 589195870Sjamie 590195870Sjamie for (i = idx; i < 2; i++) { 591195870Sjamie if (i > idx) 592195870Sjamie w = incdir[i]; 593195870Sjamie for (; w; w = w->next) { 594195870Sjamie usch *nm = stringbuf; 595195870Sjamie 596195870Sjamie savstr(w->dir); savch('/'); 597195870Sjamie savstr(fn); savch(0); 598195870Sjamie if (pushfile(nm, fn, i, w->next) == 0) 599195870Sjamie return 1; 600195870Sjamie stringbuf = nm; 601195870Sjamie } 602195870Sjamie } 603195870Sjamie 604191673Sjamie#ifdef MACHOABI 605191673Sjamie /* 606191673Sjamie * On MacOS, we may have to do some clever stuff 607191673Sjamie * to resolve framework headers. 608191673Sjamie */ 609191673Sjamie { 610194251Sjamie usch *dir = stringbuf; 611194251Sjamie savstr(ifiles->orgfn); 612194251Sjamie stringbuf = (usch *)strrchr((char *)dir, '/'); 613194251Sjamie if (stringbuf != NULL) { 614194251Sjamie stringbuf++; 615194251Sjamie savch(0); 616194251Sjamie if (fsrch_macos_framework(fn, dir) == 1) 617195974Sjamie return 1; 618195974Sjamie } 619195974Sjamie stringbuf = dir; 620195974Sjamie 621195974Sjamie if (fsrch_macos_framework(fn, (const usch *)"/Library/Frameworks/") == 1) 622195974Sjamie return 1; 623195974Sjamie 624195974Sjamie if (fsrch_macos_framework(fn, (const usch *)"/System/Library/Frameworks/") == 1) 625195974Sjamie return 1; 626195974Sjamie } 627195974Sjamie#endif 628195974Sjamie 629195974Sjamie return 0; 630195974Sjamie} 631191673Sjamie 632192895Sjamiestatic void 633192895Sjamieprem(void) 634192895Sjamie{ 635192895Sjamie error("premature EOF"); 636192895Sjamie} 637192895Sjamie 638192895Sjamiestatic struct iobuf * 639192895Sjamieincfn(void) 640191673Sjamie{ 641191673Sjamie struct iobuf *ob; 642191673Sjamie struct symtab *nl; 643191673Sjamie usch *sb; 644191673Sjamie int c; 645191673Sjamie 646191673Sjamie sb = stringbuf; 647191673Sjamie if (spechr[c = skipws(NULL)] & C_ID0) { 648191673Sjamie heapid(c); 649191673Sjamie if ((nl = lookup(sb, FIND)) == NULL) 650191673Sjamie return NULL; 651191673Sjamie 652191673Sjamie stringbuf = sb; 653191673Sjamie if (kfind(nl) == 0) 654191673Sjamie return NULL; 655191673Sjamie ob = strtobuf(sb, NULL); 656191673Sjamie } else { 657191673Sjamie ob = getobuf(); 658191673Sjamie putob(ob, c); 659191673Sjamie while ((c = cinput()) && c != '\n') 660191673Sjamie putob(ob, c); 661191673Sjamie if (c != '\n') 662193066Sjamie return NULL; 663193066Sjamie cunput(c); 664191673Sjamie } 665191673Sjamie putob(ob, 0); 666191673Sjamie ob->cptr--; 667191673Sjamie 668191673Sjamie /* now we have an (expanded?) filename in obuf */ 669191673Sjamie while (ob->buf < ob->cptr && ISWS(ob->cptr[-1])) 670191673Sjamie ob->cptr--; 671191673Sjamie 672191673Sjamie if (ob->buf[0] != '\"' && ob->buf[0] != '<') 673191673Sjamie return NULL; 674193066Sjamie if (ob->cptr[-1] != '\"' && ob->cptr[-1] != '>') 675193066Sjamie return NULL; 676193066Sjamie ob->cptr[-1] = 0; 677193066Sjamie return ob; 678193066Sjamie} 679193066Sjamie 680193066Sjamie/* 681193066Sjamie * Include a file. Include order: 682193066Sjamie * - For <...> files, first search -I directories, then system directories. 683193066Sjamie * - For "..." files, first search "current" dir, then as <...> files. 684193066Sjamie */ 685193066Sjamievoid 686193066Sjamieinclude(void) 687193066Sjamie{ 688193066Sjamie struct iobuf *ob; 689193066Sjamie usch *fn, *nm = NULL; 690193066Sjamie 691193066Sjamie if (flslvl) 692193066Sjamie return; 693193066Sjamie 694193066Sjamie if ((ob = incfn()) == NULL) /* get include file name in obuf */ 695193066Sjamie error("bad #include"); 696193066Sjamie 697193066Sjamie fn = xstrdup(ob->buf) + 1; /* Save on string heap? */ 698193066Sjamie bufree(ob); 699193066Sjamie /* test absolute path first */ 700193066Sjamie if (fn[0] == '/' && pushfile(fn, fn, 0, NULL) == 0) 701193066Sjamie goto okret; 702193066Sjamie if (fn[-1] == '\"') { 703193066Sjamie /* nope, failed, try to create a path for it */ 704193066Sjamie if ((nm = (usch *)strrchr((char *)ifiles->orgfn, '/'))) { 705193066Sjamie ob = strtobuf((usch *)ifiles->orgfn, NULL); 706193066Sjamie ob->cptr = ob->buf + (nm - ifiles->orgfn) + 1; 707193066Sjamie strtobuf(fn, ob); 708193066Sjamie putob(ob, 0); 709193066Sjamie nm = xstrdup(ob->buf); 710193066Sjamie bufree(ob); 711193066Sjamie } else { 712193066Sjamie nm = xstrdup(fn); 713193066Sjamie } 714193066Sjamie if (pushfile(nm, nm, 0, NULL) == 0) { 715193066Sjamie free(fn-1); 716193066Sjamie goto okret; 717193066Sjamie } 718193066Sjamie } 719193066Sjamie if (fsrch(fn, 0, incdir[0])) 720193066Sjamie goto okret; 721193066Sjamie 722193066Sjamie error("cannot find '%s'", fn); 723193066Sjamie /* error() do not return */ 724193066Sjamie 725193066Sjamieokret: 726193066Sjamie if (nm) 727193066Sjamie free(nm); 728193066Sjamie prtline(1); 729185435Sbz} 730191673Sjamie 731191673Sjamievoid 732195870Sjamieinclude_next(void) 733191673Sjamie{ 734191673Sjamie struct iobuf *ob; 735191673Sjamie usch *nm; 736191673Sjamie 737191673Sjamie if (flslvl) 738192895Sjamie return; 739195870Sjamie 740195870Sjamie if ((ob = incfn()) == NULL) /* get include file name in obuf */ 741195870Sjamie error("bad #include_next"); 742195870Sjamie 743195870Sjamie nm = xstrdup(ob->buf+1); 744192895Sjamie bufree(ob); 745192895Sjamie 746185435Sbz if (fsrch(nm, ifiles->idx, ifiles->incs) == 0) 747192895Sjamie error("cannot find '%s'", nm); 748192895Sjamie prtline(1); 749185435Sbz} 750195974Sjamie 751192895Sjamie/* 752192895Sjamie * Compare two replacement lists, taking in account comments etc. 753192895Sjamie */ 754192895Sjamiestatic int 755192895Sjamiecmprepl(const usch *o, const usch *n) 756202116Sbz{ 757202116Sbz for (; *o; o++, n++) { 758202116Sbz /* comment skip */ 759192895Sjamie if (*o == '/' && o[1] == '*') { 760192895Sjamie while (*o != '*' || o[1] != '/') 761192895Sjamie o++; 762192895Sjamie o += 2; 763192895Sjamie } 764192895Sjamie if (*n == '/' && n[1] == '*') { 765192895Sjamie while (*n != '*' || n[1] != '/') 766192895Sjamie n++; 767192895Sjamie n += 2; 768192895Sjamie } 769192895Sjamie while (*o == ' ' || *o == '\t') 770192895Sjamie o++; 771192895Sjamie while (*n == ' ' || *n == '\t') 772192895Sjamie n++; 773192895Sjamie if (*o != *n) 774192895Sjamie return 1; 775192895Sjamie } 776192895Sjamie return 0; 777192895Sjamie} 778192895Sjamie 779192895Sjamiestatic int 780192895Sjamieisell(void) 781192895Sjamie{ 782192895Sjamie if (cinput() != '.' || cinput() != '.') 783185435Sbz return 0; 784191673Sjamie return 1; 785191673Sjamie} 786185435Sbz 787185435Sbzstatic int 788191673Sjamieskipwscmnt(struct iobuf *ib) 789191673Sjamie{ 790195870Sjamie /* XXX comment */ 791191673Sjamie return skipws(ib); 792191673Sjamie} 793191673Sjamie 794191673Sjamiestatic int 795191673Sjamiefindarg(usch *s, usch **args, int narg) 796192895Sjamie{ 797195870Sjamie int i; 798195870Sjamie 799195870Sjamie for (i = 0; i < narg; i++) 800195870Sjamie if (strcmp((char *)s, (char *)args[i]) == 0) 801195870Sjamie return i; 802192895Sjamie return -1; 803192895Sjamie} 804185435Sbz 805192895Sjamie/* 806192895Sjamie * gcc extensions: 807185435Sbz * #define e(a...) f(s, a) -> a works as __VA_ARGS__ 808195974Sjamie * #define e(fmt, ...) f(s, fmt , ##__VA_ARGS__) -> remove , if no args 809192895Sjamie */ 810192895Sjamievoid 811192895Sjamiedefine(void) 812192895Sjamie{ 813192895Sjamie struct symtab *np; 814192895Sjamie usch *args[MAXARGS+1], *sbeg, *bp, cc[2], *vararg; 815192895Sjamie int c, i, redef, oCflag, t; 816192895Sjamie int narg = -1; 817192895Sjamie int wascon; 818192895Sjamie 819192895Sjamie if (flslvl) 820192895Sjamie return; 821192895Sjamie 822192895Sjamie oCflag = Cflag, Cflag = 0; /* Ignore comments here */ 823192895Sjamie if (!ISID0(c = skipws(0))) 824192895Sjamie goto bad; 825185435Sbz 826191673Sjamie bp = heapid(c); 827185435Sbz np = lookup(bp, ENTER); 828185435Sbz if (np->value) { 829195945Sjamie stringbuf = bp; 830195945Sjamie redef = 1; 831195945Sjamie } else 832195945Sjamie redef = 0; 833195945Sjamie 834195945Sjamie vararg = NULL; 835195945Sjamie sbeg = stringbuf++; 836195945Sjamie if ((c = cinput()) == '(') { 837195945Sjamie narg = 0; 838191673Sjamie /* function-like macros, deal with identifiers */ 839191673Sjamie c = skipws(0); 840191673Sjamie for (;;) { 841191673Sjamie switch (c) { 842191673Sjamie case ')': 843191673Sjamie break; 844191673Sjamie case '.': 845191673Sjamie if (isell() == 0 || (c = skipws(0)) != ')') 846191673Sjamie goto bad; 847191673Sjamie vararg = (usch *)"__VA_ARGS__"; 848191673Sjamie break; 849191673Sjamie default: 850191673Sjamie if (!ISID0(c)) 851191673Sjamie goto bad; 852191673Sjamie 853191673Sjamie bp = heapid(c); 854191673Sjamie /* make sure there is no arg of same name */ 855191673Sjamie if (findarg(bp, args, narg) >= 0) 856191673Sjamie error("Duplicate parameter \"%s\"", bp); 857191673Sjamie if (narg == MAXARGS) 858192895Sjamie error("Too many macro args"); 859192895Sjamie args[narg++] = xstrdup(bp); 860192895Sjamie stringbuf = bp; 861192895Sjamie switch ((c = skipws(0))) { 862192895Sjamie case ',': break; 863192895Sjamie case ')': continue; 864191673Sjamie case '.': 865191673Sjamie if (isell() == 0 || skipws(0) != ')') 866191673Sjamie goto bad; 867191673Sjamie vararg = args[--narg]; 868191673Sjamie c = ')'; 869191673Sjamie continue; 870191673Sjamie default: 871191673Sjamie goto bad; 872191673Sjamie } 873191673Sjamie c = skipws(0); 874191673Sjamie } 875191673Sjamie if (c == ')') 876191673Sjamie break; 877191673Sjamie } 878191673Sjamie c = skipws(0); 879191673Sjamie } else if (c == '\n') { 880191673Sjamie /* #define foo */ 881185435Sbz ; 882191673Sjamie } else if (c == 0) { 883191673Sjamie prem(); 884191673Sjamie } else if (!ISWS(c)) 885191673Sjamie goto bad; 886191673Sjamie 887191673Sjamie Cflag = oCflag; /* Enable comments again */ 888191673Sjamie 889191673Sjamie if (vararg) 890191673Sjamie stringbuf++; 891185435Sbz 892191673Sjamie if (ISWS(c)) 893191673Sjamie c = skipwscmnt(0); 894191673Sjamie 895191673Sjamie#define DELEWS() while (stringbuf > sbeg+1+(vararg!=NULL) && ISWS(stringbuf[-1])) stringbuf-- 896191673Sjamie 897191673Sjamie /* parse replacement-list, substituting arguments */ 898191673Sjamie wascon = 0; 899191673Sjamie while (c != '\n') { 900191673Sjamie cc[0] = c, cc[1] = inc2(); 901185435Sbz t = getyp(cc); 902191673Sjamie cunput(cc[1]); 903191673Sjamie 904185435Sbz switch (t) { 905191673Sjamie case ' ': 906191673Sjamie case '\t': 907191673Sjamie savch(' '); /* save only one space */ 908191673Sjamie while ((c = cinput()) == ' ' || c == '\t') 909191673Sjamie ; 910191673Sjamie continue; 911191673Sjamie 912196835Sjamie case '#': 913196835Sjamie if (cc[1] == '#') { 914196835Sjamie /* concat op */ 915196835Sjamie (void)cinput(); /* eat # */ 916196835Sjamie DELEWS(); 917196835Sjamie savch(CONC); 918196835Sjamie if (ISID0(c = skipws(0)) && narg >= 0) 919191673Sjamie wascon = 1; 920192895Sjamie if (c == '\n') 921192895Sjamie goto bad; /* 6.10.3.3 p1 */ 922192895Sjamie continue; 923192895Sjamie } 924192895Sjamie 925192895Sjamie if (narg < 0) { 926192895Sjamie /* no meaning in object-type macro */ 927191673Sjamie savch('#'); 928191673Sjamie break; 929191673Sjamie } 930191673Sjamie 931191673Sjamie /* remove spaces between # and arg */ 932191673Sjamie savch(SNUFF); 933191673Sjamie c = skipws(0); /* whitespace, ignore */ 934192895Sjamie if (!ISID0(c)) 935191673Sjamie goto bad; 936191673Sjamie bp = heapid(c); 937191673Sjamie if (vararg && strcmp((char *)bp, (char *)vararg) == 0) { 938191673Sjamie stringbuf = bp; 939191673Sjamie savch(WARN); 940191673Sjamie savch(VARG); 941191673Sjamie savch(SNUFF); 942191673Sjamie break; 943192895Sjamie 944192895Sjamie } 945192895Sjamie if ((i = findarg(bp, args, narg)) < 0) 946192895Sjamie goto bad; 947191673Sjamie stringbuf = bp; 948191673Sjamie savch(WARN); 949191673Sjamie savch(i); 950191673Sjamie savch(SNUFF); 951191673Sjamie break; 952191673Sjamie 953191673Sjamie case NUMBER: 954191673Sjamie c = fastnum(c, savch); 955191673Sjamie continue; 956191673Sjamie 957191673Sjamie case STRING: 958191673Sjamie if (c == 'L' || c == 'u' || c == 'U') { 959191673Sjamie savch(c); 960191673Sjamie if ((c = cinput()) == '8') { 961191673Sjamie savch(c); 962191673Sjamie c = cinput(); 963191673Sjamie } 964192895Sjamie } 965191673Sjamie if (tflag) 966191673Sjamie savch(c); 967191673Sjamie else 968191673Sjamie faststr(c, savch); 969191673Sjamie break; 970191673Sjamie 971191673Sjamie case IDENT: 972191673Sjamie bp = heapid(c); 973191673Sjamie stringbuf--; /* remove \0 */ 974191673Sjamie if (narg < 0) 975191673Sjamie break; /* keep on heap */ 976191673Sjamie if (vararg && strcmp((char *)bp, (char *)vararg) == 0) { 977191673Sjamie stringbuf = bp; 978191673Sjamie savch(WARN); 979191673Sjamie savch(wascon ? GCCARG : VARG); 980191673Sjamie break; 981191673Sjamie } 982191673Sjamie 983191673Sjamie /* check if its an argument */ 984191673Sjamie if ((i = findarg(bp, args, narg)) < 0) 985196835Sjamie break; 986196835Sjamie stringbuf = bp; 987196835Sjamie savch(WARN); 988196835Sjamie savch(i); 989192895Sjamie break; 990192895Sjamie 991192895Sjamie case 0: 992192895Sjamie goto bad; 993192895Sjamie 994196835Sjamie default: 995192895Sjamie savch(c); 996196835Sjamie break; 997196835Sjamie } 998192895Sjamie wascon = 0; 999192895Sjamie c = cinput(); 1000192895Sjamie } 1001192895Sjamie cunput(c); 1002192895Sjamie /* remove trailing whitespace */ 1003192895Sjamie DELEWS(); 1004192895Sjamie 1005192895Sjamie if (sbeg[1+(vararg != 0)] == CONC) 1006192895Sjamie goto bad; /* 6.10.3.3 p1 */ 1007192895Sjamie 1008192895Sjamie if (vararg) { 1009192895Sjamie sbeg[0] = VARG; 1010192895Sjamie sbeg[1] = narg; 1011192895Sjamie } else 1012192895Sjamie sbeg[0] = (narg < 0 ? OBJCT : narg); 1013192895Sjamie savch(0); 1014196835Sjamie 1015192895Sjamie if (redef && ifiles->idx != SYSINC) { 1016191673Sjamie if (cmprepl(np->value, sbeg)) { /* not equal */ 1017192895Sjamie np->value = sbeg; 1018192895Sjamie warning("%s redefined (previously defined at \"%s\" line %d)", 1019192895Sjamie np->namep, np->file, np->line); 1020191673Sjamie } else 1021192895Sjamie stringbuf = sbeg; /* forget this space */ 1022191673Sjamie } else 1023192895Sjamie np->value = sbeg; 1024191673Sjamie 1025191673Sjamie#ifdef PCC_DEBUG 1026191673Sjamie if (dflag) { 1027191673Sjamie const usch *w = np->value; 1028191673Sjamie 1029191673Sjamie printf("!define %s: ", np->namep); 1030191673Sjamie if (*w == OBJCT) 1031191673Sjamie printf("[object]"); 1032191673Sjamie else if (*w == VARG) 1033191673Sjamie printf("[VARG%d]", *++w); 1034191673Sjamie else 1035191673Sjamie printf("[%d]", *w); 1036191673Sjamie putchar('\''); 1037191673Sjamie prrep(++w); 1038191673Sjamie printf("\'\n"); 1039191673Sjamie } 1040191673Sjamie#endif 1041191673Sjamie for (i = 0; i < narg; i++) 1042191673Sjamie free(args[i]); 1043192895Sjamie return; 1044191673Sjamie 1045191673Sjamiebad: error("bad #define"); 1046191673Sjamie} 1047191673Sjamie 1048191673Sjamievoid 1049191673Sjamiewarning(const char *fmt, ...) 1050191673Sjamie{ 1051191673Sjamie va_list ap; 1052191673Sjamie 1053191673Sjamie if (ifiles != NULL) 1054191673Sjamie fprintf(stderr, "%s:%d: warning: ", 1055191673Sjamie ifiles->fname, ifiles->lineno); 1056191673Sjamie 1057191673Sjamie va_start(ap,fmt); 1058191673Sjamie vfprintf(stderr, fmt, ap); 1059191673Sjamie va_end(ap); 1060191673Sjamie fputc('\n', stderr); 1061191673Sjamie 1062191673Sjamie warnings++; 1063191673Sjamie} 1064191673Sjamie 1065191673Sjamievoid 1066191673Sjamieerror(const char *fmt, ...) 1067191673Sjamie{ 1068191673Sjamie va_list ap; 1069191673Sjamie 1070191673Sjamie if (ifiles != NULL) 1071191673Sjamie fprintf(stderr, "%s:%d: error: ", 1072191673Sjamie ifiles->fname, ifiles->lineno); 1073191673Sjamie 1074191673Sjamie va_start(ap, fmt); 1075191673Sjamie vfprintf(stderr, fmt, ap); 1076191673Sjamie va_end(ap); 1077191673Sjamie fputc('\n', stderr); 1078191673Sjamie exit(1); 1079191673Sjamie} 1080191673Sjamie 1081191673Sjamie/* 1082191673Sjamie * store a character into the "define" buffer. 1083191673Sjamie */ 1084191673Sjamievoid 1085191673Sjamiesavch(int c) 1086185435Sbz{ 1087191673Sjamie if (stringbuf >= &sbf[SBSIZE]) 1088191673Sjamie error("out of macro space!"); 1089194762Sjamie 1090194762Sjamie *stringbuf++ = (usch)c; 1091194762Sjamie} 1092194762Sjamie 1093194762Sjamiestatic int 1094194762Sjamiepragwin(struct iobuf *ib) 1095191673Sjamie{ 1096192895Sjamie return ib ? *ib->cptr++ : cinput(); 1097192895Sjamie} 1098192895Sjamie 1099192895Sjamiestatic int 1100192895Sjamieskipws(struct iobuf *ib) 1101192895Sjamie{ 1102192895Sjamie int t; 1103192895Sjamie 1104192895Sjamie while ((t = pragwin(ib)) == ' ' || t == '\t') 1105192895Sjamie ; 1106191673Sjamie return t; 1107191673Sjamie} 1108191673Sjamie 1109191673Sjamie/* 1110191673Sjamie * convert _Pragma() to #pragma for output. 1111191673Sjamie * Syntax is already correct. 1112191673Sjamie */ 1113191673Sjamiestatic void 1114191673Sjamiepragoper(struct iobuf *ib) 1115191673Sjamie{ 1116191673Sjamie int t; 1117191673Sjamie usch *bp = stringbuf; 1118191673Sjamie 1119191673Sjamie if (skipws(ib) != '(' || ((t = skipws(ib)) != '\"' && t != 'L')) 1120191673Sjamie goto err; 1121191673Sjamie if (t == 'L' && (t = pragwin(ib)) != '\"') 1122191673Sjamie goto err; 1123191673Sjamie savstr((const usch *)"\n#pragma "); 1124191673Sjamie while ((t = pragwin(ib)) != '\"') { 1125192895Sjamie if (t == BLKID) { 1126192895Sjamie pragwin(ib); 1127192895Sjamie continue; 1128191673Sjamie } 1129191673Sjamie if (t == '\"') 1130191673Sjamie continue; 1131191673Sjamie if (t == '\\') { 1132191673Sjamie if ((t = pragwin(ib)) != '\"' && t != '\\') 1133191673Sjamie savch('\\'); 1134191673Sjamie } 1135191673Sjamie savch(t); 1136191673Sjamie } 1137191673Sjamie sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname); 1138191673Sjamie putstr(bp); 1139191673Sjamie stringbuf = bp; 1140191673Sjamie if (skipws(ib) == ')') 1141191673Sjamie return; 1142191673Sjamie 1143191673Sjamieerr: error("_Pragma() syntax error"); 1144191673Sjamie} 1145191673Sjamie 1146192895Sjamiestatic int 1147192895Sjamieexpok(struct symtab *sp, int l) 1148194762Sjamie{ 1149185435Sbz struct blocker *w; 1150192895Sjamie 1151191673Sjamie if (l == 0) 1152192895Sjamie return 1; 1153192895Sjamie#ifdef PCC_DEBUG 1154191673Sjamieif (dflag) { printf("expok blocked: "); for (w = blkidx[l]; w; w = w->next) printf("%s ", w->sp->namep); printf("\n"); } 1155191673Sjamie#endif 1156191673Sjamie w = blkidx[l]; 1157191673Sjamie while (w) { 1158192895Sjamie if (w->sp == sp) 1159191673Sjamie return 0; 1160191673Sjamie w = w->next; 1161195944Sjamie } 1162195944Sjamie return 1; 1163195945Sjamie} 1164195945Sjamie 1165195945Sjamiestatic int 1166195945Sjamieexpokb(struct symtab *sp, struct blocker *bl) 1167195945Sjamie{ 1168192895Sjamie struct blocker *w; 1169195974Sjamie 1170195974Sjamie if (bl == 0) 1171195974Sjamie return 1; 1172195974Sjamie#ifdef PCC_DEBUG 1173195974Sjamieif (dflag) { printf("expokb blocked: "); for (w = bl; w; w = w->next) printf("%s ", w->sp->namep); printf("\n"); } 1174195974Sjamie#endif 1175195974Sjamie w = bl; 1176195974Sjamie while (w) { 1177195974Sjamie if (w->sp == sp) 1178195974Sjamie return 0; 1179195974Sjamie w = w->next; 1180195974Sjamie } 1181195974Sjamie return 1; 1182195974Sjamie} 1183192895Sjamie 1184192895Sjamiestatic struct blocker * 1185195974Sjamieblkget(struct symtab *sp, struct blocker *obl) 1186195974Sjamie{ 1187195974Sjamie struct blocker *bl = calloc(sizeof(*obl), 1); 1188195974Sjamie 1189195974Sjamie bl->sp = sp; 1190195974Sjamie bl->next = obl; 1191195974Sjamie return bl; 1192195974Sjamie} 1193195974Sjamie 1194195974Sjamiestatic int 1195195974Sjamieblkix(struct blocker *obl) 1196195974Sjamie{ 1197195974Sjamie if (blkidp > 1 && blkidx[blkidp-1] == obl) 1198195974Sjamie return blkidp-1; 1199192895Sjamie if (blkidp == RECMAX) 1200195945Sjamie error("blkix"); 1201195945Sjamie blkidx[blkidp] = obl; 1202192895Sjamie return blkidp++; 1203192895Sjamie} 1204196002Sjamie 1205191673Sjamiestatic struct blocker * 1206192895Sjamiemergeadd(struct blocker *bl, int m) 1207192895Sjamie{ 1208191673Sjamie struct blocker *w, *ww; 1209194251Sjamie 1210194251Sjamie DPRINT(("mergeadd: %p %d\n", bl, m)); 1211194251Sjamie if (bl == 0) 1212194251Sjamie return blkidx[m]; 1213194251Sjamie if (m == 0) 1214185435Sbz return bl; 1215191673Sjamie 1216191673Sjamie blkidx[blkidp] = bl; 1217185435Sbz for (w = blkidx[m]; w; w = w->next) { 1218192895Sjamie ww = calloc(sizeof(*w), 1); 1219191673Sjamie ww->sp = w->sp; 1220191673Sjamie ww->next = blkidx[blkidp]; 1221191673Sjamie blkidx[blkidp] = ww; 1222191673Sjamie } 1223185435Sbz DPRINT(("mergeadd return: %d ", blkidp)); 1224191673Sjamie#ifdef PCC_DEBUG 1225185435Sbz if (dflag) { 1226191673Sjamie for (w = blkidx[blkidp]; w; w = w->next) 1227191673Sjamie printf("%s ", w->sp->namep); 1228191673Sjamie printf("\n"); 1229185435Sbz } 1230191673Sjamie#endif 1231191673Sjamie return blkidx[blkidp++]; 1232195974Sjamie} 1233195974Sjamie 1234195974Sjamiestatic void 1235195974Sjamiestoreblk(int l, struct iobuf *ob) 1236195974Sjamie{ 1237195945Sjamie DPRINT(("storeblk: %d\n", l)); 1238195945Sjamie putob(ob, BLKID); 1239195945Sjamie putob(ob, l); 1240195945Sjamie} 1241195945Sjamie 1242195945Sjamie/* 1243195945Sjamie * Save filename on heap (with escaped chars). 1244195945Sjamie */ 1245195945Sjamiestatic usch * 1246195974Sjamieunfname(void) 1247195974Sjamie{ 1248195974Sjamie usch *sb = stringbuf; 1249195974Sjamie const usch *bp = ifiles->fname; 1250195974Sjamie 1251195974Sjamie savch('\"'); 1252195974Sjamie for (; *bp; bp++) { 1253195974Sjamie if (*bp == '\"' || *bp == '\'' || *bp == '\\') 1254195974Sjamie savch('\\'); 1255195974Sjamie savch(*bp); 1256195974Sjamie } 1257195974Sjamie savch('\"'); 1258195974Sjamie *stringbuf = 0; 1259195974Sjamie return sb; 1260195974Sjamie} 1261195974Sjamie 1262191673Sjamie/* 1263185435Sbz * Version of fastnum that reads from a string and saves in ob. 1264191673Sjamie * We know that it is a number before calling this routine. 1265192895Sjamie */ 1266192895Sjamiestatic usch * 1267192895Sjamiefstrnum(usch *s, struct iobuf *ob) 1268192895Sjamie{ 1269192895Sjamie if (*s == '.') { 1270192895Sjamie /* not digit, dot. Next will be digit */ 1271194762Sjamie putob(ob, *s++); 1272194762Sjamie } 1273194762Sjamie for (;;) { 1274194762Sjamie putob(ob, *s++); 1275194762Sjamie if ((spechr[*s] & C_EP)) { 1276194762Sjamie if (s[1] != '-' && s[1] != '+') 1277192895Sjamie break; 1278192895Sjamie putob(ob, *s++); 1279192895Sjamie } else if ((*s != '.') && ((spechr[*s] & C_ID) == 0)) 1280192895Sjamie break; 1281192895Sjamie } 1282192895Sjamie return s; 1283185435Sbz} 1284195974Sjamie 1285192895Sjamie/* 1286195974Sjamie * get a string or character constant. 1287195974Sjamie * similar to faststr. 1288195974Sjamie */ 1289195974Sjamiestatic usch * 1290195974Sjamiefstrstr(usch *s, struct iobuf *ob) 1291195974Sjamie{ 1292195974Sjamie int ch; 1293195974Sjamie 1294195974Sjamie if (*s == 'L' || *s == 'U' || *s == 'u') 1295195974Sjamie putob(ob, *s++); 1296195974Sjamie if (*s == '8') 1297195974Sjamie putob(ob, *s++); 1298195974Sjamie ch = *s; 1299195974Sjamie putob(ob, *s++); 1300195974Sjamie while (*s != ch) { 1301195974Sjamie if (*s == '\\') 1302195974Sjamie putob(ob, *s++); 1303195974Sjamie putob(ob, *s++); 1304195974Sjamie } 1305195974Sjamie putob(ob, *s++); 1306195974Sjamie return s; 1307195974Sjamie} 1308195974Sjamie 1309195974Sjamie/* 1310192895Sjamie * Save standard comments if found. 1311192895Sjamie */ 1312192895Sjamiestatic usch * 1313192895Sjamiefcmnt(usch *s, struct iobuf *ob) 1314192895Sjamie{ 1315192895Sjamie putob(ob, *s++); /* / */ 1316192895Sjamie putob(ob, *s++); /* * */ 1317195974Sjamie for (;;s++) { 1318195974Sjamie putob(ob, *s); 1319195974Sjamie if (s[-1] == '*' && *s == '/') 1320195974Sjamie break; 1321195974Sjamie } 1322195974Sjamie return s+1; 1323195974Sjamie} 1324195945Sjamie 1325195974Sjamiestatic int 1326195974Sjamiegetyp(usch *s) 1327195974Sjamie{ 1328195945Sjamie 1329195974Sjamie if (ISID0(*s)) return IDENT; 1330195974Sjamie if ((*s == 'L' || *s == 'U' || *s == 'u') && 1331195945Sjamie (s[1] == '\'' || s[1] == '\"')) return STRING; 1332195974Sjamie if (s[0] == 'u' && s[1] == 'U' && s[2] == '\"') return STRING; 1333195945Sjamie if (s[0] == '\'' || s[0] == '\"') return STRING; 1334195974Sjamie if (spechr[*s] & C_DIGIT) return NUMBER; 1335192895Sjamie if (*s == '.' && (spechr[s[1]] & C_DIGIT)) return NUMBER; 1336195974Sjamie if (*s == '/' && (s[1] == '/' || s[1] == '*')) return CMNT; 1337195974Sjamie return *s; 1338195974Sjamie 1339195974Sjamie} 1340195974Sjamie 1341195974Sjamie/* 1342195974Sjamie * Check ib and print out the symbols there. 1343195974Sjamie * If expandable symbols found recurse and expand them. 1344195974Sjamie * If last identifier on the input list is expandable return it. 1345195974Sjamie * Expect ib to be zero-terminated. 1346195974Sjamie */ 1347195974Sjamiestatic struct symtab * 1348195974Sjamieloopover(struct iobuf *ib) 1349195974Sjamie{ 1350192895Sjamie struct iobuf *xb, *xob; 1351192895Sjamie struct symtab *sp; 1352192895Sjamie usch *cp; 1353192895Sjamie int l, c, t; 1354185435Sbz 1355191673Sjamie ib->cptr = ib->buf; /* start from beginning */ 1356195974Sjamie#ifdef PCC_DEBUG 1357192895Sjamie if (dflag) { 1358195974Sjamie printf("loopover: '"); 1359195974Sjamie prline(ib->cptr); 1360195974Sjamie printf("'\n"); 1361195974Sjamie } 1362195974Sjamie#endif 1363195974Sjamie 1364195974Sjamie xb = getobuf(); 1365195974Sjamie while ((c = *ib->cptr)) { 1366195974Sjamie switch (t = getyp(ib->cptr)) { 1367195974Sjamie case CMNT: 1368195974Sjamie xb->cptr = xb->buf; 1369195974Sjamie ib->cptr = fcmnt(ib->cptr, xb); 1370195974Sjamie *xb->cptr = 0; 1371195974Sjamie savstr(xb->buf); 1372195974Sjamie continue; 1373195974Sjamie case NUMBER: 1374195974Sjamie xb->cptr = xb->buf; 1375195974Sjamie ib->cptr = fstrnum(ib->cptr, xb); 1376195974Sjamie *xb->cptr = 0; 1377195974Sjamie savstr(xb->buf); 1378195974Sjamie continue; 1379195974Sjamie case STRING: 1380195974Sjamie xb->cptr = xb->buf; 1381192895Sjamie ib->cptr = fstrstr(ib->cptr,xb); 1382192895Sjamie *xb->cptr = 0; 1383192895Sjamie for (cp = xb->buf; *cp; cp++) { 1384192895Sjamie if (*cp <= BLKID) { 1385192895Sjamie if (*cp == BLKID) 1386192895Sjamie cp++; 1387192895Sjamie continue; 1388195974Sjamie } 1389195974Sjamie savch(*cp); 1390195945Sjamie } 1391195974Sjamie continue; 1392195974Sjamie case BLKID: 1393195974Sjamie l = ib->cptr[1]; 1394195945Sjamie ib->cptr+=2; 1395195974Sjamie /* FALLTHROUGH */ 1396195974Sjamie case IDENT: 1397195945Sjamie if (t != BLKID) 1398195974Sjamie l = 0; 1399195945Sjamie /* 1400195974Sjamie * Tricky: if this is the last identifier 1401192895Sjamie * in the expanded list, and it is defined 1402195974Sjamie * as a function-like macro, then push it 1403195974Sjamie * back on the input stream and let fastscan 1404195974Sjamie * handle it as a new macro. 1405195974Sjamie * BUT: if this macro is blocked then this 1406195974Sjamie * should not be done. 1407195974Sjamie */ 1408195974Sjamie for (cp = ib->cptr; ISID(*ib->cptr); ib->cptr++) 1409195974Sjamie ; 1410195974Sjamie if ((sp = lookup(cp, FIND)) == NULL) { 1411195974Sjamiesstr: for (; cp < ib->cptr; cp++) 1412195974Sjamie savch(*cp); 1413195974Sjamie continue; 1414195974Sjamie } 1415195974Sjamie if (expok(sp, l) == 0) { 1416192895Sjamie /* blocked */ 1417192895Sjamie goto sstr; 1418191673Sjamie } else { 1419192895Sjamie if (*sp->value != OBJCT) { 1420191673Sjamie cp = ib->cptr; 1421192895Sjamie while (ISWS(*ib->cptr)) 1422192895Sjamie ib->cptr++; 1423191673Sjamie if (*ib->cptr == 0) { 1424191673Sjamie bufree(xb); 1425191673Sjamie return sp; 1426196835Sjamie } 1427196835Sjamie ib->cptr = cp; 1428191673Sjamie } 1429196835Sjamienewmac: if ((xob = submac(sp, 1, ib, NULL)) == NULL) { 1430196835Sjamie savstr(sp->namep); 1431192895Sjamie } else { 1432191673Sjamie sp = loopover(xob); 1433191673Sjamie bufree(xob); 1434192895Sjamie if (sp != NULL) 1435192895Sjamie goto newmac; 1436191673Sjamie } 1437192895Sjamie } 1438192895Sjamie continue; 1439192895Sjamie default: 1440192895Sjamie savch(c); 1441192895Sjamie } 1442192895Sjamie 1443192895Sjamie ib->cptr++; 1444192895Sjamie } 1445192895Sjamie 1446192895Sjamie bufree(xb); 1447192895Sjamie DPRINT(("loopover return 0\n")); 1448192895Sjamie return 0; 1449192895Sjamie} 1450191673Sjamie 1451192895Sjamie/* 1452192895Sjamie * Handle defined macro keywords found on input stream. 1453192895Sjamie * When finished print out the full expanded line. 1454192895Sjamie * Input here is from the lex buffer. 1455185435Sbz * Return 1 if success, 0 otherwise. fastscan restores stringbuf. 1456191673Sjamie * Scanned data is stored on heap. Last scan prints out the buffer. 1457191673Sjamie */ 1458192895Sjamieint 1459195974Sjamiekfind(struct symtab *sp) 1460195974Sjamie{ 1461195974Sjamie extern int inexpr; 1462195974Sjamie struct blocker *bl; 1463195974Sjamie struct iobuf *ib, *ob; 1464195974Sjamie const usch *argary[MAXARGS+1], *sbp; 1465192895Sjamie int c, n = 0; 1466195945Sjamie 1467195945Sjamie blkidp = 1; 1468195945Sjamie sbp = stringbuf; 1469195945Sjamie DPRINT(("%d:enter kfind(%s)\n",0,sp->namep)); 1470195945Sjamie switch (*sp->value) { 1471195945Sjamie case FILLOC: 1472192895Sjamie unfname(); 1473192895Sjamie return 1; 1474192895Sjamie 1475192895Sjamie case LINLOC: 1476192895Sjamie sheap("%d", ifiles->lineno); 1477185435Sbz return 1; 1478191673Sjamie 1479191673Sjamie case PRAGLOC: 1480192895Sjamie pragoper(NULL); 1481195974Sjamie return 1; 1482195974Sjamie 1483195974Sjamie case DEFLOC: 1484195974Sjamie case OBJCT: 1485195974Sjamie bl = blkget(sp, NULL); 1486195974Sjamie ib = mkrobuf(sp->value+1); 1487192895Sjamie ob = getobuf(); 1488195945Sjamie ob = exparg(1, ib, ob, bl); 1489195945Sjamie bufree(ib); 1490195945Sjamie break; 1491195945Sjamie 1492195945Sjamie case CTRLOC: 1493195945Sjamie sheap("%d", counter++); 1494192895Sjamie return 1; 1495192895Sjamie 1496192895Sjamie default: 1497192895Sjamie /* Search for '(' */ 1498192895Sjamie while (ISWSNL(c = cinput())) 1499191673Sjamie if (c == '\n') 1500191673Sjamie n++; 1501192895Sjamie if (c != '(') { 1502191673Sjamie if (inexpr == 0) 1503192895Sjamie putstr(sp->namep); 1504192895Sjamie if (n == 0) 1505192895Sjamie putch(' '); 1506192895Sjamie else for (ifiles->lineno += n; n; n--) 1507192895Sjamie putch('\n'); 1508194762Sjamie cunput(c); 1509194762Sjamie return 0; /* Failed */ 1510194762Sjamie } 1511194762Sjamie 1512194762Sjamie /* fetch arguments */ 1513194762Sjamieagain: if (readargs1(sp, argary)) 1514194762Sjamie error("readargs"); 1515194762Sjamie 1516192895Sjamie bl = blkget(sp, NULL); 1517192895Sjamie ib = subarg(sp, argary, 1, bl); 1518192895Sjamie ob = getobuf(); 1519192895Sjamie ob = exparg(1, ib, ob, bl); 1520192895Sjamie bufree(ib); 1521192895Sjamie break; 1522192895Sjamie } 1523192895Sjamie 1524192895Sjamie /* 1525192895Sjamie * Loop over stringbuf, output the data and remove remaining 1526192895Sjamie * directives. Start with extracting the last keyword (if any). 1527192895Sjamie */ 1528192895Sjamie putob(ob, 0); /* XXX needed? */ 1529192895Sjamie 1530192895Sjamie stringbuf = (usch *)sbp; /* XXX should check cleanup */ 1531192895Sjamie if ((sp = loopover(ob))) { 1532192895Sjamie /* Search for '(' */ 1533192895Sjamie while (ISWSNL(c = cinput())) 1534192895Sjamie if (c == '\n') 1535192895Sjamie n++; 1536191673Sjamie if (c == '(') { 1537192895Sjamie bufree(ob); 1538192895Sjamie goto again; 1539192895Sjamie } 1540192895Sjamie cunput(c); 1541192895Sjamie savstr(sp->namep); 1542192895Sjamie } 1543191673Sjamie bufree(ob); 1544191673Sjamie 1545193066Sjamie for (ifiles->lineno += n; n; n--) 1546193066Sjamie savch('\n'); 1547193066Sjamie savch(0); 1548193066Sjamie stringbuf = (usch *)sbp; 1549193066Sjamie if (nbufused) 1550193066Sjamie error("lost buffer"); 1551193066Sjamie return 1; 1552193066Sjamie} 1553194118Sjamie 1554194118Sjamie/* 1555194118Sjamie * Replace and push-back on input stream the eventual replaced macro. 1556194118Sjamie * The check for whether it can expand or not should already have been done. 1557194118Sjamie * Blocks for this identifier will be added via insblock() after expansion. 1558194118Sjamie * The same as kfind but read a string. 1559193066Sjamie */ 1560193066Sjamiestruct iobuf * 1561193066Sjamiesubmac(struct symtab *sp, int lvl, struct iobuf *ib, struct blocker *obl) 1562193066Sjamie{ 1563193066Sjamie struct blocker *bl; 1564194118Sjamie struct iobuf *ob; 1565193066Sjamie const usch *argary[MAXARGS+1]; 1566194118Sjamie usch *cp, *pr; 1567194118Sjamie 1568193066Sjamie DPRINT(("%d:submac: trying '%s'\n", lvl, sp->namep)); 1569194118Sjamie switch (*sp->value) { 1570193066Sjamie case FILLOC: 1571193066Sjamie ob = strtobuf(unfname(), NULL); 1572193066Sjamie break; 1573193066Sjamie case LINLOC: 1574193066Sjamie ob = strtobuf(sheap("%d", ifiles->lineno), NULL); 1575193066Sjamie break; 1576193066Sjamie case PRAGLOC: 1577194118Sjamie pragoper(ib); 1578194118Sjamie ob = strtobuf((usch *)"", NULL); 1579194118Sjamie break; 1580193066Sjamie case OBJCT: 1581194118Sjamie bl = blkget(sp, obl); 1582194118Sjamie ib = mkrobuf(sp->value+1); 1583194118Sjamie ob = getobuf(); 1584193066Sjamie DPRINT(("%d:submac: calling exparg\n", lvl)); 1585194118Sjamie ob = exparg(lvl+1, ib, ob, bl); 1586194118Sjamie bufree(ib); 1587194118Sjamie DPRINT(("%d:submac: return exparg\n", lvl)); 1588193066Sjamie break; 1589193066Sjamie case CTRLOC: 1590193066Sjamie ob = strtobuf(sheap("%d", counter++), NULL); 1591193066Sjamie break; 1592193066Sjamie default: 1593192895Sjamie cp = ib->cptr; 1594192895Sjamie while (ISWSNL(*ib->cptr)) 1595192895Sjamie ib->cptr++; 1596192895Sjamie if (*ib->cptr != '(') { 1597192895Sjamie ib->cptr = cp; 1598192895Sjamie return 0; 1599191673Sjamie } 1600191673Sjamie cp = ib->cptr++; 1601191673Sjamie pr = stringbuf; 1602191673Sjamie if (readargs2(&ib->cptr, sp, argary)) { 1603191673Sjamie /* Bailed out in the middle of arg list */ 1604191673Sjamie ib->cptr = cp; /* XXX */ 1605191673Sjamie return 0; 1606191673Sjamie } 1607191673Sjamie bl = blkget(sp, obl); 1608191673Sjamie ib = subarg(sp, argary, lvl+1, bl); 1609191673Sjamie stringbuf = pr; 1610191673Sjamie 1611191673Sjamie ob = getobuf(); 1612191673Sjamie DPRINT(("%d:submac(: calling exparg\n", lvl)); 1613191673Sjamie ob = exparg(lvl+1, ib, ob, bl); 1614191673Sjamie bufree(ib); 1615191673Sjamie DPRINT(("%d:submac(: return exparg\n", lvl)); 1616185435Sbz break; 1617192895Sjamie } 1618192895Sjamie putob(ob, 0); 1619192895Sjamie ob->cptr--; 1620192895Sjamie 1621192895Sjamie return ob; 1622192895Sjamie} 1623192895Sjamie 1624192895Sjamiestatic int 1625192895Sjamieisdir(void) 1626192895Sjamie{ 1627195945Sjamie usch ch; 1628195945Sjamie 1629195945Sjamie while ((ch = cinput()) == ' ' || ch == '\t') 1630195945Sjamie ; 1631195945Sjamie if (ch == '#') 1632195945Sjamie return 1; 1633192895Sjamie cunput(ch); 1634192895Sjamie return 0; 1635192895Sjamie} 1636192895Sjamie 1637192895Sjamie/* 1638192895Sjamie * Deal with directives inside a macro. 1639192895Sjamie * Doing so is really ugly but gcc allows it, so... 1640192895Sjamie */ 1641192895Sjamiestatic void 1642192895Sjamiechkdir(void) 1643192895Sjamie{ 1644192895Sjamie usch ch; 1645192895Sjamie 1646192895Sjamie for (;;) { 1647192895Sjamie if (isdir()) { 1648192895Sjamie#ifndef GCC_COMPAT 1649192895Sjamie warning("conditionals inside macro arg list"); 1650195945Sjamie#endif 1651195945Sjamie ppdir(); 1652195945Sjamie } 1653195945Sjamie if (flslvl == 0) 1654195945Sjamie return; 1655195945Sjamie while ((ch = cinput()) != '\n') 1656192895Sjamie ; 1657192895Sjamie ifiles->lineno++; 1658192895Sjamie putch('\n'); 1659192895Sjamie } 1660192895Sjamie} 1661192895Sjamie 1662192895Sjamiestatic int 1663192895Sjamiera1_wsnl(int sp) 1664192895Sjamie{ 1665192895Sjamie int c; 1666192895Sjamie 1667191673Sjamie while (ISWSNL(c = cinput())) { 1668191673Sjamie if (c == '\n') { 1669191673Sjamie putch('\n'); 1670191673Sjamie chkdir(); 1671191673Sjamie ifiles->lineno++; 1672191673Sjamie if (sp) savch(' '); 1673191673Sjamie } 1674191673Sjamie } 1675191673Sjamie return c; 1676191673Sjamie} 1677191673Sjamie 1678191673Sjamie/* 1679191673Sjamie * Read arguments and put in argument array. 1680191673Sjamie * If EOF is encountered return 1, otherwise 0. 1681191673Sjamie */ 1682191673Sjamieint 1683191673Sjamiereadargs1(struct symtab *sp, const usch **args) 1684191673Sjamie{ 1685191673Sjamie const usch *vp = sp->value; 1686191673Sjamie int c, i, plev, narg, ellips = 0; 1687191673Sjamie 1688191673Sjamie DPRINT(("readargs1\n")); 1689191673Sjamie narg = *vp++; 1690191673Sjamie if (narg == VARG) { 1691191673Sjamie narg = *vp++; 1692191673Sjamie ellips = 1; 1693191673Sjamie } 1694191673Sjamie#ifdef PCC_DEBUG 1695191673Sjamie if (dflag > 1) { 1696191673Sjamie printf("narg %d varg %d: ", narg, ellips); 1697191673Sjamie prrep(vp); 1698191673Sjamie printf("\n"); 1699191673Sjamie } 1700191673Sjamie#endif 1701191673Sjamie 1702191673Sjamie /* 1703191673Sjamie * read arguments and store them on heap. 1704191673Sjamie */ 1705191673Sjamie c = '('; 1706191673Sjamie for (i = 0; i < narg && c != ')'; i++) { 1707191673Sjamie args[i] = stringbuf; 1708191673Sjamie plev = 0; 1709191673Sjamie 1710191673Sjamie c = ra1_wsnl(0); 1711191673Sjamie for (;;) { 1712191673Sjamie if (plev == 0 && (c == ')' || c == ',')) 1713191673Sjamie break; 1714191673Sjamie if (c == '(') plev++; 1715191673Sjamie if (c == ')') plev--; 1716191673Sjamie if (c == 0) 1717191673Sjamie error("eof in macro"); 1718191673Sjamie else if (c == '/') Ccmnt(savch); 1719192895Sjamie else if (c == '\"' || c == '\'') faststr(c, savch); 1720192895Sjamie else if (ISID0(c)) { 1721192895Sjamie usch *bp = stringbuf; 1722192895Sjamie do { 1723192895Sjamie savch(c); 1724191673Sjamie } while ((spechr[c = cinput()] & C_ID)); 1725191673Sjamie if ((sp = lookup(bp, FIND)) != NULL) { 1726191673Sjamie if (sp == linloc) { 1727191673Sjamie stringbuf = bp; 1728191673Sjamie sheap("%d", ifiles->lineno); 1729191673Sjamie } else if (sp == ctrloc) { 1730191673Sjamie stringbuf = bp; 1731191673Sjamie sheap("%d", counter++); 1732191673Sjamie } 1733191673Sjamie } 1734191673Sjamie cunput(c); 1735191673Sjamie } else 1736191673Sjamie savch(c); 1737191673Sjamie if ((c = cinput()) == '\n') { 1738191673Sjamie chkdir(); 1739191673Sjamie ifiles->lineno++, putch(c), c = ' '; 1740191673Sjamie } 1741191673Sjamie } 1742191673Sjamie 1743191673Sjamie while (args[i] < stringbuf && ISWSNL(stringbuf[-1])) 1744191673Sjamie stringbuf--; 1745191673Sjamie savch('\0'); 1746191673Sjamie#ifdef PCC_DEBUG 1747191673Sjamie if (dflag) { 1748191673Sjamie printf("readargs: save arg %d '", i); 1749191673Sjamie prline(args[i]); 1750191673Sjamie printf("'\n"); 1751191673Sjamie } 1752191673Sjamie#endif 1753191673Sjamie } 1754191673Sjamie 1755191673Sjamie /* Handle varargs readin */ 1756191673Sjamie if (ellips) 1757191673Sjamie args[i] = (const usch *)""; 1758191673Sjamie if (ellips && c != ')') { 1759191673Sjamie args[i] = stringbuf; 1760191673Sjamie plev = 0; 176182710Sdillon c = ra1_wsnl(0); 1762191673Sjamie for (;;) { 1763191673Sjamie if (plev == 0 && c == ')') 1764191673Sjamie break; 1765191673Sjamie if (c == '(') plev++; 1766114168Smike if (c == ')') plev--; 176782710Sdillon if (c == '\"' || c == '\'') faststr(c, savch); 176846155Sphk else 1769191673Sjamie savch(c); 177046155Sphk if ((c = cinput()) == '\n') 1771191673Sjamie ifiles->lineno++, c = ' '; 1772185435Sbz } 1773185435Sbz while (args[i] < stringbuf && ISWSNL(stringbuf[-1])) 1774191673Sjamie stringbuf--; 1775191673Sjamie savch('\0'); 1776191673Sjamie#ifdef PCC_DEBUG 1777191673Sjamie if (dflag) { 1778191673Sjamie printf("readargs: vararg arg %d '", i); 1779185435Sbz prline(args[i]); 1780185435Sbz printf("'\n"); 1781191673Sjamie } 1782191673Sjamie#endif 1783191673Sjamie 1784191673Sjamie } 1785191673Sjamie if (narg == 0 && ellips == 0) 1786191673Sjamie c = ra1_wsnl(0); 1787191673Sjamie 1788185435Sbz if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) 1789191673Sjamie error("wrong arg count"); 1790191673Sjamie return 0; 1791191673Sjamie} 1792192895Sjamie 1793191673Sjamiestatic usch *raptr; 1794191673Sjamiestatic int 1795191673Sjamieraread(void) 1796192895Sjamie{ 1797185435Sbz int rv; 1798191673Sjamie 1799191673Sjamie if (raptr) { 1800185435Sbz if ((rv = *raptr)) 1801191673Sjamie raptr++; 1802191673Sjamie } else 1803191673Sjamie rv = cinput(); 1804191673Sjamie return rv; 1805191673Sjamie} 1806192895Sjamie 1807185435Sbz 1808191673Sjamie/* 1809191673Sjamie * Read arguments and put in argument array. 1810191673Sjamie * If EOF is encountered return 1, otherwise 0. 1811191673Sjamie */ 1812191673Sjamieint 1813191673Sjamiereadargs2(usch **inp, struct symtab *sp, const usch **args) 1814191673Sjamie{ 1815192895Sjamie const usch *vp = sp->value; 1816191673Sjamie usch *bp; 1817191673Sjamie int c, i, plev, narg, ellips = 0; 1818191673Sjamie 1819191673Sjamie DPRINT(("readargs2 %s '", sp->namep)); 1820191673Sjamie#ifdef PCC_DEBUG 1821191673Sjamie if (dflag && inp) { 1822191673Sjamie prline(*inp); 1823191673Sjamie printf("'\n"); 1824191673Sjamie } 1825191673Sjamie#endif 1826191673Sjamie raptr = inp ? *inp : 0; 1827191673Sjamie narg = *vp++; 1828191673Sjamie if (narg == VARG) { 1829191673Sjamie narg = *vp++; 1830185435Sbz ellips = 1; 1831191673Sjamie } 1832191673Sjamie#ifdef PCC_DEBUG 1833191673Sjamie if (dflag > 1) { 1834192895Sjamie prrep(vp); 1835191673Sjamie printf("\n"); 1836191673Sjamie } 1837191673Sjamie#endif 1838191673Sjamie 1839191673Sjamie 1840191673Sjamie /* 1841191673Sjamie * read arguments and store them on heap. 1842191673Sjamie */ 1843191673Sjamie c = '('; 1844191673Sjamie for (i = 0; i < narg && c != ')'; i++) { 1845191673Sjamie args[i] = stringbuf; 1846191673Sjamie plev = 0; 1847191673Sjamie 1848191673Sjamie while ((c = raread()) == ' ' || c == '\t') 1849191673Sjamie ; 1850191673Sjamie for (;;) { 185146155Sphk if (plev == 0 && (c == ')' || c == ',')) 1852191673Sjamie break; 1853191673Sjamie if (c == '(') plev++; 1854191673Sjamie if (c == ')') plev--; 1855191673Sjamie if (c == 0) { 1856191673Sjamie if (raptr) { 1857191673Sjamie *inp = raptr; 1858192895Sjamie raptr = 0; 1859191673Sjamie } else 1860191673Sjamie error("eof in macro"); 1861191673Sjamie } else if (c == BLKID) { 1862191673Sjamie savch(c), savch(raread()); 1863191673Sjamie } else if (c == '/') { 1864191673Sjamie if ((c = raread()) == '*') 1865191673Sjamie error("FIXME ccmnt"); 1866191673Sjamie savch('/'); 1867191673Sjamie continue; 1868191673Sjamie } else if (c == '\"' || c == '\'') { 1869191673Sjamie if (raptr) { 1870191673Sjamie struct iobuf *xob = getobuf(); 1871191673Sjamie raptr = fstrstr(raptr-1, xob); 1872191673Sjamie *xob->cptr = 0; 1873191673Sjamie savstr(xob->buf); 1874185435Sbz bufree(xob); 1875191673Sjamie } else 1876191673Sjamie faststr(c, savch); 1877191673Sjamie } else if (ISID0(c)) { 1878191673Sjamie bp = stringbuf; 1879191673Sjamie do { 1880191673Sjamie savch(c); 1881191673Sjamie } while (ISID(c = raread())); 1882191673Sjamie *stringbuf = 0; 1883191673Sjamie if ((sp = lookup(bp, FIND)) && (sp == linloc)) { 1884191673Sjamie stringbuf = bp; 1885191673Sjamie sheap("%d", ifiles->lineno); 1886191673Sjamie } 1887192895Sjamie continue; 1888192895Sjamie } else 1889191673Sjamie savch(c); 1890191673Sjamie c = raread(); 1891192895Sjamie } 1892192895Sjamie 1893192895Sjamie while (args[i] < stringbuf && ISWSNL(stringbuf[-1])) 1894192895Sjamie stringbuf--; 1895191673Sjamie savch('\0'); 1896191673Sjamie#ifdef PCC_DEBUG 1897191673Sjamie if (dflag) { 1898192895Sjamie printf("readargs2: save arg %d '", i); 1899191673Sjamie prline(args[i]); 1900191673Sjamie printf("'\n"); 1901191673Sjamie } 1902191673Sjamie#endif 1903191673Sjamie } 1904191673Sjamie 1905191673Sjamie /* Handle varargs readin */ 1906191673Sjamie if (ellips) 1907191673Sjamie args[i] = (const usch *)""; 1908191673Sjamie if (ellips && c != ')') { 1909191673Sjamie args[i] = stringbuf; 1910191673Sjamie plev = 0; 1911191673Sjamie while ((c = raread()) == ' ' || c == '\t') 1912191673Sjamie ; 1913191673Sjamie for (;;) { 1914191673Sjamie if (plev == 0 && c == ')') 1915191673Sjamie break; 1916191673Sjamie if (c == '(') plev++; 1917194762Sjamie if (c == ')') plev--; 1918194762Sjamie if (c == '\"' || c == '\'') { 1919194762Sjamie if (raptr) { 1920194762Sjamie struct iobuf *xob = getobuf(); 1921194762Sjamie raptr = fstrstr(raptr-1, xob); 1922194762Sjamie *xob->cptr = 0; 1923194762Sjamie savstr(xob->buf); 1924194762Sjamie bufree(xob); 1925194118Sjamie } else 1926191673Sjamie faststr(c, savch); 1927191673Sjamie } else 1928194118Sjamie savch(c); 1929193066Sjamie c = raread(); 1930193066Sjamie } 1931194118Sjamie while (args[i] < stringbuf && ISWSNL(stringbuf[-1])) 1932193066Sjamie stringbuf--; 1933193066Sjamie savch('\0'); 1934193066Sjamie 1935193066Sjamie } 1936193066Sjamie if (narg == 0 && ellips == 0) { 1937193066Sjamie while ((c = raread()) == ' ' || c == '\t') 1938193066Sjamie ; 1939193066Sjamie } 1940193066Sjamie 1941193066Sjamie if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) 1942193066Sjamie error("wrong arg count"); 1943193066Sjamie if (raptr) 1944193066Sjamie *inp = raptr; 1945192895Sjamie return 0; 1946192895Sjamie} 1947191673Sjamie 1948191673Sjamie/* 1949192895Sjamie * expand a function-like macro. 1950192895Sjamie * vp points to end of replacement-list 1951192895Sjamie * reads function arguments from input stream. 1952192895Sjamie * result is pushed-back for more scanning. 1953192895Sjamie */ 1954192895Sjamiestruct iobuf * 1955192895Sjamiesubarg(struct symtab *nl, const usch **args, int lvl, struct blocker *bl) 1956192895Sjamie{ 1957192895Sjamie struct blocker *w; 1958192895Sjamie struct iobuf *ob, *cb, *nb; 1959192895Sjamie int narg, instr, snuff; 1960192895Sjamie const usch *sp, *bp, *ap, *vp, *tp; 1961192895Sjamie 1962195870Sjamie DPRINT(("%d:subarg '%s'\n", lvl, nl->namep)); 1963195870Sjamie ob = getobuf(); 1964195870Sjamie vp = nl->value; 1965195870Sjamie narg = *vp++; 1966195870Sjamie if (narg == VARG) 1967195870Sjamie narg = *vp++; 1968195870Sjamie 1969195870Sjamie sp = vp; 1970195870Sjamie instr = snuff = 0; 1971195870Sjamie#ifdef PCC_DEBUG 1972195870Sjamie if (dflag>1) { 1973195870Sjamie printf("%d:subarg ARGlist for %s: '", lvl, nl->namep); 1974195870Sjamie prrep(vp); 1975192895Sjamie printf("' "); 1976192895Sjamie for (w = bl; w; w = w->next) 1977192895Sjamie printf("%s ", w->sp->namep); 1978192895Sjamie printf("\n"); 1979192895Sjamie } 1980192895Sjamie#endif 1981192895Sjamie 1982192895Sjamie /* 1983192895Sjamie * walk forward over replacement-list while replacing 1984192895Sjamie * arguments. Arguments are macro-expanded if required. 1985192895Sjamie */ 1986192895Sjamie while (*sp) { 1987192895Sjamie if (*sp == SNUFF) 1988191673Sjamie putob(ob, '\"'), snuff ^= 1; 1989191673Sjamie else if (*sp == CONC) 1990191673Sjamie ; 1991191673Sjamie else if (*sp == WARN) { 1992191673Sjamie 1993191673Sjamie if (sp[1] == VARG) { 1994191673Sjamie bp = ap = args[narg]; 1995191673Sjamie sp++; 1996191673Sjamie#ifdef GCC_COMPAT 1997191673Sjamie } else if (sp[1] == GCCARG) { 1998191673Sjamie /* XXX remove last , not add 0 */ 1999191673Sjamie ap = args[narg]; 2000191673Sjamie if (ap[0] == 0) 200146155Sphk ap = (const usch *)"0"; 2002191673Sjamie bp = ap; 2003191673Sjamie sp++; 200484828Sjhb#endif 2005191673Sjamie } else 2006191673Sjamie bp = ap = args[(int)*++sp]; 2007191673Sjamie#ifdef PCC_DEBUG 2008191673Sjamie if (dflag>1){ 2009191673Sjamie printf("%d:subarg GOTwarn; arglist '", lvl); 2010191673Sjamie prline(bp); 2011191673Sjamie printf("'\n"); 2012185435Sbz } 2013191673Sjamie#endif 2014191673Sjamie if (sp[-2] != CONC && !snuff && sp[1] != CONC) { 2015191673Sjamie /* 2016191673Sjamie * Expand an argument; 6.10.3.1: 2017191673Sjamie * "A parameter in the replacement list, 2018191673Sjamie * is replaced by the corresponding argument 2019191673Sjamie * after all macros contained therein have 2020191673Sjamie * been expanded.". 2021191673Sjamie */ 2022191673Sjamie w = bl ? bl->next : NULL; 2023191673Sjamie cb = mkrobuf(bp); 2024191673Sjamie nb = getobuf(); 2025191673Sjamie DPRINT(("%d:subarg: calling exparg\n", lvl)); 2026191673Sjamie nb = exparg(lvl+1, cb, nb, w); 2027191673Sjamie DPRINT(("%d:subarg: return exparg\n", lvl)); 2028191673Sjamie bufree(cb); 2029191673Sjamie strtobuf(nb->buf, ob); 2030191673Sjamie bufree(nb); 2031191673Sjamie } else { 2032191673Sjamie while (*bp) { 2033191673Sjamie if (snuff && !instr && ISWS(*bp)) { 2034185435Sbz while (ISWS(*bp)) 2035191673Sjamie bp++; 2036191673Sjamie putob(ob, ' '); 2037191673Sjamie } 2038191673Sjamie 2039191673Sjamie if (snuff && 2040191673Sjamie (*bp == '\'' || *bp == '"')) { 2041191673Sjamie instr ^= 1; 2042191673Sjamie for (tp = bp - 1; *tp == '\\'; tp--) 2043191673Sjamie instr ^= 1; 2044191673Sjamie if (*bp == '"') 2045191673Sjamie putob(ob, '\\'); 2046191673Sjamie } 2047191673Sjamie if (snuff && instr && *bp == '\\') 2048191673Sjamie putob(ob, '\\'); 2049191673Sjamie putob(ob, *bp); 2050191673Sjamie bp++; 2051191673Sjamie } 2052191673Sjamie } 2053191673Sjamie } else if (ISID0(*sp)) { 2054191673Sjamie if (lookup(sp, FIND)) 2055191673Sjamie storeblk(blkix(bl), ob); 2056191673Sjamie while (ISID(*sp)) 2057185435Sbz putob(ob, *sp++); 2058191673Sjamie sp--; 2059191673Sjamie } else 2060191673Sjamie putob(ob, *sp); 2061113275Smike sp++; 2062192895Sjamie } 2063191673Sjamie putob(ob, 0); 2064191673Sjamie ob->cptr = ob->buf; 2065191673Sjamie DPRINT(("%d:subarg retline %s\n", lvl, ob->buf)); 2066191673Sjamie return ob; 2067191673Sjamie} 2068191673Sjamie 2069191673Sjamie/* 2070191673Sjamie * Do a (correct) expansion of a WARN-terminated buffer of tokens. 2071192895Sjamie * Data is read from the lex buffer, result on lex buffer, WARN-terminated. 2072192895Sjamie * Expansion blocking is not altered here unless when tokens are 2073185435Sbz * concatenated, in which case they are removed. 2074191673Sjamie */ 2075185435Sbzstruct iobuf * 2076191673Sjamieexparg(int lvl, struct iobuf *ib, struct iobuf *ob, struct blocker *bl) 2077185435Sbz{ 2078185435Sbz extern int inexpr; 2079192895Sjamie struct iobuf *nob; 2080191673Sjamie struct symtab *nl; 2081185435Sbz int c, m; 2082191673Sjamie usch *cp, *bp, *sbp; 2083185435Sbz 2084185435Sbz DPRINT(("%d:exparg: entry ib %s\n", lvl, ib->cptr)); 2085192895Sjamie#ifdef PCC_DEBUG 2086192895Sjamie if (dflag > 1) { 2087192895Sjamie printf("exparg entry: full "); 2088192895Sjamie prline(ib->cptr); 2089192895Sjamie printf("\n"); 2090192895Sjamie } 2091192895Sjamie#endif 2092192895Sjamie 2093192895Sjamie while ((c = getyp(ib->cptr)) != 0) { 2094192895Sjamie ib->cptr++; 2095192895Sjamie 2096192895Sjamie switch (c) { 2097192895Sjamie 2098192895Sjamie case CMNT: 2099192895Sjamie ib->cptr = fcmnt(ib->cptr-1, ob); 2100192895Sjamie break; 2101192895Sjamie case NUMBER: 2102192895Sjamie ib->cptr = fstrnum(ib->cptr-1, ob); 2103192895Sjamie break; 2104192895Sjamie case STRING: 2105192895Sjamie ib->cptr = fstrstr(ib->cptr-1, ob); 2106192895Sjamie break; 2107192895Sjamie case BLKID: 2108192895Sjamie m = *ib->cptr++; 2109192895Sjamie ib->cptr++; 2110192895Sjamie /* FALLTHROUGH */ 2111192895Sjamie case IDENT: 2112192895Sjamie if (c != BLKID) 2113192895Sjamie m = 0; 2114192895Sjamie for (cp = ib->cptr-1; ISID(*cp); cp++) 2115192895Sjamie ; 2116192895Sjamie#ifdef PCC_DEBUG 2117192895Sjamieif (dflag) { printf("!! ident "); prline(ib->cptr-1); printf("\n"); } 2118192895Sjamie#endif 2119192895Sjamie sbp = stringbuf; 2120192895Sjamie if (*cp == BLKID) { 2121192895Sjamie /* concatenation */ 2122192895Sjamie bp = stringbuf; 2123192895Sjamie for (cp = ib->cptr-1; 2124192895Sjamie ISID(*cp) || *cp == BLKID; cp++) { 2125192895Sjamie if (*cp == BLKID) { 2126191673Sjamie /* XXX add to block list */ 2127191673Sjamie cp++; 2128191673Sjamie } else 2129191673Sjamie savch(*cp); 2130191673Sjamie } 2131191673Sjamie ib->cptr = cp; 2132179881Sdelphij cp = stringbuf; 2133113275Smike savch(0); 2134192895Sjamie } else { 2135192895Sjamie bp = ib->cptr-1; 2136192895Sjamie ib->cptr = cp; 2137192895Sjamie } 2138192895Sjamie#ifdef PCC_DEBUG 2139192895Sjamieif (dflag) { printf("!! ident2 "); prline(bp); printf("\n"); } 2140192895Sjamie#endif 2141191673Sjamie if ((nl = lookup(bp, FIND)) == NULL) { 2142191673Sjamiesstr: for (; bp < cp; bp++) 2143192895Sjamie putob(ob, *bp); 2144191673Sjamie stringbuf = sbp; 2145191673Sjamie break; 2146113275Smike } else if (inexpr && *nl->value == DEFLOC) { 2147191673Sjamie int gotlp = 0; 2148191673Sjamie while (ISWS(*ib->cptr)) ib->cptr++; 2149191673Sjamie if (*ib->cptr == '(') 2150191673Sjamie gotlp++, ib->cptr++; 2151191673Sjamie while (ISWS(*ib->cptr)) ib->cptr++; 2152191673Sjamie if (!ISID0(*ib->cptr)) 2153191673Sjamie error("bad defined"); 2154191673Sjamie putob(ob, lookup(ib->cptr, FIND) ? '1' : '0'); 2155191673Sjamie while (ISID(*ib->cptr)) ib->cptr++; 2156191673Sjamie while (ISWS(*ib->cptr)) ib->cptr++; 2157191673Sjamie if (gotlp && *ib->cptr != ')') 2158191673Sjamie error("bad defined"); 2159191673Sjamie ib->cptr++; 2160192895Sjamie break; 2161191673Sjamie } 2162113275Smike stringbuf = sbp; 2163113275Smike if (expokb(nl, bl) && expok(nl, m)) { 2164190466Sjamie if ((nob = submac(nl, lvl+1, ib, bl))) { 2165113275Smike if (nob->buf[0] == '-' || 2166114168Smike nob->buf[0] == '+') 2167114168Smike putob(ob, ' '); 2168114168Smike strtobuf(nob->buf, ob); 2169113275Smike if (ob->cptr[-1] == '-' || 2170113275Smike ob->cptr[-1] == '+') 2171114168Smike putob(ob, ' '); 2172113275Smike bufree(nob); 2173113275Smike } else { 2174191673Sjamie goto sblk; 2175167309Spjd } 2176164032Srwatson } else { 2177126023Snectar /* blocked */ 2178126023Snectarsblk: storeblk(blkix(mergeadd(bl, m)), ob); 2179126023Snectar goto sstr; 2180168401Spjd } 2181192895Sjamie break; 2182113275Smike 2183168401Spjd default: 2184113275Smike putob(ob, c); 2185113275Smike break; 2186185435Sbz } 2187185435Sbz } 2188185435Sbz putob(ob, 0); 2189191673Sjamie ob->cptr--; 2190185435Sbz DPRINT(("%d:exparg return: ob %s\n", lvl, ob->buf)); 2191191673Sjamie#ifdef PCC_DEBUG 2192185435Sbz if (dflag > 1) { 2193185435Sbz printf("%d:exparg: full ", lvl); 2194185435Sbz prline(ob->buf); 2195185435Sbz printf("\n"); 2196191673Sjamie } 2197191673Sjamie#endif 2198191673Sjamie return ob; 2199191673Sjamie} 2200191673Sjamie 2201191673Sjamie#ifdef PCC_DEBUG 2202191673Sjamie 2203192895Sjamiestatic void 2204191673Sjamieprrep(const usch *s) 2205191673Sjamie{ 2206191673Sjamie while (*s) { 2207191673Sjamie switch (*s) { 2208191673Sjamie case WARN: 2209191673Sjamie if (s[1] == VARG) printf("<VARG>"); 2210191673Sjamie else if (s[1] == GCCARG) printf("<GCCARG>"); 2211191673Sjamie else printf("<ARG(%d)>", s[1]); 2212191673Sjamie s++; 2213191673Sjamie break; 2214191673Sjamie case CONC: printf("<CONC>"); break; 2215191673Sjamie case SNUFF: printf("<SNUFF>"); break; 2216113275Smike case BLKID: printf("<BLKID(%d)>",s[1]); s++; break; 2217191673Sjamie default: printf("%c", *s); break; 2218113275Smike } 2219191673Sjamie s++; 2220191673Sjamie } 2221191673Sjamie} 2222191673Sjamie 2223191673Sjamiestatic void 2224191673Sjamieprline(const usch *s) 2225191673Sjamie{ 2226168401Spjd while (*s) { 2227113275Smike switch (*s) { 2228185435Sbz case BLKID: printf("<BLKID(%d)>", *++s); break; 2229185435Sbz case WARN: printf("<WARN>"); break; 2230185435Sbz case CONC: printf("<CONC>"); break; 2231192895Sjamie case SNUFF: printf("<SNUFF>"); break; 2232191673Sjamie case '\n': printf("<NL>"); break; 2233185435Sbz default: 2234185435Sbz if (*s > 0x7f) 2235191673Sjamie printf("<0x%x>", *s); 2236185435Sbz else 2237150652Scsjp printf("%c", *s); 2238175202Sattilio break; 2239113275Smike } 2240113275Smike s++; 2241113275Smike } 2242172930Srwatson} 2243113275Smike#endif 2244113275Smike 2245175294Sattiliousch * 2246191673Sjamiesavstr(const usch *str) 2247191673Sjamie{ 2248150652Scsjp usch *rv = stringbuf; 2249113275Smike 225084828Sjhb do { 225184828Sjhb if (stringbuf >= &sbf[SBSIZE]) 225284828Sjhb error("out of macro space!"); 2253113275Smike } while ((*stringbuf++ = *str++)); 225484828Sjhb stringbuf--; 2255113630Sjhb return rv; 225684828Sjhb} 225784828Sjhb 225884828Sjhbvoid 2259192895Sjamieputch(int ch) 226046155Sphk{ 2261191673Sjamie if (Mflag) 2262175294Sattilio return; 2263191673Sjamie fputc(ch, stdout); 2264150652Scsjp} 2265191673Sjamie 2266191673Sjamievoid 2267192895Sjamieputstr(const usch *s) 2268191673Sjamie{ 226946155Sphk for (; *s; s++) { 227046155Sphk if (Mflag == 0) 227146155Sphk fputc(*s, stdout); 2272192895Sjamie } 2273113275Smike} 2274113275Smike 2275113275Smike/* 2276168399Spjd * convert a number to an ascii string. Store it on the heap. 2277113275Smike */ 2278113275Smikestatic void 2279113275Smikenum2str(int num) 2280113275Smike{ 2281168401Spjd static usch buf[12]; 2282191673Sjamie usch *b = buf; 2283113275Smike int m = 0; 2284113275Smike 2285191673Sjamie if (num < 0) 2286191673Sjamie num = -num, m = 1; 2287191673Sjamie do { 2288113275Smike *b++ = (usch)(num % 10 + '0'); 2289113275Smike num /= 10; 2290113275Smike } while (num); 2291113275Smike if (m) 2292113275Smike *b++ = '-'; 2293191673Sjamie while (b > buf) 2294192895Sjamie savch(*--b); 2295191673Sjamie} 2296191673Sjamie 2297192895Sjamie/* 2298191673Sjamie * similar to sprintf, but only handles %c, %s and %d. 2299192895Sjamie * saves result on heap. 2300192895Sjamie */ 2301192895Sjamiestatic void 2302192895Sjamievsheap(const char *fmt, va_list ap) 2303192895Sjamie{ 2304192895Sjamie for (; *fmt; fmt++) { 2305192895Sjamie if (*fmt == '%') { 2306192895Sjamie fmt++; 2307192895Sjamie switch (*fmt) { 2308192895Sjamie case 's': 2309192895Sjamie savstr(va_arg(ap, usch *)); 2310192895Sjamie break; 2311192895Sjamie case 'd': 2312192895Sjamie num2str(va_arg(ap, int)); 2313192895Sjamie break; 2314192895Sjamie case 'c': 2315192895Sjamie savch(va_arg(ap, int)); 2316192895Sjamie break; 2317192895Sjamie default: 2318192895Sjamie error("bad sheap"); 2319192895Sjamie } 2320191673Sjamie } else 2321192895Sjamie savch(*fmt); 2322192895Sjamie } 2323191673Sjamie *stringbuf = 0; 2324191673Sjamie} 2325192895Sjamie 2326191673Sjamieusch * 2327191673Sjamiesheap(const char *fmt, ...) 2328192895Sjamie{ 2329192895Sjamie va_list ap; 2330191673Sjamie usch *op = stringbuf; 2331191673Sjamie 2332191673Sjamie va_start(ap, fmt); 2333191673Sjamie vsheap(fmt, ap); 2334191673Sjamie va_end(ap); 2335191673Sjamie 2336191673Sjamie return op; 2337191673Sjamie} 2338191673Sjamie 2339192895Sjamiestatic void 2340191673Sjamieusage(void) 2341191673Sjamie{ 2342191673Sjamie error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]"); 2343191673Sjamie} 2344191673Sjamie 2345191673Sjamie#ifdef notyet 2346191673Sjamie/* 2347191673Sjamie * Symbol table stuff. 2348191673Sjamie * The data structure used is a patricia tree implementation using only 2349191673Sjamie * bytes to store offsets. 2350191673Sjamie * The information stored is (lower address to higher): 2351192895Sjamie * 2352192895Sjamie * unsigned char bitno[2]; bit number in the string 2353192895Sjamie * unsigned char left[3]; offset from base to left element 2354192895Sjamie * unsigned char right[3]; offset from base to right element 2355192895Sjamie */ 2356192895Sjamie#endif 2357192895Sjamie 2358192895Sjamie/* 2359192895Sjamie * This patricia implementation is more-or-less the same as 2360192895Sjamie * used in ccom for string matching. 2361192895Sjamie */ 2362192895Sjamiestruct tree { 2363192895Sjamie int bitno; 2364192895Sjamie struct tree *lr[2]; 2365192895Sjamie}; 2366192895Sjamie 2367192895Sjamie#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF)) 2368192895Sjamie#define LEFT_IS_LEAF 0x80000000 2369192895Sjamie#define RIGHT_IS_LEAF 0x40000000 2370191673Sjamie#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0) 2371191673Sjamie#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0) 2372191673Sjamie#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1 237372786Srwatson#define CHECKBITS 8 2374185029Spjd 237572786Srwatsonstatic struct tree *sympole; 237672786Srwatsonstatic int numsyms; 2377185029Spjd 237872786Srwatsonstatic struct tree * 237972786Srwatsongtree(void) 2380168483Spjd{ 2381124882Srwatson static int ntrees; 2382144660Sjeff static struct tree *tp; 238387275Srwatson 238472786Srwatson if (ntrees == 0) { 238587275Srwatson tp = xmalloc(BUFSIZ); 238672786Srwatson ntrees = BUFSIZ/sizeof(*tp); 238772786Srwatson } 2388185029Spjd return &tp[--ntrees]; 2389185029Spjd} 2390185029Spjd 2391185029Spjd/* 2392185029Spjd * Allocate a symtab struct and store the string. 2393185029Spjd */ 2394185029Spjdstatic struct symtab * 2395185029Spjdgetsymtab(const usch *str) 2396124882Srwatson{ 2397124882Srwatson static int nsyms; 2398124882Srwatson static struct symtab *spp; 2399191673Sjamie struct symtab *sp; 2400191673Sjamie 2401191673Sjamie if (nsyms == 0) { 2402191673Sjamie spp = xmalloc(BUFSIZ); 2403191673Sjamie nsyms = BUFSIZ/sizeof(*sp); 2404191673Sjamie } 2405191673Sjamie sp = &spp[--nsyms]; 2406191673Sjamie 2407191673Sjamie sp->namep = str; 2408191673Sjamie sp->value = NULL; 2409191673Sjamie sp->file = ifiles ? ifiles->orgfn : (const usch *)"<initial>"; 2410191673Sjamie sp->line = ifiles ? ifiles->lineno : 0; 2411191673Sjamie return sp; 2412192895Sjamie} 2413150652Scsjp 2414124882Srwatson/* 2415191673Sjamie * Do symbol lookup in a patricia tree. 2416191673Sjamie * Only do full string matching, no pointer optimisations. 2417192895Sjamie */ 2418191673Sjamiestruct symtab * 2419192895Sjamielookup(const usch *key, int enterf) 2420192895Sjamie{ 2421192895Sjamie struct symtab *sp; 2422192895Sjamie struct tree *w, *new, *last; 2423192895Sjamie int len, cix, bit, fbit, svbit, ix, bitno; 2424192895Sjamie const usch *k, *m; 2425192895Sjamie 2426192895Sjamie /* Count full string length */ 2427191673Sjamie for (k = key, len = 0; ISID(*k) & C_ID; k++, len++) 2428191673Sjamie ; 2429192895Sjamie 2430191673Sjamie switch (numsyms) { 2431191673Sjamie case 0: /* no symbols yet */ 2432191673Sjamie if (enterf != ENTER) 2433191673Sjamie return NULL; 2434191673Sjamie sympole = (struct tree *)getsymtab(key); 2435191673Sjamie numsyms++; 2436192895Sjamie return (struct symtab *)sympole; 2437192895Sjamie 2438192895Sjamie case 1: 2439192895Sjamie w = sympole; 2440191673Sjamie svbit = 0; /* XXX gcc */ 2441124882Srwatson break; 2442192895Sjamie 2443192895Sjamie default: 2444192895Sjamie w = sympole; 2445192895Sjamie bitno = len * CHECKBITS; 2446192895Sjamie for (;;) { 2447192895Sjamie bit = BITNO(w->bitno); 2448192895Sjamie fbit = bit >= bitno ? 0 : P_BIT(key, bit); 2449192895Sjamie svbit = fbit ? IS_RIGHT_LEAF(w->bitno) : 2450192895Sjamie IS_LEFT_LEAF(w->bitno); 2451192895Sjamie w = w->lr[fbit]; 2452192895Sjamie if (svbit) 2453191673Sjamie break; 2454191673Sjamie } 2455192895Sjamie } 2456192895Sjamie 2457192895Sjamie sp = (struct symtab *)w; 2458192895Sjamie 2459192895Sjamie m = sp->namep; 2460192895Sjamie k = key; 2461192895Sjamie 2462192895Sjamie /* Check for correct string and return */ 2463168489Spjd for (cix = 0; *m && ISID(*k) && *m == *k; m++, k++, cix += CHECKBITS) 2464192895Sjamie ; 2465192895Sjamie if (*m == 0 && ISID(*k) == 0) { 2466192895Sjamie if (enterf != ENTER && sp->value == NULL) 2467192895Sjamie return NULL; 2468194762Sjamie return sp; 2469196592Sjamie } 2470192895Sjamie 2471194251Sjamie if (enterf != ENTER) 2472196505Szec return NULL; /* no string found and do not enter */ 2473194251Sjamie 2474194251Sjamie ix = *m ^ *k; 2475192895Sjamie while ((ix & 1) == 0) 2476192895Sjamie ix >>= 1, cix++; 2477192895Sjamie 2478192895Sjamie /* Create new node */ 2479192895Sjamie new = gtree(); 2480192895Sjamie bit = P_BIT(key, cix); 2481191673Sjamie new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); 2482192895Sjamie new->lr[bit] = (struct tree *)getsymtab(key); 2483191673Sjamie 2484185435Sbz if (numsyms++ == 1) { 2485192895Sjamie new->lr[!bit] = sympole; 2486185435Sbz new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); 2487192895Sjamie sympole = new; 2488192895Sjamie return (struct symtab *)new->lr[bit]; 2489192895Sjamie } 2490192895Sjamie 2491192895Sjamie w = sympole; 2492192895Sjamie last = NULL; 2493192895Sjamie for (;;) { 2494192895Sjamie fbit = w->bitno; 2495196592Sjamie bitno = BITNO(w->bitno); 2496192895Sjamie if (bitno == cix) 2497124882Srwatson error("bitno == cix"); 2498124882Srwatson if (bitno > cix) 249972786Srwatson break; 2500185029Spjd svbit = P_BIT(key, bitno); 250172786Srwatson last = w; 250272786Srwatson w = w->lr[svbit]; 2503185029Spjd if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF)) 2504168489Spjd break; 2505191671Sjamie } 250672786Srwatson 2507185029Spjd new->lr[!bit] = w; 2508185029Spjd if (last == NULL) { 2509185029Spjd sympole = new; 2510185029Spjd } else { 2511185029Spjd last->lr[svbit] = new; 2512185029Spjd last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); 2513185029Spjd } 2514185029Spjd if (bitno < cix) 251587275Srwatson new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); 251672786Srwatson return (struct symtab *)new->lr[bit]; 251772786Srwatson} 2518185435Sbz 2519185435Sbzstatic void * 252087275Srwatsonxmalloc(int sz) 252187275Srwatson{ 2522185435Sbz usch *rv; 2523191673Sjamie 2524191673Sjamie if ((rv = (void *)malloc(sz)) == NULL) 2525191673Sjamie error("xmalloc: out of mem"); 2526185435Sbz return rv; 252787275Srwatson} 252887275Srwatson 2529185435Sbzstatic void * 2530185435Sbzxrealloc(void *p, int sz) 2531185435Sbz{ 2532185435Sbz usch *rv; 2533185435Sbz 2534191673Sjamie if ((rv = (void *)realloc(p, sz)) == NULL) 2535191673Sjamie error("xrealloc: out of mem"); 2536191673Sjamie return rv; 2537185435Sbz} 2538185435Sbz 2539185435Sbzstatic usch * 2540185435Sbzxstrdup(const usch *str) 2541185435Sbz{ 2542192895Sjamie usch *rv; 2543192895Sjamie 2544192895Sjamie if ((rv = (usch *)strdup((const char *)str)) == NULL) 2545192895Sjamie error("xstrdup: out of mem"); 2546192895Sjamie return rv; 2547192895Sjamie} 2548192895Sjamie