File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / relaxng.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:22:18 2013 UTC (10 years, 11 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_8_0p0, v2_8_0, HEAD
2.8.0

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>