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 MRI mode on the fly. */
138 macro_mri_mode (int mri
)
143 /* Read input lines till we get to a TO string.
144 Increase nesting depth if we get a FROM string.
145 Put the results into sb at PTR.
146 Add a new input line to an sb using GET_LINE.
147 Return 1 on success, 0 on unexpected EOF. */
150 buffer_and_nest (const char *from
, const char *to
, sb
*ptr
,
151 int (*get_line
) (sb
*))
153 int from_len
= strlen (from
);
154 int to_len
= strlen (to
);
156 int line_start
= ptr
->len
;
158 int more
= get_line (ptr
);
162 /* Try and find the first pseudo op on the line. */
165 if (! macro_alternate
&& ! macro_mri
)
167 /* With normal syntax we can suck what we want till we get
168 to the dot. With the alternate, labels have to start in
169 the first column, since we cant tell what's a label and
172 /* Skip leading whitespace. */
173 while (i
< ptr
->len
&& ISWHITE (ptr
->ptr
[i
]))
176 /* Skip over a label. */
178 && (ISALNUM (ptr
->ptr
[i
])
179 || ptr
->ptr
[i
] == '_'
180 || ptr
->ptr
[i
] == '$'))
185 && ptr
->ptr
[i
] == ':')
189 /* Skip trailing whitespace. */
190 while (i
< ptr
->len
&& ISWHITE (ptr
->ptr
[i
]))
193 if (i
< ptr
->len
&& (ptr
->ptr
[i
] == '.'
197 if (ptr
->ptr
[i
] == '.')
199 if (strncasecmp (ptr
->ptr
+ i
, from
, from_len
) == 0
200 && (ptr
->len
== (i
+ from_len
)
201 || ! ISALNUM (ptr
->ptr
[i
+ from_len
])))
203 if (strncasecmp (ptr
->ptr
+ i
, to
, to_len
) == 0
204 && (ptr
->len
== (i
+ to_len
)
205 || ! ISALNUM (ptr
->ptr
[i
+ to_len
])))
210 /* Reset the string to not include the ending rune. */
211 ptr
->len
= line_start
;
217 /* Add the original end-of-line char to the end and keep running. */
218 sb_add_char (ptr
, more
);
219 line_start
= ptr
->len
;
220 more
= get_line (ptr
);
223 /* Return 1 on success, 0 on unexpected EOF. */
227 /* Pick up a token. */
230 get_token (int idx
, sb
*in
, sb
*name
)
233 && (ISALPHA (in
->ptr
[idx
])
234 || in
->ptr
[idx
] == '_'
235 || in
->ptr
[idx
] == '$'))
237 sb_add_char (name
, in
->ptr
[idx
++]);
239 && (ISALNUM (in
->ptr
[idx
])
240 || in
->ptr
[idx
] == '_'
241 || in
->ptr
[idx
] == '$'))
243 sb_add_char (name
, in
->ptr
[idx
++]);
246 /* Ignore trailing &. */
247 if (macro_alternate
&& idx
< in
->len
&& in
->ptr
[idx
] == '&')
252 /* Pick up a string. */
255 getstring (int idx
, sb
*in
, sb
*acc
)
257 idx
= sb_skip_white (idx
, in
);
260 && (in
->ptr
[idx
] == '"'
261 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
262 || (in
->ptr
[idx
] == '\'' && macro_alternate
)))
264 if (in
->ptr
[idx
] == '<')
268 while ((in
->ptr
[idx
] != '>' || nest
)
271 if (in
->ptr
[idx
] == '!')
274 sb_add_char (acc
, in
->ptr
[idx
++]);
278 if (in
->ptr
[idx
] == '>')
280 if (in
->ptr
[idx
] == '<')
282 sb_add_char (acc
, in
->ptr
[idx
++]);
287 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
289 char tchar
= in
->ptr
[idx
];
294 while (idx
< in
->len
)
296 if (in
->ptr
[idx
- 1] == '\\')
301 if (macro_alternate
&& in
->ptr
[idx
] == '!')
305 sb_add_char (acc
, in
->ptr
[idx
]);
309 else if (escaped
&& in
->ptr
[idx
] == tchar
)
311 sb_add_char (acc
, tchar
);
316 if (in
->ptr
[idx
] == tchar
)
320 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
324 sb_add_char (acc
, in
->ptr
[idx
]);
334 /* Fetch string from the input stream,
336 'Bxyx<whitespace> -> return 'Bxyza
337 %<char> -> return string of decimal value of x
338 "<string>" -> return string
339 xyx<whitespace> -> return xyz
343 get_any_string (int idx
, sb
*in
, sb
*out
, int expand
, int pretend_quoted
)
346 idx
= sb_skip_white (idx
, in
);
350 if (in
->len
> idx
+ 2 && in
->ptr
[idx
+ 1] == '\'' && ISBASE (in
->ptr
[idx
]))
352 while (!ISSEP (in
->ptr
[idx
]))
353 sb_add_char (out
, in
->ptr
[idx
++]);
355 else if (in
->ptr
[idx
] == '%'
361 /* Turns the next expression into a string. */
362 /* xgettext: no-c-format */
363 idx
= (*macro_expr
) (_("% operator needs absolute expression"),
367 sprintf (buf
, "%d", val
);
368 sb_add_string (out
, buf
);
370 else if (in
->ptr
[idx
] == '"'
371 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
372 || (macro_alternate
&& in
->ptr
[idx
] == '\''))
378 /* Keep the quotes. */
379 sb_add_char (out
, '\"');
381 idx
= getstring (idx
, in
, out
);
382 sb_add_char (out
, '\"');
386 idx
= getstring (idx
, in
, out
);
392 && (in
->ptr
[idx
] == '"'
393 || in
->ptr
[idx
] == '\''
395 || (in
->ptr
[idx
] != ' '
396 && in
->ptr
[idx
] != '\t'
397 && in
->ptr
[idx
] != ','
398 && (in
->ptr
[idx
] != '<'
399 || (! macro_alternate
&& ! macro_mri
)))))
401 if (in
->ptr
[idx
] == '"'
402 || in
->ptr
[idx
] == '\'')
404 char tchar
= in
->ptr
[idx
];
405 sb_add_char (out
, in
->ptr
[idx
++]);
407 && in
->ptr
[idx
] != tchar
)
408 sb_add_char (out
, in
->ptr
[idx
++]);
412 sb_add_char (out
, in
->ptr
[idx
++]);
420 /* Pick up the formal parameters of a macro definition. */
423 do_formals (macro_entry
*macro
, int idx
, sb
*in
)
425 formal_entry
**p
= ¯o
->formals
;
427 macro
->formal_count
= 0;
428 macro
->formal_hash
= hash_new ();
429 while (idx
< in
->len
)
431 formal_entry
*formal
;
433 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
435 sb_new (&formal
->name
);
436 sb_new (&formal
->def
);
437 sb_new (&formal
->actual
);
439 idx
= sb_skip_white (idx
, in
);
440 idx
= get_token (idx
, in
, &formal
->name
);
441 if (formal
->name
.len
== 0)
443 idx
= sb_skip_white (idx
, in
);
444 if (formal
->name
.len
)
446 /* This is a formal. */
447 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
450 idx
= get_any_string (idx
+ 1, in
, &formal
->def
, 1, 0);
454 /* Add to macro's hash table. */
455 hash_jam (macro
->formal_hash
, sb_terminate (&formal
->name
), formal
);
457 formal
->index
= macro
->formal_count
;
458 idx
= sb_skip_comma (idx
, in
);
459 macro
->formal_count
++;
467 formal_entry
*formal
;
470 /* Add a special NARG formal, which macro_expand will set to the
471 number of arguments. */
472 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
474 sb_new (&formal
->name
);
475 sb_new (&formal
->def
);
476 sb_new (&formal
->actual
);
478 /* The same MRI assemblers which treat '@' characters also use
479 the name $NARG. At least until we find an exception. */
485 sb_add_string (&formal
->name
, name
);
487 /* Add to macro's hash table. */
488 hash_jam (macro
->formal_hash
, name
, formal
);
490 formal
->index
= NARG_INDEX
;
498 /* Define a new macro. Returns NULL on success, otherwise returns an
499 error message. If NAMEP is not NULL, *NAMEP is set to the name of
500 the macro which was defined. */
503 define_macro (int idx
, sb
*in
, sb
*label
,
504 int (*get_line
) (sb
*), const char **namep
)
510 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
511 sb_new (¯o
->sub
);
514 macro
->formal_count
= 0;
517 idx
= sb_skip_white (idx
, in
);
518 if (! buffer_and_nest ("MACRO", "ENDM", ¯o
->sub
, get_line
))
519 return _("unexpected end of file in macro definition");
520 if (label
!= NULL
&& label
->len
!= 0)
522 sb_add_sb (&name
, label
);
523 if (idx
< in
->len
&& in
->ptr
[idx
] == '(')
525 /* It's the label: MACRO (formals,...) sort */
526 idx
= do_formals (macro
, idx
+ 1, in
);
527 if (in
->ptr
[idx
] != ')')
528 return _("missing ) after formals");
532 /* It's the label: MACRO formals,... sort */
533 idx
= do_formals (macro
, idx
, in
);
538 idx
= get_token (idx
, in
, &name
);
539 idx
= sb_skip_comma (idx
, in
);
540 idx
= do_formals (macro
, idx
, in
);
543 /* And stick it in the macro hash table. */
544 for (idx
= 0; idx
< name
.len
; idx
++)
545 name
.ptr
[idx
] = TOLOWER (name
.ptr
[idx
]);
546 namestr
= sb_terminate (&name
);
547 hash_jam (macro_hash
, namestr
, (PTR
) macro
);
557 /* Scan a token, and then skip KIND. */
560 get_apost_token (int idx
, sb
*in
, sb
*name
, int kind
)
562 idx
= get_token (idx
, in
, name
);
564 && in
->ptr
[idx
] == kind
565 && (! macro_mri
|| macro_strip_at
)
566 && (! macro_strip_at
|| kind
== '@'))
571 /* Substitute the actual value for a formal parameter. */
574 sub_actual (int start
, sb
*in
, sb
*t
, struct hash_control
*formal_hash
,
575 int kind
, sb
*out
, int copyifnotthere
)
580 src
= get_apost_token (start
, in
, t
, kind
);
581 /* See if it's in the macro's hash table, unless this is
582 macro_strip_at and kind is '@' and the token did not end in '@'. */
585 && (src
== start
|| in
->ptr
[src
- 1] != '@'))
588 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (t
));
593 sb_add_sb (out
, &ptr
->actual
);
597 sb_add_sb (out
, &ptr
->def
);
600 else if (kind
== '&')
602 /* Doing this permits people to use & in macro bodies. */
603 sb_add_char (out
, '&');
606 else if (copyifnotthere
)
612 sb_add_char (out
, '\\');
618 /* Expand the body of a macro. */
621 macro_expand_body (sb
*in
, sb
*out
, formal_entry
*formals
,
622 struct hash_control
*formal_hash
, int locals
)
627 formal_entry
*loclist
= NULL
;
631 while (src
< in
->len
)
633 if (in
->ptr
[src
] == '&')
638 if (src
+ 1 < in
->len
&& in
->ptr
[src
+ 1] == '&')
639 src
= sub_actual (src
+ 2, in
, &t
, formal_hash
, '\'', out
, 1);
641 sb_add_char (out
, in
->ptr
[src
++]);
645 /* FIXME: Why do we do this? */
646 src
= sub_actual (src
+ 1, in
, &t
, formal_hash
, '&', out
, 0);
649 else if (in
->ptr
[src
] == '\\')
652 if (in
->ptr
[src
] == '(')
654 /* Sub in till the next ')' literally. */
656 while (src
< in
->len
&& in
->ptr
[src
] != ')')
658 sb_add_char (out
, in
->ptr
[src
++]);
660 if (in
->ptr
[src
] == ')')
663 return _("missplaced )");
665 else if (in
->ptr
[src
] == '@')
667 /* Sub in the macro invocation number. */
671 sprintf (buffer
, "%d", macro_number
);
672 sb_add_string (out
, buffer
);
674 else if (in
->ptr
[src
] == '&')
676 /* This is a preprocessor variable name, we don't do them
678 sb_add_char (out
, '\\');
679 sb_add_char (out
, '&');
682 else if (macro_mri
&& ISALNUM (in
->ptr
[src
]))
687 if (ISDIGIT (in
->ptr
[src
]))
688 ind
= in
->ptr
[src
] - '0';
689 else if (ISUPPER (in
->ptr
[src
]))
690 ind
= in
->ptr
[src
] - 'A' + 10;
692 ind
= in
->ptr
[src
] - 'a' + 10;
694 for (f
= formals
; f
!= NULL
; f
= f
->next
)
696 if (f
->index
== ind
- 1)
698 if (f
->actual
.len
!= 0)
699 sb_add_sb (out
, &f
->actual
);
701 sb_add_sb (out
, &f
->def
);
709 src
= sub_actual (src
, in
, &t
, formal_hash
, '\'', out
, 0);
712 else if ((macro_alternate
|| macro_mri
)
713 && (ISALPHA (in
->ptr
[src
])
714 || in
->ptr
[src
] == '_'
715 || in
->ptr
[src
] == '$')
718 || (src
> 0 && in
->ptr
[src
- 1] == '@')))
721 || src
+ 5 >= in
->len
722 || strncasecmp (in
->ptr
+ src
, "LOCAL", 5) != 0
723 || ! ISWHITE (in
->ptr
[src
+ 5]))
726 src
= sub_actual (src
, in
, &t
, formal_hash
,
727 (macro_strip_at
&& inquote
) ? '@' : '\'',
734 src
= sb_skip_white (src
+ 5, in
);
735 while (in
->ptr
[src
] != '\n')
741 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
745 f
->index
= LOCAL_INDEX
;
749 src
= get_token (src
, in
, &f
->name
);
751 sprintf (buf
, "LL%04x", loccnt
);
752 sb_add_string (&f
->actual
, buf
);
754 err
= hash_jam (formal_hash
, sb_terminate (&f
->name
), f
);
758 src
= sb_skip_comma (src
, in
);
762 else if (in
->ptr
[src
] == '"'
763 || (macro_mri
&& in
->ptr
[src
] == '\''))
766 sb_add_char (out
, in
->ptr
[src
++]);
768 else if (in
->ptr
[src
] == '@' && macro_strip_at
)
772 && in
->ptr
[src
] == '@')
774 sb_add_char (out
, '@');
779 && in
->ptr
[src
] == '='
781 && in
->ptr
[src
+ 1] == '=')
786 src
= get_token (src
+ 2, in
, &t
);
787 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (&t
));
790 /* FIXME: We should really return a warning string here,
791 but we can't, because the == might be in the MRI
792 comment field, and, since the nature of the MRI
793 comment field depends upon the exact instruction
794 being used, we don't have enough information here to
795 figure out whether it is or not. Instead, we leave
796 the == in place, which should cause a syntax error if
797 it is not in a comment. */
798 sb_add_char (out
, '=');
799 sb_add_char (out
, '=');
806 sb_add_string (out
, "-1");
810 sb_add_char (out
, '0');
816 sb_add_char (out
, in
->ptr
[src
++]);
822 while (loclist
!= NULL
)
827 /* Setting the value to NULL effectively deletes the entry. We
828 avoid calling hash_delete because it doesn't reclaim memory. */
829 hash_jam (formal_hash
, sb_terminate (&loclist
->name
), NULL
);
830 sb_kill (&loclist
->name
);
831 sb_kill (&loclist
->def
);
832 sb_kill (&loclist
->actual
);
840 /* Assign values to the formal parameters of a macro, and expand the
844 macro_expand (int idx
, sb
*in
, macro_entry
*m
, sb
*out
)
849 int is_positional
= 0;
856 /* Reset any old value the actuals may have. */
857 for (f
= m
->formals
; f
; f
= f
->next
)
858 sb_reset (&f
->actual
);
860 while (f
!= NULL
&& f
->index
< 0)
865 /* The macro may be called with an optional qualifier, which may
866 be referred to in the macro body as \0. */
867 if (idx
< in
->len
&& in
->ptr
[idx
] == '.')
869 /* The Microtec assembler ignores this if followed by a white space.
870 (Macro invocation with empty extension) */
873 && in
->ptr
[idx
] != ' '
874 && in
->ptr
[idx
] != '\t')
878 n
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
882 n
->index
= QUAL_INDEX
;
884 n
->next
= m
->formals
;
887 idx
= get_any_string (idx
, in
, &n
->actual
, 1, 0);
892 /* Peel off the actuals and store them away in the hash tables' actuals. */
893 idx
= sb_skip_white (idx
, in
);
894 while (idx
< in
->len
)
898 /* Look and see if it's a positional or keyword arg. */
900 while (scan
< in
->len
901 && !ISSEP (in
->ptr
[scan
])
902 && !(macro_mri
&& in
->ptr
[scan
] == '\'')
903 && (!macro_alternate
&& in
->ptr
[scan
] != '='))
905 if (scan
< in
->len
&& !macro_alternate
&& in
->ptr
[scan
] == '=')
909 /* It's OK to go from positional to keyword. */
911 /* This is a keyword arg, fetch the formal name and
912 then the actual stuff. */
914 idx
= get_token (idx
, in
, &t
);
915 if (in
->ptr
[idx
] != '=')
916 return _("confusion in formal parameters");
918 /* Lookup the formal in the macro's list. */
919 ptr
= (formal_entry
*) hash_find (m
->formal_hash
, sb_terminate (&t
));
921 return _("macro formal argument does not exist");
924 /* Insert this value into the right place. */
925 sb_reset (&ptr
->actual
);
926 idx
= get_any_string (idx
+ 1, in
, &ptr
->actual
, 0, 0);
927 if (ptr
->actual
.len
> 0)
933 /* This is a positional arg. */
936 return _("can't mix positional and keyword arguments");
944 return _("too many positional arguments");
946 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
953 for (pf
= &m
->formals
; *pf
!= NULL
; pf
= &(*pf
)->next
)
954 if ((*pf
)->index
>= c
)
955 c
= (*pf
)->index
+ 1;
962 sb_reset (&f
->actual
);
963 idx
= get_any_string (idx
, in
, &f
->actual
, 1, 0);
964 if (f
->actual
.len
> 0)
970 while (f
!= NULL
&& f
->index
< 0);
974 idx
= sb_skip_comma (idx
, in
);
977 if (in
->ptr
[idx
] == ',')
979 if (ISWHITE (in
->ptr
[idx
]))
989 sb_add_string (&t
, macro_strip_at
? "$NARG" : "NARG");
990 ptr
= (formal_entry
*) hash_find (m
->formal_hash
, sb_terminate (&t
));
991 sb_reset (&ptr
->actual
);
992 sprintf (buffer
, "%d", narg
);
993 sb_add_string (&ptr
->actual
, buffer
);
996 err
= macro_expand_body (&m
->sub
, out
, m
->formals
, m
->formal_hash
, 1);
1000 /* Discard any unnamed formal arguments. */
1008 if ((*pf
)->name
.len
!= 0)
1012 sb_kill (&(*pf
)->name
);
1013 sb_kill (&(*pf
)->def
);
1014 sb_kill (&(*pf
)->actual
);
1028 /* Check for a macro. If one is found, put the expansion into
1029 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
1032 check_macro (const char *line
, sb
*expand
,
1033 const char **error
, macro_entry
**info
)
1040 if (! ISALPHA (*line
)
1043 && (! macro_mri
|| *line
!= '.'))
1052 copy
= (char *) alloca (s
- line
+ 1);
1053 memcpy (copy
, line
, s
- line
);
1054 copy
[s
- line
] = '\0';
1055 for (cs
= copy
; *cs
!= '\0'; cs
++)
1056 *cs
= TOLOWER (*cs
);
1058 macro
= (macro_entry
*) hash_find (macro_hash
, copy
);
1063 /* Wrap the line up in an sb. */
1065 while (*s
!= '\0' && *s
!= '\n' && *s
!= '\r')
1066 sb_add_char (&line_sb
, *s
++);
1069 *error
= macro_expand (0, &line_sb
, macro
, expand
);
1073 /* Export the macro information if requested. */
1080 /* Delete a macro. */
1083 delete_macro (const char *name
)
1085 hash_delete (macro_hash
, name
);
1088 /* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
1089 combined macro definition and execution. This returns NULL on
1090 success, or an error message otherwise. */
1093 expand_irp (int irpc
, int idx
, sb
*in
, sb
*out
, int (*get_line
) (sb
*))
1098 struct hash_control
*h
;
1106 idx
= sb_skip_white (idx
, in
);
1109 if (! buffer_and_nest (mn
, "ENDR", &sub
, get_line
))
1110 return _("unexpected end of file in irp or irpc");
1116 idx
= get_token (idx
, in
, &f
.name
);
1117 if (f
.name
.len
== 0)
1118 return _("missing model parameter");
1121 err
= hash_jam (h
, sb_terminate (&f
.name
), &f
);
1130 idx
= sb_skip_comma (idx
, in
);
1133 /* Expand once with a null string. */
1134 err
= macro_expand_body (&sub
, out
, &f
, h
, 0);
1140 if (irpc
&& in
->ptr
[idx
] == '"')
1142 while (idx
< in
->len
)
1145 idx
= get_any_string (idx
, in
, &f
.actual
, 1, 0);
1148 if (in
->ptr
[idx
] == '"')
1152 nxt
= sb_skip_white (idx
+ 1, in
);
1159 sb_reset (&f
.actual
);
1160 sb_add_char (&f
.actual
, in
->ptr
[idx
]);
1163 err
= macro_expand_body (&sub
, out
, &f
, h
, 0);
1167 idx
= sb_skip_comma (idx
, in
);
1169 idx
= sb_skip_white (idx
, in
);
This page took 0.053537 seconds and 4 git commands to generate.