/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 = ¯o->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 (¯o->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 (¯o->sub); |
665 | 2.89k | sb_new (&name); |
666 | 2.89k | macro->file = as_where (¯o->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", ¯o->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 | } |