/*
*
* This file is part of
* MakeIndex - A formatter and format independent index processor
*
* Copyright (C) 1989 by Chen & Harrison International Systems, Inc.
* Copyright (C) 1988 by Olivetti Research Center
* Copyright (C) 1987 by Regents of the University of California
*
* Author:
* Pehong Chen
* Chen & Harrison International Systems, Inc.
* Palo Alto, California
* USA
* (phc@renoir.berkeley.edu or chen@orc.olivetti.com)
*
* Contributors:
* Please refer to the CONTRIB file that comes with this release
* for a list of people who have contributed to this and/or previous
* release(s) of MakeIndex.
*
* All rights reserved by the copyright holders. See the copyright
* notice distributed with this software for a complete description of
* the conditions under which it is made available.
*
*/
#define MKIND_C 1
#include "mkind.h"
#undef MKIND_C
int letter_ordering = FALSE;
int compress_blanks = FALSE;
int merge_page = TRUE;
int init_page = FALSE;
int even_odd = -1;
int verbose = TRUE;
int german_sort = FALSE;
int fn_no = -1; /* total number of files */
int idx_dot = TRUE; /* flag which shows dot in ilg being
* active */
int idx_tt = 0; /* total entry count (all files) */
int idx_et = 0; /* erroneous entry count (all files) */
int idx_gt = 0; /* good entry count (all files) */
FIELD_PTR *idx_key;
FILE *log_fp;
FILE *sty_fp;
FILE *idx_fp;
FILE *ind_fp;
FILE *ilg_fp;
#if OS_BS2000
FILE *widx_fp;
char widx_fn[STRING_MAX + 5];
#endif /* OS_BS2000 */
char *pgm_fn;
char sty_fn[LINE_MAX];
char *idx_fn;
char ind[STRING_MAX];
char *ind_fn;
char ilg[STRING_MAX];
char *ilg_fn;
char pageno[NUMBER_MAX];
static char log_fn[STRING_MAX];
static char base[STRING_MAX];
static int need_version = TRUE;
static void check_all ARGS((char *fn,int ind_given,int ilg_given,
int log_given));
static void check_idx ARGS((char *fn,int open_fn));
static void find_pageno ARGS((void));
static void open_sty ARGS((char *fn));
static void prepare_idx ARGS((void));
static void process_idx ARGS((char * *fn,int use_stdin,int sty_given,
int ind_given,int ilg_given,int log_given));
#if OS_PCDOS
#if IBM_PC_TURBO
unsigned _stklen = 0xf000; /* Turbo C ignores size set in
.exe file by LINK or EXEMOD,
sigh... */
#endif /* IBM_PC_TURBO */
#endif /* OS_PCDOS */
#if OS_ATARI
long _stksize = 20000L; /* make the stack larger than 2KB */
/* size must be given */
#endif /* OS_ATARI */
#ifdef DEBUG
long totmem = 0L; /* for debugging memory usage */
#endif /* DEBUG */
int
#if STDC
main(int argc, char *argv[])
#else
main(argc, argv)
int argc;
char *argv[];
#endif
{
char *fns[ARRAY_MAX];
char *ap;
int use_stdin = FALSE;
int sty_given = FALSE;
int ind_given = FALSE;
int ilg_given = FALSE;
int log_given = FALSE;
/* determine program name */
#if (OS_ATARI | OS_VAXVMS | OS_BS2000 | OS_MVSXA | OS_VMCMS)
pgm_fn = "MakeIndex"; /* Use symbolic name on some systems */
#else
pgm_fn = strrchr(*argv, DIR_DELIM);
if (pgm_fn == NULL)
pgm_fn = *argv;
else
pgm_fn++;
#if OS_PCDOS
{
register char *ext = pgm_fn + strlen(pgm_fn)-4;
if ( *ext == '.' )
*ext = NUL; /* cut off ".EXE" */
}
(void)strlwr(pgm_fn); /* lower program name */
#endif /* OS_PCDOS */
#endif /* OS_VAXVMS | OS_BS2000 | OS_MVSXA */
/* process command line options */
while (--argc > 0) {
if (**++argv == SW_PREFIX) {
if (*(*argv + 1) == NUL)
break;
for (ap = ++*argv; *ap != NUL; ap++)
#if (OS_BS2000 | OS_MVSXA | OS_VAXVMS)
switch (tolower(*ap)) {
#else
switch (*ap) {
#endif /* (OS_BS2000 | OS_MVSXA | OS_VAXVMS) */
/* use standard input */
case 'i':
use_stdin = TRUE;
break;
/* enable letter ordering */
case 'l':
letter_ordering = TRUE;
break;
/* disable range merge */
case 'r':
merge_page = FALSE;
break;
/* supress progress message -- quiet mode */
case 'q':
verbose = FALSE;
break;
/* compress blanks */
case 'c':
compress_blanks = TRUE;
break;
/* style file */
case 's':
argc--;
if (argc <= 0)
FATAL("Expected -s <stylefile>\n","");
open_sty(*++argv);
sty_given = TRUE;
break;
/* output index file name */
case 'o':
argc--;
if (argc <= 0)
FATAL("Expected -o <ind>\n","");
ind_fn = *++argv;
ind_given = TRUE;
break;
/* transcript file name */
case 't':
argc--;
if (argc <= 0)
FATAL("Expected -t <logfile>\n","");
ilg_fn = *++argv;
ilg_given = TRUE;
break;
/* initial page */
case 'p':
argc--;
if (argc <= 0)
FATAL("Expected -p <num>\n","");
strcpy(pageno, *++argv);
init_page = TRUE;
if (STREQ(pageno, EVEN)) {
log_given = TRUE;
even_odd = 2;
} else if (STREQ(pageno, ODD)) {
log_given = TRUE;
even_odd = 1;
} else if (STREQ(pageno, ANY)) {
log_given = TRUE;
even_odd = 0;
}
break;
/* enable german sort */
case 'g':
german_sort = TRUE;
break;
/* bad option */
default:
FATAL("Unknown option -%c.\n", *ap);
break;
}
} else {
if (fn_no < ARRAY_MAX) {
check_idx(*argv, FALSE);
fns[++fn_no] = *argv;
} else {
FATAL("Too many input files (max %d).\n", ARRAY_MAX);
}
}
}
/* changes for 2.12 (May 20, 1993) by Julian Reschke (jr@ms.maus.de):
if only one input file and no explicit style file was given */
#if OS_BS2000
/* not supported */
#else
if (fn_no == 0 && !sty_given)
{
char tmp[STRING_MAX + 5];
/* base set by last call to check_idx */
sprintf (tmp, "%s%s", base, INDEX_STY);
if (0 == access(tmp, R_OK)) {
open_sty (tmp);
sty_given = TRUE;
}
}
#endif
process_idx(fns, use_stdin, sty_given, ind_given, ilg_given, log_given);
idx_gt = idx_tt - idx_et;
ALL_DONE;
if (idx_gt > 0) {
prepare_idx();
sort_idx();
gen_ind();
MESSAGE("Output written in %s.\n", ind_fn);
} else
MESSAGE("Nothing written in %s.\n", ind_fn);
MESSAGE("Transcript written in %s.\n", ilg_fn);
CLOSE(ind_fp);
CLOSE(ilg_fp);
EXIT(0);
return (0); /* never executed--avoids complaints */
/* about no return value */
}
static void
prepare_idx(VOID_ARG)
{
NODE_PTR ptr = head;
int i = 0;
#ifdef DEBUG
totmem += idx_gt * sizeof(FIELD_PTR);
(void)fprintf(stderr,"prepare_idx(): calloc(%d,%d)\ttotmem = %ld\n",
idx_gt,sizeof(FIELD_PTR),totmem);
#endif /* DEBUG */
if (head == (NODE_PTR)NULL)
FATAL("No valid index entries collected.\n", "");
if ((idx_key = (FIELD_PTR *) calloc(idx_gt, sizeof(FIELD_PTR))) == NULL) {
FATAL("Not enough core...abort.\n", "");
}
for (i = 0; i < idx_gt; i++) {
idx_key[i] = &(ptr->data);
ptr = ptr->next;
}
}
static void
#if STDC
process_idx(char *fn[], int use_stdin, int sty_given, int ind_given,
int ilg_given, int log_given)
#else
process_idx(fn, use_stdin, sty_given, ind_given, ilg_given, log_given)
char *fn[];
int use_stdin;
int sty_given;
int ind_given;
int ilg_given;
int log_given;
#endif
{
int i;
if (fn_no == -1)
/* use stdin if no input files specified */
use_stdin = TRUE;
else {
check_all(fn[0], ind_given, ilg_given, log_given);
PUT_VERSION;
if (sty_given)
scan_sty();
if (german_sort && (idx_quote == '"'))
FATAL("Option -g invalid, quote character must be different from '%c'.\n",
'"');
scan_idx();
ind_given = TRUE;
ilg_given = TRUE;
for (i = 1; i <= fn_no; i++) {
check_idx(fn[i], TRUE);
scan_idx();
}
}
if (use_stdin) {
idx_fn = "stdin";
idx_fp = stdin;
if (ind_given) {
if (!ind_fp && ((ind_fp = OPEN_OUT(ind_fn)) == NULL))
FATAL("Can't create output index file %s.\n", ind_fn);
} else {
ind_fn = "stdout";
ind_fp = stdout;
}
if (ilg_given) {
if (!ilg_fp && ((ilg_fp = OPEN_OUT(ilg_fn)) == NULL))
FATAL("Can't create transcript file %s.\n", ilg_fn);
} else {
ilg_fn = "stderr";
ilg_fp = stderr;
verbose = FALSE;
}
if ((fn_no == -1) && (sty_given))
scan_sty();
if (german_sort && (idx_quote == '"'))
FATAL("Option -g ignored, quote character must be different from '%c'.\n",
'"');
if (need_version) {
PUT_VERSION;
}
scan_idx();
fn_no++;
}
}
static void
#if STDC
check_idx(char *fn, int open_fn)
#else
check_idx(fn, open_fn)
char *fn;
int open_fn;
#endif
{
char *ptr = fn;
char *ext;
int with_ext = FALSE;
int i = 0;
#if OS_BS2000
char message[256]; /* error message */
char arg[8]; /* argument for sprintf() */
ext = strrchr(fn, EXT_DELIM);
if ((ext != NULL) &&
(((*fn == CATID) && (*(fn + 3) != DIR_DELIM)) ||
(((*fn == DIR_DELIM) || (*fn == CATID)) &&
(strchr(fn, EXT_DELIM) < ext)))) {
#else
ext = strrchr(fn, EXT_DELIM);
if ((ext != NULL) && (ext != fn) && (*(ext + 1) != DIR_DELIM)) {
#endif /* OS_BS2000 */
with_ext = TRUE;
while ((ptr != ext) && (i < STRING_MAX))
base[i++] = *ptr++;
} else
while ((*ptr != NUL) && (i < STRING_MAX))
base[i++] = *ptr++;
if (i < STRING_MAX)
base[i] = NUL;
else
FATAL2("Index file name %s too long (max %d).\n",
base, STRING_MAX);
idx_fn = fn;
#if OS_BS2000 /* Search both on HOME-PVS and
* WORK-PVS */
sprintf(widx_fn, "%s%s", WORK, idx_fn);
if (((((idx_fp = OPEN_IN(idx_fn)) == NULL) && open_fn) ||
!(open_fn || idx_fp)) &&
((((widx_fp = OPEN_IN(widx_fn)) == NULL) && open_fn) ||
!(open_fn || widx_fp)))
if (with_ext) {
sprintf(message, "Input index file %s%%s not found.\n",
(strchr(idx_fn, ':') || (strlen(WORK) == 0)) ?
NIL : "<" WORK ">");
FATAL(message, idx_fn);
} else {
#ifdef DEBUG
totmem += STRING_MAX;
(void)fprintf(stderr,"check_idx()-1: malloc(%d)\ttotmem = %ld\n",
STRING_MAX,totmem);
#endif /* DEBUG */
if ((idx_fn = (char *) malloc(STRING_MAX)) == NULL)
FATAL("Not enough core...abort.\n", "");
sprintf(idx_fn, "%s%s", base, INDEX_IDX);
sprintf(widx_fn, "%s%s%s", WORK, base, INDEX_IDX);
if (((((idx_fp = OPEN_IN(idx_fn)) == NULL) && open_fn) ||
!(open_fn || idx_fp)) &&
((((widx_fp = OPEN_IN(widx_fn)) == NULL) && open_fn) ||
!(open_fn || widx_fp))) {
sprintf(arg, "%s",
(strchr(idx_fn, ':') || (strlen(WORK) == 0)) ?
NIL : "<" WORK ">");
sprintf(message,
"Couldn't find neither input file %s%%s nor %s%%s.\n",
arg, arg);
FATAL2(message, base, idx_fn);
}
}
if (!open_fn) { /* Close files if open */
if (idx_fp)
FCLOSE(idx_fp);
if (widx_fp)
FCLOSE(widx_fp);
}
if (open_fn && (!idx_fp) && widx_fp) { /* File was found on PVS W */
idx_fp = widx_fp;
idx_fn = widx_fn;
}
#else /* NOT OS_BS2000 */
if ( ( open_fn &&
((idx_fp = OPEN_IN(idx_fn)) == NULL)
) ||
((!open_fn) && (access(idx_fn, R_OK) != 0)))
if (with_ext) {
FATAL("Input index file %s not found.\n", idx_fn);
} else {
#ifdef DEBUG
totmem += STRING_MAX;
(void)fprintf(stderr,"check_idx()-2: malloc(%d)\ttotmem = %ld\n",
STRING_MAX,totmem);
#endif /* DEBUG */
if ((idx_fn = (char *) malloc(STRING_MAX)) == NULL)
FATAL("Not enough core...abort.\n", "");
sprintf(idx_fn, "%s%s", base, INDEX_IDX);
if ((open_fn &&
((idx_fp = OPEN_IN(idx_fn)) == NULL)
) ||
((!open_fn) && (access(idx_fn, R_OK) != 0))) {
FATAL2("Couldn't find input index file %s nor %s.\n", base,
idx_fn);
}
}
#endif /* OS_BS2000 */
}
static void
#if STDC
check_all(char *fn, int ind_given, int ilg_given, int log_given)
#else
check_all(fn, ind_given, ilg_given, log_given)
char *fn;
int ind_given;
int ilg_given;
int log_given;
#endif
{
check_idx(fn, TRUE);
/* index output file */
if (!ind_given) {
sprintf(ind, "%s%s", base, INDEX_IND);
ind_fn = ind;
#if OS_BS2000 /* Look on HOME-, then WORK-PVS */
if ((ind_fp = OPEN_IN(ind_fn)) == NULL) {
sprintf(ind, "%s%s%s", strchr(base, ':') ?
NIL : WORK, base, INDEX_IND);
ind_fn = ind;
} else
fclose(ind_fp);
#endif /* OS_BS2000 */
}
if ((ind_fp = OPEN_OUT(ind_fn)) == NULL)
FATAL("Can't create output index file %s.\n", ind_fn);
/* index transcript file */
if (!ilg_given) {
sprintf(ilg, "%s%s", base, INDEX_ILG);
ilg_fn = ilg;
#if OS_BS2000 /* Look on HOME-, then WORK-PVS */
if ((ilg_fp = OPEN_IN(ilg_fn)) == NULL) {
sprintf(ilg, "%s%s%s", strchr(base, ':') ?
NIL : WORK, base, INDEX_ILG);
ilg_fn = ilg;
} else
fclose(ilg_fp);
#endif /* OS_BS2000 */
}
if ((ilg_fp = OPEN_OUT(ilg_fn)) == NULL)
FATAL("Can't create transcript file %s.\n", ilg_fn);
#if OS_BS2000 /* Search both on HOME-PVS ans
* WORK-PVS */
if (log_given) {
sprintf(log_fn, "%s%s%s", strchr(base, ':') ? NIL : WORK,
base, INDEX_LOG);
if ((log_fp = OPEN_IN(log_fn)) == NULL) {
if (strchr(base, ':'))
sprintf(log_fn, "%s%s", strrchr(base, ':') + 1, INDEX_LOG);
else
sprintf(log_fn, "%s%s", base, INDEX_LOG);
if ((log_fp = OPEN_IN(log_fn)) == NULL)
FATAL2("Source log file %s%s not found.\n", WORK, log_fn);
} else {
find_pageno();
CLOSE(log_fp);
}
}
#else
if (log_given) {
sprintf(log_fn, "%s%s", base, INDEX_LOG);
#if OS_PCDOS /* open in binary mode (CR-LF) */
if ((log_fp = OPEN_IN_B(log_fn)) == NULL) {
#else
if ((log_fp = OPEN_IN(log_fn)) == NULL) {
#endif /* OS_PCDOS */
FATAL("Source log file %s not found.\n", log_fn);
} else {
find_pageno();
CLOSE(log_fp);
}
}
#endif /* OS_BS2000 */
}
static void
find_pageno(VOID_ARG)
{
int i = 0;
int p, c;
#if (OS_VAXVMS | OS_BS2000 | OS_MVSXA)
/*
* Scan forward through the file for VMS, because fseek doesn't work on
* variable record files
*/
c = GET_CHAR(log_fp);
while (c != EOF) {
p = c;
c = GET_CHAR(log_fp);
if (p == LSQ && isdigit(c)) {
i = 0;
do {
pageno[i++] = c;
c = GET_CHAR(log_fp);
} while (isdigit(c));
pageno[i] = NUL;
}
}
if (i == 0) {
fprintf(ilg_fp, "Couldn't find any page number in %s...ignored\n",
log_fn);
init_page = FALSE;
}
#else /* NOT (OS_VAXVMS | ...) */
fseek(log_fp, -1L, 2);
p = GET_CHAR(log_fp);
fseek(log_fp, -2L, 1);
do {
c = p;
p = GET_CHAR(log_fp);
} while (!(((p == LSQ) && isdigit(c)) || (fseek(log_fp, -2L, 1) != 0)));
if (p == LSQ) {
while ((c = GET_CHAR(log_fp)) == SPC);
do {
pageno[i++] = (char) c;
c = GET_CHAR(log_fp);
} while (isdigit(c));
pageno[i] = NUL;
} else {
fprintf(ilg_fp, "Couldn't find any page number in %s...ignored\n",
log_fn);
init_page = FALSE;
}
#endif /* (OS_VAXVMS | ...) */
}
static void
#if STDC
open_sty(char *fn)
#else
open_sty(fn)
char *fn;
#endif
{
char *path;
char *ptr;
int i;
int len;
if ((path = getenv(STYLE_PATH)) == NULL) {
/* style input path not defined */
strcpy(sty_fn, fn);
sty_fp = OPEN_IN(sty_fn);
} else {
#if OS_VAXVMS
if ((strlen(STYLE_PATH) + strlen(fn) + 1) > ARRAY_MAX) {
FATAL2("Path %s too long (max %d).\n", STYLE_PATH, ARRAY_MAX);
} else {
sprintf(sty_fn, "%s:%s", STYLE_PATH, fn);
sty_fp = OPEN_IN(sty_fn);
}
#else /* NOT OS_VAXVMS */
len = ARRAY_MAX - strlen(fn) - 1;
while (*path != NUL) {
#if OS_XENIX
i = 0;
while ((*path != ENV_SEPAR) && (*path != NUL) && (i < len))
sty_fn[i++] = *path++;
#else /* NOT OS_XENIX */
ptr = strchr(path, ENV_SEPAR);
i = 0;
if (ptr == (char*)NULL)
{
int j = strlen(path);
while (i < j)
sty_fn[i++] = *path++;
}
else
{
while ((path != ptr) && (i < len))
sty_fn[i++] = *path++;
}
#endif /* OS_XENIX */
if (i == len) {
FATAL2("Path %s too long (max %d).\n", sty_fn, ARRAY_MAX);
} else {
#ifdef OS_VAXVMS
if (sty_fn[i-1] != ']')
sty_fn[i++] = DIR_DELIM;
#else
sty_fn[i++] = DIR_DELIM;
#endif
sty_fn[i] = NUL;
strcat(sty_fn, fn);
#if OS_XENIX
if (((sty_fp = OPEN_IN(sty_fn)) == NULL) && (*path != NUL))
#else /* NOT OS_XENIX */
if ((sty_fp = OPEN_IN(sty_fn)) == NULL)
#endif /* OS_XENIX */
path++;
else
break;
}
}
#endif /* OS_VAXVMS */
}
if (sty_fp == NULL)
FATAL("Index style file %s not found.\n", fn);
}
int
#if STDC
strtoint(char *str)
#else
strtoint(str)
char *str;
#endif
{
int val = 0;
while (*str != NUL) {
#if (OS_BS2000 | OS_MVSXA)
val = 10 * val + *str - '0';
#else
val = 10 * val + *str - 48;
#endif /* (OS_BS2000 | OS_MVSXA) */
str++;
}
return (val);
}
|