summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog27
-rw-r--r--gas/as.h2
-rw-r--r--gas/doc/internals.texi18
-rw-r--r--gas/gasp.c33
-rw-r--r--gas/input-scrub.c30
-rw-r--r--gas/macro.c43
-rw-r--r--gas/macro.h39
-rw-r--r--gas/read.c48
-rw-r--r--gas/sb.h2
9 files changed, 160 insertions, 82 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index e532a76691..591d0b39ea 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,30 @@
+2000-03-26 Timothy Wall <twall@cygnus.com>
+
+ * gasp.c (macro_op): Add new argument to check_macro call.
+ Macro structure definitions moved to macro.h
+ * sb.h: Add argument to prototype for input_scrub_include_sb.
+ * input-scrub.c (input_scrub_include_sb): Allow disabling of sb
+ nesting checks with an additional flag.
+ (struct input_save): Add flag to indicate whether current sb
+ should be checked for proper macro/conditional nesting.
+ (input_scrub_push/pop): Save/restore nest check flag.
+ (input_scrub_next_buffer): Ditto. Also call end of macro hook if
+ defined.
+ * macro.c (check_macro): Allow caller to retrieve parsed macro
+ information if a pointer is provided. This information may be
+ used by the new macro hooks.
+ * macro.h: Update prototype for check_macro. Macro struct
+ definitions moved here from macro.c/gasp.c.
+ * read.c (read_a_source_file): Add parameter to check_macro call,
+ and pass macro info to the macro hook, if defined.
+ (input_scrub_insert_line): New. Allow insertion of a line of
+ characters into the input stream.
+ (input_scrub_insert_file): New. Allow insertion of an arbitrary
+ file into the input stream.
+ (s_include): Use input_scrub_insert_file.
+ * internals.texi: Document new macro hooks.
+ * as.h: New prototypes added.
+
2000-03-26 Alan Modra <alan@linuxcare.com>
* config/tc-i386.c: Don't start any as_bad or as_warn message with
diff --git a/gas/as.h b/gas/as.h
index 9efd7aba43..4c4658a04d 100644
--- a/gas/as.h
+++ b/gas/as.h
@@ -557,6 +557,8 @@ void print_version_id PARAMS ((void));
char *app_push PARAMS ((void));
char *atof_ieee PARAMS ((char *str, int what_kind, LITTLENUM_TYPE * words));
char *input_scrub_include_file PARAMS ((char *filename, char *position));
+extern void input_scrub_insert_line PARAMS((const char *line));
+extern void input_scrub_insert_file PARAMS((char *path));
char *input_scrub_new_file PARAMS ((char *filename));
char *input_scrub_next_buffer PARAMS ((char **bufp));
int do_scrub_chars PARAMS ((int (*get) (char *, int), char *to, int tolen));
diff --git a/gas/doc/internals.texi b/gas/doc/internals.texi
index 1e05131df7..3be8b81281 100644
--- a/gas/doc/internals.texi
+++ b/gas/doc/internals.texi
@@ -1247,6 +1247,24 @@ must take two arguments, a @code{segT} for the section and a @code{valueT}
for the size of the section, and return a @code{valueT} for the rounded
size.
+@item md_macro_start
+@cindex md_macro_start
+If defined, GAS will call this macro when it starts to include a macro
+expansion. @code{macro_nest} indicates the current macro nesting level, which
+includes the one being expanded.
+
+@item md_macro_info
+@cindex md_macro_info
+If defined, GAS will call this macro after the macro expansion has been
+included in the input and after parsing the macro arguments. The single
+argument is a pointer to the macro processing's internal representation of the
+macro (macro_entry *), which includes expansion of the formal arguments.
+
+@item md_macro_end
+@cindex md_macro_end
+Complement to md_macro_start. If defined, it is called when finished
+processing an inserted macro expansion, just before decrementing macro_nest.
+
@item DOUBLEBAR_PARALLEL
@cindex DOUBLEBAR_PARALLEL
Affects the preprocessor so that lines containing '||' don't have their
diff --git a/gas/gasp.c b/gas/gasp.c
index 629e0c0478..b35a4ae57c 100644
--- a/gas/gasp.c
+++ b/gas/gasp.c
@@ -193,37 +193,6 @@ typedef struct
} hash_table;
-/* Structures used to store macros.
-
- Each macro knows its name and included text. It gets built with a
- list of formal arguments, and also keeps a hash table which points
- into the list to speed up formal search. Each formal knows its
- name and its default value. Each time the macro is expanded, the
- formals get the actual values attatched to them. */
-
-/* describe the formal arguments to a macro */
-
-typedef struct formal_struct
- {
- struct formal_struct *next; /* next formal in list */
- sb name; /* name of the formal */
- sb def; /* the default value */
- sb actual; /* the actual argument (changed on each expansion) */
- int index; /* the index of the formal 0..formal_count-1 */
- }
-formal_entry;
-
-/* describe the macro. */
-
-typedef struct macro_struct
- {
- sb sub; /* substitution text. */
- int formal_count; /* number of formal args. */
- formal_entry *formals; /* pointer to list of formal_structs */
- hash_table formal_hash; /* hash table of formals. */
- }
-macro_entry;
-
/* how we nest files and expand macros etc.
we keep a stack of of include_stack structs. each include file
@@ -2687,7 +2656,7 @@ macro_op (idx, in)
return 0;
sb_terminate (in);
- if (! check_macro (in->ptr + idx, &out, comment_char, &err))
+ if (! check_macro (in->ptr + idx, &out, comment_char, &err, NULL))
return 0;
if (err != NULL)
diff --git a/gas/input-scrub.c b/gas/input-scrub.c
index 46a3bb3b7f..ecbdaef7fd 100644
--- a/gas/input-scrub.c
+++ b/gas/input-scrub.c
@@ -74,6 +74,9 @@ static int sb_index = -1;
/* If we are reading from an sb structure, this is it. */
static sb from_sb;
+/* Should we do a conditional check on from_sb? */
+static int from_sb_is_expansion = 1;
+
/* The number of nested sb structures we have included. */
int macro_nest;
@@ -111,6 +114,7 @@ struct input_save
int logical_input_line;
int sb_index;
sb from_sb;
+ int from_sb_is_expansion; /* Should we do a conditional check? */
struct input_save *next_saved_file; /* Chain of input_saves */
char *input_file_save; /* Saved state of input routines */
char *saved_position; /* Caller's saved position in buf */
@@ -147,6 +151,7 @@ input_scrub_push (saved_position)
saved->logical_input_line = logical_input_line;
saved->sb_index = sb_index;
saved->from_sb = from_sb;
+ saved->from_sb_is_expansion = from_sb_is_expansion;
memcpy (saved->save_source, save_source, sizeof (save_source));
saved->next_saved_file = next_saved_file;
saved->input_file_save = input_file_push ();
@@ -181,6 +186,7 @@ input_scrub_pop (saved)
logical_input_line = saved->logical_input_line;
sb_index = saved->sb_index;
from_sb = saved->from_sb;
+ from_sb_is_expansion = saved->from_sb_is_expansion;
partial_where = saved->partial_where;
partial_size = saved->partial_size;
next_saved_file = saved->next_saved_file;
@@ -255,17 +261,26 @@ input_scrub_include_file (filename, position)
expanding a macro. */
void
-input_scrub_include_sb (from, position)
+input_scrub_include_sb (from, position, is_expansion)
sb *from;
char *position;
+ int is_expansion;
{
if (macro_nest > max_macro_nest)
- as_fatal (_("macros nested too deeply"));
+ as_fatal (_("buffers nested too deeply"));
++macro_nest;
+#ifdef md_macro_start
+ if (is_expansion)
+ {
+ md_macro_start ();
+ }
+#endif
+
next_saved_file = input_scrub_push (position);
sb_new (&from_sb);
+ from_sb_is_expansion = is_expansion;
if (from->len >= 1 && from->ptr[0] != '\n')
{
/* Add the sentinel required by read.c. */
@@ -297,8 +312,15 @@ input_scrub_next_buffer (bufp)
if (sb_index >= from_sb.len)
{
sb_kill (&from_sb);
- cond_finish_check (macro_nest);
- --macro_nest;
+ if (from_sb_is_expansion)
+ {
+ cond_finish_check (macro_nest);
+#ifdef md_macro_end
+ /* allow the target to clean up per-macro expansion data */
+ md_macro_end ();
+#endif
+ }
+ --macro_nest;
partial_where = NULL;
if (next_saved_file != NULL)
*bufp = input_scrub_pop (next_saved_file);
diff --git a/gas/macro.c b/gas/macro.c
index 7407f1d114..12a757e223 100644
--- a/gas/macro.c
+++ b/gas/macro.c
@@ -70,42 +70,6 @@ extern void *alloca ();
/* The routines in this file handle macro definition and expansion.
They are called by both gasp and gas. */
-/* Structures used to store macros.
-
- Each macro knows its name and included text. It gets built with a
- list of formal arguments, and also keeps a hash table which points
- into the list to speed up formal search. Each formal knows its
- name and its default value. Each time the macro is expanded, the
- formals get the actual values attatched to them. */
-
-/* describe the formal arguments to a macro */
-
-typedef struct formal_struct
- {
- struct formal_struct *next; /* next formal in list */
- sb name; /* name of the formal */
- sb def; /* the default value */
- sb actual; /* the actual argument (changed on each expansion) */
- int index; /* the index of the formal 0..formal_count-1 */
- }
-formal_entry;
-
-/* Other values found in the index field of a formal_entry. */
-#define QUAL_INDEX (-1)
-#define NARG_INDEX (-2)
-#define LOCAL_INDEX (-3)
-
-/* describe the macro. */
-
-typedef struct macro_struct
- {
- sb sub; /* substitution text. */
- int formal_count; /* number of formal args. */
- formal_entry *formals; /* pointer to list of formal_structs */
- struct hash_control *formal_hash; /* hash table of formals. */
- }
-macro_entry;
-
/* Internal functions. */
static int get_token PARAMS ((int, sb *, sb *));
@@ -1108,11 +1072,12 @@ macro_expand (idx, in, m, out, comment_char)
gasp. Return 1 if a macro is found, 0 otherwise. */
int
-check_macro (line, expand, comment_char, error)
+check_macro (line, expand, comment_char, error, info)
const char *line;
sb *expand;
int comment_char;
const char **error;
+ macro_entry **info;
{
const char *s;
char *copy, *cs;
@@ -1153,6 +1118,10 @@ check_macro (line, expand, comment_char, error)
sb_kill (&line_sb);
+ /* export the macro information if requested */
+ if (info)
+ *info = macro;
+
return 1;
}
diff --git a/gas/macro.h b/gas/macro.h
index cdeea4ad3b..9c61acd89a 100644
--- a/gas/macro.h
+++ b/gas/macro.h
@@ -28,6 +28,42 @@
#include "ansidecl.h"
#include "sb.h"
+/* Structures used to store macros.
+
+ Each macro knows its name and included text. It gets built with a
+ list of formal arguments, and also keeps a hash table which points
+ into the list to speed up formal search. Each formal knows its
+ name and its default value. Each time the macro is expanded, the
+ formals get the actual values attatched to them. */
+
+/* describe the formal arguments to a macro */
+
+typedef struct formal_struct
+ {
+ struct formal_struct *next; /* next formal in list */
+ sb name; /* name of the formal */
+ sb def; /* the default value */
+ sb actual; /* the actual argument (changed on each expansion) */
+ int index; /* the index of the formal 0..formal_count-1 */
+ }
+formal_entry;
+
+/* Other values found in the index field of a formal_entry. */
+#define QUAL_INDEX (-1)
+#define NARG_INDEX (-2)
+#define LOCAL_INDEX (-3)
+
+/* describe the macro. */
+
+typedef struct macro_struct
+ {
+ sb sub; /* substitution text. */
+ int formal_count; /* number of formal args. */
+ formal_entry *formals; /* pointer to list of formal_structs */
+ struct hash_control *formal_hash; /* hash table of formals. */
+ }
+macro_entry;
+
/* Whether any macros have been defined. */
extern int macro_defined;
@@ -45,7 +81,8 @@ extern void macro_mri_mode PARAMS ((int));
extern const char *define_macro
PARAMS ((int idx, sb *in, sb *label, int (*get_line) PARAMS ((sb *)),
const char **namep));
-extern int check_macro PARAMS ((const char *, sb *, int, const char **));
+extern int check_macro PARAMS ((const char *, sb *, int, const char **,
+ macro_entry **));
extern void delete_macro PARAMS ((const char *));
extern const char *expand_irp
PARAMS ((int, int, sb *, sb *, int (*) PARAMS ((sb *)), int));
diff --git a/gas/read.c b/gas/read.c
index b8afe1c2e2..15228426af 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -879,17 +879,21 @@ read_a_source_file (name)
{
sb out;
const char *err;
+ macro_entry *macro;
- if (check_macro (s, &out, '\0', &err))
+ if (check_macro (s, &out, '\0', &err, &macro))
{
if (err != NULL)
as_bad ("%s", err);
*input_line_pointer++ = c;
input_scrub_include_sb (&out,
- input_line_pointer);
+ input_line_pointer, 1);
sb_kill (&out);
buffer_limit =
input_scrub_next_buffer (&input_line_pointer);
+#ifdef md_macro_info
+ md_macro_info (macro);
+#endif
continue;
}
}
@@ -1842,7 +1846,7 @@ s_irp (irpc)
sb_kill (&s);
- input_scrub_include_sb (&out, input_line_pointer);
+ input_scrub_include_sb (&out, input_line_pointer, 1);
sb_kill (&out);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
@@ -2675,7 +2679,7 @@ do_repeat (count, start, end)
sb_kill (&one);
- input_scrub_include_sb (&many, input_line_pointer);
+ input_scrub_include_sb (&many, input_line_pointer, 1);
sb_kill (&many);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
@@ -4878,7 +4882,6 @@ void
s_include (arg)
int arg ATTRIBUTE_UNUSED;
{
- char *newbuf;
char *filename;
int i;
FILE *try;
@@ -4929,8 +4932,7 @@ s_include (arg)
gotit:
/* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */
register_dependency (path);
- newbuf = input_scrub_include_file (path, input_line_pointer);
- buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+ input_scrub_insert_file (path);
} /* s_include() */
void
@@ -5115,4 +5117,36 @@ read_print_statistics (file)
hash_print_statistics (file, "pseudo-op table", po_hash);
}
+/* Inserts the given line into the input stream.
+
+ This call avoids macro/conditionals nesting checking, since the contents of
+ the line are assumed to replace the contents of a line already scanned.
+
+ An appropriate use of this function would be substition of input lines when
+ called by md_start_line_hook(). The given line is assumed to already be
+ properly scrubbed. */
+
+void
+input_scrub_insert_line (line)
+ const char *line;
+{
+ sb newline;
+ sb_new (&newline);
+ sb_add_string (&newline, line);
+ input_scrub_include_sb (&newline, input_line_pointer, 0);
+ sb_kill (&newline);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
+/* Insert a file into the input stream; the path must resolve to an actual
+ file; no include path searching or dependency registering is performed. */
+
+void
+input_scrub_insert_file (path)
+ char *path;
+{
+ input_scrub_include_file (path, input_line_pointer);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
/* end of read.c */
diff --git a/gas/sb.h b/gas/sb.h
index 7e6daf167d..7eaed258a3 100644
--- a/gas/sb.h
+++ b/gas/sb.h
@@ -94,6 +94,6 @@ extern int sb_skip_white PARAMS ((int, sb *));
extern int sb_skip_comma PARAMS ((int, sb *));
/* Actually in input-scrub.c. */
-extern void input_scrub_include_sb PARAMS ((sb *, char *));
+extern void input_scrub_include_sb PARAMS ((sb *, char *, int));
#endif /* SB_H */