1 /* makeinfo -- convert Texinfo source into other formats.
2 $Id: makeinfo.c,v 1.123 2008/08/28 22:53:30 karl Exp $
4 Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
5 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
6 Free Software Foundation, Inc.
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 Original author of makeinfo: Brian Fox (bfox@ai.mit.edu). */
27 #define COMPILING_MAKEINFO
35 #include "insertion.h"
39 #include "sectioning.h"
43 /* You can change some of the behavior of Makeinfo by changing the
46 /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
47 appear within an @table, @ftable, or @itemize environment to have
48 standard paragraph indentation. Without this, such paragraphs have
49 no starting indentation. */
50 /* #define INDENT_PARAGRAPHS_IN_TABLE */
52 /* Define PARAGRAPH_START_INDENT to be the amount of indentation that
53 the first lines of paragraphs receive by default, where no other
54 value has been specified. Users can change this value on the command
55 line, with the --paragraph-indent option, or within the texinfo file,
56 with the @paragraphindent command. */
57 #define PARAGRAPH_START_INDENT 3
59 /* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
60 wish to appear between paragraphs. A value of 1 creates a single blank
61 line between paragraphs. Paragraphs are defined by 2 or more consecutive
62 newlines in the input file (i.e., one or more blank lines). */
63 #define DEFAULT_PARAGRAPH_SPACING 1
65 /* Global variables. */
67 /* The output file name. */
68 char *output_filename = NULL;
70 /* Name of the output file that the user elected to pass on the command line.
71 Such a name overrides any name found with the @setfilename command. */
72 char *command_output_filename = NULL;
73 static char *save_command_output_filename = NULL;
75 /* The amount of indentation to add at the starts of paragraphs.
76 0 means don't change existing indentation at paragraph starts.
77 > 0 is amount to indent new paragraphs by.
78 < 0 means indent to column zero by removing indentation if necessary.
80 This is normally zero, but some people prefer paragraph starts to be
81 somewhat more indented than paragraph bodies. A pretty value for
83 int paragraph_start_indent = PARAGRAPH_START_INDENT;
85 /* Indentation that is pending insertion. We have this for hacking lines
86 which look blank, but contain whitespace. We want to treat those as
88 int pending_indent = 0;
90 /* The index in our internal command table of the currently
94 /* A search string which is used to find the first @setfilename. */
95 char setfilename_search[] =
97 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
99 /* Values for calling handle_variable_internal (). */
105 /* Flags controlling the operation of the program. */
107 /* Default is to remove output if there were errors. */
110 /* Default is to notify users of bad choices. */
111 int print_warnings = 1;
113 /* Number of errors that we tolerate on a given fileset. */
114 int max_error_level = 100;
116 /* The actual last inserted character. Note that this may be something
117 other than NEWLINE even if last_char_was_newline is 1. */
118 int last_inserted_character = 0;
120 /* Nonzero means that a newline character has already been
121 inserted, so close_paragraph () should insert one less. */
122 int line_already_broken = 0;
124 /* When nonzero we have finished an insertion (see end_insertion ()) and we
125 want to ignore false continued paragraph closings. */
126 int insertion_paragraph_closed = 0;
128 /* Nonzero means attempt to make all of the lines have fill_column width. */
129 int do_justification = 0;
131 /* Nonzero means don't replace whitespace with in HTML mode. */
134 /* Nonzero means we are inserting a block level HTML element that must not be
135 enclosed in a <p>, such as <ul>, <ol> and <h?>. */
136 int in_html_block_level_elt = 0;
138 /* True when expanding a macro definition. */
139 static int executing_macro = 0;
141 /* True when we are inside a <li> block of a menu. */
142 static int in_menu_item = 0;
144 /* The column position of output_paragraph[0]. This is not saved and restored
145 in the multitable code because flush_output () is only called in environment
147 static int output_paragraph_start_column = 0;
149 typedef struct brace_element
151 struct brace_element *next;
152 COMMAND_FUNCTION *proc;
155 int in_fixed_width_font;
158 BRACE_ELEMENT *brace_stack = NULL;
160 static void convert_from_file (char *name);
161 static void convert_from_loaded_file (char *name);
162 static void convert_from_stream (FILE *stream, char *name);
163 static void do_flush_right_indentation (void);
164 static void handle_variable (int action);
165 static void handle_variable_internal (int action, char *name);
166 static void init_brace_stack (void);
167 static void init_internals (void);
168 static void pop_and_call_brace (void);
169 static void remember_brace (COMMAND_FUNCTION (*proc));
170 static void write_trailer (char *filename, char *trailer);
171 static int end_of_sentence_p (void);
173 void maybe_update_execution_strings (char **text, unsigned int new_len);
175 /* Error handling. */
177 /* Number of errors encountered. */
178 int errors_printed = 0;
180 /* Remember that an error has been printed. If more than
181 max_error_level have been printed, then exit the program. */
183 remember_error (void)
186 if (max_error_level && (errors_printed > max_error_level))
188 fprintf (stderr, _("Too many errors! Gave up.\n"));
190 if (errors_printed - max_error_level < 2)
196 /* Print the last error gotten from the file system. */
198 fs_error (char *filename)
205 /* Print an error message, and return false. */
207 #if defined (VA_FPRINTF) && __STDC__
208 error (const char *format, ...)
210 error (format, va_alist)
221 VA_START (ap, format);
223 VA_FPRINTF (stderr, format, ap);
225 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
226 #endif /* not VA_FPRINTF */
232 /* Just like error (), but print the input file and line number as well. */
234 #if defined (VA_FPRINTF) && __STDC__
235 file_line_error (char *infile, int lno, const char *format, ...)
237 file_line_error (infile, lno, format, va_alist)
249 fprintf (stderr, "%s:%d: ", infile, lno);
251 VA_START (ap, format);
253 VA_FPRINTF (stderr, format, ap);
255 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
256 #endif /* not VA_FPRINTF */
259 fprintf (stderr, ".\n");
262 /* Just like file_line_error (), but take the input file and the line
263 number from global variables. */
265 #if defined (VA_FPRINTF) && __STDC__
266 line_error (const char *format, ...)
268 line_error (format, va_alist)
278 fprintf (stderr, "%s:%d: ", input_filename, line_number);
280 VA_START (ap, format);
282 VA_FPRINTF (stderr, format, ap);
284 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
285 #endif /* not VA_FPRINTF */
288 fprintf (stderr, ".\n");
292 #if defined (VA_FPRINTF) && __STDC__
293 warning (const char *format, ...)
295 warning (format, va_alist)
306 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
308 VA_START (ap, format);
310 VA_FPRINTF (stderr, format, ap);
312 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
313 #endif /* not VA_FPRINTF */
316 fprintf (stderr, ".\n");
321 /* The other side of a malformed expression. */
323 misplaced_brace (void)
325 line_error (_("Misplaced %c"), '}');
330 /* Display the version info of this invocation of Makeinfo. */
332 print_version_info (void)
334 printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION);
337 /* If EXIT_VALUE is zero, print the full usage message to stdout.
338 Otherwise, just say to use --help for more info.
339 Then exit with EXIT_VALUE. */
341 usage (int exit_value)
344 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
347 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname);
351 Translate Texinfo source documentation to various other formats, by default\n\
352 Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
356 --error-limit=NUM quit after NUM errors (default %d).\n\
357 --document-language=STR locale to use in translating Texinfo keywords\n\
358 for the output document (default C).\n\
359 --force preserve output even if errors.\n\
360 --help display this help and exit.\n\
361 --no-validate suppress node cross-reference validation.\n\
362 --no-warn suppress warnings (but not errors).\n\
363 -v, --verbose explain what is being done.\n\
364 --version display version information and exit.\n"),
368 /* xgettext: no-wrap */
370 Output format selection (default is to produce Info):\n\
371 --docbook output Docbook XML rather than Info.\n\
372 --html output HTML rather than Info.\n\
373 --xml output Texinfo XML rather than Info.\n\
374 --plaintext output plain text rather than Info.\n\
378 General output options:\n\
379 -E, --macro-expand=FILE output macro-expanded source to FILE,\n\
380 ignoring any @setfilename.\n\
381 --no-headers suppress node separators, Node: lines, and menus\n\
382 from Info output (thus producing plain text)\n\
383 or from HTML (thus producing shorter output);\n\
384 also, write to standard output by default.\n\
385 --no-split suppress the splitting of Info or HTML output,\n\
386 generate only one output file.\n\
387 --number-sections output chapter and sectioning numbers.\n\
388 -o, --output=FILE output to FILE (or directory if split HTML).\n\
392 Options for Info and plain text:\n\
393 --disable-encoding do not output accented and special characters\n\
394 in Info output based on @documentencoding.\n\
395 --enable-encoding override --disable-encoding (default).\n\
396 --fill-column=NUM break Info lines at NUM characters (default %d).\n\
397 --footnote-style=STYLE output footnotes in Info according to STYLE:\n\
398 `separate' to put them in their own node;\n\
399 `end' to put them at the end of the node, in\n\
400 which they are defined (this is the default).\n\
401 --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
402 If VAL is `none', do not indent; if VAL is\n\
403 `asis', preserve existing indentation.\n\
404 --split-size=NUM split Info files at size NUM (default %d).\n"),
405 fill_column, paragraph_start_indent,
411 --css-include=FILE include FILE in HTML <style> output;\n\
412 read stdin if FILE is -.\n\
413 --css-ref=URL generate reference to a CSS file.\n\
414 --internal-links=FILE produce list of internal links in FILE.\n\
415 --transliterate-file-names\n\
416 produce file names in ASCII transliteration.\n\
420 Options for XML and Docbook:\n\
421 --output-indent=VAL indent XML elements by VAL spaces (default %d).\n\
422 If VAL is 0, ignorable whitespace is dropped.\n\
423 "), xml_indentation_increment);
427 Input file options:\n\
428 --commands-in-node-names allow @ commands in node names.\n\
429 -D VAR define the variable VAR, as with @set.\n\
430 -I DIR append DIR to the @include search path.\n\
431 -P DIR prepend DIR to the @include search path.\n\
432 -U VAR undefine the variable VAR, as with @clear.\n\
436 Conditional processing in input:\n\
437 --ifdocbook process @ifdocbook and @docbook even if\n\
438 not generating Docbook.\n\
439 --ifhtml process @ifhtml and @html even if not generating HTML.\n\
440 --ifinfo process @ifinfo even if not generating Info.\n\
441 --ifplaintext process @ifplaintext even if not generating plain text.\n\
442 --iftex process @iftex and @tex; implies --no-split.\n\
443 --ifxml process @ifxml and @xml.\n\
444 --no-ifdocbook do not process @ifdocbook and @docbook text.\n\
445 --no-ifhtml do not process @ifhtml and @html text.\n\
446 --no-ifinfo do not process @ifinfo text.\n\
447 --no-ifplaintext do not process @ifplaintext text.\n\
448 --no-iftex do not process @iftex and @tex text.\n\
449 --no-ifxml do not process @ifxml and @xml text.\n\
451 Also, for the --no-ifFORMAT options, do process @ifnotFORMAT text.\n\
455 The defaults for the @if... conditionals depend on the output format:\n\
456 if generating HTML, --ifhtml is on and the others are off;\n\
457 if generating Info, --ifinfo is on and the others are off;\n\
458 if generating plain text, --ifplaintext is on and the others are off;\n\
459 if generating XML, --ifxml is on and the others are off.\n\
464 makeinfo foo.texi write Info to foo's @setfilename\n\
465 makeinfo --html foo.texi write HTML to @setfilename\n\
466 makeinfo --xml foo.texi write Texinfo XML to @setfilename\n\
467 makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\
468 makeinfo --no-headers foo.texi write plain text to standard output\n\
470 makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
471 makeinfo --number-sections foo.texi write Info with numbered sections\n\
472 makeinfo --no-split foo.texi write one Info file however big\n\
476 Email bug reports to bug-texinfo@gnu.org,\n\
477 general questions and discussion to help-texinfo@gnu.org.\n\
478 Texinfo home page: http://www.gnu.org/software/texinfo/"));
480 } /* end of full help */
485 #define OPT_CSSREF 256
486 #define OPT_TRANSLITERATE_FILE_NAMES 257
487 #define OPT_INTERNAL_LINKS 258
489 struct option long_options[] =
491 { "commands-in-node-names", 0, &expensive_validation, 1 },
492 { "css-include", 1, 0, 'C' },
493 { "css-ref", 1, 0, OPT_CSSREF },
494 { "docbook", 0, 0, 'd' },
495 { "disable-encoding", 0, &enable_encoding, 0 },
496 { "enable-encoding", 0, &enable_encoding, 1 },
497 { "document-language", 1, 0, 'l' },
498 { "error-limit", 1, 0, 'e' },
499 { "fill-column", 1, 0, 'f' },
500 { "footnote-style", 1, 0, 's' },
501 { "force", 0, &force, 1 },
502 { "help", 0, 0, 'h' },
503 { "html", 0, 0, 'w' },
504 { "ifdocbook", 0, &process_docbook, 1 },
505 { "ifhtml", 0, &process_html, 1 },
506 { "ifinfo", 0, &process_info, 1 },
507 { "ifplaintext", 0, &process_plaintext, 1 },
508 { "iftex", 0, &process_tex, 1 },
509 { "ifxml", 0, &process_xml, 1 },
510 { "internal-links", 1, 0, OPT_INTERNAL_LINKS },
511 { "macro-expand", 1, 0, 'E' },
512 { "no-headers", 0, &no_headers, 1 },
513 { "no-ifdocbook", 0, &process_docbook, 0 },
514 { "no-ifhtml", 0, &process_html, 0 },
515 { "no-ifinfo", 0, &process_info, 0 },
516 { "no-ifplaintext", 0, &process_plaintext, 0 },
517 { "no-iftex", 0, &process_tex, 0 },
518 { "no-ifxml", 0, &process_xml, 0 },
519 { "no-number-footnotes", 0, &number_footnotes, 0 },
520 { "no-number-sections", 0, &number_sections, 0 },
521 { "no-pointer-validate", 0, &validating, 0 },
522 { "no-split", 0, &splitting, 0 },
523 { "no-validate", 0, &validating, 0 },
524 { "no-warn", 0, &print_warnings, 0 },
525 { "number-footnotes", 0, &number_footnotes, 1 },
526 { "number-sections", 0, &number_sections, 1 },
527 { "output", 1, 0, 'o' },
528 { "output-indent", 1, 0, 'i' },
529 { "paragraph-indent", 1, 0, 'p' },
530 { "plaintext", 0, 0, 't' },
531 { "reference-limit", 1, 0, 'r' },
532 { "split-size", 1, 0, 'S'},
533 { "transliterate-file-names", 0, &transliterate_file_names, 1 },
534 { "verbose", 0, &verbose_mode, 1 },
535 { "version", 0, 0, 'V' },
536 { "xml", 0, 0, 'x' },
540 /* We use handle_variable_internal for -D and -U, and it depends on
541 execute_string, which depends on input_filename, which is not defined
542 while we are handling options. :-\ So we save these defines in this
543 struct, and handle them later. */
544 typedef struct command_line_define
546 struct command_line_define *next;
549 } COMMAND_LINE_DEFINE;
551 static COMMAND_LINE_DEFINE *command_line_defines = NULL;
553 /* For each file mentioned in the command line, process it, turning
554 Texinfo commands into wonderfully formatted output text. */
556 main (int argc, char *argv[])
559 int reading_from_stdin = 0;
561 #ifdef HAVE_SETLOCALE
562 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
563 of the argument to @multicolumn. */
564 setlocale (LC_TIME, "");
565 #ifdef LC_MESSAGES /* ultrix, djgpp 2.04 */
566 setlocale (LC_MESSAGES, "");
568 setlocale (LC_CTYPE, "");
569 setlocale (LC_COLLATE, "");
573 /* Set the text message domain. */
574 bindtextdomain (PACKAGE, LOCALEDIR);
575 textdomain (PACKAGE);
578 /* If TEXINFO_OUTPUT_FORMAT envvar is set, use it to set default output.
579 Can be overridden with one of the output options. */
580 if (getenv ("TEXINFO_OUTPUT_FORMAT") != NULL)
582 if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "docbook"))
590 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "html"))
597 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "info"))
603 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "plaintext"))
610 process_plaintext = 1;
612 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "xml"))
622 _("%s: Ignoring unrecognized TEXINFO_OUTPUT_FORMAT value `%s'.\n"),
623 progname, getenv ("TEXINFO_OUTPUT_FORMAT"));
626 /* Parse argument flags from the input line. */
627 while ((c = getopt_long (argc, argv, "D:de:E:f:hI:i:o:p:P:r:s:t:U:vV:wx",
628 long_options, &ind)) != EOF)
630 if (c == 0 && long_options[ind].flag == 0)
631 c = long_options[ind].val;
635 case 'C': /* --css-include */
636 css_include = xstrdup (optarg);
640 css_ref = xstrdup (optarg);
645 /* User specified variable to set or clear. */
648 COMMAND_LINE_DEFINE *new = xmalloc (sizeof (COMMAND_LINE_DEFINE));
649 new->action = (c == 'D') ? SET : CLEAR;
650 new->define = xstrdup (optarg);
651 new->next = command_line_defines;
652 command_line_defines = new;
655 handle_variable_internal ((c == 'D' ? SET : CLEAR), optarg);
658 case 'd': /* --docbook */
666 case 'e': /* --error-limit */
667 if (sscanf (optarg, "%d", &max_error_level) != 1)
670 _("%s: %s arg must be numeric, not `%s'.\n"),
671 progname, "--error-limit", optarg);
676 case 'E': /* --macro-expand */
677 if (!macro_expansion_output_stream)
679 macro_expansion_filename = optarg;
680 macro_expansion_output_stream
681 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
682 if (!macro_expansion_output_stream)
683 error (_("%s: could not open macro expansion output `%s'"),
688 _("%s: ignoring second macro expansion output `%s'.\n"),
692 case 'f': /* --fill-column */
693 if (sscanf (optarg, "%d", &fill_column) != 1)
696 _("%s: %s arg must be numeric, not `%s'.\n"),
697 progname, "--fill-column", optarg);
702 case 'h': /* --help */
707 /* Append user-specified dir to include file path. */
708 append_to_include_path (optarg);
712 /* save the override language code */
713 document_language = xstrdup (optarg);
717 if (sscanf (optarg, "%d", &xml_indentation_increment) != 1)
720 _("%s: %s arg must be numeric, not `%s'.\n"),
721 progname, "--output-indent", optarg);
726 case OPT_INTERNAL_LINKS:
727 if (!internal_links_stream)
729 internal_links_filename = xstrdup (optarg);
730 internal_links_stream = strcmp (optarg, "-") == 0 ? stdout :
732 if (!internal_links_stream)
733 error (_("%s: could not open internal links output `%s'"),
738 _("%s: ignoring second internal links output `%s'.\n"),
742 case 'o': /* --output */
743 command_output_filename = xstrdup (optarg);
744 save_command_output_filename = command_output_filename;
747 case 'p': /* --paragraph-indent */
748 if (set_paragraph_indent (optarg) < 0)
751 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
758 /* Prepend user-specified include dir to include path. */
759 prepend_to_include_path (optarg);
762 case 'r': /* was --reference-limit; obsolete, ignore */
765 case 's': /* --footnote-style */
766 if (set_footnote_style (optarg) < 0)
769 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
773 footnote_style_preset = 1;
776 case 'S': /* --split-size */
777 if (sscanf (optarg, "%d", &split_size) != 1)
780 _("%s: %s arg must be numeric, not `%s'.\n"),
781 progname, "--split-size", optarg);
786 case 't': /* --plaintext */
792 process_plaintext = 1;
799 case 'V': /* --version */
800 print_version_info ();
802 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
803 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
804 This is free software: you are free to change and redistribute it.\n\
805 There is NO WARRANTY, to the extent permitted by law.\n"),
810 case 'w': /* --html */
817 case 'x': /* --xml */
831 if (macro_expansion_output_stream)
835 expensive_validation = 0;
839 /* Check to see if input is a file. If so, process that. */
840 if (!isatty (fileno (stdin)))
841 reading_from_stdin = 1;
844 fprintf (stderr, _("%s: missing file argument.\n"), progname);
851 /* If the user did not specify an output file, use stdout. */
852 if (!command_output_filename)
853 command_output_filename = xstrdup ("-");
855 if (html && splitting && !STREQ (command_output_filename, "-"))
856 { /* --no-headers --no-split --html indicates confusion. */
858 "%s: can't split --html output to `%s' with --no-headers.\n",
859 progname, command_output_filename);
863 /* --no-headers implies --no-split. */
867 if (process_info == -1)
868 { /* no explicit --[no-]ifinfo option, so we'll do @ifinfo
869 if we're generating info or (for compatibility) plain text. */
870 process_info = !html && !xml;
873 if (process_plaintext == -1)
874 { /* no explicit --[no-]ifplaintext option, so we'll do @ifplaintext
875 if we're generating plain text. */
876 process_plaintext = no_headers && !html && !xml;
880 print_version_info ();
882 /* Remaining arguments are file names of texinfo files.
883 Convert them, one by one. */
884 if (!reading_from_stdin)
886 while (optind != argc)
888 if (STREQ (argv[optind], "-"))
889 convert_from_stream (stdin, "stdin");
891 convert_from_file (argv[optind]);
896 convert_from_stream (stdin, "stdin");
898 xexit (errors_printed ? 2 : 0);
899 return 0; /* Avoid bogus warnings. */
902 /* Hacking tokens and strings. */
904 /* Return the next token as a string pointer. We cons the string. This
905 `token' means simply a command name. */
907 /* = is so @alias works. ^ and _ are so macros can be used in math mode
908 without a space following. Possibly we should simply allow alpha, to
909 be compatible with TeX. */
910 #define COMMAND_CHAR(c) (!cr_or_whitespace(c) \
924 /* If the first character to be read is self-delimiting, then that
925 is the command itself. */
926 character = curchar ();
927 if (self_delimiting (character))
931 if (character == '\n')
934 result = xstrdup (" ");
939 for (i = 0; ((input_text_offset != input_text_length)
940 && (character = curchar ())
941 && COMMAND_CHAR (character));
942 i++, input_text_offset++);
943 result = xmalloc (i + 1);
944 memcpy (result, &input_text[input_text_offset - i], i);
949 /* Return nonzero if CHARACTER is self-delimiting. */
951 self_delimiting (int character)
953 /* @; and @\ are not Texinfo commands, but they are listed here
954 anyway. I don't know why. --karl, 10aug96. */
955 return strchr ("~{|}`^\\@?=;:./-,*\'\" !\n\t", character) != NULL;
958 /* Clear whitespace from the front and end of string. */
960 canon_white (char *string)
970 if (!cr_or_whitespace (*p))
977 while (len && cr_or_whitespace (p[len-1]))
981 memmove (string, p, len);
986 /* Bash STRING, replacing all whitespace with just one space. */
988 fix_whitespace (char *string)
990 char *temp = xmalloc (strlen (string) + 1);
991 int string_index = 0;
995 canon_white (string);
997 while (string[string_index])
999 c = temp[temp_index++] = string[string_index++];
1001 if (c == ' ' || c == '\n' || c == '\t')
1003 temp[temp_index - 1] = ' ';
1004 while ((c = string[string_index]) && (c == ' ' ||
1010 temp[temp_index] = 0;
1011 strcpy (string, temp);
1015 /* Discard text until the desired string is found. The string is
1016 included in the discarded text. */
1018 discard_until (char *string)
1020 int temp = search_forward (string, input_text_offset);
1022 int tt = (temp < 0) ? input_text_length : temp + strlen (string);
1023 int from = input_text_offset;
1025 /* Find out what line we are on. */
1027 if (input_text[from++] == '\n')
1032 /* not found, move current position to end of string */
1033 input_text_offset = input_text_length;
1034 if (strcmp (string, "\n") != 0)
1035 { /* Give a more descriptive feedback, if we are looking for ``@end ''
1036 during macro execution. That means someone used a multiline
1037 command as an argument to, say, @section ... style commands. */
1038 char *end_block = xmalloc (8);
1039 sprintf (end_block, "\n%cend ", COMMAND_PREFIX);
1040 if (executing_string && strstr (string, end_block))
1041 line_error (_("Multiline command %c%s used improperly"),
1042 COMMAND_PREFIX, command);
1044 line_error (_("Expected `%s'"), string);
1050 /* found, move current position to after the found string */
1051 input_text_offset = temp + strlen (string);
1054 /* Read characters from the file until we are at MATCH.
1055 Place the characters read into STRING.
1056 On exit input_text_offset is after the match string.
1057 Return the offset where the string starts. */
1059 get_until (char *match, char **string)
1061 int len, current_point, x, new_point, tem;
1063 current_point = x = input_text_offset;
1064 new_point = search_forward (match, input_text_offset);
1067 new_point = input_text_length;
1068 len = new_point - current_point;
1070 /* Keep track of which line number we are at. */
1071 tem = new_point + (strlen (match) - 1);
1073 if (input_text[x++] == '\n')
1076 *string = xmalloc (len + 1);
1078 memcpy (*string, &input_text[current_point], len);
1081 /* Now leave input_text_offset in a consistent state. */
1082 input_text_offset = tem;
1084 if (input_text_offset > input_text_length)
1085 input_text_offset = input_text_length;
1090 /* Replace input_text[FROM .. TO] with its expansion. */
1092 replace_with_expansion (int from, int *to)
1095 unsigned xp_len, new_len;
1096 char *old_input = input_text;
1097 unsigned raw_len = *to - from;
1100 /* The rest of the code here moves large buffers, so let's
1101 not waste time if the input cannot possibly expand
1102 into anything. Unfortunately, we cannot avoid expansion
1103 when we see things like @code etc., even if they only
1104 asked for expansion of macros, since any Texinfo command
1105 can be potentially redefined with a macro. */
1106 if (only_macro_expansion &&
1107 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
1110 /* Get original string from input. */
1111 str = xmalloc (raw_len + 1);
1112 memcpy (str, input_text + from, raw_len);
1115 /* We are going to relocate input_text, so we had better output
1116 pending portion of input_text now, before the pointer changes. */
1117 if (macro_expansion_output_stream && !executing_string
1118 && !me_inhibit_expansion)
1119 append_to_expansion_output (from);
1122 xp = expansion (str, 0);
1123 xp_len = strlen (xp);
1126 /* Plunk the expansion into the middle of `input_text' --
1127 which is terminated by a newline, not a null. Avoid
1128 expensive move of the rest of the input if the expansion
1129 has the same length as the original string. */
1130 if (xp_len != raw_len)
1132 new_len = from + xp_len + input_text_length - *to + 1;
1133 if (executing_string)
1134 { /* If we are in execute_string, we might need to update
1135 the relevant element in the execution_strings[] array,
1136 since it could have to be relocated from under our
1137 feet. (input_text is reallocated here as well, if needed.) */
1138 maybe_update_execution_strings (&input_text, new_len);
1140 else if (new_len > input_text_length + 1)
1141 /* Don't bother to realloc if we have enough space. */
1142 input_text = xrealloc (input_text, new_len);
1144 memmove (input_text + from + xp_len,
1145 input_text + *to, input_text_length - *to + 1);
1147 *to += xp_len - raw_len;
1148 /* Since we change input_text_length here, the comparison above
1149 isn't really valid, but it seems the worst that might happen is
1150 an extra xrealloc or two, so let's not worry. */
1151 input_text_length += xp_len - raw_len;
1153 memcpy (input_text + from, xp, xp_len);
1156 /* Synchronize the macro-expansion pointers with our new input_text. */
1157 if (input_text != old_input)
1158 forget_itext (old_input);
1159 if (macro_expansion_output_stream && !executing_string)
1160 remember_itext (input_text, from);
1163 /* Read characters from the file until we are at MATCH or end of line.
1164 Place the characters read into STRING. If EXPAND is nonzero,
1165 expand the text before looking for MATCH for those cases where
1166 MATCH might be produced by some macro. */
1168 get_until_in_line (int expand, char *match, char **string)
1170 int real_bottom = input_text_length;
1171 int limit = search_forward ("\n", input_text_offset);
1173 limit = input_text_length;
1175 /* Replace input_text[input_text_offset .. limit-1] with its expansion.
1176 This allows the node names and menu entries themselves to be
1177 constructed via a macro, as in:
1179 Together: \p\ & \q\.
1182 @node @foo{A,B}, next, prev, top
1184 Otherwise, the `,' separating the macro args A and B is taken as
1185 the node argument separator, so the node name is `@foo{A'. This
1186 expansion is only necessary on the first call, since we expand the
1190 replace_with_expansion (input_text_offset, &limit);
1193 real_bottom = input_text_length;
1194 input_text_length = limit;
1195 get_until (match, string);
1196 input_text_length = real_bottom;
1200 get_rest_of_line (int expand, char **string)
1207 /* Don't expand non-macros in input, since we want them
1208 intact in the macro-expanded output. */
1209 only_macro_expansion++;
1210 get_until_in_line (1, "\n", &tem);
1211 only_macro_expansion--;
1212 *string = expansion (tem, 0);
1216 get_until_in_line (0, "\n", string);
1218 canon_white (*string);
1220 if (curchar () == '\n') /* as opposed to the end of the file... */
1223 input_text_offset++;
1228 /* Backup the input pointer to the previous character, keeping track
1229 of the current line number. */
1231 backup_input_pointer (void)
1233 if (input_text_offset)
1235 input_text_offset--;
1236 if (curchar () == '\n')
1241 /* Read characters from the file until we are at MATCH or closing brace.
1242 Place the characters read into STRING. */
1244 get_until_in_braces (char *match, char **string)
1248 int match_len = strlen (match);
1250 for (i = input_text_offset; i < input_text_length; i++)
1252 if (i < input_text_length - 1 && input_text[i] == '@')
1254 i++; /* skip commands like @, and @{ */
1257 else if (input_text[i] == '{')
1259 else if (input_text[i] == '}')
1262 /* If looking for a brace, don't stop at the interior brace,
1263 like after "baz" in "@foo{something @bar{baz} more}". */
1267 else if (input_text[i] == '\n')
1271 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1275 match_len = i - input_text_offset;
1276 temp = xmalloc (2 + match_len);
1277 memcpy (temp, input_text + input_text_offset, match_len);
1278 temp[match_len] = 0;
1279 input_text_offset = i;
1285 /* Converting a file. */
1287 /* Convert the file named by NAME. The output is saved on the file
1288 named as the argument to the @setfilename command. */
1289 static char *suffixes[] = {
1290 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1291 have "texinfo.txi" and "texinfo.tex" in the same directory, the
1292 former is used rather than the latter, due to file name truncation. */
1302 initialize_conversion (void)
1309 /* This is used for splitting the output file and for doing section
1310 headings. It was previously initialized in `init_paragraph', but its
1311 use there loses with the `init_paragraph' calls done by the
1312 multitable code; the tag indices get reset to zero. */
1313 output_position = 0;
1316 /* Reverse the chain of structures in LIST. Output the new head
1317 of the chain. You should always assign the output value of this
1318 function to something, or you will lose the chain. */
1320 reverse_list (GENERIC_LIST *list)
1323 GENERIC_LIST *prev = NULL;
1335 /* We read in multiples of 4k, simply because it is a typical pipe size
1337 #define READ_BUFFER_GROWTH (4 * 4096)
1339 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1340 source of the stream is named NAME. */
1342 convert_from_stream (FILE *stream, char *name)
1344 char *buffer = NULL;
1345 int buffer_offset = 0, buffer_size = 0;
1347 initialize_conversion ();
1349 /* Read until the end of the stream. This isn't strictly correct, since
1350 the texinfo input may end before the stream ends, but it is a quick
1351 working heuristic. */
1352 while (!feof (stream))
1356 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1358 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1360 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1368 buffer_offset += count;
1373 /* Set the globals to the new file. */
1374 input_text = buffer;
1375 input_text_length = buffer_offset;
1376 input_filename = xstrdup (name);
1377 node_filename = xstrdup (name);
1378 input_text_offset = 0;
1381 /* Not strictly necessary. This magic prevents read_token () from doing
1382 extra unnecessary work each time it is called (that is a lot of times).
1383 The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1384 input_text[input_text_length] = '\n';
1386 convert_from_loaded_file (name);
1390 convert_from_file (char *name)
1393 char *filename = xmalloc (strlen (name) + 50);
1395 /* Prepend NAME's directory to the search path, so relative links work. */
1396 prepend_to_include_path (pathname_part (name));
1398 initialize_conversion ();
1400 /* Try to load the file specified by NAME, concatenated with our
1401 various suffixes. Prefer files like `makeinfo.texi' to `makeinfo'. */
1402 for (i = 0; suffixes[i]; i++)
1404 strcpy (filename, name);
1405 strcat (filename, suffixes[i]);
1407 if (find_and_load (filename, 1))
1418 /* `find_and_load' (when successful) clobbers this global with new
1419 memory. We're about to reset it, so may as well free first. */
1420 free (input_filename);
1422 /* Set the current filename. */
1423 input_filename = filename;
1425 /* Do the main conversion. */
1426 convert_from_loaded_file (name);
1428 /* Pop the prepended path, so multiple filenames in the
1429 command line do not screw each others include paths. */
1430 pop_path_from_include_path ();
1434 create_html_directory (char *dir, int can_remove_file)
1438 /* Already exists. */
1439 if (stat (dir, &st) == 0)
1441 /* And it's a directory, so silently reuse it. */
1442 if (S_ISDIR (st.st_mode))
1444 /* Not a directory, so move it out of the way if we are allowed. */
1445 else if (can_remove_file)
1447 if (unlink (dir) != 0)
1454 if (mkdir (dir, 0777) == 0)
1461 /* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
1462 "/foo/bar/baz/baz.html". This routine is called only if html && splitting.
1464 Split html output goes into the subdirectory of the toplevel
1465 filename, without extension. For example:
1466 @setfilename foo.info
1467 produces output in files foo/index.html, foo/second-node.html, ...
1469 But if the user said -o foo.whatever on the cmd line, then use
1470 foo.whatever unchanged. */
1473 insert_toplevel_subdirectory (char *output_filename)
1475 static const char index_name[] = "index.html";
1476 char *dir, *subdir, *base, *basename, *p;
1478 const int index_len = sizeof (index_name) - 1;
1480 strcpy (buf, output_filename);
1481 dir = pathname_part (buf); /* directory of output_filename */
1482 base = filename_part (buf); /* strips suffix, too */
1483 basename = xstrdup (base); /* remember real @setfilename name */
1484 p = dir + strlen (dir) - 1;
1485 if (p > dir && IS_SLASH (*p))
1487 p = strrchr (base, '.');
1491 /* Split html output goes into subdirectory of toplevel name. */
1492 if (save_command_output_filename
1493 && STREQ (output_filename, save_command_output_filename))
1494 subdir = basename; /* from user, use unchanged */
1496 subdir = base; /* implicit, omit suffix */
1498 free (output_filename);
1499 output_filename = xmalloc (strlen (dir) + 1
1500 + strlen (basename) + 1
1503 strcpy (output_filename, dir);
1505 strcat (output_filename, "/");
1506 strcat (output_filename, subdir);
1508 /* First try, do not remove existing file. */
1509 if (!create_html_directory (output_filename, 0))
1511 /* That failed, try subdir name with .html.
1512 Remove it if it exists. */
1513 strcpy (output_filename, dir);
1515 strcat (output_filename, "/");
1516 strcat (output_filename, basename);
1518 if (!create_html_directory (output_filename, 1))
1520 /* Last try failed too :-\ */
1521 line_error (_("Can't create directory `%s': %s"),
1522 output_filename, strerror (errno));
1527 strcat (output_filename, "/");
1528 strcat (output_filename, index_name);
1529 return output_filename;
1532 /* FIXME: this is way too hairy */
1534 convert_from_loaded_file (char *name)
1536 char *real_output_filename = NULL;
1538 remember_itext (input_text, 0);
1540 input_text_offset = 0;
1542 /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1544 if (looking_at ("\\input"))
1545 discard_until ("\n");
1547 /* Search this file looking for the special string which starts conversion.
1548 Once found, we may truly begin. */
1549 while (input_text_offset >= 0)
1552 search_forward (setfilename_search, input_text_offset);
1554 if (input_text_offset == 0
1555 || (input_text_offset > 0
1556 && input_text[input_text_offset -1] == '\n'))
1558 else if (input_text_offset > 0)
1559 input_text_offset++;
1562 if (input_text_offset < 0)
1564 if (!command_output_filename)
1566 #if defined (REQUIRE_SETFILENAME)
1567 error (_("No `%s' found in `%s'"), setfilename_search, name);
1570 command_output_filename = output_name_from_input_name (name);
1571 #endif /* !REQUIRE_SETFILENAME */
1575 int i, end_of_first_line;
1577 /* Find the end of the first line in the file. */
1578 for (i = 0; i < input_text_length - 1; i++)
1579 if (input_text[i] == '\n')
1582 end_of_first_line = i + 1;
1584 for (i = 0; i < end_of_first_line; i++)
1586 if ((input_text[i] == '\\') &&
1587 (strncmp (input_text + i + 1, "input", 5) == 0))
1589 input_text_offset = i;
1596 input_text_offset += strlen (setfilename_search);
1598 if (!command_output_filename)
1600 get_until ("\n", &output_filename); /* read rest of line */
1602 { /* Change any extension to .html or .xml. */
1603 char *html_name, *directory_part, *basename_part, *temp;
1605 canon_white (output_filename);
1606 directory_part = pathname_part (output_filename);
1608 basename_part = filename_part (output_filename);
1610 /* Zap any existing extension. */
1611 temp = strrchr (basename_part, '.');
1615 /* Construct new filename. */
1616 html_name = xmalloc (strlen (directory_part)
1617 + strlen (basename_part) + 6);
1618 strcpy (html_name, directory_part);
1619 strcat (html_name, basename_part);
1620 strcat (html_name, html ? ".html" : ".xml");
1622 /* Replace name from @setfilename with the html name. */
1623 free (output_filename);
1624 output_filename = html_name;
1629 if (input_text_offset != -1)
1630 discard_until ("\n");
1632 input_text_offset = 0;
1634 real_output_filename = output_filename = command_output_filename;
1635 command_output_filename = NULL; /* for included files or whatever */
1638 canon_white (output_filename);
1639 toplevel_output_filename = xstrdup (output_filename);
1641 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1643 if (macro_expansion_filename
1644 && strcmp (macro_expansion_filename, "-") == 0)
1647 _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1649 macro_expansion_output_stream = NULL;
1651 real_output_filename = xstrdup (real_output_filename);
1652 output_stream = stdout;
1653 splitting = 0; /* Cannot split when writing to stdout. */
1657 if (html && splitting)
1659 if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
1660 || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
1663 output_filename = insert_toplevel_subdirectory (output_filename);
1664 real_output_filename = xstrdup (output_filename);
1666 else if (!real_output_filename)
1667 real_output_filename = expand_filename (output_filename, name);
1669 real_output_filename = xstrdup (real_output_filename);
1671 output_stream = fopen (real_output_filename, "w");
1674 set_current_output_filename (real_output_filename);
1677 printf (_("Making %s file `%s' from `%s'.\n"),
1682 output_filename, input_filename);
1684 if (output_stream == NULL)
1686 fs_error (real_output_filename);
1691 xml_begin_document (filename_part (output_filename));
1693 /* Make the displayable filename from output_filename. Only the base
1694 portion of the filename need be displayed. */
1695 flush_output (); /* in case there was no @bye */
1696 if (output_stream != stdout)
1697 pretty_output_filename = filename_part (output_filename);
1699 pretty_output_filename = xstrdup ("stdout");
1701 /* For this file only, count the number of newlines from the top of
1702 the file to here. This way, we keep track of line numbers for
1703 error reporting. Line_number starts at 1, since the user isn't
1708 while (temp != input_text_offset)
1709 if (input_text[temp++] == '\n')
1713 if (xml && !docbook)
1715 /* Just before the real main loop, let's handle the defines. */
1716 COMMAND_LINE_DEFINE *temp;
1718 for (temp = command_line_defines; temp; temp = temp->next)
1720 handle_variable_internal (temp->action, temp->define);
1727 xml_end_document ();
1731 discard_insertions (0);
1733 flush_file_stack ();
1735 if (macro_expansion_output_stream)
1737 fclose (macro_expansion_output_stream);
1738 if (errors_printed && !force
1739 && strcmp (macro_expansion_filename, "-") != 0
1740 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1741 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1744 _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1745 progname, macro_expansion_filename);
1746 if (unlink (macro_expansion_filename) < 0)
1747 perror (macro_expansion_filename);
1753 output_pending_notes ();
1759 add_word ("</body></html>\n");
1763 /* Write stuff makeinfo generates after @bye, ie. info_trailer. */
1766 if (output_stream != stdout)
1767 if (fclose (output_stream) != 0)
1768 fs_error (real_output_filename);
1770 /* If validating, then validate the entire file right now. */
1772 validate_file (tag_table);
1774 handle_delayed_writes ();
1778 tag_table = (TAG_ENTRY *) reverse_list ((GENERIC_LIST *) tag_table);
1779 if (!no_headers && !html && !STREQ (current_output_filename, "-"))
1780 write_tag_table (real_output_filename);
1783 /* Maybe we want local variables in info output. Must be after
1784 tag table, since otherwise usually Emacs will not see it. */
1785 write_trailer (real_output_filename, info_trailer ());
1787 if (splitting && !html && (!errors_printed || force))
1789 clean_old_split_files (real_output_filename);
1790 split_file (real_output_filename, split_size);
1792 else if (errors_printed
1794 && strcmp (real_output_filename, "-") != 0
1795 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1796 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1797 { /* If there were errors, and no --force, remove the output. */
1799 _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1800 progname, real_output_filename);
1801 if (unlink (real_output_filename) < 0)
1802 perror (real_output_filename);
1806 if (internal_links_stream)
1808 if (internal_links_stream != stdout
1809 && fclose (internal_links_stream) != 0)
1810 fs_error(internal_links_filename);
1811 internal_links_stream = NULL;
1812 if (errors_printed && !force
1813 && strcmp (internal_links_filename, "-") != 0
1814 && FILENAME_CMP (internal_links_filename, NULL_DEVICE) != 0
1815 && FILENAME_CMP (internal_links_filename, ALSO_NULL_DEVICE) != 0)
1818 _("%s: Removing internal links output file `%s' due to errors; use --force to preserve.\n"),
1819 progname, internal_links_filename);
1820 if (unlink (internal_links_filename) < 0)
1821 perror (internal_links_filename);
1825 free (real_output_filename);
1828 /* If enable_encoding is set and @documentencoding is used, return a
1829 Local Variables section (as a malloc-ed string) so that Emacs'
1830 locale features can work. Else return NULL. */
1836 if (!enable_encoding)
1839 encoding = current_document_encoding ();
1841 if (encoding && *encoding)
1843 #define LV_FMT "\n\037\nLocal Variables:\ncoding: %s\nEnd:\n"
1844 char *lv = xmalloc (sizeof (LV_FMT) + strlen (encoding));
1845 sprintf (lv, LV_FMT, encoding);
1854 /* Append TRAILER to FILENAME for Info and HTML output. Include HTML
1855 comments if needed. */
1857 write_trailer (char *filename, char *trailer)
1859 if (!trailer || xml || docbook)
1862 if (output_stream != stdout)
1863 output_stream = fopen (filename, "a");
1866 fs_error (filename);
1871 fwrite ("<!--", 1, 4, output_stream);
1873 fwrite (trailer, 1, strlen (trailer), output_stream);
1877 fwrite ("\n-->\n", 1, 5, output_stream);
1879 if (output_stream != stdout)
1880 if (fclose (output_stream) != 0)
1881 fs_error (filename);
1886 free_and_clear (char **pointer)
1895 /* Initialize some state. */
1897 init_internals (void)
1899 free_and_clear (&output_filename);
1900 free_and_clear (&command);
1901 free_and_clear (&input_filename);
1902 free_node_references ();
1903 free_node_node_references ();
1905 init_insertion_stack ();
1906 init_brace_stack ();
1907 current_node = NULL; /* sometimes already freed */
1912 non_top_node_seen = 0;
1917 init_paragraph (void)
1919 if (output_paragraph)
1920 free (output_paragraph);
1921 output_paragraph = xmalloc (paragraph_buffer_len);
1922 output_paragraph[0] = 0;
1923 output_paragraph_offset = 0;
1924 output_paragraph_start_column = 0;
1925 paragraph_is_open = 0;
1930 /* This is called from `reader_loop' when we are at the * beginning a
1934 handle_menu_entry (void)
1938 /* Ugh, glean_node_from_menu wants to read the * itself. */
1939 input_text_offset--;
1941 /* Find node name in menu entry and save it in references list for
1942 later validation. Use followed_reference type for detailmenu
1943 references since we don't want to use them for default node pointers. */
1944 tem = glean_node_from_menu (1, in_detailmenu
1945 ? followed_reference : menu_reference);
1948 { /* Start a menu item with the cleaned-up line. Put an anchor
1949 around the start text (before `:' or the node name). */
1952 discard_until ("* ");
1954 /* The line number was already incremented in reader_loop when we
1955 saw the newline, and discard_until has now incremented again. */
1958 if (had_menu_commentary)
1960 add_html_block_elt ("<ul class=\"menu\">\n");
1961 had_menu_commentary = 0;
1967 add_html_block_elt ("</p>\n");
1968 add_html_block_elt ("<ul class=\"menu\">\n");
1974 add_html_block_elt ("<li><a");
1975 if (next_menu_item_number <= 9)
1977 add_word(" accesskey=");
1978 add_word_args("\"%d\"", next_menu_item_number);
1979 next_menu_item_number++;
1981 add_word (" href=\"");
1982 string = expansion (tem, 0);
1983 add_anchor_name (string, 1);
1987 /* The menu item may use macros, so expand them now. */
1988 only_macro_expansion++;
1989 get_until_in_line (1, ":", &string);
1990 only_macro_expansion--;
1991 execute_string ("%s", string); /* get escaping done */
1996 if (looking_at ("::"))
1997 discard_until (":");
1999 { /* discard the node name */
2000 get_until_in_line (0, ".", &string);
2003 input_text_offset++; /* discard the second colon or the period */
2005 /* Insert a colon only if there is a description of this menu item. */
2007 int save_input_text_offset = input_text_offset;
2008 int save_line_number = line_number;
2010 get_rest_of_line (0, &test_string);
2011 if (strlen (test_string) > 0)
2013 input_text_offset = save_input_text_offset;
2014 line_number = save_line_number;
2017 else if (xml && tem)
2019 xml_start_menu_entry (tem);
2022 { /* For Info output, we can just use the input and the main case in
2023 reader_loop where we output what comes in. Just move off the *
2024 so the next time through reader_loop we don't end up back here. */
2026 input_text_offset += 2; /* undo the pointer back-up above. */
2033 /* Find the command corresponding to STRING. If the command is found,
2034 return a pointer to the data structure. Otherwise return -1. */
2036 get_command_entry (char *string)
2040 for (i = 0; command_table[i].name; i++)
2041 if (strcmp (command_table[i].name, string) == 0)
2042 return &command_table[i];
2044 /* This command is not in our predefined command table. Perhaps
2045 it is a user defined command. */
2046 for (i = 0; i < user_command_array_len; i++)
2047 if (user_command_array[i] &&
2048 (strcmp (user_command_array[i]->name, string) == 0))
2049 return user_command_array[i];
2051 /* We never heard of this command. */
2052 return (COMMAND *) -1;
2056 /* input_text_offset is right at the command prefix character.
2057 Read the next token to determine what to do. Return zero
2058 if there's no known command or macro after the prefix character. */
2063 int old_text_offset = input_text_offset++;
2065 free_and_clear (&command);
2066 command = read_token ();
2068 /* Check to see if this command is a macro. If so, execute it here. */
2072 def = find_macro (command);
2076 /* We disallow recursive use of a macro call. Inhibit the expansion
2077 of this macro during the life of its execution. */
2078 if (!(def->flags & ME_RECURSE))
2082 execute_macro (def);
2085 if (!(def->flags & ME_RECURSE))
2092 if (only_macro_expansion)
2094 /* Back up to the place where we were called, so the
2095 caller will have a chance to process this non-macro. */
2096 input_text_offset = old_text_offset;
2100 /* Perform alias expansion */
2101 command = alias_expand (command);
2103 if (enclosure_command (command))
2105 remember_brace (enclosure_expand);
2106 enclosure_expand (START, output_paragraph_offset, 0);
2110 entry = get_command_entry (command);
2111 if (entry == (COMMAND *)-1)
2113 line_error (_("Unknown command `%s'"), command);
2117 if (entry->argument_in_braces == BRACE_ARGS)
2118 remember_brace (entry->proc);
2119 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
2121 if (curchar () == '{')
2122 remember_brace (entry->proc);
2124 { /* No braces, so arg is next char. */
2126 int saved_offset = output_paragraph_offset;
2127 (*(entry->proc)) (START, output_paragraph_offset, 0);
2129 /* Possibilities left for the next character: @ (error), }
2130 (error), whitespace (skip) anything else (normal char). */
2135 line_error (_("Use braces to give a command as an argument to @%s"),
2141 /* Our caller will give the error message, because this }
2142 won't match anything. */
2147 input_text_offset++;
2148 (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
2153 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
2155 (*(entry->proc)) (START, output_paragraph_offset, 0);
2159 /* Okay, we are ready to start the conversion. Call the reader on
2160 some text, and fill the text as it is output. Handle commands by
2161 remembering things like open braces and the current file position on a
2162 stack, and when the corresponding close brace is found, you can call
2163 the function with the proper arguments. Although the filling isn't
2164 necessary for HTML, it should do no harm. */
2173 if (input_text_offset >= input_text_length)
2176 character = curchar ();
2178 /* If only_macro_expansion, only handle macros and leave
2179 everything else intact. */
2180 if (!only_macro_expansion && !in_fixed_width_font
2181 && ((!html && !xml) || escape_html)
2182 && (character == '\'' || character == '`')
2183 && input_text[input_text_offset + 1] == character)
2187 input_text_offset += 2;
2188 add_word (character == '`' ? "“" : "”");
2193 input_text_offset += 2;
2194 xml_insert_entity (character == '`' ? "ldquo" : "rdquo");
2199 input_text_offset++;
2204 /* Convert --- to --. */
2205 if (!only_macro_expansion && character == '-' && !in_fixed_width_font
2206 && ((!html && !xml) || escape_html))
2210 /* Get the number of consequtive dashes. */
2211 while (input_text[input_text_offset] == '-')
2214 input_text_offset++;
2222 if (dash_count == 0)
2225 while (dash_count > 0)
2227 if (dash_count >= 2)
2230 add_word ("—");
2232 xml_insert_entity ("mdash");
2235 else if (dash_count >= 1)
2238 add_word ("–");
2240 xml_insert_entity ("ndash");
2248 while (--dash_count > 0)
2255 /* If this is a whitespace character, then check to see if the line
2256 is blank. If so, advance to the carriage return. */
2257 if (!only_macro_expansion && whitespace (character))
2259 int i = input_text_offset + 1;
2261 while (i < input_text_length && whitespace (input_text[i]))
2264 if (i == input_text_length || input_text[i] == '\n')
2266 if (i == input_text_length)
2269 input_text_offset = i;
2270 character = curchar ();
2274 if (character == '\n')
2279 case '*': /* perhaps we are at a menu */
2280 /* We used to check for this in the \n case but an @c in a
2281 menu swallows its newline, so check here instead. */
2282 if (!only_macro_expansion && in_menu
2283 && input_text_offset + 1 < input_text_length
2284 && input_text_offset > 0
2285 && input_text[input_text_offset-1] == '\n')
2286 handle_menu_entry ();
2288 { /* Duplicate code from below, but not worth twisting the
2289 fallthroughs to get down there. */
2290 add_char (character);
2291 input_text_offset++;
2295 /* Escapes for HTML unless we're outputting raw HTML. Do
2296 this always, even if SGML rules don't require it since
2297 that's easier and safer for non-conforming browsers. */
2299 if (html && escape_html)
2302 add_char (character);
2303 input_text_offset++;
2307 if (html && escape_html)
2309 else if (xml && escape_html)
2310 xml_insert_entity ("lt");
2312 add_char (character);
2313 input_text_offset++;
2317 if (html && escape_html)
2319 else if (xml && escape_html)
2320 xml_insert_entity ("gt");
2322 add_char (character);
2323 input_text_offset++;
2326 case COMMAND_PREFIX: /* @ */
2327 if (read_command () || !only_macro_expansion)
2330 /* FALLTHROUGH (usually) */
2332 /* Special case. We're not supposed to see this character by itself.
2333 If we do, it means there is a syntax error in the input text.
2334 Report the error here, but remember this brace on the stack so
2335 we can ignore its partner. */
2336 if (!only_macro_expansion)
2338 if (command && !STREQ (command, "math"))
2340 line_error (_("Misplaced %c"), '{');
2341 remember_brace (misplaced_brace);
2344 /* We don't mind `extra' braces inside @math. */
2345 remember_brace (cm_no_op);
2346 /* remember_brace advances input_text_offset. */
2350 /* FALLTHROUGH (usually) */
2352 if (!only_macro_expansion)
2354 pop_and_call_brace ();
2355 input_text_offset++;
2359 /* FALLTHROUGH (usually) */
2361 add_char (character);
2362 input_text_offset++;
2365 if (macro_expansion_output_stream && !only_macro_expansion)
2366 maybe_write_itext (input_text, input_text_offset);
2370 init_brace_stack (void)
2375 /* Remember the current output position here. Save PROC
2376 along with it so you can call it later. */
2378 remember_brace_1 (COMMAND_FUNCTION (*proc), int position)
2380 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
2381 new->next = brace_stack;
2383 new->command = xstrdup (command ? command : "");
2384 new->pos = position;
2385 new->line = line_number;
2386 new->in_fixed_width_font = in_fixed_width_font;
2391 remember_brace (COMMAND_FUNCTION (*proc))
2393 if (curchar () != '{')
2394 line_error (_("%c%s expected braces"), COMMAND_PREFIX, command);
2396 input_text_offset++;
2397 remember_brace_1 (proc, output_paragraph_offset);
2400 /* Pop the top of the brace stack, and call the associated function
2401 with the args END and POS. */
2403 pop_and_call_brace (void)
2405 if (brace_stack == NULL)
2407 line_error (_("Unmatched }"));
2412 BRACE_ELEMENT *temp;
2414 int pos = brace_stack->pos;
2415 COMMAND_FUNCTION *proc = brace_stack->proc;
2416 in_fixed_width_font = brace_stack->in_fixed_width_font;
2418 /* Reset current command, so the proc can know who it is. This is
2419 used in cm_accent. */
2420 command = brace_stack->command;
2422 temp = brace_stack->next;
2426 (*proc) (END, pos, output_paragraph_offset);
2430 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2432 adjust_braces_following (int here, int amount)
2434 BRACE_ELEMENT *stack = brace_stack;
2438 if (stack->pos >= here)
2439 stack->pos += amount;
2440 stack = stack->next;
2444 /* Return the string which invokes PROC; a pointer to a function.
2445 Always returns the first function in the command table if more than
2446 one matches PROC. */
2448 find_proc_name (COMMAND_FUNCTION (*proc))
2452 for (i = 0; command_table[i].name; i++)
2453 if (proc == command_table[i].proc)
2454 return command_table[i].name;
2455 return _("NO_NAME!");
2458 /* You call discard_braces () when you shouldn't have any braces on the stack.
2459 I used to think that this happens for commands that don't take arguments
2460 in braces, but that was wrong because of things like @code{foo @@}. So now
2461 I only detect it at the beginning of nodes. */
2463 discard_braces (void)
2470 if (brace_stack->proc != misplaced_brace)
2472 const char *proc_name;
2474 proc_name = find_proc_name (brace_stack->proc);
2475 file_line_error (input_filename, brace_stack->line,
2476 _("%c%s missing close brace"), COMMAND_PREFIX,
2478 pop_and_call_brace ();
2482 BRACE_ELEMENT *temp;
2483 temp = brace_stack->next;
2490 /* Return the 0-based number of the current output column */
2492 current_output_column (void)
2496 for (i = output_paragraph_offset; i > 0 && output_paragraph[i - 1] != '\n';
2500 column = output_paragraph_start_column;
2503 while (i < output_paragraph_offset)
2507 /* Find a span of non-control characters */
2508 for (j = i; j < output_paragraph_offset; j++)
2512 c = output_paragraph[j];
2513 if ((0 <= c && c < ' ') || c == '\t' || c == NON_BREAKING_SPACE)
2518 column += mbsnwidth ((char *)(output_paragraph + i), j - i, 0);
2521 if (i < output_paragraph_offset)
2525 /* Handle a control character */
2526 c = output_paragraph[i];
2529 column = (column + 8) & ~0x7;
2530 if (column > fill_column)
2531 column = fill_column;
2533 else if (c == NON_BREAKING_SPACE)
2537 /* ASCII control characters appear as two characters in the
2538 output (e.g., ^A). */
2539 if (!(0 <= c && c < ' '))
2550 #if defined (VA_FPRINTF) && __STDC__
2551 add_word_args (const char *format, ...)
2553 add_word_args (format, va_alist)
2558 char buffer[2000]; /* xx no fixed limits */
2563 VA_START (ap, format);
2565 VA_SPRINTF (buffer, format, ap);
2567 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2568 #endif /* not VA_SPRINTF */
2573 /* Add STRING to output_paragraph. */
2575 add_word (char *string)
2578 add_char (*string++);
2581 /* Like add_word, but inhibits conversion of whitespace into .
2582 Use this to output HTML directives with embedded blanks, to make
2585 add_html_elt (char *string)
2592 /* These two functions below, add_html_block_elt and add_html_block_elt_args,
2593 are mixtures of add_html_elt and add_word_args. They inform makeinfo that
2594 the current HTML element being inserted should not be enclosed in a <p>
2597 add_html_block_elt (char *string)
2599 in_html_block_level_elt++;
2601 in_html_block_level_elt--;
2605 #if defined (VA_FPRINTF) && __STDC__
2606 add_html_block_elt_args (const char *format, ...)
2608 add_html_block_elt_args (format, va_alist)
2613 char buffer[2000]; /* xx no fixed limits */
2618 VA_START (ap, format);
2620 VA_SPRINTF (buffer, format, ap);
2622 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2623 #endif /* not VA_SPRINTF */
2625 add_html_block_elt (buffer);
2628 /* Here is another awful kludge, used in add_char. Ordinarily, macro
2629 expansions take place in the body of the document, and therefore we
2630 should html_output_head when we see one. But there's an exception: a
2631 macro call might take place within @copying, and that does not start
2632 the real output, even though we fully expand the copying text.
2634 So we need to be able to check if we are defining the @copying text.
2635 We do this by looking back through the insertion stack. */
2637 defining_copying (void)
2640 for (i = insertion_stack; i; i = i->next)
2642 if (i->insertion == copying)
2648 /* Output the header for Info.
2649 html fixxme: should output this as trailer on first page (at least). */
2652 info_output_head (void)
2654 add_word_args (gdt("This is %s, produced by makeinfo version %s from %s.\n"),
2655 output_filename, VERSION, input_filename);
2657 /* Start afresh with whatever real text we have. */
2660 /* We do not want indentation in what follows, which is usually going
2661 to be a node marker (CTRL-_). */
2662 if (inhibit_paragraph_indentation == 0)
2663 inhibit_paragraph_indentation = -1;
2669 if (output_head_p) /* no-op if we're mistakenly called twice */
2674 html_output_head ();
2676 ; /* handled differently, via xml_begin_document */
2677 else if (no_headers)
2678 ; /* no header for plain text */
2680 info_output_head ();
2684 /* Add the character to the current paragraph. If filling_enabled is
2685 nonzero, then do filling as well. */
2687 add_char (int character)
2691 xml_add_char (character);
2695 /* If we are avoiding outputting headers, and we are currently
2696 in a menu, then simply return. But if we're only expanding macros,
2697 then we're being called from glean_node_from_menu to try to
2698 remember a menu reference, and we need that so we can do defaulting. */
2699 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2702 /* If we are adding a character now, then we don't have to
2703 ignore close_paragraph () calls any more. */
2704 if (must_start_paragraph && character != '\n')
2708 must_start_paragraph = 0;
2709 line_already_broken = 0; /* The line is no longer broken. */
2710 column = current_output_column ();
2711 if (current_indent > column)
2712 indent (current_indent - column);
2715 if (non_splitting_words
2716 && !(html && in_html_elt)
2717 && strchr (" \t\n", character))
2719 if (html || docbook)
2720 { /* Seems cleaner to use than an 8-bit char. */
2721 int saved_escape_html = escape_html;
2724 escape_html = saved_escape_html;
2728 character = NON_BREAKING_SPACE; /* restored in flush_output */
2731 insertion_paragraph_closed = 0;
2736 if (!filling_enabled && !(html && (in_menu || in_detailmenu)))
2740 if (force_flush_right)
2743 /* Hack to force single blank lines out in this mode. */
2747 if (!no_indent && paragraph_is_open)
2748 indent (current_indent);
2751 else if (end_of_sentence_p () && !french_spacing)
2752 /* CHARACTER is newline, filling is enabled, and we're at the
2753 end of a sentence. Insert an extra space, unless
2754 @frenchspacing is in effect. */
2757 last_inserted_character = character;
2760 if (last_char_was_newline)
2763 last_char_was_newline++;
2769 last_char_was_newline = 1;
2777 default: /* not at newline */
2780 int suppress_insert = 0;
2782 if ((character == ' ') && (last_char_was_newline))
2784 if (!paragraph_is_open)
2791 /* This is a sad place to do this, but it seems highly desirable
2792 to not force any particular order on the front matter
2793 commands. This way, the document can do @settitle,
2794 @documentlanguage, etc, in any order and with any omissions,
2795 and we'll still output the header ("produced by makeinfo",
2796 HTML <head>, etc.) `just in time'. */
2797 if ((executing_macro || !executing_string)
2798 && !only_macro_expansion
2799 && !defining_copying ()
2805 if (!paragraph_is_open)
2808 /* If the paragraph is supposed to be indented a certain
2809 way, then discard all of the pending whitespace.
2810 Otherwise, we let the whitespace stay. */
2811 if (!paragraph_start_indent)
2812 indent (pending_indent);
2815 /* This check for in_html_block_level_elt prevents <p> from being
2816 inserted when we already have html markup starting a paragraph,
2817 as with <ul> and <h1> and the like. */
2818 if (html && !in_html_block_level_elt)
2820 if ((in_menu || in_detailmenu) && in_menu_item)
2822 insert_string ("</li></ul>\n");
2825 insert_string ("<p>");
2827 adjust_braces_following (0, 3); /* adjust for <p> */
2831 output_paragraph[output_paragraph_offset] = character;
2832 output_paragraph_offset++;
2833 column = current_output_column ();
2834 output_paragraph_offset--;
2835 if (column > fill_column)
2837 if (filling_enabled && !html)
2839 int temp = output_paragraph_offset;
2840 while (--temp > 0 && output_paragraph[temp] != '\n')
2842 /* If we have found a space, we have the place to break
2844 if (output_paragraph[temp] == ' ')
2846 /* Remove trailing whitespace from output. */
2847 while (temp && whitespace (output_paragraph[temp - 1]))
2850 /* If we went back all the way to the newline of the
2851 preceding line, it probably means that the word we
2852 are adding is itself wider than the space that the
2853 indentation and the fill_column let us use. In
2854 that case, do NOT insert another newline, since it
2855 won't help. Just indent to current_indent and
2856 leave it alone, since that's the most we can do. */
2857 if (temp && output_paragraph[temp - 1] != '\n')
2858 output_paragraph[temp++] = '\n';
2860 /* We have correctly broken the line where we want
2861 to. What we don't want is spaces following where
2862 we have decided to break the line. We get rid of
2869 if (t1 == output_paragraph_offset)
2871 if (whitespace (character))
2872 suppress_insert = 1;
2875 if (!whitespace (output_paragraph[t1]))
2881 adjust_braces_following (temp, (- (t1 - temp)));
2882 memmove (&output_paragraph[temp],
2883 &output_paragraph[t1],
2884 output_paragraph_offset - t1);
2885 output_paragraph_offset -= (t1 - temp);
2889 /* Filled, but now indent if that is right. */
2890 if (indented_fill && current_indent > 0)
2892 int buffer_len = ((output_paragraph_offset - temp)
2894 char *temp_buffer = xmalloc (buffer_len);
2895 int indentation = 0;
2897 /* We have to shift any markers that are in
2898 front of the wrap point. */
2899 adjust_braces_following (temp, current_indent);
2901 while (current_indent > 0 &&
2902 indentation != current_indent)
2903 temp_buffer[indentation++] = ' ';
2905 memcpy ((char *) &temp_buffer[current_indent],
2906 (char *) &output_paragraph[temp],
2907 buffer_len - current_indent);
2909 if (output_paragraph_offset + buffer_len
2910 >= paragraph_buffer_len)
2912 unsigned char *tt = xrealloc
2914 (paragraph_buffer_len += buffer_len));
2915 output_paragraph = tt;
2917 memcpy ((char *) &output_paragraph[temp],
2918 temp_buffer, buffer_len);
2919 output_paragraph_offset += current_indent;
2928 if (!suppress_insert)
2931 last_inserted_character = character;
2933 last_char_was_newline = 0;
2934 line_already_broken = 0;
2939 /* Add a character and store its position in meta_char_pos. */
2941 add_meta_char (int character)
2943 meta_char_pos = output_paragraph_offset;
2944 add_char (character);
2947 /* Insert CHARACTER into `output_paragraph'. */
2949 insert (int character)
2951 /* We don't want to strip trailing whitespace in multitables. Otherwise
2952 horizontal separators confuse the font locking in Info mode in Emacs,
2953 because it looks like a @subsection. Adding a trailing space to those
2955 if (character == '\n' && !html && !xml && !multitable_active)
2957 while (output_paragraph_offset
2958 && whitespace (output_paragraph[output_paragraph_offset-1]))
2959 output_paragraph_offset--;
2962 output_paragraph[output_paragraph_offset++] = character;
2963 if (output_paragraph_offset == paragraph_buffer_len)
2966 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2970 /* Insert the null-terminated string STRING into `output_paragraph'. */
2972 insert_string (const char *string)
2979 /* Sentences might have these characters after the period (or whatever). */
2980 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2983 /* Return true if at an end-of-sentence character, possibly followed by
2984 post-sentence punctuation to ignore. */
2986 end_of_sentence_p (void)
2988 int loc = output_paragraph_offset - 1;
2990 /* If nothing has been output, don't check output_paragraph[-1]. */
2994 /* A post-sentence character that is at meta_char_pos is not really
2995 a post-sentence character; it was produced by a markup such as
2996 @samp. We don't want the period inside @samp to be treated as a
2999 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
3001 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
3005 /* Remove upto COUNT characters of whitespace from the
3006 the current output line. If COUNT is less than zero,
3007 then remove until none left. */
3009 kill_self_indent (int count)
3011 /* Handle infinite case first. */
3014 while (output_paragraph_offset)
3016 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
3017 output_paragraph_offset--;
3024 while (output_paragraph_offset && count--)
3025 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
3026 output_paragraph_offset--;
3032 /* Nonzero means do not honor calls to flush_output (). */
3033 static int flushing_ignored = 0;
3035 /* Prevent calls to flush_output () from having any effect. */
3037 inhibit_output_flushing (void)
3042 /* Allow calls to flush_output () to write the paragraph data. */
3044 uninhibit_output_flushing (void)
3054 if (!output_paragraph_offset || flushing_ignored)
3057 for (i = 0; i < output_paragraph_offset; i++)
3059 if (output_paragraph[i] == '\n')
3061 output_line_number++;
3065 /* If we turned on the 8th bit for a space inside @w, turn it back off
3066 for output. Don't do this for HTML, since the nbsp character is valid
3067 input and must be passed along to the browser. */
3068 if (!html && output_paragraph[i] == NON_BREAKING_SPACE)
3069 output_paragraph[i] = ' ';
3072 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
3074 output_position += output_paragraph_offset;
3075 output_paragraph_start_column = current_output_column ();
3076 output_paragraph_offset = 0;
3080 /* How to close a paragraph controlling the number of lines between
3081 this one and the last one. */
3083 /* Paragraph spacing is controlled by this variable. It is the number of
3084 blank lines that you wish to appear between paragraphs. A value of
3085 1 creates a single blank line between paragraphs. */
3086 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
3089 close_paragraph_with_lines (int lines)
3091 int old_spacing = paragraph_spacing;
3092 paragraph_spacing = lines;
3094 paragraph_spacing = old_spacing;
3097 /* Close the current paragraph, leaving no blank lines between them. */
3099 close_single_paragraph (void)
3101 close_paragraph_with_lines (0);
3104 /* Close a paragraph after an insertion has ended. */
3106 close_insertion_paragraph (void)
3108 if (!insertion_paragraph_closed)
3110 /* Close the current paragraph, breaking the line. */
3111 close_single_paragraph ();
3113 /* Start a new paragraph, with the correct indentation for the now
3114 current insertion level (one above the one that we are ending). */
3117 /* Tell `close_paragraph' that the previous line has already been
3118 broken, so it should insert one less newline. */
3119 line_already_broken = 1;
3121 /* Tell functions such as `add_char' we've already found a newline. */
3122 ignore_blank_line ();
3128 /* If the insertion paragraph is closed already, then we are seeing
3129 two `@end' commands in a row. Note that the first one we saw was
3130 handled in the first part of this if-then-else clause, and at that
3131 time `start_paragraph' was called, partially to handle the proper
3132 indentation of the current line. However, the indentation level
3133 may have just changed again, so we may have to outdent the current
3134 line to the new indentation level. */
3135 column = current_output_column ();
3136 if (current_indent < column)
3137 kill_self_indent (column - current_indent);
3140 insertion_paragraph_closed = 1;
3143 /* Close the currently open paragraph. */
3145 close_paragraph (void)
3149 /* We don't need these newlines in XML and Docbook outputs for
3150 paragraph separation. We have the <para> element for that. */
3154 /* The insertion paragraph is no longer closed. */
3155 insertion_paragraph_closed = 0;
3157 if (paragraph_is_open && !must_start_paragraph)
3159 int tindex = output_paragraph_offset;
3161 /* Back up to last non-newline/space character, forcing all such
3162 subsequent characters to be newlines. This isn't strictly
3163 necessary, but a couple of functions use the presence of a newline
3164 to make decisions. */
3165 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
3167 int c = output_paragraph[tindex];
3169 if (c == ' '|| c == '\n')
3170 output_paragraph[tindex] = '\n';
3175 /* All trailing whitespace is ignored. */
3176 output_paragraph_offset = ++tindex;
3178 /* Break the line if that is appropriate. */
3179 if (paragraph_spacing >= 0)
3182 /* Add as many blank lines as is specified in `paragraph_spacing'. */
3183 if (!force_flush_right)
3185 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
3188 /* Don't need anything extra for HTML in usual case of no
3189 extra paragraph spacing. */
3191 insert_string ("<br>");
3195 /* If we are doing flush right indentation, then do it now
3196 on the paragraph (really a single line). */
3197 if (force_flush_right)
3198 do_flush_right_indentation ();
3201 paragraph_is_open = 0;
3205 ignore_blank_line ();
3208 /* Make the last line just read look as if it were only a newline. */
3210 ignore_blank_line (void)
3212 last_inserted_character = '\n';
3213 last_char_was_newline = 1;
3216 /* Align the end of the text in output_paragraph with fill_column. The last
3217 character in output_paragraph is '\n'. */
3219 do_flush_right_indentation (void)
3223 kill_self_indent (-1);
3225 if (output_paragraph[0] != '\n')
3229 width = mbsnwidth ((char *)output_paragraph, output_paragraph_offset - 1,
3231 if (width < fill_column)
3235 if (output_paragraph_offset + (fill_column - width)
3236 >= paragraph_buffer_len)
3238 xrealloc (output_paragraph,
3239 (paragraph_buffer_len += fill_column));
3241 temp = xmalloc (output_paragraph_offset);
3242 memcpy (temp, (char *)output_paragraph, output_paragraph_offset);
3244 for (i = 0; i < fill_column - width; i++)
3245 output_paragraph[i] = ' ';
3247 memcpy ((char *)output_paragraph + i, temp, output_paragraph_offset);
3249 output_paragraph_offset += i;
3250 adjust_braces_following (0, i);
3255 /* Begin a new paragraph. */
3257 start_paragraph (void)
3259 /* First close existing one. */
3260 if (paragraph_is_open)
3263 /* In either case, the insertion paragraph is no longer closed. */
3264 insertion_paragraph_closed = 0;
3266 /* However, the paragraph is open! */
3267 paragraph_is_open = 1;
3269 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
3270 had to be called before we would allow any other paragraph operations
3271 to have an effect. */
3272 if (!must_start_paragraph)
3274 int amount_to_indent = 0;
3276 /* If doing indentation, then insert the appropriate amount. */
3281 if (inhibit_paragraph_indentation)
3283 amount_to_indent = current_indent;
3284 if (inhibit_paragraph_indentation < 0)
3285 inhibit_paragraph_indentation++;
3287 else if (paragraph_start_indent < 0)
3288 amount_to_indent = current_indent;
3290 amount_to_indent = current_indent + paragraph_start_indent;
3292 column = current_output_column ();
3293 if (amount_to_indent >= column)
3294 indent (amount_to_indent - column);
3298 must_start_paragraph = 0;
3301 /* Insert the indentation specified by AMOUNT. */
3305 /* For every START_POS saved within the brace stack which will be affected
3306 by this indentation, bump that start pos forward. */
3307 adjust_braces_following (output_paragraph_offset, amount);
3309 while (--amount >= 0)
3313 /* Search forward for STRING in input_text.
3314 FROM says where to start. */
3316 search_forward (const char *string, int from)
3318 int len = strlen (string);
3320 while (from < input_text_length)
3322 if (strncmp (input_text + from, string, len) == 0)
3329 /* search_forward until n characters. */
3331 search_forward_until_pos (char *string, int from, int end_pos)
3333 int save_input_text_length = input_text_length;
3334 input_text_length = end_pos;
3336 from = search_forward (string, from);
3338 input_text_length = save_input_text_length;
3343 /* Return next non-whitespace and non-cr character. */
3345 next_nonwhitespace_character (void)
3347 /* First check the current input_text. Start from the next char because
3348 we already have input_text[input_text_offset] in ``current''. */
3349 int pos = input_text_offset + 1;
3351 while (pos < input_text_length)
3353 if (!cr_or_whitespace(input_text[pos]))
3354 return input_text[pos];
3358 { /* Can't find a valid character, so go through filestack
3359 in case we are doing @include or expanding a macro. */
3360 FSTACK *tos = filestack;
3364 int tmp_input_text_length = filestack->size;
3365 int tmp_input_text_offset = filestack->offset;
3366 char *tmp_input_text = filestack->text;
3368 while (tmp_input_text_offset < tmp_input_text_length)
3370 if (!cr_or_whitespace(tmp_input_text[tmp_input_text_offset]))
3371 return tmp_input_text[tmp_input_text_offset];
3372 tmp_input_text_offset++;
3384 /* Replace " with \" and \ with \\. Used for alt tag in Info output.
3385 Return a newly-malloced string in all cases. */
3388 bs_escape_quote (const char *src)
3391 char *dest = xmalloc (2 * strlen (src) + 1); /* can't need more. */
3394 for (; c = *src; src++)
3396 if (c == '"' || c == '\\')
3408 /* An external image is a reference, kind of. The parsing is (not
3409 coincidentally) similar, anyway. */
3414 char *name_arg, *w_arg, *h_arg, *alt_arg, *ext_arg;
3419 name_arg = get_xref_token (1); /* expands all macros in image */
3420 w_arg = get_xref_token (0);
3421 h_arg = get_xref_token (0);
3422 alt_arg = get_xref_token (1); /* expands all macros in alt text */
3423 ext_arg = get_xref_token (0);
3427 struct stat file_info;
3428 char *pathname = NULL;
3429 unsigned ext_len = (ext_arg && *ext_arg) ? strlen (ext_arg) : 0;
3430 /* One byte for the . period separator, one byte for the null.
3431 The 3 is for the max length of the hardwired extensions we try. */
3432 char *fullname = xmalloc (strlen (name_arg) + 1 + MAX (ext_len, 3) + 1);
3434 if (ext_arg && *ext_arg)
3436 sprintf (fullname, "%s%s", name_arg, ext_arg);
3437 if (access (fullname, R_OK) != 0)
3438 pathname = get_file_info_in_path (fullname, include_files_path,
3441 if (pathname == NULL)
3443 /* Backwards compatibility (4.6 <= version < 4.7):
3444 try prefixing @image's EXTENSION parameter with a period. */
3445 sprintf (fullname, "%s.%s", name_arg, ext_arg);
3446 if (access (fullname, R_OK) != 0)
3447 pathname = get_file_info_in_path (fullname, include_files_path,
3453 sprintf (fullname, "%s.png", name_arg);
3454 if (access (fullname, R_OK) != 0) {
3455 pathname = get_file_info_in_path (fullname,
3456 include_files_path, &file_info);
3457 if (pathname == NULL) {
3458 sprintf (fullname, "%s.jpg", name_arg);
3459 if (access (fullname, R_OK) != 0) {
3460 pathname = get_file_info_in_path (fullname,
3463 if (pathname == NULL) {
3464 sprintf (fullname, "%s.gif", name_arg);
3465 if (access (fullname, R_OK) != 0) {
3466 pathname = get_file_info_in_path (fullname,
3478 int image_in_div = 0;
3480 if (pathname == NULL && access (fullname, R_OK) != 0)
3482 line_error(_("@image file `%s' (for HTML) not readable: %s"),
3483 fullname, strerror (errno));
3486 if (pathname != NULL && access (pathname, R_OK) != 0)
3488 line_error (_("No such file `%s'"),
3493 if (!paragraph_is_open)
3495 add_html_block_elt ("<div class=\"block-image\">");
3499 add_html_elt ("<img src=");
3500 add_word_args ("\"%s\"", fullname);
3501 add_html_elt (" alt=");
3502 add_word_args ("\"%s\">",
3503 escape_string (*alt_arg ? text_expansion (alt_arg) : fullname));
3506 add_html_block_elt ("</div>");
3508 else if (xml && docbook)
3509 xml_insert_docbook_image (name_arg);
3512 extern int xml_in_para;
3513 extern int xml_no_para;
3514 int elt = xml_in_para ? INLINEIMAGE : IMAGE;
3519 xml_insert_element_with_attribute (elt,
3520 START, "width=\"%s\" height=\"%s\" name=\"%s\" extension=\"%s\"",
3521 w_arg, h_arg, name_arg, ext_arg);
3522 xml_insert_element (IMAGEALTTEXT, START);
3523 execute_string ("%s", alt_arg);
3524 xml_insert_element (IMAGEALTTEXT, END);
3525 xml_insert_element (elt, END);
3531 { /* Prefer foo.txt for Info/ASCII. Seems wrong nowadays. */
3533 char *txtpath = NULL;
3534 char *txtname = xmalloc (strlen (name_arg) + 4 + 1);
3535 strcpy (txtname, name_arg);
3536 strcat (txtname, ".txt");
3537 image_file = fopen (txtname, "r");
3538 if (image_file == NULL)
3540 txtpath = get_file_info_in_path (txtname,
3541 include_files_path, &file_info);
3542 if (txtpath != NULL)
3543 image_file = fopen (txtpath, "r");
3546 if (image_file != NULL
3547 || access (fullname, R_OK) == 0
3548 || (pathname != NULL && access (pathname, R_OK) == 0))
3551 int save_inhibit_indentation = inhibit_paragraph_indentation;
3552 int save_filling_enabled = filling_enabled;
3553 int image_in_brackets = paragraph_is_open;
3555 /* Write magic ^@^H[image ...^@^H] cookie in the info file, if
3556 there's an accompanying bitmap. Otherwise just include the
3557 text image. In the plaintext output, always include the text
3558 image without the magic cookie. */
3559 int use_magic_cookie = !no_headers
3560 && access (fullname, R_OK) == 0 && !STREQ (fullname, txtname);
3562 inhibit_paragraph_indentation = 1;
3563 filling_enabled = 0;
3564 last_char_was_newline = 0;
3566 if (use_magic_cookie)
3569 add_word ("\010[image");
3571 if (access (fullname, R_OK) == 0
3572 || (pathname != NULL && access (pathname, R_OK) == 0))
3573 add_word_args (" src=\"%s\"", fullname);
3577 char *expanded = text_expansion (alt_arg);
3578 char *escaped = bs_escape_quote (expanded);
3579 add_word_args (" alt=\"%s\"", escaped);
3585 if (image_file != NULL)
3587 if (use_magic_cookie)
3588 add_word (" text=\"");
3590 if (image_in_brackets)
3593 /* Maybe we need to remove the final newline if the image
3594 file is only one line to allow in-line images. On the
3595 other hand, they could just make the file without a
3597 while ((ch = getc (image_file)) != EOF)
3599 if (use_magic_cookie && (ch == '"' || ch == '\\'))
3604 if (image_in_brackets)
3607 if (use_magic_cookie)
3610 if (fclose (image_file) != 0)
3614 if (use_magic_cookie)
3620 inhibit_paragraph_indentation = save_inhibit_indentation;
3621 filling_enabled = save_filling_enabled;
3624 warning (_("@image file `%s' (for text) unreadable: %s"),
3625 txtname, strerror (errno));
3633 line_error (_("@image missing filename argument"));
3649 /* A structure which contains `defined' variables. */
3650 typedef struct defines {
3651 struct defines *next;
3656 /* The linked list of `set' defines. */
3657 DEFINE *defines = NULL;
3659 /* Add NAME to the list of `set' defines. */
3661 set (char *name, char *value)
3665 for (temp = defines; temp; temp = temp->next)
3666 if (strcmp (name, temp->name) == 0)
3669 temp->value = xstrdup (value);
3673 temp = xmalloc (sizeof (DEFINE));
3674 temp->next = defines;
3675 temp->name = xstrdup (name);
3676 temp->value = xstrdup (value);
3679 if (xml && !docbook)
3681 xml_insert_element_with_attribute (SETVALUE, START, "name=\"%s\"", name);
3682 execute_string ("%s", value);
3683 xml_insert_element (SETVALUE, END);
3687 /* Remove NAME from the list of `set' defines. */
3691 DEFINE *temp, *last;
3698 if (strcmp (temp->name, name) == 0)
3701 last->next = temp->next;
3703 defines = temp->next;
3714 if (xml && !docbook)
3716 xml_insert_element_with_attribute (CLEARVALUE, START, "name=\"%s\"", name);
3717 xml_insert_element (CLEARVALUE, END);
3721 /* Return the value of NAME. The return value is NULL if NAME is unset. */
3727 for (temp = defines; temp; temp = temp->next)
3728 if (strcmp (temp->name, name) == 0)
3734 /* Create a variable whose name appears as the first word on this line. */
3738 handle_variable (SET);
3741 /* Remove a variable whose name appears as the first word on this line. */
3745 handle_variable (CLEAR);
3751 handle_variable (IFSET);
3757 handle_variable (IFCLEAR);
3760 /* This command takes braces, but we parse the contents specially, so we
3761 don't use the standard brace popping code.
3763 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3764 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3765 it produces no output. */
3771 arglist = get_brace_args (quote_none);
3775 if (array_len (arglist) > 1)
3777 if ((mbscasecmp (arglist[0], arglist[1]) == 0) &&
3779 execute_string ("%s\n", arglist[2]);
3782 free_array (arglist);
3787 cm_value (int arg, int start_pos, int end_pos)
3789 static int value_level = 0, saved_meta_pos = -1;
3791 /* xml_add_char() skips any content inside menus when output format is
3792 Docbook, so @value{} is no use there. Also start_pos and end_pos does not
3793 get updated, causing name to be empty string. So just return. */
3794 if (docbook && in_menu)
3797 /* All the text after @value{ upto the matching } will eventually
3798 disappear from output_paragraph, when this function is called
3799 with ARG == END. If the text produced until then sets
3800 meta_char_pos, we will need to restore it to the value it had
3801 before @value was seen. So we need to save the previous value
3802 of meta_char_pos here. */
3805 /* If we are already inside some outer @value, don't overwrite
3806 the value saved in saved_meta_pos. */
3808 saved_meta_pos = meta_char_pos;
3810 /* While the argument of @value is processed, we need to inhibit
3811 textual transformations like "--" into "-", since @set didn't
3812 do that when it grabbed the name of the variable. */
3813 in_fixed_width_font++;
3817 char *name = (char *) &output_paragraph[start_pos];
3819 output_paragraph[end_pos] = 0;
3820 name = xstrdup (name);
3821 value = set_p (name);
3822 output_paragraph_offset = start_pos;
3824 /* Restore the previous value of meta_char_pos if the stuff
3825 inside this @value{} moved it. */
3826 if (saved_meta_pos == -1) /* can't happen inside @value{} */
3828 if (value_level == 1
3829 && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3831 meta_char_pos = saved_meta_pos;
3832 saved_meta_pos = -1;
3835 /* No need to decrement in_fixed_width_font, since before
3836 we are called with arg == END, the reader loop already
3837 popped the brace stack, which restored in_fixed_width_font,
3838 among other things. */
3842 /* We need to get past the closing brace since the value may
3843 expand to a context-sensitive macro (e.g. @xref) and produce
3844 spurious warnings */
3845 input_text_offset++;
3846 execute_string ("%s", value);
3847 input_text_offset--;
3851 warning (_("undefined flag: %s"), name);
3852 add_word_args (_("{No value for `%s'}"), name);
3859 /* Set, clear, or conditionalize based on ACTION. */
3861 handle_variable (int action)
3865 get_rest_of_line (0, &name);
3866 /* If we hit the end of text in get_rest_of_line, backing up
3867 input pointer will cause the last character of the last line
3868 be pushed back onto the input, which is wrong. */
3869 if (input_text_offset < input_text_length)
3870 backup_input_pointer ();
3871 handle_variable_internal (action, name);
3876 handle_variable_internal (int action, char *name)
3879 int delimiter, additional_text_present = 0;
3881 /* Only the first word of NAME is a valid tag. */
3884 while (*temp && (delimiter || !whitespace (*temp)))
3886 /* #if defined (SET_WITH_EQUAL) */
3887 if (*temp == '"' || *temp == '\'')
3889 if (*temp == delimiter)
3894 /* #endif SET_WITH_EQUAL */
3899 additional_text_present++;
3904 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3913 #if defined (SET_WITH_EQUAL)
3914 /* Allow a value to be saved along with a variable. The value is
3915 the text following an `=' sign in NAME, if any is present. */
3917 for (value = name; *value && *value != '='; value++);
3922 if (*value == '"' || *value == '\'')
3925 value[strlen (value) - 1] = 0;
3928 #else /* !SET_WITH_EQUAL */
3929 /* The VALUE of NAME is the remainder of the line sans
3931 if (additional_text_present)
3934 canon_white (value);
3938 #endif /* !SET_WITH_VALUE */
3950 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3951 read lines from the the file until we reach a matching
3952 "@end CONDITION". This means that we only take note of
3953 "@ifset/clear" and "@end" commands. */
3957 int orig_line_number = line_number;
3959 if (action == IFSET)
3960 strcpy (condition, "ifset");
3962 strcpy (condition, "ifclear");
3964 condition_len = strlen (condition);
3966 if ((action == IFSET && !set_p (name))
3967 || (action == IFCLEAR && set_p (name)))
3969 int level = 0, done = 0;
3971 while (!done && input_text_offset < input_text_length)
3973 char *freeable_line, *line;
3975 get_rest_of_line (0, &freeable_line);
3977 for (line = freeable_line; whitespace (*line); line++);
3979 if (*line == COMMAND_PREFIX &&
3980 (strncmp (line + 1, condition, condition_len) == 0))
3982 else if (strncmp (line, "@end", 4) == 0)
3984 char *cname = line + 4;
3987 while (*cname && whitespace (*cname))
3991 while (*temp && !whitespace (*temp))
3995 if (strcmp (cname, condition) == 0)
4005 free (freeable_line);
4009 file_line_error (input_filename, orig_line_number,
4010 _("Reached eof before matching @end %s"),
4013 /* We found the end of a false @ifset/ifclear. If we are
4014 in a menu, back up over the newline that ends the ifset,
4015 since that newline may also begin the next menu entry. */
4020 if (action == IFSET)
4021 begin_insertion (ifset);
4023 begin_insertion (ifclear);
4031 /* Execution of random text not in file. */
4033 char *string; /* The string buffer. */
4034 int size; /* The size of the buffer. */
4035 int in_use; /* Nonzero means string currently in use. */
4038 static EXECUTION_STRING **execution_strings = NULL;
4039 static int execution_strings_index = 0;
4040 static int execution_strings_slots = 0;
4042 static EXECUTION_STRING *
4043 get_execution_string (int initial_size)
4046 EXECUTION_STRING *es = NULL;
4048 if (execution_strings)
4050 for (i = 0; i < execution_strings_index; i++)
4051 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
4053 es = execution_strings[i];
4060 if (execution_strings_index + 1 >= execution_strings_slots)
4062 execution_strings = xrealloc
4064 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
4065 for (; i < execution_strings_slots; i++)
4066 execution_strings[i] = NULL;
4069 execution_strings[execution_strings_index] =
4070 xmalloc (sizeof (EXECUTION_STRING));
4071 es = execution_strings[execution_strings_index];
4072 execution_strings_index++;
4079 if (initial_size > es->size)
4081 es->string = xrealloc (es->string, initial_size);
4082 es->size = initial_size;
4087 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
4088 entry in the execution_strings[] array and change the .STRING and
4089 .SIZE members of that entry as appropriate. */
4091 maybe_update_execution_strings (char **text, unsigned int new_len)
4095 if (execution_strings)
4097 for (i = 0; i < execution_strings_index; i++)
4098 if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
4099 execution_strings[i]->string == *text)
4101 /* Don't ever shrink the string storage in execution_strings[]!
4102 execute_string assumes that it is always big enough to store
4103 every possible execution_string, and will break if that's
4104 not true. So we only enlarge the string storage if the
4105 current size isn't big enough. */
4106 if (execution_strings[i]->size < new_len)
4108 execution_strings[i]->string =
4109 *text = xrealloc (*text, new_len + 1);
4110 execution_strings[i]->size = new_len + 1;
4115 /* We should *never* end up here, since if we are inside
4116 execute_string, TEXT is always in execution_strings[]. */
4120 #define EXECUTE_STRING_MAX (32*1024) /* FIXXME: this is an arbitrary limit. */
4122 /* Execute the string produced by formatting the ARGs with FORMAT. This
4123 is like submitting a new file with @include. */
4125 #if defined (VA_FPRINTF) && __STDC__
4126 execute_string (char *format, ...)
4128 execute_string (format, va_alist)
4133 EXECUTION_STRING *es;
4134 char *temp_string, *temp_input_filename;
4138 int insertion_level_at_start = insertion_level;
4140 es = get_execution_string (EXECUTE_STRING_MAX);
4141 temp_string = es->string;
4144 VA_START (ap, format);
4146 VA_SPRINTF (temp_string, format, ap);
4148 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
4149 #endif /* not VA_SPRINTF */
4153 input_text_offset = 0;
4154 input_text = temp_string;
4155 input_text_length = strlen (temp_string);
4156 input_filename = xstrdup (input_filename);
4157 temp_input_filename = input_filename;
4162 /* If insertion stack level changes during execution, that means a multiline
4163 command is used inside braces or @section ... kind of commands. */
4164 if (insertion_level_at_start != insertion_level && !executing_macro)
4166 line_error (_("Multiline command %c%s used improperly"),
4169 /* We also need to keep insertion_level intact to make sure warnings are
4170 issued for @end ... command. */
4171 while (insertion_level > insertion_level_at_start)
4178 free (temp_input_filename);
4182 /* Return what would be output for STR (in newly-malloced memory), i.e.,
4183 expand Texinfo commands according to the current output format. If
4184 IMPLICIT_CODE is set, expand @code{STR}. This is generally used for
4185 short texts; filling, indentation, and html escapes are disabled. */
4188 expansion (char *str, int implicit_code)
4190 return maybe_escaped_expansion (str, implicit_code, 0);
4194 /* Do HTML escapes according to DO_HTML_ESCAPE. Needed in
4195 cm_printindex, q.v. */
4198 maybe_escaped_expansion (char *str, int implicit_code, int do_html_escape)
4202 /* Inhibit indentation and filling, so that extra newlines
4203 are not added to the expansion. (This is undesirable if
4204 we write the expanded text to macro_expansion_output_stream.) */
4205 int saved_filling_enabled = filling_enabled;
4206 int saved_indented_fill = indented_fill;
4207 int saved_no_indent = no_indent;
4208 int saved_escape_html = escape_html;
4210 filling_enabled = 0;
4213 escape_html = do_html_escape;
4216 result = full_expansion (str, implicit_code);
4218 filling_enabled = saved_filling_enabled;
4219 indented_fill = saved_indented_fill;
4220 no_indent = saved_no_indent;
4221 escape_html = saved_escape_html;
4228 /* Expand STR (or @code{STR} if IMPLICIT_CODE is nonzero). No change to
4229 any formatting parameters -- filling, indentation, html escapes,
4230 etc., are not reset. Always returned in new memory. */
4233 full_expansion (char *str, int implicit_code)
4238 /* Inhibit any real output. */
4239 int start = output_paragraph_offset;
4240 int saved_paragraph_is_open = paragraph_is_open;
4242 /* More output state to save. */
4243 int saved_meta_pos = meta_char_pos;
4244 int saved_last_char = last_inserted_character;
4245 int saved_last_nl = last_char_was_newline;
4247 /* If we are called in the middle of processing a command, we need
4248 to dup and save the global variable `command' (which holds the
4249 name of this command), since the recursive reader loop will free
4250 it from under our feet if it finds any macros in STR. */
4251 char *saved_command = command ? xstrdup (command) : NULL;
4253 inhibit_output_flushing ();
4254 paragraph_is_open = 1;
4255 if (strlen (str) > (implicit_code
4256 ? EXECUTE_STRING_MAX - 1 - sizeof("@code{}")
4257 : EXECUTE_STRING_MAX - 1))
4258 line_error (_("`%.40s...' is too long for expansion; not expanded"), str);
4260 execute_string (implicit_code ? "@code{%s}" : "%s", str);
4261 uninhibit_output_flushing ();
4263 /* Copy the expansion from the buffer. */
4264 length = output_paragraph_offset - start;
4265 result = xmalloc (1 + length);
4266 memcpy (result, (char *) (output_paragraph + start), length);
4269 /* Pretend it never happened. */
4270 free_and_clear (&command);
4271 command = saved_command;
4273 output_paragraph_offset = start;
4274 paragraph_is_open = saved_paragraph_is_open;
4276 meta_char_pos = saved_meta_pos;
4277 last_inserted_character = saved_last_char;
4278 last_char_was_newline = saved_last_nl;
4284 /* Return text (info) expansion of STR no matter what the current output
4288 text_expansion (char *str)
4291 int save_html = html;
4293 int save_docbook = docbook;
4298 ret = expansion (str, 0);
4301 docbook = save_docbook;
4307 /* Set the paragraph indentation variable to the value specified in STRING.
4309 `asis': Don't change existing indentation.
4310 `none': Remove existing indentation.
4311 NUM: Indent NUM spaces at the starts of paragraphs.
4312 If NUM is zero, we assume `none'.
4313 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
4315 set_paragraph_indent (char *string)
4317 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
4318 paragraph_start_indent = 0;
4319 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
4320 paragraph_start_indent = -1;
4323 if (sscanf (string, "%d", ¶graph_start_indent) != 1)
4327 if (paragraph_start_indent == 0)
4328 paragraph_start_indent = -1;
4335 /* Translate MSGID according to the document language (@documentlanguage
4336 value or --document-language), rather than the current locale
4337 (LANGUAGE/LC_ALL/LANG). This code is from the get_title function in
4338 gettext. (xsetenv and unsetenv come from the gnulib xsetenv module.) */
4341 getdocumenttext (const char *msgid)
4343 /* The original get_title also saves, sets, and restores
4344 OUTPUT_CHARSET, so that the translation will be given in
4345 the proper encoding (via canonical_locale_charset). But defining
4346 that function ends up pulling a whole lot of subsidiary functions.
4347 Not sure how to handle it; skip the whole thing for now. */
4352 #ifdef HAVE_SETLOCALE
4356 /* Save LC_ALL, LANGUAGE environment variables. */
4358 tmp = getenv ("LC_ALL");
4359 old_LC_ALL = (tmp != NULL ? xstrdup (tmp) : NULL);
4361 tmp = getenv ("LANGUAGE");
4362 old_LANGUAGE = (tmp != NULL ? xstrdup (tmp) : NULL);
4364 xsetenv ("LC_ALL", document_language, 1);
4365 unsetenv ("LANGUAGE");
4367 #ifdef HAVE_SETLOCALE
4368 old_locale = xstrdup (setlocale (LC_ALL, NULL));
4369 if (setlocale (LC_ALL, "") == NULL)
4370 /* Nonexistent locale. Use the original. */
4375 /* Fetch the translation. */
4376 result = gettext ((char *) msgid);
4379 /* Restore LC_ALL, LANGUAGE environment variables. */
4381 if (old_LC_ALL != NULL)
4382 xsetenv ("LC_ALL", old_LC_ALL, 1), free (old_LC_ALL);
4384 unsetenv ("LC_ALL");
4386 if (old_LANGUAGE != NULL)
4387 xsetenv ("LANGUAGE", old_LANGUAGE, 1), free (old_LANGUAGE);
4389 unsetenv ("LANGUAGE");
4391 #ifdef HAVE_SETLOCALE
4392 setlocale (LC_ALL, old_locale);
4396 return (char *) result;