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 
    153 struct _xmlRelaxNGDefine {
    154     xmlRelaxNGType type;        /* the type of definition */
    155     xmlNodePtr node;            /* the node in the source */
    156     xmlChar *name;              /* the element local name if present */
    157     xmlChar *ns;                /* the namespace local name if present */
    158     xmlChar *value;             /* value when available */
    159     void *data;                 /* data lib or specific pointer */
    160     xmlRelaxNGDefinePtr content;        /* the expected content */
    161     xmlRelaxNGDefinePtr parent; /* the parent definition, if any */
    162     xmlRelaxNGDefinePtr next;   /* list within grouping sequences */
    163     xmlRelaxNGDefinePtr attrs;  /* list of attributes for elements */
    164     xmlRelaxNGDefinePtr nameClass;      /* the nameClass definition if any */
    165     xmlRelaxNGDefinePtr nextHash;       /* next define in defs/refs hash tables */
    166     short depth;                /* used for the cycle detection */
    167     short dflags;               /* define related flags */
    168     xmlRegexpPtr contModel;     /* a compiled content model if available */
    169 };
    170 
    171 /**
    172  * _xmlRelaxNG:
    173  *
    174  * A RelaxNGs definition
    175  */
    176 struct _xmlRelaxNG {
    177     void *_private;             /* unused by the library for users or bindings */
    178     xmlRelaxNGGrammarPtr topgrammar;
    179     xmlDocPtr doc;
    180 
    181     int idref;                  /* requires idref checking */
    182 
    183     xmlHashTablePtr defs;       /* define */
    184     xmlHashTablePtr refs;       /* references */
    185     xmlRelaxNGDocumentPtr documents;    /* all the documents loaded */
    186     xmlRelaxNGIncludePtr includes;      /* all the includes loaded */
    187     int defNr;                  /* number of defines used */
    188     xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */
    189 
    190 };
    191 
    192 #define XML_RELAXNG_IN_ATTRIBUTE	(1 << 0)
    193 #define XML_RELAXNG_IN_ONEORMORE	(1 << 1)
    194 #define XML_RELAXNG_IN_LIST		(1 << 2)
    195 #define XML_RELAXNG_IN_DATAEXCEPT	(1 << 3)
    196 #define XML_RELAXNG_IN_START		(1 << 4)
    197 #define XML_RELAXNG_IN_OOMGROUP		(1 << 5)
    198 #define XML_RELAXNG_IN_OOMINTERLEAVE	(1 << 6)
    199 #define XML_RELAXNG_IN_EXTERNALREF	(1 << 7)
    200 #define XML_RELAXNG_IN_ANYEXCEPT	(1 << 8)
    201 #define XML_RELAXNG_IN_NSEXCEPT		(1 << 9)
    202 
    203 struct _xmlRelaxNGParserCtxt {
    204     void *userData;             /* user specific data block */
    205     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */
    206     xmlRelaxNGValidityWarningFunc warning;      /* the callback in case of warning */
    207     xmlStructuredErrorFunc serror;
    208     xmlRelaxNGValidErr err;
    209 
    210     xmlRelaxNGPtr schema;       /* The schema in use */
    211     xmlRelaxNGGrammarPtr grammar;       /* the current grammar */
    212     xmlRelaxNGGrammarPtr parentgrammar; /* the parent grammar */
    213     int flags;                  /* parser flags */
    214     int nbErrors;               /* number of errors at parse time */
    215     int nbWarnings;             /* number of warnings at parse time */
    216     const xmlChar *define;      /* the current define scope */
    217     xmlRelaxNGDefinePtr def;    /* the current define */
    218 
    219     int nbInterleaves;
    220     xmlHashTablePtr interleaves;        /* keep track of all the interleaves */
    221 
    222     xmlRelaxNGDocumentPtr documents;    /* all the documents loaded */
    223     xmlRelaxNGIncludePtr includes;      /* all the includes loaded */
    224     xmlChar *URL;
    225     xmlDocPtr document;
    226 
    227     int defNr;                  /* number of defines used */
    228     int defMax;                 /* number of defines aloocated */
    229     xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */
    230 
    231     const char *buffer;
    232     int size;
    233 
    234     /* the document stack */
    235     xmlRelaxNGDocumentPtr doc;  /* Current parsed external ref */
    236     int docNr;                  /* Depth of the parsing stack */
    237     int docMax;                 /* Max depth of the parsing stack */
    238     xmlRelaxNGDocumentPtr *docTab;      /* array of docs */
    239 
    240     /* the include stack */
    241     xmlRelaxNGIncludePtr inc;   /* Current parsed include */
    242     int incNr;                  /* Depth of the include parsing stack */
    243     int incMax;                 /* Max depth of the parsing stack */
    244     xmlRelaxNGIncludePtr *incTab;       /* array of incs */
    245 
    246     int idref;                  /* requires idref checking */
    247 
    248     /* used to compile content models */
    249     xmlAutomataPtr am;          /* the automata */
    250     xmlAutomataStatePtr state;  /* used to build the automata */
    251 
    252     int crng;			/* compact syntax and other flags */
    253     int freedoc;		/* need to free the document */
    254 };
    255 
    256 #define FLAGS_IGNORABLE		1
    257 #define FLAGS_NEGATIVE		2
    258 #define FLAGS_MIXED_CONTENT	4
    259 #define FLAGS_NOERROR		8
    260 
    261 /**
    262  * xmlRelaxNGInterleaveGroup:
    263  *
    264  * A RelaxNGs partition set associated to lists of definitions
    265  */
    266 typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup;
    267 typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr;
    268 struct _xmlRelaxNGInterleaveGroup {
    269     xmlRelaxNGDefinePtr rule;   /* the rule to satisfy */
    270     xmlRelaxNGDefinePtr *defs;  /* the array of element definitions */
    271     xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */
    272 };
    273 
    274 #define IS_DETERMINIST		1
    275 #define IS_NEEDCHECK		2
    276 
    277 /**
    278  * xmlRelaxNGPartitions:
    279  *
    280  * A RelaxNGs partition associated to an interleave group
    281  */
    282 typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition;
    283 typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr;
    284 struct _xmlRelaxNGPartition {
    285     int nbgroups;               /* number of groups in the partitions */
    286     xmlHashTablePtr triage;     /* hash table used to direct nodes to the
    287                                  * right group when possible */
    288     int flags;                  /* determinist ? */
    289     xmlRelaxNGInterleaveGroupPtr *groups;
    290 };
    291 
    292 /**
    293  * xmlRelaxNGValidState:
    294  *
    295  * A RelaxNGs validation state
    296  */
    297 #define MAX_ATTR 20
    298 typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState;
    299 typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr;
    300 struct _xmlRelaxNGValidState {
    301     xmlNodePtr node;            /* the current node */
    302     xmlNodePtr seq;             /* the sequence of children left to validate */
    303     int nbAttrs;                /* the number of attributes */
    304     int maxAttrs;               /* the size of attrs */
    305     int nbAttrLeft;             /* the number of attributes left to validate */
    306     xmlChar *value;             /* the value when operating on string */
    307     xmlChar *endvalue;          /* the end value when operating on string */
    308     xmlAttrPtr *attrs;          /* the array of attributes */
    309 };
    310 
    311 /**
    312  * xmlRelaxNGStates:
    313  *
    314  * A RelaxNGs container for validation state
    315  */
    316 typedef struct _xmlRelaxNGStates xmlRelaxNGStates;
    317 typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr;
    318 struct _xmlRelaxNGStates {
    319     int nbState;                /* the number of states */
    320     int maxState;               /* the size of the array */
    321     xmlRelaxNGValidStatePtr *tabState;
    322 };
    323 
    324 #define ERROR_IS_DUP	1
    325 
    326 /**
    327  * xmlRelaxNGValidError:
    328  *
    329  * A RelaxNGs validation error
    330  */
    331 typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;
    332 typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;
    333 struct _xmlRelaxNGValidError {
    334     xmlRelaxNGValidErr err;     /* the error number */
    335     int flags;                  /* flags */
    336     xmlNodePtr node;            /* the current node */
    337     xmlNodePtr seq;             /* the current child */
    338     const xmlChar *arg1;        /* first arg */
    339     const xmlChar *arg2;        /* second arg */
    340 };
    341 
    342 /**
    343  * xmlRelaxNGValidCtxt:
    344  *
    345  * A RelaxNGs validation context
    346  */
    347 
    348 struct _xmlRelaxNGValidCtxt {
    349     void *userData;             /* user specific data block */
    350     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */
    351     xmlRelaxNGValidityWarningFunc warning;      /* the callback in case of warning */
    352     xmlStructuredErrorFunc serror;
    353     int nbErrors;               /* number of errors in validation */
    354 
    355     xmlRelaxNGPtr schema;       /* The schema in use */
    356     xmlDocPtr doc;              /* the document being validated */
    357     int flags;                  /* validation flags */
    358     int depth;                  /* validation depth */
    359     int idref;                  /* requires idref checking */
    360     int errNo;                  /* the first error found */
    361 
    362     /*
    363      * Errors accumulated in branches may have to be stacked to be
    364      * provided back when it's sure they affect validation.
    365      */
    366     xmlRelaxNGValidErrorPtr err;        /* Last error */
    367     int errNr;                  /* Depth of the error stack */
    368     int errMax;                 /* Max depth of the error stack */
    369     xmlRelaxNGValidErrorPtr errTab;     /* stack of errors */
    370 
    371     xmlRelaxNGValidStatePtr state;      /* the current validation state */
    372     xmlRelaxNGStatesPtr states; /* the accumulated state list */
    373 
    374     xmlRelaxNGStatesPtr freeState;      /* the pool of free valid states */
    375     int freeStatesNr;
    376     int freeStatesMax;
    377     xmlRelaxNGStatesPtr *freeStates;    /* the pool of free state groups */
    378 
    379     /*
    380      * This is used for "progressive" validation
    381      */
    382     xmlRegExecCtxtPtr elem;     /* the current element regexp */
    383     int elemNr;                 /* the number of element validated */
    384     int elemMax;                /* the max depth of elements */
    385     xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */
    386     int pstate;                 /* progressive state */
    387     xmlNodePtr pnode;           /* the current node */
    388     xmlRelaxNGDefinePtr pdef;   /* the non-streamable definition */
    389     int perr;                   /* signal error in content model
    390                                  * outside the regexp */
    391 };
    392 
    393 /**
    394  * xmlRelaxNGInclude:
    395  *
    396  * Structure associated to a RelaxNGs document element
    397  */
    398 struct _xmlRelaxNGInclude {
    399     xmlRelaxNGIncludePtr next;  /* keep a chain of includes */
    400     xmlChar *href;              /* the normalized href value */
    401     xmlDocPtr doc;              /* the associated XML document */
    402     xmlRelaxNGDefinePtr content;        /* the definitions */
    403     xmlRelaxNGPtr schema;       /* the schema */
    404 };
    405 
    406 /**
    407  * xmlRelaxNGDocument:
    408  *
    409  * Structure associated to a RelaxNGs document element
    410  */
    411 struct _xmlRelaxNGDocument {
    412     xmlRelaxNGDocumentPtr next; /* keep a chain of documents */
    413     xmlChar *href;              /* the normalized href value */
    414     xmlDocPtr doc;              /* the associated XML document */
    415     xmlRelaxNGDefinePtr content;        /* the definitions */
    416     xmlRelaxNGPtr schema;       /* the schema */
    417 };
    418 
    419 
    420 /************************************************************************
    421  *									*
    422  * 		Some factorized error routines				*
    423  *									*
    424  ************************************************************************/
    425 
    426 /**
    427  * xmlRngPErrMemory:
    428  * @ctxt:  an Relax-NG parser context
    429  * @extra:  extra informations
    430  *
    431  * Handle a redefinition of attribute error
    432  */
    433 static void
    434 xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
    435 {
    436     xmlStructuredErrorFunc schannel = NULL;
    437     xmlGenericErrorFunc channel = NULL;
    438     void *data = NULL;
    439 
    440     if (ctxt != NULL) {
    441         if (ctxt->serror != NULL)
    442 	    schannel = ctxt->serror;
    443 	else
    444 	    channel = ctxt->error;
    445         data = ctxt->userData;
    446         ctxt->nbErrors++;
    447     }
    448     if (extra)
    449         __xmlRaiseError(schannel, channel, data,
    450                         NULL, NULL, XML_FROM_RELAXNGP,
    451                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
    452                         NULL, NULL, 0, 0,
    453                         "Memory allocation failed : %s\n", extra);
    454     else
    455         __xmlRaiseError(schannel, channel, data,
    456                         NULL, NULL, XML_FROM_RELAXNGP,
    457                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
    458                         NULL, NULL, 0, 0, "Memory allocation failed\n");
    459 }
    460 
    461 /**
    462  * xmlRngVErrMemory:
    463  * @ctxt:  a Relax-NG validation context
    464  * @extra:  extra informations
    465  *
    466  * Handle a redefinition of attribute error
    467  */
    468 static void
    469 xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)
    470 {
    471     xmlStructuredErrorFunc schannel = NULL;
    472     xmlGenericErrorFunc channel = NULL;
    473     void *data = NULL;
    474 
    475     if (ctxt != NULL) {
    476         if (ctxt->serror != NULL)
    477 	    schannel = ctxt->serror;
    478 	else
    479 	    channel = ctxt->error;
    480         data = ctxt->userData;
    481         ctxt->nbErrors++;
    482     }
    483     if (extra)
    484         __xmlRaiseError(schannel, channel, data,
    485                         NULL, NULL, XML_FROM_RELAXNGV,
    486                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
    487                         NULL, NULL, 0, 0,
    488                         "Memory allocation failed : %s\n", extra);
    489     else
    490         __xmlRaiseError(schannel, channel, data,
    491                         NULL, NULL, XML_FROM_RELAXNGV,
    492                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
    493                         NULL, NULL, 0, 0, "Memory allocation failed\n");
    494 }
    495 
    496 /**
    497  * xmlRngPErr:
    498  * @ctxt:  a Relax-NG parser context
    499  * @node:  the node raising the error
    500  * @error:  the error code
    501  * @msg:  message
    502  * @str1:  extra info
    503  * @str2:  extra info
    504  *
    505  * Handle a Relax NG Parsing error
    506  */
    507 static void
    508 xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
    509            const char *msg, const xmlChar * str1, const xmlChar * str2)
    510 {
    511     xmlStructuredErrorFunc schannel = NULL;
    512     xmlGenericErrorFunc channel = NULL;
    513     void *data = NULL;
    514 
    515     if (ctxt != NULL) {
    516         if (ctxt->serror != NULL)
    517 	    schannel = ctxt->serror;
    518 	else
    519 	    channel = ctxt->error;
    520         data = ctxt->userData;
    521         ctxt->nbErrors++;
    522     }
    523     __xmlRaiseError(schannel, channel, data,
    524                     NULL, node, XML_FROM_RELAXNGP,
    525                     error, XML_ERR_ERROR, NULL, 0,
    526                     (const char *) str1, (const char *) str2, NULL, 0, 0,
    527                     msg, str1, str2);
    528 }
    529 
    530 /**
    531  * xmlRngVErr:
    532  * @ctxt:  a Relax-NG validation context
    533  * @node:  the node raising the error
    534  * @error:  the error code
    535  * @msg:  message
    536  * @str1:  extra info
    537  * @str2:  extra info
    538  *
    539  * Handle a Relax NG Validation error
    540  */
    541 static void
    542 xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
    543            const char *msg, const xmlChar * str1, const xmlChar * str2)
    544 {
    545     xmlStructuredErrorFunc schannel = NULL;
    546     xmlGenericErrorFunc channel = NULL;
    547     void *data = NULL;
    548 
    549     if (ctxt != NULL) {
    550         if (ctxt->serror != NULL)
    551 	    schannel = ctxt->serror;
    552 	else
    553 	    channel = ctxt->error;
    554         data = ctxt->userData;
    555         ctxt->nbErrors++;
    556     }
    557     __xmlRaiseError(schannel, channel, data,
    558                     NULL, node, XML_FROM_RELAXNGV,
    559                     error, XML_ERR_ERROR, NULL, 0,
    560                     (const char *) str1, (const char *) str2, NULL, 0, 0,
    561                     msg, str1, str2);
    562 }
    563 
    564 /************************************************************************
    565  * 									*
    566  * 		Preliminary type checking interfaces			*
    567  * 									*
    568  ************************************************************************/
    569 
    570 /**
    571  * xmlRelaxNGTypeHave:
    572  * @data:  data needed for the library
    573  * @type:  the type name
    574  * @value:  the value to check
    575  *
    576  * Function provided by a type library to check if a type is exported
    577  *
    578  * Returns 1 if yes, 0 if no and -1 in case of error.
    579  */
    580 typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar * type);
    581 
    582 /**
    583  * xmlRelaxNGTypeCheck:
    584  * @data:  data needed for the library
    585  * @type:  the type name
    586  * @value:  the value to check
    587  * @result:  place to store the result if needed
    588  *
    589  * Function provided by a type library to check if a value match a type
    590  *
    591  * Returns 1 if yes, 0 if no and -1 in case of error.
    592  */
    593 typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar * type,
    594                                     const xmlChar * value, void **result,
    595                                     xmlNodePtr node);
    596 
    597 /**
    598  * xmlRelaxNGFacetCheck:
    599  * @data:  data needed for the library
    600  * @type:  the type name
    601  * @facet:  the facet name
    602  * @val:  the facet value
    603  * @strval:  the string value
    604  * @value:  the value to check
    605  *
    606  * Function provided by a type library to check a value facet
    607  *
    608  * Returns 1 if yes, 0 if no and -1 in case of error.
    609  */
    610 typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar * type,
    611                                      const xmlChar * facet,
    612                                      const xmlChar * val,
    613                                      const xmlChar * strval, void *value);
    614 
    615 /**
    616  * xmlRelaxNGTypeFree:
    617  * @data:  data needed for the library
    618  * @result:  the value to free
    619  *
    620  * Function provided by a type library to free a returned result
    621  */
    622 typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);
    623 
    624 /**
    625  * xmlRelaxNGTypeCompare:
    626  * @data:  data needed for the library
    627  * @type:  the type name
    628  * @value1:  the first value
    629  * @value2:  the second value
    630  *
    631  * Function provided by a type library to compare two values accordingly
    632  * to a type.
    633  *
    634  * Returns 1 if yes, 0 if no and -1 in case of error.
    635  */
    636 typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar * type,
    637                                       const xmlChar * value1,
    638                                       xmlNodePtr ctxt1,
    639                                       void *comp1,
    640                                       const xmlChar * value2,
    641                                       xmlNodePtr ctxt2);
    642 typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
    643 typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
    644 struct _xmlRelaxNGTypeLibrary {
    645     const xmlChar *namespace;   /* the datatypeLibrary value */
    646     void *data;                 /* data needed for the library */
    647     xmlRelaxNGTypeHave have;    /* the export function */
    648     xmlRelaxNGTypeCheck check;  /* the checking function */
    649     xmlRelaxNGTypeCompare comp; /* the compare function */
    650     xmlRelaxNGFacetCheck facet; /* the facet check function */
    651     xmlRelaxNGTypeFree freef;   /* the freeing function */
    652 };
    653 
    654 /************************************************************************
    655  * 									*
    656  * 			Allocation functions				*
    657  * 									*
    658  ************************************************************************/
    659 static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);
    660 static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);
    661 static void xmlRelaxNGNormExtSpace(xmlChar * value);
    662 static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema);
    663 static int xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt
    664                                      ATTRIBUTE_UNUSED,
    665                                      xmlRelaxNGValidStatePtr state1,
    666                                      xmlRelaxNGValidStatePtr state2);
    667 static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
    668                                      xmlRelaxNGValidStatePtr state);
    669 
    670 /**
    671  * xmlRelaxNGFreeDocument:
    672  * @docu:  a document structure
    673  *
    674  * Deallocate a RelaxNG document structure.
    675  */
    676 static void
    677 xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu)
    678 {
    679     if (docu == NULL)
    680         return;
    681 
    682     if (docu->href != NULL)
    683         xmlFree(docu->href);
    684     if (docu->doc != NULL)
    685         xmlFreeDoc(docu->doc);
    686     if (docu->schema != NULL)
    687         xmlRelaxNGFreeInnerSchema(docu->schema);
    688     xmlFree(docu);
    689 }
    690 
    691 /**
    692  * xmlRelaxNGFreeDocumentList:
    693  * @docu:  a list of  document structure
    694  *
    695  * Deallocate a RelaxNG document structures.
    696  */
    697 static void
    698 xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu)
    699 {
    700     xmlRelaxNGDocumentPtr next;
    701 
    702     while (docu != NULL) {
    703         next = docu->next;
    704         xmlRelaxNGFreeDocument(docu);
    705         docu = next;
    706     }
    707 }
    708 
    709 /**
    710  * xmlRelaxNGFreeInclude:
    711  * @incl:  a include structure
    712  *
    713  * Deallocate a RelaxNG include structure.
    714  */
    715 static void
    716 xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl)
    717 {
    718     if (incl == NULL)
    719         return;
    720 
    721     if (incl->href != NULL)
    722         xmlFree(incl->href);
    723     if (incl->doc != NULL)
    724         xmlFreeDoc(incl->doc);
    725     if (incl->schema != NULL)
    726         xmlRelaxNGFree(incl->schema);
    727     xmlFree(incl);
    728 }
    729 
    730 /**
    731  * xmlRelaxNGFreeIncludeList:
    732  * @incl:  a include structure list
    733  *
    734  * Deallocate a RelaxNG include structure.
    735  */
    736 static void
    737 xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl)
    738 {
    739     xmlRelaxNGIncludePtr next;
    740 
    741     while (incl != NULL) {
    742         next = incl->next;
    743         xmlRelaxNGFreeInclude(incl);
    744         incl = next;
    745     }
    746 }
    747 
    748 /**
    749  * xmlRelaxNGNewRelaxNG:
    750  * @ctxt:  a Relax-NG validation context (optional)
    751  *
    752  * Allocate a new RelaxNG structure.
    753  *
    754  * Returns the newly allocated structure or NULL in case or error
    755  */
    756 static xmlRelaxNGPtr
    757 xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)
    758 {
    759     xmlRelaxNGPtr ret;
    760 
    761     ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));
    762     if (ret == NULL) {
    763         xmlRngPErrMemory(ctxt, NULL);
    764         return (NULL);
    765     }
    766     memset(ret, 0, sizeof(xmlRelaxNG));
    767 
    768     return (ret);
    769 }
    770 
    771 /**
    772  * xmlRelaxNGFreeInnerSchema:
    773  * @schema:  a schema structure
    774  *
    775  * Deallocate a RelaxNG schema structure.
    776  */
    777 static void
    778 xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema)
    779 {
    780     if (schema == NULL)
    781         return;
    782 
    783     if (schema->doc != NULL)
    784         xmlFreeDoc(schema->doc);
    785     if (schema->defTab != NULL) {
    786         int i;
    787 
    788         for (i = 0; i < schema->defNr; i++)
    789             xmlRelaxNGFreeDefine(schema->defTab[i]);
    790         xmlFree(schema->defTab);
    791     }
    792 
    793     xmlFree(schema);
    794 }
    795 
    796 /**
    797  * xmlRelaxNGFree:
    798  * @schema:  a schema structure
    799  *
    800  * Deallocate a RelaxNG structure.
    801  */
    802 void
    803 xmlRelaxNGFree(xmlRelaxNGPtr schema)
    804 {
    805     if (schema == NULL)
    806         return;
    807 
    808     if (schema->topgrammar != NULL)
    809         xmlRelaxNGFreeGrammar(schema->topgrammar);
    810     if (schema->doc != NULL)
    811         xmlFreeDoc(schema->doc);
    812     if (schema->documents != NULL)
    813         xmlRelaxNGFreeDocumentList(schema->documents);
    814     if (schema->includes != NULL)
    815         xmlRelaxNGFreeIncludeList(schema->includes);
    816     if (schema->defTab != NULL) {
    817         int i;
    818 
    819         for (i = 0; i < schema->defNr; i++)
    820             xmlRelaxNGFreeDefine(schema->defTab[i]);
    821         xmlFree(schema->defTab);
    822     }
    823 
    824     xmlFree(schema);
    825 }
    826 
    827 /**
    828  * xmlRelaxNGNewGrammar:
    829  * @ctxt:  a Relax-NG validation context (optional)
    830  *
    831  * Allocate a new RelaxNG grammar.
    832  *
    833  * Returns the newly allocated structure or NULL in case or error
    834  */
    835 static xmlRelaxNGGrammarPtr
    836 xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)
    837 {
    838     xmlRelaxNGGrammarPtr ret;
    839 
    840     ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));
    841     if (ret == NULL) {
    842         xmlRngPErrMemory(ctxt, NULL);
    843         return (NULL);
    844     }
    845     memset(ret, 0, sizeof(xmlRelaxNGGrammar));
    846 
    847     return (ret);
    848 }
    849 
    850 /**
    851  * xmlRelaxNGFreeGrammar:
    852  * @grammar:  a grammar structure
    853  *
    854  * Deallocate a RelaxNG grammar structure.
    855  */
    856 static void
    857 xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar)
    858 {
    859     if (grammar == NULL)
    860         return;
    861 
    862     if (grammar->children != NULL) {
    863         xmlRelaxNGFreeGrammar(grammar->children);
    864     }
    865     if (grammar->next != NULL) {
    866         xmlRelaxNGFreeGrammar(grammar->next);
    867     }
    868     if (grammar->refs != NULL) {
    869         xmlHashFree(grammar->refs, NULL);
    870     }
    871     if (grammar->defs != NULL) {
    872         xmlHashFree(grammar->defs, NULL);
    873     }
    874 
    875     xmlFree(grammar);
    876 }
    877 
    878 /**
    879  * xmlRelaxNGNewDefine:
    880  * @ctxt:  a Relax-NG validation context
    881  * @node:  the node in the input document.
    882  *
    883  * Allocate a new RelaxNG define.
    884  *
    885  * Returns the newly allocated structure or NULL in case or error
    886  */
    887 static xmlRelaxNGDefinePtr
    888 xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
    889 {
    890     xmlRelaxNGDefinePtr ret;
    891 
    892     if (ctxt->defMax == 0) {
    893         ctxt->defMax = 16;
    894         ctxt->defNr = 0;
    895         ctxt->defTab = (xmlRelaxNGDefinePtr *)
    896             xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
    897         if (ctxt->defTab == NULL) {
    898             xmlRngPErrMemory(ctxt, "allocating define\n");
    899             return (NULL);
    900         }
    901     } else if (ctxt->defMax <= ctxt->defNr) {
    902         xmlRelaxNGDefinePtr *tmp;
    903 
    904         ctxt->defMax *= 2;
    905         tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,
    906                                                  ctxt->defMax *
    907                                                  sizeof
    908                                                  (xmlRelaxNGDefinePtr));
    909         if (tmp == NULL) {
    910             xmlRngPErrMemory(ctxt, "allocating define\n");
    911             return (NULL);
    912         }
    913         ctxt->defTab = tmp;
    914     }
    915     ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
    916     if (ret == NULL) {
    917         xmlRngPErrMemory(ctxt, "allocating define\n");
    918         return (NULL);
    919     }
    920     memset(ret, 0, sizeof(xmlRelaxNGDefine));
    921     ctxt->defTab[ctxt->defNr++] = ret;
    922     ret->node = node;
    923     ret->depth = -1;
    924     return (ret);
    925 }
    926 
    927 /**
    928  * xmlRelaxNGFreePartition:
    929  * @partitions:  a partition set structure
    930  *
    931  * Deallocate RelaxNG partition set structures.
    932  */
    933 static void
    934 xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions)
    935 {
    936     xmlRelaxNGInterleaveGroupPtr group;
    937     int j;
    938 
    939     if (partitions != NULL) {
    940         if (partitions->groups != NULL) {
    941             for (j = 0; j < partitions->nbgroups; j++) {
    942                 group = partitions->groups[j];
    943                 if (group != NULL) {
    944                     if (group->defs != NULL)
    945                         xmlFree(group->defs);
    946                     if (group->attrs != NULL)
    947                         xmlFree(group->attrs);
    948                     xmlFree(group);
    949                 }
    950             }
    951             xmlFree(partitions->groups);
    952         }
    953         if (partitions->triage != NULL) {
    954             xmlHashFree(partitions->triage, NULL);
    955         }
    956         xmlFree(partitions);
    957     }
    958 }
    959 
    960 /**
    961  * xmlRelaxNGFreeDefine:
    962  * @define:  a define structure
    963  *
    964  * Deallocate a RelaxNG define structure.
    965  */
    966 static void
    967 xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define)
    968 {
    969     if (define == NULL)
    970         return;
    971 
    972     if ((define->type == XML_RELAXNG_VALUE) && (define->attrs != NULL)) {
    973         xmlRelaxNGTypeLibraryPtr lib;
    974 
    975         lib = (xmlRelaxNGTypeLibraryPtr) define->data;
    976         if ((lib != NULL) && (lib->freef != NULL))
    977             lib->freef(lib->data, (void *) define->attrs);
    978     }
    979     if ((define->data != NULL) && (define->type == XML_RELAXNG_INTERLEAVE))
    980         xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
    981     if ((define->data != NULL) && (define->type == XML_RELAXNG_CHOICE))
    982         xmlHashFree((xmlHashTablePtr) define->data, NULL);
    983     if (define->name != NULL)
    984         xmlFree(define->name);
    985     if (define->ns != NULL)
    986         xmlFree(define->ns);
    987     if (define->value != NULL)
    988         xmlFree(define->value);
    989     if (define->contModel != NULL)
    990         xmlRegFreeRegexp(define->contModel);
    991     xmlFree(define);
    992 }
    993 
    994 /**
    995  * xmlRelaxNGNewStates:
    996  * @ctxt:  a Relax-NG validation context
    997  * @size:  the default size for the container
    998  *
    999  * Allocate a new RelaxNG validation state container
   1000  *
   1001  * Returns the newly allocated structure or NULL in case or error
   1002  */
   1003 static xmlRelaxNGStatesPtr
   1004 xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
   1005 {
   1006     xmlRelaxNGStatesPtr ret;
   1007 
   1008     if ((ctxt != NULL) &&
   1009         (ctxt->freeState != NULL) && (ctxt->freeStatesNr > 0)) {
   1010         ctxt->freeStatesNr--;
   1011         ret = ctxt->freeStates[ctxt->freeStatesNr];
   1012         ret->nbState = 0;
   1013         return (ret);
   1014     }
   1015     if (size < 16)
   1016         size = 16;
   1017 
   1018     ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +
   1019                                           (size -
   1020                                            1) *
   1021                                           sizeof(xmlRelaxNGValidStatePtr));
   1022     if (ret == NULL) {
   1023         xmlRngVErrMemory(ctxt, "allocating states\n");
   1024         return (NULL);
   1025     }
   1026     ret->nbState = 0;
   1027     ret->maxState = size;
   1028     ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc((size) *
   1029                                                           sizeof
   1030                                                           (xmlRelaxNGValidStatePtr));
   1031     if (ret->tabState == NULL) {
   1032         xmlRngVErrMemory(ctxt, "allocating states\n");
   1033         xmlFree(ret);
   1034         return (NULL);
   1035     }
   1036     return (ret);
   1037 }
   1038 
   1039 /**
   1040  * xmlRelaxNGAddStateUniq:
   1041  * @ctxt:  a Relax-NG validation context
   1042  * @states:  the states container
   1043  * @state:  the validation state
   1044  *
   1045  * Add a RelaxNG validation state to the container without checking
   1046  * for unicity.
   1047  *
   1048  * Return 1 in case of success and 0 if this is a duplicate and -1 on error
   1049  */
   1050 static int
   1051 xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,
   1052                         xmlRelaxNGStatesPtr states,
   1053                         xmlRelaxNGValidStatePtr state)
   1054 {
   1055     if (state == NULL) {
   1056         return (-1);
   1057     }
   1058     if (states->nbState >= states->maxState) {
   1059         xmlRelaxNGValidStatePtr *tmp;
   1060         int size;
   1061 
   1062         size = states->maxState * 2;
   1063         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
   1064                                                      (size) *
   1065                                                      sizeof
   1066                                                      (xmlRelaxNGValidStatePtr));
   1067         if (tmp == NULL) {
   1068             xmlRngVErrMemory(ctxt, "adding states\n");
   1069             return (-1);
   1070         }
   1071         states->tabState = tmp;
   1072         states->maxState = size;
   1073     }
   1074     states->tabState[states->nbState++] = state;
   1075     return (1);
   1076 }
   1077 
   1078 /**
   1079  * xmlRelaxNGAddState:
   1080  * @ctxt:  a Relax-NG validation context
   1081  * @states:  the states container
   1082  * @state:  the validation state
   1083  *
   1084  * Add a RelaxNG validation state to the container
   1085  *
   1086  * Return 1 in case of success and 0 if this is a duplicate and -1 on error
   1087  */
   1088 static int
   1089 xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt,
   1090                     xmlRelaxNGStatesPtr states,
   1091                     xmlRelaxNGValidStatePtr state)
   1092 {
   1093     int i;
   1094 
   1095     if (state == NULL) {
   1096         return (-1);
   1097     }
   1098     if (states->nbState >= states->maxState) {
   1099         xmlRelaxNGValidStatePtr *tmp;
   1100         int size;
   1101 
   1102         size = states->maxState * 2;
   1103         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
   1104                                                      (size) *
   1105                                                      sizeof
   1106                                                      (xmlRelaxNGValidStatePtr));
   1107         if (tmp == NULL) {
   1108             xmlRngVErrMemory(ctxt, "adding states\n");
   1109             return (-1);
   1110         }
   1111         states->tabState = tmp;
   1112         states->maxState = size;
   1113     }
   1114     for (i = 0; i < states->nbState; i++) {
   1115         if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) {
   1116             xmlRelaxNGFreeValidState(ctxt, state);
   1117             return (0);
   1118         }
   1119     }
   1120     states->tabState[states->nbState++] = state;
   1121     return (1);
   1122 }
   1123 
   1124 /**
   1125  * xmlRelaxNGFreeStates:
   1126  * @ctxt:  a Relax-NG validation context
   1127  * @states:  teh container
   1128  *
   1129  * Free a RelaxNG validation state container
   1130  */
   1131 static void
   1132 xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
   1133                      xmlRelaxNGStatesPtr states)
   1134 {
   1135     if (states == NULL)
   1136         return;
   1137     if ((ctxt != NULL) && (ctxt->freeStates == NULL)) {
   1138         ctxt->freeStatesMax = 40;
   1139         ctxt->freeStatesNr = 0;
   1140         ctxt->freeStates = (xmlRelaxNGStatesPtr *)
   1141             xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
   1142         if (ctxt->freeStates == NULL) {
   1143             xmlRngVErrMemory(ctxt, "storing states\n");
   1144         }
   1145     } else if ((ctxt != NULL)
   1146                && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) {
   1147         xmlRelaxNGStatesPtr *tmp;
   1148 
   1149         tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates,
   1150                                                  2 * ctxt->freeStatesMax *
   1151                                                  sizeof
   1152                                                  (xmlRelaxNGStatesPtr));
   1153         if (tmp == NULL) {
   1154             xmlRngVErrMemory(ctxt, "storing states\n");
   1155             xmlFree(states->tabState);
   1156             xmlFree(states);
   1157             return;
   1158         }
   1159         ctxt->freeStates = tmp;
   1160         ctxt->freeStatesMax *= 2;
   1161     }
   1162     if ((ctxt == NULL) || (ctxt->freeStates == NULL)) {
   1163         xmlFree(states->tabState);
   1164         xmlFree(states);
   1165     } else {
   1166         ctxt->freeStates[ctxt->freeStatesNr++] = states;
   1167     }
   1168 }
   1169 
   1170 /**
   1171  * xmlRelaxNGNewValidState:
   1172  * @ctxt:  a Relax-NG validation context
   1173  * @node:  the current node or NULL for the document
   1174  *
   1175  * Allocate a new RelaxNG validation state
   1176  *
   1177  * Returns the newly allocated structure or NULL in case or error
   1178  */
   1179 static xmlRelaxNGValidStatePtr
   1180 xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
   1181 {
   1182     xmlRelaxNGValidStatePtr ret;
   1183     xmlAttrPtr attr;
   1184     xmlAttrPtr attrs[MAX_ATTR];
   1185     int nbAttrs = 0;
   1186     xmlNodePtr root = NULL;
   1187 
   1188     if (node == NULL) {
   1189         root = xmlDocGetRootElement(ctxt->doc);
   1190         if (root == NULL)
   1191             return (NULL);
   1192     } else {
   1193         attr = node->properties;
   1194         while (attr != NULL) {
   1195             if (nbAttrs < MAX_ATTR)
   1196                 attrs[nbAttrs++] = attr;
   1197             else
   1198                 nbAttrs++;
   1199             attr = attr->next;
   1200         }
   1201     }
   1202     if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
   1203         ctxt->freeState->nbState--;
   1204         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
   1205     } else {
   1206         ret =
   1207             (xmlRelaxNGValidStatePtr)
   1208             xmlMalloc(sizeof(xmlRelaxNGValidState));
   1209         if (ret == NULL) {
   1210             xmlRngVErrMemory(ctxt, "allocating states\n");
   1211             return (NULL);
   1212         }
   1213         memset(ret, 0, sizeof(xmlRelaxNGValidState));
   1214     }
   1215     ret->value = NULL;
   1216     ret->endvalue = NULL;
   1217     if (node == NULL) {
   1218         ret->node = (xmlNodePtr) ctxt->doc;
   1219         ret->seq = root;
   1220     } else {
   1221         ret->node = node;
   1222         ret->seq = node->children;
   1223     }
   1224     ret->nbAttrs = 0;
   1225     if (nbAttrs > 0) {
   1226         if (ret->attrs == NULL) {
   1227             if (nbAttrs < 4)
   1228                 ret->maxAttrs = 4;
   1229             else
   1230                 ret->maxAttrs = nbAttrs;
   1231             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
   1232                                                   sizeof(xmlAttrPtr));
   1233             if (ret->attrs == NULL) {
   1234                 xmlRngVErrMemory(ctxt, "allocating states\n");
   1235                 return (ret);
   1236             }
   1237         } else if (ret->maxAttrs < nbAttrs) {
   1238             xmlAttrPtr *tmp;
   1239 
   1240             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *
   1241                                             sizeof(xmlAttrPtr));
   1242             if (tmp == NULL) {
   1243                 xmlRngVErrMemory(ctxt, "allocating states\n");
   1244                 return (ret);
   1245             }
   1246             ret->attrs = tmp;
   1247             ret->maxAttrs = nbAttrs;
   1248         }
   1249         ret->nbAttrs = nbAttrs;
   1250         if (nbAttrs < MAX_ATTR) {
   1251             memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs);
   1252         } else {
   1253             attr = node->properties;
   1254             nbAttrs = 0;
   1255             while (attr != NULL) {
   1256                 ret->attrs[nbAttrs++] = attr;
   1257                 attr = attr->next;
   1258             }
   1259         }
   1260     }
   1261     ret->nbAttrLeft = ret->nbAttrs;
   1262     return (ret);
   1263 }
   1264 
   1265 /**
   1266  * xmlRelaxNGCopyValidState:
   1267  * @ctxt:  a Relax-NG validation context
   1268  * @state:  a validation state
   1269  *
   1270  * Copy the validation state
   1271  *
   1272  * Returns the newly allocated structure or NULL in case or error
   1273  */
   1274 static xmlRelaxNGValidStatePtr
   1275 xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
   1276                          xmlRelaxNGValidStatePtr state)
   1277 {
   1278     xmlRelaxNGValidStatePtr ret;
   1279     unsigned int maxAttrs;
   1280     xmlAttrPtr *attrs;
   1281 
   1282     if (state == NULL)
   1283         return (NULL);
   1284     if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
   1285         ctxt->freeState->nbState--;
   1286         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
   1287     } else {
   1288         ret =
   1289             (xmlRelaxNGValidStatePtr)
   1290             xmlMalloc(sizeof(xmlRelaxNGValidState));
   1291         if (ret == NULL) {
   1292             xmlRngVErrMemory(ctxt, "allocating states\n");
   1293             return (NULL);
   1294         }
   1295         memset(ret, 0, sizeof(xmlRelaxNGValidState));
   1296     }
   1297     attrs = ret->attrs;
   1298     maxAttrs = ret->maxAttrs;
   1299     memcpy(ret, state, sizeof(xmlRelaxNGValidState));
   1300     ret->attrs = attrs;
   1301     ret->maxAttrs = maxAttrs;
   1302     if (state->nbAttrs > 0) {
   1303         if (ret->attrs == NULL) {
   1304             ret->maxAttrs = state->maxAttrs;
   1305             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
   1306                                                   sizeof(xmlAttrPtr));
   1307             if (ret->attrs == NULL) {
   1308                 xmlRngVErrMemory(ctxt, "allocating states\n");
   1309                 ret->nbAttrs = 0;
   1310                 return (ret);
   1311             }
   1312         } else if (ret->maxAttrs < state->nbAttrs) {
   1313             xmlAttrPtr *tmp;
   1314 
   1315             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *
   1316                                             sizeof(xmlAttrPtr));
   1317             if (tmp == NULL) {
   1318                 xmlRngVErrMemory(ctxt, "allocating states\n");
   1319                 ret->nbAttrs = 0;
   1320                 return (ret);
   1321             }
   1322             ret->maxAttrs = state->maxAttrs;
   1323             ret->attrs = tmp;
   1324         }
   1325         memcpy(ret->attrs, state->attrs,
   1326                state->nbAttrs * sizeof(xmlAttrPtr));
   1327     }
   1328     return (ret);
   1329 }
   1330 
   1331 /**
   1332  * xmlRelaxNGEqualValidState:
   1333  * @ctxt:  a Relax-NG validation context
   1334  * @state1:  a validation state
   1335  * @state2:  a validation state
   1336  *
   1337  * Compare the validation states for equality
   1338  *
   1339  * Returns 1 if equald, 0 otherwise
   1340  */
   1341 static int
   1342 xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
   1343                           xmlRelaxNGValidStatePtr state1,
   1344                           xmlRelaxNGValidStatePtr state2)
   1345 {
   1346     int i;
   1347 
   1348     if ((state1 == NULL) || (state2 == NULL))
   1349         return (0);
   1350     if (state1 == state2)
   1351         return (1);
   1352     if (state1->node != state2->node)
   1353         return (0);
   1354     if (state1->seq != state2->seq)
   1355         return (0);
   1356     if (state1->nbAttrLeft != state2->nbAttrLeft)
   1357         return (0);
   1358     if (state1->nbAttrs != state2->nbAttrs)
   1359         return (0);
   1360     if (state1->endvalue != state2->endvalue)
   1361         return (0);
   1362     if ((state1->value != state2->value) &&
   1363         (!xmlStrEqual(state1->value, state2->value)))
   1364         return (0);
   1365     for (i = 0; i < state1->nbAttrs; i++) {
   1366         if (state1->attrs[i] != state2->attrs[i])
   1367             return (0);
   1368     }
   1369     return (1);
   1370 }
   1371 
   1372 /**
   1373  * xmlRelaxNGFreeValidState:
   1374  * @state:  a validation state structure
   1375  *
   1376  * Deallocate a RelaxNG validation state structure.
   1377  */
   1378 static void
   1379 xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
   1380                          xmlRelaxNGValidStatePtr state)
   1381 {
   1382     if (state == NULL)
   1383         return;
   1384 
   1385     if ((ctxt != NULL) && (ctxt->freeState == NULL)) {
   1386         ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40);
   1387     }
   1388     if ((ctxt == NULL) || (ctxt->freeState == NULL)) {
   1389         if (state->attrs != NULL)
   1390             xmlFree(state->attrs);
   1391         xmlFree(state);
   1392     } else {
   1393         xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state);
   1394     }
   1395 }
   1396 
   1397 /************************************************************************
   1398  * 									*
   1399  * 			Semi internal functions				*
   1400  * 									*
   1401  ************************************************************************/
   1402 
   1403 /**
   1404  * xmlRelaxParserSetFlag:
   1405  * @ctxt: a RelaxNG parser context
   1406  * @flags: a set of flags values
   1407  *
   1408  * Semi private function used to pass informations to a parser context
   1409  * which are a combination of xmlRelaxNGParserFlag .
   1410  *
   1411  * Returns 0 if success and -1 in case of error
   1412  */
   1413 int
   1414 xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags)
   1415 {
   1416     if (ctxt == NULL) return(-1);
   1417     if (flags & XML_RELAXNGP_FREE_DOC) {
   1418         ctxt->crng |= XML_RELAXNGP_FREE_DOC;
   1419 	flags -= XML_RELAXNGP_FREE_DOC;
   1420     }
   1421     if (flags & XML_RELAXNGP_CRNG) {
   1422         ctxt->crng |= XML_RELAXNGP_CRNG;
   1423 	flags -= XML_RELAXNGP_CRNG;
   1424     }
   1425     if (flags != 0) return(-1);
   1426     return(0);
   1427 }
   1428 
   1429 /************************************************************************
   1430  * 									*
   1431  * 			Document functions				*
   1432  * 									*
   1433  ************************************************************************/
   1434 static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
   1435                                       xmlDocPtr doc);
   1436 
   1437 /**
   1438  * xmlRelaxNGIncludePush:
   1439  * @ctxt:  the parser context
   1440  * @value:  the element doc
   1441  *
   1442  * Pushes a new include on top of the include stack
   1443  *
   1444  * Returns 0 in case of error, the index in the stack otherwise
   1445  */
   1446 static int
   1447 xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
   1448                       xmlRelaxNGIncludePtr value)
   1449 {
   1450     if (ctxt->incTab == NULL) {
   1451         ctxt->incMax = 4;
   1452         ctxt->incNr = 0;
   1453         ctxt->incTab =
   1454             (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *
   1455                                                sizeof(ctxt->incTab[0]));
   1456         if (ctxt->incTab == NULL) {
   1457             xmlRngPErrMemory(ctxt, "allocating include\n");
   1458             return (0);
   1459         }
   1460     }
   1461     if (ctxt->incNr >= ctxt->incMax) {
   1462         ctxt->incMax *= 2;
   1463         ctxt->incTab =
   1464             (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,
   1465                                                 ctxt->incMax *
   1466                                                 sizeof(ctxt->incTab[0]));
   1467         if (ctxt->incTab == NULL) {
   1468             xmlRngPErrMemory(ctxt, "allocating include\n");
   1469             return (0);
   1470         }
   1471     }
   1472     ctxt->incTab[ctxt->incNr] = value;
   1473     ctxt->inc = value;
   1474     return (ctxt->incNr++);
   1475 }
   1476 
   1477 /**
   1478  * xmlRelaxNGIncludePop:
   1479  * @ctxt: the parser context
   1480  *
   1481  * Pops the top include from the include stack
   1482  *
   1483  * Returns the include just removed
   1484  */
   1485 static xmlRelaxNGIncludePtr
   1486 xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt)
   1487 {
   1488     xmlRelaxNGIncludePtr ret;
   1489 
   1490     if (ctxt->incNr <= 0)
   1491         return (NULL);
   1492     ctxt->incNr--;
   1493     if (ctxt->incNr > 0)
   1494         ctxt->inc = ctxt->incTab[ctxt->incNr - 1];
   1495     else
   1496         ctxt->inc = NULL;
   1497     ret = ctxt->incTab[ctxt->incNr];
   1498     ctxt->incTab[ctxt->incNr] = NULL;
   1499     return (ret);
   1500 }
   1501 
   1502 /**
   1503  * xmlRelaxNGRemoveRedefine:
   1504  * @ctxt: the parser context
   1505  * @URL:  the normalized URL
   1506  * @target:  the included target
   1507  * @name:  the define name to eliminate
   1508  *
   1509  * Applies the elimination algorithm of 4.7
   1510  *
   1511  * Returns 0 in case of error, 1 in case of success.
   1512  */
   1513 static int
   1514 xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
   1515                          const xmlChar * URL ATTRIBUTE_UNUSED,
   1516                          xmlNodePtr target, const xmlChar * name)
   1517 {
   1518     int found = 0;
   1519     xmlNodePtr tmp, tmp2;
   1520     xmlChar *name2;
   1521 
   1522 #ifdef DEBUG_INCLUDE
   1523     if (name == NULL)
   1524         xmlGenericError(xmlGenericErrorContext,
   1525                         "Elimination of <include> start from %s\n", URL);
   1526     else
   1527         xmlGenericError(xmlGenericErrorContext,
   1528                         "Elimination of <include> define %s from %s\n",
   1529                         name, URL);
   1530 #endif
   1531     tmp = target;
   1532     while (tmp != NULL) {
   1533         tmp2 = tmp->next;
   1534         if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) {
   1535             found = 1;
   1536             xmlUnlinkNode(tmp);
   1537             xmlFreeNode(tmp);
   1538         } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) {
   1539             name2 = xmlGetProp(tmp, BAD_CAST "name");
   1540             xmlRelaxNGNormExtSpace(name2);
   1541             if (name2 != NULL) {
   1542                 if (xmlStrEqual(name, name2)) {
   1543                     found = 1;
   1544                     xmlUnlinkNode(tmp);
   1545                     xmlFreeNode(tmp);
   1546                 }
   1547                 xmlFree(name2);
   1548             }
   1549         } else if (IS_RELAXNG(tmp, "include")) {
   1550             xmlChar *href = NULL;
   1551             xmlRelaxNGDocumentPtr inc = tmp->psvi;
   1552 
   1553             if ((inc != NULL) && (inc->doc != NULL) &&
   1554                 (inc->doc->children != NULL)) {
   1555 
   1556                 if (xmlStrEqual
   1557                     (inc->doc->children->name, BAD_CAST "grammar")) {
   1558 #ifdef DEBUG_INCLUDE
   1559                     href = xmlGetProp(tmp, BAD_CAST "href");
   1560 #endif
   1561                     if (xmlRelaxNGRemoveRedefine(ctxt, href,
   1562                                                  inc->doc->children->
   1563                                                  children, name) == 1) {
   1564                         found = 1;
   1565                     }
   1566 #ifdef DEBUG_INCLUDE
   1567                     if (href != NULL)
   1568                         xmlFree(href);
   1569 #endif
   1570                 }
   1571             }
   1572         }
   1573         tmp = tmp2;
   1574     }
   1575     return (found);
   1576 }
   1577 
   1578 /**
   1579  * xmlRelaxNGLoadInclude:
   1580  * @ctxt: the parser context
   1581  * @URL:  the normalized URL
   1582  * @node: the include node.
   1583  * @ns:  the namespace passed from the context.
   1584  *
   1585  * First lookup if the document is already loaded into the parser context,
   1586  * check against recursion. If not found the resource is loaded and
   1587  * the content is preprocessed before being returned back to the caller.
   1588  *
   1589  * Returns the xmlRelaxNGIncludePtr or NULL in case of error
   1590  */
   1591 static xmlRelaxNGIncludePtr
   1592 xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
   1593                       xmlNodePtr node, const xmlChar * ns)
   1594 {
   1595     xmlRelaxNGIncludePtr ret = NULL;
   1596     xmlDocPtr doc;
   1597     int i;
   1598     xmlNodePtr root, cur;
   1599 
   1600 #ifdef DEBUG_INCLUDE
   1601     xmlGenericError(xmlGenericErrorContext,
   1602                     "xmlRelaxNGLoadInclude(%s)\n", URL);
   1603 #endif
   1604 
   1605     /*
   1606      * check against recursion in the stack
   1607      */
   1608     for (i = 0; i < ctxt->incNr; i++) {
   1609         if (xmlStrEqual(ctxt->incTab[i]->href, URL)) {
   1610             xmlRngPErr(ctxt, NULL, XML_RNGP_INCLUDE_RECURSE,
   1611                        "Detected an Include recursion for %s\n", URL,
   1612                        NULL);
   1613             return (NULL);
   1614         }
   1615     }
   1616 
   1617     /*
   1618      * load the document
   1619      */
   1620     doc = xmlReadFile((const char *) URL,NULL,0);
   1621     if (doc == NULL) {
   1622         xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR,
   1623                    "xmlRelaxNG: could not load %s\n", URL, NULL);
   1624         return (NULL);
   1625     }
   1626 #ifdef DEBUG_INCLUDE
   1627     xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL);
   1628 #endif
   1629 
   1630     /*
   1631      * Allocate the document structures and register it first.
   1632      */
   1633     ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));
   1634     if (ret == NULL) {
   1635         xmlRngPErrMemory(ctxt, "allocating include\n");
   1636         xmlFreeDoc(doc);
   1637         return (NULL);
   1638     }
   1639     memset(ret, 0, sizeof(xmlRelaxNGInclude));
   1640     ret->doc = doc;
   1641     ret->href = xmlStrdup(URL);
   1642     ret->next = ctxt->includes;
   1643     ctxt->includes = ret;
   1644 
   1645     /*
   1646      * transmit the ns if needed
   1647      */
   1648     if (ns != NULL) {
   1649         root = xmlDocGetRootElement(doc);
   1650         if (root != NULL) {
   1651             if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
   1652                 xmlSetProp(root, BAD_CAST "ns", ns);
   1653             }
   1654         }
   1655     }
   1656 
   1657     /*
   1658      * push it on the stack
   1659      */
   1660     xmlRelaxNGIncludePush(ctxt, ret);
   1661 
   1662     /*
   1663      * Some preprocessing of the document content, this include recursing
   1664      * in the include stack.
   1665      */
   1666 #ifdef DEBUG_INCLUDE
   1667     xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL);
   1668 #endif
   1669 
   1670     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
   1671     if (doc == NULL) {
   1672         ctxt->inc = NULL;
   1673         return (NULL);
   1674     }
   1675 
   1676     /*
   1677      * Pop up the include from the stack
   1678      */
   1679     xmlRelaxNGIncludePop(ctxt);
   1680 
   1681 #ifdef DEBUG_INCLUDE
   1682     xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL);
   1683 #endif
   1684     /*
   1685      * Check that the top element is a grammar
   1686      */
   1687     root = xmlDocGetRootElement(doc);
   1688     if (root == NULL) {
   1689         xmlRngPErr(ctxt, node, XML_RNGP_EMPTY,
   1690                    "xmlRelaxNG: included document is empty %s\n", URL,
   1691                    NULL);
   1692         return (NULL);
   1693     }
   1694     if (!IS_RELAXNG(root, "grammar")) {
   1695         xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
   1696                    "xmlRelaxNG: included document %s root is not a grammar\n",
   1697                    URL, NULL);
   1698         return (NULL);
   1699     }
   1700 
   1701     /*
   1702      * Elimination of redefined rules in the include.
   1703      */
   1704     cur = node->children;
   1705     while (cur != NULL) {
   1706         if (IS_RELAXNG(cur, "start")) {
   1707             int found = 0;
   1708 
   1709             found =
   1710                 xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);
   1711             if (!found) {
   1712                 xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING,
   1713                            "xmlRelaxNG: include %s has a start but not the included grammar\n",
   1714                            URL, NULL);
   1715             }
   1716         } else if (IS_RELAXNG(cur, "define")) {
   1717             xmlChar *name;
   1718 
   1719             name = xmlGetProp(cur, BAD_CAST "name");
   1720             if (name == NULL) {
   1721                 xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING,
   1722                            "xmlRelaxNG: include %s has define without name\n",
   1723                            URL, NULL);
   1724             } else {
   1725                 int found;
   1726 
   1727                 xmlRelaxNGNormExtSpace(name);
   1728                 found = xmlRelaxNGRemoveRedefine(ctxt, URL,
   1729                                                  root->children, name);
   1730                 if (!found) {
   1731                     xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING,
   1732                                "xmlRelaxNG: include %s has a define %s but not the included grammar\n",
   1733                                URL, name);
   1734                 }
   1735                 xmlFree(name);
   1736             }
   1737         }
   1738         cur = cur->next;
   1739     }
   1740 
   1741 
   1742     return (ret);
   1743 }
   1744 
   1745 /**
   1746  * xmlRelaxNGValidErrorPush:
   1747  * @ctxt:  the validation context
   1748  * @err:  the error code
   1749  * @arg1:  the first string argument
   1750  * @arg2:  the second string argument
   1751  * @dup:  arg need to be duplicated
   1752  *
   1753  * Pushes a new error on top of the error stack
   1754  *
   1755  * Returns 0 in case of error, the index in the stack otherwise
   1756  */
   1757 static int
   1758 xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
   1759                          xmlRelaxNGValidErr err, const xmlChar * arg1,
   1760                          const xmlChar * arg2, int dup)
   1761 {
   1762     xmlRelaxNGValidErrorPtr cur;
   1763 
   1764 #ifdef DEBUG_ERROR
   1765     xmlGenericError(xmlGenericErrorContext,
   1766                     "Pushing error %d at %d on stack\n", err, ctxt->errNr);
   1767 #endif
   1768     if (ctxt->errTab == NULL) {
   1769         ctxt->errMax = 8;
   1770         ctxt->errNr = 0;
   1771         ctxt->errTab =
   1772             (xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax *
   1773                                                 sizeof
   1774                                                 (xmlRelaxNGValidError));
   1775         if (ctxt->errTab == NULL) {
   1776             xmlRngVErrMemory(ctxt, "pushing error\n");
   1777             return (0);
   1778         }
   1779         ctxt->err = NULL;
   1780     }
   1781     if (ctxt->errNr >= ctxt->errMax) {
   1782         ctxt->errMax *= 2;
   1783         ctxt->errTab =
   1784             (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,
   1785                                                  ctxt->errMax *
   1786                                                  sizeof
   1787                                                  (xmlRelaxNGValidError));
   1788         if (ctxt->errTab == NULL) {
   1789             xmlRngVErrMemory(ctxt, "pushing error\n");
   1790             return (0);
   1791         }
   1792         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
   1793     }
   1794     if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
   1795         (ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err))
   1796         return (ctxt->errNr);
   1797     cur = &ctxt->errTab[ctxt->errNr];
   1798     cur->err = err;
   1799     if (dup) {
   1800         cur->arg1 = xmlStrdup(arg1);
   1801         cur->arg2 = xmlStrdup(arg2);
   1802         cur->flags = ERROR_IS_DUP;
   1803     } else {
   1804         cur->arg1 = arg1;
   1805         cur->arg2 = arg2;
   1806         cur->flags = 0;
   1807     }
   1808     if (ctxt->state != NULL) {
   1809         cur->node = ctxt->state->node;
   1810         cur->seq = ctxt->state->seq;
   1811     } else {
   1812         cur->node = NULL;
   1813         cur->seq = NULL;
   1814     }
   1815     ctxt->err = cur;
   1816     return (ctxt->errNr++);
   1817 }
   1818 
   1819 /**
   1820  * xmlRelaxNGValidErrorPop:
   1821  * @ctxt: the validation context
   1822  *
   1823  * Pops the top error from the error stack
   1824  */
   1825 static void
   1826 xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
   1827 {
   1828     xmlRelaxNGValidErrorPtr cur;
   1829 
   1830     if (ctxt->errNr <= 0) {
   1831         ctxt->err = NULL;
   1832         return;
   1833     }
   1834     ctxt->errNr--;
   1835     if (ctxt->errNr > 0)
   1836         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
   1837     else
   1838         ctxt->err = NULL;
   1839     cur = &ctxt->errTab[ctxt->errNr];
   1840     if (cur->flags & ERROR_IS_DUP) {
   1841         if (cur->arg1 != NULL)
   1842             xmlFree((xmlChar *) cur->arg1);
   1843         cur->arg1 = NULL;
   1844         if (cur->arg2 != NULL)
   1845             xmlFree((xmlChar *) cur->arg2);
   1846         cur->arg2 = NULL;
   1847         cur->flags = 0;
   1848     }
   1849 }
   1850 
   1851 /**
   1852  * xmlRelaxNGDocumentPush:
   1853  * @ctxt:  the parser context
   1854  * @value:  the element doc
   1855  *
   1856  * Pushes a new doc on top of the doc stack
   1857  *
   1858  * Returns 0 in case of error, the index in the stack otherwise
   1859  */
   1860 static int
   1861 xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
   1862                        xmlRelaxNGDocumentPtr value)
   1863 {
   1864     if (ctxt->docTab == NULL) {
   1865         ctxt->docMax = 4;
   1866         ctxt->docNr = 0;
   1867         ctxt->docTab =
   1868             (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *
   1869                                                 sizeof(ctxt->docTab[0]));
   1870         if (ctxt->docTab == NULL) {
   1871             xmlRngPErrMemory(ctxt, "adding document\n");
   1872             return (0);
   1873         }
   1874     }
   1875     if (ctxt->docNr >= ctxt->docMax) {
   1876         ctxt->docMax *= 2;
   1877         ctxt->docTab =
   1878             (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,
   1879                                                  ctxt->docMax *
   1880                                                  sizeof(ctxt->docTab[0]));
   1881         if (ctxt->docTab == NULL) {
   1882             xmlRngPErrMemory(ctxt, "adding document\n");
   1883             return (0);
   1884         }
   1885     }
   1886     ctxt->docTab[ctxt->docNr] = value;
   1887     ctxt->doc = value;
   1888     return (ctxt->docNr++);
   1889 }
   1890 
   1891 /**
   1892  * xmlRelaxNGDocumentPop:
   1893  * @ctxt: the parser context
   1894  *
   1895  * Pops the top doc from the doc stack
   1896  *
   1897  * Returns the doc just removed
   1898  */
   1899 static xmlRelaxNGDocumentPtr
   1900 xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)
   1901 {
   1902     xmlRelaxNGDocumentPtr ret;
   1903 
   1904     if (ctxt->docNr <= 0)
   1905         return (NULL);
   1906     ctxt->docNr--;
   1907     if (ctxt->docNr > 0)
   1908         ctxt->doc = ctxt->docTab[ctxt->docNr - 1];
   1909     else
   1910         ctxt->doc = NULL;
   1911     ret = ctxt->docTab[ctxt->docNr];
   1912     ctxt->docTab[ctxt->docNr] = NULL;
   1913     return (ret);
   1914 }
   1915 
   1916 /**
   1917  * xmlRelaxNGLoadExternalRef:
   1918  * @ctxt: the parser context
   1919  * @URL:  the normalized URL
   1920  * @ns:  the inherited ns if any
   1921  *
   1922  * First lookup if the document is already loaded into the parser context,
   1923  * check against recursion. If not found the resource is loaded and
   1924  * the content is preprocessed before being returned back to the caller.
   1925  *
   1926  * Returns the xmlRelaxNGDocumentPtr or NULL in case of error
   1927  */
   1928 static xmlRelaxNGDocumentPtr
   1929 xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
   1930                           const xmlChar * URL, const xmlChar * ns)
   1931 {
   1932     xmlRelaxNGDocumentPtr ret = NULL;
   1933     xmlDocPtr doc;
   1934     xmlNodePtr root;
   1935     int i;
   1936 
   1937     /*
   1938      * check against recursion in the stack
   1939      */
   1940     for (i = 0; i < ctxt->docNr; i++) {
   1941         if (xmlStrEqual(ctxt->docTab[i]->href, URL)) {
   1942             xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE,
   1943                        "Detected an externalRef recursion for %s\n", URL,
   1944                        NULL);
   1945             return (NULL);
   1946         }
   1947     }
   1948 
   1949     /*
   1950      * load the document
   1951      */
   1952     doc = xmlReadFile((const char *) URL,NULL,0);
   1953     if (doc == NULL) {
   1954         xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
   1955                    "xmlRelaxNG: could not load %s\n", URL, NULL);
   1956         return (NULL);
   1957     }
   1958 
   1959     /*
   1960      * Allocate the document structures and register it first.
   1961      */
   1962     ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
   1963     if (ret == NULL) {
   1964         xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,
   1965                    "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);
   1966         xmlFreeDoc(doc);
   1967         return (NULL);
   1968     }
   1969     memset(ret, 0, sizeof(xmlRelaxNGDocument));
   1970     ret->doc = doc;
   1971     ret->href = xmlStrdup(URL);
   1972     ret->next = ctxt->documents;
   1973     ctxt->documents = ret;
   1974 
   1975     /*
   1976      * transmit the ns if needed
   1977      */
   1978     if (ns != NULL) {
   1979         root = xmlDocGetRootElement(doc);
   1980         if (root != NULL) {
   1981             if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
   1982                 xmlSetProp(root, BAD_CAST "ns", ns);
   1983             }
   1984         }
   1985     }
   1986 
   1987     /*
   1988      * push it on the stack and register it in the hash table
   1989      */
   1990     xmlRelaxNGDocumentPush(ctxt, ret);
   1991 
   1992     /*
   1993      * Some preprocessing of the document content
   1994      */
   1995     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
   1996     if (doc == NULL) {
   1997         ctxt->doc = NULL;
   1998         return (NULL);
   1999     }
   2000 
   2001     xmlRelaxNGDocumentPop(ctxt);
   2002 
   2003     return (ret);
   2004 }
   2005 
   2006 /************************************************************************
   2007  * 									*
   2008  * 			Error functions					*
   2009  * 									*
   2010  ************************************************************************/
   2011 
   2012 #define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
   2013 #define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
   2014 #define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
   2015 #define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
   2016 #define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
   2017 
   2018 static const char *
   2019 xmlRelaxNGDefName(xmlRelaxNGDefinePtr def)
   2020 {
   2021     if (def == NULL)
   2022         return ("none");
   2023     switch (def->type) {
   2024         case XML_RELAXNG_EMPTY:
   2025             return ("empty");
   2026         case XML_RELAXNG_NOT_ALLOWED:
   2027             return ("notAllowed");
   2028         case XML_RELAXNG_EXCEPT:
   2029             return ("except");
   2030         case XML_RELAXNG_TEXT:
   2031             return ("text");
   2032         case XML_RELAXNG_ELEMENT:
   2033             return ("element");
   2034         case XML_RELAXNG_DATATYPE:
   2035             return ("datatype");
   2036         case XML_RELAXNG_VALUE:
   2037             return ("value");
   2038         case XML_RELAXNG_LIST:
   2039             return ("list");
   2040         case XML_RELAXNG_ATTRIBUTE:
   2041             return ("attribute");
   2042         case XML_RELAXNG_DEF:
   2043             return ("def");
   2044         case XML_RELAXNG_REF:
   2045             return ("ref");
   2046         case XML_RELAXNG_EXTERNALREF:
   2047             return ("externalRef");
   2048         case XML_RELAXNG_PARENTREF:
   2049             return ("parentRef");
   2050         case XML_RELAXNG_OPTIONAL:
   2051             return ("optional");
   2052         case XML_RELAXNG_ZEROORMORE:
   2053             return ("zeroOrMore");
   2054         case XML_RELAXNG_ONEORMORE:
   2055             return ("oneOrMore");
   2056         case XML_RELAXNG_CHOICE:
   2057             return ("choice");
   2058         case XML_RELAXNG_GROUP:
   2059             return ("group");
   2060         case XML_RELAXNG_INTERLEAVE:
   2061             return ("interleave");
   2062         case XML_RELAXNG_START:
   2063             return ("start");
   2064         case XML_RELAXNG_NOOP:
   2065             return ("noop");
   2066         case XML_RELAXNG_PARAM:
   2067             return ("param");
   2068     }
   2069     return ("unknown");
   2070 }
   2071 
   2072 /**
   2073  * xmlRelaxNGGetErrorString:
   2074  * @err:  the error code
   2075  * @arg1:  the first string argument
   2076  * @arg2:  the second string argument
   2077  *
   2078  * computes a formatted error string for the given error code and args
   2079  *
   2080  * Returns the error string, it must be deallocated by the caller
   2081  */
   2082 static xmlChar *
   2083 xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
   2084                          const xmlChar * arg2)
   2085 {
   2086     char msg[1000];
   2087 
   2088     if (arg1 == NULL)
   2089         arg1 = BAD_CAST "";
   2090     if (arg2 == NULL)
   2091         arg2 = BAD_CAST "";
   2092 
   2093     msg[0] = 0;
   2094     switch (err) {
   2095         case XML_RELAXNG_OK:
   2096             return (NULL);
   2097         case XML_RELAXNG_ERR_MEMORY:
   2098             return (xmlCharStrdup("out of memory\n"));
   2099         case XML_RELAXNG_ERR_TYPE:
   2100             snprintf(msg, 1000, "failed to validate type %s\n", arg1);
   2101             break;
   2102         case XML_RELAXNG_ERR_TYPEVAL:
   2103             snprintf(msg, 1000, "Type %s doesn't allow value '%s'\n", arg1,
   2104                      arg2);
   2105             break;
   2106         case XML_RELAXNG_ERR_DUPID:
   2107             snprintf(msg, 1000, "ID %s redefined\n", arg1);
   2108             break;
   2109         case XML_RELAXNG_ERR_TYPECMP:
   2110             snprintf(msg, 1000, "failed to compare type %s\n", arg1);
   2111             break;
   2112         case XML_RELAXNG_ERR_NOSTATE:
   2113             return (xmlCharStrdup("Internal error: no state\n"));
   2114         case XML_RELAXNG_ERR_NODEFINE:
   2115             return (xmlCharStrdup("Internal error: no define\n"));
   2116         case XML_RELAXNG_ERR_INTERNAL:
   2117             snprintf(msg, 1000, "Internal error: %s\n", arg1);
   2118             break;
   2119         case XML_RELAXNG_ERR_LISTEXTRA:
   2120             snprintf(msg, 1000, "Extra data in list: %s\n", arg1);
   2121             break;
   2122         case XML_RELAXNG_ERR_INTERNODATA:
   2123             return (xmlCharStrdup
   2124                     ("Internal: interleave block has no data\n"));
   2125         case XML_RELAXNG_ERR_INTERSEQ:
   2126             return (xmlCharStrdup("Invalid sequence in interleave\n"));
   2127         case XML_RELAXNG_ERR_INTEREXTRA:
   2128             snprintf(msg, 1000, "Extra element %s in interleave\n", arg1);
   2129             break;
   2130         case XML_RELAXNG_ERR_ELEMNAME:
   2131             snprintf(msg, 1000, "Expecting element %s, got %s\n", arg1,
   2132                      arg2);
   2133             break;
   2134         case XML_RELAXNG_ERR_ELEMNONS:
   2135             snprintf(msg, 1000, "Expecting a namespace for element %s\n",
   2136                      arg1);
   2137             break;
   2138         case XML_RELAXNG_ERR_ELEMWRONGNS:
   2139             snprintf(msg, 1000,
   2140                      "Element %s has wrong namespace: expecting %s\n", arg1,
   2141                      arg2);
   2142             break;
   2143         case XML_RELAXNG_ERR_ELEMWRONG:
   2144             snprintf(msg, 1000, "Did not expect element %s there\n", arg1);
   2145             break;
   2146         case XML_RELAXNG_ERR_TEXTWRONG:
   2147             snprintf(msg, 1000,
   2148                      "Did not expect text in element %s content\n", arg1);
   2149             break;
   2150         case XML_RELAXNG_ERR_ELEMEXTRANS:
   2151             snprintf(msg, 1000, "Expecting no namespace for element %s\n",
   2152                      arg1);
   2153             break;
   2154         case XML_RELAXNG_ERR_ELEMNOTEMPTY:
   2155             snprintf(msg, 1000, "Expecting element %s to be empty\n", arg1);
   2156             break;
   2157         case XML_RELAXNG_ERR_NOELEM:
   2158             snprintf(msg, 1000, "Expecting an element %s, got nothing\n",
   2159                      arg1);
   2160             break;
   2161         case XML_RELAXNG_ERR_NOTELEM:
   2162             return (xmlCharStrdup("Expecting an element got text\n"));
   2163         case XML_RELAXNG_ERR_ATTRVALID:
   2164             snprintf(msg, 1000, "Element %s failed to validate attributes\n",
   2165                      arg1);
   2166             break;
   2167         case XML_RELAXNG_ERR_CONTENTVALID:
   2168             snprintf(msg, 1000, "Element %s failed to validate content\n",
   2169                      arg1);
   2170             break;
   2171         case XML_RELAXNG_ERR_EXTRACONTENT:
   2172             snprintf(msg, 1000, "Element %s has extra content: %s\n",
   2173                      arg1, arg2);
   2174             break;
   2175         case XML_RELAXNG_ERR_INVALIDATTR:
   2176             snprintf(msg, 1000, "Invalid attribute %s for element %s\n",
   2177                      arg1, arg2);
   2178             break;
   2179         case XML_RELAXNG_ERR_LACKDATA:
   2180             snprintf(msg, 1000, "Datatype element %s contains no data\n",
   2181                      arg1);
   2182             break;
   2183         case XML_RELAXNG_ERR_DATAELEM:
   2184             snprintf(msg, 1000, "Datatype element %s has child elements\n",
   2185                      arg1);
   2186             break;
   2187         case XML_RELAXNG_ERR_VALELEM:
   2188             snprintf(msg, 1000, "Value element %s has child elements\n",
   2189                      arg1);
   2190             break;
   2191         case XML_RELAXNG_ERR_LISTELEM:
   2192             snprintf(msg, 1000, "List element %s has child elements\n",
   2193                      arg1);
   2194             break;
   2195         case XML_RELAXNG_ERR_DATATYPE:
   2196             snprintf(msg, 1000, "Error validating datatype %s\n", arg1);
   2197             break;
   2198         case XML_RELAXNG_ERR_VALUE:
   2199             snprintf(msg, 1000, "Error validating value %s\n", arg1);
   2200             break;
   2201         case XML_RELAXNG_ERR_LIST:
   2202             return (xmlCharStrdup("Error validating list\n"));
   2203         case XML_RELAXNG_ERR_NOGRAMMAR:
   2204             return (xmlCharStrdup("No top grammar defined\n"));
   2205         case XML_RELAXNG_ERR_EXTRADATA:
   2206             return (xmlCharStrdup("Extra data in the document\n"));
   2207         default:
   2208             return (xmlCharStrdup("Unknown error !\n"));
   2209     }
   2210     if (msg[0] == 0) {
   2211         snprintf(msg, 1000, "Unknown error code %d\n", err);
   2212     }
   2213     msg[1000 - 1] = 0;
   2214     return (xmlStrdup((xmlChar *) msg));
   2215 }
   2216 
   2217 /**
   2218  * xmlRelaxNGShowValidError:
   2219  * @ctxt:  the validation context
   2220  * @err:  the error number
   2221  * @node:  the node
   2222  * @child:  the node child generating the problem.
   2223  * @arg1:  the first argument
   2224  * @arg2:  the second argument
   2225  *
   2226  * Show a validation error.
   2227  */
   2228 static void
   2229 xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt,
   2230                          xmlRelaxNGValidErr err, xmlNodePtr node,
   2231                          xmlNodePtr child, const xmlChar * arg1,
   2232                          const xmlChar * arg2)
   2233 {
   2234     xmlChar *msg;
   2235 
   2236     if (ctxt->flags & FLAGS_NOERROR)
   2237         return;
   2238 
   2239 #ifdef DEBUG_ERROR
   2240     xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err);
   2241 #endif
   2242     msg = xmlRelaxNGGetErrorString(err, arg1, arg2);
   2243     if (msg == NULL)
   2244         return;
   2245 
   2246     if (ctxt->errNo == XML_RELAXNG_OK)
   2247         ctxt->errNo = err;
   2248     xmlRngVErr(ctxt, (child == NULL ? node : child), err,
   2249                (const char *) msg, arg1, arg2);
   2250     xmlFree(msg);
   2251 }
   2252 
   2253 /**
   2254  * xmlRelaxNGPopErrors:
   2255  * @ctxt:  the validation context
   2256  * @level:  the error level in the stack
   2257  *
   2258  * pop and discard all errors until the given level is reached
   2259  */
   2260 static void
   2261 xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level)
   2262 {
   2263     int i;
   2264     xmlRelaxNGValidErrorPtr err;
   2265 
   2266 #ifdef DEBUG_ERROR
   2267     xmlGenericError(xmlGenericErrorContext,
   2268                     "Pop errors till level %d\n", level);
   2269 #endif
   2270     for (i = level; i < ctxt->errNr; i++) {
   2271         err = &ctxt->errTab[i];
   2272         if (err->flags & ERROR_IS_DUP) {
   2273             if (err->arg1 != NULL)
   2274                 xmlFree((xmlChar *) err->arg1);
   2275             err->arg1 = NULL;
   2276             if (err->arg2 != NULL)
   2277                 xmlFree((xmlChar *) err->arg2);
   2278             err->arg2 = NULL;
   2279             err->flags = 0;
   2280         }
   2281     }
   2282     ctxt->errNr = level;
   2283     if (ctxt->errNr <= 0)
   2284         ctxt->err = NULL;
   2285 }
   2286 
   2287 /**
   2288  * xmlRelaxNGDumpValidError:
   2289  * @ctxt:  the validation context
   2290  *
   2291  * Show all validation error over a given index.
   2292  */
   2293 static void
   2294 xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt)
   2295 {
   2296     int i, j, k;
   2297     xmlRelaxNGValidErrorPtr err, dup;
   2298 
   2299 #ifdef DEBUG_ERROR
   2300     xmlGenericError(xmlGenericErrorContext,
   2301                     "Dumping error stack %d errors\n", ctxt->errNr);
   2302 #endif
   2303     for (i = 0, k = 0; i < ctxt->errNr; i++) {
   2304         err = &ctxt->errTab[i];
   2305         if (k < MAX_ERROR) {
   2306             for (j = 0; j < i; j++) {
   2307                 dup = &ctxt->errTab[j];
   2308                 if ((err->err == dup->err) && (err->node == dup->node) &&
   2309                     (xmlStrEqual(err->arg1, dup->arg1)) &&
   2310                     (xmlStrEqual(err->arg2, dup->arg2))) {
   2311                     goto skip;
   2312                 }
   2313             }
   2314             xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,
   2315                                      err->arg1, err->arg2);
   2316             k++;
   2317         }
   2318       skip:
   2319         if (err->flags & ERROR_IS_DUP) {
   2320             if (err->arg1 != NULL)
   2321                 xmlFree((xmlChar *) err->arg1);
   2322             err->arg1 = NULL;
   2323             if (err->arg2 != NULL)
   2324                 xmlFree((xmlChar *) err->arg2);
   2325             err->arg2 = NULL;
   2326             err->flags = 0;
   2327         }
   2328     }
   2329     ctxt->errNr = 0;
   2330 }
   2331 
   2332 /**
   2333  * xmlRelaxNGAddValidError:
   2334  * @ctxt:  the validation context
   2335  * @err:  the error number
   2336  * @arg1:  the first argument
   2337  * @arg2:  the second argument
   2338  * @dup:  need to dup the args
   2339  *
   2340  * Register a validation error, either generating it if it's sure
   2341  * or stacking it for later handling if unsure.
   2342  */
   2343 static void
   2344 xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt,
   2345                         xmlRelaxNGValidErr err, const xmlChar * arg1,
   2346                         const xmlChar * arg2, int dup)
   2347 {
   2348     if (ctxt == NULL)
   2349         return;
   2350     if (ctxt->flags & FLAGS_NOERROR)
   2351         return;
   2352 
   2353 #ifdef DEBUG_ERROR
   2354     xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err);
   2355 #endif
   2356     /*
   2357      * generate the error directly
   2358      */
   2359     if (((ctxt->flags & FLAGS_IGNORABLE) == 0) ||
   2360     	 (ctxt->flags & FLAGS_NEGATIVE)) {
   2361         xmlNodePtr node, seq;
   2362 
   2363         /*
   2364          * Flush first any stacked error which might be the
   2365          * real cause of the problem.
   2366          */
   2367         if (ctxt->errNr != 0)
   2368             xmlRelaxNGDumpValidError(ctxt);
   2369         if (ctxt->state != NULL) {
   2370             node = ctxt->state->node;
   2371             seq = ctxt->state->seq;
   2372         } else {
   2373             node = seq = NULL;
   2374         }
   2375         xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2);
   2376     }
   2377     /*
   2378      * Stack the error for later processing if needed
   2379      */
   2380     else {
   2381         xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);
   2382     }
   2383 }
   2384 
   2385 
   2386 /************************************************************************
   2387  * 									*
   2388  * 			Type library hooks				*
   2389  * 									*
   2390  ************************************************************************/
   2391 static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt,
   2392                                     const xmlChar * str);
   2393 
   2394 /**
   2395  * xmlRelaxNGSchemaTypeHave:
   2396  * @data:  data needed for the library
   2397  * @type:  the type name
   2398  *
   2399  * Check if the given type is provided by
   2400  * the W3C XMLSchema Datatype library.
   2401  *
   2402  * Returns 1 if yes, 0 if no and -1 in case of error.
   2403  */
   2404 static int
   2405 xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar * type)
   2406 {
   2407     xmlSchemaTypePtr typ;
   2408 
   2409     if (type == NULL)
   2410         return (-1);
   2411     typ = xmlSchemaGetPredefinedType(type,
   2412                                      BAD_CAST
   2413                                      "http://www.w3.org/2001/XMLSchema");
   2414     if (typ == NULL)
   2415         return (0);
   2416     return (1);
   2417 }
   2418 
   2419 /**
   2420  * xmlRelaxNGSchemaTypeCheck:
   2421  * @data:  data needed for the library
   2422  * @type:  the type name
   2423  * @value:  the value to check
   2424  * @node:  the node
   2425  *
   2426  * Check if the given type and value are validated by
   2427  * the W3C XMLSchema Datatype library.
   2428  *
   2429  * Returns 1 if yes, 0 if no and -1 in case of error.
   2430  */
   2431 static int
   2432 xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
   2433                           const xmlChar * type,
   2434                           const xmlChar * value,
   2435                           void **result, xmlNodePtr node)
   2436 {
   2437     xmlSchemaTypePtr typ;
   2438     int ret;
   2439 
   2440     if ((type == NULL) || (value == NULL))
   2441         return (-1);
   2442     typ = xmlSchemaGetPredefinedType(type,
   2443                                      BAD_CAST
   2444                                      "http://www.w3.org/2001/XMLSchema");
   2445     if (typ == NULL)
   2446         return (-1);
   2447     ret = xmlSchemaValPredefTypeNode(typ, value,
   2448                                      (xmlSchemaValPtr *) result, node);
   2449     if (ret == 2)               /* special ID error code */
   2450         return (2);
   2451     if (ret == 0)
   2452         return (1);
   2453     if (ret > 0)
   2454         return (0);
   2455     return (-1);
   2456 }
   2457 
   2458 /**
   2459  * xmlRelaxNGSchemaFacetCheck:
   2460  * @data:  data needed for the library
   2461  * @type:  the type name
   2462  * @facet:  the facet name
   2463  * @val:  the facet value
   2464  * @strval:  the string value
   2465  * @value:  the value to check
   2466  *
   2467  * Function provided by a type library to check a value facet
   2468  *
   2469  * Returns 1 if yes, 0 if no and -1 in case of error.
   2470  */
   2471 static int
   2472 xmlRelaxNGSchemaFacetCheck(void *data ATTRIBUTE_UNUSED,
   2473                            const xmlChar * type, const xmlChar * facetname,
   2474                            const xmlChar * val, const xmlChar * strval,
   2475                            void *value)
   2476 {
   2477     xmlSchemaFacetPtr facet;
   2478     xmlSchemaTypePtr typ;
   2479     int ret;
   2480 
   2481     if ((type == NULL) || (strval == NULL))
   2482         return (-1);
   2483     typ = xmlSchemaGetPredefinedType(type,
   2484                                      BAD_CAST
   2485                                      "http://www.w3.org/2001/XMLSchema");
   2486     if (typ == NULL)
   2487         return (-1);
   2488 
   2489     facet = xmlSchemaNewFacet();
   2490     if (facet == NULL)
   2491         return (-1);
   2492 
   2493     if (xmlStrEqual(facetname, BAD_CAST "minInclusive")) {
   2494         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
   2495     } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive")) {
   2496         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
   2497     } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive")) {
   2498         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
   2499     } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive")) {
   2500         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
   2501     } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits")) {
   2502         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
   2503     } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits")) {
   2504         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
   2505     } else if (xmlStrEqual(facetname, BAD_CAST "pattern")) {
   2506         facet->type = XML_SCHEMA_FACET_PATTERN;
   2507     } else if (xmlStrEqual(facetname, BAD_CAST "enumeration")) {
   2508         facet->type = XML_SCHEMA_FACET_ENUMERATION;
   2509     } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace")) {
   2510         facet->type = XML_SCHEMA_FACET_WHITESPACE;
   2511     } else if (xmlStrEqual(facetname, BAD_CAST "length")) {
   2512         facet->type = XML_SCHEMA_FACET_LENGTH;
   2513     } else if (xmlStrEqual(facetname, BAD_CAST "maxLength")) {
   2514         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
   2515     } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) {
   2516         facet->type = XML_SCHEMA_FACET_MINLENGTH;
   2517     } else {
   2518         xmlSchemaFreeFacet(facet);
   2519         return (-1);
   2520     }
   2521     facet->value = val;
   2522     ret = xmlSchemaCheckFacet(facet, typ, NULL, type);
   2523     if (ret != 0) {
   2524         xmlSchemaFreeFacet(facet);
   2525         return (-1);
   2526     }
   2527     ret = xmlSchemaValidateFacet(typ, facet, strval, value);
   2528     xmlSchemaFreeFacet(facet);
   2529     if (ret != 0)
   2530         return (-1);
   2531     return (0);
   2532 }
   2533 
   2534 /**
   2535  * xmlRelaxNGSchemaFreeValue:
   2536  * @data:  data needed for the library
   2537  * @value:  the value to free
   2538  *
   2539  * Function provided by a type library to free a Schemas value
   2540  *
   2541  * Returns 1 if yes, 0 if no and -1 in case of error.
   2542  */
   2543 static void
   2544 xmlRelaxNGSchemaFreeValue(void *data ATTRIBUTE_UNUSED, void *value)
   2545 {
   2546     xmlSchemaFreeValue(value);
   2547 }
   2548 
   2549 /**
   2550  * xmlRelaxNGSchemaTypeCompare:
   2551  * @data:  data needed for the library
   2552  * @type:  the type name
   2553  * @value1:  the first value
   2554  * @value2:  the second value
   2555  *
   2556  * Compare two values for equality accordingly a type from the W3C XMLSchema
   2557  * Datatype library.
   2558  *
   2559  * Returns 1 if equal, 0 if no and -1 in case of error.
   2560  */
   2561 static int
   2562 xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
   2563                             const xmlChar * type,
   2564                             const xmlChar * value1,
   2565                             xmlNodePtr ctxt1,
   2566                             void *comp1,
   2567                             const xmlChar * value2, xmlNodePtr ctxt2)
   2568 {
   2569     int ret;
   2570     xmlSchemaTypePtr typ;
   2571     xmlSchemaValPtr res1 = NULL, res2 = NULL;
   2572 
   2573     if ((type == NULL) || (value1 == NULL) || (value2 == NULL))
   2574         return (-1);
   2575     typ = xmlSchemaGetPredefinedType(type,
   2576                                      BAD_CAST
   2577                                      "http://www.w3.org/2001/XMLSchema");
   2578     if (typ == NULL)
   2579         return (-1);
   2580     if (comp1 == NULL) {
   2581         ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1);
   2582         if (ret != 0)
   2583             return (-1);
   2584         if (res1 == NULL)
   2585             return (-1);
   2586     } else {
   2587         res1 = (xmlSchemaValPtr) comp1;
   2588     }
   2589     ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2);
   2590     if (ret != 0) {
   2591 	if ((comp1 == NULL) && (res1 != NULL))
   2592 	    xmlSchemaFreeValue(res1);
   2593         return (-1);
   2594     }
   2595     if (res1 == NULL) {
   2596         return (-1);
   2597     }
   2598     ret = xmlSchemaCompareValues(res1, res2);
   2599     if (res1 != (xmlSchemaValPtr) comp1)
   2600         xmlSchemaFreeValue(res1);
   2601     xmlSchemaFreeValue(res2);
   2602     if (ret == -2)
   2603         return (-1);
   2604     if (ret == 0)
   2605         return (1);
   2606     return (0);
   2607 }
   2608 
   2609 /**
   2610  * xmlRelaxNGDefaultTypeHave:
   2611  * @data:  data needed for the library
   2612  * @type:  the type name
   2613  *
   2614  * Check if the given type is provided by
   2615  * the default datatype library.
   2616  *
   2617  * Returns 1 if yes, 0 if no and -1 in case of error.
   2618  */
   2619 static int
   2620 xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED,
   2621                           const xmlChar * type)
   2622 {
   2623     if (type == NULL)
   2624         return (-1);
   2625     if (xmlStrEqual(type, BAD_CAST "string"))
   2626         return (1);
   2627     if (xmlStrEqual(type, BAD_CAST "token"))
   2628         return (1);
   2629     return (0);
   2630 }
   2631 
   2632 /**
   2633  * xmlRelaxNGDefaultTypeCheck:
   2634  * @data:  data needed for the library
   2635  * @type:  the type name
   2636  * @value:  the value to check
   2637  * @node:  the node
   2638  *
   2639  * Check if the given type and value are validated by
   2640  * the default datatype library.
   2641  *
   2642  * Returns 1 if yes, 0 if no and -1 in case of error.
   2643  */
   2644 static int
   2645 xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
   2646                            const xmlChar * type ATTRIBUTE_UNUSED,
   2647                            const xmlChar * value ATTRIBUTE_UNUSED,
   2648                            void **result ATTRIBUTE_UNUSED,
   2649                            xmlNodePtr node ATTRIBUTE_UNUSED)
   2650 {
   2651     if (value == NULL)
   2652         return (-1);
   2653     if (xmlStrEqual(type, BAD_CAST "string"))
   2654         return (1);
   2655     if (xmlStrEqual(type, BAD_CAST "token")) {
   2656         return (1);
   2657     }
   2658 
   2659     return (0);
   2660 }
   2661 
   2662 /**
   2663  * xmlRelaxNGDefaultTypeCompare:
   2664  * @data:  data needed for the library
   2665  * @type:  the type name
   2666  * @value1:  the first value
   2667  * @value2:  the second value
   2668  *
   2669  * Compare two values accordingly a type from the default
   2670  * datatype library.
   2671  *
   2672  * Returns 1 if yes, 0 if no and -1 in case of error.
   2673  */
   2674 static int
   2675 xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
   2676                              const xmlChar * type,
   2677                              const xmlChar * value1,
   2678                              xmlNodePtr ctxt1 ATTRIBUTE_UNUSED,
   2679                              void *comp1 ATTRIBUTE_UNUSED,
   2680                              const xmlChar * value2,
   2681                              xmlNodePtr ctxt2 ATTRIBUTE_UNUSED)
   2682 {
   2683     int ret = -1;
   2684 
   2685     if (xmlStrEqual(type, BAD_CAST "string")) {
   2686         ret = xmlStrEqual(value1, value2);
   2687     } else if (xmlStrEqual(type, BAD_CAST "token")) {
   2688         if (!xmlStrEqual(value1, value2)) {
   2689             xmlChar *nval, *nvalue;
   2690 
   2691             /*
   2692              * TODO: trivial optimizations are possible by
   2693              * computing at compile-time
   2694              */
   2695             nval = xmlRelaxNGNormalize(NULL, value1);
   2696             nvalue = xmlRelaxNGNormalize(NULL, value2);
   2697 
   2698             if ((nval == NULL) || (nvalue == NULL))
   2699                 ret = -1;
   2700             else if (xmlStrEqual(nval, nvalue))
   2701                 ret = 1;
   2702             else
   2703                 ret = 0;
   2704             if (nval != NULL)
   2705                 xmlFree(nval);
   2706             if (nvalue != NULL)
   2707                 xmlFree(nvalue);
   2708         } else
   2709             ret = 1;
   2710     }
   2711     return (ret);
   2712 }
   2713 
   2714 static int xmlRelaxNGTypeInitialized = 0;
   2715 static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
   2716 
   2717 /**
   2718  * xmlRelaxNGFreeTypeLibrary:
   2719  * @lib:  the type library structure
   2720  * @namespace:  the URI bound to the library
   2721  *
   2722  * Free the structure associated to the type library
   2723  */
   2724 static void
   2725 xmlRelaxNGFreeTypeLibrary(xmlRelaxNGTypeLibraryPtr lib,
   2726                           const xmlChar * namespace ATTRIBUTE_UNUSED)
   2727 {
   2728     if (lib == NULL)
   2729         return;
   2730     if (lib->namespace != NULL)
   2731         xmlFree((xmlChar *) lib->namespace);
   2732     xmlFree(lib);
   2733 }
   2734 
   2735 /**
   2736  * xmlRelaxNGRegisterTypeLibrary:
   2737  * @namespace:  the URI bound to the library
   2738  * @data:  data associated to the library
   2739  * @have:  the provide function
   2740  * @check:  the checking function
   2741  * @comp:  the comparison function
   2742  *
   2743  * Register a new type library
   2744  *
   2745  * Returns 0 in case of success and -1 in case of error.
   2746  */
   2747 static int
   2748 xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,
   2749                               xmlRelaxNGTypeHave have,
   2750                               xmlRelaxNGTypeCheck check,
   2751                               xmlRelaxNGTypeCompare comp,
   2752                               xmlRelaxNGFacetCheck facet,
   2753                               xmlRelaxNGTypeFree freef)
   2754 {
   2755     xmlRelaxNGTypeLibraryPtr lib;
   2756     int ret;
   2757 
   2758     if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
   2759         (check == NULL) || (comp == NULL))
   2760         return (-1);
   2761     if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
   2762         xmlGenericError(xmlGenericErrorContext,
   2763                         "Relax-NG types library '%s' already registered\n",
   2764                         namespace);
   2765         return (-1);
   2766     }
   2767     lib =
   2768         (xmlRelaxNGTypeLibraryPtr)
   2769         xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
   2770     if (lib == NULL) {
   2771         xmlRngVErrMemory(NULL, "adding types library\n");
   2772         return (-1);
   2773     }
   2774     memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
   2775     lib->namespace = xmlStrdup(namespace);
   2776     lib->data = data;
   2777     lib->have = have;
   2778     lib->comp = comp;
   2779     lib->check = check;
   2780     lib->facet = facet;
   2781     lib->freef = freef;
   2782     ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
   2783     if (ret < 0) {
   2784         xmlGenericError(xmlGenericErrorContext,
   2785                         "Relax-NG types library failed to register '%s'\n",
   2786                         namespace);
   2787         xmlRelaxNGFreeTypeLibrary(lib, namespace);
   2788         return (-1);
   2789     }
   2790     return (0);
   2791 }
   2792 
   2793 /**
   2794  * xmlRelaxNGInitTypes:
   2795  *
   2796  * Initilize the default type libraries.
   2797  *
   2798  * Returns 0 in case of success and -1 in case of error.
   2799  */
   2800 int
   2801 xmlRelaxNGInitTypes(void)
   2802 {
   2803     if (xmlRelaxNGTypeInitialized != 0)
   2804         return (0);
   2805     xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
   2806     if (xmlRelaxNGRegisteredTypes == NULL) {
   2807         xmlGenericError(xmlGenericErrorContext,
   2808                         "Failed to allocate sh table for Relax-NG types\n");
   2809         return (-1);
   2810     }
   2811     xmlRelaxNGRegisterTypeLibrary(BAD_CAST
   2812                                   "http://www.w3.org/2001/XMLSchema-datatypes",
   2813                                   NULL, xmlRelaxNGSchemaTypeHave,
   2814                                   xmlRelaxNGSchemaTypeCheck,
   2815                                   xmlRelaxNGSchemaTypeCompare,
   2816                                   xmlRelaxNGSchemaFacetCheck,
   2817                                   xmlRelaxNGSchemaFreeValue);
   2818     xmlRelaxNGRegisterTypeLibrary(xmlRelaxNGNs, NULL,
   2819                                   xmlRelaxNGDefaultTypeHave,
   2820                                   xmlRelaxNGDefaultTypeCheck,
   2821                                   xmlRelaxNGDefaultTypeCompare, NULL,
   2822                                   NULL);
   2823     xmlRelaxNGTypeInitialized = 1;
   2824     return (0);
   2825 }
   2826 
   2827 /**
   2828  * xmlRelaxNGCleanupTypes:
   2829  *
   2830  * Cleanup the default Schemas type library associated to RelaxNG
   2831  */
   2832 void
   2833 xmlRelaxNGCleanupTypes(void)
   2834 {
   2835     xmlSchemaCleanupTypes();
   2836     if (xmlRelaxNGTypeInitialized == 0)
   2837         return;
   2838     xmlHashFree(xmlRelaxNGRegisteredTypes, (xmlHashDeallocator)
   2839                 xmlRelaxNGFreeTypeLibrary);
   2840     xmlRelaxNGTypeInitialized = 0;
   2841 }
   2842 
   2843 /************************************************************************
   2844  * 									*
   2845  * 		Compiling element content into regexp			*
   2846  * 									*
   2847  * Sometime the element content can be compiled into a pure regexp,	*
   2848  * This allows a faster execution and streamability at that level	*
   2849  * 									*
   2850  ************************************************************************/
   2851 
   2852 static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,
   2853                                 xmlRelaxNGDefinePtr def);
   2854 
   2855 /**
   2856  * xmlRelaxNGIsCompileable:
   2857  * @define:  the definition to check
   2858  *
   2859  * Check if a definition is nullable.
   2860  *
   2861  * Returns 1 if yes, 0 if no and -1 in case of error
   2862  */
   2863 static int
   2864 xmlRelaxNGIsCompileable(xmlRelaxNGDefinePtr def)
   2865 {
   2866     int ret = -1;
   2867 
   2868     if (def == NULL) {
   2869         return (-1);
   2870     }
   2871     if ((def->type != XML_RELAXNG_ELEMENT) &&
   2872         (def->dflags & IS_COMPILABLE))
   2873         return (1);
   2874     if ((def->type != XML_RELAXNG_ELEMENT) &&
   2875         (def->dflags & IS_NOT_COMPILABLE))
   2876         return (0);
   2877     switch (def->type) {
   2878         case XML_RELAXNG_NOOP:
   2879             ret = xmlRelaxNGIsCompileable(def->content);
   2880             break;
   2881         case XML_RELAXNG_TEXT:
   2882         case XML_RELAXNG_EMPTY:
   2883             ret = 1;
   2884             break;
   2885         case XML_RELAXNG_ELEMENT:
   2886             /*
   2887              * Check if the element content is compileable
   2888              */
   2889             if (((def->dflags & IS_NOT_COMPILABLE) == 0) &&
   2890                 ((def->dflags & IS_COMPILABLE) == 0)) {
   2891                 xmlRelaxNGDefinePtr list;
   2892 
   2893                 list = def->content;
   2894                 while (list != NULL) {
   2895                     ret = xmlRelaxNGIsCompileable(list);
   2896                     if (ret != 1)
   2897                         break;
   2898                     list = list->next;
   2899                 }
   2900 		/*
   2901 		 * Because the routine is recursive, we must guard against
   2902 		 * discovering both COMPILABLE and NOT_COMPILABLE
   2903 		 */
   2904                 if (ret == 0) {
   2905 		    def->dflags &= ~IS_COMPILABLE;
   2906                     def->dflags |= IS_NOT_COMPILABLE;
   2907 		}
   2908                 if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE))
   2909                     def->dflags |= IS_COMPILABLE;
   2910 #ifdef DEBUG_COMPILE
   2911                 if (ret == 1) {
   2912                     xmlGenericError(xmlGenericErrorContext,
   2913                                     "element content for %s is compilable\n",
   2914                                     def->name);
   2915                 } else if (ret == 0) {
   2916                     xmlGenericError(xmlGenericErrorContext,
   2917                                     "element content for %s is not compilable\n",
   2918                                     def->name);
   2919                 } else {
   2920                     xmlGenericError(xmlGenericErrorContext,
   2921                                     "Problem in RelaxNGIsCompileable for element %s\n",
   2922                                     def->name);
   2923                 }
   2924 #endif
   2925             }
   2926             /*
   2927              * All elements return a compileable status unless they
   2928              * are generic like anyName
   2929              */
   2930             if ((def->nameClass != NULL) || (def->name == NULL))
   2931                 ret = 0;
   2932             else
   2933                 ret = 1;
   2934             return (ret);
   2935         case XML_RELAXNG_REF:
   2936         case XML_RELAXNG_EXTERNALREF:
   2937         case XML_RELAXNG_PARENTREF:
   2938             if (def->depth == -20) {
   2939                 return (1);
   2940             } else {
   2941                 xmlRelaxNGDefinePtr list;
   2942 
   2943                 def->depth = -20;
   2944                 list = def->content;
   2945                 while (list != NULL) {
   2946                     ret = xmlRelaxNGIsCompileable(list);
   2947                     if (ret != 1)
   2948                         break;
   2949                     list = list->next;
   2950                 }
   2951             }
   2952             break;
   2953         case XML_RELAXNG_START:
   2954         case XML_RELAXNG_OPTIONAL:
   2955         case XML_RELAXNG_ZEROORMORE:
   2956         case XML_RELAXNG_ONEORMORE:
   2957         case XML_RELAXNG_CHOICE:
   2958         case XML_RELAXNG_GROUP:
   2959         case XML_RELAXNG_DEF:{
   2960                 xmlRelaxNGDefinePtr list;
   2961 
   2962                 list = def->content;
   2963                 while (list != NULL) {
   2964                     ret = xmlRelaxNGIsCompileable(list);
   2965                     if (ret != 1)
   2966                         break;
   2967                     list = list->next;
   2968                 }
   2969                 break;
   2970             }
   2971         case XML_RELAXNG_EXCEPT:
   2972         case XML_RELAXNG_ATTRIBUTE:
   2973         case XML_RELAXNG_INTERLEAVE:
   2974         case XML_RELAXNG_DATATYPE:
   2975         case XML_RELAXNG_LIST:
   2976         case XML_RELAXNG_PARAM:
   2977         case XML_RELAXNG_VALUE:
   2978         case XML_RELAXNG_NOT_ALLOWED:
   2979             ret = 0;
   2980             break;
   2981     }
   2982     if (ret == 0)
   2983         def->dflags |= IS_NOT_COMPILABLE;
   2984     if (ret == 1)
   2985         def->dflags |= IS_COMPILABLE;
   2986 #ifdef DEBUG_COMPILE
   2987     if (ret == 1) {
   2988         xmlGenericError(xmlGenericErrorContext,
   2989                         "RelaxNGIsCompileable %s : true\n",
   2990                         xmlRelaxNGDefName(def));
   2991     } else if (ret == 0) {
   2992         xmlGenericError(xmlGenericErrorContext,
   2993                         "RelaxNGIsCompileable %s : false\n",
   2994                         xmlRelaxNGDefName(def));
   2995     } else {
   2996         xmlGenericError(xmlGenericErrorContext,
   2997                         "Problem in RelaxNGIsCompileable %s\n",
   2998                         xmlRelaxNGDefName(def));
   2999     }
   3000 #endif
   3001     return (ret);
   3002 }
   3003 
   3004 /**
   3005  * xmlRelaxNGCompile:
   3006  * ctxt:  the RelaxNG parser context
   3007  * @define:  the definition tree to compile
   3008  *
   3009  * Compile the set of definitions, it works recursively, till the
   3010  * element boundaries, where it tries to compile the content if possible
   3011  *
   3012  * Returns 0 if success and -1 in case of error
   3013  */
   3014 static int
   3015 xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
   3016 {
   3017     int ret = 0;
   3018     xmlRelaxNGDefinePtr list;
   3019 
   3020     if ((ctxt == NULL) || (def == NULL))
   3021         return (-1);
   3022 
   3023     switch (def->type) {
   3024         case XML_RELAXNG_START:
   3025             if ((xmlRelaxNGIsCompileable(def) == 1) && (def->depth != -25)) {
   3026                 xmlAutomataPtr oldam = ctxt->am;
   3027                 xmlAutomataStatePtr oldstate = ctxt->state;
   3028 
   3029                 def->depth = -25;
   3030 
   3031                 list = def->content;
   3032                 ctxt->am = xmlNewAutomata();
   3033                 if (ctxt->am == NULL)
   3034                     return (-1);
   3035                 ctxt->state = xmlAutomataGetInitState(ctxt->am);
   3036                 while (list != NULL) {
   3037                     xmlRelaxNGCompile(ctxt, list);
   3038                     list = list->next;
   3039                 }
   3040                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
   3041                 def->contModel = xmlAutomataCompile(ctxt->am);
   3042                 xmlRegexpIsDeterminist(def->contModel);
   3043 
   3044                 xmlFreeAutomata(ctxt->am);
   3045                 ctxt->state = oldstate;
   3046                 ctxt->am = oldam;
   3047             }
   3048             break;
   3049         case XML_RELAXNG_ELEMENT:
   3050             if ((ctxt->am != NULL) && (def->name != NULL)) {
   3051                 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
   3052                                                         ctxt->state, NULL,
   3053                                                         def->name, def->ns,
   3054                                                         def);
   3055             }
   3056             if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
   3057                 xmlAutomataPtr oldam = ctxt->am;
   3058                 xmlAutomataStatePtr oldstate = ctxt->state;
   3059 
   3060                 def->depth = -25;
   3061 
   3062                 list = def->content;
   3063                 ctxt->am = xmlNewAutomata();
   3064                 if (ctxt->am == NULL)
   3065                     return (-1);
   3066                 ctxt->state = xmlAutomataGetInitState(ctxt->am);
   3067                 while (list != NULL) {
   3068                     xmlRelaxNGCompile(ctxt, list);
   3069                     list = list->next;
   3070                 }
   3071                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
   3072                 def->contModel = xmlAutomataCompile(ctxt->am);
   3073                 if (!xmlRegexpIsDeterminist(def->contModel)) {
   3074                     /*
   3075                      * we can only use the automata if it is determinist
   3076                      */
   3077                     xmlRegFreeRegexp(def->contModel);
   3078                     def->contModel = NULL;
   3079                 }
   3080                 xmlFreeAutomata(ctxt->am);
   3081                 ctxt->state = oldstate;
   3082                 ctxt->am = oldam;
   3083             } else {
   3084                 xmlAutomataPtr oldam = ctxt->am;
   3085 
   3086                 /*
   3087                  * we can't build the content model for this element content
   3088                  * but it still might be possible to build it for some of its
   3089                  * children, recurse.
   3090                  */
   3091                 ret = xmlRelaxNGTryCompile(ctxt, def);
   3092                 ctxt->am = oldam;
   3093             }
   3094             break;
   3095         case XML_RELAXNG_NOOP:
   3096             ret = xmlRelaxNGCompile(ctxt, def->content);
   3097             break;
   3098         case XML_RELAXNG_OPTIONAL:{
   3099                 xmlAutomataStatePtr oldstate = ctxt->state;
   3100 
   3101                 xmlRelaxNGCompile(ctxt, def->content);
   3102                 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
   3103                 break;
   3104             }
   3105         case XML_RELAXNG_ZEROORMORE:{
   3106                 xmlAutomataStatePtr oldstate;
   3107 
   3108                 ctxt->state =
   3109                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
   3110                 oldstate = ctxt->state;
   3111                 list = def->content;
   3112                 while (list != NULL) {
   3113                     xmlRelaxNGCompile(ctxt, list);
   3114                     list = list->next;
   3115                 }
   3116                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
   3117                 ctxt->state =
   3118                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
   3119                 break;
   3120             }
   3121         case XML_RELAXNG_ONEORMORE:{
   3122                 xmlAutomataStatePtr oldstate;
   3123 
   3124                 list = def->content;
   3125                 while (list != NULL) {
   3126                     xmlRelaxNGCompile(ctxt, list);
   3127                     list = list->next;
   3128                 }
   3129                 oldstate = ctxt->state;
   3130                 list = def->content;
   3131                 while (list != NULL) {
   3132                     xmlRelaxNGCompile(ctxt, list);
   3133                     list = list->next;
   3134                 }
   3135                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
   3136                 ctxt->state =
   3137                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
   3138                 break;
   3139             }
   3140         case XML_RELAXNG_CHOICE:{
   3141                 xmlAutomataStatePtr target = NULL;
   3142                 xmlAutomataStatePtr oldstate = ctxt->state;
   3143 
   3144                 list = def->content;
   3145                 while (list != NULL) {
   3146                     ctxt->state = oldstate;
   3147                     ret = xmlRelaxNGCompile(ctxt, list);
   3148                     if (ret != 0)
   3149                         break;
   3150                     if (target == NULL)
   3151                         target = ctxt->state;
   3152                     else {
   3153                         xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
   3154                                               target);
   3155                     }
   3156                     list = list->next;
   3157                 }
   3158                 ctxt->state = target;
   3159 
   3160                 break;
   3161             }
   3162         case XML_RELAXNG_REF:
   3163         case XML_RELAXNG_EXTERNALREF:
   3164         case XML_RELAXNG_PARENTREF:
   3165         case XML_RELAXNG_GROUP:
   3166         case XML_RELAXNG_DEF:
   3167             list = def->content;
   3168             while (list != NULL) {
   3169                 ret = xmlRelaxNGCompile(ctxt, list);
   3170                 if (ret != 0)
   3171                     break;
   3172                 list = list->next;
   3173             }
   3174             break;
   3175         case XML_RELAXNG_TEXT:{
   3176                 xmlAutomataStatePtr oldstate;
   3177 
   3178                 ctxt->state =
   3179                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
   3180                 oldstate = ctxt->state;
   3181                 xmlRelaxNGCompile(ctxt, def->content);
   3182                 xmlAutomataNewTransition(ctxt->am, ctxt->state,
   3183                                          ctxt->state, BAD_CAST "#text",
   3184                                          NULL);
   3185                 ctxt->state =
   3186                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
   3187                 break;
   3188             }
   3189         case XML_RELAXNG_EMPTY:
   3190             ctxt->state =
   3191                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
   3192             break;
   3193         case XML_RELAXNG_EXCEPT:
   3194         case XML_RELAXNG_ATTRIBUTE:
   3195         case XML_RELAXNG_INTERLEAVE:
   3196         case XML_RELAXNG_NOT_ALLOWED:
   3197         case XML_RELAXNG_DATATYPE:
   3198         case XML_RELAXNG_LIST:
   3199         case XML_RELAXNG_PARAM:
   3200         case XML_RELAXNG_VALUE:
   3201             /* This should not happen and generate an internal error */
   3202             fprintf(stderr, "RNG internal error trying to compile %s\n",
   3203                     xmlRelaxNGDefName(def));
   3204             break;
   3205     }
   3206     return (ret);
   3207 }
   3208 
   3209 /**
   3210  * xmlRelaxNGTryCompile:
   3211  * ctxt:  the RelaxNG parser context
   3212  * @define:  the definition tree to compile
   3213  *
   3214  * Try to compile the set of definitions, it works recursively,
   3215  * possibly ignoring parts which cannot be compiled.
   3216  *
   3217  * Returns 0 if success and -1 in case of error
   3218  */
   3219 static int
   3220 xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
   3221 {
   3222     int ret = 0;
   3223     xmlRelaxNGDefinePtr list;
   3224 
   3225     if ((ctxt == NULL) || (def == NULL))
   3226         return (-1);
   3227 
   3228     if ((def->type == XML_RELAXNG_START) ||
   3229         (def->type == XML_RELAXNG_ELEMENT)) {
   3230         ret = xmlRelaxNGIsCompileable(def);
   3231         if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
   3232             ctxt->am = NULL;
   3233             ret = xmlRelaxNGCompile(ctxt, def);
   3234 #ifdef DEBUG_PROGRESSIVE
   3235             if (ret == 0) {
   3236                 if (def->type == XML_RELAXNG_START)
   3237                     xmlGenericError(xmlGenericErrorContext,
   3238                                     "compiled the start\n");
   3239                 else
   3240                     xmlGenericError(xmlGenericErrorContext,
   3241                                     "compiled element %s\n", def->name);
   3242             } else {
   3243                 if (def->type == XML_RELAXNG_START)
   3244                     xmlGenericError(xmlGenericErrorContext,
   3245                                     "failed to compile the start\n");
   3246                 else
   3247                     xmlGenericError(xmlGenericErrorContext,
   3248                                     "failed to compile element %s\n",
   3249                                     def->name);
   3250             }
   3251 #endif
   3252             return (ret);
   3253         }
   3254     }
   3255     switch (def->type) {
   3256         case XML_RELAXNG_NOOP:
   3257             ret = xmlRelaxNGTryCompile(ctxt, def->content);
   3258             break;
   3259         case XML_RELAXNG_TEXT:
   3260         case XML_RELAXNG_DATATYPE:
   3261         case XML_RELAXNG_LIST:
   3262         case XML_RELAXNG_PARAM:
   3263         case XML_RELAXNG_VALUE:
   3264         case XML_RELAXNG_EMPTY:
   3265         case XML_RELAXNG_ELEMENT:
   3266             ret = 0;
   3267             break;
   3268         case XML_RELAXNG_OPTIONAL:
   3269         case XML_RELAXNG_ZEROORMORE:
   3270         case XML_RELAXNG_ONEORMORE:
   3271         case XML_RELAXNG_CHOICE:
   3272         case XML_RELAXNG_GROUP:
   3273         case XML_RELAXNG_DEF:
   3274         case XML_RELAXNG_START:
   3275         case XML_RELAXNG_REF:
   3276         case XML_RELAXNG_EXTERNALREF:
   3277         case XML_RELAXNG_PARENTREF:
   3278             list = def->content;
   3279             while (list != NULL) {
   3280                 ret = xmlRelaxNGTryCompile(ctxt, list);
   3281                 if (ret != 0)
   3282                     break;
   3283                 list = list->next;
   3284             }
   3285             break;
   3286         case XML_RELAXNG_EXCEPT:
   3287         case XML_RELAXNG_ATTRIBUTE:
   3288         case XML_RELAXNG_INTERLEAVE:
   3289         case XML_RELAXNG_NOT_ALLOWED:
   3290             ret = 0;
   3291             break;
   3292     }
   3293     return (ret);
   3294 }
   3295 
   3296 /************************************************************************
   3297  * 									*
   3298  * 			Parsing functions				*
   3299  * 									*
   3300  ************************************************************************/
   3301 
   3302 static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr
   3303                                                     ctxt, xmlNodePtr node);
   3304 static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr
   3305                                                   ctxt, xmlNodePtr node);
   3306 static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr
   3307                                                    ctxt, xmlNodePtr nodes,
   3308                                                    int group);
   3309 static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr
   3310                                                   ctxt, xmlNodePtr node);
   3311 static xmlRelaxNGPtr xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt,
   3312                                              xmlNodePtr node);
   3313 static int xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
   3314                                          xmlNodePtr nodes);
   3315 static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr
   3316                                                     ctxt, xmlNodePtr node,
   3317                                                     xmlRelaxNGDefinePtr
   3318                                                     def);
   3319 static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr
   3320                                                    ctxt, xmlNodePtr nodes);
   3321 static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
   3322                                   xmlRelaxNGDefinePtr define,
   3323                                   xmlNodePtr elem);
   3324 
   3325 
   3326 #define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
   3327 
   3328 /**
   3329  * xmlRelaxNGIsNullable:
   3330  * @define:  the definition to verify
   3331  *
   3332  * Check if a definition is nullable.
   3333  *
   3334  * Returns 1 if yes, 0 if no and -1 in case of error
   3335  */
   3336 static int
   3337 xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define)
   3338 {
   3339     int ret;
   3340 
   3341     if (define == NULL)
   3342         return (-1);
   3343 
   3344     if (define->dflags & IS_NULLABLE)
   3345         return (1);
   3346     if (define->dflags & IS_NOT_NULLABLE)
   3347         return (0);
   3348     switch (define->type) {
   3349         case XML_RELAXNG_EMPTY:
   3350         case XML_RELAXNG_TEXT:
   3351             ret = 1;
   3352             break;
   3353         case XML_RELAXNG_NOOP:
   3354         case XML_RELAXNG_DEF:
   3355         case XML_RELAXNG_REF:
   3356         case XML_RELAXNG_EXTERNALREF:
   3357         case XML_RELAXNG_PARENTREF:
   3358         case XML_RELAXNG_ONEORMORE:
   3359             ret = xmlRelaxNGIsNullable(define->content);
   3360             break;
   3361         case XML_RELAXNG_EXCEPT:
   3362         case XML_RELAXNG_NOT_ALLOWED:
   3363         case XML_RELAXNG_ELEMENT:
   3364         case XML_RELAXNG_DATATYPE:
   3365         case XML_RELAXNG_PARAM:
   3366         case XML_RELAXNG_VALUE:
   3367         case XML_RELAXNG_LIST:
   3368         case XML_RELAXNG_ATTRIBUTE:
   3369             ret = 0;
   3370             break;
   3371         case XML_RELAXNG_CHOICE:{
   3372                 xmlRelaxNGDefinePtr list = define->content;
   3373 
   3374                 while (list != NULL) {
   3375                     ret = xmlRelaxNGIsNullable(list);
   3376                     if (ret != 0)
   3377                         goto done;
   3378                     list = list->next;
   3379                 }
   3380                 ret = 0;
   3381                 break;
   3382             }
   3383         case XML_RELAXNG_START:
   3384         case XML_RELAXNG_INTERLEAVE:
   3385         case XML_RELAXNG_GROUP:{
   3386                 xmlRelaxNGDefinePtr list = define->content;
   3387 
   3388                 while (list != NULL) {
   3389                     ret = xmlRelaxNGIsNullable(list);
   3390                     if (ret != 1)
   3391                         goto done;
   3392                     list = list->next;
   3393                 }
   3394                 return (1);
   3395             }
   3396         default:
   3397             return (-1);
   3398     }
   3399   done:
   3400     if (ret == 0)
   3401         define->dflags |= IS_NOT_NULLABLE;
   3402     if (ret == 1)
   3403         define->dflags |= IS_NULLABLE;
   3404     return (ret);
   3405 }
   3406 
   3407 /**
   3408  * xmlRelaxNGIsBlank:
   3409  * @str:  a string
   3410  *
   3411  * Check if a string is ignorable c.f. 4.2. Whitespace
   3412  *
   3413  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
   3414  */
   3415 static int
   3416 xmlRelaxNGIsBlank(xmlChar * str)
   3417 {
   3418     if (str == NULL)
   3419         return (1);
   3420     while (*str != 0) {
   3421         if (!(IS_BLANK_CH(*str)))
   3422             return (0);
   3423         str++;
   3424     }
   3425     return (1);
   3426 }
   3427 
   3428 /**
   3429  * xmlRelaxNGGetDataTypeLibrary:
   3430  * @ctxt:  a Relax-NG parser context
   3431  * @node:  the current data or value element
   3432  *
   3433  * Applies algorithm from 4.3. datatypeLibrary attribute
   3434  *
   3435  * Returns the datatypeLibary value or NULL if not found
   3436  */
   3437 static xmlChar *
   3438 xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
   3439                              xmlNodePtr node)
   3440 {
   3441     xmlChar *ret, *escape;
   3442 
   3443     if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
   3444         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
   3445         if (ret != NULL) {
   3446             if (ret[0] == 0) {
   3447                 xmlFree(ret);
   3448                 return (NULL);
   3449             }
   3450             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
   3451             if (escape == NULL) {
   3452                 return (ret);
   3453             }
   3454             xmlFree(ret);
   3455             return (escape);
   3456         }
   3457     }
   3458     node = node->parent;
   3459     while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
   3460         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
   3461         if (ret != NULL) {
   3462             if (ret[0] == 0) {
   3463                 xmlFree(ret);
   3464                 return (NULL);
   3465             }
   3466             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
   3467             if (escape == NULL) {
   3468                 return (ret);
   3469             }
   3470             xmlFree(ret);
   3471             return (escape);
   3472         }
   3473         node = node->parent;
   3474     }
   3475     return (NULL);
   3476 }
   3477 
   3478 /**
   3479  * xmlRelaxNGParseValue:
   3480  * @ctxt:  a Relax-NG parser context
   3481  * @node:  the data node.
   3482  *
   3483  * parse the content of a RelaxNG value node.
   3484  *
   3485  * Returns the definition pointer or NULL in case of error
   3486  */
   3487 static xmlRelaxNGDefinePtr
   3488 xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   3489 {
   3490     xmlRelaxNGDefinePtr def = NULL;
   3491     xmlRelaxNGTypeLibraryPtr lib = NULL;
   3492     xmlChar *type;
   3493     xmlChar *library;
   3494     int success = 0;
   3495 
   3496     def = xmlRelaxNGNewDefine(ctxt, node);
   3497     if (def == NULL)
   3498         return (NULL);
   3499     def->type = XML_RELAXNG_VALUE;
   3500 
   3501     type = xmlGetProp(node, BAD_CAST "type");
   3502     if (type != NULL) {
   3503         xmlRelaxNGNormExtSpace(type);
   3504         if (xmlValidateNCName(type, 0)) {
   3505             xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
   3506                        "value type '%s' is not an NCName\n", type, NULL);
   3507         }
   3508         library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
   3509         if (library == NULL)
   3510             library =
   3511                 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
   3512 
   3513         def->name = type;
   3514         def->ns = library;
   3515 
   3516         lib = (xmlRelaxNGTypeLibraryPtr)
   3517             xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
   3518         if (lib == NULL) {
   3519             xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
   3520                        "Use of unregistered type library '%s'\n", library,
   3521                        NULL);
   3522             def->data = NULL;
   3523         } else {
   3524             def->data = lib;
   3525             if (lib->have == NULL) {
   3526                 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
   3527                            "Internal error with type library '%s': no 'have'\n",
   3528                            library, NULL);
   3529             } else {
   3530                 success = lib->have(lib->data, def->name);
   3531                 if (success != 1) {
   3532                     xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
   3533                                "Error type '%s' is not exported by type library '%s'\n",
   3534                                def->name, library);
   3535                 }
   3536             }
   3537         }
   3538     }
   3539     if (node->children == NULL) {
   3540         def->value = xmlStrdup(BAD_CAST "");
   3541     } else if (((node->children->type != XML_TEXT_NODE) &&
   3542                 (node->children->type != XML_CDATA_SECTION_NODE)) ||
   3543                (node->children->next != NULL)) {
   3544         xmlRngPErr(ctxt, node, XML_RNGP_TEXT_EXPECTED,
   3545                    "Expecting a single text value for <value>content\n",
   3546                    NULL, NULL);
   3547     } else if (def != NULL) {
   3548         def->value = xmlNodeGetContent(node);
   3549         if (def->value == NULL) {
   3550             xmlRngPErr(ctxt, node, XML_RNGP_VALUE_NO_CONTENT,
   3551                        "Element <value> has no content\n", NULL, NULL);
   3552         } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) {
   3553             void *val = NULL;
   3554 
   3555             success =
   3556                 lib->check(lib->data, def->name, def->value, &val, node);
   3557             if (success != 1) {
   3558                 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_VALUE,
   3559                            "Value '%s' is not acceptable for type '%s'\n",
   3560                            def->value, def->name);
   3561             } else {
   3562                 if (val != NULL)
   3563                     def->attrs = val;
   3564             }
   3565         }
   3566     }
   3567     return (def);
   3568 }
   3569 
   3570 /**
   3571  * xmlRelaxNGParseData:
   3572  * @ctxt:  a Relax-NG parser context
   3573  * @node:  the data node.
   3574  *
   3575  * parse the content of a RelaxNG data node.
   3576  *
   3577  * Returns the definition pointer or NULL in case of error
   3578  */
   3579 static xmlRelaxNGDefinePtr
   3580 xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   3581 {
   3582     xmlRelaxNGDefinePtr def = NULL, except;
   3583     xmlRelaxNGDefinePtr param, lastparam = NULL;
   3584     xmlRelaxNGTypeLibraryPtr lib;
   3585     xmlChar *type;
   3586     xmlChar *library;
   3587     xmlNodePtr content;
   3588     int tmp;
   3589 
   3590     type = xmlGetProp(node, BAD_CAST "type");
   3591     if (type == NULL) {
   3592         xmlRngPErr(ctxt, node, XML_RNGP_TYPE_MISSING, "data has no type\n", NULL,
   3593                    NULL);
   3594         return (NULL);
   3595     }
   3596     xmlRelaxNGNormExtSpace(type);
   3597     if (xmlValidateNCName(type, 0)) {
   3598         xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
   3599                    "data type '%s' is not an NCName\n", type, NULL);
   3600     }
   3601     library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
   3602     if (library == NULL)
   3603         library =
   3604             xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
   3605 
   3606     def = xmlRelaxNGNewDefine(ctxt, node);
   3607     if (def == NULL) {
   3608         xmlFree(type);
   3609         return (NULL);
   3610     }
   3611     def->type = XML_RELAXNG_DATATYPE;
   3612     def->name = type;
   3613     def->ns = library;
   3614 
   3615     lib = (xmlRelaxNGTypeLibraryPtr)
   3616         xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
   3617     if (lib == NULL) {
   3618         xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
   3619                    "Use of unregistered type library '%s'\n", library,
   3620                    NULL);
   3621         def->data = NULL;
   3622     } else {
   3623         def->data = lib;
   3624         if (lib->have == NULL) {
   3625             xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
   3626                        "Internal error with type library '%s': no 'have'\n",
   3627                        library, NULL);
   3628         } else {
   3629             tmp = lib->have(lib->data, def->name);
   3630             if (tmp != 1) {
   3631                 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
   3632                            "Error type '%s' is not exported by type library '%s'\n",
   3633                            def->name, library);
   3634             } else
   3635                 if ((xmlStrEqual
   3636                      (library,
   3637                       BAD_CAST
   3638                       "http://www.w3.org/2001/XMLSchema-datatypes"))
   3639                     && ((xmlStrEqual(def->name, BAD_CAST "IDREF"))
   3640                         || (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) {
   3641                 ctxt->idref = 1;
   3642             }
   3643         }
   3644     }
   3645     content = node->children;
   3646 
   3647     /*
   3648      * Handle optional params
   3649      */
   3650     while (content != NULL) {
   3651         if (!xmlStrEqual(content->name, BAD_CAST "param"))
   3652             break;
   3653         if (xmlStrEqual(library,
   3654                         BAD_CAST "http://relaxng.org/ns/structure/1.0")) {
   3655             xmlRngPErr(ctxt, node, XML_RNGP_PARAM_FORBIDDEN,
   3656                        "Type library '%s' does not allow type parameters\n",
   3657                        library, NULL);
   3658             content = content->next;
   3659             while ((content != NULL) &&
   3660                    (xmlStrEqual(content->name, BAD_CAST "param")))
   3661                 content = content->next;
   3662         } else {
   3663             param = xmlRelaxNGNewDefine(ctxt, node);
   3664             if (param != NULL) {
   3665                 param->type = XML_RELAXNG_PARAM;
   3666                 param->name = xmlGetProp(content, BAD_CAST "name");
   3667                 if (param->name == NULL) {
   3668                     xmlRngPErr(ctxt, node, XML_RNGP_PARAM_NAME_MISSING,
   3669                                "param has no name\n", NULL, NULL);
   3670                 }
   3671                 param->value = xmlNodeGetContent(content);
   3672                 if (lastparam == NULL) {
   3673                     def->attrs = lastparam = param;
   3674                 } else {
   3675                     lastparam->next = param;
   3676                     lastparam = param;
   3677                 }
   3678                 if (lib != NULL) {
   3679                 }
   3680             }
   3681             content = content->next;
   3682         }
   3683     }
   3684     /*
   3685      * Handle optional except
   3686      */
   3687     if ((content != NULL)
   3688         && (xmlStrEqual(content->name, BAD_CAST "except"))) {
   3689         xmlNodePtr child;
   3690         xmlRelaxNGDefinePtr tmp2, last = NULL;
   3691 
   3692         except = xmlRelaxNGNewDefine(ctxt, node);
   3693         if (except == NULL) {
   3694             return (def);
   3695         }
   3696         except->type = XML_RELAXNG_EXCEPT;
   3697         child = content->children;
   3698 	def->content = except;
   3699         if (child == NULL) {
   3700             xmlRngPErr(ctxt, content, XML_RNGP_EXCEPT_NO_CONTENT,
   3701                        "except has no content\n", NULL, NULL);
   3702         }
   3703         while (child != NULL) {
   3704             tmp2 = xmlRelaxNGParsePattern(ctxt, child);
   3705             if (tmp2 != NULL) {
   3706                 if (last == NULL) {
   3707                     except->content = last = tmp2;
   3708                 } else {
   3709                     last->next = tmp2;
   3710                     last = tmp2;
   3711                 }
   3712             }
   3713             child = child->next;
   3714         }
   3715         content = content->next;
   3716     }
   3717     /*
   3718      * Check there is no unhandled data
   3719      */
   3720     if (content != NULL) {
   3721         xmlRngPErr(ctxt, content, XML_RNGP_DATA_CONTENT,
   3722                    "Element data has unexpected content %s\n",
   3723                    content->name, NULL);
   3724     }
   3725 
   3726     return (def);
   3727 }
   3728 
   3729 static const xmlChar *invalidName = BAD_CAST "\1";
   3730 
   3731 /**
   3732  * xmlRelaxNGCompareNameClasses:
   3733  * @defs1:  the first element/attribute defs
   3734  * @defs2:  the second element/attribute defs
   3735  * @name:  the restriction on the name
   3736  * @ns:  the restriction on the namespace
   3737  *
   3738  * Compare the 2 lists of element definitions. The comparison is
   3739  * that if both lists do not accept the same QNames, it returns 1
   3740  * If the 2 lists can accept the same QName the comparison returns 0
   3741  *
   3742  * Returns 1 disttinct, 0 if equal
   3743  */
   3744 static int
   3745 xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,
   3746                              xmlRelaxNGDefinePtr def2)
   3747 {
   3748     int ret = 1;
   3749     xmlNode node;
   3750     xmlNs ns;
   3751     xmlRelaxNGValidCtxt ctxt;
   3752 
   3753     memset(&ctxt, 0, sizeof(xmlRelaxNGValidCtxt));
   3754 
   3755     ctxt.flags = FLAGS_IGNORABLE | FLAGS_NOERROR;
   3756 
   3757     if ((def1->type == XML_RELAXNG_ELEMENT) ||
   3758         (def1->type == XML_RELAXNG_ATTRIBUTE)) {
   3759         if (def2->type == XML_RELAXNG_TEXT)
   3760             return (1);
   3761         if (def1->name != NULL) {
   3762             node.name = def1->name;
   3763         } else {
   3764             node.name = invalidName;
   3765         }
   3766         if (def1->ns != NULL) {
   3767             if (def1->ns[0] == 0) {
   3768                 node.ns = NULL;
   3769             } else {
   3770 	        node.ns = &ns;
   3771                 ns.href = def1->ns;
   3772             }
   3773         } else {
   3774             node.ns = NULL;
   3775         }
   3776         if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) {
   3777             if (def1->nameClass != NULL) {
   3778                 ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2);
   3779             } else {
   3780                 ret = 0;
   3781             }
   3782         } else {
   3783             ret = 1;
   3784         }
   3785     } else if (def1->type == XML_RELAXNG_TEXT) {
   3786         if (def2->type == XML_RELAXNG_TEXT)
   3787             return (0);
   3788         return (1);
   3789     } else if (def1->type == XML_RELAXNG_EXCEPT) {
   3790         TODO ret = 0;
   3791     } else {
   3792         TODO ret = 0;
   3793     }
   3794     if (ret == 0)
   3795         return (ret);
   3796     if ((def2->type == XML_RELAXNG_ELEMENT) ||
   3797         (def2->type == XML_RELAXNG_ATTRIBUTE)) {
   3798         if (def2->name != NULL) {
   3799             node.name = def2->name;
   3800         } else {
   3801             node.name = invalidName;
   3802         }
   3803         node.ns = &ns;
   3804         if (def2->ns != NULL) {
   3805             if (def2->ns[0] == 0) {
   3806                 node.ns = NULL;
   3807             } else {
   3808                 ns.href = def2->ns;
   3809             }
   3810         } else {
   3811             ns.href = invalidName;
   3812         }
   3813         if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) {
   3814             if (def2->nameClass != NULL) {
   3815                 ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1);
   3816             } else {
   3817                 ret = 0;
   3818             }
   3819         } else {
   3820             ret = 1;
   3821         }
   3822     } else {
   3823         TODO ret = 0;
   3824     }
   3825 
   3826     return (ret);
   3827 }
   3828 
   3829 /**
   3830  * xmlRelaxNGCompareElemDefLists:
   3831  * @ctxt:  a Relax-NG parser context
   3832  * @defs1:  the first list of element/attribute defs
   3833  * @defs2:  the second list of element/attribute defs
   3834  *
   3835  * Compare the 2 lists of element or attribute definitions. The comparison
   3836  * is that if both lists do not accept the same QNames, it returns 1
   3837  * If the 2 lists can accept the same QName the comparison returns 0
   3838  *
   3839  * Returns 1 disttinct, 0 if equal
   3840  */
   3841 static int
   3842 xmlRelaxNGCompareElemDefLists(xmlRelaxNGParserCtxtPtr ctxt
   3843                               ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr * def1,
   3844                               xmlRelaxNGDefinePtr * def2)
   3845 {
   3846     xmlRelaxNGDefinePtr *basedef2 = def2;
   3847 
   3848     if ((def1 == NULL) || (def2 == NULL))
   3849         return (1);
   3850     if ((*def1 == NULL) || (*def2 == NULL))
   3851         return (1);
   3852     while (*def1 != NULL) {
   3853         while ((*def2) != NULL) {
   3854             if (xmlRelaxNGCompareNameClasses(*def1, *def2) == 0)
   3855                 return (0);
   3856             def2++;
   3857         }
   3858         def2 = basedef2;
   3859         def1++;
   3860     }
   3861     return (1);
   3862 }
   3863 
   3864 /**
   3865  * xmlRelaxNGGenerateAttributes:
   3866  * @ctxt:  a Relax-NG parser context
   3867  * @def:  the definition definition
   3868  *
   3869  * Check if the definition can only generate attributes
   3870  *
   3871  * Returns 1 if yes, 0 if no and -1 in case of error.
   3872  */
   3873 static int
   3874 xmlRelaxNGGenerateAttributes(xmlRelaxNGParserCtxtPtr ctxt,
   3875                              xmlRelaxNGDefinePtr def)
   3876 {
   3877     xmlRelaxNGDefinePtr parent, cur, tmp;
   3878 
   3879     /*
   3880      * Don't run that check in case of error. Infinite recursion
   3881      * becomes possible.
   3882      */
   3883     if (ctxt->nbErrors != 0)
   3884         return (-1);
   3885 
   3886     parent = NULL;
   3887     cur = def;
   3888     while (cur != NULL) {
   3889         if ((cur->type == XML_RELAXNG_ELEMENT) ||
   3890             (cur->type == XML_RELAXNG_TEXT) ||
   3891             (cur->type == XML_RELAXNG_DATATYPE) ||
   3892             (cur->type == XML_RELAXNG_PARAM) ||
   3893             (cur->type == XML_RELAXNG_LIST) ||
   3894             (cur->type == XML_RELAXNG_VALUE) ||
   3895             (cur->type == XML_RELAXNG_EMPTY))
   3896             return (0);
   3897         if ((cur->type == XML_RELAXNG_CHOICE) ||
   3898             (cur->type == XML_RELAXNG_INTERLEAVE) ||
   3899             (cur->type == XML_RELAXNG_GROUP) ||
   3900             (cur->type == XML_RELAXNG_ONEORMORE) ||
   3901             (cur->type == XML_RELAXNG_ZEROORMORE) ||
   3902             (cur->type == XML_RELAXNG_OPTIONAL) ||
   3903             (cur->type == XML_RELAXNG_PARENTREF) ||
   3904             (cur->type == XML_RELAXNG_EXTERNALREF) ||
   3905             (cur->type == XML_RELAXNG_REF) ||
   3906             (cur->type == XML_RELAXNG_DEF)) {
   3907             if (cur->content != NULL) {
   3908                 parent = cur;
   3909                 cur = cur->content;
   3910                 tmp = cur;
   3911                 while (tmp != NULL) {
   3912                     tmp->parent = parent;
   3913                     tmp = tmp->next;
   3914                 }
   3915                 continue;
   3916             }
   3917         }
   3918         if (cur == def)
   3919             break;
   3920         if (cur->next != NULL) {
   3921             cur = cur->next;
   3922             continue;
   3923         }
   3924         do {
   3925             cur = cur->parent;
   3926             if (cur == NULL)
   3927                 break;
   3928             if (cur == def)
   3929                 return (1);
   3930             if (cur->next != NULL) {
   3931                 cur = cur->next;
   3932                 break;
   3933             }
   3934         } while (cur != NULL);
   3935     }
   3936     return (1);
   3937 }
   3938 
   3939 /**
   3940  * xmlRelaxNGGetElements:
   3941  * @ctxt:  a Relax-NG parser context
   3942  * @def:  the definition definition
   3943  * @eora:  gather elements (0) or attributes (1)
   3944  *
   3945  * Compute the list of top elements a definition can generate
   3946  *
   3947  * Returns a list of elements or NULL if none was found.
   3948  */
   3949 static xmlRelaxNGDefinePtr *
   3950 xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
   3951                       xmlRelaxNGDefinePtr def, int eora)
   3952 {
   3953     xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp;
   3954     int len = 0;
   3955     int max = 0;
   3956 
   3957     /*
   3958      * Don't run that check in case of error. Infinite recursion
   3959      * becomes possible.
   3960      */
   3961     if (ctxt->nbErrors != 0)
   3962         return (NULL);
   3963 
   3964     parent = NULL;
   3965     cur = def;
   3966     while (cur != NULL) {
   3967         if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||
   3968                              (cur->type == XML_RELAXNG_TEXT))) ||
   3969             ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE))) {
   3970             if (ret == NULL) {
   3971                 max = 10;
   3972                 ret = (xmlRelaxNGDefinePtr *)
   3973                     xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr));
   3974                 if (ret == NULL) {
   3975                     xmlRngPErrMemory(ctxt, "getting element list\n");
   3976                     return (NULL);
   3977                 }
   3978             } else if (max <= len) {
   3979 	        xmlRelaxNGDefinePtr *temp;
   3980 
   3981                 max *= 2;
   3982                 temp = xmlRealloc(ret,
   3983                                (max + 1) * sizeof(xmlRelaxNGDefinePtr));
   3984                 if (temp == NULL) {
   3985                     xmlRngPErrMemory(ctxt, "getting element list\n");
   3986 		    xmlFree(ret);
   3987                     return (NULL);
   3988                 }
   3989 		ret = temp;
   3990             }
   3991             ret[len++] = cur;
   3992             ret[len] = NULL;
   3993         } else if ((cur->type == XML_RELAXNG_CHOICE) ||
   3994                    (cur->type == XML_RELAXNG_INTERLEAVE) ||
   3995                    (cur->type == XML_RELAXNG_GROUP) ||
   3996                    (cur->type == XML_RELAXNG_ONEORMORE) ||
   3997                    (cur->type == XML_RELAXNG_ZEROORMORE) ||
   3998                    (cur->type == XML_RELAXNG_OPTIONAL) ||
   3999                    (cur->type == XML_RELAXNG_PARENTREF) ||
   4000                    (cur->type == XML_RELAXNG_REF) ||
   4001                    (cur->type == XML_RELAXNG_DEF) ||
   4002 		   (cur->type == XML_RELAXNG_EXTERNALREF)) {
   4003             /*
   4004              * Don't go within elements or attributes or string values.
   4005              * Just gather the element top list
   4006              */
   4007             if (cur->content != NULL) {
   4008                 parent = cur;
   4009                 cur = cur->content;
   4010                 tmp = cur;
   4011                 while (tmp != NULL) {
   4012                     tmp->parent = parent;
   4013                     tmp = tmp->next;
   4014                 }
   4015                 continue;
   4016             }
   4017         }
   4018         if (cur == def)
   4019             break;
   4020         if (cur->next != NULL) {
   4021             cur = cur->next;
   4022             continue;
   4023         }
   4024         do {
   4025             cur = cur->parent;
   4026             if (cur == NULL)
   4027                 break;
   4028             if (cur == def)
   4029                 return (ret);
   4030             if (cur->next != NULL) {
   4031                 cur = cur->next;
   4032                 break;
   4033             }
   4034         } while (cur != NULL);
   4035     }
   4036     return (ret);
   4037 }
   4038 
   4039 /**
   4040  * xmlRelaxNGCheckChoiceDeterminism:
   4041  * @ctxt:  a Relax-NG parser context
   4042  * @def:  the choice definition
   4043  *
   4044  * Also used to find indeterministic pattern in choice
   4045  */
   4046 static void
   4047 xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt,
   4048                                  xmlRelaxNGDefinePtr def)
   4049 {
   4050     xmlRelaxNGDefinePtr **list;
   4051     xmlRelaxNGDefinePtr cur;
   4052     int nbchild = 0, i, j, ret;
   4053     int is_nullable = 0;
   4054     int is_indeterminist = 0;
   4055     xmlHashTablePtr triage = NULL;
   4056     int is_triable = 1;
   4057 
   4058     if ((def == NULL) || (def->type != XML_RELAXNG_CHOICE))
   4059         return;
   4060 
   4061     if (def->dflags & IS_PROCESSED)
   4062         return;
   4063 
   4064     /*
   4065      * Don't run that check in case of error. Infinite recursion
   4066      * becomes possible.
   4067      */
   4068     if (ctxt->nbErrors != 0)
   4069         return;
   4070 
   4071     is_nullable = xmlRelaxNGIsNullable(def);
   4072 
   4073     cur = def->content;
   4074     while (cur != NULL) {
   4075         nbchild++;
   4076         cur = cur->next;
   4077     }
   4078 
   4079     list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
   4080                                               sizeof(xmlRelaxNGDefinePtr
   4081                                                      *));
   4082     if (list == NULL) {
   4083         xmlRngPErrMemory(ctxt, "building choice\n");
   4084         return;
   4085     }
   4086     i = 0;
   4087     /*
   4088      * a bit strong but safe
   4089      */
   4090     if (is_nullable == 0) {
   4091         triage = xmlHashCreate(10);
   4092     } else {
   4093         is_triable = 0;
   4094     }
   4095     cur = def->content;
   4096     while (cur != NULL) {
   4097         list[i] = xmlRelaxNGGetElements(ctxt, cur, 0);
   4098         if ((list[i] == NULL) || (list[i][0] == NULL)) {
   4099             is_triable = 0;
   4100         } else if (is_triable == 1) {
   4101             xmlRelaxNGDefinePtr *tmp;
   4102             int res;
   4103 
   4104             tmp = list[i];
   4105             while ((*tmp != NULL) && (is_triable == 1)) {
   4106                 if ((*tmp)->type == XML_RELAXNG_TEXT) {
   4107                     res = xmlHashAddEntry2(triage,
   4108                                            BAD_CAST "#text", NULL,
   4109                                            (void *) cur);
   4110                     if (res != 0)
   4111                         is_triable = -1;
   4112                 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
   4113                            ((*tmp)->name != NULL)) {
   4114                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
   4115                         res = xmlHashAddEntry2(triage,
   4116                                                (*tmp)->name, NULL,
   4117                                                (void *) cur);
   4118                     else
   4119                         res = xmlHashAddEntry2(triage,
   4120                                                (*tmp)->name, (*tmp)->ns,
   4121                                                (void *) cur);
   4122                     if (res != 0)
   4123                         is_triable = -1;
   4124                 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
   4125                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
   4126                         res = xmlHashAddEntry2(triage,
   4127                                                BAD_CAST "#any", NULL,
   4128                                                (void *) cur);
   4129                     else
   4130                         res = xmlHashAddEntry2(triage,
   4131                                                BAD_CAST "#any", (*tmp)->ns,
   4132                                                (void *) cur);
   4133                     if (res != 0)
   4134                         is_triable = -1;
   4135                 } else {
   4136                     is_triable = -1;
   4137                 }
   4138                 tmp++;
   4139             }
   4140         }
   4141         i++;
   4142         cur = cur->next;
   4143     }
   4144 
   4145     for (i = 0; i < nbchild; i++) {
   4146         if (list[i] == NULL)
   4147             continue;
   4148         for (j = 0; j < i; j++) {
   4149             if (list[j] == NULL)
   4150                 continue;
   4151             ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
   4152             if (ret == 0) {
   4153                 is_indeterminist = 1;
   4154             }
   4155         }
   4156     }
   4157     for (i = 0; i < nbchild; i++) {
   4158         if (list[i] != NULL)
   4159             xmlFree(list[i]);
   4160     }
   4161 
   4162     xmlFree(list);
   4163     if (is_indeterminist) {
   4164         def->dflags |= IS_INDETERMINIST;
   4165     }
   4166     if (is_triable == 1) {
   4167         def->dflags |= IS_TRIABLE;
   4168         def->data = triage;
   4169     } else if (triage != NULL) {
   4170         xmlHashFree(triage, NULL);
   4171     }
   4172     def->dflags |= IS_PROCESSED;
   4173 }
   4174 
   4175 /**
   4176  * xmlRelaxNGCheckGroupAttrs:
   4177  * @ctxt:  a Relax-NG parser context
   4178  * @def:  the group definition
   4179  *
   4180  * Detects violations of rule 7.3
   4181  */
   4182 static void
   4183 xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,
   4184                           xmlRelaxNGDefinePtr def)
   4185 {
   4186     xmlRelaxNGDefinePtr **list;
   4187     xmlRelaxNGDefinePtr cur;
   4188     int nbchild = 0, i, j, ret;
   4189 
   4190     if ((def == NULL) ||
   4191         ((def->type != XML_RELAXNG_GROUP) &&
   4192          (def->type != XML_RELAXNG_ELEMENT)))
   4193         return;
   4194 
   4195     if (def->dflags & IS_PROCESSED)
   4196         return;
   4197 
   4198     /*
   4199      * Don't run that check in case of error. Infinite recursion
   4200      * becomes possible.
   4201      */
   4202     if (ctxt->nbErrors != 0)
   4203         return;
   4204 
   4205     cur = def->attrs;
   4206     while (cur != NULL) {
   4207         nbchild++;
   4208         cur = cur->next;
   4209     }
   4210     cur = def->content;
   4211     while (cur != NULL) {
   4212         nbchild++;
   4213         cur = cur->next;
   4214     }
   4215 
   4216     list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
   4217                                               sizeof(xmlRelaxNGDefinePtr
   4218                                                      *));
   4219     if (list == NULL) {
   4220         xmlRngPErrMemory(ctxt, "building group\n");
   4221         return;
   4222     }
   4223     i = 0;
   4224     cur = def->attrs;
   4225     while (cur != NULL) {
   4226         list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
   4227         i++;
   4228         cur = cur->next;
   4229     }
   4230     cur = def->content;
   4231     while (cur != NULL) {
   4232         list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
   4233         i++;
   4234         cur = cur->next;
   4235     }
   4236 
   4237     for (i = 0; i < nbchild; i++) {
   4238         if (list[i] == NULL)
   4239             continue;
   4240         for (j = 0; j < i; j++) {
   4241             if (list[j] == NULL)
   4242                 continue;
   4243             ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
   4244             if (ret == 0) {
   4245                 xmlRngPErr(ctxt, def->node, XML_RNGP_GROUP_ATTR_CONFLICT,
   4246                            "Attributes conflicts in group\n", NULL, NULL);
   4247             }
   4248         }
   4249     }
   4250     for (i = 0; i < nbchild; i++) {
   4251         if (list[i] != NULL)
   4252             xmlFree(list[i]);
   4253     }
   4254 
   4255     xmlFree(list);
   4256     def->dflags |= IS_PROCESSED;
   4257 }
   4258 
   4259 /**
   4260  * xmlRelaxNGComputeInterleaves:
   4261  * @def:  the interleave definition
   4262  * @ctxt:  a Relax-NG parser context
   4263  * @name:  the definition name
   4264  *
   4265  * A lot of work for preprocessing interleave definitions
   4266  * is potentially needed to get a decent execution speed at runtime
   4267  *   - trying to get a total order on the element nodes generated
   4268  *     by the interleaves, order the list of interleave definitions
   4269  *     following that order.
   4270  *   - if <text/> is used to handle mixed content, it is better to
   4271  *     flag this in the define and simplify the runtime checking
   4272  *     algorithm
   4273  */
   4274 static void
   4275 xmlRelaxNGComputeInterleaves(xmlRelaxNGDefinePtr def,
   4276                              xmlRelaxNGParserCtxtPtr ctxt,
   4277                              xmlChar * name ATTRIBUTE_UNUSED)
   4278 {
   4279     xmlRelaxNGDefinePtr cur, *tmp;
   4280 
   4281     xmlRelaxNGPartitionPtr partitions = NULL;
   4282     xmlRelaxNGInterleaveGroupPtr *groups = NULL;
   4283     xmlRelaxNGInterleaveGroupPtr group;
   4284     int i, j, ret, res;
   4285     int nbgroups = 0;
   4286     int nbchild = 0;
   4287     int is_mixed = 0;
   4288     int is_determinist = 1;
   4289 
   4290     /*
   4291      * Don't run that check in case of error. Infinite recursion
   4292      * becomes possible.
   4293      */
   4294     if (ctxt->nbErrors != 0)
   4295         return;
   4296 
   4297 #ifdef DEBUG_INTERLEAVE
   4298     xmlGenericError(xmlGenericErrorContext,
   4299                     "xmlRelaxNGComputeInterleaves(%s)\n", name);
   4300 #endif
   4301     cur = def->content;
   4302     while (cur != NULL) {
   4303         nbchild++;
   4304         cur = cur->next;
   4305     }
   4306 
   4307 #ifdef DEBUG_INTERLEAVE
   4308     xmlGenericError(xmlGenericErrorContext, "  %d child\n", nbchild);
   4309 #endif
   4310     groups = (xmlRelaxNGInterleaveGroupPtr *)
   4311         xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr));
   4312     if (groups == NULL)
   4313         goto error;
   4314     cur = def->content;
   4315     while (cur != NULL) {
   4316         groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr)
   4317             xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup));
   4318         if (groups[nbgroups] == NULL)
   4319             goto error;
   4320         if (cur->type == XML_RELAXNG_TEXT)
   4321             is_mixed++;
   4322         groups[nbgroups]->rule = cur;
   4323         groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 0);
   4324         groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
   4325         nbgroups++;
   4326         cur = cur->next;
   4327     }
   4328 #ifdef DEBUG_INTERLEAVE
   4329     xmlGenericError(xmlGenericErrorContext, "  %d groups\n", nbgroups);
   4330 #endif
   4331 
   4332     /*
   4333      * Let's check that all rules makes a partitions according to 7.4
   4334      */
   4335     partitions = (xmlRelaxNGPartitionPtr)
   4336         xmlMalloc(sizeof(xmlRelaxNGPartition));
   4337     if (partitions == NULL)
   4338         goto error;
   4339     memset(partitions, 0, sizeof(xmlRelaxNGPartition));
   4340     partitions->nbgroups = nbgroups;
   4341     partitions->triage = xmlHashCreate(nbgroups);
   4342     for (i = 0; i < nbgroups; i++) {
   4343         group = groups[i];
   4344         for (j = i + 1; j < nbgroups; j++) {
   4345             if (groups[j] == NULL)
   4346                 continue;
   4347 
   4348             ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs,
   4349                                                 groups[j]->defs);
   4350             if (ret == 0) {
   4351                 xmlRngPErr(ctxt, def->node, XML_RNGP_ELEM_TEXT_CONFLICT,
   4352                            "Element or text conflicts in interleave\n",
   4353                            NULL, NULL);
   4354             }
   4355             ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs,
   4356                                                 groups[j]->attrs);
   4357             if (ret == 0) {
   4358                 xmlRngPErr(ctxt, def->node, XML_RNGP_ATTR_CONFLICT,
   4359                            "Attributes conflicts in interleave\n", NULL,
   4360                            NULL);
   4361             }
   4362         }
   4363         tmp = group->defs;
   4364         if ((tmp != NULL) && (*tmp != NULL)) {
   4365             while (*tmp != NULL) {
   4366                 if ((*tmp)->type == XML_RELAXNG_TEXT) {
   4367                     res = xmlHashAddEntry2(partitions->triage,
   4368                                            BAD_CAST "#text", NULL,
   4369                                            (void *) (long) (i + 1));
   4370                     if (res != 0)
   4371                         is_determinist = -1;
   4372                 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
   4373                            ((*tmp)->name != NULL)) {
   4374                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
   4375                         res = xmlHashAddEntry2(partitions->triage,
   4376                                                (*tmp)->name, NULL,
   4377                                                (void *) (long) (i + 1));
   4378                     else
   4379                         res = xmlHashAddEntry2(partitions->triage,
   4380                                                (*tmp)->name, (*tmp)->ns,
   4381                                                (void *) (long) (i + 1));
   4382                     if (res != 0)
   4383                         is_determinist = -1;
   4384                 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
   4385                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
   4386                         res = xmlHashAddEntry2(partitions->triage,
   4387                                                BAD_CAST "#any", NULL,
   4388                                                (void *) (long) (i + 1));
   4389                     else
   4390                         res = xmlHashAddEntry2(partitions->triage,
   4391                                                BAD_CAST "#any", (*tmp)->ns,
   4392                                                (void *) (long) (i + 1));
   4393                     if ((*tmp)->nameClass != NULL)
   4394                         is_determinist = 2;
   4395                     if (res != 0)
   4396                         is_determinist = -1;
   4397                 } else {
   4398                     is_determinist = -1;
   4399                 }
   4400                 tmp++;
   4401             }
   4402         } else {
   4403             is_determinist = 0;
   4404         }
   4405     }
   4406     partitions->groups = groups;
   4407 
   4408     /*
   4409      * and save the partition list back in the def
   4410      */
   4411     def->data = partitions;
   4412     if (is_mixed != 0)
   4413         def->dflags |= IS_MIXED;
   4414     if (is_determinist == 1)
   4415         partitions->flags = IS_DETERMINIST;
   4416     if (is_determinist == 2)
   4417         partitions->flags = IS_DETERMINIST | IS_NEEDCHECK;
   4418     return;
   4419 
   4420   error:
   4421     xmlRngPErrMemory(ctxt, "in interleave computation\n");
   4422     if (groups != NULL) {
   4423         for (i = 0; i < nbgroups; i++)
   4424             if (groups[i] != NULL) {
   4425                 if (groups[i]->defs != NULL)
   4426                     xmlFree(groups[i]->defs);
   4427                 xmlFree(groups[i]);
   4428             }
   4429         xmlFree(groups);
   4430     }
   4431     xmlRelaxNGFreePartition(partitions);
   4432 }
   4433 
   4434 /**
   4435  * xmlRelaxNGParseInterleave:
   4436  * @ctxt:  a Relax-NG parser context
   4437  * @node:  the data node.
   4438  *
   4439  * parse the content of a RelaxNG interleave node.
   4440  *
   4441  * Returns the definition pointer or NULL in case of error
   4442  */
   4443 static xmlRelaxNGDefinePtr
   4444 xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4445 {
   4446     xmlRelaxNGDefinePtr def = NULL;
   4447     xmlRelaxNGDefinePtr last = NULL, cur;
   4448     xmlNodePtr child;
   4449 
   4450     def = xmlRelaxNGNewDefine(ctxt, node);
   4451     if (def == NULL) {
   4452         return (NULL);
   4453     }
   4454     def->type = XML_RELAXNG_INTERLEAVE;
   4455 
   4456     if (ctxt->interleaves == NULL)
   4457         ctxt->interleaves = xmlHashCreate(10);
   4458     if (ctxt->interleaves == NULL) {
   4459         xmlRngPErrMemory(ctxt, "create interleaves\n");
   4460     } else {
   4461         char name[32];
   4462 
   4463         snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++);
   4464         if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) {
   4465             xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_ADD,
   4466                        "Failed to add %s to hash table\n",
   4467 		       (const xmlChar *) name, NULL);
   4468         }
   4469     }
   4470     child = node->children;
   4471     if (child == NULL) {
   4472         xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_NO_CONTENT,
   4473                    "Element interleave is empty\n", NULL, NULL);
   4474     }
   4475     while (child != NULL) {
   4476         if (IS_RELAXNG(child, "element")) {
   4477             cur = xmlRelaxNGParseElement(ctxt, child);
   4478         } else {
   4479             cur = xmlRelaxNGParsePattern(ctxt, child);
   4480         }
   4481         if (cur != NULL) {
   4482             cur->parent = def;
   4483             if (last == NULL) {
   4484                 def->content = last = cur;
   4485             } else {
   4486                 last->next = cur;
   4487                 last = cur;
   4488             }
   4489         }
   4490         child = child->next;
   4491     }
   4492 
   4493     return (def);
   4494 }
   4495 
   4496 /**
   4497  * xmlRelaxNGParseInclude:
   4498  * @ctxt:  a Relax-NG parser context
   4499  * @node:  the include node
   4500  *
   4501  * Integrate the content of an include node in the current grammar
   4502  *
   4503  * Returns 0 in case of success or -1 in case of error
   4504  */
   4505 static int
   4506 xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4507 {
   4508     xmlRelaxNGIncludePtr incl;
   4509     xmlNodePtr root;
   4510     int ret = 0, tmp;
   4511 
   4512     incl = node->psvi;
   4513     if (incl == NULL) {
   4514         xmlRngPErr(ctxt, node, XML_RNGP_INCLUDE_EMPTY,
   4515                    "Include node has no data\n", NULL, NULL);
   4516         return (-1);
   4517     }
   4518     root = xmlDocGetRootElement(incl->doc);
   4519     if (root == NULL) {
   4520         xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, "Include document is empty\n",
   4521                    NULL, NULL);
   4522         return (-1);
   4523     }
   4524     if (!xmlStrEqual(root->name, BAD_CAST "grammar")) {
   4525         xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
   4526                    "Include document root is not a grammar\n", NULL, NULL);
   4527         return (-1);
   4528     }
   4529 
   4530     /*
   4531      * Merge the definition from both the include and the internal list
   4532      */
   4533     if (root->children != NULL) {
   4534         tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children);
   4535         if (tmp != 0)
   4536             ret = -1;
   4537     }
   4538     if (node->children != NULL) {
   4539         tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children);
   4540         if (tmp != 0)
   4541             ret = -1;
   4542     }
   4543     return (ret);
   4544 }
   4545 
   4546 /**
   4547  * xmlRelaxNGParseDefine:
   4548  * @ctxt:  a Relax-NG parser context
   4549  * @node:  the define node
   4550  *
   4551  * parse the content of a RelaxNG define element node.
   4552  *
   4553  * Returns 0 in case of success or -1 in case of error
   4554  */
   4555 static int
   4556 xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4557 {
   4558     xmlChar *name;
   4559     int ret = 0, tmp;
   4560     xmlRelaxNGDefinePtr def;
   4561     const xmlChar *olddefine;
   4562 
   4563     name = xmlGetProp(node, BAD_CAST "name");
   4564     if (name == NULL) {
   4565         xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_NAME_MISSING,
   4566                    "define has no name\n", NULL, NULL);
   4567     } else {
   4568         xmlRelaxNGNormExtSpace(name);
   4569         if (xmlValidateNCName(name, 0)) {
   4570             xmlRngPErr(ctxt, node, XML_RNGP_INVALID_DEFINE_NAME,
   4571                        "define name '%s' is not an NCName\n", name, NULL);
   4572         }
   4573         def = xmlRelaxNGNewDefine(ctxt, node);
   4574         if (def == NULL) {
   4575             xmlFree(name);
   4576             return (-1);
   4577         }
   4578         def->type = XML_RELAXNG_DEF;
   4579         def->name = name;
   4580         if (node->children == NULL) {
   4581             xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_EMPTY,
   4582                        "define has no children\n", NULL, NULL);
   4583         } else {
   4584             olddefine = ctxt->define;
   4585             ctxt->define = name;
   4586             def->content =
   4587                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
   4588             ctxt->define = olddefine;
   4589         }
   4590         if (ctxt->grammar->defs == NULL)
   4591             ctxt->grammar->defs = xmlHashCreate(10);
   4592         if (ctxt->grammar->defs == NULL) {
   4593             xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
   4594                        "Could not create definition hash\n", NULL, NULL);
   4595             ret = -1;
   4596         } else {
   4597             tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
   4598             if (tmp < 0) {
   4599                 xmlRelaxNGDefinePtr prev;
   4600 
   4601                 prev = xmlHashLookup(ctxt->grammar->defs, name);
   4602                 if (prev == NULL) {
   4603                     xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
   4604                                "Internal error on define aggregation of %s\n",
   4605                                name, NULL);
   4606                     ret = -1;
   4607                 } else {
   4608                     while (prev->nextHash != NULL)
   4609                         prev = prev->nextHash;
   4610                     prev->nextHash = def;
   4611                 }
   4612             }
   4613         }
   4614     }
   4615     return (ret);
   4616 }
   4617 
   4618 /**
   4619  * xmlRelaxNGProcessExternalRef:
   4620  * @ctxt: the parser context
   4621  * @node:  the externlRef node
   4622  *
   4623  * Process and compile an externlRef node
   4624  *
   4625  * Returns the xmlRelaxNGDefinePtr or NULL in case of error
   4626  */
   4627 static xmlRelaxNGDefinePtr
   4628 xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4629 {
   4630     xmlRelaxNGDocumentPtr docu;
   4631     xmlNodePtr root, tmp;
   4632     xmlChar *ns;
   4633     int newNs = 0, oldflags;
   4634     xmlRelaxNGDefinePtr def;
   4635 
   4636     docu = node->psvi;
   4637     if (docu != NULL) {
   4638         def = xmlRelaxNGNewDefine(ctxt, node);
   4639         if (def == NULL)
   4640             return (NULL);
   4641         def->type = XML_RELAXNG_EXTERNALREF;
   4642 
   4643         if (docu->content == NULL) {
   4644             /*
   4645              * Then do the parsing for good
   4646              */
   4647             root = xmlDocGetRootElement(docu->doc);
   4648             if (root == NULL) {
   4649                 xmlRngPErr(ctxt, node, XML_RNGP_EXTERNALREF_EMTPY,
   4650                            "xmlRelaxNGParse: %s is empty\n", ctxt->URL,
   4651                            NULL);
   4652                 return (NULL);
   4653             }
   4654             /*
   4655              * ns transmission rules
   4656              */
   4657             ns = xmlGetProp(root, BAD_CAST "ns");
   4658             if (ns == NULL) {
   4659                 tmp = node;
   4660                 while ((tmp != NULL) && (tmp->type == XML_ELEMENT_NODE)) {
   4661                     ns = xmlGetProp(tmp, BAD_CAST "ns");
   4662                     if (ns != NULL) {
   4663                         break;
   4664                     }
   4665                     tmp = tmp->parent;
   4666                 }
   4667                 if (ns != NULL) {
   4668                     xmlSetProp(root, BAD_CAST "ns", ns);
   4669                     newNs = 1;
   4670                     xmlFree(ns);
   4671                 }
   4672             } else {
   4673                 xmlFree(ns);
   4674             }
   4675 
   4676             /*
   4677              * Parsing to get a precompiled schemas.
   4678              */
   4679             oldflags = ctxt->flags;
   4680             ctxt->flags |= XML_RELAXNG_IN_EXTERNALREF;
   4681             docu->schema = xmlRelaxNGParseDocument(ctxt, root);
   4682             ctxt->flags = oldflags;
   4683             if ((docu->schema != NULL) &&
   4684                 (docu->schema->topgrammar != NULL)) {
   4685                 docu->content = docu->schema->topgrammar->start;
   4686             }
   4687 
   4688             /*
   4689              * the externalRef may be reused in a different ns context
   4690              */
   4691             if (newNs == 1) {
   4692                 xmlUnsetProp(root, BAD_CAST "ns");
   4693             }
   4694         }
   4695         def->content = docu->content;
   4696     } else {
   4697         def = NULL;
   4698     }
   4699     return (def);
   4700 }
   4701 
   4702 /**
   4703  * xmlRelaxNGParsePattern:
   4704  * @ctxt:  a Relax-NG parser context
   4705  * @node:  the pattern node.
   4706  *
   4707  * parse the content of a RelaxNG pattern node.
   4708  *
   4709  * Returns the definition pointer or NULL in case of error or if no
   4710  *     pattern is generated.
   4711  */
   4712 static xmlRelaxNGDefinePtr
   4713 xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
   4714 {
   4715     xmlRelaxNGDefinePtr def = NULL;
   4716 
   4717     if (node == NULL) {
   4718         return (NULL);
   4719     }
   4720     if (IS_RELAXNG(node, "element")) {
   4721         def = xmlRelaxNGParseElement(ctxt, node);
   4722     } else if (IS_RELAXNG(node, "attribute")) {
   4723         def = xmlRelaxNGParseAttribute(ctxt, node);
   4724     } else if (IS_RELAXNG(node, "empty")) {
   4725         def = xmlRelaxNGNewDefine(ctxt, node);
   4726         if (def == NULL)
   4727             return (NULL);
   4728         def->type = XML_RELAXNG_EMPTY;
   4729         if (node->children != NULL) {
   4730             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_NOT_EMPTY,
   4731                        "empty: had a child node\n", NULL, NULL);
   4732         }
   4733     } else if (IS_RELAXNG(node, "text")) {
   4734         def = xmlRelaxNGNewDefine(ctxt, node);
   4735         if (def == NULL)
   4736             return (NULL);
   4737         def->type = XML_RELAXNG_TEXT;
   4738         if (node->children != NULL) {
   4739             xmlRngPErr(ctxt, node, XML_RNGP_TEXT_HAS_CHILD,
   4740                        "text: had a child node\n", NULL, NULL);
   4741         }
   4742     } else if (IS_RELAXNG(node, "zeroOrMore")) {
   4743         def = xmlRelaxNGNewDefine(ctxt, node);
   4744         if (def == NULL)
   4745             return (NULL);
   4746         def->type = XML_RELAXNG_ZEROORMORE;
   4747         if (node->children == NULL) {
   4748             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4749                        "Element %s is empty\n", node->name, NULL);
   4750         } else {
   4751             def->content =
   4752                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
   4753         }
   4754     } else if (IS_RELAXNG(node, "oneOrMore")) {
   4755         def = xmlRelaxNGNewDefine(ctxt, node);
   4756         if (def == NULL)
   4757             return (NULL);
   4758         def->type = XML_RELAXNG_ONEORMORE;
   4759         if (node->children == NULL) {
   4760             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4761                        "Element %s is empty\n", node->name, NULL);
   4762         } else {
   4763             def->content =
   4764                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
   4765         }
   4766     } else if (IS_RELAXNG(node, "optional")) {
   4767         def = xmlRelaxNGNewDefine(ctxt, node);
   4768         if (def == NULL)
   4769             return (NULL);
   4770         def->type = XML_RELAXNG_OPTIONAL;
   4771         if (node->children == NULL) {
   4772             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4773                        "Element %s is empty\n", node->name, NULL);
   4774         } else {
   4775             def->content =
   4776                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
   4777         }
   4778     } else if (IS_RELAXNG(node, "choice")) {
   4779         def = xmlRelaxNGNewDefine(ctxt, node);
   4780         if (def == NULL)
   4781             return (NULL);
   4782         def->type = XML_RELAXNG_CHOICE;
   4783         if (node->children == NULL) {
   4784             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4785                        "Element %s is empty\n", node->name, NULL);
   4786         } else {
   4787             def->content =
   4788                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
   4789         }
   4790     } else if (IS_RELAXNG(node, "group")) {
   4791         def = xmlRelaxNGNewDefine(ctxt, node);
   4792         if (def == NULL)
   4793             return (NULL);
   4794         def->type = XML_RELAXNG_GROUP;
   4795         if (node->children == NULL) {
   4796             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4797                        "Element %s is empty\n", node->name, NULL);
   4798         } else {
   4799             def->content =
   4800                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
   4801         }
   4802     } else if (IS_RELAXNG(node, "ref")) {
   4803         def = xmlRelaxNGNewDefine(ctxt, node);
   4804         if (def == NULL)
   4805             return (NULL);
   4806         def->type = XML_RELAXNG_REF;
   4807         def->name = xmlGetProp(node, BAD_CAST "name");
   4808         if (def->name == NULL) {
   4809             xmlRngPErr(ctxt, node, XML_RNGP_REF_NO_NAME, "ref has no name\n",
   4810                        NULL, NULL);
   4811         } else {
   4812             xmlRelaxNGNormExtSpace(def->name);
   4813             if (xmlValidateNCName(def->name, 0)) {
   4814                 xmlRngPErr(ctxt, node, XML_RNGP_REF_NAME_INVALID,
   4815                            "ref name '%s' is not an NCName\n", def->name,
   4816                            NULL);
   4817             }
   4818         }
   4819         if (node->children != NULL) {
   4820             xmlRngPErr(ctxt, node, XML_RNGP_REF_NOT_EMPTY, "ref is not empty\n",
   4821                        NULL, NULL);
   4822         }
   4823         if (ctxt->grammar->refs == NULL)
   4824             ctxt->grammar->refs = xmlHashCreate(10);
   4825         if (ctxt->grammar->refs == NULL) {
   4826             xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
   4827                        "Could not create references hash\n", NULL, NULL);
   4828             def = NULL;
   4829         } else {
   4830             int tmp;
   4831 
   4832             tmp = xmlHashAddEntry(ctxt->grammar->refs, def->name, def);
   4833             if (tmp < 0) {
   4834                 xmlRelaxNGDefinePtr prev;
   4835 
   4836                 prev = (xmlRelaxNGDefinePtr)
   4837                     xmlHashLookup(ctxt->grammar->refs, def->name);
   4838                 if (prev == NULL) {
   4839                     if (def->name != NULL) {
   4840 		        xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
   4841 				   "Error refs definitions '%s'\n",
   4842 				   def->name, NULL);
   4843                     } else {
   4844 		        xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
   4845 				   "Error refs definitions\n",
   4846 				   NULL, NULL);
   4847                     }
   4848                     def = NULL;
   4849                 } else {
   4850                     def->nextHash = prev->nextHash;
   4851                     prev->nextHash = def;
   4852                 }
   4853             }
   4854         }
   4855     } else if (IS_RELAXNG(node, "data")) {
   4856         def = xmlRelaxNGParseData(ctxt, node);
   4857     } else if (IS_RELAXNG(node, "value")) {
   4858         def = xmlRelaxNGParseValue(ctxt, node);
   4859     } else if (IS_RELAXNG(node, "list")) {
   4860         def = xmlRelaxNGNewDefine(ctxt, node);
   4861         if (def == NULL)
   4862             return (NULL);
   4863         def->type = XML_RELAXNG_LIST;
   4864         if (node->children == NULL) {
   4865             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
   4866                        "Element %s is empty\n", node->name, NULL);
   4867         } else {
   4868             def->content =
   4869                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
   4870         }
   4871     } else if (IS_RELAXNG(node, "interleave")) {
   4872         def =