summaryrefslogtreecommitdiffstats
path: root/contrib/texinfo/makeinfo
diff options
context:
space:
mode:
authorru <ru@FreeBSD.org>2002-03-25 13:10:59 +0000
committerru <ru@FreeBSD.org>2002-03-25 13:10:59 +0000
commit333ccbd459b8f8b7ca3e35ac14aa4175d683420a (patch)
tree4d5bf107ba5862656b07b4384bd499cfb63ac3f5 /contrib/texinfo/makeinfo
parent6feb2c895f76c85f62bf9654677786e91af23e0f (diff)
downloadFreeBSD-src-333ccbd459b8f8b7ca3e35ac14aa4175d683420a.zip
FreeBSD-src-333ccbd459b8f8b7ca3e35ac14aa4175d683420a.tar.gz
Use stock (FSF) version of this file.
Diffstat (limited to 'contrib/texinfo/makeinfo')
-rw-r--r--contrib/texinfo/makeinfo/makeinfo.c885
1 files changed, 637 insertions, 248 deletions
diff --git a/contrib/texinfo/makeinfo/makeinfo.c b/contrib/texinfo/makeinfo/makeinfo.c
index 5f042bc..5bd7ff4 100644
--- a/contrib/texinfo/makeinfo/makeinfo.c
+++ b/contrib/texinfo/makeinfo/makeinfo.c
@@ -1,7 +1,8 @@
+/* $FreeBSD$ */
/* makeinfo -- convert Texinfo source into other formats.
- $Id: makeinfo.c,v 1.171 1999/09/19 15:24:44 karl Exp $
+ $Id: makeinfo.c,v 1.195 2002/02/11 17:12:49 karl Exp $
- Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98, 99
+ Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 01, 02
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -34,34 +35,7 @@
#include "macro.h"
#include "node.h"
#include "toc.h"
-
-/* We'd like to take advantage of _doprnt if it's around, a la error.c,
- but then we'd have no VA_SPRINTF. */
-#if HAVE_VPRINTF
-# if __STDC__
-# include <stdarg.h>
-# define VA_START(args, lastarg) va_start(args, lastarg)
-# else
-# include <varargs.h>
-# define VA_START(args, lastarg) va_start(args)
-# endif
-# define VA_FPRINTF(file, fmt, ap) vfprintf (file, fmt, ap)
-# define VA_SPRINTF(str, fmt, ap) vsprintf (str, fmt, ap)
-#else /* not HAVE_VPRINTF */
-# define VA_START(args, lastarg)
-# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
-# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
-# define va_end(args)
-#endif
-
-/* DJGPP supports /dev/null, which is okay for Unix aficionados,
- shell scripts and Makefiles, but interactive DOS die-hards
- would probably want to have NUL as well. */
-#ifdef __DJGPP__
-# define ALSO_NULL_DEVICE "NUL"
-#else
-# define ALSO_NULL_DEVICE ""
-#endif
+#include "xml.h"
/* You can change some of the behavior of Makeinfo by changing the
following defines: */
@@ -157,6 +131,9 @@ int insertion_paragraph_closed = 0;
/* Nonzero means attempt to make all of the lines have fill_column width. */
int do_justification = 0;
+/* Nonzero means don't replace whitespace with &nbsp; in HTML mode. */
+int in_html_elt = 0;
+
typedef struct brace_element
{
struct brace_element *next;
@@ -262,7 +239,38 @@ error (format, va_alist)
putc ('\n', stderr);
}
-/* Just like error (), but print the line number as well. */
+/* Just like error (), but print the input file and line number as well. */
+void
+#if defined (VA_FPRINTF) && __STDC__
+file_line_error (char *infile, int lno, char *format, ...)
+#else
+file_line_error (infile, lno, format, va_alist)
+ char *infile;
+ int lno;
+ char *format;
+ va_dcl
+#endif
+{
+#ifdef VA_FPRINTF
+ va_list ap;
+#endif
+
+ remember_error ();
+ fprintf (stderr, "%s:%d: ", infile, lno);
+
+ VA_START (ap, format);
+#ifdef VA_FPRINTF
+ VA_FPRINTF (stderr, format, ap);
+#else
+ fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
+#endif /* not VA_FPRINTF */
+ va_end (ap);
+
+ fprintf (stderr, ".\n");
+}
+
+/* Just like file_line_error (), but take the input file and the line
+ number from global variables. */
void
#if defined (VA_FPRINTF) && __STDC__
line_error (char *format, ...)
@@ -362,68 +370,106 @@ usage (exit_value)
fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
else
{
- printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n\
-\n\
-Translate Texinfo source documentation to various other formats:\n\
-Info files suitable for reading online with Emacs or standalone GNU Info\n\
-(by default); plain text (with --no-headers); or HTML (with --html).\n\
-\n\
-Options:\n\
- --commands-in-node-names allow @ commands in node names.\n\
- -D VAR define a variable, as with @set.\n\
- -E, --macro-expand FILE output macro-expanded source to FILE.\n\
- --error-limit=NUM quit after NUM errors (default %d).\n\
- --fill-column=NUM break Info lines at NUM characters (default %d).\n\
- --footnote-style=STYLE output footnotes according to STYLE:\n\
- `separate' to place footnotes in their own node,\n\
- `end' to place the footnotes at the end of the\n\
- node in which they are defined (the default).\n\
- --force preserve output even if errors.\n\
- --help display this help and exit.\n\
- --html output HTML rather than Info format;\n\
- -I DIR append DIR to the @include search path.\n\
- --ifhtml process @ifhtml and @html text even when not\n\
- generating HTML.\n\
- --ifinfo process @ifinfo text even when generating HTML.\n\
- --iftex process @iftex and @tex text.\n\
- implies --no-split.\n"),
- progname, max_error_level, fill_column);
+ printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n"), progname);
+ printf ("\n");
+ /* xgettext: no-wrap */
+ puts (_("\
+Translate Texinfo source documentation to various other formats, by default\n\
+Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
+
+ /* xgettext: no-wrap */
printf (_("\
- --no-headers suppress Info node separators and Node: lines and\n\
- write to standard output without --output.\n\
- --no-ifhtml do not process @ifhtml and @html text.\n\
- --no-ifinfo do not process @ifinfo text.\n\
- --no-iftex do not process @iftex and @tex text.\n\
- --no-split suppress splitting of large Info output files or\n\
- generation of one HTML file per node.\n\
- --no-validate suppress node cross-reference validation.\n\
- --no-warn suppress warnings (but not errors).\n\
- --number-sections include chapter, section, etc. numbers in output.\n\
- -o, --output=FILE output to FILE, ignoring any @setfilename.\n\
- -P DIR prepend DIR to the @include search path.\n\
- --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
- if VAL is `none', do not indent;\n\
- if VAL is `asis', preserve existing indentation.\n\
- --reference-limit=NUM warn about at most NUM references (default %d).\n\
- -U VAR undefine a variable, as with @clear.\n\
- -v, --verbose explain what is being done.\n\
- --version display version information and exit.\n\
-"),
- paragraph_start_indent, reference_warning_limit);
+General options:\n\
+ --error-limit=NUM quit after NUM errors (default %d).\n\
+ --force preserve output even if errors.\n\
+ --help display this help and exit.\n\
+ --no-validate suppress node cross-reference validation.\n\
+ --no-warn suppress warnings (but not errors).\n\
+ --reference-limit=NUM warn about at most NUM references (default %d).\n\
+ -v, --verbose explain what is being done.\n\
+ --version display version information and exit.\n"),
+ max_error_level, reference_warning_limit);
+ printf ("\n");
+
+ /* xgettext: no-wrap */
+ puts (_("\
+Output format selection (default is to produce Info):\n\
+ --docbook output DocBook rather than Info.\n\
+ --html output HTML rather than Info.\n\
+ --no-headers output plain text, suppressing Info node\n\
+ separators and Node: lines; also, write to\n\
+ standard output without --output.\n\
+ --xml output XML (TexinfoML) rather than Info.\n\
+"));
+
+ puts (_("\
+General output options:\n\
+ -E, --macro-expand FILE output macro-expanded source to FILE.\n\
+ ignoring any @setfilename.\n\
+ --no-split suppress splitting of Info or HTML output,\n\
+ generate only one output file.\n\
+ --number-sections output chapter and sectioning numbers.\n\
+ -o, --output=FILE output to FILE (directory if split HTML),\n\
+"));
+
+ /* xgettext: no-wrap */
+ printf (_("\
+Options for Info and plain text:\n\
+ --enable-encoding output accented and special characters in\n\
+ Info output based on @documentencoding.\n\
+ --fill-column=NUM break Info lines at NUM characters (default %d).\n\
+ --footnote-style=STYLE output footnotes in Info according to STYLE:\n\
+ `separate' to put them in their own node;\n\
+ `end' to put them at the end of the node\n\
+ in which they are defined (default).\n\
+ --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d).\n\
+ If VAL is `none', do not indent; if VAL is\n\
+ `asis', preserve existing indentation.\n\
+ --split-size=NUM split Info files at size NUM (default %d).\n"),
+ fill_column, paragraph_start_indent,
+ DEFAULT_SPLIT_SIZE);
}
-
- puts (_("\n\
-The defaults for the @if... conditionals depend on the output format:\n\
-if generating HTML, --ifhtml is on and the others are off;\n\
-if generating Info or plain text, --ifinfo is on and the others are off.\n\
-\n\
+ printf ("\n");
+
+ /* xgettext: no-wrap */
+ puts (_("\
+Input file options:\n\
+ --commands-in-node-names allow @ commands in node names.\n\
+ -D VAR define the variable VAR, as with @set.\n\
+ -I DIR append DIR to the @include search path.\n\
+ -P DIR prepend DIR to the @include search path.\n\
+ -U VAR undefine the variable VAR, as with @clear.\n\
+"));
+ /* xgettext: no-wrap */
+ puts (_("\
+Conditional processing in input:\n\
+ --ifhtml process @ifhtml and @html even if not generating HTML.\n\
+ --ifinfo process @ifinfo text even when generating HTML.\n\
+ --iftex process @iftex and @tex text; implies --no-split.\n\
+ --no-ifhtml do not process @ifhtml and @html text.\n\
+ --no-ifinfo do not process @ifinfo text.\n\
+ --no-iftex do not process @iftex and @tex text.\n\
+"));
+
+ /* xgettext: no-wrap */
+ puts (_("\
+ The defaults for the @if... conditionals depend on the output format:\n\
+ if generating HTML, --ifhtml is on and the others are off;\n\
+ if generating Info or plain text, --ifinfo is on and the others are off.\n\
+"));
+
+ /* xgettext: no-wrap */
+ puts (_("\
Examples:\n\
- makeinfo foo.texi write Info to foo's @setfilename\n\
- makeinfo --html foo.texi write HTML to foo's @setfilename\n\
- makeinfo --no-headers -o - foo.texi write plain text to standard output\n\
- makeinfo --number-sections foo.texi write Info with numbered sections\n\
- makeinfo --no-split foo.texi write one Info file however big\n\
-\n\
+ makeinfo foo.texi write Info to foo's @setfilename\n\
+ makeinfo --html foo.texi write HTML to foo's @setfilename\n\
+ makeinfo --no-headers -o - foo.texi write plain text to standard output\n\
+ makeinfo --number-sections foo.texi write Info with numbered sections\n\
+ makeinfo --no-split foo.texi write one Info file however big\n\
+"));
+
+ /* xgettext: no-wrap */
+ puts (_("\
Email bug reports to bug-texinfo@gnu.org,\n\
general questions and discussion to help-texinfo@gnu.org."));
xexit (exit_value);
@@ -432,6 +478,8 @@ general questions and discussion to help-texinfo@gnu.org."));
struct option long_options[] =
{
{ "commands-in-node-names", 0, &expensive_validation, 1 },
+ { "docbook", 0, 0, 'd' },
+ { "enable-encoding", 0, &enable_encoding, 1 },
{ "error-limit", 1, 0, 'e' },
{ "fill-column", 1, 0, 'f' },
{ "footnote-style", 1, 0, 's' },
@@ -457,8 +505,10 @@ struct option long_options[] =
{ "output", 1, 0, 'o' },
{ "paragraph-indent", 1, 0, 'p' },
{ "reference-limit", 1, 0, 'r' },
+ { "split-size", 1, 0, 'S'},
{ "verbose", 0, &verbose_mode, 1 },
{ "version", 0, 0, 'V' },
+ { "xml", 0, 0, 'x' },
{NULL, 0, NULL, 0}
};
@@ -487,7 +537,7 @@ main (argc, argv)
textdomain (PACKAGE);
/* Parse argument flags from the input line. */
- while ((c = getopt_long (argc, argv, "D:e:E:f:hI:o:p:P:r:s:U:vV:w",
+ while ((c = getopt_long (argc, argv, "D:de:E:f:hI:o:p:P:r:s:U:vV:wx",
long_options, &ind)) != EOF)
{
if (c == 0 && long_options[ind].flag == 0)
@@ -501,13 +551,19 @@ main (argc, argv)
handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
break;
+ case 'd': /* --docbook */
+ splitting = 0;
+ xml = 1;
+ docbook = 1;
+ break;
+
case 'e': /* --error-limit */
if (sscanf (optarg, "%d", &max_error_level) != 1)
{
fprintf (stderr,
_("%s: %s arg must be numeric, not `%s'.\n"),
"--error-limit", progname, optarg);
- usage (stderr, 1);
+ usage (1);
}
break;
@@ -606,6 +662,16 @@ main (argc, argv)
footnote_style_preset = 1;
break;
+ case 'S': /* --split-size */
+ if (sscanf (optarg, "%d", &split_size) != 1)
+ {
+ fprintf (stderr,
+ _("%s: %s arg must be numeric, not `%s'.\n"),
+ "--split-size", progname, optarg);
+ usage (1);
+ }
+ break;
+
case 'v':
verbose_mode++;
break;
@@ -617,7 +683,7 @@ main (argc, argv)
There is NO warranty. You may redistribute this software\n\
under the terms of the GNU General Public License.\n\
For more information about these matters, see the files named COPYING.\n"),
- "1999");
+ "2002");
exit (0);
break;
@@ -625,9 +691,13 @@ For more information about these matters, see the files named COPYING.\n"),
html = 1;
process_html = 1;
process_info = 0;
- splitting = 0; /* too complicated for now */
break;
+ case 'x': /* --xml */
+ splitting = 0;
+ xml = 1;
+ break;
+
case '?':
usage (1);
break;
@@ -971,6 +1041,7 @@ get_rest_of_line (expand, string)
int expand;
char **string;
{
+ xml_no_para ++;
if (expand)
{
char *tem;
@@ -993,6 +1064,7 @@ get_rest_of_line (expand, string)
line_number++;
input_text_offset++;
}
+ xml_no_para --;
}
/* Backup the input pointer to the previous character, keeping track
@@ -1020,10 +1092,21 @@ get_until_in_braces (match, string)
for (i = input_text_offset; i < input_text_length; i++)
{
- if (input_text[i] == '{')
+ if (i < input_text_length - 1 && input_text[i] == '@')
+ {
+ i++; /* skip commands like @, and @{ */
+ continue;
+ }
+ else if (input_text[i] == '{')
brace++;
else if (input_text[i] == '}')
- brace--;
+ {
+ brace--;
+ /* If looking for a brace, don't stop at the interior brace,
+ like after "baz" in "@foo{something @bar{baz} more}". */
+ if (brace == 0)
+ continue;
+ }
else if (input_text[i] == '\n')
line_number++;
@@ -1191,6 +1274,77 @@ convert_from_file (name)
convert_from_loaded_file (name);
}
+/* Given OUTPUT_FILENAME == ``/foo/bar/baz.html'', return
+ ``/foo/bar/baz/baz.html''.
+
+ Split html output goes into the subdirectory of the toplevel
+ filename, without extension. For example:
+
+ @setfilename foo.info
+
+ produces output in files foo/index.html, foo/second-node.html, .... */
+
+static char *
+insert_toplevel_subdirectory (output_filename)
+ char *output_filename;
+{
+ char *dir, *subdir, *base, *basename, *p;
+ char buf[PATH_MAX];
+ int max_name_len;
+ static const char index_name[] = "index.html";
+ const int index_len = sizeof (index_name) - 1;
+
+ strcpy (buf, output_filename);
+ dir = pathname_part (buf);
+ base = filename_part (buf);
+ basename = xstrdup (base); /* remember real @setfilename name */
+ p = dir + strlen (dir) - 1;
+ if (p > dir && IS_SLASH (*p))
+ *p = 0;
+ p = strrchr (base, '.');
+ if (p)
+ *p = 0;
+
+ /* Split html output goes into subdirectory of toplevel name. */
+ subdir = "";
+ if (FILENAME_CMP (base, filename_part (dir)) != 0)
+ subdir = base;
+
+ max_name_len = strlen (basename);
+ if (index_len > max_name_len)
+ max_name_len = index_len;
+
+ free (output_filename);
+ output_filename = xmalloc (strlen (dir) + 1
+ + strlen (subdir) + 1
+ + max_name_len
+ + 1);
+ strcpy (output_filename, dir);
+ if (strlen (dir))
+ strcat (output_filename, "/");
+ strcat (output_filename, subdir);
+ if (mkdir (output_filename, 0777) == -1 && errno != EEXIST)
+ { /* that failed, try subdir name with .html */
+ strcpy (output_filename, dir);
+ if (strlen (dir))
+ strcat (output_filename, "/");
+ strcat (output_filename, basename);
+ if (mkdir (output_filename, 0777) == -1 && errno != EEXIST)
+ {
+ line_error (_("Can't create directory `%s': %s"),
+ output_filename,
+ strerror (errno));
+ exit (1);
+ }
+ strcat (output_filename, "/");
+ }
+ else if (strlen (subdir))
+ strcat (output_filename, "/");
+ strcat (output_filename, index_name);
+ return output_filename;
+}
+
+/* FIXME: this is way too hairy */
void
convert_from_loaded_file (name)
char *name;
@@ -1260,12 +1414,15 @@ convert_from_loaded_file (name)
if (!command_output_filename)
{
get_until ("\n", &output_filename); /* read rest of line */
- if (html)
- { /* Change any extension to .html. */
+ if (xml && !docbook)
+ xml_begin_document (output_filename);
+ if (html || xml)
+ { /* Change any extension to .html or .xml. */
char *html_name, *directory_part, *basename_part, *temp;
canon_white (output_filename);
directory_part = pathname_part (output_filename);
+
basename_part = filename_part (output_filename);
/* Zap any existing extension. */
@@ -1278,7 +1435,7 @@ convert_from_loaded_file (name)
+ strlen (basename_part) + 6);
strcpy (html_name, directory_part);
strcat (html_name, basename_part);
- strcat (html_name, ".html");
+ strcat (html_name, html ? ".html" : ".xml");
/* Replace name from @setfilename with the html name. */
free (output_filename);
@@ -1297,13 +1454,15 @@ convert_from_loaded_file (name)
}
canon_white (output_filename);
+ toplevel_output_filename = xstrdup (output_filename);
if (real_output_filename && strcmp (real_output_filename, "-") == 0)
{
if (macro_expansion_filename
&& strcmp (macro_expansion_filename, "-") == 0)
{
- fprintf (stderr, _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
+ fprintf (stderr,
+ _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
progname);
macro_expansion_output_stream = NULL;
}
@@ -1313,7 +1472,16 @@ convert_from_loaded_file (name)
}
else
{
- if (!real_output_filename)
+ if (html && splitting)
+ {
+ if (FILENAME_CMP (output_filename, NULL_DEVICE) == 0
+ || FILENAME_CMP (output_filename, ALSO_NULL_DEVICE) == 0)
+ splitting = 0;
+ else
+ output_filename = insert_toplevel_subdirectory (output_filename);
+ real_output_filename = xstrdup (output_filename);
+ }
+ else if (!real_output_filename)
real_output_filename = expand_filename (output_filename, name);
else
real_output_filename = xstrdup (real_output_filename);
@@ -1325,7 +1493,10 @@ convert_from_loaded_file (name)
if (verbose_mode)
printf (_("Making %s file `%s' from `%s'.\n"),
- no_headers ? "text" : (html ? "HTML" : "info"),
+ no_headers ? "text"
+ : html ? "HTML"
+ : xml ? "XML"
+ : "info",
output_filename, input_filename);
if (output_stream == NULL)
@@ -1336,6 +1507,7 @@ convert_from_loaded_file (name)
/* Make the displayable filename from output_filename. Only the base
portion of the filename need be displayed. */
+ flush_output (); /* in case there was no @bye */
if (output_stream != stdout)
pretty_output_filename = filename_part (output_filename);
else
@@ -1354,12 +1526,15 @@ convert_from_loaded_file (name)
}
/* html fixxme: should output this as trailer on first page. */
- if (!no_headers && !html)
+ if (!no_headers && !html && !xml)
add_word_args (_("This is %s, produced by makeinfo version %s from %s.\n"),
output_filename, VERSION, input_filename);
close_paragraph ();
reader_loop ();
+ if (xml)
+ xml_end_document ();
+
finished:
discard_insertions (0);
@@ -1398,6 +1573,7 @@ finished:
close_paragraph ();
}
+ flush_output (); /* in case there was no @bye */
if (output_stream != stdout)
fclose (output_stream);
@@ -1410,7 +1586,7 @@ finished:
toc_update ();
if (splitting && !html && (!errors_printed || force))
- split_file (real_output_filename, 0);
+ split_file (real_output_filename, split_size);
else if (errors_printed
&& !force
&& strcmp (real_output_filename, "-") != 0
@@ -1542,6 +1718,10 @@ handle_menu_entry ()
input_text_offset++; /* discard the second colon or the period */
add_word (": ");
}
+ else if (xml && tem)
+ {
+ xml_start_menu_entry (tem);
+ }
else if (tem)
{ /* For Info output, we can just use the input and the main case in
reader_loop where we output what comes in. Just move off the *
@@ -1774,6 +1954,8 @@ reader_loop ()
case '<':
if (html && escape_html)
add_word ("&lt;");
+ else if (xml)
+ xml_insert_entity ("lt");
else
add_char (character);
input_text_offset++;
@@ -1782,6 +1964,8 @@ reader_loop ()
case '>':
if (html && escape_html)
add_word ("&gt;");
+ else if (xml)
+ xml_insert_entity ("gt");
else
add_char (character);
input_text_offset++;
@@ -1799,8 +1983,16 @@ reader_loop ()
we can ignore its partner. */
if (!only_macro_expansion)
{
- line_error (_("Misplaced %c"), '{');
- remember_brace (misplaced_brace);
+ if (!STREQ (command, "math"))
+ {
+ line_error (_("Misplaced %c"), '{');
+ remember_brace (misplaced_brace);
+ }
+ else
+ { /* We don't mind `extra' braces inside @math. */
+ extern void cm_no_op ();
+ remember_brace (cm_no_op);
+ }
/* remember_brace advances input_text_offset. */
break;
}
@@ -1851,7 +2043,7 @@ remember_brace_1 (proc, position)
BRACE_ELEMENT *new = xmalloc (sizeof (BRACE_ELEMENT));
new->next = brace_stack;
new->proc = proc;
- new->command = xstrdup (command);
+ new->command = command ? xstrdup (command) : "";
new->pos = position;
new->line = line_number;
new->in_fixed_width_font = in_fixed_width_font;
@@ -1933,12 +2125,11 @@ discard_braces ()
if (brace_stack->proc != misplaced_brace)
{
char *proc_name;
- int temp_line_number = line_number;
- line_number = brace_stack->line;
proc_name = find_proc_name (brace_stack->proc);
- line_error (_("%c%s missing close brace"), COMMAND_PREFIX, proc_name);
- line_number = temp_line_number;
+ file_line_error (input_filename, brace_stack->line,
+ _("%c%s missing close brace"), COMMAND_PREFIX,
+ proc_name);
pop_and_call_brace ();
}
else
@@ -2018,12 +2209,30 @@ add_word (string)
add_char (*string++);
}
+/* Like add_word, but inhibits conversion of whitespace into &nbsp;.
+ Use this to output HTML directives with embedded blanks, to make
+ them @w-safe. */
+void
+add_html_elt (string)
+ char *string;
+{
+ in_html_elt++;
+ add_word (string);
+ in_html_elt--;
+}
+
/* Add the character to the current paragraph. If filling_enabled is
nonzero, then do filling as well. */
void
add_char (character)
int character;
{
+ if (xml)
+ {
+ xml_add_char (character);
+ return;
+ }
+
/* If we are avoiding outputting headers, and we are currently
in a menu, then simply return. But if we're only expanding macros,
then we're being called from glean_node_from_menu to try to
@@ -2044,9 +2253,11 @@ add_char (character)
}
}
- if (non_splitting_words && strchr (" \t\n", character))
+ if (non_splitting_words
+ && !(html && in_html_elt)
+ && strchr (" \t\n", character))
{
- if (html)
+ if (html || docbook)
{ /* Seems cleaner to use &nbsp; than an 8-bit char. */
add_word ("&nbsp");
character = ';';
@@ -2117,6 +2328,14 @@ add_char (character)
}
}
+ /* This is sad, but it seems desirable to not force any
+ particular order on the front matter commands. This way,
+ the document can do @settitle, @documentlanguage, etc, in
+ any order and with any omissions, and we'll still output
+ the html <head> `just in time'. */
+ if (!executing_string && html && !html_output_head_p)
+ html_output_head ();
+
if (!paragraph_is_open)
{
start_paragraph ();
@@ -2263,13 +2482,6 @@ void
insert (character)
int character;
{
- /* This is sad, but it seems desirable to not force any particular
- order on the front matter commands. This way, the document can do
- @settitle, @documentlanguage, etc, in any order and with any
- omissions, and we'll still output the html <head> `just in time'. */
- if (!executing_string && html && !html_output_head_p)
- html_output_head ();
-
output_paragraph[output_paragraph_offset++] = character;
if (output_paragraph_offset == paragraph_buffer_len)
{
@@ -2701,7 +2913,68 @@ cm_xref (arg)
char *arg5 = get_xref_token (0);
char *tem;
- if (html)
+ /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
+ first argument must never be blank." --rms.
+ We hereby comply by disallowing such constructs. */
+ if (!*arg1)
+ line_error (_("First argument to cross-reference may not be empty"));
+
+ if (xml && docbook)
+ {
+ if (!*arg4 && !*arg5)
+ {
+ char *arg1_id = xml_id (arg1);
+ if (*arg2)
+ {
+ xml_insert_element_with_attribute (XREFNODENAME, START,
+ "linkend=\"%s\"", arg1_id);
+ free (arg1_id);
+ if (*arg2)
+ execute_string (arg2);
+ xml_insert_element (XREFNODENAME, END);
+ }
+ else
+ {
+ xml_insert_element_with_attribute (XREF, START,
+ "linkend=\"%s\"", arg1_id);
+ free (arg1_id);
+ xml_pop_current_element ();
+ }
+ }
+ }
+ else if (xml)
+ {
+ xml_insert_element (XREF, START);
+ xml_insert_element (XREFNODENAME, START);
+ execute_string (arg1);
+ xml_insert_element (XREFNODENAME, END);
+ if (*arg2)
+ {
+ xml_insert_element (XREFINFONAME, START);
+ execute_string (arg2);
+ xml_insert_element (XREFINFONAME, END);
+ }
+ if (*arg3)
+ {
+ xml_insert_element (XREFPRINTEDDESC, START);
+ execute_string (arg3);
+ xml_insert_element (XREFPRINTEDDESC, END);
+ }
+ if (*arg4)
+ {
+ xml_insert_element (XREFINFOFILE, START);
+ execute_string (arg4);
+ xml_insert_element (XREFINFOFILE, END);
+ }
+ if (*arg5)
+ {
+ xml_insert_element (XREFPRINTEDNAME, START);
+ execute_string (arg5);
+ xml_insert_element (XREFPRINTEDNAME, END);
+ }
+ xml_insert_element (XREF, END);
+ }
+ else if (html)
{
if (!ref_flag)
add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
@@ -2709,109 +2982,126 @@ cm_xref (arg)
else
add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
- if (*arg5 || *arg4)
- {
- char *node_name;
-
- if (!*arg2)
- {
- if (*arg3)
- node_name = arg3;
- else
- node_name = arg1;
- }
- else
- node_name = arg2;
-
- if (html)
- {
- /* html fixxme: revisit this; external node name not
- much use to us with numbered nodes. */
- add_word ("<a href=");
- execute_string ("\"%s.html#", arg4);
- /* Do not collapse -- to -, etc., in references. */
- in_fixed_width_font++;
- tem = expansion (node_name, 0);
- in_fixed_width_font--;
- add_escaped_anchor_name (tem);
- free (tem);
- add_word ("\">");
- execute_string ("%s", arg1);
- add_word ("</a>");
- }
- else
- {
- execute_string ("%s:", node_name);
- in_fixed_width_font++;
- execute_string (" (%s)%s%s", arg4, arg1, px_ref_flag ? "." : "");
- in_fixed_width_font--;
- }
-
- /* Free all of the arguments found. */
- if (arg1) free (arg1);
- if (arg2) free (arg2);
- if (arg3) free (arg3);
- if (arg4) free (arg4);
- if (arg5) free (arg5);
- return;
- }
- else
- remember_node_reference (arg1, line_number, followed_reference);
-
- if (*arg3)
- {
- if (html)
- {
- add_word ("<a href=\"");
- in_fixed_width_font++;
- tem = expansion (arg1, 0);
- in_fixed_width_font--;
- add_anchor_name (tem, 1);
- free (tem);
- add_word ("\">");
- execute_string ("%s", *arg2 ? arg2 : arg3);
- add_word ("</a>");
- }
- else
- {
- execute_string ("%s:", *arg2 ? arg2 : arg3);
- in_fixed_width_font++;
- execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
- in_fixed_width_font--;
- }
- }
- else
- {
- if (html)
- {
- add_word ("<a href=\"");
- in_fixed_width_font++;
- tem = expansion (arg1, 0);
- in_fixed_width_font--;
- add_anchor_name (tem, 1);
- free (tem);
- add_word ("\">");
- execute_string ("%s", *arg2 ? arg2 : arg1);
- add_word ("</a>");
- }
- else
- {
- if (*arg2)
- {
- execute_string ("%s:", arg2);
- in_fixed_width_font++;
- execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
- in_fixed_width_font--;
- }
- else
- {
- in_fixed_width_font++;
- execute_string ("%s::", arg1);
- in_fixed_width_font--;
- }
- }
- }
-
+ if (!xml)
+ {
+ if (*arg5 || *arg4)
+ {
+ /* arg1 - node name
+ arg2 - reference name
+ arg3 - title or topic (and reference name if arg2 is NULL)
+ arg4 - info file name
+ arg5 - printed manual title */
+ char *ref_name;
+
+ if (!*arg2)
+ {
+ if (*arg3)
+ ref_name = arg3;
+ else
+ ref_name = arg1;
+ }
+ else
+ ref_name = arg2;
+
+ if (html)
+ {
+ /* html fixxme: revisit this; external node name not
+ much use to us with numbered nodes. */
+ add_html_elt ("<a href=");
+ /* Note that if we are splitting, and the referenced
+ tag is an anchor rather than a node, we will
+ produce a reference to a file whose name is
+ derived from the anchor name. However, only
+ nodes create files, so we are referencing a
+ non-existent file. cm_anchor, which see, deals
+ with that problem. */
+ if (splitting)
+ execute_string ("\"../%s/", arg4);
+ else
+ execute_string ("\"%s.html", arg4);
+ /* Do not collapse -- to -, etc., in references. */
+ in_fixed_width_font++;
+ tem = expansion (arg1, 0); /* expand @-commands in node */
+ in_fixed_width_font--;
+ add_anchor_name (tem, 1);
+ free (tem);
+ add_word ("\">");
+ execute_string ("%s", ref_name);
+ add_word ("</a>");
+ }
+ else
+ {
+ execute_string ("%s:", ref_name);
+ in_fixed_width_font++;
+ execute_string (" (%s)%s%s", arg4, arg1, px_ref_flag ? "." : "");
+ in_fixed_width_font--;
+ }
+
+ /* Free all of the arguments found. */
+ if (arg1) free (arg1);
+ if (arg2) free (arg2);
+ if (arg3) free (arg3);
+ if (arg4) free (arg4);
+ if (arg5) free (arg5);
+ return;
+ }
+ else
+ remember_node_reference (arg1, line_number, followed_reference);
+
+ if (*arg3)
+ {
+ if (html)
+ {
+ add_html_elt ("<a href=\"");
+ in_fixed_width_font++;
+ tem = expansion (arg1, 0);
+ in_fixed_width_font--;
+ add_anchor_name (tem, 1);
+ free (tem);
+ add_word ("\">");
+ execute_string ("%s", *arg2 ? arg2 : arg3);
+ add_word ("</a>");
+ }
+ else
+ {
+ execute_string ("%s:", *arg2 ? arg2 : arg3);
+ in_fixed_width_font++;
+ execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
+ in_fixed_width_font--;
+ }
+ }
+ else
+ {
+ if (html)
+ {
+ add_html_elt ("<a href=\"");
+ in_fixed_width_font++;
+ tem = expansion (arg1, 0);
+ in_fixed_width_font--;
+ add_anchor_name (tem, 1);
+ free (tem);
+ add_word ("\">");
+ execute_string ("%s", *arg2 ? arg2 : arg1);
+ add_word ("</a>");
+ }
+ else
+ {
+ if (*arg2)
+ {
+ execute_string ("%s:", arg2);
+ in_fixed_width_font++;
+ execute_string (" %s%s", arg1, px_ref_flag ? "." : "");
+ in_fixed_width_font--;
+ }
+ else
+ {
+ in_fixed_width_font++;
+ execute_string ("%s::", arg1);
+ in_fixed_width_font--;
+ }
+ }
+ }
+ }
/* Free all of the arguments found. */
if (arg1) free (arg1);
if (arg2) free (arg2);
@@ -2879,15 +3169,45 @@ cm_inforef (arg)
char *pname = get_xref_token (0);
char *file = get_xref_token (0);
- if (html)
+ /* (see comments at cm_xref). */
+ if (!*node)
+ line_error (_("First argument to @inforef may not be empty"));
+
+ if (xml && !docbook)
+ {
+ xml_insert_element (INFOREF, START);
+ xml_insert_element (INFOREFNODENAME, START);
+ execute_string (node);
+ xml_insert_element (INFOREFNODENAME, END);
+ if (*pname)
+ {
+ xml_insert_element (INFOREFREFNAME, START);
+ execute_string (pname);
+ xml_insert_element (INFOREFREFNAME, END);
+ }
+ xml_insert_element (INFOREFINFONAME, START);
+ execute_string (file);
+ xml_insert_element (INFOREFINFONAME, END);
+
+ xml_insert_element (INFOREF, END);
+ }
+ else if (html)
{
+ char *tem;
+
add_word (_("see "));
/* html fixxme: revisit this */
- add_word ("<a href=");
- execute_string ("\"%s.html\"", file);
- add_word (">");
- execute_string ("%s", pname);
+ add_html_elt ("<a href=");
+ if (splitting)
+ execute_string ("\"../%s/", file);
+ else
+ execute_string ("\"%s.html", file);
+ tem = expansion (node, 0);
+ add_anchor_name (tem, 1);
+ add_word ("\">");
+ execute_string ("%s", *pname ? pname : tem);
add_word ("</a>");
+ free (tem);
}
else
{
@@ -2915,9 +3235,29 @@ cm_uref (arg)
char *desc = get_xref_token (0);
char *replacement = get_xref_token (0);
- if (html)
+ if (xml)
+ {
+ xml_insert_element (UREF, START);
+ xml_insert_element (UREFURL, START);
+ execute_string (url);
+ xml_insert_element (UREFURL, END);
+ if (*desc)
+ {
+ xml_insert_element (UREFDESC, START);
+ execute_string (desc);
+ xml_insert_element (UREFDESC, END);
+ }
+ if (*replacement)
+ {
+ xml_insert_element (UREFREPLACEMENT, START);
+ execute_string (replacement);
+ xml_insert_element (UREFREPLACEMENT, END);
+ }
+ xml_insert_element (UREF, END);
+ }
+ else if (html)
{ /* never need to show the url */
- add_word ("<a href=");
+ add_html_elt ("<a href=");
/* don't collapse `--' etc. in the url */
in_fixed_width_font++;
execute_string ("\"%s\"", url);
@@ -2964,9 +3304,30 @@ cm_email (arg)
char *addr = get_xref_token (1); /* expands all macros in email */
char *name = get_xref_token (0);
- if (html)
+ if (xml && docbook)
+ {
+ xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
+ if (*name)
+ execute_string (name);
+ xml_insert_element (EMAIL, END);
+ }
+ else if (xml)
+ {
+ xml_insert_element (EMAIL, START);
+ xml_insert_element (EMAILADDRESS, START);
+ execute_string (addr);
+ xml_insert_element (EMAILADDRESS, END);
+ if (*name)
+ {
+ xml_insert_element (EMAILNAME, START);
+ execute_string (name);
+ xml_insert_element (EMAILNAME, END);
+ }
+ xml_insert_element (EMAIL, END);
+ }
+ else if (html)
{
- add_word ("<a href=");
+ add_html_elt ("<a href=");
/* don't collapse `--' etc. in the address */
in_fixed_width_font++;
execute_string ("\"mailto:%s\"", addr);
@@ -2996,13 +3357,13 @@ void
cm_image (arg)
int arg;
{
- char *name_arg, *rest;
+ char *name_arg, *rest, *alt_arg, *ext_arg;
if (arg == END)
return;
name_arg = get_xref_token (1); /* expands all macros in image */
- /* We don't (yet) care about any other args, but read them so they
+ /* We don't (yet) care about the next two args, but read them so they
don't end up in the text. */
rest = get_xref_token (0);
if (rest)
@@ -3010,26 +3371,54 @@ cm_image (arg)
rest = get_xref_token (0);
if (rest)
free (rest);
+ alt_arg = get_xref_token (1); /* expands all macros in alt text */
+ ext_arg = get_xref_token (0);
if (*name_arg)
{
- char *fullname = xmalloc (strlen (name_arg) + 4 + 1);
+ char *fullname = xmalloc (strlen (name_arg)
+ + (ext_arg && *ext_arg ? strlen (ext_arg) + 1 : 4) + 1);
if (html)
- { /* fixxme It would be nice to insert more useful alt text. */
+ {
+ if (ext_arg && *ext_arg)
+ {
+ sprintf (fullname, "%s.%s", name_arg, ext_arg);
+ if (access (fullname, R_OK) != 0)
+ {
+ line_error(_("@image file `%s' (for HTML) not readable: %s"),
+ fullname, strerror (errno));
+ return;
+ }
+ }
+ else
+ {
sprintf (fullname, "%s.png", name_arg);
if (access (fullname, R_OK) != 0)
{
sprintf (fullname, "%s.jpg", name_arg);
if (access (fullname, R_OK) != 0)
{
- line_error (_("No .png or .jpg for `%s'"), name_arg);
+ line_error (_("No `%s.png' or `.jpg', and no extension supplied"),
+ name_arg);
return;
}
}
+ }
- add_word_args ("<img src=\"%s\" alt=\"%s\">", fullname, fullname);
+ add_html_elt ("<img src=");
+ add_word_args ("\"%s\"", fullname);
+ add_html_elt (" alt=");
+ add_word_args ("\"%s\">", (*alt_arg) ? alt_arg : fullname);
}
+ else if (xml && docbook)
+ xml_insert_docbook_image (name_arg);
+ else if (xml)
+ {
+ xml_insert_element (IMAGE, START);
+ add_word (name_arg);
+ xml_insert_element (IMAGE, END);
+ }
else
{ /* Try to open foo.txt. */
FILE *image_file;
@@ -3060,8 +3449,8 @@ cm_image (arg)
perror (fullname);
}
else
- warning (_("@image file `%s' unreadable: %s"), fullname,
- strerror (errno));
+ line_error (_("@image file `%s' (for text) unreadable: %s"),
+ fullname, strerror (errno));
}
free (fullname);
@@ -3071,6 +3460,10 @@ cm_image (arg)
if (name_arg)
free (name_arg);
+ if (alt_arg)
+ free (alt_arg);
+ if (ext_arg)
+ free (ext_arg);
}
/* Conditionals. */
@@ -3415,13 +3808,9 @@ handle_variable_internal (action, name)
}
if (!done)
- {
- int save = line_number;
- line_number = orig_line_number;
- line_error (_("Reached eof before matching @end %s"),
- condition);
- line_number = save;
- }
+ file_line_error (input_filename, orig_line_number,
+ _("Reached eof before matching @end %s"),
+ condition);
/* We found the end of a false @ifset/ifclear. If we are
in a menu, back up over the newline that ends the ifset,
OpenPOWER on IntegriCloud