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