iical: improve and simplify line parsing - 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 92a5d0067b717710eb607c0465a8a60d4b4c8655 /scm/ics2txt/commit/92a5d0067b717710eb607c0465a8a60d4b4c8655.gph bitreich.org 70 1parent d10df705caaa2ca4e3229af6d5ec76e0f0d301da /scm/ics2txt/commit/d10df705caaa2ca4e3229af6d5ec76e0f0d301da.gph bitreich.org 70 hAuthor: Josuah Demangeon URL:mailto:me@josuah.net bitreich.org 70 iDate: Wed, 16 Jun 2021 23:13:22 +0200 Err bitreich.org 70 i Err bitreich.org 70 iical: improve and simplify line parsing Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M Makefile | 2 +- Err bitreich.org 70 i M bin/ics2tsv | 2 +- Err bitreich.org 70 i M ical.c | 152 +++++++++++++++++++------------ Err bitreich.org 70 i M ical.h | 25 ++++++++++++++++++------- Err bitreich.org 70 i M ics2tree.c | 8 ++++---- Err bitreich.org 70 i A ics2tsv.c | 99 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i M tcal.5 | 11 +++++------ Err bitreich.org 70 i Err bitreich.org 70 i7 files changed, 220 insertions(+), 79 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/Makefile b/Makefile /scm/ics2txt/file/Makefile.gph 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 Err bitreich.org 70 i+BIN = ics2tree ics2tsv Err bitreich.org 70 i MAN1 = ics2txt.1 Err bitreich.org 70 i MAN5 = tcal.5 Err bitreich.org 70 i Err bitreich.org 70 1diff --git a/bin/ics2tsv b/bin/ics2tsv /scm/ics2txt/file/bin/ics2tsv.gph bitreich.org 70 i@@ -126,7 +126,7 @@ sub("^ ", "") { Err bitreich.org 70 i next Err bitreich.org 70 i Err bitreich.org 70 i if (content["name"] == "TZID") { Err bitreich.org 70 i- ical_set_tzid(content["value"]) Err bitreich.org 70 i+ ical_set_tz(content["value"]) Err bitreich.org 70 i } else if (DT[content["name"]]) { Err bitreich.org 70 i vevent[content["name"]] = ical_to_epoch(content, params) Err bitreich.org 70 i } else { Err bitreich.org 70 1diff --git a/ical.c b/ical.c /scm/ics2txt/file/ical.c.gph bitreich.org 70 i@@ -11,14 +11,20 @@ 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-#define Xstrlcpy(d, s) (strlcpy((d), (s), sizeof(d)) < sizeof(d)) Err bitreich.org 70 i-#define Xstrlcat(d, s) (strlcat((d), (s), sizeof(d)) < sizeof(d)) Err bitreich.org 70 i- Err bitreich.org 70 i-/* helpers: common utilities to call within the p->fn() callbacks as Err bitreich.org 70 i- * well as in the code below */ Err bitreich.org 70 i+char *ical_block_name[ICAL_BLOCK_OTHER + 1] = { Err bitreich.org 70 i+ [ICAL_BLOCK_VEVENT] = "VEVENT", Err bitreich.org 70 i+ [ICAL_BLOCK_VTODO] = "VTODO", Err bitreich.org 70 i+ [ICAL_BLOCK_VJOURNAL] = "VJOURNAL", Err bitreich.org 70 i+ [ICAL_BLOCK_VFREEBUSY] = "VFREEBUSY", Err bitreich.org 70 i+ [ICAL_BLOCK_VALARM] = "VALARM", Err bitreich.org 70 i+ [ICAL_BLOCK_OTHER] = NULL, Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+/* valuel helpers: common utilities to call within the p->fn() Err bitreich.org 70 i+ * callbacks as well as in the code below */ Err bitreich.org 70 i Err bitreich.org 70 i int Err bitreich.org 70 i-ical_error(IcalParser *p, char const *msg) Err bitreich.org 70 i+ical_err(IcalParser *p, char *msg) Err bitreich.org 70 i { Err bitreich.org 70 i p->errmsg = msg; Err bitreich.org 70 i return -1; Err bitreich.org 70 i@@ -36,7 +42,7 @@ ical_get_value(IcalParser *p, char *s, size_t *len) Err bitreich.org 70 i *len = strlen(s); Err bitreich.org 70 i if (p->base64) Err bitreich.org 70 i if (base64_decode(s, len, s, len) < 0) Err bitreich.org 70 i- return ical_error(p, "invalid base64 data"); Err bitreich.org 70 i+ return ical_err(p, "invalid base64 data"); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -55,7 +61,7 @@ ical_get_time(IcalParser *p, char *s, time_t *t) Err bitreich.org 70 i /* date */ Err bitreich.org 70 i for (int i = 0; i < 8; i++) Err bitreich.org 70 i if (!isdigit(s[i])) Err bitreich.org 70 i- return ical_error(p, "invalid date format"); Err bitreich.org 70 i+ return ical_err(p, "invalid date format"); Err bitreich.org 70 i tm.tm_year = N(0,1000) + N(1,100) + N(2,10) + N(3,1) - 1900; Err bitreich.org 70 i tm.tm_mon = N(4,10) + N(5,1) - 1; Err bitreich.org 70 i tm.tm_mday = N(6,10) + N(7,1); Err bitreich.org 70 i@@ -66,7 +72,7 @@ ical_get_time(IcalParser *p, char *s, time_t *t) Err bitreich.org 70 i s++; Err bitreich.org 70 i for (int i = 0; i < 6; i++) Err bitreich.org 70 i if (!isdigit(s[i])) Err bitreich.org 70 i- return ical_error(p, "invalid time format"); Err bitreich.org 70 i+ return ical_err(p, "invalid time format"); Err bitreich.org 70 i tm.tm_hour = N(0,10) + N(1,1); Err bitreich.org 70 i tm.tm_min = N(2,10) + N(3,1); Err bitreich.org 70 i tm.tm_sec = N(4,10) + N(5,1); Err bitreich.org 70 i@@ -74,8 +80,10 @@ ical_get_time(IcalParser *p, char *s, time_t *t) Err bitreich.org 70 i tzid = "UTC"; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+#undef N Err bitreich.org 70 i+ Err bitreich.org 70 i if ((*t = tztime(&tm, tzid)) == (time_t)-1) Err bitreich.org 70 i- return ical_error(p, "could not convert time"); Err bitreich.org 70 i+ return ical_err(p, "could not convert time"); Err bitreich.org 70 i Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i@@ -84,21 +92,21 @@ ical_get_time(IcalParser *p, char *s, time_t *t) Err bitreich.org 70 i * processing time zones definition or prepare base64 decoding, and Err bitreich.org 70 i * permit to only have parsing code left to parsing functions */ Err bitreich.org 70 i Err bitreich.org 70 i-int Err bitreich.org 70 i+static int Err bitreich.org 70 i hook_entry_name(IcalParser *p, char *name) Err bitreich.org 70 i { Err bitreich.org 70 i (void)p; (void)name; Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-int Err bitreich.org 70 i+static int Err bitreich.org 70 i hook_param_name(IcalParser *p, char *name) Err bitreich.org 70 i { Err bitreich.org 70 i (void)p; (void)name; Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-int Err bitreich.org 70 i+static int Err bitreich.org 70 i hook_param_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i { Err bitreich.org 70 i if (strcasecmp(name, "ENCODING") == 0) Err bitreich.org 70 i@@ -110,38 +118,53 @@ hook_param_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-int Err bitreich.org 70 i+static int Err bitreich.org 70 i hook_entry_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i { Err bitreich.org 70 i if (strcasecmp(name, "TZID") == 0) Err bitreich.org 70 i- if (!Xstrlcpy(p->current->tzid, value)) Err bitreich.org 70 i- return ical_error(p, "TZID: name too large"); Err bitreich.org 70 i+ if (strlcpy(p->current->tzid, value, sizeof p->current->tzid) >= Err bitreich.org 70 i+ sizeof p->current->tzid) Err bitreich.org 70 i+ return ical_err(p, "TZID: name too large"); Err bitreich.org 70 i Err bitreich.org 70 i p->tzid = NULL; Err bitreich.org 70 i Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-int Err bitreich.org 70 i+static int Err bitreich.org 70 i hook_block_begin(IcalParser *p, char *name) Err bitreich.org 70 i { Err bitreich.org 70 i p->current++; Err bitreich.org 70 i memset(p->current, 0, sizeof(*p->current)); Err bitreich.org 70 i if (ical_get_level(p) >= ICAL_STACK_SIZE) Err bitreich.org 70 i- return ical_error(p, "max recurion reached"); Err bitreich.org 70 i- if (!Xstrlcpy(p->current->name, name)) Err bitreich.org 70 i- return ical_error(p, "value too large"); Err bitreich.org 70 i+ return ical_err(p, "max recurion reached"); Err bitreich.org 70 i+ if (strlcpy(p->current->name, name, sizeof p->current->name) >= Err bitreich.org 70 i+ sizeof p->current->name) Err bitreich.org 70 i+ return ical_err(p, "value too large"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (int i = 0; ical_block_name[i] != NULL; i++) { Err bitreich.org 70 i+ if (strcasecmp(ical_block_name[i], name) == 0) { Err bitreich.org 70 i+ if (p->block != ICAL_BLOCK_OTHER) Err bitreich.org 70 i+ return ical_err(p, "BEGIN:V* in BEGIN:V*"); Err bitreich.org 70 i+ p->block = i; Err bitreich.org 70 i+ } 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 i Err bitreich.org 70 i-int Err bitreich.org 70 i+static int Err bitreich.org 70 i hook_block_end(IcalParser *p, char *name) Err bitreich.org 70 i { Err bitreich.org 70 i if (strcasecmp(p->current->name, name) != 0) Err bitreich.org 70 i- return ical_error(p, "mismatching BEGIN: and END:"); Err bitreich.org 70 i+ return ical_err(p, "mismatching BEGIN: and END:"); Err bitreich.org 70 i p->current--; Err bitreich.org 70 i if (p->current < p->stack) Err bitreich.org 70 i- return ical_error(p, "more END: than BEGIN:"); Err bitreich.org 70 i+ return ical_err(p, "more END: than BEGIN:"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (ical_block_name[p->block] != NULL && Err bitreich.org 70 i+ strcasecmp(ical_block_name[p->block], name) == 0) Err bitreich.org 70 i+ p->block = ICAL_BLOCK_OTHER; Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -162,7 +185,7 @@ ical_parse_value(IcalParser *p, char **sp, char *name) Err bitreich.org 70 i while (!iscntrl(*s) && *s != '"') Err bitreich.org 70 i s++; Err bitreich.org 70 i if (*s != '"') Err bitreich.org 70 i- return ical_error(p, "missing '\"'"); Err bitreich.org 70 i+ return ical_err(p, "missing '\"'"); Err bitreich.org 70 i *s++ = '\0'; Err bitreich.org 70 i } else { Err bitreich.org 70 i val = s; Err bitreich.org 70 i@@ -188,7 +211,7 @@ ical_parse_param(IcalParser *p, char **sp) Err bitreich.org 70 i do { Err bitreich.org 70 i for (name = s; isalnum(*s) || *s == '-'; s++); Err bitreich.org 70 i if (s == name || (*s != '=')) Err bitreich.org 70 i- return ical_error(p, "invalid parameter name"); Err bitreich.org 70 i+ return ical_err(p, "invalid parameter name"); Err bitreich.org 70 i *s++ = '\0'; Err bitreich.org 70 i if ((err = hook_param_name(p, name)) != 0 || Err bitreich.org 70 i (err = CALL(p, fn_param_name, name)) != 0) Err bitreich.org 70 i@@ -208,9 +231,12 @@ ical_parse_contentline(IcalParser *p, char *s) Err bitreich.org 70 i int err; Err bitreich.org 70 i char c, *name, *sep; Err bitreich.org 70 i Err bitreich.org 70 i+ if (*s == '\0') Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+ Err bitreich.org 70 i for (name = s; isalnum(*s) || *s == '-'; s++); Err bitreich.org 70 i if (s == name || (*s != ';' && *s != ':')) Err bitreich.org 70 i- return ical_error(p, "invalid entry name"); Err bitreich.org 70 i+ return ical_err(p, "invalid property name"); Err bitreich.org 70 i c = *s, *s = '\0'; Err bitreich.org 70 i if (strcasecmp(name, "BEGIN") != 0 && strcasecmp(name, "END") != 0) Err bitreich.org 70 i if ((err = hook_entry_name(p, name)) != 0 || Err bitreich.org 70 i@@ -227,7 +253,7 @@ ical_parse_contentline(IcalParser *p, char *s) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i if (*s != ':') Err bitreich.org 70 i- return ical_error(p, "expected ':' delimiter"); Err bitreich.org 70 i+ return ical_err(p, "expected ':' delimiter"); Err bitreich.org 70 i s++; Err bitreich.org 70 i Err bitreich.org 70 i *sep = '\0'; Err bitreich.org 70 i@@ -247,47 +273,53 @@ ical_parse_contentline(IcalParser *p, char *s) Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+static ssize_t Err bitreich.org 70 i+ical_getline(char **contentline, char **line, size_t *sz, FILE *fp) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t num = 0; Err bitreich.org 70 i+ int c; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if ((*contentline = realloc(*contentline, 1)) == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ **contentline = '\0'; Err bitreich.org 70 i+ Err bitreich.org 70 i+ do { Err bitreich.org 70 i+ if (getline(line, sz, fp) <= 0) Err bitreich.org 70 i+ goto end; Err bitreich.org 70 i+ num++; Err bitreich.org 70 i+ strchomp(*line); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (strappend(contentline, *line) < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ if ((c = fgetc(fp)) == EOF) Err bitreich.org 70 i+ goto end; Err bitreich.org 70 i+ } while (c == ' '); Err bitreich.org 70 i+ ungetc(c, fp); Err bitreich.org 70 i+ assert(!ferror(fp)); Err bitreich.org 70 i+end: Err bitreich.org 70 i+ return ferror(fp) ? -1 : num; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i int Err bitreich.org 70 i ical_parse(IcalParser *p, FILE *fp) Err bitreich.org 70 i { Err bitreich.org 70 i- char *ln = NULL, *contentline = NULL; Err bitreich.org 70 i+ char *line = NULL, *contentline = NULL; Err bitreich.org 70 i size_t sz = 0; Err bitreich.org 70 i- int err, c; Err bitreich.org 70 i+ ssize_t l; Err bitreich.org 70 i+ int err; Err bitreich.org 70 i Err bitreich.org 70 i p->current = p->stack; Err bitreich.org 70 i+ p->linenum = 0; Err bitreich.org 70 i+ p->block = ICAL_BLOCK_OTHER; Err bitreich.org 70 i Err bitreich.org 70 i- while (!feof(fp)) { Err bitreich.org 70 i- if ((contentline = realloc(contentline, 1)) == NULL) Err bitreich.org 70 i- return ical_error(p, strerror(errno)); Err bitreich.org 70 i- *contentline = '\0'; Err bitreich.org 70 i- Err bitreich.org 70 i- do { Err bitreich.org 70 i- do { Err bitreich.org 70 i- p->linenum++; Err bitreich.org 70 i- if (getline(&ln, &sz, fp) <= 0) { Err bitreich.org 70 i- if (ferror(fp)) Err bitreich.org 70 i- return ical_error(p, strerror(errno)); Err bitreich.org 70 i- goto end; Err bitreich.org 70 i- } Err bitreich.org 70 i- strchomp(ln); Err bitreich.org 70 i- } while (*ln == '\0'); Err bitreich.org 70 i- Err bitreich.org 70 i- if (strappend(&contentline, ln) < 0) Err bitreich.org 70 i- return ical_error(p, strerror(errno)); Err bitreich.org 70 i- if ((c = fgetc(fp)) == EOF) { Err bitreich.org 70 i- if (ferror(fp)) Err bitreich.org 70 i- return ical_error(p, strerror(errno)); Err bitreich.org 70 i- goto done; Err bitreich.org 70 i- } Err bitreich.org 70 i- } while (c == ' '); Err bitreich.org 70 i- ungetc(c, fp); Err bitreich.org 70 i-done: Err bitreich.org 70 i- assert(!ferror(fp)); Err bitreich.org 70 i- if ((err = ical_parse_contentline(p, contentline)) != 0) Err bitreich.org 70 i+ do { Err bitreich.org 70 i+ if ((l = ical_getline(&contentline, &line, &sz, fp)) < 0) { Err bitreich.org 70 i+ err = ical_err(p, "readling line"); Err bitreich.org 70 i break; Err bitreich.org 70 i- } Err bitreich.org 70 i-end: Err bitreich.org 70 i+ } Err bitreich.org 70 i+ p->linenum += l; Err bitreich.org 70 i+ } while (l > 0 && (err = ical_parse_contentline(p, contentline)) == 0); Err bitreich.org 70 i free(contentline); Err bitreich.org 70 i- free(ln); Err bitreich.org 70 i+ free(line); Err bitreich.org 70 i return err; Err bitreich.org 70 i } Err bitreich.org 70 1diff --git a/ical.h b/ical.h /scm/ics2txt/file/ical.h.gph bitreich.org 70 i@@ -9,6 +9,15 @@ 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+ ICAL_BLOCK_VJOURNAL, Err bitreich.org 70 i+ ICAL_BLOCK_VFREEBUSY, Err bitreich.org 70 i+ ICAL_BLOCK_VALARM, 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 char name[32]; Err bitreich.org 70 i char tzid[32]; Err bitreich.org 70 i@@ -25,17 +34,19 @@ struct IcalParser { Err bitreich.org 70 i /* if returning non-zero then halt the parser */ Err bitreich.org 70 i Err bitreich.org 70 i int base64; Err bitreich.org 70 i- char const *errmsg; Err bitreich.org 70 i+ char *errmsg; Err bitreich.org 70 i size_t linenum; Err bitreich.org 70 i char *tzid; Err bitreich.org 70 i- Err bitreich.org 70 i+ IcalBlock block; Err bitreich.org 70 i IcalStack stack[ICAL_STACK_SIZE], *current; Err bitreich.org 70 i }; Err bitreich.org 70 i Err bitreich.org 70 i-int ical_parse(IcalParser *, FILE *); Err bitreich.org 70 i-int ical_get_level(IcalParser *); Err bitreich.org 70 i-int ical_get_time(IcalParser *, char *, time_t *); Err bitreich.org 70 i-int ical_get_value(IcalParser *, char *, size_t *); Err bitreich.org 70 i-int ical_error(IcalParser *, char const *); Err bitreich.org 70 i+extern char *ical_block_name[ICAL_BLOCK_OTHER + 1]; Err bitreich.org 70 i+ Err bitreich.org 70 i+int ical_parse(IcalParser *, FILE *); Err bitreich.org 70 i+int ical_get_level(IcalParser *); Err bitreich.org 70 i+int ical_get_time(IcalParser *, char *, time_t *); Err bitreich.org 70 i+int ical_get_value(IcalParser *, char *, size_t *); Err bitreich.org 70 i+int ical_err(IcalParser *, char *); Err bitreich.org 70 i Err bitreich.org 70 i #endif Err bitreich.org 70 1diff --git a/ics2tree.c b/ics2tree.c /scm/ics2txt/file/ics2tree.c.gph bitreich.org 70 i@@ -18,6 +18,7 @@ fn_entry_name(IcalParser *p, char *name) Err bitreich.org 70 i { Err bitreich.org 70 i print_ruler(ical_get_level(p)); Err bitreich.org 70 i printf("name %s\n", name); Err bitreich.org 70 i+ fflush(stdout); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -26,6 +27,7 @@ fn_block_begin(IcalParser *p, char *name) Err bitreich.org 70 i { Err bitreich.org 70 i print_ruler(ical_get_level(p) - 1); Err bitreich.org 70 i printf("begin %s\n", name); Err bitreich.org 70 i+ fflush(stdout); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -34,6 +36,7 @@ fn_param_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i { Err bitreich.org 70 i print_ruler(ical_get_level(p) + 1); Err bitreich.org 70 i printf("param %s=%s\n", name, value); Err bitreich.org 70 i+ fflush(stdout); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -45,21 +48,18 @@ fn_entry_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i Err bitreich.org 70 i if (ical_get_value(p, value, &len) < 0) Err bitreich.org 70 i return -1; Err bitreich.org 70 i- Err bitreich.org 70 i print_ruler(ical_get_level(p) + 1); Err bitreich.org 70 i- Err bitreich.org 70 i if (strcasecmp(name, "DTSTART") == 0 || Err bitreich.org 70 i strcasecmp(name, "DTSTAMP") == 0 || Err bitreich.org 70 i strcasecmp(name, "DTEND") == 0) { Err bitreich.org 70 i time_t t; Err bitreich.org 70 i- Err bitreich.org 70 i if (ical_get_time(p, value, &t) != 0) Err bitreich.org 70 i warn("%s: %s", p->errmsg, value); Err bitreich.org 70 i printf("epoch %lld\n", t); Err bitreich.org 70 i } else { Err bitreich.org 70 i printf("value %s\n", value); Err bitreich.org 70 i } Err bitreich.org 70 i- Err bitreich.org 70 i+ fflush(stdout); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 1diff --git a/ics2tsv.c b/ics2tsv.c /scm/ics2txt/file/ics2tsv.c.gph bitreich.org 70 i@@ -0,0 +1,99 @@ 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 "ical.h" Err bitreich.org 70 i+#include "util.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#define FIELDS_MAX 64 Err bitreich.org 70 i+ Err bitreich.org 70 i+typedef struct Event Event; Err bitreich.org 70 i+ Err bitreich.org 70 i+struct Event { Err bitreich.org 70 i+ time_t beg, end; Err bitreich.org 70 i+ char *fields[FIELDS_MAX]; Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+static char *fields_time[] = { Err bitreich.org 70 i+ "DTSTART", "DTEND", "DTSTAMP", "DUE", "EXDATE", "RDATE" Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+static char *fields_default[] = { Err bitreich.org 70 i+ "ATTENDEE", "CATEGORY", "DESCRIPTION", "LOCATION", "SUMMARY", "URL" Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+static char **fields = fields_default; Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+fn_entry_name(IcalParser *p, char *name) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ printf("name %s\n", name); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+fn_block_begin(IcalParser *p, char *name) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ printf("begin %s\n", name); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+fn_param_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ printf("param %s=%s\n", name, value); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+fn_entry_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t len; Err bitreich.org 70 i+ (void)name; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (ical_get_value(p, value, &len) < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (strcasecmp(name, "DTSTART") == 0 || Err bitreich.org 70 i+ strcasecmp(name, "DTSTAMP") == 0 || Err bitreich.org 70 i+ strcasecmp(name, "DTEND") == 0) { Err bitreich.org 70 i+ time_t t = 0; Err bitreich.org 70 i+ if (ical_get_time(p, value, &t) != 0) Err bitreich.org 70 i+ warn("%s: %s", p->errmsg, value); Err bitreich.org 70 i+ printf("epoch %lld\n", t); Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ printf("value %s\n", value); 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 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+ IcalParser p = {0}; Err bitreich.org 70 i+ arg0 = *argv++; Err bitreich.org 70 i+ Err bitreich.org 70 i+ p.fn_entry_name = fn_entry_name; Err bitreich.org 70 i+ p.fn_block_begin = fn_block_begin; Err bitreich.org 70 i+ p.fn_param_value = fn_param_value; Err bitreich.org 70 i+ p.fn_entry_value = fn_entry_value; 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 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+ 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+ 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+ fclose(fp); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/tcal.5 b/tcal.5 /scm/ics2txt/file/tcal.5.gph bitreich.org 70 i@@ -36,17 +36,16 @@ end of line. Err bitreich.org 70 i .Bd -literal Err bitreich.org 70 i TZ+0200 Err bitreich.org 70 i Err bitreich.org 70 i-2020-06-28 00:00 Err bitreich.org 70 i-2020-06-05 00:00 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-2020-06-29 13:30 Err bitreich.org 70 i-2020-06-29 15:00 Err bitreich.org 70 i- loc: online, irc.freenode.net, #bitreich-en 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- Err bitreich.org 70 i .Ed Err bitreich.org 70 i . Err bitreich.org 70 i . Err bitreich.org 70 .