add more direct/unpack code
[deliverable/binutils-gdb.git] / gas / gasp.c
index acc7b93c18bd7cb95b1af724870303e921d542ae..3fb51b84b61f1504696c235579d33d530bb2486f 100644 (file)
@@ -1,5 +1,5 @@
 /* gasp.c - Gnu assembler preprocessor main program.
-   Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1994, 95, 96, 1997 Free Software Foundation, Inc.
 
    Written by Steve and Judy Chamberlain of Cygnus Support,
       sac@cygnus.com
@@ -65,9 +65,16 @@ extern char *malloc ();
 
 #include "ansidecl.h"
 #include "libiberty.h"
+#include "sb.h"
+#include "macro.h"
 
 char *program_version = "1.2";
 
+/* This is normally declared in as.h, but we don't include that.  We
+   need the function because other files linked with gasp.c might call
+   it.  */
+extern void as_abort PARAMS ((const char *, int, const char *));
+
 #define MAX_INCLUDES 30                /* Maximum include depth */
 #define MAX_REASONABLE 1000    /* Maximum number of expansions */
 
@@ -88,58 +95,6 @@ int had_end; /* Seen .END */
 /* The output stream */
 FILE *outfile;
 
-/* string blocks
-
-   I had a couple of choices when deciding upon this data structure.
-   gas uses null terminated strings for all its internal work.  This
-   often means that parts of the program that want to examine
-   substrings have to manipulate the data in the string to do the
-   right thing (a common operation is to single out a bit of text by
-   saving away the character after it, nulling it out, operating on
-   the substring and then replacing the character which was under the
-   null).  This is a pain and I remember a load of problems that I had with
-   code in gas which almost got this right.  Also, it's harder to grow and
-   allocate null terminated strings efficiently.
-
-   Obstacks provide all the functionality needed, but are too
-   complicated, hence the sb.
-
-   An sb is allocated by the caller, and is initialzed to point to an
-   sb_element.  sb_elements are kept on a free lists, and used when
-   needed, replaced onto the free list when unused.
- */
-
-#define max_power_two    30    /* don't allow strings more than
-                                  2^max_power_two long */
-/* structure of an sb */
-typedef struct sb
-  {
-    char *ptr;                 /* points to the current block. */
-    int len;                   /* how much is used. */
-    int pot;                   /* the maximum length is 1<<pot */
-    struct le *item;
-  }
-sb;
-
-/* Structure of the free list object of an sb */
-typedef struct le
-  {
-    struct le *next;
-    int size;
-    char data[1];
-  }
-sb_element;
-
-/* The free list */
-typedef struct
-  {
-    sb_element *size[max_power_two];
-  } sb_list_vector;
-
-sb_list_vector free_list;
-
-int string_count[max_power_two];
-
 /* the attributes of each character are stored as a bit pattern
    chartype, which gives us quick tests. */
 
@@ -298,10 +253,6 @@ include_stack[MAX_INCLUDES];
 struct include_stack *sp;
 #define isp (sp - include_stack)
 
-#define dsize 5
-
-
-
 /* Include file list */
 
 typedef struct include_path 
@@ -315,20 +266,6 @@ include_path *paths_tail;
 
 
 static void quit PARAMS ((void));
-static void sb_build PARAMS ((sb *, int));
-static void sb_new PARAMS ((sb *));
-static void sb_kill PARAMS ((sb *));
-static void sb_add_sb PARAMS ((sb *, sb *));
-static void sb_check PARAMS ((sb *, int));
-static void sb_reset PARAMS ((sb *));
-static void sb_add_char PARAMS ((sb *, int));
-static void sb_add_string PARAMS ((sb *, const char *));
-static void sb_add_buffer PARAMS ((sb *, const char *, int));
-static void sb_print PARAMS ((sb *));
-static void sb_print_at PARAMS ((int, sb *));
-static char *sb_name PARAMS ((sb *));
-static int sb_skip_white PARAMS ((int, sb *));
-static int sb_skip_comma PARAMS ((int, sb *));
 static void hash_new_table PARAMS ((int, hash_table *));
 static int hash PARAMS ((sb *));
 static hash_entry *hash_create PARAMS ((hash_table *, sb *));
@@ -393,7 +330,6 @@ static int condass_on PARAMS ((void));
 static void do_if PARAMS ((int, sb *, int));
 static int get_mri_string PARAMS ((int, sb *, sb *, int));
 static void do_ifc PARAMS ((int, sb *, int));
-static void buffer_and_nest PARAMS ((const char *, const char *, sb *));
 static void do_aendr PARAMS ((void));
 static void do_awhile PARAMS ((int, sb *));
 static void do_aendw PARAMS ((void));
@@ -401,16 +337,8 @@ static void do_exitm PARAMS ((void));
 static void do_arepeat PARAMS ((int, sb *));
 static void do_endm PARAMS ((void));
 static void do_irp PARAMS ((int, sb *, int));
-static int do_formals PARAMS ((macro_entry *, int, sb *));
 static void do_local PARAMS ((int, sb *));
 static void do_macro PARAMS ((int, sb *));
-static int get_token PARAMS ((int, sb *, sb *));
-static int get_apost_token PARAMS ((int, sb *, sb *, int));
-static int sub_actual
-  PARAMS ((int, sb *, sb *, hash_table *, int, sb *, int));
-static void macro_expand_body
-  PARAMS ((sb *, sb *, sb *, formal_entry *, hash_table *));
-static void macro_expand PARAMS ((sb *, int, sb *, macro_entry *));
 static int macro_op PARAMS ((int, sb *));
 static int getstring PARAMS ((int, sb *, sb *));
 static void do_sdata PARAMS ((int, sb *, int));
