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