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