Coverage Report

Created: 2025-06-24 06:45

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