diff options
author | David Oberhollenzer <david.oberhollenzer@tele2.at> | 2018-04-02 21:26:45 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@tele2.at> | 2018-04-04 00:03:28 +0200 |
commit | 352a9060b6813c41527f0c5da43f0c86aecfde2a (patch) | |
tree | 25103794889d8a3b900632611b70f162b95ca0a6 /lib/src | |
parent | dc5afbc7712b49ec130088d0ccae327db61bd97b (diff) |
Add statefull preprocessing to rdline
Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
Diffstat (limited to 'lib/src')
-rw-r--r-- | lib/src/rdline.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/lib/src/rdline.c b/lib/src/rdline.c index 1b91008..4e72a25 100644 --- a/lib/src/rdline.c +++ b/lib/src/rdline.c @@ -22,11 +22,18 @@ #include "util.h" +enum { + STATE_INITIAL = 0, + STATE_STRING = 1, + STATE_STRING_ESC = 2, + STATE_COMMENT = 3, +}; + char *rdline(int fd) { size_t i = 0, bufsiz = 0, newsz; + int ret, state = STATE_INITIAL; char c, *new, *buffer = NULL; - int ret; for (;;) { switch (read(fd, &c, 1)) { @@ -47,6 +54,39 @@ char *rdline(int fd) goto fail; } + switch (state) { + case STATE_STRING: + if (c == '\\') + state = STATE_STRING_ESC; + if (c == '"') + state = STATE_INITIAL; + break; + case STATE_STRING_ESC: + state = STATE_STRING; + break; + case STATE_COMMENT: + if (c != '\0') + continue; + break; + default: + if (isspace(c)) + c = ' '; + if (c == ' ' && (i == 0 || buffer[i - 1] == ' ')) + continue; + if (c == '#') { + state = STATE_COMMENT; + continue; + } + if (c == '"') + state = STATE_STRING; + break; + } + + if (c == '\0') { + while (i > 0 && buffer[i - 1] == ' ') + --i; + } + if (i == bufsiz) { newsz = bufsiz ? bufsiz * 2 : 16; new = realloc(buffer, newsz); @@ -62,6 +102,11 @@ char *rdline(int fd) if (c == '\0') break; } + + if (state == STATE_STRING || state == STATE_STRING_ESC) { + errno = EILSEQ; + goto fail; + } return buffer; fail: ret = errno; |