@@ -1,5 +1,5 @@
11#include "hexml.h"
2−#include <stdlib.h>
2+#include <malloc.h>
33#include <string.h>
44#include <assert.h>
55#include <ctype.h>
@@ -10,18 +10,18 @@ typedef int bool;
1010/////////////////////////////////////////////////////////////////////
1111// TYPES
1212
13−static inline int end(str s) { return s.start + s.length; }
13+int static inline end(str s) { return s.start + s.length; }
1414
15−static inline str start_length(int32_t start, int32_t length)
15+str static inline start_length(int32_t start, int32_t length)
1616{
17− assert(start >= 0 && length >= 0);
17+ if (start < 0 || length < 0) assert(0);
1818 str res;
1919 res.start = start;
2020 res.length = length;
2121 return res;
2222}
2323
24−static inline str start_end(int32_t start, int32_t end)
24+str static inline start_end(int32_t start, int32_t end)
2525{
2626 return start_length(start, end - start);
2727}
@@ -40,7 +40,7 @@ typedef struct
4040 // have a cursor at the end, which is stack scoped, so children write out, then I do
4141 // when you commit, you copy over from end to front
4242
43− // nodes
43+ // nodes
4444 int size;
4545 int used_front; // front entries, stored for good
4646 int used_back; // back entries, stack based, copied into front
@@ -51,11 +51,11 @@ typedef struct
5151
5252struct document
5353{
54− const char* body; // pointer to initial argument, not owned by us
54+ char* body; // pointer to initial argument, not owned by us
5555
5656 // things only used while parsing
57− const char* cursor; // pointer to where we are in body
58− const char* end; // pointer to one past the last char
57+ char* cursor; // pointer to where we are in body
58+ char* end; // pointer to one past the last char
5959 // if cursor is > end we have gone past the end
6060
6161 char* error_message;
@@ -63,8 +63,8 @@ struct document
6363 attr_buffer attrs;
6464};
6565
66−static inline int doc_length(const document* d) { return (int) (d->end - d->body); }
67−static inline int doc_position(const document* d) { return (int) (d->cursor - d->body); }
66+int static inline doc_length(document* d) { return (int) (d->end - d->body); }
67+int static inline doc_position(document* d) { return (int) (d->cursor - d->body); }
6868
6969
7070/////////////////////////////////////////////////////////////////////
@@ -72,45 +72,49 @@ static inline int doc_position(const document* d) { return (int) (d->cursor - d-
7272
7373typedef struct
7474{
75− const document* d;
75+ document* d;
7676 char* buffer;
7777 int length;
7878 int cursor;
7979} render;
8080
81−static inline void render_char(render* r, char c)
81+void static inline render_char(render* r, char c)
8282{
8383 if (r->cursor < r->length)
8484 r->buffer[r->cursor] = c;
8585 r->cursor++;
8686}
8787
88−static inline void bound(int idx, int mn, int mx)
88+void static inline bound(char* msg, int index, int mn, int mx)
8989{
90− assert(idx >= mn && idx <= mx);
90+ if (index < mn || index > mx)
91+ {
92+ //printf("Bounds checking failed %s, got %i, which should be in %i:%i\n", msg, index, mn, mx);
93+ assert(0);
94+ }
9195}
9296
93−static inline void bound_str(str s, int mn, int mx)
97+void static inline bound_str(char* msg, str s, int mn, int mx)
9498{
95− assert(s.length >= 0);
96− bound(s.start, mn, mx);
97− bound(end(s), mn, mx);
99+ if (s.length < 0) assert(0);
100+ bound(msg, s.start, mn, mx);
101+ bound(msg, end(s), mn, mx);
98102}
99103
100−static void render_str(render* r, str s)
104+void render_str(render* r, str s)
101105{
102− bound_str(s, 0, doc_length(r->d));
106+ bound_str("render_str", s, 0, doc_length(r->d));
103107 for (int i = 0; i < s.length; i++)
104108 render_char(r, r->d->body[s.start + i]);
105109}
106110
107−static void render_tag(render* r, const node* n);
111+void render_tag(render* r, node* n);
108112
109−static void render_content(render* r, const node* n)
113+void render_content(render* r, node* n)
110114{
111− bound_str(n->inner, 0, doc_length(r->d));
112− bound_str(n->nodes, 0, r->d->nodes.used_front);
113− bound_str(n->attrs, 0, r->d->attrs.used);
115+ bound_str("render_conent inner", n->inner, 0, doc_length(r->d));
116+ bound_str("render_conent nodes", n->nodes, 0, r->d->nodes.used_front);
117+ bound_str("render_conent attrs", n->attrs, 0, r->d->attrs.used);
114118
115119 int done = n->inner.start;
116120 for (int i = 0; i < n->nodes.length; i++)
@@ -123,7 +127,7 @@ static void render_content(render* r, const node* n)
123127 render_str(r, start_end(done, end(n->inner)));
124128}
125129
126−static void render_tag(render* r, const node* n)
130+void render_tag(render* r, node* n)
127131{
128132 render_char(r, '<');
129133 render_str(r, n->name);
@@ -145,7 +149,7 @@ static void render_tag(render* r, const node* n)
145149 render_char(r, '>');
146150}
147151
148−int hexml_node_render(const document* d, const node* n, char* buffer, int length)
152+int node_render(document* d, node* n, char* buffer, int length)
149153{
150154 render r;
151155 r.d = d;
@@ -164,10 +168,10 @@ int hexml_node_render(const document* d, const node* n, char* buffer, int length
164168/////////////////////////////////////////////////////////////////////
165169// NOT THE PARSER
166170
167−char* hexml_document_error(const document* d){return d->error_message;}
168−node* hexml_document_node(const document* d){return &d->nodes.nodes[0];}
171+char* document_error(document* d){return d->error_message;}
172+node* document_node(document* d){return &d->nodes.nodes[0];}
169173
170−void hexml_document_free(document* d)
174+void document_free(document* d)
171175{
172176 free(d->error_message);
173177 free(d->nodes.alloc);
@@ -175,20 +179,20 @@ void hexml_document_free(document* d)
175179 free(d);
176180}
177181
178−node* hexml_node_children(const document* d, const node* n, int* res)
182+node* node_children(document* d, node* n, int* res)
179183{
180184 *res = n->nodes.length;
181185 return &d->nodes.nodes[n->nodes.start];
182186}
183187
184−attr* hexml_node_attributes(const document* d, const node* n, int* res)
188+attr* node_attributes(document* d, node* n, int* res)
185189{
186190 *res = n->attrs.length;
187191 return &d->attrs.attrs[n->attrs.start];
188192}
189193
190194
191−attr* hexml_node_attribute(const document* d, const node* n, const char* s, int slen)
195+attr* node_attributeBy(document* d, node* n, char* s, int slen)
192196{
193197 if (slen == -1) slen = (int) strlen(s);
194198 const int limit = end(n->attrs);
@@ -202,7 +206,7 @@ attr* hexml_node_attribute(const document* d, const node* n, const char* s, int
202206}
203207
204208// Search for given strings within a node
205−node* hexml_node_child(const document* d, const node* parent, const node* prev, const char* s, int slen)
209+node* node_childBy(document* d, node* parent, node* prev, char* s, int slen)
206210{
207211 if (slen == -1) slen = (int) strlen(s);
208212 int i = prev == NULL ? parent->nodes.start : (int) (prev + 1 - d->nodes.nodes);
@@ -220,49 +224,49 @@ node* hexml_node_child(const document* d, const node* parent, const node* prev,
220224/////////////////////////////////////////////////////////////////////
221225// PARSE TABLE
222226
223−static const char tag_name1 = 0x1;
224−static const char tag_name = 0x2;
225−static const char tag_space = 0x4;
227+const char tag_name1 = 0x1;
228+const char tag_name = 0x2;
229+const char tag_space = 0x4;
226230
227−static char parse_table[256];
231+char parse_table[256];
228232
229−static void init_parse_table()
233+void init_parse_table()
230234{
231235 static bool done = 0;
232236 if (done) return;
233237 for (int i = 0; i < 256; i++)
234238 {
235239 bool name1 = i == ':' || i == '_' || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z');
236− bool name = name1 || i == '-' || i == '.' || (i >= '0' && i <= '9');
240+ bool name = name1 || i == '-' || (i >= '0' && i <= '9');
237241 bool space = i == ' ' || i == '\t' || i == '\r' || i == '\n';
238242 parse_table[i] = (name1 ? tag_name1 : 0) | (name ? tag_name : 0) | (space ? tag_space : 0);
239243 }
240244 done = 1;
241245}
242246
243−static inline bool is(char c, char tag) { return parse_table[(unsigned char) c] & tag; }
244−static inline bool is_name1(char c) { return is(c, tag_name1); }
245−static inline bool is_name(char c) { return is(c, tag_name); }
246−static inline bool is_space(char c) { return is(c, tag_space); }
247+bool static inline is(char c, char tag) { return parse_table[c] & tag; }
248+bool static inline is_name1(char c) { return is(c, tag_name1); }
249+bool static inline is_name(char c) { return is(c, tag_name); }
250+bool static inline is_space(char c) { return is(c, tag_space); }
247251
248252
249253/////////////////////////////////////////////////////////////////////
250254// PARSER COMBINATORS
251255
252−static inline char peek_at(const document* d, int i) { return d->cursor[i]; }
253−static inline char peek(const document* d) { return peek_at(d, 0); }
254−static inline void skip(document* d, int i) { d->cursor += i; }
255−static inline char get(document* d) { char c = peek(d); skip(d, 1); return c; }
256+char static inline peekAt(document* d, int i) { return d->cursor[i]; }
257+void static inline skip(document* d, int i) { d->cursor += i; }
258+char static inline peek(document* d) { return peekAt(d, 0); }
259+char static inline get(document* d) { char c = peek(d); skip(d, 1); return c; }
256260
257261// Remove whitespace characters from the cursor while they are still whitespace
258−static inline void trim(document* d)
262+void static inline trim(document* d)
259263{
260264 while (is_space(peek(d)))
261265 skip(d, 1);
262266}
263267
264268// Find this character form the cursor onwards, if true adjust the cursor to that char, otherwise leave it at the end
265−static bool find(document* d, char c)
269+bool find(document* d, char c)
266270{
267271 char* x = memchr(d->cursor, c, d->end - d->cursor);
268272 if (x == NULL)
@@ -281,7 +285,7 @@ static bool find(document* d, char c)
281285/////////////////////////////////////////////////////////////////////
282286// PARSING CODE
283287
284−static inline void node_alloc(node_buffer* b, int ask)
288+void static inline node_alloc(node_buffer* b, int ask)
285289{
286290 int space = b->size - b->used_back - b->used_front;
287291 if (space >= ask) return;
@@ -296,7 +300,7 @@ static inline void node_alloc(node_buffer* b, int ask)
296300 b->alloc = buf2;
297301}
298302
299−static inline void attr_alloc(attr_buffer* b, int ask)
303+void static inline attr_alloc(attr_buffer* b, int ask)
300304{
301305 int space = b->size - b->used;
302306 if (space >= ask) return;
@@ -310,7 +314,7 @@ static inline void attr_alloc(attr_buffer* b, int ask)
310314 b->alloc = buf2;
311315}
312316
313−static void set_error(document* d, const char* msg)
317+void set_error(document* d, char* msg)
314318{
315319 if (d->error_message != NULL) return; // keep the first error message
316320 d->error_message = malloc(strlen(msg)+1);
@@ -320,7 +324,7 @@ static void set_error(document* d, const char* msg)
320324
321325// you now expect a name, perhaps preceeded by whitespace
322326// the name may be empty
323−static inline str parse_name(document* d)
327+str static inline parse_name(document* d)
324328{
325329 int start = doc_position(d);
326330 if (!is_name1(peek(d)))
@@ -331,15 +335,14 @@ static inline str parse_name(document* d)
331335 return start_end(start, doc_position(d));
332336}
333337
334−static inline str parse_attrval(document* d)
338+str static inline parse_attrval(document* d)
335339{
336340 trim(d);
337− if (peek(d) != '=')
341+ if (get(d) != '=')
338342 {
339343 set_error(d, "Expected = in attribute, but missing");
340344 return start_length(0, 0);
341345 }
342− skip(d, 1);
343346 trim(d);
344347 char c = peek(d);
345348 if (c == '\"' || c == '\'')
@@ -365,10 +368,10 @@ static inline str parse_attrval(document* d)
365368
366369// seen a tag name, now looking for attributes terminated by >
367370// puts the attributes it finds in the attribute buffer
368−static inline str parse_attributes(document* d)
371+str static inline parse_attributes(document* d)
369372{
370373 int start = d->attrs.used;
371− while (d->error_message == NULL)
374+ for (int i = 0; ; i++)
372375 {
373376 trim(d);
374377 str name = parse_name(d);
@@ -381,11 +384,11 @@ static inline str parse_attributes(document* d)
381384 return start_end(start, d->attrs.used);
382385}
383386
384−static str parse_content(document* d);
387+str parse_content(document* d);
385388
386389
387390// Add a new entry into tag, am at a '<'
388−static inline void parse_tag(document* d)
391+void static inline parse_tag(document* d)
389392{
390393 node_alloc(&d->nodes, 1);
391394 d->nodes.used_back++;
@@ -396,18 +399,12 @@ static inline void parse_tag(document* d)
396399 assert(c == '<');
397400 if (peek(d) == '?') skip(d, 1);
398401 me->name = parse_name(d);
399− if (me->name.length == 0)
400− {
401− set_error(d, "Missing tag name");
402− return;
403− }
404402 me->attrs = parse_attributes(d);
405− if (d->error_message != NULL) return;
406403
407− c = peek(d);
408− if ((c == '/' || c == '?') && peek_at(d, 1) == '>')
404+ c = get(d);
405+ if ((c == '/' || c == '?') && peek(d) == '>')
409406 {
410− skip(d, 2);
407+ skip(d, 1);
411408 me->nodes = start_length(0, 0);
412409 me->outer.length = start_end(me->outer.start, doc_position(d)).length;
413410 me->inner = start_length(doc_position(d), 0);
@@ -418,8 +415,6 @@ static inline void parse_tag(document* d)
418415 set_error(d, "Gunk at the end of the tag");
419416 return;
420417 }
421− else
422− skip(d, 1);
423418 me->inner.start = doc_position(d);
424419 str content = parse_content(d);
425420
@@ -429,7 +424,7 @@ static inline void parse_tag(document* d)
429424 me->inner.length = start_end(me->inner.start, doc_position(d)).length;
430425
431426 if (d->error_message != NULL) return;
432− if (peek(d) == '<' && peek_at(d, 1) == '/')
427+ if (peek(d) == '<' && peekAt(d, 1) == '/')
433428 {
434429 skip(d, 2);
435430 if (d->end - d->cursor >= me->name.length &&
@@ -451,7 +446,7 @@ static inline void parse_tag(document* d)
451446
452447// Parser until </, return the index of your node children
453448// Not inline as it is recursive
454−static str parse_content(document* d)
449+str parse_content(document* d)
455450{
456451 int before = d->nodes.used_back;
457452 while (d->error_message == NULL)
@@ -461,22 +456,22 @@ static str parse_content(document* d)
461456 {
462457 break;
463458 }
464− else if (peek_at(d, 1) == '/')
459+ else if (peekAt(d, 1) == '/')
465460 {
466461 // have found a </
467462 break;
468463 }
469− else if (peek_at(d, 1) == '!' && peek_at(d, 2) == '-' && peek_at(d, 3) == '-')
464+ else if (peekAt(d, 1) == '!' && peekAt(d, 2) == '-' && peekAt(d, 3) == '-')
470465 {
471466 skip(d, 3);
472467 // you can't reuse the two '-' characters for the closing as well
473− if (peek_at(d, 0) == '\0' || peek_at(d, 1) == '\0')
468+ if (peekAt(d, 0) == '\0' || peekAt(d, 1) == '\0')
474469 {
475470 set_error(d, "Didn't get a closing comment");
476471 return start_end(0, 0);
477472 }
478473 skip(d, 2);
479− for (;;)
474+ while (1)
480475 {
481476 if (!find(d, '>'))
482477 {
@@ -484,7 +479,7 @@ static str parse_content(document* d)
484479 return start_end(0, 0);
485480 }
486481 skip(d, 1);
487− if (peek_at(d, -3) == '-' && peek_at(d, -2) == '-')
482+ if (peekAt(d, -3) == '-' && peekAt(d, -2))
488483 break;
489484 }
490485 }
@@ -512,7 +507,7 @@ typedef struct
512507 node nodes[500];
513508} buffer;
514509
515−document* hexml_document_parse(const char* s, int slen)
510+document* document_parse(char* s, int slen)
516511{
517512 if (slen == -1) slen = (int) strlen(s);
518513 assert(s[slen] == 0);
@@ -539,13 +534,15 @@ document* hexml_document_parse(const char* s, int slen)
539534 d->nodes.nodes[0].outer = start_length(0, slen);
540535 d->nodes.nodes[0].inner = start_length(0, slen);
541536 d->nodes.nodes[0].attrs = start_length(0, 0);
542−
537+
543538 // Introduce an intermediate result, otherwise behaviour is undefined
544539 // because there is no guaranteed ordering between LHS and RHS evaluation
545540 str content = parse_content(d);
546541 d->nodes.nodes[0].nodes = content;
547542
548− if (d->cursor < d->end)
543+ if (d->cursor < d->end && d->error_message == NULL)
544+ {
549545 set_error(d, "Trailing junk at the end of the document");
546+ }
550547 return d;
551548}