1
1
/* install-info -- create Info directory entry(ies) for an Info file.
2
$Id: install-info.c,v 1.52 2002/01/19 01:12:29 karl Exp $
2
$Id: install-info.c,v 1.12 2004/04/11 17:56:47 karl Exp $
4
Copyright (C) 1996, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc.
4
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
6
7
This program is free software; you can redistribute it and/or modify
7
8
it under the terms of the GNU General Public License as published by
23
24
static char *progname = "install-info";
25
struct line_data *findlines ();
26
void insert_entry_here ();
27
int compare_section_names (), compare_entries_text ();
29
struct line_data *findlines (char *data, int size, int *nlinesp);
30
void insert_entry_here (struct spec_entry *entry, int line_number,
31
struct line_data *dir_lines, int n_entries);
32
int compare_section_names (const void *s1, const void *s2);
33
int compare_entries_text (const void *e1, const void *e2);
31
35
/* Data structures. */
119
123
{ "dir-file", required_argument, NULL, 'd' },
120
124
{ "entry", required_argument, NULL, 'e' },
121
125
{ "help", no_argument, NULL, 'h' },
126
{ "infodir", required_argument, NULL, 'D' },
122
127
{ "info-dir", required_argument, NULL, 'D' },
123
128
{ "info-file", required_argument, NULL, 'i' },
124
129
{ "item", required_argument, NULL, 'e' },
143
error (const char *s1, const char *s2, const char *s3)
141
145
fprintf (stderr, "%s: ", progname);
142
146
fprintf (stderr, s1, s2, s3);
152
warning (const char *s1, const char *s2, const char *s3)
151
154
fprintf (stderr, _("%s: warning: "), progname);
152
155
fprintf (stderr, s1, s2, s3);
156
159
/* Print error message and exit. */
162
fatal (const char *s1, const char *s2, const char *s3)
162
164
error (s1, s2, s3);
166
/* Memory allocation and string operations. */
168
/* Like malloc but get fatal error if memory is exhausted. */
173
extern void *malloc ();
174
void *result = malloc (size);
176
fatal (_("virtual memory exhausted"), 0, 0);
180
/* Like realloc but get fatal error if memory is exhausted. */
186
extern void *realloc ();
187
void *result = realloc (obj, size);
189
fatal (_("virtual memory exhausted"), 0, 0);
193
168
/* Return a newly-allocated string
194
169
whose contents concatenate those of S1, S2, S3. */
171
concat (const char *s1, const char *s2, const char *s3)
199
173
int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
200
174
char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
226
198
/* Print fatal error message based on errno, with file name NAME. */
229
pfatal_with_name (name)
201
pfatal_with_name (const char *name)
232
203
char *s = concat ("", strerror (errno), _(" for %s"));
233
204
fatal (s, name, 0);
207
/* Compare the menu item names in LINE1 (line length LEN1)
208
and LINE2 (line length LEN2). Return 1 if the item name
209
in LINE1 is less, 0 otherwise. */
212
menu_line_lessp (char *line1, int len1, char *line2, int len2)
214
int minlen = (len1 < len2 ? len1 : len2);
217
for (i = 0; i < minlen; i++)
219
/* If one item name is a prefix of the other,
220
the former one is less. */
221
if (line1[i] == ':' && line2[i] != ':')
223
if (line2[i] == ':' && line1[i] != ':')
225
/* If they both continue and differ, one is less. */
226
if (line1[i] < line2[i])
228
if (line1[i] > line2[i])
231
/* With a properly formatted dir file,
232
we can only get here if the item names are equal. */
236
/* Compare the menu item names in LINE1 (line length LEN1)
237
and LINE2 (line length LEN2). Return 1 if the item names are equal,
241
menu_line_equal (char *line1, int len1, char *line2, int len2)
243
int minlen = (len1 < len2 ? len1 : len2);
246
for (i = 0; i < minlen; i++)
248
/* If both item names end here, they are equal. */
249
if (line1[i] == ':' && line2[i] == ':')
251
/* If they both continue and differ, one is less. */
252
if (line1[i] != line2[i])
255
/* With a properly formatted dir file,
256
we can only get here if the item names are equal. */
236
261
/* Given the full text of a menu entry, null terminated,
237
262
return just the menu item name (copied). */
240
extract_menu_item_name (item_text)
265
extract_menu_item_name (char *item_text)
340
367
TERM_CHAR) and still match. */
343
menu_item_equal (item, term_char, name)
370
menu_item_equal (const char *item, char term_char, const char *name)
373
const char *item_basename = item;
348
374
unsigned name_len = strlen (name);
376
/* We must compare the basename in ITEM, since we are passed the
377
basename of the original info file. Otherwise, a new entry like
378
"lilypond/lilypond" won't match "lilypond".
380
Actually, it seems to me that we should really compare the whole
381
name, and not just the basename. Couldn't there be dir1/foo.info
382
and dir2/foo.info? Also, it seems like we should be using the
383
filename from the new dir entries, not the filename on the command
384
line. Not worrying about those things right now, though. --karl,
386
while (*item_basename && !IS_SLASH (*item_basename)
387
&& *item_basename != term_char)
389
if (! *item_basename || *item_basename == term_char)
390
item_basename = item; /* no /, use original */
392
item_basename++; /* have /, move past it */
349
394
/* First, ITEM must actually match NAME (usually it won't). */
350
int ret = strncasecmp (item, name, name_len) == 0;
395
ret = strncasecmp (item_basename, name, name_len) == 0;
353
398
/* Then, `foobar' doesn't match `foo', so be sure we've got all of
366
411
char *suffix = suffixes[i];
367
412
unsigned suffix_len = strlen (suffix);
368
ret = strncasecmp (item + name_len, suffix, suffix_len) == 0
369
&& item[name_len + suffix_len] == term_char;
413
ret = strncasecmp (item_basename + name_len, suffix, suffix_len) == 0
414
&& item_basename[name_len + suffix_len] == term_char;
416
461
If you don't specify any sections, they are determined\n\
417
462
from information in the Info file itself.\n\
418
463
--version display version information and exit.\n\
420
467
Email bug reports to bug-texinfo@gnu.org,\n\
421
468
general questions and discussion to help-texinfo@gnu.org.\n\
469
Texinfo home page: http://www.gnu.org/software/texinfo/"));
442
488
fprintf (f, _("This is the file .../info/dir, which contains the\n\
443
489
topmost node of the Info hierarchy, called (dir)Top.\n\
444
490
The first time you invoke Info you start off looking at this node.\n\
446
492
%s\tThis is the top of the INFO tree\n\
448
494
This (the Directory node) gives a menu of major topics.\n\
453
499
In Emacs, you can click mouse button 2 on a menu item or cross reference\n\
457
"), "File: dir,\tNode: Top"); /* This part must not be translated. */
503
"), "File: dir,\tNode: Top", /* These keywords must not be translated. */
458
506
if (fclose (f) < 0)
459
507
pfatal_with_name (dirfile);
482
530
magic number, not the filename. */
485
open_possibly_compressed_file (filename, create_callback,
486
opened_filename, compression_program, is_pipe)
488
void (*create_callback) ();
489
char **opened_filename;
490
char **compression_program;
533
open_possibly_compressed_file (char *filename,
534
void (*create_callback) (char *),
535
char **opened_filename, char **compression_program, int *is_pipe)
493
537
char *local_opened_filename, *local_compression_program;
507
551
*opened_filename = concat (filename, ".gz", "");
508
552
f = fopen (*opened_filename, FOPEN_RBIN);
555
free (*opened_filename);
556
*opened_filename = concat (filename, ".bz2", "");
557
f = fopen (*opened_filename, FOPEN_RBIN);
562
613
*compression_program = "gzip";
615
else if(data[0] == 'B' && data[1] == 'Z' && data[2] == 'h')
616
#ifndef STRIP_DOT_EXE
617
*compression_program = "bzip2.exe";
619
*compression_program = "bzip2";
621
else if(data[0] == 'B' && data[1] == 'Z' && data[2] == '0')
622
#ifndef STRIP_DOT_EXE
623
*compression_program = "bzip.exe";
625
*compression_program = "bzip";
565
628
*compression_program = NULL;
599
662
a fatal error. */
602
readfile (filename, sizep, create_callback,
603
opened_filename, compression_program)
606
void (*create_callback) ();
607
char **opened_filename;
608
char **compression_program;
665
readfile (char *filename, int *sizep,
666
void (*create_callback) (char *), char **opened_filename,
667
char **compression_program)
656
715
we'll write dir.gz on output. */
659
output_dirfile (dirfile, dir_nlines, dir_lines,
660
n_entries_to_add, entries_to_add, input_sections,
664
struct line_data *dir_lines;
665
int n_entries_to_add;
666
struct spec_entry *entries_to_add;
667
struct spec_section *input_sections;
668
char *compression_program;
718
output_dirfile (char *dirfile, int dir_nlines, struct line_data *dir_lines,
719
int n_entries_to_add, struct spec_entry *entries_to_add,
720
struct spec_section *input_sections, char *compression_program)
794
846
/* Parse the input to find the section names and the entry names it
795
847
specifies. Return the number of entries to add from this file. */
797
parse_input (lines, nlines, sections, entries)
798
const struct line_data *lines;
800
struct spec_section **sections;
801
struct spec_entry **entries;
849
parse_input (const struct line_data *lines, int nlines,
850
struct spec_section **sections, struct spec_entry **entries)
803
852
int n_entries = 0;
804
853
int prefix_length = strlen ("INFO-DIR-SECTION ");
924
973
/* Parse the dir file whose basename is BASE_NAME. Find all the
925
974
nodes, and their menus, and the sections of their menus. */
927
parse_dir_file (lines, nlines, nodes, base_name)
928
struct line_data *lines;
931
const char *base_name;
976
parse_dir_file (struct line_data *lines, int nlines, struct node **nodes,
977
const char *base_name)
933
979
int node_header_flag = 0;
934
980
int something_deleted = 0;
1127
main (int argc, char **argv)
1085
1129
char *opened_dirfilename;
1086
1130
char *compression_program;
1087
1131
char *infile_sans_info;
1088
1132
char *infile = 0, *dirfile = 0;
1089
unsigned infilelen_sans_info;
1091
1134
/* Record the text of the Info file, as a sequence of characters
1092
1135
and as a sequence of lines. */
1158
fprintf (stderr, _("%s: Specify the Info directory only once.\n"),
1201
fprintf (stderr, _("%s: already have dir file: %s\n"),
1160
1203
suggest_asking_for_help ();
1162
1205
dirfile = concat (optarg, "", "/dir");
1220
1263
printf ("install-info (GNU %s) %s\n", PACKAGE, VERSION);
1222
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
1223
There is NO warranty. You may redistribute this software\n\
1265
puts ("Copyright (C) 2004 Free Software Foundation, Inc.");
1266
printf (_("There is NO warranty. You may redistribute this software\n\
1224
1267
under the terms of the GNU General Public License.\n\
1225
For more information about these matters, see the files named COPYING.\n"),
1268
For more information about these matters, see the files named COPYING.\n"));
1311
1353
char *infile_basename = infile + strlen (infile);
1313
1355
if (HAVE_DRIVE (infile))
1314
infile += 2; /* get past the drive spec X: */
1356
infile += 2; /* get past the drive spec X: */
1316
1358
while (infile_basename > infile && !IS_SLASH (infile_basename[-1]))
1317
1359
infile_basename--;
1319
1361
infile_sans_info = strip_info_suffix (infile_basename);
1320
infilelen_sans_info = strlen (infile_sans_info);
1323
1364
something_deleted
1470
/* Compare the menu item names in LINE1 (line length LEN1)
1471
and LINE2 (line length LEN2). Return 1 if the item name
1472
in LINE1 is less, 0 otherwise. */
1475
menu_line_lessp (line1, len1, line2, len2)
1481
int minlen = (len1 < len2 ? len1 : len2);
1484
for (i = 0; i < minlen; i++)
1486
/* If one item name is a prefix of the other,
1487
the former one is less. */
1488
if (line1[i] == ':' && line2[i] != ':')
1490
if (line2[i] == ':' && line1[i] != ':')
1492
/* If they both continue and differ, one is less. */
1493
if (line1[i] < line2[i])
1495
if (line1[i] > line2[i])
1498
/* With a properly formatted dir file,
1499
we can only get here if the item names are equal. */
1503
/* Compare the menu item names in LINE1 (line length LEN1)
1504
and LINE2 (line length LEN2). Return 1 if the item names are equal,
1508
menu_line_equal (line1, len1, line2, len2)
1514
int minlen = (len1 < len2 ? len1 : len2);
1517
for (i = 0; i < minlen; i++)
1519
/* If both item names end here, they are equal. */
1520
if (line1[i] == ':' && line2[i] == ':')
1522
/* If they both continue and differ, one is less. */
1523
if (line1[i] != line2[i])
1526
/* With a properly formatted dir file,
1527
we can only get here if the item names are equal. */
1531
/* This is the comparison function for qsort
1532
for a vector of pointers to struct spec_section.
1508
/* This is the comparison function for qsort for a vector of pointers to
1509
struct spec_section. (Have to use const void * as the parameter type
1510
to avoid incompatible-with-qsort warnings.)
1533
1511
Compare the section names. */
1536
compare_section_names (sec1, sec2)
1537
struct spec_section **sec1, **sec2;
1514
compare_section_names (const void *p1, const void *p2)
1516
struct spec_section **sec1 = (struct spec_section **) p1;
1517
struct spec_section **sec2 = (struct spec_section **) p2;
1539
1518
char *name1 = (*sec1)->name;
1540
1519
char *name2 = (*sec2)->name;
1541
1520
return strcmp (name1, name2);
1546
1525
Compare the entries' text. */
1549
compare_entries_text (entry1, entry2)
1550
struct spec_entry **entry1, **entry2;
1528
compare_entries_text (const void *p1, const void *p2)
1530
struct spec_entry **entry1 = (struct spec_entry **) p1;
1531
struct spec_entry **entry2 = (struct spec_entry **) p2;
1552
1532
char *text1 = (*entry1)->text;
1553
1533
char *text2 = (*entry2)->text;
1554
1534
char *colon1 = strchr (text1, ':');
1575
insert_entry_here (entry, line_number, dir_lines, n_entries)
1576
struct spec_entry *entry;
1578
struct line_data *dir_lines;
1555
insert_entry_here (struct spec_entry *entry, int line_number,
1556
struct line_data *dir_lines, int n_entries)