* lib/insight-support.exp (_gdbtk_export_target_info): Add
[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
fa6e9318 27#ifndef __GNUC__
252b5132
RH
28# if HAVE_ALLOCA_H
29# include <alloca.h>
30# else
31# ifdef _AIX
fa6e9318
AM
32/* Indented so that pre-ansi C compilers will ignore it, rather than
33 choke on it. Some versions of AIX require this to be the first
34 thing in the file. */
252b5132
RH
35 #pragma alloca
36# else
37# ifndef alloca /* predefined by HP cc +Olibcalls */
38# if !defined (__STDC__) && !defined (__hpux)
39extern char *alloca ();
40# else
41extern void *alloca ();
42# endif /* __STDC__, __hpux */
43# endif /* alloca */
44# endif /* _AIX */
45# endif /* HAVE_ALLOCA_H */
fa6e9318 46#endif /* __GNUC__ */
252b5132
RH
47
48#include <stdio.h>
49#ifdef HAVE_STRING_H
50#include <string.h>
51#else
52#include <strings.h>
53#endif
54#include <ctype.h>
55#ifdef HAVE_STDLIB_H
56#include <stdlib.h>
57#endif
58#include "libiberty.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 both gasp and gas. */
67
252b5132
RH
68/* Internal functions. */
69
70static int get_token PARAMS ((int, sb *, sb *));
71static int getstring PARAMS ((int, sb *, sb *));
72static int get_any_string PARAMS ((int, sb *, sb *, int, int));
73static int do_formals PARAMS ((macro_entry *, int, sb *));
74static int get_apost_token PARAMS ((int, sb *, sb *, int));
75static int sub_actual
76 PARAMS ((int, sb *, sb *, struct hash_control *, int, sb *, int));
77static const char *macro_expand_body
78 PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int, int));
79static const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *, int));
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
96static struct hash_control *macro_hash;
97
98/* Whether any macros have been defined. */
99
100int macro_defined;
101
102/* Whether we are in GASP alternate mode. */
103
104static int macro_alternate;
105
106/* Whether we are in MRI mode. */
107
108static int macro_mri;
109
110/* Whether we should strip '@' characters. */
111
112static int macro_strip_at;
113
114/* Function to use to parse an expression. */
115
116static int (*macro_expr) PARAMS ((const char *, int, sb *, int *));
117
118/* Number of macro expansions that have been done. */
119
120static int macro_number;
121
122/* Initialize macro processing. */
123
124void
125macro_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
141void
142macro_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
154int
155buffer_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 {
29f8404c 170 /* Try and find the first pseudo op on the line. */
252b5132
RH
171 int i = line_start;
172
173 if (! macro_alternate && ! macro_mri)
174 {
175 /* With normal syntax we can suck what we want till we get
176 to the dot. With the alternate, labels have to start in
177 the first column, since we cant tell what's a label and
29f8404c 178 whats a pseudoop. */
252b5132 179
29f8404c 180 /* Skip leading whitespace. */
252b5132
RH
181 while (i < ptr->len && ISWHITE (ptr->ptr[i]))
182 i++;
183
29f8404c 184 /* Skip over a label. */
252b5132
RH
185 while (i < ptr->len
186 && (isalnum ((unsigned char) ptr->ptr[i])
187 || ptr->ptr[i] == '_'
188 || ptr->ptr[i] == '$'))
189 i++;
190
29f8404c 191 /* And a colon. */
252b5132
RH
192 if (i < ptr->len
193 && ptr->ptr[i] == ':')
194 i++;
195
196 }
29f8404c 197 /* Skip trailing whitespace. */
252b5132
RH
198 while (i < ptr->len && ISWHITE (ptr->ptr[i]))
199 i++;
200
201 if (i < ptr->len && (ptr->ptr[i] == '.'
202 || macro_alternate
203 || macro_mri))
204 {
205 if (ptr->ptr[i] == '.')
29f8404c 206 i++;
c1eae114 207 if (strncasecmp (ptr->ptr + i, from, from_len) == 0
29f8404c
KH
208 && (ptr->len == (i + from_len)
209 || ! isalnum (ptr->ptr[i + from_len])))
252b5132 210 depth++;
c1eae114 211 if (strncasecmp (ptr->ptr + i, to, to_len) == 0
29f8404c
KH
212 && (ptr->len == (i + to_len)
213 || ! isalnum (ptr->ptr[i + to_len])))
252b5132
RH
214 {
215 depth--;
216 if (depth == 0)
217 {
29f8404c 218 /* Reset the string to not include the ending rune. */
252b5132
RH
219 ptr->len = line_start;
220 break;
221 }
222 }
223 }
224
29f8404c 225 /* Add a CR to the end and keep running. */
252b5132
RH
226 sb_add_char (ptr, '\n');
227 line_start = ptr->len;
228 more = get_line (ptr);
229 }
230
231 /* Return 1 on success, 0 on unexpected EOF. */
232 return depth == 0;
233}
234
235/* Pick up a token. */
236
237static int
238get_token (idx, in, name)
239 int idx;
240 sb *in;
241 sb *name;
242{
243 if (idx < in->len
244 && (isalpha ((unsigned char) 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 ((unsigned char) in->ptr[idx])
251 || in->ptr[idx] == '_'
252 || in->ptr[idx] == '$'))
253 {
254 sb_add_char (name, in->ptr[idx++]);
255 }
256 }
29f8404c 257 /* Ignore trailing &. */
252b5132
RH
258 if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
259 idx++;
260 return idx;
261}
262
263/* Pick up a string. */
264
265static int
266getstring (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
29f8404c 274 && (in->ptr[idx] == '"'
252b5132
RH
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 {
29f8404c 287 idx++;
252b5132
RH
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];
c06ae4f2 304 int escaped = 0;
29f8404c 305
252b5132 306 idx++;
29f8404c 307
252b5132
RH
308 while (idx < in->len)
309 {
29f8404c 310 if (in->ptr[idx - 1] == '\\')
c06ae4f2
UC
311 escaped ^= 1;
312 else
313 escaped = 0;
314
252b5132
RH
315 if (macro_alternate && in->ptr[idx] == '!')
316 {
e972090a 317 idx ++;
29f8404c 318
1994a7c7
NC
319 sb_add_char (acc, in->ptr[idx]);
320
e972090a 321 idx ++;
252b5132 322 }
c06ae4f2
UC
323 else if (escaped && in->ptr[idx] == tchar)
324 {
325 sb_add_char (acc, tchar);
e972090a 326 idx ++;
c06ae4f2 327 }
252b5132
RH
328 else
329 {
330 if (in->ptr[idx] == tchar)
331 {
e972090a 332 idx ++;
29f8404c 333
252b5132
RH
334 if (idx >= in->len || in->ptr[idx] != tchar)
335 break;
336 }
29f8404c 337
252b5132 338 sb_add_char (acc, in->ptr[idx]);
e972090a 339 idx ++;
252b5132
RH
340 }
341 }
342 }
343 }
29f8404c 344
252b5132
RH
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
356static int
357get_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 {
29f8404c 369 if (in->len > 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
252b5132
RH
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];
29f8404c 380 /* Turns the next expression into a string. */
252b5132
RH
381 idx = (*macro_expr) (_("% operator needs absolute expression"),
382 idx + 1,
383 in,
384 &val);
385 sprintf(buf, "%d", val);
386 sb_add_string (out, buf);
387 }
388 else if (in->ptr[idx] == '"'
389 || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
390 || (macro_alternate && in->ptr[idx] == '\''))
391 {
392 if (macro_alternate
393 && ! macro_strip_at
394 && expand)
395 {
29f8404c
KH
396 /* Keep the quotes. */
397 sb_add_char (out, '\"');
252b5132
RH
398
399 idx = getstring (idx, in, out);
29f8404c 400 sb_add_char (out, '\"');
252b5132
RH
401 }
402 else
403 {
404 idx = getstring (idx, in, out);
405 }
406 }
29f8404c 407 else
252b5132 408 {
29f8404c 409 while (idx < in->len
252b5132
RH
410 && (in->ptr[idx] == '"'
411 || in->ptr[idx] == '\''
29f8404c 412 || pretend_quoted
252b5132
RH
413 || (in->ptr[idx] != ' '
414 && in->ptr[idx] != '\t'
415 && in->ptr[idx] != ','
416 && (in->ptr[idx] != '<'
417 || (! macro_alternate && ! macro_mri)))))
418 {
29f8404c 419 if (in->ptr[idx] == '"'
252b5132
RH
420 || in->ptr[idx] == '\'')
421 {
422 char tchar = in->ptr[idx];
423 sb_add_char (out, in->ptr[idx++]);
424 while (idx < in->len
425 && in->ptr[idx] != tchar)
29f8404c 426 sb_add_char (out, in->ptr[idx++]);
252b5132 427 if (idx == in->len)
29f8404c 428 return idx;
252b5132
RH
429 }
430 sb_add_char (out, in->ptr[idx++]);
431 }
432 }
433 }
434
435 return idx;
436}
437
438/* Pick up the formal parameters of a macro definition. */
439
440static int
441do_formals (macro, idx, in)
442 macro_entry *macro;
443 int idx;
444 sb *in;
445{
446 formal_entry **p = &macro->formals;
447
448 macro->formal_count = 0;
449 macro->formal_hash = hash_new ();
450 while (idx < in->len)
451 {
452 formal_entry *formal;
453
454 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
455
456 sb_new (&formal->name);
457 sb_new (&formal->def);
458 sb_new (&formal->actual);
459
460 idx = sb_skip_white (idx, in);
461 idx = get_token (idx, in, &formal->name);
462 if (formal->name.len == 0)
463 break;
464 idx = sb_skip_white (idx, in);
465 if (formal->name.len)
466 {
29f8404c 467 /* This is a formal. */
252b5132
RH
468 if (idx < in->len && in->ptr[idx] == '=')
469 {
29f8404c 470 /* Got a default. */
252b5132
RH
471 idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
472 }
473 }
474
29f8404c 475 /* Add to macro's hash table. */
252b5132
RH
476 hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
477
478 formal->index = macro->formal_count;
479 idx = sb_skip_comma (idx, in);
480 macro->formal_count++;
481 *p = formal;
482 p = &formal->next;
483 *p = NULL;
484 }
485
486 if (macro_mri)
487 {
488 formal_entry *formal;
489 const char *name;
490
491 /* Add a special NARG formal, which macro_expand will set to the
492 number of arguments. */
493 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
494
495 sb_new (&formal->name);
496 sb_new (&formal->def);
497 sb_new (&formal->actual);
498
499 /* The same MRI assemblers which treat '@' characters also use
500 the name $NARG. At least until we find an exception. */
501 if (macro_strip_at)
502 name = "$NARG";
503 else
504 name = "NARG";
505
506 sb_add_string (&formal->name, name);
507
29f8404c 508 /* Add to macro's hash table. */
252b5132
RH
509 hash_jam (macro->formal_hash, name, formal);
510
511 formal->index = NARG_INDEX;
512 *p = formal;
513 formal->next = NULL;
514 }
515
516 return idx;
517}
518
519/* Define a new macro. Returns NULL on success, otherwise returns an
520 error message. If NAMEP is not NULL, *NAMEP is set to the name of
521 the macro which was defined. */
522
523const char *
524define_macro (idx, in, label, get_line, namep)
525 int idx;
526 sb *in;
527 sb *label;
528 int (*get_line) PARAMS ((sb *));
529 const char **namep;
530{
531 macro_entry *macro;
532 sb name;
533 const char *namestr;
534
535 macro = (macro_entry *) xmalloc (sizeof (macro_entry));
536 sb_new (&macro->sub);
537 sb_new (&name);
538
539 macro->formal_count = 0;
540 macro->formals = 0;
541
542 idx = sb_skip_white (idx, in);
543 if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
544 return _("unexpected end of file in macro definition");
545 if (label != NULL && label->len != 0)
546 {
547 sb_add_sb (&name, label);
548 if (idx < in->len && in->ptr[idx] == '(')
549 {
29f8404c 550 /* It's the label: MACRO (formals,...) sort */
252b5132
RH
551 idx = do_formals (macro, idx + 1, in);
552 if (in->ptr[idx] != ')')
553 return _("missing ) after formals");
554 }
555 else
556 {
29f8404c 557 /* It's the label: MACRO formals,... sort */
252b5132
RH
558 idx = do_formals (macro, idx, in);
559 }
560 }
561 else
562 {
563 idx = get_token (idx, in, &name);
564 idx = sb_skip_comma (idx, in);
565 idx = do_formals (macro, idx, in);
566 }
567
29f8404c 568 /* And stick it in the macro hash table. */
252b5132
RH
569 for (idx = 0; idx < name.len; idx++)
570 if (isupper ((unsigned char) name.ptr[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
585static int
586get_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
603static int
604sub_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 }
29f8404c 645 else
252b5132
RH
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
655static const char *
656macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
657 sb *in;
658 sb *out;
659 formal_entry *formals;
660 struct hash_control *formal_hash;
661 int comment_char;
662 int locals;
663{
664 sb t;
665 int src = 0;
666 int inquote = 0;
667 formal_entry *loclist = NULL;
668
669 sb_new (&t);
670
671 while (src < in->len)
672 {
673 if (in->ptr[src] == '&')
674 {
675 sb_reset (&t);
676 if (macro_mri)
677 {
678 if (src + 1 < in->len && in->ptr[src + 1] == '&')
679 src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
680 else
681 sb_add_char (out, in->ptr[src++]);
682 }
683 else
684 {
685 /* FIXME: Why do we do this? */
686 src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
687 }
688 }
689 else if (in->ptr[src] == '\\')
690 {
691 src++;
692 if (in->ptr[src] == comment_char && comment_char != '\0')
693 {
29f8404c 694 /* This is a comment, just drop the rest of the line. */
252b5132
RH
695 while (src < in->len
696 && in->ptr[src] != '\n')
697 src++;
698 }
699 else if (in->ptr[src] == '(')
700 {
29f8404c 701 /* Sub in till the next ')' literally. */
252b5132
RH
702 src++;
703 while (src < in->len && in->ptr[src] != ')')
704 {
705 sb_add_char (out, in->ptr[src++]);
706 }
707 if (in->ptr[src] == ')')
708 src++;
709 else
710 return _("missplaced )");
711 }
712 else if (in->ptr[src] == '@')
713 {
29f8404c 714 /* Sub in the macro invocation number. */
252b5132
RH
715
716 char buffer[10];
717 src++;
a2984248 718 sprintf (buffer, "%d", macro_number);
252b5132
RH
719 sb_add_string (out, buffer);
720 }
721 else if (in->ptr[src] == '&')
722 {
723 /* This is a preprocessor variable name, we don't do them
29f8404c 724 here. */
252b5132
RH
725 sb_add_char (out, '\\');
726 sb_add_char (out, '&');
727 src++;
728 }
729 else if (macro_mri
730 && isalnum ((unsigned char) in->ptr[src]))
731 {
732 int ind;
733 formal_entry *f;
734
735 if (isdigit ((unsigned char) in->ptr[src]))
736 ind = in->ptr[src] - '0';
737 else if (isupper ((unsigned char) in->ptr[src]))
738 ind = in->ptr[src] - 'A' + 10;
739 else
740 ind = in->ptr[src] - 'a' + 10;
741 ++src;
742 for (f = formals; f != NULL; f = f->next)
743 {
744 if (f->index == ind - 1)
745 {
746 if (f->actual.len != 0)
747 sb_add_sb (out, &f->actual);
748 else
749 sb_add_sb (out, &f->def);
750 break;
751 }
752 }
753 }
754 else
755 {
756 sb_reset (&t);
757 src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
758 }
759 }
760 else if ((macro_alternate || macro_mri)
761 && (isalpha ((unsigned char) in->ptr[src])
762 || in->ptr[src] == '_'
763 || in->ptr[src] == '$')
764 && (! inquote
765 || ! macro_strip_at
766 || (src > 0 && in->ptr[src - 1] == '@')))
767 {
768 if (! locals
769 || src + 5 >= in->len
770 || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
771 || ! ISWHITE (in->ptr[src + 5]))
772 {
773 sb_reset (&t);
774 src = sub_actual (src, in, &t, formal_hash,
775 (macro_strip_at && inquote) ? '@' : '\'',
776 out, 1);
777 }
778 else
779 {
780 formal_entry *f;
781
782 src = sb_skip_white (src + 5, in);
783 while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
784 {
785 static int loccnt;
786 char buf[20];
787 const char *err;
788
789 f = (formal_entry *) xmalloc (sizeof (formal_entry));
790 sb_new (&f->name);
791 sb_new (&f->def);
792 sb_new (&f->actual);
793 f->index = LOCAL_INDEX;
794 f->next = loclist;
795 loclist = f;
796
797 src = get_token (src, in, &f->name);
798 ++loccnt;
799 sprintf (buf, "LL%04x", loccnt);
800 sb_add_string (&f->actual, buf);
801
802 err = hash_jam (formal_hash, sb_terminate (&f->name), f);
803 if (err != NULL)
804 return err;
805
806 src = sb_skip_comma (src, in);
807 }
808 }
809 }
810 else if (comment_char != '\0'
811 && in->ptr[src] == comment_char
812 && src + 1 < in->len
813 && in->ptr[src + 1] == comment_char
814 && !inquote)
815 {
816 /* Two comment chars in a row cause the rest of the line to
817 be dropped. */
818 while (src < in->len && in->ptr[src] != '\n')
819 src++;
820 }
821 else if (in->ptr[src] == '"'
822 || (macro_mri && in->ptr[src] == '\''))
823 {
824 inquote = !inquote;
825 sb_add_char (out, in->ptr[src++]);
826 }
827 else if (in->ptr[src] == '@' && macro_strip_at)
828 {
829 ++src;
830 if (src < in->len
831 && in->ptr[src] == '@')
832 {
833 sb_add_char (out, '@');
834 ++src;
835 }
836 }
837 else if (macro_mri
838 && in->ptr[src] == '='
839 && src + 1 < in->len
840 && in->ptr[src + 1] == '=')
841 {
842 formal_entry *ptr;
843
844 sb_reset (&t);
845 src = get_token (src + 2, in, &t);
846 ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
847 if (ptr == NULL)
848 {
849 /* FIXME: We should really return a warning string here,
850 but we can't, because the == might be in the MRI
851 comment field, and, since the nature of the MRI
852 comment field depends upon the exact instruction
853 being used, we don't have enough information here to
854 figure out whether it is or not. Instead, we leave
855 the == in place, which should cause a syntax error if
856 it is not in a comment. */
857 sb_add_char (out, '=');
858 sb_add_char (out, '=');
859 sb_add_sb (out, &t);
860 }
861 else
862 {
863 if (ptr->actual.len)
864 {
865 sb_add_string (out, "-1");
866 }
867 else
868 {
869 sb_add_char (out, '0');
870 }
871 }
872 }
873 else
874 {
875 sb_add_char (out, in->ptr[src++]);
876 }
877 }
878
879 sb_kill (&t);
880
881 while (loclist != NULL)
882 {
883 formal_entry *f;
884
885 f = loclist->next;
1af6dcd2
ILT
886 /* Setting the value to NULL effectively deletes the entry. We
887 avoid calling hash_delete because it doesn't reclaim memory. */
888 hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
252b5132
RH
889 sb_kill (&loclist->name);
890 sb_kill (&loclist->def);
891 sb_kill (&loclist->actual);
892 free (loclist);
893 loclist = f;
894 }
895
896 return NULL;
897}
898
899/* Assign values to the formal parameters of a macro, and expand the
900 body. */
901
902static const char *
903macro_expand (idx, in, m, out, comment_char)
904 int idx;
905 sb *in;
906 macro_entry *m;
907 sb *out;
908 int comment_char;
909{
910 sb t;
911 formal_entry *ptr;
912 formal_entry *f;
913 int is_positional = 0;
914 int is_keyword = 0;
915 int narg = 0;
916 const char *err;
917
918 sb_new (&t);
29f8404c
KH
919
920 /* Reset any old value the actuals may have. */
252b5132 921 for (f = m->formals; f; f = f->next)
29f8404c 922 sb_reset (&f->actual);
252b5132
RH
923 f = m->formals;
924 while (f != NULL && f->index < 0)
925 f = f->next;
926
927 if (macro_mri)
928 {
929 /* The macro may be called with an optional qualifier, which may
930 be referred to in the macro body as \0. */
931 if (idx < in->len && in->ptr[idx] == '.')
e1f44d10
NC
932 {
933 /* The Microtec assembler ignores this if followed by a white space.
934 (Macro invocation with empty extension) */
935 idx++;
936 if ( idx < in->len
937 && in->ptr[idx] != ' '
938 && in->ptr[idx] != '\t')
939 {
940 formal_entry *n;
941
942 n = (formal_entry *) xmalloc (sizeof (formal_entry));
943 sb_new (&n->name);
944 sb_new (&n->def);
945 sb_new (&n->actual);
946 n->index = QUAL_INDEX;
947
948 n->next = m->formals;
949 m->formals = n;
950
951 idx = get_any_string (idx, in, &n->actual, 1, 0);
952 }
953 }
954 }
252b5132 955
29f8404c 956 /* Peel off the actuals and store them away in the hash tables' actuals. */
252b5132
RH
957 idx = sb_skip_white (idx, in);
958 while (idx < in->len && in->ptr[idx] != comment_char)
959 {
960 int scan;
961
29f8404c 962 /* Look and see if it's a positional or keyword arg. */
252b5132
RH
963 scan = idx;
964 while (scan < in->len
965 && !ISSEP (in->ptr[scan])
966 && !(macro_mri && in->ptr[scan] == '\'')
967 && (!macro_alternate && in->ptr[scan] != '='))
968 scan++;
969 if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
970 {
971 is_keyword = 1;
972
973 /* It's OK to go from positional to keyword. */
974
975 /* This is a keyword arg, fetch the formal name and
29f8404c 976 then the actual stuff. */
252b5132
RH
977 sb_reset (&t);
978 idx = get_token (idx, in, &t);
979 if (in->ptr[idx] != '=')
980 return _("confusion in formal parameters");
981
29f8404c 982 /* Lookup the formal in the macro's list. */
252b5132
RH
983 ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
984 if (!ptr)
985 return _("macro formal argument does not exist");
986 else
987 {
29f8404c 988 /* Insert this value into the right place. */
252b5132
RH
989 sb_reset (&ptr->actual);
990 idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
991 if (ptr->actual.len > 0)
992 ++narg;
993 }
994 }
995 else
996 {
29f8404c 997 /* This is a positional arg. */
252b5132
RH
998 is_positional = 1;
999 if (is_keyword)
1000 return _("can't mix positional and keyword arguments");
1001
1002 if (!f)
1003 {
1004 formal_entry **pf;
1005 int c;
1006
1007 if (!macro_mri)
1008 return _("too many positional arguments");
1009
1010 f = (formal_entry *) xmalloc (sizeof (formal_entry));
1011 sb_new (&f->name);
1012 sb_new (&f->def);
1013 sb_new (&f->actual);
1014 f->next = NULL;
1015
1016 c = -1;
1017 for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
1018 if ((*pf)->index >= c)
1019 c = (*pf)->index + 1;
1020 if (c == -1)
1021 c = 0;
1022 *pf = f;
1023 f->index = c;
1024 }
1025
1026 sb_reset (&f->actual);
1027 idx = get_any_string (idx, in, &f->actual, 1, 0);
1028 if (f->actual.len > 0)
1029 ++narg;
1030 do
1031 {
1032 f = f->next;
1033 }
1034 while (f != NULL && f->index < 0);
1035 }
1036
1037 if (! macro_mri)
1038 idx = sb_skip_comma (idx, in);
1039 else
1040 {
1041 if (in->ptr[idx] == ',')
1042 ++idx;
1043 if (ISWHITE (in->ptr[idx]))
1044 break;
1045 }
1046 }
1047
1048 if (macro_mri)
1049 {
1050 char buffer[20];
1051
1052 sb_reset (&t);
1053 sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
1054 ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1055 sb_reset (&ptr->actual);
1056 sprintf (buffer, "%d", narg);
1057 sb_add_string (&ptr->actual, buffer);
1058 }
1059
1060 err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash,
1061 comment_char, 1);
1062 if (err != NULL)
1063 return err;
1064
1065 /* Discard any unnamed formal arguments. */
1066 if (macro_mri)
1067 {
1068 formal_entry **pf;
1069
1070 pf = &m->formals;
1071 while (*pf != NULL)
1072 {
1073 if ((*pf)->name.len != 0)
1074 pf = &(*pf)->next;
1075 else
1076 {
1077 sb_kill (&(*pf)->name);
1078 sb_kill (&(*pf)->def);
1079 sb_kill (&(*pf)->actual);
1080 f = (*pf)->next;
1081 free (*pf);
1082 *pf = f;
1083 }
1084 }
1085 }
1086
1087 sb_kill (&t);
1088 macro_number++;
1089
1090 return NULL;
1091}
1092
1093/* Check for a macro. If one is found, put the expansion into
1094 *EXPAND. COMMENT_CHAR is the comment character--this is used by
1095 gasp. Return 1 if a macro is found, 0 otherwise. */
1096
1097int
9f10757c 1098check_macro (line, expand, comment_char, error, info)
252b5132
RH
1099 const char *line;
1100 sb *expand;
1101 int comment_char;
1102 const char **error;
9f10757c 1103 macro_entry **info;
252b5132
RH
1104{
1105 const char *s;
1106 char *copy, *cs;
1107 macro_entry *macro;
1108 sb line_sb;
1109
1110 if (! isalpha ((unsigned char) *line)
1111 && *line != '_'
1112 && *line != '$'
1113 && (! macro_mri || *line != '.'))
1114 return 0;
1115
1116 s = line + 1;
1117 while (isalnum ((unsigned char) *s)
1118 || *s == '_'
1119 || *s == '$')
1120 ++s;
1121
1122 copy = (char *) alloca (s - line + 1);
1123 memcpy (copy, line, s - line);
1124 copy[s - line] = '\0';
1125 for (cs = copy; *cs != '\0'; cs++)
1126 if (isupper ((unsigned char) *cs))
1127 *cs = tolower (*cs);
1128
1129 macro = (macro_entry *) hash_find (macro_hash, copy);
1130
1131 if (macro == NULL)
1132 return 0;
1133
1134 /* Wrap the line up in an sb. */
1135 sb_new (&line_sb);
1136 while (*s != '\0' && *s != '\n' && *s != '\r')
1137 sb_add_char (&line_sb, *s++);
1138
1139 sb_new (expand);
1140 *error = macro_expand (0, &line_sb, macro, expand, comment_char);
1141
1142 sb_kill (&line_sb);
1143
29f8404c 1144 /* Export the macro information if requested. */
9f10757c
TW
1145 if (info)
1146 *info = macro;
1147
252b5132
RH
1148 return 1;
1149}
1150
1151/* Delete a macro. */
1152
1153void
1154delete_macro (name)
1155 const char *name;
1156{
1157 hash_delete (macro_hash, name);
1158}
1159
1160/* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
1161 combined macro definition and execution. This returns NULL on
1162 success, or an error message otherwise. */
1163
1164const char *
1165expand_irp (irpc, idx, in, out, get_line, comment_char)
1166 int irpc;
1167 int idx;
1168 sb *in;
1169 sb *out;
1170 int (*get_line) PARAMS ((sb *));
1171 int comment_char;
1172{
1173 const char *mn;
1174 sb sub;
1175 formal_entry f;
1176 struct hash_control *h;
1177 const char *err;
1178
1179 if (irpc)
1180 mn = "IRPC";
1181 else
1182 mn = "IRP";
1183
1184 idx = sb_skip_white (idx, in);
1185
1186 sb_new (&sub);
1187 if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
1188 return _("unexpected end of file in irp or irpc");
29f8404c 1189
252b5132
RH
1190 sb_new (&f.name);
1191 sb_new (&f.def);
1192 sb_new (&f.actual);
1193
1194 idx = get_token (idx, in, &f.name);
1195 if (f.name.len == 0)
1196 return _("missing model parameter");
1197
1198 h = hash_new ();
1199 err = hash_jam (h, sb_terminate (&f.name), &f);
1200 if (err != NULL)
1201 return err;
1202
1203 f.index = 1;
1204 f.next = NULL;
1205
1206 sb_reset (out);
1207
1208 idx = sb_skip_comma (idx, in);
1209 if (idx >= in->len || in->ptr[idx] == comment_char)
1210 {
1211 /* Expand once with a null string. */
1212 err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1213 if (err != NULL)
1214 return err;
1215 }
1216 else
1217 {
1218 if (irpc && in->ptr[idx] == '"')
1219 ++idx;
1220 while (idx < in->len && in->ptr[idx] != comment_char)
1221 {
1222 if (!irpc)
1223 idx = get_any_string (idx, in, &f.actual, 1, 0);
1224 else
1225 {
1226 if (in->ptr[idx] == '"')
1227 {
1228 int nxt;
1229
1230 nxt = sb_skip_white (idx + 1, in);
1231 if (nxt >= in->len || in->ptr[nxt] == comment_char)
1232 {
1233 idx = nxt;
1234 break;
1235 }
1236 }
1237 sb_reset (&f.actual);
1238 sb_add_char (&f.actual, in->ptr[idx]);
1239 ++idx;
1240 }
1241 err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
1242 if (err != NULL)
1243 return err;
1244 if (!irpc)
1245 idx = sb_skip_comma (idx, in);
1246 else
1247 idx = sb_skip_white (idx, in);
1248 }
1249 }
1250
1251 hash_die (h);
1252 sb_kill (&sub);
1253
1254 return NULL;
1255}
This page took 0.19458 seconds and 4 git commands to generate.