@@ -451,7 +379,7 @@ quit ()
   if (stats) 
     {
       int i;
-      for (i = 0; i < max_power_two; i++) 
+      for (i = 0; i < sb_max_power_two; i++) 
        {
          fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
        }
@@ -459,241 +387,6 @@ quit ()
   exit (exitcode);
 }
 
-
-/* this program is about manipulating strings.
-   they are managed in things called `sb's which is an abbreviation
-   for string buffers.  an sb has to be created, things can be glued
-   on to it, and at the end of it's life it should be freed.  the
-   contents should never be pointed at whilst it is still growing,
-   since it could be moved at any time
-
-   eg:
-   sb_new (&foo);
-   sb_grow... (&foo,...);
-   use foo->ptr[*];
-   sb_kill (&foo);
-
-*/
-
-/* initializes an sb. */
-
-static void
-sb_build (ptr, size)
-     sb *ptr;
-     int size;
-{
-  /* see if we can find one to allocate */
-  sb_element *e;
-
-  if (size > max_power_two)
-    {
-      FATAL ((stderr, "string longer than %d bytes requested.\n",
-             1 << max_power_two));
-    }
-  e = free_list.size[size];
-  if (!e)
-    {
-      /* nothing there, allocate one and stick into the free list */
-      e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
-      e->next = free_list.size[size];
-      e->size = 1 << size;
-      free_list.size[size] = e;
-      string_count[size]++;
-    }
-
-  /* remove from free list */
-
-  free_list.size[size] = e->next;
-
-  /* copy into callers world */
-  ptr->ptr = e->data;
-  ptr->pot = size;
-  ptr->len = 0;
-  ptr->item = e;
-}
-
-
-static void
-sb_new (ptr)
-     sb *ptr;
-{
-  sb_build (ptr, dsize);
-}
-
-/* deallocate the sb at ptr */
-
-static
-void
-sb_kill (ptr)
-     sb *ptr;
-{
-  /* return item to free list */
-  ptr->item->next = free_list.size[ptr->pot];
-  free_list.size[ptr->pot] = ptr->item;
-}
-
-/* add the sb at s to the end of the sb at ptr */
-
-static void sb_check ();
-
-static
-void
-sb_add_sb (ptr, s)
-     sb *ptr;
-     sb *s;
-{
-  sb_check (ptr, s->len);
-  memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
-  ptr->len += s->len;
-}
-
-/* make sure that the sb at ptr has room for another len characters,
-   and grow it if it doesn't. */
-
-static void
-sb_check (ptr, len)
-     sb *ptr;
-     int len;
-{
-  if (ptr->len + len >= 1 << ptr->pot)
-    {
-      sb tmp;
-      int pot = ptr->pot;
-      while (ptr->len + len >= 1 << pot)
-       pot++;
-      sb_build (&tmp, pot);
-      sb_add_sb (&tmp, ptr);
-      sb_kill (ptr);
-      *ptr = tmp;
-    }
-}
-
-/* make the sb at ptr point back to the beginning.  */
-
-static void
-sb_reset (ptr)
-     sb *ptr;
-{
-  ptr->len = 0;
-}
-
-/* add character c to the end of the sb at ptr. */
-
-static void
-sb_add_char (ptr, c)
-     sb *ptr;
-     int c;
-{
-  sb_check (ptr, 1);
-  ptr->ptr[ptr->len++] = c;
-}
-
-/* add null terminated string s to the end of sb at ptr. */
-
-static void
-sb_add_string (ptr, s)
-     sb *ptr;
-     const char *s;
-{
-  int len = strlen (s);
-  sb_check (ptr, len);
-  memcpy (ptr->ptr + ptr->len, s, len);
-  ptr->len += len;
-}
-
-/* add string at s of length len to sb at ptr */
-
-static void
-sb_add_buffer (ptr, s, len)
-     sb *ptr;
-     const char *s;
-     int len;
-{
-  sb_check (ptr, len);
-  memcpy (ptr->ptr + ptr->len, s, len);
-  ptr->len += len;
-}
-
-
-/* print the sb at ptr to the output file */
-
-static
-void
-sb_print (ptr)
-     sb *ptr;
-{
-  int i;
-  int nc = 0;
-
-  for (i = 0; i < ptr->len; i++)
-    {
-      if (nc)
-       {
-         fprintf (outfile, ",");
-       }
-      fprintf (outfile, "%d", ptr->ptr[i]);
-      nc = 1;
-    }
-}
-
-static void 
-sb_print_at (idx, ptr)
-     int idx;
-     sb *ptr;
-{
-  int i;
-  for (i = idx; i < ptr->len; i++)
-    putc (ptr->ptr[i], outfile);
-}
-/* put a null at the end of the sb at in and return the start of the
-   string, so that it can be used as an arg to printf %s. */
-
-static
-char *
-sb_name (in)
-     sb *in;
-{
-  /* stick a null on the end of the string */
-  sb_add_char (in, 0);
-  return in->ptr;
-}
-
-/* start at the index idx into the string in sb at ptr and skip
-   whitespace. return the index of the first non whitespace character */
-
-static int
-sb_skip_white (idx, ptr)
-     int idx;
-     sb *ptr;
-{
-  while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
-    idx++;
-  return idx;
-}
-
-/* start at the index idx into the sb at ptr. skips whitespace,
-   a comma and any following whitespace. returnes the index of the
-   next character. */
-
-static int
-sb_skip_comma (idx, ptr)
-     int idx;
-     sb *ptr;
-{
-  while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
-    idx++;
-
-  if (idx < ptr->len
-      && ptr->ptr[idx] == ',')
-    idx++;
-
-  while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
-    idx++;
-
-  return idx;
-}
-
-
 /* hash table maintenance. */
 
 /* build a new hash table with size buckets, and fill in the info at ptr. */
