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