summaryrefslogtreecommitdiff
path: root/lib/src
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@tele2.at>2018-04-02 21:26:45 +0200
committerDavid Oberhollenzer <david.oberhollenzer@tele2.at>2018-04-04 00:03:28 +0200
commit352a9060b6813c41527f0c5da43f0c86aecfde2a (patch)
tree25103794889d8a3b900632611b70f162b95ca0a6 /lib/src
parentdc5afbc7712b49ec130088d0ccae327db61bd97b (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.c47
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;