No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / texinfo / makeinfo / makeinfo.c
blob8ad5f6612551ba99c89e59ce20c3cf9c23837cde
1 /* $NetBSD: makeinfo.c,v 1.15 2009/02/28 19:14:15 joerg Exp $ */
3 /* makeinfo -- convert Texinfo source into other formats.
4 Id: makeinfo.c,v 1.74 2004/12/19 17:15:42 karl Exp
6 Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
7 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 Original author of makeinfo: Brian Fox (bfox@ai.mit.edu). */
25 #include "system.h"
26 #include "getopt.h"
28 #define COMPILING_MAKEINFO
29 #include "makeinfo.h"
30 #include "cmds.h"
31 #include "files.h"
32 #include "float.h"
33 #include "footnote.h"
34 #include "html.h"
35 #include "index.h"
36 #include "insertion.h"
37 #include "lang.h"
38 #include "macro.h"
39 #include "node.h"
40 #include "sectioning.h"
41 #include "toc.h"
42 #include "xml.h"
44 /* You can change some of the behavior of Makeinfo by changing the
45 following defines: */
47 /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
48 appear within an @table, @ftable, or @itemize environment to have
49 standard paragraph indentation. Without this, such paragraphs have
50 no starting indentation. */
51 /* #define INDENT_PARAGRAPHS_IN_TABLE */
53 /* Define PARAGRAPH_START_INDENT to be the amount of indentation that
54 the first lines of paragraphs receive by default, where no other
55 value has been specified. Users can change this value on the command
56 line, with the --paragraph-indent option, or within the texinfo file,
57 with the @paragraphindent command. */
58 #define PARAGRAPH_START_INDENT 3
60 /* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
61 wish to appear between paragraphs. A value of 1 creates a single blank
62 line between paragraphs. Paragraphs are defined by 2 or more consecutive
63 newlines in the input file (i.e., one or more blank lines). */
64 #define DEFAULT_PARAGRAPH_SPACING 1
66 /* Global variables. */
68 /* The output file name. */
69 char *output_filename = NULL;
71 /* Name of the output file that the user elected to pass on the command line.
72 Such a name overrides any name found with the @setfilename command. */
73 char *command_output_filename = NULL;
74 static char *save_command_output_filename = NULL;
76 #define INITIAL_PARAGRAPH_SPACE 5000
77 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
79 /* The amount of indentation to add at the starts of paragraphs.
80 0 means don't change existing indentation at paragraph starts.
81 > 0 is amount to indent new paragraphs by.
82 < 0 means indent to column zero by removing indentation if necessary.
84 This is normally zero, but some people prefer paragraph starts to be
85 somewhat more indented than paragraph bodies. A pretty value for
86 this is 3. */
87 int paragraph_start_indent = PARAGRAPH_START_INDENT;
89 /* Indentation that is pending insertion. We have this for hacking lines
90 which look blank, but contain whitespace. We want to treat those as
91 blank lines. */
92 int pending_indent = 0;
94 /* The index in our internal command table of the currently
95 executing command. */
96 int command_index;
98 /* A search string which is used to find the first @setfilename. */
99 char setfilename_search[] =
100 { COMMAND_PREFIX,
101 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
103 /* Values for calling handle_variable_internal (). */
104 #define SET 1
105 #define CLEAR 2
106 #define IFSET 3
107 #define IFCLEAR 4
109 /* Flags controlling the operation of the program. */
111 /* Default is to remove output if there were errors. */
112 int force = 0;
114 /* Default is to notify users of bad choices. */
115 int print_warnings = 1;
117 /* Number of errors that we tolerate on a given fileset. */
118 int max_error_level = 100;
120 /* The actual last inserted character. Note that this may be something
121 other than NEWLINE even if last_char_was_newline is 1. */
122 int last_inserted_character = 0;
124 /* Nonzero means that a newline character has already been
125 inserted, so close_paragraph () should insert one less. */
126 int line_already_broken = 0;
128 /* When nonzero we have finished an insertion (see end_insertion ()) and we
129 want to ignore false continued paragraph closings. */
130 int insertion_paragraph_closed = 0;
132 /* Nonzero means attempt to make all of the lines have fill_column width. */
133 int do_justification = 0;
135 /* Nonzero means don't replace whitespace with &nbsp; in HTML mode. */
136 int in_html_elt = 0;
138 /* Nonzero means we are inserting a block level HTML element that must not be
139 enclosed in a <p>, such as <ul>, <ol> and <h?>. */
140 int in_html_block_level_elt = 0;
142 /* True when expanding a macro definition. */
143 static int executing_macro = 0;
145 /* True when we are inside a <li> block of a menu. */
146 static int in_menu_item = 0;
148 typedef struct brace_element
150 struct brace_element *next;
151 COMMAND_FUNCTION *proc;
152 char *command;
153 int pos, line;
154 int in_fixed_width_font;
155 } BRACE_ELEMENT;
157 BRACE_ELEMENT *brace_stack = NULL;
159 static void convert_from_file (char *name);
160 static void convert_from_loaded_file (char *name);
161 static void convert_from_stream (FILE *stream, char *name);
162 static void do_flush_right_indentation (void);
163 static void handle_variable (int action);
164 static void handle_variable_internal (int action, char *name);
165 static void init_brace_stack (void);
166 static void init_internals (void);
167 static void pop_and_call_brace (void);
168 static void remember_brace (COMMAND_FUNCTION (*proc));
169 static int end_of_sentence_p (void);
171 void maybe_update_execution_strings (char **text, unsigned int new_len);
173 /* Error handling. */
175 /* Number of errors encountered. */
176 int errors_printed = 0;
178 /* Remember that an error has been printed. If more than
179 max_error_level have been printed, then exit the program. */
180 static void
181 remember_error (void)
183 errors_printed++;
184 if (max_error_level && (errors_printed > max_error_level))
186 fprintf (stderr, _("Too many errors! Gave up.\n"));
187 flush_file_stack ();
188 if (errors_printed - max_error_level < 2)
189 cm_bye ();
190 xexit (1);
194 /* Print the last error gotten from the file system. */
196 fs_error (char *filename)
198 remember_error ();
199 perror (filename);
200 return 0;
203 /* Print an error message, and return false. */
204 void
205 #if defined (VA_FPRINTF) && __STDC__
206 error (const char *format, ...)
207 #else
208 error (format, va_alist)
209 const char *format;
210 va_dcl
211 #endif
213 #ifdef VA_FPRINTF
214 va_list ap;
215 #endif
217 remember_error ();
219 VA_START (ap, format);
220 #ifdef VA_FPRINTF
221 VA_FPRINTF (stderr, format, ap);
222 #else
223 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
224 #endif /* not VA_FPRINTF */
225 va_end (ap);
227 putc ('\n', stderr);
230 /* Just like error (), but print the input file and line number as well. */
231 void
232 #if defined (VA_FPRINTF) && __STDC__
233 file_line_error (char *infile, int lno, const char *format, ...)
234 #else
235 file_line_error (infile, lno, format, va_alist)
236 char *infile;
237 int lno;
238 const char *format;
239 va_dcl
240 #endif
242 #ifdef VA_FPRINTF
243 va_list ap;
244 #endif
246 remember_error ();
247 fprintf (stderr, "%s:%d: ", infile, lno);
249 VA_START (ap, format);
250 #ifdef VA_FPRINTF
251 VA_FPRINTF (stderr, format, ap);
252 #else
253 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
254 #endif /* not VA_FPRINTF */
255 va_end (ap);
257 fprintf (stderr, ".\n");
260 /* Just like file_line_error (), but take the input file and the line
261 number from global variables. */
262 void
263 #if defined (VA_FPRINTF) && __STDC__
264 line_error (const char *format, ...)
265 #else
266 line_error (format, va_alist)
267 const char *format;
268 va_dcl
269 #endif
271 #ifdef VA_FPRINTF
272 va_list ap;
273 #endif
275 remember_error ();
276 fprintf (stderr, "%s:%d: ", input_filename, line_number);
278 VA_START (ap, format);
279 #ifdef VA_FPRINTF
280 VA_FPRINTF (stderr, format, ap);
281 #else
282 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
283 #endif /* not VA_FPRINTF */
284 va_end (ap);
286 fprintf (stderr, ".\n");
289 void
290 #if defined (VA_FPRINTF) && __STDC__
291 warning (const char *format, ...)
292 #else
293 warning (format, va_alist)
294 const char *format;
295 va_dcl
296 #endif
298 #ifdef VA_FPRINTF
299 va_list ap;
300 #endif
302 if (print_warnings)
304 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
306 VA_START (ap, format);
307 #ifdef VA_FPRINTF
308 VA_FPRINTF (stderr, format, ap);
309 #else
310 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
311 #endif /* not VA_FPRINTF */
312 va_end (ap);
314 fprintf (stderr, ".\n");
319 /* The other side of a malformed expression. */
320 static void
321 misplaced_brace (void)
323 line_error (_("Misplaced %c"), '}');
326 /* Main. */
328 /* Display the version info of this invocation of Makeinfo. */
329 static void
330 print_version_info (void)
332 printf ("makeinfo (GNU %s) %s\n", PACKAGE, VERSION);
335 /* If EXIT_VALUE is zero, print the full usage message to stdout.
336 Otherwise, just say to use --help for more info.
337 Then exit with EXIT_VALUE. */
338 static void
339 usage (int exit_value)
341 if (exit_value != 0)
342 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
343 else
345 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname);
346 puts ("");
348 puts (_("\
349 Translate Texinfo source documentation to various other formats, by default\n\
350 Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
352 printf (_("\
353 General options:\n\
354 --error-limit=NUM quit after NUM errors (default %d).\n\
355 --force preserve output even if errors.\n\
356 --help display this help and exit.\n\
357 --no-validate suppress node cross-reference validation.\n\
358 --no-warn suppress warnings (but not errors).\n\
359 --reference-limit=NUM warn about at most NUM references (default %d).\n\
360 -v, --verbose explain what is being done.\n\
361 --version display version information and exit.\n"),
362 max_error_level, reference_warning_limit);
363 puts ("");
365 /* xgettext: no-wrap */
366 puts (_("\
367 Output format selection (default is to produce Info):\n\
368 --docbook output Docbook XML rather than Info.\n\
369 --html output HTML rather than Info.\n\
370 --xml output Texinfo XML rather than Info.\n\
371 --plaintext output plain text rather than Info.\n\
372 "));
374 puts (_("\
375 General output options:\n\
376 -E, --macro-expand FILE output macro-expanded source to FILE.\n\
377 ignoring any @setfilename.\n\
378 --no-headers suppress node separators, Node: lines, and menus\n\
379 from Info output (thus producing plain text)\n\
380 or from HTML (thus producing shorter output);\n\
381 also, write to standard output by default.\n\
382 --no-split suppress splitting of Info or HTML output,\n\
383 generate only one output file.\n\
384 --no-version-headers suppress header with makeinfo version and\n\
385 source path.\n\
386 --number-sections output chapter and sectioning numbers.\n\
387 -o, --output=FILE output to FILE (directory if split HTML),\n\
388 "));
390 printf (_("\
391 Options for Info and plain text:\n\
392 --enable-encoding output accented and special characters in\n\
393 Info output based on @documentencoding.\n\
394 --fill-column=NUM break Info lines at NUM characters (default %d).\n\
395 --footnote-style=STYLE output footnotes in Info according to STYLE:\n\
396 `separate' to put them in their own node;\n\
397 `end' to put them at the end of the node\n\
398 in which they are defined (default).\n\
399 --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
400 If VAL is `none', do not indent; if VAL is\n\
401 `asis', preserve existing indentation.\n\
402 --split-size=NUM split Info files at size NUM (default %d).\n"),
403 fill_column, paragraph_start_indent,
404 DEFAULT_SPLIT_SIZE);
405 puts ("");
407 puts (_("\
408 Options for HTML:\n\
409 --css-include=FILE include FILE in HTML <style> output;\n\
410 read stdin if FILE is -.\n\
411 "));
413 printf (_("\
414 Options for XML and Docbook:\n\
415 --output-indent=VAL indent XML elements by VAL spaces (default %d).\n\
416 If VAL is 0, ignorable whitespace is dropped.\n\
417 "), xml_indentation_increment);
418 puts ("");
420 puts (_("\
421 Input file options:\n\
422 --commands-in-node-names allow @ commands in node names.\n\
423 -D VAR define the variable VAR, as with @set.\n\
424 -I DIR append DIR to the @include search path.\n\
425 -P DIR prepend DIR to the @include search path.\n\
426 -U VAR undefine the variable VAR, as with @clear.\n\
427 "));
429 puts (_("\
430 Conditional processing in input:\n\
431 --ifdocbook process @ifdocbook and @docbook even if\n\
432 not generating Docbook.\n\
433 --ifhtml process @ifhtml and @html even if not generating HTML.\n\
434 --ifinfo process @ifinfo even if not generating Info.\n\
435 --ifplaintext process @ifplaintext even if not generating plain text.\n\
436 --iftex process @iftex and @tex; implies --no-split.\n\
437 --ifxml process @ifxml and @xml.\n\
438 --no-ifdocbook do not process @ifdocbook and @docbook text.\n\
439 --no-ifhtml do not process @ifhtml and @html text.\n\
440 --no-ifinfo do not process @ifinfo text.\n\
441 --no-ifplaintext do not process @ifplaintext text.\n\
442 --no-iftex do not process @iftex and @tex text.\n\
443 --no-ifxml do not process @ifxml and @xml text.\n\
445 Also, for the --no-ifFORMAT options, do process @ifnotFORMAT text.\n\
446 "));
448 puts (_("\
449 The defaults for the @if... conditionals depend on the output format:\n\
450 if generating HTML, --ifhtml is on and the others are off;\n\
451 if generating Info, --ifinfo is on and the others are off;\n\
452 if generating plain text, --ifplaintext is on and the others are off;\n\
453 if generating XML, --ifxml is on and the others are off.\n\
454 "));
456 fputs (_("\
457 Examples:\n\
458 makeinfo foo.texi write Info to foo's @setfilename\n\
459 makeinfo --html foo.texi write HTML to @setfilename\n\
460 makeinfo --xml foo.texi write Texinfo XML to @setfilename\n\
461 makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\
462 makeinfo --no-headers foo.texi write plain text to standard output\n\
464 makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
465 makeinfo --number-sections foo.texi write Info with numbered sections\n\
466 makeinfo --no-split foo.texi write one Info file however big\n\
467 "), stdout);
469 puts (_("\n\
470 Email bug reports to bug-texinfo@gnu.org,\n\
471 general questions and discussion to help-texinfo@gnu.org.\n\
472 Texinfo home page: http://www.gnu.org/software/texinfo/"));
474 } /* end of full help */
476 xexit (exit_value);
479 struct option long_options[] =
481 { "commands-in-node-names", 0, &expensive_validation, 1 },
482 { "css-include", 1, 0, 'C' },
483 { "docbook", 0, 0, 'd' },
484 { "enable-encoding", 0, &enable_encoding, 1 },
485 { "error-limit", 1, 0, 'e' },
486 { "fill-column", 1, 0, 'f' },
487 { "footnote-style", 1, 0, 's' },
488 { "force", 0, &force, 1 },
489 { "help", 0, 0, 'h' },
490 { "html", 0, 0, 'w' },
491 { "ifdocbook", 0, &process_docbook, 1 },
492 { "ifhtml", 0, &process_html, 1 },
493 { "ifinfo", 0, &process_info, 1 },
494 { "ifplaintext", 0, &process_plaintext, 1 },
495 { "iftex", 0, &process_tex, 1 },
496 { "ifxml", 0, &process_xml, 1 },
497 { "macro-expand", 1, 0, 'E' },
498 { "no-headers", 0, &no_headers, 1 },
499 { "no-ifdocbook", 0, &process_docbook, 0 },
500 { "no-ifhtml", 0, &process_html, 0 },
501 { "no-ifinfo", 0, &process_info, 0 },
502 { "no-ifplaintext", 0, &process_plaintext, 0 },
503 { "no-iftex", 0, &process_tex, 0 },
504 { "no-ifxml", 0, &process_xml, 0 },
505 { "no-number-footnotes", 0, &number_footnotes, 0 },
506 { "no-number-sections", 0, &number_sections, 0 },
507 { "no-pointer-validate", 0, &validating, 0 },
508 { "no-split", 0, &splitting, 0 },
509 { "no-validate", 0, &validating, 0 },
510 { "no-version-header", 0, &no_version_header, 1 },
511 { "no-warn", 0, &print_warnings, 0 },
512 { "number-footnotes", 0, &number_footnotes, 1 },
513 { "number-sections", 0, &number_sections, 1 },
514 { "output", 1, 0, 'o' },
515 { "output-indent", 1, 0, 'i' },
516 { "paragraph-indent", 1, 0, 'p' },
517 { "plaintext", 0, 0, 't' },
518 { "reference-limit", 1, 0, 'r' },
519 { "split-size", 1, 0, 'S'},
520 { "verbose", 0, &verbose_mode, 1 },
521 { "version", 0, 0, 'V' },
522 { "xml", 0, 0, 'x' },
523 {NULL, 0, NULL, 0}
526 /* We use handle_variable_internal for -D and -U, and it depends on
527 execute_string, which depends on input_filename, which is not defined
528 while we are handling options. :-\ So we save these defines in this
529 struct, and handle them later. */
530 typedef struct command_line_define
532 struct command_line_define *next;
533 int action;
534 char *define;
535 } COMMAND_LINE_DEFINE;
537 static COMMAND_LINE_DEFINE *command_line_defines = NULL;
539 /* For each file mentioned in the command line, process it, turning
540 Texinfo commands into wonderfully formatted output text. */
542 main (int argc, char **argv)
544 int c, ind;
545 int reading_from_stdin = 0;
547 #ifdef HAVE_SETLOCALE
548 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
549 of the argument to @multicolumn. */
550 setlocale (LC_TIME, "");
551 #ifdef LC_MESSAGES /* ultrix */
552 setlocale (LC_MESSAGES, "");
553 #endif
554 setlocale (LC_CTYPE, "");
555 setlocale (LC_COLLATE, "");
556 #endif
558 #ifdef ENABLE_NLS
559 /* Set the text message domain. */
560 bindtextdomain (PACKAGE, LOCALEDIR);
561 textdomain (PACKAGE);
562 #endif
564 /* If TEXINFO_OUTPUT_FORMAT envvar is set, use it to set default output.
565 Can be overridden with one of the output options. */
566 if (getenv ("TEXINFO_OUTPUT_FORMAT") != NULL)
568 if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "docbook"))
570 splitting = 0;
571 html = 0;
572 docbook = 1;
573 xml = 1;
574 process_docbook = 1;
576 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "html"))
578 html = 1;
579 docbook = 0;
580 xml = 0;
581 process_html = 1;
583 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "info"))
585 html = 0;
586 docbook = 0;
587 xml = 0;
589 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "plaintext"))
591 splitting = 0;
592 no_headers = 1;
593 html = 0;
594 docbook = 0;
595 xml = 0;
596 process_plaintext = 1;
598 else if (STREQ (getenv ("TEXINFO_OUTPUT_FORMAT"), "xml"))
600 splitting = 0;
601 html = 0;
602 docbook = 0;
603 xml = 1;
604 process_xml = 1;
606 else
607 fprintf (stderr,
608 _("%s: Ignoring unrecognized TEXINFO_OUTPUT_FORMAT value `%s'.\n"),
609 progname, getenv ("TEXINFO_OUTPUT_FORMAT"));
612 /* Parse argument flags from the input line. */
613 while ((c = getopt_long (argc, argv, "D:de:E:f:hI:i:o:p:P:r:s:t:U:vV:wx",
614 long_options, &ind)) != EOF)
616 if (c == 0 && long_options[ind].flag == 0)
617 c = long_options[ind].val;
619 switch (c)
621 case 'C': /* --css-include */
622 css_include = xstrdup (optarg);
623 break;
625 case 'D':
626 case 'U':
627 /* User specified variable to set or clear. */
628 if (xml && !docbook)
630 COMMAND_LINE_DEFINE *new = xmalloc (sizeof (COMMAND_LINE_DEFINE));
631 new->action = (c == 'D') ? SET : CLEAR;
632 new->define = xstrdup (optarg);
633 new->next = command_line_defines;
634 command_line_defines = new;
636 else
637 handle_variable_internal ((c == 'D' ? SET : CLEAR), optarg);
638 break;
640 case 'd': /* --docbook */
641 splitting = 0;
642 xml = 1;
643 docbook = 1;
644 html = 0;
645 process_docbook = 1;
646 break;
648 case 'e': /* --error-limit */
649 if (sscanf (optarg, "%d", &max_error_level) != 1)
651 fprintf (stderr,
652 _("%s: %s arg must be numeric, not `%s'.\n"),
653 progname, "--error-limit", optarg);
654 usage (1);
656 break;
658 case 'E': /* --macro-expand */
659 if (!macro_expansion_output_stream)
661 macro_expansion_filename = optarg;
662 macro_expansion_output_stream
663 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
664 if (!macro_expansion_output_stream)
665 error (_("%s: could not open macro expansion output `%s'"),
666 progname, optarg);
668 else
669 fprintf (stderr,
670 _("%s: ignoring second macro expansion output `%s'.\n"),
671 progname, optarg);
672 break;
674 case 'f': /* --fill-column */
675 if (sscanf (optarg, "%d", &fill_column) != 1)
677 fprintf (stderr,
678 _("%s: %s arg must be numeric, not `%s'.\n"),
679 progname, "--fill-column", optarg);
680 usage (1);
682 break;
684 case 'h': /* --help */
685 usage (0);
686 break;
688 case 'I':
689 /* Append user-specified dir to include file path. */
690 append_to_include_path (optarg);
691 break;
693 case 'i':
694 if (sscanf (optarg, "%d", &xml_indentation_increment) != 1)
696 fprintf (stderr,
697 _("%s: %s arg must be numeric, not `%s'.\n"),
698 progname, "--output-indent", optarg);
699 usage (1);
701 break;
703 case 'o': /* --output */
704 command_output_filename = xstrdup (optarg);
705 save_command_output_filename = command_output_filename;
706 break;
708 case 'p': /* --paragraph-indent */
709 if (set_paragraph_indent (optarg) < 0)
711 fprintf (stderr,
712 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
713 progname, optarg);
714 usage (1);
716 break;
718 case 'P':
719 /* Prepend user-specified include dir to include path. */
720 prepend_to_include_path (optarg);
721 break;
723 case 'r': /* --reference-limit */
724 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
726 fprintf (stderr,
727 _("%s: %s arg must be numeric, not `%s'.\n"),
728 progname, "--reference-limit", optarg);
729 usage (1);
731 break;
733 case 's': /* --footnote-style */
734 if (set_footnote_style (optarg) < 0)
736 fprintf (stderr,
737 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
738 progname, optarg);
739 usage (1);
741 footnote_style_preset = 1;
742 break;
744 case 'S': /* --split-size */
745 if (sscanf (optarg, "%d", &split_size) != 1)
747 fprintf (stderr,
748 _("%s: %s arg must be numeric, not `%s'.\n"),
749 progname, "--split-size", optarg);
750 usage (1);
752 break;
754 case 't': /* --plaintext */
755 splitting = 0;
756 no_headers = 1;
757 html = 0;
758 docbook = 0;
759 xml = 0;
760 process_plaintext = 1;
761 break;
763 case 'v':
764 verbose_mode++;
765 break;
767 case 'V': /* --version */
768 print_version_info ();
769 puts ("");
770 puts ("Copyright (C) 2004 Free Software Foundation, Inc.");
771 printf (_("There is NO warranty. You may redistribute this software\n\
772 under the terms of the GNU General Public License.\n\
773 For more information about these matters, see the files named COPYING.\n"));
774 xexit (0);
775 break;
777 case 'w': /* --html */
778 xml = 0;
779 docbook = 0;
780 html = 1;
781 process_html = 1;
782 break;
784 case 'x': /* --xml */
785 splitting = 0;
786 html = 0;
787 docbook = 0;
788 xml = 1;
789 process_xml = 1;
790 break;
792 case '?':
793 usage (1);
794 break;
798 if (macro_expansion_output_stream)
799 validating = 0;
801 if (!validating)
802 expensive_validation = 0;
804 if (optind == argc)
806 /* Check to see if input is a file. If so, process that. */
807 if (!isatty (fileno (stdin)))
808 reading_from_stdin = 1;
809 else
811 fprintf (stderr, _("%s: missing file argument.\n"), progname);
812 usage (1);
816 if (no_headers)
818 /* If the user did not specify an output file, use stdout. */
819 if (!command_output_filename)
820 command_output_filename = xstrdup ("-");
822 if (html && splitting && !STREQ (command_output_filename, "-"))
823 { /* --no-headers --no-split --html indicates confusion. */
824 fprintf (stderr,
825 "%s: can't split --html output to `%s' with --no-headers.\n",
826 progname, command_output_filename);
827 usage (1);
830 /* --no-headers implies --no-split. */
831 splitting = 0;
834 if (process_info == -1)
835 { /* no explicit --[no-]ifinfo option, so we'll do @ifinfo
836 if we're generating info or (for compatibility) plain text. */
837 process_info = !html && !xml;
840 if (process_plaintext == -1)
841 { /* no explicit --[no-]ifplaintext option, so we'll do @ifplaintext
842 if we're generating plain text. */
843 process_plaintext = no_headers && !html && !xml;
846 if (verbose_mode)
847 print_version_info ();
849 /* Remaining arguments are file names of texinfo files.
850 Convert them, one by one. */
851 if (!reading_from_stdin)
853 while (optind != argc)
854 convert_from_file (argv[optind++]);
856 else
857 convert_from_stream (stdin, "stdin");
859 xexit (errors_printed ? 2 : 0);
860 return 0; /* Avoid bogus warnings. */
863 /* Hacking tokens and strings. */
865 /* Return the next token as a string pointer. We cons the string. This
866 `token' means simply a command name. */
868 /* = is so @alias works. ^ and _ are so macros can be used in math mode
869 without a space following. Possibly we should simply allow alpha, to
870 be compatible with TeX. */
871 #define COMMAND_CHAR(c) (!cr_or_whitespace(c) \
872 && (c) != '{' \
873 && (c) != '}' \
874 && (c) != '=' \
875 && (c) != '_' \
876 && (c) != '^' \
879 static char *
880 read_token (void)
882 int i, character;
883 char *result;
885 /* If the first character to be read is self-delimiting, then that
886 is the command itself. */
887 character = curchar ();
888 if (self_delimiting (character))
890 input_text_offset++;
892 if (character == '\n')
893 line_number++;
895 result = xstrdup (" ");
896 *result = character;
897 return result;
900 for (i = 0; ((input_text_offset != input_text_length)
901 && (character = curchar ())
902 && COMMAND_CHAR (character));
903 i++, input_text_offset++);
904 result = xmalloc (i + 1);
905 memcpy (result, &input_text[input_text_offset - i], i);
906 result[i] = 0;
907 return result;
910 /* Return nonzero if CHARACTER is self-delimiting. */
912 self_delimiting (int character)
914 /* @; and @\ are not Texinfo commands, but they are listed here
915 anyway. I don't know why. --karl, 10aug96. */
916 return strchr ("~{|}`^\\@?=;:./-,*\'\" !\n\t", character) != NULL;
919 /* Clear whitespace from the front and end of string. */
920 void
921 canon_white (char *string)
923 char *p = string;
924 unsigned len;
926 if (!*p)
927 return;
931 if (!cr_or_whitespace (*p))
932 break;
933 ++p;
935 while (*p);
937 len = strlen (p);
938 while (len && cr_or_whitespace (p[len-1]))
939 --len;
941 if (p != string)
942 memmove (string, p, len);
944 string[len] = 0;
947 /* Bash STRING, replacing all whitespace with just one space. */
948 void
949 fix_whitespace (char *string)
951 char *temp = xmalloc (strlen (string) + 1);
952 int string_index = 0;
953 int temp_index = 0;
954 int c;
956 canon_white (string);
958 while (string[string_index])
960 c = temp[temp_index++] = string[string_index++];
962 if (c == ' ' || c == '\n' || c == '\t')
964 temp[temp_index - 1] = ' ';
965 while ((c = string[string_index]) && (c == ' ' ||
966 c == '\t' ||
967 c == '\n'))
968 string_index++;
971 temp[temp_index] = 0;
972 strcpy (string, temp);
973 free (temp);
976 /* Discard text until the desired string is found. The string is
977 included in the discarded text. */
978 void
979 discard_until (char *string)
981 int temp = search_forward (string, input_text_offset);
983 int tt = (temp < 0) ? input_text_length : temp + strlen (string);
984 int from = input_text_offset;
986 /* Find out what line we are on. */
987 while (from != tt)
988 if (input_text[from++] == '\n')
989 line_number++;
991 if (temp < 0)
993 /* not found, move current position to end of string */
994 input_text_offset = input_text_length;
995 if (strcmp (string, "\n") != 0)
996 { /* Give a more descriptive feedback, if we are looking for ``@end ''
997 during macro execution. That means someone used a multiline
998 command as an argument to, say, @section ... style commands. */
999 char *end_block = xmalloc (8);
1000 sprintf (end_block, "\n%cend ", COMMAND_PREFIX);
1001 if (executing_string && strstr (string, end_block))
1002 line_error (_("Multiline command %c%s used improperly"),
1003 COMMAND_PREFIX, command);
1004 else
1005 line_error (_("Expected `%s'"), string);
1006 free (end_block);
1007 return;
1010 else
1011 /* found, move current position to after the found string */
1012 input_text_offset = temp + strlen (string);
1015 /* Read characters from the file until we are at MATCH.
1016 Place the characters read into STRING.
1017 On exit input_text_offset is after the match string.
1018 Return the offset where the string starts. */
1020 get_until (char *match, char **string)
1022 int len, current_point, x, new_point, tem;
1024 current_point = x = input_text_offset;
1025 new_point = search_forward (match, input_text_offset);
1027 if (new_point < 0)
1028 new_point = input_text_length;
1029 len = new_point - current_point;
1031 /* Keep track of which line number we are at. */
1032 tem = new_point + (strlen (match) - 1);
1033 while (x != tem)
1034 if (input_text[x++] == '\n')
1035 line_number++;
1037 *string = xmalloc (len + 1);
1039 memcpy (*string, &input_text[current_point], len);
1040 (*string)[len] = 0;
1042 /* Now leave input_text_offset in a consistent state. */
1043 input_text_offset = tem;
1045 if (input_text_offset > input_text_length)
1046 input_text_offset = input_text_length;
1048 return new_point;
1051 /* Replace input_text[FROM .. TO] with its expansion. */
1052 void
1053 replace_with_expansion (int from, int *to)
1055 char *xp;
1056 unsigned xp_len, new_len;
1057 char *old_input = input_text;
1058 unsigned raw_len = *to - from;
1059 char *str;
1061 /* The rest of the code here moves large buffers, so let's
1062 not waste time if the input cannot possibly expand
1063 into anything. Unfortunately, we cannot avoid expansion
1064 when we see things like @code etc., even if they only
1065 asked for expansion of macros, since any Texinfo command
1066 can be potentially redefined with a macro. */
1067 if (only_macro_expansion &&
1068 memchr (input_text + from, COMMAND_PREFIX, raw_len) == 0)
1069 return;
1071 /* Get original string from input. */
1072 str = xmalloc (raw_len + 1);
1073 memcpy (str, input_text + from, raw_len);
1074 str[raw_len] = 0;
1076 /* We are going to relocate input_text, so we had better output
1077 pending portion of input_text now, before the pointer changes. */
1078 if (macro_expansion_output_stream && !executing_string
1079 && !me_inhibit_expansion)
1080 append_to_expansion_output (from);
1082 /* Expand it. */
1083 xp = expansion (str, 0);
1084 xp_len = strlen (xp);
1085 free (str);
1087 /* Plunk the expansion into the middle of `input_text' --
1088 which is terminated by a newline, not a null. Avoid
1089 expensive move of the rest of the input if the expansion
1090 has the same length as the original string. */
1091 if (xp_len != raw_len)
1093 new_len = from + xp_len + input_text_length - *to + 1;
1094 if (executing_string)
1095 { /* If we are in execute_string, we might need to update
1096 the relevant element in the execution_strings[] array,
1097 since it could have to be relocated from under our
1098 feet. (input_text is reallocated here as well, if needed.) */
1099 maybe_update_execution_strings (&input_text, new_len);
1101 else if (new_len > input_text_length + 1)
1102 /* Don't bother to realloc if we have enough space. */
1103 input_text = xrealloc (input_text, new_len);
1105 memmove (input_text + from + xp_len,
1106 input_text + *to, input_text_length - *to + 1);
1108 *to += xp_len - raw_len;
1109 /* Since we change input_text_length here, the comparison above
1110 isn't really valid, but it seems the worst that might happen is
1111 an extra xrealloc or two, so let's not worry. */
1112 input_text_length += xp_len - raw_len;
1114 memcpy (input_text + from, xp, xp_len);
1115 free (xp);
1117 /* Synchronize the macro-expansion pointers with our new input_text. */
1118 if (input_text != old_input)
1119 forget_itext (old_input);
1120 if (macro_expansion_output_stream && !executing_string)
1121 remember_itext (input_text, from);
1124 /* Read characters from the file until we are at MATCH or end of line.
1125 Place the characters read into STRING. If EXPAND is nonzero,
1126 expand the text before looking for MATCH for those cases where
1127 MATCH might be produced by some macro. */
1128 void
1129 get_until_in_line (int expand, char *match, char **string)
1131 int real_bottom = input_text_length;
1132 int limit = search_forward ("\n", input_text_offset);
1133 if (limit < 0)
1134 limit = input_text_length;
1136 /* Replace input_text[input_text_offset .. limit-1] with its expansion.
1137 This allows the node names and menu entries themselves to be
1138 constructed via a macro, as in:
1139 @macro foo{p, q}
1140 Together: \p\ & \q\.
1141 @end macro
1143 @node @foo{A,B}, next, prev, top
1145 Otherwise, the `,' separating the macro args A and B is taken as
1146 the node argument separator, so the node name is `@foo{A'. This
1147 expansion is only necessary on the first call, since we expand the
1148 whole line then. */
1149 if (expand)
1151 replace_with_expansion (input_text_offset, &limit);
1154 real_bottom = input_text_length;
1155 input_text_length = limit;
1156 get_until (match, string);
1157 input_text_length = real_bottom;
1160 void
1161 get_rest_of_line (int expand, char **string)
1163 xml_no_para ++;
1164 if (expand)
1166 char *tem;
1168 /* Don't expand non-macros in input, since we want them
1169 intact in the macro-expanded output. */
1170 only_macro_expansion++;
1171 get_until_in_line (1, "\n", &tem);
1172 only_macro_expansion--;
1173 *string = expansion (tem, 0);
1174 free (tem);
1176 else
1177 get_until_in_line (0, "\n", string);
1179 canon_white (*string);
1181 if (curchar () == '\n') /* as opposed to the end of the file... */
1183 line_number++;
1184 input_text_offset++;
1186 xml_no_para --;
1189 /* Backup the input pointer to the previous character, keeping track
1190 of the current line number. */
1191 void
1192 backup_input_pointer (void)
1194 if (input_text_offset)
1196 input_text_offset--;
1197 if (curchar () == '\n')
1198 line_number--;
1202 /* Read characters from the file until we are at MATCH or closing brace.
1203 Place the characters read into STRING. */
1204 void
1205 get_until_in_braces (char *match, char **string)
1207 char *temp;
1208 int i, brace = 0;
1209 int match_len = strlen (match);
1211 for (i = input_text_offset; i < input_text_length; i++)
1213 if (i < input_text_length - 1 && input_text[i] == '@')
1215 i++; /* skip commands like @, and @{ */
1216 continue;
1218 else if (input_text[i] == '{')
1219 brace++;
1220 else if (input_text[i] == '}')
1222 brace--;
1223 /* If looking for a brace, don't stop at the interior brace,
1224 like after "baz" in "@foo{something @bar{baz} more}". */
1225 if (brace == 0)
1226 continue;
1228 else if (input_text[i] == '\n')
1229 line_number++;
1231 if (brace < 0 ||
1232 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1233 break;
1236 match_len = i - input_text_offset;
1237 temp = xmalloc (2 + match_len);
1238 memcpy (temp, input_text + input_text_offset, match_len);
1239 temp[match_len] = 0;
1240 input_text_offset = i;
1241 *string = temp;
1246 /* Converting a file. */
1248 /* Convert the file named by NAME. The output is saved on the file
1249 named as the argument to the @setfilename command. */
1250 static char *suffixes[] = {
1251 /* ".txi" is checked first so that on 8+3 DOS filesystems, if they
1252 have "texinfo.txi" and "texinfo.tex" in the same directory, the
1253 former is used rather than the latter, due to file name truncation. */
1254 ".txi",
1255 ".texinfo",
1256 ".texi",
1257 ".txinfo",
1259 NULL
1262 static void
1263 initialize_conversion (void)
1265 init_tag_table ();
1266 init_indices ();
1267 init_internals ();
1268 init_paragraph ();
1270 /* This is used for splitting the output file and for doing section
1271 headings. It was previously initialized in `init_paragraph', but its
1272 use there loses with the `init_paragraph' calls done by the
1273 multitable code; the tag indices get reset to zero. */
1274 output_position = 0;
1277 /* Reverse the chain of structures in LIST. Output the new head
1278 of the chain. You should always assign the output value of this
1279 function to something, or you will lose the chain. */
1280 GENERIC_LIST *
1281 reverse_list (GENERIC_LIST *list)
1283 GENERIC_LIST *next;
1284 GENERIC_LIST *prev = NULL;
1286 while (list)
1288 next = list->next;
1289 list->next = prev;
1290 prev = list;
1291 list = next;
1293 return prev;
1296 /* We read in multiples of 4k, simply because it is a typical pipe size
1297 on unix systems. */
1298 #define READ_BUFFER_GROWTH (4 * 4096)
1300 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1301 source of the stream is named NAME. */
1302 static void
1303 convert_from_stream (FILE *stream, char *name)
1305 char *buffer = NULL;
1306 int buffer_offset = 0, buffer_size = 0;
1308 initialize_conversion ();
1310 /* Read until the end of the stream. This isn't strictly correct, since
1311 the texinfo input may end before the stream ends, but it is a quick
1312 working hueristic. */
1313 while (!feof (stream))
1315 int count;
1317 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1318 buffer = (char *)
1319 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1321 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1323 if (count < 0)
1325 perror (name);
1326 xexit (1);
1329 buffer_offset += count;
1330 if (count == 0)
1331 break;
1334 /* Set the globals to the new file. */
1335 input_text = buffer;
1336 input_text_length = buffer_offset;
1337 input_filename = xstrdup (name);
1338 node_filename = xstrdup (name);
1339 input_text_offset = 0;
1340 line_number = 1;
1342 /* Not strictly necessary. This magic prevents read_token () from doing
1343 extra unnecessary work each time it is called (that is a lot of times).
1344 The INPUT_TEXT_LENGTH is one past the actual end of the text. */
1345 input_text[input_text_length] = '\n';
1347 convert_from_loaded_file (name);
1350 static void
1351 convert_from_file (char *name)
1353 int i;
1354 char *filename = xmalloc (strlen (name) + 50);
1356 /* Prepend file directory to the search path, so relative links work. */
1357 prepend_to_include_path (pathname_part (name));
1359 initialize_conversion ();
1361 /* Try to load the file specified by NAME, concatenated with our
1362 various suffixes. Prefer files like `makeinfo.texi' to
1363 `makeinfo'. */
1364 for (i = 0; suffixes[i]; i++)
1366 strcpy (filename, name);
1367 strcat (filename, suffixes[i]);
1369 if (find_and_load (filename, 1))
1370 break;
1372 if (!suffixes[i][0] && strrchr (filename, '.'))
1374 fs_error (filename);
1375 free (filename);
1376 return;
1380 if (!suffixes[i])
1382 fs_error (name);
1383 free (filename);
1384 return;
1387 input_filename = filename;
1389 convert_from_loaded_file (name);
1391 /* Pop the prepended path, so multiple filenames in the
1392 command line do not screw each others include paths. */
1393 pop_path_from_include_path ();
1396 static int
1397 create_html_directory (char *dir, int can_remove_file)
1399 struct stat st;
1401 /* Already exists. */
1402 if (stat (dir, &st) == 0)
1404 /* And it's a directory, so silently reuse it. */
1405 if (S_ISDIR (st.st_mode))
1406 return 1;
1407 /* Not a directory, so move it out of the way if we are allowed. */
1408 else if (can_remove_file)
1410 if (unlink (dir) != 0)
1411 return 0;
1413 else
1414 return 0;
1417 if (mkdir (dir, 0777) == 0)
1418 /* Success! */
1419 return 1;
1420 else
1421 return 0;
1424 /* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
1425 "/foo/bar/baz/baz.html". This routine is called only if html && splitting.
1427 Split html output goes into the subdirectory of the toplevel
1428 filename, without extension. For example:
1429 @setfilename foo.info
1430 produces output in files foo/index.html, foo/second-node.html, ...
1432 But if the user said -o foo.whatever on the cmd line, then use
1433 foo.whatever unchanged. */
1435 static char *
1436 insert_toplevel_subdirectory (char *output_filename)
1438 static const char index_name[] = "index.html";
1439 char *dir, *subdir, *base, *basename, *p;
1440 char buf[PATH_MAX];
1441 const int index_len = sizeof (index_name) - 1;
1443 strcpy (buf, output_filename);
1444 dir = pathname_part (buf); /* directory of output_filename */
1445 base = filename_part (buf); /* strips suffix, too */
1446 basename = xstrdup (base); /* remember real @setfilename name */
1447 p = dir + strlen (dir) - 1;
1448 if (p > dir && IS_SLASH (*p))
1449 *p = 0;
1450 p = strrchr (base, '.');
1451 if (p)
1452 *p = 0;
1454 /* Split html output goes into subdirectory of toplevel name. */
1455 if (save_command_output_filename
1456 && STREQ (output_filename, save_command_output_filename))
1457 subdir = basename; /* from user, use unchanged */
1458 else
1459 subdir = base; /* implicit, omit suffix */
1461 free (output_filename);
1462 output_filename = xmalloc (strlen (dir) + 1
1463 + strlen (basename) + 1
1464 + index_len
1465 + 1);
1466 strcpy (output_filename, dir);
1467 if (strlen (dir))
1468 strcat (output_filename, "/");
1469 strcat (output_filename, subdir);
1471 /* First try, do not remove existing file. */
1472 if (!create_html_directory (output_filename, 0))
1474 /* That failed, try subdir name with .html.
1475 Remove it if it exists. */
1476 strcpy (output_filename, dir);
1477 if (strlen (dir))
1478 strcat (output_filename, "/");
1479 strcat (output_filename, basename);
1481 if (!create_html_directory (output_filename, 1))
1483 /* Last try failed too :-\ */
1484 line_error (_("Can't create directory `%s': %s"),
1485 output_filename, strerror (errno));
1486 xexit (1);
1490 strcat (output_filename, "/");
1491 strcat (output_filename, index_name);
1492 return output_filename;
1495 /* FIXME: this is way too hairy */
1496 static void
1497 convert_from_loaded_file (char *name)
1499 char *real_output_filename = NULL;
1501 remember_itext (input_text, 0);
1503 input_text_offset = 0;
1505 /* Avoid the `\input texinfo' line in HTML output (assuming it starts
1506 the file). */
1507 if (looking_at ("\\input"))
1508 discard_until ("\n");
1510 /* Search this file looking for the special string which starts conversion.
1511 Once found, we may truly begin. */
1512 while (input_text_offset >= 0)
1514 input_text_offset =
1515 search_forward (setfilename_search, input_text_offset);
1517 if (input_text_offset == 0
1518 || (input_text_offset > 0
1519 && input_text[input_text_offset -1] == '\n'))
1520 break;
1521 else if (input_text_offset > 0)
1522 input_text_offset++;
1525 if (input_text_offset < 0)
1527 if (!command_output_filename)
1529 #if defined (REQUIRE_SETFILENAME)
1530 error (_("No `%s' found in `%s'"), setfilename_search, name);
1531 goto finished;
1532 #else
1533 command_output_filename = output_name_from_input_name (name);
1534 #endif /* !REQUIRE_SETFILENAME */
1538 int i, end_of_first_line;
1540 /* Find the end of the first line in the file. */
1541 for (i = 0; i < input_text_length - 1; i++)
1542 if (input_text[i] == '\n')
1543 break;
1545 end_of_first_line = i + 1;
1547 for (i = 0; i < end_of_first_line; i++)
1549 if ((input_text[i] == '\\') &&
1550 (strncmp (input_text + i + 1, "input", 5) == 0))
1552 input_text_offset = i;
1553 break;
1558 else
1559 input_text_offset += strlen (setfilename_search);
1561 if (!command_output_filename)
1563 get_until ("\n", &output_filename); /* read rest of line */
1564 if (html || xml)
1565 { /* Change any extension to .html or .xml. */
1566 char *html_name, *directory_part, *basename_part, *temp;
1568 canon_white (output_filename);
1569 directory_part = pathname_part (output_filename);
1571 basename_part = filename_part (output_filename);
1573 /* Zap any existing extension. */
1574 temp = strrchr (basename_part, '.');
1575 if (temp)
1576 *temp = 0;
1578 /* Construct new filename. */
1579 html_name = xmalloc (strlen (directory_part)
1580 + strlen (basename_part) + 6);
1581 strcpy (html_name, directory_part);
1582 strcat (html_name, basename_part);
1583 strcat (html_name, html ? ".html" : ".xml");
1585 /* Replace name from @setfilename with the html name. */
1586 free (output_filename);
1587 output_filename = html_name;
1590 else
1592 if (input_text_offset != -1)
1593 discard_until ("\n");
1594 else
1595 input_text_offset = 0;
1597 real_output_filename = output_filename = command_output_filename;
1598 command_output_filename = NULL; /* for included files or whatever */
1601 canon_white (output_filename);
1602 toplevel_output_filename = xstrdup (output_filename);
1604 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
1606 if (macro_expansion_filename
1607 && strcmp (macro_expansion_filename, "-") == 0)
1609 fprintf (stderr,
1610 _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
1611 progname);
1612 macro_expansion_output_stream = NULL;
1614 real_output_filename = xstrdup (real_output_filename);
1615 output_stream = stdout;
1616 splitting = 0; /* Cannot split when writing to stdout. */
1618 else
1620 if (html && splitting)
1622 if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
1623 || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
1624 splitting = 0;
1625 else
1626 output_filename = insert_toplevel_subdirectory (output_filename);
1627 real_output_filename = xstrdup (output_filename);
1629 else if (!real_output_filename)
1630 real_output_filename = expand_filename (output_filename, name);
1631 else
1632 real_output_filename = xstrdup (real_output_filename);
1634 output_stream = fopen (real_output_filename, "w");
1637 set_current_output_filename (real_output_filename);
1639 if (xml && !docbook)
1640 xml_begin_document (filename_part (output_filename));
1642 if (verbose_mode)
1643 printf (_("Making %s file `%s' from `%s'.\n"),
1644 no_headers ? "text"
1645 : html ? "HTML"
1646 : xml ? "XML"
1647 : "info",
1648 output_filename, input_filename);
1650 if (output_stream == NULL)
1652 fs_error (real_output_filename);
1653 goto finished;
1656 /* Make the displayable filename from output_filename. Only the base
1657 portion of the filename need be displayed. */
1658 flush_output (); /* in case there was no @bye */
1659 if (output_stream != stdout)
1660 pretty_output_filename = filename_part (output_filename);
1661 else
1662 pretty_output_filename = xstrdup ("stdout");
1664 /* For this file only, count the number of newlines from the top of
1665 the file to here. This way, we keep track of line numbers for
1666 error reporting. Line_number starts at 1, since the user isn't
1667 zero-based. */
1669 int temp = 0;
1670 line_number = 1;
1671 while (temp != input_text_offset)
1672 if (input_text[temp++] == '\n')
1673 line_number++;
1676 /* html fixxme: should output this as trailer on first page. */
1677 if (!no_headers && !html && !xml && !no_version_header)
1678 add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
1679 output_filename, VERSION, input_filename);
1681 close_paragraph ();
1683 if (xml && !docbook)
1685 /* Just before the real main loop, let's handle the defines. */
1686 COMMAND_LINE_DEFINE *temp;
1688 for (temp = command_line_defines; temp; temp = temp->next)
1690 handle_variable_internal (temp->action, temp->define);
1691 free(temp->define);
1695 reader_loop ();
1696 if (xml)
1697 xml_end_document ();
1700 finished:
1701 discard_insertions (0);
1702 close_paragraph ();
1703 flush_file_stack ();
1705 if (macro_expansion_output_stream)
1707 fclose (macro_expansion_output_stream);
1708 if (errors_printed && !force
1709 && strcmp (macro_expansion_filename, "-") != 0
1710 && FILENAME_CMP (macro_expansion_filename, NULL_DEVICE) != 0
1711 && FILENAME_CMP (macro_expansion_filename, ALSO_NULL_DEVICE) != 0)
1713 fprintf (stderr,
1714 _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
1715 progname, macro_expansion_filename);
1716 if (unlink (macro_expansion_filename) < 0)
1717 perror (macro_expansion_filename);
1721 if (output_stream)
1723 output_pending_notes ();
1725 if (html)
1727 no_indent = 1;
1728 start_paragraph ();
1729 add_word ("</body></html>\n");
1730 close_paragraph ();
1733 /* maybe we want local variables in info output. */
1735 char *trailer = info_trailer ();
1736 if (!xml && !docbook && trailer)
1738 if (html)
1739 insert_string ("<!--");
1740 insert_string (trailer);
1741 free (trailer);
1742 if (html)
1743 insert_string ("\n-->\n");
1747 /* Write stuff makeinfo generates after @bye, ie. info_trailer. */
1748 flush_output ();
1750 if (output_stream != stdout)
1751 fclose (output_stream);
1753 /* If validating, then validate the entire file right now. */
1754 if (validating)
1755 validate_file (tag_table);
1757 handle_delayed_writes ();
1759 if (tag_table)
1761 tag_table = (TAG_ENTRY *) reverse_list ((GENERIC_LIST *) tag_table);
1762 if (!no_headers && !html && !STREQ (current_output_filename, "-"))
1763 write_tag_table (real_output_filename);
1766 if (splitting && !html && (!errors_printed || force))
1768 clean_old_split_files (real_output_filename);
1769 split_file (real_output_filename, split_size);
1771 else if (errors_printed
1772 && !force
1773 && strcmp (real_output_filename, "-") != 0
1774 && FILENAME_CMP (real_output_filename, NULL_DEVICE) != 0
1775 && FILENAME_CMP (real_output_filename, ALSO_NULL_DEVICE) != 0)
1776 { /* If there were errors, and no --force, remove the output. */
1777 fprintf (stderr,
1778 _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
1779 progname, real_output_filename);
1780 if (unlink (real_output_filename) < 0)
1781 perror (real_output_filename);
1784 free (real_output_filename);
1787 /* If enable_encoding is set and @documentencoding is used, return a
1788 Local Variables section (as a malloc-ed string) so that Emacs'
1789 locale features can work. Else return NULL. */
1790 char *
1791 info_trailer (void)
1793 char *encoding;
1795 if (!enable_encoding)
1796 return NULL;
1798 encoding = current_document_encoding ();
1800 if (encoding && *encoding)
1802 #define LV_FMT "\n\037\nLocal Variables:\ncoding: %s\nEnd:\n"
1803 char *lv = xmalloc (sizeof (LV_FMT) + strlen (encoding));
1804 sprintf (lv, LV_FMT, encoding);
1805 free (encoding);
1806 return lv;
1809 free (encoding);
1810 return NULL;
1813 void
1814 free_and_clear (char **pointer)
1816 if (*pointer)
1818 free (*pointer);
1819 *pointer = NULL;
1823 /* Initialize some state. */
1824 static void
1825 init_internals (void)
1827 free_and_clear (&output_filename);
1828 free_and_clear (&command);
1829 free_and_clear (&input_filename);
1830 free_node_references ();
1831 free_node_node_references ();
1832 toc_free ();
1833 init_insertion_stack ();
1834 init_brace_stack ();
1835 current_node = NULL; /* sometimes already freed */
1836 command_index = 0;
1837 in_menu = 0;
1838 in_detailmenu = 0;
1839 top_node_seen = 0;
1840 non_top_node_seen = 0;
1841 node_number = -1;
1844 void
1845 init_paragraph (void)
1847 free (output_paragraph);
1848 output_paragraph = xmalloc (paragraph_buffer_len);
1849 output_paragraph[0] = 0;
1850 output_paragraph_offset = 0;
1851 output_column = 0;
1852 paragraph_is_open = 0;
1853 current_indent = 0;
1854 meta_char_pos = 0;
1857 /* This is called from `reader_loop' when we are at the * beginning a
1858 menu line. */
1860 static void
1861 handle_menu_entry (void)
1863 char *tem;
1865 /* Ugh, glean_node_from_menu wants to read the * itself. */
1866 input_text_offset--;
1868 /* Find node name in menu entry and save it in references list for
1869 later validation. Use followed_reference type for detailmenu
1870 references since we don't want to use them for default node pointers. */
1871 tem = glean_node_from_menu (1, in_detailmenu
1872 ? followed_reference : menu_reference);
1874 if (html && tem)
1875 { /* Start a menu item with the cleaned-up line. Put an anchor
1876 around the start text (before `:' or the node name). */
1877 char *string;
1879 discard_until ("* ");
1881 /* The line number was already incremented in reader_loop when we
1882 saw the newline, and discard_until has now incremented again. */
1883 line_number--;
1885 if (had_menu_commentary)
1887 add_html_block_elt ("<ul class=\"menu\">\n");
1888 had_menu_commentary = 0;
1889 in_paragraph = 0;
1892 if (in_paragraph)
1894 add_html_block_elt ("</p>\n");
1895 add_html_block_elt ("<ul class=\"menu\">\n");
1896 in_paragraph = 0;
1899 in_menu_item = 1;
1901 add_html_block_elt ("<li><a");
1902 if (next_menu_item_number <= 9)
1904 add_word(" accesskey=");
1905 add_word_args("\"%d\"", next_menu_item_number);
1906 next_menu_item_number++;
1908 add_word (" href=\"");
1909 string = expansion (tem, 0);
1910 add_anchor_name (string, 1);
1911 add_word ("\">");
1912 free (string);
1914 /* The menu item may use macros, so expand them now. */
1915 only_macro_expansion++;
1916 get_until_in_line (1, ":", &string);
1917 only_macro_expansion--;
1918 execute_string ("%s", string); /* get escaping done */
1919 free (string);
1921 add_word ("</a>");
1923 if (looking_at ("::"))
1924 discard_until (":");
1925 else
1926 { /* discard the node name */
1927 get_until_in_line (0, ".", &string);
1928 free (string);
1930 input_text_offset++; /* discard the second colon or the period */
1932 /* Insert a colon only if there is a description of this menu item. */
1934 int save_input_text_offset = input_text_offset;
1935 int save_line_number = line_number;
1936 char *test_string;
1937 get_rest_of_line (0, &test_string);
1938 if (strlen (test_string) > 0)
1939 add_word (": ");
1940 input_text_offset = save_input_text_offset;
1941 line_number = save_line_number;
1944 else if (xml && tem)
1946 xml_start_menu_entry (tem);
1948 else if (tem)
1949 { /* For Info output, we can just use the input and the main case in
1950 reader_loop where we output what comes in. Just move off the *
1951 so the next time through reader_loop we don't end up back here. */
1952 add_char ('*');
1953 input_text_offset += 2; /* undo the pointer back-up above. */
1956 if (tem)
1957 free (tem);
1960 /* Find the command corresponding to STRING. If the command is found,
1961 return a pointer to the data structure. Otherwise return -1. */
1962 static COMMAND *
1963 get_command_entry (char *string)
1965 int i;
1967 for (i = 0; command_table[i].name; i++)
1968 if (strcmp (command_table[i].name, string) == 0)
1969 return &command_table[i];
1971 /* This command is not in our predefined command table. Perhaps
1972 it is a user defined command. */
1973 for (i = 0; i < user_command_array_len; i++)
1974 if (user_command_array[i] &&
1975 (strcmp (user_command_array[i]->name, string) == 0))
1976 return user_command_array[i];
1978 /* We never heard of this command. */
1979 return (COMMAND *) -1;
1982 /* input_text_offset is right at the command prefix character.
1983 Read the next token to determine what to do. Return zero
1984 if there's no known command or macro after the prefix character. */
1985 static int
1986 read_command (void)
1988 COMMAND *entry;
1989 int old_text_offset = input_text_offset++;
1991 free_and_clear (&command);
1992 command = read_token ();
1994 /* Check to see if this command is a macro. If so, execute it here. */
1996 MACRO_DEF *def;
1998 def = find_macro (command);
2000 if (def)
2002 /* We disallow recursive use of a macro call. Inhibit the expansion
2003 of this macro during the life of its execution. */
2004 if (!(def->flags & ME_RECURSE))
2005 def->inhibited = 1;
2007 executing_macro++;
2008 execute_macro (def);
2009 executing_macro--;
2011 if (!(def->flags & ME_RECURSE))
2012 def->inhibited = 0;
2014 return 1;
2018 if (only_macro_expansion)
2020 /* Back up to the place where we were called, so the
2021 caller will have a chance to process this non-macro. */
2022 input_text_offset = old_text_offset;
2023 return 0;
2026 /* Perform alias expansion */
2027 command = alias_expand (command);
2029 if (enclosure_command (command))
2031 remember_brace (enclosure_expand);
2032 enclosure_expand (START, output_paragraph_offset, 0);
2033 return 0;
2036 entry = get_command_entry (command);
2037 if (entry == (COMMAND *)-1)
2039 line_error (_("Unknown command `%s'"), command);
2040 return 0;
2043 if (entry->argument_in_braces == BRACE_ARGS)
2044 remember_brace (entry->proc);
2045 else if (entry->argument_in_braces == MAYBE_BRACE_ARGS)
2047 if (curchar () == '{')
2048 remember_brace (entry->proc);
2049 else
2050 { /* No braces, so arg is next char. */
2051 int ch;
2052 int saved_offset = output_paragraph_offset;
2053 (*(entry->proc)) (START, output_paragraph_offset, 0);
2055 /* Possibilities left for the next character: @ (error), }
2056 (error), whitespace (skip) anything else (normal char). */
2057 skip_whitespace ();
2058 ch = curchar ();
2059 if (ch == '@')
2061 line_error (_("Use braces to give a command as an argument to @%s"),
2062 entry->name);
2063 return 0;
2065 else if (ch == '}')
2067 /* Our caller will give the error message, because this }
2068 won't match anything. */
2069 return 0;
2072 add_char (ch);
2073 input_text_offset++;
2074 (*(entry->proc)) (END, saved_offset, output_paragraph_offset);
2075 return 1;
2079 /* Get here if we have BRACE_ARGS, NO_BRACE_ARGS, or MAYBE_BRACE_ARGS
2080 with braces. */
2081 (*(entry->proc)) (START, output_paragraph_offset, 0);
2082 return 1;
2085 /* Okay, we are ready to start the conversion. Call the reader on
2086 some text, and fill the text as it is output. Handle commands by
2087 remembering things like open braces and the current file position on a
2088 stack, and when the corresponding close brace is found, you can call
2089 the function with the proper arguments. Although the filling isn't
2090 necessary for HTML, it should do no harm. */
2091 void
2092 reader_loop (void)
2094 int character;
2095 int done = 0;
2097 while (!done)
2099 if (input_text_offset >= input_text_length)
2100 break;
2102 character = curchar ();
2104 /* If only_macro_expansion, only handle macros and leave
2105 everything else intact. */
2106 if (!only_macro_expansion && !in_fixed_width_font
2107 && ((!html && !xml) || escape_html)
2108 && (character == '\'' || character == '`')
2109 && input_text[input_text_offset + 1] == character)
2111 if (html)
2113 input_text_offset += 2;
2114 add_word (character == '`' ? "&ldquo;" : "&rdquo;");
2115 continue;
2117 else if (xml)
2119 input_text_offset += 2;
2120 xml_insert_entity (character == '`' ? "ldquo" : "rdquo");
2121 continue;
2123 else
2125 input_text_offset++;
2126 character = '"';
2130 /* Convert --- to --. */
2131 if (!only_macro_expansion && character == '-' && !in_fixed_width_font
2132 && ((!html && !xml) || escape_html))
2134 int dash_count = 0;
2136 /* Get the number of consequtive dashes. */
2137 while (input_text[input_text_offset] == '-')
2139 dash_count++;
2140 input_text_offset++;
2143 /* Eat one dash. */
2144 dash_count--;
2146 if (html || xml)
2148 if (dash_count == 0)
2149 add_char ('-');
2150 else
2151 while (dash_count > 0)
2153 if (dash_count >= 2)
2155 if (html)
2156 add_word ("&mdash;");
2157 else
2158 xml_insert_entity ("mdash");
2159 dash_count -= 2;
2161 else if (dash_count >= 1)
2163 if (html)
2164 add_word ("&ndash;");
2165 else
2166 xml_insert_entity ("ndash");
2167 dash_count--;
2171 else
2173 add_char ('-');
2174 while (--dash_count > 0)
2175 add_char ('-');
2178 continue;
2181 /* If this is a whitespace character, then check to see if the line
2182 is blank. If so, advance to the carriage return. */
2183 if (!only_macro_expansion && whitespace (character))
2185 int i = input_text_offset + 1;
2187 while (i < input_text_length && whitespace (input_text[i]))
2188 i++;
2190 if (i == input_text_length || input_text[i] == '\n')
2192 if (i == input_text_length)
2193 i--;
2195 input_text_offset = i;
2196 character = curchar ();
2200 if (character == '\n')
2201 line_number++;
2203 switch (character)
2205 case '*': /* perhaps we are at a menu */
2206 /* We used to check for this in the \n case but an @c in a
2207 menu swallows its newline, so check here instead. */
2208 if (!only_macro_expansion && in_menu
2209 && input_text_offset + 1 < input_text_length
2210 && input_text[input_text_offset-1] == '\n')
2211 handle_menu_entry ();
2212 else
2213 { /* Duplicate code from below, but not worth twisting the
2214 fallthroughs to get down there. */
2215 add_char (character);
2216 input_text_offset++;
2218 break;
2220 /* Escapes for HTML unless we're outputting raw HTML. Do
2221 this always, even if SGML rules don't require it since
2222 that's easier and safer for non-conforming browsers. */
2223 case '&':
2224 if (html && escape_html)
2225 add_word ("&amp;");
2226 else
2227 add_char (character);
2228 input_text_offset++;
2229 break;
2231 case '<':
2232 if (html && escape_html)
2233 add_word ("&lt;");
2234 else if (xml && escape_html)
2235 xml_insert_entity ("lt");
2236 else
2237 add_char (character);
2238 input_text_offset++;
2239 break;
2241 case '>':
2242 if (html && escape_html)
2243 add_word ("&gt;");
2244 else if (xml && escape_html)
2245 xml_insert_entity ("gt");
2246 else
2247 add_char (character);
2248 input_text_offset++;
2249 break;
2251 case COMMAND_PREFIX: /* @ */
2252 if (read_command () || !only_macro_expansion)
2253 break;
2255 /* FALLTHROUGH (usually) */
2256 case '{':
2257 /* Special case. We're not supposed to see this character by itself.
2258 If we do, it means there is a syntax error in the input text.
2259 Report the error here, but remember this brace on the stack so
2260 we can ignore its partner. */
2261 if (!only_macro_expansion)
2263 if (command && !STREQ (command, "math"))
2265 line_error (_("Misplaced %c"), '{');
2266 remember_brace (misplaced_brace);
2268 else
2269 /* We don't mind `extra' braces inside @math. */
2270 remember_brace (cm_no_op);
2271 /* remember_brace advances input_text_offset. */
2272 break;
2275 /* FALLTHROUGH (usually) */
2276 case '}':
2277 if (!only_macro_expansion)
2279 pop_and_call_brace ();
2280 input_text_offset++;
2281 break;
2284 /* FALLTHROUGH (usually) */
2285 default:
2286 add_char (character);
2287 input_text_offset++;
2290 if (macro_expansion_output_stream && !only_macro_expansion)
2291 maybe_write_itext (input_text, input_text_offset);
2294 static void
2295 init_brace_stack (void)
2297 brace_stack = NULL;
2300 /* Remember the current output position here. Save PROC
2301 along with it so you can call it later. */
2302 static void
2303 remember_brace_1 (COMMAND_FUNCTION (*proc), int position)
2305 BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
2306 new->next = brace_stack;
2307 new->proc = proc;
2308 new->command = command ? xstrdup (command) : "";
2309 new->pos = position;
2310 new->line = line_number;
2311 new->in_fixed_width_font = in_fixed_width_font;
2312 brace_stack = new;
2315 static void
2316 remember_brace (COMMAND_FUNCTION (*proc))
2318 if (curchar () != '{')
2319 line_error (_("%c%s expected braces"), COMMAND_PREFIX, command);
2320 else
2321 input_text_offset++;
2322 remember_brace_1 (proc, output_paragraph_offset);
2325 /* Pop the top of the brace stack, and call the associated function
2326 with the args END and POS. */
2327 static void
2328 pop_and_call_brace (void)
2330 if (brace_stack == NULL)
2332 line_error (_("Unmatched }"));
2333 return;
2337 BRACE_ELEMENT *temp;
2339 int pos = brace_stack->pos;
2340 COMMAND_FUNCTION *proc = brace_stack->proc;
2341 in_fixed_width_font = brace_stack->in_fixed_width_font;
2343 /* Reset current command, so the proc can know who it is. This is
2344 used in cm_accent. */
2345 command = brace_stack->command;
2347 temp = brace_stack->next;
2348 free (brace_stack);
2349 brace_stack = temp;
2351 (*proc) (END, pos, output_paragraph_offset);
2355 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2356 static void
2357 adjust_braces_following (int here, int amount)
2359 BRACE_ELEMENT *stack = brace_stack;
2361 while (stack)
2363 if (stack->pos >= here)
2364 stack->pos += amount;
2365 stack = stack->next;
2369 /* Return the string which invokes PROC; a pointer to a function.
2370 Always returns the first function in the command table if more than
2371 one matches PROC. */
2372 static const char *
2373 find_proc_name (COMMAND_FUNCTION (*proc))
2375 int i;
2377 for (i = 0; command_table[i].name; i++)
2378 if (proc == command_table[i].proc)
2379 return command_table[i].name;
2380 return _("NO_NAME!");
2383 /* You call discard_braces () when you shouldn't have any braces on the stack.
2384 I used to think that this happens for commands that don't take arguments
2385 in braces, but that was wrong because of things like @code{foo @@}. So now
2386 I only detect it at the beginning of nodes. */
2387 void
2388 discard_braces (void)
2390 if (!brace_stack)
2391 return;
2393 while (brace_stack)
2395 if (brace_stack->proc != misplaced_brace)
2397 const char *proc_name;
2399 proc_name = find_proc_name (brace_stack->proc);
2400 file_line_error (input_filename, brace_stack->line,
2401 _("%c%s missing close brace"), COMMAND_PREFIX,
2402 proc_name);
2403 pop_and_call_brace ();
2405 else
2407 BRACE_ELEMENT *temp;
2408 temp = brace_stack->next;
2409 free (brace_stack);
2410 brace_stack = temp;
2415 static int
2416 get_char_len (int character)
2418 /* Return the printed length of the character. */
2419 int len;
2421 switch (character)
2423 case '\t':
2424 len = (output_column + 8) & 0xf7;
2425 if (len > fill_column)
2426 len = fill_column - output_column;
2427 else
2428 len = len - output_column;
2429 break;
2431 case '\n':
2432 len = fill_column - output_column;
2433 break;
2435 default:
2436 /* ASCII control characters appear as two characters in the output
2437 (e.g., ^A). But characters with the high bit set are just one
2438 on suitable terminals, so don't count them as two for line
2439 breaking purposes. */
2440 if (0 <= character && character < ' ')
2441 len = 2;
2442 else
2443 len = 1;
2445 return len;
2448 void
2449 #if defined (VA_FPRINTF) && __STDC__
2450 add_word_args (const char *format, ...)
2451 #else
2452 add_word_args (format, va_alist)
2453 const char *format;
2454 va_dcl
2455 #endif
2457 char buffer[2000]; /* xx no fixed limits */
2458 #ifdef VA_FPRINTF
2459 va_list ap;
2460 #endif
2462 VA_START (ap, format);
2463 #ifdef VA_SPRINTF
2464 VA_SPRINTF (buffer, format, ap);
2465 #else
2466 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2467 #endif /* not VA_SPRINTF */
2468 va_end (ap);
2469 add_word (buffer);
2472 /* Add STRING to output_paragraph. */
2473 void
2474 add_word (char *string)
2476 while (*string)
2477 add_char (*string++);
2480 /* Like add_word, but inhibits conversion of whitespace into &nbsp;.
2481 Use this to output HTML directives with embedded blanks, to make
2482 them @w-safe. */
2483 void
2484 add_html_elt (char *string)
2486 in_html_elt++;
2487 add_word (string);
2488 in_html_elt--;
2491 /* These two functions below, add_html_block_elt and add_html_block_elt_args,
2492 are mixtures of add_html_elt and add_word_args. They inform makeinfo that
2493 the current HTML element being inserted should not be enclosed in a <p>
2494 element. */
2495 void
2496 add_html_block_elt (char *string)
2498 in_html_block_level_elt++;
2499 add_word (string);
2500 in_html_block_level_elt--;
2503 void
2504 #if defined (VA_FPRINTF) && __STDC__
2505 add_html_block_elt_args (const char *format, ...)
2506 #else
2507 add_html_block_elt_args (format, va_alist)
2508 const char *format;
2509 va_dcl
2510 #endif
2512 char buffer[2000]; /* xx no fixed limits */
2513 #ifdef VA_FPRINTF
2514 va_list ap;
2515 #endif
2517 VA_START (ap, format);
2518 #ifdef VA_SPRINTF
2519 VA_SPRINTF (buffer, format, ap);
2520 #else
2521 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2522 #endif /* not VA_SPRINTF */
2523 va_end (ap);
2524 add_html_block_elt (buffer);
2527 /* Here is another awful kludge, used in add_char. Ordinarily, macro
2528 expansions take place in the body of the document, and therefore we
2529 should html_output_head when we see one. But there's an exception: a
2530 macro call might take place within @copying, and that does not start
2531 the real output, even though we fully expand the copying text.
2533 So we need to be able to check if we are defining the @copying text.
2534 We do this by looking back through the insertion stack. */
2535 static int
2536 defining_copying (void)
2538 INSERTION_ELT *i;
2539 for (i = insertion_stack; i; i = i->next)
2541 if (i->insertion == copying)
2542 return 1;
2544 return 0;
2548 /* Add the character to the current paragraph. If filling_enabled is
2549 nonzero, then do filling as well. */
2550 void
2551 add_char (int character)
2553 if (xml)
2555 xml_add_char (character);
2556 return;
2559 /* If we are avoiding outputting headers, and we are currently
2560 in a menu, then simply return. But if we're only expanding macros,
2561 then we're being called from glean_node_from_menu to try to
2562 remember a menu reference, and we need that so we can do defaulting. */
2563 if (no_headers && !only_macro_expansion && (in_menu || in_detailmenu))
2564 return;
2566 /* If we are adding a character now, then we don't have to
2567 ignore close_paragraph () calls any more. */
2568 if (must_start_paragraph && character != '\n')
2570 must_start_paragraph = 0;
2571 line_already_broken = 0; /* The line is no longer broken. */
2572 if (current_indent > output_column)
2574 indent (current_indent - output_column);
2575 output_column = current_indent;
2579 if (non_splitting_words
2580 && !(html && in_html_elt)
2581 && strchr (" \t\n", character))
2583 if (html || docbook)
2584 { /* Seems cleaner to use &nbsp; than an 8-bit char. */
2585 int saved_escape_html = escape_html;
2586 escape_html = 0;
2587 add_word ("&nbsp");
2588 escape_html = saved_escape_html;
2589 character = ';';
2591 else
2592 character = META (' '); /* unmeta-d in flush_output */
2595 insertion_paragraph_closed = 0;
2597 switch (character)
2599 case '\n':
2600 if (!filling_enabled && !(html && (in_menu || in_detailmenu)))
2602 insert ('\n');
2604 if (force_flush_right)
2606 close_paragraph ();
2607 /* Hack to force single blank lines out in this mode. */
2608 flush_output ();
2611 output_column = 0;
2613 if (!no_indent && paragraph_is_open)
2614 indent (output_column = current_indent);
2615 break;
2617 else if (end_of_sentence_p ())
2618 /* CHARACTER is newline, and filling is enabled. */
2620 insert (' ');
2621 output_column++;
2622 last_inserted_character = character;
2625 if (last_char_was_newline)
2627 if (html)
2628 last_char_was_newline++;
2629 close_paragraph ();
2630 pending_indent = 0;
2632 else
2634 last_char_was_newline = 1;
2635 if (html)
2636 insert ('\n');
2637 else
2638 insert (' ');
2639 output_column++;
2641 break;
2643 default: /* not at newline */
2645 int len = get_char_len (character);
2646 int suppress_insert = 0;
2648 if ((character == ' ') && (last_char_was_newline))
2650 if (!paragraph_is_open)
2652 pending_indent++;
2653 return;
2657 /* This is sad, but it seems desirable to not force any
2658 particular order on the front matter commands. This way,
2659 the document can do @settitle, @documentlanguage, etc, in
2660 any order and with any omissions, and we'll still output
2661 the html <head> `just in time'. */
2662 if ((executing_macro || !executing_string)
2663 && !only_macro_expansion
2664 && html && !html_output_head_p && !defining_copying ())
2665 html_output_head ();
2667 if (!paragraph_is_open)
2669 start_paragraph ();
2670 /* If the paragraph is supposed to be indented a certain
2671 way, then discard all of the pending whitespace.
2672 Otherwise, we let the whitespace stay. */
2673 if (!paragraph_start_indent)
2674 indent (pending_indent);
2675 pending_indent = 0;
2677 /* This check for in_html_block_level_elt prevents <p> from being
2678 inserted when we already have html markup starting a paragraph,
2679 as with <ul> and <h1> and the like. */
2680 if (html && !in_html_block_level_elt)
2682 if ((in_menu || in_detailmenu) && in_menu_item)
2684 insert_string ("</li></ul>\n");
2685 in_menu_item = 0;
2687 insert_string ("<p>");
2688 in_paragraph = 1;
2689 adjust_braces_following (0, 3); /* adjust for <p> */
2693 output_column += len;
2694 if (output_column > fill_column)
2696 if (filling_enabled && !html)
2698 int temp = output_paragraph_offset;
2699 while (--temp > 0 && output_paragraph[temp] != '\n')
2701 /* If we have found a space, we have the place to break
2702 the line. */
2703 if (output_paragraph[temp] == ' ')
2705 /* Remove trailing whitespace from output. */
2706 while (temp && whitespace (output_paragraph[temp - 1]))
2707 temp--;
2709 /* If we went back all the way to the newline of the
2710 preceding line, it probably means that the word we
2711 are adding is itself wider than the space that the
2712 indentation and the fill_column let us use. In
2713 that case, do NOT insert another newline, since it
2714 won't help. Just indent to current_indent and
2715 leave it alone, since that's the most we can do. */
2716 if (temp && output_paragraph[temp - 1] != '\n')
2717 output_paragraph[temp++] = '\n';
2719 /* We have correctly broken the line where we want
2720 to. What we don't want is spaces following where
2721 we have decided to break the line. We get rid of
2722 them. */
2724 int t1 = temp;
2726 for (;; t1++)
2728 if (t1 == output_paragraph_offset)
2730 if (whitespace (character))
2731 suppress_insert = 1;
2732 break;
2734 if (!whitespace (output_paragraph[t1]))
2735 break;
2738 if (t1 != temp)
2740 adjust_braces_following (temp, (- (t1 - temp)));
2741 memmove (&output_paragraph[temp],
2742 &output_paragraph[t1],
2743 output_paragraph_offset - t1);
2744 output_paragraph_offset -= (t1 - temp);
2748 /* Filled, but now indent if that is right. */
2749 if (indented_fill && current_indent > 0)
2751 int buffer_len = ((output_paragraph_offset - temp)
2752 + current_indent);
2753 char *temp_buffer = xmalloc (buffer_len);
2754 int indentation = 0;
2756 /* We have to shift any markers that are in
2757 front of the wrap point. */
2758 adjust_braces_following (temp, current_indent);
2760 while (current_indent > 0 &&
2761 indentation != current_indent)
2762 temp_buffer[indentation++] = ' ';
2764 memcpy ((char *) &temp_buffer[current_indent],
2765 (char *) &output_paragraph[temp],
2766 buffer_len - current_indent);
2768 if (output_paragraph_offset + buffer_len
2769 >= paragraph_buffer_len)
2771 unsigned char *tt = xrealloc
2772 (output_paragraph,
2773 (paragraph_buffer_len += buffer_len));
2774 output_paragraph = tt;
2776 memcpy ((char *) &output_paragraph[temp],
2777 temp_buffer, buffer_len);
2778 output_paragraph_offset += current_indent;
2779 free (temp_buffer);
2781 output_column = 0;
2782 while (temp < output_paragraph_offset)
2783 output_column +=
2784 get_char_len (output_paragraph[temp++]);
2785 output_column += len;
2786 break;
2792 if (!suppress_insert)
2794 insert (character);
2795 last_inserted_character = character;
2797 last_char_was_newline = 0;
2798 line_already_broken = 0;
2803 /* Add a character and store its position in meta_char_pos. */
2804 void
2805 add_meta_char (int character)
2807 meta_char_pos = output_paragraph_offset;
2808 add_char (character);
2811 /* Insert CHARACTER into `output_paragraph'. */
2812 void
2813 insert (int character)
2815 /* We don't want to strip trailing whitespace in multitables. Otherwise
2816 horizontal separators confuse the font locking in Info mode in Emacs,
2817 because it looks like a @subsection. Adding a trailing space to those
2818 lines fixes it. */
2819 if (character == '\n' && !html && !xml && !multitable_active)
2821 while (output_paragraph_offset
2822 && whitespace (output_paragraph[output_paragraph_offset-1]))
2823 output_paragraph_offset--;
2826 output_paragraph[output_paragraph_offset++] = character;
2827 if (output_paragraph_offset == paragraph_buffer_len)
2829 output_paragraph =
2830 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2834 /* Insert the null-terminated string STRING into `output_paragraph'. */
2835 void
2836 insert_string (const char *string)
2838 while (*string)
2839 insert (*string++);
2843 /* Sentences might have these characters after the period (or whatever). */
2844 #define POST_SENTENCE(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2845 || (c) == ']')
2847 /* Return true if at an end-of-sentence character, possibly followed by
2848 post-sentence punctuation to ignore. */
2849 static int
2850 end_of_sentence_p (void)
2852 int loc = output_paragraph_offset - 1;
2854 /* If nothing has been output, don't check output_paragraph[-1]. */
2855 if (loc < 0)
2856 return 0;
2858 /* A post-sentence character that is at meta_char_pos is not really
2859 a post-sentence character; it was produced by a markup such as
2860 @samp. We don't want the period inside @samp to be treated as a
2861 sentence ender. */
2862 while (loc > 0
2863 && loc != meta_char_pos && POST_SENTENCE (output_paragraph[loc]))
2864 loc--;
2865 return loc != meta_char_pos && sentence_ender (output_paragraph[loc]);
2869 /* Remove upto COUNT characters of whitespace from the
2870 the current output line. If COUNT is less than zero,
2871 then remove until none left. */
2872 void
2873 kill_self_indent (int count)
2875 /* Handle infinite case first. */
2876 if (count < 0)
2878 output_column = 0;
2879 while (output_paragraph_offset)
2881 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2882 output_paragraph_offset--;
2883 else
2884 break;
2887 else
2889 while (output_paragraph_offset && count--)
2890 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2891 output_paragraph_offset--;
2892 else
2893 break;
2897 /* Nonzero means do not honor calls to flush_output (). */
2898 static int flushing_ignored = 0;
2900 /* Prevent calls to flush_output () from having any effect. */
2901 void
2902 inhibit_output_flushing (void)
2904 flushing_ignored++;
2907 /* Allow calls to flush_output () to write the paragraph data. */
2908 void
2909 uninhibit_output_flushing (void)
2911 flushing_ignored--;
2914 void
2915 flush_output (void)
2917 int i;
2919 if (!output_paragraph_offset || flushing_ignored)
2920 return;
2922 for (i = 0; i < output_paragraph_offset; i++)
2924 if (output_paragraph[i] == '\n')
2926 output_line_number++;
2927 node_line_number++;
2930 /* If we turned on the 8th bit for a space inside @w, turn it
2931 back off for output. This might be problematic, since the
2932 0x80 character may be used in 8-bit character sets. Sigh.
2933 In any case, don't do this for HTML, since the nbsp character
2934 is valid input and must be passed along to the browser. */
2935 if (!html && (output_paragraph[i] & meta_character_bit))
2937 int temp = UNMETA (output_paragraph[i]);
2938 if (temp == ' ')
2939 output_paragraph[i] &= 0x7f;
2943 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2945 output_position += output_paragraph_offset;
2946 output_paragraph_offset = 0;
2947 meta_char_pos = 0;
2950 /* How to close a paragraph controlling the number of lines between
2951 this one and the last one. */
2953 /* Paragraph spacing is controlled by this variable. It is the number of
2954 blank lines that you wish to appear between paragraphs. A value of
2955 1 creates a single blank line between paragraphs. */
2956 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2958 static void
2959 close_paragraph_with_lines (int lines)
2961 int old_spacing = paragraph_spacing;
2962 paragraph_spacing = lines;
2963 close_paragraph ();
2964 paragraph_spacing = old_spacing;
2967 /* Close the current paragraph, leaving no blank lines between them. */
2968 void
2969 close_single_paragraph (void)
2971 close_paragraph_with_lines (0);
2974 /* Close a paragraph after an insertion has ended. */
2975 void
2976 close_insertion_paragraph (void)
2978 if (!insertion_paragraph_closed)
2980 /* Close the current paragraph, breaking the line. */
2981 close_single_paragraph ();
2983 /* Start a new paragraph, with the correct indentation for the now
2984 current insertion level (one above the one that we are ending). */
2985 start_paragraph ();
2987 /* Tell `close_paragraph' that the previous line has already been
2988 broken, so it should insert one less newline. */
2989 line_already_broken = 1;
2991 /* Tell functions such as `add_char' we've already found a newline. */
2992 ignore_blank_line ();
2994 else
2996 /* If the insertion paragraph is closed already, then we are seeing
2997 two `@end' commands in a row. Note that the first one we saw was
2998 handled in the first part of this if-then-else clause, and at that
2999 time `start_paragraph' was called, partially to handle the proper
3000 indentation of the current line. However, the indentation level
3001 may have just changed again, so we may have to outdent the current
3002 line to the new indentation level. */
3003 if (current_indent < output_column)
3004 kill_self_indent (output_column - current_indent);
3007 insertion_paragraph_closed = 1;
3010 /* Close the currently open paragraph. */
3011 void
3012 close_paragraph (void)
3014 int i;
3016 /* We don't need these newlines in XML and Docbook outputs for
3017 paragraph seperation. We have <para> element for that. */
3018 if (xml)
3019 return;
3021 /* The insertion paragraph is no longer closed. */
3022 insertion_paragraph_closed = 0;
3024 if (paragraph_is_open && !must_start_paragraph)
3026 int tindex = output_paragraph_offset;
3028 /* Back up to last non-newline/space character, forcing all such
3029 subsequent characters to be newlines. This isn't strictly
3030 necessary, but a couple of functions use the presence of a newline
3031 to make decisions. */
3032 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
3034 int c = output_paragraph[tindex];
3036 if (c == ' '|| c == '\n')
3037 output_paragraph[tindex] = '\n';
3038 else
3039 break;
3042 /* All trailing whitespace is ignored. */
3043 output_paragraph_offset = ++tindex;
3045 /* Break the line if that is appropriate. */
3046 if (paragraph_spacing >= 0)
3047 insert ('\n');
3049 /* Add as many blank lines as is specified in `paragraph_spacing'. */
3050 if (!force_flush_right)
3052 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
3054 insert ('\n');
3055 /* Don't need anything extra for HTML in usual case of no
3056 extra paragraph spacing. */
3057 if (html && i > 0)
3058 insert_string ("<br>");
3062 /* If we are doing flush right indentation, then do it now
3063 on the paragraph (really a single line). */
3064 if (force_flush_right)
3065 do_flush_right_indentation ();
3067 flush_output ();
3068 paragraph_is_open = 0;
3069 no_indent = 0;
3070 output_column = 0;
3073 ignore_blank_line ();
3076 /* Make the last line just read look as if it were only a newline. */
3077 void
3078 ignore_blank_line (void)
3080 last_inserted_character = '\n';
3081 last_char_was_newline = 1;
3084 /* Align the end of the text in output_paragraph with fill_column. */
3085 static void
3086 do_flush_right_indentation (void)
3088 char *temp;
3089 int temp_len;
3091 kill_self_indent (-1);
3093 if (output_paragraph[0] != '\n')
3095 output_paragraph[output_paragraph_offset] = 0;
3097 if (output_paragraph_offset < fill_column)
3099 int i;
3101 if (fill_column >= paragraph_buffer_len)
3102 output_paragraph =
3103 xrealloc (output_paragraph,
3104 (paragraph_buffer_len += fill_column));
3106 temp_len = strlen ((char *)output_paragraph);
3107 temp = xmalloc (temp_len + 1);
3108 memcpy (temp, (char *)output_paragraph, temp_len);
3110 for (i = 0; i < fill_column - output_paragraph_offset; i++)
3111 output_paragraph[i] = ' ';
3113 memcpy ((char *)output_paragraph + i, temp, temp_len);
3114 free (temp);
3115 output_paragraph_offset = fill_column;
3116 adjust_braces_following (0, i);
3121 /* Begin a new paragraph. */
3122 void
3123 start_paragraph (void)
3125 /* First close existing one. */
3126 if (paragraph_is_open)
3127 close_paragraph ();
3129 /* In either case, the insertion paragraph is no longer closed. */
3130 insertion_paragraph_closed = 0;
3132 /* However, the paragraph is open! */
3133 paragraph_is_open = 1;
3135 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
3136 had to be called before we would allow any other paragraph operations
3137 to have an effect. */
3138 if (!must_start_paragraph)
3140 int amount_to_indent = 0;
3142 /* If doing indentation, then insert the appropriate amount. */
3143 if (!no_indent)
3145 if (inhibit_paragraph_indentation)
3147 amount_to_indent = current_indent;
3148 if (inhibit_paragraph_indentation < 0)
3149 inhibit_paragraph_indentation++;
3151 else if (paragraph_start_indent < 0)
3152 amount_to_indent = current_indent;
3153 else
3154 amount_to_indent = current_indent + paragraph_start_indent;
3156 if (amount_to_indent >= output_column)
3158 amount_to_indent -= output_column;
3159 indent (amount_to_indent);
3160 output_column += amount_to_indent;
3164 else
3165 must_start_paragraph = 0;
3168 /* Insert the indentation specified by AMOUNT. */
3169 void
3170 indent (int amount)
3172 /* For every START_POS saved within the brace stack which will be affected
3173 by this indentation, bump that start pos forward. */
3174 adjust_braces_following (output_paragraph_offset, amount);
3176 while (--amount >= 0)
3177 insert (' ');
3180 /* Search forward for STRING in input_text.
3181 FROM says where where to start. */
3183 search_forward (char *string, int from)
3185 int len = strlen (string);
3187 while (from < input_text_length)
3189 if (strncmp (input_text + from, string, len) == 0)
3190 return from;
3191 from++;
3193 return -1;
3196 /* search_forward until n characters. */
3198 search_forward_until_pos (char *string, int from, int end_pos)
3200 int save_input_text_length = input_text_length;
3201 input_text_length = end_pos;
3203 from = search_forward (string, from);
3205 input_text_length = save_input_text_length;
3207 return from;
3210 /* Return next non-whitespace and non-cr character. */
3212 next_nonwhitespace_character (void)
3214 /* First check the current input_text. Start from the next char because
3215 we already have input_text[input_text_offset] in ``current''. */
3216 int pos = input_text_offset + 1;
3218 while (pos < input_text_length)
3220 if (!cr_or_whitespace(input_text[pos]))
3221 return input_text[pos];
3222 pos++;
3225 { /* Can't find a valid character, so go through filestack
3226 in case we are doing @include or expanding a macro. */
3227 FSTACK *tos = filestack;
3229 while (tos)
3231 int tmp_input_text_length = filestack->size;
3232 int tmp_input_text_offset = filestack->offset;
3233 char *tmp_input_text = filestack->text;
3235 while (tmp_input_text_offset < tmp_input_text_length)
3237 if (!cr_or_whitespace(tmp_input_text[tmp_input_text_offset]))
3238 return tmp_input_text[tmp_input_text_offset];
3239 tmp_input_text_offset++;
3242 tos = tos->next;
3246 return -1;
3249 /* An external image is a reference, kind of. The parsing is (not
3250 coincidentally) similar, anyway. */
3251 void
3252 cm_image (int arg)
3254 char *name_arg, *w_arg, *h_arg, *alt_arg, *ext_arg;
3256 if (arg == END)
3257 return;
3259 name_arg = get_xref_token (1); /* expands all macros in image */
3260 w_arg = get_xref_token (0);
3261 h_arg = get_xref_token (0);
3262 alt_arg = get_xref_token (1); /* expands all macros in alt text */
3263 ext_arg = get_xref_token (0);
3265 if (*name_arg)
3267 struct stat file_info;
3268 char *pathname = NULL;
3269 char *fullname = xmalloc (strlen (name_arg)
3270 + (ext_arg && *ext_arg ? strlen (ext_arg) + 1: 4) + 1);
3272 if (ext_arg && *ext_arg)
3274 sprintf (fullname, "%s%s", name_arg, ext_arg);
3275 if (access (fullname, R_OK) != 0)
3276 pathname = get_file_info_in_path (fullname, include_files_path,
3277 &file_info);
3279 if (pathname == NULL)
3281 /* Backwards compatibility (4.6 <= version < 4.7):
3282 try prefixing @image's EXTENSION parameter with a period. */
3283 sprintf (fullname, "%s.%s", name_arg, ext_arg);
3284 if (access (fullname, R_OK) != 0)
3285 pathname = get_file_info_in_path (fullname, include_files_path,
3286 &file_info);
3289 else
3291 sprintf (fullname, "%s.png", name_arg);
3292 if (access (fullname, R_OK) != 0) {
3293 pathname = get_file_info_in_path (fullname,
3294 include_files_path, &file_info);
3295 if (pathname == NULL) {
3296 sprintf (fullname, "%s.jpg", name_arg);
3297 if (access (fullname, R_OK) != 0) {
3298 sprintf (fullname, "%s.gif", name_arg);
3299 if (access (fullname, R_OK) != 0) {
3300 pathname = get_file_info_in_path (fullname,
3301 include_files_path, &file_info);
3308 if (html)
3310 int image_in_div = 0;
3312 if (pathname == NULL && access (fullname, R_OK) != 0)
3314 line_error(_("@image file `%s' (for HTML) not readable: %s"),
3315 fullname, strerror (errno));
3316 return;
3318 if (pathname != NULL && access (pathname, R_OK) != 0)
3320 line_error (_("No such file `%s'"),
3321 fullname);
3322 return;
3325 if (!paragraph_is_open)
3327 add_html_block_elt ("<div class=\"block-image\">");
3328 image_in_div = 1;
3331 add_html_elt ("<img src=");
3332 add_word_args ("\"%s\"", fullname);
3333 add_html_elt (" alt=");
3334 add_word_args ("\"%s\">",
3335 escape_string (*alt_arg ? text_expansion (alt_arg) : fullname));
3337 if (image_in_div)
3338 add_html_block_elt ("</div>");
3340 else if (xml && docbook)
3341 xml_insert_docbook_image (name_arg);
3342 else if (xml)
3344 extern int xml_in_para;
3345 extern int xml_no_para;
3346 int elt = xml_in_para ? INLINEIMAGE : IMAGE;
3348 if (!xml_in_para)
3349 xml_no_para++;
3351 xml_insert_element_with_attribute (elt,
3352 START, "width=\"%s\" height=\"%s\" name=\"%s\" extension=\"%s\"",
3353 w_arg, h_arg, name_arg, ext_arg);
3354 xml_insert_element (IMAGEALTTEXT, START);
3355 execute_string ("%s", alt_arg);
3356 xml_insert_element (IMAGEALTTEXT, END);
3357 xml_insert_element (elt, END);
3359 if (!xml_in_para)
3360 xml_no_para--;
3362 else
3363 { /* Try to open foo.EXT or foo.txt. */
3364 FILE *image_file;
3365 char *txtpath = NULL;
3366 char *txtname = xmalloc (strlen (name_arg)
3367 + (ext_arg && *ext_arg
3368 ? strlen (ext_arg) : 4) + 1);
3369 strcpy (txtname, name_arg);
3370 strcat (txtname, ".txt");
3371 image_file = fopen (txtname, "r");
3372 if (image_file == NULL)
3374 txtpath = get_file_info_in_path (txtname,
3375 include_files_path, &file_info);
3376 if (txtpath != NULL)
3377 image_file = fopen (txtpath, "r");
3380 if (image_file != NULL
3381 || access (fullname, R_OK) == 0
3382 || (pathname != NULL && access (pathname, R_OK) == 0))
3384 int ch;
3385 int save_inhibit_indentation = inhibit_paragraph_indentation;
3386 int save_filling_enabled = filling_enabled;
3387 int image_in_brackets = paragraph_is_open;
3389 /* Write magic ^@^H[image ...^@^H] cookie in the info file, if
3390 there's an accompanying bitmap. Otherwise just include the
3391 text image. In the plaintext output, always include the text
3392 image without the magic cookie. */
3393 int use_magic_cookie = !no_headers
3394 && access (fullname, R_OK) == 0 && !STREQ (fullname, txtname);
3396 inhibit_paragraph_indentation = 1;
3397 filling_enabled = 0;
3398 last_char_was_newline = 0;
3400 if (use_magic_cookie)
3402 add_char ('\0');
3403 add_word ("\010[image");
3405 if (access (fullname, R_OK) == 0
3406 || (pathname != NULL && access (pathname, R_OK) == 0))
3407 add_word_args (" src=\"%s\"", fullname);
3409 if (*alt_arg)
3410 add_word_args (" alt=\"%s\"", alt_arg);
3413 if (image_file != NULL)
3415 if (use_magic_cookie)
3416 add_word (" text=\"");
3418 if (image_in_brackets)
3419 add_char ('[');
3421 /* Maybe we need to remove the final newline if the image
3422 file is only one line to allow in-line images. On the
3423 other hand, they could just make the file without a
3424 final newline. */
3425 while ((ch = getc (image_file)) != EOF)
3427 if (use_magic_cookie && (ch == '"' || ch == '\\'))
3428 add_char ('\\');
3429 add_char (ch);
3432 if (image_in_brackets)
3433 add_char (']');
3435 if (use_magic_cookie)
3436 add_char ('"');
3438 if (fclose (image_file) != 0)
3439 perror (txtname);
3442 if (use_magic_cookie)
3444 add_char ('\0');
3445 add_word ("\010]");
3448 inhibit_paragraph_indentation = save_inhibit_indentation;
3449 filling_enabled = save_filling_enabled;
3451 else
3452 warning (_("@image file `%s' (for text) unreadable: %s"),
3453 txtname, strerror (errno));
3456 free (fullname);
3457 if (pathname)
3458 free (pathname);
3460 else
3461 line_error (_("@image missing filename argument"));
3463 if (name_arg)
3464 free (name_arg);
3465 if (w_arg)
3466 free (w_arg);
3467 if (h_arg)
3468 free (h_arg);
3469 if (alt_arg)
3470 free (alt_arg);
3471 if (ext_arg)
3472 free (ext_arg);
3475 /* Conditionals. */
3477 /* A structure which contains `defined' variables. */
3478 typedef struct defines {
3479 struct defines *next;
3480 char *name;
3481 char *value;
3482 } DEFINE;
3484 /* The linked list of `set' defines. */
3485 DEFINE *defines = NULL;
3487 /* Add NAME to the list of `set' defines. */
3488 static void
3489 set (char *name, char *value)
3491 DEFINE *temp;
3493 for (temp = defines; temp; temp = temp->next)
3494 if (strcmp (name, temp->name) == 0)
3496 free (temp->value);
3497 temp->value = xstrdup (value);
3498 return;
3501 temp = xmalloc (sizeof (DEFINE));
3502 temp->next = defines;
3503 temp->name = xstrdup (name);
3504 temp->value = xstrdup (value);
3505 defines = temp;
3507 if (xml && !docbook)
3509 xml_insert_element_with_attribute (SETVALUE, START, "name=\"%s\"", name);
3510 execute_string ("%s", value);
3511 xml_insert_element (SETVALUE, END);
3515 /* Remove NAME from the list of `set' defines. */
3516 static void
3517 clear (char *name)
3519 DEFINE *temp, *last;
3521 last = NULL;
3522 temp = defines;
3524 while (temp)
3526 if (strcmp (temp->name, name) == 0)
3528 if (last)
3529 last->next = temp->next;
3530 else
3531 defines = temp->next;
3533 free (temp->name);
3534 free (temp->value);
3535 free (temp);
3536 break;
3538 last = temp;
3539 temp = temp->next;
3542 if (xml && !docbook)
3544 xml_insert_element_with_attribute (CLEARVALUE, START, "name=\"%s\"", name);
3545 xml_insert_element (CLEARVALUE, END);
3549 /* Return the value of NAME. The return value is NULL if NAME is unset. */
3550 static char *
3551 set_p (char *name)
3553 DEFINE *temp;
3555 for (temp = defines; temp; temp = temp->next)
3556 if (strcmp (temp->name, name) == 0)
3557 return temp->value;
3559 return NULL;
3562 /* Create a variable whose name appears as the first word on this line. */
3563 void
3564 cm_set (void)
3566 handle_variable (SET);
3569 /* Remove a variable whose name appears as the first word on this line. */
3570 void
3571 cm_clear (void)
3573 handle_variable (CLEAR);
3576 void
3577 cm_ifset (void)
3579 handle_variable (IFSET);
3582 void
3583 cm_ifclear (void)
3585 handle_variable (IFCLEAR);
3588 /* This command takes braces, but we parse the contents specially, so we
3589 don't use the standard brace popping code.
3591 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
3592 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
3593 it produces no output. */
3594 void
3595 cm_ifeq (void)
3597 char **arglist;
3599 arglist = get_brace_args (0);
3601 if (arglist)
3603 if (array_len (arglist) > 1)
3605 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
3606 (arglist[2]))
3607 execute_string ("%s\n", arglist[2]);
3610 free_array (arglist);
3614 void
3615 cm_value (int arg, int start_pos, int end_pos)
3617 static int value_level = 0, saved_meta_pos = -1;
3619 /* xml_add_char() skips any content inside menus when output format is
3620 Docbook, so @value{} is no use there. Also start_pos and end_pos does not
3621 get updated, causing name to be empty string. So just return. */
3622 if (docbook && in_menu)
3623 return;
3625 /* All the text after @value{ upto the matching } will eventually
3626 disappear from output_paragraph, when this function is called
3627 with ARG == END. If the text produced until then sets
3628 meta_char_pos, we will need to restore it to the value it had
3629 before @value was seen. So we need to save the previous value
3630 of meta_char_pos here. */
3631 if (arg == START)
3633 /* If we are already inside some outer @value, don't overwrite
3634 the value saved in saved_meta_pos. */
3635 if (!value_level)
3636 saved_meta_pos = meta_char_pos;
3637 value_level++;
3638 /* While the argument of @value is processed, we need to inhibit
3639 textual transformations like "--" into "-", since @set didn't
3640 do that when it grabbed the name of the variable. */
3641 in_fixed_width_font++;
3643 else
3645 char *name = (char *) &output_paragraph[start_pos];
3646 char *value;
3647 output_paragraph[end_pos] = 0;
3648 name = xstrdup (name);
3649 value = set_p (name);
3650 output_column -= end_pos - start_pos;
3651 output_paragraph_offset = start_pos;
3653 /* Restore the previous value of meta_char_pos if the stuff
3654 inside this @value{} moved it. */
3655 if (saved_meta_pos == -1) /* can't happen inside @value{} */
3656 abort ();
3657 if (value_level == 1
3658 && meta_char_pos >= start_pos && meta_char_pos < end_pos)
3660 meta_char_pos = saved_meta_pos;
3661 saved_meta_pos = -1;
3663 value_level--;
3664 /* No need to decrement in_fixed_width_font, since before
3665 we are called with arg == END, the reader loop already
3666 popped the brace stack, which restored in_fixed_width_font,
3667 among other things. */
3669 if (value)
3671 /* We need to get past the closing brace since the value may
3672 expand to a context-sensitive macro (e.g. @xref) and produce
3673 spurious warnings */
3674 input_text_offset++;
3675 execute_string ("%s", value);
3676 input_text_offset--;
3678 else
3680 warning (_("undefined flag: %s"), name);
3681 add_word_args (_("{No value for `%s'}"), name);
3684 free (name);
3688 /* Set, clear, or conditionalize based on ACTION. */
3689 static void
3690 handle_variable (int action)
3692 char *name;
3694 get_rest_of_line (0, &name);
3695 /* If we hit the end of text in get_rest_of_line, backing up
3696 input pointer will cause the last character of the last line
3697 be pushed back onto the input, which is wrong. */
3698 if (input_text_offset < input_text_length)
3699 backup_input_pointer ();
3700 handle_variable_internal (action, name);
3701 free (name);
3704 static void
3705 handle_variable_internal (int action, char *name)
3707 char *temp;
3708 int delimiter, additional_text_present = 0;
3710 /* Only the first word of NAME is a valid tag. */
3711 temp = name;
3712 delimiter = 0;
3713 while (*temp && (delimiter || !whitespace (*temp)))
3715 /* #if defined (SET_WITH_EQUAL) */
3716 if (*temp == '"' || *temp == '\'')
3718 if (*temp == delimiter)
3719 delimiter = 0;
3720 else
3721 delimiter = *temp;
3723 /* #endif SET_WITH_EQUAL */
3724 temp++;
3727 if (*temp)
3728 additional_text_present++;
3730 *temp = 0;
3732 if (!*name)
3733 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
3734 else
3736 switch (action)
3738 case SET:
3740 char *value;
3742 #if defined (SET_WITH_EQUAL)
3743 /* Allow a value to be saved along with a variable. The value is
3744 the text following an `=' sign in NAME, if any is present. */
3746 for (value = name; *value && *value != '='; value++);
3748 if (*value)
3749 *value++ = 0;
3751 if (*value == '"' || *value == '\'')
3753 value++;
3754 value[strlen (value) - 1] = 0;
3757 #else /* !SET_WITH_EQUAL */
3758 /* The VALUE of NAME is the remainder of the line sans
3759 whitespace. */
3760 if (additional_text_present)
3762 value = temp + 1;
3763 canon_white (value);
3765 else
3766 value = "";
3767 #endif /* !SET_WITH_VALUE */
3769 set (name, value);
3771 break;
3773 case CLEAR:
3774 clear (name);
3775 break;
3777 case IFSET:
3778 case IFCLEAR:
3779 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
3780 read lines from the the file until we reach a matching
3781 "@end CONDITION". This means that we only take note of
3782 "@ifset/clear" and "@end" commands. */
3784 char condition[8];
3785 int condition_len;
3786 int orig_line_number = line_number;
3788 if (action == IFSET)
3789 strcpy (condition, "ifset");
3790 else
3791 strcpy (condition, "ifclear");
3793 condition_len = strlen (condition);
3795 if ((action == IFSET && !set_p (name))
3796 || (action == IFCLEAR && set_p (name)))
3798 int level = 0, done = 0;
3800 while (!done && input_text_offset < input_text_length)
3802 char *freeable_line, *line;
3804 get_rest_of_line (0, &freeable_line);
3806 for (line = freeable_line; whitespace (*line); line++);
3808 if (*line == COMMAND_PREFIX &&
3809 (strncmp (line + 1, condition, condition_len) == 0))
3810 level++;
3811 else if (strncmp (line, "@end", 4) == 0)
3813 char *cname = line + 4;
3814 char *temp;
3816 while (*cname && whitespace (*cname))
3817 cname++;
3818 temp = cname;
3820 while (*temp && !whitespace (*temp))
3821 temp++;
3822 *temp = 0;
3824 if (strcmp (cname, condition) == 0)
3826 if (!level)
3828 done = 1;
3830 else
3831 level--;
3834 free (freeable_line);
3837 if (!done)
3838 file_line_error (input_filename, orig_line_number,
3839 _("Reached eof before matching @end %s"),
3840 condition);
3842 /* We found the end of a false @ifset/ifclear. If we are
3843 in a menu, back up over the newline that ends the ifset,
3844 since that newline may also begin the next menu entry. */
3845 break;
3847 else
3849 if (action == IFSET)
3850 begin_insertion (ifset);
3851 else
3852 begin_insertion (ifclear);
3855 break;
3860 /* Execution of random text not in file. */
3861 typedef struct {
3862 char *string; /* The string buffer. */
3863 int size; /* The size of the buffer. */
3864 int in_use; /* Nonzero means string currently in use. */
3865 } EXECUTION_STRING;
3867 static EXECUTION_STRING **execution_strings = NULL;
3868 static int execution_strings_index = 0;
3869 static int execution_strings_slots = 0;
3871 static EXECUTION_STRING *
3872 get_execution_string (int initial_size)
3874 int i = 0;
3875 EXECUTION_STRING *es = NULL;
3877 if (execution_strings)
3879 for (i = 0; i < execution_strings_index; i++)
3880 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
3882 es = execution_strings[i];
3883 break;
3887 if (!es)
3889 if (execution_strings_index + 1 >= execution_strings_slots)
3891 execution_strings = xrealloc
3892 (execution_strings,
3893 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
3894 for (; i < execution_strings_slots; i++)
3895 execution_strings[i] = NULL;
3898 execution_strings[execution_strings_index] =
3899 xmalloc (sizeof (EXECUTION_STRING));
3900 es = execution_strings[execution_strings_index];
3901 execution_strings_index++;
3903 es->size = 0;
3904 es->string = NULL;
3905 es->in_use = 0;
3908 if (initial_size > es->size)
3910 es->string = xrealloc (es->string, initial_size);
3911 es->size = initial_size;
3913 return es;
3916 /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
3917 entry in the execution_strings[] array and change the .STRING and
3918 .SIZE members of that entry as appropriate. */
3919 void
3920 maybe_update_execution_strings (char **text, unsigned int new_len)
3922 int i = 0;
3924 if (execution_strings)
3926 for (i = 0; i < execution_strings_index; i++)
3927 if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
3928 execution_strings[i]->string == *text)
3930 /* Don't ever shrink the string storage in execution_strings[]!
3931 execute_string assumes that it is always big enough to store
3932 every possible execution_string, and will break if that's
3933 not true. So we only enlarge the string storage if the
3934 current size isn't big enough. */
3935 if (execution_strings[i]->size < new_len)
3937 execution_strings[i]->string =
3938 *text = xrealloc (*text, new_len + 1);
3939 execution_strings[i]->size = new_len + 1;
3941 return;
3944 /* We should *never* end up here, since if we are inside
3945 execute_string, TEXT is always in execution_strings[]. */
3946 abort ();
3949 /* FIXME: this is an arbitrary limit. */
3950 #define EXECUTE_STRING_MAX 16*1024
3952 /* Execute the string produced by formatting the ARGs with FORMAT. This
3953 is like submitting a new file with @include. */
3954 void
3955 #if defined (VA_FPRINTF) && __STDC__
3956 execute_string (char *format, ...)
3957 #else
3958 execute_string (format, va_alist)
3959 char *format;
3960 va_dcl
3961 #endif
3963 EXECUTION_STRING *es;
3964 char *temp_string, *temp_input_filename;
3965 #ifdef VA_FPRINTF
3966 va_list ap;
3967 #endif
3968 int insertion_level_at_start = insertion_level;
3970 es = get_execution_string (EXECUTE_STRING_MAX);
3971 temp_string = es->string;
3972 es->in_use = 1;
3974 VA_START (ap, format);
3975 #ifdef VA_SPRINTF
3976 VA_SPRINTF (temp_string, format, ap);
3977 #else
3978 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
3979 #endif /* not VA_SPRINTF */
3980 va_end (ap);
3982 pushfile ();
3983 input_text_offset = 0;
3984 input_text = temp_string;
3985 input_text_length = strlen (temp_string);
3986 input_filename = xstrdup (input_filename);
3987 temp_input_filename = input_filename;
3989 executing_string++;
3990 reader_loop ();
3992 /* If insertion stack level changes during execution, that means a multiline
3993 command is used inside braces or @section ... kind of commands. */
3994 if (insertion_level_at_start != insertion_level && !executing_macro)
3996 line_error (_("Multiline command %c%s used improperly"),
3997 COMMAND_PREFIX,
3998 command);
3999 /* We also need to keep insertion_level intact to make sure warnings are
4000 issued for @end ... command. */
4001 while (insertion_level > insertion_level_at_start)
4002 pop_insertion ();
4005 popfile ();
4006 executing_string--;
4007 es->in_use = 0;
4008 free (temp_input_filename);
4012 /* Return what would be output for STR (in newly-malloced memory), i.e.,
4013 expand Texinfo commands according to the current output format. If
4014 IMPLICIT_CODE is set, expand @code{STR}. This is generally used for
4015 short texts; filling, indentation, and html escapes are disabled. */
4017 char *
4018 expansion (char *str, int implicit_code)
4020 return maybe_escaped_expansion (str, implicit_code, 0);
4024 /* Do HTML escapes according to DO_HTML_ESCAPE. Needed in
4025 cm_printindex, q.v. */
4027 char *
4028 maybe_escaped_expansion (char *str, int implicit_code, int do_html_escape)
4030 char *result;
4032 /* Inhibit indentation and filling, so that extra newlines
4033 are not added to the expansion. (This is undesirable if
4034 we write the expanded text to macro_expansion_output_stream.) */
4035 int saved_filling_enabled = filling_enabled;
4036 int saved_indented_fill = indented_fill;
4037 int saved_no_indent = no_indent;
4038 int saved_escape_html = escape_html;
4040 filling_enabled = 0;
4041 indented_fill = 0;
4042 no_indent = 1;
4043 escape_html = do_html_escape;
4045 result = full_expansion (str, implicit_code);
4047 filling_enabled = saved_filling_enabled;
4048 indented_fill = saved_indented_fill;
4049 no_indent = saved_no_indent;
4050 escape_html = saved_escape_html;
4052 return result;
4056 /* Expand STR (or @code{STR} if IMPLICIT_CODE is nonzero). No change to
4057 any formatting parameters -- filling, indentation, html escapes,
4058 etc., are not reset. Always returned in new memory. */
4060 char *
4061 full_expansion (char *str, int implicit_code)
4063 int length;
4064 char *result;
4066 /* Inhibit any real output. */
4067 int start = output_paragraph_offset;
4068 int saved_paragraph_is_open = paragraph_is_open;
4069 int saved_output_column = output_column;
4071 /* More output state to save. */
4072 int saved_meta_pos = meta_char_pos;
4073 int saved_last_char = last_inserted_character;
4074 int saved_last_nl = last_char_was_newline;
4076 /* If we are called in the middle of processing a command, we need
4077 to dup and save the global variable `command' (which holds the
4078 name of this command), since the recursive reader loop will free
4079 it from under our feet if it finds any macros in STR. */
4080 char *saved_command = command ? xstrdup (command) : NULL;
4082 inhibit_output_flushing ();
4083 paragraph_is_open = 1;
4084 if (strlen (str) > (implicit_code
4085 ? EXECUTE_STRING_MAX - 1 - sizeof("@code{}")
4086 : EXECUTE_STRING_MAX - 1))
4087 line_error (_("`%.40s...' is too long for expansion; not expanded"), str);
4088 else
4089 execute_string (implicit_code ? "@code{%s}" : "%s", str);
4090 uninhibit_output_flushing ();
4092 /* Copy the expansion from the buffer. */
4093 length = output_paragraph_offset - start;
4094 result = xmalloc (1 + length);
4095 memcpy (result, (char *) (output_paragraph + start), length);
4096 result[length] = 0;
4098 /* Pretend it never happened. */
4099 free_and_clear (&command);
4100 command = saved_command;
4102 output_paragraph_offset = start;
4103 paragraph_is_open = saved_paragraph_is_open;
4104 output_column = saved_output_column;
4106 meta_char_pos = saved_meta_pos;
4107 last_inserted_character = saved_last_char;
4108 last_char_was_newline = saved_last_nl;
4110 return result;
4114 /* Return text (info) expansion of STR no matter what the current output
4115 format is. */
4117 char *
4118 text_expansion (char *str)
4120 char *ret;
4121 int save_html = html;
4122 int save_xml = xml;
4123 int save_docbook = docbook;
4125 html = 0;
4126 xml = 0;
4127 docbook = 0;
4128 ret = expansion (str, 0);
4129 html = save_html;
4130 xml = save_xml;
4131 docbook = save_docbook;
4133 return ret;
4137 /* Set the paragraph indentation variable to the value specified in STRING.
4138 Values can be:
4139 `asis': Don't change existing indentation.
4140 `none': Remove existing indentation.
4141 NUM: Indent NUM spaces at the starts of paragraphs.
4142 If NUM is zero, we assume `none'.
4143 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
4145 set_paragraph_indent (char *string)
4147 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
4148 paragraph_start_indent = 0;
4149 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
4150 paragraph_start_indent = -1;
4151 else
4153 if (sscanf (string, "%d", &paragraph_start_indent) != 1)
4154 return -1;
4155 else
4157 if (paragraph_start_indent == 0)
4158 paragraph_start_indent = -1;
4161 return 0;