8 Commits
onedir ... utf8

78 changed files with 259 additions and 129 deletions

View File

@@ -64,7 +64,7 @@ build/%.o: build/%.c #src/%.h
build/%.c: src/%.re.c build/%.c: src/%.re.c
@echo "\033[0;34mhttps://re2c.org/ generate $@\033[0m" @echo "\033[0;34mhttps://re2c.org/ generate $@\033[0m"
@mkdir -p build @mkdir -p build
re2c -W --tags --conditions -o $@ $< re2c -W -8 --tags --conditions -o $@ $<
#doc/%.md: src/%.h #doc/%.md: src/%.h
# # https://github.com/neil-edelman/cdoc documentation # # https://github.com/neil-edelman/cdoc documentation

3
derived/.gitignore vendored
View File

@@ -1,2 +1,5 @@
* *
!.gitignore !.gitignore
!interpret
!kjv/
!kjv/*

1
derived/interpret Normal file
View File

@@ -0,0 +1 @@
../../../Documents/journal/

View File

@@ -10,41 +10,81 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <unistd.h> /* getcwd, chdir */
int main(void) { int main(void) {
const char *intent = "start"; const char *intent = "start";
struct journal jrnl = {0}; struct journal jrnl = {0};
struct scan scn = {0}; struct scan scn = {0};
int showhelp = 1;
FILE *fpwhere = 0;
char cwd[PATH_MAX], jdir[PATH_MAX];
errno = 0; errno = 0;
intent = "journal (cwd)"; intent = "current directory";
if(!getcwd(cwd, sizeof(cwd))) goto catch;
intent = "interpret";
if(!(fpwhere = fopen(intent, "r"))) goto catch;
if(!fgets(jdir, sizeof jdir, fpwhere)) {
if(!errno) errno = EDOM;
fprintf(stderr, "first line error\n");
goto catch;
}
if(fgetc(fpwhere) != EOF) {
fprintf(stderr, "expected eof\n");
errno = EDOM; goto catch;
}
/* Could be something other than EOF. */
if(errno || (fclose(fpwhere) == EOF && (fpwhere = 0, 1))) goto catch;
fpwhere = 0;
jdir[strcspn(jdir, "\n")] = '\0'; /* Strip. */
if(chdir(jdir)) {
fprintf(stderr, "while switching to directory: %s\n", jdir);
goto catch;
}
showhelp = 0;
intent = "interesting";
perror("errno");
if(errno) goto catch;
intent = "journal";
jrnl = journal(); jrnl = journal();
fprintf(stderr, "Journal: %s.\n", journal_to_string(&jrnl)); fprintf(stderr, "Journal: %s.\n", journal_to_string(&jrnl));
if(errno) goto catch; if(errno) goto catch;
intent = cwd;
if(chdir(cwd)) goto catch;
intent = "parse"; intent = "parse";
scn = scan(&jrnl); scn = scan(&jrnl);
//fprintf(stderr, "Scan: %s.\n", scan_to_string(&scrs)); //fprintf(stderr, "Scan: %s.\n", scan_to_string(&scrs));
// <- Not sure what that would do. // <- Not sure what that would do.
if(errno) goto catch; if(errno) goto catch;
intent = "derived/score.gnu"; intent = "score.gnu";
if(!freopen(intent, "w", stdout)) goto catch; if(!freopen(intent, "w", stdout)) goto catch;
scan_score_graph(&scn); scan_score_graph(&scn);
intent = "derived/glider.gnu"; intent = "labs.csv";
if(!freopen(intent, "w", stdout)) goto catch;
scan_labs_graph(&scn);
intent = "glider.gnu";
if(!freopen(intent, "w", stdout)) goto catch; if(!freopen(intent, "w", stdout)) goto catch;
scan_glider_graph(&scn); scan_glider_graph(&scn);
intent = "derived/flight.gnu"; intent = "flight.gnu";
if(!freopen(intent, "w", stdout)) goto catch; if(!freopen(intent, "w", stdout)) goto catch;
scan_flight_graph(&scn); scan_flight_graph(&scn);
intent = "derived/kjv.gnu"; intent = "kjv.gnu";
if(!freopen(intent, "w", stdout)) goto catch; if(!freopen(intent, "w", stdout)) goto catch;
scan_kjv_graph(&scn); scan_kjv_graph(&scn);
intent = "derived/dream.gnu"; intent = "dream.gnu";
if(!freopen(intent, "w", stdout)) goto catch; if(!freopen(intent, "w", stdout)) goto catch;
scan_dream_graph(&scn); scan_dream_graph(&scn);
@@ -52,10 +92,23 @@ int main(void) {
goto finally; goto finally;
catch: catch:
perror(intent); perror(intent);
/* Don't know if that will give real insight into the problem… */
if(freopen("error.txt", "w", stdout)) {
printf("Journal: %s.\n", journal_to_string(&jrnl));
}
finally: finally:
/* fixme: ~scan should be idempotent but it's not on disabling ASLR, which /* fixme: ~scan should be idempotent but it's not on disabling ASLR, which
debug mode is in. */ debug mode is in. */
if(fpwhere && fclose(fpwhere) == EOF)
intent = "interpret", perror(intent);
scan_(&scn); scan_(&scn);
journal_(&jrnl); journal_(&jrnl);
if(intent && showhelp)
fprintf(stderr, "\nMeant to be run in a directory with a file called "
"\"interpret\".\n"
"The contents of that file shall be a directory wherein\n"
"<year>/<month>/<day>.txt, eg 2000/12/01.txt.\n"
"Loads all journal entries and parses them, outputting to the "
"current directory.\n\n");
return intent ? EXIT_FAILURE : EXIT_SUCCESS; return intent ? EXIT_FAILURE : EXIT_SUCCESS;
} }

View File

@@ -215,7 +215,7 @@ struct journal journal(void/*const char *const dir_journal*/) {
m = 0, int_array_clear(&months); m = 0, int_array_clear(&months);
if(chdir("..") == -1) goto catch; if(chdir("..") == -1) goto catch;
} }
if(/*chdir("../..") == -1 ||*/ !day_tree_bulk_finish(&j.days)) goto catch; if(!day_tree_bulk_finish(&j.days)) goto catch;
/* Structure is now stable because we aren't going to move it; /* Structure is now stable because we aren't going to move it;
convert all of offsets back to pointers. */ convert all of offsets back to pointers. */

View File

