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
ppmultiple(register struct ppfile * fp,register struct ppsymbol * test)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
search(register struct ppfile * fp,register struct ppdirs * dp,int type,int flags)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
ppsearch(char * file,int type,int flags)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