VirtualBox

source: kBuild/trunk/src/kmk/vpath.c@ 2074

Last change on this file since 2074 was 1993, checked in by bird, 16 years ago

Merged in current GNU Make code (CVS from 2008-10-28). Ref #55.

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