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