root/trunk/texinfo/texinfo-4.9-nokeep-1.patch

Revision 1861, 18.6 kB (checked in by robert, 1 year ago)

Added -keep/-nokeep removal backport for Texinfo

  • texinfo-4.9/util/texindex.c

    old new  
    11/* texindex -- sort TeX index dribble output into an actual index. 
    2    $Id: texindex.c,v 1.11.2.2 2007/06/27 17:11:08 karl Exp $ 
     2   $Id: texindex.c,v 1.22 2007/07/01 21:20:34 karl Exp $ 
    33 
    44   Copyright (C) 1987, 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2001, 
    5    2002, 2003, 2004, 2007 Free Software Foundation, Inc. 
     5   2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 
    66 
    7    This program is free software; you can redistribute it and/or modify 
     7   This program is free software: you can redistribute it and/or modify 
    88   it under the terms of the GNU General Public License as published by 
    9    the Free Software Foundation; either version 3, or (at your option) 
    10    any later version. 
     9   the Free Software Foundation, either version 3 of the License, or 
     10   (at your option) any later version. 
    1111 
    1212   This program is distributed in the hope that it will be useful, 
    1313   but WITHOUT ANY WARRANTY; without even the implied warranty of 
     
    1515   GNU General Public License for more details. 
    1616 
    1717   You should have received a copy of the GNU General Public License 
    18    along with this program; if not, write to the Free Software 
    19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307. */ 
     18   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ 
    2019 
    2120#include "system.h" 
    2221#include <getopt.h> 
    2322 
    24 static char *program_name = "texindex"; 
     23char *program_name = "texindex"; 
    2524 
    2625#if defined (emacs) 
    2726#  include "../src/config.h" 
     
    3736#define memset(ptr, ignore, count) bzero (ptr, count) 
    3837#endif 
    3938 
    40 char *mktemp (char *); 
    41  
    4239#if !defined (SEEK_SET) 
    4340#  define SEEK_SET 0 
    4441#  define SEEK_CUR 1 
    4542#  define SEEK_END 2 
    4643#endif /* !SEEK_SET */ 
    4744 
    48 struct linebuffer; 
    49  
    5045/* When sorting in core, this structure describes one line 
    5146   and the position and length of its first keyfield.  */ 
    5247struct lineinfo 
     
    9691/* The allocated length of `linearray'. */ 
    9792long nlines; 
    9893 
    99 /* Directory to use for temporary files.  On Unix, it ends with a slash.  */ 
    100 char *tempdir; 
    101  
    102 /* Number of last temporary file.  */ 
    103 int tempcount; 
    104  
    105 /* Number of last temporary file already deleted. 
    106    Temporary files are deleted by `flush_tempfiles' in order of creation.  */ 
    107 int last_deleted_tempcount; 
    108  
    10994/* During in-core sort, this points to the base of the data block 
    11095   which contains all the lines of data.  */ 
    11196char *text_base; 
     
    117102   determine whether we need initials in the sorted form.  */ 
    118103char first_initial; 
    119104 
    120 /* Additional command switches .*/ 
    121  
    122 /* Nonzero means do not delete tempfiles -- for debugging. */ 
    123 int keep_tempfiles; 
    124  
    125105/* Forward declarations of functions in this file. */ 
    126106void decode_command (int argc, char **argv); 
    127107void sort_in_core (char *infile, int total, char *outfile); 
    128 void sort_offline (char *infile, off_t total, char *outfile); 
    129108char **parsefile (char *filename, char **nextline, char *data, long int size); 
    130109char *find_field (struct keyfield *keyfield, char *str, long int *lengthptr); 
    131110char *find_pos (char *str, int words, int chars, int ignore_blanks); 
     
    137116                   long int length1, long int pos1, char *start2, 
    138117                   long int length2, long int pos2); 
    139118int compare_full (const void *, const void *); 
    140 long readline (struct linebuffer *linebuffer, FILE *stream); 
    141 int merge_files (char **infiles, int nfiles, char *outfile); 
    142 int merge_direct (char **infiles, int nfiles, char *outfile); 
    143119void pfatal_with_name (const char *name); 
    144120void fatal (const char *format, const char *arg); 
    145121void error (const char *format, const char *arg); 
    146122void *xmalloc (), *xrealloc (); 
    147 char *concat (char *s1, char *s2); 
    148 void flush_tempfiles (int to_count); 
     123static char *concat3 (const char *, const char *, const char *); 
    149124  
    150 #define MAX_IN_CORE_SORT 500000 
    151  
    152125int 
    153126main (int argc, char **argv) 
    154127{ 
    155128  int i; 
    156129 
    157   tempcount = 0; 
    158   last_deleted_tempcount = 0; 
    159  
    160130#ifdef HAVE_SETLOCALE 
    161131  /* Set locale via LC_ALL.  */ 
    162132  setlocale (LC_ALL, ""); 
     
    220190 
    221191      outfile = outfiles[i]; 
    222192      if (!outfile) 
    223         outfile = concat (infiles[i], "s"); 
     193        outfile = concat3 (infiles[i], "s", ""); 
    224194 
    225195      need_initials = 0; 
    226196      first_initial = '\0'; 
    227197 
    228       if (ptr < MAX_IN_CORE_SORT) 
    229         /* Sort a small amount of data. */ 
    230         sort_in_core (infiles[i], (int)ptr, outfile); 
    231       else 
    232         sort_offline (infiles[i], ptr, outfile); 
     198      if (ptr != (int)ptr) 
     199        { 
     200          fprintf (stderr, "%s: %s: file too large\n", program_name, 
     201                   infiles[i]); 
     202          xexit (1); 
     203        } 
     204      sort_in_core (infiles[i], (int)ptr, outfile); 
    233205    } 
    234206 
    235   flush_tempfiles (tempcount); 
    236207  xexit (0); 
    237208  return 0; /* Avoid bogus warnings.  */ 
    238209} 
     
    250221TEXINDEX_OPTION texindex_options[] = { 
    251222  { "--help", "-h", (int *)NULL, 0, (char *)NULL, 
    252223      N_("display this help and exit") }, 
    253   { "--keep", "-k", &keep_tempfiles, 1, (char *)NULL, 
    254       N_("keep temporary files around after processing") }, 
    255   { "--no-keep", 0, &keep_tempfiles, 0, (char *)NULL, 
    256       N_("do not keep temporary files around after processing (default)") }, 
    257224  { "--output", "-o", (int *)NULL, 0, "FILE", 
    258225      N_("send output to FILE") }, 
    259226  { "--version", (char *)NULL, (int *)NULL, 0, (char *)NULL, 
     
    308275  char **ip; 
    309276  char **op; 
    310277 
    311   /* Store default values into parameter variables. */ 
    312  
    313   tempdir = getenv ("TMPDIR"); 
    314   if (tempdir == NULL) 
    315     tempdir = getenv ("TEMP"); 
    316   if (tempdir == NULL) 
    317     tempdir = getenv ("TMP"); 
    318   if (tempdir == NULL) 
    319     tempdir = DEFAULT_TMPDIR; 
    320   else 
    321     tempdir = concat (tempdir, "/"); 
    322  
    323   keep_tempfiles = 0; 
    324  
    325278  /* Allocate ARGC input files, which must be enough.  */ 
    326279 
    327280  infiles = (char **) xmalloc (argc * sizeof (char *)); 
     
    349302          else if ((strcmp (arg, "--keep") == 0) || 
    350303                   (strcmp (arg, "-k") == 0)) 
    351304            { 
    352               keep_tempfiles = 1; 
     305              /* Ignore, for backward compatibility */ 
    353306            } 
    354307          else if ((strcmp (arg, "--help") == 0) || 
    355308                   (strcmp (arg, "-h") == 0)) 
     
    385338    usage (1); 
    386339} 
    387340  
    388 /* Return a name for temporary file COUNT. */ 
    389  
    390 static char * 
    391 maketempname (int count) 
    392 { 
    393   static char *tempbase = NULL; 
    394   char tempsuffix[10]; 
    395  
    396   if (!tempbase) 
    397     { 
    398       int fd; 
    399       tempbase = concat (tempdir, "txidxXXXXXX"); 
    400  
    401       fd = mkstemp (tempbase); 
    402       if (fd == -1) 
    403         pfatal_with_name (tempbase); 
    404     } 
    405  
    406   sprintf (tempsuffix, ".%d", count); 
    407   return concat (tempbase, tempsuffix); 
    408 } 
    409  
    410  
    411 /* Delete all temporary files up to TO_COUNT. */ 
    412  
    413 void 
    414 flush_tempfiles (int to_count) 
    415 { 
    416   if (keep_tempfiles) 
    417     return; 
    418   while (last_deleted_tempcount < to_count) 
    419     unlink (maketempname (++last_deleted_tempcount)); 
    420 } 
    421  
    422   
    423341/* Compare LINE1 and LINE2 according to the specified set of keyfields. */ 
    424342 
    425343int 
     
    802720    } 
    803721} 
    804722  
    805 /* A `struct linebuffer' is a structure which holds a line of text. 
    806    `readline' reads a line from a stream into a linebuffer 
    807    and works regardless of the length of the line.  */ 
    808  
    809 struct linebuffer 
    810 { 
    811   long size; 
    812   char *buffer; 
    813 }; 
    814  
    815 /* Initialize LINEBUFFER for use. */ 
    816  
    817 void 
    818 initbuffer (struct linebuffer *linebuffer) 
    819 { 
    820   linebuffer->size = 200; 
    821   linebuffer->buffer = (char *) xmalloc (200); 
    822 } 
    823  
    824 /* Read a line of text from STREAM into LINEBUFFER. 
    825    Return the length of the line.  */ 
    826  
    827 long 
    828 readline (struct linebuffer *linebuffer, FILE *stream) 
    829 { 
    830   char *buffer = linebuffer->buffer; 
    831   char *p = linebuffer->buffer; 
    832   char *end = p + linebuffer->size; 
    833  
    834   while (1) 
    835     { 
    836       int c = getc (stream); 
    837       if (p == end) 
    838         { 
    839           buffer = (char *) xrealloc (buffer, linebuffer->size *= 2); 
    840           p += buffer - linebuffer->buffer; 
    841           end += buffer - linebuffer->buffer; 
    842           linebuffer->buffer = buffer; 
    843         } 
    844       if (c < 0 || c == '\n') 
    845         { 
    846           *p = 0; 
    847           break; 
    848         } 
    849       *p++ = c; 
    850     } 
    851  
    852   return p - buffer; 
    853 } 
    854   
    855 /* Sort an input file too big to sort in core.  */ 
    856  
    857 void 
    858 sort_offline (char *infile, off_t total, char *outfile) 
    859 { 
    860   /* More than enough. */ 
    861   int ntemps = 2 * (total + MAX_IN_CORE_SORT - 1) / MAX_IN_CORE_SORT; 
    862   char **tempfiles = (char **) xmalloc (ntemps * sizeof (char *)); 
    863   FILE *istream = fopen (infile, "r"); 
    864   int i; 
    865   struct linebuffer lb; 
    866   long linelength; 
    867   int failure = 0; 
    868  
    869   initbuffer (&lb); 
    870  
    871   /* Read in one line of input data.  */ 
    872  
    873   linelength = readline (&lb, istream); 
    874  
    875   if (lb.buffer[0] != '\\' && lb.buffer[0] != '@') 
    876     { 
    877       error (_("%s: not a texinfo index file"), infile); 
    878       return; 
    879     } 
    880  
    881   /* Split up the input into `ntemps' temporary files, or maybe fewer, 
    882      and put the new files' names into `tempfiles' */ 
    883  
    884   for (i = 0; i < ntemps; i++) 
    885     { 
    886       char *outname = maketempname (++tempcount); 
    887       FILE *ostream = fopen (outname, "w"); 
    888       long tempsize = 0; 
    889  
    890       if (!ostream) 
    891         pfatal_with_name (outname); 
    892       tempfiles[i] = outname; 
    893  
    894       /* Copy lines into this temp file as long as it does not make file 
    895          "too big" or until there are no more lines.  */ 
    896  
    897       while (tempsize + linelength + 1 <= MAX_IN_CORE_SORT) 
    898         { 
    899           tempsize += linelength + 1; 
    900           fputs (lb.buffer, ostream); 
    901           putc ('\n', ostream); 
    902  
    903           /* Read another line of input data.  */ 
    904  
    905           linelength = readline (&lb, istream); 
    906           if (!linelength && feof (istream)) 
    907             break; 
    908  
    909           if (lb.buffer[0] != '\\' && lb.buffer[0] != '@') 
    910             { 
    911               error (_("%s: not a texinfo index file"), infile); 
    912               failure = 1; 
    913               goto fail; 
    914             } 
    915         } 
    916       fclose (ostream); 
    917       if (feof (istream)) 
    918         break; 
    919     } 
    920  
    921   free (lb.buffer); 
    922  
    923 fail: 
    924   /* Record number of temp files we actually needed.  */ 
    925  
    926   ntemps = i; 
    927  
    928   /* Sort each tempfile into another tempfile. 
    929     Delete the first set of tempfiles and put the names of the second 
    930     into `tempfiles'. */ 
    931  
    932   for (i = 0; i < ntemps; i++) 
    933     { 
    934       char *newtemp = maketempname (++tempcount); 
    935       sort_in_core (tempfiles[i], MAX_IN_CORE_SORT, newtemp); 
    936       if (!keep_tempfiles) 
    937         unlink (tempfiles[i]); 
    938       tempfiles[i] = newtemp; 
    939     } 
    940  
    941   if (failure) 
    942     return; 
    943  
    944   /* Merge the tempfiles together and indexify. */ 
    945  
    946   merge_files (tempfiles, ntemps, outfile); 
    947 } 
    948   
    949723/* Sort INFILE, whose size is TOTAL, 
    950724   assuming that is small enough to be done in-core, 
    951725   then indexify it and send the output to OUTFILE (or to stdout).  */ 
     
    13491123 
    13501124  for (next_line = linearray; next_line != stop_line; next_line++) 
    13511125    { 
    1352       /* If -u was specified, output the line only if distinct from 
    1353          previous one.  */ 
     1126      /* Output the line only if distinct from previous one.  */ 
    13541127      if (next_line == linearray 
    13551128      /* Compare previous line with this one, using only the 
    13561129         explicitly specd keyfields. */ 
     
    13701143  finish_index (ostream); 
    13711144} 
    13721145  
    1373 /* Assume (and optionally verify) that each input file is sorted; 
    1374    merge them and output the result. 
    1375    Returns nonzero if any input file fails to be sorted. 
    1376  
    1377    This is the high-level interface that can handle an unlimited 
    1378    number of files.  */ 
    1379  
    1380 #define MAX_DIRECT_MERGE 10 
    1381  
    1382 int 
    1383 merge_files (char **infiles, int nfiles, char *outfile) 
    1384 { 
    1385   char **tempfiles; 
    1386   int ntemps; 
    1387   int i; 
    1388   int value = 0; 
    1389   int start_tempcount = tempcount; 
    1390  
    1391   if (nfiles <= MAX_DIRECT_MERGE) 
    1392     return merge_direct (infiles, nfiles, outfile); 
    1393  
    1394   /* Merge groups of MAX_DIRECT_MERGE input files at a time, 
    1395      making a temporary file to hold each group's result.  */ 
    1396  
    1397   ntemps = (nfiles + MAX_DIRECT_MERGE - 1) / MAX_DIRECT_MERGE; 
    1398   tempfiles = (char **) xmalloc (ntemps * sizeof (char *)); 
    1399   for (i = 0; i < ntemps; i++) 
    1400     { 
    1401       int nf = MAX_DIRECT_MERGE; 
    1402       if (i + 1 == ntemps) 
    1403         nf = nfiles - i * MAX_DIRECT_MERGE; 
    1404       tempfiles[i] = maketempname (++tempcount); 
    1405       value |= merge_direct (&infiles[i * MAX_DIRECT_MERGE], nf, tempfiles[i]); 
    1406     } 
    1407  
    1408   /* All temporary files that existed before are no longer needed 
    1409      since their contents have been merged into our new tempfiles. 
    1410      So delete them.  */ 
    1411   flush_tempfiles (start_tempcount); 
    1412  
    1413   /* Now merge the temporary files we created.  */ 
    1414  
    1415   merge_files (tempfiles, ntemps, outfile); 
    1416  
    1417   free (tempfiles); 
    1418  
    1419   return value; 
    1420 } 
    1421   
    1422 /* Assume (and optionally verify) that each input file is sorted; 
    1423    merge them and output the result. 
    1424    Returns nonzero if any input file fails to be sorted. 
    1425  
    1426    This version of merging will not work if the number of 
    1427    input files gets too high.  Higher level functions 
    1428    use it only with a bounded number of input files.  */ 
    1429  
    1430 int 
    1431 merge_direct (char **infiles, int nfiles, char *outfile) 
    1432 { 
    1433   struct linebuffer *lb1, *lb2; 
    1434   struct linebuffer **thisline, **prevline; 
    1435   FILE **streams; 
    1436   int i; 
    1437   int nleft; 
    1438   int lossage = 0; 
    1439   int *file_lossage; 
    1440   struct linebuffer *prev_out = 0; 
    1441   FILE *ostream = stdout; 
    1442  
    1443   if (outfile) 
    1444     { 
    1445       ostream = fopen (outfile, "w"); 
    1446     } 
    1447   if (!ostream) 
    1448     pfatal_with_name (outfile); 
    1449  
    1450   init_index (); 
    1451  
    1452   if (nfiles == 0) 
    1453     { 
    1454       if (outfile) 
    1455         fclose (ostream); 
    1456       return 0; 
    1457     } 
    1458  
    1459   /* For each file, make two line buffers.  Also, for each file, there 
    1460      is an element of `thisline' which points at any time to one of the 
    1461      file's two buffers, and an element of `prevline' which points to 
    1462      the other buffer.  `thisline' is supposed to point to the next 
    1463      available line from the file, while `prevline' holds the last file 
    1464      line used, which is remembered so that we can verify that the file 
    1465      is properly sorted. */ 
    1466  
    1467   /* lb1 and lb2 contain one buffer each per file. */ 
    1468   lb1 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer)); 
    1469   lb2 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer)); 
    1470  
    1471   /* thisline[i] points to the linebuffer holding the next available 
    1472      line in file i, or is zero if there are no lines left in that file.  */ 
    1473   thisline = (struct linebuffer **) 
    1474     xmalloc (nfiles * sizeof (struct linebuffer *)); 
    1475   /* prevline[i] points to the linebuffer holding the last used line 
    1476      from file i.  This is just for verifying that file i is properly 
    1477      sorted.  */ 
    1478   prevline = (struct linebuffer **) 
    1479     xmalloc (nfiles * sizeof (struct linebuffer *)); 
    1480   /* streams[i] holds the input stream for file i.  */ 
    1481   streams = (FILE **) xmalloc (nfiles * sizeof (FILE *)); 
    1482   /* file_lossage[i] is nonzero if we already know file i is not 
    1483      properly sorted.  */ 
    1484   file_lossage = (int *) xmalloc (nfiles * sizeof (int)); 
    1485  
    1486   /* Allocate and initialize all that storage. */ 
    1487  
    1488   for (i = 0; i < nfiles; i++) 
    1489     { 
    1490       initbuffer (&lb1[i]); 
    1491       initbuffer (&lb2[i]); 
    1492       thisline[i] = &lb1[i]; 
    1493       prevline[i] = &lb2[i]; 
    1494       file_lossage[i] = 0; 
    1495       streams[i] = fopen (infiles[i], "r"); 
    1496       if (!streams[i]) 
    1497         pfatal_with_name (infiles[i]); 
    1498  
    1499       readline (thisline[i], streams[i]); 
    1500     } 
    1501  
    1502   /* Keep count of number of files not at eof. */ 
    1503   nleft = nfiles; 
    1504  
    1505   while (nleft) 
    1506     { 
    1507       struct linebuffer *best = 0; 
    1508       struct linebuffer *exch; 
    1509       int bestfile = -1; 
    1510       int i; 
    1511  
    1512       /* Look at the next avail line of each file; choose the least one.  */ 
    1513  
    1514       for (i = 0; i < nfiles; i++) 
    1515         { 
    1516           if (thisline[i] && 
    1517               (!best || 
    1518                0 < compare_general (best->buffer, thisline[i]->buffer, 
    1519                                  (long) bestfile, (long) i, num_keyfields))) 
    1520             { 
    1521               best = thisline[i]; 
    1522               bestfile = i; 
    1523             } 
    1524         } 
    1525  
    1526       /* Output that line, unless it matches the previous one and we 
    1527          don't want duplicates. */ 
    1528  
    1529       if (!(prev_out && 
    1530             !compare_general (prev_out->buffer, 
    1531                               best->buffer, 0L, 1L, num_keyfields - 1))) 
    1532         indexify (best->buffer, ostream); 
    1533       prev_out = best; 
    1534  
    1535       /* Now make the line the previous of its file, and fetch a new 
    1536          line from that file.  */ 
    1537  
    1538       exch = prevline[bestfile]; 
    1539       prevline[bestfile] = thisline[bestfile]; 
    1540       thisline[bestfile] = exch; 
    1541  
    1542       while (1) 
    1543         { 
    1544           /* If the file has no more, mark it empty. */ 
    1545  
    1546           if (feof (streams[bestfile])) 
    1547             { 
    1548               thisline[bestfile] = 0; 
    1549               /* Update the number of files still not empty. */ 
    1550               nleft--; 
    1551               break; 
    1552             } 
    1553           readline (thisline[bestfile], streams[bestfile]); 
    1554           if (thisline[bestfile]->buffer[0] || !feof (streams[bestfile])) 
    1555             break; 
    1556         } 
    1557     } 
    1558  
    1559   finish_index (ostream); 
    1560  
    1561   /* Free all storage and close all input streams. */ 
    1562  
    1563   for (i = 0; i < nfiles; i++) 
    1564     { 
    1565       fclose (streams[i]); 
    1566       free (lb1[i].buffer); 
    1567       free (lb2[i].buffer); 
    1568     } 
    1569   free (file_lossage); 
    1570   free (lb1); 
    1571   free (lb2); 
    1572   free (thisline); 
    1573   free (prevline); 
    1574   free (streams); 
    1575  
    1576   if (outfile) 
    1577     fclose (ostream); 
    1578  
    1579   return lossage; 
    1580 } 
    1581   
    15821146/* Print error message and exit.  */ 
    15831147 
    15841148void 
     
    16131177} 
    16141178 
    16151179  
    1616 /* Return a newly-allocated string concatenating S1 and S2.  */ 
     1180/* Return a newly-allocated string concatenating S1, S2, and S3.  */ 
    16171181 
    1618 char * 
    1619 concat (char *s1, char *s2
     1182static char * 
     1183concat3 (const char *s1, const char *s2, const char *s3
    16201184{ 
    1621   int len1 = strlen (s1), len2 = strlen (s2)
    1622   char *result = (char *) xmalloc (len1 + len2 + 1); 
     1185  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3)
     1186  char *result = (char *) xmalloc (len1 + len2 + len3 + 1); 
    16231187 
    16241188  strcpy (result, s1); 
    16251189  strcpy (result + len1, s2); 
    1626   *(result + len1 + len2) = 0; 
     1190  strcpy (result + len1 + len2, s3); 
     1191  *(result + len1 + len2 + len3) = 0; 
    16271192 
    16281193  return result; 
    16291194} 
Note: See TracBrowser for help on using the browser.