summaryrefslogtreecommitdiffstats
path: root/contrib/texinfo/util/install-info.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/texinfo/util/install-info.c')
-rw-r--r--contrib/texinfo/util/install-info.c271
1 files changed, 182 insertions, 89 deletions
diff --git a/contrib/texinfo/util/install-info.c b/contrib/texinfo/util/install-info.c
index b6a7a91..afa9a68 100644
--- a/contrib/texinfo/util/install-info.c
+++ b/contrib/texinfo/util/install-info.c
@@ -1,37 +1,27 @@
/* install-info -- create Info directory entry(ies) for an Info file.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ $Id: install-info.c,v 1.21 1998/03/01 15:38:45 karl Exp $
-$Id: install-info.c,v 1.12 1996/10/03 23:13:36 karl Exp $
+ Copyright (C) 1996, 97, 98 Free Software Foundation, Inc.
-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 of the License, or
-(at your option) any later version.
+ 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 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
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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. */
+ 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.*/
-#define INSTALL_INFO_VERSION_STRING "GNU install-info (Texinfo 3.9) 1.2"
-
-#include <stdio.h>
-#include <errno.h>
+#include "system.h"
#include <getopt.h>
-#include <sys/types.h>
-
-/* Get O_RDONLY. */
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#else
-#include <fcntl.h>
-#endif /* !HAVE_SYS_FCNTL_H */
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
+
+#ifdef HAVE_LIBZ
+#include <zlib.h>
#endif
/* Name this program was invoked with. */
@@ -47,9 +37,8 @@ struct spec_entry;
/* Data structures. */
-/* Record info about a single line from a file
- as read into core. */
+/* Record info about a single line from a file as read into core. */
struct line_data
{
/* The start of the line. */
@@ -66,9 +55,9 @@ struct line_data
int delete;
};
+
/* This is used for a list of the specified menu section names
in which entries should be added. */
-
struct spec_section
{
struct spec_section *next;
@@ -78,16 +67,16 @@ struct spec_section
int missing;
};
-/* This is used for a list of the entries specified to be added. */
+/* This is used for a list of the entries specified to be added. */
struct spec_entry
{
struct spec_entry *next;
char *text;
};
-
-/* This is used for a list of nodes found by parsing the dir file. */
+
+/* This is used for a list of nodes found by parsing the dir file. */
struct node
{
struct node *next;
@@ -108,9 +97,9 @@ struct node
struct menu_section *last_section;
};
+
/* This is used for a list of sections found in a node's menu.
Each struct node has such a list in the sections field. */
-
struct menu_section
{
struct menu_section *next;
@@ -124,7 +113,6 @@ struct menu_section
/* Memory allocation and string operations. */
/* Like malloc but get fatal error if memory is exhausted. */
-
void *
xmalloc (size)
unsigned int size;
@@ -132,12 +120,11 @@ xmalloc (size)
extern void *malloc ();
void *result = malloc (size);
if (result == NULL)
- fatal ("virtual memory exhausted", 0);
+ fatal (_("virtual memory exhausted"), 0);
return result;
}
-/* Like malloc but get fatal error if memory is exhausted. */
-
+/* Like realloc but get fatal error if memory is exhausted. */
void *
xrealloc (obj, size)
void *obj;
@@ -146,12 +133,12 @@ xrealloc (obj, size)
extern void *realloc ();
void *result = realloc (obj, size);
if (result == NULL)
- fatal ("virtual memory exhausted", 0);
+ fatal (_("virtual memory exhausted"), 0);
return result;
}
-/* Return a newly-allocated string whose contents concatenate those of 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;
@@ -185,7 +172,7 @@ copy_string (string, size)
/* Error message functions. */
-/* Print error message. `s1' is printf control string, `s2' is arg for it. */
+/* Print error message. S1 is printf control string, S2 and S3 args for it. */
/* VARARGS1 */
void
@@ -194,7 +181,7 @@ error (s1, s2, s3)
{
fprintf (stderr, "%s: ", progname);
fprintf (stderr, s1, s2, s3);
- fprintf (stderr, "\n");
+ putc ('\n', stderr);
}
/* VARARGS1 */
@@ -202,9 +189,9 @@ void
warning (s1, s2, s3)
char *s1, *s2, *s3;
{
- fprintf (stderr, "%s: Warning: ", progname);
+ fprintf (stderr, _("%s: warning: "), progname);
fprintf (stderr, s1, s2, s3);
- fprintf (stderr, "\n");
+ putc ('\n', stderr);
}
/* Print error message and exit. */
@@ -223,7 +210,7 @@ void
pfatal_with_name (name)
char *name;
{
- char *s = concat ("", strerror (errno), " for %s");
+ char *s = concat ("", strerror (errno), _(" for %s"));
fatal (s, name);
}
@@ -292,7 +279,7 @@ extract_menu_file_name (item_text)
void
suggest_asking_for_help ()
{
- fprintf (stderr, "\tTry `%s --help' for a complete list of options.\n",
+ fprintf (stderr, _("\tTry `%s --help' for a complete list of options.\n"),
progname);
exit (1);
}
@@ -300,8 +287,9 @@ suggest_asking_for_help ()
void
print_help ()
{
- printf ("%s [OPTION]... [INFO-FILE [DIR-FILE]]\n\
- Install INFO-FILE in the Info directory file DIR-FILE.\n\
+ printf (_("Usage: %s [OPTION]... [INFO-FILE [DIR-FILE]]\n\
+\n\
+Install INFO-FILE in the Info directory file DIR-FILE.\n\
\n\
Options:\n\
--delete Delete existing entries in INFO-FILE;\n\
@@ -334,33 +322,80 @@ Options:\n\
from information in the Info file itself.\n\
--version Display version information and exit.\n\
\n\
-Email bug reports to bug-texinfo@prep.ai.mit.edu.\n\
-", progname);
+Email bug reports to bug-texinfo@gnu.org.\n\
+"), progname);
}
+/* If DIRFILE does not exist, create a minimal one (or abort). If it
+ already exists, do nothing. */
+
+void
+ensure_dirfile_exists (dirfile)
+ char *dirfile;
+{
+ int desc = open (dirfile, O_RDONLY);
+ if (desc < 0 && errno == ENOENT)
+ {
+ FILE *f;
+ char *readerr = strerror (errno);
+ close (desc);
+ f = fopen (dirfile, "w");
+ if (f)
+ {
+ fputs (_("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\
+File: dir,\tNode: Top,\tThis is the top of the INFO tree\n\
+\n\
+ This (the Directory node) gives a menu of major topics.\n\
+ Typing \"q\" exits, \"?\" lists all Info commands, \"d\" returns here,\n\
+ \"h\" gives a primer for first-timers,\n\
+ \"mEmacs<Return>\" visits the Emacs manual, etc.\n\
+\n\
+ In Emacs, you can click mouse button 2 on a menu item or cross reference\n\
+ to select it.\n\
+\n\
+* Menu:\n\
+"), f);
+ if (fclose (f) < 0)
+ pfatal_with_name (dirfile);
+ }
+ else
+ {
+ /* Didn't exist, but couldn't open for writing. */
+ fprintf (stderr,
+ _("%s: could not read (%s) and could not create (%s)\n"),
+ dirfile, readerr, strerror (errno));
+ exit (1);
+ }
+ }
+ else
+ close (desc); /* It already existed, so fine. */
+}
+
/* This table defines all the long-named options, says whether they
use an argument, and maps them into equivalent single-letter options. */
struct option longopts[] =
{
- { "delete", no_argument, NULL, 'r' },
- { "defentry", required_argument, NULL, 'E' },
- { "defsection", required_argument, NULL, 'S' },
- { "dir-file", required_argument, NULL, 'd' },
- { "entry", required_argument, NULL, 'e' },
- { "forceentry", required_argument, NULL, 'f' },
- { "help", no_argument, NULL, 'h' },
- { "info-dir", required_argument, NULL, 'D' },
- { "info-file", required_argument, NULL, 'i' },
- { "item", required_argument, NULL, 'e' },
- { "quiet", no_argument, NULL, 'q' },
- { "remove", no_argument, NULL, 'r' },
- { "section", required_argument, NULL, 's' },
- { "version", no_argument, NULL, 'V' },
+ { "delete", no_argument, NULL, 'r' },
+ { "dir-file", required_argument, NULL, 'd' },
+ { "entry", required_argument, NULL, 'e' },
+ { "help", no_argument, NULL, 'h' },
+ { "info-dir", required_argument, NULL, 'D' },
+ { "info-file", required_argument, NULL, 'i' },
+ { "item", required_argument, NULL, 'e' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "remove", no_argument, NULL, 'r' },
+ { "section", required_argument, NULL, 's' },
+ { "version", no_argument, NULL, 'V' },
{ 0 }
};
+
+int
main (argc, argv)
int argc;
char **argv;
@@ -407,6 +442,15 @@ main (argc, argv)
progname = argv[0];
+#ifdef HAVE_SETLOCALE
+ /* Set locale via LC_ALL. */
+ setlocale (LC_ALL, "");
+#endif
+
+ /* Set the text message domain. */
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
while (1)
{
int opt = getopt_long (argc, argv, "i:d:e:s:hHr", longopts, 0);
@@ -427,7 +471,7 @@ main (argc, argv)
case 'd':
if (dirfile)
{
- fprintf (stderr, "%s: Specify the Info directory only once.\n",
+ fprintf (stderr, _("%s: Specify the Info directory only once.\n"),
progname);
suggest_asking_for_help ();
}
@@ -437,7 +481,7 @@ main (argc, argv)
case 'D':
if (dirfile)
{
- fprintf (stderr, "%s: Specify the Info directory only once.\n",
+ fprintf (stderr, _("%s: Specify the Info directory only once.\n"),
progname);
suggest_asking_for_help ();
}
@@ -476,7 +520,7 @@ main (argc, argv)
case 'i':
if (infile)
{
- fprintf (stderr, "%s: Specify the Info file only once.\n",
+ fprintf (stderr, _("%s: Specify the Info file only once.\n"),
progname);
suggest_asking_for_help ();
}
@@ -507,12 +551,13 @@ main (argc, argv)
break;
case 'V':
- puts (INSTALL_INFO_VERSION_STRING);
-puts ("Copyright (C) 1996 Free Software Foundation, Inc.\n\
+ printf ("install-info (GNU %s) %s\n", PACKAGE, VERSION);
+ printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
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.");
- exit (0);
+For more information about these matters, see the files named COPYING.\n"),
+ "1998");
+ exit (0);
default:
suggest_asking_for_help ();
@@ -530,13 +575,13 @@ For more information about these matters, see the files named COPYING.");
else if (dirfile == 0)
dirfile = argv[optind];
else
- error ("excess command line argument `%s'", argv[optind]);
+ error (_("excess command line argument `%s'"), argv[optind]);
}
if (!infile)
- fatal ("No input file specified");
+ fatal (_("No input file specified; try --help for more information."));
if (!dirfile)
- fatal ("No dir file specified");
+ fatal (_("No dir file specified; try --help for more information."));
/* Read the Info file and parse it into lines. */
@@ -595,7 +640,7 @@ For more information about these matters, see the files named COPYING.");
&& sizeof ("START-INFO-DIR-ENTRY") - 1 == input_lines[i].size)
{
if (start_of_this_entry != 0)
- fatal ("START-INFO-DIR-ENTRY without matching END-INFO-DIR-ENTRY");
+ fatal (_("START-INFO-DIR-ENTRY without matching END-INFO-DIR-ENTRY"));
start_of_this_entry = input_lines[i + 1].start;
}
if (!strncmp ("END-INFO-DIR-ENTRY", input_lines[i].start,
@@ -621,18 +666,26 @@ For more information about these matters, see the files named COPYING.");
start_of_this_entry = 0;
}
else
- fatal ("END-INFO-DIR-ENTRY without matching START-INFO-DIR-ENTRY");
+ fatal (_("END-INFO-DIR-ENTRY without matching START-INFO-DIR-ENTRY"));
}
}
if (start_of_this_entry != 0)
- fatal ("START-INFO-DIR-ENTRY without matching END-INFO-DIR-ENTRY");
+ fatal (_("START-INFO-DIR-ENTRY without matching END-INFO-DIR-ENTRY"));
}
if (!delete_flag)
if (entries_to_add == 0)
- fatal ("no info dir entry in `%s'", infile);
+ { /* No need to abort here, the original info file may not have
+ the requisite Texinfo commands. This is not something an
+ installer should have to correct (it's a problem for the
+ maintainer), and there's no need to cause subsequent parts of
+ `make install' to fail. */
+ warning (_("no info dir entry in `%s'"), infile);
+ exit (0);
+ }
/* Now read in the Info dir file. */
+ ensure_dirfile_exists (dirfile);
dir_data = readfile (dirfile, &dir_size);
dir_lines = findlines (dir_data, dir_size, &dir_nlines);
@@ -641,7 +694,6 @@ For more information about these matters, see the files named COPYING.");
.info suffix. */
{
unsigned basename_len;
- extern char *strrchr ();
char *infile_basename = strrchr (infile, '/');
if (infile_basename)
infile_basename++;
@@ -761,10 +813,13 @@ For more information about these matters, see the files named COPYING.");
p++;
if ((dir_lines[i].size
> (p - dir_lines[i].start + infilelen_sans_info))
- && !strncmp(p, infile_sans_info, infilelen_sans_info)
- && ( p[infilelen_sans_info] == ')' ||
- strncmp (p + infilelen_sans_info, ".info)", 6) == 0))
- dir_lines[i].delete = 1;
+ && !strncmp (p, infile_sans_info, infilelen_sans_info)
+ && (p[infilelen_sans_info] == ')'
+ || !strncmp (p + infilelen_sans_info, ".info)", 6)))
+ {
+ dir_lines[i].delete = 1;
+ something_deleted = 1;
+ }
}
}
/* Treat lines that start with whitespace
@@ -836,7 +891,7 @@ For more information about these matters, see the files named COPYING.");
dir_lines[i].start,
dir_lines[i].size)
&& !dir_lines[i].delete)
- fatal ("menu item `%s' already exists, for file `%s'",
+ fatal (_("menu item `%s' already exists, for file `%s'"),
extract_menu_item_name (entry->text),
extract_menu_file_name (dir_lines[i].start));
if (dir_lines[i].start[0] == '*'
@@ -859,7 +914,7 @@ For more information about these matters, see the files named COPYING.");
}
if (delete_flag && !something_deleted && !quiet_flag)
- warning ("no entries found for `%s'; nothing deleted", infile);
+ warning (_("no entries found for `%s'; nothing deleted"), infile);
/* Output the old dir file, interpolating the new sections
and/or new entries where appropriate. */
@@ -951,19 +1006,49 @@ readfile (filename, sizep)
char *filename;
int *sizep;
{
+ int desc;
int data_size = 1024;
char *data = (char *) xmalloc (data_size);
int filled = 0;
int nread = 0;
+#ifdef HAVE_LIBZ
+ int isGZ = 0;
+ gzFile zdesc;
+#endif
- int desc = open (filename, O_RDONLY);
-
+ desc = open (filename, O_RDONLY);
if (desc < 0)
pfatal_with_name (filename);
+#ifdef HAVE_LIBZ
+ /* The file should always be two bytes long. */
+ if (read (desc, data, 2) != 2)
+ pfatal_with_name (filename);
+
+ /* Undo that read. */
+ lseek (desc, 0, SEEK_SET);
+
+ /* If we see gzip magic, use gzdopen. */
+ if (data[0] == '\x1f' && data[1] == '\x8b')
+ {
+ isGZ = 1;
+ zdesc = gzdopen (desc, "r");
+ if (zdesc == NULL) {
+ close (desc);
+ pfatal_with_name (filename);
+ }
+ }
+#endif /* HAVE_LIBZ */
+
while (1)
{
- nread = read (desc, data + filled, data_size - filled);
+#ifdef HAVE_LIBZ
+ if (isGZ)
+ nread = gzread (zdesc, data + filled, data_size - filled);
+ else
+#endif
+ nread = read (desc, data + filled, data_size - filled);
+
if (nread < 0)
pfatal_with_name (filename);
if (nread == 0)
@@ -978,6 +1063,14 @@ readfile (filename, sizep)
}
*sizep = filled;
+
+#ifdef HAVE_LIBZ
+ if (isGZ)
+ gzclose (zdesc);
+ else
+#endif
+ close(desc);
+
return data;
}
OpenPOWER on IntegriCloud