/******* helpmake.c: Create the index file for a help database. ******* Command-line parameters: the help database name (input file), and the help index file name (output file). File formats described elsewhere. */ #include #include #include #define MAXNAME 10 /* Maximum length of a help item name */ #define MAXDESCRIPTION 50 /* Maximum length of the short description */ void putstring(char *str, FILE *f); /* Fn to write nul-terminated string */ int process_help_entry(FILE *helpdata, FILE *index); /* process_help_entry returns true if another entry follows this one. */ FILE * file_open(char name[], char access_mode[]); main(int argc, char *argv[]) { FILE *helpdata, *index; int there_is_another_entry; /* Open files. */ if (argc != 3) { fprintf( stderr, "You must supply a help database name and a name\n" "for the index file to be created.\n" ); exit(EXIT_FAILURE); } helpdata = file_open(argv[1], "r"); index = file_open(argv[2], "wb"); /* Check format of help database */ if (getc(helpdata) != ':' || getc(helpdata) != ':') { /* First two input characters are not "::", print error and stop. */ fprintf(stderr, "Incorrect format to help database.\n"); exit(EXIT_FAILURE); } /* Write index file header entry. */ fputs("!!", index); /* Note: OK to write chars to binary stream */ putstring(argv[1], index); do { there_is_another_entry = process_help_entry(helpdata, index); } while (there_is_another_entry); fclose(helpdata); fclose(index); return 0; } /**** putstring: write a nul-terminated string **** On entry: str is a string, f is an open output file. On exit: Characters in string, including terminating nul, are written to file, or an error message printed and program stopped. */ void putstring(char str[], FILE *f) { /* Fn to write nul-terminated string */ int leng = strlen(str) + 1; /* +1 for the nul */ if (fwrite(str, 1, leng, f) != leng) { perror("Error writing index file"); exit(EXIT_FAILURE); } } /**** process_help_entry: reads a help entry, and writes info to index **** On entry: helpdata is the help database file, open for input, positioned just after the "::" starting an entry. index is the index file, open for output in binary. On exit: Writes entry to the index file. If another entry follows this in the database, positions helpdata input just past its "::", and returns 1, else returns 0. Terminates program on error. */ int process_help_entry(FILE *helpdata, FILE *index) { char name[MAXNAME+1], description[MAXDESCRIPTION+1], flag[3]; int status, entry_size, ch; fpos_t location; /* Read item name & description; write to index file. */ if (fscanf(helpdata, "%10s %50[^\n]%*[^\n]", name, description) < 2) { perror("Missing items in help data"); exit(EXIT_FAILURE); } putstring(name, index); putstring(description, index); getc(helpdata); /* Advance past end-of-line in input file */ /* Find file location; write to index file. */ if (fgetpos(helpdata, &location) != 0) { /* error */ perror("Can't find help file position"); exit(EXIT_FAILURE); } fwrite(&location, sizeof(fpos_t), 1, index); /* error check shortly */ /* Skip the rest of the help entry (until EOF or "\n::" is seen). Measure the size of the text as it is skipped. We are at the start of a line, skip a line at a time */ entry_size = 0; /* Seen nothing yet */ status = fscanf(helpdata, "%2[^\n]", flag);/* first two chars in line */ while (status >= 0 && strcmp(flag,"::") != 0) { /*Skip a line per loop*/ entry_size += strlen(flag); /* Up to 2 chars already */ while (ch = getc(helpdata), ch != EOF && ch != '\n') { entry_size++; /* Skip & count a char */ } /* until end of line */ if (ch == '\n') entry_size++; /* Count end of lines */ status = fscanf(helpdata, "%2[^\n]",flag);/* 2 chars in next line */ } /* Now write entry size to index file */ if (fwrite(&entry_size, sizeof(int), 1, index) != 1) { perror("Error writing index file"); exit(EXIT_FAILURE); } if (status == EOF) { /* If EOF encountered, return 0. */ return 0; /* No more entries */ } return 1; /* The "::" of another entry seen */ } /* The following #ifdef includes the file_open function; if you have it in a personal function library, you may wish to delete these lines and link the two files separately. */ #ifdef __cplusplus #include "lst10-7.cpp" /* or maybe "lst10-7.cxx" */ #else #include "lst10-7.c" #endif