]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/macro.c
apply mising piece of previous patch
[thirdparty/binutils-gdb.git] / gas / macro.c
CommitLineData
fea17916 1/* macro.c - macro support for gas
1c53c80d 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
29f8404c 3 Free Software Foundation, Inc.
252b5132
RH
4
5 Written by Steve and Judy Chamberlain of Cygnus Support,
6 sac@cygnus.com
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
29f8404c 23 02111-1307, USA. */
252b5132
RH
24
25#include "config.h"
26
fa6e9318 27#ifndef __GNUC__
252b5132
RH
28# if HAVE_ALLOCA_H
29# include <alloca.h>
30# else
31# ifdef _AIX
fa6e9318
AM
32/* Indented so that pre-ansi C compilers will ignore it, rather than
33 choke on it. Some versions of AIX require this to be the first
34 thing in the file. */
252b5132
RH
35 #pragma alloca
36# else
37# ifndef alloca /* predefined by HP cc +Olibcalls */
38# if !defined (__STDC__) && !defined (__hpux)
39extern char *alloca ();
40# else
41extern void *alloca ();
42# endif /* __STDC__, __hpux */
43# endif /* alloca */
44# endif /* _AIX */
45# endif /* HAVE_ALLOCA_H */
fa6e9318 46#endif /* __GNUC__ */
252b5132
RH
47
48#include <stdio.h>
49#ifdef HAVE_STRING_H
50#include <string.h>
51#else
52#include <strings.h>
53#endif
252b5132
RH
54#ifdef HAVE_STDLIB_H
55#include <stdlib.h>
56#endif
57#include "libiberty.h"
3882b010 58#include "safe-ctype.h"
252b5132
RH
59#include "sb.h"
60#include "hash.h"
61#include "macro.h"
62
63#include "asintl.h"
64
65/* The routines in this file handle macro definition and expansion.
fea17916 66 They are called by gas. */
252b5132 67
252b5132
RH
68/* Internal functions. */
69
254d758c
KH
70static int get_token (int, sb *, sb *);
71static int getstring (int, sb *, sb *);
72static int get_any_string (int, sb *, sb *, int, int);
73static int do_formals (macro_entry *, int, sb *);
74static int get_apost_token (int, sb *, sb *, int);
75static int sub_actual (int, sb *, sb *, struct hash_control *, int, sb *, int);
252b5132 76static const char *macro_expand_body
254d758c
KH
77 (sb *, sb *, formal_entry *, struct hash_control *, int);
78static const char *macro_expand (int, sb *, macro_entry *, sb *);
252b5132
RH
79
80#define ISWHITE(x) ((x) == ' ' || (x) == '\t')
81
82#define ISSEP(x) \
83 ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
84 || (x) == ')' || (x) == '(' \
85 || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
86
87#define ISBASE(x) \
88 ((x) == 'b' || (x) == 'B' \
89 || (x) == 'q' || (x) == 'Q' \
90 || (x) == 'h' || (x) == 'H' \
91 || (x) == 'd' || (x) == 'D')
92
93/* The macro hash table. */
94
1c53c80d 95struct hash_control *macro_hash;
252b5132
RH
96
97/* Whether any macros have been defined. */
98
99int macro_defined;
100
fea17916 101/* Whether we are in alternate syntax mode. */
252b5132
RH
102
103static int macro_alternate;
104
105/* Whether we are in MRI mode. */
106
107static int macro_mri;
108
109/* Whether we should strip '@' characters. */
110
111static int macro_strip_at;
112
113/* Function to use to parse an expression. */
114
254d758c 115static int (*macro_expr) (const char *, int, sb *, int *);
252b5132
RH
116
117/* Number of macro expansions that have been done. */
118
119static int macro_number;
120
121/* Initialize macro processing. */
122
123void
254d758c
KH
124macro_init (int alternate, int mri, int strip_at,
125 int (*expr) (const char *, int, sb *, int *))
252b5132
RH
126{
127 macro_hash = hash_new ();
128 macro_defined = 0;
129 macro_alternate = alternate;
130 macro_mri = mri;
131 macro_strip_at = strip_at;
132 macro_expr = expr;
133}
134
caa32fe5
NC
135/* Switch in and out of alternate mode on the fly. */
136
137void
2766e5e4 138macro_set_alternate (int alternate)
caa32fe5
NC
139{
140 macro_alternate = alternate;
141}
142
252b5132
RH
143/* Switch in and out of MRI mode on the fly. */
144
145void
254d758c 146macro_mri_mode (int mri)
252b5132
RH
147{
148 macro_mri = mri;
149}
150
151/* Read input lines till we get to a TO string.
152 Increase nesting depth if we get a FROM string.
153 Put the results into sb at PTR.
154 Add a new input line to an sb using GET_LINE.
155 Return 1 on success, 0 on unexpected EOF. */
156
157int
254d758c
KH
158buffer_and_nest (const char *from, const char *to, sb *ptr,
159 int (*get_line) (sb *))
252b5132
RH
160{
161 int from_len = strlen (from);
162 int to_len = strlen (to);
163 int depth = 1;
164 int line_start = ptr->len;
165
166 int more = get_line (ptr);
167
168 while (more)
169 {
29f8404c 170 /* Try and find the first pseudo op on the line. */
252b5132
RH
171 int i = line_start;
172
173 if (! macro_alternate && ! macro_mri)
174 {
175 /* With normal syntax we can suck what we want till we get
176 to the dot. With the alternate, labels have to start in
177 the first column, since we cant tell what's a label and
29f8404c 178 whats a pseudoop. */
252b5132 179
29f8404c 180 /* Skip leading whitespace. */
252b5132
RH
181 while (i < ptr->len && ISWHITE (ptr->ptr[i]))
182 i++;
183
29f8404c 184 /* Skip over a label. */
252b5132 185 while (i < ptr->len
3882b010 186 && (ISALNUM (ptr->ptr[i])
252b5132
RH
187 || ptr->ptr[i] == '_'
188 || ptr->ptr[i] == '$'))
189 i++;
190
29f8404c 191 /* And a colon. */
252b5132
RH
192 if (i < ptr->len
193 && ptr->ptr[i] == ':')
194 i++;
195
196 }
29f8404c 197 /* Skip trailing whitespace. */
252b5132
RH
198 while (i < ptr->len && ISWHITE (ptr->ptr[i]))
199 i++;
200
201 if (i < ptr->len && (ptr->ptr[i] == '.'
202 || macro_alternate
203 || macro_mri))
204 {
205 if (ptr->ptr[i] == '.')
29f8404c 206 i++;
c1eae114 207 if (strncasecmp (ptr->ptr + i, from, from_len) == 0
29f8404c 208 && (ptr->len == (i + from_len)
3882b010 209 || ! ISALNUM (ptr->ptr[i + from_len])))
252b5132 210 depth++;
c1eae114 211 if (strncasecmp (ptr->ptr + i, to, to_len) == 0
29f8404c 212 && (ptr->len == (i + to_len)
3882b010 213 || ! ISALNUM (ptr->ptr[i + to_len])))
252b5132
RH
214 {
215 depth--;
216 if (depth == 0)
217 {
29f8404c 218 /* Reset the string to not include the ending rune. */
252b5132
RH
219 ptr->len = line_start;
220 break;
221 }
222 }
223 }
224
0822d075
NC
225 /* Add the original end-of-line char to the end and keep running. */
226 sb_add_char (ptr, more);
252b5132
RH
227 line_start = ptr->len;
228 more = get_line (ptr);
229 }
230
231 /* Return 1 on success, 0 on unexpected EOF. */
232 return depth == 0;
233}
234
235/* Pick up a token. */
236
237static int
254d758c 238get_token (int idx, sb *in, sb *name)
252b5132
RH
239{
240 if (idx < in->len
3882b010 241 && (ISALPHA (in->ptr[idx])
252b5132
RH
242 || in->ptr[idx] == '_'
243 || in->ptr[idx] == '$'))
244 {
245 sb_add_char (name, in->ptr[idx++]);
246 while (idx < in->len
3882b010 247 && (ISALNUM (in->ptr[idx])
252b5132
RH
248 || in->ptr[idx] == '_'
249 || in->ptr[idx] == '$'))
250 {
251 sb_add_char (name, in->ptr[idx++]);
252 }
253 }
29f8404c 254 /* Ignore trailing &. */
252b5132
RH
255 if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
256 idx++;
257 return idx;
258}
259
260/* Pick up a string. */
261
262static int
254d758c 263getstring (int idx, sb *in, sb *acc)
252b5132
RH
264{
265 idx = sb_skip_white (idx, in);
266
267 while (idx < in->len
29f8404c 268 && (in->ptr[idx] == '"'
252b5132
RH
269 || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
270 || (in->ptr[idx] == '\'' && macro_alternate)))
271 {
272 if (in->ptr[idx] == '<')
273 {
274 int nest = 0;
275 idx++;
276 while ((in->ptr[idx] != '>' || nest)
277 && idx < in->len)
278 {
279 if (in->ptr[idx] == '!')
280 {
29f8404c 281 idx++;
252b5132
RH
282 sb_add_char (acc, in->ptr[idx++]);
283 }
284 else
285 {
286 if (in->ptr[idx] == '>')
287 nest--;
288 if (in->ptr[idx] == '<')
289 nest++;
290 sb_add_char (acc, in->ptr[idx++]);
291 }
292 }
293 idx++;
294 }
295 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
296 {
297 char tchar = in->ptr[idx];
c06ae4f2 298 int escaped = 0;
29f8404c 299
252b5132 300 idx++;
29f8404c 301
252b5132
RH
302 while (idx < in->len)
303 {
29f8404c 304 if (in->ptr[idx - 1] == '\\')
c06ae4f2
UC
305 escaped ^= 1;
306 else
307 escaped = 0;
308
252b5132
RH
309 if (macro_alternate && in->ptr[idx] == '!')
310 {
e972090a 311 idx ++;
29f8404c 312
1994a7c7
NC
313 sb_add_char (acc, in->ptr[idx]);
314
e972090a 315 idx ++;
252b5132 316 }
c06ae4f2
UC
317 else if (escaped && in->ptr[idx] == tchar)
318 {
319 sb_add_char (acc, tchar);
e972090a 320 idx ++;
c06ae4f2 321 }
252b5132
RH
322 else
323 {
324 if (in->ptr[idx] == tchar)
325 {
e972090a 326 idx ++;
29f8404c 327
252b5132
RH
328 if (idx >= in->len || in->ptr[idx] != tchar)
329 break;
330 }
29f8404c 331
252b5132 332 sb_add_char (acc, in->ptr[idx]);
e972090a 333 idx ++;
252b5132
RH
334 }
335 }
336 }
337 }
29f8404c 338
252b5132
RH
339 return idx;
340}
341
342/* Fetch string from the input stream,
343 rules:
344 'Bxyx<whitespace> -> return 'Bxyza
345 %<char> -> return string of decimal value of x
346 "<string>" -> return string
347 xyx<whitespace> -> return xyz
348*/
349
350static int
254d758c 351get_any_string (int idx, sb *in, sb *out, int expand, int pretend_quoted)
252b5132
RH
352{
353 sb_reset (out);
354 idx = sb_skip_white (idx, in);
355
356 if (idx < in->len)
357 {
9df59bba 358 if (in->len > idx + 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
252b5132
RH
359 {
360 while (!ISSEP (in->ptr[idx]))
361 sb_add_char (out, in->ptr[idx++]);
362 }
363 else if (in->ptr[idx] == '%'
364 && macro_alternate
365 && expand)
366 {
367 int val;
368 char buf[20];
29f8404c 369 /* Turns the next expression into a string. */
06f030db 370 /* xgettext: no-c-format */
252b5132
RH
371 idx = (*macro_expr) (_("% operator needs absolute expression"),
372 idx + 1,
373 in,
374 &val);
d1a6c242 375 sprintf (buf, "%d", val);
252b5132
RH
376 sb_add_string (out, buf);
377 }
378 else if (in->ptr[idx] == '"'
379 || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
380 || (macro_alternate && in->ptr[idx] == '\''))
381 {
382 if (macro_alternate
383 && ! macro_strip_at
384 && expand)
385 {
29f8404c
KH
386 /* Keep the quotes. */
387 sb_add_char (out, '\"');
252b5132
RH
388
389 idx = getstring (idx, in, out);
29f8404c 390 sb_add_char (out, '\"');
252b5132
RH
391 }
392 else
393 {
394 idx = getstring (idx, in, out);
395 }
396 }
29f8404c 397 else
252b5132 398 {
29f8404c 399 while (idx < in->len
252b5132
RH
400 && (in->ptr[idx] == '"'
401 || in->ptr[idx] == '\''
29f8404c 402 || pretend_quoted
252b5132
RH
403 || (in->ptr[idx] != ' '
404 && in->ptr[idx] != '\t'
405 && in->ptr[idx] != ','
406 && (in->ptr[idx] != '<'
407 || (! macro_alternate && ! macro_mri)))))
408 {
29f8404c 409 if (in->ptr[idx] == '"'
252b5132
RH
410 || in->ptr[idx] == '\'')
411 {
412 char tchar = in->ptr[idx];
413 sb_add_char (out, in->ptr[idx++]);
414 while (idx < in->len
415 && in->ptr[idx] != tchar)
29f8404c 416 sb_add_char (out, in->ptr[idx++]);
252b5132 417 if (idx == in->len)
29f8404c 418 return idx;
252b5132
RH
419 }
420 sb_add_char (out, in->ptr[idx++]);
421 }
422 }
423 }
424
425 return idx;
426}
427
428/* Pick up the formal parameters of a macro definition. */
429
430static int
254d758c 431do_formals (macro_entry *macro, int idx, sb *in)
252b5132
RH
432{
433 formal_entry **p = &macro->formals;
434
435 macro->formal_count = 0;
436 macro->formal_hash = hash_new ();
437 while (idx < in->len)
438 {
439 formal_entry *formal;
440
441 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
442
443 sb_new (&formal->name);
444 sb_new (&formal->def);
445 sb_new (&formal->actual);
446
447 idx = sb_skip_white (idx, in);
448 idx = get_token (idx, in, &formal->name);
449 if (formal->name.len == 0)
450 break;
451 idx = sb_skip_white (idx, in);
452 if (formal->name.len)
453 {
29f8404c 454 /* This is a formal. */
252b5132
RH
455 if (idx < in->len && in->ptr[idx] == '=')
456 {
29f8404c 457 /* Got a default. */
252b5132
RH
458 idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
459 }
460 }
461
29f8404c 462 /* Add to macro's hash table. */
252b5132
RH
463 hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
464
465 formal->index = macro->formal_count;
466 idx = sb_skip_comma (idx, in);
467 macro->formal_count++;
468 *p = formal;
469 p = &formal->next;
470 *p = NULL;
471 }
472
473 if (macro_mri)
474 {
475 formal_entry *formal;
476 const char *name;
477
478 /* Add a special NARG formal, which macro_expand will set to the
479 number of arguments. */
480 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
481
482 sb_new (&formal->name);
483 sb_new (&formal->def);
484 sb_new (&formal->actual);
485
486 /* The same MRI assemblers which treat '@' characters also use
487 the name $NARG. At least until we find an exception. */
488 if (macro_strip_at)
489 name = "$NARG";
490 else
491 name = "NARG";
492
493 sb_add_string (&formal->name, name);
494
29f8404c 495 /* Add to macro's hash table. */
252b5132
RH
496 hash_jam (macro->formal_hash, name, formal);
497
498 formal->index = NARG_INDEX;
499 *p = formal;
500 formal->next = NULL;
501 }
502
503 return idx;
504}
505
506/* Define a new macro. Returns NULL on success, otherwise returns an
507 error message. If NAMEP is not NULL, *NAMEP is set to the name of
508 the macro which was defined. */
509
510const char *
254d758c
KH
511define_macro (int idx, sb *in, sb *label,
512 int (*get_line) (sb *), const char **namep)
252b5132
RH
513{
514 macro_entry *macro;
515 sb name;
516 const char *namestr;
517
518 macro = (macro_entry *) xmalloc (sizeof (macro_entry));
519 sb_new (&macro->sub);
520 sb_new (&name);
521
522 macro->formal_count = 0;
523 macro->formals = 0;
524
525 idx = sb_skip_white (idx, in);
526 if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
527 return _("unexpected end of file in macro definition");
528 if (label != NULL && label->len != 0)
529 {
530 sb_add_sb (&name, label);
531 if (idx < in->len && in->ptr[idx] == '(')
532 {
29f8404c 533 /* It's the label: MACRO (formals,...) sort */
252b5132
RH
534 idx = do_formals (macro, idx + 1, in);
535 if (in->ptr[idx] != ')')
536 return _("missing ) after formals");
537 }
538 else
539 {
29f8404c 540 /* It's the label: MACRO formals,... sort */
252b5132
RH
541 idx = do_formals (macro, idx, in);
542 }
543 }
544 else
545 {
546 idx = get_token (idx, in, &name);
547 idx = sb_skip_comma (idx, in);
548 idx = do_formals (macro, idx, in);
549 }
550
29f8404c 551 /* And stick it in the macro hash table. */
252b5132 552 for (idx = 0; idx < name.len; idx++)
3882b010 553 name.ptr[idx] = TOLOWER (name.ptr[idx]);
252b5132
RH
554 namestr = sb_terminate (&name);
555 hash_jam (macro_hash, namestr, (PTR) macro);
556
557 macro_defined = 1;
558
559 if (namep != NULL)
560 *namep = namestr;
561
562 return NULL;
563}
564
565/* Scan a token, and then skip KIND. */
566
567static int
254d758c 568get_apost_token (int idx, sb *in, sb *name, int kind)
252b5132
RH
569{
570 idx = get_token (idx, in, name);
571 if (idx < in->len
572 && in->ptr[idx] == kind
573 && (! macro_mri || macro_strip_at)
574 && (! macro_strip_at || kind == '@'))
575 idx++;
576 return idx;
577}
578
579/* Substitute the actual value for a formal parameter. */
580
581static int
254d758c
KH
582sub_actual (int start, sb *in, sb *t, struct hash_control *formal_hash,
583 int kind, sb *out, int copyifnotthere)
252b5132
RH
584{
585 int src;
586 formal_entry *ptr;
587
588 src = get_apost_token (start, in, t, kind);
589 /* See if it's in the macro's hash table, unless this is
590 macro_strip_at and kind is '@' and the token did not end in '@'. */
591 if (macro_strip_at
592 && kind == '@'
593 && (src == start || in->ptr[src - 1] != '@'))
594 ptr = NULL;
595 else
596 ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
597 if (ptr)
598 {
599 if (ptr->actual.len)
600 {
601 sb_add_sb (out, &ptr->actual);
602 }
603 else
604 {
605 sb_add_sb (out, &ptr->def);
606 }
607 }
608 else if (kind == '&')
609 {
610 /* Doing this permits people to use & in macro bodies. */
611 sb_add_char (out, '&');
c1ed1235 612 sb_add_sb (out, t);
252b5132
RH
613 }
614 else if (copyifnotthere)
615 {
616 sb_add_sb (out, t);
617 }
29f8404c 618 else
252b5132
RH
619 {
620 sb_add_char (out, '\\');
621 sb_add_sb (out, t);
622 }
623 return src;
624}
625
626/* Expand the body of a macro. */
627
628static const char *
254d758c
KH
629macro_expand_body (sb *in, sb *out, formal_entry *formals,
630 struct hash_control *formal_hash, int locals)
252b5132
RH
631{
632 sb t;
633 int src = 0;
634 int inquote = 0;
635 formal_entry *loclist = NULL;
636
637 sb_new (&t);
638
639 while (src < in->len)
640 {
641 if (in->ptr[src] == '&')
642 {
643 sb_reset (&t);
644 if (macro_mri)
645 {
646 if (src + 1 < in->len && in->ptr[src + 1] == '&')
647 src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
648 else
649 sb_add_char (out, in->ptr[src++]);
650 }
651 else
652 {
653 /* FIXME: Why do we do this? */
654 src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
655 }
656 }
657 else if (in->ptr[src] == '\\')
658 {
659 src++;
fea17916 660 if (in->ptr[src] == '(')
252b5132 661 {
29f8404c 662 /* Sub in till the next ')' literally. */
252b5132
RH
663 src++;
664 while (src < in->len && in->ptr[src] != ')')
665 {
666 sb_add_char (out, in->ptr[src++]);
667 }
668 if (in->ptr[src] == ')')
669 src++;
670 else
671 return _("missplaced )");
672 }
673 else if (in->ptr[src] == '@')
674 {
29f8404c 675 /* Sub in the macro invocation number. */
252b5132
RH
676
677 char buffer[10];
678 src++;
a2984248 679 sprintf (buffer, "%d", macro_number);
252b5132
RH
680 sb_add_string (out, buffer);
681 }
682 else if (in->ptr[src] == '&')
683 {
684 /* This is a preprocessor variable name, we don't do them
29f8404c 685 here. */
252b5132
RH
686 sb_add_char (out, '\\');
687 sb_add_char (out, '&');
688 src++;
689 }
3882b010 690 else if (macro_mri && ISALNUM (in->ptr[src]))
252b5132
RH
691 {
692 int ind;
693 formal_entry *f;
694
3882b010 695 if (ISDIGIT (in->ptr[src]))
252b5132 696 ind = in->ptr[src] - '0';
3882b010 697 else if (ISUPPER (in->ptr[src]))
252b5132
RH
698 ind = in->ptr[src] - 'A' + 10;
699 else
700 ind = in->ptr[src] - 'a' + 10;
701 ++src;
702 for (f = formals; f != NULL; f = f->next)
703 {
704 if (f->index == ind - 1)
705 {
706 if (f->actual.len != 0)
707 sb_add_sb (out, &f->actual);
708 else
709 sb_add_sb (out, &f->def);
710 break;
711 }
712 }
713 }
714 else
715 {
716 sb_reset (&t);
717 src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
718 }
719 }
720 else if ((macro_alternate || macro_mri)
3882b010 721 && (ISALPHA (in->ptr[src])
252b5132
RH
722 || in->ptr[src] == '_'
723 || in->ptr[src] == '$')
724 && (! inquote
725 || ! macro_strip_at
726 || (src > 0 && in->ptr[src - 1] == '@')))
727 {
728 if (! locals
729 || src + 5 >= in->len
730 || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
731 || ! ISWHITE (in->ptr[src + 5]))
732 {
733 sb_reset (&t);
734 src = sub_actual (src, in, &t, formal_hash,
735 (macro_strip_at && inquote) ? '@' : '\'',
736 out, 1);
737 }
738 else
739 {
740 formal_entry *f;
741
742 src = sb_skip_white (src + 5, in);
fea17916 743 while (in->ptr[src] != '\n')
252b5132
RH
744 {
745 static int loccnt;
746 char buf[20];
747 const char *err;
748
749 f = (formal_entry *) xmalloc (sizeof (formal_entry));
750 sb_new (&f->name);
751 sb_new (&f->def);
752 sb_new (&f->actual);
753 f->index = LOCAL_INDEX;
754 f->next = loclist;
755 loclist = f;
756
757 src = get_token (src, in, &f->name);
758 ++loccnt;
759 sprintf (buf, "LL%04x", loccnt);
760 sb_add_string (&f->actual, buf);
761
762 err = hash_jam (formal_hash, sb_terminate (&f->name), f);
763 if (err != NULL)
764 return err;
765
766 src = sb_skip_comma (src, in);
767 }
768 }
769 }
252b5132
RH
770 else if (in->ptr[src] == '"'
771 || (macro_mri && in->ptr[src] == '\''))
772 {
773 inquote = !inquote;
774 sb_add_char (out, in->ptr[src++]);
775 }
776 else if (in->ptr[src] == '@' && macro_strip_at)
777 {
778 ++src;
779 if (src < in->len
780 && in->ptr[src] == '@')
781 {
782 sb_add_char (out, '@');
783 ++src;
784 }
785 }
786 else if (macro_mri
787 && in->ptr[src] == '='
788 && src + 1 < in->len
789 && in->ptr[src + 1] == '=')
790 {
791 formal_entry *ptr;
792
793 sb_reset (&t);
794 src = get_token (src + 2, in, &t);
795 ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
796 if (ptr == NULL)
797 {
798 /* FIXME: We should really return a warning string here,
799 but we can't, because the == might be in the MRI
800 comment field, and, since the nature of the MRI
801 comment field depends upon the exact instruction
802 being used, we don't have enough information here to
803 figure out whether it is or not. Instead, we leave
804 the == in place, which should cause a syntax error if
805 it is not in a comment. */
806 sb_add_char (out, '=');
807 sb_add_char (out, '=');
808 sb_add_sb (out, &t);
809 }
810 else
811 {
812 if (ptr->actual.len)
813 {
814 sb_add_string (out, "-1");
815 }
816 else
817 {
818 sb_add_char (out, '0');
819 }
820 }
821 }
822 else
823 {
824 sb_add_char (out, in->ptr[src++]);
825 }
826 }
827
828 sb_kill (&t);
829
830 while (loclist != NULL)
831 {
832 formal_entry *f;
833
834 f = loclist->next;
1af6dcd2
ILT
835 /* Setting the value to NULL effectively deletes the entry. We
836 avoid calling hash_delete because it doesn't reclaim memory. */
837 hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
252b5132
RH
838 sb_kill (&loclist->name);
839 sb_kill (&loclist->def);
840 sb_kill (&loclist->actual);
841 free (loclist);
842 loclist = f;
843 }
844
845 return NULL;
846}
847
848/* Assign values to the formal parameters of a macro, and expand the
849 body. */
850
851static const char *
254d758c 852macro_expand (int idx, sb *in, macro_entry *m, sb *out)
252b5132
RH
853{
854 sb t;
855 formal_entry *ptr;
856 formal_entry *f;
857 int is_positional = 0;
858 int is_keyword = 0;
859 int narg = 0;
860 const char *err;
861
862 sb_new (&t);
29f8404c
KH
863
864 /* Reset any old value the actuals may have. */
252b5132 865 for (f = m->formals; f; f = f->next)
29f8404c 866 sb_reset (&f->actual);
252b5132
RH
867 f = m->formals;
868 while (f != NULL && f->index < 0)
869 f = f->next;
870
871 if (macro_mri)
872 {
873 /* The macro may be called with an optional qualifier, which may
874 be referred to in the macro body as \0. */
875 if (idx < in->len && in->ptr[idx] == '.')
d1a6c242
KH
876 {
877 /* The Microtec assembler ignores this if followed by a white space.
878 (Macro invocation with empty extension) */
879 idx++;
880 if ( idx < in->len
881 && in->ptr[idx] != ' '
882 && in->ptr[idx] != '\t')
883 {
884 formal_entry *n;
885
886 n = (formal_entry *) xmalloc (sizeof (formal_entry));
887 sb_new (&n->name);
888 sb_new (&n->def);
889 sb_new (&n->actual);
890 n->index = QUAL_INDEX;
891
892 n->next = m->formals;
893 m->formals = n;
894
895 idx = get_any_string (idx, in, &n->actual, 1, 0);
896 }
897 }
898 }
252b5132 899
29f8404c 900 /* Peel off the actuals and store them away in the hash tables' actuals. */
252b5132 901 idx = sb_skip_white (idx, in);
fea17916 902 while (idx < in->len)
252b5132
RH
903 {
904 int scan;
905
29f8404c 906 /* Look and see if it's a positional or keyword arg. */
252b5132
RH
907 scan = idx;
908 while (scan < in->len
909 && !ISSEP (in->ptr[scan])
910 && !(macro_mri && in->ptr[scan] == '\'')
911 && (!macro_alternate && in->ptr[scan] != '='))
912 scan++;
913 if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
914 {
915 is_keyword = 1;
916
917 /* It's OK to go from positional to keyword. */
918
919 /* This is a keyword arg, fetch the formal name and
29f8404c 920 then the actual stuff. */
252b5132
RH
921 sb_reset (&t);
922 idx = get_token (idx, in, &t);
923 if (in->ptr[idx] != '=')
924 return _("confusion in formal parameters");
925
29f8404c 926 /* Lookup the formal in the macro's list. */
252b5132
RH
927 ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
928 if (!ptr)
929 return _("macro formal argument does not exist");
930 else
931 {
29f8404c 932 /* Insert this value into the right place. */
252b5132
RH
933 sb_reset (&ptr->actual);
934 idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
935 if (ptr->actual.len > 0)
936 ++narg;
937 }
938 }
939 else
940 {
29f8404c 941 /* This is a positional arg. */
252b5132
RH
942 is_positional = 1;
943 if (is_keyword)
944 return _("can't mix positional and keyword arguments");
945
946 if (!f)
947 {
948 formal_entry **pf;
949 int c;
950
951 if (!macro_mri)
952 return _("too many positional arguments");
953
954 f = (formal_entry *) xmalloc (sizeof (formal_entry));
955 sb_new (&f->name);
956 sb_new (&f->def);
957 sb_new (&f->actual);
958 f->next = NULL;
959
960 c = -1;
961 for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
962 if ((*pf)->index >= c)
963 c = (*pf)->index + 1;
964 if (c == -1)
965 c = 0;
966 *pf = f;
967 f->index = c;
968 }
969
970 sb_reset (&f->actual);
971 idx = get_any_string (idx, in, &f->actual, 1, 0);
972 if (f->actual.len > 0)
973 ++narg;
974 do
975 {
976 f = f->next;
977 }
978 while (f != NULL && f->index < 0);
979 }
980
981 if (! macro_mri)
982 idx = sb_skip_comma (idx, in);
983 else
984 {
985 if (in->ptr[idx] == ',')
986 ++idx;
987 if (ISWHITE (in->ptr[idx]))
988 break;
989 }
990 }
991
992 if (macro_mri)
993 {
994 char buffer[20];
995
996 sb_reset (&t);
997 sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
998 ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
999 sb_reset (&ptr->actual);
1000 sprintf (buffer, "%d", narg);
1001 sb_add_string (&ptr->actual, buffer);
1002 }
1003
fea17916 1004 err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, 1);
252b5132
RH
1005 if (err != NULL)
1006 return err;
1007
1008 /* Discard any unnamed formal arguments. */
1009 if (macro_mri)
1010 {
1011 formal_entry **pf;
1012
1013 pf = &m->formals;
1014 while (*pf != NULL)
1015 {
1016 if ((*pf)->name.len != 0)
1017 pf = &(*pf)->next;
1018 else
1019 {
1020 sb_kill (&(*pf)->name);
1021 sb_kill (&(*pf)->def);
1022 sb_kill (&(*pf)->actual);
1023 f = (*pf)->next;
1024 free (*pf);
1025 *pf = f;
1026 }
1027 }
1028 }
1029
1030 sb_kill (&t);
1031 macro_number++;
1032
1033 return NULL;
1034}
1035
1036/* Check for a macro. If one is found, put the expansion into
fea17916 1037 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
252b5132
RH
1038
1039int
254d758c
KH
1040check_macro (const char *line, sb *expand,
1041 const char **error, macro_entry **info)
252b5132
RH
1042{
1043 const char *s;
1044 char *copy, *cs;
1045 macro_entry *macro;
1046 sb line_sb;
1047
3882b010 1048 if (! ISALPHA (*line)
252b5132
RH
1049 && *line != '_'
1050 && *line != '$'
1051 && (! macro_mri || *line != '.'))
1052 return 0;
1053
1054 s = line + 1;
3882b010 1055 while (ISALNUM (*s)
252b5132
RH
1056 || *s == '_'
1057 || *s == '$')
1058 ++s;
1059
1060 copy = (char *) alloca (s - line + 1);
1061 memcpy (copy, line, s - line);
1062 copy[s - line] = '\0';
1063 for (cs = copy; *cs != '\0'; cs++)
3882b010 1064 *cs = TOLOWER (*cs);
252b5132
RH
1065
1066 macro = (macro_entry *) hash_find (macro_hash, copy);
1067
1068 if (macro == NULL)
1069 return 0;
1070
1071 /* Wrap the line up in an sb. */
1072 sb_new (&line_sb);
1073 while (*s != '\0' && *s != '\n' && *s != '\r')
1074 sb_add_char (&line_sb, *s++);
1075
1076 sb_new (expand);
fea17916 1077 *error = macro_expand (0, &line_sb, macro, expand);
252b5132
RH
1078
1079 sb_kill (&line_sb);
1080
29f8404c 1081 /* Export the macro information if requested. */
9f10757c
TW
1082 if (info)
1083 *info = macro;
1084
252b5132
RH
1085 return 1;
1086}
1087
1088/* Delete a macro. */
1089
1090void
254d758c 1091delete_macro (const char *name)
252b5132
RH
1092{
1093 hash_delete (macro_hash, name);
1094}
1095
1096/* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
1097 combined macro definition and execution. This returns NULL on
1098 success, or an error message otherwise. */
1099
1100const char *
254d758c 1101expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
252b5132
RH
1102{
1103 const char *mn;
1104 sb sub;
1105 formal_entry f;
1106 struct hash_control *h;
1107 const char *err;
1108
1109 if (irpc)
1110 mn = "IRPC";
1111 else
1112 mn = "IRP";
1113
1114 idx = sb_skip_white (idx, in);
1115
1116 sb_new (&sub);
1117 if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
1118 return _("unexpected end of file in irp or irpc");
29f8404c 1119
252b5132
RH
1120 sb_new (&f.name);
1121 sb_new (&f.def);
1122 sb_new (&f.actual);
1123
1124 idx = get_token (idx, in, &f.name);
1125 if (f.name.len == 0)
1126 return _("missing model parameter");
1127
1128 h = hash_new ();
1129 err = hash_jam (h, sb_terminate (&f.name), &f);
1130 if (err != NULL)
1131 return err;
1132
1133 f.index = 1;
1134 f.next = NULL;
1135
1136 sb_reset (out);
1137
1138 idx = sb_skip_comma (idx, in);
fea17916 1139 if (idx >= in->len)
252b5132
RH
1140 {
1141 /* Expand once with a null string. */
fea17916 1142 err = macro_expand_body (&sub, out, &f, h, 0);
252b5132
RH
1143 if (err != NULL)
1144 return err;
1145 }
1146 else
1147 {
1148 if (irpc && in->ptr[idx] == '"')
1149 ++idx;
fea17916 1150 while (idx < in->len)
252b5132
RH
1151 {
1152 if (!irpc)
1153 idx = get_any_string (idx, in, &f.actual, 1, 0);
1154 else
1155 {
1156 if (in->ptr[idx] == '"')
1157 {
1158 int nxt;
1159
1160 nxt = sb_skip_white (idx + 1, in);
fea17916 1161 if (nxt >= in->len)
252b5132
RH
1162 {
1163 idx = nxt;
1164 break;
1165 }
1166 }
1167 sb_reset (&f.actual);
1168 sb_add_char (&f.actual, in->ptr[idx]);
1169 ++idx;
1170 }
fea17916 1171 err = macro_expand_body (&sub, out, &f, h, 0);
252b5132
RH
1172 if (err != NULL)
1173 return err;
1174 if (!irpc)
1175 idx = sb_skip_comma (idx, in);
1176 else
1177 idx = sb_skip_white (idx, in);
1178 }
1179 }
1180
1181 hash_die (h);
1182 sb_kill (&sub);
1183
1184 return NULL;
1185}