Home | History | Annotate | Download | only in libxml2
      1 /*
      2  * relaxng.c : implementation of the Relax-NG handling and validity checking
      3  *
      4  * See Copyright for the status of this software.
      5  *
      6  * Daniel Veillard <veillard (at) redhat.com>
      7  */
      8 
      9 /**
     10  * TODO:
     11  * - add support for DTD compatibility spec
     12  *   http://www.oasis-open.org/committees/relax-ng/compatibility-20011203.html
     13  * - report better mem allocations pbms at runtime and abort immediately.
     14  */
     15 
     16 #define IN_LIBXML
     17 #include "libxml.h"
     18 
     19 #ifdef LIBXML_SCHEMAS_ENABLED
     20 
     21 #include <string.h>
     22 #include <stdio.h>
     23 #include <stddef.h>
     24 #include <libxml/xmlmemory.h>
     25 #include <libxml/parser.h>
     26 #include <libxml/parserInternals.h>
     27 #include <libxml/hash.h>
     28 #include <libxml/uri.h>
     29 
     30 #include <libxml/relaxng.h>
     31 
     32 #include <libxml/xmlschemastypes.h>
     33 #include <libxml/xmlautomata.h>
     34 #include <libxml/xmlregexp.h>
     35 #include <libxml/xmlschemastypes.h>
     36 
     37 /*
     38  * The Relax-NG namespace
     39  */
     40 static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
     41     "http://relaxng.org/ns/structure/1.0";
     42 
     43 #define IS_RELAXNG(node, typ)						\
     44    ((node != NULL) && (node->ns != NULL) &&				\
     45     (node->type == XML_ELEMENT_NODE) &&					\
     46     (xmlStrEqual(node->name, (const xmlChar *) typ)) &&		\
     47     (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))
     48 
     49 
     50 #if 0
     51 #define DEBUG 1
     52 
     53 #define DEBUG_GRAMMAR 1
     54 
     55 #define DEBUG_CONTENT 1
     56 
     57 #define DEBUG_TYPE 1
     58 
     59 #define DEBUG_VALID 1
     60 
     61 #define DEBUG_INTERLEAVE 1
     62 
     63 #define DEBUG_LIST 1
     64 
     65 #define DEBUG_INCLUDE 1
     66 
     67 #define DEBUG_ERROR 1
     68 
     69 #define DEBUG_COMPILE 1
     70 
     71 #define DEBUG_PROGRESSIVE 1
     72 #endif
     73 
     74 #define MAX_ERROR 5
     75 
     76 #define TODO								\
     77     xmlGenericError(xmlGenericErrorContext,				\
     78 	    "Unimplemented block at %s:%d\n",				\
     79             __FILE__, __LINE__);
     80 
     81 typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;
     82 typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;
     83 
     84 typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine;
     85 typedef xmlRelaxNGDefine *xmlRelaxNGDefinePtr;
     86 
     87 typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument;
     88 typedef xmlRelaxNGDocument *xmlRelaxNGDocumentPtr;
     89 
     90 typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude;
     91 typedef xmlRelaxNGInclude *xmlRelaxNGIncludePtr;
     92 
     93 typedef enum {
     94     XML_RELAXNG_COMBINE_UNDEFINED = 0,  /* undefined */
     95     XML_RELAXNG_COMBINE_CHOICE, /* choice */
     96     XML_RELAXNG_COMBINE_INTERLEAVE      /* interleave */
     97 } xmlRelaxNGCombine;
     98 
     99 typedef enum {
    100     XML_RELAXNG_CONTENT_ERROR = -1,
    101     XML_RELAXNG_CONTENT_EMPTY = 0,
    102     XML_RELAXNG_CONTENT_SIMPLE,
    103     XML_RELAXNG_CONTENT_COMPLEX
    104 } xmlRelaxNGContentType;
    105 
    106 typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar;
    107 typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr;
    108 
    109 struct _xmlRelaxNGGrammar {
    110     xmlRelaxNGGrammarPtr parent;        /* the parent grammar if any */
    111     xmlRelaxNGGrammarPtr children;      /* the children grammar if any */
    112     xmlRelaxNGGrammarPtr next;  /* the next grammar if any */
    113     xmlRelaxNGDefinePtr start;  /* <start> content */
    114     xmlRelaxNGCombine combine;  /* the default combine value */
    115     xmlRelaxNGDefinePtr startList;      /* list of <start> definitions */
    116     xmlHashTablePtr defs;       /* define* */
    117     xmlHashTablePtr refs;       /* references */
    118 };
    119 
    120 
    121 typedef enum {
    122     XML_RELAXNG_NOOP = -1,      /* a no operation from simplification  */
    123     XML_RELAXNG_EMPTY = 0,      /* an empty pattern */
    124     XML_RELAXNG_NOT_ALLOWED,    /* not allowed top */
    125     XML_RELAXNG_EXCEPT,         /* except present in nameclass defs */
    126     XML_RELAXNG_TEXT,           /* textual content */
    127     XML_RELAXNG_ELEMENT,        /* an element */
    128     XML_RELAXNG_DATATYPE,       /* extenal data type definition */
    129     XML_RELAXNG_PARAM,          /* extenal data type parameter */
    130     XML_RELAXNG_VALUE,          /* value from an extenal data type definition */
    131     XML_RELAXNG_LIST,           /* a list of patterns */
    132     XML_RELAXNG_ATTRIBUTE,      /* an attrbute following a pattern */
    133     XML_RELAXNG_DEF,            /* a definition */
    134     XML_RELAXNG_REF,            /* reference to a definition */
    135     XML_RELAXNG_EXTERNALREF,    /* reference to an external def */
    136     XML_RELAXNG_PARENTREF,      /* reference to a def in the parent grammar */
    137     XML_RELAXNG_OPTIONAL,       /* optional patterns */
    138     XML_RELAXNG_ZEROORMORE,     /* zero or more non empty patterns */
    139     XML_RELAXNG_ONEORMORE,      /* one or more non empty patterns */
    140     XML_RELAXNG_CHOICE,         /* a choice between non empty patterns */
    141     XML_RELAXNG_GROUP,          /* a pair/group of non empty patterns */
    142     XML_RELAXNG_INTERLEAVE,     /* interleaving choice of non-empty patterns */
    143     XML_RELAXNG_START           /* Used to keep track of starts on grammars */
    144 } xmlRelaxNGType;
    145 
    146 #define IS_NULLABLE		(1 << 0)
    147 #define IS_NOT_NULLABLE		(1 << 1)
    148 #define IS_INDETERMINIST	(1 << 2)
    149 #define IS_MIXED		(1 << 3)
    150 #define IS_TRIABLE		(1 << 4)
    151 #define IS_PROCESSED		(1 << 5)
    152 #define IS_COMPILABLE		(1 << 6)
    153 #define IS_NOT_COMPILABLE	(1 << 7)
    154 #define IS_EXTERNAL_REF	        (1 << 8)
    155 
    156 struct _xmlRelaxNGDefine {
    157     xmlRelaxNGType type;        /* the type of definition */
    158     xmlNodePtr node;            /* the node in the source */
    159     xmlChar *name;              /* the element local name if present */
    160     xmlChar *ns;                /* the namespace local name if present */
    161     xmlChar *value;             /* value when available */
    162     void *data;                 /* data lib or specific pointer */
    163     xmlRelaxNGDefinePtr content;        /* the expected content */
    164     xmlRelaxNGDefinePtr parent; /* the parent definition, if any */
    165     xmlRelaxNGDefinePtr next;   /* list within grouping sequences */
    166     xmlRelaxNGDefinePtr attrs;  /* list of attributes for elements */
    167     xmlRelaxNGDefinePtr nameClass;      /* the nameClass definition if any */
    168     xmlRelaxNGDefinePtr nextHash;       /* next define in defs/refs hash tables */
    169     short depth;                /* used for the cycle detection */
    170     short dflags;               /* define related flags */
    171     xmlRegexpPtr contModel;     /* a compiled content model if available */
    172 };
    173 
    174 /**
    175  * _xmlRelaxNG:
    176  *
    177  * A RelaxNGs definition
    178  */
    179 struct _xmlRelaxNG {
    180     void *_private;             /* unused by the library for users or bindings */
    181     xmlRelaxNGGrammarPtr topgrammar;
    182     xmlDocPtr doc;
    183 
    184     int idref;                  /* requires idref checking */
    185 
    186     xmlHashTablePtr defs;       /* define */
    187     xmlHashTablePtr refs;       /* references */
    188     xmlRelaxNGDocumentPtr documents;    /* all the documents loaded */
    189     xmlRelaxNGIncludePtr includes;      /* all the includes loaded */
    190     int defNr;                  /* number of defines used */
    191     xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */
    192 
    193 };
    194 
    195 #define XML_RELAXNG_IN_ATTRIBUTE	(1 << 0)
    196 #define XML_RELAXNG_IN_ONEORMORE	(1 << 1)
    197 #define XML_RELAXNG_IN_LIST		(1 << 2)
    198 #define XML_RELAXNG_IN_DATAEXCEPT	(1 << 3)
    199 #define XML_RELAXNG_IN_START		(1 << 4)
    200 #define XML_RELAXNG_IN_OOMGROUP		(1 << 5)
    201 #define XML_RELAXNG_IN_OOMINTERLEAVE	(1 << 6)
    202 #define XML_RELAXNG_IN_EXTERNALREF	(1 << 7)
    203 #define XML_RELAXNG_IN_ANYEXCEPT	(1 << 8)
    204 #define XML_RELAXNG_IN_NSEXCEPT		(1 << 9)
    205 
    206 struct _xmlRelaxNGParserCtxt {
    207     void *userData;             /* user specific data block */
    208     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */
    209     xmlRelaxNGValidityWarningFunc warning;      /* the callback in case of warning */
    210     xmlStructuredErrorFunc serror;
    211     xmlRelaxNGValidErr err;
    212 
    213     xmlRelaxNGPtr schema;       /* The schema in use */
    214     xmlRelaxNGGrammarPtr grammar;       /* the current grammar */
    215     xmlRelaxNGGrammarPtr parentgrammar; /* the parent grammar */
    216     int flags;                  /* parser flags */
    217     int nbErrors;               /* number of errors at parse time */
    218     int nbWarnings;             /* number of warnings at parse time */
    219     const xmlChar *define;      /* the current define scope */
    220     xmlRelaxNGDefinePtr def;    /* the current define */
    221 
    222     int nbInterleaves;
    223     xmlHashTablePtr interleaves;        /* keep track of all the interleaves */
    224 
    225     xmlRelaxNGDocumentPtr documents;    /* all the documents loaded */
    226     xmlRelaxNGIncludePtr includes;      /* all the includes loaded */
    227     xmlChar *URL;
    228     xmlDocPtr document;
    229 
    230     int defNr;                  /* number of defines used */
    231     int defMax;                 /* number of defines aloocated */
    232     xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */
    233 
    234     const char *buffer;
    235     int size;
    236 
    237     /* the document stack */
    238     xmlRelaxNGDocumentPtr doc;  /* Current parsed external ref */
    239     int docNr;                  /* Depth of the parsing stack */
    240     int docMax;                 /* Max depth of the parsing stack */
    241     xmlRelaxNGDocumentPtr *docTab;      /* array of docs */
    242 
    243     /* the include stack */
    244     xmlRelaxNGIncludePtr inc;   /* Current parsed include */
    245     int incNr;                  /* Depth of the include parsing stack */
    246     int incMax;                 /* Max depth of the parsing stack */
    247     xmlRelaxNGIncludePtr *incTab;       /* array of incs */
    248 
    249     int idref;                  /* requires idref checking */
    250 
    251     /* used to compile content models */
    252     xmlAutomataPtr am;          /* the automata */
    253     xmlAutomataStatePtr state;  /* used to build the automata */
    254 
    255     int crng;			/* compact syntax and other flags */
    256     int freedoc;		/* need to free the document */
    257 };
    258 
    259 #define FLAGS_IGNORABLE		1
    260 #define FLAGS_NEGATIVE		2
    261 #define FLAGS_MIXED_CONTENT	4
    262 #define FLAGS_NOERROR		8
    263 
    264 /**
    265  * xmlRelaxNGInterleaveGroup:
    266  *
    267  * A RelaxNGs partition set associated to lists of definitions
    268  */
    269 typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup;
    270 typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr;
    271 struct _xmlRelaxNGInterleaveGroup {
    272     xmlRelaxNGDefinePtr rule;   /* the rule to satisfy */
    273     xmlRelaxNGDefinePtr *defs;  /* the array of element definitions */
    274     xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */
    275 };
    276 
    277 #define IS_DETERMINIST		1
    278 #define IS_NEEDCHECK		2
    279 
    280 /**
    281  * xmlRelaxNGPartitions:
    282  *
    283  * A RelaxNGs partition associated to an interleave group
    284  */
    285 typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition;
    286 typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr;
    287 struct _xmlRelaxNGPartition {
    288     int nbgroups;               /* number of groups in the partitions */
    289     xmlHashTablePtr triage;     /* hash table used to direct nodes to the
    290                                  * right group when possible */
    291     int flags;                  /* determinist ? */
    292     xmlRelaxNGInterleaveGroupPtr *groups;
    293 };
    294 
    295 /**
    296  * xmlRelaxNGValidState:
    297  *
    298  * A RelaxNGs validation state
    299  */
    300 #define MAX_ATTR 20
    301 typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState;
    302 typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr;
    303 struct _xmlRelaxNGValidState {
    304     xmlNodePtr node;            /* the current node */
    305     xmlNodePtr seq;             /* the sequence of children left to validate */
    306     int nbAttrs;                /* the number of attributes */
    307     int maxAttrs;               /* the size of attrs */
    308     int nbAttrLeft;             /* the number of attributes left to validate */
    309     xmlChar *value;             /* the value when operating on string */
    310     xmlChar *endvalue;          /* the end value when operating on string */
    311     xmlAttrPtr *attrs;          /* the array of attributes */
    312 };
    313 
    314 /**
    315  * xmlRelaxNGStates:
    316  *
    317  * A RelaxNGs container for validation state
    318  */
    319 typedef struct _xmlRelaxNGStates xmlRelaxNGStates;
    320 typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr;
    321 struct _xmlRelaxNGStates {
    322     int nbState;                /* the number of states */
    323     int maxState;               /* the size of the array */
    324     xmlRelaxNGValidStatePtr *tabState;
    325 };
    326 
    327 #define ERROR_IS_DUP	1
    328 
    329 /**
    330  * xmlRelaxNGValidError:
    331  *
    332  * A RelaxNGs validation error
    333  */
    334 typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;
    335 typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;
    336 struct _xmlRelaxNGValidError {
    337     xmlRelaxNGValidErr err;     /* the error number */
    338     int flags;                  /* flags */
    339     xmlNodePtr node;            /* the current node */
    340     xmlNodePtr seq;             /* the current child */
    341     const xmlChar *arg1;        /* first arg */
    342     const xmlChar *arg2;        /* second arg */
    343 };
    344 
    345 /**
    346  * xmlRelaxNGValidCtxt:
    347  *
    348  * A RelaxNGs validation context
    349  */
    350 
    351 struct _xmlRelaxNGValidCtxt {
    352     void *userData;             /* user specific data block */
    353     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */
    354     xmlRelaxNGValidityWarningFunc warning;      /* the callback in case of warning */
    355     xmlStructuredErrorFunc serror;
    356     int nbErrors;               /* number of errors in validation */
    357 
    358     xmlRelaxNGPtr schema;       /* The schema in use */
    359     xmlDocPtr doc;              /* the document being validated */
    360     int flags;                  /* validation flags */
    361     int depth;                  /* validation depth */
    362     int idref;                  /* requires idref checking */
    363     int errNo;                  /* the first error found */
    364 
    365     /*
    366      * Errors accumulated in branches may have to be stacked to be
    367      * provided back when it's sure they affect validation.
    368      */
    369     xmlRelaxNGValidErrorPtr err;        /* Last error */
    370     int errNr;                  /* Depth of the error stack */
    371     int errMax;                 /* Max depth of the error stack */
    372     xmlRelaxNGValidErrorPtr errTab;     /* stack of errors */
    373 
    374     xmlRelaxNGValidStatePtr state;      /* the current validation state */
    375     xmlRelaxNGStatesPtr states; /* the accumulated state list */
    376 
    377     xmlRelaxNGStatesPtr freeState;      /* the pool of free valid states */
    378     int freeStatesNr;
    379     int freeStatesMax;
    380     xmlRelaxNGStatesPtr *freeStates;    /* the pool of free state groups */
    381 
    382     /*
    383      * This is used for "progressive" validation
    384      */
    385     xmlRegExecCtxtPtr elem;     /* the current element regexp */
    386     int elemNr;                 /* the number of element validated */
    387     int elemMax;                /* the max depth of elements */
    388     xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */
    389     int pstate;                 /* progressive state */
    390     xmlNodePtr pnode;           /* the current node */
    391     xmlRelaxNGDefinePtr pdef;   /* the non-streamable definition */
    392     int perr;                   /* signal error in content model
    393                                  * outside the regexp */
    394 };
    395 
    396 /**
    397  * xmlRelaxNGInclude:
    398  *
    399  * Structure associated to a RelaxNGs document element
    400  */
    401 struct _xmlRelaxNGInclude {
    402     xmlRelaxNGIncludePtr next;  /* keep a chain of includes */
    403     xmlChar *href;              /* the normalized href value */
    404     xmlDocPtr doc;              /* the associated XML document */
    405     xmlRelaxNGDefinePtr content;        /* the definitions */
    406     xmlRelaxNGPtr schema;       /* the schema */
    407 };
    408 
    409 /**
    410  * xmlRelaxNGDocument:
    411  *
    412  * Structure associated to a RelaxNGs document element
    413  */
    414 struct _xmlRelaxNGDocument {
    415     xmlRelaxNGDocumentPtr next; /* keep a chain of documents */
    416     xmlChar *href;              /* the normalized href value */
    417     xmlDocPtr doc;              /* the associated XML document */
    418     xmlRelaxNGDefinePtr content;        /* the definitions */
    419     xmlRelaxNGPtr schema;       /* the schema */
    420     int externalRef;            /* 1 if an external ref */
    421 };
    422 
    423 
    424 /************************************************************************
    425  *									*
    426  *		Some factorized error routines				*
    427  *									*
    428  ************************************************************************/
    429 
    430 /**
    431  * xmlRngPErrMemory:
    432  * @ctxt:  an Relax-NG parser context
    433  * @extra:  extra informations
    434  *
    435  * Handle a redefinition of attribute error
    436  */
    437 static void
    438 xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
    439 {
    440     xmlStructuredErrorFunc schannel = NULL;
    441     xmlGenericErrorFunc channel = NULL;
    442     void *data = NULL;
    443 
    444     if (ctxt != NULL) {
    445         if (ctxt->serror != NULL)
    446 	    schannel = ctxt->serror;
    447 	else
    448 	    channel = ctxt->error;
    449         data = ctxt->userData;
    450         ctxt->nbErrors++;
    451     }
    452     if (extra)
    453         __xmlRaiseError(schannel, channel, data,
    454                         NULL, NULL, XML_FROM_RELAXNGP,
    455                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
    456                         NULL, NULL, 0, 0,
    457                         "Memory allocation failed : %s\n", extra);
    458     else
    459         __xmlRaiseError(schannel, channel, data,
    460                         NULL, NULL, XML_FROM_RELAXNGP,
    461                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
    462                         NULL, NULL, 0, 0, "Memory allocation failed\n");
    463 }
    464 
    465 /**
    466  * xmlRngVErrMemory:
    467  * @ctxt:  a Relax-NG validation context
    468  * @extra:  extra informations
    469  *
    470  * Handle a redefinition of attribute error
    471  */
    472 static void
    473 xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)
    474 {
    475     xmlStructuredErrorFunc schannel = NULL;
    476     xmlGenericErrorFunc channel = NULL;
    477     void *data = NULL;
    478 
    479     if (ctxt != NULL) {
    480         if (ctxt->serror != NULL)
    481 	    schannel = ctxt->serror;
    482 	else
    483 	    channel = ctxt->error;
    484         data = ctxt->userData;
    485         ctxt->nbErrors++;
    486     }
    487     if (extra)
    488         __xmlRaiseError(schannel, channel, data,
    489                         NULL, NULL, XML_FROM_RELAXNGV,
    490                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
    491                         NULL, NULL, 0, 0,
    492                         "Memory allocation failed : %s\n", extra);
    493     else
    494         __xmlRaiseError(schannel, channel, data,
    495                         NULL, NULL, XML_FROM_RELAXNGV,
    496                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
    497                         NULL, NULL, 0, 0, "Memory allocation failed\n");
    498 }
    499 
    500 /**
    501  * xmlRngPErr:
    502  * @ctxt:  a Relax-NG parser context
    503  * @node:  the node raising the error
    504  * @error:  the error code
    505  * @msg:  message
    506  * @str1:  extra info
    507  * @str2:  extra info
    508  *
    509  * Handle a Relax NG Parsing error
    510  */
    511 static void LIBXML_ATTR_FORMAT(4,0)
    512 xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
    513            const char *msg, const xmlChar * str1, const xmlChar * str2)
    514 {
    515     xmlStructuredErrorFunc schannel = NULL;
    516     xmlGenericErrorFunc channel = NULL;
    517     void *data = NULL;
    518 
    519     if (ctxt != NULL) {
    520         if (ctxt->serror != NULL)
    521 	    schannel = ctxt->serror;
    522 	else
    523 	    channel = ctxt->error;
    524         data = ctxt->userData;
    525         ctxt->nbErrors++;
    526     }
    527     __xmlRaiseError(schannel, channel, data,
    528                     NULL, node, XML_FROM_RELAXNGP,
    529                     error, XML_ERR_ERROR, NULL, 0,
    530                     (const char *) str1, (const char *) str2, NULL, 0, 0,
    531                     msg, str1, str2);
    532 }
    533 
    534 /**
    535  * xmlRngVErr:
    536  * @ctxt:  a Relax-NG validation context
    537  * @node:  the node raising the error
    538  * @error:  the error code
    539  * @msg:  message
    540  * @str1:  extra info
    541  * @str2:  extra info
    542  *
    543  * Handle a Relax NG Validation error
    544  */
    545 static void LIBXML_ATTR_FORMAT(4,0)
    546 xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
    547            const char *msg, const xmlChar * str1, const xmlChar * str2)
    548 {
    549     xmlStructuredErrorFunc schannel = NULL;
    550     xmlGenericErrorFunc channel = NULL;
    551     void *data = NULL;
    552 
    553     if (ctxt != NULL) {
    554         if (ctxt->serror != NULL)
    555 	    schannel = ctxt->serror;
    556 	else
    557 	    channel = ctxt->error;
    558         data = ctxt->userData;
    559         ctxt->nbErrors++;
    560     }
    561     __xmlRaiseError(schannel, channel, data,
    562                     NULL, node, XML_FROM_RELAXNGV,
    563                     error, XML_ERR_ERROR, NULL, 0,
    564                     (const char *) str1, (const char *) str2, NULL, 0, 0,
    565                     msg, str1, str2);
    566 }
    567 
    568 /************************************************************************
    569  *									*
    570  *		Preliminary type checking interfaces			*
    571  *									*
    572  ************************************************************************/
    573 
    574 /**
    575  * xmlRelaxNGTypeHave:
    576  * @data:  data needed for the library
    577  * @type:  the type name
    578  * @value:  the value to check
    579  *
    580  * Function provided by a type library to check if a type is exported
    581  *
    582  * Returns 1 if yes, 0 if no and -1 in case of error.
    583  */
    584 typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar * type);
    585 
    586 /**
    587  * xmlRelaxNGTypeCheck:
    588  * @data:  data needed for the library
    589  * @type:  the type name
    590  * @value:  the value to check
    591  * @result:  place to store the result if needed
    592  *
    593  * Function provided by a type library to check if a value match a type
    594  *
    595  * Returns 1 if yes, 0 if no and -1 in case of error.
    596  */
    597 typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar * type,
    598                                     const xmlChar * value, void **result,
    599                                     xmlNodePtr node);
    600 
    601 /**
    602  * xmlRelaxNGFacetCheck:
    603  * @data:  data needed for the library
    604  * @type:  the type name
    605  * @facet:  the facet name
    606  * @val:  the facet value
    607  * @strval:  the string value
    608  * @value:  the value to check
    609  *
    610  * Function provided by a type library to check a value facet
    611  *
    612  * Returns 1 if yes, 0 if no and -1 in case of error.
    613  */
    614 typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar * type,
    615                                      const xmlChar * facet,
    616                                      const xmlChar * val,
    617                                      const xmlChar * strval, void *value);
    618 
    619 /**
    620  * xmlRelaxNGTypeFree:
    621  * @data:  data needed for the library
    622  * @result:  the value to free
    623  *
    624  * Function provided by a type library to free a returned result
    625  */
    626 typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);
    627 
    628 /**
    629  * xmlRelaxNGTypeCompare:
    630  * @data:  data needed for the library
    631  * @type:  the type name
    632  * @value1:  the first value
    633  * @value2:  the second value
    634  *
    635  * Function provided by a type library to compare two values accordingly
    636  * to a type.
    637  *
    638  * Returns 1 if yes, 0 if no and -1 in case of error.
    639  */
    640 typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar * type,
    641                                       const xmlChar * value1,
    642                                       xmlNodePtr ctxt1,
    643                                       void *comp1,
    644                                       const xmlChar * value2,
    645                                       xmlNodePtr ctxt2);
    646 typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
    647 typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
    648 struct _xmlRelaxNGTypeLibrary {
    649     const xmlChar *namespace;   /* the datatypeLibrary value */
    650     void *data;                 /* data needed for the library */
    651     xmlRelaxNGTypeHave have;    /* the export function */
    652     xmlRelaxNGTypeCheck check;  /* the checking function */
    653     xmlRelaxNGTypeCompare comp; /* the compare function */
    654     xmlRelaxNGFacetCheck facet; /* the facet check function */
    655     xmlRelaxNGTypeFree freef;   /* the freeing function */
    656 };
    657 
    658 /************************************************************************
    659  *									*
    660  *			Allocation functions				*
    661  *									*
    662  ************************************************************************/
    663 static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);
    664 static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);
    665 static void xmlRelaxNGNormExtSpace(xmlChar * value);
    666 static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema);
    667 static int xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt
    668                                      ATTRIBUTE_UNUSED,
    669                                      xmlRelaxNGValidStatePtr state1,
    670                                      xmlRelaxNGValidStatePtr state2);
    671 static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
    672                                      xmlRelaxNGValidStatePtr state);
    673 
    674 /**
    675  * xmlRelaxNGFreeDocument:
    676  * @docu:  a document structure
    677  *
    678  * Deallocate a RelaxNG document structure.
    679  */
    680 static void
    681 xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu)
    682 {
    683     if (docu == NULL)
    684         return;
    685 
    686     if (docu->href != NULL)
    687         xmlFree(docu->href);
    688     if (docu->doc != NULL)
    689         xmlFreeDoc(docu->doc);
    690     if (docu->schema != NULL)
    691         xmlRelaxNGFreeInnerSchema(docu->schema);
    692     xmlFree(docu);
    693 }
    694 
    695 /**
    696  * xmlRelaxNGFreeDocumentList:
    697  * @docu:  a list of  document structure
    698  *
    699  * Deallocate a RelaxNG document structures.
    700  */
    701 static void
    702 xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu)
    703 {
    704     xmlRelaxNGDocumentPtr next;
    705 
    706     while (docu != NULL) {
    707         next = docu->next;
    708         xmlRelaxNGFreeDocument(docu);
    709         docu = next;
    710     }
    711 }
    712 
    713 /**
    714  * xmlRelaxNGFreeInclude:
    715  * @incl:  a include structure
    716  *
    717  * Deallocate a RelaxNG include structure.
    718  */
    719 static void
    720 xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl)
    721 {
    722     if (incl == NULL)
    723         return;
    724 
    725     if (incl->href != NULL)
    726         xmlFree(incl->href);
    727     if (incl->doc != NULL)
    728         xmlFreeDoc(incl->doc);
    729     if (incl->schema != NULL)
    730         xmlRelaxNGFree(incl->schema);
    731     xmlFree(incl);
    732 }
    733 
    734 /**
    735  * xmlRelaxNGFreeIncludeList:
    736  * @incl:  a include structure list
    737  *
    738  * Deallocate a RelaxNG include structure.
    739  */
    740 static void
    741 xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl)
    742 {
    743     xmlRelaxNGIncludePtr next;
    744 
    745     while (incl != NULL) {
    746         next = incl->next;
    747         xmlRelaxNGFreeInclude(incl);
    748         incl = next;
    749     }
    750 }
    751 
    752 /**
    753  * xmlRelaxNGNewRelaxNG:
    754  * @ctxt:  a Relax-NG validation context (optional)
    755  *
    756  * Allocate a new RelaxNG structure.
    757  *
    758  * Returns the newly allocated structure or NULL in case or error
    759  */
    760 static xmlRelaxNGPtr
    761 xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)
    762 {
    763     xmlRelaxNGPtr ret;
    764 
    765     ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));
    766     if (ret == NULL) {
    767         xmlRngPErrMemory(ctxt, NULL);
    768         return (NULL);
    769     }
    770     memset(ret, 0, sizeof(xmlRelaxNG));
    771 
    772     return (ret);
    773 }
    774 
    775 /**
    776  * xmlRelaxNGFreeInnerSchema:
    777  * @schema:  a schema structure
    778  *
    779  * Deallocate a RelaxNG schema structure.
    780  */
    781 static void
    782 xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema)
    783 {
    784     if (schema == NULL)
    785         return;
    786 
    787     if (schema->doc != NULL)
    788         xmlFreeDoc(schema->doc);
    789     if (schema->defTab != NULL) {
    790         int i;
    791 
    792         for (i = 0; i < schema->defNr; i++)
    793             xmlRelaxNGFreeDefine(schema->defTab[i]);
    794         xmlFree(schema->defTab);
    795     }
    796 
    797     xmlFree(schema);
    798 }
    799 
    800 /**
    801  * xmlRelaxNGFree:
    802  * @schema:  a schema structure
    803  *
    804  * Deallocate a RelaxNG structure.
    805  */
    806 void
    807 xmlRelaxNGFree(xmlRelaxNGPtr schema)
    808 {
    809     if (schema == NULL)
    810         return;
    811 
    812     if (schema->topgrammar != NULL)
    813         xmlRelaxNGFreeGrammar(schema->topgrammar);
    814     if (schema->doc != NULL)
    815         xmlFreeDoc(schema->doc);
    816     if (schema->documents != NULL)
    817         xmlRelaxNGFreeDocumentList(schema->documents);
    818     if (schema->includes != NULL)
    819         xmlRelaxNGFreeIncludeList(schema->includes);
    820     if (schema->defTab != NULL) {
    821         int i;
    822 
    823         for (i = 0; i < schema->defNr; i++)
    824             xmlRelaxNGFreeDefine(schema->defTab[i]);
    825         xmlFree(schema->defTab);
    826     }
    827 
    828     xmlFree(schema);
    829 }
    830 
    831 /**
    832  * xmlRelaxNGNewGrammar:
    833  * @ctxt:  a Relax-NG validation context (optional)
    834  *
    835  * Allocate a new RelaxNG grammar.
    836  *
    837  * Returns the newly allocated structure or NULL in case or error
    838  */
    839 static xmlRelaxNGGrammarPtr
    840 xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)
    841 {
    842     xmlRelaxNGGrammarPtr ret;
    843 
    844     ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));
    845     if (ret == NULL) {
    846         xmlRngPErrMemory(ctxt, NULL);
    847         return (NULL);
    848     }
    849     memset(ret, 0, sizeof(xmlRelaxNGGrammar));
    850 
    851     return (ret);
    852 }
    853 
    854 /**
    855  * xmlRelaxNGFreeGrammar:
    856  * @grammar:  a grammar structure
    857  *
    858  * Deallocate a RelaxNG grammar structure.
    859  */
    860 static void
    861 xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar)
    862 {
    863     if (grammar == NULL)
    864         return;
    865 
    866     if (grammar->children != NULL) {
    867         xmlRelaxNGFreeGrammar(grammar->children);
    868     }
    869     if (grammar->next != NULL) {
    870         xmlRelaxNGFreeGrammar(grammar->next);
    871     }
    872     if (grammar->refs != NULL) {
    873         xmlHashFree(grammar->refs, NULL);
    874     }
    875     if (grammar->defs != NULL) {
    876         xmlHashFree(grammar->defs, NULL);
    877     }
    878 
    879     xmlFree(grammar);
    880 }
    881 
    882 /**
    883  * xmlRelaxNGNewDefine:
    884  * @ctxt:  a Relax-NG validation context
    885  * @node:  the node in the input document.
    886  *
    887  * Allocate a new RelaxNG define.
    888  *
    889  * Returns the newly allocated structure or NULL in case or error
    890  */
    891 static xmlRelaxNGDefinePtr
    892 xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
    893 {
    894     xmlRelaxNGDefinePtr ret;
    895 
    896     if (ctxt->defMax == 0) {
    897         ctxt->defMax = 16;
    898         ctxt->defNr = 0;
    899         ctxt->defTab = (xmlRelaxNGDefinePtr *)
    900             xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
    901         if (ctxt->defTab == NULL) {
    902             xmlRngPErrMemory(ctxt, "allocating define\n");
    903             return (NULL);
    904         }
    905     } else if (ctxt->defMax <= ctxt->defNr) {
    906         xmlRelaxNGDefinePtr *tmp;
    907 
    908         ctxt->defMax *= 2;
    909         tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,
    910                                                  ctxt->defMax *
    911                                                  sizeof
    912                                                  (xmlRelaxNGDefinePtr));
    913         if (tmp == NULL) {
    914             xmlRngPErrMemory(ctxt, "allocating define\n");
    915             return (NULL);
    916         }
    917         ctxt->defTab = tmp;
    918     }
    919     ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
    920     if (ret == NULL) {
    921         xmlRngPErrMemory(ctxt, "allocating define\n");
    922         return (NULL);
    923     }
    924     memset(ret, 0, sizeof(xmlRelaxNGDefine));
    925     ctxt->defTab[ctxt->defNr++] = ret;
    926     ret->node = node;
    927     ret->depth = -1;
    928     return (ret);
    929 }
    930 
    931 /**
    932  * xmlRelaxNGFreePartition:
    933  * @partitions:  a partition set structure
    934  *
    935  * Deallocate RelaxNG partition set structures.
    936  */
    937 static void
    938 xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions)
    939 {
    940     xmlRelaxNGInterleaveGroupPtr group;
    941     int j;
    942 
    943     if (partitions != NULL) {
    944         if (partitions->groups != NULL) {
    945             for (j = 0; j < partitions->nbgroups; j++) {
    946                 group = partitions->groups[j];
    947                 if (group != NULL) {
    948                     if (group->defs != NULL)
    949                         xmlFree(group->defs);
    950                     if (group->attrs != NULL)
    951                         xmlFree(group->attrs);
    952                     xmlFree(group);
    953                 }
    954             }
    955             xmlFree(partitions->groups);
    956         }
    957         if (partitions->triage != NULL) {
    958             xmlHashFree(partitions->triage, NULL);
    959         }
    960         xmlFree(partitions);
    961     }
    962 }
    963 
    964 /**
    965  * xmlRelaxNGFreeDefine:
    966  * @define:  a define structure
    967  *
    968  * Deallocate a RelaxNG define structure.
    969  */
    970 static void
    971 xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define)
    972 {
    973     if (define == NULL)
    974         return;
    975 
    976     if ((define->type == XML_RELAXNG_VALUE) && (define->attrs != NULL)) {
    977         xmlRelaxNGTypeLibraryPtr lib;
    978 
    979         lib = (xmlRelaxNGTypeLibraryPtr) define->data;
    980         if ((lib != NULL) && (lib->freef != NULL))
    981             lib->freef(lib->data, (void *) define->attrs);
    982     }
    983     if ((define->data != NULL) && (define->type == XML_RELAXNG_INTERLEAVE))
    984         xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
    985     if ((define->data != NULL) && (define->type == XML_RELAXNG_CHOICE))
    986         xmlHashFree((xmlHashTablePtr) define->data, NULL);
    987     if (define->name != NULL)
    988         xmlFree(define->name);
    989     if (define->ns != NULL)
    990         xmlFree(define->ns);
    991     if (define->value != NULL)
    992         xmlFree(define->value);
    993     if (define->contModel != NULL)
    994         xmlRegFreeRegexp(define->contModel);
    995     xmlFree(define);
    996 }
    997 
    998 /**
    999  * xmlRelaxNGNewStates:
   1000  * @ctxt:  a Relax-NG validation context
   1001  * @size:  the default size for the container
   1002  *
   1003  * Allocate a new RelaxNG validation state container
   1004  *
   1005  * Returns the newly allocated structure or NULL in case or error
   1006  */
   1007 static xmlRelaxNGStatesPtr
   1008 xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
   1009 {
   1010     xmlRelaxNGStatesPtr ret;
   1011 
   1012     if ((ctxt != NULL) &&
   1013         (ctxt->freeStates != NULL) && (ctxt->freeStatesNr > 0)) {
   1014         ctxt->freeStatesNr--;
   1015         ret = ctxt->freeStates[ctxt->freeStatesNr];
   1016         ret->nbState = 0;
   1017         return (ret);
   1018     }
   1019     if (size < 16)
   1020         size = 16;
   1021 
   1022     ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +
   1023                                           (size -
   1024                                            1) *
   1025                                           sizeof(xmlRelaxNGValidStatePtr));
   1026     if (ret == NULL) {
   1027         xmlRngVErrMemory(ctxt, "allocating states\n");
   1028         return (NULL);
   1029     }
   1030     ret->nbState = 0;
   1031     ret->maxState = size;
   1032     ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc((size) *
   1033                                                           sizeof
   1034                                                           (xmlRelaxNGValidStatePtr));
   1035     if (ret->tabState == NULL) {
   1036         xmlRngVErrMemory(ctxt, "allocating states\n");
   1037         xmlFree(ret);
   1038         return (NULL);
   1039     }
   1040     return (ret);
   1041 }
   1042 
   1043 /**
   1044  * xmlRelaxNGAddStateUniq:
   1045  * @ctxt:  a Relax-NG validation context
   1046  * @states:  the states container
   1047  * @state:  the validation state
   1048  *
   1049  * Add a RelaxNG validation state to the container without checking
   1050  * for unicity.
   1051  *
   1052  * Return 1 in case of success and 0 if this is a duplicate and -1 on error
   1053  */
   1054 static int
   1055 xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,
   1056                         xmlRelaxNGStatesPtr states,
   1057                         xmlRelaxNGValidStatePtr state)
   1058 {
   1059     if (state == NULL) {
   1060         return (-1);
   1061     }
   1062     if (states->nbState >= states->maxState) {
   1063         xmlRelaxNGValidStatePtr *tmp;
   1064         int size;
   1065 
   1066         size = states->maxState * 2;
   1067         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
   1068                                                      (size) *
   1069                                                      sizeof
   1070                                                      (xmlRelaxNGValidStatePtr));
   1071         if (tmp == NULL) {
   1072             xmlRngVErrMemory(ctxt, "adding states\n");
   1073             return (-1);
   1074         }
   1075         states->tabState = tmp;
   1076         states->maxState = size;
   1077     }
   1078     states->tabState[states->nbState++] = state;
   1079     return (1);
   1080 }
   1081 
   1082 /**
   1083  * xmlRelaxNGAddState:
   1084  * @ctxt:  a Relax-NG validation context
   1085  * @states:  the states container
   1086  * @state:  the validation state
   1087  *
   1088  * Add a RelaxNG validation state to the container
   1089  *
   1090  * Return 1 in case of success and 0 if this is a duplicate and -1 on error
   1091  */
   1092 static int
   1093 xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt,
   1094                     xmlRelaxNGStatesPtr states,
   1095                     xmlRelaxNGValidStatePtr state)
   1096 {
   1097     int i;
   1098 
   1099     if (state == NULL || states == NULL) {
   1100         return (-1);
   1101     }
   1102     if (states->nbState >= states->maxState) {
   1103         xmlRelaxNGValidStatePtr *tmp;
   1104         int size;
   1105 
   1106         size = states->maxState * 2;
   1107         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
   1108                                                      (size) *
   1109                                                      sizeof
   1110                                                      (xmlRelaxNGValidStatePtr));
   1111         if (tmp == NULL) {
   1112             xmlRngVErrMemory(ctxt, "adding states\n");
   1113             return (-1);
   1114         }
   1115         states->tabState = tmp;
   1116         states->maxState = size;
   1117     }
   1118     for (i = 0; i < states->nbState; i++) {
   1119         if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) {
   1120             xmlRelaxNGFreeValidState(ctxt, state);
   1121             return (0);
   1122         }
   1123     }
   1124     states->tabState[states->nbState++] = state;
   1125     return (1);
   1126 }
   1127 
   1128 /**
   1129  * xmlRelaxNGFreeStates:
   1130  * @ctxt:  a Relax-NG validation context
   1131  * @states:  teh container
   1132  *
   1133  * Free a RelaxNG validation state container
   1134  */
   1135 static void
   1136 xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
   1137                      xmlRelaxNGStatesPtr states)
   1138 {
   1139     if (states == NULL)
   1140         return;
   1141     if ((ctxt != NULL) && (ctxt->freeStates == NULL)) {
   1142         ctxt->freeStatesMax = 40;
   1143         ctxt->freeStatesNr = 0;
   1144         ctxt->freeStates = (xmlRelaxNGStatesPtr *)
   1145             xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
   1146         if (ctxt->freeStates == NULL) {
   1147             xmlRngVErrMemory(ctxt, "storing states\n");
   1148         }
   1149     } else if ((ctxt != NULL)
   1150                && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) {
   1151         xmlRelaxNGStatesPtr *tmp;
   1152 
   1153         tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates,
   1154                                                  2 * ctxt->freeStatesMax *
   1155                                                  sizeof
   1156                                                  (xmlRelaxNGStatesPtr));
   1157         if (tmp == NULL) {
   1158             xmlRngVErrMemory(ctxt, "storing states\n");
   1159             xmlFree(states->tabState);
   1160             xmlFree(states);
   1161             return;
   1162         }
   1163         ctxt->freeStates = tmp;
   1164         ctxt->freeStatesMax *= 2;
   1165     }
   1166     if ((ctxt == NULL) || (ctxt->freeStates == NULL)) {
   1167         xmlFree(states->tabState);
   1168         xmlFree(states);
   1169     } else {
   1170         ctxt->freeStates[ctxt->freeStatesNr++] = states;
   1171     }
   1172 }
   1173 
   1174 /**
   1175  * xmlRelaxNGNewValidState:
   1176  * @ctxt:  a Relax-NG validation context
   1177  * @node:  the current node or NULL for the document
   1178  *
   1179  * Allocate a new RelaxNG validation state
   1180  *
   1181  * Returns the newly allocated structure or NULL in case or error
   1182  */
   1183 static xmlRelaxNGValidStatePtr
   1184 xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
   1185 {
   1186     xmlRelaxNGValidStatePtr ret;
   1187     xmlAttrPtr attr;
   1188     xmlAttrPtr attrs[MAX_ATTR];
   1189     int nbAttrs = 0;
   1190     xmlNodePtr root = NULL;
   1191 
   1192     if (node == NULL) {
   1193         root = xmlDocGetRootElement(ctxt->doc);
   1194         if (root == NULL)
   1195             return (NULL);
   1196     } else {
   1197         attr = node->properties;
   1198         while (attr != NULL) {
   1199             if (nbAttrs < MAX_ATTR)
   1200                 attrs[nbAttrs++] = attr;
   1201             else
   1202                 nbAttrs++;
   1203             attr = attr->next;
   1204         }
   1205     }
   1206     if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
   1207         ctxt->freeState->nbState--;
   1208         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
   1209     } else {
   1210         ret =
   1211             (xmlRelaxNGValidStatePtr)
   1212             xmlMalloc(sizeof(xmlRelaxNGValidState));
   1213         if (ret == NULL) {
   1214             xmlRngVErrMemory(ctxt, "allocating states\n");
   1215             return (NULL);
   1216         }
   1217         memset(ret, 0, sizeof(xmlRelaxNGValidState));
   1218     }
   1219     ret->value = NULL;
   1220     ret->endvalue = NULL;
   1221     if (node == NULL) {
   1222         ret->node = (xmlNodePtr) ctxt->doc;
   1223         ret->seq = root;
   1224     } else {
   1225         ret->node = node;
   1226         ret->seq = node->children;
   1227     }
   1228     ret->nbAttrs = 0;
   1229     if (nbAttrs > 0) {
   1230         if (ret->attrs == NULL) {
   1231             if (nbAttrs < 4)
   1232                 ret->maxAttrs = 4;
   1233             else
   1234                 ret->maxAttrs = nbAttrs;
   1235             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
   1236                                                   sizeof(xmlAttrPtr));
   1237             if (ret->attrs == NULL) {
   1238                 xmlRngVErrMemory(ctxt, "allocating states\n");
   1239                 return (ret);
   1240             }
   1241         } else if (ret->maxAttrs < nbAttrs) {
   1242             xmlAttrPtr *tmp;
   1243 
   1244             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *
   1245                                             sizeof(xmlAttrPtr));
   1246             if (tmp == NULL) {
   1247                 xmlRngVErrMemory(ctxt, "allocating states\n");
   1248                 return (ret);
   1249             }
   1250             ret->attrs = tmp;
   1251             ret->maxAttrs = nbAttrs;
   1252         }
   1253         ret->nbAttrs = nbAttrs;
   1254         if (nbAttrs < MAX_ATTR) {
   1255             memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs);
   1256         } else {
   1257             attr = node->properties;
   1258             nbAttrs = 0;
   1259             while (attr != NULL) {
   1260                 ret->attrs[nbAttrs++] = attr;
   1261                 attr = attr->next;
   1262             }
   1263         }
   1264     }
   1265     ret->nbAttrLeft = ret->nbAttrs;
   1266     return (ret);
   1267 }
   1268 
   1269 /**
   1270  * xmlRelaxNGCopyValidState:
   1271  * @ctxt:  a Relax-NG validation context
   1272  * @state:  a validation state
   1273  *
   1274  * Copy the validation state
   1275  *
   1276  * Returns the newly allocated structure or NULL in case or error
   1277  */
   1278 static xmlRelaxNGValidStatePtr
   1279 xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
   1280                          xmlRelaxNGValidStatePtr state)
   1281 {
   1282     xmlRelaxNGValidStatePtr ret;
   1283     unsigned int maxAttrs;
   1284     xmlAttrPtr *attrs;
   1285 
   1286     if (state == NULL)
   1287         return (NULL);
   1288     if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
   1289         ctxt->freeState->nbState--;
   1290         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
   1291     } else {
   1292         ret =
   1293             (xmlRelaxNGValidStatePtr)
   1294             xmlMalloc(sizeof(xmlRelaxNGValidState));
   1295         if (ret == NULL) {
   1296             xmlRngVErrMemory(ctxt, "allocating states\n");
   1297             return (NULL);
   1298         }
   1299         memset(ret, 0, sizeof(xmlRelaxNGValidState));
   1300     }
   1301     attrs = ret->attrs;
   1302     maxAttrs = ret->maxAttrs;
   1303     memcpy(ret, state, sizeof(xmlRelaxNGValidState));
   1304     ret->attrs = attrs;
   1305     ret->maxAttrs = maxAttrs;
   1306     if (state->nbAttrs > 0) {
   1307         if (ret->attrs == NULL) {
   1308             ret->maxAttrs = state->maxAttrs;
   1309             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
   1310                                                   sizeof(xmlAttrPtr));
   1311             if (ret->attrs == NULL) {
   1312                 xmlRngVErrMemory(ctxt, "allocating states\n");
   1313                 ret->nbAttrs = 0;
   1314                 return (ret);
   1315             }
   1316         } else if (ret->maxAttrs < state->nbAttrs) {
   1317             xmlAttrPtr *tmp;
   1318 
   1319             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *
   1320                                             sizeof(xmlAttrPtr));
   1321             if (tmp == NULL) {
   1322                 xmlRngVErrMemory(ctxt, "allocating states\n");
   1323                 ret->nbAttrs = 0;
   1324                 return (ret);
   1325             }
   1326             ret->maxAttrs = state->maxAttrs;
   1327             ret->attrs = tmp;
   1328         }
   1329         memcpy(ret->attrs, state->attrs,
   1330                state->nbAttrs * sizeof(xmlAttrPtr));
   1331     }
   1332     return (ret);
   1333 }
   1334 
   1335 /**
   1336  * xmlRelaxNGEqualValidState:
   1337  * @ctxt:  a Relax-NG validation context
   1338  * @state1:  a validation state
   1339  * @state2:  a validation state
   1340  *
   1341  * Compare the validation states for equality
   1342  *
   1343  * Returns 1 if equald, 0 otherwise
   1344  */
   1345 static int
   1346 xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
   1347                           xmlRelaxNGValidStatePtr state1,
   1348                           xmlRelaxNGValidStatePtr state2)
   1349 {
   1350     int i;
   1351 
   1352     if ((state1 == NULL) || (state2 == NULL))
   1353         return (0);
   1354     if (state1 == state2)
   1355         return (1);
   1356     if (state1->node != state2->node)
   1357         return (0);
   1358     if (state1->seq != state2->seq)
   1359         return (0);
   1360     if (state1->nbAttrLeft != state2->nbAttrLeft)
   1361         return (0);
   1362     if (state1->nbAttrs != state2->nbAttrs)
   1363         return (0);
   1364     if (state1->endvalue != state2->endvalue)
   1365         return (0);
   1366     if ((state1->value != state2->value) &&
   1367         (!xmlStrEqual(state1->value, state2->value)))
   1368         return (0);
   1369     for (i = 0; i < state1->nbAttrs; i++) {
   1370         if (state1->attrs[i] != state2->attrs[i])
   1371             return (0);
   1372     }
   1373     return (1);
   1374 }
   1375 
   1376 /**
   1377  * xmlRelaxNGFreeValidState:
   1378  * @state:  a validation state structure
   1379  *
   1380  * Deallocate a RelaxNG validation state structure.
   1381  */
   1382 static void
   1383 xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
   1384                          xmlRelaxNGValidStatePtr state)
   1385 {
   1386     if (state == NULL)
   1387         return;
   1388 
   1389     if ((ctxt != NULL) && (ctxt->freeState == NULL)) {
   1390         ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40);
   1391     }
   1392     if ((ctxt == NULL) || (ctxt->freeState == NULL)) {
   1393         if (state->attrs != NULL)
   1394             xmlFree(state->attrs);
   1395         xmlFree(state);
   1396     } else {
   1397         xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state);
   1398     }
   1399 }
   1400 
   1401 /************************************************************************
   1402  *									*
   1403  *			Semi internal functions				*
   1404  *									*
   1405  ************************************************************************/
   1406 
   1407 /**
   1408  * xmlRelaxParserSetFlag:
   1409  * @ctxt: a RelaxNG parser context
   1410  * @flags: a set of flags values
   1411  *
   1412  * Semi private function used to pass informations to a parser context
   1413  * which are a combination of xmlRelaxNGParserFlag .
   1414  *
   1415  * Returns 0 if success and -1 in case of error
   1416  */
   1417 int
   1418 xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags)
   1419 {
   1420     if (ctxt == NULL) return(-1);
   1421     if (flags & XML_RELAXNGP_FREE_DOC) {
   1422         ctxt->crng |= XML_RELAXNGP_FREE_DOC;
   1423 	flags -= XML_RELAXNGP_FREE_DOC;
   1424     }
   1425     if (flags & XML_RELAXNGP_CRNG) {
   1426         ctxt->crng |= XML_RELAXNGP_CRNG;
   1427 	flags -= XML_RELAXNGP_CRNG;
   1428     }
   1429     if (flags != 0) return(-1);
   1430     return(0);
   1431 }
   1432 
   1433 /************************************************************************
   1434  *									*
   1435  *			Document functions				*
   1436  *									*
   1437  ************************************************************************/
   1438 static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
   1439                                       xmlDocPtr doc);
   1440 
   1441 /**
   1442  * xmlRelaxNGIncludePush:
   1443  * @ctxt:  the parser context
   1444  * @value:  the element doc
   1445  *
   1446  * Pushes a new include on top of the include stack
   1447  *
   1448  * Returns 0 in case of error, the index in the stack otherwise
   1449  */
   1450 static int
   1451 xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
   1452                       xmlRelaxNGIncludePtr value)
   1453 {
   1454     if (ctxt->incTab == NULL) {
   1455         ctxt->incMax = 4;
   1456         ctxt->incNr = 0;
   1457         ctxt->incTab =
   1458             (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *
   1459                                                sizeof(ctxt->incTab[0]));
   1460         if (ctxt->incTab == NULL) {
   1461             xmlRngPErrMemory(ctxt, "allocating include\n");
   1462             return (0);
   1463         }
   1464     }
   1465     if (ctxt->incNr >= ctxt->incMax) {
   1466         ctxt->incMax *= 2;
   1467         ctxt->incTab =
   1468             (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,
   1469                                                 ctxt->incMax *
   1470                                                 sizeof(ctxt->incTab[0]));
   1471         if (ctxt->incTab == NULL) {
   1472             xmlRngPErrMemory(ctxt, "allocating include\n");
   1473             return (0);
   1474         }
   1475     }
   1476     ctxt->incTab[ctxt->incNr] = value;
   1477     ctxt->inc = value;
   1478     return (ctxt->incNr++);
   1479 }
   1480 
   1481 /**
   1482  * xmlRelaxNGIncludePop:
   1483  * @ctxt: the parser context
   1484  *
   1485  * Pops the top include from the include stack
   1486  *
   1487  * Returns the include just removed
   1488  */
   1489 static xmlRelaxNGIncludePtr
   1490 xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt)
   1491 {
   1492     xmlRelaxNGIncludePtr ret;
   1493 
   1494     if (ctxt->incNr <= 0)
   1495         return (NULL);
   1496     ctxt->incNr--;
   1497     if (ctxt->incNr > 0)
   1498         ctxt->inc = ctxt->incTab[ctxt->incNr - 1];
   1499     else
   1500         ctxt->inc = NULL;
   1501     ret = ctxt->incTab[ctxt->incNr];
   1502     ctxt->incTab[ctxt->incNr] = NULL;
   1503     return (ret);
   1504 }
   1505 
   1506 /**
   1507  * xmlRelaxNGRemoveRedefine:
   1508  * @ctxt: the parser context
   1509  * @URL:  the normalized URL
   1510  * @target:  the included target
   1511  * @name:  the define name to eliminate
   1512  *
   1513  * Applies the elimination algorithm of 4.7
   1514  *
   1515  * Returns 0 in case of error, 1 in case of success.
   1516  */
   1517 static int
   1518 xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
   1519                          const xmlChar * URL ATTRIBUTE_UNUSED,
   1520                          xmlNodePtr target, const xmlChar * name)
   1521 {
   1522     int found = 0;
   1523     xmlNodePtr tmp, tmp2;
   1524     xmlChar *name2;
   1525 
   1526 #ifdef DEBUG_INCLUDE
   1527     if (name == NULL)
   1528         xmlGenericError(xmlGenericErrorContext,
   1529                         "Elimination of <include> start from %s\n", URL);
   1530     else
   1531         xmlGenericError(xmlGenericErrorContext,
   1532                         "Elimination of <include> define %s from %s\n",
   1533                         name, URL);
   1534 #endif
   1535     tmp = target;
   1536     while (tmp != NULL) {
   1537         tmp2 = tmp->next;
   1538         if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) {
   1539             found = 1;
   1540             xmlUnlinkNode(tmp);
   1541             xmlFreeNode(tmp);
   1542         } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) {
   1543             name2 = xmlGetProp(tmp, BAD_CAST "name");
   1544             xmlRelaxNGNormExtSpace(name2);
   1545             if (name2 != NULL) {
   1546                 if (xmlStrEqual(name, name2)) {
   1547                     found = 1;
   1548                     xmlUnlinkNode(tmp);
   1549                     xmlFreeNode(tmp);
   1550                 }
   1551                 xmlFree(name2);
   1552             }
   1553         } else if (IS_RELAXNG(tmp, "include")) {
   1554             xmlChar *href = NULL;
   1555             xmlRelaxNGDocumentPtr inc = tmp->psvi;
   1556 
   1557             if ((inc != NULL) && (inc->doc != NULL) &&
   1558                 (inc->doc->children != NULL)) {
   1559 
   1560                 if (xmlStrEqual
   1561                     (inc->doc->children->name, BAD_CAST "grammar")) {
   1562 #ifdef DEBUG_INCLUDE
   1563                     href = xmlGetProp(tmp, BAD_CAST "href");
   1564 #endif
   1565                     if (xmlRelaxNGRemoveRedefine(ctxt, href,
   1566                                                  xmlDocGetRootElement(inc->doc)->children,
   1567                                                  name) == 1) {
   1568                         found = 1;
   1569                     }
   1570 #ifdef DEBUG_INCLUDE
   1571                     if (href != NULL)
   1572                         xmlFree(href);
   1573 #endif
   1574                 }
   1575             }
   1576             if (xmlRelaxNGRemoveRedefine(ctxt, URL, tmp->children, name) == 1) {
   1577                 found = 1;
   1578             }
   1579         }
   1580         tmp = tmp2;
   1581     }
   1582     return (found);
   1583 }
   1584 
   1585 /**
   1586  * xmlRelaxNGLoadInclude:
   1587  * @ctxt: the parser context
   1588  * @URL:  the normalized URL
   1589  * @node: the include node.
   1590  * @ns:  the namespace passed from the context.
   1591  *
   1592  * First lookup if the document is already loaded into the parser context,
   1593  * check against recursion. If not found the resource is loaded and
   1594  * the content is preprocessed before being returned back to the caller.
   1595  *
   1596  * Returns the xmlRelaxNGIncludePtr or NULL in case of error
   1597  */
   1598 static xmlRelaxNGIncludePtr
   1599 xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
   1600                       xmlNodePtr node, const xmlChar * ns)
   1601 {
   1602     xmlRelaxNGIncludePtr ret = NULL;
   1603     xmlDocPtr doc;
   1604     int i;
   1605     xmlNodePtr root, cur;
   1606 
   1607 #ifdef DEBUG_INCLUDE
   1608     xmlGenericError(xmlGenericErrorContext,
   1609                     "xmlRelaxNGLoadInclude(%s)\n", URL);
   1610 #endif
   1611 
   1612     /*
   1613      * check against recursion in the stack
   1614      */
   1615     for (i = 0; i < ctxt->incNr; i++) {
   1616         if (xmlStrEqual(ctxt->incTab[i]->href, URL)) {
   1617             xmlRngPErr(ctxt, NULL, XML_RNGP_INCLUDE_RECURSE,
   1618                        "Detected an Include recursion for %s\n", URL,
   1619                        NULL);
   1620             return (NULL);
   1621         }
   1622     }
   1623 
   1624     /*
   1625      * load the document
   1626      */
   1627     doc = xmlReadFile((const char *) URL,NULL,0);
   1628     if (doc == NULL) {
   1629         xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR,
   1630                    "xmlRelaxNG: could not load %s\n", URL, NULL);
   1631         return (NULL);
   1632     }
   1633 #ifdef DEBUG_INCLUDE
   1634     xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL);
   1635 #endif
   1636 
   1637     /*
   1638      * Allocate the document structures and register it first.
   1639      */
   1640     ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));
   1641     if (ret == NULL) {
   1642         xmlRngPErrMemory(ctxt, "allocating include\n");
   1643         xmlFreeDoc(doc);
   1644         return (NULL);
   1645     }
   1646     memset(ret, 0, sizeof(xmlRelaxNGInclude));
   1647     ret->doc = doc;
   1648     ret->href = xmlStrdup(URL);
   1649     ret->next = ctxt->includes;
   1650     ctxt->includes = ret;
   1651 
   1652     /*
   1653      * transmit the ns if needed
   1654      */
   1655     if (ns != NULL) {
   1656         root = xmlDocGetRootElement(doc);
   1657         if (root != NULL) {
   1658             if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
   1659                 xmlSetProp(root, BAD_CAST "ns", ns);
   1660             }
   1661         }
   1662     }
   1663 
   1664     /*
   1665      * push it on the stack
   1666      */
   1667     xmlRelaxNGIncludePush(ctxt, ret);
   1668 
   1669     /*
   1670      * Some preprocessing of the document content, this include recursing
   1671      * in the include stack.
   1672      */
   1673 #ifdef DEBUG_INCLUDE
   1674     xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL);
   1675 #endif
   1676 
   1677     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
   1678     if (doc == NULL) {
   1679         ctxt->inc = NULL;
   1680         return (NULL);
   1681     }
   1682 
   1683     /*
   1684      * Pop up the include from the stack
   1685      */
   1686     xmlRelaxNGIncludePop(ctxt);
   1687 
   1688 #ifdef DEBUG_INCLUDE
   1689     xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL);
   1690 #endif
   1691     /*
   1692      * Check that the top element is a grammar
   1693      */
   1694     root = xmlDocGetRootElement(doc);
   1695     if (root == NULL) {
   1696         xmlRngPErr(ctxt, node, XML_RNGP_EMPTY,
   1697                    "xmlRelaxNG: included document is empty %s\n", URL,
   1698                    NULL);
   1699         return (NULL);
   1700     }
   1701     if (!IS_RELAXNG(root, "grammar")) {
   1702         xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
   1703                    "xmlRelaxNG: included document %s root is not a grammar\n",
   1704                    URL, NULL);
   1705         return (NULL);
   1706     }
   1707 
   1708     /*
   1709      * Elimination of redefined rules in the include.
   1710      */
   1711     cur = node->children;
   1712     while (cur != NULL) {
   1713         if (IS_RELAXNG(cur, "start")) {
   1714             int found = 0;
   1715 
   1716             found =
   1717                 xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);
   1718             if (!found) {
   1719                 xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING,
   1720                            "xmlRelaxNG: include %s has a start but not the included grammar\n",
   1721                            URL, NULL);
   1722             }
   1723         } else if (IS_RELAXNG(cur, "define")) {
   1724             xmlChar *name;
   1725 
   1726             name = xmlGetProp(cur, BAD_CAST "name");
   1727             if (name == NULL) {
   1728                 xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING,
   1729                            "xmlRelaxNG: include %s has define without name\n",
   1730                            URL, NULL);
   1731             } else {
   1732                 int found;
   1733 
   1734                 xmlRelaxNGNormExtSpace(name);
   1735                 found = xmlRelaxNGRemoveRedefine(ctxt, URL,
   1736                                                  root->children, name);
   1737                 if (!found) {
   1738                     xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING,
   1739                                "xmlRelaxNG: include %s has a define %s but not the included grammar\n",
   1740                                URL, name);
   1741                 }
   1742                 xmlFree(name);
   1743             }
   1744         }
   1745         if (IS_RELAXNG(cur, "div") && cur->children != NULL) {
   1746             cur = cur->children;
   1747         } else {
   1748             if (cur->next != NULL) {
   1749                 cur = cur->next;
   1750             } else {
   1751                 while (cur->parent != node && cur->parent->next == NULL) {
   1752                     cur = cur->parent;
   1753                 }
   1754                 cur = cur->parent != node ? cur->parent->next : NULL;
   1755             }
   1756         }
   1757     }
   1758 
   1759 
   1760     return (ret);
   1761 }
   1762 
   1763 /**
   1764  * xmlRelaxNGValidErrorPush:
   1765  * @ctxt:  the validation context
   1766  * @err:  the error code
   1767  * @arg1:  the first string argument
   1768  * @arg2:  the second string argument
   1769  * @dup:  arg need to be duplicated
   1770  *
   1771  * Pushes a new error on top of the error stack
   1772  *
   1773  * Returns 0 in case of error, the index in the stack otherwise
   1774  */
   1775 static int
   1776 xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
   1777                          xmlRelaxNGValidErr err, const xmlChar * arg1,
   1778                          const xmlChar * arg2, int dup)
   1779 {
   1780     xmlRelaxNGValidErrorPtr cur;
   1781 
   1782 #ifdef DEBUG_ERROR
   1783     xmlGenericError(xmlGenericErrorContext,
   1784                     "Pushing error %d at %d on stack\n", err, ctxt->errNr);
   1785 #endif
   1786     if (ctxt->errTab == NULL) {
   1787         ctxt->errMax = 8;
   1788         ctxt->errNr = 0;
   1789         ctxt->errTab =
   1790             (xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax *
   1791                                                 sizeof
   1792                                                 (xmlRelaxNGValidError));
   1793         if (ctxt->errTab == NULL) {
   1794             xmlRngVErrMemory(ctxt, "pushing error\n");
   1795             return (0);
   1796         }
   1797         ctxt->err = NULL;
   1798     }
   1799     if (ctxt->errNr >= ctxt->errMax) {
   1800         ctxt->errMax *= 2;
   1801         ctxt->errTab =
   1802             (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,
   1803                                                  ctxt->errMax *
   1804                                                  sizeof
   1805                                                  (xmlRelaxNGValidError));
   1806         if (ctxt->errTab == NULL) {
   1807             xmlRngVErrMemory(ctxt, "pushing error\n");
   1808             return (0);
   1809         }
   1810         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
   1811     }
   1812     if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
   1813         (ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err))
   1814         return (ctxt->errNr);
   1815     cur = &ctxt->errTab[ctxt->errNr];
   1816     cur->err = err;
   1817     if (dup) {
   1818         cur->arg1 = xmlStrdup(arg1);
   1819         cur->arg2 = xmlStrdup(arg2);
   1820         cur->flags = ERROR_IS_DUP;
   1821     } else {
   1822         cur->arg1 = arg1;
   1823         cur->arg2 = arg2;
   1824         cur->flags = 0;
   1825     }
   1826     if (ctxt->state != NULL) {
   1827         cur->node = ctxt->state->node;
   1828         cur->seq = ctxt->state->seq;
   1829     } else {
   1830         cur->node = NULL;
   1831         cur->seq = NULL;
   1832     }
   1833     ctxt->err = cur;
   1834     return (ctxt->errNr++);
   1835 }
   1836 
   1837 /**
   1838  * xmlRelaxNGValidErrorPop:
   1839  * @ctxt: the validation context
   1840  *
   1841  * Pops the top error from the error stack
   1842  */
   1843 static void
   1844 xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
   1845 {
   1846     xmlRelaxNGValidErrorPtr cur;
   1847 
   1848     if (ctxt->errNr <= 0) {
   1849         ctxt->err = NULL;
   1850         return;
   1851     }
   1852     ctxt->errNr--;
   1853     if (ctxt->errNr > 0)
   1854         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
   1855     else
   1856         ctxt->err = NULL;
   1857     cur = &ctxt->errTab[ctxt->errNr];
   1858     if (cur->flags & ERROR_IS_DUP) {
   1859         if (cur->arg1 != NULL)
   1860             xmlFree((xmlChar *) cur->arg1);
   1861         cur->arg1 = NULL;
   1862         if (cur->arg2 != NULL)
   1863             xmlFree((xmlChar *) cur->arg2);
   1864         cur->arg2 = NULL;
   1865         cur->flags = 0;
   1866     }
   1867 }
   1868 
   1869 /**
   1870  * xmlRelaxNGDocumentPush:
   1871  * @ctxt:  the parser context
   1872  * @value:  the element doc
   1873  *
   1874  * Pushes a new doc on top of the doc stack
   1875  *
   1876  * Returns 0 in case of error, the index in the stack otherwise
   1877  */
   1878 static int
   1879 xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
   1880                        xmlRelaxNGDocumentPtr value)
   1881 {
   1882     if (ctxt->docTab == NULL) {
   1883         ctxt->docMax = 4;
   1884         ctxt->docNr = 0;
   1885         ctxt->docTab =
   1886             (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *
   1887                                                 sizeof(ctxt->docTab[0]));
   1888         if (ctxt->docTab == NULL) {
   1889             xmlRngPErrMemory(ctxt, "adding document\n");
   1890             return (0);
   1891         }
   1892     }
   1893     if (ctxt->docNr >= ctxt->docMax) {
   1894         ctxt->docMax *= 2;
   1895         ctxt->docTab =
   1896             (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,
   1897                                                  ctxt->docMax *
   1898                                                  sizeof(ctxt->docTab[0]));
   1899         if (ctxt->docTab == NULL) {
   1900             xmlRngPErrMemory(ctxt, "adding document\n");
   1901             return (0);
   1902         }
   1903     }
   1904     ctxt->docTab[ctxt->docNr] = value;
   1905     ctxt->doc = value;
   1906     return (ctxt->docNr++);
   1907 }
   1908 
   1909 /**
   1910  * xmlRelaxNGDocumentPop:
   1911  * @ctxt: the parser context
   1912  *
   1913  * Pops the top doc from the doc stack
   1914  *
   1915  * Returns the doc just removed
   1916  */
   1917 static xmlRelaxNGDocumentPtr
   1918 xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)
   1919 {
   1920     xmlRelaxNGDocumentPtr ret;
   1921 
   1922     if (ctxt->docNr <= 0)
   1923         return (NULL);
   1924     ctxt->docNr--;
   1925     if (ctxt->docNr > 0)
   1926         ctxt->doc = ctxt->docTab[ctxt->docNr - 1];
   1927     else
   1928         ctxt->doc = NULL;
   1929     ret = ctxt->docTab[ctxt->docNr];
   1930     ctxt->docTab[ctxt->docNr] = NULL;
   1931     return (ret);
   1932 }
   1933 
   1934 /**
   1935  * xmlRelaxNGLoadExternalRef:
   1936  * @ctxt: the parser context
   1937  * @URL:  the normalized URL
   1938  * @ns:  the inherited ns if any
   1939  *
   1940  * First lookup if the document is already loaded into the parser context,
   1941  * check against recursion. If not found the resource is loaded and
   1942  * the content is preprocessed before being returned back to the caller.
   1943  *
   1944  * Returns the xmlRelaxNGDocumentPtr or NULL in case of error
   1945  */
   1946 static xmlRelaxNGDocumentPtr
   1947 xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
   1948                           const xmlChar * URL, const xmlChar * ns)
   1949 {
   1950     xmlRelaxNGDocumentPtr ret = NULL;
   1951     xmlDocPtr doc;
   1952     xmlNodePtr root;
   1953     int i;
   1954 
   1955     /*
   1956      * check against recursion in the stack
   1957      */
   1958     for (i = 0; i < ctxt->docNr; i++) {
   1959         if (xmlStrEqual(ctxt->docTab[i]->href, URL)) {
   1960             xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE,
   1961                        "Detected an externalRef recursion for %s\n", URL,
   1962                        NULL);
   1963             return (NULL);
   1964         }
   1965     }
   1966 
   1967     /*
   1968      * load the document
   1969      */
   1970     doc = xmlReadFile((const char *) URL,NULL,0);
   1971     if (doc == NULL) {
   1972         xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
   1973                    "xmlRelaxNG: could not load %s\n", URL, NULL);
   1974         return (NULL);
   1975     }
   1976 
   1977     /*
   1978      * Allocate the document structures and register it first.
   1979      */
   1980     ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
   1981     if (ret == NULL) {
   1982         xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,
   1983                    "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);
   1984         xmlFreeDoc(doc);
   1985         return (NULL);
   1986     }
   1987     memset(ret, 0, sizeof(xmlRelaxNGDocument));
   1988     ret->doc = doc;
   1989     ret->href = xmlStrdup(URL);
   1990     ret->next = ctxt->documents;
   1991     ret->externalRef = 1;
   1992     ctxt->documents = ret;
   1993 
   1994     /*
   1995      * transmit the ns if needed
   1996      */
   1997     if (ns != NULL) {
   1998         root = xmlDocGetRootElement(doc);
   1999         if (root != NULL) {
   2000             if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
   2001                 xmlSetProp(root, BAD_CAST "ns", ns);
   2002             }
   2003         }
   2004     }
   2005 
   2006     /*
   2007      * push it on the stack and register it in the hash table
   2008      */
   2009     xmlRelaxNGDocumentPush(ctxt, ret);
   2010 
   2011     /*
   2012      * Some preprocessing of the document content
   2013      */
   2014     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
   2015     if (doc == NULL) {
   2016         ctxt->doc = NULL;
   2017         return (NULL);
   2018     }
   2019 
   2020     xmlRelaxNGDocumentPop(ctxt);
   2021 
   2022     return (ret);
   2023 }
   2024 
   2025 /************************************************************************
   2026  *									*
   2027  *			Error functions					*
   2028  *									*
   2029  ************************************************************************/
   2030 
   2031 #define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
   2032 #define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
   2033 #define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
   2034 #define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
   2035 #define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
   2036 
   2037 static const char *
   2038 xmlRelaxNGDefName(xmlRelaxNGDefinePtr def)
   2039 {
   2040     if (def == NULL)
   2041         return ("none");
   2042     switch (def->type) {
   2043         case XML_RELAXNG_EMPTY:
   2044             return ("empty");
   2045         case XML_RELAXNG_NOT_ALLOWED:
   2046             return ("notAllowed");
   2047         case XML_RELAXNG_EXCEPT:
   2048             return ("except");
   2049         case XML_RELAXNG_TEXT:
   2050             return ("text");
   2051         case XML_RELAXNG_ELEMENT:
   2052             return ("element");
   2053         case XML_RELAXNG_DATATYPE:
   2054             return ("datatype");
   2055         case XML_RELAXNG_VALUE:
   2056             return ("value");
   2057         case XML_RELAXNG_LIST:
   2058             return ("list");
   2059         case XML_RELAXNG_ATTRIBUTE:
   2060             return ("attribute");
   2061         case XML_RELAXNG_DEF:
   2062             return ("def");
   2063         case XML_RELAXNG_REF:
   2064             return ("ref");
   2065         case XML_RELAXNG_EXTERNALREF:
   2066             return ("externalRef");
   2067         case XML_RELAXNG_PARENTREF:
   2068             return ("parentRef");
   2069         case XML_RELAXNG_OPTIONAL:
   2070             return ("optional");
   2071         case XML_RELAXNG_ZEROORMORE:
   2072             return ("zeroOrMore");
   2073         case XML_RELAXNG_ONEORMORE:
   2074             return ("oneOrMore");
   2075         case XML_RELAXNG_CHOICE:
   2076             return ("choice");
   2077         case XML_RELAXNG_GROUP:
   2078             return ("group");
   2079         case XML_RELAXNG_INTERLEAVE:
   2080             return ("interleave");
   2081         case XML_RELAXNG_START:
   2082             return ("start");
   2083         case XML_RELAXNG_NOOP:
   2084             return ("noop");
   2085         case XML_RELAXNG_PARAM:
   2086             return ("param");
   2087     }
   2088     return ("unknown");
   2089 }
   2090 
   2091 /**
   2092  * xmlRelaxNGGetErrorString:
   2093  * @err:  the error code
   2094  * @arg1:  the first string argument
   2095  * @arg2:  the second string argument
   2096  *
   2097  * computes a formatted error string for the given error code and args
   2098  *
   2099  * Returns the error string, it must be deallocated by the caller
   2100  */
   2101 static xmlChar *
   2102 xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
   2103                          const xmlChar * arg2)
   2104 {
   2105     char msg[1000];
   2106     xmlChar *result;
   2107 
   2108     if (arg1 == NULL)
   2109         arg1 = BAD_CAST "";
   2110     if (arg2 == NULL)
   2111         arg2 = BAD_CAST "";
   2112 
   2113     msg[0] = 0;
   2114     switch (err) {
   2115         case XML_RELAXNG_OK:
   2116             return (NULL);
   2117         case XML_RELAXNG_ERR_MEMORY:
   2118             return (xmlCharStrdup("out of memory\n"));
   2119         case XML_RELAXNG_ERR_TYPE:
   2120             snprintf(msg, 1000, "failed to validate type %s\n", arg1);
   2121             break;
   2122         case XML_RELAXNG_ERR_TYPEVAL:
   2123             snprintf(msg, 1000, "Type %s doesn't allow value '%s'\n", arg1,
   2124                      arg2);
   2125             break;
   2126         case XML_RELAXNG_ERR_DUPID:
   2127             snprintf(msg, 1000, "ID %s redefined\n", arg1);
   2128             break;
   2129         case XML_RELAXNG_ERR_TYPECMP:
   2130             snprintf(msg, 1000, "failed to compare type %s\n", arg1);
   2131             break;
   2132         case XML_RELAXNG_ERR_NOSTATE:
   2133             return (xmlCharStrdup("Internal error: no state\n"));
   2134         case XML_RELAXNG_ERR_NODEFINE:
   2135             return (xmlCharStrdup("Internal error: no define\n"));
   2136         case XML_RELAXNG_ERR_INTERNAL:
   2137             snprintf(msg, 1000, "Internal error: %s\n", arg1);
   2138             break;
   2139         case XML_RELAXNG_ERR_LISTEXTRA:
   2140             snprintf(msg, 1000, "Extra data in list: %s\n", arg1);
   2141             break;
   2142         case XML_RELAXNG_ERR_INTERNODATA:
   2143             return (xmlCharStrdup
   2144                     ("Internal: interleave block has no data\n"));
   2145         case XML_RELAXNG_ERR_INTERSEQ:
   2146             return (xmlCharStrdup("Invalid sequence in interleave\n"));
   2147         case XML_RELAXNG_ERR_INTEREXTRA:
   2148             snprintf(msg, 1000, "Extra element %s in interleave\n", arg1);
   2149             break;
   2150         case XML_RELAXNG_ERR_ELEMNAME:
   2151             snprintf(msg, 1000, "Expecting element %s, got %s\n", arg1,
   2152                      arg2);
   2153             break;
   2154         case XML_RELAXNG_ERR_ELEMNONS:
   2155             snprintf(msg, 1000, "Expecting a namespace for element %s\n",
   2156                      arg1);
   2157             break;
   2158         case XML_RELAXNG_ERR_ELEMWRONGNS:
   2159             snprintf(msg, 1000,
   2160                      "Element %s has wrong namespace: expecting %s\n", arg1,
   2161                      arg2);
   2162             break;
   2163         case XML_RELAXNG_ERR_ELEMWRONG:
   2164             snprintf(msg, 1000, "Did not expect element %s there\n", arg1);
   2165             break;
   2166         case XML_RELAXNG_ERR_TEXTWRONG:
   2167             snprintf(msg, 1000,
   2168                      "Did not expect text in element %s content\n", arg1);
   2169             break;
   2170         case XML_RELAXNG_ERR_ELEMEXTRANS:
   2171             snprintf(msg, 1000, "Expecting no namespace for element %s\n",
   2172                      arg1);
   2173             break;
   2174         case XML_RELAXNG_ERR_ELEMNOTEMPTY:
   2175             snprintf(msg, 1000, "Expecting element %s to be empty\n", arg1);
   2176             break;
   2177         case XML_RELAXNG_ERR_NOELEM:
   2178             snprintf(msg, 1000, "Expecting an element %s, got nothing\n",
   2179                      arg1);
   2180             break;
   2181         case XML_RELAXNG_ERR_NOTELEM:
   2182             return (xmlCharStrdup("Expecting an element got text\n"));
   2183         case XML_RELAXNG_ERR_ATTRVALID:
   2184             snprintf(msg, 1000, "Element %s failed to validate attributes\n",
   2185                      arg1);
   2186             break;
   2187         case XML_RELAXNG_ERR_CONTENTVALID:
   2188             snprintf(msg, 1000, "Element %s failed to validate content\n",
   2189                      arg1);
   2190             break;
   2191         case XML_RELAXNG_ERR_EXTRACONTENT:
   2192             snprintf(msg, 1000, "Element %s has extra content: %s\n",
   2193                      arg1, arg2);
   2194             break;
   2195         case XML_RELAXNG_ERR_INVALIDATTR:
   2196             snprintf(msg, 1000, "Invalid attribute %s for element %s\n",
   2197                      arg1, arg2);
   2198             break;
   2199         case XML_RELAXNG_ERR_LACKDATA:
   2200             snprintf(msg, 1000, "Datatype element %s contains no data\n",
   2201                      arg1);
   2202             break;
   2203         case XML_RELAXNG_ERR_DATAELEM:
   2204             snprintf(msg, 1000, "Datatype element %s has child elements\n",
   2205                      arg1);
   2206             break;
   2207         case XML_RELAXNG_ERR_VALELEM:
   2208             snprintf(msg, 1000, "Value element %s has child elements\n",
   2209                      arg1);
   2210             break;
   2211         case XML_RELAXNG_ERR_LISTELEM:
   2212             snprintf(msg, 1000, "List element %s has child elements\n",
   2213                      arg1);
   2214             break;
   2215         case XML_RELAXNG_ERR_DATATYPE:
   2216             snprintf(msg, 1000, "Error validating datatype %s\n", arg1);
   2217             break;
   2218         case XML_RELAXNG_ERR_VALUE:
   2219             snprintf(msg, 1000, "Error validating value %s\n", arg1);
   2220             break;
   2221         case XML_RELAXNG_ERR_LIST:
   2222             return (xmlCharStrdup("Error validating list\n"));
   2223         case XML_RELAXNG_ERR_NOGRAMMAR:
   2224             return (xmlCharStrdup("No top grammar defined\n"));
   2225         case XML_RELAXNG_ERR_EXTRADATA:
   2226             return (xmlCharStrdup("Extra data in the document\n"));
   2227         default:
   2228             return (xmlCharStrdup("Unknown error !\n"));
   2229     }
   2230     if (msg[0] == 0) {
   2231         snprintf(msg, 1000, "Unknown error code %d\n", err);
   2232     }
   2233     msg[1000 - 1] = 0;
   2234     result = xmlCharStrdup(msg);
   2235     return (xmlEscapeFormatString(&result));
   2236 }
   2237 
   2238 /**
   2239  * xmlRelaxNGShowValidError:
   2240  * @ctxt:  the validation context
   2241  * @err:  the error number
   2242  * @node:  the node
   2243  * @child:  the node child generating the problem.
   2244  * @arg1:  the first argument
   2245  * @arg2:  the second argument
   2246  *
   2247  * Show a validation error.
   2248  */
   2249 static void
   2250 xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt,
   2251                          xmlRelaxNGValidErr err, xmlNodePtr node,
   2252                          xmlNodePtr child, const xmlChar * arg1,
   2253                          const xmlChar * arg2)
   2254 {
   2255     xmlChar *msg;
   2256 
   2257     if (ctxt->flags & FLAGS_NOERROR)
   2258         return;
   2259 
   2260 #ifdef DEBUG_ERROR
   2261     xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err);
   2262 #endif
   2263     msg = xmlRelaxNGGetErrorString(err, arg1, arg2);
   2264     if (msg == NULL)
   2265         return;
   2266 
   2267     if (ctxt->errNo == XML_RELAXNG_OK)
   2268         ctxt->errNo = err;
   2269     xmlRngVErr(ctxt, (child == NULL ? node : child), err,
   2270                (const char *) msg, arg1, arg2);
   2271     xmlFree(msg);
   2272 }
   2273 
   2274 /**
   2275  * xmlRelaxNGPopErrors:
   2276  * @ctxt:  the validation context
   2277  * @level:  the error level in the stack
   2278  *
   2279  * pop and discard all errors until the given level is reached
   2280  */
   2281 static void
   2282 xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level)
   2283 {
   2284     int i;
   2285     xmlRelaxNGValidErrorPtr err;
   2286 
   2287 #ifdef DEBUG_ERROR
   2288     xmlGenericError(xmlGenericErrorContext,
   2289                     "Pop errors till level %d\n", level);
   2290 #endif
   2291     for (i = level; i < ctxt->errNr; i++) {
   2292         err = &ctxt->errTab[i];
   2293         if (err->flags & ERROR_IS_DUP) {
   2294             if (err->arg1 != NULL)
   2295                 xmlFree((xmlChar *) err->arg1);
   2296             err->arg1 = NULL;
   2297             if (err->arg2 != NULL)
   2298                 xmlFree((xmlChar *) err->arg2);
   2299             err->arg2 = NULL;
   2300             err->flags = 0;
   2301         }
   2302     }
   2303     ctxt->errNr = level;
   2304     if (ctxt->errNr <= 0)
   2305         ctxt->err = NULL;
   2306 }
   2307 
   2308 /**
   2309  * xmlRelaxNGDumpValidError:
   2310  * @ctxt:  the validation context
   2311  *
   2312  * Show all validation error over a given index.
   2313  */
   2314 static void
   2315 xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt)
   2316 {
   2317     int i, j, k;
   2318     xmlRelaxNGValidErrorPtr err, dup;
   2319 
   2320 #ifdef DEBUG_ERROR
   2321     xmlGenericError(xmlGenericErrorContext,
   2322                     "Dumping error stack %d errors\n", ctxt->errNr);
   2323 #endif
   2324     for (i = 0, k = 0; i < ctxt->errNr; i++) {
   2325         err = &ctxt->errTab[i];
   2326         if (k < MAX_ERROR) {
   2327             for (j = 0; j < i; j++) {
   2328                 dup = &ctxt->errTab[j];
   2329                 if ((err->err == dup->err) && (err->node == dup->node) &&
   2330                     (xmlStrEqual(err->arg1, dup->arg1)) &&
   2331                     (xmlStrEqual(err->arg2, dup->arg2))) {
   2332                     goto skip;
   2333                 }
   2334             }
   2335             xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,
   2336                                      err->arg1, err->arg2);
   2337             k++;
   2338         }
   2339       skip:
   2340         if (err->flags & ERROR_IS_DUP) {
   2341             if (err->arg1 != NULL)
   2342                 xmlFree((xmlChar *) err->arg1);
   2343             err->arg1 = NULL;
   2344             if (err->arg2 != NULL)
   2345                 xmlFree((xmlChar *) err->arg2);
   2346             err->arg2 = NULL;
   2347             err->flags = 0;
   2348         }
   2349     }
   2350     ctxt->errNr = 0;
   2351 }
   2352 
   2353 /**
   2354  * xmlRelaxNGAddValidError:
   2355  * @ctxt:  the validation context
   2356  * @err:  the error number
   2357  * @arg1:  the first argument
   2358  * @arg2:  the second argument
   2359  * @dup:  need to dup the args
   2360  *
   2361  * Register a validation error, either generating it if it's sure
   2362  * or stacking it for later handling if unsure.
   2363  */
   2364 static void
   2365 xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt,
   2366                         xmlRelaxNGValidErr err, const xmlChar * arg1,
   2367                         const xmlChar * arg2, int dup)
   2368 {
   2369     if (ctxt == NULL)
   2370         return;
   2371     if (ctxt->flags & FLAGS_NOERROR)
   2372         return;
   2373 
   2374 #ifdef DEBUG_ERROR
   2375     xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err);
   2376 #endif
   2377     /*
   2378      * generate the error directly
   2379      */
   2380     if (((ctxt->flags & FLAGS_IGNORABLE) == 0) ||
   2381 	 (ctxt->flags & FLAGS_NEGATIVE)) {
   2382         xmlNodePtr node, seq;
   2383 
   2384         /*
   2385          * Flush first any stacked error which might be the
   2386          * real cause of the problem.
   2387          */
   2388         if (ctxt->errNr != 0)
   2389             xmlRelaxNGDumpValidError(ctxt);
   2390         if (ctxt->state != NULL) {
   2391             node = ctxt->state->node;
   2392             seq = ctxt->state->seq;
   2393         } else {
   2394             node = seq = NULL;
   2395         }
   2396         if ((node == NULL) && (seq == NULL)) {
   2397             node = ctxt->pnode;
   2398         }
   2399         xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2);
   2400     }
   2401     /*
   2402      * Stack the error for later processing if needed
   2403      */
   2404     else {
   2405         xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);
   2406     }
   2407 }
   2408 
   2409 
   2410 /************************************************************************
   2411  *									*
   2412  *			Type library hooks				*
   2413  *									*
   2414  ************************************************************************/
   2415 static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt,
   2416                                     const xmlChar * str);
   2417 
   2418 /**
   2419  * xmlRelaxNGSchemaTypeHave:
   2420  * @data:  data needed for the library
   2421  * @type:  the type name
   2422  *
   2423  * Check if the given type is provided by
   2424  * the W3C XMLSchema Datatype library.
   2425  *
   2426  * Returns 1 if yes, 0 if no and -1 in case of error.
   2427  */
   2428 static int
   2429 xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar * type)
   2430 {
   2431     xmlSchemaTypePtr typ;
   2432 
   2433     if (type == NULL)
   2434         return (-1);
   2435     typ = xmlSchemaGetPredefinedType(type,
   2436                                      BAD_CAST
   2437                                      "http://www.w3.org/2001/XMLSchema");
   2438     if (typ == NULL)
   2439         return (0);
   2440     return (1);
   2441 }
   2442 
   2443 /**
   2444  * xmlRelaxNGSchemaTypeCheck:
   2445  * @data:  data needed for the library
   2446  * @type:  the type name
   2447  * @value:  the value to check
   2448  * @node:  the node
   2449  *
   2450  * Check if the given type and value are validated by
   2451  * the W3C XMLSchema Datatype library.
   2452  *
   2453  * Returns 1 if yes, 0 if no and -1 in case of error.
   2454  */
   2455 static int
   2456 xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
   2457                           const xmlChar * type,
   2458                           const xmlChar * value,
   2459                           void **result, xmlNodePtr node)
   2460 {
   2461     xmlSchemaTypePtr typ;
   2462     int ret;
   2463 
   2464     if ((type == NULL) || (value == NULL))
   2465         return (-1);
   2466     typ = xmlSchemaGetPredefinedType(type,
   2467                                      BAD_CAST
   2468                                      "http://www.w3.org/2001/XMLSchema");
   2469     if (typ == NULL)
   2470         return (-1);
   2471     ret = xmlSchemaValPredefTypeNode(typ, value,
   2472                                      (xmlSchemaValPtr *) result, node);
   2473     if (ret == 2)               /* special ID error code */
   2474         return (2);
   2475     if (ret == 0)
   2476         return (1);
   2477     if (ret > 0)
   2478         return (0);
   2479     return (-1);
   2480 }
   2481 
   2482 /**
   2483  * xmlRelaxNGSchemaFacetCheck:
   2484  * @data:  data needed for the library
   2485  * @type:  the type name
   2486  * @facet:  the facet name
   2487  * @val:  the facet value
   2488  * @strval:  the string value
   2489  * @value:  the value to check
   2490  *
   2491  * Function provided by a type library to check a value facet
   2492  *
   2493  * Returns 1 if yes, 0 if no and -1 in case of error.
   2494  */
   2495 static int
   2496 xmlRelaxNGSchemaFacetCheck(void *data ATTRIBUTE_UNUSED,
   2497                            const xmlChar * type, const xmlChar * facetname,
   2498                            const xmlChar * val, const xmlChar * strval,
   2499                            void *value)
   2500 {
   2501     xmlSchemaFacetPtr facet;
   2502     xmlSchemaTypePtr typ;
   2503     int ret;
   2504 
   2505     if ((type == NULL) || (strval == NULL))
   2506         return (-1);
   2507     typ = xmlSchemaGetPredefinedType(type,
   2508                                      BAD_CAST
   2509                                      "http://www.w3.org/2001/XMLSchema");
   2510     if (typ == NULL)
   2511         return (-1);
   2512 
   2513     facet = xmlSchemaNewFacet();
   2514     if (facet == NULL)
   2515         return (-1);
   2516 
   2517     if (xmlStrEqual(facetname, BAD_CAST "minInclusive")) {
   2518         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
   2519     } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive")) {
   2520         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
   2521     } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive")) {
   2522         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
   2523     } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive")) {
   2524         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
   2525     } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits")) {
   2526         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
   2527     } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits")) {
   2528         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
   2529     } else if (xmlStrEqual(facetname, BAD_CAST "pattern")) {
   2530         facet->type = XML_SCHEMA_FACET_PATTERN;
   2531     } else if (xmlStrEqual(facetname, BAD_CAST "enumeration")) {
   2532         facet->type = XML_SCHEMA_FACET_ENUMERATION;
   2533     } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace")) {
   2534         facet->type = XML_SCHEMA_FACET_WHITESPACE;
   2535     } else if (xmlStrEqual(facetname, BAD_CAST "length")) {
   2536         facet->type = XML_SCHEMA_FACET_LENGTH;
   2537     } else if (xmlStrEqual(facetname, BAD_CAST "maxLength")) {
   2538         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
   2539     } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) {
   2540         facet->type = XML_SCHEMA_FACET_MINLENGTH;
   2541     } else {
   2542         xmlSchemaFreeFacet(facet);
   2543         return (-1);
   2544     }
   2545     facet->value = val;
   2546     ret = xmlSchemaCheckFacet(facet, typ, NULL, type);
   2547     if (ret != 0) {
   2548         xmlSchemaFreeFacet(facet);
   2549         return (-1);
   2550     }
   2551     ret = xmlSchemaValidateFacet(typ, facet, strval, value);
   2552     xmlSchemaFreeFacet(facet);
   2553     if (ret != 0)
   2554         return (-1);
   2555     return (0);
   2556 }
   2557 
   2558 /**
   2559  * xmlRelaxNGSchemaFreeValue:
   2560  * @data:  data needed for the library
   2561  * @value:  the value to free
   2562  *
   2563  * Function provided by a type library to free a Schemas value
   2564  *
   2565  * Returns 1 if yes, 0 if no and -1 in case of error.
   2566  */
   2567 static void
   2568 xmlRelaxNGSchemaFreeValue(void *data ATTRIBUTE_UNUSED, void *value)
   2569 {
   2570     xmlSchemaFreeValue(value);
   2571 }
   2572 
   2573 /**
   2574  * xmlRelaxNGSchemaTypeCompare:
   2575  * @data:  data needed for the library
   2576  * @type:  the type name
   2577  * @value1:  the first value
   2578  * @value2:  the second value
   2579  *
   2580  * Compare two values for equality accordingly a type from the W3C XMLSchema
   2581  * Datatype library.
   2582  *
   2583  * Returns 1 if equal, 0 if no and -1 in case of error.
   2584  */
   2585 static int
   2586 xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
   2587                             const xmlChar * type,
   2588                             const xmlChar * value1,
   2589                             xmlNodePtr ctxt1,
   2590                             void *comp1,
   2591                             const xmlChar * value2, xmlNodePtr ctxt2)
   2592 {
   2593     int ret;
   2594     xmlSchemaTypePtr typ;
   2595     xmlSchemaValPtr res1 = NULL, res2 = NULL;
   2596 
   2597     if ((type == NULL) || (value1 == NULL) || (value2 == NULL))
   2598         return (-1);
   2599     typ = xmlSchemaGetPredefinedType(type,
   2600                                      BAD_CAST
   2601                                      "http://www.w3.org/2001/XMLSchema");
   2602     if (typ == NULL)
   2603         return (-1);
   2604     if (comp1 == NULL) {
   2605         ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1);
   2606         if (ret != 0)
   2607             return (-1);
   2608         if (res1 == NULL)
   2609             return (-1);
   2610     } else {
   2611         res1 = (xmlSchemaValPtr) comp1;
   2612     }
   2613     ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2);
   2614     if (ret != 0) {
   2615 	if (res1 != (xmlSchemaValPtr) comp1)
   2616 	    xmlSchemaFreeValue(res1);
   2617         return (-1);
   2618     }
   2619     ret = xmlSchemaCompareValues(res1, res2);
   2620     if (res1 != (xmlSchemaValPtr) comp1)
   2621         xmlSchemaFreeValue(res1);
   2622     xmlSchemaFreeValue(res2);
   2623     if (ret == -2)
   2624         return (-1);
   2625     if (ret == 0)
   2626         return (1);
   2627     return (0);
   2628 }
   2629 
   2630 /**
   2631  * xmlRelaxNGDefaultTypeHave:
   2632  * @data:  data needed for the library
   2633  * @type:  the type name
   2634  *
   2635  * Check if the given type is provided by
   2636  * the default datatype library.
   2637  *
   2638  * Returns 1 if yes, 0 if no and -1 in case of error.
   2639  */
   2640 static int
   2641 xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED,
   2642                           const xmlChar * type)
   2643 {
   2644     if (type == NULL)
   2645         return (-1);
   2646     if (xmlStrEqual(type, BAD_CAST "string"))
   2647         return (1);
   2648     if (xmlStrEqual(type, BAD_CAST "token"))
   2649         return (1);
   2650     return (0);
   2651 }
   2652 
   2653 /**
   2654  * xmlRelaxNGDefaultTypeCheck:
   2655  * @data:  data needed for the library
   2656  * @type:  the type name
   2657  * @value:  the value to check
   2658  * @node:  the node
   2659  *
   2660  * Check if the given type and value are validated by
   2661  * the default datatype library.
   2662  *
   2663  * Returns 1 if yes, 0 if no and -1 in case of error.
   2664  */
   2665 static int
   2666 xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
   2667                            const xmlChar * type ATTRIBUTE_UNUSED,
   2668                            const xmlChar * value ATTRIBUTE_UNUSED,
   2669                            void **result ATTRIBUTE_UNUSED,
   2670                            xmlNodePtr node ATTRIBUTE_UNUSED)
   2671 {
   2672     if (value == NULL)
   2673         return (-1);
   2674     if (xmlStrEqual(type, BAD_CAST "string"))
   2675         return (1);
   2676     if (xmlStrEqual(type, BAD_CAST "token")) {
   2677         return (1);
   2678     }
   2679 
   2680     return (0);
   2681 }
   2682 
   2683 /**
   2684  * xmlRelaxNGDefaultTypeCompare:
   2685  * @data:  data needed for the library
   2686  * @type:  the type name
   2687  * @value1:  the first value
   2688  * @value2:  the second value
   2689  *
   2690  * Compare two values accordingly a type from the default
   2691  * datatype library.
   2692  *
   2693  * Returns 1 if yes, 0 if no and -1 in case of error.
   2694  */
   2695 static int
   2696 xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
   2697                              const xmlChar * type,
   2698                              const xmlChar * value1,
   2699                              xmlNodePtr ctxt1 ATTRIBUTE_UNUSED,
   2700                              void *comp1 ATTRIBUTE_UNUSED,
   2701                              const xmlChar * value2,
   2702                              xmlNodePtr ctxt2 ATTRIBUTE_UNUSED)
   2703 {
   2704     int ret = -1;
   2705 
   2706     if (xmlStrEqual(type, BAD_CAST "string")) {
   2707         ret = xmlStrEqual(value1, value2);
   2708     } else if (xmlStrEqual(type, BAD_CAST "token")) {
   2709         if (!xmlStrEqual(value1, value2)) {
   2710             xmlChar *nval, *nvalue;
   2711 
   2712             /*
   2713              * TODO: trivial optimizations are possible by
   2714              * computing at compile-time
   2715              */
   2716             nval = xmlRelaxNGNormalize(NULL, value1);
   2717             nvalue = xmlRelaxNGNormalize(NULL, value2);
   2718 
   2719             if ((nval == NULL) || (nvalue == NULL))
   2720                 ret = -1;
   2721             else if (xmlStrEqual(nval, nvalue))
   2722                 ret = 1;
   2723             else
   2724                 ret = 0;
   2725             if (nval != NULL)
   2726                 xmlFree(nval);
   2727             if (nvalue != NULL)
   2728                 xmlFree(nvalue);
   2729         } else
   2730             ret = 1;
   2731     }
   2732     return (ret);
   2733 }
   2734 
   2735 static int xmlRelaxNGTypeInitialized = 0;
   2736 static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
   2737 
   2738 /**
   2739  * xmlRelaxNGFreeTypeLibrary:
   2740  * @lib:  the type library structure
   2741  * @namespace:  the URI bound to the library
   2742  *
   2743  * Free the structure associated to the type library
   2744  */
   2745 static void
   2746 xmlRelaxNGFreeTypeLibrary(void *payload,
   2747                           const xmlChar * namespace ATTRIBUTE_UNUSED)
   2748 {
   2749     xmlRelaxNGTypeLibraryPtr lib = (xmlRelaxNGTypeLibraryPtr) payload;
   2750     if (lib == NULL)
   2751         return;
   2752     if (lib->namespace != NULL)
   2753         xmlFree((xmlChar *) lib->namespace);
   2754     xmlFree(lib);
   2755 }
   2756 
   2757 /**
   2758  * xmlRelaxNGRegisterTypeLibrary:
   2759  * @namespace:  the URI bound to the library
   2760  * @data:  data associated to the library
   2761  * @have:  the provide function
   2762  * @check:  the checking function
   2763  * @comp:  the comparison function
   2764  *
   2765  * Register a new type library
   2766  *
   2767  * Returns 0 in case of success and -1 in case of error.
   2768  */
   2769 static int
   2770 xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,
   2771                               xmlRelaxNGTypeHave have,
   2772                               xmlRelaxNGTypeCheck check,
   2773                               xmlRelaxNGTypeCompare comp,
   2774                               xmlRelaxNGFacetCheck facet,
   2775                               xmlRelaxNGTypeFree freef)
   2776 {
   2777     xmlRelaxNGTypeLibraryPtr lib;
   2778     int ret;
   2779 
   2780     if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
   2781         (check == NULL) || (comp == NULL))
   2782         return (-1);
   2783     if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
   2784         xmlGenericError(xmlGenericErrorContext,
   2785                         "Relax-NG types library '%s' already registered\n",
   2786                         namespace);
   2787         return (-1);
   2788     }
   2789     lib =
   2790         (xmlRelaxNGTypeLibraryPtr)
   2791         xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
   2792     if (lib == NULL) {
   2793         xmlRngVErrMemory(NULL, "adding types library\n");
   2794         return (-1);
   2795     }
   2796     memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
   2797     lib->namespace = xmlStrdup(namespace);
   2798     lib->data = data;
   2799     lib->have = have;
   2800     lib->comp = comp;
   2801     lib->check = check;
   2802     lib->facet = facet;
   2803     lib->freef = freef;
   2804     ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
   2805     if (ret < 0) {
   2806         xmlGenericError(xmlGenericErrorContext,
   2807                         "Relax-NG types library failed to register '%s'\n",
   2808                         namespace);
   2809         xmlRelaxNGFreeTypeLibrary(lib, namespace);
   2810         return (-1);
   2811     }
   2812     return (0);
   2813 }
   2814 
   2815 /**
   2816  * xmlRelaxNGInitTypes:
   2817  *
   2818  * Initilize the default type libraries.
   2819  *
   2820  * Returns 0 in case of success and -1 in case of error.
   2821  */
   2822 int
   2823 xmlRelaxNGInitTypes(void)
   2824 {
   2825     if (xmlRelaxNGTypeInitialized != 0)
   2826         return (0);
   2827     xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
   2828     if (xmlRelaxNGRegisteredTypes == NULL) {
   2829         xmlGenericError(xmlGenericErrorContext,
   2830                         "Failed to allocate sh table for Relax-NG types\n");
   2831         return (-1);
   2832     }
   2833     xmlRelaxNGRegisterTypeLibrary(BAD_CAST
   2834                                   "http://www.w3.org/2001/XMLSchema-datatypes",
   2835                                   NULL, xmlRelaxNGSchemaTypeHave,
   2836                                   xmlRelaxNGSchemaTypeCheck,
   2837                                   xmlRelaxNGSchemaTypeCompare,
   2838                                   xmlRelaxNGSchemaFacetCheck,
   2839                                   xmlRelaxNGSchemaFreeValue);
   2840     xmlRelaxNGRegisterTypeLibrary(xmlRelaxNGNs, NULL,
   2841                                   xmlRelaxNGDefaultTypeHave,
   2842                                   xmlRelaxNGDefaultTypeCheck,
   2843                                   xmlRelaxNGDefaultTypeCompare, NULL,
   2844                                   NULL);
   2845     xmlRelaxNGTypeInitialized = 1;
   2846     return (0);
   2847 }
   2848 
   2849 /**
   2850  * xmlRelaxNGCleanupTypes:
   2851  *
   2852  * Cleanup the default Schemas type library associated to RelaxNG
   2853  */
   2854 void
   2855 xmlRelaxNGCleanupTypes(void)
   2856 {
   2857     xmlSchemaCleanupTypes();
   2858     if (xmlRelaxNGTypeInitialized == 0)
   2859         return;
   2860     xmlHashFree(xmlRelaxNGRegisteredTypes, xmlRelaxNGFreeTypeLibrary);
   2861     xmlRelaxNGTypeInitialized = 0;
   2862 }
   2863 
   2864 /************************************************************************
   2865  *									*
   2866  *		Compiling element content into regexp			*
   2867  *									*
   2868  * Sometime the element content can be compiled into a pure regexp,	*
   2869  * This allows a faster execution and streamability at that level	*
   2870  *									*
   2871  ************************************************************************/
   2872 
   2873 /* from automata.c but not exported */
   2874 void xmlAutomataSetFlags(xmlAutomataPtr am, int flags);
   2875 
   2876 
   2877 static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,
   2878                                 xmlRelaxNGDefinePtr def);
   2879 
   2880 /**
   2881  * xmlRelaxNGIsCompileable:
   2882  * @define:  the definition to check
   2883  *
   2884  * Check if a definition is nullable.
   2885  *
   2886  * Returns 1 if yes, 0 if no and -1 in case of error
   2887  */
   2888 static int
   2889 xmlRelaxNGIsCompileable(xmlRelaxNGDefinePtr def)
   2890 {
   2891     int ret = -1;
   2892 
   2893     if (def == NULL) {
   2894         return (-1);
   2895     }
   2896     if ((def->type != XML_RELAXNG_ELEMENT) &&
   2897         (def->dflags & IS_COMPILABLE))
   2898         return (1);
   2899     if ((def->type != XML_RELAXNG_ELEMENT) &&
   2900         (def->dflags & IS_NOT_COMPILABLE))
   2901         return (0);
   2902     switch (def->type) {
   2903         case XML_RELAXNG_NOOP:
   2904             ret = xmlRelaxNGIsCompileable(def->content);
   2905             break;
   2906         case XML_RELAXNG_TEXT:
   2907         case XML_RELAXNG_EMPTY:
   2908             ret = 1;
   2909             break;
   2910         case XML_RELAXNG_ELEMENT:
   2911             /*
   2912              * Check if the element content is compileable
   2913              */
   2914             if (((def->dflags & IS_NOT_COMPILABLE) == 0) &&
   2915                 ((def->dflags & IS_COMPILABLE) == 0)) {
   2916                 xmlRelaxNGDefinePtr list;
   2917 
   2918                 list = def->content;
   2919                 while (list != NULL) {
   2920                     ret = xmlRelaxNGIsCompileable(list);
   2921                     if (ret != 1)
   2922                         break;
   2923                     list = list->next;
   2924                 }
   2925 		/*
   2926 		 * Because the routine is recursive, we must guard against
   2927 		 * discovering both COMPILABLE and NOT_COMPILABLE
   2928 		 */
   2929                 if (ret == 0) {
   2930 		    def->dflags &= ~IS_COMPILABLE;
   2931                     def->dflags |= IS_NOT_COMPILABLE;
   2932 		}
   2933                 if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE))
   2934                     def->dflags |= IS_COMPILABLE;
   2935 #ifdef DEBUG_COMPILE
   2936                 if (ret == 1) {
   2937                     xmlGenericError(xmlGenericErrorContext,
   2938                                     "element content for %s is compilable\n",
   2939                                     def->name);
   2940                 } else if (ret == 0) {
   2941                     xmlGenericError(xmlGenericErrorContext,
   2942                                     "element content for %s is not compilable\n",
   2943                                     def->name);
   2944                 } else {
   2945                     xmlGenericError(xmlGenericErrorContext,
   2946                                     "Problem in RelaxNGIsCompileable for element %s\n",
   2947                                     def->name);
   2948                 }
   2949 #endif
   2950             }
   2951             /*
   2952              * All elements return a compileable status unless they
   2953              * are generic like anyName
   2954              */
   2955             if ((def->nameClass != NULL) || (def->name == NULL))
   2956                 ret = 0;
   2957             else
   2958                 ret = 1;
   2959             return (ret);
   2960         case XML_RELAXNG_REF:
   2961         case XML_RELAXNG_EXTERNALREF:
   2962         case XML_RELAXNG_PARENTREF:
   2963             if (def->depth == -20) {
   2964                 return (1);
   2965             } else {
   2966                 xmlRelaxNGDefinePtr list;
   2967 
   2968                 def->depth = -20;
   2969                 list = def->content;
   2970                 while (list != NULL) {
   2971                     ret = xmlRelaxNGIsCompileable(list);
   2972                     if (ret != 1)
   2973                         break;
   2974                     list = list->next;
   2975                 }
   2976             }
   2977             break;
   2978         case XML_RELAXNG_START:
   2979         case XML_RELAXNG_OPTIONAL:
   2980         case XML_RELAXNG_ZEROORMORE:
   2981         case XML_RELAXNG_ONEORMORE:
   2982         case XML_RELAXNG_CHOICE:
   2983         case XML_RELAXNG_GROUP:
   2984         case XML_RELAXNG_DEF:{
   2985                 xmlRelaxNGDefinePtr list;
   2986 
   2987                 list = def->content;
   2988                 while (list != NULL) {
   2989                     ret = xmlRelaxNGIsCompileable(list);
   2990                     if (ret != 1)
   2991                         break;
   2992                     list = list->next;
   2993                 }
   2994                 break;
   2995             }
   2996         case XML_RELAXNG_EXCEPT:
   2997         case XML_RELAXNG_ATTRIBUTE:
   2998         case XML_RELAXNG_INTERLEAVE:
   2999         case XML_RELAXNG_DATATYPE:
   3000         case XML_RELAXNG_LIST:
   3001         case XML_RELAXNG_PARAM:
   3002         case XML_RELAXNG_VALUE:
   3003         case XML_RELAXNG_NOT_ALLOWED:
   3004             ret = 0;
   3005             break;
   3006     }
   3007     if (ret == 0)
   3008         def->dflags |= IS_NOT_COMPILABLE;
   3009     if (ret == 1)
   3010         def->dflags |= IS_COMPILABLE;
   3011 #ifdef DEBUG_COMPILE
   3012     if (ret == 1) {
   3013         xmlGenericError(xmlGenericErrorContext,
   3014                         "RelaxNGIsCompileable %s : true\n",
   3015                         xmlRelaxNGDefName(def));
   3016     } else if (ret == 0) {
   3017         xmlGenericError(xmlGenericErrorContext,
   3018                         "RelaxNGIsCompileable %s : false\n",
   3019                         xmlRelaxNGDefName(def));
   3020     } else {
   3021         xmlGenericError(xmlGenericErrorContext,
   3022                         "Problem in RelaxNGIsCompileable %s\n",
   3023                         xmlRelaxNGDefName(def));
   3024     }
   3025 #endif
   3026     return (ret);
   3027 }
   3028 
   3029 /**
   3030  * xmlRelaxNGCompile:
   3031  * ctxt:  the RelaxNG parser context
   3032  * @define:  the definition tree to compile
   3033  *
   3034  * Compile the set of definitions, it works recursively, till the
   3035  * element boundaries, where it tries to compile the content if possible
   3036  *
   3037  * Returns 0 if success and -1 in case of error
   3038  */
   3039 static int
   3040 xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
   3041 {
   3042     int ret = 0;
   3043     xmlRelaxNGDefinePtr list;
   3044 
   3045     if ((ctxt == NULL) || (def == NULL))
   3046         return (-1);
   3047 
   3048     switch (def->type) {
   3049         case XML_RELAXNG_START:
   3050             if ((xmlRelaxNGIsCompileable(def) == 1) && (def->depth != -25)) {
   3051                 xmlAutomataPtr oldam = ctxt->am;
   3052                 xmlAutomataStatePtr oldstate = ctxt->state;
   3053 
   3054                 def->depth = -25;
   3055 
   3056                 list = def->content;
   3057                 ctxt->am = xmlNewAutomata();
   3058                 if (ctxt->am == NULL)
   3059                     return (-1);
   3060 
   3061                 /*
   3062                  * assume identical strings but not same pointer are different
   3063                  * atoms, needed for non-determinism detection
   3064                  * That way if 2 elements with the same name are in a choice
   3065                  * branch the automata is found non-deterministic and
   3066                  * we fallback to the normal validation which does the right
   3067                  * thing of exploring both choices.
   3068                  */
   3069                 xmlAutomataSetFlags(ctxt->am, 1);
   3070 
   3071                 ctxt->state = xmlAutomataGetInitState(ctxt->am);
   3072                 while (list != NULL) {
   3073                     xmlRelaxNGCompile(ctxt, list);
   3074                     list = list->next;
   3075                 }
   3076                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
   3077                 if (xmlAutomataIsDeterminist(ctxt->am))
   3078                     def->contModel = xmlAutomataCompile(ctxt->am);
   3079 
   3080                 xmlFreeAutomata(ctxt->am);
   3081                 ctxt->state = oldstate;
   3082                 ctxt->am = oldam;
   3083             }
   3084             break;
   3085         case XML_RELAXNG_ELEMENT:
   3086             if ((ctxt->am != NULL) && (def->name != NULL)) {
   3087                 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
   3088                                                         ctxt->state, NULL,
   3089                                                         def->name, def->ns,
   3090                                                         def);
   3091             }
   3092             if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
   3093                 xmlAutomataPtr oldam = ctxt->am;
   3094                 xmlAutomataStatePtr oldstate = ctxt->state;
   3095 
   3096                 def->depth = -25;
   3097 
   3098                 list = def->content;
   3099                 ctxt->am = xmlNewAutomata();
   3100                 if (ctxt->am == NULL)
   3101                     return (-1);
   3102                 xmlAutomataSetFlags(ctxt->am, 1);
   3103                 ctxt->state = xmlAutomataGetInitState(ctxt->am);
   3104                 while (list != NULL) {
   3105                     xmlRelaxNGCompile(ctxt, list);
   3106                     list = list->next;
   3107                 }
   3108                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
   3109                 def->contModel = xmlAutomataCompile(ctxt->am);
   3110                 if (!xmlRegexpIsDeterminist(def->contModel)) {
   3111 #ifdef DEBUG_COMPILE
   3112                     xmlGenericError(xmlGenericErrorContext,
   3113                         "Content model not determinist %s\n",
   3114                                     def->name);
   3115 #endif
   3116                     /*
   3117                      * we can only use the automata if it is determinist
   3118                      */
   3119                     xmlRegFreeRegexp(def->contModel);
   3120                     def->contModel = NULL;
   3121                 }
   3122                 xmlFreeAutomata(ctxt->am);
   3123                 ctxt->state = oldstate;
   3124                 ctxt->am = oldam;
   3125             } else {
   3126                 xmlAutomataPtr oldam = ctxt->am;
   3127 
   3128                 /*
   3129                  * we can't build the content model for this element content
   3130                  * but it still might be possible to build it for some of its
   3131                  * children, recurse.
   3132                  */
   3133                 ret = xmlRelaxNGTryCompile(ctxt, def);
   3134                 ctxt->am = oldam;
   3135             }
   3136             break;
   3137         case XML_RELAXNG_NOOP:
   3138             ret = xmlRelaxNGCompile(ctxt, def->content);
   3139             break;
   3140         case XML_RELAXNG_OPTIONAL:{
   3141                 xmlAutomataStatePtr oldstate = ctxt->state;
   3142 
   3143                 list = def->content;
   3144                 while (list != NULL) {
   3145                     xmlRelaxNGCompile(ctxt, list);
   3146                     list = list->next;
   3147                 }
   3148                 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
   3149                 break;
   3150             }
   3151         case XML_RELAXNG_ZEROORMORE:{
   3152                 xmlAutomataStatePtr oldstate;
   3153 
   3154                 ctxt->state =
   3155                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
   3156                 oldstate = ctxt->state;
   3157                 list = def->content;
   3158                 while (list != NULL) {
   3159                     xmlRelaxNGCompile(ctxt, list);
   3160                     list = list->next;
   3161                 }
   3162                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
   3163                 ctxt->state =
   3164                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
   3165                 break;
   3166             }
   3167         case XML_RELAXNG_ONEORMORE:{
   3168                 xmlAutomataStatePtr oldstate;
   3169 
   3170                 list = def->content;
   3171                 while (list != NULL) {
   3172                     xmlRelaxNGCompile(ctxt, list);
   3173                     list = list->next;
   3174                 }
   3175                 oldstate = ctxt->state;
   3176                 list = def->content;
   3177                 while (list != NULL) {
   3178                     xmlRelaxNGCompile(ctxt, list);
   3179                     list = list->next;
   3180                 }
   3181                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
   3182                 ctxt->state =
   3183                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
   3184                 break;
   3185             }
   3186         case XML_RELAXNG_CHOICE:{
   3187                 xmlAutomataStatePtr target = NULL;
   3188                 xmlAutomataStatePtr oldstate = ctxt->state;
   3189 
   3190                 list = def->content;
   3191                 while (list != NULL) {
   3192                     ctxt->state = oldstate;
   3193                     ret = xmlRelaxNGCompile(ctxt, list);
   3194                     if (ret != 0)
   3195                         break;
   3196                     if (target == NULL)
   3197                         target = ctxt->state;
   3198                     else {
   3199                         xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
   3200                                               target);
   3201                     }
   3202                     list = list->next;
   3203                 }
   3204                 ctxt->state = target;
   3205 
   3206                 break;
   3207             }
   3208         case XML_RELAXNG_REF:
   3209         case XML_RELAXNG_EXTERNALREF:
   3210         case XML_RELAXNG_PARENTREF:
   3211         case XML_RELAXNG_GROUP:
   3212         case XML_RELAXNG_DEF:
   3213             list = def->content;
   3214             while (list != NULL) {
   3215                 ret = xmlRelaxNGCompile(ctxt, list);
   3216                 if (ret != 0)
   3217                     break;
   3218                 list = list->next;
   3219             }
   3220             break;
   3221         case XML_RELAXNG_TEXT:{
   3222                 xmlAutomataStatePtr oldstate;
   3223 
   3224                 ctxt->state =
   3225                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
   3226                 oldstate = ctxt->state;
   3227                 xmlRelaxNGCompile(ctxt, def->content);
   3228                 xmlAutomataNewTransition(ctxt->am, ctxt->state,
   3229                                          ctxt->state, BAD_CAST "#text",
   3230                                          NULL);
   3231                 ctxt->state =
   3232                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
   3233                 break;
   3234             }
   3235         case XML_RELAXNG_EMPTY:
   3236             ctxt->state =
   3237                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
   3238             break;
   3239         case XML_RELAXNG_EXCEPT:
   3240         case XML_RELAXNG_ATTRIBUTE:
   3241         case XML_RELAXNG_INTERLEAVE:
   3242         case XML_RELAXNG_NOT_ALLOWED:
   3243         case XML_RELAXNG_DATATYPE:
   3244         case XML_RELAXNG_LIST:
   3245         case XML_RELAXNG_PARAM:
   3246         case XML_RELAXNG_VALUE:
   3247             /* This should not happen and generate an internal error */
   3248             fprintf(stderr, "RNG internal error trying to compile %s\n",
   3249                     xmlRelaxNGDefName(def));
   3250             break;
   3251     }
   3252     return (ret);
   3253 }
   3254 
   3255 /**
   3256  * xmlRelaxNGTryCompile:
   3257  * ctxt:  the RelaxNG parser context
   3258  * @define:  the definition tree to compile
   3259  *
   3260  * Try to compile the set of definitions, it works recursively,
   3261  * possibly ignoring parts which cannot be compiled.
   3262  *
   3263  * Returns 0 if success and -1 in case of error
   3264  */
   3265 static int
   3266 xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
   3267 {
   3268     int ret = 0;
   3269     xmlRelaxNGDefinePtr list;
   3270 
   3271     if ((ctxt == NULL) || (def == NULL))
   3272         return (-1);
   3273 
   3274     if ((def->type == XML_RELAXNG_START) ||
   3275         (def->type == XML_RELAXNG_ELEMENT)) {
   3276         ret = xmlRelaxNGIsCompileable(def);
   3277         if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
   3278             ctxt->am = NULL;
   3279             ret = xmlRelaxNGCompile(ctxt, def);
   3280 #ifdef DEBUG_PROGRESSIVE
   3281             if (ret == 0) {
   3282                 if (def->type == XML_RELAXNG_START)
   3283                     xmlGenericError(xmlGenericErrorContext,
   3284                                     "compiled the start\n");
   3285                 else
   3286                     xmlGenericError(xmlGenericErrorContext,
   3287                                     "compiled element %s\n", def->name);
   3288             } else {
   3289                 if (def->type == XML_RELAXNG_START)
   3290                     xmlGenericError(xmlGenericErrorContext,
   3291                                     "failed to compile the start\n");
   3292                 else
   3293                     xmlGenericError(xmlGenericErrorContext,
   3294                                     "failed to compile element %s\n",
   3295                                     def->name);
   3296             }
   3297 #endif
   3298             return (ret);
   3299         }
   3300     }
   3301     switch (def->type) {
   3302         case XML_RELAXNG_NOOP:
   3303             ret = xmlRelaxNGTryCompile(ctxt, def->content);
   3304             break;
   3305         case XML_RELAXNG_TEXT:
   3306         case XML_RELAXNG_DATATYPE:
   3307         case XML_RELAXNG_LIST:
   3308         case XML_RELAXNG_PARAM:
   3309         case XML_RELAXNG_VALUE:
   3310         case XML_RELAXNG_EMPTY:
   3311         case XML_RELAXNG_ELEMENT:
   3312             ret = 0;
   3313             break;
   3314         case XML_RELAXNG_OPTIONAL:
   3315         case XML_RELAXNG_ZEROORMORE:
   3316         case XML_RELAXNG_ONEORMORE:
   3317         case XML_RELAXNG_CHOICE:
   3318         case XML_RELAXNG_GROUP:
   3319         case XML_RELAXNG_DEF:
   3320         case XML_RELAXNG_START:
   3321         case XML_RELAXNG_REF:
   3322         case XML_RELAXNG_EXTERNALREF:
   3323         case XML_RELAXNG_PARENTREF:
   3324             list = def->content;
   3325             while (list != NULL) {
   3326                 ret = xmlRelaxNGTryCompile(ctxt, list);
   3327                 if (ret != 0)
   3328                     break;
   3329                 list = list->next;
   3330             }
   3331             break;
   3332         case XML_RELAXNG_EXCEPT:
   3333         case XML_RELAXNG_ATTRIBUTE:
   3334         case XML_RELAXNG_INTERLEAVE:
   3335         case XML_RELAXNG_NOT_ALLOWED:
   3336             ret = 0;
   3337             break;
   3338     }
   3339     return (ret);
   3340 }
   3341 
   3342 /************************************************************************
   3343  *									*
   3344  *			Parsing functions				*
   3345  *									*
   3346  ************************************************************************/
   3347 
   3348 static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr
   3349                                                     ctxt, xmlNodePtr node);
   3350 static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr
   3351                                                   ctxt, xmlNodePtr node);
   3352 static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr
   3353                                                    ctxt, xmlNodePtr nodes,
   3354                                                    int group);
   3355 static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr
   3356                                                   ctxt, xmlNodePtr node);
   3357 static xmlRelaxNGPtr xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt,
   3358                                              xmlNodePtr node);
   3359 static int xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
   3360                                          xmlNodePtr nodes);
   3361 static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr
   3362                                                     ctxt, xmlNodePtr node,
   3363                                                     xmlRelaxNGDefinePtr
   3364                                                     def);
   3365 static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr
   3366                                                    ctxt, xmlNodePtr nodes);
   3367 static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
   3368                                   xmlRelaxNGDefinePtr define,
   3369                                   xmlNodePtr elem);
   3370 
   3371 
   3372 #define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
   3373 
   3374 /**
   3375  * xmlRelaxNGIsNullable:
   3376  * @define:  the definition to verify
   3377  *
   3378  * Check if a definition is nullable.
   3379  *
   3380  * Returns 1 if yes, 0 if no and -1 in case of error
   3381  */
   3382 static int
   3383 xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define)
   3384 {
   3385     int ret;
   3386 
   3387     if (define == NULL)
   3388         return (-1);
   3389 
   3390     if (define->dflags & IS_NULLABLE)
   3391         return (1);
   3392     if (define->dflags & IS_NOT_NULLABLE)
   3393         return (0);
   3394     switch (define->type) {
   3395         case XML_RELAXNG_EMPTY:
   3396         case XML_RELAXNG_TEXT:
   3397             ret = 1;
   3398             break;
   3399         case XML_RELAXNG_NOOP:
   3400         case XML_RELAXNG_DEF:
   3401         case XML_RELAXNG_REF:
   3402         case XML_RELAXNG_EXTERNALREF:
   3403         case XML_RELAXNG_PARENTREF:
   3404         case XML_RELAXNG_ONEORMORE:
   3405             ret = xmlRelaxNGIsNullable(define->content);
   3406             break;
   3407         case XML_RELAXNG_EXCEPT:
   3408         case XML_RELAXNG_NOT_ALLOWED:
   3409         case XML_RELAXNG_ELEMENT:
   3410         case XML_RELAXNG_DATATYPE:
   3411         case XML_RELAXNG_PARAM:
   3412         case XML_RELAXNG_VALUE:
   3413         case XML_RELAXNG_LIST:
   3414         case XML_RELAXNG_ATTRIBUTE:
   3415             ret = 0;
   3416             break;
   3417         case XML_RELAXNG_CHOICE:{
   3418                 xmlRelaxNGDefinePtr list = define->content;
   3419 
   3420                 while (list != NULL) {
   3421                     ret = xmlRelaxNGIsNullable(list);
   3422                     if (ret != 0)
   3423                         goto done;
   3424                     list = list->next;
   3425                 }
   3426                 ret = 0;
   3427                 break;
   3428             }
   3429         case XML_RELAXNG_START:
   3430         case XML_RELAXNG_INTERLEAVE:
   3431         case XML_RELAXNG_GROUP:{
   3432                 xmlRelaxNGDefinePtr list = define->content;
   3433 
   3434                 while (list != NULL) {
   3435                     ret = xmlRelaxNGIsNullable(list);
   3436                     if (ret != 1)
   3437                         goto done;
   3438                     list = list->next;
   3439                 }
   3440                 return (1);
   3441             }
   3442         default:
   3443             return (-1);
   3444     }
   3445   done:
   3446     if (ret == 0)
   3447         define->dflags |= IS_NOT_NULLABLE;
   3448     if (ret == 1)
   3449         define->dflags |= IS_NULLABLE;
   3450     return (ret);
   3451 }
   3452 
   3453 /**
   3454  * xmlRelaxNGIsBlank:
   3455  * @str:  a string
   3456  *
   3457  * Check if a string is ignorable c.f. 4.2. Whitespace
   3458  *
   3459  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
   3460  */
   3461 static int
   3462 xmlRelaxNGIsBlank(xmlChar * str)
   3463 {
   3464     if (str == NULL)
   3465         return (1);
   3466     while (*str != 0) {
   3467         if (!(IS_BLANK_CH(*str)))
   3468             return (0);
   3469         str++;
   3470     }
   3471     return (1);
   3472 }
   3473 
   3474 /**
   3475  * xmlRelaxNGGetDataTypeLibrary:
   3476  * @ctxt:  a Relax-NG parser context
   3477  * @node:  the current data or value element
   3478  *
   3479  * Applies algorithm from 4.3. datatypeLibrary attribute
   3480  *
   3481  * Returns the datatypeLibary value or NULL if not found
   3482  */
   3483 static xmlChar *
   3484 xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
   3485                              xmlNodePtr node)
   3486 {
   3487     xmlChar *ret, *escape;
   3488 
   3489     if (node == NULL)
   3490         return(NULL);
   3491 
   3492     if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
   3493         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
   3494         if (ret != NULL) {
   3495             if (ret[0] == 0) {
   3496                 xmlFree(ret);
   3497                 return (NULL);
   3498             }
   3499             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
   3500             if (escape == NULL) {
   3501                 return (ret);
   3502             }
   3503             xmlFree(ret);
   3504             return (escape);
   3505         }
   3506     }
   3507     node = node->parent;
   3508     while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
   3509         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
   3510         if (ret != NULL) {
   3511             if (ret[0] == 0) {
   3512                 xmlFree(ret);
   3513                 return (NULL);
   3514             }
   3515             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
   3516             if (escape == NULL) {
   3517                 return (ret);
   3518             }
   3519             xmlFree(ret);
   3520             return (escape);
   3521         }
   3522         node = node->parent;
   3523     }
   3524     return (NULL);
   3525 }
   3526 
   3527 /**
   3528  * xmlRelaxNGParseValue:
   3529  * @ctxt:  a Relax-NG parser context
   3530  * @node:  the data node.
   3531  *
   3532  * parse the content of a RelaxNG value node.
   3533  *
   3534  * Returns the definition pointer or NULL in case of error
   3535  */
   3536 static xmlRelaxNGDefinePtr
   3537 xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   3538 {
   3539     xmlRelaxNGDefinePtr def = NULL;
   3540     xmlRelaxNGTypeLibraryPtr lib = NULL;
   3541     xmlChar *type;
   3542     xmlChar *library;
   3543     int success = 0;
   3544 
   3545     def = xmlRelaxNGNewDefine(ctxt, node);
   3546     if (def == NULL)
   3547         return (NULL);
   3548     def->type = XML_RELAXNG_VALUE;
   3549 
   3550     type = xmlGetProp(node, BAD_CAST "type");
   3551     if (type != NULL) {
   3552         xmlRelaxNGNormExtSpace(type);
   3553         if (xmlValidateNCName(type, 0)) {
   3554             xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
   3555                        "value type '%s' is not an NCName\n", type, NULL);
   3556         }
   3557         library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
   3558         if (library == NULL)
   3559             library =
   3560                 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
   3561 
   3562         def->name = type;
   3563         def->ns = library;
   3564 
   3565         lib = (xmlRelaxNGTypeLibraryPtr)
   3566             xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
   3567         if (lib == NULL) {
   3568             xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
   3569                        "Use of unregistered type library '%s'\n", library,
   3570                        NULL);
   3571             def->data = NULL;
   3572         } else {
   3573             def->data = lib;
   3574             if (lib->have == NULL) {
   3575                 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
   3576                            "Internal error with type library '%s': no 'have'\n",
   3577                            library, NULL);
   3578             } else {
   3579                 success = lib->have(lib->data, def->name);
   3580                 if (success != 1) {
   3581                     xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
   3582                                "Error type '%s' is not exported by type library '%s'\n",
   3583                                def->name, library);
   3584                 }
   3585             }
   3586         }
   3587     }
   3588     if (node->children == NULL) {
   3589         def->value = xmlStrdup(BAD_CAST "");
   3590     } else if (((node->children->type != XML_TEXT_NODE) &&
   3591                 (node->children->type != XML_CDATA_SECTION_NODE)) ||
   3592                (node->children->next != NULL)) {
   3593         xmlRngPErr(ctxt, node, XML_RNGP_TEXT_EXPECTED,
   3594                    "Expecting a single text value for <value>content\n",
   3595                    NULL, NULL);
   3596     } else if (def != NULL) {
   3597         def->value = xmlNodeGetContent(node);
   3598         if (def->value == NULL) {
   3599             xmlRngPErr(ctxt, node, XML_RNGP_VALUE_NO_CONTENT,
   3600                        "Element <value> has no content\n", NULL, NULL);
   3601         } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) {
   3602             void *val = NULL;
   3603 
   3604             success =
   3605                 lib->check(lib->data, def->name, def->value, &val, node);
   3606             if (success != 1) {
   3607                 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_VALUE,
   3608                            "Value '%s' is not acceptable for type '%s'\n",
   3609                            def->value, def->name);
   3610             } else {
   3611                 if (val != NULL)
   3612                     def->attrs = val;
   3613             }
   3614         }
   3615     }
   3616     return (def);
   3617 }
   3618 
   3619 /**
   3620  * xmlRelaxNGParseData:
   3621  * @ctxt:  a Relax-NG parser context
   3622  * @node:  the data node.
   3623  *
   3624  * parse the content of a RelaxNG data node.
   3625  *
   3626  * Returns the definition pointer or NULL in case of error
   3627  */
   3628 static xmlRelaxNGDefinePtr
   3629 xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   3630 {
   3631     xmlRelaxNGDefinePtr def = NULL, except;
   3632     xmlRelaxNGDefinePtr param, lastparam = NULL;
   3633     xmlRelaxNGTypeLibraryPtr lib;
   3634     xmlChar *type;
   3635     xmlChar *library;
   3636     xmlNodePtr content;
   3637     int tmp;
   3638 
   3639     type = xmlGetProp(node, BAD_CAST "type");
   3640     if (type == NULL) {
   3641         xmlRngPErr(ctxt, node, XML_RNGP_TYPE_MISSING, "data has no type\n", NULL,
   3642                    NULL);
   3643         return (NULL);
   3644     }
   3645     xmlRelaxNGNormExtSpace(type);
   3646     if (xmlValidateNCName(type, 0)) {
   3647         xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
   3648                    "data type '%s' is not an NCName\n", type, NULL);
   3649     }
   3650     library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
   3651     if (library == NULL)
   3652         library =
   3653             xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
   3654 
   3655     def = xmlRelaxNGNewDefine(ctxt, node);
   3656     if (def == NULL) {
   3657         xmlFree(type);
   3658         return (NULL);
   3659     }
   3660     def->type = XML_RELAXNG_DATATYPE;
   3661     def->name = type;
   3662     def->ns = library;
   3663 
   3664     lib = (xmlRelaxNGTypeLibraryPtr)
   3665         xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
   3666     if (lib == NULL) {
   3667         xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
   3668                    "Use of unregistered type library '%s'\n", library,
   3669                    NULL);
   3670         def->data = NULL;
   3671     } else {
   3672         def->data = lib;
   3673         if (lib->have == NULL) {
   3674             xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
   3675                        "Internal error with type library '%s': no 'have'\n",
   3676                        library, NULL);
   3677         } else {
   3678             tmp = lib->have(lib->data, def->name);
   3679             if (tmp != 1) {
   3680                 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
   3681                            "Error type '%s' is not exported by type library '%s'\n",
   3682                            def->name, library);
   3683             } else
   3684                 if ((xmlStrEqual
   3685                      (library,
   3686                       BAD_CAST
   3687                       "http://www.w3.org/2001/XMLSchema-datatypes"))
   3688                     && ((xmlStrEqual(def->name, BAD_CAST "IDREF"))
   3689                         || (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) {
   3690                 ctxt->idref = 1;
   3691             }
   3692         }
   3693     }
   3694     content = node->children;
   3695 
   3696     /*
   3697      * Handle optional params
   3698      */
   3699     while (content != NULL) {
   3700         if (!xmlStrEqual(content->name, BAD_CAST "param"))
   3701             break;
   3702         if (xmlStrEqual(library,
   3703                         BAD_CAST "http://relaxng.org/ns/structure/1.0")) {
   3704             xmlRngPErr(ctxt, node, XML_RNGP_PARAM_FORBIDDEN,
   3705                        "Type library '%s' does not allow type parameters\n",
   3706                        library, NULL);
   3707             content = content->next;
   3708             while ((content != NULL) &&
   3709                    (xmlStrEqual(content->name, BAD_CAST "param")))
   3710                 content = content->next;
   3711         } else {
   3712             param = xmlRelaxNGNewDefine(ctxt, node);
   3713             if (param != NULL) {
   3714                 param->type = XML_RELAXNG_PARAM;
   3715                 param->name = xmlGetProp(content, BAD_CAST "name");
   3716                 if (param->name == NULL) {
   3717                     xmlRngPErr(ctxt, node, XML_RNGP_PARAM_NAME_MISSING,
   3718                                "param has no name\n", NULL, NULL);
   3719                 }
   3720                 param->value = xmlNodeGetContent(content);
   3721                 if (lastparam == NULL) {
   3722                     def->attrs = lastparam = param;
   3723                 } else {
   3724                     lastparam->next = param;
   3725                     lastparam = param;
   3726                 }
   3727                 if (lib != NULL) {
   3728                 }
   3729             }
   3730             content = content->next;
   3731         }
   3732     }
   3733     /*
   3734      * Handle optional except
   3735      */
   3736     if ((content != NULL)
   3737         && (xmlStrEqual(content->name, BAD_CAST "except"))) {
   3738         xmlNodePtr child;
   3739         xmlRelaxNGDefinePtr tmp2, last = NULL;
   3740 
   3741         except = xmlRelaxNGNewDefine(ctxt, node);
   3742         if (except == NULL) {
   3743             return (def);
   3744         }
   3745         except->type = XML_RELAXNG_EXCEPT;
   3746         child = content->children;
   3747 	def->content = except;
   3748         if (child == NULL) {
   3749             xmlRngPErr(ctxt, content, XML_RNGP_EXCEPT_NO_CONTENT,
   3750                        "except has no content\n", NULL, NULL);
   3751         }
   3752         while (child != NULL) {
   3753             tmp2 = xmlRelaxNGParsePattern(ctxt, child);
   3754             if (tmp2 != NULL) {
   3755                 if (last == NULL) {
   3756                     except->content = last = tmp2;
   3757                 } else {
   3758                     last->next = tmp2;
   3759                     last = tmp2;
   3760                 }
   3761             }
   3762             child = child->next;
   3763         }
   3764         content = content->next;
   3765     }
   3766     /*
   3767      * Check there is no unhandled data
   3768      */
   3769     if (content != NULL) {
   3770         xmlRngPErr(ctxt, content, XML_RNGP_DATA_CONTENT,
   3771                    "Element data has unexpected content %s\n",
   3772                    content->name, NULL);
   3773     }
   3774 
   3775     return (def);
   3776 }
   3777 
   3778 static const xmlChar *invalidName = BAD_CAST "\1";
   3779 
   3780 /**
   3781  * xmlRelaxNGCompareNameClasses:
   3782  * @defs1:  the first element/attribute defs
   3783  * @defs2:  the second element/attribute defs
   3784  * @name:  the restriction on the name
   3785  * @ns:  the restriction on the namespace
   3786  *
   3787  * Compare the 2 lists of element definitions. The comparison is
   3788  * that if both lists do not accept the same QNames, it returns 1
   3789  * If the 2 lists can accept the same QName the comparison returns 0
   3790  *
   3791  * Returns 1 disttinct, 0 if equal
   3792  */
   3793 static int
   3794 xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,
   3795                              xmlRelaxNGDefinePtr def2)
   3796 {
   3797     int ret = 1;
   3798     xmlNode node;
   3799     xmlNs ns;
   3800     xmlRelaxNGValidCtxt ctxt;
   3801 
   3802     memset(&ctxt, 0, sizeof(xmlRelaxNGValidCtxt));
   3803 
   3804     ctxt.flags = FLAGS_IGNORABLE | FLAGS_NOERROR;
   3805 
   3806     if ((def1->type == XML_RELAXNG_ELEMENT) ||
   3807         (def1->type == XML_RELAXNG_ATTRIBUTE)) {
   3808         if (def2->type == XML_RELAXNG_TEXT)
   3809             return (1);
   3810         if (def1->name != NULL) {
   3811             node.name = def1->name;
   3812         } else {
   3813             node.name = invalidName;
   3814         }
   3815         if (def1->ns != NULL) {
   3816             if (def1->ns[0] == 0) {
   3817                 node.ns = NULL;
   3818             } else {
   3819 	        node.ns = &ns;
   3820                 ns.href = def1->ns;
   3821             }
   3822         } else {
   3823             node.ns = NULL;
   3824         }
   3825         if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) {
   3826             if (def1->nameClass != NULL) {
   3827                 ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2);
   3828             } else {
   3829                 ret = 0;
   3830             }
   3831         } else {
   3832             ret = 1;
   3833         }
   3834     } else if (def1->type == XML_RELAXNG_TEXT) {
   3835         if (def2->type == XML_RELAXNG_TEXT)
   3836             return (0);
   3837         return (1);
   3838     } else if (def1->type == XML_RELAXNG_EXCEPT) {
   3839         ret = xmlRelaxNGCompareNameClasses(def1->content, def2);
   3840 	if (ret == 0)
   3841 	    ret = 1;
   3842 	else if (ret == 1)
   3843 	    ret = 0;
   3844     } else {
   3845         TODO ret = 0;
   3846     }
   3847     if (ret == 0)
   3848         return (ret);
   3849     if ((def2->type == XML_RELAXNG_ELEMENT) ||
   3850         (def2->type == XML_RELAXNG_ATTRIBUTE)) {
   3851         if (def2->name != NULL) {
   3852             node.name = def2->name;
   3853         } else {
   3854             node.name = invalidName;
   3855         }
   3856         node.ns = &ns;
   3857         if (def2->ns != NULL) {
   3858             if (def2->ns[0] == 0) {
   3859                 node.ns = NULL;
   3860             } else {
   3861                 ns.href = def2->ns;
   3862             }
   3863         } else {
   3864             ns.href = invalidName;
   3865         }
   3866         if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) {
   3867             if (def2->nameClass != NULL) {
   3868                 ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1);
   3869             } else {
   3870                 ret = 0;
   3871             }
   3872         } else {
   3873             ret = 1;
   3874         }
   3875     } else {
   3876         TODO ret = 0;
   3877     }
   3878 
   3879     return (ret);
   3880 }
   3881 
   3882 /**
   3883  * xmlRelaxNGCompareElemDefLists:
   3884  * @ctxt:  a Relax-NG parser context
   3885  * @defs1:  the first list of element/attribute defs
   3886  * @defs2:  the second list of element/attribute defs
   3887  *
   3888  * Compare the 2 lists of element or attribute definitions. The comparison
   3889  * is that if both lists do not accept the same QNames, it returns 1
   3890  * If the 2 lists can accept the same QName the comparison returns 0
   3891  *
   3892  * Returns 1 disttinct, 0 if equal
   3893  */
   3894 static int
   3895 xmlRelaxNGCompareElemDefLists(xmlRelaxNGParserCtxtPtr ctxt
   3896                               ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr * def1,
   3897                               xmlRelaxNGDefinePtr * def2)
   3898 {
   3899     xmlRelaxNGDefinePtr *basedef2 = def2;
   3900 
   3901     if ((def1 == NULL) || (def2 == NULL))
   3902         return (1);
   3903     if ((*def1 == NULL) || (*def2 == NULL))
   3904         return (1);
   3905     while (*def1 != NULL) {
   3906         while ((*def2) != NULL) {
   3907             if (xmlRelaxNGCompareNameClasses(*def1, *def2) == 0)
   3908                 return (0);
   3909             def2++;
   3910         }
   3911         def2 = basedef2;
   3912         def1++;
   3913     }
   3914     return (1);
   3915 }
   3916 
   3917 /**
   3918  * xmlRelaxNGGenerateAttributes:
   3919  * @ctxt:  a Relax-NG parser context
   3920  * @def:  the definition definition
   3921  *
   3922  * Check if the definition can only generate attributes
   3923  *
   3924  * Returns 1 if yes, 0 if no and -1 in case of error.
   3925  */
   3926 static int
   3927 xmlRelaxNGGenerateAttributes(xmlRelaxNGParserCtxtPtr ctxt,
   3928                              xmlRelaxNGDefinePtr def)
   3929 {
   3930     xmlRelaxNGDefinePtr parent, cur, tmp;
   3931 
   3932     /*
   3933      * Don't run that check in case of error. Infinite recursion
   3934      * becomes possible.
   3935      */
   3936     if (ctxt->nbErrors != 0)
   3937         return (-1);
   3938 
   3939     parent = NULL;
   3940     cur = def;
   3941     while (cur != NULL) {
   3942         if ((cur->type == XML_RELAXNG_ELEMENT) ||
   3943             (cur->type == XML_RELAXNG_TEXT) ||
   3944             (cur->type == XML_RELAXNG_DATATYPE) ||
   3945             (cur->type == XML_RELAXNG_PARAM) ||
   3946             (cur->type == XML_RELAXNG_LIST) ||
   3947             (cur->type == XML_RELAXNG_VALUE) ||
   3948             (cur->type == XML_RELAXNG_EMPTY))
   3949             return (0);
   3950         if ((cur->type == XML_RELAXNG_CHOICE) ||
   3951             (cur->type == XML_RELAXNG_INTERLEAVE) ||
   3952             (cur->type == XML_RELAXNG_GROUP) ||
   3953             (cur->type == XML_RELAXNG_ONEORMORE) ||
   3954             (cur->type == XML_RELAXNG_ZEROORMORE) ||
   3955             (cur->type == XML_RELAXNG_OPTIONAL) ||
   3956             (cur->type == XML_RELAXNG_PARENTREF) ||
   3957             (cur->type == XML_RELAXNG_EXTERNALREF) ||
   3958             (cur->type == XML_RELAXNG_REF) ||
   3959             (cur->type == XML_RELAXNG_DEF)) {
   3960             if (cur->content != NULL) {
   3961                 parent = cur;
   3962                 cur = cur->content;
   3963                 tmp = cur;
   3964                 while (tmp != NULL) {
   3965                     tmp->parent = parent;
   3966                     tmp = tmp->next;
   3967                 }
   3968                 continue;
   3969             }
   3970         }
   3971         if (cur == def)
   3972             break;
   3973         if (cur->next != NULL) {
   3974             cur = cur->next;
   3975             continue;
   3976         }
   3977         do {
   3978             cur = cur->parent;
   3979             if (cur == NULL)
   3980                 break;
   3981             if (cur == def)
   3982                 return (1);
   3983             if (cur->next != NULL) {
   3984                 cur = cur->next;
   3985                 break;
   3986             }
   3987         } while (cur != NULL);
   3988     }
   3989     return (1);
   3990 }
   3991 
   3992 /**
   3993  * xmlRelaxNGGetElements:
   3994  * @ctxt:  a Relax-NG parser context
   3995  * @def:  the definition definition
   3996  * @eora:  gather elements (0), attributes (1) or elements and text (2)
   3997  *
   3998  * Compute the list of top elements a definition can generate
   3999  *
   4000  * Returns a list of elements or NULL if none was found.
   4001  */
   4002 static xmlRelaxNGDefinePtr *
   4003 xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
   4004                       xmlRelaxNGDefinePtr def, int eora)
   4005 {
   4006     xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp;
   4007     int len = 0;
   4008     int max = 0;
   4009 
   4010     /*
   4011      * Don't run that check in case of error. Infinite recursion
   4012      * becomes possible.
   4013      */
   4014     if (ctxt->nbErrors != 0)
   4015         return (NULL);
   4016 
   4017     parent = NULL;
   4018     cur = def;
   4019     while (cur != NULL) {
   4020         if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||
   4021                              (cur->type == XML_RELAXNG_TEXT))) ||
   4022             ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE)) ||
   4023             ((eora == 2) && ((cur->type == XML_RELAXNG_DATATYPE) ||
   4024 	                     (cur->type == XML_RELAXNG_ELEMENT) ||
   4025 			     (cur->type == XML_RELAXNG_LIST) ||
   4026                              (cur->type == XML_RELAXNG_TEXT) ||
   4027 			     (cur->type == XML_RELAXNG_VALUE)))) {
   4028             if (ret == NULL) {
   4029                 max = 10;
   4030                 ret = (xmlRelaxNGDefinePtr *)
   4031                     xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr));
   4032                 if (ret == NULL) {
   4033                     xmlRngPErrMemory(ctxt, "getting element list\n");
   4034                     return (NULL);
   4035                 }
   4036             } else if (max <= len) {
   4037 	        xmlRelaxNGDefinePtr *temp;
   4038 
   4039                 max *= 2;
   4040                 temp = xmlRealloc(ret,
   4041                                (max + 1) * sizeof(xmlRelaxNGDefinePtr));
   4042                 if (temp == NULL) {
   4043                     xmlRngPErrMemory(ctxt, "getting element list\n");
   4044 		    xmlFree(ret);
   4045                     return (NULL);
   4046                 }
   4047 		ret = temp;
   4048             }
   4049             ret[len++] = cur;
   4050             ret[len] = NULL;
   4051         } else if ((cur->type == XML_RELAXNG_CHOICE) ||
   4052                    (cur->type == XML_RELAXNG_INTERLEAVE) ||
   4053                    (cur->type == XML_RELAXNG_GROUP) ||
   4054                    (cur->type == XML_RELAXNG_ONEORMORE) ||
   4055                    (cur->type == XML_RELAXNG_ZEROORMORE) ||
   4056                    (cur->type == XML_RELAXNG_OPTIONAL) ||
   4057                    (cur->type == XML_RELAXNG_PARENTREF) ||
   4058                    (cur->type == XML_RELAXNG_REF) ||
   4059                    (cur->type == XML_RELAXNG_DEF) ||
   4060 		   (cur->type == XML_RELAXNG_EXTERNALREF)) {
   4061             /*
   4062              * Don't go within elements or attributes or string values.
   4063              * Just gather the element top list
   4064              */
   4065             if (cur->content != NULL) {
   4066                 parent = cur;
   4067                 cur = cur->content;
   4068                 tmp = cur;
   4069                 while (tmp != NULL) {
   4070                     tmp->parent = parent;
   4071                     tmp = tmp->next;
   4072                 }
   4073                 continue;
   4074             }
   4075         }
   4076         if (cur == def)
   4077             break;
   4078         if (cur->next != NULL) {
   4079             cur = cur->next;
   4080             continue;
   4081         }
   4082         do {
   4083             cur = cur->parent;
   4084             if (cur == NULL)
   4085                 break;
   4086             if (cur == def)
   4087                 return (ret);
   4088             if (cur->next != NULL) {
   4089                 cur = cur->next;
   4090                 break;
   4091             }
   4092         } while (cur != NULL);
   4093     }
   4094     return (ret);
   4095 }
   4096 
   4097 /**
   4098  * xmlRelaxNGCheckChoiceDeterminism:
   4099  * @ctxt:  a Relax-NG parser context
   4100  * @def:  the choice definition
   4101  *
   4102  * Also used to find indeterministic pattern in choice
   4103  */
   4104 static void
   4105 xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt,
   4106                                  xmlRelaxNGDefinePtr def)
   4107 {
   4108     xmlRelaxNGDefinePtr **list;
   4109     xmlRelaxNGDefinePtr cur;
   4110     int nbchild = 0, i, j, ret;
   4111     int is_nullable = 0;
   4112     int is_indeterminist = 0;
   4113     xmlHashTablePtr triage = NULL;
   4114     int is_triable = 1;
   4115 
   4116     if ((def == NULL) || (def->type != XML_RELAXNG_CHOICE))
   4117         return;
   4118 
   4119     if (def->dflags & IS_PROCESSED)
   4120         return;
   4121 
   4122     /*
   4123      * Don't run that check in case of error. Infinite recursion
   4124      * becomes possible.
   4125      */
   4126     if (ctxt->nbErrors != 0)
   4127         return;
   4128 
   4129     is_nullable = xmlRelaxNGIsNullable(def);
   4130 
   4131     cur = def->content;
   4132     while (cur != NULL) {
   4133         nbchild++;
   4134         cur = cur->next;
   4135     }
   4136 
   4137     list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
   4138                                               sizeof(xmlRelaxNGDefinePtr
   4139                                                      *));
   4140     if (list == NULL) {
   4141         xmlRngPErrMemory(ctxt, "building choice\n");
   4142         return;
   4143     }
   4144     i = 0;
   4145     /*
   4146      * a bit strong but safe
   4147      */
   4148     if (is_nullable == 0) {
   4149         triage = xmlHashCreate(10);
   4150     } else {
   4151         is_triable = 0;
   4152     }
   4153     cur = def->content;
   4154     while (cur != NULL) {
   4155         list[i] = xmlRelaxNGGetElements(ctxt, cur, 0);
   4156         if ((list[i] == NULL) || (list[i][0] == NULL)) {
   4157             is_triable = 0;
   4158         } else if (is_triable == 1) {
   4159             xmlRelaxNGDefinePtr *tmp;
   4160             int res;
   4161 
   4162             tmp = list[i];
   4163             while ((*tmp != NULL) && (is_triable == 1)) {
   4164                 if ((*tmp)->type == XML_RELAXNG_TEXT) {
   4165                     res = xmlHashAddEntry2(triage,
   4166                                            BAD_CAST "#text", NULL,
   4167                                            (void *) cur);
   4168                     if (res != 0)
   4169                         is_triable = -1;
   4170                 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
   4171                            ((*tmp)->name != NULL)) {
   4172                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
   4173                         res = xmlHashAddEntry2(triage,
   4174                                                (*tmp)->name, NULL,
   4175                                                (void *) cur);
   4176                     else
   4177                         res = xmlHashAddEntry2(triage,
   4178                                                (*tmp)->name, (*tmp)->ns,
   4179                                                (void *) cur);
   4180                     if (res != 0)
   4181                         is_triable = -1;
   4182                 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
   4183                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
   4184                         res = xmlHashAddEntry2(triage,
   4185                                                BAD_CAST "#any", NULL,
   4186                                                (void *) cur);
   4187                     else
   4188                         res = xmlHashAddEntry2(triage,
   4189                                                BAD_CAST "#any", (*tmp)->ns,
   4190                                                (void *) cur);
   4191                     if (res != 0)
   4192                         is_triable = -1;
   4193                 } else {
   4194                     is_triable = -1;
   4195                 }
   4196                 tmp++;
   4197             }
   4198         }
   4199         i++;
   4200         cur = cur->next;
   4201     }
   4202 
   4203     for (i = 0; i < nbchild; i++) {
   4204         if (list[i] == NULL)
   4205             continue;
   4206         for (j = 0; j < i; j++) {
   4207             if (list[j] == NULL)
   4208                 continue;
   4209             ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
   4210             if (ret == 0) {
   4211                 is_indeterminist = 1;
   4212             }
   4213         }
   4214     }
   4215     for (i = 0; i < nbchild; i++) {
   4216         if (list[i] != NULL)
   4217             xmlFree(list[i]);
   4218     }
   4219 
   4220     xmlFree(list);
   4221     if (is_indeterminist) {
   4222         def->dflags |= IS_INDETERMINIST;
   4223     }
   4224     if (is_triable == 1) {
   4225         def->dflags |= IS_TRIABLE;
   4226         def->data = triage;
   4227     } else if (triage != NULL) {
   4228         xmlHashFree(triage, NULL);
   4229     }
   4230     def->dflags |= IS_PROCESSED;
   4231 }
   4232 
   4233 /**
   4234  * xmlRelaxNGCheckGroupAttrs:
   4235  * @ctxt:  a Relax-NG parser context
   4236  * @def:  the group definition
   4237  *
   4238  * Detects violations of rule 7.3
   4239  */
   4240 static void
   4241 xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,
   4242                           xmlRelaxNGDefinePtr def)
   4243 {
   4244     xmlRelaxNGDefinePtr **list;
   4245     xmlRelaxNGDefinePtr cur;
   4246     int nbchild = 0, i, j, ret;
   4247 
   4248     if ((def == NULL) ||
   4249         ((def->type != XML_RELAXNG_GROUP) &&
   4250          (def->type != XML_RELAXNG_ELEMENT)))
   4251         return;
   4252 
   4253     if (def->dflags & IS_PROCESSED)
   4254         return;
   4255 
   4256     /*
   4257      * Don't run that check in case of error. Infinite recursion
   4258      * becomes possible.
   4259      */
   4260     if (ctxt->nbErrors != 0)
   4261         return;
   4262 
   4263     cur = def->attrs;
   4264     while (cur != NULL) {
   4265         nbchild++;
   4266         cur = cur->next;
   4267     }
   4268     cur = def->content;
   4269     while (cur != NULL) {
   4270         nbchild++;
   4271         cur = cur->next;
   4272     }
   4273 
   4274     list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
   4275                                               sizeof(xmlRelaxNGDefinePtr
   4276                                                      *));
   4277     if (list == NULL) {
   4278         xmlRngPErrMemory(ctxt, "building group\n");
   4279         return;
   4280     }
   4281     i = 0;
   4282     cur = def->attrs;
   4283     while (cur != NULL) {
   4284         list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
   4285         i++;
   4286         cur = cur->next;
   4287     }
   4288     cur = def->content;
   4289     while (cur != NULL) {
   4290         list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
   4291         i++;
   4292         cur = cur->next;
   4293     }
   4294 
   4295     for (i = 0; i < nbchild; i++) {
   4296         if (list[i] == NULL)
   4297             continue;
   4298         for (j = 0; j < i; j++) {
   4299             if (list[j] == NULL)
   4300                 continue;
   4301             ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
   4302             if (ret == 0) {
   4303                 xmlRngPErr(ctxt, def->node, XML_RNGP_GROUP_ATTR_CONFLICT,
   4304                            "Attributes conflicts in group\n", NULL, NULL);
   4305             }
   4306         }
   4307     }
   4308     for (i = 0; i < nbchild; i++) {
   4309         if (list[i] != NULL)
   4310             xmlFree(list[i]);
   4311     }
   4312 
   4313     xmlFree(list);
   4314     def->dflags |= IS_PROCESSED;
   4315 }
   4316 
   4317 /**
   4318  * xmlRelaxNGComputeInterleaves:
   4319  * @def:  the interleave definition
   4320  * @ctxt:  a Relax-NG parser context
   4321  * @name:  the definition name
   4322  *
   4323  * A lot of work for preprocessing interleave definitions
   4324  * is potentially needed to get a decent execution speed at runtime
   4325  *   - trying to get a total order on the element nodes generated
   4326  *     by the interleaves, order the list of interleave definitions
   4327  *     following that order.
   4328  *   - if <text/> is used to handle mixed content, it is better to
   4329  *     flag this in the define and simplify the runtime checking
   4330  *     algorithm
   4331  */
   4332 static void
   4333 xmlRelaxNGComputeInterleaves(void *payload, void *data,
   4334                              const xmlChar * name ATTRIBUTE_UNUSED)
   4335 {
   4336     xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
   4337     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
   4338     xmlRelaxNGDefinePtr cur, *tmp;
   4339 
   4340     xmlRelaxNGPartitionPtr partitions = NULL;
   4341     xmlRelaxNGInterleaveGroupPtr *groups = NULL;
   4342     xmlRelaxNGInterleaveGroupPtr group;
   4343     int i, j, ret, res;
   4344     int nbgroups = 0;
   4345     int nbchild = 0;
   4346     int is_mixed = 0;
   4347     int is_determinist = 1;
   4348 
   4349     /*
   4350      * Don't run that check in case of error. Infinite recursion
   4351      * becomes possible.
   4352      */
   4353     if (ctxt->nbErrors != 0)
   4354         return;
   4355 
   4356 #ifdef DEBUG_INTERLEAVE
   4357     xmlGenericError(xmlGenericErrorContext,
   4358                     "xmlRelaxNGComputeInterleaves(%s)\n", name);
   4359 #endif
   4360     cur = def->content;
   4361     while (cur != NULL) {
   4362         nbchild++;
   4363         cur = cur->next;
   4364     }
   4365 
   4366 #ifdef DEBUG_INTERLEAVE
   4367     xmlGenericError(xmlGenericErrorContext, "  %d child\n", nbchild);
   4368 #endif
   4369     groups = (xmlRelaxNGInterleaveGroupPtr *)
   4370         xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr));
   4371     if (groups == NULL)
   4372         goto error;
   4373     cur = def->content;
   4374     while (cur != NULL) {
   4375         groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr)
   4376             xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup));
   4377         if (groups[nbgroups] == NULL)
   4378             goto error;
   4379         if (cur->type == XML_RELAXNG_TEXT)
   4380             is_mixed++;
   4381         groups[nbgroups]->rule = cur;
   4382         groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 2);
   4383         groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
   4384         nbgroups++;
   4385         cur = cur->next;
   4386     }
   4387 #ifdef DEBUG_INTERLEAVE
   4388     xmlGenericError(xmlGenericErrorContext, "  %d groups\n", nbgroups);
   4389 #endif
   4390 
   4391     /*
   4392      * Let's check that all rules makes a partitions according to 7.4
   4393      */
   4394     partitions = (xmlRelaxNGPartitionPtr)
   4395         xmlMalloc(sizeof(xmlRelaxNGPartition));
   4396     if (partitions == NULL)
   4397         goto error;
   4398     memset(partitions, 0, sizeof(xmlRelaxNGPartition));
   4399     partitions->nbgroups = nbgroups;
   4400     partitions->triage = xmlHashCreate(nbgroups);
   4401     for (i = 0; i < nbgroups; i++) {
   4402         group = groups[i];
   4403         for (j = i + 1; j < nbgroups; j++) {
   4404             if (groups[j] == NULL)
   4405                 continue;
   4406 
   4407             ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs,
   4408                                                 groups[j]->defs);
   4409             if (ret == 0) {
   4410                 xmlRngPErr(ctxt, def->node, XML_RNGP_ELEM_TEXT_CONFLICT,
   4411                            "Element or text conflicts in interleave\n",
   4412                            NULL, NULL);
   4413             }
   4414             ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs,
   4415                                                 groups[j]->attrs);
   4416             if (ret == 0) {
   4417                 xmlRngPErr(ctxt, def->node, XML_RNGP_ATTR_CONFLICT,
   4418                            "Attributes conflicts in interleave\n", NULL,
   4419                            NULL);
   4420             }
   4421         }
   4422         tmp = group->defs;
   4423         if ((tmp != NULL) && (*tmp != NULL)) {
   4424             while (*tmp != NULL) {
   4425                 if ((*tmp)->type == XML_RELAXNG_TEXT) {
   4426                     res = xmlHashAddEntry2(partitions->triage,
   4427                                            BAD_CAST "#text", NULL,
   4428                                            (void *) (ptrdiff_t) (i + 1));
   4429                     if (res != 0)
   4430                         is_determinist = -1;
   4431                 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
   4432                            ((*tmp)->name != NULL)) {
   4433                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
   4434                         res = xmlHashAddEntry2(partitions->triage,
   4435                                                (*tmp)->name, NULL,
   4436                                                (void *) (ptrdiff_t) (i + 1));
   4437                     else
   4438                         res = xmlHashAddEntry2(partitions->triage,
   4439                                                (*tmp)->name, (*tmp)->ns,
   4440                                                (void *) (ptrdiff_t) (i + 1));
   4441                     if (res != 0)
   4442                         is_determinist = -1;
   4443                 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
   4444                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
   4445                         res = xmlHashAddEntry2(partitions->triage,
   4446                                                BAD_CAST "#any", NULL,
   4447                                                (void *) (ptrdiff_t) (i + 1));
   4448                     else
   4449                         res = xmlHashAddEntry2(partitions->triage,
   4450                                                BAD_CAST "#any", (*tmp)->ns,
   4451                                                (void *) (ptrdiff_t) (i + 1));
   4452                     if ((*tmp)->nameClass != NULL)
   4453                         is_determinist = 2;
   4454                     if (res != 0)
   4455                         is_determinist = -1;
   4456                 } else {
   4457                     is_determinist = -1;
   4458                 }
   4459                 tmp++;
   4460             }
   4461         } else {
   4462             is_determinist = 0;
   4463         }
   4464     }
   4465     partitions->groups = groups;
   4466 
   4467     /*
   4468      * and save the partition list back in the def
   4469      */
   4470     def->data = partitions;
   4471     if (is_mixed != 0)
   4472         def->dflags |= IS_MIXED;
   4473     if (is_determinist == 1)
   4474         partitions->flags = IS_DETERMINIST;
   4475     if (is_determinist == 2)
   4476         partitions->flags = IS_DETERMINIST | IS_NEEDCHECK;
   4477     return;
   4478 
   4479   error:
   4480     xmlRngPErrMemory(ctxt, "in interleave computation\n");
   4481     if (groups != NULL) {
   4482         for (i = 0; i < nbgroups; i++)
   4483             if (groups[i] != NULL) {
   4484                 if (groups[i]->defs != NULL)
   4485                     xmlFree(groups[i]->defs);
   4486                 xmlFree(groups[i]);
   4487             }
   4488         xmlFree(groups);
   4489     }
   4490     xmlRelaxNGFreePartition(partitions);
   4491 }
   4492 
   4493 /**
   4494  * xmlRelaxNGParseInterleave:
   4495  * @ctxt:  a Relax-NG parser context
   4496  * @node:  the data node.
   4497  *
   4498  * parse the content of a RelaxNG interleave node.
   4499  *
   4500  * Returns the definition pointer or NULL in case of error
   4501  */
   4502 static xmlRelaxNGDefinePtr
   4503 xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4504 {
   4505     xmlRelaxNGDefinePtr def = NULL;
   4506     xmlRelaxNGDefinePtr last = NULL, cur;
   4507     xmlNodePtr child;
   4508 
   4509     def = xmlRelaxNGNewDefine(ctxt, node);
   4510     if (def == NULL) {
   4511         return (NULL);
   4512     }
   4513     def->type = XML_RELAXNG_INTERLEAVE;
   4514 
   4515     if (ctxt->interleaves == NULL)
   4516         ctxt->interleaves = xmlHashCreate(10);
   4517     if (ctxt->interleaves == NULL) {
   4518         xmlRngPErrMemory(ctxt, "create interleaves\n");
   4519     } else {
   4520         char name[32];
   4521 
   4522         snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++);
   4523         if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) {
   4524             xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_ADD,
   4525                        "Failed to add %s to hash table\n",
   4526 		       (const xmlChar *) name, NULL);
   4527         }
   4528     }
   4529     child = node->children;
   4530     if (child == NULL) {
   4531         xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_NO_CONTENT,
   4532                    "Element interleave is empty\n", NULL, NULL);
   4533     }
   4534     while (child != NULL) {
   4535         if (IS_RELAXNG(child, "element")) {
   4536             cur = xmlRelaxNGParseElement(ctxt, child);
   4537         } else {
   4538             cur = xmlRelaxNGParsePattern(ctxt, child);
   4539         }
   4540         if (cur != NULL) {
   4541             cur->parent = def;
   4542             if (last == NULL) {
   4543                 def->content = last = cur;
   4544             } else {
   4545                 last->next = cur;
   4546                 last = cur;
   4547             }
   4548         }
   4549         child = child->next;
   4550     }
   4551 
   4552     return (def);
   4553 }
   4554 
   4555 /**
   4556  * xmlRelaxNGParseInclude:
   4557  * @ctxt:  a Relax-NG parser context
   4558  * @node:  the include node
   4559  *
   4560  * Integrate the content of an include node in the current grammar
   4561  *
   4562  * Returns 0 in case of success or -1 in case of error
   4563  */
   4564 static int
   4565 xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4566 {
   4567     xmlRelaxNGIncludePtr incl;
   4568     xmlNodePtr root;
   4569     int ret = 0, tmp;
   4570 
   4571     incl = node->psvi;
   4572     if (incl == NULL) {
   4573         xmlRngPErr(ctxt, node, XML_RNGP_INCLUDE_EMPTY,
   4574                    "Include node has no data\n", NULL, NULL);
   4575         return (-1);
   4576     }
   4577     root = xmlDocGetRootElement(incl->doc);
   4578     if (root == NULL) {
   4579         xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, "Include document is empty\n",
   4580                    NULL, NULL);
   4581         return (-1);
   4582     }
   4583     if (!xmlStrEqual(root->name, BAD_CAST "grammar")) {
   4584         xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
   4585                    "Include document root is not a grammar\n", NULL, NULL);
   4586         return (-1);
   4587     }
   4588 
   4589     /*
   4590      * Merge the definition from both the include and the internal list
   4591      */
   4592     if (root->children != NULL) {
   4593         tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children);
   4594         if (tmp != 0)
   4595             ret = -1;
   4596     }
   4597     if (node->children != NULL) {
   4598         tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children);
   4599         if (tmp != 0)
   4600             ret = -1;
   4601     }
   4602     return (ret);
   4603 }
   4604 
   4605 /**
   4606  * xmlRelaxNGParseDefine:
   4607  * @ctxt:  a Relax-NG parser context
   4608  * @node:  the define node
   4609  *
   4610  * parse the content of a RelaxNG define element node.
   4611  *
   4612  * Returns 0 in case of success or -1 in case of error
   4613  */
   4614 static int
   4615 xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4616 {
   4617     xmlChar *name;
   4618     int ret = 0, tmp;
   4619     xmlRelaxNGDefinePtr def;
   4620     const xmlChar *olddefine;
   4621 
   4622     name = xmlGetProp(node, BAD_CAST "name");
   4623     if (name == NULL) {
   4624         xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_NAME_MISSING,
   4625                    "define has no name\n", NULL, NULL);
   4626     } else {
   4627         xmlRelaxNGNormExtSpace(name);
   4628         if (xmlValidateNCName(name, 0)) {
   4629             xmlRngPErr(ctxt, node, XML_RNGP_INVALID_DEFINE_NAME,
   4630                        "define name '%s' is not an NCName\n", name, NULL);
   4631         }
   4632         def = xmlRelaxNGNewDefine(ctxt, node);
   4633         if (def == NULL) {
   4634             xmlFree(name);
   4635             return (-1);
   4636         }
   4637         def->type = XML_RELAXNG_DEF;
   4638         def->name = name;
   4639         if (node->children == NULL) {
   4640             xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_EMPTY,
   4641                        "define has no children\n", NULL, NULL);
   4642         } else {
   4643             olddefine = ctxt->define;
   4644             ctxt->define = name;
   4645             def->content =
   4646                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
   4647             ctxt->define = olddefine;
   4648         }
   4649         if (ctxt->grammar->defs == NULL)
   4650             ctxt->grammar->defs = xmlHashCreate(10);
   4651         if (ctxt->grammar->defs == NULL) {
   4652             xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
   4653                        "Could not create definition hash\n", NULL, NULL);
   4654             ret = -1;
   4655         } else {
   4656             tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
   4657             if (tmp < 0) {
   4658                 xmlRelaxNGDefinePtr prev;
   4659 
   4660                 prev = xmlHashLookup(ctxt->grammar->defs, name);
   4661                 if (prev == NULL) {
   4662                     xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
   4663                                "Internal error on define aggregation of %s\n",
   4664                                name, NULL);
   4665                     ret = -1;
   4666                 } else {
   4667                     while (prev->nextHash != NULL)
   4668                         prev = prev->nextHash;
   4669                     prev->nextHash = def;
   4670                 }
   4671             }
   4672         }
   4673     }
   4674     return (ret);
   4675 }
   4676 
   4677 /**
   4678  * xmlRelaxNGParseImportRef:
   4679  * @payload: the parser context
   4680  * @data: the current grammar
   4681  * @name: the reference name
   4682  *
   4683  * Import import one references into the current grammar
   4684  */
   4685 static void
   4686 xmlRelaxNGParseImportRef(void *payload, void *data, const xmlChar *name) {
   4687     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
   4688     xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
   4689     int tmp;
   4690 
   4691     def->dflags |= IS_EXTERNAL_REF;
   4692 
   4693     tmp = xmlHashAddEntry(ctxt->grammar->refs, name, def);
   4694     if (tmp < 0) {
   4695         xmlRelaxNGDefinePtr prev;
   4696 
   4697         prev = (xmlRelaxNGDefinePtr)
   4698             xmlHashLookup(ctxt->grammar->refs, def->name);
   4699         if (prev == NULL) {
   4700             if (def->name != NULL) {
   4701                 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
   4702                            "Error refs definitions '%s'\n",
   4703                            def->name, NULL);
   4704             } else {
   4705                 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
   4706                            "Error refs definitions\n",
   4707                            NULL, NULL);
   4708             }
   4709         } else {
   4710             def->nextHash = prev->nextHash;
   4711             prev->nextHash = def;
   4712         }
   4713     }
   4714 }
   4715 
   4716 /**
   4717  * xmlRelaxNGParseImportRefs:
   4718  * @ctxt: the parser context
   4719  * @grammar: the sub grammar
   4720  *
   4721  * Import references from the subgrammar into the current grammar
   4722  *
   4723  * Returns 0 in case of success, -1 in case of failure
   4724  */
   4725 static int
   4726 xmlRelaxNGParseImportRefs(xmlRelaxNGParserCtxtPtr ctxt,
   4727                           xmlRelaxNGGrammarPtr grammar) {
   4728     if ((ctxt == NULL) || (grammar == NULL) || (ctxt->grammar == NULL))
   4729         return(-1);
   4730     if (grammar->refs == NULL)
   4731         return(0);
   4732     if (ctxt->grammar->refs == NULL)
   4733         ctxt->grammar->refs = xmlHashCreate(10);
   4734     if (ctxt->grammar->refs == NULL) {
   4735         xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
   4736                    "Could not create references hash\n", NULL, NULL);
   4737         return(-1);
   4738     }
   4739     xmlHashScan(grammar->refs, xmlRelaxNGParseImportRef, ctxt);
   4740     return(0);
   4741 }
   4742 
   4743 /**
   4744  * xmlRelaxNGProcessExternalRef:
   4745  * @ctxt: the parser context
   4746  * @node:  the externlRef node
   4747  *
   4748  * Process and compile an externlRef node
   4749  *
   4750  * Returns the xmlRelaxNGDefinePtr or NULL in case of error
   4751  */
   4752 static xmlRelaxNGDefinePtr
   4753 xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4754 {
   4755     xmlRelaxNGDocumentPtr docu;
   4756     xmlNodePtr root, tmp;
   4757     xmlChar *ns;
   4758     int newNs = 0, oldflags;
   4759     xmlRelaxNGDefinePtr def;
   4760 
   4761     docu = node->psvi;
   4762     if (docu != NULL) {
   4763         def = xmlRelaxNGNewDefine(ctxt, node);
   4764         if (def == NULL)
   4765             return (NULL);
   4766         def->type = XML_RELAXNG_EXTERNALREF;
   4767 
   4768         if (docu->content == NULL) {
   4769             /*
   4770              * Then do the parsing for good
   4771              */
   4772             root = xmlDocGetRootElement(docu->doc);
   4773             if (root == NULL) {
   4774                 xmlRngPErr(ctxt, node, XML_RNGP_EXTERNALREF_EMTPY,
   4775                            "xmlRelaxNGParse: %s is empty\n", ctxt->URL,
   4776                            NULL);
   4777                 return (NULL);
   4778             }
   4779             /*
   4780              * ns transmission rules
   4781              */
   4782             ns = xmlGetProp(root, BAD_CAST "ns");
   4783             if (ns == NULL) {
   4784                 tmp = node;
   4785                 while ((tmp != NULL) && (tmp->type == XML_ELEMENT_NODE)) {
   4786                     ns = xmlGetProp(tmp, BAD_CAST "ns");
   4787                     if (ns != NULL) {
   4788                         break;
   4789                     }
   4790                     tmp = tmp->parent;
   4791                 }
   4792                 if (ns != NULL) {
   4793                     xmlSetProp(root, BAD_CAST "ns", ns);
   4794                     newNs = 1;
   4795                     xmlFree(ns);
   4796                 }
   4797             } else {
   4798                 xmlFree(ns);
   4799             }
   4800 
   4801             /*
   4802              * Parsing to get a precompiled schemas.
   4803              */
   4804             oldflags = ctxt->flags;
   4805             ctxt->flags |= XML_RELAXNG_IN_EXTERNALREF;
   4806             docu->schema = xmlRelaxNGParseDocument(ctxt, root);
   4807             ctxt->flags = oldflags;
   4808             if ((docu->schema != NULL) &&
   4809                 (docu->schema->topgrammar != NULL)) {
   4810                 docu->content = docu->schema->topgrammar->start;
   4811                 if (docu->schema->topgrammar->refs)
   4812                     xmlRelaxNGParseImportRefs(ctxt, docu->schema->topgrammar);
   4813             }
   4814 
   4815             /*
   4816              * the externalRef may be reused in a different ns context
   4817              */
   4818             if (newNs == 1) {
   4819                 xmlUnsetProp(root, BAD_CAST "ns");
   4820             }
   4821         }
   4822         def->content = docu->content;
   4823     } else {
   4824         def = NULL;
   4825     }
   4826     return (def);
   4827 }
   4828 
   4829 /**
   4830  * xmlRelaxNGParsePattern:
   4831  * @ctxt:  a Relax-NG parser context
   4832  * @node:  the pattern node.
   4833  *
   4834  * parse the content of a RelaxNG pattern node.
   4835  *
   4836  * Returns the definition pointer or NULL in case of error or if no
   4837  *     pattern is generated.
   4838  */
   4839 static xmlRelaxNGDefinePtr
   4840 xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4841 {
   4842     xmlRelaxNGDefinePtr def = NULL;
   4843 
   4844     if (node == NULL) {
   4845         return (NULL);
   4846     }
   4847     if (IS_RELAXNG(node, "element")) {
   4848         def = xmlRelaxNGParseElement(ctxt, node);
   4849     } else if (IS_RELAXNG(node, "attribute")) {
   4850         def = xmlRelaxNGParseAttribute(ctxt, node);
   4851     } else if (IS_RELAXNG(node, "empty")) {
   4852         def = xmlRelaxNGNewDefine(ctxt, node);
   4853         if (def == NULL)
   4854             return (NULL);
   4855         def->type = XML_RELAXNG_EMPTY;
   4856         if (node->children != NULL) {
   4857             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_NOT_EMPTY,
   4858                        "empty: had a child node\n", NULL, NULL);
   4859         }
   4860     } else if (IS_RELAXNG(node, "text")) {
   4861         def = xmlRelaxNGNewDefine(ctxt, node);
   4862         if (def == NULL)
   4863             return (NULL);
   4864         def->type = XML_RELAXNG_TEXT;
   4865         if (node->children != NULL) {
   4866             xmlRngPErr(ctxt, node, XML_RNGP_TEXT_HAS_CHILD,
   4867                        "text: had a child node\n", NULL, NULL);
   4868         }
   4869     } else if (IS_RELAXNG(node, "zeroOrMore")) {
   4870         def = xmlRelaxNGNewDefine(ctxt, node);
   4871         if (def == NULL)
   4872             return (NULL);
   4873         def->type = XML_RELAXNG_ZEROORMORE;
   4874         if (node->children == NULL) {
   4875             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4876                        "Element %s is empty\n", node->name, NULL);
   4877         } else {
   4878             def->content =
   4879                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
   4880         }
   4881     } else if (IS_RELAXNG(node, "oneOrMore")) {
   4882         def = xmlRelaxNGNewDefine(ctxt, node);
   4883         if (def == NULL)
   4884             return (NULL);
   4885         def->type = XML_RELAXNG_ONEORMORE;
   4886         if (node->children == NULL) {
   4887             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4888                        "Element %s is empty\n", node->name, NULL);
   4889         } else {
   4890             def->content =
   4891                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
   4892         }
   4893     } else if (IS_RELAXNG(node, "optional")) {
   4894         def = xmlRelaxNGNewDefine(ctxt, node);
   4895         if (def == NULL)
   4896             return (NULL);
   4897         def->type = XML_RELAXNG_OPTIONAL;
   4898         if (node->children == NULL) {
   4899             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4900                        "Element %s is empty\n", node->name, NULL);
   4901         } else {
   4902             def->content =
   4903                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
   4904         }
   4905     } else if (IS_RELAXNG(node, "choice")) {
   4906         def = xmlRelaxNGNewDefine(ctxt, node);
   4907         if (def == NULL)
   4908             return (NULL);
   4909         def->type = XML_RELAXNG_CHOICE;
   4910         if (node->children == NULL) {
   4911             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4912                        "Element %s is empty\n", node->name, NULL);
   4913         } else {
   4914             def->content =
   4915                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
   4916         }
   4917     } else if (IS_RELAXNG(node, "group")) {
   4918         def = xmlRelaxNGNewDefine(ctxt, node);
   4919         if (def == NULL)
   4920             return (NULL);
   4921         def->type = XML_RELAXNG_GROUP;
   4922         if (node->children == NULL) {
   4923             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4924                        "Element %s is empty\n", node->name, NULL);
   4925         } else {
   4926             def->content =
   4927                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
   4928         }
   4929     } else if (IS_RELAXNG(node, "ref")) {
   4930         def = xmlRelaxNGNewDefine(ctxt, node);
   4931         if (def == NULL)
   4932             return (NULL);
   4933         def->type = XML_RELAXNG_REF;
   4934         def->name = xmlGetProp(node, BAD_CAST "name");
   4935         if (def->name == NULL) {
   4936             xmlRngPErr(ctxt, node, XML_RNGP_REF_NO_NAME, "ref has no name\n",
   4937                        NULL, NULL);
   4938         } else {
   4939             xmlRelaxNGNormExtSpace(def->name);
   4940             if (xmlValidateNCName(def->name, 0)) {
   4941                 xmlRngPErr(ctxt, node, XML_RNGP_REF_NAME_INVALID,
   4942                            "ref name '%s' is not an NCName\n", def->name,
   4943                            NULL);
   4944             }
   4945         }
   4946         if (node->children != NULL) {
   4947             xmlRngPErr(ctxt, node, XML_RNGP_REF_NOT_EMPTY, "ref is not empty\n",
   4948                        NULL, NULL);
   4949         }
   4950         if (ctxt->grammar->refs == NULL)
   4951             ctxt->grammar->refs = xmlHashCreate(10);
   4952         if (ctxt->grammar->refs == NULL) {
   4953             xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
   4954                        "Could not create references hash\n", NULL, NULL);
   4955             def = NULL;
   4956         } else {
   4957             int tmp;
   4958 
   4959             tmp = xmlHashAddEntry(ctxt->grammar->refs, def->name, def);
   4960             if (tmp < 0) {
   4961                 xmlRelaxNGDefinePtr prev;
   4962 
   4963                 prev = (xmlRelaxNGDefinePtr)
   4964                     xmlHashLookup(ctxt->grammar->refs, def->name);
   4965                 if (prev == NULL) {
   4966                     if (def->name != NULL) {
   4967 		        xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
   4968 				   "Error refs definitions '%s'\n",
   4969 				   def->name, NULL);
   4970                     } else {
   4971 		        xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
   4972 				   "Error refs definitions\n",
   4973 				   NULL, NULL);
   4974                     }
   4975                     def = NULL;
   4976                 } else {
   4977                     def->nextHash = prev->nextHash;
   4978                     prev->nextHash = def;
   4979                 }
   4980             }
   4981         }
   4982     } else if (IS_RELAXNG(node, "data")) {
   4983         def = xmlRelaxNGParseData(ctxt, node);
   4984     } else if (IS_RELAXNG(node, "value")) {
   4985         def = xmlRelaxNGParseValue(ctxt, node);
   4986     } else if (IS_RELAXNG(node, "list")) {
   4987         def = xmlRelaxNGNewDefine(ctxt, node);
   4988         if (def == NULL)
   4989             return (NULL);
   4990         def->type = XML_RELAXNG_LIST;
   4991         if (node->children == NULL) {
   4992             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4993                        "Element %s is empty\n", node->name, NULL);
   4994         } else {
   4995             def->content =
   4996                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
   4997         }
   4998     } else if (IS_RELAXNG(node, "interleave")) {
   4999         def = xmlRelaxNGParseInterleave(ctxt, node);
   5000     } else if (IS_RELAXNG(node, "externalRef")) {
   5001         def = xmlRelaxNGProcessExternalRef(ctxt, node);
   5002     } else if (IS_RELAXNG(node, "notAllowed")) {
   5003         def = xmlRelaxNGNewDefine(ctxt, node);
   5004         if (def == NULL)
   5005             return (NULL);
   5006         def->type = XML_RELAXNG_NOT_ALLOWED;
   5007         if (node->children != NULL) {
   5008             xmlRngPErr(ctxt, node, XML_RNGP_NOTALLOWED_NOT_EMPTY,
   5009                        "xmlRelaxNGParse: notAllowed element is not empty\n",
   5010                        NULL, NULL);
   5011         }
   5012     } else if (IS_RELAXNG(node, "grammar")) {
   5013         xmlRelaxNGGrammarPtr grammar, old;
   5014         xmlRelaxNGGrammarPtr oldparent;
   5015 
   5016 #ifdef DEBUG_GRAMMAR
   5017         xmlGenericError(xmlGenericErrorContext,
   5018                         "Found <grammar> pattern\n");
   5019 #endif
   5020 
   5021         oldparent = ctxt->parentgrammar;
   5022         old = ctxt->grammar;
   5023         ctxt->parentgrammar = old;
   5024         grammar = xmlRelaxNGParseGrammar(ctxt, node->children);
   5025         if (old != NULL) {
   5026             ctxt->grammar = old;
   5027             ctxt->parentgrammar = oldparent;
   5028 #if 0
   5029             if (grammar != NULL) {
   5030                 grammar->next = old->next;
   5031                 old->next = grammar;
   5032             }
   5033 #endif
   5034         }
   5035         if (grammar != NULL)
   5036             def = grammar->start;
   5037         else
   5038             def = NULL;
   5039     } else if (IS_RELAXNG(node, "parentRef")) {
   5040         if (ctxt->parentgrammar == NULL) {
   5041             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_PARENT,
   5042                        "Use of parentRef without a parent grammar\n", NULL,
   5043                        NULL);
   5044             return (NULL);
   5045         }
   5046         def = xmlRelaxNGNewDefine(ctxt, node);
   5047         if (def == NULL)
   5048             return (NULL);
   5049         def->type = XML_RELAXNG_PARENTREF;
   5050         def->name = xmlGetProp(node, BAD_CAST "name");
   5051         if (def->name == NULL) {
   5052             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_NAME,
   5053                        "parentRef has no name\n", NULL, NULL);
   5054         } else {
   5055             xmlRelaxNGNormExtSpace(def->name);
   5056             if (xmlValidateNCName(def->name, 0)) {
   5057                 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NAME_INVALID,
   5058                            "parentRef name '%s' is not an NCName\n",
   5059                            def->name, NULL);
   5060             }
   5061         }
   5062         if (node->children != NULL) {
   5063             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NOT_EMPTY,
   5064                        "parentRef is not empty\n", NULL, NULL);
   5065         }
   5066         if (ctxt->parentgrammar->refs == NULL)
   5067             ctxt->parentgrammar->refs = xmlHashCreate(10);
   5068         if (ctxt->parentgrammar->refs == NULL) {
   5069             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
   5070                        "Could not create references hash\n", NULL, NULL);
   5071             def = NULL;
   5072         } else if (def->name != NULL) {
   5073             int tmp;
   5074 
   5075             tmp =
   5076                 xmlHashAddEntry(ctxt->parentgrammar->refs, def->name, def);
   5077             if (tmp < 0) {
   5078                 xmlRelaxNGDefinePtr prev;
   5079 
   5080                 prev = (xmlRelaxNGDefinePtr)
   5081                     xmlHashLookup(ctxt->parentgrammar->refs, def->name);
   5082                 if (prev == NULL) {
   5083                     xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
   5084                                "Internal error parentRef definitions '%s'\n",
   5085                                def->name, NULL);
   5086                     def = NULL;
   5087                 } else {
   5088                     def->nextHash = prev->nextHash;
   5089                     prev->nextHash = def;
   5090                 }
   5091             }
   5092         }
   5093     } else if (IS_RELAXNG(node, "mixed")) {
   5094         if (node->children == NULL) {
   5095             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, "Mixed is empty\n",
   5096                        NULL, NULL);
   5097             def = NULL;
   5098         } else {
   5099             def = xmlRelaxNGParseInterleave(ctxt, node);
   5100             if (def != NULL) {
   5101                 xmlRelaxNGDefinePtr tmp;
   5102 
   5103                 if ((def->content != NULL) && (def->content->next != NULL)) {
   5104                     tmp = xmlRelaxNGNewDefine(ctxt, node);
   5105                     if (tmp != NULL) {
   5106                         tmp->type = XML_RELAXNG_GROUP;
   5107                         tmp->content = def->content;
   5108                         def->content = tmp;
   5109                     }
   5110                 }
   5111 
   5112                 tmp = xmlRelaxNGNewDefine(ctxt, node);
   5113                 if (tmp == NULL)
   5114                     return (def);
   5115                 tmp->type = XML_RELAXNG_TEXT;
   5116                 tmp->next = def->content;
   5117                 def->content = tmp;
   5118             }
   5119         }
   5120     } else {
   5121         xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_CONSTRUCT,
   5122                    "Unexpected node %s is not a pattern\n", node->name,
   5123                    NULL);
   5124         def = NULL;
   5125     }
   5126     return (def);
   5127 }
   5128 
   5129 /**
   5130  * xmlRelaxNGParseAttribute:
   5131  * @ctxt:  a Relax-NG parser context
   5132  * @node:  the element node
   5133  *
   5134  * parse the content of a RelaxNG attribute node.
   5135  *
   5136  * Returns the definition pointer or NULL in case of error.
   5137  */
   5138 static xmlRelaxNGDefinePtr
   5139 xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   5140 {
   5141     xmlRelaxNGDefinePtr ret, cur;
   5142     xmlNodePtr child;
   5143     int old_flags;
   5144 
   5145     ret = xmlRelaxNGNewDefine(ctxt, node);
   5146     if (ret == NULL)
   5147         return (NULL);
   5148     ret->type = XML_RELAXNG_ATTRIBUTE;
   5149     ret->parent = ctxt->def;
   5150     child = node->children;
   5151     if (child == NULL) {
   5152         xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_EMPTY,
   5153                    "xmlRelaxNGParseattribute: attribute has no children\n",
   5154                    NULL, NULL);
   5155         return (ret);
   5156     }
   5157     old_flags = ctxt->flags;
   5158     ctxt->flags |= XML_RELAXNG_IN_ATTRIBUTE;
   5159     cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
   5160     if (cur != NULL)
   5161         child = child->next;
   5162 
   5163     if (child != NULL) {
   5164         cur = xmlRelaxNGParsePattern(ctxt, child);
   5165         if (cur != NULL) {
   5166             switch (cur->type) {
   5167                 case XML_RELAXNG_EMPTY:
   5168                 case XML_RELAXNG_NOT_ALLOWED:
   5169                 case XML_RELAXNG_TEXT:
   5170                 case XML_RELAXNG_ELEMENT:
   5171                 case XML_RELAXNG_DATATYPE:
   5172                 case XML_RELAXNG_VALUE:
   5173                 case XML_RELAXNG_LIST:
   5174                 case XML_RELAXNG_REF:
   5175                 case XML_RELAXNG_PARENTREF:
   5176                 case XML_RELAXNG_EXTERNALREF:
   5177                 case XML_RELAXNG_DEF:
   5178                 case XML_RELAXNG_ONEORMORE:
   5179                 case XML_RELAXNG_ZEROORMORE:
   5180                 case XML_RELAXNG_OPTIONAL:
   5181                 case XML_RELAXNG_CHOICE:
   5182                 case XML_RELAXNG_GROUP:
   5183                 case XML_RELAXNG_INTERLEAVE:
   5184                 case XML_RELAXNG_ATTRIBUTE:
   5185                     ret->content = cur;
   5186                     cur->parent = ret;
   5187                     break;
   5188                 case XML_RELAXNG_START:
   5189                 case XML_RELAXNG_PARAM:
   5190                 case XML_RELAXNG_EXCEPT:
   5191                     xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CONTENT,
   5192                                "attribute has invalid content\n", NULL,
   5193                                NULL);
   5194                     break;
   5195                 case XML_RELAXNG_NOOP:
   5196                     xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_NOOP,
   5197                                "RNG Internal error, noop found in attribute\n",
   5198                                NULL, NULL);
   5199                     break;
   5200             }
   5201         }
   5202         child = child->next;
   5203     }
   5204     if (child != NULL) {
   5205         xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CHILDREN,
   5206                    "attribute has multiple children\n", NULL, NULL);
   5207     }
   5208     ctxt->flags = old_flags;
   5209     return (ret);
   5210 }
   5211 
   5212 /**
   5213  * xmlRelaxNGParseExceptNameClass:
   5214  * @ctxt:  a Relax-NG parser context
   5215  * @node:  the except node
   5216  * @attr:  1 if within an attribute, 0 if within an element
   5217  *
   5218  * parse the content of a RelaxNG nameClass node.
   5219  *
   5220  * Returns the definition pointer or NULL in case of error.
   5221  */
   5222 static xmlRelaxNGDefinePtr
   5223 xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt,
   5224                                xmlNodePtr node, int attr)
   5225 {
   5226     xmlRelaxNGDefinePtr ret, cur, last = NULL;
   5227     xmlNodePtr child;
   5228 
   5229     if (!IS_RELAXNG(node, "except")) {
   5230         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MISSING,
   5231                    "Expecting an except node\n", NULL, NULL);
   5232         return (NULL);
   5233     }
   5234     if (node->next != NULL) {
   5235         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MULTIPLE,
   5236                    "exceptNameClass allows only a single except node\n",
   5237                    NULL, NULL);
   5238     }
   5239     if (node->children == NULL) {
   5240         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_EMPTY, "except has no content\n",
   5241                    NULL, NULL);
   5242         return (NULL);
   5243     }
   5244 
   5245     ret = xmlRelaxNGNewDefine(ctxt, node);
   5246     if (ret == NULL)
   5247         return (NULL);
   5248     ret->type = XML_RELAXNG_EXCEPT;
   5249     child = node->children;
   5250     while (child != NULL) {
   5251         cur = xmlRelaxNGNewDefine(ctxt, child);
   5252         if (cur == NULL)
   5253             break;
   5254         if (attr)
   5255             cur->type = XML_RELAXNG_ATTRIBUTE;
   5256         else
   5257             cur->type = XML_RELAXNG_ELEMENT;
   5258 
   5259         if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) {
   5260             if (last == NULL) {
   5261                 ret->content = cur;
   5262             } else {
   5263                 last->next = cur;
   5264             }
   5265             last = cur;
   5266         }
   5267         child = child->next;
   5268     }
   5269 
   5270     return (ret);
   5271 }
   5272 
   5273 /**
   5274  * xmlRelaxNGParseNameClass:
   5275  * @ctxt:  a Relax-NG parser context
   5276  * @node:  the nameClass node
   5277  * @def:  the current definition
   5278  *
   5279  * parse the content of a RelaxNG nameClass node.
   5280  *
   5281  * Returns the definition pointer or NULL in case of error.
   5282  */
   5283 static xmlRelaxNGDefinePtr
   5284 xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
   5285                          xmlRelaxNGDefinePtr def)
   5286 {
   5287     xmlRelaxNGDefinePtr ret, tmp;
   5288     xmlChar *val;
   5289 
   5290     ret = def;
   5291     if ((IS_RELAXNG(node, "name")) || (IS_RELAXNG(node, "anyName")) ||
   5292         (IS_RELAXNG(node, "nsName"))) {
   5293         if ((def->type != XML_RELAXNG_ELEMENT) &&
   5294             (def->type != XML_RELAXNG_ATTRIBUTE)) {
   5295             ret = xmlRelaxNGNewDefine(ctxt, node);
   5296             if (ret == NULL)
   5297                 return (NULL);
   5298             ret->parent = def;
   5299             if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE)
   5300                 ret->type = XML_RELAXNG_ATTRIBUTE;
   5301             else
   5302                 ret->type = XML_RELAXNG_ELEMENT;
   5303         }
   5304     }
   5305     if (IS_RELAXNG(node, "name")) {
   5306         val = xmlNodeGetContent(node);
   5307         xmlRelaxNGNormExtSpace(val);
   5308         if (xmlValidateNCName(val, 0)) {
   5309 	    if (node->parent != NULL)
   5310 		xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
   5311 			   "Element %s name '%s' is not an NCName\n",
   5312 			   node->parent->name, val);
   5313 	    else
   5314 		xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
   5315 			   "name '%s' is not an NCName\n",
   5316 			   val, NULL);
   5317         }
   5318         ret->name = val;
   5319         val = xmlGetProp(node, BAD_CAST "ns");
   5320         ret->ns = val;
   5321         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
   5322             (val != NULL) &&
   5323             (xmlStrEqual(val, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
   5324 	    xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
   5325                         "Attribute with namespace '%s' is not allowed\n",
   5326                         val, NULL);
   5327         }
   5328         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
   5329             (val != NULL) &&
   5330             (val[0] == 0) && (xmlStrEqual(ret->name, BAD_CAST "xmlns"))) {
   5331 	    xmlRngPErr(ctxt, node, XML_RNGP_XMLNS_NAME,
   5332                        "Attribute with QName 'xmlns' is not allowed\n",
   5333                        val, NULL);
   5334         }
   5335     } else if (IS_RELAXNG(node, "anyName")) {
   5336         ret->name = NULL;
   5337         ret->ns = NULL;
   5338         if (node->children != NULL) {
   5339             ret->nameClass =
   5340                 xmlRelaxNGParseExceptNameClass(ctxt, node->children,
   5341                                                (def->type ==
   5342                                                 XML_RELAXNG_ATTRIBUTE));
   5343         }
   5344     } else if (IS_RELAXNG(node, "nsName")) {
   5345         ret->name = NULL;
   5346         ret->ns = xmlGetProp(node, BAD_CAST "ns");
   5347         if (ret->ns == NULL) {
   5348             xmlRngPErr(ctxt, node, XML_RNGP_NSNAME_NO_NS,
   5349                        "nsName has no ns attribute\n", NULL, NULL);
   5350         }
   5351         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
   5352             (ret->ns != NULL) &&
   5353             (xmlStrEqual
   5354              (ret->ns, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
   5355             xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
   5356                        "Attribute with namespace '%s' is not allowed\n",
   5357                        ret->ns, NULL);
   5358         }
   5359         if (node->children != NULL) {
   5360             ret->nameClass =
   5361                 xmlRelaxNGParseExceptNameClass(ctxt, node->children,
   5362                                                (def->type ==
   5363                                                 XML_RELAXNG_ATTRIBUTE));
   5364         }
   5365     } else if (IS_RELAXNG(node, "choice")) {
   5366         xmlNodePtr child;
   5367         xmlRelaxNGDefinePtr last = NULL;
   5368 
   5369         if (def->type == XML_RELAXNG_CHOICE) {
   5370             ret = def;
   5371         } else {
   5372             ret = xmlRelaxNGNewDefine(ctxt, node);
   5373             if (ret == NULL)
   5374                 return (NULL);
   5375             ret->parent = def;
   5376             ret->type = XML_RELAXNG_CHOICE;
   5377         }
   5378 
   5379         if (node->children == NULL) {
   5380             xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,
   5381                        "Element choice is empty\n", NULL, NULL);
   5382         } else {
   5383 
   5384             child = node->children;
   5385             while (child != NULL) {
   5386                 tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);
   5387                 if (tmp != NULL) {
   5388                     if (last == NULL) {
   5389                         last = tmp;
   5390                     } else {
   5391                         last->next = tmp;
   5392                         last = tmp;
   5393                     }
   5394                 }
   5395                 child = child->next;
   5396             }
   5397         }
   5398     } else {
   5399         xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT,
   5400                    "expecting name, anyName, nsName or choice : got %s\n",
   5401                    (node == NULL ? (const xmlChar *) "nothing" : node->name),
   5402 		   NULL);
   5403         return (NULL);
   5404     }
   5405     if (ret != def) {
   5406         if (def->nameClass == NULL) {
   5407             def->nameClass = ret;
   5408         } else {
   5409             tmp = def->nameClass;
   5410             while (tmp->next != NULL) {
   5411                 tmp = tmp->next;
   5412             }
   5413             tmp->next = ret;
   5414         }
   5415     }
   5416     return (ret);
   5417 }
   5418 
   5419 /**
   5420  * xmlRelaxNGParseElement:
   5421  * @ctxt:  a Relax-NG parser context
   5422  * @node:  the element node
   5423  *
   5424  * parse the content of a RelaxNG element node.
   5425  *
   5426  * Returns the definition pointer or NULL in case of error.
   5427  */
   5428 static xmlRelaxNGDefinePtr
   5429 xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   5430 {
   5431     xmlRelaxNGDefinePtr ret, cur, last;
   5432     xmlNodePtr child;
   5433     const xmlChar *olddefine;
   5434 
   5435     ret = xmlRelaxNGNewDefine(ctxt, node);
   5436     if (ret == NULL)
   5437         return (NULL);
   5438     ret->type = XML_RELAXNG_ELEMENT;
   5439     ret->parent = ctxt->def;
   5440     child = node->children;
   5441     if (child == NULL) {
   5442         xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_EMPTY,
   5443                    "xmlRelaxNGParseElement: element has no children\n",
   5444                    NULL, NULL);
   5445         return (ret);
   5446     }
   5447     cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
   5448     if (cur != NULL)
   5449         child = child->next;
   5450 
   5451     if (child == NULL) {
   5452         xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NO_CONTENT,
   5453                    "xmlRelaxNGParseElement: element has no content\n",
   5454                    NULL, NULL);
   5455         return (ret);
   5456     }
   5457     olddefine = ctxt->define;
   5458     ctxt->define = NULL;
   5459     last = NULL;
   5460     while (child != NULL) {
   5461         cur = xmlRelaxNGParsePattern(ctxt, child);
   5462         if (cur != NULL) {
   5463             cur->parent = ret;
   5464             switch (cur->type) {
   5465                 case XML_RELAXNG_EMPTY:
   5466                 case XML_RELAXNG_NOT_ALLOWED:
   5467                 case XML_RELAXNG_TEXT:
   5468                 case XML_RELAXNG_ELEMENT:
   5469                 case XML_RELAXNG_DATATYPE:
   5470                 case XML_RELAXNG_VALUE:
   5471                 case XML_RELAXNG_LIST:
   5472                 case XML_RELAXNG_REF:
   5473                 case XML_RELAXNG_PARENTREF:
   5474                 case XML_RELAXNG_EXTERNALREF:
   5475                 case XML_RELAXNG_DEF:
   5476                 case XML_RELAXNG_ZEROORMORE:
   5477                 case XML_RELAXNG_ONEORMORE:
   5478                 case XML_RELAXNG_OPTIONAL:
   5479                 case XML_RELAXNG_CHOICE:
   5480                 case XML_RELAXNG_GROUP:
   5481                 case XML_RELAXNG_INTERLEAVE:
   5482                     if (last == NULL) {
   5483                         ret->content = last = cur;
   5484                     } else {
   5485                         if ((last->type == XML_RELAXNG_ELEMENT) &&
   5486                             (ret->content == last)) {
   5487                             ret->content = xmlRelaxNGNewDefine(ctxt, node);
   5488                             if (ret->content != NULL) {
   5489                                 ret->content->type = XML_RELAXNG_GROUP;
   5490                                 ret->content->content = last;
   5491                             } else {
   5492                                 ret->content = last;
   5493                             }
   5494                         }
   5495                         last->next = cur;
   5496                         last = cur;
   5497                     }
   5498                     break;
   5499                 case XML_RELAXNG_ATTRIBUTE:
   5500                     cur->next = ret->attrs;
   5501                     ret->attrs = cur;
   5502                     break;
   5503                 case XML_RELAXNG_START:
   5504                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
   5505                                "RNG Internal error, start found in element\n",
   5506                                NULL, NULL);
   5507                     break;
   5508                 case XML_RELAXNG_PARAM:
   5509                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
   5510                                "RNG Internal error, param found in element\n",
   5511                                NULL, NULL);
   5512                     break;
   5513                 case XML_RELAXNG_EXCEPT:
   5514                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
   5515                                "RNG Internal error, except found in element\n",
   5516                                NULL, NULL);
   5517                     break;
   5518                 case XML_RELAXNG_NOOP:
   5519                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
   5520                                "RNG Internal error, noop found in element\n",
   5521                                NULL, NULL);
   5522                     break;
   5523             }
   5524         }
   5525         child = child->next;
   5526     }
   5527     ctxt->define = olddefine;
   5528     return (ret);
   5529 }
   5530 
   5531 /**
   5532  * xmlRelaxNGParsePatterns:
   5533  * @ctxt:  a Relax-NG parser context
   5534  * @nodes:  list of nodes
   5535  * @group:  use an implicit <group> for elements
   5536  *
   5537  * parse the content of a RelaxNG start node.
   5538  *
   5539  * Returns the definition pointer or NULL in case of error.
   5540  */
   5541 static xmlRelaxNGDefinePtr
   5542 xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes,
   5543                         int group)
   5544 {
   5545     xmlRelaxNGDefinePtr def = NULL, last = NULL, cur, parent;
   5546 
   5547     parent = ctxt->def;
   5548     while (nodes != NULL) {
   5549         if (IS_RELAXNG(nodes, "element")) {
   5550             cur = xmlRelaxNGParseElement(ctxt, nodes);
   5551             if (def == NULL) {
   5552                 def = last = cur;
   5553             } else {
   5554                 if ((group == 1) && (def->type == XML_RELAXNG_ELEMENT) &&
   5555                     (def == last)) {
   5556                     def = xmlRelaxNGNewDefine(ctxt, nodes);
   5557                     def->type = XML_RELAXNG_GROUP;
   5558                     def->content = last;
   5559                 }
   5560                 last->next = cur;
   5561                 last = cur;
   5562             }
   5563             cur->parent = parent;
   5564         } else {
   5565             cur = xmlRelaxNGParsePattern(ctxt, nodes);
   5566             if (cur != NULL) {
   5567                 if (def == NULL) {
   5568                     def = last = cur;
   5569                 } else {
   5570                     last->next = cur;
   5571                     last = cur;
   5572                 }
   5573             }
   5574         }
   5575         nodes = nodes->next;
   5576     }
   5577     return (def);
   5578 }
   5579 
   5580 /**
   5581  * xmlRelaxNGParseStart:
   5582  * @ctxt:  a Relax-NG parser context
   5583  * @nodes:  start children nodes
   5584  *
   5585  * parse the content of a RelaxNG start node.
   5586  *
   5587  * Returns 0 in case of success, -1 in case of error
   5588  */
   5589 static int
   5590 xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
   5591 {
   5592     int ret = 0;
   5593     xmlRelaxNGDefinePtr def = NULL, last;
   5594 
   5595     if (nodes == NULL) {
   5596         xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY, "start has no children\n",
   5597                    NULL, NULL);
   5598         return (-1);
   5599     }
   5600     if (IS_RELAXNG(nodes, "empty")) {
   5601         def = xmlRelaxNGNewDefine(ctxt, nodes);
   5602         if (def == NULL)
   5603             return (-1);
   5604         def->type = XML_RELAXNG_EMPTY;
   5605         if (nodes->children != NULL) {
   5606             xmlRngPErr(ctxt, nodes, XML_RNGP_EMPTY_CONTENT,
   5607                        "element empty is not empty\n", NULL, NULL);
   5608         }
   5609     } else if (IS_RELAXNG(nodes, "notAllowed")) {
   5610         def = xmlRelaxNGNewDefine(ctxt, nodes);
   5611         if (def == NULL)
   5612             return (-1);
   5613         def->type = XML_RELAXNG_NOT_ALLOWED;
   5614         if (nodes->children != NULL) {
   5615             xmlRngPErr(ctxt, nodes, XML_RNGP_NOTALLOWED_NOT_EMPTY,
   5616                        "element notAllowed is not empty\n", NULL, NULL);
   5617         }
   5618     } else {
   5619         def = xmlRelaxNGParsePatterns(ctxt, nodes, 1);
   5620     }
   5621     if (ctxt->grammar->start != NULL) {
   5622         last = ctxt->grammar->start;
   5623         while (last->next != NULL)
   5624             last = last->next;
   5625         last->next = def;
   5626     } else {
   5627         ctxt->grammar->start = def;
   5628     }
   5629     nodes = nodes->next;
   5630     if (nodes != NULL) {
   5631         xmlRngPErr(ctxt, nodes, XML_RNGP_START_CONTENT,
   5632                    "start more than one children\n", NULL, NULL);
   5633         return (-1);
   5634     }
   5635     return (ret);
   5636 }
   5637 
   5638 /**
   5639  * xmlRelaxNGParseGrammarContent:
   5640  * @ctxt:  a Relax-NG parser context
   5641  * @nodes:  grammar children nodes
   5642  *
   5643  * parse the content of a RelaxNG grammar node.
   5644  *
   5645  * Returns 0 in case of success, -1 in case of error
   5646  */
   5647 static int
   5648 xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
   5649                               xmlNodePtr nodes)
   5650 {
   5651     int ret = 0, tmp;
   5652 
   5653     if (nodes == NULL) {
   5654         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_EMPTY,
   5655                    "grammar has no children\n", NULL, NULL);
   5656         return (-1);
   5657     }
   5658     while (nodes != NULL) {
   5659         if (IS_RELAXNG(nodes, "start")) {
   5660             if (nodes->children == NULL) {
   5661                 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY,
   5662                            "start has no children\n", NULL, NULL);
   5663             } else {
   5664                 tmp = xmlRelaxNGParseStart(ctxt, nodes->children);
   5665                 if (tmp != 0)
   5666                     ret = -1;
   5667             }
   5668         } else if (IS_RELAXNG(nodes, "define")) {
   5669             tmp = xmlRelaxNGParseDefine(ctxt, nodes);
   5670             if (tmp != 0)
   5671                 ret = -1;
   5672         } else if (IS_RELAXNG(nodes, "include")) {
   5673             tmp = xmlRelaxNGParseInclude(ctxt, nodes);
   5674             if (tmp != 0)
   5675                 ret = -1;
   5676         } else {
   5677             xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
   5678                        "grammar has unexpected child %s\n", nodes->name,
   5679                        NULL);
   5680             ret = -1;
   5681         }
   5682         nodes = nodes->next;
   5683     }
   5684     return (ret);
   5685 }
   5686 
   5687 /**
   5688  * xmlRelaxNGCheckReference:
   5689  * @ref:  the ref
   5690  * @ctxt:  a Relax-NG parser context
   5691  * @name:  the name associated to the defines
   5692  *
   5693  * Applies the 4.17. combine attribute rule for all the define
   5694  * element of a given grammar using the same name.
   5695  */
   5696 static void
   5697 xmlRelaxNGCheckReference(void *payload, void *data, const xmlChar * name)
   5698 {
   5699     xmlRelaxNGDefinePtr ref = (xmlRelaxNGDefinePtr) payload;
   5700     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
   5701     xmlRelaxNGGrammarPtr grammar;
   5702     xmlRelaxNGDefinePtr def, cur;
   5703 
   5704     /*
   5705      * Those rules don't apply to imported ref from xmlRelaxNGParseImportRef
   5706      */
   5707     if (ref->dflags & IS_EXTERNAL_REF)
   5708         return;
   5709 
   5710     grammar = ctxt->grammar;
   5711     if (grammar == NULL) {
   5712         xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
   5713                    "Internal error: no grammar in CheckReference %s\n",
   5714                    name, NULL);
   5715         return;
   5716     }
   5717     if (ref->content != NULL) {
   5718         xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
   5719                    "Internal error: reference has content in CheckReference %s\n",
   5720                    name, NULL);
   5721         return;
   5722     }
   5723     if (grammar->defs != NULL) {
   5724         def = xmlHashLookup(grammar->defs, name);
   5725         if (def != NULL) {
   5726             cur = ref;
   5727             while (cur != NULL) {
   5728                 cur->content = def;
   5729                 cur = cur->nextHash;
   5730             }
   5731         } else {
   5732             xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
   5733                        "Reference %s has no matching definition\n", name,
   5734                        NULL);
   5735         }
   5736     } else {
   5737         xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
   5738                    "Reference %s has no matching definition\n", name,
   5739                    NULL);
   5740     }
   5741 }
   5742 
   5743 /**
   5744  * xmlRelaxNGCheckCombine:
   5745  * @define:  the define(s) list
   5746  * @ctxt:  a Relax-NG parser context
   5747  * @name:  the name associated to the defines
   5748  *
   5749  * Applies the 4.17. combine attribute rule for all the define
   5750  * element of a given grammar using the same name.
   5751  */
   5752 static void
   5753 xmlRelaxNGCheckCombine(void *payload, void *data, const xmlChar * name)
   5754 {
   5755     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) payload;
   5756     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
   5757     xmlChar *combine;
   5758     int choiceOrInterleave = -1;
   5759     int missing = 0;
   5760     xmlRelaxNGDefinePtr cur, last, tmp, tmp2;
   5761 
   5762     if (define->nextHash == NULL)
   5763         return;
   5764     cur = define;
   5765     while (cur != NULL) {
   5766         combine = xmlGetProp(cur->node, BAD_CAST "combine");
   5767         if (combine != NULL) {
   5768             if (xmlStrEqual(combine, BAD_CAST "choice")) {
   5769                 if (choiceOrInterleave == -1)
   5770                     choiceOrInterleave = 1;
   5771                 else if (choiceOrInterleave == 0) {
   5772                     xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
   5773                                "Defines for %s use both 'choice' and 'interleave'\n",
   5774                                name, NULL);
   5775                 }
   5776             } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
   5777                 if (choiceOrInterleave == -1)
   5778                     choiceOrInterleave = 0;
   5779                 else if (choiceOrInterleave == 1) {
   5780                     xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
   5781                                "Defines for %s use both 'choice' and 'interleave'\n",
   5782                                name, NULL);
   5783                 }
   5784             } else {
   5785                 xmlRngPErr(ctxt, define->node, XML_RNGP_UNKNOWN_COMBINE,
   5786                            "Defines for %s use unknown combine value '%s''\n",
   5787                            name, combine);
   5788             }
   5789             xmlFree(combine);
   5790         } else {
   5791             if (missing == 0)
   5792                 missing = 1;
   5793             else {
   5794                 xmlRngPErr(ctxt, define->node, XML_RNGP_NEED_COMBINE,
   5795                            "Some defines for %s needs the combine attribute\n",
   5796                            name, NULL);
   5797             }
   5798         }
   5799 
   5800         cur = cur->nextHash;
   5801     }
   5802 #ifdef DEBUG
   5803     xmlGenericError(xmlGenericErrorContext,
   5804                     "xmlRelaxNGCheckCombine(): merging %s defines: %d\n",
   5805                     name, choiceOrInterleave);
   5806 #endif
   5807     if (choiceOrInterleave == -1)
   5808         choiceOrInterleave = 0;
   5809     cur = xmlRelaxNGNewDefine(ctxt, define->node);
   5810     if (cur == NULL)
   5811         return;
   5812     if (choiceOrInterleave == 0)
   5813         cur->type = XML_RELAXNG_INTERLEAVE;
   5814     else
   5815         cur->type = XML_RELAXNG_CHOICE;
   5816     tmp = define;
   5817     last = NULL;
   5818     while (tmp != NULL) {
   5819         if (tmp->content != NULL) {
   5820             if (tmp->content->next != NULL) {
   5821                 /*
   5822                  * we need first to create a wrapper.
   5823                  */
   5824                 tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node);
   5825                 if (tmp2 == NULL)
   5826                     break;
   5827                 tmp2->type = XML_RELAXNG_GROUP;
   5828                 tmp2->content = tmp->content;
   5829             } else {
   5830                 tmp2 = tmp->content;
   5831             }
   5832             if (last == NULL) {
   5833                 cur->content = tmp2;
   5834             } else {
   5835                 last->next = tmp2;
   5836             }
   5837             last = tmp2;
   5838         }
   5839         tmp->content = cur;
   5840         tmp = tmp->nextHash;
   5841     }
   5842     define->content = cur;
   5843     if (choiceOrInterleave == 0) {
   5844         if (ctxt->interleaves == NULL)
   5845             ctxt->interleaves = xmlHashCreate(10);
   5846         if (ctxt->interleaves == NULL) {
   5847             xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
   5848                        "Failed to create interleaves hash table\n", NULL,
   5849                        NULL);
   5850         } else {
   5851             char tmpname[32];
   5852 
   5853             snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
   5854             if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
   5855                 0) {
   5856                 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
   5857                            "Failed to add %s to hash table\n",
   5858 			   (const xmlChar *) tmpname, NULL);
   5859             }
   5860         }
   5861     }
   5862 }
   5863 
   5864 /**
   5865  * xmlRelaxNGCombineStart:
   5866  * @ctxt:  a Relax-NG parser context
   5867  * @grammar:  the grammar
   5868  *
   5869  * Applies the 4.17. combine rule for all the start
   5870  * element of a given grammar.
   5871  */
   5872 static void
   5873 xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt,
   5874                        xmlRelaxNGGrammarPtr grammar)
   5875 {
   5876     xmlRelaxNGDefinePtr starts;
   5877     xmlChar *combine;
   5878     int choiceOrInterleave = -1;
   5879     int missing = 0;
   5880     xmlRelaxNGDefinePtr cur;
   5881 
   5882     starts = grammar->start;
   5883     if ((starts == NULL) || (starts->next == NULL))
   5884         return;
   5885     cur = starts;
   5886     while (cur != NULL) {
   5887         if ((cur->node == NULL) || (cur->node->parent == NULL) ||
   5888             (!xmlStrEqual(cur->node->parent->name, BAD_CAST "start"))) {
   5889             combine = NULL;
   5890             xmlRngPErr(ctxt, cur->node, XML_RNGP_START_MISSING,
   5891                        "Internal error: start element not found\n", NULL,
   5892                        NULL);
   5893         } else {
   5894             combine = xmlGetProp(cur->node->parent, BAD_CAST "combine");
   5895         }
   5896 
   5897         if (combine != NULL) {
   5898             if (xmlStrEqual(combine, BAD_CAST "choice")) {
   5899                 if (choiceOrInterleave == -1)
   5900                     choiceOrInterleave = 1;
   5901                 else if (choiceOrInterleave == 0) {
   5902                     xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
   5903                                "<start> use both 'choice' and 'interleave'\n",
   5904                                NULL, NULL);
   5905                 }
   5906             } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
   5907                 if (choiceOrInterleave == -1)
   5908                     choiceOrInterleave = 0;
   5909                 else if (choiceOrInterleave == 1) {
   5910                     xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
   5911                                "<start> use both 'choice' and 'interleave'\n",
   5912                                NULL, NULL);
   5913                 }
   5914             } else {
   5915                 xmlRngPErr(ctxt, cur->node, XML_RNGP_UNKNOWN_COMBINE,
   5916                            "<start> uses unknown combine value '%s''\n",
   5917                            combine, NULL);
   5918             }
   5919             xmlFree(combine);
   5920         } else {
   5921             if (missing == 0)
   5922                 missing = 1;
   5923             else {
   5924                 xmlRngPErr(ctxt, cur->node, XML_RNGP_NEED_COMBINE,
   5925                            "Some <start> element miss the combine attribute\n",
   5926                            NULL, NULL);
   5927             }
   5928         }
   5929 
   5930         cur = cur->next;
   5931     }
   5932 #ifdef DEBUG
   5933     xmlGenericError(xmlGenericErrorContext,
   5934                     "xmlRelaxNGCombineStart(): merging <start>: %d\n",
   5935                     choiceOrInterleave);
   5936 #endif
   5937     if (choiceOrInterleave == -1)
   5938         choiceOrInterleave = 0;
   5939     cur = xmlRelaxNGNewDefine(ctxt, starts->node);
   5940     if (cur == NULL)
   5941         return;
   5942     if (choiceOrInterleave == 0)
   5943         cur->type = XML_RELAXNG_INTERLEAVE;
   5944     else
   5945         cur->type = XML_RELAXNG_CHOICE;
   5946     cur->content = grammar->start;
   5947     grammar->start = cur;
   5948     if (choiceOrInterleave == 0) {
   5949         if (ctxt->interleaves == NULL)
   5950             ctxt->interleaves = xmlHashCreate(10);
   5951         if (ctxt->interleaves == NULL) {
   5952             xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
   5953                        "Failed to create interleaves hash table\n", NULL,
   5954                        NULL);
   5955         } else {
   5956             char tmpname[32];
   5957 
   5958             snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
   5959             if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
   5960                 0) {
   5961                 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
   5962                            "Failed to add %s to hash table\n",
   5963 			   (const xmlChar *) tmpname, NULL);
   5964             }
   5965         }
   5966     }
   5967 }
   5968 
   5969 /**
   5970  * xmlRelaxNGCheckCycles:
   5971  * @ctxt:  a Relax-NG parser context
   5972  * @nodes:  grammar children nodes
   5973  * @depth:  the counter
   5974  *
   5975  * Check for cycles.
   5976  *
   5977  * Returns 0 if check passed, and -1 in case of error
   5978  */
   5979 static int
   5980 xmlRelaxNGCheckCycles(xmlRelaxNGParserCtxtPtr ctxt,
   5981                       xmlRelaxNGDefinePtr cur, int depth)
   5982 {
   5983     int ret = 0;
   5984 
   5985     while ((ret == 0) && (cur != NULL)) {
   5986         if ((cur->type == XML_RELAXNG_REF) ||
   5987             (cur->type == XML_RELAXNG_PARENTREF)) {
   5988             if (cur->depth == -1) {
   5989                 cur->depth = depth;
   5990                 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
   5991                 cur->depth = -2;
   5992             } else if (depth == cur->depth) {
   5993                 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_CYCLE,
   5994                            "Detected a cycle in %s references\n",
   5995                            cur->name, NULL);
   5996                 return (-1);
   5997             }
   5998         } else if (cur->type == XML_RELAXNG_ELEMENT) {
   5999             ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth + 1);
   6000         } else {
   6001             ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
   6002         }
   6003         cur = cur->next;
   6004     }
   6005     return (ret);
   6006 }
   6007 
   6008 /**
   6009  * xmlRelaxNGTryUnlink:
   6010  * @ctxt:  a Relax-NG parser context
   6011  * @cur:  the definition to unlink
   6012  * @parent:  the parent definition
   6013  * @prev:  the previous sibling definition
   6014  *
   6015  * Try to unlink a definition. If not possble make it a NOOP
   6016  *
   6017  * Returns the new prev definition
   6018  */
   6019 static xmlRelaxNGDefinePtr
   6020 xmlRelaxNGTryUnlink(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
   6021                     xmlRelaxNGDefinePtr cur,
   6022                     xmlRelaxNGDefinePtr parent, xmlRelaxNGDefinePtr prev)
   6023 {
   6024     if (prev != NULL) {
   6025         prev->next = cur->next;
   6026     } else {
   6027         if (parent != NULL) {
   6028             if (parent->content == cur)
   6029                 parent->content = cur->next;
   6030             else if (parent->attrs == cur)
   6031                 parent->attrs = cur->next;
   6032             else if (parent->nameClass == cur)
   6033                 parent->nameClass = cur->next;
   6034         } else {
   6035             cur->type = XML_RELAXNG_NOOP;
   6036             prev = cur;
   6037         }
   6038     }
   6039     return (prev);
   6040 }
   6041 
   6042 /**
   6043  * xmlRelaxNGSimplify:
   6044  * @ctxt:  a Relax-NG parser context
   6045  * @nodes:  grammar children nodes
   6046  *
   6047  * Check for simplification of empty and notAllowed
   6048  */
   6049 static void
   6050 xmlRelaxNGSimplify(xmlRelaxNGParserCtxtPtr ctxt,
   6051                    xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent)
   6052 {
   6053     xmlRelaxNGDefinePtr prev = NULL;
   6054 
   6055     while (cur != NULL) {
   6056         if ((cur->type == XML_RELAXNG_REF) ||
   6057             (cur->type == XML_RELAXNG_PARENTREF)) {
   6058             if (cur->depth != -3) {
   6059                 cur->depth = -3;
   6060                 xmlRelaxNGSimplify(ctxt, cur->content, cur);
   6061             }
   6062         } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
   6063             cur->parent = parent;
   6064             if ((parent != NULL) &&
   6065                 ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
   6066                  (parent->type == XML_RELAXNG_LIST) ||
   6067                  (parent->type == XML_RELAXNG_GROUP) ||
   6068                  (parent->type == XML_RELAXNG_INTERLEAVE) ||
   6069                  (parent->type == XML_RELAXNG_ONEORMORE) ||
   6070                  (parent->type == XML_RELAXNG_ZEROORMORE))) {
   6071                 parent->type = XML_RELAXNG_NOT_ALLOWED;
   6072                 break;
   6073             }
   6074             if ((parent != NULL) && (parent->type == XML_RELAXNG_CHOICE)) {
   6075                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
   6076             } else
   6077                 prev = cur;
   6078         } else if (cur->type == XML_RELAXNG_EMPTY) {
   6079             cur->parent = parent;
   6080             if ((parent != NULL) &&
   6081                 ((parent->type == XML_RELAXNG_ONEORMORE) ||
   6082                  (parent->type == XML_RELAXNG_ZEROORMORE))) {
   6083                 parent->type = XML_RELAXNG_EMPTY;
   6084                 break;
   6085             }
   6086             if ((parent != NULL) &&
   6087                 ((parent->type == XML_RELAXNG_GROUP) ||
   6088                  (parent->type == XML_RELAXNG_INTERLEAVE))) {
   6089                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
   6090             } else
   6091                 prev = cur;
   6092         } else {
   6093             cur->parent = parent;
   6094             if (cur->content != NULL)
   6095                 xmlRelaxNGSimplify(ctxt, cur->content, cur);
   6096             if ((cur->type != XML_RELAXNG_VALUE) && (cur->attrs != NULL))
   6097                 xmlRelaxNGSimplify(ctxt, cur->attrs, cur);
   6098             if (cur->nameClass != NULL)
   6099                 xmlRelaxNGSimplify(ctxt, cur->nameClass, cur);
   6100             /*
   6101              * On Elements, try to move attribute only generating rules on
   6102              * the attrs rules.
   6103              */
   6104             if (cur->type == XML_RELAXNG_ELEMENT) {
   6105                 int attronly;
   6106                 xmlRelaxNGDefinePtr tmp, pre;
   6107 
   6108                 while (cur->content != NULL) {
   6109                     attronly =
   6110                         xmlRelaxNGGenerateAttributes(ctxt, cur->content);
   6111                     if (attronly == 1) {
   6112                         /*
   6113                          * migrate cur->content to attrs
   6114                          */
   6115                         tmp = cur->content;
   6116                         cur->content = tmp->next;
   6117                         tmp->next = cur->attrs;
   6118                         cur->attrs = tmp;
   6119                     } else {
   6120                         /*
   6121                          * cur->content can generate elements or text
   6122                          */
   6123                         break;
   6124                     }
   6125                 }
   6126                 pre = cur->content;
   6127                 while ((pre != NULL) && (pre->next != NULL)) {
   6128                     tmp = pre->next;
   6129                     attronly = xmlRelaxNGGenerateAttributes(ctxt, tmp);
   6130                     if (attronly == 1) {
   6131                         /*
   6132                          * migrate tmp to attrs
   6133                          */
   6134                         pre->next = tmp->next;
   6135                         tmp->next = cur->attrs;
   6136                         cur->attrs = tmp;
   6137                     } else {
   6138                         pre = tmp;
   6139                     }
   6140                 }
   6141             }
   6142             /*
   6143              * This may result in a simplification
   6144              */
   6145             if ((cur->type == XML_RELAXNG_GROUP) ||
   6146                 (cur->type == XML_RELAXNG_INTERLEAVE)) {
   6147                 if (cur->content == NULL)
   6148                     cur->type = XML_RELAXNG_EMPTY;
   6149                 else if (cur->content->next == NULL) {
   6150                     if ((parent == NULL) && (prev == NULL)) {
   6151                         cur->type = XML_RELAXNG_NOOP;
   6152                     } else if (prev == NULL) {
   6153                         parent->content = cur->content;
   6154                         cur->content->next = cur->next;
   6155                         cur = cur->content;
   6156                     } else {
   6157                         cur->content->next = cur->next;
   6158                         prev->next = cur->content;
   6159                         cur = cur->content;
   6160                     }
   6161                 }
   6162             }
   6163             /*
   6164              * the current node may have been transformed back
   6165              */
   6166             if ((cur->type == XML_RELAXNG_EXCEPT) &&
   6167                 (cur->content != NULL) &&
   6168                 (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) {
   6169                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
   6170             } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
   6171                 if ((parent != NULL) &&
   6172                     ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
   6173                      (parent->type == XML_RELAXNG_LIST) ||
   6174                      (parent->type == XML_RELAXNG_GROUP) ||
   6175                      (parent->type == XML_RELAXNG_INTERLEAVE) ||
   6176                      (parent->type == XML_RELAXNG_ONEORMORE) ||
   6177                      (parent->type == XML_RELAXNG_ZEROORMORE))) {
   6178                     parent->type = XML_RELAXNG_NOT_ALLOWED;
   6179                     break;
   6180                 }
   6181                 if ((parent != NULL) &&
   6182                     (parent->type == XML_RELAXNG_CHOICE)) {
   6183                     prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
   6184                 } else
   6185                     prev = cur;
   6186             } else if (cur->type == XML_RELAXNG_EMPTY) {
   6187                 if ((parent != NULL) &&
   6188                     ((parent->type == XML_RELAXNG_ONEORMORE) ||
   6189                      (parent->type == XML_RELAXNG_ZEROORMORE))) {
   6190                     parent->type = XML_RELAXNG_EMPTY;
   6191                     break;
   6192                 }
   6193                 if ((parent != NULL) &&
   6194                     ((parent->type == XML_RELAXNG_GROUP) ||
   6195                      (parent->type == XML_RELAXNG_INTERLEAVE) ||
   6196                      (parent->type == XML_RELAXNG_CHOICE))) {
   6197                     prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
   6198                 } else
   6199                     prev = cur;
   6200             } else {
   6201                 prev = cur;
   6202             }
   6203         }
   6204         cur = cur->next;
   6205     }
   6206 }
   6207 
   6208 /**
   6209  * xmlRelaxNGGroupContentType:
   6210  * @ct1:  the first content type
   6211  * @ct2:  the second content type
   6212  *
   6213  * Try to group 2 content types
   6214  *
   6215  * Returns the content type
   6216  */
   6217 static xmlRelaxNGContentType
   6218 xmlRelaxNGGroupContentType(xmlRelaxNGContentType ct1,
   6219                            xmlRelaxNGContentType ct2)
   6220 {
   6221     if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
   6222         (ct2 == XML_RELAXNG_CONTENT_ERROR))
   6223         return (XML_RELAXNG_CONTENT_ERROR);
   6224     if (ct1 == XML_RELAXNG_CONTENT_EMPTY)
   6225         return (ct2);
   6226     if (ct2 == XML_RELAXNG_CONTENT_EMPTY)
   6227         return (ct1);
   6228     if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) &&
   6229         (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
   6230         return (XML_RELAXNG_CONTENT_COMPLEX);
   6231     return (XML_RELAXNG_CONTENT_ERROR);
   6232 }
   6233 
   6234 /**
   6235  * xmlRelaxNGMaxContentType:
   6236  * @ct1:  the first content type
   6237  * @ct2:  the second content type
   6238  *
   6239  * Compute the max content-type
   6240  *
   6241  * Returns the content type
   6242  */
   6243 static xmlRelaxNGContentType
   6244 xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1,
   6245                          xmlRelaxNGContentType ct2)
   6246 {
   6247     if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
   6248         (ct2 == XML_RELAXNG_CONTENT_ERROR))
   6249         return (XML_RELAXNG_CONTENT_ERROR);
   6250     if ((ct1 == XML_RELAXNG_CONTENT_SIMPLE) ||
   6251         (ct2 == XML_RELAXNG_CONTENT_SIMPLE))
   6252         return (XML_RELAXNG_CONTENT_SIMPLE);
   6253     if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) ||
   6254         (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
   6255         return (XML_RELAXNG_CONTENT_COMPLEX);
   6256     return (XML_RELAXNG_CONTENT_EMPTY);
   6257 }
   6258 
   6259 /**
   6260  * xmlRelaxNGCheckRules:
   6261  * @ctxt:  a Relax-NG parser context
   6262  * @cur:  the current definition
   6263  * @flags:  some accumulated flags
   6264  * @ptype:  the parent type
   6265  *
   6266  * Check for rules in section 7.1 and 7.2
   6267  *
   6268  * Returns the content type of @cur
   6269  */
   6270 static xmlRelaxNGContentType
   6271 xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt,
   6272                      xmlRelaxNGDefinePtr cur, int flags,
   6273                      xmlRelaxNGType ptype)
   6274 {
   6275     int nflags;
   6276     xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY;
   6277 
   6278     while (cur != NULL) {
   6279         ret = XML_RELAXNG_CONTENT_EMPTY;
   6280         if ((cur->type == XML_RELAXNG_REF) ||
   6281             (cur->type == XML_RELAXNG_PARENTREF)) {
   6282            /*
   6283             * This should actually be caught by list//element(ref) at the
   6284             * element boundaries, c.f. Bug #159968 local refs are dropped
   6285             * in step 4.19.
   6286             */
   6287 #if 0
   6288             if (flags & XML_RELAXNG_IN_LIST) {
   6289                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_REF,
   6290                            "Found forbidden pattern list//ref\n", NULL,
   6291                            NULL);
   6292             }
   6293 #endif
   6294             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6295                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_REF,
   6296                            "Found forbidden pattern data/except//ref\n",
   6297                            NULL, NULL);
   6298             }
   6299             if (cur->content == NULL) {
   6300                 if (cur->type == XML_RELAXNG_PARENTREF)
   6301                     xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,
   6302                                "Internal found no define for parent refs\n",
   6303                                NULL, NULL);
   6304                 else
   6305                     xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,
   6306                                "Internal found no define for ref %s\n",
   6307                                (cur->name ? cur->name: BAD_CAST "null"), NULL);
   6308             }
   6309             if (cur->depth > -4) {
   6310                 cur->depth = -4;
   6311                 ret = xmlRelaxNGCheckRules(ctxt, cur->content,
   6312                                            flags, cur->type);
   6313                 cur->depth = ret - 15;
   6314             } else if (cur->depth == -4) {
   6315                 ret = XML_RELAXNG_CONTENT_COMPLEX;
   6316             } else {
   6317                 ret = (xmlRelaxNGContentType) (cur->depth + 15);
   6318             }
   6319         } else if (cur->type == XML_RELAXNG_ELEMENT) {
   6320             /*
   6321              * The 7.3 Attribute derivation rule for groups is plugged there
   6322              */
   6323             xmlRelaxNGCheckGroupAttrs(ctxt, cur);
   6324             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6325                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ELEM,
   6326                            "Found forbidden pattern data/except//element(ref)\n",
   6327                            NULL, NULL);
   6328             }
   6329             if (flags & XML_RELAXNG_IN_LIST) {
   6330                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ELEM,
   6331                            "Found forbidden pattern list//element(ref)\n",
   6332                            NULL, NULL);
   6333             }
   6334             if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
   6335                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
   6336                            "Found forbidden pattern attribute//element(ref)\n",
   6337                            NULL, NULL);
   6338             }
   6339             if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
   6340                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
   6341                            "Found forbidden pattern attribute//element(ref)\n",
   6342                            NULL, NULL);
   6343             }
   6344             /*
   6345              * reset since in the simple form elements are only child
   6346              * of grammar/define
   6347              */
   6348             nflags = 0;
   6349             ret =
   6350                 xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type);
   6351             if (ret != XML_RELAXNG_CONTENT_EMPTY) {
   6352                 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_EMPTY,
   6353                            "Element %s attributes have a content type error\n",
   6354                            cur->name, NULL);
   6355             }
   6356             ret =
   6357                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
   6358                                      cur->type);
   6359             if (ret == XML_RELAXNG_CONTENT_ERROR) {
   6360                 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_ERROR,
   6361                            "Element %s has a content type error\n",
   6362                            cur->name, NULL);
   6363             } else {
   6364                 ret = XML_RELAXNG_CONTENT_COMPLEX;
   6365             }
   6366         } else if (cur->type == XML_RELAXNG_ATTRIBUTE) {
   6367             if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
   6368                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ATTR,
   6369                            "Found forbidden pattern attribute//attribute\n",
   6370                            NULL, NULL);
   6371             }
   6372             if (flags & XML_RELAXNG_IN_LIST) {
   6373                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ATTR,
   6374                            "Found forbidden pattern list//attribute\n",
   6375                            NULL, NULL);
   6376             }
   6377             if (flags & XML_RELAXNG_IN_OOMGROUP) {
   6378                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_GROUP_ATTR,
   6379                            "Found forbidden pattern oneOrMore//group//attribute\n",
   6380                            NULL, NULL);
   6381             }
   6382             if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) {
   6383                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR,
   6384                            "Found forbidden pattern oneOrMore//interleave//attribute\n",
   6385                            NULL, NULL);
   6386             }
   6387             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6388                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ATTR,
   6389                            "Found forbidden pattern data/except//attribute\n",
   6390                            NULL, NULL);
   6391             }
   6392             if (flags & XML_RELAXNG_IN_START) {
   6393                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ATTR,
   6394                            "Found forbidden pattern start//attribute\n",
   6395                            NULL, NULL);
   6396             }
   6397             if ((!(flags & XML_RELAXNG_IN_ONEORMORE))
   6398                 && (cur->name == NULL)) {
   6399                 if (cur->ns == NULL) {
   6400                     xmlRngPErr(ctxt, cur->node, XML_RNGP_ANYNAME_ATTR_ANCESTOR,
   6401                                "Found anyName attribute without oneOrMore ancestor\n",
   6402                                NULL, NULL);
   6403                 } else {
   6404                     xmlRngPErr(ctxt, cur->node, XML_RNGP_NSNAME_ATTR_ANCESTOR,
   6405                                "Found nsName attribute without oneOrMore ancestor\n",
   6406                                NULL, NULL);
   6407                 }
   6408             }
   6409             nflags = flags | XML_RELAXNG_IN_ATTRIBUTE;
   6410             xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
   6411             ret = XML_RELAXNG_CONTENT_EMPTY;
   6412         } else if ((cur->type == XML_RELAXNG_ONEORMORE) ||
   6413                    (cur->type == XML_RELAXNG_ZEROORMORE)) {
   6414             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6415                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ONEMORE,
   6416                            "Found forbidden pattern data/except//oneOrMore\n",
   6417                            NULL, NULL);
   6418             }
   6419             if (flags & XML_RELAXNG_IN_START) {
   6420                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ONEMORE,
   6421                            "Found forbidden pattern start//oneOrMore\n",
   6422                            NULL, NULL);
   6423             }
   6424             nflags = flags | XML_RELAXNG_IN_ONEORMORE;
   6425             ret =
   6426                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
   6427                                      cur->type);
   6428             ret = xmlRelaxNGGroupContentType(ret, ret);
   6429         } else if (cur->type == XML_RELAXNG_LIST) {
   6430             if (flags & XML_RELAXNG_IN_LIST) {
   6431                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_LIST,
   6432                            "Found forbidden pattern list//list\n", NULL,
   6433                            NULL);
   6434             }
   6435             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6436                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_LIST,
   6437                            "Found forbidden pattern data/except//list\n",
   6438                            NULL, NULL);
   6439             }
   6440             if (flags & XML_RELAXNG_IN_START) {
   6441                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_LIST,
   6442                            "Found forbidden pattern start//list\n", NULL,
   6443                            NULL);
   6444             }
   6445             nflags = flags | XML_RELAXNG_IN_LIST;
   6446             ret =
   6447                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
   6448                                      cur->type);
   6449         } else if (cur->type == XML_RELAXNG_GROUP) {
   6450             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6451                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_GROUP,
   6452                            "Found forbidden pattern data/except//group\n",
   6453                            NULL, NULL);
   6454             }
   6455             if (flags & XML_RELAXNG_IN_START) {
   6456                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_GROUP,
   6457                            "Found forbidden pattern start//group\n", NULL,
   6458                            NULL);
   6459             }
   6460             if (flags & XML_RELAXNG_IN_ONEORMORE)
   6461                 nflags = flags | XML_RELAXNG_IN_OOMGROUP;
   6462             else
   6463                 nflags = flags;
   6464             ret =
   6465                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
   6466                                      cur->type);
   6467             /*
   6468              * The 7.3 Attribute derivation rule for groups is plugged there
   6469              */
   6470             xmlRelaxNGCheckGroupAttrs(ctxt, cur);
   6471         } else if (cur->type == XML_RELAXNG_INTERLEAVE) {
   6472             if (flags & XML_RELAXNG_IN_LIST) {
   6473                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_INTERLEAVE,
   6474                            "Found forbidden pattern list//interleave\n",
   6475                            NULL, NULL);
   6476             }
   6477             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6478                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
   6479                            "Found forbidden pattern data/except//interleave\n",
   6480                            NULL, NULL);
   6481             }
   6482             if (flags & XML_RELAXNG_IN_START) {
   6483                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
   6484                            "Found forbidden pattern start//interleave\n",
   6485                            NULL, NULL);
   6486             }
   6487             if (flags & XML_RELAXNG_IN_ONEORMORE)
   6488                 nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE;
   6489             else
   6490                 nflags = flags;
   6491             ret =
   6492                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
   6493                                      cur->type);
   6494         } else if (cur->type == XML_RELAXNG_EXCEPT) {
   6495             if ((cur->parent != NULL) &&
   6496                 (cur->parent->type == XML_RELAXNG_DATATYPE))
   6497                 nflags = flags | XML_RELAXNG_IN_DATAEXCEPT;
   6498             else
   6499                 nflags = flags;
   6500             ret =
   6501                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
   6502                                      cur->type);
   6503         } else if (cur->type == XML_RELAXNG_DATATYPE) {
   6504             if (flags & XML_RELAXNG_IN_START) {
   6505                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_DATA,
   6506                            "Found forbidden pattern start//data\n", NULL,
   6507                            NULL);
   6508             }
   6509             xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
   6510             ret = XML_RELAXNG_CONTENT_SIMPLE;
   6511         } else if (cur->type == XML_RELAXNG_VALUE) {
   6512             if (flags & XML_RELAXNG_IN_START) {
   6513                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_VALUE,
   6514                            "Found forbidden pattern start//value\n", NULL,
   6515                            NULL);
   6516             }
   6517             xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
   6518             ret = XML_RELAXNG_CONTENT_SIMPLE;
   6519         } else if (cur->type == XML_RELAXNG_TEXT) {
   6520             if (flags & XML_RELAXNG_IN_LIST) {
   6521                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_TEXT,
   6522                            "Found forbidden pattern list//text\n", NULL,
   6523                            NULL);
   6524             }
   6525             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6526                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_TEXT,
   6527                            "Found forbidden pattern data/except//text\n",
   6528                            NULL, NULL);
   6529             }
   6530             if (flags & XML_RELAXNG_IN_START) {
   6531                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_TEXT,
   6532                            "Found forbidden pattern start//text\n", NULL,
   6533                            NULL);
   6534             }
   6535             ret = XML_RELAXNG_CONTENT_COMPLEX;
   6536         } else if (cur->type == XML_RELAXNG_EMPTY) {
   6537             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
   6538                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_EMPTY,
   6539                            "Found forbidden pattern data/except//empty\n",
   6540                            NULL, NULL);
   6541             }
   6542             if (flags & XML_RELAXNG_IN_START) {
   6543                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_EMPTY,
   6544                            "Found forbidden pattern start//empty\n", NULL,
   6545                            NULL);
   6546             }
   6547             ret = XML_RELAXNG_CONTENT_EMPTY;
   6548         } else if (cur->type == XML_RELAXNG_CHOICE) {
   6549             xmlRelaxNGCheckChoiceDeterminism(ctxt, cur);
   6550             ret =
   6551                 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
   6552         } else {
   6553             ret =
   6554                 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
   6555         }
   6556         cur = cur->next;
   6557         if (ptype == XML_RELAXNG_GROUP) {
   6558             val = xmlRelaxNGGroupContentType(val, ret);
   6559         } else if (ptype == XML_RELAXNG_INTERLEAVE) {
   6560             /*
   6561              * TODO: scan complain that tmp is never used, seems on purpose
   6562              *       need double-checking
   6563              */
   6564             tmp = xmlRelaxNGGroupContentType(val, ret);
   6565             if (tmp != XML_RELAXNG_CONTENT_ERROR)
   6566                 tmp = xmlRelaxNGMaxContentType(val, ret);
   6567         } else if (ptype == XML_RELAXNG_CHOICE) {
   6568             val = xmlRelaxNGMaxContentType(val, ret);
   6569         } else if (ptype == XML_RELAXNG_LIST) {
   6570             val = XML_RELAXNG_CONTENT_SIMPLE;
   6571         } else if (ptype == XML_RELAXNG_EXCEPT) {
   6572             if (ret == XML_RELAXNG_CONTENT_ERROR)
   6573                 val = XML_RELAXNG_CONTENT_ERROR;
   6574             else
   6575                 val = XML_RELAXNG_CONTENT_SIMPLE;
   6576         } else {
   6577             val = xmlRelaxNGGroupContentType(val, ret);
   6578         }
   6579 
   6580     }
   6581     return (val);
   6582 }
   6583 
   6584 /**
   6585  * xmlRelaxNGParseGrammar:
   6586  * @ctxt:  a Relax-NG parser context
   6587  * @nodes:  grammar children nodes
   6588  *
   6589  * parse a Relax-NG <grammar> node
   6590  *
   6591  * Returns the internal xmlRelaxNGGrammarPtr built or
   6592  *         NULL in case of error
   6593  */
   6594 static xmlRelaxNGGrammarPtr
   6595 xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
   6596 {
   6597     xmlRelaxNGGrammarPtr ret, tmp, old;
   6598 
   6599 #ifdef DEBUG_GRAMMAR
   6600     xmlGenericError(xmlGenericErrorContext, "Parsing a new grammar\n");
   6601 #endif
   6602 
   6603     ret = xmlRelaxNGNewGrammar(ctxt);
   6604     if (ret == NULL)
   6605         return (NULL);
   6606 
   6607     /*
   6608      * Link the new grammar in the tree
   6609      */
   6610     ret->parent = ctxt->grammar;
   6611     if (ctxt->grammar != NULL) {
   6612         tmp = ctxt->grammar->children;
   6613         if (tmp == NULL) {
   6614             ctxt->grammar->children = ret;
   6615         } else {
   6616             while (tmp->next != NULL)
   6617                 tmp = tmp->next;
   6618             tmp->next = ret;
   6619         }
   6620     }
   6621 
   6622     old = ctxt->grammar;
   6623     ctxt->grammar = ret;
   6624     xmlRelaxNGParseGrammarContent(ctxt, nodes);
   6625     ctxt->grammar = ret;
   6626     if (ctxt->grammar == NULL) {
   6627         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
   6628                    "Failed to parse <grammar> content\n", NULL, NULL);
   6629     } else if (ctxt->grammar->start == NULL) {
   6630         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_NO_START,
   6631                    "Element <grammar> has no <start>\n", NULL, NULL);
   6632     }
   6633 
   6634     /*
   6635      * Apply 4.17 merging rules to defines and starts
   6636      */
   6637     xmlRelaxNGCombineStart(ctxt, ret);
   6638     if (ret->defs != NULL) {
   6639         xmlHashScan(ret->defs, xmlRelaxNGCheckCombine, ctxt);
   6640     }
   6641 
   6642     /*
   6643      * link together defines and refs in this grammar
   6644      */
   6645     if (ret->refs != NULL) {
   6646         xmlHashScan(ret->refs, xmlRelaxNGCheckReference, ctxt);
   6647     }
   6648 
   6649 
   6650     /* @@@@ */
   6651 
   6652     ctxt->grammar = old;
   6653     return (ret);
   6654 }
   6655 
   6656 /**
   6657  * xmlRelaxNGParseDocument:
   6658  * @ctxt:  a Relax-NG parser context
   6659  * @node:  the root node of the RelaxNG schema
   6660  *
   6661  * parse a Relax-NG definition resource and build an internal
   6662  * xmlRelaxNG struture which can be used to validate instances.
   6663  *
   6664  * Returns the internal XML RelaxNG structure built or
   6665  *         NULL in case of error
   6666  */
   6667 static xmlRelaxNGPtr
   6668 xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   6669 {
   6670     xmlRelaxNGPtr schema = NULL;
   6671     const xmlChar *olddefine;
   6672     xmlRelaxNGGrammarPtr old;
   6673 
   6674     if ((ctxt == NULL) || (node == NULL))
   6675         return (NULL);
   6676 
   6677     schema = xmlRelaxNGNewRelaxNG(ctxt);
   6678     if (schema == NULL)
   6679         return (NULL);
   6680 
   6681     olddefine = ctxt->define;
   6682     ctxt->define = NULL;
   6683     if (IS_RELAXNG(node, "grammar")) {
   6684         schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children);
   6685         if (schema->topgrammar == NULL) {
   6686             xmlRelaxNGFree(schema);
   6687             return (NULL);
   6688         }
   6689     } else {
   6690         xmlRelaxNGGrammarPtr tmp, ret;
   6691 
   6692         schema->topgrammar = ret = xmlRelaxNGNewGrammar(ctxt);
   6693         if (schema->topgrammar == NULL) {
   6694             xmlRelaxNGFree(schema);
   6695             return (NULL);
   6696         }
   6697         /*
   6698          * Link the new grammar in the tree
   6699          */
   6700         ret->parent = ctxt->grammar;
   6701         if (ctxt->grammar != NULL) {
   6702             tmp = ctxt->grammar->children;
   6703             if (tmp == NULL) {
   6704                 ctxt->grammar->children = ret;
   6705             } else {
   6706                 while (tmp->next != NULL)
   6707                     tmp = tmp->next;
   6708                 tmp->next = ret;
   6709             }
   6710         }
   6711         old = ctxt->grammar;
   6712         ctxt->grammar = ret;
   6713         xmlRelaxNGParseStart(ctxt, node);
   6714         if (old != NULL)
   6715             ctxt->grammar = old;
   6716     }
   6717     ctxt->define = olddefine;
   6718     if (schema->topgrammar->start != NULL) {
   6719         xmlRelaxNGCheckCycles(ctxt, schema->topgrammar->start, 0);
   6720         if ((ctxt->flags & XML_RELAXNG_IN_EXTERNALREF) == 0) {
   6721             xmlRelaxNGSimplify(ctxt, schema->topgrammar->start, NULL);
   6722             while ((schema->topgrammar->start != NULL) &&
   6723                    (schema->topgrammar->start->type == XML_RELAXNG_NOOP) &&
   6724                    (schema->topgrammar->start->next != NULL))
   6725                 schema->topgrammar->start =
   6726                     schema->topgrammar->start->content;
   6727             xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start,
   6728                                  XML_RELAXNG_IN_START, XML_RELAXNG_NOOP);
   6729         }
   6730     }
   6731 #ifdef DEBUG
   6732     if (schema == NULL)
   6733         xmlGenericError(xmlGenericErrorContext,
   6734                         "xmlRelaxNGParseDocument() failed\n");
   6735 #endif
   6736 
   6737     return (schema);
   6738 }
   6739 
   6740 /************************************************************************
   6741  *									*
   6742  *			Reading RelaxNGs				*
   6743  *									*
   6744  ************************************************************************/
   6745 
   6746 /**
   6747  * xmlRelaxNGNewParserCtxt:
   6748  * @URL:  the location of the schema
   6749  *
   6750  * Create an XML RelaxNGs parse context for that file/resource expected
   6751  * to contain an XML RelaxNGs file.
   6752  *
   6753  * Returns the parser context or NULL in case of error
   6754  */
   6755 xmlRelaxNGParserCtxtPtr
   6756 xmlRelaxNGNewParserCtxt(const char *URL)
   6757 {
   6758     xmlRelaxNGParserCtxtPtr ret;
   6759 
   6760     if (URL == NULL)
   6761         return (NULL);
   6762 
   6763     ret =
   6764         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
   6765     if (ret == NULL) {
   6766         xmlRngPErrMemory(NULL, "building parser\n");
   6767         return (NULL);
   6768     }
   6769     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
   6770     ret->URL = xmlStrdup((const xmlChar *) URL);
   6771     ret->error = xmlGenericError;
   6772     ret->userData = xmlGenericErrorContext;
   6773     return (ret);
   6774 }
   6775 
   6776 /**
   6777  * xmlRelaxNGNewMemParserCtxt:
   6778  * @buffer:  a pointer to a char array containing the schemas
   6779  * @size:  the size of the array
   6780  *
   6781  * Create an XML RelaxNGs parse context for that memory buffer expected
   6782  * to contain an XML RelaxNGs file.
   6783  *
   6784  * Returns the parser context or NULL in case of error
   6785  */
   6786 xmlRelaxNGParserCtxtPtr
   6787 xmlRelaxNGNewMemParserCtxt(const char *buffer, int size)
   6788 {
   6789     xmlRelaxNGParserCtxtPtr ret;
   6790 
   6791     if ((buffer == NULL) || (size <= 0))
   6792         return (NULL);
   6793 
   6794     ret =
   6795         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
   6796     if (ret == NULL) {
   6797         xmlRngPErrMemory(NULL, "building parser\n");
   6798         return (NULL);
   6799     }
   6800     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
   6801     ret->buffer = buffer;
   6802     ret->size = size;
   6803     ret->error = xmlGenericError;
   6804     ret->userData = xmlGenericErrorContext;
   6805     return (ret);
   6806 }
   6807 
   6808 /**
   6809  * xmlRelaxNGNewDocParserCtxt:
   6810  * @doc:  a preparsed document tree
   6811  *
   6812  * Create an XML RelaxNGs parser context for that document.
   6813  * Note: since the process of compiling a RelaxNG schemas modifies the
   6814  *       document, the @doc parameter is duplicated internally.
   6815  *
   6816  * Returns the parser context or NULL in case of error
   6817  */
   6818 xmlRelaxNGParserCtxtPtr
   6819 xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc)
   6820 {
   6821     xmlRelaxNGParserCtxtPtr ret;
   6822     xmlDocPtr copy;
   6823 
   6824     if (doc == NULL)
   6825         return (NULL);
   6826     copy = xmlCopyDoc(doc, 1);
   6827     if (copy == NULL)
   6828         return (NULL);
   6829 
   6830     ret =
   6831         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
   6832     if (ret == NULL) {
   6833         xmlRngPErrMemory(NULL, "building parser\n");
   6834         return (NULL);
   6835     }
   6836     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
   6837     ret->document = copy;
   6838     ret->freedoc = 1;
   6839     ret->userData = xmlGenericErrorContext;
   6840     return (ret);
   6841 }
   6842 
   6843 /**
   6844  * xmlRelaxNGFreeParserCtxt:
   6845  * @ctxt:  the schema parser context
   6846  *
   6847  * Free the resources associated to the schema parser context
   6848  */
   6849 void
   6850 xmlRelaxNGFreeParserCtxt(xmlRelaxNGParserCtxtPtr ctxt)
   6851 {
   6852     if (ctxt == NULL)
   6853         return;
   6854     if (ctxt->URL != NULL)
   6855         xmlFree(ctxt->URL);
   6856     if (ctxt->doc != NULL)
   6857         xmlRelaxNGFreeDocument(ctxt->doc);
   6858     if (ctxt->interleaves != NULL)
   6859         xmlHashFree(ctxt->interleaves, NULL);
   6860     if (ctxt->documents != NULL)
   6861         xmlRelaxNGFreeDocumentList(ctxt->documents);
   6862     if (ctxt->includes != NULL)
   6863         xmlRelaxNGFreeIncludeList(ctxt->includes);
   6864     if (ctxt->docTab != NULL)
   6865         xmlFree(ctxt->docTab);
   6866     if (ctxt->incTab != NULL)
   6867         xmlFree(ctxt->incTab);
   6868     if (ctxt->defTab != NULL) {
   6869         int i;
   6870 
   6871         for (i = 0; i < ctxt->defNr; i++)
   6872             xmlRelaxNGFreeDefine(ctxt->defTab[i]);
   6873         xmlFree(ctxt->defTab);
   6874     }
   6875     if ((ctxt->document != NULL) && (ctxt->freedoc))
   6876         xmlFreeDoc(ctxt->document);
   6877     xmlFree(ctxt);
   6878 }
   6879 
   6880 /**
   6881  * xmlRelaxNGNormExtSpace:
   6882  * @value:  a value
   6883  *
   6884  * Removes the leading and ending spaces of the value
   6885  * The string is modified "in situ"
   6886  */
   6887 static void
   6888 xmlRelaxNGNormExtSpace(xmlChar * value)
   6889 {
   6890     xmlChar *start = value;
   6891     xmlChar *cur = value;
   6892 
   6893     if (value == NULL)
   6894         return;
   6895 
   6896     while (IS_BLANK_CH(*cur))
   6897         cur++;
   6898     if (cur == start) {
   6899         do {
   6900             while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
   6901                 cur++;
   6902             if (*cur == 0)
   6903                 return;
   6904             start = cur;
   6905             while (IS_BLANK_CH(*cur))
   6906                 cur++;
   6907             if (*cur == 0) {
   6908                 *start = 0;
   6909                 return;
   6910             }
   6911         } while (1);
   6912     } else {
   6913         do {
   6914             while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
   6915                 *start++ = *cur++;
   6916             if (*cur == 0) {
   6917                 *start = 0;
   6918                 return;
   6919             }
   6920             /* don't try to normalize the inner spaces */
   6921             while (IS_BLANK_CH(*cur))
   6922                 cur++;
   6923             if (*cur == 0) {
   6924                 *start = 0;
   6925                 return;
   6926             }
   6927             *start++ = *cur++;
   6928         } while (1);
   6929     }
   6930 }
   6931 
   6932 /**
   6933  * xmlRelaxNGCleanupAttributes:
   6934  * @ctxt:  a Relax-NG parser context
   6935  * @node:  a Relax-NG node
   6936  *
   6937  * Check all the attributes on the given node
   6938  */
   6939 static void
   6940 xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   6941 {
   6942     xmlAttrPtr cur, next;
   6943 
   6944     cur = node->properties;
   6945     while (cur != NULL) {
   6946         next = cur->next;
   6947         if ((cur->ns == NULL) ||
   6948             (xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
   6949             if (xmlStrEqual(cur->name, BAD_CAST "name")) {
   6950                 if ((!xmlStrEqual(node->name, BAD_CAST "element")) &&
   6951                     (!xmlStrEqual(node->name, BAD_CAST "attribute")) &&
   6952                     (!xmlStrEqual(node->name, BAD_CAST "ref")) &&
   6953                     (!xmlStrEqual(node->name, BAD_CAST "parentRef")) &&
   6954                     (!xmlStrEqual(node->name, BAD_CAST "param")) &&
   6955                     (!xmlStrEqual(node->name, BAD_CAST "define"))) {
   6956                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
   6957                                "Attribute %s is not allowed on %s\n",
   6958                                cur->name, node->name);
   6959                 }
   6960             } else if (xmlStrEqual(cur->name, BAD_CAST "type")) {
   6961                 if ((!xmlStrEqual(node->name, BAD_CAST "value")) &&
   6962                     (!xmlStrEqual(node->name, BAD_CAST "data"))) {
   6963                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
   6964                                "Attribute %s is not allowed on %s\n",
   6965                                cur->name, node->name);
   6966                 }
   6967             } else if (xmlStrEqual(cur->name, BAD_CAST "href")) {
   6968                 if ((!xmlStrEqual(node->name, BAD_CAST "externalRef")) &&
   6969                     (!xmlStrEqual(node->name, BAD_CAST "include"))) {
   6970                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
   6971                                "Attribute %s is not allowed on %s\n",
   6972                                cur->name, node->name);
   6973                 }
   6974             } else if (xmlStrEqual(cur->name, BAD_CAST "combine")) {
   6975                 if ((!xmlStrEqual(node->name, BAD_CAST "start")) &&
   6976                     (!xmlStrEqual(node->name, BAD_CAST "define"))) {
   6977                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
   6978                                "Attribute %s is not allowed on %s\n",
   6979                                cur->name, node->name);
   6980                 }
   6981             } else if (xmlStrEqual(cur->name, BAD_CAST "datatypeLibrary")) {
   6982                 xmlChar *val;
   6983                 xmlURIPtr uri;
   6984 
   6985                 val = xmlNodeListGetString(node->doc, cur->children, 1);
   6986                 if (val != NULL) {
   6987                     if (val[0] != 0) {
   6988                         uri = xmlParseURI((const char *) val);
   6989                         if (uri == NULL) {
   6990                             xmlRngPErr(ctxt, node, XML_RNGP_INVALID_URI,
   6991                                        "Attribute %s contains invalid URI %s\n",
   6992                                        cur->name, val);
   6993                         } else {
   6994                             if (uri->scheme == NULL) {
   6995                                 xmlRngPErr(ctxt, node, XML_RNGP_URI_NOT_ABSOLUTE,
   6996                                            "Attribute %s URI %s is not absolute\n",
   6997                                            cur->name, val);
   6998                             }
   6999                             if (uri->fragment != NULL) {
   7000                                 xmlRngPErr(ctxt, node, XML_RNGP_URI_FRAGMENT,
   7001                                            "Attribute %s URI %s has a fragment ID\n",
   7002                                            cur->name, val);
   7003                             }
   7004                             xmlFreeURI(uri);
   7005                         }
   7006                     }
   7007                     xmlFree(val);
   7008                 }
   7009             } else if (!xmlStrEqual(cur->name, BAD_CAST "ns")) {
   7010                 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_ATTRIBUTE,
   7011                            "Unknown attribute %s on %s\n", cur->name,
   7012                            node->name);
   7013             }
   7014         }
   7015         cur = next;
   7016     }
   7017 }
   7018 
   7019 /**
   7020  * xmlRelaxNGCleanupTree:
   7021  * @ctxt:  a Relax-NG parser context
   7022  * @root:  an xmlNodePtr subtree
   7023  *
   7024  * Cleanup the subtree from unwanted nodes for parsing, resolve
   7025  * Include and externalRef lookups.
   7026  */
   7027 static void
   7028 xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root)
   7029 {
   7030     xmlNodePtr cur, delete;
   7031 
   7032     delete = NULL;
   7033     cur = root;
   7034     while (cur != NULL) {
   7035         if (delete != NULL) {
   7036             xmlUnlinkNode(delete);
   7037             xmlFreeNode(delete);
   7038             delete = NULL;
   7039         }
   7040         if (cur->type == XML_ELEMENT_NODE) {
   7041             /*
   7042              * Simplification 4.1. Annotations
   7043              */
   7044             if ((cur->ns == NULL) ||
   7045                 (!xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
   7046                 if ((cur->parent != NULL) &&
   7047                     (cur->parent->type == XML_ELEMENT_NODE) &&
   7048                     ((xmlStrEqual(cur->parent->name, BAD_CAST "name")) ||
   7049                      (xmlStrEqual(cur->parent->name, BAD_CAST "value")) ||
   7050                      (xmlStrEqual(cur->parent->name, BAD_CAST "param")))) {
   7051                     xmlRngPErr(ctxt, cur, XML_RNGP_FOREIGN_ELEMENT,
   7052                                "element %s doesn't allow foreign elements\n",
   7053                                cur->parent->name, NULL);
   7054                 }
   7055                 delete = cur;
   7056                 goto skip_children;
   7057             } else {
   7058                 xmlRelaxNGCleanupAttributes(ctxt, cur);
   7059                 if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) {
   7060                     xmlChar *href, *ns, *base, *URL;
   7061                     xmlRelaxNGDocumentPtr docu;
   7062                     xmlNodePtr tmp;
   7063 		    xmlURIPtr uri;
   7064 
   7065                     ns = xmlGetProp(cur, BAD_CAST "ns");
   7066                     if (ns == NULL) {
   7067                         tmp = cur->parent;
   7068                         while ((tmp != NULL) &&
   7069                                (tmp->type == XML_ELEMENT_NODE)) {
   7070                             ns = xmlGetProp(tmp, BAD_CAST "ns");
   7071                             if (ns != NULL)
   7072                                 break;
   7073                             tmp = tmp->parent;
   7074                         }
   7075                     }
   7076                     href = xmlGetProp(cur, BAD_CAST "href");
   7077                     if (href == NULL) {
   7078                         xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
   7079                                    "xmlRelaxNGParse: externalRef has no href attribute\n",
   7080                                    NULL, NULL);
   7081                         if (ns != NULL)
   7082                             xmlFree(ns);
   7083                         delete = cur;
   7084                         goto skip_children;
   7085                     }
   7086 		    uri = xmlParseURI((const char *) href);
   7087 		    if (uri == NULL) {
   7088                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
   7089                                    "Incorrect URI for externalRef %s\n",
   7090                                    href, NULL);
   7091                         if (ns != NULL)
   7092                             xmlFree(ns);
   7093                         if (href != NULL)
   7094                             xmlFree(href);
   7095                         delete = cur;
   7096                         goto skip_children;
   7097 		    }
   7098 		    if (uri->fragment != NULL) {
   7099                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
   7100 			       "Fragment forbidden in URI for externalRef %s\n",
   7101                                    href, NULL);
   7102                         if (ns != NULL)
   7103                             xmlFree(ns);
   7104 		        xmlFreeURI(uri);
   7105                         if (href != NULL)
   7106                             xmlFree(href);
   7107                         delete = cur;
   7108                         goto skip_children;
   7109 		    }
   7110 		    xmlFreeURI(uri);
   7111                     base = xmlNodeGetBase(cur->doc, cur);
   7112                     URL = xmlBuildURI(href, base);
   7113                     if (URL == NULL) {
   7114                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
   7115                                    "Failed to compute URL for externalRef %s\n",
   7116                                    href, NULL);
   7117                         if (ns != NULL)
   7118                             xmlFree(ns);
   7119                         if (href != NULL)
   7120                             xmlFree(href);
   7121                         if (base != NULL)
   7122                             xmlFree(base);
   7123                         delete = cur;
   7124                         goto skip_children;
   7125                     }
   7126                     if (href != NULL)
   7127                         xmlFree(href);
   7128                     if (base != NULL)
   7129                         xmlFree(base);
   7130                     docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns);
   7131                     if (docu == NULL) {
   7132                         xmlRngPErr(ctxt, cur, XML_RNGP_EXTERNAL_REF_FAILURE,
   7133                                    "Failed to load externalRef %s\n", URL,
   7134                                    NULL);
   7135                         if (ns != NULL)
   7136                             xmlFree(ns);
   7137                         xmlFree(URL);
   7138                         delete = cur;
   7139                         goto skip_children;
   7140                     }
   7141                     if (ns != NULL)
   7142                         xmlFree(ns);
   7143                     xmlFree(URL);
   7144                     cur->psvi = docu;
   7145                 } else if (xmlStrEqual(cur->name, BAD_CAST "include")) {
   7146                     xmlChar *href, *ns, *base, *URL;
   7147                     xmlRelaxNGIncludePtr incl;
   7148                     xmlNodePtr tmp;
   7149 
   7150                     href = xmlGetProp(cur, BAD_CAST "href");
   7151                     if (href == NULL) {
   7152                         xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
   7153                                    "xmlRelaxNGParse: include has no href attribute\n",
   7154                                    NULL, NULL);
   7155                         delete = cur;
   7156                         goto skip_children;
   7157                     }
   7158                     base = xmlNodeGetBase(cur->doc, cur);
   7159                     URL = xmlBuildURI(href, base);
   7160                     if (URL == NULL) {
   7161                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
   7162                                    "Failed to compute URL for include %s\n",
   7163                                    href, NULL);
   7164                         if (href != NULL)
   7165                             xmlFree(href);
   7166                         if (base != NULL)
   7167                             xmlFree(base);
   7168                         delete = cur;
   7169                         goto skip_children;
   7170                     }
   7171                     if (href != NULL)
   7172                         xmlFree(href);
   7173                     if (base != NULL)
   7174                         xmlFree(base);
   7175                     ns = xmlGetProp(cur, BAD_CAST "ns");
   7176                     if (ns == NULL) {
   7177                         tmp = cur->parent;
   7178                         while ((tmp != NULL) &&
   7179                                (tmp->type == XML_ELEMENT_NODE)) {
   7180                             ns = xmlGetProp(tmp, BAD_CAST "ns");
   7181                             if (ns != NULL)
   7182                                 break;
   7183                             tmp = tmp->parent;
   7184                         }
   7185                     }
   7186                     incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns);
   7187                     if (ns != NULL)
   7188                         xmlFree(ns);
   7189                     if (incl == NULL) {
   7190                         xmlRngPErr(ctxt, cur, XML_RNGP_INCLUDE_FAILURE,
   7191                                    "Failed to load include %s\n", URL,
   7192                                    NULL);
   7193                         xmlFree(URL);
   7194                         delete = cur;
   7195                         goto skip_children;
   7196                     }
   7197                     xmlFree(URL);
   7198                     cur->psvi = incl;
   7199                 } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) ||
   7200                            (xmlStrEqual(cur->name, BAD_CAST "attribute")))
   7201                 {
   7202                     xmlChar *name, *ns;
   7203                     xmlNodePtr text = NULL;
   7204 
   7205                     /*
   7206                      * Simplification 4.8. name attribute of element
   7207                      * and attribute elements
   7208                      */
   7209                     name = xmlGetProp(cur, BAD_CAST "name");
   7210                     if (name != NULL) {
   7211                         if (cur->children == NULL) {
   7212                             text =
   7213                                 xmlNewChild(cur, cur->ns, BAD_CAST "name",
   7214                                             name);
   7215                         } else {
   7216                             xmlNodePtr node;
   7217 
   7218                             node = xmlNewDocNode(cur->doc, cur->ns,
   7219 			                         BAD_CAST "name", NULL);
   7220                             if (node != NULL) {
   7221                                 xmlAddPrevSibling(cur->children, node);
   7222                                 text = xmlNewText(name);
   7223                                 xmlAddChild(node, text);
   7224                                 text = node;
   7225                             }
   7226                         }
   7227                         if (text == NULL) {
   7228                             xmlRngPErr(ctxt, cur, XML_RNGP_CREATE_FAILURE,
   7229                                        "Failed to create a name %s element\n",
   7230                                        name, NULL);
   7231                         }
   7232                         xmlUnsetProp(cur, BAD_CAST "name");
   7233                         xmlFree(name);
   7234                         ns = xmlGetProp(cur, BAD_CAST "ns");
   7235                         if (ns != NULL) {
   7236                             if (text != NULL) {
   7237                                 xmlSetProp(text, BAD_CAST "ns", ns);
   7238                                 /* xmlUnsetProp(cur, BAD_CAST "ns"); */
   7239                             }
   7240                             xmlFree(ns);
   7241                         } else if (xmlStrEqual(cur->name,
   7242                                                BAD_CAST "attribute")) {
   7243                             xmlSetProp(text, BAD_CAST "ns", BAD_CAST "");
   7244                         }
   7245                     }
   7246                 } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) ||
   7247                            (xmlStrEqual(cur->name, BAD_CAST "nsName")) ||
   7248                            (xmlStrEqual(cur->name, BAD_CAST "value"))) {
   7249                     /*
   7250                      * Simplification 4.8. name attribute of element
   7251                      * and attribute elements
   7252                      */
   7253                     if (xmlHasProp(cur, BAD_CAST "ns") == NULL) {
   7254                         xmlNodePtr node;
   7255                         xmlChar *ns = NULL;
   7256 
   7257                         node = cur->parent;
   7258                         while ((node != NULL) &&
   7259                                (node->type == XML_ELEMENT_NODE)) {
   7260                             ns = xmlGetProp(node, BAD_CAST "ns");
   7261                             if (ns != NULL) {
   7262                                 break;
   7263                             }
   7264                             node = node->parent;
   7265                         }
   7266                         if (ns == NULL) {
   7267                             xmlSetProp(cur, BAD_CAST "ns", BAD_CAST "");
   7268                         } else {
   7269                             xmlSetProp(cur, BAD_CAST "ns", ns);
   7270                             xmlFree(ns);
   7271                         }
   7272                     }
   7273                     if (xmlStrEqual(cur->name, BAD_CAST "name")) {
   7274                         xmlChar *name, *local, *prefix;
   7275 
   7276                         /*
   7277                          * Simplification: 4.10. QNames
   7278                          */
   7279                         name = xmlNodeGetContent(cur);
   7280                         if (name != NULL) {
   7281                             local = xmlSplitQName2(name, &prefix);
   7282                             if (local != NULL) {
   7283                                 xmlNsPtr ns;
   7284 
   7285                                 ns = xmlSearchNs(cur->doc, cur, prefix);
   7286                                 if (ns == NULL) {
   7287                                     xmlRngPErr(ctxt, cur,
   7288                                                XML_RNGP_PREFIX_UNDEFINED,
   7289                                                "xmlRelaxNGParse: no namespace for prefix %s\n",
   7290                                                prefix, NULL);
   7291                                 } else {
   7292                                     xmlSetProp(cur, BAD_CAST "ns",
   7293                                                ns->href);
   7294                                     xmlNodeSetContent(cur, local);
   7295                                 }
   7296                                 xmlFree(local);
   7297                                 xmlFree(prefix);
   7298                             }
   7299                             xmlFree(name);
   7300                         }
   7301                     }
   7302                     /*
   7303                      * 4.16
   7304                      */
   7305                     if (xmlStrEqual(cur->name, BAD_CAST "nsName")) {
   7306                         if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
   7307                             xmlRngPErr(ctxt, cur,
   7308                                        XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME,
   7309                                        "Found nsName/except//nsName forbidden construct\n",
   7310                                        NULL, NULL);
   7311                         }
   7312                     }
   7313                 } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) &&
   7314                            (cur != root)) {
   7315                     int oldflags = ctxt->flags;
   7316 
   7317                     /*
   7318                      * 4.16
   7319                      */
   7320                     if ((cur->parent != NULL) &&
   7321                         (xmlStrEqual
   7322                          (cur->parent->name, BAD_CAST "anyName"))) {
   7323                         ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT;
   7324                         xmlRelaxNGCleanupTree(ctxt, cur);
   7325                         ctxt->flags = oldflags;
   7326                         goto skip_children;
   7327                     } else if ((cur->parent != NULL) &&
   7328                                (xmlStrEqual
   7329                                 (cur->parent->name, BAD_CAST "nsName"))) {
   7330                         ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT;
   7331                         xmlRelaxNGCleanupTree(ctxt, cur);
   7332                         ctxt->flags = oldflags;
   7333                         goto skip_children;
   7334                     }
   7335                 } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) {
   7336                     /*
   7337                      * 4.16
   7338                      */
   7339                     if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) {
   7340                         xmlRngPErr(ctxt, cur,
   7341                                    XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME,
   7342                                    "Found anyName/except//anyName forbidden construct\n",
   7343                                    NULL, NULL);
   7344                     } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
   7345                         xmlRngPErr(ctxt, cur,
   7346                                    XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME,
   7347                                    "Found nsName/except//anyName forbidden construct\n",
   7348                                    NULL, NULL);
   7349                     }
   7350                 }
   7351                 /*
   7352                  * This is not an else since "include" is transformed
   7353                  * into a div
   7354                  */
   7355                 if (xmlStrEqual(cur->name, BAD_CAST "div")) {
   7356                     xmlChar *ns;
   7357                     xmlNodePtr child, ins, tmp;
   7358 
   7359                     /*
   7360                      * implements rule 4.11
   7361                      */
   7362 
   7363                     ns = xmlGetProp(cur, BAD_CAST "ns");
   7364 
   7365                     child = cur->children;
   7366                     ins = cur;
   7367                     while (child != NULL) {
   7368                         if (ns != NULL) {
   7369                             if (!xmlHasProp(child, BAD_CAST "ns")) {
   7370                                 xmlSetProp(child, BAD_CAST "ns", ns);
   7371                             }
   7372                         }
   7373                         tmp = child->next;
   7374                         xmlUnlinkNode(child);
   7375                         ins = xmlAddNextSibling(ins, child);
   7376                         child = tmp;
   7377                     }
   7378                     if (ns != NULL)
   7379                         xmlFree(ns);
   7380 		    /*
   7381 		     * Since we are about to delete cur, if its nsDef is non-NULL we
   7382 		     * need to preserve it (it contains the ns definitions for the
   7383 		     * children we just moved).  We'll just stick it on to the end
   7384 		     * of cur->parent's list, since it's never going to be re-serialized
   7385 		     * (bug 143738).
   7386 		     */
   7387 		    if ((cur->nsDef != NULL) && (cur->parent != NULL)) {
   7388 			xmlNsPtr parDef = (xmlNsPtr)&cur->parent->nsDef;
   7389 			while (parDef->next != NULL)
   7390 			    parDef = parDef->next;
   7391 			parDef->next = cur->nsDef;
   7392 			cur->nsDef = NULL;
   7393 		    }
   7394                     delete = cur;
   7395                     goto skip_children;
   7396                 }
   7397             }
   7398         }
   7399         /*
   7400          * Simplification 4.2 whitespaces
   7401          */
   7402         else if ((cur->type == XML_TEXT_NODE) ||
   7403                  (cur->type == XML_CDATA_SECTION_NODE)) {
   7404             if (IS_BLANK_NODE(cur)) {
   7405                 if ((cur->parent != NULL) &&
   7406 		    (cur->parent->type == XML_ELEMENT_NODE)) {
   7407                     if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value"))
   7408                         &&
   7409                         (!xmlStrEqual
   7410                          (cur->parent->name, BAD_CAST "param")))
   7411                         delete = cur;
   7412                 } else {
   7413                     delete = cur;
   7414                     goto skip_children;
   7415                 }
   7416             }
   7417         } else {
   7418             delete = cur;
   7419             goto skip_children;
   7420         }
   7421 
   7422         /*
   7423          * Skip to next node
   7424          */
   7425         if (cur->children != NULL) {
   7426             if ((cur->children->type != XML_ENTITY_DECL) &&
   7427                 (cur->children->type != XML_ENTITY_REF_NODE) &&
   7428                 (cur->children->type != XML_ENTITY_NODE)) {
   7429                 cur = cur->children;
   7430                 continue;
   7431             }
   7432         }
   7433       skip_children:
   7434         if (cur->next != NULL) {
   7435             cur = cur->next;
   7436             continue;
   7437         }
   7438 
   7439         do {
   7440             cur = cur->parent;
   7441             if (cur == NULL)
   7442                 break;
   7443             if (cur == root) {
   7444                 cur = NULL;
   7445                 break;
   7446             }
   7447             if (cur->next != NULL) {
   7448                 cur = cur->next;
   7449                 break;
   7450             }
   7451         } while (cur != NULL);
   7452     }
   7453     if (delete != NULL) {
   7454         xmlUnlinkNode(delete);
   7455         xmlFreeNode(delete);
   7456         delete = NULL;
   7457     }
   7458 }
   7459 
   7460 /**
   7461  * xmlRelaxNGCleanupDoc:
   7462  * @ctxt:  a Relax-NG parser context
   7463  * @doc:  an xmldocPtr document pointer
   7464  *
   7465  * Cleanup the document from unwanted nodes for parsing, resolve
   7466  * Include and externalRef lookups.
   7467  *
   7468  * Returns the cleaned up document or NULL in case of error
   7469  */
   7470 static xmlDocPtr
   7471 xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc)
   7472 {
   7473     xmlNodePtr root;
   7474 
   7475     /*
   7476      * Extract the root
   7477      */
   7478     root = xmlDocGetRootElement(doc);
   7479     if (root == NULL) {
   7480         xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
   7481                    ctxt->URL, NULL);
   7482         return (NULL);
   7483     }
   7484     xmlRelaxNGCleanupTree(ctxt, root);
   7485     return (doc);
   7486 }
   7487 
   7488 /**
   7489  * xmlRelaxNGParse:
   7490  * @ctxt:  a Relax-NG parser context
   7491  *
   7492  * parse a schema definition resource and build an internal
   7493  * XML Shema struture which can be used to validate instances.
   7494  *
   7495  * Returns the internal XML RelaxNG structure built from the resource or
   7496  *         NULL in case of error
   7497  */
   7498 xmlRelaxNGPtr
   7499 xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
   7500 {
   7501     xmlRelaxNGPtr ret = NULL;
   7502     xmlDocPtr doc;
   7503     xmlNodePtr root;
   7504 
   7505     xmlRelaxNGInitTypes();
   7506 
   7507     if (ctxt == NULL)
   7508         return (NULL);
   7509 
   7510     /*
   7511      * First step is to parse the input document into an DOM/Infoset
   7512      */
   7513     if (ctxt->URL != NULL) {
   7514         doc = xmlReadFile((const char *) ctxt->URL,NULL,0);
   7515         if (doc == NULL) {
   7516             xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
   7517                        "xmlRelaxNGParse: could not load %s\n", ctxt->URL,
   7518                        NULL);
   7519             return (NULL);
   7520         }
   7521     } else if (ctxt->buffer != NULL) {
   7522         doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0);
   7523         if (doc == NULL) {
   7524             xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
   7525                        "xmlRelaxNGParse: could not parse schemas\n", NULL,
   7526                        NULL);
   7527             return (NULL);
   7528         }
   7529         doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
   7530         ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
   7531     } else if (ctxt->document != NULL) {
   7532         doc = ctxt->document;
   7533     } else {
   7534         xmlRngPErr(ctxt, NULL, XML_RNGP_EMPTY,
   7535                    "xmlRelaxNGParse: nothing to parse\n", NULL, NULL);
   7536         return (NULL);
   7537     }
   7538     ctxt->document = doc;
   7539 
   7540     /*
   7541      * Some preprocessing of the document content
   7542      */
   7543     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
   7544     if (doc == NULL) {
   7545         xmlFreeDoc(ctxt->document);
   7546         ctxt->document = NULL;
   7547         return (NULL);
   7548     }
   7549 
   7550     /*
   7551      * Then do the parsing for good
   7552      */
   7553     root = xmlDocGetRootElement(doc);
   7554     if (root == NULL) {
   7555         xmlRngPErr(ctxt, (xmlNodePtr) doc,
   7556 	           XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
   7557                    (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL);
   7558 
   7559         xmlFreeDoc(ctxt->document);
   7560         ctxt->document = NULL;
   7561         return (NULL);
   7562     }
   7563     ret = xmlRelaxNGParseDocument(ctxt, root);
   7564     if (ret == NULL) {
   7565         xmlFreeDoc(ctxt->document);
   7566         ctxt->document = NULL;
   7567         return (NULL);
   7568     }
   7569 
   7570     /*
   7571      * Check the ref/defines links
   7572      */
   7573     /*
   7574      * try to preprocess interleaves
   7575      */
   7576     if (ctxt->interleaves != NULL) {
   7577         xmlHashScan(ctxt->interleaves, xmlRelaxNGComputeInterleaves, ctxt);
   7578     }
   7579 
   7580     /*
   7581      * if there was a parsing error return NULL
   7582      */
   7583     if (ctxt->nbErrors > 0) {
   7584         xmlRelaxNGFree(ret);
   7585         ctxt->document = NULL;
   7586         xmlFreeDoc(doc);
   7587         return (NULL);
   7588     }
   7589 
   7590     /*
   7591      * try to compile (parts of) the schemas
   7592      */
   7593     if ((ret->topgrammar != NULL) && (ret->topgrammar->start != NULL)) {
   7594         if (ret->topgrammar->start->type != XML_RELAXNG_START) {
   7595             xmlRelaxNGDefinePtr def;
   7596 
   7597             def = xmlRelaxNGNewDefine(ctxt, NULL);
   7598             if (def != NULL) {
   7599                 def->type = XML_RELAXNG_START;
   7600                 def->content = ret->topgrammar->start;
   7601                 ret->topgrammar->start = def;
   7602             }
   7603         }
   7604         xmlRelaxNGTryCompile(ctxt, ret->topgrammar->start);
   7605     }
   7606 
   7607     /*
   7608      * Transfer the pointer for cleanup at the schema level.
   7609      */
   7610     ret->doc = doc;
   7611     ctxt->document = NULL;
   7612     ret->documents = ctxt->documents;
   7613     ctxt->documents = NULL;
   7614 
   7615     ret->includes = ctxt->includes;
   7616     ctxt->includes = NULL;
   7617     ret->defNr = ctxt->defNr;
   7618     ret->defTab = ctxt->defTab;
   7619     ctxt->defTab = NULL;
   7620     if (ctxt->idref == 1)
   7621         ret->idref = 1;
   7622 
   7623     return (ret);
   7624 }
   7625 
   7626 /**
   7627  * xmlRelaxNGSetParserErrors:
   7628  * @ctxt:  a Relax-NG validation context
   7629  * @err:  the error callback
   7630  * @warn:  the warning callback
   7631  * @ctx:  contextual data for the callbacks
   7632  *
   7633  * Set the callback functions used to handle errors for a validation context
   7634  */
   7635 void
   7636 xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
   7637                           xmlRelaxNGValidityErrorFunc err,
   7638                           xmlRelaxNGValidityWarningFunc warn, void *ctx)
   7639 {
   7640     if (ctxt == NULL)
   7641         return;
   7642     ctxt->error = err;
   7643     ctxt->warning = warn;
   7644     ctxt->serror = NULL;
   7645     ctxt->userData = ctx;
   7646 }
   7647 
   7648 /**
   7649  * xmlRelaxNGGetParserErrors:
   7650  * @ctxt:  a Relax-NG validation context
   7651  * @err:  the error callback result
   7652  * @warn:  the warning callback result
   7653  * @ctx:  contextual data for the callbacks result
   7654  *
   7655  * Get the callback information used to handle errors for a validation context
   7656  *
   7657  * Returns -1 in case of failure, 0 otherwise.
   7658  */
   7659 int
   7660 xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
   7661                           xmlRelaxNGValidityErrorFunc * err,
   7662                           xmlRelaxNGValidityWarningFunc * warn, void **ctx)
   7663 {
   7664     if (ctxt == NULL)
   7665         return (-1);
   7666     if (err != NULL)
   7667         *err = ctxt->error;
   7668     if (warn != NULL)
   7669         *warn = ctxt->warning;
   7670     if (ctx != NULL)
   7671         *ctx = ctxt->userData;
   7672     return (0);
   7673 }
   7674 
   7675 /**
   7676  * xmlRelaxNGSetParserStructuredErrors:
   7677  * @ctxt:  a Relax-NG parser context
   7678  * @serror:  the error callback
   7679  * @ctx:  contextual data for the callbacks
   7680  *
   7681  * Set the callback functions used to handle errors for a parsing context
   7682  */
   7683 void
   7684 xmlRelaxNGSetParserStructuredErrors(xmlRelaxNGParserCtxtPtr ctxt,
   7685 				    xmlStructuredErrorFunc serror,
   7686 				    void *ctx)
   7687 {
   7688     if (ctxt == NULL)
   7689         return;
   7690     ctxt->serror = serror;
   7691     ctxt->error = NULL;
   7692     ctxt->warning = NULL;
   7693     ctxt->userData = ctx;
   7694 }
   7695 
   7696 #ifdef LIBXML_OUTPUT_ENABLED
   7697 
   7698 /************************************************************************
   7699  *									*
   7700  *			Dump back a compiled form			*
   7701  *									*
   7702  ************************************************************************/
   7703 static void xmlRelaxNGDumpDefine(FILE * output,
   7704                                  xmlRelaxNGDefinePtr define);
   7705 
   7706 /**
   7707  * xmlRelaxNGDumpDefines:
   7708  * @output:  the file output
   7709  * @defines:  a list of define structures
   7710  *
   7711  * Dump a RelaxNG structure back
   7712  */
   7713 static void
   7714 xmlRelaxNGDumpDefines(FILE * output, xmlRelaxNGDefinePtr defines)
   7715 {
   7716     while (defines != NULL) {
   7717         xmlRelaxNGDumpDefine(output, defines);
   7718         defines = defines->next;
   7719     }
   7720 }
   7721 
   7722 /**
   7723  * xmlRelaxNGDumpDefine:
   7724  * @output:  the file output
   7725  * @define:  a define structure
   7726  *
   7727  * Dump a RelaxNG structure back
   7728  */
   7729 static void
   7730 xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define)
   7731 {
   7732     if (define == NULL)
   7733         return;
   7734     switch (define->type) {
   7735         case XML_RELAXNG_EMPTY:
   7736             fprintf(output, "<empty/>\n");
   7737             break;
   7738         case XML_RELAXNG_NOT_ALLOWED:
   7739             fprintf(output, "<notAllowed/>\n");
   7740             break;
   7741         case XML_RELAXNG_TEXT:
   7742             fprintf(output, "<text/>\n");
   7743             break;
   7744         case XML_RELAXNG_ELEMENT:
   7745             fprintf(output, "<element>\n");
   7746             if (define->name != NULL) {
   7747                 fprintf(output, "<name");
   7748                 if (define->ns != NULL)
   7749                     fprintf(output, " ns=\"%s\"", define->ns);
   7750                 fprintf(output, ">%s</name>\n", define->name);
   7751             }
   7752             xmlRelaxNGDumpDefines(output, define->attrs);
   7753             xmlRelaxNGDumpDefines(output, define->content);
   7754             fprintf(output, "</element>\n");
   7755             break;
   7756         case XML_RELAXNG_LIST:
   7757             fprintf(output, "<list>\n");
   7758             xmlRelaxNGDumpDefines(output, define->content);
   7759             fprintf(output, "</list>\n");
   7760             break;
   7761         case XML_RELAXNG_ONEORMORE:
   7762             fprintf(output, "<oneOrMore>\n");
   7763             xmlRelaxNGDumpDefines(output, define->content);
   7764             fprintf(output, "</oneOrMore>\n");
   7765             break;
   7766         case XML_RELAXNG_ZEROORMORE:
   7767             fprintf(output, "<zeroOrMore>\n");
   7768             xmlRelaxNGDumpDefines(output, define->content);
   7769             fprintf(output, "</zeroOrMore>\n");
   7770             break;
   7771         case XML_RELAXNG_CHOICE:
   7772             fprintf(output, "<choice>\n");
   7773             xmlRelaxNGDumpDefines(output, define->content);
   7774             fprintf(output, "</choice>\n");
   7775             break;
   7776         case XML_RELAXNG_GROUP:
   7777             fprintf(output, "<group>\n");
   7778             xmlRelaxNGDumpDefines(output, define->content);
   7779             fprintf(output, "</group>\n");
   7780             break;
   7781         case XML_RELAXNG_INTERLEAVE:
   7782             fprintf(output, "<interleave>\n");
   7783             xmlRelaxNGDumpDefines(output, define->content);
   7784             fprintf(output, "</interleave>\n");
   7785             break;
   7786         case XML_RELAXNG_OPTIONAL:
   7787             fprintf(output, "<optional>\n");
   7788             xmlRelaxNGDumpDefines(output, define->content);
   7789             fprintf(output, "</optional>\n");
   7790             break;
   7791         case XML_RELAXNG_ATTRIBUTE:
   7792             fprintf(output, "<attribute>\n");
   7793             xmlRelaxNGDumpDefines(output, define->content);
   7794             fprintf(output, "</attribute>\n");
   7795             break;
   7796         case XML_RELAXNG_DEF:
   7797             fprintf(output, "<define");
   7798             if (define->name != NULL)
   7799                 fprintf(output, " name=\"%s\"", define->name);
   7800             fprintf(output, ">\n");
   7801             xmlRelaxNGDumpDefines(output, define->content);
   7802             fprintf(output, "</define>\n");
   7803             break;
   7804         case XML_RELAXNG_REF:
   7805             fprintf(output, "<ref");
   7806             if (define->name != NULL)
   7807                 fprintf(output, " name=\"%s\"", define->name);
   7808             fprintf(output, ">\n");
   7809             xmlRelaxNGDumpDefines(output, define->content);
   7810             fprintf(output, "</ref>\n");
   7811             break;
   7812         case XML_RELAXNG_PARENTREF:
   7813             fprintf(output, "<parentRef");
   7814             if (define->name != NULL)
   7815                 fprintf(output, " name=\"%s\"", define->name);
   7816             fprintf(output, ">\n");
   7817             xmlRelaxNGDumpDefines(output, define->content);
   7818             fprintf(output, "</parentRef>\n");
   7819             break;
   7820         case XML_RELAXNG_EXTERNALREF:
   7821             fprintf(output, "<externalRef>");
   7822             xmlRelaxNGDumpDefines(output, define->content);
   7823             fprintf(output, "</externalRef>\n");
   7824             break;
   7825         case XML_RELAXNG_DATATYPE:
   7826         case XML_RELAXNG_VALUE:
   7827             TODO break;
   7828         case XML_RELAXNG_START:
   7829         case XML_RELAXNG_EXCEPT:
   7830         case XML_RELAXNG_PARAM:
   7831             TODO break;
   7832         case XML_RELAXNG_NOOP:
   7833             xmlRelaxNGDumpDefines(output, define->content);
   7834             break;
   7835     }
   7836 }
   7837 
   7838 /**
   7839  * xmlRelaxNGDumpGrammar:
   7840  * @output:  the file output
   7841  * @grammar:  a grammar structure
   7842  * @top:  is this a top grammar
   7843  *
   7844  * Dump a RelaxNG structure back
   7845  */
   7846 static void
   7847 xmlRelaxNGDumpGrammar(FILE * output, xmlRelaxNGGrammarPtr grammar, int top)
   7848 {
   7849     if (grammar == NULL)
   7850         return;
   7851 
   7852     fprintf(output, "<grammar");
   7853     if (top)
   7854         fprintf(output, " xmlns=\"http://relaxng.org/ns/structure/1.0\"");
   7855     switch (grammar->combine) {
   7856         case XML_RELAXNG_COMBINE_UNDEFINED:
   7857             break;
   7858         case XML_RELAXNG_COMBINE_CHOICE:
   7859             fprintf(output, " combine=\"choice\"");
   7860             break;
   7861         case XML_RELAXNG_COMBINE_INTERLEAVE:
   7862             fprintf(output, " combine=\"interleave\"");
   7863             break;
   7864         default:
   7865             fprintf(output, " <!-- invalid combine value -->");
   7866     }
   7867     fprintf(output, ">\n");
   7868     if (grammar->start == NULL) {
   7869         fprintf(output, " <!-- grammar had no start -->");
   7870     } else {
   7871         fprintf(output, "<start>\n");
   7872         xmlRelaxNGDumpDefine(output, grammar->start);
   7873         fprintf(output, "</start>\n");
   7874     }
   7875     /* TODO ? Dump the defines ? */
   7876     fprintf(output, "</grammar>\n");
   7877 }
   7878 
   7879 /**
   7880  * xmlRelaxNGDump:
   7881  * @output:  the file output
   7882  * @schema:  a schema structure
   7883  *
   7884  * Dump a RelaxNG structure back
   7885  */
   7886 void
   7887 xmlRelaxNGDump(FILE * output, xmlRelaxNGPtr schema)
   7888 {
   7889     if (output == NULL)
   7890         return;
   7891     if (schema == NULL) {
   7892         fprintf(output, "RelaxNG empty or failed to compile\n");
   7893         return;
   7894     }
   7895     fprintf(output, "RelaxNG: ");
   7896     if (schema->doc == NULL) {
   7897         fprintf(output, "no document\n");
   7898     } else if (schema->doc->URL != NULL) {
   7899         fprintf(output, "%s\n", schema->doc->URL);
   7900     } else {
   7901         fprintf(output, "\n");
   7902     }
   7903     if (schema->topgrammar == NULL) {
   7904         fprintf(output, "RelaxNG has no top grammar\n");
   7905         return;
   7906     }
   7907     xmlRelaxNGDumpGrammar(output, schema->topgrammar, 1);
   7908 }
   7909 
   7910 /**
   7911  * xmlRelaxNGDumpTree:
   7912  * @output:  the file output
   7913  * @schema:  a schema structure
   7914  *
   7915  * Dump the transformed RelaxNG tree.
   7916  */
   7917 void
   7918 xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema)
   7919 {
   7920     if (output == NULL)
   7921         return;
   7922     if (schema == NULL) {
   7923         fprintf(output, "RelaxNG empty or failed to compile\n");
   7924         return;
   7925     }
   7926     if (schema->doc == NULL) {
   7927         fprintf(output, "no document\n");
   7928     } else {
   7929         xmlDocDump(output, schema->doc);
   7930     }
   7931 }
   7932 #endif /* LIBXML_OUTPUT_ENABLED */
   7933 
   7934 /************************************************************************
   7935  *									*
   7936  *		Validation of compiled content				*
   7937  *									*
   7938  ************************************************************************/
   7939 static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
   7940                                         xmlRelaxNGDefinePtr define);
   7941 
   7942 /**
   7943  * xmlRelaxNGValidateCompiledCallback:
   7944  * @exec:  the regular expression instance
   7945  * @token:  the token which matched
   7946  * @transdata:  callback data, the define for the subelement if available
   7947  @ @inputdata:  callback data, the Relax NG validation context
   7948  *
   7949  * Handle the callback and if needed validate the element children.
   7950  */
   7951 static void
   7952 xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
   7953                                    const xmlChar * token,
   7954                                    void *transdata, void *inputdata)
   7955 {
   7956     xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
   7957     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
   7958     int ret;
   7959 
   7960 #ifdef DEBUG_COMPILE
   7961     xmlGenericError(xmlGenericErrorContext,
   7962                     "Compiled callback for: '%s'\n", token);
   7963 #endif
   7964     if (ctxt == NULL) {
   7965         fprintf(stderr, "callback on %s missing context\n", token);
   7966         return;
   7967     }
   7968     if (define == NULL) {
   7969         if (token[0] == '#')
   7970             return;
   7971         fprintf(stderr, "callback on %s missing define\n", token);
   7972         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
   7973             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
   7974         return;
   7975     }
   7976     if ((ctxt == NULL) || (define == NULL)) {
   7977         fprintf(stderr, "callback on %s missing info\n", token);
   7978         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
   7979             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
   7980         return;
   7981     } else if (define->type != XML_RELAXNG_ELEMENT) {
   7982         fprintf(stderr, "callback on %s define is not element\n", token);
   7983         if (ctxt->errNo == XML_RELAXNG_OK)
   7984             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
   7985         return;
   7986     }
   7987     ret = xmlRelaxNGValidateDefinition(ctxt, define);
   7988     if (ret != 0)
   7989         ctxt->perr = ret;
   7990 }
   7991 
   7992 /**
   7993  * xmlRelaxNGValidateCompiledContent:
   7994  * @ctxt:  the RelaxNG validation context
   7995  * @regexp:  the regular expression as compiled
   7996  * @content:  list of children to test against the regexp
   7997  *
   7998  * Validate the content model of an element or start using the regexp
   7999  *
   8000  * Returns 0 in case of success, -1 in case of error.
   8001  */
   8002 static int
   8003 xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt,
   8004                                   xmlRegexpPtr regexp, xmlNodePtr content)
   8005 {
   8006     xmlRegExecCtxtPtr exec;
   8007     xmlNodePtr cur;
   8008     int ret = 0;
   8009     int oldperr;
   8010 
   8011     if ((ctxt == NULL) || (regexp == NULL))
   8012         return (-1);
   8013     oldperr = ctxt->perr;
   8014     exec = xmlRegNewExecCtxt(regexp,
   8015                              xmlRelaxNGValidateCompiledCallback, ctxt);
   8016     ctxt->perr = 0;
   8017     cur = content;
   8018     while (cur != NULL) {
   8019         ctxt->state->seq = cur;
   8020         switch (cur->type) {
   8021             case XML_TEXT_NODE:
   8022             case XML_CDATA_SECTION_NODE:
   8023                 if (xmlIsBlankNode(cur))
   8024                     break;
   8025                 ret = xmlRegExecPushString(exec, BAD_CAST "#text", ctxt);
   8026                 if (ret < 0) {
   8027                     VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG,
   8028                                cur->parent->name);
   8029                 }
   8030                 break;
   8031             case XML_ELEMENT_NODE:
   8032                 if (cur->ns != NULL) {
   8033                     ret = xmlRegExecPushString2(exec, cur->name,
   8034                                                 cur->ns->href, ctxt);
   8035                 } else {
   8036                     ret = xmlRegExecPushString(exec, cur->name, ctxt);
   8037                 }
   8038                 if (ret < 0) {
   8039                     VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, cur->name);
   8040                 }
   8041                 break;
   8042             default:
   8043                 break;
   8044         }
   8045         if (ret < 0)
   8046             break;
   8047         /*
   8048          * Switch to next element
   8049          */
   8050         cur = cur->next;
   8051     }
   8052     ret = xmlRegExecPushString(exec, NULL, NULL);
   8053     if (ret == 1) {
   8054         ret = 0;
   8055         ctxt->state->seq = NULL;
   8056     } else if (ret == 0) {
   8057         /*
   8058          * TODO: get some of the names needed to exit the current state of exec
   8059          */
   8060         VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
   8061         ret = -1;
   8062         if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
   8063             xmlRelaxNGDumpValidError(ctxt);
   8064     } else {
   8065         ret = -1;
   8066     }
   8067     xmlRegFreeExecCtxt(exec);
   8068     /*
   8069      * There might be content model errors outside of the pure
   8070      * regexp validation, e.g. for attribute values.
   8071      */
   8072     if ((ret == 0) && (ctxt->perr != 0)) {
   8073         ret = ctxt->perr;
   8074     }
   8075     ctxt->perr = oldperr;
   8076     return (ret);
   8077 }
   8078 
   8079 /************************************************************************
   8080  *									*
   8081  *		Progressive validation of when possible			*
   8082  *									*
   8083  ************************************************************************/
   8084 static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
   8085                                            xmlRelaxNGDefinePtr defines);
   8086 static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt,
   8087                                         int dolog);
   8088 static void xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt);
   8089 
   8090 /**
   8091  * xmlRelaxNGElemPush:
   8092  * @ctxt:  the validation context
   8093  * @exec:  the regexp runtime for the new content model
   8094  *
   8095  * Push a new regexp for the current node content model on the stack
   8096  *
   8097  * Returns 0 in case of success and -1 in case of error.
   8098  */
   8099 static int
   8100 xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec)
   8101 {
   8102     if (ctxt->elemTab == NULL) {
   8103         ctxt->elemMax = 10;
   8104         ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlMalloc(ctxt->elemMax *
   8105                                                         sizeof
   8106                                                         (xmlRegExecCtxtPtr));
   8107         if (ctxt->elemTab == NULL) {
   8108             xmlRngVErrMemory(ctxt, "validating\n");
   8109             return (-1);
   8110         }
   8111     }
   8112     if (ctxt->elemNr >= ctxt->elemMax) {
   8113         ctxt->elemMax *= 2;
   8114         ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlRealloc(ctxt->elemTab,
   8115                                                          ctxt->elemMax *
   8116                                                          sizeof
   8117                                                          (xmlRegExecCtxtPtr));
   8118         if (ctxt->elemTab == NULL) {
   8119             xmlRngVErrMemory(ctxt, "validating\n");
   8120             return (-1);
   8121         }
   8122     }
   8123     ctxt->elemTab[ctxt->elemNr++] = exec;
   8124     ctxt->elem = exec;
   8125     return (0);
   8126 }
   8127 
   8128 /**
   8129  * xmlRelaxNGElemPop:
   8130  * @ctxt:  the validation context
   8131  *
   8132  * Pop the regexp of the current node content model from the stack
   8133  *
   8134  * Returns the exec or NULL if empty
   8135  */
   8136 static xmlRegExecCtxtPtr
   8137 xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt)
   8138 {
   8139     xmlRegExecCtxtPtr ret;
   8140 
   8141     if (ctxt->elemNr <= 0)
   8142         return (NULL);
   8143     ctxt->elemNr--;
   8144     ret = ctxt->elemTab[ctxt->elemNr];
   8145     ctxt->elemTab[ctxt->elemNr] = NULL;
   8146     if (ctxt->elemNr > 0)
   8147         ctxt->elem = ctxt->elemTab[ctxt->elemNr - 1];
   8148     else
   8149         ctxt->elem = NULL;
   8150     return (ret);
   8151 }
   8152 
   8153 /**
   8154  * xmlRelaxNGValidateProgressiveCallback:
   8155  * @exec:  the regular expression instance
   8156  * @token:  the token which matched
   8157  * @transdata:  callback data, the define for the subelement if available
   8158  @ @inputdata:  callback data, the Relax NG validation context
   8159  *
   8160  * Handle the callback and if needed validate the element children.
   8161  * some of the in/out informations are passed via the context in @inputdata.
   8162  */
   8163 static void
   8164 xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec
   8165                                       ATTRIBUTE_UNUSED,
   8166                                       const xmlChar * token,
   8167                                       void *transdata, void *inputdata)
   8168 {
   8169     xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
   8170     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
   8171     xmlRelaxNGValidStatePtr state, oldstate;
   8172     xmlNodePtr node;
   8173     int ret = 0, oldflags;
   8174 
   8175 #ifdef DEBUG_PROGRESSIVE
   8176     xmlGenericError(xmlGenericErrorContext,
   8177                     "Progressive callback for: '%s'\n", token);
   8178 #endif
   8179     if (ctxt == NULL) {
   8180         fprintf(stderr, "callback on %s missing context\n", token);
   8181         return;
   8182     }
   8183     node = ctxt->pnode;
   8184     ctxt->pstate = 1;
   8185     if (define == NULL) {
   8186         if (token[0] == '#')
   8187             return;
   8188         fprintf(stderr, "callback on %s missing define\n", token);
   8189         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
   8190             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
   8191         ctxt->pstate = -1;
   8192         return;
   8193     }
   8194     if ((ctxt == NULL) || (define == NULL)) {
   8195         fprintf(stderr, "callback on %s missing info\n", token);
   8196         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
   8197             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
   8198         ctxt->pstate = -1;
   8199         return;
   8200     } else if (define->type != XML_RELAXNG_ELEMENT) {
   8201         fprintf(stderr, "callback on %s define is not element\n", token);
   8202         if (ctxt->errNo == XML_RELAXNG_OK)
   8203             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
   8204         ctxt->pstate = -1;
   8205         return;
   8206     }
   8207     if (node->type != XML_ELEMENT_NODE) {
   8208         VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
   8209         if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
   8210             xmlRelaxNGDumpValidError(ctxt);
   8211         ctxt->pstate = -1;
   8212         return;
   8213     }
   8214     if (define->contModel == NULL) {
   8215         /*
   8216          * this node cannot be validated in a streamable fashion
   8217          */
   8218 #ifdef DEBUG_PROGRESSIVE
   8219         xmlGenericError(xmlGenericErrorContext,
   8220                         "Element '%s' validation is not streamable\n",
   8221                         token);
   8222 #endif
   8223         ctxt->pstate = 0;
   8224         ctxt->pdef = define;
   8225         return;
   8226     }
   8227     exec = xmlRegNewExecCtxt(define->contModel,
   8228                              xmlRelaxNGValidateProgressiveCallback, ctxt);
   8229     if (exec == NULL) {
   8230         ctxt->pstate = -1;
   8231         return;
   8232     }
   8233     xmlRelaxNGElemPush(ctxt, exec);
   8234 
   8235     /*
   8236      * Validate the attributes part of the content.
   8237      */
   8238     state = xmlRelaxNGNewValidState(ctxt, node);
   8239     if (state == NULL) {
   8240         ctxt->pstate = -1;
   8241         return;
   8242     }
   8243     oldstate = ctxt->state;
   8244     ctxt->state = state;
   8245     if (define->attrs != NULL) {
   8246         ret = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
   8247         if (ret != 0) {
   8248             ctxt->pstate = -1;
   8249             VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
   8250         }
   8251     }
   8252     if (ctxt->state != NULL) {
   8253         ctxt->state->seq = NULL;
   8254         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
   8255         if (ret != 0) {
   8256             ctxt->pstate = -1;
   8257         }
   8258         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   8259     } else if (ctxt->states != NULL) {
   8260         int tmp = -1, i;
   8261 
   8262         oldflags = ctxt->flags;
   8263 
   8264         for (i = 0; i < ctxt->states->nbState; i++) {
   8265             state = ctxt->states->tabState[i];
   8266             ctxt->state = state;
   8267             ctxt->state->seq = NULL;
   8268 
   8269             if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
   8270                 tmp = 0;
   8271                 break;
   8272             }
   8273         }
   8274         if (tmp != 0) {
   8275             /*
   8276              * validation error, log the message for the "best" one
   8277              */
   8278             ctxt->flags |= FLAGS_IGNORABLE;
   8279             xmlRelaxNGLogBestError(ctxt);
   8280         }
   8281         for (i = 0; i < ctxt->states->nbState; i++) {
   8282             xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[i]);
   8283         }
   8284         xmlRelaxNGFreeStates(ctxt, ctxt->states);
   8285         ctxt->states = NULL;
   8286         if ((ret == 0) && (tmp == -1))
   8287             ctxt->pstate = -1;
   8288         ctxt->flags = oldflags;
   8289     }
   8290     if (ctxt->pstate == -1) {
   8291         if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
   8292             xmlRelaxNGDumpValidError(ctxt);
   8293         }
   8294     }
   8295     ctxt->state = oldstate;
   8296 }
   8297 
   8298 /**
   8299  * xmlRelaxNGValidatePushElement:
   8300  * @ctxt:  the validation context
   8301  * @doc:  a document instance
   8302  * @elem:  an element instance
   8303  *
   8304  * Push a new element start on the RelaxNG validation stack.
   8305  *
   8306  * returns 1 if no validation problem was found or 0 if validating the
   8307  *         element requires a full node, and -1 in case of error.
   8308  */
   8309 int
   8310 xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt,
   8311                               xmlDocPtr doc ATTRIBUTE_UNUSED,
   8312                               xmlNodePtr elem)
   8313 {
   8314     int ret = 1;
   8315 
   8316     if ((ctxt == NULL) || (elem == NULL))
   8317         return (-1);
   8318 
   8319 #ifdef DEBUG_PROGRESSIVE
   8320     xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name);
   8321 #endif
   8322     if (ctxt->elem == 0) {
   8323         xmlRelaxNGPtr schema;
   8324         xmlRelaxNGGrammarPtr grammar;
   8325         xmlRegExecCtxtPtr exec;
   8326         xmlRelaxNGDefinePtr define;
   8327 
   8328         schema = ctxt->schema;
   8329         if (schema == NULL) {
   8330             VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
   8331             return (-1);
   8332         }
   8333         grammar = schema->topgrammar;
   8334         if ((grammar == NULL) || (grammar->start == NULL)) {
   8335             VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
   8336             return (-1);
   8337         }
   8338         define = grammar->start;
   8339         if (define->contModel == NULL) {
   8340             ctxt->pdef = define;
   8341             return (0);
   8342         }
   8343         exec = xmlRegNewExecCtxt(define->contModel,
   8344                                  xmlRelaxNGValidateProgressiveCallback,
   8345                                  ctxt);
   8346         if (exec == NULL) {
   8347             return (-1);
   8348         }
   8349         xmlRelaxNGElemPush(ctxt, exec);
   8350     }
   8351     ctxt->pnode = elem;
   8352     ctxt->pstate = 0;
   8353     if (elem->ns != NULL) {
   8354         ret =
   8355             xmlRegExecPushString2(ctxt->elem, elem->name, elem->ns->href,
   8356                                   ctxt);
   8357     } else {
   8358         ret = xmlRegExecPushString(ctxt->elem, elem->name, ctxt);
   8359     }
   8360     if (ret < 0) {
   8361         VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, elem->name);
   8362     } else {
   8363         if (ctxt->pstate == 0)
   8364             ret = 0;
   8365         else if (ctxt->pstate < 0)
   8366             ret = -1;
   8367         else
   8368             ret = 1;
   8369     }
   8370 #ifdef DEBUG_PROGRESSIVE
   8371     if (ret < 0)
   8372         xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n",
   8373                         elem->name);
   8374 #endif
   8375     return (ret);
   8376 }
   8377 
   8378 /**
   8379  * xmlRelaxNGValidatePushCData:
   8380  * @ctxt:  the RelaxNG validation context
   8381  * @data:  some character data read
   8382  * @len:  the length of the data
   8383  *
   8384  * check the CData parsed for validation in the current stack
   8385  *
   8386  * returns 1 if no validation problem was found or -1 otherwise
   8387  */
   8388 int
   8389 xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt,
   8390                             const xmlChar * data, int len ATTRIBUTE_UNUSED)
   8391 {
   8392     int ret = 1;
   8393 
   8394     if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL))
   8395         return (-1);
   8396 
   8397 #ifdef DEBUG_PROGRESSIVE
   8398     xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len);
   8399 #endif
   8400 
   8401     while (*data != 0) {
   8402         if (!IS_BLANK_CH(*data))
   8403             break;
   8404         data++;
   8405     }
   8406     if (*data == 0)
   8407         return (1);
   8408 
   8409     ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt);
   8410     if (ret < 0) {
   8411         VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO ");
   8412 #ifdef DEBUG_PROGRESSIVE
   8413         xmlGenericError(xmlGenericErrorContext, "CDATA failed\n");
   8414 #endif
   8415 
   8416         return (-1);
   8417     }
   8418     return (1);
   8419 }
   8420 
   8421 /**
   8422  * xmlRelaxNGValidatePopElement:
   8423  * @ctxt:  the RelaxNG validation context
   8424  * @doc:  a document instance
   8425  * @elem:  an element instance
   8426  *
   8427  * Pop the element end from the RelaxNG validation stack.
   8428  *
   8429  * returns 1 if no validation problem was found or 0 otherwise
   8430  */
   8431 int
   8432 xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,
   8433                              xmlDocPtr doc ATTRIBUTE_UNUSED,
   8434                              xmlNodePtr elem)
   8435 {
   8436     int ret;
   8437     xmlRegExecCtxtPtr exec;
   8438 
   8439     if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL))
   8440         return (-1);
   8441 #ifdef DEBUG_PROGRESSIVE
   8442     xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name);
   8443 #endif
   8444     /*
   8445      * verify that we reached a terminal state of the content model.
   8446      */
   8447     exec = xmlRelaxNGElemPop(ctxt);
   8448     ret = xmlRegExecPushString(exec, NULL, NULL);
   8449     if (ret == 0) {
   8450         /*
   8451          * TODO: get some of the names needed to exit the current state of exec
   8452          */
   8453         VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
   8454         ret = -1;
   8455     } else if (ret < 0) {
   8456         ret = -1;
   8457     } else {
   8458         ret = 1;
   8459     }
   8460     xmlRegFreeExecCtxt(exec);
   8461 #ifdef DEBUG_PROGRESSIVE
   8462     if (ret < 0)
   8463         xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n",
   8464                         elem->name);
   8465 #endif
   8466     return (ret);
   8467 }
   8468 
   8469 /**
   8470  * xmlRelaxNGValidateFullElement:
   8471  * @ctxt:  the validation context
   8472  * @doc:  a document instance
   8473  * @elem:  an element instance
   8474  *
   8475  * Validate a full subtree when xmlRelaxNGValidatePushElement() returned
   8476  * 0 and the content of the node has been expanded.
   8477  *
   8478  * returns 1 if no validation problem was found or -1 in case of error.
   8479  */
   8480 int
   8481 xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt,
   8482                               xmlDocPtr doc ATTRIBUTE_UNUSED,
   8483                               xmlNodePtr elem)
   8484 {
   8485     int ret;
   8486     xmlRelaxNGValidStatePtr state;
   8487 
   8488     if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL))
   8489         return (-1);
   8490 #ifdef DEBUG_PROGRESSIVE
   8491     xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name);
   8492 #endif
   8493     state = xmlRelaxNGNewValidState(ctxt, elem->parent);
   8494     if (state == NULL) {
   8495         return (-1);
   8496     }
   8497     state->seq = elem;
   8498     ctxt->state = state;
   8499     ctxt->errNo = XML_RELAXNG_OK;
   8500     ret = xmlRelaxNGValidateDefinition(ctxt, ctxt->pdef);
   8501     if ((ret != 0) || (ctxt->errNo != XML_RELAXNG_OK))
   8502         ret = -1;
   8503     else
   8504         ret = 1;
   8505     xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   8506     ctxt->state = NULL;
   8507 #ifdef DEBUG_PROGRESSIVE
   8508     if (ret < 0)
   8509         xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n",
   8510                         elem->name);
   8511 #endif
   8512     return (ret);
   8513 }
   8514 
   8515 /************************************************************************
   8516  *									*
   8517  *		Generic interpreted validation implementation		*
   8518  *									*
   8519  ************************************************************************/
   8520 static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
   8521                                    xmlRelaxNGDefinePtr define);
   8522 
   8523 /**
   8524  * xmlRelaxNGSkipIgnored:
   8525  * @ctxt:  a schema validation context
   8526  * @node:  the top node.
   8527  *
   8528  * Skip ignorable nodes in that context
   8529  *
   8530  * Returns the new sibling or NULL in case of error.
   8531  */
   8532 static xmlNodePtr
   8533 xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
   8534                       xmlNodePtr node)
   8535 {
   8536     /*
   8537      * TODO complete and handle entities
   8538      */
   8539     while ((node != NULL) &&
   8540            ((node->type == XML_COMMENT_NODE) ||
   8541             (node->type == XML_PI_NODE) ||
   8542 	    (node->type == XML_XINCLUDE_START) ||
   8543 	    (node->type == XML_XINCLUDE_END) ||
   8544             (((node->type == XML_TEXT_NODE) ||
   8545               (node->type == XML_CDATA_SECTION_NODE)) &&
   8546              ((ctxt->flags & FLAGS_MIXED_CONTENT) ||
   8547               (IS_BLANK_NODE(node)))))) {
   8548         node = node->next;
   8549     }
   8550     return (node);
   8551 }
   8552 
   8553 /**
   8554  * xmlRelaxNGNormalize:
   8555  * @ctxt:  a schema validation context
   8556  * @str:  the string to normalize
   8557  *
   8558  * Implements the  normalizeWhiteSpace( s ) function from
   8559  * section 6.2.9 of the spec
   8560  *
   8561  * Returns the new string or NULL in case of error.
   8562  */
   8563 static xmlChar *
   8564 xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str)
   8565 {
   8566     xmlChar *ret, *p;
   8567     const xmlChar *tmp;
   8568     int len;
   8569 
   8570     if (str == NULL)
   8571         return (NULL);
   8572     tmp = str;
   8573     while (*tmp != 0)
   8574         tmp++;
   8575     len = tmp - str;
   8576 
   8577     ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
   8578     if (ret == NULL) {
   8579         xmlRngVErrMemory(ctxt, "validating\n");
   8580         return (NULL);
   8581     }
   8582     p = ret;
   8583     while (IS_BLANK_CH(*str))
   8584         str++;
   8585     while (*str != 0) {
   8586         if (IS_BLANK_CH(*str)) {
   8587             while (IS_BLANK_CH(*str))
   8588                 str++;
   8589             if (*str == 0)
   8590                 break;
   8591             *p++ = ' ';
   8592         } else
   8593             *p++ = *str++;
   8594     }
   8595     *p = 0;
   8596     return (ret);
   8597 }
   8598 
   8599 /**
   8600  * xmlRelaxNGValidateDatatype:
   8601  * @ctxt:  a Relax-NG validation context
   8602  * @value:  the string value
   8603  * @type:  the datatype definition
   8604  * @node:  the node
   8605  *
   8606  * Validate the given value against the dataype
   8607  *
   8608  * Returns 0 if the validation succeeded or an error code.
   8609  */
   8610 static int
   8611 xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt,
   8612                            const xmlChar * value,
   8613                            xmlRelaxNGDefinePtr define, xmlNodePtr node)
   8614 {
   8615     int ret, tmp;
   8616     xmlRelaxNGTypeLibraryPtr lib;
   8617     void *result = NULL;
   8618     xmlRelaxNGDefinePtr cur;
   8619 
   8620     if ((define == NULL) || (define->data == NULL)) {
   8621         return (-1);
   8622     }
   8623     lib = (xmlRelaxNGTypeLibraryPtr) define->data;
   8624     if (lib->check != NULL) {
   8625         if ((define->attrs != NULL) &&
   8626             (define->attrs->type == XML_RELAXNG_PARAM)) {
   8627             ret =
   8628                 lib->check(lib->data, define->name, value, &result, node);
   8629         } else {
   8630             ret = lib->check(lib->data, define->name, value, NULL, node);
   8631         }
   8632     } else
   8633         ret = -1;
   8634     if (ret < 0) {
   8635         VALID_ERR2(XML_RELAXNG_ERR_TYPE, define->name);
   8636         if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
   8637             lib->freef(lib->data, result);
   8638         return (-1);
   8639     } else if (ret == 1) {
   8640         ret = 0;
   8641     } else if (ret == 2) {
   8642         VALID_ERR2P(XML_RELAXNG_ERR_DUPID, value);
   8643     } else {
   8644         VALID_ERR3P(XML_RELAXNG_ERR_TYPEVAL, define->name, value);
   8645         ret = -1;
   8646     }
   8647     cur = define->attrs;
   8648     while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) {
   8649         if (lib->facet != NULL) {
   8650             tmp = lib->facet(lib->data, define->name, cur->name,
   8651                              cur->value, value, result);
   8652             if (tmp != 0)
   8653                 ret = -1;
   8654         }
   8655         cur = cur->next;
   8656     }
   8657     if ((ret == 0) && (define->content != NULL)) {
   8658         const xmlChar *oldvalue, *oldendvalue;
   8659 
   8660         oldvalue = ctxt->state->value;
   8661         oldendvalue = ctxt->state->endvalue;
   8662         ctxt->state->value = (xmlChar *) value;
   8663         ctxt->state->endvalue = NULL;
   8664         ret = xmlRelaxNGValidateValue(ctxt, define->content);
   8665         ctxt->state->value = (xmlChar *) oldvalue;
   8666         ctxt->state->endvalue = (xmlChar *) oldendvalue;
   8667     }
   8668     if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
   8669         lib->freef(lib->data, result);
   8670     return (ret);
   8671 }
   8672 
   8673 /**
   8674  * xmlRelaxNGNextValue:
   8675  * @ctxt:  a Relax-NG validation context
   8676  *
   8677  * Skip to the next value when validating within a list
   8678  *
   8679  * Returns 0 if the operation succeeded or an error code.
   8680  */
   8681 static int
   8682 xmlRelaxNGNextValue(xmlRelaxNGValidCtxtPtr ctxt)
   8683 {
   8684     xmlChar *cur;
   8685 
   8686     cur = ctxt->state->value;
   8687     if ((cur == NULL) || (ctxt->state->endvalue == NULL)) {
   8688         ctxt->state->value = NULL;
   8689         ctxt->state->endvalue = NULL;
   8690         return (0);
   8691     }
   8692     while (*cur != 0)
   8693         cur++;
   8694     while ((cur != ctxt->state->endvalue) && (*cur == 0))
   8695         cur++;
   8696     if (cur == ctxt->state->endvalue)
   8697         ctxt->state->value = NULL;
   8698     else
   8699         ctxt->state->value = cur;
   8700     return (0);
   8701 }
   8702 
   8703 /**
   8704  * xmlRelaxNGValidateValueList:
   8705  * @ctxt:  a Relax-NG validation context
   8706  * @defines:  the list of definitions to verify
   8707  *
   8708  * Validate the given set of definitions for the current value
   8709  *
   8710  * Returns 0 if the validation succeeded or an error code.
   8711  */
   8712 static int
   8713 xmlRelaxNGValidateValueList(xmlRelaxNGValidCtxtPtr ctxt,
   8714                             xmlRelaxNGDefinePtr defines)
   8715 {
   8716     int ret = 0;
   8717 
   8718     while (defines != NULL) {
   8719         ret = xmlRelaxNGValidateValue(ctxt, defines);
   8720         if (ret != 0)
   8721             break;
   8722         defines = defines->next;
   8723     }
   8724     return (ret);
   8725 }
   8726 
   8727 /**
   8728  * xmlRelaxNGValidateValue:
   8729  * @ctxt:  a Relax-NG validation context
   8730  * @define:  the definition to verify
   8731  *
   8732  * Validate the given definition for the current value
   8733  *
   8734  * Returns 0 if the validation succeeded or an error code.
   8735  */
   8736 static int
   8737 xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
   8738                         xmlRelaxNGDefinePtr define)
   8739 {
   8740     int ret = 0, oldflags;
   8741     xmlChar *value;
   8742 
   8743     value = ctxt->state->value;
   8744     switch (define->type) {
   8745         case XML_RELAXNG_EMPTY:{
   8746                 if ((value != NULL) && (value[0] != 0)) {
   8747                     int idx = 0;
   8748 
   8749                     while (IS_BLANK_CH(value[idx]))
   8750                         idx++;
   8751                     if (value[idx] != 0)
   8752                         ret = -1;
   8753                 }
   8754                 break;
   8755             }
   8756         case XML_RELAXNG_TEXT:
   8757             break;
   8758         case XML_RELAXNG_VALUE:{
   8759                 if (!xmlStrEqual(value, define->value)) {
   8760                     if (define->name != NULL) {
   8761                         xmlRelaxNGTypeLibraryPtr lib;
   8762 
   8763                         lib = (xmlRelaxNGTypeLibraryPtr) define->data;
   8764                         if ((lib != NULL) && (lib->comp != NULL)) {
   8765                             ret = lib->comp(lib->data, define->name,
   8766                                             define->value, define->node,
   8767                                             (void *) define->attrs,
   8768                                             value, ctxt->state->node);
   8769                         } else
   8770                             ret = -1;
   8771                         if (ret < 0) {
   8772                             VALID_ERR2(XML_RELAXNG_ERR_TYPECMP,
   8773                                        define->name);
   8774                             return (-1);
   8775                         } else if (ret == 1) {
   8776                             ret = 0;
   8777                         } else {
   8778                             ret = -1;
   8779                         }
   8780                     } else {
   8781                         xmlChar *nval, *nvalue;
   8782 
   8783                         /*
   8784                          * TODO: trivial optimizations are possible by
   8785                          * computing at compile-time
   8786                          */
   8787                         nval = xmlRelaxNGNormalize(ctxt, define->value);
   8788                         nvalue = xmlRelaxNGNormalize(ctxt, value);
   8789 
   8790                         if ((nval == NULL) || (nvalue == NULL) ||
   8791                             (!xmlStrEqual(nval, nvalue)))
   8792                             ret = -1;
   8793                         if (nval != NULL)
   8794                             xmlFree(nval);
   8795                         if (nvalue != NULL)
   8796                             xmlFree(nvalue);
   8797                     }
   8798                 }
   8799                 if (ret == 0)
   8800                     xmlRelaxNGNextValue(ctxt);
   8801                 break;
   8802             }
   8803         case XML_RELAXNG_DATATYPE:{
   8804                 ret = xmlRelaxNGValidateDatatype(ctxt, value, define,
   8805                                                  ctxt->state->seq);
   8806                 if (ret == 0)
   8807                     xmlRelaxNGNextValue(ctxt);
   8808 
   8809                 break;
   8810             }
   8811         case XML_RELAXNG_CHOICE:{
   8812                 xmlRelaxNGDefinePtr list = define->content;
   8813                 xmlChar *oldvalue;
   8814 
   8815                 oldflags = ctxt->flags;
   8816                 ctxt->flags |= FLAGS_IGNORABLE;
   8817 
   8818                 oldvalue = ctxt->state->value;
   8819                 while (list != NULL) {
   8820                     ret = xmlRelaxNGValidateValue(ctxt, list);
   8821                     if (ret == 0) {
   8822                         break;
   8823                     }
   8824                     ctxt->state->value = oldvalue;
   8825                     list = list->next;
   8826                 }
   8827                 ctxt->flags = oldflags;
   8828                 if (ret != 0) {
   8829                     if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
   8830                         xmlRelaxNGDumpValidError(ctxt);
   8831                 } else {
   8832                     if (ctxt->errNr > 0)
   8833                         xmlRelaxNGPopErrors(ctxt, 0);
   8834                 }
   8835                 break;
   8836             }
   8837         case XML_RELAXNG_LIST:{
   8838                 xmlRelaxNGDefinePtr list = define->content;
   8839                 xmlChar *oldvalue, *oldend, *val, *cur;
   8840 
   8841 #ifdef DEBUG_LIST
   8842                 int nb_values = 0;
   8843 #endif
   8844 
   8845                 oldvalue = ctxt->state->value;
   8846                 oldend = ctxt->state->endvalue;
   8847 
   8848                 val = xmlStrdup(oldvalue);
   8849                 if (val == NULL) {
   8850                     val = xmlStrdup(BAD_CAST "");
   8851                 }
   8852                 if (val == NULL) {
   8853                     VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
   8854                     return (-1);
   8855                 }
   8856                 cur = val;
   8857                 while (*cur != 0) {
   8858                     if (IS_BLANK_CH(*cur)) {
   8859                         *cur = 0;
   8860                         cur++;
   8861 #ifdef DEBUG_LIST
   8862                         nb_values++;
   8863 #endif
   8864                         while (IS_BLANK_CH(*cur))
   8865                             *cur++ = 0;
   8866                     } else
   8867                         cur++;
   8868                 }
   8869 #ifdef DEBUG_LIST
   8870                 xmlGenericError(xmlGenericErrorContext,
   8871                                 "list value: '%s' found %d items\n",
   8872                                 oldvalue, nb_values);
   8873                 nb_values = 0;
   8874 #endif
   8875                 ctxt->state->endvalue = cur;
   8876                 cur = val;
   8877                 while ((*cur == 0) && (cur != ctxt->state->endvalue))
   8878                     cur++;
   8879 
   8880                 ctxt->state->value = cur;
   8881 
   8882                 while (list != NULL) {
   8883                     if (ctxt->state->value == ctxt->state->endvalue)
   8884                         ctxt->state->value = NULL;
   8885                     ret = xmlRelaxNGValidateValue(ctxt, list);
   8886                     if (ret != 0) {
   8887 #ifdef DEBUG_LIST
   8888                         xmlGenericError(xmlGenericErrorContext,
   8889                                         "Failed to validate value: '%s' with %d rule\n",
   8890                                         ctxt->state->value, nb_values);
   8891 #endif
   8892                         break;
   8893                     }
   8894 #ifdef DEBUG_LIST
   8895                     nb_values++;
   8896 #endif
   8897                     list = list->next;
   8898                 }
   8899 
   8900                 if ((ret == 0) && (ctxt->state->value != NULL) &&
   8901                     (ctxt->state->value != ctxt->state->endvalue)) {
   8902                     VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA,
   8903                                ctxt->state->value);
   8904                     ret = -1;
   8905                 }
   8906                 xmlFree(val);
   8907                 ctxt->state->value = oldvalue;
   8908                 ctxt->state->endvalue = oldend;
   8909                 break;
   8910             }
   8911         case XML_RELAXNG_ONEORMORE:
   8912             ret = xmlRelaxNGValidateValueList(ctxt, define->content);
   8913             if (ret != 0) {
   8914                 break;
   8915             }
   8916             /* Falls through. */
   8917         case XML_RELAXNG_ZEROORMORE:{
   8918                 xmlChar *cur, *temp;
   8919 
   8920                 if ((ctxt->state->value == NULL) ||
   8921                     (*ctxt->state->value == 0)) {
   8922                     ret = 0;
   8923                     break;
   8924                 }
   8925                 oldflags = ctxt->flags;
   8926                 ctxt->flags |= FLAGS_IGNORABLE;
   8927                 cur = ctxt->state->value;
   8928                 temp = NULL;
   8929                 while ((cur != NULL) && (cur != ctxt->state->endvalue) &&
   8930                        (temp != cur)) {
   8931                     temp = cur;
   8932                     ret =
   8933                         xmlRelaxNGValidateValueList(ctxt, define->content);
   8934                     if (ret != 0) {
   8935                         ctxt->state->value = temp;
   8936                         ret = 0;
   8937                         break;
   8938                     }
   8939                     cur = ctxt->state->value;
   8940                 }
   8941                 ctxt->flags = oldflags;
   8942 		if (ctxt->errNr > 0)
   8943 		    xmlRelaxNGPopErrors(ctxt, 0);
   8944                 break;
   8945             }
   8946         case XML_RELAXNG_OPTIONAL:{
   8947                 xmlChar *temp;
   8948 
   8949                 if ((ctxt->state->value == NULL) ||
   8950                     (*ctxt->state->value == 0)) {
   8951                     ret = 0;
   8952                     break;
   8953                 }
   8954                 oldflags = ctxt->flags;
   8955                 ctxt->flags |= FLAGS_IGNORABLE;
   8956                 temp = ctxt->state->value;
   8957                 ret = xmlRelaxNGValidateValue(ctxt, define->content);
   8958                 ctxt->flags = oldflags;
   8959                 if (ret != 0) {
   8960                     ctxt->state->value = temp;
   8961                     if (ctxt->errNr > 0)
   8962                         xmlRelaxNGPopErrors(ctxt, 0);
   8963                     ret = 0;
   8964                     break;
   8965                 }
   8966 		if (ctxt->errNr > 0)
   8967 		    xmlRelaxNGPopErrors(ctxt, 0);
   8968                 break;
   8969             }
   8970         case XML_RELAXNG_EXCEPT:{
   8971                 xmlRelaxNGDefinePtr list;
   8972 
   8973                 list = define->content;
   8974                 while (list != NULL) {
   8975                     ret = xmlRelaxNGValidateValue(ctxt, list);
   8976                     if (ret == 0) {
   8977                         ret = -1;
   8978                         break;
   8979                     } else
   8980                         ret = 0;
   8981                     list = list->next;
   8982                 }
   8983                 break;
   8984             }
   8985         case XML_RELAXNG_DEF:
   8986         case XML_RELAXNG_GROUP:{
   8987                 xmlRelaxNGDefinePtr list;
   8988 
   8989                 list = define->content;
   8990                 while (list != NULL) {
   8991                     ret = xmlRelaxNGValidateValue(ctxt, list);
   8992                     if (ret != 0) {
   8993                         ret = -1;
   8994                         break;
   8995                     } else
   8996                         ret = 0;
   8997                     list = list->next;
   8998                 }
   8999                 break;
   9000             }
   9001         case XML_RELAXNG_REF:
   9002         case XML_RELAXNG_PARENTREF:
   9003 	    if (define->content == NULL) {
   9004                 VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
   9005                 ret = -1;
   9006 	    } else {
   9007                 ret = xmlRelaxNGValidateValue(ctxt, define->content);
   9008             }
   9009             break;
   9010         default:
   9011             TODO ret = -1;
   9012     }
   9013     return (ret);
   9014 }
   9015 
   9016 /**
   9017  * xmlRelaxNGValidateValueContent:
   9018  * @ctxt:  a Relax-NG validation context
   9019  * @defines:  the list of definitions to verify
   9020  *
   9021  * Validate the given definitions for the current value
   9022  *
   9023  * Returns 0 if the validation succeeded or an error code.
   9024  */
   9025 static int
   9026 xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt,
   9027                                xmlRelaxNGDefinePtr defines)
   9028 {
   9029     int ret = 0;
   9030 
   9031     while (defines != NULL) {
   9032         ret = xmlRelaxNGValidateValue(ctxt, defines);
   9033         if (ret != 0)
   9034             break;
   9035         defines = defines->next;
   9036     }
   9037     return (ret);
   9038 }
   9039 
   9040 /**
   9041  * xmlRelaxNGAttributeMatch:
   9042  * @ctxt:  a Relax-NG validation context
   9043  * @define:  the definition to check
   9044  * @prop:  the attribute
   9045  *
   9046  * Check if the attribute matches the definition nameClass
   9047  *
   9048  * Returns 1 if the attribute matches, 0 if no, or -1 in case of error
   9049  */
   9050 static int
   9051 xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt,
   9052                          xmlRelaxNGDefinePtr define, xmlAttrPtr prop)
   9053 {
   9054     int ret;
   9055 
   9056     if (define->name != NULL) {
   9057         if (!xmlStrEqual(define->name, prop->name))
   9058             return (0);
   9059     }
   9060     if (define->ns != NULL) {
   9061         if (define->ns[0] == 0) {
   9062             if (prop->ns != NULL)
   9063                 return (0);
   9064         } else {
   9065             if ((prop->ns == NULL) ||
   9066                 (!xmlStrEqual(define->ns, prop->ns->href)))
   9067                 return (0);
   9068         }
   9069     }
   9070     if (define->nameClass == NULL)
   9071         return (1);
   9072     define = define->nameClass;
   9073     if (define->type == XML_RELAXNG_EXCEPT) {
   9074         xmlRelaxNGDefinePtr list;
   9075 
   9076         list = define->content;
   9077         while (list != NULL) {
   9078             ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);
   9079             if (ret == 1)
   9080                 return (0);
   9081             if (ret < 0)
   9082                 return (ret);
   9083             list = list->next;
   9084         }
   9085     } else if (define->type == XML_RELAXNG_CHOICE) {
   9086         xmlRelaxNGDefinePtr list;
   9087 
   9088         list = define->nameClass;
   9089         while (list != NULL) {
   9090             ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);
   9091             if (ret == 1)
   9092                 return (1);
   9093             if (ret < 0)
   9094                 return (ret);
   9095             list = list->next;
   9096         }
   9097         return (0);
   9098     } else {
   9099     TODO}
   9100     return (1);
   9101 }
   9102 
   9103 /**
   9104  * xmlRelaxNGValidateAttribute:
   9105  * @ctxt:  a Relax-NG validation context
   9106  * @define:  the definition to verify
   9107  *
   9108  * Validate the given attribute definition for that node
   9109  *
   9110  * Returns 0 if the validation succeeded or an error code.
   9111  */
   9112 static int
   9113 xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
   9114                             xmlRelaxNGDefinePtr define)
   9115 {
   9116     int ret = 0, i;
   9117     xmlChar *value, *oldvalue;
   9118     xmlAttrPtr prop = NULL, tmp;
   9119     xmlNodePtr oldseq;
   9120 
   9121     if (ctxt->state->nbAttrLeft <= 0)
   9122         return (-1);
   9123     if (define->name != NULL) {
   9124         for (i = 0; i < ctxt->state->nbAttrs; i++) {
   9125             tmp = ctxt->state->attrs[i];
   9126             if ((tmp != NULL) && (xmlStrEqual(define->name, tmp->name))) {
   9127                 if ((((define->ns == NULL) || (define->ns[0] == 0)) &&
   9128                      (tmp->ns == NULL)) ||
   9129                     ((tmp->ns != NULL) &&
   9130                      (xmlStrEqual(define->ns, tmp->ns->href)))) {
   9131                     prop = tmp;
   9132                     break;
   9133                 }
   9134             }
   9135         }
   9136         if (prop != NULL) {
   9137             value = xmlNodeListGetString(prop->doc, prop->children, 1);
   9138             oldvalue = ctxt->state->value;
   9139             oldseq = ctxt->state->seq;
   9140             ctxt->state->seq = (xmlNodePtr) prop;
   9141             ctxt->state->value = value;
   9142             ctxt->state->endvalue = NULL;
   9143             ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
   9144             if (ctxt->state->value != NULL)
   9145                 value = ctxt->state->value;
   9146             if (value != NULL)
   9147                 xmlFree(value);
   9148             ctxt->state->value = oldvalue;
   9149             ctxt->state->seq = oldseq;
   9150             if (ret == 0) {
   9151                 /*
   9152                  * flag the attribute as processed
   9153                  */
   9154                 ctxt->state->attrs[i] = NULL;
   9155                 ctxt->state->nbAttrLeft--;
   9156             }
   9157         } else {
   9158             ret = -1;
   9159         }
   9160 #ifdef DEBUG
   9161         xmlGenericError(xmlGenericErrorContext,
   9162                         "xmlRelaxNGValidateAttribute(%s): %d\n",
   9163                         define->name, ret);
   9164 #endif
   9165     } else {
   9166         for (i = 0; i < ctxt->state->nbAttrs; i++) {
   9167             tmp = ctxt->state->attrs[i];
   9168             if ((tmp != NULL) &&
   9169                 (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) {
   9170                 prop = tmp;
   9171                 break;
   9172             }
   9173         }
   9174         if (prop != NULL) {
   9175             value = xmlNodeListGetString(prop->doc, prop->children, 1);
   9176             oldvalue = ctxt->state->value;
   9177             oldseq = ctxt->state->seq;
   9178             ctxt->state->seq = (xmlNodePtr) prop;
   9179             ctxt->state->value = value;
   9180             ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
   9181             if (ctxt->state->value != NULL)
   9182                 value = ctxt->state->value;
   9183             if (value != NULL)
   9184                 xmlFree(value);
   9185             ctxt->state->value = oldvalue;
   9186             ctxt->state->seq = oldseq;
   9187             if (ret == 0) {
   9188                 /*
   9189                  * flag the attribute as processed
   9190                  */
   9191                 ctxt->state->attrs[i] = NULL;
   9192                 ctxt->state->nbAttrLeft--;
   9193             }
   9194         } else {
   9195             ret = -1;
   9196         }
   9197 #ifdef DEBUG
   9198         if (define->ns != NULL) {
   9199             xmlGenericError(xmlGenericErrorContext,
   9200                             "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",
   9201                             define->ns, ret);
   9202         } else {
   9203             xmlGenericError(xmlGenericErrorContext,
   9204                             "xmlRelaxNGValidateAttribute(anyName): %d\n",
   9205                             ret);
   9206         }
   9207 #endif
   9208     }
   9209 
   9210     return (ret);
   9211 }
   9212 
   9213 /**
   9214  * xmlRelaxNGValidateAttributeList:
   9215  * @ctxt:  a Relax-NG validation context
   9216  * @define:  the list of definition to verify
   9217  *
   9218  * Validate the given node against the list of attribute definitions
   9219  *
   9220  * Returns 0 if the validation succeeded or an error code.
   9221  */
   9222 static int
   9223 xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
   9224                                 xmlRelaxNGDefinePtr defines)
   9225 {
   9226     int ret = 0, res;
   9227     int needmore = 0;
   9228     xmlRelaxNGDefinePtr cur;
   9229 
   9230     cur = defines;
   9231     while (cur != NULL) {
   9232         if (cur->type == XML_RELAXNG_ATTRIBUTE) {
   9233             if (xmlRelaxNGValidateAttribute(ctxt, cur) != 0)
   9234                 ret = -1;
   9235         } else
   9236             needmore = 1;
   9237         cur = cur->next;
   9238     }
   9239     if (!needmore)
   9240         return (ret);
   9241     cur = defines;
   9242     while (cur != NULL) {
   9243         if (cur->type != XML_RELAXNG_ATTRIBUTE) {
   9244             if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
   9245                 res = xmlRelaxNGValidateDefinition(ctxt, cur);
   9246                 if (res < 0)
   9247                     ret = -1;
   9248             } else {
   9249                 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
   9250                 return (-1);
   9251             }
   9252             if (res == -1)      /* continues on -2 */
   9253                 break;
   9254         }
   9255         cur = cur->next;
   9256     }
   9257 
   9258     return (ret);
   9259 }
   9260 
   9261 /**
   9262  * xmlRelaxNGNodeMatchesList:
   9263  * @node:  the node
   9264  * @list:  a NULL terminated array of definitions
   9265  *
   9266  * Check if a node can be matched by one of the definitions
   9267  *
   9268  * Returns 1 if matches 0 otherwise
   9269  */
   9270 static int
   9271 xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr * list)
   9272 {
   9273     xmlRelaxNGDefinePtr cur;
   9274     int i = 0, tmp;
   9275 
   9276     if ((node == NULL) || (list == NULL))
   9277         return (0);
   9278 
   9279     cur = list[i++];
   9280     while (cur != NULL) {
   9281         if ((node->type == XML_ELEMENT_NODE) &&
   9282             (cur->type == XML_RELAXNG_ELEMENT)) {
   9283             tmp = xmlRelaxNGElementMatch(NULL, cur, node);
   9284             if (tmp == 1)
   9285                 return (1);
   9286         } else if (((node->type == XML_TEXT_NODE) ||
   9287                     (node->type == XML_CDATA_SECTION_NODE)) &&
   9288                    ((cur->type == XML_RELAXNG_DATATYPE) ||
   9289 		    (cur->type == XML_RELAXNG_LIST) ||
   9290                     (cur->type == XML_RELAXNG_TEXT) ||
   9291                     (cur->type == XML_RELAXNG_VALUE))) {
   9292             return (1);
   9293         }
   9294         cur = list[i++];
   9295     }
   9296     return (0);
   9297 }
   9298 
   9299 /**
   9300  * xmlRelaxNGValidateInterleave:
   9301  * @ctxt:  a Relax-NG validation context
   9302  * @define:  the definition to verify
   9303  *
   9304  * Validate an interleave definition for a node.
   9305  *
   9306  * Returns 0 if the validation succeeded or an error code.
   9307  */
   9308 static int
   9309 xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt,
   9310                              xmlRelaxNGDefinePtr define)
   9311 {
   9312     int ret = 0, i, nbgroups;
   9313     int errNr = ctxt->errNr;
   9314     int oldflags;
   9315 
   9316     xmlRelaxNGValidStatePtr oldstate;
   9317     xmlRelaxNGPartitionPtr partitions;
   9318     xmlRelaxNGInterleaveGroupPtr group = NULL;
   9319     xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem;
   9320     xmlNodePtr *list = NULL, *lasts = NULL;
   9321 
   9322     if (define->data != NULL) {
   9323         partitions = (xmlRelaxNGPartitionPtr) define->data;
   9324         nbgroups = partitions->nbgroups;
   9325     } else {
   9326         VALID_ERR(XML_RELAXNG_ERR_INTERNODATA);
   9327         return (-1);
   9328     }
   9329     /*
   9330      * Optimizations for MIXED
   9331      */
   9332     oldflags = ctxt->flags;
   9333     if (define->dflags & IS_MIXED) {
   9334         ctxt->flags |= FLAGS_MIXED_CONTENT;
   9335         if (nbgroups == 2) {
   9336             /*
   9337              * this is a pure <mixed> case
   9338              */
   9339             if (ctxt->state != NULL)
   9340                 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
   9341                                                          ctxt->state->seq);
   9342             if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT)
   9343                 ret = xmlRelaxNGValidateDefinition(ctxt,
   9344                                                    partitions->groups[1]->
   9345                                                    rule);
   9346             else
   9347                 ret = xmlRelaxNGValidateDefinition(ctxt,
   9348                                                    partitions->groups[0]->
   9349                                                    rule);
   9350             if (ret == 0) {
   9351                 if (ctxt->state != NULL)
   9352                     ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
   9353                                                              ctxt->state->
   9354                                                              seq);
   9355             }
   9356             ctxt->flags = oldflags;
   9357             return (ret);
   9358         }
   9359     }
   9360 
   9361     /*
   9362      * Build arrays to store the first and last node of the chain
   9363      * pertaining to each group
   9364      */
   9365     list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
   9366     if (list == NULL) {
   9367         xmlRngVErrMemory(ctxt, "validating\n");
   9368         return (-1);
   9369     }
   9370     memset(list, 0, nbgroups * sizeof(xmlNodePtr));
   9371     lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
   9372     if (lasts == NULL) {
   9373         xmlRngVErrMemory(ctxt, "validating\n");
   9374         return (-1);
   9375     }
   9376     memset(lasts, 0, nbgroups * sizeof(xmlNodePtr));
   9377 
   9378     /*
   9379      * Walk the sequence of children finding the right group and
   9380      * sorting them in sequences.
   9381      */
   9382     cur = ctxt->state->seq;
   9383     cur = xmlRelaxNGSkipIgnored(ctxt, cur);
   9384     start = cur;
   9385     while (cur != NULL) {
   9386         ctxt->state->seq = cur;
   9387         if ((partitions->triage != NULL) &&
   9388             (partitions->flags & IS_DETERMINIST)) {
   9389             void *tmp = NULL;
   9390 
   9391             if ((cur->type == XML_TEXT_NODE) ||
   9392                 (cur->type == XML_CDATA_SECTION_NODE)) {
   9393                 tmp = xmlHashLookup2(partitions->triage, BAD_CAST "#text",
   9394                                      NULL);
   9395             } else if (cur->type == XML_ELEMENT_NODE) {
   9396                 if (cur->ns != NULL) {
   9397                     tmp = xmlHashLookup2(partitions->triage, cur->name,
   9398                                          cur->ns->href);
   9399                     if (tmp == NULL)
   9400                         tmp = xmlHashLookup2(partitions->triage,
   9401                                              BAD_CAST "#any",
   9402                                              cur->ns->href);
   9403                 } else
   9404                     tmp =
   9405                         xmlHashLookup2(partitions->triage, cur->name,
   9406                                        NULL);
   9407                 if (tmp == NULL)
   9408                     tmp =
   9409                         xmlHashLookup2(partitions->triage, BAD_CAST "#any",
   9410                                        NULL);
   9411             }
   9412 
   9413             if (tmp == NULL) {
   9414                 i = nbgroups;
   9415             } else {
   9416                 i = ((ptrdiff_t) tmp) - 1;
   9417                 if (partitions->flags & IS_NEEDCHECK) {
   9418                     group = partitions->groups[i];
   9419                     if (!xmlRelaxNGNodeMatchesList(cur, group->defs))
   9420                         i = nbgroups;
   9421                 }
   9422             }
   9423         } else {
   9424             for (i = 0; i < nbgroups; i++) {
   9425                 group = partitions->groups[i];
   9426                 if (group == NULL)
   9427                     continue;
   9428                 if (xmlRelaxNGNodeMatchesList(cur, group->defs))
   9429                     break;
   9430             }
   9431         }
   9432         /*
   9433          * We break as soon as an element not matched is found
   9434          */
   9435         if (i >= nbgroups) {
   9436             break;
   9437         }
   9438         if (lasts[i] != NULL) {
   9439             lasts[i]->next = cur;
   9440             lasts[i] = cur;
   9441         } else {
   9442             list[i] = cur;
   9443             lasts[i] = cur;
   9444         }
   9445         if (cur->next != NULL)
   9446             lastchg = cur->next;
   9447         else
   9448             lastchg = cur;
   9449         cur = xmlRelaxNGSkipIgnored(ctxt, cur->next);
   9450     }
   9451     if (ret != 0) {
   9452         VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
   9453         ret = -1;
   9454         goto done;
   9455     }
   9456     lastelem = cur;
   9457     oldstate = ctxt->state;
   9458     for (i = 0; i < nbgroups; i++) {
   9459         ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate);
   9460 	if (ctxt->state == NULL) {
   9461 	    ret = -1;
   9462 	    break;
   9463 	}
   9464         group = partitions->groups[i];
   9465         if (lasts[i] != NULL) {
   9466             last = lasts[i]->next;
   9467             lasts[i]->next = NULL;
   9468         }
   9469         ctxt->state->seq = list[i];
   9470         ret = xmlRelaxNGValidateDefinition(ctxt, group->rule);
   9471         if (ret != 0)
   9472             break;
   9473         if (ctxt->state != NULL) {
   9474             cur = ctxt->state->seq;
   9475             cur = xmlRelaxNGSkipIgnored(ctxt, cur);
   9476             xmlRelaxNGFreeValidState(ctxt, oldstate);
   9477             oldstate = ctxt->state;
   9478             ctxt->state = NULL;
   9479             if (cur != NULL) {
   9480                 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
   9481                 ret = -1;
   9482                 ctxt->state = oldstate;
   9483                 goto done;
   9484             }
   9485         } else if (ctxt->states != NULL) {
   9486             int j;
   9487             int found = 0;
   9488 	    int best = -1;
   9489 	    int lowattr = -1;
   9490 
   9491 	    /*
   9492 	     * PBM: what happen if there is attributes checks in the interleaves
   9493 	     */
   9494 
   9495             for (j = 0; j < ctxt->states->nbState; j++) {
   9496                 cur = ctxt->states->tabState[j]->seq;
   9497                 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
   9498                 if (cur == NULL) {
   9499 		    if (found == 0) {
   9500 		        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
   9501 			best = j;
   9502 		    }
   9503                     found = 1;
   9504 		    if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) {
   9505 		        /* try  to keep the latest one to mach old heuristic */
   9506 		        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
   9507 			best = j;
   9508 		    }
   9509                     if (lowattr == 0)
   9510 		        break;
   9511                 } else if (found == 0) {
   9512                     if (lowattr == -1) {
   9513 		        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
   9514 			best = j;
   9515 		    } else
   9516 		    if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr)  {
   9517 		        /* try  to keep the latest one to mach old heuristic */
   9518 		        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
   9519 			best = j;
   9520 		    }
   9521 		}
   9522             }
   9523 	    /*
   9524 	     * BIG PBM: here we pick only one restarting point :-(
   9525 	     */
   9526             if (ctxt->states->nbState > 0) {
   9527                 xmlRelaxNGFreeValidState(ctxt, oldstate);
   9528 		if (best != -1) {
   9529 		    oldstate = ctxt->states->tabState[best];
   9530 		    ctxt->states->tabState[best] = NULL;
   9531 		} else {
   9532 		    oldstate =
   9533 			ctxt->states->tabState[ctxt->states->nbState - 1];
   9534                     ctxt->states->tabState[ctxt->states->nbState - 1] = NULL;
   9535                     ctxt->states->nbState--;
   9536 		}
   9537             }
   9538             for (j = 0; j < ctxt->states->nbState ; j++) {
   9539                 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[j]);
   9540             }
   9541             xmlRelaxNGFreeStates(ctxt, ctxt->states);
   9542             ctxt->states = NULL;
   9543             if (found == 0) {
   9544                 if (cur == NULL) {
   9545 		    VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA,
   9546 			       (const xmlChar *) "noname");
   9547                 } else {
   9548                     VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
   9549                 }
   9550                 ret = -1;
   9551                 ctxt->state = oldstate;
   9552                 goto done;
   9553             }
   9554         } else {
   9555             ret = -1;
   9556             break;
   9557         }
   9558         if (lasts[i] != NULL) {
   9559             lasts[i]->next = last;
   9560         }
   9561     }
   9562     if (ctxt->state != NULL)
   9563         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   9564     ctxt->state = oldstate;
   9565     ctxt->state->seq = lastelem;
   9566     if (ret != 0) {
   9567         VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
   9568         ret = -1;
   9569         goto done;
   9570     }
   9571 
   9572   done:
   9573     ctxt->flags = oldflags;
   9574     /*
   9575      * builds the next links chain from the prev one
   9576      */
   9577     cur = lastchg;
   9578     while (cur != NULL) {
   9579         if ((cur == start) || (cur->prev == NULL))
   9580             break;
   9581         cur->prev->next = cur;
   9582         cur = cur->prev;
   9583     }
   9584     if (ret == 0) {
   9585         if (ctxt->errNr > errNr)
   9586             xmlRelaxNGPopErrors(ctxt, errNr);
   9587     }
   9588 
   9589     xmlFree(list);
   9590     xmlFree(lasts);
   9591     return (ret);
   9592 }
   9593 
   9594 /**
   9595  * xmlRelaxNGValidateDefinitionList:
   9596  * @ctxt:  a Relax-NG validation context
   9597  * @define:  the list of definition to verify
   9598  *
   9599  * Validate the given node content against the (list) of definitions
   9600  *
   9601  * Returns 0 if the validation succeeded or an error code.
   9602  */
   9603 static int
   9604 xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt,
   9605                                  xmlRelaxNGDefinePtr defines)
   9606 {
   9607     int ret = 0, res;
   9608 
   9609 
   9610     if (defines == NULL) {
   9611         VALID_ERR2(XML_RELAXNG_ERR_INTERNAL,
   9612                    BAD_CAST "NULL definition list");
   9613         return (-1);
   9614     }
   9615     while (defines != NULL) {
   9616         if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
   9617             res = xmlRelaxNGValidateDefinition(ctxt, defines);
   9618             if (res < 0)
   9619                 ret = -1;
   9620         } else {
   9621             VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
   9622             return (-1);
   9623         }
   9624         if (res == -1)          /* continues on -2 */
   9625             break;
   9626         defines = defines->next;
   9627     }
   9628 
   9629     return (ret);
   9630 }
   9631 
   9632 /**
   9633  * xmlRelaxNGElementMatch:
   9634  * @ctxt:  a Relax-NG validation context
   9635  * @define:  the definition to check
   9636  * @elem:  the element
   9637  *
   9638  * Check if the element matches the definition nameClass
   9639  *
   9640  * Returns 1 if the element matches, 0 if no, or -1 in case of error
   9641  */
   9642 static int
   9643 xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
   9644                        xmlRelaxNGDefinePtr define, xmlNodePtr elem)
   9645 {
   9646     int ret = 0, oldflags = 0;
   9647 
   9648     if (define->name != NULL) {
   9649         if (!xmlStrEqual(elem->name, define->name)) {
   9650             VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name);
   9651             return (0);
   9652         }
   9653     }
   9654     if ((define->ns != NULL) && (define->ns[0] != 0)) {
   9655         if (elem->ns == NULL) {
   9656             VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name);
   9657             return (0);
   9658         } else if (!xmlStrEqual(elem->ns->href, define->ns)) {
   9659             VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS,
   9660                        elem->name, define->ns);
   9661             return (0);
   9662         }
   9663     } else if ((elem->ns != NULL) && (define->ns != NULL) &&
   9664                (define->name == NULL)) {
   9665         VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name);
   9666         return (0);
   9667     } else if ((elem->ns != NULL) && (define->name != NULL)) {
   9668         VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name);
   9669         return (0);
   9670     }
   9671 
   9672     if (define->nameClass == NULL)
   9673         return (1);
   9674 
   9675     define = define->nameClass;
   9676     if (define->type == XML_RELAXNG_EXCEPT) {
   9677         xmlRelaxNGDefinePtr list;
   9678 
   9679         if (ctxt != NULL) {
   9680             oldflags = ctxt->flags;
   9681             ctxt->flags |= FLAGS_IGNORABLE;
   9682         }
   9683 
   9684         list = define->content;
   9685         while (list != NULL) {
   9686             ret = xmlRelaxNGElementMatch(ctxt, list, elem);
   9687             if (ret == 1) {
   9688                 if (ctxt != NULL)
   9689                     ctxt->flags = oldflags;
   9690                 return (0);
   9691             }
   9692             if (ret < 0) {
   9693                 if (ctxt != NULL)
   9694                     ctxt->flags = oldflags;
   9695                 return (ret);
   9696             }
   9697             list = list->next;
   9698         }
   9699         ret = 1;
   9700         if (ctxt != NULL) {
   9701             ctxt->flags = oldflags;
   9702         }
   9703     } else if (define->type == XML_RELAXNG_CHOICE) {
   9704         xmlRelaxNGDefinePtr list;
   9705 
   9706         if (ctxt != NULL) {
   9707             oldflags = ctxt->flags;
   9708             ctxt->flags |= FLAGS_IGNORABLE;
   9709         }
   9710 
   9711         list = define->nameClass;
   9712         while (list != NULL) {
   9713             ret = xmlRelaxNGElementMatch(ctxt, list, elem);
   9714             if (ret == 1) {
   9715                 if (ctxt != NULL)
   9716                     ctxt->flags = oldflags;
   9717                 return (1);
   9718             }
   9719             if (ret < 0) {
   9720                 if (ctxt != NULL)
   9721                     ctxt->flags = oldflags;
   9722                 return (ret);
   9723             }
   9724             list = list->next;
   9725         }
   9726         if (ctxt != NULL) {
   9727             if (ret != 0) {
   9728                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
   9729                     xmlRelaxNGDumpValidError(ctxt);
   9730             } else {
   9731                 if (ctxt->errNr > 0)
   9732                     xmlRelaxNGPopErrors(ctxt, 0);
   9733             }
   9734         }
   9735         ret = 0;
   9736         if (ctxt != NULL) {
   9737             ctxt->flags = oldflags;
   9738         }
   9739     } else {
   9740         TODO ret = -1;
   9741     }
   9742     return (ret);
   9743 }
   9744 
   9745 /**
   9746  * xmlRelaxNGBestState:
   9747  * @ctxt:  a Relax-NG validation context
   9748  *
   9749  * Find the "best" state in the ctxt->states list of states to report
   9750  * errors about. I.e. a state with no element left in the child list
   9751  * or the one with the less attributes left.
   9752  * This is called only if a falidation error was detected
   9753  *
   9754  * Returns the index of the "best" state or -1 in case of error
   9755  */
   9756 static int
   9757 xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt)
   9758 {
   9759     xmlRelaxNGValidStatePtr state;
   9760     int i, tmp;
   9761     int best = -1;
   9762     int value = 1000000;
   9763 
   9764     if ((ctxt == NULL) || (ctxt->states == NULL) ||
   9765         (ctxt->states->nbState <= 0))
   9766         return (-1);
   9767 
   9768     for (i = 0; i < ctxt->states->nbState; i++) {
   9769         state = ctxt->states->tabState[i];
   9770         if (state == NULL)
   9771             continue;
   9772         if (state->seq != NULL) {
   9773             if ((best == -1) || (value > 100000)) {
   9774                 value = 100000;
   9775                 best = i;
   9776             }
   9777         } else {
   9778             tmp = state->nbAttrLeft;
   9779             if ((best == -1) || (value > tmp)) {
   9780                 value = tmp;
   9781                 best = i;
   9782             }
   9783         }
   9784     }
   9785     return (best);
   9786 }
   9787 
   9788 /**
   9789  * xmlRelaxNGLogBestError:
   9790  * @ctxt:  a Relax-NG validation context
   9791  *
   9792  * Find the "best" state in the ctxt->states list of states to report
   9793  * errors about and log it.
   9794  */
   9795 static void
   9796 xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt)
   9797 {
   9798     int best;
   9799 
   9800     if ((ctxt == NULL) || (ctxt->states == NULL) ||
   9801         (ctxt->states->nbState <= 0))
   9802         return;
   9803 
   9804     best = xmlRelaxNGBestState(ctxt);
   9805     if ((best >= 0) && (best < ctxt->states->nbState)) {
   9806         ctxt->state = ctxt->states->tabState[best];
   9807 
   9808         xmlRelaxNGValidateElementEnd(ctxt, 1);
   9809     }
   9810 }
   9811 
   9812 /**
   9813  * xmlRelaxNGValidateElementEnd:
   9814  * @ctxt:  a Relax-NG validation context
   9815  * @dolog:  indicate that error logging should be done
   9816  *
   9817  * Validate the end of the element, implements check that
   9818  * there is nothing left not consumed in the element content
   9819  * or in the attribute list.
   9820  *
   9821  * Returns 0 if the validation succeeded or an error code.
   9822  */
   9823 static int
   9824 xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int dolog)
   9825 {
   9826     int i;
   9827     xmlRelaxNGValidStatePtr state;
   9828 
   9829     state = ctxt->state;
   9830     if (state->seq != NULL) {
   9831         state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq);
   9832         if (state->seq != NULL) {
   9833             if (dolog) {
   9834                 VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT,
   9835                            state->node->name, state->seq->name);
   9836             }
   9837             return (-1);
   9838         }
   9839     }
   9840     for (i = 0; i < state->nbAttrs; i++) {
   9841         if (state->attrs[i] != NULL) {
   9842             if (dolog) {
   9843                 VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR,
   9844                            state->attrs[i]->name, state->node->name);
   9845             }
   9846             return (-1 - i);
   9847         }
   9848     }
   9849     return (0);
   9850 }
   9851 
   9852 /**
   9853  * xmlRelaxNGValidateState:
   9854  * @ctxt:  a Relax-NG validation context
   9855  * @define:  the definition to verify
   9856  *
   9857  * Validate the current state against the definition
   9858  *
   9859  * Returns 0 if the validation succeeded or an error code.
   9860  */
   9861 static int
   9862 xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
   9863                         xmlRelaxNGDefinePtr define)
   9864 {
   9865     xmlNodePtr node;
   9866     int ret = 0, i, tmp, oldflags, errNr;
   9867     xmlRelaxNGValidStatePtr oldstate = NULL, state;
   9868 
   9869     if (define == NULL) {
   9870         VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
   9871         return (-1);
   9872     }
   9873 
   9874     if (ctxt->state != NULL) {
   9875         node = ctxt->state->seq;
   9876     } else {
   9877         node = NULL;
   9878     }
   9879 #ifdef DEBUG
   9880     for (i = 0; i < ctxt->depth; i++)
   9881         xmlGenericError(xmlGenericErrorContext, " ");
   9882     xmlGenericError(xmlGenericErrorContext,
   9883                     "Start validating %s ", xmlRelaxNGDefName(define));
   9884     if (define->name != NULL)
   9885         xmlGenericError(xmlGenericErrorContext, "%s ", define->name);
   9886     if ((node != NULL) && (node->name != NULL))
   9887         xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name);
   9888     else
   9889         xmlGenericError(xmlGenericErrorContext, "\n");
   9890 #endif
   9891     ctxt->depth++;
   9892     switch (define->type) {
   9893         case XML_RELAXNG_EMPTY:
   9894             xmlRelaxNGSkipIgnored(ctxt, node);
   9895             ret = 0;
   9896             break;
   9897         case XML_RELAXNG_NOT_ALLOWED:
   9898             ret = -1;
   9899             break;
   9900         case XML_RELAXNG_TEXT:
   9901             while ((node != NULL) &&
   9902                    ((node->type == XML_TEXT_NODE) ||
   9903                     (node->type == XML_COMMENT_NODE) ||
   9904                     (node->type == XML_PI_NODE) ||
   9905                     (node->type == XML_CDATA_SECTION_NODE)))
   9906                 node = node->next;
   9907             ctxt->state->seq = node;
   9908             break;
   9909         case XML_RELAXNG_ELEMENT:
   9910             errNr = ctxt->errNr;
   9911             node = xmlRelaxNGSkipIgnored(ctxt, node);
   9912             if (node == NULL) {
   9913                 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name);
   9914                 ret = -1;
   9915                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
   9916                     xmlRelaxNGDumpValidError(ctxt);
   9917                 break;
   9918             }
   9919             if (node->type != XML_ELEMENT_NODE) {
   9920                 VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
   9921                 ret = -1;
   9922                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
   9923                     xmlRelaxNGDumpValidError(ctxt);
   9924                 break;
   9925             }
   9926             /*
   9927              * This node was already validated successfully against
   9928              * this definition.
   9929              */
   9930             if (node->psvi == define) {
   9931                 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
   9932                 if (ctxt->errNr > errNr)
   9933                     xmlRelaxNGPopErrors(ctxt, errNr);
   9934                 if (ctxt->errNr != 0) {
   9935                     while ((ctxt->err != NULL) &&
   9936                            (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME)
   9937                              && (xmlStrEqual(ctxt->err->arg2, node->name)))
   9938                             ||
   9939                             ((ctxt->err->err ==
   9940                               XML_RELAXNG_ERR_ELEMEXTRANS)
   9941                              && (xmlStrEqual(ctxt->err->arg1, node->name)))
   9942                             || (ctxt->err->err == XML_RELAXNG_ERR_NOELEM)
   9943                             || (ctxt->err->err ==
   9944                                 XML_RELAXNG_ERR_NOTELEM)))
   9945                         xmlRelaxNGValidErrorPop(ctxt);
   9946                 }
   9947                 break;
   9948             }
   9949 
   9950             ret = xmlRelaxNGElementMatch(ctxt, define, node);
   9951             if (ret <= 0) {
   9952                 ret = -1;
   9953                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
   9954                     xmlRelaxNGDumpValidError(ctxt);
   9955                 break;
   9956             }
   9957             ret = 0;
   9958             if (ctxt->errNr != 0) {
   9959                 if (ctxt->errNr > errNr)
   9960                     xmlRelaxNGPopErrors(ctxt, errNr);
   9961                 while ((ctxt->err != NULL) &&
   9962                        (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) &&
   9963                          (xmlStrEqual(ctxt->err->arg2, node->name))) ||
   9964                         ((ctxt->err->err == XML_RELAXNG_ERR_ELEMEXTRANS) &&
   9965                          (xmlStrEqual(ctxt->err->arg1, node->name))) ||
   9966                         (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) ||
   9967                         (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM)))
   9968                     xmlRelaxNGValidErrorPop(ctxt);
   9969             }
   9970             errNr = ctxt->errNr;
   9971 
   9972             oldflags = ctxt->flags;
   9973             if (ctxt->flags & FLAGS_MIXED_CONTENT) {
   9974                 ctxt->flags -= FLAGS_MIXED_CONTENT;
   9975             }
   9976             state = xmlRelaxNGNewValidState(ctxt, node);
   9977             if (state == NULL) {
   9978                 ret = -1;
   9979                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
   9980                     xmlRelaxNGDumpValidError(ctxt);
   9981                 break;
   9982             }
   9983 
   9984             oldstate = ctxt->state;
   9985             ctxt->state = state;
   9986             if (define->attrs != NULL) {
   9987                 tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
   9988                 if (tmp != 0) {
   9989                     ret = -1;
   9990                     VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
   9991                 }
   9992             }
   9993             if (define->contModel != NULL) {
   9994                 xmlRelaxNGValidStatePtr nstate, tmpstate = ctxt->state;
   9995                 xmlRelaxNGStatesPtr tmpstates = ctxt->states;
   9996                 xmlNodePtr nseq;
   9997 
   9998                 nstate = xmlRelaxNGNewValidState(ctxt, node);
   9999                 ctxt->state = nstate;
   10000                 ctxt->states = NULL;
   10001 
   10002                 tmp = xmlRelaxNGValidateCompiledContent(ctxt,
   10003                                                         define->contModel,
   10004                                                         ctxt->state->seq);
   10005                 nseq = ctxt->state->seq;
   10006                 ctxt->state = tmpstate;
   10007                 ctxt->states = tmpstates;
   10008                 xmlRelaxNGFreeValidState(ctxt, nstate);
   10009 
   10010 #ifdef DEBUG_COMPILE
   10011                 xmlGenericError(xmlGenericErrorContext,
   10012                                 "Validating content of '%s' : %d\n",
   10013                                 define->name, tmp);
   10014 #endif
   10015                 if (tmp != 0)
   10016                     ret = -1;
   10017 
   10018                 if (ctxt->states != NULL) {
   10019                     tmp = -1;
   10020 
   10021                     for (i = 0; i < ctxt->states->nbState; i++) {
   10022                         state = ctxt->states->tabState[i];
   10023                         ctxt->state = state;
   10024                         ctxt->state->seq = nseq;
   10025 
   10026                         if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
   10027                             tmp = 0;
   10028                             break;
   10029                         }
   10030                     }
   10031                     if (tmp != 0) {
   10032                         /*
   10033                          * validation error, log the message for the "best" one
   10034                          */
   10035                         ctxt->flags |= FLAGS_IGNORABLE;
   10036                         xmlRelaxNGLogBestError(ctxt);
   10037                     }
   10038                     for (i = 0; i < ctxt->states->nbState; i++) {
   10039                         xmlRelaxNGFreeValidState(ctxt,
   10040                                                  ctxt->states->
   10041                                                  tabState[i]);
   10042                     }
   10043                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
   10044                     ctxt->flags = oldflags;
   10045                     ctxt->states = NULL;
   10046                     if ((ret == 0) && (tmp == -1))
   10047                         ret = -1;
   10048                 } else {
   10049                     state = ctxt->state;
   10050 		    if (ctxt->state != NULL)
   10051 			ctxt->state->seq = nseq;
   10052                     if (ret == 0)
   10053                         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
   10054                     xmlRelaxNGFreeValidState(ctxt, state);
   10055                 }
   10056             } else {
   10057                 if (define->content != NULL) {
   10058                     tmp = xmlRelaxNGValidateDefinitionList(ctxt,
   10059                                                            define->
   10060                                                            content);
   10061                     if (tmp != 0) {
   10062                         ret = -1;
   10063                         if (ctxt->state == NULL) {
   10064                             ctxt->state = oldstate;
   10065                             VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
   10066                                        node->name);
   10067                             ctxt->state = NULL;
   10068                         } else {
   10069                             VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
   10070                                        node->name);
   10071                         }
   10072 
   10073                     }
   10074                 }
   10075                 if (ctxt->states != NULL) {
   10076                     tmp = -1;
   10077 
   10078                     for (i = 0; i < ctxt->states->nbState; i++) {
   10079                         state = ctxt->states->tabState[i];
   10080                         ctxt->state = state;
   10081 
   10082                         if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
   10083                             tmp = 0;
   10084                             break;
   10085                         }
   10086                     }
   10087                     if (tmp != 0) {
   10088                         /*
   10089                          * validation error, log the message for the "best" one
   10090                          */
   10091                         ctxt->flags |= FLAGS_IGNORABLE;
   10092                         xmlRelaxNGLogBestError(ctxt);
   10093                     }
   10094                     for (i = 0; i < ctxt->states->nbState; i++) {
   10095                         xmlRelaxNGFreeValidState(ctxt,
   10096                                                  ctxt->states->tabState[i]);
   10097                         ctxt->states->tabState[i] = NULL;
   10098                     }
   10099                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
   10100                     ctxt->flags = oldflags;
   10101                     ctxt->states = NULL;
   10102                     if ((ret == 0) && (tmp == -1))
   10103                         ret = -1;
   10104                 } else {
   10105                     state = ctxt->state;
   10106                     if (ret == 0)
   10107                         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
   10108                     xmlRelaxNGFreeValidState(ctxt, state);
   10109                 }
   10110             }
   10111             if (ret == 0) {
   10112                 node->psvi = define;
   10113             }
   10114             ctxt->flags = oldflags;
   10115             ctxt->state = oldstate;
   10116             if (oldstate != NULL)
   10117                 oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
   10118             if (ret != 0) {
   10119                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
   10120                     xmlRelaxNGDumpValidError(ctxt);
   10121                     ret = 0;
   10122 #if 0
   10123                 } else {
   10124                     ret = -2;
   10125 #endif
   10126                 }
   10127             } else {
   10128                 if (ctxt->errNr > errNr)
   10129                     xmlRelaxNGPopErrors(ctxt, errNr);
   10130             }
   10131 
   10132 #ifdef DEBUG
   10133             xmlGenericError(xmlGenericErrorContext,
   10134                             "xmlRelaxNGValidateDefinition(): validated %s : %d",
   10135                             node->name, ret);
   10136             if (oldstate == NULL)
   10137                 xmlGenericError(xmlGenericErrorContext, ": no state\n");
   10138             else if (oldstate->seq == NULL)
   10139                 xmlGenericError(xmlGenericErrorContext, ": done\n");
   10140             else if (oldstate->seq->type == XML_ELEMENT_NODE)
   10141                 xmlGenericError(xmlGenericErrorContext, ": next elem %s\n",
   10142                                 oldstate->seq->name);
   10143             else
   10144                 xmlGenericError(xmlGenericErrorContext, ": next %s %d\n",
   10145                                 oldstate->seq->name, oldstate->seq->type);
   10146 #endif
   10147             break;
   10148         case XML_RELAXNG_OPTIONAL:{
   10149                 errNr = ctxt->errNr;
   10150                 oldflags = ctxt->flags;
   10151                 ctxt->flags |= FLAGS_IGNORABLE;
   10152                 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
   10153                 ret =
   10154                     xmlRelaxNGValidateDefinitionList(ctxt,
   10155                                                      define->content);
   10156                 if (ret != 0) {
   10157                     if (ctxt->state != NULL)
   10158                         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10159                     ctxt->state = oldstate;
   10160                     ctxt->flags = oldflags;
   10161                     ret = 0;
   10162                     if (ctxt->errNr > errNr)
   10163                         xmlRelaxNGPopErrors(ctxt, errNr);
   10164                     break;
   10165                 }
   10166                 if (ctxt->states != NULL) {
   10167                     xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
   10168                 } else {
   10169                     ctxt->states = xmlRelaxNGNewStates(ctxt, 1);
   10170                     if (ctxt->states == NULL) {
   10171                         xmlRelaxNGFreeValidState(ctxt, oldstate);
   10172                         ctxt->flags = oldflags;
   10173                         ret = -1;
   10174                         if (ctxt->errNr > errNr)
   10175                             xmlRelaxNGPopErrors(ctxt, errNr);
   10176                         break;
   10177                     }
   10178                     xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
   10179                     xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state);
   10180                     ctxt->state = NULL;
   10181                 }
   10182                 ctxt->flags = oldflags;
   10183                 ret = 0;
   10184                 if (ctxt->errNr > errNr)
   10185                     xmlRelaxNGPopErrors(ctxt, errNr);
   10186                 break;
   10187             }
   10188         case XML_RELAXNG_ONEORMORE:
   10189             errNr = ctxt->errNr;
   10190             ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
   10191             if (ret != 0) {
   10192                 break;
   10193             }
   10194             if (ctxt->errNr > errNr)
   10195                 xmlRelaxNGPopErrors(ctxt, errNr);
   10196             /* Falls through. */
   10197         case XML_RELAXNG_ZEROORMORE:{
   10198                 int progress;
   10199                 xmlRelaxNGStatesPtr states = NULL, res = NULL;
   10200                 int base, j;
   10201 
   10202                 errNr = ctxt->errNr;
   10203                 res = xmlRelaxNGNewStates(ctxt, 1);
   10204                 if (res == NULL) {
   10205                     ret = -1;
   10206                     break;
   10207                 }
   10208                 /*
   10209                  * All the input states are also exit states
   10210                  */
   10211                 if (ctxt->state != NULL) {
   10212                     xmlRelaxNGAddStates(ctxt, res,
   10213                                         xmlRelaxNGCopyValidState(ctxt,
   10214                                                                  ctxt->
   10215                                                                  state));
   10216                 } else {
   10217                     for (j = 0; j < ctxt->states->nbState; j++) {
   10218                         xmlRelaxNGAddStates(ctxt, res,
   10219                             xmlRelaxNGCopyValidState(ctxt,
   10220                                             ctxt->states->tabState[j]));
   10221                     }
   10222                 }
   10223                 oldflags = ctxt->flags;
   10224                 ctxt->flags |= FLAGS_IGNORABLE;
   10225                 do {
   10226                     progress = 0;
   10227                     base = res->nbState;
   10228 
   10229                     if (ctxt->states != NULL) {
   10230                         states = ctxt->states;
   10231                         for (i = 0; i < states->nbState; i++) {
   10232                             ctxt->state = states->tabState[i];
   10233                             ctxt->states = NULL;
   10234                             ret = xmlRelaxNGValidateDefinitionList(ctxt,
   10235                                                                    define->
   10236                                                                    content);
   10237                             if (ret == 0) {
   10238                                 if (ctxt->state != NULL) {
   10239                                     tmp = xmlRelaxNGAddStates(ctxt, res,
   10240                                                               ctxt->state);
   10241                                     ctxt->state = NULL;
   10242                                     if (tmp == 1)
   10243                                         progress = 1;
   10244                                 } else if (ctxt->states != NULL) {
   10245                                     for (j = 0; j < ctxt->states->nbState;
   10246                                          j++) {
   10247                                         tmp =
   10248                                             xmlRelaxNGAddStates(ctxt, res,
   10249                                                    ctxt->states->tabState[j]);
   10250                                         if (tmp == 1)
   10251                                             progress = 1;
   10252                                     }
   10253                                     xmlRelaxNGFreeStates(ctxt,
   10254                                                          ctxt->states);
   10255                                     ctxt->states = NULL;
   10256                                 }
   10257                             } else {
   10258                                 if (ctxt->state != NULL) {
   10259                                     xmlRelaxNGFreeValidState(ctxt,
   10260                                                              ctxt->state);
   10261                                     ctxt->state = NULL;
   10262                                 }
   10263                             }
   10264                         }
   10265                     } else {
   10266                         ret = xmlRelaxNGValidateDefinitionList(ctxt,
   10267                                                                define->
   10268                                                                content);
   10269                         if (ret != 0) {
   10270                             xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10271                             ctxt->state = NULL;
   10272                         } else {
   10273                             base = res->nbState;
   10274                             if (ctxt->state != NULL) {
   10275                                 tmp = xmlRelaxNGAddStates(ctxt, res,
   10276                                                           ctxt->state);
   10277                                 ctxt->state = NULL;
   10278                                 if (tmp == 1)
   10279                                     progress = 1;
   10280                             } else if (ctxt->states != NULL) {
   10281                                 for (j = 0; j < ctxt->states->nbState; j++) {
   10282                                     tmp = xmlRelaxNGAddStates(ctxt, res,
   10283                                                ctxt->states->tabState[j]);
   10284                                     if (tmp == 1)
   10285                                         progress = 1;
   10286                                 }
   10287                                 if (states == NULL) {
   10288                                     states = ctxt->states;
   10289                                 } else {
   10290                                     xmlRelaxNGFreeStates(ctxt,
   10291                                                          ctxt->states);
   10292                                 }
   10293                                 ctxt->states = NULL;
   10294                             }
   10295                         }
   10296                     }
   10297                     if (progress) {
   10298                         /*
   10299                          * Collect all the new nodes added at that step
   10300                          * and make them the new node set
   10301                          */
   10302                         if (res->nbState - base == 1) {
   10303                             ctxt->state = xmlRelaxNGCopyValidState(ctxt,
   10304                                                                    res->
   10305                                                                    tabState
   10306                                                                    [base]);
   10307                         } else {
   10308                             if (states == NULL) {
   10309                                 xmlRelaxNGNewStates(ctxt,
   10310                                                     res->nbState - base);
   10311 			        states = ctxt->states;
   10312 				if (states == NULL) {
   10313 				    progress = 0;
   10314 				    break;
   10315 				}
   10316                             }
   10317                             states->nbState = 0;
   10318                             for (i = base; i < res->nbState; i++)
   10319                                 xmlRelaxNGAddStates(ctxt, states,
   10320                                                     xmlRelaxNGCopyValidState
   10321                                                     (ctxt, res->tabState[i]));
   10322                             ctxt->states = states;
   10323                         }
   10324                     }
   10325                 } while (progress == 1);
   10326                 if (states != NULL) {
   10327                     xmlRelaxNGFreeStates(ctxt, states);
   10328                 }
   10329                 ctxt->states = res;
   10330                 ctxt->flags = oldflags;
   10331 #if 0
   10332                 /*
   10333                  * errors may have to be propagated back...
   10334                  */
   10335                 if (ctxt->errNr > errNr)
   10336                     xmlRelaxNGPopErrors(ctxt, errNr);
   10337 #endif
   10338                 ret = 0;
   10339                 break;
   10340             }
   10341         case XML_RELAXNG_CHOICE:{
   10342                 xmlRelaxNGDefinePtr list = NULL;
   10343                 xmlRelaxNGStatesPtr states = NULL;
   10344 
   10345                 node = xmlRelaxNGSkipIgnored(ctxt, node);
   10346 
   10347                 errNr = ctxt->errNr;
   10348                 if ((define->dflags & IS_TRIABLE) && (define->data != NULL) &&
   10349 		    (node != NULL)) {
   10350 		    /*
   10351 		     * node == NULL can't be optimized since IS_TRIABLE
   10352 		     * doesn't account for choice which may lead to
   10353 		     * only attributes.
   10354 		     */
   10355                     xmlHashTablePtr triage =
   10356                         (xmlHashTablePtr) define->data;
   10357 
   10358                     /*
   10359                      * Something we can optimize cleanly there is only one
   10360                      * possble branch out !
   10361                      */
   10362                     if ((node->type == XML_TEXT_NODE) ||
   10363                         (node->type == XML_CDATA_SECTION_NODE)) {
   10364                         list =
   10365                             xmlHashLookup2(triage, BAD_CAST "#text", NULL);
   10366                     } else if (node->type == XML_ELEMENT_NODE) {
   10367                         if (node->ns != NULL) {
   10368                             list = xmlHashLookup2(triage, node->name,
   10369                                                   node->ns->href);
   10370                             if (list == NULL)
   10371                                 list =
   10372                                     xmlHashLookup2(triage, BAD_CAST "#any",
   10373                                                    node->ns->href);
   10374                         } else
   10375                             list =
   10376                                 xmlHashLookup2(triage, node->name, NULL);
   10377                         if (list == NULL)
   10378                             list =
   10379                                 xmlHashLookup2(triage, BAD_CAST "#any",
   10380                                                NULL);
   10381                     }
   10382                     if (list == NULL) {
   10383                         ret = -1;
   10384 			VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, node->name);
   10385                         break;
   10386                     }
   10387                     ret = xmlRelaxNGValidateDefinition(ctxt, list);
   10388                     if (ret == 0) {
   10389                     }
   10390                     break;
   10391                 }
   10392 
   10393                 list = define->content;
   10394                 oldflags = ctxt->flags;
   10395                 ctxt->flags |= FLAGS_IGNORABLE;
   10396 
   10397                 while (list != NULL) {
   10398                     oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
   10399                     ret = xmlRelaxNGValidateDefinition(ctxt, list);
   10400                     if (ret == 0) {
   10401                         if (states == NULL) {
   10402                             states = xmlRelaxNGNewStates(ctxt, 1);
   10403                         }
   10404                         if (ctxt->state != NULL) {
   10405                             xmlRelaxNGAddStates(ctxt, states, ctxt->state);
   10406                         } else if (ctxt->states != NULL) {
   10407                             for (i = 0; i < ctxt->states->nbState; i++) {
   10408                                 xmlRelaxNGAddStates(ctxt, states,
   10409                                                     ctxt->states->
   10410                                                     tabState[i]);
   10411                             }
   10412                             xmlRelaxNGFreeStates(ctxt, ctxt->states);
   10413                             ctxt->states = NULL;
   10414                         }
   10415                     } else {
   10416                         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10417                     }
   10418                     ctxt->state = oldstate;
   10419                     list = list->next;
   10420                 }
   10421                 if (states != NULL) {
   10422                     xmlRelaxNGFreeValidState(ctxt, oldstate);
   10423                     ctxt->states = states;
   10424                     ctxt->state = NULL;
   10425                     ret = 0;
   10426                 } else {
   10427                     ctxt->states = NULL;
   10428                 }
   10429                 ctxt->flags = oldflags;
   10430                 if (ret != 0) {
   10431                     if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
   10432                         xmlRelaxNGDumpValidError(ctxt);
   10433                     }
   10434                 } else {
   10435                     if (ctxt->errNr > errNr)
   10436                         xmlRelaxNGPopErrors(ctxt, errNr);
   10437                 }
   10438                 break;
   10439             }
   10440         case XML_RELAXNG_DEF:
   10441         case XML_RELAXNG_GROUP:
   10442             ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
   10443             break;
   10444         case XML_RELAXNG_INTERLEAVE:
   10445             ret = xmlRelaxNGValidateInterleave(ctxt, define);
   10446             break;
   10447         case XML_RELAXNG_ATTRIBUTE:
   10448             ret = xmlRelaxNGValidateAttribute(ctxt, define);
   10449             break;
   10450         case XML_RELAXNG_START:
   10451         case XML_RELAXNG_NOOP:
   10452         case XML_RELAXNG_REF:
   10453         case XML_RELAXNG_EXTERNALREF:
   10454         case XML_RELAXNG_PARENTREF:
   10455             ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
   10456             break;
   10457         case XML_RELAXNG_DATATYPE:{
   10458                 xmlNodePtr child;
   10459                 xmlChar *content = NULL;
   10460 
   10461                 child = node;
   10462                 while (child != NULL) {
   10463                     if (child->type == XML_ELEMENT_NODE) {
   10464                         VALID_ERR2(XML_RELAXNG_ERR_DATAELEM,
   10465                                    node->parent->name);
   10466                         ret = -1;
   10467                         break;
   10468                     } else if ((child->type == XML_TEXT_NODE) ||
   10469                                (child->type == XML_CDATA_SECTION_NODE)) {
   10470                         content = xmlStrcat(content, child->content);
   10471                     }
   10472                     /* TODO: handle entities ... */
   10473                     child = child->next;
   10474                 }
   10475                 if (ret == -1) {
   10476                     if (content != NULL)
   10477                         xmlFree(content);
   10478                     break;
   10479                 }
   10480                 if (content == NULL) {
   10481                     content = xmlStrdup(BAD_CAST "");
   10482                     if (content == NULL) {
   10483                         xmlRngVErrMemory(ctxt, "validating\n");
   10484                         ret = -1;
   10485                         break;
   10486                     }
   10487                 }
   10488                 ret = xmlRelaxNGValidateDatatype(ctxt, content, define,
   10489                                                  ctxt->state->seq);
   10490                 if (ret == -1) {
   10491                     VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name);
   10492                 } else if (ret == 0) {
   10493                     ctxt->state->seq = NULL;
   10494                 }
   10495                 if (content != NULL)
   10496                     xmlFree(content);
   10497                 break;
   10498             }
   10499         case XML_RELAXNG_VALUE:{
   10500                 xmlChar *content = NULL;
   10501                 xmlChar *oldvalue;
   10502                 xmlNodePtr child;
   10503 
   10504                 child = node;
   10505                 while (child != NULL) {
   10506                     if (child->type == XML_ELEMENT_NODE) {
   10507                         VALID_ERR2(XML_RELAXNG_ERR_VALELEM,
   10508                                    node->parent->name);
   10509                         ret = -1;
   10510                         break;
   10511                     } else if ((child->type == XML_TEXT_NODE) ||
   10512                                (child->type == XML_CDATA_SECTION_NODE)) {
   10513                         content = xmlStrcat(content, child->content);
   10514                     }
   10515                     /* TODO: handle entities ... */
   10516                     child = child->next;
   10517                 }
   10518                 if (ret == -1) {
   10519                     if (content != NULL)
   10520                         xmlFree(content);
   10521                     break;
   10522                 }
   10523                 if (content == NULL) {
   10524                     content = xmlStrdup(BAD_CAST "");
   10525                     if (content == NULL) {
   10526                         xmlRngVErrMemory(ctxt, "validating\n");
   10527                         ret = -1;
   10528                         break;
   10529                     }
   10530                 }
   10531                 oldvalue = ctxt->state->value;
   10532                 ctxt->state->value = content;
   10533                 ret = xmlRelaxNGValidateValue(ctxt, define);
   10534                 ctxt->state->value = oldvalue;
   10535                 if (ret == -1) {
   10536                     VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name);
   10537                 } else if (ret == 0) {
   10538                     ctxt->state->seq = NULL;
   10539                 }
   10540                 if (content != NULL)
   10541                     xmlFree(content);
   10542                 break;
   10543             }
   10544         case XML_RELAXNG_LIST:{
   10545                 xmlChar *content;
   10546                 xmlNodePtr child;
   10547                 xmlChar *oldvalue, *oldendvalue;
   10548                 int len;
   10549 
   10550                 /*
   10551                  * Make sure it's only text nodes
   10552                  */
   10553 
   10554                 content = NULL;
   10555                 child = node;
   10556                 while (child != NULL) {
   10557                     if (child->type == XML_ELEMENT_NODE) {
   10558                         VALID_ERR2(XML_RELAXNG_ERR_LISTELEM,
   10559                                    node->parent->name);
   10560                         ret = -1;
   10561                         break;
   10562                     } else if ((child->type == XML_TEXT_NODE) ||
   10563                                (child->type == XML_CDATA_SECTION_NODE)) {
   10564                         content = xmlStrcat(content, child->content);
   10565                     }
   10566                     /* TODO: handle entities ... */
   10567                     child = child->next;
   10568                 }
   10569                 if (ret == -1) {
   10570                     if (content != NULL)
   10571                         xmlFree(content);
   10572                     break;
   10573                 }
   10574                 if (content == NULL) {
   10575                     content = xmlStrdup(BAD_CAST "");
   10576                     if (content == NULL) {
   10577                         xmlRngVErrMemory(ctxt, "validating\n");
   10578                         ret = -1;
   10579                         break;
   10580                     }
   10581                 }
   10582                 len = xmlStrlen(content);
   10583                 oldvalue = ctxt->state->value;
   10584                 oldendvalue = ctxt->state->endvalue;
   10585                 ctxt->state->value = content;
   10586                 ctxt->state->endvalue = content + len;
   10587                 ret = xmlRelaxNGValidateValue(ctxt, define);
   10588                 ctxt->state->value = oldvalue;
   10589                 ctxt->state->endvalue = oldendvalue;
   10590                 if (ret == -1) {
   10591                     VALID_ERR(XML_RELAXNG_ERR_LIST);
   10592                 } else if ((ret == 0) && (node != NULL)) {
   10593                     ctxt->state->seq = node->next;
   10594                 }
   10595                 if (content != NULL)
   10596                     xmlFree(content);
   10597                 break;
   10598             }
   10599         case XML_RELAXNG_EXCEPT:
   10600         case XML_RELAXNG_PARAM:
   10601             TODO ret = -1;
   10602             break;
   10603     }
   10604     ctxt->depth--;
   10605 #ifdef DEBUG
   10606     for (i = 0; i < ctxt->depth; i++)
   10607         xmlGenericError(xmlGenericErrorContext, " ");
   10608     xmlGenericError(xmlGenericErrorContext,
   10609                     "Validating %s ", xmlRelaxNGDefName(define));
   10610     if (define->name != NULL)
   10611         xmlGenericError(xmlGenericErrorContext, "%s ", define->name);
   10612     if (ret == 0)
   10613         xmlGenericError(xmlGenericErrorContext, "suceeded\n");
   10614     else
   10615         xmlGenericError(xmlGenericErrorContext, "failed\n");
   10616 #endif
   10617     return (ret);
   10618 }
   10619 
   10620 /**
   10621  * xmlRelaxNGValidateDefinition:
   10622  * @ctxt:  a Relax-NG validation context
   10623  * @define:  the definition to verify
   10624  *
   10625  * Validate the current node lists against the definition
   10626  *
   10627  * Returns 0 if the validation succeeded or an error code.
   10628  */
   10629 static int
   10630 xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
   10631                              xmlRelaxNGDefinePtr define)
   10632 {
   10633     xmlRelaxNGStatesPtr states, res;
   10634     int i, j, k, ret, oldflags;
   10635 
   10636     /*
   10637      * We should NOT have both ctxt->state and ctxt->states
   10638      */
   10639     if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
   10640         TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10641         ctxt->state = NULL;
   10642     }
   10643 
   10644     if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) {
   10645         if (ctxt->states != NULL) {
   10646             ctxt->state = ctxt->states->tabState[0];
   10647             xmlRelaxNGFreeStates(ctxt, ctxt->states);
   10648             ctxt->states = NULL;
   10649         }
   10650         ret = xmlRelaxNGValidateState(ctxt, define);
   10651         if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
   10652             TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10653             ctxt->state = NULL;
   10654         }
   10655         if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) {
   10656             ctxt->state = ctxt->states->tabState[0];
   10657             xmlRelaxNGFreeStates(ctxt, ctxt->states);
   10658             ctxt->states = NULL;
   10659         }
   10660         return (ret);
   10661     }
   10662 
   10663     states = ctxt->states;
   10664     ctxt->states = NULL;
   10665     res = NULL;
   10666     j = 0;
   10667     oldflags = ctxt->flags;
   10668     ctxt->flags |= FLAGS_IGNORABLE;
   10669     for (i = 0; i < states->nbState; i++) {
   10670         ctxt->state = states->tabState[i];
   10671         ctxt->states = NULL;
   10672         ret = xmlRelaxNGValidateState(ctxt, define);
   10673         /*
   10674          * We should NOT have both ctxt->state and ctxt->states
   10675          */
   10676         if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
   10677             TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10678             ctxt->state = NULL;
   10679         }
   10680         if (ret == 0) {
   10681             if (ctxt->states == NULL) {
   10682                 if (res != NULL) {
   10683                     /* add the state to the container */
   10684                     xmlRelaxNGAddStates(ctxt, res, ctxt->state);
   10685                     ctxt->state = NULL;
   10686                 } else {
   10687                     /* add the state directly in states */
   10688                     states->tabState[j++] = ctxt->state;
   10689                     ctxt->state = NULL;
   10690                 }
   10691             } else {
   10692                 if (res == NULL) {
   10693                     /* make it the new container and copy other results */
   10694                     res = ctxt->states;
   10695                     ctxt->states = NULL;
   10696                     for (k = 0; k < j; k++)
   10697                         xmlRelaxNGAddStates(ctxt, res,
   10698                                             states->tabState[k]);
   10699                 } else {
   10700                     /* add all the new results to res and reff the container */
   10701                     for (k = 0; k < ctxt->states->nbState; k++)
   10702                         xmlRelaxNGAddStates(ctxt, res,
   10703                                             ctxt->states->tabState[k]);
   10704                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
   10705                     ctxt->states = NULL;
   10706                 }
   10707             }
   10708         } else {
   10709             if (ctxt->state != NULL) {
   10710                 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10711                 ctxt->state = NULL;
   10712             } else if (ctxt->states != NULL) {
   10713                 for (k = 0; k < ctxt->states->nbState; k++)
   10714                     xmlRelaxNGFreeValidState(ctxt,
   10715                                              ctxt->states->tabState[k]);
   10716                 xmlRelaxNGFreeStates(ctxt, ctxt->states);
   10717                 ctxt->states = NULL;
   10718             }
   10719         }
   10720     }
   10721     ctxt->flags = oldflags;
   10722     if (res != NULL) {
   10723         xmlRelaxNGFreeStates(ctxt, states);
   10724         ctxt->states = res;
   10725         ret = 0;
   10726     } else if (j > 1) {
   10727         states->nbState = j;
   10728         ctxt->states = states;
   10729         ret = 0;
   10730     } else if (j == 1) {
   10731         ctxt->state = states->tabState[0];
   10732         xmlRelaxNGFreeStates(ctxt, states);
   10733         ret = 0;
   10734     } else {
   10735         ret = -1;
   10736         xmlRelaxNGFreeStates(ctxt, states);
   10737         if (ctxt->states != NULL) {
   10738             xmlRelaxNGFreeStates(ctxt, ctxt->states);
   10739             ctxt->states = NULL;
   10740         }
   10741     }
   10742     if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
   10743         TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10744         ctxt->state = NULL;
   10745     }
   10746     return (ret);
   10747 }
   10748 
   10749 /**
   10750  * xmlRelaxNGValidateDocument:
   10751  * @ctxt:  a Relax-NG validation context
   10752  * @doc:  the document
   10753  *
   10754  * Validate the given document
   10755  *
   10756  * Returns 0 if the validation succeeded or an error code.
   10757  */
   10758 static int
   10759 xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
   10760 {
   10761     int ret;
   10762     xmlRelaxNGPtr schema;
   10763     xmlRelaxNGGrammarPtr grammar;
   10764     xmlRelaxNGValidStatePtr state;
   10765     xmlNodePtr node;
   10766 
   10767     if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL))
   10768         return (-1);
   10769 
   10770     ctxt->errNo = XML_RELAXNG_OK;
   10771     schema = ctxt->schema;
   10772     grammar = schema->topgrammar;
   10773     if (grammar == NULL) {
   10774         VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
   10775         return (-1);
   10776     }
   10777     state = xmlRelaxNGNewValidState(ctxt, NULL);
   10778     ctxt->state = state;
   10779     ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start);
   10780     if ((ctxt->state != NULL) && (state->seq != NULL)) {
   10781         state = ctxt->state;
   10782         node = state->seq;
   10783         node = xmlRelaxNGSkipIgnored(ctxt, node);
   10784         if (node != NULL) {
   10785             if (ret != -1) {
   10786                 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
   10787                 ret = -1;
   10788             }
   10789         }
   10790     } else if (ctxt->states != NULL) {
   10791         int i;
   10792         int tmp = -1;
   10793 
   10794         for (i = 0; i < ctxt->states->nbState; i++) {
   10795             state = ctxt->states->tabState[i];
   10796             node = state->seq;
   10797             node = xmlRelaxNGSkipIgnored(ctxt, node);
   10798             if (node == NULL)
   10799                 tmp = 0;
   10800             xmlRelaxNGFreeValidState(ctxt, state);
   10801         }
   10802         if (tmp == -1) {
   10803             if (ret != -1) {
   10804                 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
   10805                 ret = -1;
   10806             }
   10807         }
   10808     }
   10809     if (ctxt->state != NULL) {
   10810         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
   10811         ctxt->state = NULL;
   10812     }
   10813     if (ret != 0)
   10814         xmlRelaxNGDumpValidError(ctxt);
   10815 #ifdef DEBUG
   10816     else if (ctxt->errNr != 0) {
   10817         ctxt->error(ctxt->userData,
   10818                     "%d Extra error messages left on stack !\n",
   10819                     ctxt->errNr);
   10820         xmlRelaxNGDumpValidError(ctxt);
   10821     }
   10822 #endif
   10823 #ifdef LIBXML_VALID_ENABLED
   10824     if (ctxt->idref == 1) {
   10825         xmlValidCtxt vctxt;
   10826 
   10827         memset(&vctxt, 0, sizeof(xmlValidCtxt));
   10828         vctxt.valid = 1;
   10829         vctxt.error = ctxt->error;
   10830         vctxt.warning = ctxt->warning;
   10831         vctxt.userData = ctxt->userData;
   10832 
   10833         if (xmlValidateDocumentFinal(&vctxt, doc) != 1)
   10834             ret = -1;
   10835     }
   10836 #endif /* LIBXML_VALID_ENABLED */
   10837     if ((ret == 0) && (ctxt->errNo != XML_RELAXNG_OK))
   10838         ret = -1;
   10839 
   10840     return (ret);
   10841 }
   10842 
   10843 /**
   10844  * xmlRelaxNGCleanPSVI:
   10845  * @node:  an input element or document
   10846  *
   10847  * Call this routine to speed up XPath computation on static documents.
   10848  * This stamps all the element nodes with the document order
   10849  * Like for line information, the order is kept in the element->content
   10850  * field, the value stored is actually - the node number (starting at -1)
   10851  * to be able to differentiate from line numbers.
   10852  *
   10853  * Returns the number of elements found in the document or -1 in case
   10854  *    of error.
   10855  */
   10856 static void
   10857 xmlRelaxNGCleanPSVI(xmlNodePtr node) {
   10858     xmlNodePtr cur;
   10859 
   10860     if ((node == NULL) ||
   10861         ((node->type != XML_ELEMENT_NODE) &&
   10862          (node->type != XML_DOCUMENT_NODE) &&
   10863          (node->type != XML_HTML_DOCUMENT_NODE)))
   10864 	return;
   10865     if (node->type == XML_ELEMENT_NODE)
   10866         node->psvi = NULL;
   10867 
   10868     cur = node->children;
   10869     while (cur != NULL) {
   10870 	if (cur->type == XML_ELEMENT_NODE) {
   10871 	    cur->psvi = NULL;
   10872 	    if (cur->children != NULL) {
   10873 		cur = cur->children;
   10874 		continue;
   10875 	    }
   10876 	}
   10877 	if (cur->next != NULL) {
   10878 	    cur = cur->next;
   10879 	    continue;
   10880 	}
   10881 	do {
   10882 	    cur = cur->parent;
   10883 	    if (cur == NULL)
   10884 		break;
   10885 	    if (cur == node) {
   10886 		cur = NULL;
   10887 		break;
   10888 	    }
   10889 	    if (cur->next != NULL) {
   10890 		cur = cur->next;
   10891 		break;
   10892 	    }
   10893 	} while (cur != NULL);
   10894     }
   10895     return;
   10896 }
   10897 /************************************************************************
   10898  *									*
   10899  *			Validation interfaces				*
   10900  *									*
   10901  ************************************************************************/
   10902 
   10903 /**
   10904  * xmlRelaxNGNewValidCtxt:
   10905  * @schema:  a precompiled XML RelaxNGs
   10906  *
   10907  * Create an XML RelaxNGs validation context based on the given schema
   10908  *
   10909  * Returns the validation context or NULL in case of error
   10910  */
   10911 xmlRelaxNGValidCtxtPtr
   10912 xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema)
   10913 {
   10914     xmlRelaxNGValidCtxtPtr ret;
   10915 
   10916     ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt));
   10917     if (ret == NULL) {
   10918         xmlRngVErrMemory(NULL, "building context\n");
   10919         return (NULL);
   10920     }
   10921     memset(ret, 0, sizeof(xmlRelaxNGValidCtxt));
   10922     ret->schema = schema;
   10923     ret->error = xmlGenericError;
   10924     ret->userData = xmlGenericErrorContext;
   10925     ret->errNr = 0;
   10926     ret->errMax = 0;
   10927     ret->err = NULL;
   10928     ret->errTab = NULL;
   10929     if (schema != NULL)
   10930 	ret->idref = schema->idref;
   10931     ret->states = NULL;
   10932     ret->freeState = NULL;
   10933     ret->freeStates = NULL;
   10934     ret->errNo = XML_RELAXNG_OK;
   10935     return (ret);
   10936 }
   10937 
   10938 /**
   10939  * xmlRelaxNGFreeValidCtxt:
   10940  * @ctxt:  the schema validation context
   10941  *
   10942  * Free the resources associated to the schema validation context
   10943  */
   10944 void
   10945 xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt)
   10946 {
   10947     int k;
   10948 
   10949     if (ctxt == NULL)
   10950         return;
   10951     if (ctxt->states != NULL)
   10952         xmlRelaxNGFreeStates(NULL, ctxt->states);
   10953     if (ctxt->freeState != NULL) {
   10954         for (k = 0; k < ctxt->freeState->nbState; k++) {
   10955             xmlRelaxNGFreeValidState(NULL, ctxt->freeState->tabState[k]);
   10956         }
   10957         xmlRelaxNGFreeStates(NULL, ctxt->freeState);
   10958     }
   10959     if (ctxt->freeStates != NULL) {
   10960         for (k = 0; k < ctxt->freeStatesNr; k++) {
   10961             xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]);
   10962         }
   10963         xmlFree(ctxt->freeStates);
   10964     }
   10965     if (ctxt->errTab != NULL)
   10966         xmlFree(ctxt->errTab);
   10967     if (ctxt->elemTab != NULL) {
   10968         xmlRegExecCtxtPtr exec;
   10969 
   10970         exec = xmlRelaxNGElemPop(ctxt);
   10971         while (exec != NULL) {
   10972             xmlRegFreeExecCtxt(exec);
   10973             exec = xmlRelaxNGElemPop(ctxt);
   10974         }
   10975         xmlFree(ctxt->elemTab);
   10976     }
   10977     xmlFree(ctxt);
   10978 }
   10979 
   10980 /**
   10981  * xmlRelaxNGSetValidErrors:
   10982  * @ctxt:  a Relax-NG validation context
   10983  * @err:  the error function
   10984  * @warn: the warning function
   10985  * @ctx: the functions context
   10986  *
   10987  * Set the error and warning callback informations
   10988  */
   10989 void
   10990 xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
   10991                          xmlRelaxNGValidityErrorFunc err,
   10992                          xmlRelaxNGValidityWarningFunc warn, void *ctx)
   10993 {
   10994     if (ctxt == NULL)
   10995         return;
   10996     ctxt->error = err;
   10997     ctxt->warning = warn;
   10998     ctxt->userData = ctx;
   10999     ctxt->serror = NULL;
   11000 }
   11001 
   11002 /**
   11003  * xmlRelaxNGSetValidStructuredErrors:
   11004  * @ctxt:  a Relax-NG validation context
   11005  * @serror:  the structured error function
   11006  * @ctx: the functions context
   11007  *
   11008  * Set the structured error callback
   11009  */
   11010 void
   11011 xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt,
   11012                                    xmlStructuredErrorFunc serror, void *ctx)
   11013 {
   11014     if (ctxt == NULL)
   11015         return;
   11016     ctxt->serror = serror;
   11017     ctxt->error = NULL;
   11018     ctxt->warning = NULL;
   11019     ctxt->userData = ctx;
   11020 }
   11021 
   11022 /**
   11023  * xmlRelaxNGGetValidErrors:
   11024  * @ctxt:  a Relax-NG validation context
   11025  * @err:  the error function result
   11026  * @warn: the warning function result
   11027  * @ctx: the functions context result
   11028  *
   11029  * Get the error and warning callback informations
   11030  *
   11031  * Returns -1 in case of error and 0 otherwise
   11032  */
   11033 int
   11034 xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
   11035                          xmlRelaxNGValidityErrorFunc * err,
   11036                          xmlRelaxNGValidityWarningFunc * warn, void **ctx)
   11037 {
   11038     if (ctxt == NULL)
   11039         return (-1);
   11040     if (err != NULL)
   11041         *err = ctxt->error;
   11042     if (warn != NULL)
   11043         *warn = ctxt->warning;
   11044     if (ctx != NULL)
   11045         *ctx = ctxt->userData;
   11046     return (0);
   11047 }
   11048 
   11049 /**
   11050  * xmlRelaxNGValidateDoc:
   11051  * @ctxt:  a Relax-NG validation context
   11052  * @doc:  a parsed document tree
   11053  *
   11054  * Validate a document tree in memory.
   11055  *
   11056  * Returns 0 if the document is valid, a positive error code
   11057  *     number otherwise and -1 in case of internal or API error.
   11058  */
   11059 int
   11060 xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
   11061 {
   11062     int ret;
   11063 
   11064     if ((ctxt == NULL) || (doc == NULL))
   11065         return (-1);
   11066 
   11067     ctxt->doc = doc;
   11068 
   11069     ret = xmlRelaxNGValidateDocument(ctxt, doc);
   11070     /*
   11071      * Remove all left PSVI
   11072      */
   11073     xmlRelaxNGCleanPSVI((xmlNodePtr) doc);
   11074 
   11075     /*
   11076      * TODO: build error codes
   11077      */
   11078     if (ret == -1)
   11079         return (1);
   11080     return (ret);
   11081 }
   11082 
   11083 #define bottom_relaxng
   11084 #include "elfgcchack.h"
   11085 #endif /* LIBXML_SCHEMAS_ENABLED */
   11086