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