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