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

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

GNU Texinfo 4.8

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