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