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