xref: /netbsd-src/external/gpl3/binutils/dist/gas/macro.c (revision dd7241df2fae9da4ea2bd20a68f001fa86ecf909)
1 /* macro.c - macro support for gas
2    Copyright (C) 1994-2024 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
22    02110-1301, USA.  */
23 
24 #include "as.h"
25 #include "safe-ctype.h"
26 #include "sb.h"
27 #include "macro.h"
28 
29 /* The routines in this file handle macro definition and expansion.
30    They are called by gas.  */
31 
32 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
33 
34 #define ISSEP(x) \
35  ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
36   || (x) == ')' || (x) == '(' \
37   || ((flag_macro_alternate || flag_mri) && ((x) == '<' || (x) == '>')))
38 
39 #define ISBASE(x) \
40   ((x) == 'b' || (x) == 'B' \
41    || (x) == 'q' || (x) == 'Q' \
42    || (x) == 'h' || (x) == 'H' \
43    || (x) == 'd' || (x) == 'D')
44 
45 /* The macro hash table.  */
46 
47 htab_t macro_hash;
48 
49 /* Whether any macros have been defined.  */
50 
51 int macro_defined;
52 
53 /* Whether we should strip '@' characters.  */
54 
55 #define macro_strip_at false
56 
57 /* Number of macro expansions that have been done.  */
58 
59 static int macro_number;
60 
61 static void free_macro (macro_entry *);
62 
63 static void
macro_del_f(void * ent)64 macro_del_f (void *ent)
65 {
66   string_tuple_t *tuple = ent;
67   free_macro ((macro_entry *) tuple->value);
68 }
69 
70 /* Initialize macro processing.  */
71 
72 void
macro_init(void)73 macro_init (void)
74 {
75   macro_hash = htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
76 				  macro_del_f, notes_calloc, NULL);
77   macro_defined = 0;
78 }
79 
80 void
macro_end(void)81 macro_end (void)
82 {
83   htab_delete (macro_hash);
84 }
85 
86 /* Read input lines till we get to a TO string.
87    Increase nesting depth if we get a FROM string.
88    Put the results into sb at PTR.
89    FROM may be NULL (or will be ignored) if TO is "ENDR".
90    Add a new input line to an sb using GET_LINE.
91    Return 1 on success, 0 on unexpected EOF.  */
92 
93 int
buffer_and_nest(const char * from,const char * to,sb * ptr,size_t (* get_line)(sb *))94 buffer_and_nest (const char *from, const char *to, sb *ptr,
95 		 size_t (*get_line) (sb *))
96 {
97   size_t from_len;
98   size_t to_len = strlen (to);
99   int depth = 1;
100   size_t line_start, more;
101 
102   if (to_len == 4 && strcasecmp (to, "ENDR") == 0)
103     {
104       from = NULL;
105       from_len = 0;
106     }
107   else
108     from_len = strlen (from);
109 
110   /* Record the present source position, such that diagnostics and debug info
111      can be properly associated with the respective original lines, rather
112      than with the line of the ending directive (TO).  */
113   {
114     unsigned int line;
115     char *linefile;
116 
117     as_where_top (&line);
118     if (!flag_m68k_mri)
119       linefile = xasprintf ("\t.linefile %u .", line + 1);
120     else
121       linefile = xasprintf ("\tlinefile %u .", line + 1);
122     sb_add_string (ptr, linefile);
123     xfree (linefile);
124   }
125 
126   line_start = ptr->len;
127   more = get_line (ptr);
128   while (more)
129     {
130       /* Try to find the first pseudo op on the line.  */
131       size_t i = line_start;
132       bool had_colon = false;
133 
134       /* With normal syntax we can suck what we want till we get
135 	 to the dot.  With the alternate, labels have to start in
136 	 the first column, since we can't tell what's a label and
137 	 what's a pseudoop.  */
138 
139       if (! LABELS_WITHOUT_COLONS)
140 	{
141 	  /* Skip leading whitespace.  */
142 	  while (i < ptr->len && ISWHITE (ptr->ptr[i]))
143 	    i++;
144 	}
145 
146       for (;;)
147 	{
148 	  /* Skip over a label, if any.  */
149 	  if (i >= ptr->len || ! is_name_beginner (ptr->ptr[i]))
150 	    break;
151 	  i++;
152 	  while (i < ptr->len && is_part_of_name (ptr->ptr[i]))
153 	    i++;
154 	  if (i < ptr->len && is_name_ender (ptr->ptr[i]))
155 	    i++;
156 	  /* Skip whitespace.  */
157 	  while (i < ptr->len && ISWHITE (ptr->ptr[i]))
158 	    i++;
159 	  /* Check for the colon.  */
160 	  if (i >= ptr->len || ptr->ptr[i] != ':')
161 	    {
162 	      /* LABELS_WITHOUT_COLONS doesn't mean we cannot have a
163 		 colon after a label.  If we do have a colon on the
164 		 first label then handle more than one label on the
165 		 line, assuming that each label has a colon.  */
166 	      if (LABELS_WITHOUT_COLONS && !had_colon)
167 		break;
168 	      i = line_start;
169 	      break;
170 	    }
171 	  i++;
172 	  line_start = i;
173 	  had_colon = true;
174 	}
175 
176       /* Skip trailing whitespace.  */
177       while (i < ptr->len && ISWHITE (ptr->ptr[i]))
178 	i++;
179 
180       if (i < ptr->len && (ptr->ptr[i] == '.'
181 			   || NO_PSEUDO_DOT
182 			   || flag_mri))
183 	{
184 	  if (! flag_m68k_mri && ptr->ptr[i] == '.')
185 	    i++;
186 	  size_t len = ptr->len - i;
187 	  if (from == NULL)
188 	    {
189 	      if (len >= 5 && strncasecmp (ptr->ptr + i, "IREPC", 5) == 0)
190 		from_len = 5;
191 	      else if (len >= 4 && strncasecmp (ptr->ptr + i, "IREP", 4) == 0)
192 		from_len = 4;
193 	      else if (len >= 4 && strncasecmp (ptr->ptr + i, "IRPC", 4) == 0)
194 		from_len = 4;
195 	      else if (len >= 4 && strncasecmp (ptr->ptr + i, "REPT", 4) == 0)
196 		from_len = 4;
197 	      else if (len >= 3 && strncasecmp (ptr->ptr + i, "IRP", 3) == 0)
198 		from_len = 3;
199 	      else if (len >= 3 && strncasecmp (ptr->ptr + i, "REP", 3) == 0)
200 		from_len = 3;
201 	      else
202 		from_len = 0;
203 	    }
204 	  if ((from != NULL
205 	       ? (len >= from_len
206 		  && strncasecmp (ptr->ptr + i, from, from_len) == 0)
207 	       : from_len > 0)
208 	      && (len == from_len
209 		  || ! (is_part_of_name (ptr->ptr[i + from_len])
210 			|| is_name_ender (ptr->ptr[i + from_len]))))
211 	    depth++;
212 	  if (len >= to_len
213 	      && strncasecmp (ptr->ptr + i, to, to_len) == 0
214 	      && (len == to_len
215 		  || ! (is_part_of_name (ptr->ptr[i + to_len])
216 			|| is_name_ender (ptr->ptr[i + to_len]))))
217 	    {
218 	      depth--;
219 	      if (depth == 0)
220 		{
221 		  /* Reset the string to not include the ending rune.  */
222 		  ptr->len = line_start;
223 		  break;
224 		}
225 	    }
226 
227 	  /* PR gas/16908
228 	     Apply .linefile directives that appear within the macro, alongside
229 	     keeping them for later expansion of the macro.  */
230 	  if (from != NULL && strcasecmp (from, "MACRO") == 0
231 	      && len >= 8 && strncasecmp (ptr->ptr + i, "linefile", 8) == 0)
232 	    {
233 	      sb_add_char (ptr, more);
234 	      temp_ilp (sb_terminate (ptr) + i + 8);
235 	      s_linefile (0);
236 	      restore_ilp ();
237 	      line_start = ptr->len;
238 	      more = get_line (ptr);
239 	      continue;
240 	    }
241 	}
242 
243       /* Add the original end-of-line char to the end and keep running.  */
244       sb_add_char (ptr, more);
245       line_start = ptr->len;
246       more = get_line (ptr);
247     }
248 
249   /* Return 1 on success, 0 on unexpected EOF.  */
250   return depth == 0;
251 }
252 
253 /* Pick up a token.  */
254 
255 static size_t
get_token(size_t idx,sb * in,sb * name)256 get_token (size_t idx, sb *in, sb *name)
257 {
258   if (idx < in->len
259       && is_name_beginner (in->ptr[idx]))
260     {
261       sb_add_char (name, in->ptr[idx++]);
262       while (idx < in->len
263 	     && is_part_of_name (in->ptr[idx]))
264 	{
265 	  sb_add_char (name, in->ptr[idx++]);
266 	}
267       if (idx < in->len
268 	     && is_name_ender (in->ptr[idx]))
269 	{
270 	  sb_add_char (name, in->ptr[idx++]);
271 	}
272     }
273   /* Ignore trailing &.  */
274   if (flag_macro_alternate && idx < in->len && in->ptr[idx] == '&')
275     idx++;
276   return idx;
277 }
278 
279 /* Pick up a string.  */
280 
281 static size_t
getstring(size_t idx,sb * in,sb * acc)282 getstring (size_t idx, sb *in, sb *acc)
283 {
284   while (idx < in->len
285 	 && (in->ptr[idx] == '"'
286 	     || (in->ptr[idx] == '<' && (flag_macro_alternate || flag_mri))
287 	     || (in->ptr[idx] == '\'' && flag_macro_alternate)))
288     {
289       if (in->ptr[idx] == '<')
290 	{
291 	  int nest = 0;
292 	  idx++;
293 	  while (idx < in->len
294 		 && (in->ptr[idx] != '>' || nest))
295 	    {
296 	      if (in->ptr[idx] == '!')
297 		{
298 		  idx++;
299 		  sb_add_char (acc, in->ptr[idx++]);
300 		}
301 	      else
302 		{
303 		  if (in->ptr[idx] == '>')
304 		    nest--;
305 		  if (in->ptr[idx] == '<')
306 		    nest++;
307 		  sb_add_char (acc, in->ptr[idx++]);
308 		}
309 	    }
310 	  idx++;
311 	}
312       else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
313 	{
314 	  char tchar = in->ptr[idx];
315 	  int escaped = 0;
316 
317 	  idx++;
318 
319 	  while (idx < in->len)
320 	    {
321 	      if (in->ptr[idx - 1] == '\\')
322 		escaped ^= 1;
323 	      else
324 		escaped = 0;
325 
326 	      if (flag_macro_alternate && in->ptr[idx] == '!')
327 		{
328 		  idx ++;
329 
330 		  sb_add_char (acc, in->ptr[idx]);
331 
332 		  idx ++;
333 		}
334 	      else if (escaped && in->ptr[idx] == tchar)
335 		{
336 		  sb_add_char (acc, tchar);
337 		  idx ++;
338 		}
339 	      else
340 		{
341 		  if (in->ptr[idx] == tchar)
342 		    {
343 		      idx ++;
344 
345 		      if (idx >= in->len || in->ptr[idx] != tchar)
346 			break;
347 		    }
348 
349 		  sb_add_char (acc, in->ptr[idx]);
350 		  idx ++;
351 		}
352 	    }
353 	}
354     }
355 
356   return idx;
357 }
358 
359 /* Fetch string from the input stream,
360    rules:
361     'Bxyx<whitespace>  	-> return 'Bxyza
362     %<expr>		-> return string of decimal value of <expr>
363     "string"		-> return string
364     (string)		-> return (string-including-whitespaces)
365     xyx<whitespace>     -> return xyz.  */
366 
367 static size_t
get_any_string(size_t idx,sb * in,sb * out)368 get_any_string (size_t idx, sb *in, sb *out)
369 {
370   sb_reset (out);
371   idx = sb_skip_white (idx, in);
372 
373   if (idx < in->len)
374     {
375       if (in->len > idx + 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
376 	{
377 	  while (idx < in->len && !ISSEP (in->ptr[idx]))
378 	    sb_add_char (out, in->ptr[idx++]);
379 	}
380       else if (in->ptr[idx] == '%' && flag_macro_alternate)
381 	{
382 	  /* Turn the following expression into a string.  */
383 	  expressionS ex;
384 	  char buf[64];
385 
386 	  sb_terminate (in);
387 
388 	  temp_ilp (in->ptr + idx + 1);
389 	  expression_and_evaluate (&ex);
390 	  idx = input_line_pointer - in->ptr;
391 	  restore_ilp ();
392 
393 	  if (ex.X_op != O_constant)
394 	    as_bad (_("%% operator needs absolute expression"));
395 
396 	  sprintf (buf, "%" PRId64, (int64_t) ex.X_add_number);
397 	  sb_add_string (out, buf);
398 	}
399       else if (in->ptr[idx] == '"'
400 	       || (in->ptr[idx] == '<' && (flag_macro_alternate || flag_mri))
401 	       || (flag_macro_alternate && in->ptr[idx] == '\''))
402 	{
403 	  if (flag_macro_alternate && ! macro_strip_at && in->ptr[idx] != '<')
404 	    {
405 	      /* Keep the quotes.  */
406 	      sb_add_char (out, '"');
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 	  char *br_buf = XNEWVEC (char, 1);
418 	  char *in_br = br_buf;
419 
420 	  *in_br = '\0';
421 	  while (idx < in->len
422 		 && (*in_br
423 		     || (in->ptr[idx] != ' '
424 			 && in->ptr[idx] != '\t'))
425 		 && in->ptr[idx] != ','
426 		 && (in->ptr[idx] != '<'
427 		     || (! flag_macro_alternate && ! flag_mri)))
428 	    {
429 	      char tchar = in->ptr[idx];
430 
431 	      switch (tchar)
432 		{
433 		case '"':
434 		case '\'':
435 		  sb_add_char (out, in->ptr[idx++]);
436 		  while (idx < in->len
437 			 && in->ptr[idx] != tchar)
438 		    sb_add_char (out, in->ptr[idx++]);
439 		  if (idx == in->len)
440 		    {
441 		      free (br_buf);
442 		      return idx;
443 		    }
444 		  break;
445 		case '(':
446 		case '[':
447 		  if (in_br > br_buf)
448 		    --in_br;
449 		  else
450 		    {
451 		      br_buf = XNEWVEC (char, strlen (in_br) + 2);
452 		      strcpy (br_buf + 1, in_br);
453 		      free (in_br);
454 		      in_br = br_buf;
455 		    }
456 		  *in_br = tchar;
457 		  break;
458 		case ')':
459 		  if (*in_br == '(')
460 		    ++in_br;
461 		  break;
462 		case ']':
463 		  if (*in_br == '[')
464 		    ++in_br;
465 		  break;
466 		}
467 	      sb_add_char (out, tchar);
468 	      ++idx;
469 	    }
470 	  free (br_buf);
471 	}
472     }
473 
474   return idx;
475 }
476 
477 /* Allocate a new formal.  */
478 
479 static formal_entry *
new_formal(void)480 new_formal (void)
481 {
482   formal_entry *formal;
483 
484   formal = XNEW (formal_entry);
485 
486   sb_new (&formal->name);
487   sb_new (&formal->def);
488   sb_new (&formal->actual);
489   formal->next = NULL;
490   formal->type = FORMAL_OPTIONAL;
491   return formal;
492 }
493 
494 /* Free a formal.  */
495 
496 static void
del_formal(formal_entry * formal)497 del_formal (formal_entry *formal)
498 {
499   sb_kill (&formal->actual);
500   sb_kill (&formal->def);
501   sb_kill (&formal->name);
502   free (formal);
503 }
504 
505 /* Pick up the formal parameters of a macro definition.  */
506 
507 static size_t
do_formals(macro_entry * macro,size_t idx,sb * in)508 do_formals (macro_entry *macro, size_t idx, sb *in)
509 {
510   formal_entry **p = &macro->formals;
511   const char *name;
512 
513   idx = sb_skip_white (idx, in);
514   while (idx < in->len)
515     {
516       formal_entry *formal = new_formal ();
517       size_t cidx;
518 
519       idx = get_token (idx, in, &formal->name);
520       if (formal->name.len == 0)
521 	{
522 	  if (macro->formal_count)
523 	    --idx;
524 	  del_formal (formal);	/* 'formal' goes out of scope.  */
525 	  break;
526 	}
527       idx = sb_skip_white (idx, in);
528       /* This is a formal.  */
529       name = sb_terminate (&formal->name);
530       if (! flag_mri
531 	  && idx < in->len
532 	  && in->ptr[idx] == ':'
533 	  && (! is_name_beginner (':')
534 	      || idx + 1 >= in->len
535 	      || ! is_part_of_name (in->ptr[idx + 1])))
536 	{
537 	  /* Got a qualifier.  */
538 	  sb qual;
539 
540 	  sb_new (&qual);
541 	  idx = get_token (sb_skip_white (idx + 1, in), in, &qual);
542 	  sb_terminate (&qual);
543 	  if (qual.len == 0)
544 	    as_bad_where (macro->file,
545 			  macro->line,
546 			  _("Missing parameter qualifier for `%s' in macro `%s'"),
547 			  name,
548 			  macro->name);
549 	  else if (strcmp (qual.ptr, "req") == 0)
550 	    formal->type = FORMAL_REQUIRED;
551 	  else if (strcmp (qual.ptr, "vararg") == 0)
552 	    formal->type = FORMAL_VARARG;
553 	  else
554 	    as_bad_where (macro->file,
555 			  macro->line,
556 			  _("`%s' is not a valid parameter qualifier for `%s' in macro `%s'"),
557 			  qual.ptr,
558 			  name,
559 			  macro->name);
560 	  sb_kill (&qual);
561 	  idx = sb_skip_white (idx, in);
562 	}
563       if (idx < in->len && in->ptr[idx] == '=')
564 	{
565 	  /* Got a default.  */
566 	  idx = get_any_string (idx + 1, in, &formal->def);
567 	  idx = sb_skip_white (idx, in);
568 	  if (formal->type == FORMAL_REQUIRED)
569 	    {
570 	      sb_reset (&formal->def);
571 	      as_warn_where (macro->file,
572 			    macro->line,
573 			    _("Pointless default value for required parameter `%s' in macro `%s'"),
574 			    name,
575 			    macro->name);
576 	    }
577 	}
578 
579       /* Add to macro's hash table.  */
580       if (str_hash_insert (macro->formal_hash, name, formal, 0) != NULL)
581 	{
582 	  as_bad_where (macro->file, macro->line,
583 			_("A parameter named `%s' "
584 			  "already exists for macro `%s'"),
585 			name, macro->name);
586 	}
587 
588       formal->index = macro->formal_count++;
589       *p = formal;
590       p = &formal->next;
591       if (formal->type == FORMAL_VARARG)
592 	break;
593       cidx = idx;
594       idx = sb_skip_comma (idx, in);
595       if (idx != cidx && idx >= in->len)
596 	{
597 	  idx = cidx;
598 	  break;
599 	}
600     }
601 
602   if (flag_mri)
603     {
604       formal_entry *formal = new_formal ();
605 
606       /* Add a special NARG formal, which macro_expand will set to the
607 	 number of arguments.  */
608       /* The same MRI assemblers which treat '@' characters also use
609 	 the name $NARG.  At least until we find an exception.  */
610       if (macro_strip_at)
611 	name = "$NARG";
612       else
613 	name = "NARG";
614 
615       sb_add_string (&formal->name, name);
616 
617       /* Add to macro's hash table.  */
618       if (str_hash_insert (macro->formal_hash, name, formal, 0) != NULL)
619 	{
620 	  as_bad_where (macro->file, macro->line,
621 			_("Reserved word `%s' used as parameter in macro `%s'"),
622 			name, macro->name);
623 	}
624 
625       formal->index = NARG_INDEX;
626       *p = formal;
627     }
628 
629   return idx;
630 }
631 
632 /* Free the memory allocated to a macro.  */
633 
634 static void
free_macro(macro_entry * macro)635 free_macro (macro_entry *macro)
636 {
637   formal_entry *formal;
638 
639   for (formal = macro->formals; formal; )
640     {
641       formal_entry *f;
642 
643       f = formal;
644       formal = formal->next;
645       del_formal (f);
646     }
647   htab_delete (macro->formal_hash);
648   sb_kill (&macro->sub);
649   free ((char *) macro->name);
650   free (macro);
651 }
652 
653 /* Define a new macro.  */
654 
655 macro_entry *
define_macro(sb * in,sb * label,size_t (* get_line)(sb *))656 define_macro (sb *in, sb *label, size_t (*get_line) (sb *))
657 {
658   macro_entry *macro;
659   sb name;
660   size_t idx;
661   const char *error = NULL;
662 
663   macro = XNEW (macro_entry);
664   sb_new (&macro->sub);
665   sb_new (&name);
666   macro->file = as_where (&macro->line);
667 
668   macro->formal_count = 0;
669   macro->formals = 0;
670   macro->formal_hash = str_htab_create ();
671 
672   idx = sb_skip_white (0, in);
673   if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
674     error = _("unexpected end of file in macro `%s' definition");
675   if (label != NULL && label->len != 0)
676     {
677       sb_add_sb (&name, label);
678       macro->name = sb_terminate (&name);
679       if (idx < in->len && in->ptr[idx] == '(')
680 	{
681 	  /* It's the label: MACRO (formals,...)  sort  */
682 	  idx = do_formals (macro, idx + 1, in);
683 	  if (idx < in->len && in->ptr[idx] == ')')
684 	    idx = sb_skip_white (idx + 1, in);
685 	  else if (!error)
686 	    error = _("missing `)' after formals in macro definition `%s'");
687 	}
688       else
689 	{
690 	  /* It's the label: MACRO formals,...  sort  */
691 	  idx = do_formals (macro, idx, in);
692 	}
693     }
694   else
695     {
696       size_t cidx;
697 
698       idx = get_token (idx, in, &name);
699       macro->name = sb_terminate (&name);
700       if (name.len == 0)
701 	error = _("Missing macro name");
702       cidx = sb_skip_white (idx, in);
703       idx = sb_skip_comma (cidx, in);
704       if (idx == cidx || idx < in->len)
705 	idx = do_formals (macro, idx, in);
706       else
707 	idx = cidx;
708     }
709   if (!error && idx < in->len)
710     error = _("Bad parameter list for macro `%s'");
711 
712   /* And stick it in the macro hash table.  */
713   for (idx = 0; idx < name.len; idx++)
714     name.ptr[idx] = TOLOWER (name.ptr[idx]);
715   if (!error)
716     {
717       if (str_hash_insert (macro_hash, macro->name, macro, 0) != NULL)
718 	error = _("Macro `%s' was already defined");
719     }
720 
721   if (!error)
722     macro_defined = 1;
723   else
724     {
725       as_bad_where (macro->file, macro->line, error, macro->name);
726       free_macro (macro);
727       macro = NULL;
728     }
729 
730   return macro;
731 }
732 
733 /* Scan a token, and then skip KIND.  */
734 
735 static size_t
get_apost_token(size_t idx,sb * in,sb * name,int kind)736 get_apost_token (size_t idx, sb *in, sb *name, int kind)
737 {
738   idx = get_token (idx, in, name);
739   if (idx < in->len
740       && in->ptr[idx] == kind
741       && (! flag_mri || macro_strip_at)
742       && (! macro_strip_at || kind == '@'))
743     idx++;
744   return idx;
745 }
746 
747 /* Substitute the actual value for a formal parameter.  */
748 
749 static size_t
sub_actual(size_t start,sb * in,sb * t,struct htab * formal_hash,int kind,sb * out,int copyifnotthere)750 sub_actual (size_t start, sb *in, sb *t, struct htab *formal_hash,
751 	    int kind, sb *out, int copyifnotthere)
752 {
753   size_t src;
754   formal_entry *ptr;
755 
756   src = get_apost_token (start, in, t, kind);
757   /* See if it's in the macro's hash table, unless this is
758      macro_strip_at and kind is '@' and the token did not end in '@'.  */
759   if (macro_strip_at
760       && kind == '@'
761       && (src == start || in->ptr[src - 1] != '@'))
762     ptr = NULL;
763   else
764     ptr = str_hash_find (formal_hash, sb_terminate (t));
765   if (ptr)
766     {
767       if (ptr->actual.len)
768 	{
769 	  sb_add_sb (out, &ptr->actual);
770 	}
771       else
772 	{
773 	  sb_add_sb (out, &ptr->def);
774 	}
775     }
776   else if (kind == '&')
777     {
778       /* Doing this permits people to use & in macro bodies.  */
779       sb_add_char (out, '&');
780       sb_add_sb (out, t);
781       if (src != start && in->ptr[src - 1] == '&')
782 	sb_add_char (out, '&');
783     }
784   else if (copyifnotthere)
785     {
786       sb_add_sb (out, t);
787     }
788   else
789     {
790       sb_add_char (out, '\\');
791       sb_add_sb (out, t);
792     }
793   return src;
794 }
795 
796 /* Expand the body of a macro.  */
797 
798 static const char *
macro_expand_body(sb * in,sb * out,formal_entry * formals,struct htab * formal_hash,const macro_entry * macro)799 macro_expand_body (sb *in, sb *out, formal_entry *formals,
800 		   struct htab *formal_hash, const macro_entry *macro)
801 {
802   sb t;
803   size_t src = 0;
804   int inquote = 0, macro_line = 0;
805   formal_entry *loclist = NULL;
806   const char *err = NULL;
807 
808   sb_new (&t);
809 
810   while (src < in->len && !err)
811     {
812       if (in->ptr[src] == '&')
813 	{
814 	  sb_reset (&t);
815 	  if (flag_mri)
816 	    {
817 	      if (src + 1 < in->len && in->ptr[src + 1] == '&')
818 		src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
819 	      else
820 		sb_add_char (out, in->ptr[src++]);
821 	    }
822 	  else
823 	    {
824 	      /* Permit macro parameter substitution delineated with
825 		 an '&' prefix and optional '&' suffix.  */
826 	      src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
827 	    }
828 	}
829       else if (in->ptr[src] == '\\')
830 	{
831 	  src++;
832 	  if (src < in->len && in->ptr[src] == '(')
833 	    {
834 	      /* Sub in till the next ')' literally.  */
835 	      src++;
836 	      while (src < in->len && in->ptr[src] != ')')
837 		{
838 		  sb_add_char (out, in->ptr[src++]);
839 		}
840 	      if (src < in->len)
841 		src++;
842 	      else if (!macro)
843 		err = _("missing `)'");
844 	      else
845 		as_bad_where (macro->file, macro->line + macro_line, _("missing `)'"));
846 	    }
847 	  else if (src < in->len && in->ptr[src] == '@')
848 	    {
849 	      /* Sub in the macro invocation number.  */
850 
851 	      char buffer[12];
852 	      src++;
853 	      sprintf (buffer, "%d", macro_number);
854 	      sb_add_string (out, buffer);
855 	    }
856 	  else if (src < in->len && in->ptr[src] == '&')
857 	    {
858 	      /* This is a preprocessor variable name, we don't do them
859 		 here.  */
860 	      sb_add_char (out, '\\');
861 	      sb_add_char (out, '&');
862 	      src++;
863 	    }
864 	  else if (flag_mri && src < in->len && ISALNUM (in->ptr[src]))
865 	    {
866 	      int ind;
867 	      formal_entry *f;
868 
869 	      if (ISDIGIT (in->ptr[src]))
870 		ind = in->ptr[src] - '0';
871 	      else if (ISUPPER (in->ptr[src]))
872 		ind = in->ptr[src] - 'A' + 10;
873 	      else
874 		ind = in->ptr[src] - 'a' + 10;
875 	      ++src;
876 	      for (f = formals; f != NULL; f = f->next)
877 		{
878 		  if (f->index == ind - 1)
879 		    {
880 		      if (f->actual.len != 0)
881 			sb_add_sb (out, &f->actual);
882 		      else
883 			sb_add_sb (out, &f->def);
884 		      break;
885 		    }
886 		}
887 	    }
888 	  else
889 	    {
890 	      sb_reset (&t);
891 	      src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
892 	    }
893 	}
894       else if ((flag_macro_alternate || flag_mri)
895 	       && is_name_beginner (in->ptr[src])
896 	       && (! inquote
897 		   || ! macro_strip_at
898 		   || (src > 0 && in->ptr[src - 1] == '@')))
899 	{
900 	  if (! macro
901 	      || src + 5 >= in->len
902 	      || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
903 	      || ! ISWHITE (in->ptr[src + 5])
904 	      /* PR 11507: Skip keyword LOCAL if it is found inside a quoted string.  */
905 	      || inquote)
906 	    {
907 	      sb_reset (&t);
908 	      src = sub_actual (src, in, &t, formal_hash,
909 				(macro_strip_at && inquote) ? '@' : '\'',
910 				out, 1);
911 	    }
912 	  else
913 	    {
914 	      src = sb_skip_white (src + 5, in);
915 	      while (in->ptr[src] != '\n')
916 		{
917 		  const char *name;
918 		  formal_entry *f = new_formal ();
919 
920 		  src = get_token (src, in, &f->name);
921 		  name = sb_terminate (&f->name);
922 		  if (str_hash_insert (formal_hash, name, f, 0) != NULL)
923 		    {
924 		      as_bad_where (macro->file, macro->line + macro_line,
925 				    _("`%s' was already used as parameter "
926 				      "(or another local) name"), name);
927 		      del_formal (f);
928 		    }
929 		  else
930 		    {
931 		      static int loccnt;
932 		      char buf[20];
933 
934 		      f->index = LOCAL_INDEX;
935 		      f->next = loclist;
936 		      loclist = f;
937 
938 		      sprintf (buf, IS_ELF ? ".LL%04x" : "LL%04x", ++loccnt);
939 		      sb_add_string (&f->actual, buf);
940 		    }
941 
942 		  src = sb_skip_comma (src, in);
943 		}
944 	    }
945 	}
946       else if (in->ptr[src] == '"'
947 	       || (flag_mri && in->ptr[src] == '\''))
948 	{
949 	  inquote = !inquote;
950 	  sb_add_char (out, in->ptr[src++]);
951 	}
952       else if (in->ptr[src] == '@' && macro_strip_at)
953 	{
954 	  ++src;
955 	  if (src < in->len
956 	      && in->ptr[src] == '@')
957 	    {
958 	      sb_add_char (out, '@');
959 	      ++src;
960 	    }
961 	}
962       else if (flag_mri
963 	       && in->ptr[src] == '='
964 	       && src + 1 < in->len
965 	       && in->ptr[src + 1] == '=')
966 	{
967 	  formal_entry *ptr;
968 
969 	  sb_reset (&t);
970 	  src = get_token (src + 2, in, &t);
971 	  ptr = str_hash_find (formal_hash, sb_terminate (&t));
972 	  if (ptr == NULL)
973 	    {
974 	      /* FIXME: We should really return a warning string here,
975 		 but we can't, because the == might be in the MRI
976 		 comment field, and, since the nature of the MRI
977 		 comment field depends upon the exact instruction
978 		 being used, we don't have enough information here to
979 		 figure out whether it is or not.  Instead, we leave
980 		 the == in place, which should cause a syntax error if
981 		 it is not in a comment.  */
982 	      sb_add_char (out, '=');
983 	      sb_add_char (out, '=');
984 	      sb_add_sb (out, &t);
985 	    }
986 	  else
987 	    {
988 	      if (ptr->actual.len)
989 		{
990 		  sb_add_string (out, "-1");
991 		}
992 	      else
993 		{
994 		  sb_add_char (out, '0');
995 		}
996 	    }
997 	}
998       else
999 	{
1000 	  if (in->ptr[src] == '\n')
1001 	    ++macro_line;
1002 	  sb_add_char (out, in->ptr[src++]);
1003 	}
1004     }
1005 
1006   sb_kill (&t);
1007 
1008   while (loclist != NULL)
1009     {
1010       formal_entry *f;
1011       const char *name;
1012 
1013       f = loclist->next;
1014       name = sb_terminate (&loclist->name);
1015       str_hash_delete (formal_hash, name);
1016       del_formal (loclist);
1017       loclist = f;
1018     }
1019 
1020   if (!err && (out->len == 0 || out->ptr[out->len - 1] != '\n'))
1021     sb_add_char (out, '\n');
1022   return err;
1023 }
1024 
1025 /* Assign values to the formal parameters of a macro, and expand the
1026    body.  */
1027 
1028 static const char *
macro_expand(size_t idx,sb * in,macro_entry * m,sb * out)1029 macro_expand (size_t idx, sb *in, macro_entry *m, sb *out)
1030 {
1031   sb t;
1032   formal_entry *ptr;
1033   formal_entry *f;
1034   int is_keyword = 0;
1035   int narg = 0;
1036   const char *err = NULL;
1037 
1038   sb_new (&t);
1039 
1040   /* Reset any old value the actuals may have.  */
1041   for (f = m->formals; f; f = f->next)
1042     sb_reset (&f->actual);
1043   f = m->formals;
1044   while (f != NULL && f->index < 0)
1045     f = f->next;
1046 
1047   if (flag_mri)
1048     {
1049       /* The macro may be called with an optional qualifier, which may
1050 	 be referred to in the macro body as \0.  */
1051       if (idx < in->len && in->ptr[idx] == '.')
1052 	{
1053 	  /* The Microtec assembler ignores this if followed by a white space.
1054 	     (Macro invocation with empty extension) */
1055 	  idx++;
1056 	  if (    idx < in->len
1057 		  && in->ptr[idx] != ' '
1058 		  && in->ptr[idx] != '\t')
1059 	    {
1060 	      formal_entry *n = new_formal ();
1061 
1062 	      n->index = QUAL_INDEX;
1063 
1064 	      n->next = m->formals;
1065 	      m->formals = n;
1066 
1067 	      idx = get_any_string (idx, in, &n->actual);
1068 	    }
1069 	}
1070     }
1071 
1072   /* Peel off the actuals and store them away in the hash tables' actuals.  */
1073   idx = sb_skip_white (idx, in);
1074   while (idx < in->len)
1075     {
1076       size_t scan;
1077 
1078       /* Look and see if it's a positional or keyword arg.  */
1079       scan = idx;
1080       while (scan < in->len
1081 	     && !ISSEP (in->ptr[scan])
1082 	     && !(flag_mri && in->ptr[scan] == '\'')
1083 	     && (!flag_macro_alternate && in->ptr[scan] != '='))
1084 	scan++;
1085       if (scan < in->len && !flag_macro_alternate && in->ptr[scan] == '=')
1086 	{
1087 	  is_keyword = 1;
1088 
1089 	  /* It's OK to go from positional to keyword.  */
1090 
1091 	  /* This is a keyword arg, fetch the formal name and
1092 	     then the actual stuff.  */
1093 	  sb_reset (&t);
1094 	  idx = get_token (idx, in, &t);
1095 	  if (idx >= in->len || in->ptr[idx] != '=')
1096 	    {
1097 	      err = _("confusion in formal parameters");
1098 	      break;
1099 	    }
1100 
1101 	  /* Lookup the formal in the macro's list.  */
1102 	  ptr = str_hash_find (m->formal_hash, sb_terminate (&t));
1103 	  if (!ptr)
1104 	    {
1105 	      as_bad (_("Parameter named `%s' does not exist for macro `%s'"),
1106 		      t.ptr,
1107 		      m->name);
1108 	      sb_reset (&t);
1109 	      idx = get_any_string (idx + 1, in, &t);
1110 	    }
1111 	  else
1112 	    {
1113 	      /* Insert this value into the right place.  */
1114 	      if (ptr->actual.len)
1115 		{
1116 		  as_warn (_("Value for parameter `%s' of macro `%s' was already specified"),
1117 			   ptr->name.ptr,
1118 			   m->name);
1119 		  sb_reset (&ptr->actual);
1120 		}
1121 	      idx = get_any_string (idx + 1, in, &ptr->actual);
1122 	      if (ptr->actual.len > 0)
1123 		++narg;
1124 	    }
1125 	}
1126       else
1127 	{
1128 	  if (is_keyword)
1129 	    {
1130 	      err = _("can't mix positional and keyword arguments");
1131 	      break;
1132 	    }
1133 
1134 	  if (!f)
1135 	    {
1136 	      formal_entry **pf;
1137 	      int c;
1138 
1139 	      if (!flag_mri)
1140 		{
1141 		  err = _("too many positional arguments");
1142 		  break;
1143 		}
1144 
1145 	      f = new_formal ();
1146 
1147 	      c = -1;
1148 	      for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
1149 		if ((*pf)->index >= c)
1150 		  c = (*pf)->index + 1;
1151 	      if (c == -1)
1152 		c = 0;
1153 	      *pf = f;
1154 	      f->index = c;
1155 	    }
1156 
1157 	  if (f->type != FORMAL_VARARG)
1158 	    idx = get_any_string (idx, in, &f->actual);
1159 	  else if (idx < in->len)
1160 	    {
1161 	      sb_add_buffer (&f->actual, in->ptr + idx, in->len - idx);
1162 	      idx = in->len;
1163 	    }
1164 	  if (f->actual.len > 0)
1165 	    ++narg;
1166 	  do
1167 	    {
1168 	      f = f->next;
1169 	    }
1170 	  while (f != NULL && f->index < 0);
1171 	}
1172 
1173       if (! flag_mri)
1174 	idx = sb_skip_comma (idx, in);
1175       else
1176 	{
1177 	  if (idx < in->len && in->ptr[idx] == ',')
1178 	    ++idx;
1179 	  if (idx < in->len && ISWHITE (in->ptr[idx]))
1180 	    break;
1181 	}
1182     }
1183 
1184   if (! err)
1185     {
1186       for (ptr = m->formals; ptr; ptr = ptr->next)
1187 	{
1188 	  if (ptr->type == FORMAL_REQUIRED && ptr->actual.len == 0)
1189 	    as_bad (_("Missing value for required parameter `%s' of macro `%s'"),
1190 		    ptr->name.ptr,
1191 		    m->name);
1192 	}
1193 
1194       if (flag_mri)
1195 	{
1196 	  ptr = str_hash_find (m->formal_hash,
1197 			       macro_strip_at ? "$NARG" : "NARG");
1198 	  if (ptr)
1199 	    {
1200 	      char buffer[20];
1201 	      sprintf (buffer, "%d", narg);
1202 	      sb_add_string (&ptr->actual, buffer);
1203 	    }
1204 	}
1205 
1206       err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m);
1207     }
1208 
1209   /* Discard any unnamed formal arguments.  */
1210   if (flag_mri)
1211     {
1212       formal_entry **pf;
1213 
1214       pf = &m->formals;
1215       while (*pf != NULL)
1216 	{
1217 	  if ((*pf)->name.len != 0)
1218 	    pf = &(*pf)->next;
1219 	  else
1220 	    {
1221 	      f = (*pf)->next;
1222 	      del_formal (*pf);
1223 	      *pf = f;
1224 	    }
1225 	}
1226     }
1227 
1228   sb_kill (&t);
1229   if (!err)
1230     macro_number++;
1231 
1232   return err;
1233 }
1234 
1235 /* Check for a macro.  If one is found, put the expansion into
1236    *EXPAND.  Return 1 if a macro is found, 0 otherwise.  */
1237 
1238 int
check_macro(const char * line,sb * expand,const char ** error,macro_entry ** info)1239 check_macro (const char *line, sb *expand,
1240 	     const char **error, macro_entry **info)
1241 {
1242   const char *s;
1243   char *copy, *cls;
1244   macro_entry *macro;
1245   sb line_sb;
1246 
1247   if (! is_name_beginner (*line)
1248       && (! flag_mri || *line != '.'))
1249     return 0;
1250 
1251   s = line + 1;
1252   while (is_part_of_name (*s))
1253     ++s;
1254   if (is_name_ender (*s))
1255     ++s;
1256 
1257   copy = xmemdup0 (line, s - line);
1258   for (cls = copy; *cls != '\0'; cls ++)
1259     *cls = TOLOWER (*cls);
1260 
1261   macro = str_hash_find (macro_hash, copy);
1262   free (copy);
1263 
1264   if (macro == NULL)
1265     return 0;
1266 
1267   /* Wrap the line up in an sb.  */
1268   sb_new (&line_sb);
1269   while (*s != '\0' && *s != '\n' && *s != '\r')
1270     sb_add_char (&line_sb, *s++);
1271 
1272   sb_new (expand);
1273   *error = macro_expand (0, &line_sb, macro, expand);
1274 
1275   sb_kill (&line_sb);
1276 
1277   /* Export the macro information if requested.  */
1278   if (info)
1279     *info = macro;
1280 
1281   return 1;
1282 }
1283 
1284 /* Delete a macro.  */
1285 
1286 void
delete_macro(const char * name)1287 delete_macro (const char *name)
1288 {
1289   char *copy;
1290   size_t i, len;
1291   macro_entry *macro;
1292 
1293   len = strlen (name);
1294   copy = XNEWVEC (char, len + 1);
1295   for (i = 0; i < len; ++i)
1296     copy[i] = TOLOWER (name[i]);
1297   copy[i] = '\0';
1298 
1299   macro = str_hash_find (macro_hash, copy);
1300   if (macro != NULL)
1301     str_hash_delete (macro_hash, copy);
1302   else
1303     as_warn (_("Attempt to purge non-existing macro `%s'"), copy);
1304   free (copy);
1305 }
1306 
1307 /* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
1308    combined macro definition and execution.  This returns NULL on
1309    success, or an error message otherwise.  */
1310 
1311 const char *
expand_irp(int irpc,size_t idx,sb * in,sb * out,size_t (* get_line)(sb *))1312 expand_irp (int irpc, size_t idx, sb *in, sb *out, size_t (*get_line) (sb *))
1313 {
1314   sb sub;
1315   formal_entry f;
1316   struct htab *h;
1317   const char *err = NULL;
1318 
1319   idx = sb_skip_white (idx, in);
1320 
1321   sb_new (&sub);
1322   if (! buffer_and_nest (NULL, "ENDR", &sub, get_line))
1323     {
1324       err = _("unexpected end of file in irp or irpc");
1325       goto out2;
1326     }
1327 
1328   sb_new (&f.name);
1329   sb_new (&f.def);
1330   sb_new (&f.actual);
1331 
1332   idx = get_token (idx, in, &f.name);
1333   if (f.name.len == 0)
1334     {
1335       err = _("missing model parameter");
1336       goto out1;
1337     }
1338 
1339   h = str_htab_create ();
1340 
1341   str_hash_insert (h, sb_terminate (&f.name), &f, 0);
1342 
1343   f.index = 1;
1344   f.next = NULL;
1345   f.type = FORMAL_OPTIONAL;
1346 
1347   sb_reset (out);
1348 
1349   idx = sb_skip_comma (idx, in);
1350   if (idx >= in->len)
1351     {
1352       /* Expand once with a null string.  */
1353       err = macro_expand_body (&sub, out, &f, h, 0);
1354     }
1355   else
1356     {
1357       bool in_quotes = false;
1358 
1359       if (irpc && in->ptr[idx] == '"')
1360 	{
1361 	  in_quotes = true;
1362 	  ++idx;
1363 	}
1364 
1365       while (idx < in->len)
1366 	{
1367 	  if (!irpc)
1368 	    idx = get_any_string (idx, in, &f.actual);
1369 	  else
1370 	    {
1371 	      if (in->ptr[idx] == '"')
1372 		{
1373 		  size_t nxt;
1374 
1375 		  if (irpc)
1376 		    in_quotes = ! in_quotes;
1377 
1378 		  nxt = sb_skip_white (idx + 1, in);
1379 		  if (nxt >= in->len)
1380 		    {
1381 		      idx = nxt;
1382 		      break;
1383 		    }
1384 		}
1385 	      sb_reset (&f.actual);
1386 	      sb_add_char (&f.actual, in->ptr[idx]);
1387 	      ++idx;
1388 	    }
1389 
1390 	  err = macro_expand_body (&sub, out, &f, h, 0);
1391 	  if (err != NULL)
1392 	    break;
1393 	  if (!irpc)
1394 	    idx = sb_skip_comma (idx, in);
1395 	  else if (! in_quotes)
1396 	    idx = sb_skip_white (idx, in);
1397 	}
1398     }
1399 
1400   htab_delete (h);
1401  out1:
1402   sb_kill (&f.actual);
1403   sb_kill (&f.def);
1404   sb_kill (&f.name);
1405  out2:
1406   sb_kill (&sub);
1407 
1408   return err;
1409 }
1410