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