From 9f10757c407c9946029436682ae554f9739fa62d Mon Sep 17 00:00:00 2001 From: Timothy Wall Date: Sun, 26 Mar 2000 14:47:33 +0000 Subject: [PATCH] Add macro handling extensions and line substitution support. --- gas/ChangeLog | 27 +++++++++++++++++++++++++++ gas/as.h | 2 ++ gas/doc/internals.texi | 18 ++++++++++++++++++ gas/gasp.c | 33 +-------------------------------- gas/input-scrub.c | 30 ++++++++++++++++++++++++++---- gas/macro.c | 43 ++++++------------------------------------- gas/macro.h | 39 ++++++++++++++++++++++++++++++++++++++- gas/read.c | 48 +++++++++++++++++++++++++++++++++++++++++------- gas/sb.h | 2 +- 9 files changed, 160 insertions(+), 82 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index e532a76..591d0b3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,30 @@ +2000-03-26 Timothy Wall + + * 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 * 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 9efd7ab..4c4658a 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 1e05131..3be8b81 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 629e0c0..b35a4ae 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 46a3bb3..ecbdaef 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 7407f1d..12a757e 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 cdeea4a..9c61acd 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 b8afe1c..1522842 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, ¯o)) { 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 7e6daf1..7eaed25 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 */ -- 2.7.4