11590Srgrimes/* Implementation of pattern-matching file search paths for GNU Make.
21590SrgrimesCopyright (C) 1988,89,91,92,93,94,95,96,97 Free Software Foundation, Inc.
31590SrgrimesThis file is part of GNU Make.
41590Srgrimes
51590SrgrimesGNU Make is free software; you can redistribute it and/or modify
61590Srgrimesit under the terms of the GNU General Public License as published by
71590Srgrimesthe Free Software Foundation; either version 2, or (at your option)
81590Srgrimesany later version.
91590Srgrimes
101590SrgrimesGNU Make is distributed in the hope that it will be useful,
111590Srgrimesbut WITHOUT ANY WARRANTY; without even the implied warranty of
121590SrgrimesMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
131590SrgrimesGNU General Public License for more details.
141590Srgrimes
151590SrgrimesYou should have received a copy of the GNU General Public License
161590Srgrimesalong with GNU Make; see the file COPYING.  If not, write to
171590Srgrimesthe Free Software Foundation, Inc., 59 Temple Place - Suite 330,
181590SrgrimesBoston, MA 02111-1307, USA.  */
191590Srgrimes
201590Srgrimes#include "make.h"
211590Srgrimes#include "filedef.h"
221590Srgrimes#include "variable.h"
231590Srgrimes#ifdef WINDOWS32
241590Srgrimes#include "pathstuff.h"
251590Srgrimes#endif
261590Srgrimes
271590Srgrimes
281590Srgrimes/* Structure used to represent a selective VPATH searchpath.  */
291590Srgrimes
301590Srgrimesstruct vpath
311590Srgrimes  {
321590Srgrimes    struct vpath *next;	/* Pointer to next struct in the linked list.  */
331590Srgrimes    char *pattern;	/* The pattern to match.  */
341590Srgrimes    char *percent;	/* Pointer into `pattern' where the `%' is.  */
351590Srgrimes    unsigned int patlen;/* Length of the pattern.  */
361590Srgrimes    char **searchpath;	/* Null-terminated list of directories.  */
37207705Sdelphij    unsigned int maxlen;/* Maximum length of any entry in the list.  */
38207705Sdelphij  };
39207705Sdelphij
40207705Sdelphij/* Linked-list of all selective VPATHs.  */
41207705Sdelphij
42207705Sdelphijstatic struct vpath *vpaths;
4393604Sobrien
4493604Sobrien/* Structure for the general VPATH given in the variable.  */
451590Srgrimes
461590Srgrimesstatic struct vpath *general_vpath;
471590Srgrimes
481590Srgrimes/* Structure for GPATH given in the variable.  */
491590Srgrimes
501590Srgrimesstatic struct vpath *gpaths;
5172945Sknu
52200462Sdelphijstatic int selective_vpath_search PARAMS ((struct vpath *path, char **file, FILE_TIMESTAMP *mtime_ptr));
531590Srgrimes
541590Srgrimes/* Reverse the chain of selective VPATH lists so they
551590Srgrimes   will be searched in the order given in the makefiles
561590Srgrimes   and construct the list from the VPATH variable.  */
571590Srgrimes
58207705Sdelphijvoid
5991400Sdwmalonebuild_vpath_lists ()
601590Srgrimes{
61176478Simp  register struct vpath *new = 0;
621590Srgrimes  register struct vpath *old, *nexto;
6376250Sphk  register char *p;
6476250Sphk
6576250Sphk  /* Reverse the chain.  */
66157555Sceri  for (old = vpaths; old != 0; old = nexto)
67157555Sceri    {
68157555Sceri      nexto = old->next;
6976250Sphk      old->next = new;
70127796Sbmilekic      new = old;
7176250Sphk    }
7276250Sphk
7376250Sphk  vpaths = new;
7476250Sphk
7576250Sphk  /* If there is a VPATH variable with a nonnull value, construct the
7676250Sphk     general VPATH list from it.  We use variable_expand rather than just
7776250Sphk     calling lookup_variable so that it will be recursively expanded.  */
78176478Simp
79176478Simp  {
8076250Sphk    /* Turn off --warn-undefined-variables while we expand SHELL and IFS.  */
81129812Seik    int save = warn_undefined_variables_flag;
8276250Sphk    warn_undefined_variables_flag = 0;
8376250Sphk
8476250Sphk    p = variable_expand ("$(strip $(VPATH))");
85176478Simp
8676250Sphk    warn_undefined_variables_flag = save;
87176478Simp  }
8876250Sphk
89176478Simp  if (*p != '\0')
90176478Simp    {
91176478Simp      /* Save the list of vpaths.  */
9276250Sphk      struct vpath *save_vpaths = vpaths;
93176478Simp
9476250Sphk      /* Empty `vpaths' so the new one will have no next, and `vpaths'
95176478Simp	 will still be nil if P contains no existing directories.  */
96176478Simp      vpaths = 0;
9776250Sphk
9876250Sphk      /* Parse P.  */
9976250Sphk      construct_vpath_list ("%", p);
10076250Sphk
101176478Simp      /* Store the created path as the general path,
10276250Sphk	 and restore the old list of vpaths.  */
103176478Simp      general_vpath = vpaths;
10476250Sphk      vpaths = save_vpaths;
10576250Sphk    }
10676250Sphk
10776250Sphk  /* If there is a GPATH variable with a nonnull value, construct the
10876250Sphk     GPATH list from it.  We use variable_expand rather than just
109176478Simp     calling lookup_variable so that it will be recursively expanded.  */
11076250Sphk
11176250Sphk  {
11276250Sphk    /* Turn off --warn-undefined-variables while we expand SHELL and IFS.  */
113157555Sceri    int save = warn_undefined_variables_flag;
114157555Sceri    warn_undefined_variables_flag = 0;
115157555Sceri
116157555Sceri    p = variable_expand ("$(strip $(GPATH))");
117157555Sceri
118157555Sceri    warn_undefined_variables_flag = save;
11976250Sphk  }
12076250Sphk
12176250Sphk  if (*p != '\0')
12276250Sphk    {
123157555Sceri      /* Save the list of vpaths.  */
12476250Sphk      struct vpath *save_vpaths = vpaths;
12576250Sphk
12676250Sphk      /* Empty `vpaths' so the new one will have no next, and `vpaths'
12776250Sphk	 will still be nil if P contains no existing directories.  */
128157555Sceri      vpaths = 0;
12976250Sphk
13076250Sphk      /* Parse P.  */
13176250Sphk      construct_vpath_list ("%", p);
13276250Sphk
13376250Sphk      /* Store the created path as the GPATH,
134176478Simp	 and restore the old list of vpaths.  */
135176478Simp      gpaths = vpaths;
136111084Sdes      vpaths = save_vpaths;
13776250Sphk    }
13876250Sphk}
13976250Sphk
14076250Sphk/* Construct the VPATH listing for the pattern and searchpath given.
14176250Sphk
14276250Sphk   This function is called to generate selective VPATH lists and also for
14376250Sphk   the general VPATH list (which is in fact just a selective VPATH that
14476250Sphk   is applied to everything).  The returned pointer is either put in the
14576250Sphk   linked list of all selective VPATH lists or in the GENERAL_VPATH
146176478Simp   variable.
14776250Sphk
148176478Simp   If SEARCHPATH is nil, remove all previous listings with the same
14976250Sphk   pattern.  If PATTERN is nil, remove all VPATH listings.  Existing
150176478Simp   and readable directories that are not "." given in the searchpath
15176250Sphk   separated by the path element separator (defined in make.h) are
152176478Simp   loaded into the directory hash table if they are not there already
15376250Sphk   and put in the VPATH searchpath for the given pattern with trailing
154176478Simp   slashes stripped off if present (and if the directory is not the
15576250Sphk   root, "/").  The length of the longest entry in the list is put in
156176478Simp   the structure as well.  The new entry will be at the head of the
15776250Sphk   VPATHS chain.  */
158176478Simp
1591590Srgrimesvoid
1601590Srgrimesconstruct_vpath_list (pattern, dirpath)
1611590Srgrimes     char *pattern, *dirpath;
1621590Srgrimes{
1631590Srgrimes  register unsigned int elem;
1641590Srgrimes  register char *p;
1651590Srgrimes  register char **vpath;
1661590Srgrimes  register unsigned int maxvpath;
1671590Srgrimes  unsigned int maxelem;
1681590Srgrimes  char *percent = NULL;
1691590Srgrimes
170116333Smarkm  if (pattern != 0)
1711590Srgrimes    {
17291400Sdwmalone      pattern = xstrdup (pattern);
1731590Srgrimes      percent = find_percent (pattern);
1741590Srgrimes    }
1751590Srgrimes
1761590Srgrimes  if (dirpath == 0)
1771590Srgrimes    {
17891400Sdwmalone      /* Remove matching listings.  */
1791590Srgrimes      register struct vpath *path, *lastpath;
1801590Srgrimes
1811590Srgrimes      lastpath = 0;
18276250Sphk      path = vpaths;
1831590Srgrimes      while (path != 0)
1841590Srgrimes	{
1851590Srgrimes	  struct vpath *next = path->next;
1861590Srgrimes
18776250Sphk	  if (pattern == 0
188116333Smarkm	      || (((percent == 0 && path->percent == 0)
1891590Srgrimes		   || (percent - pattern == path->percent - path->pattern))
1901590Srgrimes		  && streq (pattern, path->pattern)))
1911590Srgrimes	    {
1921590Srgrimes	      /* Remove it from the linked list.  */
1931590Srgrimes	      if (lastpath == 0)
1941590Srgrimes		vpaths = path->next;
1951590Srgrimes	      else
1961590Srgrimes		lastpath->next = next;
197207705Sdelphij
198116333Smarkm	      /* Free its unused storage.  */
1991590Srgrimes	      free (path->pattern);
20091400Sdwmalone	      free ((char *) path->searchpath);
2011590Srgrimes	      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#ifdef __MSDOS__
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/* 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 (file, len)
321     char *file;
322     int len;
323{
324  register char **gp;
325
326  if (gpaths && (len <= gpaths->maxlen))
327    for (gp = gpaths->searchpath; *gp != NULL; ++gp)
328      if (strneq (*gp, file, len) && (*gp)[len] == '\0')
329        return 1;
330
331  return 0;
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 (file, mtime_ptr)
342     char **file;
343     FILE_TIMESTAMP *mtime_ptr;
344{
345  register struct vpath *v;
346
347  /* If there are no VPATH entries or FILENAME starts at the root,
348     there is nothing we can do.  */
349
350  if (**file == '/'
351#ifdef HAVE_DOS_PATHS
352      || **file == '\\'
353      || (*file)[1] == ':'
354#endif
355      || (vpaths == 0 && general_vpath == 0))
356    return 0;
357
358  for (v = vpaths; v != 0; v = v->next)
359    if (pattern_matches (v->pattern, v->percent, *file))
360      if (selective_vpath_search (v, file, mtime_ptr))
361	return 1;
362
363  if (general_vpath != 0
364      && selective_vpath_search (general_vpath, file, mtime_ptr))
365    return 1;
366
367  return 0;
368}
369
370
371/* Search the given VPATH list for a directory where the name pointed
372   to by FILE exists.  If it is found, we set *FILE to the newly malloc'd
373   name of the existing file, *MTIME_PTR (if MTIME_PTR is not NULL) to
374   its modtime (or zero if no stat call was done), and we return 1.
375   Otherwise we return 0.  */
376
377static int
378selective_vpath_search (path, file, mtime_ptr)
379     struct vpath *path;
380     char **file;
381     FILE_TIMESTAMP *mtime_ptr;
382{
383  int not_target;
384  char *name, *n;
385  char *filename;
386  register char **vpath = path->searchpath;
387  unsigned int maxvpath = path->maxlen;
388  register unsigned int i;
389  unsigned int flen, vlen, name_dplen;
390  int exists = 0;
391
392  /* Find out if *FILE is a target.
393     If and only if it is NOT a target, we will accept prospective
394     files that don't exist but are mentioned in a makefile.  */
395  {
396    struct file *f = lookup_file (*file);
397    not_target = f == 0 || !f->is_target;
398  }
399
400  flen = strlen (*file);
401
402  /* Split *FILE into a directory prefix and a name-within-directory.
403     NAME_DPLEN gets the length of the prefix; FILENAME gets the
404     pointer to the name-within-directory and FLEN is its length.  */
405
406  n = strrchr (*file, '/');
407#ifdef HAVE_DOS_PATHS
408  /* We need the rightmost slash or backslash.  */
409  {
410    char *bslash = strrchr(*file, '\\');
411    if (!n || bslash > n)
412      n = bslash;
413  }
414#endif
415  name_dplen = n != 0 ? n - *file : 0;
416  filename = name_dplen > 0 ? n + 1 : *file;
417  if (name_dplen > 0)
418    flen -= name_dplen + 1;
419
420  /* Allocate enough space for the biggest VPATH entry,
421     a slash, the directory prefix that came with *FILE,
422     another slash (although this one may not always be
423     necessary), the filename, and a null terminator.  */
424  name = (char *) xmalloc (maxvpath + 1 + name_dplen + 1 + flen + 1);
425
426  /* Try each VPATH entry.  */
427  for (i = 0; vpath[i] != 0; ++i)
428    {
429      int exists_in_cache = 0;
430
431      n = name;
432
433      /* Put the next VPATH entry into NAME at N and increment N past it.  */
434      vlen = strlen (vpath[i]);
435      bcopy (vpath[i], n, vlen);
436      n += vlen;
437
438      /* Add the directory prefix already in *FILE.  */
439      if (name_dplen > 0)
440	{
441#ifndef VMS
442	  *n++ = '/';
443#endif
444	  bcopy (*file, n, name_dplen);
445	  n += name_dplen;
446	}
447
448#ifdef HAVE_DOS_PATHS
449      /* Cause the next if to treat backslash and slash alike.  */
450      if (n != name && n[-1] == '\\' )
451	n[-1] = '/';
452#endif
453      /* Now add the name-within-directory at the end of NAME.  */
454#ifndef VMS
455      if (n != name && n[-1] != '/')
456	{
457	  *n = '/';
458	  bcopy (filename, n + 1, flen + 1);
459	}
460      else
461#endif
462	bcopy (filename, n, flen + 1);
463
464      /* Check if the file is mentioned in a makefile.  If *FILE is not
465	 a target, that is enough for us to decide this file exists.
466	 If *FILE is a target, then the file must be mentioned in the
467	 makefile also as a target to be chosen.
468
469	 The restriction that *FILE must not be a target for a
470	 makefile-mentioned file to be chosen was added by an
471	 inadequately commented change in July 1990; I am not sure off
472	 hand what problem it fixes.
473
474	 In December 1993 I loosened this restriction to allow a file
475	 to be chosen if it is mentioned as a target in a makefile.  This
476	 seem logical.  */
477      {
478	struct file *f = lookup_file (name);
479	if (f != 0)
480	  exists = not_target || f->is_target;
481      }
482
483      if (!exists)
484	{
485	  /* That file wasn't mentioned in the makefile.
486	     See if it actually exists.  */
487
488#ifdef VMS
489	  exists_in_cache = exists = dir_file_exists_p (vpath[i], filename);
490#else
491	  /* Clobber a null into the name at the last slash.
492	     Now NAME is the name of the directory to look in.  */
493	  *n = '\0';
494
495	  /* We know the directory is in the hash table now because either
496	     construct_vpath_list or the code just above put it there.
497	     Does the file we seek exist in it?  */
498	  exists_in_cache = exists = dir_file_exists_p (name, filename);
499#endif
500	}
501
502      if (exists)
503	{
504	  /* The file is in the directory cache.
505	     Now check that it actually exists in the filesystem.
506	     The cache may be out of date.  When vpath thinks a file
507	     exists, but stat fails for it, confusion results in the
508	     higher levels.  */
509
510	  struct stat st;
511
512#ifndef VMS
513	  /* Put the slash back in NAME.  */
514	  *n = '/';
515#endif
516
517	  if (!exists_in_cache	/* Makefile-mentioned file need not exist.  */
518	      || stat (name, &st) == 0) /* Does it really exist?  */
519	    {
520	      /* We have found a file.
521		 Store the name we found into *FILE for the caller.  */
522
523	      *file = savestring (name, (n + 1 - name) + flen);
524
525	      if (mtime_ptr != 0)
526		/* Store the modtime into *MTIME_PTR for the caller.
527		   If we have had no need to stat the file here,
528		   we record UNKNOWN_MTIME to indicate this.  */
529		*mtime_ptr = (exists_in_cache
530			      ? FILE_TIMESTAMP_STAT_MODTIME (name, st)
531			      : UNKNOWN_MTIME);
532
533	      free (name);
534	      return 1;
535	    }
536	  else
537	    exists = 0;
538	}
539    }
540
541  free (name);
542  return 0;
543}
544
545/* Print the data base of VPATH search paths.  */
546
547void
548print_vpath_data_base ()
549{
550  register unsigned int nvpaths;
551  register struct vpath *v;
552
553  puts (_("\n# VPATH Search Paths\n"));
554
555  nvpaths = 0;
556  for (v = vpaths; v != 0; v = v->next)
557    {
558      register unsigned int i;
559
560      ++nvpaths;
561
562      printf ("vpath %s ", v->pattern);
563
564      for (i = 0; v->searchpath[i] != 0; ++i)
565	printf ("%s%c", v->searchpath[i],
566		v->searchpath[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR);
567    }
568
569  if (vpaths == 0)
570    puts (_("# No `vpath' search paths."));
571  else
572    printf (_("\n# %u `vpath' search paths.\n"), nvpaths);
573
574  if (general_vpath == 0)
575    puts (_("\n# No general (`VPATH' variable) search path."));
576  else
577    {
578      register char **path = general_vpath->searchpath;
579      register unsigned int i;
580
581      fputs (_("\n# General (`VPATH' variable) search path:\n# "), stdout);
582
583      for (i = 0; path[i] != 0; ++i)
584	printf ("%s%c", path[i],
585		path[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR);
586    }
587}
588