iinitial C implementation - 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 94bccd0b9ea7049ebeec4fcf2416f6f0b7d221b5 /scm/ics2txt/commit/94bccd0b9ea7049ebeec4fcf2416f6f0b7d221b5.gph bitreich.org 70 1parent 78e0184b4deb29669bfde9a66fc945968845ced8 /scm/ics2txt/commit/78e0184b4deb29669bfde9a66fc945968845ced8.gph bitreich.org 70 hAuthor: Josuah Demangeon URL:mailto:me@josuah.net bitreich.org 70 iDate: Sat, 27 Jun 2020 20:31:09 +0200 Err bitreich.org 70 i Err bitreich.org 70 iinitial C implementation Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i A .gitignore | 2 ++ Err bitreich.org 70 i M Makefile | 24 +++++++++++++++++++----- Err bitreich.org 70 i A bin/ics2tsv | 141 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i R ics2txt -> bin/ics2txt | 0 Err bitreich.org 70 i R tcal2tsv -> bin/tcal2tsv | 0 Err bitreich.org 70 i R tsv2ics -> bin/tsv2ics | 0 Err bitreich.org 70 i A bin/tsv2tcal | 91 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A doc/index.md | 11 +++++++++++ Err bitreich.org 70 i D ics2tsv | 138 ------------------------------ Err bitreich.org 70 i A ics2tsv.c | 62 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A src/ical.c | 108 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A src/ical.h | 25 +++++++++++++++++++++++++ Err bitreich.org 70 i A src/log.c | 89 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A src/log.h | 15 +++++++++++++++ Err bitreich.org 70 i A src/map.c | 102 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A src/map.h | 23 +++++++++++++++++++++++ Err bitreich.org 70 i A src/util.c | 74 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A src/util.h | 13 +++++++++++++ Err bitreich.org 70 i D tsv2tcal | 91 ------------------------------- Err bitreich.org 70 i Err bitreich.org 70 i19 files changed, 775 insertions(+), 234 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@@ -0,0 +1,2 @@ Err bitreich.org 70 i+*.o Err bitreich.org 70 i+ics2tsv Err bitreich.org 70 1diff --git a/Makefile b/Makefile /scm/ics2txt/file/Makefile.gph bitreich.org 70 i@@ -1,23 +1,37 @@ Err bitreich.org 70 i NAME = ics2txt Err bitreich.org 70 i VERSION = 0.1 Err bitreich.org 70 i Err bitreich.org 70 i-BIN = ics2tsv tsv2tcal tcal2tsv tsv2ics ics2txt Err bitreich.org 70 i- Err bitreich.org 70 i+W = -Wall -Wextra -std=c99 --pedantic Err bitreich.org 70 i+I = -Isrc Err bitreich.org 70 i+D = -D_POSIX_C_SOURCE=200811L -DVERSION='"${VERSION}"' Err bitreich.org 70 i+CFLAGS = $I $D $W -g Err bitreich.org 70 i PREFIX = /usr/local Err bitreich.org 70 i MANPREFIX = ${PREFIX}/man Err bitreich.org 70 i Err bitreich.org 70 i+SRC = src/ical.c src/map.c src/util.c src/log.c Err bitreich.org 70 i+HDR = src/ical.h src/map.h src/util.h src/log.h Err bitreich.org 70 i+OBJ = ${SRC:.c=.o} Err bitreich.org 70 i+BIN = ics2tsv Err bitreich.org 70 i+ Err bitreich.org 70 i all: ${BIN} Err bitreich.org 70 i Err bitreich.org 70 i+.c.o: Err bitreich.org 70 i+ ${CC} -c ${CFLAGS} -o $@ $< Err bitreich.org 70 i+ Err bitreich.org 70 i+${OBJ}: ${HDR} Err bitreich.org 70 i+${BIN}: ${OBJ} ${BIN:=.o} Err bitreich.org 70 i+ ${CC} ${LDFLAGS} -o $@ $@.o ${OBJ} Err bitreich.org 70 i+ Err bitreich.org 70 i clean: Err bitreich.org 70 i- rm -rf ${NAME}-${VERSION} *.gz Err bitreich.org 70 i+ rm -rf *.o */*.o ${BIN} ${NAME}-${VERSION} *.gz Err bitreich.org 70 i Err bitreich.org 70 i install: Err bitreich.org 70 i mkdir -p ${DESTDIR}$(PREFIX)/bin Err bitreich.org 70 i- cp $(BIN) ${DESTDIR}$(PREFIX)/bin Err bitreich.org 70 i+ cp bin/* $(BIN) ${DESTDIR}$(PREFIX)/bin Err bitreich.org 70 i mkdir -p ${DESTDIR}$(MANPREFIX)/man1 Err bitreich.org 70 i cp doc/*.1 ${DESTDIR}$(MANPREFIX)/man1 Err bitreich.org 70 i Err bitreich.org 70 i dist: clean Err bitreich.org 70 i mkdir -p ${NAME}-${VERSION} Err bitreich.org 70 i- cp -r README Makefile doc ${BIN} ${NAME}-${VERSION} Err bitreich.org 70 i+ cp -r README Makefile doc bin ${SRC} ${NAME}-${VERSION} Err bitreich.org 70 i tar -cf - ${NAME}-${VERSION} | gzip -c >${NAME}-${VERSION}.tar.gz Err bitreich.org 70 1diff --git a/bin/ics2tsv b/bin/ics2tsv /scm/ics2txt/file/bin/ics2tsv.gph bitreich.org 70 i@@ -0,0 +1,141 @@ 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 timegm(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 print_vevent(ev, fields, Err bitreich.org 70 i+ 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+} Err bitreich.org 70 i+ Err bitreich.org 70 i+function ical_parse_line(str, content, params, Err bitreich.org 70 i+ i, eq) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if ((i = index(str, ":")) == 0) Err bitreich.org 70 i+ return -1 Err bitreich.org 70 i+ content["value"] = substr(str, i + 1) Err bitreich.org 70 i+ str = substr(str, 1, i - 1) Err bitreich.org 70 i+ Err bitreich.org 70 i+ if ((i = index(str, ";")) == 0) { Err bitreich.org 70 i+ content["name"] = str Err bitreich.org 70 i+ return 0 Err bitreich.org 70 i+ } Err bitreich.org 70 i+ content["name"] = substr(str, 1, i - 1) Err bitreich.org 70 i+ str = substr(str, i + 1) Err bitreich.org 70 i+ Err bitreich.org 70 i+ while ((i = index(str, ";")) > 0) { Err bitreich.org 70 i+ if ((eq = index(str, "=")) == 0) Err bitreich.org 70 i+ return -1 Err bitreich.org 70 i+ param[substr(str, 1, eq - 1)] = substr(str, eq + 1, i - 1) Err bitreich.org 70 i+ str = substr(str, eq + 1) Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if ((eq = index(str, "=")) == 0) Err bitreich.org 70 i+ return -1 Err bitreich.org 70 i+ params[substr(str, 1, eq - 1)] = substr(str, eq + 1) Err bitreich.org 70 i+ return 0 Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+function ical_set_tz(tzid) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ gsub("'", "", tzid) Err bitreich.org 70 i+ cmd = "TZ='" tzid "' exec date +%z" Err bitreich.org 70 i+ cmd | getline tzid Err bitreich.org 70 i+ close(cmd) Err bitreich.org 70 i+ TZ = substr(tzid, 1, 1) substr(tzid, 2, 2)*3600 + substr(tzid, 4, 2)*60 Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+function ical_to_epoch(content, param, Err bitreich.org 70 i+ tz, cmd) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (param["TZID"]) Err bitreich.org 70 i+ ical_set_tz(param["TZID"]) Err bitreich.org 70 i+ Err bitreich.org 70 i+ tm["year"] = substr(content["value"], 1, 4) Err bitreich.org 70 i+ tm["mon"] = substr(content["value"], 5, 2) Err bitreich.org 70 i+ tm["mday"] = substr(content["value"], 7, 2) Err bitreich.org 70 i+ tm["hour"] = substr(content["value"], 10, 2) Err bitreich.org 70 i+ tm["min"] = substr(content["value"], 12, 2) Err bitreich.org 70 i+ tm["sec"] = substr(content["value"], 14, 2) Err bitreich.org 70 i+ Err bitreich.org 70 i+ return timegm(tm) + TZ Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+BEGIN { Err bitreich.org 70 i+ split("DTSTART DTEND CATEGORIES LOCATION SUMMARY DESCRIPTION URL", Err bitreich.org 70 i+ FIELDS, " ") Err bitreich.org 70 i+ DT["DTSTART"] = DT["DTEND"] = DT["DUE"] = 1 Err bitreich.org 70 i+ Err bitreich.org 70 i+ # by default: "CATEGORIES" -> "cat", "LOCATION" -> "loc"... Err bitreich.org 70 i+ translate["DTSTART"] = "beg" Err bitreich.org 70 i+ translate["DTEND"] = "end" Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (i = 1; i in FIELDS; i++) { Err bitreich.org 70 i+ if (!(s = translate[FIELDS[i]])) Err bitreich.org 70 i+ s = tolower(substr(FIELDS[i], 1, 3)) Err bitreich.org 70 i+ printf("%s%s", (i > 1 ? "\t" : ""), s) Err bitreich.org 70 i+ } Err bitreich.org 70 i+ printf("\n") Err bitreich.org 70 i+ Err bitreich.org 70 i+ FS = "[:;]" Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+{ Err bitreich.org 70 i+ gsub("\r", "") Err bitreich.org 70 i+ gsub("\t", "\\\\t") Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+sub("^ ", "") { Err bitreich.org 70 i+ content["value"] = content["value"] $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+ delete content Err bitreich.org 70 i+ delete param Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (ical_parse_line($0, content, params) < 0) 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+ } 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 i+ vevent[content["name"]] = content["value"] Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/^END:VEVENT/ { Err bitreich.org 70 i+ print_vevent(vevent, FIELDS) Err bitreich.org 70 i+ delete vevent Err bitreich.org 70 i+ next Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/ics2txt b/bin/ics2txt /scm/ics2txt/file/bin/ics2txt.gph bitreich.org 70 1diff --git a/tcal2tsv b/bin/tcal2tsv /scm/ics2txt/file/bin/tcal2tsv.gph bitreich.org 70 1diff --git a/tsv2ics b/bin/tsv2ics /scm/ics2txt/file/bin/tsv2ics.gph bitreich.org 70 1diff --git a/bin/tsv2tcal b/bin/tsv2tcal /scm/ics2txt/file/bin/tsv2tcal.gph bitreich.org 70 i@@ -0,0 +1,91 @@ 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/doc/index.md b/doc/index.md /scm/ics2txt/file/doc/index.md.gph bitreich.org 70 i@@ -0,0 +1,11 @@ Err bitreich.org 70 i+ics2txt Err bitreich.org 70 i+======= Err bitreich.org 70 i+Set of tools to work with the popular iCalendar format and converting to even Err bitreich.org 70 i+simpler TSV and text forms. Err bitreich.org 70 i+ Err bitreich.org 70 i+Parsing have been tested with the following input formats (sample account Err bitreich.org 70 i+created for testing): 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 i+* Google Calendar Err bitreich.org 70 1diff --git a/ics2tsv b/ics2tsv /scm/ics2txt/file/ics2tsv.gph bitreich.org 70 i@@ -1,138 +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 timegm(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 print_vevent(ev, fields, Err bitreich.org 70 i- 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-} Err bitreich.org 70 i- Err bitreich.org 70 i-function ical_parse_line(str, content, params, Err bitreich.org 70 i- i, eq) Err bitreich.org 70 i-{ Err bitreich.org 70 i- if ((i = index(str, ":")) == 0) Err bitreich.org 70 i- return -1 Err bitreich.org 70 i- content["value"] = substr(str, i + 1) Err bitreich.org 70 i- str = substr(str, 1, i - 1) Err bitreich.org 70 i- Err bitreich.org 70 i- if ((i = index(str, ";")) == 0) { Err bitreich.org 70 i- content["name"] = str Err bitreich.org 70 i- return 0 Err bitreich.org 70 i- } Err bitreich.org 70 i- content["name"] = substr(str, 1, i - 1) Err bitreich.org 70 i- str = substr(str, i + 1) Err bitreich.org 70 i- Err bitreich.org 70 i- while ((i = index(str, ";")) > 0) { Err bitreich.org 70 i- if ((eq = index(str, "=")) == 0) Err bitreich.org 70 i- return -1 Err bitreich.org 70 i- param[substr(str, 1, eq - 1)] = substr(str, eq + 1, i - 1) Err bitreich.org 70 i- str = substr(str, eq + 1) Err bitreich.org 70 i- } Err bitreich.org 70 i- if ((eq = index(str, "=")) == 0) Err bitreich.org 70 i- return -1 Err bitreich.org 70 i- params[substr(str, 1, eq - 1)] = substr(str, eq + 1) Err bitreich.org 70 i- return 0 Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-function ical_to_epoch(content, param, Err bitreich.org 70 i- tz, cmd) Err bitreich.org 70 i-{ Err bitreich.org 70 i- tz = (param["TZID"] ? param["TZID"] : vcalendar["TZID"]) Err bitreich.org 70 i- gsub("'", "", tz) Err bitreich.org 70 i- Err bitreich.org 70 i- cmd = "TZ='"tz"' date +%z" Err bitreich.org 70 i- cmd | getline tz Err bitreich.org 70 i- close(cmd) Err bitreich.org 70 i- 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- tm["year"] = substr(content["value"], 1, 4) Err bitreich.org 70 i- tm["mon"] = substr(content["value"], 5, 2) Err bitreich.org 70 i- tm["mday"] = substr(content["value"], 8, 2) Err bitreich.org 70 i- tm["hour"] = substr(content["value"], 12, 2) Err bitreich.org 70 i- tm["min"] = substr(content["value"], 15, 2) Err bitreich.org 70 i- tm["sec"] = substr(content["value"], 18, 2) Err bitreich.org 70 i- Err bitreich.org 70 i- return timegm(tm) + tz Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-BEGIN { Err bitreich.org 70 i- split("DTSTART DTEND CATEGORIES LOCATION SUMMARY DESCRIPTION", Err bitreich.org 70 i- FIELDS, " ") Err bitreich.org 70 i- DT["DTSTART"] = DT["DTEND"] = DT["DUE"] = 1 Err bitreich.org 70 i- Err bitreich.org 70 i- # by default: "CATEGORIES" -> "cat", "LOCATION" -> "loc"... Err bitreich.org 70 i- translate["DTSTART"] = "beg" Err bitreich.org 70 i- translate["DTEND"] = "end" Err bitreich.org 70 i- Err bitreich.org 70 i- for (i = 1; i in FIELDS; i++) { Err bitreich.org 70 i- if (!(s = translate[FIELDS[i]])) Err bitreich.org 70 i- s = tolower(substr(FIELDS[i], 1, 3)) Err bitreich.org 70 i- printf("%s%s", (i > 1 ? "\t" : ""), s) Err bitreich.org 70 i- } Err bitreich.org 70 i- printf("\n") Err bitreich.org 70 i- Err bitreich.org 70 i- FS = "[:;]" Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-{ Err bitreich.org 70 i- gsub("\r", "") Err bitreich.org 70 i- gsub("\t", "\\\\t") Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-sub("^ ", "") { Err bitreich.org 70 i- content["value"] = content["value"] $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- delete content Err bitreich.org 70 i- delete param Err bitreich.org 70 i- Err bitreich.org 70 i- if (ical_parse_line($0, content, params) < 0) 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- vcalendar[content["name"]] = 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 i- vevent[content["name"]] = content["value"] Err bitreich.org 70 i- } Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-/^END:VEVENT/ { Err bitreich.org 70 i- print_vevent(vevent, FIELDS) Err bitreich.org 70 i- delete vevent Err bitreich.org 70 i- next 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,62 @@ 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 "log.h" Err bitreich.org 70 i+#include "util.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+print_ical_to_tsv(FILE *fp) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct ical_contentline contentline; Err bitreich.org 70 i+ char *line = NULL; Err bitreich.org 70 i+ size_t sz = 0; Err bitreich.org 70 i+ ssize_t r; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ical_init_contentline(&contentline); Err bitreich.org 70 i+ Err bitreich.org 70 i+ while ((r = ical_read_line(&line, &sz, fp)) > 0) { Err bitreich.org 70 i+ debug("readling line \"%s\"", line); Err bitreich.org 70 i+ if (ical_parse_contentline(&contentline, line) < 0) Err bitreich.org 70 i+ die("parsing line \"%s\"", line); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ return r; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+print_header(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *fields[] = { "", NULL }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ printf("%s\t%s", "beg", "end"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (char **f = fields; *f != NULL; f++) { Err bitreich.org 70 i+ fprintf(stdout, "\t%s", *f); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ fprintf(stdout, "\n"); 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+ print_header(); Err bitreich.org 70 i+ Err bitreich.org 70 i+ log_arg0 = *argv++; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (*argv == NULL) { Err bitreich.org 70 i+ if (print_ical_to_tsv(stdin) < 0) Err bitreich.org 70 i+ die("converting stdin"); 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+ info("converting \"%s\"", *argv); Err bitreich.org 70 i+ if ((fp = fopen(*argv, "r")) == NULL) Err bitreich.org 70 i+ die("opening %s", *argv); Err bitreich.org 70 i+ if (print_ical_to_tsv(fp) < 0) Err bitreich.org 70 i+ die("converting %s", *argv); 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/src/ical.c b/src/ical.c /scm/ics2txt/file/src/ical.c.gph bitreich.org 70 i@@ -0,0 +1,108 @@ 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+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include "util.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+ical_read_line(char **line, size_t *sz, FILE *fp) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ ssize_t r; Err bitreich.org 70 i+ char *tail = NULL; Err bitreich.org 70 i+ size_t tail_sz = 0; Err bitreich.org 70 i+ int c, ret = -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if ((r = getline(line, sz, fp)) <= 0) Err bitreich.org 70 i+ return r; Err bitreich.org 70 i+ strchomp(*line); Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (;;) { Err bitreich.org 70 i+ if ((c = fgetc(fp)) == EOF) { Err bitreich.org 70 i+ ret = ferror(fp) ? -1 : 0; Err bitreich.org 70 i+ goto end; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (c != ' ') Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ if ((r = getline(&tail, &tail_sz, fp)) <= 0) { Err bitreich.org 70 i+ ret = r; Err bitreich.org 70 i+ goto end; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ strchomp(tail); Err bitreich.org 70 i+ if (strappend(line, tail) < 0) Err bitreich.org 70 i+ goto end; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ ret = 1; Err bitreich.org 70 i+end: Err bitreich.org 70 i+ free(tail); Err bitreich.org 70 i+ ungetc(c, fp); Err bitreich.org 70 i+ return ret; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+ical_parse_contentline(struct ical_contentline *contentline, char *line) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *column, *equal, *param, *cp; Err bitreich.org 70 i+ size_t sz; Err bitreich.org 70 i+ Err bitreich.org 70 i+ debug("0"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if ((column = strchr(line, ':')) == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ *column = '\0'; Err bitreich.org 70 i+ Err bitreich.org 70 i+ { Err bitreich.org 70 i+ size_t len; Err bitreich.org 70 i+ Err bitreich.org 70 i+ debug("1.1"); Err bitreich.org 70 i+ len = strlen(column + 1); Err bitreich.org 70 i+ debug("1.2"); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ Err bitreich.org 70 i+ if ((contentline->value = strdup(column + 1)) == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ debug("2"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ cp = strchr(line, ';'); Err bitreich.org 70 i+ cp = (cp == NULL) ? (NULL) : (cp + 1); Err bitreich.org 70 i+ Err bitreich.org 70 i+ debug("3"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ while ((param = strsep(&cp, ";")) != NULL) { Err bitreich.org 70 i+ if ((equal = strchr(param, '=')) == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ *equal = '\0'; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (map_set(&contentline->param, param, equal + 1) < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ debug("4"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ sz = sizeof(contentline->name); Err bitreich.org 70 i+ if (strlcpy(contentline->name, line, sz) >= sz) Err bitreich.org 70 i+ return errno=EMSGSIZE, -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ debug("5"); 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+void Err bitreich.org 70 i+ical_init_contentline(struct ical_contentline *contentline) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ memset(contentline, 0, sizeof(*contentline)); 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+ical_free_contentline(struct ical_contentline *contentline) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ map_free(&contentline->param); Err bitreich.org 70 i+ free(contentline->value); Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/src/ical.h b/src/ical.h /scm/ics2txt/file/src/ical.h.gph bitreich.org 70 i@@ -0,0 +1,25 @@ Err bitreich.org 70 i+#ifndef ICAL_H Err bitreich.org 70 i+#define ICAL_H Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include "map.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+struct ical_vevent { Err bitreich.org 70 i+ time_t beg, end; Err bitreich.org 70 i+ struct map map; Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+struct ical_contentline { Err bitreich.org 70 i+ char name[32], *value; Err bitreich.org 70 i+ struct map param; Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+/** src/ical.c **/ Err bitreich.org 70 i+int ical_read_line(char **line, size_t *sz, FILE *fp); Err bitreich.org 70 i+int ical_parse_contentline(struct ical_contentline *contentline, char *line); Err bitreich.org 70 i+void ical_init_contentline(struct ical_contentline *contentline); Err bitreich.org 70 i+void ical_free_contentline(struct ical_contentline *contentline); Err bitreich.org 70 i+ Err bitreich.org 70 i+#endif Err bitreich.org 70 1diff --git a/src/log.c b/src/log.c /scm/ics2txt/file/src/log.c.gph bitreich.org 70 i@@ -0,0 +1,89 @@ Err bitreich.org 70 i+#include "log.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+/* Err bitreich.org 70 i+ * log.c - log to standard error according to the log level Err bitreich.org 70 i+ * Err bitreich.org 70 i+ * Instead of logging to syslog, delegate logging to a separate Err bitreich.org 70 i+ * tool, such as FreeBSD's daemon(8), POSIX's logger(1). 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 LOG_DEFAULT 3 /* info */ Err bitreich.org 70 i+ Err bitreich.org 70 i+int log_level = -1; Err bitreich.org 70 i+char *log_arg0 = NULL; Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+vlogf(int level, char const *flag, char const *fmt, va_list va) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *env; Err bitreich.org 70 i+ int e = errno; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (log_level < 0) { Err bitreich.org 70 i+ env = getenv("LOG"); Err bitreich.org 70 i+ log_level = (env == NULL ? 0 : atoi(env)); Err bitreich.org 70 i+ log_level = (log_level > 0 ? log_level : LOG_DEFAULT); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (log_level < level) Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (log_arg0 != NULL) Err bitreich.org 70 i+ fprintf(stderr, "%s: ", log_arg0); Err bitreich.org 70 i+ Err bitreich.org 70 i+ fprintf(stderr, "%s: ", flag); Err bitreich.org 70 i+ vfprintf(stderr, fmt, va); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (e != 0) Err bitreich.org 70 i+ fprintf(stderr, ": %s", strerror(e)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ fprintf(stderr, "\n"); Err bitreich.org 70 i+ fflush(stderr); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+die(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+ vlogf(1, "error", fmt, va); Err bitreich.org 70 i+ va_end(va); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+warn(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+ vlogf(2, "warn", fmt, va); Err bitreich.org 70 i+ va_end(va); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+info(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+ vlogf(3, "info", fmt, va); Err bitreich.org 70 i+ va_end(va); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+debug(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+ vlogf(4, "debug", fmt, va); Err bitreich.org 70 i+ va_end(va); Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/src/log.h b/src/log.h /scm/ics2txt/file/src/log.h.gph bitreich.org 70 i@@ -0,0 +1,15 @@ Err bitreich.org 70 i+#ifndef LOG_H Err bitreich.org 70 i+#define LOG_H Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+/** src/log.c **/ Err bitreich.org 70 i+int log_level; Err bitreich.org 70 i+char *log_arg0; Err bitreich.org 70 i+void vlogf(int level, char const *flag, char const *fmt, va_list va); Err bitreich.org 70 i+void die(char const *fmt, ...); Err bitreich.org 70 i+void warn(char const *fmt, ...); Err bitreich.org 70 i+void info(char const *fmt, ...); Err bitreich.org 70 i+void debug(char const *fmt, ...); Err bitreich.org 70 i+ Err bitreich.org 70 i+#endif Err bitreich.org 70 1diff --git a/src/map.c b/src/map.c /scm/ics2txt/file/src/map.c.gph bitreich.org 70 i@@ -0,0 +1,102 @@ Err bitreich.org 70 i+#include "map.h" Err bitreich.org 70 i+ 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+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+map_cmp(void const *v1, void const *v2) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct map_entry const *e1 = v1, *e2 = v2; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return strcmp(e1->key, e2->key); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void * Err bitreich.org 70 i+map_get(struct map *map, char *key) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct map_entry *entry, k = { .key = key }; Err bitreich.org 70 i+ size_t sz; Err bitreich.org 70 i+ Err bitreich.org 70 i+ sz = sizeof(*map->entry); Err bitreich.org 70 i+ if ((entry = bsearch(&k, map->entry, map->len, sz, map_cmp)) == NULL) Err bitreich.org 70 i+ return NULL; Err bitreich.org 70 i+ return entry->value; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+map_set(struct map *map, char *key, void *value) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct map_entry *insert, *e; Err bitreich.org 70 i+ size_t i, sz; Err bitreich.org 70 i+ void *v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ debug("%s: key=%s len=%zd", __func__, key, map->len); Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (i = 0; i < map->len; i++) { Err bitreich.org 70 i+ int cmp = strcmp(key, map->entry[i].key); Err bitreich.org 70 i+ debug("cmp(%s,%s)=%d", key, map->entry[i].key, cmp); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (cmp == 0) { Err bitreich.org 70 i+ map->entry[i].value = value; Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (cmp < 0) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ sz = sizeof(*map->entry); Err bitreich.org 70 i+ if ((v = reallocarray(map->entry, map->len + 1, sz)) == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ map->entry = v; Err bitreich.org 70 i+ map->len++; Err bitreich.org 70 i+ Err bitreich.org 70 i+ insert = map->entry + i; Err bitreich.org 70 i+ e = map->entry + map->len - 1 - 1; Err bitreich.org 70 i+ for (; e >= insert; e--) Err bitreich.org 70 i+ e[1].key = e[0].key; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if ((insert->key = strdup(key)) == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ insert->value = value; 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+map_del(struct map *map, char *key) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (i = 0; i < map->len; i++) { Err bitreich.org 70 i+ int cmp = strcmp(key, map->entry[i].key); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (cmp == 0) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ if (cmp < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (i == map->len) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ map->len--; Err bitreich.org 70 i+ for (; i < map->len; i++) Err bitreich.org 70 i+ map->entry[i] = map->entry[i + 1]; Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+map_free_values(struct map *map) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ for (size_t i = 0; i < map->len; i++) Err bitreich.org 70 i+ free(map->entry[map->len - 1].value); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+map_free(struct map *map) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ for (size_t i = 0; i < map->len; i++) Err bitreich.org 70 i+ free(map->entry[map->len - 1].key); Err bitreich.org 70 i+ free(map->entry); Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/src/map.h b/src/map.h /scm/ics2txt/file/src/map.h.gph bitreich.org 70 i@@ -0,0 +1,23 @@ Err bitreich.org 70 i+#ifndef MAP_H Err bitreich.org 70 i+#define MAP_H Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+struct map_entry { Err bitreich.org 70 i+ char *key; Err bitreich.org 70 i+ void *value; Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+struct map { Err bitreich.org 70 i+ struct map_entry *entry; Err bitreich.org 70 i+ size_t len; Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+/** src/map.c **/ Err bitreich.org 70 i+void * map_get(struct map *map, char *key); Err bitreich.org 70 i+int map_set(struct map *map, char *key, void *value); Err bitreich.org 70 i+int map_del(struct map *map, char *key); Err bitreich.org 70 i+void map_free_values(struct map *map); Err bitreich.org 70 i+void map_free(struct map *map); Err bitreich.org 70 i+ Err bitreich.org 70 i+#endif Err bitreich.org 70 1diff --git a/src/util.c b/src/util.c /scm/ics2txt/file/src/util.c.gph bitreich.org 70 i@@ -0,0 +1,74 @@ 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+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+size_t Err bitreich.org 70 i+strlcpy(char *buf, char const *str, size_t sz) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t len, cpy; Err bitreich.org 70 i+ Err bitreich.org 70 i+ cpy = ((len = strlen(str)) > sz) ? (sz) : (len); Err bitreich.org 70 i+ memcpy(buf, str, cpy + 1); Err bitreich.org 70 i+ buf[sz - 1] = '\0'; Err bitreich.org 70 i+ return len; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+char * Err bitreich.org 70 i+strsep(char **str_p, char const *sep) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *s, *prev; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (*str_p == NULL) Err bitreich.org 70 i+ return NULL; Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (s = prev = *str_p; strchr(sep, *s) == NULL; s++) Err bitreich.org 70 i+ continue; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (*s == '\0') { Err bitreich.org 70 i+ *str_p = NULL; Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ *s = '\0'; Err bitreich.org 70 i+ *str_p = s + 1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ return prev; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+strchomp(char *line) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t len; Err bitreich.org 70 i+ Err bitreich.org 70 i+ len = strlen(line); Err bitreich.org 70 i+ if (len > 0 && line[len - 1] == '\n') Err bitreich.org 70 i+ line[len-- - 1] = '\0'; Err bitreich.org 70 i+ if (len > 0 && line[len - 1] == '\r') Err bitreich.org 70 i+ line[len-- - 1] = '\0'; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+strappend(char **base_p, char const *s) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t base_len, s_len; Err bitreich.org 70 i+ void *v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ base_len = strlen(*base_p); Err bitreich.org 70 i+ s_len = strlen(s); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if ((v = realloc(*base_p, base_len + s_len + 1)) == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ *base_p = v; Err bitreich.org 70 i+ memcpy(*base_p + base_len, s, s_len + 1); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void * Err bitreich.org 70 i+reallocarray(void *buf, size_t len, size_t sz) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (SIZE_MAX / len < sz) Err bitreich.org 70 i+ return errno=ERANGE, NULL; Err bitreich.org 70 i+ return realloc(buf, len * sz); Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/src/util.h b/src/util.h /scm/ics2txt/file/src/util.h.gph bitreich.org 70 i@@ -0,0 +1,13 @@ Err bitreich.org 70 i+#ifndef UTIL_H Err bitreich.org 70 i+#define UTIL_H Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+/** src/util.c **/ Err bitreich.org 70 i+size_t strlcpy(char *buf, char const *str, size_t sz); Err bitreich.org 70 i+char * strsep(char **str_p, char const *sep); Err bitreich.org 70 i+void strchomp(char *line); Err bitreich.org 70 i+int strappend(char **base_p, char const *s); Err bitreich.org 70 i+void * reallocarray(void *buf, size_t len, size_t sz); Err bitreich.org 70 i+ Err bitreich.org 70 i+#endif Err bitreich.org 70 1diff --git a/tsv2tcal b/tsv2tcal /scm/ics2txt/file/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- "date +%z" | getline tz Err bitreich.org 70 i- close("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 .