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