macro.c revision 60484
1178825Sdfr/* macro.c - macro support for gas and gasp
2178825Sdfr   Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
3178825Sdfr
4178825Sdfr   Written by Steve and Judy Chamberlain of Cygnus Support,
5178825Sdfr      sac@cygnus.com
6178825Sdfr
7178825Sdfr   This file is part of GAS, the GNU Assembler.
8178825Sdfr
9178825Sdfr   GAS is free software; you can redistribute it and/or modify
10178825Sdfr   it under the terms of the GNU General Public License as published by
11178825Sdfr   the Free Software Foundation; either version 2, or (at your option)
12178825Sdfr   any later version.
13178825Sdfr
14178825Sdfr   GAS is distributed in the hope that it will be useful,
15178825Sdfr   but WITHOUT ANY WARRANTY; without even the implied warranty of
16178825Sdfr   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17178825Sdfr   GNU General Public License for more details.
18178825Sdfr
19178825Sdfr   You should have received a copy of the GNU General Public License
20178825Sdfr   along with GAS; see the file COPYING.  If not, write to the Free
21178825Sdfr   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22178825Sdfr   02111-1307, USA. */
23178825Sdfr
24178825Sdfr#include "config.h"
25178825Sdfr
26178825Sdfr/* AIX requires this to be the first thing in the file.  */
27178825Sdfr#ifdef __GNUC__
28178825Sdfr# ifndef alloca
29178825Sdfr#  ifdef __STDC__
30178825Sdfrextern void *alloca ();
31178825Sdfr#  else
32178825Sdfrextern char *alloca ();
33178825Sdfr#  endif
34178825Sdfr# endif
35178825Sdfr#else
36178825Sdfr# if HAVE_ALLOCA_H
37178825Sdfr#  include <alloca.h>
38178825Sdfr# else
39178825Sdfr#  ifdef _AIX
40178825Sdfr #pragma alloca
41178825Sdfr#  else
42178825Sdfr#   ifndef alloca /* predefined by HP cc +Olibcalls */
43178825Sdfr#    if !defined (__STDC__) && !defined (__hpux)
44178825Sdfrextern char *alloca ();
45178825Sdfr#    else
46178825Sdfrextern void *alloca ();
47178825Sdfr#    endif /* __STDC__, __hpux */
48178825Sdfr#   endif /* alloca */
49178825Sdfr#  endif /* _AIX */
50178825Sdfr# endif /* HAVE_ALLOCA_H */
51178825Sdfr#endif
52178825Sdfr
53178825Sdfr#include <stdio.h>
54178825Sdfr#ifdef HAVE_STRING_H
55178825Sdfr#include <string.h>
56178825Sdfr#else
57178825Sdfr#include <strings.h>
58178825Sdfr#endif
59178825Sdfr#include <ctype.h>
60178825Sdfr#ifdef HAVE_STDLIB_H
61178825Sdfr#include <stdlib.h>
62178825Sdfr#endif
63178825Sdfr#include "libiberty.h"
64178825Sdfr#include "sb.h"
65178825Sdfr#include "hash.h"
66178825Sdfr#include "macro.h"
67178825Sdfr
68178825Sdfr#include "asintl.h"
69178825Sdfr
70178825Sdfr/* The routines in this file handle macro definition and expansion.
71178825Sdfr   They are called by both gasp and gas.  */
72178825Sdfr
73178825Sdfr/* Internal functions.  */
74178825Sdfr
75178825Sdfrstatic int get_token PARAMS ((int, sb *, sb *));
76178825Sdfrstatic int getstring PARAMS ((int, sb *, sb *));
77178825Sdfrstatic int get_any_string PARAMS ((int, sb *, sb *, int, int));
78178825Sdfrstatic int do_formals PARAMS ((macro_entry *, int, sb *));
79178825Sdfrstatic int get_apost_token PARAMS ((int, sb *, sb *, int));
80178825Sdfrstatic int sub_actual
81178825Sdfr  PARAMS ((int, sb *, sb *, struct hash_control *, int, sb *, int));
82178825Sdfrstatic const char *macro_expand_body
83178825Sdfr  PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int, int));
84178825Sdfrstatic const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *, int));
85178825Sdfr
86178825Sdfr#define ISWHITE(x) ((x) == ' ' || (x) == '\t')
87178825Sdfr
88178825Sdfr#define ISSEP(x) \
89178825Sdfr ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
90178825Sdfr  || (x) == ')' || (x) == '(' \
91178825Sdfr  || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
92178825Sdfr
93178825Sdfr#define ISBASE(x) \
94178825Sdfr  ((x) == 'b' || (x) == 'B' \
95178825Sdfr   || (x) == 'q' || (x) == 'Q' \
96178825Sdfr   || (x) == 'h' || (x) == 'H' \
97178825Sdfr   || (x) == 'd' || (x) == 'D')
98178825Sdfr
99178825Sdfr/* The macro hash table.  */
100178825Sdfr
101178825Sdfrstatic struct hash_control *macro_hash;
102178825Sdfr
103178825Sdfr/* Whether any macros have been defined.  */
104178825Sdfr
105178825Sdfrint macro_defined;
106178825Sdfr
107178825Sdfr/* Whether we are in GASP alternate mode.  */
108178825Sdfr
109178825Sdfrstatic int macro_alternate;
110178825Sdfr
111178825Sdfr/* Whether we are in MRI mode.  */
112178825Sdfr
113178825Sdfrstatic int macro_mri;
114178825Sdfr
115178825Sdfr/* Whether we should strip '@' characters.  */
116178825Sdfr
117178825Sdfrstatic int macro_strip_at;
118178825Sdfr
119178825Sdfr/* Function to use to parse an expression.  */
120178825Sdfr
121178825Sdfrstatic int (*macro_expr) PARAMS ((const char *, int, sb *, int *));
122178825Sdfr
123178825Sdfr/* Number of macro expansions that have been done.  */
124178825Sdfr
125178825Sdfrstatic int macro_number;
126178825Sdfr
127178825Sdfr/* Initialize macro processing.  */
128178825Sdfr
129178825Sdfrvoid
130178825Sdfrmacro_init (alternate, mri, strip_at, expr)
131178825Sdfr     int alternate;
132178825Sdfr     int mri;
133178825Sdfr     int strip_at;
134178825Sdfr     int (*expr) PARAMS ((const char *, int, sb *, int *));
135178825Sdfr{
136178825Sdfr  macro_hash = hash_new ();
137178825Sdfr  macro_defined = 0;
138178825Sdfr  macro_alternate = alternate;
139178825Sdfr  macro_mri = mri;
140178825Sdfr  macro_strip_at = strip_at;
141178825Sdfr  macro_expr = expr;
142178825Sdfr}
143178825Sdfr
144178825Sdfr/* Switch in and out of MRI mode on the fly.  */
145178825Sdfr
146178825Sdfrvoid
147178825Sdfrmacro_mri_mode (mri)
148178825Sdfr     int mri;
149178825Sdfr{
150178825Sdfr  macro_mri = mri;
151178825Sdfr}
152178825Sdfr
153178825Sdfr/* Read input lines till we get to a TO string.
154178825Sdfr   Increase nesting depth if we get a FROM string.
155178825Sdfr   Put the results into sb at PTR.
156178825Sdfr   Add a new input line to an sb using GET_LINE.
157178825Sdfr   Return 1 on success, 0 on unexpected EOF.  */
158178825Sdfr
159178825Sdfrint
160178825Sdfrbuffer_and_nest (from, to, ptr, get_line)
161178825Sdfr     const char *from;
162178825Sdfr     const char *to;
163178825Sdfr     sb *ptr;
164178825Sdfr     int (*get_line) PARAMS ((sb *));
165178825Sdfr{
166178825Sdfr  int from_len = strlen (from);
167178825Sdfr  int to_len = strlen (to);
168178825Sdfr  int depth = 1;
169178825Sdfr  int line_start = ptr->len;
170178825Sdfr
171178825Sdfr  int more = get_line (ptr);
172178825Sdfr
173178825Sdfr  while (more)
174178825Sdfr    {
175178825Sdfr      /* Try and find the first pseudo op on the line */
176178825Sdfr      int i = line_start;
177178825Sdfr
178178825Sdfr      if (! macro_alternate && ! macro_mri)
179178825Sdfr	{
180178825Sdfr	  /* With normal syntax we can suck what we want till we get
181178825Sdfr	     to the dot.  With the alternate, labels have to start in
182178825Sdfr	     the first column, since we cant tell what's a label and
183178825Sdfr	     whats a pseudoop */
184178825Sdfr
185178825Sdfr	  /* Skip leading whitespace */
186178825Sdfr	  while (i < ptr->len && ISWHITE (ptr->ptr[i]))
187178825Sdfr	    i++;
188178825Sdfr
189178825Sdfr	  /* Skip over a label */
190178825Sdfr	  while (i < ptr->len
191178825Sdfr		 && (isalnum ((unsigned char) ptr->ptr[i])
192178825Sdfr		     || ptr->ptr[i] == '_'
193178825Sdfr		     || ptr->ptr[i] == '$'))
194178825Sdfr	    i++;
195178825Sdfr
196178825Sdfr	  /* And a colon */
197178825Sdfr	  if (i < ptr->len
198178825Sdfr	      && ptr->ptr[i] == ':')
199178825Sdfr	    i++;
200178825Sdfr
201178825Sdfr	}
202178825Sdfr      /* Skip trailing whitespace */
203178825Sdfr      while (i < ptr->len && ISWHITE (ptr->ptr[i]))
204178825Sdfr	i++;
205178825Sdfr
206178825Sdfr      if (i < ptr->len && (ptr->ptr[i] == '.'
207178825Sdfr			   || macro_alternate
208178825Sdfr			   || macro_mri))
209178825Sdfr	{
210178825Sdfr	  if (ptr->ptr[i] == '.')
211178825Sdfr	      i++;
212178825Sdfr	  if (strncasecmp (ptr->ptr + i, from, from_len) == 0
213178825Sdfr	      && (ptr->len == (i + from_len) || ! isalnum (ptr->ptr[i + from_len])))
214178825Sdfr	    depth++;
215178825Sdfr	  if (strncasecmp (ptr->ptr + i, to, to_len) == 0
216178825Sdfr	      && (ptr->len == (i + to_len) || ! isalnum (ptr->ptr[i + to_len])))
217178825Sdfr	    {
218178825Sdfr	      depth--;
219178825Sdfr	      if (depth == 0)
220178825Sdfr		{
221178825Sdfr		  /* Reset the string to not include the ending rune */
222178825Sdfr		  ptr->len = line_start;
223178825Sdfr		  break;
224178825Sdfr		}
225178825Sdfr	    }
226178825Sdfr	}
227178825Sdfr
228178825Sdfr      /* Add a CR to the end and keep running */
229178825Sdfr      sb_add_char (ptr, '\n');
230178825Sdfr      line_start = ptr->len;
231178825Sdfr      more = get_line (ptr);
232178825Sdfr    }
233178825Sdfr
234178825Sdfr  /* Return 1 on success, 0 on unexpected EOF.  */
235178825Sdfr  return depth == 0;
236178825Sdfr}
237178825Sdfr
238178825Sdfr/* Pick up a token.  */
239178825Sdfr
240178825Sdfrstatic int
241178825Sdfrget_token (idx, in, name)
242178825Sdfr     int idx;
243178825Sdfr     sb *in;
244178825Sdfr     sb *name;
245178825Sdfr{
246178825Sdfr  if (idx < in->len
247178825Sdfr      && (isalpha ((unsigned char) in->ptr[idx])
248178825Sdfr	  || in->ptr[idx] == '_'
249178825Sdfr	  || in->ptr[idx] == '$'))
250178825Sdfr    {
251178825Sdfr      sb_add_char (name, in->ptr[idx++]);
252178825Sdfr      while (idx < in->len
253	     && (isalnum ((unsigned char) in->ptr[idx])
254		 || in->ptr[idx] == '_'
255		 || in->ptr[idx] == '$'))
256	{
257	  sb_add_char (name, in->ptr[idx++]);
258	}
259    }
260  /* Ignore trailing & */
261  if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
262    idx++;
263  return idx;
264}
265
266/* Pick up a string.  */
267
268static int
269getstring (idx, in, acc)
270     int idx;
271     sb *in;
272     sb *acc;
273{
274  idx = sb_skip_white (idx, in);
275
276  while (idx < in->len
277	 && (in->ptr[idx] == '"'
278	     || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
279	     || (in->ptr[idx] == '\'' && macro_alternate)))
280    {
281      if (in->ptr[idx] == '<')
282	{
283	  int nest = 0;
284	  idx++;
285	  while ((in->ptr[idx] != '>' || nest)
286		 && idx < in->len)
287	    {
288	      if (in->ptr[idx] == '!')
289		{
290		  idx++  ;
291		  sb_add_char (acc, in->ptr[idx++]);
292		}
293	      else
294		{
295		  if (in->ptr[idx] == '>')
296		    nest--;
297		  if (in->ptr[idx] == '<')
298		    nest++;
299		  sb_add_char (acc, in->ptr[idx++]);
300		}
301	    }
302	  idx++;
303	}
304      else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
305	{
306	  char tchar = in->ptr[idx];
307	  idx++;
308	  while (idx < in->len)
309	    {
310	      if (macro_alternate && in->ptr[idx] == '!')
311		{
312		  idx++  ;
313		  sb_add_char (acc, in->ptr[idx++]);
314		}
315	      else
316		{
317		  if (in->ptr[idx] == tchar)
318		    {
319		      idx++;
320		      if (idx >= in->len || in->ptr[idx] != tchar)
321			break;
322		    }
323		  sb_add_char (acc, in->ptr[idx]);
324		  idx++;
325		}
326	    }
327	}
328    }
329
330  return idx;
331}
332
333/* Fetch string from the input stream,
334   rules:
335    'Bxyx<whitespace>  	-> return 'Bxyza
336    %<char>		-> return string of decimal value of x
337    "<string>"		-> return string
338    xyx<whitespace>     -> return xyz
339*/
340
341static int
342get_any_string (idx, in, out, expand, pretend_quoted)
343     int idx;
344     sb *in;
345     sb *out;
346     int expand;
347     int pretend_quoted;
348{
349  sb_reset (out);
350  idx = sb_skip_white (idx, in);
351
352  if (idx < in->len)
353    {
354      if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
355	{
356	  while (!ISSEP (in->ptr[idx]))
357	    sb_add_char (out, in->ptr[idx++]);
358	}
359      else if (in->ptr[idx] == '%'
360	       && macro_alternate
361	       && expand)
362	{
363	  int val;
364	  char buf[20];
365	  /* Turns the next expression into a string */
366	  idx = (*macro_expr) (_("% operator needs absolute expression"),
367			       idx + 1,
368			       in,
369			       &val);
370	  sprintf(buf, "%d", val);
371	  sb_add_string (out, buf);
372	}
373      else if (in->ptr[idx] == '"'
374	       || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
375	       || (macro_alternate && in->ptr[idx] == '\''))
376	{
377	  if (macro_alternate
378	      && ! macro_strip_at
379	      && expand)
380	    {
381	      /* Keep the quotes */
382	      sb_add_char (out,  '\"');
383
384	      idx = getstring (idx, in, out);
385	      sb_add_char (out,  '\"');
386	    }
387	  else
388	    {
389	      idx = getstring (idx, in, out);
390	    }
391	}
392      else
393	{
394	  while (idx < in->len
395		 && (in->ptr[idx] == '"'
396		     || in->ptr[idx] == '\''
397		     || pretend_quoted
398		     || (in->ptr[idx] != ' '
399			 && in->ptr[idx] != '\t'
400			 && in->ptr[idx] != ','
401			 && (in->ptr[idx] != '<'
402			     || (! macro_alternate && ! macro_mri)))))
403	    {
404	      if (in->ptr[idx] == '"'
405		  || in->ptr[idx] == '\'')
406		{
407		  char tchar = in->ptr[idx];
408		  sb_add_char (out, in->ptr[idx++]);
409		  while (idx < in->len
410			 && in->ptr[idx] != tchar)
411		    sb_add_char (out, in->ptr[idx++]);
412		  if (idx == in->len)
413		    return idx;
414		}
415	      sb_add_char (out, in->ptr[idx++]);
416	    }
417	}
418    }
419
420  return idx;
421}
422
423/* Pick up the formal parameters of a macro definition.  */
424
425static int
426do_formals (macro, idx, in)
427     macro_entry *macro;
428     int idx;
429     sb *in;
430{
431  formal_entry **p = &macro->formals;
432
433  macro->formal_count = 0;
434  macro->formal_hash = hash_new ();
435  while (idx < in->len)
436    {
437      formal_entry *formal;
438
439      formal = (formal_entry *) xmalloc (sizeof (formal_entry));
440
441      sb_new (&formal->name);
442      sb_new (&formal->def);
443      sb_new (&formal->actual);
444
445      idx = sb_skip_white (idx, in);
446      idx = get_token (idx, in, &formal->name);
447      if (formal->name.len == 0)
448	break;
449      idx = sb_skip_white (idx, in);
450      if (formal->name.len)
451	{
452	  /* This is a formal */
453	  if (idx < in->len && in->ptr[idx] == '=')
454	    {
455	      /* Got a default */
456	      idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
457	    }
458	}
459
460      /* Add to macro's hash table */
461      hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
462
463      formal->index = macro->formal_count;
464      idx = sb_skip_comma (idx, in);
465      macro->formal_count++;
466      *p = formal;
467      p = &formal->next;
468      *p = NULL;
469    }
470
471  if (macro_mri)
472    {
473      formal_entry *formal;
474      const char *name;
475
476      /* Add a special NARG formal, which macro_expand will set to the
477         number of arguments.  */
478      formal = (formal_entry *) xmalloc (sizeof (formal_entry));
479
480      sb_new (&formal->name);
481      sb_new (&formal->def);
482      sb_new (&formal->actual);
483
484      /* The same MRI assemblers which treat '@' characters also use
485         the name $NARG.  At least until we find an exception.  */
486      if (macro_strip_at)
487	name = "$NARG";
488      else
489	name = "NARG";
490
491      sb_add_string (&formal->name, name);
492
493      /* Add to macro's hash table */
494      hash_jam (macro->formal_hash, name, formal);
495
496      formal->index = NARG_INDEX;
497      *p = formal;
498      formal->next = NULL;
499    }
500
501  return idx;
502}
503
504/* Define a new macro.  Returns NULL on success, otherwise returns an
505   error message.  If NAMEP is not NULL, *NAMEP is set to the name of
506   the macro which was defined.  */
507
508const char *
509define_macro (idx, in, label, get_line, namep)
510     int idx;
511     sb *in;
512     sb *label;
513     int (*get_line) PARAMS ((sb *));
514     const char **namep;
515{
516  macro_entry *macro;
517  sb name;
518  const char *namestr;
519
520  macro = (macro_entry *) xmalloc (sizeof (macro_entry));
521  sb_new (&macro->sub);
522  sb_new (&name);
523
524  macro->formal_count = 0;
525  macro->formals = 0;
526
527  idx = sb_skip_white (idx, in);
528  if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
529    return _("unexpected end of file in macro definition");
530  if (label != NULL && label->len != 0)
531    {
532      sb_add_sb (&name, label);
533      if (idx < in->len && in->ptr[idx] == '(')
534	{
535	  /* It's the label: MACRO (formals,...)  sort */
536	  idx = do_formals (macro, idx + 1, in);
537	  if (in->ptr[idx] != ')')
538	    return _("missing ) after formals");
539	}
540      else
541	{
542	  /* It's the label: MACRO formals,...  sort */
543	  idx = do_formals (macro, idx, in);
544	}
545    }
546  else
547    {
548      idx = get_token (idx, in, &name);
549      idx = sb_skip_comma (idx, in);
550      idx = do_formals (macro, idx, in);
551    }
552
553  /* and stick it in the macro hash table */
554  for (idx = 0; idx < name.len; idx++)
555    if (isupper ((unsigned char) name.ptr[idx]))
556      name.ptr[idx] = tolower (name.ptr[idx]);
557  namestr = sb_terminate (&name);
558  hash_jam (macro_hash, namestr, (PTR) macro);
559
560  macro_defined = 1;
561
562  if (namep != NULL)
563    *namep = namestr;
564
565  return NULL;
566}
567
568/* Scan a token, and then skip KIND.  */
569
570static int
571get_apost_token (idx, in, name, kind)
572     int idx;
573     sb *in;
574     sb *name;
575     int kind;
576{
577  idx = get_token (idx, in, name);
578  if (idx < in->len
579      && in->ptr[idx] == kind
580      && (! macro_mri || macro_strip_at)
581      && (! macro_strip_at || kind == '@'))
582    idx++;
583  return idx;
584}
585
586/* Substitute the actual value for a formal parameter.  */
587
588static int
589sub_actual (start, in, t, formal_hash, kind, out, copyifnotthere)
590     int start;
591     sb *in;
592     sb *t;
593     struct hash_control *formal_hash;
594     int kind;
595     sb *out;
596     int copyifnotthere;
597{
598  int src;
599  formal_entry *ptr;
600
601  src = get_apost_token (start, in, t, kind);
602  /* See if it's in the macro's hash table, unless this is
603     macro_strip_at and kind is '@' and the token did not end in '@'.  */
604  if (macro_strip_at
605      && kind == '@'
606      && (src == start || in->ptr[src - 1] != '@'))
607    ptr = NULL;
608  else
609    ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
610  if (ptr)
611    {
612      if (ptr->actual.len)
613	{
614	  sb_add_sb (out, &ptr->actual);
615	}
616      else
617	{
618	  sb_add_sb (out, &ptr->def);
619	}
620    }
621  else if (kind == '&')
622    {
623      /* Doing this permits people to use & in macro bodies.  */
624      sb_add_char (out, '&');
625    }
626  else if (copyifnotthere)
627    {
628      sb_add_sb (out, t);
629    }
630  else
631    {
632      sb_add_char (out, '\\');
633      sb_add_sb (out, t);
634    }
635  return src;
636}
637
638/* Expand the body of a macro.  */
639
640static const char *
641macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
642     sb *in;
643     sb *out;
644     formal_entry *formals;
645     struct hash_control *formal_hash;
646     int comment_char;
647     int locals;
648{
649  sb t;
650  int src = 0;
651  int inquote = 0;
652  formal_entry *loclist = NULL;
653
654  sb_new (&t);
655
656  while (src < in->len)
657    {
658      if (in->ptr[src] == '&')
659	{
660	  sb_reset (&t);
661	  if (macro_mri)
662	    {
663	      if (src + 1 < in->len && in->ptr[src + 1] == '&')
664		src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
665	      else
666		sb_add_char (out, in->ptr[src++]);
667	    }
668	  else
669	    {
670	      /* FIXME: Why do we do this?  */
671	      src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
672	    }
673	}
674      else if (in->ptr[src] == '\\')
675	{
676	  src++;
677	  if (in->ptr[src] == comment_char && comment_char != '\0')
678	    {
679	      /* This is a comment, just drop the rest of the line */
680	      while (src < in->len
681		     && in->ptr[src] != '\n')
682		src++;
683	    }
684	  else if (in->ptr[src] == '(')
685	    {
686	      /* Sub in till the next ')' literally */
687	      src++;
688	      while (src < in->len && in->ptr[src] != ')')
689		{
690		  sb_add_char (out, in->ptr[src++]);
691		}
692	      if (in->ptr[src] == ')')
693		src++;
694	      else
695		return _("missplaced )");
696	    }
697	  else if (in->ptr[src] == '@')
698	    {
699	      /* Sub in the macro invocation number */
700
701	      char buffer[10];
702	      src++;
703	      sprintf (buffer, "%05d", macro_number);
704	      sb_add_string (out, buffer);
705	    }
706	  else if (in->ptr[src] == '&')
707	    {
708	      /* This is a preprocessor variable name, we don't do them
709		 here */
710	      sb_add_char (out, '\\');
711	      sb_add_char (out, '&');
712	      src++;
713	    }
714	  else if (macro_mri
715		   && isalnum ((unsigned char) in->ptr[src]))
716	    {
717	      int ind;
718	      formal_entry *f;
719
720	      if (isdigit ((unsigned char) in->ptr[src]))
721		ind = in->ptr[src] - '0';
722	      else if (isupper ((unsigned char) in->ptr[src]))
723		ind = in->ptr[src] - 'A' + 10;
724	      else
725		ind = in->ptr[src] - 'a' + 10;
726	      ++src;
727	      for (f = formals; f != NULL; f = f->next)
728		{
729		  if (f->index == ind - 1)
730		    {
731		      if (f->actual.len != 0)
732			sb_add_sb (out, &f->actual);
733		      else
734			sb_add_sb (out, &f->def);
735		      break;
736		    }
737		}
738	    }
739	  else
740	    {
741	      sb_reset (&t);
742	      src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
743	    }
744	}
745      else if ((macro_alternate || macro_mri)
746	       && (isalpha ((unsigned char) in->ptr[src])
747		   || in->ptr[src] == '_'
748		   || in->ptr[src] == '$')
749	       && (! inquote
750		   || ! macro_strip_at
751		   || (src > 0 && in->ptr[src - 1] == '@')))
752	{
753	  if (! locals
754	      || src + 5 >= in->len
755	      || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
756	      || ! ISWHITE (in->ptr[src + 5]))
757	    {
758	      sb_reset (&t);
759	      src = sub_actual (src, in, &t, formal_hash,
760				(macro_strip_at && inquote) ? '@' : '\'',
761				out, 1);
762	    }
763	  else
764	    {
765	      formal_entry *f;
766
767	      src = sb_skip_white (src + 5, in);
768	      while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
769		{
770		  static int loccnt;
771		  char buf[20];
772		  const char *err;
773
774		  f = (formal_entry *) xmalloc (sizeof (formal_entry));
775		  sb_new (&f->name);
776		  sb_new (&f->def);
777		  sb_new (&f->actual);
778		  f->index = LOCAL_INDEX;
779		  f->next = loclist;
780		  loclist = f;
781
782		  src = get_token (src, in, &f->name);
783		  ++loccnt;
784		  sprintf (buf, "LL%04x", loccnt);
785		  sb_add_string (&f->actual, buf);
786
787		  err = hash_jam (formal_hash, sb_terminate (&f->name), f);
788		  if (err != NULL)
789		    return err;
790
791		  src = sb_skip_comma (src, in);
792		}
793	    }
794	}
795      else if (comment_char != '\0'
796	       && in->ptr[src] == comment_char
797	       && src + 1 < in->len
798	       && in->ptr[src + 1] == comment_char
799	       && !inquote)
800	{
801	  /* Two comment chars in a row cause the rest of the line to
802             be dropped.  */
803	  while (src < in->len && in->ptr[src] != '\n')
804	    src++;
805	}
806      else if (in->ptr[src] == '"'
807	       || (macro_mri && in->ptr[src] == '\''))
808	{
809	  inquote = !inquote;
810	  sb_add_char (out, in->ptr[src++]);
811	}
812      else if (in->ptr[src] == '@' && macro_strip_at)
813	{
814	  ++src;
815	  if (src < in->len
816	      && in->ptr[src] == '@')
817	    {
818	      sb_add_char (out, '@');
819	      ++src;
820	    }
821	}
822      else if (macro_mri
823	       && in->ptr[src] == '='
824	       && src + 1 < in->len
825	       && in->ptr[src + 1] == '=')
826	{
827	  formal_entry *ptr;
828
829	  sb_reset (&t);
830	  src = get_token (src + 2, in, &t);
831	  ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
832	  if (ptr == NULL)
833	    {
834	      /* FIXME: We should really return a warning string here,
835                 but we can't, because the == might be in the MRI
836                 comment field, and, since the nature of the MRI
837                 comment field depends upon the exact instruction
838                 being used, we don't have enough information here to
839                 figure out whether it is or not.  Instead, we leave
840                 the == in place, which should cause a syntax error if
841                 it is not in a comment.  */
842	      sb_add_char (out, '=');
843	      sb_add_char (out, '=');
844	      sb_add_sb (out, &t);
845	    }
846	  else
847	    {
848	      if (ptr->actual.len)
849		{
850		  sb_add_string (out, "-1");
851		}
852	      else
853		{
854		  sb_add_char (out, '0');
855		}
856	    }
857	}
858      else
859	{
860	  sb_add_char (out, in->ptr[src++]);
861	}
862    }
863
864  sb_kill (&t);
865
866  while (loclist != NULL)
867    {
868      formal_entry *f;
869
870      f = loclist->next;
871      /* Setting the value to NULL effectively deletes the entry.  We
872         avoid calling hash_delete because it doesn't reclaim memory.  */
873      hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
874      sb_kill (&loclist->name);
875      sb_kill (&loclist->def);
876      sb_kill (&loclist->actual);
877      free (loclist);
878      loclist = f;
879    }
880
881  return NULL;
882}
883
884/* Assign values to the formal parameters of a macro, and expand the
885   body.  */
886
887static const char *
888macro_expand (idx, in, m, out, comment_char)
889     int idx;
890     sb *in;
891     macro_entry *m;
892     sb *out;
893     int comment_char;
894{
895  sb t;
896  formal_entry *ptr;
897  formal_entry *f;
898  int is_positional = 0;
899  int is_keyword = 0;
900  int narg = 0;
901  const char *err;
902
903  sb_new (&t);
904
905  /* Reset any old value the actuals may have */
906  for (f = m->formals; f; f = f->next)
907      sb_reset (&f->actual);
908  f = m->formals;
909  while (f != NULL && f->index < 0)
910    f = f->next;
911
912  if (macro_mri)
913    {
914      /* The macro may be called with an optional qualifier, which may
915         be referred to in the macro body as \0.  */
916      if (idx < in->len && in->ptr[idx] == '.')
917	{
918	  formal_entry *n;
919
920	  n = (formal_entry *) xmalloc (sizeof (formal_entry));
921	  sb_new (&n->name);
922	  sb_new (&n->def);
923	  sb_new (&n->actual);
924	  n->index = QUAL_INDEX;
925
926	  n->next = m->formals;
927	  m->formals = n;
928
929	  idx = get_any_string (idx + 1, in, &n->actual, 1, 0);
930	}
931    }
932
933  /* Peel off the actuals and store them away in the hash tables' actuals */
934  idx = sb_skip_white (idx, in);
935  while (idx < in->len && in->ptr[idx] != comment_char)
936    {
937      int scan;
938
939      /* Look and see if it's a positional or keyword arg */
940      scan = idx;
941      while (scan < in->len
942	     && !ISSEP (in->ptr[scan])
943	     && !(macro_mri && in->ptr[scan] == '\'')
944	     && (!macro_alternate && in->ptr[scan] != '='))
945	scan++;
946      if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
947	{
948	  is_keyword = 1;
949
950	  /* It's OK to go from positional to keyword.  */
951
952	  /* This is a keyword arg, fetch the formal name and
953	     then the actual stuff */
954	  sb_reset (&t);
955	  idx = get_token (idx, in, &t);
956	  if (in->ptr[idx] != '=')
957	    return _("confusion in formal parameters");
958
959	  /* Lookup the formal in the macro's list */
960	  ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
961	  if (!ptr)
962	    return _("macro formal argument does not exist");
963	  else
964	    {
965	      /* Insert this value into the right place */
966	      sb_reset (&ptr->actual);
967	      idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
968	      if (ptr->actual.len > 0)
969		++narg;
970	    }
971	}
972      else
973	{
974	  /* This is a positional arg */
975	  is_positional = 1;
976	  if (is_keyword)
977	    return _("can't mix positional and keyword arguments");
978
979	  if (!f)
980	    {
981	      formal_entry **pf;
982	      int c;
983
984	      if (!macro_mri)
985		return _("too many positional arguments");
986
987	      f = (formal_entry *) xmalloc (sizeof (formal_entry));
988	      sb_new (&f->name);
989	      sb_new (&f->def);
990	      sb_new (&f->actual);
991	      f->next = NULL;
992
993	      c = -1;
994	      for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
995		if ((*pf)->index >= c)
996		  c = (*pf)->index + 1;
997	      if (c == -1)
998		c = 0;
999	      *pf = f;
1000	      f->index = c;
1001	    }
1002
1003	  sb_reset (&f->actual);
1004	  idx = get_any_string (idx, in, &f->actual, 1, 0);
1005	  if (f->actual.len > 0)
1006	    ++narg;
1007	  do
1008	    {
1009	      f = f->next;
1010	    }
1011	  while (f != NULL && f->index < 0);
1012	}
1013
1014      if (! macro_mri)
1015	idx = sb_skip_comma (idx, in);
1016      else
1017	{
1018	  if (in->ptr[idx] == ',')
1019	    ++idx;
1020	  if (ISWHITE (in->ptr[idx]))
1021	    break;
1022	}
1023    }
1024
1025  if (macro_mri)
1026    {
1027      char buffer[20];
1028
1029      sb_reset (&t);
1030      sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
1031      ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1032      sb_reset (&ptr->actual);
1033      sprintf (buffer, "%d", narg);
1034      sb_add_string (&ptr->actual, buffer);
1035    }
1036
1037  err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash,
1038			   comment_char, 1);
1039  if (err != NULL)
1040    return err;
1041
1042  /* Discard any unnamed formal arguments.  */
1043  if (macro_mri)
1044    {
1045      formal_entry **pf;
1046
1047      pf = &m->formals;
1048      while (*pf != NULL)
1049	{
1050	  if ((*pf)->name.len != 0)
1051	    pf = &(*pf)->next;
1052	  else
1053	    {
1054	      sb_kill (&(*pf)->name);
1055	      sb_kill (&(*pf)->def);
1056	      sb_kill (&(*pf)->actual);
1057	      f = (*pf)->next;
1058	      free (*pf);
1059	      *pf = f;
1060	    }
1061	}
1062    }
1063
1064  sb_kill (&t);
1065  macro_number++;
1066
1067  return NULL;
1068}
1069
1070/* Check for a macro.  If one is found, put the expansion into
1071   *EXPAND.  COMMENT_CHAR is the comment character--this is used by
1072   gasp.  Return 1 if a macro is found, 0 otherwise.  */
1073
1074int
1075check_macro (line, expand, comment_char, error, info)
1076     const char *line;
1077     sb *expand;
1078     int comment_char;
1079     const char **error;
1080     macro_entry **info;
1081{
1082  const char *s;
1083  char *copy, *cs;
1084  macro_entry *macro;
1085  sb line_sb;
1086
1087  if (! isalpha ((unsigned char) *line)
1088      && *line != '_'
1089      && *line != '$'
1090      && (! macro_mri || *line != '.'))
1091    return 0;
1092
1093  s = line + 1;
1094  while (isalnum ((unsigned char) *s)
1095	 || *s == '_'
1096	 || *s == '$')
1097    ++s;
1098
1099  copy = (char *) alloca (s - line + 1);
1100  memcpy (copy, line, s - line);
1101  copy[s - line] = '\0';
1102  for (cs = copy; *cs != '\0'; cs++)
1103    if (isupper ((unsigned char) *cs))
1104      *cs = tolower (*cs);
1105
1106  macro = (macro_entry *) hash_find (macro_hash, copy);
1107
1108  if (macro == NULL)
1109    return 0;
1110
1111  /* Wrap the line up in an sb.  */
1112  sb_new (&line_sb);
1113  while (*s != '\0' && *s != '\n' && *s != '\r')
1114    sb_add_char (&line_sb, *s++);
1115
1116  sb_new (expand);
1117  *error = macro_expand (0, &line_sb, macro, expand, comment_char);
1118
1119  sb_kill (&line_sb);
1120
1121  /* export the macro information if requested */
1122  if (info)
1123    *info = macro;
1124
1125  return 1;
1126}
1127
1128/* Delete a macro.  */
1129
1130void
1131delete_macro (name)
1132     const char *name;
1133{
1134  hash_delete (macro_hash, name);
1135}
1136
1137/* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
1138   combined macro definition and execution.  This returns NULL on
1139   success, or an error message otherwise.  */
1140
1141const char *
1142expand_irp (irpc, idx, in, out, get_line, comment_char)
1143     int irpc;
1144     int idx;
1145     sb *in;
1146     sb *out;
1147     int (*get_line) PARAMS ((sb *));
1148     int comment_char;
1149{
1150  const char *mn;
1151  sb sub;
1152  formal_entry f;
1153  struct hash_control *h;
1154  const char *err;
1155
1156  if (irpc)
1157    mn = "IRPC";
1158  else
1159    mn = "IRP";
1160
1161  idx = sb_skip_white (idx, in);
1162
1163  sb_new (&sub);
1164  if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
1165    return _("unexpected end of file in irp or irpc");
1166
1167  sb_new (&f.name);
1168  sb_new (&f.def);
1169  sb_new (&f.actual);
1170
1171  idx = get_token (idx, in, &f.name);
1172  if (f.name.len == 0)
1173    return _("missing model parameter");
1174
1175  h = hash_new ();
1176  err = hash_jam (h, sb_terminate (&f.name), &f);
1177  if (err != NULL)
1178    return err;
1179
1180  f.index = 1;
1181  f.next = NULL;
1182
1183  sb_reset (out);
1184
1185  idx = sb_skip_comma (idx, in);
1186  if (idx >= in->len || in->ptr[idx] == comment_char)
1187    {
1188      /* Expand once with a null string.  */
1189      err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1190      if (err != NULL)
1191	return err;
1192    }
1193  else
1194    {
1195      if (irpc && in->ptr[idx] == '"')
1196	++idx;
1197      while (idx < in->len && in->ptr[idx] != comment_char)
1198	{
1199	  if (!irpc)
1200	    idx = get_any_string (idx, in, &f.actual, 1, 0);
1201	  else
1202	    {
1203	      if (in->ptr[idx] == '"')
1204		{
1205		  int nxt;
1206
1207		  nxt = sb_skip_white (idx + 1, in);
1208		  if (nxt >= in->len || in->ptr[nxt] == comment_char)
1209		    {
1210		      idx = nxt;
1211		      break;
1212		    }
1213		}
1214	      sb_reset (&f.actual);
1215	      sb_add_char (&f.actual, in->ptr[idx]);
1216	      ++idx;
1217	    }
1218	  err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1219	  if (err != NULL)
1220	    return err;
1221	  if (!irpc)
1222	    idx = sb_skip_comma (idx, in);
1223	  else
1224	    idx = sb_skip_white (idx, in);
1225	}
1226    }
1227
1228  hash_die (h);
1229  sb_kill (&sub);
1230
1231  return NULL;
1232}
1233