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