~ubuntu-branches/ubuntu/maverick/texinfo/maverick

« back to all changes in this revision

Viewing changes to util/install-info.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2005-10-28 15:10:30 UTC
  • mto: (2.1.1 dapper) (3.1.4 hardy)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20051028151030-9nsf2s2k2z3fktjt
Tags: upstream-4.8
ImportĀ upstreamĀ versionĀ 4.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 $
3
3
 
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
 
5
   Foundation, Inc.
5
6
 
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
22
23
 
23
24
static char *progname = "install-info";
24
25
 
25
 
struct line_data *findlines ();
26
 
void insert_entry_here ();
27
 
int compare_section_names (), compare_entries_text ();
28
 
 
29
26
struct spec_entry;
 
27
struct spec_section;
 
28
 
 
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); 
30
34
 
31
35
/* Data structures.  */
32
36
 
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' },
135
140
 
136
141
/* VARARGS1 */
137
142
void
138
 
error (s1, s2, s3)
139
 
     char *s1, *s2, *s3;
 
143
error (const char *s1, const char *s2, const char *s3)
140
144
{
141
145
  fprintf (stderr, "%s: ", progname);
142
146
  fprintf (stderr, s1, s2, s3);
145
149
 
146
150
/* VARARGS1 */
147
151
void
148
 
warning (s1, s2, s3)
149
 
     char *s1, *s2, *s3;
 
152
warning (const char *s1, const char *s2, const char *s3)
150
153
{
151
154
  fprintf (stderr, _("%s: warning: "), progname);
152
155
  fprintf (stderr, s1, s2, s3);
156
159
/* Print error message and exit.  */
157
160
 
158
161
void
159
 
fatal (s1, s2, s3)
160
 
     char *s1, *s2, *s3;
 
162
fatal (const char *s1, const char *s2, const char *s3)
161
163
{
162
164
  error (s1, s2, s3);
163
165
  xexit (1);
164
166
}
165
167
 
166
 
/* Memory allocation and string operations.  */
167
 
 
168
 
/* Like malloc but get fatal error if memory is exhausted.  */
169
 
void *
170
 
xmalloc (size)
171
 
     unsigned int size;
172
 
{
173
 
  extern void *malloc ();
174
 
  void *result = malloc (size);
175
 
  if (result == NULL)
176
 
    fatal (_("virtual memory exhausted"), 0, 0);
177
 
  return result;
178
 
}
179
 
 
180
 
/* Like realloc but get fatal error if memory is exhausted.  */
181
 
void *
182
 
xrealloc (obj, size)
183
 
     void *obj;
184
 
     unsigned int size;
185
 
{
186
 
  extern void *realloc ();
187
 
  void *result = realloc (obj, size);
188
 
  if (result == NULL)
189
 
    fatal (_("virtual memory exhausted"), 0, 0);
190
 
  return result;
191
 
}
192
 
 
193
168
/* Return a newly-allocated string
194
169
   whose contents concatenate those of S1, S2, S3.  */
195
170
char *
196
 
concat (s1, s2, s3)
197
 
     char *s1, *s2, *s3;
 
171
concat (const char *s1, const char *s2, const char *s3)
198
172
{
199
173
  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
200
174
  char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
211
185
   copied from starting at STRING.  */
212
186
 
213
187
char *
214
 
copy_string (string, size)
215
 
     char *string;
216
 
     int size;
 
188
copy_string (const char *string, int size)
217
189
{
218
190
  int i;
219
191
  char *copy = (char *) xmalloc (size + 1);
226
198
/* Print fatal error message based on errno, with file name NAME.  */
227
199
 
228
200
void
229
 
pfatal_with_name (name)
230
 
     char *name;
 
201
pfatal_with_name (const char *name)
231
202
{
232
203
  char *s = concat ("", strerror (errno), _(" for %s"));
233
204
  fatal (s, name, 0);
234
205
}
235
206
 
 
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.  */
 
210
 
 
211
static int
 
212
menu_line_lessp (char *line1, int len1, char *line2, int len2)
 
213
{
 
214
  int minlen = (len1 < len2 ? len1 : len2);
 
215
  int i;
 
216
 
 
217
  for (i = 0; i < minlen; i++)
 
218
    {
 
219
      /* If one item name is a prefix of the other,
 
220
         the former one is less.  */
 
221
      if (line1[i] == ':' && line2[i] != ':')
 
222
        return 1;
 
223
      if (line2[i] == ':' && line1[i] != ':')
 
224
        return 0;
 
225
      /* If they both continue and differ, one is less.  */
 
226
      if (line1[i] < line2[i])
 
227
        return 1;
 
228
      if (line1[i] > line2[i])
 
229
        return 0;
 
230
    }
 
231
  /* With a properly formatted dir file,
 
232
     we can only get here if the item names are equal.  */
 
233
  return 0;
 
234
}
 
235
 
 
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,
 
238
   0 otherwise.  */
 
239
 
 
240
static int
 
241
menu_line_equal (char *line1, int len1, char *line2, int len2)
 
242
{
 
243
  int minlen = (len1 < len2 ? len1 : len2);
 
244
  int i;
 
245
 
 
246
  for (i = 0; i < minlen; i++)
 
247
    {
 
248
      /* If both item names end here, they are equal.  */
 
249
      if (line1[i] == ':' && line2[i] == ':')
 
250
        return 1;
 
251
      /* If they both continue and differ, one is less.  */
 
252
      if (line1[i] != line2[i])
 
253
        return 0;
 
254
    }
 
255
  /* With a properly formatted dir file,
 
256
     we can only get here if the item names are equal.  */
 
257
  return 1;
 
258
}
 
259
 
 
260
 
236
261
/* Given the full text of a menu entry, null terminated,
237
262
   return just the menu item name (copied).  */
238
263
 
239
264
char *
240
 
extract_menu_item_name (item_text)
241
 
     char *item_text;
 
265
extract_menu_item_name (char *item_text)
242
266
{
243
267
  char *p;
244
268
 
256
280
   return just the menu item file (copied).  */
257
281
 
258
282
char *
259
 
extract_menu_file_name (item_text)
260
 
     char *item_text;
 
283
extract_menu_file_name (char *item_text)
261
284
{
262
285
  char *p = item_text;
263
286
 
300
323
/* Return FNAME with any [.info][.gz] suffix removed.  */
301
324
 
302
325
static char *
303
 
strip_info_suffix (fname)
304
 
     char *fname;
 
326
strip_info_suffix (char *fname)
305
327
{
306
328
  char *ret = xstrdup (fname);
307
329
  unsigned len = strlen (ret);
311
333
      len -= 3;
312
334
      ret[len] = 0;
313
335
    }
 
336
  else if (len > 4 && FILENAME_CMP (ret + len - 4, ".bz2") == 0)
 
337
    {
 
338
      len -= 4;
 
339
      ret[len] = 0;
 
340
    }
314
341
 
315
342
  if (len > 5 && FILENAME_CMP (ret + len - 5, ".info") == 0)
316
343
    {
340
367
   TERM_CHAR) and still match.  */
341
368
 
342
369
static int
343
 
menu_item_equal (item, term_char, name)
344
 
     char *item;
345
 
     char term_char;
346
 
     char *name;
 
370
menu_item_equal (const char *item, char term_char, const char *name)
347
371
{
 
372
  int ret;
 
373
  const char *item_basename = item;
348
374
  unsigned name_len = strlen (name);
 
375
 
 
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".
 
379
     
 
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,
 
385
     26mar04.  */
 
386
  while (*item_basename && !IS_SLASH (*item_basename)
 
387
         && *item_basename != term_char)
 
388
    item_basename++;
 
389
  if (! *item_basename || *item_basename == term_char)
 
390
    item_basename = item;  /* no /, use original */
 
391
  else
 
392
    item_basename++;       /* have /, move past it */
 
393
    
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;
351
396
  if (ret)
352
397
    {
353
398
      /* Then, `foobar' doesn't match `foo', so be sure we've got all of
365
410
        {
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;
370
415
        }
371
416
    }
372
417
 
376
421
 
377
422
 
378
423
void
379
 
suggest_asking_for_help ()
 
424
suggest_asking_for_help (void)
380
425
{
381
426
  fprintf (stderr, _("\tTry `%s --help' for a complete list of options.\n"),
382
427
           progname);
384
429
}
385
430
 
386
431
void
387
 
print_help ()
 
432
print_help (void)
388
433
{
389
434
  printf (_("Usage: %s [OPTION]... [INFO-FILE [DIR-FILE]]\n\
390
435
\n\
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\
419
 
\n\
 
464
"), progname);
 
465
 
 
466
  puts (_("\n\
420
467
Email bug reports to bug-texinfo@gnu.org,\n\
421
468
general questions and discussion to help-texinfo@gnu.org.\n\
422
 
"), progname);
 
469
Texinfo home page: http://www.gnu.org/software/texinfo/"));
423
470
}
424
471
 
425
472
 
427
474
   already exists, do nothing.  */
428
475
 
429
476
void
430
 
ensure_dirfile_exists (dirfile)
431
 
     char *dirfile;
 
477
ensure_dirfile_exists (char *dirfile)
432
478
{
433
479
  int desc = open (dirfile, O_RDONLY);
434
480
  if (desc < 0 && errno == ENOENT)
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\
445
 
\n\
 
491
\x1f\n\
446
492
%s\tThis is the top of the INFO tree\n\
447
493
\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\
454
500
  to select it.\n\
455
501
\n\
456
 
* Menu:\n\
457
 
"), "File: dir,\tNode: Top"); /* This part must not be translated.  */
 
502
%s\n\
 
503
"), "File: dir,\tNode: Top",  /* These keywords must not be translated.  */
 
504
    "* Menu:"
 
505
);
458
506
          if (fclose (f) < 0)
459
507
            pfatal_with_name (dirfile);
460
508
        }
482
530
   magic number, not the filename.  */
483
531
 
484
532
FILE *
485
 
open_possibly_compressed_file (filename, create_callback,
486
 
                               opened_filename, compression_program, is_pipe)
487
 
     char *filename;
488
 
     void (*create_callback) ();
489
 
     char **opened_filename;
490
 
     char **compression_program;
491
 
     int  *is_pipe;
 
533
open_possibly_compressed_file (char *filename,
 
534
    void (*create_callback) (char *),
 
535
    char **opened_filename, char **compression_program, int *is_pipe) 
492
536
{
493
537
  char *local_opened_filename, *local_compression_program;
494
538
  int nread;
506
550
    {
507
551
      *opened_filename = concat (filename, ".gz", "");
508
552
      f = fopen (*opened_filename, FOPEN_RBIN);
 
553
  if (!f)
 
554
    {
 
555
      free (*opened_filename);
 
556
      *opened_filename = concat (filename, ".bz2", "");
 
557
      f = fopen (*opened_filename, FOPEN_RBIN);
 
558
    }
 
559
 
509
560
#ifdef __MSDOS__
510
561
      if (!f)
511
562
        {
561
612
#else
562
613
    *compression_program = "gzip";
563
614
#endif
 
615
  else if(data[0] == 'B' && data[1] == 'Z' && data[2] == 'h')
 
616
#ifndef STRIP_DOT_EXE
 
617
    *compression_program = "bzip2.exe";
 
618
#else
 
619
    *compression_program = "bzip2";
 
620
#endif
 
621
  else if(data[0] == 'B' && data[1] == 'Z' && data[2] == '0')
 
622
#ifndef STRIP_DOT_EXE
 
623
    *compression_program = "bzip.exe";
 
624
#else
 
625
    *compression_program = "bzip";
 
626
#endif
564
627
  else
565
628
    *compression_program = NULL;
566
629
 
599
662
   a fatal error.  */
600
663
 
601
664
char *
602
 
readfile (filename, sizep, create_callback,
603
 
          opened_filename, compression_program)
604
 
     char *filename;
605
 
     int *sizep;
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)
609
668
{
610
669
  char *real_name;
611
670
  FILE *f;
656
715
   we'll write dir.gz on output.  */
657
716
 
658
717
static void
659
 
output_dirfile (dirfile, dir_nlines, dir_lines,
660
 
                n_entries_to_add, entries_to_add, input_sections,
661
 
                compression_program)
662
 
      char *dirfile;
663
 
      int dir_nlines;
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)
669
721
{
670
722
  int i;
671
723
  FILE *output;
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.  */
796
848
int
797
 
parse_input (lines, nlines, sections, entries)
798
 
     const struct line_data *lines;
799
 
     int nlines;
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) 
802
851
{
803
852
  int n_entries = 0;
804
853
  int prefix_length = strlen ("INFO-DIR-SECTION ");
902
951
    }
903
952
  if (start_of_this_entry != 0)
904
953
    fatal (_("START-INFO-DIR-ENTRY without matching END-INFO-DIR-ENTRY"),
905
 
           0, 0);
 
954
           0, 0);
906
955
 
907
956
  /* If we ignored the INFO-DIR-ENTRY directives, we need now go back
908
957
     and plug the names of all the sections we found into every
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.  */
926
975
int
927
 
parse_dir_file (lines, nlines, nodes, base_name)
928
 
     struct line_data *lines;
929
 
     int nlines;
930
 
     struct node **nodes;
931
 
     const char *base_name;
 
976
parse_dir_file (struct line_data *lines, int nlines, struct node **nodes,
 
977
                const char *base_name)
932
978
{
933
979
  int node_header_flag = 0;
934
980
  int something_deleted = 0;
1078
1124
}
1079
1125
 
1080
1126
int
1081
 
main (argc, argv)
1082
 
     int argc;
1083
 
     char **argv;
 
1127
main (int argc, char **argv)
1084
1128
{
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;
1090
1133
 
1091
1134
  /* Record the text of the Info file, as a sequence of characters
1092
1135
     and as a sequence of lines.  */
1145
1188
        case 'd':
1146
1189
          if (dirfile)
1147
1190
            {
1148
 
              fprintf (stderr, _("%s: Specify the Info directory only once.\n"),
1149
 
                       progname);
 
1191
              fprintf (stderr, _("%s: already have dir file: %s\n"),
 
1192
                       progname, dirfile);
1150
1193
              suggest_asking_for_help ();
1151
1194
            }
1152
1195
          dirfile = optarg;
1155
1198
        case 'D':
1156
1199
          if (dirfile)
1157
1200
            {
1158
 
              fprintf (stderr, _("%s: Specify the Info directory only once.\n"),
1159
 
                       progname);
 
1201
              fprintf (stderr, _("%s: already have dir file: %s\n"),
 
1202
                       progname, dirfile);
1160
1203
              suggest_asking_for_help ();
1161
1204
            }
1162
1205
          dirfile = concat (optarg, "", "/dir");
1219
1262
        case 'V':
1220
1263
          printf ("install-info (GNU %s) %s\n", PACKAGE, VERSION);
1221
1264
          puts ("");
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"),
1226
 
                  "2002");
 
1268
For more information about these matters, see the files named COPYING.\n"));
1227
1269
          xexit (0);
1228
1270
 
1229
1271
        default:
1244
1286
 
1245
1287
  if (!infile)
1246
1288
    fatal (_("No input file specified; try --help for more information."),
1247
 
           0, 0);
 
1289
           0, 0);
1248
1290
  if (!dirfile)
1249
1291
    fatal (_("No dir file specified; try --help for more information."), 0, 0);
1250
1292
 
1311
1353
    char *infile_basename = infile + strlen (infile);
1312
1354
 
1313
1355
    if (HAVE_DRIVE (infile))
1314
 
      infile += 2;      /* get past the drive spec X: */
 
1356
      infile += 2;      /* get past the drive spec X: */
1315
1357
 
1316
1358
    while (infile_basename > infile && !IS_SLASH (infile_basename[-1]))
1317
1359
      infile_basename--;
1318
1360
 
1319
1361
    infile_sans_info = strip_info_suffix (infile_basename);
1320
 
    infilelen_sans_info = strlen (infile_sans_info);
1321
1362
  }
1322
1363
 
1323
1364
  something_deleted
1327
1368
     Find the menu sections to add them in.
1328
1369
     In each section, find the proper alphabetical place to add
1329
1370
     each of the entries.  */
1330
 
 
1331
1371
  if (!delete_flag)
1332
1372
    {
1333
1373
      struct node *node;
1367
1407
                      }
1368
1408
                    if (!spec || spec == entry->entry_sections_tail)
1369
1409
                      continue;
1370
 
                    
 
1410
 
1371
1411
                    /* Subtract one because dir_lines is zero-based,
1372
1412
                       but the `end_line' and `start_line' members are
1373
1413
                       one-based.  */
1412
1452
                  entries_to_add, input_sections, compression_program);
1413
1453
 
1414
1454
  xexit (0);
 
1455
  return 0; /* Avoid bogus warnings.  */
1415
1456
}
1416
1457
 
1417
1458
/* Divide the text at DATA (of SIZE bytes) into lines.
1419
1460
   Store the length of that vector into *NLINESP.  */
1420
1461
 
1421
1462
struct line_data *
1422
 
findlines (data, size, nlinesp)
1423
 
     char *data;
1424
 
     int size;
1425
 
     int *nlinesp;
 
1463
findlines (char *data, int size, int *nlinesp)
1426
1464
{
1427
1465
  int i;
1428
1466
  int lineflag = 1;
1467
1505
  return lines;
1468
1506
}
1469
1507
 
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.  */
1473
 
 
1474
 
int
1475
 
menu_line_lessp (line1, len1, line2, len2)
1476
 
     char *line1;
1477
 
     int len1;
1478
 
     char *line2;
1479
 
     int len2;
1480
 
{
1481
 
  int minlen = (len1 < len2 ? len1 : len2);
1482
 
  int i;
1483
 
 
1484
 
  for (i = 0; i < minlen; i++)
1485
 
    {
1486
 
      /* If one item name is a prefix of the other,
1487
 
         the former one is less.  */
1488
 
      if (line1[i] == ':' && line2[i] != ':')
1489
 
        return 1;
1490
 
      if (line2[i] == ':' && line1[i] != ':')
1491
 
        return 0;
1492
 
      /* If they both continue and differ, one is less.  */
1493
 
      if (line1[i] < line2[i])
1494
 
        return 1;
1495
 
      if (line1[i] > line2[i])
1496
 
        return 0;
1497
 
    }
1498
 
  /* With a properly formatted dir file,
1499
 
     we can only get here if the item names are equal.  */
1500
 
  return 0;
1501
 
}
1502
 
 
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,
1505
 
   0 otherwise.  */
1506
 
 
1507
 
int
1508
 
menu_line_equal (line1, len1, line2, len2)
1509
 
     char *line1;
1510
 
     int len1;
1511
 
     char *line2;
1512
 
     int len2;
1513
 
{
1514
 
  int minlen = (len1 < len2 ? len1 : len2);
1515
 
  int i;
1516
 
 
1517
 
  for (i = 0; i < minlen; i++)
1518
 
    {
1519
 
      /* If both item names end here, they are equal.  */
1520
 
      if (line1[i] == ':' && line2[i] == ':')
1521
 
        return 1;
1522
 
      /* If they both continue and differ, one is less.  */
1523
 
      if (line1[i] != line2[i])
1524
 
        return 0;
1525
 
    }
1526
 
  /* With a properly formatted dir file,
1527
 
     we can only get here if the item names are equal.  */
1528
 
  return 1;
1529
 
}
1530
 
 
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.  */
1534
1512
 
1535
1513
int
1536
 
compare_section_names (sec1, sec2)
1537
 
     struct spec_section **sec1, **sec2;
 
1514
compare_section_names (const void *p1, const void *p2)
1538
1515
{
 
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.  */
1547
1526
 
1548
1527
int
1549
 
compare_entries_text (entry1, entry2)
1550
 
     struct spec_entry **entry1, **entry2;
 
1528
compare_entries_text (const void *p1, const void *p2)
1551
1529
{
 
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, ':');
1572
1552
   in main.  */
1573
1553
 
1574
1554
void
1575
 
insert_entry_here (entry, line_number, dir_lines, n_entries)
1576
 
     struct spec_entry *entry;
1577
 
     int line_number;
1578
 
     struct line_data *dir_lines;
1579
 
     int n_entries;
 
1555
insert_entry_here (struct spec_entry *entry, int line_number,
 
1556
                   struct line_data *dir_lines, int n_entries)
1580
1557
{
1581
1558
  int i, j;
1582
1559