/* * UCW Library -- A simple XML parser * * (c) 2007--2008 Pavel Charvat * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. */ #ifndef _UCW_XML_INTERNALS_H #define _UCW_XML_INTERNALS_H #include #include #ifdef CONFIG_UCW_CLEAN_ABI #define xml_do_pop ucw_xml_do_pop #define xml_do_push ucw_xml_do_push #define xml_fatal_expected ucw_xml_fatal_expected #define xml_fatal_expected_quot ucw_xml_fatal_expected_quot #define xml_fatal_expected_white ucw_xml_fatal_expected_white #define xml_fatal_nested ucw_xml_fatal_nested #define xml_hash_new ucw_xml_hash_new #define xml_ns_cleanup ucw_xml_ns_cleanup #define xml_ns_pop_element ucw_xml_ns_pop_element #define xml_ns_push_element ucw_xml_ns_push_element #define xml_ns_reset ucw_xml_ns_reset #define xml_parse_attr_list_decl ucw_xml_parse_attr_list_decl #define xml_parse_attr_value ucw_xml_parse_attr_value #define xml_parse_char_ref ucw_xml_parse_char_ref #define xml_parse_element_decl ucw_xml_parse_element_decl #define xml_parse_entity_decl ucw_xml_parse_entity_decl #define xml_parse_eq ucw_xml_parse_eq #define xml_parse_name ucw_xml_parse_name #define xml_parse_nmtoken ucw_xml_parse_nmtoken #define xml_parse_notation_decl ucw_xml_parse_notation_decl #define xml_parse_pe_ref ucw_xml_parse_pe_ref #define xml_parse_pubid_literal ucw_xml_parse_pubid_literal #define xml_parse_system_literal ucw_xml_parse_system_literal #define xml_parse_white ucw_xml_parse_white #define xml_pop_comment ucw_xml_pop_comment #define xml_pop_dom ucw_xml_pop_dom #define xml_pop_pi ucw_xml_pop_pi #define xml_push_comment ucw_xml_push_comment #define xml_push_dom ucw_xml_push_dom #define xml_push_entity ucw_xml_push_entity #define xml_push_pi ucw_xml_push_pi #define xml_push_source ucw_xml_push_source #define xml_refill ucw_xml_refill #define xml_skip_comment ucw_xml_skip_comment #define xml_skip_internal_subset ucw_xml_skip_internal_subset #define xml_skip_name ucw_xml_skip_name #define xml_skip_pi ucw_xml_skip_pi #define xml_sources_cleanup ucw_xml_sources_cleanup #define xml_spout_chars ucw_xml_spout_chars #define xml_throw ucw_xml_throw #define xml_validate_attr ucw_xml_validate_attr #endif /*** Debugging ***/ #ifdef LOCAL_DEBUG #define TRACE(c, f, p...) do { DBG("XML %u: " f, xml_row(c), ##p); } while(0) #else #define TRACE(c, f, p...) do {} while(0) #endif /*** Error handling ***/ void NONRET xml_throw(struct xml_context *ctx); /*** Memory management ***/ struct xml_stack { struct xml_stack *next; struct mempool_state state; uint flags; }; void *xml_do_push(struct xml_context *ctx, uint size); void xml_do_pop(struct xml_context *ctx, struct xml_stack *s); static inline void xml_push(struct xml_context *ctx) { TRACE(ctx, "push"); xml_do_push(ctx, sizeof(struct xml_stack)); } static inline void xml_pop(struct xml_context *ctx) { TRACE(ctx, "pop"); ASSERT(ctx->stack_list); xml_do_pop(ctx, ctx->stack_list); } struct xml_dom_stack { struct xml_stack stack; struct mempool_state state; }; struct xml_node *xml_push_dom(struct xml_context *ctx, struct mempool_state *state); void xml_pop_dom(struct xml_context *ctx, uint free); #define XML_HASH_HDR_SIZE ALIGN_TO(sizeof(void *), CPU_STRUCT_ALIGN) #define XML_HASH_GIVE_ALLOC struct HASH_PREFIX(table); \ static inline void *HASH_PREFIX(alloc)(struct HASH_PREFIX(table) *t, uint size) \ { return mp_alloc(*(void **)((void *)t - XML_HASH_HDR_SIZE), size); } \ static inline void HASH_PREFIX(free)(struct HASH_PREFIX(table) *t UNUSED, void *p UNUSED) {} void *xml_hash_new(struct mempool *pool, uint size); void xml_spout_chars(struct fastbuf *fb); /*** Reading of document/external entities ***/ void NONRET xml_fatal_nested(struct xml_context *ctx); static inline void xml_inc(struct xml_context *ctx) { /* Called after the first character of a block */ TRACE(ctx, "inc"); ctx->depth++; } static inline void xml_dec(struct xml_context *ctx) { /* Called after the last character of a block */ TRACE(ctx, "dec"); if (unlikely(!ctx->depth--)) xml_fatal_nested(ctx); } #include "obj/ucw-xml/unicat.h" static inline uint xml_char_cat(uint c) { if (c < 0x10000) return 1U << ucw_xml_char_tab1[(c & 0xff) + ucw_xml_char_tab2[c >> 8]]; else if (likely(c < 0x110000)) return 1U << ucw_xml_char_tab3[c >> 16]; else return 1; } static inline uint xml_ascii_cat(uint c) { return ucw_xml_char_tab1[c]; } struct xml_source *xml_push_source(struct xml_context *ctx); void xml_push_entity(struct xml_context *ctx, struct xml_dtd_entity *ent); void xml_refill(struct xml_context *ctx); static inline uint xml_peek_char(struct xml_context *ctx) { if (ctx->bptr == ctx->bstop) xml_refill(ctx); return ctx->bptr[0]; } static inline uint xml_peek_cat(struct xml_context *ctx) { if (ctx->bptr == ctx->bstop) xml_refill(ctx); return ctx->bptr[1]; } static inline uint xml_get_char(struct xml_context *ctx) { uint c = xml_peek_char(ctx); ctx->bptr += 2; return c; } static inline uint xml_get_cat(struct xml_context *ctx) { uint c = xml_peek_cat(ctx); ctx->bptr += 2; return c; } static inline uint xml_last_char(struct xml_context *ctx) { return ctx->bptr[-2]; } static inline uint xml_last_cat(struct xml_context *ctx) { return ctx->bptr[-1]; } static inline uint xml_skip_char(struct xml_context *ctx) { uint c = ctx->bptr[0]; ctx->bptr += 2; return c; } static inline uint xml_unget_char(struct xml_context *ctx) { return *(ctx->bptr -= 2); } void xml_sources_cleanup(struct xml_context *ctx); /*** Parsing ***/ void NONRET xml_fatal_expected(struct xml_context *ctx, uint c); void NONRET xml_fatal_expected_white(struct xml_context *ctx); void NONRET xml_fatal_expected_quot(struct xml_context *ctx); uint xml_parse_white(struct xml_context *ctx, uint mandatory); static inline void xml_parse_char(struct xml_context *ctx, uint c) { /* Consumes a given Unicode character */ if (unlikely(c != xml_get_char(ctx))) xml_fatal_expected(ctx, c); } static inline void xml_parse_seq(struct xml_context *ctx, const char *seq) { /* Consumes a given sequence of ASCII characters */ while (*seq) xml_parse_char(ctx, *seq++); } void xml_parse_eq(struct xml_context *ctx); static inline uint xml_parse_quote(struct xml_context *ctx) { /* "'" | '"' */ uint c = xml_get_char(ctx); if (unlikely(c != '\'' && c != '\"')) xml_fatal_expected_quot(ctx); return c; } char *xml_parse_name(struct xml_context *ctx, struct mempool *pool); void xml_skip_name(struct xml_context *ctx); char *xml_parse_nmtoken(struct xml_context *ctx, struct mempool *pool); char *xml_parse_system_literal(struct xml_context *ctx, struct mempool *pool); char *xml_parse_pubid_literal(struct xml_context *ctx, struct mempool *pool); uint xml_parse_char_ref(struct xml_context *ctx); void xml_parse_pe_ref(struct xml_context *ctx); char *xml_parse_attr_value(struct xml_context *ctx, struct xml_dtd_attr *attr); void xml_skip_internal_subset(struct xml_context *ctx); void xml_parse_notation_decl(struct xml_context *ctx); void xml_parse_entity_decl(struct xml_context *ctx); void xml_parse_element_decl(struct xml_context *ctx); void xml_parse_attr_list_decl(struct xml_context *ctx); void xml_push_comment(struct xml_context *ctx); void xml_pop_comment(struct xml_context *ctx); void xml_skip_comment(struct xml_context *ctx); void xml_push_pi(struct xml_context *ctx); void xml_pop_pi(struct xml_context *ctx); void xml_skip_pi(struct xml_context *ctx); void xml_validate_attr(struct xml_context *ctx, struct xml_dtd_attr *dtd, char *value); /*** Namespaces ***/ void xml_ns_cleanup(struct xml_context *ctx); void xml_ns_reset(struct xml_context *ctx); void xml_ns_push_element(struct xml_context *ctx); void xml_ns_pop_element(struct xml_context *ctx); #endif