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