home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD2.bin
/
bbs
/
gnu
/
gawk-2.15.5-src.lha
/
gawk-2.15.5
/
support
/
texindex.c
next >
Wrap
C/C++ Source or Header
|
1991-10-29
|
38KB
|
1,606 lines
/* Prepare Tex index dribble output into an actual index.
Copyright (C) 1987 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, 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.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#ifdef VMS
#ifndef VAX11C
#define noshare
#endif
#include <perror.h>
#include <file.h>
#define EXIT_SUCCESS ((1 << 28) | 1)
#define EXIT_FATAL ((1 << 28) | 4)
#define unlink delete
#define tell(fd) lseek(fd, 0L, 1)
#else /* Not VMS */
#ifdef USG
#include <sys/types.h>
#include <sys/fcntl.h>
#endif
#include <sys/file.h>
#define EXIT_SUCCESS 0
#define EXIT_FATAL 1
#endif /* Not VMS */
#ifndef L_XTND
#define L_XTND 2
#endif
#ifdef VMS
extern noshare int sys_nerr;
extern noshare char *sys_errlist[];
#else
extern int sys_nerr;
extern char *sys_errlist[];
#endif
/* When sorting in core, this structure describes one line
and the position and length of its first keyfield. */
struct lineinfo
{
char *text; /* The actual text of the line */
union
{ /* The start of the key (for textual comparison) */
char *text;
long number; /* or the numeric value (for numeric comparison) */
} key;
long keylen; /* Length of key field */
};
/* This structure describes a field to use as a sort key */
struct keyfield
{
int startwords; /* # words to skip */
int startchars; /* and # additional chars to skip, to start of field */
int endwords; /* similar, from beg (or end) of line, to find end of field */
int endchars;
char ignore_blanks; /* Ignore spaces and tabs within the field */
char fold_case; /* Convert upper case to lower before comparing */
char reverse; /* Compare in reverse order */
char numeric; /* Parse text as an integer and compare the integers */
char positional; /* Sort according to position within the file */
char braced; /* Count balanced-braced groupings as fields */
};
/* Vector of keyfields to use */
struct keyfield keyfields[3];
/* Number of keyfields stored in that vector. */
int num_keyfields = 3;
/* Vector of input file names, terminated with a zero (null pointer) */
char **infiles;
/* Vector of corresponding output file names, or zero meaning default it */
char **outfiles;
/* Length of `infiles' */
int num_infiles;
/* Pointer to the array of pointers to lines being sorted */
char **linearray;
/* The allocated length of `linearray'. */
long nlines;
/* Directory to use for temporary files. On Unix, it ends with a slash. */
char *tempdir;
/* Start of filename to use for temporary files. */
char *tempbase;
/* Number of last temporary file. */
int tempcount;
/* Number of last temporary file already deleted.
Temporary files are deleted by `flush_tempfiles' in order of creation. */
int last_deleted_tempcount;
/* During in-core sort, this points to the base of the data block
which contains all the lines of data. */
char *text_base;
/* Additional command switches */
int keep_tempfiles; /* Nonzero means do not delete tempfiles -- for debugging */
/* Forward declarations of functions in this file */
void decode_command ();
void sort_in_core ();
void sort_offline ();
char **parsefile ();
char *find_field ();
char *find_pos ();
long find_value ();
char *find_braced_pos ();
char *find_braced_end ();
void writelines ();
int compare_full ();
long readline ();
int merge_files ();
int merge_direct ();
char *concat ();
char *maketempname ();
void flush_tempfiles ();
char *tempcopy ();
extern char *mktemp ();
#define MAX_IN_CORE_SORT 500000
int
main (argc, argv)
int argc;
char **argv;
{
int i;
tempcount = 0;
last_deleted_tempcount = 0;
/* Describe the kind of sorting to do. */
/* The first keyfield uses the first braced field and folds case */
keyfields[0].braced = 1;
keyfields[0].fold_case = 1;
keyfields[0].endwords = -1;
keyfields[0].endchars = -1;
/* The second keyfield uses the second braced field, numerically */
keyfields[1].braced = 1;
keyfields[1].numeric = 1;
keyfields[1].startwords = 1;
keyfields[1].endwords = -1;
keyfields[1].endchars = -1;
/* The third keyfield (which is ignored while discarding duplicates)
compares the whole line */
keyfields[2].endwords = -1;
keyfields[2].endchars = -1;
decode_command (argc, argv);
tempbase = mktemp (concat ("txiXXXXXX", "", ""));
/* Process input files completely, one by one. */
for (i = 0; i < num_infiles; i++)
{
int desc;
long ptr;
char *outfile;
char *p;
desc = open (infiles[i], 0, 0);
if (desc < 0) pfatal_with_name (infiles[i]);
lseek (desc, 0, L_XTND);
ptr = tell (desc);
close (desc);
outfile = outfiles[i];
if (!outfile)
{
outfile = concat (infiles[i], "s", "");
}
if (ptr < MAX_IN_CORE_SORT)
/* Sort a small amount of data */
sort_in_core (infiles[i], ptr, outfile);
else
sort_offline (infiles[i], ptr, outfile);
}
flush_tempfiles (tempcount);
exit (EXIT_SUCCESS);
}
/* This page decodes the command line arguments to set the parameter variables
and set up the vector of keyfields and the vector of input files */
void
decode_command (argc, argv)
int argc;
char **argv;
{
int i;
char **ip;
char **op;
/* Store default values into parameter variables */
#ifdef VMS
tempdir = "sys$scratch:";
#else
tempdir = "/tmp/";
#endif
keep_tempfiles = 0;
/* Allocate argc input files, which must be enough. */
infiles = (char **) xmalloc (argc * sizeof (char *));
outfiles = (char **) xmalloc (argc * sizeof (char *));
ip = infiles;
op = outfiles;
/* First find all switches that control the default kind-of-sort */
for (i = 1; i < argc; i++)
{
int tem = classify_arg (argv[i]);
char c;
char *p;
if (tem <= 0)
{
*ip++ = argv[i];
*op++ = 0;
continue;
}
if (tem > 1)
{
if (i + 1 == argc)
fatal ("switch %s given with no argument following it", argv[i]);
else if (!strcmp (argv[i], "-T"))
tempdir = argv[i + 1];
else if (!strcmp (argv[i], "-o"))
*(op - 1) = argv[i + 1];
i += tem - 1;
continue;
}
p = &argv[i][1];
while (c = *p++)
switch (c)
{
case 'k':
keep_tempfiles = 1;
break;
default:
fatal ("invalid command switch %c", c);
}
switchdone: ;
}
/* Record number of keyfields, terminate list of filenames */
num_infiles = ip - infiles;
*ip = 0;
}
/* Return 0 for an argument that is not a switch;
for a switch, return 1 plus the number of following arguments that the switch swallows.
*/
int
classify_arg (arg)
char *arg;
{
if (!strcmp (arg, "-T") || !strcmp (arg, "-o"))
return 2;
if (arg[0] == '-')
return 1;
return 0;
}
/* Create a name for a temporary file */
char *
maketempname (count)
int count;
{
char tempsuffix[10];
sprintf (tempsuffix, "%d", count);
return concat (tempdir, tempbase, tempsuffix);
}
/* Delete all temporary files up to the specified count */
void
flush_tempfiles (to_count)
int to_count;
{
if (keep_tempfiles) return;
while (last_deleted_tempcount < to_count)
unlink (maketempname (++last_deleted_tempcount));
}
/* Copy an input file into a temporary file, and return the temporary file name */
#define BUFSIZE 1024
char *
tempcopy (idesc)
int idesc;
{
char *outfile = maketempname (++tempcount);
int odesc;
char buffer[BUFSIZE];
odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
if (odesc < 0) pfatal_with_name (outfile);
while