14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1986-2009 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin * Glenn Fowler
234887Schin * AT&T Research
244887Schin *
254887Schin * include file search support
264887Schin */
274887Schin
284887Schin #include "pplib.h"
294887Schin
304887Schin #define SEARCH_NEXT (SEARCH_USER<<1)/* search for next (uncover) */
314887Schin #define SEARCH_SKIP (SEARCH_USER<<2)/* current binding skipped */
324887Schin #define SEARCH_TEST (SEARCH_USER<<3)/* test for binding */
334887Schin #define SEARCH_FOUND (SEARCH_USER<<4)/* current binding found */
344887Schin
354887Schin #define COLUMN_TAB 7
364887Schin #define COLUMN_MAX 72
374887Schin
384887Schin #if ARCHIVE
394887Schin
404887Schin #include <vdb.h>
414887Schin #include <ls.h>
424887Schin
434887Schin #endif
444887Schin
454887Schin /*
464887Schin * multiple include test
474887Schin * fp is a canonicalized ppfile pointer
484887Schin *
494887Schin * test
504887Schin *
514887Schin * INC_CLEAR can be included again
524887Schin * INC_TEST test if include required
534887Schin * <symbol> ifndef guard symbol
544887Schin *
554887Schin * test!=INC_CLEAR returns 1 if file can be included again
564887Schin *
574887Schin * NOTE:
584887Schin *
594887Schin * (1) different hard links to the same file are treated as
604887Schin * different files
614887Schin *
624887Schin * (2) symbolic links in combination with .. may cause two
634887Schin * different files to be treated as the same file:
644887Schin *
654887Schin * "../h/<file>" == "/usr/include/sys/../h/<file>" -> "/usr/include/h/<file>"
664887Schin * "h/<file>" -> "/usr/include/h/<file>"
674887Schin */
684887Schin
694887Schin int
ppmultiple(register struct ppfile * fp,register struct ppsymbol * test)704887Schin ppmultiple(register struct ppfile* fp, register struct ppsymbol* test)
714887Schin {
724887Schin register struct ppsymbol* status;
734887Schin
744887Schin status = fp->guard;
754887Schin 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));
764887Schin if (status == INC_IGNORE)
774887Schin {
784887Schin message((-2, "%s: ignored [%s]", fp->name, pp.ignore));
794887Schin return 0;
804887Schin }
814887Schin if (test == INC_TEST)
824887Schin {
834887Schin if (status != INC_CLEAR)
844887Schin {
85*10898Sroland.mainz@nrubsig.org if (status == INC_TEST || status->macro)
864887Schin {
874887Schin if ((pp.mode & (ALLMULTIPLE|LOADING)) == LOADING)
884887Schin fp->guard = INC_IGNORE;
898462SApril.Chin@Sun.COM if ((pp.state & WARN) && (pp.mode & (HOSTED|MARKHOSTED|RELAX|PEDANTIC)) == PEDANTIC)
904887Schin error(1, "%s: ignored -- already included", fp->name);
914887Schin else
924887Schin message((-3, "%s: ignored -- already included", fp->name));
934887Schin return 0;
944887Schin }
954887Schin return 1;
964887Schin }
974887Schin if ((pp.mode & (ALLMULTIPLE|LOADING)) == LOADING)
984887Schin test = INC_IGNORE;
99*10898Sroland.mainz@nrubsig.org else
100*10898Sroland.mainz@nrubsig.org return 1;
1014887Schin }
1024887Schin fp->guard = test;
1034887Schin return 1;
1044887Schin }
1054887Schin
1064887Schin /*
1074887Schin * search for file using directories in dp
1084887Schin */
1094887Schin
1104887Schin static int
search(register struct ppfile * fp,register struct ppdirs * dp,int type,int flags)1114887Schin search(register struct ppfile* fp, register struct ppdirs* dp, int type, int flags)
1124887Schin {
1134887Schin register char* prefix;
1144887Schin register struct ppdirs* up;
1154887Schin register struct ppfile* xp;
1164887Schin struct ppfile* mp;
1174887Schin int fd;
1184887Schin int index;
1194887Schin int need;
1204887Schin int markhosted;
1214887Schin char* t;
1224887Schin
1234887Schin if (!(pp.option & PREFIX))
1244887Schin prefix = 0;
1254887Schin else if ((prefix = strrchr(fp->name, '/')) && prefix > fp->name)
1264887Schin {
1274887Schin *prefix = 0;
1284887Schin t = ppsetfile(fp->name)->name;
1294887Schin *prefix = '/';
1304887Schin prefix = t;
1314887Schin }
1324887Schin 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",
1334887Schin fp->name,
1344887Schin (flags & SEARCH_INCLUDE) ? "include" : "exists",
1354887Schin (flags & SEARCH_VENDOR) ? " vendor" : "",
1364887Schin (flags & SEARCH_HOSTED) ? " hosted" : "",
1374887Schin (flags & SEARCH_NEXT) ? " next" : "",
1384887Schin (flags & SEARCH_SKIP) ? " skip" : "",
1394887Schin (flags & SEARCH_TEST) ? " test" : "",
1404887Schin type == T_HEADER ? "<*>" : "\"*\"", prefix,
1414887Schin (fp->flags & INC_SELF) ? "SELF|" : "",
1424887Schin (fp->flags & INC_EXISTS) ? "EXISTS|" : "",
1434887Schin (fp->flags & INC_BOUND(INC_PREFIX)) ? "PREFIX|" : "",
1444887Schin (fp->flags & INC_BOUND(INC_LOCAL)) ? "LOCAL|" : "",
1454887Schin (fp->flags & INC_BOUND(INC_VENDOR)) ? "VENDOR|" : "",
1464887Schin (fp->flags & INC_BOUND(INC_STANDARD)) ? "STANDARD|" : "",
1474887Schin dp ? (dp->index == INC_PREFIX ? "pre" : dp->index == INC_LOCAL ? "lcl" : dp->index == INC_VENDOR ? "vnd" : "std") : NiL,
1484887Schin dp ? dp->name : NiL,
1494887Schin !(fp->flags & INC_MEMBER(INC_PREFIX)) && (xp = fp->bound[INC_PREFIX]) ? xp->name : NiL,
1504887Schin !(fp->flags & INC_MEMBER(INC_LOCAL)) && (xp = fp->bound[INC_LOCAL]) ? xp->name : NiL,
1514887Schin !(fp->flags & INC_MEMBER(INC_VENDOR)) && (xp = fp->bound[INC_VENDOR]) ? xp->name : NiL,
1524887Schin !(fp->flags & INC_MEMBER(INC_STANDARD)) && (xp = fp->bound[INC_STANDARD]) ? xp->name : NiL,
1534887Schin error_info.file
1544887Schin ));
1554887Schin if (flags & SEARCH_HOSTED)
1564887Schin need = TYPE_HOSTED;
1574887Schin else if (flags & SEARCH_VENDOR)
1584887Schin need = TYPE_VENDOR;
1594887Schin else
1604887Schin need = TYPE_INCLUDE;
1614887Schin for (index = -1; dp; dp = dp->next)
1624887Schin if (dp->type & need)
1634887Schin {
1644887Schin 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));
1654887Schin #if ARCHIVE
1664887Schin if (!(dp->type & (TYPE_ARCHIVE|TYPE_DIRECTORY)))
1674887Schin {
1684887Schin struct stat st;
1694887Schin
1704887Schin if (stat(dp->name, &st))
1714887Schin {
1724887Schin message((-3, "search: omit %s", dp->name));
1734887Schin dp->type = 0;
1744887Schin continue;
1754887Schin }
1764887Schin if (S_ISREG(st.st_mode))
1774887Schin {
1784887Schin register char* s;
1794887Schin char* e;
1804887Schin int delimiter;
1814887Schin int variant;
1824887Schin unsigned long siz;
1834887Schin unsigned long off;
1844887Schin struct ppmember* ap;
1854887Schin Sfio_t* sp;
1864887Schin
1874887Schin /*
1884887Schin * check for vdb header archive
1894887Schin */
1904887Schin
1914887Schin if (!(sp = sfopen(NiL, dp->name, "r")))
1924887Schin {
1934887Schin error(ERROR_SYSTEM|1, "%s: ignored -- cannot open", dp->name);
1944887Schin dp->type = 0;
1954887Schin continue;
1964887Schin }
1974887Schin variant = sfsprintf(pp.tmpbuf, MAXTOKEN, "%c%s%c%s:archive", VDB_DELIMITER, VDB_MAGIC, VDB_DELIMITER, pp.pass);
1984887Schin if (!(s = sfgetr(sp, '\n', 1)) || !strneq(s, pp.tmpbuf, variant))
1994887Schin {
2004887Schin sfclose(sp);
2014887Schin error(1, "%s: ignored -- not a directory or archive", dp->name);
2024887Schin dp->type = 0;
2034887Schin continue;
2044887Schin }
2054887Schin
2064887Schin /*
2074887Schin * parse the options
2084887Schin */
2094887Schin
2104887Schin dp->type |= TYPE_ARCHIVE;
2114887Schin for (s += variant;;)
2124887Schin {
2134887Schin while (*s == ' ') s++;
2144887Schin e = s;
2154887Schin for (t = 0; *s && *s != ' '; s++)
2164887Schin if (*s == '=')
2174887Schin {
2184887Schin *s = 0;
2194887Schin t = s + 1;
2204887Schin }
2214887Schin if (*s)
2224887Schin *s++ = 0;
2234887Schin if (!*e)
2244887Schin break;
2254887Schin switch ((int)hashref(pp.strtab, e))
2264887Schin {
2274887Schin case X_CHECKPOINT:
2284887Schin #if CHECKPOINT
2294887Schin dp->type |= TYPE_CHECKPOINT;
2304887Schin break;
2314887Schin #else
2324887Schin error(1, "preprocessor not compiled with checkpoint enabled");
2334887Schin goto notvdb;
2344887Schin #endif
2354887Schin case X_HIDE:
2364887Schin
2374887Schin if (t)
2384887Schin error(1, "%s: %s: archive option value ignored", e);
2394887Schin if (e = strrchr(dp->name, '/'))
2404887Schin *e = 0;
2414887Schin else
2424887Schin dp->name = ".";
2434887Schin break;
2444887Schin case X_MAP:
2454887Schin if (!t)
2464887Schin error(1, "%s: archive option value expected", e);
2474887Schin else
2484887Schin dp->name = strdup(t);
2494887Schin break;
2504887Schin default:
2514887Schin error(1, "%s: unknown archive option", e);
2524887Schin break;
2534887Schin }
2544887Schin }
2554887Schin if (sfseek(sp, -(VDB_LENGTH + 1), SEEK_END) <= 0 || !(s = sfgetr(sp, '\n', 1)))
2564887Schin {
2574887Schin notvdb:
2584887Schin sfclose(sp);
2594887Schin error(1, "%s: ignored -- cannot load archive", dp->name);
2604887Schin dp->type = 0;
2614887Schin continue;
2624887Schin }
2634887Schin if (variant = *s != 0)
2644887Schin s++;
2654887Schin else if (!(s = sfgetr(sp, '\n', 1)))
2664887Schin goto notvdb;
2674887Schin if (sfvalue(sp) != (VDB_LENGTH + variant))
2684887Schin goto notvdb;
2694887Schin if (!strneq(s, VDB_DIRECTORY, sizeof(VDB_DIRECTORY) - 1))
2704887Schin goto notvdb;
2714887Schin delimiter = s[VDB_OFFSET - 1];
2724887Schin off = strtol(s + VDB_OFFSET, NiL, 10) - sizeof(VDB_DIRECTORY);
2734887Schin siz = strtol(s + VDB_SIZE, NiL, 10);
2744887Schin if (sfseek(sp, off, SEEK_SET) != off)
2754887Schin goto notvdb;
2764887Schin if (!(s = sfreserve(sp, siz + 1, 0)))
2774887Schin goto notvdb;
2784887Schin s[siz] = 0;
2794887Schin if (!strneq(s, VDB_DIRECTORY, sizeof(VDB_DIRECTORY)) - 1)
2804887Schin goto notvdb;
2814887Schin if (!(s = strchr(s, '\n')))
2824887Schin goto notvdb;
2834887Schin s++;
2844887Schin while (e = strchr(s, '\n'))
2854887Schin {
2864887Schin delimiter = variant ? *s++ : delimiter;
2874887Schin if (!(t = strchr(s, delimiter)))
2884887Schin break;
2894887Schin *t = 0;
2904887Schin if (!streq(s, VDB_DIRECTORY))
2914887Schin {
2924887Schin pathcanon(s, 0);
2934887Schin ap = newof(0, struct ppmember, 1, 0);
2944887Schin ap->archive = dp;
2954887Schin ap->offset = strtol(t + 1, &t, 10);
2964887Schin ap->size = strtol(t + 1, NiL, 10);
2974887Schin xp = ppsetfile(s);
2984887Schin xp->flags |= INC_MEMBER(dp->index);
2994887Schin xp->bound[dp->index] = (struct ppfile*)ap;
3004887Schin 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);
3014887Schin }
3024887Schin s = e + 1;
3034887Schin }
3044887Schin if (sfseek(sp, 0L, SEEK_SET))
3054887Schin goto notvdb;
3064887Schin if (!(pp.test & 0x4000) &&
3074887Schin #if POOL
3084887Schin (pp.pool.input || !(dp->type & TYPE_CHECKPOINT))
3094887Schin #else
3104887Schin !(dp->type & TYPE_CHECKPOINT)
3114887Schin #endif
3124887Schin && (dp->info.buffer = sfreserve(sp, off, 0)))
3134887Schin dp->type |= TYPE_BUFFER;
3144887Schin else
3154887Schin {
3164887Schin dp->info.sp = sp;
3174887Schin #if POOL
3184887Schin if (pp.pool.input)
3194887Schin sfset(sp, SF_SHARE, 1);
3204887Schin #endif
3214887Schin }
3224887Schin }
3234887Schin else
3244887Schin dp->type |= TYPE_DIRECTORY;
3254887Schin }
3264887Schin #endif
3274887Schin if (streq(fp->name, "."))
3284887Schin continue;
3294887Schin if (prefix && *fp->name != '/' && dp->index != INC_PREFIX)
3304887Schin #if ARCHIVE
3314887Schin if (dp->type & TYPE_DIRECTORY)
3324887Schin #endif
3334887Schin {
3344887Schin for (up = dp->info.subdir; up; up = up->next)
3354887Schin if (up->name == prefix)
3364887Schin break;
3374887Schin if (!up)
3384887Schin {
3394887Schin up = newof(0, struct ppdirs, 1, 0);
3404887Schin up->name = prefix;
3414887Schin up->type = dp->type;
3424887Schin up->next = dp->info.subdir;
3434887Schin dp->info.subdir = up;
3444887Schin if (!*dp->name)
3454887Schin t = prefix;
3464887Schin else
3474887Schin sfsprintf(t = pp.path, PATH_MAX - 1, "%s/%s", dp->name, prefix);
3484887Schin if (eaccess(t, X_OK))
3494887Schin {
3504887Schin message((-3, "search: omit %s", t));
3514887Schin continue;
3524887Schin }
3534887Schin up->type |= TYPE_HOSTED;
3544887Schin }
3554887Schin else if (!(up->type & TYPE_HOSTED))
3564887Schin continue;
3574887Schin }
3584887Schin mp = xp = 0;
3594887Schin if (!(flags & SEARCH_NEXT) && index != dp->index && (!(need & TYPE_HOSTED) || dp->index == INC_STANDARD) && (!(need & TYPE_VENDOR) || dp->index == INC_VENDOR))
3604887Schin {
3614887Schin if (index >= 0 && !(fp->flags & INC_MEMBER(index)))
3624887Schin fp->flags |= INC_BOUND(index);
3634887Schin index = dp->index;
3644887Schin if (fp->flags & INC_BOUND(index))
3654887Schin {
3664887Schin xp = fp->bound[index];
3674887Schin if (index == INC_PREFIX)
3684887Schin {
3694887Schin if (*fp->name == '/' || !*dp->name)
3704887Schin strcpy(pp.path, fp->name);
3714887Schin else
3724887Schin sfsprintf(pp.path, PATH_MAX - 1, "%s/%s", dp->name, fp->name);
3734887Schin pathcanon(pp.path, 0);
3744887Schin if (!xp || !streq(xp->name, pp.path))
3754887Schin {
3764887Schin fp->bound[index] = xp = ppsetfile(pp.path);
3774887Schin if (dp->type & TYPE_HOSTED)
3784887Schin xp->flags |= INC_HOSTED;
3794887Schin if ((flags & SEARCH_INCLUDE) || (xp->flags & INC_EXISTS))
3804887Schin {
3814887Schin if (!(flags & SEARCH_INCLUDE))
3824887Schin return 0;
3834887Schin if (!ppmultiple(xp, INC_TEST))
3844887Schin {
3854887Schin if (flags & SEARCH_TEST)
3864887Schin pp.include = xp->name;
3874887Schin return 0;
3884887Schin }
3894887Schin mp = xp;
3904887Schin }
3914887Schin }
3924887Schin }
3934887Schin else if (!xp)
3944887Schin {
3954887Schin while (dp->next && dp->next->index == index)
3964887Schin dp = dp->next;
3974887Schin message((-3, "search: omit %s/%s", dp->name, fp->name));
3984887Schin continue;
3994887Schin }
4004887Schin else
4014887Schin {
4024887Schin strcpy(pp.path, xp->name);
4034887Schin if (!(flags & SEARCH_INCLUDE))
4044887Schin return 0;
4054887Schin if (!ppmultiple(xp, INC_TEST))
4064887Schin {
4074887Schin if (flags & SEARCH_TEST)
4084887Schin pp.include = xp->name;
4094887Schin return 0;
4104887Schin }
4114887Schin mp = xp;
4124887Schin }
4134887Schin }
4144887Schin }
4154887Schin if (!(fp->flags & INC_BOUND(index)) || (flags & SEARCH_NEXT))
4164887Schin {
4174887Schin if (*fp->name == '/' || !*dp->name)
4184887Schin strcpy(pp.path, fp->name);
4194887Schin else
4204887Schin sfsprintf(pp.path, PATH_MAX - 1, "%s/%s", dp->name, fp->name);
4214887Schin pathcanon(pp.path, 0);
4224887Schin if (!(flags & SEARCH_SKIP))
4234887Schin {
4244887Schin int found;
4254887Schin struct ppinstk* in;
4264887Schin
4274887Schin if (streq(error_info.file, pp.path))
4284887Schin found = 1;
4294887Schin else
4304887Schin {
4314887Schin found = 0;
4324887Schin for (in = pp.in; in; in = in->prev)
4334887Schin if (in->type == IN_FILE && in->file && streq(in->file, pp.path))
4344887Schin {
4354887Schin found = 1;
4364887Schin break;
4374887Schin }
4384887Schin }
4394887Schin if (found)
4404887Schin {
4414887Schin flags |= SEARCH_FOUND;
4424887Schin continue;
4434887Schin }
4444887Schin if (!(flags & SEARCH_FOUND))
4454887Schin continue;
4464887Schin }
4474887Schin }
4484887Schin if ((xp || (xp = ppgetfile(pp.path))) && (xp->flags & INC_SELF))
4494887Schin {
4504887Schin if (xp->flags & INC_EXISTS)
4514887Schin {
4524887Schin if (!(flags & SEARCH_INCLUDE))
4534887Schin return 0;
4544887Schin if (!(flags & SEARCH_NEXT) && mp != xp && (mp = xp) && !ppmultiple(xp, INC_TEST))
4554887Schin {
4564887Schin if (flags & SEARCH_TEST)
4574887Schin pp.include = xp->name;
4584887Schin return 0;
4594887Schin }
4604887Schin }
4614887Schin else if (*fp->name == '/')
4624887Schin break;
4634887Schin else
4644887Schin continue;
4654887Schin }
4664887Schin message((-3, "search: file=%s path=%s", fp->name, pp.path));
4674887Schin #if ARCHIVE
4684887Schin 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);
4694887Schin if ((fp->flags & INC_MEMBER(index)) && ((struct ppmember*)fp->bound[index])->archive == dp)
4704887Schin {
4714887Schin fd = 0;
4724887Schin pp.member = (struct ppmember*)fp->bound[index];
4734887Schin 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);
4744887Schin }
4754887Schin else if (!(dp->type & TYPE_DIRECTORY))
4764887Schin continue;
4774887Schin else
4784887Schin #endif
4794887Schin {
4804887Schin pp.member = 0;
4814887Schin fd = (flags & SEARCH_INCLUDE) ? open(pp.path, O_RDONLY) : eaccess(pp.path, R_OK);
4824887Schin }
4834887Schin if (fd >= 0)
4844887Schin {
4854887Schin pp.found = dp;
4864887Schin if ((pp.option & (PLUSPLUS|NOPROTO)) == PLUSPLUS && !(pp.test & TEST_noproto))
4874887Schin {
4884887Schin if (dp->c)
4894887Schin pp.mode |= MARKC;
4904887Schin else
4914887Schin pp.mode &= ~MARKC;
4924887Schin }
4934887Schin if (xp)
4944887Schin markhosted = xp->flags & INC_HOSTED;
4954887Schin else if (!(markhosted = (dp->type & TYPE_HOSTED)) && dp->index == INC_PREFIX && (pp.mode & (FILEDEPS|HEADERDEPS|INIT)) == FILEDEPS)
4964887Schin {
4974887Schin up = dp;
4984887Schin while ((up = up->next) && !streq(up->name, dp->name));
4994887Schin if (up && (up->type & TYPE_HOSTED))
5004887Schin markhosted = 1;
5014887Schin }
5024887Schin if (markhosted)
5034887Schin pp.mode |= MARKHOSTED;
5044887Schin else
5054887Schin pp.mode &= ~MARKHOSTED;
5064887Schin xp = ppsetfile(pp.path);
5074887Schin if (markhosted)
5084887Schin xp->flags |= INC_HOSTED;
5094887Schin message((-2, "search: %s -> %s%s%s", fp->name, pp.path, (pp.mode & MARKC) ? " [C]" : "", (pp.mode & MARKHOSTED) ? " [hosted]" : ""));
5104887Schin #if ARCHIVE
5114887Schin if (!pp.member)
5124887Schin {
5134887Schin #endif
5144887Schin fp->flags |= INC_BOUND(index);
5154887Schin fp->bound[index] = xp;
5164887Schin if ((index == INC_STANDARD || index == INC_VENDOR) && type != T_HEADER && !(fp->flags & INC_BOUND(INC_LOCAL)))
5174887Schin {
5184887Schin fp->flags |= INC_BOUND(INC_LOCAL);
5194887Schin fp->bound[INC_LOCAL] = xp;
5204887Schin }
5214887Schin #if ARCHIVE
5224887Schin }
5234887Schin #endif
5244887Schin xp->flags |= INC_SELF|INC_EXISTS;
5254887Schin if (flags & SEARCH_INCLUDE)
5264887Schin {
5274887Schin if ((pp.prefix = prefix) || (pp.prefix = pp.in->prefix))
5284887Schin message((-2, "search: %s: prefix=%s", xp->name, pp.prefix));
5294887Schin if (!(pp.mode & ALLMULTIPLE))
5304887Schin {
5314887Schin if (xp->guard == INC_CLEAR || xp == mp)
5324887Schin xp->guard = INC_TEST;
5334887Schin else
5344887Schin {
5358462SApril.Chin@Sun.COM if ((pp.state & WARN) && (pp.mode & (HOSTED|MARKHOSTED|RELAX|PEDANTIC)) == PEDANTIC)
5364887Schin error(1, "%s: ignored -- already included", xp->name);
5374887Schin else
5384887Schin message((-3, "%s: ignored -- already included", xp->name));
5394887Schin xp->guard = fp->guard = INC_IGNORE;
5404887Schin #if ARCHIVE
5414887Schin if (!pp.member)
5424887Schin #endif
5434887Schin if (fd > 0)
5444887Schin close(fd);
5454887Schin if (flags & SEARCH_TEST)
5464887Schin pp.include = xp->name;
5474887Schin return 0;
5484887Schin }
5494887Schin }
5504887Schin pp.include = xp->name;
5514887Schin if ((pp.mode & (FILEDEPS|INIT)) == FILEDEPS && ((pp.mode & HEADERDEPS) || !(pp.mode & MARKHOSTED)) && !(xp->flags & INC_LISTED))
5524887Schin {
5534887Schin xp->flags |= INC_LISTED;
5544887Schin if ((pp.column + strlen(xp->name)) >= COLUMN_MAX)
5554887Schin {
5564887Schin sfprintf(pp.filedeps.sp, " \\\n");
5574887Schin pp.column = COLUMN_TAB;
5584887Schin index = '\t';
5594887Schin }
5604887Schin else
5614887Schin index = ' ';
5624887Schin pp.column += sfprintf(pp.filedeps.sp, "%c%s", index, xp->name);
5634887Schin }
5644887Schin }
5654887Schin return fd;
5664887Schin }
5674887Schin if (xp)
5684887Schin xp->flags |= INC_SELF;
5694887Schin if (errno == EMFILE)
5704887Schin error(3, "%s: too many open files", fp->name);
5714887Schin else if (errno != ENOENT && errno != ENOTDIR)
5724887Schin error(ERROR_SYSTEM|1, "%s: cannot open file for reading", pp.path);
5734887Schin if (*fp->name == '/')
5744887Schin break;
5754887Schin }
5764887Schin strcpy(pp.path, fp->name);
5774887Schin message((-2, "search: %s%s not found", (flags & SEARCH_NEXT) ? "next " : "", fp->name));
5784887Schin return -1;
5794887Schin }
5804887Schin
5814887Schin /*
5824887Schin * search for an include file
5834887Schin * if (flags&SEARCH_INCLUDE) then
5844887Schin * if file found then open read file descriptor returned
5854887Schin * with pp.path set to the full path and
5864887Schin * pp.prefix set to the directory prefix
5874887Schin * otherwise 0 returned if file found but ignored
5884887Schin * otherwise -1 returned
5894887Schin * otherwise
5904887Schin * if file found then 0 returned
5914887Schin * otherwise -1 returned
5924887Schin */
5934887Schin
5944887Schin int
ppsearch(char * file,int type,int flags)5954887Schin ppsearch(char* file, int type, int flags)
5964887Schin {
5974887Schin register struct ppfile* fp;
5984887Schin register char* s;
5994887Schin register struct ppdirs* dp;
6004887Schin struct oplist* cp;
6014887Schin struct ppfile* xp;
6024887Schin int dospath;
6038462SApril.Chin@Sun.COM int chop;
6044887Schin int fd;
6054887Schin int index;
6064887Schin char name[MAXTOKEN + 1];
6074887Schin
6084887Schin pp.include = 0;
6094887Schin fd = -1;
6108462SApril.Chin@Sun.COM chop = 0;
611*10898Sroland.mainz@nrubsig.org if (s = strchr(file, '\\'))
612*10898Sroland.mainz@nrubsig.org {
613*10898Sroland.mainz@nrubsig.org do *s++ = '/'; while (s = strchr(s, '\\'));
614*10898Sroland.mainz@nrubsig.org dospath = 1;
615*10898Sroland.mainz@nrubsig.org }
616*10898Sroland.mainz@nrubsig.org else
617*10898Sroland.mainz@nrubsig.org dospath = 0;
6184887Schin again:
6194887Schin pathcanon(file, 0);
6208462SApril.Chin@Sun.COM if (chop)
6218462SApril.Chin@Sun.COM for (cp = pp.chop; cp; cp = cp->next)
6228462SApril.Chin@Sun.COM if (strneq(file, cp->value, cp->op))
6234887Schin {
6248462SApril.Chin@Sun.COM if (cp->value[cp->op + 1])
6258462SApril.Chin@Sun.COM {
6268462SApril.Chin@Sun.COM sfsprintf(name, sizeof(name) - 1, "%s%s", cp->value + cp->op + 1, file + cp->op);
6278462SApril.Chin@Sun.COM message((-2, "search: %s -> %s", file, name));
6288462SApril.Chin@Sun.COM file = name;
6298462SApril.Chin@Sun.COM }
6308462SApril.Chin@Sun.COM else if (strchr(file + cp->op, '/'))
6318462SApril.Chin@Sun.COM {
6328462SApril.Chin@Sun.COM message((-2, "search: %s -> %s", file, file + cp->op));
6338462SApril.Chin@Sun.COM file += cp->op;
6348462SApril.Chin@Sun.COM }
6358462SApril.Chin@Sun.COM break;
6364887Schin }
6374887Schin fp = ppsetfile(file);
6384887Schin while ((fp->flags & INC_MAPALL) || (fp->flags & INC_MAPHOSTED) && (pp.mode & HOSTED) || (fp->flags & INC_MAPNOHOSTED) && !(pp.mode & HOSTED))
6394887Schin {
6404887Schin if (!(xp = fp->bound[type == T_HEADER ? INC_STANDARD : INC_LOCAL]) || xp == fp)
6414887Schin break;
6424887Schin message((-1, "map: %s -> %s", fp->name, xp->name));
6434887Schin fp = xp;
6444887Schin }
6454887Schin if ((fp->flags & INC_MAPNOLOCAL) && (pp.mode & HOSTED))
6464887Schin flags |= SEARCH_HOSTED;
6474887Schin else if (pp.vendor)
6484887Schin flags |= SEARCH_VENDOR;
6494887Schin pp.original = fp;
6504887Schin if (type == T_HEADER && strneq(fp->name, "...", 3) && (!fp->name[3] || fp->name[3] == '/'))
6514887Schin {
6524887Schin if (fp->name[3] == '/')
6534887Schin {
6544887Schin int n;
6554887Schin int m;
6564887Schin
6574887Schin n = strlen(error_info.file);
6584887Schin m = strlen(fp->name + 4);
6594887Schin if (n < m || !streq(fp->name + 4, error_info.file + n - m))
6604887Schin {
6614887Schin if ((fd = ppsearch(fp->name + 4, type, flags|SEARCH_TEST)) < 0)
6624887Schin return -1;
6634887Schin if (fd > 0)
6644887Schin close(fd);
6654887Schin s = error_info.file;
6664887Schin error_info.file = pp.include;
6674887Schin fd = ppsearch(fp->name + 4, type, flags|SEARCH_NEXT);
6684887Schin error_info.file = s;
6694887Schin return fd;
6704887Schin }
6714887Schin file = error_info.file + n - m;
6724887Schin }
6734887Schin else if (file = strrchr(error_info.file, '/'))
6744887Schin file++;
6754887Schin else
6764887Schin file = error_info.file;
6774887Schin flags |= SEARCH_NEXT;
6784887Schin #if _HUH_2002_05_28
6794887Schin if (pp.in->prefix)
6804887Schin {
6814887Schin sfsprintf(name, sizeof(name) - 1, "%s/%s", pp.in->prefix, file);
6824887Schin fp = ppsetfile(name);
6834887Schin if ((fd = ppsearch(fp->name, type, flags)) >= 0)
6844887Schin return fd;
6854887Schin }
6864887Schin #endif
6874887Schin fp = ppsetfile(file);
6884887Schin return ppsearch(fp->name, type, flags);
6894887Schin }
6904887Schin else if ((flags & SEARCH_INCLUDE) && fp->guard == INC_IGNORE)
6914887Schin {
6924887Schin strcpy(pp.path, fp->name);
6934887Schin message((-2, "%s: ignored", fp->name));
6944887Schin return 0;
6954887Schin }
6964887Schin else if (!(flags & SEARCH_NEXT))
6974887Schin flags |= SEARCH_SKIP;
6984887Schin pp.prefix = 0;
6994887Schin if (type == T_HEADER)
7004887Schin dp = pp.stddirs->next;
7014887Schin else
7024887Schin {
7034887Schin dp = pp.lcldirs;
7044887Schin if (dp == pp.firstdir)
7054887Schin {
7064887Schin /*
7074887Schin * look in directory of including file first
7084887Schin */
7094887Schin
7104887Schin if (error_info.file && (s = strrchr(error_info.file, '/')))
7114887Schin {
7124887Schin *s = 0;
7134887Schin dp->name = ppsetfile(error_info.file)->name;
7144887Schin *s = '/';
7154887Schin }
7164887Schin else
7174887Schin dp->name = "";
7184887Schin }
7194887Schin else if (pp.in->prefix && pp.lcldirs != pp.firstdir)
7204887Schin {
7214887Schin /*
7224887Schin * look in prefix directory of including file first
7234887Schin */
7244887Schin
7254887Schin if (*fp->name != '/')
7264887Schin {
7274887Schin if ((s = strchr(fp->name, '/')) && (fp->name[0]
7284887Schin != '.' || fp->name[1] != '.' || fp->name[2] != '/'))
7294887Schin {
7304887Schin *s = 0;
7314887Schin if (!streq(fp->name, pp.in->prefix))
7324887Schin fd = 0;
7334887Schin *s = '/';
7344887Schin }
7354887Schin else
7364887Schin fd = 0;
7374887Schin }
7384887Schin if (fd >= 0)
7394887Schin {
7404887Schin sfsprintf(name, sizeof(name) - 1, "%s/%s", pp.in->prefix, fp->name);
7414887Schin pathcanon(name, 0);
7424887Schin xp = ppsetfile(name);
7434887Schin if ((fd = search(xp, dp, type, flags)) >= 0)
7444887Schin return fd;
7454887Schin }
7464887Schin }
7474887Schin }
7484887Schin if ((fd = search(fp, dp, type, flags)) < 0)
7494887Schin {
7504887Schin if ((pp.option & PLUSPLUS) && file != pp.tmpbuf)
7514887Schin {
7524887Schin s = file + strlen(file);
7534887Schin while (s > file && *--s != '/' && *s != '\\' && *s != '.');
7544887Schin if (*s != '.')
7554887Schin {
7564887Schin sfsprintf(pp.tmpbuf, MAXTOKEN, "%s.h", file);
7574887Schin file = pp.tmpbuf;
7584887Schin goto again;
7594887Schin }
7604887Schin }
7614887Schin
7624887Schin /*
7634887Schin * hackery for msdos files viewed through unix
7644887Schin */
7654887Schin
7664887Schin switch (dospath)
7674887Schin {
7684887Schin case 1:
7694887Schin if (ppisid(file[0]) && file[1] == ':' && file[2] == '/')
7704887Schin {
7714887Schin file[1] = file[0];
7724887Schin file[0] = '/';
7734887Schin pathcanon(file, 0);
7744887Schin dospath = 2;
7754887Schin goto again;
7764887Schin }
7774887Schin break;
7784887Schin case 2:
7794887Schin file += 2;
7804887Schin goto again;
7814887Schin }
7824887Schin if ((flags & (SEARCH_INCLUDE|SEARCH_NEXT)) == SEARCH_INCLUDE)
7834887Schin {
7848462SApril.Chin@Sun.COM if (!chop && pp.chop)
7858462SApril.Chin@Sun.COM {
7868462SApril.Chin@Sun.COM chop = 1;
7878462SApril.Chin@Sun.COM type = T_STRING;
7888462SApril.Chin@Sun.COM goto again;
7898462SApril.Chin@Sun.COM }
7904887Schin if (!(pp.mode & GENDEPS))
7914887Schin {
7924887Schin if (!(pp.option & ALLPOSSIBLE) || pp.in->prev->prev)
7934887Schin error(2, "%s: cannot find include file", file);
7944887Schin }
7954887Schin else if (!(pp.mode & INIT))
7964887Schin {
7974887Schin xp = ppsetfile(file);
7984887Schin if (!(xp->flags & INC_LISTED))
7994887Schin {
8004887Schin xp->flags |= INC_LISTED;
8014887Schin if ((pp.column + strlen(file)) >= COLUMN_MAX)
8024887Schin {
8034887Schin sfprintf(pp.filedeps.sp, " \\\n");
8044887Schin pp.column = COLUMN_TAB;
8054887Schin index = '\t';
8064887Schin }
8074887Schin else
8084887Schin index = ' ';
8094887Schin pp.column += sfprintf(pp.filedeps.sp, "%c%s", index, file);
8104887Schin }
8114887Schin }
8124887Schin }
8134887Schin }
8144887Schin return fd;
8154887Schin }
816