VirtualBox

source: kBuild/vendor/gnumake/2008-10-28/vpath.c

Last change on this file was 1989, checked in by bird, 16 years ago

Load gnumake-2008-10-28-CVS into vendor/gnumake/current.

  • Property svn:eol-style set to native
File size: 16.8 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 Free Software
4Foundation, 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 searchpath 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 SEARCHPATH 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 searchpath
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 free (path->searchpath);
198 free (path);
199 }
200 else
201 lastpath = path;
202
203 path = next;
204 }
205
206 return;
207 }
208
209#ifdef WINDOWS32
210 convert_vpath_to_windows32(dirpath, ';');
211#endif
212
213 /* Skip over any initial separators and blanks. */
214 while (*dirpath == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*dirpath))
215 ++dirpath;
216
217 /* Figure out the maximum number of VPATH entries and put it in
218 MAXELEM. We start with 2, one before the first separator and one
219 nil (the list terminator) and increment our estimated number for
220 each separator or blank we find. */
221 maxelem = 2;
222 p = dirpath;
223 while (*p != '\0')
224 if (*p++ == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
225 ++maxelem;
226
227 vpath = xmalloc (maxelem * sizeof (const char *));
228 maxvpath = 0;
229
230 elem = 0;
231 p = dirpath;
232 while (*p != '\0')
233 {
234 char *v;
235 unsigned int len;
236
237 /* Find the end of this entry. */
238 v = p;
239 while (*p != '\0'
240#if defined(HAVE_DOS_PATHS) && (PATH_SEPARATOR_CHAR == ':')
241 /* Platforms whose PATH_SEPARATOR_CHAR is ':' and which
242 also define HAVE_DOS_PATHS would like us to recognize
243 colons after the drive letter in the likes of
244 "D:/foo/bar:C:/xyzzy". */
245 && (*p != PATH_SEPARATOR_CHAR
246 || (p == v + 1 && (p[1] == '/' || p[1] == '\\')))
247#else
248 && *p != PATH_SEPARATOR_CHAR
249#endif
250 && !isblank ((unsigned char)*p))
251 ++p;
252
253 len = p - v;
254 /* Make sure there's no trailing slash,
255 but still allow "/" as a directory. */
256#if defined(__MSDOS__) || defined(__EMX__) || defined(HAVE_DOS_PATHS)
257 /* We need also to leave alone a trailing slash in "d:/". */
258 if (len > 3 || (len > 1 && v[1] != ':'))
259#endif
260 if (len > 1 && p[-1] == '/')
261 --len;
262
263 /* Put the directory on the vpath list. */
264 if (len > 1 || *v != '.')
265 {
266 vpath[elem++] = dir_name (strcache_add_len (v, len));
267 if (len > maxvpath)
268 maxvpath = len;
269 }
270
271 /* Skip over separators and blanks between entries. */
272 while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
273 ++p;
274 }
275
276 if (elem > 0)
277 {
278 struct vpath *path;
279 /* ELEM is now incremented one element past the last
280 entry, to where the nil-pointer terminator goes.
281 Usually this is maxelem - 1. If not, shrink down. */
282 if (elem < (maxelem - 1))
283 vpath = xrealloc (vpath, (elem+1) * sizeof (const char *));
284
285 /* Put the nil-pointer terminator on the end of the VPATH list. */
286 vpath[elem] = NULL;
287
288 /* Construct the vpath structure and put it into the linked list. */
289 path = xmalloc (sizeof (struct vpath));
290 path->searchpath = vpath;
291 path->maxlen = maxvpath;
292 path->next = vpaths;
293 vpaths = path;
294
295 /* Set up the members. */
296 path->pattern = strcache_add (pattern);
297 path->patlen = strlen (pattern);
298 path->percent = percent ? path->pattern + (percent - pattern) : 0;
299 }
300 else
301 /* There were no entries, so free whatever space we allocated. */
302 free (vpath);
303}
304
305
306/* Search the GPATH list for a pathname string that matches the one passed
307 in. If it is found, return 1. Otherwise we return 0. */
308
309int
310gpath_search (const char *file, unsigned int len)
311{
312 const char **gp;
313
314 if (gpaths && (len <= gpaths->maxlen))
315 for (gp = gpaths->searchpath; *gp != NULL; ++gp)
316 if (strneq (*gp, file, len) && (*gp)[len] == '\0')
317 return 1;
318
319 return 0;
320}
321
322
323
324/* Search the given VPATH list for a directory where the name pointed to by
325 FILE exists. If it is found, we return a cached name of the existing file
326 and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
327 stat call was done). Otherwise we return NULL. */
328
329static const char *
330selective_vpath_search (struct vpath *path, const char *file,
331 FILE_TIMESTAMP *mtime_ptr)
332{
333 int not_target;
334 char *name;
335 const char *n;
336 const char *filename;
337 const char **vpath = path->searchpath;
338 unsigned int maxvpath = path->maxlen;
339 unsigned int i;
340 unsigned int flen, vlen, name_dplen;
341 int exists = 0;
342
343 /* Find out if *FILE is a target.
344 If and only if it is NOT a target, we will accept prospective
345 files that don't exist but are mentioned in a makefile. */
346 {
347 struct file *f = lookup_file (file);
348 not_target = f == 0 || !f->is_target;
349 }
350
351 flen = strlen (file);
352
353 /* Split *FILE into a directory prefix and a name-within-directory.
354 NAME_DPLEN gets the length of the prefix; FILENAME gets the pointer to
355 the name-within-directory and FLEN is its length. */
356
357 n = strrchr (file, '/');
358#ifdef HAVE_DOS_PATHS
359 /* We need the rightmost slash or backslash. */
360 {
361 const char *bslash = strrchr(file, '\\');
362 if (!n || bslash > n)
363 n = bslash;
364 }
365#endif
366 name_dplen = n != 0 ? n - file : 0;
367 filename = name_dplen > 0 ? n + 1 : file;
368 if (name_dplen > 0)
369 flen -= name_dplen + 1;
370
371 /* Get enough space for the biggest VPATH entry, a slash, the directory
372 prefix that came with FILE, another slash (although this one may not
373 always be necessary), the filename, and a null terminator. */
374 name = alloca (maxvpath + 1 + name_dplen + 1 + flen + 1);
375
376 /* Try each VPATH entry. */
377 for (i = 0; vpath[i] != 0; ++i)
378 {
379 int exists_in_cache = 0;
380 char *p;
381
382 p = name;
383
384 /* Put the next VPATH entry into NAME at P and increment P past it. */
385 vlen = strlen (vpath[i]);
386 memcpy (p, vpath[i], vlen);
387 p += vlen;
388
389 /* Add the directory prefix already in *FILE. */
390 if (name_dplen > 0)
391 {
392#ifndef VMS
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#endif
413 memcpy (p, filename, flen + 1);
414
415 /* Check if the file is mentioned in a makefile. If *FILE is not
416 a target, that is enough for us to decide this file exists.
417 If *FILE is a target, then the file must be mentioned in the
418 makefile also as a target to be chosen.
419
420 The restriction that *FILE must not be a target for a
421 makefile-mentioned file to be chosen was added by an
422 inadequately commented change in July 1990; I am not sure off
423 hand what problem it fixes.
424
425 In December 1993 I loosened this restriction to allow a file
426 to be chosen if it is mentioned as a target in a makefile. This
427 seem logical.
428
429 Special handling for -W / -o: make sure we preserve the special
430 values here. Actually this whole thing is a little bogus: I think
431 we should ditch the name/hname thing and look into the renamed
432 capability that already exists for files: that is, have a new struct
433 file* entry for the VPATH-found file, and set the renamed field if
434 we use it.
435 */
436 {
437 struct file *f = lookup_file (name);
438 if (f != 0)
439 {
440 exists = not_target || f->is_target;
441 if (exists && mtime_ptr
442 && (f->last_mtime == OLD_MTIME || f->last_mtime == NEW_MTIME))
443 {
444 *mtime_ptr = f->last_mtime;
445 mtime_ptr = 0;
446 }
447 }
448 }
449
450 if (!exists)
451 {
452 /* That file wasn't mentioned in the makefile.
453 See if it actually exists. */
454
455#ifdef VMS
456 exists_in_cache = exists = dir_file_exists_p (vpath[i], filename);
457#else
458 /* Clobber a null into the name at the last slash.
459 Now NAME is the name of the directory to look in. */
460 *p = '\0';
461
462 /* We know the directory is in the hash table now because either
463 construct_vpath_list or the code just above put it there.
464 Does the file we seek exist in it? */
465 exists_in_cache = exists = dir_file_exists_p (name, filename);
466#endif
467 }
468
469 if (exists)
470 {
471 /* The file is in the directory cache.
472 Now check that it actually exists in the filesystem.
473 The cache may be out of date. When vpath thinks a file
474 exists, but stat fails for it, confusion results in the
475 higher levels. */
476
477 struct stat st;
478
479#ifndef VMS
480 /* Put the slash back in NAME. */
481 *p = '/';
482#endif
483
484 if (exists_in_cache) /* Makefile-mentioned file need not exist. */
485 {
486 int e;
487
488 EINTRLOOP (e, stat (name, &st)); /* Does it really exist? */
489 if (e != 0)
490 {
491 exists = 0;
492 continue;
493 }
494
495 /* Store the modtime into *MTIME_PTR for the caller. */
496 if (mtime_ptr != 0)
497 {
498 *mtime_ptr = FILE_TIMESTAMP_STAT_MODTIME (name, st);
499 mtime_ptr = 0;
500 }
501 }
502
503 /* We have found a file.
504 If we get here and mtime_ptr hasn't been set, record
505 UNKNOWN_MTIME to indicate this. */
506 if (mtime_ptr != 0)
507 *mtime_ptr = UNKNOWN_MTIME;
508
509 /* Store the name we found and return it. */
510
511 return strcache_add_len (name, (p + 1 - name) + flen);
512 }
513 }
514
515 return 0;
516}
517
518
519/* Search the VPATH list whose pattern matches FILE for a directory where FILE
520 exists. If it is found, return the cached name of an existing file, and
521 set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
522 stat call was done). Otherwise we return 0. */
523
524const char *
525vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr)
526{
527 struct vpath *v;
528
529 /* If there are no VPATH entries or FILENAME starts at the root,
530 there is nothing we can do. */
531
532 if (file[0] == '/'
533#ifdef HAVE_DOS_PATHS
534 || file[0] == '\\' || file[1] == ':'
535#endif
536 || (vpaths == 0 && general_vpath == 0))
537 return 0;
538
539 for (v = vpaths; v != 0; v = v->next)
540 if (pattern_matches (v->pattern, v->percent, file))
541 {
542 const char *p = selective_vpath_search (v, file, mtime_ptr);
543 if (p)
544 return p;
545 }
546
547 if (general_vpath != 0)
548 {
549 const char *p = selective_vpath_search (general_vpath, file, mtime_ptr);
550 if (p)
551 return p;
552 }
553
554 return 0;
555}
556
557
558/* Print the data base of VPATH search paths. */
559
560void
561print_vpath_data_base (void)
562{
563 unsigned int nvpaths;
564 struct vpath *v;
565
566 puts (_("\n# VPATH Search Paths\n"));
567
568 nvpaths = 0;
569 for (v = vpaths; v != 0; v = v->next)
570 {
571 register unsigned int i;
572
573 ++nvpaths;
574
575 printf ("vpath %s ", v->pattern);
576
577 for (i = 0; v->searchpath[i] != 0; ++i)
578 printf ("%s%c", v->searchpath[i],
579 v->searchpath[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR);
580 }
581
582 if (vpaths == 0)
583 puts (_("# No `vpath' search paths."));
584 else
585 printf (_("\n# %u `vpath' search paths.\n"), nvpaths);
586
587 if (general_vpath == 0)
588 puts (_("\n# No general (`VPATH' variable) search path."));
589 else
590 {
591 const char **path = general_vpath->searchpath;
592 unsigned int i;
593
594 fputs (_("\n# General (`VPATH' variable) search path:\n# "), stdout);
595
596 for (i = 0; path[i] != 0; ++i)
597 printf ("%s%c", path[i],
598 path[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR);
599 }
600}
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