[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/5] use strchr for simple case of find_char_unquote
From: |
Paolo Bonzini |
Subject: |
[PATCH 2/5] use strchr for simple case of find_char_unquote |
Date: |
Wed, 2 Nov 2016 17:24:15 +0100 |
In most cases, find_char_unquote has a single stopchar. In that
case we can look for it using strchr's optimized implementation.
The resulting speedup on QEMU's noop build is 4.4% (from 14.5 seconds
to 13.8).
* read.c (find_char_unquote): Rename to find_map_unquote. Replace
with an implementation optimized for the case where the stopchar
is a singleton. Adjust all callers.
---
read.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 54 insertions(+), 13 deletions(-)
diff --git a/read.c b/read.c
index 0883100..c2d42d2 100644
--- a/read.c
+++ b/read.c
@@ -153,7 +153,8 @@ 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 map);
+static char *find_map_unquote (char *string, int map);
+static char *find_char_unquote (char *string, int stop);
static char *unescape_char (char *string, int c);
@@ -1008,7 +1009,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, MAP_SEMI|MAP_COMMENT|MAP_VARIABLE);
+ cmdleft = find_map_unquote (line, MAP_SEMI|MAP_COMMENT|MAP_VARIABLE);
if (cmdleft != 0 && *cmdleft == '#')
{
/* We found a comment before a semicolon. */
@@ -1055,7 +1056,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (cmdleft == 0)
{
/* Look for a semicolon in the expanded line. */
- cmdleft = find_char_unquote (p2, MAP_SEMI);
+ cmdleft = find_char_unquote (p2, ';');
if (cmdleft != 0)
{
@@ -1082,7 +1083,7 @@ eval (struct ebuffer *ebuf, int set_default)
}
}
- colonp = find_char_unquote (p2, MAP_COLON);
+ colonp = find_char_unquote (p2, ':');
#ifdef HAVE_DOS_PATHS
/* The drive spec brain-damage strikes again... */
/* Note that the only separators of targets in this context
@@ -1091,7 +1092,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, MAP_COLON);
+ colonp = find_char_unquote (colonp + 1, ':');
#endif
if (colonp != 0)
break;
@@ -1184,7 +1185,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, MAP_EQUALS);
+ find_char_unquote (lb_next, '=');
/* Remember the command prefix for this target. */
prefix = cmd_prefix;
@@ -1202,7 +1203,7 @@ eval (struct ebuffer *ebuf, int set_default)
/* Look for a semicolon in the expanded line. */
if (cmdleft == 0)
{
- cmdleft = find_char_unquote (p2, MAP_SEMI);
+ cmdleft = find_char_unquote (p2, ';');
if (cmdleft != 0)
*(cmdleft++) = '\0';
}
@@ -1405,7 +1406,7 @@ remove_comments (char *line)
{
char *comment;
- comment = find_char_unquote (line, MAP_COMMENT);
+ comment = find_char_unquote (line, '#');
if (comment != 0)
/* Cut off the line at the #. */
@@ -2234,7 +2235,7 @@ record_files (struct nameseq *filenames, const char
*pattern,
STOPCHAR _cannot_ be '$' if IGNOREVARS is true. */
static char *
-find_char_unquote (char *string, int map)
+find_map_unquote (char *string, int map)
{
unsigned int string_len = 0;
char *p = string;
@@ -2315,6 +2316,46 @@ find_char_unquote (char *string, int map)
return 0;
}
+static char *
+find_char_unquote (char *string, int stop)
+{
+ unsigned int string_len = 0;
+ char *p = string;
+
+ while (1)
+ {
+ p = strchr(p, stop);
+
+ if (!p)
+ return NULL;
+
+ if (p > string && p[-1] == '\\')
+ {
+ /* Search for more backslashes. */
+ int i = -2;
+ while (&p[i] >= string && p[i] == '\\')
+ --i;
+ ++i;
+ /* Only compute the length if really needed. */
+ if (string_len == 0)
+ string_len = strlen (string);
+ /* The number of backslashes is now -I.
+ Copy P over itself to swallow half of them. */
+ memmove (&p[i], &p[i/2], (string_len - (p - string)) - (i/2) + 1);
+ p += i/2;
+ if (i % 2 == 0)
+ /* All the backslashes quoted each other; the STOPCHAR was
+ unquoted. */
+ return p;
+
+ /* The STOPCHAR was quoted by a backslash. Look for another. */
+ }
+ else
+ /* No backslash in sight. */
+ return p;
+ }
+}
+
/* Unescape a character in a string. The string is compressed onto itself. */
static char *
@@ -2368,7 +2409,7 @@ unescape_char (char *string, int c)
char *
find_percent (char *pattern)
{
- return find_char_unquote (pattern, MAP_PERCENT);
+ return find_char_unquote (pattern, '%');
}
/* Search STRING for an unquoted % and handle quoting. Returns a pointer to
@@ -3072,7 +3113,7 @@ parse_file_seq (char **stringp, unsigned int size, int
stopmap,
/* 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, stopmap|MAP_VMSCOMMA|MAP_BLANK);
+ p = find_map_unquote (p, stopmap|MAP_VMSCOMMA|MAP_BLANK);
#ifdef VMS
/* convert comma separated list to space separated */
if (p && *p == ',')
@@ -3081,7 +3122,7 @@ parse_file_seq (char **stringp, unsigned int size, int
stopmap,
#ifdef _AMIGA
if (p && STOP_SET (*p, stopmap & MAP_COLON)
&& !(ISSPACE (p[1]) || !p[1] || ISSPACE (p[-1])))
- p = find_char_unquote (p+1, stopmap|MAP_VMSCOMMA|MAP_BLANK);
+ p = find_map_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
@@ -3091,7 +3132,7 @@ parse_file_seq (char **stringp, unsigned int size, int
stopmap,
if (stopmap | MAP_COLON)
while (p != 0 && !ISSPACE (*p) &&
(p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]))
- p = find_char_unquote (p + 1, stopmap|MAP_VMSCOMMA|MAP_BLANK);
+ p = find_map_unquote (p + 1, stopmap|MAP_VMSCOMMA|MAP_BLANK);
#endif
if (p == 0)
p = s + strlen (s);
--
2.7.4
- [PATCH 0/5] Miscellaneous speed up patches, Paolo Bonzini, 2016/11/02
- [PATCH 1/5] optimize checking for globs, Paolo Bonzini, 2016/11/02
- [PATCH 3/5] use jhash for STRING_N_HASH, Paolo Bonzini, 2016/11/02
- [PATCH 5/5] speedup parsing of functions, Paolo Bonzini, 2016/11/02
- [PATCH 4/5] remove MAP_PERCENT, Paolo Bonzini, 2016/11/02
- [PATCH 2/5] use strchr for simple case of find_char_unquote,
Paolo Bonzini <=
- Re: [PATCH 0/5] Miscellaneous speed up patches, Paolo Bonzini, 2016/11/11