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