* m4/m4module.h (struct m4_macro_args): Cache length.
(m4_get_symbol_len, m4_get_symbol_value_len): New accessors.
(m4_set_symbol_value_text): Change signature.
* m4/m4private.h (struct m4_symbol_value): Store string length.
(m4_get_symbol_value_text, m4_get_symbol_value_placeholder)
(m4_set_symbol_value_placeholder): Update accordingly.
(m4_set_symbol_value_text): Change signature.
(m4_get_symbol_value_len): New accessor.
* m4/input.c (struct m4_input_block, string_peek, string_read)
(string_unget, string_print, m4_push_string_finish)
(m4_push_wrapup): Track length of string input.
(m4__next_token): Adjust all users of symbol text to track length,
too.
* m4/macro.c (expand_argument, collect_arguments): Likewise.
* m4/module.c (install_macro_table): Likewise.
* modules/gnu.c (builtin, indir): Likewise.
* modules/m4.c (define, pushdef): Likewise.
* src/main.c (main): Likewise.
* src/freeze.c (reload_frozen_state): Likewise.
* m4/symtab.c (m4_symbol_value_copy): Likewise.
(m4_get_symbol_value_len): New function.
(m4_get_symbol_value_text, m4_get_symbol_value_placeholder)
(m4_set_symbol_value_text, m4_set_symbol_value_placeholder):
Adjust implementation.
Signed-off-by: Eric Blake <ebb9@byu.net>
index 7cdf53b2026d8f1e34c48d74de824865313c5545..eb29c87982deb5b3c3364b6e1027498251f54d88 100644 (file)
+2007年11月28日 Eric Blake <ebb9@byu.net>
+
+ Stage 3a: cache length, rather than computing it, in libm4.
+ * m4/m4module.h (struct m4_macro_args): Cache length.
+ (m4_get_symbol_len, m4_get_symbol_value_len): New accessors.
+ (m4_set_symbol_value_text): Change signature.
+ * m4/m4private.h (struct m4_symbol_value): Store string length.
+ (m4_get_symbol_value_text, m4_get_symbol_value_placeholder)
+ (m4_set_symbol_value_placeholder): Update accordingly.
+ (m4_set_symbol_value_text): Change signature.
+ (m4_get_symbol_value_len): New accessor.
+ * m4/input.c (struct m4_input_block, string_peek, string_read)
+ (string_unget, string_print, m4_push_string_finish)
+ (m4_push_wrapup): Track length of string input.
+ (m4__next_token): Adjust all users of symbol text to track length,
+ too.
+ * m4/macro.c (expand_argument, collect_arguments): Likewise.
+ * m4/module.c (install_macro_table): Likewise.
+ * modules/gnu.c (builtin, indir): Likewise.
+ * modules/m4.c (define, pushdef): Likewise.
+ * src/main.c (main): Likewise.
+ * src/freeze.c (reload_frozen_state): Likewise.
+ * m4/symtab.c (m4_symbol_value_copy): Likewise.
+ (m4_get_symbol_value_len): New function.
+ (m4_get_symbol_value_text, m4_get_symbol_value_placeholder)
+ (m4_set_symbol_value_text, m4_set_symbol_value_placeholder):
+ Adjust implementation.
+
2007年11月27日 Eric Blake <ebb9@byu.net>
Stage 2: use accessors, not direct reference, into argv.
index 9fbbe08c70d7e31a9bd396fa5f9bedcf87dc2f9a..37cdcce6fd4f3fb5bfd8068d89d1a3152b4b06b4 100644 (file)
{
struct
{
- char *start; /* string value */
- char *current; /* current value */
+ char *str; /* string value */
+ size_t len; /* remaining length */
}
u_s;
struct
static int
string_peek (m4_input_block *me)
{
- int ch = to_uchar (*me->u.u_s.current);
-
- return (ch == '0円') ? CHAR_RETRY : ch;
+ return me->u.u_s.len ? to_uchar (*me->u.u_s.str) : CHAR_RETRY;
}
static int
string_read (m4_input_block *me, m4 *context M4_GNUC_UNUSED,
bool retry M4_GNUC_UNUSED)
{
- int ch = to_uchar (*me->u.u_s.current);
- if (ch == '0円')
+ if (!me->u.u_s.len)
return CHAR_RETRY;
- me->u.u_s.current++;
- return ch;
+ me->u.u_s.len--;
+ return to_uchar (*me->u.u_s.str++);
}
static void
string_unget (m4_input_block *me, int ch)
{
- assert (me->u.u_s.current > me->u.u_s.start && ch < CHAR_EOF);
- *--me->u.u_s.current = ch;
+ assert (ch < CHAR_EOF && to_uchar (me->u.u_s.str[-1]) == ch);
+ me->u.u_s.str--;
+ me->u.u_s.len++;
}
static void
@@ -479,13 +477,15 @@ string_print (m4_input_block *me, m4 *context, m4_obstack *obs)
const char *lquote = m4_get_syntax_lquote (M4SYNTAX);
const char *rquote = m4_get_syntax_rquote (M4SYNTAX);
size_t arg_length = m4_get_max_debug_arg_length_opt (context);
- const char *text = me->u.u_s.start;
- size_t len = arg_length ? strnlen (text, arg_length) : strlen (text);
+ const char *text = me->u.u_s.str;
+ size_t len = me->u.u_s.len;
+ if (arg_length && arg_length < len)
+ len = arg_length;
if (quote)
obstack_grow (obs, lquote, strlen (lquote));
obstack_grow (obs, text, len);
- if (len == arg_length && text[len] != '0円')
+ if (len != me->u.u_s.len)
obstack_grow (obs, "...", 3);
if (quote)
obstack_grow (obs, rquote, strlen (rquote));
if (obstack_object_size (current_input) > 0)
{
+ next->u.u_s.len = obstack_object_size (current_input);
obstack_1grow (current_input, '0円');
- next->u.u_s.start = obstack_finish (current_input);
- next->u.u_s.current = next->u.u_s.start;
+ next->u.u_s.str = obstack_finish (current_input);
next->prev = isp;
ret = isp = next;
input_change = true;
@@ -665,8 +665,8 @@ m4_push_wrapup (m4 *context, const char *s)
i->file = m4_get_current_file (context);
i->line = m4_get_current_line (context);
- i->u.u_s.start = obstack_copy0 (wrapup_stack, s, strlen (s));
- i->u.u_s.current = i->u.u_s.start;
+ i->u.u_s.len = strlen (s);
+ i->u.u_s.str = obstack_copy0 (wrapup_stack, s, i->u.u_s.len);
wsp = i;
}
@@ -1019,6 +1019,7 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line,
m4__token_type type;
const char *file;
int dummy;
+ size_t len;
assert (next == NULL);
if (!line)
@@ -1221,11 +1222,12 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line,
}
} while (type == M4_TOKEN_NONE);
+ len = obstack_object_size (&token_stack);
obstack_1grow (&token_stack, '0円');
memset (token, '0円', sizeof (m4_symbol_value));
- m4_set_symbol_value_text (token, obstack_finish (&token_stack));
+ m4_set_symbol_value_text (token, obstack_finish (&token_stack), len);
VALUE_MAX_ARGS (token) = -1;
#ifdef DEBUG_INPUT
index b0e9405c59416ca8138a8bd411884086baa0683e..7ffaffdfe24b136817e413a3ef243adca2331cce 100644 (file)
until all references have been rescanned. */
bool inuse;
const char *argv0; /* The macro name being expanded. */
+ size_t argv0_len; /* Length of argv0. */
size_t arraylen; /* True length of allocated elements in array. */
/* Used as a variable-length array, storing information about each
argument. */
@@ -267,6 +268,8 @@ extern bool m4_symbol_value_groks_macro (m4_symbol_value *);
(m4_is_symbol_value_placeholder (m4_get_symbol_value (symbol)))
#define m4_get_symbol_text(symbol) \
(m4_get_symbol_value_text (m4_get_symbol_value (symbol)))
+#define m4_get_symbol_len(symbol) \
+ (m4_get_symbol_value_len (m4_get_symbol_value (symbol)))
#define m4_get_symbol_func(symbol) \
(m4_get_symbol_value_func (m4_get_symbol_value (symbol)))
#define m4_get_symbol_builtin(symbol) \
@@ -284,12 +287,13 @@ extern bool m4_is_symbol_value_text (m4_symbol_value *);
extern bool m4_is_symbol_value_func (m4_symbol_value *);
extern bool m4_is_symbol_value_placeholder (m4_symbol_value *);
extern bool m4_is_symbol_value_void (m4_symbol_value *);
-extern const char *m4_get_symbol_value_text (m4_symbol_value *);
+extern const char * m4_get_symbol_value_text (m4_symbol_value *);
+extern size_t m4_get_symbol_value_len (m4_symbol_value *);
extern m4_builtin_func *m4_get_symbol_value_func (m4_symbol_value *);
extern const m4_builtin *m4_get_symbol_value_builtin (m4_symbol_value *);
-extern const char *m4_get_symbol_value_placeholder (m4_symbol_value *);
+extern const char * m4_get_symbol_value_placeholder (m4_symbol_value *);
extern void m4_set_symbol_value_text (m4_symbol_value *,
- const char *);
+ const char *, size_t);
extern void m4_set_symbol_value_builtin (m4_symbol_value *,
const m4_builtin *);
extern void m4_set_symbol_value_placeholder (m4_symbol_value *,
index 10d82c94a31c22c5281673a85da5edc7b16d4273..84e71570befb8f5680b6dd22cc09c466e9c0b90d 100644 (file)
size_t pending_expansions;
m4__symbol_type type;
- union {
- const char * text; /* Valid when type is TEXT, PLACEHOLDER. */
+ union
+ {
+ struct
+ {
+ size_t len; /* Length of string. */
+ const char * text; /* String contents. */
+ } u_t; /* Valid when type is TEXT, PLACEHOLDER. */
const m4_builtin * builtin;/* Valid when type is FUNC. */
m4_symbol_chain * chain; /* Valid when type is COMP. */
} u;
# define m4_is_symbol_value_void(V) ((V)->type == M4_SYMBOL_VOID)
# define m4_is_symbol_value_placeholder(V) \
((V)->type == M4_SYMBOL_PLACEHOLDER)
-# define m4_get_symbol_value_text(V) ((V)->u.text)
+# define m4_get_symbol_value_text(V) ((V)->u.u_t.text)
+# define m4_get_symbol_value_len(V) ((V)->u.u_t.len)
# define m4_get_symbol_value_func(V) ((V)->u.builtin->func)
# define m4_get_symbol_value_builtin(V) ((V)->u.builtin)
# define m4_get_symbol_value_placeholder(V) \
- ((V)->u.text)
+ ((V)->u.u_t.text)
# define m4_symbol_value_groks_macro(V) (BIT_TEST ((V)->flags, \
VALUE_MACRO_ARGS_BIT))
-# define m4_set_symbol_value_text(V, T) \
- ((V)->type = M4_SYMBOL_TEXT, (V)->u.text = (T))
+# define m4_set_symbol_value_text(V, T, L) \
+ ((V)->type = M4_SYMBOL_TEXT, (V)->u.u_t.text = (T), (V)->u.u_t.len = (L))
# define m4_set_symbol_value_builtin(V, B) \
- ((V)->type = M4_SYMBOL_FUNC, (V)->u.builtin = (B))
+ ((V)->type = M4_SYMBOL_FUNC, (V)->u.builtin = (B))
# define m4_set_symbol_value_placeholder(V, T) \
- ((V)->type = M4_SYMBOL_PLACEHOLDER, (V)->u.text = (T))
+ ((V)->type = M4_SYMBOL_PLACEHOLDER, (V)->u.u_t.text = (T))
#endif
index 449f160fa95f6d38fd788a054e18d9cd37cec2c6..d9538532cdb3ec4e05cc55ab0164b22c4946016b 100644 (file)
@@ -163,6 +163,7 @@ expand_argument (m4 *context, m4_obstack *obs, m4_symbol_value *argp,
int paren_level = 0;
const char *file = m4_get_current_file (context);
int line = m4_get_current_line (context);
+ size_t len;
argp->type = M4_SYMBOL_VOID;
@@ -188,9 +189,10 @@ expand_argument (m4 *context, m4_obstack *obs, m4_symbol_value *argp,
if (argp->type == M4_SYMBOL_FUNC
&& obstack_object_size (obs) == 0)
return type == M4_TOKEN_COMMA;
+ len = obstack_object_size (obs);
obstack_1grow (obs, '0円');
VALUE_MODULE (argp) = NULL;
- m4_set_symbol_value_text (argp, obstack_finish (obs));
+ m4_set_symbol_value_text (argp, obstack_finish (obs), len);
return type == M4_TOKEN_COMMA;
}
/* fallthru */
@@ -369,7 +371,7 @@ collect_arguments (m4 *context, const char *name, m4_symbol *symbol,
if (!groks_macro_args && m4_is_symbol_value_func (&token))
{
VALUE_MODULE (&token) = NULL;
- m4_set_symbol_value_text (&token, "");
+ m4_set_symbol_value_text (&token, "", 0);
}
tokenp = (m4_symbol_value *) obstack_copy (arguments, &token,
sizeof token);
index 4a65dbdbf2573e9ee171b3b655362d8c46336908..afeece4f4f7735905fbe1f56de54acc958703b52 100644 (file)
@@ -193,8 +193,9 @@ install_macro_table (m4 *context, m4_module *module)
for (; mp->name != NULL; mp++)
{
m4_symbol_value *value = m4_symbol_value_create ();
+ size_t len = strlen (mp->value);
- m4_set_symbol_value_text (value, xstrdup (mp->value));
+ m4_set_symbol_value_text (value, xmemdup (mp->value, len + 1), len);
VALUE_MODULE (value) = module;
m4_symbol_pushdef (M4SYMTAB, mp->name, value);
index 97f247bad0a97d0316b90bc26aa38382ff72d76b..7c253a0d9bcaafd6f3bfe6d97067e4daa8f47aba 100644 (file)
@@ -412,7 +412,12 @@ m4_symbol_value_copy (m4_symbol_value *dest, m4_symbol_value *src)
/* Caller is supposed to free text token strings, so we have to
copy the string not just its address in that case. */
if (m4_is_symbol_value_text (src))
- m4_set_symbol_value_text (dest, xstrdup (m4_get_symbol_value_text (src)));
+ {
+ size_t len = m4_get_symbol_value_len (src);
+ m4_set_symbol_value_text (dest,
+ xmemdup (m4_get_symbol_value_text (src),
+ len + 1), len);
+ }
else if (m4_is_symbol_value_placeholder (src))
m4_set_symbol_value_placeholder (dest,
xstrdup (m4_get_symbol_value_placeholder
m4_get_symbol_value_text (m4_symbol_value *value)
{
assert (value && value->type == M4_SYMBOL_TEXT);
- return value->u.text;
+ return value->u.u_t.text;
+}
+
+#undef m4_get_symbol_value_len
+size_t
+m4_get_symbol_value_len (m4_symbol_value *value)
+{
+ assert (value && value->type == M4_SYMBOL_TEXT);
+ return value->u.u_t.len;
}
#undef m4_get_symbol_value_func
m4_get_symbol_value_placeholder (m4_symbol_value *value)
{
assert (value && value->type == M4_SYMBOL_PLACEHOLDER);
- return value->u.text;
+ return value->u.u_t.text;
}
#undef m4_set_symbol_value_text
void
-m4_set_symbol_value_text (m4_symbol_value *value, const char *text)
+m4_set_symbol_value_text (m4_symbol_value *value, const char *text, size_t len)
{
- assert (value);
- assert (text);
+ assert (value && text);
+ /* TODO - this assertion requires NUL-terminated text. Do we want
+ to optimize memory usage and use purely length-based
+ manipulation, for one less byte per string? Perhaps only without
+ NDEBUG? */
+ assert (strlen (text) <= len);
- value->type = M4_SYMBOL_TEXT;
- value->u.text = text;
+ value->type = M4_SYMBOL_TEXT;
+ value->u.u_t.text = text;
+ value->u.u_t.len = len;
}
#undef m4_set_symbol_value_builtin
@@ -694,8 +712,9 @@ m4_set_symbol_value_placeholder (m4_symbol_value *value, const char *text)
assert (value);
assert (text);
- value->type = M4_SYMBOL_PLACEHOLDER;
- value->u.text = text;
+ value->type = M4_SYMBOL_PLACEHOLDER;
+ value->u.u_t.text = text;
+ value->u.u_t.len = SIZE_MAX; /* len is not tracked for placeholders. */
}
\f
index 70c7cf6027ca52a75d3bc4210d4b2eb033852550..560e0d5eb611d55b92ec2375716ed9b8a2939be0 100644 (file)
for (i = 2; i < argc; i++)
if (!m4_is_arg_text (argv, i))
m4_set_symbol_value_text (m4_arg_symbol (new_argv, i - 1),
- "");
+ "", 0);
bp->func (context, obs, argc - 1, new_argv);
free (new_argv);
}
if (!m4_symbol_groks_macro (symbol))
for (i = 2; i < argc; i++)
if (!m4_is_arg_text (argv, i))
- m4_set_symbol_value_text (m4_arg_symbol (new_argv, i - 1), "");
+ m4_set_symbol_value_text (m4_arg_symbol (new_argv, i - 1),
+ "", 0);
m4_macro_call (context, m4_get_symbol_value (symbol), obs,
argc - 1, new_argv);
free (new_argv);
index 37497e64f63e1d1f9db20fb2fe609c3c5007d1d4..87584a2eecf4da13c8ca09e748d42bc07d66aa1f 100644 (file)
m4_symbol_value *value = m4_symbol_value_create ();
if (argc == 2)
- m4_set_symbol_value_text (value, xstrdup (""));
+ m4_set_symbol_value_text (value, xstrdup (""), 0);
else
m4_symbol_value_copy (value, m4_arg_symbol (argv, 2));
m4_symbol_value *value = m4_symbol_value_create ();
if (argc == 2)
- m4_set_symbol_value_text (value, xstrdup (""));
+ m4_set_symbol_value_text (value, xstrdup (""), 0);
else
m4_symbol_value_copy (value, m4_arg_symbol (argv, 2));
index 6e467bb887353dbe92ff8e3771dbf5313f8d242f..c17f4f33357a5f6cfa33628b9fa03ae533594417 100644 (file)
@@ -755,7 +755,9 @@ ill-formed frozen file, version 2 directive `%c' encountered"), 'T');
if (number[2] > 0)
module = m4__module_find (string[2]);
- m4_set_symbol_value_text (token, xstrdup (string[1]));
+ m4_set_symbol_value_text (token, xmemdup (string[1],
+ number[1] + 1),
+ number[1]);
VALUE_MODULE (token) = module;
VALUE_MAX_ARGS (token) = -1;
index a54a533256f61bfda7ffd96c430aee302e7a1c1f..ef9cb7bc68da3211623558037d5389b8e352e99b 100644 (file)
@@ -667,11 +667,16 @@ main (int argc, char *const *argv, char *const *envp)
/* defn->value is read-only, so we need a copy. */
char *macro_name = xstrdup (arg);
char *macro_value = strchr (macro_name, '=');
+ size_t len = 0;
if (macro_value != NULL)
- *macro_value++ = '0円';
+ {
+ *macro_value++ = '0円';
+ len = strlen (macro_value);
+ }
m4_set_symbol_value_text (value, xstrdup (macro_value
- ? macro_value : ""));
+ ? macro_value : ""),
+ len);
if (defn->code == 'D')
m4_symbol_define (M4SYMTAB, macro_name, value);