VirtualBox

source: kBuild/vendor/gnumake/3.81/vpath.c

Last change on this file was 501, checked in by bird, 18 years ago

Load make-3.81/ into vendor/gnumake/current.

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