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