23 |
#include "m4.h" |
#include "m4.h" |
24 |
#include "m4private.h" |
#include "m4private.h" |
25 |
|
|
|
#define M4_ARG_SIGNATURE_DEFAULT_SIZE 7 |
|
|
|
|
|
static m4_hash *m4_arg_signature_parse (const char *name, const char *param); |
|
|
|
|
|
|
|
|
|
|
26 |
/* Find the builtin, which has NAME. If BP argument is supplied |
/* Find the builtin, which has NAME. If BP argument is supplied |
27 |
then search only in table BP. */ |
then search only in table BP. */ |
28 |
const m4_builtin * |
const m4_builtin * |
64 |
|
|
65 |
return NULL; |
return NULL; |
66 |
} |
} |
|
|
|
|
m4_symbol * |
|
|
m4_symbol_set_token (m4 *context, const char *name, m4_symbol_type type, |
|
|
m4_token *token, |
|
|
m4_symbol *(*getter) (m4_symtab *, const char *), |
|
|
m4_symbol *(*setter) (m4_symbol *, m4_token *)) |
|
|
{ |
|
|
const char *openp = NULL; |
|
|
const char *params = NULL; |
|
|
m4_symbol *symbol; |
|
|
size_t len; |
|
|
|
|
|
assert (name); |
|
|
assert (!token || (TOKEN_TYPE (token) == type)); |
|
|
assert (getter); |
|
|
assert (setter); |
|
|
|
|
|
if (!no_gnu_extensions) |
|
|
{ |
|
|
/* If name contains an open paren, then parse before that paren |
|
|
as the actual name, and the rest as a formal parameter list. */ |
|
|
len = 0; |
|
|
for (openp = name; *openp && !M4_IS_OPEN (*openp); ++openp) |
|
|
++len; |
|
|
|
|
|
if (*openp) |
|
|
{ |
|
|
name = xstrzdup (name, len); |
|
|
params = 1+ openp; |
|
|
} |
|
|
} |
|
|
|
|
|
/* Get a symbol table entry for the name. */ |
|
|
symbol = (*getter) (M4SYMTAB, name); |
|
|
|
|
|
if (symbol) |
|
|
{ |
|
|
m4_token empty; |
|
|
|
|
|
if (!token) |
|
|
{ |
|
|
bzero (&empty, sizeof (m4_token)); |
|
|
TOKEN_TYPE (&empty) = type; |
|
|
switch (type) |
|
|
{ |
|
|
case M4_TOKEN_TEXT: |
|
|
TOKEN_TEXT (&empty) = ""; |
|
|
break; |
|
|
|
|
|
case M4_TOKEN_FUNC: |
|
|
case M4_TOKEN_VOID: |
|
|
break; |
|
|
} |
|
|
|
|
|
token = ∅ |
|
|
} |
|
|
|
|
|
if (params) |
|
|
{ |
|
|
/* Make a hash table to map formal parameter names to |
|
|
argv offsets, and store that in the symbol's token. */ |
|
|
TOKEN_ARG_SIGNATURE (token) = m4_arg_signature_parse (name, params); |
|
|
} |
|
|
|
|
|
(*setter) (symbol, token); |
|
|
} |
|
|
|
|
|
/* If we split name on open paren, free the copied substring. */ |
|
|
if (params) |
|
|
xfree ((char *) name); |
|
|
|
|
|
return symbol; |
|
|
} |
|
|
|
|
|
static m4_hash * |
|
|
m4_arg_signature_parse (const char *name, const char *params) |
|
|
{ |
|
|
m4_hash *arg_signature; |
|
|
const char *commap; |
|
|
int offset; |
|
|
|
|
|
assert (params); |
|
|
|
|
|
arg_signature = m4_hash_new (M4_ARG_SIGNATURE_DEFAULT_SIZE, |
|
|
m4_hash_string_hash, m4_hash_string_cmp); |
|
|
|
|
|
for (offset = 1; *params && !M4_IS_CLOSE (*params); ++offset) |
|
|
{ |
|
|
size_t len = 0; |
|
|
|
|
|
/* Skip leading whitespace. */ |
|
|
while (M4_IS_SPACE (*params)) |
|
|
++params; |
|
|
|
|
|
for (commap = params; *commap && M4_IS_IDENT (*commap); ++commap) |
|
|
++len; |
|
|
|
|
|
/* Skip trailing whitespace. */ |
|
|
while (M4_IS_SPACE (*commap)) |
|
|
++commap; |
|
|
|
|
|
if (!M4_IS_COMMA (*commap) && !M4_IS_CLOSE (*commap)) |
|
|
M4ERROR ((EXIT_FAILURE, 0, |
|
|
_("Error: %s: syntax error in parameter list at char `%c'"), |
|
|
name, *commap)); |
|
|
|
|
|
/* Skip parameter delimiter. */ |
|
|
if (M4_IS_COMMA (*commap)) |
|
|
++commap; |
|
|
|
|
|
if (len) |
|
|
{ |
|
|
struct m4_token_arg *arg = XCALLOC (struct m4_token_arg, 1); |
|
|
|
|
|
TOKEN_ARG_INDEX (arg) = offset; |
|
|
|
|
|
m4_hash_insert (arg_signature, xstrzdup (params, len), arg); |
|
|
|
|
|
params = commap; |
|
|
} |
|
|
} |
|
|
|
|
|
if (!M4_IS_CLOSE (*commap)) |
|
|
M4WARN ((warning_status, 0, |
|
|
_("Warning: %s: unterminated parameter list"), name)); |
|
|
|
|
|
return arg_signature; |
|
|
} |
|