2 * Sherlock Library -- A simple XML parser
4 * (c) 2007 Pavel Charvat <pchar@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
10 #ifndef _SHERLOCK_XML_COMMON_H
11 #define _SHERLOCK_XML_COMMON_H
13 #include "sherlock/xml/xml.h"
14 #include "sherlock/xml/dtd.h"
19 #define TRACE(c, f, p...) do { DBG("XML %u: " f, xml_row(c), ##p); } while(0)
21 #define TRACE(c, f, p...) do {} while(0)
24 /*** Error handling ***/
26 void NONRET xml_throw(struct xml_context *ctx);
27 void xml_warn(struct xml_context *ctx, const char *format, ...);
28 void xml_error(struct xml_context *ctx, const char *format, ...);
29 void xml_fatal(struct xml_context *ctx, const char *format, ...);
31 /*** Charecter categorization ***/
33 #include "obj/sherlock/xml/unicat.h"
39 return 1U << xml_char_tab1[(c & 0xff) + xml_char_tab2[c >> 8]];
40 else if (likely(c < 0x110000))
41 return 1U << xml_char_tab3[c >> 16];
49 return xml_char_tab1[c];
52 /*** Memory management ***/
54 void NONRET xml_fatal_nested(struct xml_context *ctx);
57 xml_inc(struct xml_context *ctx)
59 /* Called after the first character of a block */
65 xml_dec(struct xml_context *ctx)
67 /* Called after the last character of a block */
69 if (unlikely(!ctx->depth--))
70 xml_fatal_nested(ctx);
74 struct xml_stack *next;
75 struct mempool_state state;
80 xml_do_push(struct xml_context *ctx, uns size)
82 /* Saves ctx->stack and ctx->flags state */
83 struct mempool_state state;
84 mp_save(ctx->stack, &state);
85 struct xml_stack *s = mp_alloc(ctx->stack, size);
87 s->flags = ctx->flags;
88 s->next = ctx->stack_list;
94 xml_do_pop(struct xml_context *ctx, struct xml_stack *s)
96 /* Restore ctx->stack and ctx->flags state */
97 ctx->stack_list = s->next;
98 ctx->flags = s->flags;
99 mp_restore(ctx->stack, &s->state);
103 xml_push(struct xml_context *ctx)
106 xml_do_push(ctx, sizeof(struct xml_stack));
110 xml_pop(struct xml_context *ctx)
113 ASSERT(ctx->stack_list);
114 xml_do_pop(ctx, ctx->stack_list);
117 struct xml_dom_stack {
118 struct xml_stack stack;
119 struct mempool_state state;
122 static inline struct xml_node *
123 xml_push_dom(struct xml_context *ctx)
125 /* Create a new DOM node */
126 TRACE(ctx, "push_dom");
127 struct xml_dom_stack *s = xml_do_push(ctx, sizeof(*s));
128 mp_save(ctx->pool, &s->state);
129 struct xml_node *n = mp_alloc(ctx->pool, sizeof(*n));
130 if (n->parent = ctx->node)
131 clist_add_tail(&n->parent->sons, &n->n);
132 return ctx->node = n;
136 xml_pop_dom(struct xml_context *ctx)
138 /* Leave DOM subtree */
139 TRACE(ctx, "pop_dom");
141 struct xml_node *p = ctx->node->parent;
142 struct xml_dom_stack *s = (void *)ctx->stack_list;
143 if (ctx->flags & XML_DOM_FREE)
145 /* See xml_pop_element() for cleanup of attribute hash table */
147 clist_remove(&ctx->node->n);
148 mp_restore(ctx->pool, &s->state);
151 xml_do_pop(ctx, &s->stack);
154 #define XML_HASH_HDR_SIZE ALIGN_TO(sizeof(void *), CPU_STRUCT_ALIGN)
155 #define XML_HASH_GIVE_ALLOC struct HASH_PREFIX(table); \
156 static inline void *HASH_PREFIX(alloc)(struct HASH_PREFIX(table) *t, uns size) \
157 { return mp_alloc(*(void **)((void *)t - XML_HASH_HDR_SIZE), size); } \
158 static inline void HASH_PREFIX(free)(struct HASH_PREFIX(table) *t UNUSED, void *p UNUSED) {}
160 void *xml_hash_new(struct mempool *pool, uns size);
163 xml_start_chars(struct xml_context *ctx)
165 struct fastbuf *fb = &ctx->chars;
166 fb->bstop = fb->bptr = fb->buffer = mp_start_noalign(ctx->pool, 1);
167 fb->bufend = fb->buffer + mp_avail(ctx->pool);
171 xml_end_chars(struct xml_context *ctx, uns *len)
173 struct fastbuf *fb = &ctx->chars;
174 uns l = fb->bufend - fb->buffer;
175 if (fb->bptr == fb->bufend)
176 fb->bptr = mp_expand(ctx->pool) + l;
178 char *c = mp_end(ctx->pool, fb->bptr + 1);
179 fb->bptr = fb->bstop = fb->buffer = fb->bufend = NULL;
184 /*** Reading of document/external entities ***/
186 struct xml_source *xml_push_source(struct xml_context *ctx, uns flags);
187 void xml_push_entity(struct xml_context *ctx, struct xml_dtd_ent *ent);
189 void xml_refill(struct xml_context *ctx);
192 xml_peek_char(struct xml_context *ctx)
194 if (ctx->bptr == ctx->bstop)
200 xml_peek_cat(struct xml_context *ctx)
202 if (ctx->bptr == ctx->bstop)
208 xml_get_char(struct xml_context *ctx)
210 uns c = xml_peek_char(ctx);
216 xml_get_cat(struct xml_context *ctx)
218 uns c = xml_peek_cat(ctx);
224 xml_last_char(struct xml_context *ctx)
226 return ctx->bptr[-2];
230 xml_last_cat(struct xml_context *ctx)
232 return ctx->bptr[-1];
236 xml_skip_char(struct xml_context *ctx)
238 uns c = ctx->bptr[0];
244 xml_unget_char(struct xml_context *ctx)
246 return *(ctx->bptr -= 2);
249 /*** Basic parsing ***/
251 void NONRET xml_fatal_expected(struct xml_context *ctx, uns c);
252 void NONRET xml_fatal_expected_white(struct xml_context *ctx);
253 void NONRET xml_fatal_expected_quot(struct xml_context *ctx);
256 xml_parse_white(struct xml_context *ctx, uns mandatory)
258 /* mandatory=1 -> S ::= (#x20 | #x9 | #xD | #xA)+
259 * mandatory=0 -> S? */
261 while (xml_peek_cat(ctx) & XML_CHAR_WHITE)
266 if (unlikely(mandatory && !cnt))
267 xml_fatal_expected_white(ctx);
272 xml_parse_char(struct xml_context *ctx, uns c)
274 /* Consumes a given Unicode character */
275 if (unlikely(c != xml_get_char(ctx)))
276 xml_fatal_expected(ctx, c);
280 xml_parse_seq(struct xml_context *ctx, const char *seq)
282 /* Consumes a given sequence of ASCII characters */
284 xml_parse_char(ctx, *seq++);
287 void xml_parse_eq(struct xml_context *ctx);
290 xml_parse_quote(struct xml_context *ctx)
293 uns c = xml_get_char(ctx);
294 if (unlikely(c != '\'' && c != '\"'))
295 xml_fatal_expected_quot(ctx);
299 /* Names and nmtokens */
301 char *xml_parse_name(struct xml_context *ctx, struct mempool *pool);
302 void xml_skip_name(struct xml_context *ctx);
303 char *xml_parse_nmtoken(struct xml_context *ctx, struct mempool *pool);
305 /* Simple literals */
307 char *xml_parse_system_literal(struct xml_context *ctx, struct mempool *pool);
308 char *xml_parse_pubid_literal(struct xml_context *ctx, struct mempool *pool);
312 uns xml_parse_char_ref(struct xml_context *ctx);
313 void xml_parse_ref(struct xml_context *ctx);
314 void xml_parse_pe_ref(struct xml_context *ctx);
315 char *xml_parse_attr_value(struct xml_context *ctx, struct xml_dtd_attr *attr);
316 void xml_parse_notation_decl(struct xml_context *ctx);
317 void xml_parse_entity_decl(struct xml_context *ctx);
318 void xml_parse_element_decl(struct xml_context *ctx);
319 void xml_parse_attr_list_decl(struct xml_context *ctx);
320 void xml_push_comment(struct xml_context *ctx);
321 void xml_pop_comment(struct xml_context *ctx);
322 void xml_skip_comment(struct xml_context *ctx);
323 void xml_push_pi(struct xml_context *ctx);
324 void xml_pop_pi(struct xml_context *ctx);
325 void xml_skip_pi(struct xml_context *ctx);