/* mkindx.c - make help/news file indexes */ /* $Id: mkindx.c,v 1.10 2000/11/25 21:40:52 merlin Exp $ */ /* * mkindx now supports multiple tags for a single entry. * example: * * & foo * & bar * This is foo and bar. * & baz * This is baz. * */ #include "copyright.h" #include "autoconf.h" #include "help.h" char line[LINE_SIZE + 1]; typedef struct _help_indx_list { help_indx entry; struct _help_indx_list *next; } help_indx_list; int dump_entries(FILE *wfp, long pos, help_indx_list *entries); int main(argc, argv) int argc; char *argv[]; { long pos; int i, n, lineno, ntopics, actualdata; char *s, *topic; help_indx_list *entries, *ep; FILE *rfp, *wfp; 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], "w")) == NULL) { fprintf(stderr, "can't open %s for writing\n", argv[2]); exit(-1); } pos = 0L; lineno = 0; ntopics = 0; actualdata = 0; /* create initial entry storage */ entries = (help_indx_list *)malloc(sizeof(help_indx_list)); memset(entries, 0, sizeof(help_indx_list)); 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 ( (ntopics > 1) && actualdata ) { /* * we've hit the next topic, time to write the ones we've been * building */ actualdata = 0; if (dump_entries(wfp, pos, entries)) { fprintf(stderr, "error writing %s\n", argv[2]); exit(-1); } memset(entries, 0, sizeof(help_indx_list)); } if (entries->entry.pos) { /* * we're already working on an entry... time to start nesting */ ep = entries; entries = (help_indx_list *)malloc(sizeof(help_indx_list)); memset(entries, 0, sizeof(help_indx_list)); entries->next = ep; } for (topic = &line[1]; (*topic == ' ' || *topic == '\t') && *topic != '\0'; topic++) ; for (i = -1, s = topic; *s != '\n' && *s != '\0'; s++) { if (i >= TOPIC_NAME_LEN - 1) break; if (*s != ' ' || entries->entry.topic[i] != ' ') entries->entry.topic[++i] = *s; } entries->entry.topic[++i] = '\0'; entries->entry.pos = pos + (long)n; } else if (n > 1) { /* * a non blank line. we can flush entries to the .indx file the next * time we run into a topic line... */ actualdata = 1; } pos += n; } if (dump_entries(wfp, pos, entries)) { fprintf(stderr, "error writing %s\n", argv[2]); exit(-1); } fclose(rfp); fclose(wfp); printf("%d topics indexed\n", ntopics); exit(0); } int dump_entries(FILE *wfp, long pos, help_indx_list *entries) { int truepos; int truelen; int depth; help_indx_list *prev_ep, *ep; /* * if we have more than one entry, the one on the top of the chain * is going to have the actual pos we want to use to index with */ truepos = (long)entries->entry.pos; truelen = (int)(pos - entries->entry.pos); prev_ep = 0; depth = 0; for (ep = entries; ep; ep = ep->next) { ep->entry.pos = (long)truepos; ep->entry.len = truelen; if (fwrite(&ep->entry, sizeof(help_indx), 1, wfp) < 1) return(-1); if (prev_ep) free(prev_ep); if (depth++) /* don't want to try to free the top of the chain */ prev_ep = ep; } /* * no attempt is made to free the last remaining struct as its actually the * one on the top of the chain, ie. the statically allocated struct. */ return(0); }