source: trunk/texinfo/makeinfo/makeinfo.c@ 2619

Last change on this file since 2619 was 2619, checked in by bird, 19 years ago

applied OS/2 patches (manually).

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