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