1130561Sobrien/* macro.c - macro support for gas
2218822Sdim   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3218822Sdim   2004, 2005, 2006 Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   Written by Steve and Judy Chamberlain of Cygnus Support,
633965Sjdp      sac@cygnus.com
733965Sjdp
833965Sjdp   This file is part of GAS, the GNU Assembler.
933965Sjdp
1033965Sjdp   GAS is free software; you can redistribute it and/or modify
1133965Sjdp   it under the terms of the GNU General Public License as published by
1233965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1333965Sjdp   any later version.
1433965Sjdp
1533965Sjdp   GAS is distributed in the hope that it will be useful,
1633965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1733965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1833965Sjdp   GNU General Public License for more details.
1933965Sjdp
2033965Sjdp   You should have received a copy of the GNU General Public License
2133965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
22218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
23218822Sdim   02110-1301, USA.  */
2433965Sjdp
25218822Sdim#include "as.h"
2689857Sobrien#include "safe-ctype.h"
2733965Sjdp#include "sb.h"
2833965Sjdp#include "macro.h"
2933965Sjdp
3033965Sjdp/* The routines in this file handle macro definition and expansion.
31130561Sobrien   They are called by gas.  */
3233965Sjdp
3333965Sjdp/* Internal functions.  */
3433965Sjdp
35130561Sobrienstatic int get_token (int, sb *, sb *);
36130561Sobrienstatic int getstring (int, sb *, sb *);
37218822Sdimstatic int get_any_string (int, sb *, sb *);
38218822Sdimstatic formal_entry *new_formal (void);
39218822Sdimstatic void del_formal (formal_entry *);
40130561Sobrienstatic int do_formals (macro_entry *, int, sb *);
41130561Sobrienstatic int get_apost_token (int, sb *, sb *, int);
42130561Sobrienstatic int sub_actual (int, sb *, sb *, struct hash_control *, int, sb *, int);
4333965Sjdpstatic const char *macro_expand_body
44218822Sdim  (sb *, sb *, formal_entry *, struct hash_control *, const macro_entry *);
45130561Sobrienstatic const char *macro_expand (int, sb *, macro_entry *, sb *);
46218822Sdimstatic void free_macro(macro_entry *);
4733965Sjdp
4833965Sjdp#define ISWHITE(x) ((x) == ' ' || (x) == '\t')
4933965Sjdp
5033965Sjdp#define ISSEP(x) \
5133965Sjdp ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
5238889Sjdp  || (x) == ')' || (x) == '(' \
5338889Sjdp  || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
5433965Sjdp
5533965Sjdp#define ISBASE(x) \
5633965Sjdp  ((x) == 'b' || (x) == 'B' \
5733965Sjdp   || (x) == 'q' || (x) == 'Q' \
5833965Sjdp   || (x) == 'h' || (x) == 'H' \
5933965Sjdp   || (x) == 'd' || (x) == 'D')
6033965Sjdp
6133965Sjdp/* The macro hash table.  */
6233965Sjdp
63130561Sobrienstruct hash_control *macro_hash;
6433965Sjdp
6533965Sjdp/* Whether any macros have been defined.  */
6633965Sjdp
6733965Sjdpint macro_defined;
6833965Sjdp
69130561Sobrien/* Whether we are in alternate syntax mode.  */
7033965Sjdp
7133965Sjdpstatic int macro_alternate;
7233965Sjdp
7333965Sjdp/* Whether we are in MRI mode.  */
7433965Sjdp
7533965Sjdpstatic int macro_mri;
7633965Sjdp
7733965Sjdp/* Whether we should strip '@' characters.  */
7833965Sjdp
7933965Sjdpstatic int macro_strip_at;
8033965Sjdp
8133965Sjdp/* Function to use to parse an expression.  */
8233965Sjdp
83130561Sobrienstatic int (*macro_expr) (const char *, int, sb *, int *);
8433965Sjdp
8533965Sjdp/* Number of macro expansions that have been done.  */
8633965Sjdp
8733965Sjdpstatic int macro_number;
8833965Sjdp
8933965Sjdp/* Initialize macro processing.  */
9033965Sjdp
9133965Sjdpvoid
92130561Sobrienmacro_init (int alternate, int mri, int strip_at,
93130561Sobrien	    int (*expr) (const char *, int, sb *, int *))
9433965Sjdp{
9533965Sjdp  macro_hash = hash_new ();
9633965Sjdp  macro_defined = 0;
9733965Sjdp  macro_alternate = alternate;
9833965Sjdp  macro_mri = mri;
9933965Sjdp  macro_strip_at = strip_at;
10033965Sjdp  macro_expr = expr;
10133965Sjdp}
10233965Sjdp
103218822Sdim/* Switch in and out of alternate mode on the fly.  */
104218822Sdim
105218822Sdimvoid
106218822Sdimmacro_set_alternate (int alternate)
107218822Sdim{
108218822Sdim  macro_alternate = alternate;
109218822Sdim}
110218822Sdim
11160484Sobrien/* Switch in and out of MRI mode on the fly.  */
11260484Sobrien
11360484Sobrienvoid
114130561Sobrienmacro_mri_mode (int mri)
11560484Sobrien{
11660484Sobrien  macro_mri = mri;
11760484Sobrien}
11860484Sobrien
11933965Sjdp/* Read input lines till we get to a TO string.
12033965Sjdp   Increase nesting depth if we get a FROM string.
12133965Sjdp   Put the results into sb at PTR.
122218822Sdim   FROM may be NULL (or will be ignored) if TO is "ENDR".
12333965Sjdp   Add a new input line to an sb using GET_LINE.
12433965Sjdp   Return 1 on success, 0 on unexpected EOF.  */
12533965Sjdp
12633965Sjdpint
127130561Sobrienbuffer_and_nest (const char *from, const char *to, sb *ptr,
128130561Sobrien		 int (*get_line) (sb *))
12933965Sjdp{
130218822Sdim  int from_len;
13133965Sjdp  int to_len = strlen (to);
13233965Sjdp  int depth = 1;
13333965Sjdp  int line_start = ptr->len;
13433965Sjdp
13533965Sjdp  int more = get_line (ptr);
13633965Sjdp
137218822Sdim  if (to_len == 4 && strcasecmp(to, "ENDR") == 0)
138218822Sdim    {
139218822Sdim      from = NULL;
140218822Sdim      from_len = 0;
141218822Sdim    }
142218822Sdim  else
143218822Sdim    from_len = strlen (from);
144218822Sdim
14533965Sjdp  while (more)
14633965Sjdp    {
147218822Sdim      /* Try to find the first pseudo op on the line.  */
14833965Sjdp      int i = line_start;
14933965Sjdp
150218822Sdim      /* With normal syntax we can suck what we want till we get
151218822Sdim	 to the dot.  With the alternate, labels have to start in
152218822Sdim	 the first column, since we can't tell what's a label and
153218822Sdim	 what's a pseudoop.  */
154218822Sdim
155218822Sdim      if (! LABELS_WITHOUT_COLONS)
15633965Sjdp	{
15777298Sobrien	  /* Skip leading whitespace.  */
15833965Sjdp	  while (i < ptr->len && ISWHITE (ptr->ptr[i]))
15933965Sjdp	    i++;
160218822Sdim	}
16133965Sjdp
162218822Sdim      for (;;)
163218822Sdim	{
164218822Sdim	  /* Skip over a label, if any.  */
165218822Sdim	  if (i >= ptr->len || ! is_name_beginner (ptr->ptr[i]))
166218822Sdim	    break;
167218822Sdim	  i++;
168218822Sdim	  while (i < ptr->len && is_part_of_name (ptr->ptr[i]))
16933965Sjdp	    i++;
170218822Sdim	  if (i < ptr->len && is_name_ender (ptr->ptr[i]))
17133965Sjdp	    i++;
172218822Sdim	  if (LABELS_WITHOUT_COLONS)
173218822Sdim	    break;
174218822Sdim	  /* Skip whitespace.  */
175218822Sdim	  while (i < ptr->len && ISWHITE (ptr->ptr[i]))
176218822Sdim	    i++;
177218822Sdim	  /* Check for the colon.  */
178218822Sdim	  if (i >= ptr->len || ptr->ptr[i] != ':')
179218822Sdim	    {
180218822Sdim	      i = line_start;
181218822Sdim	      break;
182218822Sdim	    }
183218822Sdim	  i++;
184218822Sdim	  line_start = i;
185218822Sdim	}
18633965Sjdp
18777298Sobrien      /* Skip trailing whitespace.  */
18833965Sjdp      while (i < ptr->len && ISWHITE (ptr->ptr[i]))
18933965Sjdp	i++;
19033965Sjdp
19133965Sjdp      if (i < ptr->len && (ptr->ptr[i] == '.'
192218822Sdim			   || NO_PSEUDO_DOT
19333965Sjdp			   || macro_mri))
19433965Sjdp	{
195218822Sdim	  if (! flag_m68k_mri && ptr->ptr[i] == '.')
19677298Sobrien	    i++;
197218822Sdim	  if (from == NULL
198218822Sdim	     && strncasecmp (ptr->ptr + i, "IRPC", from_len = 4) != 0
199218822Sdim	     && strncasecmp (ptr->ptr + i, "IRP", from_len = 3) != 0
200218822Sdim	     && strncasecmp (ptr->ptr + i, "IREPC", from_len = 5) != 0
201218822Sdim	     && strncasecmp (ptr->ptr + i, "IREP", from_len = 4) != 0
202218822Sdim	     && strncasecmp (ptr->ptr + i, "REPT", from_len = 4) != 0
203218822Sdim	     && strncasecmp (ptr->ptr + i, "REP", from_len = 3) != 0)
204218822Sdim	    from_len = 0;
205218822Sdim	  if ((from != NULL
206218822Sdim	       ? strncasecmp (ptr->ptr + i, from, from_len) == 0
207218822Sdim	       : from_len > 0)
20877298Sobrien	      && (ptr->len == (i + from_len)
209218822Sdim		  || ! (is_part_of_name (ptr->ptr[i + from_len])
210218822Sdim			|| is_name_ender (ptr->ptr[i + from_len]))))
21133965Sjdp	    depth++;
21260484Sobrien	  if (strncasecmp (ptr->ptr + i, to, to_len) == 0
21377298Sobrien	      && (ptr->len == (i + to_len)
214218822Sdim		  || ! (is_part_of_name (ptr->ptr[i + to_len])
215218822Sdim			|| is_name_ender (ptr->ptr[i + to_len]))))
21633965Sjdp	    {
21733965Sjdp	      depth--;
21833965Sjdp	      if (depth == 0)
21933965Sjdp		{
22077298Sobrien		  /* Reset the string to not include the ending rune.  */
22133965Sjdp		  ptr->len = line_start;
22233965Sjdp		  break;
22333965Sjdp		}
22433965Sjdp	    }
22533965Sjdp	}
22633965Sjdp
227130561Sobrien      /* Add the original end-of-line char to the end and keep running.  */
228130561Sobrien      sb_add_char (ptr, more);
22933965Sjdp      line_start = ptr->len;
23033965Sjdp      more = get_line (ptr);
23133965Sjdp    }
23233965Sjdp
23333965Sjdp  /* Return 1 on success, 0 on unexpected EOF.  */
23433965Sjdp  return depth == 0;
23533965Sjdp}
23633965Sjdp
23733965Sjdp/* Pick up a token.  */
23833965Sjdp
23933965Sjdpstatic int
240130561Sobrienget_token (int idx, sb *in, sb *name)
24133965Sjdp{
24233965Sjdp  if (idx < in->len
243218822Sdim      && is_name_beginner (in->ptr[idx]))
24433965Sjdp    {
24533965Sjdp      sb_add_char (name, in->ptr[idx++]);
24633965Sjdp      while (idx < in->len
247218822Sdim	     && is_part_of_name (in->ptr[idx]))
24833965Sjdp	{
24933965Sjdp	  sb_add_char (name, in->ptr[idx++]);
25033965Sjdp	}
251218822Sdim      if (idx < in->len
252218822Sdim	     && is_name_ender (in->ptr[idx]))
253218822Sdim	{
254218822Sdim	  sb_add_char (name, in->ptr[idx++]);
255218822Sdim	}
25633965Sjdp    }
25777298Sobrien  /* Ignore trailing &.  */
25833965Sjdp  if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
25933965Sjdp    idx++;
26033965Sjdp  return idx;
26133965Sjdp}
26233965Sjdp
26333965Sjdp/* Pick up a string.  */
26433965Sjdp
26533965Sjdpstatic int
266130561Sobriengetstring (int idx, sb *in, sb *acc)
26733965Sjdp{
26833965Sjdp  while (idx < in->len
26977298Sobrien	 && (in->ptr[idx] == '"'
27038889Sjdp	     || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
27133965Sjdp	     || (in->ptr[idx] == '\'' && macro_alternate)))
27233965Sjdp    {
27333965Sjdp      if (in->ptr[idx] == '<')
27433965Sjdp	{
27538889Sjdp	  int nest = 0;
27638889Sjdp	  idx++;
27738889Sjdp	  while ((in->ptr[idx] != '>' || nest)
27838889Sjdp		 && idx < in->len)
27933965Sjdp	    {
28038889Sjdp	      if (in->ptr[idx] == '!')
28133965Sjdp		{
28277298Sobrien		  idx++;
28338889Sjdp		  sb_add_char (acc, in->ptr[idx++]);
28433965Sjdp		}
28538889Sjdp	      else
28638889Sjdp		{
28738889Sjdp		  if (in->ptr[idx] == '>')
28838889Sjdp		    nest--;
28938889Sjdp		  if (in->ptr[idx] == '<')
29038889Sjdp		    nest++;
29138889Sjdp		  sb_add_char (acc, in->ptr[idx++]);
29238889Sjdp		}
29333965Sjdp	    }
29438889Sjdp	  idx++;
29533965Sjdp	}
29633965Sjdp      else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
29733965Sjdp	{
29833965Sjdp	  char tchar = in->ptr[idx];
29977298Sobrien	  int escaped = 0;
30077298Sobrien
30133965Sjdp	  idx++;
30277298Sobrien
30333965Sjdp	  while (idx < in->len)
30433965Sjdp	    {
30577298Sobrien	      if (in->ptr[idx - 1] == '\\')
30677298Sobrien		escaped ^= 1;
30777298Sobrien	      else
30877298Sobrien		escaped = 0;
30977298Sobrien
31033965Sjdp	      if (macro_alternate && in->ptr[idx] == '!')
31133965Sjdp		{
31277298Sobrien		  idx ++;
31377298Sobrien
31477298Sobrien		  sb_add_char (acc, in->ptr[idx]);
31577298Sobrien
31677298Sobrien		  idx ++;
31733965Sjdp		}
31877298Sobrien	      else if (escaped && in->ptr[idx] == tchar)
31977298Sobrien		{
32077298Sobrien		  sb_add_char (acc, tchar);
32177298Sobrien		  idx ++;
32277298Sobrien		}
32333965Sjdp	      else
32433965Sjdp		{
32533965Sjdp		  if (in->ptr[idx] == tchar)
32633965Sjdp		    {
32777298Sobrien		      idx ++;
32877298Sobrien
32933965Sjdp		      if (idx >= in->len || in->ptr[idx] != tchar)
33033965Sjdp			break;
33133965Sjdp		    }
33277298Sobrien
33333965Sjdp		  sb_add_char (acc, in->ptr[idx]);
33477298Sobrien		  idx ++;
33533965Sjdp		}
33633965Sjdp	    }
33733965Sjdp	}
33833965Sjdp    }
33977298Sobrien
34033965Sjdp  return idx;
34133965Sjdp}
34233965Sjdp
34333965Sjdp/* Fetch string from the input stream,
34433965Sjdp   rules:
34533965Sjdp    'Bxyx<whitespace>  	-> return 'Bxyza
346218822Sdim    %<expr>		-> return string of decimal value of <expr>
347218822Sdim    "string"		-> return string
348218822Sdim    (string)		-> return (string-including-whitespaces)
349218822Sdim    xyx<whitespace>     -> return xyz.  */
35033965Sjdp
35133965Sjdpstatic int
352218822Sdimget_any_string (int idx, sb *in, sb *out)
35333965Sjdp{
35433965Sjdp  sb_reset (out);
35533965Sjdp  idx = sb_skip_white (idx, in);
35633965Sjdp
35733965Sjdp  if (idx < in->len)
35833965Sjdp    {
359130561Sobrien      if (in->len > idx + 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
36033965Sjdp	{
36133965Sjdp	  while (!ISSEP (in->ptr[idx]))
36233965Sjdp	    sb_add_char (out, in->ptr[idx++]);
36333965Sjdp	}
364218822Sdim      else if (in->ptr[idx] == '%' && macro_alternate)
36533965Sjdp	{
36633965Sjdp	  int val;
36733965Sjdp	  char buf[20];
368218822Sdim
36977298Sobrien	  /* Turns the next expression into a string.  */
37089857Sobrien	  /* xgettext: no-c-format */
37160484Sobrien	  idx = (*macro_expr) (_("% operator needs absolute expression"),
37233965Sjdp			       idx + 1,
37333965Sjdp			       in,
37433965Sjdp			       &val);
375104834Sobrien	  sprintf (buf, "%d", val);
37633965Sjdp	  sb_add_string (out, buf);
37733965Sjdp	}
37833965Sjdp      else if (in->ptr[idx] == '"'
37938889Sjdp	       || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
38033965Sjdp	       || (macro_alternate && in->ptr[idx] == '\''))
38133965Sjdp	{
382218822Sdim	  if (macro_alternate && ! macro_strip_at && in->ptr[idx] != '<')
38333965Sjdp	    {
38477298Sobrien	      /* Keep the quotes.  */
385218822Sdim	      sb_add_char (out, '"');
38633965Sjdp	      idx = getstring (idx, in, out);
387218822Sdim	      sb_add_char (out, '"');
38833965Sjdp	    }
38933965Sjdp	  else
39033965Sjdp	    {
39133965Sjdp	      idx = getstring (idx, in, out);
39233965Sjdp	    }
39333965Sjdp	}
39477298Sobrien      else
39533965Sjdp	{
396218822Sdim	  char *br_buf = xmalloc(1);
397218822Sdim	  char *in_br = br_buf;
398218822Sdim
399218822Sdim	  *in_br = '\0';
40077298Sobrien	  while (idx < in->len
401218822Sdim		 && (*in_br
40233965Sjdp		     || (in->ptr[idx] != ' '
403218822Sdim			 && in->ptr[idx] != '\t'))
404218822Sdim		 && in->ptr[idx] != ','
405218822Sdim		 && (in->ptr[idx] != '<'
406218822Sdim		     || (! macro_alternate && ! macro_mri)))
40733965Sjdp	    {
408218822Sdim	      char tchar = in->ptr[idx];
409218822Sdim
410218822Sdim	      switch (tchar)
41133965Sjdp		{
412218822Sdim		case '"':
413218822Sdim		case '\'':
41433965Sjdp		  sb_add_char (out, in->ptr[idx++]);
41533965Sjdp		  while (idx < in->len
41633965Sjdp			 && in->ptr[idx] != tchar)
41777298Sobrien		    sb_add_char (out, in->ptr[idx++]);
41833965Sjdp		  if (idx == in->len)
41977298Sobrien		    return idx;
420218822Sdim		  break;
421218822Sdim		case '(':
422218822Sdim		case '[':
423218822Sdim		  if (in_br > br_buf)
424218822Sdim		    --in_br;
425218822Sdim		  else
426218822Sdim		    {
427218822Sdim		      br_buf = xmalloc(strlen(in_br) + 2);
428218822Sdim		      strcpy(br_buf + 1, in_br);
429218822Sdim		      free(in_br);
430218822Sdim		      in_br = br_buf;
431218822Sdim		    }
432218822Sdim		  *in_br = tchar;
433218822Sdim		  break;
434218822Sdim		case ')':
435218822Sdim		  if (*in_br == '(')
436218822Sdim		    ++in_br;
437218822Sdim		  break;
438218822Sdim		case ']':
439218822Sdim		  if (*in_br == '[')
440218822Sdim		    ++in_br;
441218822Sdim		  break;
44233965Sjdp		}
443218822Sdim	      sb_add_char (out, tchar);
444218822Sdim	      ++idx;
44533965Sjdp	    }
446218822Sdim	  free(br_buf);
44733965Sjdp	}
44833965Sjdp    }
44933965Sjdp
45033965Sjdp  return idx;
45133965Sjdp}
45233965Sjdp
453218822Sdim/* Allocate a new formal.  */
454218822Sdim
455218822Sdimstatic formal_entry *
456218822Sdimnew_formal (void)
457218822Sdim{
458218822Sdim  formal_entry *formal;
459218822Sdim
460218822Sdim  formal = xmalloc (sizeof (formal_entry));
461218822Sdim
462218822Sdim  sb_new (&formal->name);
463218822Sdim  sb_new (&formal->def);
464218822Sdim  sb_new (&formal->actual);
465218822Sdim  formal->next = NULL;
466218822Sdim  formal->type = FORMAL_OPTIONAL;
467218822Sdim  return formal;
468218822Sdim}
469218822Sdim
470218822Sdim/* Free a formal.  */
471218822Sdim
472218822Sdimstatic void
473218822Sdimdel_formal (formal_entry *formal)
474218822Sdim{
475218822Sdim  sb_kill (&formal->actual);
476218822Sdim  sb_kill (&formal->def);
477218822Sdim  sb_kill (&formal->name);
478218822Sdim  free (formal);
479218822Sdim}
480218822Sdim
48133965Sjdp/* Pick up the formal parameters of a macro definition.  */
48233965Sjdp
48333965Sjdpstatic int
484130561Sobriendo_formals (macro_entry *macro, int idx, sb *in)
48533965Sjdp{
48633965Sjdp  formal_entry **p = &macro->formals;
487218822Sdim  const char *name;
48833965Sjdp
489218822Sdim  idx = sb_skip_white (idx, in);
49033965Sjdp  while (idx < in->len)
49133965Sjdp    {
492218822Sdim      formal_entry *formal = new_formal ();
493218822Sdim      int cidx;
49433965Sjdp
49533965Sjdp      idx = get_token (idx, in, &formal->name);
49633965Sjdp      if (formal->name.len == 0)
497218822Sdim	{
498218822Sdim	  if (macro->formal_count)
499218822Sdim	    --idx;
500218822Sdim	  break;
501218822Sdim	}
50233965Sjdp      idx = sb_skip_white (idx, in);
503218822Sdim      /* This is a formal.  */
504218822Sdim      name = sb_terminate (&formal->name);
505218822Sdim      if (! macro_mri
506218822Sdim	  && idx < in->len
507218822Sdim	  && in->ptr[idx] == ':'
508218822Sdim	  && (! is_name_beginner (':')
509218822Sdim	      || idx + 1 >= in->len
510218822Sdim	      || ! is_part_of_name (in->ptr[idx + 1])))
51133965Sjdp	{
512218822Sdim	  /* Got a qualifier.  */
513218822Sdim	  sb qual;
514218822Sdim
515218822Sdim	  sb_new (&qual);
516218822Sdim	  idx = get_token (sb_skip_white (idx + 1, in), in, &qual);
517218822Sdim	  sb_terminate (&qual);
518218822Sdim	  if (qual.len == 0)
519218822Sdim	    as_bad_where (macro->file,
520218822Sdim			  macro->line,
521218822Sdim			  _("Missing parameter qualifier for `%s' in macro `%s'"),
522218822Sdim			  name,
523218822Sdim			  macro->name);
524218822Sdim	  else if (strcmp (qual.ptr, "req") == 0)
525218822Sdim	    formal->type = FORMAL_REQUIRED;
526218822Sdim	  else if (strcmp (qual.ptr, "vararg") == 0)
527218822Sdim	    formal->type = FORMAL_VARARG;
528218822Sdim	  else
529218822Sdim	    as_bad_where (macro->file,
530218822Sdim			  macro->line,
531218822Sdim			  _("`%s' is not a valid parameter qualifier for `%s' in macro `%s'"),
532218822Sdim			  qual.ptr,
533218822Sdim			  name,
534218822Sdim			  macro->name);
535218822Sdim	  sb_kill (&qual);
536218822Sdim	  idx = sb_skip_white (idx, in);
537218822Sdim	}
538218822Sdim      if (idx < in->len && in->ptr[idx] == '=')
539218822Sdim	{
540218822Sdim	  /* Got a default.  */
541218822Sdim	  idx = get_any_string (idx + 1, in, &formal->def);
542218822Sdim	  idx = sb_skip_white (idx, in);
543218822Sdim	  if (formal->type == FORMAL_REQUIRED)
54433965Sjdp	    {
545218822Sdim	      sb_reset (&formal->def);
546218822Sdim	      as_warn_where (macro->file,
547218822Sdim			    macro->line,
548218822Sdim			    _("Pointless default value for required parameter `%s' in macro `%s'"),
549218822Sdim			    name,
550218822Sdim			    macro->name);
55133965Sjdp	    }
55233965Sjdp	}
55333965Sjdp
55477298Sobrien      /* Add to macro's hash table.  */
555218822Sdim      if (! hash_find (macro->formal_hash, name))
556218822Sdim	hash_jam (macro->formal_hash, name, formal);
557218822Sdim      else
558218822Sdim	as_bad_where (macro->file,
559218822Sdim		      macro->line,
560218822Sdim		      _("A parameter named `%s' already exists for macro `%s'"),
561218822Sdim		      name,
562218822Sdim		      macro->name);
56333965Sjdp
564218822Sdim      formal->index = macro->formal_count++;
56533965Sjdp      *p = formal;
56633965Sjdp      p = &formal->next;
567218822Sdim      if (formal->type == FORMAL_VARARG)
568218822Sdim	break;
569218822Sdim      cidx = idx;
570218822Sdim      idx = sb_skip_comma (idx, in);
571218822Sdim      if (idx != cidx && idx >= in->len)
572218822Sdim	{
573218822Sdim	  idx = cidx;
574218822Sdim	  break;
575218822Sdim	}
57633965Sjdp    }
57733965Sjdp
57833965Sjdp  if (macro_mri)
57933965Sjdp    {
580218822Sdim      formal_entry *formal = new_formal ();
58133965Sjdp
58233965Sjdp      /* Add a special NARG formal, which macro_expand will set to the
58333965Sjdp         number of arguments.  */
58433965Sjdp      /* The same MRI assemblers which treat '@' characters also use
58533965Sjdp         the name $NARG.  At least until we find an exception.  */
58633965Sjdp      if (macro_strip_at)
58733965Sjdp	name = "$NARG";
58833965Sjdp      else
58933965Sjdp	name = "NARG";
59033965Sjdp
59133965Sjdp      sb_add_string (&formal->name, name);
59233965Sjdp
59377298Sobrien      /* Add to macro's hash table.  */
594218822Sdim      if (hash_find (macro->formal_hash, name))
595218822Sdim	as_bad_where (macro->file,
596218822Sdim		      macro->line,
597218822Sdim		      _("Reserved word `%s' used as parameter in macro `%s'"),
598218822Sdim		      name,
599218822Sdim		      macro->name);
60033965Sjdp      hash_jam (macro->formal_hash, name, formal);
60133965Sjdp
60233965Sjdp      formal->index = NARG_INDEX;
60333965Sjdp      *p = formal;
60433965Sjdp    }
60533965Sjdp
60633965Sjdp  return idx;
60733965Sjdp}
60833965Sjdp
60933965Sjdp/* Define a new macro.  Returns NULL on success, otherwise returns an
61033965Sjdp   error message.  If NAMEP is not NULL, *NAMEP is set to the name of
61133965Sjdp   the macro which was defined.  */
61233965Sjdp
61333965Sjdpconst char *
614130561Sobriendefine_macro (int idx, sb *in, sb *label,
615218822Sdim	      int (*get_line) (sb *),
616218822Sdim	      char *file, unsigned int line,
617218822Sdim	      const char **namep)
61833965Sjdp{
61933965Sjdp  macro_entry *macro;
62033965Sjdp  sb name;
621218822Sdim  const char *error = NULL;
62233965Sjdp
62333965Sjdp  macro = (macro_entry *) xmalloc (sizeof (macro_entry));
62433965Sjdp  sb_new (&macro->sub);
62533965Sjdp  sb_new (&name);
626218822Sdim  macro->file = file;
627218822Sdim  macro->line = line;
62833965Sjdp
62933965Sjdp  macro->formal_count = 0;
63033965Sjdp  macro->formals = 0;
631218822Sdim  macro->formal_hash = hash_new ();
63233965Sjdp
63333965Sjdp  idx = sb_skip_white (idx, in);
63433965Sjdp  if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
635218822Sdim    error = _("unexpected end of file in macro `%s' definition");
63633965Sjdp  if (label != NULL && label->len != 0)
63733965Sjdp    {
63833965Sjdp      sb_add_sb (&name, label);
639218822Sdim      macro->name = sb_terminate (&name);
64038889Sjdp      if (idx < in->len && in->ptr[idx] == '(')
64133965Sjdp	{
64277298Sobrien	  /* It's the label: MACRO (formals,...)  sort  */
64333965Sjdp	  idx = do_formals (macro, idx + 1, in);
644218822Sdim	  if (idx < in->len && in->ptr[idx] == ')')
645218822Sdim	    idx = sb_skip_white (idx + 1, in);
646218822Sdim	  else if (!error)
647218822Sdim	    error = _("missing `)' after formals in macro definition `%s'");
64833965Sjdp	}
64933965Sjdp      else
65033965Sjdp	{
65177298Sobrien	  /* It's the label: MACRO formals,...  sort  */
65233965Sjdp	  idx = do_formals (macro, idx, in);
65333965Sjdp	}
65433965Sjdp    }
65533965Sjdp  else
65633965Sjdp    {
657218822Sdim      int cidx;
658218822Sdim
65933965Sjdp      idx = get_token (idx, in, &name);
660218822Sdim      macro->name = sb_terminate (&name);
661218822Sdim      if (name.len == 0)
662218822Sdim	error = _("Missing macro name");
663218822Sdim      cidx = sb_skip_white (idx, in);
664218822Sdim      idx = sb_skip_comma (cidx, in);
665218822Sdim      if (idx == cidx || idx < in->len)
666218822Sdim	idx = do_formals (macro, idx, in);
667218822Sdim      else
668218822Sdim	idx = cidx;
66933965Sjdp    }
670218822Sdim  if (!error && idx < in->len)
671218822Sdim    error = _("Bad parameter list for macro `%s'");
67233965Sjdp
67377298Sobrien  /* And stick it in the macro hash table.  */
67433965Sjdp  for (idx = 0; idx < name.len; idx++)
67589857Sobrien    name.ptr[idx] = TOLOWER (name.ptr[idx]);
676218822Sdim  if (hash_find (macro_hash, macro->name))
677218822Sdim    error = _("Macro `%s' was already defined");
678218822Sdim  if (!error)
679218822Sdim    error = hash_jam (macro_hash, macro->name, (PTR) macro);
68033965Sjdp
68133965Sjdp  if (namep != NULL)
682218822Sdim    *namep = macro->name;
68333965Sjdp
684218822Sdim  if (!error)
685218822Sdim    macro_defined = 1;
686218822Sdim  else
687218822Sdim    free_macro (macro);
688218822Sdim
689218822Sdim  return error;
69033965Sjdp}
69133965Sjdp
69233965Sjdp/* Scan a token, and then skip KIND.  */
69333965Sjdp
69433965Sjdpstatic int
695130561Sobrienget_apost_token (int idx, sb *in, sb *name, int kind)
69633965Sjdp{
69733965Sjdp  idx = get_token (idx, in, name);
69833965Sjdp  if (idx < in->len
69933965Sjdp      && in->ptr[idx] == kind
70033965Sjdp      && (! macro_mri || macro_strip_at)
70133965Sjdp      && (! macro_strip_at || kind == '@'))
70233965Sjdp    idx++;
70333965Sjdp  return idx;
70433965Sjdp}
70533965Sjdp
70633965Sjdp/* Substitute the actual value for a formal parameter.  */
70733965Sjdp
70833965Sjdpstatic int
709130561Sobriensub_actual (int start, sb *in, sb *t, struct hash_control *formal_hash,
710130561Sobrien	    int kind, sb *out, int copyifnotthere)
71133965Sjdp{
71233965Sjdp  int src;
71333965Sjdp  formal_entry *ptr;
71433965Sjdp
71533965Sjdp  src = get_apost_token (start, in, t, kind);
71633965Sjdp  /* See if it's in the macro's hash table, unless this is
71733965Sjdp     macro_strip_at and kind is '@' and the token did not end in '@'.  */
71833965Sjdp  if (macro_strip_at
71933965Sjdp      && kind == '@'
72033965Sjdp      && (src == start || in->ptr[src - 1] != '@'))
72133965Sjdp    ptr = NULL;
72233965Sjdp  else
72333965Sjdp    ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
72433965Sjdp  if (ptr)
72533965Sjdp    {
72633965Sjdp      if (ptr->actual.len)
72733965Sjdp	{
72833965Sjdp	  sb_add_sb (out, &ptr->actual);
72933965Sjdp	}
73033965Sjdp      else
73133965Sjdp	{
73233965Sjdp	  sb_add_sb (out, &ptr->def);
73333965Sjdp	}
73433965Sjdp    }
73538889Sjdp  else if (kind == '&')
73638889Sjdp    {
73738889Sjdp      /* Doing this permits people to use & in macro bodies.  */
73838889Sjdp      sb_add_char (out, '&');
739130561Sobrien      sb_add_sb (out, t);
74038889Sjdp    }
74133965Sjdp  else if (copyifnotthere)
74233965Sjdp    {
74333965Sjdp      sb_add_sb (out, t);
74433965Sjdp    }
74577298Sobrien  else
74633965Sjdp    {
74733965Sjdp      sb_add_char (out, '\\');
74833965Sjdp      sb_add_sb (out, t);
74933965Sjdp    }
75033965Sjdp  return src;
75133965Sjdp}
75233965Sjdp
75333965Sjdp/* Expand the body of a macro.  */
75433965Sjdp
75533965Sjdpstatic const char *
756130561Sobrienmacro_expand_body (sb *in, sb *out, formal_entry *formals,
757218822Sdim		   struct hash_control *formal_hash, const macro_entry *macro)
75833965Sjdp{
75933965Sjdp  sb t;
760218822Sdim  int src = 0, inquote = 0, macro_line = 0;
76133965Sjdp  formal_entry *loclist = NULL;
762218822Sdim  const char *err = NULL;
76333965Sjdp
76433965Sjdp  sb_new (&t);
76533965Sjdp
766218822Sdim  while (src < in->len && !err)
76733965Sjdp    {
76833965Sjdp      if (in->ptr[src] == '&')
76933965Sjdp	{
77033965Sjdp	  sb_reset (&t);
77133965Sjdp	  if (macro_mri)
77233965Sjdp	    {
77333965Sjdp	      if (src + 1 < in->len && in->ptr[src + 1] == '&')
77433965Sjdp		src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
77533965Sjdp	      else
77633965Sjdp		sb_add_char (out, in->ptr[src++]);
77733965Sjdp	    }
77833965Sjdp	  else
77933965Sjdp	    {
78038889Sjdp	      /* FIXME: Why do we do this?  */
781218822Sdim	      /* At least in alternate mode this seems correct; without this
782218822Sdim	         one can't append a literal to a parameter.  */
78333965Sjdp	      src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
78433965Sjdp	    }
78533965Sjdp	}
78633965Sjdp      else if (in->ptr[src] == '\\')
78733965Sjdp	{
78833965Sjdp	  src++;
789218822Sdim	  if (src < in->len && in->ptr[src] == '(')
79033965Sjdp	    {
79177298Sobrien	      /* Sub in till the next ')' literally.  */
79233965Sjdp	      src++;
79333965Sjdp	      while (src < in->len && in->ptr[src] != ')')
79433965Sjdp		{
79533965Sjdp		  sb_add_char (out, in->ptr[src++]);
79633965Sjdp		}
797218822Sdim	      if (src < in->len)
79833965Sjdp		src++;
799218822Sdim	      else if (!macro)
800218822Sdim		err = _("missing `)'");
80133965Sjdp	      else
802218822Sdim		as_bad_where (macro->file, macro->line + macro_line, _("missing `)'"));
80333965Sjdp	    }
804218822Sdim	  else if (src < in->len && in->ptr[src] == '@')
80533965Sjdp	    {
80677298Sobrien	      /* Sub in the macro invocation number.  */
80733965Sjdp
80838889Sjdp	      char buffer[10];
80933965Sjdp	      src++;
81077298Sobrien	      sprintf (buffer, "%d", macro_number);
81133965Sjdp	      sb_add_string (out, buffer);
81233965Sjdp	    }
813218822Sdim	  else if (src < in->len && in->ptr[src] == '&')
81433965Sjdp	    {
81533965Sjdp	      /* This is a preprocessor variable name, we don't do them
81677298Sobrien		 here.  */
81733965Sjdp	      sb_add_char (out, '\\');
81833965Sjdp	      sb_add_char (out, '&');
81933965Sjdp	      src++;
82033965Sjdp	    }
821218822Sdim	  else if (macro_mri && src < in->len && ISALNUM (in->ptr[src]))
82233965Sjdp	    {
82333965Sjdp	      int ind;
82433965Sjdp	      formal_entry *f;
82533965Sjdp
82689857Sobrien	      if (ISDIGIT (in->ptr[src]))
82733965Sjdp		ind = in->ptr[src] - '0';
82889857Sobrien	      else if (ISUPPER (in->ptr[src]))
82933965Sjdp		ind = in->ptr[src] - 'A' + 10;
83033965Sjdp	      else
83133965Sjdp		ind = in->ptr[src] - 'a' + 10;
83233965Sjdp	      ++src;
83333965Sjdp	      for (f = formals; f != NULL; f = f->next)
83433965Sjdp		{
83533965Sjdp		  if (f->index == ind - 1)
83633965Sjdp		    {
83733965Sjdp		      if (f->actual.len != 0)
83833965Sjdp			sb_add_sb (out, &f->actual);
83933965Sjdp		      else
84033965Sjdp			sb_add_sb (out, &f->def);
84133965Sjdp		      break;
84233965Sjdp		    }
84333965Sjdp		}
84433965Sjdp	    }
84533965Sjdp	  else
84633965Sjdp	    {
84733965Sjdp	      sb_reset (&t);
84833965Sjdp	      src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
84933965Sjdp	    }
85033965Sjdp	}
85133965Sjdp      else if ((macro_alternate || macro_mri)
852218822Sdim	       && is_name_beginner (in->ptr[src])
85333965Sjdp	       && (! inquote
85433965Sjdp		   || ! macro_strip_at
85533965Sjdp		   || (src > 0 && in->ptr[src - 1] == '@')))
85633965Sjdp	{
857218822Sdim	  if (! macro
85833965Sjdp	      || src + 5 >= in->len
85933965Sjdp	      || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
86033965Sjdp	      || ! ISWHITE (in->ptr[src + 5]))
86133965Sjdp	    {
86233965Sjdp	      sb_reset (&t);
86333965Sjdp	      src = sub_actual (src, in, &t, formal_hash,
86433965Sjdp				(macro_strip_at && inquote) ? '@' : '\'',
86533965Sjdp				out, 1);
86633965Sjdp	    }
86733965Sjdp	  else
86833965Sjdp	    {
86933965Sjdp	      src = sb_skip_white (src + 5, in);
870130561Sobrien	      while (in->ptr[src] != '\n')
87133965Sjdp		{
872218822Sdim		  const char *name;
873218822Sdim		  formal_entry *f = new_formal ();
87433965Sjdp
87533965Sjdp		  src = get_token (src, in, &f->name);
876218822Sdim		  name = sb_terminate (&f->name);
877218822Sdim		  if (! hash_find (formal_hash, name))
878218822Sdim		    {
879218822Sdim		      static int loccnt;
880218822Sdim		      char buf[20];
88133965Sjdp
882218822Sdim		      f->index = LOCAL_INDEX;
883218822Sdim		      f->next = loclist;
884218822Sdim		      loclist = f;
88533965Sjdp
886218822Sdim		      sprintf (buf, IS_ELF ? ".LL%04x" : "LL%04x", ++loccnt);
887218822Sdim		      sb_add_string (&f->actual, buf);
888218822Sdim
889218822Sdim		      err = hash_jam (formal_hash, name, f);
890218822Sdim		      if (err != NULL)
891218822Sdim			break;
892218822Sdim		    }
893218822Sdim		  else
894218822Sdim		    {
895218822Sdim		      as_bad_where (macro->file,
896218822Sdim				    macro->line + macro_line,
897218822Sdim				    _("`%s' was already used as parameter (or another local) name"),
898218822Sdim				    name);
899218822Sdim		      del_formal (f);
900218822Sdim		    }
901218822Sdim
90233965Sjdp		  src = sb_skip_comma (src, in);
90333965Sjdp		}
90433965Sjdp	    }
90533965Sjdp	}
90633965Sjdp      else if (in->ptr[src] == '"'
90733965Sjdp	       || (macro_mri && in->ptr[src] == '\''))
90833965Sjdp	{
90933965Sjdp	  inquote = !inquote;
91033965Sjdp	  sb_add_char (out, in->ptr[src++]);
91133965Sjdp	}
91233965Sjdp      else if (in->ptr[src] == '@' && macro_strip_at)
91333965Sjdp	{
91433965Sjdp	  ++src;
91533965Sjdp	  if (src < in->len
91633965Sjdp	      && in->ptr[src] == '@')
91733965Sjdp	    {
91833965Sjdp	      sb_add_char (out, '@');
91933965Sjdp	      ++src;
92033965Sjdp	    }
92133965Sjdp	}
92233965Sjdp      else if (macro_mri
92333965Sjdp	       && in->ptr[src] == '='
92433965Sjdp	       && src + 1 < in->len
92533965Sjdp	       && in->ptr[src + 1] == '=')
92633965Sjdp	{
92733965Sjdp	  formal_entry *ptr;
92833965Sjdp
92933965Sjdp	  sb_reset (&t);
93033965Sjdp	  src = get_token (src + 2, in, &t);
93133965Sjdp	  ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
93233965Sjdp	  if (ptr == NULL)
93333965Sjdp	    {
93433965Sjdp	      /* FIXME: We should really return a warning string here,
93533965Sjdp                 but we can't, because the == might be in the MRI
93633965Sjdp                 comment field, and, since the nature of the MRI
93733965Sjdp                 comment field depends upon the exact instruction
93833965Sjdp                 being used, we don't have enough information here to
93933965Sjdp                 figure out whether it is or not.  Instead, we leave
94033965Sjdp                 the == in place, which should cause a syntax error if
94133965Sjdp                 it is not in a comment.  */
94233965Sjdp	      sb_add_char (out, '=');
94333965Sjdp	      sb_add_char (out, '=');
94433965Sjdp	      sb_add_sb (out, &t);
94533965Sjdp	    }
94633965Sjdp	  else
94733965Sjdp	    {
94833965Sjdp	      if (ptr->actual.len)
94933965Sjdp		{
95033965Sjdp		  sb_add_string (out, "-1");
95133965Sjdp		}
95233965Sjdp	      else
95333965Sjdp		{
95433965Sjdp		  sb_add_char (out, '0');
95533965Sjdp		}
95633965Sjdp	    }
95733965Sjdp	}
95833965Sjdp      else
95933965Sjdp	{
960218822Sdim	  if (in->ptr[src] == '\n')
961218822Sdim	    ++macro_line;
96233965Sjdp	  sb_add_char (out, in->ptr[src++]);
96333965Sjdp	}
96433965Sjdp    }
96533965Sjdp
96633965Sjdp  sb_kill (&t);
96733965Sjdp
96833965Sjdp  while (loclist != NULL)
96933965Sjdp    {
97033965Sjdp      formal_entry *f;
97133965Sjdp
97233965Sjdp      f = loclist->next;
97360484Sobrien      /* Setting the value to NULL effectively deletes the entry.  We
97460484Sobrien         avoid calling hash_delete because it doesn't reclaim memory.  */
97560484Sobrien      hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
976218822Sdim      del_formal (loclist);
97733965Sjdp      loclist = f;
97833965Sjdp    }
97933965Sjdp
980218822Sdim  return err;
98133965Sjdp}
98233965Sjdp
98333965Sjdp/* Assign values to the formal parameters of a macro, and expand the
98433965Sjdp   body.  */
98533965Sjdp
98633965Sjdpstatic const char *
987130561Sobrienmacro_expand (int idx, sb *in, macro_entry *m, sb *out)
98833965Sjdp{
98933965Sjdp  sb t;
99033965Sjdp  formal_entry *ptr;
99133965Sjdp  formal_entry *f;
99233965Sjdp  int is_keyword = 0;
99333965Sjdp  int narg = 0;
994218822Sdim  const char *err = NULL;
99533965Sjdp
99633965Sjdp  sb_new (&t);
99777298Sobrien
99877298Sobrien  /* Reset any old value the actuals may have.  */
99933965Sjdp  for (f = m->formals; f; f = f->next)
100077298Sobrien    sb_reset (&f->actual);
100133965Sjdp  f = m->formals;
100233965Sjdp  while (f != NULL && f->index < 0)
100333965Sjdp    f = f->next;
100433965Sjdp
100533965Sjdp  if (macro_mri)
100633965Sjdp    {
100733965Sjdp      /* The macro may be called with an optional qualifier, which may
100833965Sjdp         be referred to in the macro body as \0.  */
100933965Sjdp      if (idx < in->len && in->ptr[idx] == '.')
1010104834Sobrien	{
1011104834Sobrien	  /* The Microtec assembler ignores this if followed by a white space.
1012104834Sobrien	     (Macro invocation with empty extension) */
1013104834Sobrien	  idx++;
1014104834Sobrien	  if (    idx < in->len
1015104834Sobrien		  && in->ptr[idx] != ' '
1016104834Sobrien		  && in->ptr[idx] != '\t')
1017104834Sobrien	    {
1018218822Sdim	      formal_entry *n = new_formal ();
101933965Sjdp
1020104834Sobrien	      n->index = QUAL_INDEX;
102133965Sjdp
1022104834Sobrien	      n->next = m->formals;
1023104834Sobrien	      m->formals = n;
102433965Sjdp
1025218822Sdim	      idx = get_any_string (idx, in, &n->actual);
1026104834Sobrien	    }
1027104834Sobrien	}
1028104834Sobrien    }
102933965Sjdp
103077298Sobrien  /* Peel off the actuals and store them away in the hash tables' actuals.  */
103133965Sjdp  idx = sb_skip_white (idx, in);
1032130561Sobrien  while (idx < in->len)
103333965Sjdp    {
103433965Sjdp      int scan;
103533965Sjdp
103677298Sobrien      /* Look and see if it's a positional or keyword arg.  */
103733965Sjdp      scan = idx;
103833965Sjdp      while (scan < in->len
103933965Sjdp	     && !ISSEP (in->ptr[scan])
104038889Sjdp	     && !(macro_mri && in->ptr[scan] == '\'')
104133965Sjdp	     && (!macro_alternate && in->ptr[scan] != '='))
104233965Sjdp	scan++;
104333965Sjdp      if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
104433965Sjdp	{
104533965Sjdp	  is_keyword = 1;
104633965Sjdp
104738889Sjdp	  /* It's OK to go from positional to keyword.  */
104838889Sjdp
104933965Sjdp	  /* This is a keyword arg, fetch the formal name and
105077298Sobrien	     then the actual stuff.  */
105133965Sjdp	  sb_reset (&t);
105233965Sjdp	  idx = get_token (idx, in, &t);
105333965Sjdp	  if (in->ptr[idx] != '=')
1054218822Sdim	    {
1055218822Sdim	      err = _("confusion in formal parameters");
1056218822Sdim	      break;
1057218822Sdim	    }
105833965Sjdp
105977298Sobrien	  /* Lookup the formal in the macro's list.  */
106033965Sjdp	  ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
106133965Sjdp	  if (!ptr)
1062218822Sdim	    as_bad (_("Parameter named `%s' does not exist for macro `%s'"),
1063218822Sdim		    t.ptr,
1064218822Sdim		    m->name);
106533965Sjdp	  else
106633965Sjdp	    {
106777298Sobrien	      /* Insert this value into the right place.  */
1068218822Sdim	      if (ptr->actual.len)
1069218822Sdim		{
1070218822Sdim		  as_warn (_("Value for parameter `%s' of macro `%s' was already specified"),
1071218822Sdim			   ptr->name.ptr,
1072218822Sdim			   m->name);
1073218822Sdim		  sb_reset (&ptr->actual);
1074218822Sdim		}
1075218822Sdim	      idx = get_any_string (idx + 1, in, &ptr->actual);
107633965Sjdp	      if (ptr->actual.len > 0)
107733965Sjdp		++narg;
107833965Sjdp	    }
107933965Sjdp	}
108033965Sjdp      else
108133965Sjdp	{
108233965Sjdp	  if (is_keyword)
1083218822Sdim	    {
1084218822Sdim	      err = _("can't mix positional and keyword arguments");
1085218822Sdim	      break;
1086218822Sdim	    }
108733965Sjdp
108833965Sjdp	  if (!f)
108933965Sjdp	    {
109033965Sjdp	      formal_entry **pf;
109133965Sjdp	      int c;
109233965Sjdp
109333965Sjdp	      if (!macro_mri)
1094218822Sdim		{
1095218822Sdim		  err = _("too many positional arguments");
1096218822Sdim		  break;
1097218822Sdim		}
109833965Sjdp
1099218822Sdim	      f = new_formal ();
110033965Sjdp
110133965Sjdp	      c = -1;
110233965Sjdp	      for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
110333965Sjdp		if ((*pf)->index >= c)
110433965Sjdp		  c = (*pf)->index + 1;
110533965Sjdp	      if (c == -1)
110633965Sjdp		c = 0;
110733965Sjdp	      *pf = f;
110833965Sjdp	      f->index = c;
110933965Sjdp	    }
111033965Sjdp
1111218822Sdim	  if (f->type != FORMAL_VARARG)
1112218822Sdim	    idx = get_any_string (idx, in, &f->actual);
1113218822Sdim	  else
1114218822Sdim	    {
1115218822Sdim	      sb_add_buffer (&f->actual, in->ptr + idx, in->len - idx);
1116218822Sdim	      idx = in->len;
1117218822Sdim	    }
111833965Sjdp	  if (f->actual.len > 0)
111933965Sjdp	    ++narg;
112033965Sjdp	  do
112133965Sjdp	    {
112233965Sjdp	      f = f->next;
112333965Sjdp	    }
112433965Sjdp	  while (f != NULL && f->index < 0);
112533965Sjdp	}
112633965Sjdp
112733965Sjdp      if (! macro_mri)
112833965Sjdp	idx = sb_skip_comma (idx, in);
112933965Sjdp      else
113033965Sjdp	{
113133965Sjdp	  if (in->ptr[idx] == ',')
113233965Sjdp	    ++idx;
113333965Sjdp	  if (ISWHITE (in->ptr[idx]))
113433965Sjdp	    break;
113533965Sjdp	}
113633965Sjdp    }
113733965Sjdp
1138218822Sdim  if (! err)
113933965Sjdp    {
1140218822Sdim      for (ptr = m->formals; ptr; ptr = ptr->next)
1141218822Sdim	{
1142218822Sdim	  if (ptr->type == FORMAL_REQUIRED && ptr->actual.len == 0)
1143218822Sdim	    as_bad (_("Missing value for required parameter `%s' of macro `%s'"),
1144218822Sdim		    ptr->name.ptr,
1145218822Sdim		    m->name);
1146218822Sdim	}
114733965Sjdp
1148218822Sdim      if (macro_mri)
1149218822Sdim	{
1150218822Sdim	  char buffer[20];
1151218822Sdim
1152218822Sdim	  sb_reset (&t);
1153218822Sdim	  sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
1154218822Sdim	  ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1155218822Sdim	  sprintf (buffer, "%d", narg);
1156218822Sdim	  sb_add_string (&ptr->actual, buffer);
1157218822Sdim	}
1158218822Sdim
1159218822Sdim      err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m);
116033965Sjdp    }
116133965Sjdp
116233965Sjdp  /* Discard any unnamed formal arguments.  */
116333965Sjdp  if (macro_mri)
116433965Sjdp    {
116533965Sjdp      formal_entry **pf;
116633965Sjdp
116733965Sjdp      pf = &m->formals;
116833965Sjdp      while (*pf != NULL)
116933965Sjdp	{
117033965Sjdp	  if ((*pf)->name.len != 0)
117133965Sjdp	    pf = &(*pf)->next;
117233965Sjdp	  else
117333965Sjdp	    {
117433965Sjdp	      f = (*pf)->next;
1175218822Sdim	      del_formal (*pf);
117633965Sjdp	      *pf = f;
117733965Sjdp	    }
117833965Sjdp	}
117933965Sjdp    }
118033965Sjdp
118133965Sjdp  sb_kill (&t);
1182218822Sdim  if (!err)
1183218822Sdim    macro_number++;
118433965Sjdp
1185218822Sdim  return err;
118633965Sjdp}
118733965Sjdp
118833965Sjdp/* Check for a macro.  If one is found, put the expansion into
1189130561Sobrien   *EXPAND.  Return 1 if a macro is found, 0 otherwise.  */
119033965Sjdp
119133965Sjdpint
1192130561Sobriencheck_macro (const char *line, sb *expand,
1193130561Sobrien	     const char **error, macro_entry **info)
119433965Sjdp{
119533965Sjdp  const char *s;
119633965Sjdp  char *copy, *cs;
119733965Sjdp  macro_entry *macro;
119833965Sjdp  sb line_sb;
119933965Sjdp
1200218822Sdim  if (! is_name_beginner (*line)
120133965Sjdp      && (! macro_mri || *line != '.'))
120233965Sjdp    return 0;
120333965Sjdp
120433965Sjdp  s = line + 1;
1205218822Sdim  while (is_part_of_name (*s))
120633965Sjdp    ++s;
1207218822Sdim  if (is_name_ender (*s))
1208218822Sdim    ++s;
120933965Sjdp
121038889Sjdp  copy = (char *) alloca (s - line + 1);
121133965Sjdp  memcpy (copy, line, s - line);
121233965Sjdp  copy[s - line] = '\0';
121333965Sjdp  for (cs = copy; *cs != '\0'; cs++)
121489857Sobrien    *cs = TOLOWER (*cs);
121533965Sjdp
121633965Sjdp  macro = (macro_entry *) hash_find (macro_hash, copy);
121733965Sjdp
121833965Sjdp  if (macro == NULL)
121933965Sjdp    return 0;
122033965Sjdp
122133965Sjdp  /* Wrap the line up in an sb.  */
122233965Sjdp  sb_new (&line_sb);
122333965Sjdp  while (*s != '\0' && *s != '\n' && *s != '\r')
122433965Sjdp    sb_add_char (&line_sb, *s++);
122533965Sjdp
122633965Sjdp  sb_new (expand);
1227130561Sobrien  *error = macro_expand (0, &line_sb, macro, expand);
122833965Sjdp
122933965Sjdp  sb_kill (&line_sb);
123033965Sjdp
123177298Sobrien  /* Export the macro information if requested.  */
123260484Sobrien  if (info)
123360484Sobrien    *info = macro;
123460484Sobrien
123533965Sjdp  return 1;
123633965Sjdp}
123733965Sjdp
1238218822Sdim/* Free the memory allocated to a macro.  */
1239218822Sdim
1240218822Sdimstatic void
1241218822Sdimfree_macro(macro_entry *macro)
1242218822Sdim{
1243218822Sdim  formal_entry *formal;
1244218822Sdim
1245218822Sdim  for (formal = macro->formals; formal; )
1246218822Sdim    {
1247218822Sdim      formal_entry *f;
1248218822Sdim
1249218822Sdim      f = formal;
1250218822Sdim      formal = formal->next;
1251218822Sdim      del_formal (f);
1252218822Sdim    }
1253218822Sdim  hash_die (macro->formal_hash);
1254218822Sdim  sb_kill (&macro->sub);
1255218822Sdim  free (macro);
1256218822Sdim}
1257218822Sdim
125833965Sjdp/* Delete a macro.  */
125933965Sjdp
126033965Sjdpvoid
1261130561Sobriendelete_macro (const char *name)
126233965Sjdp{
1263218822Sdim  char *copy;
1264218822Sdim  size_t i, len;
1265218822Sdim  macro_entry *macro;
1266218822Sdim
1267218822Sdim  len = strlen (name);
1268218822Sdim  copy = (char *) alloca (len + 1);
1269218822Sdim  for (i = 0; i < len; ++i)
1270218822Sdim    copy[i] = TOLOWER (name[i]);
1271218822Sdim  copy[i] = '\0';
1272218822Sdim
1273218822Sdim  /* Since hash_delete doesn't free memory, just clear out the entry.  */
1274218822Sdim  if ((macro = hash_find (macro_hash, copy)) != NULL)
1275218822Sdim    {
1276218822Sdim      hash_jam (macro_hash, copy, NULL);
1277218822Sdim      free_macro (macro);
1278218822Sdim    }
1279218822Sdim  else
1280218822Sdim    as_warn (_("Attempt to purge non-existant macro `%s'"), copy);
128133965Sjdp}
128233965Sjdp
128333965Sjdp/* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
128433965Sjdp   combined macro definition and execution.  This returns NULL on
128533965Sjdp   success, or an error message otherwise.  */
128633965Sjdp
128733965Sjdpconst char *
1288130561Sobrienexpand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
128933965Sjdp{
129033965Sjdp  sb sub;
129133965Sjdp  formal_entry f;
129233965Sjdp  struct hash_control *h;
129333965Sjdp  const char *err;
129433965Sjdp
129533965Sjdp  idx = sb_skip_white (idx, in);
129633965Sjdp
129733965Sjdp  sb_new (&sub);
1298218822Sdim  if (! buffer_and_nest (NULL, "ENDR", &sub, get_line))
129960484Sobrien    return _("unexpected end of file in irp or irpc");
130077298Sobrien
130133965Sjdp  sb_new (&f.name);
130233965Sjdp  sb_new (&f.def);
130333965Sjdp  sb_new (&f.actual);
130433965Sjdp
130533965Sjdp  idx = get_token (idx, in, &f.name);
130633965Sjdp  if (f.name.len == 0)
130760484Sobrien    return _("missing model parameter");
130833965Sjdp
130933965Sjdp  h = hash_new ();
131033965Sjdp  err = hash_jam (h, sb_terminate (&f.name), &f);
131133965Sjdp  if (err != NULL)
131233965Sjdp    return err;
131333965Sjdp
131433965Sjdp  f.index = 1;
131533965Sjdp  f.next = NULL;
1316218822Sdim  f.type = FORMAL_OPTIONAL;
131733965Sjdp
131833965Sjdp  sb_reset (out);
131933965Sjdp
132033965Sjdp  idx = sb_skip_comma (idx, in);
1321130561Sobrien  if (idx >= in->len)
132233965Sjdp    {
132333965Sjdp      /* Expand once with a null string.  */
1324130561Sobrien      err = macro_expand_body (&sub, out, &f, h, 0);
132533965Sjdp    }
132633965Sjdp  else
132733965Sjdp    {
1328218822Sdim      bfd_boolean in_quotes = FALSE;
1329218822Sdim
133033965Sjdp      if (irpc && in->ptr[idx] == '"')
1331218822Sdim	{
1332218822Sdim	  in_quotes = TRUE;
1333218822Sdim	  ++idx;
1334218822Sdim	}
1335218822Sdim
1336130561Sobrien      while (idx < in->len)
133733965Sjdp	{
133833965Sjdp	  if (!irpc)
1339218822Sdim	    idx = get_any_string (idx, in, &f.actual);
134033965Sjdp	  else
134133965Sjdp	    {
134233965Sjdp	      if (in->ptr[idx] == '"')
134333965Sjdp		{
134433965Sjdp		  int nxt;
134533965Sjdp
1346218822Sdim		  if (irpc)
1347218822Sdim		    in_quotes = ! in_quotes;
1348218822Sdim
134933965Sjdp		  nxt = sb_skip_white (idx + 1, in);
1350130561Sobrien		  if (nxt >= in->len)
135133965Sjdp		    {
135233965Sjdp		      idx = nxt;
135333965Sjdp		      break;
135433965Sjdp		    }
135533965Sjdp		}
135633965Sjdp	      sb_reset (&f.actual);
135733965Sjdp	      sb_add_char (&f.actual, in->ptr[idx]);
135833965Sjdp	      ++idx;
135933965Sjdp	    }
1360218822Sdim
1361130561Sobrien	  err = macro_expand_body (&sub, out, &f, h, 0);
136233965Sjdp	  if (err != NULL)
1363218822Sdim	    break;
136433965Sjdp	  if (!irpc)
136533965Sjdp	    idx = sb_skip_comma (idx, in);
1366218822Sdim	  else if (! in_quotes)
136733965Sjdp	    idx = sb_skip_white (idx, in);
136833965Sjdp	}
136933965Sjdp    }
137033965Sjdp
137133965Sjdp  hash_die (h);
1372218822Sdim  sb_kill (&f.actual);
1373218822Sdim  sb_kill (&f.def);
1374218822Sdim  sb_kill (&f.name);
137533965Sjdp  sb_kill (&sub);
137633965Sjdp
1377218822Sdim  return err;
137833965Sjdp}
1379