#include #include #include #include #include #ifndef __GNUC__ #include #else #include #endif #include #include #include #include #ifndef O_BINARY #define O_BINARY 0 #endif char readline(int fd, char **buf) { char ch; if (*buf) delete [] *buf; *buf = 0; int len; long index = lseek(fd, 0, SEEK_CUR); // clean up any preceding white space while ((len = read(fd, &ch, 1)) == 1) { if ((ch != 13) && (ch != ' ') && (ch != '\t')) break; else index++; } while (ch != 10) { if ((len = read(fd, &ch, 1)) != 1) break; } int size = (lseek(fd, 0, SEEK_CUR) - index) - 1; *buf = new char [ size + 1 ]; if (size > 0) { lseek(fd, index, SEEK_SET); read(fd, *buf, size); read(fd, &ch, 1); //pop terminating char (*buf)[size] = 0; // clean up any trailing junk on buf for (char *it = *buf+(strlen(*buf)-1); it > *buf; it--) { if ((*it != 10) && (*it != 13) && (*it != ' ') && (*it != '\t')) break; else *it = 0; } } else **buf = 0; return !len; } char *parseVReg(char *buf) { char stage = 0; while (*buf) { switch (stage) { case 0: if (isalpha(*buf)) stage++; break; case 1: if (isdigit(*buf)) stage++; break; case 2: if (*buf == ':') stage++; break; case 3: if (isdigit(*buf)) stage++; break; case 4: if (*buf == ' ') { *buf = 0; return ++buf; } break; } buf++; } return (stage == 4) ? buf : 0; // if we got to stage 4 return empty buf, else return error } bool isKJVRef(const char *buf) { VerseKey vk, test; vk.AutoNormalize(0); vk.Headings(1); // turn on mod/testmnt/book/chap headings vk.Persist(1); // lets do some tests on the verse -------------- vk = buf; test = buf; if (vk.Testament() && vk.Book() && vk.Chapter() && vk.Verse()) { // if we're not a heading // cerr << (const char*)vk << " == " << (const char*)test << endl; return (vk == test); } else return true; // no check if we're a heading... Probably bad. } void fixText(char *text) { char *to = text; while(*text) { *to++ = *text++; *to++ = *text++; if (!*text) break; if (*text != ' ') cerr << "problem\n"; else text++; } *to = 0; } int main(int argc, char **argv) { // Let's test our command line arguments if (argc < 2) { // fprintf(stderr, "usage: %s [0|1 - file includes prepended verse references]\n", argv[0]); fprintf(stderr, "usage: %s [0|1 - prepended verse refs] [0|1 - NT only]\n\n", argv[0]); fprintf(stderr, "\tWith no verse refs, source file must contain exactly 31102 lines.\n"); fprintf(stderr, "\tThis is KJV verse count plus headings for MODULE,\n"); fprintf(stderr, "\tTESTAMENT, BOOK, CHAPTER. An example snippet follows:\n\n"); fprintf(stderr, "\t\tMODULE HEADER\n"); fprintf(stderr, "\t\tOLD TESTAMENT HEADER\n"); fprintf(stderr, "\t\tGENESIS HEADER\n"); fprintf(stderr, "\t\tCHAPTER 1 HEADER\n"); fprintf(stderr, "\t\tIn the beginning...\n\n"); fprintf(stderr, "\t... implying there must also be a CHAPTER2 HEADER,\n"); fprintf(stderr, "\tEXODUS HEADER, NEW TESTAMENT HEADER, etc. If there is no text for\n"); fprintf(stderr, "\tthe header, a blank line must, at least, hold place.\n\n"); fprintf(stderr, "\tWith verse refs, source file must simply contain any number of lines,\n"); fprintf(stderr, "\tthat begin with the verse reference for which it is an entry. e.g.:\n\n"); fprintf(stderr, "\t\tgen 1:0 CHAPTER 1 HEADER\n"); fprintf(stderr, "\t\tgen 1:1 In the beginning...\n\n"); exit(-1); } // Let's see if we can open our input file int fd = open(argv[1], O_RDONLY|O_BINARY); if (fd < 0) { fprintf(stderr, "error: %s: couldn't open input file: %s \n", argv[0], argv[1]); exit(-2); } // Try to initialize a default set of datafiles and indicies at our // datapath location passed to us from the user. if (RawText::createModule(argv[2])) { fprintf(stderr, "error: %s: couldn't create module at path: %s \n", argv[0], argv[2]); exit(-3); } // not used yet, but for future support of a vpl file with each line // prepended with verse reference, eg. "Gen 1:1 In the beginning..." bool vref = false; if (argc > 3) vref = (argv[3][0] == '0') ? false : true; // if 'nt' is the 4th arg, our vpl file only has the NT bool ntonly = false; if (argc > 4) ntonly = (argv[4][0] == '0') ? false : true; // Do some initialization stuff char *buffer = 0; RawText mod(argv[2]); // open our datapath with our RawText driver. VerseKey vk; vk.AutoNormalize(0); vk.Headings(1); // turn on mod/testmnt/book/chap headings vk.Persist(1); mod.SetKey(vk); // Loop through module from TOP to BOTTOM and set next line from // input file as text for this entry in the module mod = TOP; if (ntonly) vk = "Matthew 1:1"; int successive = 0; //part of hack below while ((!mod.Error()) && (!readline(fd, &buffer))) { if (*buffer == '|') // comments, ignore line continue; if (vref) { const char *verseText = parseVReg(buffer); if (!verseText) { // if we didn't find a valid verse ref cerr << "No valid verse ref found on line: " << buffer << "\n"; exit(-4); } vk = buffer; string orig = mod.getRawEntry(); if (!isKJVRef(buffer)) { VerseKey origVK = vk; /* This block is functioning improperly -- problem with AutoNormalize??? do { vk--; } while (!vk.Error() && !isKJVRef(vk)); */ //hack to replace above: successive++; vk -= successive; orig = mod.getRawEntry(); cerr << "Not a valid KJV ref: " << origVK << "\n"; cerr << "appending to ref: " << vk << "\n"; orig += " [ ("; orig += origVK; orig += ") "; orig += verseText; orig += " ] "; verseText = orig.c_str(); } else { successive = 0; } if (orig.length() > 1) cerr << "Warning, overwriting verse: " << vk << endl; // ------------- End verse tests ----------------- mod << verseText; // save text to module at current position } else { fixText(buffer); mod << buffer; // save text to module at current position mod++; // increment module position } } // clear up our buffer that readline might have allocated if (buffer) delete [] buffer; }