diff --git a/src/interpret.c b/src/interpret.c deleted file mode 100644 index d872198..0000000 --- a/src/interpret.c +++ /dev/null @@ -1,422 +0,0 @@ -/** @std GNU C11 */ - -#include "lex.h" -#include /* chdir (POSIX) */ -#include /* mode_t (POSIX) */ -#include /* umask (POSIX) */ -#include /* opendir readdir closedir */ -#include -#include -#include -#include - -#if INT_MAX >= 100000000000 -#error int_to_string requires truncation on this compiler. -#endif -static void int_to_string(const int *const n, char (*const a)[12]) - { sprintf(*a, "%d", *n); } -#define ARRAY_NAME int -#define ARRAY_TYPE int -#define ARRAY_TO_STRING -#include "array.h" -static int int_cmp(const int *const a, const int *const b) - { return (*b < *a) - (*a < *b); } -static int void_int_cmp(const void *const a, const void *const b) - { return int_cmp(a, b); } - -#define ARRAY_NAME char -#define ARRAY_TYPE char -#include "array.h" -/** Append a text file, `fn`, to `c`, and add a '\0'. - @return Success. A partial read is failure. @throws[fopen, fread, malloc] - @throws[EISEQ] The text file has embedded nulls. - @throws[ERANGE] If the standard library does not follow POSIX. */ -static int append_file(struct char_array *c, const char *const fn) { - FILE *fp = 0; - const size_t granularity = 1024; - size_t nread; - char *cursor; - int success = 0; - assert(c && fn); - if(!(fp = fopen(fn, "r"))) goto catch; - /* Read entire file in chunks. */ - do if(!(cursor = char_array_buffer(c, granularity)) - || (nread = fread(cursor, 1, granularity, fp), ferror(fp)) - || !char_array_append(c, nread)) goto catch; - while(nread == granularity); - /* File to `C` string. */ - if(!(cursor = char_array_new(c))) goto catch; - *cursor = '\0'; - /* Binary files with embedded '\0' are not allowed. */ - if(strchr(c->data, '\0') != cursor) { errno = EILSEQ; goto catch; } - { success = 1; goto finally; } -catch: - if(!errno) errno = EILSEQ; /* Will never be true on POSIX. */ -finally: - if(fp && fclose(fp)) success = 0; - return success; -} - -/** Is `y` a leap-year? */ -static int leap(int y) { - assert(y >= 1582); - if(!(y % 400)) return 1; - if(!(y % 100)) return 0; - if(!(y % 4)) return 1; - return 0; -} -/** Assumes: reverse ordering of byte-fields; unsigned is defined; C11 and GNU - anonymous unions. */ -union date32 { - uint32_t u32; - struct { unsigned day : 5, month : 4, year : 23; }; -}; -static int page_compare(const union date32 a, const union date32 b) - { return a.u32 > b.u32; } -static void date32_to_string(const union date32 d, char (*const z)[12]) { - assert(d.year < 10000 && d.month && d.month <= 31 && d.day && d.day <= 31); - sprintf(*z, "%u-%2.2u-%2.2u", d.year % 10000, d.month, d.day); -} - -/** Convert or narrower type or return zero. */ -static union date32 date_to_32(const int y, const int m, const int d) { - union date32 d32 = { 0 }; - /* Leap year calculations only work at y>=1 and Gregorian Calendar and max - 23 bits. */ - if(y < 1582 || y > 8388607 || m < 1 || m > 12 || d < 1 || d > 31) goto no; - switch(m) { - case 1: case 3: case 5: case 7: case 8: case 10: case 12: break; - case 4: case 6: case 9: case 11: if(d > 30) goto no; break; - case 2: if(d > 28 + leap(y)) goto no; break; - default: assert(0); break; - } - d32.year = (unsigned)y, d32.month = (unsigned)m, d32.day = (unsigned)d; -no: - return d32; -} - -/** Tomohiko Sakamoto comp.lang.c 1993-04-10. */ -/*static unsigned weekday(union date32 d) { - d.year -= d.month < 3; - return (d.year + d.year / 4 - d.year / 100 + d.year / 400 - + "-bed=pen+mad."[d.month] + d.day) % 7; -}*/ - - -/* Contained in to share with . */ -#define ARRAY_NAME lex -#define ARRAY_TYPE struct lex -#include "array.h" -struct page_tree_entry; -static void page_to_string(struct page_tree_entry, char (*)[12]); -struct page { - struct char_array entry; - struct lex_array meaning; -}; -#define TREE_NAME page -#define TREE_KEY union date32 -#define TREE_VALUE struct page -#define TREE_COMPARE &page_compare -#define TREE_TO_STRING -#include "tree.h" -static void page_to_string(const struct page_tree_entry entry, - char (*const z)[12]) { date32_to_string(*entry.key, z); } - -struct source { char *key, *desc; }; - -/* -### plot with steps -reset session - -$Data <meaning); - (lex = lex_array_next(&l_it)); ) { - switch(lex->symbol) { - case KJV_BOOK: - if(state != CHILL && state != WORD) goto catch; - if(state == WORD) printf("\n"); - fprintf(stderr, "%d-%.2d-%.2d: \"%.*s\", ", - entry.key->year, entry.key->month, entry.key->day, - (int)(lex->s1 - lex->s0), lex->s0); - state = BOOK; - break; - case KJV_CHAPTER_VERSE: - if(state != BOOK) goto catch; - printf("\"%.*s\", \"", (int)(lex->s1 - lex->s0), lex->s0); - state = CHAPTER; - break; - case KJV_NEXT: - if(state != WORD) goto catch; - printf("\"\n"); - break; - case KJV_TEXT: - if(state != WORD && state != CHAPTER && state != NEXT) - goto catch; - printf("%s%.*s<%d>", state == WORD ? "*" : "", - (int)(lex->s1 - lex->s0 < 0 ? 10 : lex->s1 - lex->s0), lex->s0, (int)(lex->s1 - lex->s0)); - count++; - state = WORD; - break; - default: - if(state != CHILL && state != WORD) goto catch; - if(state == WORD) printf("\"\n"), state = CHILL; - break; - } - } - if(state != CHILL && state != WORD) goto catch; - if(state == WORD) printf("\n"), state = CHILL; - } - printf("Count: %lu.\n", (unsigned long)count); - return 1; -catch: - fprintf(stderr, "Bible error.\n"); - if(entry.key) { - fprintf(stderr, "On date: %d-%.2d-%.2d.\n", - entry.key->year, entry.key->month, entry.key->day); - if(lex) fprintf(stderr, "At line %lu.\n", (unsigned long)lex->line); - } - errno = EILSEQ; - return 0; -} - -/*#define C_BLACK "\033[0;30m" -#define C_RED "\033[0;31m" -#define C_GREEN "\033[0;32m"*/ -#define C_YELLOW "\033[0;33m" -/*#define C_BLUE "\033[0;34m" -#define C_PURPLE "\033[0;35m" -#define C_CYAN "\033[0;36m" -#define C_WHITE "\033[0;37m" - -#define CB_BLACK "\033[1;30m" -#define CB_RED "\033[1;31m" -#define CB_GREEN "\033[1;32m" -#define CB_YELLOW "\033[1;33m" -#define CB_BLUE "\033[1;34m" -#define CB_PURPLE "\033[1;35m" -#define CB_CYAN "\033[1;36m" -#define CB_WHITE "\033[1;37m"*/ - -#define C_RESET "\033[0m" - -int main(int argc, char **argv) { - int success = EXIT_SUCCESS; - char *intent = 0; - - /* For reading in files, overwritten. */ - DIR *dir = 0; - struct dirent *de; - struct int_array years = int_array(), months = int_array(), - days = int_array(); - int *y, *y_end; - - struct page_tree journal = page_tree(); - - errno = 0; - if(argc != 2) { intent = "needs journal location, which should" - " contain //.txt"; goto catch; } - - /* Get the years list as directories matching a year. */ - if(chdir(argv[1]) == -1 || !(dir = opendir("."))) goto catch; - while((de = readdir(dir))) { - struct stat st; - int year, *p; - if(!lex_looks_like_year(de->d_name, &year)) continue; - if(stat(de->d_name, &st)) goto catch; - if(!S_ISDIR(st.st_mode)) continue; - if(!(p = int_array_new(&years))) goto catch; - *p = year; - } - closedir(dir), dir = 0; - /* Sort the years for sensible ordering of parsing. */ - qsort(years.data, years.size, sizeof *years.data, &void_int_cmp); - fprintf(stderr, "Years in <<%s>>: %s.\n", - argv[1], int_array_to_string(&years)); - - /* Go though each year. */ - for(y = years.data, y_end = y + years.size; y < y_end; y++) { - char fn[64]; - int *m, *m_end; - sprintf(fn, "%d", *y); - - /* Get the months as directories. */ - if(chdir(fn) == -1 || !(dir = opendir("."))) goto catch; - while((de = readdir(dir))) { - struct stat st; - int month, *p; - if(!(month = lex_looks_like_month(de->d_name))) continue; - if(stat(de->d_name, &st)) goto catch; - if(!S_ISDIR(st.st_mode)) continue; - if(!(p = int_array_new(&months))) goto catch; - *p = month; - } - closedir(dir), dir = 0; - qsort(months.data, months.size, sizeof *months.data, &void_int_cmp); - fprintf(stderr, "Months in <<%s>>: %s.)\n", - fn, int_array_to_string(&months)); - - /* Go though each month. */ - for(m = months.data, m_end = m + months.size; m < m_end; m++) { - int *d, *d_end; - sprintf(fn, "%.2d", *m); - - /* Get the days as files. */ - if(chdir(fn) == -1 || !(dir = opendir("."))) goto catch; - while((de = readdir(dir))) { - struct stat st; - int day, *p; - /* fixme: Have yyyy-mm-dd to figure out how many days. */ - if(!(day = lex_looks_like_day(de->d_name))) continue; - if(stat(de->d_name, &st)) goto catch; - if(S_ISDIR(st.st_mode)) continue; - if(!(p = int_array_new(&days))) goto catch; - *p = day; - } - closedir(dir), dir = 0; - qsort(days.data, days.size, sizeof *days.data, &void_int_cmp); - fprintf(stderr, "Days in <<%s>>: %s.\n", - fn, int_array_to_string(&days)); - - for(d = days.data, d_end = d + days.size; d < d_end; d++) { - struct lex *lex = 0; - struct page *page = 0; - union date32 d32; - if(!(d32 = date_to_32(*y, *m, *d)).year) { errno = EILSEQ; - intent = "date parse error"; goto syntax; } - sprintf(fn, "%.2d.txt", *d); - if(page_tree_bulk_add(&journal, d32, &page) != TREE_UNIQUE) { - if(!errno) intent = "not unique", errno = EDOM; - goto syntax; - } - page->entry = char_array(); - page->meaning = lex_array(); - if(!append_file(&page->entry, fn)) goto syntax; - int first = 1; - for(lex_reset(page->entry.data); ; ) { - if(!(lex = lex_array_new(&page->meaning))) goto syntax; - if(!lex_next(lex)) { - if(lex->symbol != END) { errno = EILSEQ; goto syntax; } - break; /* Terminated successfully. */ - } - switch(lex->symbol) { - case TEXT: printf("%s%.*s", - first ? "" : " ", (int)(lex->s1 - lex->s0), lex->s0); - first = 0; break; - case PARAGRAPH: printf("\n" C_RESET); break; - case KJV_BOOK: printf(C_YELLOW "%.*s", - (int)(lex->s1 - lex->s0), lex->s0); break; - case KJV_CHAPTER_VERSE: printf(" ch. %.*s", - (int)(lex->s1 - lex->s0), lex->s0); break; - case KJV_TEXT: printf("%.*s", - (int)(lex->s1 - lex->s0), lex->s0); break; - case KJV_NEXT: printf("(next)\n"); break; - default: - fprintf(stderr, "%lu: %s", - (unsigned long)lex->line, lex_symbols[lex->symbol]); - if(lex->s0 && lex->s1) { - if(lex->s0 + INT_MAX < lex->s1) - intent = "line too long", errno = EILSEQ; - else - fprintf(stderr, " <<%.*s>>", - (int)(lex->s1 - lex->s0), lex->s0); - } - fprintf(stderr, ".\n"); - break; - } - } - continue; -syntax: - fprintf(stderr, "On date: %d-%.2d-%.2d.\n", *y, *m, *d); - if(!page) goto catch; - if(!lex) { fprintf(stderr, "While parsing <<<\n%s>>>.\n", - page->entry.data); goto catch; } - for(struct lex_array_iterator it - = lex_array_iterator(&page->meaning); - lex = lex_array_next(&it); ) { - fprintf(stderr, "%lu: %s", - (unsigned long)lex->line, lex_symbols[lex->symbol]); - if(lex->s0 && lex->s1) { - if(lex->s0 + INT_MAX < lex->s1) - intent = "line too long", errno = EILSEQ; - else - fprintf(stderr, " <<%.*s>>", - (int)(lex->s1 - lex->s0), lex->s0); - } - fprintf(stderr, ".\n"); - } - goto catch; - } - - int_array_clear(&days); - if(chdir("..") == -1) goto catch; - } - - int_array_clear(&months); - if(chdir("..") == -1) goto catch; - /* fixme: Expand, contact is the next thing that it doesn't get. */ - if(*y == 1993/*1996*/) break; - } - page_tree_bulk_finish(&journal); - int_array_(&years), int_array_(&months), int_array_(&days); - fprintf(stderr, "Journal has entries: %s\n", page_tree_to_string(&journal)); - - /* Do something interesting? */ - if(!bible_graph(&journal)) goto catch; - - goto finally; -catch: - success = EXIT_FAILURE; - perror("interpret"); - if(intent) fprintf(stderr, "Further explanation: %s.\n", intent); -finally: - if(dir && closedir(dir)) success = EXIT_FAILURE, perror("dir"); - int_array_(&years), int_array_(&months), int_array_(&days); - struct page_tree_entry entry; - for(struct page_tree_iterator it = page_tree_begin(&journal); - (entry = page_tree_next(&it)).key; ) { - struct page *const page = entry.value; - char z[12]; - date32_to_string(*entry.key, &z); - lex_array_(&page->meaning); - char_array_(&page->entry); - } - return success; -} - -/* Popular KJV 738137 words. */ diff --git a/src/scan_kjv.re.c b/src/scan_kjv.re.c index 8eb53d3..2e09927 100644 --- a/src/scan_kjv.re.c +++ b/src/scan_kjv.re.c @@ -13,12 +13,14 @@ /*!conditions:re2c*/ -static int scan(union date32 date, const char *const buffer) { +static int scan(union date32 date, const char *const buffer, + struct kjv *const kj) { const char *YYCURSOR, *YYMARKER, *yyt1, *yyt2, *yyt3, *s0, *s1, *t0, *t1; enum kjv_book book = Revelation; uint32_t chapter, verse; enum YYCONDTYPE condition = yycline; size_t line = 1; + assert(buffer && kj); YYCURSOR = YYMARKER = yyt1 = buffer; /*!re2c /**/ re2c:define:YYCTYPE = char; @@ -37,7 +39,8 @@ static int scan(union date32 date, const char *const buffer) { */ for( ; ; ) { /*!re2c /**/ * { printf("*! %zu\n", line);goto error; } - "\x00" { printf("yes!\n");return 1; } + "\x00" { printf("%zu lines\n", line); return 1; } + "\n" { line++; continue; } * :=> skip "Genesis" / lookat => book { book = Genesis; continue; } "Exodus" / lookat => book { book = Exodus; continue; } @@ -48,7 +51,9 @@ static int scan(union date32 date, const char *const buffer) { | "Jeremiah" | "Lamentations" | "Ezekiel" | "Daniel" | "Hosea" | "Joel" | "Amos" | "Obadiah" | "Jonah" | "Micah" | "Nahum" | "Habakkuk" | "Zephaniah" | "Haggai" | "Zechariah" | "Malachi" | "Matthew" | "Mark" - | "Luke" | "John" | "Acts" | "Romans" | "I"{1,2} " Corinthians" + | "Luke" | "John" | "Acts" | */ + "Romans" / lookat => book { book = Romans; continue; } + /*| "I"{1,2} " Corinthians" | "Galatians" | "Ephesians" | "Philippians" | "Colossians" | "I"{1,2} " Thessalonians" | "I"{1,2} " Timothy" | "Titus" | "Philemon" | "Hebrews" | "James" | "I"{1,2} " Peter" | "I"{1,3} " John" | "Jude" @@ -61,12 +66,14 @@ static int scan(union date32 date, const char *const buffer) { = { .book = book, .chapter = chapter, .verse = verse }; char a[12]; kjvcite_to_string(c, &a), printf("Parsed %s\n", a); + if(!kjv_add(kj, c)) goto error; continue; } [^\n\x00]* "\n" => line { line++; continue; } //=> bible { x->s0 = s0, x->s1 = s1; return x->symbol = KJV_BOOK, 1; } */ } error: + errno = EILSEQ; { char a[12]; date32_to_string(date, &a); @@ -76,19 +83,23 @@ error: } int main(void) { - struct journal j = journal(); int success = EXIT_SUCCESS; + struct journal j = journal(); struct journal_iterator it; + struct kjv kj = kjv(); union date32 k; union load *v; + size_t i; + scan((union date32){.year=2000, .month=1, .day=1}, + "\n\n\n" + "Romans 3:23 -- ``For all have sinned, and come short of the glory of God.''\n", &kj); if(!journal_is_valid(&j)) goto catch; printf("Journal: %s.\n", journal_to_string(&j)); - if(!scan((union date32){ .u32 = 42 }, "Genesis 1:1 -- fdgYo.\n" - "Exodus 1:2 -- fuck\n" - "no\n")) fprintf(stderr, "Error :[\n"); - it = journal_begin(&j); while(journal_next(&it, &k, &v)) { + it = journal_begin(&j), i = 0; while(journal_next(&it, &k, &v)) { char a[12]; - date32_to_string(k, &a), printf("%s: %s\n", a, v->text); + date32_to_string(k, &a), printf("%s: %.6s\n", a, v->text); + if(!scan(k, v->text, &kj/*, fp*/)) goto catch; + if(++i > 32) break; } goto finally; catch: diff --git a/test/interpret.c b/test/interpret.c deleted file mode 100644 index b2de962..0000000 --- a/test/interpret.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include -#include -#include - -int main(void) { - return EXIT_SUCCESS; -}