summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog24
-rw-r--r--ar.c63
-rw-r--r--commands.c4
-rw-r--r--default.c10
-rw-r--r--dep.h15
-rw-r--r--dir.c22
-rw-r--r--expand.c8
-rw-r--r--file.c410
-rw-r--r--filedef.h18
-rw-r--r--function.c366
-rw-r--r--implicit.c119
-rw-r--r--job.c4
-rw-r--r--main.c177
-rw-r--r--maintMakefile28
-rw-r--r--make.h15
-rw-r--r--misc.c101
-rw-r--r--read.c457
-rw-r--r--remake.c67
-rw-r--r--rule.c241
-rw-r--r--rule.h15
-rw-r--r--strcache.c72
-rwxr-xr-xtests/run_make_tests.pl3
-rw-r--r--tests/scripts/features/patternrules14
-rw-r--r--tests/test_driver.pl10
-rw-r--r--variable.c55
-rw-r--r--variable.h22
-rw-r--r--vpath.c171
27 files changed, 1266 insertions, 1245 deletions
diff --git a/ChangeLog b/ChangeLog
index a3b5237..aa8fa94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,31 @@
+2007-03-19 Paul Smith <psmith@gnu.org>
+
+ * ALL: Use the strcache for all file name strings, or other
+ strings which we will never free. The goal is to save memory by
+ avoiding duplicate copies of strings. However, at the moment this
+ doesn't save much memory in most situations: due to secondary
+ expansion we actually save prerequisite lists twice (once before
+ the secondary expansion, and then again after it's been parsed
+ into individual file names in the dep list). We will resolve this
+ in a future change, by doing the parsing up-front for targets
+ where secondary expansion is not set.
+
+ Moving things into the strcache also allows us to use const
+ pointers in many more places.
+
+2007-01-03 Paul Smith <psmith@gnu.org>
+
+ * make.h (ENULLLOOP): Reset errno after each failed invocation of
+ the function, not just the first. Fixes Savannah bug #18680.
+
2006-11-18 Paul Smith <psmith@gnu.org>
* strcache.c (strcache_add_len): Don't allocate a new buffer
unless the string is not already nil-terminated. Technically this
is a violation of the standard, since we may be passed an array
that is not long enough to test one past. However, in make this
- is never true since we only use nil-terminated strings.
+ is never true since we only use nil-terminated strings or
+ sub-strings thereof.
* read.c (eval, do_define): Use cmd_prefix instead of '\t'.
@@ -24,6 +45,7 @@
* vmsify.c: Constification. Hard to test this but I hope I didn't
screw it up!
* vpath.c: Partial constification.
+ * w32/pathstuff.c: Partial constification.
2006-11-16 Eli Zaretskii <eliz@gnu.org>
diff --git a/ar.c b/ar.c
index 9bf0cb7..a8b5ceb 100644
--- a/ar.c
+++ b/ar.c
@@ -50,19 +50,19 @@ ar_name (const char *name)
/* Parse the archive-member reference NAME into the archive and member names.
- Put the malloc'd archive name in *ARNAME_P if ARNAME_P is non-nil;
- put the malloc'd member name in *MEMNAME_P if MEMNAME_P is non-nil. */
+ Creates one allocated string containing both names, pointed to by ARNAME_P.
+ MEMNAME_P points to the member. */
void
ar_parse_name (const char *name, char **arname_p, char **memname_p)
{
- const char *p = strchr (name, '('), *end = name + strlen (name) - 1;
+ char *p;
- if (arname_p != 0)
- *arname_p = savestring (name, p - name);
-
- if (memname_p != 0)
- *memname_p = savestring (p + 1, end - (p + 1));
+ *arname_p = xstrdup (name);
+ p = strchr (*arname_p, '(');
+ *(p++) = '\0';
+ p[strlen(p) - 1] = '\0';
+ *memname_p = p;
}
@@ -86,7 +86,6 @@ ar_member_date (const char *name)
{
char *arname;
char *memname;
- int arname_used = 0;
long int val;
ar_parse_name (name, &arname, &memname);
@@ -102,10 +101,7 @@ ar_member_date (const char *name)
struct file *arfile;
arfile = lookup_file (arname);
if (arfile == 0 && file_exists_p (arname))
- {
- arfile = enter_file (arname);
- arname_used = 1;
- }
+ arfile = enter_file (strcache_add (arname));
if (arfile != 0)
(void) f_mtime (arfile, 0);
@@ -113,9 +109,7 @@ ar_member_date (const char *name)
val = ar_scan (arname, ar_member_date_1, memname);
- if (!arname_used)
- free (arname);
- free (memname);
+ free (arname);
return (val <= 0 ? (time_t) -1 : (time_t) val);
}
@@ -134,23 +128,16 @@ int
ar_touch (const char *name)
{
char *arname, *memname;
- int arname_used = 0;
- register int val;
+ int val;
ar_parse_name (name, &arname, &memname);
/* Make sure we know the modtime of the archive itself before we
- touch the member, since this will change the archive itself. */
+ touch the member, since this will change the archive modtime. */
{
struct file *arfile;
- arfile = lookup_file (arname);
- if (arfile == 0)
- {
- arfile = enter_file (arname);
- arname_used = 1;
- }
-
- (void) f_mtime (arfile, 0);
+ arfile = enter_file (strcache_add (arname));
+ f_mtime (arfile, 0);
}
val = 1;
@@ -177,9 +164,7 @@ ar_touch (const char *name)
_("touch: Bad return code from ar_member_touch on `%s'"), name);
}
- if (!arname_used)
- free (arname);
- free (memname);
+ free (arname);
return val;
}
@@ -189,7 +174,7 @@ ar_touch (const char *name)
struct ar_glob_state
{
- char *arname;
+ const char *arname;
const char *pattern;
unsigned int size;
struct nameseq *chain;
@@ -211,7 +196,7 @@ ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED,
{
/* We have a match. Add it to the chain. */
struct nameseq *new = xmalloc (state->size);
- new->name = concat (state->arname, mem, ")");
+ new->name = strcache_add (concat (state->arname, mem, ")"));
new->next = state->chain;
state->chain = new;
++state->n;
@@ -260,8 +245,9 @@ struct nameseq *
ar_glob (const char *arname, const char *member_pattern, unsigned int size)
{
struct ar_glob_state state;
- char **names;
struct nameseq *n;
+ const char **names;
+ char *name;
unsigned int i;
if (! glob_pattern_p (member_pattern, 1))
@@ -270,10 +256,11 @@ ar_glob (const char *arname, const char *member_pattern, unsigned int size)
/* Scan the archive for matches.
ar_glob_match will accumulate them in STATE.chain. */
i = strlen (arname);
- state.arname = alloca (i + 2);
- memcpy (state.arname, arname, i);
- state.arname[i] = '(';
- state.arname[i + 1] = '\0';
+ name = alloca (i + 2);
+ memcpy (name, arname, i);
+ name[i] = '(';
+ name[i + 1] = '\0';
+ state.arname = name;
state.pattern = member_pattern;
state.size = size;
state.chain = 0;
@@ -284,7 +271,7 @@ ar_glob (const char *arname, const char *member_pattern, unsigned int size)
return 0;
/* Now put the names into a vector for sorting. */
- names = alloca (state.n * sizeof (char *));
+ names = alloca (state.n * sizeof (const char *));
i = 0;
for (n = state.chain; n != 0; n = n->next)
names[i++] = n->name;
diff --git a/commands.c b/commands.c
index d1db6fe..246fe28 100644
--- a/commands.c
+++ b/commands.c
@@ -97,12 +97,12 @@ set_file_variables (struct file *file)
len = strlen (name);
}
- for (d = enter_file (".SUFFIXES")->deps; d != 0; d = d->next)
+ for (d = enter_file (strcache_add (".SUFFIXES"))->deps; d ; d = d->next)
{
unsigned int slen = strlen (dep_name (d));
if (len > slen && strneq (dep_name (d), name + (len - slen), slen))
{
- file->stem = savestring (name, len - slen);
+ file->stem = strcache_add_len (name, len - slen);
break;
}
}
diff --git a/default.c b/default.c
index 95f5635..2d5480d 100644
--- a/default.c
+++ b/default.c
@@ -522,23 +522,23 @@ static const char *default_variables[] =
void
set_default_suffixes (void)
{
- suffix_file = enter_file (".SUFFIXES");
+ suffix_file = enter_file (strcache_add (".SUFFIXES"));
if (no_builtin_rules_flag)
- (void) define_variable ("SUFFIXES", 8, "", o_default, 0);
+ define_variable ("SUFFIXES", 8, "", o_default, 0);
else
{
char *p = default_suffixes;
suffix_file->deps = (struct dep *)
multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
sizeof (struct dep));
- (void) define_variable ("SUFFIXES", 8, default_suffixes, o_default, 0);
+ define_variable ("SUFFIXES", 8, default_suffixes, o_default, 0);
}
}
/* Enter the default suffix rules as file rules. This used to be done in
install_default_implicit_rules, but that loses because we want the
- suffix rules installed before reading makefiles, and thee pattern rules
+ suffix rules installed before reading makefiles, and the pattern rules
installed after. */
void
@@ -551,7 +551,7 @@ install_default_suffix_rules (void)
for (s = default_suffix_rules; *s != 0; s += 2)
{
- struct file *f = enter_file (s[0]);
+ struct file *f = enter_file (strcache_add (s[0]));
/* Don't clobber cmds given in a makefile if there were any. */
if (f->cmds == 0)
{
diff --git a/dep.h b/dep.h
index f84a83e..adc92c7 100644
--- a/dep.h
+++ b/dep.h
@@ -36,8 +36,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
struct dep
{
struct dep *next;
- char *name;
- char *stem;
+ const char *name;
+ const char *stem;
struct file *file;
unsigned int changed : 8;
unsigned int ignore_mtime : 1;
@@ -51,7 +51,7 @@ struct dep
struct nameseq
{
struct nameseq *next;
- char *name;
+ const char *name;
};
@@ -61,25 +61,20 @@ struct nameseq *parse_file_seq ();
#else
struct nameseq *parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip);
#endif
-char *tilde_expand (char *name);
+char *tilde_expand (const char *name);
#ifndef NO_ARCHIVES
struct nameseq *ar_glob (const char *arname, const char *member_pattern, unsigned int size);
#endif
-#ifndef iAPX286
#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name)
-#else
-/* Buggy compiler can't hack this. */
-char *dep_name ();
-#endif
struct dep *alloc_dep (void);
void free_dep (struct dep *d);
struct dep *copy_dep_chain (const struct dep *d);
void free_dep_chain (struct dep *d);
void free_ns_chain (struct nameseq *n);
-struct dep *read_all_makefiles (char **makefiles);
+struct dep *read_all_makefiles (const char **makefiles);
int eval_buffer (char *buffer);
int update_goal_chain (struct dep *goals);
void uniquize_deps (struct dep *);
diff --git a/dir.c b/dir.c
index 12e0382..de4debc 100644
--- a/dir.c
+++ b/dir.c
@@ -1124,29 +1124,28 @@ open_dirstream (const char *directory)
static struct dirent *
read_dirstream (__ptr_t stream)
{
+ static char *buf;
+ static unsigned int bufsz;
+
struct dirstream *const ds = (struct dirstream *) stream;
struct directory_contents *dc = ds->contents;
struct dirfile **dirfile_end = (struct dirfile **) dc->dirfiles.ht_vec + dc->dirfiles.ht_size;
- static char *buf;
- static unsigned int bufsz;
while (ds->dirfile_slot < dirfile_end)
{
- register struct dirfile *df = *ds->dirfile_slot++;
+ struct dirfile *df = *ds->dirfile_slot++;
if (! HASH_VACANT (df) && !df->impossible)
{
- /* The glob interface wants a `struct dirent',
- so mock one up. */
+ /* The glob interface wants a `struct dirent', so mock one up. */
struct dirent *d;
unsigned int len = df->length + 1;
- if (sizeof *d - sizeof d->d_name + len > bufsz)
+ unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len;
+ if (sz > bufsz)
{
- if (buf != 0)
- free (buf);
bufsz *= 2;
- if (sizeof *d - sizeof d->d_name + len > bufsz)
- bufsz = sizeof *d - sizeof d->d_name + len;
- buf = xmalloc (bufsz);
+ if (sz > bufsz)
+ bufsz = sz;
+ buf = xrealloc (buf, bufsz);
}
d = (struct dirent *) buf;
#ifdef __MINGW32__
@@ -1200,7 +1199,6 @@ local_stat (const char *path, struct stat *buf)
void
dir_setup_glob (glob_t *gl)
{
- /* Bogus sunos4 compiler complains (!) about & before functions. */
gl->gl_opendir = open_dirstream;
gl->gl_readdir = read_dirstream;
gl->gl_closedir = ansi_free;
diff --git a/expand.c b/expand.c
index 4aadb26..cc8ede4 100644
--- a/expand.c
+++ b/expand.c
@@ -360,7 +360,9 @@ variable_expand_string (char *line, const char *string, long length)
if (ppercent)
{
++ppercent;
- rpercent = 0;
+ rpercent = find_percent (replace);
+ if (rpercent)
+ ++rpercent;
}
else
{
@@ -370,8 +372,8 @@ variable_expand_string (char *line, const char *string, long length)
--replace;
}
- o = patsubst_expand (o, value, pattern, replace,
- ppercent, rpercent);
+ o = patsubst_expand_pat (o, value, pattern, replace,
+ ppercent, rpercent);
if (v->recursive)
free (value);
diff --git a/file.c b/file.c
index 638736b..479d893 100644
--- a/file.c
+++ b/file.c
@@ -69,16 +69,16 @@ static int all_secondary = 0;
/* Access the hash table of all file records.
lookup_file given a name, return the struct file * for that name,
- or nil if there is none.
- enter_file similar, but create one if there is none. */
+ or nil if there is none.
+*/
struct file *
-lookup_file (char *name)
+lookup_file (const char *name)
{
- register struct file *f;
+ struct file *f;
struct file file_key;
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
- char *lname, *ln;
+ char *lname;
#endif
assert (*name != '\0');
@@ -90,8 +90,9 @@ lookup_file (char *name)
# ifndef WANT_CASE_SENSITIVE_TARGETS
if (*name != '.')
{
- char *n;
- lname = xmalloc (strlen (name) + 1);
+ const char *n;
+ char *ln;
+ lname = xstrdup (name);
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
*ln = isupper ((unsigned char)*n) ? tolower ((unsigned char)*n) : *n;
*ln = '\0';
@@ -112,15 +113,13 @@ lookup_file (char *name)
if (*name == '\0')
/* It was all slashes after a dot. */
-#ifdef VMS
+#if defined(VMS)
name = "[]";
-#else
-#ifdef _AMIGA
+#elif defined(_AMIGA)
name = "";
#else
name = "./";
-#endif /* AMIGA */
-#endif /* VMS */
+#endif
file_key.hname = name;
f = hash_find_item (&files, &file_key);
@@ -128,39 +127,41 @@ lookup_file (char *name)
if (*name != '.')
free (lname);
#endif
+
return f;
}
+/* Look up a file record for file NAME and return it.
+ Create a new record if one doesn't exist. NAME will be stored in the
+ new record so it should be constant or in the strcache etc.
+ */
+
struct file *
-enter_file (char *name)
+enter_file (const char *name)
{
- register struct file *f;
- register struct file *new;
- register struct file **file_slot;
+ struct file *f;
+ struct file *new;
+ struct file **file_slot;
struct file file_key;
-#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
- char *lname, *ln;
-#endif
assert (*name != '\0');
+ assert (strcache_iscached (name));
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
if (*name != '.')
{
- char *n;
- lname = xmalloc (strlen (name) + 1);
+ const char *n;
+ char *lname, *ln;
+ lname = xstrdup (name);
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
- {
- if (isupper ((unsigned char)*n))
- *ln = tolower ((unsigned char)*n);
- else
- *ln = *n;
- }
+ if (isupper ((unsigned char)*n))
+ *ln = tolower ((unsigned char)*n);
+ else
+ *ln = *n;
- *ln = 0;
- /* Creates a possible leak, old value of name is unreachable, but I
- currently don't know how to fix it. */
- name = lname;
+ *ln = '\0';
+ name = strcache_add (lname);
+ free (lname);
}
#endif
@@ -168,13 +169,7 @@ enter_file (char *name)
file_slot = (struct file **) hash_find_slot (&files, &file_key);
f = *file_slot;
if (! HASH_VACANT (f) && !f->double_colon)
- {
-#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
- if (*name != '.')
- free (lname);
-#endif
- return f;
- }
+ return f;
new = xmalloc (sizeof (struct file));
memset (new, '\0', sizeof (struct file));
@@ -197,27 +192,12 @@ enter_file (char *name)
return new;
}
-/* Rename FILE to NAME. This is not as simple as resetting
- the `name' member, since it must be put in a new hash bucket,
- and possibly merged with an existing file called NAME. */
-
-void
-rename_file (struct file *from_file, char *to_hname)
-{
- rehash_file (from_file, to_hname);
- while (from_file)
- {
- from_file->name = from_file->hname;
- from_file = from_file->prev;
- }
-}
-
/* Rehash FILE to NAME. This is not as simple as resetting
the `hname' member, since it must be put in a new hash bucket,
and possibly merged with an existing file called NAME. */
void
-rehash_file (struct file *from_file, char *to_hname)
+rehash_file (struct file *from_file, const char *to_hname)
{
struct file file_key;
struct file **file_slot;
@@ -225,108 +205,130 @@ rehash_file (struct file *from_file, char *to_hname)
struct file *deleted_file;
struct file *f;
+ /* If it's already that name, we're done. */
file_key.hname = to_hname;
- if (0 == file_hash_cmp (from_file, &file_key))
+ if (! file_hash_cmp (from_file, &file_key))
return;
+ /* Find the end of the renamed list for the "from" file. */
file_key.hname = from_file->hname;
while (from_file->renamed != 0)
from_file = from_file->renamed;
if (file_hash_cmp (from_file, &file_key))
- /* hname changed unexpectedly */
+ /* hname changed unexpectedly!! */
abort ();
+ /* Remove the "from" file from the hash. */
deleted_file = hash_delete (&files, from_file);
if (deleted_file != from_file)
/* from_file isn't the one stored in files */
abort ();
+ /* Find where the newly renamed file will go in the hash. */
file_key.hname = to_hname;
file_slot = (struct file **) hash_find_slot (&files, &file_key);
to_file = *file_slot;
+ /* Change the hash name for this file. */
from_file->hname = to_hname;
for (f = from_file->double_colon; f != 0; f = f->prev)
f->hname = to_hname;
+ /* If the new name doesn't exist yet just set it to the renamed file. */
if (HASH_VACANT (to_file))
- hash_insert_at (&files, from_file, file_slot);
- else
{
- /* TO_FILE already exists under TO_HNAME.
- We must retain TO_FILE and merge FROM_FILE into it. */
+ hash_insert_at (&files, from_file, file_slot);
+ return;
+ }
- if (from_file->cmds != 0)
- {
- if (to_file->cmds == 0)
- to_file->cmds = from_file->cmds;
- else if (from_file->cmds != to_file->cmds)
- {
- /* We have two sets of commands. We will go with the
- one given in the rule explicitly mentioning this name,
- but give a message to let the user know what's going on. */
- if (to_file->cmds->fileinfo.filenm != 0)
- error (&from_file->cmds->fileinfo,
- _("Commands were specified for file `%s' at %s:%lu,"),
- from_file->name, to_file->cmds->fileinfo.filenm,
- to_file->cmds->fileinfo.lineno);
- else
- error (&from_file->cmds->fileinfo,
- _("Commands for file `%s' were found by implicit rule search,"),
- from_file->name);
- error (&from_file->cmds->fileinfo,
- _("but `%s' is now considered the same file as `%s'."),
- from_file->name, to_hname);
- error (&from_file->cmds->fileinfo,
- _("Commands for `%s' will be ignored in favor of those for `%s'."),
- to_hname, from_file->name);
- }
- }
+ /* TO_FILE already exists under TO_HNAME.
+ We must retain TO_FILE and merge FROM_FILE into it. */
- /* Merge the dependencies of the two files. */
+ if (from_file->cmds != 0)
+ {
+ if (to_file->cmds == 0)
+ to_file->cmds = from_file->cmds;
+ else if (from_file->cmds != to_file->cmds)
+ {
+ /* We have two sets of commands. We will go with the
+ one given in the rule explicitly mentioning this name,
+ but give a message to let the user know what's going on. */
+ if (to_file->cmds->fileinfo.filenm != 0)
+ error (&from_file->cmds->fileinfo,
+ _("Commands were specified for file `%s' at %s:%lu,"),
+ from_file->name, to_file->cmds->fileinfo.filenm,
+ to_file->cmds->fileinfo.lineno);
+ else
+ error (&from_file->cmds->fileinfo,
+ _("Commands for file `%s' were found by implicit rule search,"),
+ from_file->name);
+ error (&from_file->cmds->fileinfo,
+ _("but `%s' is now considered the same file as `%s'."),
+ from_file->name, to_hname);
+ error (&from_file->cmds->fileinfo,
+ _("Commands for `%s' will be ignored in favor of those for `%s'."),
+ to_hname, from_file->name);
+ }
+ }
- if (to_file->deps == 0)
- to_file->deps = from_file->deps;
- else
- {
- register struct dep *deps = to_file->deps;
- while (deps->next != 0)
- deps = deps->next;
- deps->next = from_file->deps;
- }
+ /* Merge the dependencies of the two files. */
- merge_variable_set_lists (&to_file->variables, from_file->variables);
+ if (to_file->deps == 0)
+ to_file->deps = from_file->deps;
+ else
+ {
+ struct dep *deps = to_file->deps;
+ while (deps->next != 0)
+ deps = deps->next;
+ deps->next = from_file->deps;
+ }
- if (to_file->double_colon && from_file->is_target && !from_file->double_colon)
- fatal (NILF, _("can't rename single-colon `%s' to double-colon `%s'"),
- from_file->name, to_hname);
- if (!to_file->double_colon && from_file->double_colon)
- {
- if (to_file->is_target)
- fatal (NILF, _("can't rename double-colon `%s' to single-colon `%s'"),
- from_file->name, to_hname);
- else
- to_file->double_colon = from_file->double_colon;
- }
+ merge_variable_set_lists (&to_file->variables, from_file->variables);
+
+ if (to_file->double_colon && from_file->is_target && !from_file->double_colon)
+ fatal (NILF, _("can't rename single-colon `%s' to double-colon `%s'"),
+ from_file->name, to_hname);
+ if (!to_file->double_colon && from_file->double_colon)
+ {
+ if (to_file->is_target)
+ fatal (NILF, _("can't rename double-colon `%s' to single-colon `%s'"),
+ from_file->name, to_hname);
+ else
+ to_file->double_colon = from_file->double_colon;
+ }
- if (from_file->last_mtime > to_file->last_mtime)
- /* %%% Kludge so -W wins on a file that gets vpathized. */
- to_file->last_mtime = from_file->last_mtime;
+ if (from_file->last_mtime > to_file->last_mtime)
+ /* %%% Kludge so -W wins on a file that gets vpathized. */
+ to_file->last_mtime = from_file->last_mtime;
- to_file->mtime_before_update = from_file->mtime_before_update;
+ to_file->mtime_before_update = from_file->mtime_before_update;
#define MERGE(field) to_file->field |= from_file->field
- MERGE (precious);
- MERGE (tried_implicit);
- MERGE (updating);
- MERGE (updated);
- MERGE (is_target);
- MERGE (cmd_target);
- MERGE (phony);
- MERGE (ignore_vpath);
+ MERGE (precious);
+ MERGE (tried_implicit);
+ MERGE (updating);
+ MERGE (updated);
+ MERGE (is_target);
+ MERGE (cmd_target);
+ MERGE (phony);
+ MERGE (ignore_vpath);
#undef MERGE
- from_file->renamed = to_file;
+ from_file->renamed = to_file;
+}
+
+/* Rename FILE to NAME. This is not as simple as resetting
+ the `name' member, since it must be put in a new hash bucket,
+ and possibly merged with an existing file called NAME. */
+
+void
+rename_file (struct file *from_file, const char *to_hname)
+{
+ rehash_file (from_file, to_hname);
+ while (from_file)
+ {
+ from_file->name = from_file->hname;
+ from_file = from_file->prev;
}
}
@@ -338,8 +340,8 @@ rehash_file (struct file *from_file, char *to_hname)
void
remove_intermediates (int sig)
{
- register struct file **file_slot;
- register struct file **file_end;
+ struct file **file_slot;
+ struct file **file_end;
int doneany = 0;
/* If there's no way we will ever remove anything anyway, punt early. */
@@ -354,7 +356,7 @@ remove_intermediates (int sig)
for ( ; file_slot < file_end; file_slot++)
if (! HASH_VACANT (*file_slot))
{
- register struct file *f = *file_slot;
+ struct file *f = *file_slot;
/* Is this file eligible for automatic deletion?
Yes, IFF: it's marked intermediate, it's not secondary, it wasn't
given on the command-line, and it's either a -include makefile or
@@ -444,7 +446,6 @@ parse_prereqs (char *p)
return new;
}
-
/* Set the intermediate flag. */
static void
@@ -460,7 +461,7 @@ expand_deps (struct file *f)
{
struct dep *d;
struct dep *old = f->deps;
- char *file_stem = f->stem;
+ const char *file_stem = f->stem;
unsigned int last_dep_has_cmds = f->updating;
int initialized = 0;
@@ -476,9 +477,13 @@ expand_deps (struct file *f)
continue;
/* Create the dependency list.
- If we're not doing 2nd expansion, then it's just the name. */
+ If we're not doing 2nd expansion, then it's just the name. We will
+ still need to massage it though. */
if (! d->need_2nd_expansion)
- p = d->name;
+ {
+ p = variable_expand ("");
+ variable_buffer_output (p, d->name, strlen (d->name) + 1);
+ }
else
{
/* If it's from a static pattern rule, convert the patterns into
@@ -490,8 +495,7 @@ expand_deps (struct file *f)
o = subst_expand (buffer, d->name, "%", "$*", 1, 2, 0);
- free (d->name);
- d->name = savestring (buffer, o - buffer);
+ d->name = strcache_add_len (buffer, o - buffer);
d->staticpattern = 0; /* Clear staticpattern so that we don't
re-expand %s below. */
}
@@ -525,48 +529,47 @@ expand_deps (struct file *f)
plain prerequisite names. */
if (new && d->staticpattern)
{
- char *pattern = "%";
+ const char *pattern = "%";
char *buffer = variable_expand ("");
struct dep *dp = new, *dl = 0;
while (dp != 0)
{
- char *percent = find_percent (dp->name);
+ char *percent;
+ int nl = strlen (dp->name) + 1;
+ char *nm = alloca (nl);
+ memcpy (nm, dp->name, nl);
+ percent = find_percent (nm);
if (percent)
{
+ char *o;
+
/* We have to handle empty stems specially, because that
would be equivalent to $(patsubst %,dp->name,) which
will always be empty. */
if (d->stem[0] == '\0')
- /* This needs memmove() in ISO C. */
- memmove (percent, percent+1, strlen (percent));
- else
{
- char *o = patsubst_expand (buffer, d->stem, pattern,
- dp->name, pattern+1,
- percent+1);
- if (o == buffer)
- dp->name[0] = '\0';
- else
- {
- free (dp->name);
- dp->name = savestring (buffer, o - buffer);
- }
+ memmove (percent, percent+1, strlen (percent));
+ o = variable_buffer_output (buffer, nm, strlen (nm) + 1);
}
+ else
+ o = patsubst_expand_pat (buffer, d->stem, pattern, nm,
+ pattern+1, percent+1);
/* If the name expanded to the empty string, ignore it. */
- if (dp->name[0] == '\0')
+ if (buffer[0] == '\0')
{
struct dep *df = dp;
if (dp == new)
dp = new = new->next;
else
dp = dl->next = dp->next;
- /* @@ Are we leaking df->name here? */
- df->name = 0;
free_dep (df);
continue;
}
+
+ /* Save the name. */
+ dp->name = strcache_add_len (buffer, o - buffer);
}
dl = dp;
dp = dp->next;
@@ -579,8 +582,6 @@ expand_deps (struct file *f)
d1->file = lookup_file (d1->name);
if (d1->file == 0)
d1->file = enter_file (d1->name);
- else
- free (d1->name);
d1->name = 0;
d1->staticpattern = 0;
d1->need_2nd_expansion = 0;
@@ -635,27 +636,25 @@ snap_deps (void)
struct file **file_slot;
struct file **file_end;
- /* Perform second expansion and enter each dependency
- name as a file. */
+ /* Perform second expansion and enter each dependency name as a file. */
- /* Expand .SUFFIXES first; it's dependencies are used for
- $$* calculation. */
+ /* Expand .SUFFIXES first; it's dependencies are used for $$* calculation. */
for (f = lookup_file (".SUFFIXES"); f != 0; f = f->prev)
expand_deps (f);
- /* We must use hash_dump (), because within this loop
- we might add new files to the table, possibly causing
- an in-situ table expansion. */
+ /* For every target that's not .SUFFIXES, expand its dependencies.
+ We must use hash_dump (), because within this loop we might add new files
+ to the table, possibly causing an in-situ table expansion. */
file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
file_end = file_slot_0 + files.ht_fill;
for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
for (f = *file_slot; f != 0; f = f->prev)
- {
- if (strcmp (f->name, ".SUFFIXES") != 0)
- expand_deps (f);
- }
+ if (strcmp (f->name, ".SUFFIXES") != 0)
+ expand_deps (f);
free (file_slot_0);
+ /* Now manage all the special targets. */
+
for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev)
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
@@ -678,35 +677,26 @@ snap_deps (void)
}
for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
- {
- /* .INTERMEDIATE with deps listed
- marks those deps as intermediate files. */
- for (d = f->deps; d != 0; d = d->next)
- for (f2 = d->file; f2 != 0; f2 = f2->prev)
- f2->intermediate = 1;
- /* .INTERMEDIATE with no deps does nothing.
- Marking all files as intermediates is useless
- since the goal targets would be deleted after they are built. */
- }
+ /* Mark .INTERMEDIATE deps as intermediate files. */
+ for (d = f->deps; d != 0; d = d->next)
+ for (f2 = d->file; f2 != 0; f2 = f2->prev)
+ f2->intermediate = 1;
+ /* .INTERMEDIATE with no deps does nothing.
+ Marking all files as intermediates is useless since the goal targets
+ would be deleted after they are built. */
for (f = lookup_file (".SECONDARY"); f != 0; f = f->prev)
- {
- /* .SECONDARY with deps listed
- marks those deps as intermediate files
- in that they don't get rebuilt if not actually needed;
- but unlike real intermediate files,
- these are not deleted after make finishes. */
- if (f->deps)
- for (d = f->deps; d != 0; d = d->next)
- for (f2 = d->file; f2 != 0; f2 = f2->prev)
- f2->intermediate = f2->secondary = 1;
- /* .SECONDARY with no deps listed marks *all* files that way. */
- else
- {
- all_secondary = 1;
- hash_map (&files, set_intermediate);
- }
- }
+ /* Mark .SECONDARY deps as both intermediate and secondary. */
+ if (f->deps)
+ for (d = f->deps; d != 0; d = d->next)
+ for (f2 = d->file; f2 != 0; f2 = f2->prev)
+ f2->intermediate = f2->secondary = 1;
+ /* .SECONDARY with no deps listed marks *all* files that way. */
+ else
+ {
+ all_secondary = 1;
+ hash_map (&files, set_intermediate);
+ }
f = lookup_file (".EXPORT_ALL_VARIABLES");
if (f != 0 && f->is_target)
@@ -853,11 +843,10 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
sprintf (p, "%lu", (unsigned long) t);
p += strlen (p);
- /* Append nanoseconds as a fraction, but remove trailing zeros.
- We don't know the actual timestamp resolution, since clock_getres
- applies only to local times, whereas this timestamp might come
- from a remote filesystem. So removing trailing zeros is the
- best guess that we can do. */
+ /* Append nanoseconds as a fraction, but remove trailing zeros. We don't
+ know the actual timestamp resolution, since clock_getres applies only to
+ local times, whereas this timestamp might come from a remote filesystem.
+ So removing trailing zeros is the best guess that we can do. */
sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts));
p += strlen (p) - 1;
while (*p == '0')
@@ -872,7 +861,7 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
static void
print_file (const void *item)
{
- struct file *f = (struct file *) item;
+ const struct file *f = item;
struct dep *d;
struct dep *ood = 0;
@@ -993,6 +982,39 @@ print_file_data_base (void)
fputs (_("\n# files hash-table stats:\n# "), stdout);
hash_print_stats (&files, stdout);
}
+
+/* Verify the integrity of the data base of files. */
+
+#define VERIFY_CACHED(_p,_n) \
+ do{\
+ if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \
+ printf ("%s: Field %s not cached: %s\n", _p->name, # _n, _p->_n); \
+ }while(0)
+
+static void
+verify_file (const void *item)
+{
+ const struct file *f = item;
+ const struct dep *d;
+
+ VERIFY_CACHED (f, name);
+ VERIFY_CACHED (f, hname);
+ VERIFY_CACHED (f, vpath);
+ VERIFY_CACHED (f, stem);
+
+ /* Check the deps. */
+ for (d = f->deps; d != 0; d = d->next)
+ {
+ VERIFY_CACHED (d, name);
+ VERIFY_CACHED (d, stem);
+ }
+}
+
+void
+verify_file_data_base (void)
+{
+ hash_map (&files, verify_file);
+}
#define EXPANSION_INCREMENT(_l) ((((_l) / 500) + 1) * 500)
diff --git a/filedef.h b/filedef.h
index b5469a2..0af72f5 100644
--- a/filedef.h
+++ b/filedef.h
@@ -25,14 +25,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
struct file
{
- char *name;
- char *hname; /* Hashed filename */
- char *vpath; /* VPATH/vpath pathname */
+ const char *name;
+ const char *hname; /* Hashed filename */
+ const char *vpath; /* VPATH/vpath pathname */
struct dep *deps; /* all dependencies, including duplicates */
struct commands *cmds; /* Commands to execute for this target. */
int command_flags; /* Flags OR'd in for cmds; see commands.h. */
- char *stem; /* Implicit stem, if an implicit
- rule has been used */
+ const char *stem; /* Implicit stem, if an implicit
+ rule has been used */
struct dep *also_make; /* Targets that are made by making this. */
FILE_TIMESTAMP last_mtime; /* File's modtime, if already known. */
FILE_TIMESTAMP mtime_before_update; /* File's modtime before any updating
@@ -101,13 +101,13 @@ extern struct file *default_goal_file, *suffix_file, *default_file;
extern char **default_goal_name;
-struct file *lookup_file (char *name);
-struct file *enter_file (char *name);
+struct file *lookup_file (const char *name);
+struct file *enter_file (const char *name);
struct dep *parse_prereqs (char *prereqs);
void remove_intermediates (int sig);
void snap_deps (void);
-void rename_file (struct file *file, char *name);
-void rehash_file (struct file *file, char *name);
+void rename_file (struct file *file, const char *name);
+void rehash_file (struct file *file, const char *name);
void set_command_state (struct file *file, enum cmd_state state);
void notice_finished_file (struct file *file);
void init_hash_files (void);
diff --git a/function.c b/function.c
index 1dda6d8..d6818c0 100644
--- a/function.c
+++ b/function.c
@@ -74,11 +74,11 @@ static struct hash_table function_table;
whitespace-delimited words. */
char *
-subst_expand (char *o, char *text, char *subst, char *replace,
+subst_expand (char *o, const char *text, const char *subst, const char *replace,
unsigned int slen, unsigned int rlen, int by_word)
{
- char *t = text;
- char *p;
+ const char *t = text;
+ const char *p;
if (slen == 0 && !by_word)
{
@@ -123,10 +123,7 @@ subst_expand (char *o, char *text, char *subst, char *replace,
o = variable_buffer_output (o, replace, rlen);
/* Advance T past the string to be replaced. */
- {
- char *nt = p + slen;
- t = nt;
- }
+ t = p + slen;
} while (*t != '\0');
return o;
@@ -144,24 +141,16 @@ subst_expand (char *o, char *text, char *subst, char *replace,
*/
char *
-patsubst_expand (char *o, char *text, char *pattern, char *replace,
- char *pattern_percent, char *replace_percent)
+patsubst_expand_pat (char *o, const char *text,
+ const char *pattern, const char *replace,
+ const char *pattern_percent, const char *replace_percent)
{
unsigned int pattern_prepercent_len, pattern_postpercent_len;
unsigned int replace_prepercent_len, replace_postpercent_len;
- char *t;
+ const char *t;
unsigned int len;
int doneany = 0;
- /* We call find_percent on REPLACE before checking PATTERN so that REPLACE
- will be collapsed before we call subst_expand if PATTERN has no %. */
- if (!replace_percent)
- {
- replace_percent = find_percent (replace);
- if (replace_percent)
- ++replace_percent;
- }
-
/* Record the length of REPLACE before and after the % so we don't have to
compute these lengths more than once. */
if (replace_percent)
@@ -176,12 +165,6 @@ patsubst_expand (char *o, char *text, char *pattern, char *replace,
}
if (!pattern_percent)
- {
- pattern_percent = find_percent (pattern);
- if (pattern_percent)
- ++pattern_percent;
- }
- if (!pattern_percent)
/* With no % in the pattern, this is just a simple substitution. */
return subst_expand (o, text, pattern, replace,
strlen (pattern), strlen (replace), 1);
@@ -251,6 +234,32 @@ patsubst_expand (char *o, char *text, char *pattern, char *replace,
return o;
}
+
+/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
+ and replacing strings matching PATTERN with REPLACE.
+ If PATTERN_PERCENT is not nil, PATTERN has already been
+ run through find_percent, and PATTERN_PERCENT is the result.
+ If REPLACE_PERCENT is not nil, REPLACE has already been
+ run through find_percent, and REPLACE_PERCENT is the result.
+ Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
+ character _AFTER_ the %, not to the % itself.
+*/
+
+char *
+patsubst_expand (char *o, const char *text, char *pattern, char *replace)
+{
+ const char *pattern_percent = find_percent (pattern);
+ const char *replace_percent = find_percent (replace);
+
+ /* If there's a percent in the pattern or replacement skip it. */
+ if (replace_percent)
+ ++replace_percent;
+ if (pattern_percent)
+ ++pattern_percent;
+
+ return patsubst_expand_pat (o, text, pattern, replace,
+ pattern_percent, replace_percent);
+}
/* Look up a function by name. */
@@ -343,8 +352,8 @@ string_glob (char *line)
{
static char *result = 0;
static unsigned int length;
- register struct nameseq *chain;
- register unsigned int idx;
+ struct nameseq *chain;
+ unsigned int idx;
chain = multi_glob (parse_file_seq
(&line, '\0', sizeof (struct nameseq),
@@ -363,7 +372,7 @@ string_glob (char *line)
idx = 0;
while (chain != 0)
{
- register char *name = chain->name;
+ const char *name = chain->name;
unsigned int len = strlen (name);
struct nameseq *next = chain->next;
@@ -383,8 +392,6 @@ string_glob (char *line)
idx += len;
result[idx++] = ' ';
}
-
- free (name);
}
/* Kill the last space and terminate the string. */
@@ -403,7 +410,7 @@ string_glob (char *line)
static char *
func_patsubst (char *o, char **argv, const char *funcname UNUSED)
{
- o = patsubst_expand (o, argv[2], argv[0], argv[1], (char *) 0, (char *) 0);
+ o = patsubst_expand (o, argv[2], argv[0], argv[1]);
return o;
}
@@ -417,10 +424,10 @@ func_join (char *o, char **argv, const char *funcname UNUSED)
by the corresponding word of the second argument.
If the two arguments have a different number of words,
the excess words are just output separated by blanks. */
- register char *tp;
- register char *pp;
- char *list1_iterator = argv[0];
- char *list2_iterator = argv[1];
+ const char *tp;
+ const char *pp;
+ const char *list1_iterator = argv[0];
+ const char *list2_iterator = argv[1];
do
{
unsigned int len1, len2;
@@ -452,7 +459,7 @@ static char *
func_origin (char *o, char **argv, const char *funcname UNUSED)
{
/* Expand the argument. */
- register struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
+ struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
if (v == 0)
o = variable_buffer_output (o, "undefined", 9);
else
@@ -491,7 +498,7 @@ func_origin (char *o, char **argv, const char *funcname UNUSED)
static char *
func_flavor (char *o, char **argv, const char *funcname UNUSED)
{
- register struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
+ struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
if (v == 0)
o = variable_buffer_output (o, "undefined", 9);
@@ -519,8 +526,8 @@ static char *
func_notdir_suffix (char *o, char **argv, const char *funcname)
{
/* Expand the argument. */
- char *list_iterator = argv[0];
- char *p2 =0;
+ const char *list_iterator = argv[0];
+ const char *p2;
int doneany =0;
unsigned int len=0;
@@ -528,7 +535,7 @@ func_notdir_suffix (char *o, char **argv, const char *funcname)
int is_notdir = !is_suffix;
while ((p2 = find_next_token (&list_iterator, &len)) != 0)
{
- char *p = p2 + len;
+ const char *p = p2 + len;
while (p >= p2 && (!is_suffix || *p != '.'))
@@ -563,13 +570,12 @@ func_notdir_suffix (char *o, char **argv, const char *funcname)
doneany = 1;
}
}
+
if (doneany)
/* Kill last space. */
--o;
-
return o;
-
}
@@ -577,68 +583,68 @@ static char *
func_basename_dir (char *o, char **argv, const char *funcname)
{
/* Expand the argument. */
- char *p3 = argv[0];
- char *p2=0;
+ const char *p3 = argv[0];
+ const char *p2;
int doneany=0;
unsigned int len=0;
- char *p=0;
+
int is_basename= streq (funcname, "basename");
int is_dir= !is_basename;
while ((p2 = find_next_token (&p3, &len)) != 0)
- {
- p = p2 + len;
- while (p >= p2 && (!is_basename || *p != '.'))
- {
- if (IS_PATHSEP (*p))
- break;
- --p;
- }
+ {
+ const char *p = p2 + len;
+ while (p >= p2 && (!is_basename || *p != '.'))
+ {
+ if (IS_PATHSEP (*p))
+ break;
+ --p;
+ }
- if (p >= p2 && (is_dir))
- o = variable_buffer_output (o, p2, ++p - p2);
- else if (p >= p2 && (*p == '.'))
- o = variable_buffer_output (o, p2, p - p2);
+ if (p >= p2 && (is_dir))
+ o = variable_buffer_output (o, p2, ++p - p2);
+ else if (p >= p2 && (*p == '.'))
+ o = variable_buffer_output (o, p2, p - p2);
#ifdef HAVE_DOS_PATHS
- /* Handle the "d:foobar" case */
- else if (p2[0] && p2[1] == ':' && is_dir)
- o = variable_buffer_output (o, p2, 2);
+ /* Handle the "d:foobar" case */
+ else if (p2[0] && p2[1] == ':' && is_dir)
+ o = variable_buffer_output (o, p2, 2);
#endif
- else if (is_dir)
+ else if (is_dir)
#ifdef VMS
- o = variable_buffer_output (o, "[]", 2);
+ o = variable_buffer_output (o, "[]", 2);
#else
#ifndef _AMIGA
- o = variable_buffer_output (o, "./", 2);
+ o = variable_buffer_output (o, "./", 2);
#else
- ; /* Just a nop... */
+ ; /* Just a nop... */
#endif /* AMIGA */
#endif /* !VMS */
- else
- /* The entire name is the basename. */
- o = variable_buffer_output (o, p2, len);
+ else
+ /* The entire name is the basename. */
+ o = variable_buffer_output (o, p2, len);
- o = variable_buffer_output (o, " ", 1);
- doneany = 1;
- }
- if (doneany)
- /* Kill last space. */
- --o;
+ o = variable_buffer_output (o, " ", 1);
+ doneany = 1;
+ }
+ if (doneany)
+ /* Kill last space. */
+ --o;
- return o;
+ return o;
}
static char *
func_addsuffix_addprefix (char *o, char **argv, const char *funcname)
{
int fixlen = strlen (argv[0]);
- char *list_iterator = argv[1];
+ const char *list_iterator = argv[1];
int is_addprefix = streq (funcname, "addprefix");
int is_addsuffix = !is_addprefix;
int doneany = 0;
- char *p;
+ const char *p;
unsigned int len;
while ((p = find_next_token (&list_iterator, &len)) != 0)
@@ -673,8 +679,8 @@ static char *
func_firstword (char *o, char **argv, const char *funcname UNUSED)
{
unsigned int i;
- char *words = argv[0]; /* Use a temp variable for find_next_token */
- char *p = find_next_token (&words, &i);
+ const char *words = argv[0]; /* Use a temp variable for find_next_token */
+ const char *p = find_next_token (&words, &i);
if (p != 0)
o = variable_buffer_output (o, p, i);
@@ -686,9 +692,9 @@ static char *
func_lastword (char *o, char **argv, const char *funcname UNUSED)
{
unsigned int i;
- char *words = argv[0]; /* Use a temp variable for find_next_token */
- char *p = 0;
- char *t;
+ const char *words = argv[0]; /* Use a temp variable for find_next_token */
+ const char *p;
+ const char *t;
while ((t = find_next_token (&words, &i)))
p = t;
@@ -703,7 +709,7 @@ static char *
func_words (char *o, char **argv, const char *funcname UNUSED)
{
int i = 0;
- char *word_iterator = argv[0];
+ const char *word_iterator = argv[0];
char buf[20];
while (find_next_token (&word_iterator, (unsigned int *) 0) != 0)
@@ -712,7 +718,6 @@ func_words (char *o, char **argv, const char *funcname UNUSED)
sprintf (buf, "%d", i);
o = variable_buffer_output (o, buf, strlen (buf));
-
return o;
}
@@ -751,19 +756,18 @@ check_numeric (const char *s, const char *msg)
static char *
func_word (char *o, char **argv, const char *funcname UNUSED)
{
- char *end_p=0;
- int i=0;
- char *p=0;
+ const char *end_p;
+ const char *p;
+ int i;
/* Check the first argument. */
check_numeric (argv[0], _("non-numeric first argument to `word' function"));
- i = atoi (argv[0]);
+ i = atoi (argv[0]);
if (i == 0)
fatal (*expanding_var,
_("first argument to `word' function must be greater than 0"));
-
end_p = argv[1];
while ((p = find_next_token (&end_p, 0)) != 0)
if (--i == 0)
@@ -795,8 +799,8 @@ func_wordlist (char *o, char **argv, const char *funcname UNUSED)
if (count > 0)
{
- char *p;
- char *end_p = argv[2];
+ const char *p;
+ const char *end_p = argv[2];
/* Find the beginning of the "start"th word. */
while (((p = find_next_token (&end_p, 0)) != 0) && --start)
@@ -816,7 +820,7 @@ func_wordlist (char *o, char **argv, const char *funcname UNUSED)
return o;
}
-static char*
+static char *
func_findstring (char *o, char **argv, const char *funcname UNUSED)
{
/* Find the first occurrence of the first string in the second. */
@@ -832,13 +836,13 @@ func_foreach (char *o, char **argv, const char *funcname UNUSED)
/* expand only the first two. */
char *varname = expand_argument (argv[0], NULL);
char *list = expand_argument (argv[1], NULL);
- char *body = argv[2];
+ const char *body = argv[2];
int doneany = 0;
- char *list_iterator = list;
- char *p;
+ const char *list_iterator = list;
+ const char *p;
unsigned int len;
- register struct variable *var;
+ struct variable *var;
push_new_variable_scope ();
var = define_variable (varname, strlen (varname), "", o_automatic, 0);
@@ -848,14 +852,8 @@ func_foreach (char *o, char **argv, const char *funcname UNUSED)
{
char *result = 0;
- {
- char save = p[len];
-
- p[len] = '\0';
- free (var->value);
- var->value = xstrdup ((char*) p);
- p[len] = save;
- }
+ free (var->value);
+ var->value = savestring (p, len);
result = allocated_variable_expand (body);
@@ -928,8 +926,8 @@ func_filter_filterout (char *o, char **argv, const char *funcname)
struct hash_table a_word_table;
int is_filter = streq (funcname, "filter");
- char *pat_iterator = argv[0];
- char *word_iterator = argv[1];
+ const char *pat_iterator = argv[0];
+ const char *word_iterator = argv[1];
int literals = 0;
int words = 0;
int hashing = 0;
@@ -985,7 +983,8 @@ func_filter_filterout (char *o, char **argv, const char *funcname)
hashing = (literals >= 2 && (literals * words) >= 10);
if (hashing)
{
- hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2, a_word_hash_cmp);
+ hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2,
+ a_word_hash_cmp);
for (wp = wordhead; wp != 0; wp = wp->next)
{
struct a_word *owp = hash_insert (&a_word_table, wp);
@@ -1009,7 +1008,7 @@ func_filter_filterout (char *o, char **argv, const char *funcname)
struct a_word a_word_key;
a_word_key.str = pp->str;
a_word_key.length = pp->length;
- wp = (struct a_word *) hash_find_item (&a_word_table, &a_word_key);
+ wp = hash_find_item (&a_word_table, &a_word_key);
while (wp)
{
wp->matched |= 1;
@@ -1049,13 +1048,13 @@ func_filter_filterout (char *o, char **argv, const char *funcname)
static char *
func_strip (char *o, char **argv, const char *funcname UNUSED)
{
- char *p = argv[0];
- int doneany =0;
+ const char *p = argv[0];
+ int doneany = 0;
while (*p != '\0')
{
int i=0;
- char *word_start=0;
+ const char *word_start;
while (isspace ((unsigned char)*p))
++p;
@@ -1072,6 +1071,7 @@ func_strip (char *o, char **argv, const char *funcname UNUSED)
if (doneany)
/* Kill the last space. */
--o;
+
return o;
}
@@ -1130,46 +1130,61 @@ func_error (char *o, char **argv, const char *funcname)
static char *
func_sort (char *o, char **argv, const char *funcname UNUSED)
{
- char **words = 0;
- int nwords = 0;
- register int wordi = 0;
-
- /* Chop ARGV[0] into words and put them in WORDS. */
- char *t = argv[0];
+ const char *t;
+ char **words;
+ int wordi;
char *p;
unsigned int len;
int i;
- while ((p = find_next_token (&t, &len)) != 0)
+ /* Find the maximum number of words we'll have. */
+ t = argv[0];
+ wordi = 1;
+ while (*t != '\0')
{
- if (wordi >= nwords - 1)
- {
- nwords = (2 * nwords) + 5;
- words = xrealloc (words, nwords * sizeof (char *));
- }
- words[wordi++] = savestring (p, len);
+ char c = *(t++);
+
+ if (! isspace ((unsigned char)c))
+ continue;
+
+ ++wordi;
+
+ while (isspace ((unsigned char)*t))
+ ++t;
}
- if (!wordi)
- return o;
+ words = xmalloc (wordi * sizeof (char *));
- /* Now sort the list of words. */
- qsort (words, wordi, sizeof (char *), alpha_compare);
+ /* Now assign pointers to each string in the array. */
+ t = argv[0];
+ wordi = 0;
+ while ((p = find_next_token (&t, &len)) != 0)
+ {
+ ++t;
+ p[len] = '\0';
+ words[wordi++] = p;
+ }
- /* Now write the sorted list. */
- for (i = 0; i < wordi; ++i)
+ if (wordi)
{
- len = strlen (words[i]);
- if (i == wordi - 1 || strlen (words[i + 1]) != len
- || strcmp (words[i], words[i + 1]))
+ /* Now sort the list of words. */
+ qsort (words, wordi, sizeof (char *), alpha_compare);
+
+ /* Now write the sorted list, uniquified. */
+ for (i = 0; i < wordi; ++i)
{
- o = variable_buffer_output (o, words[i], len);
- o = variable_buffer_output (o, " ", 1);
+ len = strlen (words[i]);
+ if (i == wordi - 1 || strlen (words[i + 1]) != len
+ || strcmp (words[i], words[i + 1]))
+ {
+ o = variable_buffer_output (o, words[i], len);
+ o = variable_buffer_output (o, " ", 1);
+ }
}
- free (words[i]);
+
+ /* Kill the last space. */
+ --o;
}
- /* Kill the last space. */
- --o;
free (words);
@@ -1215,11 +1230,9 @@ func_if (char *o, char **argv, const char *funcname UNUSED)
argv += 1 + !result;
- if (argv[0])
+ if (*argv)
{
- char *expansion;
-
- expansion = expand_argument (argv[0], NULL);
+ char *expansion = expand_argument (*argv, NULL);
o = variable_buffer_output (o, expansion, strlen (expansion));
@@ -1336,7 +1349,6 @@ func_and (char *o, char **argv, const char *funcname UNUSED)
static char *
func_wildcard (char *o, char **argv, const char *funcname UNUSED)
{
-
#ifdef _AMIGA
o = wildcard_expansion (argv[0], o);
#else
@@ -1576,22 +1588,20 @@ msdos_openpipe (int* pipedes, int *pidp, char *text)
static char *
func_shell (char *o, char **argv, const char *funcname UNUSED)
{
- char* batch_filename = NULL;
+ char *batch_filename = NULL;
#ifdef __MSDOS__
FILE *fpipe;
#endif
char **command_argv;
- char *error_prefix;
+ const char *error_prefix;
char **envp;
int pipedes[2];
int pid;
#ifndef __MSDOS__
/* Construct the argument list. */
- command_argv = construct_command_argv (argv[0],
- (char **) NULL, (struct file *) 0,
- &batch_filename);
+ command_argv = construct_command_argv (argv[0], NULL, NULL, &batch_filename);
if (command_argv == 0)
return o;
#endif
@@ -1603,6 +1613,8 @@ func_shell (char *o, char **argv, const char *funcname UNUSED)
var was not explicitly exported, but just appeared in the
calling environment.
+ See Savannah bug #10593.
+
envp = target_environment (NILF);
*/
@@ -1611,35 +1623,31 @@ func_shell (char *o, char **argv, const char *funcname UNUSED)
/* For error messages. */
if (reading_file && reading_file->filenm)
{
- error_prefix = alloca (strlen (reading_file->filenm)+11+4);
- sprintf (error_prefix,
- "%s:%lu: ", reading_file->filenm, reading_file->lineno);
+ char *p = alloca (strlen (reading_file->filenm)+11+4);
+ sprintf (p, "%s:%lu: ", reading_file->filenm, reading_file->lineno);
+ error_prefix = p;
}
else
error_prefix = "";
-#ifdef WINDOWS32
-
- windows32_openpipe (pipedes, &pid, command_argv, envp);
-
- if (pipedes[0] < 0) {
- /* open of the pipe failed, mark as failed execution */
- shell_function_completed = -1;
-
- return o;
- } else
-
-#elif defined(__MSDOS__)
-
+#if defined(__MSDOS__)
fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
if (pipedes[0] < 0)
{
perror_with_name (error_prefix, "pipe");
return o;
}
+#elif defined(WINDOWS32)
+ windows32_openpipe (pipedes, &pid, command_argv, envp);
+ if (pipedes[0] < 0)
+ {
+ /* open of the pipe failed, mark as failed execution */
+ shell_function_completed = -1;
+ return o;
+ }
+ else
#else
-
if (pipe (pipedes) < 0)
{
perror_with_name (error_prefix, "pipe");
@@ -1647,7 +1655,6 @@ func_shell (char *o, char **argv, const char *funcname UNUSED)
}
# ifdef __EMX__
-
/* close some handles that are unnecessary for the child process */
CLOSE_ON_EXEC(pipedes[1]);
CLOSE_ON_EXEC(pipedes[0]);
@@ -1655,18 +1662,14 @@ func_shell (char *o, char **argv, const char *funcname UNUSED)
pid = child_execute_job (0, pipedes[1], command_argv, envp);
if (pid < 0)
perror_with_name (error_prefix, "spawn");
-
# else /* ! __EMX__ */
-
pid = vfork ();
if (pid < 0)
perror_with_name (error_prefix, "fork");
else if (pid == 0)
child_execute_job (0, pipedes[1], command_argv, envp);
else
-
# endif
-
#endif
{
/* We are the parent. */
@@ -1863,7 +1866,7 @@ func_eq (char *o, char **argv, char *funcname)
static char *
func_not (char *o, char **argv, char *funcname)
{
- char *s = argv[0];
+ const char *s = argv[0];
int result = 0;
while (isspace ((unsigned char)*s))
s++;
@@ -1956,8 +1959,8 @@ static char *
func_realpath (char *o, char **argv, const char *funcname UNUSED)
{
/* Expand the argument. */
- char *p = argv[0];
- char *path = 0;
+ const char *p = argv[0];
+ const char *path = 0;
int doneany = 0;
unsigned int len = 0;
PATH_VAR (in);
@@ -1970,14 +1973,13 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED)
strncpy (in, path, len);
in[len] = '\0';
- if
- (
+ if (
#ifdef HAVE_REALPATH
- realpath (in, out)
+ realpath (in, out)
#else
- abspath (in, out)
+ abspath (in, out)
#endif
- )
+ )
{
o = variable_buffer_output (o, out, strlen (out));
o = variable_buffer_output (o, " ", 1);
@@ -1990,15 +1992,15 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED)
if (doneany)
--o;
- return o;
+ return o;
}
static char *
func_abspath (char *o, char **argv, const char *funcname UNUSED)
{
/* Expand the argument. */
- char *p = argv[0];
- char *path = 0;
+ const char *p = argv[0];
+ const char *path = 0;
int doneany = 0;
unsigned int len = 0;
PATH_VAR (in);
@@ -2024,7 +2026,7 @@ func_abspath (char *o, char **argv, const char *funcname UNUSED)
if (doneany)
--o;
- return o;
+ return o;
}
/* Lookup table for builtin functions.
@@ -2268,13 +2270,11 @@ func_call (char *o, char **argv, const char *funcname UNUSED)
/* Are we invoking a builtin function? */
entry_p = lookup_function (fname);
-
if (entry_p)
{
/* How many arguments do we have? */
for (i=0; argv[i+1]; ++i)
;
-
return expand_builtin_function (o, i, argv+1, entry_p);
}
diff --git a/implicit.c b/implicit.c
index d239952..7255bc7 100644
--- a/implicit.c
+++ b/implicit.c
@@ -68,9 +68,9 @@ try_implicit_rule (struct file *file, unsigned int depth)
struct idep
{
struct idep *next; /* struct dep -compatible interface */
- char *name; /* name of the prerequisite */
+ const char *name; /* name of the prerequisite */
struct file *intermediate_file; /* intermediate file, 0 otherwise */
- char *intermediate_pattern; /* pattern for intermediate file */
+ const char *intermediate_pattern; /* pattern for intermediate file */
unsigned char had_stem; /* had % substituted with stem */
unsigned char ignore_mtime; /* ignore_mtime flag */
};
@@ -83,18 +83,6 @@ free_idep_chain (struct idep *p)
for (; p != 0; p = n)
{
n = p->next;
-
- if (p->name)
- {
- struct file *f = p->intermediate_file;
-
- if (f != 0
- && (f->stem < f->name || f->stem > f->name + strlen (f->name)))
- free (f->stem);
-
- free (p->name);
- }
-
free (p);
}
}
@@ -105,9 +93,9 @@ free_idep_chain (struct idep *p)
length of the word. */
static char *
-get_next_word (char *buffer, unsigned int *length)
+get_next_word (const char *buffer, unsigned int *length)
{
- char *p = buffer, *beg;
+ const char *p = buffer, *beg;
char c;
/* Skip any leading whitespace. */
@@ -178,7 +166,7 @@ get_next_word (char *buffer, unsigned int *length)
if (length)
*length = p - beg;
- return beg;
+ return (char *)beg;
}
/* Search the pattern rules for a rule with an existing dependency to make
@@ -200,7 +188,7 @@ pattern_search (struct file *file, int archive,
unsigned int depth, unsigned int recursions)
{
/* Filename we are searching for a rule for. */
- char *filename = archive ? strchr (file->name, '(') : file->name;
+ const char *filename = archive ? strchr (file->name, '(') : file->name;
/* Length of FILENAME. */
unsigned int namelen = strlen (filename);
@@ -225,7 +213,7 @@ pattern_search (struct file *file, int archive,
char *depname = alloca (namelen + max_pattern_dep_length);
/* The start and length of the stem of FILENAME for the current rule. */
- char *stem = 0;
+ const char *stem = 0;
unsigned int stemlen = 0;
unsigned int fullstemlen = 0;
@@ -258,8 +246,6 @@ pattern_search (struct file *file, int archive,
struct rule *rule;
struct dep *dep, *expl_d;
- char *p, *vname;
-
struct idep *d;
struct idep **id_ptr;
struct dep **d_ptr;
@@ -318,10 +304,10 @@ pattern_search (struct file *file, int archive,
continue;
}
- for (ti = 0; rule->targets[ti] != 0; ++ti)
+ for (ti = 0; ti < rule->num; ++ti)
{
- char *target = rule->targets[ti];
- char *suffix = rule->suffixes[ti];
+ const char *target = rule->targets[ti];
+ const char *suffix = rule->suffixes[ti];
int check_lastslash;
/* Rules that can match any filename and are not terminal
@@ -416,11 +402,12 @@ pattern_search (struct file *file, int archive,
if (!tryrules[ri]->terminal)
{
unsigned int j;
- for (j = 0; tryrules[ri]->targets[j] != 0; ++j)
+ for (j = 0; j < tryrules[ri]->num; ++j)
if (tryrules[ri]->targets[j][1] == '\0')
- break;
- if (tryrules[ri]->targets[j] != 0)
- tryrules[ri] = 0;
+ {
+ tryrules[ri] = 0;
+ break;
+ }
}
/* We are going to do second expansion so initialize file variables
@@ -486,6 +473,7 @@ pattern_search (struct file *file, int archive,
for (dep = rule->deps; dep != 0; dep = dep->next)
{
unsigned int len;
+ char *p;
char *p2;
unsigned int order_only = 0; /* Set if '|' was seen. */
@@ -614,14 +602,10 @@ pattern_search (struct file *file, int archive,
if (add_dir)
{
- char *n = d->name;
-
- d->name = xmalloc (strlen (n) + l + 1);
-
- memcpy (d->name, filename, l);
- memcpy (d->name + l, n, strlen (n) + 1);
-
- free (n);
+ char *n = alloca (strlen (d->name) + l + 1);
+ memcpy (n, filename, l);
+ memcpy (n+l, d->name, strlen (d->name) + 1);
+ d->name = strcache_add (n);
}
if (had_stem)
@@ -653,7 +637,7 @@ pattern_search (struct file *file, int archive,
for (d = deps; d != 0; d = d->next)
{
- char *name = d->name;
+ const char *name = d->name;
if (file_impossible_p (name))
{
@@ -701,17 +685,16 @@ pattern_search (struct file *file, int archive,
/* This code, given FILENAME = "lib/foo.o", dependency name
"lib/foo.c", and VPATH=src, searches for "src/lib/foo.c". */
- vname = name;
- if (vpath_search (&vname, (FILE_TIMESTAMP *) 0))
- {
- DBS (DB_IMPLICIT,
- (_("Found prerequisite `%s' as VPATH `%s'\n"),
- name,
- vname));
-
- free (vname);
- continue;
- }
+ {
+ const char *vname = vpath_search (name, 0);
+ if (vname)
+ {
+ DBS (DB_IMPLICIT,
+ (_("Found prerequisite `%s' as VPATH `%s'\n"),
+ name, vname));
+ continue;
+ }
+ }
/* We could not find the file in any place we should look. Try
@@ -734,10 +717,9 @@ pattern_search (struct file *file, int archive,
depth + 1,
recursions + 1))
{
- d->intermediate_file = intermediate_file;
d->intermediate_pattern = intermediate_file->name;
-
- intermediate_file->name = xstrdup (name);
+ intermediate_file->name = strcache_add (name);
+ d->intermediate_file = intermediate_file;
intermediate_file = 0;
continue;
@@ -819,7 +801,7 @@ pattern_search (struct file *file, int archive,
for (d = deps; d != 0; d = d->next)
{
- register char *s;
+ const char *s;
if (d->intermediate_file != 0)
{
@@ -839,7 +821,7 @@ pattern_search (struct file *file, int archive,
if (f != 0)
f->precious = 1;
else
- f = enter_file (imf->name);
+ f = enter_file (strcache_add (imf->name));
f->deps = imf->deps;
f->cmds = imf->cmds;
@@ -859,9 +841,6 @@ pattern_search (struct file *file, int archive,
for (dep = f->deps; dep != 0; dep = dep->next)
{
dep->file = enter_file (dep->name);
- /* enter_file uses dep->name _if_ we created a new file. */
- if (dep->name != dep->file->name)
- free (dep->name);
dep->name = 0;
dep->file->tried_implicit |= dep->changed;
}
@@ -875,17 +854,10 @@ pattern_search (struct file *file, int archive,
{
dep->file = lookup_file (s);
if (dep->file == 0)
- /* enter_file consumes S's storage. */
dep->file = enter_file (s);
- else
- /* A copy of S is already allocated in DEP->file->name.
- So we can free S. */
- free (s);
}
else
- {
- dep->name = s;
- }
+ dep->name = s;
if (d->intermediate_file == 0 && tryrules[foundrule]->terminal)
{
@@ -910,20 +882,22 @@ pattern_search (struct file *file, int archive,
{
/* Always allocate new storage, since STEM might be
on the stack for an intermediate file. */
- file->stem = savestring (stem, stemlen);
+ file->stem = strcache_add_len (stem, stemlen);
fullstemlen = stemlen;
}
else
{
int dirlen = (lastslash + 1) - filename;
+ char *sp;
/* We want to prepend the directory from
the original FILENAME onto the stem. */
fullstemlen = dirlen + stemlen;
- file->stem = xmalloc (fullstemlen + 1);
- memcpy (file->stem, filename, dirlen);
- memcpy (file->stem + dirlen, stem, stemlen);
- file->stem[fullstemlen] = '\0';
+ sp = alloca (fullstemlen + 1);
+ memcpy (sp, filename, dirlen);
+ memcpy (sp + dirlen, stem, stemlen);
+ sp[fullstemlen] = '\0';
+ file->stem = strcache_add (sp);
}
file->cmds = rule->cmds;
@@ -939,15 +913,15 @@ pattern_search (struct file *file, int archive,
/* If this rule builds other targets, too, put the others into FILE's
`also_make' member. */
- if (rule->targets[1] != 0)
- for (ri = 0; rule->targets[ri] != 0; ++ri)
+ if (rule->num > 1)
+ for (ri = 0; ri < rule->num; ++ri)
if (ri != matches[foundrule])
{
+ char *p = alloca (rule->lens[ri] + fullstemlen + 1);
struct file *f;
struct dep *new = alloc_dep ();
/* GKM FIMXE: handle '|' here too */
- new->name = p = xmalloc (rule->lens[ri] + fullstemlen + 1);
memcpy (p, rule->targets[ri],
rule->suffixes[ri] - rule->targets[ri] - 1);
p += rule->suffixes[ri] - rule->targets[ri] - 1;
@@ -955,6 +929,7 @@ pattern_search (struct file *file, int archive,
p += fullstemlen;
memcpy (p, rule->suffixes[ri],
rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1);
+ new->name = strcache_add (p);
new->file = enter_file (new->name);
new->next = file->also_make;
diff --git a/job.c b/job.c
index 347c8c6..a8c6754 100644
--- a/job.c
+++ b/job.c
@@ -374,8 +374,8 @@ _is_unixy_shell (const char *path)
Append "(ignored)" if IGNORED is nonzero. */
static void
-child_error (char *target_name, int exit_code, int exit_sig, int coredump,
- int ignored)
+child_error (const char *target_name,
+ int exit_code, int exit_sig, int coredump, int ignored)
{
if (ignored && silent_flag)
return;
diff --git a/main.c b/main.c
index ba7f87d..ea9a5a0 100644
--- a/main.c
+++ b/main.c
@@ -67,6 +67,8 @@ void print_rule_data_base (void);
void print_file_data_base (void);
void print_vpath_data_base (void);
+void verify_file_data_base (void);
+
#if defined HAVE_WAITPID || defined HAVE_WAIT3
# define HAVE_WAIT_NOHANG
#endif
@@ -87,7 +89,7 @@ static void print_version (void);
static void decode_switches (int argc, char **argv, int env);
static void decode_env_switches (char *envar, unsigned int len);
static void define_makeflags (int all, int makefile);
-static char *quote_for_env (char *out, char *in);
+static char *quote_for_env (char *out, const char *in);
static void initialize_global_hash_tables (void);
@@ -102,6 +104,7 @@ struct command_switch
flag, /* Turn int flag on. */
flag_off, /* Turn int flag off. */
string, /* One string per switch. */
+ filename, /* A string containing a file name. */
positive_int, /* A positive integer. */
floating, /* A floating-point number (double). */
ignore /* Ignored. */
@@ -128,7 +131,7 @@ struct command_switch
struct stringlist
{
- char **list; /* Nil-terminated list of strings. */
+ const char **list; /* Nil-terminated list of strings. */
unsigned int idx; /* Index into above. */
unsigned int max; /* Number of pointers allocated. */
};
@@ -371,17 +374,17 @@ static const struct command_switch switches[] =
{
{ 'b', ignore, 0, 0, 0, 0, 0, 0, 0 },
{ 'B', flag, &always_make_set, 1, 1, 0, 0, 0, "always-make" },
- { 'C', string, &directories, 0, 0, 0, 0, 0, "directory" },
+ { 'C', filename, &directories, 0, 0, 0, 0, 0, "directory" },
{ 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0 },
{ CHAR_MAX+1, string, &db_flags, 1, 1, 0, "basic", 0, "debug" },
#ifdef WINDOWS32
{ 'D', flag, &suspend_flag, 1, 1, 0, 0, 0, "suspend-for-debug" },
#endif
{ 'e', flag, &env_overrides, 1, 1, 0, 0, 0, "environment-overrides", },
- { 'f', string, &makefiles, 0, 0, 0, 0, 0, "file" },
+ { 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file" },
{ 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, "help" },
{ 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, "ignore-errors" },
- { 'I', string, &include_directories, 1, 1, 0, 0, 0,
+ { 'I', filename, &include_directories, 1, 1, 0, 0, 0,
"include-dir" },
{ 'j', positive_int, &job_slots, 1, 1, 0, &inf_jobs, &default_job_slots,
"jobs" },
@@ -398,7 +401,7 @@ static const struct command_switch switches[] =
{ 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, "check-symlink-times" },
{ 'm', ignore, 0, 0, 0, 0, 0, 0, 0 },
{ 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, "just-print" },
- { 'o', string, &old_files, 0, 0, 0, 0, 0, "old-file" },
+ { 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" },
{ 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, "print-data-base" },
{ 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question" },
{ 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules" },
@@ -414,7 +417,7 @@ static const struct command_switch switches[] =
{ 'w', flag, &print_directory_flag, 1, 1, 0, 0, 0, "print-directory" },
{ CHAR_MAX+4, flag, &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
"no-print-directory" },
- { 'W', string, &new_files, 0, 0, 0, 0, 0, "what-if" },
+ { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" },
{ CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
"warn-undefined-variables" },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
@@ -543,17 +546,20 @@ initialize_global_hash_tables (void)
hash_init_function_table ();
}
-static struct file *
-enter_command_line_file (char *name)
+static const char *
+expand_command_line_file (char *name)
{
+ const char *cp;
+ char *expanded = 0;
+
if (name[0] == '\0')
fatal (NILF, _("empty string invalid as file name"));
if (name[0] == '~')
{
- char *expanded = tilde_expand (name);
+ expanded = tilde_expand (name);
if (expanded != 0)
- name = expanded; /* Memory leak; I don't care. */
+ name = expanded;
}
/* This is also done in parse_file_seq, so this is redundant
@@ -577,7 +583,12 @@ enter_command_line_file (char *name)
name[2] = '\0';
}
- return enter_file (xstrdup (name));
+ cp = strcache_add (name);
+
+ if (expanded)
+ free (expanded);
+
+ return cp;
}
/* Toggle -d on receipt of SIGUSR1. */
@@ -593,7 +604,7 @@ debug_signal_handler (int sig UNUSED)
static void
decode_debug_flags (void)
{
- char **pp;
+ const char **pp;
if (debug_flag)
db_level = DB_ALL;
@@ -728,9 +739,10 @@ handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo )
*/
int
-find_and_set_default_shell (char *token)
+find_and_set_default_shell (const char *token)
{
int sh_found = 0;
+ char *atoken = 0;
char *search_token;
char *tokend;
PATH_VAR(sh_path);
@@ -739,8 +751,7 @@ find_and_set_default_shell (char *token)
if (!token)
search_token = default_shell;
else
- search_token = token;
-
+ atoken = search_token = xstrdup (token);
/* If the user explicitly requests the DOS cmd shell, obey that request.
However, make sure that's what they really want by requiring the value
@@ -766,10 +777,10 @@ find_and_set_default_shell (char *token)
(token == NULL || !strcmp (search_token, default_shell))) {
/* no new information, path already set or known */
sh_found = 1;
- } else if (file_exists_p(search_token)) {
+ } else if (file_exists_p (search_token)) {
/* search token path was found */
- sprintf(sh_path, "%s", search_token);
- default_shell = xstrdup(w32ify(sh_path,0));
+ sprintf (sh_path, "%s", search_token);
+ default_shell = xstrdup (w32ify (sh_path, 0));
DB (DB_VERBOSE,
(_("find_and_set_shell setting default_shell = %s\n"), default_shell));
sh_found = 1;
@@ -782,31 +793,31 @@ find_and_set_default_shell (char *token)
char *ep;
p = v->value;
- ep = strchr(p, PATH_SEPARATOR_CHAR);
+ ep = strchr (p, PATH_SEPARATOR_CHAR);
while (ep && *ep) {
*ep = '\0';
- if (dir_file_exists_p(p, search_token)) {
- sprintf(sh_path, "%s/%s", p, search_token);
- default_shell = xstrdup(w32ify(sh_path,0));
+ if (dir_file_exists_p (p, search_token)) {
+ sprintf (sh_path, "%s/%s", p, search_token);
+ default_shell = xstrdup (w32ify (sh_path, 0));
sh_found = 1;
*ep = PATH_SEPARATOR_CHAR;
/* terminate loop */
- p += strlen(p);
+ p += strlen (p);
} else {
*ep = PATH_SEPARATOR_CHAR;
p = ++ep;
}
- ep = strchr(p, PATH_SEPARATOR_CHAR);
+ ep = strchr (p, PATH_SEPARATOR_CHAR);
}
/* be sure to check last element of Path */
- if (p && *p && dir_file_exists_p(p, search_token)) {
- sprintf(sh_path, "%s/%s", p, search_token);
- default_shell = xstrdup(w32ify(sh_path,0));
+ if (p && *p && dir_file_exists_p (p, search_token)) {
+ sprintf (sh_path, "%s/%s", p, search_token);
+ default_shell = xstrdup (w32ify (sh_path, 0));
sh_found = 1;
}
@@ -819,7 +830,7 @@ find_and_set_default_shell (char *token)
/* naive test */
if (!unixy_shell && sh_found &&
- (strstr(default_shell, "sh") || strstr(default_shell, "SH"))) {
+ (strstr (default_shell, "sh") || strstr (default_shell, "SH"))) {
unixy_shell = 1;
batch_mode_shell = 0;
}
@@ -828,6 +839,9 @@ find_and_set_default_shell (char *token)
batch_mode_shell = 1;
#endif
+ if (atoken)
+ free (atoken);
+
return (sh_found);
}
#endif /* WINDOWS32 */
@@ -1228,7 +1242,7 @@ main (int argc, char **argv, char **envp)
decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
#if 0
/* People write things like:
- MFLAGS="CC=gcc -pipe" "CFLAGS=-g"
+ MFLAGS="CC=gcc -pipe" "CFLAGS=-g"
and we set the -p, -i and -e switches. Doesn't seem quite right. */
decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
#endif
@@ -1296,7 +1310,7 @@ main (int argc, char **argv, char **envp)
&& (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\') != 0)
# endif
)
- argv[0] = concat (current_directory, "/", argv[0]);
+ argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
#else /* !__MSDOS__ */
if (current_directory[0] != '\0'
&& argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0
@@ -1305,7 +1319,7 @@ main (int argc, char **argv, char **envp)
&& strchr (argv[0], '\\') != 0
#endif
)
- argv[0] = concat (current_directory, "/", argv[0]);
+ argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
#endif /* !__MSDOS__ */
#endif /* WINDOWS32 */
#endif
@@ -1370,14 +1384,7 @@ main (int argc, char **argv, char **envp)
unsigned int i;
for (i = 0; directories->list[i] != 0; ++i)
{
- char *dir = directories->list[i];
- char *expanded = 0;
- if (dir[0] == '~')
- {
- expanded = tilde_expand (dir);
- if (expanded != 0)
- dir = expanded;
- }
+ const char *dir = directories->list[i];
#ifdef WINDOWS32
/* WINDOWS32 chdir() doesn't work if the directory has a trailing '/'
But allow -C/ just in case someone wants that. */
@@ -1390,8 +1397,6 @@ main (int argc, char **argv, char **envp)
#endif
if (chdir (dir) < 0)
pfatal_with_name (dir);
- if (expanded)
- free (expanded);
}
}
@@ -1524,11 +1529,11 @@ main (int argc, char **argv, char **envp)
/* Replace the name that read_all_makefiles will
see with the name of the temporary file. */
- makefiles->list[i] = xstrdup (stdin_nm);
+ makefiles->list[i] = strcache_add (stdin_nm);
/* Make sure the temporary file will not be remade. */
{
- struct file *f = enter_file (stdin_nm);
+ struct file *f = enter_file (strcache_add (stdin_nm));
f->updated = 1;
f->update_status = 0;
f->command_state = cs_finished;
@@ -1595,7 +1600,7 @@ main (int argc, char **argv, char **envp)
/* Define the default variables. */
define_default_variables ();
- default_file = enter_file (".DEFAULT");
+ default_file = enter_file (strcache_add (".DEFAULT"));
{
struct variable *v = define_variable (".DEFAULT_GOAL", 13, "", o_file, 0);
@@ -1660,7 +1665,7 @@ main (int argc, char **argv, char **envp)
if (jobserver_fds)
{
- char *cp;
+ const char *cp;
unsigned int ui;
for (ui=1; ui < jobserver_fds->idx; ++ui)
@@ -1719,6 +1724,7 @@ main (int argc, char **argv, char **envp)
if (job_slots > 1)
{
+ char *cp;
char c = '+';
if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0)
@@ -1742,12 +1748,13 @@ main (int argc, char **argv, char **envp)
/* Fill in the jobserver_fds struct for our children. */
+ cp = xmalloc ((sizeof ("1024")*2)+1);
+ sprintf (cp, "%d,%d", job_fds[0], job_fds[1]);
+
jobserver_fds = (struct stringlist *)
xmalloc (sizeof (struct stringlist));
jobserver_fds->list = xmalloc (sizeof (char *));
- jobserver_fds->list[0] = xmalloc ((sizeof ("1024")*2)+1);
-
- sprintf (jobserver_fds->list[0], "%d,%d", job_fds[0], job_fds[1]);
+ jobserver_fds->list[0] = cp;
jobserver_fds->idx = 1;
jobserver_fds->max = 1;
}
@@ -1798,10 +1805,10 @@ main (int argc, char **argv, char **envp)
if (old_files != 0)
{
- char **p;
+ const char **p;
for (p = old_files->list; *p != 0; ++p)
{
- struct file *f = enter_command_line_file (*p);
+ struct file *f = enter_file (*p);
f->last_mtime = f->mtime_before_update = OLD_MTIME;
f->updated = 1;
f->update_status = 0;
@@ -1811,10 +1818,10 @@ main (int argc, char **argv, char **envp)
if (!restarts && new_files != 0)
{
- char **p;
+ const char **p;
for (p = new_files->list; *p != 0; ++p)
{
- struct file *f = enter_command_line_file (*p);
+ struct file *f = enter_file (*p);
f->last_mtime = f->mtime_before_update = NEW_MTIME;
}
}
@@ -2000,9 +2007,10 @@ main (int argc, char **argv, char **envp)
{
char *p = &argv[i][2];
if (*p == '\0')
- argv[++i] = makefiles->list[j];
+ /* This cast is OK since we never modify argv. */
+ argv[++i] = (char *) makefiles->list[j];
else
- argv[i] = concat ("-f", makefiles->list[j], "");
+ argv[i] = xstrdup (concat ("-f", makefiles->list[j], ""));
++j;
}
}
@@ -2012,25 +2020,20 @@ main (int argc, char **argv, char **envp)
{
nargv = xmalloc ((nargc + 2) * sizeof (char *));
memcpy (nargv, argv, argc * sizeof (char *));
- nargv[nargc++] = concat ("-o", stdin_nm, "");
+ nargv[nargc++] = xstrdup (concat ("-o", stdin_nm, ""));
nargv[nargc] = 0;
}
if (directories != 0 && directories->idx > 0)
{
- char bad;
+ int bad = 1;
if (directory_before_chdir != 0)
{
if (chdir (directory_before_chdir) < 0)
- {
perror_with_name ("chdir", "");
- bad = 1;
- }
else
bad = 0;
}
- else
- bad = 1;
if (bad)
fatal (NILF, _("Couldn't change back to original directory."));
}
@@ -2142,10 +2145,10 @@ main (int argc, char **argv, char **envp)
/* If restarts is set we haven't set up -W files yet, so do that now. */
if (restarts && new_files != 0)
{
- char **p;
+ const char **p;
for (p = new_files->list; *p != 0; ++p)
{
- struct file *f = enter_command_line_file (*p);
+ struct file *f = enter_file (*p);
f->last_mtime = f->mtime_before_update = NEW_MTIME;
}
}
@@ -2184,7 +2187,7 @@ main (int argc, char **argv, char **envp)
if (ns->next != 0)
fatal (NILF, _(".DEFAULT_GOAL contains more than one target"));
- default_goal_file = enter_file (ns->name);
+ default_goal_file = enter_file (strcache_add (ns->name));
ns->name = 0; /* It was reused by enter_file(). */
free_ns_chain (ns);
@@ -2287,6 +2290,7 @@ init_switches (void)
break;
case string:
+ case filename:
case positive_int:
case floating:
if (short_option (switches[i].c))
@@ -2342,7 +2346,7 @@ handle_non_switch_argument (char *arg, int env)
/* Not an option or variable definition; it must be a goal
target! Enter it as a file and add it to the dep chain of
goals. */
- struct file *f = enter_command_line_file (arg);
+ struct file *f = enter_file (strcache_add (expand_command_line_file (arg)));
f->cmd_target = 1;
if (goals == 0)
@@ -2361,7 +2365,7 @@ handle_non_switch_argument (char *arg, int env)
{
/* Add this target name to the MAKECMDGOALS variable. */
struct variable *gv;
- char *value;
+ const char *value;
gv = lookup_variable (STRING_SIZE_TUPLE ("MAKECMDGOALS"));
if (gv == 0)
@@ -2370,13 +2374,15 @@ handle_non_switch_argument (char *arg, int env)
{
/* Paste the old and new values together */
unsigned int oldlen, newlen;
+ char *vp;
oldlen = strlen (gv->value);
newlen = strlen (f->name);
- value = alloca (oldlen + 1 + newlen + 1);
- memcpy (value, gv->value, oldlen);
- value[oldlen] = ' ';
- memcpy (&value[oldlen + 1], f->name, newlen + 1);
+ vp = alloca (oldlen + 1 + newlen + 1);
+ memcpy (vp, gv->value, oldlen);
+ vp[oldlen] = ' ';
+ memcpy (&vp[oldlen + 1], f->name, newlen + 1);
+ value = vp;
}
define_variable ("MAKECMDGOALS", 12, value, o_default, 0);
}
@@ -2472,6 +2478,7 @@ decode_switches (int argc, char **argv, int env)
break;
case string:
+ case filename:
if (!doit)
break;
@@ -2500,7 +2507,10 @@ decode_switches (int argc, char **argv, int env)
sl->list = xrealloc (sl->list,
sl->max * sizeof (char *));
}
- sl->list[sl->idx++] = optarg;
+ if (cs->type == filename)
+ sl->list[sl->idx++] = expand_command_line_file (optarg);
+ else
+ sl->list[sl->idx++] = optarg;
sl->list[sl->idx] = 0;
break;
@@ -2641,7 +2651,7 @@ decode_env_switches (char *envar, unsigned int len)
definition. Add a dash and pass it along to decode_switches. We
need permanent storage for this in case decode_switches saves
pointers into the value. */
- argv[1] = concat ("-", argv[1], "");
+ argv[1] = xstrdup (concat ("-", argv[1], ""));
/* Parse those words. */
decode_switches (argc, argv, 1);
@@ -2654,7 +2664,7 @@ decode_env_switches (char *envar, unsigned int len)
Allocating space for OUT twice the length of IN is always sufficient. */
static char *
-quote_for_env (char *out, char *in)
+quote_for_env (char *out, const char *in)
{
while (*in != '\0')
{
@@ -2692,7 +2702,7 @@ define_makeflags (int all, int makefile)
{
struct flag *next;
const struct command_switch *cs;
- char *arg;
+ const char *arg;
};
struct flag *flags = 0;
unsigned int flagslen = 0;
@@ -2716,9 +2726,6 @@ define_makeflags (int all, int makefile)
if (cs->toenv && (!makefile || !cs->no_makefile))
switch (cs->type)
{
- default:
- abort ();
-
case ignore:
break;
@@ -2775,21 +2782,25 @@ define_makeflags (int all, int makefile)
break;
#endif
+ case filename:
case string:
if (all)
{
struct stringlist *sl = *(struct stringlist **) cs->value_ptr;
if (sl != 0)
{
- /* Add the elements in reverse order, because
- all the flags get reversed below; and the order
- matters for some switches (like -I). */
- register unsigned int i = sl->idx;
+ /* Add the elements in reverse order, because all the flags
+ get reversed below; and the order matters for some
+ switches (like -I). */
+ unsigned int i = sl->idx;
while (i-- > 0)
ADD_FLAG (sl->list[i], strlen (sl->list[i]));
}
}
break;
+
+ default:
+ abort ();
}
flagslen += 4 + sizeof posixref; /* Four more for the possible " -- ". */
@@ -3073,6 +3084,8 @@ die (int status)
if (print_data_base_flag)
print_data_base ();
+ verify_file_data_base ();
+
clean_jobserver (status);
/* Try to move back to the original directory. This is essential on
diff --git a/maintMakefile b/maintMakefile
index 4599e15..6cef280 100644
--- a/maintMakefile
+++ b/maintMakefile
@@ -226,7 +226,8 @@ po-check:
## ------------------------- ##
# This target creates the upload artifacts.
-# Sign it with my key.
+# Sign it with my key. If you don't have my key/passphrase then sorry,
+# you're SOL! :)
GPG = gpg
GPGFLAGS = -u 6338B6D4
@@ -234,21 +235,24 @@ GPGFLAGS = -u 6338B6D4
DIST_ARCHIVES_SIG = $(addsuffix .sig,$(DIST_ARCHIVES))
DIST_ARCHIVES_DIRECTIVE = $(addsuffix .directive.asc,$(DIST_ARCHIVES))
+# A simple rule to test signing, etc.
.PHONY: distsign
distsign: $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
-$(DIST_ARCHIVES_DIRECTIVE): .directive.asc
- cp $< $@
-
%.sig : %
@echo "Signing file '$<':"
- $(GPG) $(GPGFLAGS) -o $@ -b $<
+ $(GPG) $(GPGFLAGS) -o "$@" -b "$<"
-.directive.asc:
+%.directive.asc: %
@echo "Creating directive file '$@':"
- @echo 'directory: make' > .directive
- $(GPG) $(GPGFLAGS) -o $@ --clearsign .directive
- @rm -f .directive
+ @( \
+ echo 'verstion: 1.1'; \
+ echo 'directory: make'; \
+ echo 'filename: $*'; \
+ echo 'comment: Official upload of GNU make version $(VERSION)'; \
+ ) > "$*.directive"
+ $(GPG) $(GPGFLAGS) -o "$@" --clearsign "$*.directive"
+ @rm -f "$*.directive"
# Upload the artifacts
@@ -258,11 +262,11 @@ gnu-url = ftp-upload.gnu.org /incoming
UPLOADS = upload-alpha upload-ftp
.PHONY: $(UPLOADS)
$(UPLOADS): $(DIST_ARCHIVES) $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
- $(FTPPUT) $(gnu-url)/$(@:upload-%=%) $^
+ $(FTPPUT) "$(gnu-url)/$(@:upload-%=%)" $^
-# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-# Free Software Foundation, Inc.
+# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+# 2007 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
diff --git a/make.h b/make.h
index 08f5543..35335f0 100644
--- a/make.h
+++ b/make.h
@@ -334,8 +334,8 @@ int strcmpi (const char *,const char *);
void sync_Path_environment (void);
int kill (int pid, int sig);
-char *end_of_token_w32 (char *s, char stopchar);
-int find_and_set_default_shell (char *token);
+char *end_of_token_w32 (const char *s, char stopchar);
+int find_and_set_default_shell (const char *token);
/* indicates whether or not we have Bourne shell */
extern int no_default_sh_exe;
@@ -385,7 +385,7 @@ char *concat (const char *, const char *, const char *);
void *xmalloc (unsigned int);
void *xrealloc (void *, unsigned int);
char *xstrdup (const char *);
-char *find_next_token (char **, unsigned int *);
+char *find_next_token (const char **, unsigned int *);
char *next_token (const char *);
char *end_of_token (const char *);
void collapse_continuations (char *);
@@ -393,6 +393,7 @@ char *lindex (const char *, const char *, int);
int alpha_compare (const void *, const void *);
void print_spaces (unsigned int);
char *find_percent (char *);
+const char *find_percent_cached (const char **);
FILE *open_tmpfile (char **, const char *);
#ifndef NO_ARCHIVES
@@ -427,10 +428,10 @@ void install_default_implicit_rules (void);
void build_vpath_lists (void);
void construct_vpath_list (char *pattern, char *dirpath);
-int vpath_search (char **file, FILE_TIMESTAMP *mtime_ptr);
+const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr);
int gpath_search (const char *file, unsigned int len);
-void construct_include_path (char **arg_dirs);
+void construct_include_path (const char **arg_dirs);
void user_access (void);
void make_access (void);
@@ -585,5 +586,5 @@ extern int handling_fatal_signal;
NULL at the end of the directory--and _doesn't_ reset errno. So, we have
to do it ourselves here. */
-#define ENULLLOOP(_v,_c) do{ errno = 0; \
- while (((_v)=_c)==0 && errno==EINTR); }while(0)
+#define ENULLLOOP(_v,_c) do { errno = 0; (_v) = _c; } \
+ while((_v)==0 && errno==EINTR)
diff --git a/misc.c b/misc.c
index 47703d9..df54163 100644
--- a/misc.c
+++ b/misc.c
@@ -158,28 +158,31 @@ print_spaces (unsigned int n)
}
-/* Return a newly-allocated string whose contents
- concatenate those of s1, s2, s3. */
+/* Return a string whose contents concatenate those of s1, s2, s3.
+ This string lives in static, re-used memory. */
char *
concat (const char *s1, const char *s2, const char *s3)
{
unsigned int len1, len2, len3;
- char *result;
+ static unsigned int rlen = 0;
+ static char *result = NULL;
- len1 = *s1 != '\0' ? strlen (s1) : 0;
- len2 = *s2 != '\0' ? strlen (s2) : 0;
- len3 = *s3 != '\0' ? strlen (s3) : 0;
+ len1 = (s1 && *s1 != '\0') ? strlen (s1) : 0;
+ len2 = (s2 && *s2 != '\0') ? strlen (s2) : 0;
+ len3 = (s3 && *s3 != '\0') ? strlen (s3) : 0;
- result = xmalloc (len1 + len2 + len3 + 1);
+ if (len1 + len2 + len3 + 1 > rlen)
+ result = xrealloc (result, (rlen = len1 + len2 + len3 + 10));
- if (*s1 != '\0')
+ if (len1)
memcpy (result, s1, len1);
- if (*s2 != '\0')
+ if (len2)
memcpy (result + len1, s2, len2);
- if (*s3 != '\0')
+ if (len3)
memcpy (result + len1 + len2, s3, len3);
- *(result + len1 + len2 + len3) = '\0';
+
+ result[len1+len2+len3] = '\0';
return result;
}
@@ -426,10 +429,10 @@ end_of_token (const char *s)
* Same as end_of_token, but take into account a stop character
*/
char *
-end_of_token_w32 (char *s, char stopchar)
+end_of_token_w32 (const char *s, char stopchar)
{
- register char *p = s;
- register int backslash = 0;
+ const char *p = s;
+ int backslash = 0;
while (*p != '\0' && *p != stopchar
&& (backslash || !isblank ((unsigned char)*p)))
@@ -447,7 +450,7 @@ end_of_token_w32 (char *s, char stopchar)
backslash = 0;
}
- return p;
+ return (char *)p;
}
#endif
@@ -461,22 +464,23 @@ next_token (const char *s)
return (char *)s;
}
-/* Find the next token in PTR; return the address of it, and store the
- length of the token into *LENGTHPTR if LENGTHPTR is not nil. */
+/* Find the next token in PTR; return the address of it, and store the length
+ of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end
+ of the token, so this function can be called repeatedly in a loop. */
char *
-find_next_token (char **ptr, unsigned int *lengthptr)
+find_next_token (const char **ptr, unsigned int *lengthptr)
{
- char *p = next_token (*ptr);
- char *end;
+ const char *p = next_token (*ptr);
if (*p == '\0')
return 0;
- *ptr = end = end_of_token (p);
+ *ptr = end_of_token (p);
if (lengthptr != 0)
- *lengthptr = end - p;
- return p;
+ *lengthptr = *ptr - p;
+
+ return (char *)p;
}
@@ -496,12 +500,6 @@ alloc_dep ()
void
free_dep (struct dep *d)
{
- if (d->name != 0)
- free (d->name);
-
- if (d->stem != 0)
- free (d->stem);
-
free (d);
}
@@ -511,20 +509,14 @@ free_dep (struct dep *d)
struct dep *
copy_dep_chain (const struct dep *d)
{
- register struct dep *c;
struct dep *firstnew = 0;
struct dep *lastnew = 0;
while (d != 0)
{
- c = xmalloc (sizeof (struct dep));
+ struct dep *c = xmalloc (sizeof (struct dep));
memcpy (c, d, sizeof (struct dep));
- if (c->name != 0)
- c->name = xstrdup (c->name);
- if (c->stem != 0)
- c->stem = xstrdup (c->stem);
-
c->next = 0;
if (firstnew == 0)
firstnew = lastnew = c;
@@ -549,37 +541,20 @@ free_dep_chain (struct dep *d)
free_dep (df);
}
}
-
-/* Free a chain of `struct nameseq'. Each nameseq->name is freed
- as well. For `struct dep' chains use free_dep_chain. */
-
-void
-free_ns_chain (struct nameseq *n)
-{
- register struct nameseq *tmp;
- while (n != 0)
- {
- if (n->name != 0)
- free (n->name);
+/* Free a chain of struct nameseq.
+ For struct dep chains use free_dep_chain. */
- tmp = n;
-
- n = n->next;
-
- free (tmp);
- }
-
-}
-#ifdef iAPX286
-/* The losing compiler on this machine can't handle this macro. */
-
-char *
-dep_name (struct dep *dep)
+void
+free_ns_chain (struct nameseq *ns)
{
- return dep->name == 0 ? dep->file->name : dep->name;
+ while (ns != 0)
+ {
+ struct nameseq *t = ns;
+ ns = ns->next;
+ free (t);
+ }
}
-#endif
#ifdef GETLOADAVG_PRIVILEGED
diff --git a/read.c b/read.c
index 6b0c0aa..e50a76c 100644
--- a/read.c
+++ b/read.c
@@ -88,14 +88,12 @@ static struct conditionals *conditionals = &toplevel_conditionals;
/* Default directories to search for include files in */
-static char *default_include_directories[] =
+static const char *default_include_directories[] =
{
#if defined(WINDOWS32) && !defined(INCLUDEDIR)
-/*
- * This completely up to the user when they install MSVC or other packages.
- * This is defined as a placeholder.
- */
-#define INCLUDEDIR "."
+/* This completely up to the user when they install MSVC or other packages.
+ This is defined as a placeholder. */
+# define INCLUDEDIR "."
#endif
INCLUDEDIR,
#ifndef _AMIGA
@@ -108,7 +106,7 @@ static char *default_include_directories[] =
/* List of directories to search for include files in */
-static char **include_directories;
+static const char **include_directories;
/* Maximum length of an element of the above. */
@@ -123,15 +121,15 @@ const struct floc *reading_file = 0;
static struct dep *read_makefiles = 0;
-static int eval_makefile (char *filename, int flags);
+static int eval_makefile (const char *filename, int flags);
static int eval (struct ebuffer *buffer, int flags);
static long readline (struct ebuffer *ebuf);
static void do_define (char *name, unsigned int namelen,
enum variable_origin origin, struct ebuffer *ebuf);
static int conditional_line (char *line, int len, const struct floc *flocp);
-static void record_files (struct nameseq *filenames, char *pattern,
- char *pattern_percent, struct dep *deps,
+static void record_files (struct nameseq *filenames, const char *pattern,
+ const char *pattern_percent, struct dep *deps,
unsigned int cmds_started, char *commands,
unsigned int commands_idx, int two_colon,
const struct floc *flocp);
@@ -147,7 +145,7 @@ static char *find_char_unquote (char *string, int stop1, int stop2,
/* Read in all the makefiles and return the chain of their names. */
struct dep *
-read_all_makefiles (char **makefiles)
+read_all_makefiles (const char **makefiles)
{
unsigned int num_makefiles = 0;
@@ -181,7 +179,7 @@ read_all_makefiles (char **makefiles)
MAKEFILES is updated for finding remaining tokens. */
p = value;
- while ((name = find_next_token (&p, &length)) != 0)
+ while ((name = find_next_token ((const char **)&p, &length)) != 0)
{
if (*p != '\0')
*p++ = '\0';
@@ -248,7 +246,7 @@ read_all_makefiles (char **makefiles)
for (p = default_makefiles; *p != 0; ++p)
{
struct dep *d = alloc_dep ();
- d->file = enter_file (*p);
+ d->file = enter_file (strcache_add (*p));
d->file->dontcare = 1;
/* Tell update_goal_chain to bail out as soon as this file is
made, and main not to die if we can't make this file. */
@@ -296,17 +294,17 @@ restore_conditionals (struct conditionals *saved)
}
static int
-eval_makefile (char *filename, int flags)
+eval_makefile (const char *filename, int flags)
{
struct dep *deps;
struct ebuffer ebuf;
const struct floc *curfile;
char *expanded = 0;
- char *included = 0;
int makefile_errno;
int r;
- ebuf.floc.filenm = strcache_add (filename);
+ filename = strcache_add (filename);
+ ebuf.floc.filenm = filename;
ebuf.floc.lineno = 1;
if (ISDB (DB_VERBOSE))
@@ -343,21 +341,17 @@ eval_makefile (char *filename, int flags)
search the included makefile search path for this makefile. */
if (ebuf.fp == 0 && (flags & RM_INCLUDED) && *filename != '/')
{
- register unsigned int i;
+ unsigned int i;
for (i = 0; include_directories[i] != 0; ++i)
{
- included = concat (include_directories[i], "/", filename);
+ const char *included = concat (include_directories[i], "/", filename);
ebuf.fp = fopen (included, "r");
if (ebuf.fp)
{
- filename = included;
+ filename = strcache_add (included);
break;
}
- free (included);
}
- /* If we're not using it, we already freed it above. */
- if (filename != included)
- included = 0;
}
/* Add FILENAME to the chain of read makefiles. */
@@ -366,7 +360,7 @@ eval_makefile (char *filename, int flags)
read_makefiles = deps;
deps->file = lookup_file (filename);
if (deps->file == 0)
- deps->file = enter_file (xstrdup (filename));
+ deps->file = enter_file (filename);
filename = deps->file->name;
deps->changed = flags;
if (flags & RM_DONTCARE)
@@ -374,8 +368,6 @@ eval_makefile (char *filename, int flags)
if (expanded)
free (expanded);
- if (included)
- free (included);
/* If the makefile can't be found at all, give up entirely. */
@@ -464,7 +456,8 @@ eval (struct ebuffer *ebuf, int set_default)
struct dep *deps = 0;
long nlines = 0;
int two_colon = 0;
- char *pattern = 0, *pattern_percent;
+ const char *pattern = 0;
+ const char *pattern_percent;
struct floc *fstart;
struct floc fi;
@@ -481,7 +474,7 @@ eval (struct ebuffer *ebuf, int set_default)
filenames = 0; \
commands_idx = 0; \
no_targets = 0; \
- if (pattern) { free(pattern); pattern = 0; } \
+ pattern = 0; \
} while (0)
pattern_percent = 0;
@@ -708,14 +701,15 @@ eval (struct ebuffer *ebuf, int set_default)
else
{
unsigned int l;
+ const char *cp;
char *ap;
/* Expand the line so we can use indirect and constructed
variable names in an export command. */
- p2 = ap = allocated_variable_expand (p2);
+ cp = ap = allocated_variable_expand (p2);
- for (p = find_next_token (&p2, &l); p != 0;
- p = find_next_token (&p2, &l))
+ for (p = find_next_token (&cp, &l); p != 0;
+ p = find_next_token (&cp, &l))
{
v = lookup_variable (p, l);
if (v == 0)
@@ -737,14 +731,15 @@ eval (struct ebuffer *ebuf, int set_default)
{
unsigned int l;
struct variable *v;
+ const char *cp;
char *ap;
/* Expand the line so we can use indirect and constructed
variable names in an unexport command. */
- p2 = ap = allocated_variable_expand (p2);
+ cp = ap = allocated_variable_expand (p2);
- for (p = find_next_token (&p2, &l); p != 0;
- p = find_next_token (&p2, &l))
+ for (p = find_next_token (&cp, &l); p != 0;
+ p = find_next_token (&cp, &l))
{
v = lookup_variable (p, l);
if (v == 0)
@@ -761,14 +756,15 @@ eval (struct ebuffer *ebuf, int set_default)
skip_conditionals:
if (word1eq ("vpath"))
{
+ const char *cp;
char *vpat;
unsigned int l;
- p2 = variable_expand (p2);
- p = find_next_token (&p2, &l);
+ cp = variable_expand (p2);
+ p = find_next_token (&cp, &l);
if (p != 0)
{
vpat = savestring (p, l);
- p = find_next_token (&p2, &l);
+ p = find_next_token (&cp, &l);
/* No searchpath means remove all previous
selective VPATH's with the same pattern. */
}
@@ -822,7 +818,7 @@ eval (struct ebuffer *ebuf, int set_default)
while (files != 0)
{
struct nameseq *next = files->next;
- char *name = files->name;
+ const char *name = files->name;
int r;
free (files);
@@ -832,7 +828,6 @@ eval (struct ebuffer *ebuf, int set_default)
| (noerror ? RM_DONTCARE : 0)));
if (!r && !noerror)
error (fstart, "%s: %s", name, strerror (errno));
- free (name);
}
/* Restore conditional state. */
@@ -1148,8 +1143,8 @@ eval (struct ebuffer *ebuf, int set_default)
fatal (fstart, _("missing target pattern"));
else if (target->next != 0)
fatal (fstart, _("multiple target patterns"));
+ pattern_percent = find_percent_cached (&target->name);
pattern = target->name;
- pattern_percent = find_percent (pattern);
if (pattern_percent == 0)
fatal (fstart, _("target pattern contains no `%%'"));
free (target);
@@ -1166,7 +1161,7 @@ eval (struct ebuffer *ebuf, int set_default)
{
/* Put all the prerequisites here; they'll be parsed later. */
deps = alloc_dep ();
- deps->name = savestring (beg, end - beg + 1);
+ deps->name = strcache_add_len (beg, end - beg + 1);
}
else
deps = 0;
@@ -1208,7 +1203,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (**default_goal_name == '\0' && set_default)
{
- char* name;
+ const char *name;
struct dep *d;
struct nameseq *t = filenames;
@@ -1769,9 +1764,9 @@ record_target_var (struct nameseq *filenames, char *defn,
for (; filenames != 0; filenames = nextf)
{
struct variable *v;
- register char *name = filenames->name;
- char *fname;
- char *percent;
+ const char *name = filenames->name;
+ const char *fname;
+ const char *percent;
struct pattern_var *p;
nextf = filenames->next;
@@ -1779,7 +1774,7 @@ record_target_var (struct nameseq *filenames, char *defn,
/* If it's a pattern target, then add it to the pattern-specific
variable list. */
- percent = find_percent (name);
+ percent = find_percent_cached (&name);
if (percent)
{
/* Get a reference for this pattern-specific variable struct. */
@@ -1807,7 +1802,7 @@ record_target_var (struct nameseq *filenames, char *defn,
this situation. */
f = lookup_file (name);
if (!f)
- f = enter_file (name);
+ f = enter_file (strcache_add (name));
else if (f->double_colon)
f = f->double_colon;
@@ -1844,10 +1839,6 @@ record_target_var (struct nameseq *filenames, char *defn,
v->append = 0;
}
}
-
- /* Free name if not needed further. */
- if (name != fname && (name < fname || name > fname + strlen (fname)))
- free (name);
}
}
@@ -1863,15 +1854,16 @@ record_target_var (struct nameseq *filenames, char *defn,
that are not incorporated into other data structures. */
static void
-record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
- struct dep *deps, unsigned int cmds_started, char *commands,
+record_files (struct nameseq *filenames, const char *pattern,
+ const char *pattern_percent, struct dep *deps,
+ unsigned int cmds_started, char *commands,
unsigned int commands_idx, int two_colon,
const struct floc *flocp)
{
struct nameseq *nextf;
int implicit = 0;
unsigned int max_targets = 0, target_idx = 0;
- char **targets = 0, **target_percents = 0;
+ const char **targets = 0, **target_percents = 0;
struct commands *cmds;
/* If we've already snapped deps, that means we're in an eval being
@@ -1894,10 +1886,10 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
for (; filenames != 0; filenames = nextf)
{
- char *name = filenames->name;
+ const char *name = filenames->name;
struct file *f;
struct dep *this = 0;
- char *implicit_percent;
+ const char *implicit_percent;
nextf = filenames->next;
free (filenames);
@@ -1910,17 +1902,17 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
else if (streq (name, ".SECONDEXPANSION"))
second_expansion = 1;
- implicit_percent = find_percent (name);
+ implicit_percent = find_percent_cached (&name);
implicit |= implicit_percent != 0;
- if (implicit && pattern != 0)
- fatal (flocp, _("mixed implicit and static pattern rules"));
+ if (implicit)
+ {
+ if (pattern != 0)
+ fatal (flocp, _("mixed implicit and static pattern rules"));
- if (implicit && implicit_percent == 0)
- fatal (flocp, _("mixed implicit and normal rules"));
+ if (implicit_percent == 0)
+ fatal (flocp, _("mixed implicit and normal rules"));
- if (implicit)
- {
if (targets == 0)
{
max_targets = 5;
@@ -1960,7 +1952,7 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
{
/* Single-colon. Combine these dependencies
with others in file's existing record, if any. */
- f = enter_file (name);
+ f = enter_file (strcache_add (name));
if (f->double_colon)
fatal (flocp,
@@ -2066,7 +2058,7 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
if (f != 0 && f->is_target && !f->double_colon)
fatal (flocp,
_("target file `%s' has both : and :: entries"), f->name);
- f = enter_file (name);
+ f = enter_file (strcache_add (name));
/* If there was an existing entry and it was a double-colon entry,
enter_file will have returned a new one, making it the prev
pointer of the old one, and setting its double_colon pointer to
@@ -2085,25 +2077,19 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
commands. */
if (pattern)
{
- static char *percent = "%";
+ static const char *percent = "%";
char *buffer = variable_expand ("");
- char *o = patsubst_expand (buffer, name, pattern, percent,
- pattern_percent+1, percent+1);
- f->stem = savestring (buffer, o - buffer);
+ char *o = patsubst_expand_pat (buffer, name, pattern, percent,
+ pattern_percent+1, percent+1);
+ f->stem = strcache_add_len (buffer, o - buffer);
if (this)
{
this->staticpattern = 1;
- this->stem = xstrdup (f->stem);
+ this->stem = f->stem;
}
}
- /* Free name if not needed further. */
- if (f != 0 && name != f->name
- && (name < f->name || name > f->name + strlen (f->name)))
- {
- free (name);
- name = f->name;
- }
+ name = f->name;
/* If this target is a default target, update DEFAULT_GOAL_FILE. */
if (streq (*default_goal_name, name)
@@ -2114,12 +2100,10 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent,
if (implicit)
{
- targets[target_idx] = 0;
- target_percents[target_idx] = 0;
if (deps)
deps->need_2nd_expansion = second_expansion;
- create_pattern_rule (targets, target_percents, two_colon, deps, cmds, 1);
- free (target_percents);
+ create_pattern_rule (targets, target_percents, target_idx,
+ two_colon, deps, cmds, 1);
}
}
@@ -2137,7 +2121,7 @@ find_char_unquote (char *string, int stop1, int stop2, int blank,
int ignorevars)
{
unsigned int string_len = 0;
- register char *p = string;
+ char *p = string;
if (ignorevars)
ignorevars = '$';
@@ -2230,6 +2214,82 @@ find_percent (char *pattern)
{
return find_char_unquote (pattern, '%', 0, 0, 0);
}
+
+/* Search STRING for an unquoted % and handle quoting. Returns a pointer to
+ the % or NULL if no % was found.
+ This version is used with strings in the string cache: if there's a need to
+ modify the string a new version will be added to the string cache and
+ *STRING will be set to that. */
+
+const char *
+find_percent_cached (const char **string)
+{
+ const char *p = *string;
+ char *new = 0;
+ int slen;
+
+ /* If the first char is a % return now. This lets us avoid extra tests
+ inside the loop. */
+ if (*p == '%')
+ return p;
+
+ while (1)
+ {
+ while (*p != '\0' && *p != '%')
+ ++p;
+
+ if (*p == '\0')
+ break;
+
+ /* See if this % is escaped with a backslash; if not we're done. */
+ if (p[-1] != '\\')
+ break;
+
+ {
+ /* Search for more backslashes. */
+ char *pv;
+ int i = -2;
+
+ while (&p[i] >= *string && p[i] == '\\')
+ --i;
+ ++i;
+
+ /* At this point we know we'll need to allocate a new string.
+ Make a copy if we haven't yet done so. */
+ if (! new)
+ {
+ slen = strlen (*string);
+ new = alloca (slen + 1);
+ memcpy (new, *string, slen + 1);
+ p = new + (p - *string);
+ *string = new;
+ }
+
+ /* At this point *string, p, and new all point into the same string.
+ Get a non-const version of p so we can modify new. */
+ pv = new + (p - *string);
+
+ /* The number of backslashes is now -I.
+ Copy P over itself to swallow half of them. */
+ memmove (&pv[i], &pv[i/2], (slen - (pv - new)) - (i/2) + 1);
+ p += i/2;
+
+ /* If the backslashes quoted each other; the % was unquoted. */
+ if (i % 2 == 0)
+ break;
+ }
+ }
+
+ /* If we had to change STRING, add it to the strcache. */
+ if (new)
+ {
+ *string = strcache_add (*string);
+ p = *string + (p - new);
+ }
+
+ /* If we didn't find a %, return NULL. Otherwise return a ptr to it. */
+ return (*p == '\0') ? NULL : p;
+}
/* Parse a string into a sequence of filenames represented as a
chain of struct nameseq's in reverse order and return that chain.
@@ -2250,8 +2310,6 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
struct nameseq *new = 0;
struct nameseq *new1, *lastnew1;
char *p = *stringp;
- char *q;
- char *name;
#ifdef VMS
# define VMS_COMMA ','
@@ -2261,6 +2319,9 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
while (1)
{
+ const char *name;
+ char *q;
+
/* Skip whitespace; see if any more names are left. */
p = next_token (p);
if (*p == '\0')
@@ -2268,7 +2329,7 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
if (*p == stopchar)
break;
- /* Yes, find end of next name. */
+ /* There are, so find the end of the next name. */
q = p;
p = find_char_unquote (q, stopchar, VMS_COMMA, 1, 0);
#ifdef VMS
@@ -2280,9 +2341,7 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
if (stopchar == ':' && p && *p == ':'
&& !(isspace ((unsigned char)p[1]) || !p[1]
|| isspace ((unsigned char)p[-1])))
- {
p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0);
- }
#endif
#ifdef HAVE_DOS_PATHS
/* For DOS paths, skip a "C:\..." or a "C:/..." until we find the
@@ -2316,14 +2375,12 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
if (q == p)
/* ".///" was stripped to "". */
-#ifdef VMS
+#if defined(VMS)
continue;
+#elif defined(_AMIGA)
+ name = "";
#else
-#ifdef _AMIGA
- name = savestring ("", 0);
-#else
- name = savestring ("./", 2);
-#endif
+ name = "./";
#endif
else
#ifdef VMS
@@ -2347,11 +2404,11 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
}
*q2++ = *q1++;
}
- name = savestring (qbase, p1 - qbase);
+ name = strcache_add_len (qbase, p1 - qbase);
free (qbase);
}
#else
- name = savestring (q, p - q);
+ name = strcache_add_len (q, p - q);
#endif
/* Add it to the front of the chain. */
@@ -2407,7 +2464,6 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
/* N was just "lib(", part of something like "lib( a b)".
Edit it out of the chain and free its storage. */
lastn->next = n->next;
- free (n->name);
free (n);
/* LASTN->next is the new stopping elt for the loop below. */
n = lastn->next;
@@ -2415,9 +2471,7 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
else
{
/* Replace N's name with the full archive reference. */
- name = concat (libname, paren, ")");
- free (n->name);
- n->name = name;
+ n->name = strcache_add (concat (libname, paren, ")"));
}
if (new1->name[1] == '\0')
@@ -2430,15 +2484,12 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
lastnew1->next = new1->next;
lastn = new1;
new1 = new1->next;
- free (lastn->name);
free (lastn);
}
else
{
/* Replace also NEW1->name, which already has closing `)'. */
- name = concat (libname, new1->name, "");
- free (new1->name);
- new1->name = name;
+ new1->name = strcache_add (concat (libname, new1->name, ""));
new1 = new1->next;
}
@@ -2448,9 +2499,7 @@ parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
while (new1 != n)
{
- name = concat (libname, new1->name, ")");
- free (new1->name);
- new1->name = name;
+ new1->name = strcache_add (concat (libname, new1->name, ")"));
lastnew1 = new1;
new1 = new1->next;
}
@@ -2818,104 +2867,112 @@ get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length)
from the arguments and the default list. */
void
-construct_include_path (char **arg_dirs)
+construct_include_path (const char **arg_dirs)
{
- register unsigned int i;
#ifdef VAXC /* just don't ask ... */
stat_t stbuf;
#else
struct stat stbuf;
#endif
- /* Table to hold the dirs. */
+ const char **dirs;
+ const char **cpp;
+ unsigned int idx;
- unsigned int defsize = (sizeof (default_include_directories)
- / sizeof (default_include_directories[0]));
- unsigned int max = 5;
- char **dirs = xmalloc ((5 + defsize) * sizeof (char *));
- unsigned int idx = 0;
+ /* Compute the number of pointers we need in the table. */
+ idx = sizeof (default_include_directories) / sizeof (const char *);
+ if (arg_dirs)
+ for (cpp = arg_dirs; *cpp != 0; ++cpp)
+ ++idx;
#ifdef __MSDOS__
- defsize++;
+ /* Add one for $DJDIR. */
+ ++idx;
#endif
+ dirs = xmalloc (idx * sizeof (const char *));
+
+ idx = 0;
+ max_incl_len = 0;
+
/* First consider any dirs specified with -I switches.
- Ignore dirs that don't exist. */
+ Ignore any that don't exist. Remember the maximum string length. */
- if (arg_dirs != 0)
+ if (arg_dirs)
while (*arg_dirs != 0)
{
- char *dir = *arg_dirs++;
+ const char *dir = *(arg_dirs++);
+ char *expanded = 0;
int e;
if (dir[0] == '~')
{
- char *expanded = tilde_expand (dir);
+ expanded = tilde_expand (dir);
if (expanded != 0)
dir = expanded;
}
EINTRLOOP (e, stat (dir, &stbuf));
if (e == 0 && S_ISDIR (stbuf.st_mode))
- {
- if (idx == max - 1)
- {
- max += 5;
- dirs = xrealloc (dirs, (max + defsize) * sizeof (char *));
- }
- dirs[idx++] = dir;
- }
- else if (dir != arg_dirs[-1])
- free (dir);
+ {
+ unsigned int len = strlen (dir);
+ /* If dir name is written with trailing slashes, discard them. */
+ while (len > 1 && dir[len - 1] == '/')
+ --len;
+ if (len > max_incl_len)
+ max_incl_len = len;
+ dirs[idx++] = strcache_add_len (dir, len);
+ }
+
+ if (expanded)
+ free (expanded);
}
- /* Now add at the end the standard default dirs. */
+ /* Now add the standard default dirs at the end. */
#ifdef __MSDOS__
{
- /* The environment variable $DJDIR holds the root of the
- DJGPP directory tree; add ${DJDIR}/include. */
+ /* The environment variable $DJDIR holds the root of the DJGPP directory
+ tree; add ${DJDIR}/include. */
struct variable *djdir = lookup_variable ("DJDIR", 5);
if (djdir)
{
- char *defdir = xmalloc (strlen (djdir->value) + 8 + 1);
+ unsigned int len = strlen (djdir->value) + 8;
+ char *defdir = alloca (len + 1);
strcat (strcpy (defdir, djdir->value), "/include");
- dirs[idx++] = defdir;
+ dirs[idx++] = strcache_add (defdir);
+
+ if (len > max_incl_len)
+ max_incl_len = len;
}
}
#endif
- for (i = 0; default_include_directories[i] != 0; ++i)
+ for (cpp = default_include_directories; *cpp != 0; ++cpp)
{
int e;
- EINTRLOOP (e, stat (default_include_directories[i], &stbuf));
+ EINTRLOOP (e, stat (*cpp, &stbuf));
if (e == 0 && S_ISDIR (stbuf.st_mode))
- dirs[idx++] = default_include_directories[i];
+ {
+ unsigned int len = strlen (*cpp);
+ /* If dir name is written with trailing slashes, discard them. */
+ while (len > 1 && (*cpp)[len - 1] == '/')
+ --len;
+ if (len > max_incl_len)
+ max_incl_len = len;
+ dirs[idx++] = strcache_add_len (*cpp, len - 1);
+ }
}
dirs[idx] = 0;
- /* Now compute the maximum length of any name in it. Also add each
- dir to the .INCLUDE_DIRS variable. */
+ /* Now add each dir to the .INCLUDE_DIRS variable. */
- max_incl_len = 0;
- for (i = 0; i < idx; ++i)
- {
- unsigned int len = strlen (dirs[i]);
- /* If dir name is written with a trailing slash, discard it. */
- if (dirs[i][len - 1] == '/')
- /* We can't just clobber a null in because it may have come from
- a literal string and literal strings may not be writable. */
- dirs[i] = savestring (dirs[i], len - 1);
- if (len > max_incl_len)
- max_incl_len = len;
-
- /* Append to .INCLUDE_DIRS. */
- do_variable_definition (NILF, ".INCLUDE_DIRS", dirs[i],
- o_default, f_append, 0);
- }
+ for (cpp = dirs; *cpp != 0; ++cpp)
+ do_variable_definition (NILF, ".INCLUDE_DIRS", *cpp,
+ o_default, f_append, 0);
include_directories = dirs;
}
@@ -2924,7 +2981,7 @@ construct_include_path (char **arg_dirs)
Return a newly malloc'd string or 0. */
char *
-tilde_expand (char *name)
+tilde_expand (const char *name)
{
#ifndef VMS
if (name[1] == '/' || name[1] == '\0')
@@ -2949,7 +3006,7 @@ tilde_expand (char *name)
free (home_dir);
home_dir = getenv ("HOME");
}
-#if !defined(_AMIGA) && !defined(WINDOWS32)
+# if !defined(_AMIGA) && !defined(WINDOWS32)
if (home_dir == 0 || home_dir[0] == '\0')
{
extern char *getlogin ();
@@ -2962,16 +3019,16 @@ tilde_expand (char *name)
home_dir = p->pw_dir;
}
}
-#endif /* !AMIGA && !WINDOWS32 */
+# endif /* !AMIGA && !WINDOWS32 */
if (home_dir != 0)
{
- char *new = concat (home_dir, "", name + 1);
+ char *new = xstrdup (concat (home_dir, "", name + 1));
if (is_variable)
free (home_dir);
return new;
}
}
-#if !defined(_AMIGA) && !defined(WINDOWS32)
+# if !defined(_AMIGA) && !defined(WINDOWS32)
else
{
struct passwd *pwent;
@@ -2984,12 +3041,12 @@ tilde_expand (char *name)
if (userend == 0)
return xstrdup (pwent->pw_dir);
else
- return concat (pwent->pw_dir, "/", userend + 1);
+ return xstrdup (concat (pwent->pw_dir, "/", userend + 1));
}
else if (userend != 0)
*userend = '/';
}
-#endif /* !AMIGA && !WINDOWS32 */
+# endif /* !AMIGA && !WINDOWS32 */
#endif /* !VMS */
return 0;
}
@@ -3007,9 +3064,9 @@ tilde_expand (char *name)
struct nameseq *
multi_glob (struct nameseq *chain, unsigned int size)
{
- extern void dir_setup_glob ();
- register struct nameseq *new = 0;
- register struct nameseq *old;
+ void dir_setup_glob (glob_t *);
+ struct nameseq *new = 0;
+ struct nameseq *old;
struct nameseq *nexto;
glob_t gl;
@@ -3017,44 +3074,37 @@ multi_glob (struct nameseq *chain, unsigned int size)
for (old = chain; old != 0; old = nexto)
{
+ const char *gname;
#ifndef NO_ARCHIVES
- char *memname;
+ char *arname = 0;
+ char *memname = 0;
#endif
-
nexto = old->next;
+ gname = old->name;
- if (old->name[0] == '~')
+ if (gname[0] == '~')
{
char *newname = tilde_expand (old->name);
if (newname != 0)
- {
- free (old->name);
- old->name = newname;
- }
+ gname = newname;
}
#ifndef NO_ARCHIVES
- if (ar_name (old->name))
+ if (ar_name (gname))
{
- /* OLD->name is an archive member reference.
- Replace it with the archive file name,
- and save the member name in MEMNAME.
- We will glob on the archive name and then
- reattach MEMNAME later. */
- char *arname;
- ar_parse_name (old->name, &arname, &memname);
- free (old->name);
- old->name = arname;
+ /* OLD->name is an archive member reference. Replace it with the
+ archive file name, and save the member name in MEMNAME. We will
+ glob on the archive name and then reattach MEMNAME later. */
+ ar_parse_name (gname, &arname, &memname);
+ gname = arname;
}
- else
- memname = 0;
#endif /* !NO_ARCHIVES */
- switch (glob (old->name, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl))
+ switch (glob (gname, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl))
{
case 0: /* Success. */
{
- register int i = gl.gl_pathc;
+ int i = gl.gl_pathc;
while (i-- > 0)
{
#ifndef NO_ARCHIVES
@@ -3063,21 +3113,22 @@ multi_glob (struct nameseq *chain, unsigned int size)
/* Try to glob on MEMNAME within the archive. */
struct nameseq *found
= ar_glob (gl.gl_pathv[i], memname, size);
- if (found == 0)
+ if (! found)
{
/* No matches. Use MEMNAME as-is. */
unsigned int alen = strlen (gl.gl_pathv[i]);
unsigned int mlen = strlen (memname);
+ char *name;
struct nameseq *elt = xmalloc (size);
- if (size > sizeof (struct nameseq))
- memset (((char *)elt)+sizeof (struct nameseq), '\0',
- size - sizeof (struct nameseq));
- elt->name = xmalloc (alen + 1 + mlen + 2);
- memcpy (elt->name, gl.gl_pathv[i], alen);
- elt->name[alen] = '(';
- memcpy (&elt->name[alen + 1], memname, mlen);
- elt->name[alen + 1 + mlen] = ')';
- elt->name[alen + 1 + mlen + 1] = '\0';
+ memset (elt, '\0', size);
+
+ name = alloca (alen + 1 + mlen + 2);
+ memcpy (name, gl.gl_pathv[i], alen);
+ name[alen] = '(';
+ memcpy (name+alen+1, memname, mlen);
+ name[alen + 1 + mlen] = ')';
+ name[alen + 1 + mlen + 1] = '\0';
+ elt->name = strcache_add (name);
elt->next = new;
new = elt;
}
@@ -3093,23 +3144,18 @@ multi_glob (struct nameseq *chain, unsigned int size)
f->next = new;
new = found;
}
-
- free (memname);
}
else
#endif /* !NO_ARCHIVES */
{
struct nameseq *elt = xmalloc (size);
- if (size > sizeof (struct nameseq))
- memset (((char *)elt)+sizeof (struct nameseq), '\0',
- size - sizeof (struct nameseq));
- elt->name = xstrdup (gl.gl_pathv[i]);
+ memset (elt, '\0', size);
+ elt->name = strcache_add (gl.gl_pathv[i]);
elt->next = new;
new = elt;
}
}
globfree (&gl);
- free (old->name);
free (old);
break;
}
@@ -3123,6 +3169,11 @@ multi_glob (struct nameseq *chain, unsigned int size)
new = old;
break;
}
+
+#ifndef NO_ARCHIVES
+ if (arname)
+ free (arname);
+#endif
}
return new;
diff --git a/remake.c b/remake.c
index ea6e555..ee8acf3 100644
--- a/remake.c
+++ b/remake.c
@@ -66,8 +66,8 @@ static int check_dep (struct file *file, unsigned int depth,
FILE_TIMESTAMP this_mtime, int *must_make_ptr);
static int touch_file (struct file *file);
static void remake_file (struct file *file);
-static FILE_TIMESTAMP name_mtime (char *name);
-static int library_search (char **lib, FILE_TIMESTAMP *mtime_ptr);
+static FILE_TIMESTAMP name_mtime (const char *name);
+static const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr);
/* Remake all the goals in the `struct dep' chain GOALS. Return -1 if nothing
@@ -913,7 +913,7 @@ notice_finished_file (struct file *file)
We do this instead of just invalidating the cached time
so that a vpath_search can happen. Otherwise, it would
never be done because the target is already updated. */
- (void) f_mtime (d->file, 0);
+ f_mtime (d->file, 0);
}
else if (file->update_status == -1)
/* Nothing was done for FILE, but it needed nothing done.
@@ -1152,7 +1152,6 @@ f_mtime (struct file *file, int search)
char *arname, *memname;
struct file *arfile;
- int arname_used = 0;
time_t member_date;
/* Find the archive's name. */
@@ -1162,10 +1161,7 @@ f_mtime (struct file *file, int search)
Also allow for its name to be changed via VPATH search. */
arfile = lookup_file (arname);
if (arfile == 0)
- {
- arfile = enter_file (arname);
- arname_used = 1;
- }
+ arfile = enter_file (strcache_add (arname));
mtime = f_mtime (arfile, search);
check_renamed (arfile);
if (search && strcmp (arfile->hname, arname))
@@ -1176,20 +1172,11 @@ f_mtime (struct file *file, int search)
char *name;
unsigned int arlen, memlen;
- if (!arname_used)
- {
- free (arname);
- arname_used = 1;
- }
-
- arname = arfile->hname;
- arlen = strlen (arname);
+ arlen = strlen (arfile->hname);
memlen = strlen (memname);
- /* free (file->name); */
-
name = xmalloc (arlen + 1 + memlen + 2);
- memcpy (name, arname, arlen);
+ memcpy (name, arfile->hname, arlen);
name[arlen] = '(';
memcpy (name + arlen + 1, memname, memlen);
name[arlen + 1 + memlen] = ')';
@@ -1204,9 +1191,7 @@ f_mtime (struct file *file, int search)
check_renamed (file);
}
- if (!arname_used)
- free (arname);
- free (memname);
+ free (arname);
file->low_resolution_time = 1;
@@ -1227,11 +1212,11 @@ f_mtime (struct file *file, int search)
if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath)
{
/* If name_mtime failed, search VPATH. */
- char *name = file->name;
- if (vpath_search (&name, &mtime)
+ const char *name = vpath_search (file->name, &mtime);
+ if (name
/* Last resort, is it a library (-lxxx)? */
- || (name[0] == '-' && name[1] == 'l'
- && library_search (&name, &mtime)))
+ || (file->name[0] == '-' && file->name[1] == 'l'
+ && (name = library_search (file->name, &mtime)) != 0))
{
if (mtime != UNKNOWN_MTIME)
/* vpath_search and library_search store UNKNOWN_MTIME
@@ -1350,7 +1335,7 @@ f_mtime (struct file *file, int search)
much cleaner. */
static FILE_TIMESTAMP
-name_mtime (char *name)
+name_mtime (const char *name)
{
FILE_TIMESTAMP mtime;
struct stat st;
@@ -1444,8 +1429,8 @@ name_mtime (char *name)
suitable library file in the system library directories and the VPATH
directories. */
-static int
-library_search (char **lib, FILE_TIMESTAMP *mtime_ptr)
+static const char *
+library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
{
static char *dirs[] =
{
@@ -1466,14 +1451,15 @@ library_search (char **lib, FILE_TIMESTAMP *mtime_ptr)
static char *libpatterns = NULL;
- char *libname = &(*lib)[2]; /* Name without the `-l'. */
+ const char *libname = lib+2; /* Name without the '-l'. */
FILE_TIMESTAMP mtime;
/* Loop variables for the libpatterns value. */
- char *p, *p2;
+ char *p;
+ const char *p2;
unsigned int len;
- char *file, **dp;
+ char **dp;
/* If we don't have libpatterns, get it. */
if (!libpatterns)
@@ -1522,20 +1508,18 @@ library_search (char **lib, FILE_TIMESTAMP *mtime_ptr)
mtime = name_mtime (libbuf);
if (mtime != NONEXISTENT_MTIME)
{
- *lib = xstrdup (libbuf);
if (mtime_ptr != 0)
*mtime_ptr = mtime;
- return 1;
+ return strcache_add (libbuf);
}
/* Now try VPATH search on that. */
- file = libbuf;
- if (vpath_search (&file, mtime_ptr))
- {
- *lib = file;
- return 1;
- }
+ {
+ const char *file = vpath_search (libbuf, mtime_ptr);
+ if (file)
+ return file;
+ }
/* Now try the standard set of directories. */
@@ -1562,10 +1546,9 @@ library_search (char **lib, FILE_TIMESTAMP *mtime_ptr)
mtime = name_mtime (buf);
if (mtime != NONEXISTENT_MTIME)
{
- *lib = xstrdup (buf);
if (mtime_ptr != 0)
*mtime_ptr = mtime;
- return 1;
+ return strcache_add (buf);
}
}
}
diff --git a/rule.c b/rule.c
index ee96ec1..52fdf51 100644
--- a/rule.c
+++ b/rule.c
@@ -17,6 +17,9 @@ GNU Make; see the file COPYING. If not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "make.h"
+
+#include <assert.h>
+
#include "dep.h"
#include "filedef.h"
#include "job.h"
@@ -69,7 +72,7 @@ count_implicit_rule_limits (void)
{
char *name;
int namelen;
- register struct rule *rule, *lastrule;
+ struct rule *rule, *lastrule;
num_pattern_rules = max_pattern_targets = max_pattern_deps = 0;
max_pattern_dep_length = 0;
@@ -81,32 +84,27 @@ count_implicit_rule_limits (void)
while (rule != 0)
{
unsigned int ndeps = 0;
- register struct dep *dep;
+ struct dep *dep;
struct rule *next = rule->next;
- unsigned int ntargets;
++num_pattern_rules;
- ntargets = 0;
- while (rule->targets[ntargets] != 0)
- ++ntargets;
-
- if (ntargets > max_pattern_targets)
- max_pattern_targets = ntargets;
+ if (rule->num > max_pattern_targets)
+ max_pattern_targets = rule->num;
for (dep = rule->deps; dep != 0; dep = dep->next)
{
unsigned int len = strlen (dep->name);
#ifdef VMS
- char *p = strrchr (dep->name, ']');
- char *p2;
+ const char *p = strrchr (dep->name, ']');
+ const char *p2;
if (p == 0)
p = strrchr (dep->name, ':');
p2 = p != 0 ? strchr (dep->name, '%') : 0;
#else
- char *p = strrchr (dep->name, '/');
- char *p2 = p != 0 ? strchr (dep->name, '%') : 0;
+ const char *p = strrchr (dep->name, '/');
+ const char *p2 = p != 0 ? strchr (dep->name, '%') : 0;
#endif
ndeps++;
@@ -121,10 +119,8 @@ count_implicit_rule_limits (void)
++p;
if (p - dep->name > namelen)
{
- if (name != 0)
- free (name);
namelen = p - dep->name;
- name = xmalloc (namelen + 1);
+ name = xrealloc (name, namelen + 1);
}
memcpy (name, dep->name, p - dep->name);
name[p - dep->name] = '\0';
@@ -158,98 +154,103 @@ count_implicit_rule_limits (void)
If SOURCE is nil, it means there should be no deps. */
static void
-convert_suffix_rule (char *target, char *source, struct commands *cmds)
+convert_suffix_rule (const char *target, const char *source,
+ struct commands *cmds)
{
- char *targname, *targpercent, *depname;
- char **names, **percents;
+ const char **names, **percents;
struct dep *deps;
- unsigned int len;
+
+ names = xmalloc (sizeof (const char *));
+ percents = xmalloc (sizeof (const char *));
if (target == 0)
- /* Special case: TARGET being nil means we are defining a
- `.X.a' suffix rule; the target pattern is always `(%.o)'. */
{
+ /* Special case: TARGET being nil means we are defining a `.X.a' suffix
+ rule; the target pattern is always `(%.o)'. */
#ifdef VMS
- targname = savestring ("(%.obj)", 7);
+ *names = strcache_add_len ("(%.obj)", 7);
#else
- targname = savestring ("(%.o)", 5);
+ *names = strcache_add_len ("(%.o)", 5);
#endif
- targpercent = targname + 1;
+ *percents = *names + 1;
}
else
{
/* Construct the target name. */
- len = strlen (target);
- targname = xmalloc (1 + len + 1);
- targname[0] = '%';
- memcpy (targname + 1, target, len + 1);
- targpercent = targname;
+ unsigned int len = strlen (target);
+ char *p = alloca (1 + len + 1);
+ p[0] = '%';
+ memcpy (p + 1, target, len + 1);
+ *names = strcache_add_len (p, len + 1);
+ *percents = *names;
}
- names = xmalloc (2 * sizeof (char *));
- percents = alloca (2 * sizeof (char *));
- names[0] = targname;
- percents[0] = targpercent;
- names[1] = percents[1] = 0;
-
if (source == 0)
deps = 0;
else
{
/* Construct the dependency name. */
- len = strlen (source);
- depname = xmalloc (1 + len + 1);
- depname[0] = '%';
- memcpy (depname + 1, source, len + 1);
+ unsigned int len = strlen (source);
+ char *p = alloca (1 + len + 1);
+ p[0] = '%';
+ memcpy (p + 1, source, len + 1);
deps = alloc_dep ();
- deps->name = depname;
+ deps->name = strcache_add_len (p, len + 1);
}
- create_pattern_rule (names, percents, 0, deps, cmds, 0);
+ create_pattern_rule (names, percents, 1, 0, deps, cmds, 0);
}
/* Convert old-style suffix rules to pattern rules.
- All rules for the suffixes on the .SUFFIXES list
- are converted and added to the chain of pattern rules. */
+ All rules for the suffixes on the .SUFFIXES list are converted and added to
+ the chain of pattern rules. */
void
convert_to_pattern (void)
{
- register struct dep *d, *d2;
- register struct file *f;
- register char *rulename;
- register unsigned int slen, s2len;
+ struct dep *d, *d2;
+ char *rulename;
- /* Compute maximum length of all the suffixes. */
+ /* We will compute every potential suffix rule (.x.y) from the list of
+ suffixes in the .SUFFIXES target's dependencies and see if it exists.
+ First find the longest of the suffixes. */
maxsuffix = 0;
for (d = suffix_file->deps; d != 0; d = d->next)
{
- register unsigned int namelen = strlen (dep_name (d));
- if (namelen > maxsuffix)
- maxsuffix = namelen;
+ unsigned int l = strlen (dep_name (d));
+ if (l > maxsuffix)
+ maxsuffix = l;
}
+ /* Space to construct the suffix rule target name. */
rulename = alloca ((maxsuffix * 2) + 1);
for (d = suffix_file->deps; d != 0; d = d->next)
{
+ unsigned int slen;
+
/* Make a rule that is just the suffix, with no deps or commands.
This rule exists solely to disqualify match-anything rules. */
convert_suffix_rule (dep_name (d), 0, 0);
- f = d->file;
- if (f->cmds != 0)
+ if (d->file->cmds != 0)
/* Record a pattern for this suffix's null-suffix rule. */
- convert_suffix_rule ("", dep_name (d), f->cmds);
+ convert_suffix_rule ("", dep_name (d), d->file->cmds);
- /* Record a pattern for each of this suffix's two-suffix rules. */
+ /* Add every other suffix to this one and see if it exists as a
+ two-suffix rule. */
slen = strlen (dep_name (d));
memcpy (rulename, dep_name (d), slen);
+
for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)
{
+ struct file *f;
+ unsigned int s2len;
+
s2len = strlen (dep_name (d2));
+ /* Can't build something from itself. */
if (slen == s2len && streq (dep_name (d), dep_name (d2)))
continue;
@@ -273,19 +274,18 @@ convert_to_pattern (void)
}
-/* Install the pattern rule RULE (whose fields have been filled in)
- at the end of the list (so that any rules previously defined
- will take precedence). If this rule duplicates a previous one
- (identical target and dependencies), the old one is replaced
- if OVERRIDE is nonzero, otherwise this new one is thrown out.
- When an old rule is replaced, the new one is put at the end of the
- list. Return nonzero if RULE is used; zero if not. */
+/* Install the pattern rule RULE (whose fields have been filled in) at the end
+ of the list (so that any rules previously defined will take precedence).
+ If this rule duplicates a previous one (identical target and dependencies),
+ the old one is replaced if OVERRIDE is nonzero, otherwise this new one is
+ thrown out. When an old rule is replaced, the new one is put at the end of
+ the list. Return nonzero if RULE is used; zero if not. */
-int
+static int
new_pattern_rule (struct rule *rule, int override)
{
- register struct rule *r, *lastrule;
- register unsigned int i, j;
+ struct rule *r, *lastrule;
+ unsigned int i, j;
rule->in_use = 0;
rule->terminal = 0;
@@ -295,15 +295,15 @@ new_pattern_rule (struct rule *rule, int override)
/* Search for an identical rule. */
lastrule = 0;
for (r = pattern_rules; r != 0; lastrule = r, r = r->next)
- for (i = 0; rule->targets[i] != 0; ++i)
+ for (i = 0; i < rule->num; ++i)
{
- for (j = 0; r->targets[j] != 0; ++j)
+ for (j = 0; j < r->num; ++j)
if (!streq (rule->targets[i], r->targets[j]))
break;
- if (r->targets[j] == 0)
- /* All the targets matched. */
+ /* If all the targets matched... */
+ if (j == r->num)
{
- register struct dep *d, *d2;
+ struct dep *d, *d2;
for (d = rule->deps, d2 = r->deps;
d != 0 && d2 != 0; d = d->next, d2 = d2->next)
if (!streq (dep_name (d), dep_name (d2)))
@@ -359,29 +359,21 @@ new_pattern_rule (struct rule *rule, int override)
void
install_pattern_rule (struct pspec *p, int terminal)
{
- register struct rule *r;
+ struct rule *r;
char *ptr;
r = xmalloc (sizeof (struct rule));
- r->targets = xmalloc (2 * sizeof (char *));
- r->suffixes = xmalloc (2 * sizeof (char *));
- r->lens = xmalloc (2 * sizeof (unsigned int));
-
- r->targets[1] = 0;
- r->suffixes[1] = 0;
- r->lens[1] = 0;
+ r->num = 1;
+ r->targets = xmalloc (sizeof (const char *));
+ r->suffixes = xmalloc (sizeof (const char *));
+ r->lens = xmalloc (sizeof (unsigned int));
r->lens[0] = strlen (p->target);
- /* These will all be string literals, but we malloc space for
- them anyway because somebody might want to free them later on. */
- r->targets[0] = savestring (p->target, r->lens[0]);
- r->suffixes[0] = find_percent (r->targets[0]);
- if (r->suffixes[0] == 0)
- /* Programmer-out-to-lunch error. */
- abort ();
- else
- ++r->suffixes[0];
+ r->targets[0] = p->target;
+ r->suffixes[0] = find_percent_cached (&r->targets[0]);
+ assert (r->suffixes[0] != NULL);
+ ++r->suffixes[0];
ptr = p->dep;
r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0',
@@ -410,21 +402,12 @@ static void
freerule (struct rule *rule, struct rule *lastrule)
{
struct rule *next = rule->next;
- register unsigned int i;
- register struct dep *dep;
-
- for (i = 0; rule->targets[i] != 0; ++i)
- free (rule->targets[i]);
+ struct dep *dep;
dep = rule->deps;
while (dep)
{
- struct dep *t;
-
- t = dep->next;
- /* We might leak dep->name here, but I'm not sure how to fix this: I
- think that pointer might be shared (e.g., in the file hash?) */
- dep->name = 0; /* Make sure free_dep does not free name. */
+ struct dep *t = dep->next;
free_dep (dep);
dep = t;
}
@@ -457,51 +440,36 @@ freerule (struct rule *rule, struct rule *lastrule)
last_pattern_rule = lastrule;
}
-/* Create a new pattern rule with the targets in the nil-terminated
- array TARGETS. If TARGET_PERCENTS is not nil, it is an array of
- pointers into the elements of TARGETS, where the `%'s are.
- The new rule has dependencies DEPS and commands from COMMANDS.
+/* Create a new pattern rule with the targets in the nil-terminated array
+ TARGETS. TARGET_PERCENTS is an array of pointers to the % in each element
+ of TARGETS. N is the number of items in the array (not counting the nil
+ element). The new rule has dependencies DEPS and commands from COMMANDS.
It is a terminal rule if TERMINAL is nonzero. This rule overrides
identical rules with different commands if OVERRIDE is nonzero.
- The storage for TARGETS and its elements is used and must not be freed
- until the rule is destroyed. The storage for TARGET_PERCENTS is not used;
- it may be freed. */
+ The storage for TARGETS and its elements and TARGET_PERCENTS is used and
+ must not be freed until the rule is destroyed. */
void
-create_pattern_rule (char **targets, char **target_percents,
- int terminal, struct dep *deps,
+create_pattern_rule (const char **targets, const char **target_percents,
+ unsigned int n, int terminal, struct dep *deps,
struct commands *commands, int override)
{
- unsigned int max_targets, i;
+ unsigned int i;
struct rule *r = xmalloc (sizeof (struct rule));
+ r->num = n;
r->cmds = commands;
r->deps = deps;
r->targets = targets;
+ r->suffixes = target_percents;
+ r->lens = xmalloc (n * sizeof (unsigned int));
- max_targets = 2;
- r->lens = xmalloc (2 * sizeof (unsigned int));
- r->suffixes = xmalloc (2 * sizeof (char *));
- for (i = 0; targets[i] != 0; ++i)
+ for (i = 0; i < n; ++i)
{
- if (i == max_targets - 1)
- {
- max_targets += 5;
- r->lens = xrealloc (r->lens, max_targets * sizeof (unsigned int));
- r->suffixes = xrealloc (r->suffixes, max_targets * sizeof (char *));
- }
r->lens[i] = strlen (targets[i]);
- r->suffixes[i] = (target_percents == 0 ? find_percent (targets[i])
- : target_percents[i]) + 1;
- if (r->suffixes[i] == 0)
- abort ();
- }
-
- if (i < max_targets - 1)
- {
- r->lens = xrealloc (r->lens, (i + 1) * sizeof (unsigned int));
- r->suffixes = xrealloc (r->suffixes, (i + 1) * sizeof (char *));
+ assert (r->suffixes[i] != NULL);
+ ++r->suffixes[i];
}
if (new_pattern_rule (r, override))
@@ -513,16 +481,13 @@ create_pattern_rule (char **targets, char **target_percents,
static void /* Useful to call from gdb. */
print_rule (struct rule *r)
{
- register unsigned int i;
- register struct dep *d;
+ unsigned int i;
+ struct dep *d;
- for (i = 0; r->targets[i] != 0; ++i)
+ for (i = 0; i < r->num; ++i)
{
fputs (r->targets[i], stdout);
- if (r->targets[i + 1] != 0)
- putchar (' ');
- else
- putchar (':');
+ putchar ((i + 1 == r->num) ? ':' : ' ');
}
if (r->terminal)
putchar (':');
@@ -538,8 +503,8 @@ print_rule (struct rule *r)
void
print_rule_data_base (void)
{
- register unsigned int rules, terminal;
- register struct rule *r;
+ unsigned int rules, terminal;
+ struct rule *r;
puts (_("\n# Implicit Rules"));
diff --git a/rule.h b/rule.h
index 91378f6..16b4d51 100644
--- a/rule.h
+++ b/rule.h
@@ -16,16 +16,18 @@ 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
-/* Structure used for pattern rules. */
+
+/* Structure used for pattern (implicit) rules. */
struct rule
{
struct rule *next;
- char **targets; /* Targets of the rule. */
+ const char **targets; /* Targets of the rule. */
unsigned int *lens; /* Lengths of each target. */
- char **suffixes; /* Suffixes (after `%') of each target. */
+ const char **suffixes; /* Suffixes (after `%') of each target. */
struct dep *deps; /* Dependencies of the rule. */
struct commands *cmds; /* Commands to execute. */
+ unsigned short num; /* Number of targets. */
char terminal; /* If terminal (double-colon). */
char in_use; /* If in use by a parent pattern_search. */
};
@@ -49,10 +51,9 @@ extern struct file *suffix_file;
extern unsigned int maxsuffix;
-void install_pattern_rule (struct pspec *p, int terminal);
-int new_pattern_rule (struct rule *rule, int override);
void count_implicit_rule_limits (void);
void convert_to_pattern (void);
-void create_pattern_rule (char **targets, char **target_percents,
- int terminal, struct dep *deps,
+void install_pattern_rule (struct pspec *p, int terminal);
+void create_pattern_rule (const char **targets, const char **target_percents,
+ unsigned int num, int terminal, struct dep *deps,
struct commands *commands, int override);
diff --git a/strcache.c b/strcache.c
index 5b72399..8065194 100644
--- a/strcache.c
+++ b/strcache.c
@@ -20,8 +20,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "hash.h"
-/* The size (in bytes) of each cache buffer. */
-#define CACHE_BUFFER_SIZE (4096)
+/* The size (in bytes) of each cache buffer.
+ Try to pick something that will map well into the heap. */
+#define CACHE_BUFFER_SIZE (8192 - 16)
/* A string cached here will never be freed, so we don't need to worry about
@@ -39,6 +40,11 @@ struct strcache {
static int bufsize = CACHE_BUFFER_SIZE;
static struct strcache *strcache = NULL;
+/* Add a new buffer to the cache. Add it at the front to reduce search time.
+ This can also increase the overhead, since it's less likely that older
+ buffers will be filled in. However, GNU make has so many smaller strings
+ that this doesn't seem to be much of an issue in practice.
+ */
static struct strcache *
new_cache()
{
@@ -61,9 +67,9 @@ add_string(const char *str, int len)
struct strcache *sp;
const char *res;
- /* If the string we want is too large to fit into a single buffer, then we're
- screwed; nothing will ever fit! Change the maximum size of the cache to
- be big enough. */
+ /* If the string we want is too large to fit into a single buffer, then
+ we're screwed; nothing will ever fit! Change the maximum size of the
+ cache to be big enough. */
if (len > bufsize)
bufsize = len * 2;
@@ -113,6 +119,7 @@ str_hash_cmp (const void *x, const void *y)
}
static struct hash_table strings;
+static unsigned long total_adds = 0;
static const char *
add_hash (const char *str, int len)
@@ -121,6 +128,9 @@ add_hash (const char *str, int len)
char *const *slot = (char *const *) hash_find_slot (&strings, str);
const char *key = *slot;
+ /* Count the total number of adds we performed. */
+ ++total_adds;
+
if (!HASH_VACANT (key))
return key;
@@ -179,7 +189,7 @@ strcache_setbufsize(int size)
void
strcache_init (void)
{
- hash_init (&strings, 1000, str_hash_1, str_hash_2, str_hash_cmp);
+ hash_init (&strings, 8000, str_hash_1, str_hash_2, str_hash_cmp);
}
@@ -191,32 +201,46 @@ strcache_print_stats (const char *prefix)
int numbuffs = 0, numstrs = 0;
int totsize = 0, avgsize, maxsize = 0, minsize = bufsize;
int totfree = 0, avgfree, maxfree = 0, minfree = bufsize;
- const struct strcache *sp;
+ int lastused = 0, lastfree = 0;
- for (sp = strcache; sp != NULL; sp = sp->next)
+ if (strcache)
{
- int bf = sp->bytesfree;
- int sz = (sp->end - sp->buffer) + bf;
+ const struct strcache *sp;
+
+ /* Count the first buffer separately since it's not full. */
+ lastused = strcache->end - strcache->buffer;
+ lastfree = strcache->bytesfree;
+
+ for (sp = strcache->next; sp != NULL; sp = sp->next)
+ {
+ int bf = sp->bytesfree;
+ int sz = sp->end - sp->buffer;
- ++numbuffs;
- numstrs += sp->count;
+ ++numbuffs;
+ numstrs += sp->count;
- totsize += sz;
- maxsize = (sz > maxsize ? sz : maxsize);
- minsize = (sz < minsize ? sz : minsize);
+ totsize += sz;
+ maxsize = (sz > maxsize ? sz : maxsize);
+ minsize = (sz < minsize ? sz : minsize);
- totfree += bf;
- maxfree = (bf > maxfree ? bf : maxfree);
- minfree = (bf < minfree ? bf : minfree);
+ totfree += bf;
+ maxfree = (bf > maxfree ? bf : maxfree);
+ minfree = (bf < minfree ? bf : minfree);
+ }
}
avgsize = numbuffs ? (int)(totsize / numbuffs) : 0;
avgfree = numbuffs ? (int)(totfree / numbuffs) : 0;
- printf (_("\n%s # of strings in strcache: %d\n"), prefix, numstrs);
- printf (_("%s # of strcache buffers: %d\n"), prefix, numbuffs);
- printf (_("%s strcache size: total = %d / max = %d / min = %d / avg = %d\n"),
- prefix, totsize, maxsize, minsize, avgsize);
- printf (_("%s strcache free: total = %d / max = %d / min = %d / avg = %d\n"),
- prefix, totfree, maxfree, minfree, avgfree);
+ printf (_("\n%s # of strings in strcache: %d / lookups = %lu / hits = %lu\n"),
+ prefix, numstrs, total_adds, (total_adds - numstrs));
+ printf (_("%s # of strcache buffers: %d (* %d B/buffer = %d B)\n"),
+ prefix, (numbuffs + 1), bufsize, ((numbuffs + 1) * bufsize));
+ printf (_("%s strcache used: total = %d (%d) / max = %d / min = %d / avg = %d\n"),
+ prefix, totsize, lastused, maxsize, minsize, avgsize);
+ printf (_("%s strcache free: total = %d (%d) / max = %d / min = %d / avg = %d\n"),
+ prefix, totfree, lastfree, maxfree, minfree, avgfree);
+
+ fputs (_("\n# strcache hash-table stats:\n# "), stdout);
+ hash_print_stats (&strings, stdout);
}
diff --git a/tests/run_make_tests.pl b/tests/run_make_tests.pl
index 0419fef..82e7c38 100755
--- a/tests/run_make_tests.pl
+++ b/tests/run_make_tests.pl
@@ -190,7 +190,8 @@ sub run_make_with_options {
sub print_usage
{
- &print_standard_usage ("run_make_tests", "[-make_path make_pathname]");
+ &print_standard_usage ("run_make_tests",
+ "[-make_path make_pathname] [-valgrind]",);
}
sub print_help
diff --git a/tests/scripts/features/patternrules b/tests/scripts/features/patternrules
index 90525ae..53ec704 100644
--- a/tests/scripts/features/patternrules
+++ b/tests/scripts/features/patternrules
@@ -10,9 +10,9 @@ $dir = cwd;
$dir =~ s,.*/([^/]+)$,../$1,;
-# TEST #1: Make sure that multiple patterns where the same target
-# can be built are searched even if the first one fails
-# to match properly.
+# TEST #0: Make sure that multiple patterns where the same target
+# can be built are searched even if the first one fails
+# to match properly.
#
run_make_test('
@@ -45,7 +45,7 @@ a: void
'',
'');
-# TEST #2: make sure files that are built via implicit rules are marked
+# TEST #1: make sure files that are built via implicit rules are marked
# as targets (Savannah bug #12202).
#
run_make_test('
@@ -69,7 +69,7 @@ foo.in: ; @:
foo.out');
-# TEST #3: make sure intermidite files that also happened to be
+# TEST #2: make sure intermediate files that also happened to be
# prerequisites are not removed (Savannah bug #12267).
#
run_make_test('
@@ -96,7 +96,7 @@ $dir/foo.o");
unlink("$dir/foo.c");
-# TEST #4: make sure precious flag is set properly for targets
+# TEST #3: make sure precious flag is set properly for targets
# that are built via implicit rules (Savannah bug #13218).
#
run_make_test('
@@ -116,7 +116,7 @@ $(dir)/foo.bar:
unlink("$dir/foo.bar");
-# TEST #5: make sure targets of a macthed implicit pattern rule never
+# TEST #4: make sure targets of a matched implicit pattern rule are
# never considered intermediate (Savannah bug #13022).
#
run_make_test('
diff --git a/tests/test_driver.pl b/tests/test_driver.pl
index dd1b33b..cefe80f 100644
--- a/tests/test_driver.pl
+++ b/tests/test_driver.pl
@@ -547,12 +547,10 @@ sub print_standard_usage
local($plname,@moreusage) = @_;
local($line);
- print "Usage: perl $plname [testname] [-verbose] [-detail] [-keep]\n";
- print " [-profile] [-usage] [-help] "
- . "[-debug]\n";
- foreach $line (@moreusage)
- {
- print " $line\n";
+ print "usage:\t$plname [testname] [-verbose] [-detail] [-keep]\n";
+ print "\t\t\t[-profile] [-usage] [-help] [-debug]\n";
+ foreach (@moreusage) {
+ print "\t\t\t$_\n";
}
}
diff --git a/variable.c b/variable.c
index 8a82a3f..b564614 100644
--- a/variable.c
+++ b/variable.c
@@ -42,7 +42,7 @@ static struct pattern_var *last_pattern_var;
/* Create a new pattern-specific variable struct. */
struct pattern_var *
-create_pattern_var (char *target, char *suffix)
+create_pattern_var (const char *target, const char *suffix)
{
register struct pattern_var *p = xmalloc (sizeof (struct pattern_var));
@@ -63,14 +63,14 @@ create_pattern_var (char *target, char *suffix)
/* Look up a target in the pattern-specific variable list. */
static struct pattern_var *
-lookup_pattern_var (struct pattern_var *start, char *target)
+lookup_pattern_var (struct pattern_var *start, const char *target)
{
struct pattern_var *p;
unsigned int targlen = strlen(target);
for (p = start ? start->next : pattern_vars; p != 0; p = p->next)
{
- char *stem;
+ const char *stem;
unsigned int stemlen;
if (p->len > targlen)
@@ -962,7 +962,7 @@ target_environment (struct file *file)
strcmp(v->name, "PATH") == 0)
convert_Path_to_windows32(value, ';');
#endif
- *result++ = concat (v->name, "=", value);
+ *result++ = xstrdup (concat (v->name, "=", value));
free (value);
}
else
@@ -972,7 +972,7 @@ target_environment (struct file *file)
strcmp(v->name, "PATH") == 0)
convert_Path_to_windows32(v->value, ';');
#endif
- *result++ = concat (v->name, "=", v->value);
+ *result++ = xstrdup (concat (v->name, "=", v->value));
}
}
@@ -990,10 +990,11 @@ target_environment (struct file *file)
struct variable *
do_variable_definition (const struct floc *flocp, const char *varname,
- char *value, enum variable_origin origin,
+ const char *value, enum variable_origin origin,
enum variable_flavor flavor, int target_var)
{
- char *p, *alloc_value = NULL;
+ const char *p;
+ char *alloc_value = NULL;
struct variable *v;
int append = 0;
int conditional = 0;
@@ -1058,7 +1059,8 @@ do_variable_definition (const struct floc *flocp, const char *varname,
/* Paste the old and new values together in VALUE. */
unsigned int oldlen, vallen;
- char *val;
+ const char *val;
+ char *tp;
val = value;
if (v->recursive)
@@ -1075,10 +1077,11 @@ do_variable_definition (const struct floc *flocp, const char *varname,
oldlen = strlen (v->value);
vallen = strlen (val);
- p = alloca (oldlen + 1 + vallen + 1);
- memcpy (p, v->value, oldlen);
- p[oldlen] = ' ';
- memcpy (&p[oldlen + 1], val, vallen + 1);
+ tp = alloca (oldlen + 1 + vallen + 1);
+ memcpy (tp, v->value, oldlen);
+ tp[oldlen] = ' ';
+ memcpy (&tp[oldlen + 1], val, vallen + 1);
+ p = tp;
}
}
}
@@ -1106,20 +1109,19 @@ do_variable_definition (const struct floc *flocp, const char *varname,
/* See if we can find "/bin/sh.exe", "/bin/sh.com", etc. */
if (__dosexec_find_on_path (p, NULL, shellpath))
{
- char *p;
+ char *tp;
+
+ for (tp = shellpath; *tp; tp++)
+ if (*tp == '\\')
+ *tp = '/';
- for (p = shellpath; *p; p++)
- {
- if (*p == '\\')
- *p = '/';
- }
v = define_variable_loc (varname, strlen (varname),
shellpath, origin, flavor == f_recursive,
flocp);
}
else
{
- char *shellbase, *bslash;
+ const char *shellbase, *bslash;
struct variable *pathv = lookup_variable ("PATH", 4);
char *path_string;
char *fake_env[2];
@@ -1147,13 +1149,12 @@ do_variable_definition (const struct floc *flocp, const char *varname,
fake_env[1] = 0;
if (__dosexec_find_on_path (shellbase, fake_env, shellpath))
{
- char *p;
+ char *tp;
+
+ for (tp = shellpath; *tp; tp++)
+ if (*tp == '\\')
+ *tp = '/';
- for (p = shellpath; *p; p++)
- {
- if (*p == '\\')
- *p = '/';
- }
v = define_variable_loc (varname, strlen (varname),
shellpath, origin,
flavor == f_recursive, flocp);
@@ -1473,7 +1474,7 @@ print_variable_data_base (void)
/* Print all the local variables of FILE. */
void
-print_file_variables (struct file *file)
+print_file_variables (const struct file *file)
{
if (file->variables != 0)
print_variable_set (file->variables->set, "# ");
@@ -1500,7 +1501,7 @@ sync_Path_environment (void)
* Create something WINDOWS32 world can grok
*/
convert_Path_to_windows32 (path, ';');
- environ_path = concat ("PATH", "=", path);
+ environ_path = xstrdup (concat ("PATH", "=", path));
putenv (environ_path);
free (path);
}
diff --git a/variable.h b/variable.h
index 937a88e..61ee6be 100644
--- a/variable.h
+++ b/variable.h
@@ -99,9 +99,9 @@ struct variable_set_list
struct pattern_var
{
struct pattern_var *next;
- char *target;
+ const char *suffix;
+ const char *target;
unsigned int len;
- char *suffix;
struct variable variable;
};
@@ -123,10 +123,13 @@ void restore_variable_buffer (char *buf, unsigned int len);
/* function.c */
int handle_function (char **op, const char **stringp);
int pattern_matches (const char *pattern, const char *percent, const char *str);
-char *subst_expand (char *o, char *text, char *subst, char *replace,
- unsigned int slen, unsigned int rlen, int by_word);
-char *patsubst_expand (char *o, char *text, char *pattern, char *replace,
- char *pattern_percent, char *replace_percent);
+char *subst_expand (char *o, const char *text, const char *subst,
+ const char *replace, unsigned int slen, unsigned int rlen,
+ int by_word);
+char *patsubst_expand_pat (char *o, const char *text, const char *pattern,
+ const char *replace, const char *pattern_percent,
+ const char *replace_percent);
+char *patsubst_expand (char *o, const char *text, char *pattern, char *replace);
/* expand.c */
char *recursively_expand_for_file (struct variable *v, struct file *file);
@@ -139,12 +142,12 @@ struct variable_set_list *push_new_variable_scope (void);
void pop_variable_scope (void);
void define_automatic_variables (void);
void initialize_file_variables (struct file *file, int reading);
-void print_file_variables (struct file *file);
+void print_file_variables (const struct file *file);
void print_variable_set (struct variable_set *set, char *prefix);
void merge_variable_set_lists (struct variable_set_list **to_list,
struct variable_set_list *from_list);
struct variable *do_variable_definition (const struct floc *flocp,
- const char *name, char *value,
+ const char *name, const char *value,
enum variable_origin origin,
enum variable_flavor flavor,
int target_var);
@@ -198,7 +201,8 @@ struct variable *define_variable_in_set (const char *name, unsigned int length,
char **target_environment (struct file *file);
-struct pattern_var *create_pattern_var (char *target, char *suffix);
+struct pattern_var *create_pattern_var (const char *target,
+ const char *suffix);
extern int export_all_variables;
diff --git a/vpath.c b/vpath.c
index 992065b..4c79fcd 100644
--- a/vpath.c
+++ b/vpath.c
@@ -48,12 +48,10 @@ static struct vpath *general_vpath;
static struct vpath *gpaths;
-static int selective_vpath_search (struct vpath *path, char **file,
- FILE_TIMESTAMP *mtime_ptr);
-/* 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. */
+/* 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 ()
@@ -284,8 +282,8 @@ construct_vpath_list (char *pattern, char *dirpath)
/* Set up the members. */
path->pattern = strcache_add (pattern);
- path->percent = path->pattern + (percent - pattern);
path->patlen = strlen (pattern);
+ path->percent = percent ? path->pattern + (percent - pattern) : 0;
}
else
/* There were no entries, so free whatever space we allocated. */
@@ -308,57 +306,23 @@ gpath_search (const char *file, unsigned int len)
return 0;
}
-/* Search the VPATH list whose pattern matches *FILE for a directory
- where the name pointed to by FILE exists. If it is found, we set *FILE to
- the newly malloc'd name of the existing file, *MTIME_PTR (if MTIME_PTR is
- not NULL) to its modtime (or zero if no stat call was done), and return 1.
- Otherwise we return 0. */
-int
-vpath_search (char **file, FILE_TIMESTAMP *mtime_ptr)
-{
- struct vpath *v;
-
- /* If there are no VPATH entries or FILENAME starts at the root,
- there is nothing we can do. */
+/* Search the given VPATH list for a directory where the name pointed to by
+ FILE exists. If it is found, we return a cached name of the existing file
+ and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
+ stat call was done). Otherwise we return NULL. */
- if (**file == '/'
-#ifdef HAVE_DOS_PATHS
- || **file == '\\'
- || (*file)[1] == ':'
-#endif
- || (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, mtime_ptr))
- return 1;
-
- if (general_vpath != 0
- && selective_vpath_search (general_vpath, file, mtime_ptr))
- return 1;
-
- return 0;
-}
-
-
-/* Search the given VPATH list for a directory where the name pointed
- to by FILE exists. If it is found, we set *FILE to the newly malloc'd
- name of the existing file, *MTIME_PTR (if MTIME_PTR is not NULL) to
- its modtime (or zero if no stat call was done), and we return 1.
- Otherwise we return 0. */
-
-static int
-selective_vpath_search (struct vpath *path, char **file,
+static const char *
+selective_vpath_search (struct vpath *path, const char *file,
FILE_TIMESTAMP *mtime_ptr)
{
int not_target;
- char *name, *n;
- char *filename;
+ char *name;
+ const char *n;
+ const char *filename;
const char **vpath = path->searchpath;
unsigned int maxvpath = path->maxlen;
- register unsigned int i;
+ unsigned int i;
unsigned int flen, vlen, name_dplen;
int exists = 0;
@@ -366,73 +330,73 @@ selective_vpath_search (struct vpath *path, char **file,
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);
+ struct file *f = lookup_file (file);
not_target = f == 0 || !f->is_target;
}
- flen = strlen (*file);
+ 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. */
+ NAME_DPLEN gets the length of the prefix; FILENAME gets the pointer to
+ the name-within-directory and FLEN is its length. */
- n = strrchr (*file, '/');
+ n = strrchr (file, '/');
#ifdef HAVE_DOS_PATHS
/* We need the rightmost slash or backslash. */
{
- char *bslash = strrchr(*file, '\\');
+ const char *bslash = strrchr(file, '\\');
if (!n || bslash > n)
n = bslash;
}
#endif
- name_dplen = n != 0 ? n - *file : 0;
- filename = name_dplen > 0 ? n + 1 : *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 = xmalloc (maxvpath + 1 + name_dplen + 1 + flen + 1);
+ /* Get 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 = alloca (maxvpath + 1 + name_dplen + 1 + flen + 1);
/* Try each VPATH entry. */
for (i = 0; vpath[i] != 0; ++i)
{
int exists_in_cache = 0;
+ char *p;
- n = name;
+ p = name;
- /* Put the next VPATH entry into NAME at N and increment N past it. */
+ /* Put the next VPATH entry into NAME at P and increment P past it. */
vlen = strlen (vpath[i]);
- memcpy (n, vpath[i], vlen);
- n += vlen;
+ memcpy (p, vpath[i], vlen);
+ p += vlen;
/* Add the directory prefix already in *FILE. */
if (name_dplen > 0)
{
#ifndef VMS
- *n++ = '/';
+ *p++ = '/';
#endif
- memcpy (n, *file, name_dplen);
- n += name_dplen;
+ memcpy (p, file, name_dplen);
+ p += name_dplen;
}
#ifdef HAVE_DOS_PATHS
/* Cause the next if to treat backslash and slash alike. */
- if (n != name && n[-1] == '\\' )
- n[-1] = '/';
+ if (p != name && p[-1] == '\\' )
+ p[-1] = '/';
#endif
/* Now add the name-within-directory at the end of NAME. */
#ifndef VMS
- if (n != name && n[-1] != '/')
+ if (p != name && p[-1] != '/')
{
- *n = '/';
- memcpy (n + 1, filename, flen + 1);
+ *p = '/';
+ memcpy (p + 1, filename, flen + 1);
}
else
#endif
- memcpy (n, filename, flen + 1);
+ memcpy (p, filename, flen + 1);
/* Check if the file is mentioned in a makefile. If *FILE is not
a target, that is enough for us to decide this file exists.
@@ -479,7 +443,7 @@ selective_vpath_search (struct vpath *path, char **file,
#else
/* Clobber a null into the name at the last slash.
Now NAME is the name of the directory to look in. */
- *n = '\0';
+ *p = '\0';
/* We know the directory is in the hash table now because either
construct_vpath_list or the code just above put it there.
@@ -500,7 +464,7 @@ selective_vpath_search (struct vpath *path, char **file,
#ifndef VMS
/* Put the slash back in NAME. */
- *n = '/';
+ *p = '/';
#endif
if (exists_in_cache) /* Makefile-mentioned file need not exist. */
@@ -523,21 +487,56 @@ selective_vpath_search (struct vpath *path, char **file,
}
/* We have found a file.
- Store the name we found into *FILE for the caller. */
-
- *file = savestring (name, (n + 1 - name) + flen);
-
- /* If we get here and mtime_ptr hasn't been set, record
+ If we get here and mtime_ptr hasn't been set, record
UNKNOWN_MTIME to indicate this. */
if (mtime_ptr != 0)
*mtime_ptr = UNKNOWN_MTIME;
- free (name);
- return 1;
+ /* Store the name we found and return it. */
+
+ return strcache_add_len (name, (p + 1 - name) + flen);
}
}
- free (name);
+ return 0;
+}
+
+
+/* Search the VPATH list whose pattern matches FILE for a directory where FILE
+ exists. If it is found, return the cached name of an existing file, and
+ set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
+ stat call was done). Otherwise we return 0. */
+
+const char *
+vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr)
+{
+ struct vpath *v;
+
+ /* If there are no VPATH entries or FILENAME starts at the root,
+ there is nothing we can do. */
+
+ if (file[0] == '/'
+#ifdef HAVE_DOS_PATHS
+ || file[0] == '\\' || file[1] == ':'
+#endif
+ || (vpaths == 0 && general_vpath == 0))
+ return 0;
+
+ for (v = vpaths; v != 0; v = v->next)
+ if (pattern_matches (v->pattern, v->percent, file))
+ {
+ const char *p = selective_vpath_search (v, file, mtime_ptr);
+ if (p)
+ return p;
+ }
+
+ if (general_vpath != 0)
+ {
+ const char *p = selective_vpath_search (general_vpath, file, mtime_ptr);
+ if (p)
+ return p;
+ }
+
return 0;
}