Initial revision
authorRoland McGrath <roland@redhat.com>
Mon, 3 Jun 1991 20:37:27 +0000 (20:37 +0000)
committerRoland McGrath <roland@redhat.com>
Mon, 3 Jun 1991 20:37:27 +0000 (20:37 +0000)
commands.h [new file with mode: 0644]
dep.h [new file with mode: 0644]
variable.h [new file with mode: 0644]
vpath.c [new file with mode: 0644]

diff --git a/commands.h b/commands.h
new file mode 100644 (file)
index 0000000..7b3a036
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Make is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Make; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Structure that gives the commands to make a file
+   and information about where these commands came from.  */
+
+struct commands
+  {
+    char *filename;            /* File that contains commands.  */
+    unsigned int lineno;       /* Line number in file.  */
+    char *commands;            /* Commands text.  */
+    unsigned int ncommand_lines;/* Number of command lines.  */
+    char **command_lines;      /* Commands chopped up into lines.  */
+    char *lines_recurse;       /* One flag for each line.  */
+    char any_recurse;          /* Nonzero if any `lines_recurse' elt is.  */
+  };
+
+
+extern void execute_file_commands ();
+extern void print_commands ();
+extern void delete_child_targets ();
+extern void chop_commands ();
diff --git a/dep.h b/dep.h
new file mode 100644 (file)
index 0000000..f5a373c
--- /dev/null
+++ b/dep.h
@@ -0,0 +1,50 @@
+/* Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Make is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Make; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Structure representing one dependency of a file.
+   Each struct file's `deps' points to a chain of these,
+   chained through the `next'.
+
+   Note that the first three words of this match a struct nameseq.  */
+
+struct dep
+  {
+    struct dep *next;
+    char *name;
+    struct file *file;
+    int changed;
+  };
+
+
+/* Structure used in chains of names, for parsing and globbing */
+
+struct nameseq
+  {
+    struct nameseq *next;
+    char *name;
+  };
+
+
+extern struct nameseq *multi_glob (), *parse_file_seq ();
+
+
+#ifndef        iAPX286
+#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name)
+#else
+/* Buggy compiler can't hack this.  */
+extern char *dep_name ();
+#endif
diff --git a/variable.h b/variable.h
new file mode 100644 (file)
index 0000000..00a44fb
--- /dev/null
@@ -0,0 +1,94 @@
+/* Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Make is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Make; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Codes in a variable definition saying where the definition came from.
+   Increasing numeric values signify less-overridable definitions.  */
+enum variable_origin
+  {
+    o_default,         /* Variable from the default set.  */
+    o_env,             /* Variable from environment.  */
+    o_file,            /* Variable given in a makefile.  */
+    o_env_override,    /* Variable from environment, if -e.  */
+    o_command,         /* Variable given by user.  */
+    o_override,        /* Variable from an `override' directive.  */
+    o_automatic,       /* Automatic variable -- cannot be set.  */
+    o_invalid          /* Core dump time.  */
+  };
+
+/* Structure that represents one variable definition.
+   Each bucket of the hash table is a chain of these,
+   chained through `next'.  */
+
+struct variable
+  {
+    struct variable *next;     /* Link in the chain.  */
+    char *name;                        /* Variable name.  */
+    char *value;               /* Variable value.  */
+    enum variable_origin
+      origin ENUM_BITFIELD (3);        /* Variable origin.  */
+    unsigned int recursive:1;  /* Gets recursively re-evaluated.  */
+    unsigned int expanding:1;  /* Nonzero if currently being expanded.  */
+  };
+
+/* Structure that represents a variable set.  */
+
+struct variable_set
+  {
+    struct variable **table;   /* Hash table of variables.  */
+    unsigned int buckets;      /* Number of hash buckets in `table'.  */
+  };
+
+/* Structure that represents a list of variable sets.  */
+
+struct variable_set_list
+  {
+    struct variable_set_list *next;    /* Link in the chain.  */
+    struct variable_set *set;          /* Variable set.  */
+  };
+
+extern struct variable_set_list *current_variable_set_list;
+
+
+extern char *variable_buffer_output ();
+extern char *initialize_variable_output ();
+extern char *save_variable_output ();
+extern void restore_variable_output ();
+
+extern void push_new_variable_scope (), pop_variable_scope ();
+
+extern int handle_function ();
+
+extern char *variable_expand (), *allocated_variable_expand ();
+extern char *variable_expand_for_file ();
+extern char *allocated_variable_expand_for_file ();
+extern char *expand_argument ();
+
+extern void define_automatic_variables ();
+extern void initialize_file_variables ();
+extern void print_file_variables ();
+
+extern void merge_variable_set_lists ();
+
+extern int try_variable_definition ();
+
+extern struct variable *lookup_variable (), *define_variable ();
+extern struct variable *define_variable_for_file ();
+
+extern int pattern_matches ();
+extern char *subst_expand (), *patsubst_expand ();
+
+extern char **target_environment ();
diff --git a/vpath.c b/vpath.c
new file mode 100644 (file)
index 0000000..edd0be3
--- /dev/null
+++ b/vpath.c
@@ -0,0 +1,417 @@
+/* Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Make is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Make; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "make.h"
+#include "file.h"
+#include "variable.h"
+
+
+/* Structure used to represent a selective VPATH searchpath.  */
+
+struct vpath
+  {
+    struct vpath *next;        /* Pointer to next struct in the linked list.  */
+    char *pattern;     /* The pattern to match.  */
+    char *percent;     /* Pointer into `pattern' where the `%' is.  */
+    unsigned int patlen;/* Length of the pattern.  */
+    char **searchpath; /* Null-terminated list of directories.  */
+    unsigned int maxlen;/* Maximum length of any entry in the list.  */
+  };
+
+/* Linked-list of all selective VPATHs.  */
+
+static struct vpath *vpaths;
+
+/* Structure for the general VPATH given in the variable.  */
+
+static struct vpath *general_vpath;
+\f
+static int selective_vpath_search ();
+
+/* Reverse the chain of selective VPATH lists so they
+   will be searched in the order given in the makefiles
+   and construct the list from the VPATH variable.  */
+
+void
+build_vpath_lists ()
+{
+  register struct vpath *new = 0;
+  register struct vpath *old, *nexto;
+  register char *p;
+
+  /* Reverse the chain.  */
+  for (old = vpaths; old != 0; old = nexto)
+    {
+      nexto = old->next;
+      old->next = new;
+      new = old;
+    }
+
+  vpaths = new;
+
+  /* If there is a VPATH variable with a nonnull value, construct the
+     general VPATH list from it.  We use variable_expand rather than just
+     calling lookup_variable so that it will be recursively expanded.  */
+  p = variable_expand ("$(VPATH)");
+  if (*p != '\0')
+    {
+      construct_vpath_list ("%", p);
+      /* VPATHS will be nil if there have been no previous `vpath'
+        directives and none of the given directories exists.  */
+      if (vpaths == 0)
+       general_vpath = 0;
+      else
+       {
+         general_vpath = vpaths;
+         /* It was just put into the linked list,
+            but we don't want it there, so we must remove it.  */
+         vpaths = general_vpath->next;
+       }
+    }
+}
+\f
+/* Construct the VPATH listing for the pattern and searchpath given.
+
+   This function is called to generate selective VPATH lists and also for
+   the general VPATH list (which is in fact just a selective VPATH that
+   is applied to everything).  The returned pointer is either put in the
+   linked list of all selective VPATH lists or in the GENERAL_VPATH
+   variable.
+
+   If SEARCHPATH is nil, remove all previous listings with the same
+   pattern.  If PATTERN is nil, remove all VPATH listings.
+   Existing and readable directories that are not "." given in the
+   searchpath separated by colons are loaded into the directory hash
+   table if they are not there already and put in the VPATH searchpath
+   for the given pattern with trailing slashes stripped off if present
+   (and if the directory is not the root, "/").
+   The length of the longest entry in the list is put in the structure as well.
+   The new entry will be at the head of the VPATHS chain.  */
+
+void
+construct_vpath_list (pattern, dirpath)
+     char *pattern, *dirpath;
+{
+  register unsigned int elem;
+  register char *p;
+  register char **vpath;
+  register unsigned int maxvpath;
+  unsigned int maxelem;
+  char *percent;
+
+  if (pattern != 0)
+    {
+      pattern = savestring (pattern, strlen (pattern));
+      percent = find_percent (pattern);
+    }
+
+  if (dirpath == 0)
+    {
+      /* Remove matching listings.  */
+      register struct vpath *path, *lastpath;
+
+      lastpath = vpaths;
+      for (path = vpaths; path != 0; lastpath = path, path = path->next)
+       if (pattern == 0
+           || (((percent == 0 && path->percent == 0)
+                || (percent - pattern == path->percent - path->pattern))
+               && streq (pattern, path->pattern)))
+         {
+           /* Remove it from the linked list.  */
+           if (lastpath == vpaths)
+             vpaths = path->next;
+           else
+             lastpath->next = path->next;
+
+           /* Free its unused storage.  */
+           free (path->pattern);
+           free ((char *) path->searchpath);
+           free ((char *) path);
+         }
+      if (pattern != 0)
+       free (pattern);
+      return;
+    }
+
+  /* Skip over any initial colons.  */
+  p = dirpath;
+  while (*p == ':')
+    ++p;
+
+  /* Figure out the maximum number of VPATH entries and
+     put it in MAXELEM.  We start with 2, one before the
+     first colon and one nil, the list terminator and
+     increment our estimated number for each colon we find.  */
+  maxelem = 2;
+  while (*p != '\0')
+    if (*p++ == ':')
+      ++maxelem;
+
+  vpath = (char **) xmalloc (maxelem * sizeof (char *));
+  maxvpath = 0;
+
+  elem = 0;
+  p = dirpath;
+  while (*p != '\0')
+    {
+      char *v;
+      unsigned int len;
+
+      /* Find the next entry.  */
+      while (*p != '\0' && *p == ':')
+       ++p;
+      if (*p == '\0')
+       break;
+
+      /* Find the end of this entry.  */
+      v = p;
+      while (*p != '\0' && *p != ':')
+       ++p;
+
+      len = p - v;
+      /* Make sure there's no trailing slash,
+        but still allow "/" as a directory.  */
+      if (len > 1 && p[-1] == '/')
+       --len;
+
+      if (len == 1 && *v == '.')
+       continue;
+
+      v = savestring (v, len);
+      if (dir_file_exists_p (v, ""))
+       {
+         vpath[elem++] = dir_name (v);
+         free (v);
+         if (len > maxvpath)
+           maxvpath = len;
+       }
+      else
+       free (v);
+    }
+
+  if (elem > 0)
+    {
+      struct vpath *path;
+      /* ELEM is now incremented one element past the last
+        entry, to where the nil-pointer terminator goes.
+        Usually this is maxelem - 1.  If not, shrink down.  */
+      if (elem < (maxelem - 1))
+       vpath = (char **) xrealloc ((char *) vpath,
+                                   (elem + 1) * sizeof (char *));
+
+      /* Put the nil-pointer terminator on the end of the VPATH list.  */
+      vpath[elem] = 0;
+
+      /* Construct the vpath structure and put it into the linked list.  */
+      path = (struct vpath *) xmalloc (sizeof (struct vpath));
+      path->searchpath = vpath;
+      path->maxlen = maxvpath;
+      path->next = vpaths;
+      vpaths = path;
+
+      /* Set up the members.  */
+      path->pattern = pattern;
+      path->percent = percent;
+      path->patlen = strlen (pattern);
+    }
+  else
+    /* There were no entries, so free whatever space we allocated.  */
+    free ((char *) vpath);
+}
+\f
+/* Search the VPATH list whose pattern matches *FILE for a directory
+   where the name pointed to by FILE exists.  If it is found, the pointer
+   in FILE is set to the newly malloc'd name of the existing file and
+   we return 1.  Otherwise we return 0.  */
+
+int
+vpath_search (file)
+     char **file;
+{
+  register struct vpath *v;
+
+  /* If there are no VPATH entries or FILENAME starts at the root,
+     there is nothing we can do.  */
+
+  if (**file == '/' || (vpaths == 0 && general_vpath == 0))
+    return 0;
+
+  for (v = vpaths; v != 0; v = v->next)
+    if (pattern_matches (v->pattern, v->percent, *file))
+      if (selective_vpath_search (v, file))
+       return 1;
+
+  if (general_vpath != 0
+      && selective_vpath_search (general_vpath, file))
+    return 1;
+
+  return 0;
+}
+
+
+/* Search the given VPATH list for a directory where the name pointed
+   to by FILE exists.  If it is found, the pointer in FILE
+   is set to the newly malloc'd name of the existing file and we return 1.
+   Otherwise we return 0.  */
+
+static int
+selective_vpath_search (path, file)
+     struct vpath *path;
+     char **file;
+{
+  int not_target;
+  char *name, *n;
+  char *filename;
+  register char **vpath = path->searchpath;
+  unsigned int maxvpath = path->maxlen;
+  register unsigned int i;
+  unsigned int flen, vlen, name_dplen;
+  int exists = 0;
+
+  /* Find out if *FILE is a target.
+     If and only if it is NOT a target, we will accept prospective
+     files that don't exist but are mentioned in a makefile.  */
+  {
+    struct file *f = lookup_file (*file);
+    not_target = f == 0 || !f->is_target;
+  }
+
+  flen = strlen (*file);
+
+  /* Split *FILE into a directory prefix and a name-within-directory.
+     NAME_DPLEN gets the length of the prefix; FILENAME gets the
+     pointer to the name-within-directory and FLEN is its length.  */
+
+  n = rindex (*file, '/');
+  name_dplen = n != 0 ? n - *file : 0;
+  filename = name_dplen > 0 ? n + 1 : *file;
+  if (name_dplen > 0)
+    flen -= name_dplen + 1;
+
+  /* Allocate enough space for the biggest VPATH entry,
+     a slash, the directory prefix that came with *FILE,
+     another slash (although this one may not always be
+     necessary), the filename, and a null terminator.  */
+  name = (char *) alloca (maxvpath + 1 + name_dplen + 1 + flen + 1);
+
+  /* Try each VPATH entry.  */
+  for (i = 0; vpath[i] != 0; ++i)
+    {
+      n = name;
+
+      /* Put the next VPATH entry into NAME at N and increment N past it.  */
+      vlen = strlen (vpath[i]);
+      bcopy (vpath[i], n, vlen);
+      n += vlen;
+
+      /* Add the directory prefix already in *FILE.  */
+      if (name_dplen > 0)
+       {
+         *n++ = '/';
+         bcopy (*file, n, name_dplen);
+         n += name_dplen;
+       }
+
+      /* Now add the name-within-directory at the end of NAME.  */
+      if (n != name && n[-1] != '/')
+       *n = '/';
+      bcopy (filename, n + 1, flen + 1);
+
+      if (not_target)
+       /* Since *FILE is not a target, if the file is
+          mentioned in a makefile, we consider it existent.  */
+       exists = lookup_file (name) != 0;
+
+      if (!exists)
+       {
+         /* That file wasn't mentioned in the makefile.
+            See if it actually exists.  */
+
+         /* Clobber a null into the name at the last slash.
+            Now NAME is the name of the directory to look in.  */
+         *n = '\0';
+
+         /* Make sure the directory exists and we know its contents.  */
+         if (name_dplen > 0 && !dir_file_exists_p (name, ""))
+           /* It doesn't exist.  */
+           continue;
+
+         /* We know the directory is in the hash table now because either
+            construct_vpath_list or the code just above put it there.
+            Does the file we seek exist in it?  */
+         exists = dir_file_exists_p (name, filename);
+       }
+
+      if (exists)
+       {
+         /* We have found a file.
+            Store the name we found into *FILE for the caller.  */
+
+         /* Put the slash back in NAME.  */
+         *n = '/';
+
+         *file = savestring (name, (n + 1 - name) + flen);
+
+         return 1;
+       }
+    }
+
+  return 0;
+}
+\f
+/* Print the data base of VPATH search paths.  */
+
+void
+print_vpath_data_base ()
+{
+  register unsigned int nvpaths;
+  register struct vpath *v;
+
+  puts ("\n# VPATH Search Paths\n");
+
+  nvpaths = 0;
+  for (v = vpaths; v != 0; v = v->next)
+    {
+      register unsigned int i;
+
+      ++nvpaths;
+
+      printf ("vpath %s ", v->pattern);
+
+      for (i = 0; v->searchpath[i] != 0; ++i)
+       printf ("%s%c", v->searchpath[i],
+               v->searchpath[i + 1] == 0 ? '\n' : ':');
+    }
+
+  if (vpaths == 0)
+    puts ("# No `vpath' search paths.");
+  else
+    printf ("\n# %u `vpath' search paths.\n", nvpaths);
+
+  if (general_vpath == 0)
+    puts ("\n# No general (`VPATH' variable) search path.");
+  else
+    {
+      register char **path = general_vpath->searchpath;
+      register unsigned int i;
+
+      fputs ("\n# General (`VPATH' variable) search path:\n# ", stdout);
+
+      for (i = 0; path[i] != 0; ++i)
+       printf ("%s%c", path[i], path[i + 1] == 0 ? '\n' : ':');
+    }
+}