Merge texinfo 4.8 changes onto the trunk.

This commit is contained in:
Ruslan Ermilov 2005-05-23 10:50:48 +00:00
parent cea538d9c7
commit 13b21befd2

View File

@ -1,8 +1,8 @@
/* $FreeBSD$ */
/* install-info -- create Info directory entry(ies) for an Info file.
$Id: install-info.c,v 1.9 2003/05/19 13:10:59 karl Exp $
$Id: install-info.c,v 1.12 2004/04/11 17:56:47 karl Exp $
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@ -25,11 +25,14 @@
static char *progname = "install-info";
static char *default_section = NULL;
struct line_data *findlines ();
void insert_entry_here ();
int compare_section_names (), compare_entries_text ();
struct spec_entry;
struct spec_section;
struct line_data *findlines (char *data, int size, int *nlinesp);
void insert_entry_here (struct spec_entry *entry, int line_number,
struct line_data *dir_lines, int n_entries);
int compare_section_names (const void *s1, const void *s2);
int compare_entries_text (const void *e1, const void *e2);
/* Data structures. */
@ -141,8 +144,7 @@ struct option longopts[] =
/* VARARGS1 */
void
error (s1, s2, s3)
char *s1, *s2, *s3;
error (const char *s1, const char *s2, const char *s3)
{
fprintf (stderr, "%s: ", progname);
fprintf (stderr, s1, s2, s3);
@ -151,8 +153,7 @@ error (s1, s2, s3)
/* VARARGS1 */
void
warning (s1, s2, s3)
char *s1, *s2, *s3;
warning (const char *s1, const char *s2, const char *s3)
{
fprintf (stderr, _("%s: warning: "), progname);
fprintf (stderr, s1, s2, s3);
@ -162,8 +163,7 @@ warning (s1, s2, s3)
/* Print error message and exit. */
void
fatal (s1, s2, s3)
char *s1, *s2, *s3;
fatal (const char *s1, const char *s2, const char *s3)
{
error (s1, s2, s3);
xexit (1);
@ -172,8 +172,7 @@ fatal (s1, s2, s3)
/* Return a newly-allocated string
whose contents concatenate those of S1, S2, S3. */
char *
concat (s1, s2, s3)
char *s1, *s2, *s3;
concat (const char *s1, const char *s2, const char *s3)
{
int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
@ -190,9 +189,7 @@ concat (s1, s2, s3)
copied from starting at STRING. */
char *
copy_string (string, size)
char *string;
int size;
copy_string (const char *string, int size)
{
int i;
char *copy = (char *) xmalloc (size + 1);
@ -205,19 +202,71 @@ copy_string (string, size)
/* Print fatal error message based on errno, with file name NAME. */
void
pfatal_with_name (name)
char *name;
pfatal_with_name (const char *name)
{
char *s = concat ("", strerror (errno), _(" for %s"));
fatal (s, name, 0);
}
/* Compare the menu item names in LINE1 (line length LEN1)
and LINE2 (line length LEN2). Return 1 if the item name
in LINE1 is less, 0 otherwise. */
static int
menu_line_lessp (char *line1, int len1, char *line2, int len2)
{
int minlen = (len1 < len2 ? len1 : len2);
int i;
for (i = 0; i < minlen; i++)
{
/* If one item name is a prefix of the other,
the former one is less. */
if (line1[i] == ':' && line2[i] != ':')
return 1;
if (line2[i] == ':' && line1[i] != ':')
return 0;
/* If they both continue and differ, one is less. */
if (line1[i] < line2[i])
return 1;
if (line1[i] > line2[i])
return 0;
}
/* With a properly formatted dir file,
we can only get here if the item names are equal. */
return 0;
}
/* Compare the menu item names in LINE1 (line length LEN1)
and LINE2 (line length LEN2). Return 1 if the item names are equal,
0 otherwise. */
static int
menu_line_equal (char *line1, int len1, char *line2, int len2)
{
int minlen = (len1 < len2 ? len1 : len2);
int i;
for (i = 0; i < minlen; i++)
{
/* If both item names end here, they are equal. */
if (line1[i] == ':' && line2[i] == ':')
return 1;
/* If they both continue and differ, one is less. */
if (line1[i] != line2[i])
return 0;
}
/* With a properly formatted dir file,
we can only get here if the item names are equal. */
return 1;
}
/* Given the full text of a menu entry, null terminated,
return just the menu item name (copied). */
char *
extract_menu_item_name (item_text)
char *item_text;
extract_menu_item_name (char *item_text)
{
char *p;
@ -235,8 +284,7 @@ extract_menu_item_name (item_text)
return just the menu item file (copied). */
char *
extract_menu_file_name (item_text)
char *item_text;
extract_menu_file_name (char *item_text)
{
char *p = item_text;
@ -279,8 +327,7 @@ extract_menu_file_name (item_text)
/* Return FNAME with any [.info][.gz] suffix removed. */
static char *
strip_info_suffix (fname)
char *fname;
strip_info_suffix (char *fname)
{
char *ret = xstrdup (fname);
unsigned len = strlen (ret);
@ -324,14 +371,32 @@ strip_info_suffix (fname)
TERM_CHAR) and still match. */
static int
menu_item_equal (item, term_char, name)
char *item;
char term_char;
char *name;
menu_item_equal (const char *item, char term_char, const char *name)
{
int ret;
const char *item_basename = item;
unsigned name_len = strlen (name);
/* We must compare the basename in ITEM, since we are passed the
basename of the original info file. Otherwise, a new entry like
"lilypond/lilypond" won't match "lilypond".
Actually, it seems to me that we should really compare the whole
name, and not just the basename. Couldn't there be dir1/foo.info
and dir2/foo.info? Also, it seems like we should be using the
filename from the new dir entries, not the filename on the command
line. Not worrying about those things right now, though. --karl,
26mar04. */
while (*item_basename && !IS_SLASH (*item_basename)
&& *item_basename != term_char)
item_basename++;
if (! *item_basename || *item_basename == term_char)
item_basename = item; /* no /, use original */
else
item_basename++; /* have /, move past it */
/* First, ITEM must actually match NAME (usually it won't). */
int ret = strncasecmp (item, name, name_len) == 0;
ret = strncasecmp (item_basename, name, name_len) == 0;
if (ret)
{
/* Then, `foobar' doesn't match `foo', so be sure we've got all of
@ -349,8 +414,8 @@ menu_item_equal (item, term_char, name)
{
char *suffix = suffixes[i];
unsigned suffix_len = strlen (suffix);
ret = strncasecmp (item + name_len, suffix, suffix_len) == 0
&& item[name_len + suffix_len] == term_char;
ret = strncasecmp (item_basename + name_len, suffix, suffix_len) == 0
&& item_basename[name_len + suffix_len] == term_char;
}
}
@ -360,7 +425,7 @@ menu_item_equal (item, term_char, name)
void
suggest_asking_for_help ()
suggest_asking_for_help (void)
{
fprintf (stderr, _("\tTry `%s --help' for a complete list of options.\n"),
progname);
@ -368,7 +433,7 @@ suggest_asking_for_help ()
}
void
print_help ()
print_help (void)
{
printf (_("Usage: %s [OPTION]... [INFO-FILE [DIR-FILE]]\n\
\n\
@ -417,8 +482,7 @@ Texinfo home page: http://www.gnu.org/software/texinfo/"));
already exists, do nothing. */
void
ensure_dirfile_exists (dirfile)
char *dirfile;
ensure_dirfile_exists (char *dirfile)
{
int desc = open (dirfile, O_RDONLY);
if (desc < 0 && errno == ENOENT)
@ -432,7 +496,7 @@ ensure_dirfile_exists (dirfile)
fprintf (f, _("This is the file .../info/dir, which contains the\n\
topmost node of the Info hierarchy, called (dir)Top.\n\
The first time you invoke Info you start off looking at this node.\n\
\n\
\x1f\n\
%s\tThis is the top of the INFO tree\n\
\n\
This (the Directory node) gives a menu of major topics.\n\
@ -474,13 +538,9 @@ The first time you invoke Info you start off looking at this node.\n\
magic number, not the filename. */
FILE *
open_possibly_compressed_file (filename, create_callback,
opened_filename, compression_program, is_pipe)
char *filename;
void (*create_callback) ();
char **opened_filename;
char **compression_program;
int *is_pipe;
open_possibly_compressed_file (char *filename,
void (*create_callback) (char *),
char **opened_filename, char **compression_program, int *is_pipe)
{
char *local_opened_filename, *local_compression_program;
int nread;
@ -610,13 +670,9 @@ open_possibly_compressed_file (filename, create_callback,
a fatal error. */
char *
readfile (filename, sizep, create_callback,
opened_filename, compression_program)
char *filename;
int *sizep;
void (*create_callback) ();
char **opened_filename;
char **compression_program;
readfile (char *filename, int *sizep,
void (*create_callback) (char *), char **opened_filename,
char **compression_program)
{
char *real_name;
FILE *f;
@ -667,16 +723,9 @@ readfile (filename, sizep, create_callback,
we'll write dir.gz on output. */
static void
output_dirfile (dirfile, dir_nlines, dir_lines,
n_entries_to_add, entries_to_add, input_sections,
compression_program)
char *dirfile;
int dir_nlines;
struct line_data *dir_lines;
int n_entries_to_add;
struct spec_entry *entries_to_add;
struct spec_section *input_sections;
char *compression_program;
output_dirfile (char *dirfile, int dir_nlines, struct line_data *dir_lines,
int n_entries_to_add, struct spec_entry *entries_to_add,
struct spec_section *input_sections, char *compression_program)
{
int i;
FILE *output;
@ -805,11 +854,8 @@ output_dirfile (dirfile, dir_nlines, dir_lines,
/* Parse the input to find the section names and the entry names it
specifies. Return the number of entries to add from this file. */
int
parse_input (lines, nlines, sections, entries)
const struct line_data *lines;
int nlines;
struct spec_section **sections;
struct spec_entry **entries;
parse_input (const struct line_data *lines, int nlines,
struct spec_section **sections, struct spec_entry **entries)
{
int n_entries = 0;
int prefix_length = strlen ("INFO-DIR-SECTION ");
@ -936,11 +982,8 @@ parse_input (lines, nlines, sections, entries)
/* Parse the dir file whose basename is BASE_NAME. Find all the
nodes, and their menus, and the sections of their menus. */
int
parse_dir_file (lines, nlines, nodes, base_name)
struct line_data *lines;
int nlines;
struct node **nodes;
const char *base_name;
parse_dir_file (struct line_data *lines, int nlines, struct node **nodes,
const char *base_name)
{
int node_header_flag = 0;
int something_deleted = 0;
@ -1090,15 +1133,12 @@ parse_dir_file (lines, nlines, nodes, base_name)
}
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
char *opened_dirfilename;
char *compression_program;
char *infile_sans_info;
char *infile = 0, *dirfile = 0;
unsigned infilelen_sans_info;
/* Record the text of the Info file, as a sequence of characters
and as a sequence of lines. */
@ -1159,8 +1199,8 @@ main (argc, argv)
case 'd':
if (dirfile)
{
fprintf (stderr, _("%s: Specify the Info directory only once.\n"),
progname);
fprintf (stderr, _("%s: already have dir file: %s\n"),
progname, dirfile);
suggest_asking_for_help ();
}
dirfile = optarg;
@ -1169,8 +1209,8 @@ main (argc, argv)
case 'D':
if (dirfile)
{
fprintf (stderr, _("%s: Specify the Info directory only once.\n"),
progname);
fprintf (stderr, _("%s: already have dir file: %s\n"),
progname, dirfile);
suggest_asking_for_help ();
}
dirfile = concat (optarg, "", "/dir");
@ -1247,11 +1287,10 @@ main (argc, argv)
case 'V':
printf ("install-info (GNU %s) %s\n", PACKAGE, VERSION);
puts ("");
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
There is NO warranty. You may redistribute this software\n\
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"),
"2003");
For more information about these matters, see the files named COPYING.\n"));
xexit (0);
default:
@ -1351,7 +1390,6 @@ For more information about these matters, see the files named COPYING.\n"),
infile_basename--;
infile_sans_info = strip_info_suffix (infile_basename);
infilelen_sans_info = strlen (infile_sans_info);
}
something_deleted
@ -1361,7 +1399,6 @@ For more information about these matters, see the files named COPYING.\n"),
Find the menu sections to add them in.
In each section, find the proper alphabetical place to add
each of the entries. */
if (!delete_flag)
{
struct node *node;
@ -1459,10 +1496,7 @@ For more information about these matters, see the files named COPYING.\n"),
Store the length of that vector into *NLINESP. */
struct line_data *
findlines (data, size, nlinesp)
char *data;
int size;
int *nlinesp;
findlines (char *data, int size, int *nlinesp)
{
int i;
int lineflag = 1;
@ -1507,75 +1541,16 @@ findlines (data, size, nlinesp)
return lines;
}
/* Compare the menu item names in LINE1 (line length LEN1)
and LINE2 (line length LEN2). Return 1 if the item name
in LINE1 is less, 0 otherwise. */
int
menu_line_lessp (line1, len1, line2, len2)
char *line1;
int len1;
char *line2;
int len2;
{
int minlen = (len1 < len2 ? len1 : len2);
int i;
for (i = 0; i < minlen; i++)
{
/* If one item name is a prefix of the other,
the former one is less. */
if (line1[i] == ':' && line2[i] != ':')
return 1;
if (line2[i] == ':' && line1[i] != ':')
return 0;
/* If they both continue and differ, one is less. */
if (line1[i] < line2[i])
return 1;
if (line1[i] > line2[i])
return 0;
}
/* With a properly formatted dir file,
we can only get here if the item names are equal. */
return 0;
}
/* Compare the menu item names in LINE1 (line length LEN1)
and LINE2 (line length LEN2). Return 1 if the item names are equal,
0 otherwise. */
int
menu_line_equal (line1, len1, line2, len2)
char *line1;
int len1;
char *line2;
int len2;
{
int minlen = (len1 < len2 ? len1 : len2);
int i;
for (i = 0; i < minlen; i++)
{
/* If both item names end here, they are equal. */
if (line1[i] == ':' && line2[i] == ':')
return 1;
/* If they both continue and differ, one is less. */
if (line1[i] != line2[i])
return 0;
}
/* With a properly formatted dir file,
we can only get here if the item names are equal. */
return 1;
}
/* This is the comparison function for qsort
for a vector of pointers to struct spec_section.
/* This is the comparison function for qsort for a vector of pointers to
struct spec_section. (Have to use const void * as the parameter type
to avoid incompatible-with-qsort warnings.)
Compare the section names. */
int
compare_section_names (sec1, sec2)
struct spec_section **sec1, **sec2;
compare_section_names (const void *p1, const void *p2)
{
struct spec_section **sec1 = (struct spec_section **) p1;
struct spec_section **sec2 = (struct spec_section **) p2;
char *name1 = (*sec1)->name;
char *name2 = (*sec2)->name;
return strcmp (name1, name2);
@ -1586,9 +1561,10 @@ compare_section_names (sec1, sec2)
Compare the entries' text. */
int
compare_entries_text (entry1, entry2)
struct spec_entry **entry1, **entry2;
compare_entries_text (const void *p1, const void *p2)
{
struct spec_entry **entry1 = (struct spec_entry **) p1;
struct spec_entry **entry2 = (struct spec_entry **) p2;
char *text1 = (*entry1)->text;
char *text2 = (*entry2)->text;
char *colon1 = strchr (text1, ':');
@ -1612,11 +1588,8 @@ compare_entries_text (entry1, entry2)
in main. */
void
insert_entry_here (entry, line_number, dir_lines, n_entries)
struct spec_entry *entry;
int line_number;
struct line_data *dir_lines;
int n_entries;
insert_entry_here (struct spec_entry *entry, int line_number,
struct line_data *dir_lines, int n_entries)
{
int i, j;