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,
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)
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
26 /* AIX requires this to be the first thing in the file. */
30 extern void *alloca ();
32 extern char *alloca ();
42 # ifndef alloca /* predefined by HP cc +Olibcalls */
43 # if !defined (__STDC__) && !defined (__hpux)
44 extern char *alloca ();
46 extern void *alloca ();
47 # endif /* __STDC__, __hpux */
50 # endif /* HAVE_ALLOCA_H */
63 #include "libiberty.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));
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')
89 ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
90 || (x) == ')' || (x) == '(' \
91 || ((macro_alternate || macro_mri) && ((x) == '<' || (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. */
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. */
130 macro_init (alternate
, mri
, strip_at
, expr
)
134 int (*expr
) PARAMS ((const char *, int, sb
*, int *));
136 macro_hash
= hash_new ();
138 macro_alternate
= alternate
;
140 macro_strip_at
= strip_at
;
144 /* Switch in and out of MRI mode on the fly. */
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
)
164 int (*get_line
) PARAMS ((sb
*));
166 int from_len
= strlen (from
);
167 int to_len
= strlen (to
);
169 int line_start
= ptr
->len
;
171 int more
= get_line (ptr
);
175 /* Try and find the first pseudo op on the line */
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
185 /* Skip leading whitespace */
186 while (i
< ptr
->len
&& ISWHITE (ptr
->ptr
[i
]))
189 /* Skip over a label */
191 && (isalnum ((unsigned char) ptr
->ptr
[i
])
192 || ptr
->ptr
[i
] == '_'
193 || ptr
->ptr
[i
] == '$'))
198 && ptr
->ptr
[i
] == ':')
202 /* Skip trailing whitespace */
203 while (i
< ptr
->len
&& ISWHITE (ptr
->ptr
[i
]))
206 if (i
< ptr
->len
&& (ptr
->ptr
[i
] == '.'
210 if (ptr
->ptr
[i
] == '.')
212 if (strncasecmp (ptr
->ptr
+ i
, from
, from_len
) == 0
213 && (ptr
->len
== (i
+ from_len
) || ! isalnum (ptr
->ptr
[i
+ from_len
])))
215 if (strncasecmp (ptr
->ptr
+ i
, to
, to_len
) == 0
216 && (ptr
->len
== (i
+ to_len
) || ! isalnum (ptr
->ptr
[i
+ to_len
])))
221 /* Reset the string to not include the ending rune */
222 ptr
->len
= line_start
;
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. */
238 /* Pick up a token. */
241 get_token (idx
, in
, name
)
247 && (isalpha ((unsigned char) in
->ptr
[idx
])
248 || in
->ptr
[idx
] == '_'
249 || in
->ptr
[idx
] == '$'))
251 sb_add_char (name
, in
->ptr
[idx
++]);
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
] == '&')
266 /* Pick up a string. */
269 getstring (idx
, in
, acc
)
274 idx
= sb_skip_white (idx
, in
);
277 && (in
->ptr
[idx
] == '"'
278 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
279 || (in
->ptr
[idx
] == '\'' && macro_alternate
)))
281 if (in
->ptr
[idx
] == '<')
285 while ((in
->ptr
[idx
] != '>' || nest
)
288 if (in
->ptr
[idx
] == '!')
291 sb_add_char (acc
, in
->ptr
[idx
++]);
295 if (in
->ptr
[idx
] == '>')
297 if (in
->ptr
[idx
] == '<')
299 sb_add_char (acc
, in
->ptr
[idx
++]);
304 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
306 char tchar
= in
->ptr
[idx
];
308 while (idx
< in
->len
)
310 if (macro_alternate
&& in
->ptr
[idx
] == '!')
313 sb_add_char (acc
, in
->ptr
[idx
++]);
317 if (in
->ptr
[idx
] == tchar
)
320 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
323 sb_add_char (acc
, in
->ptr
[idx
]);
333 /* Fetch string from the input stream,
335 'Bxyx<whitespace> -> return 'Bxyza
336 %<char> -> return string of decimal value of x
337 "<string>" -> return string
338 xyx<whitespace> -> return xyz
342 get_any_string (idx
, in
, out
, expand
, pretend_quoted
)
350 idx
= sb_skip_white (idx
, in
);
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
] == '%'
365 /* Turns the next expression into a string */
366 idx
= (*macro_expr
) (_("% operator needs absolute expression"),
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
] == '\''))
381 /* Keep the quotes */
382 sb_add_char (out
, '\"');
384 idx
= getstring (idx
, in
, out
);
385 sb_add_char (out
, '\"');
389 idx
= getstring (idx
, in
, out
);
395 && (in
->ptr
[idx
] == '"'
396 || in
->ptr
[idx
] == '\''
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
++]);
410 && in
->ptr
[idx
] != tchar
)
411 sb_add_char (out
, in
->ptr
[idx
++]);
415 sb_add_char (out
, in
->ptr
[idx
++]);
423 /* Pick up the formal parameters of a macro definition. */
426 do_formals (macro
, idx
, in
)
431 formal_entry
**p
= ¯o
->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)
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
] == '=')
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
++;
473 formal_entry
*formal
;
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. */
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
;
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. */
509 define_macro (idx
, in
, label
, get_line
, namep
)
513 int (*get_line
) PARAMS ((sb
*));
520 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
521 sb_new (¯o
->sub
);
524 macro
->formal_count
= 0;
527 idx
= sb_skip_white (idx
, in
);
528 if (! buffer_and_nest ("MACRO", "ENDM", ¯o
->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");
542 /* It's the label: MACRO formals,... sort */
543 idx
= do_formals (macro
, idx
, in
);
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
);
568 /* Scan a token, and then skip KIND. */
571 get_apost_token (idx
, in
, name
, kind
)
577 idx
= get_token (idx
, in
, name
);
579 && in
->ptr
[idx
] == kind
580 && (! macro_mri
|| macro_strip_at
)
581 && (! macro_strip_at
|| kind
== '@'))
586 /* Substitute the actual value for a formal parameter. */
589 sub_actual (start
, in
, t
, formal_hash
, kind
, out
, copyifnotthere
)
593 struct hash_control
*formal_hash
;
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 '@'. */
606 && (src
== start
|| in
->ptr
[src
- 1] != '@'))
609 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (t
));
614 sb_add_sb (out
, &ptr
->actual
);
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
)
632 sb_add_char (out
, '\\');
638 /* Expand the body of a macro. */
641 macro_expand_body (in
, out
, formals
, formal_hash
, comment_char
, locals
)
644 formal_entry
*formals
;
645 struct hash_control
*formal_hash
;
652 formal_entry
*loclist
= NULL
;
656 while (src
< in
->len
)
658 if (in
->ptr
[src
] == '&')
663 if (src
+ 1 < in
->len
&& in
->ptr
[src
+ 1] == '&')
664 src
= sub_actual (src
+ 2, in
, &t
, formal_hash
, '\'', out
, 1);
666 sb_add_char (out
, in
->ptr
[src
++]);
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
] == '\\')
677 if (in
->ptr
[src
] == comment_char
&& comment_char
!= '\0')
679 /* This is a comment, just drop the rest of the line */
681 && in
->ptr
[src
] != '\n')
684 else if (in
->ptr
[src
] == '(')
686 /* Sub in till the next ')' literally */
688 while (src
< in
->len
&& in
->ptr
[src
] != ')')
690 sb_add_char (out
, in
->ptr
[src
++]);
692 if (in
->ptr
[src
] == ')')
695 return _("missplaced )");
697 else if (in
->ptr
[src
] == '@')
699 /* Sub in the macro invocation number */
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
710 sb_add_char (out
, '\\');
711 sb_add_char (out
, '&');
715 && isalnum ((unsigned char) in
->ptr
[src
]))
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;
725 ind
= in
->ptr
[src
] - 'a' + 10;
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
);
734 sb_add_sb (out
, &f
->def
);
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
] == '$')
751 || (src
> 0 && in
->ptr
[src
- 1] == '@')))
754 || src
+ 5 >= in
->len
755 || strncasecmp (in
->ptr
+ src
, "LOCAL", 5) != 0
756 || ! ISWHITE (in
->ptr
[src
+ 5]))
759 src
= sub_actual (src
, in
, &t
, formal_hash
,
760 (macro_strip_at
&& inquote
) ? '@' : '\'',
767 src
= sb_skip_white (src
+ 5, in
);
768 while (in
->ptr
[src
] != '\n' && in
->ptr
[src
] != comment_char
)
774 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
778 f
->index
= LOCAL_INDEX
;
782 src
= get_token (src
, in
, &f
->name
);
784 sprintf (buf
, "LL%04x", loccnt
);
785 sb_add_string (&f
->actual
, buf
);
787 err
= hash_jam (formal_hash
, sb_terminate (&f
->name
), f
);
791 src
= sb_skip_comma (src
, in
);
795 else if (comment_char
!= '\0'
796 && in
->ptr
[src
] == comment_char
798 && in
->ptr
[src
+ 1] == comment_char
801 /* Two comment chars in a row cause the rest of the line to
803 while (src
< in
->len
&& in
->ptr
[src
] != '\n')
806 else if (in
->ptr
[src
] == '"'
807 || (macro_mri
&& in
->ptr
[src
] == '\''))
810 sb_add_char (out
, in
->ptr
[src
++]);
812 else if (in
->ptr
[src
] == '@' && macro_strip_at
)
816 && in
->ptr
[src
] == '@')
818 sb_add_char (out
, '@');
823 && in
->ptr
[src
] == '='
825 && in
->ptr
[src
+ 1] == '=')
830 src
= get_token (src
+ 2, in
, &t
);
831 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (&t
));
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
, '=');
850 sb_add_string (out
, "-1");
854 sb_add_char (out
, '0');
860 sb_add_char (out
, in
->ptr
[src
++]);
866 while (loclist
!= NULL
)
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
);
884 /* Assign values to the formal parameters of a macro, and expand the
888 macro_expand (idx
, in
, m
, out
, comment_char
)
898 int is_positional
= 0;
905 /* Reset any old value the actuals may have */
906 for (f
= m
->formals
; f
; f
= f
->next
)
907 sb_reset (&f
->actual
);
909 while (f
!= NULL
&& f
->index
< 0)
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
] == '.')
920 n
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
924 n
->index
= QUAL_INDEX
;
926 n
->next
= m
->formals
;
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
)
939 /* Look and see if it's a positional or keyword arg */
941 while (scan
< in
->len
942 && !ISSEP (in
->ptr
[scan
])
943 && !(macro_mri
&& in
->ptr
[scan
] == '\'')
944 && (!macro_alternate
&& in
->ptr
[scan
] != '='))
946 if (scan
< in
->len
&& !macro_alternate
&& in
->ptr
[scan
] == '=')
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 */
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
));
962 return _("macro formal argument does not exist");
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)
974 /* This is a positional arg */
977 return _("can't mix positional and keyword arguments");
985 return _("too many positional arguments");
987 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
994 for (pf
= &m
->formals
; *pf
!= NULL
; pf
= &(*pf
)->next
)
995 if ((*pf
)->index
>= c
)
996 c
= (*pf
)->index
+ 1;
1003 sb_reset (&f
->actual
);
1004 idx
= get_any_string (idx
, in
, &f
->actual
, 1, 0);
1005 if (f
->actual
.len
> 0)
1011 while (f
!= NULL
&& f
->index
< 0);
1015 idx
= sb_skip_comma (idx
, in
);
1018 if (in
->ptr
[idx
] == ',')
1020 if (ISWHITE (in
->ptr
[idx
]))
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
,
1042 /* Discard any unnamed formal arguments. */
1050 if ((*pf
)->name
.len
!= 0)
1054 sb_kill (&(*pf
)->name
);
1055 sb_kill (&(*pf
)->def
);
1056 sb_kill (&(*pf
)->actual
);
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
)
1087 if (! isalpha ((unsigned char) *line
)
1090 && (! macro_mri
|| *line
!= '.'))
1094 while (isalnum ((unsigned char) *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
);
1111 /* Wrap the line up in an sb. */
1113 while (*s
!= '\0' && *s
!= '\n' && *s
!= '\r')
1114 sb_add_char (&line_sb
, *s
++);
1117 *error
= macro_expand (0, &line_sb
, macro
, expand
, comment_char
);
1121 /* export the macro information if requested */
1128 /* Delete a macro. */
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. */
1142 expand_irp (irpc
, idx
, in
, out
, get_line
, comment_char
)
1147 int (*get_line
) PARAMS ((sb
*));
1153 struct hash_control
*h
;
1161 idx
= sb_skip_white (idx
, in
);
1164 if (! buffer_and_nest (mn
, "ENDR", &sub
, get_line
))
1165 return _("unexpected end of file in irp or irpc");
1171 idx
= get_token (idx
, in
, &f
.name
);
1172 if (f
.name
.len
== 0)
1173 return _("missing model parameter");
1176 err
= hash_jam (h
, sb_terminate (&f
.name
), &f
);
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);
1195 if (irpc
&& in
->ptr
[idx
] == '"')
1197 while (idx
< in
->len
&& in
->ptr
[idx
] != comment_char
)
1200 idx
= get_any_string (idx
, in
, &f
.actual
, 1, 0);
1203 if (in
->ptr
[idx
] == '"')
1207 nxt
= sb_skip_white (idx
+ 1, in
);
1208 if (nxt
>= in
->len
|| in
->ptr
[nxt
] == comment_char
)
1214 sb_reset (&f
.actual
);
1215 sb_add_char (&f
.actual
, in
->ptr
[idx
]);
1218 err
= macro_expand_body (&sub
, out
, &f
, h
, comment_char
, 0);
1222 idx
= sb_skip_comma (idx
, in
);
1224 idx
= sb_skip_white (idx
, in
);