Add macro handling extensions and line substitution support.
authorTimothy Wall <twall@alum.mit.edu>
Sun, 26 Mar 2000 14:47:33 +0000 (14:47 +0000)
committerTimothy Wall <twall@alum.mit.edu>
Sun, 26 Mar 2000 14:47:33 +0000 (14:47 +0000)
gas/ChangeLog
gas/as.h
gas/doc/internals.texi
gas/gasp.c
gas/input-scrub.c
gas/macro.c
gas/macro.h
gas/read.c
gas/sb.h

index e532a7669187c7f9c0714b5ae7fdf16351209328..591d0b39ea7294e9b8309e49c42fb485a0a7255a 100644 (file)
@@ -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
index 9efd7aba43dcdac8faa9b515ed557a6e3a80679f..4c4658a04d354094cc8a97fa808059fce59fd052 100644 (file)
--- 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));
index 1e05131df7a002146aee485aea751b7c12367b35..3be8b8128174867e4b9e0fac061216113d55bd56 100644 (file)
@@ -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
index 629e0c0478bc5d781642a5042e26fe6fbaeb20f6..b35a4ae57c1671b23e3eeaa08d3e748b489ca2ed 100644 (file)
@@ -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)
index 46a3bb3b7f81c0b19f10906bc066dd8c91db01df..ecbdaef7fda5946b2491ba68791c5a939bcac396 100644 (file)
@@ -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);
index 7407f1d11495a3a57895408571ab11a14a630432..12a757e22389c71ce0953587db18e57bfc9d0c86 100644 (file)
@@ -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;
 }
 
index cdeea4ad3b475076194090b73dde36766e0248e0..9c61acd89a97bc4ca306228ce5e536dbaa1cc081 100644 (file)
 #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));
index b8afe1c2e24a2be2a22cbd1122de732be2e0656f..15228426af143f713174b9bb69d4255ab880c86f 100644 (file)
@@ -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 */
index 7e6daf167de2b4156523705b64c504acf299d0b5..7eaed258a3b0c2955e2b3b637e63c90182a3049d 100644 (file)
--- 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 */