mirror of
https://github.com/pygos/init.git
synced 2024-11-22 11:19:45 +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.
|
cleared if end-of-file is reached.
|
||||||
|
|
||||||
The line must be deallocated with free().
|
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);
|
char *rdline(int fd);
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,18 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STATE_INITIAL = 0,
|
||||||
|
STATE_STRING = 1,
|
||||||
|
STATE_STRING_ESC = 2,
|
||||||
|
STATE_COMMENT = 3,
|
||||||
|
};
|
||||||
|
|
||||||
char *rdline(int fd)
|
char *rdline(int fd)
|
||||||
{
|
{
|
||||||
size_t i = 0, bufsiz = 0, newsz;
|
size_t i = 0, bufsiz = 0, newsz;
|
||||||
|
int ret, state = STATE_INITIAL;
|
||||||
char c, *new, *buffer = NULL;
|
char c, *new, *buffer = NULL;
|
||||||
int ret;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (read(fd, &c, 1)) {
|
switch (read(fd, &c, 1)) {
|
||||||
|
@ -47,6 +54,39 @@ char *rdline(int fd)
|
||||||
goto fail;
|
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) {
|
if (i == bufsiz) {
|
||||||
newsz = bufsiz ? bufsiz * 2 : 16;
|
newsz = bufsiz ? bufsiz * 2 : 16;
|
||||||
new = realloc(buffer, newsz);
|
new = realloc(buffer, newsz);
|
||||||
|
@ -62,6 +102,11 @@ char *rdline(int fd)
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state == STATE_STRING || state == STATE_STRING_ESC) {
|
||||||
|
errno = EILSEQ;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
fail:
|
fail:
|
||||||
ret = errno;
|
ret = errno;
|
||||||
|
|
Loading…
Reference in a new issue