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