This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
[PATCH] macro hooks (revised)
- To: binutils at sourceware dot cygnus dot com
- Subject: [PATCH] macro hooks (revised)
- From: Timothy Wall <twall at domesolutions dot com>
- Date: Wed, 08 Mar 2000 14:55:37 -0500
- Organization: Dome Solutions
Here is the macro hooks/line substitution patch previously submitted,
and revised according to previous discussion.
Index: gas/ChangeLog
===================================================================
RCS file: /cvs/src/src/gas/ChangeLog,v
retrieving revision 1.279
diff -d -c -p -r1.279 ChangeLog
*** ChangeLog 2000/03/07 00:06:51 1.279
--- ChangeLog 2000/03/08 19:50:05
***************
*** 1,3 ****
--- 1,30 ----
+ 2000-03-08 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_scrib_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-06 Nick Clifton <nickc@cygnus.com>
* config/tc-m32r.c (struct md_longopts): Add -m32r command line
Index: gas/as.h
===================================================================
RCS file: /cvs/src/src/gas/as.h,v
retrieving revision 1.8
diff -d -c -p -r1.8 as.h
*** as.h 2000/02/24 01:56:31 1.8
--- as.h 2000/03/08 19:50:05
*************** void print_version_id PARAMS ((void));
*** 557,562 ****
--- 557,564 ----
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));
Index: gas/gasp.c
===================================================================
RCS file: /cvs/src/src/gas/gasp.c,v
retrieving revision 1.5
diff -d -c -p -r1.5 gasp.c
*** gasp.c 2000/03/01 18:03:49 1.5
--- gasp.c 2000/03/08 19:50:06
*************** typedef struct
*** 193,229 ****
} 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
--- 193,198 ----
*************** macro_op (idx, in)
*** 2687,2693 ****
return 0;
sb_terminate (in);
! if (! check_macro (in->ptr + idx, &out, comment_char, &err))
return 0;
if (err != NULL)
--- 2656,2662 ----
return 0;
sb_terminate (in);
! if (! check_macro (in->ptr + idx, &out, comment_char, &err, NULL))
return 0;
if (err != NULL)
Index: gas/input-scrub.c
===================================================================
RCS file: /cvs/src/src/gas/input-scrub.c,v
retrieving revision 1.1.1.1
diff -d -c -p -r1.1.1.1 input-scrub.c
*** input-scrub.c 1999/05/03 07:28:41 1.1.1.1
--- input-scrub.c 2000/03/08 19:50:06
*************** static int sb_index = -1;
*** 74,79 ****
--- 74,82 ----
/* 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 check_from_sb = 1;
+
/* The number of nested sb structures we have included. */
int macro_nest;
*************** struct input_save
*** 111,116 ****
--- 114,120 ----
int logical_input_line;
int sb_index;
sb from_sb;
+ int check_from_sb; /* 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 */
*************** input_scrub_push (saved_position)
*** 147,152 ****
--- 151,157 ----
saved->logical_input_line = logical_input_line;
saved->sb_index = sb_index;
saved->from_sb = from_sb;
+ saved->check_from_sb = check_from_sb;
memcpy (saved->save_source, save_source, sizeof (save_source));
saved->next_saved_file = next_saved_file;
saved->input_file_save = input_file_push ();
*************** input_scrub_pop (saved)
*** 181,186 ****
--- 186,192 ----
logical_input_line = saved->logical_input_line;
sb_index = saved->sb_index;
from_sb = saved->from_sb;
+ check_from_sb = saved->check_from_sb;
partial_where = saved->partial_where;
partial_size = saved->partial_size;
next_saved_file = saved->next_saved_file;
*************** input_scrub_include_file (filename, posi
*** 255,271 ****
expanding a macro. */
void
! input_scrub_include_sb (from, position)
sb *from;
char *position;
{
! if (macro_nest > max_macro_nest)
! as_fatal (_("macros nested too deeply"));
! ++macro_nest;
next_saved_file = input_scrub_push (position);
sb_new (&from_sb);
if (from->len >= 1 && from->ptr[0] != '\n')
{
/* Add the sentinel required by read.c. */
--- 261,285 ----
expanding a macro. */
void
! input_scrub_include_sb (from, position, do_check)
sb *from;
char *position;
+ int do_check;
{
! if (do_check)
! {
! if (macro_nest > max_macro_nest)
! as_fatal (_("macros nested too deeply"));
! ++macro_nest;
! #ifdef md_macro_start
! md_macro_start ();
! #endif
! }
next_saved_file = input_scrub_push (position);
sb_new (&from_sb);
+ check_from_sb = do_check;
if (from->len >= 1 && from->ptr[0] != '\n')
{
/* Add the sentinel required by read.c. */
*************** input_scrub_next_buffer (bufp)
*** 297,304 ****
if (sb_index >= from_sb.len)
{
sb_kill (&from_sb);
! cond_finish_check (macro_nest);
! --macro_nest;
partial_where = NULL;
if (next_saved_file != NULL)
*bufp = input_scrub_pop (next_saved_file);
--- 311,325 ----
if (sb_index >= from_sb.len)
{
sb_kill (&from_sb);
! if (check_from_sb)
! {
! cond_finish_check (macro_nest);
! /* allow the target to clean up per-macro expansion data */
! #ifdef md_macro_end
! md_macro_end ();
! #endif
! --macro_nest;
! }
partial_where = NULL;
if (next_saved_file != NULL)
*bufp = input_scrub_pop (next_saved_file);
Index: gas/macro.c
===================================================================
RCS file: /cvs/src/src/gas/macro.c,v
retrieving revision 1.5
diff -d -c -p -r1.5 macro.c
*** macro.c 1999/11/12 15:39:46 1.5
--- macro.c 2000/03/08 19:50:06
*************** extern void *alloca ();
*** 70,111 ****
/* 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 *));
--- 70,75 ----
*************** macro_expand (idx, in, m, out, comment_c
*** 1108,1118 ****
gasp. Return 1 if a macro is found, 0 otherwise. */
int
! check_macro (line, expand, comment_char, error)
const char *line;
sb *expand;
int comment_char;
const char **error;
{
const char *s;
char *copy, *cs;
--- 1072,1083 ----
gasp. Return 1 if a macro is found, 0 otherwise. */
int
! 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;
*************** check_macro (line, expand, comment_char,
*** 1152,1157 ****
--- 1117,1126 ----
*error = macro_expand (0, &line_sb, macro, expand, comment_char);
sb_kill (&line_sb);
+
+ /* export the macro information if requested */
+ if (info)
+ *info = macro;
return 1;
}
Index: gas/macro.h
===================================================================
RCS file: /cvs/src/src/gas/macro.h,v
retrieving revision 1.1.1.1
diff -d -c -p -r1.1.1.1 macro.h
*** macro.h 1999/05/03 07:28:41 1.1.1.1
--- macro.h 2000/03/08 19:50:06
***************
*** 28,33 ****
--- 28,69 ----
#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;
*************** extern void macro_mri_mode PARAMS ((int)
*** 45,51 ****
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 void delete_macro PARAMS ((const char *));
extern const char *expand_irp
PARAMS ((int, int, sb *, sb *, int (*) PARAMS ((sb *)), int));
--- 81,88 ----
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 **,
! macro_entry **));
extern void delete_macro PARAMS ((const char *));
extern const char *expand_irp
PARAMS ((int, int, sb *, sb *, int (*) PARAMS ((sb *)), int));
Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.16
diff -d -c -p -r1.16 read.c
*** read.c 2000/02/24 01:56:31 1.16
--- read.c 2000/03/08 19:50:07
*************** read_a_source_file (name)
*** 864,880 ****
{
sb out;
const char *err;
! if (check_macro (s, &out, '\0', &err))
{
if (err != NULL)
as_bad ("%s", err);
*input_line_pointer++ = c;
input_scrub_include_sb (&out,
! input_line_pointer);
sb_kill (&out);
buffer_limit =
input_scrub_next_buffer (&input_line_pointer);
continue;
}
}
--- 864,884 ----
{
sb out;
const char *err;
+ macro_entry *macro;
! 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, 1);
sb_kill (&out);
buffer_limit =
input_scrub_next_buffer (&input_line_pointer);
+ #ifdef md_macro_info
+ md_macro_info (macro);
+ #endif
continue;
}
}
*************** s_irp (irpc)
*** 1827,1833 ****
sb_kill (&s);
! input_scrub_include_sb (&out, input_line_pointer);
sb_kill (&out);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
--- 1831,1837 ----
sb_kill (&s);
! input_scrub_include_sb (&out, input_line_pointer, 1);
sb_kill (&out);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
*************** do_repeat (count, start, end)
*** 2670,2676 ****
sb_kill (&one);
! input_scrub_include_sb (&many, input_line_pointer);
sb_kill (&many);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
--- 2674,2680 ----
sb_kill (&one);
! input_scrub_include_sb (&many, input_line_pointer, 1);
sb_kill (&many);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
*************** void
*** 4873,4879 ****
s_include (arg)
int arg ATTRIBUTE_UNUSED;
{
- char *newbuf;
char *filename;
int i;
FILE *try;
--- 4877,4882 ----
*************** s_include (arg)
*** 4924,4931 ****
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);
} /* s_include() */
void
--- 4927,4933 ----
gotit:
/* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */
register_dependency (path);
! input_scrub_insert_file (path);
} /* s_include() */
void
*************** read_print_statistics (file)
*** 5108,5113 ****
--- 5110,5148 ----
FILE *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 considered a self-contained element, but may actually replace
+ the starting line of a conditional.
+ This function allows easy 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 (usually automatically generated) 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 */
Index: gas/sb.h
===================================================================
RCS file: /cvs/src/src/gas/sb.h,v
retrieving revision 1.1.1.1
diff -d -c -p -r1.1.1.1 sb.h
*** sb.h 1999/05/03 07:28:41 1.1.1.1
--- sb.h 2000/03/08 19:50:07
*************** extern int sb_skip_white PARAMS ((int, s
*** 94,99 ****
extern int sb_skip_comma PARAMS ((int, sb *));
/* Actually in input-scrub.c. */
! extern void input_scrub_include_sb PARAMS ((sb *, char *));
#endif /* SB_H */
--- 94,99 ----
extern int sb_skip_comma PARAMS ((int, sb *));
/* Actually in input-scrub.c. */
! extern void input_scrub_include_sb PARAMS ((sb *, char *, int));
#endif /* SB_H */
Index: gas/doc/internals.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/internals.texi,v
retrieving revision 1.7
diff -d -c -p -r1.7 internals.texi
*** internals.texi 2000/02/28 04:08:32 1.7
--- internals.texi 2000/03/08 19:50:07
*************** must take two arguments, a @code{segT} f
*** 1237,1242 ****
--- 1237,1260 ----
for the size of the section, and return a @code{valueT} for the rounded
size.
+ @item md_macro_start
+ @cindex md_macro_start
+ GAS will call this function when it starts to include a macro expansion.
+ 'macro_nest' indicates the current macro nesting level, which includes the one
+ being expanded.
+
+ @item md_macro_info
+ @cindex md_macro_info
+ GAS will call this function after the macro expansion has been included and
+ after parsing the macro arguments. The single argument is a pointer to the
+ macro processing's internal representation of the macro, which includes
+ expansion of the formal arguments.
+
+ @item md_macro_end
+ @cindex md_macro_end
+ Complement to md_macro_start, 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