xref: /netbsd-src/external/gpl2/gmake/dist/vpath.c (revision 69606e3f5c9388e52aed8c120ad63c049ca45d8f)
1*69606e3fSchristos /* Implementation of pattern-matching file search paths for GNU Make.
2*69606e3fSchristos Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3*69606e3fSchristos 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
4*69606e3fSchristos Foundation, Inc.
5*69606e3fSchristos This file is part of GNU Make.
6*69606e3fSchristos 
7*69606e3fSchristos GNU Make is free software; you can redistribute it and/or modify it under the
8*69606e3fSchristos terms of the GNU General Public License as published by the Free Software
9*69606e3fSchristos Foundation; either version 2, or (at your option) any later version.
10*69606e3fSchristos 
11*69606e3fSchristos GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12*69606e3fSchristos WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13*69606e3fSchristos A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
14*69606e3fSchristos 
15*69606e3fSchristos You should have received a copy of the GNU General Public License along with
16*69606e3fSchristos GNU Make; see the file COPYING.  If not, write to the Free Software
17*69606e3fSchristos Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
18*69606e3fSchristos 
19*69606e3fSchristos #include "make.h"
20*69606e3fSchristos #include "filedef.h"
21*69606e3fSchristos #include "variable.h"
22*69606e3fSchristos #ifdef WINDOWS32
23*69606e3fSchristos #include "pathstuff.h"
24*69606e3fSchristos #endif
25*69606e3fSchristos 
26*69606e3fSchristos 
27*69606e3fSchristos /* Structure used to represent a selective VPATH searchpath.  */
28*69606e3fSchristos 
29*69606e3fSchristos struct vpath
30*69606e3fSchristos   {
31*69606e3fSchristos     struct vpath *next;	/* Pointer to next struct in the linked list.  */
32*69606e3fSchristos     char *pattern;	/* The pattern to match.  */
33*69606e3fSchristos     char *percent;	/* Pointer into `pattern' where the `%' is.  */
34*69606e3fSchristos     unsigned int patlen;/* Length of the pattern.  */
35*69606e3fSchristos     char **searchpath;	/* Null-terminated list of directories.  */
36*69606e3fSchristos     unsigned int maxlen;/* Maximum length of any entry in the list.  */
37*69606e3fSchristos   };
38*69606e3fSchristos 
39*69606e3fSchristos /* Linked-list of all selective VPATHs.  */
40*69606e3fSchristos 
41*69606e3fSchristos static struct vpath *vpaths;
42*69606e3fSchristos 
43*69606e3fSchristos /* Structure for the general VPATH given in the variable.  */
44*69606e3fSchristos 
45*69606e3fSchristos static struct vpath *general_vpath;
46*69606e3fSchristos 
47*69606e3fSchristos /* Structure for GPATH given in the variable.  */
48*69606e3fSchristos 
49*69606e3fSchristos static struct vpath *gpaths;
50*69606e3fSchristos 
51*69606e3fSchristos static int selective_vpath_search PARAMS ((struct vpath *path, char **file, FILE_TIMESTAMP *mtime_ptr));
52*69606e3fSchristos 
53*69606e3fSchristos /* Reverse the chain of selective VPATH lists so they
54*69606e3fSchristos    will be searched in the order given in the makefiles
55*69606e3fSchristos    and construct the list from the VPATH variable.  */
56*69606e3fSchristos 
57*69606e3fSchristos void
build_vpath_lists()58*69606e3fSchristos build_vpath_lists ()
59*69606e3fSchristos {
60*69606e3fSchristos   register struct vpath *new = 0;
61*69606e3fSchristos   register struct vpath *old, *nexto;
62*69606e3fSchristos   register char *p;
63*69606e3fSchristos 
64*69606e3fSchristos   /* Reverse the chain.  */
65*69606e3fSchristos   for (old = vpaths; old != 0; old = nexto)
66*69606e3fSchristos     {
67*69606e3fSchristos       nexto = old->next;
68*69606e3fSchristos       old->next = new;
69*69606e3fSchristos       new = old;
70*69606e3fSchristos     }
71*69606e3fSchristos 
72*69606e3fSchristos   vpaths = new;
73*69606e3fSchristos 
74*69606e3fSchristos   /* If there is a VPATH variable with a nonnull value, construct the
75*69606e3fSchristos      general VPATH list from it.  We use variable_expand rather than just
76*69606e3fSchristos      calling lookup_variable so that it will be recursively expanded.  */
77*69606e3fSchristos 
78*69606e3fSchristos   {
79*69606e3fSchristos     /* Turn off --warn-undefined-variables while we expand SHELL and IFS.  */
80*69606e3fSchristos     int save = warn_undefined_variables_flag;
81*69606e3fSchristos     warn_undefined_variables_flag = 0;
82*69606e3fSchristos 
83*69606e3fSchristos     p = variable_expand ("$(strip $(VPATH))");
84*69606e3fSchristos 
85*69606e3fSchristos     warn_undefined_variables_flag = save;
86*69606e3fSchristos   }
87*69606e3fSchristos 
88*69606e3fSchristos   if (*p != '\0')
89*69606e3fSchristos     {
90*69606e3fSchristos       /* Save the list of vpaths.  */
91*69606e3fSchristos       struct vpath *save_vpaths = vpaths;
92*69606e3fSchristos 
93*69606e3fSchristos       /* Empty `vpaths' so the new one will have no next, and `vpaths'
94*69606e3fSchristos 	 will still be nil if P contains no existing directories.  */
95*69606e3fSchristos       vpaths = 0;
96*69606e3fSchristos 
97*69606e3fSchristos       /* Parse P.  */
98*69606e3fSchristos       construct_vpath_list ("%", p);
99*69606e3fSchristos 
100*69606e3fSchristos       /* Store the created path as the general path,
101*69606e3fSchristos 	 and restore the old list of vpaths.  */
102*69606e3fSchristos       general_vpath = vpaths;
103*69606e3fSchristos       vpaths = save_vpaths;
104*69606e3fSchristos     }
105*69606e3fSchristos 
106*69606e3fSchristos   /* If there is a GPATH variable with a nonnull value, construct the
107*69606e3fSchristos      GPATH list from it.  We use variable_expand rather than just
108*69606e3fSchristos      calling lookup_variable so that it will be recursively expanded.  */
109*69606e3fSchristos 
110*69606e3fSchristos   {
111*69606e3fSchristos     /* Turn off --warn-undefined-variables while we expand SHELL and IFS.  */
112*69606e3fSchristos     int save = warn_undefined_variables_flag;
113*69606e3fSchristos     warn_undefined_variables_flag = 0;
114*69606e3fSchristos 
115*69606e3fSchristos     p = variable_expand ("$(strip $(GPATH))");
116*69606e3fSchristos 
117*69606e3fSchristos     warn_undefined_variables_flag = save;
118*69606e3fSchristos   }
119*69606e3fSchristos 
120*69606e3fSchristos   if (*p != '\0')
121*69606e3fSchristos     {
122*69606e3fSchristos       /* Save the list of vpaths.  */
123*69606e3fSchristos       struct vpath *save_vpaths = vpaths;
124*69606e3fSchristos 
125*69606e3fSchristos       /* Empty `vpaths' so the new one will have no next, and `vpaths'
126*69606e3fSchristos 	 will still be nil if P contains no existing directories.  */
127*69606e3fSchristos       vpaths = 0;
128*69606e3fSchristos 
129*69606e3fSchristos       /* Parse P.  */
130*69606e3fSchristos       construct_vpath_list ("%", p);
131*69606e3fSchristos 
132*69606e3fSchristos       /* Store the created path as the GPATH,
133*69606e3fSchristos 	 and restore the old list of vpaths.  */
134*69606e3fSchristos       gpaths = vpaths;
135*69606e3fSchristos       vpaths = save_vpaths;
136*69606e3fSchristos     }
137*69606e3fSchristos }
138*69606e3fSchristos 
139*69606e3fSchristos /* Construct the VPATH listing for the pattern and searchpath given.
140*69606e3fSchristos 
141*69606e3fSchristos    This function is called to generate selective VPATH lists and also for
142*69606e3fSchristos    the general VPATH list (which is in fact just a selective VPATH that
143*69606e3fSchristos    is applied to everything).  The returned pointer is either put in the
144*69606e3fSchristos    linked list of all selective VPATH lists or in the GENERAL_VPATH
145*69606e3fSchristos    variable.
146*69606e3fSchristos 
147*69606e3fSchristos    If SEARCHPATH is nil, remove all previous listings with the same
148*69606e3fSchristos    pattern.  If PATTERN is nil, remove all VPATH listings.  Existing
149*69606e3fSchristos    and readable directories that are not "." given in the searchpath
150*69606e3fSchristos    separated by the path element separator (defined in make.h) are
151*69606e3fSchristos    loaded into the directory hash table if they are not there already
152*69606e3fSchristos    and put in the VPATH searchpath for the given pattern with trailing
153*69606e3fSchristos    slashes stripped off if present (and if the directory is not the
154*69606e3fSchristos    root, "/").  The length of the longest entry in the list is put in
155*69606e3fSchristos    the structure as well.  The new entry will be at the head of the
156*69606e3fSchristos    VPATHS chain.  */
157*69606e3fSchristos 
158*69606e3fSchristos void
construct_vpath_list(char * pattern,char * dirpath)159*69606e3fSchristos construct_vpath_list (char *pattern, char *dirpath)
160*69606e3fSchristos {
161*69606e3fSchristos   register unsigned int elem;
162*69606e3fSchristos   register char *p;
163*69606e3fSchristos   register char **vpath;
164*69606e3fSchristos   register unsigned int maxvpath;
165*69606e3fSchristos   unsigned int maxelem;
166*69606e3fSchristos   char *percent = NULL;
167*69606e3fSchristos 
168*69606e3fSchristos   if (pattern != 0)
169*69606e3fSchristos     {
170*69606e3fSchristos       pattern = xstrdup (pattern);
171*69606e3fSchristos       percent = find_percent (pattern);
172*69606e3fSchristos     }
173*69606e3fSchristos 
174*69606e3fSchristos   if (dirpath == 0)
175*69606e3fSchristos     {
176*69606e3fSchristos       /* Remove matching listings.  */
177*69606e3fSchristos       register struct vpath *path, *lastpath;
178*69606e3fSchristos 
179*69606e3fSchristos       lastpath = 0;
180*69606e3fSchristos       path = vpaths;
181*69606e3fSchristos       while (path != 0)
182*69606e3fSchristos 	{
183*69606e3fSchristos 	  struct vpath *next = path->next;
184*69606e3fSchristos 
185*69606e3fSchristos 	  if (pattern == 0
186*69606e3fSchristos 	      || (((percent == 0 && path->percent == 0)
187*69606e3fSchristos 		   || (percent - pattern == path->percent - path->pattern))
188*69606e3fSchristos 		  && streq (pattern, path->pattern)))
189*69606e3fSchristos 	    {
190*69606e3fSchristos 	      /* Remove it from the linked list.  */
191*69606e3fSchristos 	      if (lastpath == 0)
192*69606e3fSchristos 		vpaths = path->next;
193*69606e3fSchristos 	      else
194*69606e3fSchristos 		lastpath->next = next;
195*69606e3fSchristos 
196*69606e3fSchristos 	      /* Free its unused storage.  */
197*69606e3fSchristos 	      free (path->pattern);
198*69606e3fSchristos 	      free ((char *) path->searchpath);
199*69606e3fSchristos 	      free ((char *) path);
200*69606e3fSchristos 	    }
201*69606e3fSchristos 	  else
202*69606e3fSchristos 	    lastpath = path;
203*69606e3fSchristos 
204*69606e3fSchristos 	  path = next;
205*69606e3fSchristos 	}
206*69606e3fSchristos 
207*69606e3fSchristos       if (pattern != 0)
208*69606e3fSchristos 	free (pattern);
209*69606e3fSchristos       return;
210*69606e3fSchristos     }
211*69606e3fSchristos 
212*69606e3fSchristos #ifdef WINDOWS32
213*69606e3fSchristos     convert_vpath_to_windows32(dirpath, ';');
214*69606e3fSchristos #endif
215*69606e3fSchristos 
216*69606e3fSchristos   /* Figure out the maximum number of VPATH entries and put it in
217*69606e3fSchristos      MAXELEM.  We start with 2, one before the first separator and one
218*69606e3fSchristos      nil (the list terminator) and increment our estimated number for
219*69606e3fSchristos      each separator or blank we find.  */
220*69606e3fSchristos   maxelem = 2;
221*69606e3fSchristos   p = dirpath;
222*69606e3fSchristos   while (*p != '\0')
223*69606e3fSchristos     if (*p++ == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
224*69606e3fSchristos       ++maxelem;
225*69606e3fSchristos 
226*69606e3fSchristos   vpath = (char **) xmalloc (maxelem * sizeof (char *));
227*69606e3fSchristos   maxvpath = 0;
228*69606e3fSchristos 
229*69606e3fSchristos   /* Skip over any initial separators and blanks.  */
230*69606e3fSchristos   p = dirpath;
231*69606e3fSchristos   while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
232*69606e3fSchristos     ++p;
233*69606e3fSchristos 
234*69606e3fSchristos   elem = 0;
235*69606e3fSchristos   while (*p != '\0')
236*69606e3fSchristos     {
237*69606e3fSchristos       char *v;
238*69606e3fSchristos       unsigned int len;
239*69606e3fSchristos 
240*69606e3fSchristos       /* Find the end of this entry.  */
241*69606e3fSchristos       v = p;
242*69606e3fSchristos       while (*p != '\0' && *p != PATH_SEPARATOR_CHAR
243*69606e3fSchristos 	     && !isblank ((unsigned char)*p))
244*69606e3fSchristos 	++p;
245*69606e3fSchristos 
246*69606e3fSchristos       len = p - v;
247*69606e3fSchristos       /* Make sure there's no trailing slash,
248*69606e3fSchristos 	 but still allow "/" as a directory.  */
249*69606e3fSchristos #if defined(__MSDOS__) || defined(__EMX__)
250*69606e3fSchristos       /* We need also to leave alone a trailing slash in "d:/".  */
251*69606e3fSchristos       if (len > 3 || (len > 1 && v[1] != ':'))
252*69606e3fSchristos #endif
253*69606e3fSchristos       if (len > 1 && p[-1] == '/')
254*69606e3fSchristos 	--len;
255*69606e3fSchristos 
256*69606e3fSchristos       if (len > 1 || *v != '.')
257*69606e3fSchristos 	{
258*69606e3fSchristos 	  v = savestring (v, len);
259*69606e3fSchristos 
260*69606e3fSchristos 	  /* Verify that the directory actually exists.  */
261*69606e3fSchristos 
262*69606e3fSchristos 	  if (dir_file_exists_p (v, ""))
263*69606e3fSchristos 	    {
264*69606e3fSchristos 	      /* It does.  Put it in the list.  */
265*69606e3fSchristos 	      vpath[elem++] = dir_name (v);
266*69606e3fSchristos 	      free (v);
267*69606e3fSchristos 	      if (len > maxvpath)
268*69606e3fSchristos 		maxvpath = len;
269*69606e3fSchristos 	    }
270*69606e3fSchristos 	  else
271*69606e3fSchristos 	    /* The directory does not exist.  Omit from the list.  */
272*69606e3fSchristos 	    free (v);
273*69606e3fSchristos 	}
274*69606e3fSchristos 
275*69606e3fSchristos       /* Skip over separators and blanks between entries.  */
276*69606e3fSchristos       while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
277*69606e3fSchristos 	++p;
278*69606e3fSchristos     }
279*69606e3fSchristos 
280*69606e3fSchristos   if (elem > 0)
281*69606e3fSchristos     {
282*69606e3fSchristos       struct vpath *path;
283*69606e3fSchristos       /* ELEM is now incremented one element past the last
284*69606e3fSchristos 	 entry, to where the nil-pointer terminator goes.
285*69606e3fSchristos 	 Usually this is maxelem - 1.  If not, shrink down.  */
286*69606e3fSchristos       if (elem < (maxelem - 1))
287*69606e3fSchristos 	vpath = (char **) xrealloc ((char *) vpath,
288*69606e3fSchristos 				    (elem + 1) * sizeof (char *));
289*69606e3fSchristos 
290*69606e3fSchristos       /* Put the nil-pointer terminator on the end of the VPATH list.  */
291*69606e3fSchristos       vpath[elem] = 0;
292*69606e3fSchristos 
293*69606e3fSchristos       /* Construct the vpath structure and put it into the linked list.  */
294*69606e3fSchristos       path = (struct vpath *) xmalloc (sizeof (struct vpath));
295*69606e3fSchristos       path->searchpath = vpath;
296*69606e3fSchristos       path->maxlen = maxvpath;
297*69606e3fSchristos       path->next = vpaths;
298*69606e3fSchristos       vpaths = path;
299*69606e3fSchristos 
300*69606e3fSchristos       /* Set up the members.  */
301*69606e3fSchristos       path->pattern = pattern;
302*69606e3fSchristos       path->percent = percent;
303*69606e3fSchristos       path->patlen = strlen (pattern);
304*69606e3fSchristos     }
305*69606e3fSchristos   else
306*69606e3fSchristos     {
307*69606e3fSchristos       /* There were no entries, so free whatever space we allocated.  */
308*69606e3fSchristos       free ((char *) vpath);
309*69606e3fSchristos       if (pattern != 0)
310*69606e3fSchristos 	free (pattern);
311*69606e3fSchristos     }
312*69606e3fSchristos }
313*69606e3fSchristos 
314*69606e3fSchristos /* Search the GPATH list for a pathname string that matches the one passed
315*69606e3fSchristos    in.  If it is found, return 1.  Otherwise we return 0.  */
316*69606e3fSchristos 
317*69606e3fSchristos int
gpath_search(char * file,unsigned int len)318*69606e3fSchristos gpath_search (char *file, unsigned int len)
319*69606e3fSchristos {
320*69606e3fSchristos   char **gp;
321*69606e3fSchristos 
322*69606e3fSchristos   if (gpaths && (len <= gpaths->maxlen))
323*69606e3fSchristos     for (gp = gpaths->searchpath; *gp != NULL; ++gp)
324*69606e3fSchristos       if (strneq (*gp, file, len) && (*gp)[len] == '\0')
325*69606e3fSchristos         return 1;
326*69606e3fSchristos 
327*69606e3fSchristos   return 0;
328*69606e3fSchristos }
329*69606e3fSchristos 
330*69606e3fSchristos /* Search the VPATH list whose pattern matches *FILE for a directory
331*69606e3fSchristos    where the name pointed to by FILE exists.  If it is found, we set *FILE to
332*69606e3fSchristos    the newly malloc'd name of the existing file, *MTIME_PTR (if MTIME_PTR is
333*69606e3fSchristos    not NULL) to its modtime (or zero if no stat call was done), and return 1.
334*69606e3fSchristos    Otherwise we return 0.  */
335*69606e3fSchristos 
336*69606e3fSchristos int
vpath_search(char ** file,FILE_TIMESTAMP * mtime_ptr)337*69606e3fSchristos vpath_search (char **file, FILE_TIMESTAMP *mtime_ptr)
338*69606e3fSchristos {
339*69606e3fSchristos   register struct vpath *v;
340*69606e3fSchristos 
341*69606e3fSchristos   /* If there are no VPATH entries or FILENAME starts at the root,
342*69606e3fSchristos      there is nothing we can do.  */
343*69606e3fSchristos 
344*69606e3fSchristos   if (**file == '/'
345*69606e3fSchristos #ifdef HAVE_DOS_PATHS
346*69606e3fSchristos       || **file == '\\'
347*69606e3fSchristos       || (*file)[1] == ':'
348*69606e3fSchristos #endif
349*69606e3fSchristos       || (vpaths == 0 && general_vpath == 0))
350*69606e3fSchristos     return 0;
351*69606e3fSchristos 
352*69606e3fSchristos   for (v = vpaths; v != 0; v = v->next)
353*69606e3fSchristos     if (pattern_matches (v->pattern, v->percent, *file))
354*69606e3fSchristos       if (selective_vpath_search (v, file, mtime_ptr))
355*69606e3fSchristos 	return 1;
356*69606e3fSchristos 
357*69606e3fSchristos   if (general_vpath != 0
358*69606e3fSchristos       && selective_vpath_search (general_vpath, file, mtime_ptr))
359*69606e3fSchristos     return 1;
360*69606e3fSchristos 
361*69606e3fSchristos   return 0;
362*69606e3fSchristos }
363*69606e3fSchristos 
364*69606e3fSchristos 
365*69606e3fSchristos /* Search the given VPATH list for a directory where the name pointed
366*69606e3fSchristos    to by FILE exists.  If it is found, we set *FILE to the newly malloc'd
367*69606e3fSchristos    name of the existing file, *MTIME_PTR (if MTIME_PTR is not NULL) to
368*69606e3fSchristos    its modtime (or zero if no stat call was done), and we return 1.
369*69606e3fSchristos    Otherwise we return 0.  */
370*69606e3fSchristos 
371*69606e3fSchristos static int
selective_vpath_search(struct vpath * path,char ** file,FILE_TIMESTAMP * mtime_ptr)372*69606e3fSchristos selective_vpath_search (struct vpath *path, char **file,
373*69606e3fSchristos                         FILE_TIMESTAMP *mtime_ptr)
374*69606e3fSchristos {
375*69606e3fSchristos   int not_target;
376*69606e3fSchristos   char *name, *n;
377*69606e3fSchristos   char *filename;
378*69606e3fSchristos   register char **vpath = path->searchpath;
379*69606e3fSchristos   unsigned int maxvpath = path->maxlen;
380*69606e3fSchristos   register unsigned int i;
381*69606e3fSchristos   unsigned int flen, vlen, name_dplen;
382*69606e3fSchristos   int exists = 0;
383*69606e3fSchristos 
384*69606e3fSchristos   /* Find out if *FILE is a target.
385*69606e3fSchristos      If and only if it is NOT a target, we will accept prospective
386*69606e3fSchristos      files that don't exist but are mentioned in a makefile.  */
387*69606e3fSchristos   {
388*69606e3fSchristos     struct file *f = lookup_file (*file);
389*69606e3fSchristos     not_target = f == 0 || !f->is_target;
390*69606e3fSchristos   }
391*69606e3fSchristos 
392*69606e3fSchristos   flen = strlen (*file);
393*69606e3fSchristos 
394*69606e3fSchristos   /* Split *FILE into a directory prefix and a name-within-directory.
395*69606e3fSchristos      NAME_DPLEN gets the length of the prefix; FILENAME gets the
396*69606e3fSchristos      pointer to the name-within-directory and FLEN is its length.  */
397*69606e3fSchristos 
398*69606e3fSchristos   n = strrchr (*file, '/');
399*69606e3fSchristos #ifdef HAVE_DOS_PATHS
400*69606e3fSchristos   /* We need the rightmost slash or backslash.  */
401*69606e3fSchristos   {
402*69606e3fSchristos     char *bslash = strrchr(*file, '\\');
403*69606e3fSchristos     if (!n || bslash > n)
404*69606e3fSchristos       n = bslash;
405*69606e3fSchristos   }
406*69606e3fSchristos #endif
407*69606e3fSchristos   name_dplen = n != 0 ? n - *file : 0;
408*69606e3fSchristos   filename = name_dplen > 0 ? n + 1 : *file;
409*69606e3fSchristos   if (name_dplen > 0)
410*69606e3fSchristos     flen -= name_dplen + 1;
411*69606e3fSchristos 
412*69606e3fSchristos   /* Allocate enough space for the biggest VPATH entry,
413*69606e3fSchristos      a slash, the directory prefix that came with *FILE,
414*69606e3fSchristos      another slash (although this one may not always be
415*69606e3fSchristos      necessary), the filename, and a null terminator.  */
416*69606e3fSchristos   name = (char *) xmalloc (maxvpath + 1 + name_dplen + 1 + flen + 1);
417*69606e3fSchristos 
418*69606e3fSchristos   /* Try each VPATH entry.  */
419*69606e3fSchristos   for (i = 0; vpath[i] != 0; ++i)
420*69606e3fSchristos     {
421*69606e3fSchristos       int exists_in_cache = 0;
422*69606e3fSchristos 
423*69606e3fSchristos       n = name;
424*69606e3fSchristos 
425*69606e3fSchristos       /* Put the next VPATH entry into NAME at N and increment N past it.  */
426*69606e3fSchristos       vlen = strlen (vpath[i]);
427*69606e3fSchristos       bcopy (vpath[i], n, vlen);
428*69606e3fSchristos       n += vlen;
429*69606e3fSchristos 
430*69606e3fSchristos       /* Add the directory prefix already in *FILE.  */
431*69606e3fSchristos       if (name_dplen > 0)
432*69606e3fSchristos 	{
433*69606e3fSchristos #ifndef VMS
434*69606e3fSchristos 	  *n++ = '/';
435*69606e3fSchristos #endif
436*69606e3fSchristos 	  bcopy (*file, n, name_dplen);
437*69606e3fSchristos 	  n += name_dplen;
438*69606e3fSchristos 	}
439*69606e3fSchristos 
440*69606e3fSchristos #ifdef HAVE_DOS_PATHS
441*69606e3fSchristos       /* Cause the next if to treat backslash and slash alike.  */
442*69606e3fSchristos       if (n != name && n[-1] == '\\' )
443*69606e3fSchristos 	n[-1] = '/';
444*69606e3fSchristos #endif
445*69606e3fSchristos       /* Now add the name-within-directory at the end of NAME.  */
446*69606e3fSchristos #ifndef VMS
447*69606e3fSchristos       if (n != name && n[-1] != '/')
448*69606e3fSchristos 	{
449*69606e3fSchristos 	  *n = '/';
450*69606e3fSchristos 	  bcopy (filename, n + 1, flen + 1);
451*69606e3fSchristos 	}
452*69606e3fSchristos       else
453*69606e3fSchristos #endif
454*69606e3fSchristos 	bcopy (filename, n, flen + 1);
455*69606e3fSchristos 
456*69606e3fSchristos       /* Check if the file is mentioned in a makefile.  If *FILE is not
457*69606e3fSchristos 	 a target, that is enough for us to decide this file exists.
458*69606e3fSchristos 	 If *FILE is a target, then the file must be mentioned in the
459*69606e3fSchristos 	 makefile also as a target to be chosen.
460*69606e3fSchristos 
461*69606e3fSchristos 	 The restriction that *FILE must not be a target for a
462*69606e3fSchristos 	 makefile-mentioned file to be chosen was added by an
463*69606e3fSchristos 	 inadequately commented change in July 1990; I am not sure off
464*69606e3fSchristos 	 hand what problem it fixes.
465*69606e3fSchristos 
466*69606e3fSchristos 	 In December 1993 I loosened this restriction to allow a file
467*69606e3fSchristos 	 to be chosen if it is mentioned as a target in a makefile.  This
468*69606e3fSchristos 	 seem logical.
469*69606e3fSchristos 
470*69606e3fSchristos          Special handling for -W / -o: make sure we preserve the special
471*69606e3fSchristos          values here.  Actually this whole thing is a little bogus: I think
472*69606e3fSchristos          we should ditch the name/hname thing and look into the renamed
473*69606e3fSchristos          capability that already exists for files: that is, have a new struct
474*69606e3fSchristos          file* entry for the VPATH-found file, and set the renamed field if
475*69606e3fSchristos          we use it.
476*69606e3fSchristos       */
477*69606e3fSchristos       {
478*69606e3fSchristos 	struct file *f = lookup_file (name);
479*69606e3fSchristos 	if (f != 0)
480*69606e3fSchristos           {
481*69606e3fSchristos             exists = not_target || f->is_target;
482*69606e3fSchristos             if (exists && mtime_ptr
483*69606e3fSchristos                 && (f->last_mtime == OLD_MTIME || f->last_mtime == NEW_MTIME))
484*69606e3fSchristos               {
485*69606e3fSchristos                 *mtime_ptr = f->last_mtime;
486*69606e3fSchristos                 mtime_ptr = 0;
487*69606e3fSchristos               }
488*69606e3fSchristos           }
489*69606e3fSchristos       }
490*69606e3fSchristos 
491*69606e3fSchristos       if (!exists)
492*69606e3fSchristos 	{
493*69606e3fSchristos 	  /* That file wasn't mentioned in the makefile.
494*69606e3fSchristos 	     See if it actually exists.  */
495*69606e3fSchristos 
496*69606e3fSchristos #ifdef VMS
497*69606e3fSchristos 	  exists_in_cache = exists = dir_file_exists_p (vpath[i], filename);
498*69606e3fSchristos #else
499*69606e3fSchristos 	  /* Clobber a null into the name at the last slash.
500*69606e3fSchristos 	     Now NAME is the name of the directory to look in.  */
501*69606e3fSchristos 	  *n = '\0';
502*69606e3fSchristos 
503*69606e3fSchristos 	  /* We know the directory is in the hash table now because either
504*69606e3fSchristos 	     construct_vpath_list or the code just above put it there.
505*69606e3fSchristos 	     Does the file we seek exist in it?  */
506*69606e3fSchristos 	  exists_in_cache = exists = dir_file_exists_p (name, filename);
507*69606e3fSchristos #endif
508*69606e3fSchristos 	}
509*69606e3fSchristos 
510*69606e3fSchristos       if (exists)
511*69606e3fSchristos 	{
512*69606e3fSchristos 	  /* The file is in the directory cache.
513*69606e3fSchristos 	     Now check that it actually exists in the filesystem.
514*69606e3fSchristos 	     The cache may be out of date.  When vpath thinks a file
515*69606e3fSchristos 	     exists, but stat fails for it, confusion results in the
516*69606e3fSchristos 	     higher levels.  */
517*69606e3fSchristos 
518*69606e3fSchristos 	  struct stat st;
519*69606e3fSchristos 
520*69606e3fSchristos #ifndef VMS
521*69606e3fSchristos 	  /* Put the slash back in NAME.  */
522*69606e3fSchristos 	  *n = '/';
523*69606e3fSchristos #endif
524*69606e3fSchristos 
525*69606e3fSchristos 	  if (exists_in_cache)	/* Makefile-mentioned file need not exist.  */
526*69606e3fSchristos 	    {
527*69606e3fSchristos               int e;
528*69606e3fSchristos 
529*69606e3fSchristos               EINTRLOOP (e, stat (name, &st)); /* Does it really exist?  */
530*69606e3fSchristos               if (e != 0)
531*69606e3fSchristos                 {
532*69606e3fSchristos                   exists = 0;
533*69606e3fSchristos                   continue;
534*69606e3fSchristos                 }
535*69606e3fSchristos 
536*69606e3fSchristos               /* Store the modtime into *MTIME_PTR for the caller.  */
537*69606e3fSchristos               if (mtime_ptr != 0)
538*69606e3fSchristos                 {
539*69606e3fSchristos                   *mtime_ptr = FILE_TIMESTAMP_STAT_MODTIME (name, st);
540*69606e3fSchristos                   mtime_ptr = 0;
541*69606e3fSchristos                 }
542*69606e3fSchristos             }
543*69606e3fSchristos 
544*69606e3fSchristos           /* We have found a file.
545*69606e3fSchristos              Store the name we found into *FILE for the caller.  */
546*69606e3fSchristos 
547*69606e3fSchristos           *file = savestring (name, (n + 1 - name) + flen);
548*69606e3fSchristos 
549*69606e3fSchristos           /* If we get here and mtime_ptr hasn't been set, record
550*69606e3fSchristos              UNKNOWN_MTIME to indicate this.  */
551*69606e3fSchristos           if (mtime_ptr != 0)
552*69606e3fSchristos             *mtime_ptr = UNKNOWN_MTIME;
553*69606e3fSchristos 
554*69606e3fSchristos           free (name);
555*69606e3fSchristos           return 1;
556*69606e3fSchristos 	}
557*69606e3fSchristos     }
558*69606e3fSchristos 
559*69606e3fSchristos   free (name);
560*69606e3fSchristos   return 0;
561*69606e3fSchristos }
562*69606e3fSchristos 
563*69606e3fSchristos /* Print the data base of VPATH search paths.  */
564*69606e3fSchristos 
565*69606e3fSchristos void
print_vpath_data_base(void)566*69606e3fSchristos print_vpath_data_base (void)
567*69606e3fSchristos {
568*69606e3fSchristos   register unsigned int nvpaths;
569*69606e3fSchristos   register struct vpath *v;
570*69606e3fSchristos 
571*69606e3fSchristos   puts (_("\n# VPATH Search Paths\n"));
572*69606e3fSchristos 
573*69606e3fSchristos   nvpaths = 0;
574*69606e3fSchristos   for (v = vpaths; v != 0; v = v->next)
575*69606e3fSchristos     {
576*69606e3fSchristos       register unsigned int i;
577*69606e3fSchristos 
578*69606e3fSchristos       ++nvpaths;
579*69606e3fSchristos 
580*69606e3fSchristos       printf ("vpath %s ", v->pattern);
581*69606e3fSchristos 
582*69606e3fSchristos       for (i = 0; v->searchpath[i] != 0; ++i)
583*69606e3fSchristos 	printf ("%s%c", v->searchpath[i],
584*69606e3fSchristos 		v->searchpath[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR);
585*69606e3fSchristos     }
586*69606e3fSchristos 
587*69606e3fSchristos   if (vpaths == 0)
588*69606e3fSchristos     puts (_("# No `vpath' search paths."));
589*69606e3fSchristos   else
590*69606e3fSchristos     printf (_("\n# %u `vpath' search paths.\n"), nvpaths);
591*69606e3fSchristos 
592*69606e3fSchristos   if (general_vpath == 0)
593*69606e3fSchristos     puts (_("\n# No general (`VPATH' variable) search path."));
594*69606e3fSchristos   else
595*69606e3fSchristos     {
596*69606e3fSchristos       register char **path = general_vpath->searchpath;
597*69606e3fSchristos       register unsigned int i;
598*69606e3fSchristos 
599*69606e3fSchristos       fputs (_("\n# General (`VPATH' variable) search path:\n# "), stdout);
600*69606e3fSchristos 
601*69606e3fSchristos       for (i = 0; path[i] != 0; ++i)
602*69606e3fSchristos 	printf ("%s%c", path[i],
603*69606e3fSchristos 		path[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR);
604*69606e3fSchristos     }
605*69606e3fSchristos }
606