1*3d8817e4Smiod /* macro.c - macro support for gas
2*3d8817e4Smiod Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3*3d8817e4Smiod 2004, 2005 Free Software Foundation, Inc.
4*3d8817e4Smiod
5*3d8817e4Smiod Written by Steve and Judy Chamberlain of Cygnus Support,
6*3d8817e4Smiod sac@cygnus.com
7*3d8817e4Smiod
8*3d8817e4Smiod This file is part of GAS, the GNU Assembler.
9*3d8817e4Smiod
10*3d8817e4Smiod GAS is free software; you can redistribute it and/or modify
11*3d8817e4Smiod it under the terms of the GNU General Public License as published by
12*3d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
13*3d8817e4Smiod any later version.
14*3d8817e4Smiod
15*3d8817e4Smiod GAS is distributed in the hope that it will be useful,
16*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
17*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18*3d8817e4Smiod GNU General Public License for more details.
19*3d8817e4Smiod
20*3d8817e4Smiod You should have received a copy of the GNU General Public License
21*3d8817e4Smiod along with GAS; see the file COPYING. If not, write to the Free
22*3d8817e4Smiod Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
23*3d8817e4Smiod 02110-1301, USA. */
24*3d8817e4Smiod
25*3d8817e4Smiod #include "config.h"
26*3d8817e4Smiod
27*3d8817e4Smiod #ifndef __GNUC__
28*3d8817e4Smiod # if HAVE_ALLOCA_H
29*3d8817e4Smiod # include <alloca.h>
30*3d8817e4Smiod # else
31*3d8817e4Smiod # ifdef _AIX
32*3d8817e4Smiod /* Indented so that pre-ansi C compilers will ignore it, rather than
33*3d8817e4Smiod choke on it. Some versions of AIX require this to be the first
34*3d8817e4Smiod thing in the file. */
35*3d8817e4Smiod #pragma alloca
36*3d8817e4Smiod # else
37*3d8817e4Smiod # ifndef alloca /* predefined by HP cc +Olibcalls */
38*3d8817e4Smiod # if !defined (__STDC__) && !defined (__hpux)
39*3d8817e4Smiod extern char *alloca ();
40*3d8817e4Smiod # else
41*3d8817e4Smiod extern void *alloca ();
42*3d8817e4Smiod # endif /* __STDC__, __hpux */
43*3d8817e4Smiod # endif /* alloca */
44*3d8817e4Smiod # endif /* _AIX */
45*3d8817e4Smiod # endif /* HAVE_ALLOCA_H */
46*3d8817e4Smiod #endif /* __GNUC__ */
47*3d8817e4Smiod
48*3d8817e4Smiod #include <stdio.h>
49*3d8817e4Smiod #ifdef HAVE_STRING_H
50*3d8817e4Smiod #include <string.h>
51*3d8817e4Smiod #else
52*3d8817e4Smiod #include <strings.h>
53*3d8817e4Smiod #endif
54*3d8817e4Smiod #ifdef HAVE_STDLIB_H
55*3d8817e4Smiod #include <stdlib.h>
56*3d8817e4Smiod #endif
57*3d8817e4Smiod #include "as.h"
58*3d8817e4Smiod #include "libiberty.h"
59*3d8817e4Smiod #include "safe-ctype.h"
60*3d8817e4Smiod #include "sb.h"
61*3d8817e4Smiod #include "hash.h"
62*3d8817e4Smiod #include "macro.h"
63*3d8817e4Smiod
64*3d8817e4Smiod #include "asintl.h"
65*3d8817e4Smiod
66*3d8817e4Smiod /* The routines in this file handle macro definition and expansion.
67*3d8817e4Smiod They are called by gas. */
68*3d8817e4Smiod
69*3d8817e4Smiod /* Internal functions. */
70*3d8817e4Smiod
71*3d8817e4Smiod static int get_token (int, sb *, sb *);
72*3d8817e4Smiod static int getstring (int, sb *, sb *);
73*3d8817e4Smiod static int get_any_string (int, sb *, sb *);
74*3d8817e4Smiod static formal_entry *new_formal (void);
75*3d8817e4Smiod static void del_formal (formal_entry *);
76*3d8817e4Smiod static int do_formals (macro_entry *, int, sb *);
77*3d8817e4Smiod static int get_apost_token (int, sb *, sb *, int);
78*3d8817e4Smiod static int sub_actual (int, sb *, sb *, struct hash_control *, int, sb *, int);
79*3d8817e4Smiod static const char *macro_expand_body
80*3d8817e4Smiod (sb *, sb *, formal_entry *, struct hash_control *, const macro_entry *);
81*3d8817e4Smiod static const char *macro_expand (int, sb *, macro_entry *, sb *);
82*3d8817e4Smiod static void free_macro(macro_entry *);
83*3d8817e4Smiod
84*3d8817e4Smiod #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
85*3d8817e4Smiod
86*3d8817e4Smiod #define ISSEP(x) \
87*3d8817e4Smiod ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
88*3d8817e4Smiod || (x) == ')' || (x) == '(' \
89*3d8817e4Smiod || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
90*3d8817e4Smiod
91*3d8817e4Smiod #define ISBASE(x) \
92*3d8817e4Smiod ((x) == 'b' || (x) == 'B' \
93*3d8817e4Smiod || (x) == 'q' || (x) == 'Q' \
94*3d8817e4Smiod || (x) == 'h' || (x) == 'H' \
95*3d8817e4Smiod || (x) == 'd' || (x) == 'D')
96*3d8817e4Smiod
97*3d8817e4Smiod /* The macro hash table. */
98*3d8817e4Smiod
99*3d8817e4Smiod struct hash_control *macro_hash;
100*3d8817e4Smiod
101*3d8817e4Smiod /* Whether any macros have been defined. */
102*3d8817e4Smiod
103*3d8817e4Smiod int macro_defined;
104*3d8817e4Smiod
105*3d8817e4Smiod /* Whether we are in alternate syntax mode. */
106*3d8817e4Smiod
107*3d8817e4Smiod static int macro_alternate;
108*3d8817e4Smiod
109*3d8817e4Smiod /* Whether we are in MRI mode. */
110*3d8817e4Smiod
111*3d8817e4Smiod static int macro_mri;
112*3d8817e4Smiod
113*3d8817e4Smiod /* Whether we should strip '@' characters. */
114*3d8817e4Smiod
115*3d8817e4Smiod static int macro_strip_at;
116*3d8817e4Smiod
117*3d8817e4Smiod /* Function to use to parse an expression. */
118*3d8817e4Smiod
119*3d8817e4Smiod static int (*macro_expr) (const char *, int, sb *, int *);
120*3d8817e4Smiod
121*3d8817e4Smiod /* Number of macro expansions that have been done. */
122*3d8817e4Smiod
123*3d8817e4Smiod static int macro_number;
124*3d8817e4Smiod
125*3d8817e4Smiod /* Initialize macro processing. */
126*3d8817e4Smiod
127*3d8817e4Smiod void
macro_init(int alternate,int mri,int strip_at,int (* expr)(const char *,int,sb *,int *))128*3d8817e4Smiod macro_init (int alternate, int mri, int strip_at,
129*3d8817e4Smiod int (*expr) (const char *, int, sb *, int *))
130*3d8817e4Smiod {
131*3d8817e4Smiod macro_hash = hash_new ();
132*3d8817e4Smiod macro_defined = 0;
133*3d8817e4Smiod macro_alternate = alternate;
134*3d8817e4Smiod macro_mri = mri;
135*3d8817e4Smiod macro_strip_at = strip_at;
136*3d8817e4Smiod macro_expr = expr;
137*3d8817e4Smiod }
138*3d8817e4Smiod
139*3d8817e4Smiod /* Switch in and out of alternate mode on the fly. */
140*3d8817e4Smiod
141*3d8817e4Smiod void
macro_set_alternate(int alternate)142*3d8817e4Smiod macro_set_alternate (int alternate)
143*3d8817e4Smiod {
144*3d8817e4Smiod macro_alternate = alternate;
145*3d8817e4Smiod }
146*3d8817e4Smiod
147*3d8817e4Smiod /* Switch in and out of MRI mode on the fly. */
148*3d8817e4Smiod
149*3d8817e4Smiod void
macro_mri_mode(int mri)150*3d8817e4Smiod macro_mri_mode (int mri)
151*3d8817e4Smiod {
152*3d8817e4Smiod macro_mri = mri;
153*3d8817e4Smiod }
154*3d8817e4Smiod
155*3d8817e4Smiod /* Read input lines till we get to a TO string.
156*3d8817e4Smiod Increase nesting depth if we get a FROM string.
157*3d8817e4Smiod Put the results into sb at PTR.
158*3d8817e4Smiod FROM may be NULL (or will be ignored) if TO is "ENDR".
159*3d8817e4Smiod Add a new input line to an sb using GET_LINE.
160*3d8817e4Smiod Return 1 on success, 0 on unexpected EOF. */
161*3d8817e4Smiod
162*3d8817e4Smiod int
buffer_and_nest(const char * from,const char * to,sb * ptr,int (* get_line)(sb *))163*3d8817e4Smiod buffer_and_nest (const char *from, const char *to, sb *ptr,
164*3d8817e4Smiod int (*get_line) (sb *))
165*3d8817e4Smiod {
166*3d8817e4Smiod int from_len;
167*3d8817e4Smiod int to_len = strlen (to);
168*3d8817e4Smiod int depth = 1;
169*3d8817e4Smiod int line_start = ptr->len;
170*3d8817e4Smiod
171*3d8817e4Smiod int more = get_line (ptr);
172*3d8817e4Smiod
173*3d8817e4Smiod if (to_len == 4 && strcasecmp(to, "ENDR") == 0)
174*3d8817e4Smiod {
175*3d8817e4Smiod from = NULL;
176*3d8817e4Smiod from_len = 0;
177*3d8817e4Smiod }
178*3d8817e4Smiod else
179*3d8817e4Smiod from_len = strlen (from);
180*3d8817e4Smiod
181*3d8817e4Smiod while (more)
182*3d8817e4Smiod {
183*3d8817e4Smiod /* Try to find the first pseudo op on the line. */
184*3d8817e4Smiod int i = line_start;
185*3d8817e4Smiod
186*3d8817e4Smiod /* With normal syntax we can suck what we want till we get
187*3d8817e4Smiod to the dot. With the alternate, labels have to start in
188*3d8817e4Smiod the first column, since we can't tell what's a label and
189*3d8817e4Smiod what's a pseudoop. */
190*3d8817e4Smiod
191*3d8817e4Smiod if (! LABELS_WITHOUT_COLONS)
192*3d8817e4Smiod {
193*3d8817e4Smiod /* Skip leading whitespace. */
194*3d8817e4Smiod while (i < ptr->len && ISWHITE (ptr->ptr[i]))
195*3d8817e4Smiod i++;
196*3d8817e4Smiod }
197*3d8817e4Smiod
198*3d8817e4Smiod for (;;)
199*3d8817e4Smiod {
200*3d8817e4Smiod /* Skip over a label, if any. */
201*3d8817e4Smiod if (i >= ptr->len || ! is_name_beginner (ptr->ptr[i]))
202*3d8817e4Smiod break;
203*3d8817e4Smiod i++;
204*3d8817e4Smiod while (i < ptr->len && is_part_of_name (ptr->ptr[i]))
205*3d8817e4Smiod i++;
206*3d8817e4Smiod if (i < ptr->len && is_name_ender (ptr->ptr[i]))
207*3d8817e4Smiod i++;
208*3d8817e4Smiod if (LABELS_WITHOUT_COLONS)
209*3d8817e4Smiod break;
210*3d8817e4Smiod /* Skip whitespace. */
211*3d8817e4Smiod while (i < ptr->len && ISWHITE (ptr->ptr[i]))
212*3d8817e4Smiod i++;
213*3d8817e4Smiod /* Check for the colon. */
214*3d8817e4Smiod if (i >= ptr->len || ptr->ptr[i] != ':')
215*3d8817e4Smiod {
216*3d8817e4Smiod i = line_start;
217*3d8817e4Smiod break;
218*3d8817e4Smiod }
219*3d8817e4Smiod i++;
220*3d8817e4Smiod line_start = i;
221*3d8817e4Smiod }
222*3d8817e4Smiod
223*3d8817e4Smiod /* Skip trailing whitespace. */
224*3d8817e4Smiod while (i < ptr->len && ISWHITE (ptr->ptr[i]))
225*3d8817e4Smiod i++;
226*3d8817e4Smiod
227*3d8817e4Smiod if (i < ptr->len && (ptr->ptr[i] == '.'
228*3d8817e4Smiod || NO_PSEUDO_DOT
229*3d8817e4Smiod || macro_mri))
230*3d8817e4Smiod {
231*3d8817e4Smiod if (! flag_m68k_mri && ptr->ptr[i] == '.')
232*3d8817e4Smiod i++;
233*3d8817e4Smiod if (from == NULL
234*3d8817e4Smiod && strncasecmp (ptr->ptr + i, "IRPC", from_len = 4) != 0
235*3d8817e4Smiod && strncasecmp (ptr->ptr + i, "IRP", from_len = 3) != 0
236*3d8817e4Smiod && strncasecmp (ptr->ptr + i, "IREPC", from_len = 5) != 0
237*3d8817e4Smiod && strncasecmp (ptr->ptr + i, "IREP", from_len = 4) != 0
238*3d8817e4Smiod && strncasecmp (ptr->ptr + i, "REPT", from_len = 4) != 0
239*3d8817e4Smiod && strncasecmp (ptr->ptr + i, "REP", from_len = 3) != 0)
240*3d8817e4Smiod from_len = 0;
241*3d8817e4Smiod if ((from != NULL
242*3d8817e4Smiod ? strncasecmp (ptr->ptr + i, from, from_len) == 0
243*3d8817e4Smiod : from_len > 0)
244*3d8817e4Smiod && (ptr->len == (i + from_len)
245*3d8817e4Smiod || ! (is_part_of_name (ptr->ptr[i + from_len])
246*3d8817e4Smiod || is_name_ender (ptr->ptr[i + from_len]))))
247*3d8817e4Smiod depth++;
248*3d8817e4Smiod if (strncasecmp (ptr->ptr + i, to, to_len) == 0
249*3d8817e4Smiod && (ptr->len == (i + to_len)
250*3d8817e4Smiod || ! (is_part_of_name (ptr->ptr[i + to_len])
251*3d8817e4Smiod || is_name_ender (ptr->ptr[i + to_len]))))
252*3d8817e4Smiod {
253*3d8817e4Smiod depth--;
254*3d8817e4Smiod if (depth == 0)
255*3d8817e4Smiod {
256*3d8817e4Smiod /* Reset the string to not include the ending rune. */
257*3d8817e4Smiod ptr->len = line_start;
258*3d8817e4Smiod break;
259*3d8817e4Smiod }
260*3d8817e4Smiod }
261*3d8817e4Smiod }
262*3d8817e4Smiod
263*3d8817e4Smiod /* Add the original end-of-line char to the end and keep running. */
264*3d8817e4Smiod sb_add_char (ptr, more);
265*3d8817e4Smiod line_start = ptr->len;
266*3d8817e4Smiod more = get_line (ptr);
267*3d8817e4Smiod }
268*3d8817e4Smiod
269*3d8817e4Smiod /* Return 1 on success, 0 on unexpected EOF. */
270*3d8817e4Smiod return depth == 0;
271*3d8817e4Smiod }
272*3d8817e4Smiod
273*3d8817e4Smiod /* Pick up a token. */
274*3d8817e4Smiod
275*3d8817e4Smiod static int
get_token(int idx,sb * in,sb * name)276*3d8817e4Smiod get_token (int idx, sb *in, sb *name)
277*3d8817e4Smiod {
278*3d8817e4Smiod if (idx < in->len
279*3d8817e4Smiod && is_name_beginner (in->ptr[idx]))
280*3d8817e4Smiod {
281*3d8817e4Smiod sb_add_char (name, in->ptr[idx++]);
282*3d8817e4Smiod while (idx < in->len
283*3d8817e4Smiod && is_part_of_name (in->ptr[idx]))
284*3d8817e4Smiod {
285*3d8817e4Smiod sb_add_char (name, in->ptr[idx++]);
286*3d8817e4Smiod }
287*3d8817e4Smiod if (idx < in->len
288*3d8817e4Smiod && is_name_ender (in->ptr[idx]))
289*3d8817e4Smiod {
290*3d8817e4Smiod sb_add_char (name, in->ptr[idx++]);
291*3d8817e4Smiod }
292*3d8817e4Smiod }
293*3d8817e4Smiod /* Ignore trailing &. */
294*3d8817e4Smiod if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
295*3d8817e4Smiod idx++;
296*3d8817e4Smiod return idx;
297*3d8817e4Smiod }
298*3d8817e4Smiod
299*3d8817e4Smiod /* Pick up a string. */
300*3d8817e4Smiod
301*3d8817e4Smiod static int
getstring(int idx,sb * in,sb * acc)302*3d8817e4Smiod getstring (int idx, sb *in, sb *acc)
303*3d8817e4Smiod {
304*3d8817e4Smiod while (idx < in->len
305*3d8817e4Smiod && (in->ptr[idx] == '"'
306*3d8817e4Smiod || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
307*3d8817e4Smiod || (in->ptr[idx] == '\'' && macro_alternate)))
308*3d8817e4Smiod {
309*3d8817e4Smiod if (in->ptr[idx] == '<')
310*3d8817e4Smiod {
311*3d8817e4Smiod int nest = 0;
312*3d8817e4Smiod idx++;
313*3d8817e4Smiod while ((in->ptr[idx] != '>' || nest)
314*3d8817e4Smiod && idx < in->len)
315*3d8817e4Smiod {
316*3d8817e4Smiod if (in->ptr[idx] == '!')
317*3d8817e4Smiod {
318*3d8817e4Smiod idx++;
319*3d8817e4Smiod sb_add_char (acc, in->ptr[idx++]);
320*3d8817e4Smiod }
321*3d8817e4Smiod else
322*3d8817e4Smiod {
323*3d8817e4Smiod if (in->ptr[idx] == '>')
324*3d8817e4Smiod nest--;
325*3d8817e4Smiod if (in->ptr[idx] == '<')
326*3d8817e4Smiod nest++;
327*3d8817e4Smiod sb_add_char (acc, in->ptr[idx++]);
328*3d8817e4Smiod }
329*3d8817e4Smiod }
330*3d8817e4Smiod idx++;
331*3d8817e4Smiod }
332*3d8817e4Smiod else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
333*3d8817e4Smiod {
334*3d8817e4Smiod char tchar = in->ptr[idx];
335*3d8817e4Smiod int escaped = 0;
336*3d8817e4Smiod
337*3d8817e4Smiod idx++;
338*3d8817e4Smiod
339*3d8817e4Smiod while (idx < in->len)
340*3d8817e4Smiod {
341*3d8817e4Smiod if (in->ptr[idx - 1] == '\\')
342*3d8817e4Smiod escaped ^= 1;
343*3d8817e4Smiod else
344*3d8817e4Smiod escaped = 0;
345*3d8817e4Smiod
346*3d8817e4Smiod if (macro_alternate && in->ptr[idx] == '!')
347*3d8817e4Smiod {
348*3d8817e4Smiod idx ++;
349*3d8817e4Smiod
350*3d8817e4Smiod sb_add_char (acc, in->ptr[idx]);
351*3d8817e4Smiod
352*3d8817e4Smiod idx ++;
353*3d8817e4Smiod }
354*3d8817e4Smiod else if (escaped && in->ptr[idx] == tchar)
355*3d8817e4Smiod {
356*3d8817e4Smiod sb_add_char (acc, tchar);
357*3d8817e4Smiod idx ++;
358*3d8817e4Smiod }
359*3d8817e4Smiod else
360*3d8817e4Smiod {
361*3d8817e4Smiod if (in->ptr[idx] == tchar)
362*3d8817e4Smiod {
363*3d8817e4Smiod idx ++;
364*3d8817e4Smiod
365*3d8817e4Smiod if (idx >= in->len || in->ptr[idx] != tchar)
366*3d8817e4Smiod break;
367*3d8817e4Smiod }
368*3d8817e4Smiod
369*3d8817e4Smiod sb_add_char (acc, in->ptr[idx]);
370*3d8817e4Smiod idx ++;
371*3d8817e4Smiod }
372*3d8817e4Smiod }
373*3d8817e4Smiod }
374*3d8817e4Smiod }
375*3d8817e4Smiod
376*3d8817e4Smiod return idx;
377*3d8817e4Smiod }
378*3d8817e4Smiod
379*3d8817e4Smiod /* Fetch string from the input stream,
380*3d8817e4Smiod rules:
381*3d8817e4Smiod 'Bxyx<whitespace> -> return 'Bxyza
382*3d8817e4Smiod %<expr> -> return string of decimal value of <expr>
383*3d8817e4Smiod "string" -> return string
384*3d8817e4Smiod (string) -> return (string-including-whitespaces)
385*3d8817e4Smiod xyx<whitespace> -> return xyz. */
386*3d8817e4Smiod
387*3d8817e4Smiod static int
get_any_string(int idx,sb * in,sb * out)388*3d8817e4Smiod get_any_string (int idx, sb *in, sb *out)
389*3d8817e4Smiod {
390*3d8817e4Smiod sb_reset (out);
391*3d8817e4Smiod idx = sb_skip_white (idx, in);
392*3d8817e4Smiod
393*3d8817e4Smiod if (idx < in->len)
394*3d8817e4Smiod {
395*3d8817e4Smiod if (in->len > idx + 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
396*3d8817e4Smiod {
397*3d8817e4Smiod while (!ISSEP (in->ptr[idx]))
398*3d8817e4Smiod sb_add_char (out, in->ptr[idx++]);
399*3d8817e4Smiod }
400*3d8817e4Smiod else if (in->ptr[idx] == '%' && macro_alternate)
401*3d8817e4Smiod {
402*3d8817e4Smiod int val;
403*3d8817e4Smiod char buf[20];
404*3d8817e4Smiod
405*3d8817e4Smiod /* Turns the next expression into a string. */
406*3d8817e4Smiod /* xgettext: no-c-format */
407*3d8817e4Smiod idx = (*macro_expr) (_("% operator needs absolute expression"),
408*3d8817e4Smiod idx + 1,
409*3d8817e4Smiod in,
410*3d8817e4Smiod &val);
411*3d8817e4Smiod sprintf (buf, "%d", val);
412*3d8817e4Smiod sb_add_string (out, buf);
413*3d8817e4Smiod }
414*3d8817e4Smiod else if (in->ptr[idx] == '"'
415*3d8817e4Smiod || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
416*3d8817e4Smiod || (macro_alternate && in->ptr[idx] == '\''))
417*3d8817e4Smiod {
418*3d8817e4Smiod if (macro_alternate && ! macro_strip_at && in->ptr[idx] != '<')
419*3d8817e4Smiod {
420*3d8817e4Smiod /* Keep the quotes. */
421*3d8817e4Smiod sb_add_char (out, '"');
422*3d8817e4Smiod idx = getstring (idx, in, out);
423*3d8817e4Smiod sb_add_char (out, '"');
424*3d8817e4Smiod }
425*3d8817e4Smiod else
426*3d8817e4Smiod {
427*3d8817e4Smiod idx = getstring (idx, in, out);
428*3d8817e4Smiod }
429*3d8817e4Smiod }
430*3d8817e4Smiod else
431*3d8817e4Smiod {
432*3d8817e4Smiod char *br_buf = xmalloc(1);
433*3d8817e4Smiod char *in_br = br_buf;
434*3d8817e4Smiod
435*3d8817e4Smiod *in_br = '\0';
436*3d8817e4Smiod while (idx < in->len
437*3d8817e4Smiod && (*in_br
438*3d8817e4Smiod || (in->ptr[idx] != ' '
439*3d8817e4Smiod && in->ptr[idx] != '\t'))
440*3d8817e4Smiod && in->ptr[idx] != ','
441*3d8817e4Smiod && (in->ptr[idx] != '<'
442*3d8817e4Smiod || (! macro_alternate && ! macro_mri)))
443*3d8817e4Smiod {
444*3d8817e4Smiod char tchar = in->ptr[idx];
445*3d8817e4Smiod
446*3d8817e4Smiod switch (tchar)
447*3d8817e4Smiod {
448*3d8817e4Smiod case '"':
449*3d8817e4Smiod case '\'':
450*3d8817e4Smiod sb_add_char (out, in->ptr[idx++]);
451*3d8817e4Smiod while (idx < in->len
452*3d8817e4Smiod && in->ptr[idx] != tchar)
453*3d8817e4Smiod sb_add_char (out, in->ptr[idx++]);
454*3d8817e4Smiod if (idx == in->len)
455*3d8817e4Smiod return idx;
456*3d8817e4Smiod break;
457*3d8817e4Smiod case '(':
458*3d8817e4Smiod case '[':
459*3d8817e4Smiod if (in_br > br_buf)
460*3d8817e4Smiod --in_br;
461*3d8817e4Smiod else
462*3d8817e4Smiod {
463*3d8817e4Smiod br_buf = xmalloc(strlen(in_br) + 2);
464*3d8817e4Smiod strcpy(br_buf + 1, in_br);
465*3d8817e4Smiod free(in_br);
466*3d8817e4Smiod in_br = br_buf;
467*3d8817e4Smiod }
468*3d8817e4Smiod *in_br = tchar;
469*3d8817e4Smiod break;
470*3d8817e4Smiod case ')':
471*3d8817e4Smiod if (*in_br == '(')
472*3d8817e4Smiod ++in_br;
473*3d8817e4Smiod break;
474*3d8817e4Smiod case ']':
475*3d8817e4Smiod if (*in_br == '[')
476*3d8817e4Smiod ++in_br;
477*3d8817e4Smiod break;
478*3d8817e4Smiod }
479*3d8817e4Smiod sb_add_char (out, tchar);
480*3d8817e4Smiod ++idx;
481*3d8817e4Smiod }
482*3d8817e4Smiod free(br_buf);
483*3d8817e4Smiod }
484*3d8817e4Smiod }
485*3d8817e4Smiod
486*3d8817e4Smiod return idx;
487*3d8817e4Smiod }
488*3d8817e4Smiod
489*3d8817e4Smiod /* Allocate a new formal. */
490*3d8817e4Smiod
491*3d8817e4Smiod static formal_entry *
new_formal(void)492*3d8817e4Smiod new_formal (void)
493*3d8817e4Smiod {
494*3d8817e4Smiod formal_entry *formal;
495*3d8817e4Smiod
496*3d8817e4Smiod formal = xmalloc (sizeof (formal_entry));
497*3d8817e4Smiod
498*3d8817e4Smiod sb_new (&formal->name);
499*3d8817e4Smiod sb_new (&formal->def);
500*3d8817e4Smiod sb_new (&formal->actual);
501*3d8817e4Smiod formal->next = NULL;
502*3d8817e4Smiod formal->type = FORMAL_OPTIONAL;
503*3d8817e4Smiod return formal;
504*3d8817e4Smiod }
505*3d8817e4Smiod
506*3d8817e4Smiod /* Free a formal. */
507*3d8817e4Smiod
508*3d8817e4Smiod static void
del_formal(formal_entry * formal)509*3d8817e4Smiod del_formal (formal_entry *formal)
510*3d8817e4Smiod {
511*3d8817e4Smiod sb_kill (&formal->actual);
512*3d8817e4Smiod sb_kill (&formal->def);
513*3d8817e4Smiod sb_kill (&formal->name);
514*3d8817e4Smiod free (formal);
515*3d8817e4Smiod }
516*3d8817e4Smiod
517*3d8817e4Smiod /* Pick up the formal parameters of a macro definition. */
518*3d8817e4Smiod
519*3d8817e4Smiod static int
do_formals(macro_entry * macro,int idx,sb * in)520*3d8817e4Smiod do_formals (macro_entry *macro, int idx, sb *in)
521*3d8817e4Smiod {
522*3d8817e4Smiod formal_entry **p = ¯o->formals;
523*3d8817e4Smiod const char *name;
524*3d8817e4Smiod
525*3d8817e4Smiod idx = sb_skip_white (idx, in);
526*3d8817e4Smiod while (idx < in->len)
527*3d8817e4Smiod {
528*3d8817e4Smiod formal_entry *formal = new_formal ();
529*3d8817e4Smiod int cidx;
530*3d8817e4Smiod
531*3d8817e4Smiod idx = get_token (idx, in, &formal->name);
532*3d8817e4Smiod if (formal->name.len == 0)
533*3d8817e4Smiod {
534*3d8817e4Smiod if (macro->formal_count)
535*3d8817e4Smiod --idx;
536*3d8817e4Smiod break;
537*3d8817e4Smiod }
538*3d8817e4Smiod idx = sb_skip_white (idx, in);
539*3d8817e4Smiod /* This is a formal. */
540*3d8817e4Smiod name = sb_terminate (&formal->name);
541*3d8817e4Smiod if (! macro_mri
542*3d8817e4Smiod && idx < in->len
543*3d8817e4Smiod && in->ptr[idx] == ':'
544*3d8817e4Smiod && (! is_name_beginner (':')
545*3d8817e4Smiod || idx + 1 >= in->len
546*3d8817e4Smiod || ! is_part_of_name (in->ptr[idx + 1])))
547*3d8817e4Smiod {
548*3d8817e4Smiod /* Got a qualifier. */
549*3d8817e4Smiod sb qual;
550*3d8817e4Smiod
551*3d8817e4Smiod sb_new (&qual);
552*3d8817e4Smiod idx = get_token (sb_skip_white (idx + 1, in), in, &qual);
553*3d8817e4Smiod sb_terminate (&qual);
554*3d8817e4Smiod if (qual.len == 0)
555*3d8817e4Smiod as_bad_where (macro->file,
556*3d8817e4Smiod macro->line,
557*3d8817e4Smiod _("Missing parameter qualifier for `%s' in macro `%s'"),
558*3d8817e4Smiod name,
559*3d8817e4Smiod macro->name);
560*3d8817e4Smiod else if (strcmp (qual.ptr, "req") == 0)
561*3d8817e4Smiod formal->type = FORMAL_REQUIRED;
562*3d8817e4Smiod else if (strcmp (qual.ptr, "vararg") == 0)
563*3d8817e4Smiod formal->type = FORMAL_VARARG;
564*3d8817e4Smiod else
565*3d8817e4Smiod as_bad_where (macro->file,
566*3d8817e4Smiod macro->line,
567*3d8817e4Smiod _("`%s' is not a valid parameter qualifier for `%s' in macro `%s'"),
568*3d8817e4Smiod qual.ptr,
569*3d8817e4Smiod name,
570*3d8817e4Smiod macro->name);
571*3d8817e4Smiod sb_kill (&qual);
572*3d8817e4Smiod idx = sb_skip_white (idx, in);
573*3d8817e4Smiod }
574*3d8817e4Smiod if (idx < in->len && in->ptr[idx] == '=')
575*3d8817e4Smiod {
576*3d8817e4Smiod /* Got a default. */
577*3d8817e4Smiod idx = get_any_string (idx + 1, in, &formal->def);
578*3d8817e4Smiod idx = sb_skip_white (idx, in);
579*3d8817e4Smiod if (formal->type == FORMAL_REQUIRED)
580*3d8817e4Smiod {
581*3d8817e4Smiod sb_reset (&formal->def);
582*3d8817e4Smiod as_warn_where (macro->file,
583*3d8817e4Smiod macro->line,
584*3d8817e4Smiod _("Pointless default value for required parameter `%s' in macro `%s'"),
585*3d8817e4Smiod name,
586*3d8817e4Smiod macro->name);
587*3d8817e4Smiod }
588*3d8817e4Smiod }
589*3d8817e4Smiod
590*3d8817e4Smiod /* Add to macro's hash table. */
591*3d8817e4Smiod if (! hash_find (macro->formal_hash, name))
592*3d8817e4Smiod hash_jam (macro->formal_hash, name, formal);
593*3d8817e4Smiod else
594*3d8817e4Smiod as_bad_where (macro->file,
595*3d8817e4Smiod macro->line,
596*3d8817e4Smiod _("A parameter named `%s' already exists for macro `%s'"),
597*3d8817e4Smiod name,
598*3d8817e4Smiod macro->name);
599*3d8817e4Smiod
600*3d8817e4Smiod formal->index = macro->formal_count++;
601*3d8817e4Smiod *p = formal;
602*3d8817e4Smiod p = &formal->next;
603*3d8817e4Smiod if (formal->type == FORMAL_VARARG)
604*3d8817e4Smiod break;
605*3d8817e4Smiod cidx = idx;
606*3d8817e4Smiod idx = sb_skip_comma (idx, in);
607*3d8817e4Smiod if (idx != cidx && idx >= in->len)
608*3d8817e4Smiod {
609*3d8817e4Smiod idx = cidx;
610*3d8817e4Smiod break;
611*3d8817e4Smiod }
612*3d8817e4Smiod }
613*3d8817e4Smiod
614*3d8817e4Smiod if (macro_mri)
615*3d8817e4Smiod {
616*3d8817e4Smiod formal_entry *formal = new_formal ();
617*3d8817e4Smiod
618*3d8817e4Smiod /* Add a special NARG formal, which macro_expand will set to the
619*3d8817e4Smiod number of arguments. */
620*3d8817e4Smiod /* The same MRI assemblers which treat '@' characters also use
621*3d8817e4Smiod the name $NARG. At least until we find an exception. */
622*3d8817e4Smiod if (macro_strip_at)
623*3d8817e4Smiod name = "$NARG";
624*3d8817e4Smiod else
625*3d8817e4Smiod name = "NARG";
626*3d8817e4Smiod
627*3d8817e4Smiod sb_add_string (&formal->name, name);
628*3d8817e4Smiod
629*3d8817e4Smiod /* Add to macro's hash table. */
630*3d8817e4Smiod if (hash_find (macro->formal_hash, name))
631*3d8817e4Smiod as_bad_where (macro->file,
632*3d8817e4Smiod macro->line,
633*3d8817e4Smiod _("Reserved word `%s' used as parameter in macro `%s'"),
634*3d8817e4Smiod name,
635*3d8817e4Smiod macro->name);
636*3d8817e4Smiod hash_jam (macro->formal_hash, name, formal);
637*3d8817e4Smiod
638*3d8817e4Smiod formal->index = NARG_INDEX;
639*3d8817e4Smiod *p = formal;
640*3d8817e4Smiod }
641*3d8817e4Smiod
642*3d8817e4Smiod return idx;
643*3d8817e4Smiod }
644*3d8817e4Smiod
645*3d8817e4Smiod /* Define a new macro. Returns NULL on success, otherwise returns an
646*3d8817e4Smiod error message. If NAMEP is not NULL, *NAMEP is set to the name of
647*3d8817e4Smiod the macro which was defined. */
648*3d8817e4Smiod
649*3d8817e4Smiod const char *
define_macro(int idx,sb * in,sb * label,int (* get_line)(sb *),char * file,unsigned int line,const char ** namep)650*3d8817e4Smiod define_macro (int idx, sb *in, sb *label,
651*3d8817e4Smiod int (*get_line) (sb *),
652*3d8817e4Smiod char *file, unsigned int line,
653*3d8817e4Smiod const char **namep)
654*3d8817e4Smiod {
655*3d8817e4Smiod macro_entry *macro;
656*3d8817e4Smiod sb name;
657*3d8817e4Smiod const char *error = NULL;
658*3d8817e4Smiod
659*3d8817e4Smiod macro = (macro_entry *) xmalloc (sizeof (macro_entry));
660*3d8817e4Smiod sb_new (¯o->sub);
661*3d8817e4Smiod sb_new (&name);
662*3d8817e4Smiod macro->file = file;
663*3d8817e4Smiod macro->line = line;
664*3d8817e4Smiod
665*3d8817e4Smiod macro->formal_count = 0;
666*3d8817e4Smiod macro->formals = 0;
667*3d8817e4Smiod macro->formal_hash = hash_new ();
668*3d8817e4Smiod
669*3d8817e4Smiod idx = sb_skip_white (idx, in);
670*3d8817e4Smiod if (! buffer_and_nest ("MACRO", "ENDM", ¯o->sub, get_line))
671*3d8817e4Smiod error = _("unexpected end of file in macro `%s' definition");
672*3d8817e4Smiod if (label != NULL && label->len != 0)
673*3d8817e4Smiod {
674*3d8817e4Smiod sb_add_sb (&name, label);
675*3d8817e4Smiod macro->name = sb_terminate (&name);
676*3d8817e4Smiod if (idx < in->len && in->ptr[idx] == '(')
677*3d8817e4Smiod {
678*3d8817e4Smiod /* It's the label: MACRO (formals,...) sort */
679*3d8817e4Smiod idx = do_formals (macro, idx + 1, in);
680*3d8817e4Smiod if (idx < in->len && in->ptr[idx] == ')')
681*3d8817e4Smiod idx = sb_skip_white (idx + 1, in);
682*3d8817e4Smiod else if (!error)
683*3d8817e4Smiod error = _("missing `)' after formals in macro definition `%s'");
684*3d8817e4Smiod }
685*3d8817e4Smiod else
686*3d8817e4Smiod {
687*3d8817e4Smiod /* It's the label: MACRO formals,... sort */
688*3d8817e4Smiod idx = do_formals (macro, idx, in);
689*3d8817e4Smiod }
690*3d8817e4Smiod }
691*3d8817e4Smiod else
692*3d8817e4Smiod {
693*3d8817e4Smiod int cidx;
694*3d8817e4Smiod
695*3d8817e4Smiod idx = get_token (idx, in, &name);
696*3d8817e4Smiod macro->name = sb_terminate (&name);
697*3d8817e4Smiod if (name.len == 0)
698*3d8817e4Smiod error = _("Missing macro name");
699*3d8817e4Smiod cidx = sb_skip_white (idx, in);
700*3d8817e4Smiod idx = sb_skip_comma (cidx, in);
701*3d8817e4Smiod if (idx == cidx || idx < in->len)
702*3d8817e4Smiod idx = do_formals (macro, idx, in);
703*3d8817e4Smiod else
704*3d8817e4Smiod idx = cidx;
705*3d8817e4Smiod }
706*3d8817e4Smiod if (!error && idx < in->len)
707*3d8817e4Smiod error = _("Bad parameter list for macro `%s'");
708*3d8817e4Smiod
709*3d8817e4Smiod /* And stick it in the macro hash table. */
710*3d8817e4Smiod for (idx = 0; idx < name.len; idx++)
711*3d8817e4Smiod name.ptr[idx] = TOLOWER (name.ptr[idx]);
712*3d8817e4Smiod if (hash_find (macro_hash, macro->name))
713*3d8817e4Smiod error = _("Macro `%s' was already defined");
714*3d8817e4Smiod if (!error)
715*3d8817e4Smiod error = hash_jam (macro_hash, macro->name, (PTR) macro);
716*3d8817e4Smiod
717*3d8817e4Smiod if (namep != NULL)
718*3d8817e4Smiod *namep = macro->name;
719*3d8817e4Smiod
720*3d8817e4Smiod if (!error)
721*3d8817e4Smiod macro_defined = 1;
722*3d8817e4Smiod else
723*3d8817e4Smiod free_macro (macro);
724*3d8817e4Smiod
725*3d8817e4Smiod return error;
726*3d8817e4Smiod }
727*3d8817e4Smiod
728*3d8817e4Smiod /* Scan a token, and then skip KIND. */
729*3d8817e4Smiod
730*3d8817e4Smiod static int
get_apost_token(int idx,sb * in,sb * name,int kind)731*3d8817e4Smiod get_apost_token (int idx, sb *in, sb *name, int kind)
732*3d8817e4Smiod {
733*3d8817e4Smiod idx = get_token (idx, in, name);
734*3d8817e4Smiod if (idx < in->len
735*3d8817e4Smiod && in->ptr[idx] == kind
736*3d8817e4Smiod && (! macro_mri || macro_strip_at)
737*3d8817e4Smiod && (! macro_strip_at || kind == '@'))
738*3d8817e4Smiod idx++;
739*3d8817e4Smiod return idx;
740*3d8817e4Smiod }
741*3d8817e4Smiod
742*3d8817e4Smiod /* Substitute the actual value for a formal parameter. */
743*3d8817e4Smiod
744*3d8817e4Smiod static int
sub_actual(int start,sb * in,sb * t,struct hash_control * formal_hash,int kind,sb * out,int copyifnotthere)745*3d8817e4Smiod sub_actual (int start, sb *in, sb *t, struct hash_control *formal_hash,
746*3d8817e4Smiod int kind, sb *out, int copyifnotthere)
747*3d8817e4Smiod {
748*3d8817e4Smiod int src;
749*3d8817e4Smiod formal_entry *ptr;
750*3d8817e4Smiod
751*3d8817e4Smiod src = get_apost_token (start, in, t, kind);
752*3d8817e4Smiod /* See if it's in the macro's hash table, unless this is
753*3d8817e4Smiod macro_strip_at and kind is '@' and the token did not end in '@'. */
754*3d8817e4Smiod if (macro_strip_at
755*3d8817e4Smiod && kind == '@'
756*3d8817e4Smiod && (src == start || in->ptr[src - 1] != '@'))
757*3d8817e4Smiod ptr = NULL;
758*3d8817e4Smiod else
759*3d8817e4Smiod ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
760*3d8817e4Smiod if (ptr)
761*3d8817e4Smiod {
762*3d8817e4Smiod if (ptr->actual.len)
763*3d8817e4Smiod {
764*3d8817e4Smiod sb_add_sb (out, &ptr->actual);
765*3d8817e4Smiod }
766*3d8817e4Smiod else
767*3d8817e4Smiod {
768*3d8817e4Smiod sb_add_sb (out, &ptr->def);
769*3d8817e4Smiod }
770*3d8817e4Smiod }
771*3d8817e4Smiod else if (kind == '&')
772*3d8817e4Smiod {
773*3d8817e4Smiod /* Doing this permits people to use & in macro bodies. */
774*3d8817e4Smiod sb_add_char (out, '&');
775*3d8817e4Smiod sb_add_sb (out, t);
776*3d8817e4Smiod }
777*3d8817e4Smiod else if (copyifnotthere)
778*3d8817e4Smiod {
779*3d8817e4Smiod sb_add_sb (out, t);
780*3d8817e4Smiod }
781*3d8817e4Smiod else
782*3d8817e4Smiod {
783*3d8817e4Smiod sb_add_char (out, '\\');
784*3d8817e4Smiod sb_add_sb (out, t);
785*3d8817e4Smiod }
786*3d8817e4Smiod return src;
787*3d8817e4Smiod }
788*3d8817e4Smiod
789*3d8817e4Smiod /* Expand the body of a macro. */
790*3d8817e4Smiod
791*3d8817e4Smiod static const char *
macro_expand_body(sb * in,sb * out,formal_entry * formals,struct hash_control * formal_hash,const macro_entry * macro)792*3d8817e4Smiod macro_expand_body (sb *in, sb *out, formal_entry *formals,
793*3d8817e4Smiod struct hash_control *formal_hash, const macro_entry *macro)
794*3d8817e4Smiod {
795*3d8817e4Smiod sb t;
796*3d8817e4Smiod int src = 0, inquote = 0, macro_line = 0;
797*3d8817e4Smiod formal_entry *loclist = NULL;
798*3d8817e4Smiod const char *err = NULL;
799*3d8817e4Smiod
800*3d8817e4Smiod sb_new (&t);
801*3d8817e4Smiod
802*3d8817e4Smiod while (src < in->len && !err)
803*3d8817e4Smiod {
804*3d8817e4Smiod if (in->ptr[src] == '&')
805*3d8817e4Smiod {
806*3d8817e4Smiod sb_reset (&t);
807*3d8817e4Smiod if (macro_mri)
808*3d8817e4Smiod {
809*3d8817e4Smiod if (src + 1 < in->len && in->ptr[src + 1] == '&')
810*3d8817e4Smiod src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
811*3d8817e4Smiod else
812*3d8817e4Smiod sb_add_char (out, in->ptr[src++]);
813*3d8817e4Smiod }
814*3d8817e4Smiod else
815*3d8817e4Smiod {
816*3d8817e4Smiod /* FIXME: Why do we do this? */
817*3d8817e4Smiod /* At least in alternate mode this seems correct; without this
818*3d8817e4Smiod one can't append a literal to a parameter. */
819*3d8817e4Smiod src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
820*3d8817e4Smiod }
821*3d8817e4Smiod }
822*3d8817e4Smiod else if (in->ptr[src] == '\\')
823*3d8817e4Smiod {
824*3d8817e4Smiod src++;
825*3d8817e4Smiod if (src < in->len && in->ptr[src] == '(')
826*3d8817e4Smiod {
827*3d8817e4Smiod /* Sub in till the next ')' literally. */
828*3d8817e4Smiod src++;
829*3d8817e4Smiod while (src < in->len && in->ptr[src] != ')')
830*3d8817e4Smiod {
831*3d8817e4Smiod sb_add_char (out, in->ptr[src++]);
832*3d8817e4Smiod }
833*3d8817e4Smiod if (src < in->len)
834*3d8817e4Smiod src++;
835*3d8817e4Smiod else if (!macro)
836*3d8817e4Smiod err = _("missing `)'");
837*3d8817e4Smiod else
838*3d8817e4Smiod as_bad_where (macro->file, macro->line + macro_line, _("missing `)'"));
839*3d8817e4Smiod }
840*3d8817e4Smiod else if (src < in->len && in->ptr[src] == '@')
841*3d8817e4Smiod {
842*3d8817e4Smiod /* Sub in the macro invocation number. */
843*3d8817e4Smiod
844*3d8817e4Smiod char buffer[10];
845*3d8817e4Smiod src++;
846*3d8817e4Smiod sprintf (buffer, "%d", macro_number);
847*3d8817e4Smiod sb_add_string (out, buffer);
848*3d8817e4Smiod }
849*3d8817e4Smiod else if (src < in->len && in->ptr[src] == '&')
850*3d8817e4Smiod {
851*3d8817e4Smiod /* This is a preprocessor variable name, we don't do them
852*3d8817e4Smiod here. */
853*3d8817e4Smiod sb_add_char (out, '\\');
854*3d8817e4Smiod sb_add_char (out, '&');
855*3d8817e4Smiod src++;
856*3d8817e4Smiod }
857*3d8817e4Smiod else if (macro_mri && src < in->len && ISALNUM (in->ptr[src]))
858*3d8817e4Smiod {
859*3d8817e4Smiod int ind;
860*3d8817e4Smiod formal_entry *f;
861*3d8817e4Smiod
862*3d8817e4Smiod if (ISDIGIT (in->ptr[src]))
863*3d8817e4Smiod ind = in->ptr[src] - '0';
864*3d8817e4Smiod else if (ISUPPER (in->ptr[src]))
865*3d8817e4Smiod ind = in->ptr[src] - 'A' + 10;
866*3d8817e4Smiod else
867*3d8817e4Smiod ind = in->ptr[src] - 'a' + 10;
868*3d8817e4Smiod ++src;
869*3d8817e4Smiod for (f = formals; f != NULL; f = f->next)
870*3d8817e4Smiod {
871*3d8817e4Smiod if (f->index == ind - 1)
872*3d8817e4Smiod {
873*3d8817e4Smiod if (f->actual.len != 0)
874*3d8817e4Smiod sb_add_sb (out, &f->actual);
875*3d8817e4Smiod else
876*3d8817e4Smiod sb_add_sb (out, &f->def);
877*3d8817e4Smiod break;
878*3d8817e4Smiod }
879*3d8817e4Smiod }
880*3d8817e4Smiod }
881*3d8817e4Smiod else
882*3d8817e4Smiod {
883*3d8817e4Smiod sb_reset (&t);
884*3d8817e4Smiod src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
885*3d8817e4Smiod }
886*3d8817e4Smiod }
887*3d8817e4Smiod else if ((macro_alternate || macro_mri)
888*3d8817e4Smiod && is_name_beginner (in->ptr[src])
889*3d8817e4Smiod && (! inquote
890*3d8817e4Smiod || ! macro_strip_at
891*3d8817e4Smiod || (src > 0 && in->ptr[src - 1] == '@')))
892*3d8817e4Smiod {
893*3d8817e4Smiod if (! macro
894*3d8817e4Smiod || src + 5 >= in->len
895*3d8817e4Smiod || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
896*3d8817e4Smiod || ! ISWHITE (in->ptr[src + 5]))
897*3d8817e4Smiod {
898*3d8817e4Smiod sb_reset (&t);
899*3d8817e4Smiod src = sub_actual (src, in, &t, formal_hash,
900*3d8817e4Smiod (macro_strip_at && inquote) ? '@' : '\'',
901*3d8817e4Smiod out, 1);
902*3d8817e4Smiod }
903*3d8817e4Smiod else
904*3d8817e4Smiod {
905*3d8817e4Smiod src = sb_skip_white (src + 5, in);
906*3d8817e4Smiod while (in->ptr[src] != '\n')
907*3d8817e4Smiod {
908*3d8817e4Smiod const char *name;
909*3d8817e4Smiod formal_entry *f = new_formal ();
910*3d8817e4Smiod
911*3d8817e4Smiod src = get_token (src, in, &f->name);
912*3d8817e4Smiod name = sb_terminate (&f->name);
913*3d8817e4Smiod if (! hash_find (formal_hash, name))
914*3d8817e4Smiod {
915*3d8817e4Smiod static int loccnt;
916*3d8817e4Smiod char buf[20];
917*3d8817e4Smiod
918*3d8817e4Smiod f->index = LOCAL_INDEX;
919*3d8817e4Smiod f->next = loclist;
920*3d8817e4Smiod loclist = f;
921*3d8817e4Smiod
922*3d8817e4Smiod sprintf (buf, IS_ELF ? ".LL%04x" : "LL%04x", ++loccnt);
923*3d8817e4Smiod sb_add_string (&f->actual, buf);
924*3d8817e4Smiod
925*3d8817e4Smiod err = hash_jam (formal_hash, name, f);
926*3d8817e4Smiod if (err != NULL)
927*3d8817e4Smiod break;
928*3d8817e4Smiod }
929*3d8817e4Smiod else
930*3d8817e4Smiod {
931*3d8817e4Smiod as_bad_where (macro->file,
932*3d8817e4Smiod macro->line + macro_line,
933*3d8817e4Smiod _("`%s' was already used as parameter (or another local) name"),
934*3d8817e4Smiod name);
935*3d8817e4Smiod del_formal (f);
936*3d8817e4Smiod }
937*3d8817e4Smiod
938*3d8817e4Smiod src = sb_skip_comma (src, in);
939*3d8817e4Smiod }
940*3d8817e4Smiod }
941*3d8817e4Smiod }
942*3d8817e4Smiod else if (in->ptr[src] == '"'
943*3d8817e4Smiod || (macro_mri && in->ptr[src] == '\''))
944*3d8817e4Smiod {
945*3d8817e4Smiod inquote = !inquote;
946*3d8817e4Smiod sb_add_char (out, in->ptr[src++]);
947*3d8817e4Smiod }
948*3d8817e4Smiod else if (in->ptr[src] == '@' && macro_strip_at)
949*3d8817e4Smiod {
950*3d8817e4Smiod ++src;
951*3d8817e4Smiod if (src < in->len
952*3d8817e4Smiod && in->ptr[src] == '@')
953*3d8817e4Smiod {
954*3d8817e4Smiod sb_add_char (out, '@');
955*3d8817e4Smiod ++src;
956*3d8817e4Smiod }
957*3d8817e4Smiod }
958*3d8817e4Smiod else if (macro_mri
959*3d8817e4Smiod && in->ptr[src] == '='
960*3d8817e4Smiod && src + 1 < in->len
961*3d8817e4Smiod && in->ptr[src + 1] == '=')
962*3d8817e4Smiod {
963*3d8817e4Smiod formal_entry *ptr;
964*3d8817e4Smiod
965*3d8817e4Smiod sb_reset (&t);
966*3d8817e4Smiod src = get_token (src + 2, in, &t);
967*3d8817e4Smiod ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
968*3d8817e4Smiod if (ptr == NULL)
969*3d8817e4Smiod {
970*3d8817e4Smiod /* FIXME: We should really return a warning string here,
971*3d8817e4Smiod but we can't, because the == might be in the MRI
972*3d8817e4Smiod comment field, and, since the nature of the MRI
973*3d8817e4Smiod comment field depends upon the exact instruction
974*3d8817e4Smiod being used, we don't have enough information here to
975*3d8817e4Smiod figure out whether it is or not. Instead, we leave
976*3d8817e4Smiod the == in place, which should cause a syntax error if
977*3d8817e4Smiod it is not in a comment. */
978*3d8817e4Smiod sb_add_char (out, '=');
979*3d8817e4Smiod sb_add_char (out, '=');
980*3d8817e4Smiod sb_add_sb (out, &t);
981*3d8817e4Smiod }
982*3d8817e4Smiod else
983*3d8817e4Smiod {
984*3d8817e4Smiod if (ptr->actual.len)
985*3d8817e4Smiod {
986*3d8817e4Smiod sb_add_string (out, "-1");
987*3d8817e4Smiod }
988*3d8817e4Smiod else
989*3d8817e4Smiod {
990*3d8817e4Smiod sb_add_char (out, '0');
991*3d8817e4Smiod }
992*3d8817e4Smiod }
993*3d8817e4Smiod }
994*3d8817e4Smiod else
995*3d8817e4Smiod {
996*3d8817e4Smiod if (in->ptr[src] == '\n')
997*3d8817e4Smiod ++macro_line;
998*3d8817e4Smiod sb_add_char (out, in->ptr[src++]);
999*3d8817e4Smiod }
1000*3d8817e4Smiod }
1001*3d8817e4Smiod
1002*3d8817e4Smiod sb_kill (&t);
1003*3d8817e4Smiod
1004*3d8817e4Smiod while (loclist != NULL)
1005*3d8817e4Smiod {
1006*3d8817e4Smiod formal_entry *f;
1007*3d8817e4Smiod
1008*3d8817e4Smiod f = loclist->next;
1009*3d8817e4Smiod /* Setting the value to NULL effectively deletes the entry. We
1010*3d8817e4Smiod avoid calling hash_delete because it doesn't reclaim memory. */
1011*3d8817e4Smiod hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
1012*3d8817e4Smiod del_formal (loclist);
1013*3d8817e4Smiod loclist = f;
1014*3d8817e4Smiod }
1015*3d8817e4Smiod
1016*3d8817e4Smiod return err;
1017*3d8817e4Smiod }
1018*3d8817e4Smiod
1019*3d8817e4Smiod /* Assign values to the formal parameters of a macro, and expand the
1020*3d8817e4Smiod body. */
1021*3d8817e4Smiod
1022*3d8817e4Smiod static const char *
macro_expand(int idx,sb * in,macro_entry * m,sb * out)1023*3d8817e4Smiod macro_expand (int idx, sb *in, macro_entry *m, sb *out)
1024*3d8817e4Smiod {
1025*3d8817e4Smiod sb t;
1026*3d8817e4Smiod formal_entry *ptr;
1027*3d8817e4Smiod formal_entry *f;
1028*3d8817e4Smiod int is_positional = 0;
1029*3d8817e4Smiod int is_keyword = 0;
1030*3d8817e4Smiod int narg = 0;
1031*3d8817e4Smiod const char *err = NULL;
1032*3d8817e4Smiod
1033*3d8817e4Smiod sb_new (&t);
1034*3d8817e4Smiod
1035*3d8817e4Smiod /* Reset any old value the actuals may have. */
1036*3d8817e4Smiod for (f = m->formals; f; f = f->next)
1037*3d8817e4Smiod sb_reset (&f->actual);
1038*3d8817e4Smiod f = m->formals;
1039*3d8817e4Smiod while (f != NULL && f->index < 0)
1040*3d8817e4Smiod f = f->next;
1041*3d8817e4Smiod
1042*3d8817e4Smiod if (macro_mri)
1043*3d8817e4Smiod {
1044*3d8817e4Smiod /* The macro may be called with an optional qualifier, which may
1045*3d8817e4Smiod be referred to in the macro body as \0. */
1046*3d8817e4Smiod if (idx < in->len && in->ptr[idx] == '.')
1047*3d8817e4Smiod {
1048*3d8817e4Smiod /* The Microtec assembler ignores this if followed by a white space.
1049*3d8817e4Smiod (Macro invocation with empty extension) */
1050*3d8817e4Smiod idx++;
1051*3d8817e4Smiod if ( idx < in->len
1052*3d8817e4Smiod && in->ptr[idx] != ' '
1053*3d8817e4Smiod && in->ptr[idx] != '\t')
1054*3d8817e4Smiod {
1055*3d8817e4Smiod formal_entry *n = new_formal ();
1056*3d8817e4Smiod
1057*3d8817e4Smiod n->index = QUAL_INDEX;
1058*3d8817e4Smiod
1059*3d8817e4Smiod n->next = m->formals;
1060*3d8817e4Smiod m->formals = n;
1061*3d8817e4Smiod
1062*3d8817e4Smiod idx = get_any_string (idx, in, &n->actual);
1063*3d8817e4Smiod }
1064*3d8817e4Smiod }
1065*3d8817e4Smiod }
1066*3d8817e4Smiod
1067*3d8817e4Smiod /* Peel off the actuals and store them away in the hash tables' actuals. */
1068*3d8817e4Smiod idx = sb_skip_white (idx, in);
1069*3d8817e4Smiod while (idx < in->len)
1070*3d8817e4Smiod {
1071*3d8817e4Smiod int scan;
1072*3d8817e4Smiod
1073*3d8817e4Smiod /* Look and see if it's a positional or keyword arg. */
1074*3d8817e4Smiod scan = idx;
1075*3d8817e4Smiod while (scan < in->len
1076*3d8817e4Smiod && !ISSEP (in->ptr[scan])
1077*3d8817e4Smiod && !(macro_mri && in->ptr[scan] == '\'')
1078*3d8817e4Smiod && (!macro_alternate && in->ptr[scan] != '='))
1079*3d8817e4Smiod scan++;
1080*3d8817e4Smiod if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
1081*3d8817e4Smiod {
1082*3d8817e4Smiod is_keyword = 1;
1083*3d8817e4Smiod
1084*3d8817e4Smiod /* It's OK to go from positional to keyword. */
1085*3d8817e4Smiod
1086*3d8817e4Smiod /* This is a keyword arg, fetch the formal name and
1087*3d8817e4Smiod then the actual stuff. */
1088*3d8817e4Smiod sb_reset (&t);
1089*3d8817e4Smiod idx = get_token (idx, in, &t);
1090*3d8817e4Smiod if (in->ptr[idx] != '=')
1091*3d8817e4Smiod {
1092*3d8817e4Smiod err = _("confusion in formal parameters");
1093*3d8817e4Smiod break;
1094*3d8817e4Smiod }
1095*3d8817e4Smiod
1096*3d8817e4Smiod /* Lookup the formal in the macro's list. */
1097*3d8817e4Smiod ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1098*3d8817e4Smiod if (!ptr)
1099*3d8817e4Smiod as_bad (_("Parameter named `%s' does not exist for macro `%s'"),
1100*3d8817e4Smiod t.ptr,
1101*3d8817e4Smiod m->name);
1102*3d8817e4Smiod else
1103*3d8817e4Smiod {
1104*3d8817e4Smiod /* Insert this value into the right place. */
1105*3d8817e4Smiod if (ptr->actual.len)
1106*3d8817e4Smiod {
1107*3d8817e4Smiod as_warn (_("Value for parameter `%s' of macro `%s' was already specified"),
1108*3d8817e4Smiod ptr->name.ptr,
1109*3d8817e4Smiod m->name);
1110*3d8817e4Smiod sb_reset (&ptr->actual);
1111*3d8817e4Smiod }
1112*3d8817e4Smiod idx = get_any_string (idx + 1, in, &ptr->actual);
1113*3d8817e4Smiod if (ptr->actual.len > 0)
1114*3d8817e4Smiod ++narg;
1115*3d8817e4Smiod }
1116*3d8817e4Smiod }
1117*3d8817e4Smiod else
1118*3d8817e4Smiod {
1119*3d8817e4Smiod /* This is a positional arg. */
1120*3d8817e4Smiod is_positional = 1;
1121*3d8817e4Smiod if (is_keyword)
1122*3d8817e4Smiod {
1123*3d8817e4Smiod err = _("can't mix positional and keyword arguments");
1124*3d8817e4Smiod break;
1125*3d8817e4Smiod }
1126*3d8817e4Smiod
1127*3d8817e4Smiod if (!f)
1128*3d8817e4Smiod {
1129*3d8817e4Smiod formal_entry **pf;
1130*3d8817e4Smiod int c;
1131*3d8817e4Smiod
1132*3d8817e4Smiod if (!macro_mri)
1133*3d8817e4Smiod {
1134*3d8817e4Smiod err = _("too many positional arguments");
1135*3d8817e4Smiod break;
1136*3d8817e4Smiod }
1137*3d8817e4Smiod
1138*3d8817e4Smiod f = new_formal ();
1139*3d8817e4Smiod
1140*3d8817e4Smiod c = -1;
1141*3d8817e4Smiod for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
1142*3d8817e4Smiod if ((*pf)->index >= c)
1143*3d8817e4Smiod c = (*pf)->index + 1;
1144*3d8817e4Smiod if (c == -1)
1145*3d8817e4Smiod c = 0;
1146*3d8817e4Smiod *pf = f;
1147*3d8817e4Smiod f->index = c;
1148*3d8817e4Smiod }
1149*3d8817e4Smiod
1150*3d8817e4Smiod if (f->type != FORMAL_VARARG)
1151*3d8817e4Smiod idx = get_any_string (idx, in, &f->actual);
1152*3d8817e4Smiod else
1153*3d8817e4Smiod {
1154*3d8817e4Smiod sb_add_buffer (&f->actual, in->ptr + idx, in->len - idx);
1155*3d8817e4Smiod idx = in->len;
1156*3d8817e4Smiod }
1157*3d8817e4Smiod if (f->actual.len > 0)
1158*3d8817e4Smiod ++narg;
1159*3d8817e4Smiod do
1160*3d8817e4Smiod {
1161*3d8817e4Smiod f = f->next;
1162*3d8817e4Smiod }
1163*3d8817e4Smiod while (f != NULL && f->index < 0);
1164*3d8817e4Smiod }
1165*3d8817e4Smiod
1166*3d8817e4Smiod if (! macro_mri)
1167*3d8817e4Smiod idx = sb_skip_comma (idx, in);
1168*3d8817e4Smiod else
1169*3d8817e4Smiod {
1170*3d8817e4Smiod if (in->ptr[idx] == ',')
1171*3d8817e4Smiod ++idx;
1172*3d8817e4Smiod if (ISWHITE (in->ptr[idx]))
1173*3d8817e4Smiod break;
1174*3d8817e4Smiod }
1175*3d8817e4Smiod }
1176*3d8817e4Smiod
1177*3d8817e4Smiod if (! err)
1178*3d8817e4Smiod {
1179*3d8817e4Smiod for (ptr = m->formals; ptr; ptr = ptr->next)
1180*3d8817e4Smiod {
1181*3d8817e4Smiod if (ptr->type == FORMAL_REQUIRED && ptr->actual.len == 0)
1182*3d8817e4Smiod as_bad (_("Missing value for required parameter `%s' of macro `%s'"),
1183*3d8817e4Smiod ptr->name.ptr,
1184*3d8817e4Smiod m->name);
1185*3d8817e4Smiod }
1186*3d8817e4Smiod
1187*3d8817e4Smiod if (macro_mri)
1188*3d8817e4Smiod {
1189*3d8817e4Smiod char buffer[20];
1190*3d8817e4Smiod
1191*3d8817e4Smiod sb_reset (&t);
1192*3d8817e4Smiod sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
1193*3d8817e4Smiod ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1194*3d8817e4Smiod sprintf (buffer, "%d", narg);
1195*3d8817e4Smiod sb_add_string (&ptr->actual, buffer);
1196*3d8817e4Smiod }
1197*3d8817e4Smiod
1198*3d8817e4Smiod err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m);
1199*3d8817e4Smiod }
1200*3d8817e4Smiod
1201*3d8817e4Smiod /* Discard any unnamed formal arguments. */
1202*3d8817e4Smiod if (macro_mri)
1203*3d8817e4Smiod {
1204*3d8817e4Smiod formal_entry **pf;
1205*3d8817e4Smiod
1206*3d8817e4Smiod pf = &m->formals;
1207*3d8817e4Smiod while (*pf != NULL)
1208*3d8817e4Smiod {
1209*3d8817e4Smiod if ((*pf)->name.len != 0)
1210*3d8817e4Smiod pf = &(*pf)->next;
1211*3d8817e4Smiod else
1212*3d8817e4Smiod {
1213*3d8817e4Smiod f = (*pf)->next;
1214*3d8817e4Smiod del_formal (*pf);
1215*3d8817e4Smiod *pf = f;
1216*3d8817e4Smiod }
1217*3d8817e4Smiod }
1218*3d8817e4Smiod }
1219*3d8817e4Smiod
1220*3d8817e4Smiod sb_kill (&t);
1221*3d8817e4Smiod if (!err)
1222*3d8817e4Smiod macro_number++;
1223*3d8817e4Smiod
1224*3d8817e4Smiod return err;
1225*3d8817e4Smiod }
1226*3d8817e4Smiod
1227*3d8817e4Smiod /* Check for a macro. If one is found, put the expansion into
1228*3d8817e4Smiod *EXPAND. Return 1 if a macro is found, 0 otherwise. */
1229*3d8817e4Smiod
1230*3d8817e4Smiod int
check_macro(const char * line,sb * expand,const char ** error,macro_entry ** info)1231*3d8817e4Smiod check_macro (const char *line, sb *expand,
1232*3d8817e4Smiod const char **error, macro_entry **info)
1233*3d8817e4Smiod {
1234*3d8817e4Smiod const char *s;
1235*3d8817e4Smiod char *copy, *cs;
1236*3d8817e4Smiod macro_entry *macro;
1237*3d8817e4Smiod sb line_sb;
1238*3d8817e4Smiod
1239*3d8817e4Smiod if (! is_name_beginner (*line)
1240*3d8817e4Smiod && (! macro_mri || *line != '.'))
1241*3d8817e4Smiod return 0;
1242*3d8817e4Smiod
1243*3d8817e4Smiod s = line + 1;
1244*3d8817e4Smiod while (is_part_of_name (*s))
1245*3d8817e4Smiod ++s;
1246*3d8817e4Smiod if (is_name_ender (*s))
1247*3d8817e4Smiod ++s;
1248*3d8817e4Smiod
1249*3d8817e4Smiod copy = (char *) alloca (s - line + 1);
1250*3d8817e4Smiod memcpy (copy, line, s - line);
1251*3d8817e4Smiod copy[s - line] = '\0';
1252*3d8817e4Smiod for (cs = copy; *cs != '\0'; cs++)
1253*3d8817e4Smiod *cs = TOLOWER (*cs);
1254*3d8817e4Smiod
1255*3d8817e4Smiod macro = (macro_entry *) hash_find (macro_hash, copy);
1256*3d8817e4Smiod
1257*3d8817e4Smiod if (macro == NULL)
1258*3d8817e4Smiod return 0;
1259*3d8817e4Smiod
1260*3d8817e4Smiod /* Wrap the line up in an sb. */
1261*3d8817e4Smiod sb_new (&line_sb);
1262*3d8817e4Smiod while (*s != '\0' && *s != '\n' && *s != '\r')
1263*3d8817e4Smiod sb_add_char (&line_sb, *s++);
1264*3d8817e4Smiod
1265*3d8817e4Smiod sb_new (expand);
1266*3d8817e4Smiod *error = macro_expand (0, &line_sb, macro, expand);
1267*3d8817e4Smiod
1268*3d8817e4Smiod sb_kill (&line_sb);
1269*3d8817e4Smiod
1270*3d8817e4Smiod /* Export the macro information if requested. */
1271*3d8817e4Smiod if (info)
1272*3d8817e4Smiod *info = macro;
1273*3d8817e4Smiod
1274*3d8817e4Smiod return 1;
1275*3d8817e4Smiod }
1276*3d8817e4Smiod
1277*3d8817e4Smiod /* Free the memory allocated to a macro. */
1278*3d8817e4Smiod
1279*3d8817e4Smiod static void
free_macro(macro_entry * macro)1280*3d8817e4Smiod free_macro(macro_entry *macro)
1281*3d8817e4Smiod {
1282*3d8817e4Smiod formal_entry *formal;
1283*3d8817e4Smiod
1284*3d8817e4Smiod for (formal = macro->formals; formal; )
1285*3d8817e4Smiod {
1286*3d8817e4Smiod formal_entry *f;
1287*3d8817e4Smiod
1288*3d8817e4Smiod f = formal;
1289*3d8817e4Smiod formal = formal->next;
1290*3d8817e4Smiod del_formal (f);
1291*3d8817e4Smiod }
1292*3d8817e4Smiod hash_die (macro->formal_hash);
1293*3d8817e4Smiod sb_kill (¯o->sub);
1294*3d8817e4Smiod free (macro);
1295*3d8817e4Smiod }
1296*3d8817e4Smiod
1297*3d8817e4Smiod /* Delete a macro. */
1298*3d8817e4Smiod
1299*3d8817e4Smiod void
delete_macro(const char * name)1300*3d8817e4Smiod delete_macro (const char *name)
1301*3d8817e4Smiod {
1302*3d8817e4Smiod char *copy;
1303*3d8817e4Smiod size_t i, len;
1304*3d8817e4Smiod macro_entry *macro;
1305*3d8817e4Smiod
1306*3d8817e4Smiod len = strlen (name);
1307*3d8817e4Smiod copy = (char *) alloca (len + 1);
1308*3d8817e4Smiod for (i = 0; i < len; ++i)
1309*3d8817e4Smiod copy[i] = TOLOWER (name[i]);
1310*3d8817e4Smiod copy[i] = '\0';
1311*3d8817e4Smiod
1312*3d8817e4Smiod /* Since hash_delete doesn't free memory, just clear out the entry. */
1313*3d8817e4Smiod if ((macro = hash_find (macro_hash, copy)) != NULL)
1314*3d8817e4Smiod {
1315*3d8817e4Smiod hash_jam (macro_hash, copy, NULL);
1316*3d8817e4Smiod free_macro (macro);
1317*3d8817e4Smiod }
1318*3d8817e4Smiod else
1319*3d8817e4Smiod as_warn (_("Attempt to purge non-existant macro `%s'"), copy);
1320*3d8817e4Smiod }
1321*3d8817e4Smiod
1322*3d8817e4Smiod /* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
1323*3d8817e4Smiod combined macro definition and execution. This returns NULL on
1324*3d8817e4Smiod success, or an error message otherwise. */
1325*3d8817e4Smiod
1326*3d8817e4Smiod const char *
expand_irp(int irpc,int idx,sb * in,sb * out,int (* get_line)(sb *))1327*3d8817e4Smiod expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
1328*3d8817e4Smiod {
1329*3d8817e4Smiod sb sub;
1330*3d8817e4Smiod formal_entry f;
1331*3d8817e4Smiod struct hash_control *h;
1332*3d8817e4Smiod const char *err;
1333*3d8817e4Smiod
1334*3d8817e4Smiod idx = sb_skip_white (idx, in);
1335*3d8817e4Smiod
1336*3d8817e4Smiod sb_new (&sub);
1337*3d8817e4Smiod if (! buffer_and_nest (NULL, "ENDR", &sub, get_line))
1338*3d8817e4Smiod return _("unexpected end of file in irp or irpc");
1339*3d8817e4Smiod
1340*3d8817e4Smiod sb_new (&f.name);
1341*3d8817e4Smiod sb_new (&f.def);
1342*3d8817e4Smiod sb_new (&f.actual);
1343*3d8817e4Smiod
1344*3d8817e4Smiod idx = get_token (idx, in, &f.name);
1345*3d8817e4Smiod if (f.name.len == 0)
1346*3d8817e4Smiod return _("missing model parameter");
1347*3d8817e4Smiod
1348*3d8817e4Smiod h = hash_new ();
1349*3d8817e4Smiod err = hash_jam (h, sb_terminate (&f.name), &f);
1350*3d8817e4Smiod if (err != NULL)
1351*3d8817e4Smiod return err;
1352*3d8817e4Smiod
1353*3d8817e4Smiod f.index = 1;
1354*3d8817e4Smiod f.next = NULL;
1355*3d8817e4Smiod f.type = FORMAL_OPTIONAL;
1356*3d8817e4Smiod
1357*3d8817e4Smiod sb_reset (out);
1358*3d8817e4Smiod
1359*3d8817e4Smiod idx = sb_skip_comma (idx, in);
1360*3d8817e4Smiod if (idx >= in->len)
1361*3d8817e4Smiod {
1362*3d8817e4Smiod /* Expand once with a null string. */
1363*3d8817e4Smiod err = macro_expand_body (&sub, out, &f, h, 0);
1364*3d8817e4Smiod }
1365*3d8817e4Smiod else
1366*3d8817e4Smiod {
1367*3d8817e4Smiod if (irpc && in->ptr[idx] == '"')
1368*3d8817e4Smiod ++idx;
1369*3d8817e4Smiod while (idx < in->len)
1370*3d8817e4Smiod {
1371*3d8817e4Smiod if (!irpc)
1372*3d8817e4Smiod idx = get_any_string (idx, in, &f.actual);
1373*3d8817e4Smiod else
1374*3d8817e4Smiod {
1375*3d8817e4Smiod if (in->ptr[idx] == '"')
1376*3d8817e4Smiod {
1377*3d8817e4Smiod int nxt;
1378*3d8817e4Smiod
1379*3d8817e4Smiod nxt = sb_skip_white (idx + 1, in);
1380*3d8817e4Smiod if (nxt >= in->len)
1381*3d8817e4Smiod {
1382*3d8817e4Smiod idx = nxt;
1383*3d8817e4Smiod break;
1384*3d8817e4Smiod }
1385*3d8817e4Smiod }
1386*3d8817e4Smiod sb_reset (&f.actual);
1387*3d8817e4Smiod sb_add_char (&f.actual, in->ptr[idx]);
1388*3d8817e4Smiod ++idx;
1389*3d8817e4Smiod }
1390*3d8817e4Smiod err = macro_expand_body (&sub, out, &f, h, 0);
1391*3d8817e4Smiod if (err != NULL)
1392*3d8817e4Smiod break;
1393*3d8817e4Smiod if (!irpc)
1394*3d8817e4Smiod idx = sb_skip_comma (idx, in);
1395*3d8817e4Smiod else
1396*3d8817e4Smiod idx = sb_skip_white (idx, in);
1397*3d8817e4Smiod }
1398*3d8817e4Smiod }
1399*3d8817e4Smiod
1400*3d8817e4Smiod hash_die (h);
1401*3d8817e4Smiod sb_kill (&f.actual);
1402*3d8817e4Smiod sb_kill (&f.def);
1403*3d8817e4Smiod sb_kill (&f.name);
1404*3d8817e4Smiod sb_kill (&sub);
1405*3d8817e4Smiod
1406*3d8817e4Smiod return err;
1407*3d8817e4Smiod }
1408