Coverage Report

Created: 2026-03-10 08:46

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