]> mj.ucw.cz Git - libucw.git/blobdiff - sherlock/xml/dtd.c
XML: Small bugfix in xml_merge_chars.
[libucw.git] / sherlock / xml / dtd.c
index 289a224342cccbf71faf64477bd9149d6ba69791..8c50a53265785502445376e1f27bebc46a8d43ac 100644 (file)
@@ -12,7 +12,7 @@
 #include "sherlock/sherlock.h"
 #include "sherlock/xml/xml.h"
 #include "sherlock/xml/dtd.h"
-#include "sherlock/xml/common.h"
+#include "sherlock/xml/internals.h"
 #include "lib/fastbuf.h"
 #include "lib/ff-unicode.h"
 #include "lib/unicode.h"
@@ -136,6 +136,14 @@ xml_dtd_find_pentity(struct xml_context *ctx, char *name)
 
 /* Elements */
 
+struct xml_dtd_elems_table;
+
+static void
+xml_dtd_elems_init_data(struct xml_dtd_elems_table *tab UNUSED, struct xml_dtd_elem *e)
+{
+  slist_init(&e->attrs);
+}
+
 #define HASH_PREFIX(x) xml_dtd_elems_##x
 #define HASH_NODE struct xml_dtd_elem
 #define HASH_KEY_STRING name
@@ -144,6 +152,7 @@ xml_dtd_find_pentity(struct xml_context *ctx, char *name)
 #define HASH_WANT_FIND
 #define HASH_WANT_LOOKUP
 #define HASH_GIVE_ALLOC
+#define HASH_GIVE_INIT_DATA
 #define HASH_TABLE_ALLOC
 XML_HASH_GIVE_ALLOC
 #include "lib/hashtable.h"
@@ -214,6 +223,7 @@ xml_dtd_attrs_init_key(struct xml_dtd_attrs_table *tab UNUSED, struct xml_dtd_at
 {
   attr->elem = elem;
   attr->name = name;
+  slist_add_tail(&elem->attrs, &attr->n);
 }
 
 #define HASH_PREFIX(x) xml_dtd_attrs_##x
@@ -380,24 +390,32 @@ xml_parse_pe_ref(struct xml_context *ctx)
   xml_dec(ctx);
 }
 
-static void
-xml_parse_dtd_pe(struct xml_context *ctx)
+static uns
+xml_parse_dtd_pe(struct xml_context *ctx, uns entity_decl)
 {
+  /* Already parsed: '%' */
   do
     {
-      xml_skip_char(ctx);
       xml_inc(ctx);
+      if (!~entity_decl && (xml_peek_cat(ctx) & XML_CHAR_WHITE))
+        {
+         xml_dec(ctx);
+         return ~0U;
+       }
+      xml_parse_pe_ref(ctx);
       while (xml_peek_cat(ctx) & XML_CHAR_WHITE)
        xml_skip_char(ctx);
-      xml_parse_pe_ref(ctx);
     }
-  while (xml_peek_char(ctx) != '%');
+  while (xml_get_char(ctx) == '%');
+  xml_unget_char(ctx);
+  return 1;
 }
 
 static inline uns
 xml_parse_dtd_white(struct xml_context *ctx, uns mandatory)
 {
-  /* Whitespace or parameter entity */
+  /* Whitespace or parameter entity,
+   * mandatory==~0U has a special maening of the whitespace before the '%' character in an parameter entity declaration */
   uns cnt = 0;
   while (xml_peek_cat(ctx) & XML_CHAR_WHITE)
     {
@@ -406,8 +424,8 @@ xml_parse_dtd_white(struct xml_context *ctx, uns mandatory)
     }
   if (xml_peek_char(ctx) == '%')
     {
-      xml_parse_dtd_pe(ctx);
-      return 1;
+      xml_skip_char(ctx);
+      return xml_parse_dtd_pe(ctx, mandatory);
     }
   else if (unlikely(mandatory && !cnt))
     xml_fatal_expected_white(ctx);
@@ -478,23 +496,17 @@ xml_parse_entity_decl(struct xml_context *ctx)
   /* Already parsed: '<!ENTITY' */
   TRACE(ctx, "parse_entity_decl");
   struct xml_dtd *dtd = ctx->dtd;
-  xml_parse_dtd_white(ctx, 1);
-
-  uns flags = (xml_get_char(ctx) == '%') ? XML_DTD_ENTITY_PARAMETER : 0;
+  uns flags = ~xml_parse_dtd_white(ctx, ~0U) ? 0 : XML_DTD_ENTITY_PARAMETER;
   if (flags)
     xml_parse_dtd_white(ctx, 1);
-  else
-    xml_unget_char(ctx);
-
   struct xml_dtd_entity *ent = xml_dtd_ents_lookup(flags ? dtd->tab_pents : dtd->tab_ents, xml_parse_name(ctx, dtd->pool));
-  slist *list = flags ? &dtd->pents : &dtd->ents;
   xml_parse_dtd_white(ctx, 1);
+  slist *list = flags ? &dtd->pents : &dtd->ents;
   if (ent->flags & XML_DTD_ENTITY_DECLARED)
     {
        xml_fatal(ctx, "Entity &%s; already declared, skipping not implemented", ent->name);
        // FIXME: should be only warning
     }
-
   uns c, sep = xml_get_char(ctx);
   if (sep == '\'' || sep == '"')
     {