1 /* makeinfo -- convert Texinfo source into other formats.
2 $Id: makeinfo.c,v 1.171 1999/09/19 15:24:44 karl Exp $
4 Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98, 99
5 Free Software Foundation, Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 Makeinfo was authored by Brian Fox (bfox@ai.mit.edu). */
26 #define COMPILING_MAKEINFO
33 #include "insertion.h"
38 /* We'd like to take advantage of _doprnt if it's around, a la error.c,
39 but then we'd have no VA_SPRINTF. */
43 # define VA_START(args, lastarg) va_start(args, lastarg)
46 # define VA_START(args, lastarg) va_start(args)
48 # define VA_FPRINTF(file, fmt, ap) vfprintf (file, fmt, ap)
49 # define VA_SPRINTF(str, fmt, ap) vsprintf (str, fmt, ap)
50 #else /* not HAVE_VPRINTF */
51 # define VA_START(args, lastarg)
52 # define va_alist a1, a2, a3, a4, a5, a6, a7, a8
53 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
57 /* DJGPP supports /dev/null, which is okay for Unix aficionados,
58 shell scripts and Makefiles, but interactive DOS die-hards
59 would probably want to have NUL as well. */
61 # define ALSO_NULL_DEVICE "NUL"
63 # define ALSO_NULL_DEVICE ""
66 /* You can change some of the behavior of Makeinfo by changing the
69 /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
70 appear within an @table, @ftable, or @itemize environment to have
71 standard paragraph indentation. Without this, such paragraphs have
72 no starting indentation. */
73 /* #define INDENT_PARAGRAPHS_IN_TABLE */
75 /* Define PARAGRAPH_START_INDENT to be the amount of indentation that
76 the first lines of paragraphs receive by default, where no other
77 value has been specified. Users can change this value on the command
78 line, with the --paragraph-indent option, or within the texinfo file,
79 with the @paragraphindent command. */
80 #define PARAGRAPH_START_INDENT 3
82 /* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
83 wish to appear between paragraphs. A value of 1 creates a single blank
84 line between paragraphs. Paragraphs are defined by 2 or more consecutive
85 newlines in the input file (i.e., one or more blank lines). */
86 #define DEFAULT_PARAGRAPH_SPACING 1
88 /* Global variables. */
90 /* The output file name. */
91 char *output_filename = NULL;
93 /* Name of the output file that the user elected to pass on the command line.
94 Such a name overrides any name found with the @setfilename command. */
95 char *command_output_filename = NULL;
97 /* Flags which control initial output string for xrefs. */
101 #define INITIAL_PARAGRAPH_SPACE 5000
102 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
104 /* The amount of indentation to add at the starts of paragraphs.
105 0 means don't change existing indentation at paragraph starts.
106 > 0 is amount to indent new paragraphs by.
107 < 0 means indent to column zero by removing indentation if necessary.
109 This is normally zero, but some people prefer paragraph starts to be
110 somewhat more indented than paragraph bodies. A pretty value for
112 int paragraph_start_indent = PARAGRAPH_START_INDENT;
114 /* Indentation that is pending insertion. We have this for hacking lines
115 which look blank, but contain whitespace. We want to treat those as
117 int pending_indent = 0;
119 /* The index in our internal command table of the currently
120 executing command. */
123 /* A search string which is used to find the first @setfilename. */
124 char setfilename_search[] =
126 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
128 /* Values for calling handle_variable_internal (). */
134 /* Flags controlling the operation of the program. */
136 /* Default is to remove output if there were errors. */
139 /* Default is to notify users of bad choices. */
140 int print_warnings = 1;
142 /* Number of errors that we tolerate on a given fileset. */
143 int max_error_level = 100;
145 /* The actual last inserted character. Note that this may be something
146 other than NEWLINE even if last_char_was_newline is 1. */
147 int last_inserted_character = 0;
149 /* Nonzero means that a newline character has already been
150 inserted, so close_paragraph () should insert one less. */
151 int line_already_broken = 0;
153 /* When nonzero we have finished an insertion (see end_insertion ()) and we
154 want to ignore false continued paragraph closings. */
155 int insertion_paragraph_closed = 0;
157 /* Nonzero means attempt to make all of the lines have fill_column width. */
158 int do_justification = 0;
160 typedef struct brace_element
162 struct brace_element *next;
163 COMMAND_FUNCTION *proc;
166 int in_fixed_width_font;
169 BRACE_ELEMENT *brace_stack = NULL;
171 extern void do_multitable (), end_multitable ();
173 void push_node_filename (), pop_node_filename ();
174 void remember_error ();
175 void convert_from_stream (), convert_from_file (), convert_from_loaded_file ();
176 void init_internals (), init_paragraph (), init_brace_stack ();
177 void init_insertion_stack (), init_indices ();
178 void init_tag_table (), write_tag_table (), write_tag_table_internal ();
179 void validate_file (), validate_other_references (), split_file ();
180 void free_node_references (), handle_variable ();
181 void handle_variable_internal ();
182 void normalize_node_name ();
183 void add_anchor_name ();
184 void free_node_node_references (), remember_node_node_reference ();
186 char **get_brace_args ();
189 static int end_of_sentence_p ();
190 static void isolate_nodename ();
192 void remember_brace (), remember_brace_1 ();
193 void pop_and_call_brace (), discard_braces ();
194 void add_word (), add_char (), insert (), flush_output ();
195 void insert_string ();
196 void close_paragraph ();
197 void ignore_blank_line ();
198 void do_flush_right_indentation (), discard_insertions ();
199 void start_paragraph (), indent ();
200 void inhibit_output_flushing (), uninhibit_output_flushing ();
201 int set_paragraph_indent ();
202 int self_delimiting (), search_forward ();
203 int multitable_item (), number_of_node ();
204 extern void add_link (), add_escaped_anchor_name ();
206 void me_execute_string_keep_state ();
207 void maybe_update_execution_strings ();
209 extern char *escape_string ();
210 extern void insert_html_tag ();
211 extern void sectioning_html ();
212 extern void add_link ();
214 #if defined (VA_FPRINTF) && __STDC__
215 /* Unfortunately we must use prototypes if we are to use <stdarg.h>. */
216 void add_word_args (char *, ...);
217 void execute_string (char *, ...);
219 void add_word_args ();
220 void execute_string ();
221 #endif /* no prototypes */
223 /* Error handling. */
225 /* Number of errors encountered. */
226 int errors_printed = 0;
228 /* Print the last error gotten from the file system. */
238 /* Print an error message, and return false. */
240 #if defined (VA_FPRINTF) && __STDC__
241 error (char *format, ...)
243 error (format, va_alist)
254 VA_START (ap, format);
256 VA_FPRINTF (stderr, format, ap);
258 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
259 #endif /* not VA_FPRINTF */
265 /* Just like error (), but print the line number as well. */
267 #if defined (VA_FPRINTF) && __STDC__
268 line_error (char *format, ...)
270 line_error (format, va_alist)
280 fprintf (stderr, "%s:%d: ", input_filename, line_number);
282 VA_START (ap, format);
284 VA_FPRINTF (stderr, format, ap);
286 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
287 #endif /* not VA_FPRINTF */
290 fprintf (stderr, ".\n");
294 #if defined (VA_FPRINTF) && __STDC__
295 warning (char *format, ...)
297 warning (format, va_alist)
308 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
310 VA_START (ap, format);
312 VA_FPRINTF (stderr, format, ap);
314 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
315 #endif /* not VA_FPRINTF */
318 fprintf (stderr, ".\n");
323 /* Remember that an error has been printed. If more than
324 max_error_level have been printed, then exit the program. */
329 if (max_error_level && (errors_printed > max_error_level))
331 fprintf (stderr, _("Too many errors! Gave up.\n"));
338 /* The other side of a malformed expression. */
342 line_error (_("Misplaced %c"), '}');
347 /* Display the version info of this invocation of Makeinfo. */
349 print_version_info ()
351 printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION);
354 /* If EXIT_VALUE is zero, print the full usage message to stdout.
355 Otherwise, just say to use --help for more info.
356 Then exit with EXIT_VALUE. */
362 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
365 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n\
367 Translate Texinfo source documentation to various other formats:\n\
368 Info files suitable for reading online with Emacs or standalone GNU Info\n\
369 (by default); plain text (with --no-headers); or HTML (with --html).\n\
372 --commands-in-node-names allow @ commands in node names.\n\
373 -D VAR define a variable, as with @set.\n\
374 -E, --macro-expand FILE output macro-expanded source to FILE.\n\
375 --error-limit=NUM quit after NUM errors (default %d).\n\
376 --fill-column=NUM break Info lines at NUM characters (default %d).\n\
377 --footnote-style=STYLE output footnotes according to STYLE:\n\
378 `separate' to place footnotes in their own node,\n\
379 `end' to place the footnotes at the end of the\n\
380 node in which they are defined (the default).\n\
381 --force preserve output even if errors.\n\
382 --help display this help and exit.\n\
383 --html output HTML rather than Info format;\n\
384 -I DIR append DIR to the @include search path.\n\
385 --ifhtml process @ifhtml and @html text even when not\n\
387 --ifinfo process @ifinfo text even when generating HTML.\n\
388 --iftex process @iftex and @tex text.\n\
389 implies --no-split.\n"),
390 progname, max_error_level, fill_column);
392 --no-headers suppress Info node separators and Node: lines and\n\
393 write to standard output without --output.\n\
394 --no-ifhtml do not process @ifhtml and @html text.\n\
395 --no-ifinfo do not process @ifinfo text.\n\
396 --no-iftex do not process @iftex and @tex text.\n\
397 --no-split suppress splitting of large Info output files or\n\
398 generation of one HTML file per node.\n\
399 --no-validate suppress node cross-reference validation.\n\
400 --no-warn suppress warnings (but not errors).\n\
401 --number-sections include chapter, section, etc. numbers in output.\n\
402 -o, --output=FILE output to FILE, ignoring any @setfilename.\n\
403 -P DIR prepend DIR to the @include search path.\n\
404 --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
405 if VAL is `none', do not indent;\n\
406 if VAL is `asis', preserve existing indentation.\n\
407 --reference-limit=NUM warn about at most NUM references (default %d).\n\
408 -U VAR undefine a variable, as with @clear.\n\
409 -v, --verbose explain what is being done.\n\
410 --version display version information and exit.\n\
412 paragraph_start_indent, reference_warning_limit);
416 The defaults for the @if... conditionals depend on the output format:\n\
417 if generating HTML, --ifhtml is on and the others are off;\n\
418 if generating Info or plain text, --ifinfo is on and the others are off.\n\
421 makeinfo foo.texi write Info to foo's @setfilename\n\
422 makeinfo --html foo.texi write HTML to foo's @setfilename\n\
423 makeinfo --no-headers -o - foo.texi write plain text to standard output\n\
424 makeinfo --number-sections foo.texi write Info with numbered sections\n\
425 makeinfo --no-split foo.texi write one Info file however big\n\
427 Email bug reports to bug-texinfo@gnu.org,\n\
428 general questions and discussion to help-texinfo@gnu.org."));
432 struct option long_options[] =
434 { "commands-in-node-names", 0, &expensive_validation, 1 },
435 { "error-limit", 1, 0, 'e' },
436 { "fill-column", 1, 0, 'f' },
437 { "footnote-style", 1, 0, 's' },
438 { "force", 0, &force, 1 },
439 { "help", 0, 0, 'h' },
440 { "html", 0, 0, 'w' },
441 { "ifhtml", 0, &process_html, 1 },
442 { "ifinfo", 0, &process_info, 1 },
443 { "iftex", 0, &process_tex, 1 },
444 { "macro-expand", 1, 0, 'E' },
445 { "no-headers", 0, &no_headers, 1 },
446 { "no-ifhtml", 0, &process_html, 0 },
447 { "no-ifinfo", 0, &process_info, 0 },
448 { "no-iftex", 0, &process_tex, 0 },
449 { "no-number-footnotes", 0, &number_footnotes, 0 },
450 { "no-number-sections", 0, &number_sections, 0 },
451 { "no-pointer-validate", 0, &validating, 0 },
452 { "no-split", 0, &splitting, 0 },
453 { "no-validate", 0, &validating, 0 },
454 { "no-warn", 0, &print_warnings, 0 },
455 { "number-footnotes", 0, &number_footnotes, 1 },
456 { "number-sections", 0, &number_sections, 1 },
457 { "output", 1, 0, 'o' },
458 { "paragraph-indent", 1, 0, 'p' },
459 { "reference-limit", 1, 0, 'r' },
460 { "verbose", 0, &verbose_mode, 1 },
461 { "version", 0, 0, 'V' },
465 /* For each file mentioned in the command line, process it, turning
466 Texinfo commands into wonderfully formatted output text. */
472 extern int errors_printed;
474 int reading_from_stdin = 0;
476 #ifdef HAVE_SETLOCALE
477 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
478 of the argument to @multicolumn. */
479 setlocale (LC_TIME, "");
480 setlocale (LC_MESSAGES, "");
481 setlocale (LC_CTYPE, "");
482 setlocale (LC_COLLATE, "");
485 /* Set the text message domain. */
486 bindtextdomain (PACKAGE, LOCALEDIR);
487 textdomain (PACKAGE);
489 /* Parse argument flags from the input line. */
490 while ((c = getopt_long (argc, argv, "D:e:E:f:hI:o:p:P:r:s:U:vV:w",
491 long_options, &ind)) != EOF)
493 if (c == 0 && long_options[ind].flag == 0)
494 c = long_options[ind].val;
500 /* User specified variable to set or clear. */
501 handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
504 case 'e': /* --error-limit */
505 if (sscanf (optarg, "%d", &max_error_level) != 1)
508 _("%s: %s arg must be numeric, not `%s'.\n"),
509 "--error-limit", progname, optarg);
514 case 'E': /* --macro-expand */
515 if (!macro_expansion_output_stream)
517 macro_expansion_filename = optarg;
518 macro_expansion_output_stream
519 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
520 if (!macro_expansion_output_stream)
521 error (_("Couldn't open macro expansion output `%s'"), optarg);
524 error (_("Cannot specify more than one macro expansion output"));
527 case 'f': /* --fill-column */
528 if (sscanf (optarg, "%d", &fill_column) != 1)
531 _("%s: %s arg must be numeric, not `%s'.\n"),
532 "--fill-column", progname, optarg);
537 case 'h': /* --help */
542 /* Append user-specified dir to include file path. */
543 if (!include_files_path)
544 include_files_path = xstrdup (".");
546 include_files_path = (char *)
547 xrealloc (include_files_path,
548 2 + strlen (include_files_path) + strlen (optarg));
549 strcat (include_files_path, PATH_SEP);
550 strcat (include_files_path, optarg);
553 case 'o': /* --output */
554 command_output_filename = xstrdup (optarg);
557 case 'p': /* --paragraph-indent */
558 if (set_paragraph_indent (optarg) < 0)
561 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
568 /* Prepend user-specified include dir to include path. */
569 if (!include_files_path)
571 include_files_path = xstrdup (optarg);
572 include_files_path = xrealloc (include_files_path,
573 strlen (include_files_path) + 3); /* 3 for ":.\0" */
574 strcat (strcat (include_files_path, PATH_SEP), ".");
578 char *tmp = xstrdup (include_files_path);
579 include_files_path = xrealloc (include_files_path,
580 strlen (include_files_path) + strlen (optarg) + 2); /* 2 for ":\0" */
581 strcpy (include_files_path, optarg);
582 strcat (include_files_path, ":");
583 strcat (include_files_path, tmp);
588 case 'r': /* --reference-limit */
589 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
592 _("%s: %s arg must be numeric, not `%s'.\n"),
593 "--reference-limit", progname, optarg);
598 case 's': /* --footnote-style */
599 if (set_footnote_style (optarg) < 0)
602 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
606 footnote_style_preset = 1;
613 case 'V': /* --version */
614 print_version_info ();
616 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
617 There is NO warranty. You may redistribute this software\n\
618 under the terms of the GNU General Public License.\n\
619 For more information about these matters, see the files named COPYING.\n"),
624 case 'w': /* --html */
628 splitting = 0; /* too complicated for now */
638 expensive_validation = 0;
642 /* Check to see if input is a file. If so, process that. */
643 if (!isatty (fileno (stdin)))
644 reading_from_stdin = 1;
647 fprintf (stderr, _("%s: missing file argument.\n"), progname);
654 if (html && splitting)
655 { /* --no-headers --no-split --html indicates confusion. */
657 "%s: --no-headers conflicts with --no-split for --html.\n",
662 /* --no-headers implies --no-split. */
665 /* If the user did not specify an output file, use stdout. */
666 if (!command_output_filename)
667 command_output_filename = xstrdup ("-");
671 print_version_info ();
673 /* Remaining arguments are file names of texinfo files.
674 Convert them, one by one. */
675 if (!reading_from_stdin)
677 while (optind != argc)
678 convert_from_file (argv[optind++]);
681 convert_from_stream (stdin, "stdin");
683 return errors_printed ? 2 : 0;
687 /* Hacking tokens and strings. */
689 /* Return the next token as a string pointer. We cons the string. */
696 /* If the first character to be read is self-delimiting, then that
697 is the command itself. */
698 character = curchar ();
699 if (self_delimiting (character))
703 if (character == '\n')
706 result = xstrdup (" ");
711 for (i = 0; ((input_text_offset != input_text_length)
712 && (character = curchar ())
713 && command_char (character));
714 i++, input_text_offset++);
715 result = xmalloc (i + 1);
716 memcpy (result, &input_text[input_text_offset - i], i);
721 /* Return nonzero if CHARACTER is self-delimiting. */
723 self_delimiting (character)
726 /* @; and @\ are not Texinfo commands, but they are listed here
727 anyway. I don't know why. --karl, 10aug96. */
728 return strchr ("~{|}`^\\@?=;:.-,*\'\" !\n\t", character) != NULL;
731 /* Clear whitespace from the front and end of string. */
736 int len = strlen (string);
742 for (x = 0; x < len; x++)
744 if (!cr_or_whitespace (string[x]))
746 strcpy (string, string + x);
750 len = strlen (string);
753 while (len > -1 && cr_or_whitespace (string[len]))
758 /* Bash STRING, replacing all whitespace with just one space. */
760 fix_whitespace (string)
763 char *temp = xmalloc (strlen (string) + 1);
764 int string_index = 0;
768 canon_white (string);
770 while (string[string_index])
772 c = temp[temp_index++] = string[string_index++];
774 if (c == ' ' || c == '\n' || c == '\t')
776 temp[temp_index - 1] = ' ';
777 while ((c = string[string_index]) && (c == ' ' ||
783 temp[temp_index] = 0;
784 strcpy (string, temp);
788 /* Discard text until the desired string is found. The string is
789 included in the discarded text. */
791 discard_until (string)
794 int temp = search_forward (string, input_text_offset);
796 int tt = (temp < 0) ? input_text_length : temp + strlen (string);
797 int from = input_text_offset;
799 /* Find out what line we are on. */
801 if (input_text[from++] == '\n')
806 input_text_offset = input_text_length - strlen (string);
808 if (strcmp (string, "\n") != 0)
810 line_error (_("Expected `%s'"), string);
815 input_text_offset = temp;
817 input_text_offset += strlen (string);
820 /* Read characters from the file until we are at MATCH.
821 Place the characters read into STRING.
822 On exit input_text_offset is after the match string.
823 Return the offset where the string starts. */
825 get_until (match, string)
826 char *match, **string;
828 int len, current_point, x, new_point, tem;
830 current_point = x = input_text_offset;
831 new_point = search_forward (match, input_text_offset);
834 new_point = input_text_length;
835 len = new_point - current_point;
837 /* Keep track of which line number we are at. */
838 tem = new_point + (strlen (match) - 1);
840 if (input_text[x++] == '\n')
843 *string = xmalloc (len + 1);
845 memcpy (*string, &input_text[current_point], len);
848 /* Now leave input_text_offset in a consistent state. */
849 input_text_offset = tem;
851 if (input_text_offset > input_text_length)
852 input_text_offset = input_text_length;
857 /* Replace input_text[FROM .. TO] with its expansion. */
859 replace_with_expansion (from, to)
863 unsigned xp_len, new_len;
864 char *old_input = input_text;
865 unsigned raw_len = *to - from;
868 /* The rest of the code here moves large buffers, so let's
869 not waste time if the input cannot possibly expand
870 into anything. Unfortunately, we cannot avoid expansion
871 when we see things like @code etc., even if they only
872 asked for expansion of macros, since any Texinfo command
873 can be potentially redefined with a macro. */
874 if (only_macro_expansion &&
875 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
878 /* Get original string from input. */
879 str = xmalloc (raw_len + 1);
880 memcpy (str, input_text + from, raw_len);
883 /* We are going to relocate input_text, so we had better output
884 pending portion of input_text now, before the pointer changes. */
885 if (macro_expansion_output_stream && !executing_string
886 && !me_inhibit_expansion)
887 append_to_expansion_output (from);
890 xp = expansion (str, 0);
891 xp_len = strlen (xp);
894 /* Plunk the expansion into the middle of `input_text' --
895 which is terminated by a newline, not a null. Avoid
896 expensive move of the rest of the input if the expansion
897 has the same length as the original string. */
898 if (xp_len != raw_len)
900 new_len = from + xp_len + input_text_length - *to + 1;
901 if (executing_string)
902 { /* If we are in execute_string, we might need to update
903 the relevant element in the execution_strings[] array,
904 since it could have to be relocated from under our
905 feet. (input_text is reallocated here as well, if needed.) */
906 maybe_update_execution_strings (&input_text, new_len);
908 else if (new_len > input_text_length + 1)
909 /* Don't bother to realloc if we have enough space. */
910 input_text = xrealloc (input_text, new_len);
912 memmove (input_text + from + xp_len,
913 input_text + *to, input_text_length - *to + 1);
915 *to += xp_len - raw_len;
916 /* Since we change input_text_length here, the comparison above
917 isn't really valid, but it seems the worst that might happen is
918 an extra xrealloc or two, so let's not worry. */
919 input_text_length += xp_len - raw_len;
921 memcpy (input_text + from, xp, xp_len);
924 /* Synchronize the macro-expansion pointers with our new input_text. */
925 if (input_text != old_input)
926 forget_itext (old_input);
927 if (macro_expansion_output_stream && !executing_string)
928 remember_itext (input_text, from);
931 /* Read characters from the file until we are at MATCH or end of line.
932 Place the characters read into STRING. If EXPAND is nonzero,
933 expand the text before looking for MATCH for those cases where
934 MATCH might be produced by some macro. */
936 get_until_in_line (expand, match, string)
938 char *match, **string;
940 int real_bottom = input_text_length;
941 int limit = search_forward ("\n", input_text_offset);
943 limit = input_text_length;
945 /* Replace input_text[input_text_offset .. limit-1] with its expansion.
946 This allows the node names and menu entries themselves to be
947 constructed via a macro, as in:
952 @node @foo{A,B}, next, prev, top
954 Otherwise, the `,' separating the macro args A and B is taken as
955 the node argument separator, so the node name is `@foo{A'. This
956 expansion is only necessary on the first call, since we expand the
960 replace_with_expansion (input_text_offset, &limit);
963 real_bottom = input_text_length;
964 input_text_length = limit;
965 get_until (match, string);
966 input_text_length = real_bottom;
970 get_rest_of_line (expand, string)
978 /* Don't expand non-macros in input, since we want them
979 intact in the macro-expanded output. */
980 only_macro_expansion++;
981 get_until_in_line (1, "\n", &tem);
982 only_macro_expansion--;
983 *string = expansion (tem, 0);
987 get_until_in_line (0, "\n", string);
989 canon_white (*string);
991 if (curchar () == '\n') /* as opposed to the end of the file... */
998 /* Backup the input pointer to the previous character, keeping track
999 of the current line number. */
1001 backup_input_pointer ()
1003 if (input_text_offset)
1005 input_text_offset--;
1006 if (curchar () == '\n')
1011 /* Read characters from the file until we are at MATCH or closing brace.
1012 Place the characters read into STRING. */
1014 get_until_in_braces (match, string)
1015 char *match, **string;
1019 int match_len = strlen (match);
1021 for (i = input_text_offset; i < input_text_length; i++)
1023 if (input_text[i] == '{')
1025 else if (input_text[i] == '}')
1027 else if (input_text[i] == '\n')
1031 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1035 match_len = i - input_text_offset;
1036 temp = xmalloc (2 + match_len);
1037 memcpy (temp, input_text + input_text_offset, match_len);
1038 temp[match_len] = 0;
1039 input_text_offset = i;
1043 /* Converting a file. */
1045 /* Convert the file named by NAME. The output is saved on the file
1046 named as the argument to the @setfilename command. */
1047 static char *suffixes[] = {
1048 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1049 have "texinfo.txi" and "texinfo.tex" in the same directory, the
1050 former is used rather than the latter, due to file name truncation. */
1060 initialize_conversion ()
1067 /* This is used for splitting the output file and for doing section
1068 headings. It was previously initialized in `init_paragraph', but its
1069 use there loses with the `init_paragraph' calls done by the
1070 multitable code; the tag indices get reset to zero. */
1071 output_position = 0;
1074 typedef struct generic_list {
1075 struct generic_list *next;
1078 /* Reverse the chain of structures in LIST. Output the new head
1079 of the chain. You should always assign the output value of this
1080 function to something, or you will lose the chain. */
1086 GENERIC_LIST *prev = NULL;
1098 /* We read in multiples of 4k, simply because it is a typical pipe size
1100 #define READ_BUFFER_GROWTH (4 * 4096)
1102 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1103 source of the stream is named NAME. */
1105 convert_from_stream (stream, name)
1109 char *buffer = NULL;
1110 int buffer_offset = 0, buffer_size = 0;
1112 initialize_conversion ();
1114 /* Read until the end of the stream. This isn't strictly correct, since
1115 the texinfo input may end before the stream ends, but it is a quick
1116 working hueristic. */
1117 while (!feof (stream))
1121 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1123 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1125 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1133 buffer_offset += count;
1138 /* Set the globals to the new file. */
1139 input_text = buffer;
1140 input_text_length = buffer_offset;
1141 input_filename = xstrdup (name);
1142 node_filename = xstrdup (name);
1143 input_text_offset = 0;
1146 /* Not strictly necessary. This magic prevents read_token () from doing
1147 extra unnecessary work each time it is called (that is a lot of times).
1148 The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1149 input_text[input_text_length] = '\n';
1151 convert_from_loaded_file (name);
1155 convert_from_file (name)
1159 char *filename = xmalloc (strlen (name) + 50);
1161 initialize_conversion ();
1163 /* Try to load the file specified by NAME, concatenated with our
1164 various suffixes. Prefer files like `makeinfo.texi' to
1166 for (i = 0; suffixes[i]; i++)
1168 strcpy (filename, name);
1169 strcat (filename, suffixes[i]);
1171 if (find_and_load (filename))
1174 if (!suffixes[i][0] && strrchr (filename, '.'))
1176 fs_error (filename);
1189 input_filename = filename;
1191 convert_from_loaded_file (name);
1195 convert_from_loaded_file (name)
1198 char *real_output_filename = NULL;
1200 remember_itext (input_text, 0);
1202 input_text_offset = 0;
1204 /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1206 if (looking_at ("\\input"))
1207 discard_until ("\n");
1209 /* Search this file looking for the special string which starts conversion.
1210 Once found, we may truly begin. */
1211 while (input_text_offset >= 0)
1214 search_forward (setfilename_search, input_text_offset);
1216 if (input_text_offset == 0
1217 || (input_text_offset > 0
1218 && input_text[input_text_offset -1] == '\n'))
1220 else if (input_text_offset > 0)
1221 input_text_offset++;
1224 if (input_text_offset < 0)
1226 if (!command_output_filename)
1228 #if defined (REQUIRE_SETFILENAME)
1229 error (_("No `%s' found in `%s'"), setfilename_search, name);
1232 command_output_filename = output_name_from_input_name (name);
1233 #endif /* !REQUIRE_SETFILENAME */
1237 int i, end_of_first_line;
1239 /* Find the end of the first line in the file. */
1240 for (i = 0; i < input_text_length - 1; i++)
1241 if (input_text[i] == '\n')
1244 end_of_first_line = i + 1;
1246 for (i = 0; i < end_of_first_line; i++)
1248 if ((input_text[i] == '\\') &&
1249 (strncmp (input_text + i + 1, "input", 5) == 0))
1251 input_text_offset = i;
1258 input_text_offset += strlen (setfilename_search);
1260 if (!command_output_filename)
1262 get_until ("\n", &output_filename); /* read rest of line */
1264 { /* Change any extension to .html. */
1265 char *html_name, *directory_part, *basename_part, *temp;
1267 canon_white (output_filename);
1268 directory_part = pathname_part (output_filename);
1269 basename_part = filename_part (output_filename);
1271 /* Zap any existing extension. */
1272 temp = strrchr (basename_part, '.');
1276 /* Construct new filename. */
1277 html_name = xmalloc (strlen (directory_part)
1278 + strlen (basename_part) + 6);
1279 strcpy (html_name, directory_part);
1280 strcat (html_name, basename_part);
1281 strcat (html_name, ".html");
1283 /* Replace name from @setfilename with the html name. */
1284 free (output_filename);
1285 output_filename = html_name;
1290 if (input_text_offset != -1)
1291 discard_until ("\n");
1293 input_text_offset = 0;
1295 real_output_filename = output_filename = command_output_filename;
1296 command_output_filename = NULL;
1299 canon_white (output_filename);
1301 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1303 if (macro_expansion_filename
1304 && strcmp (macro_expansion_filename, "-") == 0)
1306 fprintf (stderr, _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1308 macro_expansion_output_stream = NULL;
1310 real_output_filename = xstrdup (real_output_filename);
1311 output_stream = stdout;
1312 splitting = 0; /* Cannot split when writing to stdout. */
1316 if (!real_output_filename)
1317 real_output_filename = expand_filename (output_filename, name);
1319 real_output_filename = xstrdup (real_output_filename);
1321 output_stream = fopen (real_output_filename, "w");
1324 set_current_output_filename (real_output_filename);
1327 printf (_("Making %s file `%s' from `%s'.\n"),
1328 no_headers ? "text" : (html ? "HTML" : "info"),
1329 output_filename, input_filename);
1331 if (output_stream == NULL)
1333 fs_error (real_output_filename);
1337 /* Make the displayable filename from output_filename. Only the base
1338 portion of the filename need be displayed. */
1339 if (output_stream != stdout)
1340 pretty_output_filename = filename_part (output_filename);
1342 pretty_output_filename = xstrdup ("stdout");
1344 /* For this file only, count the number of newlines from the top of
1345 the file to here. This way, we keep track of line numbers for
1346 error reporting. Line_number starts at 1, since the user isn't
1351 while (temp != input_text_offset)
1352 if (input_text[temp++] == '\n')
1356 /* html fixxme: should output this as trailer on first page. */
1357 if (!no_headers && !html)
1358 add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
1359 output_filename, VERSION, input_filename);
1365 discard_insertions (0);
1367 flush_file_stack ();
1369 if (macro_expansion_output_stream)
1371 fclose (macro_expansion_output_stream);
1372 if (errors_printed && !force
1373 && strcmp (macro_expansion_filename, "-") != 0
1374 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1375 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1377 fprintf (stderr, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1378 progname, macro_expansion_filename);
1379 if (unlink (macro_expansion_filename) < 0)
1380 perror (macro_expansion_filename);
1386 output_pending_notes ();
1389 tag_table = (TAG_ENTRY *) reverse_list (tag_table);
1390 if (!no_headers && !html)
1397 add_word ("</body></html>\n");
1401 if (output_stream != stdout)
1402 fclose (output_stream);
1404 /* If validating, then validate the entire file right now. */
1406 validate_file (tag_table);
1408 /* If we need to output the table of contents, do it now. */
1409 if (contents_filename || shortcontents_filename)
1412 if (splitting && !html && (!errors_printed || force))
1413 split_file (real_output_filename, 0);
1414 else if (errors_printed
1416 && strcmp (real_output_filename, "-") != 0
1417 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1418 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1419 { /* If there were errors, and no --force, remove the output. */
1420 fprintf (stderr, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1421 progname, real_output_filename);
1422 if (unlink (real_output_filename) < 0)
1423 perror (real_output_filename);
1426 free (real_output_filename);
1430 free_and_clear (pointer)
1440 /* Initialize some state. */
1444 free_and_clear (&output_filename);
1445 free_and_clear (&command);
1446 free_and_clear (&input_filename);
1447 free_node_references ();
1448 free_node_node_references ();
1450 init_insertion_stack ();
1451 init_brace_stack ();
1452 current_node = NULL; /* sometimes already freed */
1457 non_top_node_seen = 0;
1464 free_and_clear (&output_paragraph);
1465 output_paragraph = xmalloc (paragraph_buffer_len);
1466 output_paragraph[0] = 0;
1467 output_paragraph_offset = 0;
1469 paragraph_is_open = 0;
1474 /* This is called from `reader_loop' when we are at the * beginning a
1478 handle_menu_entry ()
1482 /* Ugh, glean_node_from_menu wants to read the * itself. */
1483 input_text_offset--;
1485 /* Find node name in menu entry and save it in references list for
1486 later validation. Use followed_reference type for detailmenu
1487 references since we don't want to use them for default node pointers. */
1488 tem = glean_node_from_menu (1, in_detailmenu
1489 ? followed_reference : menu_reference);
1492 { /* Start a menu item with the cleaned-up line. Put an anchor
1493 around the start text (before `:' or the node name). */
1496 discard_until ("* ");
1498 /* The line number was already incremented in reader_loop when we
1499 saw the newline, and discard_until has now incremented again. */
1502 if (had_menu_commentary)
1504 add_word ("<ul>\n");
1505 had_menu_commentary = 0;
1508 else if (!in_paragraph && !paragraph_is_open)
1520 add_word ("<li><a href=\"");
1521 string = expansion (tem, 0);
1522 add_anchor_name (string, 1);
1526 /* The menu item may use macros, so expand them now. */
1527 only_macro_expansion++;
1528 get_until_in_line (1, ":", &string);
1529 only_macro_expansion--;
1530 execute_string ("%s", string); /* get escaping done */
1535 if (looking_at ("::"))
1536 discard_until (":");
1538 { /* discard the node name */
1539 get_until_in_line (0, ".", &string);
1542 input_text_offset++; /* discard the second colon or the period */
1546 { /* For Info output, we can just use the input and the main case in
1547 reader_loop where we output what comes in. Just move off the *
1548 so the next time through reader_loop we don't end up back here. */
1550 input_text_offset += 2; /* undo the pointer back-up above. */
1557 /* Find the command corresponding to STRING. If the command is found,
1558 return a pointer to the data structure. Otherwise return -1. */
1560 get_command_entry (string)
1565 for (i = 0; command_table[i].name; i++)
1566 if (strcmp (command_table[i].name, string) == 0)
1567 return &command_table[i];
1569 /* This command is not in our predefined command table. Perhaps
1570 it is a user defined command. */
1571 for (i = 0; i < user_command_array_len; i++)
1572 if (user_command_array[i] &&
1573 (strcmp (user_command_array[i]->name, string) == 0))
1574 return user_command_array[i];
1576 /* We never heard of this command. */
1577 return (COMMAND *) -1;
1580 /* input_text_offset is right at the command prefix character.
1581 Read the next token to determine what to do. Return zero
1582 if there's no known command or macro after the prefix character. */
1587 int old_text_offset = input_text_offset++;
1589 free_and_clear (&command);
1590 command = read_token ();
1592 /* Check to see if this command is a macro. If so, execute it here. */
1596 def = find_macro (command);
1600 /* We disallow recursive use of a macro call. Inhibit the expansion
1601 of this macro during the life of its execution. */
1602 if (!(def->flags & ME_RECURSE))
1605 execute_macro (def);
1607 if (!(def->flags & ME_RECURSE))
1614 if (only_macro_expansion)
1616 /* Back up to the place where we were called, so the
1617 caller will have a chance to process this non-macro. */
1618 input_text_offset = old_text_offset;
1622 /* Perform alias expansion */
1623 command = alias_expand (command);
1625 if (enclosure_command (command))
1627 remember_brace (enclosure_expand);
1628 enclosure_expand (START, output_paragraph_offset, 0);
1632 entry = get_command_entry (command);
1633 if (entry == (COMMAND *)-1)
1635 line_error (_("Unknown command `%s'"), command);
1639 if (entry->argument_in_braces == BRACE_ARGS)
1640 remember_brace (entry->proc);
1641 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
1643 if (curchar () == '{')
1644 remember_brace (entry->proc);
1646 { /* No braces, so arg is next char. */
1648 int saved_offset = output_paragraph_offset;
1649 (*(entry->proc)) (START, output_paragraph_offset, 0);
1651 /* Possibilities left for the next character: @ (error), }
1652 (error), whitespace (skip) anything else (normal char). */
1657 line_error (_("Use braces to give a command as an argument to @%s"),
1663 /* Our caller will give the error message, because this }
1664 won't match anything. */
1669 input_text_offset++;
1670 (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
1675 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
1677 (*(entry->proc)) (START, output_paragraph_offset, 0);
1681 /* Okay, we are ready to start the conversion. Call the reader on
1682 some text, and fill the text as it is output. Handle commands by
1683 remembering things like open braces and the current file position on a
1684 stack, and when the corresponding close brace is found, you can call
1685 the function with the proper arguments. Although the filling isn't
1686 necessary for HTML, it should do no harm. */
1696 if (input_text_offset >= input_text_length)
1699 character = curchar ();
1701 /* If only_macro_expansion, only handle macros and leave
1702 everything else intact. */
1703 if (!only_macro_expansion && !in_fixed_width_font
1704 && (character == '\'' || character == '`')
1705 && input_text[input_text_offset + 1] == character)
1707 input_text_offset++;
1708 character = '"'; /* html fixxme */
1711 /* Convert --- to --. */
1712 if (!only_macro_expansion && character == '-')
1715 if (dash_count == 2 && !in_fixed_width_font)
1717 input_text_offset++;
1721 else if (dash_count > 0)
1724 /* If this is a whitespace character, then check to see if the line
1725 is blank. If so, advance to the carriage return. */
1726 if (!only_macro_expansion && whitespace (character))
1728 int i = input_text_offset + 1;
1730 while (i < input_text_length && whitespace (input_text[i]))
1733 if (i == input_text_length || input_text[i] == '\n')
1735 if (i == input_text_length)
1738 input_text_offset = i;
1739 character = curchar ();
1743 if (character == '\n')
1748 case '*': /* perhaps we are at a menu */
1749 /* We used to check for this in the \n case but an @c in a
1750 menu swallows its newline, so check here instead. */
1751 if (!only_macro_expansion && in_menu
1752 && input_text_offset + 1 < input_text_length
1753 && input_text[input_text_offset-1] == '\n')
1754 handle_menu_entry ();
1756 { /* Duplicate code from below, but not worth twisting the
1757 fallthroughs to get down there. */
1758 add_char (character);
1759 input_text_offset++;
1763 /* Escapes for HTML unless we're outputting raw HTML. Do
1764 this always, even if SGML rules don't require it since
1765 that's easier and safer for non-conforming browsers. */
1767 if (html && escape_html)
1770 add_char (character);
1771 input_text_offset++;
1775 if (html && escape_html)
1778 add_char (character);
1779 input_text_offset++;
1783 if (html && escape_html)
1786 add_char (character);
1787 input_text_offset++;
1790 case COMMAND_PREFIX: /* @ */
1791 if (read_command () || !only_macro_expansion)
1794 /* FALLTHROUGH (usually) */
1796 /* Special case. We're not supposed to see this character by itself.
1797 If we do, it means there is a syntax error in the input text.
1798 Report the error here, but remember this brace on the stack so
1799 we can ignore its partner. */
1800 if (!only_macro_expansion)
1802 line_error (_("Misplaced %c"), '{');
1803 remember_brace (misplaced_brace);
1804 /* remember_brace advances input_text_offset. */
1808 /* FALLTHROUGH (usually) */
1810 if (!only_macro_expansion)
1812 pop_and_call_brace ();
1813 input_text_offset++;
1817 /* FALLTHROUGH (usually) */
1819 add_char (character);
1820 input_text_offset++;
1823 if (macro_expansion_output_stream && !only_macro_expansion)
1824 maybe_write_itext (input_text, input_text_offset);
1834 remember_brace (proc)
1835 COMMAND_FUNCTION *proc;
1837 if (curchar () != '{')
1838 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command);
1840 input_text_offset++;
1841 remember_brace_1 (proc, output_paragraph_offset);
1844 /* Remember the current output position here. Save PROC
1845 along with it so you can call it later. */
1847 remember_brace_1 (proc, position)
1848 COMMAND_FUNCTION *proc;
1851 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
1852 new->next = brace_stack;
1854 new->command = xstrdup (command);
1855 new->pos = position;
1856 new->line = line_number;
1857 new->in_fixed_width_font = in_fixed_width_font;
1861 /* Pop the top of the brace stack, and call the associated function
1862 with the args END and POS. */
1864 pop_and_call_brace ()
1866 if (brace_stack == NULL)
1868 line_error (_("Unmatched }"));
1873 BRACE_ELEMENT *temp;
1875 int pos = brace_stack->pos;
1876 COMMAND_FUNCTION *proc = brace_stack->proc;
1877 in_fixed_width_font = brace_stack->in_fixed_width_font;
1879 /* Reset current command, so the proc can know who it is. This is
1880 used in cm_accent. */
1881 command = brace_stack->command;
1883 temp = brace_stack->next;
1887 (*proc) (END, pos, output_paragraph_offset);
1891 /* Shift all of the markers in `brace_stack' by AMOUNT. */
1893 adjust_braces_following (here, amount)
1896 BRACE_ELEMENT *stack = brace_stack;
1900 if (stack->pos >= here)
1901 stack->pos += amount;
1902 stack = stack->next;
1906 /* Return the string which invokes PROC; a pointer to a function.
1907 Always returns the first function in the command table if more than
1908 one matches PROC. */
1910 find_proc_name (proc)
1911 COMMAND_FUNCTION *proc;
1915 for (i = 0; command_table[i].name; i++)
1916 if (proc == command_table[i].proc)
1917 return command_table[i].name;
1918 return _("NO_NAME!");
1921 /* You call discard_braces () when you shouldn't have any braces on the stack.
1922 I used to think that this happens for commands that don't take arguments
1923 in braces, but that was wrong because of things like @code{foo @@}. So now
1924 I only detect it at the beginning of nodes. */
1933 if (brace_stack->proc != misplaced_brace)
1936 int temp_line_number = line_number;
1938 line_number = brace_stack->line;
1939 proc_name = find_proc_name (brace_stack->proc);
1940 line_error (_("%c%s missing close brace"), COMMAND_PREFIX, proc_name);
1941 line_number = temp_line_number;
1942 pop_and_call_brace ();
1946 BRACE_ELEMENT *temp;
1947 temp = brace_stack->next;
1955 get_char_len (character)
1958 /* Return the printed length of the character. */
1964 len = (output_column + 8) & 0xf7;
1965 if (len > fill_column)
1966 len = fill_column - output_column;
1968 len = len - output_column;
1972 len = fill_column - output_column;
1976 /* ASCII control characters appear as two characters in the output
1977 (e.g., ^A). But characters with the high bit set are just one
1978 on suitable terminals, so don't count them as two for line
1979 breaking purposes. */
1980 if (0 <= character && character < ' ')
1989 #if defined (VA_FPRINTF) && __STDC__
1990 add_word_args (char *format, ...)
1992 add_word_args (format, va_alist)
1997 char buffer[2000]; /* xx no fixed limits */
2002 VA_START (ap, format);
2004 VA_SPRINTF (buffer, format, ap);
2006 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2007 #endif /* not VA_SPRINTF */
2012 /* Add STRING to output_paragraph. */
2018 add_char (*string++);
2021 /* Add the character to the current paragraph. If filling_enabled is
2022 nonzero, then do filling as well. */
2024 add_char (character)
2027 /* If we are avoiding outputting headers, and we are currently
2028 in a menu, then simply return. But if we're only expanding macros,
2029 then we're being called from glean_node_from_menu to try to
2030 remember a menu reference, and we need that so we can do defaulting. */
2031 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2034 /* If we are adding a character now, then we don't have to
2035 ignore close_paragraph () calls any more. */
2036 if (must_start_paragraph && character != '\n')
2038 must_start_paragraph = 0;
2039 line_already_broken = 0; /* The line is no longer broken. */
2040 if (current_indent > output_column)
2042 indent (current_indent - output_column);
2043 output_column = current_indent;
2047 if (non_splitting_words && strchr (" \t\n", character))
2050 { /* Seems cleaner to use than an 8-bit char. */
2055 character = META (' '); /* unmeta-d in flush_output */
2058 insertion_paragraph_closed = 0;
2063 if (!filling_enabled && ! (html && (in_menu || in_detailmenu)))
2067 if (force_flush_right)
2070 /* Hack to force single blank lines out in this mode. */
2076 if (!no_indent && paragraph_is_open)
2077 indent (output_column = current_indent);
2080 else if (end_of_sentence_p ())
2081 /* CHARACTER is newline, and filling is enabled. */
2085 last_inserted_character = character;
2088 if (last_char_was_newline)
2091 last_char_was_newline++;
2097 last_char_was_newline = 1;
2106 default: /* not at newline */
2108 int len = get_char_len (character);
2109 int suppress_insert = 0;
2111 if ((character == ' ') && (last_char_was_newline))
2113 if (!paragraph_is_open)
2120 if (!paragraph_is_open)
2123 /* If the paragraph is supposed to be indented a certain
2124 way, then discard all of the pending whitespace.
2125 Otherwise, we let the whitespace stay. */
2126 if (!paragraph_start_indent)
2127 indent (pending_indent);
2130 /* This horrible kludge of checking for a < prevents <p>
2131 from being inserted when we already have html markup
2132 starting a paragraph, as with <ul> and <h1> and the like. */
2133 if (html && escape_html && character != '<'
2134 && (!in_fixed_width_font || in_menu || in_detailmenu))
2136 insert_string ("<p>");
2138 adjust_braces_following (0, 3); /* adjust for <p> */
2142 output_column += len;
2143 if (output_column > fill_column)
2145 if (filling_enabled && !html)
2147 int temp = output_paragraph_offset;
2148 while (--temp > 0 && output_paragraph[temp] != '\n')
2150 /* If we have found a space, we have the place to break
2152 if (output_paragraph[temp] == ' ')
2154 /* Remove trailing whitespace from output. */
2155 while (temp && whitespace (output_paragraph[temp - 1]))
2158 /* If we went back all the way to the newline of the
2159 preceding line, it probably means that the word we
2160 are adding is itself wider than the space that the
2161 indentation and the fill_column let us use. In
2162 that case, do NOT insert another newline, since it
2163 won't help. Just indent to current_indent and
2164 leave it alone, since that's the most we can do. */
2165 if (temp && output_paragraph[temp - 1] != '\n')
2166 output_paragraph[temp++] = '\n';
2168 /* We have correctly broken the line where we want
2169 to. What we don't want is spaces following where
2170 we have decided to break the line. We get rid of
2177 if (t1 == output_paragraph_offset)
2179 if (whitespace (character))
2180 suppress_insert = 1;
2183 if (!whitespace (output_paragraph[t1]))
2189 adjust_braces_following (temp, (- (t1 - temp)));
2190 strncpy ((char *) &output_paragraph[temp],
2191 (char *) &output_paragraph[t1],
2192 (output_paragraph_offset - t1));
2193 output_paragraph_offset -= (t1 - temp);
2197 /* Filled, but now indent if that is right. */
2198 if (indented_fill && current_indent > 0)
2200 int buffer_len = ((output_paragraph_offset - temp)
2202 char *temp_buffer = xmalloc (buffer_len);
2203 int indentation = 0;
2205 /* We have to shift any markers that are in
2206 front of the wrap point. */
2207 adjust_braces_following (temp, current_indent);
2209 while (current_indent > 0 &&
2210 indentation != current_indent)
2211 temp_buffer[indentation++] = ' ';
2213 memcpy ((char *) &temp_buffer[current_indent],
2214 (char *) &output_paragraph[temp],
2215 buffer_len - current_indent);
2217 if (output_paragraph_offset + buffer_len
2218 >= paragraph_buffer_len)
2220 unsigned char *tt = xrealloc
2222 (paragraph_buffer_len += buffer_len));
2223 output_paragraph = tt;
2225 memcpy ((char *) &output_paragraph[temp],
2226 temp_buffer, buffer_len);
2227 output_paragraph_offset += current_indent;
2231 while (temp < output_paragraph_offset)
2233 get_char_len (output_paragraph[temp++]);
2234 output_column += len;
2241 if (!suppress_insert)
2244 last_inserted_character = character;
2246 last_char_was_newline = 0;
2247 line_already_broken = 0;
2252 /* Add a character and store its position in meta_char_pos. */
2254 add_meta_char (character)
2257 meta_char_pos = output_paragraph_offset;
2258 add_char (character);
2261 /* Insert CHARACTER into `output_paragraph'. */
2266 /* This is sad, but it seems desirable to not force any particular
2267 order on the front matter commands. This way, the document can do
2268 @settitle, @documentlanguage, etc, in any order and with any
2269 omissions, and we'll still output the html <head> `just in time'. */
2270 if (!executing_string && html && !html_output_head_p)
2271 html_output_head ();
2273 output_paragraph[output_paragraph_offset++] = character;
2274 if (output_paragraph_offset == paragraph_buffer_len)
2277 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2281 /* Insert the null-terminated string STRING into `output_paragraph'. */
2283 insert_string (string)
2291 /* Sentences might have these characters after the period (or whatever). */
2292 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2295 /* Return true if at an end-of-sentence character, possibly followed by
2296 post-sentence punctuation to ignore. */
2298 end_of_sentence_p ()
2300 int loc = output_paragraph_offset - 1;
2302 /* If nothing has been output, don't check output_paragraph[-1]. */
2306 /* A post-sentence character that is at meta_char_pos is not really
2307 a post-sentence character; it was produced by a markup such as
2308 @samp. We don't want the period inside @samp to be treated as a
2311 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
2313 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
2317 /* Remove upto COUNT characters of whitespace from the
2318 the current output line. If COUNT is less than zero,
2319 then remove until none left. */
2321 kill_self_indent (count)
2324 /* Handle infinite case first. */
2328 while (output_paragraph_offset)
2330 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2331 output_paragraph_offset--;
2338 while (output_paragraph_offset && count--)
2339 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2340 output_paragraph_offset--;
2346 /* Nonzero means do not honor calls to flush_output (). */
2347 static int flushing_ignored = 0;
2349 /* Prevent calls to flush_output () from having any effect. */
2351 inhibit_output_flushing ()
2356 /* Allow calls to flush_output () to write the paragraph data. */
2358 uninhibit_output_flushing ()
2368 if (!output_paragraph_offset || flushing_ignored)
2371 for (i = 0; i < output_paragraph_offset; i++)
2373 /* If we turned on the 8th bit for a space inside @w, turn it
2374 back off for output. This might be problematic, since the
2375 0x80 character may be used in 8-bit character sets. Sigh.
2376 In any case, don't do this for HTML, since the nbsp character
2377 is valid input and must be passed along to the browser. */
2378 if (!html && (output_paragraph[i] & meta_character_bit))
2380 int temp = UNMETA (output_paragraph[i]);
2382 output_paragraph[i] &= 0x7f;
2386 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2388 output_position += output_paragraph_offset;
2389 output_paragraph_offset = 0;
2393 /* How to close a paragraph controlling the number of lines between
2394 this one and the last one. */
2396 /* Paragraph spacing is controlled by this variable. It is the number of
2397 blank lines that you wish to appear between paragraphs. A value of
2398 1 creates a single blank line between paragraphs. */
2399 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2402 close_paragraph_with_lines (lines)
2405 int old_spacing = paragraph_spacing;
2406 paragraph_spacing = lines;
2408 paragraph_spacing = old_spacing;
2411 /* Close the current paragraph, leaving no blank lines between them. */
2413 close_single_paragraph ()
2415 close_paragraph_with_lines (0);
2418 /* Close a paragraph after an insertion has ended. */
2420 close_insertion_paragraph ()
2422 if (!insertion_paragraph_closed)
2424 /* Close the current paragraph, breaking the line. */
2425 close_single_paragraph ();
2427 /* Start a new paragraph, with the correct indentation for the now
2428 current insertion level (one above the one that we are ending). */
2431 /* Tell `close_paragraph' that the previous line has already been
2432 broken, so it should insert one less newline. */
2433 line_already_broken = 1;
2435 /* Tell functions such as `add_char' we've already found a newline. */
2436 ignore_blank_line ();
2440 /* If the insertion paragraph is closed already, then we are seeing
2441 two `@end' commands in a row. Note that the first one we saw was
2442 handled in the first part of this if-then-else clause, and at that
2443 time `start_paragraph' was called, partially to handle the proper
2444 indentation of the current line. However, the indentation level
2445 may have just changed again, so we may have to outdent the current
2446 line to the new indentation level. */
2447 if (current_indent < output_column)
2448 kill_self_indent (output_column - current_indent);
2451 insertion_paragraph_closed = 1;
2454 /* Close the currently open paragraph. */
2460 /* The insertion paragraph is no longer closed. */
2461 insertion_paragraph_closed = 0;
2463 if (paragraph_is_open && !must_start_paragraph)
2467 tindex = output_paragraph_offset;
2469 /* Back up to last non-newline/space character, forcing all such
2470 subsequent characters to be newlines. This isn't strictly
2471 necessary, but a couple of functions use the presence of a newline
2472 to make decisions. */
2473 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
2475 c = output_paragraph[tindex];
2477 if (c == ' '|| c == '\n')
2478 output_paragraph[tindex] = '\n';
2483 /* All trailing whitespace is ignored. */
2484 output_paragraph_offset = ++tindex;
2486 /* Break the line if that is appropriate. */
2487 if (paragraph_spacing >= 0)
2490 /* Add as many blank lines as is specified in `paragraph_spacing'. */
2491 if (!force_flush_right)
2493 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
2496 /* Don't need anything extra for HTML in usual case of no
2497 extra paragraph spacing. */
2499 insert_string ("<br>");
2503 /* If we are doing flush right indentation, then do it now
2504 on the paragraph (really a single line). */
2505 if (force_flush_right)
2506 do_flush_right_indentation ();
2509 paragraph_is_open = 0;
2514 ignore_blank_line ();
2517 /* Make the last line just read look as if it were only a newline. */
2519 ignore_blank_line ()
2521 last_inserted_character = '\n';
2522 last_char_was_newline = 1;
2525 /* Align the end of the text in output_paragraph with fill_column. */
2527 do_flush_right_indentation ()
2532 kill_self_indent (-1);
2534 if (output_paragraph[0] != '\n')
2536 output_paragraph[output_paragraph_offset] = 0;
2538 if (output_paragraph_offset < fill_column)
2542 if (fill_column >= paragraph_buffer_len)
2544 xrealloc (output_paragraph,
2545 (paragraph_buffer_len += fill_column));
2547 temp_len = strlen ((char *)output_paragraph);
2548 temp = xmalloc (temp_len + 1);
2549 memcpy (temp, (char *)output_paragraph, temp_len);
2551 for (i = 0; i < fill_column - output_paragraph_offset; i++)
2552 output_paragraph[i] = ' ';
2554 memcpy ((char *)output_paragraph + i, temp, temp_len);
2556 output_paragraph_offset = fill_column;
2557 adjust_braces_following (0, i);
2562 /* Begin a new paragraph. */
2566 /* First close existing one. */
2567 if (paragraph_is_open)
2570 /* In either case, the insertion paragraph is no longer closed. */
2571 insertion_paragraph_closed = 0;
2573 /* However, the paragraph is open! */
2574 paragraph_is_open = 1;
2576 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
2577 had to be called before we would allow any other paragraph operations
2578 to have an effect. */
2579 if (!must_start_paragraph)
2581 int amount_to_indent = 0;
2583 /* If doing indentation, then insert the appropriate amount. */
2586 if (inhibit_paragraph_indentation)
2588 amount_to_indent = current_indent;
2589 if (inhibit_paragraph_indentation < 0)
2590 inhibit_paragraph_indentation++;
2592 else if (paragraph_start_indent < 0)
2593 amount_to_indent = current_indent;
2595 amount_to_indent = current_indent + paragraph_start_indent;
2597 if (amount_to_indent >= output_column)
2599 amount_to_indent -= output_column;
2600 indent (amount_to_indent);
2601 output_column += amount_to_indent;
2606 must_start_paragraph = 0;
2609 /* Insert the indentation specified by AMOUNT. */
2617 /* For every START_POS saved within the brace stack which will be affected
2618 by this indentation, bump that start pos forward. */
2619 adjust_braces_following (output_paragraph_offset, amount);
2621 while (--amount >= 0)
2625 /* Search forward for STRING in input_text.
2626 FROM says where where to start. */
2628 search_forward (string, from)
2632 int len = strlen (string);
2634 while (from < input_text_length)
2636 if (strncmp (input_text + from, string, len) == 0)
2643 /* Cross references. */
2645 /* Return next comma-delimited argument, but do not cross a close-brace
2646 boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
2647 the entire brace-delimited argument list with its expansion before
2648 looking for the next comma. */
2650 get_xref_token (expand)
2657 int old_offset = input_text_offset;
2658 int old_lineno = line_number;
2660 get_until_in_braces ("}", &string);
2661 if (curchar () == '}') /* as opposed to end of text */
2662 input_text_offset++;
2663 if (input_text_offset > old_offset)
2665 int limit = input_text_offset;
2667 input_text_offset = old_offset;
2668 line_number = old_lineno;
2669 only_macro_expansion++;
2670 replace_with_expansion (input_text_offset, &limit);
2671 only_macro_expansion--;
2676 get_until_in_braces (",", &string);
2677 if (curchar () == ',')
2678 input_text_offset++;
2679 fix_whitespace (string);
2683 /* NOTE: If you wonder why the HTML output is produced with such a
2684 peculiar mix of calls to add_word and execute_string, here's the
2685 reason. get_xref_token (1) expands all macros in a reference, but
2686 any other commands, like @value, @@, etc., are left intact. To
2687 expand them, we need to run the arguments through execute_string.
2688 However, characters like <, &, > and others cannot be let into
2689 execute_string, because they will be escaped. See the mess? */
2691 /* Make a cross reference. */
2697 char *arg1 = get_xref_token (1); /* expands all macros in xref */
2698 char *arg2 = get_xref_token (0);
2699 char *arg3 = get_xref_token (0);
2700 char *arg4 = get_xref_token (0);
2701 char *arg5 = get_xref_token (0);
2707 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
2710 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
2728 /* html fixxme: revisit this; external node name not
2729 much use to us with numbered nodes. */
2730 add_word ("<a href=");
2731 execute_string ("\"%s.html#", arg4);
2732 /* Do not collapse -- to -, etc., in references. */
2733 in_fixed_width_font++;
2734 tem = expansion (node_name, 0);
2735 in_fixed_width_font--;
2736 add_escaped_anchor_name (tem);
2739 execute_string ("%s", arg1);
2744 execute_string ("%s:", node_name);
2745 in_fixed_width_font++;
2746 execute_string (" (%s)%s%s", arg4, arg1, px_ref_flag ? "." : "");
2747 in_fixed_width_font--;
2750 /* Free all of the arguments found. */
2751 if (arg1) free (arg1);
2752 if (arg2) free (arg2);
2753 if (arg3) free (arg3);
2754 if (arg4) free (arg4);
2755 if (arg5) free (arg5);
2759 remember_node_reference (arg1, line_number, followed_reference);
2765 add_word ("<a href=\"");
2766 in_fixed_width_font++;
2767 tem = expansion (arg1, 0);
2768 in_fixed_width_font--;
2769 add_anchor_name (tem, 1);
2772 execute_string ("%s", *arg2 ? arg2 : arg3);
2777 execute_string ("%s:", *arg2 ? arg2 : arg3);
2778 in_fixed_width_font++;
2779 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
2780 in_fixed_width_font--;
2787 add_word ("<a href=\"");
2788 in_fixed_width_font++;
2789 tem = expansion (arg1, 0);
2790 in_fixed_width_font--;
2791 add_anchor_name (tem, 1);
2794 execute_string ("%s", *arg2 ? arg2 : arg1);
2801 execute_string ("%s:", arg2);
2802 in_fixed_width_font++;
2803 execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
2804 in_fixed_width_font--;
2808 in_fixed_width_font++;
2809 execute_string ("%s::", arg1);
2810 in_fixed_width_font--;
2815 /* Free all of the arguments found. */
2816 if (arg1) free (arg1);
2817 if (arg2) free (arg2);
2818 if (arg3) free (arg3);
2819 if (arg4) free (arg4);
2820 if (arg5) free (arg5);
2823 { /* Check to make sure that the next non-whitespace character is
2824 valid to follow an xref (so info readers can find the node
2825 names). `input_text_offset' is pointing at the "}" which ended
2826 the xref or ref command. */
2829 for (temp = input_text_offset + 1; temp < input_text_length; )
2831 if (cr_or_whitespace (input_text[temp]))
2835 if (input_text[temp] != '.' && input_text[temp] != ',')
2836 warning (_("`.' or `,' must follow cross reference, not %c"),
2854 /* Note that cm_xref isn't called with arg == END, which disables
2855 the code near the end of cm_xref that checks for `.' or `,'
2856 after the cross-reference. This is because @pxref{} generates
2857 the required character itself, when needed. */
2878 char *node = get_xref_token (1); /* expands all macros in inforef */
2879 char *pname = get_xref_token (0);
2880 char *file = get_xref_token (0);
2884 add_word (_("see "));
2885 /* html fixxme: revisit this */
2886 add_word ("<a href=");
2887 execute_string ("\"%s.html\"", file);
2889 execute_string ("%s", pname);
2895 execute_string ("*note %s: (%s)%s", pname, file, node);
2897 execute_string ("*note (%s)%s::", file, node);
2906 /* A URL reference. */
2913 extern int printing_index;
2914 char *url = get_xref_token (1); /* expands all macros in uref */
2915 char *desc = get_xref_token (0);
2916 char *replacement = get_xref_token (0);
2919 { /* never need to show the url */
2920 add_word ("<a href=");
2921 /* don't collapse `--' etc. in the url */
2922 in_fixed_width_font++;
2923 execute_string ("\"%s\"", url);
2924 in_fixed_width_font--;
2926 execute_string ("%s", *replacement ? replacement
2927 : (*desc ? desc : url));
2930 else if (*replacement) /* do not show the url */
2931 execute_string ("%s", replacement);
2932 else if (*desc) /* show both text and url */
2934 execute_string ("%s ", desc);
2935 in_fixed_width_font++;
2936 execute_string ("(%s)", url);
2937 in_fixed_width_font--;
2939 else /* no text at all, so have the url to show */
2941 in_fixed_width_font++;
2942 execute_string ("%s%s%s",
2943 printing_index ? "" : "`",
2945 printing_index ? "" : "'");
2946 in_fixed_width_font--;
2957 /* An email reference. */
2964 char *addr = get_xref_token (1); /* expands all macros in email */
2965 char *name = get_xref_token (0);
2969 add_word ("<a href=");
2970 /* don't collapse `--' etc. in the address */
2971 in_fixed_width_font++;
2972 execute_string ("\"mailto:%s\"", addr);
2973 in_fixed_width_font--;
2975 execute_string ("%s", *name ? name : addr);
2980 execute_string ("%s%s", name, *name ? " " : "");
2981 in_fixed_width_font++;
2982 execute_string ("<%s>", addr);
2983 in_fixed_width_font--;
2993 /* An external image is a reference, kind of. The parsing is (not
2994 coincidentally) similar, anyway. */
2999 char *name_arg, *rest;
3004 name_arg = get_xref_token (1); /* expands all macros in image */
3005 /* We don't (yet) care about any other args, but read them so they
3006 don't end up in the text. */
3007 rest = get_xref_token (0);
3010 rest = get_xref_token (0);
3016 char *fullname = xmalloc (strlen (name_arg) + 4 + 1);
3019 { /* fixxme It would be nice to insert more useful alt text. */
3020 sprintf (fullname, "%s.png", name_arg);
3021 if (access (fullname, R_OK) != 0)
3023 sprintf (fullname, "%s.jpg", name_arg);
3024 if (access (fullname, R_OK) != 0)
3026 line_error (_("No .png or .jpg for `%s'"), name_arg);
3031 add_word_args ("<img src=\"%s\" alt=\"%s\">", fullname, fullname);
3034 { /* Try to open foo.txt. */
3036 strcpy (fullname, name_arg);
3037 strcat (fullname, ".txt");
3038 image_file = fopen (fullname, "r");
3042 int save_inhibit_indentation = inhibit_paragraph_indentation;
3043 int save_filling_enabled = filling_enabled;
3045 inhibit_paragraph_indentation = 1;
3046 filling_enabled = 0;
3047 last_char_was_newline = 0;
3049 /* Maybe we need to remove the final newline if the image
3050 file is only one line to allow in-line images. On the
3051 other hand, they could just make the file without a
3053 while ((ch = getc (image_file)) != EOF)
3056 inhibit_paragraph_indentation = save_inhibit_indentation;
3057 filling_enabled = save_filling_enabled;
3059 if (fclose (image_file) != 0)
3063 warning (_("@image file `%s' unreadable: %s"), fullname,
3070 line_error (_("@image missing filename argument"));
3078 /* A structure which contains `defined' variables. */
3079 typedef struct defines {
3080 struct defines *next;
3085 /* The linked list of `set' defines. */
3086 DEFINE *defines = NULL;
3088 /* Add NAME to the list of `set' defines. */
3096 for (temp = defines; temp; temp = temp->next)
3097 if (strcmp (name, temp->name) == 0)
3100 temp->value = xstrdup (value);
3104 temp = xmalloc (sizeof (DEFINE));
3105 temp->next = defines;
3106 temp->name = xstrdup (name);
3107 temp->value = xstrdup (value);
3111 /* Remove NAME from the list of `set' defines. */
3116 DEFINE *temp, *last;
3123 if (strcmp (temp->name, name) == 0)
3126 last->next = temp->next;
3128 defines = temp->next;
3140 /* Return the value of NAME. The return value is NULL if NAME is unset. */
3147 for (temp = defines; temp; temp = temp->next)
3148 if (strcmp (temp->name, name) == 0)
3154 /* Create a variable whose name appears as the first word on this line. */
3158 handle_variable (SET);
3161 /* Remove a variable whose name appears as the first word on this line. */
3165 handle_variable (CLEAR);
3171 handle_variable (IFSET);
3177 handle_variable (IFCLEAR);
3180 /* This command takes braces, but we parse the contents specially, so we
3181 don't use the standard brace popping code.
3183 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3184 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3185 it produces no output. */
3191 arglist = get_brace_args (0);
3195 if (array_len (arglist) > 1)
3197 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
3199 execute_string ("%s\n", arglist[2]);
3202 free_array (arglist);
3207 cm_value (arg, start_pos, end_pos)
3208 int arg, start_pos, end_pos;
3210 static int value_level = 0, saved_meta_pos = -1;
3212 /* All the text after @value{ upto the matching } will eventually
3213 disappear from output_paragraph, when this function is called
3214 with ARG == END. If the text produced until then sets
3215 meta_char_pos, we will need to restore it to the value it had
3216 before @value was seen. So we need to save the previous value
3217 of meta_char_pos here. */
3220 /* If we are already inside some outer @value, don't overwrite
3221 the value saved in saved_meta_pos. */
3223 saved_meta_pos = meta_char_pos;
3225 /* While the argument of @value is processed, we need to inhibit
3226 textual transformations like "--" into "-", since @set didn't
3227 do that when it grabbed the name of the variable. */
3228 in_fixed_width_font++;
3232 char *name = (char *) &output_paragraph[start_pos];
3234 output_paragraph[end_pos] = 0;
3235 name = xstrdup (name);
3236 value = set_p (name);
3237 output_column -= end_pos - start_pos;
3238 output_paragraph_offset = start_pos;
3240 /* Restore the previous value of meta_char_pos if the stuff
3241 inside this @value{} moved it. */
3242 if (saved_meta_pos == -1) /* can't happen inside @value{} */
3244 if (value_level == 1
3245 && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3247 meta_char_pos = saved_meta_pos;
3248 saved_meta_pos = -1;
3251 /* No need to decrement in_fixed_width_font, since before
3252 we are called with arg == END, the reader loop already
3253 popped the brace stack, which restored in_fixed_width_font,
3254 among other things. */
3257 execute_string ("%s", value);
3259 add_word_args (_("{No value for `%s'}"), name);
3265 /* Set, clear, or conditionalize based on ACTION. */
3267 handle_variable (action)
3272 get_rest_of_line (0, &name);
3273 /* If we hit the end of text in get_rest_of_line, backing up
3274 input pointer will cause the last character of the last line
3275 be pushed back onto the input, which is wrong. */
3276 if (input_text_offset < input_text_length)
3277 backup_input_pointer ();
3278 handle_variable_internal (action, name);
3283 handle_variable_internal (action, name)
3288 int delimiter, additional_text_present = 0;
3290 /* Only the first word of NAME is a valid tag. */
3293 while (*temp && (delimiter || !whitespace (*temp)))
3295 /* #if defined (SET_WITH_EQUAL) */
3296 if (*temp == '"' || *temp == '\'')
3298 if (*temp == delimiter)
3303 /* #endif SET_WITH_EQUAL */
3308 additional_text_present++;
3313 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3322 #if defined (SET_WITH_EQUAL)
3323 /* Allow a value to be saved along with a variable. The value is
3324 the text following an `=' sign in NAME, if any is present. */
3326 for (value = name; *value && *value != '='; value++);
3331 if (*value == '"' || *value == '\'')
3334 value[strlen (value) - 1] = 0;
3337 #else /* !SET_WITH_EQUAL */
3338 /* The VALUE of NAME is the remainder of the line sans
3340 if (additional_text_present)
3343 canon_white (value);
3347 #endif /* !SET_WITH_VALUE */
3359 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3360 read lines from the the file until we reach a matching
3361 "@end CONDITION". This means that we only take note of
3362 "@ifset/clear" and "@end" commands. */
3366 int orig_line_number = line_number;
3368 if (action == IFSET)
3369 strcpy (condition, "ifset");
3371 strcpy (condition, "ifclear");
3373 condition_len = strlen (condition);
3375 if ((action == IFSET && !set_p (name))
3376 || (action == IFCLEAR && set_p (name)))
3378 int level = 0, done = 0;
3380 while (!done && input_text_offset < input_text_length)
3382 char *freeable_line, *line;
3384 get_rest_of_line (0, &freeable_line);
3386 for (line = freeable_line; whitespace (*line); line++);
3388 if (*line == COMMAND_PREFIX &&
3389 (strncmp (line + 1, condition, condition_len) == 0))
3391 else if (strncmp (line, "@end", 4) == 0)
3393 char *cname = line + 4;
3396 while (*cname && whitespace (*cname))
3400 while (*temp && !whitespace (*temp))
3404 if (strcmp (cname, condition) == 0)
3414 free (freeable_line);
3419 int save = line_number;
3420 line_number = orig_line_number;
3421 line_error (_("Reached eof before matching @end %s"),
3426 /* We found the end of a false @ifset/ifclear. If we are
3427 in a menu, back up over the newline that ends the ifset,
3428 since that newline may also begin the next menu entry. */
3433 if (action == IFSET)
3434 begin_insertion (ifset);
3436 begin_insertion (ifclear);
3444 /* Execution of random text not in file. */
3447 char *string; /* The string buffer. */
3448 int size; /* The size of the buffer. */
3449 int in_use; /* Nonzero means string currently in use. */
3452 static EXECUTION_STRING **execution_strings = NULL;
3453 static int execution_strings_index = 0;
3454 static int execution_strings_slots = 0;
3457 get_execution_string (initial_size)
3461 EXECUTION_STRING *es = NULL;
3463 if (execution_strings)
3465 for (i = 0; i < execution_strings_index; i++)
3466 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
3468 es = execution_strings[i];
3475 if (execution_strings_index + 1 >= execution_strings_slots)
3477 execution_strings = xrealloc
3479 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
3480 for (; i < execution_strings_slots; i++)
3481 execution_strings[i] = NULL;
3484 execution_strings[execution_strings_index] =
3485 xmalloc (sizeof (EXECUTION_STRING));
3486 es = execution_strings[execution_strings_index];
3487 execution_strings_index++;
3494 if (initial_size > es->size)
3496 es->string = xrealloc (es->string, initial_size);
3497 es->size = initial_size;
3502 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
3503 entry in the execution_strings[] array and change the .STRING and
3504 .SIZE members of that entry as appropriate. */
3506 maybe_update_execution_strings (text, new_len)
3512 if (execution_strings)
3514 for (i = 0; i < execution_strings_index; i++)
3515 if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
3516 execution_strings[i]->string == *text)
3518 /* Don't ever shrink the string storage in execution_strings[]!
3519 execute_string assumes that it is always big enough to store
3520 every possible execution_string, and will break if that's
3521 not true. So we only enlarge the string storage if the
3522 current size isn't big enough. */
3523 if (execution_strings[i]->size < new_len)
3525 execution_strings[i]->string =
3526 *text = xrealloc (*text, new_len + 1);
3527 execution_strings[i]->size = new_len + 1;
3532 /* We should *never* end up here, since if we are inside
3533 execute_string, TEXT is always in execution_strings[]. */
3537 /* Execute the string produced by formatting the ARGs with FORMAT. This
3538 is like submitting a new file with @include. */
3540 #if defined (VA_FPRINTF) && __STDC__
3541 execute_string (char *format, ...)
3543 execute_string (format, va_alist)
3548 EXECUTION_STRING *es;
3554 es = get_execution_string (4000);
3555 temp_string = es->string;
3558 VA_START (ap, format);
3560 VA_SPRINTF (temp_string, format, ap);
3562 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
3563 #endif /* not VA_SPRINTF */
3567 input_text_offset = 0;
3568 input_text = temp_string;
3569 input_filename = xstrdup (input_filename);
3570 input_text_length = strlen (temp_string);
3574 free (input_filename);
3582 /* Return what would be output for STR (in newly-malloced memory), i.e.,
3583 expand Texinfo commands. If IMPLICIT_CODE is set, expand @code{STR}. */
3586 expansion (str, implicit_code)
3593 /* Inhibit any real output. */
3594 int start = output_paragraph_offset;
3595 int saved_paragraph_is_open = paragraph_is_open;
3596 int saved_output_column = output_column;
3598 /* Inhibit indentation and filling, so that extra newlines
3599 are not added to the expansion. (This is undesirable if
3600 we write the expanded text to macro_expansion_output_stream.) */
3601 int saved_filling_enabled = filling_enabled;
3602 int saved_indented_fill = indented_fill;
3603 int saved_no_indent = no_indent;
3604 int saved_escape_html = escape_html;
3605 int saved_meta_pos = meta_char_pos;
3606 int saved_last_char = last_inserted_character;
3607 int saved_last_nl = last_char_was_newline;
3609 /* If we are called in the middle of processing a command, we need
3610 to dup and save the global variable `command' (which holds the
3611 name of this command), since the recursive reader loop will free
3612 it from under our feet if it finds any macros in STR. */
3613 char *saved_command = command ? xstrdup (command) : NULL;
3615 filling_enabled = 0;
3620 inhibit_output_flushing ();
3621 paragraph_is_open = 1;
3622 execute_string (implicit_code ? "@code{%s}" : "%s", str);
3623 uninhibit_output_flushing ();
3625 /* Copy the expansion from the buffer. */
3626 length = output_paragraph_offset - start;
3627 result = xmalloc (1 + length);
3628 memcpy (result, (char *) (output_paragraph + start), length);
3631 /* Pretend it never happened. */
3632 free_and_clear (&command);
3633 command = saved_command;
3634 output_paragraph_offset = start;
3635 paragraph_is_open = saved_paragraph_is_open;
3636 output_column = saved_output_column;
3637 filling_enabled = saved_filling_enabled;
3638 indented_fill = saved_indented_fill;
3639 no_indent = saved_no_indent;
3640 escape_html = saved_escape_html;
3641 meta_char_pos = saved_meta_pos;
3642 last_inserted_character = saved_last_char;
3643 last_char_was_newline = saved_last_nl;
3649 /* Return text (info) expansion of STR no matter what the current output
3653 text_expansion (str)
3657 int save_html = html;
3660 ret = expansion (str, 0);
3667 /* Set the paragraph indentation variable to the value specified in STRING.
3669 `asis': Don't change existing indentation.
3670 `none': Remove existing indentation.
3671 NUM: Indent NUM spaces at the starts of paragraphs.
3672 If NUM is zero, we assume `none'.
3673 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
3675 set_paragraph_indent (string)
3678 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
3679 paragraph_start_indent = 0;
3680 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
3681 paragraph_start_indent = -1;
3684 if (sscanf (string, "%d", ¶graph_start_indent) != 1)
3688 if (paragraph_start_indent == 0)
3689 paragraph_start_indent = -1;