VirtualBox

source: kBuild/trunk/src/gmakenew/vpath.c@ 936

Last change on this file since 936 was 903, checked in by bird, 18 years ago

Merged with the 2007-05-23 CVS. Added rsort and fixed a couple of windows build issues.

  • 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 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 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' && *p != PATH_SEPARATOR_CHAR
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__)
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