xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/macro.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
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 = &macro->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 (&macro->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", &macro->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 (&macro->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