1 /* macro.c - macro support for gas
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
5 Written by Steve and Judy Chamberlain of Cygnus Support,
8 This file is part of GAS, the GNU Assembler.
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)
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.
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
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
37 # ifndef alloca /* predefined by HP cc +Olibcalls */
38 # if !defined (__STDC__) && !defined (__hpux)
39 extern char *alloca ();
41 extern void *alloca ();
42 # endif /* __STDC__, __hpux */
45 # endif /* HAVE_ALLOCA_H */
57 #include "libiberty.h"
58 #include "safe-ctype.h"
65 /* The routines in this file handle macro definition and expansion.
66 They are called by gas. */
68 /* Internal functions. */
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
*);
80 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
83 ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
84 || (x) == ')' || (x) == '(' \
85 || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
88 ((x) == 'b' || (x) == 'B' \
89 || (x) == 'q' || (x) == 'Q' \
90 || (x) == 'h' || (x) == 'H' \
91 || (x) == 'd' || (x) == 'D')
93 /* The macro hash table. */
95 struct hash_control
*macro_hash
;
97 /* Whether any macros have been defined. */
101 /* Whether we are in alternate syntax mode. */
103 static int macro_alternate
;
105 /* Whether we are in MRI mode. */
107 static int macro_mri
;
109 /* Whether we should strip '@' characters. */
111 static int macro_strip_at
;
113 /* Function to use to parse an expression. */
115 static int (*macro_expr
) (const char *, int, sb
*, int *);
117 /* Number of macro expansions that have been done. */
119 static int macro_number
;
121 /* Initialize macro processing. */
124 macro_init (int alternate
, int mri
, int strip_at
,
125 int (*expr
) (const char *, int, sb
*, int *))
127 macro_hash
= hash_new ();
129 macro_alternate
= alternate
;
131 macro_strip_at
= strip_at
;
135 /* Switch in and out of alternate mode on the fly. */
138 macro_set_alternate (int alternate
)
140 macro_alternate
= alternate
;
143 /* Switch in and out of MRI mode on the fly. */
146 macro_mri_mode (int mri
)
151 /* Read input lines till we get to a TO string.
152 Increase nesting depth if we get a FROM string.
153 Put the results into sb at PTR.
154 Add a new input line to an sb using GET_LINE.
155 Return 1 on success, 0 on unexpected EOF. */
158 buffer_and_nest (const char *from
, const char *to
, sb
*ptr
,
159 int (*get_line
) (sb
*))
161 int from_len
= strlen (from
);
162 int to_len
= strlen (to
);
164 int line_start
= ptr
->len
;
166 int more
= get_line (ptr
);
170 /* Try and find the first pseudo op on the line. */
173 if (! macro_alternate
&& ! macro_mri
)
175 /* With normal syntax we can suck what we want till we get
176 to the dot. With the alternate, labels have to start in
177 the first column, since we cant tell what's a label and
180 /* Skip leading whitespace. */
181 while (i
< ptr
->len
&& ISWHITE (ptr
->ptr
[i
]))
184 /* Skip over a label. */
186 && (ISALNUM (ptr
->ptr
[i
])
187 || ptr
->ptr
[i
] == '_'
188 || ptr
->ptr
[i
] == '$'))
193 && ptr
->ptr
[i
] == ':')
197 /* Skip trailing whitespace. */
198 while (i
< ptr
->len
&& ISWHITE (ptr
->ptr
[i
]))
201 if (i
< ptr
->len
&& (ptr
->ptr
[i
] == '.'
205 if (ptr
->ptr
[i
] == '.')
207 if (strncasecmp (ptr
->ptr
+ i
, from
, from_len
) == 0
208 && (ptr
->len
== (i
+ from_len
)
209 || ! ISALNUM (ptr
->ptr
[i
+ from_len
])))
211 if (strncasecmp (ptr
->ptr
+ i
, to
, to_len
) == 0
212 && (ptr
->len
== (i
+ to_len
)
213 || ! ISALNUM (ptr
->ptr
[i
+ to_len
])))
218 /* Reset the string to not include the ending rune. */
219 ptr
->len
= line_start
;
225 /* Add the original end-of-line char to the end and keep running. */
226 sb_add_char (ptr
, more
);
227 line_start
= ptr
->len
;
228 more
= get_line (ptr
);
231 /* Return 1 on success, 0 on unexpected EOF. */
235 /* Pick up a token. */
238 get_token (int idx
, sb
*in
, sb
*name
)
241 && (ISALPHA (in
->ptr
[idx
])
242 || in
->ptr
[idx
] == '_'
243 || in
->ptr
[idx
] == '$'))
245 sb_add_char (name
, in
->ptr
[idx
++]);
247 && (ISALNUM (in
->ptr
[idx
])
248 || in
->ptr
[idx
] == '_'
249 || in
->ptr
[idx
] == '$'))
251 sb_add_char (name
, in
->ptr
[idx
++]);
254 /* Ignore trailing &. */
255 if (macro_alternate
&& idx
< in
->len
&& in
->ptr
[idx
] == '&')
260 /* Pick up a string. */
263 getstring (int idx
, sb
*in
, sb
*acc
)
265 idx
= sb_skip_white (idx
, in
);
268 && (in
->ptr
[idx
] == '"'
269 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
270 || (in
->ptr
[idx
] == '\'' && macro_alternate
)))
272 if (in
->ptr
[idx
] == '<')
276 while ((in
->ptr
[idx
] != '>' || nest
)
279 if (in
->ptr
[idx
] == '!')
282 sb_add_char (acc
, in
->ptr
[idx
++]);
286 if (in
->ptr
[idx
] == '>')
288 if (in
->ptr
[idx
] == '<')
290 sb_add_char (acc
, in
->ptr
[idx
++]);
295 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
297 char tchar
= in
->ptr
[idx
];
302 while (idx
< in
->len
)
304 if (in
->ptr
[idx
- 1] == '\\')
309 if (macro_alternate
&& in
->ptr
[idx
] == '!')
313 sb_add_char (acc
, in
->ptr
[idx
]);
317 else if (escaped
&& in
->ptr
[idx
] == tchar
)
319 sb_add_char (acc
, tchar
);
324 if (in
->ptr
[idx
] == tchar
)
328 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
332 sb_add_char (acc
, in
->ptr
[idx
]);
342 /* Fetch string from the input stream,
344 'Bxyx<whitespace> -> return 'Bxyza
345 %<char> -> return string of decimal value of x
346 "<string>" -> return string
347 xyx<whitespace> -> return xyz
351 get_any_string (int idx
, sb
*in
, sb
*out
, int expand
, int pretend_quoted
)
354 idx
= sb_skip_white (idx
, in
);
358 if (in
->len
> idx
+ 2 && in
->ptr
[idx
+ 1] == '\'' && ISBASE (in
->ptr
[idx
]))
360 while (!ISSEP (in
->ptr
[idx
]))
361 sb_add_char (out
, in
->ptr
[idx
++]);
363 else if (in
->ptr
[idx
] == '%'
369 /* Turns the next expression into a string. */
370 /* xgettext: no-c-format */
371 idx
= (*macro_expr
) (_("% operator needs absolute expression"),
375 sprintf (buf
, "%d", val
);
376 sb_add_string (out
, buf
);
378 else if (in
->ptr
[idx
] == '"'
379 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
380 || (macro_alternate
&& in
->ptr
[idx
] == '\''))
386 /* Keep the quotes. */
387 sb_add_char (out
, '\"');
389 idx
= getstring (idx
, in
, out
);
390 sb_add_char (out
, '\"');
394 idx
= getstring (idx
, in
, out
);
400 && (in
->ptr
[idx
] == '"'
401 || in
->ptr
[idx
] == '\''
403 || (in
->ptr
[idx
] != ' '
404 && in
->ptr
[idx
] != '\t'
405 && in
->ptr
[idx
] != ','
406 && (in
->ptr
[idx
] != '<'
407 || (! macro_alternate
&& ! macro_mri
)))))
409 if (in
->ptr
[idx
] == '"'
410 || in
->ptr
[idx
] == '\'')
412 char tchar
= in
->ptr
[idx
];
413 sb_add_char (out
, in
->ptr
[idx
++]);
415 && in
->ptr
[idx
] != tchar
)
416 sb_add_char (out
, in
->ptr
[idx
++]);
420 sb_add_char (out
, in
->ptr
[idx
++]);
428 /* Pick up the formal parameters of a macro definition. */
431 do_formals (macro_entry
*macro
, int idx
, sb
*in
)
433 formal_entry
**p
= ¯o
->formals
;
435 macro
->formal_count
= 0;
436 macro
->formal_hash
= hash_new ();
437 while (idx
< in
->len
)
439 formal_entry
*formal
;
441 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
443 sb_new (&formal
->name
);
444 sb_new (&formal
->def
);
445 sb_new (&formal
->actual
);
447 idx
= sb_skip_white (idx
, in
);
448 idx
= get_token (idx
, in
, &formal
->name
);
449 if (formal
->name
.len
== 0)
451 idx
= sb_skip_white (idx
, in
);
452 if (formal
->name
.len
)
454 /* This is a formal. */
455 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
458 idx
= get_any_string (idx
+ 1, in
, &formal
->def
, 1, 0);
462 /* Add to macro's hash table. */
463 hash_jam (macro
->formal_hash
, sb_terminate (&formal
->name
), formal
);
465 formal
->index
= macro
->formal_count
;
466 idx
= sb_skip_comma (idx
, in
);
467 macro
->formal_count
++;
475 formal_entry
*formal
;
478 /* Add a special NARG formal, which macro_expand will set to the
479 number of arguments. */
480 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
482 sb_new (&formal
->name
);
483 sb_new (&formal
->def
);
484 sb_new (&formal
->actual
);
486 /* The same MRI assemblers which treat '@' characters also use
487 the name $NARG. At least until we find an exception. */
493 sb_add_string (&formal
->name
, name
);
495 /* Add to macro's hash table. */
496 hash_jam (macro
->formal_hash
, name
, formal
);
498 formal
->index
= NARG_INDEX
;
506 /* Define a new macro. Returns NULL on success, otherwise returns an
507 error message. If NAMEP is not NULL, *NAMEP is set to the name of
508 the macro which was defined. */
511 define_macro (int idx
, sb
*in
, sb
*label
,
512 int (*get_line
) (sb
*), const char **namep
)
518 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
519 sb_new (¯o
->sub
);
522 macro
->formal_count
= 0;
525 idx
= sb_skip_white (idx
, in
);
526 if (! buffer_and_nest ("MACRO", "ENDM", ¯o
->sub
, get_line
))
527 return _("unexpected end of file in macro definition");
528 if (label
!= NULL
&& label
->len
!= 0)
530 sb_add_sb (&name
, label
);
531 if (idx
< in
->len
&& in
->ptr
[idx
] == '(')
533 /* It's the label: MACRO (formals,...) sort */
534 idx
= do_formals (macro
, idx
+ 1, in
);
535 if (in
->ptr
[idx
] != ')')
536 return _("missing ) after formals");
540 /* It's the label: MACRO formals,... sort */
541 idx
= do_formals (macro
, idx
, in
);
546 idx
= get_token (idx
, in
, &name
);
547 idx
= sb_skip_comma (idx
, in
);
548 idx
= do_formals (macro
, idx
, in
);
551 /* And stick it in the macro hash table. */
552 for (idx
= 0; idx
< name
.len
; idx
++)
553 name
.ptr
[idx
] = TOLOWER (name
.ptr
[idx
]);
554 namestr
= sb_terminate (&name
);
555 hash_jam (macro_hash
, namestr
, (PTR
) macro
);
565 /* Scan a token, and then skip KIND. */
568 get_apost_token (int idx
, sb
*in
, sb
*name
, int kind
)
570 idx
= get_token (idx
, in
, name
);
572 && in
->ptr
[idx
] == kind
573 && (! macro_mri
|| macro_strip_at
)
574 && (! macro_strip_at
|| kind
== '@'))
579 /* Substitute the actual value for a formal parameter. */
582 sub_actual (int start
, sb
*in
, sb
*t
, struct hash_control
*formal_hash
,
583 int kind
, sb
*out
, int copyifnotthere
)
588 src
= get_apost_token (start
, in
, t
, kind
);
589 /* See if it's in the macro's hash table, unless this is
590 macro_strip_at and kind is '@' and the token did not end in '@'. */
593 && (src
== start
|| in
->ptr
[src
- 1] != '@'))
596 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (t
));
601 sb_add_sb (out
, &ptr
->actual
);
605 sb_add_sb (out
, &ptr
->def
);
608 else if (kind
== '&')
610 /* Doing this permits people to use & in macro bodies. */
611 sb_add_char (out
, '&');
614 else if (copyifnotthere
)
620 sb_add_char (out
, '\\');
626 /* Expand the body of a macro. */
629 macro_expand_body (sb
*in
, sb
*out
, formal_entry
*formals
,
630 struct hash_control
*formal_hash
, int locals
)
635 formal_entry
*loclist
= NULL
;
639 while (src
< in
->len
)
641 if (in
->ptr
[src
] == '&')
646 if (src
+ 1 < in
->len
&& in
->ptr
[src
+ 1] == '&')
647 src
= sub_actual (src
+ 2, in
, &t
, formal_hash
, '\'', out
, 1);
649 sb_add_char (out
, in
->ptr
[src
++]);
653 /* FIXME: Why do we do this? */
654 src
= sub_actual (src
+ 1, in
, &t
, formal_hash
, '&', out
, 0);
657 else if (in
->ptr
[src
] == '\\')
660 if (in
->ptr
[src
] == '(')
662 /* Sub in till the next ')' literally. */
664 while (src
< in
->len
&& in
->ptr
[src
] != ')')
666 sb_add_char (out
, in
->ptr
[src
++]);
668 if (in
->ptr
[src
] == ')')
671 return _("missplaced )");
673 else if (in
->ptr
[src
] == '@')
675 /* Sub in the macro invocation number. */
679 sprintf (buffer
, "%d", macro_number
);
680 sb_add_string (out
, buffer
);
682 else if (in
->ptr
[src
] == '&')
684 /* This is a preprocessor variable name, we don't do them
686 sb_add_char (out
, '\\');
687 sb_add_char (out
, '&');
690 else if (macro_mri
&& ISALNUM (in
->ptr
[src
]))
695 if (ISDIGIT (in
->ptr
[src
]))
696 ind
= in
->ptr
[src
] - '0';
697 else if (ISUPPER (in
->ptr
[src
]))
698 ind
= in
->ptr
[src
] - 'A' + 10;
700 ind
= in
->ptr
[src
] - 'a' + 10;
702 for (f
= formals
; f
!= NULL
; f
= f
->next
)
704 if (f
->index
== ind
- 1)
706 if (f
->actual
.len
!= 0)
707 sb_add_sb (out
, &f
->actual
);
709 sb_add_sb (out
, &f
->def
);
717 src
= sub_actual (src
, in
, &t
, formal_hash
, '\'', out
, 0);
720 else if ((macro_alternate
|| macro_mri
)
721 && (ISALPHA (in
->ptr
[src
])
722 || in
->ptr
[src
] == '_'
723 || in
->ptr
[src
] == '$')
726 || (src
> 0 && in
->ptr
[src
- 1] == '@')))
729 || src
+ 5 >= in
->len
730 || strncasecmp (in
->ptr
+ src
, "LOCAL", 5) != 0
731 || ! ISWHITE (in
->ptr
[src
+ 5]))
734 src
= sub_actual (src
, in
, &t
, formal_hash
,
735 (macro_strip_at
&& inquote
) ? '@' : '\'',
742 src
= sb_skip_white (src
+ 5, in
);
743 while (in
->ptr
[src
] != '\n')
749 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
753 f
->index
= LOCAL_INDEX
;
757 src
= get_token (src
, in
, &f
->name
);
759 sprintf (buf
, "LL%04x", loccnt
);
760 sb_add_string (&f
->actual
, buf
);
762 err
= hash_jam (formal_hash
, sb_terminate (&f
->name
), f
);
766 src
= sb_skip_comma (src
, in
);
770 else if (in
->ptr
[src
] == '"'
771 || (macro_mri
&& in
->ptr
[src
] == '\''))
774 sb_add_char (out
, in
->ptr
[src
++]);
776 else if (in
->ptr
[src
] == '@' && macro_strip_at
)
780 && in
->ptr
[src
] == '@')
782 sb_add_char (out
, '@');
787 && in
->ptr
[src
] == '='
789 && in
->ptr
[src
+ 1] == '=')
794 src
= get_token (src
+ 2, in
, &t
);
795 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (&t
));
798 /* FIXME: We should really return a warning string here,
799 but we can't, because the == might be in the MRI
800 comment field, and, since the nature of the MRI
801 comment field depends upon the exact instruction
802 being used, we don't have enough information here to
803 figure out whether it is or not. Instead, we leave
804 the == in place, which should cause a syntax error if
805 it is not in a comment. */
806 sb_add_char (out
, '=');
807 sb_add_char (out
, '=');
814 sb_add_string (out
, "-1");
818 sb_add_char (out
, '0');
824 sb_add_char (out
, in
->ptr
[src
++]);
830 while (loclist
!= NULL
)
835 /* Setting the value to NULL effectively deletes the entry. We
836 avoid calling hash_delete because it doesn't reclaim memory. */
837 hash_jam (formal_hash
, sb_terminate (&loclist
->name
), NULL
);
838 sb_kill (&loclist
->name
);
839 sb_kill (&loclist
->def
);
840 sb_kill (&loclist
->actual
);
848 /* Assign values to the formal parameters of a macro, and expand the
852 macro_expand (int idx
, sb
*in
, macro_entry
*m
, sb
*out
)
857 int is_positional
= 0;
864 /* Reset any old value the actuals may have. */
865 for (f
= m
->formals
; f
; f
= f
->next
)
866 sb_reset (&f
->actual
);
868 while (f
!= NULL
&& f
->index
< 0)
873 /* The macro may be called with an optional qualifier, which may
874 be referred to in the macro body as \0. */
875 if (idx
< in
->len
&& in
->ptr
[idx
] == '.')
877 /* The Microtec assembler ignores this if followed by a white space.
878 (Macro invocation with empty extension) */
881 && in
->ptr
[idx
] != ' '
882 && in
->ptr
[idx
] != '\t')
886 n
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
890 n
->index
= QUAL_INDEX
;
892 n
->next
= m
->formals
;
895 idx
= get_any_string (idx
, in
, &n
->actual
, 1, 0);
900 /* Peel off the actuals and store them away in the hash tables' actuals. */
901 idx
= sb_skip_white (idx
, in
);
902 while (idx
< in
->len
)
906 /* Look and see if it's a positional or keyword arg. */
908 while (scan
< in
->len
909 && !ISSEP (in
->ptr
[scan
])
910 && !(macro_mri
&& in
->ptr
[scan
] == '\'')
911 && (!macro_alternate
&& in
->ptr
[scan
] != '='))
913 if (scan
< in
->len
&& !macro_alternate
&& in
->ptr
[scan
] == '=')
917 /* It's OK to go from positional to keyword. */
919 /* This is a keyword arg, fetch the formal name and
920 then the actual stuff. */
922 idx
= get_token (idx
, in
, &t
);
923 if (in
->ptr
[idx
] != '=')
924 return _("confusion in formal parameters");
926 /* Lookup the formal in the macro's list. */
927 ptr
= (formal_entry
*) hash_find (m
->formal_hash
, sb_terminate (&t
));
929 return _("macro formal argument does not exist");
932 /* Insert this value into the right place. */
933 sb_reset (&ptr
->actual
);
934 idx
= get_any_string (idx
+ 1, in
, &ptr
->actual
, 0, 0);
935 if (ptr
->actual
.len
> 0)
941 /* This is a positional arg. */
944 return _("can't mix positional and keyword arguments");
952 return _("too many positional arguments");
954 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
961 for (pf
= &m
->formals
; *pf
!= NULL
; pf
= &(*pf
)->next
)
962 if ((*pf
)->index
>= c
)
963 c
= (*pf
)->index
+ 1;
970 sb_reset (&f
->actual
);
971 idx
= get_any_string (idx
, in
, &f
->actual
, 1, 0);
972 if (f
->actual
.len
> 0)
978 while (f
!= NULL
&& f
->index
< 0);
982 idx
= sb_skip_comma (idx
, in
);
985 if (in
->ptr
[idx
] == ',')
987 if (ISWHITE (in
->ptr
[idx
]))
997 sb_add_string (&t
, macro_strip_at
? "$NARG" : "NARG");
998 ptr
= (formal_entry
*) hash_find (m
->formal_hash
, sb_terminate (&t
));
999 sb_reset (&ptr
->actual
);
1000 sprintf (buffer
, "%d", narg
);
1001 sb_add_string (&ptr
->actual
, buffer
);
1004 err
= macro_expand_body (&m
->sub
, out
, m
->formals
, m
->formal_hash
, 1);
1008 /* Discard any unnamed formal arguments. */
1016 if ((*pf
)->name
.len
!= 0)
1020 sb_kill (&(*pf
)->name
);
1021 sb_kill (&(*pf
)->def
);
1022 sb_kill (&(*pf
)->actual
);
1036 /* Check for a macro. If one is found, put the expansion into
1037 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
1040 check_macro (const char *line
, sb
*expand
,
1041 const char **error
, macro_entry
**info
)
1048 if (! ISALPHA (*line
)
1051 && (! macro_mri
|| *line
!= '.'))
1060 copy
= (char *) alloca (s
- line
+ 1);
1061 memcpy (copy
, line
, s
- line
);
1062 copy
[s
- line
] = '\0';
1063 for (cs
= copy
; *cs
!= '\0'; cs
++)
1064 *cs
= TOLOWER (*cs
);
1066 macro
= (macro_entry
*) hash_find (macro_hash
, copy
);
1071 /* Wrap the line up in an sb. */
1073 while (*s
!= '\0' && *s
!= '\n' && *s
!= '\r')
1074 sb_add_char (&line_sb
, *s
++);
1077 *error
= macro_expand (0, &line_sb
, macro
, expand
);
1081 /* Export the macro information if requested. */
1088 /* Delete a macro. */
1091 delete_macro (const char *name
)
1093 hash_delete (macro_hash
, name
);
1096 /* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
1097 combined macro definition and execution. This returns NULL on
1098 success, or an error message otherwise. */
1101 expand_irp (int irpc
, int idx
, sb
*in
, sb
*out
, int (*get_line
) (sb
*))
1106 struct hash_control
*h
;
1114 idx
= sb_skip_white (idx
, in
);
1117 if (! buffer_and_nest (mn
, "ENDR", &sub
, get_line
))
1118 return _("unexpected end of file in irp or irpc");
1124 idx
= get_token (idx
, in
, &f
.name
);
1125 if (f
.name
.len
== 0)
1126 return _("missing model parameter");
1129 err
= hash_jam (h
, sb_terminate (&f
.name
), &f
);
1138 idx
= sb_skip_comma (idx
, in
);
1141 /* Expand once with a null string. */
1142 err
= macro_expand_body (&sub
, out
, &f
, h
, 0);
1148 if (irpc
&& in
->ptr
[idx
] == '"')
1150 while (idx
< in
->len
)
1153 idx
= get_any_string (idx
, in
, &f
.actual
, 1, 0);
1156 if (in
->ptr
[idx
] == '"')
1160 nxt
= sb_skip_white (idx
+ 1, in
);
1167 sb_reset (&f
.actual
);
1168 sb_add_char (&f
.actual
, in
->ptr
[idx
]);
1171 err
= macro_expand_body (&sub
, out
, &f
, h
, 0);
1175 idx
= sb_skip_comma (idx
, in
);
1177 idx
= sb_skip_white (idx
, in
);