1 /* macro.c -- user-defined macros for Texinfo. 2 $Id: macro.c,v 1.1.1.3 2006/07/17 16:03:47 espie Exp $ 3 4 Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software Foundation, 18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20 #include "system.h" 21 #include "cmds.h" 22 #include "files.h" 23 #include "macro.h" 24 #include "makeinfo.h" 25 #include "insertion.h" 26 27 /* If non-NULL, this is an output stream to write the full macro expansion 28 of the input text to. The result is another texinfo file, but 29 missing @include, @infoinclude, @macro, and macro invocations. Instead, 30 all of the text is placed within the file. */ 31 FILE *macro_expansion_output_stream = NULL; 32 33 /* Output file for -E. */ 34 char *macro_expansion_filename; 35 36 /* Nonzero means a macro string is in execution, as opposed to a file. */ 37 int me_executing_string = 0; 38 39 /* Nonzero means we want only to expand macros and 40 leave everything else intact. */ 41 int only_macro_expansion = 0; 42 43 static ITEXT **itext_info = NULL; 44 static int itext_size = 0; 45 46 /* Return the arglist on the current line. This can behave in two different 47 ways, depending on the variable BRACES_REQUIRED_FOR_MACRO_ARGS. */ 48 int braces_required_for_macro_args = 0; 49 50 /* Array of macros and definitions. */ 51 MACRO_DEF **macro_list = NULL; 52 53 int macro_list_len = 0; /* Number of elements. */ 54 int macro_list_size = 0; /* Number of slots in total. */ 55 56 /* Return the length of the array in ARRAY. */ 57 int 58 array_len (char **array) 59 { 60 int i = 0; 61 62 if (array) 63 for (i = 0; array[i]; i++); 64 65 return i; 66 } 67 68 void 69 free_array (char **array) 70 { 71 if (array) 72 { 73 int i; 74 for (i = 0; array[i]; i++) 75 free (array[i]); 76 77 free (array); 78 } 79 } 80 81 /* Return the macro definition of NAME or NULL if NAME is not defined. */ 82 MACRO_DEF * 83 find_macro (char *name) 84 { 85 int i; 86 MACRO_DEF *def; 87 88 def = NULL; 89 for (i = 0; macro_list && (def = macro_list[i]); i++) 90 { 91 if ((!def->inhibited) && (strcmp (def->name, name) == 0)) 92 break; 93 } 94 return def; 95 } 96 97 /* Add the macro NAME with ARGLIST and BODY to the list of defined macros. 98 SOURCE_FILE is the name of the file where this definition can be found, 99 and SOURCE_LINENO is the line number within that file. If a macro already 100 exists with NAME, then a warning is produced, and that previous 101 definition is overwritten. */ 102 static void 103 add_macro (char *name, char **arglist, char *body, char *source_file, 104 int source_lineno, int flags) 105 { 106 MACRO_DEF *def; 107 108 def = find_macro (name); 109 110 if (!def) 111 { 112 if (macro_list_len + 2 >= macro_list_size) 113 macro_list = xrealloc 114 (macro_list, ((macro_list_size += 10) * sizeof (MACRO_DEF *))); 115 116 macro_list[macro_list_len] = xmalloc (sizeof (MACRO_DEF)); 117 macro_list[macro_list_len + 1] = NULL; 118 119 def = macro_list[macro_list_len]; 120 macro_list_len += 1; 121 def->name = name; 122 } 123 else 124 { 125 char *temp_filename = input_filename; 126 int temp_line = line_number; 127 128 warning (_("macro `%s' previously defined"), name); 129 130 input_filename = def->source_file; 131 line_number = def->source_lineno; 132 warning (_("here is the previous definition of `%s'"), name); 133 134 input_filename = temp_filename; 135 line_number = temp_line; 136 137 if (def->arglist) 138 { 139 int i; 140 141 for (i = 0; def->arglist[i]; i++) 142 free (def->arglist[i]); 143 144 free (def->arglist); 145 } 146 free (def->source_file); 147 free (def->body); 148 } 149 150 def->source_file = xstrdup (source_file); 151 def->source_lineno = source_lineno; 152 def->body = body; 153 def->arglist = arglist; 154 def->inhibited = 0; 155 def->flags = flags; 156 } 157 158 159 char ** 160 get_brace_args (int quote_single) 161 { 162 char **arglist, *word; 163 int arglist_index, arglist_size; 164 int character, escape_seen, start; 165 int depth = 1; 166 167 /* There is an arglist in braces here, so gather the args inside of it. */ 168 skip_whitespace_and_newlines (); 169 input_text_offset++; 170 arglist = NULL; 171 arglist_index = arglist_size = 0; 172 173 get_arg: 174 skip_whitespace_and_newlines (); 175 start = input_text_offset; 176 escape_seen = 0; 177 178 while ((character = curchar ())) 179 { 180 if (character == '\\') 181 { 182 input_text_offset += 2; 183 escape_seen = 1; 184 } 185 else if (character == '{') 186 { 187 depth++; 188 input_text_offset++; 189 } 190 else if ((character == ',' && !quote_single) || 191 ((character == '}') && depth == 1)) 192 { 193 int len = input_text_offset - start; 194 195 if (len || (character != '}')) 196 { 197 word = xmalloc (1 + len); 198 memcpy (word, input_text + start, len); 199 word[len] = 0; 200 201 /* Clean up escaped characters. */ 202 if (escape_seen) 203 { 204 int i; 205 for (i = 0; word[i]; i++) 206 if (word[i] == '\\') 207 memmove (word + i, word + i + 1, 208 1 + strlen (word + i + 1)); 209 } 210 211 if (arglist_index + 2 >= arglist_size) 212 arglist = xrealloc 213 (arglist, (arglist_size += 10) * sizeof (char *)); 214 215 arglist[arglist_index++] = word; 216 arglist[arglist_index] = NULL; 217 } 218 219 input_text_offset++; 220 if (character == '}') 221 break; 222 else 223 goto get_arg; 224 } 225 else if (character == '}') 226 { 227 depth--; 228 input_text_offset++; 229 } 230 else 231 { 232 input_text_offset++; 233 if (character == '\n') line_number++; 234 } 235 } 236 return arglist; 237 } 238 239 static char ** 240 get_macro_args (MACRO_DEF *def) 241 { 242 int i; 243 char *word; 244 245 /* Quickly check to see if this macro has been invoked with any arguments. 246 If not, then don't skip any of the following whitespace. */ 247 for (i = input_text_offset; i < input_text_length; i++) 248 if (!cr_or_whitespace (input_text[i])) 249 break; 250 251 if (input_text[i] != '{') 252 { 253 if (braces_required_for_macro_args) 254 { 255 return NULL; 256 } 257 else 258 { 259 /* Braces are not required to fill out the macro arguments. If 260 this macro takes one argument, it is considered to be the 261 remainder of the line, sans whitespace. */ 262 if (def->arglist && def->arglist[0] && !def->arglist[1]) 263 { 264 char **arglist; 265 266 get_rest_of_line (0, &word); 267 if (input_text[input_text_offset - 1] == '\n') 268 { 269 input_text_offset--; 270 line_number--; 271 } 272 /* canon_white (word); */ 273 arglist = xmalloc (2 * sizeof (char *)); 274 arglist[0] = word; 275 arglist[1] = NULL; 276 return arglist; 277 } 278 else 279 { 280 /* The macro either took no arguments, or took more than 281 one argument. In that case, it must be invoked with 282 arguments surrounded by braces. */ 283 return NULL; 284 } 285 } 286 } 287 return get_brace_args (def->flags & ME_QUOTE_ARG); 288 } 289 290 /* Substitute actual parameters for named parameters in body. 291 The named parameters which appear in BODY must by surrounded 292 reverse slashes, as in \foo\. */ 293 static char * 294 apply (char **named, char **actuals, char *body) 295 { 296 int i; 297 int new_body_index, new_body_size; 298 char *new_body, *text; 299 int length_of_actuals; 300 301 length_of_actuals = array_len (actuals); 302 new_body_size = strlen (body); 303 new_body = xmalloc (1 + new_body_size); 304 305 /* Copy chars from BODY into NEW_BODY. */ 306 i = 0; 307 new_body_index = 0; 308 309 while (body[i]) 310 { /* Anything but a \ is easy. */ 311 if (body[i] != '\\') 312 new_body[new_body_index++] = body[i++]; 313 else 314 { /* Snarf parameter name, check against named parameters. */ 315 char *param; 316 int param_start, len; 317 318 param_start = ++i; 319 while (body[i] && body[i] != '\\') 320 i++; 321 322 len = i - param_start; 323 param = xmalloc (1 + len); 324 memcpy (param, body + param_start, len); 325 param[len] = 0; 326 327 if (body[i]) /* move past \ */ 328 i++; 329 330 if (len == 0) 331 { /* \\ always means \, even if macro has no args. */ 332 len++; 333 text = xmalloc (1 + len); 334 sprintf (text, "\\%s", param); 335 } 336 else 337 { 338 int which; 339 340 /* Check against named parameters. */ 341 for (which = 0; named && named[which]; which++) 342 if (STREQ (named[which], param)) 343 break; 344 345 if (named && named[which]) 346 { 347 text = which < length_of_actuals ? actuals[which] : NULL; 348 if (!text) 349 text = ""; 350 len = strlen (text); 351 text = xstrdup (text); /* so we can free it */ 352 } 353 else 354 { /* not a parameter, so it's an error. */ 355 warning (_("\\ in macro expansion followed by `%s' instead of parameter name"), 356 param); 357 len++; 358 text = xmalloc (1 + len); 359 sprintf (text, "\\%s", param); 360 } 361 } 362 363 if (strlen (param) + 2 < len) 364 { 365 new_body_size += len + 1; 366 new_body = xrealloc (new_body, new_body_size); 367 } 368 369 free (param); 370 371 strcpy (new_body + new_body_index, text); 372 new_body_index += len; 373 374 free (text); 375 } 376 } 377 378 new_body[new_body_index] = 0; 379 return new_body; 380 } 381 382 /* Expand macro passed in DEF, a pointer to a MACRO_DEF, and 383 return its expansion as a string. */ 384 char * 385 expand_macro (MACRO_DEF *def) 386 { 387 char **arglist; 388 int num_args; 389 char *execution_string = NULL; 390 int start_line = line_number; 391 392 /* Find out how many arguments this macro definition takes. */ 393 num_args = array_len (def->arglist); 394 395 /* Gather the arguments present on the line if there are any. */ 396 arglist = get_macro_args (def); 397 398 if (num_args < array_len (arglist)) 399 { 400 free_array (arglist); 401 line_error (_("Macro `%s' called on line %d with too many args"), 402 def->name, start_line); 403 return execution_string; 404 } 405 406 if (def->body) 407 execution_string = apply (def->arglist, arglist, def->body); 408 409 free_array (arglist); 410 return execution_string; 411 } 412 413 /* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */ 414 void 415 execute_macro (MACRO_DEF *def) 416 { 417 char *execution_string; 418 int start_line = line_number, end_line; 419 420 if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion) 421 me_append_before_this_command (); 422 423 execution_string = expand_macro (def); 424 if (!execution_string) 425 return; 426 427 if (def->body) 428 { 429 /* Reset the line number to where the macro arguments began. 430 This makes line numbers reported in error messages correct in 431 case the macro arguments span several lines and the expanded 432 arguments invoke other commands. */ 433 end_line = line_number; 434 line_number = start_line; 435 436 if (macro_expansion_output_stream 437 && !executing_string && !me_inhibit_expansion) 438 { 439 remember_itext (input_text, input_text_offset); 440 me_execute_string (execution_string); 441 } 442 else 443 execute_string ("%s", execution_string); 444 445 free (execution_string); 446 line_number = end_line; 447 } 448 } 449 450 451 /* Read and remember the definition of a macro. If RECURSIVE is set, 452 set the ME_RECURSE flag. MACTYPE is either "macro" or "rmacro", and 453 tells us what the matching @end should be. */ 454 static void 455 define_macro (char *mactype, int recursive) 456 { 457 int i, start; 458 char *name, *line; 459 char *last_end = NULL; 460 char *body = NULL; 461 char **arglist = NULL; 462 int body_size = 0, body_index = 0; 463 int depth = 1; 464 int flags = 0; 465 int defining_line = line_number; 466 467 if (macro_expansion_output_stream && !executing_string) 468 me_append_before_this_command (); 469 470 skip_whitespace (); 471 472 /* Get the name of the macro. This is the set of characters which are 473 not whitespace and are not `{' immediately following the @macro. */ 474 start = input_text_offset; 475 { 476 int len; 477 478 for (i = start; i < input_text_length && input_text[i] != '{' 479 && !cr_or_whitespace (input_text[i]); 480 i++) ; 481 482 len = i - start; 483 name = xmalloc (1 + len); 484 memcpy (name, input_text + start, len); 485 name[len] = 0; 486 input_text_offset = i; 487 } 488 489 skip_whitespace (); 490 491 /* It is not required that the definition of a macro includes an arglist. 492 If not, don't try to get the named parameters, just use a null list. */ 493 if (curchar () == '{') 494 { 495 int character; 496 int arglist_index = 0, arglist_size = 0; 497 int gathering_words = 1; 498 char *word = NULL; 499 500 /* Read the words inside of the braces which determine the arglist. 501 These words will be replaced within the body of the macro at 502 execution time. */ 503 504 input_text_offset++; 505 skip_whitespace_and_newlines (); 506 507 while (gathering_words) 508 { 509 int len; 510 511 for (i = input_text_offset; 512 (character = input_text[i]); 513 i++) 514 { 515 switch (character) 516 { 517 case '\n': 518 line_number++; 519 case ' ': 520 case '\t': 521 case ',': 522 case '}': 523 /* Found the end of the current arglist word. Save it. */ 524 len = i - input_text_offset; 525 word = xmalloc (1 + len); 526 memcpy (word, input_text + input_text_offset, len); 527 word[len] = 0; 528 input_text_offset = i; 529 530 /* Advance to the comma or close-brace that signified 531 the end of the argument. */ 532 while ((character = curchar ()) 533 && character != ',' 534 && character != '}') 535 { 536 input_text_offset++; 537 if (character == '\n') 538 line_number++; 539 } 540 541 /* Add the word to our list of words. */ 542 if (arglist_index + 2 >= arglist_size) 543 { 544 arglist_size += 10; 545 arglist = xrealloc (arglist, 546 arglist_size * sizeof (char *)); 547 } 548 549 arglist[arglist_index++] = word; 550 arglist[arglist_index] = NULL; 551 break; 552 } 553 554 if (character == '}') 555 { 556 input_text_offset++; 557 gathering_words = 0; 558 break; 559 } 560 561 if (character == ',') 562 { 563 input_text_offset++; 564 skip_whitespace_and_newlines (); 565 i = input_text_offset - 1; 566 } 567 } 568 } 569 570 /* If we have exactly one argument, do @quote-arg implicitly. Not 571 only does this match TeX's behavior (which can't feasibly be 572 changed), but it's a good idea. */ 573 if (arglist_index == 1) 574 flags |= ME_QUOTE_ARG; 575 } 576 577 /* Read the text carefully until we find an "@end macro" which 578 matches this one. The text in between is the body of the macro. */ 579 skip_whitespace_and_newlines (); 580 581 while (depth) 582 { 583 if ((input_text_offset + 9) > input_text_length) 584 { 585 file_line_error (input_filename, defining_line, 586 _("%cend macro not found"), COMMAND_PREFIX); 587 return; 588 } 589 590 get_rest_of_line (0, &line); 591 592 /* Handle commands only meaningful within a macro. */ 593 if ((*line == COMMAND_PREFIX) && (depth == 1) && 594 (strncmp (line + 1, "allow-recursion", 15) == 0) && 595 (line[16] == 0 || whitespace (line[16]))) 596 { 597 for (i = 16; whitespace (line[i]); i++); 598 strcpy (line, line + i); 599 flags |= ME_RECURSE; 600 if (!*line) 601 { 602 free (line); 603 continue; 604 } 605 } 606 607 if ((*line == COMMAND_PREFIX) && (depth == 1) && 608 (strncmp (line + 1, "quote-arg", 9) == 0) && 609 (line[10] == 0 || whitespace (line[10]))) 610 { 611 for (i = 10; whitespace (line[i]); i++); 612 strcpy (line, line + i); 613 614 if (arglist && arglist[0] && !arglist[1]) 615 { 616 flags |= ME_QUOTE_ARG; 617 if (!*line) 618 { 619 free (line); 620 continue; 621 } 622 } 623 else 624 line_error (_("@quote-arg only useful for single-argument macros")); 625 } 626 627 if (*line == COMMAND_PREFIX 628 && (strncmp (line + 1, "macro ", 6) == 0 629 || strncmp (line + 1, "rmacro ", 7) == 0)) 630 depth++; 631 632 /* Incorrect implementation of nesting -- just check that the last 633 @end matches what we started with. Since nested macros don't 634 work in TeX anyway, this isn't worth the trouble to get right. */ 635 if (*line == COMMAND_PREFIX && strncmp (line + 1, "end macro", 9) == 0) 636 { 637 depth--; 638 last_end = "macro"; 639 } 640 if (*line == COMMAND_PREFIX && strncmp (line + 1, "end rmacro", 10) == 0) 641 { 642 depth--; 643 last_end = "rmacro"; 644 } 645 646 if (depth) 647 { 648 if ((body_index + strlen (line) + 3) >= body_size) 649 body = xrealloc (body, body_size += 3 + strlen (line)); 650 strcpy (body + body_index, line); 651 body_index += strlen (line); 652 body[body_index++] = '\n'; 653 body[body_index] = 0; 654 } 655 free (line); 656 } 657 658 /* Check that @end matched the macro command. */ 659 if (!STREQ (last_end, mactype)) 660 warning (_("mismatched @end %s with @%s"), last_end, mactype); 661 662 /* If it was an empty macro like 663 @macro foo 664 @end macro 665 create an empty body. (Otherwise, the macro is not expanded.) */ 666 if (!body) 667 { 668 body = (char *)malloc(1); 669 *body = 0; 670 } 671 672 /* We now have the name, the arglist, and the body. However, BODY 673 includes the final newline which preceded the `@end macro' text. 674 Delete it. */ 675 if (body && strlen (body)) 676 body[strlen (body) - 1] = 0; 677 678 if (recursive) 679 flags |= ME_RECURSE; 680 681 add_macro (name, arglist, body, input_filename, defining_line, flags); 682 683 if (macro_expansion_output_stream && !executing_string) 684 { 685 /* Remember text for future expansions. */ 686 remember_itext (input_text, input_text_offset); 687 688 /* Bizarrely, output the @macro itself. This is so texinfo.tex 689 will have a chance to read it when texi2dvi calls makeinfo -E. 690 The problem is that we don't really expand macros in all 691 contexts; a @table's @item is one. And a fix is not obvious to 692 me, since it appears virtually identical to any other internal 693 expansion. Just setting a variable in cm_item caused other 694 strange expansion problems. */ 695 write_region_to_macro_output ("@", 0, 1); 696 write_region_to_macro_output (mactype, 0, strlen (mactype)); 697 write_region_to_macro_output (" ", 0, 1); 698 write_region_to_macro_output (input_text, start, input_text_offset); 699 } 700 } 701 702 void 703 cm_macro (void) 704 { 705 define_macro ("macro", 0); 706 } 707 708 void 709 cm_rmacro (void) 710 { 711 define_macro ("rmacro", 1); 712 } 713 714 /* Delete the macro with name NAME. The macro is deleted from the list, 715 but it is also returned. If there was no macro defined, NULL is 716 returned. */ 717 718 static MACRO_DEF * 719 delete_macro (char *name) 720 { 721 int i; 722 MACRO_DEF *def; 723 724 def = NULL; 725 726 for (i = 0; macro_list && (def = macro_list[i]); i++) 727 if (strcmp (def->name, name) == 0) 728 { 729 memmove (macro_list + i, macro_list + i + 1, 730 ((macro_list_len + 1) - i) * sizeof (MACRO_DEF *)); 731 macro_list_len--; 732 break; 733 } 734 return def; 735 } 736 737 void 738 cm_unmacro (void) 739 { 740 int i; 741 char *line, *name; 742 MACRO_DEF *def; 743 744 if (macro_expansion_output_stream && !executing_string) 745 me_append_before_this_command (); 746 747 get_rest_of_line (0, &line); 748 749 for (i = 0; line[i] && !whitespace (line[i]); i++); 750 name = xmalloc (i + 1); 751 memcpy (name, line, i); 752 name[i] = 0; 753 754 def = delete_macro (name); 755 756 if (def) 757 { 758 free (def->source_file); 759 free (def->name); 760 free (def->body); 761 762 if (def->arglist) 763 { 764 int i; 765 766 for (i = 0; def->arglist[i]; i++) 767 free (def->arglist[i]); 768 769 free (def->arglist); 770 } 771 772 free (def); 773 } 774 775 free (line); 776 free (name); 777 778 if (macro_expansion_output_stream && !executing_string) 779 remember_itext (input_text, input_text_offset); 780 } 781 782 /* How to output sections of the input file verbatim. */ 783 784 /* Set the value of POINTER's offset to OFFSET. */ 785 ITEXT * 786 remember_itext (char *pointer, int offset) 787 { 788 int i; 789 ITEXT *itext = NULL; 790 791 /* If we have no info, initialize a blank list. */ 792 if (!itext_info) 793 { 794 itext_info = xmalloc ((itext_size = 10) * sizeof (ITEXT *)); 795 for (i = 0; i < itext_size; i++) 796 itext_info[i] = NULL; 797 } 798 799 /* If the pointer is already present in the list, then set the offset. */ 800 for (i = 0; i < itext_size; i++) 801 if ((itext_info[i]) && 802 (itext_info[i]->pointer == pointer)) 803 { 804 itext = itext_info[i]; 805 itext_info[i]->offset = offset; 806 break; 807 } 808 809 if (i == itext_size) 810 { 811 /* Find a blank slot (or create a new one), and remember the 812 pointer and offset. */ 813 for (i = 0; i < itext_size; i++) 814 if (itext_info[i] == NULL) 815 break; 816 817 /* If not found, then add some slots. */ 818 if (i == itext_size) 819 { 820 int j; 821 822 itext_info = xrealloc 823 (itext_info, (itext_size += 10) * sizeof (ITEXT *)); 824 825 for (j = i; j < itext_size; j++) 826 itext_info[j] = NULL; 827 } 828 829 /* Now add the pointer and the offset. */ 830 itext_info[i] = xmalloc (sizeof (ITEXT)); 831 itext_info[i]->pointer = pointer; 832 itext_info[i]->offset = offset; 833 itext = itext_info[i]; 834 } 835 return itext; 836 } 837 838 /* Forget the input text associated with POINTER. */ 839 void 840 forget_itext (char *pointer) 841 { 842 int i; 843 844 for (i = 0; i < itext_size; i++) 845 if (itext_info[i] && (itext_info[i]->pointer == pointer)) 846 { 847 free (itext_info[i]); 848 itext_info[i] = NULL; 849 break; 850 } 851 } 852 853 /* Append the text which appeared in input_text from the last offset to 854 the character just before the command that we are currently executing. */ 855 void 856 me_append_before_this_command (void) 857 { 858 int i; 859 860 for (i = input_text_offset; i && (input_text[i] != COMMAND_PREFIX); i--) 861 ; 862 maybe_write_itext (input_text, i); 863 } 864 865 /* Similar to execute_string, but only takes a single string argument, 866 and remembers the input text location, etc. */ 867 void 868 me_execute_string (char *execution_string) 869 { 870 int saved_escape_html = escape_html; 871 int saved_in_paragraph = in_paragraph; 872 escape_html = me_executing_string == 0; 873 in_paragraph = 0; 874 875 pushfile (); 876 input_text_offset = 0; 877 /* The following xstrdup is so we can relocate input_text at will. */ 878 input_text = xstrdup (execution_string); 879 input_filename = xstrdup (input_filename); 880 input_text_length = strlen (execution_string); 881 882 remember_itext (input_text, 0); 883 884 me_executing_string++; 885 reader_loop (); 886 free (input_text); 887 free (input_filename); 888 popfile (); 889 me_executing_string--; 890 891 in_paragraph = saved_in_paragraph; 892 escape_html = saved_escape_html; 893 } 894 895 /* A wrapper around me_execute_string which saves and restores 896 variables important for output generation. This is called 897 when we need to produce macro-expanded output for input which 898 leaves no traces in the Info output. */ 899 void 900 me_execute_string_keep_state (char *execution_string, char *append_string) 901 { 902 int op_orig, opcol_orig, popen_orig; 903 int fill_orig, newline_orig, indent_orig, meta_pos_orig; 904 905 remember_itext (input_text, input_text_offset); 906 op_orig = output_paragraph_offset; 907 meta_pos_orig = meta_char_pos; 908 opcol_orig = output_column; 909 popen_orig = paragraph_is_open; 910 fill_orig = filling_enabled; 911 newline_orig = last_char_was_newline; 912 filling_enabled = 0; 913 indent_orig = no_indent; 914 no_indent = 1; 915 me_execute_string (execution_string); 916 if (append_string) 917 write_region_to_macro_output (append_string, 0, strlen (append_string)); 918 output_paragraph_offset = op_orig; 919 meta_char_pos = meta_pos_orig; 920 output_column = opcol_orig; 921 paragraph_is_open = popen_orig; 922 filling_enabled = fill_orig; 923 last_char_was_newline = newline_orig; 924 no_indent = indent_orig; 925 } 926 927 /* Append the text which appears in input_text from the last offset to 928 the current OFFSET. */ 929 void 930 append_to_expansion_output (int offset) 931 { 932 int i; 933 ITEXT *itext = NULL; 934 935 for (i = 0; i < itext_size; i++) 936 if (itext_info[i] && itext_info[i]->pointer == input_text) 937 { 938 itext = itext_info[i]; 939 break; 940 } 941 942 if (!itext) 943 return; 944 945 if (offset > itext->offset) 946 { 947 write_region_to_macro_output (input_text, itext->offset, offset); 948 remember_itext (input_text, offset); 949 } 950 } 951 952 /* Only write this input text iff it appears in our itext list. */ 953 void 954 maybe_write_itext (char *pointer, int offset) 955 { 956 int i; 957 ITEXT *itext = NULL; 958 959 for (i = 0; i < itext_size; i++) 960 if (itext_info[i] && (itext_info[i]->pointer == pointer)) 961 { 962 itext = itext_info[i]; 963 break; 964 } 965 966 if (itext && (itext->offset < offset)) 967 { 968 write_region_to_macro_output (itext->pointer, itext->offset, offset); 969 remember_itext (pointer, offset); 970 } 971 } 972 973 void 974 write_region_to_macro_output (char *string, int start, int end) 975 { 976 if (macro_expansion_output_stream) 977 fwrite (string + start, 1, end - start, macro_expansion_output_stream); 978 } 979 980 /* Aliases. */ 981 982 typedef struct alias_struct 983 { 984 char *alias; 985 char *mapto; 986 struct alias_struct *next; 987 } alias_type; 988 989 static alias_type *aliases; 990 991 /* @alias aname = cmdname */ 992 993 void 994 cm_alias (void) 995 { 996 alias_type *a = xmalloc (sizeof (alias_type)); 997 998 skip_whitespace (); 999 get_until_in_line (0, "=", &(a->alias)); 1000 canon_white (a->alias); 1001 1002 discard_until ("="); 1003 skip_whitespace (); 1004 get_until_in_line (0, " ", &(a->mapto)); 1005 1006 a->next = aliases; 1007 aliases = a; 1008 } 1009 1010 /* Perform an alias expansion. Called from read_command. */ 1011 char * 1012 alias_expand (char *tok) 1013 { 1014 alias_type *findit = aliases; 1015 1016 while (findit) 1017 if (strcmp (findit->alias, tok) == 0) 1018 { 1019 free (tok); 1020 return alias_expand (xstrdup (findit->mapto)); 1021 } 1022 else 1023 findit = findit->next; 1024 1025 return tok; 1026 } 1027 1028 /* definfoenclose implementation. */ 1029 1030 /* This structure is used to track enclosure macros. When an enclosure 1031 macro is recognized, a pointer to the enclosure block corresponding 1032 to its name is saved in the brace element for its argument. */ 1033 typedef struct enclose_struct 1034 { 1035 char *enclose; 1036 char *before; 1037 char *after; 1038 struct enclose_struct *next; 1039 } enclosure_type; 1040 1041 static enclosure_type *enclosures; 1042 1043 typedef struct enclosure_stack_struct 1044 { 1045 enclosure_type *current; 1046 struct enclosure_stack_struct *next; 1047 } enclosure_stack_type; 1048 1049 static enclosure_stack_type *enclosure_stack; 1050 1051 /* @definfoenclose */ 1052 void 1053 cm_definfoenclose (void) 1054 { 1055 enclosure_type *e = xmalloc (sizeof (enclosure_type)); 1056 1057 skip_whitespace (); 1058 get_until_in_line (1, ",", &(e->enclose)); 1059 discard_until (","); 1060 get_until_in_line (0, ",", &(e->before)); 1061 discard_until (","); 1062 get_until_in_line (0, "\n", &(e->after)); 1063 1064 e->next = enclosures; 1065 enclosures = e; 1066 } 1067 1068 /* If TOK is an enclosure command, push it on the enclosure stack and 1069 return 1. Else return 0. */ 1070 1071 int 1072 enclosure_command (char *tok) 1073 { 1074 enclosure_type *findit = enclosures; 1075 1076 while (findit) 1077 if (strcmp (findit->enclose, tok) == 0) 1078 { 1079 enclosure_stack_type *new = xmalloc (sizeof (enclosure_stack_type)); 1080 new->current = findit; 1081 new->next = enclosure_stack; 1082 enclosure_stack = new; 1083 1084 return 1; 1085 } 1086 else 1087 findit = findit->next; 1088 1089 return 0; 1090 } 1091 1092 /* actually perform the enclosure expansion */ 1093 void 1094 enclosure_expand (int arg, int start, int end) 1095 { 1096 if (arg == START) 1097 add_word (enclosure_stack->current->before); 1098 else 1099 { 1100 enclosure_stack_type *temp; 1101 1102 add_word (enclosure_stack->current->after); 1103 1104 temp = enclosure_stack; 1105 enclosure_stack = enclosure_stack->next; 1106 free (temp); 1107 } 1108 } 1109