1 /* makeinfo -- convert Texinfo source into other formats.
2 $Id: makeinfo.c,v 1.205 2002/03/28 16:33:48 karl Exp $
4 Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 01, 02
5 Free Software Foundation, Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 Makeinfo was authored by Brian Fox (bfox@ai.mit.edu). */
26 #define COMPILING_MAKEINFO
33 #include "insertion.h"
39 /* You can change some of the behavior of Makeinfo by changing the
42 /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
43 appear within an @table, @ftable, or @itemize environment to have
44 standard paragraph indentation. Without this, such paragraphs have
45 no starting indentation. */
46 /* #define INDENT_PARAGRAPHS_IN_TABLE */
48 /* Define PARAGRAPH_START_INDENT to be the amount of indentation that
49 the first lines of paragraphs receive by default, where no other
50 value has been specified. Users can change this value on the command
51 line, with the --paragraph-indent option, or within the texinfo file,
52 with the @paragraphindent command. */
53 #define PARAGRAPH_START_INDENT 3
55 /* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
56 wish to appear between paragraphs. A value of 1 creates a single blank
57 line between paragraphs. Paragraphs are defined by 2 or more consecutive
58 newlines in the input file (i.e., one or more blank lines). */
59 #define DEFAULT_PARAGRAPH_SPACING 1
61 /* Global variables. */
63 /* The output file name. */
64 char *output_filename = NULL;
66 /* Name of the output file that the user elected to pass on the command line.
67 Such a name overrides any name found with the @setfilename command. */
68 char *command_output_filename = NULL;
69 static char *save_command_output_filename = NULL;
71 /* Flags which control initial output string for xrefs. */
75 #define INITIAL_PARAGRAPH_SPACE 5000
76 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
78 /* The amount of indentation to add at the starts of paragraphs.
79 0 means don't change existing indentation at paragraph starts.
80 > 0 is amount to indent new paragraphs by.
81 < 0 means indent to column zero by removing indentation if necessary.
83 This is normally zero, but some people prefer paragraph starts to be
84 somewhat more indented than paragraph bodies. A pretty value for
86 int paragraph_start_indent = PARAGRAPH_START_INDENT;
88 /* Indentation that is pending insertion. We have this for hacking lines
89 which look blank, but contain whitespace. We want to treat those as
91 int pending_indent = 0;
93 /* The index in our internal command table of the currently
97 /* A search string which is used to find the first @setfilename. */
98 char setfilename_search[] =
100 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
102 /* Values for calling handle_variable_internal (). */
108 /* Flags controlling the operation of the program. */
110 /* Default is to remove output if there were errors. */
113 /* Default is to notify users of bad choices. */
114 int print_warnings = 1;
116 /* Number of errors that we tolerate on a given fileset. */
117 int max_error_level = 100;
119 /* The actual last inserted character. Note that this may be something
120 other than NEWLINE even if last_char_was_newline is 1. */
121 int last_inserted_character = 0;
123 /* Nonzero means that a newline character has already been
124 inserted, so close_paragraph () should insert one less. */
125 int line_already_broken = 0;
127 /* When nonzero we have finished an insertion (see end_insertion ()) and we
128 want to ignore false continued paragraph closings. */
129 int insertion_paragraph_closed = 0;
131 /* Nonzero means attempt to make all of the lines have fill_column width. */
132 int do_justification = 0;
134 /* Nonzero means don't replace whitespace with in HTML mode. */
137 typedef struct brace_element
139 struct brace_element *next;
140 COMMAND_FUNCTION *proc;
143 int in_fixed_width_font;
146 BRACE_ELEMENT *brace_stack = NULL;
148 extern void do_multitable (), end_multitable ();
150 void push_node_filename (), pop_node_filename ();
151 void remember_error ();
152 void convert_from_stream (), convert_from_file (), convert_from_loaded_file ();
153 void init_internals (), init_paragraph (), init_brace_stack ();
154 void init_insertion_stack (), init_indices ();
155 void init_tag_table (), write_tag_table (), write_tag_table_internal ();
156 void validate_file (), validate_other_references (), split_file ();
157 void free_node_references (), handle_variable ();
158 void handle_variable_internal ();
159 void normalize_node_name ();
160 void add_anchor_name ();
161 void free_node_node_references (), remember_node_node_reference ();
163 char **get_brace_args ();
166 static int end_of_sentence_p ();
167 static void isolate_nodename ();
169 void remember_brace (), remember_brace_1 ();
170 void pop_and_call_brace (), discard_braces ();
171 void add_word (), add_char (), insert (), flush_output ();
172 void insert_string ();
173 void close_paragraph ();
174 void ignore_blank_line ();
175 void do_flush_right_indentation (), discard_insertions ();
176 void start_paragraph (), indent ();
177 void inhibit_output_flushing (), uninhibit_output_flushing ();
178 int set_paragraph_indent ();
179 int self_delimiting (), search_forward ();
180 int multitable_item (), number_of_node ();
181 extern void add_link (), add_escaped_anchor_name ();
183 void me_execute_string_keep_state ();
184 void maybe_update_execution_strings ();
186 extern char *escape_string ();
187 extern void insert_html_tag ();
188 extern void sectioning_html ();
189 extern void add_link ();
191 #if defined (VA_FPRINTF) && __STDC__
192 /* Unfortunately we must use prototypes if we are to use <stdarg.h>. */
193 void add_word_args (char *, ...);
194 void execute_string (char *, ...);
196 void add_word_args ();
197 void execute_string ();
198 #endif /* no prototypes */
200 /* Error handling. */
202 /* Number of errors encountered. */
203 int errors_printed = 0;
205 /* Print the last error gotten from the file system. */
215 /* Print an error message, and return false. */
217 #if defined (VA_FPRINTF) && __STDC__
218 error (char *format, ...)
220 error (format, va_alist)
231 VA_START (ap, format);
233 VA_FPRINTF (stderr, format, ap);
235 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
236 #endif /* not VA_FPRINTF */
242 /* Just like error (), but print the input file and line number as well. */
244 #if defined (VA_FPRINTF) && __STDC__
245 file_line_error (char *infile, int lno, char *format, ...)
247 file_line_error (infile, lno, format, va_alist)
259 fprintf (stderr, "%s:%d: ", infile, lno);
261 VA_START (ap, format);
263 VA_FPRINTF (stderr, format, ap);
265 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
266 #endif /* not VA_FPRINTF */
269 fprintf (stderr, ".\n");
272 /* Just like file_line_error (), but take the input file and the line
273 number from global variables. */
275 #if defined (VA_FPRINTF) && __STDC__
276 line_error (char *format, ...)
278 line_error (format, va_alist)
288 fprintf (stderr, "%s:%d: ", input_filename, line_number);
290 VA_START (ap, format);
292 VA_FPRINTF (stderr, format, ap);
294 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
295 #endif /* not VA_FPRINTF */
298 fprintf (stderr, ".\n");
302 #if defined (VA_FPRINTF) && __STDC__
303 warning (char *format, ...)
305 warning (format, va_alist)
316 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
318 VA_START (ap, format);
320 VA_FPRINTF (stderr, format, ap);
322 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
323 #endif /* not VA_FPRINTF */
326 fprintf (stderr, ".\n");
331 /* Remember that an error has been printed. If more than
332 max_error_level have been printed, then exit the program. */
337 if (max_error_level && (errors_printed > max_error_level))
339 fprintf (stderr, _("Too many errors! Gave up.\n"));
346 /* The other side of a malformed expression. */
350 line_error (_("Misplaced %c"), '}');
355 /* Display the version info of this invocation of Makeinfo. */
357 print_version_info ()
359 printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION);
362 /* If EXIT_VALUE is zero, print the full usage message to stdout.
363 Otherwise, just say to use --help for more info.
364 Then exit with EXIT_VALUE. */
370 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
373 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname);
377 Translate Texinfo source documentation to various other formats, by default\n\
378 Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
382 --error-limit=NUM quit after NUM errors (default %d).\n\
383 --force preserve output even if errors.\n\
384 --help display this help and exit.\n\
385 --no-validate suppress node cross-reference validation.\n\
386 --no-warn suppress warnings (but not errors).\n\
387 --reference-limit=NUM warn about at most NUM references (default %d).\n\
388 -v, --verbose explain what is being done.\n\
389 --version display version information and exit.\n"),
390 max_error_level, reference_warning_limit);
393 /* xgettext: no-wrap */
395 Output format selection (default is to produce Info):\n\
396 --docbook output DocBook rather than Info.\n\
397 --html output HTML rather than Info.\n\
398 --xml output XML (TexinfoML) rather than Info.\n\
402 General output options:\n\
403 -E, --macro-expand FILE output macro-expanded source to FILE.\n\
404 ignoring any @setfilename.\n\
405 --no-headers suppress node separators, Node: lines, and menus\n\
406 from Info output (thus producing plain text)\n\
407 or from HTML (thus producing shorter output);\n\
408 also, write to standard output by default.\n\
409 --no-split suppress splitting of Info or HTML output,\n\
410 generate only one output file.\n\
411 --number-sections output chapter and sectioning numbers.\n\
412 -o, --output=FILE output to FILE (directory if split HTML),\n\
416 Options for Info and plain text:\n\
417 --enable-encoding output accented and special characters in\n\
418 Info output based on @documentencoding.\n\
419 --fill-column=NUM break Info lines at NUM characters (default %d).\n\
420 --footnote-style=STYLE output footnotes in Info according to STYLE:\n\
421 `separate' to put them in their own node;\n\
422 `end' to put them at the end of the node\n\
423 in which they are defined (default).\n\
424 --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
425 If VAL is `none', do not indent; if VAL is\n\
426 `asis', preserve existing indentation.\n\
427 --split-size=NUM split Info files at size NUM (default %d).\n"),
428 fill_column, paragraph_start_indent,
434 Input file options:\n\
435 --commands-in-node-names allow @ commands in node names.\n\
436 -D VAR define the variable VAR, as with @set.\n\
437 -I DIR append DIR to the @include search path.\n\
438 -P DIR prepend DIR to the @include search path.\n\
439 -U VAR undefine the variable VAR, as with @clear.\n\
443 Conditional processing in input:\n\
444 --ifhtml process @ifhtml and @html even if not generating HTML.\n\
445 --ifinfo process @ifinfo even if not generating Info.\n\
446 --ifplaintext process @ifplaintext even if not generating plain text.\n\
447 --iftex process @iftex and @tex; implies --no-split.\n\
448 --no-ifhtml do not process @ifhtml and @html text.\n\
449 --no-ifinfo do not process @ifinfo text.\n\
450 --no-ifplaintext do not process @ifplaintext text.\n\
451 --no-iftex do not process @iftex and @tex 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\
463 makeinfo foo.texi write Info to foo's @setfilename\n\
464 makeinfo --html foo.texi write HTML to @setfilename\n\
465 makeinfo --xml foo.texi write XML to @setfilename\n\
466 makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\
467 makeinfo --no-headers foo.texi write plain text to standard output\n\
469 makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
470 makeinfo --number-sections foo.texi write Info with numbered sections\n\
471 makeinfo --no-split foo.texi write one Info file however big\n\
475 Email bug reports to bug-texinfo@gnu.org,\n\
476 general questions and discussion to help-texinfo@gnu.org.\n\
477 Texinfo home page: http://www.gnu.org/software/texinfo/"));
482 struct option long_options[] =
484 { "commands-in-node-names", 0, &expensive_validation, 1 },
485 { "docbook", 0, 0, 'd' },
486 { "enable-encoding", 0, &enable_encoding, 1 },
487 { "error-limit", 1, 0, 'e' },
488 { "fill-column", 1, 0, 'f' },
489 { "footnote-style", 1, 0, 's' },
490 { "force", 0, &force, 1 },
491 { "help", 0, 0, 'h' },
492 { "html", 0, 0, 'w' },
493 { "ifhtml", 0, &process_html, 1 },
494 { "ifinfo", 0, &process_info, 1 },
495 { "ifplaintext", 0, &process_plaintext, 1 },
496 { "iftex", 0, &process_tex, 1 },
497 { "macro-expand", 1, 0, 'E' },
498 { "no-headers", 0, &no_headers, 1 },
499 { "no-ifhtml", 0, &process_html, 0 },
500 { "no-ifinfo", 0, &process_info, 0 },
501 { "no-ifplaintext", 0, &process_plaintext, 0 },
502 { "no-iftex", 0, &process_tex, 0 },
503 { "no-number-footnotes", 0, &number_footnotes, 0 },
504 { "no-number-sections", 0, &number_sections, 0 },
505 { "no-pointer-validate", 0, &validating, 0 },
506 { "no-split", 0, &splitting, 0 },
507 { "no-validate", 0, &validating, 0 },
508 { "no-warn", 0, &print_warnings, 0 },
509 { "number-footnotes", 0, &number_footnotes, 1 },
510 { "number-sections", 0, &number_sections, 1 },
511 { "output", 1, 0, 'o' },
512 { "paragraph-indent", 1, 0, 'p' },
513 { "reference-limit", 1, 0, 'r' },
514 { "split-size", 1, 0, 'S'},
515 { "verbose", 0, &verbose_mode, 1 },
516 { "version", 0, 0, 'V' },
517 { "xml", 0, 0, 'x' },
521 /* For each file mentioned in the command line, process it, turning
522 Texinfo commands into wonderfully formatted output text. */
528 extern int errors_printed;
530 int reading_from_stdin = 0;
532 #ifdef HAVE_SETLOCALE
533 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
534 of the argument to @multicolumn. */
535 setlocale (LC_TIME, "");
536 setlocale (LC_MESSAGES, "");
537 setlocale (LC_CTYPE, "");
538 setlocale (LC_COLLATE, "");
541 /* Set the text message domain. */
542 bindtextdomain (PACKAGE, LOCALEDIR);
543 textdomain (PACKAGE);
545 /* Parse argument flags from the input line. */
546 while ((c = getopt_long (argc, argv, "D:de:E:f:hI:o:p:P:r:s:U:vV:wx",
547 long_options, &ind)) != EOF)
549 if (c == 0 && long_options[ind].flag == 0)
550 c = long_options[ind].val;
556 /* User specified variable to set or clear. */
557 handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
560 case 'd': /* --docbook */
566 case 'e': /* --error-limit */
567 if (sscanf (optarg, "%d", &max_error_level) != 1)
570 _("%s: %s arg must be numeric, not `%s'.\n"),
571 "--error-limit", progname, optarg);
576 case 'E': /* --macro-expand */
577 if (!macro_expansion_output_stream)
579 macro_expansion_filename = optarg;
580 macro_expansion_output_stream
581 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
582 if (!macro_expansion_output_stream)
583 error (_("Couldn't open macro expansion output `%s'"), optarg);
586 error (_("Cannot specify more than one macro expansion output"));
589 case 'f': /* --fill-column */
590 if (sscanf (optarg, "%d", &fill_column) != 1)
593 _("%s: %s arg must be numeric, not `%s'.\n"),
594 "--fill-column", progname, optarg);
599 case 'h': /* --help */
604 /* Append user-specified dir to include file path. */
605 if (!include_files_path)
606 include_files_path = xstrdup (".");
608 include_files_path = (char *)
609 xrealloc (include_files_path,
610 2 + strlen (include_files_path) + strlen (optarg));
611 strcat (include_files_path, PATH_SEP);
612 strcat (include_files_path, optarg);
615 case 'o': /* --output */
616 command_output_filename = xstrdup (optarg);
617 save_command_output_filename = command_output_filename;
620 case 'p': /* --paragraph-indent */
621 if (set_paragraph_indent (optarg) < 0)
624 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
631 /* Prepend user-specified include dir to include path. */
632 if (!include_files_path)
634 include_files_path = xstrdup (optarg);
635 include_files_path = xrealloc (include_files_path,
636 strlen (include_files_path) + 3); /* 3 for ":.\0" */
637 strcat (strcat (include_files_path, PATH_SEP), ".");
641 char *tmp = xstrdup (include_files_path);
642 include_files_path = xrealloc (include_files_path,
643 strlen (include_files_path) + strlen (optarg) + 2); /* 2 for ":\0" */
644 strcpy (include_files_path, optarg);
645 strcat (include_files_path, ":");
646 strcat (include_files_path, tmp);
651 case 'r': /* --reference-limit */
652 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
655 _("%s: %s arg must be numeric, not `%s'.\n"),
656 "--reference-limit", progname, optarg);
661 case 's': /* --footnote-style */
662 if (set_footnote_style (optarg) < 0)
665 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
669 footnote_style_preset = 1;
672 case 'S': /* --split-size */
673 if (sscanf (optarg, "%d", &split_size) != 1)
676 _("%s: %s arg must be numeric, not `%s'.\n"),
677 "--split-size", progname, optarg);
686 case 'V': /* --version */
687 print_version_info ();
689 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
690 There is NO warranty. You may redistribute this software\n\
691 under the terms of the GNU General Public License.\n\
692 For more information about these matters, see the files named COPYING.\n"),
697 case 'w': /* --html */
702 case 'x': /* --xml */
714 expensive_validation = 0;
718 /* Check to see if input is a file. If so, process that. */
719 if (!isatty (fileno (stdin)))
720 reading_from_stdin = 1;
723 fprintf (stderr, _("%s: missing file argument.\n"), progname);
730 if (html && splitting)
731 { /* --no-headers --no-split --html indicates confusion. */
733 "%s: --no-headers conflicts with --no-split for --html.\n",
738 /* --no-headers implies --no-split. */
741 /* If the user did not specify an output file, use stdout. */
742 if (!command_output_filename)
743 command_output_filename = xstrdup ("-");
746 if (process_info == -1)
747 { /* no explicit --[no-]ifinfo option, so we'll do @ifinfo
748 if we're generating info or (for compatibility) plain text. */
749 process_info = !html && !xml;
752 if (process_plaintext == -1)
753 { /* no explicit --[no-]ifplaintext option, so we'll do @ifplaintext
754 if we're generating plain text. */
755 process_plaintext = no_headers && !html && !xml;
759 print_version_info ();
761 /* Remaining arguments are file names of texinfo files.
762 Convert them, one by one. */
763 if (!reading_from_stdin)
765 while (optind != argc)
766 convert_from_file (argv[optind++]);
769 convert_from_stream (stdin, "stdin");
771 return errors_printed ? 2 : 0;
775 /* Hacking tokens and strings. */
777 /* Return the next token as a string pointer. We cons the string. */
784 /* If the first character to be read is self-delimiting, then that
785 is the command itself. */
786 character = curchar ();
787 if (self_delimiting (character))
791 if (character == '\n')
794 result = xstrdup (" ");
799 for (i = 0; ((input_text_offset != input_text_length)
800 && (character = curchar ())
801 && command_char (character));
802 i++, input_text_offset++);
803 result = xmalloc (i + 1);
804 memcpy (result, &input_text[input_text_offset - i], i);
809 /* Return nonzero if CHARACTER is self-delimiting. */
811 self_delimiting (character)
814 /* @; and @\ are not Texinfo commands, but they are listed here
815 anyway. I don't know why. --karl, 10aug96. */
816 return strchr ("~{|}`^\\@?=;:.-,*\'\" !\n\t", character) != NULL;
819 /* Clear whitespace from the front and end of string. */
824 int len = strlen (string);
830 for (x = 0; x < len; x++)
832 if (!cr_or_whitespace (string[x]))
834 strcpy (string, string + x);
838 len = strlen (string);
841 while (len > -1 && cr_or_whitespace (string[len]))
846 /* Bash STRING, replacing all whitespace with just one space. */
848 fix_whitespace (string)
851 char *temp = xmalloc (strlen (string) + 1);
852 int string_index = 0;
856 canon_white (string);
858 while (string[string_index])
860 c = temp[temp_index++] = string[string_index++];
862 if (c == ' ' || c == '\n' || c == '\t')
864 temp[temp_index - 1] = ' ';
865 while ((c = string[string_index]) && (c == ' ' ||
871 temp[temp_index] = 0;
872 strcpy (string, temp);
876 /* Discard text until the desired string is found. The string is
877 included in the discarded text. */
879 discard_until (string)
882 int temp = search_forward (string, input_text_offset);
884 int tt = (temp < 0) ? input_text_length : temp + strlen (string);
885 int from = input_text_offset;
887 /* Find out what line we are on. */
889 if (input_text[from++] == '\n')
894 input_text_offset = input_text_length - strlen (string);
896 if (strcmp (string, "\n") != 0)
898 line_error (_("Expected `%s'"), string);
903 input_text_offset = temp;
905 input_text_offset += strlen (string);
908 /* Read characters from the file until we are at MATCH.
909 Place the characters read into STRING.
910 On exit input_text_offset is after the match string.
911 Return the offset where the string starts. */
913 get_until (match, string)
914 char *match, **string;
916 int len, current_point, x, new_point, tem;
918 current_point = x = input_text_offset;
919 new_point = search_forward (match, input_text_offset);
922 new_point = input_text_length;
923 len = new_point - current_point;
925 /* Keep track of which line number we are at. */
926 tem = new_point + (strlen (match) - 1);
928 if (input_text[x++] == '\n')
931 *string = xmalloc (len + 1);
933 memcpy (*string, &input_text[current_point], len);
936 /* Now leave input_text_offset in a consistent state. */
937 input_text_offset = tem;
939 if (input_text_offset > input_text_length)
940 input_text_offset = input_text_length;
945 /* Replace input_text[FROM .. TO] with its expansion. */
947 replace_with_expansion (from, to)
951 unsigned xp_len, new_len;
952 char *old_input = input_text;
953 unsigned raw_len = *to - from;
956 /* The rest of the code here moves large buffers, so let's
957 not waste time if the input cannot possibly expand
958 into anything. Unfortunately, we cannot avoid expansion
959 when we see things like @code etc., even if they only
960 asked for expansion of macros, since any Texinfo command
961 can be potentially redefined with a macro. */
962 if (only_macro_expansion &&
963 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
966 /* Get original string from input. */
967 str = xmalloc (raw_len + 1);
968 memcpy (str, input_text + from, raw_len);
971 /* We are going to relocate input_text, so we had better output
972 pending portion of input_text now, before the pointer changes. */
973 if (macro_expansion_output_stream && !executing_string
974 && !me_inhibit_expansion)
975 append_to_expansion_output (from);
978 xp = expansion (str, 0);
979 xp_len = strlen (xp);
982 /* Plunk the expansion into the middle of `input_text' --
983 which is terminated by a newline, not a null. Avoid
984 expensive move of the rest of the input if the expansion
985 has the same length as the original string. */
986 if (xp_len != raw_len)
988 new_len = from + xp_len + input_text_length - *to + 1;
989 if (executing_string)
990 { /* If we are in execute_string, we might need to update
991 the relevant element in the execution_strings[] array,
992 since it could have to be relocated from under our
993 feet. (input_text is reallocated here as well, if needed.) */
994 maybe_update_execution_strings (&input_text, new_len);
996 else if (new_len > input_text_length + 1)
997 /* Don't bother to realloc if we have enough space. */
998 input_text = xrealloc (input_text, new_len);
1000 memmove (input_text + from + xp_len,
1001 input_text + *to, input_text_length - *to + 1);
1003 *to += xp_len - raw_len;
1004 /* Since we change input_text_length here, the comparison above
1005 isn't really valid, but it seems the worst that might happen is
1006 an extra xrealloc or two, so let's not worry. */
1007 input_text_length += xp_len - raw_len;
1009 memcpy (input_text + from, xp, xp_len);
1012 /* Synchronize the macro-expansion pointers with our new input_text. */
1013 if (input_text != old_input)
1014 forget_itext (old_input);
1015 if (macro_expansion_output_stream && !executing_string)
1016 remember_itext (input_text, from);
1019 /* Read characters from the file until we are at MATCH or end of line.
1020 Place the characters read into STRING. If EXPAND is nonzero,
1021 expand the text before looking for MATCH for those cases where
1022 MATCH might be produced by some macro. */
1024 get_until_in_line (expand, match, string)
1026 char *match, **string;
1028 int real_bottom = input_text_length;
1029 int limit = search_forward ("\n", input_text_offset);
1031 limit = input_text_length;
1033 /* Replace input_text[input_text_offset .. limit-1] with its expansion.
1034 This allows the node names and menu entries themselves to be
1035 constructed via a macro, as in:
1037 Together: \p\ & \q\.
1040 @node @foo{A,B}, next, prev, top
1042 Otherwise, the `,' separating the macro args A and B is taken as
1043 the node argument separator, so the node name is `@foo{A'. This
1044 expansion is only necessary on the first call, since we expand the
1048 replace_with_expansion (input_text_offset, &limit);
1051 real_bottom = input_text_length;
1052 input_text_length = limit;
1053 get_until (match, string);
1054 input_text_length = real_bottom;
1058 get_rest_of_line (expand, string)
1067 /* Don't expand non-macros in input, since we want them
1068 intact in the macro-expanded output. */
1069 only_macro_expansion++;
1070 get_until_in_line (1, "\n", &tem);
1071 only_macro_expansion--;
1072 *string = expansion (tem, 0);
1076 get_until_in_line (0, "\n", string);
1078 canon_white (*string);
1080 if (curchar () == '\n') /* as opposed to the end of the file... */
1083 input_text_offset++;
1088 /* Backup the input pointer to the previous character, keeping track
1089 of the current line number. */
1091 backup_input_pointer ()
1093 if (input_text_offset)
1095 input_text_offset--;
1096 if (curchar () == '\n')
1101 /* Read characters from the file until we are at MATCH or closing brace.
1102 Place the characters read into STRING. */
1104 get_until_in_braces (match, string)
1105 char *match, **string;
1109 int match_len = strlen (match);
1111 for (i = input_text_offset; i < input_text_length; i++)
1113 if (i < input_text_length - 1 && input_text[i] == '@')
1115 i++; /* skip commands like @, and @{ */
1118 else if (input_text[i] == '{')
1120 else if (input_text[i] == '}')
1123 /* If looking for a brace, don't stop at the interior brace,
1124 like after "baz" in "@foo{something @bar{baz} more}". */
1128 else if (input_text[i] == '\n')
1132 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1136 match_len = i - input_text_offset;
1137 temp = xmalloc (2 + match_len);
1138 memcpy (temp, input_text + input_text_offset, match_len);
1139 temp[match_len] = 0;
1140 input_text_offset = i;
1144 /* Converting a file. */
1146 /* Convert the file named by NAME. The output is saved on the file
1147 named as the argument to the @setfilename command. */
1148 static char *suffixes[] = {
1149 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1150 have "texinfo.txi" and "texinfo.tex" in the same directory, the
1151 former is used rather than the latter, due to file name truncation. */
1161 initialize_conversion ()
1168 /* This is used for splitting the output file and for doing section
1169 headings. It was previously initialized in `init_paragraph', but its
1170 use there loses with the `init_paragraph' calls done by the
1171 multitable code; the tag indices get reset to zero. */
1172 output_position = 0;
1175 typedef struct generic_list {
1176 struct generic_list *next;
1179 /* Reverse the chain of structures in LIST. Output the new head
1180 of the chain. You should always assign the output value of this
1181 function to something, or you will lose the chain. */
1187 GENERIC_LIST *prev = NULL;
1199 /* We read in multiples of 4k, simply because it is a typical pipe size
1201 #define READ_BUFFER_GROWTH (4 * 4096)
1203 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1204 source of the stream is named NAME. */
1206 convert_from_stream (stream, name)
1210 char *buffer = NULL;
1211 int buffer_offset = 0, buffer_size = 0;
1213 initialize_conversion ();
1215 /* Read until the end of the stream. This isn't strictly correct, since
1216 the texinfo input may end before the stream ends, but it is a quick
1217 working hueristic. */
1218 while (!feof (stream))
1222 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1224 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1226 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1234 buffer_offset += count;
1239 /* Set the globals to the new file. */
1240 input_text = buffer;
1241 input_text_length = buffer_offset;
1242 input_filename = xstrdup (name);
1243 node_filename = xstrdup (name);
1244 input_text_offset = 0;
1247 /* Not strictly necessary. This magic prevents read_token () from doing
1248 extra unnecessary work each time it is called (that is a lot of times).
1249 The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1250 input_text[input_text_length] = '\n';
1252 convert_from_loaded_file (name);
1256 convert_from_file (name)
1260 char *filename = xmalloc (strlen (name) + 50);
1262 initialize_conversion ();
1264 /* Try to load the file specified by NAME, concatenated with our
1265 various suffixes. Prefer files like `makeinfo.texi' to
1267 for (i = 0; suffixes[i]; i++)
1269 strcpy (filename, name);
1270 strcat (filename, suffixes[i]);
1272 if (find_and_load (filename))
1275 if (!suffixes[i][0] && strrchr (filename, '.'))
1277 fs_error (filename);
1290 input_filename = filename;
1292 convert_from_loaded_file (name);
1295 /* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
1296 "/foo/bar/baz/baz.html". This routine is called only if html && splitting.
1298 Split html output goes into the subdirectory of the toplevel
1299 filename, without extension. For example:
1300 @setfilename foo.info
1301 produces output in files foo/index.html, foo/second-node.html, ...
1303 But if the user said -o foo.whatever on the cmd line, then use
1304 foo.whatever unchanged. */
1307 insert_toplevel_subdirectory (output_filename)
1308 char *output_filename;
1310 char *dir, *subdir, *base, *basename, *p;
1313 static const char index_name[] = "index.html";
1314 const int index_len = sizeof (index_name) - 1;
1316 strcpy (buf, output_filename);
1317 dir = pathname_part (buf);
1318 base = filename_part (buf);
1319 basename = xstrdup (base); /* remember real @setfilename name */
1320 p = dir + strlen (dir) - 1;
1321 if (p > dir && IS_SLASH (*p))
1323 p = strrchr (base, '.');
1327 /* Split html output goes into subdirectory of toplevel name. */
1329 if (FILENAME_CMP (base, filename_part (dir)) != 0)
1331 if (save_command_output_filename
1332 && STREQ (output_filename, save_command_output_filename))
1333 subdir = basename; /* from user, use unchanged */
1335 subdir = base; /* implicit, omit suffix */
1338 free (output_filename);
1339 output_filename = xmalloc (strlen (dir) + 1
1340 + strlen (basename) + 1
1343 strcpy (output_filename, dir);
1345 strcat (output_filename, "/");
1346 strcat (output_filename, subdir);
1347 if (mkdir (output_filename, 0777) == -1 && errno != EEXIST
1348 /* output_filename might exist, but be a non-directory. */
1349 || (stat (output_filename, &st) == 0 && !S_ISDIR (st.st_mode)))
1350 { /* that failed, try subdir name with .html */
1351 strcpy (output_filename, dir);
1353 strcat (output_filename, "/");
1354 strcat (output_filename, basename);
1355 if (mkdir (output_filename, 0777) == -1)
1357 char *errmsg = strerror (errno);
1359 if ((errno == EEXIST
1364 && (stat (output_filename, &st) == 0 && !S_ISDIR (st.st_mode)))
1365 errmsg = _("File exists, but is not a directory");
1366 line_error (_("Can't create directory `%s': %s"),
1367 output_filename, errmsg);
1370 strcat (output_filename, "/");
1372 else if (strlen (subdir))
1373 strcat (output_filename, "/");
1374 strcat (output_filename, index_name);
1375 return output_filename;
1378 /* FIXME: this is way too hairy */
1380 convert_from_loaded_file (name)
1383 char *real_output_filename = NULL;
1385 remember_itext (input_text, 0);
1387 input_text_offset = 0;
1389 /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1391 if (looking_at ("\\input"))
1392 discard_until ("\n");
1394 /* Search this file looking for the special string which starts conversion.
1395 Once found, we may truly begin. */
1396 while (input_text_offset >= 0)
1399 search_forward (setfilename_search, input_text_offset);
1401 if (input_text_offset == 0
1402 || (input_text_offset > 0
1403 && input_text[input_text_offset -1] == '\n'))
1405 else if (input_text_offset > 0)
1406 input_text_offset++;
1409 if (input_text_offset < 0)
1411 if (!command_output_filename)
1413 #if defined (REQUIRE_SETFILENAME)
1414 error (_("No `%s' found in `%s'"), setfilename_search, name);
1417 command_output_filename = output_name_from_input_name (name);
1418 #endif /* !REQUIRE_SETFILENAME */
1422 int i, end_of_first_line;
1424 /* Find the end of the first line in the file. */
1425 for (i = 0; i < input_text_length - 1; i++)
1426 if (input_text[i] == '\n')
1429 end_of_first_line = i + 1;
1431 for (i = 0; i < end_of_first_line; i++)
1433 if ((input_text[i] == '\\') &&
1434 (strncmp (input_text + i + 1, "input", 5) == 0))
1436 input_text_offset = i;
1443 input_text_offset += strlen (setfilename_search);
1445 if (!command_output_filename)
1447 get_until ("\n", &output_filename); /* read rest of line */
1448 if (xml && !docbook)
1449 xml_begin_document (output_filename);
1451 { /* Change any extension to .html or .xml. */
1452 char *html_name, *directory_part, *basename_part, *temp;
1454 canon_white (output_filename);
1455 directory_part = pathname_part (output_filename);
1457 basename_part = filename_part (output_filename);
1459 /* Zap any existing extension. */
1460 temp = strrchr (basename_part, '.');
1464 /* Construct new filename. */
1465 html_name = xmalloc (strlen (directory_part)
1466 + strlen (basename_part) + 6);
1467 strcpy (html_name, directory_part);
1468 strcat (html_name, basename_part);
1469 strcat (html_name, html ? ".html" : ".xml");
1471 /* Replace name from @setfilename with the html name. */
1472 free (output_filename);
1473 output_filename = html_name;
1478 if (input_text_offset != -1)
1479 discard_until ("\n");
1481 input_text_offset = 0;
1483 real_output_filename = output_filename = command_output_filename;
1484 command_output_filename = NULL; /* for included files or whatever */
1487 canon_white (output_filename);
1488 toplevel_output_filename = xstrdup (output_filename);
1490 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1492 if (macro_expansion_filename
1493 && strcmp (macro_expansion_filename, "-") == 0)
1496 _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1498 macro_expansion_output_stream = NULL;
1500 real_output_filename = xstrdup (real_output_filename);
1501 output_stream = stdout;
1502 splitting = 0; /* Cannot split when writing to stdout. */
1506 if (html && splitting)
1508 if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
1509 || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
1512 output_filename = insert_toplevel_subdirectory (output_filename);
1513 real_output_filename = xstrdup (output_filename);
1515 else if (!real_output_filename)
1516 real_output_filename = expand_filename (output_filename, name);
1518 real_output_filename = xstrdup (real_output_filename);
1520 output_stream = fopen (real_output_filename, "w");
1523 set_current_output_filename (real_output_filename);
1526 printf (_("Making %s file `%s' from `%s'.\n"),
1531 output_filename, input_filename);
1533 if (output_stream == NULL)
1535 fs_error (real_output_filename);
1539 /* Make the displayable filename from output_filename. Only the base
1540 portion of the filename need be displayed. */
1541 flush_output (); /* in case there was no @bye */
1542 if (output_stream != stdout)
1543 pretty_output_filename = filename_part (output_filename);
1545 pretty_output_filename = xstrdup ("stdout");
1547 /* For this file only, count the number of newlines from the top of
1548 the file to here. This way, we keep track of line numbers for
1549 error reporting. Line_number starts at 1, since the user isn't
1554 while (temp != input_text_offset)
1555 if (input_text[temp++] == '\n')
1559 /* html fixxme: should output this as trailer on first page. */
1560 if (!no_headers && !html && !xml)
1561 add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
1562 output_filename, VERSION, input_filename);
1567 xml_end_document ();
1571 discard_insertions (0);
1573 flush_file_stack ();
1575 if (macro_expansion_output_stream)
1577 fclose (macro_expansion_output_stream);
1578 if (errors_printed && !force
1579 && strcmp (macro_expansion_filename, "-") != 0
1580 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1581 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1583 fprintf (stderr, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1584 progname, macro_expansion_filename);
1585 if (unlink (macro_expansion_filename) < 0)
1586 perror (macro_expansion_filename);
1592 output_pending_notes ();
1595 tag_table = (TAG_ENTRY *) reverse_list (tag_table);
1596 if (!no_headers && !html)
1603 add_word ("</body></html>\n");
1607 flush_output (); /* in case there was no @bye */
1608 if (output_stream != stdout)
1609 fclose (output_stream);
1611 /* If validating, then validate the entire file right now. */
1613 validate_file (tag_table);
1615 /* If we need to output the table of contents, do it now. */
1616 if (contents_filename || shortcontents_filename)
1619 if (splitting && !html && (!errors_printed || force))
1620 split_file (real_output_filename, split_size);
1621 else if (errors_printed
1623 && strcmp (real_output_filename, "-") != 0
1624 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1625 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1626 { /* If there were errors, and no --force, remove the output. */
1627 fprintf (stderr, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1628 progname, real_output_filename);
1629 if (unlink (real_output_filename) < 0)
1630 perror (real_output_filename);
1633 free (real_output_filename);
1637 free_and_clear (pointer)
1647 /* Initialize some state. */
1651 free_and_clear (&output_filename);
1652 free_and_clear (&command);
1653 free_and_clear (&input_filename);
1654 free_node_references ();
1655 free_node_node_references ();
1657 init_insertion_stack ();
1658 init_brace_stack ();
1659 current_node = NULL; /* sometimes already freed */
1664 non_top_node_seen = 0;
1671 free_and_clear (&output_paragraph);
1672 output_paragraph = xmalloc (paragraph_buffer_len);
1673 output_paragraph[0] = 0;
1674 output_paragraph_offset = 0;
1676 paragraph_is_open = 0;
1681 /* This is called from `reader_loop' when we are at the * beginning a
1685 handle_menu_entry ()
1689 /* Ugh, glean_node_from_menu wants to read the * itself. */
1690 input_text_offset--;
1692 /* Find node name in menu entry and save it in references list for
1693 later validation. Use followed_reference type for detailmenu
1694 references since we don't want to use them for default node pointers. */
1695 tem = glean_node_from_menu (1, in_detailmenu
1696 ? followed_reference : menu_reference);
1699 { /* Start a menu item with the cleaned-up line. Put an anchor
1700 around the start text (before `:' or the node name). */
1703 discard_until ("* ");
1705 /* The line number was already incremented in reader_loop when we
1706 saw the newline, and discard_until has now incremented again. */
1709 if (had_menu_commentary)
1711 add_word ("<ul>\n");
1712 had_menu_commentary = 0;
1715 else if (!in_paragraph && !paragraph_is_open)
1727 add_word ("<li><a");
1728 if (next_menu_item_number <= 9)
1730 add_word(" accesskey=");
1731 add_word_args("%d", next_menu_item_number);
1732 next_menu_item_number++;
1734 add_word (" href=\"");
1735 string = expansion (tem, 0);
1736 add_anchor_name (string, 1);
1740 /* The menu item may use macros, so expand them now. */
1741 only_macro_expansion++;
1742 get_until_in_line (1, ":", &string);
1743 only_macro_expansion--;
1744 execute_string ("%s", string); /* get escaping done */
1749 if (looking_at ("::"))
1750 discard_until (":");
1752 { /* discard the node name */
1753 get_until_in_line (0, ".", &string);
1756 input_text_offset++; /* discard the second colon or the period */
1759 else if (xml && tem)
1761 xml_start_menu_entry (tem);
1764 { /* For Info output, we can just use the input and the main case in
1765 reader_loop where we output what comes in. Just move off the *
1766 so the next time through reader_loop we don't end up back here. */
1768 input_text_offset += 2; /* undo the pointer back-up above. */
1775 /* Find the command corresponding to STRING. If the command is found,
1776 return a pointer to the data structure. Otherwise return -1. */
1778 get_command_entry (string)
1783 for (i = 0; command_table[i].name; i++)
1784 if (strcmp (command_table[i].name, string) == 0)
1785 return &command_table[i];
1787 /* This command is not in our predefined command table. Perhaps
1788 it is a user defined command. */
1789 for (i = 0; i < user_command_array_len; i++)
1790 if (user_command_array[i] &&
1791 (strcmp (user_command_array[i]->name, string) == 0))
1792 return user_command_array[i];
1794 /* We never heard of this command. */
1795 return (COMMAND *) -1;
1798 /* input_text_offset is right at the command prefix character.
1799 Read the next token to determine what to do. Return zero
1800 if there's no known command or macro after the prefix character. */
1805 int old_text_offset = input_text_offset++;
1807 free_and_clear (&command);
1808 command = read_token ();
1810 /* Check to see if this command is a macro. If so, execute it here. */
1814 def = find_macro (command);
1818 /* We disallow recursive use of a macro call. Inhibit the expansion
1819 of this macro during the life of its execution. */
1820 if (!(def->flags & ME_RECURSE))
1823 execute_macro (def);
1825 if (!(def->flags & ME_RECURSE))
1832 if (only_macro_expansion)
1834 /* Back up to the place where we were called, so the
1835 caller will have a chance to process this non-macro. */
1836 input_text_offset = old_text_offset;
1840 /* Perform alias expansion */
1841 command = alias_expand (command);
1843 if (enclosure_command (command))
1845 remember_brace (enclosure_expand);
1846 enclosure_expand (START, output_paragraph_offset, 0);
1850 entry = get_command_entry (command);
1851 if (entry == (COMMAND *)-1)
1853 line_error (_("Unknown command `%s'"), command);
1857 if (entry->argument_in_braces == BRACE_ARGS)
1858 remember_brace (entry->proc);
1859 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
1861 if (curchar () == '{')
1862 remember_brace (entry->proc);
1864 { /* No braces, so arg is next char. */
1866 int saved_offset = output_paragraph_offset;
1867 (*(entry->proc)) (START, output_paragraph_offset, 0);
1869 /* Possibilities left for the next character: @ (error), }
1870 (error), whitespace (skip) anything else (normal char). */
1875 line_error (_("Use braces to give a command as an argument to @%s"),
1881 /* Our caller will give the error message, because this }
1882 won't match anything. */
1887 input_text_offset++;
1888 (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
1893 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
1895 (*(entry->proc)) (START, output_paragraph_offset, 0);
1899 /* Okay, we are ready to start the conversion. Call the reader on
1900 some text, and fill the text as it is output. Handle commands by
1901 remembering things like open braces and the current file position on a
1902 stack, and when the corresponding close brace is found, you can call
1903 the function with the proper arguments. Although the filling isn't
1904 necessary for HTML, it should do no harm. */
1914 if (input_text_offset >= input_text_length)
1917 character = curchar ();
1919 /* If only_macro_expansion, only handle macros and leave
1920 everything else intact. */
1921 if (!only_macro_expansion && !in_fixed_width_font
1922 && (character == '\'' || character == '`')
1923 && input_text[input_text_offset + 1] == character)
1925 input_text_offset++;
1926 character = '"'; /* html fixxme */
1929 /* Convert --- to --. */
1930 if (!only_macro_expansion && character == '-')
1933 if (dash_count == 2 && !in_fixed_width_font)
1935 input_text_offset++;
1939 else if (dash_count > 0)
1942 /* If this is a whitespace character, then check to see if the line
1943 is blank. If so, advance to the carriage return. */
1944 if (!only_macro_expansion && whitespace (character))
1946 int i = input_text_offset + 1;
1948 while (i < input_text_length && whitespace (input_text[i]))
1951 if (i == input_text_length || input_text[i] == '\n')
1953 if (i == input_text_length)
1956 input_text_offset = i;
1957 character = curchar ();
1961 if (character == '\n')
1966 case '*': /* perhaps we are at a menu */
1967 /* We used to check for this in the \n case but an @c in a
1968 menu swallows its newline, so check here instead. */
1969 if (!only_macro_expansion && in_menu
1970 && input_text_offset + 1 < input_text_length
1971 && input_text[input_text_offset-1] == '\n')
1972 handle_menu_entry ();
1974 { /* Duplicate code from below, but not worth twisting the
1975 fallthroughs to get down there. */
1976 add_char (character);
1977 input_text_offset++;
1981 /* Escapes for HTML unless we're outputting raw HTML. Do
1982 this always, even if SGML rules don't require it since
1983 that's easier and safer for non-conforming browsers. */
1985 if (html && escape_html)
1988 add_char (character);
1989 input_text_offset++;
1993 if (html && escape_html)
1996 xml_insert_entity ("lt");
1998 add_char (character);
1999 input_text_offset++;
2003 if (html && escape_html)
2006 xml_insert_entity ("gt");
2008 add_char (character);
2009 input_text_offset++;
2012 case COMMAND_PREFIX: /* @ */
2013 if (read_command () || !only_macro_expansion)
2016 /* FALLTHROUGH (usually) */
2018 /* Special case. We're not supposed to see this character by itself.
2019 If we do, it means there is a syntax error in the input text.
2020 Report the error here, but remember this brace on the stack so
2021 we can ignore its partner. */
2022 if (!only_macro_expansion)
2024 if (!STREQ (command, "math"))
2026 line_error (_("Misplaced %c"), '{');
2027 remember_brace (misplaced_brace);
2030 { /* We don't mind `extra' braces inside @math. */
2031 extern void cm_no_op ();
2032 remember_brace (cm_no_op);
2034 /* remember_brace advances input_text_offset. */
2038 /* FALLTHROUGH (usually) */
2040 if (!only_macro_expansion)
2042 pop_and_call_brace ();
2043 input_text_offset++;
2047 /* FALLTHROUGH (usually) */
2049 add_char (character);
2050 input_text_offset++;
2053 if (macro_expansion_output_stream && !only_macro_expansion)
2054 maybe_write_itext (input_text, input_text_offset);
2064 remember_brace (proc)
2065 COMMAND_FUNCTION *proc;
2067 if (curchar () != '{')
2068 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command);
2070 input_text_offset++;
2071 remember_brace_1 (proc, output_paragraph_offset);
2074 /* Remember the current output position here. Save PROC
2075 along with it so you can call it later. */
2077 remember_brace_1 (proc, position)
2078 COMMAND_FUNCTION *proc;
2081 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
2082 new->next = brace_stack;
2084 new->command = command ? xstrdup (command) : "";
2085 new->pos = position;
2086 new->line = line_number;
2087 new->in_fixed_width_font = in_fixed_width_font;
2091 /* Pop the top of the brace stack, and call the associated function
2092 with the args END and POS. */
2094 pop_and_call_brace ()
2096 if (brace_stack == NULL)
2098 line_error (_("Unmatched }"));
2103 BRACE_ELEMENT *temp;
2105 int pos = brace_stack->pos;
2106 COMMAND_FUNCTION *proc = brace_stack->proc;
2107 in_fixed_width_font = brace_stack->in_fixed_width_font;
2109 /* Reset current command, so the proc can know who it is. This is
2110 used in cm_accent. */
2111 command = brace_stack->command;
2113 temp = brace_stack->next;
2117 (*proc) (END, pos, output_paragraph_offset);
2121 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2123 adjust_braces_following (here, amount)
2126 BRACE_ELEMENT *stack = brace_stack;
2130 if (stack->pos >= here)
2131 stack->pos += amount;
2132 stack = stack->next;
2136 /* Return the string which invokes PROC; a pointer to a function.
2137 Always returns the first function in the command table if more than
2138 one matches PROC. */
2140 find_proc_name (proc)
2141 COMMAND_FUNCTION *proc;
2145 for (i = 0; command_table[i].name; i++)
2146 if (proc == command_table[i].proc)
2147 return command_table[i].name;
2148 return _("NO_NAME!");
2151 /* You call discard_braces () when you shouldn't have any braces on the stack.
2152 I used to think that this happens for commands that don't take arguments
2153 in braces, but that was wrong because of things like @code{foo @@}. So now
2154 I only detect it at the beginning of nodes. */
2163 if (brace_stack->proc != misplaced_brace)
2167 proc_name = find_proc_name (brace_stack->proc);
2168 file_line_error (input_filename, brace_stack->line,
2169 _("%c%s missing close brace"), COMMAND_PREFIX,
2171 pop_and_call_brace ();
2175 BRACE_ELEMENT *temp;
2176 temp = brace_stack->next;
2184 get_char_len (character)
2187 /* Return the printed length of the character. */
2193 len = (output_column + 8) & 0xf7;
2194 if (len > fill_column)
2195 len = fill_column - output_column;
2197 len = len - output_column;
2201 len = fill_column - output_column;
2205 /* ASCII control characters appear as two characters in the output
2206 (e.g., ^A). But characters with the high bit set are just one
2207 on suitable terminals, so don't count them as two for line
2208 breaking purposes. */
2209 if (0 <= character && character < ' ')
2218 #if defined (VA_FPRINTF) && __STDC__
2219 add_word_args (char *format, ...)
2221 add_word_args (format, va_alist)
2226 char buffer[2000]; /* xx no fixed limits */
2231 VA_START (ap, format);
2233 VA_SPRINTF (buffer, format, ap);
2235 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2236 #endif /* not VA_SPRINTF */
2241 /* Add STRING to output_paragraph. */
2247 add_char (*string++);
2250 /* Like add_word, but inhibits conversion of whitespace into .
2251 Use this to output HTML directives with embedded blanks, to make
2254 add_html_elt (string)
2262 /* Add the character to the current paragraph. If filling_enabled is
2263 nonzero, then do filling as well. */
2265 add_char (character)
2270 xml_add_char (character);
2274 /* If we are avoiding outputting headers, and we are currently
2275 in a menu, then simply return. But if we're only expanding macros,
2276 then we're being called from glean_node_from_menu to try to
2277 remember a menu reference, and we need that so we can do defaulting. */
2278 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2281 /* If we are adding a character now, then we don't have to
2282 ignore close_paragraph () calls any more. */
2283 if (must_start_paragraph && character != '\n')
2285 must_start_paragraph = 0;
2286 line_already_broken = 0; /* The line is no longer broken. */
2287 if (current_indent > output_column)
2289 indent (current_indent - output_column);
2290 output_column = current_indent;
2294 if (non_splitting_words
2295 && !(html && in_html_elt)
2296 && strchr (" \t\n", character))
2298 if (html || docbook)
2299 { /* Seems cleaner to use than an 8-bit char. */
2304 character = META (' '); /* unmeta-d in flush_output */
2307 insertion_paragraph_closed = 0;
2312 if (!filling_enabled && ! (html && (in_menu || in_detailmenu)))
2316 if (force_flush_right)
2319 /* Hack to force single blank lines out in this mode. */
2325 if (!no_indent && paragraph_is_open)
2326 indent (output_column = current_indent);
2329 else if (end_of_sentence_p ())
2330 /* CHARACTER is newline, and filling is enabled. */
2334 last_inserted_character = character;
2337 if (last_char_was_newline)
2340 last_char_was_newline++;
2346 last_char_was_newline = 1;
2355 default: /* not at newline */
2357 int len = get_char_len (character);
2358 int suppress_insert = 0;
2360 if ((character == ' ') && (last_char_was_newline))
2362 if (!paragraph_is_open)
2369 /* This is sad, but it seems desirable to not force any
2370 particular order on the front matter commands. This way,
2371 the document can do @settitle, @documentlanguage, etc, in
2372 any order and with any omissions, and we'll still output
2373 the html <head> `just in time'. */
2374 if (!executing_string && html && !html_output_head_p)
2375 html_output_head ();
2377 if (!paragraph_is_open)
2380 /* If the paragraph is supposed to be indented a certain
2381 way, then discard all of the pending whitespace.
2382 Otherwise, we let the whitespace stay. */
2383 if (!paragraph_start_indent)
2384 indent (pending_indent);
2387 /* This horrible kludge of checking for a < prevents <p>
2388 from being inserted when we already have html markup
2389 starting a paragraph, as with <ul> and <h1> and the like. */
2390 if (html && escape_html && character != '<'
2391 && (!in_fixed_width_font || in_menu || in_detailmenu))
2393 insert_string ("<p>");
2395 adjust_braces_following (0, 3); /* adjust for <p> */
2399 output_column += len;
2400 if (output_column > fill_column)
2402 if (filling_enabled && !html)
2404 int temp = output_paragraph_offset;
2405 while (--temp > 0 && output_paragraph[temp] != '\n')
2407 /* If we have found a space, we have the place to break
2409 if (output_paragraph[temp] == ' ')
2411 /* Remove trailing whitespace from output. */
2412 while (temp && whitespace (output_paragraph[temp - 1]))
2415 /* If we went back all the way to the newline of the
2416 preceding line, it probably means that the word we
2417 are adding is itself wider than the space that the
2418 indentation and the fill_column let us use. In
2419 that case, do NOT insert another newline, since it
2420 won't help. Just indent to current_indent and
2421 leave it alone, since that's the most we can do. */
2422 if (temp && output_paragraph[temp - 1] != '\n')
2423 output_paragraph[temp++] = '\n';
2425 /* We have correctly broken the line where we want
2426 to. What we don't want is spaces following where
2427 we have decided to break the line. We get rid of
2434 if (t1 == output_paragraph_offset)
2436 if (whitespace (character))
2437 suppress_insert = 1;
2440 if (!whitespace (output_paragraph[t1]))
2446 adjust_braces_following (temp, (- (t1 - temp)));
2447 strncpy ((char *) &output_paragraph[temp],
2448 (char *) &output_paragraph[t1],
2449 (output_paragraph_offset - t1));
2450 output_paragraph_offset -= (t1 - temp);
2454 /* Filled, but now indent if that is right. */
2455 if (indented_fill && current_indent > 0)
2457 int buffer_len = ((output_paragraph_offset - temp)
2459 char *temp_buffer = xmalloc (buffer_len);
2460 int indentation = 0;
2462 /* We have to shift any markers that are in
2463 front of the wrap point. */
2464 adjust_braces_following (temp, current_indent);
2466 while (current_indent > 0 &&
2467 indentation != current_indent)
2468 temp_buffer[indentation++] = ' ';
2470 memcpy ((char *) &temp_buffer[current_indent],
2471 (char *) &output_paragraph[temp],
2472 buffer_len - current_indent);
2474 if (output_paragraph_offset + buffer_len
2475 >= paragraph_buffer_len)
2477 unsigned char *tt = xrealloc
2479 (paragraph_buffer_len += buffer_len));
2480 output_paragraph = tt;
2482 memcpy ((char *) &output_paragraph[temp],
2483 temp_buffer, buffer_len);
2484 output_paragraph_offset += current_indent;
2488 while (temp < output_paragraph_offset)
2490 get_char_len (output_paragraph[temp++]);
2491 output_column += len;
2498 if (!suppress_insert)
2501 last_inserted_character = character;
2503 last_char_was_newline = 0;
2504 line_already_broken = 0;
2509 /* Add a character and store its position in meta_char_pos. */
2511 add_meta_char (character)
2514 meta_char_pos = output_paragraph_offset;
2515 add_char (character);
2518 /* Insert CHARACTER into `output_paragraph'. */
2523 output_paragraph[output_paragraph_offset++] = character;
2524 if (output_paragraph_offset == paragraph_buffer_len)
2527 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2531 /* Insert the null-terminated string STRING into `output_paragraph'. */
2533 insert_string (string)
2541 /* Sentences might have these characters after the period (or whatever). */
2542 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2545 /* Return true if at an end-of-sentence character, possibly followed by
2546 post-sentence punctuation to ignore. */
2548 end_of_sentence_p ()
2550 int loc = output_paragraph_offset - 1;
2552 /* If nothing has been output, don't check output_paragraph[-1]. */
2556 /* A post-sentence character that is at meta_char_pos is not really
2557 a post-sentence character; it was produced by a markup such as
2558 @samp. We don't want the period inside @samp to be treated as a
2561 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
2563 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
2567 /* Remove upto COUNT characters of whitespace from the
2568 the current output line. If COUNT is less than zero,
2569 then remove until none left. */
2571 kill_self_indent (count)
2574 /* Handle infinite case first. */
2578 while (output_paragraph_offset)
2580 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2581 output_paragraph_offset--;
2588 while (output_paragraph_offset && count--)
2589 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2590 output_paragraph_offset--;
2596 /* Nonzero means do not honor calls to flush_output (). */
2597 static int flushing_ignored = 0;
2599 /* Prevent calls to flush_output () from having any effect. */
2601 inhibit_output_flushing ()
2606 /* Allow calls to flush_output () to write the paragraph data. */
2608 uninhibit_output_flushing ()
2618 if (!output_paragraph_offset || flushing_ignored)
2621 for (i = 0; i < output_paragraph_offset; i++)
2623 /* If we turned on the 8th bit for a space inside @w, turn it
2624 back off for output. This might be problematic, since the
2625 0x80 character may be used in 8-bit character sets. Sigh.
2626 In any case, don't do this for HTML, since the nbsp character
2627 is valid input and must be passed along to the browser. */
2628 if (!html && (output_paragraph[i] & meta_character_bit))
2630 int temp = UNMETA (output_paragraph[i]);
2632 output_paragraph[i] &= 0x7f;
2636 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2638 output_position += output_paragraph_offset;
2639 output_paragraph_offset = 0;
2643 /* How to close a paragraph controlling the number of lines between
2644 this one and the last one. */
2646 /* Paragraph spacing is controlled by this variable. It is the number of
2647 blank lines that you wish to appear between paragraphs. A value of
2648 1 creates a single blank line between paragraphs. */
2649 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2652 close_paragraph_with_lines (lines)
2655 int old_spacing = paragraph_spacing;
2656 paragraph_spacing = lines;
2658 paragraph_spacing = old_spacing;
2661 /* Close the current paragraph, leaving no blank lines between them. */
2663 close_single_paragraph ()
2665 close_paragraph_with_lines (0);
2668 /* Close a paragraph after an insertion has ended. */
2670 close_insertion_paragraph ()
2672 if (!insertion_paragraph_closed)
2674 /* Close the current paragraph, breaking the line. */
2675 close_single_paragraph ();
2677 /* Start a new paragraph, with the correct indentation for the now
2678 current insertion level (one above the one that we are ending). */
2681 /* Tell `close_paragraph' that the previous line has already been
2682 broken, so it should insert one less newline. */
2683 line_already_broken = 1;
2685 /* Tell functions such as `add_char' we've already found a newline. */
2686 ignore_blank_line ();
2690 /* If the insertion paragraph is closed already, then we are seeing
2691 two `@end' commands in a row. Note that the first one we saw was
2692 handled in the first part of this if-then-else clause, and at that
2693 time `start_paragraph' was called, partially to handle the proper
2694 indentation of the current line. However, the indentation level
2695 may have just changed again, so we may have to outdent the current
2696 line to the new indentation level. */
2697 if (current_indent < output_column)
2698 kill_self_indent (output_column - current_indent);
2701 insertion_paragraph_closed = 1;
2704 /* Close the currently open paragraph. */
2710 /* The insertion paragraph is no longer closed. */
2711 insertion_paragraph_closed = 0;
2713 if (paragraph_is_open && !must_start_paragraph)
2717 tindex = output_paragraph_offset;
2719 /* Back up to last non-newline/space character, forcing all such
2720 subsequent characters to be newlines. This isn't strictly
2721 necessary, but a couple of functions use the presence of a newline
2722 to make decisions. */
2723 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
2725 c = output_paragraph[tindex];
2727 if (c == ' '|| c == '\n')
2728 output_paragraph[tindex] = '\n';
2733 /* All trailing whitespace is ignored. */
2734 output_paragraph_offset = ++tindex;
2736 /* Break the line if that is appropriate. */
2737 if (paragraph_spacing >= 0)
2740 /* Add as many blank lines as is specified in `paragraph_spacing'. */
2741 if (!force_flush_right)
2743 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
2746 /* Don't need anything extra for HTML in usual case of no
2747 extra paragraph spacing. */
2749 insert_string ("<br>");
2753 /* If we are doing flush right indentation, then do it now
2754 on the paragraph (really a single line). */
2755 if (force_flush_right)
2756 do_flush_right_indentation ();
2759 paragraph_is_open = 0;
2764 ignore_blank_line ();
2767 /* Make the last line just read look as if it were only a newline. */
2769 ignore_blank_line ()
2771 last_inserted_character = '\n';
2772 last_char_was_newline = 1;
2775 /* Align the end of the text in output_paragraph with fill_column. */
2777 do_flush_right_indentation ()
2782 kill_self_indent (-1);
2784 if (output_paragraph[0] != '\n')
2786 output_paragraph[output_paragraph_offset] = 0;
2788 if (output_paragraph_offset < fill_column)
2792 if (fill_column >= paragraph_buffer_len)
2794 xrealloc (output_paragraph,
2795 (paragraph_buffer_len += fill_column));
2797 temp_len = strlen ((char *)output_paragraph);
2798 temp = xmalloc (temp_len + 1);
2799 memcpy (temp, (char *)output_paragraph, temp_len);
2801 for (i = 0; i < fill_column - output_paragraph_offset; i++)
2802 output_paragraph[i] = ' ';
2804 memcpy ((char *)output_paragraph + i, temp, temp_len);
2806 output_paragraph_offset = fill_column;
2807 adjust_braces_following (0, i);
2812 /* Begin a new paragraph. */
2816 /* First close existing one. */
2817 if (paragraph_is_open)
2820 /* In either case, the insertion paragraph is no longer closed. */
2821 insertion_paragraph_closed = 0;
2823 /* However, the paragraph is open! */
2824 paragraph_is_open = 1;
2826 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
2827 had to be called before we would allow any other paragraph operations
2828 to have an effect. */
2829 if (!must_start_paragraph)
2831 int amount_to_indent = 0;
2833 /* If doing indentation, then insert the appropriate amount. */
2836 if (inhibit_paragraph_indentation)
2838 amount_to_indent = current_indent;
2839 if (inhibit_paragraph_indentation < 0)
2840 inhibit_paragraph_indentation++;
2842 else if (paragraph_start_indent < 0)
2843 amount_to_indent = current_indent;
2845 amount_to_indent = current_indent + paragraph_start_indent;
2847 if (amount_to_indent >= output_column)
2849 amount_to_indent -= output_column;
2850 indent (amount_to_indent);
2851 output_column += amount_to_indent;
2856 must_start_paragraph = 0;
2859 /* Insert the indentation specified by AMOUNT. */
2867 /* For every START_POS saved within the brace stack which will be affected
2868 by this indentation, bump that start pos forward. */
2869 adjust_braces_following (output_paragraph_offset, amount);
2871 while (--amount >= 0)
2875 /* Search forward for STRING in input_text.
2876 FROM says where where to start. */
2878 search_forward (string, from)
2882 int len = strlen (string);
2884 while (from < input_text_length)
2886 if (strncmp (input_text + from, string, len) == 0)
2893 /* Cross references. */
2895 /* Return next comma-delimited argument, but do not cross a close-brace
2896 boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
2897 the entire brace-delimited argument list with its expansion before
2898 looking for the next comma. */
2900 get_xref_token (expand)
2907 int old_offset = input_text_offset;
2908 int old_lineno = line_number;
2910 get_until_in_braces ("}", &string);
2911 if (curchar () == '}') /* as opposed to end of text */
2912 input_text_offset++;
2913 if (input_text_offset > old_offset)
2915 int limit = input_text_offset;
2917 input_text_offset = old_offset;
2918 line_number = old_lineno;
2919 only_macro_expansion++;
2920 replace_with_expansion (input_text_offset, &limit);
2921 only_macro_expansion--;
2926 get_until_in_braces (",", &string);
2927 if (curchar () == ',')
2928 input_text_offset++;
2929 fix_whitespace (string);
2933 /* NOTE: If you wonder why the HTML output is produced with such a
2934 peculiar mix of calls to add_word and execute_string, here's the
2935 reason. get_xref_token (1) expands all macros in a reference, but
2936 any other commands, like @value, @@, etc., are left intact. To
2937 expand them, we need to run the arguments through execute_string.
2938 However, characters like <, &, > and others cannot be let into
2939 execute_string, because they will be escaped. See the mess? */
2941 /* Make a cross reference. */
2947 char *arg1 = get_xref_token (1); /* expands all macros in xref */
2948 char *arg2 = get_xref_token (0);
2949 char *arg3 = get_xref_token (0);
2950 char *arg4 = get_xref_token (0);
2951 char *arg5 = get_xref_token (0);
2954 /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
2955 first argument must never be blank." --rms.
2956 We hereby comply by disallowing such constructs. */
2958 line_error (_("First argument to cross-reference may not be empty"));
2962 if (!*arg4 && !*arg5)
2964 char *arg1_id = xml_id (arg1);
2967 xml_insert_element_with_attribute (XREFNODENAME, START,
2968 "linkend=\"%s\"", arg1_id);
2971 execute_string (arg2);
2972 xml_insert_element (XREFNODENAME, END);
2976 xml_insert_element_with_attribute (XREF, START,
2977 "linkend=\"%s\"", arg1_id);
2979 xml_pop_current_element ();
2985 xml_insert_element (XREF, START);
2986 xml_insert_element (XREFNODENAME, START);
2987 execute_string (arg1);
2988 xml_insert_element (XREFNODENAME, END);
2991 xml_insert_element (XREFINFONAME, START);
2992 execute_string (arg2);
2993 xml_insert_element (XREFINFONAME, END);
2997 xml_insert_element (XREFPRINTEDDESC, START);
2998 execute_string (arg3);
2999 xml_insert_element (XREFPRINTEDDESC, END);
3003 xml_insert_element (XREFINFOFILE, START);
3004 execute_string (arg4);
3005 xml_insert_element (XREFINFOFILE, END);
3009 xml_insert_element (XREFPRINTEDNAME, START);
3010 execute_string (arg5);
3011 xml_insert_element (XREFPRINTEDNAME, END);
3013 xml_insert_element (XREF, END);
3018 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
3021 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
3028 arg2 - reference name
3029 arg3 - title or topic (and reference name if arg2 is NULL)
3030 arg4 - info file name
3031 arg5 - printed manual title */
3046 /* html fixxme: revisit this; external node name not
3047 much use to us with numbered nodes. */
3048 add_html_elt ("<a href=");
3049 /* Note that if we are splitting, and the referenced
3050 tag is an anchor rather than a node, we will
3051 produce a reference to a file whose name is
3052 derived from the anchor name. However, only
3053 nodes create files, so we are referencing a
3054 non-existent file. cm_anchor, which see, deals
3055 with that problem. */
3057 execute_string ("\"../%s/", arg4);
3059 execute_string ("\"%s.html", arg4);
3060 /* Do not collapse -- to -, etc., in references. */
3061 in_fixed_width_font++;
3062 tem = expansion (arg1, 0); /* expand @-commands in node */
3063 in_fixed_width_font--;
3064 add_anchor_name (tem, 1);
3067 execute_string ("%s", ref_name);
3072 execute_string ("%s:", ref_name);
3073 in_fixed_width_font++;
3074 execute_string (" (%s)%s%s", arg4, arg1, px_ref_flag ? "." : "");
3075 in_fixed_width_font--;
3078 /* Free all of the arguments found. */
3079 if (arg1) free (arg1);
3080 if (arg2) free (arg2);
3081 if (arg3) free (arg3);
3082 if (arg4) free (arg4);
3083 if (arg5) free (arg5);
3087 remember_node_reference (arg1, line_number, followed_reference);
3093 add_html_elt ("<a href=\"");
3094 in_fixed_width_font++;
3095 tem = expansion (arg1, 0);
3096 in_fixed_width_font--;
3097 add_anchor_name (tem, 1);
3100 execute_string ("%s", *arg2 ? arg2 : arg3);
3105 execute_string ("%s:", *arg2 ? arg2 : arg3);
3106 in_fixed_width_font++;
3107 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
3108 in_fixed_width_font--;
3115 add_html_elt ("<a href=\"");
3116 in_fixed_width_font++;
3117 tem = expansion (arg1, 0);
3118 in_fixed_width_font--;
3119 add_anchor_name (tem, 1);
3122 execute_string ("%s", *arg2 ? arg2 : arg1);
3129 execute_string ("%s:", arg2);
3130 in_fixed_width_font++;
3131 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
3132 in_fixed_width_font--;
3136 in_fixed_width_font++;
3137 execute_string ("%s::", arg1);
3138 in_fixed_width_font--;
3143 /* Free all of the arguments found. */
3144 if (arg1) free (arg1);
3145 if (arg2) free (arg2);
3146 if (arg3) free (arg3);
3147 if (arg4) free (arg4);
3148 if (arg5) free (arg5);
3151 { /* Check to make sure that the next non-whitespace character is
3152 valid to follow an xref (so info readers can find the node
3153 names). `input_text_offset' is pointing at the "}" which ended
3154 the xref or ref command. */
3157 for (temp = input_text_offset + 1; temp < input_text_length; )
3159 if (cr_or_whitespace (input_text[temp]))
3163 if (input_text[temp] != '.' && input_text[temp] != ',')
3164 warning (_("`.' or `,' must follow cross reference, not %c"),
3182 /* Note that cm_xref isn't called with arg == END, which disables
3183 the code near the end of cm_xref that checks for `.' or `,'
3184 after the cross-reference. This is because @pxref{} generates
3185 the required character itself, when needed. */
3206 char *node = get_xref_token (1); /* expands all macros in inforef */
3207 char *pname = get_xref_token (0);
3208 char *file = get_xref_token (0);
3210 /* (see comments at cm_xref). */
3212 line_error (_("First argument to @inforef may not be empty"));
3214 if (xml && !docbook)
3216 xml_insert_element (INFOREF, START);
3217 xml_insert_element (INFOREFNODENAME, START);
3218 execute_string (node);
3219 xml_insert_element (INFOREFNODENAME, END);
3222 xml_insert_element (INFOREFREFNAME, START);
3223 execute_string (pname);
3224 xml_insert_element (INFOREFREFNAME, END);
3226 xml_insert_element (INFOREFINFONAME, START);
3227 execute_string (file);
3228 xml_insert_element (INFOREFINFONAME, END);
3230 xml_insert_element (INFOREF, END);
3236 add_word (_("see "));
3237 /* html fixxme: revisit this */
3238 add_html_elt ("<a href=");
3240 execute_string ("\"../%s/", file);
3242 execute_string ("\"%s.html", file);
3243 tem = expansion (node, 0);
3244 add_anchor_name (tem, 1);
3246 execute_string ("%s", *pname ? pname : tem);
3253 execute_string ("*note %s: (%s)%s", pname, file, node);
3255 execute_string ("*note (%s)%s::", file, node);
3264 /* A URL reference. */
3271 extern int printing_index;
3272 char *url = get_xref_token (1); /* expands all macros in uref */
3273 char *desc = get_xref_token (0);
3274 char *replacement = get_xref_token (0);
3278 xml_insert_element (UREF, START);
3279 xml_insert_element (UREFURL, START);
3280 execute_string (url);
3281 xml_insert_element (UREFURL, END);
3284 xml_insert_element (UREFDESC, START);
3285 execute_string (desc);
3286 xml_insert_element (UREFDESC, END);
3290 xml_insert_element (UREFREPLACEMENT, START);
3291 execute_string (replacement);
3292 xml_insert_element (UREFREPLACEMENT, END);
3294 xml_insert_element (UREF, END);
3297 { /* never need to show the url */
3298 add_html_elt ("<a href=");
3299 /* don't collapse `--' etc. in the url */
3300 in_fixed_width_font++;
3301 execute_string ("\"%s\"", url);
3302 in_fixed_width_font--;
3304 execute_string ("%s", *replacement ? replacement
3305 : (*desc ? desc : url));
3308 else if (*replacement) /* do not show the url */
3309 execute_string ("%s", replacement);
3310 else if (*desc) /* show both text and url */
3312 execute_string ("%s ", desc);
3313 in_fixed_width_font++;
3314 execute_string ("(%s)", url);
3315 in_fixed_width_font--;
3317 else /* no text at all, so have the url to show */
3319 in_fixed_width_font++;
3320 execute_string ("%s%s%s",
3321 printing_index ? "" : "`",
3323 printing_index ? "" : "'");
3324 in_fixed_width_font--;
3335 /* An email reference. */
3342 char *addr = get_xref_token (1); /* expands all macros in email */
3343 char *name = get_xref_token (0);
3347 xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
3349 execute_string (name);
3350 xml_insert_element (EMAIL, END);
3354 xml_insert_element (EMAIL, START);
3355 xml_insert_element (EMAILADDRESS, START);
3356 execute_string (addr);
3357 xml_insert_element (EMAILADDRESS, END);
3360 xml_insert_element (EMAILNAME, START);
3361 execute_string (name);
3362 xml_insert_element (EMAILNAME, END);
3364 xml_insert_element (EMAIL, END);
3368 add_html_elt ("<a href=");
3369 /* don't collapse `--' etc. in the address */
3370 in_fixed_width_font++;
3371 execute_string ("\"mailto:%s\"", addr);
3372 in_fixed_width_font--;
3374 execute_string ("%s", *name ? name : addr);
3379 execute_string ("%s%s", name, *name ? " " : "");
3380 in_fixed_width_font++;
3381 execute_string ("<%s>", addr);
3382 in_fixed_width_font--;
3392 /* An external image is a reference, kind of. The parsing is (not
3393 coincidentally) similar, anyway. */
3398 char *name_arg, *rest, *alt_arg, *ext_arg;
3403 name_arg = get_xref_token (1); /* expands all macros in image */
3404 /* We don't (yet) care about the next two args, but read them so they
3405 don't end up in the text. */
3406 rest = get_xref_token (0);
3409 rest = get_xref_token (0);
3412 alt_arg = get_xref_token (1); /* expands all macros in alt text */
3413 ext_arg = get_xref_token (0);
3417 char *fullname = xmalloc (strlen (name_arg)
3418 + (ext_arg && *ext_arg ? strlen (ext_arg) + 1 : 4) + 1);
3422 if (ext_arg && *ext_arg)
3424 sprintf (fullname, "%s.%s", name_arg, ext_arg);
3425 if (access (fullname, R_OK) != 0)
3427 line_error(_("@image file `%s' (for HTML) not readable: %s"),
3428 fullname, strerror (errno));
3434 sprintf (fullname, "%s.png", name_arg);
3435 if (access (fullname, R_OK) != 0)
3437 sprintf (fullname, "%s.jpg", name_arg);
3438 if (access (fullname, R_OK) != 0)
3440 line_error (_("No `%s.png' or `.jpg', and no extension supplied"),
3447 add_html_elt ("<img src=");
3448 add_word_args ("\"%s\"", fullname);
3449 add_html_elt (" alt=");
3450 add_word_args ("\"%s\">", (*alt_arg) ? alt_arg : fullname);
3452 else if (xml && docbook)
3453 xml_insert_docbook_image (name_arg);
3456 xml_insert_element (IMAGE, START);
3457 add_word (name_arg);
3458 xml_insert_element (IMAGE, END);
3461 { /* Try to open foo.txt. */
3463 strcpy (fullname, name_arg);
3464 strcat (fullname, ".txt");
3465 image_file = fopen (fullname, "r");
3469 int save_inhibit_indentation = inhibit_paragraph_indentation;
3470 int save_filling_enabled = filling_enabled;
3472 inhibit_paragraph_indentation = 1;
3473 filling_enabled = 0;
3474 last_char_was_newline = 0;
3476 /* Maybe we need to remove the final newline if the image
3477 file is only one line to allow in-line images. On the
3478 other hand, they could just make the file without a
3480 while ((ch = getc (image_file)) != EOF)
3483 inhibit_paragraph_indentation = save_inhibit_indentation;
3484 filling_enabled = save_filling_enabled;
3486 if (fclose (image_file) != 0)
3490 line_error (_("@image file `%s' (for text) unreadable: %s"),
3491 fullname, strerror (errno));
3497 line_error (_("@image missing filename argument"));
3509 /* A structure which contains `defined' variables. */
3510 typedef struct defines {
3511 struct defines *next;
3516 /* The linked list of `set' defines. */
3517 DEFINE *defines = NULL;
3519 /* Add NAME to the list of `set' defines. */
3527 for (temp = defines; temp; temp = temp->next)
3528 if (strcmp (name, temp->name) == 0)
3531 temp->value = xstrdup (value);
3535 temp = xmalloc (sizeof (DEFINE));
3536 temp->next = defines;
3537 temp->name = xstrdup (name);
3538 temp->value = xstrdup (value);
3542 /* Remove NAME from the list of `set' defines. */
3547 DEFINE *temp, *last;
3554 if (strcmp (temp->name, name) == 0)
3557 last->next = temp->next;
3559 defines = temp->next;
3571 /* Return the value of NAME. The return value is NULL if NAME is unset. */
3578 for (temp = defines; temp; temp = temp->next)
3579 if (strcmp (temp->name, name) == 0)
3585 /* Create a variable whose name appears as the first word on this line. */
3589 handle_variable (SET);
3592 /* Remove a variable whose name appears as the first word on this line. */
3596 handle_variable (CLEAR);
3602 handle_variable (IFSET);
3608 handle_variable (IFCLEAR);
3611 /* This command takes braces, but we parse the contents specially, so we
3612 don't use the standard brace popping code.
3614 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3615 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3616 it produces no output. */
3622 arglist = get_brace_args (0);
3626 if (array_len (arglist) > 1)
3628 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
3630 execute_string ("%s\n", arglist[2]);
3633 free_array (arglist);
3638 cm_value (arg, start_pos, end_pos)
3639 int arg, start_pos, end_pos;
3641 static int value_level = 0, saved_meta_pos = -1;
3643 /* All the text after @value{ upto the matching } will eventually
3644 disappear from output_paragraph, when this function is called
3645 with ARG == END. If the text produced until then sets
3646 meta_char_pos, we will need to restore it to the value it had
3647 before @value was seen. So we need to save the previous value
3648 of meta_char_pos here. */
3651 /* If we are already inside some outer @value, don't overwrite
3652 the value saved in saved_meta_pos. */
3654 saved_meta_pos = meta_char_pos;
3656 /* While the argument of @value is processed, we need to inhibit
3657 textual transformations like "--" into "-", since @set didn't
3658 do that when it grabbed the name of the variable. */
3659 in_fixed_width_font++;
3663 char *name = (char *) &output_paragraph[start_pos];
3665 output_paragraph[end_pos] = 0;
3666 name = xstrdup (name);
3667 value = set_p (name);
3668 output_column -= end_pos - start_pos;
3669 output_paragraph_offset = start_pos;
3671 /* Restore the previous value of meta_char_pos if the stuff
3672 inside this @value{} moved it. */
3673 if (saved_meta_pos == -1) /* can't happen inside @value{} */
3675 if (value_level == 1
3676 && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3678 meta_char_pos = saved_meta_pos;
3679 saved_meta_pos = -1;
3682 /* No need to decrement in_fixed_width_font, since before
3683 we are called with arg == END, the reader loop already
3684 popped the brace stack, which restored in_fixed_width_font,
3685 among other things. */
3688 execute_string ("%s", value);
3690 add_word_args (_("{No value for `%s'}"), name);
3696 /* Set, clear, or conditionalize based on ACTION. */
3698 handle_variable (action)
3703 get_rest_of_line (0, &name);
3704 /* If we hit the end of text in get_rest_of_line, backing up
3705 input pointer will cause the last character of the last line
3706 be pushed back onto the input, which is wrong. */
3707 if (input_text_offset < input_text_length)
3708 backup_input_pointer ();
3709 handle_variable_internal (action, name);
3714 handle_variable_internal (action, name)
3719 int delimiter, additional_text_present = 0;
3721 /* Only the first word of NAME is a valid tag. */
3724 while (*temp && (delimiter || !whitespace (*temp)))
3726 /* #if defined (SET_WITH_EQUAL) */
3727 if (*temp == '"' || *temp == '\'')
3729 if (*temp == delimiter)
3734 /* #endif SET_WITH_EQUAL */
3739 additional_text_present++;
3744 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3753 #if defined (SET_WITH_EQUAL)
3754 /* Allow a value to be saved along with a variable. The value is
3755 the text following an `=' sign in NAME, if any is present. */
3757 for (value = name; *value && *value != '='; value++);
3762 if (*value == '"' || *value == '\'')
3765 value[strlen (value) - 1] = 0;
3768 #else /* !SET_WITH_EQUAL */
3769 /* The VALUE of NAME is the remainder of the line sans
3771 if (additional_text_present)
3774 canon_white (value);
3778 #endif /* !SET_WITH_VALUE */
3790 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3791 read lines from the the file until we reach a matching
3792 "@end CONDITION". This means that we only take note of
3793 "@ifset/clear" and "@end" commands. */
3797 int orig_line_number = line_number;
3799 if (action == IFSET)
3800 strcpy (condition, "ifset");
3802 strcpy (condition, "ifclear");
3804 condition_len = strlen (condition);
3806 if ((action == IFSET && !set_p (name))
3807 || (action == IFCLEAR && set_p (name)))
3809 int level = 0, done = 0;
3811 while (!done && input_text_offset < input_text_length)
3813 char *freeable_line, *line;
3815 get_rest_of_line (0, &freeable_line);
3817 for (line = freeable_line; whitespace (*line); line++);
3819 if (*line == COMMAND_PREFIX &&
3820 (strncmp (line + 1, condition, condition_len) == 0))
3822 else if (strncmp (line, "@end", 4) == 0)
3824 char *cname = line + 4;
3827 while (*cname && whitespace (*cname))
3831 while (*temp && !whitespace (*temp))
3835 if (strcmp (cname, condition) == 0)
3845 free (freeable_line);
3849 file_line_error (input_filename, orig_line_number,
3850 _("Reached eof before matching @end %s"),
3853 /* We found the end of a false @ifset/ifclear. If we are
3854 in a menu, back up over the newline that ends the ifset,
3855 since that newline may also begin the next menu entry. */
3860 if (action == IFSET)
3861 begin_insertion (ifset);
3863 begin_insertion (ifclear);
3871 /* Execution of random text not in file. */
3874 char *string; /* The string buffer. */
3875 int size; /* The size of the buffer. */
3876 int in_use; /* Nonzero means string currently in use. */
3879 static EXECUTION_STRING **execution_strings = NULL;
3880 static int execution_strings_index = 0;
3881 static int execution_strings_slots = 0;
3884 get_execution_string (initial_size)
3888 EXECUTION_STRING *es = NULL;
3890 if (execution_strings)
3892 for (i = 0; i < execution_strings_index; i++)
3893 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
3895 es = execution_strings[i];
3902 if (execution_strings_index + 1 >= execution_strings_slots)
3904 execution_strings = xrealloc
3906 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
3907 for (; i < execution_strings_slots; i++)
3908 execution_strings[i] = NULL;
3911 execution_strings[execution_strings_index] =
3912 xmalloc (sizeof (EXECUTION_STRING));
3913 es = execution_strings[execution_strings_index];
3914 execution_strings_index++;
3921 if (initial_size > es->size)
3923 es->string = xrealloc (es->string, initial_size);
3924 es->size = initial_size;
3929 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
3930 entry in the execution_strings[] array and change the .STRING and
3931 .SIZE members of that entry as appropriate. */
3933 maybe_update_execution_strings (text, new_len)
3939 if (execution_strings)
3941 for (i = 0; i < execution_strings_index; i++)
3942 if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
3943 execution_strings[i]->string == *text)
3945 /* Don't ever shrink the string storage in execution_strings[]!
3946 execute_string assumes that it is always big enough to store
3947 every possible execution_string, and will break if that's
3948 not true. So we only enlarge the string storage if the
3949 current size isn't big enough. */
3950 if (execution_strings[i]->size < new_len)
3952 execution_strings[i]->string =
3953 *text = xrealloc (*text, new_len + 1);
3954 execution_strings[i]->size = new_len + 1;
3959 /* We should *never* end up here, since if we are inside
3960 execute_string, TEXT is always in execution_strings[]. */
3964 /* FIXME: this is an arbitrary limit. */
3965 #define EXECUTE_STRING_MAX 16*1024
3967 /* Execute the string produced by formatting the ARGs with FORMAT. This
3968 is like submitting a new file with @include. */
3970 #if defined (VA_FPRINTF) && __STDC__
3971 execute_string (char *format, ...)
3973 execute_string (format, va_alist)
3978 EXECUTION_STRING *es;
3984 es = get_execution_string (EXECUTE_STRING_MAX);
3985 temp_string = es->string;
3988 VA_START (ap, format);
3990 VA_SPRINTF (temp_string, format, ap);
3992 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
3993 #endif /* not VA_SPRINTF */
3997 input_text_offset = 0;
3998 input_text = temp_string;
3999 input_filename = xstrdup (input_filename);
4000 input_text_length = strlen (temp_string);
4004 free (input_filename);
4012 /* Return what would be output for STR (in newly-malloced memory), i.e.,
4013 expand Texinfo commands. If IMPLICIT_CODE is set, expand @code{STR}.
4014 This is generally used for short texts; filling, indentation, and
4015 html escapes are disabled. */
4018 expansion (str, implicit_code)
4024 /* Inhibit indentation and filling, so that extra newlines
4025 are not added to the expansion. (This is undesirable if
4026 we write the expanded text to macro_expansion_output_stream.) */
4027 int saved_filling_enabled = filling_enabled;
4028 int saved_indented_fill = indented_fill;
4029 int saved_no_indent = no_indent;
4030 int saved_escape_html = escape_html;
4032 filling_enabled = 0;
4037 result = full_expansion (str, implicit_code);
4039 filling_enabled = saved_filling_enabled;
4040 indented_fill = saved_indented_fill;
4041 no_indent = saved_no_indent;
4042 escape_html = saved_escape_html;
4048 /* Expand STR (or @code{STR} if IMPLICIT_CODE is nonzero). No change to
4049 any formatting parameters -- filling, indentation, html escapes,
4050 etc., are not reset. */
4053 full_expansion (str, implicit_code)
4060 /* Inhibit any real output. */
4061 int start = output_paragraph_offset;
4062 int saved_paragraph_is_open = paragraph_is_open;
4063 int saved_output_column = output_column;
4065 /* More output state to save. */
4066 int saved_meta_pos = meta_char_pos;
4067 int saved_last_char = last_inserted_character;
4068 int saved_last_nl = last_char_was_newline;
4070 /* If we are called in the middle of processing a command, we need
4071 to dup and save the global variable `command' (which holds the
4072 name of this command), since the recursive reader loop will free
4073 it from under our feet if it finds any macros in STR. */
4074 char *saved_command = command ? xstrdup (command) : NULL;
4076 inhibit_output_flushing ();
4077 paragraph_is_open = 1;
4078 if (strlen (str) > (implicit_code
4079 ? EXECUTE_STRING_MAX - 1 - sizeof("@code{}")
4080 : EXECUTE_STRING_MAX - 1))
4081 line_error (_("`%.40s...' is too long for expansion; not expanded"), str);
4083 execute_string (implicit_code ? "@code{%s}" : "%s", str);
4084 uninhibit_output_flushing ();
4086 /* Copy the expansion from the buffer. */
4087 length = output_paragraph_offset - start;
4088 result = xmalloc (1 + length);
4089 memcpy (result, (char *) (output_paragraph + start), length);
4092 /* Pretend it never happened. */
4093 free_and_clear (&command);
4094 command = saved_command;
4096 output_paragraph_offset = start;
4097 paragraph_is_open = saved_paragraph_is_open;
4098 output_column = saved_output_column;
4100 meta_char_pos = saved_meta_pos;
4101 last_inserted_character = saved_last_char;
4102 last_char_was_newline = saved_last_nl;
4108 /* Return text (info) expansion of STR no matter what the current output
4112 text_expansion (str)
4116 int save_html = html;
4121 ret = expansion (str, 0);
4129 /* Set the paragraph indentation variable to the value specified in STRING.
4131 `asis': Don't change existing indentation.
4132 `none': Remove existing indentation.
4133 NUM: Indent NUM spaces at the starts of paragraphs.
4134 If NUM is zero, we assume `none'.
4135 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
4137 set_paragraph_indent (string)
4140 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
4141 paragraph_start_indent = 0;
4142 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
4143 paragraph_start_indent = -1;
4146 if (sscanf (string, "%d", ¶graph_start_indent) != 1)
4150 if (paragraph_start_indent == 0)
4151 paragraph_start_indent = -1;