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