/* 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 }