version 1.5, 2019/03/28 12:21:10 |
version 1.6, 2019/03/28 15:05:40 |
|
|
*/ |
*/ |
#include <assert.h> |
#include <assert.h> |
#include <ctype.h> |
#include <ctype.h> |
|
#include <stdarg.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
Line 187 static const struct element elements[] = { |
|
Line 188 static const struct element elements[] = { |
|
{ NULL, NODE_IGNORE } |
{ NULL, NODE_IGNORE } |
}; |
}; |
|
|
|
static void |
|
error_msg(struct parse *p, const char *fmt, ...) |
|
{ |
|
va_list ap; |
|
|
|
fprintf(stderr, "%s:%d:%d: ", p->fname, p->line, p->col); |
|
va_start(ap, fmt); |
|
vfprintf(stderr, fmt, ap); |
|
va_end(ap); |
|
fputc('\n', stderr); |
|
p->tree->flags |= TREE_FAIL; |
|
} |
|
|
|
static void |
|
warn_msg(struct parse *p, const char *fmt, ...) |
|
{ |
|
va_list ap; |
|
|
|
if (p->warn == 0) |
|
return; |
|
|
|
fprintf(stderr, "%s:%d:%d: warning: ", p->fname, p->line, p->col); |
|
va_start(ap, fmt); |
|
vfprintf(stderr, fmt, ap); |
|
va_end(ap); |
|
fputc('\n', stderr); |
|
} |
|
|
/* |
/* |
* Process a string of characters. |
* Process a string of characters. |
* If a text node is already open, append to it. |
* If a text node is already open, append to it. |
Line 201 xml_char(struct parse *ps, const char *p, int sz) |
|
Line 230 xml_char(struct parse *ps, const char *p, int sz) |
|
return; |
return; |
|
|
if (ps->cur == NULL) { |
if (ps->cur == NULL) { |
fprintf(stderr, "%s:%d:%d: discarding text before docum" |
error_msg(ps, "discarding text before document: %.*s", sz, p); |
"ent: %.*s\n", ps->fname, ps->line, ps->col, sz, p); |
|
ps->tree->flags |= TREE_FAIL; |
|
return; |
return; |
} |
} |
|
|
Line 221 xml_char(struct parse *ps, const char *p, int sz) |
|
Line 248 xml_char(struct parse *ps, const char *p, int sz) |
|
} |
} |
|
|
if (ps->tree->flags & TREE_CLOSED && |
if (ps->tree->flags & TREE_CLOSED && |
ps->cur->parent == ps->tree->root && ps->warn) |
ps->cur->parent == ps->tree->root) |
fprintf(stderr, "%s:%d:%d: warning: " |
warn_msg(ps, "text after end of document: %.*s", sz, p); |
"text after end of document: %.*s\n", |
|
ps->fname, ps->line, ps->col, sz, p); |
|
|
|
/* Append to the current text node. */ |
/* Append to the current text node. */ |
|
|
Line 280 xml_elem_start(struct parse *ps, const char *name) |
|
Line 305 xml_elem_start(struct parse *ps, const char *name) |
|
if (strcmp(elem->name, name) == 0) |
if (strcmp(elem->name, name) == 0) |
break; |
break; |
|
|
if (elem->name == NULL) { |
if (elem->name == NULL) |
fprintf(stderr, "%s:%d:%d: unknown element <%s>\n", |
error_msg(ps, "unknown element <%s>", name); |
ps->fname, ps->line, ps->col, name); |
|
ps->tree->flags |= TREE_FAIL; |
|
} |
|
ps->ncur = elem->node; |
ps->ncur = elem->node; |
|
|
switch (ps->ncur) { |
switch (ps->ncur) { |
case NODE_DELETE_WARN: |
case NODE_DELETE_WARN: |
if (ps->warn) |
warn_msg(ps, "skipping element <%s>", name); |
fprintf(stderr, "%s:%d:%d: warning: " |
|
"skipping element <%s>\n", |
|
ps->fname, ps->line, ps->col, name); |
|
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
case NODE_DELETE: |
case NODE_DELETE: |
ps->del = 1; |
ps->del = 1; |
Line 306 xml_elem_start(struct parse *ps, const char *name) |
|
Line 326 xml_elem_start(struct parse *ps, const char *name) |
|
break; |
break; |
} |
} |
|
|
if (ps->tree->flags & TREE_CLOSED && |
if (ps->tree->flags & TREE_CLOSED && ps->cur->parent == NULL) |
ps->cur->parent == NULL && ps->warn) |
warn_msg(ps, "element after end of document: <%s>", name); |
fprintf(stderr, "%s:%d:%d: warning: " |
|
"element after end of document: %s\n", |
|
ps->fname, ps->line, ps->col, name); |
|
|
|
if ((dat = calloc(1, sizeof(*dat))) == NULL) { |
if ((dat = calloc(1, sizeof(*dat))) == NULL) { |
perror(NULL); |
perror(NULL); |
Line 338 xml_attrkey(struct parse *ps, const char *name) |
|
Line 355 xml_attrkey(struct parse *ps, const char *name) |
|
if (ps->del > 0 || *name == '\0') |
if (ps->del > 0 || *name == '\0') |
return; |
return; |
if ((key = attrkey_parse(name)) == ATTRKEY__MAX) { |
if ((key = attrkey_parse(name)) == ATTRKEY__MAX) { |
if (ps->warn) |
|
fprintf(stderr, "%s:%d:%d: warning: " |
|
"unknown attribute \"%s\"\n", |
|
ps->fname, ps->line, ps->col, name); |
|
ps->attr = 0; |
ps->attr = 0; |
return; |
return; |
} |
} |
Line 415 xml_elem_end(struct parse *ps, const char *name) |
|
Line 428 xml_elem_end(struct parse *ps, const char *name) |
|
break; |
break; |
default: |
default: |
if (ps->cur == NULL || node != ps->cur->node) { |
if (ps->cur == NULL || node != ps->cur->node) { |
if (ps->warn) |
warn_msg(ps, "element not open: </%s>", name); |
fprintf(stderr, "%s:%d:%d: warning: " |
|
"element not open: </%s>\n", |
|
ps->fname, ps->line, ps->col, name); |
|
break; |
break; |
} |
} |
|
|
Line 677 parse_file(struct parse *p, int fd, const char *fname) |
|
Line 687 parse_file(struct parse *p, int fd, const char *fname) |
|
pnode_trim(p->cur); |
pnode_trim(p->cur); |
p->cur = p->cur->parent; |
p->cur = p->cur->parent; |
} |
} |
if ((p->tree->flags & TREE_CLOSED) == 0 && p->warn) |
if ((p->tree->flags & TREE_CLOSED) == 0) |
fprintf(stderr, "%s:%d:%d: warning: document not closed\n", |
warn_msg(p, "document not closed"); |
p->fname, p->line, p->col); |
|
return p->tree; |
return p->tree; |
} |
} |