* NEWS: Mention improved location expression support.
[deliverable/binutils-gdb.git] / gas / macro.c
CommitLineData
fea17916 1/* macro.c - macro support for gas
1c53c80d 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
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
252b5132
RH
54#ifdef HAVE_STDLIB_H
55#include <stdlib.h>
56#endif
57#include "libiberty.h"
3882b010 58#include "safe-ctype.h"
252b5132
RH
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.
fea17916 66 They are called by gas. */
252b5132 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
fea17916
NC
78 PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int));
79static const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *));
252b5132
RH
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
1c53c80d 96struct hash_control *macro_hash;
252b5132
RH
97
98/* Whether any macros have been defined. */
99
100int macro_defined;
101
fea17916 102/* Whether we are in alternate syntax mode. */
252b5132
RH
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 185 while (i < ptr->len
3882b010 186 && (ISALNUM (ptr->ptr[i])
252b5132
RH
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 208 && (ptr->len == (i + from_len)
3882b010 209 || ! ISALNUM (ptr->ptr[i + from_len])))
252b5132 210 depth++;
c1eae114 211 if (strncasecmp (ptr->ptr + i, to, to_len) == 0
29f8404c 212 && (ptr->len == (i + to_len)
3882b010 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
0822d075
NC
225 /* Add the original end-of-line char to the end and keep running. */
226 sb_add_char (ptr, more);
252b5132
RH
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
3882b010 244 && (ISALPHA (in->ptr[idx])
252b5132
RH
245 || in->ptr[idx] == '_'
246 || in->ptr[idx] == '$'))
247 {
248 sb_add_char (name, in->ptr[idx++]);
249 while (idx < in->len
3882b010 250 && (ISALNUM (in->ptr[idx])
252b5132
RH
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 {
9df59bba 369 if (in->len > idx + 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. */
06f030db 381 /* xgettext: no-c-format */
252b5132
RH
382 idx = (*macro_expr) (_("% operator needs absolute expression"),
383 idx + 1,
384 in,
385 &val);
d1a6c242 386 sprintf (buf, "%d", val);
252b5132
RH
387 sb_add_string (out, buf);
388 }
389 else if (in->ptr[idx] == '"'
390 || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
391 || (macro_alternate && in->ptr[idx] == '\''))
392 {
393 if (macro_alternate
394 && ! macro_strip_at
395 && expand)
396 {
29f8404c
KH
397 /* Keep the quotes. */
398 sb_add_char (out, '\"');
252b5132
RH
399
400 idx = getstring (idx, in, out);
29f8404c 401 sb_add_char (out, '\"');
252b5132
RH
402 }
403 else
404 {
405 idx = getstring (idx, in, out);
406 }
407 }
29f8404c 408 else
252b5132 409 {
29f8404c 410 while (idx < in->len
252b5132
RH
411 && (in->ptr[idx] == '"'
412 || in->ptr[idx] == '\''
29f8404c 413 || pretend_quoted
252b5132
RH
414 || (in->ptr[idx] != ' '
415 && in->ptr[idx] != '\t'
416 && in->ptr[idx] != ','
417 && (in->ptr[idx] != '<'
418 || (! macro_alternate && ! macro_mri)))))
419 {
29f8404c 420 if (in->ptr[idx] == '"'
252b5132
RH
421 || in->ptr[idx] == '\'')
422 {
423 char tchar = in->ptr[idx];
424 sb_add_char (out, in->ptr[idx++]);
425 while (idx < in->len
426 && in->ptr[idx] != tchar)
29f8404c 427 sb_add_char (out, in->ptr[idx++]);
252b5132 428 if (idx == in->len)
29f8404c 429 return idx;
252b5132
RH
430 }
431 sb_add_char (out, in->ptr[idx++]);
432 }
433 }
434 }
435
436 return idx;
437}
438
439/* Pick up the formal parameters of a macro definition. */
440
441static int
442do_formals (macro, idx, in)
443 macro_entry *macro;
444 int idx;
445 sb *in;
446{
447 formal_entry **p = &macro->formals;
448
449 macro->formal_count = 0;
450 macro->formal_hash = hash_new ();
451 while (idx < in->len)
452 {
453 formal_entry *formal;
454
455 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
456
457 sb_new (&formal->name);
458 sb_new (&formal->def);
459 sb_new (&formal->actual);
460
461 idx = sb_skip_white (idx, in);
462 idx = get_token (idx, in, &formal->name);
463 if (formal->name.len == 0)
464 break;
465 idx = sb_skip_white (idx, in);
466 if (formal->name.len)
467 {
29f8404c 468 /* This is a formal. */
252b5132
RH
469 if (idx < in->len && in->ptr[idx] == '=')
470 {
29f8404c 471 /* Got a default. */
252b5132
RH
472 idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
473 }
474 }
475
29f8404c 476 /* Add to macro's hash table. */
252b5132
RH
477 hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
478
479 formal->index = macro->formal_count;
480 idx = sb_skip_comma (idx, in);
481 macro->formal_count++;
482 *p = formal;
483 p = &formal->next;
484 *p = NULL;
485 }
486
487 if (macro_mri)
488 {
489 formal_entry *formal;
490 const char *name;
491
492 /* Add a special NARG formal, which macro_expand will set to the
493 number of arguments. */
494 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
495
496 sb_new (&formal->name);
497 sb_new (&formal->def);
498 sb_new (&formal->actual);
499
500 /* The same MRI assemblers which treat '@' characters also use
501 the name $NARG. At least until we find an exception. */
502 if (macro_strip_at)
503 name = "$NARG";
504 else
505 name = "NARG";
506
507 sb_add_string (&formal->name, name);
508
29f8404c 509 /* Add to macro's hash table. */
252b5132
RH
510 hash_jam (macro->formal_hash, name, formal);
511
512 formal->index = NARG_INDEX;
513 *p = formal;
514 formal->next = NULL;
515 }
516
517 return idx;
518}
519
520/* Define a new macro. Returns NULL on success, otherwise returns an
521 error message. If NAMEP is not NULL, *NAMEP is set to the name of
522 the macro which was defined. */
523
524const char *
525define_macro (idx, in, label, get_line, namep)
526 int idx;
527 sb *in;
528 sb *label;
529 int (*get_line) PARAMS ((sb *));
530 const char **namep;
531{
532 macro_entry *macro;
533 sb name;
534 const char *namestr;
535
536 macro = (macro_entry *) xmalloc (sizeof (macro_entry));
537 sb_new (&macro->sub);
538 sb_new (&name);
539
540 macro->formal_count = 0;
541 macro->formals = 0;
542
543 idx = sb_skip_white (idx, in);
544 if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
545 return _("unexpected end of file in macro definition");
546 if (label != NULL && label->len != 0)
547 {
548 sb_add_sb (&name, label);
549 if (idx < in->len && in->ptr[idx] == '(')
550 {
29f8404c 551 /* It's the label: MACRO (formals,...) sort */
252b5132
RH
552 idx = do_formals (macro, idx + 1, in);
553 if (in->ptr[idx] != ')')
554 return _("missing ) after formals");
555 }
556 else
557 {
29f8404c 558 /* It's the label: MACRO formals,... sort */
252b5132
RH
559 idx = do_formals (macro, idx, in);
560 }
561 }
562 else
563 {
564 idx = get_token (idx, in, &name);
565 idx = sb_skip_comma (idx, in);
566 idx = do_formals (macro, idx, in);
567 }
568
29f8404c 569 /* And stick it in the macro hash table. */
252b5132 570 for (idx = 0; idx < name.len; idx++)
3882b010 571 name.ptr[idx] = TOLOWER (name.ptr[idx]);
252b5132
RH
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, '&');
c1ed1235 640 sb_add_sb (out, t);
252b5132
RH
641 }
642 else if (copyifnotthere)
643 {
644 sb_add_sb (out, t);
645 }
29f8404c 646 else
252b5132
RH
647 {
648 sb_add_char (out, '\\');
649 sb_add_sb (out, t);
650 }
651 return src;
652}
653
654/* Expand the body of a macro. */
655
656static const char *
fea17916 657macro_expand_body (in, out, formals, formal_hash, locals)
252b5132
RH
658 sb *in;
659 sb *out;
660 formal_entry *formals;
661 struct hash_control *formal_hash;
252b5132
RH
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++;
fea17916 692 if (in->ptr[src] == '(')
252b5132 693 {
29f8404c 694 /* Sub in till the next ')' literally. */
252b5132
RH
695 src++;
696 while (src < in->len && in->ptr[src] != ')')
697 {
698 sb_add_char (out, in->ptr[src++]);
699 }
700 if (in->ptr[src] == ')')
701 src++;
702 else
703 return _("missplaced )");
704 }
705 else if (in->ptr[src] == '@')
706 {
29f8404c 707 /* Sub in the macro invocation number. */
252b5132
RH
708
709 char buffer[10];
710 src++;
a2984248 711 sprintf (buffer, "%d", macro_number);
252b5132
RH
712 sb_add_string (out, buffer);
713 }
714 else if (in->ptr[src] == '&')
715 {
716 /* This is a preprocessor variable name, we don't do them
29f8404c 717 here. */
252b5132
RH
718 sb_add_char (out, '\\');
719 sb_add_char (out, '&');
720 src++;
721 }
3882b010 722 else if (macro_mri && ISALNUM (in->ptr[src]))
252b5132
RH
723 {
724 int ind;
725 formal_entry *f;
726
3882b010 727 if (ISDIGIT (in->ptr[src]))
252b5132 728 ind = in->ptr[src] - '0';
3882b010 729 else if (ISUPPER (in->ptr[src]))
252b5132
RH
730 ind = in->ptr[src] - 'A' + 10;
731 else
732 ind = in->ptr[src] - 'a' + 10;
733 ++src;
734 for (f = formals; f != NULL; f = f->next)
735 {
736 if (f->index == ind - 1)
737 {
738 if (f->actual.len != 0)
739 sb_add_sb (out, &f->actual);
740 else
741 sb_add_sb (out, &f->def);
742 break;
743 }
744 }
745 }
746 else
747 {
748 sb_reset (&t);
749 src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
750 }
751 }
752 else if ((macro_alternate || macro_mri)
3882b010 753 && (ISALPHA (in->ptr[src])
252b5132
RH
754 || in->ptr[src] == '_'
755 || in->ptr[src] == '$')
756 && (! inquote
757 || ! macro_strip_at
758 || (src > 0 && in->ptr[src - 1] == '@')))
759 {
760 if (! locals
761 || src + 5 >= in->len
762 || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
763 || ! ISWHITE (in->ptr[src + 5]))
764 {
765 sb_reset (&t);
766 src = sub_actual (src, in, &t, formal_hash,
767 (macro_strip_at && inquote) ? '@' : '\'',
768 out, 1);
769 }
770 else
771 {
772 formal_entry *f;
773
774 src = sb_skip_white (src + 5, in);
fea17916 775 while (in->ptr[src] != '\n')
252b5132
RH
776 {
777 static int loccnt;
778 char buf[20];
779 const char *err;
780
781 f = (formal_entry *) xmalloc (sizeof (formal_entry));
782 sb_new (&f->name);
783 sb_new (&f->def);
784 sb_new (&f->actual);
785 f->index = LOCAL_INDEX;
786 f->next = loclist;
787 loclist = f;
788
789 src = get_token (src, in, &f->name);
790 ++loccnt;
791 sprintf (buf, "LL%04x", loccnt);
792 sb_add_string (&f->actual, buf);
793
794 err = hash_jam (formal_hash, sb_terminate (&f->name), f);
795 if (err != NULL)
796 return err;
797
798 src = sb_skip_comma (src, in);
799 }
800 }
801 }
252b5132
RH
802 else if (in->ptr[src] == '"'
803 || (macro_mri && in->ptr[src] == '\''))
804 {
805 inquote = !inquote;
806 sb_add_char (out, in->ptr[src++]);
807 }
808 else if (in->ptr[src] == '@' && macro_strip_at)
809 {
810 ++src;
811 if (src < in->len
812 && in->ptr[src] == '@')
813 {
814 sb_add_char (out, '@');
815 ++src;
816 }
817 }
818 else if (macro_mri
819 && in->ptr[src] == '='
820 && src + 1 < in->len
821 && in->ptr[src + 1] == '=')
822 {
823 formal_entry *ptr;
824
825 sb_reset (&t);
826 src = get_token (src + 2, in, &t);
827 ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
828 if (ptr == NULL)
829 {
830 /* FIXME: We should really return a warning string here,
831 but we can't, because the == might be in the MRI
832 comment field, and, since the nature of the MRI
833 comment field depends upon the exact instruction
834 being used, we don't have enough information here to
835 figure out whether it is or not. Instead, we leave
836 the == in place, which should cause a syntax error if
837 it is not in a comment. */
838 sb_add_char (out, '=');
839 sb_add_char (out, '=');
840 sb_add_sb (out, &t);
841 }
842 else
843 {
844 if (ptr->actual.len)
845 {
846 sb_add_string (out, "-1");
847 }
848 else
849 {
850 sb_add_char (out, '0');
851 }
852 }
853 }
854 else
855 {
856 sb_add_char (out, in->ptr[src++]);
857 }
858 }
859
860 sb_kill (&t);
861
862 while (loclist != NULL)
863 {
864 formal_entry *f;
865
866 f = loclist->next;
1af6dcd2
ILT
867 /* Setting the value to NULL effectively deletes the entry. We
868 avoid calling hash_delete because it doesn't reclaim memory. */
869 hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
252b5132
RH
870 sb_kill (&loclist->name);
871 sb_kill (&loclist->def);
872 sb_kill (&loclist->actual);
873 free (loclist);
874 loclist = f;
875 }
876
877 return NULL;
878}
879
880/* Assign values to the formal parameters of a macro, and expand the
881 body. */
882
883static const char *
fea17916 884macro_expand (idx, in, m, out)
252b5132
RH
885 int idx;
886 sb *in;
887 macro_entry *m;
888 sb *out;
252b5132
RH
889{
890 sb t;
891 formal_entry *ptr;
892 formal_entry *f;
893 int is_positional = 0;
894 int is_keyword = 0;
895 int narg = 0;
896 const char *err;
897
898 sb_new (&t);
29f8404c
KH
899
900 /* Reset any old value the actuals may have. */
252b5132 901 for (f = m->formals; f; f = f->next)
29f8404c 902 sb_reset (&f->actual);
252b5132
RH
903 f = m->formals;
904 while (f != NULL && f->index < 0)
905 f = f->next;
906
907 if (macro_mri)
908 {
909 /* The macro may be called with an optional qualifier, which may
910 be referred to in the macro body as \0. */
911 if (idx < in->len && in->ptr[idx] == '.')
d1a6c242
KH
912 {
913 /* The Microtec assembler ignores this if followed by a white space.
914 (Macro invocation with empty extension) */
915 idx++;
916 if ( idx < in->len
917 && in->ptr[idx] != ' '
918 && in->ptr[idx] != '\t')
919 {
920 formal_entry *n;
921
922 n = (formal_entry *) xmalloc (sizeof (formal_entry));
923 sb_new (&n->name);
924 sb_new (&n->def);
925 sb_new (&n->actual);
926 n->index = QUAL_INDEX;
927
928 n->next = m->formals;
929 m->formals = n;
930
931 idx = get_any_string (idx, in, &n->actual, 1, 0);
932 }
933 }
934 }
252b5132 935
29f8404c 936 /* Peel off the actuals and store them away in the hash tables' actuals. */
252b5132 937 idx = sb_skip_white (idx, in);
fea17916 938 while (idx < in->len)
252b5132
RH
939 {
940 int scan;
941
29f8404c 942 /* Look and see if it's a positional or keyword arg. */
252b5132
RH
943 scan = idx;
944 while (scan < in->len
945 && !ISSEP (in->ptr[scan])
946 && !(macro_mri && in->ptr[scan] == '\'')
947 && (!macro_alternate && in->ptr[scan] != '='))
948 scan++;
949 if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
950 {
951 is_keyword = 1;
952
953 /* It's OK to go from positional to keyword. */
954
955 /* This is a keyword arg, fetch the formal name and
29f8404c 956 then the actual stuff. */
252b5132
RH
957 sb_reset (&t);
958 idx = get_token (idx, in, &t);
959 if (in->ptr[idx] != '=')
960 return _("confusion in formal parameters");
961
29f8404c 962 /* Lookup the formal in the macro's list. */
252b5132
RH
963 ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
964 if (!ptr)
965 return _("macro formal argument does not exist");
966 else
967 {
29f8404c 968 /* Insert this value into the right place. */
252b5132
RH
969 sb_reset (&ptr->actual);
970 idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
971 if (ptr->actual.len > 0)
972 ++narg;
973 }
974 }
975 else
976 {
29f8404c 977 /* This is a positional arg. */
252b5132
RH
978 is_positional = 1;
979 if (is_keyword)
980 return _("can't mix positional and keyword arguments");
981
982 if (!f)
983 {
984 formal_entry **pf;
985 int c;
986
987 if (!macro_mri)
988 return _("too many positional arguments");
989
990 f = (formal_entry *) xmalloc (sizeof (formal_entry));
991 sb_new (&f->name);
992 sb_new (&f->def);
993 sb_new (&f->actual);
994 f->next = NULL;
995
996 c = -1;
997 for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
998 if ((*pf)->index >= c)
999 c = (*pf)->index + 1;
1000 if (c == -1)
1001 c = 0;
1002 *pf = f;
1003 f->index = c;
1004 }
1005
1006 sb_reset (&f->actual);
1007 idx = get_any_string (idx, in, &f->actual, 1, 0);
1008 if (f->actual.len > 0)
1009 ++narg;
1010 do
1011 {
1012 f = f->next;
1013 }
1014 while (f != NULL && f->index < 0);
1015 }
1016
1017 if (! macro_mri)
1018 idx = sb_skip_comma (idx, in);
1019 else
1020 {
1021 if (in->ptr[idx] == ',')
1022 ++idx;
1023 if (ISWHITE (in->ptr[idx]))
1024 break;
1025 }
1026 }
1027
1028 if (macro_mri)
1029 {
1030 char buffer[20];
1031
1032 sb_reset (&t);
1033 sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
1034 ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
1035 sb_reset (&ptr->actual);
1036 sprintf (buffer, "%d", narg);
1037 sb_add_string (&ptr->actual, buffer);
1038 }
1039
fea17916 1040 err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, 1);
252b5132
RH
1041 if (err != NULL)
1042 return err;
1043
1044 /* Discard any unnamed formal arguments. */
1045 if (macro_mri)
1046 {
1047 formal_entry **pf;
1048
1049 pf = &m->formals;
1050 while (*pf != NULL)
1051 {
1052 if ((*pf)->name.len != 0)
1053 pf = &(*pf)->next;
1054 else
1055 {
1056 sb_kill (&(*pf)->name);
1057 sb_kill (&(*pf)->def);
1058 sb_kill (&(*pf)->actual);
1059 f = (*pf)->next;
1060 free (*pf);
1061 *pf = f;
1062 }
1063 }
1064 }
1065
1066 sb_kill (&t);
1067 macro_number++;
1068
1069 return NULL;
1070}
1071
1072/* Check for a macro. If one is found, put the expansion into
fea17916 1073 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
252b5132
RH
1074
1075int
fea17916 1076check_macro (line, expand, error, info)
252b5132
RH
1077 const char *line;
1078 sb *expand;
252b5132 1079 const char **error;
9f10757c 1080 macro_entry **info;
252b5132
RH
1081{
1082 const char *s;
1083 char *copy, *cs;
1084 macro_entry *macro;
1085 sb line_sb;
1086
3882b010 1087 if (! ISALPHA (*line)
252b5132
RH
1088 && *line != '_'
1089 && *line != '$'
1090 && (! macro_mri || *line != '.'))
1091 return 0;
1092
1093 s = line + 1;
3882b010 1094 while (ISALNUM (*s)
252b5132
RH
1095 || *s == '_'
1096 || *s == '$')
1097 ++s;
1098
1099 copy = (char *) alloca (s - line + 1);
1100 memcpy (copy, line, s - line);
1101 copy[s - line] = '\0';
1102 for (cs = copy; *cs != '\0'; cs++)
3882b010 1103 *cs = TOLOWER (*cs);
252b5132
RH
1104
1105 macro = (macro_entry *) hash_find (macro_hash, copy);
1106
1107 if (macro == NULL)
1108 return 0;
1109
1110 /* Wrap the line up in an sb. */
1111 sb_new (&line_sb);
1112 while (*s != '\0' && *s != '\n' && *s != '\r')
1113 sb_add_char (&line_sb, *s++);
1114
1115 sb_new (expand);
fea17916 1116 *error = macro_expand (0, &line_sb, macro, expand);
252b5132
RH
1117
1118 sb_kill (&line_sb);
1119
29f8404c 1120 /* Export the macro information if requested. */
9f10757c
TW
1121 if (info)
1122 *info = macro;
1123
252b5132
RH
1124 return 1;
1125}
1126
1127/* Delete a macro. */
1128
1129void
1130delete_macro (name)
1131 const char *name;
1132{
1133 hash_delete (macro_hash, name);
1134}
1135
1136/* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
1137 combined macro definition and execution. This returns NULL on
1138 success, or an error message otherwise. */
1139
1140const char *
fea17916 1141expand_irp (irpc, idx, in, out, get_line)
252b5132
RH
1142 int irpc;
1143 int idx;
1144 sb *in;
1145 sb *out;
1146 int (*get_line) PARAMS ((sb *));
252b5132
RH
1147{
1148 const char *mn;
1149 sb sub;
1150 formal_entry f;
1151 struct hash_control *h;
1152 const char *err;
1153
1154 if (irpc)
1155 mn = "IRPC";
1156 else
1157 mn = "IRP";
1158
1159 idx = sb_skip_white (idx, in);
1160
1161 sb_new (&sub);
1162 if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
1163 return _("unexpected end of file in irp or irpc");
29f8404c 1164
252b5132
RH
1165 sb_new (&f.name);
1166 sb_new (&f.def);
1167 sb_new (&f.actual);
1168
1169 idx = get_token (idx, in, &f.name);
1170 if (f.name.len == 0)
1171 return _("missing model parameter");
1172
1173 h = hash_new ();
1174 err = hash_jam (h, sb_terminate (&f.name), &f);
1175 if (err != NULL)
1176 return err;
1177
1178 f.index = 1;
1179 f.next = NULL;
1180
1181 sb_reset (out);
1182
1183 idx = sb_skip_comma (idx, in);
fea17916 1184 if (idx >= in->len)
252b5132
RH
1185 {
1186 /* Expand once with a null string. */
fea17916 1187 err = macro_expand_body (&sub, out, &f, h, 0);
252b5132
RH
1188 if (err != NULL)
1189 return err;
1190 }
1191 else
1192 {
1193 if (irpc && in->ptr[idx] == '"')
1194 ++idx;
fea17916 1195 while (idx < in->len)
252b5132
RH
1196 {
1197 if (!irpc)
1198 idx = get_any_string (idx, in, &f.actual, 1, 0);
1199 else
1200 {
1201 if (in->ptr[idx] == '"')
1202 {
1203 int nxt;
1204
1205 nxt = sb_skip_white (idx + 1, in);
fea17916 1206 if (nxt >= in->len)
252b5132
RH
1207 {
1208 idx = nxt;
1209 break;
1210 }
1211 }
1212 sb_reset (&f.actual);
1213 sb_add_char (&f.actual, in->ptr[idx]);
1214 ++idx;
1215 }
fea17916 1216 err = macro_expand_body (&sub, out, &f, h, 0);
252b5132
RH
1217 if (err != NULL)
1218 return err;
1219 if (!irpc)
1220 idx = sb_skip_comma (idx, in);
1221 else
1222 idx = sb_skip_white (idx, in);
1223 }
1224 }
1225
1226 hash_die (h);
1227 sb_kill (&sub);
1228
1229 return NULL;
1230}
This page took 0.30975 seconds and 4 git commands to generate.