This commit is contained in:
Nishi 2025-12-22 21:33:45 +09:00
commit 45b3706810
Signed by: nishi
GPG key ID: 27EF69B208EB9343
3 changed files with 175 additions and 38 deletions

View file

@ -6,8 +6,22 @@ void recursive(xl_node_t* node, int indent) {
int i;
xl_node_t* n;
for(i = 0; i < indent; i++) printf(" ");
if(node->name != NULL && node->type == XL_NODE_NODE) {
printf("<%s>\n", node->name);
if(node->name != NULL && (node->type == XL_NODE_NODE || node->type == XL_NODE_PROCESS)) {
xl_attribute_t* a;
printf("<%s%s", node->type == XL_NODE_PROCESS ? "?" : "", node->name);
a = node->first_attribute;
while(a != NULL) {
if(a->value == NULL) {
printf(" %s", a->key);
} else {
printf(" %s=\"%s\"", a->key, a->value);
}
a = a->next;
}
printf("%s>\n", node->type == XL_NODE_PROCESS ? "?" : "");
if(node->text != NULL) {
for(i = 0; i < indent + INDENT; i++) printf(" ");
printf("%s\n", node->text);

View file

@ -8,9 +8,10 @@
#define XLDECL extern
typedef struct xl_driver xl_driver_t;
typedef struct xmllib xmllib_t;
typedef struct xl_node xl_node_t;
typedef struct xl_driver xl_driver_t;
typedef struct xmllib xmllib_t;
typedef struct xl_node xl_node_t;
typedef struct xl_attribute xl_attribute_t;
#define XL_SKIPPABLE(x) (((x) == ' ') || ((x) == '\t') || ((x) == '\n') || ((x) == '\r'))
@ -23,14 +24,22 @@ struct xl_driver {
enum XL_NODE_TYPE {
XL_NODE_COMMENT = 0,
XL_NODE_NODE,
XL_NODE_PROCESS,
XL_NODE_DOCTYPE
XL_NODE_PROCESS
};
struct xl_attribute {
char* key;
char* value;
xl_attribute_t* prev;
xl_attribute_t* next;
};
struct xl_node {
int type;
char* name;
char* text;
int type;
char* name;
char* text;
xl_attribute_t* first_attribute;
xl_node_t* root;
xl_node_t* parent;

View file

@ -57,6 +57,83 @@ enum STATES {
#define STATE state[arrlen(state) - 1]
static xl_attribute_t* xl_parse_attribute(const char* str) {
xl_attribute_t* first = NULL;
xl_attribute_t* current = NULL;
char* s = malloc(strlen(str) + 1);
int i;
int st = 0;
int start = -1;
int dq = 0;
strcpy(s, str);
i = 0;
while(1) {
int cp;
int new = xl_unicode_8_to_32(s + i, &cp);
if(st == 0 && XL_SKIPPABLE(cp)) {
} else if(st == 0) {
xl_attribute_t* old = current;
st = 1;
start = i;
current = malloc(sizeof(*current));
current->key = NULL;
current->value = NULL;
current->prev = NULL;
current->next = NULL;
if(old != NULL) {
current->prev = old;
old->next = current;
}
if(first == NULL) first = current;
}
if(st == 1 && (cp == '=' || cp == 0)) {
char* b = malloc(i - start + 1);
memcpy(b, s + start, i - start);
b[i - start] = 0;
current->key = b;
st = 2;
if(cp == '=') {
current->value = malloc(1);
current->value[0] = 0;
}
} else if(st == 2 && ((dq ? 0 : XL_SKIPPABLE(cp)) || cp == 0)) {
st = 0;
} else if(st == 2 && cp == '"') {
dq = dq ? 0 : 1;
} else if(st == 2) {
char* old = current->value;
current->value = malloc(strlen(old) + new + 1);
strcpy(current->value, old);
memcpy(current->value + strlen(old), s + i, new);
current->value[strlen(old) + new] = 0;
free(old);
}
i += new;
if(cp == 0) break;
}
free(s);
return first;
}
int xl_parse(xmllib_t* handle) {
jmp_buf err;
int* state = NULL;
@ -115,9 +192,10 @@ int xl_parse(xmllib_t* handle) {
if(strlen(node) > (1 + 3 + 2) && nest_level > 0) {
n = malloc(sizeof(*n));
n->type = XL_NODE_COMMENT;
n->name = NULL;
n->text = malloc(strlen(node) + 1);
n->type = XL_NODE_COMMENT;
n->name = NULL;
n->text = malloc(strlen(node) + 1);
n->first_attribute = NULL;
strcpy(n->text, node + 3);
n->text[strlen(n->text) - 2] = 0;
@ -138,12 +216,12 @@ int xl_parse(xmllib_t* handle) {
current->text[strlen(current->text) - 2] = 0;
}
} else {
/* doctype or something - we ignore this for now */
/* DOCTYPE or something - ignored for now */
}
} else if(node[0] == '?') {
/* process */
} else {
/* normal tag */
int proc = 0;
if(node[0] == '/') {
/* close tag */
char* str;
@ -164,40 +242,68 @@ int xl_parse(xmllib_t* handle) {
free(current->text);
current->text = NULL;
}
proc = 1;
} else {
int i;
int i;
int set = 0;
char* s = malloc(strlen(node) + 1);
n = malloc(sizeof(*n));
n->type = XL_NODE_NODE;
n->name = malloc(strlen(node) + 1);
n->text = NULL;
if(node[0] == '?' && node[strlen(node) - 1] == '?') {
n->type = XL_NODE_PROCESS;
strcpy(n->name, node);
i = 0;
while(1) {
int icp;
int nb = xl_unicode_8_to_32(n->name + i, &icp);
strcpy(s, node + 1);
s[strlen(s) - 1] = 0;
} else {
n->type = XL_NODE_NODE;
if(icp == 0) break;
strcpy(s, node);
}
if(n->type == XL_NODE_PROCESS && nest_level == 0) {
free(n);
n = NULL;
} else {
n->name = malloc(strlen(s) + 1);
n->text = NULL;
n->first_attribute = NULL;
if(XL_SKIPPABLE(icp)) {
n->name[i] = 0;
break;
strcpy(n->name, s);
i = 0;
while(1) {
int icp;
int nb = xl_unicode_8_to_32(n->name + i, &icp);
if(icp == 0) break;
if(XL_SKIPPABLE(icp)) {
n->name[i] = 0;
set = 1;
} else if(set) {
n->first_attribute = xl_parse_attribute(s + i);
break;
}
i += nb;
}
i += nb;
}
if(n->type == XL_NODE_NODE && node[strlen(node) - 1] != '/') {
/* non self-closing tag */
targ = n;
nest_level++;
if(node[strlen(node) - 1] != '/') {
/* non self-closing tag */
targ = n;
nest_level++;
proc = 1;
}
}
free(s);
}
if(nest_level < 0) ERROR;
if(nest_level == 0) break;
if(proc) {
if(nest_level < 0) ERROR;
if(nest_level == 0) break;
}
}
if(n != NULL) {
@ -292,13 +398,21 @@ int xl_parse(xmllib_t* handle) {
}
void recursive_free(xl_node_t* node) {
xl_node_t* n = node->first_child;
xl_node_t* n = node->first_child;
xl_attribute_t* a = node->first_attribute;
while(n != NULL) {
recursive_free(n);
n = n->next;
}
while(a != NULL) {
free(a->key);
if(a->value != NULL) free(a->value);
a = a->next;
}
if(node->name != NULL) free(node->name);
if(node->text != NULL) free(node->text);
free(node);