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