This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
[PATCH] macro hooks
- To: binutils at sourceware dot cygnus dot com
- Subject: [PATCH] macro hooks
- From: Timothy Wall <twall at alum dot mit dot edu>
- Date: Wed, 23 Feb 2000 11:16:45 -0500
- CC: nickc at cygnus dot com
This patch adds hooks to allow the target to do things when a macro is
encountered, parsed, and terminated. It also adds convenience functions
to aid in substituting the contents of a line and inserting an
automatically generated file into the input stream.
Index: gas/ChangeLog
===================================================================
RCS file: /cvs/src/src/gas/ChangeLog,v
retrieving revision 1.260
diff -d -c -p -r1.260 ChangeLog
*** ChangeLog 2000/02/23 13:52:20 1.260
--- ChangeLog 2000/02/23 16:13:28
***************
*** 1,3 ****
--- 1,25 ----
+ 2000-02-23 Timothy Wall <twall@cygnus.com>
+
+ * gasp.c (macro_op): Add new argument to check_macro call.
+ * input-scrub.c (input_scrub_inlcude_sb): Allow disabling of sb
+ nesting checks when appropriate.
+ (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.
+ * read.c (read_a_source_file): Add parameter to check_macro call,
+ and pass macro info to the macro hook, if defined.
+ (insert_line): New. Allow insertion of a line of characters into
+ the input stream.
+ (insert_file): New. Allow insertion of an arbitrary file into the
+ input stream.
+ * read.h: New prototypes added.
+ * sb.c: Initialize no_macro_check field.
+ * sb.h: Add no_macro_check field for line substitution support.
+ * internals.texi: Document new macro hooks.
+
2000-02-23 Linas Vepstas <linas@linas.org>
* config/tc-i370.c, config/tc-i370.h: New files.
Index: gas/gasp.c
===================================================================
RCS file: /cvs/src/src/gas/gasp.c,v
retrieving revision 1.4
diff -d -c -p -r1.4 gasp.c
*** gasp.c 2000/01/26 22:48:31 1.4
--- gasp.c 2000/02/23 16:13:28
*************** macro_op (idx, in)
*** 2692,2698 ****
return 0;
sb_terminate (in);
! if (! check_macro (in->ptr + idx, &out, comment_char, &err))
return 0;
if (err != NULL)
--- 2692,2698 ----
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/02/23 16:13:28
*************** input_scrub_include_sb (from, position)
*** 259,267 ****
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);
--- 259,279 ----
sb *from;
char *position;
{
! /* I put this flag so that it's possible to do a wholesale
! replace of a single line w/o disrupting the input stream; if the checking
! is enabled, substitutions on lines like " .if SUBS" will fail, thinking
! they have to see ".endif" before the end of the single-line sb
! twall@cygnus.com
! */
! if (!from->no_macro_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);
*************** input_scrub_include_sb (from, position)
*** 272,277 ****
--- 284,290 ----
sb_add_char (&from_sb, '\n');
}
sb_add_sb (&from_sb, from);
+ from_sb.no_macro_check = from->no_macro_check;
sb_index = 1;
/* These variables are reset by input_scrub_push. Restore them
*************** input_scrub_next_buffer (bufp)
*** 296,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);
--- 309,325 ----
{
if (sb_index >= from_sb.len)
{
+ int macro_check = !from_sb.no_macro_check;
sb_kill (&from_sb);
! if (macro_check)
! {
! 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/02/23 16:13:29
*************** 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;
--- 1108,1119 ----
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;
+ void **info;
{
const char *s;
char *copy, *cs;
*************** check_macro (line, expand, comment_char,
*** 1152,1157 ****
--- 1153,1162 ----
*error = macro_expand (0, &line_sb, macro, expand, comment_char);
sb_kill (&line_sb);
+
+ /* export the macro information if requested */
+ if (info)
+ *info = (void *)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/02/23 16:13:29
*************** 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));
--- 45,52 ----
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 **,
! void **));
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.15
diff -d -c -p -r1.15 read.c
*** read.c 2000/02/10 21:03:12 1.15
--- read.c 2000/02/23 16:13:29
*************** read_a_source_file (name)
*** 872,879 ****
{
sb out;
const char *err;
! if (check_macro (s, &out, '\0', &err))
{
if (err != NULL)
as_bad ("%s", err);
--- 872,880 ----
{
sb out;
const char *err;
+ void *macro;
! if (check_macro (s, &out, '\0', &err, ¯o))
{
if (err != NULL)
as_bad ("%s", err);
*************** read_a_source_file (name)
*** 883,888 ****
--- 884,892 ----
sb_kill (&out);
buffer_limit =
input_scrub_next_buffer (&input_line_pointer);
+ #ifdef md_macro_info
+ md_macro_info (macro);
+ #endif
continue;
}
}
*************** read_print_statistics (file)
*** 5112,5117 ****
--- 5116,5157 ----
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.
+ This function allows easy substition of input lines when called by
+ md_start_line_hook(). The line is assumed to already be properly
+ scrubbed.
+ */
+
+ void
+ insert_line (line)
+ const char *line;
+ {
+ sb newline;
+ sb_new (&newline);
+ while (*line != 0)
+ sb_add_char (&newline, *line++);
+ newline.no_macro_check = 1;
+ input_scrub_include_sb (&newline, input_line_pointer);
+ 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
+ insert_file (path)
+ const 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/read.h
===================================================================
RCS file: /cvs/src/src/gas/read.h,v
retrieving revision 1.4
diff -d -c -p -r1.4 read.h
*** read.h 2000/02/08 19:06:00 1.4
--- read.h 2000/02/23 16:13:29
*************** extern void stabs_generate_asm_func PARA
*** 118,123 ****
--- 118,125 ----
extern void stabs_generate_asm_endfunc PARAMS ((const char *, const char *));
extern void do_repeat PARAMS((int,const char *,const char *));
extern void end_repeat PARAMS((int));
+ extern void insert_line PARAMS((const char *line));
+ extern void insert_file PARAMS((const char *filename));
extern void generate_lineno_debug PARAMS ((void));
Index: gas/sb.c
===================================================================
RCS file: /cvs/src/src/gas/sb.c,v
retrieving revision 1.1.1.1
diff -d -c -p -r1.1.1.1 sb.c
*** sb.c 1999/05/03 07:28:41 1.1.1.1
--- sb.c 2000/02/23 16:13:29
*************** sb_build (ptr, size)
*** 92,97 ****
--- 92,98 ----
ptr->pot = size;
ptr->len = 0;
ptr->item = e;
+ ptr->no_macro_check = 0;
}
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/02/23 16:13:29
*************** typedef struct sb
*** 58,63 ****
--- 58,64 ----
int len; /* how much is used. */
int pot; /* the maximum length is 1<<pot */
struct le *item;
+ int no_macro_check; /* skip macro/conditional nest checking */
}
sb;
Index: gas/doc/internals.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/internals.texi,v
retrieving revision 1.6
diff -d -c -p -r1.6 internals.texi
*** internals.texi 2000/02/10 21:00:10 1.6
--- internals.texi 2000/02/23 16:13:30
*************** If you define this macro, GAS will call
*** 1229,1234 ****
--- 1229,1252 ----
GAS will call this function for each section at the end of the assembly, to
permit the CPU backend to adjust the alignment of a section.
+ @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