2000-05-29 Philip Blundell <philb@gnu.org>
[binutils.git] / gas / macro.c
blobdf01bc5ca0c43d5015ff1a8ffffa24227aea294a
1 /* macro.c - macro support for gas and gasp
2 Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
4 Written by Steve and Judy Chamberlain of Cygnus Support,
5 sac@cygnus.com
7 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
24 #include "config.h"
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
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"
68 #include "asintl.h"
70 /* The routines in this file handle macro definition and expansion.
71 They are called by both gasp and gas. */
73 /* Internal functions. */
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));
86 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
88 #define ISSEP(x) \
89 ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
90 || (x) == ')' || (x) == '(' \
91 || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
93 #define ISBASE(x) \
94 ((x) == 'b' || (x) == 'B' \
95 || (x) == 'q' || (x) == 'Q' \
96 || (x) == 'h' || (x) == 'H' \
97 || (x) == 'd' || (x) == 'D')
99 /* The macro hash table. */
101 static struct hash_control *macro_hash;
103 /* Whether any macros have been defined. */
105 int macro_defined;
107 /* Whether we are in GASP alternate mode. */
109 static int macro_alternate;
111 /* Whether we are in MRI mode. */
113 static int macro_mri;
115 /* Whether we should strip '@' characters. */
117 static int macro_strip_at;
119 /* Function to use to parse an expression. */
121 static int (*macro_expr) PARAMS ((const char *, int, sb *, int *));
123 /* Number of macro expansions that have been done. */
125 static int macro_number;
127 /* Initialize macro processing. */
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 *));
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;
144 /* Switch in and out of MRI mode on the fly. */
146 void
147 macro_mri_mode (mri)
148 int mri;
150 macro_mri = mri;
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. */
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 *));
166 int from_len = strlen (from);
167 int to_len = strlen (to);
168 int depth = 1;
169 int line_start = ptr->len;
171 int more = get_line (ptr);
173 while (more)
175 /* Try and find the first pseudo op on the line */
176 int i = line_start;
178 if (! macro_alternate && ! macro_mri)
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 */
185 /* Skip leading whitespace */
186 while (i < ptr->len && ISWHITE (ptr->ptr[i]))
187 i++;
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++;
196 /* And a colon */
197 if (i < ptr->len
198 && ptr->ptr[i] == ':')
199 i++;
202 /* Skip trailing whitespace */
203 while (i < ptr->len && ISWHITE (ptr->ptr[i]))
204 i++;
206 if (i < ptr->len && (ptr->ptr[i] == '.'
207 || macro_alternate
208 || macro_mri))
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])))
218 depth--;
219 if (depth == 0)
221 /* Reset the string to not include the ending rune */
222 ptr->len = line_start;
223 break;
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);
234 /* Return 1 on success, 0 on unexpected EOF. */
235 return depth == 0;
238 /* Pick up a token. */
240 static int
241 get_token (idx, in, name)
242 int idx;
243 sb *in;
244 sb *name;
246 if (idx < in->len
247 && (isalpha ((unsigned char) in->ptr[idx])
248 || in->ptr[idx] == '_'
249 || in->ptr[idx] == '$'))
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] == '$'))
257 sb_add_char (name, in->ptr[idx++]);
260 /* Ignore trailing & */
261 if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
262 idx++;
263 return idx;
266 /* Pick up a string. */
268 static int
269 getstring (idx, in, acc)
270 int idx;
271 sb *in;
272 sb *acc;
274 idx = sb_skip_white (idx, in);
276 while (idx < in->len
277 && (in->ptr[idx] == '"'
278 || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
279 || (in->ptr[idx] == '\'' && macro_alternate)))
281 if (in->ptr[idx] == '<')
283 int nest = 0;
284 idx++;
285 while ((in->ptr[idx] != '>' || nest)
286 && idx < in->len)
288 if (in->ptr[idx] == '!')
290 idx++ ;
291 sb_add_char (acc, in->ptr[idx++]);
293 else
295 if (in->ptr[idx] == '>')
296 nest--;
297 if (in->ptr[idx] == '<')
298 nest++;
299 sb_add_char (acc, in->ptr[idx++]);
302 idx++;
304 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
306 char tchar = in->ptr[idx];
307 idx++;
308 while (idx < in->len)
310 if (macro_alternate && in->ptr[idx] == '!')
312 idx++ ;
313 sb_add_char (acc, in->ptr[idx++]);
315 else
317 if (in->ptr[idx] == tchar)
319 idx++;
320 if (idx >= in->len || in->ptr[idx] != tchar)
321 break;
323 sb_add_char (acc, in->ptr[idx]);
324 idx++;
330 return idx;
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
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;
349 sb_reset (out);
350 idx = sb_skip_white (idx, in);
352 if (idx < in->len)
354 if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
356 while (!ISSEP (in->ptr[idx]))
357 sb_add_char (out, in->ptr[idx++]);
359 else if (in->ptr[idx] == '%'
360 && macro_alternate
361 && expand)
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,
369 &val);
370 sprintf(buf, "%d", val);
371 sb_add_string (out, buf);
373 else if (in->ptr[idx] == '"'
374 || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
375 || (macro_alternate && in->ptr[idx] == '\''))
377 if (macro_alternate
378 && ! macro_strip_at
379 && expand)
381 /* Keep the quotes */
382 sb_add_char (out, '\"');
384 idx = getstring (idx, in, out);
385 sb_add_char (out, '\"');
387 else
389 idx = getstring (idx, in, out);
392 else
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)))))
404 if (in->ptr[idx] == '"'
405 || in->ptr[idx] == '\'')
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;
415 sb_add_char (out, in->ptr[idx++]);
420 return idx;
423 /* Pick up the formal parameters of a macro definition. */
425 static int
426 do_formals (macro, idx, in)
427 macro_entry *macro;
428 int idx;
429 sb *in;
431 formal_entry **p = &macro->formals;
433 macro->formal_count = 0;
434 macro->formal_hash = hash_new ();
435 while (idx < in->len)
437 formal_entry *formal;
439 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
441 sb_new (&formal->name);
442 sb_new (&formal->def);
443 sb_new (&formal->actual);
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)
452 /* This is a formal */
453 if (idx < in->len && in->ptr[idx] == '=')
455 /* Got a default */
456 idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
460 /* Add to macro's hash table */
461 hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
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;
471 if (macro_mri)
473 formal_entry *formal;
474 const char *name;
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));
480 sb_new (&formal->name);
481 sb_new (&formal->def);
482 sb_new (&formal->actual);
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";
491 sb_add_string (&formal->name, name);
493 /* Add to macro's hash table */
494 hash_jam (macro->formal_hash, name, formal);
496 formal->index = NARG_INDEX;
497 *p = formal;
498 formal->next = NULL;
501 return idx;
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. */
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;
516 macro_entry *macro;
517 sb name;
518 const char *namestr;
520 macro = (macro_entry *) xmalloc (sizeof (macro_entry));
521 sb_new (&macro->sub);
522 sb_new (&name);
524 macro->formal_count = 0;
525 macro->formals = 0;
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)
532 sb_add_sb (&name, label);
533 if (idx < in->len && in->ptr[idx] == '(')
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");
540 else
542 /* It's the label: MACRO formals,... sort */
543 idx = do_formals (macro, idx, in);
546 else
548 idx = get_token (idx, in, &name);
549 idx = sb_skip_comma (idx, in);
550 idx = do_formals (macro, idx, in);
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);
560 macro_defined = 1;
562 if (namep != NULL)
563 *namep = namestr;
565 return NULL;
568 /* Scan a token, and then skip KIND. */
570 static int
571 get_apost_token (idx, in, name, kind)
572 int idx;
573 sb *in;
574 sb *name;
575 int kind;
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;
586 /* Substitute the actual value for a formal parameter. */
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;
598 int src;
599 formal_entry *ptr;
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)
612 if (ptr->actual.len)
614 sb_add_sb (out, &ptr->actual);
616 else
618 sb_add_sb (out, &ptr->def);
621 else if (kind == '&')
623 /* Doing this permits people to use & in macro bodies. */
624 sb_add_char (out, '&');
626 else if (copyifnotthere)
628 sb_add_sb (out, t);
630 else
632 sb_add_char (out, '\\');
633 sb_add_sb (out, t);
635 return src;
638 /* Expand the body of a macro. */
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;
649 sb t;
650 int src = 0;
651 int inquote = 0;
652 formal_entry *loclist = NULL;
654 sb_new (&t);
656 while (src < in->len)
658 if (in->ptr[src] == '&')
660 sb_reset (&t);
661 if (macro_mri)
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++]);
668 else
670 /* FIXME: Why do we do this? */
671 src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
674 else if (in->ptr[src] == '\\')
676 src++;
677 if (in->ptr[src] == comment_char && comment_char != '\0')
679 /* This is a comment, just drop the rest of the line */
680 while (src < in->len
681 && in->ptr[src] != '\n')
682 src++;
684 else if (in->ptr[src] == '(')
686 /* Sub in till the next ')' literally */
687 src++;
688 while (src < in->len && in->ptr[src] != ')')
690 sb_add_char (out, in->ptr[src++]);
692 if (in->ptr[src] == ')')
693 src++;
694 else
695 return _("missplaced )");
697 else if (in->ptr[src] == '@')
699 /* Sub in the macro invocation number */
701 char buffer[10];
702 src++;
703 sprintf (buffer, "%d", macro_number);
704 sb_add_string (out, buffer);
706 else if (in->ptr[src] == '&')
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++;
714 else if (macro_mri
715 && isalnum ((unsigned char) in->ptr[src]))
717 int ind;
718 formal_entry *f;
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)
729 if (f->index == ind - 1)
731 if (f->actual.len != 0)
732 sb_add_sb (out, &f->actual);
733 else
734 sb_add_sb (out, &f->def);
735 break;
739 else
741 sb_reset (&t);
742 src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
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] == '@')))
753 if (! locals
754 || src + 5 >= in->len
755 || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
756 || ! ISWHITE (in->ptr[src + 5]))
758 sb_reset (&t);
759 src = sub_actual (src, in, &t, formal_hash,
760 (macro_strip_at && inquote) ? '@' : '\'',
761 out, 1);
763 else
765 formal_entry *f;
767 src = sb_skip_white (src + 5, in);
768 while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
770 static int loccnt;
771 char buf[20];
772 const char *err;
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;
782 src = get_token (src, in, &f->name);
783 ++loccnt;
784 sprintf (buf, "LL%04x", loccnt);
785 sb_add_string (&f->actual, buf);
787 err = hash_jam (formal_hash, sb_terminate (&f->name), f);
788 if (err != NULL)
789 return err;
791 src = sb_skip_comma (src, in);
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)
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++;
806 else if (in->ptr[src] == '"'
807 || (macro_mri && in->ptr[src] == '\''))
809 inquote = !inquote;
810 sb_add_char (out, in->ptr[src++]);
812 else if (in->ptr[src] == '@' && macro_strip_at)
814 ++src;
815 if (src < in->len
816 && in->ptr[src] == '@')
818 sb_add_char (out, '@');
819 ++src;
822 else if (macro_mri
823 && in->ptr[src] == '='
824 && src + 1 < in->len
825 && in->ptr[src + 1] == '=')
827 formal_entry *ptr;
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)
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);
846 else
848 if (ptr->actual.len)
850 sb_add_string (out, "-1");
852 else
854 sb_add_char (out, '0');
858 else
860 sb_add_char (out, in->ptr[src++]);
864 sb_kill (&t);
866 while (loclist != NULL)
868 formal_entry *f;
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;
881 return NULL;
884 /* Assign values to the formal parameters of a macro, and expand the
885 body. */
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;
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;
903 sb_new (&t);
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;
912 if (macro_mri)
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] == '.')
918 formal_entry *n;
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;
926 n->next = m->formals;
927 m->formals = n;
929 idx = get_any_string (idx + 1, in, &n->actual, 1, 0);
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)
937 int scan;
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] == '=')
948 is_keyword = 1;
950 /* It's OK to go from positional to keyword. */
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");
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
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;
972 else
974 /* This is a positional arg */
975 is_positional = 1;
976 if (is_keyword)
977 return _("can't mix positional and keyword arguments");
979 if (!f)
981 formal_entry **pf;
982 int c;
984 if (!macro_mri)
985 return _("too many positional arguments");
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;
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;
1003 sb_reset (&f->actual);
1004 idx = get_any_string (idx, in, &f->actual, 1, 0);
1005 if (f->actual.len > 0)
1006 ++narg;
1009 f = f->next;
1011 while (f != NULL && f->index < 0);
1014 if (! macro_mri)
1015 idx = sb_skip_comma (idx, in);
1016 else
1018 if (in->ptr[idx] == ',')
1019 ++idx;
1020 if (ISWHITE (in->ptr[idx]))
1021 break;
1025 if (macro_mri)
1027 char buffer[20];
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);
1037 err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash,
1038 comment_char, 1);
1039 if (err != NULL)
1040 return err;
1042 /* Discard any unnamed formal arguments. */
1043 if (macro_mri)
1045 formal_entry **pf;
1047 pf = &m->formals;
1048 while (*pf != NULL)
1050 if ((*pf)->name.len != 0)
1051 pf = &(*pf)->next;
1052 else
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;
1064 sb_kill (&t);
1065 macro_number++;
1067 return NULL;
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. */
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;
1082 const char *s;
1083 char *copy, *cs;
1084 macro_entry *macro;
1085 sb line_sb;
1087 if (! isalpha ((unsigned char) *line)
1088 && *line != '_'
1089 && *line != '$'
1090 && (! macro_mri || *line != '.'))
1091 return 0;
1093 s = line + 1;
1094 while (isalnum ((unsigned char) *s)
1095 || *s == '_'
1096 || *s == '$')
1097 ++s;
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);
1106 macro = (macro_entry *) hash_find (macro_hash, copy);
1108 if (macro == NULL)
1109 return 0;
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++);
1116 sb_new (expand);
1117 *error = macro_expand (0, &line_sb, macro, expand, comment_char);
1119 sb_kill (&line_sb);
1121 /* export the macro information if requested */
1122 if (info)
1123 *info = macro;
1125 return 1;
1128 /* Delete a macro. */
1130 void
1131 delete_macro (name)
1132 const char *name;
1134 hash_delete (macro_hash, name);
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. */
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;
1150 const char *mn;
1151 sb sub;
1152 formal_entry f;
1153 struct hash_control *h;
1154 const char *err;
1156 if (irpc)
1157 mn = "IRPC";
1158 else
1159 mn = "IRP";
1161 idx = sb_skip_white (idx, in);
1163 sb_new (&sub);
1164 if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
1165 return _("unexpected end of file in irp or irpc");
1167 sb_new (&f.name);
1168 sb_new (&f.def);
1169 sb_new (&f.actual);
1171 idx = get_token (idx, in, &f.name);
1172 if (f.name.len == 0)
1173 return _("missing model parameter");
1175 h = hash_new ();
1176 err = hash_jam (h, sb_terminate (&f.name), &f);
1177 if (err != NULL)
1178 return err;
1180 f.index = 1;
1181 f.next = NULL;
1183 sb_reset (out);
1185 idx = sb_skip_comma (idx, in);
1186 if (idx >= in->len || in->ptr[idx] == comment_char)
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;
1193 else
1195 if (irpc && in->ptr[idx] == '"')
1196 ++idx;
1197 while (idx < in->len && in->ptr[idx] != comment_char)
1199 if (!irpc)
1200 idx = get_any_string (idx, in, &f.actual, 1, 0);
1201 else
1203 if (in->ptr[idx] == '"')
1205 int nxt;
1207 nxt = sb_skip_white (idx + 1, in);
1208 if (nxt >= in->len || in->ptr[nxt] == comment_char)
1210 idx = nxt;
1211 break;
1214 sb_reset (&f.actual);
1215 sb_add_char (&f.actual, in->ptr[idx]);
1216 ++idx;
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);
1228 hash_die (h);
1229 sb_kill (&sub);
1231 return NULL;