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(alternate
)
141 macro_alternate
= alternate
;
144 /* Switch in and out of MRI mode on the fly. */
147 macro_mri_mode (int mri
)
152 /* Read input lines till we get to a TO string.
153 Increase nesting depth if we get a FROM string.
154 Put the results into sb at PTR.
155 Add a new input line to an sb using GET_LINE.
156 Return 1 on success, 0 on unexpected EOF. */
159 buffer_and_nest (const char *from
, const char *to
, sb
*ptr
,
160 int (*get_line
) (sb
*))
162 int from_len
= strlen (from
);
163 int to_len
= strlen (to
);
165 int line_start
= ptr
->len
;
167 int more
= get_line (ptr
);
171 /* Try and find the first pseudo op on the line. */
174 if (! macro_alternate
&& ! macro_mri
)
176 /* With normal syntax we can suck what we want till we get
177 to the dot. With the alternate, labels have to start in
178 the first column, since we cant tell what's a label and
181 /* Skip leading whitespace. */
182 while (i
< ptr
->len
&& ISWHITE (ptr
->ptr
[i
]))
185 /* Skip over a label. */
187 && (ISALNUM (ptr
->ptr
[i
])
188 || ptr
->ptr
[i
] == '_'
189 || ptr
->ptr
[i
] == '$'))
194 && ptr
->ptr
[i
] == ':')
198 /* Skip trailing whitespace. */
199 while (i
< ptr
->len
&& ISWHITE (ptr
->ptr
[i
]))
202 if (i
< ptr
->len
&& (ptr
->ptr
[i
] == '.'
206 if (ptr
->ptr
[i
] == '.')
208 if (strncasecmp (ptr
->ptr
+ i
, from
, from_len
) == 0
209 && (ptr
->len
== (i
+ from_len
)
210 || ! ISALNUM (ptr
->ptr
[i
+ from_len
])))
212 if (strncasecmp (ptr
->ptr
+ i
, to
, to_len
) == 0
213 && (ptr
->len
== (i
+ to_len
)
214 || ! ISALNUM (ptr
->ptr
[i
+ to_len
])))
219 /* Reset the string to not include the ending rune. */
220 ptr
->len
= line_start
;
226 /* Add the original end-of-line char to the end and keep running. */
227 sb_add_char (ptr
, more
);
228 line_start
= ptr
->len
;
229 more
= get_line (ptr
);
232 /* Return 1 on success, 0 on unexpected EOF. */
236 /* Pick up a token. */
239 get_token (int idx
, sb
*in
, sb
*name
)
242 && (ISALPHA (in
->ptr
[idx
])
243 || in
->ptr
[idx
] == '_'
244 || in
->ptr
[idx
] == '$'))
246 sb_add_char (name
, in
->ptr
[idx
++]);
248 && (ISALNUM (in
->ptr
[idx
])
249 || in
->ptr
[idx
] == '_'
250 || in
->ptr
[idx
] == '$'))
252 sb_add_char (name
, in
->ptr
[idx
++]);
255 /* Ignore trailing &. */
256 if (macro_alternate
&& idx
< in
->len
&& in
->ptr
[idx
] == '&')
261 /* Pick up a string. */
264 getstring (int idx
, sb
*in
, sb
*acc
)
266 idx
= sb_skip_white (idx
, in
);
269 && (in
->ptr
[idx
] == '"'
270 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
271 || (in
->ptr
[idx
] == '\'' && macro_alternate
)))
273 if (in
->ptr
[idx
] == '<')
277 while ((in
->ptr
[idx
] != '>' || nest
)
280 if (in
->ptr
[idx
] == '!')
283 sb_add_char (acc
, in
->ptr
[idx
++]);
287 if (in
->ptr
[idx
] == '>')
289 if (in
->ptr
[idx
] == '<')
291 sb_add_char (acc
, in
->ptr
[idx
++]);
296 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
298 char tchar
= in
->ptr
[idx
];
303 while (idx
< in
->len
)
305 if (in
->ptr
[idx
- 1] == '\\')
310 if (macro_alternate
&& in
->ptr
[idx
] == '!')
314 sb_add_char (acc
, in
->ptr
[idx
]);
318 else if (escaped
&& in
->ptr
[idx
] == tchar
)
320 sb_add_char (acc
, tchar
);
325 if (in
->ptr
[idx
] == tchar
)
329 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
333 sb_add_char (acc
, in
->ptr
[idx
]);
343 /* Fetch string from the input stream,
345 'Bxyx<whitespace> -> return 'Bxyza
346 %<char> -> return string of decimal value of x
347 "<string>" -> return string
348 xyx<whitespace> -> return xyz
352 get_any_string (int idx
, sb
*in
, sb
*out
, int expand
, int pretend_quoted
)
355 idx
= sb_skip_white (idx
, in
);
359 if (in
->len
> idx
+ 2 && in
->ptr
[idx
+ 1] == '\'' && ISBASE (in
->ptr
[idx
]))
361 while (!ISSEP (in
->ptr
[idx
]))
362 sb_add_char (out
, in
->ptr
[idx
++]);
364 else if (in
->ptr
[idx
] == '%'
370 /* Turns the next expression into a string. */
371 /* xgettext: no-c-format */
372 idx
= (*macro_expr
) (_("% operator needs absolute expression"),
376 sprintf (buf
, "%d", val
);
377 sb_add_string (out
, buf
);
379 else if (in
->ptr
[idx
] == '"'
380 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
381 || (macro_alternate
&& in
->ptr
[idx
] == '\''))
387 /* Keep the quotes. */
388 sb_add_char (out
, '\"');
390 idx
= getstring (idx
, in
, out
);
391 sb_add_char (out
, '\"');
395 idx
= getstring (idx
, in
, out
);
401 && (in
->ptr
[idx
] == '"'
402 || in
->ptr
[idx
] == '\''
404 || (in
->ptr
[idx
] != ' '
405 && in
->ptr
[idx
] != '\t'
406 && in
->ptr
[idx
] != ','
407 && (in
->ptr
[idx
] != '<'
408 || (! macro_alternate
&& ! macro_mri
)))))
410 if (in
->ptr
[idx
] == '"'
411 || in
->ptr
[idx
] == '\'')
413 char tchar
= in
->ptr
[idx
];
414 sb_add_char (out
, in
->ptr
[idx
++]);
416 && in
->ptr
[idx
] != tchar
)
417 sb_add_char (out
, in
->ptr
[idx
++]);
421 sb_add_char (out
, in
->ptr
[idx
++]);
429 /* Pick up the formal parameters of a macro definition. */
432 do_formals (macro_entry
*macro
, int idx
, sb
*in
)
434 formal_entry
**p
= ¯o
->formals
;
436 macro
->formal_count
= 0;
437 macro
->formal_hash
= hash_new ();
438 while (idx
< in
->len
)
440 formal_entry
*formal
;
442 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
444 sb_new (&formal
->name
);
445 sb_new (&formal
->def
);
446 sb_new (&formal
->actual
);
448 idx
= sb_skip_white (idx
, in
);
449 idx
= get_token (idx
, in
, &formal
->name
);
450 if (formal
->name
.len
== 0)
452 idx
= sb_skip_white (idx
, in
);
453 if (formal
->name
.len
)
455 /* This is a formal. */
456 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
459 idx
= get_any_string (idx
+ 1, in
, &formal
->def
, 1, 0);
463 /* Add to macro's hash table. */
464 hash_jam (macro
->formal_hash
, sb_terminate (&formal
->name
), formal
);
466 formal
->index
= macro
->formal_count
;
467 idx
= sb_skip_comma (idx
, in
);
468 macro
->formal_count
++;
476 formal_entry
*formal
;
479 /* Add a special NARG formal, which macro_expand will set to the
480 number of arguments. */
481 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
483 sb_new (&formal
->name
);
484 sb_new (&formal
->def
);
485 sb_new (&formal
->actual
);
487 /* The same MRI assemblers which treat '@' characters also use
488 the name $NARG. At least until we find an exception. */
494 sb_add_string (&formal
->name
, name
);
496 /* Add to macro's hash table. */
497 hash_jam (macro
->formal_hash
, name
, formal
);
499 formal
->index
= NARG_INDEX
;
507 /* Define a new macro. Returns NULL on success, otherwise returns an
508 error message. If NAMEP is not NULL, *NAMEP is set to the name of
509 the macro which was defined. */
512 define_macro (int idx
, sb
*in
, sb
*label
,
513 int (*get_line
) (sb
*), const char **namep
)
519 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
520 sb_new (¯o
->sub
);
523 macro
->formal_count
= 0;
526 idx
= sb_skip_white (idx
, in
);
527 if (! buffer_and_nest ("MACRO", "ENDM", ¯o
->sub
, get_line
))
528 return _("unexpected end of file in macro definition");
529 if (label
!= NULL
&& label
->len
!= 0)
531 sb_add_sb (&name
, label
);
532 if (idx
< in
->len
&& in
->ptr
[idx
] == '(')
534 /* It's the label: MACRO (formals,...) sort */
535 idx
= do_formals (macro
, idx
+ 1, in
);
536 if (in
->ptr
[idx
] != ')')
537 return _("missing ) after formals");
541 /* It's the label: MACRO formals,... sort */
542 idx
= do_formals (macro
, idx
, in
);
547 idx
= get_token (idx
, in
, &name
);
548 idx
= sb_skip_comma (idx
, in
);
549 idx
= do_formals (macro
, idx
, in
);
552 /* And stick it in the macro hash table. */
553 for (idx
= 0; idx
< name
.len
; idx
++)
554 name
.ptr
[idx
] = TOLOWER (name
.ptr
[idx
]);
555 namestr
= sb_terminate (&name
);
556 hash_jam (macro_hash
, namestr
, (PTR
) macro
);
566 /* Scan a token, and then skip KIND. */
569 get_apost_token (int idx
, sb
*in
, sb
*name
, int kind
)
571 idx
= get_token (idx
, in
, name
);
573 && in
->ptr
[idx
] == kind
574 && (! macro_mri
|| macro_strip_at
)
575 && (! macro_strip_at
|| kind
== '@'))
580 /* Substitute the actual value for a formal parameter. */
583 sub_actual (int start
, sb
*in
, sb
*t
, struct hash_control
*formal_hash
,
584 int kind
, sb
*out
, int copyifnotthere
)
589 src
= get_apost_token (start
, in
, t
, kind
);
590 /* See if it's in the macro's hash table, unless this is
591 macro_strip_at and kind is '@' and the token did not end in '@'. */
594 && (src
== start
|| in
->ptr
[src
- 1] != '@'))
597 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (t
));
602 sb_add_sb (out
, &ptr
->actual
);
606 sb_add_sb (out
, &ptr
->def
);
609 else if (kind
== '&')
611 /* Doing this permits people to use & in macro bodies. */
612 sb_add_char (out
, '&');
615 else if (copyifnotthere
)
621 sb_add_char (out
, '\\');
627 /* Expand the body of a macro. */
630 macro_expand_body (sb
*in
, sb
*out
, formal_entry
*formals
,
631 struct hash_control
*formal_hash
, int locals
)
636 formal_entry
*loclist
= NULL
;
640 while (src
< in
->len
)
642 if (in
->ptr
[src
] == '&')
647 if (src
+ 1 < in
->len
&& in
->ptr
[src
+ 1] == '&')
648 src
= sub_actual (src
+ 2, in
, &t
, formal_hash
, '\'', out
, 1);
650 sb_add_char (out
, in
->ptr
[src
++]);
654 /* FIXME: Why do we do this? */
655 src
= sub_actual (src
+ 1, in
, &t
, formal_hash
, '&', out
, 0);
658 else if (in
->ptr
[src
] == '\\')
661 if (in
->ptr
[src
] == '(')
663 /* Sub in till the next ')' literally. */
665 while (src
< in
->len
&& in
->ptr
[src
] != ')')
667 sb_add_char (out
, in
->ptr
[src
++]);
669 if (in
->ptr
[src
] == ')')
672 return _("missplaced )");
674 else if (in
->ptr
[src
] == '@')
676 /* Sub in the macro invocation number. */
680 sprintf (buffer
, "%d", macro_number
);
681 sb_add_string (out
, buffer
);
683 else if (in
->ptr
[src
] == '&')
685 /* This is a preprocessor variable name, we don't do them
687 sb_add_char (out
, '\\');
688 sb_add_char (out
, '&');
691 else if (macro_mri
&& ISALNUM (in
->ptr
[src
]))
696 if (ISDIGIT (in
->ptr
[src
]))
697 ind
= in
->ptr
[src
] - '0';
698 else if (ISUPPER (in
->ptr
[src
]))
699 ind
= in
->ptr
[src
] - 'A' + 10;
701 ind
= in
->ptr
[src
] - 'a' + 10;
703 for (f
= formals
; f
!= NULL
; f
= f
->next
)
705 if (f
->index
== ind
- 1)
707 if (f
->actual
.len
!= 0)
708 sb_add_sb (out
, &f
->actual
);
710 sb_add_sb (out
, &f
->def
);
718 src
= sub_actual (src
, in
, &t
, formal_hash
, '\'', out
, 0);
721 else if ((macro_alternate
|| macro_mri
)
722 && (ISALPHA (in
->ptr
[src
])
723 || in
->ptr
[src
] == '_'
724 || in
->ptr
[src
] == '$')
727 || (src
> 0 && in
->ptr
[src
- 1] == '@')))
730 || src
+ 5 >= in
->len
731 || strncasecmp (in
->ptr
+ src
, "LOCAL", 5) != 0
732 || ! ISWHITE (in
->ptr
[src
+ 5]))
735 src
= sub_actual (src
, in
, &t
, formal_hash
,
736 (macro_strip_at
&& inquote
) ? '@' : '\'',
743 src
= sb_skip_white (src
+ 5, in
);
744 while (in
->ptr
[src
] != '\n')
750 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
754 f
->index
= LOCAL_INDEX
;
758 src
= get_token (src
, in
, &f
->name
);
760 sprintf (buf
, "LL%04x", loccnt
);
761 sb_add_string (&f
->actual
, buf
);
763 err
= hash_jam (formal_hash
, sb_terminate (&f
->name
), f
);
767 src
= sb_skip_comma (src
, in
);
771 else if (in
->ptr
[src
] == '"'
772 || (macro_mri
&& in
->ptr
[src
] == '\''))
775 sb_add_char (out
, in
->ptr
[src
++]);
777 else if (in
->ptr
[src
] == '@' && macro_strip_at
)
781 && in
->ptr
[src
] == '@')
783 sb_add_char (out
, '@');
788 && in
->ptr
[src
] == '='
790 && in
->ptr
[src
+ 1] == '=')
795 src
= get_token (src
+ 2, in
, &t
);
796 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (&t
));
799 /* FIXME: We should really return a warning string here,
800 but we can't, because the == might be in the MRI
801 comment field, and, since the nature of the MRI
802 comment field depends upon the exact instruction
803 being used, we don't have enough information here to
804 figure out whether it is or not. Instead, we leave
805 the == in place, which should cause a syntax error if
806 it is not in a comment. */
807 sb_add_char (out
, '=');
808 sb_add_char (out
, '=');
815 sb_add_string (out
, "-1");
819 sb_add_char (out
, '0');
825 sb_add_char (out
, in
->ptr
[src
++]);
831 while (loclist
!= NULL
)
836 /* Setting the value to NULL effectively deletes the entry. We
837 avoid calling hash_delete because it doesn't reclaim memory. */
838 hash_jam (formal_hash
, sb_terminate (&loclist
->name
), NULL
);
839 sb_kill (&loclist
->name
);
840 sb_kill (&loclist
->def
);
841 sb_kill (&loclist
->actual
);
849 /* Assign values to the formal parameters of a macro, and expand the
853 macro_expand (int idx
, sb
*in
, macro_entry
*m
, sb
*out
)
858 int is_positional
= 0;
865 /* Reset any old value the actuals may have. */
866 for (f
= m
->formals
; f
; f
= f
->next
)
867 sb_reset (&f
->actual
);
869 while (f
!= NULL
&& f
->index
< 0)
874 /* The macro may be called with an optional qualifier, which may
875 be referred to in the macro body as \0. */
876 if (idx
< in
->len
&& in
->ptr
[idx
] == '.')
878 /* The Microtec assembler ignores this if followed by a white space.
879 (Macro invocation with empty extension) */
882 && in
->ptr
[idx
] != ' '
883 && in
->ptr
[idx
] != '\t')
887 n
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
891 n
->index
= QUAL_INDEX
;
893 n
->next
= m
->formals
;
896 idx
= get_any_string (idx
, in
, &n
->actual
, 1, 0);
901 /* Peel off the actuals and store them away in the hash tables' actuals. */
902 idx
= sb_skip_white (idx
, in
);
903 while (idx
< in
->len
)
907 /* Look and see if it's a positional or keyword arg. */
909 while (scan
< in
->len
910 && !ISSEP (in
->ptr
[scan
])
911 && !(macro_mri
&& in
->ptr
[scan
] == '\'')
912 && (!macro_alternate
&& in
->ptr
[scan
] != '='))
914 if (scan
< in
->len
&& !macro_alternate
&& in
->ptr
[scan
] == '=')
918 /* It's OK to go from positional to keyword. */
920 /* This is a keyword arg, fetch the formal name and
921 then the actual stuff. */
923 idx
= get_token (idx
, in
, &t
);
924 if (in
->ptr
[idx
] != '=')
925 return _("confusion in formal parameters");
927 /* Lookup the formal in the macro's list. */
928 ptr
= (formal_entry
*) hash_find (m
->formal_hash
, sb_terminate (&t
));
930 return _("macro formal argument does not exist");
933 /* Insert this value into the right place. */
934 sb_reset (&ptr
->actual
);
935 idx
= get_any_string (idx
+ 1, in
, &ptr
->actual
, 0, 0);
936 if (ptr
->actual
.len
> 0)
942 /* This is a positional arg. */
945 return _("can't mix positional and keyword arguments");
953 return _("too many positional arguments");
955 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
962 for (pf
= &m
->formals
; *pf
!= NULL
; pf
= &(*pf
)->next
)
963 if ((*pf
)->index
>= c
)
964 c
= (*pf
)->index
+ 1;
971 sb_reset (&f
->actual
);
972 idx
= get_any_string (idx
, in
, &f
->actual
, 1, 0);
973 if (f
->actual
.len
> 0)
979 while (f
!= NULL
&& f
->index
< 0);
983 idx
= sb_skip_comma (idx
, in
);
986 if (in
->ptr
[idx
] == ',')
988 if (ISWHITE (in
->ptr
[idx
]))
998 sb_add_string (&t
, macro_strip_at
? "$NARG" : "NARG");
999 ptr
= (formal_entry
*) hash_find (m
->formal_hash
, sb_terminate (&t
));
1000 sb_reset (&ptr
->actual
);
1001 sprintf (buffer
, "%d", narg
);
1002 sb_add_string (&ptr
->actual
, buffer
);
1005 err
= macro_expand_body (&m
->sub
, out
, m
->formals
, m
->formal_hash
, 1);
1009 /* Discard any unnamed formal arguments. */
1017 if ((*pf
)->name
.len
!= 0)
1021 sb_kill (&(*pf
)->name
);
1022 sb_kill (&(*pf
)->def
);
1023 sb_kill (&(*pf
)->actual
);
1037 /* Check for a macro. If one is found, put the expansion into
1038 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
1041 check_macro (const char *line
, sb
*expand
,
1042 const char **error
, macro_entry
**info
)
1049 if (! ISALPHA (*line
)
1052 && (! macro_mri
|| *line
!= '.'))
1061 copy
= (char *) alloca (s
- line
+ 1);
1062 memcpy (copy
, line
, s
- line
);
1063 copy
[s
- line
] = '\0';
1064 for (cs
= copy
; *cs
!= '\0'; cs
++)
1065 *cs
= TOLOWER (*cs
);
1067 macro
= (macro_entry
*) hash_find (macro_hash
, copy
);
1072 /* Wrap the line up in an sb. */
1074 while (*s
!= '\0' && *s
!= '\n' && *s
!= '\r')
1075 sb_add_char (&line_sb
, *s
++);
1078 *error
= macro_expand (0, &line_sb
, macro
, expand
);
1082 /* Export the macro information if requested. */
1089 /* Delete a macro. */
1092 delete_macro (const char *name
)
1094 hash_delete (macro_hash
, name
);
1097 /* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
1098 combined macro definition and execution. This returns NULL on
1099 success, or an error message otherwise. */
1102 expand_irp (int irpc
, int idx
, sb
*in
, sb
*out
, int (*get_line
) (sb
*))
1107 struct hash_control
*h
;
1115 idx
= sb_skip_white (idx
, in
);
1118 if (! buffer_and_nest (mn
, "ENDR", &sub
, get_line
))
1119 return _("unexpected end of file in irp or irpc");
1125 idx
= get_token (idx
, in
, &f
.name
);
1126 if (f
.name
.len
== 0)
1127 return _("missing model parameter");
1130 err
= hash_jam (h
, sb_terminate (&f
.name
), &f
);
1139 idx
= sb_skip_comma (idx
, in
);
1142 /* Expand once with a null string. */
1143 err
= macro_expand_body (&sub
, out
, &f
, h
, 0);
1149 if (irpc
&& in
->ptr
[idx
] == '"')
1151 while (idx
< in
->len
)
1154 idx
= get_any_string (idx
, in
, &f
.actual
, 1, 0);
1157 if (in
->ptr
[idx
] == '"')
1161 nxt
= sb_skip_white (idx
+ 1, in
);
1168 sb_reset (&f
.actual
);
1169 sb_add_char (&f
.actual
, in
->ptr
[idx
]);
1172 err
= macro_expand_body (&sub
, out
, &f
, h
, 0);
1176 idx
= sb_skip_comma (idx
, in
);
1178 idx
= sb_skip_white (idx
, in
);