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