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