VirtualBox

source: kBuild/trunk/src/gmake/vpath.c@ 783

最後變更 在這個檔案從783是 527,由 bird 提交於 19 年 前

CONFIG_WITH_OPTIMIZATION_HACKS

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

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