summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog36
-rw-r--r--default.c2
-rw-r--r--dep.h15
-rw-r--r--dir.c9
-rw-r--r--file.c4
-rw-r--r--function.c55
-rw-r--r--implicit.c2
-rw-r--r--job.c2
-rw-r--r--main.c48
-rw-r--r--makeint.h31
-rw-r--r--misc.c32
-rw-r--r--read.c98
-rw-r--r--rule.c2
-rw-r--r--variable.c2
14 files changed, 191 insertions, 147 deletions
diff --git a/ChangeLog b/ChangeLog
index ded8974..fe7cd99 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2013-06-22 Paul Smith <psmith@gnu.org>
+
+ Improve performance by using a character map to determine where we
+ want to stop searching strings, rather than discrete comparisons.
+
+ * read.c (find_char_unquote): Pass a stop map instead of various
+ flags and use that to check when to stop parsing the string.
+ (eval): Use the new find_char_unquote() calling signature.
+ (remove_comments): Ditto.
+ (unescape_char): Ditto.
+ (find_percent_cached): Ditto.
+ (parse_file_seq): Use a stop-map flag.
+ * main.c (stopchar_map): Character map definition.
+ (initialize_stopchar_map): Initialize the map definition.
+ (main): Invoke the map initialization function.
+ * misc.c (end_of_token_w32): Remove unused function.
+ * dir.c (dosify): Use STOP_SET to check for stop chars.
+ * main.c (main): Ditto.
+ * misc.c (end_of_token): Ditto.
+ * function.c (subst_expand): Ditto.
+ (func_notdir_suffix): Ditto.
+ (func_basename_dir): Ditto.
+ (abspath): Ditto.
+ * job.c (is_bourne_compatible_shell): Ditto.
+ * variable.c (parse_variable_definition): Ditto.
+ * read.c (eval): Ditto.
+ (conditional_line): Ditto.
+ (find_percent_cached): Ditto.
+ * dep.h (PARSE_FILE_SEQ): Update function declaration.
+ * default.c (set_default_suffixes): Update PARSE_FILE_SEQ() call.
+ * file.c (split_prereqs): Ditto.
+ * function.c (string_glob): Ditto.
+ * implicit.c (pattern_search): Ditto.
+ * rule.c (install_pattern_rule): Ditto.
+ * main.c (main): Ditto.
+
2013-06-21 Paul Smith <psmith@gnu.org>
* main.c (verify_flag): Global variable to determine whether to
diff --git a/default.c b/default.c
index d471eaf..32b878a 100644
--- a/default.c
+++ b/default.c
@@ -547,7 +547,7 @@ set_default_suffixes (void)
{
struct dep *d;
char *p = default_suffixes;
- suffix_file->deps = enter_prereqs (PARSE_FILE_SEQ (&p, struct dep, '\0',
+ suffix_file->deps = enter_prereqs (PARSE_FILE_SEQ (&p, struct dep, MAP_NUL,
NULL, 0),
NULL);
for (d = suffix_file->deps; d; d = d->next)
diff --git a/dep.h b/dep.h
index d1d3bbb..a7c74a1 100644
--- a/dep.h
+++ b/dep.h
@@ -53,13 +53,12 @@ struct nameseq
const char *name;
};
-
-#define PARSEFS_NONE (0x0000)
-#define PARSEFS_NOSTRIP (0x0001)
-#define PARSEFS_NOAR (0x0002)
-#define PARSEFS_NOGLOB (0x0004)
-#define PARSEFS_EXISTS (0x0008)
-#define PARSEFS_NOCACHE (0x0010)
+#define PARSEFS_NONE 0x0000
+#define PARSEFS_NOSTRIP 0x0001
+#define PARSEFS_NOAR 0x0002
+#define PARSEFS_NOGLOB 0x0004
+#define PARSEFS_EXISTS 0x0008
+#define PARSEFS_NOCACHE 0x0010
#define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \
(_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f))
@@ -68,7 +67,7 @@ struct nameseq
void *parse_file_seq ();
#else
void *parse_file_seq (char **stringp, unsigned int size,
- int stopchar, const char *prefix, int flags);
+ int stopmap, const char *prefix, int flags);
#endif
char *tilde_expand (const char *name);
diff --git a/dir.c b/dir.c
index 87b8eb3..5681275 100644
--- a/dir.c
+++ b/dir.c
@@ -16,6 +16,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
#include "makeint.h"
#include "hash.h"
+#include "dep.h"
#ifdef HAVE_DIRENT_H
# include <dirent.h>
@@ -84,21 +85,21 @@ dosify (const char *filename)
df = dos_filename;
/* First, transform the name part. */
- for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i)
+ for (i = 0; i < 8 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)
*df++ = tolower ((unsigned char)*filename++);
/* Now skip to the next dot. */
- while (*filename != '\0' && *filename != '.')
+ while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))
++filename;
if (*filename != '\0')
{
*df++ = *filename++;
- for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i)
+ for (i = 0; i < 3 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)
*df++ = tolower ((unsigned char)*filename++);
}
/* Look for more dots. */
- while (*filename != '\0' && *filename != '.')
+ while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))
++filename;
if (*filename == '.')
return filename;
diff --git a/file.c b/file.c
index b392ace..284e19a 100644
--- a/file.c
+++ b/file.c
@@ -430,7 +430,7 @@ remove_intermediates (int sig)
struct dep *
split_prereqs (char *p)
{
- struct dep *new = PARSE_FILE_SEQ (&p, struct dep, '|', NULL, 0);
+ struct dep *new = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE, NULL, 0);
if (*p)
{
@@ -439,7 +439,7 @@ split_prereqs (char *p)
struct dep *ood;
++p;
- ood = PARSE_FILE_SEQ (&p, struct dep, '\0', NULL, 0);
+ ood = PARSE_FILE_SEQ (&p, struct dep, MAP_NUL, NULL, 0);
if (! new)
new = ood;
diff --git a/function.c b/function.c
index 896cbb2..431c060 100644
--- a/function.c
+++ b/function.c
@@ -116,7 +116,7 @@ subst_expand (char *o, const char *text, const char *subst, const char *replace,
or only at the ends of words, check that this case qualifies. */
if (by_word
&& ((p > text && !isblank ((unsigned char)p[-1]))
- || (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
+ || ! STOP_SET (p[slen], MAP_BLANK|MAP_NUL)))
/* Struck out. Output the rest of the string that is
no longer to be replaced. */
o = variable_buffer_output (o, subst, slen);
@@ -357,7 +357,7 @@ string_glob (char *line)
struct nameseq *chain;
unsigned int idx;
- chain = PARSE_FILE_SEQ (&line, struct nameseq, '\0', NULL,
+ chain = PARSE_FILE_SEQ (&line, struct nameseq, MAP_NUL, NULL,
/* We do not want parse_file_seq to strip './'s.
That would break examples like:
$(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
@@ -507,16 +507,6 @@ func_flavor (char *o, char **argv, const char *funcname UNUSED)
return o;
}
-#ifdef VMS
-# define IS_PATHSEP(c) ((c) == ']')
-#else
-# ifdef HAVE_DOS_PATHS
-# define IS_PATHSEP(c) ((c) == '/' || (c) == '\\')
-# else
-# define IS_PATHSEP(c) ((c) == '/')
-# endif
-#endif
-
static char *
func_notdir_suffix (char *o, char **argv, const char *funcname)
@@ -529,17 +519,13 @@ func_notdir_suffix (char *o, char **argv, const char *funcname)
int is_suffix = funcname[0] == 's';
int is_notdir = !is_suffix;
+ int stop = MAP_PATHSEP | (is_suffix ? MAP_DOT : 0);
while ((p2 = find_next_token (&list_iterator, &len)) != 0)
{
- const char *p = p2 + len;
+ const char *p = p2 + len - 1;
-
- while (p >= p2 && (!is_suffix || *p != '.'))
- {
- if (IS_PATHSEP (*p))
- break;
- --p;
- }
+ while (p >= p2 && ! STOP_SET (*p, stop))
+ --p;
if (p >= p2)
{
@@ -586,16 +572,12 @@ func_basename_dir (char *o, char **argv, const char *funcname)
int is_basename = funcname[0] == 'b';
int is_dir = !is_basename;
-
+ int stop = MAP_PATHSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL;
while ((p2 = find_next_token (&p3, &len)) != 0)
{
- const char *p = p2 + len;
- while (p >= p2 && (!is_basename || *p != '.'))
- {
- if (IS_PATHSEP (*p))
- break;
- --p;
- }
+ const char *p = p2 + len - 1;
+ while (p >= p2 && ! STOP_SET (*p, stop))
+ --p;
if (p >= p2 && (is_dir))
o = variable_buffer_output (o, p2, ++p - p2);
@@ -1984,9 +1966,9 @@ abspath (const char *name, char *apath)
strcpy (apath, starting_directory);
#ifdef HAVE_DOS_PATHS
- if (IS_PATHSEP(name[0]))
+ if (STOP_SET (name[0], MAP_PATHSEP))
{
- if (IS_PATHSEP(name[1]))
+ if (STOP_SET (name[1], MAP_PATHSEP))
{
/* A UNC. Don't prepend a drive letter. */
apath[0] = name[0];
@@ -2011,7 +1993,7 @@ abspath (const char *name, char *apath)
/* Get past the root, since we already copied it. */
name += root_len;
#ifdef HAVE_DOS_PATHS
- if (!IS_PATHSEP(apath[2]))
+ if (! STOP_SET (apath[2], MAP_PATHSEP))
{
/* Convert d:foo into d:./foo and increase root_len. */
apath[2] = '.';
@@ -2031,11 +2013,11 @@ abspath (const char *name, char *apath)
unsigned long len;
/* Skip sequence of multiple path-separators. */
- while (IS_PATHSEP(*start))
+ while (STOP_SET (*start, MAP_PATHSEP))
++start;
/* Find end of path component. */
- for (end = start; *end != '\0' && !IS_PATHSEP(*end); ++end)
+ for (end = start; ! STOP_SET (*end, MAP_PATHSEP|MAP_NUL); ++end)
;
len = end - start;
@@ -2048,11 +2030,12 @@ abspath (const char *name, char *apath)
{
/* Back up to previous component, ignore if at root already. */
if (dest > apath + root_len)
- for (--dest; !IS_PATHSEP(dest[-1]); --dest);
+ for (--dest; ! STOP_SET (dest[-1], MAP_PATHSEP); --dest)
+ ;
}
else
{
- if (!IS_PATHSEP(dest[-1]))
+ if (! STOP_SET (dest[-1], MAP_PATHSEP))
*dest++ = '/';
if (dest + len >= apath_limit)
@@ -2065,7 +2048,7 @@ abspath (const char *name, char *apath)
}
/* Unless it is root strip trailing separator. */
- if (dest > apath + root_len && IS_PATHSEP(dest[-1]))
+ if (dest > apath + root_len && STOP_SET (dest[-1], MAP_PATHSEP))
--dest;
*dest = '\0';
diff --git a/implicit.c b/implicit.c
index 9712780..97233a6 100644
--- a/implicit.c
+++ b/implicit.c
@@ -634,7 +634,7 @@ pattern_search (struct file *file, int archive,
p = variable_expand_for_file (depname, file);
/* Parse the expanded string. */
- dl = PARSE_FILE_SEQ (&p, struct dep, order_only ? '\0' : '|',
+ dl = PARSE_FILE_SEQ (&p, struct dep, order_only ? MAP_NUL : MAP_PIPE,
add_dir ? dir : NULL, 0);
for (d = dl; d != NULL; d = d->next)
diff --git a/job.c b/job.c
index 507b90d..ef24caa 100644
--- a/job.c
+++ b/job.c
@@ -459,7 +459,7 @@ is_bourne_compatible_shell (const char *path)
len = strlen (unix_shells[i]);
#if defined(WINDOWS32) || defined(__MSDOS__)
if ((strncasecmp (name, unix_shells[i], len) == 0) &&
- (strlen (name) >= len && (name[len] == '\0' || name[len] == '.')))
+ (strlen (name) >= len && STOP_SET (name[len], MAP_DOT|MAP_NUL)))
#else
if ((strncmp (name, unix_shells[i], len) == 0) &&
(strlen (name) >= len && name[len] == '\0'))
diff --git a/main.c b/main.c
index a14f34b..147f77d 100644
--- a/main.c
+++ b/main.c
@@ -548,6 +548,13 @@ int not_parallel;
warning at the end of the run. */
int clock_skew_detected;
+
+/* Map of possible stop characters for searching strings. */
+#ifndef UCHAR_MAX
+# define UCHAR_MAX 255
+#endif
+unsigned short stopchar_map[UCHAR_MAX + 1] = {0};
+
/* Mask of signals that are being caught with fatal_error_signal. */
@@ -590,6 +597,41 @@ initialize_global_hash_tables (void)
hash_init_function_table ();
}
+/* This character map locate stop chars when parsing GNU makefiles.
+ Each element is true if we should stop parsing on that character. */
+
+static void
+initialize_stopchar_map ()
+{
+ int i;
+
+ stopchar_map[(int)'\0'] = MAP_NUL;
+ stopchar_map[(int)'#'] = MAP_COMMENT;
+ stopchar_map[(int)';'] = MAP_SEMI;
+ stopchar_map[(int)'='] = MAP_EQUALS;
+ stopchar_map[(int)':'] = MAP_COLON;
+ stopchar_map[(int)'%'] = MAP_PERCENT;
+ stopchar_map[(int)'|'] = MAP_PIPE;
+ stopchar_map[(int)'.'] = MAP_DOT;
+ stopchar_map[(int)','] = MAP_COMMA;
+ stopchar_map[(int)'$'] = MAP_VARIABLE;
+
+ stopchar_map[(int)'/'] = MAP_PATHSEP;
+#if defined(VMS)
+ stopchar_map[(int)']'] = MAP_PATHSEP;
+#elif defined(HAVE_DOS_PATHS)
+ stopchar_map[(int)'\\'] = MAP_PATHSEP;
+#endif
+
+ for (i = 1; i <= UCHAR_MAX; ++i)
+ {
+ if (isblank(i))
+ stopchar_map[i] = MAP_BLANK;
+ if (isspace(i))
+ stopchar_map[i] |= MAP_SPACE;
+ }
+}
+
static const char *
expand_command_line_file (char *name)
{
@@ -1026,6 +1068,8 @@ main (int argc, char **argv, char **envp)
no_default_sh_exe = 1;
#endif
+ initialize_stopchar_map();
+
#ifdef SET_STACK_SIZE
/* Get rid of any avoidable limit on stack size. */
{
@@ -1278,7 +1322,7 @@ main (int argc, char **argv, char **envp)
int do_not_define = 0;
char *ep = envp[i];
- while (*ep != '\0' && *ep != '=')
+ while (! STOP_SET (*ep, MAP_EQUALS))
++ep;
#ifdef WINDOWS32
if (!unix_path && strneq (envp[i], "PATH=", 5))
@@ -2420,7 +2464,7 @@ main (int argc, char **argv, char **envp)
{
struct nameseq *ns;
- ns = PARSE_FILE_SEQ (&p, struct nameseq, '\0', NULL, 0);
+ ns = PARSE_FILE_SEQ (&p, struct nameseq, MAP_NUL, NULL, 0);
if (ns)
{
/* .DEFAULT_GOAL should contain one target. */
diff --git a/makeint.h b/makeint.h
index a145970..f119680 100644
--- a/makeint.h
+++ b/makeint.h
@@ -364,7 +364,6 @@ char *strsignal (int signum);
void sync_Path_environment (void);
int w32_kill (pid_t pid, int sig);
-char *end_of_token_w32 (const char *s, char stopchar);
int find_and_set_default_shell (const char *token);
/* indicates whether or not we have Bourne shell */
@@ -382,6 +381,34 @@ extern int unixy_shell;
#define WIN32_LEAN_AND_MEAN
#endif /* WINDOWS32 */
+#define ANY_SET(_v,_m) (((_v)&(_m)) != 0)
+#define NONE_SET(_v,_m) (! ANY_SET ((_v),(_m)))
+
+#define MAP_NUL 0x0001
+#define MAP_BLANK 0x0002
+#define MAP_SPACE 0x0004
+#define MAP_COMMENT 0x0008
+#define MAP_SEMI 0x0010
+#define MAP_EQUALS 0x0020
+#define MAP_COLON 0x0040
+#define MAP_PERCENT 0x0080
+#define MAP_PIPE 0x0100
+#define MAP_DOT 0x0200
+#define MAP_COMMA 0x0400
+
+/* This means not only a '$', but skip the variable reference. */
+#define MAP_VARIABLE 0x4000
+/* The set of characters which are path separators is OS-specific. */
+#define MAP_PATHSEP 0x8000
+
+#ifdef VMS
+# define MAP_VMSCOMMA MAP_COMMA
+#else
+# define MAP_VMSCOMMA 0x0000
+#endif
+
+#define STOP_SET(_v,_m) ANY_SET (stopchar_map[(int)(_v)],(_m))
+
#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
# define SET_STACK_SIZE
#endif
@@ -555,6 +582,8 @@ extern const gmk_floc **expanding_var;
extern char **environ;
+extern unsigned short stopchar_map[];
+
extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag;
extern int print_data_base_flag, question_flag, touch_flag, always_make_flag;
extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
diff --git a/misc.c b/misc.c
index d89b29b..1b1441b 100644
--- a/misc.c
+++ b/misc.c
@@ -483,41 +483,11 @@ lindex (const char *s, const char *limit, int c)
char *
end_of_token (const char *s)
{
- while (*s != '\0' && !isblank ((unsigned char)*s))
+ while (! STOP_SET (*s, MAP_BLANK|MAP_NUL))
++s;
return (char *)s;
}
-#ifdef WINDOWS32
-/*
- * Same as end_of_token, but take into account a stop character
- */
-char *
-end_of_token_w32 (const char *s, char stopchar)
-{
- const char *p = s;
- int backslash = 0;
-
- while (*p != '\0' && *p != stopchar
- && (backslash || !isblank ((unsigned char)*p)))
- {
- if (*p++ == '\\')
- {
- backslash = !backslash;
- while (*p == '\\')
- {
- backslash = !backslash;
- ++p;
- }
- }
- else
- backslash = 0;
- }
-
- return (char *)p;
-}
-#endif
-
/* Return the address of the first nonwhitespace or null in the string S. */
char *
diff --git a/read.c b/read.c
index d6e6fcb..07bc8da 100644
--- a/read.c
+++ b/read.c
@@ -155,8 +155,7 @@ static void record_target_var (struct nameseq *filenames, char *defn,
static enum make_word_type get_next_mword (char *buffer, char *delim,
char **startp, unsigned int *length);
static void remove_comments (char *line);
-static char *find_char_unquote (char *string, int stop1, int stop2,
- int blank, int ignorevars);
+static char *find_char_unquote (char *string, int map);
static char *unescape_char (char *string, int c);
@@ -758,7 +757,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (in_ignored_define)
{
/* See if this is an endef line (plus optional comment). */
- if (word1eq ("endef") && (*p2 == '\0' || *p2 == '#'))
+ if (word1eq ("endef") && STOP_SET (*p2, MAP_COMMENT|MAP_NUL))
in_ignored_define = 0;
continue;
@@ -872,7 +871,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Parse the list of file names. Don't expand archive references! */
p2 = p;
- files = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL,
+ files = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_NUL, NULL,
PARSEFS_NOAR);
free (p);
@@ -930,7 +929,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Parse the list of file names.
Don't expand archive references or strip "./" */
p2 = p;
- files = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL,
+ files = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_NUL, NULL,
PARSEFS_NOAR);
free (p);
@@ -989,7 +988,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Search the line for an unquoted ; that is not after an
unquoted #. */
- cmdleft = find_char_unquote (line, ';', '#', 0, 1);
+ cmdleft = find_char_unquote (line, MAP_SEMI|MAP_COMMENT|MAP_VARIABLE);
if (cmdleft != 0 && *cmdleft == '#')
{
/* We found a comment before a semicolon. */
@@ -1036,7 +1035,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (cmdleft == 0)
{
/* Look for a semicolon in the expanded line. */
- cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
+ cmdleft = find_char_unquote (p2, MAP_SEMI);
if (cmdleft != 0)
{
@@ -1063,7 +1062,7 @@ eval (struct ebuffer *ebuf, int set_default)
}
}
- colonp = find_char_unquote (p2, ':', 0, 0, 0);
+ colonp = find_char_unquote (p2, MAP_COLON);
#ifdef HAVE_DOS_PATHS
/* The drive spec brain-damage strikes again... */
/* Note that the only separators of targets in this context
@@ -1072,7 +1071,7 @@ eval (struct ebuffer *ebuf, int set_default)
while (colonp && (colonp[1] == '/' || colonp[1] == '\\') &&
colonp > p2 && isalpha ((unsigned char)colonp[-1]) &&
(colonp == p2 + 1 || strchr (" \t(", colonp[-2]) != 0))
- colonp = find_char_unquote (colonp + 1, ':', 0, 0, 0);
+ colonp = find_char_unquote (colonp + 1, MAP_COLON);
#endif
if (colonp != 0)
break;
@@ -1108,7 +1107,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Make the colon the end-of-string so we know where to stop
looking for targets. Start there again once we're done. */
*colonp = '\0';
- filenames = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, 0);
+ filenames = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_NUL, NULL, 0);
*colonp = ':';
p2 = colonp;
@@ -1163,7 +1162,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* This is a normal target, _not_ a target-specific variable.
Unquote any = in the dependency list. */
- find_char_unquote (lb_next, '=', 0, 0, 0);
+ find_char_unquote (lb_next, MAP_EQUALS);
/* Remember the command prefix for this target. */
prefix = cmd_prefix;
@@ -1181,7 +1180,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Look for a semicolon in the expanded line. */
if (cmdleft == 0)
{
- cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
+ cmdleft = find_char_unquote (p2, MAP_SEMI);
if (cmdleft != 0)
*(cmdleft++) = '\0';
}
@@ -1235,7 +1234,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (p != 0)
{
struct nameseq *target;
- target = PARSE_FILE_SEQ (&p2, struct nameseq, ':', NULL,
+ target = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_COLON, NULL,
PARSEFS_NOGLOB);
++p2;
if (target == 0)
@@ -1387,7 +1386,7 @@ remove_comments (char *line)
{
char *comment;
- comment = find_char_unquote (line, '#', 0, 0, 0);
+ comment = find_char_unquote (line, MAP_COMMENT);
if (comment != 0)
/* Cut off the line at the #. */
@@ -1620,7 +1619,7 @@ conditional_line (char *line, int len, const gmk_floc *flocp)
and cannot be an 'else' or 'endif'. */
/* Find the length of the next word. */
- for (p = line+1; *p != '\0' && !isspace ((unsigned char)*p); ++p)
+ for (p = line+1; ! STOP_SET (*p, MAP_SPACE|MAP_NUL); ++p)
;
len = p - line;
@@ -2211,37 +2210,24 @@ record_files (struct nameseq *filenames, const char *pattern,
STOPCHAR _cannot_ be '$' if IGNOREVARS is true. */
static char *
-find_char_unquote (char *string, int stop1, int stop2, int blank,
- int ignorevars)
+find_char_unquote (char *string, int map)
{
unsigned int string_len = 0;
char *p = string;
- if (ignorevars)
- ignorevars = '$';
+ /* Always stop on NUL. */
+ map |= MAP_NUL;
while (1)
{
- if (stop2 && blank)
- while (*p != '\0' && *p != ignorevars && *p != stop1 && *p != stop2
- && ! isblank ((unsigned char) *p))
- ++p;
- else if (stop2)
- while (*p != '\0' && *p != ignorevars && *p != stop1 && *p != stop2)
- ++p;
- else if (blank)
- while (*p != '\0' && *p != ignorevars && *p != stop1
- && ! isblank ((unsigned char) *p))
- ++p;
- else
- while (*p != '\0' && *p != ignorevars && *p != stop1)
- ++p;
+ while (! STOP_SET (*p, map))
+ ++p;
if (*p == '\0')
break;
/* If we stopped due to a variable reference, skip over its contents. */
- if (*p == ignorevars)
+ if (STOP_SET (*p, MAP_VARIABLE))
{
char openparen = p[1];
@@ -2349,7 +2335,7 @@ unescape_char (char *string, int c)
char *
find_percent (char *pattern)
{
- return find_char_unquote (pattern, '%', 0, 0, 0);
+ return find_char_unquote (pattern, MAP_PERCENT);
}
/* Search STRING for an unquoted % and handle quoting. Returns a pointer to
@@ -2372,7 +2358,7 @@ find_percent_cached (const char **string)
while (1)
{
- while (*p != '\0' && *p != '%')
+ while (! STOP_SET (*p, MAP_PERCENT|MAP_NUL))
++p;
if (*p == '\0')
@@ -2987,7 +2973,7 @@ tilde_expand (const char *name)
*/
void *
-parse_file_seq (char **stringp, unsigned int size, int stopchar,
+parse_file_seq (char **stringp, unsigned int size, int stopmap,
const char *prefix, int flags)
{
extern void dir_setup_glob (glob_t *glob);
@@ -2997,7 +2983,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
static char *tmpbuf = NULL;
static int tmpbuf_len = 0;
- int cachep = (! (flags & PARSEFS_NOCACHE));
+ int cachep = NONE_SET (flags, PARSEFS_NOCACHE);
struct nameseq *new = 0;
struct nameseq **newp = &new;
@@ -3012,16 +2998,13 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
glob_t gl;
char *tp;
-#ifdef VMS
-# define VMS_COMMA ','
-#else
-# define VMS_COMMA 0
-#endif
+ /* Always stop on NUL. */
+ stopmap |= MAP_NUL;
if (size < sizeof (struct nameseq))
size = sizeof (struct nameseq);
- if (! (flags & PARSEFS_NOGLOB))
+ if (NONE_SET (flags, PARSEFS_NOGLOB))
dir_setup_glob (&gl);
/* Get enough temporary space to construct the largest possible target. */
@@ -3053,39 +3036,39 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
/* Skip whitespace; at the end of the string or STOPCHAR we're done. */
p = next_token (p);
- if (*p == '\0' || *p == stopchar)
+ if (STOP_SET (*p, stopmap))
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);
+ p = find_char_unquote (p, stopmap|MAP_VMSCOMMA|MAP_BLANK);
#ifdef VMS
/* convert comma separated list to space separated */
if (p && *p == ',')
*p =' ';
#endif
#ifdef _AMIGA
- if (stopchar == ':' && p && *p == ':'
+ if (p && STOP_SET (*p, stopmap & MAP_COLON)
&& !(isspace ((unsigned char)p[1]) || !p[1]
|| isspace ((unsigned char)p[-1])))
- p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0);
+ p = find_char_unquote (p+1, stopmap|MAP_VMSCOMMA|MAP_BLANK);
#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 == ':')
+ if (stopmap | MAP_COLON)
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);
+ p = find_char_unquote (p + 1, stopmap|MAP_VMSCOMMA|MAP_BLANK);
#endif
if (p == 0)
p = s + strlen (s);
/* Strip leading "this directory" references. */
- if (! (flags & PARSEFS_NOSTRIP))
+ if (NONE_SET (flags, PARSEFS_NOSTRIP))
#ifdef VMS
/* Skip leading '[]'s. */
while (p - s > 2 && s[0] == '[' && s[1] == ']')
@@ -3159,7 +3142,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
Finally, note that archive groups must end with ')' as the last
character, so ensure there's some word ending like that before
considering this an archive group. */
- if (! (flags & PARSEFS_NOAR)
+ if (NONE_SET (flags, PARSEFS_NOAR)
&& tp == tmpbuf && tp[0] != '(' && tp[nlen-1] != ')')
{
char *n = strchr (tp, '(');
@@ -3175,8 +3158,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
/* Find the end of this word. We don't want to unquote and
we don't care about quoting since we're looking for the
last char in the word. */
- while (*e != '\0' && *e != stopchar && *e != VMS_COMMA
- && ! isblank ((unsigned char) *e))
+ while (! STOP_SET (*e, stopmap|MAP_BLANK|MAP_VMSCOMMA))
++e;
/* If we didn't move, we're done now. */
if (e == o)
@@ -3225,7 +3207,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
/* 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)
+ if (ANY_SET (flags, PARSEFS_NOGLOB))
{
NEWELT (concat (2, prefix, tmpbuf));
continue;
@@ -3248,7 +3230,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
/* 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 (! (flags & PARSEFS_NOAR) && ar_name (name))
+ if (NONE_SET (flags, PARSEFS_NOAR) && ar_name (name))
{
ar_parse_name (name, &arname, &memname);
name = arname;
@@ -3256,7 +3238,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
#endif /* !NO_ARCHIVES */
/* glob() is expensive: don't call it unless we need to. */
- if (!(flags & PARSEFS_EXISTS) && strpbrk (name, "?*[") == NULL)
+ if (NONE_SET (flags, PARSEFS_EXISTS) && strpbrk (name, "?*[") == NULL)
{
globme = 0;
i = 1;
@@ -3276,7 +3258,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopchar,
case GLOB_NOMATCH:
/* If we want only existing items, skip this one. */
- if (flags & PARSEFS_EXISTS)
+ if (ANY_SET (flags, PARSEFS_EXISTS))
{
i = 0;
break;
diff --git a/rule.c b/rule.c
index a1f1e7a..9a9e229 100644
--- a/rule.c
+++ b/rule.c
@@ -373,7 +373,7 @@ install_pattern_rule (struct pspec *p, int terminal)
++r->suffixes[0];
ptr = p->dep;
- r->deps = PARSE_FILE_SEQ (&ptr, struct dep, '\0', NULL, 0);
+ r->deps = PARSE_FILE_SEQ (&ptr, struct dep, MAP_NUL, NULL, 0);
if (new_pattern_rule (r, 0))
{
diff --git a/variable.c b/variable.c
index f76b02b..74e866a 100644
--- a/variable.c
+++ b/variable.c
@@ -1419,7 +1419,7 @@ parse_variable_definition (const char *p, struct variable *var)
int c = *p++;
/* If we find a comment or EOS, it's not a variable definition. */
- if (c == '\0' || c == '#')
+ if (STOP_SET (c, MAP_COMMENT|MAP_NUL))
return NULL;
if (c == '$')