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