This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / gas / macro.c
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)
39 extern char *alloca ();
40 #    else
41 extern 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
70 static int get_token PARAMS ((int, sb *, sb *));
71 static int getstring PARAMS ((int, sb *, sb *));
72 static int get_any_string PARAMS ((int, sb *, sb *, int, int));
73 static int do_formals PARAMS ((macro_entry *, int, sb *));
74 static int get_apost_token PARAMS ((int, sb *, sb *, int));
75 static int sub_actual
76   PARAMS ((int, sb *, sb *, struct hash_control *, int, sb *, int));
77 static const char *macro_expand_body
78   PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int, int));
79 static 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
96 static struct hash_control *macro_hash;
97
98 /* Whether any macros have been defined.  */
99
100 int macro_defined;
101
102 /* Whether we are in GASP alternate mode.  */
103
104 static int macro_alternate;
105
106 /* Whether we are in MRI mode.  */
107
108 static int macro_mri;
109
110 /* Whether we should strip '@' characters.  */
111
112 static int macro_strip_at;
113
114 /* Function to use to parse an expression.  */
115
116 static int (*macro_expr) PARAMS ((const char *, int, sb *, int *));
117
118 /* Number of macro expansions that have been done.  */
119
120 static int macro_number;
121
122 /* Initialize macro processing.  */
123
124 void
125 macro_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
141 void
142 macro_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
154 int
155 buffer_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
237 static int
238 get_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
265 static int
266 getstring (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
356 static int
357 get_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
441 static int
442 do_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
524 const char *
525 define_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
585 static int
586 get_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
603 static int
604 sub_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
655 static const char *
656 macro_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
901 static const char *
902 macro_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
1096 int
1097 check_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
1151 void
1152 delete_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
1162 const char *
1163 expand_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 }