@@ -78,7 +78,7 @@ static void kjvcount_to_string(const union kjvcite x, const unsigned count,
/* Parse filename of books. */ /* Parse filename of books. */
/*!re2c /**/ /*!re2c /**/
re2c:yyfill:enable = 0; re2c:yyfill:enable = 0;
re2c:define:YYCTYPE = char; re2c:define:YYCTYPE = "unsigned char";
natural = [1-9][0-9]*; natural = [1-9][0-9]*;
whitespace = [ \t\v\f]; whitespace = [ \t\v\f];
word = [^ \t\v\f\n\x00]+; word = [^ \t\v\f\n\x00]+;
@@ -86,13 +86,14 @@ word = [^ \t\v\f\n\x00]+;
/** `fn` contains "<number>[*].txt", sticks that in `book_no`, otherwise /** `fn` contains "<number>[*].txt", sticks that in `book_no`, otherwise
returns false. */ returns false. */
static int looks_like_book_fn(const char *fn, unsigned *const book_no) { static int looks_like_book_fn(const char *fn, unsigned *const book_no) {
const char *YYCURSOR = fn, *YYMARKER, *yyt1, *yyt2, *s0, *s1; const unsigned char *YYCURSOR = (const unsigned char *)fn,
*YYMARKER, *yyt1, *yyt2, *s0, *s1;
assert(fn && book_no); assert(fn && book_no);
/*!re2c /**/ /*!re2c /**/
* *
{ return 0; } { return 0; }
@s0 natural @s1 [^.\x00]* ".txt" "\x00" @s0 natural @s1 [^.\x00]* ".txt" "\x00"
{ return pair_to_natural(s0, s1, book_no); } { return pair_to_natural(pair_u(s0, s1), book_no); }
*/ */
} }
@@ -100,22 +101,23 @@ static int looks_like_book_fn(const char *fn, unsigned *const book_no) {
/* This is the contents of the <fn:looks_like_book_fn>. */ /* This is the contents of the <fn:looks_like_book_fn>. */
struct lex { struct lex {
size_t line; size_t line;
const char *cursor; const unsigned char *cursor;
int error; int error;
uint32_t chapter, verse, words; uint32_t chapter, verse, words;
}; };
static struct lex lex(const char *cursor) { static struct lex lex(const char *cursor) {
struct lex lex; struct lex lex;
union { const unsigned char *u; const char *s; } flex = { .s = cursor };
assert(cursor); assert(cursor);
lex.line = 1; lex.line = 1;
lex.cursor = cursor; lex.cursor = flex.u;
lex.error = 0; lex.error = 0;
lex.chapter = lex.verse = lex.words = 0; lex.chapter = lex.verse = lex.words = 0;
return lex; return lex;
} }
/*!conditions:re2c*/ /*!conditions:re2c*/
static int lex_next_verse(struct lex *const lex) { static int lex_next_verse(struct lex *const lex) {
const char *YYMARKER, *yyt1 = 0, *yyt2 = 0, *s0, *s1, *t0, *t1; const unsigned char *YYMARKER, *yyt1 = 0, *yyt2 = 0, *s0, *s1, *t0, *t1;
enum YYCONDTYPE condition = yycline; enum YYCONDTYPE condition = yycline;
/*!re2c /**/ /*!re2c /**/
re2c:define:YYCURSOR = lex->cursor; re2c:define:YYCURSOR = lex->cursor;
@@ -131,8 +133,8 @@ scan:
<line> [^[\]\n\x00]* "\n" { lex->line++; goto scan; } <line> [^[\]\n\x00]* "\n" { lex->line++; goto scan; }
<line> "\x00" { return 0; } <line> "\x00" { return 0; }
<line> "[" @s0 natural @s1 ":" @t0 natural @t1 "]" => verse { <line> "[" @s0 natural @s1 ":" @t0 natural @t1 "]" => verse {
if(!pair_to_natural(s0, s1, &lex->chapter) if(!pair_to_natural(pair_u(s0, s1), &lex->chapter)
|| !pair_to_natural(t0, t1, &lex->verse)) || !pair_to_natural(pair_u(t0, t1), &lex->verse))
return errno = EILSEQ, lex->error = 1, 0; return errno = EILSEQ, lex->error = 1, 0;
lex->words = 0; lex->words = 0;
/*printf("%u:%u", lex->chapter, lex->verse);*/ /*printf("%u:%u", lex->chapter, lex->verse);*/

View File

@@ -18,45 +18,48 @@ struct pair pair(const char *const a, const char *const b) {
return p; return p;
} }
/** @returns Constructs `a` and `b` as unsigned. */
struct pair pair_u(const unsigned char *const a, const unsigned char *const b)
{ return pair((const char *)a, (const char *)b); }
/** Doesn't check if the number is actually in [0, 9]. /** Doesn't check if the number is actually in [0, 9].
@return Whether it was able to parse unsigned [`a`, `b`] to `n`. */ @return Whether it was able to parse unsigned [`a`, `b`] to `n`. */
int pair_to_natural(const char *a, const char *const b, uint32_t *const n) { int pair_to_natural(struct pair p, uint32_t *const n) {
uint32_t accum = 0; uint32_t accum = 0;
while(a < b) { while(p.a < p.b) {
unsigned next = accum * 10 + (unsigned)(*a - '0'); uint32_t next = accum * 10 + (uint32_t)(*p.a - '0');
if(accum > next) return errno = ERANGE, 0; if(accum > next) return errno = ERANGE, 0;
accum = next; accum = next;
a++; p.a++;
} }
return *n = accum, 1; return *n = accum, 1;
} }
static int pair_to_64(const char *a, const char *const b, uint64_t *const n) { static int pair_to_64(struct pair p, uint64_t *const n) {
uint64_t accum = 0; uint64_t accum = 0;
while(a < b) { while(p.a < p.b) {
uint64_t next = accum * 10 + (uint64_t)(*a - '0'); uint64_t next = accum * 10 + (uint64_t)(*p.a - '0');
if(accum > next) return errno = ERANGE, 0; if(accum > next) return errno = ERANGE, 0;
accum = next; accum = next;
a++; p.a++;
} }
return *n = accum, 1; return *n = accum, 1;
} }
/** `h0` "1" `h1` ":" `m0` "30" `m1` -> 90 `n` @return Valid. */ /** `h` "1" ":" `m` "30" -> 90 `n` @return Valid. */
int pair_colon_to_minutes(const char *h0, const char *const h1, int pair_colon_to_minutes(struct pair h, struct pair m, uint32_t *const n) {
const char *m0, const char *const m1, uint32_t *const n) {
uint32_t hours, minutes; uint32_t hours, minutes;
return pair_to_natural(h0, h1, &hours) && pair_to_natural(m0, m1, &minutes) return pair_to_natural(h, &hours) && pair_to_natural(m, &minutes)
&& minutes < 60 && hours <= UINT32_MAX / 60 - minutes && minutes < 60 && hours <= UINT32_MAX / 60 - minutes
? (*n = hours * 60 + minutes, 1) : 0; ? (*n = hours * 60 + minutes, 1) : 0;
} }
/** `h0` "1" `h1` "." `m0` "5" `m1` -> 90 `n` @return Valid. */ /** `h0` "1" `h1` "." `m0` "5" `m1` -> 90 `n` @return Valid. */
int pair_hours_to_minutes(const char *h0, const char *const h1, int pair_decimal_hours_to_minutes(struct pair h, struct pair m,
const char *m0, const char *const m1, uint32_t *const n) { uint32_t *const n) {
uint32_t hours, minutes; uint32_t hours, minutes;
/* fixme: more precision? */ /* fixme: more precision? */
return pair_to_natural(h0, h1, &hours) && pair_to_natural(m0, m1, &minutes) return pair_to_natural(h, &hours) && pair_to_natural(m, &minutes)
&& minutes <= 9 && hours <= UINT32_MAX / 60 - minutes * 6 && minutes <= 9 && hours <= UINT32_MAX / 60 - minutes * 6
? (*n = hours * 60 + minutes * 6, 1) : 0; ? (*n = hours * 60 + minutes * 6, 1) : 0;
} }
@@ -109,12 +112,12 @@ no:
@return Success. @return Success.
@throws[ERANGE] Year is more then 23 bits. @throws[ERANGE] Year is more then 23 bits.
@throws[EILSEQ] The is not a date? */ @throws[EILSEQ] The is not a date? */
int pair_to_date(const char *a, union date32 *const d) { int pair_to_date(const unsigned char *a, union date32 *const d) {
uint32_t year = 0, month, day; uint32_t year = 0, month, day;
union date32 temp; union date32 temp;
assert(a && d); assert(d);
while(*a >= '0' && *a <= '9') { while(a[0] >= '0' && a[0] <= '9') {
year = year * 10 + (unsigned)(*a - '0'); year = year * 10 + (unsigned)(a[0] - '0');
if(year > 0x7FFFFF) return errno = ERANGE, 0; /* 23 bits */ if(year > 0x7FFFFF) return errno = ERANGE, 0; /* 23 bits */
a++; a++;
} }
@@ -128,17 +131,16 @@ int pair_to_date(const char *a, union date32 *const d) {
return *d = temp, 1; return *d = temp, 1;
} }
int pair_to_cents(const char *a, const char *b, int64_t *const cents) { int pair_to_cents(struct pair p, int64_t *const cents) {
uint64_t d, c; uint64_t d, c;
int is_negative; int is_negative;
assert(a && a < b && cents); assert(p.a < p.b && cents);
if(a[0] == '-') is_negative = 1, a++, assert(a < b); if(p.a[0] == '-') is_negative = 1, p.a++; else is_negative = 0;
else is_negative = 0; if(p.a + 2 < p.b && p.b[-3] == '.') { /* dollars.cents */
if(a + 2 < b && b[-3] == '.') { /* dollars.cents */ if(!pair_to_64(pair(p.a, p.b - 3), &d)) return 0;
if(!pair_to_64(a, b - 3, &d)) return 0; c = (uint64_t)(p.b[-2] - '0') * 10 + (uint64_t)(p.b[-1] - '0');
c = (uint64_t)(b[-2] - '0') * 10 + (uint64_t)(b[-1] - '0');
} else { /* dollars */ } else { /* dollars */
if(!pair_to_64(a, b, &d)) return 0; if(!pair_to_64(pair(p.a, p.b), &d)) return 0;
c = 0; c = 0;
} }
assert(-INT64_MAX >= INT64_MIN); assert(-INT64_MAX >= INT64_MIN);

View File

@@ -5,17 +5,16 @@
struct pair { const char *a, *b; }; struct pair { const char *a, *b; };
struct pair pair(const char *const a, const char *const b); struct pair pair(const char *, const char *);
int pair_to_natural(const char *, const char *, uint32_t *); struct pair pair_u(const unsigned char *, const unsigned char *);
int pair_colon_to_minutes(const char *, const char *, int pair_to_natural(struct pair, uint32_t *);
const char *, const char *, uint32_t *); int pair_colon_to_minutes(struct pair h, struct pair m, uint32_t *);
int pair_hours_to_minutes(const char *h0, const char *const h1, int pair_decimal_hours_to_minutes(struct pair h, struct pair m, uint32_t *const n);
const char *m0, const char *const m1, uint32_t *const n);
int pair_is_equal(struct pair, struct pair); int pair_is_equal(struct pair, struct pair);
int pair_is_string(struct pair, const char *); int pair_is_string(struct pair, const char *);
#include "journal.h" /* date32 */ #include "journal.h" /* date32 */
int pair_to_date(const char *, union date32 *); int pair_to_date(const unsigned char *a, union date32 *);
int pair_to_cents(const char *, const char *, int64_t *); int pair_to_cents(struct pair p, int64_t *);
uint32_t pair_djb2(struct pair); uint32_t pair_djb2(struct pair);
/* Supporting pair -> size_t for looking up in arrays. */ /* Supporting pair -> size_t for looking up in arrays. */

View File

@@ -147,7 +147,7 @@ struct scan {
} edits; } edits;
struct linepair_tree dreams; struct linepair_tree dreams;
struct linekvpair_tree contacts, books, tvs, movies, ideas, struct linekvpair_tree contacts, books, tvs, movies, ideas,
vaccines, medications, mails, couches; vaccines, medications, labs, mails, couches;
struct linekvdate_tree froms; struct linekvdate_tree froms;
struct linekvmoney_tree taxes, incomes; struct linekvmoney_tree taxes, incomes;
struct glider_tree gliders; struct glider_tree gliders;
@@ -159,6 +159,7 @@ void scan_(struct scan *);
struct scan scan(struct journal *); struct scan scan(struct journal *);
const struct kvpair *scan_source_lookup(struct scan *, const union line64); const struct kvpair *scan_source_lookup(struct scan *, const union line64);
void scan_score_graph(struct scan *); void scan_score_graph(struct scan *);
void scan_labs_graph(struct scan *);
void scan_glider_graph(struct scan *); void scan_glider_graph(struct scan *);
void scan_flight_graph(struct scan *); void scan_flight_graph(struct scan *);
void scan_kjv_graph(struct scan *); void scan_kjv_graph(struct scan *);

View File

@@ -163,17 +163,22 @@ static int kjv_compare(const union line64 a, const union line64 b)
#include "../src/tree.h" #include "../src/tree.h"
/*!conditions:re2c*/ /*!conditions:re2c */
/*!flags:utf-8 */
/*!include:re2c "unicode_categories.re" */
static int scan_day(struct scan *const scan, union date32 date, static int scan_day(struct scan *const scan, union date32 date,
const char *const buffer) { const char *const buffer) {
const char *YYCURSOR, *YYMARKER, *yyt1, *yyt2, *yyt3, *s0, *s1, *t0, *t1; const unsigned char *const buffer_u = (const unsigned char *)buffer,
*YYCURSOR, *YYMARKER, *yyt1, *yyt2, *yyt3,
*lastnl = buffer_u, *s0 = 0, *s1, *t0, *t1;
enum YYCONDTYPE condition = yycline; enum YYCONDTYPE condition = yycline;
/* All '\n' might overflow on last, but it wouldn't matter because there's /* All '\n' might overflow on last, but it wouldn't matter because there's
no content. */ no content. */
size_t line = 1; size_t line = 1;
char datestr[12] = {0}; char datestr[12] = {0};
const char *fail = "perhaps a bat?", *lastnl = buffer; const char *fail = "perhaps a bat?";
struct { struct {
enum YYCONDTYPE future; enum YYCONDTYPE future;
union { union {
@@ -189,11 +194,11 @@ static int scan_day(struct scan *const scan, union date32 date,
} kjv = { Revelation, 0, 0, 0 }; } kjv = { Revelation, 0, 0, 0 };
assert(scan && date.u32 && buffer); assert(scan && date.u32 && buffer);
YYCURSOR = YYMARKER = yyt1 = buffer; YYCURSOR = YYMARKER = yyt1 = buffer_u;
date32_to_string(date, &datestr); date32_to_string(date, &datestr);
/*!re2c /**/ /*!re2c /**/
re2c:define:YYCTYPE = char; re2c:define:YYCTYPE = "unsigned char";
re2c:yyfill:enable = 0; re2c:yyfill:enable = 0;
re2c:define:YYGETCONDITION = "condition"; re2c:define:YYGETCONDITION = "condition";
re2c:define:YYSETCONDITION = "condition = @@;"; re2c:define:YYSETCONDITION = "condition = @@;";
@@ -215,7 +220,11 @@ static int scan_day(struct scan *const scan, union date32 date,
// label except start "()"; used in location // label except start "()"; used in location
parlabel = (parchar glyph*) (ws+ glyph+)*; parlabel = (parchar glyph*) (ws+ glyph+)*;
keyword = [A-Za-z0-9][A-Za-z0-9_-]*; //keyword = [A-Za-z0-9][A-Za-z0-9_-]*;
//keyword = [A-Za-z0-9_-é]+;
//keyword = [A-Za-z0-9_-]_;
// letter number dash connector
keyword = (L|N) (L|N|Pd|Pc)*;
uint = [0-9]+; uint = [0-9]+;
natural = [1-9][0-9]*; natural = [1-9][0-9]*;
@@ -225,13 +234,14 @@ static int scan_day(struct scan *const scan, union date32 date,
airport = [A-Z0-9]{4,4}; airport = [A-Z0-9]{4,4};
moneyamount = "-"? [0-9]+ ("." [0-9][0-9])?; // fixme? moneyamount = "-"? [0-9]+ ("." [0-9][0-9])?; // fixme?
kjvlookat = ws* natural ":" natural [ab]? ("-" natural [ab]?)? ws+ "--" ws+; kjvlookat = ws* natural ":" natural [ab]? ("-" natural [ab]?)? ws+ "--" ws+;
first = ("I" | "1") " "?; first = ("I" | "1" | "") " "?;
second = ("II" | "2") " "?; second = ("II" | "2" | "") " "?;
third = ("III" | "3") " "?; third = ("III" | "3" | "") " "?;
*/ */
for( ; ; ) { for( ; ; ) {
/*!re2c /**/ /*!re2c /**/
<skip> [^\n\x00] { continue; } /* Default ignore. */ //<skip> [^\n\x00] { continue; } /* Default ignore. */
<skip> * { continue; }
<newline> * { fail = "newline expected"; goto catch; } <newline> * { fail = "newline expected"; goto catch; }
<skip> "\x00" { fail = "no newline at end of file"; goto catch; } <skip> "\x00" { fail = "no newline at end of file"; goto catch; }
<line> "\x00" { return 1; } /* End of day. */ <line> "\x00" { return 1; } /* End of day. */
@@ -256,6 +266,7 @@ static int scan_day(struct scan *const scan, union date32 date,
<bracket> "idea: " :=> idea <bracket> "idea: " :=> idea
<bracket> "vaccine: " :=> vaccine <bracket> "vaccine: " :=> vaccine
<bracket> "medication: " :=> medication <bracket> "medication: " :=> medication
<bracket> "lab: " :=> lab
<bracket> "tax: " :=> tax <bracket> "tax: " :=> tax
<bracket> "in: " :=> income <bracket> "in: " :=> income
<bracket> "mail: " :=> mail <bracket> "mail: " :=> mail
@@ -290,7 +301,7 @@ static int scan_day(struct scan *const scan, union date32 date,
size_t *pi; size_t *pi;
struct kvpair *doc; struct kvpair *doc;
if(!(doc = kvpair_array_new(&scan->documents.array))) goto catch; if(!(doc = kvpair_array_new(&scan->documents.array))) goto catch;
doc->key.a = s0, doc->key.b = s1; doc->key.a = (const char *)s0, doc->key.b = (const char *)s1;
doc->value.a = 0, doc->value.b = 0; doc->value.a = 0, doc->value.b = 0;
input.future = yycnewline, input.pair = &doc->value; input.future = yycnewline, input.pair = &doc->value;
switch(linemap_tree_bulk_assign(&scan->documents.dates, key, &pi)) { switch(linemap_tree_bulk_assign(&scan->documents.dates, key, &pi)) {
@@ -332,7 +343,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new contact <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new contact <<%.*s>>.\n",
@@ -348,7 +359,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new book <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new book <<%.*s>>.\n",
@@ -364,7 +375,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new tv <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new tv <<%.*s>>.\n",
@@ -380,7 +391,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new movie <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new movie <<%.*s>>.\n",
@@ -396,7 +407,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new idea <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new idea <<%.*s>>.\n",
@@ -412,7 +423,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new vaccine <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new vaccine <<%.*s>>.\n",
@@ -428,7 +439,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new medication <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new medication <<%.*s>>.\n",
@@ -436,6 +447,22 @@ static int scan_day(struct scan *const scan, union date32 date,
continue; continue;
} }
<lab> * { fail = "lab unrecognized"; goto catch; }
<lab> @s0 bralabel @s1 "]" => input_text {
const union line64 key = { { (uint32_t)line, date } };
struct kvpair *pair;
switch(linekvpair_tree_bulk_assign(&scan->labs, key, &pair)) {
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break;
}
pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new lab <<%.*s>>.\n",
datestr, line, (int)(s1 - s0), s0);
continue;
}
<tax> * { fail = "tax unrecognized"; goto catch; } <tax> * { fail = "tax unrecognized"; goto catch; }
<tax> @s0 bralabel @s1 "]" => input_money { <tax> @s0 bralabel @s1 "]" => input_money {
const union line64 key = { { (uint32_t)line, date } }; const union line64 key = { { (uint32_t)line, date } };
@@ -444,7 +471,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value = (struct money){0, CAD}; pair->value = (struct money){0, CAD};
input.future = yycnewline, input.money = &pair->value; input.future = yycnewline, input.money = &pair->value;
fprintf(stderr, "%s:%zu: new tax <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new tax <<%.*s>>.\n",
@@ -460,7 +487,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value = (struct money){0, CAD}; pair->value = (struct money){0, CAD};
input.future = yycline, input.money = &pair->value; input.future = yycline, input.money = &pair->value;
fprintf(stderr, "%s:%zu: new income <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new income <<%.*s>>.\n",
@@ -476,7 +503,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new mail <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new mail <<%.*s>>.\n",
@@ -492,7 +519,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
pair->key.a = s0, pair->key.b = s1; pair->key = pair_u(s0, s1);
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new couch <<%.*s>>.\n", fprintf(stderr, "%s:%zu: new couch <<%.*s>>.\n",
@@ -508,7 +535,7 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
if(!pair_to_date(s0, &pair->key)) goto catch; if(!pair_to_date(s0, &pair->key)) goto catch; /* hmm */
pair->value.a = pair->value.b = 0; pair->value.a = pair->value.b = 0;
input.future = yycnewline, input.pair = &pair->value; input.future = yycnewline, input.pair = &pair->value;
fprintf(stderr, "%s:%zu: new from.\n", datestr, line); fprintf(stderr, "%s:%zu: new from.\n", datestr, line);
@@ -517,7 +544,7 @@ static int scan_day(struct scan *const scan, union date32 date,
<place> * { fail = "place unrecognized"; goto catch; } <place> * { fail = "place unrecognized"; goto catch; }
<place> @s0 parlabel @s1 / "\n" => skip { also_place: { <place> @s0 parlabel @s1 / "\n" => skip { also_place: {
const struct pair keyword = pair(s0, s1); const struct pair keyword = pair_u(s0, s1);
const union line64 key = { { (uint32_t)line, date } }; const union line64 key = { { (uint32_t)line, date } };
size_t i, *pi; size_t i, *pi;
/*fprintf(stderr, "map: <<%.*s>> out of %s\n", (int)(s1 - s0), s0, /*fprintf(stderr, "map: <<%.*s>> out of %s\n", (int)(s1 - s0), s0,
@@ -533,8 +560,8 @@ static int scan_day(struct scan *const scan, union date32 date,
} continue; } } continue; }
<place> "(" @t0 decimal "," @t1 decimal ")" <place> "(" @t0 decimal "," @t1 decimal ")"
ws+ @s0 parlabel @s1 / "\n" => skip { ws+ @s0 parlabel @s1 / "\n" => skip {
const struct pair keyword = pair(s0, s1); const struct pair keyword = pair_u(s0, s1);
const double x = strtod(t0, 0), y = strtod(t1, 0); /* Safe? */ const double x = strtod(keyword.a, 0), y = strtod(keyword.b, 0);
size_t *idx; size_t *idx;
struct place *place; struct place *place;
switch(pair_map_table_assign(&scan->places.map, keyword, &idx)) { switch(pair_map_table_assign(&scan->places.map, keyword, &idx)) {
@@ -544,7 +571,7 @@ static int scan_day(struct scan *const scan, union date32 date,
} }
if(!(place = place_array_new(&scan->places.array))) goto catch; if(!(place = place_array_new(&scan->places.array))) goto catch;
*idx = (size_t)(place - scan->places.array.data); *idx = (size_t)(place - scan->places.array.data);
place->name.a = s0, place->name.b = s1; place->name = keyword;
place->x = x, place->y = y; place->x = x, place->y = y;
fprintf(stderr, fprintf(stderr,
"%s:%zu: new place: <<%.*s>> at (%f,%f) stored at %zu.\n", "%s:%zu: new place: <<%.*s>> at (%f,%f) stored at %zu.\n",
@@ -555,7 +582,8 @@ static int scan_day(struct scan *const scan, union date32 date,
<place> "(" @t0 decimal "," @t1 decimal ")" / "\n" => skip { <place> "(" @t0 decimal "," @t1 decimal ")" / "\n" => skip {
size_t *idx; size_t *idx;
struct place *place; struct place *place;
const double x = strtod(t0, 0), y = strtod(t1, 0); /* Safe? */ const struct pair t = pair_u(t0, t1);
const double x = strtod(t.a, 0), y = strtod(t.b, 0); /* Safe? */
const union line64 key = { { (uint32_t)line, date } }; const union line64 key = { { (uint32_t)line, date } };
if(!(place = place_array_new(&scan->places.array))) goto catch; if(!(place = place_array_new(&scan->places.array))) goto catch;
place->name.a = place->name.b = 0; place->name.a = place->name.b = 0;
@@ -572,7 +600,7 @@ static int scan_day(struct scan *const scan, union date32 date,
<source> * { fail = "source unrecognized"; goto catch; } <source> * { fail = "source unrecognized"; goto catch; }
<source> @s0 keyword @s1 / "\n" => skip { also_source: { <source> @s0 keyword @s1 / "\n" => skip { also_source: {
const struct pair keyword = pair(s0, s1); const struct pair keyword = pair_u(s0, s1);
const union line64 key = { { (uint32_t)line, date } }; const union line64 key = { { (uint32_t)line, date } };
size_t i, *pi; size_t i, *pi;
if(!(i = pair_map_table_get(&scan->sources.map, keyword))) if(!(i = pair_map_table_get(&scan->sources.map, keyword)))
@@ -586,7 +614,7 @@ static int scan_day(struct scan *const scan, union date32 date,
} continue; } } continue; }
/* New source. */ /* New source. */
<source> @s0 keyword @s1 ":" => input_text { <source> @s0 keyword @s1 ":" => input_text {
struct pair keyword = pair(s0, s1); struct pair keyword = pair_u(s0, s1);
size_t *idx; size_t *idx;
struct kvpair *source; struct kvpair *source;
switch(pair_map_table_assign(&scan->sources.map, keyword, &idx)) { switch(pair_map_table_assign(&scan->sources.map, keyword, &idx)) {
@@ -596,7 +624,7 @@ static int scan_day(struct scan *const scan, union date32 date,
} }
if(!(source = kvpair_array_new(&scan->sources.array))) goto catch; if(!(source = kvpair_array_new(&scan->sources.array))) goto catch;
*idx = (size_t)(source - scan->sources.array.data); *idx = (size_t)(source - scan->sources.array.data);
source->key.a = s0, source->key.b = s1; source->key = keyword;
source->value.a = 0, source->value.b = 0; source->value.a = 0, source->value.b = 0;
input.future = yycnewline, input.pair = &source->value; input.future = yycnewline, input.pair = &source->value;
fprintf(stderr, "%s:%zu: new source <<%.*s>> stored at %zu.\n", fprintf(stderr, "%s:%zu: new source <<%.*s>> stored at %zu.\n",
@@ -609,7 +637,7 @@ static int scan_day(struct scan *const scan, union date32 date,
/* Already there. Use the map to get the index from the keyword and /* Already there. Use the map to get the index from the keyword and
then stick a marker in the tree with that index. */ then stick a marker in the tree with that index. */
<score> @s0 keyword @s1 / "\n" => skip { new_score: { <score> @s0 keyword @s1 / "\n" => skip { new_score: {
const struct pair keyword = pair(s0, s1); const struct pair keyword = pair_u(s0, s1);
const union line64 key = { { (uint32_t)line, date } }; const union line64 key = { { (uint32_t)line, date } };
size_t idx, *pidx; size_t idx, *pidx;
if(!(idx = pair_map_table_get(&scan->scores.map, keyword))) if(!(idx = pair_map_table_get(&scan->scores.map, keyword)))
@@ -628,10 +656,10 @@ static int scan_day(struct scan *const scan, union date32 date,
/* New score. */ /* New score. */
<score> @s0 keyword @s1 ":" => score_name { <score> @s0 keyword @s1 ":" => score_name {
size_t *idx; size_t *idx;
const struct pair keyword = pair_u(s0, s1);
assert(!new_score); assert(!new_score);
/* Create a new mapping from dateline to scores array. */ /* Create a new mapping from dateline to scores array. */
switch(pair_map_table_assign(&scan->scores.map, switch(pair_map_table_assign(&scan->scores.map, keyword, &idx)) {
pair(s0, s1), &idx)) {
case TABLE_PRESENT: errno = EDOM; fail = "new keyword already used"; case TABLE_PRESENT: errno = EDOM; fail = "new keyword already used";
case TABLE_ERROR: goto catch; /* _Sic_. */ case TABLE_ERROR: goto catch; /* _Sic_. */
case TABLE_ABSENT: *idx = 0; break; case TABLE_ABSENT: *idx = 0; break;
@@ -640,7 +668,7 @@ static int scan_day(struct scan *const scan, union date32 date,
if(!(new_score = score_array_new(&scan->scores.array))) goto catch; if(!(new_score = score_array_new(&scan->scores.array))) goto catch;
*idx = (size_t)(new_score - scan->scores.array.data); /* Offset. */ *idx = (size_t)(new_score - scan->scores.array.data); /* Offset. */
/*struct pair key, name; union date32 date, last; unsigned edges;*/ /*struct pair key, name; union date32 date, last; unsigned edges;*/
new_score->key.a = s0, new_score->key.b = s1; new_score->key = keyword;
new_score->name.a = 0, new_score->name.b = 0; new_score->name.a = 0, new_score->name.b = 0;
new_score->date.u32 = new_score->last.u32 = 0; new_score->date.u32 = new_score->last.u32 = 0;
new_score->edges = 0, new_score->score = 0; new_score->edges = 0, new_score->score = 0;
@@ -651,7 +679,7 @@ static int scan_day(struct scan *const scan, union date32 date,
<score_name> * { fail = "name unrecognized"; goto catch; } <score_name> * { fail = "name unrecognized"; goto catch; }
<score_name> ws* @s0 semilabel @s1 ";" => score_date { <score_name> ws* @s0 semilabel @s1 ";" => score_date {
assert(new_score); assert(new_score);
new_score->name.a = s0, new_score->name.b = s1; new_score->name = pair_u(s0, s1);
continue; continue;
} }
<score_date> * { fail = "date unrecognized"; goto catch; } <score_date> * { fail = "date unrecognized"; goto catch; }
@@ -662,8 +690,9 @@ static int scan_day(struct scan *const scan, union date32 date,
} }
<score_edges> * { fail = "edges unrecognized"; goto catch; } <score_edges> * { fail = "edges unrecognized"; goto catch; }
<score_edges> ws* "~"? @s0 uint @s1 / "\n" => skip { <score_edges> ws* "~"? @s0 uint @s1 / "\n" => skip {
const struct pair s = pair_u(s0, s1);
assert(new_score); assert(new_score);
if(!pair_to_natural(s0, s1, &new_score->edges)) goto catch; if(!pair_to_natural(s, &new_score->edges)) goto catch;
new_score = 0; /* Done. */ new_score = 0; /* Done. */
continue; continue;
} }
@@ -679,15 +708,15 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch; case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
new_glider->type.a = s0, new_glider->type.b = s1; new_glider->type = pair_u(s0, s1);
continue; continue;
} }
<glider_reg> * { fail = "glider reg"; goto catch; } <glider_reg> * { fail = "glider reg"; goto catch; }
<glider_reg> ws* @s0 semilabel @s1 ";" => glider_launch <glider_reg> ws* @s0 semilabel @s1 ";" => glider_launch
{ new_glider->reg.a = s0, new_glider->reg.b = s1; continue; } { new_glider->reg = pair_u(s0, s1); continue; }
<glider_launch> * { fail = "glider launch"; goto catch; } <glider_launch> * { fail = "glider launch"; goto catch; }
<glider_launch> ws* @s0 airport @s1 ";" => glider_how { <glider_launch> ws* @s0 airport @s1 ";" => glider_how {
new_glider->launch.a = s0, new_glider->launch.b = s1; new_glider->launch = pair_u(s0, s1);
fprintf(stderr, "%s:%zu: glider <<%.*s>> at <<%.*s>>\n", fprintf(stderr, "%s:%zu: glider <<%.*s>> at <<%.*s>>\n",
datestr, line, (int)(new_glider->reg.b - new_glider->reg.a), datestr, line, (int)(new_glider->reg.b - new_glider->reg.a),
new_glider->reg.a, (int)(s1 - s0), s0); new_glider->reg.a, (int)(s1 - s0), s0);
@@ -703,38 +732,46 @@ static int scan_day(struct scan *const scan, union date32 date,
continue; continue;
} }
<glider_height> * { fail = "glider height"; goto catch; } <glider_height> * { fail = "glider height"; goto catch; }
<glider_height> ws* @s0 natural @s1 "';" => glider_landing <glider_height> ws* @s0 natural @s1 "';" => glider_landing {
{ if(!pair_to_natural(s0, s1, &new_glider->height_ft)); continue; } const struct pair s = pair_u(s0, s1);
if(!pair_to_natural(s, &new_glider->height_ft));
continue;
}
<glider_landing> * { fail = "glider landing"; goto catch; } <glider_landing> * { fail = "glider landing"; goto catch; }
<glider_landing> ws* @s0 airport @s1 ";" => glider_pilot <glider_landing> ws* @s0 airport @s1 ";" => glider_pilot
{ new_glider->landing.a = s0, new_glider->landing.b = s1; continue;} { new_glider->landing = pair_u(s0, s1); continue;}
<glider_pilot> * { fail = "glider pilot time"; goto catch; } <glider_pilot> * { fail = "glider pilot time"; goto catch; }
<glider_pilot> ws* ";" => glider_dual /* not PIC */ <glider_pilot> ws* ";" => glider_dual /* not PIC */
{ new_glider->pilot_min = 0; continue; } { new_glider->pilot_min = 0; continue; }
<glider_pilot> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";" <glider_pilot> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";"
=> glider_dual { if(!pair_colon_to_minutes(s0, s1, t0, t1, => glider_dual {
if(!pair_colon_to_minutes(pair_u(s0, s1), pair_u(t0, t1),
&new_glider->pilot_min)) { fail = "glider pilot time"; goto catch; } &new_glider->pilot_min)) { fail = "glider pilot time"; goto catch; }
continue; } continue; }
<glider_dual> * { fail = "glider dual time"; goto catch; } <glider_dual> * { fail = "glider dual time"; goto catch; }
<glider_dual> ws* ";" => glider_instr <glider_dual> ws* ";" => glider_instr
{ new_glider->dual_min = 0; continue; } { new_glider->dual_min = 0; continue; }
<glider_dual> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";" <glider_dual> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";"
=> glider_instr { if(!pair_colon_to_minutes(s0, s1, t0, t1, => glider_instr {
if(!pair_colon_to_minutes(pair_u(s0, s1), pair_u(t0, t1),
&new_glider->dual_min)) { fail = "glider dual time"; goto catch; } &new_glider->dual_min)) { fail = "glider dual time"; goto catch; }
continue; } continue;
}
<glider_instr> * { fail = "glider instr time"; goto catch; } <glider_instr> * { fail = "glider instr time"; goto catch; }
<glider_instr> ws* ";" => glider_remarks <glider_instr> ws* ";" => glider_remarks
{ new_glider->instr_min = 0; continue; } { new_glider->instr_min = 0; continue; }
<glider_instr> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";" <glider_instr> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";"
=> glider_remarks { if(!pair_hours_to_minutes(s0, s1, t0, t1, => glider_remarks {
if(!pair_decimal_hours_to_minutes(pair_u(s0, s1), pair_u(t0, t1),
&new_glider->instr_min)) { fail = "glider instr time"; goto catch; } &new_glider->instr_min)) { fail = "glider instr time"; goto catch; }
continue; } continue;
}
<glider_remarks> * { fail = "glider remarks"; goto catch; } <glider_remarks> * { fail = "glider remarks"; goto catch; }
<glider_remarks> "\n" @s1 => line <glider_remarks> "\n" @s1 => line
{ new_glider->remarks.a = new_glider->remarks.b = 0; { new_glider->remarks.a = new_glider->remarks.b = 0;
new_glider = 0; line++; lastnl = s1; continue; } new_glider = 0; line++; lastnl = s1; continue; }
<glider_remarks> ws* @s0 anylabel @s1 "\n" @t1 => line <glider_remarks> ws* @s0 anylabel @s1 "\n" @t1 => line
{ new_glider->remarks.a = s0, new_glider->remarks.b = s1; { new_glider->remarks = pair_u(s0, s1);
new_glider = 0; line++; lastnl = t1; continue; } new_glider = 0; line++; lastnl = t1; continue; }
@@ -749,17 +786,17 @@ static int scan_day(struct scan *const scan, union date32 date,
case TREE_ERROR: goto catch; case TREE_ERROR: goto catch;
case TREE_ABSENT: break; case TREE_ABSENT: break;
} }
new_flight->type.a = s0, new_flight->type.b = s1; new_flight->type = pair_u(s0, s1);
continue; continue;
} }
<flight_reg> * { fail = "flight reg"; goto catch; } <flight_reg> * { fail = "flight reg"; goto catch; }
<flight_reg> ws* @s0 semilabel @s1 ";" => flight_airports <flight_reg> ws* @s0 semilabel @s1 ";" => flight_airports
{ new_flight->reg.a = s0, new_flight->reg.b = s1; continue; } { new_flight->reg = pair_u(s0, s1); continue; }
<flight_airports> * { fail = "flight airports"; goto catch; } <flight_airports> * { fail = "flight airports"; goto catch; }
<flight_airports> ws* @s0 airport @s1 ws* "--" <flight_airports> ws* @s0 airport @s1 ws* "--"
ws* @t0 airport @t1 ws* ";" => flight_pic { ws* @t0 airport @t1 ws* ";" => flight_pic {
new_flight->launch.a = s0, new_flight->launch.b = s1; new_flight->launch = pair_u(s0, s1);
new_flight->landing.a = t0, new_flight->landing.b = t1; new_flight->landing = pair_u(t0, t1);
fprintf(stderr, "%s:%zu: flight <<%.*s>> at <<%.*s>>\n", fprintf(stderr, "%s:%zu: flight <<%.*s>> at <<%.*s>>\n",
datestr, line, (int)(new_flight->reg.b - new_flight->reg.a), datestr, line, (int)(new_flight->reg.b - new_flight->reg.a),
new_flight->reg.a, (int)(s1 - s0), s0); new_flight->reg.a, (int)(s1 - s0), s0);
@@ -767,38 +804,42 @@ static int scan_day(struct scan *const scan, union date32 date,
} }
<flight_pic> * { fail = "flight pic"; goto catch; } <flight_pic> * { fail = "flight pic"; goto catch; }
<flight_pic> ws* @s0 semilabel @s1 ";" => flight_sic <flight_pic> ws* @s0 semilabel @s1 ";" => flight_sic
{ new_flight->pilot.a = s0, new_flight->pilot.b = s1; continue; } { new_flight->pilot = pair_u(s0, s1); continue; }
<flight_sic> * { fail = "flight sic"; goto catch; } <flight_sic> * { fail = "flight sic"; goto catch; }
<flight_sic> ws* ";" => flight_dual <flight_sic> ws* ";" => flight_dual
{ new_flight->copilot.a = new_flight->copilot.b = 0; continue; } { new_flight->copilot.a = new_flight->copilot.b = 0; continue; }
<flight_sic> ws* @s0 semilabel @s1 ";" => flight_dual <flight_sic> ws* @s0 semilabel @s1 ";" => flight_dual
{ new_flight->copilot.a = s0, new_flight->copilot.b = s1; continue; } { new_flight->copilot = pair_u(s0, s1); continue; }
<flight_dual> * { fail = "flight dual time"; goto catch; } <flight_dual> * { fail = "flight dual time"; goto catch; }
<flight_dual> ws* ";" => flight_pilot <flight_dual> ws* ";" => flight_pilot
{ new_flight->dual_min = 0; continue; } { new_flight->dual_min = 0; continue; }
<flight_dual> ws* @s0 [0-9]* @s1 "." @t0 [0-9] @t1 "h" ws* ";" <flight_dual> ws* @s0 [0-9]* @s1 "." @t0 [0-9] @t1 "h" ws* ";"
=> flight_pilot { if(!pair_hours_to_minutes(s0, s1, t0, t1, => flight_pilot {
if(!pair_decimal_hours_to_minutes(pair_u(s0, s1), pair_u(t0, t1),
&new_flight->dual_min)) { fail = "flight dual time"; goto catch; } &new_flight->dual_min)) { fail = "flight dual time"; goto catch; }
continue; } continue; }
<flight_pilot> * { fail = "flight pilot time"; goto catch; } <flight_pilot> * { fail = "flight pilot time"; goto catch; }
<flight_pilot> ws* ";" => flight_ifrsim <flight_pilot> ws* ";" => flight_ifrsim
{ new_flight->pilot_min = 0; continue; } { new_flight->pilot_min = 0; continue; }
<flight_pilot> ws* @s0 [0-9]* @s1 "." @t0 [0-9] @t1 "h" ws* ";" <flight_pilot> ws* @s0 [0-9]* @s1 "." @t0 [0-9] @t1 "h" ws* ";"
=> flight_ifrsim { if(!pair_hours_to_minutes(s0, s1, t0, t1, => flight_ifrsim {
if(!pair_decimal_hours_to_minutes(pair_u(s0, s1), pair_u(t0, t1),
&new_flight->pilot_min)) { fail = "flight pilot time"; &new_flight->pilot_min)) { fail = "flight pilot time";
goto catch; } continue; } goto catch; } continue; }
<flight_ifrsim> * { fail = "flight simulated ifr time"; goto catch; } <flight_ifrsim> * { fail = "flight simulated ifr time"; goto catch; }
<flight_ifrsim> ws* ";" => flight_ifr <flight_ifrsim> ws* ";" => flight_ifr
{ new_flight->ifrsim_min = 0; continue; } { new_flight->ifrsim_min = 0; continue; }
<flight_ifrsim> ws* @s0 [0-9]* @s1 "." @t0 [0-9] @t1 "h" ws* ";" <flight_ifrsim> ws* @s0 [0-9]* @s1 "." @t0 [0-9] @t1 "h" ws* ";"
=> flight_ifr { if(!pair_hours_to_minutes(s0, s1, t0, t1, => flight_ifr {
if(!pair_decimal_hours_to_minutes(pair_u(s0, s1), pair_u(t0, t1),
&new_flight->ifrsim_min)) { fail = "flight simulated ifr time"; &new_flight->ifrsim_min)) { fail = "flight simulated ifr time";
goto catch; } continue; } goto catch; } continue; }
<flight_ifr> * { fail = "flight ifr time"; goto catch; } <flight_ifr> * { fail = "flight ifr time"; goto catch; }
<flight_ifr> ws* ";" => flight_remarks <flight_ifr> ws* ";" => flight_remarks
{ new_flight->ifr_min = 0; continue; } { new_flight->ifr_min = 0; continue; }
<flight_ifr> ws* @s0 [0-9]* @s1 "." @t0 [0-9] @t1 "h" ws* ";" <flight_ifr> ws* @s0 [0-9]* @s1 "." @t0 [0-9] @t1 "h" ws* ";"
=> flight_remarks { if(!pair_hours_to_minutes(s0, s1, t0, t1, => flight_remarks {
if(!pair_decimal_hours_to_minutes(pair_u(s0, s1), pair_u(t0, t1),
&new_flight->ifr_min)) { fail = "flight ifr time"; goto catch; } &new_flight->ifr_min)) { fail = "flight ifr time"; goto catch; }
continue; } continue; }
<flight_remarks> * { fail = "flight remarks"; goto catch; } <flight_remarks> * { fail = "flight remarks"; goto catch; }
@@ -806,7 +847,7 @@ static int scan_day(struct scan *const scan, union date32 date,
{ new_flight->remarks.a = new_flight->remarks.b = 0; { new_flight->remarks.a = new_flight->remarks.b = 0;
new_flight = 0; line++; lastnl = s1; continue; } new_flight = 0; line++; lastnl = s1; continue; }
<flight_remarks> ws* @s0 anylabel @s1 "\n" @t1 => line <flight_remarks> ws* @s0 anylabel @s1 "\n" @t1 => line
{ new_flight->remarks.a = s0, new_flight->remarks.b = s1; { new_flight->remarks = pair_u(s0, s1);
new_flight = 0; line++; lastnl = t1; continue; } new_flight = 0; line++; lastnl = t1; continue; }
@@ -884,19 +925,19 @@ static int scan_day(struct scan *const scan, union date32 date,
<kjvbook> " " @s0 natural @s1 ":" @t0 natural @t1 [ab]? { <kjvbook> " " @s0 natural @s1 ":" @t0 natural @t1 [ab]? {
if(kjv.chapter || kjv.verse || kjv.verse_end) if(kjv.chapter || kjv.verse || kjv.verse_end)
{ fail = "kjv reference"; goto catch; } { fail = "kjv reference"; goto catch; }
if(!pair_to_natural(s0, s1, &kjv.chapter) if(!pair_to_natural(pair_u(s0, s1), &kjv.chapter)
|| !pair_to_natural(t0, t1, &kjv.verse)) || !pair_to_natural(pair_u(t0, t1), &kjv.verse))
{ fail = "kjv reference numerical error"; goto catch; } { fail = "kjv reference numerical error"; goto catch; }
continue; continue;
} }
<kjvbook> "-" @s0 natural @s1 [ab]? { /* Verse range. */ <kjvbook> "" @s0 natural @s1 [ab]? { /* Verse range. */
if(!kjv.chapter || !kjv.verse || kjv.verse_end) if(!kjv.chapter || !kjv.verse || kjv.verse_end)
{ fail = "kjv range unrecognized"; goto catch; } { fail = "kjv range unrecognized"; goto catch; }
if(!pair_to_natural(s0, s1, &kjv.verse_end)) if(!pair_to_natural(pair_u(s0, s1), &kjv.verse_end))
{ fail = "kjv range numerical error"; goto catch; } { fail = "kjv range numerical error"; goto catch; }
continue; continue;
} }
<kjvbook> " -- " => skip { <kjvbook> " " => skip {
if(!kjv.chapter || !kjv.verse) if(!kjv.chapter || !kjv.verse)
{ fail = "kjv missing information"; goto catch; } { fail = "kjv missing information"; goto catch; }
if(kjv.verse_end && kjv.verse_end <= kjv.verse) if(kjv.verse_end && kjv.verse_end <= kjv.verse)
@@ -927,14 +968,13 @@ static int scan_day(struct scan *const scan, union date32 date,
all the things this way. */ all the things this way. */
<input_text, input_text_multi> * { fail = "text input"; goto catch; } <input_text, input_text_multi> * { fail = "text input"; goto catch; }
<input_text> ws { continue; } <input_text> ws { continue; }
<input_text> "<<\n" @s0 => input_text_multi { // multi-line <input_text> "<<\n" @s0 => input_text_multi { // multi-line: set `s0`.
input.pair->a = s0;
line++; lastnl = s0; line++; lastnl = s0;
continue; continue;
} }
<input_text> @s0 anylabel? @s1 "\n" @t0 => line { // one line; last one <input_text> @s0 anylabel? @s1 "\n" @t0 => line { // one line; last one
/*fprintf(stderr, "text: <<%.*s>>\n", (int)(s1 - s0), s0);*/ /*fprintf(stderr, "text: <<%.*s>>\n", (int)(s1 - s0), s0);*/
input.pair->a = s0, input.pair->b = s1; *input.pair = pair_u(s0, s1);
if(input.future != yycnewline) if(input.future != yycnewline)
{ fail = "use <<text>>"; goto catch; } { fail = "use <<text>>"; goto catch; }
line++; lastnl = t0; line++; lastnl = t0;
@@ -944,10 +984,9 @@ static int scan_day(struct scan *const scan, union date32 date,
<input_text_multi> [\x00] <input_text_multi> [\x00]
{ fail = "missing closing \">>\""; goto catch; } { fail = "missing closing \">>\""; goto catch; }
<input_text_multi> "\n" @s1 { line++; lastnl = s1; continue; } <input_text_multi> "\n" @s1 { line++; lastnl = s1; continue; }
<input_text_multi> @s1 ">>" / [^>] /*future*/ { <input_text_multi> @s1 ">>" / [^>] /* future, `s0` */ {
/*fprintf(stderr, "text: <<\n%.*s>>\n", *input.pair = pair_u(s0, s1);
(int)(s1 - input.pair->a), input.pair->a);*/ fprintf(stderr, "text: <<\n%.*s>>\n", (int)(s1 - s0), s0);
input.pair->b = s1;
condition = input.future; condition = input.future;
continue; continue;
} }
@@ -956,7 +995,7 @@ static int scan_day(struct scan *const scan, union date32 date,
{ fail = "money input"; goto catch; } { fail = "money input"; goto catch; }
<input_money> ws { continue; } <input_money> ws { continue; }
<input_money> @s0 moneyamount @s1 => input_money_currency { <input_money> @s0 moneyamount @s1 => input_money_currency {
if(!pair_to_cents(s0, s1, &input.money->cents)) goto catch; if(!pair_to_cents(pair_u(s0, s1), &input.money->cents)) goto catch;
printf("input_money: amount %" PRId64 "\n", input.money->cents); printf("input_money: amount %" PRId64 "\n", input.money->cents);
continue; continue;
} }
@@ -971,8 +1010,12 @@ static int scan_day(struct scan *const scan, union date32 date,
catch: catch:
if(!errno) errno = EILSEQ; if(!errno) errno = EILSEQ;
date32_to_string(date, &datestr); date32_to_string(date, &datestr);
if(s1 = strchr(lastnl, '\n')) { {
fprintf(stderr, "%.*s\n", (int)(s1 - lastnl), lastnl); const char *const lastnl_s = (const char *)lastnl;
char *result;
if(result = strchr(lastnl_s, '\n')) {
fprintf(stderr, "%.*s\n", (int)(result - lastnl_s), lastnl_s);
}
} }
fprintf(stderr, fprintf(stderr,
"%s:%zu fail: %s" /*" condition %d"*/ ".\n", "%s:%zu fail: %s" /*" condition %d"*/ ".\n",
@@ -989,6 +1032,7 @@ void scan_(struct scan *const scan) {
linekvmoney_tree_(&scan->taxes); linekvmoney_tree_(&scan->taxes);
linekvdate_tree_(&scan->froms); linekvdate_tree_(&scan->froms);
linekvpair_tree_(&scan->couches); linekvpair_tree_(&scan->couches);
linekvpair_tree_(&scan->labs);
linekvpair_tree_(&scan->medications); linekvpair_tree_(&scan->medications);
linekvpair_tree_(&scan->vaccines); linekvpair_tree_(&scan->vaccines);
linekvpair_tree_(&scan->ideas); linekvpair_tree_(&scan->ideas);
@@ -1070,6 +1114,7 @@ struct scan scan(struct journal *const jrnl) {
|| !linekvpair_tree_bulk_finish(&scan.ideas) || !linekvpair_tree_bulk_finish(&scan.ideas)
|| !linekvpair_tree_bulk_finish(&scan.vaccines) || !linekvpair_tree_bulk_finish(&scan.vaccines)
|| !linekvpair_tree_bulk_finish(&scan.medications) || !linekvpair_tree_bulk_finish(&scan.medications)
|| !linekvpair_tree_bulk_finish(&scan.labs)
|| !linekvpair_tree_bulk_finish(&scan.couches) || !linekvpair_tree_bulk_finish(&scan.couches)
|| !linekvdate_tree_bulk_finish(&scan.froms) || !linekvdate_tree_bulk_finish(&scan.froms)
|| !linekvmoney_tree_bulk_finish(&scan.taxes) || !linekvmoney_tree_bulk_finish(&scan.taxes)
@@ -1166,7 +1211,7 @@ void scan_score_graph(struct scan *const scan) {
"myTimeFmt = \"%%Y-%%m-%%d\"\n" "myTimeFmt = \"%%Y-%%m-%%d\"\n"
"set format x myTimeFmt timedate\n" "set format x myTimeFmt timedate\n"
"set xtics format myTimeFmt rotate by -30\n" "set xtics format myTimeFmt rotate by -30\n"
"set ylabel \"meaning CDF (person·day)\"\n" "set ylabel \"person·day cdf\"\n"
"set grid\n" "set grid\n"
"set key out reverse Left noautotitle\n" "set key out reverse Left noautotitle\n"
"set style fill solid 0.5\n" "set style fill solid 0.5\n"
@@ -1193,6 +1238,27 @@ void scan_score_graph(struct scan *const scan) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
void scan_labs_graph(struct scan *const scan) {
struct linekvpair_tree_iterator it
= linekvpair_tree_iterator(&scan->labs);
union line64 line;
struct kvpair *kv;
assert(scan);
fprintf(stderr, "*** Labs graph %s.\n",
linekvpair_tree_to_string(&scan->labs));
while(linekvpair_tree_next(&it)) {
char datestr[12];
line = linekvpair_tree_key(&it);
kv = linekvpair_tree_value(&it);
date32_to_string(line.date, &datestr);
printf("%s, \"%.*s\", \"%.*s\"\n",
datestr, (int)(kv->key.b - kv->key.a), kv->key.a,
(int)(kv->value.b - kv->value.a), kv->value.a);
}
fprintf(stderr, "\n");
}
#include <inttypes.h> #include <inttypes.h>
void scan_glider_graph(struct scan *const scan) { void scan_glider_graph(struct scan *const scan) {

3
time.txt Normal file
View File

@@ -0,0 +1,3 @@
set xdata time
set timefmt myTimeFmt
set xrange ['2000-01-01':*]