Add <sys/_null.h> for the definition of NULL:
[dragonfly.git] / contrib / texinfo-4 / makeinfo / makeinfo.c
blob22ed4c4fd99f891079d6e3578dcbd0f5378a2f8f
1 /* makeinfo -- convert Texinfo source into other formats.
2 $Id: makeinfo.c,v 1.74 2004/12/19 17:15:42 karl Exp $
4 Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
5 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 Original author of makeinfo: Brian Fox (bfox@ai.mit.edu). */
23 #include "system.h"
24 #include "getopt.h"
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"
42 /* You can change some of the behavior of Makeinfo by changing the
43 following defines: */
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 */
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
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
64 /* Global variables. */
66 /* The output file name. */
67 char *output_filename = NULL;
69 /* Name of the output file that the user elected to pass on the command line.
70 Such a name overrides any name found with the @setfilename command. */
71 char *command_output_filename = NULL;
72 static char *save_command_output_filename = NULL;
74 #define INITIAL_PARAGRAPH_SPACE 5000
75 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
77 /* The amount of indentation to add at the starts of paragraphs.
78 0 means don't change existing indentation at paragraph starts.
79 > 0 is amount to indent new paragraphs by.
80 < 0 means indent to column zero by removing indentation if necessary.
82 This is normally zero, but some people prefer paragraph starts to be
83 somewhat more indented than paragraph bodies. A pretty value for
84 this is 3. */
85 int paragraph_start_indent = PARAGRAPH_START_INDENT;
87 /* Indentation that is pending insertion. We have this for hacking lines
88 which look blank, but contain whitespace. We want to treat those as
89 blank lines. */
90 int pending_indent = 0;
92 /* The index in our internal command table of the currently
93 executing command. */
94 int command_index;
96 /* A search string which is used to find the first @setfilename. */
97 char setfilename_search[] =
98 { COMMAND_PREFIX,
99 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
101 /* Values for calling handle_variable_internal (). */
102 #define SET 1
103 #define CLEAR 2
104 #define IFSET 3
105 #define IFCLEAR 4
107 /* Flags controlling the operation of the program. */
109 /* Default is to remove output if there were errors. */
110 int force = 0;
112 /* Default is to notify users of bad choices. */
113 int print_warnings = 1;
115 /* Number of errors that we tolerate on a given fileset. */
116 int max_error_level = 100;
118 /* The actual last inserted character. Note that this may be something
119 other than NEWLINE even if last_char_was_newline is 1. */
120 int last_inserted_character = 0;
122 /* Nonzero means that a newline character has already been
123 inserted, so close_paragraph () should insert one less. */
124 int line_already_broken = 0;
126 /* When nonzero we have finished an insertion (see end_insertion ()) and we
127 want to ignore false continued paragraph closings. */
128 int insertion_paragraph_closed = 0;
130 /* Nonzero means attempt to make all of the lines have fill_column width. */
131 int do_justification = 0;
133 /* Nonzero means don't replace whitespace with &nbsp; in HTML mode. */
134 int in_html_elt = 0;
136 /* Nonzero means we are inserting a block level HTML element that must not be
137 enclosed in a <p>, such as <ul>, <ol> and <h?>. */
138 int in_html_block_level_elt = 0;
140 /* True when expanding a macro definition. */
141 static int executing_macro = 0;
143 /* True when we are inside a <li> block of a menu. */
144 static int in_menu_item = 0;
146 typedef struct brace_element
148 struct brace_element *next;
149 COMMAND_FUNCTION *proc;
150 char *command;
151 int pos, line;
152 int in_fixed_width_font;
153 } BRACE_ELEMENT;
155 BRACE_ELEMENT *brace_stack = NULL;
157 static void convert_from_file (char *name);
158 static void convert_from_loaded_file (char *name);
159 static void convert_from_stream (FILE *stream, char *name);
160 static void do_flush_right_indentation (void);
161 static void handle_variable (int action);
162 static void handle_variable_internal (int action, char *name);
163 static void init_brace_stack (void);
164 static void init_internals (void);
165 static void pop_and_call_brace (void);
166 static void remember_brace (COMMAND_FUNCTION (*proc));
167 static int end_of_sentence_p (void);
169 void maybe_update_execution_strings (char **text, unsigned int new_len);
171 /* Error handling. */
173 /* Number of errors encountered. */
174 int errors_printed = 0;
176 /* Remember that an error has been printed. If more than
177 max_error_level have been printed, then exit the program. */
178 static void
179 remember_error (void)
181 errors_printed++;
182 if (max_error_level && (errors_printed > max_error_level))
184 fprintf (stderr, _("Too many errors! Gave up.\n"));
185 flush_file_stack ();
186 if (errors_printed - max_error_level < 2)
187 cm_bye ();
188 xexit (1);
192 /* Print the last error gotten from the file system. */
194 fs_error (char *filename)
196 remember_error ();
197 perror (filename);
198 return 0;
201 /* Print an error message, and return false. */
202 void
203 #if defined (VA_FPRINTF) && __STDC__
204 error (const char *format, ...)
205 #else
206 error (format, va_alist)
207 const char *format;
208 va_dcl
209 #endif
211 #ifdef VA_FPRINTF
212 va_list ap;
213 #endif
215 remember_error ();
217 VA_START (ap, format);
218 #ifdef VA_FPRINTF
219 VA_FPRINTF (stderr, format, ap);
220 #else
221 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
222 #endif /* not VA_FPRINTF */
223 va_end (ap);
225 putc ('\n', stderr);
228 /* Just like error (), but print the input file and line number as well. */
229 void
230 #if defined (VA_FPRINTF) && __STDC__
231 file_line_error (char *infile, int lno, const char *format, ...)
232 #else
233 file_line_error (infile, lno, format, va_alist)
234 char *infile;
235 int lno;
236 const char *format;
237 va_dcl
238 #endif
240 #ifdef VA_FPRINTF
241 va_list ap;
242 #endif
244 remember_error ();
245 fprintf (stderr, "%s:%d: ", infile, lno);
247 VA_START (ap, format);
248 #ifdef VA_FPRINTF
249 VA_FPRINTF (stderr, format, ap);
250 #else
251 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
252 #endif /* not VA_FPRINTF */
253 va_end (ap);
255 fprintf (stderr, ".\n");
258 /* Just like file_line_error (), but take the input file and the line
259 number from global variables. */
260 void
261 #if defined (VA_FPRINTF) && __STDC__
262 line_error (const char *format, ...)
263 #else
264 line_error (format, va_alist)
265 const char *format;
266 va_dcl
267 #endif
269 #ifdef VA_FPRINTF
270 va_list ap;
271 #endif
273 remember_error ();
274 fprintf (stderr, "%s:%d: ", input_filename, line_number);
276 VA_START (ap, format);
277 #ifdef VA_FPRINTF
278 VA_FPRINTF (stderr, format, ap);
279 #else
280 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
281 #endif /* not VA_FPRINTF */
282 va_end (ap);
284 fprintf (stderr, ".\n");
287 void
288 #if defined (VA_FPRINTF) && __STDC__
289 warning (const char *format, ...)
290 #else
291 warning (format, va_alist)
292 const char *format;
293 va_dcl
294 #endif
296 #ifdef VA_FPRINTF
297 va_list ap;
298 #endif
300 if (print_warnings)
302 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
304 VA_START (ap, format);
305 #ifdef VA_FPRINTF
306 VA_FPRINTF (stderr, format, ap);
307 #else
308 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
309 #endif /* not VA_FPRINTF */
310 va_end (ap);
312 fprintf (stderr, ".\n");
317 /* The other side of a malformed expression. */
318 static void
319 misplaced_brace (void)
321 line_error (_("Misplaced %c"), '}');
324 /* Main. */
326 /* Display the version info of this invocation of Makeinfo. */
327 static void
328 print_version_info (void)
330 printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION);
333 /* If EXIT_VALUE is zero, print the full usage message to stdout.
334 Otherwise, just say to use --help for more info.
335 Then exit with EXIT_VALUE. */
336 static void
337 usage (int exit_value)
339 if (exit_value != 0)
340 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
341 else
343 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname);
344 puts ("");
346 puts (_("\
347 Translate Texinfo source documentation to various other formats, by default\n\
348 Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
350 printf (_("\
351 General options:\n\
352 --error-limit=NUM quit after NUM errors (default %d).\n\
353 --force preserve output even if errors.\n\
354 --help display this help and exit.\n\
355 --no-validate suppress node cross-reference validation.\n\
356 --no-warn suppress warnings (but not errors).\n\
357 --reference-limit=NUM warn about at most NUM references (default %d).\n\
358 -v, --verbose explain what is being done.\n\
359 --version display version information and exit.\n"),
360 max_error_level, reference_warning_limit);
361 puts ("");
363 /* xgettext: no-wrap */
364 puts (_("\
365 Output format selection (default is to produce Info):\n\
366 --docbook output Docbook XML rather than Info.\n\
367 --html output HTML rather than Info.\n\
368 --xml output Texinfo XML rather than Info.\n\
369 --plaintext output plain text rather than Info.\n\
370 "));
372 puts (_("\
373 General output options:\n\
374 -E, --macro-expand FILE output macro-expanded source to FILE.\n\
375 ignoring any @setfilename.\n\
376 --no-headers suppress node separators, Node: lines, and menus\n\
377 from Info output (thus producing plain text)\n\
378 or from HTML (thus producing shorter output);\n\
379 also, write to standard output by default.\n\
380 --no-split suppress splitting of Info or HTML output,\n\
381 generate only one output file.\n\
382 --number-sections output chapter and sectioning numbers.\n\
383 -o, --output=FILE output to FILE (directory if split HTML),\n\
384 "));
386 printf (_("\
387 Options for Info and plain text:\n\
388 --enable-encoding output accented and special characters in\n\
389 Info output based on @documentencoding.\n\
390 --fill-column=NUM break Info lines at NUM characters (default %d).\n\
391 --footnote-style=STYLE output footnotes in Info according to STYLE:\n\
392 `separate' to put them in their own node;\n\
393 `end' to put them at the end of the node\n\
394 in which they are defined (default).\n\
395 --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
396 If VAL is `none', do not indent; if VAL is\n\
397 `asis', preserve existing indentation.\n\
398 --split-size=NUM split Info files at size NUM (default %d).\n"),
399 fill_column, paragraph_start_indent,
400 DEFAULT_SPLIT_SIZE);
401 puts ("");
403 puts (_("\
404 Options for HTML:\n\
405 --css-include=FILE include FILE in HTML <style> output;\n\
406 read stdin if FILE is -.\n\
407 "));
409 printf (_("\
410 Options for XML and Docbook:\n\
411 --output-indent=VAL indent XML elements by VAL spaces (default %d).\n\
412 If VAL is 0, ignorable whitespace is dropped.\n\
413 "), xml_indentation_increment);
414 puts ("");
416 puts (_("\
417 Input file options:\n\
418 --commands-in-node-names allow @ commands in node names.\n\
419 -D VAR define the variable VAR, as with @set.\n\
420 -I DIR append DIR to the @include search path.\n\
421 -P DIR prepend DIR to the @include search path.\n\
422 -U VAR undefine the variable VAR, as with @clear.\n\
423 "));
425 puts (_("\
426 Conditional processing in input:\n\
427 --ifdocbook process @ifdocbook and @docbook even if\n\
428 not generating Docbook.\n\
429 --ifhtml process @ifhtml and @html even if not generating HTML.\n\
430 --ifinfo process @ifinfo even if not generating Info.\n\
431 --ifplaintext process @ifplaintext even if not generating plain text.\n\
432 --iftex process @iftex and @tex; implies --no-split.\n\
433 --ifxml process @ifxml and @xml.\n\
434 --no-ifdocbook do not process @ifdocbook and @docbook text.\n\
435 --no-ifhtml do not process @ifhtml and @html text.\n\
436 --no-ifinfo do not process @ifinfo text.\n\
437 --no-ifplaintext do not process @ifplaintext text.\n\
438 --no-iftex do not process @iftex and @tex text.\n\
439 --no-ifxml do not process @ifxml and @xml text.\n\
441 Also, for the --no-ifFORMAT options, do process @ifnotFORMAT text.\n\
442 "));
444 puts (_("\
445 The defaults for the @if... conditionals depend on the output format:\n\
446 if generating HTML, --ifhtml is on and the others are off;\n\
447 if generating Info, --ifinfo is on and the others are off;\n\
448 if generating plain text, --ifplaintext is on and the others are off;\n\
449 if generating XML, --ifxml is on and the others are off.\n\
450 "));
452 fputs (_("\
453 Examples:\n\
454 makeinfo foo.texi write Info to foo's @setfilename\n\
455 makeinfo --html foo.texi write HTML to @setfilename\n\
456 makeinfo --xml foo.texi write Texinfo XML to @setfilename\n\
457 makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\
458 makeinfo --no-headers foo.texi write plain text to standard output\n\
460 makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
461 makeinfo --number-sections foo.texi write Info with numbered sections\n\
462 makeinfo --no-split foo.texi write one Info file however big\n\
463 "), stdout);
465 puts (_("\n\
466 Email bug reports to bug-texinfo@gnu.org,\n\
467 general questions and discussion to help-texinfo@gnu.org.\n\
468 Texinfo home page: http://www.gnu.org/software/texinfo/"));
470 } /* end of full help */
472 xexit (exit_value);
475 struct option long_options[] =
477 { "commands-in-node-names", 0, &expensive_validation, 1 },
478 { "css-include", 1, 0, 'C' },
479 { "docbook", 0, 0, 'd' },
480 { "enable-encoding", 0, &enable_encoding, 1 },
481 { "error-limit", 1, 0, 'e' },
482 { "fill-column", 1, 0, 'f' },
483 { "footnote-style", 1, 0, 's' },
484 { "force", 0, &force, 1 },
485 { "help", 0, 0, 'h' },
486 { "html", 0, 0, 'w' },
487 { "ifdocbook", 0, &process_docbook, 1 },
488 { "ifhtml", 0, &process_html, 1 },
489 { "ifinfo", 0, &process_info, 1 },
490 { "ifplaintext", 0, &process_plaintext, 1 },
491 { "iftex", 0, &process_tex, 1 },
492 { "ifxml", 0, &process_xml, 1 },
493 { "macro-expand", 1, 0, 'E' },
494 { "no-headers", 0, &no_headers, 1 },
495 { "no-ifdocbook", 0, &process_docbook, 0 },
496 { "no-ifhtml", 0, &process_html, 0 },
497 { "no-ifinfo", 0, &process_info, 0 },
498 { "no-ifplaintext", 0, &process_plaintext, 0 },
499 { "no-iftex", 0, &process_tex, 0 },
500 { "no-ifxml", 0, &process_xml, 0 },
501 { "no-number-footnotes", 0, &number_footnotes, 0 },
502 { "no-number-sections", 0, &number_sections, 0 },
503 { "no-pointer-validate", 0, &validating, 0 },
504 { "no-split", 0, &splitting, 0 },
505 { "no-validate", 0, &validating, 0 },
506 { "no-warn", 0, &print_warnings, 0 },
507 { "number-footnotes", 0, &number_footnotes, 1 },
508 { "number-sections", 0, &number_sections, 1 },
509 { "output", 1, 0, 'o' },
510 { "output-indent", 1, 0, 'i' },
511 { "paragraph-indent", 1, 0, 'p' },
512 { "plaintext", 0, 0, 't' },
513 { "reference-limit", 1, 0, 'r' },
514 { "split-size", 1, 0, 'S'},
515 { "verbose", 0, &verbose_mode, 1 },
516 { "version", 0, 0, 'V' },
517 { "xml", 0, 0, 'x' },
518 {NULL, 0, NULL, 0}
521 /* We use handle_variable_internal for -D and -U, and it depends on
522 execute_string, which depends on input_filename, which is not defined
523 while we are handling options. :-\ So we save these defines in this
524 struct, and handle them later. */
525 typedef struct command_line_define
527 struct command_line_define *next;
528 int action;
529 char *define;
530 } COMMAND_LINE_DEFINE;
532 static COMMAND_LINE_DEFINE *command_line_defines = NULL;
534 /* For each file mentioned in the command line, process it, turning
535 Texinfo commands into wonderfully formatted output text. */
537 main (int argc, char **argv)
539 int c, ind;
540 int reading_from_stdin = 0;
542 #ifdef HAVE_SETLOCALE
543 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
544 of the argument to @multicolumn. */
545 setlocale (LC_TIME, "");
546 #ifdef LC_MESSAGES /* ultrix */
547 setlocale (LC_MESSAGES, "");
548 #endif
549 setlocale (LC_CTYPE, "");
550 setlocale (LC_COLLATE, "");
551 #endif
553 #ifdef ENABLE_NLS
554 /* Set the text message domain. */
555 bindtextdomain (PACKAGE, LOCALEDIR);
556 textdomain (PACKAGE);
557 #endif
559 /* If TEXINFO_OUTPUT_FORMAT envvar is set, use it to set default output.
560 Can be overridden with one of the output options. */
561 if (getenv ("TEXINFO_OUTPUT_FORMAT") != NULL)
563 if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "docbook"))
565 splitting = 0;
566 html = 0;
567 docbook = 1;
568 xml = 1;
569 process_docbook = 1;
571 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "html"))
573 html = 1;
574 docbook = 0;
575 xml = 0;
576 process_html = 1;
578 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "info"))
580 html = 0;
581 docbook = 0;
582 xml = 0;
584 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "plaintext"))
586 splitting = 0;
587 no_headers = 1;
588 html = 0;
589 docbook = 0;
590 xml = 0;
591 process_plaintext = 1;
593 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "xml"))
595 splitting = 0;
596 html = 0;
597 docbook = 0;
598 xml = 1;
599 process_xml = 1;
601 else
602 fprintf (stderr,
603 _("%s: Ignoring unrecognized TEXINFO_OUTPUT_FORMAT value `%s'.\n"),
604 progname, getenv ("TEXINFO_OUTPUT_FORMAT"));
607 /* Parse argument flags from the input line. */
608 while ((c = getopt_long (argc, argv, "D:de:E:f:hI:i:o:p:P:r:s:t:U:vV:wx",
609 long_options, &ind)) != EOF)
611 if (c == 0 && long_options[ind].flag == 0)
612 c = long_options[ind].val;
614 switch (c)
616 case 'C': /* --css-include */
617 css_include = xstrdup (optarg);
618 break;
620 case 'D':
621 case 'U':
622 /* User specified variable to set or clear. */
623 if (xml && !docbook)
625 COMMAND_LINE_DEFINE *new = xmalloc (sizeof (COMMAND_LINE_DEFINE));
626 new->action = (c == 'D') ? SET : CLEAR;
627 new->define = xstrdup (optarg);
628 new->next = command_line_defines;
629 command_line_defines = new;
631 else
632 handle_variable_internal ((c == 'D' ? SET : CLEAR), optarg);
633 break;
635 case 'd': /* --docbook */
636 splitting = 0;
637 xml = 1;
638 docbook = 1;
639 html = 0;
640 process_docbook = 1;
641 break;
643 case 'e': /* --error-limit */
644 if (sscanf (optarg, "%d", &max_error_level) != 1)
646 fprintf (stderr,
647 _("%s: %s arg must be numeric, not `%s'.\n"),
648 progname, "--error-limit", optarg);
649 usage (1);
651 break;
653 case 'E': /* --macro-expand */
654 if (!macro_expansion_output_stream)
656 macro_expansion_filename = optarg;
657 macro_expansion_output_stream
658 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
659 if (!macro_expansion_output_stream)
660 error (_("%s: could not open macro expansion output `%s'"),
661 progname, optarg);
663 else
664 fprintf (stderr,
665 _("%s: ignoring second macro expansion output `%s'.\n"),
666 progname, optarg);
667 break;
669 case 'f': /* --fill-column */
670 if (sscanf (optarg, "%d", &fill_column) != 1)
672 fprintf (stderr,
673 _("%s: %s arg must be numeric, not `%s'.\n"),
674 progname, "--fill-column", optarg);
675 usage (1);
677 break;
679 case 'h': /* --help */
680 usage (0);
681 break;
683 case 'I':
684 /* Append user-specified dir to include file path. */
685 append_to_include_path (optarg);
686 break;
688 case 'i':
689 if (sscanf (optarg, "%d", &xml_indentation_increment) != 1)
691 fprintf (stderr,
692 _("%s: %s arg must be numeric, not `%s'.\n"),
693 progname, "--output-indent", optarg);
694 usage (1);
696 break;
698 case 'o': /* --output */
699 command_output_filename = xstrdup (optarg);
700 save_command_output_filename = command_output_filename;
701 break;
703 case 'p': /* --paragraph-indent */
704 if (set_paragraph_indent (optarg) < 0)
706 fprintf (stderr,
707 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
708 progname, optarg);
709 usage (1);
711 break;
713 case 'P':
714 /* Prepend user-specified include dir to include path. */
715 prepend_to_include_path (optarg);
716 break;
718 case 'r': /* --reference-limit */
719 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
721 fprintf (stderr,
722 _("%s: %s arg must be numeric, not `%s'.\n"),
723 progname, "--reference-limit", optarg);
724 usage (1);
726 break;
728 case 's': /* --footnote-style */
729 if (set_footnote_style (optarg) < 0)
731 fprintf (stderr,
732 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
733 progname, optarg);
734 usage (1);
736 footnote_style_preset = 1;
737 break;
739 case 'S': /* --split-size */
740 if (sscanf (optarg, "%d", &split_size) != 1)
742 fprintf (stderr,
743 _("%s: %s arg must be numeric, not `%s'.\n"),
744 progname, "--split-size", optarg);
745 usage (1);
747 break;
749 case 't': /* --plaintext */
750 splitting = 0;
751 no_headers = 1;
752 html = 0;
753 docbook = 0;
754 xml = 0;
755 process_plaintext = 1;
756 break;
758 case 'v':
759 verbose_mode++;
760 break;
762 case 'V': /* --version */
763 print_version_info ();
764 puts ("");
765 puts ("Copyright (C) 2004 Free Software Foundation, Inc.");
766 printf (_("There is NO warranty. You may redistribute this software\n\
767 under the terms of the GNU General Public License.\n\
768 For more information about these matters, see the files named COPYING.\n"));
769 xexit (0);
770 break;
772 case 'w': /* --html */
773 xml = 0;
774 docbook = 0;
775 html = 1;
776 process_html = 1;
777 break;
779 case 'x': /* --xml */
780 splitting = 0;
781 html = 0;
782 docbook = 0;
783 xml = 1;
784 process_xml = 1;
785 break;
787 case '?':
788 usage (1);
789 break;
793 if (macro_expansion_output_stream)
794 validating = 0;
796 if (!validating)
797 expensive_validation = 0;
799 if (optind == argc)
801 /* Check to see if input is a file. If so, process that. */
802 if (!isatty (fileno (stdin)))
803 reading_from_stdin = 1;
804 else
806 fprintf (stderr, _("%s: missing file argument.\n"), progname);
807 usage (1);
811 if (no_headers)
813 /* If the user did not specify an output file, use stdout. */
814 if (!command_output_filename)
815 command_output_filename = xstrdup ("-");
817 if (html && splitting && !STREQ (command_output_filename, "-"))
818 { /* --no-headers --no-split --html indicates confusion. */
819 fprintf (stderr,
820 "%s: can't split --html output to `%s' with --no-headers.\n",
821 progname, command_output_filename);
822 usage (1);
825 /* --no-headers implies --no-split. */
826 splitting = 0;
829 if (process_info == -1)
830 { /* no explicit --[no-]ifinfo option, so we'll do @ifinfo
831 if we're generating info or (for compatibility) plain text. */
832 process_info = !html && !xml;
835 if (process_plaintext == -1)
836 { /* no explicit --[no-]ifplaintext option, so we'll do @ifplaintext
837 if we're generating plain text. */
838 process_plaintext = no_headers && !html && !xml;
841 if (verbose_mode)
842 print_version_info ();
844 /* Remaining arguments are file names of texinfo files.
845 Convert them, one by one. */
846 if (!reading_from_stdin)
848 while (optind != argc)
849 convert_from_file (argv[optind++]);
851 else
852 convert_from_stream (stdin, "stdin");
854 xexit (errors_printed ? 2 : 0);
855 return 0; /* Avoid bogus warnings. */
858 /* Hacking tokens and strings. */
860 /* Return the next token as a string pointer. We cons the string. This
861 `token' means simply a command name. */
863 /* = is so @alias works. ^ and _ are so macros can be used in math mode
864 without a space following. Possibly we should simply allow alpha, to
865 be compatible with TeX. */
866 #define COMMAND_CHAR(c) (!cr_or_whitespace(c) \
867 && (c) != '{' \
868 && (c) != '}' \
869 && (c) != '=' \
870 && (c) != '_' \
871 && (c) != '^' \
874 static char *
875 read_token (void)
877 int i, character;
878 char *result;
880 /* If the first character to be read is self-delimiting, then that
881 is the command itself. */
882 character = curchar ();
883 if (self_delimiting (character))
885 input_text_offset++;
887 if (character == '\n')
888 line_number++;
890 result = xstrdup (" ");
891 *result = character;
892 return result;
895 for (i = 0; ((input_text_offset != input_text_length)
896 && (character = curchar ())
897 && COMMAND_CHAR (character));
898 i++, input_text_offset++);
899 result = xmalloc (i + 1);
900 memcpy (result, &input_text[input_text_offset - i], i);
901 result[i] = 0;
902 return result;
905 /* Return nonzero if CHARACTER is self-delimiting. */
907 self_delimiting (int character)
909 /* @; and @\ are not Texinfo commands, but they are listed here
910 anyway. I don't know why. --karl, 10aug96. */
911 return strchr ("~{|}`^\\@?=;:./-,*\'\" !\n\t", character) != NULL;
914 /* Clear whitespace from the front and end of string. */
915 void
916 canon_white (char *string)
918 char *p = string;
919 unsigned len;
921 if (!*p)
922 return;
926 if (!cr_or_whitespace (*p))
927 break;
928 ++p;
930 while (*p);
932 len = strlen (p);
933 while (len && cr_or_whitespace (p[len-1]))
934 --len;
936 if (p != string)
937 memmove (string, p, len);
939 string[len] = 0;
942 /* Bash STRING, replacing all whitespace with just one space. */
943 void
944 fix_whitespace (char *string)
946 char *temp = xmalloc (strlen (string) + 1);
947 int string_index = 0;
948 int temp_index = 0;
949 int c;
951 canon_white (string);
953 while (string[string_index])
955 c = temp[temp_index++] = string[string_index++];
957 if (c == ' ' || c == '\n' || c == '\t')
959 temp[temp_index - 1] = ' ';
960 while ((c = string[string_index]) && (c == ' ' ||
961 c == '\t' ||
962 c == '\n'))
963 string_index++;
966 temp[temp_index] = 0;
967 strcpy (string, temp);
968 free (temp);
971 /* Discard text until the desired string is found. The string is
972 included in the discarded text. */
973 void
974 discard_until (char *string)
976 int temp = search_forward (string, input_text_offset);
978 int tt = (temp < 0) ? input_text_length : temp + strlen (string);
979 int from = input_text_offset;
981 /* Find out what line we are on. */
982 while (from != tt)
983 if (input_text[from++] == '\n')
984 line_number++;
986 if (temp < 0)
988 /* not found, move current position to end of string */
989 input_text_offset = input_text_length;
990 if (strcmp (string, "\n") != 0)
991 { /* Give a more descriptive feedback, if we are looking for ``@end ''
992 during macro execution. That means someone used a multiline
993 command as an argument to, say, @section ... style commands. */
994 char *end_block = xmalloc (8);
995 sprintf (end_block, "\n%cend ", COMMAND_PREFIX);
996 if (executing_string && strstr (string, end_block))
997 line_error (_("Multiline command %c%s used improperly"),
998 COMMAND_PREFIX, command);
999 else
1000 line_error (_("Expected `%s'"), string);
1001 free (end_block);
1002 return;
1005 else
1006 /* found, move current position to after the found string */
1007 input_text_offset = temp + strlen (string);
1010 /* Read characters from the file until we are at MATCH.
1011 Place the characters read into STRING.
1012 On exit input_text_offset is after the match string.
1013 Return the offset where the string starts. */
1015 get_until (char *match, char **string)
1017 int len, current_point, x, new_point, tem;
1019 current_point = x = input_text_offset;
1020 new_point = search_forward (match, input_text_offset);
1022 if (new_point < 0)
1023 new_point = input_text_length;
1024 len = new_point - current_point;
1026 /* Keep track of which line number we are at. */
1027 tem = new_point + (strlen (match) - 1);
1028 while (x != tem)
1029 if (input_text[x++] == '\n')
1030 line_number++;
1032 *string = xmalloc (len + 1);
1034 memcpy (*string, &input_text[current_point], len);
1035 (*string)[len] = 0;
1037 /* Now leave input_text_offset in a consistent state. */
1038 input_text_offset = tem;
1040 if (input_text_offset > input_text_length)
1041 input_text_offset = input_text_length;
1043 return new_point;
1046 /* Replace input_text[FROM .. TO] with its expansion. */
1047 void
1048 replace_with_expansion (int from, int *to)
1050 char *xp;
1051 unsigned xp_len, new_len;
1052 char *old_input = input_text;
1053 unsigned raw_len = *to - from;
1054 char *str;
1056 /* The rest of the code here moves large buffers, so let's
1057 not waste time if the input cannot possibly expand
1058 into anything. Unfortunately, we cannot avoid expansion
1059 when we see things like @code etc., even if they only
1060 asked for expansion of macros, since any Texinfo command
1061 can be potentially redefined with a macro. */
1062 if (only_macro_expansion &&
1063 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
1064 return;
1066 /* Get original string from input. */
1067 str = xmalloc (raw_len + 1);
1068 memcpy (str, input_text + from, raw_len);
1069 str[raw_len] = 0;
1071 /* We are going to relocate input_text, so we had better output
1072 pending portion of input_text now, before the pointer changes. */
1073 if (macro_expansion_output_stream && !executing_string
1074 && !me_inhibit_expansion)
1075 append_to_expansion_output (from);
1077 /* Expand it. */
1078 xp = expansion (str, 0);
1079 xp_len = strlen (xp);
1080 free (str);
1082 /* Plunk the expansion into the middle of `input_text' --
1083 which is terminated by a newline, not a null. Avoid
1084 expensive move of the rest of the input if the expansion
1085 has the same length as the original string. */
1086 if (xp_len != raw_len)
1088 new_len = from + xp_len + input_text_length - *to + 1;
1089 if (executing_string)
1090 { /* If we are in execute_string, we might need to update
1091 the relevant element in the execution_strings[] array,
1092 since it could have to be relocated from under our
1093 feet. (input_text is reallocated here as well, if needed.) */
1094 maybe_update_execution_strings (&input_text, new_len);
1096 else if (new_len > input_text_length + 1)
1097 /* Don't bother to realloc if we have enough space. */
1098 input_text = xrealloc (input_text, new_len);
1100 memmove (input_text + from + xp_len,
1101 input_text + *to, input_text_length - *to + 1);
1103 *to += xp_len - raw_len;
1104 /* Since we change input_text_length here, the comparison above
1105 isn't really valid, but it seems the worst that might happen is
1106 an extra xrealloc or two, so let's not worry. */
1107 input_text_length += xp_len - raw_len;
1109 memcpy (input_text + from, xp, xp_len);
1110 free (xp);
1112 /* Synchronize the macro-expansion pointers with our new input_text. */
1113 if (input_text != old_input)
1114 forget_itext (old_input);
1115 if (macro_expansion_output_stream && !executing_string)
1116 remember_itext (input_text, from);
1119 /* Read characters from the file until we are at MATCH or end of line.
1120 Place the characters read into STRING. If EXPAND is nonzero,
1121 expand the text before looking for MATCH for those cases where
1122 MATCH might be produced by some macro. */
1123 void
1124 get_until_in_line (int expand, char *match, char **string)
1126 int real_bottom = input_text_length;
1127 int limit = search_forward ("\n", input_text_offset);
1128 if (limit < 0)
1129 limit = input_text_length;
1131 /* Replace input_text[input_text_offset .. limit-1] with its expansion.
1132 This allows the node names and menu entries themselves to be
1133 constructed via a macro, as in:
1134 @macro foo{p, q}
1135 Together: \p\ & \q\.
1136 @end macro
1138 @node @foo{A,B}, next, prev, top
1140 Otherwise, the `,' separating the macro args A and B is taken as
1141 the node argument separator, so the node name is `@foo{A'. This
1142 expansion is only necessary on the first call, since we expand the
1143 whole line then. */
1144 if (expand)
1146 replace_with_expansion (input_text_offset, &limit);
1149 real_bottom = input_text_length;
1150 input_text_length = limit;
1151 get_until (match, string);
1152 input_text_length = real_bottom;
1155 void
1156 get_rest_of_line (int expand, char **string)
1158 xml_no_para ++;
1159 if (expand)
1161 char *tem;
1163 /* Don't expand non-macros in input, since we want them
1164 intact in the macro-expanded output. */
1165 only_macro_expansion++;
1166 get_until_in_line (1, "\n", &tem);
1167 only_macro_expansion--;
1168 *string = expansion (tem, 0);
1169 free (tem);
1171 else
1172 get_until_in_line (0, "\n", string);
1174 canon_white (*string);
1176 if (curchar () == '\n') /* as opposed to the end of the file... */
1178 line_number++;
1179 input_text_offset++;
1181 xml_no_para --;
1184 /* Backup the input pointer to the previous character, keeping track
1185 of the current line number. */
1186 void
1187 backup_input_pointer (void)
1189 if (input_text_offset)
1191 input_text_offset--;
1192 if (curchar () == '\n')
1193 line_number--;
1197 /* Read characters from the file until we are at MATCH or closing brace.
1198 Place the characters read into STRING. */
1199 void
1200 get_until_in_braces (char *match, char **string)
1202 char *temp;
1203 int i, brace = 0;
1204 int match_len = strlen (match);
1206 for (i = input_text_offset; i < input_text_length; i++)
1208 if (i < input_text_length - 1 && input_text[i] == '@')
1210 i++; /* skip commands like @, and @{ */
1211 continue;
1213 else if (input_text[i] == '{')
1214 brace++;
1215 else if (input_text[i] == '}')
1217 brace--;
1218 /* If looking for a brace, don't stop at the interior brace,
1219 like after "baz" in "@foo{something @bar{baz} more}". */
1220 if (brace == 0)
1221 continue;
1223 else if (input_text[i] == '\n')
1224 line_number++;
1226 if (brace < 0 ||
1227 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1228 break;
1231 match_len = i - input_text_offset;
1232 temp = xmalloc (2 + match_len);
1233 memcpy (temp, input_text + input_text_offset, match_len);
1234 temp[match_len] = 0;
1235 input_text_offset = i;
1236 *string = temp;
1241 /* Converting a file. */
1243 /* Convert the file named by NAME. The output is saved on the file
1244 named as the argument to the @setfilename command. */
1245 static char *suffixes[] = {
1246 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1247 have "texinfo.txi" and "texinfo.tex" in the same directory, the
1248 former is used rather than the latter, due to file name truncation. */
1249 ".txi",
1250 ".texinfo",
1251 ".texi",
1252 ".txinfo",
1254 NULL
1257 static void
1258 initialize_conversion (void)
1260 init_tag_table ();
1261 init_indices ();
1262 init_internals ();
1263 init_paragraph ();
1265 /* This is used for splitting the output file and for doing section
1266 headings. It was previously initialized in `init_paragraph', but its
1267 use there loses with the `init_paragraph' calls done by the
1268 multitable code; the tag indices get reset to zero. */
1269 output_position = 0;
1272 /* Reverse the chain of structures in LIST. Output the new head
1273 of the chain. You should always assign the output value of this
1274 function to something, or you will lose the chain. */
1275 GENERIC_LIST *
1276 reverse_list (GENERIC_LIST *list)
1278 GENERIC_LIST *next;
1279 GENERIC_LIST *prev = NULL;
1281 while (list)
1283 next = list->next;
1284 list->next = prev;
1285 prev = list;
1286 list = next;
1288 return prev;
1291 /* We read in multiples of 4k, simply because it is a typical pipe size
1292 on unix systems. */
1293 #define READ_BUFFER_GROWTH (4 * 4096)
1295 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1296 source of the stream is named NAME. */
1297 static void
1298 convert_from_stream (FILE *stream, char *name)
1300 char *buffer = NULL;
1301 int buffer_offset = 0, buffer_size = 0;
1303 initialize_conversion ();
1305 /* Read until the end of the stream. This isn't strictly correct, since
1306 the texinfo input may end before the stream ends, but it is a quick
1307 working hueristic. */
1308 while (!feof (stream))
1310 int count;
1312 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1313 buffer = (char *)
1314 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1316 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1318 if (count < 0)
1320 perror (name);
1321 xexit (1);
1324 buffer_offset += count;
1325 if (count == 0)
1326 break;
1329 /* Set the globals to the new file. */
1330 input_text = buffer;
1331 input_text_length = buffer_offset;
1332 input_filename = xstrdup (name);
1333 node_filename = xstrdup (name);
1334 input_text_offset = 0;
1335 line_number = 1;
1337 /* Not strictly necessary. This magic prevents read_token () from doing
1338 extra unnecessary work each time it is called (that is a lot of times).
1339 The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1340 input_text[input_text_length] = '\n';
1342 convert_from_loaded_file (name);
1345 static void
1346 convert_from_file (char *name)
1348 int i;
1349 char *filename = xmalloc (strlen (name) + 50);
1351 /* Prepend file directory to the search path, so relative links work. */
1352 prepend_to_include_path (pathname_part (name));
1354 initialize_conversion ();
1356 /* Try to load the file specified by NAME, concatenated with our
1357 various suffixes. Prefer files like `makeinfo.texi' to
1358 `makeinfo'. */
1359 for (i = 0; suffixes[i]; i++)
1361 strcpy (filename, name);
1362 strcat (filename, suffixes[i]);
1364 if (find_and_load (filename, 1))
1365 break;
1367 if (!suffixes[i][0] && strrchr (filename, '.'))
1369 fs_error (filename);
1370 free (filename);
1371 return;
1375 if (!suffixes[i])
1377 fs_error (name);
1378 free (filename);
1379 return;
1382 input_filename = filename;
1384 convert_from_loaded_file (name);
1386 /* Pop the prepended path, so multiple filenames in the
1387 command line do not screw each others include paths. */
1388 pop_path_from_include_path ();
1391 static int
1392 create_html_directory (char *dir, int can_remove_file)
1394 struct stat st;
1396 /* Already exists. */
1397 if (stat (dir, &st) == 0)
1399 /* And it's a directory, so silently reuse it. */
1400 if (S_ISDIR (st.st_mode))
1401 return 1;
1402 /* Not a directory, so move it out of the way if we are allowed. */
1403 else if (can_remove_file)
1405 if (unlink (dir) != 0)
1406 return 0;
1408 else
1409 return 0;
1412 if (mkdir (dir, 0777) == 0)
1413 /* Success! */
1414 return 1;
1415 else
1416 return 0;
1419 /* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
1420 "/foo/bar/baz/baz.html". This routine is called only if html && splitting.
1422 Split html output goes into the subdirectory of the toplevel
1423 filename, without extension. For example:
1424 @setfilename foo.info
1425 produces output in files foo/index.html, foo/second-node.html, ...
1427 But if the user said -o foo.whatever on the cmd line, then use
1428 foo.whatever unchanged. */
1430 static char *
1431 insert_toplevel_subdirectory (char *output_filename)
1433 static const char index_name[] = "index.html";
1434 char *dir, *subdir, *base, *basename, *p;
1435 char buf[PATH_MAX];
1436 const int index_len = sizeof (index_name) - 1;
1438 strcpy (buf, output_filename);
1439 dir = pathname_part (buf); /* directory of output_filename */
1440 base = filename_part (buf); /* strips suffix, too */
1441 basename = xstrdup (base); /* remember real @setfilename name */
1442 p = dir + strlen (dir) - 1;
1443 if (p > dir && IS_SLASH (*p))
1444 *p = 0;
1445 p = strrchr (base, '.');
1446 if (p)
1447 *p = 0;
1449 /* Split html output goes into subdirectory of toplevel name. */
1450 if (save_command_output_filename
1451 && STREQ (output_filename, save_command_output_filename))
1452 subdir = basename; /* from user, use unchanged */
1453 else
1454 subdir = base; /* implicit, omit suffix */
1456 free (output_filename);
1457 output_filename = xmalloc (strlen (dir) + 1
1458 + strlen (basename) + 1
1459 + index_len
1460 + 1);
1461 strcpy (output_filename, dir);
1462 if (strlen (dir))
1463 strcat (output_filename, "/");
1464 strcat (output_filename, subdir);
1466 /* First try, do not remove existing file. */
1467 if (!create_html_directory (output_filename, 0))
1469 /* That failed, try subdir name with .html.
1470 Remove it if it exists. */
1471 strcpy (output_filename, dir);
1472 if (strlen (dir))
1473 strcat (output_filename, "/");
1474 strcat (output_filename, basename);
1476 if (!create_html_directory (output_filename, 1))
1478 /* Last try failed too :-\ */
1479 line_error (_("Can't create directory `%s': %s"),
1480 output_filename, strerror (errno));
1481 xexit (1);
1485 strcat (output_filename, "/");
1486 strcat (output_filename, index_name);
1487 return output_filename;
1490 /* FIXME: this is way too hairy */
1491 static void
1492 convert_from_loaded_file (char *name)
1494 char *real_output_filename = NULL;
1496 remember_itext (input_text, 0);
1498 input_text_offset = 0;
1500 /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1501 the file). */
1502 if (looking_at ("\\input"))
1503 discard_until ("\n");
1505 /* Search this file looking for the special string which starts conversion.
1506 Once found, we may truly begin. */
1507 while (input_text_offset >= 0)
1509 input_text_offset =
1510 search_forward (setfilename_search, input_text_offset);
1512 if (input_text_offset == 0
1513 || (input_text_offset > 0
1514 && input_text[input_text_offset -1] == '\n'))
1515 break;
1516 else if (input_text_offset > 0)
1517 input_text_offset++;
1520 if (input_text_offset < 0)
1522 if (!command_output_filename)
1524 #if defined (REQUIRE_SETFILENAME)
1525 error (_("No `%s' found in `%s'"), setfilename_search, name);
1526 goto finished;
1527 #else
1528 command_output_filename = output_name_from_input_name (name);
1529 #endif /* !REQUIRE_SETFILENAME */
1533 int i, end_of_first_line;
1535 /* Find the end of the first line in the file. */
1536 for (i = 0; i < input_text_length - 1; i++)
1537 if (input_text[i] == '\n')
1538 break;
1540 end_of_first_line = i + 1;
1542 for (i = 0; i < end_of_first_line; i++)
1544 if ((input_text[i] == '\\') &&
1545 (strncmp (input_text + i + 1, "input", 5) == 0))
1547 input_text_offset = i;
1548 break;
1553 else
1554 input_text_offset += strlen (setfilename_search);
1556 if (!command_output_filename)
1558 get_until ("\n", &output_filename); /* read rest of line */
1559 if (html || xml)
1560 { /* Change any extension to .html or .xml. */
1561 char *html_name, *directory_part, *basename_part, *temp;
1563 canon_white (output_filename);
1564 directory_part = pathname_part (output_filename);
1566 basename_part = filename_part (output_filename);
1568 /* Zap any existing extension. */
1569 temp = strrchr (basename_part, '.');
1570 if (temp)
1571 *temp = 0;
1573 /* Construct new filename. */
1574 html_name = xmalloc (strlen (directory_part)
1575 + strlen (basename_part) + 6);
1576 strcpy (html_name, directory_part);
1577 strcat (html_name, basename_part);
1578 strcat (html_name, html ? ".html" : ".xml");
1580 /* Replace name from @setfilename with the html name. */
1581 free (output_filename);
1582 output_filename = html_name;
1585 else
1587 if (input_text_offset != -1)
1588 discard_until ("\n");
1589 else
1590 input_text_offset = 0;
1592 real_output_filename = output_filename = command_output_filename;
1593 command_output_filename = NULL; /* for included files or whatever */
1596 canon_white (output_filename);
1597 toplevel_output_filename = xstrdup (output_filename);
1599 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1601 if (macro_expansion_filename
1602 && strcmp (macro_expansion_filename, "-") == 0)
1604 fprintf (stderr,
1605 _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1606 progname);
1607 macro_expansion_output_stream = NULL;
1609 real_output_filename = xstrdup (real_output_filename);
1610 output_stream = stdout;
1611 splitting = 0; /* Cannot split when writing to stdout. */
1613 else
1615 if (html && splitting)
1617 if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
1618 || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
1619 splitting = 0;
1620 else
1621 output_filename = insert_toplevel_subdirectory (output_filename);
1622 real_output_filename = xstrdup (output_filename);
1624 else if (!real_output_filename)
1625 real_output_filename = expand_filename (output_filename, name);
1626 else
1627 real_output_filename = xstrdup (real_output_filename);
1629 output_stream = fopen (real_output_filename, "w");
1632 set_current_output_filename (real_output_filename);
1634 if (xml && !docbook)
1635 xml_begin_document (filename_part (output_filename));
1637 if (verbose_mode)
1638 printf (_("Making %s file `%s' from `%s'.\n"),
1639 no_headers ? "text"
1640 : html ? "HTML"
1641 : xml ? "XML"
1642 : "info",
1643 output_filename, input_filename);
1645 if (output_stream == NULL)
1647 fs_error (real_output_filename);
1648 goto finished;
1651 /* Make the displayable filename from output_filename. Only the base
1652 portion of the filename need be displayed. */
1653 flush_output (); /* in case there was no @bye */
1654 if (output_stream != stdout)
1655 pretty_output_filename = filename_part (output_filename);
1656 else
1657 pretty_output_filename = xstrdup ("stdout");
1659 /* For this file only, count the number of newlines from the top of
1660 the file to here. This way, we keep track of line numbers for
1661 error reporting. Line_number starts at 1, since the user isn't
1662 zero-based. */
1664 int temp = 0;
1665 line_number = 1;
1666 while (temp != input_text_offset)
1667 if (input_text[temp++] == '\n')
1668 line_number++;
1671 /* html fixxme: should output this as trailer on first page. */
1672 if (!no_headers && !html && !xml)
1673 add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
1674 output_filename, VERSION, input_filename);
1676 close_paragraph ();
1678 if (xml && !docbook)
1680 /* Just before the real main loop, let's handle the defines. */
1681 COMMAND_LINE_DEFINE *temp;
1683 for (temp = command_line_defines; temp; temp = temp->next)
1685 handle_variable_internal (temp->action, temp->define);
1686 free(temp->define);
1690 reader_loop ();
1691 if (xml)
1692 xml_end_document ();
1695 finished:
1696 discard_insertions (0);
1697 close_paragraph ();
1698 flush_file_stack ();
1700 if (macro_expansion_output_stream)
1702 fclose (macro_expansion_output_stream);
1703 if (errors_printed && !force
1704 && strcmp (macro_expansion_filename, "-") != 0
1705 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1706 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1708 fprintf (stderr,
1709 _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1710 progname, macro_expansion_filename);
1711 if (unlink (macro_expansion_filename) < 0)
1712 perror (macro_expansion_filename);
1716 if (output_stream)
1718 output_pending_notes ();
1720 if (html)
1722 no_indent = 1;
1723 start_paragraph ();
1724 add_word ("</body></html>\n");
1725 close_paragraph ();
1728 /* maybe we want local variables in info output. */
1730 char *trailer = info_trailer ();
1731 if (!xml && !docbook && trailer)
1733 if (html)
1734 insert_string ("<!--");
1735 insert_string (trailer);
1736 free (trailer);
1737 if (html)
1738 insert_string ("\n-->\n");
1742 /* Write stuff makeinfo generates after @bye, ie. info_trailer. */
1743 flush_output ();
1745 if (output_stream != stdout)
1746 fclose (output_stream);
1748 /* If validating, then validate the entire file right now. */
1749 if (validating)
1750 validate_file (tag_table);
1752 handle_delayed_writes ();
1754 if (tag_table)
1756 tag_table = (TAG_ENTRY *) reverse_list ((GENERIC_LIST *) tag_table);
1757 if (!no_headers && !html && !STREQ (current_output_filename, "-"))
1758 write_tag_table (real_output_filename);
1761 if (splitting && !html && (!errors_printed || force))
1763 clean_old_split_files (real_output_filename);
1764 split_file (real_output_filename, split_size);
1766 else if (errors_printed
1767 && !force
1768 && strcmp (real_output_filename, "-") != 0
1769 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1770 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1771 { /* If there were errors, and no --force, remove the output. */
1772 fprintf (stderr,
1773 _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1774 progname, real_output_filename);
1775 if (unlink (real_output_filename) < 0)
1776 perror (real_output_filename);
1779 free (real_output_filename);
1782 /* If enable_encoding is set and @documentencoding is used, return a
1783 Local Variables section (as a malloc-ed string) so that Emacs'
1784 locale features can work. Else return NULL. */
1785 char *
1786 info_trailer (void)
1788 char *encoding;
1790 if (!enable_encoding)
1791 return NULL;
1793 encoding = current_document_encoding ();
1795 if (encoding && *encoding)
1797 #define LV_FMT "\n\037\nLocal Variables:\ncoding: %s\nEnd:\n"
1798 char *lv = xmalloc (sizeof (LV_FMT) + strlen (encoding));
1799 sprintf (lv, LV_FMT, encoding);
1800 free (encoding);
1801 return lv;
1804 free (encoding);
1805 return NULL;
1808 void
1809 free_and_clear (char **pointer)
1811 if (*pointer)
1813 free (*pointer);
1814 *pointer = NULL;
1818 /* Initialize some state. */
1819 static void
1820 init_internals (void)
1822 free_and_clear (&output_filename);
1823 free_and_clear (&command);
1824 free_and_clear (&input_filename);
1825 free_node_references ();
1826 free_node_node_references ();
1827 toc_free ();
1828 init_insertion_stack ();
1829 init_brace_stack ();
1830 current_node = NULL; /* sometimes already freed */
1831 command_index = 0;
1832 in_menu = 0;
1833 in_detailmenu = 0;
1834 top_node_seen = 0;
1835 non_top_node_seen = 0;
1836 node_number = -1;
1839 void
1840 init_paragraph (void)
1842 free (output_paragraph);
1843 output_paragraph = xmalloc (paragraph_buffer_len);
1844 output_paragraph[0] = 0;
1845 output_paragraph_offset = 0;
1846 output_column = 0;
1847 paragraph_is_open = 0;
1848 current_indent = 0;
1849 meta_char_pos = 0;
1852 /* This is called from `reader_loop' when we are at the * beginning a
1853 menu line. */
1855 static void
1856 handle_menu_entry (void)
1858 char *tem;
1860 /* Ugh, glean_node_from_menu wants to read the * itself. */
1861 input_text_offset--;
1863 /* Find node name in menu entry and save it in references list for
1864 later validation. Use followed_reference type for detailmenu
1865 references since we don't want to use them for default node pointers. */
1866 tem = glean_node_from_menu (1, in_detailmenu
1867 ? followed_reference : menu_reference);
1869 if (html && tem)
1870 { /* Start a menu item with the cleaned-up line. Put an anchor
1871 around the start text (before `:' or the node name). */
1872 char *string;
1874 discard_until ("* ");
1876 /* The line number was already incremented in reader_loop when we
1877 saw the newline, and discard_until has now incremented again. */
1878 line_number--;
1880 if (had_menu_commentary)
1882 add_html_block_elt ("<ul class=\"menu\">\n");
1883 had_menu_commentary = 0;
1884 in_paragraph = 0;
1887 if (in_paragraph)
1889 add_html_block_elt ("</p>\n");
1890 add_html_block_elt ("<ul class=\"menu\">\n");
1891 in_paragraph = 0;
1894 in_menu_item = 1;
1896 add_html_block_elt ("<li><a");
1897 if (next_menu_item_number <= 9)
1899 add_word(" accesskey=");
1900 add_word_args("\"%d\"", next_menu_item_number);
1901 next_menu_item_number++;
1903 add_word (" href=\"");
1904 string = expansion (tem, 0);
1905 add_anchor_name (string, 1);
1906 add_word ("\">");
1907 free (string);
1909 /* The menu item may use macros, so expand them now. */
1910 only_macro_expansion++;
1911 get_until_in_line (1, ":", &string);
1912 only_macro_expansion--;
1913 execute_string ("%s", string); /* get escaping done */
1914 free (string);
1916 add_word ("</a>");
1918 if (looking_at ("::"))
1919 discard_until (":");
1920 else
1921 { /* discard the node name */
1922 get_until_in_line (0, ".", &string);
1923 free (string);
1925 input_text_offset++; /* discard the second colon or the period */
1927 /* Insert a colon only if there is a description of this menu item. */
1929 int save_input_text_offset = input_text_offset;
1930 int save_line_number = line_number;
1931 char *test_string;
1932 get_rest_of_line (0, &test_string);
1933 if (strlen (test_string) > 0)
1934 add_word (": ");
1935 input_text_offset = save_input_text_offset;
1936 line_number = save_line_number;
1939 else if (xml && tem)
1941 xml_start_menu_entry (tem);
1943 else if (tem)
1944 { /* For Info output, we can just use the input and the main case in
1945 reader_loop where we output what comes in. Just move off the *
1946 so the next time through reader_loop we don't end up back here. */
1947 add_char ('*');
1948 input_text_offset += 2; /* undo the pointer back-up above. */
1951 if (tem)
1952 free (tem);
1955 /* Find the command corresponding to STRING. If the command is found,
1956 return a pointer to the data structure. Otherwise return -1. */
1957 static COMMAND *
1958 get_command_entry (char *string)
1960 int i;
1962 for (i = 0; command_table[i].name; i++)
1963 if (strcmp (command_table[i].name, string) == 0)
1964 return &command_table[i];
1966 /* This command is not in our predefined command table. Perhaps
1967 it is a user defined command. */
1968 for (i = 0; i < user_command_array_len; i++)
1969 if (user_command_array[i] &&
1970 (strcmp (user_command_array[i]->name, string) == 0))
1971 return user_command_array[i];
1973 /* We never heard of this command. */
1974 return (COMMAND *) -1;
1977 /* input_text_offset is right at the command prefix character.
1978 Read the next token to determine what to do. Return zero
1979 if there's no known command or macro after the prefix character. */
1980 static int
1981 read_command (void)
1983 COMMAND *entry;
1984 int old_text_offset = input_text_offset++;
1986 free_and_clear (&command);
1987 command = read_token ();
1989 /* Check to see if this command is a macro. If so, execute it here. */
1991 MACRO_DEF *def;
1993 def = find_macro (command);
1995 if (def)
1997 /* We disallow recursive use of a macro call. Inhibit the expansion
1998 of this macro during the life of its execution. */
1999 if (!(def->flags & ME_RECURSE))
2000 def->inhibited = 1;
2002 executing_macro++;
2003 execute_macro (def);
2004 executing_macro--;
2006 if (!(def->flags & ME_RECURSE))
2007 def->inhibited = 0;
2009 return 1;
2013 if (only_macro_expansion)
2015 /* Back up to the place where we were called, so the
2016 caller will have a chance to process this non-macro. */
2017 input_text_offset = old_text_offset;
2018 return 0;
2021 /* Perform alias expansion */
2022 command = alias_expand (command);
2024 if (enclosure_command (command))
2026 remember_brace (enclosure_expand);
2027 enclosure_expand (START, output_paragraph_offset, 0);
2028 return 0;
2031 entry = get_command_entry (command);
2032 if (entry == (COMMAND *)-1)
2034 line_error (_("Unknown command `%s'"), command);
2035 return 0;
2038 if (entry->argument_in_braces == BRACE_ARGS)
2039 remember_brace (entry->proc);
2040 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
2042 if (curchar () == '{')
2043 remember_brace (entry->proc);
2044 else
2045 { /* No braces, so arg is next char. */
2046 int ch;
2047 int saved_offset = output_paragraph_offset;
2048 (*(entry->proc)) (START, output_paragraph_offset, 0);
2050 /* Possibilities left for the next character: @ (error), }
2051 (error), whitespace (skip) anything else (normal char). */
2052 skip_whitespace ();
2053 ch = curchar ();
2054 if (ch == '@')
2056 line_error (_("Use braces to give a command as an argument to @%s"),
2057 entry->name);
2058 return 0;
2060 else if (ch == '}')
2062 /* Our caller will give the error message, because this }
2063 won't match anything. */
2064 return 0;
2067 add_char (ch);
2068 input_text_offset++;
2069 (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
2070 return 1;
2074 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
2075 with braces. */
2076 (*(entry->proc)) (START, output_paragraph_offset, 0);
2077 return 1;
2080 /* Okay, we are ready to start the conversion. Call the reader on
2081 some text, and fill the text as it is output. Handle commands by
2082 remembering things like open braces and the current file position on a
2083 stack, and when the corresponding close brace is found, you can call
2084 the function with the proper arguments. Although the filling isn't
2085 necessary for HTML, it should do no harm. */
2086 void
2087 reader_loop (void)
2089 int character;
2090 int done = 0;
2092 while (!done)
2094 if (input_text_offset >= input_text_length)
2095 break;
2097 character = curchar ();
2099 /* If only_macro_expansion, only handle macros and leave
2100 everything else intact. */
2101 if (!only_macro_expansion && !in_fixed_width_font
2102 && ((!html && !xml) || escape_html)
2103 && (character == '\'' || character == '`')
2104 && input_text[input_text_offset + 1] == character)
2106 if (html)
2108 input_text_offset += 2;
2109 add_word (character == '`' ? "&ldquo;" : "&rdquo;");
2110 continue;
2112 else if (xml)
2114 input_text_offset += 2;
2115 xml_insert_entity (character == '`' ? "ldquo" : "rdquo");
2116 continue;
2118 else
2120 input_text_offset++;
2121 character = '"';
2125 /* Convert --- to --. */
2126 if (!only_macro_expansion && character == '-' && !in_fixed_width_font
2127 && ((!html && !xml) || escape_html))
2129 int dash_count = 0;
2131 /* Get the number of consequtive dashes. */
2132 while (input_text[input_text_offset] == '-')
2134 dash_count++;
2135 input_text_offset++;
2138 /* Eat one dash. */
2139 dash_count--;
2141 if (html || xml)
2143 if (dash_count == 0)
2144 add_char ('-');
2145 else
2146 while (dash_count > 0)
2148 if (dash_count >= 2)
2150 if (html)
2151 add_word ("&mdash;");
2152 else
2153 xml_insert_entity ("mdash");
2154 dash_count -= 2;
2156 else if (dash_count >= 1)
2158 if (html)
2159 add_word ("&ndash;");
2160 else
2161 xml_insert_entity ("ndash");
2162 dash_count--;
2166 else
2168 add_char ('-');
2169 while (--dash_count > 0)
2170 add_char ('-');
2173 continue;
2176 /* If this is a whitespace character, then check to see if the line
2177 is blank. If so, advance to the carriage return. */
2178 if (!only_macro_expansion && whitespace (character))
2180 int i = input_text_offset + 1;
2182 while (i < input_text_length && whitespace (input_text[i]))
2183 i++;
2185 if (i == input_text_length || input_text[i] == '\n')
2187 if (i == input_text_length)
2188 i--;
2190 input_text_offset = i;
2191 character = curchar ();
2195 if (character == '\n')
2196 line_number++;
2198 switch (character)
2200 case '*': /* perhaps we are at a menu */
2201 /* We used to check for this in the \n case but an @c in a
2202 menu swallows its newline, so check here instead. */
2203 if (!only_macro_expansion && in_menu
2204 && input_text_offset + 1 < input_text_length
2205 && input_text[input_text_offset-1] == '\n')
2206 handle_menu_entry ();
2207 else
2208 { /* Duplicate code from below, but not worth twisting the
2209 fallthroughs to get down there. */
2210 add_char (character);
2211 input_text_offset++;
2213 break;
2215 /* Escapes for HTML unless we're outputting raw HTML. Do
2216 this always, even if SGML rules don't require it since
2217 that's easier and safer for non-conforming browsers. */
2218 case '&':
2219 if (html && escape_html)
2220 add_word ("&amp;");
2221 else
2222 add_char (character);
2223 input_text_offset++;
2224 break;
2226 case '<':
2227 if (html && escape_html)
2228 add_word ("&lt;");
2229 else if (xml && escape_html)
2230 xml_insert_entity ("lt");
2231 else
2232 add_char (character);
2233 input_text_offset++;
2234 break;
2236 case '>':
2237 if (html && escape_html)
2238 add_word ("&gt;");
2239 else if (xml && escape_html)
2240 xml_insert_entity ("gt");
2241 else
2242 add_char (character);
2243 input_text_offset++;
2244 break;
2246 case COMMAND_PREFIX: /* @ */
2247 if (read_command () || !only_macro_expansion)
2248 break;
2250 /* FALLTHROUGH (usually) */
2251 case '{':
2252 /* Special case. We're not supposed to see this character by itself.
2253 If we do, it means there is a syntax error in the input text.
2254 Report the error here, but remember this brace on the stack so
2255 we can ignore its partner. */
2256 if (!only_macro_expansion)
2258 if (command && !STREQ (command, "math"))
2260 line_error (_("Misplaced %c"), '{');
2261 remember_brace (misplaced_brace);
2263 else
2264 /* We don't mind `extra' braces inside @math. */
2265 remember_brace (cm_no_op);
2266 /* remember_brace advances input_text_offset. */
2267 break;
2270 /* FALLTHROUGH (usually) */
2271 case '}':
2272 if (!only_macro_expansion)
2274 pop_and_call_brace ();
2275 input_text_offset++;
2276 break;
2279 /* FALLTHROUGH (usually) */
2280 default:
2281 add_char (character);
2282 input_text_offset++;
2285 if (macro_expansion_output_stream && !only_macro_expansion)
2286 maybe_write_itext (input_text, input_text_offset);
2289 static void
2290 init_brace_stack (void)
2292 brace_stack = NULL;
2295 /* Remember the current output position here. Save PROC
2296 along with it so you can call it later. */
2297 static void
2298 remember_brace_1 (COMMAND_FUNCTION (*proc), int position)
2300 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
2301 new->next = brace_stack;
2302 new->proc = proc;
2303 new->command = command ? xstrdup (command) : "";
2304 new->pos = position;
2305 new->line = line_number;
2306 new->in_fixed_width_font = in_fixed_width_font;
2307 brace_stack = new;
2310 static void
2311 remember_brace (COMMAND_FUNCTION (*proc))
2313 if (curchar () != '{')
2314 line_error (_("%c%s expected braces"), COMMAND_PREFIX, command);
2315 else
2316 input_text_offset++;
2317 remember_brace_1 (proc, output_paragraph_offset);
2320 /* Pop the top of the brace stack, and call the associated function
2321 with the args END and POS. */
2322 static void
2323 pop_and_call_brace (void)
2325 if (brace_stack == NULL)
2327 line_error (_("Unmatched }"));
2328 return;
2332 BRACE_ELEMENT *temp;
2334 int pos = brace_stack->pos;
2335 COMMAND_FUNCTION *proc = brace_stack->proc;
2336 in_fixed_width_font = brace_stack->in_fixed_width_font;
2338 /* Reset current command, so the proc can know who it is. This is
2339 used in cm_accent. */
2340 command = brace_stack->command;
2342 temp = brace_stack->next;
2343 free (brace_stack);
2344 brace_stack = temp;
2346 (*proc) (END, pos, output_paragraph_offset);
2350 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2351 static void
2352 adjust_braces_following (int here, int amount)
2354 BRACE_ELEMENT *stack = brace_stack;
2356 while (stack)
2358 if (stack->pos >= here)
2359 stack->pos += amount;
2360 stack = stack->next;
2364 /* Return the string which invokes PROC; a pointer to a function.
2365 Always returns the first function in the command table if more than
2366 one matches PROC. */
2367 static const char *
2368 find_proc_name (COMMAND_FUNCTION (*proc))
2370 int i;
2372 for (i = 0; command_table[i].name; i++)
2373 if (proc == command_table[i].proc)
2374 return command_table[i].name;
2375 return _("NO_NAME!");
2378 /* You call discard_braces () when you shouldn't have any braces on the stack.
2379 I used to think that this happens for commands that don't take arguments
2380 in braces, but that was wrong because of things like @code{foo @@}. So now
2381 I only detect it at the beginning of nodes. */
2382 void
2383 discard_braces (void)
2385 if (!brace_stack)
2386 return;
2388 while (brace_stack)
2390 if (brace_stack->proc != misplaced_brace)
2392 const char *proc_name;
2394 proc_name = find_proc_name (brace_stack->proc);
2395 file_line_error (input_filename, brace_stack->line,
2396 _("%c%s missing close brace"), COMMAND_PREFIX,
2397 proc_name);
2398 pop_and_call_brace ();
2400 else
2402 BRACE_ELEMENT *temp;
2403 temp = brace_stack->next;
2404 free (brace_stack);
2405 brace_stack = temp;
2410 static int
2411 get_char_len (int character)
2413 /* Return the printed length of the character. */
2414 int len;
2416 switch (character)
2418 case '\t':
2419 len = (output_column + 8) & 0xf7;
2420 if (len > fill_column)
2421 len = fill_column - output_column;
2422 else
2423 len = len - output_column;
2424 break;
2426 case '\n':
2427 len = fill_column - output_column;
2428 break;
2430 default:
2431 /* ASCII control characters appear as two characters in the output
2432 (e.g., ^A). But characters with the high bit set are just one
2433 on suitable terminals, so don't count them as two for line
2434 breaking purposes. */
2435 if (0 <= character && character < ' ')
2436 len = 2;
2437 else
2438 len = 1;
2440 return len;
2443 void
2444 #if defined (VA_FPRINTF) && __STDC__
2445 add_word_args (const char *format, ...)
2446 #else
2447 add_word_args (format, va_alist)
2448 const char *format;
2449 va_dcl
2450 #endif
2452 char buffer[2000]; /* xx no fixed limits */
2453 #ifdef VA_FPRINTF
2454 va_list ap;
2455 #endif
2457 VA_START (ap, format);
2458 #ifdef VA_SPRINTF
2459 VA_SPRINTF (buffer, format, ap);
2460 #else
2461 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2462 #endif /* not VA_SPRINTF */
2463 va_end (ap);
2464 add_word (buffer);
2467 /* Add STRING to output_paragraph. */
2468 void
2469 add_word (char *string)
2471 while (*string)
2472 add_char (*string++);
2475 /* Like add_word, but inhibits conversion of whitespace into &nbsp;.
2476 Use this to output HTML directives with embedded blanks, to make
2477 them @w-safe. */
2478 void
2479 add_html_elt (char *string)
2481 in_html_elt++;
2482 add_word (string);
2483 in_html_elt--;
2486 /* These two functions below, add_html_block_elt and add_html_block_elt_args,
2487 are mixtures of add_html_elt and add_word_args. They inform makeinfo that
2488 the current HTML element being inserted should not be enclosed in a <p>
2489 element. */
2490 void
2491 add_html_block_elt (char *string)
2493 in_html_block_level_elt++;
2494 add_word (string);
2495 in_html_block_level_elt--;
2498 void
2499 #if defined (VA_FPRINTF) && __STDC__
2500 add_html_block_elt_args (const char *format, ...)
2501 #else
2502 add_html_block_elt_args (format, va_alist)
2503 const char *format;
2504 va_dcl
2505 #endif
2507 char buffer[2000]; /* xx no fixed limits */
2508 #ifdef VA_FPRINTF
2509 va_list ap;
2510 #endif
2512 VA_START (ap, format);
2513 #ifdef VA_SPRINTF
2514 VA_SPRINTF (buffer, format, ap);
2515 #else
2516 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2517 #endif /* not VA_SPRINTF */
2518 va_end (ap);
2519 add_html_block_elt (buffer);
2522 /* Here is another awful kludge, used in add_char. Ordinarily, macro
2523 expansions take place in the body of the document, and therefore we
2524 should html_output_head when we see one. But there's an exception: a
2525 macro call might take place within @copying, and that does not start
2526 the real output, even though we fully expand the copying text.
2528 So we need to be able to check if we are defining the @copying text.
2529 We do this by looking back through the insertion stack. */
2530 static int
2531 defining_copying (void)
2533 INSERTION_ELT *i;
2534 for (i = insertion_stack; i; i = i->next)
2536 if (i->insertion == copying)
2537 return 1;
2539 return 0;
2543 /* Add the character to the current paragraph. If filling_enabled is
2544 nonzero, then do filling as well. */
2545 void
2546 add_char (int character)
2548 if (xml)
2550 xml_add_char (character);
2551 return;
2554 /* If we are avoiding outputting headers, and we are currently
2555 in a menu, then simply return. But if we're only expanding macros,
2556 then we're being called from glean_node_from_menu to try to
2557 remember a menu reference, and we need that so we can do defaulting. */
2558 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2559 return;
2561 /* If we are adding a character now, then we don't have to
2562 ignore close_paragraph () calls any more. */
2563 if (must_start_paragraph && character != '\n')
2565 must_start_paragraph = 0;
2566 line_already_broken = 0; /* The line is no longer broken. */
2567 if (current_indent > output_column)
2569 indent (current_indent - output_column);
2570 output_column = current_indent;
2574 if (non_splitting_words
2575 && !(html && in_html_elt)
2576 && strchr (" \t\n", character))
2578 if (html || docbook)
2579 { /* Seems cleaner to use &nbsp; than an 8-bit char. */
2580 int saved_escape_html = escape_html;
2581 escape_html = 0;
2582 add_word ("&nbsp");
2583 escape_html = saved_escape_html;
2584 character = ';';
2586 else
2587 character = META (' '); /* unmeta-d in flush_output */
2590 insertion_paragraph_closed = 0;
2592 switch (character)
2594 case '\n':
2595 if (!filling_enabled && !(html && (in_menu || in_detailmenu)))
2597 insert ('\n');
2599 if (force_flush_right)
2601 close_paragraph ();
2602 /* Hack to force single blank lines out in this mode. */
2603 flush_output ();
2606 output_column = 0;
2608 if (!no_indent && paragraph_is_open)
2609 indent (output_column = current_indent);
2610 break;
2612 else if (end_of_sentence_p ())
2613 /* CHARACTER is newline, and filling is enabled. */
2615 insert (' ');
2616 output_column++;
2617 last_inserted_character = character;
2620 if (last_char_was_newline)
2622 if (html)
2623 last_char_was_newline++;
2624 close_paragraph ();
2625 pending_indent = 0;
2627 else
2629 last_char_was_newline = 1;
2630 if (html)
2631 insert ('\n');
2632 else
2633 insert (' ');
2634 output_column++;
2636 break;
2638 default: /* not at newline */
2640 int len = get_char_len (character);
2641 int suppress_insert = 0;
2643 if ((character == ' ') && (last_char_was_newline))
2645 if (!paragraph_is_open)
2647 pending_indent++;
2648 return;
2652 /* This is sad, but it seems desirable to not force any
2653 particular order on the front matter commands. This way,
2654 the document can do @settitle, @documentlanguage, etc, in
2655 any order and with any omissions, and we'll still output
2656 the html <head> `just in time'. */
2657 if ((executing_macro || !executing_string)
2658 && !only_macro_expansion
2659 && html && !html_output_head_p && !defining_copying ())
2660 html_output_head ();
2662 if (!paragraph_is_open)
2664 start_paragraph ();
2665 /* If the paragraph is supposed to be indented a certain
2666 way, then discard all of the pending whitespace.
2667 Otherwise, we let the whitespace stay. */
2668 if (!paragraph_start_indent)
2669 indent (pending_indent);
2670 pending_indent = 0;
2672 /* This check for in_html_block_level_elt prevents <p> from being
2673 inserted when we already have html markup starting a paragraph,
2674 as with <ul> and <h1> and the like. */
2675 if (html && !in_html_block_level_elt)
2677 if ((in_menu || in_detailmenu) && in_menu_item)
2679 insert_string ("</li></ul>\n");
2680 in_menu_item = 0;
2682 insert_string ("<p>");
2683 in_paragraph = 1;
2684 adjust_braces_following (0, 3); /* adjust for <p> */
2688 output_column += len;
2689 if (output_column > fill_column)
2691 if (filling_enabled && !html)
2693 int temp = output_paragraph_offset;
2694 while (--temp > 0 && output_paragraph[temp] != '\n')
2696 /* If we have found a space, we have the place to break
2697 the line. */
2698 if (output_paragraph[temp] == ' ')
2700 /* Remove trailing whitespace from output. */
2701 while (temp && whitespace (output_paragraph[temp - 1]))
2702 temp--;
2704 /* If we went back all the way to the newline of the
2705 preceding line, it probably means that the word we
2706 are adding is itself wider than the space that the
2707 indentation and the fill_column let us use. In
2708 that case, do NOT insert another newline, since it
2709 won't help. Just indent to current_indent and
2710 leave it alone, since that's the most we can do. */
2711 if (temp && output_paragraph[temp - 1] != '\n')
2712 output_paragraph[temp++] = '\n';
2714 /* We have correctly broken the line where we want
2715 to. What we don't want is spaces following where
2716 we have decided to break the line. We get rid of
2717 them. */
2719 int t1 = temp;
2721 for (;; t1++)
2723 if (t1 == output_paragraph_offset)
2725 if (whitespace (character))
2726 suppress_insert = 1;
2727 break;
2729 if (!whitespace (output_paragraph[t1]))
2730 break;
2733 if (t1 != temp)
2735 adjust_braces_following (temp, (- (t1 - temp)));
2736 memmove (&output_paragraph[temp],
2737 &output_paragraph[t1],
2738 output_paragraph_offset - t1);
2739 output_paragraph_offset -= (t1 - temp);
2743 /* Filled, but now indent if that is right. */
2744 if (indented_fill && current_indent > 0)
2746 int buffer_len = ((output_paragraph_offset - temp)
2747 + current_indent);
2748 char *temp_buffer = xmalloc (buffer_len);
2749 int indentation = 0;
2751 /* We have to shift any markers that are in
2752 front of the wrap point. */
2753 adjust_braces_following (temp, current_indent);
2755 while (current_indent > 0 &&
2756 indentation != current_indent)
2757 temp_buffer[indentation++] = ' ';
2759 memcpy ((char *) &temp_buffer[current_indent],
2760 (char *) &output_paragraph[temp],
2761 buffer_len - current_indent);
2763 if (output_paragraph_offset + buffer_len
2764 >= paragraph_buffer_len)
2766 unsigned char *tt = xrealloc
2767 (output_paragraph,
2768 (paragraph_buffer_len += buffer_len));
2769 output_paragraph = tt;
2771 memcpy ((char *) &output_paragraph[temp],
2772 temp_buffer, buffer_len);
2773 output_paragraph_offset += current_indent;
2774 free (temp_buffer);
2776 output_column = 0;
2777 while (temp < output_paragraph_offset)
2778 output_column +=
2779 get_char_len (output_paragraph[temp++]);
2780 output_column += len;
2781 break;
2787 if (!suppress_insert)
2789 insert (character);
2790 last_inserted_character = character;
2792 last_char_was_newline = 0;
2793 line_already_broken = 0;
2798 /* Add a character and store its position in meta_char_pos. */
2799 void
2800 add_meta_char (int character)
2802 meta_char_pos = output_paragraph_offset;
2803 add_char (character);
2806 /* Insert CHARACTER into `output_paragraph'. */
2807 void
2808 insert (int character)
2810 /* We don't want to strip trailing whitespace in multitables. Otherwise
2811 horizontal separators confuse the font locking in Info mode in Emacs,
2812 because it looks like a @subsection. Adding a trailing space to those
2813 lines fixes it. */
2814 if (character == '\n' && !html && !xml && !multitable_active)
2816 while (output_paragraph_offset
2817 && whitespace (output_paragraph[output_paragraph_offset-1]))
2818 output_paragraph_offset--;
2821 output_paragraph[output_paragraph_offset++] = character;
2822 if (output_paragraph_offset == paragraph_buffer_len)
2824 output_paragraph =
2825 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2829 /* Insert the null-terminated string STRING into `output_paragraph'. */
2830 void
2831 insert_string (const char *string)
2833 while (*string)
2834 insert (*string++);
2838 /* Sentences might have these characters after the period (or whatever). */
2839 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2840 || (c) == ']')
2842 /* Return true if at an end-of-sentence character, possibly followed by
2843 post-sentence punctuation to ignore. */
2844 static int
2845 end_of_sentence_p (void)
2847 int loc = output_paragraph_offset - 1;
2849 /* If nothing has been output, don't check output_paragraph[-1]. */
2850 if (loc < 0)
2851 return 0;
2853 /* A post-sentence character that is at meta_char_pos is not really
2854 a post-sentence character; it was produced by a markup such as
2855 @samp. We don't want the period inside @samp to be treated as a
2856 sentence ender. */
2857 while (loc > 0
2858 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
2859 loc--;
2860 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
2864 /* Remove upto COUNT characters of whitespace from the
2865 the current output line. If COUNT is less than zero,
2866 then remove until none left. */
2867 void
2868 kill_self_indent (int count)
2870 /* Handle infinite case first. */
2871 if (count < 0)
2873 output_column = 0;
2874 while (output_paragraph_offset)
2876 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2877 output_paragraph_offset--;
2878 else
2879 break;
2882 else
2884 while (output_paragraph_offset && count--)
2885 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2886 output_paragraph_offset--;
2887 else
2888 break;
2892 /* Nonzero means do not honor calls to flush_output (). */
2893 static int flushing_ignored = 0;
2895 /* Prevent calls to flush_output () from having any effect. */
2896 void
2897 inhibit_output_flushing (void)
2899 flushing_ignored++;
2902 /* Allow calls to flush_output () to write the paragraph data. */
2903 void
2904 uninhibit_output_flushing (void)
2906 flushing_ignored--;
2909 void
2910 flush_output (void)
2912 int i;
2914 if (!output_paragraph_offset || flushing_ignored)
2915 return;
2917 for (i = 0; i < output_paragraph_offset; i++)
2919 if (output_paragraph[i] == '\n')
2921 output_line_number++;
2922 node_line_number++;
2925 /* If we turned on the 8th bit for a space inside @w, turn it
2926 back off for output. This might be problematic, since the
2927 0x80 character may be used in 8-bit character sets. Sigh.
2928 In any case, don't do this for HTML, since the nbsp character
2929 is valid input and must be passed along to the browser. */
2930 if (!html && (output_paragraph[i] & meta_character_bit))
2932 int temp = UNMETA (output_paragraph[i]);
2933 if (temp == ' ')
2934 output_paragraph[i] &= 0x7f;
2938 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2940 output_position += output_paragraph_offset;
2941 output_paragraph_offset = 0;
2942 meta_char_pos = 0;
2945 /* How to close a paragraph controlling the number of lines between
2946 this one and the last one. */
2948 /* Paragraph spacing is controlled by this variable. It is the number of
2949 blank lines that you wish to appear between paragraphs. A value of
2950 1 creates a single blank line between paragraphs. */
2951 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2953 static void
2954 close_paragraph_with_lines (int lines)
2956 int old_spacing = paragraph_spacing;
2957 paragraph_spacing = lines;
2958 close_paragraph ();
2959 paragraph_spacing = old_spacing;
2962 /* Close the current paragraph, leaving no blank lines between them. */
2963 void
2964 close_single_paragraph (void)
2966 close_paragraph_with_lines (0);
2969 /* Close a paragraph after an insertion has ended. */
2970 void
2971 close_insertion_paragraph (void)
2973 if (!insertion_paragraph_closed)
2975 /* Close the current paragraph, breaking the line. */
2976 close_single_paragraph ();
2978 /* Start a new paragraph, with the correct indentation for the now
2979 current insertion level (one above the one that we are ending). */
2980 start_paragraph ();
2982 /* Tell `close_paragraph' that the previous line has already been
2983 broken, so it should insert one less newline. */
2984 line_already_broken = 1;
2986 /* Tell functions such as `add_char' we've already found a newline. */
2987 ignore_blank_line ();
2989 else
2991 /* If the insertion paragraph is closed already, then we are seeing
2992 two `@end' commands in a row. Note that the first one we saw was
2993 handled in the first part of this if-then-else clause, and at that
2994 time `start_paragraph' was called, partially to handle the proper
2995 indentation of the current line. However, the indentation level
2996 may have just changed again, so we may have to outdent the current
2997 line to the new indentation level. */
2998 if (current_indent < output_column)
2999 kill_self_indent (output_column - current_indent);
3002 insertion_paragraph_closed = 1;
3005 /* Close the currently open paragraph. */
3006 void
3007 close_paragraph (void)
3009 int i;
3011 /* We don't need these newlines in XML and Docbook outputs for
3012 paragraph seperation. We have <para> element for that. */
3013 if (xml)
3014 return;
3016 /* The insertion paragraph is no longer closed. */
3017 insertion_paragraph_closed = 0;
3019 if (paragraph_is_open && !must_start_paragraph)
3021 int tindex = output_paragraph_offset;
3023 /* Back up to last non-newline/space character, forcing all such
3024 subsequent characters to be newlines. This isn't strictly
3025 necessary, but a couple of functions use the presence of a newline
3026 to make decisions. */
3027 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
3029 int c = output_paragraph[tindex];
3031 if (c == ' '|| c == '\n')
3032 output_paragraph[tindex] = '\n';
3033 else
3034 break;
3037 /* All trailing whitespace is ignored. */
3038 output_paragraph_offset = ++tindex;
3040 /* Break the line if that is appropriate. */
3041 if (paragraph_spacing >= 0)
3042 insert ('\n');
3044 /* Add as many blank lines as is specified in `paragraph_spacing'. */
3045 if (!force_flush_right)
3047 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
3049 insert ('\n');
3050 /* Don't need anything extra for HTML in usual case of no
3051 extra paragraph spacing. */
3052 if (html && i > 0)
3053 insert_string ("<br>");
3057 /* If we are doing flush right indentation, then do it now
3058 on the paragraph (really a single line). */
3059 if (force_flush_right)
3060 do_flush_right_indentation ();
3062 flush_output ();
3063 paragraph_is_open = 0;
3064 no_indent = 0;
3065 output_column = 0;
3068 ignore_blank_line ();
3071 /* Make the last line just read look as if it were only a newline. */
3072 void
3073 ignore_blank_line (void)
3075 last_inserted_character = '\n';
3076 last_char_was_newline = 1;
3079 /* Align the end of the text in output_paragraph with fill_column. */
3080 static void
3081 do_flush_right_indentation (void)
3083 char *temp;
3084 int temp_len;
3086 kill_self_indent (-1);
3088 if (output_paragraph[0] != '\n')
3090 output_paragraph[output_paragraph_offset] = 0;
3092 if (output_paragraph_offset < fill_column)
3094 int i;
3096 if (fill_column >= paragraph_buffer_len)
3097 output_paragraph =
3098 xrealloc (output_paragraph,
3099 (paragraph_buffer_len += fill_column));
3101 temp_len = strlen ((char *)output_paragraph);
3102 temp = xmalloc (temp_len + 1);
3103 memcpy (temp, (char *)output_paragraph, temp_len);
3105 for (i = 0; i < fill_column - output_paragraph_offset; i++)
3106 output_paragraph[i] = ' ';
3108 memcpy ((char *)output_paragraph + i, temp, temp_len);
3109 free (temp);
3110 output_paragraph_offset = fill_column;
3111 adjust_braces_following (0, i);
3116 /* Begin a new paragraph. */
3117 void
3118 start_paragraph (void)
3120 /* First close existing one. */
3121 if (paragraph_is_open)
3122 close_paragraph ();
3124 /* In either case, the insertion paragraph is no longer closed. */
3125 insertion_paragraph_closed = 0;
3127 /* However, the paragraph is open! */
3128 paragraph_is_open = 1;
3130 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
3131 had to be called before we would allow any other paragraph operations
3132 to have an effect. */
3133 if (!must_start_paragraph)
3135 int amount_to_indent = 0;
3137 /* If doing indentation, then insert the appropriate amount. */
3138 if (!no_indent)
3140 if (inhibit_paragraph_indentation)
3142 amount_to_indent = current_indent;
3143 if (inhibit_paragraph_indentation < 0)
3144 inhibit_paragraph_indentation++;
3146 else if (paragraph_start_indent < 0)
3147 amount_to_indent = current_indent;
3148 else
3149 amount_to_indent = current_indent + paragraph_start_indent;
3151 if (amount_to_indent >= output_column)
3153 amount_to_indent -= output_column;
3154 indent (amount_to_indent);
3155 output_column += amount_to_indent;
3159 else
3160 must_start_paragraph = 0;
3163 /* Insert the indentation specified by AMOUNT. */
3164 void
3165 indent (int amount)
3167 /* For every START_POS saved within the brace stack which will be affected
3168 by this indentation, bump that start pos forward. */
3169 adjust_braces_following (output_paragraph_offset, amount);
3171 while (--amount >= 0)
3172 insert (' ');
3175 /* Search forward for STRING in input_text.
3176 FROM says where where to start. */
3178 search_forward (char *string, int from)
3180 int len = strlen (string);
3182 while (from < input_text_length)
3184 if (strncmp (input_text + from, string, len) == 0)
3185 return from;
3186 from++;
3188 return -1;
3191 /* search_forward until n characters. */
3193 search_forward_until_pos (char *string, int from, int end_pos)
3195 int save_input_text_length = input_text_length;
3196 input_text_length = end_pos;
3198 from = search_forward (string, from);
3200 input_text_length = save_input_text_length;
3202 return from;
3205 /* Return next non-whitespace and non-cr character. */
3207 next_nonwhitespace_character (void)
3209 /* First check the current input_text. Start from the next char because
3210 we already have input_text[input_text_offset] in ``current''. */
3211 int pos = input_text_offset + 1;
3213 while (pos < input_text_length)
3215 if (!cr_or_whitespace(input_text[pos]))
3216 return input_text[pos];
3217 pos++;
3220 { /* Can't find a valid character, so go through filestack
3221 in case we are doing @include or expanding a macro. */
3222 FSTACK *tos = filestack;
3224 while (tos)
3226 int tmp_input_text_length = filestack->size;
3227 int tmp_input_text_offset = filestack->offset;
3228 char *tmp_input_text = filestack->text;
3230 while (tmp_input_text_offset < tmp_input_text_length)
3232 if (!cr_or_whitespace(tmp_input_text[tmp_input_text_offset]))
3233 return tmp_input_text[tmp_input_text_offset];
3234 tmp_input_text_offset++;
3237 tos = tos->next;
3241 return -1;
3244 /* An external image is a reference, kind of. The parsing is (not
3245 coincidentally) similar, anyway. */
3246 void
3247 cm_image (int arg)
3249 char *name_arg, *w_arg, *h_arg, *alt_arg, *ext_arg;
3251 if (arg == END)
3252 return;
3254 name_arg = get_xref_token (1); /* expands all macros in image */
3255 w_arg = get_xref_token (0);
3256 h_arg = get_xref_token (0);
3257 alt_arg = get_xref_token (1); /* expands all macros in alt text */
3258 ext_arg = get_xref_token (0);
3260 if (*name_arg)
3262 struct stat file_info;
3263 char *pathname = NULL;
3264 char *fullname = xmalloc (strlen (name_arg)
3265 + (ext_arg && *ext_arg ? strlen (ext_arg) + 1: 4) + 1);
3267 if (ext_arg && *ext_arg)
3269 sprintf (fullname, "%s%s", name_arg, ext_arg);
3270 if (access (fullname, R_OK) != 0)
3271 pathname = get_file_info_in_path (fullname, include_files_path,
3272 &file_info);
3274 if (pathname == NULL)
3276 /* Backwards compatibility (4.6 <= version < 4.7):
3277 try prefixing @image's EXTENSION parameter with a period. */
3278 sprintf (fullname, "%s.%s", name_arg, ext_arg);
3279 if (access (fullname, R_OK) != 0)
3280 pathname = get_file_info_in_path (fullname, include_files_path,
3281 &file_info);
3284 else
3286 sprintf (fullname, "%s.png", name_arg);
3287 if (access (fullname, R_OK) != 0) {
3288 pathname = get_file_info_in_path (fullname,
3289 include_files_path, &file_info);
3290 if (pathname == NULL) {
3291 sprintf (fullname, "%s.jpg", name_arg);
3292 if (access (fullname, R_OK) != 0) {
3293 sprintf (fullname, "%s.gif", name_arg);
3294 if (access (fullname, R_OK) != 0) {
3295 pathname = get_file_info_in_path (fullname,
3296 include_files_path, &file_info);
3303 if (html)
3305 int image_in_div = 0;
3307 if (pathname == NULL && access (fullname, R_OK) != 0)
3309 line_error(_("@image file `%s' (for HTML) not readable: %s"),
3310 fullname, strerror (errno));
3311 return;
3313 if (pathname != NULL && access (pathname, R_OK) != 0)
3315 line_error (_("No such file `%s'"),
3316 fullname);
3317 return;
3320 if (!paragraph_is_open)
3322 add_html_block_elt ("<div class=\"block-image\">");
3323 image_in_div = 1;
3326 add_html_elt ("<img src=");
3327 add_word_args ("\"%s\"", fullname);
3328 add_html_elt (" alt=");
3329 add_word_args ("\"%s\">",
3330 escape_string (*alt_arg ? text_expansion (alt_arg) : fullname));
3332 if (image_in_div)
3333 add_html_block_elt ("</div>");
3335 else if (xml && docbook)
3336 xml_insert_docbook_image (name_arg);
3337 else if (xml)
3339 extern int xml_in_para;
3340 extern int xml_no_para;
3341 int elt = xml_in_para ? INLINEIMAGE : IMAGE;
3343 if (!xml_in_para)
3344 xml_no_para++;
3346 xml_insert_element_with_attribute (elt,
3347 START, "width=\"%s\" height=\"%s\" name=\"%s\" extension=\"%s\"",
3348 w_arg, h_arg, name_arg, ext_arg);
3349 xml_insert_element (IMAGEALTTEXT, START);
3350 execute_string ("%s", alt_arg);
3351 xml_insert_element (IMAGEALTTEXT, END);
3352 xml_insert_element (elt, END);
3354 if (!xml_in_para)
3355 xml_no_para--;
3357 else
3358 { /* Try to open foo.EXT or foo.txt. */
3359 FILE *image_file;
3360 char *txtpath = NULL;
3361 char *txtname = xmalloc (strlen (name_arg)
3362 + (ext_arg && *ext_arg
3363 ? strlen (ext_arg) : 4) + 1);
3364 strcpy (txtname, name_arg);
3365 strcat (txtname, ".txt");
3366 image_file = fopen (txtname, "r");
3367 if (image_file == NULL)
3369 txtpath = get_file_info_in_path (txtname,
3370 include_files_path, &file_info);
3371 if (txtpath != NULL)
3372 image_file = fopen (txtpath, "r");
3375 if (image_file != NULL
3376 || access (fullname, R_OK) == 0
3377 || (pathname != NULL && access (pathname, R_OK) == 0))
3379 int ch;
3380 int save_inhibit_indentation = inhibit_paragraph_indentation;
3381 int save_filling_enabled = filling_enabled;
3382 int image_in_brackets = paragraph_is_open;
3384 /* Write magic ^@^H[image ...^@^H] cookie in the info file, if
3385 there's an accompanying bitmap. Otherwise just include the
3386 text image. In the plaintext output, always include the text
3387 image without the magic cookie. */
3388 int use_magic_cookie = !no_headers
3389 && access (fullname, R_OK) == 0 && !STREQ (fullname, txtname);
3391 inhibit_paragraph_indentation = 1;
3392 filling_enabled = 0;
3393 last_char_was_newline = 0;
3395 if (use_magic_cookie)
3397 add_char ('\0');
3398 add_word ("\010[image");
3400 if (access (fullname, R_OK) == 0
3401 || (pathname != NULL && access (pathname, R_OK) == 0))
3402 add_word_args (" src=\"%s\"", fullname);
3404 if (*alt_arg)
3405 add_word_args (" alt=\"%s\"", alt_arg);
3408 if (image_file != NULL)
3410 if (use_magic_cookie)
3411 add_word (" text=\"");
3413 if (image_in_brackets)
3414 add_char ('[');
3416 /* Maybe we need to remove the final newline if the image
3417 file is only one line to allow in-line images. On the
3418 other hand, they could just make the file without a
3419 final newline. */
3420 while ((ch = getc (image_file)) != EOF)
3422 if (use_magic_cookie && (ch == '"' || ch == '\\'))
3423 add_char ('\\');
3424 add_char (ch);
3427 if (image_in_brackets)
3428 add_char (']');
3430 if (use_magic_cookie)
3431 add_char ('"');
3433 if (fclose (image_file) != 0)
3434 perror (txtname);
3437 if (use_magic_cookie)
3439 add_char ('\0');
3440 add_word ("\010]");
3443 inhibit_paragraph_indentation = save_inhibit_indentation;
3444 filling_enabled = save_filling_enabled;
3446 else
3447 warning (_("@image file `%s' (for text) unreadable: %s"),
3448 txtname, strerror (errno));
3451 free (fullname);
3452 if (pathname)
3453 free (pathname);
3455 else
3456 line_error (_("@image missing filename argument"));
3458 if (name_arg)
3459 free (name_arg);
3460 if (w_arg)
3461 free (w_arg);
3462 if (h_arg)
3463 free (h_arg);
3464 if (alt_arg)
3465 free (alt_arg);
3466 if (ext_arg)
3467 free (ext_arg);
3470 /* Conditionals. */
3472 /* A structure which contains `defined' variables. */
3473 typedef struct defines {
3474 struct defines *next;
3475 char *name;
3476 char *value;
3477 } DEFINE;
3479 /* The linked list of `set' defines. */
3480 DEFINE *defines = NULL;
3482 /* Add NAME to the list of `set' defines. */
3483 static void
3484 set (char *name, char *value)
3486 DEFINE *temp;
3488 for (temp = defines; temp; temp = temp->next)
3489 if (strcmp (name, temp->name) == 0)
3491 free (temp->value);
3492 temp->value = xstrdup (value);
3493 return;
3496 temp = xmalloc (sizeof (DEFINE));
3497 temp->next = defines;
3498 temp->name = xstrdup (name);
3499 temp->value = xstrdup (value);
3500 defines = temp;
3502 if (xml && !docbook)
3504 xml_insert_element_with_attribute (SETVALUE, START, "name=\"%s\"", name);
3505 execute_string ("%s", value);
3506 xml_insert_element (SETVALUE, END);
3510 /* Remove NAME from the list of `set' defines. */
3511 static void
3512 clear (char *name)
3514 DEFINE *temp, *last;
3516 last = NULL;
3517 temp = defines;
3519 while (temp)
3521 if (strcmp (temp->name, name) == 0)
3523 if (last)
3524 last->next = temp->next;
3525 else
3526 defines = temp->next;
3528 free (temp->name);
3529 free (temp->value);
3530 free (temp);
3531 break;
3533 last = temp;
3534 temp = temp->next;
3537 if (xml && !docbook)
3539 xml_insert_element_with_attribute (CLEARVALUE, START, "name=\"%s\"", name);
3540 xml_insert_element (CLEARVALUE, END);
3544 /* Return the value of NAME. The return value is NULL if NAME is unset. */
3545 static char *
3546 set_p (char *name)
3548 DEFINE *temp;
3550 for (temp = defines; temp; temp = temp->next)
3551 if (strcmp (temp->name, name) == 0)
3552 return temp->value;
3554 return NULL;
3557 /* Create a variable whose name appears as the first word on this line. */
3558 void
3559 cm_set (void)
3561 handle_variable (SET);
3564 /* Remove a variable whose name appears as the first word on this line. */
3565 void
3566 cm_clear (void)
3568 handle_variable (CLEAR);
3571 void
3572 cm_ifset (void)
3574 handle_variable (IFSET);
3577 void
3578 cm_ifclear (void)
3580 handle_variable (IFCLEAR);
3583 /* This command takes braces, but we parse the contents specially, so we
3584 don't use the standard brace popping code.
3586 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3587 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3588 it produces no output. */
3589 void
3590 cm_ifeq (void)
3592 char **arglist;
3594 arglist = get_brace_args (0);
3596 if (arglist)
3598 if (array_len (arglist) > 1)
3600 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
3601 (arglist[2]))
3602 execute_string ("%s\n", arglist[2]);
3605 free_array (arglist);
3609 void
3610 cm_value (int arg, int start_pos, int end_pos)
3612 static int value_level = 0, saved_meta_pos = -1;
3614 /* xml_add_char() skips any content inside menus when output format is
3615 Docbook, so @value{} is no use there. Also start_pos and end_pos does not
3616 get updated, causing name to be empty string. So just return. */
3617 if (docbook && in_menu)
3618 return;
3620 /* All the text after @value{ upto the matching } will eventually
3621 disappear from output_paragraph, when this function is called
3622 with ARG == END. If the text produced until then sets
3623 meta_char_pos, we will need to restore it to the value it had
3624 before @value was seen. So we need to save the previous value
3625 of meta_char_pos here. */
3626 if (arg == START)
3628 /* If we are already inside some outer @value, don't overwrite
3629 the value saved in saved_meta_pos. */
3630 if (!value_level)
3631 saved_meta_pos = meta_char_pos;
3632 value_level++;
3633 /* While the argument of @value is processed, we need to inhibit
3634 textual transformations like "--" into "-", since @set didn't
3635 do that when it grabbed the name of the variable. */
3636 in_fixed_width_font++;
3638 else
3640 char *name = (char *) &output_paragraph[start_pos];
3641 char *value;
3642 output_paragraph[end_pos] = 0;
3643 name = xstrdup (name);
3644 value = set_p (name);
3645 output_column -= end_pos - start_pos;
3646 output_paragraph_offset = start_pos;
3648 /* Restore the previous value of meta_char_pos if the stuff
3649 inside this @value{} moved it. */
3650 if (saved_meta_pos == -1) /* can't happen inside @value{} */
3651 abort ();
3652 if (value_level == 1
3653 && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3655 meta_char_pos = saved_meta_pos;
3656 saved_meta_pos = -1;
3658 value_level--;
3659 /* No need to decrement in_fixed_width_font, since before
3660 we are called with arg == END, the reader loop already
3661 popped the brace stack, which restored in_fixed_width_font,
3662 among other things. */
3664 if (value)
3666 /* We need to get past the closing brace since the value may
3667 expand to a context-sensitive macro (e.g. @xref) and produce
3668 spurious warnings */
3669 input_text_offset++;
3670 execute_string ("%s", value);
3671 input_text_offset--;
3673 else
3675 warning (_("undefined flag: %s"), name);
3676 add_word_args (_("{No value for `%s'}"), name);
3679 free (name);
3683 /* Set, clear, or conditionalize based on ACTION. */
3684 static void
3685 handle_variable (int action)
3687 char *name;
3689 get_rest_of_line (0, &name);
3690 /* If we hit the end of text in get_rest_of_line, backing up
3691 input pointer will cause the last character of the last line
3692 be pushed back onto the input, which is wrong. */
3693 if (input_text_offset < input_text_length)
3694 backup_input_pointer ();
3695 handle_variable_internal (action, name);
3696 free (name);
3699 static void
3700 handle_variable_internal (int action, char *name)
3702 char *temp;
3703 int delimiter, additional_text_present = 0;
3705 /* Only the first word of NAME is a valid tag. */
3706 temp = name;
3707 delimiter = 0;
3708 while (*temp && (delimiter || !whitespace (*temp)))
3710 /* #if defined (SET_WITH_EQUAL) */
3711 if (*temp == '"' || *temp == '\'')
3713 if (*temp == delimiter)
3714 delimiter = 0;
3715 else
3716 delimiter = *temp;
3718 /* #endif SET_WITH_EQUAL */
3719 temp++;
3722 if (*temp)
3723 additional_text_present++;
3725 *temp = 0;
3727 if (!*name)
3728 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3729 else
3731 switch (action)
3733 case SET:
3735 char *value;
3737 #if defined (SET_WITH_EQUAL)
3738 /* Allow a value to be saved along with a variable. The value is
3739 the text following an `=' sign in NAME, if any is present. */
3741 for (value = name; *value && *value != '='; value++);
3743 if (*value)
3744 *value++ = 0;
3746 if (*value == '"' || *value == '\'')
3748 value++;
3749 value[strlen (value) - 1] = 0;
3752 #else /* !SET_WITH_EQUAL */
3753 /* The VALUE of NAME is the remainder of the line sans
3754 whitespace. */
3755 if (additional_text_present)
3757 value = temp + 1;
3758 canon_white (value);
3760 else
3761 value = "";
3762 #endif /* !SET_WITH_VALUE */
3764 set (name, value);
3766 break;
3768 case CLEAR:
3769 clear (name);
3770 break;
3772 case IFSET:
3773 case IFCLEAR:
3774 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3775 read lines from the the file until we reach a matching
3776 "@end CONDITION". This means that we only take note of
3777 "@ifset/clear" and "@end" commands. */
3779 char condition[8];
3780 int condition_len;
3781 int orig_line_number = line_number;
3783 if (action == IFSET)
3784 strcpy (condition, "ifset");
3785 else
3786 strcpy (condition, "ifclear");
3788 condition_len = strlen (condition);
3790 if ((action == IFSET && !set_p (name))
3791 || (action == IFCLEAR && set_p (name)))
3793 int level = 0, done = 0;
3795 while (!done && input_text_offset < input_text_length)
3797 char *freeable_line, *line;
3799 get_rest_of_line (0, &freeable_line);
3801 for (line = freeable_line; whitespace (*line); line++);
3803 if (*line == COMMAND_PREFIX &&
3804 (strncmp (line + 1, condition, condition_len) == 0))
3805 level++;
3806 else if (strncmp (line, "@end", 4) == 0)
3808 char *cname = line + 4;
3809 char *temp;
3811 while (*cname && whitespace (*cname))
3812 cname++;
3813 temp = cname;
3815 while (*temp && !whitespace (*temp))
3816 temp++;
3817 *temp = 0;
3819 if (strcmp (cname, condition) == 0)
3821 if (!level)
3823 done = 1;
3825 else
3826 level--;
3829 free (freeable_line);
3832 if (!done)
3833 file_line_error (input_filename, orig_line_number,
3834 _("Reached eof before matching @end %s"),
3835 condition);
3837 /* We found the end of a false @ifset/ifclear. If we are
3838 in a menu, back up over the newline that ends the ifset,
3839 since that newline may also begin the next menu entry. */
3840 break;
3842 else
3844 if (action == IFSET)
3845 begin_insertion (ifset);
3846 else
3847 begin_insertion (ifclear);
3850 break;
3855 /* Execution of random text not in file. */
3856 typedef struct {
3857 char *string; /* The string buffer. */
3858 int size; /* The size of the buffer. */
3859 int in_use; /* Nonzero means string currently in use. */
3860 } EXECUTION_STRING;
3862 static EXECUTION_STRING **execution_strings = NULL;
3863 static int execution_strings_index = 0;
3864 static int execution_strings_slots = 0;
3866 static EXECUTION_STRING *
3867 get_execution_string (int initial_size)
3869 int i = 0;
3870 EXECUTION_STRING *es = NULL;
3872 if (execution_strings)
3874 for (i = 0; i < execution_strings_index; i++)
3875 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
3877 es = execution_strings[i];
3878 break;
3882 if (!es)
3884 if (execution_strings_index + 1 >= execution_strings_slots)
3886 execution_strings = xrealloc
3887 (execution_strings,
3888 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
3889 for (; i < execution_strings_slots; i++)
3890 execution_strings[i] = NULL;
3893 execution_strings[execution_strings_index] =
3894 xmalloc (sizeof (EXECUTION_STRING));
3895 es = execution_strings[execution_strings_index];
3896 execution_strings_index++;
3898 es->size = 0;
3899 es->string = NULL;
3900 es->in_use = 0;
3903 if (initial_size > es->size)
3905 es->string = xrealloc (es->string, initial_size);
3906 es->size = initial_size;
3908 return es;
3911 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
3912 entry in the execution_strings[] array and change the .STRING and
3913 .SIZE members of that entry as appropriate. */
3914 void
3915 maybe_update_execution_strings (char **text, unsigned int new_len)
3917 int i = 0;
3919 if (execution_strings)
3921 for (i = 0; i < execution_strings_index; i++)
3922 if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
3923 execution_strings[i]->string == *text)
3925 /* Don't ever shrink the string storage in execution_strings[]!
3926 execute_string assumes that it is always big enough to store
3927 every possible execution_string, and will break if that's
3928 not true. So we only enlarge the string storage if the
3929 current size isn't big enough. */
3930 if (execution_strings[i]->size < new_len)
3932 execution_strings[i]->string =
3933 *text = xrealloc (*text, new_len + 1);
3934 execution_strings[i]->size = new_len + 1;
3936 return;
3939 /* We should *never* end up here, since if we are inside
3940 execute_string, TEXT is always in execution_strings[]. */
3941 abort ();
3944 /* FIXME: this is an arbitrary limit. */
3945 #define EXECUTE_STRING_MAX 16*1024
3947 /* Execute the string produced by formatting the ARGs with FORMAT. This
3948 is like submitting a new file with @include. */
3949 void
3950 #if defined (VA_FPRINTF) && __STDC__
3951 execute_string (char *format, ...)
3952 #else
3953 execute_string (format, va_alist)
3954 char *format;
3955 va_dcl
3956 #endif
3958 EXECUTION_STRING *es;
3959 char *temp_string, *temp_input_filename;
3960 #ifdef VA_FPRINTF
3961 va_list ap;
3962 #endif
3963 int insertion_level_at_start = insertion_level;
3965 es = get_execution_string (EXECUTE_STRING_MAX);
3966 temp_string = es->string;
3967 es->in_use = 1;
3969 VA_START (ap, format);
3970 #ifdef VA_SPRINTF
3971 VA_SPRINTF (temp_string, format, ap);
3972 #else
3973 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
3974 #endif /* not VA_SPRINTF */
3975 va_end (ap);
3977 pushfile ();
3978 input_text_offset = 0;
3979 input_text = temp_string;
3980 input_text_length = strlen (temp_string);
3981 input_filename = xstrdup (input_filename);
3982 temp_input_filename = input_filename;
3984 executing_string++;
3985 reader_loop ();
3987 /* If insertion stack level changes during execution, that means a multiline
3988 command is used inside braces or @section ... kind of commands. */
3989 if (insertion_level_at_start != insertion_level && !executing_macro)
3991 line_error (_("Multiline command %c%s used improperly"),
3992 COMMAND_PREFIX,
3993 command);
3994 /* We also need to keep insertion_level intact to make sure warnings are
3995 issued for @end ... command. */
3996 while (insertion_level > insertion_level_at_start)
3997 pop_insertion ();
4000 popfile ();
4001 executing_string--;
4002 es->in_use = 0;
4003 free (temp_input_filename);
4007 /* Return what would be output for STR (in newly-malloced memory), i.e.,
4008 expand Texinfo commands according to the current output format. If
4009 IMPLICIT_CODE is set, expand @code{STR}. This is generally used for
4010 short texts; filling, indentation, and html escapes are disabled. */
4012 char *
4013 expansion (char *str, int implicit_code)
4015 return maybe_escaped_expansion (str, implicit_code, 0);
4019 /* Do HTML escapes according to DO_HTML_ESCAPE. Needed in
4020 cm_printindex, q.v. */
4022 char *
4023 maybe_escaped_expansion (char *str, int implicit_code, int do_html_escape)
4025 char *result;
4027 /* Inhibit indentation and filling, so that extra newlines
4028 are not added to the expansion. (This is undesirable if
4029 we write the expanded text to macro_expansion_output_stream.) */
4030 int saved_filling_enabled = filling_enabled;
4031 int saved_indented_fill = indented_fill;
4032 int saved_no_indent = no_indent;
4033 int saved_escape_html = escape_html;
4035 filling_enabled = 0;
4036 indented_fill = 0;
4037 no_indent = 1;
4038 escape_html = do_html_escape;
4040 result = full_expansion (str, implicit_code);
4042 filling_enabled = saved_filling_enabled;
4043 indented_fill = saved_indented_fill;
4044 no_indent = saved_no_indent;
4045 escape_html = saved_escape_html;
4047 return result;
4051 /* Expand STR (or @code{STR} if IMPLICIT_CODE is nonzero). No change to
4052 any formatting parameters -- filling, indentation, html escapes,
4053 etc., are not reset. Always returned in new memory. */
4055 char *
4056 full_expansion (char *str, int implicit_code)
4058 int length;
4059 char *result;
4061 /* Inhibit any real output. */
4062 int start = output_paragraph_offset;
4063 int saved_paragraph_is_open = paragraph_is_open;
4064 int saved_output_column = output_column;
4066 /* More output state to save. */
4067 int saved_meta_pos = meta_char_pos;
4068 int saved_last_char = last_inserted_character;
4069 int saved_last_nl = last_char_was_newline;
4071 /* If we are called in the middle of processing a command, we need
4072 to dup and save the global variable `command' (which holds the
4073 name of this command), since the recursive reader loop will free
4074 it from under our feet if it finds any macros in STR. */
4075 char *saved_command = command ? xstrdup (command) : NULL;
4077 inhibit_output_flushing ();
4078 paragraph_is_open = 1;
4079 if (strlen (str) > (implicit_code
4080 ? EXECUTE_STRING_MAX - 1 - sizeof("@code{}")
4081 : EXECUTE_STRING_MAX - 1))
4082 line_error (_("`%.40s...' is too long for expansion; not expanded"), str);
4083 else
4084 execute_string (implicit_code ? "@code{%s}" : "%s", str);
4085 uninhibit_output_flushing ();
4087 /* Copy the expansion from the buffer. */
4088 length = output_paragraph_offset - start;
4089 result = xmalloc (1 + length);
4090 memcpy (result, (char *) (output_paragraph + start), length);
4091 result[length] = 0;
4093 /* Pretend it never happened. */
4094 free_and_clear (&command);
4095 command = saved_command;
4097 output_paragraph_offset = start;
4098 paragraph_is_open = saved_paragraph_is_open;
4099 output_column = saved_output_column;
4101 meta_char_pos = saved_meta_pos;
4102 last_inserted_character = saved_last_char;
4103 last_char_was_newline = saved_last_nl;
4105 return result;
4109 /* Return text (info) expansion of STR no matter what the current output
4110 format is. */
4112 char *
4113 text_expansion (char *str)
4115 char *ret;
4116 int save_html = html;
4117 int save_xml = xml;
4118 int save_docbook = docbook;
4120 html = 0;
4121 xml = 0;
4122 docbook = 0;
4123 ret = expansion (str, 0);
4124 html = save_html;
4125 xml = save_xml;
4126 docbook = save_docbook;
4128 return ret;
4132 /* Set the paragraph indentation variable to the value specified in STRING.
4133 Values can be:
4134 `asis': Don't change existing indentation.
4135 `none': Remove existing indentation.
4136 NUM: Indent NUM spaces at the starts of paragraphs.
4137 If NUM is zero, we assume `none'.
4138 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
4140 set_paragraph_indent (char *string)
4142 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
4143 paragraph_start_indent = 0;
4144 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
4145 paragraph_start_indent = -1;
4146 else
4148 if (sscanf (string, "%d", &paragraph_start_indent) != 1)
4149 return -1;
4150 else
4152 if (paragraph_start_indent == 0)
4153 paragraph_start_indent = -1;
4156 return 0;