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