mirror of
https://github.com/mirror/make.git
synced 2025-01-26 20:30:36 +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)
|
||||
|
||||
* 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)
|
||||
{
|
||||
/* We have a match. Add it to the chain. */
|
||||
struct nameseq *new = xmalloc (state->size);
|
||||
memset (new, '\0', state->size);
|
||||
new->name = strcache_add (concat (state->arname, mem, ")"));
|
||||
struct nameseq *new = xcalloc (state->size);
|
||||
new->name = strcache_add (concat (4, state->arname, "(", mem, ")"));
|
||||
new->next = state->chain;
|
||||
state->chain = new;
|
||||
++state->n;
|
||||
@ -249,7 +248,6 @@ ar_glob (const char *arname, const char *member_pattern, unsigned int size)
|
||||
struct ar_glob_state state;
|
||||
struct nameseq *n;
|
||||
const char **names;
|
||||
char *name;
|
||||
unsigned int i;
|
||||
|
||||
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.
|
||||
ar_glob_match will accumulate them in STATE.chain. */
|
||||
i = strlen (arname);
|
||||
name = alloca (i + 2);
|
||||
memcpy (name, arname, i);
|
||||
name[i] = '(';
|
||||
name[i + 1] = '\0';
|
||||
state.arname = name;
|
||||
state.arname = arname;
|
||||
state.pattern = member_pattern;
|
||||
state.size = size;
|
||||
state.chain = 0;
|
||||
|
@ -181,7 +181,7 @@ set_file_variables (struct file *file)
|
||||
memcpy (cp, c, len);
|
||||
cp += len;
|
||||
*cp++ = FILE_LIST_SEPARATOR;
|
||||
if (! d->changed)
|
||||
if (! (d->changed || always_make_flag))
|
||||
qmark_len -= len + 1; /* Don't space in $? for this one. */
|
||||
}
|
||||
|
||||
|
@ -543,8 +543,7 @@ set_default_suffixes (void)
|
||||
{
|
||||
char *p = default_suffixes;
|
||||
suffix_file->deps = (struct dep *)
|
||||
multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
|
||||
sizeof (struct dep), 0);
|
||||
parse_file_seq (&p, sizeof (struct dep), '\0', NULL, 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
|
||||
struct nameseq *parse_file_seq ();
|
||||
#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
|
||||
|
||||
char *tilde_expand (const char *name);
|
||||
|
||||
#ifndef NO_ARCHIVES
|
||||
struct nameseq *ar_glob (const char *arname, const char *member_pattern, unsigned int size);
|
||||
#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);
|
||||
void free_dep_chain (struct dep *d);
|
||||
void free_ns_chain (struct nameseq *n);
|
||||
|
6
file.c
6
file.c
@ -415,8 +415,7 @@ struct dep *
|
||||
parse_prereqs (char *p)
|
||||
{
|
||||
struct dep *new = (struct dep *)
|
||||
multi_glob (parse_file_seq (&p, '|', sizeof (struct dep), 1),
|
||||
sizeof (struct dep), 0);
|
||||
parse_file_seq (&p, sizeof (struct dep), '|', NULL, 0);
|
||||
|
||||
if (*p)
|
||||
{
|
||||
@ -426,8 +425,7 @@ parse_prereqs (char *p)
|
||||
|
||||
++p;
|
||||
ood = (struct dep *)
|
||||
multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
|
||||
sizeof (struct dep), 0);
|
||||
parse_file_seq (&p, sizeof (struct dep), '\0', NULL, 0);
|
||||
|
||||
if (! new)
|
||||
new = ood;
|
||||
|
12
function.c
12
function.c
@ -355,13 +355,11 @@ string_glob (char *line)
|
||||
struct nameseq *chain;
|
||||
unsigned int idx;
|
||||
|
||||
chain = multi_glob (parse_file_seq
|
||||
(&line, '\0', sizeof (struct nameseq),
|
||||
/* We do not want parse_file_seq to strip `./'s.
|
||||
That would break examples like:
|
||||
$(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
|
||||
0),
|
||||
sizeof (struct nameseq), 1);
|
||||
chain = parse_file_seq (&line, sizeof (struct nameseq), '\0', NULL,
|
||||
/* We do not want parse_file_seq to strip `./'s.
|
||||
That would break examples like:
|
||||
$(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
|
||||
PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
|
34
implicit.c
34
implicit.c
@ -489,6 +489,7 @@ pattern_search (struct file *file, int archive,
|
||||
|
||||
while (1)
|
||||
{
|
||||
const char *dir = NULL;
|
||||
int add_dir = 0;
|
||||
int had_stem = 0;
|
||||
|
||||
@ -570,6 +571,16 @@ pattern_search (struct file *file, int archive,
|
||||
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. */
|
||||
|
||||
while (1)
|
||||
@ -580,33 +591,16 @@ pattern_search (struct file *file, int archive,
|
||||
;
|
||||
|
||||
*id_ptr = (struct idep *)
|
||||
multi_glob (
|
||||
parse_file_seq (&p2,
|
||||
order_only ? '\0' : '|',
|
||||
sizeof (struct idep),
|
||||
1), sizeof (struct idep), 0);
|
||||
parse_file_seq (&p2, sizeof (struct idep),
|
||||
order_only ? '\0' : '|', dir, 0);
|
||||
|
||||
/* @@ It would be nice to teach parse_file_seq or
|
||||
multi_glob to add prefix. This would save us some
|
||||
reallocations. */
|
||||
|
||||
if (order_only || add_dir || had_stem)
|
||||
if (order_only || had_stem)
|
||||
{
|
||||
unsigned long l = lastslash - filename + 1;
|
||||
|
||||
for (d = *id_ptr; d != 0; d = d->next)
|
||||
{
|
||||
if (order_only)
|
||||
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)
|
||||
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)
|
||||
# endif
|
||||
)
|
||||
argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
|
||||
argv[0] = xstrdup (concat (3, current_directory, "/", argv[0]));
|
||||
#else /* !__MSDOS__ */
|
||||
if (current_directory[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
|
||||
#endif
|
||||
)
|
||||
argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
|
||||
argv[0] = xstrdup (concat (3, current_directory, "/", argv[0]));
|
||||
#endif /* !__MSDOS__ */
|
||||
#endif /* WINDOWS32 */
|
||||
#endif
|
||||
@ -2008,7 +2008,7 @@ main (int argc, char **argv, char **envp)
|
||||
/* This cast is OK since we never modify argv. */
|
||||
argv[++i] = (char *) makefiles->list[j];
|
||||
else
|
||||
argv[i] = xstrdup (concat ("-f", makefiles->list[j], ""));
|
||||
argv[i] = xstrdup (concat (2, "-f", makefiles->list[j]));
|
||||
++j;
|
||||
}
|
||||
}
|
||||
@ -2019,7 +2019,7 @@ main (int argc, char **argv, char **envp)
|
||||
{
|
||||
nargv = xmalloc ((nargc + 2) * 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;
|
||||
}
|
||||
else
|
||||
@ -2192,8 +2192,7 @@ main (int argc, char **argv, char **envp)
|
||||
{
|
||||
struct nameseq *ns;
|
||||
|
||||
ns = multi_glob (parse_file_seq (&p, '\0', sizeof (struct nameseq), 1),
|
||||
sizeof (struct nameseq), 0);
|
||||
ns = parse_file_seq (&p, sizeof (struct nameseq), '\0', NULL, 0);
|
||||
if (ns)
|
||||
{
|
||||
/* .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
|
||||
need permanent storage for this in case decode_switches saves
|
||||
pointers into the value. */
|
||||
argv[1] = xstrdup (concat ("-", argv[1], ""));
|
||||
argv[1] = xstrdup (concat (2, "-", argv[1]));
|
||||
|
||||
/* Parse those words. */
|
||||
decode_switches (argc, argv, 1);
|
||||
|
4
make.h
4
make.h
@ -368,6 +368,7 @@ struct floc
|
||||
#endif
|
||||
|
||||
#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
|
||||
const char *concat (unsigned int, ...);
|
||||
void message (int prefix, const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
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, ...)
|
||||
__attribute__ ((noreturn, __format__ (__printf__, 2, 3)));
|
||||
#else
|
||||
const char *concat ();
|
||||
void message ();
|
||||
void error ();
|
||||
void fatal ();
|
||||
@ -384,8 +386,8 @@ void die (int) __attribute__ ((noreturn));
|
||||
void log_working_directory (int);
|
||||
void pfatal_with_name (const char *) __attribute__ ((noreturn));
|
||||
void perror_with_name (const char *, const char *);
|
||||
char *concat (const char *, const char *, const char *);
|
||||
void *xmalloc (unsigned int);
|
||||
void *xcalloc (unsigned int);
|
||||
void *xrealloc (void *, unsigned int);
|
||||
char *xstrdup (const char *);
|
||||
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. */
|
||||
|
||||
char *
|
||||
concat (const char *s1, const char *s2, const char *s3)
|
||||
const char *
|
||||
#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 char *result = NULL;
|
||||
int ri = 0;
|
||||
|
||||
len1 = (s1 && *s1 != '\0') ? strlen (s1) : 0;
|
||||
len2 = (s2 && *s2 != '\0') ? strlen (s2) : 0;
|
||||
len3 = (s3 && *s3 != '\0') ? strlen (s3) : 0;
|
||||
#if USE_VARIADIC
|
||||
va_list args;
|
||||
#endif
|
||||
|
||||
if (len1 + len2 + len3 + 1 > rlen)
|
||||
result = xrealloc (result, (rlen = len1 + len2 + len3 + 10));
|
||||
VA_START (args, num);
|
||||
|
||||
if (len1)
|
||||
memcpy (result, s1, len1);
|
||||
if (len2)
|
||||
memcpy (result + len1, s2, len2);
|
||||
if (len3)
|
||||
memcpy (result + len1 + len2, s3, len3);
|
||||
while (num-- > 0)
|
||||
{
|
||||
const char *s = va_arg (args, const char *);
|
||||
unsigned int l = s ? strlen (s) : 0;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -337,13 +355,14 @@ pfatal_with_name (const char *name)
|
||||
#ifndef HAVE_DMALLOC_H
|
||||
|
||||
#undef xmalloc
|
||||
#undef xcalloc
|
||||
#undef xrealloc
|
||||
#undef xstrdup
|
||||
|
||||
void *
|
||||
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);
|
||||
if (result == 0)
|
||||
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 *
|
||||
xrealloc (void *ptr, unsigned int size)
|
||||
{
|
||||
void *result;
|
||||
|
||||
/* Some older implementations of realloc() don't conform to ANSI. */
|
||||
/* Some older implementations of realloc() don't conform to ISO. */
|
||||
if (! size)
|
||||
size = 1;
|
||||
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
|
||||
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;
|
||||
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");
|
||||
if (ebuf.fp)
|
||||
{
|
||||
@ -473,7 +474,7 @@ eval_buffer (char *buffer)
|
||||
Returns a pointer to the first non-modifier character, and sets VMOD
|
||||
based on the modifiers found if any, plus V_ASSIGN is 1.
|
||||
*/
|
||||
char *
|
||||
static char *
|
||||
parse_var_assignment (const char *line, struct vmodifiers *vmod)
|
||||
{
|
||||
const char *p;
|
||||
@ -833,10 +834,8 @@ eval (struct ebuffer *ebuf, int set_default)
|
||||
|
||||
/* Parse the list of file names. */
|
||||
p2 = p;
|
||||
files = multi_glob (parse_file_seq (&p2, '\0',
|
||||
sizeof (struct nameseq),
|
||||
1),
|
||||
sizeof (struct nameseq), 0);
|
||||
files = parse_file_seq (&p2, sizeof (struct nameseq), '\0',
|
||||
NULL, 0);
|
||||
free (p);
|
||||
|
||||
/* 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
|
||||
looking for targets. */
|
||||
*colonp = '\0';
|
||||
filenames = multi_glob (parse_file_seq (&p2, '\0',
|
||||
sizeof (struct nameseq),
|
||||
1),
|
||||
sizeof (struct nameseq), 0);
|
||||
filenames = parse_file_seq (&p2, sizeof (struct nameseq), '\0',
|
||||
NULL, 0);
|
||||
*p2 = ':';
|
||||
|
||||
if (!filenames)
|
||||
@ -1146,7 +1143,8 @@ eval (struct ebuffer *ebuf, int set_default)
|
||||
if (p != 0)
|
||||
{
|
||||
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;
|
||||
if (target == 0)
|
||||
fatal (fstart, _("missing target pattern"));
|
||||
@ -2302,239 +2300,6 @@ find_percent_cached (const char **string)
|
||||
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
|
||||
into one line.
|
||||
Return the number of actual lines read (> 1 if continuation lines).
|
||||
@ -3034,7 +2799,7 @@ tilde_expand (const char *name)
|
||||
# endif /* !AMIGA && !WINDOWS32 */
|
||||
if (home_dir != 0)
|
||||
{
|
||||
char *new = xstrdup (concat (home_dir, "", name + 1));
|
||||
char *new = xstrdup (concat (2, home_dir, name + 1));
|
||||
if (is_variable)
|
||||
free (home_dir);
|
||||
return new;
|
||||
@ -3053,7 +2818,7 @@ tilde_expand (const char *name)
|
||||
if (userend == 0)
|
||||
return xstrdup (pwent->pw_dir);
|
||||
else
|
||||
return xstrdup (concat (pwent->pw_dir, "/", userend + 1));
|
||||
return xstrdup (concat (3, pwent->pw_dir, "/", userend + 1));
|
||||
}
|
||||
else if (userend != 0)
|
||||
*userend = '/';
|
||||
@ -3062,63 +2827,267 @@ tilde_expand (const char *name)
|
||||
#endif /* !VMS */
|
||||
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,
|
||||
in reverse of the intended order, return a new chain describing the
|
||||
result of globbing the filenames. The new chain is in forward order.
|
||||
The links of the old chain are freed or used in the new chain.
|
||||
Likewise for the names in the old 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 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 *
|
||||
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 *old;
|
||||
struct nameseq *nexto;
|
||||
struct nameseq **newp = &new;
|
||||
#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;
|
||||
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;
|
||||
int i = 0;
|
||||
const char *gname;
|
||||
char *tildep = 0;
|
||||
#ifndef NO_ARCHIVES
|
||||
char *arname = 0;
|
||||
char *memname = 0;
|
||||
#endif
|
||||
nexto = old->next;
|
||||
gname = old->name;
|
||||
char *s;
|
||||
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);
|
||||
if (newname != 0)
|
||||
gname = newname;
|
||||
#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 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
|
||||
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
|
||||
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;
|
||||
ar_parse_name (name, &arname, &memname);
|
||||
name = arname;
|
||||
}
|
||||
#endif /* !NO_ARCHIVES */
|
||||
|
||||
r = glob (gname, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl);
|
||||
switch (r)
|
||||
switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl))
|
||||
{
|
||||
case GLOB_NOSPACE:
|
||||
fatal (NILF, _("virtual memory exhausted"));
|
||||
@ -3130,7 +3099,8 @@ multi_glob (struct nameseq *chain, unsigned int size, int exists_only)
|
||||
break;
|
||||
|
||||
case GLOB_NOMATCH:
|
||||
if (exists_only)
|
||||
/* If we want only existing items, skip this one. */
|
||||
if (flags & PARSEFS_EXISTS)
|
||||
{
|
||||
i = 0;
|
||||
break;
|
||||
@ -3140,8 +3110,8 @@ multi_glob (struct nameseq *chain, unsigned int size, int exists_only)
|
||||
default:
|
||||
/* By default keep this name. */
|
||||
i = 1;
|
||||
nlist = &gname;
|
||||
break;
|
||||
nlist = &name;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Try to glob on MEMNAME within the archive. */
|
||||
struct nameseq *found
|
||||
= ar_glob (nlist[i], memname, size);
|
||||
struct nameseq *found = ar_glob (nlist[i], memname, size);
|
||||
if (! found)
|
||||
{
|
||||
/* No matches. Use MEMNAME as-is. */
|
||||
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;
|
||||
}
|
||||
/* No matches. Use MEMNAME as-is. */
|
||||
NEWELT (concat (5, prefix, nlist[i], "(", memname, ")"));
|
||||
else
|
||||
{
|
||||
/* Find the end of the FOUND chain. */
|
||||
struct nameseq *f = found;
|
||||
while (f->next != 0)
|
||||
f = f->next;
|
||||
/* We got a chain of items. Attach them. */
|
||||
(*newp)->next = found;
|
||||
|
||||
/* Attach the chain being built to the end of the FOUND
|
||||
chain, and make FOUND the new NEW chain. */
|
||||
f->next = new;
|
||||
new = found;
|
||||
/* Find and set the new end. Massage names if necessary. */
|
||||
while (1)
|
||||
{
|
||||
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
|
||||
#endif /* !NO_ARCHIVES */
|
||||
{
|
||||
struct nameseq *elt = xmalloc (size);
|
||||
memset (elt, '\0', size);
|
||||
elt->name = strcache_add (nlist[i]);
|
||||
elt->next = new;
|
||||
new = elt;
|
||||
}
|
||||
NEWELT (concat (2, prefix, nlist[i]));
|
||||
|
||||
globfree (&gl);
|
||||
|
||||
if (r == 0)
|
||||
globfree (&gl);
|
||||
free (old);
|
||||
#ifndef NO_ARCHIVES
|
||||
if (arname)
|
||||
free (arname);
|
||||
#endif
|
||||
|
||||
if (tildep)
|
||||
free (tildep);
|
||||
}
|
||||
|
||||
*stringp = p;
|
||||
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
|
||||
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)
|
||||
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];
|
||||
|
||||
ptr = p->dep;
|
||||
r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0',
|
||||
sizeof (struct dep), 1),
|
||||
sizeof (struct dep), 0);
|
||||
r->deps = (struct dep *) parse_file_seq (&ptr, sizeof (struct dep), '\0',
|
||||
NULL, 0);
|
||||
|
||||
if (new_pattern_rule (r, 0))
|
||||
{
|
||||
|
@ -32,7 +32,7 @@
|
||||
$valgrind = 0; # invoke make with valgrind
|
||||
$valgrind_args = '';
|
||||
$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;
|
||||
|
||||
$command_string = '';
|
||||
|
14
variable.c
14
variable.c
@ -979,7 +979,7 @@ target_environment (struct file *file)
|
||||
strcmp(v->name, "PATH") == 0)
|
||||
convert_Path_to_windows32(value, ';');
|
||||
#endif
|
||||
*result++ = xstrdup (concat (v->name, "=", value));
|
||||
*result++ = xstrdup (concat (3, v->name, "=", value));
|
||||
free (value);
|
||||
}
|
||||
else
|
||||
@ -989,7 +989,7 @@ target_environment (struct file *file)
|
||||
strcmp(v->name, "PATH") == 0)
|
||||
convert_Path_to_windows32(v->value, ';');
|
||||
#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;
|
||||
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;
|
||||
return (char *)p;
|
||||
}
|
||||
|
||||
/* Match assignment variants (:=, +=, ?=) */
|
||||
else if (*p == '=')
|
||||
if (*p == '=')
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@ -1592,7 +1596,7 @@ sync_Path_environment (void)
|
||||
* Create something WINDOWS32 world can grok
|
||||
*/
|
||||
convert_Path_to_windows32 (path, ';');
|
||||
environ_path = xstrdup (concat ("PATH", "=", path));
|
||||
environ_path = xstrdup (concat (3, "PATH", "=", path));
|
||||
putenv (environ_path);
|
||||
free (path);
|
||||
}
|
||||
|
@ -34,13 +34,11 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
DIR *
|
||||
opendir (char *dspec)
|
||||
{
|
||||
struct DIR *dir = (struct DIR *)xmalloc (sizeof (struct DIR));
|
||||
struct NAM *dnam = (struct NAM *)xmalloc (sizeof (struct NAM));
|
||||
struct DIR *dir = xcalloc (sizeof (struct DIR));
|
||||
struct NAM *dnam = xmalloc (sizeof (struct NAM));
|
||||
struct FAB *dfab = &dir->fab;
|
||||
char *searchspec = xmalloc (MAXNAMLEN + 1);
|
||||
|
||||
memset (dir, 0, sizeof *dir);
|
||||
|
||||
*dfab = cc$rms_fab;
|
||||
*dnam = cc$rms_nam;
|
||||
sprintf (searchspec, "%s*.*;", dspec);
|
||||
|
Loading…
Reference in New Issue
Block a user