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