Compare commits
42 Commits
Author | SHA1 | Date | |
---|---|---|---|
b9cb570691 | |||
1f6f226943 | |||
7f8937db55 | |||
81fc10966d | |||
5d111433c3 | |||
af512793b0 | |||
ea4cf06785 | |||
8b4e83e2ea | |||
45ea09d7ae | |||
a9c04a1924 | |||
e33dcbea67 | |||
66a3c1752f | |||
cb6e0ebab4 | |||
7f8c7710e0 | |||
d46b5b4d4d | |||
45c667cdda | |||
311316ef88 | |||
4b905ccefa | |||
d08047d4db | |||
e87f25c9ee | |||
98c8f8dfc7 | |||
828c2b6595 | |||
caf6924d0a | |||
b670e7f822 | |||
3e5acec91a | |||
2d11f84bd9 | |||
54dde7c057 | |||
e6a5242e73 | |||
04c87cbfa6 | |||
ecf33b18df | |||
c0228d87bc | |||
5cb731c9cc | |||
31f41f6ced | |||
f31a7a9810 | |||
c096fbf605 | |||
9c2edcb9eb | |||
72385093bd | |||
fd2b3afc70 | |||
bfd8d797f9 | |||
a07c9c5811 | |||
6866fab753 | |||
dd7ebd4075 |
6
Makefile
6
Makefile
@ -1,4 +1,4 @@
|
||||
optimize := -ffast-math
|
||||
optimize := -ffast-math
|
||||
warnbasic := -Wall -pedantic #-ansi # -std=c99
|
||||
warnclang := -Wextra -Weverything \
|
||||
-Wno-comma \
|
||||
@ -30,7 +30,7 @@ else
|
||||
CF += -g
|
||||
endif
|
||||
|
||||
projects := bin/test-text bin/test-journal bin/test-source bin/test-kjv bin/kjv bin/flight bin/score bin/scan
|
||||
projects := bin/test-text bin/test-journal bin/test-source bin/test-kjv bin/scan
|
||||
#docs := $(patsubst test/test_%.c, doc/%.md, $(wildcard test/test_*.c))
|
||||
|
||||
default: $(projects)
|
||||
@ -70,7 +70,7 @@ build/%.c: src/%.re.c
|
||||
# # https://github.com/neil-edelman/cdoc documentation
|
||||
# -cdoc -o $@ $<
|
||||
|
||||
.SECONDARY: build/kjv.c build/journal.c build/source.c build/scan_kjv.c build/flights.c build/kjvcite.c build/scores.c build/scan.c
|
||||
.SECONDARY: build/kjv.c build/journal.c build/scan.c
|
||||
.PHONY: clean release test
|
||||
|
||||
test: $(projects)
|
||||
|
3
derived/.gitignore
vendored
3
derived/.gitignore
vendored
@ -1,2 +1,5 @@
|
||||
*
|
||||
!.gitignore
|
||||
!interpret
|
||||
!kjv/
|
||||
!kjv/*
|
||||
|
1
derived/interpret
Normal file
1
derived/interpret
Normal file
@ -0,0 +1 @@
|
||||
../../../Documents/journal/
|
71
src/driver.c
71
src/driver.c
@ -10,46 +10,105 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h> /* getcwd, chdir */
|
||||
|
||||
int main(void) {
|
||||
const char *intent = "start";
|
||||
struct journal jrnl = {0};
|
||||
struct scan scn = {0};
|
||||
int showhelp = 1;
|
||||
FILE *fpwhere = 0;
|
||||
char cwd[PATH_MAX], jdir[PATH_MAX];
|
||||
|
||||
errno = 0;
|
||||
|
||||
intent = "../journal";
|
||||
jrnl = journal(intent);
|
||||
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();
|
||||
fprintf(stderr, "Journal: %s.\n", journal_to_string(&jrnl));
|
||||
if(errno) goto catch;
|
||||
|
||||
intent = cwd;
|
||||
if(chdir(cwd)) goto catch;
|
||||
|
||||
intent = "parse";
|
||||
scn = scan(&jrnl);
|
||||
//fprintf(stderr, "Scan: %s.\n", scan_to_string(&scrs));
|
||||
// <- Not sure what that would do.
|
||||
if(errno) goto catch;
|
||||
|
||||
intent = "derived/score.gnu";
|
||||
intent = "score.gnu";
|
||||
if(!freopen(intent, "w", stdout)) goto catch;
|
||||
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;
|
||||
scan_glider_graph(&scn);
|
||||
|
||||
intent = "derived/flight.gnu";
|
||||
intent = "flight.gnu";
|
||||
if(!freopen(intent, "w", stdout)) goto catch;
|
||||
scan_flight_graph(&scn);
|
||||
|
||||
intent = "derived/kjv.gnu";
|
||||
intent = "kjv.gnu";
|
||||
if(!freopen(intent, "w", stdout)) goto catch;
|
||||
scan_kjv_graph(&scn);
|
||||
|
||||
intent = "dream.gnu";
|
||||
if(!freopen(intent, "w", stdout)) goto catch;
|
||||
scan_dream_graph(&scn);
|
||||
|
||||
intent = 0;
|
||||
goto finally;
|
||||
catch:
|
||||
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:
|
||||
/* fixme: ~scan should be idempotent but it's not on disabling ASLR, which
|
||||
debug mode is in. */
|
||||
if(fpwhere && fclose(fpwhere) == EOF)
|
||||
intent = "interpret", perror(intent);
|
||||
scan_(&scn);
|
||||
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;
|
||||
}
|
||||
|
@ -20,10 +20,12 @@ union line64 {
|
||||
#define TREE_HEAD
|
||||
#include "../src/tree.h"
|
||||
|
||||
union date32 date32_last_month(union date32 d);
|
||||
union date32 date32_next_month(union date32 d);
|
||||
#include "text.h"
|
||||
struct journal { struct day_tree days; struct char_array backing; };
|
||||
struct journal_iterator { struct day_tree_iterator _; };
|
||||
struct journal journal(const char *);
|
||||
struct journal journal(void);
|
||||
void journal_(struct journal *);
|
||||
int journal_is_empty(const struct journal *);
|
||||
const char *journal_to_string(const struct journal *);
|
||||
|
@ -17,6 +17,16 @@
|
||||
#include <sys/stat.h> /* umask (POSIX) */
|
||||
#include <dirent.h> /* opendir readdir closedir */
|
||||
|
||||
union date32 date32_last_month(union date32 d) {
|
||||
if(d.month <= 1) d.month = 12, d.year--;
|
||||
else d.month--;
|
||||
return d;
|
||||
}
|
||||
union date32 date32_next_month(union date32 d) {
|
||||
if(d.month >= 12) d.month = 1, d.year++;
|
||||
else d.month++;
|
||||
return d;
|
||||
}
|
||||
/* Day tree-map from date to pointer; is backed by a huge array of text. */
|
||||
void date32_to_string(const union date32 d, char (*const a)[12]) {
|
||||
sprintf(*a, "%" PRIu32 "-%2.2" PRIu32 "-%2.2" PRIu32,
|
||||
@ -114,9 +124,9 @@ void journal_(struct journal *const j) {
|
||||
text_(&j->backing);
|
||||
}
|
||||
|
||||
/** @return A completed journal out of `dir_journal`. Any reading errors and
|
||||
`errno` will be set, it will be idle. */
|
||||
struct journal journal(const char *const dir_journal) {
|
||||
/** @return A completed journal. Any reading errors and `errno` will be set,
|
||||
and will return will be idle. */
|
||||
struct journal journal(void/*const char *const dir_journal*/) {
|
||||
struct journal j = {0};
|
||||
char *intent = 0;
|
||||
DIR *dir = 0;
|
||||
@ -126,12 +136,10 @@ struct journal journal(const char *const dir_journal) {
|
||||
int *y = 0, *y_end, *m = 0, *m_end, *d = 0, *d_end;
|
||||
struct day_tree_iterator it;
|
||||
union { const char **text; uintptr_t *offset; } v;
|
||||
char cwd[256];
|
||||
int is_dir_journal = 0;
|
||||
|
||||
/* Get the years list as directories matching a year. */
|
||||
if(!getcwd(cwd, sizeof cwd) || chdir(dir_journal) == -1) goto catch;
|
||||
is_dir_journal = 1;
|
||||
/*if(!getcwd(cwd, sizeof cwd) || chdir(dir_journal) == -1) goto catch;
|
||||
is_dir_journal = 1;*/
|
||||
if(!(dir = opendir("."))) goto catch;
|
||||
while((de = readdir(dir))) {
|
||||
struct stat st;
|
||||
@ -145,8 +153,7 @@ struct journal journal(const char *const dir_journal) {
|
||||
if(closedir(dir)) { dir = 0; goto catch; } dir = 0;
|
||||
/* Sort the years. */
|
||||
qsort(years.data, years.size, sizeof *years.data, &void_int_cmp);
|
||||
fprintf(stderr, "Years in <<%s>>: %s.\n",
|
||||
dir_journal, int_array_to_string(&years));
|
||||
fprintf(stderr, "Loading years: %s.\n", int_array_to_string(&years));
|
||||
|
||||
/* Go though each year. */
|
||||
for(y = years.data, y_end = y + years.size; y < y_end; y++) {
|
||||
@ -208,7 +215,7 @@ struct journal journal(const char *const dir_journal) {
|
||||
m = 0, int_array_clear(&months);
|
||||
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;
|
||||
convert all of offsets back to pointers. */
|
||||
@ -218,17 +225,17 @@ struct journal journal(const char *const dir_journal) {
|
||||
|
||||
goto finally;
|
||||
catch:
|
||||
fprintf(stderr, "On date: %s/%d-%.2d-%.2d.\n",
|
||||
dir_journal, y ? *y : 0, m ? *m : 0, d ? *d : 0);
|
||||
fprintf(stderr, "On date: %d-%.2d-%.2d.\n",
|
||||
y ? *y : 0, m ? *m : 0, d ? *d : 0);
|
||||
if(intent) fprintf(stderr, "(%s)\n", intent);
|
||||
recatch:
|
||||
journal_(&j);
|
||||
finally:
|
||||
if(dir) { if(closedir(dir)) { dir = 0; goto recatch; } dir = 0; }
|
||||
if(is_dir_journal) {
|
||||
/*if(is_dir_journal) {
|
||||
if(chdir(cwd) == -1) { is_dir_journal = 0; goto recatch; }
|
||||
is_dir_journal = 0;
|
||||
}
|
||||
}*/
|
||||
int_array_(&years), int_array_(&months), int_array_(&days); /* Temporary. */
|
||||
return j;
|
||||
}
|
||||
|
@ -1,3 +1,11 @@
|
||||
/** Tyler Durden: calculates a day number according to the Gregorian calendar. */
|
||||
function g(y,m,d)
|
||||
m = (m + 9) % 12
|
||||
y = y - m/10
|
||||
return 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + ( d - 1 )
|
||||
|
||||
Difference between two dates = g(y2,m2,d2) - g(y1,m1,d1)
|
||||
|
||||
/** Tomohiko Sakamoto comp.lang.c 1993-04-10. */
|
||||
static unsigned weekday(union date32 d) {
|
||||
d.year -= d.month < 3;
|
||||
|
34
src/pair.c
34
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;
|
||||
}
|
||||
|
||||
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. */
|
||||
int pair_colon_to_minutes(const char *h0, const char *const h1,
|
||||
const char *m0, const char *const m1, uint32_t *const n) {
|
||||
@ -117,8 +128,29 @@ int pair_to_date(const char *a, union date32 *const d) {
|
||||
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`. */
|
||||
static uint32_t pair_djb2(struct pair p) {
|
||||
uint32_t pair_djb2(struct pair p) {
|
||||
uint32_t hash = 5381, c;
|
||||
while(p.a < p.b) {
|
||||
c = (unsigned char)*p.a++;
|
||||
|
@ -14,7 +14,9 @@ int pair_hours_to_minutes(const char *h0, const char *const h1,
|
||||
int pair_is_equal(struct pair, struct pair);
|
||||
int pair_is_string(struct pair, const char *);
|
||||
#include "journal.h" /* date32 */
|
||||
int pair_to_date(const char *a, union date32 *const d);
|
||||
int pair_to_date(const char *, union date32 *);
|
||||
int pair_to_cents(const char *, const char *, int64_t *);
|
||||
uint32_t pair_djb2(struct pair);
|
||||
|
||||
/* Supporting pair -> size_t for looking up in arrays. */
|
||||
#define TABLE_NAME pairmap
|
||||
|
87
src/scan.h
87
src/scan.h
@ -7,11 +7,52 @@
|
||||
#define TREE_VALUE size_t
|
||||
#define TREE_HEAD
|
||||
#include "../src/tree.h"
|
||||
#define TREE_NAME linepair
|
||||
#define TREE_KEY union line64
|
||||
#define TREE_VALUE struct pair
|
||||
#define TREE_HEAD
|
||||
#include "../src/tree.h"
|
||||
|
||||
/* Source array. */
|
||||
struct source { struct pair name, desc; };
|
||||
#define ARRAY_NAME source
|
||||
#define ARRAY_TYPE struct source
|
||||
/* Eg, source array. */
|
||||
struct kvpair { struct pair key, value; };
|
||||
#define ARRAY_NAME kvpair
|
||||
#define ARRAY_TYPE struct kvpair
|
||||
#define ARRAY_HEAD
|
||||
#include "../src/array.h"
|
||||
#define TREE_NAME linekvpair
|
||||
#define TREE_KEY union line64
|
||||
#define TREE_VALUE struct kvpair
|
||||
#define TREE_HEAD
|
||||
#include "../src/tree.h"
|
||||
struct kvdate { union date32 key; struct pair value; };
|
||||
#define TREE_NAME linekvdate
|
||||
#define TREE_KEY union line64
|
||||
#define TREE_VALUE struct kvdate
|
||||
#define TREE_HEAD
|
||||
#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. */
|
||||
struct place { struct pair name; double x, y; };
|
||||
#define ARRAY_NAME place
|
||||
#define ARRAY_TYPE struct place
|
||||
#define ARRAY_HEAD
|
||||
#include "../src/array.h"
|
||||
|
||||
@ -26,6 +67,17 @@ struct score {
|
||||
#define ARRAY_HEAD
|
||||
#include "../src/array.h"
|
||||
|
||||
/* Edit array. */
|
||||
struct edit {
|
||||
union date32 edit;
|
||||
struct pair desc;
|
||||
};
|
||||
#define ARRAY_NAME edit
|
||||
#define ARRAY_TYPE struct edit
|
||||
#define ARRAY_HEAD
|
||||
#include "../src/array.h"
|
||||
|
||||
|
||||
/* Glider array. */
|
||||
#define LAUNCH_TYPE \
|
||||
X(MotorCarTow),\
|
||||
@ -65,7 +117,7 @@ struct flight {
|
||||
|
||||
|
||||
#include "kjv.h"
|
||||
#define TREE_NAME kjvline
|
||||
#define TREE_NAME kjv
|
||||
#define TREE_KEY union line64
|
||||
#define TREE_VALUE struct kjvrange
|
||||
#define TREE_HEAD
|
||||
@ -74,24 +126,41 @@ struct flight {
|
||||
|
||||
struct scan {
|
||||
struct {
|
||||
struct source_array array;
|
||||
struct kvpair_array array;
|
||||
struct pairmap_table map;
|
||||
struct linemap_tree dates;
|
||||
} sources;
|
||||
} sources, documents;
|
||||
struct {
|
||||
struct place_array array;
|
||||
struct pairmap_table map;
|
||||
struct linemap_tree dates;
|
||||
} places;
|
||||
struct {
|
||||
struct score_array array;
|
||||
struct pairmap_table map;
|
||||
struct linemap_tree dates;
|
||||
} scores;
|
||||
struct {
|
||||
struct edit_array array;
|
||||
struct pairmap_table map;
|
||||
struct linemap_tree dates;
|
||||
} edits;
|
||||
struct linepair_tree dreams;
|
||||
struct linekvpair_tree contacts, books, tvs, movies, ideas,
|
||||
vaccines, medications, labs, mails, couches;
|
||||
struct linekvdate_tree froms;
|
||||
struct linekvmoney_tree taxes, incomes;
|
||||
struct glider_tree gliders;
|
||||
struct flight_tree flights;
|
||||
struct kjvline_tree kjvs;
|
||||
struct kjv_tree kjvs;
|
||||
};
|
||||
|
||||
void scan_(struct scan *);
|
||||
struct scan scan(struct journal *);
|
||||
const struct source *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_labs_graph(struct scan *);
|
||||
void scan_glider_graph(struct scan *);
|
||||
void scan_flight_graph(struct scan *);
|
||||
void scan_kjv_graph(struct scan *);
|
||||
void scan_dream_graph(struct scan *);
|
||||
|
1069
src/scan.re.c
1069
src/scan.re.c
File diff suppressed because it is too large
Load Diff
10
src/text.c
10
src/text.c
@ -3,6 +3,8 @@
|
||||
|
||||
#include "text.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ARRAY_NAME char
|
||||
#define ARRAY_TYPE char
|
||||
@ -28,10 +30,14 @@ char *text_append_file(struct char_array *text, const char *const fn) {
|
||||
assert(text && fn);
|
||||
start = text->size;
|
||||
if(!(fp = fopen(fn, "r"))) goto catch;
|
||||
/* Read entire file in chunks. */
|
||||
/* Read entire file in chunks. We don't allow any text file to go over
|
||||
`INT_MAX` and `UINT32_MAX` because `printf("%.*s", int, char *)` is used
|
||||
and we store it in an `uint32_t`. */
|
||||
do if(!(cursor = char_array_buffer(text, granularity))
|
||||
|| (nread = fread(cursor, 1, granularity, fp), ferror(fp))
|
||||
|| !char_array_append(text, nread)) goto catch;
|
||||
|| !char_array_append(text, nread)
|
||||
|| text->size - start >= (INT_MAX < UINT32_MAX ? INT_MAX : UINT32_MAX))
|
||||
goto catch;
|
||||
while(nread == granularity);
|
||||
/* File to `C` string. */
|
||||
if(!(cursor = char_array_new(text))) goto catch;
|
||||
|
30
src/tree.h
30
src/tree.h
@ -33,8 +33,8 @@
|
||||
tree, <Sedgewick, 2008, LLRB>. The above illustration is 5.
|
||||
|
||||
@param[TREE_DEFAULT]
|
||||
Default trait; a name that satisfies `C` naming conventions when mangled and a
|
||||
<typedef:<PB>value> used in <fn:<B>tree<D>get>.
|
||||
Default trait which must be set to a <typedef:<PB>value>, used in
|
||||
<fn:<B>tree<D>get>.
|
||||
|
||||
@param[TREE_TO_STRING]
|
||||
To string trait `<STR>` contained in <src/to_string.h>. Require
|
||||
@ -42,7 +42,8 @@
|
||||
|
||||
@param[TREE_EXPECT_TRAIT, TREE_TRAIT]
|
||||
Named traits are obtained by including `tree.h` multiple times with
|
||||
`TREE_EXPECT_TRAIT` and then subsequently including the name in `TREE_TRAIT`.
|
||||
`TREE_EXPECT_TRAIT` and then subsequently including the name that satisfies
|
||||
`C` naming conventions when mangled in `TREE_TRAIT`.
|
||||
|
||||
@param[TREE_HEAD, TREE_BODY]
|
||||
These go together to allow exporting non-static data between compilation units
|
||||
@ -244,7 +245,7 @@ static int PB_(next)(struct PB_(iterator) *const it) {
|
||||
assert(it && it->root);
|
||||
|
||||
/* Tree empty. */
|
||||
if(!it->root->node || it->root->height == UINT_MAX) return 0;
|
||||
if(!it->root || !it->root->node || it->root->height == UINT_MAX) return 0;
|
||||
|
||||
/* Iterator empty; tree non-empty; point at first. */
|
||||
if(!it->ref.node) {
|
||||
@ -291,7 +292,7 @@ static int PB_(previous)(struct PB_(iterator) *const it) {
|
||||
assert(it && it->root);
|
||||
|
||||
/* Tree empty. */
|
||||
if(!it->root->node || it->root->height == UINT_MAX) return 0;
|
||||
if(!it->root || !it->root->node || it->root->height == UINT_MAX) return 0;
|
||||
|
||||
/* Iterator empty; tree non-empty; point at last. */
|
||||
if(!it->ref.node) {
|
||||
@ -514,7 +515,8 @@ static void B_(tree_)(struct B_(tree) *const tree) {
|
||||
}
|
||||
|
||||
/** Clears `tree`, which can be null, idle, empty, or full. If it is empty or
|
||||
full, it remains active. @order \O(|`tree`|) @allow */
|
||||
full, it remains active, (all except one node are freed.)
|
||||
@order \O(|`tree`|) @allow */
|
||||
static void B_(tree_clear)(struct B_(tree) *const tree) { PB_(clear)(tree); }
|
||||
|
||||
/** Private: counts a sub-tree, `tree`. */
|
||||
@ -582,12 +584,12 @@ static PB_(key) B_(tree_more_or)(const struct B_(tree) *const tree,
|
||||
}
|
||||
|
||||
#ifdef TREE_VALUE /* <!-- map */
|
||||
/** Packs `key` on the right side of `tree` without doing the usual
|
||||
restructuring. All other topology modification functions should be avoided
|
||||
until followed by <fn:<B>tree_bulk_finish>.
|
||||
/** Only if `TREE_VALUE` is set; the set version is <fn:<B>tree_try>. Packs
|
||||
`key` on the right side of `tree` without doing the usual restructuring. All
|
||||
other topology modification functions should be avoided until followed by
|
||||
<fn:<B>tree_bulk_finish>.
|
||||
@param[value] A pointer to the key's value which is set by the function on
|
||||
returning true. A null pointer in this parameter causes the value to go
|
||||
uninitialized. This parameter is not there if one didn't specify `TREE_VALUE`.
|
||||
returning true. Can be null.
|
||||
@return One of <tag:tree_result>: `TREE_ERROR` and `errno` will be set,
|
||||
`TREE_PRESENT` if the key is already (the highest) in the tree, and
|
||||
`TREE_ABSENT`, added, the `value` (if applicable) is uninitialized.
|
||||
@ -598,8 +600,8 @@ static enum tree_result B_(tree_bulk_assign)(struct B_(tree) *const tree,
|
||||
#elif defined TREE_VALUE /* map --><!-- null: For braces matching. */
|
||||
}
|
||||
#else /* null --><!-- set */
|
||||
/** Packs `key` on the right side of `tree`. See <fn:<B>tree_assign>, which is
|
||||
the map version. @allow */
|
||||
/** Only if `TREE_VALUE` is not set; see <fn:<B>tree_assign>, which is
|
||||
the map version. Packs `key` on the right side of `tree`. @allow */
|
||||
static enum tree_result B_(tree_bulk_try)(struct B_(tree) *const tree,
|
||||
PB_(key) key) {
|
||||
#endif
|
||||
@ -1636,7 +1638,7 @@ static void PBT_(to_string)(const struct PB_(ref) *const r,
|
||||
#define PB_D_(n, m) TREE_CAT(tree, B_D_(n, m))
|
||||
#endif
|
||||
/* `TREE_DEFAULT` is a valid <tag:<PB>value>. */
|
||||
static const PB_(value) PB_D_(default, value) = (TREE_DEFAULT);
|
||||
static const PB_(value) PB_D_(default, value) = TREE_DEFAULT;
|
||||
/** This is functionally identical to <fn:<B>tree_get_or>, but a with a trait
|
||||
specifying a constant default value.
|
||||
@return The value associated with `key` in `tree`, (which can be null.) If
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
int main(void) {
|
||||
errno = 0; /* `errno` is not set correctly to 0 in some debug situations. */
|
||||
struct journal j = journal("../journal");
|
||||
struct journal j = journal(/*"../journal"*/);
|
||||
int success = EXIT_SUCCESS;
|
||||
if(errno) goto catch;
|
||||
printf("Journal: %s.\n", journal_to_string(&j));
|
||||
|
@ -7,29 +7,29 @@
|
||||
int main(void) {
|
||||
int success = EXIT_SUCCESS;
|
||||
errno = 0; /* `errno` is not set correctly to 0 in some debug situations. */
|
||||
struct journal jrnl = journal("../journal");
|
||||
struct journal jrnl = journal(/*"../journal"*/);
|
||||
struct scan scn = scan(&jrnl);
|
||||
if(errno) goto catch;
|
||||
|
||||
const union line64 agenda = {{4,{{20,04,1996}}}},
|
||||
before = {{1,{{1,1,1900}}}},
|
||||
noentry = {{3,{{1,6,1995}}}};
|
||||
const struct source *source;
|
||||
const struct kvpair *source;
|
||||
|
||||
source = scan_source_lookup(&scn, agenda);
|
||||
printf("agenda: <%.*s>\n",
|
||||
(int)(source->name.b - source->name.a), source->name.a);
|
||||
assert(pair_is_string(source->name, "1995agenda"));
|
||||
(int)(source->key.b - source->key.a), source->key.a);
|
||||
assert(pair_is_string(source->key, "1995agenda"));
|
||||
|
||||
source = scan_source_lookup(&scn, before);
|
||||
printf("before: <%.*s>\n",
|
||||
(int)(source->name.b - source->name.a), source->name.a);
|
||||
assert(pair_is_string(source->name, 0));
|
||||
(int)(source->key.b - source->key.a), source->key.a);
|
||||
assert(pair_is_string(source->key, 0));
|
||||
|
||||
source = scan_source_lookup(&scn, noentry);
|
||||
printf("noentry: <%.*s>\n",
|
||||
(int)(source->name.b - source->name.a), source->name.a);
|
||||
assert(pair_is_string(source->name, 0));
|
||||
(int)(source->key.b - source->key.a), source->key.a);
|
||||
assert(pair_is_string(source->key, 0));
|
||||
|
||||
goto finally;
|
||||
catch:
|
||||
|
Loading…
x
Reference in New Issue
Block a user