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