X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fxml.c;h=15c629b1884ca172ac16e719ba3bd9eec5aba8a0;hp=be56b08ce9b899f1a0d63aeeae1d574e69595896;hb=553d2243e2a42783b8bb94addfb752b802c23311;hpb=08bcebf36eb85f5e75b968de8c648e6614cc534b diff --git a/src/shared/xml.c b/src/shared/xml.c index be56b08ce..15c629b18 100644 --- a/src/shared/xml.c +++ b/src/shared/xml.c @@ -25,17 +25,37 @@ #include "xml.h" enum { + STATE_NULL, STATE_TEXT, STATE_TAG, STATE_ATTRIBUTE, }; +static void inc_lines(unsigned *line, const char *s, size_t n) { + const char *p = s; + + if (!line) + return; + + for (;;) { + const char *f; + + f = memchr(p, '\n', n); + if (!f) + return; + + n -= (f - p) + 1; + p = f + 1; + (*line)++; + } +} + /* We don't actually do real XML here. We only read a simplistic * subset, that is a bit less strict that XML and lacks all the more * complex features, like entities, or namespaces. However, we do * support some HTML5-like simplifications */ -int xml_tokenize(const char **p, char **name, void **state) { +int xml_tokenize(const char **p, char **name, void **state, unsigned *line) { const char *c, *e, *b; char *ret; int t; @@ -48,6 +68,12 @@ int xml_tokenize(const char **p, char **name, void **state) { t = PTR_TO_INT(*state); c = *p; + if (t == STATE_NULL) { + if (line) + *line = 1; + t = STATE_TEXT; + } + for (;;) { if (*c == 0) return XML_END; @@ -64,6 +90,8 @@ int xml_tokenize(const char **p, char **name, void **state) { if (!ret) return -ENOMEM; + inc_lines(line, c, e - c); + *name = ret; *p = e; *state = INT_TO_PTR(STATE_TEXT); @@ -80,6 +108,8 @@ int xml_tokenize(const char **p, char **name, void **state) { if (!e) return -EINVAL; + inc_lines(line, b, e + 3 - b); + c = e + 3; continue; } @@ -91,6 +121,8 @@ int xml_tokenize(const char **p, char **name, void **state) { if (!e) return -EINVAL; + inc_lines(line, b, e + 2 - b); + c = e + 2; continue; } @@ -102,6 +134,8 @@ int xml_tokenize(const char **p, char **name, void **state) { if (!e) return -EINVAL; + inc_lines(line, b, e + 1 - b); + c = e + 1; continue; } @@ -134,6 +168,8 @@ int xml_tokenize(const char **p, char **name, void **state) { if (*b == 0) return -EINVAL; + inc_lines(line, c, b - c); + e = b + strcspn(b, WHITESPACE "=/>"); if (e > b) { /* An attribute */ @@ -178,6 +214,8 @@ int xml_tokenize(const char **p, char **name, void **state) { if (!e) return -EINVAL; + inc_lines(line, c, e - c); + ret = strndup(c+1, e - c - 1); if (!ret) return -ENOMEM;