1*da2e3ebdSchin /*********************************************************************** 2*da2e3ebdSchin * * 3*da2e3ebdSchin * This software is part of the ast package * 4*da2e3ebdSchin * Copyright (c) 1986-2007 AT&T Knowledge Ventures * 5*da2e3ebdSchin * and is licensed under the * 6*da2e3ebdSchin * Common Public License, Version 1.0 * 7*da2e3ebdSchin * by AT&T Knowledge Ventures * 8*da2e3ebdSchin * * 9*da2e3ebdSchin * A copy of the License is available at * 10*da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11*da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*da2e3ebdSchin * * 13*da2e3ebdSchin * Information and Software Systems Research * 14*da2e3ebdSchin * AT&T Research * 15*da2e3ebdSchin * Florham Park NJ * 16*da2e3ebdSchin * * 17*da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> * 18*da2e3ebdSchin * * 19*da2e3ebdSchin ***********************************************************************/ 20*da2e3ebdSchin #pragma prototyped 21*da2e3ebdSchin /* 22*da2e3ebdSchin * Glenn Fowler 23*da2e3ebdSchin * AT&T Research 24*da2e3ebdSchin * 25*da2e3ebdSchin * include file search support 26*da2e3ebdSchin */ 27*da2e3ebdSchin 28*da2e3ebdSchin #include "pplib.h" 29*da2e3ebdSchin 30*da2e3ebdSchin #define SEARCH_NEXT (SEARCH_USER<<1)/* search for next (uncover) */ 31*da2e3ebdSchin #define SEARCH_SKIP (SEARCH_USER<<2)/* current binding skipped */ 32*da2e3ebdSchin #define SEARCH_TEST (SEARCH_USER<<3)/* test for binding */ 33*da2e3ebdSchin #define SEARCH_FOUND (SEARCH_USER<<4)/* current binding found */ 34*da2e3ebdSchin 35*da2e3ebdSchin #define COLUMN_TAB 7 36*da2e3ebdSchin #define COLUMN_MAX 72 37*da2e3ebdSchin 38*da2e3ebdSchin #if ARCHIVE 39*da2e3ebdSchin 40*da2e3ebdSchin #include <vdb.h> 41*da2e3ebdSchin #include <ls.h> 42*da2e3ebdSchin 43*da2e3ebdSchin #endif 44*da2e3ebdSchin 45*da2e3ebdSchin /* 46*da2e3ebdSchin * multiple include test 47*da2e3ebdSchin * fp is a canonicalized ppfile pointer 48*da2e3ebdSchin * 49*da2e3ebdSchin * test 50*da2e3ebdSchin * 51*da2e3ebdSchin * INC_CLEAR can be included again 52*da2e3ebdSchin * INC_TEST test if include required 53*da2e3ebdSchin * <symbol> ifndef guard symbol 54*da2e3ebdSchin * 55*da2e3ebdSchin * test!=INC_CLEAR returns 1 if file can be included again 56*da2e3ebdSchin * 57*da2e3ebdSchin * NOTE: 58*da2e3ebdSchin * 59*da2e3ebdSchin * (1) different hard links to the same file are treated as 60*da2e3ebdSchin * different files 61*da2e3ebdSchin * 62*da2e3ebdSchin * (2) symbolic links in combination with .. may cause two 63*da2e3ebdSchin * different files to be treated as the same file: 64*da2e3ebdSchin * 65*da2e3ebdSchin * "../h/<file>" == "/usr/include/sys/../h/<file>" -> "/usr/include/h/<file>" 66*da2e3ebdSchin * "h/<file>" -> "/usr/include/h/<file>" 67*da2e3ebdSchin */ 68*da2e3ebdSchin 69*da2e3ebdSchin int 70*da2e3ebdSchin ppmultiple(register struct ppfile* fp, register struct ppsymbol* test) 71*da2e3ebdSchin { 72*da2e3ebdSchin register struct ppsymbol* status; 73*da2e3ebdSchin 74*da2e3ebdSchin status = fp->guard; 75*da2e3ebdSchin message((-3, "search: %s: status=%s%s test=%s", fp->name, status == INC_CLEAR ? "[CLEAR]" : status == INC_TEST ? "[ONCE]" : status == INC_IGNORE ? "[IGNORE]" : status->name, (pp.mode & HOSTED) ? "[HOSTED]" : "", test == INC_CLEAR ? "[CLEAR]" : test == INC_TEST ? "[TEST]" : test->name)); 76*da2e3ebdSchin if (status == INC_IGNORE) 77*da2e3ebdSchin { 78*da2e3ebdSchin message((-2, "%s: ignored [%s]", fp->name, pp.ignore)); 79*da2e3ebdSchin return 0; 80*da2e3ebdSchin } 81*da2e3ebdSchin if (test == INC_TEST) 82*da2e3ebdSchin { 83*da2e3ebdSchin if (status != INC_CLEAR) 84*da2e3ebdSchin { 85*da2e3ebdSchin if (status != INC_TEST && status->macro || !(pp.mode & ALLMULTIPLE) && !(pp.state & STRICT)) 86*da2e3ebdSchin { 87*da2e3ebdSchin if ((pp.mode & (ALLMULTIPLE|LOADING)) == LOADING) 88*da2e3ebdSchin fp->guard = INC_IGNORE; 89*da2e3ebdSchin if (pp.state & WARN) 90*da2e3ebdSchin error(1, "%s: ignored -- already included", fp->name); 91*da2e3ebdSchin else 92*da2e3ebdSchin message((-3, "%s: ignored -- already included", fp->name)); 93*da2e3ebdSchin return 0; 94*da2e3ebdSchin } 95*da2e3ebdSchin return 1; 96*da2e3ebdSchin } 97*da2e3ebdSchin if ((pp.mode & (ALLMULTIPLE|LOADING)) == LOADING) 98*da2e3ebdSchin test = INC_IGNORE; 99*da2e3ebdSchin } 100*da2e3ebdSchin fp->guard = test; 101*da2e3ebdSchin return 1; 102*da2e3ebdSchin } 103*da2e3ebdSchin 104*da2e3ebdSchin /* 105*da2e3ebdSchin * search for file using directories in dp 106*da2e3ebdSchin */ 107*da2e3ebdSchin 108*da2e3ebdSchin static int 109*da2e3ebdSchin search(register struct ppfile* fp, register struct ppdirs* dp, int type, int flags) 110*da2e3ebdSchin { 111*da2e3ebdSchin register char* prefix; 112*da2e3ebdSchin register struct ppdirs* up; 113*da2e3ebdSchin register struct ppfile* xp; 114*da2e3ebdSchin struct ppfile* mp; 115*da2e3ebdSchin int fd; 116*da2e3ebdSchin int index; 117*da2e3ebdSchin int need; 118*da2e3ebdSchin int markhosted; 119*da2e3ebdSchin char* t; 120*da2e3ebdSchin 121*da2e3ebdSchin if (!(pp.option & PREFIX)) 122*da2e3ebdSchin prefix = 0; 123*da2e3ebdSchin else if ((prefix = strrchr(fp->name, '/')) && prefix > fp->name) 124*da2e3ebdSchin { 125*da2e3ebdSchin *prefix = 0; 126*da2e3ebdSchin t = ppsetfile(fp->name)->name; 127*da2e3ebdSchin *prefix = '/'; 128*da2e3ebdSchin prefix = t; 129*da2e3ebdSchin } 130*da2e3ebdSchin message((-3, "search: %s %s%s%s%s%s%s type=%s prefix=%s flags=|%s%s%s%s%s%s start=%s=\"%s\" pre=%s lcl=%s vnd=%s std=%s cur=%s", 131*da2e3ebdSchin fp->name, 132*da2e3ebdSchin (flags & SEARCH_INCLUDE) ? "include" : "exists", 133*da2e3ebdSchin (flags & SEARCH_VENDOR) ? " vendor" : "", 134*da2e3ebdSchin (flags & SEARCH_HOSTED) ? " hosted" : "", 135*da2e3ebdSchin (flags & SEARCH_NEXT) ? " next" : "", 136*da2e3ebdSchin (flags & SEARCH_SKIP) ? " skip" : "", 137*da2e3ebdSchin (flags & SEARCH_TEST) ? " test" : "", 138*da2e3ebdSchin type == T_HEADER ? "<*>" : "\"*\"", prefix, 139*da2e3ebdSchin (fp->flags & INC_SELF) ? "SELF|" : "", 140*da2e3ebdSchin (fp->flags & INC_EXISTS) ? "EXISTS|" : "", 141*da2e3ebdSchin (fp->flags & INC_BOUND(INC_PREFIX)) ? "PREFIX|" : "", 142*da2e3ebdSchin (fp->flags & INC_BOUND(INC_LOCAL)) ? "LOCAL|" : "", 143*da2e3ebdSchin (fp->flags & INC_BOUND(INC_VENDOR)) ? "VENDOR|" : "", 144*da2e3ebdSchin (fp->flags & INC_BOUND(INC_STANDARD)) ? "STANDARD|" : "", 145*da2e3ebdSchin dp ? (dp->index == INC_PREFIX ? "pre" : dp->index == INC_LOCAL ? "lcl" : dp->index == INC_VENDOR ? "vnd" : "std") : NiL, 146*da2e3ebdSchin dp ? dp->name : NiL, 147*da2e3ebdSchin !(fp->flags & INC_MEMBER(INC_PREFIX)) && (xp = fp->bound[INC_PREFIX]) ? xp->name : NiL, 148*da2e3ebdSchin !(fp->flags & INC_MEMBER(INC_LOCAL)) && (xp = fp->bound[INC_LOCAL]) ? xp->name : NiL, 149*da2e3ebdSchin !(fp->flags & INC_MEMBER(INC_VENDOR)) && (xp = fp->bound[INC_VENDOR]) ? xp->name : NiL, 150*da2e3ebdSchin !(fp->flags & INC_MEMBER(INC_STANDARD)) && (xp = fp->bound[INC_STANDARD]) ? xp->name : NiL, 151*da2e3ebdSchin error_info.file 152*da2e3ebdSchin )); 153*da2e3ebdSchin if (flags & SEARCH_HOSTED) 154*da2e3ebdSchin need = TYPE_HOSTED; 155*da2e3ebdSchin else if (flags & SEARCH_VENDOR) 156*da2e3ebdSchin need = TYPE_VENDOR; 157*da2e3ebdSchin else 158*da2e3ebdSchin need = TYPE_INCLUDE; 159*da2e3ebdSchin for (index = -1; dp; dp = dp->next) 160*da2e3ebdSchin if (dp->type & need) 161*da2e3ebdSchin { 162*da2e3ebdSchin message((-3, "search: fp=%s need=%02x index=%d dp=%s type=%02x index=%d", fp->name, need, index, dp->name, dp->type, dp->index)); 163*da2e3ebdSchin #if ARCHIVE 164*da2e3ebdSchin if (!(dp->type & (TYPE_ARCHIVE|TYPE_DIRECTORY))) 165*da2e3ebdSchin { 166*da2e3ebdSchin struct stat st; 167*da2e3ebdSchin 168*da2e3ebdSchin if (stat(dp->name, &st)) 169*da2e3ebdSchin { 170*da2e3ebdSchin message((-3, "search: omit %s", dp->name)); 171*da2e3ebdSchin dp->type = 0; 172*da2e3ebdSchin continue; 173*da2e3ebdSchin } 174*da2e3ebdSchin if (S_ISREG(st.st_mode)) 175*da2e3ebdSchin { 176*da2e3ebdSchin register char* s; 177*da2e3ebdSchin char* e; 178*da2e3ebdSchin int delimiter; 179*da2e3ebdSchin int variant; 180*da2e3ebdSchin unsigned long siz; 181*da2e3ebdSchin unsigned long off; 182*da2e3ebdSchin struct ppmember* ap; 183*da2e3ebdSchin Sfio_t* sp; 184*da2e3ebdSchin 185*da2e3ebdSchin /* 186*da2e3ebdSchin * check for vdb header archive 187*da2e3ebdSchin */ 188*da2e3ebdSchin 189*da2e3ebdSchin if (!(sp = sfopen(NiL, dp->name, "r"))) 190*da2e3ebdSchin { 191*da2e3ebdSchin error(ERROR_SYSTEM|1, "%s: ignored -- cannot open", dp->name); 192*da2e3ebdSchin dp->type = 0; 193*da2e3ebdSchin continue; 194*da2e3ebdSchin } 195*da2e3ebdSchin variant = sfsprintf(pp.tmpbuf, MAXTOKEN, "%c%s%c%s:archive", VDB_DELIMITER, VDB_MAGIC, VDB_DELIMITER, pp.pass); 196*da2e3ebdSchin if (!(s = sfgetr(sp, '\n', 1)) || !strneq(s, pp.tmpbuf, variant)) 197*da2e3ebdSchin { 198*da2e3ebdSchin sfclose(sp); 199*da2e3ebdSchin error(1, "%s: ignored -- not a directory or archive", dp->name); 200*da2e3ebdSchin dp->type = 0; 201*da2e3ebdSchin continue; 202*da2e3ebdSchin } 203*da2e3ebdSchin 204*da2e3ebdSchin /* 205*da2e3ebdSchin * parse the options 206*da2e3ebdSchin */ 207*da2e3ebdSchin 208*da2e3ebdSchin dp->type |= TYPE_ARCHIVE; 209*da2e3ebdSchin for (s += variant;;) 210*da2e3ebdSchin { 211*da2e3ebdSchin while (*s == ' ') s++; 212*da2e3ebdSchin e = s; 213*da2e3ebdSchin for (t = 0; *s && *s != ' '; s++) 214*da2e3ebdSchin if (*s == '=') 215*da2e3ebdSchin { 216*da2e3ebdSchin *s = 0; 217*da2e3ebdSchin t = s + 1; 218*da2e3ebdSchin } 219*da2e3ebdSchin if (*s) 220*da2e3ebdSchin *s++ = 0; 221*da2e3ebdSchin if (!*e) 222*da2e3ebdSchin break; 223*da2e3ebdSchin switch ((int)hashref(pp.strtab, e)) 224*da2e3ebdSchin { 225*da2e3ebdSchin case X_CHECKPOINT: 226*da2e3ebdSchin #if CHECKPOINT 227*da2e3ebdSchin dp->type |= TYPE_CHECKPOINT; 228*da2e3ebdSchin break; 229*da2e3ebdSchin #else 230*da2e3ebdSchin error(1, "preprocessor not compiled with checkpoint enabled"); 231*da2e3ebdSchin goto notvdb; 232*da2e3ebdSchin #endif 233*da2e3ebdSchin case X_HIDE: 234*da2e3ebdSchin 235*da2e3ebdSchin if (t) 236*da2e3ebdSchin error(1, "%s: %s: archive option value ignored", e); 237*da2e3ebdSchin if (e = strrchr(dp->name, '/')) 238*da2e3ebdSchin *e = 0; 239*da2e3ebdSchin else 240*da2e3ebdSchin dp->name = "."; 241*da2e3ebdSchin break; 242*da2e3ebdSchin case X_MAP: 243*da2e3ebdSchin if (!t) 244*da2e3ebdSchin error(1, "%s: archive option value expected", e); 245*da2e3ebdSchin else 246*da2e3ebdSchin dp->name = strdup(t); 247*da2e3ebdSchin break; 248*da2e3ebdSchin default: 249*da2e3ebdSchin error(1, "%s: unknown archive option", e); 250*da2e3ebdSchin break; 251*da2e3ebdSchin } 252*da2e3ebdSchin } 253*da2e3ebdSchin if (sfseek(sp, -(VDB_LENGTH + 1), SEEK_END) <= 0 || !(s = sfgetr(sp, '\n', 1))) 254*da2e3ebdSchin { 255*da2e3ebdSchin notvdb: 256*da2e3ebdSchin sfclose(sp); 257*da2e3ebdSchin error(1, "%s: ignored -- cannot load archive", dp->name); 258*da2e3ebdSchin dp->type = 0; 259*da2e3ebdSchin continue; 260*da2e3ebdSchin } 261*da2e3ebdSchin if (variant = *s != 0) 262*da2e3ebdSchin s++; 263*da2e3ebdSchin else if (!(s = sfgetr(sp, '\n', 1))) 264*da2e3ebdSchin goto notvdb; 265*da2e3ebdSchin if (sfvalue(sp) != (VDB_LENGTH + variant)) 266*da2e3ebdSchin goto notvdb; 267*da2e3ebdSchin if (!strneq(s, VDB_DIRECTORY, sizeof(VDB_DIRECTORY) - 1)) 268*da2e3ebdSchin goto notvdb; 269*da2e3ebdSchin delimiter = s[VDB_OFFSET - 1]; 270*da2e3ebdSchin off = strtol(s + VDB_OFFSET, NiL, 10) - sizeof(VDB_DIRECTORY); 271*da2e3ebdSchin siz = strtol(s + VDB_SIZE, NiL, 10); 272*da2e3ebdSchin if (sfseek(sp, off, SEEK_SET) != off) 273*da2e3ebdSchin goto notvdb; 274*da2e3ebdSchin if (!(s = sfreserve(sp, siz + 1, 0))) 275*da2e3ebdSchin goto notvdb; 276*da2e3ebdSchin s[siz] = 0; 277*da2e3ebdSchin if (!strneq(s, VDB_DIRECTORY, sizeof(VDB_DIRECTORY)) - 1) 278*da2e3ebdSchin goto notvdb; 279*da2e3ebdSchin if (!(s = strchr(s, '\n'))) 280*da2e3ebdSchin goto notvdb; 281*da2e3ebdSchin s++; 282*da2e3ebdSchin while (e = strchr(s, '\n')) 283*da2e3ebdSchin { 284*da2e3ebdSchin delimiter = variant ? *s++ : delimiter; 285*da2e3ebdSchin if (!(t = strchr(s, delimiter))) 286*da2e3ebdSchin break; 287*da2e3ebdSchin *t = 0; 288*da2e3ebdSchin if (!streq(s, VDB_DIRECTORY)) 289*da2e3ebdSchin { 290*da2e3ebdSchin pathcanon(s, 0); 291*da2e3ebdSchin ap = newof(0, struct ppmember, 1, 0); 292*da2e3ebdSchin ap->archive = dp; 293*da2e3ebdSchin ap->offset = strtol(t + 1, &t, 10); 294*da2e3ebdSchin ap->size = strtol(t + 1, NiL, 10); 295*da2e3ebdSchin xp = ppsetfile(s); 296*da2e3ebdSchin xp->flags |= INC_MEMBER(dp->index); 297*da2e3ebdSchin xp->bound[dp->index] = (struct ppfile*)ap; 298*da2e3ebdSchin if (pp.test & 0x0020) error(1, "VDB#%d %s %s index=%d data=<%lu,%lu>", __LINE__, dp->name, xp->name, index, ap->offset, ap->size); 299*da2e3ebdSchin } 300*da2e3ebdSchin s = e + 1; 301*da2e3ebdSchin } 302*da2e3ebdSchin if (sfseek(sp, 0L, SEEK_SET)) 303*da2e3ebdSchin goto notvdb; 304*da2e3ebdSchin if (!(pp.test & 0x4000) && 305*da2e3ebdSchin #if POOL 306*da2e3ebdSchin (pp.pool.input || !(dp->type & TYPE_CHECKPOINT)) 307*da2e3ebdSchin #else 308*da2e3ebdSchin !(dp->type & TYPE_CHECKPOINT) 309*da2e3ebdSchin #endif 310*da2e3ebdSchin && (dp->info.buffer = sfreserve(sp, off, 0))) 311*da2e3ebdSchin dp->type |= TYPE_BUFFER; 312*da2e3ebdSchin else 313*da2e3ebdSchin { 314*da2e3ebdSchin dp->info.sp = sp; 315*da2e3ebdSchin #if POOL 316*da2e3ebdSchin if (pp.pool.input) 317*da2e3ebdSchin sfset(sp, SF_SHARE, 1); 318*da2e3ebdSchin #endif 319*da2e3ebdSchin } 320*da2e3ebdSchin } 321*da2e3ebdSchin else 322*da2e3ebdSchin dp->type |= TYPE_DIRECTORY; 323*da2e3ebdSchin } 324*da2e3ebdSchin #endif 325*da2e3ebdSchin if (streq(fp->name, ".")) 326*da2e3ebdSchin continue; 327*da2e3ebdSchin if (prefix && *fp->name != '/' && dp->index != INC_PREFIX) 328*da2e3ebdSchin #if ARCHIVE 329*da2e3ebdSchin if (dp->type & TYPE_DIRECTORY) 330*da2e3ebdSchin #endif 331*da2e3ebdSchin { 332*da2e3ebdSchin for (up = dp->info.subdir; up; up = up->next) 333*da2e3ebdSchin if (up->name == prefix) 334*da2e3ebdSchin break; 335*da2e3ebdSchin if (!up) 336*da2e3ebdSchin { 337*da2e3ebdSchin up = newof(0, struct ppdirs, 1, 0); 338*da2e3ebdSchin up->name = prefix; 339*da2e3ebdSchin up->type = dp->type; 340*da2e3ebdSchin up->next = dp->info.subdir; 341*da2e3ebdSchin dp->info.subdir = up; 342*da2e3ebdSchin if (!*dp->name) 343*da2e3ebdSchin t = prefix; 344*da2e3ebdSchin else 345*da2e3ebdSchin sfsprintf(t = pp.path, PATH_MAX - 1, "%s/%s", dp->name, prefix); 346*da2e3ebdSchin if (eaccess(t, X_OK)) 347*da2e3ebdSchin { 348*da2e3ebdSchin message((-3, "search: omit %s", t)); 349*da2e3ebdSchin continue; 350*da2e3ebdSchin } 351*da2e3ebdSchin up->type |= TYPE_HOSTED; 352*da2e3ebdSchin } 353*da2e3ebdSchin else if (!(up->type & TYPE_HOSTED)) 354*da2e3ebdSchin continue; 355*da2e3ebdSchin } 356*da2e3ebdSchin mp = xp = 0; 357*da2e3ebdSchin if (!(flags & SEARCH_NEXT) && index != dp->index && (!(need & TYPE_HOSTED) || dp->index == INC_STANDARD) && (!(need & TYPE_VENDOR) || dp->index == INC_VENDOR)) 358*da2e3ebdSchin { 359*da2e3ebdSchin if (index >= 0 && !(fp->flags & INC_MEMBER(index))) 360*da2e3ebdSchin fp->flags |= INC_BOUND(index); 361*da2e3ebdSchin index = dp->index; 362*da2e3ebdSchin if (fp->flags & INC_BOUND(index)) 363*da2e3ebdSchin { 364*da2e3ebdSchin xp = fp->bound[index]; 365*da2e3ebdSchin if (index == INC_PREFIX) 366*da2e3ebdSchin { 367*da2e3ebdSchin if (*fp->name == '/' || !*dp->name) 368*da2e3ebdSchin strcpy(pp.path, fp->name); 369*da2e3ebdSchin else 370*da2e3ebdSchin sfsprintf(pp.path, PATH_MAX - 1, "%s/%s", dp->name, fp->name); 371*da2e3ebdSchin pathcanon(pp.path, 0); 372*da2e3ebdSchin if (!xp || !streq(xp->name, pp.path)) 373*da2e3ebdSchin { 374*da2e3ebdSchin fp->bound[index] = xp = ppsetfile(pp.path); 375*da2e3ebdSchin if (dp->type & TYPE_HOSTED) 376*da2e3ebdSchin xp->flags |= INC_HOSTED; 377*da2e3ebdSchin if ((flags & SEARCH_INCLUDE) || (xp->flags & INC_EXISTS)) 378*da2e3ebdSchin { 379*da2e3ebdSchin if (!(flags & SEARCH_INCLUDE)) 380*da2e3ebdSchin return 0; 381*da2e3ebdSchin if (!ppmultiple(xp, INC_TEST)) 382*da2e3ebdSchin { 383*da2e3ebdSchin if (flags & SEARCH_TEST) 384*da2e3ebdSchin pp.include = xp->name; 385*da2e3ebdSchin return 0; 386*da2e3ebdSchin } 387*da2e3ebdSchin mp = xp; 388*da2e3ebdSchin } 389*da2e3ebdSchin } 390*da2e3ebdSchin } 391*da2e3ebdSchin else if (!xp) 392*da2e3ebdSchin { 393*da2e3ebdSchin while (dp->next && dp->next->index == index) 394*da2e3ebdSchin dp = dp->next; 395*da2e3ebdSchin message((-3, "search: omit %s/%s", dp->name, fp->name)); 396*da2e3ebdSchin continue; 397*da2e3ebdSchin } 398*da2e3ebdSchin else 399*da2e3ebdSchin { 400*da2e3ebdSchin strcpy(pp.path, xp->name); 401*da2e3ebdSchin if (!(flags & SEARCH_INCLUDE)) 402*da2e3ebdSchin return 0; 403*da2e3ebdSchin if (!ppmultiple(xp, INC_TEST)) 404*da2e3ebdSchin { 405*da2e3ebdSchin if (flags & SEARCH_TEST) 406*da2e3ebdSchin pp.include = xp->name; 407*da2e3ebdSchin return 0; 408*da2e3ebdSchin } 409*da2e3ebdSchin mp = xp; 410*da2e3ebdSchin } 411*da2e3ebdSchin } 412*da2e3ebdSchin } 413*da2e3ebdSchin if (!(fp->flags & INC_BOUND(index)) || (flags & SEARCH_NEXT)) 414*da2e3ebdSchin { 415*da2e3ebdSchin if (*fp->name == '/' || !*dp->name) 416*da2e3ebdSchin strcpy(pp.path, fp->name); 417*da2e3ebdSchin else 418*da2e3ebdSchin sfsprintf(pp.path, PATH_MAX - 1, "%s/%s", dp->name, fp->name); 419*da2e3ebdSchin pathcanon(pp.path, 0); 420*da2e3ebdSchin if (!(flags & SEARCH_SKIP)) 421*da2e3ebdSchin { 422*da2e3ebdSchin int found; 423*da2e3ebdSchin struct ppinstk* in; 424*da2e3ebdSchin 425*da2e3ebdSchin if (streq(error_info.file, pp.path)) 426*da2e3ebdSchin found = 1; 427*da2e3ebdSchin else 428*da2e3ebdSchin { 429*da2e3ebdSchin found = 0; 430*da2e3ebdSchin for (in = pp.in; in; in = in->prev) 431*da2e3ebdSchin if (in->type == IN_FILE && in->file && streq(in->file, pp.path)) 432*da2e3ebdSchin { 433*da2e3ebdSchin found = 1; 434*da2e3ebdSchin break; 435*da2e3ebdSchin } 436*da2e3ebdSchin } 437*da2e3ebdSchin if (found) 438*da2e3ebdSchin { 439*da2e3ebdSchin flags |= SEARCH_FOUND; 440*da2e3ebdSchin continue; 441*da2e3ebdSchin } 442*da2e3ebdSchin if (!(flags & SEARCH_FOUND)) 443*da2e3ebdSchin continue; 444*da2e3ebdSchin } 445*da2e3ebdSchin } 446*da2e3ebdSchin if ((xp || (xp = ppgetfile(pp.path))) && (xp->flags & INC_SELF)) 447*da2e3ebdSchin { 448*da2e3ebdSchin if (xp->flags & INC_EXISTS) 449*da2e3ebdSchin { 450*da2e3ebdSchin if (!(flags & SEARCH_INCLUDE)) 451*da2e3ebdSchin return 0; 452*da2e3ebdSchin if (!(flags & SEARCH_NEXT) && mp != xp && (mp = xp) && !ppmultiple(xp, INC_TEST)) 453*da2e3ebdSchin { 454*da2e3ebdSchin if (flags & SEARCH_TEST) 455*da2e3ebdSchin pp.include = xp->name; 456*da2e3ebdSchin return 0; 457*da2e3ebdSchin } 458*da2e3ebdSchin } 459*da2e3ebdSchin else if (*fp->name == '/') 460*da2e3ebdSchin break; 461*da2e3ebdSchin else 462*da2e3ebdSchin continue; 463*da2e3ebdSchin } 464*da2e3ebdSchin message((-3, "search: file=%s path=%s", fp->name, pp.path)); 465*da2e3ebdSchin #if ARCHIVE 466*da2e3ebdSchin if (pp.test & 0x0040) error(1, "SEARCH#%d dir=%s%s%s%s%s file=%s%s path=%s index=%d", __LINE__, dp->name, (dp->type & TYPE_ARCHIVE) ? " ARCHIVE" : "", (dp->type & TYPE_BUFFER) ? " BUFFER" : "", (dp->type & TYPE_CHECKPOINT) ? " CHECKPOINT" : "", (dp->type & TYPE_DIRECTORY) ? " DIRECTORY" : "", fp->name, (fp->flags & INC_MEMBER(index)) ? " MEMBER" : "", pp.path, index); 467*da2e3ebdSchin if ((fp->flags & INC_MEMBER(index)) && ((struct ppmember*)fp->bound[index])->archive == dp) 468*da2e3ebdSchin { 469*da2e3ebdSchin fd = 0; 470*da2e3ebdSchin pp.member = (struct ppmember*)fp->bound[index]; 471*da2e3ebdSchin if (pp.test & 0x0010) error(1, "SEARCH#%d file=%s path=%s index=%d data=<%lu,%lu>", __LINE__, fp->name, pp.path, index, pp.member->offset, pp.member->size); 472*da2e3ebdSchin } 473*da2e3ebdSchin else if (!(dp->type & TYPE_DIRECTORY)) 474*da2e3ebdSchin continue; 475*da2e3ebdSchin else 476*da2e3ebdSchin #endif 477*da2e3ebdSchin { 478*da2e3ebdSchin pp.member = 0; 479*da2e3ebdSchin fd = (flags & SEARCH_INCLUDE) ? open(pp.path, O_RDONLY) : eaccess(pp.path, R_OK); 480*da2e3ebdSchin } 481*da2e3ebdSchin if (fd >= 0) 482*da2e3ebdSchin { 483*da2e3ebdSchin pp.found = dp; 484*da2e3ebdSchin if ((pp.option & (PLUSPLUS|NOPROTO)) == PLUSPLUS && !(pp.test & TEST_noproto)) 485*da2e3ebdSchin { 486*da2e3ebdSchin if (dp->c) 487*da2e3ebdSchin pp.mode |= MARKC; 488*da2e3ebdSchin else 489*da2e3ebdSchin pp.mode &= ~MARKC; 490*da2e3ebdSchin } 491*da2e3ebdSchin if (xp) 492*da2e3ebdSchin markhosted = xp->flags & INC_HOSTED; 493*da2e3ebdSchin else if (!(markhosted = (dp->type & TYPE_HOSTED)) && dp->index == INC_PREFIX && (pp.mode & (FILEDEPS|HEADERDEPS|INIT)) == FILEDEPS) 494*da2e3ebdSchin { 495*da2e3ebdSchin up = dp; 496*da2e3ebdSchin while ((up = up->next) && !streq(up->name, dp->name)); 497*da2e3ebdSchin if (up && (up->type & TYPE_HOSTED)) 498*da2e3ebdSchin markhosted = 1; 499*da2e3ebdSchin } 500*da2e3ebdSchin if (markhosted) 501*da2e3ebdSchin pp.mode |= MARKHOSTED; 502*da2e3ebdSchin else 503*da2e3ebdSchin pp.mode &= ~MARKHOSTED; 504*da2e3ebdSchin xp = ppsetfile(pp.path); 505*da2e3ebdSchin if (markhosted) 506*da2e3ebdSchin xp->flags |= INC_HOSTED; 507*da2e3ebdSchin message((-2, "search: %s -> %s%s%s", fp->name, pp.path, (pp.mode & MARKC) ? " [C]" : "", (pp.mode & MARKHOSTED) ? " [hosted]" : "")); 508*da2e3ebdSchin #if ARCHIVE 509*da2e3ebdSchin if (!pp.member) 510*da2e3ebdSchin { 511*da2e3ebdSchin #endif 512*da2e3ebdSchin fp->flags |= INC_BOUND(index); 513*da2e3ebdSchin fp->bound[index] = xp; 514*da2e3ebdSchin if ((index == INC_STANDARD || index == INC_VENDOR) && type != T_HEADER && !(fp->flags & INC_BOUND(INC_LOCAL))) 515*da2e3ebdSchin { 516*da2e3ebdSchin fp->flags |= INC_BOUND(INC_LOCAL); 517*da2e3ebdSchin fp->bound[INC_LOCAL] = xp; 518*da2e3ebdSchin } 519*da2e3ebdSchin #if ARCHIVE 520*da2e3ebdSchin } 521*da2e3ebdSchin #endif 522*da2e3ebdSchin xp->flags |= INC_SELF|INC_EXISTS; 523*da2e3ebdSchin if (flags & SEARCH_INCLUDE) 524*da2e3ebdSchin { 525*da2e3ebdSchin if ((pp.prefix = prefix) || (pp.prefix = pp.in->prefix)) 526*da2e3ebdSchin message((-2, "search: %s: prefix=%s", xp->name, pp.prefix)); 527*da2e3ebdSchin if (!(pp.mode & ALLMULTIPLE)) 528*da2e3ebdSchin { 529*da2e3ebdSchin if (xp->guard == INC_CLEAR || xp == mp) 530*da2e3ebdSchin xp->guard = INC_TEST; 531*da2e3ebdSchin else 532*da2e3ebdSchin { 533*da2e3ebdSchin if (pp.state & WARN) 534*da2e3ebdSchin error(1, "%s: ignored -- already included", xp->name); 535*da2e3ebdSchin else 536*da2e3ebdSchin message((-3, "%s: ignored -- already included", xp->name)); 537*da2e3ebdSchin xp->guard = fp->guard = INC_IGNORE; 538*da2e3ebdSchin #if ARCHIVE 539*da2e3ebdSchin if (!pp.member) 540*da2e3ebdSchin #endif 541*da2e3ebdSchin if (fd > 0) 542*da2e3ebdSchin close(fd); 543*da2e3ebdSchin if (flags & SEARCH_TEST) 544*da2e3ebdSchin pp.include = xp->name; 545*da2e3ebdSchin return 0; 546*da2e3ebdSchin } 547*da2e3ebdSchin } 548*da2e3ebdSchin pp.include = xp->name; 549*da2e3ebdSchin if ((pp.mode & (FILEDEPS|INIT)) == FILEDEPS && ((pp.mode & HEADERDEPS) || !(pp.mode & MARKHOSTED)) && !(xp->flags & INC_LISTED)) 550*da2e3ebdSchin { 551*da2e3ebdSchin xp->flags |= INC_LISTED; 552*da2e3ebdSchin if ((pp.column + strlen(xp->name)) >= COLUMN_MAX) 553*da2e3ebdSchin { 554*da2e3ebdSchin sfprintf(pp.filedeps.sp, " \\\n"); 555*da2e3ebdSchin pp.column = COLUMN_TAB; 556*da2e3ebdSchin index = '\t'; 557*da2e3ebdSchin } 558*da2e3ebdSchin else 559*da2e3ebdSchin index = ' '; 560*da2e3ebdSchin pp.column += sfprintf(pp.filedeps.sp, "%c%s", index, xp->name); 561*da2e3ebdSchin } 562*da2e3ebdSchin } 563*da2e3ebdSchin return fd; 564*da2e3ebdSchin } 565*da2e3ebdSchin if (xp) 566*da2e3ebdSchin xp->flags |= INC_SELF; 567*da2e3ebdSchin if (errno == EMFILE) 568*da2e3ebdSchin error(3, "%s: too many open files", fp->name); 569*da2e3ebdSchin else if (errno != ENOENT && errno != ENOTDIR) 570*da2e3ebdSchin error(ERROR_SYSTEM|1, "%s: cannot open file for reading", pp.path); 571*da2e3ebdSchin if (*fp->name == '/') 572*da2e3ebdSchin break; 573*da2e3ebdSchin } 574*da2e3ebdSchin strcpy(pp.path, fp->name); 575*da2e3ebdSchin message((-2, "search: %s%s not found", (flags & SEARCH_NEXT) ? "next " : "", fp->name)); 576*da2e3ebdSchin return -1; 577*da2e3ebdSchin } 578*da2e3ebdSchin 579*da2e3ebdSchin /* 580*da2e3ebdSchin * search for an include file 581*da2e3ebdSchin * if (flags&SEARCH_INCLUDE) then 582*da2e3ebdSchin * if file found then open read file descriptor returned 583*da2e3ebdSchin * with pp.path set to the full path and 584*da2e3ebdSchin * pp.prefix set to the directory prefix 585*da2e3ebdSchin * otherwise 0 returned if file found but ignored 586*da2e3ebdSchin * otherwise -1 returned 587*da2e3ebdSchin * otherwise 588*da2e3ebdSchin * if file found then 0 returned 589*da2e3ebdSchin * otherwise -1 returned 590*da2e3ebdSchin */ 591*da2e3ebdSchin 592*da2e3ebdSchin int 593*da2e3ebdSchin ppsearch(char* file, int type, int flags) 594*da2e3ebdSchin { 595*da2e3ebdSchin register struct ppfile* fp; 596*da2e3ebdSchin register char* s; 597*da2e3ebdSchin register struct ppdirs* dp; 598*da2e3ebdSchin struct oplist* cp; 599*da2e3ebdSchin struct ppfile* xp; 600*da2e3ebdSchin int dospath; 601*da2e3ebdSchin int fd; 602*da2e3ebdSchin int index; 603*da2e3ebdSchin char name[MAXTOKEN + 1]; 604*da2e3ebdSchin 605*da2e3ebdSchin pp.include = 0; 606*da2e3ebdSchin fd = -1; 607*da2e3ebdSchin dospath = 0; 608*da2e3ebdSchin again: 609*da2e3ebdSchin pathcanon(file, 0); 610*da2e3ebdSchin for (cp = pp.chop; cp; cp = cp->next) 611*da2e3ebdSchin if (strneq(file, cp->value, cp->op)) 612*da2e3ebdSchin { 613*da2e3ebdSchin if (cp->value[cp->op + 1]) 614*da2e3ebdSchin { 615*da2e3ebdSchin sfsprintf(name, sizeof(name) - 1, "%s%s", cp->value + cp->op + 1, file + cp->op); 616*da2e3ebdSchin message((-3, "chop: %s -> %s", file, name)); 617*da2e3ebdSchin file = name; 618*da2e3ebdSchin } 619*da2e3ebdSchin else if (strchr(file + cp->op, '/')) 620*da2e3ebdSchin { 621*da2e3ebdSchin message((-3, "chop: %s -> %s", file, file + cp->op)); 622*da2e3ebdSchin file += cp->op; 623*da2e3ebdSchin } 624*da2e3ebdSchin break; 625*da2e3ebdSchin } 626*da2e3ebdSchin fp = ppsetfile(file); 627*da2e3ebdSchin while ((fp->flags & INC_MAPALL) || (fp->flags & INC_MAPHOSTED) && (pp.mode & HOSTED) || (fp->flags & INC_MAPNOHOSTED) && !(pp.mode & HOSTED)) 628*da2e3ebdSchin { 629*da2e3ebdSchin if (!(xp = fp->bound[type == T_HEADER ? INC_STANDARD : INC_LOCAL]) || xp == fp) 630*da2e3ebdSchin break; 631*da2e3ebdSchin message((-1, "map: %s -> %s", fp->name, xp->name)); 632*da2e3ebdSchin fp = xp; 633*da2e3ebdSchin } 634*da2e3ebdSchin if ((fp->flags & INC_MAPNOLOCAL) && (pp.mode & HOSTED)) 635*da2e3ebdSchin flags |= SEARCH_HOSTED; 636*da2e3ebdSchin else if (pp.vendor) 637*da2e3ebdSchin flags |= SEARCH_VENDOR; 638*da2e3ebdSchin pp.original = fp; 639*da2e3ebdSchin if (type == T_HEADER && strneq(fp->name, "...", 3) && (!fp->name[3] || fp->name[3] == '/')) 640*da2e3ebdSchin { 641*da2e3ebdSchin if (fp->name[3] == '/') 642*da2e3ebdSchin { 643*da2e3ebdSchin int n; 644*da2e3ebdSchin int m; 645*da2e3ebdSchin 646*da2e3ebdSchin n = strlen(error_info.file); 647*da2e3ebdSchin m = strlen(fp->name + 4); 648*da2e3ebdSchin if (n < m || !streq(fp->name + 4, error_info.file + n - m)) 649*da2e3ebdSchin { 650*da2e3ebdSchin if ((fd = ppsearch(fp->name + 4, type, flags|SEARCH_TEST)) < 0) 651*da2e3ebdSchin return -1; 652*da2e3ebdSchin if (fd > 0) 653*da2e3ebdSchin close(fd); 654*da2e3ebdSchin s = error_info.file; 655*da2e3ebdSchin error_info.file = pp.include; 656*da2e3ebdSchin fd = ppsearch(fp->name + 4, type, flags|SEARCH_NEXT); 657*da2e3ebdSchin error_info.file = s; 658*da2e3ebdSchin return fd; 659*da2e3ebdSchin } 660*da2e3ebdSchin file = error_info.file + n - m; 661*da2e3ebdSchin } 662*da2e3ebdSchin else if (file = strrchr(error_info.file, '/')) 663*da2e3ebdSchin file++; 664*da2e3ebdSchin else 665*da2e3ebdSchin file = error_info.file; 666*da2e3ebdSchin flags |= SEARCH_NEXT; 667*da2e3ebdSchin #if _HUH_2002_05_28 668*da2e3ebdSchin if (pp.in->prefix) 669*da2e3ebdSchin { 670*da2e3ebdSchin sfsprintf(name, sizeof(name) - 1, "%s/%s", pp.in->prefix, file); 671*da2e3ebdSchin fp = ppsetfile(name); 672*da2e3ebdSchin if ((fd = ppsearch(fp->name, type, flags)) >= 0) 673*da2e3ebdSchin return fd; 674*da2e3ebdSchin } 675*da2e3ebdSchin #endif 676*da2e3ebdSchin fp = ppsetfile(file); 677*da2e3ebdSchin return ppsearch(fp->name, type, flags); 678*da2e3ebdSchin } 679*da2e3ebdSchin else if ((flags & SEARCH_INCLUDE) && fp->guard == INC_IGNORE) 680*da2e3ebdSchin { 681*da2e3ebdSchin strcpy(pp.path, fp->name); 682*da2e3ebdSchin message((-2, "%s: ignored", fp->name)); 683*da2e3ebdSchin return 0; 684*da2e3ebdSchin } 685*da2e3ebdSchin else if (!(flags & SEARCH_NEXT)) 686*da2e3ebdSchin flags |= SEARCH_SKIP; 687*da2e3ebdSchin pp.prefix = 0; 688*da2e3ebdSchin if (type == T_HEADER) 689*da2e3ebdSchin dp = pp.stddirs->next; 690*da2e3ebdSchin else 691*da2e3ebdSchin { 692*da2e3ebdSchin dp = pp.lcldirs; 693*da2e3ebdSchin if (dp == pp.firstdir) 694*da2e3ebdSchin { 695*da2e3ebdSchin /* 696*da2e3ebdSchin * look in directory of including file first 697*da2e3ebdSchin */ 698*da2e3ebdSchin 699*da2e3ebdSchin if (error_info.file && (s = strrchr(error_info.file, '/'))) 700*da2e3ebdSchin { 701*da2e3ebdSchin *s = 0; 702*da2e3ebdSchin dp->name = ppsetfile(error_info.file)->name; 703*da2e3ebdSchin *s = '/'; 704*da2e3ebdSchin } 705*da2e3ebdSchin else 706*da2e3ebdSchin dp->name = ""; 707*da2e3ebdSchin } 708*da2e3ebdSchin else if (pp.in->prefix && pp.lcldirs != pp.firstdir) 709*da2e3ebdSchin { 710*da2e3ebdSchin /* 711*da2e3ebdSchin * look in prefix directory of including file first 712*da2e3ebdSchin */ 713*da2e3ebdSchin 714*da2e3ebdSchin if (*fp->name != '/') 715*da2e3ebdSchin { 716*da2e3ebdSchin if ((s = strchr(fp->name, '/')) && (fp->name[0] 717*da2e3ebdSchin != '.' || fp->name[1] != '.' || fp->name[2] != '/')) 718*da2e3ebdSchin { 719*da2e3ebdSchin *s = 0; 720*da2e3ebdSchin if (!streq(fp->name, pp.in->prefix)) 721*da2e3ebdSchin fd = 0; 722*da2e3ebdSchin *s = '/'; 723*da2e3ebdSchin } 724*da2e3ebdSchin else 725*da2e3ebdSchin fd = 0; 726*da2e3ebdSchin } 727*da2e3ebdSchin if (fd >= 0) 728*da2e3ebdSchin { 729*da2e3ebdSchin sfsprintf(name, sizeof(name) - 1, "%s/%s", pp.in->prefix, fp->name); 730*da2e3ebdSchin pathcanon(name, 0); 731*da2e3ebdSchin xp = ppsetfile(name); 732*da2e3ebdSchin if ((fd = search(xp, dp, type, flags)) >= 0) 733*da2e3ebdSchin return fd; 734*da2e3ebdSchin } 735*da2e3ebdSchin } 736*da2e3ebdSchin } 737*da2e3ebdSchin if ((fd = search(fp, dp, type, flags)) < 0) 738*da2e3ebdSchin { 739*da2e3ebdSchin if ((pp.option & PLUSPLUS) && file != pp.tmpbuf) 740*da2e3ebdSchin { 741*da2e3ebdSchin s = file + strlen(file); 742*da2e3ebdSchin while (s > file && *--s != '/' && *s != '\\' && *s != '.'); 743*da2e3ebdSchin if (*s != '.') 744*da2e3ebdSchin { 745*da2e3ebdSchin sfsprintf(pp.tmpbuf, MAXTOKEN, "%s.h", file); 746*da2e3ebdSchin file = pp.tmpbuf; 747*da2e3ebdSchin goto again; 748*da2e3ebdSchin } 749*da2e3ebdSchin } 750*da2e3ebdSchin 751*da2e3ebdSchin /* 752*da2e3ebdSchin * hackery for msdos files viewed through unix 753*da2e3ebdSchin */ 754*da2e3ebdSchin 755*da2e3ebdSchin switch (dospath) 756*da2e3ebdSchin { 757*da2e3ebdSchin case 0: 758*da2e3ebdSchin if (s = strchr(file, '\\')) 759*da2e3ebdSchin { 760*da2e3ebdSchin do *s++ = '/'; while (s = strchr(s, '\\')); 761*da2e3ebdSchin pathcanon(file, 0); 762*da2e3ebdSchin dospath = 1; 763*da2e3ebdSchin goto again; 764*da2e3ebdSchin } 765*da2e3ebdSchin /*FALLTHROUGH*/ 766*da2e3ebdSchin case 1: 767*da2e3ebdSchin if (ppisid(file[0]) && file[1] == ':' && file[2] == '/') 768*da2e3ebdSchin { 769*da2e3ebdSchin file[1] = file[0]; 770*da2e3ebdSchin file[0] = '/'; 771*da2e3ebdSchin pathcanon(file, 0); 772*da2e3ebdSchin dospath = 2; 773*da2e3ebdSchin goto again; 774*da2e3ebdSchin } 775*da2e3ebdSchin break; 776*da2e3ebdSchin case 2: 777*da2e3ebdSchin file += 2; 778*da2e3ebdSchin goto again; 779*da2e3ebdSchin } 780*da2e3ebdSchin if ((flags & (SEARCH_INCLUDE|SEARCH_NEXT)) == SEARCH_INCLUDE) 781*da2e3ebdSchin { 782*da2e3ebdSchin if (!(pp.mode & GENDEPS)) 783*da2e3ebdSchin { 784*da2e3ebdSchin if (!(pp.option & ALLPOSSIBLE) || pp.in->prev->prev) 785*da2e3ebdSchin error(2, "%s: cannot find include file", file); 786*da2e3ebdSchin } 787*da2e3ebdSchin else if (!(pp.mode & INIT)) 788*da2e3ebdSchin { 789*da2e3ebdSchin xp = ppsetfile(file); 790*da2e3ebdSchin if (!(xp->flags & INC_LISTED)) 791*da2e3ebdSchin { 792*da2e3ebdSchin xp->flags |= INC_LISTED; 793*da2e3ebdSchin if ((pp.column + strlen(file)) >= COLUMN_MAX) 794*da2e3ebdSchin { 795*da2e3ebdSchin sfprintf(pp.filedeps.sp, " \\\n"); 796*da2e3ebdSchin pp.column = COLUMN_TAB; 797*da2e3ebdSchin index = '\t'; 798*da2e3ebdSchin } 799*da2e3ebdSchin else 800*da2e3ebdSchin index = ' '; 801*da2e3ebdSchin pp.column += sfprintf(pp.filedeps.sp, "%c%s", index, file); 802*da2e3ebdSchin } 803*da2e3ebdSchin } 804*da2e3ebdSchin } 805*da2e3ebdSchin } 806*da2e3ebdSchin return fd; 807*da2e3ebdSchin } 808