mirror of
https://github.com/mirror/make.git
synced 2025-02-05 01:00:11 +08:00
- Add xcalloc() and call it
- Fix memory errors found by valgrind - Remove multi_glob() and empower parse_file_seq() to do its job: the goal here is to remove the confusing reverse/re-reverse we do on the file lists: needed for future fixes. - Add a prefix arg to parse_file_seq() - Make concat() variadic so it can take arbitrary #'s of strings
This commit is contained in:
parent
5abe477620
commit
8f30b68871
49
ChangeLog
49
ChangeLog
@ -1,3 +1,52 @@
|
|||||||
|
2009-09-16 Paul Smith <psmith@gnu.org>
|
||||||
|
|
||||||
|
* misc.c (alloc_dep, free_dep): Now that we have xcalloc(),
|
||||||
|
convert to macros.
|
||||||
|
* dep.h: Create alloc_dep() / free_dep() macros.
|
||||||
|
|
||||||
|
* implicit.c (pattern_search): Take advantage of the new
|
||||||
|
parse_file_seq() to add the directory prefix to each prereq.
|
||||||
|
|
||||||
|
* dep.h: Remove multi_glob() and enhance parse_file_seq() to do it
|
||||||
|
all. Avoid reversing chains. Support adding prefixes.
|
||||||
|
* read.c (parse_file_seq): Rewrite to support globbing. Allow for
|
||||||
|
cached/non-cached results.
|
||||||
|
(eval): Remove multi_glob() & invoke new parse_file_seq().
|
||||||
|
* rule.c (install_pattern_rule): Ditto.
|
||||||
|
* main.c (main): Ditto.
|
||||||
|
* implicit.c (pattern_search): Ditto.
|
||||||
|
* function.c (string_glob): Ditto.
|
||||||
|
* file.c (parse_prereqs): Ditto.
|
||||||
|
* default.c (set_default_suffixes): Ditto.
|
||||||
|
|
||||||
|
* variable.c (parse_variable_definition): Don't run off the end of
|
||||||
|
the string if it ends in whitespace (found with valgrind).
|
||||||
|
|
||||||
|
* commands.c (set_file_variables): Keep space for all targets in
|
||||||
|
$? if -B is given (found with valgrind).
|
||||||
|
|
||||||
|
2009-09-15 Paul Smith <psmith@gnu.org>
|
||||||
|
|
||||||
|
* misc.c (concat): Make concat() variadic so it takes >3 arguments.
|
||||||
|
(xcalloc): Add new function.
|
||||||
|
* make.h: New declarations.
|
||||||
|
|
||||||
|
* ar.c (ar_glob_match): New calling method for concat().
|
||||||
|
* main.c (main): Ditto.
|
||||||
|
(decode_env_switches): Ditto.
|
||||||
|
* read.c (eval_makefile): Ditto.
|
||||||
|
(tilde_expand): Ditto.
|
||||||
|
(parse_file_seq): Ditto.
|
||||||
|
* variable.c (target_environment): Ditto.
|
||||||
|
(sync_Path_environment): Ditto.
|
||||||
|
|
||||||
|
* ar.c (ar_glob_match): Use xcalloc().
|
||||||
|
* dir.c (file_impossible): Ditto.
|
||||||
|
* file.c (enter_file): Ditto.
|
||||||
|
* job.c (new_job): Ditto.
|
||||||
|
* read.c (parse_file_seq): Ditto.
|
||||||
|
* vmsfunctions.c (opendir): Ditto.
|
||||||
|
|
||||||
2009-09-14 Rafi Einstein <rafi.einstein@gmail.com> (tiny patch)
|
2009-09-14 Rafi Einstein <rafi.einstein@gmail.com> (tiny patch)
|
||||||
|
|
||||||
* w32/subproc/sub_proc.c (process_begin): Check *ep non-NULL
|
* w32/subproc/sub_proc.c (process_begin): Check *ep non-NULL
|
||||||
|
13
ar.c
13
ar.c
@ -196,9 +196,8 @@ ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED,
|
|||||||
if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0)
|
if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0)
|
||||||
{
|
{
|
||||||
/* We have a match. Add it to the chain. */
|
/* We have a match. Add it to the chain. */
|
||||||
struct nameseq *new = xmalloc (state->size);
|
struct nameseq *new = xcalloc (state->size);
|
||||||
memset (new, '\0', state->size);
|
new->name = strcache_add (concat (4, state->arname, "(", mem, ")"));
|
||||||
new->name = strcache_add (concat (state->arname, mem, ")"));
|
|
||||||
new->next = state->chain;
|
new->next = state->chain;
|
||||||
state->chain = new;
|
state->chain = new;
|
||||||
++state->n;
|
++state->n;
|
||||||
@ -249,7 +248,6 @@ ar_glob (const char *arname, const char *member_pattern, unsigned int size)
|
|||||||
struct ar_glob_state state;
|
struct ar_glob_state state;
|
||||||
struct nameseq *n;
|
struct nameseq *n;
|
||||||
const char **names;
|
const char **names;
|
||||||
char *name;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (! glob_pattern_p (member_pattern, 1))
|
if (! glob_pattern_p (member_pattern, 1))
|
||||||
@ -257,12 +255,7 @@ ar_glob (const char *arname, const char *member_pattern, unsigned int size)
|
|||||||
|
|
||||||
/* Scan the archive for matches.
|
/* Scan the archive for matches.
|
||||||
ar_glob_match will accumulate them in STATE.chain. */
|
ar_glob_match will accumulate them in STATE.chain. */
|
||||||
i = strlen (arname);
|
state.arname = arname;
|
||||||
name = alloca (i + 2);
|
|
||||||
memcpy (name, arname, i);
|
|
||||||
name[i] = '(';
|
|
||||||
name[i + 1] = '\0';
|
|
||||||
state.arname = name;
|
|
||||||
state.pattern = member_pattern;
|
state.pattern = member_pattern;
|
||||||
state.size = size;
|
state.size = size;
|
||||||
state.chain = 0;
|
state.chain = 0;
|
||||||
|
@ -181,7 +181,7 @@ set_file_variables (struct file *file)
|
|||||||
memcpy (cp, c, len);
|
memcpy (cp, c, len);
|
||||||
cp += len;
|
cp += len;
|
||||||
*cp++ = FILE_LIST_SEPARATOR;
|
*cp++ = FILE_LIST_SEPARATOR;
|
||||||
if (! d->changed)
|
if (! (d->changed || always_make_flag))
|
||||||
qmark_len -= len + 1; /* Don't space in $? for this one. */
|
qmark_len -= len + 1; /* Don't space in $? for this one. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,8 +543,7 @@ set_default_suffixes (void)
|
|||||||
{
|
{
|
||||||
char *p = default_suffixes;
|
char *p = default_suffixes;
|
||||||
suffix_file->deps = (struct dep *)
|
suffix_file->deps = (struct dep *)
|
||||||
multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
|
parse_file_seq (&p, sizeof (struct dep), '\0', NULL, 0);
|
||||||
sizeof (struct dep), 0);
|
|
||||||
define_variable ("SUFFIXES", 8, default_suffixes, o_default, 0);
|
define_variable ("SUFFIXES", 8, default_suffixes, o_default, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
dep.h
18
dep.h
@ -55,22 +55,30 @@ struct nameseq
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct nameseq *multi_glob (struct nameseq *chain, unsigned int size, int exists_only);
|
#define PARSEFS_NONE (0x0000)
|
||||||
|
#define PARSEFS_NOSTRIP (0x0001)
|
||||||
|
#define PARSEFS_NOGLOB (0x0002)
|
||||||
|
#define PARSEFS_EXISTS (0x0004)
|
||||||
|
#define PARSEFS_NOCACHE (0x0008)
|
||||||
|
|
||||||
#ifdef VMS
|
#ifdef VMS
|
||||||
struct nameseq *parse_file_seq ();
|
struct nameseq *parse_file_seq ();
|
||||||
#else
|
#else
|
||||||
struct nameseq *parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip);
|
struct nameseq *parse_file_seq (char **stringp, unsigned int size,
|
||||||
|
int stopchar, const char *prefix, int flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *tilde_expand (const char *name);
|
char *tilde_expand (const char *name);
|
||||||
|
|
||||||
#ifndef NO_ARCHIVES
|
#ifndef NO_ARCHIVES
|
||||||
struct nameseq *ar_glob (const char *arname, const char *member_pattern, unsigned int size);
|
struct nameseq *ar_glob (const char *arname, const char *member_pattern, unsigned int size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name)
|
#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name)
|
||||||
|
|
||||||
|
#define alloc_dep() (xcalloc (sizeof (struct dep)))
|
||||||
|
#define free_dep(_d) free (_d)
|
||||||
|
|
||||||
struct dep *alloc_dep (void);
|
|
||||||
void free_dep (struct dep *d);
|
|
||||||
struct dep *copy_dep_chain (const struct dep *d);
|
struct dep *copy_dep_chain (const struct dep *d);
|
||||||
void free_dep_chain (struct dep *d);
|
void free_dep_chain (struct dep *d);
|
||||||
void free_ns_chain (struct nameseq *n);
|
void free_ns_chain (struct nameseq *n);
|
||||||
|
6
file.c
6
file.c
@ -415,8 +415,7 @@ struct dep *
|
|||||||
parse_prereqs (char *p)
|
parse_prereqs (char *p)
|
||||||
{
|
{
|
||||||
struct dep *new = (struct dep *)
|
struct dep *new = (struct dep *)
|
||||||
multi_glob (parse_file_seq (&p, '|', sizeof (struct dep), 1),
|
parse_file_seq (&p, sizeof (struct dep), '|', NULL, 0);
|
||||||
sizeof (struct dep), 0);
|
|
||||||
|
|
||||||
if (*p)
|
if (*p)
|
||||||
{
|
{
|
||||||
@ -426,8 +425,7 @@ parse_prereqs (char *p)
|
|||||||
|
|
||||||
++p;
|
++p;
|
||||||
ood = (struct dep *)
|
ood = (struct dep *)
|
||||||
multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
|
parse_file_seq (&p, sizeof (struct dep), '\0', NULL, 0);
|
||||||
sizeof (struct dep), 0);
|
|
||||||
|
|
||||||
if (! new)
|
if (! new)
|
||||||
new = ood;
|
new = ood;
|
||||||
|
12
function.c
12
function.c
@ -355,13 +355,11 @@ string_glob (char *line)
|
|||||||
struct nameseq *chain;
|
struct nameseq *chain;
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
|
|
||||||
chain = multi_glob (parse_file_seq
|
chain = parse_file_seq (&line, sizeof (struct nameseq), '\0', NULL,
|
||||||
(&line, '\0', sizeof (struct nameseq),
|
/* We do not want parse_file_seq to strip `./'s.
|
||||||
/* We do not want parse_file_seq to strip `./'s.
|
That would break examples like:
|
||||||
That would break examples like:
|
$(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
|
||||||
$(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
|
PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS);
|
||||||
0),
|
|
||||||
sizeof (struct nameseq), 1);
|
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
|
34
implicit.c
34
implicit.c
@ -489,6 +489,7 @@ pattern_search (struct file *file, int archive,
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
const char *dir = NULL;
|
||||||
int add_dir = 0;
|
int add_dir = 0;
|
||||||
int had_stem = 0;
|
int had_stem = 0;
|
||||||
|
|
||||||
@ -570,6 +571,16 @@ pattern_search (struct file *file, int archive,
|
|||||||
p2 = depname;
|
p2 = depname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we need to add the directory prefix set it up. */
|
||||||
|
if (add_dir)
|
||||||
|
{
|
||||||
|
unsigned long l = lastslash - filename + 1;
|
||||||
|
char *n = alloca (l + 1);
|
||||||
|
memcpy (n, filename, l);
|
||||||
|
n[l] = '\0';
|
||||||
|
dir = n;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse the dependencies. */
|
/* Parse the dependencies. */
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@ -580,33 +591,16 @@ pattern_search (struct file *file, int archive,
|
|||||||
;
|
;
|
||||||
|
|
||||||
*id_ptr = (struct idep *)
|
*id_ptr = (struct idep *)
|
||||||
multi_glob (
|
parse_file_seq (&p2, sizeof (struct idep),
|
||||||
parse_file_seq (&p2,
|
order_only ? '\0' : '|', dir, 0);
|
||||||
order_only ? '\0' : '|',
|
|
||||||
sizeof (struct idep),
|
|
||||||
1), sizeof (struct idep), 0);
|
|
||||||
|
|
||||||
/* @@ It would be nice to teach parse_file_seq or
|
if (order_only || had_stem)
|
||||||
multi_glob to add prefix. This would save us some
|
|
||||||
reallocations. */
|
|
||||||
|
|
||||||
if (order_only || add_dir || had_stem)
|
|
||||||
{
|
{
|
||||||
unsigned long l = lastslash - filename + 1;
|
|
||||||
|
|
||||||
for (d = *id_ptr; d != 0; d = d->next)
|
for (d = *id_ptr; d != 0; d = d->next)
|
||||||
{
|
{
|
||||||
if (order_only)
|
if (order_only)
|
||||||
d->ignore_mtime = 1;
|
d->ignore_mtime = 1;
|
||||||
|
|
||||||
if (add_dir)
|
|
||||||
{
|
|
||||||
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)
|
if (had_stem)
|
||||||
d->had_stem = 1;
|
d->had_stem = 1;
|
||||||
}
|
}
|
||||||
|
13
main.c
13
main.c
@ -1312,7 +1312,7 @@ main (int argc, char **argv, char **envp)
|
|||||||
&& (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\') != 0)
|
&& (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\') != 0)
|
||||||
# endif
|
# endif
|
||||||
)
|
)
|
||||||
argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
|
argv[0] = xstrdup (concat (3, current_directory, "/", argv[0]));
|
||||||
#else /* !__MSDOS__ */
|
#else /* !__MSDOS__ */
|
||||||
if (current_directory[0] != '\0'
|
if (current_directory[0] != '\0'
|
||||||
&& argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0
|
&& argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0
|
||||||
@ -1321,7 +1321,7 @@ main (int argc, char **argv, char **envp)
|
|||||||
&& strchr (argv[0], '\\') != 0
|
&& strchr (argv[0], '\\') != 0
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
|
argv[0] = xstrdup (concat (3, current_directory, "/", argv[0]));
|
||||||
#endif /* !__MSDOS__ */
|
#endif /* !__MSDOS__ */
|
||||||
#endif /* WINDOWS32 */
|
#endif /* WINDOWS32 */
|
||||||
#endif
|
#endif
|
||||||
@ -2008,7 +2008,7 @@ main (int argc, char **argv, char **envp)
|
|||||||
/* This cast is OK since we never modify argv. */
|
/* This cast is OK since we never modify argv. */
|
||||||
argv[++i] = (char *) makefiles->list[j];
|
argv[++i] = (char *) makefiles->list[j];
|
||||||
else
|
else
|
||||||
argv[i] = xstrdup (concat ("-f", makefiles->list[j], ""));
|
argv[i] = xstrdup (concat (2, "-f", makefiles->list[j]));
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2019,7 +2019,7 @@ main (int argc, char **argv, char **envp)
|
|||||||
{
|
{
|
||||||
nargv = xmalloc ((nargc + 2) * sizeof (char *));
|
nargv = xmalloc ((nargc + 2) * sizeof (char *));
|
||||||
memcpy (nargv, argv, argc * sizeof (char *));
|
memcpy (nargv, argv, argc * sizeof (char *));
|
||||||
nargv[nargc++] = xstrdup (concat ("-o", stdin_nm, ""));
|
nargv[nargc++] = xstrdup (concat (2, "-o", stdin_nm));
|
||||||
nargv[nargc] = 0;
|
nargv[nargc] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2192,8 +2192,7 @@ main (int argc, char **argv, char **envp)
|
|||||||
{
|
{
|
||||||
struct nameseq *ns;
|
struct nameseq *ns;
|
||||||
|
|
||||||
ns = multi_glob (parse_file_seq (&p, '\0', sizeof (struct nameseq), 1),
|
ns = parse_file_seq (&p, sizeof (struct nameseq), '\0', NULL, 0);
|
||||||
sizeof (struct nameseq), 0);
|
|
||||||
if (ns)
|
if (ns)
|
||||||
{
|
{
|
||||||
/* .DEFAULT_GOAL should contain one target. */
|
/* .DEFAULT_GOAL should contain one target. */
|
||||||
@ -2670,7 +2669,7 @@ decode_env_switches (char *envar, unsigned int len)
|
|||||||
definition. Add a dash and pass it along to decode_switches. We
|
definition. Add a dash and pass it along to decode_switches. We
|
||||||
need permanent storage for this in case decode_switches saves
|
need permanent storage for this in case decode_switches saves
|
||||||
pointers into the value. */
|
pointers into the value. */
|
||||||
argv[1] = xstrdup (concat ("-", argv[1], ""));
|
argv[1] = xstrdup (concat (2, "-", argv[1]));
|
||||||
|
|
||||||
/* Parse those words. */
|
/* Parse those words. */
|
||||||
decode_switches (argc, argv, 1);
|
decode_switches (argc, argv, 1);
|
||||||
|
4
make.h
4
make.h
@ -368,6 +368,7 @@ struct floc
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
|
#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
|
||||||
|
const char *concat (unsigned int, ...);
|
||||||
void message (int prefix, const char *fmt, ...)
|
void message (int prefix, const char *fmt, ...)
|
||||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||||
void error (const struct floc *flocp, const char *fmt, ...)
|
void error (const struct floc *flocp, const char *fmt, ...)
|
||||||
@ -375,6 +376,7 @@ void error (const struct floc *flocp, const char *fmt, ...)
|
|||||||
void fatal (const struct floc *flocp, const char *fmt, ...)
|
void fatal (const struct floc *flocp, const char *fmt, ...)
|
||||||
__attribute__ ((noreturn, __format__ (__printf__, 2, 3)));
|
__attribute__ ((noreturn, __format__ (__printf__, 2, 3)));
|
||||||
#else
|
#else
|
||||||
|
const char *concat ();
|
||||||
void message ();
|
void message ();
|
||||||
void error ();
|
void error ();
|
||||||
void fatal ();
|
void fatal ();
|
||||||
@ -384,8 +386,8 @@ void die (int) __attribute__ ((noreturn));
|
|||||||
void log_working_directory (int);
|
void log_working_directory (int);
|
||||||
void pfatal_with_name (const char *) __attribute__ ((noreturn));
|
void pfatal_with_name (const char *) __attribute__ ((noreturn));
|
||||||
void perror_with_name (const char *, const char *);
|
void perror_with_name (const char *, const char *);
|
||||||
char *concat (const char *, const char *, const char *);
|
|
||||||
void *xmalloc (unsigned int);
|
void *xmalloc (unsigned int);
|
||||||
|
void *xcalloc (unsigned int);
|
||||||
void *xrealloc (void *, unsigned int);
|
void *xrealloc (void *, unsigned int);
|
||||||
char *xstrdup (const char *);
|
char *xstrdup (const char *);
|
||||||
char *xstrndup (const char *, unsigned int);
|
char *xstrndup (const char *, unsigned int);
|
||||||
|
85
misc.c
85
misc.c
@ -160,31 +160,49 @@ print_spaces (unsigned int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return a string whose contents concatenate those of s1, s2, s3.
|
/* Return a string whose contents concatenate the NUM strings provided
|
||||||
This string lives in static, re-used memory. */
|
This string lives in static, re-used memory. */
|
||||||
|
|
||||||
char *
|
const char *
|
||||||
concat (const char *s1, const char *s2, const char *s3)
|
#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
|
||||||
|
concat (unsigned int num, ...)
|
||||||
|
#else
|
||||||
|
concat (num, va_alist)
|
||||||
|
unsigned int num;
|
||||||
|
va_dcl
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
unsigned int len1, len2, len3;
|
|
||||||
static unsigned int rlen = 0;
|
static unsigned int rlen = 0;
|
||||||
static char *result = NULL;
|
static char *result = NULL;
|
||||||
|
int ri = 0;
|
||||||
|
|
||||||
len1 = (s1 && *s1 != '\0') ? strlen (s1) : 0;
|
#if USE_VARIADIC
|
||||||
len2 = (s2 && *s2 != '\0') ? strlen (s2) : 0;
|
va_list args;
|
||||||
len3 = (s3 && *s3 != '\0') ? strlen (s3) : 0;
|
#endif
|
||||||
|
|
||||||
if (len1 + len2 + len3 + 1 > rlen)
|
VA_START (args, num);
|
||||||
result = xrealloc (result, (rlen = len1 + len2 + len3 + 10));
|
|
||||||
|
|
||||||
if (len1)
|
while (num-- > 0)
|
||||||
memcpy (result, s1, len1);
|
{
|
||||||
if (len2)
|
const char *s = va_arg (args, const char *);
|
||||||
memcpy (result + len1, s2, len2);
|
unsigned int l = s ? strlen (s) : 0;
|
||||||
if (len3)
|
|
||||||
memcpy (result + len1 + len2, s3, len3);
|
|
||||||
|
|
||||||
result[len1+len2+len3] = '\0';
|
if (l == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ri + l > rlen)
|
||||||
|
{
|
||||||
|
rlen = ((rlen ? rlen : 60) + l) * 2;
|
||||||
|
result = xrealloc (result, rlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (result + ri, s, l);
|
||||||
|
ri += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
VA_END (args);
|
||||||
|
|
||||||
|
result[ri] = '\0';
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -337,13 +355,14 @@ pfatal_with_name (const char *name)
|
|||||||
#ifndef HAVE_DMALLOC_H
|
#ifndef HAVE_DMALLOC_H
|
||||||
|
|
||||||
#undef xmalloc
|
#undef xmalloc
|
||||||
|
#undef xcalloc
|
||||||
#undef xrealloc
|
#undef xrealloc
|
||||||
#undef xstrdup
|
#undef xstrdup
|
||||||
|
|
||||||
void *
|
void *
|
||||||
xmalloc (unsigned int size)
|
xmalloc (unsigned int size)
|
||||||
{
|
{
|
||||||
/* Make sure we don't allocate 0, for pre-ANSI libraries. */
|
/* Make sure we don't allocate 0, for pre-ISO implementations. */
|
||||||
void *result = malloc (size ? size : 1);
|
void *result = malloc (size ? size : 1);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
fatal (NILF, _("virtual memory exhausted"));
|
fatal (NILF, _("virtual memory exhausted"));
|
||||||
@ -351,12 +370,23 @@ xmalloc (unsigned int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
xcalloc (unsigned int size)
|
||||||
|
{
|
||||||
|
/* Make sure we don't allocate 0, for pre-ISO implementations. */
|
||||||
|
void *result = calloc (size ? size : 1, 1);
|
||||||
|
if (result == 0)
|
||||||
|
fatal (NILF, _("virtual memory exhausted"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
xrealloc (void *ptr, unsigned int size)
|
xrealloc (void *ptr, unsigned int size)
|
||||||
{
|
{
|
||||||
void *result;
|
void *result;
|
||||||
|
|
||||||
/* Some older implementations of realloc() don't conform to ANSI. */
|
/* Some older implementations of realloc() don't conform to ISO. */
|
||||||
if (! size)
|
if (! size)
|
||||||
size = 1;
|
size = 1;
|
||||||
result = ptr ? realloc (ptr, size) : malloc (size);
|
result = ptr ? realloc (ptr, size) : malloc (size);
|
||||||
@ -494,25 +524,6 @@ find_next_token (const char **ptr, unsigned int *lengthptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Allocate a new `struct dep' with all fields initialized to 0. */
|
|
||||||
|
|
||||||
struct dep *
|
|
||||||
alloc_dep ()
|
|
||||||
{
|
|
||||||
struct dep *d = xmalloc (sizeof (struct dep));
|
|
||||||
memset (d, '\0', sizeof (struct dep));
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Free `struct dep' along with `name' and `stem'. */
|
|
||||||
|
|
||||||
void
|
|
||||||
free_dep (struct dep *d)
|
|
||||||
{
|
|
||||||
free (d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy a chain of `struct dep', making a new chain
|
/* Copy a chain of `struct dep', making a new chain
|
||||||
with the same contents as the old one. */
|
with the same contents as the old one. */
|
||||||
|
|
||||||
|
590
read.c
590
read.c
@ -363,7 +363,8 @@ eval_makefile (const char *filename, int flags)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; include_directories[i] != 0; ++i)
|
for (i = 0; include_directories[i] != 0; ++i)
|
||||||
{
|
{
|
||||||
const char *included = concat (include_directories[i], "/", filename);
|
const char *included = concat (3, include_directories[i],
|
||||||
|
"/", filename);
|
||||||
ebuf.fp = fopen (included, "r");
|
ebuf.fp = fopen (included, "r");
|
||||||
if (ebuf.fp)
|
if (ebuf.fp)
|
||||||
{
|
{
|
||||||
@ -473,7 +474,7 @@ eval_buffer (char *buffer)
|
|||||||
Returns a pointer to the first non-modifier character, and sets VMOD
|
Returns a pointer to the first non-modifier character, and sets VMOD
|
||||||
based on the modifiers found if any, plus V_ASSIGN is 1.
|
based on the modifiers found if any, plus V_ASSIGN is 1.
|
||||||
*/
|
*/
|
||||||
char *
|
static char *
|
||||||
parse_var_assignment (const char *line, struct vmodifiers *vmod)
|
parse_var_assignment (const char *line, struct vmodifiers *vmod)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
@ -833,10 +834,8 @@ eval (struct ebuffer *ebuf, int set_default)
|
|||||||
|
|
||||||
/* Parse the list of file names. */
|
/* Parse the list of file names. */
|
||||||
p2 = p;
|
p2 = p;
|
||||||
files = multi_glob (parse_file_seq (&p2, '\0',
|
files = parse_file_seq (&p2, sizeof (struct nameseq), '\0',
|
||||||
sizeof (struct nameseq),
|
NULL, 0);
|
||||||
1),
|
|
||||||
sizeof (struct nameseq), 0);
|
|
||||||
free (p);
|
free (p);
|
||||||
|
|
||||||
/* Save the state of conditionals and start
|
/* Save the state of conditionals and start
|
||||||
@ -1020,10 +1019,8 @@ eval (struct ebuffer *ebuf, int set_default)
|
|||||||
/* Make the colon the end-of-string so we know where to stop
|
/* Make the colon the end-of-string so we know where to stop
|
||||||
looking for targets. */
|
looking for targets. */
|
||||||
*colonp = '\0';
|
*colonp = '\0';
|
||||||
filenames = multi_glob (parse_file_seq (&p2, '\0',
|
filenames = parse_file_seq (&p2, sizeof (struct nameseq), '\0',
|
||||||
sizeof (struct nameseq),
|
NULL, 0);
|
||||||
1),
|
|
||||||
sizeof (struct nameseq), 0);
|
|
||||||
*p2 = ':';
|
*p2 = ':';
|
||||||
|
|
||||||
if (!filenames)
|
if (!filenames)
|
||||||
@ -1146,7 +1143,8 @@ eval (struct ebuffer *ebuf, int set_default)
|
|||||||
if (p != 0)
|
if (p != 0)
|
||||||
{
|
{
|
||||||
struct nameseq *target;
|
struct nameseq *target;
|
||||||
target = parse_file_seq (&p2, ':', sizeof (struct nameseq), 1);
|
target = parse_file_seq (&p2, sizeof (struct nameseq), ':',
|
||||||
|
NULL, PARSEFS_NOGLOB|PARSEFS_NOCACHE);
|
||||||
++p2;
|
++p2;
|
||||||
if (target == 0)
|
if (target == 0)
|
||||||
fatal (fstart, _("missing target pattern"));
|
fatal (fstart, _("missing target pattern"));
|
||||||
@ -2302,239 +2300,6 @@ find_percent_cached (const char **string)
|
|||||||
return (*p == '\0') ? NULL : p;
|
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.
|
|
||||||
|
|
||||||
The string is passed as STRINGP, the address of a string pointer.
|
|
||||||
The string pointer is updated to point at the first character
|
|
||||||
not parsed, which either is a null char or equals STOPCHAR.
|
|
||||||
|
|
||||||
SIZE is how big to construct chain elements.
|
|
||||||
This is useful if we want them actually to be other structures
|
|
||||||
that have room for additional info.
|
|
||||||
|
|
||||||
If STRIP is nonzero, strip `./'s off the beginning. */
|
|
||||||
|
|
||||||
struct nameseq *
|
|
||||||
parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
|
|
||||||
{
|
|
||||||
struct nameseq *new = 0;
|
|
||||||
struct nameseq *new1, *lastnew1;
|
|
||||||
char *p = *stringp;
|
|
||||||
|
|
||||||
#ifdef VMS
|
|
||||||
# define VMS_COMMA ','
|
|
||||||
#else
|
|
||||||
# define VMS_COMMA 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
char *q;
|
|
||||||
|
|
||||||
/* Skip whitespace; see if any more names are left. */
|
|
||||||
p = next_token (p);
|
|
||||||
if (*p == '\0')
|
|
||||||
break;
|
|
||||||
if (*p == stopchar)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* There are, so find the end of the next name. */
|
|
||||||
q = p;
|
|
||||||
p = find_char_unquote (q, stopchar, VMS_COMMA, 1, 0);
|
|
||||||
#ifdef VMS
|
|
||||||
/* convert comma separated list to space separated */
|
|
||||||
if (p && *p == ',')
|
|
||||||
*p =' ';
|
|
||||||
#endif
|
|
||||||
#ifdef _AMIGA
|
|
||||||
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
|
|
||||||
first colon which isn't followed by a slash or a backslash.
|
|
||||||
Note that tokens separated by spaces should be treated as separate
|
|
||||||
tokens since make doesn't allow path names with spaces */
|
|
||||||
if (stopchar == ':')
|
|
||||||
while (p != 0 && !isspace ((unsigned char)*p) &&
|
|
||||||
(p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]))
|
|
||||||
p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0);
|
|
||||||
#endif
|
|
||||||
if (p == 0)
|
|
||||||
p = q + strlen (q);
|
|
||||||
|
|
||||||
if (strip)
|
|
||||||
#ifdef VMS
|
|
||||||
/* Skip leading `[]'s. */
|
|
||||||
while (p - q > 2 && q[0] == '[' && q[1] == ']')
|
|
||||||
#else
|
|
||||||
/* Skip leading `./'s. */
|
|
||||||
while (p - q > 2 && q[0] == '.' && q[1] == '/')
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
q += 2; /* Skip "./". */
|
|
||||||
while (q < p && *q == '/')
|
|
||||||
/* Skip following slashes: ".//foo" is "foo", not "/foo". */
|
|
||||||
++q;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract the filename just found, and skip it. */
|
|
||||||
|
|
||||||
if (q == p)
|
|
||||||
/* ".///" was stripped to "". */
|
|
||||||
#if defined(VMS)
|
|
||||||
continue;
|
|
||||||
#elif defined(_AMIGA)
|
|
||||||
name = "";
|
|
||||||
#else
|
|
||||||
name = "./";
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
#ifdef VMS
|
|
||||||
/* VMS filenames can have a ':' in them but they have to be '\'ed but we need
|
|
||||||
* to remove this '\' before we can use the filename.
|
|
||||||
* xstrdup called because q may be read-only string constant.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
char *qbase = xstrdup (q);
|
|
||||||
char *pbase = qbase + (p-q);
|
|
||||||
char *q1 = qbase;
|
|
||||||
char *q2 = q1;
|
|
||||||
char *p1 = pbase;
|
|
||||||
|
|
||||||
while (q1 != pbase)
|
|
||||||
{
|
|
||||||
if (*q1 == '\\' && *(q1+1) == ':')
|
|
||||||
{
|
|
||||||
q1++;
|
|
||||||
p1--;
|
|
||||||
}
|
|
||||||
*q2++ = *q1++;
|
|
||||||
}
|
|
||||||
name = strcache_add_len (qbase, p1 - qbase);
|
|
||||||
free (qbase);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
name = strcache_add_len (q, p - q);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Add it to the front of the chain. */
|
|
||||||
new1 = xmalloc (size);
|
|
||||||
memset (new1, '\0', size);
|
|
||||||
new1->name = name;
|
|
||||||
new1->next = new;
|
|
||||||
new = new1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NO_ARCHIVES
|
|
||||||
|
|
||||||
/* Look for multi-word archive references.
|
|
||||||
They are indicated by a elt ending with an unmatched `)' and
|
|
||||||
an elt further down the chain (i.e., previous in the file list)
|
|
||||||
with an unmatched `(' (e.g., "lib(mem"). */
|
|
||||||
|
|
||||||
new1 = new;
|
|
||||||
lastnew1 = 0;
|
|
||||||
while (new1 != 0)
|
|
||||||
if (new1->name[0] != '(' /* Don't catch "(%)" and suchlike. */
|
|
||||||
&& new1->name[strlen (new1->name) - 1] == ')'
|
|
||||||
&& strchr (new1->name, '(') == 0)
|
|
||||||
{
|
|
||||||
/* NEW1 ends with a `)' but does not contain a `('.
|
|
||||||
Look back for an elt with an opening `(' but no closing `)'. */
|
|
||||||
|
|
||||||
struct nameseq *n = new1->next, *lastn = new1;
|
|
||||||
char *paren = 0;
|
|
||||||
while (n != 0 && (paren = strchr (n->name, '(')) == 0)
|
|
||||||
{
|
|
||||||
lastn = n;
|
|
||||||
n = n->next;
|
|
||||||
}
|
|
||||||
if (n != 0
|
|
||||||
/* Ignore something starting with `(', as that cannot actually
|
|
||||||
be an archive-member reference (and treating it as such
|
|
||||||
results in an empty file name, which causes much lossage). */
|
|
||||||
&& n->name[0] != '(')
|
|
||||||
{
|
|
||||||
/* N is the first element in the archive group.
|
|
||||||
Its name looks like "lib(mem" (with no closing `)'). */
|
|
||||||
|
|
||||||
char *libname;
|
|
||||||
|
|
||||||
/* Copy "lib(" into LIBNAME. */
|
|
||||||
++paren;
|
|
||||||
libname = alloca (paren - n->name + 1);
|
|
||||||
memcpy (libname, n->name, paren - n->name);
|
|
||||||
libname[paren - n->name] = '\0';
|
|
||||||
|
|
||||||
if (*paren == '\0')
|
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
/* LASTN->next is the new stopping elt for the loop below. */
|
|
||||||
n = lastn->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Replace N's name with the full archive reference. */
|
|
||||||
n->name = strcache_add (concat (libname, paren, ")"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new1->name[1] == '\0')
|
|
||||||
{
|
|
||||||
/* NEW1 is just ")", part of something like "lib(a b )".
|
|
||||||
Omit it from the chain and free its storage. */
|
|
||||||
if (lastnew1 == 0)
|
|
||||||
new = new1->next;
|
|
||||||
else
|
|
||||||
lastnew1->next = new1->next;
|
|
||||||
lastn = new1;
|
|
||||||
new1 = new1->next;
|
|
||||||
free (lastn);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Replace also NEW1->name, which already has closing `)'. */
|
|
||||||
new1->name = strcache_add (concat (libname, new1->name, ""));
|
|
||||||
new1 = new1->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Trace back from NEW1 (the end of the list) until N
|
|
||||||
(the beginning of the list), rewriting each name
|
|
||||||
with the full archive reference. */
|
|
||||||
|
|
||||||
while (new1 != n)
|
|
||||||
{
|
|
||||||
new1->name = strcache_add (concat (libname, new1->name, ")"));
|
|
||||||
lastnew1 = new1;
|
|
||||||
new1 = new1->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No frobnication happening. Just step down the list. */
|
|
||||||
lastnew1 = new1;
|
|
||||||
new1 = new1->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastnew1 = new1;
|
|
||||||
new1 = new1->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*stringp = p;
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the next line of text in an eval buffer, combining continuation lines
|
/* Find the next line of text in an eval buffer, combining continuation lines
|
||||||
into one line.
|
into one line.
|
||||||
Return the number of actual lines read (> 1 if continuation lines).
|
Return the number of actual lines read (> 1 if continuation lines).
|
||||||
@ -3034,7 +2799,7 @@ tilde_expand (const char *name)
|
|||||||
# endif /* !AMIGA && !WINDOWS32 */
|
# endif /* !AMIGA && !WINDOWS32 */
|
||||||
if (home_dir != 0)
|
if (home_dir != 0)
|
||||||
{
|
{
|
||||||
char *new = xstrdup (concat (home_dir, "", name + 1));
|
char *new = xstrdup (concat (2, home_dir, name + 1));
|
||||||
if (is_variable)
|
if (is_variable)
|
||||||
free (home_dir);
|
free (home_dir);
|
||||||
return new;
|
return new;
|
||||||
@ -3053,7 +2818,7 @@ tilde_expand (const char *name)
|
|||||||
if (userend == 0)
|
if (userend == 0)
|
||||||
return xstrdup (pwent->pw_dir);
|
return xstrdup (pwent->pw_dir);
|
||||||
else
|
else
|
||||||
return xstrdup (concat (pwent->pw_dir, "/", userend + 1));
|
return xstrdup (concat (3, pwent->pw_dir, "/", userend + 1));
|
||||||
}
|
}
|
||||||
else if (userend != 0)
|
else if (userend != 0)
|
||||||
*userend = '/';
|
*userend = '/';
|
||||||
@ -3062,63 +2827,267 @@ tilde_expand (const char *name)
|
|||||||
#endif /* !VMS */
|
#endif /* !VMS */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse a string into a sequence of filenames represented as a chain of
|
||||||
|
struct nameseq's and return that chain. Optionally expand the strings via
|
||||||
|
glob().
|
||||||
|
|
||||||
/* Given a chain of struct nameseq's describing a sequence of filenames,
|
The string is passed as STRINGP, the address of a string pointer.
|
||||||
in reverse of the intended order, return a new chain describing the
|
The string pointer is updated to point at the first character
|
||||||
result of globbing the filenames. The new chain is in forward order.
|
not parsed, which either is a null char or equals STOPCHAR.
|
||||||
The links of the old chain are freed or used in the new chain.
|
|
||||||
Likewise for the names in the old chain.
|
|
||||||
|
|
||||||
SIZE is how big to construct chain elements.
|
SIZE is how big to construct chain elements.
|
||||||
This is useful if we want them actually to be other structures
|
This is useful if we want them actually to be other structures
|
||||||
that have room for additional info.
|
that have room for additional info.
|
||||||
|
|
||||||
If EXISTS_ONLY is true only return existing files. */
|
PREFIX, if non-null, is added to the beginning of each filename.
|
||||||
|
|
||||||
|
FLAGS allows one or more of the following bitflags to be set:
|
||||||
|
PARSEFS_NOSTRIP - Do no strip './'s off the beginning
|
||||||
|
PARSEFS_NOGLOB - Do not expand globbing characters
|
||||||
|
PARSEFS_EXISTS - Only return globbed files that actually exist
|
||||||
|
(cannot also set NOGLOB)
|
||||||
|
PARSEFS_NOCACHE - Do not add filenames to the strcache (caller frees)
|
||||||
|
*/
|
||||||
|
|
||||||
struct nameseq *
|
struct nameseq *
|
||||||
multi_glob (struct nameseq *chain, unsigned int size, int exists_only)
|
parse_file_seq (char **stringp, unsigned int size, int stopchar,
|
||||||
|
const char *prefix, int flags)
|
||||||
{
|
{
|
||||||
void dir_setup_glob (glob_t *);
|
extern void dir_setup_glob (glob_t *glob);
|
||||||
|
|
||||||
|
/* tmp points to tmpbuf after the prefix, if any.
|
||||||
|
tp is the end of the buffer. */
|
||||||
|
static char *tmpbuf = NULL;
|
||||||
|
static int tmpbuf_len = 0;
|
||||||
|
|
||||||
|
int cachep = (! (flags & PARSEFS_NOCACHE));
|
||||||
|
|
||||||
struct nameseq *new = 0;
|
struct nameseq *new = 0;
|
||||||
struct nameseq *old;
|
struct nameseq **newp = &new;
|
||||||
struct nameseq *nexto;
|
#define NEWELT(_n) do { \
|
||||||
|
const char *__n = (_n); \
|
||||||
|
*newp = xcalloc (size); \
|
||||||
|
(*newp)->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \
|
||||||
|
newp = &(*newp)->next; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
char *p;
|
||||||
glob_t gl;
|
glob_t gl;
|
||||||
|
char *tp;
|
||||||
|
|
||||||
dir_setup_glob (&gl);
|
#ifdef VMS
|
||||||
|
# define VMS_COMMA ','
|
||||||
|
#else
|
||||||
|
# define VMS_COMMA 0
|
||||||
|
#endif
|
||||||
|
|
||||||
for (old = chain; old != 0; old = nexto)
|
if (size < sizeof (struct nameseq))
|
||||||
|
size = sizeof (struct nameseq);
|
||||||
|
|
||||||
|
if (! (flags & PARSEFS_NOGLOB))
|
||||||
|
dir_setup_glob (&gl);
|
||||||
|
|
||||||
|
/* Get enough temporary space to construct the largest possible target. */
|
||||||
|
{
|
||||||
|
int l = strlen (*stringp) + 1;
|
||||||
|
if (l > tmpbuf_len)
|
||||||
|
{
|
||||||
|
tmpbuf = xrealloc (tmpbuf, l);
|
||||||
|
tmpbuf_len = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tp = tmpbuf;
|
||||||
|
|
||||||
|
/* Parse STRING. P will always point to the end of the parsed content. */
|
||||||
|
p = *stringp;
|
||||||
|
while (1)
|
||||||
{
|
{
|
||||||
int r;
|
const char *name;
|
||||||
const char **nlist = 0;
|
const char **nlist = 0;
|
||||||
int i = 0;
|
char *tildep = 0;
|
||||||
const char *gname;
|
|
||||||
#ifndef NO_ARCHIVES
|
#ifndef NO_ARCHIVES
|
||||||
char *arname = 0;
|
char *arname = 0;
|
||||||
char *memname = 0;
|
char *memname = 0;
|
||||||
#endif
|
#endif
|
||||||
nexto = old->next;
|
char *s;
|
||||||
gname = old->name;
|
int nlen;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (gname[0] == '~')
|
/* Skip whitespace; at the end of the string or STOPCHAR we're done. */
|
||||||
|
p = next_token (p);
|
||||||
|
if (*p == '\0' || *p == stopchar)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* There are names left, so find the end of the next name.
|
||||||
|
Throughout this iteration S points to the start. */
|
||||||
|
s = p;
|
||||||
|
p = find_char_unquote (p, stopchar, VMS_COMMA, 1, 0);
|
||||||
|
#ifdef VMS
|
||||||
|
/* convert comma separated list to space separated */
|
||||||
|
if (p && *p == ',')
|
||||||
|
*p =' ';
|
||||||
|
#endif
|
||||||
|
#ifdef _AMIGA
|
||||||
|
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
|
||||||
|
first colon which isn't followed by a slash or a backslash.
|
||||||
|
Note that tokens separated by spaces should be treated as separate
|
||||||
|
tokens since make doesn't allow path names with spaces */
|
||||||
|
if (stopchar == ':')
|
||||||
|
while (p != 0 && !isspace ((unsigned char)*p) &&
|
||||||
|
(p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]))
|
||||||
|
p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0);
|
||||||
|
#endif
|
||||||
|
if (p == 0)
|
||||||
|
p = s + strlen (s);
|
||||||
|
|
||||||
|
/* Strip leading "this directory" references. */
|
||||||
|
if (! (flags & PARSEFS_NOSTRIP))
|
||||||
|
#ifdef VMS
|
||||||
|
/* Skip leading `[]'s. */
|
||||||
|
while (p - s > 2 && s[0] == '[' && s[1] == ']')
|
||||||
|
#else
|
||||||
|
/* Skip leading `./'s. */
|
||||||
|
while (p - s > 2 && s[0] == '.' && s[1] == '/')
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Skip "./" and all following slashes. */
|
||||||
|
s += 2;
|
||||||
|
while (*s == '/')
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract the filename just found, and skip it.
|
||||||
|
Set NAME to the string, and NLEN to its length. */
|
||||||
|
|
||||||
|
if (s == p)
|
||||||
|
{
|
||||||
|
/* The name was stripped to empty ("./"). */
|
||||||
|
#if defined(VMS)
|
||||||
|
continue;
|
||||||
|
#elif defined(_AMIGA)
|
||||||
|
/* PDS-- This cannot be right!! */
|
||||||
|
tp[0] = '\0';
|
||||||
|
nlen = 0;
|
||||||
|
#else
|
||||||
|
tp[0] = '.';
|
||||||
|
tp[1] = '/';
|
||||||
|
tp[2] = '\0';
|
||||||
|
nlen = 2;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char *newname = tilde_expand (old->name);
|
#ifdef VMS
|
||||||
if (newname != 0)
|
/* VMS filenames can have a ':' in them but they have to be '\'ed but we need
|
||||||
gname = newname;
|
* to remove this '\' before we can use the filename.
|
||||||
|
* xstrdup called because S may be read-only string constant.
|
||||||
|
*/
|
||||||
|
char *n = tp;
|
||||||
|
while (s < p)
|
||||||
|
{
|
||||||
|
if (s[0] == '\\' && s[1] == ':')
|
||||||
|
++s;
|
||||||
|
*(n++) = *(s++);
|
||||||
|
}
|
||||||
|
n[0] = '\0';
|
||||||
|
nlen = strlen (tp);
|
||||||
|
#else
|
||||||
|
nlen = p - s;
|
||||||
|
memcpy (tp, s, nlen);
|
||||||
|
tp[nlen] = '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point, TP points to the element and NLEN is its length. */
|
||||||
|
|
||||||
|
#ifndef NO_ARCHIVES
|
||||||
|
/* If this is the start of an archive group that isn't complete, set up
|
||||||
|
to add the archive prefix for future files.
|
||||||
|
|
||||||
|
TP == TMP means we're not already in an archive group. Ignore
|
||||||
|
something starting with `(', as that cannot actually be an
|
||||||
|
archive-member reference (and treating it as such results in an empty
|
||||||
|
file name, which causes much lossage). Also if it ends in ")" then
|
||||||
|
it's a complete reference so we don't need to treat it specially. */
|
||||||
|
|
||||||
|
if (tp == tmpbuf && tp[0] != '(' && tp[nlen-1] != ')')
|
||||||
|
{
|
||||||
|
char *n = strchr (tp, '(');
|
||||||
|
if (n)
|
||||||
|
{
|
||||||
|
/* This is the first element in an open archive group. It looks
|
||||||
|
like "lib(mem". Remember the close paren. */
|
||||||
|
nlen -= (n + 1) - tp;
|
||||||
|
tp = n + 1;
|
||||||
|
|
||||||
|
/* If we have just "lib(", part of something like "lib( a b)",
|
||||||
|
go to the next item. */
|
||||||
|
if (! nlen)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are inside an archive group, make sure it has an end. */
|
||||||
|
if (tp > tmpbuf)
|
||||||
|
{
|
||||||
|
if (tp[nlen-1] == ')')
|
||||||
|
{
|
||||||
|
/* This is the natural end; reset TP. */
|
||||||
|
tp = tmpbuf;
|
||||||
|
|
||||||
|
/* This is just ")", something like "lib(a b )": skip it. */
|
||||||
|
if (nlen == 1)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not the end, so add a "fake" end. */
|
||||||
|
tp[nlen++] = ')';
|
||||||
|
tp[nlen] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If we're not globbing we're done: add it to the end of the chain.
|
||||||
|
Go to the next item in the string. */
|
||||||
|
if (flags & PARSEFS_NOGLOB)
|
||||||
|
{
|
||||||
|
NEWELT (concat (2, prefix, tp));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we get here we know we're doing glob expansion.
|
||||||
|
TP is a string in tmpbuf. NLEN is no longer used.
|
||||||
|
We may need to do more work: after this NAME will be set. */
|
||||||
|
name = tp;
|
||||||
|
|
||||||
|
/* Expand tilde if applicable. */
|
||||||
|
if (tp[0] == '~')
|
||||||
|
{
|
||||||
|
tildep = tilde_expand (tp);
|
||||||
|
if (tildep != 0)
|
||||||
|
name = tildep;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_ARCHIVES
|
#ifndef NO_ARCHIVES
|
||||||
if (ar_name (gname))
|
/* If 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. */
|
||||||
|
if (ar_name (name))
|
||||||
{
|
{
|
||||||
/* OLD->name is an archive member reference. Replace it with the
|
ar_parse_name (name, &arname, &memname);
|
||||||
archive file name, and save the member name in MEMNAME. We will
|
name = arname;
|
||||||
glob on the archive name and then reattach MEMNAME later. */
|
|
||||||
ar_parse_name (gname, &arname, &memname);
|
|
||||||
gname = arname;
|
|
||||||
}
|
}
|
||||||
#endif /* !NO_ARCHIVES */
|
#endif /* !NO_ARCHIVES */
|
||||||
|
|
||||||
r = glob (gname, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl);
|
switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl))
|
||||||
switch (r)
|
|
||||||
{
|
{
|
||||||
case GLOB_NOSPACE:
|
case GLOB_NOSPACE:
|
||||||
fatal (NILF, _("virtual memory exhausted"));
|
fatal (NILF, _("virtual memory exhausted"));
|
||||||
@ -3130,7 +3099,8 @@ multi_glob (struct nameseq *chain, unsigned int size, int exists_only)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GLOB_NOMATCH:
|
case GLOB_NOMATCH:
|
||||||
if (exists_only)
|
/* If we want only existing items, skip this one. */
|
||||||
|
if (flags & PARSEFS_EXISTS)
|
||||||
{
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
break;
|
break;
|
||||||
@ -3140,8 +3110,8 @@ multi_glob (struct nameseq *chain, unsigned int size, int exists_only)
|
|||||||
default:
|
default:
|
||||||
/* By default keep this name. */
|
/* By default keep this name. */
|
||||||
i = 1;
|
i = 1;
|
||||||
nlist = &gname;
|
nlist = &name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For each matched element, add it to the list. */
|
/* For each matched element, add it to the list. */
|
||||||
@ -3150,58 +3120,46 @@ multi_glob (struct nameseq *chain, unsigned int size, int exists_only)
|
|||||||
if (memname != 0)
|
if (memname != 0)
|
||||||
{
|
{
|
||||||
/* Try to glob on MEMNAME within the archive. */
|
/* Try to glob on MEMNAME within the archive. */
|
||||||
struct nameseq *found
|
struct nameseq *found = ar_glob (nlist[i], memname, size);
|
||||||
= ar_glob (nlist[i], memname, size);
|
|
||||||
if (! found)
|
if (! found)
|
||||||
{
|
/* No matches. Use MEMNAME as-is. */
|
||||||
/* No matches. Use MEMNAME as-is. */
|
NEWELT (concat (5, prefix, nlist[i], "(", memname, ")"));
|
||||||
unsigned int alen = strlen (nlist[i]);
|
|
||||||
unsigned int mlen = strlen (memname);
|
|
||||||
char *name;
|
|
||||||
struct nameseq *elt = xmalloc (size);
|
|
||||||
memset (elt, '\0', size);
|
|
||||||
|
|
||||||
name = alloca (alen + 1 + mlen + 2);
|
|
||||||
memcpy (name, nlist[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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Find the end of the FOUND chain. */
|
/* We got a chain of items. Attach them. */
|
||||||
struct nameseq *f = found;
|
(*newp)->next = found;
|
||||||
while (f->next != 0)
|
|
||||||
f = f->next;
|
|
||||||
|
|
||||||
/* Attach the chain being built to the end of the FOUND
|
/* Find and set the new end. Massage names if necessary. */
|
||||||
chain, and make FOUND the new NEW chain. */
|
while (1)
|
||||||
f->next = new;
|
{
|
||||||
new = found;
|
if (! cachep)
|
||||||
|
found->name = xstrdup (concat (2, prefix, name));
|
||||||
|
else if (prefix)
|
||||||
|
found->name = strcache_add (concat (2, prefix, name));
|
||||||
|
|
||||||
|
if (found->next == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
found = found->next;
|
||||||
|
}
|
||||||
|
newp = &found->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* !NO_ARCHIVES */
|
#endif /* !NO_ARCHIVES */
|
||||||
{
|
NEWELT (concat (2, prefix, nlist[i]));
|
||||||
struct nameseq *elt = xmalloc (size);
|
|
||||||
memset (elt, '\0', size);
|
globfree (&gl);
|
||||||
elt->name = strcache_add (nlist[i]);
|
|
||||||
elt->next = new;
|
|
||||||
new = elt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r == 0)
|
|
||||||
globfree (&gl);
|
|
||||||
free (old);
|
|
||||||
#ifndef NO_ARCHIVES
|
#ifndef NO_ARCHIVES
|
||||||
if (arname)
|
if (arname)
|
||||||
free (arname);
|
free (arname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (tildep)
|
||||||
|
free (tildep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*stringp = p;
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
2
remake.c
2
remake.c
@ -870,7 +870,7 @@ notice_finished_file (struct file *file)
|
|||||||
really check the target's mtime again. Otherwise, assume the target
|
really check the target's mtime again. Otherwise, assume the target
|
||||||
would have been updated. */
|
would have been updated. */
|
||||||
|
|
||||||
if (question_flag || just_print_flag || touch_flag && file->cmds != 0)
|
if ((question_flag || just_print_flag || touch_flag) && file->cmds)
|
||||||
{
|
{
|
||||||
for (i = file->cmds->ncommand_lines; i > 0; --i)
|
for (i = file->cmds->ncommand_lines; i > 0; --i)
|
||||||
if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE))
|
if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE))
|
||||||
|
5
rule.c
5
rule.c
@ -376,9 +376,8 @@ install_pattern_rule (struct pspec *p, int terminal)
|
|||||||
++r->suffixes[0];
|
++r->suffixes[0];
|
||||||
|
|
||||||
ptr = p->dep;
|
ptr = p->dep;
|
||||||
r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0',
|
r->deps = (struct dep *) parse_file_seq (&ptr, sizeof (struct dep), '\0',
|
||||||
sizeof (struct dep), 1),
|
NULL, 0);
|
||||||
sizeof (struct dep), 0);
|
|
||||||
|
|
||||||
if (new_pattern_rule (r, 0))
|
if (new_pattern_rule (r, 0))
|
||||||
{
|
{
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
$valgrind = 0; # invoke make with valgrind
|
$valgrind = 0; # invoke make with valgrind
|
||||||
$valgrind_args = '';
|
$valgrind_args = '';
|
||||||
$memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full';
|
$memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full';
|
||||||
$massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup';
|
$massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xcalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup';
|
||||||
$pure_log = undef;
|
$pure_log = undef;
|
||||||
|
|
||||||
$command_string = '';
|
$command_string = '';
|
||||||
|
14
variable.c
14
variable.c
@ -979,7 +979,7 @@ target_environment (struct file *file)
|
|||||||
strcmp(v->name, "PATH") == 0)
|
strcmp(v->name, "PATH") == 0)
|
||||||
convert_Path_to_windows32(value, ';');
|
convert_Path_to_windows32(value, ';');
|
||||||
#endif
|
#endif
|
||||||
*result++ = xstrdup (concat (v->name, "=", value));
|
*result++ = xstrdup (concat (3, v->name, "=", value));
|
||||||
free (value);
|
free (value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -989,7 +989,7 @@ target_environment (struct file *file)
|
|||||||
strcmp(v->name, "PATH") == 0)
|
strcmp(v->name, "PATH") == 0)
|
||||||
convert_Path_to_windows32(v->value, ';');
|
convert_Path_to_windows32(v->value, ';');
|
||||||
#endif
|
#endif
|
||||||
*result++ = xstrdup (concat (v->name, "=", v->value));
|
*result++ = xstrdup (concat (3, v->name, "=", v->value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1324,7 +1324,10 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
|
|||||||
{
|
{
|
||||||
wspace = 1;
|
wspace = 1;
|
||||||
p = next_token (p);
|
p = next_token (p);
|
||||||
c = *p++;
|
c = *p;
|
||||||
|
if (c == '\0')
|
||||||
|
return NULL;
|
||||||
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1333,8 +1336,9 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor)
|
|||||||
*flavor = f_recursive;
|
*flavor = f_recursive;
|
||||||
return (char *)p;
|
return (char *)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Match assignment variants (:=, +=, ?=) */
|
/* Match assignment variants (:=, +=, ?=) */
|
||||||
else if (*p == '=')
|
if (*p == '=')
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -1592,7 +1596,7 @@ sync_Path_environment (void)
|
|||||||
* Create something WINDOWS32 world can grok
|
* Create something WINDOWS32 world can grok
|
||||||
*/
|
*/
|
||||||
convert_Path_to_windows32 (path, ';');
|
convert_Path_to_windows32 (path, ';');
|
||||||
environ_path = xstrdup (concat ("PATH", "=", path));
|
environ_path = xstrdup (concat (3, "PATH", "=", path));
|
||||||
putenv (environ_path);
|
putenv (environ_path);
|
||||||
free (path);
|
free (path);
|
||||||
}
|
}
|
||||||
|
@ -34,13 +34,11 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||||||
DIR *
|
DIR *
|
||||||
opendir (char *dspec)
|
opendir (char *dspec)
|
||||||
{
|
{
|
||||||
struct DIR *dir = (struct DIR *)xmalloc (sizeof (struct DIR));
|
struct DIR *dir = xcalloc (sizeof (struct DIR));
|
||||||
struct NAM *dnam = (struct NAM *)xmalloc (sizeof (struct NAM));
|
struct NAM *dnam = xmalloc (sizeof (struct NAM));
|
||||||
struct FAB *dfab = &dir->fab;
|
struct FAB *dfab = &dir->fab;
|
||||||
char *searchspec = xmalloc (MAXNAMLEN + 1);
|
char *searchspec = xmalloc (MAXNAMLEN + 1);
|
||||||
|
|
||||||
memset (dir, 0, sizeof *dir);
|
|
||||||
|
|
||||||
*dfab = cc$rms_fab;
|
*dfab = cc$rms_fab;
|
||||||
*dnam = cc$rms_nam;
|
*dnam = cc$rms_nam;
|
||||||
sprintf (searchspec, "%s*.*;", dspec);
|
sprintf (searchspec, "%s*.*;", dspec);
|
||||||
|
Loading…
Reference in New Issue
Block a user