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