* as.h (alloca): Don't declare if __GNUC__. Remove an old comment.
[external/binutils.git] / gas / macro.c
1 /* macro.c - macro support for gas and gasp
2    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000
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 #include <ctype.h>
55 #ifdef HAVE_STDLIB_H
56 #include <stdlib.h>
57 #endif
58 #include "libiberty.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 ((unsigned char) 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 ((unsigned char) 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 ((unsigned char) 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           idx = (*macro_expr) (_("% operator needs absolute expression"),
382                                idx + 1,
383                                in,
384                                &val);
385           sprintf(buf, "%d", val);
386           sb_add_string (out, buf);
387         }
388       else if (in->ptr[idx] == '"'
389                || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
390                || (macro_alternate && in->ptr[idx] == '\''))
391         {
392           if (macro_alternate
393               && ! macro_strip_at
394               && expand)
395             {
396               /* Keep the quotes.  */
397               sb_add_char (out, '\"');
398
399               idx = getstring (idx, in, out);
400               sb_add_char (out, '\"');
401             }
402           else
403             {
404               idx = getstring (idx, in, out);
405             }
406         }
407       else
408         {
409           while (idx < in->len
410                  && (in->ptr[idx] == '"'
411                      || in->ptr[idx] == '\''
412                      || pretend_quoted
413                      || (in->ptr[idx] != ' '
414                          && in->ptr[idx] != '\t'
415                          && in->ptr[idx] != ','
416                          && (in->ptr[idx] != '<'
417                              || (! macro_alternate && ! macro_mri)))))
418             {
419               if (in->ptr[idx] == '"'
420                   || in->ptr[idx] == '\'')
421                 {
422                   char tchar = in->ptr[idx];
423                   sb_add_char (out, in->ptr[idx++]);
424                   while (idx < in->len
425                          && in->ptr[idx] != tchar)
426                     sb_add_char (out, in->ptr[idx++]);
427                   if (idx == in->len)
428                     return idx;
429                 }
430               sb_add_char (out, in->ptr[idx++]);
431             }
432         }
433     }
434
435   return idx;
436 }
437
438 /* Pick up the formal parameters of a macro definition.  */
439
440 static int
441 do_formals (macro, idx, in)
442      macro_entry *macro;
443      int idx;
444      sb *in;
445 {
446   formal_entry **p = &macro->formals;
447
448   macro->formal_count = 0;
449   macro->formal_hash = hash_new ();
450   while (idx < in->len)
451     {
452       formal_entry *formal;
453
454       formal = (formal_entry *) xmalloc (sizeof (formal_entry));
455
456       sb_new (&formal->name);
457       sb_new (&formal->def);
458       sb_new (&formal->actual);
459
460       idx = sb_skip_white (idx, in);
461       idx = get_token (idx, in, &formal->name);
462       if (formal->name.len == 0)
463         break;
464       idx = sb_skip_white (idx, in);
465       if (formal->name.len)
466         {
467           /* This is a formal.  */
468           if (idx < in->len && in->ptr[idx] == '=')
469             {
470               /* Got a default.  */
471               idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
472             }
473         }
474
475       /* Add to macro's hash table.  */
476       hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
477
478       formal->index = macro->formal_count;
479       idx = sb_skip_comma (idx, in);
480       macro->formal_count++;
481       *p = formal;
482       p = &formal->next;
483       *p = NULL;
484     }
485
486   if (macro_mri)
487     {
488       formal_entry *formal;
489       const char *name;
490
491       /* Add a special NARG formal, which macro_expand will set to the
492          number of arguments.  */
493       formal = (formal_entry *) xmalloc (sizeof (formal_entry));
494
495       sb_new (&formal->name);
496       sb_new (&formal->def);
497       sb_new (&formal->actual);
498
499       /* The same MRI assemblers which treat '@' characters also use
500          the name $NARG.  At least until we find an exception.  */
501       if (macro_strip_at)
502         name = "$NARG";
503       else
504         name = "NARG";
505
506       sb_add_string (&formal->name, name);
507
508       /* Add to macro's hash table.  */
509       hash_jam (macro->formal_hash, name, formal);
510
511       formal->index = NARG_INDEX;
512       *p = formal;
513       formal->next = NULL;
514     }
515
516   return idx;
517 }
518
519 /* Define a new macro.  Returns NULL on success, otherwise returns an
520    error message.  If NAMEP is not NULL, *NAMEP is set to the name of
521    the macro which was defined.  */
522
523 const char *
524 define_macro (idx, in, label, get_line, namep)
525      int idx;
526      sb *in;
527      sb *label;
528      int (*get_line) PARAMS ((sb *));
529      const char **namep;
530 {
531   macro_entry *macro;
532   sb name;
533   const char *namestr;
534
535   macro = (macro_entry *) xmalloc (sizeof (macro_entry));
536   sb_new (&macro->sub);
537   sb_new (&name);
538
539   macro->formal_count = 0;
540   macro->formals = 0;
541
542   idx = sb_skip_white (idx, in);
543   if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
544     return _("unexpected end of file in macro definition");
545   if (label != NULL && label->len != 0)
546     {
547       sb_add_sb (&name, label);
548       if (idx < in->len && in->ptr[idx] == '(')
549         {
550           /* It's the label: MACRO (formals,...)  sort  */
551           idx = do_formals (macro, idx + 1, in);
552           if (in->ptr[idx] != ')')
553             return _("missing ) after formals");
554         }
555       else
556         {
557           /* It's the label: MACRO formals,...  sort  */
558           idx = do_formals (macro, idx, in);
559         }
560     }
561   else
562     {
563       idx = get_token (idx, in, &name);
564       idx = sb_skip_comma (idx, in);
565       idx = do_formals (macro, idx, in);
566     }
567
568   /* And stick it in the macro hash table.  */
569   for (idx = 0; idx < name.len; idx++)
570     if (isupper ((unsigned char) name.ptr[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
730                    && isalnum ((unsigned char) in->ptr[src]))
731             {
732               int ind;
733               formal_entry *f;
734
735               if (isdigit ((unsigned char) in->ptr[src]))
736                 ind = in->ptr[src] - '0';
737               else if (isupper ((unsigned char) in->ptr[src]))
738                 ind = in->ptr[src] - 'A' + 10;
739               else
740                 ind = in->ptr[src] - 'a' + 10;
741               ++src;
742               for (f = formals; f != NULL; f = f->next)
743                 {
744                   if (f->index == ind - 1)
745                     {
746                       if (f->actual.len != 0)
747                         sb_add_sb (out, &f->actual);
748                       else
749                         sb_add_sb (out, &f->def);
750                       break;
751                     }
752                 }
753             }
754           else
755             {
756               sb_reset (&t);
757               src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
758             }
759         }
760       else if ((macro_alternate || macro_mri)
761                && (isalpha ((unsigned char) in->ptr[src])
762                    || in->ptr[src] == '_'
763                    || in->ptr[src] == '$')
764                && (! inquote
765                    || ! macro_strip_at
766                    || (src > 0 && in->ptr[src - 1] == '@')))
767         {
768           if (! locals
769               || src + 5 >= in->len
770               || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
771               || ! ISWHITE (in->ptr[src + 5]))
772             {
773               sb_reset (&t);
774               src = sub_actual (src, in, &t, formal_hash,
775                                 (macro_strip_at && inquote) ? '@' : '\'',
776                                 out, 1);
777             }
778           else
779             {
780               formal_entry *f;
781
782               src = sb_skip_white (src + 5, in);
783               while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
784                 {
785                   static int loccnt;
786                   char buf[20];
787                   const char *err;
788
789                   f = (formal_entry *) xmalloc (sizeof (formal_entry));
790                   sb_new (&f->name);
791                   sb_new (&f->def);
792                   sb_new (&f->actual);
793                   f->index = LOCAL_INDEX;
794                   f->next = loclist;
795                   loclist = f;
796
797                   src = get_token (src, in, &f->name);
798                   ++loccnt;
799                   sprintf (buf, "LL%04x", loccnt);
800                   sb_add_string (&f->actual, buf);
801
802                   err = hash_jam (formal_hash, sb_terminate (&f->name), f);
803                   if (err != NULL)
804                     return err;
805
806                   src = sb_skip_comma (src, in);
807                 }
808             }
809         }
810       else if (comment_char != '\0'
811                && in->ptr[src] == comment_char
812                && src + 1 < in->len
813                && in->ptr[src + 1] == comment_char
814                && !inquote)
815         {
816           /* Two comment chars in a row cause the rest of the line to
817              be dropped.  */
818           while (src < in->len && in->ptr[src] != '\n')
819             src++;
820         }
821       else if (in->ptr[src] == '"'
822                || (macro_mri && in->ptr[src] == '\''))
823         {
824           inquote = !inquote;
825           sb_add_char (out, in->ptr[src++]);
826         }
827       else if (in->ptr[src] == '@' && macro_strip_at)
828         {
829           ++src;
830           if (src < in->len
831               && in->ptr[src] == '@')
832             {
833               sb_add_char (out, '@');
834               ++src;
835             }
836         }
837       else if (macro_mri
838                && in->ptr[src] == '='
839                && src + 1 < in->len
840                && in->ptr[src + 1] == '=')
841         {
842           formal_entry *ptr;
843
844           sb_reset (&t);
845           src = get_token (src + 2, in, &t);
846           ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
847           if (ptr == NULL)
848             {
849               /* FIXME: We should really return a warning string here,
850                  but we can't, because the == might be in the MRI
851                  comment field, and, since the nature of the MRI
852                  comment field depends upon the exact instruction
853                  being used, we don't have enough information here to
854                  figure out whether it is or not.  Instead, we leave
855                  the == in place, which should cause a syntax error if
856                  it is not in a comment.  */
857               sb_add_char (out, '=');
858               sb_add_char (out, '=');
859               sb_add_sb (out, &t);
860             }
861           else
862             {
863               if (ptr->actual.len)
864                 {
865                   sb_add_string (out, "-1");
866                 }
867               else
868                 {
869                   sb_add_char (out, '0');
870                 }
871             }
872         }
873       else
874         {
875           sb_add_char (out, in->ptr[src++]);
876         }
877     }
878
879   sb_kill (&t);
880
881   while (loclist != NULL)
882     {
883       formal_entry *f;
884
885       f = loclist->next;
886       /* Setting the value to NULL effectively deletes the entry.  We
887          avoid calling hash_delete because it doesn't reclaim memory.  */
888       hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
889       sb_kill (&loclist->name);
890       sb_kill (&loclist->def);
891       sb_kill (&loclist->actual);
892       free (loclist);
893       loclist = f;
894     }
895
896   return NULL;
897 }
898
899 /* Assign values to the formal parameters of a macro, and expand the
900    body.  */
901
902 static const char *
903 macro_expand (idx, in, m, out, comment_char)
904      int idx;
905      sb *in;
906      macro_entry *m;
907      sb *out;
908      int comment_char;
909 {
910   sb t;
911   formal_entry *ptr;
912   formal_entry *f;
913   int is_positional = 0;
914   int is_keyword = 0;
915   int narg = 0;
916   const char *err;
917
918   sb_new (&t);
919
920   /* Reset any old value the actuals may have.  */
921   for (f = m->formals; f; f = f->next)
922     sb_reset (&f->actual);
923   f = m->formals;
924   while (f != NULL && f->index < 0)
925     f = f->next;
926
927   if (macro_mri)
928     {
929       /* The macro may be called with an optional qualifier, which may
930          be referred to in the macro body as \0.  */
931       if (idx < in->len && in->ptr[idx] == '.')
932         {
933           /* The Microtec assembler ignores this if followed by a white space.
934                    (Macro invocation with empty extension) */
935           idx++;
936           if (    idx < in->len
937                     && in->ptr[idx] != ' '
938                && in->ptr[idx] != '\t')
939             {
940               formal_entry *n;
941
942               n = (formal_entry *) xmalloc (sizeof (formal_entry));
943               sb_new (&n->name);
944               sb_new (&n->def);
945               sb_new (&n->actual);
946               n->index = QUAL_INDEX;
947
948               n->next = m->formals;
949               m->formals = n;
950
951               idx = get_any_string (idx, in, &n->actual, 1, 0);
952             }
953         }
954   }
955
956   /* Peel off the actuals and store them away in the hash tables' actuals.  */
957   idx = sb_skip_white (idx, in);
958   while (idx < in->len && in->ptr[idx] != comment_char)
959     {
960       int scan;
961
962       /* Look and see if it's a positional or keyword arg.  */
963       scan = idx;
964       while (scan < in->len
965              && !ISSEP (in->ptr[scan])
966              && !(macro_mri && in->ptr[scan] == '\'')
967              && (!macro_alternate && in->ptr[scan] != '='))
968         scan++;
969       if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
970         {
971           is_keyword = 1;
972
973           /* It's OK to go from positional to keyword.  */
974
975           /* This is a keyword arg, fetch the formal name and
976              then the actual stuff.  */
977           sb_reset (&t);
978           idx = get_token (idx, in, &t);
979           if (in->ptr[idx] != '=')
980             return _("confusion in formal parameters");
981
982           /* Lookup the formal in the macro's list.  */
983           ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
984           if (!ptr)
985             return _("macro formal argument does not exist");
986           else
987             {
988               /* Insert this value into the right place.  */
989               sb_reset (&ptr->actual);
990               idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
991               if (ptr->actual.len > 0)
992                 ++narg;
993             }
994         }
995       else
996         {
997           /* This is a positional arg.  */
998           is_positional = 1;
999           if (is_keyword)
1000             return _("can't mix positional and keyword arguments");
1001
1002           if (!f)
1003             {
1004               formal_entry **pf;
1005               int c;
1006
1007               if (!macro_mri)
1008                 return _("too many positional arguments");
1009
1010               f = (formal_entry *) xmalloc (sizeof (formal_entry));
1011               sb_new (&f->name);
1012               sb_new (&f->def);
1013               sb_new (&f->actual);
1014               f->next = NULL;
1015
1016               c = -1;
1017               for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
1018                 if ((*pf)->index >= c)
1019                   c = (*pf)->index + 1;
1020               if (c == -1)
1021                 c = 0;
1022               *pf = f;
1023               f->index = c;
1024             }
1025
1026           sb_reset (&f->actual);
1027           idx = get_any_string (idx, in, &f->actual, 1, 0);
1028           if (f->actual.len > 0)
1029             ++narg;
1030           do
1031             {
1032               f = f->next;
1033             }
1034           while (f != NULL && f->index < 0);
1035         }
1036
1037       if (! macro_mri)
1038         idx = sb_skip_comma (idx, in);
1039       else
1040         {
1041           if (in->ptr[idx] == ',')
1042             ++idx;
1043           if (ISWHITE (in->ptr[idx]))
1044             break;
1045         }
1046     }
1047
1048   if (macro_mri)
1049     {
1050       char buffer[20];
1051
1052       sb_reset (&t);
1053       sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
1054       ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1055       sb_reset (&ptr->actual);
1056       sprintf (buffer, "%d", narg);
1057       sb_add_string (&ptr->actual, buffer);
1058     }
1059
1060   err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash,
1061                            comment_char, 1);
1062   if (err != NULL)
1063     return err;
1064
1065   /* Discard any unnamed formal arguments.  */
1066   if (macro_mri)
1067     {
1068       formal_entry **pf;
1069
1070       pf = &m->formals;
1071       while (*pf != NULL)
1072         {
1073           if ((*pf)->name.len != 0)
1074             pf = &(*pf)->next;
1075           else
1076             {
1077               sb_kill (&(*pf)->name);
1078               sb_kill (&(*pf)->def);
1079               sb_kill (&(*pf)->actual);
1080               f = (*pf)->next;
1081               free (*pf);
1082               *pf = f;
1083             }
1084         }
1085     }
1086
1087   sb_kill (&t);
1088   macro_number++;
1089
1090   return NULL;
1091 }
1092
1093 /* Check for a macro.  If one is found, put the expansion into
1094    *EXPAND.  COMMENT_CHAR is the comment character--this is used by
1095    gasp.  Return 1 if a macro is found, 0 otherwise.  */
1096
1097 int
1098 check_macro (line, expand, comment_char, error, info)
1099      const char *line;
1100      sb *expand;
1101      int comment_char;
1102      const char **error;
1103      macro_entry **info;
1104 {
1105   const char *s;
1106   char *copy, *cs;
1107   macro_entry *macro;
1108   sb line_sb;
1109
1110   if (! isalpha ((unsigned char) *line)
1111       && *line != '_'
1112       && *line != '$'
1113       && (! macro_mri || *line != '.'))
1114     return 0;
1115
1116   s = line + 1;
1117   while (isalnum ((unsigned char) *s)
1118          || *s == '_'
1119          || *s == '$')
1120     ++s;
1121
1122   copy = (char *) alloca (s - line + 1);
1123   memcpy (copy, line, s - line);
1124   copy[s - line] = '\0';
1125   for (cs = copy; *cs != '\0'; cs++)
1126     if (isupper ((unsigned char) *cs))
1127       *cs = tolower (*cs);
1128
1129   macro = (macro_entry *) hash_find (macro_hash, copy);
1130
1131   if (macro == NULL)
1132     return 0;
1133
1134   /* Wrap the line up in an sb.  */
1135   sb_new (&line_sb);
1136   while (*s != '\0' && *s != '\n' && *s != '\r')
1137     sb_add_char (&line_sb, *s++);
1138
1139   sb_new (expand);
1140   *error = macro_expand (0, &line_sb, macro, expand, comment_char);
1141
1142   sb_kill (&line_sb);
1143
1144   /* Export the macro information if requested.  */
1145   if (info)
1146     *info = macro;
1147
1148   return 1;
1149 }
1150
1151 /* Delete a macro.  */
1152
1153 void
1154 delete_macro (name)
1155      const char *name;
1156 {
1157   hash_delete (macro_hash, name);
1158 }
1159
1160 /* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
1161    combined macro definition and execution.  This returns NULL on
1162    success, or an error message otherwise.  */
1163
1164 const char *
1165 expand_irp (irpc, idx, in, out, get_line, comment_char)
1166      int irpc;
1167      int idx;
1168      sb *in;
1169      sb *out;
1170      int (*get_line) PARAMS ((sb *));
1171      int comment_char;
1172 {
1173   const char *mn;
1174   sb sub;
1175   formal_entry f;
1176   struct hash_control *h;
1177   const char *err;
1178
1179   if (irpc)
1180     mn = "IRPC";
1181   else
1182     mn = "IRP";
1183
1184   idx = sb_skip_white (idx, in);
1185
1186   sb_new (&sub);
1187   if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
1188     return _("unexpected end of file in irp or irpc");
1189
1190   sb_new (&f.name);
1191   sb_new (&f.def);
1192   sb_new (&f.actual);
1193
1194   idx = get_token (idx, in, &f.name);
1195   if (f.name.len == 0)
1196     return _("missing model parameter");
1197
1198   h = hash_new ();
1199   err = hash_jam (h, sb_terminate (&f.name), &f);
1200   if (err != NULL)
1201     return err;
1202
1203   f.index = 1;
1204   f.next = NULL;
1205
1206   sb_reset (out);
1207
1208   idx = sb_skip_comma (idx, in);
1209   if (idx >= in->len || in->ptr[idx] == comment_char)
1210     {
1211       /* Expand once with a null string.  */
1212       err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1213       if (err != NULL)
1214         return err;
1215     }
1216   else
1217     {
1218       if (irpc && in->ptr[idx] == '"')
1219         ++idx;
1220       while (idx < in->len && in->ptr[idx] != comment_char)
1221         {
1222           if (!irpc)
1223             idx = get_any_string (idx, in, &f.actual, 1, 0);
1224           else
1225             {
1226               if (in->ptr[idx] == '"')
1227                 {
1228                   int nxt;
1229
1230                   nxt = sb_skip_white (idx + 1, in);
1231                   if (nxt >= in->len || in->ptr[nxt] == comment_char)
1232                     {
1233                       idx = nxt;
1234                       break;
1235                     }
1236                 }
1237               sb_reset (&f.actual);
1238               sb_add_char (&f.actual, in->ptr[idx]);
1239               ++idx;
1240             }
1241           err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1242           if (err != NULL)
1243             return err;
1244           if (!irpc)
1245             idx = sb_skip_comma (idx, in);
1246           else
1247             idx = sb_skip_white (idx, in);
1248         }
1249     }
1250
1251   hash_die (h);
1252   sb_kill (&sub);
1253
1254   return NULL;
1255 }