macro.c revision 104834
1/* macro.c - macro support for gas and gasp
2   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
3   Free Software Foundation, Inc.
4
5   Written by Steve and Judy Chamberlain of Cygnus Support,
6      sac@cygnus.com
7
8   This file is part of GAS, the GNU Assembler.
9
10   GAS is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2, or (at your option)
13   any later version.
14
15   GAS is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with GAS; see the file COPYING.  If not, write to the Free
22   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23   02111-1307, USA.  */
24
25#include "config.h"
26
27#ifndef __GNUC__
28# if HAVE_ALLOCA_H
29#  include <alloca.h>
30# else
31#  ifdef _AIX
32/* Indented so that pre-ansi C compilers will ignore it, rather than
33   choke on it.  Some versions of AIX require this to be the first
34   thing in the file.  */
35 #pragma alloca
36#  else
37#   ifndef alloca /* predefined by HP cc +Olibcalls */
38#    if !defined (__STDC__) && !defined (__hpux)
39extern char *alloca ();
40#    else
41extern void *alloca ();
42#    endif /* __STDC__, __hpux */
43#   endif /* alloca */
44#  endif /* _AIX */
45# endif /* HAVE_ALLOCA_H */
46#endif /* __GNUC__ */
47
48#include <stdio.h>
49#ifdef HAVE_STRING_H
50#include <string.h>
51#else
52#include <strings.h>
53#endif
54#ifdef HAVE_STDLIB_H
55#include <stdlib.h>
56#endif
57#include "libiberty.h"
58#include "safe-ctype.h"
59#include "sb.h"
60#include "hash.h"
61#include "macro.h"
62
63#include "asintl.h"
64
65/* The routines in this file handle macro definition and expansion.
66   They are called by both gasp and gas.  */
67
68/* Internal functions.  */
69
70static int get_token PARAMS ((int, sb *, sb *));
71static int getstring PARAMS ((int, sb *, sb *));
72static int get_any_string PARAMS ((int, sb *, sb *, int, int));
73static int do_formals PARAMS ((macro_entry *, int, sb *));
74static int get_apost_token PARAMS ((int, sb *, sb *, int));
75static int sub_actual
76  PARAMS ((int, sb *, sb *, struct hash_control *, int, sb *, int));
77static const char *macro_expand_body
78  PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int, int));
79static const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *, int));
80
81#define ISWHITE(x) ((x) == ' ' || (x) == '\t')
82
83#define ISSEP(x) \
84 ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
85  || (x) == ')' || (x) == '(' \
86  || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
87
88#define ISBASE(x) \
89  ((x) == 'b' || (x) == 'B' \
90   || (x) == 'q' || (x) == 'Q' \
91   || (x) == 'h' || (x) == 'H' \
92   || (x) == 'd' || (x) == 'D')
93
94/* The macro hash table.  */
95
96static struct hash_control *macro_hash;
97
98/* Whether any macros have been defined.  */
99
100int macro_defined;
101
102/* Whether we are in GASP alternate mode.  */
103
104static int macro_alternate;
105
106/* Whether we are in MRI mode.  */
107
108static int macro_mri;
109
110/* Whether we should strip '@' characters.  */
111
112static int macro_strip_at;
113
114/* Function to use to parse an expression.  */
115
116static int (*macro_expr) PARAMS ((const char *, int, sb *, int *));
117
118/* Number of macro expansions that have been done.  */
119
120static int macro_number;
121
122/* Initialize macro processing.  */
123
124void
125macro_init (alternate, mri, strip_at, expr)
126     int alternate;
127     int mri;
128     int strip_at;
129     int (*expr) PARAMS ((const char *, int, sb *, int *));
130{
131  macro_hash = hash_new ();
132  macro_defined = 0;
133  macro_alternate = alternate;
134  macro_mri = mri;
135  macro_strip_at = strip_at;
136  macro_expr = expr;
137}
138
139/* Switch in and out of MRI mode on the fly.  */
140
141void
142macro_mri_mode (mri)
143     int mri;
144{
145  macro_mri = mri;
146}
147
148/* Read input lines till we get to a TO string.
149   Increase nesting depth if we get a FROM string.
150   Put the results into sb at PTR.
151   Add a new input line to an sb using GET_LINE.
152   Return 1 on success, 0 on unexpected EOF.  */
153
154int
155buffer_and_nest (from, to, ptr, get_line)
156     const char *from;
157     const char *to;
158     sb *ptr;
159     int (*get_line) PARAMS ((sb *));
160{
161  int from_len = strlen (from);
162  int to_len = strlen (to);
163  int depth = 1;
164  int line_start = ptr->len;
165
166  int more = get_line (ptr);
167
168  while (more)
169    {
170      /* Try and find the first pseudo op on the line.  */
171      int i = line_start;
172
173      if (! macro_alternate && ! macro_mri)
174	{
175	  /* With normal syntax we can suck what we want till we get
176	     to the dot.  With the alternate, labels have to start in
177	     the first column, since we cant tell what's a label and
178	     whats a pseudoop.  */
179
180	  /* Skip leading whitespace.  */
181	  while (i < ptr->len && ISWHITE (ptr->ptr[i]))
182	    i++;
183
184	  /* Skip over a label.  */
185	  while (i < ptr->len
186		 && (ISALNUM (ptr->ptr[i])
187		     || ptr->ptr[i] == '_'
188		     || ptr->ptr[i] == '$'))
189	    i++;
190
191	  /* And a colon.  */
192	  if (i < ptr->len
193	      && ptr->ptr[i] == ':')
194	    i++;
195
196	}
197      /* Skip trailing whitespace.  */
198      while (i < ptr->len && ISWHITE (ptr->ptr[i]))
199	i++;
200
201      if (i < ptr->len && (ptr->ptr[i] == '.'
202			   || macro_alternate
203			   || macro_mri))
204	{
205	  if (ptr->ptr[i] == '.')
206	    i++;
207	  if (strncasecmp (ptr->ptr + i, from, from_len) == 0
208	      && (ptr->len == (i + from_len)
209		  || ! ISALNUM (ptr->ptr[i + from_len])))
210	    depth++;
211	  if (strncasecmp (ptr->ptr + i, to, to_len) == 0
212	      && (ptr->len == (i + to_len)
213		  || ! ISALNUM (ptr->ptr[i + to_len])))
214	    {
215	      depth--;
216	      if (depth == 0)
217		{
218		  /* Reset the string to not include the ending rune.  */
219		  ptr->len = line_start;
220		  break;
221		}
222	    }
223	}
224
225      /* Add a CR to the end and keep running.  */
226      sb_add_char (ptr, '\n');
227      line_start = ptr->len;
228      more = get_line (ptr);
229    }
230
231  /* Return 1 on success, 0 on unexpected EOF.  */
232  return depth == 0;
233}
234
235/* Pick up a token.  */
236
237static int
238get_token (idx, in, name)
239     int idx;
240     sb *in;
241     sb *name;
242{
243  if (idx < in->len
244      && (ISALPHA (in->ptr[idx])
245	  || in->ptr[idx] == '_'
246	  || in->ptr[idx] == '$'))
247    {
248      sb_add_char (name, in->ptr[idx++]);
249      while (idx < in->len
250	     && (ISALNUM (in->ptr[idx])
251		 || in->ptr[idx] == '_'
252		 || in->ptr[idx] == '$'))
253	{
254	  sb_add_char (name, in->ptr[idx++]);
255	}
256    }
257  /* Ignore trailing &.  */
258  if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
259    idx++;
260  return idx;
261}
262
263/* Pick up a string.  */
264
265static int
266getstring (idx, in, acc)
267     int idx;
268     sb *in;
269     sb *acc;
270{
271  idx = sb_skip_white (idx, in);
272
273  while (idx < in->len
274	 && (in->ptr[idx] == '"'
275	     || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
276	     || (in->ptr[idx] == '\'' && macro_alternate)))
277    {
278      if (in->ptr[idx] == '<')
279	{
280	  int nest = 0;
281	  idx++;
282	  while ((in->ptr[idx] != '>' || nest)
283		 && idx < in->len)
284	    {
285	      if (in->ptr[idx] == '!')
286		{
287		  idx++;
288		  sb_add_char (acc, in->ptr[idx++]);
289		}
290	      else
291		{
292		  if (in->ptr[idx] == '>')
293		    nest--;
294		  if (in->ptr[idx] == '<')
295		    nest++;
296		  sb_add_char (acc, in->ptr[idx++]);
297		}
298	    }
299	  idx++;
300	}
301      else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
302	{
303	  char tchar = in->ptr[idx];
304	  int escaped = 0;
305
306	  idx++;
307
308	  while (idx < in->len)
309	    {
310	      if (in->ptr[idx - 1] == '\\')
311		escaped ^= 1;
312	      else
313		escaped = 0;
314
315	      if (macro_alternate && in->ptr[idx] == '!')
316		{
317		  idx ++;
318
319		  sb_add_char (acc, in->ptr[idx]);
320
321		  idx ++;
322		}
323	      else if (escaped && in->ptr[idx] == tchar)
324		{
325		  sb_add_char (acc, tchar);
326		  idx ++;
327		}
328	      else
329		{
330		  if (in->ptr[idx] == tchar)
331		    {
332		      idx ++;
333
334		      if (idx >= in->len || in->ptr[idx] != tchar)
335			break;
336		    }
337
338		  sb_add_char (acc, in->ptr[idx]);
339		  idx ++;
340		}
341	    }
342	}
343    }
344
345  return idx;
346}
347
348/* Fetch string from the input stream,
349   rules:
350    'Bxyx<whitespace>  	-> return 'Bxyza
351    %<char>		-> return string of decimal value of x
352    "<string>"		-> return string
353    xyx<whitespace>     -> return xyz
354*/
355
356static int
357get_any_string (idx, in, out, expand, pretend_quoted)
358     int idx;
359     sb *in;
360     sb *out;
361     int expand;
362     int pretend_quoted;
363{
364  sb_reset (out);
365  idx = sb_skip_white (idx, in);
366
367  if (idx < in->len)
368    {
369      if (in->len > 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
370	{
371	  while (!ISSEP (in->ptr[idx]))
372	    sb_add_char (out, in->ptr[idx++]);
373	}
374      else if (in->ptr[idx] == '%'
375	       && macro_alternate
376	       && expand)
377	{
378	  int val;
379	  char buf[20];
380	  /* Turns the next expression into a string.  */
381	  /* xgettext: no-c-format */
382	  idx = (*macro_expr) (_("% operator needs absolute expression"),
383			       idx + 1,
384			       in,
385			       &val);
386	  sprintf (buf, "%d", val);
387	  sb_add_string (out, buf);
388	}
389      else if (in->ptr[idx] == '"'
390	       || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
391	       || (macro_alternate && in->ptr[idx] == '\''))
392	{
393	  if (macro_alternate
394	      && ! macro_strip_at
395	      && expand)
396	    {
397	      /* Keep the quotes.  */
398	      sb_add_char (out, '\"');
399
400	      idx = getstring (idx, in, out);
401	      sb_add_char (out, '\"');
402	    }
403	  else
404	    {
405	      idx = getstring (idx, in, out);
406	    }
407	}
408      else
409	{
410	  while (idx < in->len
411		 && (in->ptr[idx] == '"'
412		     || in->ptr[idx] == '\''
413		     || pretend_quoted
414		     || (in->ptr[idx] != ' '
415			 && in->ptr[idx] != '\t'
416			 && in->ptr[idx] != ','
417			 && (in->ptr[idx] != '<'
418			     || (! macro_alternate && ! macro_mri)))))
419	    {
420	      if (in->ptr[idx] == '"'
421		  || in->ptr[idx] == '\'')
422		{
423		  char tchar = in->ptr[idx];
424		  sb_add_char (out, in->ptr[idx++]);
425		  while (idx < in->len
426			 && in->ptr[idx] != tchar)
427		    sb_add_char (out, in->ptr[idx++]);
428		  if (idx == in->len)
429		    return idx;
430		}
431	      sb_add_char (out, in->ptr[idx++]);
432	    }
433	}
434    }
435
436  return idx;
437}
438
439/* Pick up the formal parameters of a macro definition.  */
440
441static int
442do_formals (macro, idx, in)
443     macro_entry *macro;
444     int idx;
445     sb *in;
446{
447  formal_entry **p = &macro->formals;
448
449  macro->formal_count = 0;
450  macro->formal_hash = hash_new ();
451  while (idx < in->len)
452    {
453      formal_entry *formal;
454
455      formal = (formal_entry *) xmalloc (sizeof (formal_entry));
456
457      sb_new (&formal->name);
458      sb_new (&formal->def);
459      sb_new (&formal->actual);
460
461      idx = sb_skip_white (idx, in);
462      idx = get_token (idx, in, &formal->name);
463      if (formal->name.len == 0)
464	break;
465      idx = sb_skip_white (idx, in);
466      if (formal->name.len)
467	{
468	  /* This is a formal.  */
469	  if (idx < in->len && in->ptr[idx] == '=')
470	    {
471	      /* Got a default.  */
472	      idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
473	    }
474	}
475
476      /* Add to macro's hash table.  */
477      hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
478
479      formal->index = macro->formal_count;
480      idx = sb_skip_comma (idx, in);
481      macro->formal_count++;
482      *p = formal;
483      p = &formal->next;
484      *p = NULL;
485    }
486
487  if (macro_mri)
488    {
489      formal_entry *formal;
490      const char *name;
491
492      /* Add a special NARG formal, which macro_expand will set to the
493         number of arguments.  */
494      formal = (formal_entry *) xmalloc (sizeof (formal_entry));
495
496      sb_new (&formal->name);
497      sb_new (&formal->def);
498      sb_new (&formal->actual);
499
500      /* The same MRI assemblers which treat '@' characters also use
501         the name $NARG.  At least until we find an exception.  */
502      if (macro_strip_at)
503	name = "$NARG";
504      else
505	name = "NARG";
506
507      sb_add_string (&formal->name, name);
508
509      /* Add to macro's hash table.  */
510      hash_jam (macro->formal_hash, name, formal);
511
512      formal->index = NARG_INDEX;
513      *p = formal;
514      formal->next = NULL;
515    }
516
517  return idx;
518}
519
520/* Define a new macro.  Returns NULL on success, otherwise returns an
521   error message.  If NAMEP is not NULL, *NAMEP is set to the name of
522   the macro which was defined.  */
523
524const char *
525define_macro (idx, in, label, get_line, namep)
526     int idx;
527     sb *in;
528     sb *label;
529     int (*get_line) PARAMS ((sb *));
530     const char **namep;
531{
532  macro_entry *macro;
533  sb name;
534  const char *namestr;
535
536  macro = (macro_entry *) xmalloc (sizeof (macro_entry));
537  sb_new (&macro->sub);
538  sb_new (&name);
539
540  macro->formal_count = 0;
541  macro->formals = 0;
542
543  idx = sb_skip_white (idx, in);
544  if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
545    return _("unexpected end of file in macro definition");
546  if (label != NULL && label->len != 0)
547    {
548      sb_add_sb (&name, label);
549      if (idx < in->len && in->ptr[idx] == '(')
550	{
551	  /* It's the label: MACRO (formals,...)  sort  */
552	  idx = do_formals (macro, idx + 1, in);
553	  if (in->ptr[idx] != ')')
554	    return _("missing ) after formals");
555	}
556      else
557	{
558	  /* It's the label: MACRO formals,...  sort  */
559	  idx = do_formals (macro, idx, in);
560	}
561    }
562  else
563    {
564      idx = get_token (idx, in, &name);
565      idx = sb_skip_comma (idx, in);
566      idx = do_formals (macro, idx, in);
567    }
568
569  /* And stick it in the macro hash table.  */
570  for (idx = 0; idx < name.len; idx++)
571    name.ptr[idx] = TOLOWER (name.ptr[idx]);
572  namestr = sb_terminate (&name);
573  hash_jam (macro_hash, namestr, (PTR) macro);
574
575  macro_defined = 1;
576
577  if (namep != NULL)
578    *namep = namestr;
579
580  return NULL;
581}
582
583/* Scan a token, and then skip KIND.  */
584
585static int
586get_apost_token (idx, in, name, kind)
587     int idx;
588     sb *in;
589     sb *name;
590     int kind;
591{
592  idx = get_token (idx, in, name);
593  if (idx < in->len
594      && in->ptr[idx] == kind
595      && (! macro_mri || macro_strip_at)
596      && (! macro_strip_at || kind == '@'))
597    idx++;
598  return idx;
599}
600
601/* Substitute the actual value for a formal parameter.  */
602
603static int
604sub_actual (start, in, t, formal_hash, kind, out, copyifnotthere)
605     int start;
606     sb *in;
607     sb *t;
608     struct hash_control *formal_hash;
609     int kind;
610     sb *out;
611     int copyifnotthere;
612{
613  int src;
614  formal_entry *ptr;
615
616  src = get_apost_token (start, in, t, kind);
617  /* See if it's in the macro's hash table, unless this is
618     macro_strip_at and kind is '@' and the token did not end in '@'.  */
619  if (macro_strip_at
620      && kind == '@'
621      && (src == start || in->ptr[src - 1] != '@'))
622    ptr = NULL;
623  else
624    ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
625  if (ptr)
626    {
627      if (ptr->actual.len)
628	{
629	  sb_add_sb (out, &ptr->actual);
630	}
631      else
632	{
633	  sb_add_sb (out, &ptr->def);
634	}
635    }
636  else if (kind == '&')
637    {
638      /* Doing this permits people to use & in macro bodies.  */
639      sb_add_char (out, '&');
640    }
641  else if (copyifnotthere)
642    {
643      sb_add_sb (out, t);
644    }
645  else
646    {
647      sb_add_char (out, '\\');
648      sb_add_sb (out, t);
649    }
650  return src;
651}
652
653/* Expand the body of a macro.  */
654
655static const char *
656macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
657     sb *in;
658     sb *out;
659     formal_entry *formals;
660     struct hash_control *formal_hash;
661     int comment_char;
662     int locals;
663{
664  sb t;
665  int src = 0;
666  int inquote = 0;
667  formal_entry *loclist = NULL;
668
669  sb_new (&t);
670
671  while (src < in->len)
672    {
673      if (in->ptr[src] == '&')
674	{
675	  sb_reset (&t);
676	  if (macro_mri)
677	    {
678	      if (src + 1 < in->len && in->ptr[src + 1] == '&')
679		src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
680	      else
681		sb_add_char (out, in->ptr[src++]);
682	    }
683	  else
684	    {
685	      /* FIXME: Why do we do this?  */
686	      src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
687	    }
688	}
689      else if (in->ptr[src] == '\\')
690	{
691	  src++;
692	  if (in->ptr[src] == comment_char && comment_char != '\0')
693	    {
694	      /* This is a comment, just drop the rest of the line.  */
695	      while (src < in->len
696		     && in->ptr[src] != '\n')
697		src++;
698	    }
699	  else if (in->ptr[src] == '(')
700	    {
701	      /* Sub in till the next ')' literally.  */
702	      src++;
703	      while (src < in->len && in->ptr[src] != ')')
704		{
705		  sb_add_char (out, in->ptr[src++]);
706		}
707	      if (in->ptr[src] == ')')
708		src++;
709	      else
710		return _("missplaced )");
711	    }
712	  else if (in->ptr[src] == '@')
713	    {
714	      /* Sub in the macro invocation number.  */
715
716	      char buffer[10];
717	      src++;
718	      sprintf (buffer, "%d", macro_number);
719	      sb_add_string (out, buffer);
720	    }
721	  else if (in->ptr[src] == '&')
722	    {
723	      /* This is a preprocessor variable name, we don't do them
724		 here.  */
725	      sb_add_char (out, '\\');
726	      sb_add_char (out, '&');
727	      src++;
728	    }
729	  else if (macro_mri && ISALNUM (in->ptr[src]))
730	    {
731	      int ind;
732	      formal_entry *f;
733
734	      if (ISDIGIT (in->ptr[src]))
735		ind = in->ptr[src] - '0';
736	      else if (ISUPPER (in->ptr[src]))
737		ind = in->ptr[src] - 'A' + 10;
738	      else
739		ind = in->ptr[src] - 'a' + 10;
740	      ++src;
741	      for (f = formals; f != NULL; f = f->next)
742		{
743		  if (f->index == ind - 1)
744		    {
745		      if (f->actual.len != 0)
746			sb_add_sb (out, &f->actual);
747		      else
748			sb_add_sb (out, &f->def);
749		      break;
750		    }
751		}
752	    }
753	  else
754	    {
755	      sb_reset (&t);
756	      src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
757	    }
758	}
759      else if ((macro_alternate || macro_mri)
760	       && (ISALPHA (in->ptr[src])
761		   || in->ptr[src] == '_'
762		   || in->ptr[src] == '$')
763	       && (! inquote
764		   || ! macro_strip_at
765		   || (src > 0 && in->ptr[src - 1] == '@')))
766	{
767	  if (! locals
768	      || src + 5 >= in->len
769	      || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
770	      || ! ISWHITE (in->ptr[src + 5]))
771	    {
772	      sb_reset (&t);
773	      src = sub_actual (src, in, &t, formal_hash,
774				(macro_strip_at && inquote) ? '@' : '\'',
775				out, 1);
776	    }
777	  else
778	    {
779	      formal_entry *f;
780
781	      src = sb_skip_white (src + 5, in);
782	      while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
783		{
784		  static int loccnt;
785		  char buf[20];
786		  const char *err;
787
788		  f = (formal_entry *) xmalloc (sizeof (formal_entry));
789		  sb_new (&f->name);
790		  sb_new (&f->def);
791		  sb_new (&f->actual);
792		  f->index = LOCAL_INDEX;
793		  f->next = loclist;
794		  loclist = f;
795
796		  src = get_token (src, in, &f->name);
797		  ++loccnt;
798		  sprintf (buf, "LL%04x", loccnt);
799		  sb_add_string (&f->actual, buf);
800
801		  err = hash_jam (formal_hash, sb_terminate (&f->name), f);
802		  if (err != NULL)
803		    return err;
804
805		  src = sb_skip_comma (src, in);
806		}
807	    }
808	}
809      else if (comment_char != '\0'
810	       && in->ptr[src] == comment_char
811	       && src + 1 < in->len
812	       && in->ptr[src + 1] == comment_char
813	       && !inquote)
814	{
815	  /* Two comment chars in a row cause the rest of the line to
816             be dropped.  */
817	  while (src < in->len && in->ptr[src] != '\n')
818	    src++;
819	}
820      else if (in->ptr[src] == '"'
821	       || (macro_mri && in->ptr[src] == '\''))
822	{
823	  inquote = !inquote;
824	  sb_add_char (out, in->ptr[src++]);
825	}
826      else if (in->ptr[src] == '@' && macro_strip_at)
827	{
828	  ++src;
829	  if (src < in->len
830	      && in->ptr[src] == '@')
831	    {
832	      sb_add_char (out, '@');
833	      ++src;
834	    }
835	}
836      else if (macro_mri
837	       && in->ptr[src] == '='
838	       && src + 1 < in->len
839	       && in->ptr[src + 1] == '=')
840	{
841	  formal_entry *ptr;
842
843	  sb_reset (&t);
844	  src = get_token (src + 2, in, &t);
845	  ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
846	  if (ptr == NULL)
847	    {
848	      /* FIXME: We should really return a warning string here,
849                 but we can't, because the == might be in the MRI
850                 comment field, and, since the nature of the MRI
851                 comment field depends upon the exact instruction
852                 being used, we don't have enough information here to
853                 figure out whether it is or not.  Instead, we leave
854                 the == in place, which should cause a syntax error if
855                 it is not in a comment.  */
856	      sb_add_char (out, '=');
857	      sb_add_char (out, '=');
858	      sb_add_sb (out, &t);
859	    }
860	  else
861	    {
862	      if (ptr->actual.len)
863		{
864		  sb_add_string (out, "-1");
865		}
866	      else
867		{
868		  sb_add_char (out, '0');
869		}
870	    }
871	}
872      else
873	{
874	  sb_add_char (out, in->ptr[src++]);
875	}
876    }
877
878  sb_kill (&t);
879
880  while (loclist != NULL)
881    {
882      formal_entry *f;
883
884      f = loclist->next;
885      /* Setting the value to NULL effectively deletes the entry.  We
886         avoid calling hash_delete because it doesn't reclaim memory.  */
887      hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
888      sb_kill (&loclist->name);
889      sb_kill (&loclist->def);
890      sb_kill (&loclist->actual);
891      free (loclist);
892      loclist = f;
893    }
894
895  return NULL;
896}
897
898/* Assign values to the formal parameters of a macro, and expand the
899   body.  */
900
901static const char *
902macro_expand (idx, in, m, out, comment_char)
903     int idx;
904     sb *in;
905     macro_entry *m;
906     sb *out;
907     int comment_char;
908{
909  sb t;
910  formal_entry *ptr;
911  formal_entry *f;
912  int is_positional = 0;
913  int is_keyword = 0;
914  int narg = 0;
915  const char *err;
916
917  sb_new (&t);
918
919  /* Reset any old value the actuals may have.  */
920  for (f = m->formals; f; f = f->next)
921    sb_reset (&f->actual);
922  f = m->formals;
923  while (f != NULL && f->index < 0)
924    f = f->next;
925
926  if (macro_mri)
927    {
928      /* The macro may be called with an optional qualifier, which may
929         be referred to in the macro body as \0.  */
930      if (idx < in->len && in->ptr[idx] == '.')
931	{
932	  /* The Microtec assembler ignores this if followed by a white space.
933	     (Macro invocation with empty extension) */
934	  idx++;
935	  if (    idx < in->len
936		  && in->ptr[idx] != ' '
937		  && in->ptr[idx] != '\t')
938	    {
939	      formal_entry *n;
940
941	      n = (formal_entry *) xmalloc (sizeof (formal_entry));
942	      sb_new (&n->name);
943	      sb_new (&n->def);
944	      sb_new (&n->actual);
945	      n->index = QUAL_INDEX;
946
947	      n->next = m->formals;
948	      m->formals = n;
949
950	      idx = get_any_string (idx, in, &n->actual, 1, 0);
951	    }
952	}
953    }
954
955  /* Peel off the actuals and store them away in the hash tables' actuals.  */
956  idx = sb_skip_white (idx, in);
957  while (idx < in->len && in->ptr[idx] != comment_char)
958    {
959      int scan;
960
961      /* Look and see if it's a positional or keyword arg.  */
962      scan = idx;
963      while (scan < in->len
964	     && !ISSEP (in->ptr[scan])
965	     && !(macro_mri && in->ptr[scan] == '\'')
966	     && (!macro_alternate && in->ptr[scan] != '='))
967	scan++;
968      if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
969	{
970	  is_keyword = 1;
971
972	  /* It's OK to go from positional to keyword.  */
973
974	  /* This is a keyword arg, fetch the formal name and
975	     then the actual stuff.  */
976	  sb_reset (&t);
977	  idx = get_token (idx, in, &t);
978	  if (in->ptr[idx] != '=')
979	    return _("confusion in formal parameters");
980
981	  /* Lookup the formal in the macro's list.  */
982	  ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
983	  if (!ptr)
984	    return _("macro formal argument does not exist");
985	  else
986	    {
987	      /* Insert this value into the right place.  */
988	      sb_reset (&ptr->actual);
989	      idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
990	      if (ptr->actual.len > 0)
991		++narg;
992	    }
993	}
994      else
995	{
996	  /* This is a positional arg.  */
997	  is_positional = 1;
998	  if (is_keyword)
999	    return _("can't mix positional and keyword arguments");
1000
1001	  if (!f)
1002	    {
1003	      formal_entry **pf;
1004	      int c;
1005
1006	      if (!macro_mri)
1007		return _("too many positional arguments");
1008
1009	      f = (formal_entry *) xmalloc (sizeof (formal_entry));
1010	      sb_new (&f->name);
1011	      sb_new (&f->def);
1012	      sb_new (&f->actual);
1013	      f->next = NULL;
1014
1015	      c = -1;
1016	      for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
1017		if ((*pf)->index >= c)
1018		  c = (*pf)->index + 1;
1019	      if (c == -1)
1020		c = 0;
1021	      *pf = f;
1022	      f->index = c;
1023	    }
1024
1025	  sb_reset (&f->actual);
1026	  idx = get_any_string (idx, in, &f->actual, 1, 0);
1027	  if (f->actual.len > 0)
1028	    ++narg;
1029	  do
1030	    {
1031	      f = f->next;
1032	    }
1033	  while (f != NULL && f->index < 0);
1034	}
1035
1036      if (! macro_mri)
1037	idx = sb_skip_comma (idx, in);
1038      else
1039	{
1040	  if (in->ptr[idx] == ',')
1041	    ++idx;
1042	  if (ISWHITE (in->ptr[idx]))
1043	    break;
1044	}
1045    }
1046
1047  if (macro_mri)
1048    {
1049      char buffer[20];
1050
1051      sb_reset (&t);
1052      sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
1053      ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1054      sb_reset (&ptr->actual);
1055      sprintf (buffer, "%d", narg);
1056      sb_add_string (&ptr->actual, buffer);
1057    }
1058
1059  err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash,
1060			   comment_char, 1);
1061  if (err != NULL)
1062    return err;
1063
1064  /* Discard any unnamed formal arguments.  */
1065  if (macro_mri)
1066    {
1067      formal_entry **pf;
1068
1069      pf = &m->formals;
1070      while (*pf != NULL)
1071	{
1072	  if ((*pf)->name.len != 0)
1073	    pf = &(*pf)->next;
1074	  else
1075	    {
1076	      sb_kill (&(*pf)->name);
1077	      sb_kill (&(*pf)->def);
1078	      sb_kill (&(*pf)->actual);
1079	      f = (*pf)->next;
1080	      free (*pf);
1081	      *pf = f;
1082	    }
1083	}
1084    }
1085
1086  sb_kill (&t);
1087  macro_number++;
1088
1089  return NULL;
1090}
1091
1092/* Check for a macro.  If one is found, put the expansion into
1093   *EXPAND.  COMMENT_CHAR is the comment character--this is used by
1094   gasp.  Return 1 if a macro is found, 0 otherwise.  */
1095
1096int
1097check_macro (line, expand, comment_char, error, info)
1098     const char *line;
1099     sb *expand;
1100     int comment_char;
1101     const char **error;
1102     macro_entry **info;
1103{
1104  const char *s;
1105  char *copy, *cs;
1106  macro_entry *macro;
1107  sb line_sb;
1108
1109  if (! ISALPHA (*line)
1110      && *line != '_'
1111      && *line != '$'
1112      && (! macro_mri || *line != '.'))
1113    return 0;
1114
1115  s = line + 1;
1116  while (ISALNUM (*s)
1117	 || *s == '_'
1118	 || *s == '$')
1119    ++s;
1120
1121  copy = (char *) alloca (s - line + 1);
1122  memcpy (copy, line, s - line);
1123  copy[s - line] = '\0';
1124  for (cs = copy; *cs != '\0'; cs++)
1125    *cs = TOLOWER (*cs);
1126
1127  macro = (macro_entry *) hash_find (macro_hash, copy);
1128
1129  if (macro == NULL)
1130    return 0;
1131
1132  /* Wrap the line up in an sb.  */
1133  sb_new (&line_sb);
1134  while (*s != '\0' && *s != '\n' && *s != '\r')
1135    sb_add_char (&line_sb, *s++);
1136
1137  sb_new (expand);
1138  *error = macro_expand (0, &line_sb, macro, expand, comment_char);
1139
1140  sb_kill (&line_sb);
1141
1142  /* Export the macro information if requested.  */
1143  if (info)
1144    *info = macro;
1145
1146  return 1;
1147}
1148
1149/* Delete a macro.  */
1150
1151void
1152delete_macro (name)
1153     const char *name;
1154{
1155  hash_delete (macro_hash, name);
1156}
1157
1158/* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
1159   combined macro definition and execution.  This returns NULL on
1160   success, or an error message otherwise.  */
1161
1162const char *
1163expand_irp (irpc, idx, in, out, get_line, comment_char)
1164     int irpc;
1165     int idx;
1166     sb *in;
1167     sb *out;
1168     int (*get_line) PARAMS ((sb *));
1169     int comment_char;
1170{
1171  const char *mn;
1172  sb sub;
1173  formal_entry f;
1174  struct hash_control *h;
1175  const char *err;
1176
1177  if (irpc)
1178    mn = "IRPC";
1179  else
1180    mn = "IRP";
1181
1182  idx = sb_skip_white (idx, in);
1183
1184  sb_new (&sub);
1185  if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
1186    return _("unexpected end of file in irp or irpc");
1187
1188  sb_new (&f.name);
1189  sb_new (&f.def);
1190  sb_new (&f.actual);
1191
1192  idx = get_token (idx, in, &f.name);
1193  if (f.name.len == 0)
1194    return _("missing model parameter");
1195
1196  h = hash_new ();
1197  err = hash_jam (h, sb_terminate (&f.name), &f);
1198  if (err != NULL)
1199    return err;
1200
1201  f.index = 1;
1202  f.next = NULL;
1203
1204  sb_reset (out);
1205
1206  idx = sb_skip_comma (idx, in);
1207  if (idx >= in->len || in->ptr[idx] == comment_char)
1208    {
1209      /* Expand once with a null string.  */
1210      err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1211      if (err != NULL)
1212	return err;
1213    }
1214  else
1215    {
1216      if (irpc && in->ptr[idx] == '"')
1217	++idx;
1218      while (idx < in->len && in->ptr[idx] != comment_char)
1219	{
1220	  if (!irpc)
1221	    idx = get_any_string (idx, in, &f.actual, 1, 0);
1222	  else
1223	    {
1224	      if (in->ptr[idx] == '"')
1225		{
1226		  int nxt;
1227
1228		  nxt = sb_skip_white (idx + 1, in);
1229		  if (nxt >= in->len || in->ptr[nxt] == comment_char)
1230		    {
1231		      idx = nxt;
1232		      break;
1233		    }
1234		}
1235	      sb_reset (&f.actual);
1236	      sb_add_char (&f.actual, in->ptr[idx]);
1237	      ++idx;
1238	    }
1239	  err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1240	  if (err != NULL)
1241	    return err;
1242	  if (!irpc)
1243	    idx = sb_skip_comma (idx, in);
1244	  else
1245	    idx = sb_skip_white (idx, in);
1246	}
1247    }
1248
1249  hash_die (h);
1250  sb_kill (&sub);
1251
1252  return NULL;
1253}
1254