@@ -782,7 +475,7 @@ hash_add_to_string_table (tab, key, name, again)
   if (ptr->value.s.len)
     {
       if (!again)
-       ERROR ((stderr, "redefintion not allowed"));
+       ERROR ((stderr, "redefinition not allowed\n"));
     }
 
   ptr->type = hash_string;
@@ -1276,7 +969,7 @@ include_print_where_line (file)
 
   while (p <= sp)
     {
-      fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - ((p == sp) ? 1 : 0));
+      fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
       p++;
     }
 }
@@ -1415,7 +1108,21 @@ change_base (idx, in, out)
 
   while (idx < in->len)
     {
-      if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
+      if (in->ptr[idx] == '\\'
+         && idx + 1 < in->len
+         && in->ptr[idx + 1] == '(')
+       {
+         idx += 2;
+         while (idx < in->len
+                && in->ptr[idx] != ')')
+           {
+             sb_add_char (out, in->ptr[idx]);
+             idx++;
+           }
+         if (idx < in->len)
+           idx++;
+       }
+      else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
        {
          int base;
          int value;
@@ -1680,7 +1387,7 @@ do_data (idx, in, size)
        }
     }
   sb_kill (&acc);
-  sb_print_at (idx, in);
+  sb_print_at (outfile, idx, in);
   fprintf (outfile, "\n");
 }
 
@@ -1711,15 +1418,29 @@ do_align (idx, in)
      int idx;
      sb *in;
 {
-  int al;
+  int al, have_fill, fill;
+
   idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
+  idx = sb_skip_white (idx, in);
+  have_fill = 0;
+  fill = 0;
+  if (! eol (idx, in))
+    {
+      idx = sb_skip_comma (idx, in);
+      idx = exp_get_abs (".align needs absolute fill value.\n", idx, in,
+                        &fill);
+      have_fill = 1;
+    }
 
   if (al != 1
       && al != 2
       && al != 4)
     WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
 
-  fprintf (outfile, ".align    %d\n", al);
+  fprintf (outfile, ".align    %d", al);
+  if (have_fill)
+    fprintf (outfile, ",%d", fill);
+  fprintf (outfile, "\n");
 }
 
 /* .res[.b|.w|.l] <size> */
