OSDN Git Service

Locale changes from Bruno Haible <haible@clisp.cons.org>.
[pf3gnuchains/pf3gnuchains3x.git] / gas / macro.c
1 /* macro.c - macro support for gas and gasp
2    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
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           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     name.ptr[idx] = TOLOWER (name.ptr[idx]);
571   namestr = sb_terminate (&name);
572   hash_jam (macro_hash, namestr, (PTR) macro);
573
574   macro_defined = 1;
575
576   if (namep != NULL)
577     *namep = namestr;
578
579   return NULL;
580 }
581
582 /* Scan a token, and then skip KIND.  */
583
584 static int
585 get_apost_token (idx, in, name, kind)
586      int idx;
587      sb *in;
588      sb *name;
589      int kind;
590 {
591   idx = get_token (idx, in, name);
592   if (idx < in->len
593       && in->ptr[idx] == kind
594       && (! macro_mri || macro_strip_at)
595       && (! macro_strip_at || kind == '@'))
596     idx++;
597   return idx;
598 }
599
600 /* Substitute the actual value for a formal parameter.  */
601
602 static int
603 sub_actual (start, in, t, formal_hash, kind, out, copyifnotthere)
604      int start;
605      sb *in;
606      sb *t;
607      struct hash_control *formal_hash;
608      int kind;
609      sb *out;
610      int copyifnotthere;
611 {
612   int src;
613   formal_entry *ptr;
614
615   src = get_apost_token (start, in, t, kind);
616   /* See if it's in the macro's hash table, unless this is
617      macro_strip_at and kind is '@' and the token did not end in '@'.  */
618   if (macro_strip_at
619       && kind == '@'
620       && (src == start || in->ptr[src - 1] != '@'))
621     ptr = NULL;
622   else
623     ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
624   if (ptr)
625     {
626       if (ptr->actual.len)
627         {
628           sb_add_sb (out, &ptr->actual);
629         }
630       else
631         {
632           sb_add_sb (out, &ptr->def);
633         }
634     }
635   else if (kind == '&')
636     {
637       /* Doing this permits people to use & in macro bodies.  */
638       sb_add_char (out, '&');
639     }
640   else if (copyifnotthere)
641     {
642       sb_add_sb (out, t);
643     }
644   else
645     {
646       sb_add_char (out, '\\');
647       sb_add_sb (out, t);
648     }
649   return src;
650 }
651
652 /* Expand the body of a macro.  */
653
654 static const char *
655 macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
656      sb *in;
657      sb *out;
658      formal_entry *formals;
659      struct hash_control *formal_hash;
660      int comment_char;
661      int locals;
662 {
663   sb t;
664   int src = 0;
665   int inquote = 0;
666   formal_entry *loclist = NULL;
667
668   sb_new (&t);
669
670   while (src < in->len)
671     {
672       if (in->ptr[src] == '&')
673         {
674           sb_reset (&t);
675           if (macro_mri)
676             {
677               if (src + 1 < in->len && in->ptr[src + 1] == '&')
678                 src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
679               else
680                 sb_add_char (out, in->ptr[src++]);
681             }
682           else
683             {
684               /* FIXME: Why do we do this?  */
685               src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
686             }
687         }
688       else if (in->ptr[src] == '\\')
689         {
690           src++;
691           if (in->ptr[src] == comment_char && comment_char != '\0')
692             {
693               /* This is a comment, just drop the rest of the line.  */
694               while (src < in->len
695                      && in->ptr[src] != '\n')
696                 src++;
697             }
698           else if (in->ptr[src] == '(')
699             {
700               /* Sub in till the next ')' literally.  */
701               src++;
702               while (src < in->len && in->ptr[src] != ')')
703                 {
704                   sb_add_char (out, in->ptr[src++]);
705                 }
706               if (in->ptr[src] == ')')
707                 src++;
708               else
709                 return _("missplaced )");
710             }
711           else if (in->ptr[src] == '@')
712             {
713               /* Sub in the macro invocation number.  */
714
715               char buffer[10];
716               src++;
717               sprintf (buffer, "%d", macro_number);
718               sb_add_string (out, buffer);
719             }
720           else if (in->ptr[src] == '&')
721             {
722               /* This is a preprocessor variable name, we don't do them
723                  here.  */
724               sb_add_char (out, '\\');
725               sb_add_char (out, '&');
726               src++;
727             }
728           else if (macro_mri && ISALNUM (in->ptr[src]))
729             {
730               int ind;
731               formal_entry *f;
732
733               if (ISDIGIT (in->ptr[src]))
734                 ind = in->ptr[src] - '0';
735               else if (ISUPPER (in->ptr[src]))
736                 ind = in->ptr[src] - 'A' + 10;
737               else
738                 ind = in->ptr[src] - 'a' + 10;
739               ++src;
740               for (f = formals; f != NULL; f = f->next)
741                 {
742                   if (f->index == ind - 1)
743                     {
744                       if (f->actual.len != 0)
745                         sb_add_sb (out, &f->actual);
746                       else
747                         sb_add_sb (out, &f->def);
748                       break;
749                     }
750                 }
751             }
752           else
753             {
754               sb_reset (&t);
755               src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
756             }
757         }
758       else if ((macro_alternate || macro_mri)
759                && (ISALPHA (in->ptr[src])
760                    || in->ptr[src] == '_'
761                    || in->ptr[src] == '$')
762                && (! inquote
763                    || ! macro_strip_at
764                    || (src > 0 && in->ptr[src - 1] == '@')))
765         {
766           if (! locals
767               || src + 5 >= in->len
768               || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
769               || ! ISWHITE (in->ptr[src + 5]))
770             {
771               sb_reset (&t);
772               src = sub_actual (src, in, &t, formal_hash,
773                                 (macro_strip_at && inquote) ? '@' : '\'',
774                                 out, 1);
775             }
776           else
777             {
778               formal_entry *f;
779
780               src = sb_skip_white (src + 5, in);
781               while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
782                 {
783                   static int loccnt;
784                   char buf[20];
785                   const char *err;
786
787                   f = (formal_entry *) xmalloc (sizeof (formal_entry));
788                   sb_new (&f->name);
789                   sb_new (&f->def);
790                   sb_new (&f->actual);
791                   f->index = LOCAL_INDEX;
792                   f->next = loclist;
793                   loclist = f;
794
795                   src = get_token (src, in, &f->name);
796                   ++loccnt;
797                   sprintf (buf, "LL%04x", loccnt);
798                   sb_add_string (&f->actual, buf);
799
800                   err = hash_jam (formal_hash, sb_terminate (&f->name), f);
801                   if (err != NULL)
802                     return err;
803
804                   src = sb_skip_comma (src, in);
805                 }
806             }
807         }
808       else if (comment_char != '\0'
809                && in->ptr[src] == comment_char
810                && src + 1 < in->len
811                && in->ptr[src + 1] == comment_char
812                && !inquote)
813         {
814           /* Two comment chars in a row cause the rest of the line to
815              be dropped.  */
816           while (src < in->len && in->ptr[src] != '\n')
817             src++;
818         }
819       else if (in->ptr[src] == '"'
820                || (macro_mri && in->ptr[src] == '\''))
821         {
822           inquote = !inquote;
823           sb_add_char (out, in->ptr[src++]);
824         }
825       else if (in->ptr[src] == '@' && macro_strip_at)
826         {
827           ++src;
828           if (src < in->len
829               && in->ptr[src] == '@')
830             {
831               sb_add_char (out, '@');
832               ++src;
833             }
834         }
835       else if (macro_mri
836                && in->ptr[src] == '='
837                && src + 1 < in->len
838                && in->ptr[src + 1] == '=')
839         {
840           formal_entry *ptr;
841
842           sb_reset (&t);
843           src = get_token (src + 2, in, &t);
844           ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
845           if (ptr == NULL)
846             {
847               /* FIXME: We should really return a warning string here,
848                  but we can't, because the == might be in the MRI
849                  comment field, and, since the nature of the MRI
850                  comment field depends upon the exact instruction
851                  being used, we don't have enough information here to
852                  figure out whether it is or not.  Instead, we leave
853                  the == in place, which should cause a syntax error if
854                  it is not in a comment.  */
855               sb_add_char (out, '=');
856               sb_add_char (out, '=');
857               sb_add_sb (out, &t);
858             }
859           else
860             {
861               if (ptr->actual.len)
862                 {
863                   sb_add_string (out, "-1");
864                 }
865               else
866                 {
867                   sb_add_char (out, '0');
868                 }
869             }
870         }
871       else
872         {
873           sb_add_char (out, in->ptr[src++]);
874         }
875     }
876
877   sb_kill (&t);
878
879   while (loclist != NULL)
880     {
881       formal_entry *f;
882
883       f = loclist->next;
884       /* Setting the value to NULL effectively deletes the entry.  We
885          avoid calling hash_delete because it doesn't reclaim memory.  */
886       hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
887       sb_kill (&loclist->name);
888       sb_kill (&loclist->def);
889       sb_kill (&loclist->actual);
890       free (loclist);
891       loclist = f;
892     }
893
894   return NULL;
895 }
896
897 /* Assign values to the formal parameters of a macro, and expand the
898    body.  */
899
900 static const char *
901 macro_expand (idx, in, m, out, comment_char)
902      int idx;
903      sb *in;
904      macro_entry *m;
905      sb *out;
906      int comment_char;
907 {
908   sb t;
909   formal_entry *ptr;
910   formal_entry *f;
911   int is_positional = 0;
912   int is_keyword = 0;
913   int narg = 0;
914   const char *err;
915
916   sb_new (&t);
917
918   /* Reset any old value the actuals may have.  */
919   for (f = m->formals; f; f = f->next)
920     sb_reset (&f->actual);
921   f = m->formals;
922   while (f != NULL && f->index < 0)
923     f = f->next;
924
925   if (macro_mri)
926     {
927       /* The macro may be called with an optional qualifier, which may
928          be referred to in the macro body as \0.  */
929       if (idx < in->len && in->ptr[idx] == '.')
930         {
931           /* The Microtec assembler ignores this if followed by a white space.
932                    (Macro invocation with empty extension) */
933           idx++;
934           if (    idx < in->len
935                     && in->ptr[idx] != ' '
936                && in->ptr[idx] != '\t')
937             {
938               formal_entry *n;
939
940               n = (formal_entry *) xmalloc (sizeof (formal_entry));
941               sb_new (&n->name);
942               sb_new (&n->def);
943               sb_new (&n->actual);
944               n->index = QUAL_INDEX;
945
946               n->next = m->formals;
947               m->formals = n;
948
949               idx = get_any_string (idx, in, &n->actual, 1, 0);
950             }
951         }
952   }
953
954   /* Peel off the actuals and store them away in the hash tables' actuals.  */
955   idx = sb_skip_white (idx, in);
956   while (idx < in->len && in->ptr[idx] != comment_char)
957     {
958       int scan;
959
960       /* Look and see if it's a positional or keyword arg.  */
961       scan = idx;
962       while (scan < in->len
963              && !ISSEP (in->ptr[scan])
964              && !(macro_mri && in->ptr[scan] == '\'')
965              && (!macro_alternate && in->ptr[scan] != '='))
966         scan++;
967       if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
968         {
969           is_keyword = 1;
970
971           /* It's OK to go from positional to keyword.  */
972
973           /* This is a keyword arg, fetch the formal name and
974              then the actual stuff.  */
975           sb_reset (&t);
976           idx = get_token (idx, in, &t);
977           if (in->ptr[idx] != '=')
978             return _("confusion in formal parameters");
979
980           /* Lookup the formal in the macro's list.  */
981           ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
982           if (!ptr)
983             return _("macro formal argument does not exist");
984           else
985             {
986               /* Insert this value into the right place.  */
987               sb_reset (&ptr->actual);
988               idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
989               if (ptr->actual.len > 0)
990                 ++narg;
991             }
992         }
993       else
994         {
995           /* This is a positional arg.  */
996           is_positional = 1;
997           if (is_keyword)
998             return _("can't mix positional and keyword arguments");
999
1000           if (!f)
1001             {
1002               formal_entry **pf;
1003               int c;
1004
1005               if (!macro_mri)
1006                 return _("too many positional arguments");
1007
1008               f = (formal_entry *) xmalloc (sizeof (formal_entry));
1009               sb_new (&f->name);
1010               sb_new (&f->def);
1011               sb_new (&f->actual);
1012               f->next = NULL;
1013
1014               c = -1;
1015               for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
1016                 if ((*pf)->index >= c)
1017                   c = (*pf)->index + 1;
1018               if (c == -1)
1019                 c = 0;
1020               *pf = f;
1021               f->index = c;
1022             }
1023
1024           sb_reset (&f->actual);
1025           idx = get_any_string (idx, in, &f->actual, 1, 0);
1026           if (f->actual.len > 0)
1027             ++narg;
1028           do
1029             {
1030               f = f->next;
1031             }
1032           while (f != NULL && f->index < 0);
1033         }
1034
1035       if (! macro_mri)
1036         idx = sb_skip_comma (idx, in);
1037       else
1038         {
1039           if (in->ptr[idx] == ',')
1040             ++idx;
1041           if (ISWHITE (in->ptr[idx]))
1042             break;
1043         }
1044     }
1045
1046   if (macro_mri)
1047     {
1048       char buffer[20];
1049
1050       sb_reset (&t);
1051       sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
1052       ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1053       sb_reset (&ptr->actual);
1054       sprintf (buffer, "%d", narg);
1055       sb_add_string (&ptr->actual, buffer);
1056     }
1057
1058   err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash,
1059                            comment_char, 1);
1060   if (err != NULL)
1061     return err;
1062
1063   /* Discard any unnamed formal arguments.  */
1064   if (macro_mri)
1065     {
1066       formal_entry **pf;
1067
1068       pf = &m->formals;
1069       while (*pf != NULL)
1070         {
1071           if ((*pf)->name.len != 0)
1072             pf = &(*pf)->next;
1073           else
1074             {
1075               sb_kill (&(*pf)->name);
1076               sb_kill (&(*pf)->def);
1077               sb_kill (&(*pf)->actual);
1078               f = (*pf)->next;
1079               free (*pf);
1080               *pf = f;
1081             }
1082         }
1083     }
1084
1085   sb_kill (&t);
1086   macro_number++;
1087
1088   return NULL;
1089 }
1090
1091 /* Check for a macro.  If one is found, put the expansion into
1092    *EXPAND.  COMMENT_CHAR is the comment character--this is used by
1093    gasp.  Return 1 if a macro is found, 0 otherwise.  */
1094
1095 int
1096 check_macro (line, expand, comment_char, error, info)
1097      const char *line;
1098      sb *expand;
1099      int comment_char;
1100      const char **error;
1101      macro_entry **info;
1102 {
1103   const char *s;
1104   char *copy, *cs;
1105   macro_entry *macro;
1106   sb line_sb;
1107
1108   if (! ISALPHA (*line)
1109       && *line != '_'
1110       && *line != '$'
1111       && (! macro_mri || *line != '.'))
1112     return 0;
1113
1114   s = line + 1;
1115   while (ISALNUM (*s)
1116          || *s == '_'
1117          || *s == '$')
1118     ++s;
1119
1120   copy = (char *) alloca (s - line + 1);
1121   memcpy (copy, line, s - line);
1122   copy[s - line] = '\0';
1123   for (cs = copy; *cs != '\0'; cs++)
1124     *cs = TOLOWER (*cs);
1125
1126   macro = (macro_entry *) hash_find (macro_hash, copy);
1127
1128   if (macro == NULL)
1129     return 0;
1130
1131   /* Wrap the line up in an sb.  */
1132   sb_new (&line_sb);
1133   while (*s != '\0' && *s != '\n' && *s != '\r')
1134     sb_add_char (&line_sb, *s++);
1135
1136   sb_new (expand);
1137   *error = macro_expand (0, &line_sb, macro, expand, comment_char);
1138
1139   sb_kill (&line_sb);
1140
1141   /* Export the macro information if requested.  */
1142   if (info)
1143     *info = macro;
1144
1145   return 1;
1146 }
1147
1148 /* Delete a macro.  */
1149
1150 void
1151 delete_macro (name)
1152      const char *name;
1153 {
1154   hash_delete (macro_hash, name);
1155 }
1156
1157 /* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
1158    combined macro definition and execution.  This returns NULL on
1159    success, or an error message otherwise.  */
1160
1161 const char *
1162 expand_irp (irpc, idx, in, out, get_line, comment_char)
1163      int irpc;
1164      int idx;
1165      sb *in;
1166      sb *out;
1167      int (*get_line) PARAMS ((sb *));
1168      int comment_char;
1169 {
1170   const char *mn;
1171   sb sub;
1172   formal_entry f;
1173   struct hash_control *h;
1174   const char *err;
1175
1176   if (irpc)
1177     mn = "IRPC";
1178   else
1179     mn = "IRP";
1180
1181   idx = sb_skip_white (idx, in);
1182
1183   sb_new (&sub);
1184   if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
1185     return _("unexpected end of file in irp or irpc");
1186
1187   sb_new (&f.name);
1188   sb_new (&f.def);
1189   sb_new (&f.actual);
1190
1191   idx = get_token (idx, in, &f.name);
1192   if (f.name.len == 0)
1193     return _("missing model parameter");
1194
1195   h = hash_new ();
1196   err = hash_jam (h, sb_terminate (&f.name), &f);
1197   if (err != NULL)
1198     return err;
1199
1200   f.index = 1;
1201   f.next = NULL;
1202
1203   sb_reset (out);
1204
1205   idx = sb_skip_comma (idx, in);
1206   if (idx >= in->len || in->ptr[idx] == comment_char)
1207     {
1208       /* Expand once with a null string.  */
1209       err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1210       if (err != NULL)
1211         return err;
1212     }
1213   else
1214     {
1215       if (irpc && in->ptr[idx] == '"')
1216         ++idx;
1217       while (idx < in->len && in->ptr[idx] != comment_char)
1218         {
1219           if (!irpc)
1220             idx = get_any_string (idx, in, &f.actual, 1, 0);
1221           else
1222             {
1223               if (in->ptr[idx] == '"')
1224                 {
1225                   int nxt;
1226
1227                   nxt = sb_skip_white (idx + 1, in);
1228                   if (nxt >= in->len || in->ptr[nxt] == comment_char)
1229                     {
1230                       idx = nxt;
1231                       break;
1232                     }
1233                 }
1234               sb_reset (&f.actual);
1235               sb_add_char (&f.actual, in->ptr[idx]);
1236               ++idx;
1237             }
1238           err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1239           if (err != NULL)
1240             return err;
1241           if (!irpc)
1242             idx = sb_skip_comma (idx, in);
1243           else
1244             idx = sb_skip_white (idx, in);
1245         }
1246     }
1247
1248   hash_die (h);
1249   sb_kill (&sub);
1250
1251   return NULL;
1252 }