File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / relaxng.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 19:53:31 2014 UTC (9 years, 11 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_9_1p0, v2_9_1, HEAD
libxml2 2.9.1

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

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