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