1 /* makeinfo -- convert Texinfo source into other formats. 2 $Id: makeinfo.c,v 1.8 2006/07/17 16:12:36 espie Exp $ 3 4 Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 5 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 21 Original author of makeinfo: Brian Fox (bfox@ai.mit.edu). */ 22 23 #include "system.h" 24 #include "getopt.h" 25 26 #define COMPILING_MAKEINFO 27 #include "makeinfo.h" 28 #include "cmds.h" 29 #include "files.h" 30 #include "float.h" 31 #include "footnote.h" 32 #include "html.h" 33 #include "index.h" 34 #include "insertion.h" 35 #include "lang.h" 36 #include "macro.h" 37 #include "node.h" 38 #include "sectioning.h" 39 #include "toc.h" 40 #include "xml.h" 41 42 /* You can change some of the behavior of Makeinfo by changing the 43 following defines: */ 44 45 /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which 46 appear within an @table, @ftable, or @itemize environment to have 47 standard paragraph indentation. Without this, such paragraphs have 48 no starting indentation. */ 49 /* #define INDENT_PARAGRAPHS_IN_TABLE */ 50 51 /* Define PARAGRAPH_START_INDENT to be the amount of indentation that 52 the first lines of paragraphs receive by default, where no other 53 value has been specified. Users can change this value on the command 54 line, with the --paragraph-indent option, or within the texinfo file, 55 with the @paragraphindent command. */ 56 #define PARAGRAPH_START_INDENT 3 57 58 /* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you 59 wish to appear between paragraphs. A value of 1 creates a single blank 60 line between paragraphs. Paragraphs are defined by 2 or more consecutive 61 newlines in the input file (i.e., one or more blank lines). */ 62 #define DEFAULT_PARAGRAPH_SPACING 1 63 64 /* Global variables. */ 65 66 /* The output file name. */ 67 char *output_filename = NULL; 68 69 /* Name of the output file that the user elected to pass on the command line. 70 Such a name overrides any name found with the @setfilename command. */ 71 char *command_output_filename = NULL; 72 static char *save_command_output_filename = NULL; 73 74 #define INITIAL_PARAGRAPH_SPACE 5000 75 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE; 76 77 /* The amount of indentation to add at the starts of paragraphs. 78 0 means don't change existing indentation at paragraph starts. 79 > 0 is amount to indent new paragraphs by. 80 < 0 means indent to column zero by removing indentation if necessary. 81 82 This is normally zero, but some people prefer paragraph starts to be 83 somewhat more indented than paragraph bodies. A pretty value for 84 this is 3. */ 85 int paragraph_start_indent = PARAGRAPH_START_INDENT; 86 87 /* Indentation that is pending insertion. We have this for hacking lines 88 which look blank, but contain whitespace. We want to treat those as 89 blank lines. */ 90 int pending_indent = 0; 91 92 /* The index in our internal command table of the currently 93 executing command. */ 94 int command_index; 95 96 /* A search string which is used to find the first @setfilename. */ 97 char setfilename_search[] = 98 { COMMAND_PREFIX, 99 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 }; 100 101 /* Values for calling handle_variable_internal (). */ 102 #define SET 1 103 #define CLEAR 2 104 #define IFSET 3 105 #define IFCLEAR 4 106 107 /* Flags controlling the operation of the program. */ 108 109 /* Default is to remove output if there were errors. */ 110 int force = 0; 111 112 /* Default is to notify users of bad choices. */ 113 int print_warnings = 1; 114 115 /* Number of errors that we tolerate on a given fileset. */ 116 int max_error_level = 100; 117 118 /* The actual last inserted character. Note that this may be something 119 other than NEWLINE even if last_char_was_newline is 1. */ 120 int last_inserted_character = 0; 121 122 /* Nonzero means that a newline character has already been 123 inserted, so close_paragraph () should insert one less. */ 124 int line_already_broken = 0; 125 126 /* When nonzero we have finished an insertion (see end_insertion ()) and we 127 want to ignore false continued paragraph closings. */ 128 int insertion_paragraph_closed = 0; 129 130 /* Nonzero means attempt to make all of the lines have fill_column width. */ 131 int do_justification = 0; 132 133 /* Nonzero means don't replace whitespace with in HTML mode. */ 134 int in_html_elt = 0; 135 136 /* Nonzero means we are inserting a block level HTML element that must not be 137 enclosed in a <p>, such as <ul>, <ol> and <h?>. */ 138 int in_html_block_level_elt = 0; 139 140 /* True when expanding a macro definition. */ 141 static int executing_macro = 0; 142 143 /* True when we are inside a <li> block of a menu. */ 144 static int in_menu_item = 0; 145 146 typedef struct brace_element 147 { 148 struct brace_element *next; 149 COMMAND_FUNCTION *proc; 150 char *command; 151 int pos, line; 152 int in_fixed_width_font; 153 } BRACE_ELEMENT; 154 155 BRACE_ELEMENT *brace_stack = NULL; 156 157 static void convert_from_file (char *name); 158 static void convert_from_loaded_file (char *name); 159 static void convert_from_stream (FILE *stream, char *name); 160 static void do_flush_right_indentation (void); 161 static void handle_variable (int action); 162 static void handle_variable_internal (int action, char *name); 163 static void init_brace_stack (void); 164 static void init_internals (void); 165 static void pop_and_call_brace (void); 166 static void remember_brace (COMMAND_FUNCTION (*proc)); 167 static int end_of_sentence_p (void); 168 169 void maybe_update_execution_strings (char **text, unsigned int new_len); 170 171 /* Error handling. */ 172 173 /* Number of errors encountered. */ 174 int errors_printed = 0; 175 176 /* Remember that an error has been printed. If more than 177 max_error_level have been printed, then exit the program. */ 178 static void 179 remember_error (void) 180 { 181 errors_printed++; 182 if (max_error_level && (errors_printed > max_error_level)) 183 { 184 fprintf (stderr, _("Too many errors! Gave up.\n")); 185 flush_file_stack (); 186 if (errors_printed - max_error_level < 2) 187 cm_bye (); 188 xexit (1); 189 } 190 } 191 192 /* Print the last error gotten from the file system. */ 193 int 194 fs_error (char *filename) 195 { 196 remember_error (); 197 perror (filename); 198 return 0; 199 } 200 201 /* Print an error message, and return false. */ 202 void 203 #if defined (VA_FPRINTF) && __STDC__ 204 error (const char *format, ...) 205 #else 206 error (format, va_alist) 207 const char *format; 208 va_dcl 209 #endif 210 { 211 #ifdef VA_FPRINTF 212 va_list ap; 213 #endif 214 215 remember_error (); 216 217 VA_START (ap, format); 218 #ifdef VA_FPRINTF 219 VA_FPRINTF (stderr, format, ap); 220 #else 221 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8); 222 #endif /* not VA_FPRINTF */ 223 va_end (ap); 224 225 putc ('\n', stderr); 226 } 227 228 /* Just like error (), but print the input file and line number as well. */ 229 void 230 #if defined (VA_FPRINTF) && __STDC__ 231 file_line_error (char *infile, int lno, const char *format, ...) 232 #else 233 file_line_error (infile, lno, format, va_alist) 234 char *infile; 235 int lno; 236 const char *format; 237 va_dcl 238 #endif 239 { 240 #ifdef VA_FPRINTF 241 va_list ap; 242 #endif 243 244 remember_error (); 245 fprintf (stderr, "%s:%d: ", infile, lno); 246 247 VA_START (ap, format); 248 #ifdef VA_FPRINTF 249 VA_FPRINTF (stderr, format, ap); 250 #else 251 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8); 252 #endif /* not VA_FPRINTF */ 253 va_end (ap); 254 255 fprintf (stderr, ".\n"); 256 } 257 258 /* Just like file_line_error (), but take the input file and the line 259 number from global variables. */ 260 void 261 #if defined (VA_FPRINTF) && __STDC__ 262 line_error (const char *format, ...) 263 #else 264 line_error (format, va_alist) 265 const char *format; 266 va_dcl 267 #endif 268 { 269 #ifdef VA_FPRINTF 270 va_list ap; 271 #endif 272 273 remember_error (); 274 fprintf (stderr, "%s:%d: ", input_filename, line_number); 275 276 VA_START (ap, format); 277 #ifdef VA_FPRINTF 278 VA_FPRINTF (stderr, format, ap); 279 #else 280 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8); 281 #endif /* not VA_FPRINTF */ 282 va_end (ap); 283 284 fprintf (stderr, ".\n"); 285 } 286 287 void 288 #if defined (VA_FPRINTF) && __STDC__ 289 warning (const char *format, ...) 290 #else 291 warning (format, va_alist) 292 const char *format; 293 va_dcl 294 #endif 295 { 296 #ifdef VA_FPRINTF 297 va_list ap; 298 #endif 299 300 if (print_warnings) 301 { 302 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number); 303 304 VA_START (ap, format); 305 #ifdef VA_FPRINTF 306 VA_FPRINTF (stderr, format, ap); 307 #else 308 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8); 309 #endif /* not VA_FPRINTF */ 310 va_end (ap); 311 312 fprintf (stderr, ".\n"); 313 } 314 } 315 316 317 /* The other side of a malformed expression. */ 318 static void 319 misplaced_brace (void) 320 { 321 line_error (_("Misplaced %c"), '}'); 322 } 323 324 /* Main. */ 325 326 /* Display the version info of this invocation of Makeinfo. */ 327 static void 328 print_version_info (void) 329 { 330 printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION); 331 } 332 333 /* If EXIT_VALUE is zero, print the full usage message to stdout. 334 Otherwise, just say to use --help for more info. 335 Then exit with EXIT_VALUE. */ 336 static void 337 usage (int exit_value) 338 { 339 if (exit_value != 0) 340 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname); 341 else 342 { 343 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname); 344 puts (""); 345 346 puts (_("\ 347 Translate Texinfo source documentation to various other formats, by default\n\ 348 Info files suitable for reading online with Emacs or standalone GNU Info.\n")); 349 350 printf (_("\ 351 General options:\n\ 352 --error-limit=NUM quit after NUM errors (default %d).\n\ 353 --force preserve output even if errors.\n\ 354 --help display this help and exit.\n\ 355 --no-validate suppress node cross-reference validation.\n\ 356 --no-warn suppress warnings (but not errors).\n\ 357 --reference-limit=NUM warn about at most NUM references (default %d).\n\ 358 -v, --verbose explain what is being done.\n\ 359 --version display version information and exit.\n"), 360 max_error_level, reference_warning_limit); 361 puts (""); 362 363 /* xgettext: no-wrap */ 364 puts (_("\ 365 Output format selection (default is to produce Info):\n\ 366 --docbook output Docbook XML rather than Info.\n\ 367 --html output HTML rather than Info.\n\ 368 --xml output Texinfo XML rather than Info.\n\ 369 --plaintext output plain text rather than Info.\n\ 370 ")); 371 372 puts (_("\ 373 General output options:\n\ 374 -E, --macro-expand FILE output macro-expanded source to FILE.\n\ 375 ignoring any @setfilename.\n\ 376 --no-headers suppress node separators, Node: lines, and menus\n\ 377 from Info output (thus producing plain text)\n\ 378 or from HTML (thus producing shorter output);\n\ 379 also, write to standard output by default.\n\ 380 --no-split suppress splitting of Info or HTML output,\n\ 381 generate only one output file.\n\ 382 --number-sections output chapter and sectioning numbers.\n\ 383 -o, --output=FILE output to FILE (directory if split HTML),\n\ 384 ")); 385 386 printf (_("\ 387 Options for Info and plain text:\n\ 388 --enable-encoding output accented and special characters in\n\ 389 Info output based on @documentencoding.\n\ 390 --fill-column=NUM break Info lines at NUM characters (default %d).\n\ 391 --footnote-style=STYLE output footnotes in Info according to STYLE:\n\ 392 `separate' to put them in their own node;\n\ 393 `end' to put them at the end of the node\n\ 394 in which they are defined (default).\n\ 395 --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\ 396 If VAL is `none', do not indent; if VAL is\n\ 397 `asis', preserve existing indentation.\n\ 398 --split-size=NUM split Info files at size NUM (default %d).\n"), 399 fill_column, paragraph_start_indent, 400 DEFAULT_SPLIT_SIZE); 401 puts (""); 402 403 puts (_("\ 404 Options for HTML:\n\ 405 --css-include=FILE include FILE in HTML <style> output;\n\ 406 read stdin if FILE is -.\n\ 407 ")); 408 409 printf (_("\ 410 Options for XML and Docbook:\n\ 411 --output-indent=VAL indent XML elements by VAL spaces (default %d).\n\ 412 If VAL is 0, ignorable whitespace is dropped.\n\ 413 "), xml_indentation_increment); 414 puts (""); 415 416 puts (_("\ 417 Input file options:\n\ 418 --commands-in-node-names allow @ commands in node names.\n\ 419 -D VAR define the variable VAR, as with @set.\n\ 420 -I DIR append DIR to the @include search path.\n\ 421 -P DIR prepend DIR to the @include search path.\n\ 422 -U VAR undefine the variable VAR, as with @clear.\n\ 423 ")); 424 425 puts (_("\ 426 Conditional processing in input:\n\ 427 --ifdocbook process @ifdocbook and @docbook even if\n\ 428 not generating Docbook.\n\ 429 --ifhtml process @ifhtml and @html even if not generating HTML.\n\ 430 --ifinfo process @ifinfo even if not generating Info.\n\ 431 --ifplaintext process @ifplaintext even if not generating plain text.\n\ 432 --iftex process @iftex and @tex; implies --no-split.\n\ 433 --ifxml process @ifxml and @xml.\n\ 434 --no-ifdocbook do not process @ifdocbook and @docbook text.\n\ 435 --no-ifhtml do not process @ifhtml and @html text.\n\ 436 --no-ifinfo do not process @ifinfo text.\n\ 437 --no-ifplaintext do not process @ifplaintext text.\n\ 438 --no-iftex do not process @iftex and @tex text.\n\ 439 --no-ifxml do not process @ifxml and @xml text.\n\ 440 \n\ 441 Also, for the --no-ifFORMAT options, do process @ifnotFORMAT text.\n\ 442 ")); 443 444 puts (_("\ 445 The defaults for the @if... conditionals depend on the output format:\n\ 446 if generating HTML, --ifhtml is on and the others are off;\n\ 447 if generating Info, --ifinfo is on and the others are off;\n\ 448 if generating plain text, --ifplaintext is on and the others are off;\n\ 449 if generating XML, --ifxml is on and the others are off.\n\ 450 ")); 451 452 fputs (_("\ 453 Examples:\n\ 454 makeinfo foo.texi write Info to foo's @setfilename\n\ 455 makeinfo --html foo.texi write HTML to @setfilename\n\ 456 makeinfo --xml foo.texi write Texinfo XML to @setfilename\n\ 457 makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\ 458 makeinfo --no-headers foo.texi write plain text to standard output\n\ 459 \n\ 460 makeinfo --html --no-headers foo.texi write html without node lines, menus\n\ 461 makeinfo --number-sections foo.texi write Info with numbered sections\n\ 462 makeinfo --no-split foo.texi write one Info file however big\n\ 463 "), stdout); 464 465 puts (_("\n\ 466 Email bug reports to bug-texinfo@gnu.org,\n\ 467 general questions and discussion to help-texinfo@gnu.org.\n\ 468 Texinfo home page: http://www.gnu.org/software/texinfo/")); 469 470 } /* end of full help */ 471 472 xexit (exit_value); 473 } 474 475 struct option long_options[] = 476 { 477 { "commands-in-node-names", 0, &expensive_validation, 1 }, 478 { "css-include", 1, 0, 'C' }, 479 { "docbook", 0, 0, 'd' }, 480 { "enable-encoding", 0, &enable_encoding, 1 }, 481 { "error-limit", 1, 0, 'e' }, 482 { "fill-column", 1, 0, 'f' }, 483 { "footnote-style", 1, 0, 's' }, 484 { "force", 0, &force, 1 }, 485 { "help", 0, 0, 'h' }, 486 { "html", 0, 0, 'w' }, 487 { "ifdocbook", 0, &process_docbook, 1 }, 488 { "ifhtml", 0, &process_html, 1 }, 489 { "ifinfo", 0, &process_info, 1 }, 490 { "ifplaintext", 0, &process_plaintext, 1 }, 491 { "iftex", 0, &process_tex, 1 }, 492 { "ifxml", 0, &process_xml, 1 }, 493 { "macro-expand", 1, 0, 'E' }, 494 { "no-headers", 0, &no_headers, 1 }, 495 { "no-ifdocbook", 0, &process_docbook, 0 }, 496 { "no-ifhtml", 0, &process_html, 0 }, 497 { "no-ifinfo", 0, &process_info, 0 }, 498 { "no-ifplaintext", 0, &process_plaintext, 0 }, 499 { "no-iftex", 0, &process_tex, 0 }, 500 { "no-ifxml", 0, &process_xml, 0 }, 501 { "no-number-footnotes", 0, &number_footnotes, 0 }, 502 { "no-number-sections", 0, &number_sections, 0 }, 503 { "no-pointer-validate", 0, &validating, 0 }, 504 { "no-split", 0, &splitting, 0 }, 505 { "no-validate", 0, &validating, 0 }, 506 { "no-warn", 0, &print_warnings, 0 }, 507 { "number-footnotes", 0, &number_footnotes, 1 }, 508 { "number-sections", 0, &number_sections, 1 }, 509 { "output", 1, 0, 'o' }, 510 { "output-indent", 1, 0, 'i' }, 511 { "paragraph-indent", 1, 0, 'p' }, 512 { "plaintext", 0, 0, 't' }, 513 { "reference-limit", 1, 0, 'r' }, 514 { "split-size", 1, 0, 'S'}, 515 { "verbose", 0, &verbose_mode, 1 }, 516 { "version", 0, 0, 'V' }, 517 { "xml", 0, 0, 'x' }, 518 {NULL, 0, NULL, 0} 519 }; 520 521 /* We use handle_variable_internal for -D and -U, and it depends on 522 execute_string, which depends on input_filename, which is not defined 523 while we are handling options. :-\ So we save these defines in this 524 struct, and handle them later. */ 525 typedef struct command_line_define 526 { 527 struct command_line_define *next; 528 int action; 529 char *define; 530 } COMMAND_LINE_DEFINE; 531 532 static COMMAND_LINE_DEFINE *command_line_defines = NULL; 533 534 /* For each file mentioned in the command line, process it, turning 535 Texinfo commands into wonderfully formatted output text. */ 536 int 537 main (int argc, char **argv) 538 { 539 int c, ind; 540 int reading_from_stdin = 0; 541 542 #ifdef HAVE_SETLOCALE 543 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing 544 of the argument to @multicolumn. */ 545 setlocale (LC_TIME, ""); 546 #ifdef LC_MESSAGES /* ultrix */ 547 setlocale (LC_MESSAGES, ""); 548 #endif 549 setlocale (LC_CTYPE, ""); 550 setlocale (LC_COLLATE, ""); 551 #endif 552 553 #ifdef ENABLE_NLS 554 /* Set the text message domain. */ 555 bindtextdomain (PACKAGE, LOCALEDIR); 556 textdomain (PACKAGE); 557 #endif 558 559 /* If TEXINFO_OUTPUT_FORMAT envvar is set, use it to set default output. 560 Can be overridden with one of the output options. */ 561 if (getenv ("TEXINFO_OUTPUT_FORMAT") != NULL) 562 { 563 if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "docbook")) 564 { 565 splitting = 0; 566 html = 0; 567 docbook = 1; 568 xml = 1; 569 process_docbook = 1; 570 } 571 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "html")) 572 { 573 html = 1; 574 docbook = 0; 575 xml = 0; 576 process_html = 1; 577 } 578 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "info")) 579 { 580 html = 0; 581 docbook = 0; 582 xml = 0; 583 } 584 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "plaintext")) 585 { 586 splitting = 0; 587 no_headers = 1; 588 html = 0; 589 docbook = 0; 590 xml = 0; 591 process_plaintext = 1; 592 } 593 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "xml")) 594 { 595 splitting = 0; 596 html = 0; 597 docbook = 0; 598 xml = 1; 599 process_xml = 1; 600 } 601 else 602 fprintf (stderr, 603 _("%s: Ignoring unrecognized TEXINFO_OUTPUT_FORMAT value `%s'.\n"), 604 progname, getenv ("TEXINFO_OUTPUT_FORMAT")); 605 } 606 607 /* Parse argument flags from the input line. */ 608 while ((c = getopt_long (argc, argv, "D:de:E:f:hI:i:o:p:P:r:s:t:U:vV:wx", 609 long_options, &ind)) != EOF) 610 { 611 if (c == 0 && long_options[ind].flag == 0) 612 c = long_options[ind].val; 613 614 switch (c) 615 { 616 case 'C': /* --css-include */ 617 css_include = xstrdup (optarg); 618 break; 619 620 case 'D': 621 case 'U': 622 /* User specified variable to set or clear. */ 623 if (xml && !docbook) 624 { 625 COMMAND_LINE_DEFINE *new = xmalloc (sizeof (COMMAND_LINE_DEFINE)); 626 new->action = (c == 'D') ? SET : CLEAR; 627 new->define = xstrdup (optarg); 628 new->next = command_line_defines; 629 command_line_defines = new; 630 } 631 else 632 handle_variable_internal ((c == 'D' ? SET : CLEAR), optarg); 633 break; 634 635 case 'd': /* --docbook */ 636 splitting = 0; 637 xml = 1; 638 docbook = 1; 639 html = 0; 640 process_docbook = 1; 641 break; 642 643 case 'e': /* --error-limit */ 644 if (sscanf (optarg, "%d", &max_error_level) != 1) 645 { 646 fprintf (stderr, 647 _("%s: %s arg must be numeric, not `%s'.\n"), 648 progname, "--error-limit", optarg); 649 usage (1); 650 } 651 break; 652 653 case 'E': /* --macro-expand */ 654 if (!macro_expansion_output_stream) 655 { 656 macro_expansion_filename = optarg; 657 macro_expansion_output_stream 658 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w"); 659 if (!macro_expansion_output_stream) 660 error (_("%s: could not open macro expansion output `%s'"), 661 progname, optarg); 662 } 663 else 664 fprintf (stderr, 665 _("%s: ignoring second macro expansion output `%s'.\n"), 666 progname, optarg); 667 break; 668 669 case 'f': /* --fill-column */ 670 if (sscanf (optarg, "%d", &fill_column) != 1) 671 { 672 fprintf (stderr, 673 _("%s: %s arg must be numeric, not `%s'.\n"), 674 progname, "--fill-column", optarg); 675 usage (1); 676 } 677 break; 678 679 case 'h': /* --help */ 680 usage (0); 681 break; 682 683 case 'I': 684 /* Append user-specified dir to include file path. */ 685 append_to_include_path (optarg); 686 break; 687 688 case 'i': 689 if (sscanf (optarg, "%d", &xml_indentation_increment) != 1) 690 { 691 fprintf (stderr, 692 _("%s: %s arg must be numeric, not `%s'.\n"), 693 progname, "--output-indent", optarg); 694 usage (1); 695 } 696 break; 697 698 case 'o': /* --output */ 699 command_output_filename = xstrdup (optarg); 700 save_command_output_filename = command_output_filename; 701 break; 702 703 case 'p': /* --paragraph-indent */ 704 if (set_paragraph_indent (optarg) < 0) 705 { 706 fprintf (stderr, 707 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"), 708 progname, optarg); 709 usage (1); 710 } 711 break; 712 713 case 'P': 714 /* Prepend user-specified include dir to include path. */ 715 prepend_to_include_path (optarg); 716 break; 717 718 case 'r': /* --reference-limit */ 719 if (sscanf (optarg, "%d", &reference_warning_limit) != 1) 720 { 721 fprintf (stderr, 722 _("%s: %s arg must be numeric, not `%s'.\n"), 723 progname, "--reference-limit", optarg); 724 usage (1); 725 } 726 break; 727 728 case 's': /* --footnote-style */ 729 if (set_footnote_style (optarg) < 0) 730 { 731 fprintf (stderr, 732 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"), 733 progname, optarg); 734 usage (1); 735 } 736 footnote_style_preset = 1; 737 break; 738 739 case 'S': /* --split-size */ 740 if (sscanf (optarg, "%d", &split_size) != 1) 741 { 742 fprintf (stderr, 743 _("%s: %s arg must be numeric, not `%s'.\n"), 744 progname, "--split-size", optarg); 745 usage (1); 746 } 747 break; 748 749 case 't': /* --plaintext */ 750 splitting = 0; 751 no_headers = 1; 752 html = 0; 753 docbook = 0; 754 xml = 0; 755 process_plaintext = 1; 756 break; 757 758 case 'v': 759 verbose_mode++; 760 break; 761 762 case 'V': /* --version */ 763 print_version_info (); 764 puts (""); 765 puts ("Copyright (C) 2004 Free Software Foundation, Inc."); 766 printf (_("There is NO warranty. You may redistribute this software\n\ 767 under the terms of the GNU General Public License.\n\ 768 For more information about these matters, see the files named COPYING.\n")); 769 xexit (0); 770 break; 771 772 case 'w': /* --html */ 773 xml = 0; 774 docbook = 0; 775 html = 1; 776 process_html = 1; 777 break; 778 779 case 'x': /* --xml */ 780 splitting = 0; 781 html = 0; 782 docbook = 0; 783 xml = 1; 784 process_xml = 1; 785 break; 786 787 case '?': 788 usage (1); 789 break; 790 } 791 } 792 793 if (macro_expansion_output_stream) 794 validating = 0; 795 796 if (!validating) 797 expensive_validation = 0; 798 799 if (optind == argc) 800 { 801 /* Check to see if input is a file. If so, process that. */ 802 if (!isatty (fileno (stdin))) 803 reading_from_stdin = 1; 804 else 805 { 806 fprintf (stderr, _("%s: missing file argument.\n"), progname); 807 usage (1); 808 } 809 } 810 811 if (no_headers) 812 { 813 /* If the user did not specify an output file, use stdout. */ 814 if (!command_output_filename) 815 command_output_filename = xstrdup ("-"); 816 817 if (html && splitting && !STREQ (command_output_filename, "-")) 818 { /* --no-headers --no-split --html indicates confusion. */ 819 fprintf (stderr, 820 "%s: can't split --html output to `%s' with --no-headers.\n", 821 progname, command_output_filename); 822 usage (1); 823 } 824 825 /* --no-headers implies --no-split. */ 826 splitting = 0; 827 } 828 829 if (process_info == -1) 830 { /* no explicit --[no-]ifinfo option, so we'll do @ifinfo 831 if we're generating info or (for compatibility) plain text. */ 832 process_info = !html && !xml; 833 } 834 835 if (process_plaintext == -1) 836 { /* no explicit --[no-]ifplaintext option, so we'll do @ifplaintext 837 if we're generating plain text. */ 838 process_plaintext = no_headers && !html && !xml; 839 } 840 841 if (verbose_mode) 842 print_version_info (); 843 844 /* Remaining arguments are file names of texinfo files. 845 Convert them, one by one. */ 846 if (!reading_from_stdin) 847 { 848 while (optind != argc) 849 convert_from_file (argv[optind++]); 850 } 851 else 852 convert_from_stream (stdin, "stdin"); 853 854 xexit (errors_printed ? 2 : 0); 855 return 0; /* Avoid bogus warnings. */ 856 } 857 858 /* Hacking tokens and strings. */ 859 860 /* Return the next token as a string pointer. We cons the string. This 861 `token' means simply a command name. */ 862 863 /* = is so @alias works. ^ and _ are so macros can be used in math mode 864 without a space following. Possibly we should simply allow alpha, to 865 be compatible with TeX. */ 866 #define COMMAND_CHAR(c) (!cr_or_whitespace(c) \ 867 && (c) != '{' \ 868 && (c) != '}' \ 869 && (c) != '=' \ 870 && (c) != '_' \ 871 && (c) != '^' \ 872 ) 873 874 static char * 875 read_token (void) 876 { 877 int i, character; 878 char *result; 879 880 /* If the first character to be read is self-delimiting, then that 881 is the command itself. */ 882 character = curchar (); 883 if (self_delimiting (character)) 884 { 885 input_text_offset++; 886 887 if (character == '\n') 888 line_number++; 889 890 result = xstrdup (" "); 891 *result = character; 892 return result; 893 } 894 895 for (i = 0; ((input_text_offset != input_text_length) 896 && (character = curchar ()) 897 && COMMAND_CHAR (character)); 898 i++, input_text_offset++); 899 result = xmalloc (i + 1); 900 memcpy (result, &input_text[input_text_offset - i], i); 901 result[i] = 0; 902 return result; 903 } 904 905 /* Return nonzero if CHARACTER is self-delimiting. */ 906 int 907 self_delimiting (int character) 908 { 909 /* @; and @\ are not Texinfo commands, but they are listed here 910 anyway. I don't know why. --karl, 10aug96. */ 911 return strchr ("~{|}`^\\@?=;:./-,*\'\" !\n\t", character) != NULL; 912 } 913 914 /* Clear whitespace from the front and end of string. */ 915 void 916 canon_white (char *string) 917 { 918 char *p = string; 919 unsigned len; 920 921 if (!*p) 922 return; 923 924 do 925 { 926 if (!cr_or_whitespace (*p)) 927 break; 928 ++p; 929 } 930 while (*p); 931 932 len = strlen (p); 933 while (len && cr_or_whitespace (p[len-1])) 934 --len; 935 936 if (p != string) 937 memmove (string, p, len); 938 939 string[len] = 0; 940 } 941 942 /* Bash STRING, replacing all whitespace with just one space. */ 943 void 944 fix_whitespace (char *string) 945 { 946 char *temp = xmalloc (strlen (string) + 1); 947 int string_index = 0; 948 int temp_index = 0; 949 int c; 950 951 canon_white (string); 952 953 while (string[string_index]) 954 { 955 c = temp[temp_index++] = string[string_index++]; 956 957 if (c == ' ' || c == '\n' || c == '\t') 958 { 959 temp[temp_index - 1] = ' '; 960 while ((c = string[string_index]) && (c == ' ' || 961 c == '\t' || 962 c == '\n')) 963 string_index++; 964 } 965 } 966 temp[temp_index] = 0; 967 strcpy (string, temp); 968 free (temp); 969 } 970 971 /* Discard text until the desired string is found. The string is 972 included in the discarded text. */ 973 void 974 discard_until (char *string) 975 { 976 int temp = search_forward (string, input_text_offset); 977 978 int tt = (temp < 0) ? input_text_length : temp + strlen (string); 979 int from = input_text_offset; 980 981 /* Find out what line we are on. */ 982 while (from != tt) 983 if (input_text[from++] == '\n') 984 line_number++; 985 986 if (temp < 0) 987 { 988 /* not found, move current position to end of string */ 989 input_text_offset = input_text_length; 990 if (strcmp (string, "\n") != 0) 991 { /* Give a more descriptive feedback, if we are looking for ``@end '' 992 during macro execution. That means someone used a multiline 993 command as an argument to, say, @section ... style commands. */ 994 char *end_block = xmalloc (8); 995 sprintf (end_block, "\n%cend ", COMMAND_PREFIX); 996 if (executing_string && strstr (string, end_block)) 997 line_error (_("Multiline command %c%s used improperly"), 998 COMMAND_PREFIX, command); 999 else 1000 line_error (_("Expected `%s'"), string); 1001 free (end_block); 1002 return; 1003 } 1004 } 1005 else 1006 /* found, move current position to after the found string */ 1007 input_text_offset = temp + strlen (string); 1008 } 1009 1010 /* Read characters from the file until we are at MATCH. 1011 Place the characters read into STRING. 1012 On exit input_text_offset is after the match string. 1013 Return the offset where the string starts. */ 1014 int 1015 get_until (char *match, char **string) 1016 { 1017 int len, current_point, x, new_point, tem; 1018 1019 current_point = x = input_text_offset; 1020 new_point = search_forward (match, input_text_offset); 1021 1022 if (new_point < 0) 1023 new_point = input_text_length; 1024 len = new_point - current_point; 1025 1026 /* Keep track of which line number we are at. */ 1027 tem = new_point + (strlen (match) - 1); 1028 while (x != tem) 1029 if (input_text[x++] == '\n') 1030 line_number++; 1031 1032 *string = xmalloc (len + 1); 1033 1034 memcpy (*string, &input_text[current_point], len); 1035 (*string)[len] = 0; 1036 1037 /* Now leave input_text_offset in a consistent state. */ 1038 input_text_offset = tem; 1039 1040 if (input_text_offset > input_text_length) 1041 input_text_offset = input_text_length; 1042 1043 return new_point; 1044 } 1045 1046 /* Replace input_text[FROM .. TO] with its expansion. */ 1047 void 1048 replace_with_expansion (int from, int *to) 1049 { 1050 char *xp; 1051 unsigned xp_len, new_len; 1052 char *old_input = input_text; 1053 unsigned raw_len = *to - from; 1054 char *str; 1055 1056 /* The rest of the code here moves large buffers, so let's 1057 not waste time if the input cannot possibly expand 1058 into anything. Unfortunately, we cannot avoid expansion 1059 when we see things like @code etc., even if they only 1060 asked for expansion of macros, since any Texinfo command 1061 can be potentially redefined with a macro. */ 1062 if (only_macro_expansion && 1063 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0) 1064 return; 1065 1066 /* Get original string from input. */ 1067 str = xmalloc (raw_len + 1); 1068 memcpy (str, input_text + from, raw_len); 1069 str[raw_len] = 0; 1070 1071 /* We are going to relocate input_text, so we had better output 1072 pending portion of input_text now, before the pointer changes. */ 1073 if (macro_expansion_output_stream && !executing_string 1074 && !me_inhibit_expansion) 1075 append_to_expansion_output (from); 1076 1077 /* Expand it. */ 1078 xp = expansion (str, 0); 1079 xp_len = strlen (xp); 1080 free (str); 1081 1082 /* Plunk the expansion into the middle of `input_text' -- 1083 which is terminated by a newline, not a null. Avoid 1084 expensive move of the rest of the input if the expansion 1085 has the same length as the original string. */ 1086 if (xp_len != raw_len) 1087 { 1088 new_len = from + xp_len + input_text_length - *to + 1; 1089 if (executing_string) 1090 { /* If we are in execute_string, we might need to update 1091 the relevant element in the execution_strings[] array, 1092 since it could have to be relocated from under our 1093 feet. (input_text is reallocated here as well, if needed.) */ 1094 maybe_update_execution_strings (&input_text, new_len); 1095 } 1096 else if (new_len > input_text_length + 1) 1097 /* Don't bother to realloc if we have enough space. */ 1098 input_text = xrealloc (input_text, new_len); 1099 1100 memmove (input_text + from + xp_len, 1101 input_text + *to, input_text_length - *to + 1); 1102 1103 *to += xp_len - raw_len; 1104 /* Since we change input_text_length here, the comparison above 1105 isn't really valid, but it seems the worst that might happen is 1106 an extra xrealloc or two, so let's not worry. */ 1107 input_text_length += xp_len - raw_len; 1108 } 1109 memcpy (input_text + from, xp, xp_len); 1110 free (xp); 1111 1112 /* Synchronize the macro-expansion pointers with our new input_text. */ 1113 if (input_text != old_input) 1114 forget_itext (old_input); 1115 if (macro_expansion_output_stream && !executing_string) 1116 remember_itext (input_text, from); 1117 } 1118 1119 /* Read characters from the file until we are at MATCH or end of line. 1120 Place the characters read into STRING. If EXPAND is nonzero, 1121 expand the text before looking for MATCH for those cases where 1122 MATCH might be produced by some macro. */ 1123 void 1124 get_until_in_line (int expand, char *match, char **string) 1125 { 1126 int real_bottom = input_text_length; 1127 int limit = search_forward ("\n", input_text_offset); 1128 if (limit < 0) 1129 limit = input_text_length; 1130 1131 /* Replace input_text[input_text_offset .. limit-1] with its expansion. 1132 This allows the node names and menu entries themselves to be 1133 constructed via a macro, as in: 1134 @macro foo{p, q} 1135 Together: \p\ & \q\. 1136 @end macro 1137 1138 @node @foo{A,B}, next, prev, top 1139 1140 Otherwise, the `,' separating the macro args A and B is taken as 1141 the node argument separator, so the node name is `@foo{A'. This 1142 expansion is only necessary on the first call, since we expand the 1143 whole line then. */ 1144 if (expand) 1145 { 1146 replace_with_expansion (input_text_offset, &limit); 1147 } 1148 1149 real_bottom = input_text_length; 1150 input_text_length = limit; 1151 get_until (match, string); 1152 input_text_length = real_bottom; 1153 } 1154 1155 void 1156 get_rest_of_line (int expand, char **string) 1157 { 1158 xml_no_para ++; 1159 if (expand) 1160 { 1161 char *tem; 1162 1163 /* Don't expand non-macros in input, since we want them 1164 intact in the macro-expanded output. */ 1165 only_macro_expansion++; 1166 get_until_in_line (1, "\n", &tem); 1167 only_macro_expansion--; 1168 *string = expansion (tem, 0); 1169 free (tem); 1170 } 1171 else 1172 get_until_in_line (0, "\n", string); 1173 1174 canon_white (*string); 1175 1176 if (curchar () == '\n') /* as opposed to the end of the file... */ 1177 { 1178 line_number++; 1179 input_text_offset++; 1180 } 1181 xml_no_para --; 1182 } 1183 1184 /* Backup the input pointer to the previous character, keeping track 1185 of the current line number. */ 1186 void 1187 backup_input_pointer (void) 1188 { 1189 if (input_text_offset) 1190 { 1191 input_text_offset--; 1192 if (curchar () == '\n') 1193 line_number--; 1194 } 1195 } 1196 1197 /* Read characters from the file until we are at MATCH or closing brace. 1198 Place the characters read into STRING. */ 1199 void 1200 get_until_in_braces (char *match, char **string) 1201 { 1202 char *temp; 1203 int i, brace = 0; 1204 int match_len = strlen (match); 1205 1206 for (i = input_text_offset; i < input_text_length; i++) 1207 { 1208 if (i < input_text_length - 1 && input_text[i] == '@') 1209 { 1210 i++; /* skip commands like @, and @{ */ 1211 continue; 1212 } 1213 else if (input_text[i] == '{') 1214 brace++; 1215 else if (input_text[i] == '}') 1216 { 1217 brace--; 1218 /* If looking for a brace, don't stop at the interior brace, 1219 like after "baz" in "@foo{something @bar{baz} more}". */ 1220 if (brace == 0) 1221 continue; 1222 } 1223 else if (input_text[i] == '\n') 1224 line_number++; 1225 1226 if (brace < 0 || 1227 (brace == 0 && strncmp (input_text + i, match, match_len) == 0)) 1228 break; 1229 } 1230 1231 match_len = i - input_text_offset; 1232 temp = xmalloc (2 + match_len); 1233 memcpy (temp, input_text + input_text_offset, match_len); 1234 temp[match_len] = 0; 1235 input_text_offset = i; 1236 *string = temp; 1237 } 1238 1239 1240 1241 /* Converting a file. */ 1242 1243 /* Convert the file named by NAME. The output is saved on the file 1244 named as the argument to the @setfilename command. */ 1245 static char *suffixes[] = { 1246 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they 1247 have "texinfo.txi" and "texinfo.tex" in the same directory, the 1248 former is used rather than the latter, due to file name truncation. */ 1249 ".txi", 1250 ".texinfo", 1251 ".texi", 1252 ".txinfo", 1253 "", 1254 NULL 1255 }; 1256 1257 static void 1258 initialize_conversion (void) 1259 { 1260 init_tag_table (); 1261 init_indices (); 1262 init_internals (); 1263 init_paragraph (); 1264 1265 /* This is used for splitting the output file and for doing section 1266 headings. It was previously initialized in `init_paragraph', but its 1267 use there loses with the `init_paragraph' calls done by the 1268 multitable code; the tag indices get reset to zero. */ 1269 output_position = 0; 1270 } 1271 1272 /* Reverse the chain of structures in LIST. Output the new head 1273 of the chain. You should always assign the output value of this 1274 function to something, or you will lose the chain. */ 1275 GENERIC_LIST * 1276 reverse_list (GENERIC_LIST *list) 1277 { 1278 GENERIC_LIST *next; 1279 GENERIC_LIST *prev = NULL; 1280 1281 while (list) 1282 { 1283 next = list->next; 1284 list->next = prev; 1285 prev = list; 1286 list = next; 1287 } 1288 return prev; 1289 } 1290 1291 /* We read in multiples of 4k, simply because it is a typical pipe size 1292 on unix systems. */ 1293 #define READ_BUFFER_GROWTH (4 * 4096) 1294 1295 /* Convert the Texinfo file coming from the open stream STREAM. Assume the 1296 source of the stream is named NAME. */ 1297 static void 1298 convert_from_stream (FILE *stream, char *name) 1299 { 1300 char *buffer = NULL; 1301 int buffer_offset = 0, buffer_size = 0; 1302 1303 initialize_conversion (); 1304 1305 /* Read until the end of the stream. This isn't strictly correct, since 1306 the texinfo input may end before the stream ends, but it is a quick 1307 working hueristic. */ 1308 while (!feof (stream)) 1309 { 1310 int count; 1311 1312 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size) 1313 buffer = (char *) 1314 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH)); 1315 1316 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream); 1317 1318 if (count < 0) 1319 { 1320 perror (name); 1321 xexit (1); 1322 } 1323 1324 buffer_offset += count; 1325 if (count == 0) 1326 break; 1327 } 1328 1329 /* Set the globals to the new file. */ 1330 input_text = buffer; 1331 input_text_length = buffer_offset; 1332 input_filename = xstrdup (name); 1333 node_filename = xstrdup (name); 1334 input_text_offset = 0; 1335 line_number = 1; 1336 1337 /* Not strictly necessary. This magic prevents read_token () from doing 1338 extra unnecessary work each time it is called (that is a lot of times). 1339 The INPUT_TEXT_LENGTH is one past the actual end of the text. */ 1340 input_text[input_text_length] = '\n'; 1341 1342 convert_from_loaded_file (name); 1343 } 1344 1345 static void 1346 convert_from_file (char *name) 1347 { 1348 int i; 1349 char *filename = xmalloc (strlen (name) + 50); 1350 1351 /* Prepend file directory to the search path, so relative links work. */ 1352 prepend_to_include_path (pathname_part (name)); 1353 1354 initialize_conversion (); 1355 1356 /* Try to load the file specified by NAME, concatenated with our 1357 various suffixes. Prefer files like `makeinfo.texi' to 1358 `makeinfo'. */ 1359 for (i = 0; suffixes[i]; i++) 1360 { 1361 strcpy (filename, name); 1362 strcat (filename, suffixes[i]); 1363 1364 if (find_and_load (filename, 1)) 1365 break; 1366 1367 if (!suffixes[i][0] && strrchr (filename, '.')) 1368 { 1369 fs_error (filename); 1370 free (filename); 1371 return; 1372 } 1373 } 1374 1375 if (!suffixes[i]) 1376 { 1377 fs_error (name); 1378 free (filename); 1379 return; 1380 } 1381 1382 input_filename = filename; 1383 1384 convert_from_loaded_file (name); 1385 1386 /* Pop the prepended path, so multiple filenames in the 1387 command line do not screw each others include paths. */ 1388 pop_path_from_include_path (); 1389 } 1390 1391 static int 1392 create_html_directory (char *dir, int can_remove_file) 1393 { 1394 struct stat st; 1395 1396 /* Already exists. */ 1397 if (stat (dir, &st) == 0) 1398 { 1399 /* And it's a directory, so silently reuse it. */ 1400 if (S_ISDIR (st.st_mode)) 1401 return 1; 1402 /* Not a directory, so move it out of the way if we are allowed. */ 1403 else if (can_remove_file) 1404 { 1405 if (unlink (dir) != 0) 1406 return 0; 1407 } 1408 else 1409 return 0; 1410 } 1411 1412 if (mkdir (dir, 0777) == 0) 1413 /* Success! */ 1414 return 1; 1415 else 1416 return 0; 1417 } 1418 1419 /* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return 1420 "/foo/bar/baz/baz.html". This routine is called only if html && splitting. 1421 1422 Split html output goes into the subdirectory of the toplevel 1423 filename, without extension. For example: 1424 @setfilename foo.info 1425 produces output in files foo/index.html, foo/second-node.html, ... 1426 1427 But if the user said -o foo.whatever on the cmd line, then use 1428 foo.whatever unchanged. */ 1429 1430 static char * 1431 insert_toplevel_subdirectory (char *output_filename) 1432 { 1433 static const char index_name[] = "index.html"; 1434 char *dir, *subdir, *base, *basename, *p; 1435 char buf[PATH_MAX]; 1436 const int index_len = sizeof (index_name) - 1; 1437 1438 strcpy (buf, output_filename); 1439 dir = pathname_part (buf); /* directory of output_filename */ 1440 base = filename_part (buf); /* strips suffix, too */ 1441 basename = xstrdup (base); /* remember real @setfilename name */ 1442 p = dir + strlen (dir) - 1; 1443 if (p > dir && IS_SLASH (*p)) 1444 *p = 0; 1445 p = strrchr (base, '.'); 1446 if (p) 1447 *p = 0; 1448 1449 /* Split html output goes into subdirectory of toplevel name. */ 1450 if (save_command_output_filename 1451 && STREQ (output_filename, save_command_output_filename)) 1452 subdir = basename; /* from user, use unchanged */ 1453 else 1454 subdir = base; /* implicit, omit suffix */ 1455 1456 free (output_filename); 1457 output_filename = xmalloc (strlen (dir) + 1 1458 + strlen (basename) + 1 1459 + index_len 1460 + 1); 1461 strcpy (output_filename, dir); 1462 if (strlen (dir)) 1463 strcat (output_filename, "/"); 1464 strcat (output_filename, subdir); 1465 1466 /* First try, do not remove existing file. */ 1467 if (!create_html_directory (output_filename, 0)) 1468 { 1469 /* That failed, try subdir name with .html. 1470 Remove it if it exists. */ 1471 strcpy (output_filename, dir); 1472 if (strlen (dir)) 1473 strcat (output_filename, "/"); 1474 strcat (output_filename, basename); 1475 1476 if (!create_html_directory (output_filename, 1)) 1477 { 1478 /* Last try failed too :-\ */ 1479 line_error (_("Can't create directory `%s': %s"), 1480 output_filename, strerror (errno)); 1481 xexit (1); 1482 } 1483 } 1484 1485 strcat (output_filename, "/"); 1486 strcat (output_filename, index_name); 1487 return output_filename; 1488 } 1489 1490 /* FIXME: this is way too hairy */ 1491 static void 1492 convert_from_loaded_file (char *name) 1493 { 1494 char *real_output_filename = NULL; 1495 1496 remember_itext (input_text, 0); 1497 1498 input_text_offset = 0; 1499 1500 /* Avoid the `\input texinfo' line in HTML output (assuming it starts 1501 the file). */ 1502 if (looking_at ("\\input")) 1503 discard_until ("\n"); 1504 1505 /* Search this file looking for the special string which starts conversion. 1506 Once found, we may truly begin. */ 1507 while (input_text_offset >= 0) 1508 { 1509 input_text_offset = 1510 search_forward (setfilename_search, input_text_offset); 1511 1512 if (input_text_offset == 0 1513 || (input_text_offset > 0 1514 && input_text[input_text_offset -1] == '\n')) 1515 break; 1516 else if (input_text_offset > 0) 1517 input_text_offset++; 1518 } 1519 1520 if (input_text_offset < 0) 1521 { 1522 if (!command_output_filename) 1523 { 1524 #if defined (REQUIRE_SETFILENAME) 1525 error (_("No `%s' found in `%s'"), setfilename_search, name); 1526 goto finished; 1527 #else 1528 command_output_filename = output_name_from_input_name (name); 1529 #endif /* !REQUIRE_SETFILENAME */ 1530 } 1531 1532 { 1533 int i, end_of_first_line; 1534 1535 /* Find the end of the first line in the file. */ 1536 for (i = 0; i < input_text_length - 1; i++) 1537 if (input_text[i] == '\n') 1538 break; 1539 1540 end_of_first_line = i + 1; 1541 1542 for (i = 0; i < end_of_first_line; i++) 1543 { 1544 if ((input_text[i] == '\\') && 1545 (strncmp (input_text + i + 1, "input", 5) == 0)) 1546 { 1547 input_text_offset = i; 1548 break; 1549 } 1550 } 1551 } 1552 } 1553 else 1554 input_text_offset += strlen (setfilename_search); 1555 1556 if (!command_output_filename) 1557 { 1558 get_until ("\n", &output_filename); /* read rest of line */ 1559 if (html || xml) 1560 { /* Change any extension to .html or .xml. */ 1561 char *html_name, *directory_part, *basename_part, *temp; 1562 1563 canon_white (output_filename); 1564 directory_part = pathname_part (output_filename); 1565 1566 basename_part = filename_part (output_filename); 1567 1568 /* Zap any existing extension. */ 1569 temp = strrchr (basename_part, '.'); 1570 if (temp) 1571 *temp = 0; 1572 1573 /* Construct new filename. */ 1574 html_name = xmalloc (strlen (directory_part) 1575 + strlen (basename_part) + 6); 1576 strcpy (html_name, directory_part); 1577 strcat (html_name, basename_part); 1578 strcat (html_name, html ? ".html" : ".xml"); 1579 1580 /* Replace name from @setfilename with the html name. */ 1581 free (output_filename); 1582 output_filename = html_name; 1583 } 1584 } 1585 else 1586 { 1587 if (input_text_offset != -1) 1588 discard_until ("\n"); 1589 else 1590 input_text_offset = 0; 1591 1592 real_output_filename = output_filename = command_output_filename; 1593 command_output_filename = NULL; /* for included files or whatever */ 1594 } 1595 1596 canon_white (output_filename); 1597 toplevel_output_filename = xstrdup (output_filename); 1598 1599 if (real_output_filename && strcmp (real_output_filename, "-") == 0) 1600 { 1601 if (macro_expansion_filename 1602 && strcmp (macro_expansion_filename, "-") == 0) 1603 { 1604 fprintf (stderr, 1605 _("%s: Skipping macro expansion to stdout as Info output is going there.\n"), 1606 progname); 1607 macro_expansion_output_stream = NULL; 1608 } 1609 real_output_filename = xstrdup (real_output_filename); 1610 output_stream = stdout; 1611 splitting = 0; /* Cannot split when writing to stdout. */ 1612 } 1613 else 1614 { 1615 if (html && splitting) 1616 { 1617 if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0 1618 || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0) 1619 splitting = 0; 1620 else 1621 output_filename = insert_toplevel_subdirectory (output_filename); 1622 real_output_filename = xstrdup (output_filename); 1623 } 1624 else if (!real_output_filename) 1625 real_output_filename = expand_filename (output_filename, name); 1626 else 1627 real_output_filename = xstrdup (real_output_filename); 1628 1629 output_stream = fopen (real_output_filename, "w"); 1630 } 1631 1632 set_current_output_filename (real_output_filename); 1633 1634 if (xml && !docbook) 1635 xml_begin_document (filename_part (output_filename)); 1636 1637 if (verbose_mode) 1638 printf (_("Making %s file `%s' from `%s'.\n"), 1639 no_headers ? "text" 1640 : html ? "HTML" 1641 : xml ? "XML" 1642 : "info", 1643 output_filename, input_filename); 1644 1645 if (output_stream == NULL) 1646 { 1647 fs_error (real_output_filename); 1648 goto finished; 1649 } 1650 1651 /* Make the displayable filename from output_filename. Only the base 1652 portion of the filename need be displayed. */ 1653 flush_output (); /* in case there was no @bye */ 1654 if (output_stream != stdout) 1655 pretty_output_filename = filename_part (output_filename); 1656 else 1657 pretty_output_filename = xstrdup ("stdout"); 1658 1659 /* For this file only, count the number of newlines from the top of 1660 the file to here. This way, we keep track of line numbers for 1661 error reporting. Line_number starts at 1, since the user isn't 1662 zero-based. */ 1663 { 1664 int temp = 0; 1665 line_number = 1; 1666 while (temp != input_text_offset) 1667 if (input_text[temp++] == '\n') 1668 line_number++; 1669 } 1670 1671 /* html fixxme: should output this as trailer on first page. */ 1672 if (!no_headers && !html && !xml) 1673 add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"), 1674 output_filename, VERSION, input_filename); 1675 1676 close_paragraph (); 1677 1678 if (xml && !docbook) 1679 { 1680 /* Just before the real main loop, let's handle the defines. */ 1681 COMMAND_LINE_DEFINE *temp; 1682 1683 for (temp = command_line_defines; temp; temp = temp->next) 1684 { 1685 handle_variable_internal (temp->action, temp->define); 1686 free(temp->define); 1687 } 1688 } 1689 1690 reader_loop (); 1691 if (xml) 1692 xml_end_document (); 1693 1694 1695 finished: 1696 discard_insertions (0); 1697 close_paragraph (); 1698 flush_file_stack (); 1699 1700 if (macro_expansion_output_stream) 1701 { 1702 fclose (macro_expansion_output_stream); 1703 if (errors_printed && !force 1704 && strcmp (macro_expansion_filename, "-") != 0 1705 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0 1706 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0) 1707 { 1708 fprintf (stderr, 1709 _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"), 1710 progname, macro_expansion_filename); 1711 if (unlink (macro_expansion_filename) < 0) 1712 perror (macro_expansion_filename); 1713 } 1714 } 1715 1716 if (output_stream) 1717 { 1718 output_pending_notes (); 1719 1720 if (html) 1721 { 1722 no_indent = 1; 1723 start_paragraph (); 1724 add_word ("</body></html>\n"); 1725 close_paragraph (); 1726 } 1727 1728 /* maybe we want local variables in info output. */ 1729 { 1730 char *trailer = info_trailer (); 1731 if (!xml && !docbook && trailer) 1732 { 1733 if (html) 1734 insert_string ("<!--"); 1735 insert_string (trailer); 1736 free (trailer); 1737 if (html) 1738 insert_string ("\n-->\n"); 1739 } 1740 } 1741 1742 /* Write stuff makeinfo generates after @bye, ie. info_trailer. */ 1743 flush_output (); 1744 1745 if (output_stream != stdout) 1746 fclose (output_stream); 1747 1748 /* If validating, then validate the entire file right now. */ 1749 if (validating) 1750 validate_file (tag_table); 1751 1752 handle_delayed_writes (); 1753 1754 if (tag_table) 1755 { 1756 tag_table = (TAG_ENTRY *) reverse_list ((GENERIC_LIST *) tag_table); 1757 if (!no_headers && !html && !STREQ (current_output_filename, "-")) 1758 write_tag_table (real_output_filename); 1759 } 1760 1761 if (splitting && !html && (!errors_printed || force)) 1762 { 1763 clean_old_split_files (real_output_filename); 1764 split_file (real_output_filename, split_size); 1765 } 1766 else if (errors_printed 1767 && !force 1768 && strcmp (real_output_filename, "-") != 0 1769 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0 1770 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0) 1771 { /* If there were errors, and no --force, remove the output. */ 1772 fprintf (stderr, 1773 _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"), 1774 progname, real_output_filename); 1775 if (unlink (real_output_filename) < 0) 1776 perror (real_output_filename); 1777 } 1778 } 1779 free (real_output_filename); 1780 } 1781 1782 /* If enable_encoding is set and @documentencoding is used, return a 1783 Local Variables section (as a malloc-ed string) so that Emacs' 1784 locale features can work. Else return NULL. */ 1785 char * 1786 info_trailer (void) 1787 { 1788 char *encoding; 1789 1790 if (!enable_encoding) 1791 return NULL; 1792 1793 encoding = current_document_encoding (); 1794 1795 if (encoding && *encoding) 1796 { 1797 #define LV_FMT "\n\037\nLocal Variables:\ncoding: %s\nEnd:\n" 1798 char *lv = xmalloc (sizeof (LV_FMT) + strlen (encoding)); 1799 sprintf (lv, LV_FMT, encoding); 1800 free (encoding); 1801 return lv; 1802 } 1803 1804 free (encoding); 1805 return NULL; 1806 } 1807 1808 void 1809 free_and_clear (char **pointer) 1810 { 1811 if (*pointer) 1812 { 1813 free (*pointer); 1814 *pointer = NULL; 1815 } 1816 } 1817 1818 /* Initialize some state. */ 1819 static void 1820 init_internals (void) 1821 { 1822 free_and_clear (&output_filename); 1823 free_and_clear (&command); 1824 free_and_clear (&input_filename); 1825 free_node_references (); 1826 free_node_node_references (); 1827 toc_free (); 1828 init_insertion_stack (); 1829 init_brace_stack (); 1830 current_node = NULL; /* sometimes already freed */ 1831 command_index = 0; 1832 in_menu = 0; 1833 in_detailmenu = 0; 1834 top_node_seen = 0; 1835 non_top_node_seen = 0; 1836 node_number = -1; 1837 } 1838 1839 void 1840 init_paragraph (void) 1841 { 1842 free (output_paragraph); 1843 output_paragraph = xmalloc (paragraph_buffer_len); 1844 output_paragraph[0] = 0; 1845 output_paragraph_offset = 0; 1846 output_column = 0; 1847 paragraph_is_open = 0; 1848 current_indent = 0; 1849 meta_char_pos = 0; 1850 } 1851 1852 /* This is called from `reader_loop' when we are at the * beginning a 1853 menu line. */ 1854 1855 static void 1856 handle_menu_entry (void) 1857 { 1858 char *tem; 1859 1860 /* Ugh, glean_node_from_menu wants to read the * itself. */ 1861 input_text_offset--; 1862 1863 /* Find node name in menu entry and save it in references list for 1864 later validation. Use followed_reference type for detailmenu 1865 references since we don't want to use them for default node pointers. */ 1866 tem = glean_node_from_menu (1, in_detailmenu 1867 ? followed_reference : menu_reference); 1868 1869 if (html && tem) 1870 { /* Start a menu item with the cleaned-up line. Put an anchor 1871 around the start text (before `:' or the node name). */ 1872 char *string; 1873 1874 discard_until ("* "); 1875 1876 /* The line number was already incremented in reader_loop when we 1877 saw the newline, and discard_until has now incremented again. */ 1878 line_number--; 1879 1880 if (had_menu_commentary) 1881 { 1882 add_html_block_elt ("<ul class=\"menu\">\n"); 1883 had_menu_commentary = 0; 1884 in_paragraph = 0; 1885 } 1886 1887 if (in_paragraph) 1888 { 1889 add_html_block_elt ("</p>\n"); 1890 add_html_block_elt ("<ul class=\"menu\">\n"); 1891 in_paragraph = 0; 1892 } 1893 1894 in_menu_item = 1; 1895 1896 add_html_block_elt ("<li><a"); 1897 if (next_menu_item_number <= 9) 1898 { 1899 add_word(" accesskey="); 1900 add_word_args("\"%d\"", next_menu_item_number); 1901 next_menu_item_number++; 1902 } 1903 add_word (" href=\""); 1904 string = expansion (tem, 0); 1905 add_anchor_name (string, 1); 1906 add_word ("\">"); 1907 free (string); 1908 1909 /* The menu item may use macros, so expand them now. */ 1910 only_macro_expansion++; 1911 get_until_in_line (1, ":", &string); 1912 only_macro_expansion--; 1913 execute_string ("%s", string); /* get escaping done */ 1914 free (string); 1915 1916 add_word ("</a>"); 1917 1918 if (looking_at ("::")) 1919 discard_until (":"); 1920 else 1921 { /* discard the node name */ 1922 get_until_in_line (0, ".", &string); 1923 free (string); 1924 } 1925 input_text_offset++; /* discard the second colon or the period */ 1926 1927 /* Insert a colon only if there is a description of this menu item. */ 1928 { 1929 int save_input_text_offset = input_text_offset; 1930 int save_line_number = line_number; 1931 char *test_string; 1932 get_rest_of_line (0, &test_string); 1933 if (strlen (test_string) > 0) 1934 add_word (": "); 1935 input_text_offset = save_input_text_offset; 1936 line_number = save_line_number; 1937 } 1938 } 1939 else if (xml && tem) 1940 { 1941 xml_start_menu_entry (tem); 1942 } 1943 else if (tem) 1944 { /* For Info output, we can just use the input and the main case in 1945 reader_loop where we output what comes in. Just move off the * 1946 so the next time through reader_loop we don't end up back here. */ 1947 add_char ('*'); 1948 input_text_offset += 2; /* undo the pointer back-up above. */ 1949 } 1950 1951 if (tem) 1952 free (tem); 1953 } 1954 1955 /* Find the command corresponding to STRING. If the command is found, 1956 return a pointer to the data structure. Otherwise return -1. */ 1957 static COMMAND * 1958 get_command_entry (char *string) 1959 { 1960 int i; 1961 1962 for (i = 0; command_table[i].name; i++) 1963 if (strcmp (command_table[i].name, string) == 0) 1964 return &command_table[i]; 1965 1966 /* This command is not in our predefined command table. Perhaps 1967 it is a user defined command. */ 1968 for (i = 0; i < user_command_array_len; i++) 1969 if (user_command_array[i] && 1970 (strcmp (user_command_array[i]->name, string) == 0)) 1971 return user_command_array[i]; 1972 1973 /* We never heard of this command. */ 1974 return (COMMAND *) -1; 1975 } 1976 1977 /* input_text_offset is right at the command prefix character. 1978 Read the next token to determine what to do. Return zero 1979 if there's no known command or macro after the prefix character. */ 1980 static int 1981 read_command (void) 1982 { 1983 COMMAND *entry; 1984 int old_text_offset = input_text_offset++; 1985 1986 free_and_clear (&command); 1987 command = read_token (); 1988 1989 /* Check to see if this command is a macro. If so, execute it here. */ 1990 { 1991 MACRO_DEF *def; 1992 1993 def = find_macro (command); 1994 1995 if (def) 1996 { 1997 /* We disallow recursive use of a macro call. Inhibit the expansion 1998 of this macro during the life of its execution. */ 1999 if (!(def->flags & ME_RECURSE)) 2000 def->inhibited = 1; 2001 2002 executing_macro++; 2003 execute_macro (def); 2004 executing_macro--; 2005 2006 if (!(def->flags & ME_RECURSE)) 2007 def->inhibited = 0; 2008 2009 return 1; 2010 } 2011 } 2012 2013 if (only_macro_expansion) 2014 { 2015 /* Back up to the place where we were called, so the 2016 caller will have a chance to process this non-macro. */ 2017 input_text_offset = old_text_offset; 2018 return 0; 2019 } 2020 2021 /* Perform alias expansion */ 2022 command = alias_expand (command); 2023 2024 if (enclosure_command (command)) 2025 { 2026 remember_brace (enclosure_expand); 2027 enclosure_expand (START, output_paragraph_offset, 0); 2028 return 0; 2029 } 2030 2031 entry = get_command_entry (command); 2032 if (entry == (COMMAND *)-1) 2033 { 2034 line_error (_("Unknown command `%s'"), command); 2035 return 0; 2036 } 2037 2038 if (entry->argument_in_braces == BRACE_ARGS) 2039 remember_brace (entry->proc); 2040 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS) 2041 { 2042 if (curchar () == '{') 2043 remember_brace (entry->proc); 2044 else 2045 { /* No braces, so arg is next char. */ 2046 int ch; 2047 int saved_offset = output_paragraph_offset; 2048 (*(entry->proc)) (START, output_paragraph_offset, 0); 2049 2050 /* Possibilities left for the next character: @ (error), } 2051 (error), whitespace (skip) anything else (normal char). */ 2052 skip_whitespace (); 2053 ch = curchar (); 2054 if (ch == '@') 2055 { 2056 line_error (_("Use braces to give a command as an argument to @%s"), 2057 entry->name); 2058 return 0; 2059 } 2060 else if (ch == '}') 2061 { 2062 /* Our caller will give the error message, because this } 2063 won't match anything. */ 2064 return 0; 2065 } 2066 2067 add_char (ch); 2068 input_text_offset++; 2069 (*(entry->proc)) (END, saved_offset, output_paragraph_offset); 2070 return 1; 2071 } 2072 } 2073 2074 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS 2075 with braces. */ 2076 (*(entry->proc)) (START, output_paragraph_offset, 0); 2077 return 1; 2078 } 2079 2080 /* Okay, we are ready to start the conversion. Call the reader on 2081 some text, and fill the text as it is output. Handle commands by 2082 remembering things like open braces and the current file position on a 2083 stack, and when the corresponding close brace is found, you can call 2084 the function with the proper arguments. Although the filling isn't 2085 necessary for HTML, it should do no harm. */ 2086 void 2087 reader_loop (void) 2088 { 2089 int character; 2090 int done = 0; 2091 2092 while (!done) 2093 { 2094 if (input_text_offset >= input_text_length) 2095 break; 2096 2097 character = curchar (); 2098 2099 /* If only_macro_expansion, only handle macros and leave 2100 everything else intact. */ 2101 if (!only_macro_expansion && !in_fixed_width_font 2102 && ((!html && !xml) || escape_html) 2103 && (character == '\'' || character == '`') 2104 && input_text[input_text_offset + 1] == character) 2105 { 2106 if (html) 2107 { 2108 input_text_offset += 2; 2109 add_word (character == '`' ? "“" : "”"); 2110 continue; 2111 } 2112 else if (xml) 2113 { 2114 input_text_offset += 2; 2115 xml_insert_entity (character == '`' ? "ldquo" : "rdquo"); 2116 continue; 2117 } 2118 else 2119 { 2120 input_text_offset++; 2121 character = '"'; 2122 } 2123 } 2124 2125 /* Convert --- to --. */ 2126 if (!only_macro_expansion && character == '-' && !in_fixed_width_font 2127 && ((!html && !xml) || escape_html)) 2128 { 2129 int dash_count = 0; 2130 2131 /* Get the number of consequtive dashes. */ 2132 while (input_text[input_text_offset] == '-') 2133 { 2134 dash_count++; 2135 input_text_offset++; 2136 } 2137 2138 /* Eat one dash. */ 2139 dash_count--; 2140 2141 if (html || xml) 2142 { 2143 if (dash_count == 0) 2144 add_char ('-'); 2145 else 2146 while (dash_count > 0) 2147 { 2148 if (dash_count >= 2) 2149 { 2150 if (html) 2151 add_word ("—"); 2152 else 2153 xml_insert_entity ("mdash"); 2154 dash_count -= 2; 2155 } 2156 else if (dash_count >= 1) 2157 { 2158 if (html) 2159 add_word ("–"); 2160 else 2161 xml_insert_entity ("ndash"); 2162 dash_count--; 2163 } 2164 } 2165 } 2166 else 2167 { 2168 add_char ('-'); 2169 while (--dash_count > 0) 2170 add_char ('-'); 2171 } 2172 2173 continue; 2174 } 2175 2176 /* If this is a whitespace character, then check to see if the line 2177 is blank. If so, advance to the carriage return. */ 2178 if (!only_macro_expansion && whitespace (character)) 2179 { 2180 int i = input_text_offset + 1; 2181 2182 while (i < input_text_length && whitespace (input_text[i])) 2183 i++; 2184 2185 if (i == input_text_length || input_text[i] == '\n') 2186 { 2187 if (i == input_text_length) 2188 i--; 2189 2190 input_text_offset = i; 2191 character = curchar (); 2192 } 2193 } 2194 2195 if (character == '\n') 2196 line_number++; 2197 2198 switch (character) 2199 { 2200 case '*': /* perhaps we are at a menu */ 2201 /* We used to check for this in the \n case but an @c in a 2202 menu swallows its newline, so check here instead. */ 2203 if (!only_macro_expansion && in_menu 2204 && input_text_offset + 1 < input_text_length 2205 && input_text[input_text_offset-1] == '\n') 2206 handle_menu_entry (); 2207 else 2208 { /* Duplicate code from below, but not worth twisting the 2209 fallthroughs to get down there. */ 2210 add_char (character); 2211 input_text_offset++; 2212 } 2213 break; 2214 2215 /* Escapes for HTML unless we're outputting raw HTML. Do 2216 this always, even if SGML rules don't require it since 2217 that's easier and safer for non-conforming browsers. */ 2218 case '&': 2219 if (html && escape_html) 2220 add_word ("&"); 2221 else 2222 add_char (character); 2223 input_text_offset++; 2224 break; 2225 2226 case '<': 2227 if (html && escape_html) 2228 add_word ("<"); 2229 else if (xml && escape_html) 2230 xml_insert_entity ("lt"); 2231 else 2232 add_char (character); 2233 input_text_offset++; 2234 break; 2235 2236 case '>': 2237 if (html && escape_html) 2238 add_word (">"); 2239 else if (xml && escape_html) 2240 xml_insert_entity ("gt"); 2241 else 2242 add_char (character); 2243 input_text_offset++; 2244 break; 2245 2246 case COMMAND_PREFIX: /* @ */ 2247 if (read_command () || !only_macro_expansion) 2248 break; 2249 2250 /* FALLTHROUGH (usually) */ 2251 case '{': 2252 /* Special case. We're not supposed to see this character by itself. 2253 If we do, it means there is a syntax error in the input text. 2254 Report the error here, but remember this brace on the stack so 2255 we can ignore its partner. */ 2256 if (!only_macro_expansion) 2257 { 2258 if (command && !STREQ (command, "math")) 2259 { 2260 line_error (_("Misplaced %c"), '{'); 2261 remember_brace (misplaced_brace); 2262 } 2263 else 2264 /* We don't mind `extra' braces inside @math. */ 2265 remember_brace (cm_no_op); 2266 /* remember_brace advances input_text_offset. */ 2267 break; 2268 } 2269 2270 /* FALLTHROUGH (usually) */ 2271 case '}': 2272 if (!only_macro_expansion) 2273 { 2274 pop_and_call_brace (); 2275 input_text_offset++; 2276 break; 2277 } 2278 2279 /* FALLTHROUGH (usually) */ 2280 default: 2281 add_char (character); 2282 input_text_offset++; 2283 } 2284 } 2285 if (macro_expansion_output_stream && !only_macro_expansion) 2286 maybe_write_itext (input_text, input_text_offset); 2287 } 2288 2289 static void 2290 init_brace_stack (void) 2291 { 2292 brace_stack = NULL; 2293 } 2294 2295 /* Remember the current output position here. Save PROC 2296 along with it so you can call it later. */ 2297 static void 2298 remember_brace_1 (COMMAND_FUNCTION (*proc), int position) 2299 { 2300 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT)); 2301 new->next = brace_stack; 2302 new->proc = proc; 2303 new->command = command ? xstrdup (command) : ""; 2304 new->pos = position; 2305 new->line = line_number; 2306 new->in_fixed_width_font = in_fixed_width_font; 2307 brace_stack = new; 2308 } 2309 2310 static void 2311 remember_brace (COMMAND_FUNCTION (*proc)) 2312 { 2313 if (curchar () != '{') 2314 line_error (_("%c%s expected braces"), COMMAND_PREFIX, command); 2315 else 2316 input_text_offset++; 2317 remember_brace_1 (proc, output_paragraph_offset); 2318 } 2319 2320 /* Pop the top of the brace stack, and call the associated function 2321 with the args END and POS. */ 2322 static void 2323 pop_and_call_brace (void) 2324 { 2325 if (brace_stack == NULL) 2326 { 2327 line_error (_("Unmatched }")); 2328 return; 2329 } 2330 2331 { 2332 BRACE_ELEMENT *temp; 2333 2334 int pos = brace_stack->pos; 2335 COMMAND_FUNCTION *proc = brace_stack->proc; 2336 in_fixed_width_font = brace_stack->in_fixed_width_font; 2337 2338 /* Reset current command, so the proc can know who it is. This is 2339 used in cm_accent. */ 2340 command = brace_stack->command; 2341 2342 temp = brace_stack->next; 2343 free (brace_stack); 2344 brace_stack = temp; 2345 2346 (*proc) (END, pos, output_paragraph_offset); 2347 } 2348 } 2349 2350 /* Shift all of the markers in `brace_stack' by AMOUNT. */ 2351 static void 2352 adjust_braces_following (int here, int amount) 2353 { 2354 BRACE_ELEMENT *stack = brace_stack; 2355 2356 while (stack) 2357 { 2358 if (stack->pos >= here) 2359 stack->pos += amount; 2360 stack = stack->next; 2361 } 2362 } 2363 2364 /* Return the string which invokes PROC; a pointer to a function. 2365 Always returns the first function in the command table if more than 2366 one matches PROC. */ 2367 static const char * 2368 find_proc_name (COMMAND_FUNCTION (*proc)) 2369 { 2370 int i; 2371 2372 for (i = 0; command_table[i].name; i++) 2373 if (proc == command_table[i].proc) 2374 return command_table[i].name; 2375 return _("NO_NAME!"); 2376 } 2377 2378 /* You call discard_braces () when you shouldn't have any braces on the stack. 2379 I used to think that this happens for commands that don't take arguments 2380 in braces, but that was wrong because of things like @code{foo @@}. So now 2381 I only detect it at the beginning of nodes. */ 2382 void 2383 discard_braces (void) 2384 { 2385 if (!brace_stack) 2386 return; 2387 2388 while (brace_stack) 2389 { 2390 if (brace_stack->proc != misplaced_brace) 2391 { 2392 const char *proc_name; 2393 2394 proc_name = find_proc_name (brace_stack->proc); 2395 file_line_error (input_filename, brace_stack->line, 2396 _("%c%s missing close brace"), COMMAND_PREFIX, 2397 proc_name); 2398 pop_and_call_brace (); 2399 } 2400 else 2401 { 2402 BRACE_ELEMENT *temp; 2403 temp = brace_stack->next; 2404 free (brace_stack); 2405 brace_stack = temp; 2406 } 2407 } 2408 } 2409 2410 static int 2411 get_char_len (int character) 2412 { 2413 /* Return the printed length of the character. */ 2414 int len; 2415 2416 switch (character) 2417 { 2418 case '\t': 2419 len = (output_column + 8) & 0xf7; 2420 if (len > fill_column) 2421 len = fill_column - output_column; 2422 else 2423 len = len - output_column; 2424 break; 2425 2426 case '\n': 2427 len = fill_column - output_column; 2428 break; 2429 2430 default: 2431 /* ASCII control characters appear as two characters in the output 2432 (e.g., ^A). But characters with the high bit set are just one 2433 on suitable terminals, so don't count them as two for line 2434 breaking purposes. */ 2435 if (0 <= character && character < ' ') 2436 len = 2; 2437 else 2438 len = 1; 2439 } 2440 return len; 2441 } 2442 2443 void 2444 #if defined (VA_FPRINTF) && __STDC__ 2445 add_word_args (const char *format, ...) 2446 #else 2447 add_word_args (format, va_alist) 2448 const char *format; 2449 va_dcl 2450 #endif 2451 { 2452 char buffer[2000]; /* xx no fixed limits */ 2453 #ifdef VA_FPRINTF 2454 va_list ap; 2455 #endif 2456 2457 VA_START (ap, format); 2458 #ifdef VA_SPRINTF 2459 VA_SPRINTF (buffer, format, ap); 2460 #else 2461 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8); 2462 #endif /* not VA_SPRINTF */ 2463 va_end (ap); 2464 add_word (buffer); 2465 } 2466 2467 /* Add STRING to output_paragraph. */ 2468 void 2469 add_word (char *string) 2470 { 2471 while (*string) 2472 add_char (*string++); 2473 } 2474 2475 /* Like add_word, but inhibits conversion of whitespace into . 2476 Use this to output HTML directives with embedded blanks, to make 2477 them @w-safe. */ 2478 void 2479 add_html_elt (char *string) 2480 { 2481 in_html_elt++; 2482 add_word (string); 2483 in_html_elt--; 2484 } 2485 2486 /* These two functions below, add_html_block_elt and add_html_block_elt_args, 2487 are mixtures of add_html_elt and add_word_args. They inform makeinfo that 2488 the current HTML element being inserted should not be enclosed in a <p> 2489 element. */ 2490 void 2491 add_html_block_elt (char *string) 2492 { 2493 in_html_block_level_elt++; 2494 add_word (string); 2495 in_html_block_level_elt--; 2496 } 2497 2498 void 2499 #if defined (VA_FPRINTF) && __STDC__ 2500 add_html_block_elt_args (const char *format, ...) 2501 #else 2502 add_html_block_elt_args (format, va_alist) 2503 const char *format; 2504 va_dcl 2505 #endif 2506 { 2507 char buffer[2000]; /* xx no fixed limits */ 2508 #ifdef VA_FPRINTF 2509 va_list ap; 2510 #endif 2511 2512 VA_START (ap, format); 2513 #ifdef VA_SPRINTF 2514 VA_SPRINTF (buffer, format, ap); 2515 #else 2516 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8); 2517 #endif /* not VA_SPRINTF */ 2518 va_end (ap); 2519 add_html_block_elt (buffer); 2520 } 2521 2522 /* Here is another awful kludge, used in add_char. Ordinarily, macro 2523 expansions take place in the body of the document, and therefore we 2524 should html_output_head when we see one. But there's an exception: a 2525 macro call might take place within @copying, and that does not start 2526 the real output, even though we fully expand the copying text. 2527 2528 So we need to be able to check if we are defining the @copying text. 2529 We do this by looking back through the insertion stack. */ 2530 static int 2531 defining_copying (void) 2532 { 2533 INSERTION_ELT *i; 2534 for (i = insertion_stack; i; i = i->next) 2535 { 2536 if (i->insertion == copying) 2537 return 1; 2538 } 2539 return 0; 2540 } 2541 2542 2543 /* Add the character to the current paragraph. If filling_enabled is 2544 nonzero, then do filling as well. */ 2545 void 2546 add_char (int character) 2547 { 2548 if (xml) 2549 { 2550 xml_add_char (character); 2551 return; 2552 } 2553 2554 /* If we are avoiding outputting headers, and we are currently 2555 in a menu, then simply return. But if we're only expanding macros, 2556 then we're being called from glean_node_from_menu to try to 2557 remember a menu reference, and we need that so we can do defaulting. */ 2558 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu)) 2559 return; 2560 2561 /* If we are adding a character now, then we don't have to 2562 ignore close_paragraph () calls any more. */ 2563 if (must_start_paragraph && character != '\n') 2564 { 2565 must_start_paragraph = 0; 2566 line_already_broken = 0; /* The line is no longer broken. */ 2567 if (current_indent > output_column) 2568 { 2569 indent (current_indent - output_column); 2570 output_column = current_indent; 2571 } 2572 } 2573 2574 if (non_splitting_words 2575 && !(html && in_html_elt) 2576 && strchr (" \t\n", character)) 2577 { 2578 if (html || docbook) 2579 { /* Seems cleaner to use than an 8-bit char. */ 2580 int saved_escape_html = escape_html; 2581 escape_html = 0; 2582 add_word (" "); 2583 escape_html = saved_escape_html; 2584 character = ';'; 2585 } 2586 else 2587 character = META (' '); /* unmeta-d in flush_output */ 2588 } 2589 2590 insertion_paragraph_closed = 0; 2591 2592 switch (character) 2593 { 2594 case '\n': 2595 if (!filling_enabled && !(html && (in_menu || in_detailmenu))) 2596 { 2597 insert ('\n'); 2598 2599 if (force_flush_right) 2600 { 2601 close_paragraph (); 2602 /* Hack to force single blank lines out in this mode. */ 2603 flush_output (); 2604 } 2605 2606 output_column = 0; 2607 2608 if (!no_indent && paragraph_is_open) 2609 indent (output_column = current_indent); 2610 break; 2611 } 2612 else if (end_of_sentence_p ()) 2613 /* CHARACTER is newline, and filling is enabled. */ 2614 { 2615 insert (' '); 2616 output_column++; 2617 last_inserted_character = character; 2618 } 2619 2620 if (last_char_was_newline) 2621 { 2622 if (html) 2623 last_char_was_newline++; 2624 close_paragraph (); 2625 pending_indent = 0; 2626 } 2627 else 2628 { 2629 last_char_was_newline = 1; 2630 if (html) 2631 insert ('\n'); 2632 else 2633 insert (' '); 2634 output_column++; 2635 } 2636 break; 2637 2638 default: /* not at newline */ 2639 { 2640 int len = get_char_len (character); 2641 int suppress_insert = 0; 2642 2643 if ((character == ' ') && (last_char_was_newline)) 2644 { 2645 if (!paragraph_is_open) 2646 { 2647 pending_indent++; 2648 return; 2649 } 2650 } 2651 2652 /* This is sad, but it seems desirable to not force any 2653 particular order on the front matter commands. This way, 2654 the document can do @settitle, @documentlanguage, etc, in 2655 any order and with any omissions, and we'll still output 2656 the html <head> `just in time'. */ 2657 if ((executing_macro || !executing_string) 2658 && !only_macro_expansion 2659 && html && !html_output_head_p && !defining_copying ()) 2660 html_output_head (); 2661 2662 if (!paragraph_is_open) 2663 { 2664 start_paragraph (); 2665 /* If the paragraph is supposed to be indented a certain 2666 way, then discard all of the pending whitespace. 2667 Otherwise, we let the whitespace stay. */ 2668 if (!paragraph_start_indent) 2669 indent (pending_indent); 2670 pending_indent = 0; 2671 2672 /* This check for in_html_block_level_elt prevents <p> from being 2673 inserted when we already have html markup starting a paragraph, 2674 as with <ul> and <h1> and the like. */ 2675 if (html && !in_html_block_level_elt) 2676 { 2677 if ((in_menu || in_detailmenu) && in_menu_item) 2678 { 2679 insert_string ("</li></ul>\n"); 2680 in_menu_item = 0; 2681 } 2682 insert_string ("<p>"); 2683 in_paragraph = 1; 2684 adjust_braces_following (0, 3); /* adjust for <p> */ 2685 } 2686 } 2687 2688 output_column += len; 2689 if (output_column > fill_column) 2690 { 2691 if (filling_enabled && !html) 2692 { 2693 int temp = output_paragraph_offset; 2694 while (--temp > 0 && output_paragraph[temp] != '\n') 2695 { 2696 /* If we have found a space, we have the place to break 2697 the line. */ 2698 if (output_paragraph[temp] == ' ') 2699 { 2700 /* Remove trailing whitespace from output. */ 2701 while (temp && whitespace (output_paragraph[temp - 1])) 2702 temp--; 2703 2704 /* If we went back all the way to the newline of the 2705 preceding line, it probably means that the word we 2706 are adding is itself wider than the space that the 2707 indentation and the fill_column let us use. In 2708 that case, do NOT insert another newline, since it 2709 won't help. Just indent to current_indent and 2710 leave it alone, since that's the most we can do. */ 2711 if (temp && output_paragraph[temp - 1] != '\n') 2712 output_paragraph[temp++] = '\n'; 2713 2714 /* We have correctly broken the line where we want 2715 to. What we don't want is spaces following where 2716 we have decided to break the line. We get rid of 2717 them. */ 2718 { 2719 int t1 = temp; 2720 2721 for (;; t1++) 2722 { 2723 if (t1 == output_paragraph_offset) 2724 { 2725 if (whitespace (character)) 2726 suppress_insert = 1; 2727 break; 2728 } 2729 if (!whitespace (output_paragraph[t1])) 2730 break; 2731 } 2732 2733 if (t1 != temp) 2734 { 2735 adjust_braces_following (temp, (- (t1 - temp))); 2736 memmove (&output_paragraph[temp], 2737 &output_paragraph[t1], 2738 output_paragraph_offset - t1); 2739 output_paragraph_offset -= (t1 - temp); 2740 } 2741 } 2742 2743 /* Filled, but now indent if that is right. */ 2744 if (indented_fill && current_indent > 0) 2745 { 2746 int buffer_len = ((output_paragraph_offset - temp) 2747 + current_indent); 2748 char *temp_buffer = xmalloc (buffer_len); 2749 int indentation = 0; 2750 2751 /* We have to shift any markers that are in 2752 front of the wrap point. */ 2753 adjust_braces_following (temp, current_indent); 2754 2755 while (current_indent > 0 && 2756 indentation != current_indent) 2757 temp_buffer[indentation++] = ' '; 2758 2759 memcpy ((char *) &temp_buffer[current_indent], 2760 (char *) &output_paragraph[temp], 2761 buffer_len - current_indent); 2762 2763 if (output_paragraph_offset + buffer_len 2764 >= paragraph_buffer_len) 2765 { 2766 unsigned char *tt = xrealloc 2767 (output_paragraph, 2768 (paragraph_buffer_len += buffer_len)); 2769 output_paragraph = tt; 2770 } 2771 memcpy ((char *) &output_paragraph[temp], 2772 temp_buffer, buffer_len); 2773 output_paragraph_offset += current_indent; 2774 free (temp_buffer); 2775 } 2776 output_column = 0; 2777 while (temp < output_paragraph_offset) 2778 output_column += 2779 get_char_len (output_paragraph[temp++]); 2780 output_column += len; 2781 break; 2782 } 2783 } 2784 } 2785 } 2786 2787 if (!suppress_insert) 2788 { 2789 insert (character); 2790 last_inserted_character = character; 2791 } 2792 last_char_was_newline = 0; 2793 line_already_broken = 0; 2794 } 2795 } 2796 } 2797 2798 /* Add a character and store its position in meta_char_pos. */ 2799 void 2800 add_meta_char (int character) 2801 { 2802 meta_char_pos = output_paragraph_offset; 2803 add_char (character); 2804 } 2805 2806 /* Insert CHARACTER into `output_paragraph'. */ 2807 void 2808 insert (int character) 2809 { 2810 /* We don't want to strip trailing whitespace in multitables. Otherwise 2811 horizontal separators confuse the font locking in Info mode in Emacs, 2812 because it looks like a @subsection. Adding a trailing space to those 2813 lines fixes it. */ 2814 if (character == '\n' && !html && !xml && !multitable_active) 2815 { 2816 while (output_paragraph_offset 2817 && whitespace (output_paragraph[output_paragraph_offset-1])) 2818 output_paragraph_offset--; 2819 } 2820 2821 output_paragraph[output_paragraph_offset++] = character; 2822 if (output_paragraph_offset == paragraph_buffer_len) 2823 { 2824 output_paragraph = 2825 xrealloc (output_paragraph, (paragraph_buffer_len += 100)); 2826 } 2827 } 2828 2829 /* Insert the null-terminated string STRING into `output_paragraph'. */ 2830 void 2831 insert_string (const char *string) 2832 { 2833 while (*string) 2834 insert (*string++); 2835 } 2836 2837 2838 /* Sentences might have these characters after the period (or whatever). */ 2839 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \ 2840 || (c) == ']') 2841 2842 /* Return true if at an end-of-sentence character, possibly followed by 2843 post-sentence punctuation to ignore. */ 2844 static int 2845 end_of_sentence_p (void) 2846 { 2847 int loc = output_paragraph_offset - 1; 2848 2849 /* If nothing has been output, don't check output_paragraph[-1]. */ 2850 if (loc < 0) 2851 return 0; 2852 2853 /* A post-sentence character that is at meta_char_pos is not really 2854 a post-sentence character; it was produced by a markup such as 2855 @samp. We don't want the period inside @samp to be treated as a 2856 sentence ender. */ 2857 while (loc > 0 2858 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc])) 2859 loc--; 2860 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]); 2861 } 2862 2863 2864 /* Remove upto COUNT characters of whitespace from the 2865 the current output line. If COUNT is less than zero, 2866 then remove until none left. */ 2867 void 2868 kill_self_indent (int count) 2869 { 2870 /* Handle infinite case first. */ 2871 if (count < 0) 2872 { 2873 output_column = 0; 2874 while (output_paragraph_offset) 2875 { 2876 if (whitespace (output_paragraph[output_paragraph_offset - 1])) 2877 output_paragraph_offset--; 2878 else 2879 break; 2880 } 2881 } 2882 else 2883 { 2884 while (output_paragraph_offset && count--) 2885 if (whitespace (output_paragraph[output_paragraph_offset - 1])) 2886 output_paragraph_offset--; 2887 else 2888 break; 2889 } 2890 } 2891 2892 /* Nonzero means do not honor calls to flush_output (). */ 2893 static int flushing_ignored = 0; 2894 2895 /* Prevent calls to flush_output () from having any effect. */ 2896 void 2897 inhibit_output_flushing (void) 2898 { 2899 flushing_ignored++; 2900 } 2901 2902 /* Allow calls to flush_output () to write the paragraph data. */ 2903 void 2904 uninhibit_output_flushing (void) 2905 { 2906 flushing_ignored--; 2907 } 2908 2909 void 2910 flush_output (void) 2911 { 2912 int i; 2913 2914 if (!output_paragraph_offset || flushing_ignored) 2915 return; 2916 2917 for (i = 0; i < output_paragraph_offset; i++) 2918 { 2919 if (output_paragraph[i] == '\n') 2920 { 2921 output_line_number++; 2922 node_line_number++; 2923 } 2924 2925 /* If we turned on the 8th bit for a space inside @w, turn it 2926 back off for output. This might be problematic, since the 2927 0x80 character may be used in 8-bit character sets. Sigh. 2928 In any case, don't do this for HTML, since the nbsp character 2929 is valid input and must be passed along to the browser. */ 2930 if (!html && (output_paragraph[i] & meta_character_bit)) 2931 { 2932 int temp = UNMETA (output_paragraph[i]); 2933 if (temp == ' ') 2934 output_paragraph[i] &= 0x7f; 2935 } 2936 } 2937 2938 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream); 2939 2940 output_position += output_paragraph_offset; 2941 output_paragraph_offset = 0; 2942 meta_char_pos = 0; 2943 } 2944 2945 /* How to close a paragraph controlling the number of lines between 2946 this one and the last one. */ 2947 2948 /* Paragraph spacing is controlled by this variable. It is the number of 2949 blank lines that you wish to appear between paragraphs. A value of 2950 1 creates a single blank line between paragraphs. */ 2951 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING; 2952 2953 static void 2954 close_paragraph_with_lines (int lines) 2955 { 2956 int old_spacing = paragraph_spacing; 2957 paragraph_spacing = lines; 2958 close_paragraph (); 2959 paragraph_spacing = old_spacing; 2960 } 2961 2962 /* Close the current paragraph, leaving no blank lines between them. */ 2963 void 2964 close_single_paragraph (void) 2965 { 2966 close_paragraph_with_lines (0); 2967 } 2968 2969 /* Close a paragraph after an insertion has ended. */ 2970 void 2971 close_insertion_paragraph (void) 2972 { 2973 if (!insertion_paragraph_closed) 2974 { 2975 /* Close the current paragraph, breaking the line. */ 2976 close_single_paragraph (); 2977 2978 /* Start a new paragraph, with the correct indentation for the now 2979 current insertion level (one above the one that we are ending). */ 2980 start_paragraph (); 2981 2982 /* Tell `close_paragraph' that the previous line has already been 2983 broken, so it should insert one less newline. */ 2984 line_already_broken = 1; 2985 2986 /* Tell functions such as `add_char' we've already found a newline. */ 2987 ignore_blank_line (); 2988 } 2989 else 2990 { 2991 /* If the insertion paragraph is closed already, then we are seeing 2992 two `@end' commands in a row. Note that the first one we saw was 2993 handled in the first part of this if-then-else clause, and at that 2994 time `start_paragraph' was called, partially to handle the proper 2995 indentation of the current line. However, the indentation level 2996 may have just changed again, so we may have to outdent the current 2997 line to the new indentation level. */ 2998 if (current_indent < output_column) 2999 kill_self_indent (output_column - current_indent); 3000 } 3001 3002 insertion_paragraph_closed = 1; 3003 } 3004 3005 /* Close the currently open paragraph. */ 3006 void 3007 close_paragraph (void) 3008 { 3009 int i; 3010 3011 /* We don't need these newlines in XML and Docbook outputs for 3012 paragraph seperation. We have <para> element for that. */ 3013 if (xml) 3014 return; 3015 3016 /* The insertion paragraph is no longer closed. */ 3017 insertion_paragraph_closed = 0; 3018 3019 if (paragraph_is_open && !must_start_paragraph) 3020 { 3021 int tindex = output_paragraph_offset; 3022 3023 /* Back up to last non-newline/space character, forcing all such 3024 subsequent characters to be newlines. This isn't strictly 3025 necessary, but a couple of functions use the presence of a newline 3026 to make decisions. */ 3027 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex) 3028 { 3029 int c = output_paragraph[tindex]; 3030 3031 if (c == ' '|| c == '\n') 3032 output_paragraph[tindex] = '\n'; 3033 else 3034 break; 3035 } 3036 3037 /* All trailing whitespace is ignored. */ 3038 output_paragraph_offset = ++tindex; 3039 3040 /* Break the line if that is appropriate. */ 3041 if (paragraph_spacing >= 0) 3042 insert ('\n'); 3043 3044 /* Add as many blank lines as is specified in `paragraph_spacing'. */ 3045 if (!force_flush_right) 3046 { 3047 for (i = 0; i < (paragraph_spacing - line_already_broken); i++) 3048 { 3049 insert ('\n'); 3050 /* Don't need anything extra for HTML in usual case of no 3051 extra paragraph spacing. */ 3052 if (html && i > 0) 3053 insert_string ("<br>"); 3054 } 3055 } 3056 3057 /* If we are doing flush right indentation, then do it now 3058 on the paragraph (really a single line). */ 3059 if (force_flush_right) 3060 do_flush_right_indentation (); 3061 3062 flush_output (); 3063 paragraph_is_open = 0; 3064 no_indent = 0; 3065 output_column = 0; 3066 } 3067 3068 ignore_blank_line (); 3069 } 3070 3071 /* Make the last line just read look as if it were only a newline. */ 3072 void 3073 ignore_blank_line (void) 3074 { 3075 last_inserted_character = '\n'; 3076 last_char_was_newline = 1; 3077 } 3078 3079 /* Align the end of the text in output_paragraph with fill_column. */ 3080 static void 3081 do_flush_right_indentation (void) 3082 { 3083 char *temp; 3084 int temp_len; 3085 3086 kill_self_indent (-1); 3087 3088 if (output_paragraph[0] != '\n') 3089 { 3090 output_paragraph[output_paragraph_offset] = 0; 3091 3092 if (output_paragraph_offset < fill_column) 3093 { 3094 int i; 3095 3096 if (fill_column >= paragraph_buffer_len) 3097 output_paragraph = 3098 xrealloc (output_paragraph, 3099 (paragraph_buffer_len += fill_column)); 3100 3101 temp_len = strlen ((char *)output_paragraph); 3102 temp = xmalloc (temp_len + 1); 3103 memcpy (temp, (char *)output_paragraph, temp_len); 3104 3105 for (i = 0; i < fill_column - output_paragraph_offset; i++) 3106 output_paragraph[i] = ' '; 3107 3108 memcpy ((char *)output_paragraph + i, temp, temp_len); 3109 free (temp); 3110 output_paragraph_offset = fill_column; 3111 adjust_braces_following (0, i); 3112 } 3113 } 3114 } 3115 3116 /* Begin a new paragraph. */ 3117 void 3118 start_paragraph (void) 3119 { 3120 /* First close existing one. */ 3121 if (paragraph_is_open) 3122 close_paragraph (); 3123 3124 /* In either case, the insertion paragraph is no longer closed. */ 3125 insertion_paragraph_closed = 0; 3126 3127 /* However, the paragraph is open! */ 3128 paragraph_is_open = 1; 3129 3130 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph () 3131 had to be called before we would allow any other paragraph operations 3132 to have an effect. */ 3133 if (!must_start_paragraph) 3134 { 3135 int amount_to_indent = 0; 3136 3137 /* If doing indentation, then insert the appropriate amount. */ 3138 if (!no_indent) 3139 { 3140 if (inhibit_paragraph_indentation) 3141 { 3142 amount_to_indent = current_indent; 3143 if (inhibit_paragraph_indentation < 0) 3144 inhibit_paragraph_indentation++; 3145 } 3146 else if (paragraph_start_indent < 0) 3147 amount_to_indent = current_indent; 3148 else 3149 amount_to_indent = current_indent + paragraph_start_indent; 3150 3151 if (amount_to_indent >= output_column) 3152 { 3153 amount_to_indent -= output_column; 3154 indent (amount_to_indent); 3155 output_column += amount_to_indent; 3156 } 3157 } 3158 } 3159 else 3160 must_start_paragraph = 0; 3161 } 3162 3163 /* Insert the indentation specified by AMOUNT. */ 3164 void 3165 indent (int amount) 3166 { 3167 /* For every START_POS saved within the brace stack which will be affected 3168 by this indentation, bump that start pos forward. */ 3169 adjust_braces_following (output_paragraph_offset, amount); 3170 3171 while (--amount >= 0) 3172 insert (' '); 3173 } 3174 3175 /* Search forward for STRING in input_text. 3176 FROM says where where to start. */ 3177 int 3178 search_forward (char *string, int from) 3179 { 3180 int len = strlen (string); 3181 3182 while (from < input_text_length) 3183 { 3184 if (strncmp (input_text + from, string, len) == 0) 3185 return from; 3186 from++; 3187 } 3188 return -1; 3189 } 3190 3191 /* search_forward until n characters. */ 3192 int 3193 search_forward_until_pos (char *string, int from, int end_pos) 3194 { 3195 int save_input_text_length = input_text_length; 3196 input_text_length = end_pos; 3197 3198 from = search_forward (string, from); 3199 3200 input_text_length = save_input_text_length; 3201 3202 return from; 3203 } 3204 3205 /* Return next non-whitespace and non-cr character. */ 3206 int 3207 next_nonwhitespace_character (void) 3208 { 3209 /* First check the current input_text. Start from the next char because 3210 we already have input_text[input_text_offset] in ``current''. */ 3211 int pos = input_text_offset + 1; 3212 3213 while (pos < input_text_length) 3214 { 3215 if (!cr_or_whitespace(input_text[pos])) 3216 return input_text[pos]; 3217 pos++; 3218 } 3219 3220 { /* Can't find a valid character, so go through filestack 3221 in case we are doing @include or expanding a macro. */ 3222 FSTACK *tos = filestack; 3223 3224 while (tos) 3225 { 3226 int tmp_input_text_length = filestack->size; 3227 int tmp_input_text_offset = filestack->offset; 3228 char *tmp_input_text = filestack->text; 3229 3230 while (tmp_input_text_offset < tmp_input_text_length) 3231 { 3232 if (!cr_or_whitespace(tmp_input_text[tmp_input_text_offset])) 3233 return tmp_input_text[tmp_input_text_offset]; 3234 tmp_input_text_offset++; 3235 } 3236 3237 tos = tos->next; 3238 } 3239 } 3240 3241 return -1; 3242 } 3243 3244 /* An external image is a reference, kind of. The parsing is (not 3245 coincidentally) similar, anyway. */ 3246 void 3247 cm_image (int arg) 3248 { 3249 char *name_arg, *w_arg, *h_arg, *alt_arg, *ext_arg; 3250 3251 if (arg == END) 3252 return; 3253 3254 name_arg = get_xref_token (1); /* expands all macros in image */ 3255 w_arg = get_xref_token (0); 3256 h_arg = get_xref_token (0); 3257 alt_arg = get_xref_token (1); /* expands all macros in alt text */ 3258 ext_arg = get_xref_token (0); 3259 3260 if (*name_arg) 3261 { 3262 struct stat file_info; 3263 char *pathname = NULL; 3264 char *fullname = xmalloc (strlen (name_arg) 3265 + (ext_arg && *ext_arg ? strlen (ext_arg) + 1: 4) + 1); 3266 3267 if (ext_arg && *ext_arg) 3268 { 3269 sprintf (fullname, "%s%s", name_arg, ext_arg); 3270 if (access (fullname, R_OK) != 0) 3271 pathname = get_file_info_in_path (fullname, include_files_path, 3272 &file_info); 3273 3274 if (pathname == NULL) 3275 { 3276 /* Backwards compatibility (4.6 <= version < 4.7): 3277 try prefixing @image's EXTENSION parameter with a period. */ 3278 sprintf (fullname, "%s.%s", name_arg, ext_arg); 3279 if (access (fullname, R_OK) != 0) 3280 pathname = get_file_info_in_path (fullname, include_files_path, 3281 &file_info); 3282 } 3283 } 3284 else 3285 { 3286 sprintf (fullname, "%s.png", name_arg); 3287 if (access (fullname, R_OK) != 0) { 3288 pathname = get_file_info_in_path (fullname, 3289 include_files_path, &file_info); 3290 if (pathname == NULL) { 3291 sprintf (fullname, "%s.jpg", name_arg); 3292 if (access (fullname, R_OK) != 0) { 3293 sprintf (fullname, "%s.gif", name_arg); 3294 if (access (fullname, R_OK) != 0) { 3295 pathname = get_file_info_in_path (fullname, 3296 include_files_path, &file_info); 3297 } 3298 } 3299 } 3300 } 3301 } 3302 3303 if (html) 3304 { 3305 int image_in_div = 0; 3306 3307 if (pathname == NULL && access (fullname, R_OK) != 0) 3308 { 3309 line_error(_("@image file `%s' (for HTML) not readable: %s"), 3310 fullname, strerror (errno)); 3311 return; 3312 } 3313 if (pathname != NULL && access (pathname, R_OK) != 0) 3314 { 3315 line_error (_("No such file `%s'"), 3316 fullname); 3317 return; 3318 } 3319 3320 if (!paragraph_is_open) 3321 { 3322 add_html_block_elt ("<div class=\"block-image\">"); 3323 image_in_div = 1; 3324 } 3325 3326 add_html_elt ("<img src="); 3327 add_word_args ("\"%s\"", fullname); 3328 add_html_elt (" alt="); 3329 add_word_args ("\"%s\">", 3330 escape_string (*alt_arg ? text_expansion (alt_arg) : fullname)); 3331 3332 if (image_in_div) 3333 add_html_block_elt ("</div>"); 3334 } 3335 else if (xml && docbook) 3336 xml_insert_docbook_image (name_arg); 3337 else if (xml) 3338 { 3339 extern int xml_in_para; 3340 extern int xml_no_para; 3341 int elt = xml_in_para ? INLINEIMAGE : IMAGE; 3342 3343 if (!xml_in_para) 3344 xml_no_para++; 3345 3346 xml_insert_element_with_attribute (elt, 3347 START, "width=\"%s\" height=\"%s\" name=\"%s\" extension=\"%s\"", 3348 w_arg, h_arg, name_arg, ext_arg); 3349 xml_insert_element (IMAGEALTTEXT, START); 3350 execute_string ("%s", alt_arg); 3351 xml_insert_element (IMAGEALTTEXT, END); 3352 xml_insert_element (elt, END); 3353 3354 if (!xml_in_para) 3355 xml_no_para--; 3356 } 3357 else 3358 { /* Try to open foo.EXT or foo.txt. */ 3359 FILE *image_file; 3360 char *txtpath = NULL; 3361 char *txtname = xmalloc (strlen (name_arg) 3362 + (ext_arg && *ext_arg 3363 ? strlen (ext_arg) : 4) + 1); 3364 strcpy (txtname, name_arg); 3365 strcat (txtname, ".txt"); 3366 image_file = fopen (txtname, "r"); 3367 if (image_file == NULL) 3368 { 3369 txtpath = get_file_info_in_path (txtname, 3370 include_files_path, &file_info); 3371 if (txtpath != NULL) 3372 image_file = fopen (txtpath, "r"); 3373 } 3374 3375 if (image_file != NULL 3376 || access (fullname, R_OK) == 0 3377 || (pathname != NULL && access (pathname, R_OK) == 0)) 3378 { 3379 int ch; 3380 int save_inhibit_indentation = inhibit_paragraph_indentation; 3381 int save_filling_enabled = filling_enabled; 3382 int image_in_brackets = paragraph_is_open; 3383 3384 /* Write magic ^@^H[image ...^@^H] cookie in the info file, if 3385 there's an accompanying bitmap. Otherwise just include the 3386 text image. In the plaintext output, always include the text 3387 image without the magic cookie. */ 3388 int use_magic_cookie = !no_headers 3389 && access (fullname, R_OK) == 0 && !STREQ (fullname, txtname); 3390 3391 inhibit_paragraph_indentation = 1; 3392 filling_enabled = 0; 3393 last_char_was_newline = 0; 3394 3395 if (use_magic_cookie) 3396 { 3397 add_char ('\0'); 3398 add_word ("\010[image"); 3399 3400 if (access (fullname, R_OK) == 0 3401 || (pathname != NULL && access (pathname, R_OK) == 0)) 3402 add_word_args (" src=\"%s\"", fullname); 3403 3404 if (*alt_arg) 3405 add_word_args (" alt=\"%s\"", alt_arg); 3406 } 3407 3408 if (image_file != NULL) 3409 { 3410 if (use_magic_cookie) 3411 add_word (" text=\""); 3412 3413 if (image_in_brackets) 3414 add_char ('['); 3415 3416 /* Maybe we need to remove the final newline if the image 3417 file is only one line to allow in-line images. On the 3418 other hand, they could just make the file without a 3419 final newline. */ 3420 while ((ch = getc (image_file)) != EOF) 3421 { 3422 if (use_magic_cookie && (ch == '"' || ch == '\\')) 3423 add_char ('\\'); 3424 add_char (ch); 3425 } 3426 3427 if (image_in_brackets) 3428 add_char (']'); 3429 3430 if (use_magic_cookie) 3431 add_char ('"'); 3432 3433 if (fclose (image_file) != 0) 3434 perror (txtname); 3435 } 3436 3437 if (use_magic_cookie) 3438 { 3439 add_char ('\0'); 3440 add_word ("\010]"); 3441 } 3442 3443 inhibit_paragraph_indentation = save_inhibit_indentation; 3444 filling_enabled = save_filling_enabled; 3445 } 3446 else 3447 warning (_("@image file `%s' (for text) unreadable: %s"), 3448 txtname, strerror (errno)); 3449 } 3450 3451 free (fullname); 3452 if (pathname) 3453 free (pathname); 3454 } 3455 else 3456 line_error (_("@image missing filename argument")); 3457 3458 if (name_arg) 3459 free (name_arg); 3460 if (w_arg) 3461 free (w_arg); 3462 if (h_arg) 3463 free (h_arg); 3464 if (alt_arg) 3465 free (alt_arg); 3466 if (ext_arg) 3467 free (ext_arg); 3468 } 3469 3470 /* Conditionals. */ 3471 3472 /* A structure which contains `defined' variables. */ 3473 typedef struct defines { 3474 struct defines *next; 3475 char *name; 3476 char *value; 3477 } DEFINE; 3478 3479 /* The linked list of `set' defines. */ 3480 DEFINE *defines = NULL; 3481 3482 /* Add NAME to the list of `set' defines. */ 3483 static void 3484 set (char *name, char *value) 3485 { 3486 DEFINE *temp; 3487 3488 for (temp = defines; temp; temp = temp->next) 3489 if (strcmp (name, temp->name) == 0) 3490 { 3491 free (temp->value); 3492 temp->value = xstrdup (value); 3493 return; 3494 } 3495 3496 temp = xmalloc (sizeof (DEFINE)); 3497 temp->next = defines; 3498 temp->name = xstrdup (name); 3499 temp->value = xstrdup (value); 3500 defines = temp; 3501 3502 if (xml && !docbook) 3503 { 3504 xml_insert_element_with_attribute (SETVALUE, START, "name=\"%s\"", name); 3505 execute_string ("%s", value); 3506 xml_insert_element (SETVALUE, END); 3507 } 3508 } 3509 3510 /* Remove NAME from the list of `set' defines. */ 3511 static void 3512 clear (char *name) 3513 { 3514 DEFINE *temp, *last; 3515 3516 last = NULL; 3517 temp = defines; 3518 3519 while (temp) 3520 { 3521 if (strcmp (temp->name, name) == 0) 3522 { 3523 if (last) 3524 last->next = temp->next; 3525 else 3526 defines = temp->next; 3527 3528 free (temp->name); 3529 free (temp->value); 3530 free (temp); 3531 break; 3532 } 3533 last = temp; 3534 temp = temp->next; 3535 } 3536 3537 if (xml && !docbook) 3538 { 3539 xml_insert_element_with_attribute (CLEARVALUE, START, "name=\"%s\"", name); 3540 xml_insert_element (CLEARVALUE, END); 3541 } 3542 } 3543 3544 /* Return the value of NAME. The return value is NULL if NAME is unset. */ 3545 static char * 3546 set_p (char *name) 3547 { 3548 DEFINE *temp; 3549 3550 for (temp = defines; temp; temp = temp->next) 3551 if (strcmp (temp->name, name) == 0) 3552 return temp->value; 3553 3554 return NULL; 3555 } 3556 3557 /* Create a variable whose name appears as the first word on this line. */ 3558 void 3559 cm_set (void) 3560 { 3561 handle_variable (SET); 3562 } 3563 3564 /* Remove a variable whose name appears as the first word on this line. */ 3565 void 3566 cm_clear (void) 3567 { 3568 handle_variable (CLEAR); 3569 } 3570 3571 void 3572 cm_ifset (void) 3573 { 3574 handle_variable (IFSET); 3575 } 3576 3577 void 3578 cm_ifclear (void) 3579 { 3580 handle_variable (IFCLEAR); 3581 } 3582 3583 /* This command takes braces, but we parse the contents specially, so we 3584 don't use the standard brace popping code. 3585 3586 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands 3587 if ARG1 and ARG2 caselessly string compare to the same string, otherwise, 3588 it produces no output. */ 3589 void 3590 cm_ifeq (void) 3591 { 3592 char **arglist; 3593 3594 arglist = get_brace_args (0); 3595 3596 if (arglist) 3597 { 3598 if (array_len (arglist) > 1) 3599 { 3600 if ((strcasecmp (arglist[0], arglist[1]) == 0) && 3601 (arglist[2])) 3602 execute_string ("%s\n", arglist[2]); 3603 } 3604 3605 free_array (arglist); 3606 } 3607 } 3608 3609 void 3610 cm_value (int arg, int start_pos, int end_pos) 3611 { 3612 static int value_level = 0, saved_meta_pos = -1; 3613 3614 /* xml_add_char() skips any content inside menus when output format is 3615 Docbook, so @value{} is no use there. Also start_pos and end_pos does not 3616 get updated, causing name to be empty string. So just return. */ 3617 if (docbook && in_menu) 3618 return; 3619 3620 /* All the text after @value{ upto the matching } will eventually 3621 disappear from output_paragraph, when this function is called 3622 with ARG == END. If the text produced until then sets 3623 meta_char_pos, we will need to restore it to the value it had 3624 before @value was seen. So we need to save the previous value 3625 of meta_char_pos here. */ 3626 if (arg == START) 3627 { 3628 /* If we are already inside some outer @value, don't overwrite 3629 the value saved in saved_meta_pos. */ 3630 if (!value_level) 3631 saved_meta_pos = meta_char_pos; 3632 value_level++; 3633 /* While the argument of @value is processed, we need to inhibit 3634 textual transformations like "--" into "-", since @set didn't 3635 do that when it grabbed the name of the variable. */ 3636 in_fixed_width_font++; 3637 } 3638 else 3639 { 3640 char *name = (char *) &output_paragraph[start_pos]; 3641 char *value; 3642 output_paragraph[end_pos] = 0; 3643 name = xstrdup (name); 3644 value = set_p (name); 3645 output_column -= end_pos - start_pos; 3646 output_paragraph_offset = start_pos; 3647 3648 /* Restore the previous value of meta_char_pos if the stuff 3649 inside this @value{} moved it. */ 3650 if (saved_meta_pos == -1) /* can't happen inside @value{} */ 3651 abort (); 3652 if (value_level == 1 3653 && meta_char_pos >= start_pos && meta_char_pos < end_pos) 3654 { 3655 meta_char_pos = saved_meta_pos; 3656 saved_meta_pos = -1; 3657 } 3658 value_level--; 3659 /* No need to decrement in_fixed_width_font, since before 3660 we are called with arg == END, the reader loop already 3661 popped the brace stack, which restored in_fixed_width_font, 3662 among other things. */ 3663 3664 if (value) 3665 { 3666 /* We need to get past the closing brace since the value may 3667 expand to a context-sensitive macro (e.g. @xref) and produce 3668 spurious warnings */ 3669 input_text_offset++; 3670 execute_string ("%s", value); 3671 input_text_offset--; 3672 } 3673 else 3674 { 3675 warning (_("undefined flag: %s"), name); 3676 add_word_args (_("{No value for `%s'}"), name); 3677 } 3678 3679 free (name); 3680 } 3681 } 3682 3683 /* Set, clear, or conditionalize based on ACTION. */ 3684 static void 3685 handle_variable (int action) 3686 { 3687 char *name; 3688 3689 get_rest_of_line (0, &name); 3690 /* If we hit the end of text in get_rest_of_line, backing up 3691 input pointer will cause the last character of the last line 3692 be pushed back onto the input, which is wrong. */ 3693 if (input_text_offset < input_text_length) 3694 backup_input_pointer (); 3695 handle_variable_internal (action, name); 3696 free (name); 3697 } 3698 3699 static void 3700 handle_variable_internal (int action, char *name) 3701 { 3702 char *temp; 3703 int delimiter, additional_text_present = 0; 3704 3705 /* Only the first word of NAME is a valid tag. */ 3706 temp = name; 3707 delimiter = 0; 3708 while (*temp && (delimiter || !whitespace (*temp))) 3709 { 3710 /* #if defined (SET_WITH_EQUAL) */ 3711 if (*temp == '"' || *temp == '\'') 3712 { 3713 if (*temp == delimiter) 3714 delimiter = 0; 3715 else 3716 delimiter = *temp; 3717 } 3718 /* #endif SET_WITH_EQUAL */ 3719 temp++; 3720 } 3721 3722 if (*temp) 3723 additional_text_present++; 3724 3725 *temp = 0; 3726 3727 if (!*name) 3728 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command); 3729 else 3730 { 3731 switch (action) 3732 { 3733 case SET: 3734 { 3735 char *value; 3736 3737 #if defined (SET_WITH_EQUAL) 3738 /* Allow a value to be saved along with a variable. The value is 3739 the text following an `=' sign in NAME, if any is present. */ 3740 3741 for (value = name; *value && *value != '='; value++); 3742 3743 if (*value) 3744 *value++ = 0; 3745 3746 if (*value == '"' || *value == '\'') 3747 { 3748 value++; 3749 value[strlen (value) - 1] = 0; 3750 } 3751 3752 #else /* !SET_WITH_EQUAL */ 3753 /* The VALUE of NAME is the remainder of the line sans 3754 whitespace. */ 3755 if (additional_text_present) 3756 { 3757 value = temp + 1; 3758 canon_white (value); 3759 } 3760 else 3761 value = ""; 3762 #endif /* !SET_WITH_VALUE */ 3763 3764 set (name, value); 3765 } 3766 break; 3767 3768 case CLEAR: 3769 clear (name); 3770 break; 3771 3772 case IFSET: 3773 case IFCLEAR: 3774 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set, 3775 read lines from the the file until we reach a matching 3776 "@end CONDITION". This means that we only take note of 3777 "@ifset/clear" and "@end" commands. */ 3778 { 3779 char condition[8]; 3780 int condition_len; 3781 int orig_line_number = line_number; 3782 3783 if (action == IFSET) 3784 strcpy (condition, "ifset"); 3785 else 3786 strcpy (condition, "ifclear"); 3787 3788 condition_len = strlen (condition); 3789 3790 if ((action == IFSET && !set_p (name)) 3791 || (action == IFCLEAR && set_p (name))) 3792 { 3793 int level = 0, done = 0; 3794 3795 while (!done && input_text_offset < input_text_length) 3796 { 3797 char *freeable_line, *line; 3798 3799 get_rest_of_line (0, &freeable_line); 3800 3801 for (line = freeable_line; whitespace (*line); line++); 3802 3803 if (*line == COMMAND_PREFIX && 3804 (strncmp (line + 1, condition, condition_len) == 0)) 3805 level++; 3806 else if (strncmp (line, "@end", 4) == 0) 3807 { 3808 char *cname = line + 4; 3809 char *temp; 3810 3811 while (*cname && whitespace (*cname)) 3812 cname++; 3813 temp = cname; 3814 3815 while (*temp && !whitespace (*temp)) 3816 temp++; 3817 *temp = 0; 3818 3819 if (strcmp (cname, condition) == 0) 3820 { 3821 if (!level) 3822 { 3823 done = 1; 3824 } 3825 else 3826 level--; 3827 } 3828 } 3829 free (freeable_line); 3830 } 3831 3832 if (!done) 3833 file_line_error (input_filename, orig_line_number, 3834 _("Reached eof before matching @end %s"), 3835 condition); 3836 3837 /* We found the end of a false @ifset/ifclear. If we are 3838 in a menu, back up over the newline that ends the ifset, 3839 since that newline may also begin the next menu entry. */ 3840 break; 3841 } 3842 else 3843 { 3844 if (action == IFSET) 3845 begin_insertion (ifset); 3846 else 3847 begin_insertion (ifclear); 3848 } 3849 } 3850 break; 3851 } 3852 } 3853 } 3854 3855 /* Execution of random text not in file. */ 3856 typedef struct { 3857 char *string; /* The string buffer. */ 3858 int size; /* The size of the buffer. */ 3859 int in_use; /* Nonzero means string currently in use. */ 3860 } EXECUTION_STRING; 3861 3862 static EXECUTION_STRING **execution_strings = NULL; 3863 static int execution_strings_index = 0; 3864 static int execution_strings_slots = 0; 3865 3866 static EXECUTION_STRING * 3867 get_execution_string (int initial_size) 3868 { 3869 int i = 0; 3870 EXECUTION_STRING *es = NULL; 3871 3872 if (execution_strings) 3873 { 3874 for (i = 0; i < execution_strings_index; i++) 3875 if (execution_strings[i] && (execution_strings[i]->in_use == 0)) 3876 { 3877 es = execution_strings[i]; 3878 break; 3879 } 3880 } 3881 3882 if (!es) 3883 { 3884 if (execution_strings_index + 1 >= execution_strings_slots) 3885 { 3886 execution_strings = xrealloc 3887 (execution_strings, 3888 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *)); 3889 for (; i < execution_strings_slots; i++) 3890 execution_strings[i] = NULL; 3891 } 3892 3893 execution_strings[execution_strings_index] = 3894 xmalloc (sizeof (EXECUTION_STRING)); 3895 es = execution_strings[execution_strings_index]; 3896 execution_strings_index++; 3897 3898 es->size = 0; 3899 es->string = NULL; 3900 es->in_use = 0; 3901 } 3902 3903 if (initial_size > es->size) 3904 { 3905 es->string = xrealloc (es->string, initial_size); 3906 es->size = initial_size; 3907 } 3908 return es; 3909 } 3910 3911 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's 3912 entry in the execution_strings[] array and change the .STRING and 3913 .SIZE members of that entry as appropriate. */ 3914 void 3915 maybe_update_execution_strings (char **text, unsigned int new_len) 3916 { 3917 int i = 0; 3918 3919 if (execution_strings) 3920 { 3921 for (i = 0; i < execution_strings_index; i++) 3922 if (execution_strings[i] && (execution_strings[i]->in_use == 1) && 3923 execution_strings[i]->string == *text) 3924 { 3925 /* Don't ever shrink the string storage in execution_strings[]! 3926 execute_string assumes that it is always big enough to store 3927 every possible execution_string, and will break if that's 3928 not true. So we only enlarge the string storage if the 3929 current size isn't big enough. */ 3930 if (execution_strings[i]->size < new_len) 3931 { 3932 execution_strings[i]->string = 3933 *text = xrealloc (*text, new_len + 1); 3934 execution_strings[i]->size = new_len + 1; 3935 } 3936 return; 3937 } 3938 } 3939 /* We should *never* end up here, since if we are inside 3940 execute_string, TEXT is always in execution_strings[]. */ 3941 abort (); 3942 } 3943 3944 /* FIXME: this is an arbitrary limit. */ 3945 #define EXECUTE_STRING_MAX 16*1024 3946 3947 /* Execute the string produced by formatting the ARGs with FORMAT. This 3948 is like submitting a new file with @include. */ 3949 void 3950 #if defined (VA_FPRINTF) && __STDC__ 3951 execute_string (char *format, ...) 3952 #else 3953 execute_string (format, va_alist) 3954 char *format; 3955 va_dcl 3956 #endif 3957 { 3958 EXECUTION_STRING *es; 3959 char *temp_string, *temp_input_filename; 3960 #ifdef VA_FPRINTF 3961 va_list ap; 3962 #endif 3963 int insertion_level_at_start = insertion_level; 3964 3965 es = get_execution_string (EXECUTE_STRING_MAX); 3966 temp_string = es->string; 3967 es->in_use = 1; 3968 3969 VA_START (ap, format); 3970 #ifdef VA_SPRINTF 3971 VA_SPRINTF (temp_string, format, ap); 3972 #else 3973 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8); 3974 #endif /* not VA_SPRINTF */ 3975 va_end (ap); 3976 3977 pushfile (); 3978 input_text_offset = 0; 3979 input_text = temp_string; 3980 input_text_length = strlen (temp_string); 3981 input_filename = xstrdup (input_filename); 3982 temp_input_filename = input_filename; 3983 3984 executing_string++; 3985 reader_loop (); 3986 3987 /* If insertion stack level changes during execution, that means a multiline 3988 command is used inside braces or @section ... kind of commands. */ 3989 if (insertion_level_at_start != insertion_level && !executing_macro) 3990 { 3991 line_error (_("Multiline command %c%s used improperly"), 3992 COMMAND_PREFIX, 3993 command); 3994 /* We also need to keep insertion_level intact to make sure warnings are 3995 issued for @end ... command. */ 3996 while (insertion_level > insertion_level_at_start) 3997 pop_insertion (); 3998 } 3999 4000 popfile (); 4001 executing_string--; 4002 es->in_use = 0; 4003 free (temp_input_filename); 4004 } 4005 4006 4007 /* Return what would be output for STR (in newly-malloced memory), i.e., 4008 expand Texinfo commands according to the current output format. If 4009 IMPLICIT_CODE is set, expand @code{STR}. This is generally used for 4010 short texts; filling, indentation, and html escapes are disabled. */ 4011 4012 char * 4013 expansion (char *str, int implicit_code) 4014 { 4015 return maybe_escaped_expansion (str, implicit_code, 0); 4016 } 4017 4018 4019 /* Do HTML escapes according to DO_HTML_ESCAPE. Needed in 4020 cm_printindex, q.v. */ 4021 4022 char * 4023 maybe_escaped_expansion (char *str, int implicit_code, int do_html_escape) 4024 { 4025 char *result; 4026 4027 /* Inhibit indentation and filling, so that extra newlines 4028 are not added to the expansion. (This is undesirable if 4029 we write the expanded text to macro_expansion_output_stream.) */ 4030 int saved_filling_enabled = filling_enabled; 4031 int saved_indented_fill = indented_fill; 4032 int saved_no_indent = no_indent; 4033 int saved_escape_html = escape_html; 4034 4035 filling_enabled = 0; 4036 indented_fill = 0; 4037 no_indent = 1; 4038 escape_html = do_html_escape; 4039 4040 result = full_expansion (str, implicit_code); 4041 4042 filling_enabled = saved_filling_enabled; 4043 indented_fill = saved_indented_fill; 4044 no_indent = saved_no_indent; 4045 escape_html = saved_escape_html; 4046 4047 return result; 4048 } 4049 4050 4051 /* Expand STR (or @code{STR} if IMPLICIT_CODE is nonzero). No change to 4052 any formatting parameters -- filling, indentation, html escapes, 4053 etc., are not reset. Always returned in new memory. */ 4054 4055 char * 4056 full_expansion (char *str, int implicit_code) 4057 { 4058 int length; 4059 char *result; 4060 4061 /* Inhibit any real output. */ 4062 int start = output_paragraph_offset; 4063 int saved_paragraph_is_open = paragraph_is_open; 4064 int saved_output_column = output_column; 4065 4066 /* More output state to save. */ 4067 int saved_meta_pos = meta_char_pos; 4068 int saved_last_char = last_inserted_character; 4069 int saved_last_nl = last_char_was_newline; 4070 4071 /* If we are called in the middle of processing a command, we need 4072 to dup and save the global variable `command' (which holds the 4073 name of this command), since the recursive reader loop will free 4074 it from under our feet if it finds any macros in STR. */ 4075 char *saved_command = command ? xstrdup (command) : NULL; 4076 4077 inhibit_output_flushing (); 4078 paragraph_is_open = 1; 4079 if (strlen (str) > (implicit_code 4080 ? EXECUTE_STRING_MAX - 1 - sizeof("@code{}") 4081 : EXECUTE_STRING_MAX - 1)) 4082 line_error (_("`%.40s...' is too long for expansion; not expanded"), str); 4083 else 4084 execute_string (implicit_code ? "@code{%s}" : "%s", str); 4085 uninhibit_output_flushing (); 4086 4087 /* Copy the expansion from the buffer. */ 4088 length = output_paragraph_offset - start; 4089 result = xmalloc (1 + length); 4090 memcpy (result, (char *) (output_paragraph + start), length); 4091 result[length] = 0; 4092 4093 /* Pretend it never happened. */ 4094 free_and_clear (&command); 4095 command = saved_command; 4096 4097 output_paragraph_offset = start; 4098 paragraph_is_open = saved_paragraph_is_open; 4099 output_column = saved_output_column; 4100 4101 meta_char_pos = saved_meta_pos; 4102 last_inserted_character = saved_last_char; 4103 last_char_was_newline = saved_last_nl; 4104 4105 return result; 4106 } 4107 4108 4109 /* Return text (info) expansion of STR no matter what the current output 4110 format is. */ 4111 4112 char * 4113 text_expansion (char *str) 4114 { 4115 char *ret; 4116 int save_html = html; 4117 int save_xml = xml; 4118 int save_docbook = docbook; 4119 4120 html = 0; 4121 xml = 0; 4122 docbook = 0; 4123 ret = expansion (str, 0); 4124 html = save_html; 4125 xml = save_xml; 4126 docbook = save_docbook; 4127 4128 return ret; 4129 } 4130 4131 4132 /* Set the paragraph indentation variable to the value specified in STRING. 4133 Values can be: 4134 `asis': Don't change existing indentation. 4135 `none': Remove existing indentation. 4136 NUM: Indent NUM spaces at the starts of paragraphs. 4137 If NUM is zero, we assume `none'. 4138 Returns 0 if successful, or nonzero if STRING isn't one of the above. */ 4139 int 4140 set_paragraph_indent (char *string) 4141 { 4142 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0) 4143 paragraph_start_indent = 0; 4144 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0) 4145 paragraph_start_indent = -1; 4146 else 4147 { 4148 if (sscanf (string, "%d", ¶graph_start_indent) != 1) 4149 return -1; 4150 else 4151 { 4152 if (paragraph_start_indent == 0) 4153 paragraph_start_indent = -1; 4154 } 4155 } 4156 return 0; 4157 } 4158