Back to index

cell-binutils  2.17cvs20070401
macro.c
Go to the documentation of this file.
00001 /* macro.c - macro support for gas
00002    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
00003    2004, 2005, 2006 Free Software Foundation, Inc.
00004 
00005    Written by Steve and Judy Chamberlain of Cygnus Support,
00006       sac@cygnus.com
00007 
00008    This file is part of GAS, the GNU Assembler.
00009 
00010    GAS is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2, or (at your option)
00013    any later version.
00014 
00015    GAS is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with GAS; see the file COPYING.  If not, write to the Free
00022    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00023    02110-1301, USA.  */
00024 
00025 #include "as.h"
00026 #include "safe-ctype.h"
00027 #include "sb.h"
00028 #include "macro.h"
00029 
00030 /* The routines in this file handle macro definition and expansion.
00031    They are called by gas.  */
00032 
00033 /* Internal functions.  */
00034 
00035 static int get_token (int, sb *, sb *);
00036 static int getstring (int, sb *, sb *);
00037 static int get_any_string (int, sb *, sb *);
00038 static formal_entry *new_formal (void);
00039 static void del_formal (formal_entry *);
00040 static int do_formals (macro_entry *, int, sb *);
00041 static int get_apost_token (int, sb *, sb *, int);
00042 static int sub_actual (int, sb *, sb *, struct hash_control *, int, sb *, int);
00043 static const char *macro_expand_body
00044   (sb *, sb *, formal_entry *, struct hash_control *, const macro_entry *);
00045 static const char *macro_expand (int, sb *, macro_entry *, sb *);
00046 static void free_macro(macro_entry *);
00047 
00048 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
00049 
00050 #define ISSEP(x) \
00051  ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
00052   || (x) == ')' || (x) == '(' \
00053   || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
00054 
00055 #define ISBASE(x) \
00056   ((x) == 'b' || (x) == 'B' \
00057    || (x) == 'q' || (x) == 'Q' \
00058    || (x) == 'h' || (x) == 'H' \
00059    || (x) == 'd' || (x) == 'D')
00060 
00061 /* The macro hash table.  */
00062 
00063 struct hash_control *macro_hash;
00064 
00065 /* Whether any macros have been defined.  */
00066 
00067 int macro_defined;
00068 
00069 /* Whether we are in alternate syntax mode.  */
00070 
00071 static int macro_alternate;
00072 
00073 /* Whether we are in MRI mode.  */
00074 
00075 static int macro_mri;
00076 
00077 /* Whether we should strip '@' characters.  */
00078 
00079 static int macro_strip_at;
00080 
00081 /* Function to use to parse an expression.  */
00082 
00083 static int (*macro_expr) (const char *, int, sb *, int *);
00084 
00085 /* Number of macro expansions that have been done.  */
00086 
00087 static int macro_number;
00088 
00089 /* Initialize macro processing.  */
00090 
00091 void
00092 macro_init (int alternate, int mri, int strip_at,
00093            int (*expr) (const char *, int, sb *, int *))
00094 {
00095   macro_hash = hash_new ();
00096   macro_defined = 0;
00097   macro_alternate = alternate;
00098   macro_mri = mri;
00099   macro_strip_at = strip_at;
00100   macro_expr = expr;
00101 }
00102 
00103 /* Switch in and out of alternate mode on the fly.  */
00104 
00105 void
00106 macro_set_alternate (int alternate)
00107 {
00108   macro_alternate = alternate;
00109 }
00110 
00111 /* Switch in and out of MRI mode on the fly.  */
00112 
00113 void
00114 macro_mri_mode (int mri)
00115 {
00116   macro_mri = mri;
00117 }
00118 
00119 /* Read input lines till we get to a TO string.
00120    Increase nesting depth if we get a FROM string.
00121    Put the results into sb at PTR.
00122    FROM may be NULL (or will be ignored) if TO is "ENDR".
00123    Add a new input line to an sb using GET_LINE.
00124    Return 1 on success, 0 on unexpected EOF.  */
00125 
00126 int
00127 buffer_and_nest (const char *from, const char *to, sb *ptr,
00128                int (*get_line) (sb *))
00129 {
00130   int from_len;
00131   int to_len = strlen (to);
00132   int depth = 1;
00133   int line_start = ptr->len;
00134 
00135   int more = get_line (ptr);
00136 
00137   if (to_len == 4 && strcasecmp(to, "ENDR") == 0)
00138     {
00139       from = NULL;
00140       from_len = 0;
00141     }
00142   else
00143     from_len = strlen (from);
00144 
00145   while (more)
00146     {
00147       /* Try to find the first pseudo op on the line.  */
00148       int i = line_start;
00149 
00150       /* With normal syntax we can suck what we want till we get
00151         to the dot.  With the alternate, labels have to start in
00152         the first column, since we can't tell what's a label and
00153         what's a pseudoop.  */
00154 
00155       if (! LABELS_WITHOUT_COLONS)
00156        {
00157          /* Skip leading whitespace.  */
00158          while (i < ptr->len && ISWHITE (ptr->ptr[i]))
00159            i++;
00160        }
00161 
00162       for (;;)
00163        {
00164          /* Skip over a label, if any.  */
00165          if (i >= ptr->len || ! is_name_beginner (ptr->ptr[i]))
00166            break;
00167          i++;
00168          while (i < ptr->len && is_part_of_name (ptr->ptr[i]))
00169            i++;
00170          if (i < ptr->len && is_name_ender (ptr->ptr[i]))
00171            i++;
00172          if (LABELS_WITHOUT_COLONS)
00173            break;
00174          /* Skip whitespace.  */
00175          while (i < ptr->len && ISWHITE (ptr->ptr[i]))
00176            i++;
00177          /* Check for the colon.  */
00178          if (i >= ptr->len || ptr->ptr[i] != ':')
00179            {
00180              i = line_start;
00181              break;
00182            }
00183          i++;
00184          line_start = i;
00185        }
00186 
00187       /* Skip trailing whitespace.  */
00188       while (i < ptr->len && ISWHITE (ptr->ptr[i]))
00189        i++;
00190 
00191       if (i < ptr->len && (ptr->ptr[i] == '.'
00192                         || NO_PSEUDO_DOT
00193                         || macro_mri))
00194        {
00195          if (! flag_m68k_mri && ptr->ptr[i] == '.')
00196            i++;
00197          if (from == NULL
00198             && strncasecmp (ptr->ptr + i, "IRPC", from_len = 4) != 0
00199             && strncasecmp (ptr->ptr + i, "IRP", from_len = 3) != 0
00200             && strncasecmp (ptr->ptr + i, "IREPC", from_len = 5) != 0
00201             && strncasecmp (ptr->ptr + i, "IREP", from_len = 4) != 0
00202             && strncasecmp (ptr->ptr + i, "REPT", from_len = 4) != 0
00203             && strncasecmp (ptr->ptr + i, "REP", from_len = 3) != 0)
00204            from_len = 0;
00205          if ((from != NULL
00206               ? strncasecmp (ptr->ptr + i, from, from_len) == 0
00207               : from_len > 0)
00208              && (ptr->len == (i + from_len)
00209                 || ! (is_part_of_name (ptr->ptr[i + from_len])
00210                      || is_name_ender (ptr->ptr[i + from_len]))))
00211            depth++;
00212          if (strncasecmp (ptr->ptr + i, to, to_len) == 0
00213              && (ptr->len == (i + to_len)
00214                 || ! (is_part_of_name (ptr->ptr[i + to_len])
00215                      || is_name_ender (ptr->ptr[i + to_len]))))
00216            {
00217              depth--;
00218              if (depth == 0)
00219               {
00220                 /* Reset the string to not include the ending rune.  */
00221                 ptr->len = line_start;
00222                 break;
00223               }
00224            }
00225        }
00226 
00227       /* Add the original end-of-line char to the end and keep running.  */
00228       sb_add_char (ptr, more);
00229       line_start = ptr->len;
00230       more = get_line (ptr);
00231     }
00232 
00233   /* Return 1 on success, 0 on unexpected EOF.  */
00234   return depth == 0;
00235 }
00236 
00237 /* Pick up a token.  */
00238 
00239 static int
00240 get_token (int idx, sb *in, sb *name)
00241 {
00242   if (idx < in->len
00243       && is_name_beginner (in->ptr[idx]))
00244     {
00245       sb_add_char (name, in->ptr[idx++]);
00246       while (idx < in->len
00247             && is_part_of_name (in->ptr[idx]))
00248        {
00249          sb_add_char (name, in->ptr[idx++]);
00250        }
00251       if (idx < in->len
00252             && is_name_ender (in->ptr[idx]))
00253        {
00254          sb_add_char (name, in->ptr[idx++]);
00255        }
00256     }
00257   /* Ignore trailing &.  */
00258   if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
00259     idx++;
00260   return idx;
00261 }
00262 
00263 /* Pick up a string.  */
00264 
00265 static int
00266 getstring (int idx, sb *in, sb *acc)
00267 {
00268   while (idx < in->len
00269         && (in->ptr[idx] == '"'
00270             || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
00271             || (in->ptr[idx] == '\'' && macro_alternate)))
00272     {
00273       if (in->ptr[idx] == '<')
00274        {
00275          int nest = 0;
00276          idx++;
00277          while ((in->ptr[idx] != '>' || nest)
00278                && idx < in->len)
00279            {
00280              if (in->ptr[idx] == '!')
00281               {
00282                 idx++;
00283                 sb_add_char (acc, in->ptr[idx++]);
00284               }
00285              else
00286               {
00287                 if (in->ptr[idx] == '>')
00288                   nest--;
00289                 if (in->ptr[idx] == '<')
00290                   nest++;
00291                 sb_add_char (acc, in->ptr[idx++]);
00292               }
00293            }
00294          idx++;
00295        }
00296       else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
00297        {
00298          char tchar = in->ptr[idx];
00299          int escaped = 0;
00300 
00301          idx++;
00302 
00303          while (idx < in->len)
00304            {
00305              if (in->ptr[idx - 1] == '\\')
00306               escaped ^= 1;
00307              else
00308               escaped = 0;
00309 
00310              if (macro_alternate && in->ptr[idx] == '!')
00311               {
00312                 idx ++;
00313 
00314                 sb_add_char (acc, in->ptr[idx]);
00315 
00316                 idx ++;
00317               }
00318              else if (escaped && in->ptr[idx] == tchar)
00319               {
00320                 sb_add_char (acc, tchar);
00321                 idx ++;
00322               }
00323              else
00324               {
00325                 if (in->ptr[idx] == tchar)
00326                   {
00327                     idx ++;
00328 
00329                     if (idx >= in->len || in->ptr[idx] != tchar)
00330                      break;
00331                   }
00332 
00333                 sb_add_char (acc, in->ptr[idx]);
00334                 idx ++;
00335               }
00336            }
00337        }
00338     }
00339 
00340   return idx;
00341 }
00342 
00343 /* Fetch string from the input stream,
00344    rules:
00345     'Bxyx<whitespace>       -> return 'Bxyza
00346     %<expr>          -> return string of decimal value of <expr>
00347     "string"         -> return string
00348     (string)         -> return (string-including-whitespaces)
00349     xyx<whitespace>     -> return xyz.  */
00350 
00351 static int
00352 get_any_string (int idx, sb *in, sb *out)
00353 {
00354   sb_reset (out);
00355   idx = sb_skip_white (idx, in);
00356 
00357   if (idx < in->len)
00358     {
00359       if (in->len > idx + 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
00360        {
00361          while (!ISSEP (in->ptr[idx]))
00362            sb_add_char (out, in->ptr[idx++]);
00363        }
00364       else if (in->ptr[idx] == '%' && macro_alternate)
00365        {
00366          int val;
00367          char buf[20];
00368 
00369          /* Turns the next expression into a string.  */
00370          /* xgettext: no-c-format */
00371          idx = (*macro_expr) (_("% operator needs absolute expression"),
00372                             idx + 1,
00373                             in,
00374                             &val);
00375          sprintf (buf, "%d", val);
00376          sb_add_string (out, buf);
00377        }
00378       else if (in->ptr[idx] == '"'
00379               || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
00380               || (macro_alternate && in->ptr[idx] == '\''))
00381        {
00382          if (macro_alternate && ! macro_strip_at && in->ptr[idx] != '<')
00383            {
00384              /* Keep the quotes.  */
00385              sb_add_char (out, '"');
00386              idx = getstring (idx, in, out);
00387              sb_add_char (out, '"');
00388            }
00389          else
00390            {
00391              idx = getstring (idx, in, out);
00392            }
00393        }
00394       else
00395        {
00396          char *br_buf = xmalloc(1);
00397          char *in_br = br_buf;
00398 
00399          *in_br = '\0';
00400          while (idx < in->len
00401                && (*in_br
00402                    || (in->ptr[idx] != ' '
00403                       && in->ptr[idx] != '\t'))
00404                && in->ptr[idx] != ','
00405                && (in->ptr[idx] != '<'
00406                    || (! macro_alternate && ! macro_mri)))
00407            {
00408              char tchar = in->ptr[idx];
00409 
00410              switch (tchar)
00411               {
00412               case '"':
00413               case '\'':
00414                 sb_add_char (out, in->ptr[idx++]);
00415                 while (idx < in->len
00416                       && in->ptr[idx] != tchar)
00417                   sb_add_char (out, in->ptr[idx++]);
00418                 if (idx == in->len)
00419                   return idx;
00420                 break;
00421               case '(':
00422               case '[':
00423                 if (in_br > br_buf)
00424                   --in_br;
00425                 else
00426                   {
00427                     br_buf = xmalloc(strlen(in_br) + 2);
00428                     strcpy(br_buf + 1, in_br);
00429                     free(in_br);
00430                     in_br = br_buf;
00431                   }
00432                 *in_br = tchar;
00433                 break;
00434               case ')':
00435                 if (*in_br == '(')
00436                   ++in_br;
00437                 break;
00438               case ']':
00439                 if (*in_br == '[')
00440                   ++in_br;
00441                 break;
00442               }
00443              sb_add_char (out, tchar);
00444              ++idx;
00445            }
00446          free(br_buf);
00447        }
00448     }
00449 
00450   return idx;
00451 }
00452 
00453 /* Allocate a new formal.  */
00454 
00455 static formal_entry *
00456 new_formal (void)
00457 {
00458   formal_entry *formal;
00459 
00460   formal = xmalloc (sizeof (formal_entry));
00461 
00462   sb_new (&formal->name);
00463   sb_new (&formal->def);
00464   sb_new (&formal->actual);
00465   formal->next = NULL;
00466   formal->type = FORMAL_OPTIONAL;
00467   return formal;
00468 }
00469 
00470 /* Free a formal.  */
00471 
00472 static void
00473 del_formal (formal_entry *formal)
00474 {
00475   sb_kill (&formal->actual);
00476   sb_kill (&formal->def);
00477   sb_kill (&formal->name);
00478   free (formal);
00479 }
00480 
00481 /* Pick up the formal parameters of a macro definition.  */
00482 
00483 static int
00484 do_formals (macro_entry *macro, int idx, sb *in)
00485 {
00486   formal_entry **p = &macro->formals;
00487   const char *name;
00488 
00489   idx = sb_skip_white (idx, in);
00490   while (idx < in->len)
00491     {
00492       formal_entry *formal = new_formal ();
00493       int cidx;
00494 
00495       idx = get_token (idx, in, &formal->name);
00496       if (formal->name.len == 0)
00497        {
00498          if (macro->formal_count)
00499            --idx;
00500          break;
00501        }
00502       idx = sb_skip_white (idx, in);
00503       /* This is a formal.  */
00504       name = sb_terminate (&formal->name);
00505       if (! macro_mri
00506          && idx < in->len
00507          && in->ptr[idx] == ':'
00508          && (! is_name_beginner (':')
00509              || idx + 1 >= in->len
00510              || ! is_part_of_name (in->ptr[idx + 1])))
00511        {
00512          /* Got a qualifier.  */
00513          sb qual;
00514 
00515          sb_new (&qual);
00516          idx = get_token (sb_skip_white (idx + 1, in), in, &qual);
00517          sb_terminate (&qual);
00518          if (qual.len == 0)
00519            as_bad_where (macro->file,
00520                        macro->line,
00521                        _("Missing parameter qualifier for `%s' in macro `%s'"),
00522                        name,
00523                        macro->name);
00524          else if (strcmp (qual.ptr, "req") == 0)
00525            formal->type = FORMAL_REQUIRED;
00526          else if (strcmp (qual.ptr, "vararg") == 0)
00527            formal->type = FORMAL_VARARG;
00528          else
00529            as_bad_where (macro->file,
00530                        macro->line,
00531                        _("`%s' is not a valid parameter qualifier for `%s' in macro `%s'"),
00532                        qual.ptr,
00533                        name,
00534                        macro->name);
00535          sb_kill (&qual);
00536          idx = sb_skip_white (idx, in);
00537        }
00538       if (idx < in->len && in->ptr[idx] == '=')
00539        {
00540          /* Got a default.  */
00541          idx = get_any_string (idx + 1, in, &formal->def);
00542          idx = sb_skip_white (idx, in);
00543          if (formal->type == FORMAL_REQUIRED)
00544            {
00545              sb_reset (&formal->def);
00546              as_warn_where (macro->file,
00547                          macro->line,
00548                          _("Pointless default value for required parameter `%s' in macro `%s'"),
00549                          name,
00550                          macro->name);
00551            }
00552        }
00553 
00554       /* Add to macro's hash table.  */
00555       if (! hash_find (macro->formal_hash, name))
00556        hash_jam (macro->formal_hash, name, formal);
00557       else
00558        as_bad_where (macro->file,
00559                     macro->line,
00560                     _("A parameter named `%s' already exists for macro `%s'"),
00561                     name,
00562                     macro->name);
00563 
00564       formal->index = macro->formal_count++;
00565       *p = formal;
00566       p = &formal->next;
00567       if (formal->type == FORMAL_VARARG)
00568        break;
00569       cidx = idx;
00570       idx = sb_skip_comma (idx, in);
00571       if (idx != cidx && idx >= in->len)
00572        {
00573          idx = cidx;
00574          break;
00575        }
00576     }
00577 
00578   if (macro_mri)
00579     {
00580       formal_entry *formal = new_formal ();
00581 
00582       /* Add a special NARG formal, which macro_expand will set to the
00583          number of arguments.  */
00584       /* The same MRI assemblers which treat '@' characters also use
00585          the name $NARG.  At least until we find an exception.  */
00586       if (macro_strip_at)
00587        name = "$NARG";
00588       else
00589        name = "NARG";
00590 
00591       sb_add_string (&formal->name, name);
00592 
00593       /* Add to macro's hash table.  */
00594       if (hash_find (macro->formal_hash, name))
00595        as_bad_where (macro->file,
00596                     macro->line,
00597                     _("Reserved word `%s' used as parameter in macro `%s'"),
00598                     name,
00599                     macro->name);
00600       hash_jam (macro->formal_hash, name, formal);
00601 
00602       formal->index = NARG_INDEX;
00603       *p = formal;
00604     }
00605 
00606   return idx;
00607 }
00608 
00609 /* Define a new macro.  Returns NULL on success, otherwise returns an
00610    error message.  If NAMEP is not NULL, *NAMEP is set to the name of
00611    the macro which was defined.  */
00612 
00613 const char *
00614 define_macro (int idx, sb *in, sb *label,
00615              int (*get_line) (sb *),
00616              char *file, unsigned int line,
00617              const char **namep)
00618 {
00619   macro_entry *macro;
00620   sb name;
00621   const char *error = NULL;
00622 
00623   macro = (macro_entry *) xmalloc (sizeof (macro_entry));
00624   sb_new (&macro->sub);
00625   sb_new (&name);
00626   macro->file = file;
00627   macro->line = line;
00628 
00629   macro->formal_count = 0;
00630   macro->formals = 0;
00631   macro->formal_hash = hash_new ();
00632 
00633   idx = sb_skip_white (idx, in);
00634   if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
00635     error = _("unexpected end of file in macro `%s' definition");
00636   if (label != NULL && label->len != 0)
00637     {
00638       sb_add_sb (&name, label);
00639       macro->name = sb_terminate (&name);
00640       if (idx < in->len && in->ptr[idx] == '(')
00641        {
00642          /* It's the label: MACRO (formals,...)  sort  */
00643          idx = do_formals (macro, idx + 1, in);
00644          if (idx < in->len && in->ptr[idx] == ')')
00645            idx = sb_skip_white (idx + 1, in);
00646          else if (!error)
00647            error = _("missing `)' after formals in macro definition `%s'");
00648        }
00649       else
00650        {
00651          /* It's the label: MACRO formals,...  sort  */
00652          idx = do_formals (macro, idx, in);
00653        }
00654     }
00655   else
00656     {
00657       int cidx;
00658 
00659       idx = get_token (idx, in, &name);
00660       macro->name = sb_terminate (&name);
00661       if (name.len == 0)
00662        error = _("Missing macro name");
00663       cidx = sb_skip_white (idx, in);
00664       idx = sb_skip_comma (cidx, in);
00665       if (idx == cidx || idx < in->len)
00666        idx = do_formals (macro, idx, in);
00667       else
00668        idx = cidx;
00669     }
00670   if (!error && idx < in->len)
00671     error = _("Bad parameter list for macro `%s'");
00672 
00673   /* And stick it in the macro hash table.  */
00674   for (idx = 0; idx < name.len; idx++)
00675     name.ptr[idx] = TOLOWER (name.ptr[idx]);
00676   if (hash_find (macro_hash, macro->name))
00677     error = _("Macro `%s' was already defined");
00678   if (!error)
00679     error = hash_jam (macro_hash, macro->name, (PTR) macro);
00680 
00681   if (namep != NULL)
00682     *namep = macro->name;
00683 
00684   if (!error)
00685     macro_defined = 1;
00686   else
00687     free_macro (macro);
00688 
00689   return error;
00690 }
00691 
00692 /* Scan a token, and then skip KIND.  */
00693 
00694 static int
00695 get_apost_token (int idx, sb *in, sb *name, int kind)
00696 {
00697   idx = get_token (idx, in, name);
00698   if (idx < in->len
00699       && in->ptr[idx] == kind
00700       && (! macro_mri || macro_strip_at)
00701       && (! macro_strip_at || kind == '@'))
00702     idx++;
00703   return idx;
00704 }
00705 
00706 /* Substitute the actual value for a formal parameter.  */
00707 
00708 static int
00709 sub_actual (int start, sb *in, sb *t, struct hash_control *formal_hash,
00710            int kind, sb *out, int copyifnotthere)
00711 {
00712   int src;
00713   formal_entry *ptr;
00714 
00715   src = get_apost_token (start, in, t, kind);
00716   /* See if it's in the macro's hash table, unless this is
00717      macro_strip_at and kind is '@' and the token did not end in '@'.  */
00718   if (macro_strip_at
00719       && kind == '@'
00720       && (src == start || in->ptr[src - 1] != '@'))
00721     ptr = NULL;
00722   else
00723     ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
00724   if (ptr)
00725     {
00726       if (ptr->actual.len)
00727        {
00728          sb_add_sb (out, &ptr->actual);
00729        }
00730       else
00731        {
00732          sb_add_sb (out, &ptr->def);
00733        }
00734     }
00735   else if (kind == '&')
00736     {
00737       /* Doing this permits people to use & in macro bodies.  */
00738       sb_add_char (out, '&');
00739       sb_add_sb (out, t);
00740     }
00741   else if (copyifnotthere)
00742     {
00743       sb_add_sb (out, t);
00744     }
00745   else
00746     {
00747       sb_add_char (out, '\\');
00748       sb_add_sb (out, t);
00749     }
00750   return src;
00751 }
00752 
00753 /* Expand the body of a macro.  */
00754 
00755 static const char *
00756 macro_expand_body (sb *in, sb *out, formal_entry *formals,
00757                  struct hash_control *formal_hash, const macro_entry *macro)
00758 {
00759   sb t;
00760   int src = 0, inquote = 0, macro_line = 0;
00761   formal_entry *loclist = NULL;
00762   const char *err = NULL;
00763 
00764   sb_new (&t);
00765 
00766   while (src < in->len && !err)
00767     {
00768       if (in->ptr[src] == '&')
00769        {
00770          sb_reset (&t);
00771          if (macro_mri)
00772            {
00773              if (src + 1 < in->len && in->ptr[src + 1] == '&')
00774               src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
00775              else
00776               sb_add_char (out, in->ptr[src++]);
00777            }
00778          else
00779            {
00780              /* FIXME: Why do we do this?  */
00781              /* At least in alternate mode this seems correct; without this
00782                 one can't append a literal to a parameter.  */
00783              src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
00784            }
00785        }
00786       else if (in->ptr[src] == '\\')
00787        {
00788          src++;
00789          if (src < in->len && in->ptr[src] == '(')
00790            {
00791              /* Sub in till the next ')' literally.  */
00792              src++;
00793              while (src < in->len && in->ptr[src] != ')')
00794               {
00795                 sb_add_char (out, in->ptr[src++]);
00796               }
00797              if (src < in->len)
00798               src++;
00799              else if (!macro)
00800               err = _("missing `)'");
00801              else
00802               as_bad_where (macro->file, macro->line + macro_line, _("missing `)'"));
00803            }
00804          else if (src < in->len && in->ptr[src] == '@')
00805            {
00806              /* Sub in the macro invocation number.  */
00807 
00808              char buffer[10];
00809              src++;
00810              sprintf (buffer, "%d", macro_number);
00811              sb_add_string (out, buffer);
00812            }
00813          else if (src < in->len && in->ptr[src] == '&')
00814            {
00815              /* This is a preprocessor variable name, we don't do them
00816                here.  */
00817              sb_add_char (out, '\\');
00818              sb_add_char (out, '&');
00819              src++;
00820            }
00821          else if (macro_mri && src < in->len && ISALNUM (in->ptr[src]))
00822            {
00823              int ind;
00824              formal_entry *f;
00825 
00826              if (ISDIGIT (in->ptr[src]))
00827               ind = in->ptr[src] - '0';
00828              else if (ISUPPER (in->ptr[src]))
00829               ind = in->ptr[src] - 'A' + 10;
00830              else
00831               ind = in->ptr[src] - 'a' + 10;
00832              ++src;
00833              for (f = formals; f != NULL; f = f->next)
00834               {
00835                 if (f->index == ind - 1)
00836                   {
00837                     if (f->actual.len != 0)
00838                      sb_add_sb (out, &f->actual);
00839                     else
00840                      sb_add_sb (out, &f->def);
00841                     break;
00842                   }
00843               }
00844            }
00845          else
00846            {
00847              sb_reset (&t);
00848              src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
00849            }
00850        }
00851       else if ((macro_alternate || macro_mri)
00852               && is_name_beginner (in->ptr[src])
00853               && (! inquote
00854                  || ! macro_strip_at
00855                  || (src > 0 && in->ptr[src - 1] == '@')))
00856        {
00857          if (! macro
00858              || src + 5 >= in->len
00859              || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
00860              || ! ISWHITE (in->ptr[src + 5]))
00861            {
00862              sb_reset (&t);
00863              src = sub_actual (src, in, &t, formal_hash,
00864                             (macro_strip_at && inquote) ? '@' : '\'',
00865                             out, 1);
00866            }
00867          else
00868            {
00869              src = sb_skip_white (src + 5, in);
00870              while (in->ptr[src] != '\n')
00871               {
00872                 const char *name;
00873                 formal_entry *f = new_formal ();
00874 
00875                 src = get_token (src, in, &f->name);
00876                 name = sb_terminate (&f->name);
00877                 if (! hash_find (formal_hash, name))
00878                   {
00879                     static int loccnt;
00880                     char buf[20];
00881 
00882                     f->index = LOCAL_INDEX;
00883                     f->next = loclist;
00884                     loclist = f;
00885 
00886                     sprintf (buf, IS_ELF ? ".LL%04x" : "LL%04x", ++loccnt);
00887                     sb_add_string (&f->actual, buf);
00888 
00889                     err = hash_jam (formal_hash, name, f);
00890                     if (err != NULL)
00891                      break;
00892                   }
00893                 else
00894                   {
00895                     as_bad_where (macro->file,
00896                                 macro->line + macro_line,
00897                                 _("`%s' was already used as parameter (or another local) name"),
00898                                 name);
00899                     del_formal (f);
00900                   }
00901 
00902                 src = sb_skip_comma (src, in);
00903               }
00904            }
00905        }
00906       else if (in->ptr[src] == '"'
00907               || (macro_mri && in->ptr[src] == '\''))
00908        {
00909          inquote = !inquote;
00910          sb_add_char (out, in->ptr[src++]);
00911        }
00912       else if (in->ptr[src] == '@' && macro_strip_at)
00913        {
00914          ++src;
00915          if (src < in->len
00916              && in->ptr[src] == '@')
00917            {
00918              sb_add_char (out, '@');
00919              ++src;
00920            }
00921        }
00922       else if (macro_mri
00923               && in->ptr[src] == '='
00924               && src + 1 < in->len
00925               && in->ptr[src + 1] == '=')
00926        {
00927          formal_entry *ptr;
00928 
00929          sb_reset (&t);
00930          src = get_token (src + 2, in, &t);
00931          ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
00932          if (ptr == NULL)
00933            {
00934              /* FIXME: We should really return a warning string here,
00935                  but we can't, because the == might be in the MRI
00936                  comment field, and, since the nature of the MRI
00937                  comment field depends upon the exact instruction
00938                  being used, we don't have enough information here to
00939                  figure out whether it is or not.  Instead, we leave
00940                  the == in place, which should cause a syntax error if
00941                  it is not in a comment.  */
00942              sb_add_char (out, '=');
00943              sb_add_char (out, '=');
00944              sb_add_sb (out, &t);
00945            }
00946          else
00947            {
00948              if (ptr->actual.len)
00949               {
00950                 sb_add_string (out, "-1");
00951               }
00952              else
00953               {
00954                 sb_add_char (out, '0');
00955               }
00956            }
00957        }
00958       else
00959        {
00960          if (in->ptr[src] == '\n')
00961            ++macro_line;
00962          sb_add_char (out, in->ptr[src++]);
00963        }
00964     }
00965 
00966   sb_kill (&t);
00967 
00968   while (loclist != NULL)
00969     {
00970       formal_entry *f;
00971 
00972       f = loclist->next;
00973       /* Setting the value to NULL effectively deletes the entry.  We
00974          avoid calling hash_delete because it doesn't reclaim memory.  */
00975       hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
00976       del_formal (loclist);
00977       loclist = f;
00978     }
00979 
00980   return err;
00981 }
00982 
00983 /* Assign values to the formal parameters of a macro, and expand the
00984    body.  */
00985 
00986 static const char *
00987 macro_expand (int idx, sb *in, macro_entry *m, sb *out)
00988 {
00989   sb t;
00990   formal_entry *ptr;
00991   formal_entry *f;
00992   int is_keyword = 0;
00993   int narg = 0;
00994   const char *err = NULL;
00995 
00996   sb_new (&t);
00997 
00998   /* Reset any old value the actuals may have.  */
00999   for (f = m->formals; f; f = f->next)
01000     sb_reset (&f->actual);
01001   f = m->formals;
01002   while (f != NULL && f->index < 0)
01003     f = f->next;
01004 
01005   if (macro_mri)
01006     {
01007       /* The macro may be called with an optional qualifier, which may
01008          be referred to in the macro body as \0.  */
01009       if (idx < in->len && in->ptr[idx] == '.')
01010        {
01011          /* The Microtec assembler ignores this if followed by a white space.
01012             (Macro invocation with empty extension) */
01013          idx++;
01014          if (    idx < in->len
01015                 && in->ptr[idx] != ' '
01016                 && in->ptr[idx] != '\t')
01017            {
01018              formal_entry *n = new_formal ();
01019 
01020              n->index = QUAL_INDEX;
01021 
01022              n->next = m->formals;
01023              m->formals = n;
01024 
01025              idx = get_any_string (idx, in, &n->actual);
01026            }
01027        }
01028     }
01029 
01030   /* Peel off the actuals and store them away in the hash tables' actuals.  */
01031   idx = sb_skip_white (idx, in);
01032   while (idx < in->len)
01033     {
01034       int scan;
01035 
01036       /* Look and see if it's a positional or keyword arg.  */
01037       scan = idx;
01038       while (scan < in->len
01039             && !ISSEP (in->ptr[scan])
01040             && !(macro_mri && in->ptr[scan] == '\'')
01041             && (!macro_alternate && in->ptr[scan] != '='))
01042        scan++;
01043       if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
01044        {
01045          is_keyword = 1;
01046 
01047          /* It's OK to go from positional to keyword.  */
01048 
01049          /* This is a keyword arg, fetch the formal name and
01050             then the actual stuff.  */
01051          sb_reset (&t);
01052          idx = get_token (idx, in, &t);
01053          if (in->ptr[idx] != '=')
01054            {
01055              err = _("confusion in formal parameters");
01056              break;
01057            }
01058 
01059          /* Lookup the formal in the macro's list.  */
01060          ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
01061          if (!ptr)
01062            as_bad (_("Parameter named `%s' does not exist for macro `%s'"),
01063                   t.ptr,
01064                   m->name);
01065          else
01066            {
01067              /* Insert this value into the right place.  */
01068              if (ptr->actual.len)
01069               {
01070                 as_warn (_("Value for parameter `%s' of macro `%s' was already specified"),
01071                         ptr->name.ptr,
01072                         m->name);
01073                 sb_reset (&ptr->actual);
01074               }
01075              idx = get_any_string (idx + 1, in, &ptr->actual);
01076              if (ptr->actual.len > 0)
01077               ++narg;
01078            }
01079        }
01080       else
01081        {
01082          if (is_keyword)
01083            {
01084              err = _("can't mix positional and keyword arguments");
01085              break;
01086            }
01087 
01088          if (!f)
01089            {
01090              formal_entry **pf;
01091              int c;
01092 
01093              if (!macro_mri)
01094               {
01095                 err = _("too many positional arguments");
01096                 break;
01097               }
01098 
01099              f = new_formal ();
01100 
01101              c = -1;
01102              for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
01103               if ((*pf)->index >= c)
01104                 c = (*pf)->index + 1;
01105              if (c == -1)
01106               c = 0;
01107              *pf = f;
01108              f->index = c;
01109            }
01110 
01111          if (f->type != FORMAL_VARARG)
01112            idx = get_any_string (idx, in, &f->actual);
01113          else
01114            {
01115              sb_add_buffer (&f->actual, in->ptr + idx, in->len - idx);
01116              idx = in->len;
01117            }
01118          if (f->actual.len > 0)
01119            ++narg;
01120          do
01121            {
01122              f = f->next;
01123            }
01124          while (f != NULL && f->index < 0);
01125        }
01126 
01127       if (! macro_mri)
01128        idx = sb_skip_comma (idx, in);
01129       else
01130        {
01131          if (in->ptr[idx] == ',')
01132            ++idx;
01133          if (ISWHITE (in->ptr[idx]))
01134            break;
01135        }
01136     }
01137 
01138   if (! err)
01139     {
01140       for (ptr = m->formals; ptr; ptr = ptr->next)
01141        {
01142          if (ptr->type == FORMAL_REQUIRED && ptr->actual.len == 0)
01143            as_bad (_("Missing value for required parameter `%s' of macro `%s'"),
01144                   ptr->name.ptr,
01145                   m->name);
01146        }
01147 
01148       if (macro_mri)
01149        {
01150          char buffer[20];
01151 
01152          sb_reset (&t);
01153          sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
01154          ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
01155          sprintf (buffer, "%d", narg);
01156          sb_add_string (&ptr->actual, buffer);
01157        }
01158 
01159       err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m);
01160     }
01161 
01162   /* Discard any unnamed formal arguments.  */
01163   if (macro_mri)
01164     {
01165       formal_entry **pf;
01166 
01167       pf = &m->formals;
01168       while (*pf != NULL)
01169        {
01170          if ((*pf)->name.len != 0)
01171            pf = &(*pf)->next;
01172          else
01173            {
01174              f = (*pf)->next;
01175              del_formal (*pf);
01176              *pf = f;
01177            }
01178        }
01179     }
01180 
01181   sb_kill (&t);
01182   if (!err)
01183     macro_number++;
01184 
01185   return err;
01186 }
01187 
01188 /* Check for a macro.  If one is found, put the expansion into
01189    *EXPAND.  Return 1 if a macro is found, 0 otherwise.  */
01190 
01191 int
01192 check_macro (const char *line, sb *expand,
01193             const char **error, macro_entry **info)
01194 {
01195   const char *s;
01196   char *copy, *cs;
01197   macro_entry *macro;
01198   sb line_sb;
01199 
01200   if (! is_name_beginner (*line)
01201       && (! macro_mri || *line != '.'))
01202     return 0;
01203 
01204   s = line + 1;
01205   while (is_part_of_name (*s))
01206     ++s;
01207   if (is_name_ender (*s))
01208     ++s;
01209 
01210   copy = (char *) alloca (s - line + 1);
01211   memcpy (copy, line, s - line);
01212   copy[s - line] = '\0';
01213   for (cs = copy; *cs != '\0'; cs++)
01214     *cs = TOLOWER (*cs);
01215 
01216   macro = (macro_entry *) hash_find (macro_hash, copy);
01217 
01218   if (macro == NULL)
01219     return 0;
01220 
01221   /* Wrap the line up in an sb.  */
01222   sb_new (&line_sb);
01223   while (*s != '\0' && *s != '\n' && *s != '\r')
01224     sb_add_char (&line_sb, *s++);
01225 
01226   sb_new (expand);
01227   *error = macro_expand (0, &line_sb, macro, expand);
01228 
01229   sb_kill (&line_sb);
01230 
01231   /* Export the macro information if requested.  */
01232   if (info)
01233     *info = macro;
01234 
01235   return 1;
01236 }
01237 
01238 /* Free the memory allocated to a macro.  */
01239 
01240 static void
01241 free_macro(macro_entry *macro)
01242 {
01243   formal_entry *formal;
01244 
01245   for (formal = macro->formals; formal; )
01246     {
01247       formal_entry *f;
01248 
01249       f = formal;
01250       formal = formal->next;
01251       del_formal (f);
01252     }
01253   hash_die (macro->formal_hash);
01254   sb_kill (&macro->sub);
01255   free (macro);
01256 }
01257 
01258 /* Delete a macro.  */
01259 
01260 void
01261 delete_macro (const char *name)
01262 {
01263   char *copy;
01264   size_t i, len;
01265   macro_entry *macro;
01266 
01267   len = strlen (name);
01268   copy = (char *) alloca (len + 1);
01269   for (i = 0; i < len; ++i)
01270     copy[i] = TOLOWER (name[i]);
01271   copy[i] = '\0';
01272 
01273   /* Since hash_delete doesn't free memory, just clear out the entry.  */
01274   if ((macro = hash_find (macro_hash, copy)) != NULL)
01275     {
01276       hash_jam (macro_hash, copy, NULL);
01277       free_macro (macro);
01278     }
01279   else
01280     as_warn (_("Attempt to purge non-existant macro `%s'"), copy);
01281 }
01282 
01283 /* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
01284    combined macro definition and execution.  This returns NULL on
01285    success, or an error message otherwise.  */
01286 
01287 const char *
01288 expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
01289 {
01290   sb sub;
01291   formal_entry f;
01292   struct hash_control *h;
01293   const char *err;
01294 
01295   idx = sb_skip_white (idx, in);
01296 
01297   sb_new (&sub);
01298   if (! buffer_and_nest (NULL, "ENDR", &sub, get_line))
01299     return _("unexpected end of file in irp or irpc");
01300 
01301   sb_new (&f.name);
01302   sb_new (&f.def);
01303   sb_new (&f.actual);
01304 
01305   idx = get_token (idx, in, &f.name);
01306   if (f.name.len == 0)
01307     return _("missing model parameter");
01308 
01309   h = hash_new ();
01310   err = hash_jam (h, sb_terminate (&f.name), &f);
01311   if (err != NULL)
01312     return err;
01313 
01314   f.index = 1;
01315   f.next = NULL;
01316   f.type = FORMAL_OPTIONAL;
01317 
01318   sb_reset (out);
01319 
01320   idx = sb_skip_comma (idx, in);
01321   if (idx >= in->len)
01322     {
01323       /* Expand once with a null string.  */
01324       err = macro_expand_body (&sub, out, &f, h, 0);
01325     }
01326   else
01327     {
01328       bfd_boolean in_quotes = FALSE;
01329 
01330       if (irpc && in->ptr[idx] == '"')
01331        {
01332          in_quotes = TRUE;
01333          ++idx;
01334        }
01335 
01336       while (idx < in->len)
01337        {
01338          if (!irpc)
01339            idx = get_any_string (idx, in, &f.actual);
01340          else
01341            {
01342              if (in->ptr[idx] == '"')
01343               {
01344                 int nxt;
01345 
01346                 if (irpc)
01347                   in_quotes = ! in_quotes;
01348          
01349                 nxt = sb_skip_white (idx + 1, in);
01350                 if (nxt >= in->len)
01351                   {
01352                     idx = nxt;
01353                     break;
01354                   }
01355               }
01356              sb_reset (&f.actual);
01357              sb_add_char (&f.actual, in->ptr[idx]);
01358              ++idx;
01359            }
01360 
01361          err = macro_expand_body (&sub, out, &f, h, 0);
01362          if (err != NULL)
01363            break;
01364          if (!irpc)
01365            idx = sb_skip_comma (idx, in);
01366          else if (! in_quotes)
01367            idx = sb_skip_white (idx, in);
01368        }
01369     }
01370 
01371   hash_die (h);
01372   sb_kill (&f.actual);
01373   sb_kill (&f.def);
01374   sb_kill (&f.name);
01375   sb_kill (&sub);
01376 
01377   return err;
01378 }