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