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