currency started
This commit is contained in:
parent
2d11f84bd9
commit
3e5acec91a
32
src/pair.c
32
src/pair.c
@ -31,6 +31,17 @@ int pair_to_natural(const char *a, const char *const b, uint32_t *const n) {
|
|||||||
return *n = accum, 1;
|
return *n = accum, 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pair_to_64(const char *a, const char *const b, uint64_t *const n) {
|
||||||
|
uint64_t accum = 0;
|
||||||
|
while(a < b) {
|
||||||
|
uint64_t next = accum * 10 + (uint64_t)(*a - '0');
|
||||||
|
if(accum > next) return errno = ERANGE, 0;
|
||||||
|
accum = next;
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
return *n = accum, 1;
|
||||||
|
}
|
||||||
|
|
||||||
/** `h0` "1" `h1` ":" `m0` "30" `m1` -> 90 `n` @return Valid. */
|
/** `h0` "1" `h1` ":" `m0` "30" `m1` -> 90 `n` @return Valid. */
|
||||||
int pair_colon_to_minutes(const char *h0, const char *const h1,
|
int pair_colon_to_minutes(const char *h0, const char *const h1,
|
||||||
const char *m0, const char *const m1, uint32_t *const n) {
|
const char *m0, const char *const m1, uint32_t *const n) {
|
||||||
@ -117,6 +128,27 @@ 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) {
|
||||||
|
uint64_t d, c;
|
||||||
|
int is_negative;
|
||||||
|
assert(a && a < b && cents);
|
||||||
|
if(a[0] == '-') is_negative = 1, a++, assert(a < b);
|
||||||
|
else is_negative = 0;
|
||||||
|
if(a + 2 < b && b[-3] == '.') { /* dollars.cents */
|
||||||
|
if(!pair_to_64(a, b - 3, &d)) return 0;
|
||||||
|
c = (uint64_t)(b[-2] - '0') * 10 + (uint64_t)(b[-1] - '0');
|
||||||
|
} else { /* dollars */
|
||||||
|
if(!pair_to_64(a, b, &d)) return 0;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
assert(-INT64_MAX >= INT64_MIN);
|
||||||
|
if(INT64_MAX / 100 < d || INT64_MAX - d * 100 < c)
|
||||||
|
return errno = ERANGE, 0;
|
||||||
|
/* Misses one in 2's. Not a very nuanced conversion. */
|
||||||
|
*cents = (is_negative ? -1 : 1) * (int64_t)(d * 100 + c);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/** @return A djb2 <http://www.cse.yorku.ca/~oz/hash.html> hash of `p`. */
|
/** @return A djb2 <http://www.cse.yorku.ca/~oz/hash.html> hash of `p`. */
|
||||||
uint32_t pair_djb2(struct pair p) {
|
uint32_t pair_djb2(struct pair p) {
|
||||||
uint32_t hash = 5381, c;
|
uint32_t hash = 5381, c;
|
||||||
|
@ -15,6 +15,7 @@ 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 char *, union date32 *);
|
||||||
|
int pair_to_cents(const char *, const char *, 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. */
|
||||||
|
21
src/scan.h
21
src/scan.h
@ -19,6 +19,24 @@ struct kvpair { struct pair key, value; };
|
|||||||
#define TREE_VALUE struct kvpair
|
#define TREE_VALUE struct kvpair
|
||||||
#define TREE_HEAD
|
#define TREE_HEAD
|
||||||
#include "../src/tree.h"
|
#include "../src/tree.h"
|
||||||
|
enum currency {
|
||||||
|
NONE,
|
||||||
|
CAD, /* Canadian $. */
|
||||||
|
USD, /* US Dollar $usd. */
|
||||||
|
EUR, /* Euro €. */
|
||||||
|
GBP, /* Pound £. */
|
||||||
|
MXN, /* Mexican pesos $mxn. */
|
||||||
|
CUP, /* Cuban pesos, (US) $cup. */
|
||||||
|
CUC, /* Cuban convertible $cuc. */
|
||||||
|
};
|
||||||
|
#include <stdint.h>
|
||||||
|
struct money { int64_t cents; enum currency currency; };
|
||||||
|
struct kvmoney { struct pair key; struct money value; };
|
||||||
|
#define TREE_NAME linekvmoney
|
||||||
|
#define TREE_KEY union line64
|
||||||
|
#define TREE_VALUE struct kvmoney
|
||||||
|
#define TREE_HEAD
|
||||||
|
#include "../src/tree.h"
|
||||||
|
|
||||||
/* Place array. */
|
/* Place array. */
|
||||||
struct place { struct pair name; double x, y; };
|
struct place { struct pair name; double x, y; };
|
||||||
@ -116,7 +134,8 @@ struct scan {
|
|||||||
struct pairmap_table map;
|
struct pairmap_table map;
|
||||||
struct linemap_tree dates;
|
struct linemap_tree dates;
|
||||||
} edits;
|
} edits;
|
||||||
struct linekvpair_tree contacts, books, tvs, movies, ideas;
|
struct linekvpair_tree contacts, books, tvs, movies, ideas, vaccines;
|
||||||
|
struct linekvmoney_tree taxes;
|
||||||
struct glider_tree gliders;
|
struct glider_tree gliders;
|
||||||
struct flight_tree flights;
|
struct flight_tree flights;
|
||||||
struct kjv_tree kjvs;
|
struct kjv_tree kjvs;
|
||||||
|
153
src/scan.re.c
153
src/scan.re.c
@ -54,6 +54,19 @@ static int linekvpair_compare(const union line64 a, const union line64 b)
|
|||||||
#define TREE_DEFAULT {{0,0},{0,0}}
|
#define TREE_DEFAULT {{0,0},{0,0}}
|
||||||
#define TREE_BODY
|
#define TREE_BODY
|
||||||
#include "../src/tree.h"
|
#include "../src/tree.h"
|
||||||
|
static void linekvmoney_to_string(const union line64 line,
|
||||||
|
const struct kvmoney *const kv,
|
||||||
|
char (*const a)[12]) { (void)kv; date32_to_string(line.date, a); }
|
||||||
|
static int linekvmoney_compare(const union line64 a, const union line64 b)
|
||||||
|
{ return a.u64 > b.u64; }
|
||||||
|
#define TREE_NAME linekvmoney
|
||||||
|
#define TREE_KEY union line64
|
||||||
|
#define TREE_VALUE struct kvmoney
|
||||||
|
#define TREE_COMPARE
|
||||||
|
#define TREE_TO_STRING
|
||||||
|
#define TREE_DEFAULT {{0,0},{0,CAD}}
|
||||||
|
#define TREE_BODY
|
||||||
|
#include "../src/tree.h"
|
||||||
|
|
||||||
|
|
||||||
/* Array of places. */
|
/* Array of places. */
|
||||||
@ -134,7 +147,8 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
size_t line = 1;
|
size_t line = 1;
|
||||||
char datestr[12] = {0};
|
char datestr[12] = {0};
|
||||||
const char *fail = "perhaps a bat?";
|
const char *fail = "perhaps a bat?";
|
||||||
struct pair *future = 0;
|
struct pair *input_text = 0;
|
||||||
|
struct money *input_money = 0;
|
||||||
struct score *new_score = 0;
|
struct score *new_score = 0;
|
||||||
struct glider *new_glider = 0;
|
struct glider *new_glider = 0;
|
||||||
struct flight *new_flight = 0;
|
struct flight *new_flight = 0;
|
||||||
@ -171,14 +185,13 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
|
|
||||||
keyword = [A-Za-z0-9][A-Za-z0-9_-]*;
|
keyword = [A-Za-z0-9][A-Za-z0-9_-]*;
|
||||||
|
|
||||||
natural = [1-9][0-9]*;
|
|
||||||
zero_natural = [0-9]+;
|
|
||||||
decimal = "-"? zero_natural ("." zero_natural?)?;
|
|
||||||
uint = [0-9]+;
|
uint = [0-9]+;
|
||||||
|
natural = [1-9][0-9]*;
|
||||||
|
decimal = "-"? [0-9]+ ("." [0-9]*)?;
|
||||||
date = natural "-" [0-1][0-9] "-" [0-3][0-9];
|
date = natural "-" [0-1][0-9] "-" [0-3][0-9];
|
||||||
minutes = [0-5][0-9];
|
minutes = [0-5][0-9];
|
||||||
airport = [A-Z0-9]{4,4};
|
airport = [A-Z0-9]{4,4};
|
||||||
|
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") " "?;
|
||||||
@ -207,16 +220,18 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
<bracket> "tv: " :=> tv
|
<bracket> "tv: " :=> tv
|
||||||
<bracket> "movie: " :=> movie
|
<bracket> "movie: " :=> movie
|
||||||
<bracket> "idea: " :=> idea
|
<bracket> "idea: " :=> idea
|
||||||
|
<bracket> "vaccine: " :=> vaccine
|
||||||
|
<bracket> "tax: " :=> tax
|
||||||
|
|
||||||
<document> * { fail = "document title"; goto catch; }
|
<document> * { fail = "document title"; goto catch; }
|
||||||
<document> @s0 bralabel @s1 "]" => future {
|
<document> @s0 bralabel @s1 "]" => input_text {
|
||||||
const union line64 key = { { (uint32_t)line, date } };
|
const union line64 key = { { (uint32_t)line, 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 = s0, doc->key.b = s1;
|
||||||
doc->value.a = 0, doc->value.b = 0;
|
doc->value.a = 0, doc->value.b = 0;
|
||||||
assert(!future), future = &doc->value;
|
assert(!input_text), input_text = &doc->value;
|
||||||
switch(linemap_tree_bulk_assign(&scan->documents.dates, key, &pi)) {
|
switch(linemap_tree_bulk_assign(&scan->documents.dates, key, &pi)) {
|
||||||
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
|
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
|
||||||
case TREE_ABSENT:
|
case TREE_ABSENT:
|
||||||
@ -228,14 +243,14 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
}
|
}
|
||||||
|
|
||||||
<remark> * { fail = "remark"; goto catch; }
|
<remark> * { fail = "remark"; goto catch; }
|
||||||
<remark> @s0 date "]" => future {
|
<remark> @s0 date "]" => input_text {
|
||||||
const union line64 key = { { (uint32_t)line, date } };
|
const union line64 key = { { (uint32_t)line, date } };
|
||||||
size_t *pi;
|
size_t *pi;
|
||||||
struct edit *ed;
|
struct edit *ed;
|
||||||
if(!(ed = edit_array_new(&scan->edits.array))) goto catch;
|
if(!(ed = edit_array_new(&scan->edits.array))) goto catch;
|
||||||
ed->edit.u32 = 0;
|
ed->edit.u32 = 0;
|
||||||
ed->desc.a = 0, ed->desc.b = 0;
|
ed->desc.a = 0, ed->desc.b = 0;
|
||||||
assert(!future), future = &ed->desc;
|
assert(!input_text), input_text = &ed->desc;
|
||||||
if(!pair_to_date(s0, &ed->edit)) goto catch;
|
if(!pair_to_date(s0, &ed->edit)) goto catch;
|
||||||
switch(linemap_tree_bulk_assign(&scan->edits.dates, key, &pi)) {
|
switch(linemap_tree_bulk_assign(&scan->edits.dates, key, &pi)) {
|
||||||
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
|
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
|
||||||
@ -249,7 +264,7 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
}
|
}
|
||||||
|
|
||||||
<contact> * { fail = "contact unrecognized"; goto catch; }
|
<contact> * { fail = "contact unrecognized"; goto catch; }
|
||||||
<contact> @s0 bralabel @s1 "]" => future {
|
<contact> @s0 bralabel @s1 "]" => input_text {
|
||||||
const union line64 key = { { (uint32_t)line, date } };
|
const union line64 key = { { (uint32_t)line, date } };
|
||||||
struct kvpair *pair;
|
struct kvpair *pair;
|
||||||
switch(linekvpair_tree_bulk_assign(&scan->contacts, key, &pair)) {
|
switch(linekvpair_tree_bulk_assign(&scan->contacts, key, &pair)) {
|
||||||
@ -258,14 +273,14 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
}
|
}
|
||||||
pair->key.a = s0, pair->key.b = s1;
|
pair->key.a = s0, pair->key.b = s1;
|
||||||
pair->value.a = pair->value.b = 0;
|
pair->value.a = pair->value.b = 0;
|
||||||
assert(!future), future = &pair->value;
|
assert(!input_text), input_text = &pair->value;
|
||||||
fprintf(stderr, "%s[%zu]: new contact <<%.*s>>.\n",
|
fprintf(stderr, "%s[%zu]: new contact <<%.*s>>.\n",
|
||||||
datestr, line, (int)(s1 - s0), s0);
|
datestr, line, (int)(s1 - s0), s0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
<book> * { fail = "book unrecognized"; goto catch; }
|
<book> * { fail = "book unrecognized"; goto catch; }
|
||||||
<book> @s0 bralabel @s1 "]" => future {
|
<book> @s0 bralabel @s1 "]" => input_text {
|
||||||
const union line64 key = { { (uint32_t)line, date } };
|
const union line64 key = { { (uint32_t)line, date } };
|
||||||
struct kvpair *pair;
|
struct kvpair *pair;
|
||||||
switch(linekvpair_tree_bulk_assign(&scan->books, key, &pair)) {
|
switch(linekvpair_tree_bulk_assign(&scan->books, key, &pair)) {
|
||||||
@ -274,14 +289,14 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
}
|
}
|
||||||
pair->key.a = s0, pair->key.b = s1;
|
pair->key.a = s0, pair->key.b = s1;
|
||||||
pair->value.a = pair->value.b = 0;
|
pair->value.a = pair->value.b = 0;
|
||||||
assert(!future), future = &pair->value;
|
assert(!input_text), input_text = &pair->value;
|
||||||
fprintf(stderr, "%s[%zu]: new book <<%.*s>>.\n",
|
fprintf(stderr, "%s[%zu]: new book <<%.*s>>.\n",
|
||||||
datestr, line, (int)(s1 - s0), s0);
|
datestr, line, (int)(s1 - s0), s0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
<tv> * { fail = "tv unrecognized"; goto catch; }
|
<tv> * { fail = "tv unrecognized"; goto catch; }
|
||||||
<tv> @s0 bralabel @s1 "]" => future {
|
<tv> @s0 bralabel @s1 "]" => input_text {
|
||||||
const union line64 key = { { (uint32_t)line, date } };
|
const union line64 key = { { (uint32_t)line, date } };
|
||||||
struct kvpair *pair;
|
struct kvpair *pair;
|
||||||
switch(linekvpair_tree_bulk_assign(&scan->tvs, key, &pair)) {
|
switch(linekvpair_tree_bulk_assign(&scan->tvs, key, &pair)) {
|
||||||
@ -290,14 +305,14 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
}
|
}
|
||||||
pair->key.a = s0, pair->key.b = s1;
|
pair->key.a = s0, pair->key.b = s1;
|
||||||
pair->value.a = pair->value.b = 0;
|
pair->value.a = pair->value.b = 0;
|
||||||
assert(!future), future = &pair->value;
|
assert(!input_text), input_text = &pair->value;
|
||||||
fprintf(stderr, "%s[%zu]: new tv <<%.*s>>.\n",
|
fprintf(stderr, "%s[%zu]: new tv <<%.*s>>.\n",
|
||||||
datestr, line, (int)(s1 - s0), s0);
|
datestr, line, (int)(s1 - s0), s0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
<movie> * { fail = "movie unrecognized"; goto catch; }
|
<movie> * { fail = "movie unrecognized"; goto catch; }
|
||||||
<movie> @s0 bralabel @s1 "]" => future {
|
<movie> @s0 bralabel @s1 "]" => input_text {
|
||||||
const union line64 key = { { (uint32_t)line, date } };
|
const union line64 key = { { (uint32_t)line, date } };
|
||||||
struct kvpair *pair;
|
struct kvpair *pair;
|
||||||
switch(linekvpair_tree_bulk_assign(&scan->contacts, key, &pair)) {
|
switch(linekvpair_tree_bulk_assign(&scan->contacts, key, &pair)) {
|
||||||
@ -306,14 +321,14 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
}
|
}
|
||||||
pair->key.a = s0, pair->key.b = s1;
|
pair->key.a = s0, pair->key.b = s1;
|
||||||
pair->value.a = pair->value.b = 0;
|
pair->value.a = pair->value.b = 0;
|
||||||
assert(!future), future = &pair->value;
|
assert(!input_text), input_text = &pair->value;
|
||||||
fprintf(stderr, "%s[%zu]: new movie <<%.*s>>.\n",
|
fprintf(stderr, "%s[%zu]: new movie <<%.*s>>.\n",
|
||||||
datestr, line, (int)(s1 - s0), s0);
|
datestr, line, (int)(s1 - s0), s0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
<idea> * { fail = "idea unrecognized"; goto catch; }
|
<idea> * { fail = "idea unrecognized"; goto catch; }
|
||||||
<idea> @s0 bralabel @s1 "]" => future {
|
<idea> @s0 bralabel @s1 "]" => input_text {
|
||||||
const union line64 key = { { (uint32_t)line, date } };
|
const union line64 key = { { (uint32_t)line, date } };
|
||||||
struct kvpair *pair;
|
struct kvpair *pair;
|
||||||
switch(linekvpair_tree_bulk_assign(&scan->contacts, key, &pair)) {
|
switch(linekvpair_tree_bulk_assign(&scan->contacts, key, &pair)) {
|
||||||
@ -322,12 +337,44 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
}
|
}
|
||||||
pair->key.a = s0, pair->key.b = s1;
|
pair->key.a = s0, pair->key.b = s1;
|
||||||
pair->value.a = pair->value.b = 0;
|
pair->value.a = pair->value.b = 0;
|
||||||
assert(!future), future = &pair->value;
|
assert(!input_text), input_text = &pair->value;
|
||||||
fprintf(stderr, "%s[%zu]: new idea <<%.*s>>.\n",
|
fprintf(stderr, "%s[%zu]: new idea <<%.*s>>.\n",
|
||||||
datestr, line, (int)(s1 - s0), s0);
|
datestr, line, (int)(s1 - s0), s0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<vaccine> * { fail = "vaccine unrecognized"; goto catch; }
|
||||||
|
<vaccine> @s0 bralabel @s1 "]" => input_text {
|
||||||
|
const union line64 key = { { (uint32_t)line, date } };
|
||||||
|
struct kvpair *pair;
|
||||||
|
switch(linekvpair_tree_bulk_assign(&scan->vaccines, key, &pair)) {
|
||||||
|
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
|
||||||
|
case TREE_ABSENT: break;
|
||||||
|
}
|
||||||
|
pair->key.a = s0, pair->key.b = s1;
|
||||||
|
pair->value.a = pair->value.b = 0;
|
||||||
|
assert(!input_text), input_text = &pair->value;
|
||||||
|
fprintf(stderr, "%s[%zu]: new vaccine <<%.*s>>.\n",
|
||||||
|
datestr, line, (int)(s1 - s0), s0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
<tax> * { fail = "tax unrecognized"; goto catch; }
|
||||||
|
<tax> @s0 bralabel @s1 "]" => input_money {
|
||||||
|
const union line64 key = { { (uint32_t)line, date } };
|
||||||
|
struct kvmoney *pair;
|
||||||
|
switch(linekvmoney_tree_bulk_assign(&scan->taxes, key, &pair)) {
|
||||||
|
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
|
||||||
|
case TREE_ABSENT: break;
|
||||||
|
}
|
||||||
|
pair->key.a = s0, pair->key.b = s1;
|
||||||
|
pair->value = (struct money){0, CAD};
|
||||||
|
assert(!input_text), input_money = &pair->value;
|
||||||
|
fprintf(stderr, "%s[%zu]: new tax <<%.*s>>.\n",
|
||||||
|
datestr, line, (int)(s1 - s0), s0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
<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(s0, s1);
|
||||||
@ -397,7 +444,7 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
datestr, line, (int)(s1 - s0), s0);
|
datestr, line, (int)(s1 - s0), s0);
|
||||||
} continue; }
|
} continue; }
|
||||||
/* New source. */
|
/* New source. */
|
||||||
<source> @s0 keyword @s1 ":" => future {
|
<source> @s0 keyword @s1 ":" => input_text {
|
||||||
struct pair keyword = pair(s0, s1);
|
struct pair keyword = pair(s0, s1);
|
||||||
size_t *idx;
|
size_t *idx;
|
||||||
struct kvpair *source;
|
struct kvpair *source;
|
||||||
@ -410,7 +457,7 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
*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.a = s0, source->key.b = s1;
|
||||||
source->value.a = 0, source->value.b = 0;
|
source->value.a = 0, source->value.b = 0;
|
||||||
assert(!future), future = &source->value;
|
assert(!input_text), input_text = &source->value;
|
||||||
fprintf(stderr, "%s[%zu]: new source <<%.*s>> stored at %zu.\n",
|
fprintf(stderr, "%s[%zu]: new source <<%.*s>> stored at %zu.\n",
|
||||||
datestr, line, (int)(s1 - s0), s0, *idx);
|
datestr, line, (int)(s1 - s0), s0, *idx);
|
||||||
goto also_source;
|
goto also_source;
|
||||||
@ -588,28 +635,28 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
<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 zero_natural? @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_hours_to_minutes(s0, s1, 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 zero_natural? @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_hours_to_minutes(s0, s1, 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 zero_natural? @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_hours_to_minutes(s0, s1, 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 zero_natural? @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_hours_to_minutes(s0, s1, t0, t1,
|
||||||
&new_flight->ifr_min)) { fail = "flight ifr time"; goto catch; }
|
&new_flight->ifr_min)) { fail = "flight ifr time"; goto catch; }
|
||||||
continue; }
|
continue; }
|
||||||
@ -737,41 +784,54 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||||||
|
|
||||||
/* fixme: This is a cool way of doing things. Avoid repetition, make
|
/* fixme: This is a cool way of doing things. Avoid repetition, make
|
||||||
all the things this way. */
|
all the things this way. */
|
||||||
/* "<<\ntext\n>>" or "text\n" used by several. Must have pointers to
|
<input_text, input_text_multi> * { fail = "text input"; goto catch; }
|
||||||
future input. */
|
<input_text> ws { continue; }
|
||||||
<future, future_multi> * { fail = "text input"; goto catch; }
|
<input_text> "\n" => line { // empty is okay
|
||||||
<future> ws+ { continue; }
|
|
||||||
<future> "\n" => line { // empty is okay
|
|
||||||
line++;
|
line++;
|
||||||
assert(future);
|
fprintf(stderr, "text: <empty>\n");
|
||||||
future->a = future->b = 0, future = 0;
|
assert(input_text);
|
||||||
|
input_text->a = input_text->b = 0, input_text = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
<future> "<<\n" @s0 => future_multi { // multi-line
|
<input_text> "<<\n" @s0 => input_text_multi { // multi-line
|
||||||
line++;
|
line++;
|
||||||
assert(future);
|
assert(input_text);
|
||||||
future->a = s0;
|
input_text->a = s0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
<future> @s0 anylabel @s1 "\n" => line { // one line
|
<input_text> @s0 anylabel @s1 "\n" => line { // one line
|
||||||
line++;
|
line++;
|
||||||
fprintf(stderr, "text: <<%.*s>>\n", (int)(s1 - s0), s0);
|
fprintf(stderr, "text: <<%.*s>>\n", (int)(s1 - s0), s0);
|
||||||
assert(future);
|
assert(input_text);
|
||||||
future->a = s0, future->b = s1, future = 0;
|
input_text->a = s0, input_text->b = s1, input_text = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
<future_multi> [^\x00\n] { continue; }
|
<input_text_multi> [^\x00\n] { continue; }
|
||||||
<future_multi> [\x00] { fail = "missing closing \">>\""; goto catch; }
|
<input_text_multi> [\x00]
|
||||||
<future_multi> "\n" { line++; continue; }
|
{ fail = "missing closing \">>\""; goto catch; }
|
||||||
|
<input_text_multi> "\n" { line++; continue; }
|
||||||
/* Restricts this to be the last one; you could imagine that it would
|
/* Restricts this to be the last one; you could imagine that it would
|
||||||
be more flexible, "<<\n>>; <<\n>>\n". */
|
be more flexible, "<<\n>>; <<\n>>\n". */
|
||||||
<future_multi> @s1 ">>\n" => line {
|
<input_text_multi> @s1 ">>\n" => line {
|
||||||
line++;
|
line++;
|
||||||
assert(future && future->a);
|
fprintf(stderr, "text: <<\n%.*s>>\n",
|
||||||
future->b = s1, future = 0;
|
(int)(s1 - input_text->a), input_text->a);
|
||||||
|
assert(input_text && input_text->a);
|
||||||
|
input_text->b = s1, input_text = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<input_money, input_money_currency> *
|
||||||
|
{ fail = "money input"; goto catch; }
|
||||||
|
<input_money> ws { continue; }
|
||||||
|
<input_money> @s0 moneyamount @s1 => input_money_currency {
|
||||||
|
if(!pair_to_cents(s0, s1, &input_money->cents)) goto catch;
|
||||||
|
printf("input_money: amount %" PRId64 "\n", input_money->cents);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
<input_money_currency> "$\n" => line
|
||||||
|
{ line++; input_money->currency = CAD; continue; }
|
||||||
|
|
||||||
*/ }
|
*/ }
|
||||||
assert(0); /* Never gets here. */
|
assert(0); /* Never gets here. */
|
||||||
catch:
|
catch:
|
||||||
@ -791,6 +851,8 @@ void scan_(struct scan *const scan) {
|
|||||||
fprintf(stderr, "~scan finished kjv\n");
|
fprintf(stderr, "~scan finished kjv\n");
|
||||||
flight_tree_(&scan->flights);
|
flight_tree_(&scan->flights);
|
||||||
glider_tree_(&scan->gliders);
|
glider_tree_(&scan->gliders);
|
||||||
|
linekvmoney_tree_(&scan->taxes);
|
||||||
|
linekvpair_tree_(&scan->vaccines);
|
||||||
linekvpair_tree_(&scan->ideas);
|
linekvpair_tree_(&scan->ideas);
|
||||||
linekvpair_tree_(&scan->movies);
|
linekvpair_tree_(&scan->movies);
|
||||||
linekvpair_tree_(&scan->tvs);
|
linekvpair_tree_(&scan->tvs);
|
||||||
@ -868,13 +930,14 @@ struct scan scan(struct journal *const jrnl) {
|
|||||||
|| !linekvpair_tree_bulk_finish(&scan.tvs)
|
|| !linekvpair_tree_bulk_finish(&scan.tvs)
|
||||||
|| !linekvpair_tree_bulk_finish(&scan.movies)
|
|| !linekvpair_tree_bulk_finish(&scan.movies)
|
||||||
|| !linekvpair_tree_bulk_finish(&scan.ideas)
|
|| !linekvpair_tree_bulk_finish(&scan.ideas)
|
||||||
|
|| !linekvpair_tree_bulk_finish(&scan.vaccines)
|
||||||
|
|| !linekvmoney_tree_bulk_finish(&scan.taxes)
|
||||||
|| !glider_tree_bulk_finish(&scan.gliders)
|
|| !glider_tree_bulk_finish(&scan.gliders)
|
||||||
|| !flight_tree_bulk_finish(&scan.flights)
|
|| !flight_tree_bulk_finish(&scan.flights)
|
||||||
|| !kjv_tree_bulk_finish(&scan.kjvs)) goto catch;
|
|| !kjv_tree_bulk_finish(&scan.kjvs)) goto catch;
|
||||||
|
|
||||||
goto finally;
|
goto finally;
|
||||||
catch:
|
catch:
|
||||||
fprintf(stderr, "Scan failed.\n");
|
|
||||||
scan_(&scan);
|
scan_(&scan);
|
||||||
finally:
|
finally:
|
||||||
return scan;
|
return scan;
|
||||||
|
Loading…
Reference in New Issue
Block a user