2 /* makeinfo -- convert Texinfo source into other formats.
3 $Id: makeinfo.c,v 1.195 2002/02/11 17:12:49 karl Exp $
5 Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 01, 02
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 2, or (at your option)
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, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 Makeinfo was authored by Brian Fox (bfox@ai.mit.edu). */
27 #define COMPILING_MAKEINFO
34 #include "insertion.h"
40 /* You can change some of the behavior of Makeinfo by changing the
43 /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
44 appear within an @table, @ftable, or @itemize environment to have
45 standard paragraph indentation. Without this, such paragraphs have
46 no starting indentation. */
47 /* #define INDENT_PARAGRAPHS_IN_TABLE */
49 /* Define PARAGRAPH_START_INDENT to be the amount of indentation that
50 the first lines of paragraphs receive by default, where no other
51 value has been specified. Users can change this value on the command
52 line, with the --paragraph-indent option, or within the texinfo file,
53 with the @paragraphindent command. */
54 #define PARAGRAPH_START_INDENT 3
56 /* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
57 wish to appear between paragraphs. A value of 1 creates a single blank
58 line between paragraphs. Paragraphs are defined by 2 or more consecutive
59 newlines in the input file (i.e., one or more blank lines). */
60 #define DEFAULT_PARAGRAPH_SPACING 1
62 /* Global variables. */
64 /* The output file name. */
65 char *output_filename = NULL;
67 /* Name of the output file that the user elected to pass on the command line.
68 Such a name overrides any name found with the @setfilename command. */
69 char *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);
375 /* xgettext: no-wrap */
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"));
380 /* xgettext: no-wrap */
383 --error-limit=NUM quit after NUM errors (default %d).\n\
384 --force preserve output even if errors.\n\
385 --help display this help and exit.\n\
386 --no-validate suppress node cross-reference validation.\n\
387 --no-warn suppress warnings (but not errors).\n\
388 --reference-limit=NUM warn about at most NUM references (default %d).\n\
389 -v, --verbose explain what is being done.\n\
390 --version display version information and exit.\n"),
391 max_error_level, reference_warning_limit);
394 /* xgettext: no-wrap */
396 Output format selection (default is to produce Info):\n\
397 --docbook output DocBook rather than Info.\n\
398 --html output HTML rather than Info.\n\
399 --no-headers output plain text, suppressing Info node\n\
400 separators and Node: lines; also, write to\n\
401 standard output without --output.\n\
402 --xml output XML (TexinfoML) rather than Info.\n\
406 General output options:\n\
407 -E, --macro-expand FILE output macro-expanded source to FILE.\n\
408 ignoring any @setfilename.\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\
415 /* xgettext: no-wrap */
417 Options for Info and plain text:\n\
418 --enable-encoding output accented and special characters in\n\
419 Info output based on @documentencoding.\n\
420 --fill-column=NUM break Info lines at NUM characters (default %d).\n\
421 --footnote-style=STYLE output footnotes in Info according to STYLE:\n\
422 `separate' to put them in their own node;\n\
423 `end' to put them at the end of the node\n\
424 in which they are defined (default).\n\
425 --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
426 If VAL is `none', do not indent; if VAL is\n\
427 `asis', preserve existing indentation.\n\
428 --split-size=NUM split Info files at size NUM (default %d).\n"),
429 fill_column, paragraph_start_indent,
434 /* xgettext: no-wrap */
436 Input file options:\n\
437 --commands-in-node-names allow @ commands in node names.\n\
438 -D VAR define the variable VAR, as with @set.\n\
439 -I DIR append DIR to the @include search path.\n\
440 -P DIR prepend DIR to the @include search path.\n\
441 -U VAR undefine the variable VAR, as with @clear.\n\
443 /* xgettext: no-wrap */
445 Conditional processing in input:\n\
446 --ifhtml process @ifhtml and @html even if not generating HTML.\n\
447 --ifinfo process @ifinfo text even when generating HTML.\n\
448 --iftex process @iftex and @tex text; implies --no-split.\n\
449 --no-ifhtml do not process @ifhtml and @html text.\n\
450 --no-ifinfo do not process @ifinfo text.\n\
451 --no-iftex do not process @iftex and @tex text.\n\
454 /* xgettext: no-wrap */
456 The defaults for the @if... conditionals depend on the output format:\n\
457 if generating HTML, --ifhtml is on and the others are off;\n\
458 if generating Info or plain text, --ifinfo is on and the others are off.\n\
461 /* xgettext: no-wrap */
464 makeinfo foo.texi write Info to foo's @setfilename\n\
465 makeinfo --html foo.texi write HTML to foo's @setfilename\n\
466 makeinfo --no-headers -o - foo.texi write plain text to standard output\n\
467 makeinfo --number-sections foo.texi write Info with numbered sections\n\
468 makeinfo --no-split foo.texi write one Info file however big\n\
471 /* xgettext: no-wrap */
473 Email bug reports to bug-texinfo@gnu.org,\n\
474 general questions and discussion to help-texinfo@gnu.org."));
478 struct option long_options[] =
480 { "commands-in-node-names", 0, &expensive_validation, 1 },
481 { "docbook", 0, 0, 'd' },
482 { "enable-encoding", 0, &enable_encoding, 1 },
483 { "error-limit", 1, 0, 'e' },
484 { "fill-column", 1, 0, 'f' },
485 { "footnote-style", 1, 0, 's' },
486 { "force", 0, &force, 1 },
487 { "help", 0, 0, 'h' },
488 { "html", 0, 0, 'w' },
489 { "ifhtml", 0, &process_html, 1 },
490 { "ifinfo", 0, &process_info, 1 },
491 { "iftex", 0, &process_tex, 1 },
492 { "macro-expand", 1, 0, 'E' },
493 { "no-headers", 0, &no_headers, 1 },
494 { "no-ifhtml", 0, &process_html, 0 },
495 { "no-ifinfo", 0, &process_info, 0 },
496 { "no-iftex", 0, &process_tex, 0 },
497 { "no-number-footnotes", 0, &number_footnotes, 0 },
498 { "no-number-sections", 0, &number_sections, 0 },
499 { "no-pointer-validate", 0, &validating, 0 },
500 { "no-split", 0, &splitting, 0 },
501 { "no-validate", 0, &validating, 0 },
502 { "no-warn", 0, &print_warnings, 0 },
503 { "number-footnotes", 0, &number_footnotes, 1 },
504 { "number-sections", 0, &number_sections, 1 },
505 { "output", 1, 0, 'o' },
506 { "paragraph-indent", 1, 0, 'p' },
507 { "reference-limit", 1, 0, 'r' },
508 { "split-size", 1, 0, 'S'},
509 { "verbose", 0, &verbose_mode, 1 },
510 { "version", 0, 0, 'V' },
511 { "xml", 0, 0, 'x' },
515 /* For each file mentioned in the command line, process it, turning
516 Texinfo commands into wonderfully formatted output text. */
522 extern int errors_printed;
524 int reading_from_stdin = 0;
526 #ifdef HAVE_SETLOCALE
527 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
528 of the argument to @multicolumn. */
529 setlocale (LC_TIME, "");
530 setlocale (LC_MESSAGES, "");
531 setlocale (LC_CTYPE, "");
532 setlocale (LC_COLLATE, "");
535 /* Set the text message domain. */
536 bindtextdomain (PACKAGE, LOCALEDIR);
537 textdomain (PACKAGE);
539 /* Parse argument flags from the input line. */
540 while ((c = getopt_long (argc, argv, "D:de:E:f:hI:o:p:P:r:s:U:vV:wx",
541 long_options, &ind)) != EOF)
543 if (c == 0 && long_options[ind].flag == 0)
544 c = long_options[ind].val;
550 /* User specified variable to set or clear. */
551 handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
554 case 'd': /* --docbook */
560 case 'e': /* --error-limit */
561 if (sscanf (optarg, "%d", &max_error_level) != 1)
564 _("%s: %s arg must be numeric, not `%s'.\n"),
565 "--error-limit", progname, optarg);
570 case 'E': /* --macro-expand */
571 if (!macro_expansion_output_stream)
573 macro_expansion_filename = optarg;
574 macro_expansion_output_stream
575 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
576 if (!macro_expansion_output_stream)
577 error (_("Couldn't open macro expansion output `%s'"), optarg);
580 error (_("Cannot specify more than one macro expansion output"));
583 case 'f': /* --fill-column */
584 if (sscanf (optarg, "%d", &fill_column) != 1)
587 _("%s: %s arg must be numeric, not `%s'.\n"),
588 "--fill-column", progname, optarg);
593 case 'h': /* --help */
598 /* Append user-specified dir to include file path. */
599 if (!include_files_path)
600 include_files_path = xstrdup (".");
602 include_files_path = (char *)
603 xrealloc (include_files_path,
604 2 + strlen (include_files_path) + strlen (optarg));
605 strcat (include_files_path, PATH_SEP);
606 strcat (include_files_path, optarg);
609 case 'o': /* --output */
610 command_output_filename = xstrdup (optarg);
613 case 'p': /* --paragraph-indent */
614 if (set_paragraph_indent (optarg) < 0)
617 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
624 /* Prepend user-specified include dir to include path. */
625 if (!include_files_path)
627 include_files_path = xstrdup (optarg);
628 include_files_path = xrealloc (include_files_path,
629 strlen (include_files_path) + 3); /* 3 for ":.\0" */
630 strcat (strcat (include_files_path, PATH_SEP), ".");
634 char *tmp = xstrdup (include_files_path);
635 include_files_path = xrealloc (include_files_path,
636 strlen (include_files_path) + strlen (optarg) + 2); /* 2 for ":\0" */
637 strcpy (include_files_path, optarg);
638 strcat (include_files_path, ":");
639 strcat (include_files_path, tmp);
644 case 'r': /* --reference-limit */
645 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
648 _("%s: %s arg must be numeric, not `%s'.\n"),
649 "--reference-limit", progname, optarg);
654 case 's': /* --footnote-style */
655 if (set_footnote_style (optarg) < 0)
658 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
662 footnote_style_preset = 1;
665 case 'S': /* --split-size */
666 if (sscanf (optarg, "%d", &split_size) != 1)
669 _("%s: %s arg must be numeric, not `%s'.\n"),
670 "--split-size", progname, optarg);
679 case 'V': /* --version */
680 print_version_info ();
682 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
683 There is NO warranty. You may redistribute this software\n\
684 under the terms of the GNU General Public License.\n\
685 For more information about these matters, see the files named COPYING.\n"),
690 case 'w': /* --html */
696 case 'x': /* --xml */
708 expensive_validation = 0;
712 /* Check to see if input is a file. If so, process that. */
713 if (!isatty (fileno (stdin)))
714 reading_from_stdin = 1;
717 fprintf (stderr, _("%s: missing file argument.\n"), progname);
724 if (html && splitting)
725 { /* --no-headers --no-split --html indicates confusion. */
727 "%s: --no-headers conflicts with --no-split for --html.\n",
732 /* --no-headers implies --no-split. */
735 /* If the user did not specify an output file, use stdout. */
736 if (!command_output_filename)
737 command_output_filename = xstrdup ("-");
741 print_version_info ();
743 /* Remaining arguments are file names of texinfo files.
744 Convert them, one by one. */
745 if (!reading_from_stdin)
747 while (optind != argc)
748 convert_from_file (argv[optind++]);
751 convert_from_stream (stdin, "stdin");
753 return errors_printed ? 2 : 0;
757 /* Hacking tokens and strings. */
759 /* Return the next token as a string pointer. We cons the string. */
766 /* If the first character to be read is self-delimiting, then that
767 is the command itself. */
768 character = curchar ();
769 if (self_delimiting (character))
773 if (character == '\n')
776 result = xstrdup (" ");
781 for (i = 0; ((input_text_offset != input_text_length)
782 && (character = curchar ())
783 && command_char (character));
784 i++, input_text_offset++);
785 result = xmalloc (i + 1);
786 memcpy (result, &input_text[input_text_offset - i], i);
791 /* Return nonzero if CHARACTER is self-delimiting. */
793 self_delimiting (character)
796 /* @; and @\ are not Texinfo commands, but they are listed here
797 anyway. I don't know why. --karl, 10aug96. */
798 return strchr ("~{|}`^\\@?=;:.-,*\'\" !\n\t", character) != NULL;
801 /* Clear whitespace from the front and end of string. */
806 int len = strlen (string);
812 for (x = 0; x < len; x++)
814 if (!cr_or_whitespace (string[x]))
816 strcpy (string, string + x);
820 len = strlen (string);
823 while (len > -1 && cr_or_whitespace (string[len]))
828 /* Bash STRING, replacing all whitespace with just one space. */
830 fix_whitespace (string)
833 char *temp = xmalloc (strlen (string) + 1);
834 int string_index = 0;
838 canon_white (string);
840 while (string[string_index])
842 c = temp[temp_index++] = string[string_index++];
844 if (c == ' ' || c == '\n' || c == '\t')
846 temp[temp_index - 1] = ' ';
847 while ((c = string[string_index]) && (c == ' ' ||
853 temp[temp_index] = 0;
854 strcpy (string, temp);
858 /* Discard text until the desired string is found. The string is
859 included in the discarded text. */
861 discard_until (string)
864 int temp = search_forward (string, input_text_offset);
866 int tt = (temp < 0) ? input_text_length : temp + strlen (string);
867 int from = input_text_offset;
869 /* Find out what line we are on. */
871 if (input_text[from++] == '\n')
876 input_text_offset = input_text_length - strlen (string);
878 if (strcmp (string, "\n") != 0)
880 line_error (_("Expected `%s'"), string);
885 input_text_offset = temp;
887 input_text_offset += strlen (string);
890 /* Read characters from the file until we are at MATCH.
891 Place the characters read into STRING.
892 On exit input_text_offset is after the match string.
893 Return the offset where the string starts. */
895 get_until (match, string)
896 char *match, **string;
898 int len, current_point, x, new_point, tem;
900 current_point = x = input_text_offset;
901 new_point = search_forward (match, input_text_offset);
904 new_point = input_text_length;
905 len = new_point - current_point;
907 /* Keep track of which line number we are at. */
908 tem = new_point + (strlen (match) - 1);
910 if (input_text[x++] == '\n')
913 *string = xmalloc (len + 1);
915 memcpy (*string, &input_text[current_point], len);
918 /* Now leave input_text_offset in a consistent state. */
919 input_text_offset = tem;
921 if (input_text_offset > input_text_length)
922 input_text_offset = input_text_length;
927 /* Replace input_text[FROM .. TO] with its expansion. */
929 replace_with_expansion (from, to)
933 unsigned xp_len, new_len;
934 char *old_input = input_text;
935 unsigned raw_len = *to - from;
938 /* The rest of the code here moves large buffers, so let's
939 not waste time if the input cannot possibly expand
940 into anything. Unfortunately, we cannot avoid expansion
941 when we see things like @code etc., even if they only
942 asked for expansion of macros, since any Texinfo command
943 can be potentially redefined with a macro. */
944 if (only_macro_expansion &&
945 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
948 /* Get original string from input. */
949 str = xmalloc (raw_len + 1);
950 memcpy (str, input_text + from, raw_len);
953 /* We are going to relocate input_text, so we had better output
954 pending portion of input_text now, before the pointer changes. */
955 if (macro_expansion_output_stream && !executing_string
956 && !me_inhibit_expansion)
957 append_to_expansion_output (from);
960 xp = expansion (str, 0);
961 xp_len = strlen (xp);
964 /* Plunk the expansion into the middle of `input_text' --
965 which is terminated by a newline, not a null. Avoid
966 expensive move of the rest of the input if the expansion
967 has the same length as the original string. */
968 if (xp_len != raw_len)
970 new_len = from + xp_len + input_text_length - *to + 1;
971 if (executing_string)
972 { /* If we are in execute_string, we might need to update
973 the relevant element in the execution_strings[] array,
974 since it could have to be relocated from under our
975 feet. (input_text is reallocated here as well, if needed.) */
976 maybe_update_execution_strings (&input_text, new_len);
978 else if (new_len > input_text_length + 1)
979 /* Don't bother to realloc if we have enough space. */
980 input_text = xrealloc (input_text, new_len);
982 memmove (input_text + from + xp_len,
983 input_text + *to, input_text_length - *to + 1);
985 *to += xp_len - raw_len;
986 /* Since we change input_text_length here, the comparison above
987 isn't really valid, but it seems the worst that might happen is
988 an extra xrealloc or two, so let's not worry. */
989 input_text_length += xp_len - raw_len;
991 memcpy (input_text + from, xp, xp_len);
994 /* Synchronize the macro-expansion pointers with our new input_text. */
995 if (input_text != old_input)
996 forget_itext (old_input);
997 if (macro_expansion_output_stream && !executing_string)
998 remember_itext (input_text, from);
1001 /* Read characters from the file until we are at MATCH or end of line.
1002 Place the characters read into STRING. If EXPAND is nonzero,
1003 expand the text before looking for MATCH for those cases where
1004 MATCH might be produced by some macro. */
1006 get_until_in_line (expand, match, string)
1008 char *match, **string;
1010 int real_bottom = input_text_length;
1011 int limit = search_forward ("\n", input_text_offset);
1013 limit = input_text_length;
1015 /* Replace input_text[input_text_offset .. limit-1] with its expansion.
1016 This allows the node names and menu entries themselves to be
1017 constructed via a macro, as in:
1019 Together: \p\ & \q\.
1022 @node @foo{A,B}, next, prev, top
1024 Otherwise, the `,' separating the macro args A and B is taken as
1025 the node argument separator, so the node name is `@foo{A'. This
1026 expansion is only necessary on the first call, since we expand the
1030 replace_with_expansion (input_text_offset, &limit);
1033 real_bottom = input_text_length;
1034 input_text_length = limit;
1035 get_until (match, string);
1036 input_text_length = real_bottom;
1040 get_rest_of_line (expand, string)
1049 /* Don't expand non-macros in input, since we want them
1050 intact in the macro-expanded output. */
1051 only_macro_expansion++;
1052 get_until_in_line (1, "\n", &tem);
1053 only_macro_expansion--;
1054 *string = expansion (tem, 0);
1058 get_until_in_line (0, "\n", string);
1060 canon_white (*string);
1062 if (curchar () == '\n') /* as opposed to the end of the file... */
1065 input_text_offset++;
1070 /* Backup the input pointer to the previous character, keeping track
1071 of the current line number. */
1073 backup_input_pointer ()
1075 if (input_text_offset)
1077 input_text_offset--;
1078 if (curchar () == '\n')
1083 /* Read characters from the file until we are at MATCH or closing brace.
1084 Place the characters read into STRING. */
1086 get_until_in_braces (match, string)
1087 char *match, **string;
1091 int match_len = strlen (match);
1093 for (i = input_text_offset; i < input_text_length; i++)
1095 if (i < input_text_length - 1 && input_text[i] == '@')
1097 i++; /* skip commands like @, and @{ */
1100 else if (input_text[i] == '{')
1102 else if (input_text[i] == '}')
1105 /* If looking for a brace, don't stop at the interior brace,
1106 like after "baz" in "@foo{something @bar{baz} more}". */
1110 else if (input_text[i] == '\n')
1114 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1118 match_len = i - input_text_offset;
1119 temp = xmalloc (2 + match_len);
1120 memcpy (temp, input_text + input_text_offset, match_len);
1121 temp[match_len] = 0;
1122 input_text_offset = i;
1126 /* Converting a file. */
1128 /* Convert the file named by NAME. The output is saved on the file
1129 named as the argument to the @setfilename command. */
1130 static char *suffixes[] = {
1131 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1132 have "texinfo.txi" and "texinfo.tex" in the same directory, the
1133 former is used rather than the latter, due to file name truncation. */
1143 initialize_conversion ()
1150 /* This is used for splitting the output file and for doing section
1151 headings. It was previously initialized in `init_paragraph', but its
1152 use there loses with the `init_paragraph' calls done by the
1153 multitable code; the tag indices get reset to zero. */
1154 output_position = 0;
1157 typedef struct generic_list {
1158 struct generic_list *next;
1161 /* Reverse the chain of structures in LIST. Output the new head
1162 of the chain. You should always assign the output value of this
1163 function to something, or you will lose the chain. */
1169 GENERIC_LIST *prev = NULL;
1181 /* We read in multiples of 4k, simply because it is a typical pipe size
1183 #define READ_BUFFER_GROWTH (4 * 4096)
1185 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1186 source of the stream is named NAME. */
1188 convert_from_stream (stream, name)
1192 char *buffer = NULL;
1193 int buffer_offset = 0, buffer_size = 0;
1195 initialize_conversion ();
1197 /* Read until the end of the stream. This isn't strictly correct, since
1198 the texinfo input may end before the stream ends, but it is a quick
1199 working hueristic. */
1200 while (!feof (stream))
1204 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1206 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1208 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1216 buffer_offset += count;
1221 /* Set the globals to the new file. */
1222 input_text = buffer;
1223 input_text_length = buffer_offset;
1224 input_filename = xstrdup (name);
1225 node_filename = xstrdup (name);
1226 input_text_offset = 0;
1229 /* Not strictly necessary. This magic prevents read_token () from doing
1230 extra unnecessary work each time it is called (that is a lot of times).
1231 The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1232 input_text[input_text_length] = '\n';
1234 convert_from_loaded_file (name);
1238 convert_from_file (name)
1242 char *filename = xmalloc (strlen (name) + 50);
1244 initialize_conversion ();
1246 /* Try to load the file specified by NAME, concatenated with our
1247 various suffixes. Prefer files like `makeinfo.texi' to
1249 for (i = 0; suffixes[i]; i++)
1251 strcpy (filename, name);
1252 strcat (filename, suffixes[i]);
1254 if (find_and_load (filename))
1257 if (!suffixes[i][0] && strrchr (filename, '.'))
1259 fs_error (filename);
1272 input_filename = filename;
1274 convert_from_loaded_file (name);
1277 /* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
1278 ``/foo/bar/baz/baz.html''.
1280 Split html output goes into the subdirectory of the toplevel
1281 filename, without extension. For example:
1283 @setfilename foo.info
1285 produces output in files foo/index.html, foo/second-node.html, .... */
1288 insert_toplevel_subdirectory (output_filename)
1289 char *output_filename;
1291 char *dir, *subdir, *base, *basename, *p;
1294 static const char index_name[] = "index.html";
1295 const int index_len = sizeof (index_name) - 1;
1297 strcpy (buf, output_filename);
1298 dir = pathname_part (buf);
1299 base = filename_part (buf);
1300 basename = xstrdup (base); /* remember real @setfilename name */
1301 p = dir + strlen (dir) - 1;
1302 if (p > dir && IS_SLASH (*p))
1304 p = strrchr (base, '.');
1308 /* Split html output goes into subdirectory of toplevel name. */
1310 if (FILENAME_CMP (base, filename_part (dir)) != 0)
1313 max_name_len = strlen (basename);
1314 if (index_len > max_name_len)
1315 max_name_len = index_len;
1317 free (output_filename);
1318 output_filename = xmalloc (strlen (dir) + 1
1319 + strlen (subdir) + 1
1322 strcpy (output_filename, dir);
1324 strcat (output_filename, "/");
1325 strcat (output_filename, subdir);
1326 if (mkdir (output_filename, 0777) == -1 && errno != EEXIST)
1327 { /* that failed, try subdir name with .html */
1328 strcpy (output_filename, dir);
1330 strcat (output_filename, "/");
1331 strcat (output_filename, basename);
1332 if (mkdir (output_filename, 0777) == -1 && errno != EEXIST)
1334 line_error (_("Can't create directory `%s': %s"),
1339 strcat (output_filename, "/");
1341 else if (strlen (subdir))
1342 strcat (output_filename, "/");
1343 strcat (output_filename, index_name);
1344 return output_filename;
1347 /* FIXME: this is way too hairy */
1349 convert_from_loaded_file (name)
1352 char *real_output_filename = NULL;
1354 remember_itext (input_text, 0);
1356 input_text_offset = 0;
1358 /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1360 if (looking_at ("\\input"))
1361 discard_until ("\n");
1363 /* Search this file looking for the special string which starts conversion.
1364 Once found, we may truly begin. */
1365 while (input_text_offset >= 0)
1368 search_forward (setfilename_search, input_text_offset);
1370 if (input_text_offset == 0
1371 || (input_text_offset > 0
1372 && input_text[input_text_offset -1] == '\n'))
1374 else if (input_text_offset > 0)
1375 input_text_offset++;
1378 if (input_text_offset < 0)
1380 if (!command_output_filename)
1382 #if defined (REQUIRE_SETFILENAME)
1383 error (_("No `%s' found in `%s'"), setfilename_search, name);
1386 command_output_filename = output_name_from_input_name (name);
1387 #endif /* !REQUIRE_SETFILENAME */
1391 int i, end_of_first_line;
1393 /* Find the end of the first line in the file. */
1394 for (i = 0; i < input_text_length - 1; i++)
1395 if (input_text[i] == '\n')
1398 end_of_first_line = i + 1;
1400 for (i = 0; i < end_of_first_line; i++)
1402 if ((input_text[i] == '\\') &&
1403 (strncmp (input_text + i + 1, "input", 5) == 0))
1405 input_text_offset = i;
1412 input_text_offset += strlen (setfilename_search);
1414 if (!command_output_filename)
1416 get_until ("\n", &output_filename); /* read rest of line */
1417 if (xml && !docbook)
1418 xml_begin_document (output_filename);
1420 { /* Change any extension to .html or .xml. */
1421 char *html_name, *directory_part, *basename_part, *temp;
1423 canon_white (output_filename);
1424 directory_part = pathname_part (output_filename);
1426 basename_part = filename_part (output_filename);
1428 /* Zap any existing extension. */
1429 temp = strrchr (basename_part, '.');
1433 /* Construct new filename. */
1434 html_name = xmalloc (strlen (directory_part)
1435 + strlen (basename_part) + 6);
1436 strcpy (html_name, directory_part);
1437 strcat (html_name, basename_part);
1438 strcat (html_name, html ? ".html" : ".xml");
1440 /* Replace name from @setfilename with the html name. */
1441 free (output_filename);
1442 output_filename = html_name;
1447 if (input_text_offset != -1)
1448 discard_until ("\n");
1450 input_text_offset = 0;
1452 real_output_filename = output_filename = command_output_filename;
1453 command_output_filename = NULL;
1456 canon_white (output_filename);
1457 toplevel_output_filename = xstrdup (output_filename);
1459 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1461 if (macro_expansion_filename
1462 && strcmp (macro_expansion_filename, "-") == 0)
1465 _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1467 macro_expansion_output_stream = NULL;
1469 real_output_filename = xstrdup (real_output_filename);
1470 output_stream = stdout;
1471 splitting = 0; /* Cannot split when writing to stdout. */
1475 if (html && splitting)
1477 if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
1478 || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
1481 output_filename = insert_toplevel_subdirectory (output_filename);
1482 real_output_filename = xstrdup (output_filename);
1484 else if (!real_output_filename)
1485 real_output_filename = expand_filename (output_filename, name);
1487 real_output_filename = xstrdup (real_output_filename);
1489 output_stream = fopen (real_output_filename, "w");
1492 set_current_output_filename (real_output_filename);
1495 printf (_("Making %s file `%s' from `%s'.\n"),
1500 output_filename, input_filename);
1502 if (output_stream == NULL)
1504 fs_error (real_output_filename);
1508 /* Make the displayable filename from output_filename. Only the base
1509 portion of the filename need be displayed. */
1510 flush_output (); /* in case there was no @bye */
1511 if (output_stream != stdout)
1512 pretty_output_filename = filename_part (output_filename);
1514 pretty_output_filename = xstrdup ("stdout");
1516 /* For this file only, count the number of newlines from the top of
1517 the file to here. This way, we keep track of line numbers for
1518 error reporting. Line_number starts at 1, since the user isn't
1523 while (temp != input_text_offset)
1524 if (input_text[temp++] == '\n')
1528 /* html fixxme: should output this as trailer on first page. */
1529 if (!no_headers && !html && !xml)
1530 add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
1531 output_filename, VERSION, input_filename);
1536 xml_end_document ();
1540 discard_insertions (0);
1542 flush_file_stack ();
1544 if (macro_expansion_output_stream)
1546 fclose (macro_expansion_output_stream);
1547 if (errors_printed && !force
1548 && strcmp (macro_expansion_filename, "-") != 0
1549 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1550 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1552 fprintf (stderr, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1553 progname, macro_expansion_filename);
1554 if (unlink (macro_expansion_filename) < 0)
1555 perror (macro_expansion_filename);
1561 output_pending_notes ();
1564 tag_table = (TAG_ENTRY *) reverse_list (tag_table);
1565 if (!no_headers && !html)
1572 add_word ("</body></html>\n");
1576 flush_output (); /* in case there was no @bye */
1577 if (output_stream != stdout)
1578 fclose (output_stream);
1580 /* If validating, then validate the entire file right now. */
1582 validate_file (tag_table);
1584 /* If we need to output the table of contents, do it now. */
1585 if (contents_filename || shortcontents_filename)
1588 if (splitting && !html && (!errors_printed || force))
1589 split_file (real_output_filename, split_size);
1590 else if (errors_printed
1592 && strcmp (real_output_filename, "-") != 0
1593 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1594 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1595 { /* If there were errors, and no --force, remove the output. */
1596 fprintf (stderr, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1597 progname, real_output_filename);
1598 if (unlink (real_output_filename) < 0)
1599 perror (real_output_filename);
1602 free (real_output_filename);
1606 free_and_clear (pointer)
1616 /* Initialize some state. */
1620 free_and_clear (&output_filename);
1621 free_and_clear (&command);
1622 free_and_clear (&input_filename);
1623 free_node_references ();
1624 free_node_node_references ();
1626 init_insertion_stack ();
1627 init_brace_stack ();
1628 current_node = NULL; /* sometimes already freed */
1633 non_top_node_seen = 0;
1640 free_and_clear (&output_paragraph);
1641 output_paragraph = xmalloc (paragraph_buffer_len);
1642 output_paragraph[0] = 0;
1643 output_paragraph_offset = 0;
1645 paragraph_is_open = 0;
1650 /* This is called from `reader_loop' when we are at the * beginning a
1654 handle_menu_entry ()
1658 /* Ugh, glean_node_from_menu wants to read the * itself. */
1659 input_text_offset--;
1661 /* Find node name in menu entry and save it in references list for
1662 later validation. Use followed_reference type for detailmenu
1663 references since we don't want to use them for default node pointers. */
1664 tem = glean_node_from_menu (1, in_detailmenu
1665 ? followed_reference : menu_reference);
1668 { /* Start a menu item with the cleaned-up line. Put an anchor
1669 around the start text (before `:' or the node name). */
1672 discard_until ("* ");
1674 /* The line number was already incremented in reader_loop when we
1675 saw the newline, and discard_until has now incremented again. */
1678 if (had_menu_commentary)
1680 add_word ("<ul>\n");
1681 had_menu_commentary = 0;
1684 else if (!in_paragraph && !paragraph_is_open)
1696 add_word ("<li><a href=\"");
1697 string = expansion (tem, 0);
1698 add_anchor_name (string, 1);
1702 /* The menu item may use macros, so expand them now. */
1703 only_macro_expansion++;
1704 get_until_in_line (1, ":", &string);
1705 only_macro_expansion--;
1706 execute_string ("%s", string); /* get escaping done */
1711 if (looking_at ("::"))
1712 discard_until (":");
1714 { /* discard the node name */
1715 get_until_in_line (0, ".", &string);
1718 input_text_offset++; /* discard the second colon or the period */
1721 else if (xml && tem)
1723 xml_start_menu_entry (tem);
1726 { /* For Info output, we can just use the input and the main case in
1727 reader_loop where we output what comes in. Just move off the *
1728 so the next time through reader_loop we don't end up back here. */
1730 input_text_offset += 2; /* undo the pointer back-up above. */
1737 /* Find the command corresponding to STRING. If the command is found,
1738 return a pointer to the data structure. Otherwise return -1. */
1740 get_command_entry (string)
1745 for (i = 0; command_table[i].name; i++)
1746 if (strcmp (command_table[i].name, string) == 0)
1747 return &command_table[i];
1749 /* This command is not in our predefined command table. Perhaps
1750 it is a user defined command. */
1751 for (i = 0; i < user_command_array_len; i++)
1752 if (user_command_array[i] &&
1753 (strcmp (user_command_array[i]->name, string) == 0))
1754 return user_command_array[i];
1756 /* We never heard of this command. */
1757 return (COMMAND *) -1;
1760 /* input_text_offset is right at the command prefix character.
1761 Read the next token to determine what to do. Return zero
1762 if there's no known command or macro after the prefix character. */
1767 int old_text_offset = input_text_offset++;
1769 free_and_clear (&command);
1770 command = read_token ();
1772 /* Check to see if this command is a macro. If so, execute it here. */
1776 def = find_macro (command);
1780 /* We disallow recursive use of a macro call. Inhibit the expansion
1781 of this macro during the life of its execution. */
1782 if (!(def->flags & ME_RECURSE))
1785 execute_macro (def);
1787 if (!(def->flags & ME_RECURSE))
1794 if (only_macro_expansion)
1796 /* Back up to the place where we were called, so the
1797 caller will have a chance to process this non-macro. */
1798 input_text_offset = old_text_offset;
1802 /* Perform alias expansion */
1803 command = alias_expand (command);
1805 if (enclosure_command (command))
1807 remember_brace (enclosure_expand);
1808 enclosure_expand (START, output_paragraph_offset, 0);
1812 entry = get_command_entry (command);
1813 if (entry == (COMMAND *)-1)
1815 line_error (_("Unknown command `%s'"), command);
1819 if (entry->argument_in_braces == BRACE_ARGS)
1820 remember_brace (entry->proc);
1821 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
1823 if (curchar () == '{')
1824 remember_brace (entry->proc);
1826 { /* No braces, so arg is next char. */
1828 int saved_offset = output_paragraph_offset;
1829 (*(entry->proc)) (START, output_paragraph_offset, 0);
1831 /* Possibilities left for the next character: @ (error), }
1832 (error), whitespace (skip) anything else (normal char). */
1837 line_error (_("Use braces to give a command as an argument to @%s"),
1843 /* Our caller will give the error message, because this }
1844 won't match anything. */
1849 input_text_offset++;
1850 (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
1855 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
1857 (*(entry->proc)) (START, output_paragraph_offset, 0);
1861 /* Okay, we are ready to start the conversion. Call the reader on
1862 some text, and fill the text as it is output. Handle commands by
1863 remembering things like open braces and the current file position on a
1864 stack, and when the corresponding close brace is found, you can call
1865 the function with the proper arguments. Although the filling isn't
1866 necessary for HTML, it should do no harm. */
1876 if (input_text_offset >= input_text_length)
1879 character = curchar ();
1881 /* If only_macro_expansion, only handle macros and leave
1882 everything else intact. */
1883 if (!only_macro_expansion && !in_fixed_width_font
1884 && (character == '\'' || character == '`')
1885 && input_text[input_text_offset + 1] == character)
1887 input_text_offset++;
1888 character = '"'; /* html fixxme */
1891 /* Convert --- to --. */
1892 if (!only_macro_expansion && character == '-')
1895 if (dash_count == 2 && !in_fixed_width_font)
1897 input_text_offset++;
1901 else if (dash_count > 0)
1904 /* If this is a whitespace character, then check to see if the line
1905 is blank. If so, advance to the carriage return. */
1906 if (!only_macro_expansion && whitespace (character))
1908 int i = input_text_offset + 1;
1910 while (i < input_text_length && whitespace (input_text[i]))
1913 if (i == input_text_length || input_text[i] == '\n')
1915 if (i == input_text_length)
1918 input_text_offset = i;
1919 character = curchar ();
1923 if (character == '\n')
1928 case '*': /* perhaps we are at a menu */
1929 /* We used to check for this in the \n case but an @c in a
1930 menu swallows its newline, so check here instead. */
1931 if (!only_macro_expansion && in_menu
1932 && input_text_offset + 1 < input_text_length
1933 && input_text[input_text_offset-1] == '\n')
1934 handle_menu_entry ();
1936 { /* Duplicate code from below, but not worth twisting the
1937 fallthroughs to get down there. */
1938 add_char (character);
1939 input_text_offset++;
1943 /* Escapes for HTML unless we're outputting raw HTML. Do
1944 this always, even if SGML rules don't require it since
1945 that's easier and safer for non-conforming browsers. */
1947 if (html && escape_html)
1950 add_char (character);
1951 input_text_offset++;
1955 if (html && escape_html)
1958 xml_insert_entity ("lt");
1960 add_char (character);
1961 input_text_offset++;
1965 if (html && escape_html)
1968 xml_insert_entity ("gt");
1970 add_char (character);
1971 input_text_offset++;
1974 case COMMAND_PREFIX: /* @ */
1975 if (read_command () || !only_macro_expansion)
1978 /* FALLTHROUGH (usually) */
1980 /* Special case. We're not supposed to see this character by itself.
1981 If we do, it means there is a syntax error in the input text.
1982 Report the error here, but remember this brace on the stack so
1983 we can ignore its partner. */
1984 if (!only_macro_expansion)
1986 if (!STREQ (command, "math"))
1988 line_error (_("Misplaced %c"), '{');
1989 remember_brace (misplaced_brace);
1992 { /* We don't mind `extra' braces inside @math. */
1993 extern void cm_no_op ();
1994 remember_brace (cm_no_op);
1996 /* remember_brace advances input_text_offset. */
2000 /* FALLTHROUGH (usually) */
2002 if (!only_macro_expansion)
2004 pop_and_call_brace ();
2005 input_text_offset++;
2009 /* FALLTHROUGH (usually) */
2011 add_char (character);
2012 input_text_offset++;
2015 if (macro_expansion_output_stream && !only_macro_expansion)
2016 maybe_write_itext (input_text, input_text_offset);
2026 remember_brace (proc)
2027 COMMAND_FUNCTION *proc;
2029 if (curchar () != '{')
2030 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command);
2032 input_text_offset++;
2033 remember_brace_1 (proc, output_paragraph_offset);
2036 /* Remember the current output position here. Save PROC
2037 along with it so you can call it later. */
2039 remember_brace_1 (proc, position)
2040 COMMAND_FUNCTION *proc;
2043 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
2044 new->next = brace_stack;
2046 new->command = command ? xstrdup (command) : "";
2047 new->pos = position;
2048 new->line = line_number;
2049 new->in_fixed_width_font = in_fixed_width_font;
2053 /* Pop the top of the brace stack, and call the associated function
2054 with the args END and POS. */
2056 pop_and_call_brace ()
2058 if (brace_stack == NULL)
2060 line_error (_("Unmatched }"));
2065 BRACE_ELEMENT *temp;
2067 int pos = brace_stack->pos;
2068 COMMAND_FUNCTION *proc = brace_stack->proc;
2069 in_fixed_width_font = brace_stack->in_fixed_width_font;
2071 /* Reset current command, so the proc can know who it is. This is
2072 used in cm_accent. */
2073 command = brace_stack->command;
2075 temp = brace_stack->next;
2079 (*proc) (END, pos, output_paragraph_offset);
2083 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2085 adjust_braces_following (here, amount)
2088 BRACE_ELEMENT *stack = brace_stack;
2092 if (stack->pos >= here)
2093 stack->pos += amount;
2094 stack = stack->next;
2098 /* Return the string which invokes PROC; a pointer to a function.
2099 Always returns the first function in the command table if more than
2100 one matches PROC. */
2102 find_proc_name (proc)
2103 COMMAND_FUNCTION *proc;
2107 for (i = 0; command_table[i].name; i++)
2108 if (proc == command_table[i].proc)
2109 return command_table[i].name;
2110 return _("NO_NAME!");
2113 /* You call discard_braces () when you shouldn't have any braces on the stack.
2114 I used to think that this happens for commands that don't take arguments
2115 in braces, but that was wrong because of things like @code{foo @@}. So now
2116 I only detect it at the beginning of nodes. */
2125 if (brace_stack->proc != misplaced_brace)
2129 proc_name = find_proc_name (brace_stack->proc);
2130 file_line_error (input_filename, brace_stack->line,
2131 _("%c%s missing close brace"), COMMAND_PREFIX,
2133 pop_and_call_brace ();
2137 BRACE_ELEMENT *temp;
2138 temp = brace_stack->next;
2146 get_char_len (character)
2149 /* Return the printed length of the character. */
2155 len = (output_column + 8) & 0xf7;
2156 if (len > fill_column)
2157 len = fill_column - output_column;
2159 len = len - output_column;
2163 len = fill_column - output_column;
2167 /* ASCII control characters appear as two characters in the output
2168 (e.g., ^A). But characters with the high bit set are just one
2169 on suitable terminals, so don't count them as two for line
2170 breaking purposes. */
2171 if (0 <= character && character < ' ')
2180 #if defined (VA_FPRINTF) && __STDC__
2181 add_word_args (char *format, ...)
2183 add_word_args (format, va_alist)
2188 char buffer[2000]; /* xx no fixed limits */
2193 VA_START (ap, format);
2195 VA_SPRINTF (buffer, format, ap);
2197 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2198 #endif /* not VA_SPRINTF */
2203 /* Add STRING to output_paragraph. */
2209 add_char (*string++);
2212 /* Like add_word, but inhibits conversion of whitespace into .
2213 Use this to output HTML directives with embedded blanks, to make
2216 add_html_elt (string)
2224 /* Add the character to the current paragraph. If filling_enabled is
2225 nonzero, then do filling as well. */
2227 add_char (character)
2232 xml_add_char (character);
2236 /* If we are avoiding outputting headers, and we are currently
2237 in a menu, then simply return. But if we're only expanding macros,
2238 then we're being called from glean_node_from_menu to try to
2239 remember a menu reference, and we need that so we can do defaulting. */
2240 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2243 /* If we are adding a character now, then we don't have to
2244 ignore close_paragraph () calls any more. */
2245 if (must_start_paragraph && character != '\n')
2247 must_start_paragraph = 0;
2248 line_already_broken = 0; /* The line is no longer broken. */
2249 if (current_indent > output_column)
2251 indent (current_indent - output_column);
2252 output_column = current_indent;
2256 if (non_splitting_words
2257 && !(html && in_html_elt)
2258 && strchr (" \t\n", character))
2260 if (html || docbook)
2261 { /* Seems cleaner to use than an 8-bit char. */
2266 character = META (' '); /* unmeta-d in flush_output */
2269 insertion_paragraph_closed = 0;
2274 if (!filling_enabled && ! (html && (in_menu || in_detailmenu)))
2278 if (force_flush_right)
2281 /* Hack to force single blank lines out in this mode. */
2287 if (!no_indent && paragraph_is_open)
2288 indent (output_column = current_indent);
2291 else if (end_of_sentence_p ())
2292 /* CHARACTER is newline, and filling is enabled. */
2296 last_inserted_character = character;
2299 if (last_char_was_newline)
2302 last_char_was_newline++;
2308 last_char_was_newline = 1;
2317 default: /* not at newline */
2319 int len = get_char_len (character);
2320 int suppress_insert = 0;
2322 if ((character == ' ') && (last_char_was_newline))
2324 if (!paragraph_is_open)
2331 /* This is sad, but it seems desirable to not force any
2332 particular order on the front matter commands. This way,
2333 the document can do @settitle, @documentlanguage, etc, in
2334 any order and with any omissions, and we'll still output
2335 the html <head> `just in time'. */
2336 if (!executing_string && html && !html_output_head_p)
2337 html_output_head ();
2339 if (!paragraph_is_open)
2342 /* If the paragraph is supposed to be indented a certain
2343 way, then discard all of the pending whitespace.
2344 Otherwise, we let the whitespace stay. */
2345 if (!paragraph_start_indent)
2346 indent (pending_indent);
2349 /* This horrible kludge of checking for a < prevents <p>
2350 from being inserted when we already have html markup
2351 starting a paragraph, as with <ul> and <h1> and the like. */
2352 if (html && escape_html && character != '<'
2353 && (!in_fixed_width_font || in_menu || in_detailmenu))
2355 insert_string ("<p>");
2357 adjust_braces_following (0, 3); /* adjust for <p> */
2361 output_column += len;
2362 if (output_column > fill_column)
2364 if (filling_enabled && !html)
2366 int temp = output_paragraph_offset;
2367 while (--temp > 0 && output_paragraph[temp] != '\n')
2369 /* If we have found a space, we have the place to break
2371 if (output_paragraph[temp] == ' ')
2373 /* Remove trailing whitespace from output. */
2374 while (temp && whitespace (output_paragraph[temp - 1]))
2377 /* If we went back all the way to the newline of the
2378 preceding line, it probably means that the word we
2379 are adding is itself wider than the space that the
2380 indentation and the fill_column let us use. In
2381 that case, do NOT insert another newline, since it
2382 won't help. Just indent to current_indent and
2383 leave it alone, since that's the most we can do. */
2384 if (temp && output_paragraph[temp - 1] != '\n')
2385 output_paragraph[temp++] = '\n';
2387 /* We have correctly broken the line where we want
2388 to. What we don't want is spaces following where
2389 we have decided to break the line. We get rid of
2396 if (t1 == output_paragraph_offset)
2398 if (whitespace (character))
2399 suppress_insert = 1;
2402 if (!whitespace (output_paragraph[t1]))
2408 adjust_braces_following (temp, (- (t1 - temp)));
2409 strncpy ((char *) &output_paragraph[temp],
2410 (char *) &output_paragraph[t1],
2411 (output_paragraph_offset - t1));
2412 output_paragraph_offset -= (t1 - temp);
2416 /* Filled, but now indent if that is right. */
2417 if (indented_fill && current_indent > 0)
2419 int buffer_len = ((output_paragraph_offset - temp)
2421 char *temp_buffer = xmalloc (buffer_len);
2422 int indentation = 0;
2424 /* We have to shift any markers that are in
2425 front of the wrap point. */
2426 adjust_braces_following (temp, current_indent);
2428 while (current_indent > 0 &&
2429 indentation != current_indent)
2430 temp_buffer[indentation++] = ' ';
2432 memcpy ((char *) &temp_buffer[current_indent],
2433 (char *) &output_paragraph[temp],
2434 buffer_len - current_indent);
2436 if (output_paragraph_offset + buffer_len
2437 >= paragraph_buffer_len)
2439 unsigned char *tt = xrealloc
2441 (paragraph_buffer_len += buffer_len));
2442 output_paragraph = tt;
2444 memcpy ((char *) &output_paragraph[temp],
2445 temp_buffer, buffer_len);
2446 output_paragraph_offset += current_indent;
2450 while (temp < output_paragraph_offset)
2452 get_char_len (output_paragraph[temp++]);
2453 output_column += len;
2460 if (!suppress_insert)
2463 last_inserted_character = character;
2465 last_char_was_newline = 0;
2466 line_already_broken = 0;
2471 /* Add a character and store its position in meta_char_pos. */
2473 add_meta_char (character)
2476 meta_char_pos = output_paragraph_offset;
2477 add_char (character);
2480 /* Insert CHARACTER into `output_paragraph'. */
2485 output_paragraph[output_paragraph_offset++] = character;
2486 if (output_paragraph_offset == paragraph_buffer_len)
2489 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2493 /* Insert the null-terminated string STRING into `output_paragraph'. */
2495 insert_string (string)
2503 /* Sentences might have these characters after the period (or whatever). */
2504 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2507 /* Return true if at an end-of-sentence character, possibly followed by
2508 post-sentence punctuation to ignore. */
2510 end_of_sentence_p ()
2512 int loc = output_paragraph_offset - 1;
2514 /* If nothing has been output, don't check output_paragraph[-1]. */
2518 /* A post-sentence character that is at meta_char_pos is not really
2519 a post-sentence character; it was produced by a markup such as
2520 @samp. We don't want the period inside @samp to be treated as a
2523 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
2525 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
2529 /* Remove upto COUNT characters of whitespace from the
2530 the current output line. If COUNT is less than zero,
2531 then remove until none left. */
2533 kill_self_indent (count)
2536 /* Handle infinite case first. */
2540 while (output_paragraph_offset)
2542 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2543 output_paragraph_offset--;
2550 while (output_paragraph_offset && count--)
2551 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2552 output_paragraph_offset--;
2558 /* Nonzero means do not honor calls to flush_output (). */
2559 static int flushing_ignored = 0;
2561 /* Prevent calls to flush_output () from having any effect. */
2563 inhibit_output_flushing ()
2568 /* Allow calls to flush_output () to write the paragraph data. */
2570 uninhibit_output_flushing ()
2580 if (!output_paragraph_offset || flushing_ignored)
2583 for (i = 0; i < output_paragraph_offset; i++)
2585 /* If we turned on the 8th bit for a space inside @w, turn it
2586 back off for output. This might be problematic, since the
2587 0x80 character may be used in 8-bit character sets. Sigh.
2588 In any case, don't do this for HTML, since the nbsp character
2589 is valid input and must be passed along to the browser. */
2590 if (!html && (output_paragraph[i] & meta_character_bit))
2592 int temp = UNMETA (output_paragraph[i]);
2594 output_paragraph[i] &= 0x7f;
2598 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2600 output_position += output_paragraph_offset;
2601 output_paragraph_offset = 0;
2605 /* How to close a paragraph controlling the number of lines between
2606 this one and the last one. */
2608 /* Paragraph spacing is controlled by this variable. It is the number of
2609 blank lines that you wish to appear between paragraphs. A value of
2610 1 creates a single blank line between paragraphs. */
2611 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2614 close_paragraph_with_lines (lines)
2617 int old_spacing = paragraph_spacing;
2618 paragraph_spacing = lines;
2620 paragraph_spacing = old_spacing;
2623 /* Close the current paragraph, leaving no blank lines between them. */
2625 close_single_paragraph ()
2627 close_paragraph_with_lines (0);
2630 /* Close a paragraph after an insertion has ended. */
2632 close_insertion_paragraph ()
2634 if (!insertion_paragraph_closed)
2636 /* Close the current paragraph, breaking the line. */
2637 close_single_paragraph ();
2639 /* Start a new paragraph, with the correct indentation for the now
2640 current insertion level (one above the one that we are ending). */
2643 /* Tell `close_paragraph' that the previous line has already been
2644 broken, so it should insert one less newline. */
2645 line_already_broken = 1;
2647 /* Tell functions such as `add_char' we've already found a newline. */
2648 ignore_blank_line ();
2652 /* If the insertion paragraph is closed already, then we are seeing
2653 two `@end' commands in a row. Note that the first one we saw was
2654 handled in the first part of this if-then-else clause, and at that
2655 time `start_paragraph' was called, partially to handle the proper
2656 indentation of the current line. However, the indentation level
2657 may have just changed again, so we may have to outdent the current
2658 line to the new indentation level. */
2659 if (current_indent < output_column)
2660 kill_self_indent (output_column - current_indent);
2663 insertion_paragraph_closed = 1;
2666 /* Close the currently open paragraph. */
2672 /* The insertion paragraph is no longer closed. */
2673 insertion_paragraph_closed = 0;
2675 if (paragraph_is_open && !must_start_paragraph)
2679 tindex = output_paragraph_offset;
2681 /* Back up to last non-newline/space character, forcing all such
2682 subsequent characters to be newlines. This isn't strictly
2683 necessary, but a couple of functions use the presence of a newline
2684 to make decisions. */
2685 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
2687 c = output_paragraph[tindex];
2689 if (c == ' '|| c == '\n')
2690 output_paragraph[tindex] = '\n';
2695 /* All trailing whitespace is ignored. */
2696 output_paragraph_offset = ++tindex;
2698 /* Break the line if that is appropriate. */
2699 if (paragraph_spacing >= 0)
2702 /* Add as many blank lines as is specified in `paragraph_spacing'. */
2703 if (!force_flush_right)
2705 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
2708 /* Don't need anything extra for HTML in usual case of no
2709 extra paragraph spacing. */
2711 insert_string ("<br>");
2715 /* If we are doing flush right indentation, then do it now
2716 on the paragraph (really a single line). */
2717 if (force_flush_right)
2718 do_flush_right_indentation ();
2721 paragraph_is_open = 0;
2726 ignore_blank_line ();
2729 /* Make the last line just read look as if it were only a newline. */
2731 ignore_blank_line ()
2733 last_inserted_character = '\n';
2734 last_char_was_newline = 1;
2737 /* Align the end of the text in output_paragraph with fill_column. */
2739 do_flush_right_indentation ()
2744 kill_self_indent (-1);
2746 if (output_paragraph[0] != '\n')
2748 output_paragraph[output_paragraph_offset] = 0;
2750 if (output_paragraph_offset < fill_column)
2754 if (fill_column >= paragraph_buffer_len)
2756 xrealloc (output_paragraph,
2757 (paragraph_buffer_len += fill_column));
2759 temp_len = strlen ((char *)output_paragraph);
2760 temp = xmalloc (temp_len + 1);
2761 memcpy (temp, (char *)output_paragraph, temp_len);
2763 for (i = 0; i < fill_column - output_paragraph_offset; i++)
2764 output_paragraph[i] = ' ';
2766 memcpy ((char *)output_paragraph + i, temp, temp_len);
2768 output_paragraph_offset = fill_column;
2769 adjust_braces_following (0, i);
2774 /* Begin a new paragraph. */
2778 /* First close existing one. */
2779 if (paragraph_is_open)
2782 /* In either case, the insertion paragraph is no longer closed. */
2783 insertion_paragraph_closed = 0;
2785 /* However, the paragraph is open! */
2786 paragraph_is_open = 1;
2788 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
2789 had to be called before we would allow any other paragraph operations
2790 to have an effect. */
2791 if (!must_start_paragraph)
2793 int amount_to_indent = 0;
2795 /* If doing indentation, then insert the appropriate amount. */
2798 if (inhibit_paragraph_indentation)
2800 amount_to_indent = current_indent;
2801 if (inhibit_paragraph_indentation < 0)
2802 inhibit_paragraph_indentation++;
2804 else if (paragraph_start_indent < 0)
2805 amount_to_indent = current_indent;
2807 amount_to_indent = current_indent + paragraph_start_indent;
2809 if (amount_to_indent >= output_column)
2811 amount_to_indent -= output_column;
2812 indent (amount_to_indent);
2813 output_column += amount_to_indent;
2818 must_start_paragraph = 0;
2821 /* Insert the indentation specified by AMOUNT. */
2829 /* For every START_POS saved within the brace stack which will be affected
2830 by this indentation, bump that start pos forward. */
2831 adjust_braces_following (output_paragraph_offset, amount);
2833 while (--amount >= 0)
2837 /* Search forward for STRING in input_text.
2838 FROM says where where to start. */
2840 search_forward (string, from)
2844 int len = strlen (string);
2846 while (from < input_text_length)
2848 if (strncmp (input_text + from, string, len) == 0)
2855 /* Cross references. */
2857 /* Return next comma-delimited argument, but do not cross a close-brace
2858 boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
2859 the entire brace-delimited argument list with its expansion before
2860 looking for the next comma. */
2862 get_xref_token (expand)
2869 int old_offset = input_text_offset;
2870 int old_lineno = line_number;
2872 get_until_in_braces ("}", &string);
2873 if (curchar () == '}') /* as opposed to end of text */
2874 input_text_offset++;
2875 if (input_text_offset > old_offset)
2877 int limit = input_text_offset;
2879 input_text_offset = old_offset;
2880 line_number = old_lineno;
2881 only_macro_expansion++;
2882 replace_with_expansion (input_text_offset, &limit);
2883 only_macro_expansion--;
2888 get_until_in_braces (",", &string);
2889 if (curchar () == ',')
2890 input_text_offset++;
2891 fix_whitespace (string);
2895 /* NOTE: If you wonder why the HTML output is produced with such a
2896 peculiar mix of calls to add_word and execute_string, here's the
2897 reason. get_xref_token (1) expands all macros in a reference, but
2898 any other commands, like @value, @@, etc., are left intact. To
2899 expand them, we need to run the arguments through execute_string.
2900 However, characters like <, &, > and others cannot be let into
2901 execute_string, because they will be escaped. See the mess? */
2903 /* Make a cross reference. */
2909 char *arg1 = get_xref_token (1); /* expands all macros in xref */
2910 char *arg2 = get_xref_token (0);
2911 char *arg3 = get_xref_token (0);
2912 char *arg4 = get_xref_token (0);
2913 char *arg5 = get_xref_token (0);
2916 /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
2917 first argument must never be blank." --rms.
2918 We hereby comply by disallowing such constructs. */
2920 line_error (_("First argument to cross-reference may not be empty"));
2924 if (!*arg4 && !*arg5)
2926 char *arg1_id = xml_id (arg1);
2929 xml_insert_element_with_attribute (XREFNODENAME, START,
2930 "linkend=\"%s\"", arg1_id);
2933 execute_string (arg2);
2934 xml_insert_element (XREFNODENAME, END);
2938 xml_insert_element_with_attribute (XREF, START,
2939 "linkend=\"%s\"", arg1_id);
2941 xml_pop_current_element ();
2947 xml_insert_element (XREF, START);
2948 xml_insert_element (XREFNODENAME, START);
2949 execute_string (arg1);
2950 xml_insert_element (XREFNODENAME, END);
2953 xml_insert_element (XREFINFONAME, START);
2954 execute_string (arg2);
2955 xml_insert_element (XREFINFONAME, END);
2959 xml_insert_element (XREFPRINTEDDESC, START);
2960 execute_string (arg3);
2961 xml_insert_element (XREFPRINTEDDESC, END);
2965 xml_insert_element (XREFINFOFILE, START);
2966 execute_string (arg4);
2967 xml_insert_element (XREFINFOFILE, END);
2971 xml_insert_element (XREFPRINTEDNAME, START);
2972 execute_string (arg5);
2973 xml_insert_element (XREFPRINTEDNAME, END);
2975 xml_insert_element (XREF, END);
2980 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
2983 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
2990 arg2 - reference name
2991 arg3 - title or topic (and reference name if arg2 is NULL)
2992 arg4 - info file name
2993 arg5 - printed manual title */
3008 /* html fixxme: revisit this; external node name not
3009 much use to us with numbered nodes. */
3010 add_html_elt ("<a href=");
3011 /* Note that if we are splitting, and the referenced
3012 tag is an anchor rather than a node, we will
3013 produce a reference to a file whose name is
3014 derived from the anchor name. However, only
3015 nodes create files, so we are referencing a
3016 non-existent file. cm_anchor, which see, deals
3017 with that problem. */
3019 execute_string ("\"../%s/", arg4);
3021 execute_string ("\"%s.html", arg4);
3022 /* Do not collapse -- to -, etc., in references. */
3023 in_fixed_width_font++;
3024 tem = expansion (arg1, 0); /* expand @-commands in node */
3025 in_fixed_width_font--;
3026 add_anchor_name (tem, 1);
3029 execute_string ("%s", ref_name);
3034 execute_string ("%s:", ref_name);
3035 in_fixed_width_font++;
3036 execute_string (" (%s)%s%s", arg4, arg1, px_ref_flag ? "." : "");
3037 in_fixed_width_font--;
3040 /* Free all of the arguments found. */
3041 if (arg1) free (arg1);
3042 if (arg2) free (arg2);
3043 if (arg3) free (arg3);
3044 if (arg4) free (arg4);
3045 if (arg5) free (arg5);
3049 remember_node_reference (arg1, line_number, followed_reference);
3055 add_html_elt ("<a href=\"");
3056 in_fixed_width_font++;
3057 tem = expansion (arg1, 0);
3058 in_fixed_width_font--;
3059 add_anchor_name (tem, 1);
3062 execute_string ("%s", *arg2 ? arg2 : arg3);
3067 execute_string ("%s:", *arg2 ? arg2 : arg3);
3068 in_fixed_width_font++;
3069 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
3070 in_fixed_width_font--;
3077 add_html_elt ("<a href=\"");
3078 in_fixed_width_font++;
3079 tem = expansion (arg1, 0);
3080 in_fixed_width_font--;
3081 add_anchor_name (tem, 1);
3084 execute_string ("%s", *arg2 ? arg2 : arg1);
3091 execute_string ("%s:", arg2);
3092 in_fixed_width_font++;
3093 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
3094 in_fixed_width_font--;
3098 in_fixed_width_font++;
3099 execute_string ("%s::", arg1);
3100 in_fixed_width_font--;
3105 /* Free all of the arguments found. */
3106 if (arg1) free (arg1);
3107 if (arg2) free (arg2);
3108 if (arg3) free (arg3);
3109 if (arg4) free (arg4);
3110 if (arg5) free (arg5);
3113 { /* Check to make sure that the next non-whitespace character is
3114 valid to follow an xref (so info readers can find the node
3115 names). `input_text_offset' is pointing at the "}" which ended
3116 the xref or ref command. */
3119 for (temp = input_text_offset + 1; temp < input_text_length; )
3121 if (cr_or_whitespace (input_text[temp]))
3125 if (input_text[temp] != '.' && input_text[temp] != ',')
3126 warning (_("`.' or `,' must follow cross reference, not %c"),
3144 /* Note that cm_xref isn't called with arg == END, which disables
3145 the code near the end of cm_xref that checks for `.' or `,'
3146 after the cross-reference. This is because @pxref{} generates
3147 the required character itself, when needed. */
3168 char *node = get_xref_token (1); /* expands all macros in inforef */
3169 char *pname = get_xref_token (0);
3170 char *file = get_xref_token (0);
3172 /* (see comments at cm_xref). */
3174 line_error (_("First argument to @inforef may not be empty"));
3176 if (xml && !docbook)
3178 xml_insert_element (INFOREF, START);
3179 xml_insert_element (INFOREFNODENAME, START);
3180 execute_string (node);
3181 xml_insert_element (INFOREFNODENAME, END);
3184 xml_insert_element (INFOREFREFNAME, START);
3185 execute_string (pname);
3186 xml_insert_element (INFOREFREFNAME, END);
3188 xml_insert_element (INFOREFINFONAME, START);
3189 execute_string (file);
3190 xml_insert_element (INFOREFINFONAME, END);
3192 xml_insert_element (INFOREF, END);
3198 add_word (_("see "));
3199 /* html fixxme: revisit this */
3200 add_html_elt ("<a href=");
3202 execute_string ("\"../%s/", file);
3204 execute_string ("\"%s.html", file);
3205 tem = expansion (node, 0);
3206 add_anchor_name (tem, 1);
3208 execute_string ("%s", *pname ? pname : tem);
3215 execute_string ("*note %s: (%s)%s", pname, file, node);
3217 execute_string ("*note (%s)%s::", file, node);
3226 /* A URL reference. */
3233 extern int printing_index;
3234 char *url = get_xref_token (1); /* expands all macros in uref */
3235 char *desc = get_xref_token (0);
3236 char *replacement = get_xref_token (0);
3240 xml_insert_element (UREF, START);
3241 xml_insert_element (UREFURL, START);
3242 execute_string (url);
3243 xml_insert_element (UREFURL, END);
3246 xml_insert_element (UREFDESC, START);
3247 execute_string (desc);
3248 xml_insert_element (UREFDESC, END);
3252 xml_insert_element (UREFREPLACEMENT, START);
3253 execute_string (replacement);
3254 xml_insert_element (UREFREPLACEMENT, END);
3256 xml_insert_element (UREF, END);
3259 { /* never need to show the url */
3260 add_html_elt ("<a href=");
3261 /* don't collapse `--' etc. in the url */
3262 in_fixed_width_font++;
3263 execute_string ("\"%s\"", url);
3264 in_fixed_width_font--;
3266 execute_string ("%s", *replacement ? replacement
3267 : (*desc ? desc : url));
3270 else if (*replacement) /* do not show the url */
3271 execute_string ("%s", replacement);
3272 else if (*desc) /* show both text and url */
3274 execute_string ("%s ", desc);
3275 in_fixed_width_font++;
3276 execute_string ("(%s)", url);
3277 in_fixed_width_font--;
3279 else /* no text at all, so have the url to show */
3281 in_fixed_width_font++;
3282 execute_string ("%s%s%s",
3283 printing_index ? "" : "`",
3285 printing_index ? "" : "'");
3286 in_fixed_width_font--;
3297 /* An email reference. */
3304 char *addr = get_xref_token (1); /* expands all macros in email */
3305 char *name = get_xref_token (0);
3309 xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
3311 execute_string (name);
3312 xml_insert_element (EMAIL, END);
3316 xml_insert_element (EMAIL, START);
3317 xml_insert_element (EMAILADDRESS, START);
3318 execute_string (addr);
3319 xml_insert_element (EMAILADDRESS, END);
3322 xml_insert_element (EMAILNAME, START);
3323 execute_string (name);
3324 xml_insert_element (EMAILNAME, END);
3326 xml_insert_element (EMAIL, END);
3330 add_html_elt ("<a href=");
3331 /* don't collapse `--' etc. in the address */
3332 in_fixed_width_font++;
3333 execute_string ("\"mailto:%s\"", addr);
3334 in_fixed_width_font--;
3336 execute_string ("%s", *name ? name : addr);
3341 execute_string ("%s%s", name, *name ? " " : "");
3342 in_fixed_width_font++;
3343 execute_string ("<%s>", addr);
3344 in_fixed_width_font--;
3354 /* An external image is a reference, kind of. The parsing is (not
3355 coincidentally) similar, anyway. */
3360 char *name_arg, *rest, *alt_arg, *ext_arg;
3365 name_arg = get_xref_token (1); /* expands all macros in image */
3366 /* We don't (yet) care about the next two args, but read them so they
3367 don't end up in the text. */
3368 rest = get_xref_token (0);
3371 rest = get_xref_token (0);
3374 alt_arg = get_xref_token (1); /* expands all macros in alt text */
3375 ext_arg = get_xref_token (0);
3379 char *fullname = xmalloc (strlen (name_arg)
3380 + (ext_arg && *ext_arg ? strlen (ext_arg) + 1 : 4) + 1);
3384 if (ext_arg && *ext_arg)
3386 sprintf (fullname, "%s.%s", name_arg, ext_arg);
3387 if (access (fullname, R_OK) != 0)
3389 line_error(_("@image file `%s' (for HTML) not readable: %s"),
3390 fullname, strerror (errno));
3396 sprintf (fullname, "%s.png", name_arg);
3397 if (access (fullname, R_OK) != 0)
3399 sprintf (fullname, "%s.jpg", name_arg);
3400 if (access (fullname, R_OK) != 0)
3402 line_error (_("No `%s.png' or `.jpg', and no extension supplied"),
3409 add_html_elt ("<img src=");
3410 add_word_args ("\"%s\"", fullname);
3411 add_html_elt (" alt=");
3412 add_word_args ("\"%s\">", (*alt_arg) ? alt_arg : fullname);
3414 else if (xml && docbook)
3415 xml_insert_docbook_image (name_arg);
3418 xml_insert_element (IMAGE, START);
3419 add_word (name_arg);
3420 xml_insert_element (IMAGE, END);
3423 { /* Try to open foo.txt. */
3425 strcpy (fullname, name_arg);
3426 strcat (fullname, ".txt");
3427 image_file = fopen (fullname, "r");
3431 int save_inhibit_indentation = inhibit_paragraph_indentation;
3432 int save_filling_enabled = filling_enabled;
3434 inhibit_paragraph_indentation = 1;
3435 filling_enabled = 0;
3436 last_char_was_newline = 0;
3438 /* Maybe we need to remove the final newline if the image
3439 file is only one line to allow in-line images. On the
3440 other hand, they could just make the file without a
3442 while ((ch = getc (image_file)) != EOF)
3445 inhibit_paragraph_indentation = save_inhibit_indentation;
3446 filling_enabled = save_filling_enabled;
3448 if (fclose (image_file) != 0)
3452 line_error (_("@image file `%s' (for text) unreadable: %s"),
3453 fullname, strerror (errno));
3459 line_error (_("@image missing filename argument"));
3471 /* A structure which contains `defined' variables. */
3472 typedef struct defines {
3473 struct defines *next;
3478 /* The linked list of `set' defines. */
3479 DEFINE *defines = NULL;
3481 /* Add NAME to the list of `set' defines. */
3489 for (temp = defines; temp; temp = temp->next)
3490 if (strcmp (name, temp->name) == 0)
3493 temp->value = xstrdup (value);
3497 temp = xmalloc (sizeof (DEFINE));
3498 temp->next = defines;
3499 temp->name = xstrdup (name);
3500 temp->value = xstrdup (value);
3504 /* Remove NAME from the list of `set' defines. */
3509 DEFINE *temp, *last;
3516 if (strcmp (temp->name, name) == 0)
3519 last->next = temp->next;
3521 defines = temp->next;
3533 /* Return the value of NAME. The return value is NULL if NAME is unset. */
3540 for (temp = defines; temp; temp = temp->next)
3541 if (strcmp (temp->name, name) == 0)
3547 /* Create a variable whose name appears as the first word on this line. */
3551 handle_variable (SET);
3554 /* Remove a variable whose name appears as the first word on this line. */
3558 handle_variable (CLEAR);
3564 handle_variable (IFSET);
3570 handle_variable (IFCLEAR);
3573 /* This command takes braces, but we parse the contents specially, so we
3574 don't use the standard brace popping code.
3576 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3577 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3578 it produces no output. */
3584 arglist = get_brace_args (0);
3588 if (array_len (arglist) > 1)
3590 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
3592 execute_string ("%s\n", arglist[2]);
3595 free_array (arglist);
3600 cm_value (arg, start_pos, end_pos)
3601 int arg, start_pos, end_pos;
3603 static int value_level = 0, saved_meta_pos = -1;
3605 /* All the text after @value{ upto the matching } will eventually
3606 disappear from output_paragraph, when this function is called
3607 with ARG == END. If the text produced until then sets
3608 meta_char_pos, we will need to restore it to the value it had
3609 before @value was seen. So we need to save the previous value
3610 of meta_char_pos here. */
3613 /* If we are already inside some outer @value, don't overwrite
3614 the value saved in saved_meta_pos. */
3616 saved_meta_pos = meta_char_pos;
3618 /* While the argument of @value is processed, we need to inhibit
3619 textual transformations like "--" into "-", since @set didn't
3620 do that when it grabbed the name of the variable. */
3621 in_fixed_width_font++;
3625 char *name = (char *) &output_paragraph[start_pos];
3627 output_paragraph[end_pos] = 0;
3628 name = xstrdup (name);
3629 value = set_p (name);
3630 output_column -= end_pos - start_pos;
3631 output_paragraph_offset = start_pos;
3633 /* Restore the previous value of meta_char_pos if the stuff
3634 inside this @value{} moved it. */
3635 if (saved_meta_pos == -1) /* can't happen inside @value{} */
3637 if (value_level == 1
3638 && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3640 meta_char_pos = saved_meta_pos;
3641 saved_meta_pos = -1;
3644 /* No need to decrement in_fixed_width_font, since before
3645 we are called with arg == END, the reader loop already
3646 popped the brace stack, which restored in_fixed_width_font,
3647 among other things. */
3650 execute_string ("%s", value);
3652 add_word_args (_("{No value for `%s'}"), name);
3658 /* Set, clear, or conditionalize based on ACTION. */
3660 handle_variable (action)
3665 get_rest_of_line (0, &name);
3666 /* If we hit the end of text in get_rest_of_line, backing up
3667 input pointer will cause the last character of the last line
3668 be pushed back onto the input, which is wrong. */
3669 if (input_text_offset < input_text_length)
3670 backup_input_pointer ();
3671 handle_variable_internal (action, name);
3676 handle_variable_internal (action, name)
3681 int delimiter, additional_text_present = 0;
3683 /* Only the first word of NAME is a valid tag. */
3686 while (*temp && (delimiter || !whitespace (*temp)))
3688 /* #if defined (SET_WITH_EQUAL) */
3689 if (*temp == '"' || *temp == '\'')
3691 if (*temp == delimiter)
3696 /* #endif SET_WITH_EQUAL */
3701 additional_text_present++;
3706 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3715 #if defined (SET_WITH_EQUAL)
3716 /* Allow a value to be saved along with a variable. The value is
3717 the text following an `=' sign in NAME, if any is present. */
3719 for (value = name; *value && *value != '='; value++);
3724 if (*value == '"' || *value == '\'')
3727 value[strlen (value) - 1] = 0;
3730 #else /* !SET_WITH_EQUAL */
3731 /* The VALUE of NAME is the remainder of the line sans
3733 if (additional_text_present)
3736 canon_white (value);
3740 #endif /* !SET_WITH_VALUE */
3752 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3753 read lines from the the file until we reach a matching
3754 "@end CONDITION". This means that we only take note of
3755 "@ifset/clear" and "@end" commands. */
3759 int orig_line_number = line_number;
3761 if (action == IFSET)
3762 strcpy (condition, "ifset");
3764 strcpy (condition, "ifclear");
3766 condition_len = strlen (condition);
3768 if ((action == IFSET && !set_p (name))
3769 || (action == IFCLEAR && set_p (name)))
3771 int level = 0, done = 0;
3773 while (!done && input_text_offset < input_text_length)
3775 char *freeable_line, *line;
3777 get_rest_of_line (0, &freeable_line);
3779 for (line = freeable_line; whitespace (*line); line++);
3781 if (*line == COMMAND_PREFIX &&
3782 (strncmp (line + 1, condition, condition_len) == 0))
3784 else if (strncmp (line, "@end", 4) == 0)
3786 char *cname = line + 4;
3789 while (*cname && whitespace (*cname))
3793 while (*temp && !whitespace (*temp))
3797 if (strcmp (cname, condition) == 0)
3807 free (freeable_line);
3811 file_line_error (input_filename, orig_line_number,
3812 _("Reached eof before matching @end %s"),
3815 /* We found the end of a false @ifset/ifclear. If we are
3816 in a menu, back up over the newline that ends the ifset,
3817 since that newline may also begin the next menu entry. */
3822 if (action == IFSET)
3823 begin_insertion (ifset);
3825 begin_insertion (ifclear);
3833 /* Execution of random text not in file. */
3836 char *string; /* The string buffer. */
3837 int size; /* The size of the buffer. */
3838 int in_use; /* Nonzero means string currently in use. */
3841 static EXECUTION_STRING **execution_strings = NULL;
3842 static int execution_strings_index = 0;
3843 static int execution_strings_slots = 0;
3846 get_execution_string (initial_size)
3850 EXECUTION_STRING *es = NULL;
3852 if (execution_strings)
3854 for (i = 0; i < execution_strings_index; i++)
3855 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
3857 es = execution_strings[i];
3864 if (execution_strings_index + 1 >= execution_strings_slots)
3866 execution_strings = xrealloc
3868 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
3869 for (; i < execution_strings_slots; i++)
3870 execution_strings[i] = NULL;
3873 execution_strings[execution_strings_index] =
3874 xmalloc (sizeof (EXECUTION_STRING));
3875 es = execution_strings[execution_strings_index];
3876 execution_strings_index++;
3883 if (initial_size > es->size)
3885 es->string = xrealloc (es->string, initial_size);
3886 es->size = initial_size;
3891 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
3892 entry in the execution_strings[] array and change the .STRING and
3893 .SIZE members of that entry as appropriate. */
3895 maybe_update_execution_strings (text, new_len)
3901 if (execution_strings)
3903 for (i = 0; i < execution_strings_index; i++)
3904 if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
3905 execution_strings[i]->string == *text)
3907 /* Don't ever shrink the string storage in execution_strings[]!
3908 execute_string assumes that it is always big enough to store
3909 every possible execution_string, and will break if that's
3910 not true. So we only enlarge the string storage if the
3911 current size isn't big enough. */
3912 if (execution_strings[i]->size < new_len)
3914 execution_strings[i]->string =
3915 *text = xrealloc (*text, new_len + 1);
3916 execution_strings[i]->size = new_len + 1;
3921 /* We should *never* end up here, since if we are inside
3922 execute_string, TEXT is always in execution_strings[]. */
3926 /* Execute the string produced by formatting the ARGs with FORMAT. This
3927 is like submitting a new file with @include. */
3929 #if defined (VA_FPRINTF) && __STDC__
3930 execute_string (char *format, ...)
3932 execute_string (format, va_alist)
3937 EXECUTION_STRING *es;
3943 es = get_execution_string (4000);
3944 temp_string = es->string;
3947 VA_START (ap, format);
3949 VA_SPRINTF (temp_string, format, ap);
3951 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
3952 #endif /* not VA_SPRINTF */
3956 input_text_offset = 0;
3957 input_text = temp_string;
3958 input_filename = xstrdup (input_filename);
3959 input_text_length = strlen (temp_string);
3963 free (input_filename);
3971 /* Return what would be output for STR (in newly-malloced memory), i.e.,
3972 expand Texinfo commands. If IMPLICIT_CODE is set, expand @code{STR}. */
3975 expansion (str, implicit_code)
3982 /* Inhibit any real output. */
3983 int start = output_paragraph_offset;
3984 int saved_paragraph_is_open = paragraph_is_open;
3985 int saved_output_column = output_column;
3987 /* Inhibit indentation and filling, so that extra newlines
3988 are not added to the expansion. (This is undesirable if
3989 we write the expanded text to macro_expansion_output_stream.) */
3990 int saved_filling_enabled = filling_enabled;
3991 int saved_indented_fill = indented_fill;
3992 int saved_no_indent = no_indent;
3993 int saved_escape_html = escape_html;
3994 int saved_meta_pos = meta_char_pos;
3995 int saved_last_char = last_inserted_character;
3996 int saved_last_nl = last_char_was_newline;
3998 /* If we are called in the middle of processing a command, we need
3999 to dup and save the global variable `command' (which holds the
4000 name of this command), since the recursive reader loop will free
4001 it from under our feet if it finds any macros in STR. */
4002 char *saved_command = command ? xstrdup (command) : NULL;
4004 filling_enabled = 0;
4009 inhibit_output_flushing ();
4010 paragraph_is_open = 1;
4011 execute_string (implicit_code ? "@code{%s}" : "%s", str);
4012 uninhibit_output_flushing ();
4014 /* Copy the expansion from the buffer. */
4015 length = output_paragraph_offset - start;
4016 result = xmalloc (1 + length);
4017 memcpy (result, (char *) (output_paragraph + start), length);
4020 /* Pretend it never happened. */
4021 free_and_clear (&command);
4022 command = saved_command;
4023 output_paragraph_offset = start;
4024 paragraph_is_open = saved_paragraph_is_open;
4025 output_column = saved_output_column;
4026 filling_enabled = saved_filling_enabled;
4027 indented_fill = saved_indented_fill;
4028 no_indent = saved_no_indent;
4029 escape_html = saved_escape_html;
4030 meta_char_pos = saved_meta_pos;
4031 last_inserted_character = saved_last_char;
4032 last_char_was_newline = saved_last_nl;
4038 /* Return text (info) expansion of STR no matter what the current output
4042 text_expansion (str)
4046 int save_html = html;
4049 ret = expansion (str, 0);
4056 /* Set the paragraph indentation variable to the value specified in STRING.
4058 `asis': Don't change existing indentation.
4059 `none': Remove existing indentation.
4060 NUM: Indent NUM spaces at the starts of paragraphs.
4061 If NUM is zero, we assume `none'.
4062 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
4064 set_paragraph_indent (string)
4067 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
4068 paragraph_start_indent = 0;
4069 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
4070 paragraph_start_indent = -1;
4073 if (sscanf (string, "%d", ¶graph_start_indent) != 1)
4077 if (paragraph_start_indent == 0)
4078 paragraph_start_indent = -1;