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