@@ -2073,11 +1794,24 @@ process_assigns (idx, in, buf)
     {
       hash_entry *ptr;
       if (in->ptr[idx] == '\\'
+         && idx + 1 < in->len
+         && in->ptr[idx + 1] == '(')
+       {
+         do
+           {
+             sb_add_char (buf, in->ptr[idx]);
+             idx++;
+           }
+         while (idx < in->len && in->ptr[idx - 1] != ')');
+       }
+      else if (in->ptr[idx] == '\\'
+         && idx + 1 < in->len
          && in->ptr[idx + 1] == '&')
        {
          idx = condass_lookup_name (in, idx + 2, buf, 1);
        }
       else if (in->ptr[idx] == '\\'
+              && idx + 1 < in->len
               && in->ptr[idx + 1] == '$')
        {
          idx = condass_lookup_name (in, idx + 2, buf, 0);
@@ -2177,23 +1911,54 @@ process_file ()
          if (condass_on ())
            fprintf (outfile, "\n");
        }
+      else if (mri
+              && (line.ptr[0] == '*'
+                  || line.ptr[0] == '!'))
+       {
+         /* MRI line comment.  */
+         fprintf (outfile, sb_name (&line));
+       }
       else
        {
          l = grab_label (&line, &label_in);
          sb_reset (&label);              
-         if (label_in.len)
-           {
-             /* Munge any label */
-
-             
-             process_assigns (0, &label_in, &label);
-           }
 
          if (line.ptr[l] == ':')
            l++;
          while (ISWHITE (line.ptr[l]) && l < line.len)
            l++;
 
+         if (label_in.len)
+           {
+             int do_assigns;
+
+             /* Munge the label, unless this is EQU or ASSIGN.  */
+             do_assigns = 1;
+             if (l < line.len
+                 && (line.ptr[l] == '.' || alternate || mri))
+               {
+                 int lx = l;
+
+                 if (line.ptr[lx] == '.')
+                   ++lx;
+                 if (lx + 3 <= line.len
+                     && strncasecmp ("EQU", line.ptr + lx, 3) == 0
+                     && (lx + 3 == line.len
+                         || ! ISFIRSTCHAR (line.ptr[lx + 3])))
+                   do_assigns = 0;
+                 else if (lx + 6 <= line.len
+                          && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
+                          && (lx + 6 == line.len
+                              || ! ISFIRSTCHAR (line.ptr[lx + 6])))
+                   do_assigns = 0;
+               }
+
+             if (do_assigns)
+               process_assigns (0, &label_in, &label);
+             else
+               sb_add_sb (&label, &label_in);
+           }
+
          if (l < line.len)
            {
              if (process_pseudo_op (l, &line, &acc))
@@ -2325,9 +2090,15 @@ do_reg (idx, in)
 {
   /* remove reg stuff from inside parens */
   sb what;
-  idx = skip_openp (idx, in);
+  if (!mri)
+    idx = skip_openp (idx, in);
+  else
+    idx = sb_skip_white (idx, in);
   sb_new (&what);
-  while (idx < in->len && in->ptr[idx] != ')')
+  while (idx < in->len
+        && (mri
+            ? ! eol (idx, in)
+            : in->ptr[idx] != ')'))
     {
       sb_add_char (&what, in->ptr[idx]);
       idx++;
@@ -2690,89 +2461,6 @@ do_ifc (idx, in, ifnc)
   ifstack[ifi].hadelse = 0;
 }
 
-/* Read input lines till we get to a TO string.
-   Increase nesting depth if we geta FROM string.
-   Put the results into sb at PTR. */
-
-static void
-buffer_and_nest (from, to, ptr)
-     const char *from;
-     const char *to;
-     sb *ptr;
-{
-  int from_len = strlen (from);
-  int to_len = strlen (to);
-  int depth = 1;
-  int line_start = ptr->len;
-  int line = linecount ();
-
-  int more = get_line (ptr);
-
-  while (more)
-    {
-      /* Try and find the first pseudo op on the line */
-      int i = line_start;
-
-      if (!alternate && !mri)
-       {
-         /* With normal syntax we can suck what we want till we get
-            to the dot.  With the alternate, labels have to start in
-            the first column, since we cant tell what's a label and
-            whats a pseudoop */
-
-         /* Skip leading whitespace */
-         while (i < ptr->len
-                && ISWHITE (ptr->ptr[i]))
-           i++;
-
-         /* Skip over a label */
-         while (i < ptr->len
-                && ISNEXTCHAR (ptr->ptr[i]))
-           i++;
-
-         /* And a colon */
-         if (i < ptr->len
-             && ptr->ptr[i] == ':')
-           i++;
-
-       }
-      /* Skip trailing whitespace */
-      while (i < ptr->len
-            && ISWHITE (ptr->ptr[i]))
-       i++;
-
-      if (i < ptr->len && (ptr->ptr[i] == '.' 
-                          || alternate
-                          || mri))
-       {
-         if (ptr->ptr[i] == '.')
-             i++;
-         if (strncasecmp (ptr->ptr + i, from, from_len) == 0)
-           depth++;
-         if (strncasecmp (ptr->ptr + i, to, to_len) == 0)
-           {
-             depth--;
-             if (depth == 0)
-               {
-                 /* Reset the string to not include the ending rune */
-                 ptr->len = line_start;
-                 break;
-               }
-           }
-       }
-
-      /* Add a CR to the end and keep running */
-      sb_add_char (ptr, '\n');
-      line_start = ptr->len;
-      more = get_line (ptr);
-    }
-
-
-  if (depth)
-    FATAL ((stderr, "End of file whilst inside %s, started on line %d.\n", from, line));
-}
-
-
 /* .ENDR */
 static void
 do_aendr ()
@@ -2791,18 +2479,19 @@ do_awhile (idx, in)
      int idx;
      sb *in;
 {
+  int line = linecount ();
   sb exp;
-
   sb sub;
-
   int doit;
+
   sb_new (&sub);
   sb_new (&exp);
 
   process_assigns (idx, in, &exp);
   doit = istrue (0, &exp);
 
-  buffer_and_nest ("AWHILE", "AENDW", &sub);
+  if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
+    FATAL ((stderr, "AWHILE without a AENDW at %d.\n", line - 1));
 
   /* Turn
        .AWHILE exp
@@ -2873,20 +2562,25 @@ do_arepeat (idx, in)
      int idx;
      sb *in;
 {
+  int line = linecount ();
   sb exp;                      /* buffer with expression in it */
   sb copy;                     /* expanded repeat block */
   sb sub;                      /* contents of AREPEAT */
   int rc;
+  int ret;
   char buffer[30];
+
   sb_new (&exp);
   sb_new (&copy);
   sb_new (&sub);
   process_assigns (idx, in, &exp);
   idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
   if (!mri)
-    buffer_and_nest ("AREPEAT", "AENDR", &sub);
+    ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
   else
-    buffer_and_nest ("REPT", "ENDR", &sub);
+    ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
+  if (! ret)
+    FATAL ((stderr, "AREPEAT without a AENDR at %d.\n", line - 1));
   if (rc > 0)
     {
       /* Push back the text following the repeat, and another repeat block
@@ -2939,174 +2633,22 @@ do_irp (idx, in, irpc)
      sb *in;
      int irpc;
 {
-  const char *mn;
-  sb sub;
-  formal_entry f;
-  hash_table h;
-  hash_entry *p;
-  sb name;
+  const char *err;
   sb out;
 
-  if (irpc)
-    mn = "IRPC";
-  else
-    mn = "IRP";
-
-  idx = sb_skip_white (idx, in);
-
-  sb_new (&sub);
-  buffer_and_nest (mn, "ENDR", &sub);
-  
-  sb_new (&f.name);
-  sb_new (&f.def);
-  sb_new (&f.actual);
-
-  idx = get_token (idx, in, &f.name);
-  if (f.name.len == 0)
-    {
-      ERROR ((stderr, "Missing model parameter in %s", mn));
-      return;
-    }
-
-  hash_new_table (1, &h);
-  p = hash_create (&h, &f.name);
-  p->type = hash_formal;
-  p->value.f = &f;
-
-  f.index = 1;
-  f.next = NULL;
-
-  sb_new (&name);
-  sb_add_string (&name, mn);
-
   sb_new (&out);
 
-  idx = sb_skip_comma (idx, in);
-  if (eol (idx, in))
-    {
-      /* Expand once with a null string.  */
-      macro_expand_body (&name, &sub, &out, &f, &h);
-      fprintf (outfile, "%s", sb_name (&out));
-    }
-  else
-    {
-      while (!eol (idx, in))
-       {
-         if (!irpc)
-           idx = get_any_string (idx, in, &f.actual, 1, 0);
-         else
-           {
-             sb_reset (&f.actual);
-             sb_add_char (&f.actual, in->ptr[idx]);
-             ++idx;
-           }
-         sb_reset (&out);
-         macro_expand_body (&name, &sub, &out, &f, &h);
-         fprintf (outfile, "%s", sb_name (&out));
-         if (!irpc)
-           idx = sb_skip_comma (idx, in);
-         else
-           idx = sb_skip_white (idx, in);
-       }
-    }
+  err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
+  if (err != NULL)
+    ERROR ((stderr, "%s\n", err));
+
+  fprintf (outfile, "%s", sb_terminate (&out));
 
-  sb_kill (&sub);
-  sb_kill (&name);
   sb_kill (&out);
 }
 
 /* MACRO PROCESSING */
 
-static int number;
-hash_table macro_table;
-
-/* Understand
-
-   .MACRO <name>
-   stuff
-   .ENDM
-*/
-
-static int
-do_formals (macro, idx, in)
-     macro_entry *macro;
-     int idx;
-     sb *in;
-{
-  formal_entry **p = &macro->formals;
-  macro->formal_count = 0;
-  hash_new_table (5, &macro->formal_hash);
-  while (idx < in->len)
-    {
-      formal_entry *formal;
-
-      formal = (formal_entry *) xmalloc (sizeof (formal_entry));
-
-      sb_new (&formal->name);
-      sb_new (&formal->def);
-      sb_new (&formal->actual);
-
-      idx = sb_skip_white (idx, in);
-      idx = get_token (idx, in, &formal->name);
-      if (formal->name.len == 0)
-       break;
-      idx = sb_skip_white (idx, in);
-      if (formal->name.len)
-       {
-         /* This is a formal */
-         if (idx < in->len && in->ptr[idx] == '=')
-           {
-             /* Got a default */
-             idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
-           }
-       }
-
-      {
-       /* Add to macro's hash table */
-
-       hash_entry *p = hash_create (&macro->formal_hash, &formal->name);
-       p->type = hash_formal;
-       p->value.f = formal;
-      }
-
-      formal->index = macro->formal_count;
-      idx = sb_skip_comma (idx, in);
-      macro->formal_count++;
-      *p = formal;
-      p = &formal->next;
-      *p = NULL;
-    }
-
-  if (mri)
-    {
-      formal_entry *formal;
-
-      /* Add a special NARG formal, which macro_expand will set to the
-         number of arguments.  */
-      formal = (formal_entry *) xmalloc (sizeof (formal_entry));
-
-      sb_new (&formal->name);
-      sb_new (&formal->def);
-      sb_new (&formal->actual);
-
-      sb_add_string (&formal->name, "NARG");
-
-      {
-       /* Add to macro's hash table */
-
-       hash_entry *p = hash_create (&macro->formal_hash, &formal->name);
-       p->type = hash_formal;
-       p->value.f = formal;
-      }
-
-      formal->index = -2;
-      *p = formal;
-      formal->next = NULL;
-    }
-
-  return idx;
-}
-
 /* Parse off LOCAL n1, n2,... Invent a label name for it */
 static
 void 
@@ -3114,519 +2656,52 @@ do_local (idx, line)
      int idx;
      sb *line;
 {
-  static int ln;
-  sb acc;
-  sb sub;
-  char subs[10];
-  sb_new (&acc);
-  sb_new (&sub);
-  idx = sb_skip_white (idx, line);
-  while (!eol(idx, line))
-    {
-      sb_reset (&acc);
-      sb_reset (&sub);
-      ln++;
-      sprintf(subs, "LL%04x", ln);
-      idx =  get_token(idx, line, &acc);
-      sb_add_string (&sub, subs);
-      hash_add_to_string_table (&assign_hash_table, &acc, &sub, 1);
-      idx = sb_skip_comma (idx, line);
-    }
-  sb_kill (&sub);
-  sb_kill (&acc);
+  ERROR ((stderr, "LOCAL outside of MACRO"));
 }
 
-static
-void
+static void
 do_macro (idx, in)
      int idx;
      sb *in;
 {
-  macro_entry *macro;
-  sb name;
-
-  macro = (macro_entry *) xmalloc (sizeof (macro_entry));
-  sb_new (&macro->sub);
-  sb_new (&name);
-
-  macro->formal_count = 0;
-  macro->formals = 0;
-
-  idx = sb_skip_white (idx, in);
-  buffer_and_nest ("MACRO", "ENDM", &macro->sub);
-  if (label.len)
-    {
-
-      sb_add_sb (&name, &label);
-      if (in->ptr[idx] == '(')
-       {
-         /* It's the label: MACRO (formals,...)  sort */
-         idx = do_formals (macro, idx + 1, in);
-         if (in->ptr[idx] != ')')
-           ERROR ((stderr, "Missing ) after formals.\n"));
-       }
-      else {
-       /* It's the label: MACRO formals,...  sort */
-       idx = do_formals (macro, idx, in);
-      }
-    }
-  else
-    {
-      idx = get_token (idx, in, &name);
-      idx = sb_skip_white (idx, in);
-      idx = do_formals (macro, idx, in);
-    }
-
-  /* and stick it in the macro hash table */
-  hash_create (&macro_table, &name)->value.m = macro;
-}
-
-static
-int
-get_token (idx, in, name)
-     int idx;
-     sb *in;
-     sb *name;
-{
-  if (idx < in->len
-      && ISFIRSTCHAR (in->ptr[idx]))
-    {
-      sb_add_char (name, in->ptr[idx++]);
-      while (idx < in->len
-            && ISNEXTCHAR (in->ptr[idx]))
-       {
-         sb_add_char (name, in->ptr[idx++]);
-       }
-    }
-  /* Ignore trailing & */
-  if (alternate && idx < in->len && in->ptr[idx] == '&')
-    idx++;
-  return idx;
-}
+  const char *err;
+  int line = linecount ();
 
-/* Scan a token, but stop if a ' is seen */
-static int
-get_apost_token (idx, in, name, kind)
-     int idx;
-     sb *in;
-     sb *name;
-     int kind;
-{
-  idx = get_token (idx, in, name);
-  if (idx < in->len && in->ptr[idx] == kind)
-    idx++;
-  return idx;
+  err = define_macro (idx, in, &label, get_line, (const char **) NULL);
+  if (err != NULL)
+    ERROR ((stderr, "macro at line %d: %s\n", line - 1, err));
 }
 
 static int
-sub_actual (src, in, t, formal_hash, kind, out, copyifnotthere)
-     int src;
-     sb *in;
-     sb *t;
-     hash_table *formal_hash;
-     int kind;
-     sb *out;
-     int copyifnotthere;
-{
-  /* This is something to take care of */
-  hash_entry *ptr;
-  src = get_apost_token (src, in, t, kind);
-  /* See if it's in the macro's hash table */
-  ptr = hash_lookup (formal_hash, t);
-  if (ptr)
-    {
-      if (ptr->value.f->actual.len)
-       {
-         sb_add_sb (out, &ptr->value.f->actual);
-       }
-      else
-       {
-         sb_add_sb (out, &ptr->value.f->def);
-       }
-    }
-  else if (copyifnotthere)
-    {
-      sb_add_sb (out, t);
-    }
-  else 
-    {
-      sb_add_char (out, '\\');
-      sb_add_sb (out, t);
-    }
-  return src;
-}
-
-/* Copy the body from the macro buffer into a safe place and
-   substitute any args.  */
-
-static void
-macro_expand_body (name, in, out, formals, formal_hash)
-     sb *name;
-     sb *in;
-     sb *out;
-     formal_entry *formals;
-     hash_table *formal_hash;
-{
-  sb t;
-  int src = 0;
-  int inquote = 0;
-
-  sb_new (&t);
-
-  while (src < in->len)
-    {
-      if (in->ptr[src] == '&')
-       {
-         sb_reset (&t);
-         if (mri && src + 1 < in->len && in->ptr[src + 1] == '&')
-           {
-             src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
-           }
-         else
-           {
-             src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
-           }
-       }
-      else if (in->ptr[src] == '\\')
-       {
-         src++;
-         if (in->ptr[src] == comment_char)
-           {
-             /* This is a comment, just drop the rest of the line */
-             while (src < in->len
-                    && in->ptr[src] != '\n')
-               src++;
-
-           }
-         else if (in->ptr[src] == '(')
-           {
-             /* Sub in till the next ')' literally */
-             src++;
-             while (src < in->len && in->ptr[src] != ')')
-               {
-                 sb_add_char (out, in->ptr[src++]);
-               }
-             if (in->ptr[src] == ')')
-               src++;
-             else
-               ERROR ((stderr, "Missplaced ).\n"));
-           }
-         else if (in->ptr[src] == '@')
-           {
-             /* Sub in the macro invocation number */
-
-             char buffer[6];
-             src++;
-             sprintf (buffer, "%05d", number);
-             sb_add_string (out, buffer);
-           }
-         else if (in->ptr[src] == '&')
-           {
-             /* This is a preprocessor variable name, we don't do them
-                here */
-             sb_add_char (out, '\\');
-             sb_add_char (out, '&');
-             src++;
-           }
-         else if (mri
-                  && isalnum ((unsigned char) in->ptr[src]))
-           {
-             int ind;
-             formal_entry *f;
-
-             if (isdigit ((unsigned char) in->ptr[src]))
-               ind = in->ptr[src] - '0';
-             else if (isupper ((unsigned char) in->ptr[src]))
-               ind = in->ptr[src] - 'A' + 10;
-             else
-               ind = in->ptr[src] - 'a' + 10;
-             ++src;
-             for (f = formals; f != NULL; f = f->next)
-               {
-                 if (f->index == ind - 1)
-                   {
-                     if (f->actual.len != 0)
-                       sb_add_sb (out, &f->actual);
-                     else
-                       sb_add_sb (out, &f->def);
-                     break;
-                   }
-               }
-           }
-         else
-           {
-             sb_reset (&t);
-             src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
-           }
-       }
-      else if (ISFIRSTCHAR (in->ptr[src]) && (alternate || mri))
-       {
-         sb_reset (&t);
-         src = sub_actual (src, in, &t, formal_hash, '\'', out, 1);
-       }
-      else if (ISCOMMENTCHAR (in->ptr[src])
-              && src + 1 <  in->len
-              && ISCOMMENTCHAR (in->ptr[src+1])
-              && !inquote)
-       {
-         /* Two comment chars in a row cause the rest of the line to
-             be dropped.  */
-         while (src < in->len && in->ptr[src] != '\n')
-           src++;
-       }
-      else if (in->ptr[src] == '"'
-              || (mri && in->ptr[src] == '\''))
-       {
-         inquote = !inquote;
-         sb_add_char (out, in->ptr[src++]);
-       }
-      else if (mri
-              && in->ptr[src] == '='
-              && src + 1 < in->len
-              && in->ptr[src + 1] == '=')
-       {
-         hash_entry *ptr;
-
-         sb_reset (&t);
-         src = get_token (src + 2, in, &t);
-         ptr = hash_lookup (formal_hash, &t);
-         if (ptr == NULL)
-           {
-             ERROR ((stderr, "MACRO formal argument %s does not exist.\n",
-                     sb_name (&t)));
-           }
-         else
-           {
-             if (ptr->value.f->actual.len)
-               {
-                 sb_add_string (out, "-1");
-               }
-             else
-               {
-                 sb_add_char (out, '0');
-               }
-           }
-       }
-      else
-       {
-         sb_add_char (out, in->ptr[src++]);
-       }
-    }
-
-  sb_kill (&t);
-}
-
-static void
-macro_expand (name, idx, in, m)
-     sb *name;
+macro_op (idx, in)
      int idx;
      sb *in;
-     macro_entry *m;
 {
-  sb t;
+  const char *err;
   sb out;
-  hash_entry *ptr;
-  formal_entry *f;
-  int is_positional = 0;
-  int is_keyword = 0;
-  int narg = 0;
-
-  sb_new (&t);
-  sb_new (&out);
-  
-  /* Reset any old value the actuals may have */
-  for (f = m->formals; f; f = f->next)
-      sb_reset (&f->actual);
-  f = m->formals;
-
-  if (mri)
-    {
-      /* The macro may be called with an optional qualifier, which may
-         be referred to in the macro body as \0.  */
-      if (idx < in->len && in->ptr[idx] == '.')
-       {
-         formal_entry *n;
-
-         n = (formal_entry *) xmalloc (sizeof (formal_entry));
-         sb_new (&n->name);
-         sb_new (&n->def);
-         sb_new (&n->actual);
-         n->index = -1;
-
-         n->next = m->formals;
-         m->formals = n;
-
-         idx = get_any_string (idx + 1, in, &n->actual, 1, 0);
-       }
-    }
-
-  /* Peel off the actuals and store them away in the hash tables' actuals */
-  while (!eol(idx, in))
-    {
-      int scan;
-      idx = sb_skip_white (idx, in);
-      /* Look and see if it's a positional or keyword arg */
-      scan = idx;
-      while (scan < in->len
-            && !ISSEP (in->ptr[scan])
-            && (!alternate && in->ptr[scan] != '='))
-       scan++;
-      if (scan < in->len && (!alternate) && in->ptr[scan] == '=')
-       {
-         is_keyword = 1;
-         if (is_positional)
-           {
-             ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
-             return;
-           }
-         /* This is a keyword arg, fetch the formal name and
-            then the actual stuff */
-         sb_reset (&t);
-         idx = get_token (idx, in, &t);
-         if (in->ptr[idx] != '=')
-           ERROR ((stderr, "confused about formal params.\n"));
-
-         /* Lookup the formal in the macro's list */
-         ptr = hash_lookup (&m->formal_hash, &t);
-         if (!ptr)
-           {
-             ERROR ((stderr, "MACRO formal argument %s does not exist.\n", sb_name (&t)));
-             return;
-           }
-         else
-           {
-             /* Insert this value into the right place */
-             sb_reset (&ptr->value.f->actual);
-             idx = get_any_string (idx + 1, in, &ptr->value.f->actual, 0, 0);
-             if (ptr->value.f->actual.len > 0)
-               ++narg;
-           }
-       }
-      else
-       {
-         /* This is a positional arg */
-         is_positional = 1;
-         if (is_keyword)
-           {
-             ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
-             return;
-           }
-         if (!f)
-           {
-             formal_entry **pf;
-             int c;
-
-             if (!mri)
-               {
-                 ERROR ((stderr, "Too many positional arguments.\n"));
-                 return;
-               }
-             f = (formal_entry *) xmalloc (sizeof (formal_entry));
-             sb_new (&f->name);
-             sb_new (&f->def);
-             sb_new (&f->actual);
-             f->next = NULL;
-
-             c = -1;
-             for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
-               if ((*pf)->index >= c)
-                 c = (*pf)->index + 1;
-             *pf = f;
-             f->index = c;
-           }
-
-         sb_reset (&f->actual);
-         idx = get_any_string (idx, in, &f->actual, 1, 0);
-         if (f->actual.len > 0)
-           ++narg;
-         do
-           {
-             f = f->next;
-           }
-         while (f != NULL && f->index < 0);
-       }
-
-      idx = sb_skip_comma (idx, in);
-    }
+  sb name;
 
-  if (mri)
-    {
-      char buffer[20];
-
-      sb_reset (&t);
-      sb_add_string (&t, "NARG");
-      ptr = hash_lookup (&m->formal_hash, &t);
-      sb_reset (&ptr->value.f->actual);
-      sprintf (buffer, "%d", narg);
-      sb_add_string (&ptr->value.f->actual, buffer);
-    }
+  if (! macro_defined)
+    return 0;
 
-  macro_expand_body (name, &m->sub, &out, m->formals, &m->formal_hash);
+  sb_terminate (in);
+  if (! check_macro (in->ptr + idx, &out, comment_char, &err))
+    return 0;
 
-  include_buf (name, &out, include_macro, include_next_index ());
+  if (err != NULL)
+    ERROR ((stderr, "%s\n", err));
 
-  if (mri)
-    {
-      formal_entry **pf;
+  sb_new (&name);
+  sb_add_string (&name, "macro expansion");
 
-      /* Discard any unnamed formal arguments.  */
-      pf = &m->formals;
-      while (*pf != NULL)
-       {
-         if ((*pf)->name.len != 0)
-           pf = &(*pf)->next;
-         else
-           {
-             sb_kill (&(*pf)->name);
-             sb_kill (&(*pf)->def);
-             sb_kill (&(*pf)->actual);
-             f = (*pf)->next;
-             free (*pf);
-             *pf = f;
-           }
-       }
-    }
+  include_buf (&name, &out, include_macro, include_next_index ());
 
-  sb_kill (&t);
+  sb_kill (&name);
   sb_kill (&out);
-  number++;
-}
 
-static int
-macro_op (idx, in)
-     int idx;
-     sb *in;
-{
-  int res = 0;
-  /* The macro name must be the first thing on the line */
-  if (idx < in->len)
-    {
-      sb name;
-      hash_entry *ptr;
-      sb_new (&name);
-      idx = get_token (idx, in, &name);
-
-      if (name.len)
-       {
-         /* Got a name, look it up */
-
-         ptr = hash_lookup (&macro_table, &name);
-
-         if (ptr)
-           {
-             /* It's in the table, copy out the stuff and convert any macro args */
-             macro_expand (&name, idx, in, ptr->value.m);
-             res = 1;
-           }
-       }
-      sb_kill (&name);
-    }
-
-
-  return res;
+  return 1;
 }
 
-
 /* STRING HANDLING */
 
 static int
@@ -3797,7 +2872,7 @@ do_sdatab (idx, in)
       if (i)
        fprintf (outfile, "\t");
       fprintf (outfile, ".byte\t");
-      sb_print (&acc);
+      sb_print (outfile, &acc);
       fprintf (outfile, "\n");
     }
   sb_kill (&acc);
@@ -3836,12 +2911,22 @@ do_include (idx, in)
 {
   sb t;
   sb cat;
-  char *text;
   include_path *includes;
+
   sb_new (&t);
   sb_new (&cat);
 
-  idx = getstring (idx, in, &t);
+  if (! mri)
+    idx = getstring (idx, in, &t);
+  else
+    {
+      idx = sb_skip_white (idx, in);
+      while (idx < in->len && ! ISWHITE (in->ptr[idx]))
+       {
+         sb_add_char (&t, in->ptr[idx]);
+         ++idx;
+       }
+    }
 
   for (includes = paths_head; includes; includes = includes->next)
     {
@@ -3856,7 +2941,8 @@ do_include (idx, in)
     }
   if (!includes)
     {
-      FATAL ((stderr, "Can't open include file `%s'.\n", text));
+      if (! new_file (sb_name (&t)))
+       FATAL ((stderr, "Can't open include file `%s'.\n", sb_name (&t)));
     }
   sb_kill (&cat);
   sb_kill (&t);
@@ -3946,6 +3032,9 @@ chartype_init ()
       if (isalpha (x) || x == '_' || x == '$')
        chartype[x] |= FIRSTBIT;
 
+      if (mri && x == '.')
+       chartype[x] |= FIRSTBIT;
+
       if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
        chartype[x] |= NEXTBIT;
 
@@ -4090,7 +3179,6 @@ static struct keyword kinfo[] =
 
 static struct keyword mrikinfo[] =
 {
-  { "IF", K_IFNE, 0 },
   { "IFEQ", K_IFEQ, 0 },
   { "IFNE", K_IFNE, 0 },
   { "IFLT", K_IFLT, 0 },
@@ -4207,6 +3295,7 @@ process_pseudo_op (idx, line, acc)
            {
            case K_ALTERNATE:
              alternate = 1;
+             macro_init (1, mri, 0, exp_get_abs);
              return 1;
            case K_AELSE:
              do_aelse ();
@@ -4248,7 +3337,7 @@ process_pseudo_op (idx, line, acc)
              do_sdata (idx, line, 'z');
              return 1;
            case K_ASSIGN:
-             do_assign (1, 0, line);
+             do_assign (0, 0, line);
              return 1;
            case K_AIF:
              do_aif (idx, line);
@@ -4266,7 +3355,7 @@ process_pseudo_op (idx, line, acc)
              do_aendr ();
              return 1;
            case K_EQU:
-             do_assign (0, idx, line);
+             do_assign (1, idx, line);
              return 1;
            case K_ALIGN:
              do_align (idx, line);
@@ -4481,13 +3570,16 @@ Usage: %s \n\
   [-h]      [--help]              print this message\n\
   [-M]      [--mri]               enter MRI compatibility mode\n\
   [-o out]  [--output out]        set the output file\n\
-  [-p]      [--print]             print line numbers\n\
+  [-p]      [--print]             print line numbers\n", program_name);
+  fprintf (file, "\
   [-s]      [--copysource]        copy source through as comments \n\
   [-u]      [--unreasonable]      allow unreasonable nesting\n\
   [-v]      [--version]           print the program version\n\
   [-Dname=value]                  create preprocessor variable called name, with value\n\
   [-Ipath]                        add to include path list\n\
-  [in-file]\n",   program_name);
+  [in-file]\n");
+  if (status == 0)
+    printf ("\nReport bugs to bug-gnu-utils@prep.ai.mit.edu\n");
   exit (status);
 }
 
@@ -4517,7 +3609,6 @@ main (argc, argv)
   program_name = argv[0];
   xmalloc_set_program_name (program_name);
 
-  hash_new_table (101, &macro_table);
   hash_new_table (101, &keyword_hash_table);
   hash_new_table (101, &assign_hash_table);
   hash_new_table (101, &vars);
@@ -4568,12 +3659,18 @@ main (argc, argv)
          break;
        case 'M':
          mri = 1;
+         comment_char = ';';
          break;
        case 'h':
          show_help ();
          /*NOTREACHED*/
        case 'v':
-         printf ("GNU %s version %s\n", program_name, program_version);
+         /* This output is intended to follow the GNU standards document.  */
+         printf ("GNU assembler pre-processor %s\n", program_version);
+         printf ("Copyright 1996 Free Software Foundation, Inc.\n");
+         printf ("\
+This program is free software; you may redistribute it under the terms of\n\
+the GNU General Public License.  This program has absolutely no warranty.\n");
          exit (0);
          /*NOTREACHED*/
        case 0:
@@ -4586,6 +3683,8 @@ main (argc, argv)
 
   process_init ();
 
+  macro_init (alternate, mri, 0, exp_get_abs);
+
   if (out_name) {
     outfile = fopen (out_name, "w");
     if (!outfile)
@@ -4623,3 +3722,18 @@ main (argc, argv)
   quit ();
   return 0;
 }
+
+/* This function is used because an abort in some of the other files
+   may be compiled into as_abort because they include as.h.  */
+
+void
+as_abort (file, line, fn)
+     const char *file, *fn;
+     int line;
+{
+  fprintf (stderr, "Internal error, aborting at %s line %d", file, line);
+  if (fn)
+    fprintf (stderr, " in %s", fn);
+  fprintf (stderr, "\nPlease report this bug.\n");
+  exit (1);
+}
This page took 0.052049 seconds and 4 git commands to generate.