1178481Sjb/* macro.c -- user-defined macros for Texinfo. 2178481Sjb $Id: macro.c,v 1.6 2004/04/11 17:56:47 karl Exp $ 3178481Sjb 4178481Sjb Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc. 5178481Sjb 6178481Sjb This program is free software; you can redistribute it and/or modify 7178481Sjb it under the terms of the GNU General Public License as published by 8178481Sjb the Free Software Foundation; either version 2, or (at your option) 9178481Sjb any later version. 10178481Sjb 11178481Sjb This program is distributed in the hope that it will be useful, 12178481Sjb but WITHOUT ANY WARRANTY; without even the implied warranty of 13178481Sjb MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14178481Sjb GNU General Public License for more details. 15178481Sjb 16178481Sjb You should have received a copy of the GNU General Public License 17178481Sjb along with this program; if not, write to the Free Software Foundation, 18178481Sjb Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19178481Sjb 20178481Sjb#include "system.h" 21178481Sjb#include "cmds.h" 22210767Srpaulo#include "files.h" 23178481Sjb#include "macro.h" 24178481Sjb#include "makeinfo.h" 25178481Sjb#include "insertion.h" 26178481Sjb 27178481Sjb/* If non-NULL, this is an output stream to write the full macro expansion 28178481Sjb of the input text to. The result is another texinfo file, but 29178481Sjb missing @include, @infoinclude, @macro, and macro invocations. Instead, 30178481Sjb all of the text is placed within the file. */ 31178481SjbFILE *macro_expansion_output_stream = NULL; 32178481Sjb 33178481Sjb/* Output file for -E. */ 34178481Sjbchar *macro_expansion_filename; 35178481Sjb 36178481Sjb/* Nonzero means a macro string is in execution, as opposed to a file. */ 37178481Sjbint me_executing_string = 0; 38178481Sjb 39178481Sjb/* Nonzero means we want only to expand macros and 40178481Sjb leave everything else intact. */ 41178481Sjbint only_macro_expansion = 0; 42178481Sjb 43178481Sjbstatic ITEXT **itext_info = NULL; 44178481Sjbstatic int itext_size = 0; 45178481Sjb 46178481Sjb/* Return the arglist on the current line. This can behave in two different 47178481Sjb ways, depending on the variable BRACES_REQUIRED_FOR_MACRO_ARGS. */ 48178481Sjbint braces_required_for_macro_args = 0; 49178481Sjb 50178481Sjb/* Array of macros and definitions. */ 51178481SjbMACRO_DEF **macro_list = NULL; 52178481Sjb 53178481Sjbint macro_list_len = 0; /* Number of elements. */ 54178481Sjbint macro_list_size = 0; /* Number of slots in total. */ 55178481Sjb 56178481Sjb/* Return the length of the array in ARRAY. */ 57178481Sjbint 58178481Sjbarray_len (char **array) 59178481Sjb{ 60178481Sjb int i = 0; 61178481Sjb 62178481Sjb if (array) 63178481Sjb for (i = 0; array[i]; i++); 64178481Sjb 65178481Sjb return i; 66178481Sjb} 67178481Sjb 68178481Sjbvoid 69178481Sjbfree_array (char **array) 70178481Sjb{ 71178481Sjb if (array) 72178481Sjb { 73178481Sjb int i; 74178481Sjb for (i = 0; array[i]; i++) 75178481Sjb free (array[i]); 76178481Sjb 77178481Sjb free (array); 78178481Sjb } 79178481Sjb} 80178481Sjb 81178481Sjb/* Return the macro definition of NAME or NULL if NAME is not defined. */ 82178481SjbMACRO_DEF * 83178481Sjbfind_macro (char *name) 84178481Sjb{ 85178481Sjb int i; 86178481Sjb MACRO_DEF *def; 87210767Srpaulo 88178481Sjb def = NULL; 89210767Srpaulo for (i = 0; macro_list && (def = macro_list[i]); i++) 90210767Srpaulo { 91178481Sjb if ((!def->inhibited) && (strcmp (def->name, name) == 0)) 92178481Sjb break; 93178481Sjb } 94178481Sjb return def; 95178481Sjb} 96178481Sjb 97178481Sjb/* Add the macro NAME with ARGLIST and BODY to the list of defined macros. 98178481Sjb SOURCE_FILE is the name of the file where this definition can be found, 99178481Sjb and SOURCE_LINENO is the line number within that file. If a macro already 100178481Sjb exists with NAME, then a warning is produced, and that previous 101178481Sjb definition is overwritten. */ 102178481Sjbstatic void 103178481Sjbadd_macro (char *name, char **arglist, char *body, char *source_file, 104178481Sjb int source_lineno, int flags) 105178481Sjb{ 106178481Sjb MACRO_DEF *def; 107178481Sjb 108178481Sjb def = find_macro (name); 109178481Sjb 110178481Sjb if (!def) 111178481Sjb { 112178481Sjb if (macro_list_len + 2 >= macro_list_size) 113178481Sjb macro_list = xrealloc 114178481Sjb (macro_list, ((macro_list_size += 10) * sizeof (MACRO_DEF *))); 115178481Sjb 116178481Sjb macro_list[macro_list_len] = xmalloc (sizeof (MACRO_DEF)); 117178481Sjb macro_list[macro_list_len + 1] = NULL; 118178481Sjb 119178481Sjb def = macro_list[macro_list_len]; 120178481Sjb macro_list_len += 1; 121178481Sjb def->name = name; 122178481Sjb } 123178481Sjb else 124178481Sjb { 125178481Sjb char *temp_filename = input_filename; 126178481Sjb int temp_line = line_number; 127178481Sjb 128178481Sjb warning (_("macro `%s' previously defined"), name); 129178481Sjb 130178481Sjb input_filename = def->source_file; 131178481Sjb line_number = def->source_lineno; 132178481Sjb warning (_("here is the previous definition of `%s'"), name); 133178481Sjb 134178481Sjb input_filename = temp_filename; 135178481Sjb line_number = temp_line; 136178481Sjb 137178481Sjb if (def->arglist) 138178481Sjb { 139178481Sjb int i; 140178481Sjb 141178481Sjb for (i = 0; def->arglist[i]; i++) 142178481Sjb free (def->arglist[i]); 143178481Sjb 144178481Sjb free (def->arglist); 145178481Sjb } 146178481Sjb free (def->source_file); 147178481Sjb free (def->body); 148178481Sjb } 149178481Sjb 150178481Sjb def->source_file = xstrdup (source_file); 151178481Sjb def->source_lineno = source_lineno; 152178481Sjb def->body = body; 153178481Sjb def->arglist = arglist; 154178481Sjb def->inhibited = 0; 155178481Sjb def->flags = flags; 156178481Sjb} 157178481Sjb 158178481Sjb 159178481Sjbchar ** 160178481Sjbget_brace_args (int quote_single) 161178481Sjb{ 162178481Sjb char **arglist, *word; 163178481Sjb int arglist_index, arglist_size; 164178481Sjb int character, escape_seen, start; 165178481Sjb int depth = 1; 166178481Sjb 167178481Sjb /* There is an arglist in braces here, so gather the args inside of it. */ 168178481Sjb skip_whitespace_and_newlines (); 169178481Sjb input_text_offset++; 170178481Sjb arglist = NULL; 171178481Sjb arglist_index = arglist_size = 0; 172178481Sjb 173178481Sjb get_arg: 174178481Sjb skip_whitespace_and_newlines (); 175178481Sjb start = input_text_offset; 176178546Sjb escape_seen = 0; 177178481Sjb 178178546Sjb while ((character = curchar ())) 179178546Sjb { 180178481Sjb if (character == '\\') 181178481Sjb { 182178481Sjb input_text_offset += 2; 183178481Sjb escape_seen = 1; 184178481Sjb } 185178481Sjb else if (character == '{') 186178481Sjb { 187178546Sjb depth++; 188178481Sjb input_text_offset++; 189178481Sjb } 190178481Sjb else if ((character == ',' && !quote_single) || 191178481Sjb ((character == '}') && depth == 1)) 192178481Sjb { 193178481Sjb int len = input_text_offset - start; 194178481Sjb 195178481Sjb if (len || (character != '}')) 196178481Sjb { 197178481Sjb word = xmalloc (1 + len); 198178481Sjb memcpy (word, input_text + start, len); 199178481Sjb word[len] = 0; 200178481Sjb 201178481Sjb /* Clean up escaped characters. */ 202178481Sjb if (escape_seen) 203178481Sjb { 204178481Sjb int i; 205178481Sjb for (i = 0; word[i]; i++) 206178481Sjb if (word[i] == '\\') 207178481Sjb memmove (word + i, word + i + 1, 208178481Sjb 1 + strlen (word + i + 1)); 209178481Sjb } 210178481Sjb 211178481Sjb if (arglist_index + 2 >= arglist_size) 212178481Sjb arglist = xrealloc 213178481Sjb (arglist, (arglist_size += 10) * sizeof (char *)); 214178481Sjb 215178481Sjb arglist[arglist_index++] = word; 216178481Sjb arglist[arglist_index] = NULL; 217178481Sjb } 218178481Sjb 219178481Sjb input_text_offset++; 220178481Sjb if (character == '}') 221178481Sjb break; 222178481Sjb else 223178481Sjb goto get_arg; 224178481Sjb } 225178481Sjb else if (character == '}') 226178481Sjb { 227178481Sjb depth--; 228178481Sjb input_text_offset++; 229178481Sjb } 230178481Sjb else 231178481Sjb { 232178481Sjb input_text_offset++; 233178481Sjb if (character == '\n') line_number++; 234178481Sjb } 235178481Sjb } 236178481Sjb return arglist; 237178481Sjb} 238178481Sjb 239178481Sjbstatic char ** 240178481Sjbget_macro_args (MACRO_DEF *def) 241178481Sjb{ 242178481Sjb int i; 243178481Sjb char *word; 244178481Sjb 245178481Sjb /* Quickly check to see if this macro has been invoked with any arguments. 246178481Sjb If not, then don't skip any of the following whitespace. */ 247178481Sjb for (i = input_text_offset; i < input_text_length; i++) 248178481Sjb if (!cr_or_whitespace (input_text[i])) 249178481Sjb break; 250178481Sjb 251178546Sjb if (input_text[i] != '{') 252178546Sjb { 253178481Sjb if (braces_required_for_macro_args) 254178546Sjb { 255178481Sjb return NULL; 256178481Sjb } 257178481Sjb else 258178481Sjb { 259178481Sjb /* Braces are not required to fill out the macro arguments. If 260178481Sjb this macro takes one argument, it is considered to be the 261178546Sjb remainder of the line, sans whitespace. */ 262178481Sjb if (def->arglist && def->arglist[0] && !def->arglist[1]) 263178481Sjb { 264178481Sjb char **arglist; 265178481Sjb 266178481Sjb get_rest_of_line (0, &word); 267178546Sjb if (input_text[input_text_offset - 1] == '\n') 268178481Sjb { 269178481Sjb input_text_offset--; 270178481Sjb line_number--; 271178546Sjb } 272178481Sjb /* canon_white (word); */ 273178546Sjb arglist = xmalloc (2 * sizeof (char *)); 274178546Sjb arglist[0] = word; 275178481Sjb arglist[1] = NULL; 276178481Sjb return arglist; 277178481Sjb } 278178481Sjb else 279178546Sjb { 280178481Sjb /* The macro either took no arguments, or took more than 281178481Sjb one argument. In that case, it must be invoked with 282178481Sjb arguments surrounded by braces. */ 283178481Sjb return NULL; 284178481Sjb } 285178481Sjb } 286178546Sjb } 287178481Sjb return get_brace_args (def->flags & ME_QUOTE_ARG); 288178481Sjb} 289178481Sjb 290178481Sjb/* Substitute actual parameters for named parameters in body. 291178481Sjb The named parameters which appear in BODY must by surrounded 292178481Sjb reverse slashes, as in \foo\. */ 293178481Sjbstatic char * 294178481Sjbapply (char **named, char **actuals, char *body) 295178481Sjb{ 296178481Sjb int i; 297178481Sjb int new_body_index, new_body_size; 298178481Sjb char *new_body, *text; 299178481Sjb int length_of_actuals; 300178481Sjb 301178481Sjb length_of_actuals = array_len (actuals); 302178481Sjb new_body_size = strlen (body); 303178481Sjb new_body = xmalloc (1 + new_body_size); 304178481Sjb 305178481Sjb /* Copy chars from BODY into NEW_BODY. */ 306178481Sjb i = 0; 307178481Sjb new_body_index = 0; 308178481Sjb 309178481Sjb while (body[i]) 310178481Sjb { /* Anything but a \ is easy. */ 311178546Sjb if (body[i] != '\\') 312178481Sjb new_body[new_body_index++] = body[i++]; 313178546Sjb else 314178546Sjb { /* Snarf parameter name, check against named parameters. */ 315178481Sjb char *param; 316178481Sjb int param_start, len; 317178481Sjb 318178481Sjb param_start = ++i; 319178481Sjb while (body[i] && body[i] != '\\') 320178481Sjb i++; 321178481Sjb 322178481Sjb len = i - param_start; 323178481Sjb param = xmalloc (1 + len); 324178481Sjb memcpy (param, body + param_start, len); 325178481Sjb param[len] = 0; 326178481Sjb 327178481Sjb if (body[i]) /* move past \ */ 328178481Sjb i++; 329178481Sjb 330178481Sjb if (len == 0) 331178481Sjb { /* \\ always means \, even if macro has no args. */ 332178546Sjb len++; 333178481Sjb text = xmalloc (1 + len); 334178481Sjb sprintf (text, "\\%s", param); 335178481Sjb } 336178481Sjb else 337178481Sjb { 338178481Sjb int which; 339178481Sjb 340178481Sjb /* Check against named parameters. */ 341178481Sjb for (which = 0; named && named[which]; which++) 342178481Sjb if (STREQ (named[which], param)) 343178481Sjb break; 344178481Sjb 345178481Sjb if (named && named[which]) 346178481Sjb { 347178481Sjb text = which < length_of_actuals ? actuals[which] : NULL; 348178481Sjb if (!text) 349178481Sjb text = ""; 350178481Sjb len = strlen (text); 351178481Sjb text = xstrdup (text); /* so we can free it */ 352178481Sjb } 353178481Sjb else 354178481Sjb { /* not a parameter, so it's an error. */ 355178481Sjb warning (_("\\ in macro expansion followed by `%s' instead of parameter name"), 356178481Sjb param); 357178481Sjb len++; 358178481Sjb text = xmalloc (1 + len); 359178481Sjb sprintf (text, "\\%s", param); 360178546Sjb } 361178481Sjb } 362178546Sjb 363178481Sjb if (strlen (param) + 2 < len) 364178481Sjb { 365178481Sjb new_body_size += len + 1; 366178481Sjb new_body = xrealloc (new_body, new_body_size); 367178481Sjb } 368178481Sjb 369178481Sjb free (param); 370178481Sjb 371178546Sjb strcpy (new_body + new_body_index, text); 372178481Sjb new_body_index += len; 373178481Sjb 374178481Sjb free (text); 375178481Sjb } 376178481Sjb } 377178481Sjb 378178481Sjb new_body[new_body_index] = 0; 379178481Sjb return new_body; 380178481Sjb} 381178481Sjb 382178481Sjb/* Expand macro passed in DEF, a pointer to a MACRO_DEF, and 383178481Sjb return its expansion as a string. */ 384178481Sjbchar * 385178481Sjbexpand_macro (MACRO_DEF *def) 386178481Sjb{ 387178481Sjb char **arglist; 388178481Sjb int num_args; 389178481Sjb char *execution_string = NULL; 390178481Sjb int start_line = line_number; 391178481Sjb 392178481Sjb /* Find out how many arguments this macro definition takes. */ 393178481Sjb num_args = array_len (def->arglist); 394178481Sjb 395178481Sjb /* Gather the arguments present on the line if there are any. */ 396178481Sjb arglist = get_macro_args (def); 397178481Sjb 398178481Sjb if (num_args < array_len (arglist)) 399178481Sjb { 400178481Sjb free_array (arglist); 401178546Sjb line_error (_("Macro `%s' called on line %d with too many args"), 402178546Sjb def->name, start_line); 403178481Sjb return execution_string; 404178481Sjb } 405178481Sjb 406178481Sjb if (def->body) 407178481Sjb execution_string = apply (def->arglist, arglist, def->body); 408178481Sjb 409178481Sjb free_array (arglist); 410178481Sjb return execution_string; 411178481Sjb} 412178481Sjb 413178481Sjb/* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */ 414178481Sjbvoid 415178481Sjbexecute_macro (MACRO_DEF *def) 416178481Sjb{ 417178481Sjb char *execution_string; 418178546Sjb int start_line = line_number, end_line; 419178481Sjb 420178481Sjb if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion) 421178481Sjb me_append_before_this_command (); 422178481Sjb 423178481Sjb execution_string = expand_macro (def); 424178481Sjb if (!execution_string) 425178481Sjb return; 426178481Sjb 427178481Sjb if (def->body) 428178481Sjb { 429178481Sjb /* Reset the line number to where the macro arguments began. 430178481Sjb This makes line numbers reported in error messages correct in 431178481Sjb case the macro arguments span several lines and the expanded 432178481Sjb arguments invoke other commands. */ 433178481Sjb end_line = line_number; 434178481Sjb line_number = start_line; 435178481Sjb 436178481Sjb if (macro_expansion_output_stream 437178481Sjb && !executing_string && !me_inhibit_expansion) 438178481Sjb { 439178481Sjb remember_itext (input_text, input_text_offset); 440178481Sjb me_execute_string (execution_string); 441178481Sjb } 442178481Sjb else 443178481Sjb execute_string ("%s", execution_string); 444178481Sjb 445178481Sjb free (execution_string); 446178481Sjb line_number = end_line; 447178481Sjb } 448178481Sjb} 449178481Sjb 450178481Sjb 451178481Sjb/* Read and remember the definition of a macro. If RECURSIVE is set, 452178481Sjb set the ME_RECURSE flag. MACTYPE is either "macro" or "rmacro", and 453178481Sjb tells us what the matching @end should be. */ 454178481Sjbstatic void 455178481Sjbdefine_macro (char *mactype, int recursive) 456178481Sjb{ 457178481Sjb int i, start; 458178481Sjb char *name, *line; 459178481Sjb char *last_end = NULL; 460178481Sjb char *body = NULL; 461178481Sjb char **arglist = NULL; 462178481Sjb int body_size = 0, body_index = 0; 463178481Sjb int depth = 1; 464178481Sjb int flags = 0; 465178481Sjb int defining_line = line_number; 466178481Sjb 467178481Sjb if (macro_expansion_output_stream && !executing_string) 468178481Sjb me_append_before_this_command (); 469178481Sjb 470178481Sjb skip_whitespace (); 471178481Sjb 472178481Sjb /* Get the name of the macro. This is the set of characters which are 473178481Sjb not whitespace and are not `{' immediately following the @macro. */ 474178481Sjb start = input_text_offset; 475178546Sjb { 476178481Sjb int len; 477178481Sjb 478178481Sjb for (i = start; i < input_text_length && input_text[i] != '{' 479178481Sjb && !cr_or_whitespace (input_text[i]); 480178481Sjb i++) ; 481178481Sjb 482178481Sjb len = i - start; 483178481Sjb name = xmalloc (1 + len); 484178481Sjb memcpy (name, input_text + start, len); 485178481Sjb name[len] = 0; 486178481Sjb input_text_offset = i; 487178481Sjb } 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 702void 703cm_macro (void) 704{ 705 define_macro ("macro", 0); 706} 707 708void 709cm_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 718static MACRO_DEF * 719delete_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 737void 738cm_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. */ 785ITEXT * 786remember_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. */ 839void 840forget_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. */ 855void 856me_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. */ 867void 868me_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. */ 899void 900me_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. */ 929void 930append_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. */ 953void 954maybe_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 973void 974write_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 982typedef struct alias_struct 983{ 984 char *alias; 985 char *mapto; 986 struct alias_struct *next; 987} alias_type; 988 989static alias_type *aliases; 990 991/* @alias aname = cmdname */ 992 993void 994cm_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. */ 1011char * 1012alias_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. */ 1033typedef struct enclose_struct 1034{ 1035 char *enclose; 1036 char *before; 1037 char *after; 1038 struct enclose_struct *next; 1039} enclosure_type; 1040 1041static enclosure_type *enclosures; 1042 1043typedef struct enclosure_stack_struct 1044{ 1045 enclosure_type *current; 1046 struct enclosure_stack_struct *next; 1047} enclosure_stack_type; 1048 1049static enclosure_stack_type *enclosure_stack; 1050 1051/* @definfoenclose */ 1052void 1053cm_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 1071int 1072enclosure_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 */ 1093void 1094enclosure_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