Coverage Report

Created: 2024-05-21 06:29

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