ireplace the not-so-useful tcal format by a plain text output - ics2txt - convert icalendar .ics file to plain text Err bitreich.org 70 hgit clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt URL:git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt bitreich.org 70 1Log /scm/ics2txt/log.gph bitreich.org 70 1Files /scm/ics2txt/files.gph bitreich.org 70 1Refs /scm/ics2txt/refs.gph bitreich.org 70 1Tags /scm/ics2txt/tag bitreich.org 70 1README /scm/ics2txt/file/README.md.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 742516775b1d9b12e4c8893114b7cc5a363884ad /scm/ics2txt/commit/742516775b1d9b12e4c8893114b7cc5a363884ad.gph bitreich.org 70 1parent 5a6d05cc7d0f248c84b7f22bd1262bd9fdc9e750 /scm/ics2txt/commit/5a6d05cc7d0f248c84b7f22bd1262bd9fdc9e750.gph bitreich.org 70 hAuthor: Josuah Demangeon URL:mailto:me@josuah.net bitreich.org 70 iDate: Sun, 20 Jun 2021 12:12:53 +0200 Err bitreich.org 70 i Err bitreich.org 70 ireplace the not-so-useful tcal format by a plain text output Err bitreich.org 70 i Err bitreich.org 70 iThe input format will be an email open by a text editor, spawned by Err bitreich.org 70 isome script. Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M .gitignore | 1 + Err bitreich.org 70 i M Makefile | 4 ++-- Err bitreich.org 70 i M README | 6 ++---- Err bitreich.org 70 i M base64.c | 3 --- Err bitreich.org 70 i D bin/tcal2tsv | 85 ------------------------------- Err bitreich.org 70 i D bin/tsv2tcal | 91 ------------------------------- Err bitreich.org 70 i M ical.c | 3 --- Err bitreich.org 70 i M ical.h | 8 +++----- Err bitreich.org 70 i M ics2tree.c | 11 +++++++---- Err bitreich.org 70 i M ics2tsv.c | 19 +++++++++++++------ Err bitreich.org 70 i A strtonum.c | 66 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i D tcal.5 | 61 ------------------------------- Err bitreich.org 70 i A tsv2agenda.c | 193 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i M util.c | 8 +++----- Err bitreich.org 70 i M util.h | 3 ++- Err bitreich.org 70 i Err bitreich.org 70 i15 files changed, 292 insertions(+), 270 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/.gitignore b/.gitignore /scm/ics2txt/file/.gitignore.gph bitreich.org 70 i@@ -1,4 +1,5 @@ Err bitreich.org 70 i *.o Err bitreich.org 70 i /ics2tsv Err bitreich.org 70 i /ics2tree Err bitreich.org 70 i+/tsv2agenda Err bitreich.org 70 i /ics2txt-[0-9]* Err bitreich.org 70 1diff --git a/Makefile b/Makefile /scm/ics2txt/file/Makefile.gph bitreich.org 70 i@@ -2,7 +2,7 @@ NAME = ics2txt Err bitreich.org 70 i VERSION = 0.2 Err bitreich.org 70 i Err bitreich.org 70 i W = -Wall -Wextra -std=c99 --pedantic Err bitreich.org 70 i-D = -D_POSIX_C_SOURCE=200811L -DVERSION='"${VERSION}"' Err bitreich.org 70 i+D = -D_POSIX_C_SOURCE=200811L -D_BSD_SOURCE -DVERSION='"${VERSION}"' Err bitreich.org 70 i CFLAGS = $D $W -g Err bitreich.org 70 i PREFIX = /usr/local Err bitreich.org 70 i MANPREFIX = ${PREFIX}/man Err bitreich.org 70 i@@ -10,7 +10,7 @@ MANPREFIX = ${PREFIX}/man Err bitreich.org 70 i SRC = ical.c base64.c util.c Err bitreich.org 70 i HDR = ical.h base64.h util.h Err bitreich.org 70 i OBJ = ${SRC:.c=.o} Err bitreich.org 70 i-BIN = ics2tree ics2tsv Err bitreich.org 70 i+BIN = ics2tree ics2tsv tsv2agenda Err bitreich.org 70 i MAN1 = ics2txt.1 ics2tsv.1 Err bitreich.org 70 i MAN5 = tcal.5 Err bitreich.org 70 i Err bitreich.org 70 1diff --git a/README b/README /scm/ics2txt/file/README.gph bitreich.org 70 i@@ -7,11 +7,9 @@ The current implementation uses [awk](//josuah.net/wiki/awk/) scripts, but a Err bitreich.org 70 i rather complete implementation of iCalendar, without memory leak or crash, is Err bitreich.org 70 i already there, and used for the `ics2tree` linting tool. Err bitreich.org 70 i Err bitreich.org 70 i-Plans include to have an `ics2json` tool for a 1:1 mapping of iCalendar, and Err bitreich.org 70 i-have `ics2tsv` a more general-purpose tool with user-chosen column fields. Err bitreich.org 70 i+`ics2tsv` converts the iCalendar data to an easier-to-parse TSV format. Err bitreich.org 70 i Err bitreich.org 70 i-So far, Awk-based parsing have been tested with the following input formats Err bitreich.org 70 i-(sample account created for testing): Err bitreich.org 70 i+So far, Awk-based parsing have been tested with the following inputs: Err bitreich.org 70 i Err bitreich.org 70 i * Zoom meetings generated events Err bitreich.org 70 i * FOSDEM events, like Err bitreich.org 70 1diff --git a/base64.c b/base64.c /scm/ics2txt/file/base64.c.gph bitreich.org 70 i@@ -1,12 +1,9 @@ Err bitreich.org 70 i #include "base64.h" Err bitreich.org 70 i- Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i Err bitreich.org 70 i-#include Err bitreich.org 70 i- Err bitreich.org 70 i static char encode_map[64] = Err bitreich.org 70 i "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; Err bitreich.org 70 i Err bitreich.org 70 1diff --git a/bin/tcal2tsv b/bin/tcal2tsv /scm/ics2txt/file/bin/tcal2tsv.gph bitreich.org 70 i@@ -1,85 +0,0 @@ Err bitreich.org 70 i-#!/usr/bin/awk -f Err bitreich.org 70 i- Err bitreich.org 70 i-function isleap(year) Err bitreich.org 70 i-{ Err bitreich.org 70 i- return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-function mdays(mon, year) Err bitreich.org 70 i-{ Err bitreich.org 70 i- return (mon == 2) ? (28 + isleap(year)) : (30 + (mon + (mon > 7)) % 2) Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-function maketime(tm, Err bitreich.org 70 i- sec, mon, day) Err bitreich.org 70 i-{ Err bitreich.org 70 i- sec = tm["sec"] + tm["min"] * 60 + tm["hour"] * 3600 Err bitreich.org 70 i- Err bitreich.org 70 i- day = tm["mday"] - 1 Err bitreich.org 70 i- Err bitreich.org 70 i- for (mon = tm["mon"] - 1; mon > 0; mon--) Err bitreich.org 70 i- day = day + mdays(mon, tm["year"]) Err bitreich.org 70 i- Err bitreich.org 70 i- # constants: x * 365 + x / 400 - x / 100 + x / 4 Err bitreich.org 70 i- day = day + int(tm["year"] / 400) * 146097 Err bitreich.org 70 i- day = day + int(tm["year"] % 400 / 100) * 36524 Err bitreich.org 70 i- day = day + int(tm["year"] % 100 / 4) * 1461 Err bitreich.org 70 i- day = day + int(tm["year"] % 4 / 1) * 365 Err bitreich.org 70 i- Err bitreich.org 70 i- return sec + (day - 719527) * 86400 Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-function text_to_epoch(str, tz, Err bitreich.org 70 i- tm) Err bitreich.org 70 i-{ Err bitreich.org 70 i- tm["year"] = substr(str, 1, 4) Err bitreich.org 70 i- tm["mon"] = substr(str, 6, 2) Err bitreich.org 70 i- tm["mday"] = substr(str, 9, 2) Err bitreich.org 70 i- tm["hour"] = substr(str, 12, 2) Err bitreich.org 70 i- tm["min"] = substr(str, 15, 2) Err bitreich.org 70 i- return maketime(tm) - tz Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-BEGIN { Err bitreich.org 70 i- FIELDS = "beg end cat loc sum des" Err bitreich.org 70 i- split(FIELDS, fields, " ") Err bitreich.org 70 i- Err bitreich.org 70 i- for (i = 1; i in fields; i++) { Err bitreich.org 70 i- pos[fields[i]] = i Err bitreich.org 70 i- printf("%s%s", (i > 1 ? "\t" : ""), fields[i]) Err bitreich.org 70 i- } Err bitreich.org 70 i- printf("\n") Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-{ Err bitreich.org 70 i- gsub(/\t/, " ") Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-/^TZ[+-]/ { Err bitreich.org 70 i- TZ = substr($1, 3, 1) substr($0, 4, 2)*3600 + substr($0, 6, 2)*60 Err bitreich.org 70 i- while (getline && $0 ~ /^$/) Err bitreich.org 70 i- continue Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-/^[0-9]+-[0-9]+-[0-9]+/ { Err bitreich.org 70 i- if ("beg" in ev) Err bitreich.org 70 i- ev["end"] = text_to_epoch($0, TZ) Err bitreich.org 70 i- else Err bitreich.org 70 i- ev["beg"] = text_to_epoch($0, TZ) Err bitreich.org 70 i- next Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-/^ / { Err bitreich.org 70 i- tag = $1 Err bitreich.org 70 i- sub("^ *[^ :]+: *", "") Err bitreich.org 70 i- sub(":$", "", tag) Err bitreich.org 70 i- ev[tag] = $0 Err bitreich.org 70 i- next Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-/^$/ { Err bitreich.org 70 i- for (i = 1; i in fields; i++) Err bitreich.org 70 i- printf("%s%s", (i > 1 ? "\t" : ""), ev[fields[i]]) Err bitreich.org 70 i- printf("\n") Err bitreich.org 70 i- delete ev Err bitreich.org 70 i-} Err bitreich.org 70 1diff --git a/bin/tsv2tcal b/bin/tsv2tcal /scm/ics2txt/file/bin/tsv2tcal.gph bitreich.org 70 i@@ -1,91 +0,0 @@ Err bitreich.org 70 i-#!/usr/bin/awk -f Err bitreich.org 70 i- Err bitreich.org 70 i-function isleap(year) Err bitreich.org 70 i-{ Err bitreich.org 70 i- return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-function mdays(mon, year) Err bitreich.org 70 i-{ Err bitreich.org 70 i- return (mon == 2) ? (28 + isleap(year)) : (30 + (mon + (mon > 7)) % 2) Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-function gmtime(sec, tm) Err bitreich.org 70 i-{ Err bitreich.org 70 i- tm["year"] = 1970 Err bitreich.org 70 i- while (sec >= (s = 86400 * (365 + isleap(tm["year"])))) { Err bitreich.org 70 i- tm["year"]++ Err bitreich.org 70 i- sec -= s Err bitreich.org 70 i- } Err bitreich.org 70 i- tm["mon"] = 1 Err bitreich.org 70 i- while (sec >= (s = 86400 * mdays(tm["mon"], tm["year"]))) { Err bitreich.org 70 i- tm["mon"]++ Err bitreich.org 70 i- sec -= s Err bitreich.org 70 i- } Err bitreich.org 70 i- tm["mday"] = 1 Err bitreich.org 70 i- while (sec >= (s = 86400)) { Err bitreich.org 70 i- tm["mday"]++ Err bitreich.org 70 i- sec -= s Err bitreich.org 70 i- } Err bitreich.org 70 i- tm["hour"] = 0 Err bitreich.org 70 i- while (sec >= 3600) { Err bitreich.org 70 i- tm["hour"]++ Err bitreich.org 70 i- sec -= 3600 Err bitreich.org 70 i- } Err bitreich.org 70 i- tm["min"] = 0 Err bitreich.org 70 i- while (sec >= 60) { Err bitreich.org 70 i- tm["min"]++ Err bitreich.org 70 i- sec -= 60 Err bitreich.org 70 i- } Err bitreich.org 70 i- tm["sec"] = sec Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-function localtime(sec, tm, Err bitreich.org 70 i- tz, h, m) Err bitreich.org 70 i-{ Err bitreich.org 70 i- return gmtime(sec + TZ, tm) Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-BEGIN { Err bitreich.org 70 i- "exec date +%z" | getline tz Err bitreich.org 70 i- close("exec date +%z") Err bitreich.org 70 i- TZ = substr(tz, 1, 1) substr(tz, 2, 2)*3600 + substr(tz, 4, 2)*60 Err bitreich.org 70 i- Err bitreich.org 70 i- print("TZ" tz) Err bitreich.org 70 i- Err bitreich.org 70 i- FS = "\t" Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-NR == 1 { Err bitreich.org 70 i- for (i = 1; i <= NF; i++) Err bitreich.org 70 i- name[i] = $i Err bitreich.org 70 i- next Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-{ Err bitreich.org 70 i- for (i = 1; i <= NF; i++) Err bitreich.org 70 i- ev[name[i]] = $i Err bitreich.org 70 i- Err bitreich.org 70 i- print("") Err bitreich.org 70 i- Err bitreich.org 70 i- localtime(ev["beg"] + offset, tm) Err bitreich.org 70 i- printf("%04d-%02d-%02d %02d:%02d\n", Err bitreich.org 70 i- tm["year"], tm["mon"], tm["mday"], tm["hour"], tm["min"]) Err bitreich.org 70 i- delete ev["beg"] Err bitreich.org 70 i- Err bitreich.org 70 i- localtime(ev["end"] + offset, tm) Err bitreich.org 70 i- printf("%04d-%02d-%02d %02d:%02d\n", Err bitreich.org 70 i- tm["year"], tm["mon"], tm["mday"], tm["hour"], tm["min"]) Err bitreich.org 70 i- delete ev["end"] Err bitreich.org 70 i- Err bitreich.org 70 i- for (i = 1; i <= NF; i++) { Err bitreich.org 70 i- if (name[i] in ev && ev[name[i]]) Err bitreich.org 70 i- printf(" %s: %s\n", name[i], ev[name[i]]) Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- delete ev Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-END { Err bitreich.org 70 i- print("") Err bitreich.org 70 i-} Err bitreich.org 70 1diff --git a/ical.c b/ical.c /scm/ics2txt/file/ical.c.gph bitreich.org 70 i@@ -1,5 +1,4 @@ Err bitreich.org 70 i #include "ical.h" Err bitreich.org 70 i- Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i@@ -7,7 +6,6 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i- Err bitreich.org 70 i #include "util.h" Err bitreich.org 70 i #include "base64.h" Err bitreich.org 70 i Err bitreich.org 70 i@@ -329,7 +327,6 @@ ical_parse(IcalParser *p, FILE *fp) Err bitreich.org 70 i } while (l > 0 && (err = ical_parse_contentline(p, contentline)) == 0); Err bitreich.org 70 i Err bitreich.org 70 i free(contentline); Err bitreich.org 70 i- free(line); Err bitreich.org 70 i Err bitreich.org 70 i if (err == 0 && p->current != p->stack) Err bitreich.org 70 i return ical_err(p, "more BEGIN: than END:"); Err bitreich.org 70 1diff --git a/ical.h b/ical.h /scm/ics2txt/file/ical.h.gph bitreich.org 70 i@@ -6,9 +6,6 @@ Err bitreich.org 70 i Err bitreich.org 70 i #define ICAL_STACK_SIZE 10 Err bitreich.org 70 i Err bitreich.org 70 i-typedef struct IcalParser IcalParser; Err bitreich.org 70 i-typedef struct IcalStack IcalStack; Err bitreich.org 70 i- Err bitreich.org 70 i typedef enum { Err bitreich.org 70 i ICAL_BLOCK_VEVENT, Err bitreich.org 70 i ICAL_BLOCK_VTODO, Err bitreich.org 70 i@@ -18,11 +15,12 @@ typedef enum { Err bitreich.org 70 i ICAL_BLOCK_OTHER, Err bitreich.org 70 i } IcalBlock; Err bitreich.org 70 i Err bitreich.org 70 i-struct IcalStack { Err bitreich.org 70 i+typedef struct { Err bitreich.org 70 i char name[32]; Err bitreich.org 70 i char tzid[32]; Err bitreich.org 70 i-}; Err bitreich.org 70 i+} IcalStack; Err bitreich.org 70 i Err bitreich.org 70 i+typedef struct IcalParser IcalParser; Err bitreich.org 70 i struct IcalParser { Err bitreich.org 70 i /* function called while parsing in this order */ Err bitreich.org 70 i int (*fn_field_name)(IcalParser *, char *); Err bitreich.org 70 1diff --git a/ics2tree.c b/ics2tree.c /scm/ics2txt/file/ics2tree.c.gph bitreich.org 70 i@@ -2,10 +2,13 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i- Err bitreich.org 70 i #include "ical.h" Err bitreich.org 70 i #include "util.h" Err bitreich.org 70 i Err bitreich.org 70 i+#ifndef __OpenBSD__ Err bitreich.org 70 i+#define pledge(...) 0 Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i static void Err bitreich.org 70 i print_ruler(int level) Err bitreich.org 70 i { Err bitreich.org 70 i@@ -76,7 +79,7 @@ main(int argc, char **argv) Err bitreich.org 70 i Err bitreich.org 70 i if (*argv == NULL) { Err bitreich.org 70 i if (ical_parse(&p, stdin) < 0) Err bitreich.org 70 i- err("parsing stdin:%d: %s", p.linenum, p.errmsg); Err bitreich.org 70 i+ err(1, "parsing stdin:%d: %s", p.linenum, p.errmsg); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i for (; *argv != NULL; argv++, argc--) { Err bitreich.org 70 i@@ -84,9 +87,9 @@ main(int argc, char **argv) Err bitreich.org 70 i Err bitreich.org 70 i debug("converting \"%s\"", *argv); Err bitreich.org 70 i if ((fp = fopen(*argv, "r")) == NULL) Err bitreich.org 70 i- err("opening %s", *argv); Err bitreich.org 70 i+ err(1, "opening %s", *argv); Err bitreich.org 70 i if (ical_parse(&p, fp) < 0) Err bitreich.org 70 i- err("parsing %s:%d: %s", *argv, p.linenum, p.errmsg); Err bitreich.org 70 i+ err(1, "parsing %s:%d: %s", *argv, p.linenum, p.errmsg); Err bitreich.org 70 i fclose(fp); Err bitreich.org 70 i } Err bitreich.org 70 i return 0; Err bitreich.org 70 1diff --git a/ics2tsv.c b/ics2tsv.c /scm/ics2txt/file/ics2tsv.c.gph bitreich.org 70 i@@ -5,10 +5,13 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i- Err bitreich.org 70 i #include "ical.h" Err bitreich.org 70 i #include "util.h" Err bitreich.org 70 i Err bitreich.org 70 i+#ifndef __OpenBSD__ Err bitreich.org 70 i+#define pledge(...) 0 Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i #define FIELDS_MAX 128 Err bitreich.org 70 i Err bitreich.org 70 i typedef struct Field Field; Err bitreich.org 70 i@@ -155,6 +158,9 @@ main(int argc, char **argv) Err bitreich.org 70 i Err bitreich.org 70 i arg0 = *argv; Err bitreich.org 70 i Err bitreich.org 70 i+ if (pledge("stdio rpath", "") < 0) Err bitreich.org 70 i+ err(1, "pledge: %s", strerror(errno)); Err bitreich.org 70 i+ Err bitreich.org 70 i p.fn_field_name = fn_field_name; Err bitreich.org 70 i p.fn_block_begin = fn_block_begin; Err bitreich.org 70 i p.fn_block_end = fn_block_end; Err bitreich.org 70 i@@ -186,12 +192,12 @@ main(int argc, char **argv) Err bitreich.org 70 i i = 0; Err bitreich.org 70 i do { Err bitreich.org 70 i if (i >= sizeof fields / sizeof *fields - 1) Err bitreich.org 70 i- err("too many fields specified with -o flag"); Err bitreich.org 70 i+ err(1, "too many fields specified with -o flag"); Err bitreich.org 70 i } while ((fields[i++] = strsep(&flag_f, ",")) != NULL); Err bitreich.org 70 i fields[i] = NULL; Err bitreich.org 70 i Err bitreich.org 70 i if (flag_1) { Err bitreich.org 70 i- printf("%s\t%s\t%s", "TYPE", "BEG", "END"); Err bitreich.org 70 i+ printf("%s\t%s\t%s\t%s", "TYPE", "BEG", "END", "RECUR"); Err bitreich.org 70 i for (i = 0; fields[i] != NULL; i++) Err bitreich.org 70 i printf("\t%s", fields[i]); Err bitreich.org 70 i fputc('\n', stdout); Err bitreich.org 70 i@@ -200,16 +206,17 @@ main(int argc, char **argv) Err bitreich.org 70 i if (*argv == NULL || strcmp(*argv, "-") == 0) { Err bitreich.org 70 i debug("converting *stdin*"); Err bitreich.org 70 i if (ical_parse(&p, stdin) < 0) Err bitreich.org 70 i- err("parsing *stdin*:%d: %s", p.linenum, p.errmsg); Err bitreich.org 70 i+ err(1, "parsing *stdin*:%d: %s", p.linenum, p.errmsg); Err bitreich.org 70 i } Err bitreich.org 70 i for (; *argv != NULL; argv++, argc--) { Err bitreich.org 70 i FILE *fp; Err bitreich.org 70 i debug("converting \"%s\"", *argv); Err bitreich.org 70 i if ((fp = fopen(*argv, "r")) == NULL) Err bitreich.org 70 i- err("opening %s: %s", *argv, strerror(errno)); Err bitreich.org 70 i+ err(1, "opening %s: %s", *argv, strerror(errno)); Err bitreich.org 70 i if (ical_parse(&p, fp) < 0) Err bitreich.org 70 i- err("parsing %s:%d: %s", *argv, p.linenum, p.errmsg); Err bitreich.org 70 i+ err(1, "parsing %s:%d: %s", *argv, p.linenum, p.errmsg); Err bitreich.org 70 i fclose(fp); Err bitreich.org 70 i } Err bitreich.org 70 i+ Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 1diff --git a/strtonum.c b/strtonum.c /scm/ics2txt/file/strtonum.c.gph bitreich.org 70 i@@ -0,0 +1,66 @@ Err bitreich.org 70 i+/* $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $ */ Err bitreich.org 70 i+ Err bitreich.org 70 i+/* Err bitreich.org 70 i+ * Copyright (c) 2004 Ted Unangst and Todd Miller Err bitreich.org 70 i+ * All rights reserved. Err bitreich.org 70 i+ * Err bitreich.org 70 i+ * Permission to use, copy, modify, and distribute this software for any Err bitreich.org 70 i+ * purpose with or without fee is hereby granted, provided that the above Err bitreich.org 70 i+ * copyright notice and this permission notice appear in all copies. Err bitreich.org 70 i+ * Err bitreich.org 70 i+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES Err bitreich.org 70 i+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF Err bitreich.org 70 i+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR Err bitreich.org 70 i+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES Err bitreich.org 70 i+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN Err bitreich.org 70 i+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF Err bitreich.org 70 i+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Err bitreich.org 70 i+ */ Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#define INVALID 1 Err bitreich.org 70 i+#define TOOSMALL 2 Err bitreich.org 70 i+#define TOOLARGE 3 Err bitreich.org 70 i+ Err bitreich.org 70 i+long long Err bitreich.org 70 i+strtonum(const char *numstr, long long minval, long long maxval, Err bitreich.org 70 i+ const char **errstrp) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ long long ll = 0; Err bitreich.org 70 i+ int error = 0; Err bitreich.org 70 i+ char *ep; Err bitreich.org 70 i+ struct errval { Err bitreich.org 70 i+ const char *errstr; Err bitreich.org 70 i+ int err; Err bitreich.org 70 i+ } ev[4] = { Err bitreich.org 70 i+ { NULL, 0 }, Err bitreich.org 70 i+ { "invalid", EINVAL }, Err bitreich.org 70 i+ { "too small", ERANGE }, Err bitreich.org 70 i+ { "too large", ERANGE }, Err bitreich.org 70 i+ }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ev[0].err = errno; Err bitreich.org 70 i+ errno = 0; Err bitreich.org 70 i+ if (minval > maxval) { Err bitreich.org 70 i+ error = INVALID; Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ ll = strtoll(numstr, &ep, 10); Err bitreich.org 70 i+ if (numstr == ep || *ep != '\0') Err bitreich.org 70 i+ error = INVALID; Err bitreich.org 70 i+ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) Err bitreich.org 70 i+ error = TOOSMALL; Err bitreich.org 70 i+ else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) Err bitreich.org 70 i+ error = TOOLARGE; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (errstrp != NULL) Err bitreich.org 70 i+ *errstrp = ev[error].errstr; Err bitreich.org 70 i+ errno = ev[error].err; Err bitreich.org 70 i+ if (error) Err bitreich.org 70 i+ ll = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return (ll); Err bitreich.org 70 i+} Err bitreich.org 70 i+DEF_WEAK(strtonum); Err bitreich.org 70 1diff --git a/tcal.5 b/tcal.5 /scm/ics2txt/file/tcal.5.gph bitreich.org 70 i@@ -1,61 +0,0 @@ Err bitreich.org 70 i-.Dd $Mdocdate: March 05 2020$ Err bitreich.org 70 i-.Dt TCAL 5 Err bitreich.org 70 i-.Os Err bitreich.org 70 i-. Err bitreich.org 70 i-. Err bitreich.org 70 i-.Sh NAME Err bitreich.org 70 i-. Err bitreich.org 70 i-.Nm tcal Err bitreich.org 70 i-.Nd plaintext calendar for editing by hand on the go Err bitreich.org 70 i-. Err bitreich.org 70 i-. Err bitreich.org 70 i-.Sh DESCRIPTION Err bitreich.org 70 i-. Err bitreich.org 70 i-The first line contain Err bitreich.org 70 i-.Dq TZ+HHMM Err bitreich.org 70 i-with Err bitreich.org 70 i-.Dq +HHMM Err bitreich.org 70 i-as returned by Err bitreich.org 70 i-.D1 $ date +%z . Err bitreich.org 70 i-. Err bitreich.org 70 i-.Pp Err bitreich.org 70 i-Then empty line delimited event entries follow, with for each: Err bitreich.org 70 i-One line with the start date, one line with the end date, Err bitreich.org 70 i-formatted like: Err bitreich.org 70 i-.Dq %Y-%m-%d %H:%M Err bitreich.org 70 i-. Err bitreich.org 70 i-.Pp Err bitreich.org 70 i-Then one line per attribute, each formatted with: Err bitreich.org 70 i-optional space, attribute name, colon, Err bitreich.org 70 i-optional space, and attribute content, Err bitreich.org 70 i-end of line. Err bitreich.org 70 i-. Err bitreich.org 70 i-. Err bitreich.org 70 i-.Sh EXAMPLES Err bitreich.org 70 i-. Err bitreich.org 70 i-.Bd -literal Err bitreich.org 70 i-TZ+0200 Err bitreich.org 70 i- Err bitreich.org 70 i-2021-06-28 00:00 Err bitreich.org 70 i-2021-06-05 00:00 Err bitreich.org 70 i- loc: 950-0994, Chuo Ward, Niigata, Japan Err bitreich.org 70 i- sum: summer holidays Err bitreich.org 70 i- Err bitreich.org 70 i-2021-06-29 13:30 Err bitreich.org 70 i-2021-06-29 15:00 Err bitreich.org 70 i- loc: online, irc.bitreich.org, #bitreich-en Err bitreich.org 70 i- sum: bitreich irc invitation Err bitreich.org 70 i- des: at this moment like all other moment, everyone invited on IRC Err bitreich.org 70 i-.Ed Err bitreich.org 70 i-. Err bitreich.org 70 i-. Err bitreich.org 70 i-.Sh SEE ALSO Err bitreich.org 70 i-. Err bitreich.org 70 i-.Xr cal 1 , Err bitreich.org 70 i-.Xr calendar 1 Err bitreich.org 70 i-. Err bitreich.org 70 i-. Err bitreich.org 70 i-.Sh AUTHORS Err bitreich.org 70 i-. Err bitreich.org 70 i-.An Josuah Demangeon Err bitreich.org 70 i-.Aq Mt me@josuah.net Err bitreich.org 70 1diff --git a/tsv2agenda.c b/tsv2agenda.c /scm/ics2txt/file/tsv2agenda.c.gph bitreich.org 70 i@@ -0,0 +1,193 @@ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include "util.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#ifndef __OpenBSD__ Err bitreich.org 70 i+#define pledge(...) 0 Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i+#define FIELDS_MAX 128 Err bitreich.org 70 i+ Err bitreich.org 70 i+enum { Err bitreich.org 70 i+ FIELD_TYPE, Err bitreich.org 70 i+ FIELD_BEG, Err bitreich.org 70 i+ FIELD_END, Err bitreich.org 70 i+ FIELD_RECUR, Err bitreich.org 70 i+ FIELD_OTHER, Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+typedef struct { Err bitreich.org 70 i+ struct tm beg, end; Err bitreich.org 70 i+} AgendaCtx; Err bitreich.org 70 i+ Err bitreich.org 70 i+static size_t field_categories = 0; Err bitreich.org 70 i+static size_t field_location = 0; Err bitreich.org 70 i+static size_t field_summary = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+print_date(struct tm *tm) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (tm == NULL) { Err bitreich.org 70 i+ fprintf(stdout, "%11s", ""); Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ char buf[128]; Err bitreich.org 70 i+ if (strftime(buf, sizeof buf, "%Y-%m-%d", tm) == 0) Err bitreich.org 70 i+ err(1, "strftime: %s", strerror(errno)); Err bitreich.org 70 i+ fprintf(stdout, "%s ", buf); Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+print_time(struct tm *tm) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (tm == NULL) { Err bitreich.org 70 i+ fprintf(stdout, "%5s ", ""); Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ char buf[128]; Err bitreich.org 70 i+ if (strftime(buf, sizeof buf, "%H:%M", tm) == 0) Err bitreich.org 70 i+ err(1, "strftime: %s", strerror(errno)); Err bitreich.org 70 i+ fprintf(stdout, "%5s ", buf); Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+print(AgendaCtx *ctx, char **fields, size_t n) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct tm beg = {0}, end = {0}; Err bitreich.org 70 i+ time_t t; Err bitreich.org 70 i+ char const *e; Err bitreich.org 70 i+ int rows, samedate; Err bitreich.org 70 i+ Err bitreich.org 70 i+ t = strtonum(fields[FIELD_BEG], 0, UINT32_MAX, &e); Err bitreich.org 70 i+ if (e != NULL) Err bitreich.org 70 i+ err(1, "start time %s is %s", fields[FIELD_BEG], e); Err bitreich.org 70 i+ localtime_r(&t, &beg); Err bitreich.org 70 i+ Err bitreich.org 70 i+ t = strtonum(fields[FIELD_END], 0, UINT32_MAX, &e); Err bitreich.org 70 i+ if (e != NULL) Err bitreich.org 70 i+ err(1, "end time %s is %s", fields[FIELD_END], e); Err bitreich.org 70 i+ localtime_r(&t, &end); Err bitreich.org 70 i+ Err bitreich.org 70 i+ fputc('\n', stdout); Err bitreich.org 70 i+ Err bitreich.org 70 i+ samedate = (ctx->beg.tm_year != beg.tm_year || ctx->beg.tm_mon != beg.tm_mon || Err bitreich.org 70 i+ ctx->beg.tm_mday != beg.tm_mday); Err bitreich.org 70 i+ print_date(samedate ? &beg : NULL); Err bitreich.org 70 i+ print_time(&beg); Err bitreich.org 70 i+ Err bitreich.org 70 i+ assert(field_summary < n); Err bitreich.org 70 i+ assert(field_summary > FIELD_OTHER); Err bitreich.org 70 i+ fprintf(stdout, "%s\n", fields[field_summary]); Err bitreich.org 70 i+ Err bitreich.org 70 i+ samedate = (beg.tm_year != end.tm_year || beg.tm_mon != end.tm_mon || Err bitreich.org 70 i+ beg.tm_mday != end.tm_mday); Err bitreich.org 70 i+ print_date(samedate ? &end : NULL); Err bitreich.org 70 i+ print_time(&end); Err bitreich.org 70 i+ Err bitreich.org 70 i+ rows = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ assert(field_location < n); Err bitreich.org 70 i+ if (field_location > 0 && fields[field_location][0] != '\0') { Err bitreich.org 70 i+ assert(field_summary > FIELD_OTHER); Err bitreich.org 70 i+ fprintf(stdout, "%s\n", fields[field_location]); Err bitreich.org 70 i+ rows++; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ assert(field_categories < n); Err bitreich.org 70 i+ if (field_categories > 0 && fields[field_categories][0] != '\0') { Err bitreich.org 70 i+ assert(field_summary > FIELD_OTHER); Err bitreich.org 70 i+ if (rows > 0) { Err bitreich.org 70 i+ print_date(NULL); Err bitreich.org 70 i+ print_time(NULL); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ fprintf(stdout, "%s\n", fields[field_categories]); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ ctx->beg = beg; Err bitreich.org 70 i+ ctx->end = end; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+set_fields_num(char **fields, size_t n) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct { char *name; size_t *var; } map[] = { Err bitreich.org 70 i+ { "CATEGORIES", &field_categories }, Err bitreich.org 70 i+ { "LOCATION", &field_location }, Err bitreich.org 70 i+ { "SUMMARY", &field_summary }, Err bitreich.org 70 i+ { NULL, NULL } Err bitreich.org 70 i+ }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ debug("n=%zd", n); Err bitreich.org 70 i+ for (size_t i1 = FIELD_OTHER; i1 < n; i1++) Err bitreich.org 70 i+ for (size_t i2 = 0; map[i2].name != NULL; i2++) Err bitreich.org 70 i+ if (strcasecmp(fields[i1], map[i2].name) == 0) Err bitreich.org 70 i+ *map[i2].var = i1; Err bitreich.org 70 i+ if (field_summary < FIELD_OTHER) Err bitreich.org 70 i+ err(1, "missing column SUMMARY"); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+ssize_t Err bitreich.org 70 i+tsv_getline(char **fields, size_t max, char **line, size_t *sz, FILE *fp) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *s; Err bitreich.org 70 i+ size_t n = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (getline(line, sz, fp) <= 0) Err bitreich.org 70 i+ return ferror(fp) ? -1 : 0; Err bitreich.org 70 i+ s = *line; Err bitreich.org 70 i+ strchomp(s); Err bitreich.org 70 i+ Err bitreich.org 70 i+ do { Err bitreich.org 70 i+ if (n >= max) Err bitreich.org 70 i+ return errno=E2BIG, -1; Err bitreich.org 70 i+ } while ((fields[n++] = strsep(&s, "\t")) != NULL); Err bitreich.org 70 i+ Err bitreich.org 70 i+ return n - 1; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+main(int argc, char **argv) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ AgendaCtx ctx = {0}; Err bitreich.org 70 i+ ssize_t nfield, n; Err bitreich.org 70 i+ size_t sz = 0; Err bitreich.org 70 i+ char *line = NULL, *fields[FIELDS_MAX]; Err bitreich.org 70 i+ Err bitreich.org 70 i+ arg0 = *argv; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (pledge("stdio", "") < 0) Err bitreich.org 70 i+ err(1, "pledge: %s", strerror(errno)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ nfield = tsv_getline(fields, FIELDS_MAX, &line, &sz, stdin); Err bitreich.org 70 i+ if (nfield == -1) Err bitreich.org 70 i+ err(1, "reading stdin: %s", strerror(errno)); Err bitreich.org 70 i+ if (nfield == 0) Err bitreich.org 70 i+ err(1, "empty input"); Err bitreich.org 70 i+ if (nfield < FIELD_OTHER) Err bitreich.org 70 i+ err(1, "not enough input columns"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ set_fields_num(fields, nfield); Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (size_t num = 1;; num++) { Err bitreich.org 70 i+ n = tsv_getline(fields, FIELDS_MAX, &line, &sz, stdin); Err bitreich.org 70 i+ if (n < 0) Err bitreich.org 70 i+ err(1, "line %zd: reading stdin: %s", num, strerror(errno)); Err bitreich.org 70 i+ if (n == 0) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ if (n != nfield) Err bitreich.org 70 i+ err(1, "line %zd: had %lld columns, wanted %lld", Err bitreich.org 70 i+ num, n, nfield); Err bitreich.org 70 i+ Err bitreich.org 70 i+ print(&ctx, fields, n); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ fputc('\n', stdout); Err bitreich.org 70 i+ Err bitreich.org 70 i+ free(line); Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/util.c b/util.c /scm/ics2txt/file/util.c.gph bitreich.org 70 i@@ -1,5 +1,4 @@ Err bitreich.org 70 i #include "util.h" Err bitreich.org 70 i- Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i@@ -22,13 +21,13 @@ _log(char const *fmt, va_list va) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i void Err bitreich.org 70 i-err(char const *fmt, ...) Err bitreich.org 70 i+err(int e, char const *fmt, ...) Err bitreich.org 70 i { Err bitreich.org 70 i va_list va; Err bitreich.org 70 i Err bitreich.org 70 i va_start(va, fmt); Err bitreich.org 70 i _log( fmt, va); Err bitreich.org 70 i- exit(1); Err bitreich.org 70 i+ exit(e); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i void Err bitreich.org 70 i@@ -87,8 +86,7 @@ strsep(char **sp, char const *sep) Err bitreich.org 70 i if (*sp == NULL) Err bitreich.org 70 i return NULL; Err bitreich.org 70 i prev = *sp; Err bitreich.org 70 i- for (s = *sp; strchr(sep, *s) == NULL; s++) Err bitreich.org 70 i- continue; Err bitreich.org 70 i+ for (s = *sp; strchr(sep, *s) == NULL; s++); Err bitreich.org 70 i if (*s == '\0') { Err bitreich.org 70 i *sp = NULL; Err bitreich.org 70 i } else { Err bitreich.org 70 1diff --git a/util.h b/util.h /scm/ics2txt/file/util.h.gph bitreich.org 70 i@@ -7,7 +7,7 @@ Err bitreich.org 70 i Err bitreich.org 70 i /** logging **/ Err bitreich.org 70 i extern char *arg0; Err bitreich.org 70 i-void err(char const *fmt, ...); Err bitreich.org 70 i+void err(int, char const *fmt, ...); Err bitreich.org 70 i void warn(char const *fmt, ...); Err bitreich.org 70 i void debug(char const *fmt, ...); Err bitreich.org 70 i Err bitreich.org 70 i@@ -17,6 +17,7 @@ char *strsep(char **, char const *); Err bitreich.org 70 i void strchomp(char *); Err bitreich.org 70 i char *strappend(char **, char const *); Err bitreich.org 70 i size_t strlcat(char *, char const *, size_t); Err bitreich.org 70 i+long long strtonum(const char *, long long, long long, const char **); Err bitreich.org 70 i Err bitreich.org 70 i /** memory **/ Err bitreich.org 70 i void *reallocarray(void *, size_t, size_t); Err bitreich.org 70 .