(macro_set_alternate): Use ISO C90 formatting.
[deliverable/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 (int, sb *, sb *);
71 static int getstring (int, sb *, sb *);
72 static int get_any_string (int, sb *, sb *, int, int);
73 static int do_formals (macro_entry *, int, sb *);
74 static int get_apost_token (int, sb *, sb *, int);
75 static int sub_actual (int, sb *, sb *, struct hash_control *, int, sb *, int);
76 static const char *macro_expand_body
77 (sb *, sb *, formal_entry *, struct hash_control *, int);
78 static const char *macro_expand (int, sb *, macro_entry *, sb *);
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
95 struct hash_control *macro_hash;
96
97 /* Whether any macros have been defined. */
98
99 int macro_defined;
100
101 /* Whether we are in alternate syntax mode. */
102
103 static int macro_alternate;
104
105 /* Whether we are in MRI mode. */
106
107 static int macro_mri;
108
109 /* Whether we should strip '@' characters. */
110
111 static int macro_strip_at;
112
113 /* Function to use to parse an expression. */
114
115 static int (*macro_expr) (const char *, int, sb *, int *);
116
117 /* Number of macro expansions that have been done. */
118
119 static int macro_number;
120
121 /* Initialize macro processing. */
122
123 void
124 macro_init (int alternate, int mri, int strip_at,
125 int (*expr) (const char *, int, sb *, int *))
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
135 /* Switch in and out of alternate mode on the fly. */
136
137 void
138 macro_set_alternate (int alternate)
139 {
140 macro_alternate = alternate;
141 }
142
143 /* Switch in and out of MRI mode on the fly. */
144
145 void
146 macro_mri_mode (int mri)
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
157 int
158 buffer_and_nest (const char *from, const char *to, sb *ptr,
159 int (*get_line) (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 (int idx, sb *in, sb *name)
239 {
240 if (idx < in->len
241 && (ISALPHA (in->ptr[idx])
242 || in->ptr[idx] == '_'
243 || in->ptr[idx] == '$'))
244 {
245 sb_add_char (name, in->ptr[idx++]);
246 while (idx < in->len
247 && (ISALNUM (in->ptr[idx])
248 || in->ptr[idx] == '_'
249 || in->ptr[idx] == '$'))
250 {
251 sb_add_char (name, in->ptr[idx++]);
252 }
253 }
254 /* Ignore trailing &. */
255 if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
256 idx++;
257 return idx;
258 }
259
260 /* Pick up a string. */
261
262 static int
263 getstring (int idx, sb *in, sb *acc)
264 {
265 idx = sb_skip_white (idx, in);
266
267 while (idx < in->len
268 && (in->ptr[idx] == '"'
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 {
281 idx++;
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];
298 int escaped = 0;
299
300 idx++;
301
302 while (idx < in->len)
303 {
304 if (in->ptr[idx - 1] == '\\')
305 escaped ^= 1;
306 else
307 escaped = 0;
308
309 if (macro_alternate && in->ptr[idx] == '!')
310 {
311 idx ++;
312
313 sb_add_char (acc, in->ptr[idx]);
314
315 idx ++;
316 }
317 else if (escaped && in->ptr[idx] == tchar)
318 {
319 sb_add_char (acc, tchar);
320 idx ++;
321 }
322 else
323 {
324 if (in->ptr[idx] == tchar)
325 {
326 idx ++;
327
328 if (idx >= in->len || in->ptr[idx] != tchar)
329 break;
330 }
331
332 sb_add_char (acc, in->ptr[idx]);
333 idx ++;
334 }
335 }
336 }
337 }
338
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
350 static int
351 get_any_string (int idx, sb *in, sb *out, int expand, int pretend_quoted)
352 {
353 sb_reset (out);
354 idx = sb_skip_white (idx, in);
355
356 if (idx < in->len)
357 {
358 if (in->len > idx + 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
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];
369 /* Turns the next expression into a string. */
370 /* xgettext: no-c-format */
371 idx = (*macro_expr) (_("% operator needs absolute expression"),
372 idx + 1,
373 in,
374 &val);
375 sprintf (buf, "%d", val);
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 {
386 /* Keep the quotes. */
387 sb_add_char (out, '\"');
388
389 idx = getstring (idx, in, out);
390 sb_add_char (out, '\"');
391 }
392 else
393 {
394 idx = getstring (idx, in, out);
395 }
396 }
397 else
398 {
399 while (idx < in->len
400 && (in->ptr[idx] == '"'
401 || in->ptr[idx] == '\''
402 || pretend_quoted
403 || (in->ptr[idx] != ' '
404 && in->ptr[idx] != '\t'
405 && in->ptr[idx] != ','
406 && (in->ptr[idx] != '<'
407 || (! macro_alternate && ! macro_mri)))))
408 {
409 if (in->ptr[idx] == '"'
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)
416 sb_add_char (out, in->ptr[idx++]);
417 if (idx == in->len)
418 return idx;
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
430 static int
431 do_formals (macro_entry *macro, int idx, sb *in)
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 {
454 /* This is a formal. */
455 if (idx < in->len && in->ptr[idx] == '=')
456 {
457 /* Got a default. */
458 idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
459 }
460 }
461
462 /* Add to macro's hash table. */
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
495 /* Add to macro's hash table. */
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
510 const char *
511 define_macro (int idx, sb *in, sb *label,
512 int (*get_line) (sb *), const char **namep)
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 {
533 /* It's the label: MACRO (formals,...) sort */
534 idx = do_formals (macro, idx + 1, in);
535 if (in->ptr[idx] != ')')
536 return _("missing ) after formals");
537 }
538 else
539 {
540 /* It's the label: MACRO formals,... sort */
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
551 /* And stick it in the macro hash table. */
552 for (idx = 0; idx < name.len; idx++)
553 name.ptr[idx] = TOLOWER (name.ptr[idx]);
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
567 static int
568 get_apost_token (int idx, sb *in, sb *name, int kind)
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
581 static int
582 sub_actual (int start, sb *in, sb *t, struct hash_control *formal_hash,
583 int kind, sb *out, int copyifnotthere)
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, '&');
612 sb_add_sb (out, t);
613 }
614 else if (copyifnotthere)
615 {
616 sb_add_sb (out, t);
617 }
618 else
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
628 static const char *
629 macro_expand_body (sb *in, sb *out, formal_entry *formals,
630 struct hash_control *formal_hash, int locals)
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++;
660 if (in->ptr[src] == '(')
661 {
662 /* Sub in till the next ')' literally. */
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 {
675 /* Sub in the macro invocation number. */
676
677 char buffer[10];
678 src++;
679 sprintf (buffer, "%d", macro_number);
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
685 here. */
686 sb_add_char (out, '\\');
687 sb_add_char (out, '&');
688 src++;
689 }
690 else if (macro_mri && ISALNUM (in->ptr[src]))
691 {
692 int ind;
693 formal_entry *f;
694
695 if (ISDIGIT (in->ptr[src]))
696 ind = in->ptr[src] - '0';
697 else if (ISUPPER (in->ptr[src]))
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)
721 && (ISALPHA (in->ptr[src])
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);
743 while (in->ptr[src] != '\n')
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 }
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;
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);
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
851 static const char *
852 macro_expand (int idx, sb *in, macro_entry *m, sb *out)
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);
863
864 /* Reset any old value the actuals may have. */
865 for (f = m->formals; f; f = f->next)
866 sb_reset (&f->actual);
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] == '.')
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 }
899
900 /* Peel off the actuals and store them away in the hash tables' actuals. */
901 idx = sb_skip_white (idx, in);
902 while (idx < in->len)
903 {
904 int scan;
905
906 /* Look and see if it's a positional or keyword arg. */
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
920 then the actual stuff. */
921 sb_reset (&t);
922 idx = get_token (idx, in, &t);
923 if (in->ptr[idx] != '=')
924 return _("confusion in formal parameters");
925
926 /* Lookup the formal in the macro's list. */
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 {
932 /* Insert this value into the right place. */
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 {
941 /* This is a positional arg. */
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
1004 err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, 1);
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
1037 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
1038
1039 int
1040 check_macro (const char *line, sb *expand,
1041 const char **error, macro_entry **info)
1042 {
1043 const char *s;
1044 char *copy, *cs;
1045 macro_entry *macro;
1046 sb line_sb;
1047
1048 if (! ISALPHA (*line)
1049 && *line != '_'
1050 && *line != '$'
1051 && (! macro_mri || *line != '.'))
1052 return 0;
1053
1054 s = line + 1;
1055 while (ISALNUM (*s)
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++)
1064 *cs = TOLOWER (*cs);
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);
1077 *error = macro_expand (0, &line_sb, macro, expand);
1078
1079 sb_kill (&line_sb);
1080
1081 /* Export the macro information if requested. */
1082 if (info)
1083 *info = macro;
1084
1085 return 1;
1086 }
1087
1088 /* Delete a macro. */
1089
1090 void
1091 delete_macro (const char *name)
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
1100 const char *
1101 expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
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");
1119
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);
1139 if (idx >= in->len)
1140 {
1141 /* Expand once with a null string. */
1142 err = macro_expand_body (&sub, out, &f, h, 0);
1143 if (err != NULL)
1144 return err;
1145 }
1146 else
1147 {
1148 if (irpc && in->ptr[idx] == '"')
1149 ++idx;
1150 while (idx < in->len)
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);
1161 if (nxt >= in->len)
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 }
1171 err = macro_expand_body (&sub, out, &f, h, 0);
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 }
This page took 0.078076 seconds and 5 git commands to generate.