1/*	$NetBSD: makeinfo.c,v 1.2 2016/01/14 00:34:53 christos Exp $	*/
2
3/* makeinfo -- convert Texinfo source into other formats.
4   Id: makeinfo.c,v 1.74 2004/12/19 17:15:42 karl Exp
5
6   Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
7   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2, or (at your option)
12   any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   Original author of makeinfo: Brian Fox (bfox@ai.mit.edu).  */
24
25#include "system.h"
26#include "getopt.h"
27
28#define COMPILING_MAKEINFO
29#include "makeinfo.h"
30#include "cmds.h"
31#include "files.h"
32#include "float.h"
33#include "footnote.h"
34#include "html.h"
35#include "index.h"
36#include "insertion.h"
37#include "lang.h"
38#include "macro.h"
39#include "node.h"
40#include "sectioning.h"
41#include "toc.h"
42#include "xml.h"
43
44/* You can change some of the behavior of Makeinfo by changing the
45   following defines: */
46
47/* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
48   appear within an @table, @ftable, or @itemize environment to have
49   standard paragraph indentation.  Without this, such paragraphs have
50   no starting indentation. */
51/* #define INDENT_PARAGRAPHS_IN_TABLE */
52
53/* Define PARAGRAPH_START_INDENT to be the amount of indentation that
54   the first lines of paragraphs receive by default, where no other
55   value has been specified.  Users can change this value on the command
56   line, with the --paragraph-indent option, or within the texinfo file,
57   with the @paragraphindent command. */
58#define PARAGRAPH_START_INDENT 3
59
60/* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
61   wish to appear between paragraphs.  A value of 1 creates a single blank
62   line between paragraphs.  Paragraphs are defined by 2 or more consecutive
63   newlines in the input file (i.e., one or more blank lines). */
64#define DEFAULT_PARAGRAPH_SPACING 1
65
66/* Global variables.  */
67
68/* The output file name. */
69char *output_filename = NULL;
70
71/* Name of the output file that the user elected to pass on the command line.
72   Such a name overrides any name found with the @setfilename command. */
73char *command_output_filename = NULL;
74static char *save_command_output_filename = NULL;
75
76#define INITIAL_PARAGRAPH_SPACE 5000
77int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
78
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.
83
84   This is normally zero, but some people prefer paragraph starts to be
85   somewhat more indented than paragraph bodies.  A pretty value for
86   this is 3. */
87int paragraph_start_indent = PARAGRAPH_START_INDENT;
88
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
91   blank lines. */
92int pending_indent = 0;
93
94/* The index in our internal command table of the currently
95   executing command. */
96int command_index;
97
98/* A search string which is used to find the first @setfilename. */
99char setfilename_search[] =
100  { COMMAND_PREFIX,
101      's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
102
103/* Values for calling handle_variable_internal (). */
104#define SET     1
105#define CLEAR   2
106#define IFSET   3
107#define IFCLEAR 4
108
109/* Flags controlling the operation of the program. */
110
111/* Default is to remove output if there were errors.  */
112int force = 0;
113
114/* Default is to notify users of bad choices. */
115int print_warnings = 1;
116
117/* Number of errors that we tolerate on a given fileset. */
118int max_error_level = 100;
119
120/* The actual last inserted character.  Note that this may be something
121   other than NEWLINE even if last_char_was_newline is 1. */
122int last_inserted_character = 0;
123
124/* Nonzero means that a newline character has already been
125   inserted, so close_paragraph () should insert one less. */
126int line_already_broken = 0;
127
128/* When nonzero we have finished an insertion (see end_insertion ()) and we
129   want to ignore false continued paragraph closings. */
130int insertion_paragraph_closed = 0;
131
132/* Nonzero means attempt to make all of the lines have fill_column width. */
133int do_justification = 0;
134
135/* Nonzero means don't replace whitespace with &nbsp; in HTML mode.  */
136int in_html_elt = 0;
137
138/* Nonzero means we are inserting a block level HTML element that must not be
139   enclosed in a <p>, such as <ul>, <ol> and <h?>.  */
140int in_html_block_level_elt = 0;
141
142/* True when expanding a macro definition.  */
143static int executing_macro = 0;
144
145/* True when we are inside a <li> block of a menu.  */
146static int in_menu_item = 0;
147
148typedef struct brace_element
149{
150  struct brace_element *next;
151  COMMAND_FUNCTION *proc;
152  char *command;
153  int pos, line;
154  int in_fixed_width_font;
155} BRACE_ELEMENT;
156
157BRACE_ELEMENT *brace_stack = NULL;
158
159static void convert_from_file (char *name);
160static void convert_from_loaded_file (char *name);
161static void convert_from_stream (FILE *stream, char *name);
162static void do_flush_right_indentation (void);
163static void handle_variable (int action);
164static void handle_variable_internal (int action, char *name);
165static void init_brace_stack (void);
166static void init_internals (void);
167static void pop_and_call_brace (void);
168static void remember_brace (COMMAND_FUNCTION (*proc));
169static int end_of_sentence_p (void);
170
171void maybe_update_execution_strings (char **text, unsigned int new_len);
172
173/* Error handling.  */
174
175/* Number of errors encountered. */
176int errors_printed = 0;
177
178/* Remember that an error has been printed.  If more than
179   max_error_level have been printed, then exit the program. */
180static void
181remember_error (void)
182{
183  errors_printed++;
184  if (max_error_level && (errors_printed > max_error_level))
185    {
186      fprintf (stderr, _("Too many errors!  Gave up.\n"));
187      flush_file_stack ();
188      if (errors_printed - max_error_level < 2)
189	cm_bye ();
190      xexit (1);
191    }
192}
193
194/* Print the last error gotten from the file system. */
195int
196fs_error (char *filename)
197{
198  remember_error ();
199  perror (filename);
200  return 0;
201}
202
203/* Print an error message, and return false. */
204void
205#if defined (VA_FPRINTF) && __STDC__
206error (const char *format, ...)
207#else
208error (format, va_alist)
209     const char *format;
210     va_dcl
211#endif
212{
213#ifdef VA_FPRINTF
214  va_list ap;
215#endif
216
217  remember_error ();
218
219  VA_START (ap, format);
220#ifdef VA_FPRINTF
221  VA_FPRINTF (stderr, format, ap);
222#else
223  fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
224#endif /* not VA_FPRINTF */
225  va_end (ap);
226
227  putc ('\n', stderr);
228}
229
230/* Just like error (), but print the input file and line number as well. */
231void
232#if defined (VA_FPRINTF) && __STDC__
233file_line_error (char *infile, int lno, const char *format, ...)
234#else
235file_line_error (infile, lno, format, va_alist)
236   char *infile;
237   int lno;
238   const char *format;
239   va_dcl
240#endif
241{
242#ifdef VA_FPRINTF
243  va_list ap;
244#endif
245
246  remember_error ();
247  fprintf (stderr, "%s:%d: ", infile, lno);
248
249  VA_START (ap, format);
250#ifdef VA_FPRINTF
251  VA_FPRINTF (stderr, format, ap);
252#else
253  fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
254#endif /* not VA_FPRINTF */
255  va_end (ap);
256
257  fprintf (stderr, ".\n");
258}
259
260/* Just like file_line_error (), but take the input file and the line
261   number from global variables. */
262void
263#if defined (VA_FPRINTF) && __STDC__
264line_error (const char *format, ...)
265#else
266line_error (format, va_alist)
267   const char *format;
268   va_dcl
269#endif
270{
271#ifdef VA_FPRINTF
272  va_list ap;
273#endif
274
275  remember_error ();
276  fprintf (stderr, "%s:%d: ", input_filename, line_number);
277
278  VA_START (ap, format);
279#ifdef VA_FPRINTF
280  VA_FPRINTF (stderr, format, ap);
281#else
282  fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
283#endif /* not VA_FPRINTF */
284  va_end (ap);
285
286  fprintf (stderr, ".\n");
287}
288
289void
290#if defined (VA_FPRINTF) && __STDC__
291warning (const char *format, ...)
292#else
293warning (format, va_alist)
294     const char *format;
295     va_dcl
296#endif
297{
298#ifdef VA_FPRINTF
299  va_list ap;
300#endif
301
302  if (print_warnings)
303    {
304      fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
305
306      VA_START (ap, format);
307#ifdef VA_FPRINTF
308      VA_FPRINTF (stderr, format, ap);
309#else
310      fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
311#endif /* not VA_FPRINTF */
312      va_end (ap);
313
314      fprintf (stderr, ".\n");
315    }
316}
317
318
319/* The other side of a malformed expression. */
320static void
321misplaced_brace (void)
322{
323  line_error (_("Misplaced %c"), '}');
324}
325
326/* Main.  */
327
328/* Display the version info of this invocation of Makeinfo. */
329static void
330print_version_info (void)
331{
332  printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION);
333}
334
335/* If EXIT_VALUE is zero, print the full usage message to stdout.
336   Otherwise, just say to use --help for more info.
337   Then exit with EXIT_VALUE. */
338static void
339usage (int exit_value)
340{
341  if (exit_value != 0)
342    fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
343  else
344  {
345    printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname);
346    puts ("");
347
348    puts (_("\
349Translate Texinfo source documentation to various other formats, by default\n\
350Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
351
352    printf (_("\
353General options:\n\
354      --error-limit=NUM       quit after NUM errors (default %d).\n\
355      --force                 preserve output even if errors.\n\
356      --help                  display this help and exit.\n\
357      --no-validate           suppress node cross-reference validation.\n\
358      --no-warn               suppress warnings (but not errors).\n\
359      --reference-limit=NUM   warn about at most NUM references (default %d).\n\
360  -v, --verbose               explain what is being done.\n\
361      --version               display version information and exit.\n"),
362            max_error_level, reference_warning_limit);
363    puts ("");
364
365     /* xgettext: no-wrap */
366    puts (_("\
367Output format selection (default is to produce Info):\n\
368      --docbook             output Docbook XML rather than Info.\n\
369      --html                output HTML rather than Info.\n\
370      --xml                 output Texinfo XML rather than Info.\n\
371      --plaintext           output plain text rather than Info.\n\
372"));
373
374    puts (_("\
375General output options:\n\
376  -E, --macro-expand FILE   output macro-expanded source to FILE.\n\
377                            ignoring any @setfilename.\n\
378      --no-headers          suppress node separators, Node: lines, and menus\n\
379                              from Info output (thus producing plain text)\n\
380                              or from HTML (thus producing shorter output);\n\
381                              also, write to standard output by default.\n\
382      --no-split            suppress splitting of Info or HTML output,\n\
383                            generate only one output file.\n\
384      --no-version-headers  suppress header with makeinfo version and\n\
385                            source path.\n\
386      --number-sections     output chapter and sectioning numbers.\n\
387  -o, --output=FILE         output to FILE (directory if split HTML),\n\
388"));
389
390    printf (_("\
391Options for Info and plain text:\n\
392      --enable-encoding       output accented and special characters in\n\
393                                Info output based on @documentencoding.\n\
394      --fill-column=NUM       break Info lines at NUM characters (default %d).\n\
395      --footnote-style=STYLE  output footnotes in Info according to STYLE:\n\
396                                `separate' to put them in their own node;\n\
397                                `end' to put them at the end of the node\n\
398                                  in which they are defined (default).\n\
399      --paragraph-indent=VAL  indent Info paragraphs by VAL spaces (default %d).\n\
400                                If VAL is `none', do not indent; if VAL is\n\
401                                `asis', preserve existing indentation.\n\
402      --split-size=NUM        split Info files at size NUM (default %d).\n"),
403             fill_column, paragraph_start_indent,
404             DEFAULT_SPLIT_SIZE);
405    puts ("");
406
407    puts (_("\
408Options for HTML:\n\
409      --css-include=FILE        include FILE in HTML <style> output;\n\
410                                  read stdin if FILE is -.\n\
411"));
412
413    printf (_("\
414Options for XML and Docbook:\n\
415      --output-indent=VAL       indent XML elements by VAL spaces (default %d).\n\
416                                  If VAL is 0, ignorable whitespace is dropped.\n\
417"), xml_indentation_increment);
418    puts ("");
419
420    puts (_("\
421Input file options:\n\
422      --commands-in-node-names  allow @ commands in node names.\n\
423  -D VAR                        define the variable VAR, as with @set.\n\
424  -I DIR                        append DIR to the @include search path.\n\
425  -P DIR                        prepend DIR to the @include search path.\n\
426  -U VAR                        undefine the variable VAR, as with @clear.\n\
427"));
428
429    puts (_("\
430Conditional processing in input:\n\
431  --ifdocbook       process @ifdocbook and @docbook even if\n\
432                      not generating Docbook.\n\
433  --ifhtml          process @ifhtml and @html even if not generating HTML.\n\
434  --ifinfo          process @ifinfo even if not generating Info.\n\
435  --ifplaintext     process @ifplaintext even if not generating plain text.\n\
436  --iftex           process @iftex and @tex; implies --no-split.\n\
437  --ifxml           process @ifxml and @xml.\n\
438  --no-ifdocbook    do not process @ifdocbook and @docbook text.\n\
439  --no-ifhtml       do not process @ifhtml and @html text.\n\
440  --no-ifinfo       do not process @ifinfo text.\n\
441  --no-ifplaintext  do not process @ifplaintext text.\n\
442  --no-iftex        do not process @iftex and @tex text.\n\
443  --no-ifxml        do not process @ifxml and @xml text.\n\
444\n\
445  Also, for the --no-ifFORMAT options, do process @ifnotFORMAT text.\n\
446"));
447
448    puts (_("\
449  The defaults for the @if... conditionals depend on the output format:\n\
450  if generating HTML, --ifhtml is on and the others are off;\n\
451  if generating Info, --ifinfo is on and the others are off;\n\
452  if generating plain text, --ifplaintext is on and the others are off;\n\
453  if generating XML, --ifxml is on and the others are off.\n\
454"));
455
456    fputs (_("\
457Examples:\n\
458  makeinfo foo.texi                     write Info to foo's @setfilename\n\
459  makeinfo --html foo.texi              write HTML to @setfilename\n\
460  makeinfo --xml foo.texi               write Texinfo XML to @setfilename\n\
461  makeinfo --docbook foo.texi           write DocBook XML to @setfilename\n\
462  makeinfo --no-headers foo.texi        write plain text to standard output\n\
463\n\
464  makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
465  makeinfo --number-sections foo.texi   write Info with numbered sections\n\
466  makeinfo --no-split foo.texi          write one Info file however big\n\
467"), stdout);
468
469    puts (_("\n\
470Email bug reports to bug-texinfo@gnu.org,\n\
471general questions and discussion to help-texinfo@gnu.org.\n\
472Texinfo home page: http://www.gnu.org/software/texinfo/"));
473
474  } /* end of full help */
475
476  xexit (exit_value);
477}
478
479struct option long_options[] =
480{
481  { "commands-in-node-names", 0, &expensive_validation, 1 },
482  { "css-include", 1, 0, 'C' },
483  { "docbook", 0, 0, 'd' },
484  { "enable-encoding", 0, &enable_encoding, 1 },
485  { "error-limit", 1, 0, 'e' },
486  { "fill-column", 1, 0, 'f' },
487  { "footnote-style", 1, 0, 's' },
488  { "force", 0, &force, 1 },
489  { "help", 0, 0, 'h' },
490  { "html", 0, 0, 'w' },
491  { "ifdocbook", 0, &process_docbook, 1 },
492  { "ifhtml", 0, &process_html, 1 },
493  { "ifinfo", 0, &process_info, 1 },
494  { "ifplaintext", 0, &process_plaintext, 1 },
495  { "iftex", 0, &process_tex, 1 },
496  { "ifxml", 0, &process_xml, 1 },
497  { "macro-expand", 1, 0, 'E' },
498  { "no-headers", 0, &no_headers, 1 },
499  { "no-ifdocbook", 0, &process_docbook, 0 },
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-ifxml", 0, &process_xml, 0 },
505  { "no-number-footnotes", 0, &number_footnotes, 0 },
506  { "no-number-sections", 0, &number_sections, 0 },
507  { "no-pointer-validate", 0, &validating, 0 },
508  { "no-split", 0, &splitting, 0 },
509  { "no-validate", 0, &validating, 0 },
510  { "no-version-header", 0, &no_version_header, 1 },
511  { "no-warn", 0, &print_warnings, 0 },
512  { "number-footnotes", 0, &number_footnotes, 1 },
513  { "number-sections", 0, &number_sections, 1 },
514  { "output", 1, 0, 'o' },
515  { "output-indent", 1, 0, 'i' },
516  { "paragraph-indent", 1, 0, 'p' },
517  { "plaintext", 0, 0, 't' },
518  { "reference-limit", 1, 0, 'r' },
519  { "split-size", 1, 0, 'S'},
520  { "verbose", 0, &verbose_mode, 1 },
521  { "version", 0, 0, 'V' },
522  { "xml", 0, 0, 'x' },
523  {NULL, 0, NULL, 0}
524};
525
526/* We use handle_variable_internal for -D and -U, and it depends on
527   execute_string, which depends on input_filename, which is not defined
528   while we are handling options. :-\  So we save these defines in this
529   struct, and handle them later.  */
530typedef struct command_line_define
531{
532  struct command_line_define *next;
533  int action;
534  char *define;
535} COMMAND_LINE_DEFINE;
536
537static COMMAND_LINE_DEFINE *command_line_defines = NULL;
538
539/* For each file mentioned in the command line, process it, turning
540   Texinfo commands into wonderfully formatted output text. */
541int
542main (int argc, char **argv)
543{
544  int c, ind;
545  int reading_from_stdin = 0;
546
547#ifdef HAVE_SETLOCALE
548  /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
549     of the argument to @multicolumn.  */
550  setlocale (LC_TIME, "");
551#ifdef LC_MESSAGES /* ultrix */
552  setlocale (LC_MESSAGES, "");
553#endif
554  setlocale (LC_CTYPE, "");
555  setlocale (LC_COLLATE, "");
556#endif
557
558#ifdef ENABLE_NLS
559  /* Set the text message domain.  */
560  bindtextdomain (PACKAGE, LOCALEDIR);
561  textdomain (PACKAGE);
562#endif
563
564  /* If TEXINFO_OUTPUT_FORMAT envvar is set, use it to set default output.
565     Can be overridden with one of the output options.  */
566  if (getenv ("TEXINFO_OUTPUT_FORMAT") != NULL)
567    {
568      if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "docbook"))
569        {
570          splitting = 0;
571          html = 0;
572          docbook = 1;
573          xml = 1;
574          process_docbook = 1;
575        }
576      else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "html"))
577        {
578          html = 1;
579          docbook = 0;
580          xml = 0;
581          process_html = 1;
582        }
583      else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "info"))
584        {
585          html = 0;
586          docbook = 0;
587          xml = 0;
588        }
589      else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "plaintext"))
590        {
591          splitting = 0;
592          no_headers = 1;
593          html = 0;
594          docbook = 0;
595          xml = 0;
596          process_plaintext = 1;
597        }
598      else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "xml"))
599        {
600          splitting = 0;
601          html = 0;
602          docbook = 0;
603          xml = 1;
604          process_xml = 1;
605        }
606      else
607        fprintf (stderr,
608            _("%s: Ignoring unrecognized TEXINFO_OUTPUT_FORMAT value `%s'.\n"),
609                 progname, getenv ("TEXINFO_OUTPUT_FORMAT"));
610    }
611
612  /* Parse argument flags from the input line. */
613  while ((c = getopt_long (argc, argv, "D:de:E:f:hI:i:o:p:P:r:s:t:U:vV:wx",
614                           long_options, &ind)) != EOF)
615    {
616      if (c == 0 && long_options[ind].flag == 0)
617        c = long_options[ind].val;
618
619      switch (c)
620        {
621        case 'C':  /* --css-include */
622          css_include = xstrdup (optarg);
623          break;
624
625        case 'D':
626        case 'U':
627          /* User specified variable to set or clear. */
628          if (xml && !docbook)
629            {
630              COMMAND_LINE_DEFINE *new = xmalloc (sizeof (COMMAND_LINE_DEFINE));
631              new->action = (c == 'D') ? SET : CLEAR;
632              new->define = xstrdup (optarg);
633              new->next = command_line_defines;
634              command_line_defines = new;
635            }
636          else
637            handle_variable_internal ((c == 'D' ? SET : CLEAR), optarg);
638          break;
639
640        case 'd': /* --docbook */
641          splitting = 0;
642          xml = 1;
643          docbook = 1;
644          html = 0;
645	  process_docbook = 1;
646          break;
647
648        case 'e': /* --error-limit */
649          if (sscanf (optarg, "%d", &max_error_level) != 1)
650            {
651              fprintf (stderr,
652                      _("%s: %s arg must be numeric, not `%s'.\n"),
653                      progname, "--error-limit", optarg);
654              usage (1);
655            }
656          break;
657
658        case 'E': /* --macro-expand */
659          if (!macro_expansion_output_stream)
660            {
661              macro_expansion_filename = optarg;
662              macro_expansion_output_stream
663                = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
664              if (!macro_expansion_output_stream)
665                error (_("%s: could not open macro expansion output `%s'"),
666                       progname, optarg);
667            }
668          else
669            fprintf (stderr,
670                     _("%s: ignoring second macro expansion output `%s'.\n"),
671                     progname, optarg);
672          break;
673
674        case 'f': /* --fill-column */
675          if (sscanf (optarg, "%d", &fill_column) != 1)
676            {
677              fprintf (stderr,
678                       _("%s: %s arg must be numeric, not `%s'.\n"),
679                       progname, "--fill-column", optarg);
680              usage (1);
681            }
682          break;
683
684        case 'h': /* --help */
685          usage (0);
686          break;
687
688        case 'I':
689          /* Append user-specified dir to include file path. */
690          append_to_include_path (optarg);
691          break;
692
693        case 'i':
694          if (sscanf (optarg, "%d", &xml_indentation_increment) != 1)
695            {
696              fprintf (stderr,
697                     _("%s: %s arg must be numeric, not `%s'.\n"),
698                     progname, "--output-indent", optarg);
699              usage (1);
700            }
701          break;
702
703        case 'o': /* --output */
704          command_output_filename = xstrdup (optarg);
705          save_command_output_filename = command_output_filename;
706          break;
707
708        case 'p': /* --paragraph-indent */
709          if (set_paragraph_indent (optarg) < 0)
710            {
711              fprintf (stderr,
712   _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
713                       progname, optarg);
714              usage (1);
715            }
716          break;
717
718        case 'P':
719          /* Prepend user-specified include dir to include path. */
720          prepend_to_include_path (optarg);
721          break;
722
723        case 'r': /* --reference-limit */
724          if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
725            {
726              fprintf (stderr,
727                     _("%s: %s arg must be numeric, not `%s'.\n"),
728                     progname, "--reference-limit", optarg);
729              usage (1);
730            }
731          break;
732
733        case 's': /* --footnote-style */
734          if (set_footnote_style (optarg) < 0)
735            {
736              fprintf (stderr,
737        _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
738                       progname, optarg);
739              usage (1);
740            }
741          footnote_style_preset = 1;
742          break;
743
744        case 'S': /* --split-size */
745          if (sscanf (optarg, "%d", &split_size) != 1)
746            {
747              fprintf (stderr,
748                     _("%s: %s arg must be numeric, not `%s'.\n"),
749                     progname, "--split-size", optarg);
750              usage (1);
751            }
752          break;
753
754        case 't': /* --plaintext */
755          splitting = 0;
756          no_headers = 1;
757          html = 0;
758          docbook = 0;
759          xml = 0;
760          process_plaintext = 1;
761          break;
762
763        case 'v':
764          verbose_mode++;
765          break;
766
767        case 'V': /* --version */
768          print_version_info ();
769          puts ("");
770          puts ("Copyright (C) 2004 Free Software Foundation, Inc.");
771          printf (_("There is NO warranty.  You may redistribute this software\n\
772under the terms of the GNU General Public License.\n\
773For more information about these matters, see the files named COPYING.\n"));
774          xexit (0);
775          break;
776
777        case 'w': /* --html */
778          xml = 0;
779          docbook = 0;
780          html = 1;
781          process_html = 1;
782          break;
783
784        case 'x': /* --xml */
785          splitting = 0;
786          html = 0;
787          docbook = 0;
788          xml = 1;
789          process_xml = 1;
790          break;
791
792        case '?':
793          usage (1);
794          break;
795        }
796    }
797
798  if (macro_expansion_output_stream)
799    validating = 0;
800
801  if (!validating)
802    expensive_validation = 0;
803
804  if (optind == argc)
805    {
806      /* Check to see if input is a file.  If so, process that. */
807      if (!isatty (fileno (stdin)))
808        reading_from_stdin = 1;
809      else
810        {
811          fprintf (stderr, _("%s: missing file argument.\n"), progname);
812          usage (1);
813        }
814    }
815
816  if (no_headers)
817    {
818      /* If the user did not specify an output file, use stdout. */
819      if (!command_output_filename)
820        command_output_filename = xstrdup ("-");
821
822      if (html && splitting && !STREQ (command_output_filename, "-"))
823        { /* --no-headers --no-split --html indicates confusion. */
824          fprintf (stderr,
825                  "%s: can't split --html output to `%s' with --no-headers.\n",
826                   progname, command_output_filename);
827          usage (1);
828        }
829
830      /* --no-headers implies --no-split.  */
831      splitting = 0;
832    }
833
834  if (process_info == -1)
835    { /* no explicit --[no-]ifinfo option, so we'll do @ifinfo
836         if we're generating info or (for compatibility) plain text.  */
837      process_info = !html && !xml;
838    }
839
840  if (process_plaintext == -1)
841    { /* no explicit --[no-]ifplaintext option, so we'll do @ifplaintext
842         if we're generating plain text.  */
843      process_plaintext = no_headers && !html && !xml;
844    }
845
846  if (verbose_mode)
847    print_version_info ();
848
849  /* Remaining arguments are file names of texinfo files.
850     Convert them, one by one. */
851  if (!reading_from_stdin)
852    {
853      while (optind != argc)
854        convert_from_file (argv[optind++]);
855    }
856  else
857    convert_from_stream (stdin, "stdin");
858
859  xexit (errors_printed ? 2 : 0);
860  return 0; /* Avoid bogus warnings.  */
861}
862
863/* Hacking tokens and strings.  */
864
865/* Return the next token as a string pointer.  We cons the string.  This
866   `token' means simply a command name.  */
867
868/* = is so @alias works.  ^ and _ are so macros can be used in math mode
869   without a space following.  Possibly we should simply allow alpha, to
870   be compatible with TeX.  */
871#define COMMAND_CHAR(c) (!cr_or_whitespace(c) \
872                         && (c) != '{' \
873                         && (c) != '}' \
874                         && (c) != '=' \
875                         && (c) != '_' \
876                         && (c) != '^' \
877                         )
878
879static char *
880read_token (void)
881{
882  int i, character;
883  char *result;
884
885  /* If the first character to be read is self-delimiting, then that
886     is the command itself. */
887  character = curchar ();
888  if (self_delimiting (character))
889    {
890      input_text_offset++;
891
892      if (character == '\n')
893        line_number++;
894
895      result = xstrdup (" ");
896      *result = character;
897      return result;
898    }
899
900  for (i = 0; ((input_text_offset != input_text_length)
901               && (character = curchar ())
902               && COMMAND_CHAR (character));
903       i++, input_text_offset++);
904  result = xmalloc (i + 1);
905  memcpy (result, &input_text[input_text_offset - i], i);
906  result[i] = 0;
907  return result;
908}
909
910/* Return nonzero if CHARACTER is self-delimiting. */
911int
912self_delimiting (int character)
913{
914  /* @; and @\ are not Texinfo commands, but they are listed here
915     anyway.  I don't know why.  --karl, 10aug96.  */
916  return strchr ("~{|}`^\\@?=;:./-,*\'\" !\n\t", character) != NULL;
917}
918
919/* Clear whitespace from the front and end of string. */
920void
921canon_white (char *string)
922{
923  char *p = string;
924  unsigned len;
925
926  if (!*p)
927    return;
928
929  do
930    {
931      if (!cr_or_whitespace (*p))
932	break;
933      ++p;
934    }
935  while (*p);
936
937  len = strlen (p);
938  while (len && cr_or_whitespace (p[len-1]))
939    --len;
940
941  if (p != string)
942    memmove (string, p, len);
943
944  string[len] = 0;
945}
946
947/* Bash STRING, replacing all whitespace with just one space. */
948void
949fix_whitespace (char *string)
950{
951  char *temp = xmalloc (strlen (string) + 1);
952  int string_index = 0;
953  int temp_index = 0;
954  int c;
955
956  canon_white (string);
957
958  while (string[string_index])
959    {
960      c = temp[temp_index++] = string[string_index++];
961
962      if (c == ' ' || c == '\n' || c == '\t')
963        {
964          temp[temp_index - 1] = ' ';
965          while ((c = string[string_index]) && (c == ' ' ||
966                                                c == '\t' ||
967                                                c == '\n'))
968            string_index++;
969        }
970    }
971  temp[temp_index] = 0;
972  strcpy (string, temp);
973  free (temp);
974}
975
976/* Discard text until the desired string is found.  The string is
977   included in the discarded text. */
978void
979discard_until (char *string)
980{
981  int temp = search_forward (string, input_text_offset);
982
983  int tt = (temp < 0) ? input_text_length : temp + strlen (string);
984  int from = input_text_offset;
985
986  /* Find out what line we are on. */
987  while (from != tt)
988    if (input_text[from++] == '\n')
989      line_number++;
990
991  if (temp < 0)
992    {
993      /* not found, move current position to end of string */
994      input_text_offset = input_text_length;
995      if (strcmp (string, "\n") != 0)
996        { /* Give a more descriptive feedback, if we are looking for ``@end ''
997             during macro execution.  That means someone used a multiline
998             command as an argument to, say, @section ... style commands.  */
999          char *end_block = xmalloc (8);
1000          sprintf (end_block, "\n%cend ", COMMAND_PREFIX);
1001          if (executing_string && strstr (string, end_block))
1002            line_error (_("Multiline command %c%s used improperly"),
1003                COMMAND_PREFIX, command);
1004          else
1005            line_error (_("Expected `%s'"), string);
1006          free (end_block);
1007          return;
1008        }
1009    }
1010  else
1011    /* found, move current position to after the found string */
1012    input_text_offset = temp + strlen (string);
1013}
1014
1015/* Read characters from the file until we are at MATCH.
1016   Place the characters read into STRING.
1017   On exit input_text_offset is after the match string.
1018   Return the offset where the string starts. */
1019int
1020get_until (char *match, char **string)
1021{
1022  int len, current_point, x, new_point, tem;
1023
1024  current_point = x = input_text_offset;
1025  new_point = search_forward (match, input_text_offset);
1026
1027  if (new_point < 0)
1028    new_point = input_text_length;
1029  len = new_point - current_point;
1030
1031  /* Keep track of which line number we are at. */
1032  tem = new_point + (strlen (match) - 1);
1033  while (x != tem)
1034    if (input_text[x++] == '\n')
1035      line_number++;
1036
1037  *string = xmalloc (len + 1);
1038
1039  memcpy (*string, &input_text[current_point], len);
1040  (*string)[len] = 0;
1041
1042  /* Now leave input_text_offset in a consistent state. */
1043  input_text_offset = tem;
1044
1045  if (input_text_offset > input_text_length)
1046    input_text_offset = input_text_length;
1047
1048  return new_point;
1049}
1050
1051/* Replace input_text[FROM .. TO] with its expansion.  */
1052void
1053replace_with_expansion (int from, int *to)
1054{
1055  char *xp;
1056  unsigned xp_len, new_len;
1057  char *old_input = input_text;
1058  unsigned raw_len = *to - from;
1059  char *str;
1060
1061  /* The rest of the code here moves large buffers, so let's
1062     not waste time if the input cannot possibly expand
1063     into anything.  Unfortunately, we cannot avoid expansion
1064     when we see things like @code etc., even if they only
1065     asked for expansion of macros, since any Texinfo command
1066     can be potentially redefined with a macro.  */
1067  if (only_macro_expansion &&
1068      memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
1069    return;
1070
1071  /* Get original string from input.  */
1072  str = xmalloc (raw_len + 1);
1073  memcpy (str, input_text + from, raw_len);
1074  str[raw_len] = 0;
1075
1076  /* We are going to relocate input_text, so we had better output
1077     pending portion of input_text now, before the pointer changes.  */
1078  if (macro_expansion_output_stream && !executing_string
1079      && !me_inhibit_expansion)
1080    append_to_expansion_output (from);
1081
1082  /* Expand it.  */
1083  xp = expansion (str, 0);
1084  xp_len = strlen (xp);
1085  free (str);
1086
1087  /* Plunk the expansion into the middle of `input_text' --
1088     which is terminated by a newline, not a null.  Avoid
1089     expensive move of the rest of the input if the expansion
1090     has the same length as the original string.  */
1091  if (xp_len != raw_len)
1092    {
1093      new_len = from + xp_len + input_text_length - *to + 1;
1094      if (executing_string)
1095        { /* If we are in execute_string, we might need to update
1096             the relevant element in the execution_strings[] array,
1097             since it could have to be relocated from under our
1098             feet.  (input_text is reallocated here as well, if needed.)  */
1099          maybe_update_execution_strings (&input_text, new_len);
1100        }
1101      else if (new_len > input_text_length + 1)
1102        /* Don't bother to realloc if we have enough space.  */
1103        input_text = xrealloc (input_text, new_len);
1104
1105      memmove (input_text + from + xp_len,
1106               input_text + *to, input_text_length - *to + 1);
1107
1108      *to += xp_len - raw_len;
1109      /* Since we change input_text_length here, the comparison above
1110         isn't really valid, but it seems the worst that might happen is
1111         an extra xrealloc or two, so let's not worry.  */
1112      input_text_length += xp_len - raw_len;
1113    }
1114  memcpy (input_text + from, xp, xp_len);
1115  free (xp);
1116
1117  /* Synchronize the macro-expansion pointers with our new input_text.  */
1118  if (input_text != old_input)
1119    forget_itext (old_input);
1120  if (macro_expansion_output_stream && !executing_string)
1121    remember_itext (input_text, from);
1122}
1123
1124/* Read characters from the file until we are at MATCH or end of line.
1125   Place the characters read into STRING.  If EXPAND is nonzero,
1126   expand the text before looking for MATCH for those cases where
1127   MATCH might be produced by some macro.  */
1128void
1129get_until_in_line (int expand, char *match, char **string)
1130{
1131  int real_bottom = input_text_length;
1132  int limit = search_forward ("\n", input_text_offset);
1133  if (limit < 0)
1134    limit = input_text_length;
1135
1136  /* Replace input_text[input_text_offset .. limit-1] with its expansion.
1137     This allows the node names and menu entries themselves to be
1138     constructed via a macro, as in:
1139        @macro foo{p, q}
1140        Together: \p\ & \q\.
1141        @end macro
1142
1143        @node @foo{A,B}, next, prev, top
1144
1145     Otherwise, the `,' separating the macro args A and B is taken as
1146     the node argument separator, so the node name is `@foo{A'.  This
1147     expansion is only necessary on the first call, since we expand the
1148     whole line then.  */
1149  if (expand)
1150    {
1151      replace_with_expansion (input_text_offset, &limit);
1152    }
1153
1154  real_bottom = input_text_length;
1155  input_text_length = limit;
1156  get_until (match, string);
1157  input_text_length = real_bottom;
1158}
1159
1160void
1161get_rest_of_line (int expand, char **string)
1162{
1163  xml_no_para ++;
1164  if (expand)
1165    {
1166      char *tem;
1167
1168      /* Don't expand non-macros in input, since we want them
1169         intact in the macro-expanded output.  */
1170      only_macro_expansion++;
1171      get_until_in_line (1, "\n", &tem);
1172      only_macro_expansion--;
1173      *string = expansion (tem, 0);
1174      free (tem);
1175    }
1176  else
1177    get_until_in_line (0, "\n", string);
1178
1179  canon_white (*string);
1180
1181  if (curchar () == '\n')       /* as opposed to the end of the file... */
1182    {
1183      line_number++;
1184      input_text_offset++;
1185    }
1186  xml_no_para --;
1187}
1188
1189/* Backup the input pointer to the previous character, keeping track
1190   of the current line number. */
1191void
1192backup_input_pointer (void)
1193{
1194  if (input_text_offset)
1195    {
1196      input_text_offset--;
1197      if (curchar () == '\n')
1198        line_number--;
1199    }
1200}
1201
1202/* Read characters from the file until we are at MATCH or closing brace.
1203   Place the characters read into STRING.  */
1204void
1205get_until_in_braces (char *match, char **string)
1206{
1207  char *temp;
1208  int i, brace = 0;
1209  int match_len = strlen (match);
1210
1211  for (i = input_text_offset; i < input_text_length; i++)
1212    {
1213      if (i < input_text_length - 1 && input_text[i] == '@')
1214        {
1215          i++;                  /* skip commands like @, and @{ */
1216          continue;
1217        }
1218      else if (input_text[i] == '{')
1219        brace++;
1220      else if (input_text[i] == '}')
1221        {
1222          brace--;
1223          /* If looking for a brace, don't stop at the interior brace,
1224             like after "baz" in "@foo{something @bar{baz} more}".  */
1225          if (brace == 0)
1226            continue;
1227        }
1228      else if (input_text[i] == '\n')
1229        line_number++;
1230
1231      if (brace < 0 ||
1232          (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1233        break;
1234    }
1235
1236  match_len = i - input_text_offset;
1237  temp = xmalloc (2 + match_len);
1238  memcpy (temp, input_text + input_text_offset, match_len);
1239  temp[match_len] = 0;
1240  input_text_offset = i;
1241  *string = temp;
1242}
1243
1244
1245
1246/* Converting a file.  */
1247
1248/* Convert the file named by NAME.  The output is saved on the file
1249   named as the argument to the @setfilename command. */
1250static char *suffixes[] = {
1251  /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1252     have "texinfo.txi" and "texinfo.tex" in the same directory, the
1253     former is used rather than the latter, due to file name truncation.  */
1254  ".txi",
1255  ".texinfo",
1256  ".texi",
1257  ".txinfo",
1258  "",
1259  NULL
1260};
1261
1262static void
1263initialize_conversion (void)
1264{
1265  init_tag_table ();
1266  init_indices ();
1267  init_internals ();
1268  init_paragraph ();
1269
1270  /* This is used for splitting the output file and for doing section
1271     headings.  It was previously initialized in `init_paragraph', but its
1272     use there loses with the `init_paragraph' calls done by the
1273     multitable code; the tag indices get reset to zero.  */
1274  output_position = 0;
1275}
1276
1277/* Reverse the chain of structures in LIST.  Output the new head
1278   of the chain.  You should always assign the output value of this
1279   function to something, or you will lose the chain. */
1280GENERIC_LIST *
1281reverse_list (GENERIC_LIST *list)
1282{
1283  GENERIC_LIST *next;
1284  GENERIC_LIST *prev = NULL;
1285
1286  while (list)
1287    {
1288      next = list->next;
1289      list->next = prev;
1290      prev = list;
1291      list = next;
1292    }
1293  return prev;
1294}
1295
1296/* We read in multiples of 4k, simply because it is a typical pipe size
1297   on unix systems. */
1298#define READ_BUFFER_GROWTH (4 * 4096)
1299
1300/* Convert the Texinfo file coming from the open stream STREAM.  Assume the
1301   source of the stream is named NAME. */
1302static void
1303convert_from_stream (FILE *stream, char *name)
1304{
1305  char *buffer = NULL;
1306  int buffer_offset = 0, buffer_size = 0;
1307
1308  initialize_conversion ();
1309
1310  /* Read until the end of the stream.  This isn't strictly correct, since
1311     the texinfo input may end before the stream ends, but it is a quick
1312     working hueristic. */
1313  while (!feof (stream))
1314    {
1315      int count;
1316
1317      if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1318        buffer = (char *)
1319          xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1320
1321      count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1322
1323      if (count < 0)
1324        {
1325          perror (name);
1326          xexit (1);
1327        }
1328
1329      buffer_offset += count;
1330      if (count == 0)
1331        break;
1332    }
1333
1334  /* Set the globals to the new file. */
1335  input_text = buffer;
1336  input_text_length = buffer_offset;
1337  input_filename = xstrdup (name);
1338  node_filename = xstrdup (name);
1339  input_text_offset = 0;
1340  line_number = 1;
1341
1342  /* Not strictly necessary.  This magic prevents read_token () from doing
1343     extra unnecessary work each time it is called (that is a lot of times).
1344     The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1345  input_text[input_text_length] = '\n';
1346
1347  convert_from_loaded_file (name);
1348}
1349
1350static void
1351convert_from_file (char *name)
1352{
1353  int i;
1354  char *filename = xmalloc (strlen (name) + 50);
1355
1356  /* Prepend file directory to the search path, so relative links work.  */
1357  prepend_to_include_path (pathname_part (name));
1358
1359  initialize_conversion ();
1360
1361  /* Try to load the file specified by NAME, concatenated with our
1362     various suffixes.  Prefer files like `makeinfo.texi' to
1363     `makeinfo'.  */
1364  for (i = 0; suffixes[i]; i++)
1365    {
1366      strcpy (filename, name);
1367      strcat (filename, suffixes[i]);
1368
1369      if (find_and_load (filename, 1))
1370        break;
1371
1372      if (!suffixes[i][0] && strrchr (filename, '.'))
1373        {
1374          fs_error (filename);
1375          free (filename);
1376          return;
1377        }
1378    }
1379
1380  if (!suffixes[i])
1381    {
1382      fs_error (name);
1383      free (filename);
1384      return;
1385    }
1386
1387  input_filename = filename;
1388
1389  convert_from_loaded_file (name);
1390
1391  /* Pop the prepended path, so multiple filenames in the
1392     command line do not screw each others include paths.  */
1393  pop_path_from_include_path ();
1394}
1395
1396static int
1397create_html_directory (char *dir, int can_remove_file)
1398{
1399  struct stat st;
1400
1401  /* Already exists.  */
1402  if (stat (dir, &st) == 0)
1403    {
1404      /* And it's a directory, so silently reuse it.  */
1405      if (S_ISDIR (st.st_mode))
1406        return 1;
1407      /* Not a directory, so move it out of the way if we are allowed.  */
1408      else if (can_remove_file)
1409        {
1410          if (unlink (dir) != 0)
1411            return 0;
1412        }
1413      else
1414        return 0;
1415    }
1416
1417  if (mkdir (dir, 0777) == 0)
1418    /* Success!  */
1419    return 1;
1420  else
1421    return 0;
1422}
1423
1424/* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
1425   "/foo/bar/baz/baz.html".  This routine is called only if html && splitting.
1426
1427  Split html output goes into the subdirectory of the toplevel
1428  filename, without extension.  For example:
1429      @setfilename foo.info
1430  produces output in files foo/index.html, foo/second-node.html, ...
1431
1432  But if the user said -o foo.whatever on the cmd line, then use
1433  foo.whatever unchanged.  */
1434
1435static char *
1436insert_toplevel_subdirectory (char *output_filename)
1437{
1438  static const char index_name[] = "index.html";
1439  char *dir, *subdir, *base, *basename, *p;
1440  char buf[PATH_MAX];
1441  const int index_len = sizeof (index_name) - 1;
1442
1443  strcpy (buf, output_filename);
1444  dir = pathname_part (buf);   /* directory of output_filename */
1445  base = filename_part (buf);  /* strips suffix, too */
1446  basename = xstrdup (base);   /* remember real @setfilename name */
1447  p = dir + strlen (dir) - 1;
1448  if (p > dir && IS_SLASH (*p))
1449    *p = 0;
1450  p = strrchr (base, '.');
1451  if (p)
1452    *p = 0;
1453
1454  /* Split html output goes into subdirectory of toplevel name. */
1455  if (save_command_output_filename
1456      && STREQ (output_filename, save_command_output_filename))
1457    subdir = basename;  /* from user, use unchanged */
1458  else
1459    subdir = base;      /* implicit, omit suffix */
1460
1461  free (output_filename);
1462  output_filename = xmalloc (strlen (dir) + 1
1463                             + strlen (basename) + 1
1464                             + index_len
1465                             + 1);
1466  strcpy (output_filename, dir);
1467  if (strlen (dir))
1468    strcat (output_filename, "/");
1469  strcat (output_filename, subdir);
1470
1471  /* First try, do not remove existing file.  */
1472  if (!create_html_directory (output_filename, 0))
1473    {
1474      /* That failed, try subdir name with .html.
1475         Remove it if it exists.  */
1476      strcpy (output_filename, dir);
1477      if (strlen (dir))
1478        strcat (output_filename, "/");
1479      strcat (output_filename, basename);
1480
1481      if (!create_html_directory (output_filename, 1))
1482        {
1483          /* Last try failed too :-\  */
1484          line_error (_("Can't create directory `%s': %s"),
1485              output_filename, strerror (errno));
1486          xexit (1);
1487        }
1488    }
1489
1490  strcat (output_filename, "/");
1491  strcat (output_filename, index_name);
1492  return output_filename;
1493}
1494
1495/* FIXME: this is way too hairy */
1496static void
1497convert_from_loaded_file (char *name)
1498{
1499  char *real_output_filename = NULL;
1500
1501  remember_itext (input_text, 0);
1502
1503  input_text_offset = 0;
1504
1505  /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1506     the file).  */
1507  if (looking_at ("\\input"))
1508    discard_until ("\n");
1509
1510  /* Search this file looking for the special string which starts conversion.
1511     Once found, we may truly begin. */
1512  while (input_text_offset >= 0)
1513    {
1514      input_text_offset =
1515        search_forward (setfilename_search, input_text_offset);
1516
1517      if (input_text_offset == 0
1518          || (input_text_offset > 0
1519              && input_text[input_text_offset -1] == '\n'))
1520        break;
1521      else if (input_text_offset > 0)
1522        input_text_offset++;
1523    }
1524
1525  if (input_text_offset < 0)
1526    {
1527      if (!command_output_filename)
1528        {
1529#if defined (REQUIRE_SETFILENAME)
1530          error (_("No `%s' found in `%s'"), setfilename_search, name);
1531          goto finished;
1532#else
1533          command_output_filename = output_name_from_input_name (name);
1534#endif /* !REQUIRE_SETFILENAME */
1535        }
1536
1537      {
1538        int i, end_of_first_line;
1539
1540        /* Find the end of the first line in the file. */
1541        for (i = 0; i < input_text_length - 1; i++)
1542          if (input_text[i] == '\n')
1543            break;
1544
1545        end_of_first_line = i + 1;
1546
1547        for (i = 0; i < end_of_first_line; i++)
1548          {
1549            if ((input_text[i] == '\\') &&
1550                (strncmp (input_text + i + 1, "input", 5) == 0))
1551              {
1552                input_text_offset = i;
1553                break;
1554              }
1555          }
1556      }
1557    }
1558  else
1559    input_text_offset += strlen (setfilename_search);
1560
1561  if (!command_output_filename)
1562    {
1563      get_until ("\n", &output_filename); /* read rest of line */
1564      if (html || xml)
1565        { /* Change any extension to .html or .xml.  */
1566          char *html_name, *directory_part, *basename_part, *temp;
1567
1568          canon_white (output_filename);
1569          directory_part = pathname_part (output_filename);
1570
1571          basename_part = filename_part (output_filename);
1572
1573          /* Zap any existing extension.  */
1574          temp = strrchr (basename_part, '.');
1575          if (temp)
1576            *temp = 0;
1577
1578          /* Construct new filename.  */
1579          html_name = xmalloc (strlen (directory_part)
1580                               + strlen (basename_part) + 6);
1581          strcpy (html_name, directory_part);
1582          strcat (html_name, basename_part);
1583          strcat (html_name, html ? ".html" : ".xml");
1584
1585          /* Replace name from @setfilename with the html name.  */
1586          free (output_filename);
1587          output_filename = html_name;
1588        }
1589    }
1590  else
1591    {
1592      if (input_text_offset != -1)
1593        discard_until ("\n");
1594      else
1595        input_text_offset = 0;
1596
1597      real_output_filename = output_filename = command_output_filename;
1598      command_output_filename = NULL;  /* for included files or whatever */
1599    }
1600
1601  canon_white (output_filename);
1602  toplevel_output_filename = xstrdup (output_filename);
1603
1604  if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1605    {
1606      if (macro_expansion_filename
1607          && strcmp (macro_expansion_filename, "-") == 0)
1608        {
1609          fprintf (stderr,
1610  _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1611                   progname);
1612          macro_expansion_output_stream = NULL;
1613        }
1614      real_output_filename = xstrdup (real_output_filename);
1615      output_stream = stdout;
1616      splitting = 0;            /* Cannot split when writing to stdout. */
1617    }
1618  else
1619    {
1620      if (html && splitting)
1621        {
1622          if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
1623              || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
1624            splitting = 0;
1625          else
1626            output_filename = insert_toplevel_subdirectory (output_filename);
1627          real_output_filename = xstrdup (output_filename);
1628        }
1629      else if (!real_output_filename)
1630        real_output_filename = expand_filename (output_filename, name);
1631      else
1632        real_output_filename = xstrdup (real_output_filename);
1633
1634      output_stream = fopen (real_output_filename, "w");
1635    }
1636
1637  set_current_output_filename (real_output_filename);
1638
1639  if (xml && !docbook)
1640    xml_begin_document (filename_part (output_filename));
1641
1642  if (verbose_mode)
1643    printf (_("Making %s file `%s' from `%s'.\n"),
1644            no_headers ? "text"
1645            : html ? "HTML"
1646            : xml ? "XML"
1647            : "info",
1648            output_filename, input_filename);
1649
1650  if (output_stream == NULL)
1651    {
1652      fs_error (real_output_filename);
1653      goto finished;
1654    }
1655
1656  /* Make the displayable filename from output_filename.  Only the base
1657     portion of the filename need be displayed. */
1658  flush_output ();              /* in case there was no @bye */
1659  if (output_stream != stdout)
1660    pretty_output_filename = filename_part (output_filename);
1661  else
1662    pretty_output_filename = xstrdup ("stdout");
1663
1664  /* For this file only, count the number of newlines from the top of
1665     the file to here.  This way, we keep track of line numbers for
1666     error reporting.  Line_number starts at 1, since the user isn't
1667     zero-based. */
1668  {
1669    int temp = 0;
1670    line_number = 1;
1671    while (temp != input_text_offset)
1672      if (input_text[temp++] == '\n')
1673        line_number++;
1674  }
1675
1676  /* html fixxme: should output this as trailer on first page.  */
1677  if (!no_headers && !html && !xml && !no_version_header)
1678    add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
1679                   output_filename, VERSION, input_filename);
1680
1681  close_paragraph ();
1682
1683  if (xml && !docbook)
1684    {
1685      /* Just before the real main loop, let's handle the defines.  */
1686      COMMAND_LINE_DEFINE *temp;
1687
1688      for (temp = command_line_defines; temp; temp = temp->next)
1689        {
1690          handle_variable_internal (temp->action, temp->define);
1691          free(temp->define);
1692        }
1693    }
1694
1695  reader_loop ();
1696  if (xml)
1697    xml_end_document ();
1698
1699
1700finished:
1701  discard_insertions (0);
1702  close_paragraph ();
1703  flush_file_stack ();
1704
1705  if (macro_expansion_output_stream)
1706    {
1707      fclose (macro_expansion_output_stream);
1708      if (errors_printed && !force
1709          && strcmp (macro_expansion_filename, "-") != 0
1710          && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1711          && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1712        {
1713          fprintf (stderr,
1714_("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1715                   progname, macro_expansion_filename);
1716          if (unlink (macro_expansion_filename) < 0)
1717            perror (macro_expansion_filename);
1718        }
1719    }
1720
1721  if (output_stream)
1722    {
1723      output_pending_notes ();
1724
1725      if (html)
1726        {
1727          no_indent = 1;
1728          start_paragraph ();
1729          add_word ("</body></html>\n");
1730          close_paragraph ();
1731        }
1732
1733      /* maybe we want local variables in info output.  */
1734      {
1735        char *trailer = info_trailer ();
1736	if (!xml && !docbook && trailer)
1737          {
1738            if (html)
1739              insert_string ("<!--");
1740            insert_string (trailer);
1741            free (trailer);
1742            if (html)
1743              insert_string ("\n-->\n");
1744          }
1745      }
1746
1747      /* Write stuff makeinfo generates after @bye, ie. info_trailer.  */
1748      flush_output ();
1749
1750      if (output_stream != stdout)
1751        fclose (output_stream);
1752
1753      /* If validating, then validate the entire file right now. */
1754      if (validating)
1755        validate_file (tag_table);
1756
1757      handle_delayed_writes ();
1758
1759      if (tag_table)
1760        {
1761          tag_table = (TAG_ENTRY *) reverse_list ((GENERIC_LIST *) tag_table);
1762          if (!no_headers && !html && !STREQ (current_output_filename, "-"))
1763            write_tag_table (real_output_filename);
1764        }
1765
1766      if (splitting && !html && (!errors_printed || force))
1767        {
1768          clean_old_split_files (real_output_filename);
1769          split_file (real_output_filename, split_size);
1770        }
1771      else if (errors_printed
1772               && !force
1773               && strcmp (real_output_filename, "-") != 0
1774               && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1775               && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1776        { /* If there were errors, and no --force, remove the output.  */
1777          fprintf (stderr,
1778  _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1779                   progname, real_output_filename);
1780          if (unlink (real_output_filename) < 0)
1781            perror (real_output_filename);
1782        }
1783    }
1784  free (real_output_filename);
1785}
1786
1787/* If enable_encoding is set and @documentencoding is used, return a
1788   Local Variables section (as a malloc-ed string) so that Emacs'
1789   locale features can work.  Else return NULL.  */
1790char *
1791info_trailer (void)
1792{
1793  char *encoding;
1794
1795  if (!enable_encoding)
1796    return NULL;
1797
1798  encoding = current_document_encoding ();
1799
1800  if (encoding && *encoding)
1801    {
1802#define LV_FMT "\n\037\nLocal Variables:\ncoding: %s\nEnd:\n"
1803      char *lv = xmalloc (sizeof (LV_FMT) + strlen (encoding));
1804      sprintf (lv, LV_FMT, encoding);
1805      free (encoding);
1806      return lv;
1807    }
1808
1809  free (encoding);
1810  return NULL;
1811}
1812
1813void
1814free_and_clear (char **pointer)
1815{
1816  if (*pointer)
1817    {
1818      free (*pointer);
1819      *pointer = NULL;
1820    }
1821}
1822
1823 /* Initialize some state. */
1824static void
1825init_internals (void)
1826{
1827  free_and_clear (&output_filename);
1828  free_and_clear (&command);
1829  free_and_clear (&input_filename);
1830  free_node_references ();
1831  free_node_node_references ();
1832  toc_free ();
1833  init_insertion_stack ();
1834  init_brace_stack ();
1835  current_node = NULL; /* sometimes already freed */
1836  command_index = 0;
1837  in_menu = 0;
1838  in_detailmenu = 0;
1839  top_node_seen = 0;
1840  non_top_node_seen = 0;
1841  node_number = -1;
1842}
1843
1844void
1845init_paragraph (void)
1846{
1847  free (output_paragraph);
1848  output_paragraph = xmalloc (paragraph_buffer_len);
1849  output_paragraph[0] = 0;
1850  output_paragraph_offset = 0;
1851  output_column = 0;
1852  paragraph_is_open = 0;
1853  current_indent = 0;
1854  meta_char_pos = 0;
1855}
1856
1857/* This is called from `reader_loop' when we are at the * beginning a
1858   menu line.  */
1859
1860static void
1861handle_menu_entry (void)
1862{
1863  char *tem;
1864
1865  /* Ugh, glean_node_from_menu wants to read the * itself.  */
1866  input_text_offset--;
1867
1868  /* Find node name in menu entry and save it in references list for
1869     later validation.  Use followed_reference type for detailmenu
1870     references since we don't want to use them for default node pointers.  */
1871  tem = glean_node_from_menu (1, in_detailmenu
1872                                 ? followed_reference : menu_reference);
1873
1874  if (html && tem)
1875    { /* Start a menu item with the cleaned-up line.  Put an anchor
1876         around the start text (before `:' or the node name). */
1877      char *string;
1878
1879      discard_until ("* ");
1880
1881      /* The line number was already incremented in reader_loop when we
1882         saw the newline, and discard_until has now incremented again.  */
1883      line_number--;
1884
1885      if (had_menu_commentary)
1886        {
1887          add_html_block_elt ("<ul class=\"menu\">\n");
1888          had_menu_commentary = 0;
1889          in_paragraph = 0;
1890        }
1891
1892      if (in_paragraph)
1893        {
1894          add_html_block_elt ("</p>\n");
1895          add_html_block_elt ("<ul class=\"menu\">\n");
1896          in_paragraph = 0;
1897        }
1898
1899      in_menu_item = 1;
1900
1901      add_html_block_elt ("<li><a");
1902      if (next_menu_item_number <= 9)
1903        {
1904          add_word(" accesskey=");
1905          add_word_args("\"%d\"", next_menu_item_number);
1906          next_menu_item_number++;
1907        }
1908      add_word (" href=\"");
1909      string = expansion (tem, 0);
1910      add_anchor_name (string, 1);
1911      add_word ("\">");
1912      free (string);
1913
1914      /* The menu item may use macros, so expand them now.  */
1915      only_macro_expansion++;
1916      get_until_in_line (1, ":", &string);
1917      only_macro_expansion--;
1918      execute_string ("%s", string); /* get escaping done */
1919      free (string);
1920
1921      add_word ("</a>");
1922
1923      if (looking_at ("::"))
1924        discard_until (":");
1925      else
1926        { /* discard the node name */
1927          get_until_in_line (0, ".", &string);
1928          free (string);
1929        }
1930      input_text_offset++;      /* discard the second colon or the period */
1931
1932      /* Insert a colon only if there is a description of this menu item.  */
1933      {
1934        int save_input_text_offset = input_text_offset;
1935        int save_line_number = line_number;
1936        char *test_string;
1937        get_rest_of_line (0, &test_string);
1938        if (strlen (test_string) > 0)
1939          add_word (": ");
1940        input_text_offset = save_input_text_offset;
1941        line_number = save_line_number;
1942      }
1943    }
1944  else if (xml && tem)
1945    {
1946      xml_start_menu_entry (tem);
1947    }
1948  else if (tem)
1949    { /* For Info output, we can just use the input and the main case in
1950         reader_loop where we output what comes in.  Just move off the *
1951         so the next time through reader_loop we don't end up back here.  */
1952      add_char ('*');
1953      input_text_offset += 2; /* undo the pointer back-up above.  */
1954    }
1955
1956  if (tem)
1957    free (tem);
1958}
1959
1960/* Find the command corresponding to STRING.  If the command is found,
1961   return a pointer to the data structure.  Otherwise return -1.  */
1962static COMMAND *
1963get_command_entry (char *string)
1964{
1965  int i;
1966
1967  for (i = 0; command_table[i].name; i++)
1968    if (strcmp (command_table[i].name, string) == 0)
1969      return &command_table[i];
1970
1971  /* This command is not in our predefined command table.  Perhaps
1972     it is a user defined command. */
1973  for (i = 0; i < user_command_array_len; i++)
1974    if (user_command_array[i] &&
1975        (strcmp (user_command_array[i]->name, string) == 0))
1976      return user_command_array[i];
1977
1978  /* We never heard of this command. */
1979  return (COMMAND *) -1;
1980}
1981
1982/* input_text_offset is right at the command prefix character.
1983   Read the next token to determine what to do.  Return zero
1984   if there's no known command or macro after the prefix character.  */
1985static int
1986read_command (void)
1987{
1988  COMMAND *entry;
1989  int old_text_offset = input_text_offset++;
1990
1991  free_and_clear (&command);
1992  command = read_token ();
1993
1994  /* Check to see if this command is a macro.  If so, execute it here. */
1995  {
1996    MACRO_DEF *def;
1997
1998    def = find_macro (command);
1999
2000    if (def)
2001      {
2002        /* We disallow recursive use of a macro call.  Inhibit the expansion
2003           of this macro during the life of its execution. */
2004        if (!(def->flags & ME_RECURSE))
2005          def->inhibited = 1;
2006
2007        executing_macro++;
2008        execute_macro (def);
2009        executing_macro--;
2010
2011        if (!(def->flags & ME_RECURSE))
2012          def->inhibited = 0;
2013
2014        return 1;
2015      }
2016  }
2017
2018  if (only_macro_expansion)
2019    {
2020      /* Back up to the place where we were called, so the
2021         caller will have a chance to process this non-macro.  */
2022      input_text_offset = old_text_offset;
2023      return 0;
2024    }
2025
2026  /* Perform alias expansion */
2027  command = alias_expand (command);
2028
2029  if (enclosure_command (command))
2030    {
2031      remember_brace (enclosure_expand);
2032      enclosure_expand (START, output_paragraph_offset, 0);
2033      return 0;
2034    }
2035
2036  entry = get_command_entry (command);
2037  if (entry == (COMMAND *)-1)
2038    {
2039      line_error (_("Unknown command `%s'"), command);
2040      return 0;
2041    }
2042
2043  if (entry->argument_in_braces == BRACE_ARGS)
2044    remember_brace (entry->proc);
2045  else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
2046    {
2047      if (curchar () == '{')
2048        remember_brace (entry->proc);
2049      else
2050        { /* No braces, so arg is next char.  */
2051          int ch;
2052          int saved_offset = output_paragraph_offset;
2053          (*(entry->proc)) (START, output_paragraph_offset, 0);
2054
2055          /* Possibilities left for the next character: @ (error), }
2056             (error), whitespace (skip) anything else (normal char).  */
2057          skip_whitespace ();
2058          ch = curchar ();
2059          if (ch == '@')
2060            {
2061           line_error (_("Use braces to give a command as an argument to @%s"),
2062               entry->name);
2063              return 0;
2064            }
2065          else if (ch == '}')
2066            {
2067              /* Our caller will give the error message, because this }
2068                 won't match anything.  */
2069              return 0;
2070            }
2071
2072          add_char (ch);
2073          input_text_offset++;
2074          (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
2075          return 1;
2076        }
2077    }
2078
2079  /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
2080     with braces.  */
2081  (*(entry->proc)) (START, output_paragraph_offset, 0);
2082  return 1;
2083}
2084
2085/* Okay, we are ready to start the conversion.  Call the reader on
2086   some text, and fill the text as it is output.  Handle commands by
2087   remembering things like open braces and the current file position on a
2088   stack, and when the corresponding close brace is found, you can call
2089   the function with the proper arguments.  Although the filling isn't
2090   necessary for HTML, it should do no harm.  */
2091void
2092reader_loop (void)
2093{
2094  int character;
2095  int done = 0;
2096
2097  while (!done)
2098    {
2099      if (input_text_offset >= input_text_length)
2100        break;
2101
2102      character = curchar ();
2103
2104      /* If only_macro_expansion, only handle macros and leave
2105         everything else intact.  */
2106      if (!only_macro_expansion && !in_fixed_width_font
2107          && ((!html && !xml) || escape_html)
2108          && (character == '\'' || character == '`')
2109          && input_text[input_text_offset + 1] == character)
2110        {
2111          if (html)
2112            {
2113              input_text_offset += 2;
2114              add_word (character == '`' ? "&ldquo;" : "&rdquo;");
2115              continue;
2116            }
2117          else if (xml)
2118            {
2119              input_text_offset += 2;
2120              xml_insert_entity (character == '`' ? "ldquo" : "rdquo");
2121              continue;
2122            }
2123          else
2124            {
2125              input_text_offset++;
2126              character = '"';
2127            }
2128        }
2129
2130      /* Convert --- to --.  */
2131      if (!only_macro_expansion && character == '-' && !in_fixed_width_font
2132          && ((!html && !xml) || escape_html))
2133        {
2134          int dash_count = 0;
2135
2136          /* Get the number of consequtive dashes.  */
2137          while (input_text[input_text_offset] == '-')
2138            {
2139              dash_count++;
2140              input_text_offset++;
2141            }
2142
2143          /* Eat one dash.  */
2144          dash_count--;
2145
2146          if (html || xml)
2147            {
2148              if (dash_count == 0)
2149                add_char ('-');
2150              else
2151                while (dash_count > 0)
2152                  {
2153                    if (dash_count >= 2)
2154                      {
2155                        if (html)
2156                          add_word ("&mdash;");
2157                        else
2158                          xml_insert_entity ("mdash");
2159                        dash_count -= 2;
2160                      }
2161                    else if (dash_count >= 1)
2162                      {
2163                        if (html)
2164                          add_word ("&ndash;");
2165                        else
2166                          xml_insert_entity ("ndash");
2167                        dash_count--;
2168                      }
2169                  }
2170            }
2171          else
2172            {
2173              add_char ('-');
2174              while (--dash_count > 0)
2175                add_char ('-');
2176            }
2177
2178          continue;
2179        }
2180
2181      /* If this is a whitespace character, then check to see if the line
2182         is blank.  If so, advance to the carriage return. */
2183      if (!only_macro_expansion && whitespace (character))
2184        {
2185          int i = input_text_offset + 1;
2186
2187          while (i < input_text_length && whitespace (input_text[i]))
2188            i++;
2189
2190          if (i == input_text_length || input_text[i] == '\n')
2191            {
2192              if (i == input_text_length)
2193                i--;
2194
2195              input_text_offset = i;
2196              character = curchar ();
2197            }
2198        }
2199
2200      if (character == '\n')
2201        line_number++;
2202
2203      switch (character)
2204        {
2205        case '*': /* perhaps we are at a menu */
2206          /* We used to check for this in the \n case but an @c in a
2207             menu swallows its newline, so check here instead.  */
2208          if (!only_macro_expansion && in_menu
2209              && input_text_offset + 1 < input_text_length
2210              && input_text[input_text_offset-1] == '\n')
2211            handle_menu_entry ();
2212          else
2213            { /* Duplicate code from below, but not worth twisting the
2214                 fallthroughs to get down there.  */
2215              add_char (character);
2216              input_text_offset++;
2217            }
2218          break;
2219
2220        /* Escapes for HTML unless we're outputting raw HTML.  Do
2221           this always, even if SGML rules don't require it since
2222           that's easier and safer for non-conforming browsers. */
2223        case '&':
2224          if (html && escape_html)
2225            add_word ("&amp;");
2226          else
2227            add_char (character);
2228          input_text_offset++;
2229          break;
2230
2231        case '<':
2232          if (html && escape_html)
2233            add_word ("&lt;");
2234          else if (xml && escape_html)
2235            xml_insert_entity ("lt");
2236          else
2237            add_char (character);
2238          input_text_offset++;
2239          break;
2240
2241        case '>':
2242          if (html && escape_html)
2243            add_word ("&gt;");
2244          else if (xml && escape_html)
2245            xml_insert_entity ("gt");
2246          else
2247            add_char (character);
2248          input_text_offset++;
2249          break;
2250
2251        case COMMAND_PREFIX: /* @ */
2252          if (read_command () || !only_macro_expansion)
2253            break;
2254
2255        /* FALLTHROUGH (usually) */
2256        case '{':
2257          /* Special case.  We're not supposed to see this character by itself.
2258             If we do, it means there is a syntax error in the input text.
2259             Report the error here, but remember this brace on the stack so
2260             we can ignore its partner. */
2261          if (!only_macro_expansion)
2262            {
2263              if (command && !STREQ (command, "math"))
2264                {
2265                  line_error (_("Misplaced %c"), '{');
2266                  remember_brace (misplaced_brace);
2267                }
2268              else
2269                /* We don't mind `extra' braces inside @math.  */
2270                remember_brace (cm_no_op);
2271              /* remember_brace advances input_text_offset.  */
2272              break;
2273            }
2274
2275        /* FALLTHROUGH (usually) */
2276        case '}':
2277          if (!only_macro_expansion)
2278            {
2279              pop_and_call_brace ();
2280              input_text_offset++;
2281              break;
2282            }
2283
2284        /* FALLTHROUGH (usually) */
2285        default:
2286          add_char (character);
2287          input_text_offset++;
2288        }
2289    }
2290  if (macro_expansion_output_stream && !only_macro_expansion)
2291    maybe_write_itext (input_text, input_text_offset);
2292}
2293
2294static void
2295init_brace_stack (void)
2296{
2297  brace_stack = NULL;
2298}
2299
2300/* Remember the current output position here.  Save PROC
2301   along with it so you can call it later. */
2302static void
2303remember_brace_1 (COMMAND_FUNCTION (*proc), int position)
2304{
2305  BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
2306  new->next = brace_stack;
2307  new->proc = proc;
2308  new->command = command ? xstrdup (command) : "";
2309  new->pos = position;
2310  new->line = line_number;
2311  new->in_fixed_width_font = in_fixed_width_font;
2312  brace_stack = new;
2313}
2314
2315static void
2316remember_brace (COMMAND_FUNCTION (*proc))
2317{
2318  if (curchar () != '{')
2319    line_error (_("%c%s expected braces"), COMMAND_PREFIX, command);
2320  else
2321    input_text_offset++;
2322  remember_brace_1 (proc, output_paragraph_offset);
2323}
2324
2325/* Pop the top of the brace stack, and call the associated function
2326   with the args END and POS. */
2327static void
2328pop_and_call_brace (void)
2329{
2330  if (brace_stack == NULL)
2331    {
2332      line_error (_("Unmatched }"));
2333      return;
2334    }
2335
2336  {
2337    BRACE_ELEMENT *temp;
2338
2339    int pos = brace_stack->pos;
2340    COMMAND_FUNCTION *proc = brace_stack->proc;
2341    in_fixed_width_font = brace_stack->in_fixed_width_font;
2342
2343    /* Reset current command, so the proc can know who it is.  This is
2344       used in cm_accent.  */
2345    command = brace_stack->command;
2346
2347    temp = brace_stack->next;
2348    free (brace_stack);
2349    brace_stack = temp;
2350
2351    (*proc) (END, pos, output_paragraph_offset);
2352  }
2353}
2354
2355/* Shift all of the markers in `brace_stack' by AMOUNT. */
2356static void
2357adjust_braces_following (int here, int amount)
2358{
2359  BRACE_ELEMENT *stack = brace_stack;
2360
2361  while (stack)
2362    {
2363      if (stack->pos >= here)
2364        stack->pos += amount;
2365      stack = stack->next;
2366    }
2367}
2368
2369/* Return the string which invokes PROC; a pointer to a function.
2370   Always returns the first function in the command table if more than
2371   one matches PROC.  */
2372static const char *
2373find_proc_name (COMMAND_FUNCTION (*proc))
2374{
2375  int i;
2376
2377  for (i = 0; command_table[i].name; i++)
2378    if (proc == command_table[i].proc)
2379      return command_table[i].name;
2380  return _("NO_NAME!");
2381}
2382
2383/* You call discard_braces () when you shouldn't have any braces on the stack.
2384   I used to think that this happens for commands that don't take arguments
2385   in braces, but that was wrong because of things like @code{foo @@}.  So now
2386   I only detect it at the beginning of nodes. */
2387void
2388discard_braces (void)
2389{
2390  if (!brace_stack)
2391    return;
2392
2393  while (brace_stack)
2394    {
2395      if (brace_stack->proc != misplaced_brace)
2396        {
2397          const char *proc_name;
2398
2399          proc_name = find_proc_name (brace_stack->proc);
2400          file_line_error (input_filename, brace_stack->line,
2401                           _("%c%s missing close brace"), COMMAND_PREFIX,
2402                           proc_name);
2403          pop_and_call_brace ();
2404        }
2405      else
2406        {
2407          BRACE_ELEMENT *temp;
2408          temp = brace_stack->next;
2409          free (brace_stack);
2410          brace_stack = temp;
2411        }
2412    }
2413}
2414
2415static int
2416get_char_len (int character)
2417{
2418  /* Return the printed length of the character. */
2419  int len;
2420
2421  switch (character)
2422    {
2423    case '\t':
2424      len = (output_column + 8) & 0xf7;
2425      if (len > fill_column)
2426        len = fill_column - output_column;
2427      else
2428        len = len - output_column;
2429      break;
2430
2431    case '\n':
2432      len = fill_column - output_column;
2433      break;
2434
2435    default:
2436      /* ASCII control characters appear as two characters in the output
2437         (e.g., ^A).  But characters with the high bit set are just one
2438         on suitable terminals, so don't count them as two for line
2439         breaking purposes.  */
2440      if (0 <= character && character < ' ')
2441        len = 2;
2442      else
2443        len = 1;
2444    }
2445  return len;
2446}
2447
2448void
2449#if defined (VA_FPRINTF) && __STDC__
2450add_word_args (const char *format, ...)
2451#else
2452add_word_args (format, va_alist)
2453    const char *format;
2454    va_dcl
2455#endif
2456{
2457  char buffer[2000]; /* xx no fixed limits */
2458#ifdef VA_FPRINTF
2459  va_list ap;
2460#endif
2461
2462  VA_START (ap, format);
2463#ifdef VA_SPRINTF
2464  VA_SPRINTF (buffer, format, ap);
2465#else
2466  sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2467#endif /* not VA_SPRINTF */
2468  va_end (ap);
2469  add_word (buffer);
2470}
2471
2472/* Add STRING to output_paragraph. */
2473void
2474add_word (char *string)
2475{
2476  while (*string)
2477    add_char (*string++);
2478}
2479
2480/* Like add_word, but inhibits conversion of whitespace into &nbsp;.
2481   Use this to output HTML directives with embedded blanks, to make
2482   them @w-safe.  */
2483void
2484add_html_elt (char *string)
2485{
2486  in_html_elt++;
2487  add_word (string);
2488  in_html_elt--;
2489}
2490
2491/* These two functions below, add_html_block_elt and add_html_block_elt_args,
2492   are mixtures of add_html_elt and add_word_args.  They inform makeinfo that
2493   the current HTML element being inserted should not be enclosed in a <p>
2494   element.  */
2495void
2496add_html_block_elt (char *string)
2497{
2498  in_html_block_level_elt++;
2499  add_word (string);
2500  in_html_block_level_elt--;
2501}
2502
2503void
2504#if defined (VA_FPRINTF) && __STDC__
2505add_html_block_elt_args (const char *format, ...)
2506#else
2507add_html_block_elt_args (format, va_alist)
2508    const char *format;
2509    va_dcl
2510#endif
2511{
2512  char buffer[2000]; /* xx no fixed limits */
2513#ifdef VA_FPRINTF
2514  va_list ap;
2515#endif
2516
2517  VA_START (ap, format);
2518#ifdef VA_SPRINTF
2519  VA_SPRINTF (buffer, format, ap);
2520#else
2521  sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2522#endif /* not VA_SPRINTF */
2523  va_end (ap);
2524  add_html_block_elt (buffer);
2525}
2526
2527/* Here is another awful kludge, used in add_char.  Ordinarily, macro
2528   expansions take place in the body of the document, and therefore we
2529   should html_output_head when we see one.  But there's an exception: a
2530   macro call might take place within @copying, and that does not start
2531   the real output, even though we fully expand the copying text.
2532
2533   So we need to be able to check if we are defining the @copying text.
2534   We do this by looking back through the insertion stack.  */
2535static int
2536defining_copying (void)
2537{
2538  INSERTION_ELT *i;
2539  for (i = insertion_stack; i; i = i->next)
2540    {
2541      if (i->insertion == copying)
2542        return 1;
2543    }
2544  return 0;
2545}
2546
2547
2548/* Add the character to the current paragraph.  If filling_enabled is
2549   nonzero, then do filling as well. */
2550void
2551add_char (int character)
2552{
2553  if (xml)
2554    {
2555      xml_add_char (character);
2556      return;
2557    }
2558
2559  /* If we are avoiding outputting headers, and we are currently
2560     in a menu, then simply return.  But if we're only expanding macros,
2561     then we're being called from glean_node_from_menu to try to
2562     remember a menu reference, and we need that so we can do defaulting.  */
2563  if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2564    return;
2565
2566  /* If we are adding a character now, then we don't have to
2567     ignore close_paragraph () calls any more. */
2568  if (must_start_paragraph && character != '\n')
2569    {
2570      must_start_paragraph = 0;
2571      line_already_broken = 0;  /* The line is no longer broken. */
2572      if (current_indent > output_column)
2573        {
2574          indent (current_indent - output_column);
2575          output_column = current_indent;
2576        }
2577    }
2578
2579  if (non_splitting_words
2580      && !(html && in_html_elt)
2581      && strchr (" \t\n", character))
2582    {
2583      if (html || docbook)
2584        { /* Seems cleaner to use &nbsp; than an 8-bit char.  */
2585          int saved_escape_html = escape_html;
2586          escape_html = 0;
2587          add_word ("&nbsp");
2588          escape_html = saved_escape_html;
2589          character = ';';
2590        }
2591      else
2592        character = META (' '); /* unmeta-d in flush_output */
2593    }
2594
2595  insertion_paragraph_closed = 0;
2596
2597  switch (character)
2598    {
2599    case '\n':
2600      if (!filling_enabled && !(html && (in_menu || in_detailmenu)))
2601        {
2602          insert ('\n');
2603
2604          if (force_flush_right)
2605            {
2606              close_paragraph ();
2607              /* Hack to force single blank lines out in this mode. */
2608              flush_output ();
2609            }
2610
2611          output_column = 0;
2612
2613          if (!no_indent && paragraph_is_open)
2614            indent (output_column = current_indent);
2615          break;
2616        }
2617      else if (end_of_sentence_p ())
2618        /* CHARACTER is newline, and filling is enabled. */
2619        {
2620          insert (' ');
2621          output_column++;
2622          last_inserted_character = character;
2623        }
2624
2625      if (last_char_was_newline)
2626        {
2627          if (html)
2628            last_char_was_newline++;
2629          close_paragraph ();
2630          pending_indent = 0;
2631        }
2632      else
2633        {
2634          last_char_was_newline = 1;
2635          if (html)
2636            insert ('\n');
2637          else
2638            insert (' ');
2639          output_column++;
2640        }
2641      break;
2642
2643    default: /* not at newline */
2644      {
2645        int len = get_char_len (character);
2646        int suppress_insert = 0;
2647
2648        if ((character == ' ') && (last_char_was_newline))
2649          {
2650            if (!paragraph_is_open)
2651              {
2652                pending_indent++;
2653                return;
2654              }
2655          }
2656
2657        /* This is sad, but it seems desirable to not force any
2658           particular order on the front matter commands.  This way,
2659           the document can do @settitle, @documentlanguage, etc, in
2660           any order and with any omissions, and we'll still output
2661           the html <head> `just in time'.  */
2662        if ((executing_macro || !executing_string)
2663            && !only_macro_expansion
2664            && html && !html_output_head_p && !defining_copying ())
2665          html_output_head ();
2666
2667        if (!paragraph_is_open)
2668          {
2669            start_paragraph ();
2670            /* If the paragraph is supposed to be indented a certain
2671               way, then discard all of the pending whitespace.
2672               Otherwise, we let the whitespace stay. */
2673            if (!paragraph_start_indent)
2674              indent (pending_indent);
2675            pending_indent = 0;
2676
2677            /* This check for in_html_block_level_elt prevents <p> from being
2678               inserted when we already have html markup starting a paragraph,
2679               as with <ul> and <h1> and the like.  */
2680            if (html && !in_html_block_level_elt)
2681              {
2682                if ((in_menu || in_detailmenu) && in_menu_item)
2683                  {
2684                    insert_string ("</li></ul>\n");
2685                    in_menu_item = 0;
2686                  }
2687                insert_string ("<p>");
2688                in_paragraph = 1;
2689                adjust_braces_following (0, 3); /* adjust for <p> */
2690              }
2691          }
2692
2693        output_column += len;
2694        if (output_column > fill_column)
2695          {
2696            if (filling_enabled && !html)
2697              {
2698                int temp = output_paragraph_offset;
2699                while (--temp > 0 && output_paragraph[temp] != '\n')
2700                  {
2701                    /* If we have found a space, we have the place to break
2702                       the line. */
2703                    if (output_paragraph[temp] == ' ')
2704                      {
2705                        /* Remove trailing whitespace from output. */
2706                        while (temp && whitespace (output_paragraph[temp - 1]))
2707                          temp--;
2708
2709                        /* If we went back all the way to the newline of the
2710                           preceding line, it probably means that the word we
2711                           are adding is itself wider than the space that the
2712                           indentation and the fill_column let us use.  In
2713                           that case, do NOT insert another newline, since it
2714                           won't help.  Just indent to current_indent and
2715                           leave it alone, since that's the most we can do.  */
2716                        if (temp && output_paragraph[temp - 1] != '\n')
2717                          output_paragraph[temp++] = '\n';
2718
2719                        /* We have correctly broken the line where we want
2720                           to.  What we don't want is spaces following where
2721                           we have decided to break the line.  We get rid of
2722                           them. */
2723                        {
2724                          int t1 = temp;
2725
2726                          for (;; t1++)
2727                            {
2728                              if (t1 == output_paragraph_offset)
2729                                {
2730                                  if (whitespace (character))
2731                                    suppress_insert = 1;
2732                                  break;
2733                                }
2734                              if (!whitespace (output_paragraph[t1]))
2735                                break;
2736                            }
2737
2738                          if (t1 != temp)
2739                            {
2740                              adjust_braces_following (temp, (- (t1 - temp)));
2741                              memmove (&output_paragraph[temp],
2742                                       &output_paragraph[t1],
2743                                       output_paragraph_offset - t1);
2744                              output_paragraph_offset -= (t1 - temp);
2745                            }
2746                        }
2747
2748                        /* Filled, but now indent if that is right. */
2749                        if (indented_fill && current_indent > 0)
2750                          {
2751                            int buffer_len = ((output_paragraph_offset - temp)
2752                                              + current_indent);
2753                            char *temp_buffer = xmalloc (buffer_len);
2754                            int indentation = 0;
2755
2756                            /* We have to shift any markers that are in
2757                               front of the wrap point. */
2758                            adjust_braces_following (temp, current_indent);
2759
2760                            while (current_indent > 0 &&
2761                                   indentation != current_indent)
2762                              temp_buffer[indentation++] = ' ';
2763
2764                            memcpy ((char *) &temp_buffer[current_indent],
2765                                     (char *) &output_paragraph[temp],
2766                                     buffer_len - current_indent);
2767
2768                            if (output_paragraph_offset + buffer_len
2769                                >= paragraph_buffer_len)
2770                              {
2771                                unsigned char *tt = xrealloc
2772                                  (output_paragraph,
2773                                   (paragraph_buffer_len += buffer_len));
2774                                output_paragraph = tt;
2775                              }
2776                            memcpy ((char *) &output_paragraph[temp],
2777                                     temp_buffer, buffer_len);
2778                            output_paragraph_offset += current_indent;
2779                            free (temp_buffer);
2780                          }
2781                        output_column = 0;
2782                        while (temp < output_paragraph_offset)
2783                          output_column +=
2784                            get_char_len (output_paragraph[temp++]);
2785                        output_column += len;
2786                        break;
2787                      }
2788                  }
2789              }
2790          }
2791
2792        if (!suppress_insert)
2793          {
2794            insert (character);
2795            last_inserted_character = character;
2796          }
2797        last_char_was_newline = 0;
2798        line_already_broken = 0;
2799      }
2800    }
2801}
2802
2803/* Add a character and store its position in meta_char_pos.  */
2804void
2805add_meta_char (int character)
2806{
2807  meta_char_pos = output_paragraph_offset;
2808  add_char (character);
2809}
2810
2811/* Insert CHARACTER into `output_paragraph'. */
2812void
2813insert (int character)
2814{
2815  /* We don't want to strip trailing whitespace in multitables.  Otherwise
2816     horizontal separators confuse the font locking in Info mode in Emacs,
2817     because it looks like a @subsection.  Adding a trailing space to those
2818     lines fixes it.  */
2819  if (character == '\n' && !html && !xml && !multitable_active)
2820    {
2821      while (output_paragraph_offset
2822	     && whitespace (output_paragraph[output_paragraph_offset-1]))
2823	output_paragraph_offset--;
2824    }
2825
2826  output_paragraph[output_paragraph_offset++] = character;
2827  if (output_paragraph_offset == paragraph_buffer_len)
2828    {
2829      output_paragraph =
2830        xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2831    }
2832}
2833
2834/* Insert the null-terminated string STRING into `output_paragraph'.  */
2835void
2836insert_string (const char *string)
2837{
2838  while (*string)
2839    insert (*string++);
2840}
2841
2842
2843/* Sentences might have these characters after the period (or whatever).  */
2844#define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2845                          || (c) == ']')
2846
2847/* Return true if at an end-of-sentence character, possibly followed by
2848   post-sentence punctuation to ignore.  */
2849static int
2850end_of_sentence_p (void)
2851{
2852  int loc = output_paragraph_offset - 1;
2853
2854  /* If nothing has been output, don't check output_paragraph[-1].  */
2855  if (loc < 0)
2856    return 0;
2857
2858  /* A post-sentence character that is at meta_char_pos is not really
2859     a post-sentence character; it was produced by a markup such as
2860     @samp.  We don't want the period inside @samp to be treated as a
2861     sentence ender. */
2862  while (loc > 0
2863         && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
2864    loc--;
2865  return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
2866}
2867
2868
2869/* Remove upto COUNT characters of whitespace from the
2870   the current output line.  If COUNT is less than zero,
2871   then remove until none left. */
2872void
2873kill_self_indent (int count)
2874{
2875  /* Handle infinite case first. */
2876  if (count < 0)
2877    {
2878      output_column = 0;
2879      while (output_paragraph_offset)
2880        {
2881          if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2882            output_paragraph_offset--;
2883          else
2884            break;
2885        }
2886    }
2887  else
2888    {
2889      while (output_paragraph_offset && count--)
2890        if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2891          output_paragraph_offset--;
2892        else
2893          break;
2894    }
2895}
2896
2897/* Nonzero means do not honor calls to flush_output (). */
2898static int flushing_ignored = 0;
2899
2900/* Prevent calls to flush_output () from having any effect. */
2901void
2902inhibit_output_flushing (void)
2903{
2904  flushing_ignored++;
2905}
2906
2907/* Allow calls to flush_output () to write the paragraph data. */
2908void
2909uninhibit_output_flushing (void)
2910{
2911  flushing_ignored--;
2912}
2913
2914void
2915flush_output (void)
2916{
2917  int i;
2918
2919  if (!output_paragraph_offset || flushing_ignored)
2920    return;
2921
2922  for (i = 0; i < output_paragraph_offset; i++)
2923    {
2924      if (output_paragraph[i] == '\n')
2925        {
2926          output_line_number++;
2927          node_line_number++;
2928        }
2929
2930      /* If we turned on the 8th bit for a space inside @w, turn it
2931         back off for output.  This might be problematic, since the
2932         0x80 character may be used in 8-bit character sets.  Sigh.
2933         In any case, don't do this for HTML, since the nbsp character
2934         is valid input and must be passed along to the browser.  */
2935      if (!html && (output_paragraph[i] & meta_character_bit))
2936        {
2937          int temp = UNMETA (output_paragraph[i]);
2938          if (temp == ' ')
2939            output_paragraph[i] &= 0x7f;
2940        }
2941    }
2942
2943  fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2944
2945  output_position += output_paragraph_offset;
2946  output_paragraph_offset = 0;
2947  meta_char_pos = 0;
2948}
2949
2950/* How to close a paragraph controlling the number of lines between
2951   this one and the last one. */
2952
2953/* Paragraph spacing is controlled by this variable.  It is the number of
2954   blank lines that you wish to appear between paragraphs.  A value of
2955   1 creates a single blank line between paragraphs. */
2956int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2957
2958static void
2959close_paragraph_with_lines (int lines)
2960{
2961  int old_spacing = paragraph_spacing;
2962  paragraph_spacing = lines;
2963  close_paragraph ();
2964  paragraph_spacing = old_spacing;
2965}
2966
2967/* Close the current paragraph, leaving no blank lines between them. */
2968void
2969close_single_paragraph (void)
2970{
2971  close_paragraph_with_lines (0);
2972}
2973
2974/* Close a paragraph after an insertion has ended. */
2975void
2976close_insertion_paragraph (void)
2977{
2978  if (!insertion_paragraph_closed)
2979    {
2980      /* Close the current paragraph, breaking the line. */
2981      close_single_paragraph ();
2982
2983      /* Start a new paragraph, with the correct indentation for the now
2984         current insertion level (one above the one that we are ending). */
2985      start_paragraph ();
2986
2987      /* Tell `close_paragraph' that the previous line has already been
2988         broken, so it should insert one less newline. */
2989      line_already_broken = 1;
2990
2991      /* Tell functions such as `add_char' we've already found a newline. */
2992      ignore_blank_line ();
2993    }
2994  else
2995    {
2996      /* If the insertion paragraph is closed already, then we are seeing
2997         two `@end' commands in a row.  Note that the first one we saw was
2998         handled in the first part of this if-then-else clause, and at that
2999         time `start_paragraph' was called, partially to handle the proper
3000         indentation of the current line.  However, the indentation level
3001         may have just changed again, so we may have to outdent the current
3002         line to the new indentation level. */
3003      if (current_indent < output_column)
3004        kill_self_indent (output_column - current_indent);
3005    }
3006
3007  insertion_paragraph_closed = 1;
3008}
3009
3010/* Close the currently open paragraph. */
3011void
3012close_paragraph (void)
3013{
3014  int i;
3015
3016  /* We don't need these newlines in XML and Docbook outputs for
3017     paragraph seperation.  We have <para> element for that.  */
3018  if (xml)
3019    return;
3020
3021  /* The insertion paragraph is no longer closed. */
3022  insertion_paragraph_closed = 0;
3023
3024  if (paragraph_is_open && !must_start_paragraph)
3025    {
3026      int tindex = output_paragraph_offset;
3027
3028      /* Back up to last non-newline/space character, forcing all such
3029         subsequent characters to be newlines.  This isn't strictly
3030         necessary, but a couple of functions use the presence of a newline
3031         to make decisions. */
3032      for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
3033        {
3034          int c = output_paragraph[tindex];
3035
3036          if (c == ' '|| c == '\n')
3037            output_paragraph[tindex] = '\n';
3038          else
3039            break;
3040        }
3041
3042      /* All trailing whitespace is ignored. */
3043      output_paragraph_offset = ++tindex;
3044
3045      /* Break the line if that is appropriate. */
3046      if (paragraph_spacing >= 0)
3047        insert ('\n');
3048
3049      /* Add as many blank lines as is specified in `paragraph_spacing'. */
3050      if (!force_flush_right)
3051        {
3052          for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
3053            {
3054              insert ('\n');
3055              /* Don't need anything extra for HTML in usual case of no
3056                 extra paragraph spacing.  */
3057              if (html && i > 0)
3058                insert_string ("<br>");
3059            }
3060        }
3061
3062      /* If we are doing flush right indentation, then do it now
3063         on the paragraph (really a single line). */
3064      if (force_flush_right)
3065        do_flush_right_indentation ();
3066
3067      flush_output ();
3068      paragraph_is_open = 0;
3069      no_indent = 0;
3070      output_column = 0;
3071    }
3072
3073  ignore_blank_line ();
3074}
3075
3076/* Make the last line just read look as if it were only a newline. */
3077void
3078ignore_blank_line (void)
3079{
3080  last_inserted_character = '\n';
3081  last_char_was_newline = 1;
3082}
3083
3084/* Align the end of the text in output_paragraph with fill_column. */
3085static void
3086do_flush_right_indentation (void)
3087{
3088  char *temp;
3089  int temp_len;
3090
3091  kill_self_indent (-1);
3092
3093  if (output_paragraph[0] != '\n')
3094    {
3095      output_paragraph[output_paragraph_offset] = 0;
3096
3097      if (output_paragraph_offset < fill_column)
3098        {
3099          int i;
3100
3101          if (fill_column >= paragraph_buffer_len)
3102            output_paragraph =
3103              xrealloc (output_paragraph,
3104                        (paragraph_buffer_len += fill_column));
3105
3106          temp_len = strlen ((char *)output_paragraph);
3107          temp = xmalloc (temp_len + 1);
3108          memcpy (temp, (char *)output_paragraph, temp_len);
3109
3110          for (i = 0; i < fill_column - output_paragraph_offset; i++)
3111            output_paragraph[i] = ' ';
3112
3113          memcpy ((char *)output_paragraph + i, temp, temp_len);
3114          free (temp);
3115          output_paragraph_offset = fill_column;
3116          adjust_braces_following (0, i);
3117        }
3118    }
3119}
3120
3121/* Begin a new paragraph. */
3122void
3123start_paragraph (void)
3124{
3125  /* First close existing one. */
3126  if (paragraph_is_open)
3127    close_paragraph ();
3128
3129  /* In either case, the insertion paragraph is no longer closed. */
3130  insertion_paragraph_closed = 0;
3131
3132  /* However, the paragraph is open! */
3133  paragraph_is_open = 1;
3134
3135  /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
3136     had to be called before we would allow any other paragraph operations
3137     to have an effect. */
3138  if (!must_start_paragraph)
3139    {
3140      int amount_to_indent = 0;
3141
3142      /* If doing indentation, then insert the appropriate amount. */
3143      if (!no_indent)
3144        {
3145          if (inhibit_paragraph_indentation)
3146            {
3147              amount_to_indent = current_indent;
3148              if (inhibit_paragraph_indentation < 0)
3149                inhibit_paragraph_indentation++;
3150            }
3151          else if (paragraph_start_indent < 0)
3152            amount_to_indent = current_indent;
3153          else
3154            amount_to_indent = current_indent + paragraph_start_indent;
3155
3156          if (amount_to_indent >= output_column)
3157            {
3158              amount_to_indent -= output_column;
3159              indent (amount_to_indent);
3160              output_column += amount_to_indent;
3161            }
3162        }
3163    }
3164  else
3165    must_start_paragraph = 0;
3166}
3167
3168/* Insert the indentation specified by AMOUNT. */
3169void
3170indent (int amount)
3171{
3172  /* For every START_POS saved within the brace stack which will be affected
3173     by this indentation, bump that start pos forward. */
3174  adjust_braces_following (output_paragraph_offset, amount);
3175
3176  while (--amount >= 0)
3177    insert (' ');
3178}
3179
3180/* Search forward for STRING in input_text.
3181   FROM says where where to start. */
3182int
3183search_forward (char *string, int from)
3184{
3185  int len = strlen (string);
3186
3187  while (from < input_text_length)
3188    {
3189      if (strncmp (input_text + from, string, len) == 0)
3190        return from;
3191      from++;
3192    }
3193  return -1;
3194}
3195
3196/* search_forward until n characters.  */
3197int
3198search_forward_until_pos (char *string, int from, int end_pos)
3199{
3200  int save_input_text_length = input_text_length;
3201  input_text_length = end_pos;
3202
3203  from = search_forward (string, from);
3204
3205  input_text_length = save_input_text_length;
3206
3207  return from;
3208}
3209
3210/* Return next non-whitespace and non-cr character.  */
3211int
3212next_nonwhitespace_character (void)
3213{
3214  /* First check the current input_text.  Start from the next char because
3215     we already have input_text[input_text_offset] in ``current''.  */
3216  int pos = input_text_offset + 1;
3217
3218  while (pos < input_text_length)
3219    {
3220      if (!cr_or_whitespace(input_text[pos]))
3221        return input_text[pos];
3222      pos++;
3223    }
3224
3225  { /* Can't find a valid character, so go through filestack
3226       in case we are doing @include or expanding a macro.  */
3227    FSTACK *tos = filestack;
3228
3229    while (tos)
3230      {
3231        int tmp_input_text_length = filestack->size;
3232        int tmp_input_text_offset = filestack->offset;
3233        char *tmp_input_text = filestack->text;
3234
3235        while (tmp_input_text_offset < tmp_input_text_length)
3236          {
3237            if (!cr_or_whitespace(tmp_input_text[tmp_input_text_offset]))
3238              return tmp_input_text[tmp_input_text_offset];
3239            tmp_input_text_offset++;
3240          }
3241
3242        tos = tos->next;
3243      }
3244  }
3245
3246  return -1;
3247}
3248
3249/* An external image is a reference, kind of.  The parsing is (not
3250   coincidentally) similar, anyway.  */
3251void
3252cm_image (int arg)
3253{
3254  char *name_arg, *w_arg, *h_arg, *alt_arg, *ext_arg;
3255
3256  if (arg == END)
3257    return;
3258
3259  name_arg = get_xref_token (1); /* expands all macros in image */
3260  w_arg = get_xref_token (0);
3261  h_arg = get_xref_token (0);
3262  alt_arg = get_xref_token (1); /* expands all macros in alt text */
3263  ext_arg = get_xref_token (0);
3264
3265  if (*name_arg)
3266    {
3267      struct stat file_info;
3268      char *pathname = NULL;
3269      char *fullname = xmalloc (strlen (name_arg)
3270                       + (ext_arg && *ext_arg ? strlen (ext_arg) + 1: 4) + 1);
3271
3272      if (ext_arg && *ext_arg)
3273        {
3274          sprintf (fullname, "%s%s", name_arg, ext_arg);
3275          if (access (fullname, R_OK) != 0)
3276            pathname = get_file_info_in_path (fullname, include_files_path,
3277                                              &file_info);
3278
3279	  if (pathname == NULL)
3280	    {
3281	      /* Backwards compatibility (4.6 <= version < 4.7):
3282		 try prefixing @image's EXTENSION parameter with a period. */
3283	      sprintf (fullname, "%s.%s", name_arg, ext_arg);
3284	      if (access (fullname, R_OK) != 0)
3285		pathname = get_file_info_in_path (fullname, include_files_path,
3286						  &file_info);
3287	    }
3288        }
3289      else
3290        {
3291          sprintf (fullname, "%s.png", name_arg);
3292          if (access (fullname, R_OK) != 0) {
3293            pathname = get_file_info_in_path (fullname,
3294                                              include_files_path, &file_info);
3295            if (pathname == NULL) {
3296              sprintf (fullname, "%s.jpg", name_arg);
3297              if (access (fullname, R_OK) != 0) {
3298                sprintf (fullname, "%s.gif", name_arg);
3299                if (access (fullname, R_OK) != 0) {
3300                  pathname = get_file_info_in_path (fullname,
3301                                               include_files_path, &file_info);
3302                }
3303              }
3304            }
3305          }
3306        }
3307
3308      if (html)
3309        {
3310          int image_in_div = 0;
3311
3312          if (pathname == NULL && access (fullname, R_OK) != 0)
3313            {
3314              line_error(_("@image file `%s' (for HTML) not readable: %s"),
3315                             fullname, strerror (errno));
3316              return;
3317            }
3318          if (pathname != NULL && access (pathname, R_OK) != 0)
3319            {
3320              line_error (_("No such file `%s'"),
3321                          fullname);
3322              return;
3323            }
3324
3325          if (!paragraph_is_open)
3326            {
3327              add_html_block_elt ("<div class=\"block-image\">");
3328              image_in_div = 1;
3329            }
3330
3331          add_html_elt ("<img src=");
3332          add_word_args ("\"%s\"", fullname);
3333          add_html_elt (" alt=");
3334          add_word_args ("\"%s\">",
3335              escape_string (*alt_arg ? text_expansion (alt_arg) : fullname));
3336
3337          if (image_in_div)
3338            add_html_block_elt ("</div>");
3339        }
3340      else if (xml && docbook)
3341        xml_insert_docbook_image (name_arg);
3342      else if (xml)
3343        {
3344          extern int xml_in_para;
3345          extern int xml_no_para;
3346          int elt = xml_in_para ? INLINEIMAGE : IMAGE;
3347
3348          if (!xml_in_para)
3349            xml_no_para++;
3350
3351          xml_insert_element_with_attribute (elt,
3352              START, "width=\"%s\" height=\"%s\" name=\"%s\" extension=\"%s\"",
3353              w_arg, h_arg, name_arg, ext_arg);
3354          xml_insert_element (IMAGEALTTEXT, START);
3355          execute_string ("%s", alt_arg);
3356          xml_insert_element (IMAGEALTTEXT, END);
3357          xml_insert_element (elt, END);
3358
3359          if (!xml_in_para)
3360            xml_no_para--;
3361        }
3362      else
3363        { /* Try to open foo.EXT or foo.txt.  */
3364          FILE *image_file;
3365          char *txtpath = NULL;
3366          char *txtname = xmalloc (strlen (name_arg)
3367                                   + (ext_arg && *ext_arg
3368                                      ? strlen (ext_arg) : 4) + 1);
3369          strcpy (txtname, name_arg);
3370          strcat (txtname, ".txt");
3371          image_file = fopen (txtname, "r");
3372          if (image_file == NULL)
3373            {
3374              txtpath = get_file_info_in_path (txtname,
3375                                               include_files_path, &file_info);
3376              if (txtpath != NULL)
3377                image_file = fopen (txtpath, "r");
3378            }
3379
3380          if (image_file != NULL
3381              || access (fullname, R_OK) == 0
3382              || (pathname != NULL && access (pathname, R_OK) == 0))
3383            {
3384              int ch;
3385              int save_inhibit_indentation = inhibit_paragraph_indentation;
3386              int save_filling_enabled = filling_enabled;
3387              int image_in_brackets = paragraph_is_open;
3388
3389              /* Write magic ^@^H[image ...^@^H] cookie in the info file, if
3390                 there's an accompanying bitmap.  Otherwise just include the
3391                 text image.  In the plaintext output, always include the text
3392                 image without the magic cookie.  */
3393              int use_magic_cookie = !no_headers
3394                && access (fullname, R_OK) == 0 && !STREQ (fullname, txtname);
3395
3396              inhibit_paragraph_indentation = 1;
3397              filling_enabled = 0;
3398              last_char_was_newline = 0;
3399
3400              if (use_magic_cookie)
3401                {
3402                  add_char ('\0');
3403                  add_word ("\010[image");
3404
3405                  if (access (fullname, R_OK) == 0
3406                      || (pathname != NULL && access (pathname, R_OK) == 0))
3407                    add_word_args (" src=\"%s\"", fullname);
3408
3409                  if (*alt_arg)
3410                    add_word_args (" alt=\"%s\"", alt_arg);
3411                }
3412
3413              if (image_file != NULL)
3414                {
3415                  if (use_magic_cookie)
3416                    add_word (" text=\"");
3417
3418                  if (image_in_brackets)
3419                    add_char ('[');
3420
3421                  /* Maybe we need to remove the final newline if the image
3422                     file is only one line to allow in-line images.  On the
3423                     other hand, they could just make the file without a
3424                     final newline.  */
3425                  while ((ch = getc (image_file)) != EOF)
3426                    {
3427                      if (use_magic_cookie && (ch == '"' || ch == '\\'))
3428                        add_char ('\\');
3429                      add_char (ch);
3430                    }
3431
3432                  if (image_in_brackets)
3433                    add_char (']');
3434
3435                  if (use_magic_cookie)
3436                    add_char ('"');
3437
3438                  if (fclose (image_file) != 0)
3439                    perror (txtname);
3440                }
3441
3442              if (use_magic_cookie)
3443                {
3444                  add_char ('\0');
3445                  add_word ("\010]");
3446                }
3447
3448              inhibit_paragraph_indentation = save_inhibit_indentation;
3449              filling_enabled = save_filling_enabled;
3450            }
3451          else
3452            warning (_("@image file `%s' (for text) unreadable: %s"),
3453                        txtname, strerror (errno));
3454        }
3455
3456      free (fullname);
3457      if (pathname)
3458        free (pathname);
3459    }
3460  else
3461    line_error (_("@image missing filename argument"));
3462
3463  if (name_arg)
3464    free (name_arg);
3465  if (w_arg)
3466    free (w_arg);
3467  if (h_arg)
3468    free (h_arg);
3469  if (alt_arg)
3470    free (alt_arg);
3471  if (ext_arg)
3472    free (ext_arg);
3473}
3474
3475/* Conditionals.  */
3476
3477/* A structure which contains `defined' variables. */
3478typedef struct defines {
3479  struct defines *next;
3480  char *name;
3481  char *value;
3482} DEFINE;
3483
3484/* The linked list of `set' defines. */
3485DEFINE *defines = NULL;
3486
3487/* Add NAME to the list of `set' defines. */
3488static void
3489set (char *name, char *value)
3490{
3491  DEFINE *temp;
3492
3493  for (temp = defines; temp; temp = temp->next)
3494    if (strcmp (name, temp->name) == 0)
3495      {
3496        free (temp->value);
3497        temp->value = xstrdup (value);
3498        return;
3499      }
3500
3501  temp = xmalloc (sizeof (DEFINE));
3502  temp->next = defines;
3503  temp->name = xstrdup (name);
3504  temp->value = xstrdup (value);
3505  defines = temp;
3506
3507  if (xml && !docbook)
3508    {
3509      xml_insert_element_with_attribute (SETVALUE, START, "name=\"%s\"", name);
3510      execute_string ("%s", value);
3511      xml_insert_element (SETVALUE, END);
3512    }
3513}
3514
3515/* Remove NAME from the list of `set' defines. */
3516static void
3517clear (char *name)
3518{
3519  DEFINE *temp, *last;
3520
3521  last = NULL;
3522  temp = defines;
3523
3524  while (temp)
3525    {
3526      if (strcmp (temp->name, name) == 0)
3527        {
3528          if (last)
3529            last->next = temp->next;
3530          else
3531            defines = temp->next;
3532
3533          free (temp->name);
3534          free (temp->value);
3535          free (temp);
3536          break;
3537        }
3538      last = temp;
3539      temp = temp->next;
3540    }
3541
3542  if (xml && !docbook)
3543    {
3544      xml_insert_element_with_attribute (CLEARVALUE, START, "name=\"%s\"", name);
3545      xml_insert_element (CLEARVALUE, END);
3546    }
3547}
3548
3549/* Return the value of NAME.  The return value is NULL if NAME is unset. */
3550static char *
3551set_p (char *name)
3552{
3553  DEFINE *temp;
3554
3555  for (temp = defines; temp; temp = temp->next)
3556    if (strcmp (temp->name, name) == 0)
3557      return temp->value;
3558
3559  return NULL;
3560}
3561
3562/* Create a variable whose name appears as the first word on this line. */
3563void
3564cm_set (void)
3565{
3566  handle_variable (SET);
3567}
3568
3569/* Remove a variable whose name appears as the first word on this line. */
3570void
3571cm_clear (void)
3572{
3573  handle_variable (CLEAR);
3574}
3575
3576void
3577cm_ifset (void)
3578{
3579  handle_variable (IFSET);
3580}
3581
3582void
3583cm_ifclear (void)
3584{
3585  handle_variable (IFCLEAR);
3586}
3587
3588/* This command takes braces, but we parse the contents specially, so we
3589   don't use the standard brace popping code.
3590
3591   The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3592   if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3593   it produces no output. */
3594void
3595cm_ifeq (void)
3596{
3597  char **arglist;
3598
3599  arglist = get_brace_args (0);
3600
3601  if (arglist)
3602    {
3603      if (array_len (arglist) > 1)
3604        {
3605          if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
3606              (arglist[2]))
3607            execute_string ("%s\n", arglist[2]);
3608        }
3609
3610      free_array (arglist);
3611    }
3612}
3613
3614void
3615cm_value (int arg, int start_pos, int end_pos)
3616{
3617  static int value_level = 0, saved_meta_pos = -1;
3618
3619  /* xml_add_char() skips any content inside menus when output format is
3620     Docbook, so @value{} is no use there.  Also start_pos and end_pos does not
3621     get updated, causing name to be empty string.  So just return.  */
3622   if (docbook && in_menu)
3623     return;
3624
3625  /* All the text after @value{ upto the matching } will eventually
3626     disappear from output_paragraph, when this function is called
3627     with ARG == END.  If the text produced until then sets
3628     meta_char_pos, we will need to restore it to the value it had
3629     before @value was seen.  So we need to save the previous value
3630     of meta_char_pos here.  */
3631  if (arg == START)
3632    {
3633      /* If we are already inside some outer @value, don't overwrite
3634         the value saved in saved_meta_pos.  */
3635      if (!value_level)
3636        saved_meta_pos = meta_char_pos;
3637      value_level++;
3638      /* While the argument of @value is processed, we need to inhibit
3639         textual transformations like "--" into "-", since @set didn't
3640         do that when it grabbed the name of the variable.  */
3641      in_fixed_width_font++;
3642    }
3643  else
3644    {
3645      char *name = (char *) &output_paragraph[start_pos];
3646      char *value;
3647      output_paragraph[end_pos] = 0;
3648      name = xstrdup (name);
3649      value = set_p (name);
3650      output_column -= end_pos - start_pos;
3651      output_paragraph_offset = start_pos;
3652
3653      /* Restore the previous value of meta_char_pos if the stuff
3654         inside this @value{} moved it.  */
3655      if (saved_meta_pos == -1) /* can't happen inside @value{} */
3656        abort ();
3657      if (value_level == 1
3658          && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3659        {
3660          meta_char_pos = saved_meta_pos;
3661          saved_meta_pos = -1;
3662        }
3663      value_level--;
3664      /* No need to decrement in_fixed_width_font, since before
3665         we are called with arg == END, the reader loop already
3666         popped the brace stack, which restored in_fixed_width_font,
3667         among other things.  */
3668
3669      if (value)
3670	{
3671	  /* We need to get past the closing brace since the value may
3672	     expand to a context-sensitive macro (e.g. @xref) and produce
3673	     spurious warnings */
3674	  input_text_offset++;
3675	  execute_string ("%s", value);
3676	  input_text_offset--;
3677	}
3678      else
3679	{
3680          warning (_("undefined flag: %s"), name);
3681          add_word_args (_("{No value for `%s'}"), name);
3682	}
3683
3684      free (name);
3685    }
3686}
3687
3688/* Set, clear, or conditionalize based on ACTION. */
3689static void
3690handle_variable (int action)
3691{
3692  char *name;
3693
3694  get_rest_of_line (0, &name);
3695  /* If we hit the end of text in get_rest_of_line, backing up
3696     input pointer will cause the last character of the last line
3697     be pushed back onto the input, which is wrong.  */
3698  if (input_text_offset < input_text_length)
3699    backup_input_pointer ();
3700  handle_variable_internal (action, name);
3701  free (name);
3702}
3703
3704static void
3705handle_variable_internal (int action, char *name)
3706{
3707  char *temp;
3708  int delimiter, additional_text_present = 0;
3709
3710  /* Only the first word of NAME is a valid tag. */
3711  temp = name;
3712  delimiter = 0;
3713  while (*temp && (delimiter || !whitespace (*temp)))
3714    {
3715/* #if defined (SET_WITH_EQUAL) */
3716      if (*temp == '"' || *temp == '\'')
3717        {
3718          if (*temp == delimiter)
3719            delimiter = 0;
3720          else
3721            delimiter = *temp;
3722        }
3723/* #endif SET_WITH_EQUAL */
3724      temp++;
3725    }
3726
3727  if (*temp)
3728    additional_text_present++;
3729
3730  *temp = 0;
3731
3732  if (!*name)
3733    line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3734  else
3735    {
3736      switch (action)
3737        {
3738        case SET:
3739          {
3740            char *value;
3741
3742#if defined (SET_WITH_EQUAL)
3743            /* Allow a value to be saved along with a variable.  The value is
3744               the text following an `=' sign in NAME, if any is present. */
3745
3746            for (value = name; *value && *value != '='; value++);
3747
3748            if (*value)
3749              *value++ = 0;
3750
3751            if (*value == '"' || *value == '\'')
3752              {
3753                value++;
3754                value[strlen (value) - 1] = 0;
3755              }
3756
3757#else /* !SET_WITH_EQUAL */
3758            /* The VALUE of NAME is the remainder of the line sans
3759               whitespace. */
3760            if (additional_text_present)
3761              {
3762                value = temp + 1;
3763                canon_white (value);
3764              }
3765            else
3766              value = "";
3767#endif /* !SET_WITH_VALUE */
3768
3769            set (name, value);
3770          }
3771          break;
3772
3773        case CLEAR:
3774          clear (name);
3775          break;
3776
3777        case IFSET:
3778        case IFCLEAR:
3779          /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3780             read lines from the the file until we reach a matching
3781             "@end CONDITION".  This means that we only take note of
3782             "@ifset/clear" and "@end" commands. */
3783          {
3784            char condition[8];
3785            int condition_len;
3786            int orig_line_number = line_number;
3787
3788            if (action == IFSET)
3789              strcpy (condition, "ifset");
3790            else
3791              strcpy (condition, "ifclear");
3792
3793            condition_len = strlen (condition);
3794
3795          if ((action == IFSET && !set_p (name))
3796              || (action == IFCLEAR && set_p (name)))
3797            {
3798              int level = 0, done = 0;
3799
3800              while (!done && input_text_offset < input_text_length)
3801                {
3802                  char *freeable_line, *line;
3803
3804                  get_rest_of_line (0, &freeable_line);
3805
3806                  for (line = freeable_line; whitespace (*line); line++);
3807
3808                  if (*line == COMMAND_PREFIX &&
3809                      (strncmp (line + 1, condition, condition_len) == 0))
3810                    level++;
3811                  else if (strncmp (line, "@end", 4) == 0)
3812                    {
3813                      char *cname = line + 4;
3814                      char *temp;
3815
3816                      while (*cname && whitespace (*cname))
3817                        cname++;
3818                      temp = cname;
3819
3820                      while (*temp && !whitespace (*temp))
3821                        temp++;
3822                      *temp = 0;
3823
3824                      if (strcmp (cname, condition) == 0)
3825                        {
3826                          if (!level)
3827                            {
3828                              done = 1;
3829                            }
3830                          else
3831                            level--;
3832                        }
3833                    }
3834                  free (freeable_line);
3835                }
3836
3837              if (!done)
3838                file_line_error (input_filename, orig_line_number,
3839                                 _("Reached eof before matching @end %s"),
3840                                 condition);
3841
3842              /* We found the end of a false @ifset/ifclear.  If we are
3843                 in a menu, back up over the newline that ends the ifset,
3844                 since that newline may also begin the next menu entry. */
3845              break;
3846            }
3847          else
3848            {
3849              if (action == IFSET)
3850                begin_insertion (ifset);
3851              else
3852                begin_insertion (ifclear);
3853            }
3854          }
3855          break;
3856        }
3857    }
3858}
3859
3860/* Execution of random text not in file. */
3861typedef struct {
3862  char *string;                 /* The string buffer. */
3863  int size;                     /* The size of the buffer. */
3864  int in_use;                   /* Nonzero means string currently in use. */
3865} EXECUTION_STRING;
3866
3867static EXECUTION_STRING **execution_strings = NULL;
3868static int execution_strings_index = 0;
3869static int execution_strings_slots = 0;
3870
3871static EXECUTION_STRING *
3872get_execution_string (int initial_size)
3873{
3874  int i = 0;
3875  EXECUTION_STRING *es = NULL;
3876
3877  if (execution_strings)
3878    {
3879      for (i = 0; i < execution_strings_index; i++)
3880        if (execution_strings[i] && (execution_strings[i]->in_use == 0))
3881          {
3882            es = execution_strings[i];
3883            break;
3884          }
3885    }
3886
3887  if (!es)
3888    {
3889      if (execution_strings_index + 1 >= execution_strings_slots)
3890        {
3891          execution_strings = xrealloc
3892            (execution_strings,
3893             (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
3894          for (; i < execution_strings_slots; i++)
3895            execution_strings[i] = NULL;
3896        }
3897
3898      execution_strings[execution_strings_index] =
3899        xmalloc (sizeof (EXECUTION_STRING));
3900      es = execution_strings[execution_strings_index];
3901      execution_strings_index++;
3902
3903      es->size = 0;
3904      es->string = NULL;
3905      es->in_use = 0;
3906    }
3907
3908  if (initial_size > es->size)
3909    {
3910      es->string = xrealloc (es->string, initial_size);
3911      es->size = initial_size;
3912    }
3913  return es;
3914}
3915
3916/* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
3917   entry in the execution_strings[] array and change the .STRING and
3918   .SIZE members of that entry as appropriate.  */
3919void
3920maybe_update_execution_strings (char **text, unsigned int new_len)
3921{
3922  int i = 0;
3923
3924  if (execution_strings)
3925    {
3926      for (i = 0; i < execution_strings_index; i++)
3927        if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
3928            execution_strings[i]->string == *text)
3929          {
3930            /* Don't ever shrink the string storage in execution_strings[]!
3931               execute_string assumes that it is always big enough to store
3932               every possible execution_string, and will break if that's
3933               not true.  So we only enlarge the string storage if the
3934               current size isn't big enough.  */
3935            if (execution_strings[i]->size < new_len)
3936              {
3937                execution_strings[i]->string =
3938                  *text = xrealloc (*text, new_len + 1);
3939                execution_strings[i]->size = new_len + 1;
3940              }
3941            return;
3942          }
3943    }
3944  /* We should *never* end up here, since if we are inside
3945     execute_string, TEXT is always in execution_strings[].  */
3946  abort ();
3947}
3948
3949/* FIXME: this is an arbitrary limit.  */
3950#define EXECUTE_STRING_MAX 16*1024
3951
3952/* Execute the string produced by formatting the ARGs with FORMAT.  This
3953   is like submitting a new file with @include. */
3954void
3955#if defined (VA_FPRINTF) && __STDC__
3956execute_string (char *format, ...)
3957#else
3958execute_string (format, va_alist)
3959    char *format;
3960    va_dcl
3961#endif
3962{
3963  EXECUTION_STRING *es;
3964  char *temp_string, *temp_input_filename;
3965#ifdef VA_FPRINTF
3966  va_list ap;
3967#endif
3968  int insertion_level_at_start = insertion_level;
3969
3970  es = get_execution_string (EXECUTE_STRING_MAX);
3971  temp_string = es->string;
3972  es->in_use = 1;
3973
3974  VA_START (ap, format);
3975#ifdef VA_SPRINTF
3976  VA_SPRINTF (temp_string, format, ap);
3977#else
3978  sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
3979#endif /* not VA_SPRINTF */
3980  va_end (ap);
3981
3982  pushfile ();
3983  input_text_offset = 0;
3984  input_text = temp_string;
3985  input_text_length = strlen (temp_string);
3986  input_filename = xstrdup (input_filename);
3987  temp_input_filename = input_filename;
3988
3989  executing_string++;
3990  reader_loop ();
3991
3992  /* If insertion stack level changes during execution, that means a multiline
3993     command is used inside braces or @section ... kind of commands.  */
3994  if (insertion_level_at_start != insertion_level && !executing_macro)
3995    {
3996      line_error (_("Multiline command %c%s used improperly"),
3997          COMMAND_PREFIX,
3998          command);
3999      /* We also need to keep insertion_level intact to make sure warnings are
4000         issued for @end ... command.  */
4001      while (insertion_level > insertion_level_at_start)
4002        pop_insertion ();
4003    }
4004
4005  popfile ();
4006  executing_string--;
4007  es->in_use = 0;
4008  free (temp_input_filename);
4009}
4010
4011
4012/* Return what would be output for STR (in newly-malloced memory), i.e.,
4013   expand Texinfo commands according to the current output format.  If
4014   IMPLICIT_CODE is set, expand @code{STR}.  This is generally used for
4015   short texts; filling, indentation, and html escapes are disabled.  */
4016
4017char *
4018expansion (char *str, int implicit_code)
4019{
4020  return maybe_escaped_expansion (str, implicit_code, 0);
4021}
4022
4023
4024/* Do HTML escapes according to DO_HTML_ESCAPE.  Needed in
4025   cm_printindex, q.v.  */
4026
4027char *
4028maybe_escaped_expansion (char *str, int implicit_code, int do_html_escape)
4029{
4030  char *result;
4031
4032  /* Inhibit indentation and filling, so that extra newlines
4033     are not added to the expansion.  (This is undesirable if
4034     we write the expanded text to macro_expansion_output_stream.)  */
4035  int saved_filling_enabled = filling_enabled;
4036  int saved_indented_fill = indented_fill;
4037  int saved_no_indent = no_indent;
4038  int saved_escape_html = escape_html;
4039
4040  filling_enabled = 0;
4041  indented_fill = 0;
4042  no_indent = 1;
4043  escape_html = do_html_escape;
4044
4045  result = full_expansion (str, implicit_code);
4046
4047  filling_enabled = saved_filling_enabled;
4048  indented_fill = saved_indented_fill;
4049  no_indent = saved_no_indent;
4050  escape_html = saved_escape_html;
4051
4052  return result;
4053}
4054
4055
4056/* Expand STR (or @code{STR} if IMPLICIT_CODE is nonzero).  No change to
4057   any formatting parameters -- filling, indentation, html escapes,
4058   etc., are not reset.  Always returned in new memory.  */
4059
4060char *
4061full_expansion (char *str, int implicit_code)
4062{
4063  int length;
4064  char *result;
4065
4066  /* Inhibit any real output.  */
4067  int start = output_paragraph_offset;
4068  int saved_paragraph_is_open = paragraph_is_open;
4069  int saved_output_column = output_column;
4070
4071  /* More output state to save.  */
4072  int saved_meta_pos = meta_char_pos;
4073  int saved_last_char = last_inserted_character;
4074  int saved_last_nl = last_char_was_newline;
4075
4076  /* If we are called in the middle of processing a command, we need
4077     to dup and save the global variable `command' (which holds the
4078     name of this command), since the recursive reader loop will free
4079     it from under our feet if it finds any macros in STR.  */
4080  char *saved_command = command ? xstrdup (command) : NULL;
4081
4082  inhibit_output_flushing ();
4083  paragraph_is_open = 1;
4084  if (strlen (str) > (implicit_code
4085                      ? EXECUTE_STRING_MAX - 1 - sizeof("@code{}")
4086                      : EXECUTE_STRING_MAX - 1))
4087    line_error (_("`%.40s...' is too long for expansion; not expanded"), str);
4088  else
4089    execute_string (implicit_code ? "@code{%s}" : "%s", str);
4090  uninhibit_output_flushing ();
4091
4092  /* Copy the expansion from the buffer.  */
4093  length = output_paragraph_offset - start;
4094  result = xmalloc (1 + length);
4095  memcpy (result, (char *) (output_paragraph + start), length);
4096  result[length] = 0;
4097
4098  /* Pretend it never happened.  */
4099  free_and_clear (&command);
4100  command = saved_command;
4101
4102  output_paragraph_offset = start;
4103  paragraph_is_open = saved_paragraph_is_open;
4104  output_column = saved_output_column;
4105
4106  meta_char_pos = saved_meta_pos;
4107  last_inserted_character = saved_last_char;
4108  last_char_was_newline = saved_last_nl;
4109
4110  return result;
4111}
4112
4113
4114/* Return text (info) expansion of STR no matter what the current output
4115   format is.  */
4116
4117char *
4118text_expansion (char *str)
4119{
4120  char *ret;
4121  int save_html = html;
4122  int save_xml = xml;
4123  int save_docbook = docbook;
4124
4125  html = 0;
4126  xml = 0;
4127  docbook = 0;
4128  ret = expansion (str, 0);
4129  html = save_html;
4130  xml = save_xml;
4131  docbook = save_docbook;
4132
4133  return ret;
4134}
4135
4136
4137/* Set the paragraph indentation variable to the value specified in STRING.
4138   Values can be:
4139     `asis': Don't change existing indentation.
4140     `none': Remove existing indentation.
4141        NUM: Indent NUM spaces at the starts of paragraphs.
4142             If NUM is zero, we assume `none'.
4143   Returns 0 if successful, or nonzero if STRING isn't one of the above. */
4144int
4145set_paragraph_indent (char *string)
4146{
4147  if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
4148    paragraph_start_indent = 0;
4149  else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
4150    paragraph_start_indent = -1;
4151  else
4152    {
4153      if (sscanf (string, "%d", &paragraph_start_indent) != 1)
4154        return -1;
4155      else
4156        {
4157          if (paragraph_start_indent == 0)
4158            paragraph_start_indent = -1;
4159        }
4160    }
4161  return 0;
4162}
4163