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