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