1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1986-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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) 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) 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 fd; 602 int index; 603 char name[MAXTOKEN + 1]; 604 605 pp.include = 0; 606 fd = -1; 607 dospath = 0; 608 again: 609 pathcanon(file, 0); 610 for (cp = pp.chop; cp; cp = cp->next) 611 if (strneq(file, cp->value, cp->op)) 612 { 613 if (cp->value[cp->op + 1]) 614 { 615 sfsprintf(name, sizeof(name) - 1, "%s%s", cp->value + cp->op + 1, file + cp->op); 616 message((-3, "chop: %s -> %s", file, name)); 617 file = name; 618 } 619 else if (strchr(file + cp->op, '/')) 620 { 621 message((-3, "chop: %s -> %s", file, file + cp->op)); 622 file += cp->op; 623 } 624 break; 625 } 626 fp = ppsetfile(file); 627 while ((fp->flags & INC_MAPALL) || (fp->flags & INC_MAPHOSTED) && (pp.mode & HOSTED) || (fp->flags & INC_MAPNOHOSTED) && !(pp.mode & HOSTED)) 628 { 629 if (!(xp = fp->bound[type == T_HEADER ? INC_STANDARD : INC_LOCAL]) || xp == fp) 630 break; 631 message((-1, "map: %s -> %s", fp->name, xp->name)); 632 fp = xp; 633 } 634 if ((fp->flags & INC_MAPNOLOCAL) && (pp.mode & HOSTED)) 635 flags |= SEARCH_HOSTED; 636 else if (pp.vendor) 637 flags |= SEARCH_VENDOR; 638 pp.original = fp; 639 if (type == T_HEADER && strneq(fp->name, "...", 3) && (!fp->name[3] || fp->name[3] == '/')) 640 { 641 if (fp->name[3] == '/') 642 { 643 int n; 644 int m; 645 646 n = strlen(error_info.file); 647 m = strlen(fp->name + 4); 648 if (n < m || !streq(fp->name + 4, error_info.file + n - m)) 649 { 650 if ((fd = ppsearch(fp->name + 4, type, flags|SEARCH_TEST)) < 0) 651 return -1; 652 if (fd > 0) 653 close(fd); 654 s = error_info.file; 655 error_info.file = pp.include; 656 fd = ppsearch(fp->name + 4, type, flags|SEARCH_NEXT); 657 error_info.file = s; 658 return fd; 659 } 660 file = error_info.file + n - m; 661 } 662 else if (file = strrchr(error_info.file, '/')) 663 file++; 664 else 665 file = error_info.file; 666 flags |= SEARCH_NEXT; 667 #if _HUH_2002_05_28 668 if (pp.in->prefix) 669 { 670 sfsprintf(name, sizeof(name) - 1, "%s/%s", pp.in->prefix, file); 671 fp = ppsetfile(name); 672 if ((fd = ppsearch(fp->name, type, flags)) >= 0) 673 return fd; 674 } 675 #endif 676 fp = ppsetfile(file); 677 return ppsearch(fp->name, type, flags); 678 } 679 else if ((flags & SEARCH_INCLUDE) && fp->guard == INC_IGNORE) 680 { 681 strcpy(pp.path, fp->name); 682 message((-2, "%s: ignored", fp->name)); 683 return 0; 684 } 685 else if (!(flags & SEARCH_NEXT)) 686 flags |= SEARCH_SKIP; 687 pp.prefix = 0; 688 if (type == T_HEADER) 689 dp = pp.stddirs->next; 690 else 691 { 692 dp = pp.lcldirs; 693 if (dp == pp.firstdir) 694 { 695 /* 696 * look in directory of including file first 697 */ 698 699 if (error_info.file && (s = strrchr(error_info.file, '/'))) 700 { 701 *s = 0; 702 dp->name = ppsetfile(error_info.file)->name; 703 *s = '/'; 704 } 705 else 706 dp->name = ""; 707 } 708 else if (pp.in->prefix && pp.lcldirs != pp.firstdir) 709 { 710 /* 711 * look in prefix directory of including file first 712 */ 713 714 if (*fp->name != '/') 715 { 716 if ((s = strchr(fp->name, '/')) && (fp->name[0] 717 != '.' || fp->name[1] != '.' || fp->name[2] != '/')) 718 { 719 *s = 0; 720 if (!streq(fp->name, pp.in->prefix)) 721 fd = 0; 722 *s = '/'; 723 } 724 else 725 fd = 0; 726 } 727 if (fd >= 0) 728 { 729 sfsprintf(name, sizeof(name) - 1, "%s/%s", pp.in->prefix, fp->name); 730 pathcanon(name, 0); 731 xp = ppsetfile(name); 732 if ((fd = search(xp, dp, type, flags)) >= 0) 733 return fd; 734 } 735 } 736 } 737 if ((fd = search(fp, dp, type, flags)) < 0) 738 { 739 if ((pp.option & PLUSPLUS) && file != pp.tmpbuf) 740 { 741 s = file + strlen(file); 742 while (s > file && *--s != '/' && *s != '\\' && *s != '.'); 743 if (*s != '.') 744 { 745 sfsprintf(pp.tmpbuf, MAXTOKEN, "%s.h", file); 746 file = pp.tmpbuf; 747 goto again; 748 } 749 } 750 751 /* 752 * hackery for msdos files viewed through unix 753 */ 754 755 switch (dospath) 756 { 757 case 0: 758 if (s = strchr(file, '\\')) 759 { 760 do *s++ = '/'; while (s = strchr(s, '\\')); 761 pathcanon(file, 0); 762 dospath = 1; 763 goto again; 764 } 765 /*FALLTHROUGH*/ 766 case 1: 767 if (ppisid(file[0]) && file[1] == ':' && file[2] == '/') 768 { 769 file[1] = file[0]; 770 file[0] = '/'; 771 pathcanon(file, 0); 772 dospath = 2; 773 goto again; 774 } 775 break; 776 case 2: 777 file += 2; 778 goto again; 779 } 780 if ((flags & (SEARCH_INCLUDE|SEARCH_NEXT)) == SEARCH_INCLUDE) 781 { 782 if (!(pp.mode & GENDEPS)) 783 { 784 if (!(pp.option & ALLPOSSIBLE) || pp.in->prev->prev) 785 error(2, "%s: cannot find include file", file); 786 } 787 else if (!(pp.mode & INIT)) 788 { 789 xp = ppsetfile(file); 790 if (!(xp->flags & INC_LISTED)) 791 { 792 xp->flags |= INC_LISTED; 793 if ((pp.column + strlen(file)) >= COLUMN_MAX) 794 { 795 sfprintf(pp.filedeps.sp, " \\\n"); 796 pp.column = COLUMN_TAB; 797 index = '\t'; 798 } 799 else 800 index = ' '; 801 pp.column += sfprintf(pp.filedeps.sp, "%c%s", index, file); 802 } 803 } 804 } 805 } 806 return fd; 807 } 808