summaryrefslogtreecommitdiff
path: root/Build/source/utils/texinfo/makeinfo/makeinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/texinfo/makeinfo/makeinfo.c')
-rw-r--r--Build/source/utils/texinfo/makeinfo/makeinfo.c595
1 files changed, 394 insertions, 201 deletions
diff --git a/Build/source/utils/texinfo/makeinfo/makeinfo.c b/Build/source/utils/texinfo/makeinfo/makeinfo.c
index 22ed4c4fd99..36792c26692 100644
--- a/Build/source/utils/texinfo/makeinfo/makeinfo.c
+++ b/Build/source/utils/texinfo/makeinfo/makeinfo.c
@@ -1,13 +1,14 @@
/* makeinfo -- convert Texinfo source into other formats.
- $Id: makeinfo.c,v 1.74 2004/12/19 17:15:42 karl Exp $
+ $Id: makeinfo.c,v 1.118 2008/03/26 23:57:11 karl Exp $
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,13 +16,13 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
Original author of makeinfo: Brian Fox (bfox@ai.mit.edu). */
#include "system.h"
#include "getopt.h"
+#include "mbswidth.h"
#define COMPILING_MAKEINFO
#include "makeinfo.h"
@@ -71,9 +72,6 @@ char *output_filename = NULL;
char *command_output_filename = NULL;
static char *save_command_output_filename = NULL;
-#define INITIAL_PARAGRAPH_SPACE 5000
-int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
-
/* The amount of indentation to add at the starts of paragraphs.
0 means don't change existing indentation at paragraph starts.
> 0 is amount to indent new paragraphs by.
@@ -143,6 +141,11 @@ static int executing_macro = 0;
/* True when we are inside a <li> block of a menu. */
static int in_menu_item = 0;
+/* The column position of output_paragraph[0]. This is not saved and restored
+ in the multitable code because flush_output () is only called in environment
+ 0. */
+static int output_paragraph_start_column = 0;
+
typedef struct brace_element
{
struct brace_element *next;
@@ -164,6 +167,7 @@ static void init_brace_stack (void);
static void init_internals (void);
static void pop_and_call_brace (void);
static void remember_brace (COMMAND_FUNCTION (*proc));
+static void write_trailer (char *filename, char *trailer);
static int end_of_sentence_p (void);
void maybe_update_execution_strings (char **text, unsigned int new_len);
@@ -350,48 +354,50 @@ Info files suitable for reading online with Emacs or standalone GNU Info.\n"));
printf (_("\
General options:\n\
--error-limit=NUM quit after NUM errors (default %d).\n\
+ --document-language=STR locale to use in translating Texinfo keywords\n\
+ for the output document (default C).\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);
+ max_error_level);
puts ("");
/* xgettext: no-wrap */
puts (_("\
Output format selection (default is to produce Info):\n\
- --docbook output Docbook XML rather than Info.\n\
- --html output HTML rather than Info.\n\
- --xml output Texinfo XML rather than Info.\n\
- --plaintext output plain text rather than Info.\n\
+ --docbook output Docbook XML rather than Info.\n\
+ --html output HTML rather than Info.\n\
+ --xml output Texinfo XML rather than Info.\n\
+ --plaintext output plain text rather than Info.\n\
"));
puts (_("\
General output options:\n\
- -E, --macro-expand FILE output macro-expanded source to FILE.\n\
- ignoring any @setfilename.\n\
- --no-headers suppress node separators, Node: lines, and menus\n\
- from Info output (thus producing plain text)\n\
- or from HTML (thus producing shorter output);\n\
- also, write to standard output by default.\n\
- --no-split suppress splitting of Info or HTML output,\n\
- generate only one output file.\n\
- --number-sections output chapter and sectioning numbers.\n\
- -o, --output=FILE output to FILE (directory if split HTML),\n\
+ -E, --macro-expand=FILE output macro-expanded source to FILE,\n\
+ ignoring any @setfilename.\n\
+ --no-headers suppress node separators, Node: lines, and menus\n\
+ from Info output (thus producing plain text)\n\
+ or from HTML (thus producing shorter output);\n\
+ also, write to standard output by default.\n\
+ --no-split suppress the 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 (or directory if split HTML).\n\
"));
printf (_("\
Options for Info and plain text:\n\
- --enable-encoding output accented and special characters in\n\
- Info output based on @documentencoding.\n\
+ --disable-encoding do not output accented and special characters\n\
+ in Info output based on @documentencoding.\n\
+ --enable-encoding override --disable-encoding (default).\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\
+ `end' to put them at the end of the node, in\n\
+ which they are defined (this is the 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\
@@ -402,14 +408,17 @@ Options for Info and plain text:\n\
puts (_("\
Options for HTML:\n\
- --css-include=FILE include FILE in HTML <style> output;\n\
- read stdin if FILE is -.\n\
+ --css-include=FILE include FILE in HTML <style> output;\n\
+ read stdin if FILE is -.\n\
+ --css-ref=URL generate reference to a CSS file.\n\
+ --transliterate-file-names\n\
+ produce file names in ASCII transliteration.\n\
"));
printf (_("\
Options for XML and Docbook:\n\
- --output-indent=VAL indent XML elements by VAL spaces (default %d).\n\
- If VAL is 0, ignorable whitespace is dropped.\n\
+ --output-indent=VAL indent XML elements by VAL spaces (default %d).\n\
+ If VAL is 0, ignorable whitespace is dropped.\n\
"), xml_indentation_increment);
puts ("");
@@ -451,15 +460,15 @@ Conditional processing in input:\n\
fputs (_("\
Examples:\n\
- makeinfo foo.texi write Info to foo's @setfilename\n\
- makeinfo --html foo.texi write HTML to @setfilename\n\
- makeinfo --xml foo.texi write Texinfo XML to @setfilename\n\
- makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\
- makeinfo --no-headers foo.texi write plain text to standard output\n\
+ makeinfo foo.texi write Info to foo's @setfilename\n\
+ makeinfo --html foo.texi write HTML to @setfilename\n\
+ makeinfo --xml foo.texi write Texinfo XML to @setfilename\n\
+ makeinfo --docbook foo.texi write DocBook XML to @setfilename\n\
+ makeinfo --no-headers foo.texi write plain text to standard output\n\
\n\
- makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
- makeinfo --number-sections foo.texi write Info with numbered sections\n\
- makeinfo --no-split foo.texi write one Info file however big\n\
+ makeinfo --html --no-headers foo.texi write html without node lines, menus\n\
+ makeinfo --number-sections foo.texi write Info with numbered sections\n\
+ makeinfo --no-split foo.texi write one Info file however big\n\
"), stdout);
puts (_("\n\
@@ -472,12 +481,18 @@ Texinfo home page: http://www.gnu.org/software/texinfo/"));
xexit (exit_value);
}
+#define OPT_CSSREF 256
+#define OPT_TRANSLITERATE_FILE_NAMES 257
+
struct option long_options[] =
{
{ "commands-in-node-names", 0, &expensive_validation, 1 },
{ "css-include", 1, 0, 'C' },
+ { "css-ref", 1, 0, OPT_CSSREF },
{ "docbook", 0, 0, 'd' },
+ { "disable-encoding", 0, &enable_encoding, 0 },
{ "enable-encoding", 0, &enable_encoding, 1 },
+ { "document-language", 1, 0, 'l' },
{ "error-limit", 1, 0, 'e' },
{ "fill-column", 1, 0, 'f' },
{ "footnote-style", 1, 0, 's' },
@@ -512,6 +527,7 @@ struct option long_options[] =
{ "plaintext", 0, 0, 't' },
{ "reference-limit", 1, 0, 'r' },
{ "split-size", 1, 0, 'S'},
+ { "transliterate-file-names", 0, &transliterate_file_names, 1 },
{ "verbose", 0, &verbose_mode, 1 },
{ "version", 0, 0, 'V' },
{ "xml", 0, 0, 'x' },
@@ -534,7 +550,7 @@ static COMMAND_LINE_DEFINE *command_line_defines = NULL;
/* For each file mentioned in the command line, process it, turning
Texinfo commands into wonderfully formatted output text. */
int
-main (int argc, char **argv)
+main (int argc, char *argv[])
{
int c, ind;
int reading_from_stdin = 0;
@@ -543,7 +559,7 @@ main (int argc, char **argv)
/* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
of the argument to @multicolumn. */
setlocale (LC_TIME, "");
-#ifdef LC_MESSAGES /* ultrix */
+#ifdef LC_MESSAGES /* ultrix, djgpp 2.04 */
setlocale (LC_MESSAGES, "");
#endif
setlocale (LC_CTYPE, "");
@@ -617,6 +633,10 @@ main (int argc, char **argv)
css_include = xstrdup (optarg);
break;
+ case OPT_CSSREF:
+ css_ref = xstrdup (optarg);
+ break;
+
case 'D':
case 'U':
/* User specified variable to set or clear. */
@@ -685,6 +705,11 @@ main (int argc, char **argv)
append_to_include_path (optarg);
break;
+ case 'l':
+ /* save the override language code */
+ document_language = xstrdup (optarg);
+ break;
+
case 'i':
if (sscanf (optarg, "%d", &xml_indentation_increment) != 1)
{
@@ -715,14 +740,7 @@ main (int argc, char **argv)
prepend_to_include_path (optarg);
break;
- case 'r': /* --reference-limit */
- if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
- {
- fprintf (stderr,
- _("%s: %s arg must be numeric, not `%s'.\n"),
- progname, "--reference-limit", optarg);
- usage (1);
- }
+ case 'r': /* was --reference-limit; obsolete, ignore */
break;
case 's': /* --footnote-style */
@@ -762,10 +780,11 @@ main (int argc, char **argv)
case 'V': /* --version */
print_version_info ();
puts ("");
- puts ("Copyright (C) 2004 Free Software Foundation, Inc.");
- printf (_("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"));
+ printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
+This is free software: you are free to change and redistribute it.\n\
+There is NO WARRANTY, to the extent permitted by law.\n"),
+ "2008");
xexit (0);
break;
@@ -1348,14 +1367,13 @@ convert_from_file (char *name)
int i;
char *filename = xmalloc (strlen (name) + 50);
- /* Prepend file directory to the search path, so relative links work. */
+ /* Prepend NAME's directory to the search path, so relative links work. */
prepend_to_include_path (pathname_part (name));
initialize_conversion ();
/* Try to load the file specified by NAME, concatenated with our
- various suffixes. Prefer files like `makeinfo.texi' to
- `makeinfo'. */
+ various suffixes. Prefer files like `makeinfo.texi' to `makeinfo'. */
for (i = 0; suffixes[i]; i++)
{
strcpy (filename, name);
@@ -1363,13 +1381,6 @@ convert_from_file (char *name)
if (find_and_load (filename, 1))
break;
-
- if (!suffixes[i][0] && strrchr (filename, '.'))
- {
- fs_error (filename);
- free (filename);
- return;
- }
}
if (!suffixes[i])
@@ -1379,8 +1390,14 @@ convert_from_file (char *name)
return;
}
+ /* `find_and_load' (when successful) clobbers this global with new
+ memory. We're about to reset it, so may as well free first. */
+ free (input_filename);
+
+ /* Set the current filename. */
input_filename = filename;
+ /* Do the main conversion. */
convert_from_loaded_file (name);
/* Pop the prepended path, so multiple filenames in the
@@ -1630,10 +1647,7 @@ convert_from_loaded_file (char *name)
}
set_current_output_filename (real_output_filename);
-
- if (xml && !docbook)
- xml_begin_document (filename_part (output_filename));
-
+
if (verbose_mode)
printf (_("Making %s file `%s' from `%s'.\n"),
no_headers ? "text"
@@ -1648,6 +1662,9 @@ convert_from_loaded_file (char *name)
goto finished;
}
+ if (xml)
+ xml_begin_document (filename_part (output_filename));
+
/* 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 */
@@ -1668,13 +1685,6 @@ convert_from_loaded_file (char *name)
line_number++;
}
- /* html fixxme: should output this as trailer on first page. */
- 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 ();
-
if (xml && !docbook)
{
/* Just before the real main loop, let's handle the defines. */
@@ -1725,25 +1735,12 @@ _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n
close_paragraph ();
}
- /* maybe we want local variables in info output. */
- {
- char *trailer = info_trailer ();
- if (!xml && !docbook && trailer)
- {
- if (html)
- insert_string ("<!--");
- insert_string (trailer);
- free (trailer);
- if (html)
- insert_string ("\n-->\n");
- }
- }
-
/* Write stuff makeinfo generates after @bye, ie. info_trailer. */
flush_output ();
if (output_stream != stdout)
- fclose (output_stream);
+ if (fclose (output_stream) != 0)
+ fs_error (real_output_filename);
/* If validating, then validate the entire file right now. */
if (validating)
@@ -1758,6 +1755,10 @@ _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n
write_tag_table (real_output_filename);
}
+ /* Maybe we want local variables in info output. Must be after
+ tag table, since otherwise usually Emacs will not see it. */
+ write_trailer (real_output_filename, info_trailer ());
+
if (splitting && !html && (!errors_printed || force))
{
clean_old_split_files (real_output_filename);
@@ -1804,6 +1805,37 @@ info_trailer (void)
free (encoding);
return NULL;
}
+
+/* Append TRAILER to FILENAME for Info and HTML output. Include HTML
+ comments if needed. */
+static void
+write_trailer (char *filename, char *trailer)
+{
+ if (!trailer || xml || docbook)
+ return;
+
+ if (output_stream != stdout)
+ output_stream = fopen (filename, "a");
+ if (!output_stream)
+ {
+ fs_error (filename);
+ return;
+ }
+
+ if (html)
+ fwrite ("<!--", 1, 4, output_stream);
+
+ fwrite (trailer, 1, strlen (trailer), output_stream);
+ free (trailer);
+
+ if (html)
+ fwrite ("\n-->\n", 1, 5, output_stream);
+
+ if (output_stream != stdout)
+ if (fclose (output_stream) != 0)
+ fs_error (filename);
+}
+
void
free_and_clear (char **pointer)
@@ -1839,11 +1871,12 @@ init_internals (void)
void
init_paragraph (void)
{
- free (output_paragraph);
+ if (output_paragraph)
+ free (output_paragraph);
output_paragraph = xmalloc (paragraph_buffer_len);
output_paragraph[0] = 0;
output_paragraph_offset = 0;
- output_column = 0;
+ output_paragraph_start_column = 0;
paragraph_is_open = 0;
current_indent = 0;
meta_char_pos = 0;
@@ -1973,7 +2006,8 @@ get_command_entry (char *string)
/* We never heard of this command. */
return (COMMAND *) -1;
}
-
+
+
/* input_text_offset is right at the command prefix character.
Read the next token to determine what to do. Return zero
if there's no known command or macro after the prefix character. */
@@ -2202,6 +2236,7 @@ reader_loop (void)
menu swallows its newline, so check here instead. */
if (!only_macro_expansion && in_menu
&& input_text_offset + 1 < input_text_length
+ && input_text_offset > 0
&& input_text[input_text_offset-1] == '\n')
handle_menu_entry ();
else
@@ -2407,37 +2442,63 @@ discard_braces (void)
}
}
-static int
-get_char_len (int character)
+/* Return the 0-based number of the current output column */
+int
+current_output_column (void)
{
- /* Return the printed length of the character. */
- int len;
+ int i, column;
- switch (character)
+ for (i = output_paragraph_offset; i > 0 && output_paragraph[i - 1] != '\n';
+ i--)
+ ;
+ if (i == 0)
+ column = output_paragraph_start_column;
+ else
+ column = 0;
+ while (i < output_paragraph_offset)
{
- case '\t':
- len = (output_column + 8) & 0xf7;
- if (len > fill_column)
- len = fill_column - output_column;
- else
- len = len - output_column;
- break;
-
- case '\n':
- len = fill_column - output_column;
- break;
-
- default:
- /* ASCII control characters appear as two characters in the output
- (e.g., ^A). But characters with the high bit set are just one
- on suitable terminals, so don't count them as two for line
- breaking purposes. */
- if (0 <= character && character < ' ')
- len = 2;
- else
- len = 1;
+ int j;
+
+ /* Find a span of non-control characters */
+ for (j = i; j < output_paragraph_offset; j++)
+ {
+ char c;
+
+ c = output_paragraph[j];
+ if ((0 <= c && c < ' ') || c == '\t' || c == NON_BREAKING_SPACE)
+ break;
+ }
+ if (i < j)
+ {
+ column += mbsnwidth ((char *)(output_paragraph + i), j - i, 0);
+ i = j;
+ }
+ if (i < output_paragraph_offset)
+ {
+ char c;
+
+ /* Handle a control character */
+ c = output_paragraph[i];
+ if (c == '\t')
+ {
+ column = (column + 8) & ~0x7;
+ if (column > fill_column)
+ column = fill_column;
+ }
+ else if (c == NON_BREAKING_SPACE)
+ column++;
+ else
+ {
+ /* ASCII control characters appear as two characters in the
+ output (e.g., ^A). */
+ if (!(0 <= c && c < ' '))
+ abort ();
+ column += 2;
+ }
+ i++;
+ }
}
- return len;
+ return column;
}
void
@@ -2539,7 +2600,42 @@ defining_copying (void)
return 0;
}
+/* Output the header for Info.
+ html fixxme: should output this as trailer on first page (at least). */
+
+static void
+info_output_head (void)
+{
+ add_word_args (gdt("This is %s, produced by makeinfo version %s from %s.\n"),
+ output_filename, VERSION, input_filename);
+
+ /* Start afresh with whatever real text we have. */
+ close_paragraph ();
+ /* We do not want indentation in what follows, which is usually going
+ to be a node marker (CTRL-_). */
+ if (inhibit_paragraph_indentation == 0)
+ inhibit_paragraph_indentation = -1;
+}
+
+void
+output_head (void)
+{
+ if (output_head_p) /* no-op if we're mistakenly called twice */
+ return;
+ output_head_p = 1;
+
+ if (html)
+ html_output_head ();
+ else if (xml)
+ ; /* handled differently, via xml_begin_document */
+ else if (no_headers)
+ ; /* no header for plain text */
+ else
+ info_output_head ();
+}
+
+
/* Add the character to the current paragraph. If filling_enabled is
nonzero, then do filling as well. */
void
@@ -2562,13 +2658,13 @@ add_char (int character)
ignore close_paragraph () calls any more. */
if (must_start_paragraph && character != '\n')
{
+ int column;
+
must_start_paragraph = 0;
line_already_broken = 0; /* The line is no longer broken. */
- if (current_indent > output_column)
- {
- indent (current_indent - output_column);
- output_column = current_indent;
- }
+ column = current_output_column ();
+ if (current_indent > column)
+ indent (current_indent - column);
}
if (non_splitting_words
@@ -2584,7 +2680,7 @@ add_char (int character)
character = ';';
}
else
- character = META (' '); /* unmeta-d in flush_output */
+ character = NON_BREAKING_SPACE; /* restored in flush_output */
}
insertion_paragraph_closed = 0;
@@ -2603,17 +2699,16 @@ add_char (int character)
flush_output ();
}
- output_column = 0;
-
if (!no_indent && paragraph_is_open)
- indent (output_column = current_indent);
+ indent (current_indent);
break;
}
- else if (end_of_sentence_p ())
- /* CHARACTER is newline, and filling is enabled. */
+ else if (end_of_sentence_p () && !french_spacing)
+ /* CHARACTER is newline, filling is enabled, and we're at the
+ end of a sentence. Insert an extra space, unless
+ @frenchspacing is in effect. */
{
insert (' ');
- output_column++;
last_inserted_character = character;
}
@@ -2631,13 +2726,12 @@ add_char (int character)
insert ('\n');
else
insert (' ');
- output_column++;
}
break;
default: /* not at newline */
{
- int len = get_char_len (character);
+ int column;
int suppress_insert = 0;
if ((character == ' ') && (last_char_was_newline))
@@ -2649,15 +2743,19 @@ add_char (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'. */
+ /* This is a sad place to do this, but it seems highly 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 header ("produced by makeinfo",
+ HTML <head>, etc.) `just in time'. */
if ((executing_macro || !executing_string)
&& !only_macro_expansion
- && html && !html_output_head_p && !defining_copying ())
- html_output_head ();
+ && !defining_copying ()
+ && !output_head_p)
+ {
+ output_head ();
+ }
if (!paragraph_is_open)
{
@@ -2685,8 +2783,11 @@ add_char (int character)
}
}
- output_column += len;
- if (output_column > fill_column)
+ output_paragraph[output_paragraph_offset] = character;
+ output_paragraph_offset++;
+ column = current_output_column ();
+ output_paragraph_offset--;
+ if (column > fill_column)
{
if (filling_enabled && !html)
{
@@ -2773,11 +2874,6 @@ add_char (int character)
output_paragraph_offset += current_indent;
free (temp_buffer);
}
- output_column = 0;
- while (temp < output_paragraph_offset)
- output_column +=
- get_char_len (output_paragraph[temp++]);
- output_column += len;
break;
}
}
@@ -2870,7 +2966,6 @@ kill_self_indent (int count)
/* Handle infinite case first. */
if (count < 0)
{
- output_column = 0;
while (output_paragraph_offset)
{
if (whitespace (output_paragraph[output_paragraph_offset - 1]))
@@ -2922,22 +3017,17 @@ flush_output (void)
node_line_number++;
}
- /* If we turned on the 8th bit for a space inside @w, turn it
- back off for output. This might be problematic, since the
- 0x80 character may be used in 8-bit character sets. Sigh.
- In any case, don't do this for HTML, since the nbsp character
- is valid input and must be passed along to the browser. */
- if (!html && (output_paragraph[i] & meta_character_bit))
- {
- int temp = UNMETA (output_paragraph[i]);
- if (temp == ' ')
- output_paragraph[i] &= 0x7f;
- }
+ /* If we turned on the 8th bit for a space inside @w, turn it back off
+ for output. Don't do this for HTML, since the nbsp character is valid
+ input and must be passed along to the browser. */
+ if (!html && output_paragraph[i] == NON_BREAKING_SPACE)
+ output_paragraph[i] = ' ';
}
fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
output_position += output_paragraph_offset;
+ output_paragraph_start_column = current_output_column ();
output_paragraph_offset = 0;
meta_char_pos = 0;
}
@@ -2988,6 +3078,8 @@ close_insertion_paragraph (void)
}
else
{
+ int column;
+
/* If the insertion paragraph is closed already, then we are seeing
two `@end' commands in a row. Note that the first one we saw was
handled in the first part of this if-then-else clause, and at that
@@ -2995,8 +3087,9 @@ close_insertion_paragraph (void)
indentation of the current line. However, the indentation level
may have just changed again, so we may have to outdent the current
line to the new indentation level. */
- if (current_indent < output_column)
- kill_self_indent (output_column - current_indent);
+ column = current_output_column ();
+ if (current_indent < column)
+ kill_self_indent (column - current_indent);
}
insertion_paragraph_closed = 1;
@@ -3009,7 +3102,7 @@ close_paragraph (void)
int i;
/* We don't need these newlines in XML and Docbook outputs for
- paragraph seperation. We have <para> element for that. */
+ paragraph separation. We have the <para> element for that. */
if (xml)
return;
@@ -3062,7 +3155,6 @@ close_paragraph (void)
flush_output ();
paragraph_is_open = 0;
no_indent = 0;
- output_column = 0;
}
ignore_blank_line ();
@@ -3076,38 +3168,40 @@ ignore_blank_line (void)
last_char_was_newline = 1;
}
-/* Align the end of the text in output_paragraph with fill_column. */
+/* Align the end of the text in output_paragraph with fill_column. The last
+ character in output_paragraph is '\n'. */
static void
do_flush_right_indentation (void)
{
char *temp;
- int temp_len;
kill_self_indent (-1);
if (output_paragraph[0] != '\n')
{
- output_paragraph[output_paragraph_offset] = 0;
+ int width;
- if (output_paragraph_offset < fill_column)
+ width = mbsnwidth ((char *)output_paragraph, output_paragraph_offset - 1,
+ 0) + 1;
+ if (width < fill_column)
{
int i;
- if (fill_column >= paragraph_buffer_len)
+ if (output_paragraph_offset + (fill_column - width)
+ >= paragraph_buffer_len)
output_paragraph =
xrealloc (output_paragraph,
(paragraph_buffer_len += fill_column));
- temp_len = strlen ((char *)output_paragraph);
- temp = xmalloc (temp_len + 1);
- memcpy (temp, (char *)output_paragraph, temp_len);
+ temp = xmalloc (output_paragraph_offset);
+ memcpy (temp, (char *)output_paragraph, output_paragraph_offset);
- for (i = 0; i < fill_column - output_paragraph_offset; i++)
+ for (i = 0; i < fill_column - width; i++)
output_paragraph[i] = ' ';
- memcpy ((char *)output_paragraph + i, temp, temp_len);
+ memcpy ((char *)output_paragraph + i, temp, output_paragraph_offset);
free (temp);
- output_paragraph_offset = fill_column;
+ output_paragraph_offset += i;
adjust_braces_following (0, i);
}
}
@@ -3137,6 +3231,8 @@ start_paragraph (void)
/* If doing indentation, then insert the appropriate amount. */
if (!no_indent)
{
+ int column;
+
if (inhibit_paragraph_indentation)
{
amount_to_indent = current_indent;
@@ -3148,12 +3244,9 @@ start_paragraph (void)
else
amount_to_indent = current_indent + paragraph_start_indent;
- if (amount_to_indent >= output_column)
- {
- amount_to_indent -= output_column;
- indent (amount_to_indent);
- output_column += amount_to_indent;
- }
+ column = current_output_column ();
+ if (amount_to_indent >= column)
+ indent (amount_to_indent - column);
}
}
else
@@ -3173,9 +3266,9 @@ indent (int amount)
}
/* Search forward for STRING in input_text.
- FROM says where where to start. */
+ FROM says where to start. */
int
-search_forward (char *string, int from)
+search_forward (const char *string, int from)
{
int len = strlen (string);
@@ -3240,6 +3333,32 @@ next_nonwhitespace_character (void)
return -1;
}
+
+
+
+/* Replace " with \" and \ with \\. Used for alt tag in Info output.
+ Return a newly-malloced string in all cases. */
+
+static char *
+bs_escape_quote (const char *src)
+{
+ int c;
+ char *dest = xmalloc (2 * strlen (src) + 1); /* can't need more. */
+ char *p = dest;
+
+ for (; c = *src; src++)
+ {
+ if (c == '"' || c == '\\')
+ *p++ = '\\';
+
+ *p++ = c;
+ }
+ *p = 0;
+
+ return dest;
+}
+
+
/* An external image is a reference, kind of. The parsing is (not
coincidentally) similar, anyway. */
@@ -3261,8 +3380,8 @@ cm_image (int arg)
{
struct stat file_info;
char *pathname = NULL;
- char *fullname = xmalloc (strlen (name_arg)
- + (ext_arg && *ext_arg ? strlen (ext_arg) + 1: 4) + 1);
+ unsigned ext_len = (ext_arg && *ext_arg) ? strlen (ext_arg) : 0;
+ char *fullname = xmalloc (strlen (name_arg) + MAX (ext_len, 4) + 1);
if (ext_arg && *ext_arg)
{
@@ -3290,10 +3409,16 @@ cm_image (int arg)
if (pathname == NULL) {
sprintf (fullname, "%s.jpg", name_arg);
if (access (fullname, R_OK) != 0) {
- sprintf (fullname, "%s.gif", name_arg);
- if (access (fullname, R_OK) != 0) {
- pathname = get_file_info_in_path (fullname,
- include_files_path, &file_info);
+ pathname = get_file_info_in_path (fullname,
+ include_files_path,
+ &file_info);
+ if (pathname == NULL) {
+ sprintf (fullname, "%s.gif", name_arg);
+ if (access (fullname, R_OK) != 0) {
+ pathname = get_file_info_in_path (fullname,
+ include_files_path,
+ &file_info);
+ }
}
}
}
@@ -3355,12 +3480,10 @@ cm_image (int arg)
xml_no_para--;
}
else
- { /* Try to open foo.EXT or foo.txt. */
+ { /* Prefer foo.txt for Info/ASCII. Seems wrong nowadays. */
FILE *image_file;
char *txtpath = NULL;
- char *txtname = xmalloc (strlen (name_arg)
- + (ext_arg && *ext_arg
- ? strlen (ext_arg) : 4) + 1);
+ char *txtname = xmalloc (strlen (name_arg) + 4 + 1);
strcpy (txtname, name_arg);
strcat (txtname, ".txt");
image_file = fopen (txtname, "r");
@@ -3402,7 +3525,13 @@ cm_image (int arg)
add_word_args (" src=\"%s\"", fullname);
if (*alt_arg)
- add_word_args (" alt=\"%s\"", alt_arg);
+ {
+ char *expanded = text_expansion (alt_arg);
+ char *escaped = bs_escape_quote (expanded);
+ add_word_args (" alt=\"%s\"", escaped);
+ free (expanded);
+ free (escaped);
+ }
}
if (image_file != NULL)
@@ -3591,13 +3720,13 @@ cm_ifeq (void)
{
char **arglist;
- arglist = get_brace_args (0);
+ arglist = get_brace_args (quote_none);
if (arglist)
{
if (array_len (arglist) > 1)
{
- if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
+ if ((mbscasecmp (arglist[0], arglist[1]) == 0) &&
(arglist[2]))
execute_string ("%s\n", arglist[2]);
}
@@ -3642,7 +3771,6 @@ cm_value (int arg, int start_pos, int end_pos)
output_paragraph[end_pos] = 0;
name = xstrdup (name);
value = set_p (name);
- output_column -= end_pos - start_pos;
output_paragraph_offset = start_pos;
/* Restore the previous value of meta_char_pos if the stuff
@@ -4036,6 +4164,7 @@ maybe_escaped_expansion (char *str, int implicit_code, int do_html_escape)
indented_fill = 0;
no_indent = 1;
escape_html = do_html_escape;
+ xml_no_para++;
result = full_expansion (str, implicit_code);
@@ -4043,6 +4172,7 @@ maybe_escaped_expansion (char *str, int implicit_code, int do_html_escape)
indented_fill = saved_indented_fill;
no_indent = saved_no_indent;
escape_html = saved_escape_html;
+ xml_no_para--;
return result;
}
@@ -4061,7 +4191,6 @@ full_expansion (char *str, int implicit_code)
/* Inhibit any real output. */
int start = output_paragraph_offset;
int saved_paragraph_is_open = paragraph_is_open;
- int saved_output_column = output_column;
/* More output state to save. */
int saved_meta_pos = meta_char_pos;
@@ -4096,7 +4225,6 @@ full_expansion (char *str, int implicit_code)
output_paragraph_offset = start;
paragraph_is_open = saved_paragraph_is_open;
- output_column = saved_output_column;
meta_char_pos = saved_meta_pos;
last_inserted_character = saved_last_char;
@@ -4155,3 +4283,68 @@ set_paragraph_indent (char *string)
}
return 0;
}
+
+
+/* Translate MSGID according to the document language (@documentlanguage
+ value or --document-language), rather than the current locale
+ (LANGUAGE/LC_ALL/LANG). This code is from the get_title function in
+ gettext. (xsetenv and unsetenv come from the gnulib xsetenv module.) */
+
+char *
+getdocumenttext (const char *msgid)
+{
+ /* The original get_title also saves, sets, and restores
+ OUTPUT_CHARSET, so that the translation will be given in
+ the proper encoding (via canonical_locale_charset). But defining
+ that function ends up pulling a whole lot of subsidiary functions.
+ Not sure how to handle it; skip the whole thing for now. */
+ const char *tmp;
+ char *old_LC_ALL;
+ char *old_LANGUAGE;
+ const char *result;
+#ifdef HAVE_SETLOCALE
+ char *old_locale;
+#endif
+
+ /* Save LC_ALL, LANGUAGE environment variables. */
+
+ tmp = getenv ("LC_ALL");
+ old_LC_ALL = (tmp != NULL ? xstrdup (tmp) : NULL);
+
+ tmp = getenv ("LANGUAGE");
+ old_LANGUAGE = (tmp != NULL ? xstrdup (tmp) : NULL);
+
+ xsetenv ("LC_ALL", document_language, 1);
+ unsetenv ("LANGUAGE");
+
+#ifdef HAVE_SETLOCALE
+ old_locale = xstrdup (setlocale (LC_ALL, NULL));
+ if (setlocale (LC_ALL, "") == NULL)
+ /* Nonexistent locale. Use the original. */
+ result = msgid;
+ else
+#endif
+ {
+ /* Fetch the translation. */
+ result = gettext ((char *) msgid);
+ }
+
+ /* Restore LC_ALL, LANGUAGE environment variables. */
+
+ if (old_LC_ALL != NULL)
+ xsetenv ("LC_ALL", old_LC_ALL, 1), free (old_LC_ALL);
+ else
+ unsetenv ("LC_ALL");
+
+ if (old_LANGUAGE != NULL)
+ xsetenv ("LANGUAGE", old_LANGUAGE, 1), free (old_LANGUAGE);
+ else
+ unsetenv ("LANGUAGE");
+
+#ifdef HAVE_SETLOCALE
+ setlocale (LC_ALL, old_locale);
+ free (old_locale);
+#endif
+
+ return (char *) result;
+}