2 * UCW Library -- A simple XML parser
4 * (c) 2007--2008 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 _UCW_XML_INTERNALS_H
11 #define _UCW_XML_INTERNALS_H
16 #ifdef CONFIG_UCW_CLEAN_ABI
17 #define xml_attrs_table_cleanup ucw_xml_attrs_table_cleanup
18 #define xml_attrs_table_init ucw_xml_attrs_table_init
19 #define xml_fatal_expected ucw_xml_fatal_expected
20 #define xml_fatal_expected_quot ucw_xml_fatal_expected_quot
21 #define xml_fatal_expected_white ucw_xml_fatal_expected_white
22 #define xml_fatal_nested ucw_xml_fatal_nested
23 #define xml_hash_new ucw_xml_hash_new
24 #define xml_parse_attr_list_decl ucw_xml_parse_attr_list_decl
25 #define xml_parse_attr_value ucw_xml_parse_attr_value
26 #define xml_parse_char_ref ucw_xml_parse_char_ref
27 #define xml_parse_element_decl ucw_xml_parse_element_decl
28 #define xml_parse_entity_decl ucw_xml_parse_entity_decl
29 #define xml_parse_eq ucw_xml_parse_eq
30 #define xml_parse_name ucw_xml_parse_name
31 #define xml_parse_nmtoken ucw_xml_parse_nmtoken
32 #define xml_parse_notation_decl ucw_xml_parse_notation_decl
33 #define xml_parse_pe_ref ucw_xml_parse_pe_ref
34 #define xml_parse_pubid_literal ucw_xml_parse_pubid_literal
35 #define xml_parse_system_literal ucw_xml_parse_system_literal
36 #define xml_pop_comment ucw_xml_pop_comment
37 #define xml_pop_pi ucw_xml_pop_pi
38 #define xml_push_comment ucw_xml_push_comment
39 #define xml_push_entity ucw_xml_push_entity
40 #define xml_push_pi ucw_xml_push_pi
41 #define xml_push_source ucw_xml_push_source
42 #define xml_refill ucw_xml_refill
43 #define xml_skip_comment ucw_xml_skip_comment
44 #define xml_skip_internal_subset ucw_xml_skip_internal_subset
45 #define xml_skip_name ucw_xml_skip_name
46 #define xml_skip_pi ucw_xml_skip_pi
47 #define xml_sources_cleanup ucw_xml_sources_cleanup
48 #define xml_spout_chars ucw_xml_spout_chars
49 #define xml_throw ucw_xml_throw
50 #define xml_validate_attr ucw_xml_validate_attr
56 #define TRACE(c, f, p...) do { DBG("XML %u: " f, xml_row(c), ##p); } while(0)
58 #define TRACE(c, f, p...) do {} while(0)
61 /*** Error handling ***/
63 void NONRET xml_throw(struct xml_context *ctx);
65 /*** Memory management ***/
68 struct xml_stack *next;
69 struct mempool_state state;
73 static inline void *xml_do_push(struct xml_context *ctx, uint size)
75 /* Saves ctx->stack and ctx->flags state */
76 struct mempool_state state;
77 mp_save(ctx->stack, &state);
78 struct xml_stack *s = mp_alloc(ctx->stack, size);
80 s->flags = ctx->flags;
81 s->next = ctx->stack_list;
86 static inline void xml_do_pop(struct xml_context *ctx, struct xml_stack *s)
88 /* Restore ctx->stack and ctx->flags state */
89 ctx->stack_list = s->next;
90 ctx->flags = s->flags;
91 mp_restore(ctx->stack, &s->state);
94 static inline void xml_push(struct xml_context *ctx)
97 xml_do_push(ctx, sizeof(struct xml_stack));
100 static inline void xml_pop(struct xml_context *ctx)
103 ASSERT(ctx->stack_list);
104 xml_do_pop(ctx, ctx->stack_list);
107 struct xml_dom_stack {
108 struct xml_stack stack;
109 struct mempool_state state;
112 static inline struct xml_node *xml_push_dom(struct xml_context *ctx, struct mempool_state *state)
114 /* Create a new DOM node */
115 TRACE(ctx, "push_dom");
116 struct xml_dom_stack *s = xml_do_push(ctx, sizeof(*s));
120 mp_save(ctx->pool, &s->state);
121 struct xml_node *n = mp_alloc(ctx->pool, sizeof(*n));
123 if (n->parent = ctx->node)
124 clist_add_tail(&n->parent->sons, &n->n);
125 return ctx->node = n;
128 static inline void xml_pop_dom(struct xml_context *ctx, uint free)
130 /* Leave DOM subtree */
131 TRACE(ctx, "pop_dom");
133 struct xml_node *p = ctx->node->parent;
134 struct xml_dom_stack *s = (void *)ctx->stack_list;
137 /* See xml_pop_element() for cleanup of attribute hash table */
139 clist_remove(&ctx->node->n);
140 mp_restore(ctx->pool, &s->state);
143 xml_do_pop(ctx, &s->stack);
146 #define XML_HASH_HDR_SIZE ALIGN_TO(sizeof(void *), CPU_STRUCT_ALIGN)
147 #define XML_HASH_GIVE_ALLOC struct HASH_PREFIX(table); \
148 static inline void *HASH_PREFIX(alloc)(struct HASH_PREFIX(table) *t, uint size) \
149 { return mp_alloc(*(void **)((void *)t - XML_HASH_HDR_SIZE), size); } \
150 static inline void HASH_PREFIX(free)(struct HASH_PREFIX(table) *t UNUSED, void *p UNUSED) {}
152 void *xml_hash_new(struct mempool *pool, uint size);
154 void xml_spout_chars(struct fastbuf *fb);
156 /*** Reading of document/external entities ***/
158 void NONRET xml_fatal_nested(struct xml_context *ctx);
160 static inline void xml_inc(struct xml_context *ctx)
162 /* Called after the first character of a block */
167 static inline void xml_dec(struct xml_context *ctx)
169 /* Called after the last character of a block */
171 if (unlikely(!ctx->depth--))
172 xml_fatal_nested(ctx);
175 #include "obj/xml/unicat.h"
177 static inline uint xml_char_cat(uint c)
180 return 1U << ucw_xml_char_tab1[(c & 0xff) + ucw_xml_char_tab2[c >> 8]];
181 else if (likely(c < 0x110000))
182 return 1U << ucw_xml_char_tab3[c >> 16];
187 static inline uint xml_ascii_cat(uint c)
189 return ucw_xml_char_tab1[c];
192 struct xml_source *xml_push_source(struct xml_context *ctx);
193 void xml_push_entity(struct xml_context *ctx, struct xml_dtd_entity *ent);
195 void xml_refill(struct xml_context *ctx);
197 static inline uint xml_peek_char(struct xml_context *ctx)
199 if (ctx->bptr == ctx->bstop)
204 static inline uint xml_peek_cat(struct xml_context *ctx)
206 if (ctx->bptr == ctx->bstop)
211 static inline uint xml_get_char(struct xml_context *ctx)
213 uint c = xml_peek_char(ctx);
218 static inline uint xml_get_cat(struct xml_context *ctx)
220 uint c = xml_peek_cat(ctx);
225 static inline uint xml_last_char(struct xml_context *ctx)
227 return ctx->bptr[-2];
230 static inline uint xml_last_cat(struct xml_context *ctx)
232 return ctx->bptr[-1];
235 static inline uint xml_skip_char(struct xml_context *ctx)
237 uint c = ctx->bptr[0];
242 static inline uint xml_unget_char(struct xml_context *ctx)
244 return *(ctx->bptr -= 2);
247 void xml_sources_cleanup(struct xml_context *ctx);
251 void NONRET xml_fatal_expected(struct xml_context *ctx, uint c);
252 void NONRET xml_fatal_expected_white(struct xml_context *ctx);
253 void NONRET xml_fatal_expected_quot(struct xml_context *ctx);
255 static inline uint xml_parse_white(struct xml_context *ctx, uint mandatory)
257 /* mandatory=1 -> S ::= (#x20 | #x9 | #xD | #xA)+
258 * mandatory=0 -> S? */
260 while (xml_peek_cat(ctx) & XML_CHAR_WHITE)
265 if (unlikely(mandatory && !cnt))
266 xml_fatal_expected_white(ctx);
270 static inline void xml_parse_char(struct xml_context *ctx, uint c)
272 /* Consumes a given Unicode character */
273 if (unlikely(c != xml_get_char(ctx)))
274 xml_fatal_expected(ctx, c);
277 static inline void xml_parse_seq(struct xml_context *ctx, const char *seq)
279 /* Consumes a given sequence of ASCII characters */
281 xml_parse_char(ctx, *seq++);
284 void xml_parse_eq(struct xml_context *ctx);
286 static inline uint xml_parse_quote(struct xml_context *ctx)
289 uint c = xml_get_char(ctx);
290 if (unlikely(c != '\'' && c != '\"'))
291 xml_fatal_expected_quot(ctx);
295 char *xml_parse_name(struct xml_context *ctx, struct mempool *pool);
296 void xml_skip_name(struct xml_context *ctx);
297 char *xml_parse_nmtoken(struct xml_context *ctx, struct mempool *pool);
299 char *xml_parse_system_literal(struct xml_context *ctx, struct mempool *pool);
300 char *xml_parse_pubid_literal(struct xml_context *ctx, struct mempool *pool);
302 uint xml_parse_char_ref(struct xml_context *ctx);
303 void xml_parse_pe_ref(struct xml_context *ctx);
305 char *xml_parse_attr_value(struct xml_context *ctx, struct xml_dtd_attr *attr);
307 void xml_skip_internal_subset(struct xml_context *ctx);
308 void xml_parse_notation_decl(struct xml_context *ctx);
309 void xml_parse_entity_decl(struct xml_context *ctx);
310 void xml_parse_element_decl(struct xml_context *ctx);
311 void xml_parse_attr_list_decl(struct xml_context *ctx);
313 void xml_push_comment(struct xml_context *ctx);
314 void xml_pop_comment(struct xml_context *ctx);
315 void xml_skip_comment(struct xml_context *ctx);
317 void xml_push_pi(struct xml_context *ctx);
318 void xml_pop_pi(struct xml_context *ctx);
319 void xml_skip_pi(struct xml_context *ctx);
321 void xml_attrs_table_init(struct xml_context *ctx);
322 void xml_attrs_table_cleanup(struct xml_context *ctx);
324 void xml_validate_attr(struct xml_context *ctx, struct xml_dtd_attr *dtd, char *value);