1 /* $FreeBSD: src/contrib/texinfo/makeinfo/makeinfo.c,v 1.9.2.2 2002/08/07 16:53:39 ru Exp $ */
2 /* $DragonFly: src/contrib/texinfo/makeinfo/Attic/makeinfo.c,v 1.2 2003/06/17 04:24:07 dillon Exp $ */
3 /* makeinfo -- convert Texinfo source into other formats.
4 $Id: makeinfo.c,v 1.205 2002/03/28 16:33:48 karl Exp $
6 Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 01, 02
7 Free Software Foundation, Inc.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 Makeinfo was authored by Brian Fox (bfox@ai.mit.edu). */
28 #define COMPILING_MAKEINFO
35 #include "insertion.h"
41 /* You can change some of the behavior of Makeinfo by changing the
44 /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
45 appear within an @table, @ftable, or @itemize environment to have
46 standard paragraph indentation. Without this, such paragraphs have
47 no starting indentation. */
48 /* #define INDENT_PARAGRAPHS_IN_TABLE */
50 /* Define PARAGRAPH_START_INDENT to be the amount of indentation that
51 the first lines of paragraphs receive by default, where no other
52 value has been specified. Users can change this value on the command
53 line, with the --paragraph-indent option, or within the texinfo file,
54 with the @paragraphindent command. */
55 #define PARAGRAPH_START_INDENT 3
57 /* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
58 wish to appear between paragraphs. A value of 1 creates a single blank
59 line between paragraphs. Paragraphs are defined by 2 or more consecutive
60 newlines in the input file (i.e., one or more blank lines). */
61 #define DEFAULT_PARAGRAPH_SPACING 1
63 /* Global variables. */
65 /* The output file name. */
66 char *output_filename = NULL;
68 /* Name of the output file that the user elected to pass on the command line.
69 Such a name overrides any name found with the @setfilename command. */
70 char *command_output_filename = NULL;
71 static char *save_command_output_filename = NULL;
73 /* Flags which control initial output string for xrefs. */
77 #define INITIAL_PARAGRAPH_SPACE 5000
78 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
80 /* The amount of indentation to add at the starts of paragraphs.
81 0 means don't change existing indentation at paragraph starts.
82 > 0 is amount to indent new paragraphs by.
83 < 0 means indent to column zero by removing indentation if necessary.
85 This is normally zero, but some people prefer paragraph starts to be
86 somewhat more indented than paragraph bodies. A pretty value for
88 int paragraph_start_indent = PARAGRAPH_START_INDENT;
90 /* Indentation that is pending insertion. We have this for hacking lines
91 which look blank, but contain whitespace. We want to treat those as
93 int pending_indent = 0;
95 /* The index in our internal command table of the currently
99 /* A search string which is used to find the first @setfilename. */
100 char setfilename_search[] =
102 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
104 /* Values for calling handle_variable_internal (). */
110 /* Flags controlling the operation of the program. */
112 /* Default is to remove output if there were errors. */
115 /* Default is to notify users of bad choices. */
116 int print_warnings = 1;
118 /* Number of errors that we tolerate on a given fileset. */
119 int max_error_level = 100;
121 /* The actual last inserted character. Note that this may be something
122 other than NEWLINE even if last_char_was_newline is 1. */
123 int last_inserted_character = 0;
125 /* Nonzero means that a newline character has already been
126 inserted, so close_paragraph () should insert one less. */
127 int line_already_broken = 0;
129 /* When nonzero we have finished an insertion (see end_insertion ()) and we
130 want to ignore false continued paragraph closings. */
131 int insertion_paragraph_closed = 0;
133 /* Nonzero means attempt to make all of the lines have fill_column width. */
134 int do_justification = 0;
136 /* Nonzero means don't replace whitespace with in HTML mode. */
139 typedef struct brace_element
141 struct brace_element *next;
142 COMMAND_FUNCTION *proc;
145 int in_fixed_width_font;
148 BRACE_ELEMENT *brace_stack = NULL;
150 extern void do_multitable (), end_multitable ();
152 void push_node_filename (), pop_node_filename ();
153 void remember_error ();
154 void convert_from_stream (), convert_from_file (), convert_from_loaded_file ();
155 void init_internals (), init_paragraph (), init_brace_stack ();
156 void init_insertion_stack (), init_indices ();
157 void init_tag_table (), write_tag_table (), write_tag_table_internal ();
158 void validate_file (), validate_other_references (), split_file ();
159 void free_node_references (), handle_variable ();
160 void handle_variable_internal ();
161 void normalize_node_name ();
162 void add_anchor_name ();
163 void free_node_node_references (), remember_node_node_reference ();
165 char **get_brace_args ();
168 static int end_of_sentence_p ();
169 static void isolate_nodename ();
171 void remember_brace (), remember_brace_1 ();
172 void pop_and_call_brace (), discard_braces ();
173 void add_word (), add_char (), insert (), flush_output ();
174 void insert_string ();
175 void close_paragraph ();
176 void ignore_blank_line ();
177 void do_flush_right_indentation (), discard_insertions ();
178 void start_paragraph (), indent ();
179 void inhibit_output_flushing (), uninhibit_output_flushing ();
180 int set_paragraph_indent ();
181 int self_delimiting (), search_forward ();
182 int multitable_item (), number_of_node ();
183 extern void add_link (), add_escaped_anchor_name ();
185 void me_execute_string_keep_state ();
186 void maybe_update_execution_strings ();
188 extern char *escape_string ();
189 extern void insert_html_tag ();
190 extern void sectioning_html ();
191 extern void add_link ();
193 #if defined (VA_FPRINTF) && __STDC__
194 /* Unfortunately we must use prototypes if we are to use <stdarg.h>. */
195 void add_word_args (char *, ...);
196 void execute_string (char *, ...);
198 void add_word_args ();
199 void execute_string ();
200 #endif /* no prototypes */
202 /* Error handling. */
204 /* Number of errors encountered. */
205 int errors_printed = 0;
207 /* Print the last error gotten from the file system. */
217 /* Print an error message, and return false. */
219 #if defined (VA_FPRINTF) && __STDC__
220 error (char *format, ...)
222 error (format, va_alist)
233 VA_START (ap, format);
235 VA_FPRINTF (stderr, format, ap);
237 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
238 #endif /* not VA_FPRINTF */
244 /* Just like error (), but print the input file and line number as well. */
246 #if defined (VA_FPRINTF) && __STDC__
247 file_line_error (char *infile, int lno, char *format, ...)
249 file_line_error (infile, lno, format, va_alist)
261 fprintf (stderr, "%s:%d: ", infile, lno);
263 VA_START (ap, format);
265 VA_FPRINTF (stderr, format, ap);
267 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
268 #endif /* not VA_FPRINTF */
271 fprintf (stderr, ".\n");
274 /* Just like file_line_error (), but take the input file and the line
275 number from global variables. */
277 #if defined (VA_FPRINTF) && __STDC__
278 line_error (char *format, ...)
280 line_error (format, va_alist)
290 fprintf (stderr, "%s:%d: ", input_filename, line_number);
292 VA_START (ap, format);
294 VA_FPRINTF (stderr, format, ap);
296 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
297 #endif /* not VA_FPRINTF */
300 fprintf (stderr, ".\n");
304 #if defined (VA_FPRINTF) && __STDC__
305 warning (char *format, ...)
307 warning (format, va_alist)
318 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
320 VA_START (ap, format);
322 VA_FPRINTF (stderr, format, ap);
324 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
325 #endif /* not VA_FPRINTF */
328 fprintf (stderr, ".\n");
333 /* Remember that an error has been printed. If more than
334 max_error_level have been printed, then exit the program. */
339 if (max_error_level && (errors_printed > max_error_level))
341 fprintf (stderr, _("Too many errors! Gave up.\n"));
348 /* The other side of a malformed expression. */
352 line_error (_("Misplaced %c"), '}');
357 /* Display the version info of this invocation of Makeinfo. */
359 print_version_info ()
361 printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION);
364 /* If EXIT_VALUE is zero, print the full usage message to stdout.
365 Otherwise, just say to use --help for more info.
366 Then exit with EXIT_VALUE. */
372 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
375 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname);
379 Translate Texinfo source documentation to various other formats, by default\n\
380 Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
384 --error-limit=NUM quit after NUM errors (default %d).\n\
385 --force preserve output even if errors.\n\
386 --help display this help and exit.\n\
387 --no-validate suppress node cross-reference validation.\n\
388 --no-warn suppress warnings (but not errors).\n\
389 --reference-limit=NUM warn about at most NUM references (default %d).\n\
390 -v, --verbose explain what is being done.\n\
391 --version display version information and exit.\n"),
392 max_error_level, reference_warning_limit);
395 /* xgettext: no-wrap */
397 Output format selection (default is to produce Info):\n\
398 --docbook output DocBook rather than Info.\n\
399 --html output HTML rather than Info.\n\
400 --xml output XML (TexinfoML) rather than Info.\n\
404 General output options:\n\
405 -E, --macro-expand FILE output macro-expanded source to FILE.\n\
406 ignoring any @setfilename.\n\
407 --no-headers suppress node separators, Node: lines, and menus\n\
408 from Info output (thus producing plain text)\n\
409 or from HTML (thus producing shorter output);\n\
410 also, write to standard output by default.\n\
411 --no-split suppress splitting of Info or HTML output,\n\
412 generate only one output file.\n\
413 --number-sections output chapter and sectioning numbers.\n\
414 -o, --output=FILE output to FILE (directory if split HTML),\n\
418 Options for Info and plain text:\n\
419 --enable-encoding output accented and special characters in\n\
420 Info output based on @documentencoding.\n\
421 --fill-column=NUM break Info lines at NUM characters (default %d).\n\
422 --footnote-style=STYLE output footnotes in Info according to STYLE:\n\
423 `separate' to put them in their own node;\n\
424 `end' to put them at the end of the node\n\
425 in which they are defined (default).\n\
426 --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
427 If VAL is `none', do not indent; if VAL is\n\
428 `asis', preserve existing indentation.\n\
429 --split-size=NUM split Info files at size NUM (default %d).\n"),
430 fill_column, paragraph_start_indent,
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\
445 Conditional processing in input:\n\
446 --ifhtml process @ifhtml and @html even if not generating HTML.\n\
447 --ifinfo process @ifinfo even if not generating Info.\n\
448 --ifplaintext process @ifplaintext even if not generating plain text.\n\
449 --iftex process @iftex and @tex; implies --no-split.\n\
450 --no-ifhtml do not process @ifhtml and @html text.\n\
451 --no-ifinfo do not process @ifinfo text.\n\
452 --no-ifplaintext do not process @ifplaintext text.\n\
453 --no-iftex do not process @iftex and @tex text.\n\
457 The defaults for the @if... conditionals depend on the output format:\n\
458 if generating HTML, --ifhtml is on and the others are off;\n\
459 if generating Info, --ifinfo is on and the others are off;\n\
460 if generating plain text, --ifplaintext is on and the others are off;\n\
465 makeinfo foo.texi write Info to foo's @setfilename\n\
466 makeinfo --html foo.texi write HTML to @setfilename\n\
467 makeinfo --xml foo.texi write XML to @setfilename\n\
468 makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\
469 makeinfo --no-headers foo.texi write plain text to standard output\n\
471 makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
472 makeinfo --number-sections foo.texi write Info with numbered sections\n\
473 makeinfo --no-split foo.texi write one Info file however big\n\
477 Email bug reports to bug-texinfo@gnu.org,\n\
478 general questions and discussion to help-texinfo@gnu.org.\n\
479 Texinfo home page: http://www.gnu.org/software/texinfo/"));
484 struct option long_options[] =
486 { "commands-in-node-names", 0, &expensive_validation, 1 },
487 { "docbook", 0, 0, 'd' },
488 { "enable-encoding", 0, &enable_encoding, 1 },
489 { "error-limit", 1, 0, 'e' },
490 { "fill-column", 1, 0, 'f' },
491 { "footnote-style", 1, 0, 's' },
492 { "force", 0, &force, 1 },
493 { "help", 0, 0, 'h' },
494 { "html", 0, 0, 'w' },
495 { "ifhtml", 0, &process_html, 1 },
496 { "ifinfo", 0, &process_info, 1 },
497 { "ifplaintext", 0, &process_plaintext, 1 },
498 { "iftex", 0, &process_tex, 1 },
499 { "macro-expand", 1, 0, 'E' },
500 { "no-headers", 0, &no_headers, 1 },
501 { "no-ifhtml", 0, &process_html, 0 },
502 { "no-ifinfo", 0, &process_info, 0 },
503 { "no-ifplaintext", 0, &process_plaintext, 0 },
504 { "no-iftex", 0, &process_tex, 0 },
505 { "no-number-footnotes", 0, &number_footnotes, 0 },
506 { "no-number-sections", 0, &number_sections, 0 },
507 { "no-pointer-validate", 0, &validating, 0 },
508 { "no-split", 0, &splitting, 0 },
509 { "no-validate", 0, &validating, 0 },
510 { "no-warn", 0, &print_warnings, 0 },
511 { "number-footnotes", 0, &number_footnotes, 1 },
512 { "number-sections", 0, &number_sections, 1 },
513 { "output", 1, 0, 'o' },
514 { "paragraph-indent", 1, 0, 'p' },
515 { "reference-limit", 1, 0, 'r' },
516 { "split-size", 1, 0, 'S'},
517 { "verbose", 0, &verbose_mode, 1 },
518 { "version", 0, 0, 'V' },
519 { "xml", 0, 0, 'x' },
523 /* For each file mentioned in the command line, process it, turning
524 Texinfo commands into wonderfully formatted output text. */
530 extern int errors_printed;
532 int reading_from_stdin = 0;
534 #ifdef HAVE_SETLOCALE
535 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
536 of the argument to @multicolumn. */
537 setlocale (LC_TIME, "");
538 setlocale (LC_MESSAGES, "");
539 setlocale (LC_CTYPE, "");
540 setlocale (LC_COLLATE, "");
543 /* Set the text message domain. */
544 bindtextdomain (PACKAGE, LOCALEDIR);
545 textdomain (PACKAGE);
547 /* Parse argument flags from the input line. */
548 while ((c = getopt_long (argc, argv, "D:de:E:f:hI:o:p:P:r:s:U:vV:wx",
549 long_options, &ind)) != EOF)
551 if (c == 0 && long_options[ind].flag == 0)
552 c = long_options[ind].val;
558 /* User specified variable to set or clear. */
559 handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
562 case 'd': /* --docbook */
568 case 'e': /* --error-limit */
569 if (sscanf (optarg, "%d", &max_error_level) != 1)
572 _("%s: %s arg must be numeric, not `%s'.\n"),
573 "--error-limit", progname, optarg);
578 case 'E': /* --macro-expand */
579 if (!macro_expansion_output_stream)
581 macro_expansion_filename = optarg;
582 macro_expansion_output_stream
583 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
584 if (!macro_expansion_output_stream)
585 error (_("Couldn't open macro expansion output `%s'"), optarg);
588 error (_("Cannot specify more than one macro expansion output"));
591 case 'f': /* --fill-column */
592 if (sscanf (optarg, "%d", &fill_column) != 1)
595 _("%s: %s arg must be numeric, not `%s'.\n"),
596 "--fill-column", progname, optarg);
601 case 'h': /* --help */
606 /* Append user-specified dir to include file path. */
607 if (!include_files_path)
608 include_files_path = xstrdup (".");
610 include_files_path = (char *)
611 xrealloc (include_files_path,
612 2 + strlen (include_files_path) + strlen (optarg));
613 strcat (include_files_path, PATH_SEP);
614 strcat (include_files_path, optarg);
617 case 'o': /* --output */
618 command_output_filename = xstrdup (optarg);
619 save_command_output_filename = command_output_filename;
622 case 'p': /* --paragraph-indent */
623 if (set_paragraph_indent (optarg) < 0)
626 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
633 /* Prepend user-specified include dir to include path. */
634 if (!include_files_path)
636 include_files_path = xstrdup (optarg);
637 include_files_path = xrealloc (include_files_path,
638 strlen (include_files_path) + 3); /* 3 for ":.\0" */
639 strcat (strcat (include_files_path, PATH_SEP), ".");
643 char *tmp = xstrdup (include_files_path);
644 include_files_path = xrealloc (include_files_path,
645 strlen (include_files_path) + strlen (optarg) + 2); /* 2 for ":\0" */
646 strcpy (include_files_path, optarg);
647 strcat (include_files_path, ":");
648 strcat (include_files_path, tmp);
653 case 'r': /* --reference-limit */
654 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
657 _("%s: %s arg must be numeric, not `%s'.\n"),
658 "--reference-limit", progname, optarg);
663 case 's': /* --footnote-style */
664 if (set_footnote_style (optarg) < 0)
667 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
671 footnote_style_preset = 1;
674 case 'S': /* --split-size */
675 if (sscanf (optarg, "%d", &split_size) != 1)
678 _("%s: %s arg must be numeric, not `%s'.\n"),
679 "--split-size", progname, optarg);
688 case 'V': /* --version */
689 print_version_info ();
691 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
692 There is NO warranty. You may redistribute this software\n\
693 under the terms of the GNU General Public License.\n\
694 For more information about these matters, see the files named COPYING.\n"),
699 case 'w': /* --html */
704 case 'x': /* --xml */
716 expensive_validation = 0;
720 /* Check to see if input is a file. If so, process that. */
721 if (!isatty (fileno (stdin)))
722 reading_from_stdin = 1;
725 fprintf (stderr, _("%s: missing file argument.\n"), progname);
732 if (html && splitting)
733 { /* --no-headers --no-split --html indicates confusion. */
735 "%s: --no-headers conflicts with --no-split for --html.\n",
740 /* --no-headers implies --no-split. */
743 /* If the user did not specify an output file, use stdout. */
744 if (!command_output_filename)
745 command_output_filename = xstrdup ("-");
748 if (process_info == -1)
749 { /* no explicit --[no-]ifinfo option, so we'll do @ifinfo
750 if we're generating info or (for compatibility) plain text. */
751 process_info = !html && !xml;
754 if (process_plaintext == -1)
755 { /* no explicit --[no-]ifplaintext option, so we'll do @ifplaintext
756 if we're generating plain text. */
757 process_plaintext = no_headers && !html && !xml;
761 print_version_info ();
763 /* Remaining arguments are file names of texinfo files.
764 Convert them, one by one. */
765 if (!reading_from_stdin)
767 while (optind != argc)
768 convert_from_file (argv[optind++]);
771 convert_from_stream (stdin, "stdin");
773 return errors_printed ? 2 : 0;
777 /* Hacking tokens and strings. */
779 /* Return the next token as a string pointer. We cons the string. */
786 /* If the first character to be read is self-delimiting, then that
787 is the command itself. */
788 character = curchar ();
789 if (self_delimiting (character))
793 if (character == '\n')
796 result = xstrdup (" ");
801 for (i = 0; ((input_text_offset != input_text_length)
802 && (character = curchar ())
803 && command_char (character));
804 i++, input_text_offset++);
805 result = xmalloc (i + 1);
806 memcpy (result, &input_text[input_text_offset - i], i);
811 /* Return nonzero if CHARACTER is self-delimiting. */
813 self_delimiting (character)
816 /* @; and @\ are not Texinfo commands, but they are listed here
817 anyway. I don't know why. --karl, 10aug96. */
818 return strchr ("~{|}`^\\@?=;:.-,*\'\" !\n\t", character) != NULL;
821 /* Clear whitespace from the front and end of string. */
826 int len = strlen (string);
832 for (x = 0; x < len; x++)
834 if (!cr_or_whitespace (string[x]))
836 strcpy (string, string + x);
840 len = strlen (string);
843 while (len > -1 && cr_or_whitespace (string[len]))
848 /* Bash STRING, replacing all whitespace with just one space. */
850 fix_whitespace (string)
853 char *temp = xmalloc (strlen (string) + 1);
854 int string_index = 0;
858 canon_white (string);
860 while (string[string_index])
862 c = temp[temp_index++] = string[string_index++];
864 if (c == ' ' || c == '\n' || c == '\t')
866 temp[temp_index - 1] = ' ';
867 while ((c = string[string_index]) && (c == ' ' ||
873 temp[temp_index] = 0;
874 strcpy (string, temp);
878 /* Discard text until the desired string is found. The string is
879 included in the discarded text. */
881 discard_until (string)
884 int temp = search_forward (string, input_text_offset);
886 int tt = (temp < 0) ? input_text_length : temp + strlen (string);
887 int from = input_text_offset;
889 /* Find out what line we are on. */
891 if (input_text[from++] == '\n')
896 input_text_offset = input_text_length - strlen (string);
898 if (strcmp (string, "\n") != 0)
900 line_error (_("Expected `%s'"), string);
905 input_text_offset = temp;
907 input_text_offset += strlen (string);
910 /* Read characters from the file until we are at MATCH.
911 Place the characters read into STRING.
912 On exit input_text_offset is after the match string.
913 Return the offset where the string starts. */
915 get_until (match, string)
916 char *match, **string;
918 int len, current_point, x, new_point, tem;
920 current_point = x = input_text_offset;
921 new_point = search_forward (match, input_text_offset);
924 new_point = input_text_length;
925 len = new_point - current_point;
927 /* Keep track of which line number we are at. */
928 tem = new_point + (strlen (match) - 1);
930 if (input_text[x++] == '\n')
933 *string = xmalloc (len + 1);
935 memcpy (*string, &input_text[current_point], len);
938 /* Now leave input_text_offset in a consistent state. */
939 input_text_offset = tem;
941 if (input_text_offset > input_text_length)
942 input_text_offset = input_text_length;
947 /* Replace input_text[FROM .. TO] with its expansion. */
949 replace_with_expansion (from, to)
953 unsigned xp_len, new_len;
954 char *old_input = input_text;
955 unsigned raw_len = *to - from;
958 /* The rest of the code here moves large buffers, so let's
959 not waste time if the input cannot possibly expand
960 into anything. Unfortunately, we cannot avoid expansion
961 when we see things like @code etc., even if they only
962 asked for expansion of macros, since any Texinfo command
963 can be potentially redefined with a macro. */
964 if (only_macro_expansion &&
965 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
968 /* Get original string from input. */
969 str = xmalloc (raw_len + 1);
970 memcpy (str, input_text + from, raw_len);
973 /* We are going to relocate input_text, so we had better output
974 pending portion of input_text now, before the pointer changes. */
975 if (macro_expansion_output_stream && !executing_string
976 && !me_inhibit_expansion)
977 append_to_expansion_output (from);
980 xp = expansion (str, 0);
981 xp_len = strlen (xp);
984 /* Plunk the expansion into the middle of `input_text' --
985 which is terminated by a newline, not a null. Avoid
986 expensive move of the rest of the input if the expansion
987 has the same length as the original string. */
988 if (xp_len != raw_len)
990 new_len = from + xp_len + input_text_length - *to + 1;
991 if (executing_string)
992 { /* If we are in execute_string, we might need to update
993 the relevant element in the execution_strings[] array,
994 since it could have to be relocated from under our
995 feet. (input_text is reallocated here as well, if needed.) */
996 maybe_update_execution_strings (&input_text, new_len);
998 else if (new_len > input_text_length + 1)
999 /* Don't bother to realloc if we have enough space. */
1000 input_text = xrealloc (input_text, new_len);
1002 memmove (input_text + from + xp_len,
1003 input_text + *to, input_text_length - *to + 1);
1005 *to += xp_len - raw_len;
1006 /* Since we change input_text_length here, the comparison above
1007 isn't really valid, but it seems the worst that might happen is
1008 an extra xrealloc or two, so let's not worry. */
1009 input_text_length += xp_len - raw_len;
1011 memcpy (input_text + from, xp, xp_len);
1014 /* Synchronize the macro-expansion pointers with our new input_text. */
1015 if (input_text != old_input)
1016 forget_itext (old_input);
1017 if (macro_expansion_output_stream && !executing_string)
1018 remember_itext (input_text, from);
1021 /* Read characters from the file until we are at MATCH or end of line.
1022 Place the characters read into STRING. If EXPAND is nonzero,
1023 expand the text before looking for MATCH for those cases where
1024 MATCH might be produced by some macro. */
1026 get_until_in_line (expand, match, string)
1028 char *match, **string;
1030 int real_bottom = input_text_length;
1031 int limit = search_forward ("\n", input_text_offset);
1033 limit = input_text_length;
1035 /* Replace input_text[input_text_offset .. limit-1] with its expansion.
1036 This allows the node names and menu entries themselves to be
1037 constructed via a macro, as in:
1039 Together: \p\ & \q\.
1042 @node @foo{A,B}, next, prev, top
1044 Otherwise, the `,' separating the macro args A and B is taken as
1045 the node argument separator, so the node name is `@foo{A'. This
1046 expansion is only necessary on the first call, since we expand the
1050 replace_with_expansion (input_text_offset, &limit);
1053 real_bottom = input_text_length;
1054 input_text_length = limit;
1055 get_until (match, string);
1056 input_text_length = real_bottom;
1060 get_rest_of_line (expand, string)
1069 /* Don't expand non-macros in input, since we want them
1070 intact in the macro-expanded output. */
1071 only_macro_expansion++;
1072 get_until_in_line (1, "\n", &tem);
1073 only_macro_expansion--;
1074 *string = expansion (tem, 0);
1078 get_until_in_line (0, "\n", string);
1080 canon_white (*string);
1082 if (curchar () == '\n') /* as opposed to the end of the file... */
1085 input_text_offset++;
1090 /* Backup the input pointer to the previous character, keeping track
1091 of the current line number. */
1093 backup_input_pointer ()
1095 if (input_text_offset)
1097 input_text_offset--;
1098 if (curchar () == '\n')
1103 /* Read characters from the file until we are at MATCH or closing brace.
1104 Place the characters read into STRING. */
1106 get_until_in_braces (match, string)
1107 char *match, **string;
1111 int match_len = strlen (match);
1113 for (i = input_text_offset; i < input_text_length; i++)
1115 if (i < input_text_length - 1 && input_text[i] == '@')
1117 i++; /* skip commands like @, and @{ */
1120 else if (input_text[i] == '{')
1122 else if (input_text[i] == '}')
1125 /* If looking for a brace, don't stop at the interior brace,
1126 like after "baz" in "@foo{something @bar{baz} more}". */
1130 else if (input_text[i] == '\n')
1134 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1138 match_len = i - input_text_offset;
1139 temp = xmalloc (2 + match_len);
1140 memcpy (temp, input_text + input_text_offset, match_len);
1141 temp[match_len] = 0;
1142 input_text_offset = i;
1146 /* Converting a file. */
1148 /* Convert the file named by NAME. The output is saved on the file
1149 named as the argument to the @setfilename command. */
1150 static char *suffixes[] = {
1151 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1152 have "texinfo.txi" and "texinfo.tex" in the same directory, the
1153 former is used rather than the latter, due to file name truncation. */
1163 initialize_conversion ()
1170 /* This is used for splitting the output file and for doing section
1171 headings. It was previously initialized in `init_paragraph', but its
1172 use there loses with the `init_paragraph' calls done by the
1173 multitable code; the tag indices get reset to zero. */
1174 output_position = 0;
1177 typedef struct generic_list {
1178 struct generic_list *next;
1181 /* Reverse the chain of structures in LIST. Output the new head
1182 of the chain. You should always assign the output value of this
1183 function to something, or you will lose the chain. */
1189 GENERIC_LIST *prev = NULL;
1201 /* We read in multiples of 4k, simply because it is a typical pipe size
1203 #define READ_BUFFER_GROWTH (4 * 4096)
1205 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1206 source of the stream is named NAME. */
1208 convert_from_stream (stream, name)
1212 char *buffer = NULL;
1213 int buffer_offset = 0, buffer_size = 0;
1215 initialize_conversion ();
1217 /* Read until the end of the stream. This isn't strictly correct, since
1218 the texinfo input may end before the stream ends, but it is a quick
1219 working hueristic. */
1220 while (!feof (stream))
1224 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1226 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1228 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1236 buffer_offset += count;
1241 /* Set the globals to the new file. */
1242 input_text = buffer;
1243 input_text_length = buffer_offset;
1244 input_filename = xstrdup (name);
1245 node_filename = xstrdup (name);
1246 input_text_offset = 0;
1249 /* Not strictly necessary. This magic prevents read_token () from doing
1250 extra unnecessary work each time it is called (that is a lot of times).
1251 The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1252 input_text[input_text_length] = '\n';
1254 convert_from_loaded_file (name);
1258 convert_from_file (name)
1262 char *filename = xmalloc (strlen (name) + 50);
1264 initialize_conversion ();
1266 /* Try to load the file specified by NAME, concatenated with our
1267 various suffixes. Prefer files like `makeinfo.texi' to
1269 for (i = 0; suffixes[i]; i++)
1271 strcpy (filename, name);
1272 strcat (filename, suffixes[i]);
1274 if (find_and_load (filename))
1277 if (!suffixes[i][0] && strrchr (filename, '.'))
1279 fs_error (filename);
1292 input_filename = filename;
1294 convert_from_loaded_file (name);
1297 /* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
1298 "/foo/bar/baz/baz.html". This routine is called only if html && splitting.
1300 Split html output goes into the subdirectory of the toplevel
1301 filename, without extension. For example:
1302 @setfilename foo.info
1303 produces output in files foo/index.html, foo/second-node.html, ...
1305 But if the user said -o foo.whatever on the cmd line, then use
1306 foo.whatever unchanged. */
1309 insert_toplevel_subdirectory (output_filename)
1310 char *output_filename;
1312 char *dir, *subdir, *base, *basename, *p;
1315 static const char index_name[] = "index.html";
1316 const int index_len = sizeof (index_name) - 1;
1318 strcpy (buf, output_filename);
1319 dir = pathname_part (buf);
1320 base = filename_part (buf);
1321 basename = xstrdup (base); /* remember real @setfilename name */
1322 p = dir + strlen (dir) - 1;
1323 if (p > dir && IS_SLASH (*p))
1325 p = strrchr (base, '.');
1329 /* Split html output goes into subdirectory of toplevel name. */
1331 if (FILENAME_CMP (base, filename_part (dir)) != 0)
1333 if (save_command_output_filename
1334 && STREQ (output_filename, save_command_output_filename))
1335 subdir = basename; /* from user, use unchanged */
1337 subdir = base; /* implicit, omit suffix */
1340 free (output_filename);
1341 output_filename = xmalloc (strlen (dir) + 1
1342 + strlen (basename) + 1
1345 strcpy (output_filename, dir);
1347 strcat (output_filename, "/");
1348 strcat (output_filename, subdir);
1349 if (mkdir (output_filename, 0777) == -1 && errno != EEXIST
1350 /* output_filename might exist, but be a non-directory. */
1351 || (stat (output_filename, &st) == 0 && !S_ISDIR (st.st_mode)))
1352 { /* that failed, try subdir name with .html */
1353 strcpy (output_filename, dir);
1355 strcat (output_filename, "/");
1356 strcat (output_filename, basename);
1357 if (mkdir (output_filename, 0777) == -1)
1359 char *errmsg = strerror (errno);
1361 if ((errno == EEXIST
1366 && (stat (output_filename, &st) == 0 && !S_ISDIR (st.st_mode)))
1367 errmsg = _("File exists, but is not a directory");
1368 line_error (_("Can't create directory `%s': %s"),
1369 output_filename, errmsg);
1372 strcat (output_filename, "/");
1374 else if (strlen (subdir))
1375 strcat (output_filename, "/");
1376 strcat (output_filename, index_name);
1377 return output_filename;
1380 /* FIXME: this is way too hairy */
1382 convert_from_loaded_file (name)
1385 char *real_output_filename = NULL;
1387 remember_itext (input_text, 0);
1389 input_text_offset = 0;
1391 /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1393 if (looking_at ("\\input"))
1394 discard_until ("\n");
1396 /* Search this file looking for the special string which starts conversion.
1397 Once found, we may truly begin. */
1398 while (input_text_offset >= 0)
1401 search_forward (setfilename_search, input_text_offset);
1403 if (input_text_offset == 0
1404 || (input_text_offset > 0
1405 && input_text[input_text_offset -1] == '\n'))
1407 else if (input_text_offset > 0)
1408 input_text_offset++;
1411 if (input_text_offset < 0)
1413 if (!command_output_filename)
1415 #if defined (REQUIRE_SETFILENAME)
1416 error (_("No `%s' found in `%s'"), setfilename_search, name);
1419 command_output_filename = output_name_from_input_name (name);
1420 #endif /* !REQUIRE_SETFILENAME */
1424 int i, end_of_first_line;
1426 /* Find the end of the first line in the file. */
1427 for (i = 0; i < input_text_length - 1; i++)
1428 if (input_text[i] == '\n')
1431 end_of_first_line = i + 1;
1433 for (i = 0; i < end_of_first_line; i++)
1435 if ((input_text[i] == '\\') &&
1436 (strncmp (input_text + i + 1, "input", 5) == 0))
1438 input_text_offset = i;
1445 input_text_offset += strlen (setfilename_search);
1447 if (!command_output_filename)
1449 get_until ("\n", &output_filename); /* read rest of line */
1450 if (xml && !docbook)
1451 xml_begin_document (output_filename);
1453 { /* Change any extension to .html or .xml. */
1454 char *html_name, *directory_part, *basename_part, *temp;
1456 canon_white (output_filename);
1457 directory_part = pathname_part (output_filename);
1459 basename_part = filename_part (output_filename);
1461 /* Zap any existing extension. */
1462 temp = strrchr (basename_part, '.');
1466 /* Construct new filename. */
1467 html_name = xmalloc (strlen (directory_part)
1468 + strlen (basename_part) + 6);
1469 strcpy (html_name, directory_part);
1470 strcat (html_name, basename_part);
1471 strcat (html_name, html ? ".html" : ".xml");
1473 /* Replace name from @setfilename with the html name. */
1474 free (output_filename);
1475 output_filename = html_name;
1480 if (input_text_offset != -1)
1481 discard_until ("\n");
1483 input_text_offset = 0;
1485 real_output_filename = output_filename = command_output_filename;
1486 command_output_filename = NULL; /* for included files or whatever */
1489 canon_white (output_filename);
1490 toplevel_output_filename = xstrdup (output_filename);
1492 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1494 if (macro_expansion_filename
1495 && strcmp (macro_expansion_filename, "-") == 0)
1498 _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1500 macro_expansion_output_stream = NULL;
1502 real_output_filename = xstrdup (real_output_filename);
1503 output_stream = stdout;
1504 splitting = 0; /* Cannot split when writing to stdout. */
1508 if (html && splitting)
1510 if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
1511 || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
1514 output_filename = insert_toplevel_subdirectory (output_filename);
1515 real_output_filename = xstrdup (output_filename);
1517 else if (!real_output_filename)
1518 real_output_filename = expand_filename (output_filename, name);
1520 real_output_filename = xstrdup (real_output_filename);
1522 output_stream = fopen (real_output_filename, "w");
1525 set_current_output_filename (real_output_filename);
1528 printf (_("Making %s file `%s' from `%s'.\n"),
1533 output_filename, input_filename);
1535 if (output_stream == NULL)
1537 fs_error (real_output_filename);
1541 /* Make the displayable filename from output_filename. Only the base
1542 portion of the filename need be displayed. */
1543 flush_output (); /* in case there was no @bye */
1544 if (output_stream != stdout)
1545 pretty_output_filename = filename_part (output_filename);
1547 pretty_output_filename = xstrdup ("stdout");
1549 /* For this file only, count the number of newlines from the top of
1550 the file to here. This way, we keep track of line numbers for
1551 error reporting. Line_number starts at 1, since the user isn't
1556 while (temp != input_text_offset)
1557 if (input_text[temp++] == '\n')
1561 /* html fixxme: should output this as trailer on first page. */
1562 if (!no_headers && !html && !xml)
1563 add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
1564 output_filename, VERSION, input_filename);
1569 xml_end_document ();
1573 discard_insertions (0);
1575 flush_file_stack ();
1577 if (macro_expansion_output_stream)
1579 fclose (macro_expansion_output_stream);
1580 if (errors_printed && !force
1581 && strcmp (macro_expansion_filename, "-") != 0
1582 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1583 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1585 fprintf (stderr, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1586 progname, macro_expansion_filename);
1587 if (unlink (macro_expansion_filename) < 0)
1588 perror (macro_expansion_filename);
1594 output_pending_notes ();
1597 tag_table = (TAG_ENTRY *) reverse_list (tag_table);
1598 if (!no_headers && !html)
1605 add_word ("</body></html>\n");
1609 flush_output (); /* in case there was no @bye */
1610 if (output_stream != stdout)
1611 fclose (output_stream);
1613 /* If validating, then validate the entire file right now. */
1615 validate_file (tag_table);
1617 /* If we need to output the table of contents, do it now. */
1618 if (contents_filename || shortcontents_filename)
1621 if (splitting && !html && (!errors_printed || force))
1622 split_file (real_output_filename, split_size);
1623 else if (errors_printed
1625 && strcmp (real_output_filename, "-") != 0
1626 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1627 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1628 { /* If there were errors, and no --force, remove the output. */
1629 fprintf (stderr, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1630 progname, real_output_filename);
1631 if (unlink (real_output_filename) < 0)
1632 perror (real_output_filename);
1635 free (real_output_filename);
1639 free_and_clear (pointer)
1649 /* Initialize some state. */
1653 free_and_clear (&output_filename);
1654 free_and_clear (&command);
1655 free_and_clear (&input_filename);
1656 free_node_references ();
1657 free_node_node_references ();
1659 init_insertion_stack ();
1660 init_brace_stack ();
1661 current_node = NULL; /* sometimes already freed */
1666 non_top_node_seen = 0;
1673 free_and_clear (&output_paragraph);
1674 output_paragraph = xmalloc (paragraph_buffer_len);
1675 output_paragraph[0] = 0;
1676 output_paragraph_offset = 0;
1678 paragraph_is_open = 0;
1683 /* This is called from `reader_loop' when we are at the * beginning a
1687 handle_menu_entry ()
1691 /* Ugh, glean_node_from_menu wants to read the * itself. */
1692 input_text_offset--;
1694 /* Find node name in menu entry and save it in references list for
1695 later validation. Use followed_reference type for detailmenu
1696 references since we don't want to use them for default node pointers. */
1697 tem = glean_node_from_menu (1, in_detailmenu
1698 ? followed_reference : menu_reference);
1701 { /* Start a menu item with the cleaned-up line. Put an anchor
1702 around the start text (before `:' or the node name). */
1705 discard_until ("* ");
1707 /* The line number was already incremented in reader_loop when we
1708 saw the newline, and discard_until has now incremented again. */
1711 if (had_menu_commentary)
1713 add_word ("<ul>\n");
1714 had_menu_commentary = 0;
1717 else if (!in_paragraph && !paragraph_is_open)
1729 add_word ("<li><a");
1730 if (next_menu_item_number <= 9)
1732 add_word(" accesskey=");
1733 add_word_args("%d", next_menu_item_number);
1734 next_menu_item_number++;
1736 add_word (" href=\"");
1737 string = expansion (tem, 0);
1738 add_anchor_name (string, 1);
1742 /* The menu item may use macros, so expand them now. */
1743 only_macro_expansion++;
1744 get_until_in_line (1, ":", &string);
1745 only_macro_expansion--;
1746 execute_string ("%s", string); /* get escaping done */
1751 if (looking_at ("::"))
1752 discard_until (":");
1754 { /* discard the node name */
1755 get_until_in_line (0, ".", &string);
1758 input_text_offset++; /* discard the second colon or the period */
1761 else if (xml && tem)
1763 xml_start_menu_entry (tem);
1766 { /* For Info output, we can just use the input and the main case in
1767 reader_loop where we output what comes in. Just move off the *
1768 so the next time through reader_loop we don't end up back here. */
1770 input_text_offset += 2; /* undo the pointer back-up above. */
1777 /* Find the command corresponding to STRING. If the command is found,
1778 return a pointer to the data structure. Otherwise return -1. */
1780 get_command_entry (string)
1785 for (i = 0; command_table[i].name; i++)
1786 if (strcmp (command_table[i].name, string) == 0)
1787 return &command_table[i];
1789 /* This command is not in our predefined command table. Perhaps
1790 it is a user defined command. */
1791 for (i = 0; i < user_command_array_len; i++)
1792 if (user_command_array[i] &&
1793 (strcmp (user_command_array[i]->name, string) == 0))
1794 return user_command_array[i];
1796 /* We never heard of this command. */
1797 return (COMMAND *) -1;
1800 /* input_text_offset is right at the command prefix character.
1801 Read the next token to determine what to do. Return zero
1802 if there's no known command or macro after the prefix character. */
1807 int old_text_offset = input_text_offset++;
1809 free_and_clear (&command);
1810 command = read_token ();
1812 /* Check to see if this command is a macro. If so, execute it here. */
1816 def = find_macro (command);
1820 /* We disallow recursive use of a macro call. Inhibit the expansion
1821 of this macro during the life of its execution. */
1822 if (!(def->flags & ME_RECURSE))
1825 execute_macro (def);
1827 if (!(def->flags & ME_RECURSE))
1834 if (only_macro_expansion)
1836 /* Back up to the place where we were called, so the
1837 caller will have a chance to process this non-macro. */
1838 input_text_offset = old_text_offset;
1842 /* Perform alias expansion */
1843 command = alias_expand (command);
1845 if (enclosure_command (command))
1847 remember_brace (enclosure_expand);
1848 enclosure_expand (START, output_paragraph_offset, 0);
1852 entry = get_command_entry (command);
1853 if (entry == (COMMAND *)-1)
1855 line_error (_("Unknown command `%s'"), command);
1859 if (entry->argument_in_braces == BRACE_ARGS)
1860 remember_brace (entry->proc);
1861 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
1863 if (curchar () == '{')
1864 remember_brace (entry->proc);
1866 { /* No braces, so arg is next char. */
1868 int saved_offset = output_paragraph_offset;
1869 (*(entry->proc)) (START, output_paragraph_offset, 0);
1871 /* Possibilities left for the next character: @ (error), }
1872 (error), whitespace (skip) anything else (normal char). */
1877 line_error (_("Use braces to give a command as an argument to @%s"),
1883 /* Our caller will give the error message, because this }
1884 won't match anything. */
1889 input_text_offset++;
1890 (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
1895 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
1897 (*(entry->proc)) (START, output_paragraph_offset, 0);
1901 /* Okay, we are ready to start the conversion. Call the reader on
1902 some text, and fill the text as it is output. Handle commands by
1903 remembering things like open braces and the current file position on a
1904 stack, and when the corresponding close brace is found, you can call
1905 the function with the proper arguments. Although the filling isn't
1906 necessary for HTML, it should do no harm. */
1916 if (input_text_offset >= input_text_length)
1919 character = curchar ();
1921 /* If only_macro_expansion, only handle macros and leave
1922 everything else intact. */
1923 if (!only_macro_expansion && !in_fixed_width_font
1924 && (character == '\'' || character == '`')
1925 && input_text[input_text_offset + 1] == character)
1927 input_text_offset++;
1928 character = '"'; /* html fixxme */
1931 /* Convert --- to --. */
1932 if (!only_macro_expansion && character == '-')
1935 if (dash_count == 2 && !in_fixed_width_font)
1937 input_text_offset++;
1941 else if (dash_count > 0)
1944 /* If this is a whitespace character, then check to see if the line
1945 is blank. If so, advance to the carriage return. */
1946 if (!only_macro_expansion && whitespace (character))
1948 int i = input_text_offset + 1;
1950 while (i < input_text_length && whitespace (input_text[i]))
1953 if (i == input_text_length || input_text[i] == '\n')
1955 if (i == input_text_length)
1958 input_text_offset = i;
1959 character = curchar ();
1963 if (character == '\n')
1968 case '*': /* perhaps we are at a menu */
1969 /* We used to check for this in the \n case but an @c in a
1970 menu swallows its newline, so check here instead. */
1971 if (!only_macro_expansion && in_menu
1972 && input_text_offset + 1 < input_text_length
1973 && input_text[input_text_offset-1] == '\n')
1974 handle_menu_entry ();
1976 { /* Duplicate code from below, but not worth twisting the
1977 fallthroughs to get down there. */
1978 add_char (character);
1979 input_text_offset++;
1983 /* Escapes for HTML unless we're outputting raw HTML. Do
1984 this always, even if SGML rules don't require it since
1985 that's easier and safer for non-conforming browsers. */
1987 if (html && escape_html)
1990 add_char (character);
1991 input_text_offset++;
1995 if (html && escape_html)
1998 xml_insert_entity ("lt");
2000 add_char (character);
2001 input_text_offset++;
2005 if (html && escape_html)
2008 xml_insert_entity ("gt");
2010 add_char (character);
2011 input_text_offset++;
2014 case COMMAND_PREFIX: /* @ */
2015 if (read_command () || !only_macro_expansion)
2018 /* FALLTHROUGH (usually) */
2020 /* Special case. We're not supposed to see this character by itself.
2021 If we do, it means there is a syntax error in the input text.
2022 Report the error here, but remember this brace on the stack so
2023 we can ignore its partner. */
2024 if (!only_macro_expansion)
2026 if (!STREQ (command, "math"))
2028 line_error (_("Misplaced %c"), '{');
2029 remember_brace (misplaced_brace);
2032 { /* We don't mind `extra' braces inside @math. */
2033 extern void cm_no_op ();
2034 remember_brace (cm_no_op);
2036 /* remember_brace advances input_text_offset. */
2040 /* FALLTHROUGH (usually) */
2042 if (!only_macro_expansion)
2044 pop_and_call_brace ();
2045 input_text_offset++;
2049 /* FALLTHROUGH (usually) */
2051 add_char (character);
2052 input_text_offset++;
2055 if (macro_expansion_output_stream && !only_macro_expansion)
2056 maybe_write_itext (input_text, input_text_offset);
2066 remember_brace (proc)
2067 COMMAND_FUNCTION *proc;
2069 if (curchar () != '{')
2070 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command);
2072 input_text_offset++;
2073 remember_brace_1 (proc, output_paragraph_offset);
2076 /* Remember the current output position here. Save PROC
2077 along with it so you can call it later. */
2079 remember_brace_1 (proc, position)
2080 COMMAND_FUNCTION *proc;
2083 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
2084 new->next = brace_stack;
2086 new->command = command ? xstrdup (command) : "";
2087 new->pos = position;
2088 new->line = line_number;
2089 new->in_fixed_width_font = in_fixed_width_font;
2093 /* Pop the top of the brace stack, and call the associated function
2094 with the args END and POS. */
2096 pop_and_call_brace ()
2098 if (brace_stack == NULL)
2100 line_error (_("Unmatched }"));
2105 BRACE_ELEMENT *temp;
2107 int pos = brace_stack->pos;
2108 COMMAND_FUNCTION *proc = brace_stack->proc;
2109 in_fixed_width_font = brace_stack->in_fixed_width_font;
2111 /* Reset current command, so the proc can know who it is. This is
2112 used in cm_accent. */
2113 command = brace_stack->command;
2115 temp = brace_stack->next;
2119 (*proc) (END, pos, output_paragraph_offset);
2123 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2125 adjust_braces_following (here, amount)
2128 BRACE_ELEMENT *stack = brace_stack;
2132 if (stack->pos >= here)
2133 stack->pos += amount;
2134 stack = stack->next;
2138 /* Return the string which invokes PROC; a pointer to a function.
2139 Always returns the first function in the command table if more than
2140 one matches PROC. */
2142 find_proc_name (proc)
2143 COMMAND_FUNCTION *proc;
2147 for (i = 0; command_table[i].name; i++)
2148 if (proc == command_table[i].proc)
2149 return command_table[i].name;
2150 return _("NO_NAME!");
2153 /* You call discard_braces () when you shouldn't have any braces on the stack.
2154 I used to think that this happens for commands that don't take arguments
2155 in braces, but that was wrong because of things like @code{foo @@}. So now
2156 I only detect it at the beginning of nodes. */
2165 if (brace_stack->proc != misplaced_brace)
2169 proc_name = find_proc_name (brace_stack->proc);
2170 file_line_error (input_filename, brace_stack->line,
2171 _("%c%s missing close brace"), COMMAND_PREFIX,
2173 pop_and_call_brace ();
2177 BRACE_ELEMENT *temp;
2178 temp = brace_stack->next;
2186 get_char_len (character)
2189 /* Return the printed length of the character. */
2195 len = (output_column + 8) & 0xf7;
2196 if (len > fill_column)
2197 len = fill_column - output_column;
2199 len = len - output_column;
2203 len = fill_column - output_column;
2207 /* ASCII control characters appear as two characters in the output
2208 (e.g., ^A). But characters with the high bit set are just one
2209 on suitable terminals, so don't count them as two for line
2210 breaking purposes. */
2211 if (0 <= character && character < ' ')
2220 #if defined (VA_FPRINTF) && __STDC__
2221 add_word_args (char *format, ...)
2223 add_word_args (format, va_alist)
2228 char buffer[2000]; /* xx no fixed limits */
2233 VA_START (ap, format);
2235 VA_SPRINTF (buffer, format, ap);
2237 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2238 #endif /* not VA_SPRINTF */
2243 /* Add STRING to output_paragraph. */
2249 add_char (*string++);
2252 /* Like add_word, but inhibits conversion of whitespace into .
2253 Use this to output HTML directives with embedded blanks, to make
2256 add_html_elt (string)
2264 /* Add the character to the current paragraph. If filling_enabled is
2265 nonzero, then do filling as well. */
2267 add_char (character)
2272 xml_add_char (character);
2276 /* If we are avoiding outputting headers, and we are currently
2277 in a menu, then simply return. But if we're only expanding macros,
2278 then we're being called from glean_node_from_menu to try to
2279 remember a menu reference, and we need that so we can do defaulting. */
2280 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2283 /* If we are adding a character now, then we don't have to
2284 ignore close_paragraph () calls any more. */
2285 if (must_start_paragraph && character != '\n')
2287 must_start_paragraph = 0;
2288 line_already_broken = 0; /* The line is no longer broken. */
2289 if (current_indent > output_column)
2291 indent (current_indent - output_column);
2292 output_column = current_indent;
2296 if (non_splitting_words
2297 && !(html && in_html_elt)
2298 && strchr (" \t\n", character))
2300 if (html || docbook)
2301 { /* Seems cleaner to use than an 8-bit char. */
2306 character = META (' '); /* unmeta-d in flush_output */
2309 insertion_paragraph_closed = 0;
2314 if (!filling_enabled && ! (html && (in_menu || in_detailmenu)))
2318 if (force_flush_right)
2321 /* Hack to force single blank lines out in this mode. */
2327 if (!no_indent && paragraph_is_open)
2328 indent (output_column = current_indent);
2331 else if (end_of_sentence_p ())
2332 /* CHARACTER is newline, and filling is enabled. */
2336 last_inserted_character = character;
2339 if (last_char_was_newline)
2342 last_char_was_newline++;
2348 last_char_was_newline = 1;
2357 default: /* not at newline */
2359 int len = get_char_len (character);
2360 int suppress_insert = 0;
2362 if ((character == ' ') && (last_char_was_newline))
2364 if (!paragraph_is_open)
2371 /* This is sad, but it seems desirable to not force any
2372 particular order on the front matter commands. This way,
2373 the document can do @settitle, @documentlanguage, etc, in
2374 any order and with any omissions, and we'll still output
2375 the html <head> `just in time'. */
2376 if (!executing_string && html && !html_output_head_p)
2377 html_output_head ();
2379 if (!paragraph_is_open)
2382 /* If the paragraph is supposed to be indented a certain
2383 way, then discard all of the pending whitespace.
2384 Otherwise, we let the whitespace stay. */
2385 if (!paragraph_start_indent)
2386 indent (pending_indent);
2389 /* This horrible kludge of checking for a < prevents <p>
2390 from being inserted when we already have html markup
2391 starting a paragraph, as with <ul> and <h1> and the like. */
2392 if (html && escape_html && character != '<'
2393 && (!in_fixed_width_font || in_menu || in_detailmenu))
2395 insert_string ("<p>");
2397 adjust_braces_following (0, 3); /* adjust for <p> */
2401 output_column += len;
2402 if (output_column > fill_column)
2404 if (filling_enabled && !html)
2406 int temp = output_paragraph_offset;
2407 while (--temp > 0 && output_paragraph[temp] != '\n')
2409 /* If we have found a space, we have the place to break
2411 if (output_paragraph[temp] == ' ')
2413 /* Remove trailing whitespace from output. */
2414 while (temp && whitespace (output_paragraph[temp - 1]))
2417 /* If we went back all the way to the newline of the
2418 preceding line, it probably means that the word we
2419 are adding is itself wider than the space that the
2420 indentation and the fill_column let us use. In
2421 that case, do NOT insert another newline, since it
2422 won't help. Just indent to current_indent and
2423 leave it alone, since that's the most we can do. */
2424 if (temp && output_paragraph[temp - 1] != '\n')
2425 output_paragraph[temp++] = '\n';
2427 /* We have correctly broken the line where we want
2428 to. What we don't want is spaces following where
2429 we have decided to break the line. We get rid of
2436 if (t1 == output_paragraph_offset)
2438 if (whitespace (character))
2439 suppress_insert = 1;
2442 if (!whitespace (output_paragraph[t1]))
2448 adjust_braces_following (temp, (- (t1 - temp)));
2449 strncpy ((char *) &output_paragraph[temp],
2450 (char *) &output_paragraph[t1],
2451 (output_paragraph_offset - t1));
2452 output_paragraph_offset -= (t1 - temp);
2456 /* Filled, but now indent if that is right. */
2457 if (indented_fill && current_indent > 0)
2459 int buffer_len = ((output_paragraph_offset - temp)
2461 char *temp_buffer = xmalloc (buffer_len);
2462 int indentation = 0;
2464 /* We have to shift any markers that are in
2465 front of the wrap point. */
2466 adjust_braces_following (temp, current_indent);
2468 while (current_indent > 0 &&
2469 indentation != current_indent)
2470 temp_buffer[indentation++] = ' ';
2472 memcpy ((char *) &temp_buffer[current_indent],
2473 (char *) &output_paragraph[temp],
2474 buffer_len - current_indent);
2476 if (output_paragraph_offset + buffer_len
2477 >= paragraph_buffer_len)
2479 unsigned char *tt = xrealloc
2481 (paragraph_buffer_len += buffer_len));
2482 output_paragraph = tt;
2484 memcpy ((char *) &output_paragraph[temp],
2485 temp_buffer, buffer_len);
2486 output_paragraph_offset += current_indent;
2490 while (temp < output_paragraph_offset)
2492 get_char_len (output_paragraph[temp++]);
2493 output_column += len;
2500 if (!suppress_insert)
2503 last_inserted_character = character;
2505 last_char_was_newline = 0;
2506 line_already_broken = 0;
2511 /* Add a character and store its position in meta_char_pos. */
2513 add_meta_char (character)
2516 meta_char_pos = output_paragraph_offset;
2517 add_char (character);
2520 /* Insert CHARACTER into `output_paragraph'. */
2525 output_paragraph[output_paragraph_offset++] = character;
2526 if (output_paragraph_offset == paragraph_buffer_len)
2529 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2533 /* Insert the null-terminated string STRING into `output_paragraph'. */
2535 insert_string (string)
2543 /* Sentences might have these characters after the period (or whatever). */
2544 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2547 /* Return true if at an end-of-sentence character, possibly followed by
2548 post-sentence punctuation to ignore. */
2550 end_of_sentence_p ()
2552 int loc = output_paragraph_offset - 1;
2554 /* If nothing has been output, don't check output_paragraph[-1]. */
2558 /* A post-sentence character that is at meta_char_pos is not really
2559 a post-sentence character; it was produced by a markup such as
2560 @samp. We don't want the period inside @samp to be treated as a
2563 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
2565 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
2569 /* Remove upto COUNT characters of whitespace from the
2570 the current output line. If COUNT is less than zero,
2571 then remove until none left. */
2573 kill_self_indent (count)
2576 /* Handle infinite case first. */
2580 while (output_paragraph_offset)
2582 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2583 output_paragraph_offset--;
2590 while (output_paragraph_offset && count--)
2591 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2592 output_paragraph_offset--;
2598 /* Nonzero means do not honor calls to flush_output (). */
2599 static int flushing_ignored = 0;
2601 /* Prevent calls to flush_output () from having any effect. */
2603 inhibit_output_flushing ()
2608 /* Allow calls to flush_output () to write the paragraph data. */
2610 uninhibit_output_flushing ()
2620 if (!output_paragraph_offset || flushing_ignored)
2623 for (i = 0; i < output_paragraph_offset; i++)
2625 /* If we turned on the 8th bit for a space inside @w, turn it
2626 back off for output. This might be problematic, since the
2627 0x80 character may be used in 8-bit character sets. Sigh.
2628 In any case, don't do this for HTML, since the nbsp character
2629 is valid input and must be passed along to the browser. */
2630 if (!html && (output_paragraph[i] & meta_character_bit))
2632 int temp = UNMETA (output_paragraph[i]);
2634 output_paragraph[i] &= 0x7f;
2638 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2640 output_position += output_paragraph_offset;
2641 output_paragraph_offset = 0;
2645 /* How to close a paragraph controlling the number of lines between
2646 this one and the last one. */
2648 /* Paragraph spacing is controlled by this variable. It is the number of
2649 blank lines that you wish to appear between paragraphs. A value of
2650 1 creates a single blank line between paragraphs. */
2651 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2654 close_paragraph_with_lines (lines)
2657 int old_spacing = paragraph_spacing;
2658 paragraph_spacing = lines;
2660 paragraph_spacing = old_spacing;
2663 /* Close the current paragraph, leaving no blank lines between them. */
2665 close_single_paragraph ()
2667 close_paragraph_with_lines (0);
2670 /* Close a paragraph after an insertion has ended. */
2672 close_insertion_paragraph ()
2674 if (!insertion_paragraph_closed)
2676 /* Close the current paragraph, breaking the line. */
2677 close_single_paragraph ();
2679 /* Start a new paragraph, with the correct indentation for the now
2680 current insertion level (one above the one that we are ending). */
2683 /* Tell `close_paragraph' that the previous line has already been
2684 broken, so it should insert one less newline. */
2685 line_already_broken = 1;
2687 /* Tell functions such as `add_char' we've already found a newline. */
2688 ignore_blank_line ();
2692 /* If the insertion paragraph is closed already, then we are seeing
2693 two `@end' commands in a row. Note that the first one we saw was
2694 handled in the first part of this if-then-else clause, and at that
2695 time `start_paragraph' was called, partially to handle the proper
2696 indentation of the current line. However, the indentation level
2697 may have just changed again, so we may have to outdent the current
2698 line to the new indentation level. */
2699 if (current_indent < output_column)
2700 kill_self_indent (output_column - current_indent);
2703 insertion_paragraph_closed = 1;
2706 /* Close the currently open paragraph. */
2712 /* The insertion paragraph is no longer closed. */
2713 insertion_paragraph_closed = 0;
2715 if (paragraph_is_open && !must_start_paragraph)
2719 tindex = output_paragraph_offset;
2721 /* Back up to last non-newline/space character, forcing all such
2722 subsequent characters to be newlines. This isn't strictly
2723 necessary, but a couple of functions use the presence of a newline
2724 to make decisions. */
2725 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
2727 c = output_paragraph[tindex];
2729 if (c == ' '|| c == '\n')
2730 output_paragraph[tindex] = '\n';
2735 /* All trailing whitespace is ignored. */
2736 output_paragraph_offset = ++tindex;
2738 /* Break the line if that is appropriate. */
2739 if (paragraph_spacing >= 0)
2742 /* Add as many blank lines as is specified in `paragraph_spacing'. */
2743 if (!force_flush_right)
2745 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
2748 /* Don't need anything extra for HTML in usual case of no
2749 extra paragraph spacing. */
2751 insert_string ("<br>");
2755 /* If we are doing flush right indentation, then do it now
2756 on the paragraph (really a single line). */
2757 if (force_flush_right)
2758 do_flush_right_indentation ();
2761 paragraph_is_open = 0;
2766 ignore_blank_line ();
2769 /* Make the last line just read look as if it were only a newline. */
2771 ignore_blank_line ()
2773 last_inserted_character = '\n';
2774 last_char_was_newline = 1;
2777 /* Align the end of the text in output_paragraph with fill_column. */
2779 do_flush_right_indentation ()
2784 kill_self_indent (-1);
2786 if (output_paragraph[0] != '\n')
2788 output_paragraph[output_paragraph_offset] = 0;
2790 if (output_paragraph_offset < fill_column)
2794 if (fill_column >= paragraph_buffer_len)
2796 xrealloc (output_paragraph,
2797 (paragraph_buffer_len += fill_column));
2799 temp_len = strlen ((char *)output_paragraph);
2800 temp = xmalloc (temp_len + 1);
2801 memcpy (temp, (char *)output_paragraph, temp_len);
2803 for (i = 0; i < fill_column - output_paragraph_offset; i++)
2804 output_paragraph[i] = ' ';
2806 memcpy ((char *)output_paragraph + i, temp, temp_len);
2808 output_paragraph_offset = fill_column;
2809 adjust_braces_following (0, i);
2814 /* Begin a new paragraph. */
2818 /* First close existing one. */
2819 if (paragraph_is_open)
2822 /* In either case, the insertion paragraph is no longer closed. */
2823 insertion_paragraph_closed = 0;
2825 /* However, the paragraph is open! */
2826 paragraph_is_open = 1;
2828 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
2829 had to be called before we would allow any other paragraph operations
2830 to have an effect. */
2831 if (!must_start_paragraph)
2833 int amount_to_indent = 0;
2835 /* If doing indentation, then insert the appropriate amount. */
2838 if (inhibit_paragraph_indentation)
2840 amount_to_indent = current_indent;
2841 if (inhibit_paragraph_indentation < 0)
2842 inhibit_paragraph_indentation++;
2844 else if (paragraph_start_indent < 0)
2845 amount_to_indent = current_indent;
2847 amount_to_indent = current_indent + paragraph_start_indent;
2849 if (amount_to_indent >= output_column)
2851 amount_to_indent -= output_column;
2852 indent (amount_to_indent);
2853 output_column += amount_to_indent;
2858 must_start_paragraph = 0;
2861 /* Insert the indentation specified by AMOUNT. */
2869 /* For every START_POS saved within the brace stack which will be affected
2870 by this indentation, bump that start pos forward. */
2871 adjust_braces_following (output_paragraph_offset, amount);
2873 while (--amount >= 0)
2877 /* Search forward for STRING in input_text.
2878 FROM says where where to start. */
2880 search_forward (string, from)
2884 int len = strlen (string);
2886 while (from < input_text_length)
2888 if (strncmp (input_text + from, string, len) == 0)
2895 /* Cross references. */
2897 /* Return next comma-delimited argument, but do not cross a close-brace
2898 boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
2899 the entire brace-delimited argument list with its expansion before
2900 looking for the next comma. */
2902 get_xref_token (expand)
2909 int old_offset = input_text_offset;
2910 int old_lineno = line_number;
2912 get_until_in_braces ("}", &string);
2913 if (curchar () == '}') /* as opposed to end of text */
2914 input_text_offset++;
2915 if (input_text_offset > old_offset)
2917 int limit = input_text_offset;
2919 input_text_offset = old_offset;
2920 line_number = old_lineno;
2921 only_macro_expansion++;
2922 replace_with_expansion (input_text_offset, &limit);
2923 only_macro_expansion--;
2928 get_until_in_braces (",", &string);
2929 if (curchar () == ',')
2930 input_text_offset++;
2931 fix_whitespace (string);
2935 /* NOTE: If you wonder why the HTML output is produced with such a
2936 peculiar mix of calls to add_word and execute_string, here's the
2937 reason. get_xref_token (1) expands all macros in a reference, but
2938 any other commands, like @value, @@, etc., are left intact. To
2939 expand them, we need to run the arguments through execute_string.
2940 However, characters like <, &, > and others cannot be let into
2941 execute_string, because they will be escaped. See the mess? */
2943 /* Make a cross reference. */
2949 char *arg1 = get_xref_token (1); /* expands all macros in xref */
2950 char *arg2 = get_xref_token (0);
2951 char *arg3 = get_xref_token (0);
2952 char *arg4 = get_xref_token (0);
2953 char *arg5 = get_xref_token (0);
2956 /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
2957 first argument must never be blank." --rms.
2958 We hereby comply by disallowing such constructs. */
2960 line_error (_("First argument to cross-reference may not be empty"));
2964 if (!*arg4 && !*arg5)
2966 char *arg1_id = xml_id (arg1);
2969 xml_insert_element_with_attribute (XREFNODENAME, START,
2970 "linkend=\"%s\"", arg1_id);
2973 execute_string (arg2);
2974 xml_insert_element (XREFNODENAME, END);
2978 xml_insert_element_with_attribute (XREF, START,
2979 "linkend=\"%s\"", arg1_id);
2981 xml_pop_current_element ();
2987 xml_insert_element (XREF, START);
2988 xml_insert_element (XREFNODENAME, START);
2989 execute_string (arg1);
2990 xml_insert_element (XREFNODENAME, END);
2993 xml_insert_element (XREFINFONAME, START);
2994 execute_string (arg2);
2995 xml_insert_element (XREFINFONAME, END);
2999 xml_insert_element (XREFPRINTEDDESC, START);
3000 execute_string (arg3);
3001 xml_insert_element (XREFPRINTEDDESC, END);
3005 xml_insert_element (XREFINFOFILE, START);
3006 execute_string (arg4);
3007 xml_insert_element (XREFINFOFILE, END);
3011 xml_insert_element (XREFPRINTEDNAME, START);
3012 execute_string (arg5);
3013 xml_insert_element (XREFPRINTEDNAME, END);
3015 xml_insert_element (XREF, END);
3020 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
3023 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
3030 arg2 - reference name
3031 arg3 - title or topic (and reference name if arg2 is NULL)
3032 arg4 - info file name
3033 arg5 - printed manual title */
3048 /* html fixxme: revisit this; external node name not
3049 much use to us with numbered nodes. */
3050 add_html_elt ("<a href=");
3051 /* Note that if we are splitting, and the referenced
3052 tag is an anchor rather than a node, we will
3053 produce a reference to a file whose name is
3054 derived from the anchor name. However, only
3055 nodes create files, so we are referencing a
3056 non-existent file. cm_anchor, which see, deals
3057 with that problem. */
3059 execute_string ("\"../%s/", arg4);
3061 execute_string ("\"%s.html", arg4);
3062 /* Do not collapse -- to -, etc., in references. */
3063 in_fixed_width_font++;
3064 tem = expansion (arg1, 0); /* expand @-commands in node */
3065 in_fixed_width_font--;
3066 add_anchor_name (tem, 1);
3069 execute_string ("%s", ref_name);
3074 execute_string ("%s:", ref_name);
3075 in_fixed_width_font++;
3076 execute_string (" (%s)%s%s", arg4, arg1, px_ref_flag ? "." : "");
3077 in_fixed_width_font--;
3080 /* Free all of the arguments found. */
3081 if (arg1) free (arg1);
3082 if (arg2) free (arg2);
3083 if (arg3) free (arg3);
3084 if (arg4) free (arg4);
3085 if (arg5) free (arg5);
3089 remember_node_reference (arg1, line_number, followed_reference);
3095 add_html_elt ("<a href=\"");
3096 in_fixed_width_font++;
3097 tem = expansion (arg1, 0);
3098 in_fixed_width_font--;
3099 add_anchor_name (tem, 1);
3102 execute_string ("%s", *arg2 ? arg2 : arg3);
3107 execute_string ("%s:", *arg2 ? arg2 : arg3);
3108 in_fixed_width_font++;
3109 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
3110 in_fixed_width_font--;
3117 add_html_elt ("<a href=\"");
3118 in_fixed_width_font++;
3119 tem = expansion (arg1, 0);
3120 in_fixed_width_font--;
3121 add_anchor_name (tem, 1);
3124 execute_string ("%s", *arg2 ? arg2 : arg1);
3131 execute_string ("%s:", arg2);
3132 in_fixed_width_font++;
3133 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
3134 in_fixed_width_font--;
3138 in_fixed_width_font++;
3139 execute_string ("%s::", arg1);
3140 in_fixed_width_font--;
3145 /* Free all of the arguments found. */
3146 if (arg1) free (arg1);
3147 if (arg2) free (arg2);
3148 if (arg3) free (arg3);
3149 if (arg4) free (arg4);
3150 if (arg5) free (arg5);
3153 { /* Check to make sure that the next non-whitespace character is
3154 valid to follow an xref (so info readers can find the node
3155 names). `input_text_offset' is pointing at the "}" which ended
3156 the xref or ref command. */
3159 for (temp = input_text_offset + 1; temp < input_text_length; )
3161 if (cr_or_whitespace (input_text[temp]))
3165 if (input_text[temp] != '.' && input_text[temp] != ',')
3166 warning (_("`.' or `,' must follow cross reference, not %c"),
3184 /* Note that cm_xref isn't called with arg == END, which disables
3185 the code near the end of cm_xref that checks for `.' or `,'
3186 after the cross-reference. This is because @pxref{} generates
3187 the required character itself, when needed. */
3208 char *node = get_xref_token (1); /* expands all macros in inforef */
3209 char *pname = get_xref_token (0);
3210 char *file = get_xref_token (0);
3212 /* (see comments at cm_xref). */
3214 line_error (_("First argument to @inforef may not be empty"));
3216 if (xml && !docbook)
3218 xml_insert_element (INFOREF, START);
3219 xml_insert_element (INFOREFNODENAME, START);
3220 execute_string (node);
3221 xml_insert_element (INFOREFNODENAME, END);
3224 xml_insert_element (INFOREFREFNAME, START);
3225 execute_string (pname);
3226 xml_insert_element (INFOREFREFNAME, END);
3228 xml_insert_element (INFOREFINFONAME, START);
3229 execute_string (file);
3230 xml_insert_element (INFOREFINFONAME, END);
3232 xml_insert_element (INFOREF, END);
3238 add_word (_("see "));
3239 /* html fixxme: revisit this */
3240 add_html_elt ("<a href=");
3242 execute_string ("\"../%s/", file);
3244 execute_string ("\"%s.html", file);
3245 tem = expansion (node, 0);
3246 add_anchor_name (tem, 1);
3248 execute_string ("%s", *pname ? pname : tem);
3255 execute_string ("*note %s: (%s)%s", pname, file, node);
3257 execute_string ("*note (%s)%s::", file, node);
3266 /* A URL reference. */
3273 extern int printing_index;
3274 char *url = get_xref_token (1); /* expands all macros in uref */
3275 char *desc = get_xref_token (0);
3276 char *replacement = get_xref_token (0);
3280 xml_insert_element (UREF, START);
3281 xml_insert_element (UREFURL, START);
3282 execute_string (url);
3283 xml_insert_element (UREFURL, END);
3286 xml_insert_element (UREFDESC, START);
3287 execute_string (desc);
3288 xml_insert_element (UREFDESC, END);
3292 xml_insert_element (UREFREPLACEMENT, START);
3293 execute_string (replacement);
3294 xml_insert_element (UREFREPLACEMENT, END);
3296 xml_insert_element (UREF, END);
3299 { /* never need to show the url */
3300 add_html_elt ("<a href=");
3301 /* don't collapse `--' etc. in the url */
3302 in_fixed_width_font++;
3303 execute_string ("\"%s\"", url);
3304 in_fixed_width_font--;
3306 execute_string ("%s", *replacement ? replacement
3307 : (*desc ? desc : url));
3310 else if (*replacement) /* do not show the url */
3311 execute_string ("%s", replacement);
3312 else if (*desc) /* show both text and url */
3314 execute_string ("%s ", desc);
3315 in_fixed_width_font++;
3316 execute_string ("(%s)", url);
3317 in_fixed_width_font--;
3319 else /* no text at all, so have the url to show */
3321 in_fixed_width_font++;
3322 execute_string ("%s%s%s",
3323 printing_index ? "" : "`",
3325 printing_index ? "" : "'");
3326 in_fixed_width_font--;
3337 /* An email reference. */
3344 char *addr = get_xref_token (1); /* expands all macros in email */
3345 char *name = get_xref_token (0);
3349 xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
3351 execute_string (name);
3352 xml_insert_element (EMAIL, END);
3356 xml_insert_element (EMAIL, START);
3357 xml_insert_element (EMAILADDRESS, START);
3358 execute_string (addr);
3359 xml_insert_element (EMAILADDRESS, END);
3362 xml_insert_element (EMAILNAME, START);
3363 execute_string (name);
3364 xml_insert_element (EMAILNAME, END);
3366 xml_insert_element (EMAIL, END);
3370 add_html_elt ("<a href=");
3371 /* don't collapse `--' etc. in the address */
3372 in_fixed_width_font++;
3373 execute_string ("\"mailto:%s\"", addr);
3374 in_fixed_width_font--;
3376 execute_string ("%s", *name ? name : addr);
3381 execute_string ("%s%s", name, *name ? " " : "");
3382 in_fixed_width_font++;
3383 execute_string ("<%s>", addr);
3384 in_fixed_width_font--;
3394 /* An external image is a reference, kind of. The parsing is (not
3395 coincidentally) similar, anyway. */
3400 char *name_arg, *rest, *alt_arg, *ext_arg;
3405 name_arg = get_xref_token (1); /* expands all macros in image */
3406 /* We don't (yet) care about the next two args, but read them so they
3407 don't end up in the text. */
3408 rest = get_xref_token (0);
3411 rest = get_xref_token (0);
3414 alt_arg = get_xref_token (1); /* expands all macros in alt text */
3415 ext_arg = get_xref_token (0);
3419 char *fullname = xmalloc (strlen (name_arg)
3420 + (ext_arg && *ext_arg ? strlen (ext_arg) + 1 : 4) + 1);
3424 if (ext_arg && *ext_arg)
3426 sprintf (fullname, "%s.%s", name_arg, ext_arg);
3427 if (access (fullname, R_OK) != 0)
3429 line_error(_("@image file `%s' (for HTML) not readable: %s"),
3430 fullname, strerror (errno));
3436 sprintf (fullname, "%s.png", name_arg);
3437 if (access (fullname, R_OK) != 0)
3439 sprintf (fullname, "%s.jpg", name_arg);
3440 if (access (fullname, R_OK) != 0)
3442 line_error (_("No `%s.png' or `.jpg', and no extension supplied"),
3449 add_html_elt ("<img src=");
3450 add_word_args ("\"%s\"", fullname);
3451 add_html_elt (" alt=");
3452 add_word_args ("\"%s\">", (*alt_arg) ? alt_arg : fullname);
3454 else if (xml && docbook)
3455 xml_insert_docbook_image (name_arg);
3458 xml_insert_element (IMAGE, START);
3459 add_word (name_arg);
3460 xml_insert_element (IMAGE, END);
3463 { /* Try to open foo.txt. */
3465 strcpy (fullname, name_arg);
3466 strcat (fullname, ".txt");
3467 image_file = fopen (fullname, "r");
3471 int save_inhibit_indentation = inhibit_paragraph_indentation;
3472 int save_filling_enabled = filling_enabled;
3474 inhibit_paragraph_indentation = 1;
3475 filling_enabled = 0;
3476 last_char_was_newline = 0;
3478 /* Maybe we need to remove the final newline if the image
3479 file is only one line to allow in-line images. On the
3480 other hand, they could just make the file without a
3482 while ((ch = getc (image_file)) != EOF)
3485 inhibit_paragraph_indentation = save_inhibit_indentation;
3486 filling_enabled = save_filling_enabled;
3488 if (fclose (image_file) != 0)
3492 line_error (_("@image file `%s' (for text) unreadable: %s"),
3493 fullname, strerror (errno));
3499 line_error (_("@image missing filename argument"));
3511 /* A structure which contains `defined' variables. */
3512 typedef struct defines {
3513 struct defines *next;
3518 /* The linked list of `set' defines. */
3519 DEFINE *defines = NULL;
3521 /* Add NAME to the list of `set' defines. */
3529 for (temp = defines; temp; temp = temp->next)
3530 if (strcmp (name, temp->name) == 0)
3533 temp->value = xstrdup (value);
3537 temp = xmalloc (sizeof (DEFINE));
3538 temp->next = defines;
3539 temp->name = xstrdup (name);
3540 temp->value = xstrdup (value);
3544 /* Remove NAME from the list of `set' defines. */
3549 DEFINE *temp, *last;
3556 if (strcmp (temp->name, name) == 0)
3559 last->next = temp->next;
3561 defines = temp->next;
3573 /* Return the value of NAME. The return value is NULL if NAME is unset. */
3580 for (temp = defines; temp; temp = temp->next)
3581 if (strcmp (temp->name, name) == 0)
3587 /* Create a variable whose name appears as the first word on this line. */
3591 handle_variable (SET);
3594 /* Remove a variable whose name appears as the first word on this line. */
3598 handle_variable (CLEAR);
3604 handle_variable (IFSET);
3610 handle_variable (IFCLEAR);
3613 /* This command takes braces, but we parse the contents specially, so we
3614 don't use the standard brace popping code.
3616 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3617 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3618 it produces no output. */
3624 arglist = get_brace_args (0);
3628 if (array_len (arglist) > 1)
3630 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
3632 execute_string ("%s\n", arglist[2]);
3635 free_array (arglist);
3640 cm_value (arg, start_pos, end_pos)
3641 int arg, start_pos, end_pos;
3643 static int value_level = 0, saved_meta_pos = -1;
3645 /* All the text after @value{ upto the matching } will eventually
3646 disappear from output_paragraph, when this function is called
3647 with ARG == END. If the text produced until then sets
3648 meta_char_pos, we will need to restore it to the value it had
3649 before @value was seen. So we need to save the previous value
3650 of meta_char_pos here. */
3653 /* If we are already inside some outer @value, don't overwrite
3654 the value saved in saved_meta_pos. */
3656 saved_meta_pos = meta_char_pos;
3658 /* While the argument of @value is processed, we need to inhibit
3659 textual transformations like "--" into "-", since @set didn't
3660 do that when it grabbed the name of the variable. */
3661 in_fixed_width_font++;
3665 char *name = (char *) &output_paragraph[start_pos];
3667 output_paragraph[end_pos] = 0;
3668 name = xstrdup (name);
3669 value = set_p (name);
3670 output_column -= end_pos - start_pos;
3671 output_paragraph_offset = start_pos;
3673 /* Restore the previous value of meta_char_pos if the stuff
3674 inside this @value{} moved it. */
3675 if (saved_meta_pos == -1) /* can't happen inside @value{} */
3677 if (value_level == 1
3678 && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3680 meta_char_pos = saved_meta_pos;
3681 saved_meta_pos = -1;
3684 /* No need to decrement in_fixed_width_font, since before
3685 we are called with arg == END, the reader loop already
3686 popped the brace stack, which restored in_fixed_width_font,
3687 among other things. */
3690 execute_string ("%s", value);
3692 add_word_args (_("{No value for `%s'}"), name);
3698 /* Set, clear, or conditionalize based on ACTION. */
3700 handle_variable (action)
3705 get_rest_of_line (0, &name);
3706 /* If we hit the end of text in get_rest_of_line, backing up
3707 input pointer will cause the last character of the last line
3708 be pushed back onto the input, which is wrong. */
3709 if (input_text_offset < input_text_length)
3710 backup_input_pointer ();
3711 handle_variable_internal (action, name);
3716 handle_variable_internal (action, name)
3721 int delimiter, additional_text_present = 0;
3723 /* Only the first word of NAME is a valid tag. */
3726 while (*temp && (delimiter || !whitespace (*temp)))
3728 /* #if defined (SET_WITH_EQUAL) */
3729 if (*temp == '"' || *temp == '\'')
3731 if (*temp == delimiter)
3736 /* #endif SET_WITH_EQUAL */
3741 additional_text_present++;
3746 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3755 #if defined (SET_WITH_EQUAL)
3756 /* Allow a value to be saved along with a variable. The value is
3757 the text following an `=' sign in NAME, if any is present. */
3759 for (value = name; *value && *value != '='; value++);
3764 if (*value == '"' || *value == '\'')
3767 value[strlen (value) - 1] = 0;
3770 #else /* !SET_WITH_EQUAL */
3771 /* The VALUE of NAME is the remainder of the line sans
3773 if (additional_text_present)
3776 canon_white (value);
3780 #endif /* !SET_WITH_VALUE */
3792 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3793 read lines from the the file until we reach a matching
3794 "@end CONDITION". This means that we only take note of
3795 "@ifset/clear" and "@end" commands. */
3799 int orig_line_number = line_number;
3801 if (action == IFSET)
3802 strcpy (condition, "ifset");
3804 strcpy (condition, "ifclear");
3806 condition_len = strlen (condition);
3808 if ((action == IFSET && !set_p (name))
3809 || (action == IFCLEAR && set_p (name)))
3811 int level = 0, done = 0;
3813 while (!done && input_text_offset < input_text_length)
3815 char *freeable_line, *line;
3817 get_rest_of_line (0, &freeable_line);
3819 for (line = freeable_line; whitespace (*line); line++);
3821 if (*line == COMMAND_PREFIX &&
3822 (strncmp (line + 1, condition, condition_len) == 0))
3824 else if (strncmp (line, "@end", 4) == 0)
3826 char *cname = line + 4;
3829 while (*cname && whitespace (*cname))
3833 while (*temp && !whitespace (*temp))
3837 if (strcmp (cname, condition) == 0)
3847 free (freeable_line);
3851 file_line_error (input_filename, orig_line_number,
3852 _("Reached eof before matching @end %s"),
3855 /* We found the end of a false @ifset/ifclear. If we are
3856 in a menu, back up over the newline that ends the ifset,
3857 since that newline may also begin the next menu entry. */
3862 if (action == IFSET)
3863 begin_insertion (ifset);
3865 begin_insertion (ifclear);
3873 /* Execution of random text not in file. */
3876 char *string; /* The string buffer. */
3877 int size; /* The size of the buffer. */
3878 int in_use; /* Nonzero means string currently in use. */
3881 static EXECUTION_STRING **execution_strings = NULL;
3882 static int execution_strings_index = 0;
3883 static int execution_strings_slots = 0;
3886 get_execution_string (initial_size)
3890 EXECUTION_STRING *es = NULL;
3892 if (execution_strings)
3894 for (i = 0; i < execution_strings_index; i++)
3895 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
3897 es = execution_strings[i];
3904 if (execution_strings_index + 1 >= execution_strings_slots)
3906 execution_strings = xrealloc
3908 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
3909 for (; i < execution_strings_slots; i++)
3910 execution_strings[i] = NULL;
3913 execution_strings[execution_strings_index] =
3914 xmalloc (sizeof (EXECUTION_STRING));
3915 es = execution_strings[execution_strings_index];
3916 execution_strings_index++;
3923 if (initial_size > es->size)
3925 es->string = xrealloc (es->string, initial_size);
3926 es->size = initial_size;
3931 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
3932 entry in the execution_strings[] array and change the .STRING and
3933 .SIZE members of that entry as appropriate. */
3935 maybe_update_execution_strings (text, new_len)
3941 if (execution_strings)
3943 for (i = 0; i < execution_strings_index; i++)
3944 if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
3945 execution_strings[i]->string == *text)
3947 /* Don't ever shrink the string storage in execution_strings[]!
3948 execute_string assumes that it is always big enough to store
3949 every possible execution_string, and will break if that's
3950 not true. So we only enlarge the string storage if the
3951 current size isn't big enough. */
3952 if (execution_strings[i]->size < new_len)
3954 execution_strings[i]->string =
3955 *text = xrealloc (*text, new_len + 1);
3956 execution_strings[i]->size = new_len + 1;
3961 /* We should *never* end up here, since if we are inside
3962 execute_string, TEXT is always in execution_strings[]. */
3966 /* FIXME: this is an arbitrary limit. */
3967 #define EXECUTE_STRING_MAX 16*1024
3969 /* Execute the string produced by formatting the ARGs with FORMAT. This
3970 is like submitting a new file with @include. */
3972 #if defined (VA_FPRINTF) && __STDC__
3973 execute_string (char *format, ...)
3975 execute_string (format, va_alist)
3980 EXECUTION_STRING *es;
3986 es = get_execution_string (EXECUTE_STRING_MAX);
3987 temp_string = es->string;
3990 VA_START (ap, format);
3992 VA_SPRINTF (temp_string, format, ap);
3994 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
3995 #endif /* not VA_SPRINTF */
3999 input_text_offset = 0;
4000 input_text = temp_string;
4001 input_filename = xstrdup (input_filename);
4002 input_text_length = strlen (temp_string);
4006 free (input_filename);
4014 /* Return what would be output for STR (in newly-malloced memory), i.e.,
4015 expand Texinfo commands. If IMPLICIT_CODE is set, expand @code{STR}.
4016 This is generally used for short texts; filling, indentation, and
4017 html escapes are disabled. */
4020 expansion (str, implicit_code)
4026 /* Inhibit indentation and filling, so that extra newlines
4027 are not added to the expansion. (This is undesirable if
4028 we write the expanded text to macro_expansion_output_stream.) */
4029 int saved_filling_enabled = filling_enabled;
4030 int saved_indented_fill = indented_fill;
4031 int saved_no_indent = no_indent;
4032 int saved_escape_html = escape_html;
4034 filling_enabled = 0;
4039 result = full_expansion (str, implicit_code);
4041 filling_enabled = saved_filling_enabled;
4042 indented_fill = saved_indented_fill;
4043 no_indent = saved_no_indent;
4044 escape_html = saved_escape_html;
4050 /* Expand STR (or @code{STR} if IMPLICIT_CODE is nonzero). No change to
4051 any formatting parameters -- filling, indentation, html escapes,
4052 etc., are not reset. */
4055 full_expansion (str, implicit_code)
4062 /* Inhibit any real output. */
4063 int start = output_paragraph_offset;
4064 int saved_paragraph_is_open = paragraph_is_open;
4065 int saved_output_column = output_column;
4067 /* More output state to save. */
4068 int saved_meta_pos = meta_char_pos;
4069 int saved_last_char = last_inserted_character;
4070 int saved_last_nl = last_char_was_newline;
4072 /* If we are called in the middle of processing a command, we need
4073 to dup and save the global variable `command' (which holds the
4074 name of this command), since the recursive reader loop will free
4075 it from under our feet if it finds any macros in STR. */
4076 char *saved_command = command ? xstrdup (command) : NULL;
4078 inhibit_output_flushing ();
4079 paragraph_is_open = 1;
4080 if (strlen (str) > (implicit_code
4081 ? EXECUTE_STRING_MAX - 1 - sizeof("@code{}")
4082 : EXECUTE_STRING_MAX - 1))
4083 line_error (_("`%.40s...' is too long for expansion; not expanded"), str);
4085 execute_string (implicit_code ? "@code{%s}" : "%s", str);
4086 uninhibit_output_flushing ();
4088 /* Copy the expansion from the buffer. */
4089 length = output_paragraph_offset - start;
4090 result = xmalloc (1 + length);
4091 memcpy (result, (char *) (output_paragraph + start), length);
4094 /* Pretend it never happened. */
4095 free_and_clear (&command);
4096 command = saved_command;
4098 output_paragraph_offset = start;
4099 paragraph_is_open = saved_paragraph_is_open;
4100 output_column = saved_output_column;
4102 meta_char_pos = saved_meta_pos;
4103 last_inserted_character = saved_last_char;
4104 last_char_was_newline = saved_last_nl;
4110 /* Return text (info) expansion of STR no matter what the current output
4114 text_expansion (str)
4118 int save_html = html;
4123 ret = expansion (str, 0);
4131 /* Set the paragraph indentation variable to the value specified in STRING.
4133 `asis': Don't change existing indentation.
4134 `none': Remove existing indentation.
4135 NUM: Indent NUM spaces at the starts of paragraphs.
4136 If NUM is zero, we assume `none'.
4137 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
4139 set_paragraph_indent (string)
4142 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
4143 paragraph_start_indent = 0;
4144 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
4145 paragraph_start_indent = -1;
4148 if (sscanf (string, "%d", ¶graph_start_indent) != 1)
4152 if (paragraph_start_indent == 0)
4153 paragraph_start_indent = -1;