Bug Summary

File:src/gnu/usr.bin/texinfo/makeinfo/makeinfo.c
Warning:line 3026, column 11
Value stored to 'tindex' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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