/* mkindx.c */
#include "config.h"
#include "copyrite.h"
#ifdef EMBEDDED_MKINDX
#include "conf.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef I_STRING
#include <string.h>
#else
#include <strings.h>
#endif
#include "help.h"
#include "globals.h"
#include "mymalloc.h"
#include "confmagic.h"
#define TRUE 1
#define FALSE 0
typedef struct TLIST {
char topic[TOPIC_NAME_LEN + 1];
struct TLIST *next;
} tlist;
tlist *top = NULL;
help_indx *topics = NULL;
unsigned num_topics = 0;
unsigned top_topics = 0;
void write_topic _((FILE * out, long int p, int l));
void flush_topics _((FILE * out));
static void add_topic _((char *name));
#ifndef EMBEDDED_MKINDX
int main _((int argc, char **argv));
#endif
#ifndef EMBEDDED_MKINDX
/* EMBEDDED_MKINDX includes this in the main prog, and thus gets strcasecmp
* from strutil */
#ifndef HAS_STRCASECMP
int strcasecmp _((const char *s1, const char *s2));
int
strcasecmp(s1, s2)
const char *s1;
const char *s2;
{
while (*s1 && *s2 && DOWNCASE(*s1) == DOWNCASE(*s2))
s1++, s2++;
return (DOWNCASE(*s1) - DOWNCASE(*s2));
}
#endif
#endif
void
write_topic(out, p, l)
FILE *out;
long int p;
int l;
{
tlist *cur, *nextptr;
help_indx *temp;
for (cur = top; cur; cur = nextptr) {
nextptr = cur->next;
if (num_topics >= top_topics) {
top_topics += top_topics / 2 + 20;
if (topics)
topics = (help_indx *) realloc(topics, top_topics * sizeof(help_indx));
else
topics = (help_indx *) malloc(top_topics * sizeof(help_indx));
if (!topics) {
fprintf(stderr, "out of memory\n");
exit(-1);
}
}
temp = &topics[num_topics++];
temp->pos = p;
temp->len = l;
strcpy(temp->topic, cur->topic);
free(cur);
}
top = NULL;
}
static void
add_topic(name)
char *name;
{
tlist *cur;
cur = (tlist *) malloc(sizeof(tlist));
strcpy(cur->topic, name);
cur->next = top;
top = cur;
}
static int topic_cmp _((const help_indx *s1, const help_indx *s2));
static int
topic_cmp(s1, s2)
const help_indx *s1;
const help_indx *s2;
{
int k = strcasecmp(s1->topic, s2->topic);
return k;
}
void
flush_topics(out)
FILE *out;
{
qsort(topics, num_topics, sizeof(help_indx), topic_cmp);
if ((Size_t) fwrite(topics, sizeof(help_indx), num_topics, out) < num_topics) {
fprintf(stderr, "error writing\n");
exit(-1);
}
}
char line[LINE_SIZE + 1];
#ifdef EMBEDDED_MKINDX
int
makeindex(char const *inputfile, char const *outputfile)
#else
int
main(argc, argv)
int argc;
char **argv;
#endif
{
long bigpos, pos = 0;
int in_topic;
int i, n, lineno, ntopics;
char *s, *topic;
char the_topic[TOPIC_NAME_LEN + 1];
FILE *rfp, *wfp;
#ifndef EMBEDDED_MKINDX
char c;
#endif
#ifdef EMBEDDED_MKINDX
/* Quietly ignore null values for the file */
if (!inputfile || !*inputfile || !outputfile || !*outputfile)
return 0;
if ((rfp = fopen(inputfile, "r")) == NULL) {
fprintf(stderr, "can't open %s for reading\n", inputfile);
exit(-1);
}
if ((wfp = fopen(outputfile, "wb")) == NULL) {
fprintf(stderr, "can't open %s for writing\n", outputfile);
exit(-1);
}
fprintf(stderr, "Indexing file %s\n", inputfile);
#else
if (argc < 2 || argc > 3) {
printf("Usage:\tmkindx <file_to_be_indexed> <output_index_filename>\n");
exit(-1);
}
if ((rfp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "can't open %s for reading\n", argv[1]);
exit(-1);
}
if ((wfp = fopen(argv[2], "wb")) == NULL) {
fprintf(stderr, "can't open %s for writing\n", argv[2]);
exit(-1);
}
#endif
bigpos = 0L;
lineno = 0;
ntopics = 0;
#ifndef EMBEDDED_MKINDX
/* try to prevent accidental clobbering if user reverses file order */
c = getc(rfp);
if (c != '&') {
printf("%s is probably not a text file.\n", argv[1]);
printf("Usage:\tmkindx <file_to_be_indexed> <output_index_filename>\n");
fclose(rfp);
fclose(wfp);
exit(-1);
}
ungetc(c, rfp);
#endif
in_topic = FALSE;
while (fgets(line, LINE_SIZE, rfp) != NULL) {
++lineno;
n = strlen(line);
if (line[n - 1] != '\n') {
fprintf(stderr, "line %d: line too long\n", lineno);
}
if (line[0] == '&') {
++ntopics;
if (!in_topic) {
/* Finish up last entry */
if (ntopics > 1) {
write_topic(wfp, pos, bigpos - pos);
}
in_topic = TRUE;
}
/* parse out the topic */
/* Get the beginning of the topic string */
for (topic = &line[1];
(*topic == ' ' || *topic == '\t') && *topic != '\0'; topic++) ;
/* Get the topic */
strcpy(the_topic, "");
for (i = -1, s = topic; *s != '\n' && *s != '\0'; s++) {
if (i >= TOPIC_NAME_LEN - 1)
break;
if (*s != ' ' || the_topic[i] != ' ')
the_topic[++i] = *s;
}
the_topic[++i] = '\0';
add_topic(the_topic);
} else {
if (in_topic) {
pos = bigpos;
}
in_topic = FALSE;
}
#ifdef EMBEDDED_MKINDX
bigpos = ftell(rfp);
#else
bigpos += (long) n;
#endif
}
/* Handle last topic */
write_topic(wfp, pos, bigpos - pos);
flush_topics(wfp);
fclose(rfp);
fclose(wfp);
#ifdef EMBEDDED_MKINDX
fprintf(stderr, " %d topics indexed\n", ntopics);
return 0;
#else
printf("%d topics indexed\n", ntopics);
exit(0);
#endif
}