mirror of
https://github.com/pygos/init.git
synced 2024-11-22 03:09:46 +01:00
Add statefull preprocessing to rdline
Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
This commit is contained in:
parent
dc5afbc771
commit
352a9060b6
2 changed files with 58 additions and 1 deletions
|
@ -43,6 +43,18 @@ typedef struct {
|
|||
cleared if end-of-file is reached.
|
||||
|
||||
The line must be deallocated with free().
|
||||
|
||||
The following transformations are applied:
|
||||
- Space characters are replaced with regular white space characters.
|
||||
- Sequences of space characters are truncated to a single space.
|
||||
- A '#' sign is interpreted as the start of a comment and removed,
|
||||
together with everything that follows.
|
||||
- Padding spaces are removed from the line.
|
||||
- If a '"' is encounterd, the above rules are disabled, until a
|
||||
after the matching '"' is read. A '"' can be escaped by preceeding
|
||||
it with a backslash.
|
||||
- If a second, coresponding '"' is not found, processing fails with
|
||||
errno set to EILSEQ.
|
||||
*/
|
||||
char *rdline(int fd);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue