/* macro.c - macro support for gas
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005 Free Software Foundation, Inc.
Written by Steve and Judy Chamberlain of Cygnus Support,
sac@cygnus.com
/* Read input lines till we get to a TO string.
Increase nesting depth if we get a FROM string.
Put the results into sb at PTR.
+ FROM may be NULL (or will be ignored) if TO is "ENDR".
Add a new input line to an sb using GET_LINE.
Return 1 on success, 0 on unexpected EOF. */
buffer_and_nest (const char *from, const char *to, sb *ptr,
int (*get_line) (sb *))
{
- int from_len = strlen (from);
+ int from_len;
int to_len = strlen (to);
int depth = 1;
int line_start = ptr->len;
int more = get_line (ptr);
+ if (to_len == 4 && strcasecmp(to, "ENDR") == 0)
+ {
+ from = NULL;
+ from_len = 0;
+ }
+ else
+ from_len = strlen (from);
+
while (more)
{
/* Try and find the first pseudo op on the line. */
int i = line_start;
- if (! macro_alternate && ! macro_mri)
+ if (! NO_PSEUDO_DOT && ! flag_m68k_mri)
{
/* With normal syntax we can suck what we want till we get
to the dot. With the alternate, labels have to start in
- the first column, since we cant tell what's a label and
+ the first column, since we can't tell what's a label and
whats a pseudoop. */
- /* Skip leading whitespace. */
- while (i < ptr->len && ISWHITE (ptr->ptr[i]))
- i++;
-
- /* Skip over a label. */
- while (i < ptr->len
- && (ISALNUM (ptr->ptr[i])
- || ptr->ptr[i] == '_'
- || ptr->ptr[i] == '$'))
- i++;
+ if (! LABELS_WITHOUT_COLONS)
+ {
+ /* Skip leading whitespace. */
+ while (i < ptr->len && ISWHITE (ptr->ptr[i]))
+ i++;
+ }
- /* And a colon. */
- if (i < ptr->len
- && ptr->ptr[i] == ':')
- i++;
+ for (;;)
+ {
+ /* Skip over a label, if any. */
+ if (i >= ptr->len || ! is_name_beginner (ptr->ptr[i]))
+ break;
+ i++;
+ while (i < ptr->len && is_part_of_name (ptr->ptr[i]))
+ i++;
+ if (i < ptr->len && is_name_ender (ptr->ptr[i]))
+ i++;
+ if (LABELS_WITHOUT_COLONS)
+ break;
+ /* Skip whitespace. */
+ while (i < ptr->len && ISWHITE (ptr->ptr[i]))
+ i++;
+ /* Check for the colon. */
+ if (i >= ptr->len || ptr->ptr[i] != ':')
+ {
+ i = line_start;
+ break;
+ }
+ i++;
+ line_start = i;
+ }
}
/* Skip trailing whitespace. */
i++;
if (i < ptr->len && (ptr->ptr[i] == '.'
- || macro_alternate
+ || NO_PSEUDO_DOT
|| macro_mri))
{
- if (ptr->ptr[i] == '.')
+ if (! flag_m68k_mri && ptr->ptr[i] == '.')
i++;
- if (strncasecmp (ptr->ptr + i, from, from_len) == 0
+ if (from == NULL
+ && strncasecmp (ptr->ptr + i, "IRPC", from_len = 4) != 0
+ && strncasecmp (ptr->ptr + i, "IRP", from_len = 3) != 0
+ && strncasecmp (ptr->ptr + i, "IREPC", from_len = 5) != 0
+ && strncasecmp (ptr->ptr + i, "IREP", from_len = 4) != 0
+ && strncasecmp (ptr->ptr + i, "REPT", from_len = 4) != 0
+ && strncasecmp (ptr->ptr + i, "REP", from_len = 3) != 0)
+ from_len = 0;
+ if ((from != NULL
+ ? strncasecmp (ptr->ptr + i, from, from_len) == 0
+ : from_len > 0)
&& (ptr->len == (i + from_len)
- || ! ISALNUM (ptr->ptr[i + from_len])))
+ || ! (is_part_of_name (ptr->ptr[i + from_len])
+ || is_name_ender (ptr->ptr[i + from_len]))))
depth++;
if (strncasecmp (ptr->ptr + i, to, to_len) == 0
&& (ptr->len == (i + to_len)
- || ! ISALNUM (ptr->ptr[i + to_len])))
+ || ! (is_part_of_name (ptr->ptr[i + to_len])
+ || is_name_ender (ptr->ptr[i + to_len]))))
{
depth--;
if (depth == 0)
get_token (int idx, sb *in, sb *name)
{
if (idx < in->len
- && (ISALPHA (in->ptr[idx])
- || in->ptr[idx] == '_'
- || in->ptr[idx] == '$'))
+ && is_name_beginner (in->ptr[idx]))
{
sb_add_char (name, in->ptr[idx++]);
while (idx < in->len
- && (ISALNUM (in->ptr[idx])
- || in->ptr[idx] == '_'
- || in->ptr[idx] == '$'))
+ && is_part_of_name (in->ptr[idx]))
+ {
+ sb_add_char (name, in->ptr[idx++]);
+ }
+ if (idx < in->len
+ && is_name_ender (in->ptr[idx]))
{
sb_add_char (name, in->ptr[idx++]);
}
else
{
/* FIXME: Why do we do this? */
+ /* At least in alternate mode this seems correct. */
src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
}
}
else if (in->ptr[src] == '\\')
{
src++;
- if (in->ptr[src] == '(')
+ if (src < in->len && in->ptr[src] == '(')
{
/* Sub in till the next ')' literally. */
src++;
if (in->ptr[src] == ')')
src++;
else
- return _("missplaced )");
+ return _("misplaced `)'");
}
- else if (in->ptr[src] == '@')
+ else if (src < in->len && in->ptr[src] == '@')
{
/* Sub in the macro invocation number. */
sprintf (buffer, "%d", macro_number);
sb_add_string (out, buffer);
}
- else if (in->ptr[src] == '&')
+ else if (src < in->len && in->ptr[src] == '&')
{
/* This is a preprocessor variable name, we don't do them
here. */
sb_add_char (out, '&');
src++;
}
- else if (macro_mri && ISALNUM (in->ptr[src]))
+ else if (macro_mri && src < in->len && ISALNUM (in->ptr[src]))
{
int ind;
formal_entry *f;
}
}
else if ((macro_alternate || macro_mri)
- && (ISALPHA (in->ptr[src])
- || in->ptr[src] == '_'
- || in->ptr[src] == '$')
+ && is_name_beginner (in->ptr[src])
&& (! inquote
|| ! macro_strip_at
|| (src > 0 && in->ptr[src - 1] == '@')))
macro_entry *macro;
sb line_sb;
- if (! ISALPHA (*line)
- && *line != '_'
- && *line != '$'
+ if (! is_name_beginner (*line)
&& (! macro_mri || *line != '.'))
return 0;
s = line + 1;
- while (ISALNUM (*s)
- || *s == '_'
- || *s == '$')
+ while (is_part_of_name (*s))
+ ++s;
+ if (is_name_ender (*s))
++s;
copy = (char *) alloca (s - line + 1);
const char *
expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
{
- const char *mn;
sb sub;
formal_entry f;
struct hash_control *h;
const char *err;
- if (irpc)
- mn = "IRPC";
- else
- mn = "IRP";
-
idx = sb_skip_white (idx, in);
sb_new (&sub);
- if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
+ if (! buffer_and_nest (NULL, "ENDR", &sub, get_line))
return _("unexpected end of file in irp or irpc");
sb_new (&f.name);