diff --git a/ChangeLog b/ChangeLog index 0f620b16..96002ae7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sun Jan 31 22:06:48 CET 1999 Daniel Veillard + + * valid.[ch], tree.c, parser.c : more work toward full parsing + of XML DTDs. + * README: added informations about mailing-list and on-line + documentation + 1999-01-27 Raja R Harinath * configure.in (XML_INCLUDEDIR): Use -I not -L for includes. diff --git a/README b/README index e69de29b..39c315c0 100644 --- a/README +++ b/README @@ -0,0 +1,14 @@ + + XML parser for Gnome + +Documentation is available on-line at + http://rufus.w3.org/veillard/XML/xml.html + +A mailing-list has been set-up, to subscribe: + echo "subscribe xml" | mail majordomo@rufus.w3.org + +The list archive is at: + http://rufus.w3.org/veillard/XML/messages/ + + +Daniel.Veillard@w3.org diff --git a/include/libxml/valid.h b/include/libxml/valid.h index d6765ff4..bef45dc4 100644 --- a/include/libxml/valid.h +++ b/include/libxml/valid.h @@ -11,8 +11,25 @@ #define __XML_VALID_H__ #include "tree.h" +/* + * ALl element declarations are stored in a table + * there is one table per DTD + */ + +#define XML_MIN_ELEMENT_TABLE 32 + +typedef struct xmlElementTable { + int nb_elements; /* number of elements stored */ + int max_elements; /* maximum number of elements */ + xmlElementPtr table; /* the table of entities */ +} xmlElementTable, *xmlElementTablePtr; + extern xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type, xmlElementContentPtr content); extern xmlElementContentPtr xmlNewElementContent(CHAR *name, int type); +extern xmlElementContentPtr xmlCopyElementContent(xmlElementContentPtr content); extern void xmlFreeElementContent(xmlElementContentPtr cur); + +extern xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table); +extern void xmlFreeElementTable(xmlElementTablePtr table); #endif /* __XML_VALID_H__ */ diff --git a/parser.c b/parser.c index a466b8b2..03cfa4e5 100644 --- a/parser.c +++ b/parser.c @@ -2388,16 +2388,21 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) { (NXT(6) == 'A')) { SKIP(7); SKIP_BLANKS; + if (CUR == ')') { + NEXT; + ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA); + return(ret); + } if ((CUR == '(') || (CUR == '|')) { ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA); if (ret == NULL) return(NULL); - } else { + } /********** else { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt, "xmlParseElementMixedContentDecl : '|' or ')' expected\n"); ctxt->wellFormed = 0; return(NULL); - } + } **********/ while (CUR == '|') { if (elem == NULL) { ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR); @@ -2422,7 +2427,7 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) { } SKIP_BLANKS; } - if (CUR == ')') { + if ((CUR == ')') && (NXT(1) == '*')) { if (elem != NULL) cur->c2 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT); @@ -2430,7 +2435,7 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) { } else { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt, - "xmlParseElementMixedContentDecl : '|' or ')' expected\n"); + "xmlParseElementMixedContentDecl : '|' or ')*' expected\n"); ctxt->wellFormed = 0; xmlFreeElementContent(ret); return(NULL); @@ -2671,6 +2676,7 @@ xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, CHAR *name, return(-1); } ****************************/ + *result = tree; return(res); } diff --git a/tree.c b/tree.c index 4d643d85..5892a4e9 100644 --- a/tree.c +++ b/tree.c @@ -20,6 +20,7 @@ #include "tree.h" #include "entities.h" +#include "valid.h" static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 }; int oldXMLWDcompatibility = 0; @@ -345,7 +346,7 @@ xmlFreeDtd(xmlDtdPtr cur) { if (cur->SystemID != NULL) free((char *) cur->SystemID); if (cur->ExternalID != NULL) free((char *) cur->ExternalID); if (cur->elements != NULL) - fprintf(stderr, "xmlFreeDtd: cur->elements != NULL !!! \n"); + xmlFreeElementTable((xmlElementTablePtr) cur->elements); if (cur->entities != NULL) xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities); memset(cur, -1, sizeof(xmlDtd)); @@ -2268,13 +2269,15 @@ xmlDtdDump(xmlDocPtr doc) { xmlBufferWriteCHAR(cur->SystemID); xmlBufferWriteChar("\""); } - if (cur->entities == NULL) { + if ((cur->entities == NULL) && (cur->elements == NULL)) { xmlBufferWriteChar(">\n"); return; } xmlBufferWriteChar(" [\n"); if (cur->entities != NULL) xmlDumpEntitiesTable((xmlEntitiesTablePtr) cur->entities); + if (cur->elements != NULL) + xmlDumpElementTable((xmlElementTablePtr) cur->elements); xmlBufferWriteChar("]"); /* TODO !!! a lot more things to dump ... */ diff --git a/valid.c b/valid.c index 215e463b..6f2f440d 100644 --- a/valid.c +++ b/valid.c @@ -56,10 +56,27 @@ xmlNewElementContent(CHAR *name, int type) { } ret->type = type; ret->ocur = XML_ELEMENT_CONTENT_ONCE; - ret->name = xmlStrdup(name); + if (name != NULL) + ret->name = xmlStrdup(name); + else + ret->name = NULL; return(ret); } +/** + * xmlCopyElementContent: + * @content: An element content pointer. + * + * Build a copy of an element content description. + * + * return values: the new xmlElementContentPtr or NULL in case of error. + */ +xmlElementContentPtr +xmlCopyElementContent(xmlElementContentPtr content) { +/* TODO !!! */ + return(NULL); +} + /** * xmlNewElementContent: * @name: the subelement name or NULL @@ -78,6 +95,37 @@ xmlFreeElementContent(xmlElementContentPtr cur) { * * ****************************************************************/ +/** + * xmlCreateElementTable: + * + * create and initialize an empty element hash table. + * + * return values: the xmlElementTablePtr just created or NULL in case of error. + */ +xmlElementTablePtr +xmlCreateElementTable(void) { + xmlElementTablePtr ret; + + ret = (xmlElementTablePtr) + malloc(sizeof(xmlElementTable)); + if (ret == NULL) { + fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n", + sizeof(xmlElementTable)); + return(NULL); + } + ret->max_elements = XML_MIN_ENTITIES_TABLE; + ret->nb_elements = 0; + ret->table = (xmlElementPtr ) + malloc(ret->max_elements * sizeof(xmlElement)); + if (ret == NULL) { + fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n", + ret->max_elements * sizeof(xmlElement)); + free(ret); + return(NULL); + } + return(ret); +} + /** * xmlAddElementDecl: @@ -90,7 +138,9 @@ xmlFreeElementContent(xmlElementContentPtr cur) { xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type, xmlElementContentPtr content) { - xmlElementPtr ret; + xmlElementPtr ret, cur; + xmlElementTablePtr table; + int i; if (dtd == NULL) { fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n"); @@ -134,29 +184,176 @@ xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type, return(NULL); } + /* + * Create the Element table if needed. + */ + table = dtd->elements; + if (table == NULL) + table = dtd->elements = xmlCreateElementTable(); + if (table == NULL) { + fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n"); + return(NULL); + } + /* * Validity Check: * Search the DTD for previous declarations of the ELEMENT */ - /* TODO */ + for (i = 0;i < table->nb_elements;i++) { + cur = &table->table[i]; + if (!xmlStrcmp(cur->name, name)) { + /* + * The element is already defined in this Dtd. + */ + fprintf(stderr, + "xmlAddElementDecl: %s already defined\n", name); + return(NULL); + } + } /* - * Create and fill the structure. + * Grow the table, if needed. */ - ret = (xmlElementPtr) malloc(sizeof(xmlElement)); - if (ret == NULL) { - fprintf(stderr, "xmlAddElementDecl: out of memory\n"); - return(NULL); + if (table->nb_elements >= table->max_elements) { + /* + * need more elements. + */ + table->max_elements *= 2; + table->table = (xmlElementPtr) + realloc(table->table, table->max_elements * sizeof(xmlElement)); + if (table->table) { + fprintf(stderr, "xmlAddElementDecl: out of memory\n"); + return(NULL); + } } + ret = &table->table[table->nb_elements]; + + /* + * fill the structure. + */ ret->type = type; ret->name = xmlStrdup(name); ret->content = content; - - /* - * Insert the structure in the DTD Element table - */ - /* TODO */ + table->nb_elements++; return(ret); } +/** + * xmlFreeElement: + * @elem: An element + * + * Deallocate the memory used by an element definition + */ +void +xmlFreeElement(xmlElementPtr elem) { + if (elem == NULL) return; + xmlFreeElementContent(elem->content); + if (elem->name != NULL) + free((CHAR *) elem->name); + memset(elem, -1, sizeof(xmlElement)); + free(elem); +} + +/** + * xmlFreeElementTable: + * @table: An element table + * + * Deallocate the memory used by an entities hash table. + */ +void +xmlFreeElementTable(xmlElementTablePtr table) { + int i; + + if (table == NULL) return; + + for (i = 0;i < table->nb_elements;i++) { + xmlFreeElement(&table->table[i]); + } + free(table->table); + free(table); +} + +/** + * xmlCopyElementTable: + * @table: An element table + * + * Build a copy of an element table. + * + * return values: the new xmlElementTablePtr or NULL in case of error. + */ +xmlElementTablePtr +xmlCopyElementTable(xmlElementTablePtr table) { + xmlElementTablePtr ret; + xmlElementPtr cur, ent; + int i; + + ret = (xmlElementTablePtr) malloc(sizeof(xmlElementTable)); + if (ret == NULL) { + fprintf(stderr, "xmlCopyElementTable: out of memory !\n"); + return(NULL); + } + ret->table = (xmlElementPtr) malloc(table->max_elements * + sizeof(xmlElement)); + if (ret->table == NULL) { + fprintf(stderr, "xmlCopyElementTable: out of memory !\n"); + free(ret); + return(NULL); + } + ret->max_elements = table->max_elements; + ret->nb_elements = table->nb_elements; + for (i = 0;i < ret->nb_elements;i++) { + cur = &ret->table[i]; + ent = &table->table[i]; + cur->type = ent->type; + if (ent->name != NULL) + cur->name = xmlStrdup(ent->name); + else + cur->name = NULL; + cur->content = xmlCopyElementContent(ent->content); + } + return(ret); +} + +/** + * xmlDumpElementTable: + * @table: An element table + * + * This will dump the content of the element table as an XML DTD definition + * + * NOTE: TODO an extra parameter allowing a reentant implementation will + * be added. + */ +void +xmlDumpElementTable(xmlElementTablePtr table) { + int i; + xmlElementPtr cur; + + if (table == NULL) return; + + for (i = 0;i < table->nb_elements;i++) { + cur = &table->table[i]; + switch (cur->type) { + case XML_ELEMENT_TYPE_EMPTY: + xmlBufferWriteChar("name); + xmlBufferWriteChar(" EMPTY>"); + break; + case XML_ELEMENT_TYPE_ANY: + xmlBufferWriteChar("name); + xmlBufferWriteChar(" ANY>"); + break; + case XML_ELEMENT_TYPE_MIXED: + /* TODO !!! */ + break; + case XML_ELEMENT_TYPE_ELEMENT: + /* TODO !!! */ + break; + default: + fprintf(stderr, + "xmlDumpElementTable: internal: unknown type %d\n", + cur->type); + } + } +} diff --git a/valid.h b/valid.h index d6765ff4..bef45dc4 100644 --- a/valid.h +++ b/valid.h @@ -11,8 +11,25 @@ #define __XML_VALID_H__ #include "tree.h" +/* + * ALl element declarations are stored in a table + * there is one table per DTD + */ + +#define XML_MIN_ELEMENT_TABLE 32 + +typedef struct xmlElementTable { + int nb_elements; /* number of elements stored */ + int max_elements; /* maximum number of elements */ + xmlElementPtr table; /* the table of entities */ +} xmlElementTable, *xmlElementTablePtr; + extern xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type, xmlElementContentPtr content); extern xmlElementContentPtr xmlNewElementContent(CHAR *name, int type); +extern xmlElementContentPtr xmlCopyElementContent(xmlElementContentPtr content); extern void xmlFreeElementContent(xmlElementContentPtr cur); + +extern xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table); +extern void xmlFreeElementTable(xmlElementTablePtr table); #endif /* __XML_VALID_H__ */