1 /* $FreeBSD: src/contrib/texinfo/makeinfo/makeinfo.c,v 1.9.2.2 2002/08/07 16:53:39 ru Exp $ */
2 /* makeinfo -- convert Texinfo source into other formats.
3 $Id: makeinfo.c,v 1.205 2002/03/28 16:33:48 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;
70 static char *save_command_output_filename = NULL;
72 /* Flags which control initial output string for xrefs. */
76 #define INITIAL_PARAGRAPH_SPACE 5000
77 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
79 /* The amount of indentation to add at the starts of paragraphs.
80 0 means don't change existing indentation at paragraph starts.
81 > 0 is amount to indent new paragraphs by.
82 < 0 means indent to column zero by removing indentation if necessary.
84 This is normally zero, but some people prefer paragraph starts to be
85 somewhat more indented than paragraph bodies. A pretty value for
87 int paragraph_start_indent = PARAGRAPH_START_INDENT;
89 /* Indentation that is pending insertion. We have this for hacking lines
90 which look blank, but contain whitespace. We want to treat those as
92 int pending_indent = 0;
94 /* The index in our internal command table of the currently
98 /* A search string which is used to find the first @setfilename. */
99 char setfilename_search[] =
101 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
103 /* Values for calling handle_variable_internal (). */
109 /* Flags controlling the operation of the program. */
111 /* Default is to remove output if there were errors. */
114 /* Default is to notify users of bad choices. */
115 int print_warnings = 1;
117 /* Number of errors that we tolerate on a given fileset. */
118 int max_error_level = 100;
120 /* The actual last inserted character. Note that this may be something
121 other than NEWLINE even if last_char_was_newline is 1. */
122 int last_inserted_character = 0;
124 /* Nonzero means that a newline character has already been
125 inserted, so close_paragraph () should insert one less. */
126 int line_already_broken = 0;
128 /* When nonzero we have finished an insertion (see end_insertion ()) and we
129 want to ignore false continued paragraph closings. */
130 int insertion_paragraph_closed = 0;
132 /* Nonzero means attempt to make all of the lines have fill_column width. */
133 int do_justification = 0;
135 /* Nonzero means don't replace whitespace with in HTML mode. */
138 typedef struct brace_element
140 struct brace_element *next;
141 COMMAND_FUNCTION *proc;
144 int in_fixed_width_font;
147 BRACE_ELEMENT *brace_stack = NULL;
149 extern void do_multitable (), end_multitable ();
151 void push_node_filename (), pop_node_filename ();
152 void remember_error ();
153 void convert_from_stream (), convert_from_file (), convert_from_loaded_file ();
154 void init_internals (), init_paragraph (), init_brace_stack ();
155 void init_insertion_stack (), init_indices ();
156 void init_tag_table (), write_tag_table (), write_tag_table_internal ();
157 void validate_file (), validate_other_references (), split_file ();
158 void free_node_references (), handle_variable ();
159 void handle_variable_internal ();
160 void normalize_node_name ();
161 void add_anchor_name ();
162 void free_node_node_references (), remember_node_node_reference ();
164 char **get_brace_args ();
167 static int end_of_sentence_p ();
168 static void isolate_nodename ();
170 void remember_brace (), remember_brace_1 ();
171 void pop_and_call_brace (), discard_braces ();
172 void add_word (), add_char (), insert (), flush_output ();
173 void insert_string ();
174 void close_paragraph ();
175 void ignore_blank_line ();
176 void do_flush_right_indentation (), discard_insertions ();
177 void start_paragraph (), indent ();
178 void inhibit_output_flushing (), uninhibit_output_flushing ();
179 int set_paragraph_indent ();
180 int self_delimiting (), search_forward ();
181 int multitable_item (), number_of_node ();
182 extern void add_link (), add_escaped_anchor_name ();
184 void me_execute_string_keep_state ();
185 void maybe_update_execution_strings ();
187 extern char *escape_string ();
188 extern void insert_html_tag ();
189 extern void sectioning_html ();
190 extern void add_link ();
192 #if defined (VA_FPRINTF) && __STDC__
193 /* Unfortunately we must use prototypes if we are to use <stdarg.h>. */
194 void add_word_args (char *, ...);
195 void execute_string (char *, ...);
197 void add_word_args ();
198 void execute_string ();
199 #endif /* no prototypes */
201 /* Error handling. */
203 /* Number of errors encountered. */
204 int errors_printed = 0;
206 /* Print the last error gotten from the file system. */
216 /* Print an error message, and return false. */
218 #if defined (VA_FPRINTF) && __STDC__
219 error (char *format, ...)
221 error (format, va_alist)
232 VA_START (ap, format);
234 VA_FPRINTF (stderr, format, ap);
236 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
237 #endif /* not VA_FPRINTF */
243 /* Just like error (), but print the input file and line number as well. */
245 #if defined (VA_FPRINTF) && __STDC__
246 file_line_error (char *infile, int lno, char *format, ...)
248 file_line_error (infile, lno, format, va_alist)
260 fprintf (stderr, "%s:%d: ", infile, lno);
262 VA_START (ap, format);
264 VA_FPRINTF (stderr, format, ap);
266 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
267 #endif /* not VA_FPRINTF */
270 fprintf (stderr, ".\n");
273 /* Just like file_line_error (), but take the input file and the line
274 number from global variables. */
276 #if defined (VA_FPRINTF) && __STDC__
277 line_error (char *format, ...)
279 line_error (format, va_alist)
289 fprintf (stderr, "%s:%d: ", input_filename, line_number);
291 VA_START (ap, format);
293 VA_FPRINTF (stderr, format, ap);
295 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
296 #endif /* not VA_FPRINTF */
299 fprintf (stderr, ".\n");
303 #if defined (VA_FPRINTF) && __STDC__
304 warning (char *format, ...)
306 warning (format, va_alist)
317 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
319 VA_START (ap, format);
321 VA_FPRINTF (stderr, format, ap);
323 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
324 #endif /* not VA_FPRINTF */
327 fprintf (stderr, ".\n");
332 /* Remember that an error has been printed. If more than
333 max_error_level have been printed, then exit the program. */
338 if (max_error_level && (errors_printed > max_error_level))
340 fprintf (stderr, _("Too many errors! Gave up.\n"));
347 /* The other side of a malformed expression. */
351 line_error (_("Misplaced %c"), '}');
356 /* Display the version info of this invocation of Makeinfo. */
358 print_version_info ()
360 printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION);
363 /* If EXIT_VALUE is zero, print the full usage message to stdout.
364 Otherwise, just say to use --help for more info.
365 Then exit with EXIT_VALUE. */
371 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
374 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname);
378 Translate Texinfo source documentation to various other formats, by default\n\
379 Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
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 --xml output XML (TexinfoML) rather than Info.\n\
403 General output options:\n\
404 -E, --macro-expand FILE output macro-expanded source to FILE.\n\
405 ignoring any @setfilename.\n\
406 --no-headers suppress node separators, Node: lines, and menus\n\
407 from Info output (thus producing plain text)\n\
408 or from HTML (thus producing shorter output);\n\
409 also, write to standard output by default.\n\
410 --no-split suppress splitting of Info or HTML output,\n\
411 generate only one output file.\n\
412 --number-sections output chapter and sectioning numbers.\n\
413 -o, --output=FILE output to FILE (directory if split HTML),\n\
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,
435 Input file options:\n\
436 --commands-in-node-names allow @ commands in node names.\n\
437 -D VAR define the variable VAR, as with @set.\n\
438 -I DIR append DIR to the @include search path.\n\
439 -P DIR prepend DIR to the @include search path.\n\
440 -U VAR undefine the variable VAR, as with @clear.\n\
444 Conditional processing in input:\n\
445 --ifhtml process @ifhtml and @html even if not generating HTML.\n\
446 --ifinfo process @ifinfo even if not generating Info.\n\
447 --ifplaintext process @ifplaintext even if not generating plain text.\n\
448 --iftex process @iftex and @tex; 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-ifplaintext do not process @ifplaintext text.\n\
452 --no-iftex do not process @iftex and @tex text.\n\
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, --ifinfo is on and the others are off;\n\
459 if generating plain text, --ifplaintext is on and the others are off;\n\
464 makeinfo foo.texi write Info to foo's @setfilename\n\
465 makeinfo --html foo.texi write HTML to @setfilename\n\
466 makeinfo --xml foo.texi write XML to @setfilename\n\
467 makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\
468 makeinfo --no-headers foo.texi write plain text to standard output\n\
470 makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
471 makeinfo --number-sections foo.texi write Info with numbered sections\n\
472 makeinfo --no-split foo.texi write one Info file however big\n\
476 Email bug reports to bug-texinfo@gnu.org,\n\
477 general questions and discussion to help-texinfo@gnu.org.\n\
478 Texinfo home page: http://www.gnu.org/software/texinfo/"));
483 struct option long_options[] =
485 { "commands-in-node-names", 0, &expensive_validation, 1 },
486 { "docbook", 0, 0, 'd' },
487 { "enable-encoding", 0, &enable_encoding, 1 },
488 { "error-limit", 1, 0, 'e' },
489 { "fill-column", 1, 0, 'f' },
490 { "footnote-style", 1, 0, 's' },
491 { "force", 0, &force, 1 },
492 { "help", 0, 0, 'h' },
493 { "html", 0, 0, 'w' },
494 { "ifhtml", 0, &process_html, 1 },
495 { "ifinfo", 0, &process_info, 1 },
496 { "ifplaintext", 0, &process_plaintext, 1 },
497 { "iftex", 0, &process_tex, 1 },
498 { "macro-expand", 1, 0, 'E' },
499 { "no-headers", 0, &no_headers, 1 },
500 { "no-ifhtml", 0, &process_html, 0 },
501 { "no-ifinfo", 0, &process_info, 0 },
502 { "no-ifplaintext", 0, &process_plaintext, 0 },
503 { "no-iftex", 0, &process_tex, 0 },
504 { "no-number-footnotes", 0, &number_footnotes, 0 },
505 { "no-number-sections", 0, &number_sections, 0 },
506 { "no-pointer-validate", 0, &validating, 0 },
507 { "no-split", 0, &splitting, 0 },
508 { "no-validate", 0, &validating, 0 },
509 { "no-warn", 0, &print_warnings, 0 },
510 { "number-footnotes", 0, &number_footnotes, 1 },
511 { "number-sections", 0, &number_sections, 1 },
512 { "output", 1, 0, 'o' },
513 { "paragraph-indent", 1, 0, 'p' },
514 { "reference-limit", 1, 0, 'r' },
515 { "split-size", 1, 0, 'S'},
516 { "verbose", 0, &verbose_mode, 1 },
517 { "version", 0, 0, 'V' },
518 { "xml", 0, 0, 'x' },
522 /* For each file mentioned in the command line, process it, turning
523 Texinfo commands into wonderfully formatted output text. */
529 extern int errors_printed;
531 int reading_from_stdin = 0;
533 #ifdef HAVE_SETLOCALE
534 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
535 of the argument to @multicolumn. */
536 setlocale (LC_TIME, "");
537 setlocale (LC_MESSAGES, "");
538 setlocale (LC_CTYPE, "");
539 setlocale (LC_COLLATE, "");
542 /* Set the text message domain. */
543 bindtextdomain (PACKAGE, LOCALEDIR);
544 textdomain (PACKAGE);
546 /* Parse argument flags from the input line. */
547 while ((c = getopt_long (argc, argv, "D:de:E:f:hI:o:p:P:r:s:U:vV:wx",
548 long_options, &ind)) != EOF)
550 if (c == 0 && long_options[ind].flag == 0)
551 c = long_options[ind].val;
557 /* User specified variable to set or clear. */
558 handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
561 case 'd': /* --docbook */
567 case 'e': /* --error-limit */
568 if (sscanf (optarg, "%d", &max_error_level) != 1)
571 _("%s: %s arg must be numeric, not `%s'.\n"),
572 "--error-limit", progname, optarg);
577 case 'E': /* --macro-expand */
578 if (!macro_expansion_output_stream)
580 macro_expansion_filename = optarg;
581 macro_expansion_output_stream
582 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
583 if (!macro_expansion_output_stream)
584 error (_("Couldn't open macro expansion output `%s'"), optarg);
587 error (_("Cannot specify more than one macro expansion output"));
590 case 'f': /* --fill-column */
591 if (sscanf (optarg, "%d", &fill_column) != 1)
594 _("%s: %s arg must be numeric, not `%s'.\n"),
595 "--fill-column", progname, optarg);
600 case 'h': /* --help */
605 /* Append user-specified dir to include file path. */
606 if (!include_files_path)
607 include_files_path = xstrdup (".");
609 include_files_path = (char *)
610 xrealloc (include_files_path,
611 2 + strlen (include_files_path) + strlen (optarg));
612 strcat (include_files_path, PATH_SEP);
613 strcat (include_files_path, optarg);
616 case 'o': /* --output */
617 command_output_filename = xstrdup (optarg);
618 save_command_output_filename = command_output_filename;
621 case 'p': /* --paragraph-indent */
622 if (set_paragraph_indent (optarg) < 0)
625 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
632 /* Prepend user-specified include dir to include path. */
633 if (!include_files_path)
635 include_files_path = xstrdup (optarg);
636 include_files_path = xrealloc (include_files_path,
637 strlen (include_files_path) + 3); /* 3 for ":.\0" */
638 strcat (strcat (include_files_path, PATH_SEP), ".");
642 char *tmp = xstrdup (include_files_path);
643 include_files_path = xrealloc (include_files_path,
644 strlen (include_files_path) + strlen (optarg) + 2); /* 2 for ":\0" */
645 strcpy (include_files_path, optarg);
646 strcat (include_files_path, ":");
647 strcat (include_files_path, tmp);
652 case 'r': /* --reference-limit */
653 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
656 _("%s: %s arg must be numeric, not `%s'.\n"),
657 "--reference-limit", progname, optarg);
662 case 's': /* --footnote-style */
663 if (set_footnote_style (optarg) < 0)
666 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
670 footnote_style_preset = 1;
673 case 'S': /* --split-size */
674 if (sscanf (optarg, "%d", &split_size) != 1)
677 _("%s: %s arg must be numeric, not `%s'.\n"),
678 "--split-size", progname, optarg);
687 case 'V': /* --version */
688 print_version_info ();
690 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
691 There is NO warranty. You may redistribute this software\n\
692 under the terms of the GNU General Public License.\n\
693 For more information about these matters, see the files named COPYING.\n"),
698 case 'w': /* --html */
703 case 'x': /* --xml */
715 expensive_validation = 0;
719 /* Check to see if input is a file. If so, process that. */
720 if (!isatty (fileno (stdin)))
721 reading_from_stdin = 1;
724 fprintf (stderr, _("%s: missing file argument.\n"), progname);
731 if (html && splitting)
732 { /* --no-headers --no-split --html indicates confusion. */
734 "%s: --no-headers conflicts with --no-split for --html.\n",
739 /* --no-headers implies --no-split. */
742 /* If the user did not specify an output file, use stdout. */
743 if (!command_output_filename)
744 command_output_filename = xstrdup ("-");
747 if (process_info == -1)
748 { /* no explicit --[no-]ifinfo option, so we'll do @ifinfo
749 if we're generating info or (for compatibility) plain text. */
750 process_info = !html && !xml;
753 if (process_plaintext == -1)
754 { /* no explicit --[no-]ifplaintext option, so we'll do @ifplaintext
755 if we're generating plain text. */
756 process_plaintext = no_headers && !html && !xml;
760 print_version_info ();
762 /* Remaining arguments are file names of texinfo files.
763 Convert them, one by one. */
764 if (!reading_from_stdin)
766 while (optind != argc)
767 convert_from_file (argv[optind++]);
770 convert_from_stream (stdin, "stdin");
772 return errors_printed ? 2 : 0;
776 /* Hacking tokens and strings. */
778 /* Return the next token as a string pointer. We cons the string. */
785 /* If the first character to be read is self-delimiting, then that
786 is the command itself. */
787 character = curchar ();
788 if (self_delimiting (character))
792 if (character == '\n')
795 result = xstrdup (" ");
800 for (i = 0; ((input_text_offset != input_text_length)
801 && (character = curchar ())
802 && command_char (character));
803 i++, input_text_offset++);
804 result = xmalloc (i + 1);
805 memcpy (result, &input_text[input_text_offset - i], i);
810 /* Return nonzero if CHARACTER is self-delimiting. */
812 self_delimiting (character)
815 /* @; and @\ are not Texinfo commands, but they are listed here
816 anyway. I don't know why. --karl, 10aug96. */
817 return strchr ("~{|}`^\\@?=;:.-,*\'\" !\n\t", character) != NULL;
820 /* Clear whitespace from the front and end of string. */
825 int len = strlen (string);
831 for (x = 0; x < len; x++)
833 if (!cr_or_whitespace (string[x]))
835 strcpy (string, string + x);
839 len = strlen (string);
842 while (len > -1 && cr_or_whitespace (string[len]))
847 /* Bash STRING, replacing all whitespace with just one space. */
849 fix_whitespace (string)
852 char *temp = xmalloc (strlen (string) + 1);
853 int string_index = 0;
857 canon_white (string);
859 while (string[string_index])
861 c = temp[temp_index++] = string[string_index++];
863 if (c == ' ' || c == '\n' || c == '\t')
865 temp[temp_index - 1] = ' ';
866 while ((c = string[string_index]) && (c == ' ' ||
872 temp[temp_index] = 0;
873 strcpy (string, temp);
877 /* Discard text until the desired string is found. The string is
878 included in the discarded text. */
880 discard_until (string)
883 int temp = search_forward (string, input_text_offset);
885 int tt = (temp < 0) ? input_text_length : temp + strlen (string);
886 int from = input_text_offset;
888 /* Find out what line we are on. */
890 if (input_text[from++] == '\n')
895 input_text_offset = input_text_length - strlen (string);
897 if (strcmp (string, "\n") != 0)
899 line_error (_("Expected `%s'"), string);
904 input_text_offset = temp;
906 input_text_offset += strlen (string);
909 /* Read characters from the file until we are at MATCH.
910 Place the characters read into STRING.
911 On exit input_text_offset is after the match string.
912 Return the offset where the string starts. */
914 get_until (match, string)
915 char *match, **string;
917 int len, current_point, x, new_point, tem;
919 current_point = x = input_text_offset;
920 new_point = search_forward (match, input_text_offset);
923 new_point = input_text_length;
924 len = new_point - current_point;
926 /* Keep track of which line number we are at. */
927 tem = new_point + (strlen (match) - 1);
929 if (input_text[x++] == '\n')
932 *string = xmalloc (len + 1);
934 memcpy (*string, &input_text[current_point], len);
937 /* Now leave input_text_offset in a consistent state. */
938 input_text_offset = tem;
940 if (input_text_offset > input_text_length)
941 input_text_offset = input_text_length;
946 /* Replace input_text[FROM .. TO] with its expansion. */
948 replace_with_expansion (from, to)
952 unsigned xp_len, new_len;
953 char *old_input = input_text;
954 unsigned raw_len = *to - from;
957 /* The rest of the code here moves large buffers, so let's
958 not waste time if the input cannot possibly expand
959 into anything. Unfortunately, we cannot avoid expansion
960 when we see things like @code etc., even if they only
961 asked for expansion of macros, since any Texinfo command
962 can be potentially redefined with a macro. */
963 if (only_macro_expansion &&
964 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
967 /* Get original string from input. */
968 str = xmalloc (raw_len + 1);
969 memcpy (str, input_text + from, raw_len);
972 /* We are going to relocate input_text, so we had better output
973 pending portion of input_text now, before the pointer changes. */
974 if (macro_expansion_output_stream && !executing_string
975 && !me_inhibit_expansion)
976 append_to_expansion_output (from);
979 xp = expansion (str, 0);
980 xp_len = strlen (xp);
983 /* Plunk the expansion into the middle of `input_text' --
984 which is terminated by a newline, not a null. Avoid
985 expensive move of the rest of the input if the expansion
986 has the same length as the original string. */
987 if (xp_len != raw_len)
989 new_len = from + xp_len + input_text_length - *to + 1;
990 if (executing_string)
991 { /* If we are in execute_string, we might need to update
992 the relevant element in the execution_strings[] array,
993 since it could have to be relocated from under our
994 feet. (input_text is reallocated here as well, if needed.) */
995 maybe_update_execution_strings (&input_text, new_len);
997 else if (new_len > input_text_length + 1)
998 /* Don't bother to realloc if we have enough space. */
999 input_text = xrealloc (input_text, new_len);
1001 memmove (input_text + from + xp_len,
1002 input_text + *to, input_text_length - *to + 1);
1004 *to += xp_len - raw_len;
1005 /* Since we change input_text_length here, the comparison above
1006 isn't really valid, but it seems the worst that might happen is
1007 an extra xrealloc or two, so let's not worry. */
1008 input_text_length += xp_len - raw_len;
1010 memcpy (input_text + from, xp, xp_len);
1013 /* Synchronize the macro-expansion pointers with our new input_text. */
1014 if (input_text != old_input)
1015 forget_itext (old_input);
1016 if (macro_expansion_output_stream && !executing_string)
1017 remember_itext (input_text, from);
1020 /* Read characters from the file until we are at MATCH or end of line.
1021 Place the characters read into STRING. If EXPAND is nonzero,
1022 expand the text before looking for MATCH for those cases where
1023 MATCH might be produced by some macro. */
1025 get_until_in_line (expand, match, string)
1027 char *match, **string;
1029 int real_bottom = input_text_length;
1030 int limit = search_forward ("\n", input_text_offset);
1032 limit = input_text_length;
1034 /* Replace input_text[input_text_offset .. limit-1] with its expansion.
1035 This allows the node names and menu entries themselves to be
1036 constructed via a macro, as in:
1038 Together: \p\ & \q\.
1041 @node @foo{A,B}, next, prev, top
1043 Otherwise, the `,' separating the macro args A and B is taken as
1044 the node argument separator, so the node name is `@foo{A'. This
1045 expansion is only necessary on the first call, since we expand the
1049 replace_with_expansion (input_text_offset, &limit);
1052 real_bottom = input_text_length;
1053 input_text_length = limit;
1054 get_until (match, string);
1055 input_text_length = real_bottom;
1059 get_rest_of_line (expand, string)
1068 /* Don't expand non-macros in input, since we want them
1069 intact in the macro-expanded output. */
1070 only_macro_expansion++;
1071 get_until_in_line (1, "\n", &tem);
1072 only_macro_expansion--;
1073 *string = expansion (tem, 0);
1077 get_until_in_line (0, "\n", string);
1079 canon_white (*string);
1081 if (curchar () == '\n') /* as opposed to the end of the file... */
1084 input_text_offset++;
1089 /* Backup the input pointer to the previous character, keeping track
1090 of the current line number. */
1092 backup_input_pointer ()
1094 if (input_text_offset)
1096 input_text_offset--;
1097 if (curchar () == '\n')
1102 /* Read characters from the file until we are at MATCH or closing brace.
1103 Place the characters read into STRING. */
1105 get_until_in_braces (match, string)
1106 char *match, **string;
1110 int match_len = strlen (match);
1112 for (i = input_text_offset; i < input_text_length; i++)
1114 if (i < input_text_length - 1 && input_text[i] == '@')
1116 i++; /* skip commands like @, and @{ */
1119 else if (input_text[i] == '{')
1121 else if (input_text[i] == '}')
1124 /* If looking for a brace, don't stop at the interior brace,
1125 like after "baz" in "@foo{something @bar{baz} more}". */
1129 else if (input_text[i] == '\n')
1133 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1137 match_len = i - input_text_offset;
1138 temp = xmalloc (2 + match_len);
1139 memcpy (temp, input_text + input_text_offset, match_len);
1140 temp[match_len] = 0;
1141 input_text_offset = i;
1145 /* Converting a file. */
1147 /* Convert the file named by NAME. The output is saved on the file
1148 named as the argument to the @setfilename command. */
1149 static char *suffixes[] = {
1150 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1151 have "texinfo.txi" and "texinfo.tex" in the same directory, the
1152 former is used rather than the latter, due to file name truncation. */
1162 initialize_conversion ()
1169 /* This is used for splitting the output file and for doing section
1170 headings. It was previously initialized in `init_paragraph', but its
1171 use there loses with the `init_paragraph' calls done by the
1172 multitable code; the tag indices get reset to zero. */
1173 output_position = 0;
1176 typedef struct generic_list {
1177 struct generic_list *next;
1180 /* Reverse the chain of structures in LIST. Output the new head
1181 of the chain. You should always assign the output value of this
1182 function to something, or you will lose the chain. */
1188 GENERIC_LIST *prev = NULL;
1200 /* We read in multiples of 4k, simply because it is a typical pipe size
1202 #define READ_BUFFER_GROWTH (4 * 4096)
1204 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1205 source of the stream is named NAME. */
1207 convert_from_stream (stream, name)
1211 char *buffer = NULL;
1212 int buffer_offset = 0, buffer_size = 0;
1214 initialize_conversion ();
1216 /* Read until the end of the stream. This isn't strictly correct, since
1217 the texinfo input may end before the stream ends, but it is a quick
1218 working hueristic. */
1219 while (!feof (stream))
1223 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1225 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1227 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1235 buffer_offset += count;
1240 /* Set the globals to the new file. */
1241 input_text = buffer;
1242 input_text_length = buffer_offset;
1243 input_filename = xstrdup (name);
1244 node_filename = xstrdup (name);
1245 input_text_offset = 0;
1248 /* Not strictly necessary. This magic prevents read_token () from doing
1249 extra unnecessary work each time it is called (that is a lot of times).
1250 The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1251 input_text[input_text_length] = '\n';
1253 convert_from_loaded_file (name);
1257 convert_from_file (name)
1261 char *filename = xmalloc (strlen (name) + 50);
1263 initialize_conversion ();
1265 /* Try to load the file specified by NAME, concatenated with our
1266 various suffixes. Prefer files like `makeinfo.texi' to
1268 for (i = 0; suffixes[i]; i++)
1270 strcpy (filename, name);
1271 strcat (filename, suffixes[i]);
1273 if (find_and_load (filename))
1276 if (!suffixes[i][0] && strrchr (filename, '.'))
1278 fs_error (filename);
1291 input_filename = filename;
1293 convert_from_loaded_file (name);
1296 /* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
1297 "/foo/bar/baz/baz.html". This routine is called only if html && splitting.
1299 Split html output goes into the subdirectory of the toplevel
1300 filename, without extension. For example:
1301 @setfilename foo.info
1302 produces output in files foo/index.html, foo/second-node.html, ...
1304 But if the user said -o foo.whatever on the cmd line, then use
1305 foo.whatever unchanged. */
1308 insert_toplevel_subdirectory (output_filename)
1309 char *output_filename;
1311 char *dir, *subdir, *base, *basename, *p;
1314 static const char index_name[] = "index.html";
1315 const int index_len = sizeof (index_name) - 1;
1317 strcpy (buf, output_filename);
1318 dir = pathname_part (buf);
1319 base = filename_part (buf);
1320 basename = xstrdup (base); /* remember real @setfilename name */
1321 p = dir + strlen (dir) - 1;
1322 if (p > dir && IS_SLASH (*p))
1324 p = strrchr (base, '.');
1328 /* Split html output goes into subdirectory of toplevel name. */
1330 if (FILENAME_CMP (base, filename_part (dir)) != 0)
1332 if (save_command_output_filename
1333 && STREQ (output_filename, save_command_output_filename))
1334 subdir = basename; /* from user, use unchanged */
1336 subdir = base; /* implicit, omit suffix */
1339 free (output_filename);
1340 output_filename = xmalloc (strlen (dir) + 1
1341 + strlen (basename) + 1
1344 strcpy (output_filename, dir);
1346 strcat (output_filename, "/");
1347 strcat (output_filename, subdir);
1348 if (mkdir (output_filename, 0777) == -1 && errno != EEXIST
1349 /* output_filename might exist, but be a non-directory. */
1350 || (stat (output_filename, &st) == 0 && !S_ISDIR (st.st_mode)))
1351 { /* that failed, try subdir name with .html */
1352 strcpy (output_filename, dir);
1354 strcat (output_filename, "/");
1355 strcat (output_filename, basename);
1356 if (mkdir (output_filename, 0777) == -1)
1358 char *errmsg = strerror (errno);
1360 if ((errno == EEXIST
1365 && (stat (output_filename, &st) == 0 && !S_ISDIR (st.st_mode)))
1366 errmsg = _("File exists, but is not a directory");
1367 line_error (_("Can't create directory `%s': %s"),
1368 output_filename, errmsg);
1371 strcat (output_filename, "/");
1373 else if (strlen (subdir))
1374 strcat (output_filename, "/");
1375 strcat (output_filename, index_name);
1376 return output_filename;
1379 /* FIXME: this is way too hairy */
1381 convert_from_loaded_file (name)
1384 char *real_output_filename = NULL;
1386 remember_itext (input_text, 0);
1388 input_text_offset = 0;
1390 /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1392 if (looking_at ("\\input"))
1393 discard_until ("\n");
1395 /* Search this file looking for the special string which starts conversion.
1396 Once found, we may truly begin. */
1397 while (input_text_offset >= 0)
1400 search_forward (setfilename_search, input_text_offset);
1402 if (input_text_offset == 0
1403 || (input_text_offset > 0
1404 && input_text[input_text_offset -1] == '\n'))
1406 else if (input_text_offset > 0)
1407 input_text_offset++;
1410 if (input_text_offset < 0)
1412 if (!command_output_filename)
1414 #if defined (REQUIRE_SETFILENAME)
1415 error (_("No `%s' found in `%s'"), setfilename_search, name);
1418 command_output_filename = output_name_from_input_name (name);
1419 #endif /* !REQUIRE_SETFILENAME */
1423 int i, end_of_first_line;
1425 /* Find the end of the first line in the file. */
1426 for (i = 0; i < input_text_length - 1; i++)
1427 if (input_text[i] == '\n')
1430 end_of_first_line = i + 1;
1432 for (i = 0; i < end_of_first_line; i++)
1434 if ((input_text[i] == '\\') &&
1435 (strncmp (input_text + i + 1, "input", 5) == 0))
1437 input_text_offset = i;
1444 input_text_offset += strlen (setfilename_search);
1446 if (!command_output_filename)
1448 get_until ("\n", &output_filename); /* read rest of line */
1449 if (xml && !docbook)
1450 xml_begin_document (output_filename);
1452 { /* Change any extension to .html or .xml. */
1453 char *html_name, *directory_part, *basename_part, *temp;
1455 canon_white (output_filename);
1456 directory_part = pathname_part (output_filename);
1458 basename_part = filename_part (output_filename);
1460 /* Zap any existing extension. */
1461 temp = strrchr (basename_part, '.');
1465 /* Construct new filename. */
1466 html_name = xmalloc (strlen (directory_part)
1467 + strlen (basename_part) + 6);
1468 strcpy (html_name, directory_part);
1469 strcat (html_name, basename_part);
1470 strcat (html_name, html ? ".html" : ".xml");
1472 /* Replace name from @setfilename with the html name. */
1473 free (output_filename);
1474 output_filename = html_name;
1479 if (input_text_offset != -1)
1480 discard_until ("\n");
1482 input_text_offset = 0;
1484 real_output_filename = output_filename = command_output_filename;
1485 command_output_filename = NULL; /* for included files or whatever */
1488 canon_white (output_filename);
1489 toplevel_output_filename = xstrdup (output_filename);
1491 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1493 if (macro_expansion_filename
1494 && strcmp (macro_expansion_filename, "-") == 0)
1497 _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1499 macro_expansion_output_stream = NULL;
1501 real_output_filename = xstrdup (real_output_filename);
1502 output_stream = stdout;
1503 splitting = 0; /* Cannot split when writing to stdout. */
1507 if (html && splitting)
1509 if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
1510 || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
1513 output_filename = insert_toplevel_subdirectory (output_filename);
1514 real_output_filename = xstrdup (output_filename);
1516 else if (!real_output_filename)
1517 real_output_filename = expand_filename (output_filename, name);
1519 real_output_filename = xstrdup (real_output_filename);
1521 output_stream = fopen (real_output_filename, "w");
1524 set_current_output_filename (real_output_filename);
1527 printf (_("Making %s file `%s' from `%s'.\n"),
1532 output_filename, input_filename);
1534 if (output_stream == NULL)
1536 fs_error (real_output_filename);
1540 /* Make the displayable filename from output_filename. Only the base
1541 portion of the filename need be displayed. */
1542 flush_output (); /* in case there was no @bye */
1543 if (output_stream != stdout)
1544 pretty_output_filename = filename_part (output_filename);
1546 pretty_output_filename = xstrdup ("stdout");
1548 /* For this file only, count the number of newlines from the top of
1549 the file to here. This way, we keep track of line numbers for
1550 error reporting. Line_number starts at 1, since the user isn't
1555 while (temp != input_text_offset)
1556 if (input_text[temp++] == '\n')
1560 /* html fixxme: should output this as trailer on first page. */
1561 if (!no_headers && !html && !xml)
1562 add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
1563 output_filename, VERSION, input_filename);
1568 xml_end_document ();
1572 discard_insertions (0);
1574 flush_file_stack ();
1576 if (macro_expansion_output_stream)
1578 fclose (macro_expansion_output_stream);
1579 if (errors_printed && !force
1580 && strcmp (macro_expansion_filename, "-") != 0
1581 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1582 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1584 fprintf (stderr, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1585 progname, macro_expansion_filename);
1586 if (unlink (macro_expansion_filename) < 0)
1587 perror (macro_expansion_filename);
1593 output_pending_notes ();
1596 tag_table = (TAG_ENTRY *) reverse_list (tag_table);
1597 if (!no_headers && !html)
1604 add_word ("</body></html>\n");
1608 flush_output (); /* in case there was no @bye */
1609 if (output_stream != stdout)
1610 fclose (output_stream);
1612 /* If validating, then validate the entire file right now. */
1614 validate_file (tag_table);
1616 /* If we need to output the table of contents, do it now. */
1617 if (contents_filename || shortcontents_filename)
1620 if (splitting && !html && (!errors_printed || force))
1621 split_file (real_output_filename, split_size);
1622 else if (errors_printed
1624 && strcmp (real_output_filename, "-") != 0
1625 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1626 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1627 { /* If there were errors, and no --force, remove the output. */
1628 fprintf (stderr, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1629 progname, real_output_filename);
1630 if (unlink (real_output_filename) < 0)
1631 perror (real_output_filename);
1634 free (real_output_filename);
1638 free_and_clear (pointer)
1648 /* Initialize some state. */
1652 free_and_clear (&output_filename);
1653 free_and_clear (&command);
1654 free_and_clear (&input_filename);
1655 free_node_references ();
1656 free_node_node_references ();
1658 init_insertion_stack ();
1659 init_brace_stack ();
1660 current_node = NULL; /* sometimes already freed */
1665 non_top_node_seen = 0;
1672 free_and_clear (&output_paragraph);
1673 output_paragraph = xmalloc (paragraph_buffer_len);
1674 output_paragraph[0] = 0;
1675 output_paragraph_offset = 0;
1677 paragraph_is_open = 0;
1682 /* This is called from `reader_loop' when we are at the * beginning a
1686 handle_menu_entry ()
1690 /* Ugh, glean_node_from_menu wants to read the * itself. */
1691 input_text_offset--;
1693 /* Find node name in menu entry and save it in references list for
1694 later validation. Use followed_reference type for detailmenu
1695 references since we don't want to use them for default node pointers. */
1696 tem = glean_node_from_menu (1, in_detailmenu
1697 ? followed_reference : menu_reference);
1700 { /* Start a menu item with the cleaned-up line. Put an anchor
1701 around the start text (before `:' or the node name). */
1704 discard_until ("* ");
1706 /* The line number was already incremented in reader_loop when we
1707 saw the newline, and discard_until has now incremented again. */
1710 if (had_menu_commentary)
1712 add_word ("<ul>\n");
1713 had_menu_commentary = 0;
1716 else if (!in_paragraph && !paragraph_is_open)
1728 add_word ("<li><a");
1729 if (next_menu_item_number <= 9)
1731 add_word(" accesskey=");
1732 add_word_args("%d", next_menu_item_number);
1733 next_menu_item_number++;
1735 add_word (" href=\"");
1736 string = expansion (tem, 0);
1737 add_anchor_name (string, 1);
1741 /* The menu item may use macros, so expand them now. */
1742 only_macro_expansion++;
1743 get_until_in_line (1, ":", &string);
1744 only_macro_expansion--;
1745 execute_string ("%s", string); /* get escaping done */
1750 if (looking_at ("::"))
1751 discard_until (":");
1753 { /* discard the node name */
1754 get_until_in_line (0, ".", &string);
1757 input_text_offset++; /* discard the second colon or the period */
1760 else if (xml && tem)
1762 xml_start_menu_entry (tem);
1765 { /* For Info output, we can just use the input and the main case in
1766 reader_loop where we output what comes in. Just move off the *
1767 so the next time through reader_loop we don't end up back here. */
1769 input_text_offset += 2; /* undo the pointer back-up above. */
1776 /* Find the command corresponding to STRING. If the command is found,
1777 return a pointer to the data structure. Otherwise return -1. */
1779 get_command_entry (string)
1784 for (i = 0; command_table[i].name; i++)
1785 if (strcmp (command_table[i].name, string) == 0)
1786 return &command_table[i];
1788 /* This command is not in our predefined command table. Perhaps
1789 it is a user defined command. */
1790 for (i = 0; i < user_command_array_len; i++)
1791 if (user_command_array[i] &&
1792 (strcmp (user_command_array[i]->name, string) == 0))
1793 return user_command_array[i];
1795 /* We never heard of this command. */
1796 return (COMMAND *) -1;
1799 /* input_text_offset is right at the command prefix character.
1800 Read the next token to determine what to do. Return zero
1801 if there's no known command or macro after the prefix character. */
1806 int old_text_offset = input_text_offset++;
1808 free_and_clear (&command);
1809 command = read_token ();
1811 /* Check to see if this command is a macro. If so, execute it here. */
1815 def = find_macro (command);
1819 /* We disallow recursive use of a macro call. Inhibit the expansion
1820 of this macro during the life of its execution. */
1821 if (!(def->flags & ME_RECURSE))
1824 execute_macro (def);
1826 if (!(def->flags & ME_RECURSE))
1833 if (only_macro_expansion)
1835 /* Back up to the place where we were called, so the
1836 caller will have a chance to process this non-macro. */
1837 input_text_offset = old_text_offset;
1841 /* Perform alias expansion */
1842 command = alias_expand (command);
1844 if (enclosure_command (command))
1846 remember_brace (enclosure_expand);
1847 enclosure_expand (START, output_paragraph_offset, 0);
1851 entry = get_command_entry (command);
1852 if (entry == (COMMAND *)-1)
1854 line_error (_("Unknown command `%s'"), command);
1858 if (entry->argument_in_braces == BRACE_ARGS)
1859 remember_brace (entry->proc);
1860 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
1862 if (curchar () == '{')
1863 remember_brace (entry->proc);
1865 { /* No braces, so arg is next char. */
1867 int saved_offset = output_paragraph_offset;
1868 (*(entry->proc)) (START, output_paragraph_offset, 0);
1870 /* Possibilities left for the next character: @ (error), }
1871 (error), whitespace (skip) anything else (normal char). */
1876 line_error (_("Use braces to give a command as an argument to @%s"),
1882 /* Our caller will give the error message, because this }
1883 won't match anything. */
1888 input_text_offset++;
1889 (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
1894 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
1896 (*(entry->proc)) (START, output_paragraph_offset, 0);
1900 /* Okay, we are ready to start the conversion. Call the reader on
1901 some text, and fill the text as it is output. Handle commands by
1902 remembering things like open braces and the current file position on a
1903 stack, and when the corresponding close brace is found, you can call
1904 the function with the proper arguments. Although the filling isn't
1905 necessary for HTML, it should do no harm. */
1915 if (input_text_offset >= input_text_length)
1918 character = curchar ();
1920 /* If only_macro_expansion, only handle macros and leave
1921 everything else intact. */
1922 if (!only_macro_expansion && !in_fixed_width_font
1923 && (character == '\'' || character == '`')
1924 && input_text[input_text_offset + 1] == character)
1926 input_text_offset++;
1927 character = '"'; /* html fixxme */
1930 /* Convert --- to --. */
1931 if (!only_macro_expansion && character == '-')
1934 if (dash_count == 2 && !in_fixed_width_font)
1936 input_text_offset++;
1940 else if (dash_count > 0)
1943 /* If this is a whitespace character, then check to see if the line
1944 is blank. If so, advance to the carriage return. */
1945 if (!only_macro_expansion && whitespace (character))
1947 int i = input_text_offset + 1;
1949 while (i < input_text_length && whitespace (input_text[i]))
1952 if (i == input_text_length || input_text[i] == '\n')
1954 if (i == input_text_length)
1957 input_text_offset = i;
1958 character = curchar ();
1962 if (character == '\n')
1967 case '*': /* perhaps we are at a menu */
1968 /* We used to check for this in the \n case but an @c in a
1969 menu swallows its newline, so check here instead. */
1970 if (!only_macro_expansion && in_menu
1971 && input_text_offset + 1 < input_text_length
1972 && input_text[input_text_offset-1] == '\n')
1973 handle_menu_entry ();
1975 { /* Duplicate code from below, but not worth twisting the
1976 fallthroughs to get down there. */
1977 add_char (character);
1978 input_text_offset++;
1982 /* Escapes for HTML unless we're outputting raw HTML. Do
1983 this always, even if SGML rules don't require it since
1984 that's easier and safer for non-conforming browsers. */
1986 if (html && escape_html)
1989 add_char (character);
1990 input_text_offset++;
1994 if (html && escape_html)
1997 xml_insert_entity ("lt");
1999 add_char (character);
2000 input_text_offset++;
2004 if (html && escape_html)
2007 xml_insert_entity ("gt");
2009 add_char (character);
2010 input_text_offset++;
2013 case COMMAND_PREFIX: /* @ */
2014 if (read_command () || !only_macro_expansion)
2017 /* FALLTHROUGH (usually) */
2019 /* Special case. We're not supposed to see this character by itself.
2020 If we do, it means there is a syntax error in the input text.
2021 Report the error here, but remember this brace on the stack so
2022 we can ignore its partner. */
2023 if (!only_macro_expansion)
2025 if (!STREQ (command, "math"))
2027 line_error (_("Misplaced %c"), '{');
2028 remember_brace (misplaced_brace);
2031 { /* We don't mind `extra' braces inside @math. */
2032 extern void cm_no_op ();
2033 remember_brace (cm_no_op);
2035 /* remember_brace advances input_text_offset. */
2039 /* FALLTHROUGH (usually) */
2041 if (!only_macro_expansion)
2043 pop_and_call_brace ();
2044 input_text_offset++;
2048 /* FALLTHROUGH (usually) */
2050 add_char (character);
2051 input_text_offset++;
2054 if (macro_expansion_output_stream && !only_macro_expansion)
2055 maybe_write_itext (input_text, input_text_offset);
2065 remember_brace (proc)
2066 COMMAND_FUNCTION *proc;
2068 if (curchar () != '{')
2069 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command);
2071 input_text_offset++;
2072 remember_brace_1 (proc, output_paragraph_offset);
2075 /* Remember the current output position here. Save PROC
2076 along with it so you can call it later. */
2078 remember_brace_1 (proc, position)
2079 COMMAND_FUNCTION *proc;
2082 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
2083 new->next = brace_stack;
2085 new->command = command ? xstrdup (command) : "";
2086 new->pos = position;
2087 new->line = line_number;
2088 new->in_fixed_width_font = in_fixed_width_font;
2092 /* Pop the top of the brace stack, and call the associated function
2093 with the args END and POS. */
2095 pop_and_call_brace ()
2097 if (brace_stack == NULL)
2099 line_error (_("Unmatched }"));
2104 BRACE_ELEMENT *temp;
2106 int pos = brace_stack->pos;
2107 COMMAND_FUNCTION *proc = brace_stack->proc;
2108 in_fixed_width_font = brace_stack->in_fixed_width_font;
2110 /* Reset current command, so the proc can know who it is. This is
2111 used in cm_accent. */
2112 command = brace_stack->command;
2114 temp = brace_stack->next;
2118 (*proc) (END, pos, output_paragraph_offset);
2122 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2124 adjust_braces_following (here, amount)
2127 BRACE_ELEMENT *stack = brace_stack;
2131 if (stack->pos >= here)
2132 stack->pos += amount;
2133 stack = stack->next;
2137 /* Return the string which invokes PROC; a pointer to a function.
2138 Always returns the first function in the command table if more than
2139 one matches PROC. */
2141 find_proc_name (proc)
2142 COMMAND_FUNCTION *proc;
2146 for (i = 0; command_table[i].name; i++)
2147 if (proc == command_table[i].proc)
2148 return command_table[i].name;
2149 return _("NO_NAME!");
2152 /* You call discard_braces () when you shouldn't have any braces on the stack.
2153 I used to think that this happens for commands that don't take arguments
2154 in braces, but that was wrong because of things like @code{foo @@}. So now
2155 I only detect it at the beginning of nodes. */
2164 if (brace_stack->proc != misplaced_brace)
2168 proc_name = find_proc_name (brace_stack->proc);
2169 file_line_error (input_filename, brace_stack->line,
2170 _("%c%s missing close brace"), COMMAND_PREFIX,
2172 pop_and_call_brace ();
2176 BRACE_ELEMENT *temp;
2177 temp = brace_stack->next;
2185 get_char_len (character)
2188 /* Return the printed length of the character. */
2194 len = (output_column + 8) & 0xf7;
2195 if (len > fill_column)
2196 len = fill_column - output_column;
2198 len = len - output_column;
2202 len = fill_column - output_column;
2206 /* ASCII control characters appear as two characters in the output
2207 (e.g., ^A). But characters with the high bit set are just one
2208 on suitable terminals, so don't count them as two for line
2209 breaking purposes. */
2210 if (0 <= character && character < ' ')
2219 #if defined (VA_FPRINTF) && __STDC__
2220 add_word_args (char *format, ...)
2222 add_word_args (format, va_alist)
2227 char buffer[2000]; /* xx no fixed limits */
2232 VA_START (ap, format);
2234 VA_SPRINTF (buffer, format, ap);
2236 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2237 #endif /* not VA_SPRINTF */
2242 /* Add STRING to output_paragraph. */
2248 add_char (*string++);
2251 /* Like add_word, but inhibits conversion of whitespace into .
2252 Use this to output HTML directives with embedded blanks, to make
2255 add_html_elt (string)
2263 /* Add the character to the current paragraph. If filling_enabled is
2264 nonzero, then do filling as well. */
2266 add_char (character)
2271 xml_add_char (character);
2275 /* If we are avoiding outputting headers, and we are currently
2276 in a menu, then simply return. But if we're only expanding macros,
2277 then we're being called from glean_node_from_menu to try to
2278 remember a menu reference, and we need that so we can do defaulting. */
2279 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2282 /* If we are adding a character now, then we don't have to
2283 ignore close_paragraph () calls any more. */
2284 if (must_start_paragraph && character != '\n')
2286 must_start_paragraph = 0;
2287 line_already_broken = 0; /* The line is no longer broken. */
2288 if (current_indent > output_column)
2290 indent (current_indent - output_column);
2291 output_column = current_indent;
2295 if (non_splitting_words
2296 && !(html && in_html_elt)
2297 && strchr (" \t\n", character))
2299 if (html || docbook)
2300 { /* Seems cleaner to use than an 8-bit char. */
2305 character = META (' '); /* unmeta-d in flush_output */
2308 insertion_paragraph_closed = 0;
2313 if (!filling_enabled && ! (html && (in_menu || in_detailmenu)))
2317 if (force_flush_right)
2320 /* Hack to force single blank lines out in this mode. */
2326 if (!no_indent && paragraph_is_open)
2327 indent (output_column = current_indent);
2330 else if (end_of_sentence_p ())
2331 /* CHARACTER is newline, and filling is enabled. */
2335 last_inserted_character = character;
2338 if (last_char_was_newline)
2341 last_char_was_newline++;
2347 last_char_was_newline = 1;
2356 default: /* not at newline */
2358 int len = get_char_len (character);
2359 int suppress_insert = 0;
2361 if ((character == ' ') && (last_char_was_newline))
2363 if (!paragraph_is_open)
2370 /* This is sad, but it seems desirable to not force any
2371 particular order on the front matter commands. This way,
2372 the document can do @settitle, @documentlanguage, etc, in
2373 any order and with any omissions, and we'll still output
2374 the html <head> `just in time'. */
2375 if (!executing_string && html && !html_output_head_p)
2376 html_output_head ();
2378 if (!paragraph_is_open)
2381 /* If the paragraph is supposed to be indented a certain
2382 way, then discard all of the pending whitespace.
2383 Otherwise, we let the whitespace stay. */
2384 if (!paragraph_start_indent)
2385 indent (pending_indent);
2388 /* This horrible kludge of checking for a < prevents <p>
2389 from being inserted when we already have html markup
2390 starting a paragraph, as with <ul> and <h1> and the like. */
2391 if (html && escape_html && character != '<'
2392 && (!in_fixed_width_font || in_menu || in_detailmenu))
2394 insert_string ("<p>");
2396 adjust_braces_following (0, 3); /* adjust for <p> */
2400 output_column += len;
2401 if (output_column > fill_column)
2403 if (filling_enabled && !html)
2405 int temp = output_paragraph_offset;
2406 while (--temp > 0 && output_paragraph[temp] != '\n')
2408 /* If we have found a space, we have the place to break
2410 if (output_paragraph[temp] == ' ')
2412 /* Remove trailing whitespace from output. */
2413 while (temp && whitespace (output_paragraph[temp - 1]))
2416 /* If we went back all the way to the newline of the
2417 preceding line, it probably means that the word we
2418 are adding is itself wider than the space that the
2419 indentation and the fill_column let us use. In
2420 that case, do NOT insert another newline, since it
2421 won't help. Just indent to current_indent and
2422 leave it alone, since that's the most we can do. */
2423 if (temp && output_paragraph[temp - 1] != '\n')
2424 output_paragraph[temp++] = '\n';
2426 /* We have correctly broken the line where we want
2427 to. What we don't want is spaces following where
2428 we have decided to break the line. We get rid of
2435 if (t1 == output_paragraph_offset)
2437 if (whitespace (character))
2438 suppress_insert = 1;
2441 if (!whitespace (output_paragraph[t1]))
2447 adjust_braces_following (temp, (- (t1 - temp)));
2448 strncpy ((char *) &output_paragraph[temp],
2449 (char *) &output_paragraph[t1],
2450 (output_paragraph_offset - t1));
2451 output_paragraph_offset -= (t1 - temp);
2455 /* Filled, but now indent if that is right. */
2456 if (indented_fill && current_indent > 0)
2458 int buffer_len = ((output_paragraph_offset - temp)
2460 char *temp_buffer = xmalloc (buffer_len);
2461 int indentation = 0;
2463 /* We have to shift any markers that are in
2464 front of the wrap point. */
2465 adjust_braces_following (temp, current_indent);
2467 while (current_indent > 0 &&
2468 indentation != current_indent)
2469 temp_buffer[indentation++] = ' ';
2471 memcpy ((char *) &temp_buffer[current_indent],
2472 (char *) &output_paragraph[temp],
2473 buffer_len - current_indent);
2475 if (output_paragraph_offset + buffer_len
2476 >= paragraph_buffer_len)
2478 unsigned char *tt = xrealloc
2480 (paragraph_buffer_len += buffer_len));
2481 output_paragraph = tt;
2483 memcpy ((char *) &output_paragraph[temp],
2484 temp_buffer, buffer_len);
2485 output_paragraph_offset += current_indent;
2489 while (temp < output_paragraph_offset)
2491 get_char_len (output_paragraph[temp++]);
2492 output_column += len;
2499 if (!suppress_insert)
2502 last_inserted_character = character;
2504 last_char_was_newline = 0;
2505 line_already_broken = 0;
2510 /* Add a character and store its position in meta_char_pos. */
2512 add_meta_char (character)
2515 meta_char_pos = output_paragraph_offset;
2516 add_char (character);
2519 /* Insert CHARACTER into `output_paragraph'. */
2524 output_paragraph[output_paragraph_offset++] = character;
2525 if (output_paragraph_offset == paragraph_buffer_len)
2528 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2532 /* Insert the null-terminated string STRING into `output_paragraph'. */
2534 insert_string (string)
2542 /* Sentences might have these characters after the period (or whatever). */
2543 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2546 /* Return true if at an end-of-sentence character, possibly followed by
2547 post-sentence punctuation to ignore. */
2549 end_of_sentence_p ()
2551 int loc = output_paragraph_offset - 1;
2553 /* If nothing has been output, don't check output_paragraph[-1]. */
2557 /* A post-sentence character that is at meta_char_pos is not really
2558 a post-sentence character; it was produced by a markup such as
2559 @samp. We don't want the period inside @samp to be treated as a
2562 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
2564 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
2568 /* Remove upto COUNT characters of whitespace from the
2569 the current output line. If COUNT is less than zero,
2570 then remove until none left. */
2572 kill_self_indent (count)
2575 /* Handle infinite case first. */
2579 while (output_paragraph_offset)
2581 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2582 output_paragraph_offset--;
2589 while (output_paragraph_offset && count--)
2590 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2591 output_paragraph_offset--;
2597 /* Nonzero means do not honor calls to flush_output (). */
2598 static int flushing_ignored = 0;
2600 /* Prevent calls to flush_output () from having any effect. */
2602 inhibit_output_flushing ()
2607 /* Allow calls to flush_output () to write the paragraph data. */
2609 uninhibit_output_flushing ()
2619 if (!output_paragraph_offset || flushing_ignored)
2622 for (i = 0; i < output_paragraph_offset; i++)
2624 /* If we turned on the 8th bit for a space inside @w, turn it
2625 back off for output. This might be problematic, since the
2626 0x80 character may be used in 8-bit character sets. Sigh.
2627 In any case, don't do this for HTML, since the nbsp character
2628 is valid input and must be passed along to the browser. */
2629 if (!html && (output_paragraph[i] & meta_character_bit))
2631 int temp = UNMETA (output_paragraph[i]);
2633 output_paragraph[i] &= 0x7f;
2637 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2639 output_position += output_paragraph_offset;
2640 output_paragraph_offset = 0;
2644 /* How to close a paragraph controlling the number of lines between
2645 this one and the last one. */
2647 /* Paragraph spacing is controlled by this variable. It is the number of
2648 blank lines that you wish to appear between paragraphs. A value of
2649 1 creates a single blank line between paragraphs. */
2650 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2653 close_paragraph_with_lines (lines)
2656 int old_spacing = paragraph_spacing;
2657 paragraph_spacing = lines;
2659 paragraph_spacing = old_spacing;
2662 /* Close the current paragraph, leaving no blank lines between them. */
2664 close_single_paragraph ()
2666 close_paragraph_with_lines (0);
2669 /* Close a paragraph after an insertion has ended. */
2671 close_insertion_paragraph ()
2673 if (!insertion_paragraph_closed)
2675 /* Close the current paragraph, breaking the line. */
2676 close_single_paragraph ();
2678 /* Start a new paragraph, with the correct indentation for the now
2679 current insertion level (one above the one that we are ending). */
2682 /* Tell `close_paragraph' that the previous line has already been
2683 broken, so it should insert one less newline. */
2684 line_already_broken = 1;
2686 /* Tell functions such as `add_char' we've already found a newline. */
2687 ignore_blank_line ();
2691 /* If the insertion paragraph is closed already, then we are seeing
2692 two `@end' commands in a row. Note that the first one we saw was
2693 handled in the first part of this if-then-else clause, and at that
2694 time `start_paragraph' was called, partially to handle the proper
2695 indentation of the current line. However, the indentation level
2696 may have just changed again, so we may have to outdent the current
2697 line to the new indentation level. */
2698 if (current_indent < output_column)
2699 kill_self_indent (output_column - current_indent);
2702 insertion_paragraph_closed = 1;
2705 /* Close the currently open paragraph. */
2711 /* The insertion paragraph is no longer closed. */
2712 insertion_paragraph_closed = 0;
2714 if (paragraph_is_open && !must_start_paragraph)
2718 tindex = output_paragraph_offset;
2720 /* Back up to last non-newline/space character, forcing all such
2721 subsequent characters to be newlines. This isn't strictly
2722 necessary, but a couple of functions use the presence of a newline
2723 to make decisions. */
2724 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
2726 c = output_paragraph[tindex];
2728 if (c == ' '|| c == '\n')
2729 output_paragraph[tindex] = '\n';
2734 /* All trailing whitespace is ignored. */
2735 output_paragraph_offset = ++tindex;
2737 /* Break the line if that is appropriate. */
2738 if (paragraph_spacing >= 0)
2741 /* Add as many blank lines as is specified in `paragraph_spacing'. */
2742 if (!force_flush_right)
2744 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
2747 /* Don't need anything extra for HTML in usual case of no
2748 extra paragraph spacing. */
2750 insert_string ("<br>");
2754 /* If we are doing flush right indentation, then do it now
2755 on the paragraph (really a single line). */
2756 if (force_flush_right)
2757 do_flush_right_indentation ();
2760 paragraph_is_open = 0;
2765 ignore_blank_line ();
2768 /* Make the last line just read look as if it were only a newline. */
2770 ignore_blank_line ()
2772 last_inserted_character = '\n';
2773 last_char_was_newline = 1;
2776 /* Align the end of the text in output_paragraph with fill_column. */
2778 do_flush_right_indentation ()
2783 kill_self_indent (-1);
2785 if (output_paragraph[0] != '\n')
2787 output_paragraph[output_paragraph_offset] = 0;
2789 if (output_paragraph_offset < fill_column)
2793 if (fill_column >= paragraph_buffer_len)
2795 xrealloc (output_paragraph,
2796 (paragraph_buffer_len += fill_column));
2798 temp_len = strlen ((char *)output_paragraph);
2799 temp = xmalloc (temp_len + 1);
2800 memcpy (temp, (char *)output_paragraph, temp_len);
2802 for (i = 0; i < fill_column - output_paragraph_offset; i++)
2803 output_paragraph[i] = ' ';
2805 memcpy ((char *)output_paragraph + i, temp, temp_len);
2807 output_paragraph_offset = fill_column;
2808 adjust_braces_following (0, i);
2813 /* Begin a new paragraph. */
2817 /* First close existing one. */
2818 if (paragraph_is_open)
2821 /* In either case, the insertion paragraph is no longer closed. */
2822 insertion_paragraph_closed = 0;
2824 /* However, the paragraph is open! */
2825 paragraph_is_open = 1;
2827 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
2828 had to be called before we would allow any other paragraph operations
2829 to have an effect. */
2830 if (!must_start_paragraph)
2832 int amount_to_indent = 0;
2834 /* If doing indentation, then insert the appropriate amount. */
2837 if (inhibit_paragraph_indentation)
2839 amount_to_indent = current_indent;
2840 if (inhibit_paragraph_indentation < 0)
2841 inhibit_paragraph_indentation++;
2843 else if (paragraph_start_indent < 0)
2844 amount_to_indent = current_indent;
2846 amount_to_indent = current_indent + paragraph_start_indent;
2848 if (amount_to_indent >= output_column)
2850 amount_to_indent -= output_column;
2851 indent (amount_to_indent);
2852 output_column += amount_to_indent;
2857 must_start_paragraph = 0;
2860 /* Insert the indentation specified by AMOUNT. */
2868 /* For every START_POS saved within the brace stack which will be affected
2869 by this indentation, bump that start pos forward. */
2870 adjust_braces_following (output_paragraph_offset, amount);
2872 while (--amount >= 0)
2876 /* Search forward for STRING in input_text.
2877 FROM says where where to start. */
2879 search_forward (string, from)
2883 int len = strlen (string);
2885 while (from < input_text_length)
2887 if (strncmp (input_text + from, string, len) == 0)
2894 /* Cross references. */
2896 /* Return next comma-delimited argument, but do not cross a close-brace
2897 boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
2898 the entire brace-delimited argument list with its expansion before
2899 looking for the next comma. */
2901 get_xref_token (expand)
2908 int old_offset = input_text_offset;
2909 int old_lineno = line_number;
2911 get_until_in_braces ("}", &string);
2912 if (curchar () == '}') /* as opposed to end of text */
2913 input_text_offset++;
2914 if (input_text_offset > old_offset)
2916 int limit = input_text_offset;
2918 input_text_offset = old_offset;
2919 line_number = old_lineno;
2920 only_macro_expansion++;
2921 replace_with_expansion (input_text_offset, &limit);
2922 only_macro_expansion--;
2927 get_until_in_braces (",", &string);
2928 if (curchar () == ',')
2929 input_text_offset++;
2930 fix_whitespace (string);
2934 /* NOTE: If you wonder why the HTML output is produced with such a
2935 peculiar mix of calls to add_word and execute_string, here's the
2936 reason. get_xref_token (1) expands all macros in a reference, but
2937 any other commands, like @value, @@, etc., are left intact. To
2938 expand them, we need to run the arguments through execute_string.
2939 However, characters like <, &, > and others cannot be let into
2940 execute_string, because they will be escaped. See the mess? */
2942 /* Make a cross reference. */
2948 char *arg1 = get_xref_token (1); /* expands all macros in xref */
2949 char *arg2 = get_xref_token (0);
2950 char *arg3 = get_xref_token (0);
2951 char *arg4 = get_xref_token (0);
2952 char *arg5 = get_xref_token (0);
2955 /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
2956 first argument must never be blank." --rms.
2957 We hereby comply by disallowing such constructs. */
2959 line_error (_("First argument to cross-reference may not be empty"));
2963 if (!*arg4 && !*arg5)
2965 char *arg1_id = xml_id (arg1);
2968 xml_insert_element_with_attribute (XREFNODENAME, START,
2969 "linkend=\"%s\"", arg1_id);
2972 execute_string (arg2);
2973 xml_insert_element (XREFNODENAME, END);
2977 xml_insert_element_with_attribute (XREF, START,
2978 "linkend=\"%s\"", arg1_id);
2980 xml_pop_current_element ();
2986 xml_insert_element (XREF, START);
2987 xml_insert_element (XREFNODENAME, START);
2988 execute_string (arg1);
2989 xml_insert_element (XREFNODENAME, END);
2992 xml_insert_element (XREFINFONAME, START);
2993 execute_string (arg2);
2994 xml_insert_element (XREFINFONAME, END);
2998 xml_insert_element (XREFPRINTEDDESC, START);
2999 execute_string (arg3);
3000 xml_insert_element (XREFPRINTEDDESC, END);
3004 xml_insert_element (XREFINFOFILE, START);
3005 execute_string (arg4);
3006 xml_insert_element (XREFINFOFILE, END);
3010 xml_insert_element (XREFPRINTEDNAME, START);
3011 execute_string (arg5);
3012 xml_insert_element (XREFPRINTEDNAME, END);
3014 xml_insert_element (XREF, END);
3019 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
3022 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
3029 arg2 - reference name
3030 arg3 - title or topic (and reference name if arg2 is NULL)
3031 arg4 - info file name
3032 arg5 - printed manual title */
3047 /* html fixxme: revisit this; external node name not
3048 much use to us with numbered nodes. */
3049 add_html_elt ("<a href=");
3050 /* Note that if we are splitting, and the referenced
3051 tag is an anchor rather than a node, we will
3052 produce a reference to a file whose name is
3053 derived from the anchor name. However, only
3054 nodes create files, so we are referencing a
3055 non-existent file. cm_anchor, which see, deals
3056 with that problem. */
3058 execute_string ("\"../%s/", arg4);
3060 execute_string ("\"%s.html", arg4);
3061 /* Do not collapse -- to -, etc., in references. */
3062 in_fixed_width_font++;
3063 tem = expansion (arg1, 0); /* expand @-commands in node */
3064 in_fixed_width_font--;
3065 add_anchor_name (tem, 1);
3068 execute_string ("%s", ref_name);
3073 execute_string ("%s:", ref_name);
3074 in_fixed_width_font++;
3075 execute_string (" (%s)%s%s", arg4, arg1, px_ref_flag ? "." : "");
3076 in_fixed_width_font--;
3079 /* Free all of the arguments found. */
3080 if (arg1) free (arg1);
3081 if (arg2) free (arg2);
3082 if (arg3) free (arg3);
3083 if (arg4) free (arg4);
3084 if (arg5) free (arg5);
3088 remember_node_reference (arg1, line_number, followed_reference);
3094 add_html_elt ("<a href=\"");
3095 in_fixed_width_font++;
3096 tem = expansion (arg1, 0);
3097 in_fixed_width_font--;
3098 add_anchor_name (tem, 1);
3101 execute_string ("%s", *arg2 ? arg2 : arg3);
3106 execute_string ("%s:", *arg2 ? arg2 : arg3);
3107 in_fixed_width_font++;
3108 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
3109 in_fixed_width_font--;
3116 add_html_elt ("<a href=\"");
3117 in_fixed_width_font++;
3118 tem = expansion (arg1, 0);
3119 in_fixed_width_font--;
3120 add_anchor_name (tem, 1);
3123 execute_string ("%s", *arg2 ? arg2 : arg1);
3130 execute_string ("%s:", arg2);
3131 in_fixed_width_font++;
3132 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
3133 in_fixed_width_font--;
3137 in_fixed_width_font++;
3138 execute_string ("%s::", arg1);
3139 in_fixed_width_font--;
3144 /* Free all of the arguments found. */
3145 if (arg1) free (arg1);
3146 if (arg2) free (arg2);
3147 if (arg3) free (arg3);
3148 if (arg4) free (arg4);
3149 if (arg5) free (arg5);
3152 { /* Check to make sure that the next non-whitespace character is
3153 valid to follow an xref (so info readers can find the node
3154 names). `input_text_offset' is pointing at the "}" which ended
3155 the xref or ref command. */
3158 for (temp = input_text_offset + 1; temp < input_text_length; )
3160 if (cr_or_whitespace (input_text[temp]))
3164 if (input_text[temp] != '.' && input_text[temp] != ',')
3165 warning (_("`.' or `,' must follow cross reference, not %c"),
3183 /* Note that cm_xref isn't called with arg == END, which disables
3184 the code near the end of cm_xref that checks for `.' or `,'
3185 after the cross-reference. This is because @pxref{} generates
3186 the required character itself, when needed. */
3207 char *node = get_xref_token (1); /* expands all macros in inforef */
3208 char *pname = get_xref_token (0);
3209 char *file = get_xref_token (0);
3211 /* (see comments at cm_xref). */
3213 line_error (_("First argument to @inforef may not be empty"));
3215 if (xml && !docbook)
3217 xml_insert_element (INFOREF, START);
3218 xml_insert_element (INFOREFNODENAME, START);
3219 execute_string (node);
3220 xml_insert_element (INFOREFNODENAME, END);
3223 xml_insert_element (INFOREFREFNAME, START);
3224 execute_string (pname);
3225 xml_insert_element (INFOREFREFNAME, END);
3227 xml_insert_element (INFOREFINFONAME, START);
3228 execute_string (file);
3229 xml_insert_element (INFOREFINFONAME, END);
3231 xml_insert_element (INFOREF, END);
3237 add_word (_("see "));
3238 /* html fixxme: revisit this */
3239 add_html_elt ("<a href=");
3241 execute_string ("\"../%s/", file);
3243 execute_string ("\"%s.html", file);
3244 tem = expansion (node, 0);
3245 add_anchor_name (tem, 1);
3247 execute_string ("%s", *pname ? pname : tem);
3254 execute_string ("*note %s: (%s)%s", pname, file, node);
3256 execute_string ("*note (%s)%s::", file, node);
3265 /* A URL reference. */
3272 extern int printing_index;
3273 char *url = get_xref_token (1); /* expands all macros in uref */
3274 char *desc = get_xref_token (0);
3275 char *replacement = get_xref_token (0);
3279 xml_insert_element (UREF, START);
3280 xml_insert_element (UREFURL, START);
3281 execute_string (url);
3282 xml_insert_element (UREFURL, END);
3285 xml_insert_element (UREFDESC, START);
3286 execute_string (desc);
3287 xml_insert_element (UREFDESC, END);
3291 xml_insert_element (UREFREPLACEMENT, START);
3292 execute_string (replacement);
3293 xml_insert_element (UREFREPLACEMENT, END);
3295 xml_insert_element (UREF, END);
3298 { /* never need to show the url */
3299 add_html_elt ("<a href=");
3300 /* don't collapse `--' etc. in the url */
3301 in_fixed_width_font++;
3302 execute_string ("\"%s\"", url);
3303 in_fixed_width_font--;
3305 execute_string ("%s", *replacement ? replacement
3306 : (*desc ? desc : url));
3309 else if (*replacement) /* do not show the url */
3310 execute_string ("%s", replacement);
3311 else if (*desc) /* show both text and url */
3313 execute_string ("%s ", desc);
3314 in_fixed_width_font++;
3315 execute_string ("(%s)", url);
3316 in_fixed_width_font--;
3318 else /* no text at all, so have the url to show */
3320 in_fixed_width_font++;
3321 execute_string ("%s%s%s",
3322 printing_index ? "" : "`",
3324 printing_index ? "" : "'");
3325 in_fixed_width_font--;
3336 /* An email reference. */
3343 char *addr = get_xref_token (1); /* expands all macros in email */
3344 char *name = get_xref_token (0);
3348 xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
3350 execute_string (name);
3351 xml_insert_element (EMAIL, END);
3355 xml_insert_element (EMAIL, START);
3356 xml_insert_element (EMAILADDRESS, START);
3357 execute_string (addr);
3358 xml_insert_element (EMAILADDRESS, END);
3361 xml_insert_element (EMAILNAME, START);
3362 execute_string (name);
3363 xml_insert_element (EMAILNAME, END);
3365 xml_insert_element (EMAIL, END);
3369 add_html_elt ("<a href=");
3370 /* don't collapse `--' etc. in the address */
3371 in_fixed_width_font++;
3372 execute_string ("\"mailto:%s\"", addr);
3373 in_fixed_width_font--;
3375 execute_string ("%s", *name ? name : addr);
3380 execute_string ("%s%s", name, *name ? " " : "");
3381 in_fixed_width_font++;
3382 execute_string ("<%s>", addr);
3383 in_fixed_width_font--;
3393 /* An external image is a reference, kind of. The parsing is (not
3394 coincidentally) similar, anyway. */
3399 char *name_arg, *rest, *alt_arg, *ext_arg;
3404 name_arg = get_xref_token (1); /* expands all macros in image */
3405 /* We don't (yet) care about the next two args, but read them so they
3406 don't end up in the text. */
3407 rest = get_xref_token (0);
3410 rest = get_xref_token (0);
3413 alt_arg = get_xref_token (1); /* expands all macros in alt text */
3414 ext_arg = get_xref_token (0);
3418 char *fullname = xmalloc (strlen (name_arg)
3419 + (ext_arg && *ext_arg ? strlen (ext_arg) + 1 : 4) + 1);
3423 if (ext_arg && *ext_arg)
3425 sprintf (fullname, "%s.%s", name_arg, ext_arg);
3426 if (access (fullname, R_OK) != 0)
3428 line_error(_("@image file `%s' (for HTML) not readable: %s"),
3429 fullname, strerror (errno));
3435 sprintf (fullname, "%s.png", name_arg);
3436 if (access (fullname, R_OK) != 0)
3438 sprintf (fullname, "%s.jpg", name_arg);
3439 if (access (fullname, R_OK) != 0)
3441 line_error (_("No `%s.png' or `.jpg', and no extension supplied"),
3448 add_html_elt ("<img src=");
3449 add_word_args ("\"%s\"", fullname);
3450 add_html_elt (" alt=");
3451 add_word_args ("\"%s\">", (*alt_arg) ? alt_arg : fullname);
3453 else if (xml && docbook)
3454 xml_insert_docbook_image (name_arg);
3457 xml_insert_element (IMAGE, START);
3458 add_word (name_arg);
3459 xml_insert_element (IMAGE, END);
3462 { /* Try to open foo.txt. */
3464 strcpy (fullname, name_arg);
3465 strcat (fullname, ".txt");
3466 image_file = fopen (fullname, "r");
3470 int save_inhibit_indentation = inhibit_paragraph_indentation;
3471 int save_filling_enabled = filling_enabled;
3473 inhibit_paragraph_indentation = 1;
3474 filling_enabled = 0;
3475 last_char_was_newline = 0;
3477 /* Maybe we need to remove the final newline if the image
3478 file is only one line to allow in-line images. On the
3479 other hand, they could just make the file without a
3481 while ((ch = getc (image_file)) != EOF)
3484 inhibit_paragraph_indentation = save_inhibit_indentation;
3485 filling_enabled = save_filling_enabled;
3487 if (fclose (image_file) != 0)
3491 line_error (_("@image file `%s' (for text) unreadable: %s"),
3492 fullname, strerror (errno));
3498 line_error (_("@image missing filename argument"));
3510 /* A structure which contains `defined' variables. */
3511 typedef struct defines {
3512 struct defines *next;
3517 /* The linked list of `set' defines. */
3518 DEFINE *defines = NULL;
3520 /* Add NAME to the list of `set' defines. */
3528 for (temp = defines; temp; temp = temp->next)
3529 if (strcmp (name, temp->name) == 0)
3532 temp->value = xstrdup (value);
3536 temp = xmalloc (sizeof (DEFINE));
3537 temp->next = defines;
3538 temp->name = xstrdup (name);
3539 temp->value = xstrdup (value);
3543 /* Remove NAME from the list of `set' defines. */
3548 DEFINE *temp, *last;
3555 if (strcmp (temp->name, name) == 0)
3558 last->next = temp->next;
3560 defines = temp->next;
3572 /* Return the value of NAME. The return value is NULL if NAME is unset. */
3579 for (temp = defines; temp; temp = temp->next)
3580 if (strcmp (temp->name, name) == 0)
3586 /* Create a variable whose name appears as the first word on this line. */
3590 handle_variable (SET);
3593 /* Remove a variable whose name appears as the first word on this line. */
3597 handle_variable (CLEAR);
3603 handle_variable (IFSET);
3609 handle_variable (IFCLEAR);
3612 /* This command takes braces, but we parse the contents specially, so we
3613 don't use the standard brace popping code.
3615 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3616 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3617 it produces no output. */
3623 arglist = get_brace_args (0);
3627 if (array_len (arglist) > 1)
3629 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
3631 execute_string ("%s\n", arglist[2]);
3634 free_array (arglist);
3639 cm_value (arg, start_pos, end_pos)
3640 int arg, start_pos, end_pos;
3642 static int value_level = 0, saved_meta_pos = -1;
3644 /* All the text after @value{ upto the matching } will eventually
3645 disappear from output_paragraph, when this function is called
3646 with ARG == END. If the text produced until then sets
3647 meta_char_pos, we will need to restore it to the value it had
3648 before @value was seen. So we need to save the previous value
3649 of meta_char_pos here. */
3652 /* If we are already inside some outer @value, don't overwrite
3653 the value saved in saved_meta_pos. */
3655 saved_meta_pos = meta_char_pos;
3657 /* While the argument of @value is processed, we need to inhibit
3658 textual transformations like "--" into "-", since @set didn't
3659 do that when it grabbed the name of the variable. */
3660 in_fixed_width_font++;
3664 char *name = (char *) &output_paragraph[start_pos];
3666 output_paragraph[end_pos] = 0;
3667 name = xstrdup (name);
3668 value = set_p (name);
3669 output_column -= end_pos - start_pos;
3670 output_paragraph_offset = start_pos;
3672 /* Restore the previous value of meta_char_pos if the stuff
3673 inside this @value{} moved it. */
3674 if (saved_meta_pos == -1) /* can't happen inside @value{} */
3676 if (value_level == 1
3677 && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3679 meta_char_pos = saved_meta_pos;
3680 saved_meta_pos = -1;
3683 /* No need to decrement in_fixed_width_font, since before
3684 we are called with arg == END, the reader loop already
3685 popped the brace stack, which restored in_fixed_width_font,
3686 among other things. */
3689 execute_string ("%s", value);
3691 add_word_args (_("{No value for `%s'}"), name);
3697 /* Set, clear, or conditionalize based on ACTION. */
3699 handle_variable (action)
3704 get_rest_of_line (0, &name);
3705 /* If we hit the end of text in get_rest_of_line, backing up
3706 input pointer will cause the last character of the last line
3707 be pushed back onto the input, which is wrong. */
3708 if (input_text_offset < input_text_length)
3709 backup_input_pointer ();
3710 handle_variable_internal (action, name);
3715 handle_variable_internal (action, name)
3720 int delimiter, additional_text_present = 0;
3722 /* Only the first word of NAME is a valid tag. */
3725 while (*temp && (delimiter || !whitespace (*temp)))
3727 /* #if defined (SET_WITH_EQUAL) */
3728 if (*temp == '"' || *temp == '\'')
3730 if (*temp == delimiter)
3735 /* #endif SET_WITH_EQUAL */
3740 additional_text_present++;
3745 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3754 #if defined (SET_WITH_EQUAL)
3755 /* Allow a value to be saved along with a variable. The value is
3756 the text following an `=' sign in NAME, if any is present. */
3758 for (value = name; *value && *value != '='; value++);
3763 if (*value == '"' || *value == '\'')
3766 value[strlen (value) - 1] = 0;
3769 #else /* !SET_WITH_EQUAL */
3770 /* The VALUE of NAME is the remainder of the line sans
3772 if (additional_text_present)
3775 canon_white (value);
3779 #endif /* !SET_WITH_VALUE */
3791 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3792 read lines from the the file until we reach a matching
3793 "@end CONDITION". This means that we only take note of
3794 "@ifset/clear" and "@end" commands. */
3798 int orig_line_number = line_number;
3800 if (action == IFSET)
3801 strcpy (condition, "ifset");
3803 strcpy (condition, "ifclear");
3805 condition_len = strlen (condition);
3807 if ((action == IFSET && !set_p (name))
3808 || (action == IFCLEAR && set_p (name)))
3810 int level = 0, done = 0;
3812 while (!done && input_text_offset < input_text_length)
3814 char *freeable_line, *line;
3816 get_rest_of_line (0, &freeable_line);
3818 for (line = freeable_line; whitespace (*line); line++);
3820 if (*line == COMMAND_PREFIX &&
3821 (strncmp (line + 1, condition, condition_len) == 0))
3823 else if (strncmp (line, "@end", 4) == 0)
3825 char *cname = line + 4;
3828 while (*cname && whitespace (*cname))
3832 while (*temp && !whitespace (*temp))
3836 if (strcmp (cname, condition) == 0)
3846 free (freeable_line);
3850 file_line_error (input_filename, orig_line_number,
3851 _("Reached eof before matching @end %s"),
3854 /* We found the end of a false @ifset/ifclear. If we are
3855 in a menu, back up over the newline that ends the ifset,
3856 since that newline may also begin the next menu entry. */
3861 if (action == IFSET)
3862 begin_insertion (ifset);
3864 begin_insertion (ifclear);
3872 /* Execution of random text not in file. */
3875 char *string; /* The string buffer. */
3876 int size; /* The size of the buffer. */
3877 int in_use; /* Nonzero means string currently in use. */
3880 static EXECUTION_STRING **execution_strings = NULL;
3881 static int execution_strings_index = 0;
3882 static int execution_strings_slots = 0;
3885 get_execution_string (initial_size)
3889 EXECUTION_STRING *es = NULL;
3891 if (execution_strings)
3893 for (i = 0; i < execution_strings_index; i++)
3894 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
3896 es = execution_strings[i];
3903 if (execution_strings_index + 1 >= execution_strings_slots)
3905 execution_strings = xrealloc
3907 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
3908 for (; i < execution_strings_slots; i++)
3909 execution_strings[i] = NULL;
3912 execution_strings[execution_strings_index] =
3913 xmalloc (sizeof (EXECUTION_STRING));
3914 es = execution_strings[execution_strings_index];
3915 execution_strings_index++;
3922 if (initial_size > es->size)
3924 es->string = xrealloc (es->string, initial_size);
3925 es->size = initial_size;
3930 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
3931 entry in the execution_strings[] array and change the .STRING and
3932 .SIZE members of that entry as appropriate. */
3934 maybe_update_execution_strings (text, new_len)
3940 if (execution_strings)
3942 for (i = 0; i < execution_strings_index; i++)
3943 if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
3944 execution_strings[i]->string == *text)
3946 /* Don't ever shrink the string storage in execution_strings[]!
3947 execute_string assumes that it is always big enough to store
3948 every possible execution_string, and will break if that's
3949 not true. So we only enlarge the string storage if the
3950 current size isn't big enough. */
3951 if (execution_strings[i]->size < new_len)
3953 execution_strings[i]->string =
3954 *text = xrealloc (*text, new_len + 1);
3955 execution_strings[i]->size = new_len + 1;
3960 /* We should *never* end up here, since if we are inside
3961 execute_string, TEXT is always in execution_strings[]. */
3965 /* FIXME: this is an arbitrary limit. */
3966 #define EXECUTE_STRING_MAX 16*1024
3968 /* Execute the string produced by formatting the ARGs with FORMAT. This
3969 is like submitting a new file with @include. */
3971 #if defined (VA_FPRINTF) && __STDC__
3972 execute_string (char *format, ...)
3974 execute_string (format, va_alist)
3979 EXECUTION_STRING *es;
3985 es = get_execution_string (EXECUTE_STRING_MAX);
3986 temp_string = es->string;
3989 VA_START (ap, format);
3991 VA_SPRINTF (temp_string, format, ap);
3993 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
3994 #endif /* not VA_SPRINTF */
3998 input_text_offset = 0;
3999 input_text = temp_string;
4000 input_filename = xstrdup (input_filename);
4001 input_text_length = strlen (temp_string);
4005 free (input_filename);
4013 /* Return what would be output for STR (in newly-malloced memory), i.e.,
4014 expand Texinfo commands. If IMPLICIT_CODE is set, expand @code{STR}.
4015 This is generally used for short texts; filling, indentation, and
4016 html escapes are disabled. */
4019 expansion (str, implicit_code)
4025 /* Inhibit indentation and filling, so that extra newlines
4026 are not added to the expansion. (This is undesirable if
4027 we write the expanded text to macro_expansion_output_stream.) */
4028 int saved_filling_enabled = filling_enabled;
4029 int saved_indented_fill = indented_fill;
4030 int saved_no_indent = no_indent;
4031 int saved_escape_html = escape_html;
4033 filling_enabled = 0;
4038 result = full_expansion (str, implicit_code);
4040 filling_enabled = saved_filling_enabled;
4041 indented_fill = saved_indented_fill;
4042 no_indent = saved_no_indent;
4043 escape_html = saved_escape_html;
4049 /* Expand STR (or @code{STR} if IMPLICIT_CODE is nonzero). No change to
4050 any formatting parameters -- filling, indentation, html escapes,
4051 etc., are not reset. */
4054 full_expansion (str, implicit_code)
4061 /* Inhibit any real output. */
4062 int start = output_paragraph_offset;
4063 int saved_paragraph_is_open = paragraph_is_open;
4064 int saved_output_column = output_column;
4066 /* More output state to save. */
4067 int saved_meta_pos = meta_char_pos;
4068 int saved_last_char = last_inserted_character;
4069 int saved_last_nl = last_char_was_newline;
4071 /* If we are called in the middle of processing a command, we need
4072 to dup and save the global variable `command' (which holds the
4073 name of this command), since the recursive reader loop will free
4074 it from under our feet if it finds any macros in STR. */
4075 char *saved_command = command ? xstrdup (command) : NULL;
4077 inhibit_output_flushing ();
4078 paragraph_is_open = 1;
4079 if (strlen (str) > (implicit_code
4080 ? EXECUTE_STRING_MAX - 1 - sizeof("@code{}")
4081 : EXECUTE_STRING_MAX - 1))
4082 line_error (_("`%.40s...' is too long for expansion; not expanded"), str);
4084 execute_string (implicit_code ? "@code{%s}" : "%s", str);
4085 uninhibit_output_flushing ();
4087 /* Copy the expansion from the buffer. */
4088 length = output_paragraph_offset - start;
4089 result = xmalloc (1 + length);
4090 memcpy (result, (char *) (output_paragraph + start), length);
4093 /* Pretend it never happened. */
4094 free_and_clear (&command);
4095 command = saved_command;
4097 output_paragraph_offset = start;
4098 paragraph_is_open = saved_paragraph_is_open;
4099 output_column = saved_output_column;
4101 meta_char_pos = saved_meta_pos;
4102 last_inserted_character = saved_last_char;
4103 last_char_was_newline = saved_last_nl;
4109 /* Return text (info) expansion of STR no matter what the current output
4113 text_expansion (str)
4117 int save_html = html;
4122 ret = expansion (str, 0);
4130 /* Set the paragraph indentation variable to the value specified in STRING.
4132 `asis': Don't change existing indentation.
4133 `none': Remove existing indentation.
4134 NUM: Indent NUM spaces at the starts of paragraphs.
4135 If NUM is zero, we assume `none'.
4136 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
4138 set_paragraph_indent (string)
4141 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
4142 paragraph_start_indent = 0;
4143 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
4144 paragraph_start_indent = -1;
4147 if (sscanf (string, "%d", ¶graph_start_indent) != 1)
4151 if (paragraph_start_indent == 0)
4152 paragraph_start_indent = -1;