VirtualBox

source: kBuild/vendor/gnumake/3.82-cvs/vpath.c

Last change on this file was 2580, checked in by bird, 12 years ago

Importing the make-3-82 CVS tag with --auto-props but no keywords.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette