diff options
Diffstat (limited to 'src/skaembutils/s6-unquote-filter.c')
-rw-r--r-- | src/skaembutils/s6-unquote-filter.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/skaembutils/s6-unquote-filter.c b/src/skaembutils/s6-unquote-filter.c new file mode 100644 index 0000000..08477ef --- /dev/null +++ b/src/skaembutils/s6-unquote-filter.c @@ -0,0 +1,198 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/buffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> + +#define USAGE "s6-unquote-filter [ -q | -Q | -v | -w ] [ -d delim ]" + +static unsigned int strictness = 1 ; +static char const *delim = "\"" ; +static unsigned int delimlen = 1 ; + +static void fillfmt (char *fmt, char const *s, unsigned int len) +{ + register unsigned int n = len < 39 ? len+1 : 36 ; + byte_copy(fmt, n, s) ; + if (len >= 39) + { + byte_copy(fmt+n, 3, "...") ; + n += 3 ; + } + fmt[n] = 0 ; +} + +static int doit (char const *s, unsigned int len) +{ + if (delimlen) + { + if (!len) + { + switch (strictness) + { + case 1 : + case 2 : + strerr_warnw1x("empty line") ; + break ; + case 3 : + buffer_flush(buffer_1) ; + strerr_dief1x(100, "empty line") ; + default : break ; + } + return 1 ; + } + if (byte_chr(delim, delimlen, *s) >= delimlen) + { + switch (strictness) + { + case 0 : return 0 ; + case 1 : + { + strerr_warnw1x("invalid starting quote character") ; + return 0 ; + } + case 2 : + { + char fmt[40] ; + fillfmt(fmt, s, len) ; + strerr_warnw3x("invalid starting quote character", " in line: ", fmt) ; + return 0 ; + } + case 3 : + { + buffer_flush(buffer_1) ; + strerr_dief1x(100, "invalid starting quote character") ; + } + default : strerr_dief1x(101, "can't happen: unknown strictness") ; + } + } + } + { + unsigned int r, w ; + char d[len] ; + if (!string_unquote_withdelim(d, &w, s + !!delimlen, len - !!delimlen, &r, delim, delimlen)) + { + switch (strictness) + { + case 0 : return 0 ; + case 1 : + { + strerr_warnwu1sys("unquote") ; + return 0 ; + } + case 2 : + { + char fmt[40] ; + fillfmt(fmt, s, len) ; + strerr_warnwu3sys("unquote", " line: ", fmt) ; + return 0 ; + } + case 3 : + { + int e = errno ; + buffer_flush(buffer_1) ; + errno = e ; + strerr_diefu1sys(100, "unquote") ; + } + default : strerr_dief1x(101, "can't happen: unknown strictness") ; + } + } + if (delimlen) + { + if (r+1 == len) + { + switch (strictness) + { + case 0 : return 0 ; + case 1 : + { + strerr_warnwu2x("unquote", ": no ending quote character") ; + return 0 ; + } + case 2 : + { + char fmt[40] ; + fillfmt(fmt, s, len) ; + strerr_warnwu5x("unquote", ": no ending quote character", " in ", "line: ", fmt) ; + return 0 ; + } + case 3 : + { + int e = errno ; + buffer_flush(buffer_1) ; + errno = e ; + strerr_diefu2x(100, "unquote", ": no ending quote character") ; + } + default : strerr_dief1x(101, "can't happen: unknown strictness") ; + } + } + else if ((r+2 < len) && (strictness >= 2)) + { + char fmtnum[UINT_FMT] ; + char fmtden[UINT_FMT] ; + char fmt[40] ; + fillfmt(fmt, s, len) ; + fmtnum[uint_fmt(fmtnum, r+1)] = 0 ; + fmtden[uint_fmt(fmtden, len-1)] = 0 ; + strerr_warnw7x("found ending quote character at position ", fmtnum, "/", fmtden, ", ignoring remainder of ", "line: ", fmt) ; + } + } + if (buffer_put(buffer_1, d, w) < (int)w) + strerr_diefu1sys(111, "write to stdout") ; + } + return 1 ; +} + + +int main (int argc, char const *const *argv) +{ + stralloc src = STRALLOC_ZERO ; + PROG = "s6-unquote-filter" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "qQvwd:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'q': strictness = 0 ; break ; + case 'Q': strictness = 1 ; break ; + case 'v': strictness = 2 ; break ; + case 'w': strictness = 3 ; break ; + case 'd': delim = l.arg ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + delimlen = str_len(delim) ; + for (;;) + { + int r ; + src.len = 0 ; + r = skagetln(buffer_0f1, &src, '\n') ; + if (!r) break ; + if (r < 0) + { + if (errno != EPIPE) strerr_diefu1sys(111, "read from stdin") ; + } + else src.len-- ; + if (!doit(src.s, src.len)) + { + if (buffer_put(buffer_1, src.s, src.len) < (int)src.len) + strerr_diefu1sys(111, "write to stdout") ; + } + if (r > 0) + { + if (buffer_put(buffer_1, "\n", 1) < 1) + strerr_diefu1sys(111, "write to stdout") ; + } + } + return 0 ; +} |