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