1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/* clectio -- tiny, fast, suckless daily readings.
*
* Computes nothing at runtime: the liturgical calendar, its reading citations
* and the scripture text are all compiled in (see gen/ and the Makefile). For a
* date it does a table lookup and prints the day and its readings. Configuration
* is compile-time (config.h), suckless-style: edit and recompile.
*
* Public domain. The compiled scripture corpus is NOT part of this program's
* licence (see README): the default is the public-domain Latin Vulgate.
*/
#define _POSIX_C_SOURCE 200809L /* localtime_r, isatty under -std=c99 */
#include "config.h"
#include LITURGY /* gen/liturgy_<form>.h: names,parts,cites_*,vpool,readings,rpool,days,cal,EPOCH,NDAYS */
#include "text.lz.h" /* embedded LZSS text blob: text_lz[], text_lz_len */
#include "lz.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static char *textbuf; /* inflated verse text */
static const char **verse; /* verse[i] -> the text of the i-th key, nul-terminated */
static int usecolor;
static const char *const colname[] = { "green", "white", "red", "violet", "rose", "black" };
static const char *const colansi[] = { "\033[32m", "\033[37m", "\033[31m", "\033[35m", "\033[95m", "\033[90m" };
/* Days since the civil epoch 1970-01-01 (Howard Hinnant's algorithm). */
static long days_from_civil(long y, unsigned m, unsigned d) {
y -= m <= 2;
long era = (y >= 0 ? y : y - 399) / 400;
unsigned yoe = (unsigned)(y - era * 400);
unsigned doy = (153u * (m + (m > 2 ? -3u : 9u)) + 2u) / 5u + d - 1;
unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
return era * 146097 + (long)doe - 719468;
}
static void load_text(void) {
unsigned raw = text_lz[0] | text_lz[1] << 8 | text_lz[2] << 16 | (unsigned)text_lz[3] << 24;
int cap = 8192, n = 0;
char *p;
textbuf = malloc(raw + 1);
lz_unpack(text_lz + 4, text_lz_len - 4, (unsigned char *)textbuf, raw);
textbuf[raw] = 0;
verse = malloc(cap * sizeof(*verse));
verse[n++] = textbuf;
for (p = textbuf; *p; p++)
if (*p == '\n') {
*p = 0;
if (p[1]) {
if (n == cap) { cap *= 2; verse = realloc(verse, cap * sizeof(*verse)); }
verse[n++] = p + 1;
}
}
}
static const char *citation(int r) {
#ifdef SIGLA_LATIN
return cites_la[readings_cite_la[r]];
#else
return cites_en[readings[r].cite];
#endif
}
static void print_day(long off, const char *datestr) {
const Day *d = &days[cal[off]];
unsigned k, ri;
if (usecolor)
printf("%s%s\033[0m", colansi[d->colour], names[d->name]);
else
printf("%s \xc2\xb7 %s", names[d->name], colname[d->colour]);
printf("\n%s for %s\n", FORMNAME, datestr);
for (k = 0; k < d->rlen; k++)
putchar('=');
putchar('\n');
for (ri = 0; ri < d->rlen; ri++) {
const Reading *r = &readings[rpool[d->roff + ri]];
unsigned v;
printf("\n%s (%s)\n\n", parts[r->part], citation(rpool[d->roff + ri]));
for (v = 0; v < r->vlen; v++)
printf("%s\n", verse[vpool[r->voff + v]]);
}
}
int main(int argc, char **argv) {
struct tm tm;
long off;
char datestr[16];
int y, m, dd;
usecolor = COLOR && isatty(1);
if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
fprintf(stderr, "usage: clectio [YYYY-MM-DD] (default: today)\n"
" compiled: %s, %s, %d-%d\n", FORMNAME, SIGLANAME, EPOCH_Y, EPOCH_Y + (NDAYS / 366));
return 0;
}
if (argc > 1) {
if (sscanf(argv[1], "%d-%d-%d", &y, &m, &dd) != 3) {
fprintf(stderr, "clectio: bad date %s (want YYYY-MM-DD)\n", argv[1]);
return 2;
}
snprintf(datestr, sizeof datestr, "%04d-%02d-%02d", y, m, dd);
} else {
time_t t = time(NULL);
localtime_r(&t, &tm);
y = tm.tm_year + 1900;
m = tm.tm_mon + 1;
dd = tm.tm_mday;
strftime(datestr, sizeof datestr, "%Y-%m-%d", &tm);
}
off = days_from_civil(y, (unsigned)m, (unsigned)dd) -
days_from_civil(EPOCH_Y, EPOCH_M, EPOCH_D);
if (off < 0 || off >= NDAYS) {
fprintf(stderr, "clectio: %s is outside the compiled range %d..%d\n",
datestr, EPOCH_Y, EPOCH_Y + (NDAYS / 366));
return 1;
}
load_text();
print_day(off, datestr);
return 0;
}
|