Changeset 39


Ignore:
Timestamp:
Feb 23, 2001, 7:50:07 AM (24 years ago)
Author:
umoeller
Message:

Misc. fixes.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/expat/expat.h

    r38 r39  
    624624                                          enum XML_ParamEntityParsing parsing);
    625625
    626 #define ERROR_EXPAT_NONE        0   // explicitly added V0.9.9 (2001-02-14) [umoeller]
    627 
    628626#define ERROR_XML_FIRST         40000   // first error code used
    629627
    630628typedef enum _XMLERROR
    631629{
     630    ERROR_EXPAT_NONE = 0,
    632631    // ERROR_EXPAT_NONE,            // removed to adhere with APIRET V0.9.9 (2001-02-14) [umoeller]
    633632    ERROR_EXPAT_NO_MEMORY = ERROR_XML_FIRST,
  • trunk/include/helpers/xml.h

    r38 r39  
    5252                // more than one declaration for an attribute type
    5353        ERROR_DOM_UNDECLARED_ATTRIBUTE,
     54        ERROR_ELEMENT_CANNOT_HAVE_CONTENT,
     55                // element was declared "empty" and contains text anyway,
     56                // or was declared "children" and contains something other
     57                // than whitespace
     58        ERROR_DOM_INVALID_ATTRIB_VALUE,
     59        ERROR_DOM_REQUIRED_ATTRIBUTE_MISSING,
     60        ERROR_DOM_SUBELEMENT_IN_EMPTY_ELEMENT,
    5461// END MATCHING ERROR MESSAGES (xmlDescribeError)
    5562
     
    6067        // additional DOM errors
    6168        ERROR_DOM_NODETYPE_NOT_SUPPORTED,
    62                 // invalid node type in xmlCreateNode
     69                // invalid node type in xmlCreateDomNode
    6370        ERROR_DOM_NO_DOCUMENT,
    6471                // cannot find document node
     
    8087    typedef enum _NODEBASETYPE
    8188    {
     89        TYPE_UNKNOWN,
     90
    8291        DOMNODE_ELEMENT,                // node is a DOM ELEMENT
    8392        DOMNODE_ATTRIBUTE,              // node is a DOM ATTRIBUTE
     
    219228        NODEBASE        NodeBase;
    220229
    221         // PXSTRING    pstrNodeName;            // ptr is NULL if none
    222230        PXSTRING        pstrNodeValue;           // ptr is NULL if none
    223231
     
    270278
    271279        TREE        *AttribDeclBasesTree;
    272                     // tree with pointers to _CMATTRIBUTEDEDECLBASE nodes
     280                    // tree with pointers to _CMATTRIBUTEDECLBASE nodes
    273281
    274282    } DOMDOCTYPENODE, *PDOMDOCTYPENODE;
     
    291299    } DOMDOCUMENTNODE, *PDOMDOCUMENTNODE;
    292300
    293     APIRET xmlCreateNode(PDOMNODE pParentNode,
    294                          ULONG ulNodeType,
    295                          PDOMNODE *ppNew);
    296 
    297     ULONG xmlDeleteNode(PDOMNODE pNode);
     301    APIRET xmlCreateDomNode(PDOMNODE pParentNode,
     302                            NODEBASETYPE ulNodeType,
     303                            const char *pcszNodeName,
     304                            ULONG ulNodeNameLength,
     305                            PDOMNODE *ppNew);
     306
     307    VOID xmlDeleteNode(PNODEBASE pNode);
    298308
    299309    /* ******************************************************************
     
    328338    typedef struct _CMELEMENTPARTICLE
    329339    {
    330         NODEBASE          CMNode;         // has TREE* as first item in turn
    331                     // NODEBASE.ulCMNodeType may be one of these:
     340        NODEBASE          NodeBase;       // has TREE* as first item in turn
     341                    // NODEBASE.ulNodeType may be one of these:
    332342                    // -- ELEMENTPARTICLE_EMPTY:
    333343                    //          ulRepeater will be XML_CQUANT_NONE, rest is NULL
     
    354364                    // -- XML_CQUANT_PLUS
    355365
     366        struct _CMELEMENTPARTICLE *pParentParticle;     // or NULL if this is in the
     367                                                        // CMELEMENTDECLNODE
     368
    356369        PLINKLIST       pllSubNodes;
    357370                    // linked list of sub-CMELEMENTPARTICLE structs
     
    378391     *
    379392     *      For the "root" element declaration in the DTD,
    380      *      Particle.NODEBASE.ulCMNodeType will always be one of the following:
     393     *      Particle.NODEBASE.ulNodeType will always be one of the following:
    381394     *
    382395     *      -- ELEMENTPARTICLE_EMPTY: element must be empty.
     
    438451     *@@ CMATTRIBUTEDECL:
    439452     *      single attribute declaration within the attribute
    440      *      declarations tree in _CMATTRIBUTEDEDECLBASE.
     453     *      declarations tree in _CMATTRIBUTEDECLBASE.
    441454     *
    442455     *@@added V0.9.9 (2001-02-16) [umoeller]
     
    445458    typedef struct _CMATTRIBUTEDECL
    446459    {
    447         NODEBASE          CMNode;         // has TREE* as first item in turn
    448                     // CMNode.strName is attribute name
    449 
    450         // XSTRING         strType;
     460        NODEBASE          NodeBase;       // has TREE* as first item in turn
     461                    // NodeBase.strName is attribute name
    451462
    452463        ATTRIBTYPE      ulAttrType;
     
    463474        TREE            *ValuesTree;
    464475                    // enumeration of allowed values, if CMAT_ENUM;
    465                     // tree entries are plain NODEBASEs
     476                    // tree entries are plain NODEBASEs with
     477                    // ATTRIBUTE_DECLARATION_ENUM type
    466478
    467479        ATTRIBCONSTRAINT    ulConstraint;
     
    479491
    480492    /*
    481      *@@ CMATTRIBUTEDEDECLBASE:
     493     *@@ CMATTRIBUTEDECLBASE:
    482494     *      representation of an @attribute_declaration.
    483495     *
     
    493505     */
    494506
    495     typedef struct _CMATTRIBUTEDEDECLBASE
    496     {
    497         NODEBASE        CMNode;         // has TREE* as first item in turn
    498                     // CMNode.strName is element name
     507    typedef struct _CMATTRIBUTEDECLBASE
     508    {
     509        NODEBASE        NodeBase;         // has TREE* as first item in turn
     510                    // NodeBase.strName is element name
    499511
    500512        TREE            *AttribDeclsTree;
    501513                            // root of tree with CMATTRIBUTEDECL;
    502514
    503     } CMATTRIBUTEDEDECLBASE, *PCMATTRIBUTEDEDECLBASE;
     515    } CMATTRIBUTEDECLBASE, *PCMATTRIBUTEDECLBASE;
    504516
    505517    /*
     
    513525    typedef struct _CMENTITYDECLNODE
    514526    {
    515         NODEBASE          CMNode;
     527        NODEBASE          NodeBase;
    516528    } CMENTITYDECLNODE, *PCMENTITYDECLNODE;
    517529
     
    526538    typedef struct _CMNOTATIONDECLNODE
    527539    {
    528         NODEBASE          CMNode;
     540        NODEBASE          NodeBase;
    529541    } CMNOTATIONDECLNODE, *PCMNOTATIONDECLNODE;
    530542
     
    568580                            // expat parser instance
    569581
    570         LINKLIST        llStack;
     582        LINKLIST        llElementStack;
    571583                            // stack for maintaining the current items;
    572                             // these point to the NODERECORDs (no auto-free)
     584                            // these point to DOMSTACKITEMs (auto-free)
    573585
    574586        PDOMNODE        pLastWasTextNode;
    575587
    576         PCMATTRIBUTEDEDECLBASE pAttListDeclCache;
     588        PCMATTRIBUTEDECLBASE pAttListDeclCache;
    577589                            // cache for attribute declarations according
    578590                            // to attdecl element name
     
    595607                                          const XSTRING *pstrElementName);
    596608
    597     PCMATTRIBUTEDEDECLBASE xmlFindAttribDeclBase(PXMLDOM pDom,
     609    PCMATTRIBUTEDECLBASE xmlFindAttribDeclBase(PXMLDOM pDom,
    598610                                                 const XSTRING *pstrElementName);
    599611
    600612    PCMATTRIBUTEDECL xmlFindAttribDecl(PXMLDOM pDom,
    601613                                       const XSTRING *pstrElementName,
    602                                        const XSTRING *pstrAttribName);
     614                                       const XSTRING *pstrAttribName,
     615                                       PCMATTRIBUTEDECLBASE *ppAttribDeclBase);
    603616
    604617#endif
  • trunk/include/setup.h

    r35 r39  
    1616        #define XWPENTRY _Optlink
    1717    #endif
    18 
    19     #error This file shouldn't be included.
    2018
    2119    /*************************************************************
  • trunk/src/helpers/tree.c

    r38 r39  
    922922 *      as a data pointer to some structure for whatever you like.
    923923 *
     924 *      WARNING: This function recurses and can use up a lot of
     925 *      stack. For very deep trees, traverse the tree using
     926 *      treeFirst and treeNext instead. See treeNext for a sample.
     927 *
    924928 *      "method" specifies in which order the nodes are traversed.
    925929 *      This can be:
     
    936940                  int method)               // in: traversal mode
    937941{
    938     if ((!tree)
    939     || (tree == TREE_NULL))
     942    if (    (!tree)
     943         || (tree == TREE_NULL))
    940944        return;
    941945
     
    963967 *@@ treeFirst:
    964968 *      finds and returns the first node in a (sub-)tree.
     969 *
     970 *      See treeNext for a sample usage for traversing a tree.
    965971 */
    966972
     
    970976       *current;
    971977
    972     if ((!tree)
    973     ||  (tree == TREE_NULL))
     978    if (    (!tree)
     979         || (tree == TREE_NULL)
     980       )
    974981        return NULL;
    975982
     
    991998       *current;
    992999
    993     if ((!tree)
    994     || (tree == TREE_NULL))
     1000    if (    (!tree)
     1001         || (tree == TREE_NULL))
    9951002        return NULL;
    9961003
     
    10051012 *@@ treeNext:
    10061013 *      finds and returns the next node in a tree.
     1014 *
     1015 *      Example for traversing a whole tree if you don't
     1016 *      want to use treeTraverse:
     1017 *
     1018 +          TREE    *TreeRoot;
     1019 +          ...
     1020 +          TREE* pNode = treeFirst(TreeRoot);
     1021 +          while (pNode)
     1022 +          {
     1023 +              ...
     1024 +              pNode = treeNext(pNode);
     1025 +          }
     1026 *
     1027 *      This runs through the tree items in sorted order.
    10071028 */
    10081029
     
    10131034       *child;
    10141035
    1015     if ((!tree)
    1016     ||  (tree == TREE_NULL))
     1036    if (    (!tree)
     1037         || (tree == TREE_NULL)
     1038       )
    10171039        return NULL;
    10181040
     
    10241046        current = tree;
    10251047        child   = TREE_NULL;
    1026         while ((current->parent)
    1027            &&  (current->right == child))
     1048        while (    (current->parent)
     1049                && (current->right == child)
     1050              )
    10281051        {
    10291052            child = current;
     
    10481071       *child;
    10491072
    1050     if ((!tree)
    1051     || (tree == TREE_NULL))
     1073    if (    (!tree)
     1074         || (tree == TREE_NULL))
    10521075        return NULL;
    10531076
  • trunk/src/helpers/xml.c

    r38 r39  
    6262 *
    6363 *      However, we do implement node management as in the standard.
    64  *      See xmlCreateNode and xmlDeleteNode.
     64 *      See xmlCreateDomNode and xmlDeleteNode.
    6565 *
    6666 *      The main entry point into this is xmlCreateDOM. See remarks
    67  *      there for details.
     67 *      there for how this will be typically used.
    6868 *
    6969 *      <B>Validation</B>
     
    7272 *      In other words, expat is a non-validating XML processor.
    7373 *
    74  *      By contrast, this pseudo-DOM implementation can validate. To
    75  *      do this, you must pass DF_PARSEDTD to xmlCreateDOM (otherwise
    76  *      the @DTD entries will not be stored in the DOM nodes). This
    77  *      will not validate yet; to do this, explicitly call xmlValidate.
     74 *      By contrast, this pseudo-DOM implementation can validate to
     75 *      a certain extent.
     76 *
     77 *      -- If you pass DF_PARSEDTD to xmlCreateDOM, the DTD will be
     78 *         parsed and the document will be validated against it.
     79 *         Validation is working as far as elements and attributes
     80 *         are checked for proper nesting. However, we cannot fully
     81 *         check for proper ordering etc. in (children) mode of
     82 *         @element_declarations. This will only check for whether
     83 *         elements may appear in another element at all -- not for
     84 *         the correct order.
     85 *
     86 *      -- Otherwise the @DTD entries will not be stored in the DOM
     87 *         nodes, and no validation occurs. Still, if a DTD exists,
     88 *         @expat will insert attributes that have a default value
     89 *         in their @attribute declaraion and have not been specified.
    7890 *
    7991 *@@header "helpers\xml.h"
     
    104116#include <stdlib.h>
    105117#include <string.h>
     118#include <stdio.h>
    106119
    107120#include "setup.h"                      // code generation and debugging options
     
    134147
    135148/*
    136  *@@ CompareCMNodeNodes:
    137  *      tree comparison func for CMNodes.
     149 *@@ CompareNodeBaseNodes:
     150 *      tree comparison func for NodeBases.
    138151 *      This works for all trees which contain structures
    139152 *      whose first item is a _NODEBASE because NODEBASE's first
     
    151164 */
    152165
    153 int CompareCMNodeNodes(TREE *t1,
    154                        TREE *t2)
     166int XWPENTRY CompareNodeBaseNodes(TREE *t1,
     167                                  TREE *t2)
    155168{
    156169    PNODEBASE   p1 = (PNODEBASE)t1,
     
    160173
    161174/*
    162  *@@ CompareCMNodeNodes:
     175 *@@ CompareNodeBaseNodes:
    163176 *      tree comparison func for element declarations.
    164177 *      Used to find nodes in _DOMDOCTYPENODE.ElementDeclsTree.
     
    167180 */
    168181
    169 int CompareCMNodeData(TREE *t1,
    170                            void *pData)
     182int XWPENTRY CompareNodeBaseData(TREE *t1,
     183                                 void *pData)
    171184{
    172185    PNODEBASE     p1 = (PNODEBASE)t1;
     
    175188
    176189/*
    177  *@@ xmlCreateNode:
     190 *@@ xmlCreateNodeBase:
     191 *      creates a new NODEBASE node.
     192 *
     193 *      Gets called from xmlCreateDomNode also to create
     194 *      a DOMNODE, since that in turn has a NODEBASE.
     195 *
     196 *@@added V0.9.9 (2001-02-16) [umoeller]
     197 */
     198
     199APIRET xmlCreateNodeBase(NODEBASETYPE ulNodeType,     // in: node type
     200                         ULONG cb,                    // in: size of struct
     201                         const char *pcszNodeName,    // in: node name or NULL
     202                         ULONG ulNodeNameLength,      // in: node name length
     203                                                      // or 0 to run strlen(pcszNodeName)
     204                         PNODEBASE *ppNew)            // out: new node
     205{
     206    APIRET      arc = NO_ERROR;
     207    PNODEBASE   pNewNode = (PNODEBASE)malloc(cb);
     208
     209    if (!pNewNode)
     210        arc = ERROR_NOT_ENOUGH_MEMORY;
     211    else
     212    {
     213        memset(pNewNode, 0, cb);
     214        pNewNode->ulNodeType = ulNodeType;
     215
     216        xstrInit(&pNewNode->strNodeName, 0);
     217        if (pcszNodeName)
     218            xstrcpy(&pNewNode->strNodeName,
     219                    pcszNodeName,
     220                    ulNodeNameLength);  // if 0, xstrcpy will do strlen()
     221
     222
     223        *ppNew = pNewNode;
     224    }
     225
     226    return (arc);
     227}
     228
     229/*
     230 *@@ xmlDeleteNode:
     231 *      deletes a NODEBASE and frees memory that was
     232 *      associated with its members.
     233 *
     234 *      NOTE: If you call this for derived types, call
     235 *      this LAST, after you have cleared additional
     236 *      members. After calling this, pNode is no longer
     237 *      valid.
     238 *
     239 *@@added V0.9.9 (2001-02-16) [umoeller]
     240 */
     241
     242VOID xmlDeleteNode(PNODEBASE pNode)
     243{
     244    if (pNode)
     245    {
     246        PLISTNODE   pNodeThis;
     247        PDOMNODE    pDomNode = NULL;
     248
     249        LINKLIST    llDeleteNodes;          // list that nodes to be deleted
     250                                            // can be appended to
     251        PLISTNODE   pDelNode;
     252        lstInit(&llDeleteNodes, FALSE);
     253
     254        // now handle special types and their allocations
     255        switch (pNode->ulNodeType)
     256        {
     257            case DOMNODE_ELEMENT:
     258            {
     259                PDOMNODE pAttrib;
     260
     261                pDomNode = (PDOMNODE)pNode;
     262
     263                // delete all attribute nodes
     264                pAttrib = (PDOMNODE)treeFirst(pDomNode->AttributesMap);
     265                while (pAttrib)
     266                {
     267                    // call delete recursively
     268                    xmlDeleteNode((PNODEBASE)pAttrib);
     269                            // this will remove pAttrib from pNode's attrib
     270                            // tree and rebalance the tree; treeNext will
     271                            // still work #### noooooo
     272                    pAttrib = (PDOMNODE)treeNext((TREE*)pAttrib);
     273                }
     274            break; }
     275
     276            case DOMNODE_ATTRIBUTE:
     277            case DOMNODE_TEXT:
     278            case DOMNODE_PROCESSING_INSTRUCTION:
     279            case DOMNODE_COMMENT:
     280            case DOMNODE_DOCUMENT:
     281                pDomNode = (PDOMNODE)pNode;
     282            break;
     283
     284            case DOMNODE_DOCUMENT_TYPE:
     285            {
     286                PDOMDOCTYPENODE pDocType = (PDOMDOCTYPENODE)pNode;
     287                PCMELEMENTDECLNODE pElDecl;
     288                PCMATTRIBUTEDECLBASE pAttrDeclBase;
     289
     290                pDomNode = (PDOMNODE)pNode;
     291
     292                pElDecl = (PCMELEMENTDECLNODE)treeFirst(pDocType->ElementDeclsTree);
     293                while (pElDecl)
     294                {
     295                    lstAppendItem(&llDeleteNodes, pElDecl);
     296                    pElDecl = (PCMELEMENTDECLNODE)treeNext((TREE*)pElDecl);
     297                }
     298
     299                pAttrDeclBase = (PCMATTRIBUTEDECLBASE)treeFirst(pDocType->AttribDeclBasesTree);
     300                while (pAttrDeclBase)
     301                {
     302                    lstAppendItem(&llDeleteNodes, pAttrDeclBase);
     303                    pAttrDeclBase = (PCMATTRIBUTEDECLBASE)treeNext((TREE*)pAttrDeclBase);
     304                }
     305
     306                xstrClear(&pDocType->strPublicID);
     307                xstrClear(&pDocType->strSystemID);
     308            break; }
     309
     310            case ELEMENTPARTICLE_EMPTY:
     311            case ELEMENTPARTICLE_ANY:
     312            case ELEMENTPARTICLE_MIXED:
     313            case ELEMENTPARTICLE_CHOICE:
     314            case ELEMENTPARTICLE_SEQ:
     315            case ELEMENTPARTICLE_NAME:
     316            {
     317                PCMELEMENTPARTICLE pp = (PCMELEMENTPARTICLE)pNode;
     318                if (pp->pllSubNodes)
     319                {
     320                    pDelNode = lstQueryFirstNode(pp->pllSubNodes);
     321                    while (pDelNode)
     322                    {
     323                        PCMELEMENTPARTICLE
     324                                pParticle = (PCMELEMENTPARTICLE)pDelNode->pItemData;
     325                        xmlDeleteNode((PNODEBASE)pParticle);
     326                        //  treeDelete(pp->         ###
     327                        pDelNode = pDelNode->pNext;
     328                    }
     329                }
     330            break; }
     331
     332            // case ATTRIBUTE_DECLARATION_ENUM:     // this is a plain NODEBASE
     333
     334            case ATTRIBUTE_DECLARATION:
     335            {
     336                PCMATTRIBUTEDECL pDecl = (PCMATTRIBUTEDECL)pNode;
     337            break; }
     338
     339            case ATTRIBUTE_DECLARATION_BASE:
     340            break;
     341        }
     342
     343        if (pDomNode)
     344        {
     345            // recurse into child nodes
     346            while (pNodeThis = lstQueryFirstNode(&pDomNode->llChildren))
     347                // recurse!!
     348                xmlDeleteNode((PNODEBASE)(pNodeThis->pItemData));
     349                            // this updates llChildren
     350
     351            if (pDomNode->pParentNode)
     352            {
     353                // node has a parent:
     354                if (pNode->ulNodeType == DOMNODE_ATTRIBUTE)
     355                    // this is an attribute:
     356                    // remove from parent's attributes map
     357                    treeDelete(&pDomNode->pParentNode->AttributesMap,
     358                               (TREE*)pNode);
     359                else
     360                    // remove this node from the parent's list
     361                    // of child nodes before deleting this node
     362                    lstRemoveItem(&pDomNode->pParentNode->llChildren,
     363                                  pNode);
     364
     365                pDomNode->pParentNode = NULL;
     366            }
     367
     368            xstrFree(pDomNode->pstrNodeValue);
     369            lstClear(&pDomNode->llChildren);
     370        }
     371
     372        pDelNode = lstQueryFirstNode(&llDeleteNodes);
     373        while (pDelNode)
     374        {
     375            PNODEBASE pNodeBase = (PNODEBASE)pDelNode->pItemData;
     376            xmlDeleteNode(pNodeBase);
     377            pDelNode = pDelNode->pNext;
     378        }
     379
     380        lstClear(&llDeleteNodes);
     381
     382        xstrClear(&pNode->strNodeName);
     383        free(pNode);
     384    }
     385}
     386
     387/*
     388 *@@ xmlCreateDomNode:
    178389 *      creates a new DOMNODE with the specified
    179390 *      type and parent. Other than that, the
     
    198409 */
    199410
    200 APIRET xmlCreateNode(PDOMNODE pParentNode,        // in: parent node or NULL if root
    201                      ULONG ulNodeType,            // in: DOMNODE_* type
    202                      PDOMNODE *ppNew)             // out: new node
     411APIRET xmlCreateDomNode(PDOMNODE pParentNode,        // in: parent node or NULL if root
     412                        NODEBASETYPE ulNodeType,     // in: DOMNODE_* type
     413                        const char *pcszNodeName,    // in: node name or NULL
     414                        ULONG ulNodeNameLength,      // in: node name length
     415                                                     // or 0 to run strlen(pcszNodeName)
     416                        PDOMNODE *ppNew)             // out: new node
    203417{
    204418    PDOMNODE pNewNode = NULL;
     
    222436    }
    223437
    224     pNewNode = (PDOMNODE)malloc(cb);
    225 
    226     if (!pNewNode)
    227         arc = ERROR_NOT_ENOUGH_MEMORY;
    228     else
    229     {
    230         memset(pNewNode, 0, cb);
    231         pNewNode->NodeBase.ulNodeType = ulNodeType;
    232         xstrInit(&pNewNode->NodeBase.strNodeName, 0);
     438    arc = xmlCreateNodeBase(ulNodeType,
     439                            cb,
     440                            pcszNodeName,
     441                            ulNodeNameLength,
     442                            (PNODEBASE*)&pNewNode);
     443    if (arc == NO_ERROR)
     444    {
    233445        pNewNode->pParentNode = pParentNode;
    234446
     
    242454                // add to parent's attributes list
    243455                if (treeInsertNode(&pParentNode->AttributesMap,
    244                                    (TREE*)pNewNode,
    245                                    CompareCMNodeNodes,
     456                                   &pNewNode->NodeBase.Tree,
     457                                   CompareNodeBaseNodes,
    246458                                   FALSE)      // no duplicates
    247459                        == TREE_DUPLICATE)
     
    283495
    284496    return (arc);
    285 }
    286 
    287 /*
    288  *@@ xmlDeleteNode:
    289  *      deletes the specified node and updates the
    290  *      parent node's children list.
    291  *
    292  *      If the node has child nodes, all of them are deleted
    293  *      as well. This recurses, if necessary.
    294  *
    295  *      As a result, if the node is a document node, this
    296  *      deletes an entire document, including all of its
    297  *      child nodes.
    298  *
    299  *      This returns the following errors:
    300  *
    301  *      -- ERROR_DOM_NOT_FOUND
    302  */
    303 
    304 APIRET xmlDeleteNode(PDOMNODE pNode)
    305 {
    306     ULONG ulrc = 0;
    307 
    308     if (!pNode)
    309     {
    310         ulrc = ERROR_INVALID_PARAMETER;
    311     }
    312     else
    313     {
    314         PLISTNODE   pNodeThis;
    315 
    316         // recurse into child nodes
    317         while (pNodeThis  = lstQueryFirstNode(&pNode->llChildren))
    318             // recurse!!
    319             xmlDeleteNode((PDOMNODE)(pNodeThis->pItemData));
    320                         // this updates llChildren
    321 
    322         // recurse into attribute nodes
    323         // while (pNodeThis = lstQueryFirstNode(&pNode->llAttributes))
    324             // recurse!! ###
    325             // xmlDeleteNode((PDOMNODE)(pNodeThis->pItemData));
    326                         // this updates llAttributes
    327 
    328         if (pNode->pParentNode)
    329         {
    330             // node has a parent:
    331             if (pNode->NodeBase.ulNodeType == DOMNODE_ATTRIBUTE)
    332                 // this is an attribute:
    333                 // remove from parent's attributes map
    334                 treeDelete(&pNode->pParentNode->AttributesMap,
    335                            (TREE*)pNode);
    336             else
    337                 // remove this node from the parent's list
    338                 // of child nodes before deleting this node
    339                 lstRemoveItem(&pNode->pParentNode->llChildren,
    340                               pNode);
    341 
    342             pNode->pParentNode = NULL;
    343         }
    344 
    345         xstrClear(&pNode->NodeBase.strNodeName);
    346         xstrFree(pNode->pstrNodeValue);
    347 
    348         lstClear(&pNode->llChildren);
    349         // lstClear(&pNode->llAttributes); ###
    350 
    351         free(pNode);
    352     }
    353 
    354     return (ulrc);
    355497}
    356498
     
    438580        "Duplicate element declaration",
    439581        "Duplicate attribute declaration",
    440         "Undeclared attribute in element"
     582        "Undeclared attribute in element",
     583        "Element cannot have content",
     584        "Invalid attribute value",
     585        "Required attribute is missing",
     586        "Subelement in empty element"
    441587    };
    442588
     
    500646{
    501647    PDOMNODE pNew = NULL;
    502     APIRET arc = xmlCreateNode(pParent,
     648    APIRET arc = xmlCreateDomNode(pParent,
    503649                               DOMNODE_ELEMENT,
     650                               pcszElement,
     651                               0,
    504652                               &pNew);
    505653
    506654    if (arc == NO_ERROR)
    507     {
    508         xstrcpy(&pNew->NodeBase.strNodeName, pcszElement, 0);
    509 
    510655        *ppNew = pNew;
    511     }
    512656
    513657    return (arc);
     
    524668 *      This returns the following errors:
    525669 *
    526  *      --  Error codes from xmlCreateNode.
     670 *      --  Error codes from xmlCreateDomNode.
    527671 *
    528672 *      --  ERROR_DOM_NO_ELEMENT: pElement is invalid or does
     
    546690    {
    547691        PDOMNODE pNew = NULL;
    548         arc = xmlCreateNode(pElement,          // this takes care of adding to the list
     692        arc = xmlCreateDomNode(pElement,          // this takes care of adding to the list
    549693                            DOMNODE_ATTRIBUTE,
     694                            pcszName,
     695                            0,
    550696                            &pNew);
    551697        if (arc == NO_ERROR)
    552698        {
    553             xstrcpy(&pNew->NodeBase.strNodeName, pcszName, 0);
    554699            pNew->pstrNodeValue = xstrCreate(0);
    555700            xstrcpy(pNew->pstrNodeValue, pcszValue, 0);
     
    579724{
    580725    PDOMNODE pNew = NULL;
    581     APIRET arc = xmlCreateNode(pParent,
    582                                DOMNODE_TEXT,
    583                                &pNew);
     726    APIRET arc = xmlCreateDomNode(pParent,
     727                                  DOMNODE_TEXT,
     728                                  NULL,
     729                                  0,
     730                                  &pNew);
    584731    if (arc == NO_ERROR)
    585732    {
     
    588735        {
    589736            arc = ERROR_NOT_ENOUGH_MEMORY;
    590             xmlDeleteNode(pNew);
     737            xmlDeleteNode((PNODEBASE)pNew);
    591738        }
    592739        else
     
    617764{
    618765    PDOMNODE pNew = NULL;
    619     APIRET arc = xmlCreateNode(pParent,
     766    APIRET arc = xmlCreateDomNode(pParent,
    620767                               DOMNODE_COMMENT,
     768                               NULL,
     769                               0,
    621770                               &pNew);
    622771    if (arc == NO_ERROR)
     
    644793{
    645794    PDOMNODE pNew = NULL;
    646     APIRET arc = xmlCreateNode(pParent,
     795    APIRET arc = xmlCreateDomNode(pParent,
    647796                               DOMNODE_PROCESSING_INSTRUCTION,
     797                               pcszTarget,
     798                               0,
    648799                               &pNew);
    649800    if (arc == NO_ERROR)
    650801    {
    651         xstrcpy(&pNew->NodeBase.strNodeName, pcszTarget, 0);
    652802        pNew->pstrNodeValue = xstrCreate(0);
    653803        xstrcpy(pNew->pstrNodeValue, pcszData, 0);
     
    683833        // create doctype node
    684834        PDOMDOCTYPENODE pNew = NULL;
    685         arc = xmlCreateNode((PDOMNODE)pDocumentNode,
     835        arc = xmlCreateDomNode((PDOMNODE)pDocumentNode,
    686836                            DOMNODE_DOCUMENT_TYPE,
     837                            NULL,
     838                            0,
    687839                            (PDOMNODE*)&pNew);
    688840
     
    764916    {
    765917        case XML_CTYPE_EMPTY: // that's easy
    766             pParticle->CMNode.ulNodeType = ELEMENTPARTICLE_EMPTY;
     918            pParticle->NodeBase.ulNodeType = ELEMENTPARTICLE_EMPTY;
    767919        break;
    768920
    769921        case XML_CTYPE_ANY:   // that's easy
    770             pParticle->CMNode.ulNodeType = ELEMENTPARTICLE_ANY;
     922            pParticle->NodeBase.ulNodeType = ELEMENTPARTICLE_ANY;
    771923        break;
    772924
    773925        case XML_CTYPE_NAME:   // that's easy
    774             pParticle->CMNode.ulNodeType = ELEMENTPARTICLE_NAME;
    775             xstrInitCopy(&pParticle->CMNode.strNodeName, pModel->name, 0);
     926            pParticle->NodeBase.ulNodeType = ELEMENTPARTICLE_NAME;
     927            xstrInitCopy(&pParticle->NodeBase.strNodeName, pModel->name, 0);
    776928            treeInsertNode(ppElementNamesTree,
    777                            &pParticle->CMNode.Tree,
    778                            CompareCMNodeNodes,
     929                           &pParticle->NodeBase.Tree,
     930                           CompareNodeBaseNodes,
    779931                           TRUE);       // allow duplicates here
    780932        break;
    781933
    782934        case XML_CTYPE_MIXED:
    783             pParticle->CMNode.ulNodeType = ELEMENTPARTICLE_MIXED;
     935            pParticle->NodeBase.ulNodeType = ELEMENTPARTICLE_MIXED;
    784936        break;
    785937
    786938        case XML_CTYPE_CHOICE:
    787             pParticle->CMNode.ulNodeType = ELEMENTPARTICLE_CHOICE;
     939            pParticle->NodeBase.ulNodeType = ELEMENTPARTICLE_CHOICE;
    788940        break;
    789941
    790942        case XML_CTYPE_SEQ:
    791             pParticle->CMNode.ulNodeType = ELEMENTPARTICLE_SEQ;
     943            pParticle->NodeBase.ulNodeType = ELEMENTPARTICLE_SEQ;
    792944        break;
    793945    }
     
    806958        {
    807959            PXMLCONTENT pSubModel = &pModel->children[ul];
    808             PCMELEMENTPARTICLE pSubNew
    809                 = (PCMELEMENTPARTICLE)malloc(sizeof(*pSubNew));
    810             if (!pSubNew)
    811                 arc = ERROR_NOT_ENOUGH_MEMORY;
    812             else
     960            PCMELEMENTPARTICLE pSubNew = NULL;
     961            arc = xmlCreateNodeBase(TYPE_UNKNOWN, //       node type... for now
     962                                    sizeof(CMELEMENTPARTICLE),
     963                                    0,
     964                                    0,
     965                                    (PNODEBASE*)&pSubNew);
     966            if (!arc)
    813967            {
    814                 memset(pSubNew, 0, sizeof(*pSubNew));
    815 
    816968                arc = SetupParticleAndSubs(pSubNew,
    817969                                           pSubModel,
     
    819971
    820972                if (!arc)
     973                {
    821974                    // no error: append sub-particle to this particle's
    822975                    // children list
    823976                    lstAppendItem(pParticle->pllSubNodes,
    824977                                  pSubNew);
     978                    // and store this particle as the parent in the
     979                    // sub-particle
     980                    pSubNew->pParentParticle = pParticle;
     981                }
    825982            }
    826983
     
    8471004{
    8481005    APIRET arc = NO_ERROR;
    849     PCMELEMENTDECLNODE pNew = (PCMELEMENTDECLNODE)malloc(sizeof(*pNew));
    850     if (!pNew)
    851         arc = ERROR_NOT_ENOUGH_MEMORY;
    852     else
    853     {
    854         memset(pNew, 0, sizeof(CMELEMENTDECLNODE));
    855 
    856         // pNew->Particle.CMNode.ulNodeType = ELEMENT_DECLARATION;
    857 
    858         xstrcpy(&pNew->Particle.CMNode.strNodeName, pcszName, 0);
    859 
     1006    PCMELEMENTDECLNODE pNew = NULL;
     1007
     1008    arc = xmlCreateNodeBase(TYPE_UNKNOWN,      // for now
     1009                            sizeof(CMELEMENTDECLNODE),
     1010                            pcszName,
     1011                            0,
     1012                            (PNODEBASE*)&pNew);
     1013
     1014    if (!arc)
     1015    {
    8601016        treeInit(&pNew->ParticleNamesTree);
    8611017
     
    8931049       )
    8941050    {
    895         pElementDecl = treeFindEQData(&pDocTypeNode->ElementDeclsTree,
     1051        pElementDecl = (PCMELEMENTDECLNODE)treeFindEQData(
     1052                                      &pDocTypeNode->ElementDeclsTree,
    8961053                                      (void*)pstrElementName->psz,
    897                                       CompareCMNodeData);
     1054                                      CompareNodeBaseData);
    8981055    }
    8991056
     
    9031060/*
    9041061 *@@ xmlFindAttribDeclBase:
    905  *      returns the _CMATTRIBUTEDEDECLBASE for the specified
     1062 *      returns the _CMATTRIBUTEDECLBASE for the specified
    9061063 *      element name, or NULL if none exists.
    9071064 *
     
    9131070 */
    9141071
    915 PCMATTRIBUTEDEDECLBASE xmlFindAttribDeclBase(PXMLDOM pDom,
     1072PCMATTRIBUTEDECLBASE xmlFindAttribDeclBase(PXMLDOM pDom,
    9161073                                             const XSTRING *pstrElementName)
    9171074{
    918     PCMATTRIBUTEDEDECLBASE pAttribDeclBase = NULL;
     1075    PCMATTRIBUTEDECLBASE pAttribDeclBase = NULL;
    9191076
    9201077    PDOMDOCTYPENODE pDocTypeNode = pDom->pDocTypeNode;
     
    9241081       )
    9251082    {
    926         pAttribDeclBase = treeFindEQData(&pDocTypeNode->AttribDeclBasesTree,
    927                                          (void*)pstrElementName->psz,
    928                                          CompareCMNodeData);
     1083        pAttribDeclBase = (PCMATTRIBUTEDECLBASE)treeFindEQData(
     1084                                        &pDocTypeNode->AttribDeclBasesTree,
     1085                                        (void*)pstrElementName->psz,
     1086                                        CompareNodeBaseData);
    9291087    }
    9301088
     
    9421100PCMATTRIBUTEDECL xmlFindAttribDecl(PXMLDOM pDom,
    9431101                                   const XSTRING *pstrElementName,
    944                                    const XSTRING *pstrAttribName)
     1102                                   const XSTRING *pstrAttribName,
     1103                                   PCMATTRIBUTEDECLBASE *ppAttribDeclBase)
     1104                                            // in/out: attr decl base cache;
     1105                                            // the pointer pointed to by this
     1106                                            // must be NULL on the first call
    9451107{
    9461108    PCMATTRIBUTEDECL pAttribDecl = NULL;
    9471109    if (pstrElementName && pstrAttribName)
    9481110    {
    949         PCMATTRIBUTEDEDECLBASE pAttribDeclBase = xmlFindAttribDeclBase(pDom,
    950                                                                        pstrElementName);
    951         if (pAttribDeclBase)
    952         {
    953             pAttribDecl = treeFindEQData(&pAttribDeclBase->AttribDeclsTree,
     1111        if (!*ppAttribDeclBase)
     1112            // first call for this:
     1113            *ppAttribDeclBase = xmlFindAttribDeclBase(pDom,
     1114                                                      pstrElementName);
     1115        if (*ppAttribDeclBase)
     1116        {
     1117            pAttribDecl = (PCMATTRIBUTEDECL)treeFindEQData(
     1118                                         &((**ppAttribDeclBase).AttribDeclsTree),
    9541119                                         (void*)pstrAttribName->psz,
    955                                          CompareCMNodeData);
     1120                                         CompareNodeBaseData);
    9561121        }
    9571122    }
     
    9611126
    9621127/*
    963  *@@ ValidateElement:
    964  *      validates the specified element against the document's
    965  *      @DTD.
     1128 *@@ ValidateElementChildren
     1129 *      validates the specified element against the document's @DTD,
     1130 *      more specifically, against the element declaration of the
     1131 *      new element's parent.
    9661132 *
    9671133 *      This sets arcDOM in XMLDOM on errors.
     
    9701136 *      is a declaration matching the element declaration where the
    9711137 *      element's name matches the element type, and _one_ of the
    972  *      following holds: ###
    973  *
    974  *      (1) The declaration matches EMPTY and the element has no @content.
     1138 *      following holds:
     1139 *
     1140 *      (1) The declaration matches EMPTY and the element has no @content. (done)
    9751141 *
    9761142 *      (2) The declaration matches (children) (see @element_declaration)
     
    9811147 *          child element and the end-tag. Note that a CDATA section
    9821148 *          is never considered "whitespace", even if it contains
    983  *          white space only.
     1149 *          white space only. @@todo
    9841150 *
    9851151 *      (3) The declaration matches (mixed) (see @element_declaration)
    9861152 *          and the content consists of @content and child elements
    987  *          whose types match names in the content model.
     1153 *          whose types match names in the content model. (done)
    9881154 *
    9891155 *      (4) The declaration matches ANY, and the types of any child
    9901156 *          elements have been declared. (done)
    9911157 *
     1158 *      Preconditions: The element must already have been inserted
     1159 *      into the parent element's list, or we cannot validate sequences.
     1160 *
    9921161 *@@added V0.9.9 (2001-02-16) [umoeller]
    9931162 */
    9941163
    9951164VOID ValidateElement(PXMLDOM pDom,
    996                      PDOMNODE pElement)
    997 {
     1165                     PDOMNODE pNewElement,     // in: new element
     1166                     PCMELEMENTDECLNODE pParentElementDecl)
     1167                                               // in: element decl of element's parent
     1168{
     1169    if (pDom && pNewElement)
     1170    {
     1171        if (!pParentElementDecl)
     1172        {
     1173            // this is always missing for the root element, of course,
     1174            // because the parent is the document
     1175            if (pNewElement->pParentNode == (PDOMNODE)pDom->pDocumentNode)
     1176                return;     // that's OK
     1177            else
     1178                pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
     1179        }
     1180        else
     1181        {
     1182            ULONG ulDeclType = pParentElementDecl->Particle.NodeBase.ulNodeType;
     1183
     1184            switch (ulDeclType)
     1185            {
     1186                case ELEMENTPARTICLE_EMPTY:
     1187                    // this is an error for sure
     1188                    xmlSetError(pDom,
     1189                                ERROR_DOM_SUBELEMENT_IN_EMPTY_ELEMENT,
     1190                                pNewElement->NodeBase.strNodeName.psz,
     1191                                TRUE);
     1192                break;
     1193
     1194                case ELEMENTPARTICLE_ANY:
     1195                    // that's always OK
     1196                break;
     1197
     1198                case ELEMENTPARTICLE_MIXED:
     1199                case ELEMENTPARTICLE_CHOICE:
     1200                case ELEMENTPARTICLE_SEQ:
     1201                {
     1202                    const char *pcszNewElementName
     1203                        = pNewElement->NodeBase.strNodeName.psz;
     1204
     1205                    // for all these, we first need to check if
     1206                    // the element is allowed at all
     1207                    PCMELEMENTPARTICLE pParticle
     1208                        = (PCMELEMENTPARTICLE)treeFindEQData(
     1209                                         &pParentElementDecl->ParticleNamesTree,
     1210                                         (void*)pcszNewElementName,
     1211                                         CompareNodeBaseData);
     1212                    if (!pParticle)
     1213                        // not found: then this element is not allowed within this
     1214                        // parent
     1215                        xmlSetError(pDom,
     1216                                    ERROR_DOM_INVALID_SUBELEMENT,
     1217                                    pcszNewElementName,
     1218                                    TRUE);
     1219                    else
     1220                    {
     1221                        // the element is allowed at all: now check for the
     1222                        // lists case...
     1223                        switch (ulDeclType)
     1224                        {
     1225                            case ELEMENTPARTICLE_CHOICE:
     1226                            break;
     1227
     1228                            case ELEMENTPARTICLE_SEQ:
     1229                            break;
     1230                        }
     1231                    }
     1232
     1233                break; }
     1234            }
     1235        }
     1236    }
     1237    else
     1238        pDom->arcDOM = ERROR_INVALID_PARAMETER;
     1239
    9981240    // yes: get the element decl from the tree
    999     PCMELEMENTDECLNODE pElementDecl = xmlFindElementDecl(pDom,
     1241    /* PCMELEMENTDECLNODE pElementDecl = xmlFindElementDecl(pDom,
    10001242                                                         &pElement->NodeBase.strNodeName);
    10011243    if (!pElementDecl)
     
    10511293                        = treeFindEQData(&pParentElementDecl->ParticleNamesTree,
    10521294                                         (void*)pElement->NodeBase.strNodeName.psz,
    1053                                          CompareCMNodeData);
     1295                                         CompareNodeBaseData);
    10541296                    if (!pParticle)
    10551297                        // not found: then this element is not allowed within this
     
    10631305        }
    10641306    }
    1065 }
    1066 
    1067 /*
    1068  *@@ ValidateAttribute:
    1069  *      validates the specified element against the document's
    1070  *      @DTD.
     1307    */
     1308}
     1309
     1310/*
     1311 *@@ ValidateAttributeType:
     1312 *      validates the specified attribute's type against the
     1313 *      document's @DTD.
    10711314 *
    10721315 *      This sets arcDOM in XMLDOM on errors.
     
    10751318 */
    10761319
    1077 VOID ValidateAttribute(PXMLDOM pDom,
    1078                        PDOMNODE pAttrib)
     1320VOID ValidateAttributeType(PXMLDOM pDom,
     1321                           PDOMNODE pAttrib,
     1322                           PCMATTRIBUTEDECLBASE *ppAttribDeclBase)
    10791323{
    10801324    PDOMNODE pElement = pAttrib->pParentNode;
     
    10821326    PCMATTRIBUTEDECL pAttribDecl = xmlFindAttribDecl(pDom,
    10831327                                                     &pElement->NodeBase.strNodeName,
    1084                                                      &pAttrib->NodeBase.strNodeName);
     1328                                                     &pAttrib->NodeBase.strNodeName,
     1329                                                     ppAttribDeclBase);
    10851330    if (!pAttribDecl)
    10861331        xmlSetError(pDom,
     
    10881333                    pAttrib->NodeBase.strNodeName.psz,
    10891334                    TRUE);
     1335    else
     1336    {
     1337        // check if the attribute value is allowed
     1338        switch (pAttribDecl->ulAttrType)
     1339        {
     1340            case CMAT_CDATA:
     1341            case CMAT_ID:
     1342            case CMAT_IDREF:
     1343            case CMAT_IDREFS:       // ###
     1344            case CMAT_ENTITY:
     1345            case CMAT_ENTITIES:
     1346            case CMAT_NMTOKEN:
     1347            case CMAT_NMTOKENS:
     1348            break;
     1349
     1350            case CMAT_ENUM:
     1351            {
     1352                // enumeration: then check if it has one of the
     1353                // allowed values
     1354                PNODEBASE pValue = (PNODEBASE)treeFindEQData(
     1355                                                &pAttribDecl->ValuesTree,
     1356                                                (void*)pAttrib->pstrNodeValue->psz,
     1357                                                CompareNodeBaseData);
     1358                if (!pValue)
     1359                    xmlSetError(pDom,
     1360                                ERROR_DOM_INVALID_ATTRIB_VALUE,
     1361                                pAttrib->NodeBase.strNodeName.psz,
     1362                                TRUE);
     1363            }
     1364        }
     1365
     1366        if (pAttribDecl->ulConstraint == CMAT_FIXED_VALUE)
     1367            if (strcmp(pAttrib->pstrNodeValue->psz, pAttribDecl->pstrDefaultValue->psz))
     1368                // fixed value doesn't match:
     1369                xmlSetError(pDom,
     1370                            ERROR_DOM_INVALID_ATTRIB_VALUE,
     1371                            pAttrib->NodeBase.strNodeName.psz,
     1372                            TRUE);
     1373    }
     1374}
     1375
     1376/*
     1377 *@@ ValidateAllAttributes:
     1378 *      validates the constraints of all attributes of the specified
     1379 *      element against the document's @DTD.
     1380 *
     1381 *@@added V0.9.9 (2001-02-16) [umoeller]
     1382 */
     1383
     1384VOID ValidateAllAttributes(PXMLDOM pDom,
     1385                           PCMATTRIBUTEDECLBASE pAttribDeclBase,
     1386                           PDOMNODE pNewElement)
     1387{
     1388    PCMATTRIBUTEDECL pDeclThis
     1389        = (PCMATTRIBUTEDECL)treeFirst(pAttribDeclBase->AttribDeclsTree);
     1390
     1391    while ((pDeclThis) && (!pDom->arcDOM))
     1392    {
     1393        // if attribute is all optional: then we don't need
     1394        // to check for whether it's here
     1395        if (    (pDeclThis->ulConstraint != CMAT_IMPLIED)
     1396             && (pDeclThis->ulConstraint != CMAT_DEFAULT_VALUE)
     1397                    // we don't have to check this case because expat
     1398                    // already adds default attributes for us
     1399           )
     1400        {
     1401            // for all others , we need to find the attribute
     1402            PSZ pszAttrNameThis = pDeclThis->NodeBase.strNodeName.psz;
     1403            PDOMNODE pAttrNode = (PDOMNODE)treeFindEQData(
     1404                                            &pNewElement->AttributesMap,
     1405                                            (void*)pszAttrNameThis,
     1406                                            CompareNodeBaseData);
     1407
     1408            // now switch again
     1409            switch (pDeclThis->ulConstraint)
     1410            {
     1411                case CMAT_REQUIRED:
     1412                    if (!pAttrNode)
     1413                        // required, but no attribute with this name exists:
     1414                        xmlSetError(pDom,
     1415                                    ERROR_DOM_REQUIRED_ATTRIBUTE_MISSING,
     1416                                    pszAttrNameThis,
     1417                                    TRUE);
     1418                break;
     1419            }
     1420        }
     1421
     1422        pDeclThis = (PCMATTRIBUTEDECL)treeNext((TREE*)pDeclThis);
     1423    }
     1424}
     1425
     1426/* ******************************************************************
     1427 *
     1428 *   Expat stack
     1429 *
     1430 ********************************************************************/
     1431
     1432/*
     1433 *@@ DOMSTACKITEM:
     1434 *
     1435 *@@added V0.9.9 (2001-02-16) [umoeller]
     1436 */
     1437
     1438typedef struct _DOMSTACKITEM
     1439{
     1440    PDOMNODE                pDomNode;
     1441    PCMELEMENTDECLNODE      pElementDecl;
     1442
     1443} DOMSTACKITEM, *PDOMSTACKITEM;
     1444
     1445/*
     1446 *@@ PopElementStack:
     1447 *
     1448 *      NOTE:
     1449 *
     1450 *@@added V0.9.9 (2001-02-16) [umoeller]
     1451 */
     1452
     1453PDOMSTACKITEM PopElementStack(PXMLDOM pDom,
     1454                              PLISTNODE *ppListNode)
     1455{
     1456    PDOMSTACKITEM   pStackItem = NULL;
     1457    PLISTNODE       pParentLN = lstPop(&pDom->llElementStack);
     1458
     1459    if (!pParentLN)
     1460        pDom->arcDOM = ERROR_DOM_NO_ELEMENT;
     1461    else
     1462    {
     1463        // we have at least one node:
     1464        pStackItem = (PDOMSTACKITEM)pParentLN->pItemData;
     1465
     1466        if (ppListNode)
     1467            *ppListNode = pParentLN;
     1468    }
     1469
     1470    return (pStackItem);
     1471}
     1472
     1473/*
     1474 *@@ PushElementStack:
     1475 *
     1476 *      NOTE: pDomNode will most frequently be an element
     1477 *      node, but will also be the document for root and
     1478 *      a DOCTYPE node while parsing the DTD.
     1479 *
     1480 *@@added V0.9.9 (2001-02-16) [umoeller]
     1481 */
     1482
     1483VOID PushElementStack(PXMLDOM pDom,
     1484                      PDOMNODE pDomNode)
     1485{
     1486    PDOMSTACKITEM pNew = (PDOMSTACKITEM)malloc(sizeof(*pNew));
     1487    if (!pNew)
     1488        pDom->arcDOM = ERROR_NOT_ENOUGH_MEMORY;
     1489    else
     1490    {
     1491        memset(pNew, 0, sizeof(*pNew));
     1492        pNew->pDomNode = pDomNode;
     1493
     1494        // shall we validate?
     1495        if (    (pDom->pDocTypeNode)
     1496             && (pDomNode->NodeBase.ulNodeType == DOMNODE_ELEMENT)
     1497           )
     1498            pNew->pElementDecl = xmlFindElementDecl(pDom,
     1499                                                    &pDomNode->NodeBase.strNodeName);
     1500
     1501        lstPush(&pDom->llElementStack,
     1502                pNew);
     1503    }
    10901504}
    10911505
     
    11181532        ULONG       i;
    11191533
    1120         PDOMNODE    pParent = NULL,
    1121                     pNew = NULL;
    1122 
    1123         PLISTNODE   pParentNode = lstPop(&pDom->llStack);
    1124 
    1125         if (!pParentNode)
    1126             pDom->arcDOM = ERROR_DOM_NO_DOCUMENT;
    1127         else
    1128         {
    1129             // we have at least one node:
    1130             pParent = (PDOMNODE)pParentNode->pItemData;
     1534        PDOMSTACKITEM pSI = PopElementStack(pDom,
     1535                                            NULL);     // no free
     1536        if (!pDom->arcDOM)
     1537        {
     1538            PDOMNODE    pParent = pSI->pDomNode,
     1539                        pNew = NULL;
    11311540
    11321541            pDom->arcDOM = xmlCreateElementNode(pParent,
     
    11351544
    11361545            if (!pDom->arcDOM)
     1546                // OK, node is valid:
     1547                // push this on the stack so we can add child elements
     1548                PushElementStack(pDom,
     1549                                 pNew);
     1550
     1551            // shall we validate?
     1552            if (    (!pDom->arcDOM)
     1553                 && (pDom->pDocTypeNode)
     1554               )
     1555                ValidateElement(pDom,
     1556                                pNew,                // new element
     1557                                pSI->pElementDecl);  // parent's elem decl
     1558
     1559            if (!pDom->arcDOM)
    11371560            {
     1561                PCMATTRIBUTEDECLBASE pAttribDeclBase = NULL;
     1562
     1563                // shall we validate?
     1564                if (pDom->pDocTypeNode)
     1565                    // yes: get attrib decl base for speed
     1566                    pAttribDeclBase
     1567                        = xmlFindAttribDeclBase(pDom,
     1568                                                &pNew->NodeBase.strNodeName);
     1569
     1570                // now for the attribs
     1571                for (i = 0;
     1572                     (papcszAttribs[i]) && (!pDom->arcDOM);
     1573                     i += 2)
     1574                {
     1575                    PDOMNODE pAttrib;
     1576                    pDom->arcDOM = xmlCreateAttributeNode(pNew,                    // element,
     1577                                                          papcszAttribs[i],        // attr name
     1578                                                          papcszAttribs[i + 1],    // attr value
     1579                                                          &pAttrib);
     1580
     1581                    // shall we validate?
     1582                    if (pDom->pDocTypeNode)
     1583                        ValidateAttributeType(pDom,
     1584                                              pAttrib,
     1585                                              &pAttribDeclBase);
     1586                }
     1587
     1588                // OK, now we got all attributes:
     1589                // now look for defaults in the DTD,
     1590                // if we shall validate
     1591                if (    (pDom->pDocTypeNode)
     1592                     && (!pDom->arcDOM)
     1593                     && (pAttribDeclBase)
     1594                   )
     1595                    ValidateAllAttributes(pDom,
     1596                                          pAttribDeclBase,
     1597                                          pNew);
     1598            }
     1599        }
     1600
     1601        pDom->pLastWasTextNode = NULL;
     1602    }
     1603}
     1604
     1605/*
     1606 *@@ EndElementHandler:
     1607 *      @expat handler for when parsing an element is done.
     1608 *      We pop the element off of our stack then.
     1609 */
     1610
     1611void EXPATENTRY EndElementHandler(void *pUserData,      // in: our PXMLDOM really
     1612                                  const XML_Char *name)
     1613{
     1614    PXMLDOM     pDom = (PXMLDOM)pUserData;
     1615    // continue parsing only if we had no errors so far
     1616    if (!pDom->arcDOM)
     1617    {
     1618        PLISTNODE pStackLN = NULL;
     1619        PDOMSTACKITEM pSI = PopElementStack(pDom,
     1620                                            &pStackLN);
     1621
     1622        if (!pDom->arcDOM)
     1623        {
     1624            // shall we validate?
     1625            /* if (pDom->pDocTypeNode)
     1626                // yes:
     1627                ValidateElementChildren(pDom,
     1628                                        pSI->pDomNode); */
     1629
     1630            lstRemoveNode(&pDom->llElementStack, pStackLN); // auto-free
     1631        }
     1632        else
     1633            pDom->arcDOM = ERROR_DOM_INTEGRITY;
     1634
     1635        pDom->pLastWasTextNode = NULL;
     1636    }
     1637}
     1638
     1639/*
     1640 *@@ CharacterDataHandler:
     1641 *      @expat handler for character data (@content).
     1642 *
     1643 *      Note: expat passes chunks of content without zero-terminating
     1644 *      them. We must concatenate the chunks to a full text node.
     1645 */
     1646
     1647void EXPATENTRY CharacterDataHandler(void *pUserData,      // in: our PXMLDOM really
     1648                                     const XML_Char *s,
     1649                                     int len)
     1650{
     1651    PXMLDOM     pDom = (PXMLDOM)pUserData;
     1652
     1653    // continue parsing only if we had no errors so far
     1654    if (!pDom->arcDOM)
     1655    {
     1656        ULONG       i;
     1657
     1658        if (len)
     1659        {
     1660            // we need a new text node:
     1661            PDOMSTACKITEM pSI = PopElementStack(pDom,
     1662                                                NULL);     // no free
     1663            if (!pDom->arcDOM)
     1664            {
     1665                PDOMNODE    pParent = pSI->pDomNode,
     1666                            pNew = NULL;
     1667
    11381668                // shall we validate?
    11391669                if (pDom->pDocTypeNode)
    11401670                {
    1141                     // yes:
    1142                     ValidateElement(pDom,
    1143                                     pNew);
    1144                 }
    1145 
    1146                 if (!pDom->arcDOM)
    1147                 {
    1148                     // OK, node is valid:
    1149                     // push this on the stack so we can add child elements
    1150                     lstPush(&pDom->llStack, pNew);
    1151 
    1152                     // now for the attribs
    1153                     for (i = 0;
    1154                          (papcszAttribs[i]) && (!pDom->arcDOM);
    1155                          i += 2)
     1671                    // yes: check if the parent element allows
     1672                    // for content at all (must be "mixed" model)
     1673
     1674                    // get the element decl from the tree
     1675                    PCMELEMENTDECLNODE pElementDecl = pSI->pElementDecl;
     1676
     1677                    if (pElementDecl)
    11561678                    {
    1157                         PDOMNODE pAttrib;
    1158 
    1159                         pDom->arcDOM = xmlCreateAttributeNode(pNew,                    // element,
    1160                                                               papcszAttribs[i],        // attr name
    1161                                                               papcszAttribs[i + 1],    // attr value
    1162                                                               &pAttrib);
    1163 
    1164                         // shall we validate?
    1165                         if (pDom->pDocTypeNode)
     1679                        switch (pElementDecl->Particle.NodeBase.ulNodeType)
    11661680                        {
    1167                             ValidateAttribute(pDom,
    1168                                               pAttrib);
     1681                            case ELEMENTPARTICLE_ANY:
     1682                            case ELEMENTPARTICLE_MIXED:
     1683                                // those two are okay
     1684                            break;
     1685
     1686                            case ELEMENTPARTICLE_EMPTY:
     1687                                // that's an error for sure
     1688                                pDom->arcDOM = ERROR_ELEMENT_CANNOT_HAVE_CONTENT;
     1689                            break;
     1690
     1691                            default:
     1692                            {
     1693                                // ELEMENTPARTICLE_CHOICE:
     1694                                // ELEMENTPARTICLE_SEQ:
     1695                                // with these two, we accept whitespace, but nothing
     1696                                // else... so if we have characters other than
     1697                                // whitespace, terminate
     1698                                ULONG ul;
     1699                                const char *p = s;
     1700                                for (ul = 0;
     1701                                     ul < len;
     1702                                     ul++, p++)
     1703                                    if (!strchr("\r\n\t ", *p))
     1704                                    {
     1705                                        // other character:
     1706                                        xmlSetError(pDom,
     1707                                                    ERROR_ELEMENT_CANNOT_HAVE_CONTENT,
     1708                                                    pParent->NodeBase.strNodeName.psz,
     1709                                                    TRUE);
     1710                                        break;
     1711                                    }
     1712                            }
    11691713                        }
    11701714                    }
    11711715                }
     1716
     1717                if (pDom->pLastWasTextNode)
     1718                {
     1719                    // we had a text node, and no elements or other
     1720                    // stuff in between:
     1721                    xstrcat(pDom->pLastWasTextNode->pstrNodeValue,
     1722                            s,
     1723                            len);
     1724                }
     1725                else
     1726                {
     1727                    pDom->arcDOM = xmlCreateTextNode(pParent,
     1728                                                     s,
     1729                                                     len,
     1730                                                     &pDom->pLastWasTextNode);
     1731                }
    11721732            }
    11731733        }
    1174 
    1175         pDom->pLastWasTextNode = NULL;
    1176     }
    1177 }
    1178 
    1179 /*
    1180  *@@ EndElementHandler:
    1181  *      @expat handler for when parsing an element is done.
    1182  *      We pop the element off of our stack then.
    1183  */
    1184 
    1185 void EXPATENTRY EndElementHandler(void *pUserData,      // in: our PXMLDOM really
    1186                                   const XML_Char *name)
     1734    }
     1735}
     1736
     1737/*
     1738 *@@ CommentHandler:
     1739 *      @expat handler for @comments.
     1740 *
     1741 *      Note: This is only set if DF_PARSECOMMENTS is
     1742 *      flagged with xmlCreateDOM.
     1743 *
     1744 *@@added V0.9.9 (2001-02-14) [umoeller]
     1745 */
     1746
     1747void EXPATENTRY CommentHandler(void *pUserData,      // in: our PXMLDOM really
     1748                               const XML_Char *data)
    11871749{
    11881750    PXMLDOM     pDom = (PXMLDOM)pUserData;
     1751
    11891752    // continue parsing only if we had no errors so far
    11901753    if (!pDom->arcDOM)
    11911754    {
    1192         PLISTNODE   pNode = lstPop(&pDom->llStack);
    1193         if (pNode)
    1194             lstRemoveNode(&pDom->llStack, pNode);
    1195 
    1196         pDom->pLastWasTextNode = NULL;
    1197     }
    1198 }
    1199 
    1200 /*
    1201  *@@ CharacterDataHandler:
    1202  *      @expat handler for character data (@content).
    1203  *
    1204  *      Note: expat passes chunks of content without zero-terminating
    1205  *      them. We must concatenate the chunks to a full text node.
    1206  */
    1207 
    1208 void EXPATENTRY CharacterDataHandler(void *pUserData,      // in: our PXMLDOM really
    1209                                      const XML_Char *s,
    1210                                      int len)
    1211 {
    1212     PXMLDOM     pDom = (PXMLDOM)pUserData;
    1213 
    1214     // continue parsing only if we had no errors so far
    1215     if (!pDom->arcDOM)
    1216     {
    1217         ULONG       i;
    1218 
    1219         if (len)
    1220         {
    1221             if (pDom->pLastWasTextNode)
    1222             {
    1223                 // we had a text node, and no elements or other
    1224                 // stuff in between:
    1225                 xstrcat(pDom->pLastWasTextNode->pstrNodeValue,
    1226                         s,
    1227                         len);
    1228             }
    1229             else
    1230             {
    1231                 // we need a new text node:
    1232                 PDOMNODE pNew,
    1233                          pParent;
    1234                 // non-root level:
    1235                 PLISTNODE pParentNode = lstPop(&pDom->llStack);
    1236                 pParent = (PDOMNODE)pParentNode->pItemData;
    1237 
    1238                 pDom->arcDOM = xmlCreateTextNode(pParent,
    1239                                                  s,
    1240                                                  len,
    1241                                                  &pDom->pLastWasTextNode);
    1242             }
    1243         }
    1244     }
    1245 }
    1246 
    1247 /*
    1248  *@@ CommentHandler:
    1249  *      @expat handler for @comments.
    1250  *
    1251  *      Note: This is only set if DF_PARSECOMMENTS is
    1252  *      flagged with xmlCreateDOM.
    1253  *
    1254  *@@added V0.9.9 (2001-02-14) [umoeller]
    1255  */
    1256 
    1257 void EXPATENTRY CommentHandler(void *pUserData,      // in: our PXMLDOM really
    1258                                const XML_Char *data)
    1259 {
    1260     PXMLDOM     pDom = (PXMLDOM)pUserData;
    1261 
    1262     // continue parsing only if we had no errors so far
    1263     if (!pDom->arcDOM)
    1264     {
    1265         PLISTNODE   pParentNode = lstPop(&pDom->llStack);
    1266 
    1267         if (pParentNode)
    1268         {
    1269             // non-root level:
    1270             PDOMNODE pParent = (PDOMNODE)pParentNode->pItemData;
    1271             PDOMNODE pComment;
     1755        // we need a new text node:
     1756        PDOMSTACKITEM pSI = PopElementStack(pDom,
     1757                                            NULL);     // no free
     1758        if (!pDom->arcDOM)
     1759        {
     1760            PDOMNODE    pParent = pSI->pDomNode,
     1761                        pNew = NULL;
    12721762
    12731763            pDom->arcDOM = xmlCreateCommentNode(pParent,
    12741764                                                data,
    1275                                                 &pComment);
     1765                                                &pNew);
    12761766        }
    12771767    }
     
    13071797        else
    13081798        {
    1309             pDom->arcDOM = xmlCreateDocumentTypeNode(pDocumentNode,
    1310                                                      pcszDoctypeName,
    1311                                                      pcszSysid,
    1312                                                      pcszPubid,
    1313                                                      fHasInternalSubset,
    1314                                                      &pDom->pDocTypeNode);
    1315 
    1316             // push this on the stack so we can add child elements
    1317             lstPush(&pDom->llStack, pDom->pDocTypeNode);
     1799            // doctype must be null
     1800            if (pDom->pDocTypeNode)
     1801                pDom->arcDOM = ERROR_DOM_DUPLICATE_DOCTYPE;
     1802            else
     1803            {
     1804                pDom->arcDOM = xmlCreateDocumentTypeNode(pDocumentNode,
     1805                                                         pcszDoctypeName,
     1806                                                         pcszSysid,
     1807                                                         pcszPubid,
     1808                                                         fHasInternalSubset,
     1809                                                         &pDom->pDocTypeNode);
     1810            }
    13181811        }
    13191812    }
     
    13321825    PXMLDOM     pDom = (PXMLDOM)pUserData;
    13331826
    1334     PLISTNODE pListNode = lstPop(&pDom->llStack);
    1335     if (!pListNode)
    1336         pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
    1337     else
    1338     {
    1339         PDOMNODE pDomNode = (PDOMNODE)pListNode->pItemData;
    1340         if (pDomNode->NodeBase.ulNodeType != DOMNODE_DOCUMENT_TYPE)
     1827    // continue parsing only if we had no errors so far
     1828    /* if (!pDom->arcDOM)
     1829    {
     1830        PLISTNODE pStackLN = NULL;
     1831        PDOMSTACKITEM pSI = PopElementStack(pDom,
     1832                                            &pStackLN);
     1833
     1834        if (pDom->arcDOM)
    13411835            pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
    1342 
    1343         lstRemoveNode(&pDom->llStack, pListNode);
    1344     }
    1345 
    1346     // continue parsing only if we had no errors so far
    1347     if (!pDom->arcDOM)
    1348     {
    1349 
    1350     }
     1836        else
     1837        {
     1838            if (pSI->pDomNode->NodeBase.ulNodeType != DOMNODE_DOCUMENT_TYPE)
     1839                pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
     1840
     1841            lstRemoveNode(&pDom->llElementStack, pStackLN); // auto-free
     1842        }
     1843    } */
    13511844}
    13521845
     
    13541847 *@@ NotationDeclHandler:
    13551848 *      @expat handler for @notation_declarations.
     1849 *
     1850 *      ###
    13561851 *
    13571852 *@@added V0.9.9 (2001-02-14) [umoeller]
     
    13931888 *
    13941889 *      The pcszSystemId is the system identifier specified in the
    1395  *      entity declaration and is never null.
     1890 *      entity declaration and is never null. This is an exact copy
     1891 *      of what was specified in the reference.
    13961892 *
    13971893 *      There are a couple of ways in which this handler differs
     
    14301926                                        const XML_Char *pcszPublicId)
    14311927{
    1432     int i = 1;
     1928    int i = 0;
     1929
     1930    FILE *f = fopen("log", "w");
     1931    fprintf(f, "sysid: %s\n", pcszSystemId);
     1932    fclose(f);
    14331933
    14341934    /* PXMLDOM     pDom = (PXMLDOM)pUserData;
     
    14671967    if (!pDom->arcDOM)
    14681968    {
    1469         // pop the last DOMNODE off the stack and check if it's a DOCTYPE
    1470         PLISTNODE pListNode = lstPop(&pDom->llStack);
    1471         if (!pListNode)
     1969        // OK, we're in a DOCTYPE node:
     1970        PDOMDOCTYPENODE pDocType = pDom->pDocTypeNode;
     1971        if (!pDocType)
    14721972            pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
    14731973        else
    14741974        {
    1475             PDOMNODE pDomNode = (PDOMNODE)pListNode->pItemData;
    1476             if (pDomNode->NodeBase.ulNodeType != DOMNODE_DOCUMENT_TYPE)
    1477                 pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
    1478             else
     1975            // create an element declaration and push it unto the
     1976            // declarations tree
     1977            PCMELEMENTDECLNODE pNew = NULL;
     1978            pDom->arcDOM = xmlCreateElementDecl(pcszName,
     1979                                                pModel,
     1980                                                &pNew);
     1981                                    // this recurses!!
     1982                                    // after this, pModel is invalid
     1983
     1984            if (pDom->arcDOM == NO_ERROR)
    14791985            {
    1480                 // OK, we're in a DOCTYPE node:
    1481                 PDOMDOCTYPENODE pDocType = (PDOMDOCTYPENODE)pDomNode;
    1482 
    1483                 // create an element declaration and push it unto the
    1484                 // declarations tree
    1485                 PCMELEMENTDECLNODE pNew = NULL;
    1486                 pDom->arcDOM = xmlCreateElementDecl(pcszName,
    1487                                                     pModel,
    1488                                                     &pNew);
    1489                                         // this recurses!!
    1490 
    1491                 if (pDom->arcDOM == NO_ERROR)
    1492                 {
    1493                     // add this to the doctype's declarations tree
    1494                     if (treeInsertNode(&pDocType->ElementDeclsTree,
    1495                                        (TREE*)pNew,
    1496                                        CompareCMNodeNodes,
    1497                                        FALSE)
    1498                             == TREE_DUPLICATE)
    1499                         // element already declared:
    1500                         // according to the XML specs, this is a validity
    1501                         // constraint, so we report a validation error
    1502                         xmlSetError(pDom,
    1503                                     ERROR_DOM_DUPLICATE_ELEMENT_DECL,
    1504                                     pNew->Particle.CMNode.strNodeName.psz,
    1505                                     TRUE);
    1506                 }
     1986                // add this to the doctype's declarations tree
     1987                if (treeInsertNode(&pDocType->ElementDeclsTree,
     1988                                   (TREE*)pNew,
     1989                                   CompareNodeBaseNodes,
     1990                                   FALSE)
     1991                        == TREE_DUPLICATE)
     1992                    // element already declared:
     1993                    // according to the XML specs, this is a validity
     1994                    // constraint, so we report a validation error
     1995                    xmlSetError(pDom,
     1996                                ERROR_DOM_DUPLICATE_ELEMENT_DECL,
     1997                                pNew->Particle.NodeBase.strNodeName.psz,
     1998                                TRUE);
    15071999            }
    15082000        }
     
    15162008 */
    15172009
    1518 VOID AddEnum(PCMATTRIBUTEDECL pNew,
    1519              const char *p,
    1520              const char *pNext)
    1521 {
    1522     PSZ pszType = strhSubstr(p, pNext);
    1523     PNODEBASE pCMNode = (PNODEBASE)malloc(sizeof(*pCMNode));
    1524     memset(pCMNode, 0, sizeof(*pCMNode));
    1525     pCMNode->ulNodeType = ATTRIBUTE_DECLARATION_ENUM;
    1526     xstrInitSet(&pCMNode->strNodeName, pszType);
    1527 
    1528     treeInsertNode(&pNew->ValuesTree,
    1529                    (TREE*)pCMNode,
    1530                    CompareCMNodeNodes,
    1531                    FALSE);
     2010APIRET AddEnum(PCMATTRIBUTEDECL pDecl,
     2011               const char *p,           // in: start of name
     2012               const char *pNext)       // in: end of name (not included)
     2013{
     2014    // PSZ pszType = strhSubstr(p, pNext);
     2015    PNODEBASE pNew = NULL;
     2016    APIRET arc = xmlCreateNodeBase(ATTRIBUTE_DECLARATION_ENUM,
     2017                                   sizeof(NODEBASE),
     2018                                   p,
     2019                                   (pNext - p),
     2020                                   &pNew);
     2021    if (!arc)
     2022        treeInsertNode(&pDecl->ValuesTree,
     2023                       (TREE*)pNew,
     2024                       CompareNodeBaseNodes,
     2025                       FALSE);
     2026
     2027    return (arc);
    15322028}
    15332029
     
    15722068    if (!pDom->arcDOM)
    15732069    {
    1574         // pop the last DOMNODE off the stack and check if it's a DOCTYPE
    1575         PLISTNODE pListNode = lstPop(&pDom->llStack);
    1576         if (!pListNode)
     2070        // OK, we're in a DOCTYPE node:
     2071        PDOMDOCTYPENODE pDocType = pDom->pDocTypeNode;
     2072        if (!pDocType)
    15772073            pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
    15782074        else
    15792075        {
    1580             PDOMNODE pDomNode = (PDOMNODE)pListNode->pItemData;
    1581             if (pDomNode->NodeBase.ulNodeType != DOMNODE_DOCUMENT_TYPE)
    1582                 pDom->arcDOM = ERROR_DOM_DOCTYPE_STRUCTURE;
    1583             else
     2076            PCMATTRIBUTEDECLBASE    pThis = NULL,
     2077                                    pCache = pDom->pAttListDeclCache;
     2078
     2079            // check if this is for the same attlist as the previous
     2080            // call (we cache the pointer for speed)
     2081            if (    (pCache)
     2082                 && (!strhcmp(pCache->NodeBase.strNodeName.psz,
     2083                              pcszElementName))
     2084               )
     2085                // this attdecl is for the same element:
     2086                // use that (we won't have to search the tree)
     2087                pThis = pDom->pAttListDeclCache;
     2088
     2089            if (!pThis)
    15842090            {
    1585                 // OK, we're in a DOCTYPE node:
    1586                 PDOMDOCTYPENODE pDocType = (PDOMDOCTYPENODE)pDomNode;
    1587                 PCMATTRIBUTEDEDECLBASE    pThis = NULL,
    1588                                         pCache = pDom->pAttListDeclCache;
    1589 
    1590                 // check if this is for the same attlist as the previous
    1591                 // call (we cache the pointer for speed)
    1592                 if (    (pCache)
    1593                      && (!strhcmp(pCache->CMNode.strNodeName.psz,
    1594                                   pcszElementName))
    1595                    )
    1596                     // this attdecl is for the same element:
    1597                     // use that (we won't have to search the tree)
    1598                     pThis = pDom->pAttListDeclCache;
     2091                // cache didn't match: look up attributes tree then
     2092                pThis = (PCMATTRIBUTEDECLBASE)treeFindEQData(
     2093                                    &pDocType->AttribDeclBasesTree,
     2094                                    (void*)pcszElementName,
     2095                                    CompareNodeBaseData);
    15992096
    16002097                if (!pThis)
    16012098                {
    1602                     // cache didn't match: look up attributes tree then
    1603                     pThis = treeFindEQData(&pDocType->AttribDeclBasesTree,
    1604                                            (void*)pcszElementName,
    1605                                            CompareCMNodeData);
    1606 
    1607                     if (!pThis)
     2099                    // still not found:
     2100                    // we need a new node then
     2101                    pDom->arcDOM = xmlCreateNodeBase(ATTRIBUTE_DECLARATION_BASE,
     2102                                                     sizeof(CMATTRIBUTEDECLBASE),
     2103                                                     pcszElementName,
     2104                                                     0,
     2105                                                     (PNODEBASE*)&pThis);
     2106                    if (!pDom->arcDOM)
    16082107                    {
    1609                         // still not found:
    1610                         // we need a new node then
    1611                         pThis = (PCMATTRIBUTEDEDECLBASE)malloc(sizeof(*pThis));
    1612                         if (!pThis)
    1613                             pDom->arcDOM = ERROR_NOT_ENOUGH_MEMORY;
    1614                         else
     2108                        // initialize the subtree
     2109                        treeInit(&pThis->AttribDeclsTree);
     2110
     2111                        treeInsertNode(&pDocType->AttribDeclBasesTree,
     2112                                       (TREE*)pThis,
     2113                                       CompareNodeBaseNodes,
     2114                                       FALSE);
     2115                    }
     2116                }
     2117
     2118                pDom->pAttListDeclCache = pThis;
     2119            }
     2120
     2121            if (pThis)
     2122            {
     2123                // pThis now has either an existing or a new CMATTRIBUTEDECLBASE;
     2124                // add a new attribute def (CMATTRIBUTEDEDECL) to that
     2125                PCMATTRIBUTEDECL  pNew = NULL;
     2126                pDom->arcDOM = xmlCreateNodeBase(ATTRIBUTE_DECLARATION,
     2127                                                 sizeof(CMATTRIBUTEDECL),
     2128                                                 pcszAttribName,
     2129                                                 0,
     2130                                                 (PNODEBASE*)&pNew);
     2131                if (!pDom->arcDOM)
     2132                {
     2133                    treeInit(&pNew->ValuesTree);
     2134
     2135                    // check the type... expat is too lazy to parse this for
     2136                    // us, so we must check manually. Expat only normalizes
     2137                    // the "type" string to kick out whitespace, so we get:
     2138                    // (TYPE1|TYPE2|TYPE3)
     2139                    if (*pcszAttribType == '(')
     2140                    {
     2141                        // enumeration:
     2142                        const char *p = pcszAttribType + 1,
     2143                                   *pNext;
     2144                        while (    (pNext = strchr(p, '|'))
     2145                                && (!pDom->arcDOM)
     2146                              )
    16152147                        {
    1616                             pThis->CMNode.ulNodeType = ATTRIBUTE_DECLARATION_BASE;
    1617                             xstrInitCopy(&pThis->CMNode.strNodeName, pcszElementName, 0);
    1618 
    1619                             // initialize the subtree
    1620                             treeInit(&pThis->AttribDeclsTree);
    1621 
    1622                             treeInsertNode(&pDocType->AttribDeclBasesTree,
    1623                                            (TREE*)pThis,
    1624                                            CompareCMNodeNodes,
    1625                                            FALSE);
     2148                            pDom->arcDOM = AddEnum(pNew, p, pNext);
     2149                            p = pNext + 1;
     2150                        }
     2151
     2152                        if (!pDom->arcDOM)
     2153                        {
     2154                            pNext = strchr(p, ')');
     2155                            AddEnum(pNew, p, pNext);
     2156
     2157                            pNew->ulAttrType = CMAT_ENUM;
    16262158                        }
    16272159                    }
    1628 
    1629                     pDom->pAttListDeclCache = pThis;
    1630                 }
    1631 
    1632                 if (pThis)
    1633                 {
    1634                     // pThis now has either an existing or a new CMATTRIBUTEDEDECLBASE;
    1635                     // add a new attribute def (CMATTRIBUTEDEDECL) to that
    1636                     PCMATTRIBUTEDECL  pNew = (PCMATTRIBUTEDECL)malloc(sizeof(*pNew));
    1637                     if (!pNew)
    1638                         pDom->arcDOM = ERROR_NOT_ENOUGH_MEMORY;
    1639                     else
     2160                    else if (!strcmp(pcszAttribType, "CDATA"))
     2161                        pNew->ulAttrType = CMAT_CDATA;
     2162                    else if (!strcmp(pcszAttribType, "ID"))
     2163                        pNew->ulAttrType = CMAT_ID;
     2164                    else if (!strcmp(pcszAttribType, "IDREF"))
     2165                        pNew->ulAttrType = CMAT_IDREF;
     2166                    else if (!strcmp(pcszAttribType, "IDREFS"))
     2167                        pNew->ulAttrType = CMAT_IDREFS;
     2168                    else if (!strcmp(pcszAttribType, "ENTITY"))
     2169                        pNew->ulAttrType = CMAT_ENTITY;
     2170                    else if (!strcmp(pcszAttribType, "ENTITIES"))
     2171                        pNew->ulAttrType = CMAT_ENTITIES;
     2172                    else if (!strcmp(pcszAttribType, "NMTOKEN"))
     2173                        pNew->ulAttrType = CMAT_NMTOKEN;
     2174                    else if (!strcmp(pcszAttribType, "NMTOKENS"))
     2175                        pNew->ulAttrType = CMAT_NMTOKENS;
     2176
     2177                    if (!pDom->arcDOM)
    16402178                    {
    1641                         memset(pNew, 0, sizeof(*pNew));
    1642                         pNew->CMNode.ulNodeType = ATTRIBUTE_DECLARATION;
    1643 
    1644                         xstrInitCopy(&pNew->CMNode.strNodeName,
    1645                                      pcszAttribName,
    1646                                      0);
    1647 
    1648                         // fill the other fields
    1649                         /* xstrInitCopy(&pNew->strType,
    1650                                      pcszAttribType,
    1651                                      0); */
    1652 
    1653                         treeInit(&pNew->ValuesTree);
    1654 
    1655                         // check the type... expat is too lazy to parse this for
    1656                         // us, so we must check manually. Expat only normalizes
    1657                         // the "type" string to kick out whitespace, so we get:
    1658                         // (TYPE1|TYPE2|TYPE3)
    1659                         if (*pcszAttribType == '(')
    1660                         {
    1661                             // enumeration:
    1662                             const char *p = pcszAttribType + 1,
    1663                                        *pNext;
    1664                             while (pNext = strchr(p, '|'))
    1665                             {
    1666                                 AddEnum(pNew, p, pNext);
    1667                                 p = pNext + 1;
    1668                             }
    1669 
    1670                             pNext = strchr(p, ')');
    1671                             AddEnum(pNew, p, pNext);
    1672 
    1673                             pNew->ulAttrType = CMAT_ENUM;
    1674                         }
    1675                         else if (!strcmp(pcszAttribType, "CDATA"))
    1676                             pNew->ulAttrType = CMAT_CDATA;
    1677                         else if (!strcmp(pcszAttribType, "ID"))
    1678                             pNew->ulAttrType = CMAT_ID;
    1679                         else if (!strcmp(pcszAttribType, "IDREF"))
    1680                             pNew->ulAttrType = CMAT_IDREF;
    1681                         else if (!strcmp(pcszAttribType, "IDREFS"))
    1682                             pNew->ulAttrType = CMAT_IDREFS;
    1683                         else if (!strcmp(pcszAttribType, "ENTITY"))
    1684                             pNew->ulAttrType = CMAT_ENTITY;
    1685                         else if (!strcmp(pcszAttribType, "ENTITIES"))
    1686                             pNew->ulAttrType = CMAT_ENTITIES;
    1687                         else if (!strcmp(pcszAttribType, "NMTOKEN"))
    1688                             pNew->ulAttrType = CMAT_NMTOKEN;
    1689                         else if (!strcmp(pcszAttribType, "NMTOKENS"))
    1690                             pNew->ulAttrType = CMAT_NMTOKENS;
    1691 
    16922179                        if (pcszDefault)
    16932180                        {
     
    17112198                        if (treeInsertNode(&pThis->AttribDeclsTree,
    17122199                                           (TREE*)pNew,
    1713                                            CompareCMNodeNodes,
     2200                                           CompareNodeBaseNodes,
    17142201                                           FALSE)
    17152202                                == TREE_DUPLICATE)
     
    18202307        memset(pDom, 0, sizeof(XMLDOM));
    18212308
    1822         lstInit(&pDom->llStack,
    1823                 FALSE);                 // no auto-free
     2309        lstInit(&pDom->llElementStack,
     2310                TRUE);                 // auto-free
    18242311
    18252312        // create the document node
    1826         arc = xmlCreateNode(NULL, // no parent
     2313        arc = xmlCreateDomNode(NULL, // no parent
    18272314                            DOMNODE_DOCUMENT,
     2315                            NULL,
     2316                            0,
    18282317                            &pDocument);
    18292318
     
    18352324            // push the document on the stack so the handlers
    18362325            // will append to that
    1837             lstPush(&pDom->llStack,
    1838                     pDom->pDocumentNode);
     2326            PushElementStack(pDom,
     2327                             pDocument);
    18392328
    18402329            pDom->pParser = XML_ParserCreate(NULL);
     
    19582447            if (pDom->pDocumentNode)
    19592448            {
    1960                 xmlDeleteNode((PDOMNODE)pDom->pDocumentNode);
     2449                xmlDeleteNode((PNODEBASE)pDom->pDocumentNode);
    19612450                pDom->pDocumentNode = NULL;
    19622451            }
     
    19832472
    19842473            // clean up the stack (but not the DOM itself)
    1985             lstClear(&pDom->llStack);
     2474            lstClear(&pDom->llElementStack);
    19862475        }
    19872476    }
  • trunk/src/helpers/xmldefs.c

    r38 r39  
    700700 *      --  A "list" is defined as an enumeration of content particles,
    701701 *          enclosed in parentheses, where the content particles are
    702  *          separated by list separators.
    703  *
    704  *      There are two types of list separators:
     702 *          separated by "connectors".
     703 *
     704 *      There are two types of "connectors":
    705705 *
    706706 *      --  Commas (",") indicate that the elements must appear
     
    710710 *          occur alternatively ("choice").
    711711 *
    712  *      The list separators cannot be mixed; the list must be
     712 *      The connectors cannot be mixed; the list must be
    713713 *      either completely "sequence" or "choice".
    714714 *
     
    743743 *
    744744 *      Now, a nested example:
     745 *
     746 +          <!ELEMENT poem (title?, (stanza+ | couplet+ | line+) ) >
     747 *
     748 *      That is, a poem consists of an optional title, followed by one or
     749 *      several stanzas, or one or several couplets, or one or several lines.
     750 *      This is different from:
     751 *
     752 +          <!ELEMENT poem (title?, (stanza | couplet | line)+ ) >
     753 *
     754 *      The latter allows for a single poem to contain a mixture of stanzas,
     755 *      couplets or lines.
     756 *
     757 *      And for WarpIN:
    745758 *
    746759 +          <!ELEMENT WARPIN (REXX*, VARPROMPT*, MSG?, TITLE?, (GROUP | PCK)+), PAGE+) >
  • trunk/src/helpers/xmlparse.c

    r38 r39  
    10531053
    10541054#ifdef XML_DTD
    1055     int oldParamEntityParsing = paramEntityParsing;
     1055    enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
    10561056
    10571057#endif
  • trunk/src/helpers/xstring.c

    r38 r39  
    376376 *      With ulSourceLength, specify the length of pcszSource.
    377377 *      If you specify 0, this function will run strlen(pcszSource)
    378  *      itself. If you already know the length of pcszSource (or
    379  *      only want to copy a substring), you can speed this function
    380  *      up a bit this way.
     378 *      itself.
     379 *
     380 *      If you already know the length of pcszSource, you can
     381 *      speed this function up a bit this way.
     382 *
     383 *      You are required to specify ulSourceLength if you only want
     384 *      to copy a substring, or pcszSource is not zero-terminated.
    381385 *
    382386 *      Returns the length of the new string (excluding the null
     
    396400 *@@changed V0.9.9 (2001-01-28) [lafaix]: fixed memory leak and NULL source behavior
    397401 *@@changed V0.9.9 (2001-02-14) [umoeller]: fixed NULL target crash
     402 *@@changed V0.9.9 (2001-02-16) [umoeller]: now supporting non-zero-terminated pcszSource
    398403 */
    399404
     
    432437        // else: we have enough memory
    433438
    434         // strcpy(pxstr->psz, pcszSource);
    435439        memcpy(pxstr->psz,
    436440               pcszSource,
    437                ulSourceLength + 1); // V0.9.9 (2001-01-31) [umoeller]
     441               ulSourceLength);
     442        *(pxstr->psz + ulSourceLength) = '\0';
     443                // V0.9.9 (2001-02-16) [umoeller]
     444                // we must do this or otherwise we require pcszSource
     445                // to be zero-terminated... not a good idea
    438446    }
    439447    else
     
    480488 *      With ulSourceLength, specify the length of pcszSource.
    481489 *      If you specify 0, this function will run strlen(pcszSource)
    482  *      itself. If you already know the length of pcszSource (or
    483  *      only want to copy a substring), you can speed this function
    484  *      up a bit this way.
     490 *      itself.
     491 *
     492 *      If you already know the length of pcszSource, you can
     493 *      speed this function up a bit this way.
     494 *
     495 *      You are required to specify ulSourceLength if you only want
     496 *      to copy a substring, or pcszSource is not zero-terminated.
    485497 *
    486498 *      Returns the length of the new string (excluding the null
     
    508520 *@@changed V0.9.7 (2000-12-10) [umoeller]: return value was wrong
    509521 *@@changed V0.9.7 (2001-01-15) [umoeller]: added ulSourceLength
     522 *@@changed V0.9.9 (2001-02-16) [umoeller]: now supporting non-zero-terminated pcszSource
    510523 */
    511524
     
    559572                memcpy(pxstr->psz + pxstr->ulLength,
    560573                       pcszSource,
    561                        ulSourceLength + 1);     // null terminator
     574                       ulSourceLength);     // null terminator
     575
     576                *(pxstr->psz + pxstr->ulLength + ulSourceLength) = '\0';
     577                        // V0.9.9 (2001-02-16) [umoeller]
     578                        // we must do this or otherwise we require pcszSource
     579                        // to be zero-terminated... not a good idea
    562580
    563581                // in all cases, set new length
Note: See TracChangeset for help on using the changeset viewer.