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