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
PARAMS ((int, sb
*, sb
*));
71 static int getstring
PARAMS ((int, sb
*, sb
*));
72 static int get_any_string
PARAMS ((int, sb
*, sb
*, int, int));
73 static int do_formals
PARAMS ((macro_entry
*, int, sb
*));
74 static int get_apost_token
PARAMS ((int, sb
*, sb
*, int));
76 PARAMS ((int, sb
*, sb
*, struct hash_control
*, int, sb
*, int));
77 static const char *macro_expand_body
78 PARAMS ((sb
*, sb
*, formal_entry
*, struct hash_control
*, int));
79 static const char *macro_expand
PARAMS ((int, sb
*, macro_entry
*, sb
*));
81 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
84 ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
85 || (x) == ')' || (x) == '(' \
86 || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
89 ((x) == 'b' || (x) == 'B' \
90 || (x) == 'q' || (x) == 'Q' \
91 || (x) == 'h' || (x) == 'H' \
92 || (x) == 'd' || (x) == 'D')
94 /* The macro hash table. */
96 struct hash_control
*macro_hash
;
98 /* Whether any macros have been defined. */
102 /* Whether we are in alternate syntax mode. */
104 static int macro_alternate
;
106 /* Whether we are in MRI mode. */
108 static int macro_mri
;
110 /* Whether we should strip '@' characters. */
112 static int macro_strip_at
;
114 /* Function to use to parse an expression. */
116 static int (*macro_expr
) PARAMS ((const char *, int, sb
*, int *));
118 /* Number of macro expansions that have been done. */
120 static int macro_number
;
122 /* Initialize macro processing. */
125 macro_init (alternate
, mri
, strip_at
, expr
)
129 int (*expr
) PARAMS ((const char *, int, sb
*, int *));
131 macro_hash
= hash_new ();
133 macro_alternate
= alternate
;
135 macro_strip_at
= strip_at
;
139 /* Switch in and out of MRI mode on the fly. */
148 /* Read input lines till we get to a TO string.
149 Increase nesting depth if we get a FROM string.
150 Put the results into sb at PTR.
151 Add a new input line to an sb using GET_LINE.
152 Return 1 on success, 0 on unexpected EOF. */
155 buffer_and_nest (from
, to
, ptr
, get_line
)
159 int (*get_line
) PARAMS ((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 (idx
, in
, name
)
244 && (ISALPHA (in
->ptr
[idx
])
245 || in
->ptr
[idx
] == '_'
246 || in
->ptr
[idx
] == '$'))
248 sb_add_char (name
, in
->ptr
[idx
++]);
250 && (ISALNUM (in
->ptr
[idx
])
251 || in
->ptr
[idx
] == '_'
252 || in
->ptr
[idx
] == '$'))
254 sb_add_char (name
, in
->ptr
[idx
++]);
257 /* Ignore trailing &. */
258 if (macro_alternate
&& idx
< in
->len
&& in
->ptr
[idx
] == '&')
263 /* Pick up a string. */
266 getstring (idx
, in
, acc
)
271 idx
= sb_skip_white (idx
, in
);
274 && (in
->ptr
[idx
] == '"'
275 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
276 || (in
->ptr
[idx
] == '\'' && macro_alternate
)))
278 if (in
->ptr
[idx
] == '<')
282 while ((in
->ptr
[idx
] != '>' || nest
)
285 if (in
->ptr
[idx
] == '!')
288 sb_add_char (acc
, in
->ptr
[idx
++]);
292 if (in
->ptr
[idx
] == '>')
294 if (in
->ptr
[idx
] == '<')
296 sb_add_char (acc
, in
->ptr
[idx
++]);
301 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
303 char tchar
= in
->ptr
[idx
];
308 while (idx
< in
->len
)
310 if (in
->ptr
[idx
- 1] == '\\')
315 if (macro_alternate
&& in
->ptr
[idx
] == '!')
319 sb_add_char (acc
, in
->ptr
[idx
]);
323 else if (escaped
&& in
->ptr
[idx
] == tchar
)
325 sb_add_char (acc
, tchar
);
330 if (in
->ptr
[idx
] == tchar
)
334 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
338 sb_add_char (acc
, in
->ptr
[idx
]);
348 /* Fetch string from the input stream,
350 'Bxyx<whitespace> -> return 'Bxyza
351 %<char> -> return string of decimal value of x
352 "<string>" -> return string
353 xyx<whitespace> -> return xyz
357 get_any_string (idx
, in
, out
, expand
, pretend_quoted
)
365 idx
= sb_skip_white (idx
, in
);
369 if (in
->len
> idx
+ 2 && in
->ptr
[idx
+ 1] == '\'' && ISBASE (in
->ptr
[idx
]))
371 while (!ISSEP (in
->ptr
[idx
]))
372 sb_add_char (out
, in
->ptr
[idx
++]);
374 else if (in
->ptr
[idx
] == '%'
380 /* Turns the next expression into a string. */
381 /* xgettext: no-c-format */
382 idx
= (*macro_expr
) (_("% operator needs absolute expression"),
386 sprintf (buf
, "%d", val
);
387 sb_add_string (out
, buf
);
389 else if (in
->ptr
[idx
] == '"'
390 || (in
->ptr
[idx
] == '<' && (macro_alternate
|| macro_mri
))
391 || (macro_alternate
&& in
->ptr
[idx
] == '\''))
397 /* Keep the quotes. */
398 sb_add_char (out
, '\"');
400 idx
= getstring (idx
, in
, out
);
401 sb_add_char (out
, '\"');
405 idx
= getstring (idx
, in
, out
);
411 && (in
->ptr
[idx
] == '"'
412 || in
->ptr
[idx
] == '\''
414 || (in
->ptr
[idx
] != ' '
415 && in
->ptr
[idx
] != '\t'
416 && in
->ptr
[idx
] != ','
417 && (in
->ptr
[idx
] != '<'
418 || (! macro_alternate
&& ! macro_mri
)))))
420 if (in
->ptr
[idx
] == '"'
421 || in
->ptr
[idx
] == '\'')
423 char tchar
= in
->ptr
[idx
];
424 sb_add_char (out
, in
->ptr
[idx
++]);
426 && in
->ptr
[idx
] != tchar
)
427 sb_add_char (out
, in
->ptr
[idx
++]);
431 sb_add_char (out
, in
->ptr
[idx
++]);
439 /* Pick up the formal parameters of a macro definition. */
442 do_formals (macro
, idx
, in
)
447 formal_entry
**p
= ¯o
->formals
;
449 macro
->formal_count
= 0;
450 macro
->formal_hash
= hash_new ();
451 while (idx
< in
->len
)
453 formal_entry
*formal
;
455 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
457 sb_new (&formal
->name
);
458 sb_new (&formal
->def
);
459 sb_new (&formal
->actual
);
461 idx
= sb_skip_white (idx
, in
);
462 idx
= get_token (idx
, in
, &formal
->name
);
463 if (formal
->name
.len
== 0)
465 idx
= sb_skip_white (idx
, in
);
466 if (formal
->name
.len
)
468 /* This is a formal. */
469 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
472 idx
= get_any_string (idx
+ 1, in
, &formal
->def
, 1, 0);
476 /* Add to macro's hash table. */
477 hash_jam (macro
->formal_hash
, sb_terminate (&formal
->name
), formal
);
479 formal
->index
= macro
->formal_count
;
480 idx
= sb_skip_comma (idx
, in
);
481 macro
->formal_count
++;
489 formal_entry
*formal
;
492 /* Add a special NARG formal, which macro_expand will set to the
493 number of arguments. */
494 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
496 sb_new (&formal
->name
);
497 sb_new (&formal
->def
);
498 sb_new (&formal
->actual
);
500 /* The same MRI assemblers which treat '@' characters also use
501 the name $NARG. At least until we find an exception. */
507 sb_add_string (&formal
->name
, name
);
509 /* Add to macro's hash table. */
510 hash_jam (macro
->formal_hash
, name
, formal
);
512 formal
->index
= NARG_INDEX
;
520 /* Define a new macro. Returns NULL on success, otherwise returns an
521 error message. If NAMEP is not NULL, *NAMEP is set to the name of
522 the macro which was defined. */
525 define_macro (idx
, in
, label
, get_line
, namep
)
529 int (*get_line
) PARAMS ((sb
*));
536 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
537 sb_new (¯o
->sub
);
540 macro
->formal_count
= 0;
543 idx
= sb_skip_white (idx
, in
);
544 if (! buffer_and_nest ("MACRO", "ENDM", ¯o
->sub
, get_line
))
545 return _("unexpected end of file in macro definition");
546 if (label
!= NULL
&& label
->len
!= 0)
548 sb_add_sb (&name
, label
);
549 if (idx
< in
->len
&& in
->ptr
[idx
] == '(')
551 /* It's the label: MACRO (formals,...) sort */
552 idx
= do_formals (macro
, idx
+ 1, in
);
553 if (in
->ptr
[idx
] != ')')
554 return _("missing ) after formals");
558 /* It's the label: MACRO formals,... sort */
559 idx
= do_formals (macro
, idx
, in
);
564 idx
= get_token (idx
, in
, &name
);
565 idx
= sb_skip_comma (idx
, in
);
566 idx
= do_formals (macro
, idx
, in
);
569 /* And stick it in the macro hash table. */
570 for (idx
= 0; idx
< name
.len
; idx
++)
571 name
.ptr
[idx
] = TOLOWER (name
.ptr
[idx
]);
572 namestr
= sb_terminate (&name
);
573 hash_jam (macro_hash
, namestr
, (PTR
) macro
);
583 /* Scan a token, and then skip KIND. */
586 get_apost_token (idx
, in
, name
, kind
)
592 idx
= get_token (idx
, in
, name
);
594 && in
->ptr
[idx
] == kind
595 && (! macro_mri
|| macro_strip_at
)
596 && (! macro_strip_at
|| kind
== '@'))
601 /* Substitute the actual value for a formal parameter. */
604 sub_actual (start
, in
, t
, formal_hash
, kind
, out
, copyifnotthere
)
608 struct hash_control
*formal_hash
;
616 src
= get_apost_token (start
, in
, t
, kind
);
617 /* See if it's in the macro's hash table, unless this is
618 macro_strip_at and kind is '@' and the token did not end in '@'. */
621 && (src
== start
|| in
->ptr
[src
- 1] != '@'))
624 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (t
));
629 sb_add_sb (out
, &ptr
->actual
);
633 sb_add_sb (out
, &ptr
->def
);
636 else if (kind
== '&')
638 /* Doing this permits people to use & in macro bodies. */
639 sb_add_char (out
, '&');
642 else if (copyifnotthere
)
648 sb_add_char (out
, '\\');
654 /* Expand the body of a macro. */
657 macro_expand_body (in
, out
, formals
, formal_hash
, locals
)
660 formal_entry
*formals
;
661 struct hash_control
*formal_hash
;
667 formal_entry
*loclist
= NULL
;
671 while (src
< in
->len
)
673 if (in
->ptr
[src
] == '&')
678 if (src
+ 1 < in
->len
&& in
->ptr
[src
+ 1] == '&')
679 src
= sub_actual (src
+ 2, in
, &t
, formal_hash
, '\'', out
, 1);
681 sb_add_char (out
, in
->ptr
[src
++]);
685 /* FIXME: Why do we do this? */
686 src
= sub_actual (src
+ 1, in
, &t
, formal_hash
, '&', out
, 0);
689 else if (in
->ptr
[src
] == '\\')
692 if (in
->ptr
[src
] == '(')
694 /* Sub in till the next ')' literally. */
696 while (src
< in
->len
&& in
->ptr
[src
] != ')')
698 sb_add_char (out
, in
->ptr
[src
++]);
700 if (in
->ptr
[src
] == ')')
703 return _("missplaced )");
705 else if (in
->ptr
[src
] == '@')
707 /* Sub in the macro invocation number. */
711 sprintf (buffer
, "%d", macro_number
);
712 sb_add_string (out
, buffer
);
714 else if (in
->ptr
[src
] == '&')
716 /* This is a preprocessor variable name, we don't do them
718 sb_add_char (out
, '\\');
719 sb_add_char (out
, '&');
722 else if (macro_mri
&& ISALNUM (in
->ptr
[src
]))
727 if (ISDIGIT (in
->ptr
[src
]))
728 ind
= in
->ptr
[src
] - '0';
729 else if (ISUPPER (in
->ptr
[src
]))
730 ind
= in
->ptr
[src
] - 'A' + 10;
732 ind
= in
->ptr
[src
] - 'a' + 10;
734 for (f
= formals
; f
!= NULL
; f
= f
->next
)
736 if (f
->index
== ind
- 1)
738 if (f
->actual
.len
!= 0)
739 sb_add_sb (out
, &f
->actual
);
741 sb_add_sb (out
, &f
->def
);
749 src
= sub_actual (src
, in
, &t
, formal_hash
, '\'', out
, 0);
752 else if ((macro_alternate
|| macro_mri
)
753 && (ISALPHA (in
->ptr
[src
])
754 || in
->ptr
[src
] == '_'
755 || in
->ptr
[src
] == '$')
758 || (src
> 0 && in
->ptr
[src
- 1] == '@')))
761 || src
+ 5 >= in
->len
762 || strncasecmp (in
->ptr
+ src
, "LOCAL", 5) != 0
763 || ! ISWHITE (in
->ptr
[src
+ 5]))
766 src
= sub_actual (src
, in
, &t
, formal_hash
,
767 (macro_strip_at
&& inquote
) ? '@' : '\'',
774 src
= sb_skip_white (src
+ 5, in
);
775 while (in
->ptr
[src
] != '\n')
781 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
785 f
->index
= LOCAL_INDEX
;
789 src
= get_token (src
, in
, &f
->name
);
791 sprintf (buf
, "LL%04x", loccnt
);
792 sb_add_string (&f
->actual
, buf
);
794 err
= hash_jam (formal_hash
, sb_terminate (&f
->name
), f
);
798 src
= sb_skip_comma (src
, in
);
802 else if (in
->ptr
[src
] == '"'
803 || (macro_mri
&& in
->ptr
[src
] == '\''))
806 sb_add_char (out
, in
->ptr
[src
++]);
808 else if (in
->ptr
[src
] == '@' && macro_strip_at
)
812 && in
->ptr
[src
] == '@')
814 sb_add_char (out
, '@');
819 && in
->ptr
[src
] == '='
821 && in
->ptr
[src
+ 1] == '=')
826 src
= get_token (src
+ 2, in
, &t
);
827 ptr
= (formal_entry
*) hash_find (formal_hash
, sb_terminate (&t
));
830 /* FIXME: We should really return a warning string here,
831 but we can't, because the == might be in the MRI
832 comment field, and, since the nature of the MRI
833 comment field depends upon the exact instruction
834 being used, we don't have enough information here to
835 figure out whether it is or not. Instead, we leave
836 the == in place, which should cause a syntax error if
837 it is not in a comment. */
838 sb_add_char (out
, '=');
839 sb_add_char (out
, '=');
846 sb_add_string (out
, "-1");
850 sb_add_char (out
, '0');
856 sb_add_char (out
, in
->ptr
[src
++]);
862 while (loclist
!= NULL
)
867 /* Setting the value to NULL effectively deletes the entry. We
868 avoid calling hash_delete because it doesn't reclaim memory. */
869 hash_jam (formal_hash
, sb_terminate (&loclist
->name
), NULL
);
870 sb_kill (&loclist
->name
);
871 sb_kill (&loclist
->def
);
872 sb_kill (&loclist
->actual
);
880 /* Assign values to the formal parameters of a macro, and expand the
884 macro_expand (idx
, in
, m
, out
)
893 int is_positional
= 0;
900 /* Reset any old value the actuals may have. */
901 for (f
= m
->formals
; f
; f
= f
->next
)
902 sb_reset (&f
->actual
);
904 while (f
!= NULL
&& f
->index
< 0)
909 /* The macro may be called with an optional qualifier, which may
910 be referred to in the macro body as \0. */
911 if (idx
< in
->len
&& in
->ptr
[idx
] == '.')
913 /* The Microtec assembler ignores this if followed by a white space.
914 (Macro invocation with empty extension) */
917 && in
->ptr
[idx
] != ' '
918 && in
->ptr
[idx
] != '\t')
922 n
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
926 n
->index
= QUAL_INDEX
;
928 n
->next
= m
->formals
;
931 idx
= get_any_string (idx
, in
, &n
->actual
, 1, 0);
936 /* Peel off the actuals and store them away in the hash tables' actuals. */
937 idx
= sb_skip_white (idx
, in
);
938 while (idx
< in
->len
)
942 /* Look and see if it's a positional or keyword arg. */
944 while (scan
< in
->len
945 && !ISSEP (in
->ptr
[scan
])
946 && !(macro_mri
&& in
->ptr
[scan
] == '\'')
947 && (!macro_alternate
&& in
->ptr
[scan
] != '='))
949 if (scan
< in
->len
&& !macro_alternate
&& in
->ptr
[scan
] == '=')
953 /* It's OK to go from positional to keyword. */
955 /* This is a keyword arg, fetch the formal name and
956 then the actual stuff. */
958 idx
= get_token (idx
, in
, &t
);
959 if (in
->ptr
[idx
] != '=')
960 return _("confusion in formal parameters");
962 /* Lookup the formal in the macro's list. */
963 ptr
= (formal_entry
*) hash_find (m
->formal_hash
, sb_terminate (&t
));
965 return _("macro formal argument does not exist");
968 /* Insert this value into the right place. */
969 sb_reset (&ptr
->actual
);
970 idx
= get_any_string (idx
+ 1, in
, &ptr
->actual
, 0, 0);
971 if (ptr
->actual
.len
> 0)
977 /* This is a positional arg. */
980 return _("can't mix positional and keyword arguments");
988 return _("too many positional arguments");
990 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
997 for (pf
= &m
->formals
; *pf
!= NULL
; pf
= &(*pf
)->next
)
998 if ((*pf
)->index
>= c
)
999 c
= (*pf
)->index
+ 1;
1006 sb_reset (&f
->actual
);
1007 idx
= get_any_string (idx
, in
, &f
->actual
, 1, 0);
1008 if (f
->actual
.len
> 0)
1014 while (f
!= NULL
&& f
->index
< 0);
1018 idx
= sb_skip_comma (idx
, in
);
1021 if (in
->ptr
[idx
] == ',')
1023 if (ISWHITE (in
->ptr
[idx
]))
1033 sb_add_string (&t
, macro_strip_at
? "$NARG" : "NARG");
1034 ptr
= (formal_entry
*) hash_find (m
->formal_hash
, sb_terminate (&t
));
1035 sb_reset (&ptr
->actual
);
1036 sprintf (buffer
, "%d", narg
);
1037 sb_add_string (&ptr
->actual
, buffer
);
1040 err
= macro_expand_body (&m
->sub
, out
, m
->formals
, m
->formal_hash
, 1);
1044 /* Discard any unnamed formal arguments. */
1052 if ((*pf
)->name
.len
!= 0)
1056 sb_kill (&(*pf
)->name
);
1057 sb_kill (&(*pf
)->def
);
1058 sb_kill (&(*pf
)->actual
);
1072 /* Check for a macro. If one is found, put the expansion into
1073 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
1076 check_macro (line
, expand
, error
, info
)
1087 if (! ISALPHA (*line
)
1090 && (! macro_mri
|| *line
!= '.'))
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 *cs
= TOLOWER (*cs
);
1105 macro
= (macro_entry
*) hash_find (macro_hash
, copy
);
1110 /* Wrap the line up in an sb. */
1112 while (*s
!= '\0' && *s
!= '\n' && *s
!= '\r')
1113 sb_add_char (&line_sb
, *s
++);
1116 *error
= macro_expand (0, &line_sb
, macro
, expand
);
1120 /* Export the macro information if requested. */
1127 /* Delete a macro. */
1133 hash_delete (macro_hash
, name
);
1136 /* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
1137 combined macro definition and execution. This returns NULL on
1138 success, or an error message otherwise. */
1141 expand_irp (irpc
, idx
, in
, out
, get_line
)
1146 int (*get_line
) PARAMS ((sb
*));
1151 struct hash_control
*h
;
1159 idx
= sb_skip_white (idx
, in
);
1162 if (! buffer_and_nest (mn
, "ENDR", &sub
, get_line
))
1163 return _("unexpected end of file in irp or irpc");
1169 idx
= get_token (idx
, in
, &f
.name
);
1170 if (f
.name
.len
== 0)
1171 return _("missing model parameter");
1174 err
= hash_jam (h
, sb_terminate (&f
.name
), &f
);
1183 idx
= sb_skip_comma (idx
, in
);
1186 /* Expand once with a null string. */
1187 err
= macro_expand_body (&sub
, out
, &f
, h
, 0);
1193 if (irpc
&& in
->ptr
[idx
] == '"')
1195 while (idx
< in
->len
)
1198 idx
= get_any_string (idx
, in
, &f
.actual
, 1, 0);
1201 if (in
->ptr
[idx
] == '"')
1205 nxt
= sb_skip_white (idx
+ 1, in
);
1212 sb_reset (&f
.actual
);
1213 sb_add_char (&f
.actual
, in
->ptr
[idx
]);
1216 err
= macro_expand_body (&sub
, out
, &f
, h
, 0);
1220 idx
= sb_skip_comma (idx
, in
);
1222 idx
= sb_skip_white (idx
, in
);
This page took 0.053935 seconds and 4 git commands to generate.