Annotation of embedaddon/libxml2/relaxng.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * relaxng.c : implementation of the Relax-NG handling and validity checking
        !             3:  *
        !             4:  * See Copyright for the status of this software.
        !             5:  *
        !             6:  * Daniel Veillard <veillard@redhat.com>
        !             7:  */
        !             8: 
        !             9: /**
        !            10:  * TODO:
        !            11:  * - add support for DTD compatibility spec
        !            12:  *   http://www.oasis-open.org/committees/relax-ng/compatibility-20011203.html
        !            13:  * - report better mem allocations pbms at runtime and abort immediately.
        !            14:  */
        !            15: 
        !            16: #define IN_LIBXML
        !            17: #include "libxml.h"
        !            18: 
        !            19: #ifdef LIBXML_SCHEMAS_ENABLED
        !            20: 
        !            21: #include <string.h>
        !            22: #include <stdio.h>
        !            23: #include <libxml/xmlmemory.h>
        !            24: #include <libxml/parser.h>
        !            25: #include <libxml/parserInternals.h>
        !            26: #include <libxml/hash.h>
        !            27: #include <libxml/uri.h>
        !            28: 
        !            29: #include <libxml/relaxng.h>
        !            30: 
        !            31: #include <libxml/xmlschemastypes.h>
        !            32: #include <libxml/xmlautomata.h>
        !            33: #include <libxml/xmlregexp.h>
        !            34: #include <libxml/xmlschemastypes.h>
        !            35: 
        !            36: /*
        !            37:  * The Relax-NG namespace
        !            38:  */
        !            39: static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
        !            40:     "http://relaxng.org/ns/structure/1.0";
        !            41: 
        !            42: #define IS_RELAXNG(node, type)                                         \
        !            43:    ((node != NULL) && (node->ns != NULL) &&                            \
        !            44:     (xmlStrEqual(node->name, (const xmlChar *) type)) &&               \
        !            45:     (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))
        !            46: 
        !            47: 
        !            48: #if 0
        !            49: #define DEBUG 1
        !            50: 
        !            51: #define DEBUG_GRAMMAR 1
        !            52: 
        !            53: #define DEBUG_CONTENT 1
        !            54: 
        !            55: #define DEBUG_TYPE 1
        !            56: 
        !            57: #define DEBUG_VALID 1
        !            58: 
        !            59: #define DEBUG_INTERLEAVE 1
        !            60: 
        !            61: #define DEBUG_LIST 1
        !            62: 
        !            63: #define DEBUG_INCLUDE 1 
        !            64: 
        !            65: #define DEBUG_ERROR 1
        !            66: 
        !            67: #define DEBUG_COMPILE 1
        !            68: 
        !            69: #define DEBUG_PROGRESSIVE 1
        !            70: #endif
        !            71: 
        !            72: #define MAX_ERROR 5
        !            73: 
        !            74: #define TODO                                                           \
        !            75:     xmlGenericError(xmlGenericErrorContext,                            \
        !            76:            "Unimplemented block at %s:%d\n",                           \
        !            77:             __FILE__, __LINE__);
        !            78: 
        !            79: typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;
        !            80: typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;
        !            81: 
        !            82: typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine;
        !            83: typedef xmlRelaxNGDefine *xmlRelaxNGDefinePtr;
        !            84: 
        !            85: typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument;
        !            86: typedef xmlRelaxNGDocument *xmlRelaxNGDocumentPtr;
        !            87: 
        !            88: typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude;
        !            89: typedef xmlRelaxNGInclude *xmlRelaxNGIncludePtr;
        !            90: 
        !            91: typedef enum {
        !            92:     XML_RELAXNG_COMBINE_UNDEFINED = 0,  /* undefined */
        !            93:     XML_RELAXNG_COMBINE_CHOICE, /* choice */
        !            94:     XML_RELAXNG_COMBINE_INTERLEAVE      /* interleave */
        !            95: } xmlRelaxNGCombine;
        !            96: 
        !            97: typedef enum {
        !            98:     XML_RELAXNG_CONTENT_ERROR = -1,
        !            99:     XML_RELAXNG_CONTENT_EMPTY = 0,
        !           100:     XML_RELAXNG_CONTENT_SIMPLE,
        !           101:     XML_RELAXNG_CONTENT_COMPLEX
        !           102: } xmlRelaxNGContentType;
        !           103: 
        !           104: typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar;
        !           105: typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr;
        !           106: 
        !           107: struct _xmlRelaxNGGrammar {
        !           108:     xmlRelaxNGGrammarPtr parent;        /* the parent grammar if any */
        !           109:     xmlRelaxNGGrammarPtr children;      /* the children grammar if any */
        !           110:     xmlRelaxNGGrammarPtr next;  /* the next grammar if any */
        !           111:     xmlRelaxNGDefinePtr start;  /* <start> content */
        !           112:     xmlRelaxNGCombine combine;  /* the default combine value */
        !           113:     xmlRelaxNGDefinePtr startList;      /* list of <start> definitions */
        !           114:     xmlHashTablePtr defs;       /* define* */
        !           115:     xmlHashTablePtr refs;       /* references */
        !           116: };
        !           117: 
        !           118: 
        !           119: typedef enum {
        !           120:     XML_RELAXNG_NOOP = -1,      /* a no operation from simplification  */
        !           121:     XML_RELAXNG_EMPTY = 0,      /* an empty pattern */
        !           122:     XML_RELAXNG_NOT_ALLOWED,    /* not allowed top */
        !           123:     XML_RELAXNG_EXCEPT,         /* except present in nameclass defs */
        !           124:     XML_RELAXNG_TEXT,           /* textual content */
        !           125:     XML_RELAXNG_ELEMENT,        /* an element */
        !           126:     XML_RELAXNG_DATATYPE,       /* extenal data type definition */
        !           127:     XML_RELAXNG_PARAM,          /* extenal data type parameter */
        !           128:     XML_RELAXNG_VALUE,          /* value from an extenal data type definition */
        !           129:     XML_RELAXNG_LIST,           /* a list of patterns */
        !           130:     XML_RELAXNG_ATTRIBUTE,      /* an attrbute following a pattern */
        !           131:     XML_RELAXNG_DEF,            /* a definition */
        !           132:     XML_RELAXNG_REF,            /* reference to a definition */
        !           133:     XML_RELAXNG_EXTERNALREF,    /* reference to an external def */
        !           134:     XML_RELAXNG_PARENTREF,      /* reference to a def in the parent grammar */
        !           135:     XML_RELAXNG_OPTIONAL,       /* optional patterns */
        !           136:     XML_RELAXNG_ZEROORMORE,     /* zero or more non empty patterns */
        !           137:     XML_RELAXNG_ONEORMORE,      /* one or more non empty patterns */
        !           138:     XML_RELAXNG_CHOICE,         /* a choice between non empty patterns */
        !           139:     XML_RELAXNG_GROUP,          /* a pair/group of non empty patterns */
        !           140:     XML_RELAXNG_INTERLEAVE,     /* interleaving choice of non-empty patterns */
        !           141:     XML_RELAXNG_START           /* Used to keep track of starts on grammars */
        !           142: } xmlRelaxNGType;
        !           143: 
        !           144: #define IS_NULLABLE            (1 << 0)
        !           145: #define IS_NOT_NULLABLE                (1 << 1)
        !           146: #define IS_INDETERMINIST       (1 << 2)
        !           147: #define IS_MIXED               (1 << 3)
        !           148: #define IS_TRIABLE             (1 << 4)
        !           149: #define IS_PROCESSED           (1 << 5)
        !           150: #define IS_COMPILABLE          (1 << 6)
        !           151: #define IS_NOT_COMPILABLE      (1 << 7)
        !           152: #define IS_EXTERNAL_REF                (1 << 8)
        !           153: 
        !           154: struct _xmlRelaxNGDefine {
        !           155:     xmlRelaxNGType type;        /* the type of definition */
        !           156:     xmlNodePtr node;            /* the node in the source */
        !           157:     xmlChar *name;              /* the element local name if present */
        !           158:     xmlChar *ns;                /* the namespace local name if present */
        !           159:     xmlChar *value;             /* value when available */
        !           160:     void *data;                 /* data lib or specific pointer */
        !           161:     xmlRelaxNGDefinePtr content;        /* the expected content */
        !           162:     xmlRelaxNGDefinePtr parent; /* the parent definition, if any */
        !           163:     xmlRelaxNGDefinePtr next;   /* list within grouping sequences */
        !           164:     xmlRelaxNGDefinePtr attrs;  /* list of attributes for elements */
        !           165:     xmlRelaxNGDefinePtr nameClass;      /* the nameClass definition if any */
        !           166:     xmlRelaxNGDefinePtr nextHash;       /* next define in defs/refs hash tables */
        !           167:     short depth;                /* used for the cycle detection */
        !           168:     short dflags;               /* define related flags */
        !           169:     xmlRegexpPtr contModel;     /* a compiled content model if available */
        !           170: };
        !           171: 
        !           172: /**
        !           173:  * _xmlRelaxNG:
        !           174:  *
        !           175:  * A RelaxNGs definition
        !           176:  */
        !           177: struct _xmlRelaxNG {
        !           178:     void *_private;             /* unused by the library for users or bindings */
        !           179:     xmlRelaxNGGrammarPtr topgrammar;
        !           180:     xmlDocPtr doc;
        !           181: 
        !           182:     int idref;                  /* requires idref checking */
        !           183: 
        !           184:     xmlHashTablePtr defs;       /* define */
        !           185:     xmlHashTablePtr refs;       /* references */
        !           186:     xmlRelaxNGDocumentPtr documents;    /* all the documents loaded */
        !           187:     xmlRelaxNGIncludePtr includes;      /* all the includes loaded */
        !           188:     int defNr;                  /* number of defines used */
        !           189:     xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */
        !           190: 
        !           191: };
        !           192: 
        !           193: #define XML_RELAXNG_IN_ATTRIBUTE       (1 << 0)
        !           194: #define XML_RELAXNG_IN_ONEORMORE       (1 << 1)
        !           195: #define XML_RELAXNG_IN_LIST            (1 << 2)
        !           196: #define XML_RELAXNG_IN_DATAEXCEPT      (1 << 3)
        !           197: #define XML_RELAXNG_IN_START           (1 << 4)
        !           198: #define XML_RELAXNG_IN_OOMGROUP                (1 << 5)
        !           199: #define XML_RELAXNG_IN_OOMINTERLEAVE   (1 << 6)
        !           200: #define XML_RELAXNG_IN_EXTERNALREF     (1 << 7)
        !           201: #define XML_RELAXNG_IN_ANYEXCEPT       (1 << 8)
        !           202: #define XML_RELAXNG_IN_NSEXCEPT                (1 << 9)
        !           203: 
        !           204: struct _xmlRelaxNGParserCtxt {
        !           205:     void *userData;             /* user specific data block */
        !           206:     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */
        !           207:     xmlRelaxNGValidityWarningFunc warning;      /* the callback in case of warning */
        !           208:     xmlStructuredErrorFunc serror;
        !           209:     xmlRelaxNGValidErr err;
        !           210: 
        !           211:     xmlRelaxNGPtr schema;       /* The schema in use */
        !           212:     xmlRelaxNGGrammarPtr grammar;       /* the current grammar */
        !           213:     xmlRelaxNGGrammarPtr parentgrammar; /* the parent grammar */
        !           214:     int flags;                  /* parser flags */
        !           215:     int nbErrors;               /* number of errors at parse time */
        !           216:     int nbWarnings;             /* number of warnings at parse time */
        !           217:     const xmlChar *define;      /* the current define scope */
        !           218:     xmlRelaxNGDefinePtr def;    /* the current define */
        !           219: 
        !           220:     int nbInterleaves;
        !           221:     xmlHashTablePtr interleaves;        /* keep track of all the interleaves */
        !           222: 
        !           223:     xmlRelaxNGDocumentPtr documents;    /* all the documents loaded */
        !           224:     xmlRelaxNGIncludePtr includes;      /* all the includes loaded */
        !           225:     xmlChar *URL;
        !           226:     xmlDocPtr document;
        !           227: 
        !           228:     int defNr;                  /* number of defines used */
        !           229:     int defMax;                 /* number of defines aloocated */
        !           230:     xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */
        !           231: 
        !           232:     const char *buffer;
        !           233:     int size;
        !           234: 
        !           235:     /* the document stack */
        !           236:     xmlRelaxNGDocumentPtr doc;  /* Current parsed external ref */
        !           237:     int docNr;                  /* Depth of the parsing stack */
        !           238:     int docMax;                 /* Max depth of the parsing stack */
        !           239:     xmlRelaxNGDocumentPtr *docTab;      /* array of docs */
        !           240: 
        !           241:     /* the include stack */
        !           242:     xmlRelaxNGIncludePtr inc;   /* Current parsed include */
        !           243:     int incNr;                  /* Depth of the include parsing stack */
        !           244:     int incMax;                 /* Max depth of the parsing stack */
        !           245:     xmlRelaxNGIncludePtr *incTab;       /* array of incs */
        !           246: 
        !           247:     int idref;                  /* requires idref checking */
        !           248: 
        !           249:     /* used to compile content models */
        !           250:     xmlAutomataPtr am;          /* the automata */
        !           251:     xmlAutomataStatePtr state;  /* used to build the automata */
        !           252: 
        !           253:     int crng;                  /* compact syntax and other flags */
        !           254:     int freedoc;               /* need to free the document */
        !           255: };
        !           256: 
        !           257: #define FLAGS_IGNORABLE                1
        !           258: #define FLAGS_NEGATIVE         2
        !           259: #define FLAGS_MIXED_CONTENT    4
        !           260: #define FLAGS_NOERROR          8
        !           261: 
        !           262: /**
        !           263:  * xmlRelaxNGInterleaveGroup:
        !           264:  *
        !           265:  * A RelaxNGs partition set associated to lists of definitions
        !           266:  */
        !           267: typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup;
        !           268: typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr;
        !           269: struct _xmlRelaxNGInterleaveGroup {
        !           270:     xmlRelaxNGDefinePtr rule;   /* the rule to satisfy */
        !           271:     xmlRelaxNGDefinePtr *defs;  /* the array of element definitions */
        !           272:     xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */
        !           273: };
        !           274: 
        !           275: #define IS_DETERMINIST         1
        !           276: #define IS_NEEDCHECK           2
        !           277: 
        !           278: /**
        !           279:  * xmlRelaxNGPartitions:
        !           280:  *
        !           281:  * A RelaxNGs partition associated to an interleave group
        !           282:  */
        !           283: typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition;
        !           284: typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr;
        !           285: struct _xmlRelaxNGPartition {
        !           286:     int nbgroups;               /* number of groups in the partitions */
        !           287:     xmlHashTablePtr triage;     /* hash table used to direct nodes to the
        !           288:                                  * right group when possible */
        !           289:     int flags;                  /* determinist ? */
        !           290:     xmlRelaxNGInterleaveGroupPtr *groups;
        !           291: };
        !           292: 
        !           293: /**
        !           294:  * xmlRelaxNGValidState:
        !           295:  *
        !           296:  * A RelaxNGs validation state
        !           297:  */
        !           298: #define MAX_ATTR 20
        !           299: typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState;
        !           300: typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr;
        !           301: struct _xmlRelaxNGValidState {
        !           302:     xmlNodePtr node;            /* the current node */
        !           303:     xmlNodePtr seq;             /* the sequence of children left to validate */
        !           304:     int nbAttrs;                /* the number of attributes */
        !           305:     int maxAttrs;               /* the size of attrs */
        !           306:     int nbAttrLeft;             /* the number of attributes left to validate */
        !           307:     xmlChar *value;             /* the value when operating on string */
        !           308:     xmlChar *endvalue;          /* the end value when operating on string */
        !           309:     xmlAttrPtr *attrs;          /* the array of attributes */
        !           310: };
        !           311: 
        !           312: /**
        !           313:  * xmlRelaxNGStates:
        !           314:  *
        !           315:  * A RelaxNGs container for validation state
        !           316:  */
        !           317: typedef struct _xmlRelaxNGStates xmlRelaxNGStates;
        !           318: typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr;
        !           319: struct _xmlRelaxNGStates {
        !           320:     int nbState;                /* the number of states */
        !           321:     int maxState;               /* the size of the array */
        !           322:     xmlRelaxNGValidStatePtr *tabState;
        !           323: };
        !           324: 
        !           325: #define ERROR_IS_DUP   1
        !           326: 
        !           327: /**
        !           328:  * xmlRelaxNGValidError:
        !           329:  *
        !           330:  * A RelaxNGs validation error
        !           331:  */
        !           332: typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;
        !           333: typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;
        !           334: struct _xmlRelaxNGValidError {
        !           335:     xmlRelaxNGValidErr err;     /* the error number */
        !           336:     int flags;                  /* flags */
        !           337:     xmlNodePtr node;            /* the current node */
        !           338:     xmlNodePtr seq;             /* the current child */
        !           339:     const xmlChar *arg1;        /* first arg */
        !           340:     const xmlChar *arg2;        /* second arg */
        !           341: };
        !           342: 
        !           343: /**
        !           344:  * xmlRelaxNGValidCtxt:
        !           345:  *
        !           346:  * A RelaxNGs validation context
        !           347:  */
        !           348: 
        !           349: struct _xmlRelaxNGValidCtxt {
        !           350:     void *userData;             /* user specific data block */
        !           351:     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */
        !           352:     xmlRelaxNGValidityWarningFunc warning;      /* the callback in case of warning */
        !           353:     xmlStructuredErrorFunc serror;
        !           354:     int nbErrors;               /* number of errors in validation */
        !           355: 
        !           356:     xmlRelaxNGPtr schema;       /* The schema in use */
        !           357:     xmlDocPtr doc;              /* the document being validated */
        !           358:     int flags;                  /* validation flags */
        !           359:     int depth;                  /* validation depth */
        !           360:     int idref;                  /* requires idref checking */
        !           361:     int errNo;                  /* the first error found */
        !           362: 
        !           363:     /*
        !           364:      * Errors accumulated in branches may have to be stacked to be
        !           365:      * provided back when it's sure they affect validation.
        !           366:      */
        !           367:     xmlRelaxNGValidErrorPtr err;        /* Last error */
        !           368:     int errNr;                  /* Depth of the error stack */
        !           369:     int errMax;                 /* Max depth of the error stack */
        !           370:     xmlRelaxNGValidErrorPtr errTab;     /* stack of errors */
        !           371: 
        !           372:     xmlRelaxNGValidStatePtr state;      /* the current validation state */
        !           373:     xmlRelaxNGStatesPtr states; /* the accumulated state list */
        !           374: 
        !           375:     xmlRelaxNGStatesPtr freeState;      /* the pool of free valid states */
        !           376:     int freeStatesNr;
        !           377:     int freeStatesMax;
        !           378:     xmlRelaxNGStatesPtr *freeStates;    /* the pool of free state groups */
        !           379: 
        !           380:     /*
        !           381:      * This is used for "progressive" validation
        !           382:      */
        !           383:     xmlRegExecCtxtPtr elem;     /* the current element regexp */
        !           384:     int elemNr;                 /* the number of element validated */
        !           385:     int elemMax;                /* the max depth of elements */
        !           386:     xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */
        !           387:     int pstate;                 /* progressive state */
        !           388:     xmlNodePtr pnode;           /* the current node */
        !           389:     xmlRelaxNGDefinePtr pdef;   /* the non-streamable definition */
        !           390:     int perr;                   /* signal error in content model
        !           391:                                  * outside the regexp */
        !           392: };
        !           393: 
        !           394: /**
        !           395:  * xmlRelaxNGInclude:
        !           396:  *
        !           397:  * Structure associated to a RelaxNGs document element
        !           398:  */
        !           399: struct _xmlRelaxNGInclude {
        !           400:     xmlRelaxNGIncludePtr next;  /* keep a chain of includes */
        !           401:     xmlChar *href;              /* the normalized href value */
        !           402:     xmlDocPtr doc;              /* the associated XML document */
        !           403:     xmlRelaxNGDefinePtr content;        /* the definitions */
        !           404:     xmlRelaxNGPtr schema;       /* the schema */
        !           405: };
        !           406: 
        !           407: /**
        !           408:  * xmlRelaxNGDocument:
        !           409:  *
        !           410:  * Structure associated to a RelaxNGs document element
        !           411:  */
        !           412: struct _xmlRelaxNGDocument {
        !           413:     xmlRelaxNGDocumentPtr next; /* keep a chain of documents */
        !           414:     xmlChar *href;              /* the normalized href value */
        !           415:     xmlDocPtr doc;              /* the associated XML document */
        !           416:     xmlRelaxNGDefinePtr content;        /* the definitions */
        !           417:     xmlRelaxNGPtr schema;       /* the schema */
        !           418:     int externalRef;            /* 1 if an external ref */
        !           419: };
        !           420: 
        !           421: 
        !           422: /************************************************************************
        !           423:  *                                                                     *
        !           424:  *             Some factorized error routines                          *
        !           425:  *                                                                     *
        !           426:  ************************************************************************/
        !           427: 
        !           428: /**
        !           429:  * xmlRngPErrMemory:
        !           430:  * @ctxt:  an Relax-NG parser context
        !           431:  * @extra:  extra informations
        !           432:  *
        !           433:  * Handle a redefinition of attribute error
        !           434:  */
        !           435: static void
        !           436: xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
        !           437: {
        !           438:     xmlStructuredErrorFunc schannel = NULL;
        !           439:     xmlGenericErrorFunc channel = NULL;
        !           440:     void *data = NULL;
        !           441: 
        !           442:     if (ctxt != NULL) {
        !           443:         if (ctxt->serror != NULL)
        !           444:            schannel = ctxt->serror;
        !           445:        else
        !           446:            channel = ctxt->error;
        !           447:         data = ctxt->userData;
        !           448:         ctxt->nbErrors++;
        !           449:     }
        !           450:     if (extra)
        !           451:         __xmlRaiseError(schannel, channel, data,
        !           452:                         NULL, NULL, XML_FROM_RELAXNGP,
        !           453:                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
        !           454:                         NULL, NULL, 0, 0,
        !           455:                         "Memory allocation failed : %s\n", extra);
        !           456:     else
        !           457:         __xmlRaiseError(schannel, channel, data,
        !           458:                         NULL, NULL, XML_FROM_RELAXNGP,
        !           459:                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
        !           460:                         NULL, NULL, 0, 0, "Memory allocation failed\n");
        !           461: }
        !           462: 
        !           463: /**
        !           464:  * xmlRngVErrMemory:
        !           465:  * @ctxt:  a Relax-NG validation context
        !           466:  * @extra:  extra informations
        !           467:  *
        !           468:  * Handle a redefinition of attribute error
        !           469:  */
        !           470: static void
        !           471: xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)
        !           472: {
        !           473:     xmlStructuredErrorFunc schannel = NULL;
        !           474:     xmlGenericErrorFunc channel = NULL;
        !           475:     void *data = NULL;
        !           476: 
        !           477:     if (ctxt != NULL) {
        !           478:         if (ctxt->serror != NULL)
        !           479:            schannel = ctxt->serror;
        !           480:        else
        !           481:            channel = ctxt->error;
        !           482:         data = ctxt->userData;
        !           483:         ctxt->nbErrors++;
        !           484:     }
        !           485:     if (extra)
        !           486:         __xmlRaiseError(schannel, channel, data,
        !           487:                         NULL, NULL, XML_FROM_RELAXNGV,
        !           488:                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
        !           489:                         NULL, NULL, 0, 0,
        !           490:                         "Memory allocation failed : %s\n", extra);
        !           491:     else
        !           492:         __xmlRaiseError(schannel, channel, data,
        !           493:                         NULL, NULL, XML_FROM_RELAXNGV,
        !           494:                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
        !           495:                         NULL, NULL, 0, 0, "Memory allocation failed\n");
        !           496: }
        !           497: 
        !           498: /**
        !           499:  * xmlRngPErr:
        !           500:  * @ctxt:  a Relax-NG parser context
        !           501:  * @node:  the node raising the error
        !           502:  * @error:  the error code
        !           503:  * @msg:  message
        !           504:  * @str1:  extra info
        !           505:  * @str2:  extra info
        !           506:  *
        !           507:  * Handle a Relax NG Parsing error
        !           508:  */
        !           509: static void
        !           510: xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
        !           511:            const char *msg, const xmlChar * str1, const xmlChar * str2)
        !           512: {
        !           513:     xmlStructuredErrorFunc schannel = NULL;
        !           514:     xmlGenericErrorFunc channel = NULL;
        !           515:     void *data = NULL;
        !           516: 
        !           517:     if (ctxt != NULL) {
        !           518:         if (ctxt->serror != NULL)
        !           519:            schannel = ctxt->serror;
        !           520:        else
        !           521:            channel = ctxt->error;
        !           522:         data = ctxt->userData;
        !           523:         ctxt->nbErrors++;
        !           524:     }
        !           525:     __xmlRaiseError(schannel, channel, data,
        !           526:                     NULL, node, XML_FROM_RELAXNGP,
        !           527:                     error, XML_ERR_ERROR, NULL, 0,
        !           528:                     (const char *) str1, (const char *) str2, NULL, 0, 0,
        !           529:                     msg, str1, str2);
        !           530: }
        !           531: 
        !           532: /**
        !           533:  * xmlRngVErr:
        !           534:  * @ctxt:  a Relax-NG validation context
        !           535:  * @node:  the node raising the error
        !           536:  * @error:  the error code
        !           537:  * @msg:  message
        !           538:  * @str1:  extra info
        !           539:  * @str2:  extra info
        !           540:  *
        !           541:  * Handle a Relax NG Validation error
        !           542:  */
        !           543: static void
        !           544: xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
        !           545:            const char *msg, const xmlChar * str1, const xmlChar * str2)
        !           546: {
        !           547:     xmlStructuredErrorFunc schannel = NULL;
        !           548:     xmlGenericErrorFunc channel = NULL;
        !           549:     void *data = NULL;
        !           550: 
        !           551:     if (ctxt != NULL) {
        !           552:         if (ctxt->serror != NULL)
        !           553:            schannel = ctxt->serror;
        !           554:        else
        !           555:            channel = ctxt->error;
        !           556:         data = ctxt->userData;
        !           557:         ctxt->nbErrors++;
        !           558:     }
        !           559:     __xmlRaiseError(schannel, channel, data,
        !           560:                     NULL, node, XML_FROM_RELAXNGV,
        !           561:                     error, XML_ERR_ERROR, NULL, 0,
        !           562:                     (const char *) str1, (const char *) str2, NULL, 0, 0,
        !           563:                     msg, str1, str2);
        !           564: }
        !           565: 
        !           566: /************************************************************************
        !           567:  *                                                                     *
        !           568:  *             Preliminary type checking interfaces                    *
        !           569:  *                                                                     *
        !           570:  ************************************************************************/
        !           571: 
        !           572: /**
        !           573:  * xmlRelaxNGTypeHave:
        !           574:  * @data:  data needed for the library
        !           575:  * @type:  the type name
        !           576:  * @value:  the value to check
        !           577:  *
        !           578:  * Function provided by a type library to check if a type is exported
        !           579:  *
        !           580:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !           581:  */
        !           582: typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar * type);
        !           583: 
        !           584: /**
        !           585:  * xmlRelaxNGTypeCheck:
        !           586:  * @data:  data needed for the library
        !           587:  * @type:  the type name
        !           588:  * @value:  the value to check
        !           589:  * @result:  place to store the result if needed
        !           590:  *
        !           591:  * Function provided by a type library to check if a value match a type
        !           592:  *
        !           593:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !           594:  */
        !           595: typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar * type,
        !           596:                                     const xmlChar * value, void **result,
        !           597:                                     xmlNodePtr node);
        !           598: 
        !           599: /**
        !           600:  * xmlRelaxNGFacetCheck:
        !           601:  * @data:  data needed for the library
        !           602:  * @type:  the type name
        !           603:  * @facet:  the facet name
        !           604:  * @val:  the facet value
        !           605:  * @strval:  the string value
        !           606:  * @value:  the value to check
        !           607:  *
        !           608:  * Function provided by a type library to check a value facet
        !           609:  *
        !           610:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !           611:  */
        !           612: typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar * type,
        !           613:                                      const xmlChar * facet,
        !           614:                                      const xmlChar * val,
        !           615:                                      const xmlChar * strval, void *value);
        !           616: 
        !           617: /**
        !           618:  * xmlRelaxNGTypeFree:
        !           619:  * @data:  data needed for the library
        !           620:  * @result:  the value to free
        !           621:  *
        !           622:  * Function provided by a type library to free a returned result
        !           623:  */
        !           624: typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);
        !           625: 
        !           626: /**
        !           627:  * xmlRelaxNGTypeCompare:
        !           628:  * @data:  data needed for the library
        !           629:  * @type:  the type name
        !           630:  * @value1:  the first value
        !           631:  * @value2:  the second value
        !           632:  *
        !           633:  * Function provided by a type library to compare two values accordingly
        !           634:  * to a type.
        !           635:  *
        !           636:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !           637:  */
        !           638: typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar * type,
        !           639:                                       const xmlChar * value1,
        !           640:                                       xmlNodePtr ctxt1,
        !           641:                                       void *comp1,
        !           642:                                       const xmlChar * value2,
        !           643:                                       xmlNodePtr ctxt2);
        !           644: typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
        !           645: typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
        !           646: struct _xmlRelaxNGTypeLibrary {
        !           647:     const xmlChar *namespace;   /* the datatypeLibrary value */
        !           648:     void *data;                 /* data needed for the library */
        !           649:     xmlRelaxNGTypeHave have;    /* the export function */
        !           650:     xmlRelaxNGTypeCheck check;  /* the checking function */
        !           651:     xmlRelaxNGTypeCompare comp; /* the compare function */
        !           652:     xmlRelaxNGFacetCheck facet; /* the facet check function */
        !           653:     xmlRelaxNGTypeFree freef;   /* the freeing function */
        !           654: };
        !           655: 
        !           656: /************************************************************************
        !           657:  *                                                                     *
        !           658:  *                     Allocation functions                            *
        !           659:  *                                                                     *
        !           660:  ************************************************************************/
        !           661: static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);
        !           662: static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);
        !           663: static void xmlRelaxNGNormExtSpace(xmlChar * value);
        !           664: static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema);
        !           665: static int xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt
        !           666:                                      ATTRIBUTE_UNUSED,
        !           667:                                      xmlRelaxNGValidStatePtr state1,
        !           668:                                      xmlRelaxNGValidStatePtr state2);
        !           669: static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
        !           670:                                      xmlRelaxNGValidStatePtr state);
        !           671: 
        !           672: /**
        !           673:  * xmlRelaxNGFreeDocument:
        !           674:  * @docu:  a document structure
        !           675:  *
        !           676:  * Deallocate a RelaxNG document structure.
        !           677:  */
        !           678: static void
        !           679: xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu)
        !           680: {
        !           681:     if (docu == NULL)
        !           682:         return;
        !           683: 
        !           684:     if (docu->href != NULL)
        !           685:         xmlFree(docu->href);
        !           686:     if (docu->doc != NULL)
        !           687:         xmlFreeDoc(docu->doc);
        !           688:     if (docu->schema != NULL)
        !           689:         xmlRelaxNGFreeInnerSchema(docu->schema);
        !           690:     xmlFree(docu);
        !           691: }
        !           692: 
        !           693: /**
        !           694:  * xmlRelaxNGFreeDocumentList:
        !           695:  * @docu:  a list of  document structure
        !           696:  *
        !           697:  * Deallocate a RelaxNG document structures.
        !           698:  */
        !           699: static void
        !           700: xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu)
        !           701: {
        !           702:     xmlRelaxNGDocumentPtr next;
        !           703: 
        !           704:     while (docu != NULL) {
        !           705:         next = docu->next;
        !           706:         xmlRelaxNGFreeDocument(docu);
        !           707:         docu = next;
        !           708:     }
        !           709: }
        !           710: 
        !           711: /**
        !           712:  * xmlRelaxNGFreeInclude:
        !           713:  * @incl:  a include structure
        !           714:  *
        !           715:  * Deallocate a RelaxNG include structure.
        !           716:  */
        !           717: static void
        !           718: xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl)
        !           719: {
        !           720:     if (incl == NULL)
        !           721:         return;
        !           722: 
        !           723:     if (incl->href != NULL)
        !           724:         xmlFree(incl->href);
        !           725:     if (incl->doc != NULL)
        !           726:         xmlFreeDoc(incl->doc);
        !           727:     if (incl->schema != NULL)
        !           728:         xmlRelaxNGFree(incl->schema);
        !           729:     xmlFree(incl);
        !           730: }
        !           731: 
        !           732: /**
        !           733:  * xmlRelaxNGFreeIncludeList:
        !           734:  * @incl:  a include structure list
        !           735:  *
        !           736:  * Deallocate a RelaxNG include structure.
        !           737:  */
        !           738: static void
        !           739: xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl)
        !           740: {
        !           741:     xmlRelaxNGIncludePtr next;
        !           742: 
        !           743:     while (incl != NULL) {
        !           744:         next = incl->next;
        !           745:         xmlRelaxNGFreeInclude(incl);
        !           746:         incl = next;
        !           747:     }
        !           748: }
        !           749: 
        !           750: /**
        !           751:  * xmlRelaxNGNewRelaxNG:
        !           752:  * @ctxt:  a Relax-NG validation context (optional)
        !           753:  *
        !           754:  * Allocate a new RelaxNG structure.
        !           755:  *
        !           756:  * Returns the newly allocated structure or NULL in case or error
        !           757:  */
        !           758: static xmlRelaxNGPtr
        !           759: xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)
        !           760: {
        !           761:     xmlRelaxNGPtr ret;
        !           762: 
        !           763:     ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));
        !           764:     if (ret == NULL) {
        !           765:         xmlRngPErrMemory(ctxt, NULL);
        !           766:         return (NULL);
        !           767:     }
        !           768:     memset(ret, 0, sizeof(xmlRelaxNG));
        !           769: 
        !           770:     return (ret);
        !           771: }
        !           772: 
        !           773: /**
        !           774:  * xmlRelaxNGFreeInnerSchema:
        !           775:  * @schema:  a schema structure
        !           776:  *
        !           777:  * Deallocate a RelaxNG schema structure.
        !           778:  */
        !           779: static void
        !           780: xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema)
        !           781: {
        !           782:     if (schema == NULL)
        !           783:         return;
        !           784: 
        !           785:     if (schema->doc != NULL)
        !           786:         xmlFreeDoc(schema->doc);
        !           787:     if (schema->defTab != NULL) {
        !           788:         int i;
        !           789: 
        !           790:         for (i = 0; i < schema->defNr; i++)
        !           791:             xmlRelaxNGFreeDefine(schema->defTab[i]);
        !           792:         xmlFree(schema->defTab);
        !           793:     }
        !           794: 
        !           795:     xmlFree(schema);
        !           796: }
        !           797: 
        !           798: /**
        !           799:  * xmlRelaxNGFree:
        !           800:  * @schema:  a schema structure
        !           801:  *
        !           802:  * Deallocate a RelaxNG structure.
        !           803:  */
        !           804: void
        !           805: xmlRelaxNGFree(xmlRelaxNGPtr schema)
        !           806: {
        !           807:     if (schema == NULL)
        !           808:         return;
        !           809: 
        !           810:     if (schema->topgrammar != NULL)
        !           811:         xmlRelaxNGFreeGrammar(schema->topgrammar);
        !           812:     if (schema->doc != NULL)
        !           813:         xmlFreeDoc(schema->doc);
        !           814:     if (schema->documents != NULL)
        !           815:         xmlRelaxNGFreeDocumentList(schema->documents);
        !           816:     if (schema->includes != NULL)
        !           817:         xmlRelaxNGFreeIncludeList(schema->includes);
        !           818:     if (schema->defTab != NULL) {
        !           819:         int i;
        !           820: 
        !           821:         for (i = 0; i < schema->defNr; i++)
        !           822:             xmlRelaxNGFreeDefine(schema->defTab[i]);
        !           823:         xmlFree(schema->defTab);
        !           824:     }
        !           825: 
        !           826:     xmlFree(schema);
        !           827: }
        !           828: 
        !           829: /**
        !           830:  * xmlRelaxNGNewGrammar:
        !           831:  * @ctxt:  a Relax-NG validation context (optional)
        !           832:  *
        !           833:  * Allocate a new RelaxNG grammar.
        !           834:  *
        !           835:  * Returns the newly allocated structure or NULL in case or error
        !           836:  */
        !           837: static xmlRelaxNGGrammarPtr
        !           838: xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)
        !           839: {
        !           840:     xmlRelaxNGGrammarPtr ret;
        !           841: 
        !           842:     ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));
        !           843:     if (ret == NULL) {
        !           844:         xmlRngPErrMemory(ctxt, NULL);
        !           845:         return (NULL);
        !           846:     }
        !           847:     memset(ret, 0, sizeof(xmlRelaxNGGrammar));
        !           848: 
        !           849:     return (ret);
        !           850: }
        !           851: 
        !           852: /**
        !           853:  * xmlRelaxNGFreeGrammar:
        !           854:  * @grammar:  a grammar structure
        !           855:  *
        !           856:  * Deallocate a RelaxNG grammar structure.
        !           857:  */
        !           858: static void
        !           859: xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar)
        !           860: {
        !           861:     if (grammar == NULL)
        !           862:         return;
        !           863: 
        !           864:     if (grammar->children != NULL) {
        !           865:         xmlRelaxNGFreeGrammar(grammar->children);
        !           866:     }
        !           867:     if (grammar->next != NULL) {
        !           868:         xmlRelaxNGFreeGrammar(grammar->next);
        !           869:     }
        !           870:     if (grammar->refs != NULL) {
        !           871:         xmlHashFree(grammar->refs, NULL);
        !           872:     }
        !           873:     if (grammar->defs != NULL) {
        !           874:         xmlHashFree(grammar->defs, NULL);
        !           875:     }
        !           876: 
        !           877:     xmlFree(grammar);
        !           878: }
        !           879: 
        !           880: /**
        !           881:  * xmlRelaxNGNewDefine:
        !           882:  * @ctxt:  a Relax-NG validation context
        !           883:  * @node:  the node in the input document.
        !           884:  *
        !           885:  * Allocate a new RelaxNG define.
        !           886:  *
        !           887:  * Returns the newly allocated structure or NULL in case or error
        !           888:  */
        !           889: static xmlRelaxNGDefinePtr
        !           890: xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !           891: {
        !           892:     xmlRelaxNGDefinePtr ret;
        !           893: 
        !           894:     if (ctxt->defMax == 0) {
        !           895:         ctxt->defMax = 16;
        !           896:         ctxt->defNr = 0;
        !           897:         ctxt->defTab = (xmlRelaxNGDefinePtr *)
        !           898:             xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
        !           899:         if (ctxt->defTab == NULL) {
        !           900:             xmlRngPErrMemory(ctxt, "allocating define\n");
        !           901:             return (NULL);
        !           902:         }
        !           903:     } else if (ctxt->defMax <= ctxt->defNr) {
        !           904:         xmlRelaxNGDefinePtr *tmp;
        !           905: 
        !           906:         ctxt->defMax *= 2;
        !           907:         tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,
        !           908:                                                  ctxt->defMax *
        !           909:                                                  sizeof
        !           910:                                                  (xmlRelaxNGDefinePtr));
        !           911:         if (tmp == NULL) {
        !           912:             xmlRngPErrMemory(ctxt, "allocating define\n");
        !           913:             return (NULL);
        !           914:         }
        !           915:         ctxt->defTab = tmp;
        !           916:     }
        !           917:     ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
        !           918:     if (ret == NULL) {
        !           919:         xmlRngPErrMemory(ctxt, "allocating define\n");
        !           920:         return (NULL);
        !           921:     }
        !           922:     memset(ret, 0, sizeof(xmlRelaxNGDefine));
        !           923:     ctxt->defTab[ctxt->defNr++] = ret;
        !           924:     ret->node = node;
        !           925:     ret->depth = -1;
        !           926:     return (ret);
        !           927: }
        !           928: 
        !           929: /**
        !           930:  * xmlRelaxNGFreePartition:
        !           931:  * @partitions:  a partition set structure
        !           932:  *
        !           933:  * Deallocate RelaxNG partition set structures.
        !           934:  */
        !           935: static void
        !           936: xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions)
        !           937: {
        !           938:     xmlRelaxNGInterleaveGroupPtr group;
        !           939:     int j;
        !           940: 
        !           941:     if (partitions != NULL) {
        !           942:         if (partitions->groups != NULL) {
        !           943:             for (j = 0; j < partitions->nbgroups; j++) {
        !           944:                 group = partitions->groups[j];
        !           945:                 if (group != NULL) {
        !           946:                     if (group->defs != NULL)
        !           947:                         xmlFree(group->defs);
        !           948:                     if (group->attrs != NULL)
        !           949:                         xmlFree(group->attrs);
        !           950:                     xmlFree(group);
        !           951:                 }
        !           952:             }
        !           953:             xmlFree(partitions->groups);
        !           954:         }
        !           955:         if (partitions->triage != NULL) {
        !           956:             xmlHashFree(partitions->triage, NULL);
        !           957:         }
        !           958:         xmlFree(partitions);
        !           959:     }
        !           960: }
        !           961: 
        !           962: /**
        !           963:  * xmlRelaxNGFreeDefine:
        !           964:  * @define:  a define structure
        !           965:  *
        !           966:  * Deallocate a RelaxNG define structure.
        !           967:  */
        !           968: static void
        !           969: xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define)
        !           970: {
        !           971:     if (define == NULL)
        !           972:         return;
        !           973: 
        !           974:     if ((define->type == XML_RELAXNG_VALUE) && (define->attrs != NULL)) {
        !           975:         xmlRelaxNGTypeLibraryPtr lib;
        !           976: 
        !           977:         lib = (xmlRelaxNGTypeLibraryPtr) define->data;
        !           978:         if ((lib != NULL) && (lib->freef != NULL))
        !           979:             lib->freef(lib->data, (void *) define->attrs);
        !           980:     }
        !           981:     if ((define->data != NULL) && (define->type == XML_RELAXNG_INTERLEAVE))
        !           982:         xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
        !           983:     if ((define->data != NULL) && (define->type == XML_RELAXNG_CHOICE))
        !           984:         xmlHashFree((xmlHashTablePtr) define->data, NULL);
        !           985:     if (define->name != NULL)
        !           986:         xmlFree(define->name);
        !           987:     if (define->ns != NULL)
        !           988:         xmlFree(define->ns);
        !           989:     if (define->value != NULL)
        !           990:         xmlFree(define->value);
        !           991:     if (define->contModel != NULL)
        !           992:         xmlRegFreeRegexp(define->contModel);
        !           993:     xmlFree(define);
        !           994: }
        !           995: 
        !           996: /**
        !           997:  * xmlRelaxNGNewStates:
        !           998:  * @ctxt:  a Relax-NG validation context
        !           999:  * @size:  the default size for the container
        !          1000:  *
        !          1001:  * Allocate a new RelaxNG validation state container
        !          1002:  *
        !          1003:  * Returns the newly allocated structure or NULL in case or error
        !          1004:  */
        !          1005: static xmlRelaxNGStatesPtr
        !          1006: xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
        !          1007: {
        !          1008:     xmlRelaxNGStatesPtr ret;
        !          1009: 
        !          1010:     if ((ctxt != NULL) &&
        !          1011:         (ctxt->freeStates != NULL) && (ctxt->freeStatesNr > 0)) {
        !          1012:         ctxt->freeStatesNr--;
        !          1013:         ret = ctxt->freeStates[ctxt->freeStatesNr];
        !          1014:         ret->nbState = 0;
        !          1015:         return (ret);
        !          1016:     }
        !          1017:     if (size < 16)
        !          1018:         size = 16;
        !          1019: 
        !          1020:     ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +
        !          1021:                                           (size -
        !          1022:                                            1) *
        !          1023:                                           sizeof(xmlRelaxNGValidStatePtr));
        !          1024:     if (ret == NULL) {
        !          1025:         xmlRngVErrMemory(ctxt, "allocating states\n");
        !          1026:         return (NULL);
        !          1027:     }
        !          1028:     ret->nbState = 0;
        !          1029:     ret->maxState = size;
        !          1030:     ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc((size) *
        !          1031:                                                           sizeof
        !          1032:                                                           (xmlRelaxNGValidStatePtr));
        !          1033:     if (ret->tabState == NULL) {
        !          1034:         xmlRngVErrMemory(ctxt, "allocating states\n");
        !          1035:         xmlFree(ret);
        !          1036:         return (NULL);
        !          1037:     }
        !          1038:     return (ret);
        !          1039: }
        !          1040: 
        !          1041: /**
        !          1042:  * xmlRelaxNGAddStateUniq:
        !          1043:  * @ctxt:  a Relax-NG validation context
        !          1044:  * @states:  the states container
        !          1045:  * @state:  the validation state
        !          1046:  *
        !          1047:  * Add a RelaxNG validation state to the container without checking
        !          1048:  * for unicity.
        !          1049:  *
        !          1050:  * Return 1 in case of success and 0 if this is a duplicate and -1 on error
        !          1051:  */
        !          1052: static int
        !          1053: xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,
        !          1054:                         xmlRelaxNGStatesPtr states,
        !          1055:                         xmlRelaxNGValidStatePtr state)
        !          1056: {
        !          1057:     if (state == NULL) {
        !          1058:         return (-1);
        !          1059:     }
        !          1060:     if (states->nbState >= states->maxState) {
        !          1061:         xmlRelaxNGValidStatePtr *tmp;
        !          1062:         int size;
        !          1063: 
        !          1064:         size = states->maxState * 2;
        !          1065:         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
        !          1066:                                                      (size) *
        !          1067:                                                      sizeof
        !          1068:                                                      (xmlRelaxNGValidStatePtr));
        !          1069:         if (tmp == NULL) {
        !          1070:             xmlRngVErrMemory(ctxt, "adding states\n");
        !          1071:             return (-1);
        !          1072:         }
        !          1073:         states->tabState = tmp;
        !          1074:         states->maxState = size;
        !          1075:     }
        !          1076:     states->tabState[states->nbState++] = state;
        !          1077:     return (1);
        !          1078: }
        !          1079: 
        !          1080: /**
        !          1081:  * xmlRelaxNGAddState:
        !          1082:  * @ctxt:  a Relax-NG validation context
        !          1083:  * @states:  the states container
        !          1084:  * @state:  the validation state
        !          1085:  *
        !          1086:  * Add a RelaxNG validation state to the container
        !          1087:  *
        !          1088:  * Return 1 in case of success and 0 if this is a duplicate and -1 on error
        !          1089:  */
        !          1090: static int
        !          1091: xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt,
        !          1092:                     xmlRelaxNGStatesPtr states,
        !          1093:                     xmlRelaxNGValidStatePtr state)
        !          1094: {
        !          1095:     int i;
        !          1096: 
        !          1097:     if (state == NULL) {
        !          1098:         return (-1);
        !          1099:     }
        !          1100:     if (states->nbState >= states->maxState) {
        !          1101:         xmlRelaxNGValidStatePtr *tmp;
        !          1102:         int size;
        !          1103: 
        !          1104:         size = states->maxState * 2;
        !          1105:         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
        !          1106:                                                      (size) *
        !          1107:                                                      sizeof
        !          1108:                                                      (xmlRelaxNGValidStatePtr));
        !          1109:         if (tmp == NULL) {
        !          1110:             xmlRngVErrMemory(ctxt, "adding states\n");
        !          1111:             return (-1);
        !          1112:         }
        !          1113:         states->tabState = tmp;
        !          1114:         states->maxState = size;
        !          1115:     }
        !          1116:     for (i = 0; i < states->nbState; i++) {
        !          1117:         if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) {
        !          1118:             xmlRelaxNGFreeValidState(ctxt, state);
        !          1119:             return (0);
        !          1120:         }
        !          1121:     }
        !          1122:     states->tabState[states->nbState++] = state;
        !          1123:     return (1);
        !          1124: }
        !          1125: 
        !          1126: /**
        !          1127:  * xmlRelaxNGFreeStates:
        !          1128:  * @ctxt:  a Relax-NG validation context
        !          1129:  * @states:  teh container
        !          1130:  *
        !          1131:  * Free a RelaxNG validation state container
        !          1132:  */
        !          1133: static void
        !          1134: xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
        !          1135:                      xmlRelaxNGStatesPtr states)
        !          1136: {
        !          1137:     if (states == NULL)
        !          1138:         return;
        !          1139:     if ((ctxt != NULL) && (ctxt->freeStates == NULL)) {
        !          1140:         ctxt->freeStatesMax = 40;
        !          1141:         ctxt->freeStatesNr = 0;
        !          1142:         ctxt->freeStates = (xmlRelaxNGStatesPtr *)
        !          1143:             xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
        !          1144:         if (ctxt->freeStates == NULL) {
        !          1145:             xmlRngVErrMemory(ctxt, "storing states\n");
        !          1146:         }
        !          1147:     } else if ((ctxt != NULL)
        !          1148:                && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) {
        !          1149:         xmlRelaxNGStatesPtr *tmp;
        !          1150: 
        !          1151:         tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates,
        !          1152:                                                  2 * ctxt->freeStatesMax *
        !          1153:                                                  sizeof
        !          1154:                                                  (xmlRelaxNGStatesPtr));
        !          1155:         if (tmp == NULL) {
        !          1156:             xmlRngVErrMemory(ctxt, "storing states\n");
        !          1157:             xmlFree(states->tabState);
        !          1158:             xmlFree(states);
        !          1159:             return;
        !          1160:         }
        !          1161:         ctxt->freeStates = tmp;
        !          1162:         ctxt->freeStatesMax *= 2;
        !          1163:     }
        !          1164:     if ((ctxt == NULL) || (ctxt->freeStates == NULL)) {
        !          1165:         xmlFree(states->tabState);
        !          1166:         xmlFree(states);
        !          1167:     } else {
        !          1168:         ctxt->freeStates[ctxt->freeStatesNr++] = states;
        !          1169:     }
        !          1170: }
        !          1171: 
        !          1172: /**
        !          1173:  * xmlRelaxNGNewValidState:
        !          1174:  * @ctxt:  a Relax-NG validation context
        !          1175:  * @node:  the current node or NULL for the document
        !          1176:  *
        !          1177:  * Allocate a new RelaxNG validation state
        !          1178:  *
        !          1179:  * Returns the newly allocated structure or NULL in case or error
        !          1180:  */
        !          1181: static xmlRelaxNGValidStatePtr
        !          1182: xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
        !          1183: {
        !          1184:     xmlRelaxNGValidStatePtr ret;
        !          1185:     xmlAttrPtr attr;
        !          1186:     xmlAttrPtr attrs[MAX_ATTR];
        !          1187:     int nbAttrs = 0;
        !          1188:     xmlNodePtr root = NULL;
        !          1189: 
        !          1190:     if (node == NULL) {
        !          1191:         root = xmlDocGetRootElement(ctxt->doc);
        !          1192:         if (root == NULL)
        !          1193:             return (NULL);
        !          1194:     } else {
        !          1195:         attr = node->properties;
        !          1196:         while (attr != NULL) {
        !          1197:             if (nbAttrs < MAX_ATTR)
        !          1198:                 attrs[nbAttrs++] = attr;
        !          1199:             else
        !          1200:                 nbAttrs++;
        !          1201:             attr = attr->next;
        !          1202:         }
        !          1203:     }
        !          1204:     if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
        !          1205:         ctxt->freeState->nbState--;
        !          1206:         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
        !          1207:     } else {
        !          1208:         ret =
        !          1209:             (xmlRelaxNGValidStatePtr)
        !          1210:             xmlMalloc(sizeof(xmlRelaxNGValidState));
        !          1211:         if (ret == NULL) {
        !          1212:             xmlRngVErrMemory(ctxt, "allocating states\n");
        !          1213:             return (NULL);
        !          1214:         }
        !          1215:         memset(ret, 0, sizeof(xmlRelaxNGValidState));
        !          1216:     }
        !          1217:     ret->value = NULL;
        !          1218:     ret->endvalue = NULL;
        !          1219:     if (node == NULL) {
        !          1220:         ret->node = (xmlNodePtr) ctxt->doc;
        !          1221:         ret->seq = root;
        !          1222:     } else {
        !          1223:         ret->node = node;
        !          1224:         ret->seq = node->children;
        !          1225:     }
        !          1226:     ret->nbAttrs = 0;
        !          1227:     if (nbAttrs > 0) {
        !          1228:         if (ret->attrs == NULL) {
        !          1229:             if (nbAttrs < 4)
        !          1230:                 ret->maxAttrs = 4;
        !          1231:             else
        !          1232:                 ret->maxAttrs = nbAttrs;
        !          1233:             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
        !          1234:                                                   sizeof(xmlAttrPtr));
        !          1235:             if (ret->attrs == NULL) {
        !          1236:                 xmlRngVErrMemory(ctxt, "allocating states\n");
        !          1237:                 return (ret);
        !          1238:             }
        !          1239:         } else if (ret->maxAttrs < nbAttrs) {
        !          1240:             xmlAttrPtr *tmp;
        !          1241: 
        !          1242:             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *
        !          1243:                                             sizeof(xmlAttrPtr));
        !          1244:             if (tmp == NULL) {
        !          1245:                 xmlRngVErrMemory(ctxt, "allocating states\n");
        !          1246:                 return (ret);
        !          1247:             }
        !          1248:             ret->attrs = tmp;
        !          1249:             ret->maxAttrs = nbAttrs;
        !          1250:         }
        !          1251:         ret->nbAttrs = nbAttrs;
        !          1252:         if (nbAttrs < MAX_ATTR) {
        !          1253:             memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs);
        !          1254:         } else {
        !          1255:             attr = node->properties;
        !          1256:             nbAttrs = 0;
        !          1257:             while (attr != NULL) {
        !          1258:                 ret->attrs[nbAttrs++] = attr;
        !          1259:                 attr = attr->next;
        !          1260:             }
        !          1261:         }
        !          1262:     }
        !          1263:     ret->nbAttrLeft = ret->nbAttrs;
        !          1264:     return (ret);
        !          1265: }
        !          1266: 
        !          1267: /**
        !          1268:  * xmlRelaxNGCopyValidState:
        !          1269:  * @ctxt:  a Relax-NG validation context
        !          1270:  * @state:  a validation state
        !          1271:  *
        !          1272:  * Copy the validation state
        !          1273:  *
        !          1274:  * Returns the newly allocated structure or NULL in case or error
        !          1275:  */
        !          1276: static xmlRelaxNGValidStatePtr
        !          1277: xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
        !          1278:                          xmlRelaxNGValidStatePtr state)
        !          1279: {
        !          1280:     xmlRelaxNGValidStatePtr ret;
        !          1281:     unsigned int maxAttrs;
        !          1282:     xmlAttrPtr *attrs;
        !          1283: 
        !          1284:     if (state == NULL)
        !          1285:         return (NULL);
        !          1286:     if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
        !          1287:         ctxt->freeState->nbState--;
        !          1288:         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
        !          1289:     } else {
        !          1290:         ret =
        !          1291:             (xmlRelaxNGValidStatePtr)
        !          1292:             xmlMalloc(sizeof(xmlRelaxNGValidState));
        !          1293:         if (ret == NULL) {
        !          1294:             xmlRngVErrMemory(ctxt, "allocating states\n");
        !          1295:             return (NULL);
        !          1296:         }
        !          1297:         memset(ret, 0, sizeof(xmlRelaxNGValidState));
        !          1298:     }
        !          1299:     attrs = ret->attrs;
        !          1300:     maxAttrs = ret->maxAttrs;
        !          1301:     memcpy(ret, state, sizeof(xmlRelaxNGValidState));
        !          1302:     ret->attrs = attrs;
        !          1303:     ret->maxAttrs = maxAttrs;
        !          1304:     if (state->nbAttrs > 0) {
        !          1305:         if (ret->attrs == NULL) {
        !          1306:             ret->maxAttrs = state->maxAttrs;
        !          1307:             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
        !          1308:                                                   sizeof(xmlAttrPtr));
        !          1309:             if (ret->attrs == NULL) {
        !          1310:                 xmlRngVErrMemory(ctxt, "allocating states\n");
        !          1311:                 ret->nbAttrs = 0;
        !          1312:                 return (ret);
        !          1313:             }
        !          1314:         } else if (ret->maxAttrs < state->nbAttrs) {
        !          1315:             xmlAttrPtr *tmp;
        !          1316: 
        !          1317:             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *
        !          1318:                                             sizeof(xmlAttrPtr));
        !          1319:             if (tmp == NULL) {
        !          1320:                 xmlRngVErrMemory(ctxt, "allocating states\n");
        !          1321:                 ret->nbAttrs = 0;
        !          1322:                 return (ret);
        !          1323:             }
        !          1324:             ret->maxAttrs = state->maxAttrs;
        !          1325:             ret->attrs = tmp;
        !          1326:         }
        !          1327:         memcpy(ret->attrs, state->attrs,
        !          1328:                state->nbAttrs * sizeof(xmlAttrPtr));
        !          1329:     }
        !          1330:     return (ret);
        !          1331: }
        !          1332: 
        !          1333: /**
        !          1334:  * xmlRelaxNGEqualValidState:
        !          1335:  * @ctxt:  a Relax-NG validation context
        !          1336:  * @state1:  a validation state
        !          1337:  * @state2:  a validation state
        !          1338:  *
        !          1339:  * Compare the validation states for equality
        !          1340:  *
        !          1341:  * Returns 1 if equald, 0 otherwise
        !          1342:  */
        !          1343: static int
        !          1344: xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
        !          1345:                           xmlRelaxNGValidStatePtr state1,
        !          1346:                           xmlRelaxNGValidStatePtr state2)
        !          1347: {
        !          1348:     int i;
        !          1349: 
        !          1350:     if ((state1 == NULL) || (state2 == NULL))
        !          1351:         return (0);
        !          1352:     if (state1 == state2)
        !          1353:         return (1);
        !          1354:     if (state1->node != state2->node)
        !          1355:         return (0);
        !          1356:     if (state1->seq != state2->seq)
        !          1357:         return (0);
        !          1358:     if (state1->nbAttrLeft != state2->nbAttrLeft)
        !          1359:         return (0);
        !          1360:     if (state1->nbAttrs != state2->nbAttrs)
        !          1361:         return (0);
        !          1362:     if (state1->endvalue != state2->endvalue)
        !          1363:         return (0);
        !          1364:     if ((state1->value != state2->value) &&
        !          1365:         (!xmlStrEqual(state1->value, state2->value)))
        !          1366:         return (0);
        !          1367:     for (i = 0; i < state1->nbAttrs; i++) {
        !          1368:         if (state1->attrs[i] != state2->attrs[i])
        !          1369:             return (0);
        !          1370:     }
        !          1371:     return (1);
        !          1372: }
        !          1373: 
        !          1374: /**
        !          1375:  * xmlRelaxNGFreeValidState:
        !          1376:  * @state:  a validation state structure
        !          1377:  *
        !          1378:  * Deallocate a RelaxNG validation state structure.
        !          1379:  */
        !          1380: static void
        !          1381: xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
        !          1382:                          xmlRelaxNGValidStatePtr state)
        !          1383: {
        !          1384:     if (state == NULL)
        !          1385:         return;
        !          1386: 
        !          1387:     if ((ctxt != NULL) && (ctxt->freeState == NULL)) {
        !          1388:         ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40);
        !          1389:     }
        !          1390:     if ((ctxt == NULL) || (ctxt->freeState == NULL)) {
        !          1391:         if (state->attrs != NULL)
        !          1392:             xmlFree(state->attrs);
        !          1393:         xmlFree(state);
        !          1394:     } else {
        !          1395:         xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state);
        !          1396:     }
        !          1397: }
        !          1398: 
        !          1399: /************************************************************************
        !          1400:  *                                                                     *
        !          1401:  *                     Semi internal functions                         *
        !          1402:  *                                                                     *
        !          1403:  ************************************************************************/
        !          1404: 
        !          1405: /**
        !          1406:  * xmlRelaxParserSetFlag:
        !          1407:  * @ctxt: a RelaxNG parser context
        !          1408:  * @flags: a set of flags values
        !          1409:  *
        !          1410:  * Semi private function used to pass informations to a parser context
        !          1411:  * which are a combination of xmlRelaxNGParserFlag .
        !          1412:  *
        !          1413:  * Returns 0 if success and -1 in case of error
        !          1414:  */
        !          1415: int
        !          1416: xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags)
        !          1417: {
        !          1418:     if (ctxt == NULL) return(-1);
        !          1419:     if (flags & XML_RELAXNGP_FREE_DOC) {
        !          1420:         ctxt->crng |= XML_RELAXNGP_FREE_DOC;
        !          1421:        flags -= XML_RELAXNGP_FREE_DOC;
        !          1422:     }
        !          1423:     if (flags & XML_RELAXNGP_CRNG) {
        !          1424:         ctxt->crng |= XML_RELAXNGP_CRNG;
        !          1425:        flags -= XML_RELAXNGP_CRNG;
        !          1426:     }
        !          1427:     if (flags != 0) return(-1);
        !          1428:     return(0);
        !          1429: }
        !          1430: 
        !          1431: /************************************************************************
        !          1432:  *                                                                     *
        !          1433:  *                     Document functions                              *
        !          1434:  *                                                                     *
        !          1435:  ************************************************************************/
        !          1436: static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
        !          1437:                                       xmlDocPtr doc);
        !          1438: 
        !          1439: /**
        !          1440:  * xmlRelaxNGIncludePush:
        !          1441:  * @ctxt:  the parser context
        !          1442:  * @value:  the element doc
        !          1443:  *
        !          1444:  * Pushes a new include on top of the include stack
        !          1445:  *
        !          1446:  * Returns 0 in case of error, the index in the stack otherwise
        !          1447:  */
        !          1448: static int
        !          1449: xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
        !          1450:                       xmlRelaxNGIncludePtr value)
        !          1451: {
        !          1452:     if (ctxt->incTab == NULL) {
        !          1453:         ctxt->incMax = 4;
        !          1454:         ctxt->incNr = 0;
        !          1455:         ctxt->incTab =
        !          1456:             (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *
        !          1457:                                                sizeof(ctxt->incTab[0]));
        !          1458:         if (ctxt->incTab == NULL) {
        !          1459:             xmlRngPErrMemory(ctxt, "allocating include\n");
        !          1460:             return (0);
        !          1461:         }
        !          1462:     }
        !          1463:     if (ctxt->incNr >= ctxt->incMax) {
        !          1464:         ctxt->incMax *= 2;
        !          1465:         ctxt->incTab =
        !          1466:             (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,
        !          1467:                                                 ctxt->incMax *
        !          1468:                                                 sizeof(ctxt->incTab[0]));
        !          1469:         if (ctxt->incTab == NULL) {
        !          1470:             xmlRngPErrMemory(ctxt, "allocating include\n");
        !          1471:             return (0);
        !          1472:         }
        !          1473:     }
        !          1474:     ctxt->incTab[ctxt->incNr] = value;
        !          1475:     ctxt->inc = value;
        !          1476:     return (ctxt->incNr++);
        !          1477: }
        !          1478: 
        !          1479: /**
        !          1480:  * xmlRelaxNGIncludePop:
        !          1481:  * @ctxt: the parser context
        !          1482:  *
        !          1483:  * Pops the top include from the include stack
        !          1484:  *
        !          1485:  * Returns the include just removed
        !          1486:  */
        !          1487: static xmlRelaxNGIncludePtr
        !          1488: xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt)
        !          1489: {
        !          1490:     xmlRelaxNGIncludePtr ret;
        !          1491: 
        !          1492:     if (ctxt->incNr <= 0)
        !          1493:         return (NULL);
        !          1494:     ctxt->incNr--;
        !          1495:     if (ctxt->incNr > 0)
        !          1496:         ctxt->inc = ctxt->incTab[ctxt->incNr - 1];
        !          1497:     else
        !          1498:         ctxt->inc = NULL;
        !          1499:     ret = ctxt->incTab[ctxt->incNr];
        !          1500:     ctxt->incTab[ctxt->incNr] = NULL;
        !          1501:     return (ret);
        !          1502: }
        !          1503: 
        !          1504: /**
        !          1505:  * xmlRelaxNGRemoveRedefine:
        !          1506:  * @ctxt: the parser context
        !          1507:  * @URL:  the normalized URL
        !          1508:  * @target:  the included target
        !          1509:  * @name:  the define name to eliminate
        !          1510:  *
        !          1511:  * Applies the elimination algorithm of 4.7
        !          1512:  *
        !          1513:  * Returns 0 in case of error, 1 in case of success.
        !          1514:  */
        !          1515: static int
        !          1516: xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
        !          1517:                          const xmlChar * URL ATTRIBUTE_UNUSED,
        !          1518:                          xmlNodePtr target, const xmlChar * name)
        !          1519: {
        !          1520:     int found = 0;
        !          1521:     xmlNodePtr tmp, tmp2;
        !          1522:     xmlChar *name2;
        !          1523: 
        !          1524: #ifdef DEBUG_INCLUDE
        !          1525:     if (name == NULL)
        !          1526:         xmlGenericError(xmlGenericErrorContext,
        !          1527:                         "Elimination of <include> start from %s\n", URL);
        !          1528:     else
        !          1529:         xmlGenericError(xmlGenericErrorContext,
        !          1530:                         "Elimination of <include> define %s from %s\n",
        !          1531:                         name, URL);
        !          1532: #endif
        !          1533:     tmp = target;
        !          1534:     while (tmp != NULL) {
        !          1535:         tmp2 = tmp->next;
        !          1536:         if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) {
        !          1537:             found = 1;
        !          1538:             xmlUnlinkNode(tmp);
        !          1539:             xmlFreeNode(tmp);
        !          1540:         } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) {
        !          1541:             name2 = xmlGetProp(tmp, BAD_CAST "name");
        !          1542:             xmlRelaxNGNormExtSpace(name2);
        !          1543:             if (name2 != NULL) {
        !          1544:                 if (xmlStrEqual(name, name2)) {
        !          1545:                     found = 1;
        !          1546:                     xmlUnlinkNode(tmp);
        !          1547:                     xmlFreeNode(tmp);
        !          1548:                 }
        !          1549:                 xmlFree(name2);
        !          1550:             }
        !          1551:         } else if (IS_RELAXNG(tmp, "include")) {
        !          1552:             xmlChar *href = NULL;
        !          1553:             xmlRelaxNGDocumentPtr inc = tmp->psvi;
        !          1554: 
        !          1555:             if ((inc != NULL) && (inc->doc != NULL) &&
        !          1556:                 (inc->doc->children != NULL)) {
        !          1557: 
        !          1558:                 if (xmlStrEqual
        !          1559:                     (inc->doc->children->name, BAD_CAST "grammar")) {
        !          1560: #ifdef DEBUG_INCLUDE
        !          1561:                     href = xmlGetProp(tmp, BAD_CAST "href");
        !          1562: #endif
        !          1563:                     if (xmlRelaxNGRemoveRedefine(ctxt, href,
        !          1564:                                                  inc->doc->children->
        !          1565:                                                  children, name) == 1) {
        !          1566:                         found = 1;
        !          1567:                     }
        !          1568: #ifdef DEBUG_INCLUDE
        !          1569:                     if (href != NULL)
        !          1570:                         xmlFree(href);
        !          1571: #endif
        !          1572:                 }
        !          1573:             }
        !          1574:         }
        !          1575:         tmp = tmp2;
        !          1576:     }
        !          1577:     return (found);
        !          1578: }
        !          1579: 
        !          1580: /**
        !          1581:  * xmlRelaxNGLoadInclude:
        !          1582:  * @ctxt: the parser context
        !          1583:  * @URL:  the normalized URL
        !          1584:  * @node: the include node.
        !          1585:  * @ns:  the namespace passed from the context.
        !          1586:  *
        !          1587:  * First lookup if the document is already loaded into the parser context,
        !          1588:  * check against recursion. If not found the resource is loaded and
        !          1589:  * the content is preprocessed before being returned back to the caller.
        !          1590:  *
        !          1591:  * Returns the xmlRelaxNGIncludePtr or NULL in case of error
        !          1592:  */
        !          1593: static xmlRelaxNGIncludePtr
        !          1594: xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
        !          1595:                       xmlNodePtr node, const xmlChar * ns)
        !          1596: {
        !          1597:     xmlRelaxNGIncludePtr ret = NULL;
        !          1598:     xmlDocPtr doc;
        !          1599:     int i;
        !          1600:     xmlNodePtr root, cur;
        !          1601: 
        !          1602: #ifdef DEBUG_INCLUDE
        !          1603:     xmlGenericError(xmlGenericErrorContext,
        !          1604:                     "xmlRelaxNGLoadInclude(%s)\n", URL);
        !          1605: #endif
        !          1606: 
        !          1607:     /*
        !          1608:      * check against recursion in the stack
        !          1609:      */
        !          1610:     for (i = 0; i < ctxt->incNr; i++) {
        !          1611:         if (xmlStrEqual(ctxt->incTab[i]->href, URL)) {
        !          1612:             xmlRngPErr(ctxt, NULL, XML_RNGP_INCLUDE_RECURSE,
        !          1613:                        "Detected an Include recursion for %s\n", URL,
        !          1614:                        NULL);
        !          1615:             return (NULL);
        !          1616:         }
        !          1617:     }
        !          1618: 
        !          1619:     /*
        !          1620:      * load the document
        !          1621:      */
        !          1622:     doc = xmlReadFile((const char *) URL,NULL,0);
        !          1623:     if (doc == NULL) {
        !          1624:         xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR,
        !          1625:                    "xmlRelaxNG: could not load %s\n", URL, NULL);
        !          1626:         return (NULL);
        !          1627:     }
        !          1628: #ifdef DEBUG_INCLUDE
        !          1629:     xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL);
        !          1630: #endif
        !          1631: 
        !          1632:     /*
        !          1633:      * Allocate the document structures and register it first.
        !          1634:      */
        !          1635:     ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));
        !          1636:     if (ret == NULL) {
        !          1637:         xmlRngPErrMemory(ctxt, "allocating include\n");
        !          1638:         xmlFreeDoc(doc);
        !          1639:         return (NULL);
        !          1640:     }
        !          1641:     memset(ret, 0, sizeof(xmlRelaxNGInclude));
        !          1642:     ret->doc = doc;
        !          1643:     ret->href = xmlStrdup(URL);
        !          1644:     ret->next = ctxt->includes;
        !          1645:     ctxt->includes = ret;
        !          1646: 
        !          1647:     /*
        !          1648:      * transmit the ns if needed
        !          1649:      */
        !          1650:     if (ns != NULL) {
        !          1651:         root = xmlDocGetRootElement(doc);
        !          1652:         if (root != NULL) {
        !          1653:             if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
        !          1654:                 xmlSetProp(root, BAD_CAST "ns", ns);
        !          1655:             }
        !          1656:         }
        !          1657:     }
        !          1658: 
        !          1659:     /*
        !          1660:      * push it on the stack
        !          1661:      */
        !          1662:     xmlRelaxNGIncludePush(ctxt, ret);
        !          1663: 
        !          1664:     /*
        !          1665:      * Some preprocessing of the document content, this include recursing
        !          1666:      * in the include stack.
        !          1667:      */
        !          1668: #ifdef DEBUG_INCLUDE
        !          1669:     xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL);
        !          1670: #endif
        !          1671: 
        !          1672:     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
        !          1673:     if (doc == NULL) {
        !          1674:         ctxt->inc = NULL;
        !          1675:         return (NULL);
        !          1676:     }
        !          1677: 
        !          1678:     /*
        !          1679:      * Pop up the include from the stack
        !          1680:      */
        !          1681:     xmlRelaxNGIncludePop(ctxt);
        !          1682: 
        !          1683: #ifdef DEBUG_INCLUDE
        !          1684:     xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL);
        !          1685: #endif
        !          1686:     /*
        !          1687:      * Check that the top element is a grammar
        !          1688:      */
        !          1689:     root = xmlDocGetRootElement(doc);
        !          1690:     if (root == NULL) {
        !          1691:         xmlRngPErr(ctxt, node, XML_RNGP_EMPTY,
        !          1692:                    "xmlRelaxNG: included document is empty %s\n", URL,
        !          1693:                    NULL);
        !          1694:         return (NULL);
        !          1695:     }
        !          1696:     if (!IS_RELAXNG(root, "grammar")) {
        !          1697:         xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
        !          1698:                    "xmlRelaxNG: included document %s root is not a grammar\n",
        !          1699:                    URL, NULL);
        !          1700:         return (NULL);
        !          1701:     }
        !          1702: 
        !          1703:     /*
        !          1704:      * Elimination of redefined rules in the include.
        !          1705:      */
        !          1706:     cur = node->children;
        !          1707:     while (cur != NULL) {
        !          1708:         if (IS_RELAXNG(cur, "start")) {
        !          1709:             int found = 0;
        !          1710: 
        !          1711:             found =
        !          1712:                 xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);
        !          1713:             if (!found) {
        !          1714:                 xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING,
        !          1715:                            "xmlRelaxNG: include %s has a start but not the included grammar\n",
        !          1716:                            URL, NULL);
        !          1717:             }
        !          1718:         } else if (IS_RELAXNG(cur, "define")) {
        !          1719:             xmlChar *name;
        !          1720: 
        !          1721:             name = xmlGetProp(cur, BAD_CAST "name");
        !          1722:             if (name == NULL) {
        !          1723:                 xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING,
        !          1724:                            "xmlRelaxNG: include %s has define without name\n",
        !          1725:                            URL, NULL);
        !          1726:             } else {
        !          1727:                 int found;
        !          1728: 
        !          1729:                 xmlRelaxNGNormExtSpace(name);
        !          1730:                 found = xmlRelaxNGRemoveRedefine(ctxt, URL,
        !          1731:                                                  root->children, name);
        !          1732:                 if (!found) {
        !          1733:                     xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING,
        !          1734:                                "xmlRelaxNG: include %s has a define %s but not the included grammar\n",
        !          1735:                                URL, name);
        !          1736:                 }
        !          1737:                 xmlFree(name);
        !          1738:             }
        !          1739:         }
        !          1740:         cur = cur->next;
        !          1741:     }
        !          1742: 
        !          1743: 
        !          1744:     return (ret);
        !          1745: }
        !          1746: 
        !          1747: /**
        !          1748:  * xmlRelaxNGValidErrorPush:
        !          1749:  * @ctxt:  the validation context
        !          1750:  * @err:  the error code
        !          1751:  * @arg1:  the first string argument
        !          1752:  * @arg2:  the second string argument
        !          1753:  * @dup:  arg need to be duplicated
        !          1754:  *
        !          1755:  * Pushes a new error on top of the error stack
        !          1756:  *
        !          1757:  * Returns 0 in case of error, the index in the stack otherwise
        !          1758:  */
        !          1759: static int
        !          1760: xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
        !          1761:                          xmlRelaxNGValidErr err, const xmlChar * arg1,
        !          1762:                          const xmlChar * arg2, int dup)
        !          1763: {
        !          1764:     xmlRelaxNGValidErrorPtr cur;
        !          1765: 
        !          1766: #ifdef DEBUG_ERROR
        !          1767:     xmlGenericError(xmlGenericErrorContext,
        !          1768:                     "Pushing error %d at %d on stack\n", err, ctxt->errNr);
        !          1769: #endif
        !          1770:     if (ctxt->errTab == NULL) {
        !          1771:         ctxt->errMax = 8;
        !          1772:         ctxt->errNr = 0;
        !          1773:         ctxt->errTab =
        !          1774:             (xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax *
        !          1775:                                                 sizeof
        !          1776:                                                 (xmlRelaxNGValidError));
        !          1777:         if (ctxt->errTab == NULL) {
        !          1778:             xmlRngVErrMemory(ctxt, "pushing error\n");
        !          1779:             return (0);
        !          1780:         }
        !          1781:         ctxt->err = NULL;
        !          1782:     }
        !          1783:     if (ctxt->errNr >= ctxt->errMax) {
        !          1784:         ctxt->errMax *= 2;
        !          1785:         ctxt->errTab =
        !          1786:             (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,
        !          1787:                                                  ctxt->errMax *
        !          1788:                                                  sizeof
        !          1789:                                                  (xmlRelaxNGValidError));
        !          1790:         if (ctxt->errTab == NULL) {
        !          1791:             xmlRngVErrMemory(ctxt, "pushing error\n");
        !          1792:             return (0);
        !          1793:         }
        !          1794:         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
        !          1795:     }
        !          1796:     if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
        !          1797:         (ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err))
        !          1798:         return (ctxt->errNr);
        !          1799:     cur = &ctxt->errTab[ctxt->errNr];
        !          1800:     cur->err = err;
        !          1801:     if (dup) {
        !          1802:         cur->arg1 = xmlStrdup(arg1);
        !          1803:         cur->arg2 = xmlStrdup(arg2);
        !          1804:         cur->flags = ERROR_IS_DUP;
        !          1805:     } else {
        !          1806:         cur->arg1 = arg1;
        !          1807:         cur->arg2 = arg2;
        !          1808:         cur->flags = 0;
        !          1809:     }
        !          1810:     if (ctxt->state != NULL) {
        !          1811:         cur->node = ctxt->state->node;
        !          1812:         cur->seq = ctxt->state->seq;
        !          1813:     } else {
        !          1814:         cur->node = NULL;
        !          1815:         cur->seq = NULL;
        !          1816:     }
        !          1817:     ctxt->err = cur;
        !          1818:     return (ctxt->errNr++);
        !          1819: }
        !          1820: 
        !          1821: /**
        !          1822:  * xmlRelaxNGValidErrorPop:
        !          1823:  * @ctxt: the validation context
        !          1824:  *
        !          1825:  * Pops the top error from the error stack
        !          1826:  */
        !          1827: static void
        !          1828: xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
        !          1829: {
        !          1830:     xmlRelaxNGValidErrorPtr cur;
        !          1831: 
        !          1832:     if (ctxt->errNr <= 0) {
        !          1833:         ctxt->err = NULL;
        !          1834:         return;
        !          1835:     }
        !          1836:     ctxt->errNr--;
        !          1837:     if (ctxt->errNr > 0)
        !          1838:         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
        !          1839:     else
        !          1840:         ctxt->err = NULL;
        !          1841:     cur = &ctxt->errTab[ctxt->errNr];
        !          1842:     if (cur->flags & ERROR_IS_DUP) {
        !          1843:         if (cur->arg1 != NULL)
        !          1844:             xmlFree((xmlChar *) cur->arg1);
        !          1845:         cur->arg1 = NULL;
        !          1846:         if (cur->arg2 != NULL)
        !          1847:             xmlFree((xmlChar *) cur->arg2);
        !          1848:         cur->arg2 = NULL;
        !          1849:         cur->flags = 0;
        !          1850:     }
        !          1851: }
        !          1852: 
        !          1853: /**
        !          1854:  * xmlRelaxNGDocumentPush:
        !          1855:  * @ctxt:  the parser context
        !          1856:  * @value:  the element doc
        !          1857:  *
        !          1858:  * Pushes a new doc on top of the doc stack
        !          1859:  *
        !          1860:  * Returns 0 in case of error, the index in the stack otherwise
        !          1861:  */
        !          1862: static int
        !          1863: xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
        !          1864:                        xmlRelaxNGDocumentPtr value)
        !          1865: {
        !          1866:     if (ctxt->docTab == NULL) {
        !          1867:         ctxt->docMax = 4;
        !          1868:         ctxt->docNr = 0;
        !          1869:         ctxt->docTab =
        !          1870:             (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *
        !          1871:                                                 sizeof(ctxt->docTab[0]));
        !          1872:         if (ctxt->docTab == NULL) {
        !          1873:             xmlRngPErrMemory(ctxt, "adding document\n");
        !          1874:             return (0);
        !          1875:         }
        !          1876:     }
        !          1877:     if (ctxt->docNr >= ctxt->docMax) {
        !          1878:         ctxt->docMax *= 2;
        !          1879:         ctxt->docTab =
        !          1880:             (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,
        !          1881:                                                  ctxt->docMax *
        !          1882:                                                  sizeof(ctxt->docTab[0]));
        !          1883:         if (ctxt->docTab == NULL) {
        !          1884:             xmlRngPErrMemory(ctxt, "adding document\n");
        !          1885:             return (0);
        !          1886:         }
        !          1887:     }
        !          1888:     ctxt->docTab[ctxt->docNr] = value;
        !          1889:     ctxt->doc = value;
        !          1890:     return (ctxt->docNr++);
        !          1891: }
        !          1892: 
        !          1893: /**
        !          1894:  * xmlRelaxNGDocumentPop:
        !          1895:  * @ctxt: the parser context
        !          1896:  *
        !          1897:  * Pops the top doc from the doc stack
        !          1898:  *
        !          1899:  * Returns the doc just removed
        !          1900:  */
        !          1901: static xmlRelaxNGDocumentPtr
        !          1902: xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)
        !          1903: {
        !          1904:     xmlRelaxNGDocumentPtr ret;
        !          1905: 
        !          1906:     if (ctxt->docNr <= 0)
        !          1907:         return (NULL);
        !          1908:     ctxt->docNr--;
        !          1909:     if (ctxt->docNr > 0)
        !          1910:         ctxt->doc = ctxt->docTab[ctxt->docNr - 1];
        !          1911:     else
        !          1912:         ctxt->doc = NULL;
        !          1913:     ret = ctxt->docTab[ctxt->docNr];
        !          1914:     ctxt->docTab[ctxt->docNr] = NULL;
        !          1915:     return (ret);
        !          1916: }
        !          1917: 
        !          1918: /**
        !          1919:  * xmlRelaxNGLoadExternalRef:
        !          1920:  * @ctxt: the parser context
        !          1921:  * @URL:  the normalized URL
        !          1922:  * @ns:  the inherited ns if any
        !          1923:  *
        !          1924:  * First lookup if the document is already loaded into the parser context,
        !          1925:  * check against recursion. If not found the resource is loaded and
        !          1926:  * the content is preprocessed before being returned back to the caller.
        !          1927:  *
        !          1928:  * Returns the xmlRelaxNGDocumentPtr or NULL in case of error
        !          1929:  */
        !          1930: static xmlRelaxNGDocumentPtr
        !          1931: xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
        !          1932:                           const xmlChar * URL, const xmlChar * ns)
        !          1933: {
        !          1934:     xmlRelaxNGDocumentPtr ret = NULL;
        !          1935:     xmlDocPtr doc;
        !          1936:     xmlNodePtr root;
        !          1937:     int i;
        !          1938: 
        !          1939:     /*
        !          1940:      * check against recursion in the stack
        !          1941:      */
        !          1942:     for (i = 0; i < ctxt->docNr; i++) {
        !          1943:         if (xmlStrEqual(ctxt->docTab[i]->href, URL)) {
        !          1944:             xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE,
        !          1945:                        "Detected an externalRef recursion for %s\n", URL,
        !          1946:                        NULL);
        !          1947:             return (NULL);
        !          1948:         }
        !          1949:     }
        !          1950: 
        !          1951:     /*
        !          1952:      * load the document
        !          1953:      */
        !          1954:     doc = xmlReadFile((const char *) URL,NULL,0);
        !          1955:     if (doc == NULL) {
        !          1956:         xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
        !          1957:                    "xmlRelaxNG: could not load %s\n", URL, NULL);
        !          1958:         return (NULL);
        !          1959:     }
        !          1960: 
        !          1961:     /*
        !          1962:      * Allocate the document structures and register it first.
        !          1963:      */
        !          1964:     ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
        !          1965:     if (ret == NULL) {
        !          1966:         xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,
        !          1967:                    "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);
        !          1968:         xmlFreeDoc(doc);
        !          1969:         return (NULL);
        !          1970:     }
        !          1971:     memset(ret, 0, sizeof(xmlRelaxNGDocument));
        !          1972:     ret->doc = doc;
        !          1973:     ret->href = xmlStrdup(URL);
        !          1974:     ret->next = ctxt->documents;
        !          1975:     ret->externalRef = 1;
        !          1976:     ctxt->documents = ret;
        !          1977: 
        !          1978:     /*
        !          1979:      * transmit the ns if needed
        !          1980:      */
        !          1981:     if (ns != NULL) {
        !          1982:         root = xmlDocGetRootElement(doc);
        !          1983:         if (root != NULL) {
        !          1984:             if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
        !          1985:                 xmlSetProp(root, BAD_CAST "ns", ns);
        !          1986:             }
        !          1987:         }
        !          1988:     }
        !          1989: 
        !          1990:     /*
        !          1991:      * push it on the stack and register it in the hash table
        !          1992:      */
        !          1993:     xmlRelaxNGDocumentPush(ctxt, ret);
        !          1994: 
        !          1995:     /*
        !          1996:      * Some preprocessing of the document content
        !          1997:      */
        !          1998:     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
        !          1999:     if (doc == NULL) {
        !          2000:         ctxt->doc = NULL;
        !          2001:         return (NULL);
        !          2002:     }
        !          2003: 
        !          2004:     xmlRelaxNGDocumentPop(ctxt);
        !          2005: 
        !          2006:     return (ret);
        !          2007: }
        !          2008: 
        !          2009: /************************************************************************
        !          2010:  *                                                                     *
        !          2011:  *                     Error functions                                 *
        !          2012:  *                                                                     *
        !          2013:  ************************************************************************/
        !          2014: 
        !          2015: #define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
        !          2016: #define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
        !          2017: #define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
        !          2018: #define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
        !          2019: #define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
        !          2020: 
        !          2021: static const char *
        !          2022: xmlRelaxNGDefName(xmlRelaxNGDefinePtr def)
        !          2023: {
        !          2024:     if (def == NULL)
        !          2025:         return ("none");
        !          2026:     switch (def->type) {
        !          2027:         case XML_RELAXNG_EMPTY:
        !          2028:             return ("empty");
        !          2029:         case XML_RELAXNG_NOT_ALLOWED:
        !          2030:             return ("notAllowed");
        !          2031:         case XML_RELAXNG_EXCEPT:
        !          2032:             return ("except");
        !          2033:         case XML_RELAXNG_TEXT:
        !          2034:             return ("text");
        !          2035:         case XML_RELAXNG_ELEMENT:
        !          2036:             return ("element");
        !          2037:         case XML_RELAXNG_DATATYPE:
        !          2038:             return ("datatype");
        !          2039:         case XML_RELAXNG_VALUE:
        !          2040:             return ("value");
        !          2041:         case XML_RELAXNG_LIST:
        !          2042:             return ("list");
        !          2043:         case XML_RELAXNG_ATTRIBUTE:
        !          2044:             return ("attribute");
        !          2045:         case XML_RELAXNG_DEF:
        !          2046:             return ("def");
        !          2047:         case XML_RELAXNG_REF:
        !          2048:             return ("ref");
        !          2049:         case XML_RELAXNG_EXTERNALREF:
        !          2050:             return ("externalRef");
        !          2051:         case XML_RELAXNG_PARENTREF:
        !          2052:             return ("parentRef");
        !          2053:         case XML_RELAXNG_OPTIONAL:
        !          2054:             return ("optional");
        !          2055:         case XML_RELAXNG_ZEROORMORE:
        !          2056:             return ("zeroOrMore");
        !          2057:         case XML_RELAXNG_ONEORMORE:
        !          2058:             return ("oneOrMore");
        !          2059:         case XML_RELAXNG_CHOICE:
        !          2060:             return ("choice");
        !          2061:         case XML_RELAXNG_GROUP:
        !          2062:             return ("group");
        !          2063:         case XML_RELAXNG_INTERLEAVE:
        !          2064:             return ("interleave");
        !          2065:         case XML_RELAXNG_START:
        !          2066:             return ("start");
        !          2067:         case XML_RELAXNG_NOOP:
        !          2068:             return ("noop");
        !          2069:         case XML_RELAXNG_PARAM:
        !          2070:             return ("param");
        !          2071:     }
        !          2072:     return ("unknown");
        !          2073: }
        !          2074: 
        !          2075: /**
        !          2076:  * xmlRelaxNGGetErrorString:
        !          2077:  * @err:  the error code
        !          2078:  * @arg1:  the first string argument
        !          2079:  * @arg2:  the second string argument
        !          2080:  *
        !          2081:  * computes a formatted error string for the given error code and args
        !          2082:  *
        !          2083:  * Returns the error string, it must be deallocated by the caller
        !          2084:  */
        !          2085: static xmlChar *
        !          2086: xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
        !          2087:                          const xmlChar * arg2)
        !          2088: {
        !          2089:     char msg[1000];
        !          2090: 
        !          2091:     if (arg1 == NULL)
        !          2092:         arg1 = BAD_CAST "";
        !          2093:     if (arg2 == NULL)
        !          2094:         arg2 = BAD_CAST "";
        !          2095: 
        !          2096:     msg[0] = 0;
        !          2097:     switch (err) {
        !          2098:         case XML_RELAXNG_OK:
        !          2099:             return (NULL);
        !          2100:         case XML_RELAXNG_ERR_MEMORY:
        !          2101:             return (xmlCharStrdup("out of memory\n"));
        !          2102:         case XML_RELAXNG_ERR_TYPE:
        !          2103:             snprintf(msg, 1000, "failed to validate type %s\n", arg1);
        !          2104:             break;
        !          2105:         case XML_RELAXNG_ERR_TYPEVAL:
        !          2106:             snprintf(msg, 1000, "Type %s doesn't allow value '%s'\n", arg1,
        !          2107:                      arg2);
        !          2108:             break;
        !          2109:         case XML_RELAXNG_ERR_DUPID:
        !          2110:             snprintf(msg, 1000, "ID %s redefined\n", arg1);
        !          2111:             break;
        !          2112:         case XML_RELAXNG_ERR_TYPECMP:
        !          2113:             snprintf(msg, 1000, "failed to compare type %s\n", arg1);
        !          2114:             break;
        !          2115:         case XML_RELAXNG_ERR_NOSTATE:
        !          2116:             return (xmlCharStrdup("Internal error: no state\n"));
        !          2117:         case XML_RELAXNG_ERR_NODEFINE:
        !          2118:             return (xmlCharStrdup("Internal error: no define\n"));
        !          2119:         case XML_RELAXNG_ERR_INTERNAL:
        !          2120:             snprintf(msg, 1000, "Internal error: %s\n", arg1);
        !          2121:             break;
        !          2122:         case XML_RELAXNG_ERR_LISTEXTRA:
        !          2123:             snprintf(msg, 1000, "Extra data in list: %s\n", arg1);
        !          2124:             break;
        !          2125:         case XML_RELAXNG_ERR_INTERNODATA:
        !          2126:             return (xmlCharStrdup
        !          2127:                     ("Internal: interleave block has no data\n"));
        !          2128:         case XML_RELAXNG_ERR_INTERSEQ:
        !          2129:             return (xmlCharStrdup("Invalid sequence in interleave\n"));
        !          2130:         case XML_RELAXNG_ERR_INTEREXTRA:
        !          2131:             snprintf(msg, 1000, "Extra element %s in interleave\n", arg1);
        !          2132:             break;
        !          2133:         case XML_RELAXNG_ERR_ELEMNAME:
        !          2134:             snprintf(msg, 1000, "Expecting element %s, got %s\n", arg1,
        !          2135:                      arg2);
        !          2136:             break;
        !          2137:         case XML_RELAXNG_ERR_ELEMNONS:
        !          2138:             snprintf(msg, 1000, "Expecting a namespace for element %s\n",
        !          2139:                      arg1);
        !          2140:             break;
        !          2141:         case XML_RELAXNG_ERR_ELEMWRONGNS:
        !          2142:             snprintf(msg, 1000,
        !          2143:                      "Element %s has wrong namespace: expecting %s\n", arg1,
        !          2144:                      arg2);
        !          2145:             break;
        !          2146:         case XML_RELAXNG_ERR_ELEMWRONG:
        !          2147:             snprintf(msg, 1000, "Did not expect element %s there\n", arg1);
        !          2148:             break;
        !          2149:         case XML_RELAXNG_ERR_TEXTWRONG:
        !          2150:             snprintf(msg, 1000,
        !          2151:                      "Did not expect text in element %s content\n", arg1);
        !          2152:             break;
        !          2153:         case XML_RELAXNG_ERR_ELEMEXTRANS:
        !          2154:             snprintf(msg, 1000, "Expecting no namespace for element %s\n",
        !          2155:                      arg1);
        !          2156:             break;
        !          2157:         case XML_RELAXNG_ERR_ELEMNOTEMPTY:
        !          2158:             snprintf(msg, 1000, "Expecting element %s to be empty\n", arg1);
        !          2159:             break;
        !          2160:         case XML_RELAXNG_ERR_NOELEM:
        !          2161:             snprintf(msg, 1000, "Expecting an element %s, got nothing\n",
        !          2162:                      arg1);
        !          2163:             break;
        !          2164:         case XML_RELAXNG_ERR_NOTELEM:
        !          2165:             return (xmlCharStrdup("Expecting an element got text\n"));
        !          2166:         case XML_RELAXNG_ERR_ATTRVALID:
        !          2167:             snprintf(msg, 1000, "Element %s failed to validate attributes\n",
        !          2168:                      arg1);
        !          2169:             break;
        !          2170:         case XML_RELAXNG_ERR_CONTENTVALID:
        !          2171:             snprintf(msg, 1000, "Element %s failed to validate content\n",
        !          2172:                      arg1);
        !          2173:             break;
        !          2174:         case XML_RELAXNG_ERR_EXTRACONTENT:
        !          2175:             snprintf(msg, 1000, "Element %s has extra content: %s\n",
        !          2176:                      arg1, arg2);
        !          2177:             break;
        !          2178:         case XML_RELAXNG_ERR_INVALIDATTR:
        !          2179:             snprintf(msg, 1000, "Invalid attribute %s for element %s\n",
        !          2180:                      arg1, arg2);
        !          2181:             break;
        !          2182:         case XML_RELAXNG_ERR_LACKDATA:
        !          2183:             snprintf(msg, 1000, "Datatype element %s contains no data\n",
        !          2184:                      arg1);
        !          2185:             break;
        !          2186:         case XML_RELAXNG_ERR_DATAELEM:
        !          2187:             snprintf(msg, 1000, "Datatype element %s has child elements\n",
        !          2188:                      arg1);
        !          2189:             break;
        !          2190:         case XML_RELAXNG_ERR_VALELEM:
        !          2191:             snprintf(msg, 1000, "Value element %s has child elements\n",
        !          2192:                      arg1);
        !          2193:             break;
        !          2194:         case XML_RELAXNG_ERR_LISTELEM:
        !          2195:             snprintf(msg, 1000, "List element %s has child elements\n",
        !          2196:                      arg1);
        !          2197:             break;
        !          2198:         case XML_RELAXNG_ERR_DATATYPE:
        !          2199:             snprintf(msg, 1000, "Error validating datatype %s\n", arg1);
        !          2200:             break;
        !          2201:         case XML_RELAXNG_ERR_VALUE:
        !          2202:             snprintf(msg, 1000, "Error validating value %s\n", arg1);
        !          2203:             break;
        !          2204:         case XML_RELAXNG_ERR_LIST:
        !          2205:             return (xmlCharStrdup("Error validating list\n"));
        !          2206:         case XML_RELAXNG_ERR_NOGRAMMAR:
        !          2207:             return (xmlCharStrdup("No top grammar defined\n"));
        !          2208:         case XML_RELAXNG_ERR_EXTRADATA:
        !          2209:             return (xmlCharStrdup("Extra data in the document\n"));
        !          2210:         default:
        !          2211:             return (xmlCharStrdup("Unknown error !\n"));
        !          2212:     }
        !          2213:     if (msg[0] == 0) {
        !          2214:         snprintf(msg, 1000, "Unknown error code %d\n", err);
        !          2215:     }
        !          2216:     msg[1000 - 1] = 0;
        !          2217:     return (xmlStrdup((xmlChar *) msg));
        !          2218: }
        !          2219: 
        !          2220: /**
        !          2221:  * xmlRelaxNGShowValidError:
        !          2222:  * @ctxt:  the validation context
        !          2223:  * @err:  the error number
        !          2224:  * @node:  the node
        !          2225:  * @child:  the node child generating the problem.
        !          2226:  * @arg1:  the first argument
        !          2227:  * @arg2:  the second argument
        !          2228:  *
        !          2229:  * Show a validation error.
        !          2230:  */
        !          2231: static void
        !          2232: xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt,
        !          2233:                          xmlRelaxNGValidErr err, xmlNodePtr node,
        !          2234:                          xmlNodePtr child, const xmlChar * arg1,
        !          2235:                          const xmlChar * arg2)
        !          2236: {
        !          2237:     xmlChar *msg;
        !          2238: 
        !          2239:     if (ctxt->flags & FLAGS_NOERROR)
        !          2240:         return;
        !          2241: 
        !          2242: #ifdef DEBUG_ERROR
        !          2243:     xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err);
        !          2244: #endif
        !          2245:     msg = xmlRelaxNGGetErrorString(err, arg1, arg2);
        !          2246:     if (msg == NULL)
        !          2247:         return;
        !          2248: 
        !          2249:     if (ctxt->errNo == XML_RELAXNG_OK)
        !          2250:         ctxt->errNo = err;
        !          2251:     xmlRngVErr(ctxt, (child == NULL ? node : child), err,
        !          2252:                (const char *) msg, arg1, arg2);
        !          2253:     xmlFree(msg);
        !          2254: }
        !          2255: 
        !          2256: /**
        !          2257:  * xmlRelaxNGPopErrors:
        !          2258:  * @ctxt:  the validation context
        !          2259:  * @level:  the error level in the stack
        !          2260:  *
        !          2261:  * pop and discard all errors until the given level is reached
        !          2262:  */
        !          2263: static void
        !          2264: xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level)
        !          2265: {
        !          2266:     int i;
        !          2267:     xmlRelaxNGValidErrorPtr err;
        !          2268: 
        !          2269: #ifdef DEBUG_ERROR
        !          2270:     xmlGenericError(xmlGenericErrorContext,
        !          2271:                     "Pop errors till level %d\n", level);
        !          2272: #endif
        !          2273:     for (i = level; i < ctxt->errNr; i++) {
        !          2274:         err = &ctxt->errTab[i];
        !          2275:         if (err->flags & ERROR_IS_DUP) {
        !          2276:             if (err->arg1 != NULL)
        !          2277:                 xmlFree((xmlChar *) err->arg1);
        !          2278:             err->arg1 = NULL;
        !          2279:             if (err->arg2 != NULL)
        !          2280:                 xmlFree((xmlChar *) err->arg2);
        !          2281:             err->arg2 = NULL;
        !          2282:             err->flags = 0;
        !          2283:         }
        !          2284:     }
        !          2285:     ctxt->errNr = level;
        !          2286:     if (ctxt->errNr <= 0)
        !          2287:         ctxt->err = NULL;
        !          2288: }
        !          2289: 
        !          2290: /**
        !          2291:  * xmlRelaxNGDumpValidError:
        !          2292:  * @ctxt:  the validation context
        !          2293:  *
        !          2294:  * Show all validation error over a given index.
        !          2295:  */
        !          2296: static void
        !          2297: xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt)
        !          2298: {
        !          2299:     int i, j, k;
        !          2300:     xmlRelaxNGValidErrorPtr err, dup;
        !          2301: 
        !          2302: #ifdef DEBUG_ERROR
        !          2303:     xmlGenericError(xmlGenericErrorContext,
        !          2304:                     "Dumping error stack %d errors\n", ctxt->errNr);
        !          2305: #endif
        !          2306:     for (i = 0, k = 0; i < ctxt->errNr; i++) {
        !          2307:         err = &ctxt->errTab[i];
        !          2308:         if (k < MAX_ERROR) {
        !          2309:             for (j = 0; j < i; j++) {
        !          2310:                 dup = &ctxt->errTab[j];
        !          2311:                 if ((err->err == dup->err) && (err->node == dup->node) &&
        !          2312:                     (xmlStrEqual(err->arg1, dup->arg1)) &&
        !          2313:                     (xmlStrEqual(err->arg2, dup->arg2))) {
        !          2314:                     goto skip;
        !          2315:                 }
        !          2316:             }
        !          2317:             xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,
        !          2318:                                      err->arg1, err->arg2);
        !          2319:             k++;
        !          2320:         }
        !          2321:       skip:
        !          2322:         if (err->flags & ERROR_IS_DUP) {
        !          2323:             if (err->arg1 != NULL)
        !          2324:                 xmlFree((xmlChar *) err->arg1);
        !          2325:             err->arg1 = NULL;
        !          2326:             if (err->arg2 != NULL)
        !          2327:                 xmlFree((xmlChar *) err->arg2);
        !          2328:             err->arg2 = NULL;
        !          2329:             err->flags = 0;
        !          2330:         }
        !          2331:     }
        !          2332:     ctxt->errNr = 0;
        !          2333: }
        !          2334: 
        !          2335: /**
        !          2336:  * xmlRelaxNGAddValidError:
        !          2337:  * @ctxt:  the validation context
        !          2338:  * @err:  the error number
        !          2339:  * @arg1:  the first argument
        !          2340:  * @arg2:  the second argument
        !          2341:  * @dup:  need to dup the args
        !          2342:  *
        !          2343:  * Register a validation error, either generating it if it's sure
        !          2344:  * or stacking it for later handling if unsure.
        !          2345:  */
        !          2346: static void
        !          2347: xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt,
        !          2348:                         xmlRelaxNGValidErr err, const xmlChar * arg1,
        !          2349:                         const xmlChar * arg2, int dup)
        !          2350: {
        !          2351:     if (ctxt == NULL)
        !          2352:         return;
        !          2353:     if (ctxt->flags & FLAGS_NOERROR)
        !          2354:         return;
        !          2355: 
        !          2356: #ifdef DEBUG_ERROR
        !          2357:     xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err);
        !          2358: #endif
        !          2359:     /*
        !          2360:      * generate the error directly
        !          2361:      */
        !          2362:     if (((ctxt->flags & FLAGS_IGNORABLE) == 0) ||
        !          2363:         (ctxt->flags & FLAGS_NEGATIVE)) {
        !          2364:         xmlNodePtr node, seq;
        !          2365: 
        !          2366:         /*
        !          2367:          * Flush first any stacked error which might be the
        !          2368:          * real cause of the problem.
        !          2369:          */
        !          2370:         if (ctxt->errNr != 0)
        !          2371:             xmlRelaxNGDumpValidError(ctxt);
        !          2372:         if (ctxt->state != NULL) {
        !          2373:             node = ctxt->state->node;
        !          2374:             seq = ctxt->state->seq;
        !          2375:         } else {
        !          2376:             node = seq = NULL;
        !          2377:         }
        !          2378:         if ((node == NULL) && (seq == NULL)) {
        !          2379:             node = ctxt->pnode;
        !          2380:         }
        !          2381:         xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2);
        !          2382:     }
        !          2383:     /*
        !          2384:      * Stack the error for later processing if needed
        !          2385:      */
        !          2386:     else {
        !          2387:         xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);
        !          2388:     }
        !          2389: }
        !          2390: 
        !          2391: 
        !          2392: /************************************************************************
        !          2393:  *                                                                     *
        !          2394:  *                     Type library hooks                              *
        !          2395:  *                                                                     *
        !          2396:  ************************************************************************/
        !          2397: static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt,
        !          2398:                                     const xmlChar * str);
        !          2399: 
        !          2400: /**
        !          2401:  * xmlRelaxNGSchemaTypeHave:
        !          2402:  * @data:  data needed for the library
        !          2403:  * @type:  the type name
        !          2404:  *
        !          2405:  * Check if the given type is provided by
        !          2406:  * the W3C XMLSchema Datatype library.
        !          2407:  *
        !          2408:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !          2409:  */
        !          2410: static int
        !          2411: xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar * type)
        !          2412: {
        !          2413:     xmlSchemaTypePtr typ;
        !          2414: 
        !          2415:     if (type == NULL)
        !          2416:         return (-1);
        !          2417:     typ = xmlSchemaGetPredefinedType(type,
        !          2418:                                      BAD_CAST
        !          2419:                                      "http://www.w3.org/2001/XMLSchema");
        !          2420:     if (typ == NULL)
        !          2421:         return (0);
        !          2422:     return (1);
        !          2423: }
        !          2424: 
        !          2425: /**
        !          2426:  * xmlRelaxNGSchemaTypeCheck:
        !          2427:  * @data:  data needed for the library
        !          2428:  * @type:  the type name
        !          2429:  * @value:  the value to check
        !          2430:  * @node:  the node
        !          2431:  *
        !          2432:  * Check if the given type and value are validated by
        !          2433:  * the W3C XMLSchema Datatype library.
        !          2434:  *
        !          2435:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !          2436:  */
        !          2437: static int
        !          2438: xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
        !          2439:                           const xmlChar * type,
        !          2440:                           const xmlChar * value,
        !          2441:                           void **result, xmlNodePtr node)
        !          2442: {
        !          2443:     xmlSchemaTypePtr typ;
        !          2444:     int ret;
        !          2445: 
        !          2446:     if ((type == NULL) || (value == NULL))
        !          2447:         return (-1);
        !          2448:     typ = xmlSchemaGetPredefinedType(type,
        !          2449:                                      BAD_CAST
        !          2450:                                      "http://www.w3.org/2001/XMLSchema");
        !          2451:     if (typ == NULL)
        !          2452:         return (-1);
        !          2453:     ret = xmlSchemaValPredefTypeNode(typ, value,
        !          2454:                                      (xmlSchemaValPtr *) result, node);
        !          2455:     if (ret == 2)               /* special ID error code */
        !          2456:         return (2);
        !          2457:     if (ret == 0)
        !          2458:         return (1);
        !          2459:     if (ret > 0)
        !          2460:         return (0);
        !          2461:     return (-1);
        !          2462: }
        !          2463: 
        !          2464: /**
        !          2465:  * xmlRelaxNGSchemaFacetCheck:
        !          2466:  * @data:  data needed for the library
        !          2467:  * @type:  the type name
        !          2468:  * @facet:  the facet name
        !          2469:  * @val:  the facet value
        !          2470:  * @strval:  the string value
        !          2471:  * @value:  the value to check
        !          2472:  *
        !          2473:  * Function provided by a type library to check a value facet
        !          2474:  *
        !          2475:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !          2476:  */
        !          2477: static int
        !          2478: xmlRelaxNGSchemaFacetCheck(void *data ATTRIBUTE_UNUSED,
        !          2479:                            const xmlChar * type, const xmlChar * facetname,
        !          2480:                            const xmlChar * val, const xmlChar * strval,
        !          2481:                            void *value)
        !          2482: {
        !          2483:     xmlSchemaFacetPtr facet;
        !          2484:     xmlSchemaTypePtr typ;
        !          2485:     int ret;
        !          2486: 
        !          2487:     if ((type == NULL) || (strval == NULL))
        !          2488:         return (-1);
        !          2489:     typ = xmlSchemaGetPredefinedType(type,
        !          2490:                                      BAD_CAST
        !          2491:                                      "http://www.w3.org/2001/XMLSchema");
        !          2492:     if (typ == NULL)
        !          2493:         return (-1);
        !          2494: 
        !          2495:     facet = xmlSchemaNewFacet();
        !          2496:     if (facet == NULL)
        !          2497:         return (-1);
        !          2498: 
        !          2499:     if (xmlStrEqual(facetname, BAD_CAST "minInclusive")) {
        !          2500:         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
        !          2501:     } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive")) {
        !          2502:         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
        !          2503:     } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive")) {
        !          2504:         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
        !          2505:     } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive")) {
        !          2506:         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
        !          2507:     } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits")) {
        !          2508:         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
        !          2509:     } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits")) {
        !          2510:         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
        !          2511:     } else if (xmlStrEqual(facetname, BAD_CAST "pattern")) {
        !          2512:         facet->type = XML_SCHEMA_FACET_PATTERN;
        !          2513:     } else if (xmlStrEqual(facetname, BAD_CAST "enumeration")) {
        !          2514:         facet->type = XML_SCHEMA_FACET_ENUMERATION;
        !          2515:     } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace")) {
        !          2516:         facet->type = XML_SCHEMA_FACET_WHITESPACE;
        !          2517:     } else if (xmlStrEqual(facetname, BAD_CAST "length")) {
        !          2518:         facet->type = XML_SCHEMA_FACET_LENGTH;
        !          2519:     } else if (xmlStrEqual(facetname, BAD_CAST "maxLength")) {
        !          2520:         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
        !          2521:     } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) {
        !          2522:         facet->type = XML_SCHEMA_FACET_MINLENGTH;
        !          2523:     } else {
        !          2524:         xmlSchemaFreeFacet(facet);
        !          2525:         return (-1);
        !          2526:     }
        !          2527:     facet->value = val;
        !          2528:     ret = xmlSchemaCheckFacet(facet, typ, NULL, type);
        !          2529:     if (ret != 0) {
        !          2530:         xmlSchemaFreeFacet(facet);
        !          2531:         return (-1);
        !          2532:     }
        !          2533:     ret = xmlSchemaValidateFacet(typ, facet, strval, value);
        !          2534:     xmlSchemaFreeFacet(facet);
        !          2535:     if (ret != 0)
        !          2536:         return (-1);
        !          2537:     return (0);
        !          2538: }
        !          2539: 
        !          2540: /**
        !          2541:  * xmlRelaxNGSchemaFreeValue:
        !          2542:  * @data:  data needed for the library
        !          2543:  * @value:  the value to free
        !          2544:  *
        !          2545:  * Function provided by a type library to free a Schemas value
        !          2546:  *
        !          2547:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !          2548:  */
        !          2549: static void
        !          2550: xmlRelaxNGSchemaFreeValue(void *data ATTRIBUTE_UNUSED, void *value)
        !          2551: {
        !          2552:     xmlSchemaFreeValue(value);
        !          2553: }
        !          2554: 
        !          2555: /**
        !          2556:  * xmlRelaxNGSchemaTypeCompare:
        !          2557:  * @data:  data needed for the library
        !          2558:  * @type:  the type name
        !          2559:  * @value1:  the first value
        !          2560:  * @value2:  the second value
        !          2561:  *
        !          2562:  * Compare two values for equality accordingly a type from the W3C XMLSchema
        !          2563:  * Datatype library.
        !          2564:  *
        !          2565:  * Returns 1 if equal, 0 if no and -1 in case of error.
        !          2566:  */
        !          2567: static int
        !          2568: xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
        !          2569:                             const xmlChar * type,
        !          2570:                             const xmlChar * value1,
        !          2571:                             xmlNodePtr ctxt1,
        !          2572:                             void *comp1,
        !          2573:                             const xmlChar * value2, xmlNodePtr ctxt2)
        !          2574: {
        !          2575:     int ret;
        !          2576:     xmlSchemaTypePtr typ;
        !          2577:     xmlSchemaValPtr res1 = NULL, res2 = NULL;
        !          2578: 
        !          2579:     if ((type == NULL) || (value1 == NULL) || (value2 == NULL))
        !          2580:         return (-1);
        !          2581:     typ = xmlSchemaGetPredefinedType(type,
        !          2582:                                      BAD_CAST
        !          2583:                                      "http://www.w3.org/2001/XMLSchema");
        !          2584:     if (typ == NULL)
        !          2585:         return (-1);
        !          2586:     if (comp1 == NULL) {
        !          2587:         ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1);
        !          2588:         if (ret != 0)
        !          2589:             return (-1);
        !          2590:         if (res1 == NULL)
        !          2591:             return (-1);
        !          2592:     } else {
        !          2593:         res1 = (xmlSchemaValPtr) comp1;
        !          2594:     }
        !          2595:     ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2);
        !          2596:     if (ret != 0) {
        !          2597:        if ((comp1 == NULL) && (res1 != NULL))
        !          2598:            xmlSchemaFreeValue(res1);
        !          2599:         return (-1);
        !          2600:     }
        !          2601:     if (res1 == NULL) {
        !          2602:         return (-1);
        !          2603:     }
        !          2604:     ret = xmlSchemaCompareValues(res1, res2);
        !          2605:     if (res1 != (xmlSchemaValPtr) comp1)
        !          2606:         xmlSchemaFreeValue(res1);
        !          2607:     xmlSchemaFreeValue(res2);
        !          2608:     if (ret == -2)
        !          2609:         return (-1);
        !          2610:     if (ret == 0)
        !          2611:         return (1);
        !          2612:     return (0);
        !          2613: }
        !          2614: 
        !          2615: /**
        !          2616:  * xmlRelaxNGDefaultTypeHave:
        !          2617:  * @data:  data needed for the library
        !          2618:  * @type:  the type name
        !          2619:  *
        !          2620:  * Check if the given type is provided by
        !          2621:  * the default datatype library.
        !          2622:  *
        !          2623:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !          2624:  */
        !          2625: static int
        !          2626: xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED,
        !          2627:                           const xmlChar * type)
        !          2628: {
        !          2629:     if (type == NULL)
        !          2630:         return (-1);
        !          2631:     if (xmlStrEqual(type, BAD_CAST "string"))
        !          2632:         return (1);
        !          2633:     if (xmlStrEqual(type, BAD_CAST "token"))
        !          2634:         return (1);
        !          2635:     return (0);
        !          2636: }
        !          2637: 
        !          2638: /**
        !          2639:  * xmlRelaxNGDefaultTypeCheck:
        !          2640:  * @data:  data needed for the library
        !          2641:  * @type:  the type name
        !          2642:  * @value:  the value to check
        !          2643:  * @node:  the node
        !          2644:  *
        !          2645:  * Check if the given type and value are validated by
        !          2646:  * the default datatype library.
        !          2647:  *
        !          2648:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !          2649:  */
        !          2650: static int
        !          2651: xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
        !          2652:                            const xmlChar * type ATTRIBUTE_UNUSED,
        !          2653:                            const xmlChar * value ATTRIBUTE_UNUSED,
        !          2654:                            void **result ATTRIBUTE_UNUSED,
        !          2655:                            xmlNodePtr node ATTRIBUTE_UNUSED)
        !          2656: {
        !          2657:     if (value == NULL)
        !          2658:         return (-1);
        !          2659:     if (xmlStrEqual(type, BAD_CAST "string"))
        !          2660:         return (1);
        !          2661:     if (xmlStrEqual(type, BAD_CAST "token")) {
        !          2662:         return (1);
        !          2663:     }
        !          2664: 
        !          2665:     return (0);
        !          2666: }
        !          2667: 
        !          2668: /**
        !          2669:  * xmlRelaxNGDefaultTypeCompare:
        !          2670:  * @data:  data needed for the library
        !          2671:  * @type:  the type name
        !          2672:  * @value1:  the first value
        !          2673:  * @value2:  the second value
        !          2674:  *
        !          2675:  * Compare two values accordingly a type from the default
        !          2676:  * datatype library.
        !          2677:  *
        !          2678:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !          2679:  */
        !          2680: static int
        !          2681: xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
        !          2682:                              const xmlChar * type,
        !          2683:                              const xmlChar * value1,
        !          2684:                              xmlNodePtr ctxt1 ATTRIBUTE_UNUSED,
        !          2685:                              void *comp1 ATTRIBUTE_UNUSED,
        !          2686:                              const xmlChar * value2,
        !          2687:                              xmlNodePtr ctxt2 ATTRIBUTE_UNUSED)
        !          2688: {
        !          2689:     int ret = -1;
        !          2690: 
        !          2691:     if (xmlStrEqual(type, BAD_CAST "string")) {
        !          2692:         ret = xmlStrEqual(value1, value2);
        !          2693:     } else if (xmlStrEqual(type, BAD_CAST "token")) {
        !          2694:         if (!xmlStrEqual(value1, value2)) {
        !          2695:             xmlChar *nval, *nvalue;
        !          2696: 
        !          2697:             /*
        !          2698:              * TODO: trivial optimizations are possible by
        !          2699:              * computing at compile-time
        !          2700:              */
        !          2701:             nval = xmlRelaxNGNormalize(NULL, value1);
        !          2702:             nvalue = xmlRelaxNGNormalize(NULL, value2);
        !          2703: 
        !          2704:             if ((nval == NULL) || (nvalue == NULL))
        !          2705:                 ret = -1;
        !          2706:             else if (xmlStrEqual(nval, nvalue))
        !          2707:                 ret = 1;
        !          2708:             else
        !          2709:                 ret = 0;
        !          2710:             if (nval != NULL)
        !          2711:                 xmlFree(nval);
        !          2712:             if (nvalue != NULL)
        !          2713:                 xmlFree(nvalue);
        !          2714:         } else
        !          2715:             ret = 1;
        !          2716:     }
        !          2717:     return (ret);
        !          2718: }
        !          2719: 
        !          2720: static int xmlRelaxNGTypeInitialized = 0;
        !          2721: static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
        !          2722: 
        !          2723: /**
        !          2724:  * xmlRelaxNGFreeTypeLibrary:
        !          2725:  * @lib:  the type library structure
        !          2726:  * @namespace:  the URI bound to the library
        !          2727:  *
        !          2728:  * Free the structure associated to the type library
        !          2729:  */
        !          2730: static void
        !          2731: xmlRelaxNGFreeTypeLibrary(xmlRelaxNGTypeLibraryPtr lib,
        !          2732:                           const xmlChar * namespace ATTRIBUTE_UNUSED)
        !          2733: {
        !          2734:     if (lib == NULL)
        !          2735:         return;
        !          2736:     if (lib->namespace != NULL)
        !          2737:         xmlFree((xmlChar *) lib->namespace);
        !          2738:     xmlFree(lib);
        !          2739: }
        !          2740: 
        !          2741: /**
        !          2742:  * xmlRelaxNGRegisterTypeLibrary:
        !          2743:  * @namespace:  the URI bound to the library
        !          2744:  * @data:  data associated to the library
        !          2745:  * @have:  the provide function
        !          2746:  * @check:  the checking function
        !          2747:  * @comp:  the comparison function
        !          2748:  *
        !          2749:  * Register a new type library
        !          2750:  *
        !          2751:  * Returns 0 in case of success and -1 in case of error.
        !          2752:  */
        !          2753: static int
        !          2754: xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,
        !          2755:                               xmlRelaxNGTypeHave have,
        !          2756:                               xmlRelaxNGTypeCheck check,
        !          2757:                               xmlRelaxNGTypeCompare comp,
        !          2758:                               xmlRelaxNGFacetCheck facet,
        !          2759:                               xmlRelaxNGTypeFree freef)
        !          2760: {
        !          2761:     xmlRelaxNGTypeLibraryPtr lib;
        !          2762:     int ret;
        !          2763: 
        !          2764:     if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
        !          2765:         (check == NULL) || (comp == NULL))
        !          2766:         return (-1);
        !          2767:     if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
        !          2768:         xmlGenericError(xmlGenericErrorContext,
        !          2769:                         "Relax-NG types library '%s' already registered\n",
        !          2770:                         namespace);
        !          2771:         return (-1);
        !          2772:     }
        !          2773:     lib =
        !          2774:         (xmlRelaxNGTypeLibraryPtr)
        !          2775:         xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
        !          2776:     if (lib == NULL) {
        !          2777:         xmlRngVErrMemory(NULL, "adding types library\n");
        !          2778:         return (-1);
        !          2779:     }
        !          2780:     memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
        !          2781:     lib->namespace = xmlStrdup(namespace);
        !          2782:     lib->data = data;
        !          2783:     lib->have = have;
        !          2784:     lib->comp = comp;
        !          2785:     lib->check = check;
        !          2786:     lib->facet = facet;
        !          2787:     lib->freef = freef;
        !          2788:     ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
        !          2789:     if (ret < 0) {
        !          2790:         xmlGenericError(xmlGenericErrorContext,
        !          2791:                         "Relax-NG types library failed to register '%s'\n",
        !          2792:                         namespace);
        !          2793:         xmlRelaxNGFreeTypeLibrary(lib, namespace);
        !          2794:         return (-1);
        !          2795:     }
        !          2796:     return (0);
        !          2797: }
        !          2798: 
        !          2799: /**
        !          2800:  * xmlRelaxNGInitTypes:
        !          2801:  *
        !          2802:  * Initilize the default type libraries.
        !          2803:  *
        !          2804:  * Returns 0 in case of success and -1 in case of error.
        !          2805:  */
        !          2806: int
        !          2807: xmlRelaxNGInitTypes(void)
        !          2808: {
        !          2809:     if (xmlRelaxNGTypeInitialized != 0)
        !          2810:         return (0);
        !          2811:     xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
        !          2812:     if (xmlRelaxNGRegisteredTypes == NULL) {
        !          2813:         xmlGenericError(xmlGenericErrorContext,
        !          2814:                         "Failed to allocate sh table for Relax-NG types\n");
        !          2815:         return (-1);
        !          2816:     }
        !          2817:     xmlRelaxNGRegisterTypeLibrary(BAD_CAST
        !          2818:                                   "http://www.w3.org/2001/XMLSchema-datatypes",
        !          2819:                                   NULL, xmlRelaxNGSchemaTypeHave,
        !          2820:                                   xmlRelaxNGSchemaTypeCheck,
        !          2821:                                   xmlRelaxNGSchemaTypeCompare,
        !          2822:                                   xmlRelaxNGSchemaFacetCheck,
        !          2823:                                   xmlRelaxNGSchemaFreeValue);
        !          2824:     xmlRelaxNGRegisterTypeLibrary(xmlRelaxNGNs, NULL,
        !          2825:                                   xmlRelaxNGDefaultTypeHave,
        !          2826:                                   xmlRelaxNGDefaultTypeCheck,
        !          2827:                                   xmlRelaxNGDefaultTypeCompare, NULL,
        !          2828:                                   NULL);
        !          2829:     xmlRelaxNGTypeInitialized = 1;
        !          2830:     return (0);
        !          2831: }
        !          2832: 
        !          2833: /**
        !          2834:  * xmlRelaxNGCleanupTypes:
        !          2835:  *
        !          2836:  * Cleanup the default Schemas type library associated to RelaxNG
        !          2837:  */
        !          2838: void
        !          2839: xmlRelaxNGCleanupTypes(void)
        !          2840: {
        !          2841:     xmlSchemaCleanupTypes();
        !          2842:     if (xmlRelaxNGTypeInitialized == 0)
        !          2843:         return;
        !          2844:     xmlHashFree(xmlRelaxNGRegisteredTypes, (xmlHashDeallocator)
        !          2845:                 xmlRelaxNGFreeTypeLibrary);
        !          2846:     xmlRelaxNGTypeInitialized = 0;
        !          2847: }
        !          2848: 
        !          2849: /************************************************************************
        !          2850:  *                                                                     *
        !          2851:  *             Compiling element content into regexp                   *
        !          2852:  *                                                                     *
        !          2853:  * Sometime the element content can be compiled into a pure regexp,    *
        !          2854:  * This allows a faster execution and streamability at that level      *
        !          2855:  *                                                                     *
        !          2856:  ************************************************************************/
        !          2857: 
        !          2858: /* from automata.c but not exported */
        !          2859: void xmlAutomataSetFlags(xmlAutomataPtr am, int flags);
        !          2860: 
        !          2861: 
        !          2862: static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,
        !          2863:                                 xmlRelaxNGDefinePtr def);
        !          2864: 
        !          2865: /**
        !          2866:  * xmlRelaxNGIsCompileable:
        !          2867:  * @define:  the definition to check
        !          2868:  *
        !          2869:  * Check if a definition is nullable.
        !          2870:  *
        !          2871:  * Returns 1 if yes, 0 if no and -1 in case of error
        !          2872:  */
        !          2873: static int
        !          2874: xmlRelaxNGIsCompileable(xmlRelaxNGDefinePtr def)
        !          2875: {
        !          2876:     int ret = -1;
        !          2877: 
        !          2878:     if (def == NULL) {
        !          2879:         return (-1);
        !          2880:     }
        !          2881:     if ((def->type != XML_RELAXNG_ELEMENT) &&
        !          2882:         (def->dflags & IS_COMPILABLE))
        !          2883:         return (1);
        !          2884:     if ((def->type != XML_RELAXNG_ELEMENT) &&
        !          2885:         (def->dflags & IS_NOT_COMPILABLE))
        !          2886:         return (0);
        !          2887:     switch (def->type) {
        !          2888:         case XML_RELAXNG_NOOP:
        !          2889:             ret = xmlRelaxNGIsCompileable(def->content);
        !          2890:             break;
        !          2891:         case XML_RELAXNG_TEXT:
        !          2892:         case XML_RELAXNG_EMPTY:
        !          2893:             ret = 1;
        !          2894:             break;
        !          2895:         case XML_RELAXNG_ELEMENT:
        !          2896:             /*
        !          2897:              * Check if the element content is compileable
        !          2898:              */
        !          2899:             if (((def->dflags & IS_NOT_COMPILABLE) == 0) &&
        !          2900:                 ((def->dflags & IS_COMPILABLE) == 0)) {
        !          2901:                 xmlRelaxNGDefinePtr list;
        !          2902: 
        !          2903:                 list = def->content;
        !          2904:                 while (list != NULL) {
        !          2905:                     ret = xmlRelaxNGIsCompileable(list);
        !          2906:                     if (ret != 1)
        !          2907:                         break;
        !          2908:                     list = list->next;
        !          2909:                 }
        !          2910:                /*
        !          2911:                 * Because the routine is recursive, we must guard against
        !          2912:                 * discovering both COMPILABLE and NOT_COMPILABLE
        !          2913:                 */
        !          2914:                 if (ret == 0) {
        !          2915:                    def->dflags &= ~IS_COMPILABLE;
        !          2916:                     def->dflags |= IS_NOT_COMPILABLE;
        !          2917:                }
        !          2918:                 if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE))
        !          2919:                     def->dflags |= IS_COMPILABLE;
        !          2920: #ifdef DEBUG_COMPILE
        !          2921:                 if (ret == 1) {
        !          2922:                     xmlGenericError(xmlGenericErrorContext,
        !          2923:                                     "element content for %s is compilable\n",
        !          2924:                                     def->name);
        !          2925:                 } else if (ret == 0) {
        !          2926:                     xmlGenericError(xmlGenericErrorContext,
        !          2927:                                     "element content for %s is not compilable\n",
        !          2928:                                     def->name);
        !          2929:                 } else {
        !          2930:                     xmlGenericError(xmlGenericErrorContext,
        !          2931:                                     "Problem in RelaxNGIsCompileable for element %s\n",
        !          2932:                                     def->name);
        !          2933:                 }
        !          2934: #endif
        !          2935:             }
        !          2936:             /*
        !          2937:              * All elements return a compileable status unless they
        !          2938:              * are generic like anyName
        !          2939:              */
        !          2940:             if ((def->nameClass != NULL) || (def->name == NULL))
        !          2941:                 ret = 0;
        !          2942:             else
        !          2943:                 ret = 1;
        !          2944:             return (ret);
        !          2945:         case XML_RELAXNG_REF:
        !          2946:         case XML_RELAXNG_EXTERNALREF:
        !          2947:         case XML_RELAXNG_PARENTREF:
        !          2948:             if (def->depth == -20) {
        !          2949:                 return (1);
        !          2950:             } else {
        !          2951:                 xmlRelaxNGDefinePtr list;
        !          2952: 
        !          2953:                 def->depth = -20;
        !          2954:                 list = def->content;
        !          2955:                 while (list != NULL) {
        !          2956:                     ret = xmlRelaxNGIsCompileable(list);
        !          2957:                     if (ret != 1)
        !          2958:                         break;
        !          2959:                     list = list->next;
        !          2960:                 }
        !          2961:             }
        !          2962:             break;
        !          2963:         case XML_RELAXNG_START:
        !          2964:         case XML_RELAXNG_OPTIONAL:
        !          2965:         case XML_RELAXNG_ZEROORMORE:
        !          2966:         case XML_RELAXNG_ONEORMORE:
        !          2967:         case XML_RELAXNG_CHOICE:
        !          2968:         case XML_RELAXNG_GROUP:
        !          2969:         case XML_RELAXNG_DEF:{
        !          2970:                 xmlRelaxNGDefinePtr list;
        !          2971: 
        !          2972:                 list = def->content;
        !          2973:                 while (list != NULL) {
        !          2974:                     ret = xmlRelaxNGIsCompileable(list);
        !          2975:                     if (ret != 1)
        !          2976:                         break;
        !          2977:                     list = list->next;
        !          2978:                 }
        !          2979:                 break;
        !          2980:             }
        !          2981:         case XML_RELAXNG_EXCEPT:
        !          2982:         case XML_RELAXNG_ATTRIBUTE:
        !          2983:         case XML_RELAXNG_INTERLEAVE:
        !          2984:         case XML_RELAXNG_DATATYPE:
        !          2985:         case XML_RELAXNG_LIST:
        !          2986:         case XML_RELAXNG_PARAM:
        !          2987:         case XML_RELAXNG_VALUE:
        !          2988:         case XML_RELAXNG_NOT_ALLOWED:
        !          2989:             ret = 0;
        !          2990:             break;
        !          2991:     }
        !          2992:     if (ret == 0)
        !          2993:         def->dflags |= IS_NOT_COMPILABLE;
        !          2994:     if (ret == 1)
        !          2995:         def->dflags |= IS_COMPILABLE;
        !          2996: #ifdef DEBUG_COMPILE
        !          2997:     if (ret == 1) {
        !          2998:         xmlGenericError(xmlGenericErrorContext,
        !          2999:                         "RelaxNGIsCompileable %s : true\n",
        !          3000:                         xmlRelaxNGDefName(def));
        !          3001:     } else if (ret == 0) {
        !          3002:         xmlGenericError(xmlGenericErrorContext,
        !          3003:                         "RelaxNGIsCompileable %s : false\n",
        !          3004:                         xmlRelaxNGDefName(def));
        !          3005:     } else {
        !          3006:         xmlGenericError(xmlGenericErrorContext,
        !          3007:                         "Problem in RelaxNGIsCompileable %s\n",
        !          3008:                         xmlRelaxNGDefName(def));
        !          3009:     }
        !          3010: #endif
        !          3011:     return (ret);
        !          3012: }
        !          3013: 
        !          3014: /**
        !          3015:  * xmlRelaxNGCompile:
        !          3016:  * ctxt:  the RelaxNG parser context
        !          3017:  * @define:  the definition tree to compile
        !          3018:  *
        !          3019:  * Compile the set of definitions, it works recursively, till the
        !          3020:  * element boundaries, where it tries to compile the content if possible
        !          3021:  *
        !          3022:  * Returns 0 if success and -1 in case of error
        !          3023:  */
        !          3024: static int
        !          3025: xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
        !          3026: {
        !          3027:     int ret = 0;
        !          3028:     xmlRelaxNGDefinePtr list;
        !          3029: 
        !          3030:     if ((ctxt == NULL) || (def == NULL))
        !          3031:         return (-1);
        !          3032: 
        !          3033:     switch (def->type) {
        !          3034:         case XML_RELAXNG_START:
        !          3035:             if ((xmlRelaxNGIsCompileable(def) == 1) && (def->depth != -25)) {
        !          3036:                 xmlAutomataPtr oldam = ctxt->am;
        !          3037:                 xmlAutomataStatePtr oldstate = ctxt->state;
        !          3038: 
        !          3039:                 def->depth = -25;
        !          3040: 
        !          3041:                 list = def->content;
        !          3042:                 ctxt->am = xmlNewAutomata();
        !          3043:                 if (ctxt->am == NULL)
        !          3044:                     return (-1);
        !          3045: 
        !          3046:                 /*
        !          3047:                  * assume identical strings but not same pointer are different
        !          3048:                  * atoms, needed for non-determinism detection
        !          3049:                  * That way if 2 elements with the same name are in a choice
        !          3050:                  * branch the automata is found non-deterministic and
        !          3051:                  * we fallback to the normal validation which does the right
        !          3052:                  * thing of exploring both choices.
        !          3053:                  */
        !          3054:                 xmlAutomataSetFlags(ctxt->am, 1);
        !          3055: 
        !          3056:                 ctxt->state = xmlAutomataGetInitState(ctxt->am);
        !          3057:                 while (list != NULL) {
        !          3058:                     xmlRelaxNGCompile(ctxt, list);
        !          3059:                     list = list->next;
        !          3060:                 }
        !          3061:                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
        !          3062:                 def->contModel = xmlAutomataCompile(ctxt->am);
        !          3063:                 xmlRegexpIsDeterminist(def->contModel);
        !          3064: 
        !          3065:                 xmlFreeAutomata(ctxt->am);
        !          3066:                 ctxt->state = oldstate;
        !          3067:                 ctxt->am = oldam;
        !          3068:             }
        !          3069:             break;
        !          3070:         case XML_RELAXNG_ELEMENT:
        !          3071:             if ((ctxt->am != NULL) && (def->name != NULL)) {
        !          3072:                 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
        !          3073:                                                         ctxt->state, NULL,
        !          3074:                                                         def->name, def->ns,
        !          3075:                                                         def);
        !          3076:             }
        !          3077:             if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
        !          3078:                 xmlAutomataPtr oldam = ctxt->am;
        !          3079:                 xmlAutomataStatePtr oldstate = ctxt->state;
        !          3080: 
        !          3081:                 def->depth = -25;
        !          3082: 
        !          3083:                 list = def->content;
        !          3084:                 ctxt->am = xmlNewAutomata();
        !          3085:                 if (ctxt->am == NULL)
        !          3086:                     return (-1);
        !          3087:                 xmlAutomataSetFlags(ctxt->am, 1);
        !          3088:                 ctxt->state = xmlAutomataGetInitState(ctxt->am);
        !          3089:                 while (list != NULL) {
        !          3090:                     xmlRelaxNGCompile(ctxt, list);
        !          3091:                     list = list->next;
        !          3092:                 }
        !          3093:                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
        !          3094:                 def->contModel = xmlAutomataCompile(ctxt->am);
        !          3095:                 if (!xmlRegexpIsDeterminist(def->contModel)) {
        !          3096: #ifdef DEBUG_COMPILE
        !          3097:                     xmlGenericError(xmlGenericErrorContext,
        !          3098:                         "Content model not determinist %s\n",
        !          3099:                                     def->name);
        !          3100: #endif
        !          3101:                     /*
        !          3102:                      * we can only use the automata if it is determinist
        !          3103:                      */
        !          3104:                     xmlRegFreeRegexp(def->contModel);
        !          3105:                     def->contModel = NULL;
        !          3106:                 }
        !          3107:                 xmlFreeAutomata(ctxt->am);
        !          3108:                 ctxt->state = oldstate;
        !          3109:                 ctxt->am = oldam;
        !          3110:             } else {
        !          3111:                 xmlAutomataPtr oldam = ctxt->am;
        !          3112: 
        !          3113:                 /*
        !          3114:                  * we can't build the content model for this element content
        !          3115:                  * but it still might be possible to build it for some of its
        !          3116:                  * children, recurse.
        !          3117:                  */
        !          3118:                 ret = xmlRelaxNGTryCompile(ctxt, def);
        !          3119:                 ctxt->am = oldam;
        !          3120:             }
        !          3121:             break;
        !          3122:         case XML_RELAXNG_NOOP:
        !          3123:             ret = xmlRelaxNGCompile(ctxt, def->content);
        !          3124:             break;
        !          3125:         case XML_RELAXNG_OPTIONAL:{
        !          3126:                 xmlAutomataStatePtr oldstate = ctxt->state;
        !          3127: 
        !          3128:                 list = def->content;
        !          3129:                 while (list != NULL) {
        !          3130:                     xmlRelaxNGCompile(ctxt, list);
        !          3131:                     list = list->next;
        !          3132:                 }
        !          3133:                 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
        !          3134:                 break;
        !          3135:             }
        !          3136:         case XML_RELAXNG_ZEROORMORE:{
        !          3137:                 xmlAutomataStatePtr oldstate;
        !          3138: 
        !          3139:                 ctxt->state =
        !          3140:                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
        !          3141:                 oldstate = ctxt->state;
        !          3142:                 list = def->content;
        !          3143:                 while (list != NULL) {
        !          3144:                     xmlRelaxNGCompile(ctxt, list);
        !          3145:                     list = list->next;
        !          3146:                 }
        !          3147:                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
        !          3148:                 ctxt->state =
        !          3149:                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
        !          3150:                 break;
        !          3151:             }
        !          3152:         case XML_RELAXNG_ONEORMORE:{
        !          3153:                 xmlAutomataStatePtr oldstate;
        !          3154: 
        !          3155:                 list = def->content;
        !          3156:                 while (list != NULL) {
        !          3157:                     xmlRelaxNGCompile(ctxt, list);
        !          3158:                     list = list->next;
        !          3159:                 }
        !          3160:                 oldstate = ctxt->state;
        !          3161:                 list = def->content;
        !          3162:                 while (list != NULL) {
        !          3163:                     xmlRelaxNGCompile(ctxt, list);
        !          3164:                     list = list->next;
        !          3165:                 }
        !          3166:                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
        !          3167:                 ctxt->state =
        !          3168:                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
        !          3169:                 break;
        !          3170:             }
        !          3171:         case XML_RELAXNG_CHOICE:{
        !          3172:                 xmlAutomataStatePtr target = NULL;
        !          3173:                 xmlAutomataStatePtr oldstate = ctxt->state;
        !          3174: 
        !          3175:                 list = def->content;
        !          3176:                 while (list != NULL) {
        !          3177:                     ctxt->state = oldstate;
        !          3178:                     ret = xmlRelaxNGCompile(ctxt, list);
        !          3179:                     if (ret != 0)
        !          3180:                         break;
        !          3181:                     if (target == NULL)
        !          3182:                         target = ctxt->state;
        !          3183:                     else {
        !          3184:                         xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
        !          3185:                                               target);
        !          3186:                     }
        !          3187:                     list = list->next;
        !          3188:                 }
        !          3189:                 ctxt->state = target;
        !          3190: 
        !          3191:                 break;
        !          3192:             }
        !          3193:         case XML_RELAXNG_REF:
        !          3194:         case XML_RELAXNG_EXTERNALREF:
        !          3195:         case XML_RELAXNG_PARENTREF:
        !          3196:         case XML_RELAXNG_GROUP:
        !          3197:         case XML_RELAXNG_DEF:
        !          3198:             list = def->content;
        !          3199:             while (list != NULL) {
        !          3200:                 ret = xmlRelaxNGCompile(ctxt, list);
        !          3201:                 if (ret != 0)
        !          3202:                     break;
        !          3203:                 list = list->next;
        !          3204:             }
        !          3205:             break;
        !          3206:         case XML_RELAXNG_TEXT:{
        !          3207:                 xmlAutomataStatePtr oldstate;
        !          3208: 
        !          3209:                 ctxt->state =
        !          3210:                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
        !          3211:                 oldstate = ctxt->state;
        !          3212:                 xmlRelaxNGCompile(ctxt, def->content);
        !          3213:                 xmlAutomataNewTransition(ctxt->am, ctxt->state,
        !          3214:                                          ctxt->state, BAD_CAST "#text",
        !          3215:                                          NULL);
        !          3216:                 ctxt->state =
        !          3217:                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
        !          3218:                 break;
        !          3219:             }
        !          3220:         case XML_RELAXNG_EMPTY:
        !          3221:             ctxt->state =
        !          3222:                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
        !          3223:             break;
        !          3224:         case XML_RELAXNG_EXCEPT:
        !          3225:         case XML_RELAXNG_ATTRIBUTE:
        !          3226:         case XML_RELAXNG_INTERLEAVE:
        !          3227:         case XML_RELAXNG_NOT_ALLOWED:
        !          3228:         case XML_RELAXNG_DATATYPE:
        !          3229:         case XML_RELAXNG_LIST:
        !          3230:         case XML_RELAXNG_PARAM:
        !          3231:         case XML_RELAXNG_VALUE:
        !          3232:             /* This should not happen and generate an internal error */
        !          3233:             fprintf(stderr, "RNG internal error trying to compile %s\n",
        !          3234:                     xmlRelaxNGDefName(def));
        !          3235:             break;
        !          3236:     }
        !          3237:     return (ret);
        !          3238: }
        !          3239: 
        !          3240: /**
        !          3241:  * xmlRelaxNGTryCompile:
        !          3242:  * ctxt:  the RelaxNG parser context
        !          3243:  * @define:  the definition tree to compile
        !          3244:  *
        !          3245:  * Try to compile the set of definitions, it works recursively,
        !          3246:  * possibly ignoring parts which cannot be compiled.
        !          3247:  *
        !          3248:  * Returns 0 if success and -1 in case of error
        !          3249:  */
        !          3250: static int
        !          3251: xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
        !          3252: {
        !          3253:     int ret = 0;
        !          3254:     xmlRelaxNGDefinePtr list;
        !          3255: 
        !          3256:     if ((ctxt == NULL) || (def == NULL))
        !          3257:         return (-1);
        !          3258: 
        !          3259:     if ((def->type == XML_RELAXNG_START) ||
        !          3260:         (def->type == XML_RELAXNG_ELEMENT)) {
        !          3261:         ret = xmlRelaxNGIsCompileable(def);
        !          3262:         if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
        !          3263:             ctxt->am = NULL;
        !          3264:             ret = xmlRelaxNGCompile(ctxt, def);
        !          3265: #ifdef DEBUG_PROGRESSIVE
        !          3266:             if (ret == 0) {
        !          3267:                 if (def->type == XML_RELAXNG_START)
        !          3268:                     xmlGenericError(xmlGenericErrorContext,
        !          3269:                                     "compiled the start\n");
        !          3270:                 else
        !          3271:                     xmlGenericError(xmlGenericErrorContext,
        !          3272:                                     "compiled element %s\n", def->name);
        !          3273:             } else {
        !          3274:                 if (def->type == XML_RELAXNG_START)
        !          3275:                     xmlGenericError(xmlGenericErrorContext,
        !          3276:                                     "failed to compile the start\n");
        !          3277:                 else
        !          3278:                     xmlGenericError(xmlGenericErrorContext,
        !          3279:                                     "failed to compile element %s\n",
        !          3280:                                     def->name);
        !          3281:             }
        !          3282: #endif
        !          3283:             return (ret);
        !          3284:         }
        !          3285:     }
        !          3286:     switch (def->type) {
        !          3287:         case XML_RELAXNG_NOOP:
        !          3288:             ret = xmlRelaxNGTryCompile(ctxt, def->content);
        !          3289:             break;
        !          3290:         case XML_RELAXNG_TEXT:
        !          3291:         case XML_RELAXNG_DATATYPE:
        !          3292:         case XML_RELAXNG_LIST:
        !          3293:         case XML_RELAXNG_PARAM:
        !          3294:         case XML_RELAXNG_VALUE:
        !          3295:         case XML_RELAXNG_EMPTY:
        !          3296:         case XML_RELAXNG_ELEMENT:
        !          3297:             ret = 0;
        !          3298:             break;
        !          3299:         case XML_RELAXNG_OPTIONAL:
        !          3300:         case XML_RELAXNG_ZEROORMORE:
        !          3301:         case XML_RELAXNG_ONEORMORE:
        !          3302:         case XML_RELAXNG_CHOICE:
        !          3303:         case XML_RELAXNG_GROUP:
        !          3304:         case XML_RELAXNG_DEF:
        !          3305:         case XML_RELAXNG_START:
        !          3306:         case XML_RELAXNG_REF:
        !          3307:         case XML_RELAXNG_EXTERNALREF:
        !          3308:         case XML_RELAXNG_PARENTREF:
        !          3309:             list = def->content;
        !          3310:             while (list != NULL) {
        !          3311:                 ret = xmlRelaxNGTryCompile(ctxt, list);
        !          3312:                 if (ret != 0)
        !          3313:                     break;
        !          3314:                 list = list->next;
        !          3315:             }
        !          3316:             break;
        !          3317:         case XML_RELAXNG_EXCEPT:
        !          3318:         case XML_RELAXNG_ATTRIBUTE:
        !          3319:         case XML_RELAXNG_INTERLEAVE:
        !          3320:         case XML_RELAXNG_NOT_ALLOWED:
        !          3321:             ret = 0;
        !          3322:             break;
        !          3323:     }
        !          3324:     return (ret);
        !          3325: }
        !          3326: 
        !          3327: /************************************************************************
        !          3328:  *                                                                     *
        !          3329:  *                     Parsing functions                               *
        !          3330:  *                                                                     *
        !          3331:  ************************************************************************/
        !          3332: 
        !          3333: static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr
        !          3334:                                                     ctxt, xmlNodePtr node);
        !          3335: static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr
        !          3336:                                                   ctxt, xmlNodePtr node);
        !          3337: static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr
        !          3338:                                                    ctxt, xmlNodePtr nodes,
        !          3339:                                                    int group);
        !          3340: static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr
        !          3341:                                                   ctxt, xmlNodePtr node);
        !          3342: static xmlRelaxNGPtr xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt,
        !          3343:                                              xmlNodePtr node);
        !          3344: static int xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
        !          3345:                                          xmlNodePtr nodes);
        !          3346: static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr
        !          3347:                                                     ctxt, xmlNodePtr node,
        !          3348:                                                     xmlRelaxNGDefinePtr
        !          3349:                                                     def);
        !          3350: static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr
        !          3351:                                                    ctxt, xmlNodePtr nodes);
        !          3352: static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
        !          3353:                                   xmlRelaxNGDefinePtr define,
        !          3354:                                   xmlNodePtr elem);
        !          3355: 
        !          3356: 
        !          3357: #define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
        !          3358: 
        !          3359: /**
        !          3360:  * xmlRelaxNGIsNullable:
        !          3361:  * @define:  the definition to verify
        !          3362:  *
        !          3363:  * Check if a definition is nullable.
        !          3364:  *
        !          3365:  * Returns 1 if yes, 0 if no and -1 in case of error
        !          3366:  */
        !          3367: static int
        !          3368: xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define)
        !          3369: {
        !          3370:     int ret;
        !          3371: 
        !          3372:     if (define == NULL)
        !          3373:         return (-1);
        !          3374: 
        !          3375:     if (define->dflags & IS_NULLABLE)
        !          3376:         return (1);
        !          3377:     if (define->dflags & IS_NOT_NULLABLE)
        !          3378:         return (0);
        !          3379:     switch (define->type) {
        !          3380:         case XML_RELAXNG_EMPTY:
        !          3381:         case XML_RELAXNG_TEXT:
        !          3382:             ret = 1;
        !          3383:             break;
        !          3384:         case XML_RELAXNG_NOOP:
        !          3385:         case XML_RELAXNG_DEF:
        !          3386:         case XML_RELAXNG_REF:
        !          3387:         case XML_RELAXNG_EXTERNALREF:
        !          3388:         case XML_RELAXNG_PARENTREF:
        !          3389:         case XML_RELAXNG_ONEORMORE:
        !          3390:             ret = xmlRelaxNGIsNullable(define->content);
        !          3391:             break;
        !          3392:         case XML_RELAXNG_EXCEPT:
        !          3393:         case XML_RELAXNG_NOT_ALLOWED:
        !          3394:         case XML_RELAXNG_ELEMENT:
        !          3395:         case XML_RELAXNG_DATATYPE:
        !          3396:         case XML_RELAXNG_PARAM:
        !          3397:         case XML_RELAXNG_VALUE:
        !          3398:         case XML_RELAXNG_LIST:
        !          3399:         case XML_RELAXNG_ATTRIBUTE:
        !          3400:             ret = 0;
        !          3401:             break;
        !          3402:         case XML_RELAXNG_CHOICE:{
        !          3403:                 xmlRelaxNGDefinePtr list = define->content;
        !          3404: 
        !          3405:                 while (list != NULL) {
        !          3406:                     ret = xmlRelaxNGIsNullable(list);
        !          3407:                     if (ret != 0)
        !          3408:                         goto done;
        !          3409:                     list = list->next;
        !          3410:                 }
        !          3411:                 ret = 0;
        !          3412:                 break;
        !          3413:             }
        !          3414:         case XML_RELAXNG_START:
        !          3415:         case XML_RELAXNG_INTERLEAVE:
        !          3416:         case XML_RELAXNG_GROUP:{
        !          3417:                 xmlRelaxNGDefinePtr list = define->content;
        !          3418: 
        !          3419:                 while (list != NULL) {
        !          3420:                     ret = xmlRelaxNGIsNullable(list);
        !          3421:                     if (ret != 1)
        !          3422:                         goto done;
        !          3423:                     list = list->next;
        !          3424:                 }
        !          3425:                 return (1);
        !          3426:             }
        !          3427:         default:
        !          3428:             return (-1);
        !          3429:     }
        !          3430:   done:
        !          3431:     if (ret == 0)
        !          3432:         define->dflags |= IS_NOT_NULLABLE;
        !          3433:     if (ret == 1)
        !          3434:         define->dflags |= IS_NULLABLE;
        !          3435:     return (ret);
        !          3436: }
        !          3437: 
        !          3438: /**
        !          3439:  * xmlRelaxNGIsBlank:
        !          3440:  * @str:  a string
        !          3441:  *
        !          3442:  * Check if a string is ignorable c.f. 4.2. Whitespace
        !          3443:  *
        !          3444:  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
        !          3445:  */
        !          3446: static int
        !          3447: xmlRelaxNGIsBlank(xmlChar * str)
        !          3448: {
        !          3449:     if (str == NULL)
        !          3450:         return (1);
        !          3451:     while (*str != 0) {
        !          3452:         if (!(IS_BLANK_CH(*str)))
        !          3453:             return (0);
        !          3454:         str++;
        !          3455:     }
        !          3456:     return (1);
        !          3457: }
        !          3458: 
        !          3459: /**
        !          3460:  * xmlRelaxNGGetDataTypeLibrary:
        !          3461:  * @ctxt:  a Relax-NG parser context
        !          3462:  * @node:  the current data or value element
        !          3463:  *
        !          3464:  * Applies algorithm from 4.3. datatypeLibrary attribute
        !          3465:  *
        !          3466:  * Returns the datatypeLibary value or NULL if not found
        !          3467:  */
        !          3468: static xmlChar *
        !          3469: xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
        !          3470:                              xmlNodePtr node)
        !          3471: {
        !          3472:     xmlChar *ret, *escape;
        !          3473: 
        !          3474:     if (node == NULL)
        !          3475:         return(NULL);
        !          3476: 
        !          3477:     if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
        !          3478:         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
        !          3479:         if (ret != NULL) {
        !          3480:             if (ret[0] == 0) {
        !          3481:                 xmlFree(ret);
        !          3482:                 return (NULL);
        !          3483:             }
        !          3484:             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
        !          3485:             if (escape == NULL) {
        !          3486:                 return (ret);
        !          3487:             }
        !          3488:             xmlFree(ret);
        !          3489:             return (escape);
        !          3490:         }
        !          3491:     }
        !          3492:     node = node->parent;
        !          3493:     while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
        !          3494:         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
        !          3495:         if (ret != NULL) {
        !          3496:             if (ret[0] == 0) {
        !          3497:                 xmlFree(ret);
        !          3498:                 return (NULL);
        !          3499:             }
        !          3500:             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
        !          3501:             if (escape == NULL) {
        !          3502:                 return (ret);
        !          3503:             }
        !          3504:             xmlFree(ret);
        !          3505:             return (escape);
        !          3506:         }
        !          3507:         node = node->parent;
        !          3508:     }
        !          3509:     return (NULL);
        !          3510: }
        !          3511: 
        !          3512: /**
        !          3513:  * xmlRelaxNGParseValue:
        !          3514:  * @ctxt:  a Relax-NG parser context
        !          3515:  * @node:  the data node.
        !          3516:  *
        !          3517:  * parse the content of a RelaxNG value node.
        !          3518:  *
        !          3519:  * Returns the definition pointer or NULL in case of error
        !          3520:  */
        !          3521: static xmlRelaxNGDefinePtr
        !          3522: xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          3523: {
        !          3524:     xmlRelaxNGDefinePtr def = NULL;
        !          3525:     xmlRelaxNGTypeLibraryPtr lib = NULL;
        !          3526:     xmlChar *type;
        !          3527:     xmlChar *library;
        !          3528:     int success = 0;
        !          3529: 
        !          3530:     def = xmlRelaxNGNewDefine(ctxt, node);
        !          3531:     if (def == NULL)
        !          3532:         return (NULL);
        !          3533:     def->type = XML_RELAXNG_VALUE;
        !          3534: 
        !          3535:     type = xmlGetProp(node, BAD_CAST "type");
        !          3536:     if (type != NULL) {
        !          3537:         xmlRelaxNGNormExtSpace(type);
        !          3538:         if (xmlValidateNCName(type, 0)) {
        !          3539:             xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
        !          3540:                        "value type '%s' is not an NCName\n", type, NULL);
        !          3541:         }
        !          3542:         library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
        !          3543:         if (library == NULL)
        !          3544:             library =
        !          3545:                 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
        !          3546: 
        !          3547:         def->name = type;
        !          3548:         def->ns = library;
        !          3549: 
        !          3550:         lib = (xmlRelaxNGTypeLibraryPtr)
        !          3551:             xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
        !          3552:         if (lib == NULL) {
        !          3553:             xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
        !          3554:                        "Use of unregistered type library '%s'\n", library,
        !          3555:                        NULL);
        !          3556:             def->data = NULL;
        !          3557:         } else {
        !          3558:             def->data = lib;
        !          3559:             if (lib->have == NULL) {
        !          3560:                 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
        !          3561:                            "Internal error with type library '%s': no 'have'\n",
        !          3562:                            library, NULL);
        !          3563:             } else {
        !          3564:                 success = lib->have(lib->data, def->name);
        !          3565:                 if (success != 1) {
        !          3566:                     xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
        !          3567:                                "Error type '%s' is not exported by type library '%s'\n",
        !          3568:                                def->name, library);
        !          3569:                 }
        !          3570:             }
        !          3571:         }
        !          3572:     }
        !          3573:     if (node->children == NULL) {
        !          3574:         def->value = xmlStrdup(BAD_CAST "");
        !          3575:     } else if (((node->children->type != XML_TEXT_NODE) &&
        !          3576:                 (node->children->type != XML_CDATA_SECTION_NODE)) ||
        !          3577:                (node->children->next != NULL)) {
        !          3578:         xmlRngPErr(ctxt, node, XML_RNGP_TEXT_EXPECTED,
        !          3579:                    "Expecting a single text value for <value>content\n",
        !          3580:                    NULL, NULL);
        !          3581:     } else if (def != NULL) {
        !          3582:         def->value = xmlNodeGetContent(node);
        !          3583:         if (def->value == NULL) {
        !          3584:             xmlRngPErr(ctxt, node, XML_RNGP_VALUE_NO_CONTENT,
        !          3585:                        "Element <value> has no content\n", NULL, NULL);
        !          3586:         } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) {
        !          3587:             void *val = NULL;
        !          3588: 
        !          3589:             success =
        !          3590:                 lib->check(lib->data, def->name, def->value, &val, node);
        !          3591:             if (success != 1) {
        !          3592:                 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_VALUE,
        !          3593:                            "Value '%s' is not acceptable for type '%s'\n",
        !          3594:                            def->value, def->name);
        !          3595:             } else {
        !          3596:                 if (val != NULL)
        !          3597:                     def->attrs = val;
        !          3598:             }
        !          3599:         }
        !          3600:     }
        !          3601:     return (def);
        !          3602: }
        !          3603: 
        !          3604: /**
        !          3605:  * xmlRelaxNGParseData:
        !          3606:  * @ctxt:  a Relax-NG parser context
        !          3607:  * @node:  the data node.
        !          3608:  *
        !          3609:  * parse the content of a RelaxNG data node.
        !          3610:  *
        !          3611:  * Returns the definition pointer or NULL in case of error
        !          3612:  */
        !          3613: static xmlRelaxNGDefinePtr
        !          3614: xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          3615: {
        !          3616:     xmlRelaxNGDefinePtr def = NULL, except;
        !          3617:     xmlRelaxNGDefinePtr param, lastparam = NULL;
        !          3618:     xmlRelaxNGTypeLibraryPtr lib;
        !          3619:     xmlChar *type;
        !          3620:     xmlChar *library;
        !          3621:     xmlNodePtr content;
        !          3622:     int tmp;
        !          3623: 
        !          3624:     type = xmlGetProp(node, BAD_CAST "type");
        !          3625:     if (type == NULL) {
        !          3626:         xmlRngPErr(ctxt, node, XML_RNGP_TYPE_MISSING, "data has no type\n", NULL,
        !          3627:                    NULL);
        !          3628:         return (NULL);
        !          3629:     }
        !          3630:     xmlRelaxNGNormExtSpace(type);
        !          3631:     if (xmlValidateNCName(type, 0)) {
        !          3632:         xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
        !          3633:                    "data type '%s' is not an NCName\n", type, NULL);
        !          3634:     }
        !          3635:     library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
        !          3636:     if (library == NULL)
        !          3637:         library =
        !          3638:             xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
        !          3639: 
        !          3640:     def = xmlRelaxNGNewDefine(ctxt, node);
        !          3641:     if (def == NULL) {
        !          3642:         xmlFree(type);
        !          3643:         return (NULL);
        !          3644:     }
        !          3645:     def->type = XML_RELAXNG_DATATYPE;
        !          3646:     def->name = type;
        !          3647:     def->ns = library;
        !          3648: 
        !          3649:     lib = (xmlRelaxNGTypeLibraryPtr)
        !          3650:         xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
        !          3651:     if (lib == NULL) {
        !          3652:         xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
        !          3653:                    "Use of unregistered type library '%s'\n", library,
        !          3654:                    NULL);
        !          3655:         def->data = NULL;
        !          3656:     } else {
        !          3657:         def->data = lib;
        !          3658:         if (lib->have == NULL) {
        !          3659:             xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
        !          3660:                        "Internal error with type library '%s': no 'have'\n",
        !          3661:                        library, NULL);
        !          3662:         } else {
        !          3663:             tmp = lib->have(lib->data, def->name);
        !          3664:             if (tmp != 1) {
        !          3665:                 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
        !          3666:                            "Error type '%s' is not exported by type library '%s'\n",
        !          3667:                            def->name, library);
        !          3668:             } else
        !          3669:                 if ((xmlStrEqual
        !          3670:                      (library,
        !          3671:                       BAD_CAST
        !          3672:                       "http://www.w3.org/2001/XMLSchema-datatypes"))
        !          3673:                     && ((xmlStrEqual(def->name, BAD_CAST "IDREF"))
        !          3674:                         || (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) {
        !          3675:                 ctxt->idref = 1;
        !          3676:             }
        !          3677:         }
        !          3678:     }
        !          3679:     content = node->children;
        !          3680: 
        !          3681:     /*
        !          3682:      * Handle optional params
        !          3683:      */
        !          3684:     while (content != NULL) {
        !          3685:         if (!xmlStrEqual(content->name, BAD_CAST "param"))
        !          3686:             break;
        !          3687:         if (xmlStrEqual(library,
        !          3688:                         BAD_CAST "http://relaxng.org/ns/structure/1.0")) {
        !          3689:             xmlRngPErr(ctxt, node, XML_RNGP_PARAM_FORBIDDEN,
        !          3690:                        "Type library '%s' does not allow type parameters\n",
        !          3691:                        library, NULL);
        !          3692:             content = content->next;
        !          3693:             while ((content != NULL) &&
        !          3694:                    (xmlStrEqual(content->name, BAD_CAST "param")))
        !          3695:                 content = content->next;
        !          3696:         } else {
        !          3697:             param = xmlRelaxNGNewDefine(ctxt, node);
        !          3698:             if (param != NULL) {
        !          3699:                 param->type = XML_RELAXNG_PARAM;
        !          3700:                 param->name = xmlGetProp(content, BAD_CAST "name");
        !          3701:                 if (param->name == NULL) {
        !          3702:                     xmlRngPErr(ctxt, node, XML_RNGP_PARAM_NAME_MISSING,
        !          3703:                                "param has no name\n", NULL, NULL);
        !          3704:                 }
        !          3705:                 param->value = xmlNodeGetContent(content);
        !          3706:                 if (lastparam == NULL) {
        !          3707:                     def->attrs = lastparam = param;
        !          3708:                 } else {
        !          3709:                     lastparam->next = param;
        !          3710:                     lastparam = param;
        !          3711:                 }
        !          3712:                 if (lib != NULL) {
        !          3713:                 }
        !          3714:             }
        !          3715:             content = content->next;
        !          3716:         }
        !          3717:     }
        !          3718:     /*
        !          3719:      * Handle optional except
        !          3720:      */
        !          3721:     if ((content != NULL)
        !          3722:         && (xmlStrEqual(content->name, BAD_CAST "except"))) {
        !          3723:         xmlNodePtr child;
        !          3724:         xmlRelaxNGDefinePtr tmp2, last = NULL;
        !          3725: 
        !          3726:         except = xmlRelaxNGNewDefine(ctxt, node);
        !          3727:         if (except == NULL) {
        !          3728:             return (def);
        !          3729:         }
        !          3730:         except->type = XML_RELAXNG_EXCEPT;
        !          3731:         child = content->children;
        !          3732:        def->content = except;
        !          3733:         if (child == NULL) {
        !          3734:             xmlRngPErr(ctxt, content, XML_RNGP_EXCEPT_NO_CONTENT,
        !          3735:                        "except has no content\n", NULL, NULL);
        !          3736:         }
        !          3737:         while (child != NULL) {
        !          3738:             tmp2 = xmlRelaxNGParsePattern(ctxt, child);
        !          3739:             if (tmp2 != NULL) {
        !          3740:                 if (last == NULL) {
        !          3741:                     except->content = last = tmp2;
        !          3742:                 } else {
        !          3743:                     last->next = tmp2;
        !          3744:                     last = tmp2;
        !          3745:                 }
        !          3746:             }
        !          3747:             child = child->next;
        !          3748:         }
        !          3749:         content = content->next;
        !          3750:     }
        !          3751:     /*
        !          3752:      * Check there is no unhandled data
        !          3753:      */
        !          3754:     if (content != NULL) {
        !          3755:         xmlRngPErr(ctxt, content, XML_RNGP_DATA_CONTENT,
        !          3756:                    "Element data has unexpected content %s\n",
        !          3757:                    content->name, NULL);
        !          3758:     }
        !          3759: 
        !          3760:     return (def);
        !          3761: }
        !          3762: 
        !          3763: static const xmlChar *invalidName = BAD_CAST "\1";
        !          3764: 
        !          3765: /**
        !          3766:  * xmlRelaxNGCompareNameClasses:
        !          3767:  * @defs1:  the first element/attribute defs
        !          3768:  * @defs2:  the second element/attribute defs
        !          3769:  * @name:  the restriction on the name
        !          3770:  * @ns:  the restriction on the namespace
        !          3771:  *
        !          3772:  * Compare the 2 lists of element definitions. The comparison is
        !          3773:  * that if both lists do not accept the same QNames, it returns 1
        !          3774:  * If the 2 lists can accept the same QName the comparison returns 0
        !          3775:  *
        !          3776:  * Returns 1 disttinct, 0 if equal
        !          3777:  */
        !          3778: static int
        !          3779: xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,
        !          3780:                              xmlRelaxNGDefinePtr def2)
        !          3781: {
        !          3782:     int ret = 1;
        !          3783:     xmlNode node;
        !          3784:     xmlNs ns;
        !          3785:     xmlRelaxNGValidCtxt ctxt;
        !          3786: 
        !          3787:     memset(&ctxt, 0, sizeof(xmlRelaxNGValidCtxt));
        !          3788: 
        !          3789:     ctxt.flags = FLAGS_IGNORABLE | FLAGS_NOERROR;
        !          3790: 
        !          3791:     if ((def1->type == XML_RELAXNG_ELEMENT) ||
        !          3792:         (def1->type == XML_RELAXNG_ATTRIBUTE)) {
        !          3793:         if (def2->type == XML_RELAXNG_TEXT)
        !          3794:             return (1);
        !          3795:         if (def1->name != NULL) {
        !          3796:             node.name = def1->name;
        !          3797:         } else {
        !          3798:             node.name = invalidName;
        !          3799:         }
        !          3800:         if (def1->ns != NULL) {
        !          3801:             if (def1->ns[0] == 0) {
        !          3802:                 node.ns = NULL;
        !          3803:             } else {
        !          3804:                node.ns = &ns;
        !          3805:                 ns.href = def1->ns;
        !          3806:             }
        !          3807:         } else {
        !          3808:             node.ns = NULL;
        !          3809:         }
        !          3810:         if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) {
        !          3811:             if (def1->nameClass != NULL) {
        !          3812:                 ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2);
        !          3813:             } else {
        !          3814:                 ret = 0;
        !          3815:             }
        !          3816:         } else {
        !          3817:             ret = 1;
        !          3818:         }
        !          3819:     } else if (def1->type == XML_RELAXNG_TEXT) {
        !          3820:         if (def2->type == XML_RELAXNG_TEXT)
        !          3821:             return (0);
        !          3822:         return (1);
        !          3823:     } else if (def1->type == XML_RELAXNG_EXCEPT) {
        !          3824:         TODO ret = 0;
        !          3825:     } else {
        !          3826:         TODO ret = 0;
        !          3827:     }
        !          3828:     if (ret == 0)
        !          3829:         return (ret);
        !          3830:     if ((def2->type == XML_RELAXNG_ELEMENT) ||
        !          3831:         (def2->type == XML_RELAXNG_ATTRIBUTE)) {
        !          3832:         if (def2->name != NULL) {
        !          3833:             node.name = def2->name;
        !          3834:         } else {
        !          3835:             node.name = invalidName;
        !          3836:         }
        !          3837:         node.ns = &ns;
        !          3838:         if (def2->ns != NULL) {
        !          3839:             if (def2->ns[0] == 0) {
        !          3840:                 node.ns = NULL;
        !          3841:             } else {
        !          3842:                 ns.href = def2->ns;
        !          3843:             }
        !          3844:         } else {
        !          3845:             ns.href = invalidName;
        !          3846:         }
        !          3847:         if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) {
        !          3848:             if (def2->nameClass != NULL) {
        !          3849:                 ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1);
        !          3850:             } else {
        !          3851:                 ret = 0;
        !          3852:             }
        !          3853:         } else {
        !          3854:             ret = 1;
        !          3855:         }
        !          3856:     } else {
        !          3857:         TODO ret = 0;
        !          3858:     }
        !          3859: 
        !          3860:     return (ret);
        !          3861: }
        !          3862: 
        !          3863: /**
        !          3864:  * xmlRelaxNGCompareElemDefLists:
        !          3865:  * @ctxt:  a Relax-NG parser context
        !          3866:  * @defs1:  the first list of element/attribute defs
        !          3867:  * @defs2:  the second list of element/attribute defs
        !          3868:  *
        !          3869:  * Compare the 2 lists of element or attribute definitions. The comparison
        !          3870:  * is that if both lists do not accept the same QNames, it returns 1
        !          3871:  * If the 2 lists can accept the same QName the comparison returns 0
        !          3872:  *
        !          3873:  * Returns 1 disttinct, 0 if equal
        !          3874:  */
        !          3875: static int
        !          3876: xmlRelaxNGCompareElemDefLists(xmlRelaxNGParserCtxtPtr ctxt
        !          3877:                               ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr * def1,
        !          3878:                               xmlRelaxNGDefinePtr * def2)
        !          3879: {
        !          3880:     xmlRelaxNGDefinePtr *basedef2 = def2;
        !          3881: 
        !          3882:     if ((def1 == NULL) || (def2 == NULL))
        !          3883:         return (1);
        !          3884:     if ((*def1 == NULL) || (*def2 == NULL))
        !          3885:         return (1);
        !          3886:     while (*def1 != NULL) {
        !          3887:         while ((*def2) != NULL) {
        !          3888:             if (xmlRelaxNGCompareNameClasses(*def1, *def2) == 0)
        !          3889:                 return (0);
        !          3890:             def2++;
        !          3891:         }
        !          3892:         def2 = basedef2;
        !          3893:         def1++;
        !          3894:     }
        !          3895:     return (1);
        !          3896: }
        !          3897: 
        !          3898: /**
        !          3899:  * xmlRelaxNGGenerateAttributes:
        !          3900:  * @ctxt:  a Relax-NG parser context
        !          3901:  * @def:  the definition definition
        !          3902:  *
        !          3903:  * Check if the definition can only generate attributes
        !          3904:  *
        !          3905:  * Returns 1 if yes, 0 if no and -1 in case of error.
        !          3906:  */
        !          3907: static int
        !          3908: xmlRelaxNGGenerateAttributes(xmlRelaxNGParserCtxtPtr ctxt,
        !          3909:                              xmlRelaxNGDefinePtr def)
        !          3910: {
        !          3911:     xmlRelaxNGDefinePtr parent, cur, tmp;
        !          3912: 
        !          3913:     /*
        !          3914:      * Don't run that check in case of error. Infinite recursion
        !          3915:      * becomes possible.
        !          3916:      */
        !          3917:     if (ctxt->nbErrors != 0)
        !          3918:         return (-1);
        !          3919: 
        !          3920:     parent = NULL;
        !          3921:     cur = def;
        !          3922:     while (cur != NULL) {
        !          3923:         if ((cur->type == XML_RELAXNG_ELEMENT) ||
        !          3924:             (cur->type == XML_RELAXNG_TEXT) ||
        !          3925:             (cur->type == XML_RELAXNG_DATATYPE) ||
        !          3926:             (cur->type == XML_RELAXNG_PARAM) ||
        !          3927:             (cur->type == XML_RELAXNG_LIST) ||
        !          3928:             (cur->type == XML_RELAXNG_VALUE) ||
        !          3929:             (cur->type == XML_RELAXNG_EMPTY))
        !          3930:             return (0);
        !          3931:         if ((cur->type == XML_RELAXNG_CHOICE) ||
        !          3932:             (cur->type == XML_RELAXNG_INTERLEAVE) ||
        !          3933:             (cur->type == XML_RELAXNG_GROUP) ||
        !          3934:             (cur->type == XML_RELAXNG_ONEORMORE) ||
        !          3935:             (cur->type == XML_RELAXNG_ZEROORMORE) ||
        !          3936:             (cur->type == XML_RELAXNG_OPTIONAL) ||
        !          3937:             (cur->type == XML_RELAXNG_PARENTREF) ||
        !          3938:             (cur->type == XML_RELAXNG_EXTERNALREF) ||
        !          3939:             (cur->type == XML_RELAXNG_REF) ||
        !          3940:             (cur->type == XML_RELAXNG_DEF)) {
        !          3941:             if (cur->content != NULL) {
        !          3942:                 parent = cur;
        !          3943:                 cur = cur->content;
        !          3944:                 tmp = cur;
        !          3945:                 while (tmp != NULL) {
        !          3946:                     tmp->parent = parent;
        !          3947:                     tmp = tmp->next;
        !          3948:                 }
        !          3949:                 continue;
        !          3950:             }
        !          3951:         }
        !          3952:         if (cur == def)
        !          3953:             break;
        !          3954:         if (cur->next != NULL) {
        !          3955:             cur = cur->next;
        !          3956:             continue;
        !          3957:         }
        !          3958:         do {
        !          3959:             cur = cur->parent;
        !          3960:             if (cur == NULL)
        !          3961:                 break;
        !          3962:             if (cur == def)
        !          3963:                 return (1);
        !          3964:             if (cur->next != NULL) {
        !          3965:                 cur = cur->next;
        !          3966:                 break;
        !          3967:             }
        !          3968:         } while (cur != NULL);
        !          3969:     }
        !          3970:     return (1);
        !          3971: }
        !          3972: 
        !          3973: /**
        !          3974:  * xmlRelaxNGGetElements:
        !          3975:  * @ctxt:  a Relax-NG parser context
        !          3976:  * @def:  the definition definition
        !          3977:  * @eora:  gather elements (0) or attributes (1)
        !          3978:  *
        !          3979:  * Compute the list of top elements a definition can generate
        !          3980:  *
        !          3981:  * Returns a list of elements or NULL if none was found.
        !          3982:  */
        !          3983: static xmlRelaxNGDefinePtr *
        !          3984: xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
        !          3985:                       xmlRelaxNGDefinePtr def, int eora)
        !          3986: {
        !          3987:     xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp;
        !          3988:     int len = 0;
        !          3989:     int max = 0;
        !          3990: 
        !          3991:     /*
        !          3992:      * Don't run that check in case of error. Infinite recursion
        !          3993:      * becomes possible.
        !          3994:      */
        !          3995:     if (ctxt->nbErrors != 0)
        !          3996:         return (NULL);
        !          3997: 
        !          3998:     parent = NULL;
        !          3999:     cur = def;
        !          4000:     while (cur != NULL) {
        !          4001:         if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||
        !          4002:                              (cur->type == XML_RELAXNG_TEXT))) ||
        !          4003:             ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE))) {
        !          4004:             if (ret == NULL) {
        !          4005:                 max = 10;
        !          4006:                 ret = (xmlRelaxNGDefinePtr *)
        !          4007:                     xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr));
        !          4008:                 if (ret == NULL) {
        !          4009:                     xmlRngPErrMemory(ctxt, "getting element list\n");
        !          4010:                     return (NULL);
        !          4011:                 }
        !          4012:             } else if (max <= len) {
        !          4013:                xmlRelaxNGDefinePtr *temp;
        !          4014: 
        !          4015:                 max *= 2;
        !          4016:                 temp = xmlRealloc(ret,
        !          4017:                                (max + 1) * sizeof(xmlRelaxNGDefinePtr));
        !          4018:                 if (temp == NULL) {
        !          4019:                     xmlRngPErrMemory(ctxt, "getting element list\n");
        !          4020:                    xmlFree(ret);
        !          4021:                     return (NULL);
        !          4022:                 }
        !          4023:                ret = temp;
        !          4024:             }
        !          4025:             ret[len++] = cur;
        !          4026:             ret[len] = NULL;
        !          4027:         } else if ((cur->type == XML_RELAXNG_CHOICE) ||
        !          4028:                    (cur->type == XML_RELAXNG_INTERLEAVE) ||
        !          4029:                    (cur->type == XML_RELAXNG_GROUP) ||
        !          4030:                    (cur->type == XML_RELAXNG_ONEORMORE) ||
        !          4031:                    (cur->type == XML_RELAXNG_ZEROORMORE) ||
        !          4032:                    (cur->type == XML_RELAXNG_OPTIONAL) ||
        !          4033:                    (cur->type == XML_RELAXNG_PARENTREF) ||
        !          4034:                    (cur->type == XML_RELAXNG_REF) ||
        !          4035:                    (cur->type == XML_RELAXNG_DEF) ||
        !          4036:                   (cur->type == XML_RELAXNG_EXTERNALREF)) {
        !          4037:             /*
        !          4038:              * Don't go within elements or attributes or string values.
        !          4039:              * Just gather the element top list
        !          4040:              */
        !          4041:             if (cur->content != NULL) {
        !          4042:                 parent = cur;
        !          4043:                 cur = cur->content;
        !          4044:                 tmp = cur;
        !          4045:                 while (tmp != NULL) {
        !          4046:                     tmp->parent = parent;
        !          4047:                     tmp = tmp->next;
        !          4048:                 }
        !          4049:                 continue;
        !          4050:             }
        !          4051:         }
        !          4052:         if (cur == def)
        !          4053:             break;
        !          4054:         if (cur->next != NULL) {
        !          4055:             cur = cur->next;
        !          4056:             continue;
        !          4057:         }
        !          4058:         do {
        !          4059:             cur = cur->parent;
        !          4060:             if (cur == NULL)
        !          4061:                 break;
        !          4062:             if (cur == def)
        !          4063:                 return (ret);
        !          4064:             if (cur->next != NULL) {
        !          4065:                 cur = cur->next;
        !          4066:                 break;
        !          4067:             }
        !          4068:         } while (cur != NULL);
        !          4069:     }
        !          4070:     return (ret);
        !          4071: }
        !          4072: 
        !          4073: /**
        !          4074:  * xmlRelaxNGCheckChoiceDeterminism:
        !          4075:  * @ctxt:  a Relax-NG parser context
        !          4076:  * @def:  the choice definition
        !          4077:  *
        !          4078:  * Also used to find indeterministic pattern in choice
        !          4079:  */
        !          4080: static void
        !          4081: xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt,
        !          4082:                                  xmlRelaxNGDefinePtr def)
        !          4083: {
        !          4084:     xmlRelaxNGDefinePtr **list;
        !          4085:     xmlRelaxNGDefinePtr cur;
        !          4086:     int nbchild = 0, i, j, ret;
        !          4087:     int is_nullable = 0;
        !          4088:     int is_indeterminist = 0;
        !          4089:     xmlHashTablePtr triage = NULL;
        !          4090:     int is_triable = 1;
        !          4091: 
        !          4092:     if ((def == NULL) || (def->type != XML_RELAXNG_CHOICE))
        !          4093:         return;
        !          4094: 
        !          4095:     if (def->dflags & IS_PROCESSED)
        !          4096:         return;
        !          4097: 
        !          4098:     /*
        !          4099:      * Don't run that check in case of error. Infinite recursion
        !          4100:      * becomes possible.
        !          4101:      */
        !          4102:     if (ctxt->nbErrors != 0)
        !          4103:         return;
        !          4104: 
        !          4105:     is_nullable = xmlRelaxNGIsNullable(def);
        !          4106: 
        !          4107:     cur = def->content;
        !          4108:     while (cur != NULL) {
        !          4109:         nbchild++;
        !          4110:         cur = cur->next;
        !          4111:     }
        !          4112: 
        !          4113:     list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
        !          4114:                                               sizeof(xmlRelaxNGDefinePtr
        !          4115:                                                      *));
        !          4116:     if (list == NULL) {
        !          4117:         xmlRngPErrMemory(ctxt, "building choice\n");
        !          4118:         return;
        !          4119:     }
        !          4120:     i = 0;
        !          4121:     /*
        !          4122:      * a bit strong but safe
        !          4123:      */
        !          4124:     if (is_nullable == 0) {
        !          4125:         triage = xmlHashCreate(10);
        !          4126:     } else {
        !          4127:         is_triable = 0;
        !          4128:     }
        !          4129:     cur = def->content;
        !          4130:     while (cur != NULL) {
        !          4131:         list[i] = xmlRelaxNGGetElements(ctxt, cur, 0);
        !          4132:         if ((list[i] == NULL) || (list[i][0] == NULL)) {
        !          4133:             is_triable = 0;
        !          4134:         } else if (is_triable == 1) {
        !          4135:             xmlRelaxNGDefinePtr *tmp;
        !          4136:             int res;
        !          4137: 
        !          4138:             tmp = list[i];
        !          4139:             while ((*tmp != NULL) && (is_triable == 1)) {
        !          4140:                 if ((*tmp)->type == XML_RELAXNG_TEXT) {
        !          4141:                     res = xmlHashAddEntry2(triage,
        !          4142:                                            BAD_CAST "#text", NULL,
        !          4143:                                            (void *) cur);
        !          4144:                     if (res != 0)
        !          4145:                         is_triable = -1;
        !          4146:                 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
        !          4147:                            ((*tmp)->name != NULL)) {
        !          4148:                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
        !          4149:                         res = xmlHashAddEntry2(triage,
        !          4150:                                                (*tmp)->name, NULL,
        !          4151:                                                (void *) cur);
        !          4152:                     else
        !          4153:                         res = xmlHashAddEntry2(triage,
        !          4154:                                                (*tmp)->name, (*tmp)->ns,
        !          4155:                                                (void *) cur);
        !          4156:                     if (res != 0)
        !          4157:                         is_triable = -1;
        !          4158:                 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
        !          4159:                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
        !          4160:                         res = xmlHashAddEntry2(triage,
        !          4161:                                                BAD_CAST "#any", NULL,
        !          4162:                                                (void *) cur);
        !          4163:                     else
        !          4164:                         res = xmlHashAddEntry2(triage,
        !          4165:                                                BAD_CAST "#any", (*tmp)->ns,
        !          4166:                                                (void *) cur);
        !          4167:                     if (res != 0)
        !          4168:                         is_triable = -1;
        !          4169:                 } else {
        !          4170:                     is_triable = -1;
        !          4171:                 }
        !          4172:                 tmp++;
        !          4173:             }
        !          4174:         }
        !          4175:         i++;
        !          4176:         cur = cur->next;
        !          4177:     }
        !          4178: 
        !          4179:     for (i = 0; i < nbchild; i++) {
        !          4180:         if (list[i] == NULL)
        !          4181:             continue;
        !          4182:         for (j = 0; j < i; j++) {
        !          4183:             if (list[j] == NULL)
        !          4184:                 continue;
        !          4185:             ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
        !          4186:             if (ret == 0) {
        !          4187:                 is_indeterminist = 1;
        !          4188:             }
        !          4189:         }
        !          4190:     }
        !          4191:     for (i = 0; i < nbchild; i++) {
        !          4192:         if (list[i] != NULL)
        !          4193:             xmlFree(list[i]);
        !          4194:     }
        !          4195: 
        !          4196:     xmlFree(list);
        !          4197:     if (is_indeterminist) {
        !          4198:         def->dflags |= IS_INDETERMINIST;
        !          4199:     }
        !          4200:     if (is_triable == 1) {
        !          4201:         def->dflags |= IS_TRIABLE;
        !          4202:         def->data = triage;
        !          4203:     } else if (triage != NULL) {
        !          4204:         xmlHashFree(triage, NULL);
        !          4205:     }
        !          4206:     def->dflags |= IS_PROCESSED;
        !          4207: }
        !          4208: 
        !          4209: /**
        !          4210:  * xmlRelaxNGCheckGroupAttrs:
        !          4211:  * @ctxt:  a Relax-NG parser context
        !          4212:  * @def:  the group definition
        !          4213:  *
        !          4214:  * Detects violations of rule 7.3
        !          4215:  */
        !          4216: static void
        !          4217: xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,
        !          4218:                           xmlRelaxNGDefinePtr def)
        !          4219: {
        !          4220:     xmlRelaxNGDefinePtr **list;
        !          4221:     xmlRelaxNGDefinePtr cur;
        !          4222:     int nbchild = 0, i, j, ret;
        !          4223: 
        !          4224:     if ((def == NULL) ||
        !          4225:         ((def->type != XML_RELAXNG_GROUP) &&
        !          4226:          (def->type != XML_RELAXNG_ELEMENT)))
        !          4227:         return;
        !          4228: 
        !          4229:     if (def->dflags & IS_PROCESSED)
        !          4230:         return;
        !          4231: 
        !          4232:     /*
        !          4233:      * Don't run that check in case of error. Infinite recursion
        !          4234:      * becomes possible.
        !          4235:      */
        !          4236:     if (ctxt->nbErrors != 0)
        !          4237:         return;
        !          4238: 
        !          4239:     cur = def->attrs;
        !          4240:     while (cur != NULL) {
        !          4241:         nbchild++;
        !          4242:         cur = cur->next;
        !          4243:     }
        !          4244:     cur = def->content;
        !          4245:     while (cur != NULL) {
        !          4246:         nbchild++;
        !          4247:         cur = cur->next;
        !          4248:     }
        !          4249: 
        !          4250:     list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
        !          4251:                                               sizeof(xmlRelaxNGDefinePtr
        !          4252:                                                      *));
        !          4253:     if (list == NULL) {
        !          4254:         xmlRngPErrMemory(ctxt, "building group\n");
        !          4255:         return;
        !          4256:     }
        !          4257:     i = 0;
        !          4258:     cur = def->attrs;
        !          4259:     while (cur != NULL) {
        !          4260:         list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
        !          4261:         i++;
        !          4262:         cur = cur->next;
        !          4263:     }
        !          4264:     cur = def->content;
        !          4265:     while (cur != NULL) {
        !          4266:         list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
        !          4267:         i++;
        !          4268:         cur = cur->next;
        !          4269:     }
        !          4270: 
        !          4271:     for (i = 0; i < nbchild; i++) {
        !          4272:         if (list[i] == NULL)
        !          4273:             continue;
        !          4274:         for (j = 0; j < i; j++) {
        !          4275:             if (list[j] == NULL)
        !          4276:                 continue;
        !          4277:             ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
        !          4278:             if (ret == 0) {
        !          4279:                 xmlRngPErr(ctxt, def->node, XML_RNGP_GROUP_ATTR_CONFLICT,
        !          4280:                            "Attributes conflicts in group\n", NULL, NULL);
        !          4281:             }
        !          4282:         }
        !          4283:     }
        !          4284:     for (i = 0; i < nbchild; i++) {
        !          4285:         if (list[i] != NULL)
        !          4286:             xmlFree(list[i]);
        !          4287:     }
        !          4288: 
        !          4289:     xmlFree(list);
        !          4290:     def->dflags |= IS_PROCESSED;
        !          4291: }
        !          4292: 
        !          4293: /**
        !          4294:  * xmlRelaxNGComputeInterleaves:
        !          4295:  * @def:  the interleave definition
        !          4296:  * @ctxt:  a Relax-NG parser context
        !          4297:  * @name:  the definition name
        !          4298:  *
        !          4299:  * A lot of work for preprocessing interleave definitions
        !          4300:  * is potentially needed to get a decent execution speed at runtime
        !          4301:  *   - trying to get a total order on the element nodes generated
        !          4302:  *     by the interleaves, order the list of interleave definitions
        !          4303:  *     following that order.
        !          4304:  *   - if <text/> is used to handle mixed content, it is better to
        !          4305:  *     flag this in the define and simplify the runtime checking
        !          4306:  *     algorithm
        !          4307:  */
        !          4308: static void
        !          4309: xmlRelaxNGComputeInterleaves(xmlRelaxNGDefinePtr def,
        !          4310:                              xmlRelaxNGParserCtxtPtr ctxt,
        !          4311:                              xmlChar * name ATTRIBUTE_UNUSED)
        !          4312: {
        !          4313:     xmlRelaxNGDefinePtr cur, *tmp;
        !          4314: 
        !          4315:     xmlRelaxNGPartitionPtr partitions = NULL;
        !          4316:     xmlRelaxNGInterleaveGroupPtr *groups = NULL;
        !          4317:     xmlRelaxNGInterleaveGroupPtr group;
        !          4318:     int i, j, ret, res;
        !          4319:     int nbgroups = 0;
        !          4320:     int nbchild = 0;
        !          4321:     int is_mixed = 0;
        !          4322:     int is_determinist = 1;
        !          4323: 
        !          4324:     /*
        !          4325:      * Don't run that check in case of error. Infinite recursion
        !          4326:      * becomes possible.
        !          4327:      */
        !          4328:     if (ctxt->nbErrors != 0)
        !          4329:         return;
        !          4330: 
        !          4331: #ifdef DEBUG_INTERLEAVE
        !          4332:     xmlGenericError(xmlGenericErrorContext,
        !          4333:                     "xmlRelaxNGComputeInterleaves(%s)\n", name);
        !          4334: #endif
        !          4335:     cur = def->content;
        !          4336:     while (cur != NULL) {
        !          4337:         nbchild++;
        !          4338:         cur = cur->next;
        !          4339:     }
        !          4340: 
        !          4341: #ifdef DEBUG_INTERLEAVE
        !          4342:     xmlGenericError(xmlGenericErrorContext, "  %d child\n", nbchild);
        !          4343: #endif
        !          4344:     groups = (xmlRelaxNGInterleaveGroupPtr *)
        !          4345:         xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr));
        !          4346:     if (groups == NULL)
        !          4347:         goto error;
        !          4348:     cur = def->content;
        !          4349:     while (cur != NULL) {
        !          4350:         groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr)
        !          4351:             xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup));
        !          4352:         if (groups[nbgroups] == NULL)
        !          4353:             goto error;
        !          4354:         if (cur->type == XML_RELAXNG_TEXT)
        !          4355:             is_mixed++;
        !          4356:         groups[nbgroups]->rule = cur;
        !          4357:         groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 0);
        !          4358:         groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
        !          4359:         nbgroups++;
        !          4360:         cur = cur->next;
        !          4361:     }
        !          4362: #ifdef DEBUG_INTERLEAVE
        !          4363:     xmlGenericError(xmlGenericErrorContext, "  %d groups\n", nbgroups);
        !          4364: #endif
        !          4365: 
        !          4366:     /*
        !          4367:      * Let's check that all rules makes a partitions according to 7.4
        !          4368:      */
        !          4369:     partitions = (xmlRelaxNGPartitionPtr)
        !          4370:         xmlMalloc(sizeof(xmlRelaxNGPartition));
        !          4371:     if (partitions == NULL)
        !          4372:         goto error;
        !          4373:     memset(partitions, 0, sizeof(xmlRelaxNGPartition));
        !          4374:     partitions->nbgroups = nbgroups;
        !          4375:     partitions->triage = xmlHashCreate(nbgroups);
        !          4376:     for (i = 0; i < nbgroups; i++) {
        !          4377:         group = groups[i];
        !          4378:         for (j = i + 1; j < nbgroups; j++) {
        !          4379:             if (groups[j] == NULL)
        !          4380:                 continue;
        !          4381: 
        !          4382:             ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs,
        !          4383:                                                 groups[j]->defs);
        !          4384:             if (ret == 0) {
        !          4385:                 xmlRngPErr(ctxt, def->node, XML_RNGP_ELEM_TEXT_CONFLICT,
        !          4386:                            "Element or text conflicts in interleave\n",
        !          4387:                            NULL, NULL);
        !          4388:             }
        !          4389:             ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs,
        !          4390:                                                 groups[j]->attrs);
        !          4391:             if (ret == 0) {
        !          4392:                 xmlRngPErr(ctxt, def->node, XML_RNGP_ATTR_CONFLICT,
        !          4393:                            "Attributes conflicts in interleave\n", NULL,
        !          4394:                            NULL);
        !          4395:             }
        !          4396:         }
        !          4397:         tmp = group->defs;
        !          4398:         if ((tmp != NULL) && (*tmp != NULL)) {
        !          4399:             while (*tmp != NULL) {
        !          4400:                 if ((*tmp)->type == XML_RELAXNG_TEXT) {
        !          4401:                     res = xmlHashAddEntry2(partitions->triage,
        !          4402:                                            BAD_CAST "#text", NULL,
        !          4403:                                            (void *) (long) (i + 1));
        !          4404:                     if (res != 0)
        !          4405:                         is_determinist = -1;
        !          4406:                 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
        !          4407:                            ((*tmp)->name != NULL)) {
        !          4408:                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
        !          4409:                         res = xmlHashAddEntry2(partitions->triage,
        !          4410:                                                (*tmp)->name, NULL,
        !          4411:                                                (void *) (long) (i + 1));
        !          4412:                     else
        !          4413:                         res = xmlHashAddEntry2(partitions->triage,
        !          4414:                                                (*tmp)->name, (*tmp)->ns,
        !          4415:                                                (void *) (long) (i + 1));
        !          4416:                     if (res != 0)
        !          4417:                         is_determinist = -1;
        !          4418:                 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
        !          4419:                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
        !          4420:                         res = xmlHashAddEntry2(partitions->triage,
        !          4421:                                                BAD_CAST "#any", NULL,
        !          4422:                                                (void *) (long) (i + 1));
        !          4423:                     else
        !          4424:                         res = xmlHashAddEntry2(partitions->triage,
        !          4425:                                                BAD_CAST "#any", (*tmp)->ns,
        !          4426:                                                (void *) (long) (i + 1));
        !          4427:                     if ((*tmp)->nameClass != NULL)
        !          4428:                         is_determinist = 2;
        !          4429:                     if (res != 0)
        !          4430:                         is_determinist = -1;
        !          4431:                 } else {
        !          4432:                     is_determinist = -1;
        !          4433:                 }
        !          4434:                 tmp++;
        !          4435:             }
        !          4436:         } else {
        !          4437:             is_determinist = 0;
        !          4438:         }
        !          4439:     }
        !          4440:     partitions->groups = groups;
        !          4441: 
        !          4442:     /*
        !          4443:      * and save the partition list back in the def
        !          4444:      */
        !          4445:     def->data = partitions;
        !          4446:     if (is_mixed != 0)
        !          4447:         def->dflags |= IS_MIXED;
        !          4448:     if (is_determinist == 1)
        !          4449:         partitions->flags = IS_DETERMINIST;
        !          4450:     if (is_determinist == 2)
        !          4451:         partitions->flags = IS_DETERMINIST | IS_NEEDCHECK;
        !          4452:     return;
        !          4453: 
        !          4454:   error:
        !          4455:     xmlRngPErrMemory(ctxt, "in interleave computation\n");
        !          4456:     if (groups != NULL) {
        !          4457:         for (i = 0; i < nbgroups; i++)
        !          4458:             if (groups[i] != NULL) {
        !          4459:                 if (groups[i]->defs != NULL)
        !          4460:                     xmlFree(groups[i]->defs);
        !          4461:                 xmlFree(groups[i]);
        !          4462:             }
        !          4463:         xmlFree(groups);
        !          4464:     }
        !          4465:     xmlRelaxNGFreePartition(partitions);
        !          4466: }
        !          4467: 
        !          4468: /**
        !          4469:  * xmlRelaxNGParseInterleave:
        !          4470:  * @ctxt:  a Relax-NG parser context
        !          4471:  * @node:  the data node.
        !          4472:  *
        !          4473:  * parse the content of a RelaxNG interleave node.
        !          4474:  *
        !          4475:  * Returns the definition pointer or NULL in case of error
        !          4476:  */
        !          4477: static xmlRelaxNGDefinePtr
        !          4478: xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          4479: {
        !          4480:     xmlRelaxNGDefinePtr def = NULL;
        !          4481:     xmlRelaxNGDefinePtr last = NULL, cur;
        !          4482:     xmlNodePtr child;
        !          4483: 
        !          4484:     def = xmlRelaxNGNewDefine(ctxt, node);
        !          4485:     if (def == NULL) {
        !          4486:         return (NULL);
        !          4487:     }
        !          4488:     def->type = XML_RELAXNG_INTERLEAVE;
        !          4489: 
        !          4490:     if (ctxt->interleaves == NULL)
        !          4491:         ctxt->interleaves = xmlHashCreate(10);
        !          4492:     if (ctxt->interleaves == NULL) {
        !          4493:         xmlRngPErrMemory(ctxt, "create interleaves\n");
        !          4494:     } else {
        !          4495:         char name[32];
        !          4496: 
        !          4497:         snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++);
        !          4498:         if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) {
        !          4499:             xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_ADD,
        !          4500:                        "Failed to add %s to hash table\n",
        !          4501:                       (const xmlChar *) name, NULL);
        !          4502:         }
        !          4503:     }
        !          4504:     child = node->children;
        !          4505:     if (child == NULL) {
        !          4506:         xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_NO_CONTENT,
        !          4507:                    "Element interleave is empty\n", NULL, NULL);
        !          4508:     }
        !          4509:     while (child != NULL) {
        !          4510:         if (IS_RELAXNG(child, "element")) {
        !          4511:             cur = xmlRelaxNGParseElement(ctxt, child);
        !          4512:         } else {
        !          4513:             cur = xmlRelaxNGParsePattern(ctxt, child);
        !          4514:         }
        !          4515:         if (cur != NULL) {
        !          4516:             cur->parent = def;
        !          4517:             if (last == NULL) {
        !          4518:                 def->content = last = cur;
        !          4519:             } else {
        !          4520:                 last->next = cur;
        !          4521:                 last = cur;
        !          4522:             }
        !          4523:         }
        !          4524:         child = child->next;
        !          4525:     }
        !          4526: 
        !          4527:     return (def);
        !          4528: }
        !          4529: 
        !          4530: /**
        !          4531:  * xmlRelaxNGParseInclude:
        !          4532:  * @ctxt:  a Relax-NG parser context
        !          4533:  * @node:  the include node
        !          4534:  *
        !          4535:  * Integrate the content of an include node in the current grammar
        !          4536:  *
        !          4537:  * Returns 0 in case of success or -1 in case of error
        !          4538:  */
        !          4539: static int
        !          4540: xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          4541: {
        !          4542:     xmlRelaxNGIncludePtr incl;
        !          4543:     xmlNodePtr root;
        !          4544:     int ret = 0, tmp;
        !          4545: 
        !          4546:     incl = node->psvi;
        !          4547:     if (incl == NULL) {
        !          4548:         xmlRngPErr(ctxt, node, XML_RNGP_INCLUDE_EMPTY,
        !          4549:                    "Include node has no data\n", NULL, NULL);
        !          4550:         return (-1);
        !          4551:     }
        !          4552:     root = xmlDocGetRootElement(incl->doc);
        !          4553:     if (root == NULL) {
        !          4554:         xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, "Include document is empty\n",
        !          4555:                    NULL, NULL);
        !          4556:         return (-1);
        !          4557:     }
        !          4558:     if (!xmlStrEqual(root->name, BAD_CAST "grammar")) {
        !          4559:         xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
        !          4560:                    "Include document root is not a grammar\n", NULL, NULL);
        !          4561:         return (-1);
        !          4562:     }
        !          4563: 
        !          4564:     /*
        !          4565:      * Merge the definition from both the include and the internal list
        !          4566:      */
        !          4567:     if (root->children != NULL) {
        !          4568:         tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children);
        !          4569:         if (tmp != 0)
        !          4570:             ret = -1;
        !          4571:     }
        !          4572:     if (node->children != NULL) {
        !          4573:         tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children);
        !          4574:         if (tmp != 0)
        !          4575:             ret = -1;
        !          4576:     }
        !          4577:     return (ret);
        !          4578: }
        !          4579: 
        !          4580: /**
        !          4581:  * xmlRelaxNGParseDefine:
        !          4582:  * @ctxt:  a Relax-NG parser context
        !          4583:  * @node:  the define node
        !          4584:  *
        !          4585:  * parse the content of a RelaxNG define element node.
        !          4586:  *
        !          4587:  * Returns 0 in case of success or -1 in case of error
        !          4588:  */
        !          4589: static int
        !          4590: xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          4591: {
        !          4592:     xmlChar *name;
        !          4593:     int ret = 0, tmp;
        !          4594:     xmlRelaxNGDefinePtr def;
        !          4595:     const xmlChar *olddefine;
        !          4596: 
        !          4597:     name = xmlGetProp(node, BAD_CAST "name");
        !          4598:     if (name == NULL) {
        !          4599:         xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_NAME_MISSING,
        !          4600:                    "define has no name\n", NULL, NULL);
        !          4601:     } else {
        !          4602:         xmlRelaxNGNormExtSpace(name);
        !          4603:         if (xmlValidateNCName(name, 0)) {
        !          4604:             xmlRngPErr(ctxt, node, XML_RNGP_INVALID_DEFINE_NAME,
        !          4605:                        "define name '%s' is not an NCName\n", name, NULL);
        !          4606:         }
        !          4607:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4608:         if (def == NULL) {
        !          4609:             xmlFree(name);
        !          4610:             return (-1);
        !          4611:         }
        !          4612:         def->type = XML_RELAXNG_DEF;
        !          4613:         def->name = name;
        !          4614:         if (node->children == NULL) {
        !          4615:             xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_EMPTY,
        !          4616:                        "define has no children\n", NULL, NULL);
        !          4617:         } else {
        !          4618:             olddefine = ctxt->define;
        !          4619:             ctxt->define = name;
        !          4620:             def->content =
        !          4621:                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
        !          4622:             ctxt->define = olddefine;
        !          4623:         }
        !          4624:         if (ctxt->grammar->defs == NULL)
        !          4625:             ctxt->grammar->defs = xmlHashCreate(10);
        !          4626:         if (ctxt->grammar->defs == NULL) {
        !          4627:             xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
        !          4628:                        "Could not create definition hash\n", NULL, NULL);
        !          4629:             ret = -1;
        !          4630:         } else {
        !          4631:             tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
        !          4632:             if (tmp < 0) {
        !          4633:                 xmlRelaxNGDefinePtr prev;
        !          4634: 
        !          4635:                 prev = xmlHashLookup(ctxt->grammar->defs, name);
        !          4636:                 if (prev == NULL) {
        !          4637:                     xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
        !          4638:                                "Internal error on define aggregation of %s\n",
        !          4639:                                name, NULL);
        !          4640:                     ret = -1;
        !          4641:                 } else {
        !          4642:                     while (prev->nextHash != NULL)
        !          4643:                         prev = prev->nextHash;
        !          4644:                     prev->nextHash = def;
        !          4645:                 }
        !          4646:             }
        !          4647:         }
        !          4648:     }
        !          4649:     return (ret);
        !          4650: }
        !          4651: 
        !          4652: /**
        !          4653:  * xmlRelaxNGParseImportRef:
        !          4654:  * @payload: the parser context
        !          4655:  * @data: the current grammar
        !          4656:  * @name: the reference name
        !          4657:  *
        !          4658:  * Import import one references into the current grammar
        !          4659:  */
        !          4660: static void
        !          4661: xmlRelaxNGParseImportRef(void *payload, void *data, xmlChar *name) {
        !          4662:     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
        !          4663:     xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
        !          4664:     int tmp;
        !          4665: 
        !          4666:     def->dflags |= IS_EXTERNAL_REF;
        !          4667: 
        !          4668:     tmp = xmlHashAddEntry(ctxt->grammar->refs, name, def);
        !          4669:     if (tmp < 0) {
        !          4670:         xmlRelaxNGDefinePtr prev;
        !          4671: 
        !          4672:         prev = (xmlRelaxNGDefinePtr)
        !          4673:             xmlHashLookup(ctxt->grammar->refs, def->name);
        !          4674:         if (prev == NULL) {
        !          4675:             if (def->name != NULL) {
        !          4676:                 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
        !          4677:                            "Error refs definitions '%s'\n",
        !          4678:                            def->name, NULL);
        !          4679:             } else {
        !          4680:                 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
        !          4681:                            "Error refs definitions\n",
        !          4682:                            NULL, NULL);
        !          4683:             }
        !          4684:         } else {
        !          4685:             def->nextHash = prev->nextHash;
        !          4686:             prev->nextHash = def;
        !          4687:         }
        !          4688:     }
        !          4689: }
        !          4690: 
        !          4691: /**
        !          4692:  * xmlRelaxNGParseImportRefs:
        !          4693:  * @ctxt: the parser context
        !          4694:  * @grammar: the sub grammar
        !          4695:  *
        !          4696:  * Import references from the subgrammar into the current grammar
        !          4697:  *
        !          4698:  * Returns 0 in case of success, -1 in case of failure
        !          4699:  */
        !          4700: static int
        !          4701: xmlRelaxNGParseImportRefs(xmlRelaxNGParserCtxtPtr ctxt,
        !          4702:                           xmlRelaxNGGrammarPtr grammar) {
        !          4703:     if ((ctxt == NULL) || (grammar == NULL) || (ctxt->grammar == NULL))
        !          4704:         return(-1);
        !          4705:     if (grammar->refs == NULL)
        !          4706:         return(0);
        !          4707:     if (ctxt->grammar->refs == NULL)
        !          4708:         ctxt->grammar->refs = xmlHashCreate(10);
        !          4709:     if (ctxt->grammar->refs == NULL) {
        !          4710:         xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
        !          4711:                    "Could not create references hash\n", NULL, NULL);
        !          4712:         return(-1);
        !          4713:     }
        !          4714:     xmlHashScan(grammar->refs, xmlRelaxNGParseImportRef, ctxt);
        !          4715:     return(0);
        !          4716: }
        !          4717: 
        !          4718: /**
        !          4719:  * xmlRelaxNGProcessExternalRef:
        !          4720:  * @ctxt: the parser context
        !          4721:  * @node:  the externlRef node
        !          4722:  *
        !          4723:  * Process and compile an externlRef node
        !          4724:  *
        !          4725:  * Returns the xmlRelaxNGDefinePtr or NULL in case of error
        !          4726:  */
        !          4727: static xmlRelaxNGDefinePtr
        !          4728: xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          4729: {
        !          4730:     xmlRelaxNGDocumentPtr docu;
        !          4731:     xmlNodePtr root, tmp;
        !          4732:     xmlChar *ns;
        !          4733:     int newNs = 0, oldflags;
        !          4734:     xmlRelaxNGDefinePtr def;
        !          4735: 
        !          4736:     docu = node->psvi;
        !          4737:     if (docu != NULL) {
        !          4738:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4739:         if (def == NULL)
        !          4740:             return (NULL);
        !          4741:         def->type = XML_RELAXNG_EXTERNALREF;
        !          4742: 
        !          4743:         if (docu->content == NULL) {
        !          4744:             /*
        !          4745:              * Then do the parsing for good
        !          4746:              */
        !          4747:             root = xmlDocGetRootElement(docu->doc);
        !          4748:             if (root == NULL) {
        !          4749:                 xmlRngPErr(ctxt, node, XML_RNGP_EXTERNALREF_EMTPY,
        !          4750:                            "xmlRelaxNGParse: %s is empty\n", ctxt->URL,
        !          4751:                            NULL);
        !          4752:                 return (NULL);
        !          4753:             }
        !          4754:             /*
        !          4755:              * ns transmission rules
        !          4756:              */
        !          4757:             ns = xmlGetProp(root, BAD_CAST "ns");
        !          4758:             if (ns == NULL) {
        !          4759:                 tmp = node;
        !          4760:                 while ((tmp != NULL) && (tmp->type == XML_ELEMENT_NODE)) {
        !          4761:                     ns = xmlGetProp(tmp, BAD_CAST "ns");
        !          4762:                     if (ns != NULL) {
        !          4763:                         break;
        !          4764:                     }
        !          4765:                     tmp = tmp->parent;
        !          4766:                 }
        !          4767:                 if (ns != NULL) {
        !          4768:                     xmlSetProp(root, BAD_CAST "ns", ns);
        !          4769:                     newNs = 1;
        !          4770:                     xmlFree(ns);
        !          4771:                 }
        !          4772:             } else {
        !          4773:                 xmlFree(ns);
        !          4774:             }
        !          4775: 
        !          4776:             /*
        !          4777:              * Parsing to get a precompiled schemas.
        !          4778:              */
        !          4779:             oldflags = ctxt->flags;
        !          4780:             ctxt->flags |= XML_RELAXNG_IN_EXTERNALREF;
        !          4781:             docu->schema = xmlRelaxNGParseDocument(ctxt, root);
        !          4782:             ctxt->flags = oldflags;
        !          4783:             if ((docu->schema != NULL) &&
        !          4784:                 (docu->schema->topgrammar != NULL)) {
        !          4785:                 docu->content = docu->schema->topgrammar->start;
        !          4786:                 if (docu->schema->topgrammar->refs)
        !          4787:                     xmlRelaxNGParseImportRefs(ctxt, docu->schema->topgrammar);
        !          4788:             }
        !          4789: 
        !          4790:             /*
        !          4791:              * the externalRef may be reused in a different ns context
        !          4792:              */
        !          4793:             if (newNs == 1) {
        !          4794:                 xmlUnsetProp(root, BAD_CAST "ns");
        !          4795:             }
        !          4796:         }
        !          4797:         def->content = docu->content;
        !          4798:     } else {
        !          4799:         def = NULL;
        !          4800:     }
        !          4801:     return (def);
        !          4802: }
        !          4803: 
        !          4804: /**
        !          4805:  * xmlRelaxNGParsePattern:
        !          4806:  * @ctxt:  a Relax-NG parser context
        !          4807:  * @node:  the pattern node.
        !          4808:  *
        !          4809:  * parse the content of a RelaxNG pattern node.
        !          4810:  *
        !          4811:  * Returns the definition pointer or NULL in case of error or if no
        !          4812:  *     pattern is generated.
        !          4813:  */
        !          4814: static xmlRelaxNGDefinePtr
        !          4815: xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          4816: {
        !          4817:     xmlRelaxNGDefinePtr def = NULL;
        !          4818: 
        !          4819:     if (node == NULL) {
        !          4820:         return (NULL);
        !          4821:     }
        !          4822:     if (IS_RELAXNG(node, "element")) {
        !          4823:         def = xmlRelaxNGParseElement(ctxt, node);
        !          4824:     } else if (IS_RELAXNG(node, "attribute")) {
        !          4825:         def = xmlRelaxNGParseAttribute(ctxt, node);
        !          4826:     } else if (IS_RELAXNG(node, "empty")) {
        !          4827:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4828:         if (def == NULL)
        !          4829:             return (NULL);
        !          4830:         def->type = XML_RELAXNG_EMPTY;
        !          4831:         if (node->children != NULL) {
        !          4832:             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_NOT_EMPTY,
        !          4833:                        "empty: had a child node\n", NULL, NULL);
        !          4834:         }
        !          4835:     } else if (IS_RELAXNG(node, "text")) {
        !          4836:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4837:         if (def == NULL)
        !          4838:             return (NULL);
        !          4839:         def->type = XML_RELAXNG_TEXT;
        !          4840:         if (node->children != NULL) {
        !          4841:             xmlRngPErr(ctxt, node, XML_RNGP_TEXT_HAS_CHILD,
        !          4842:                        "text: had a child node\n", NULL, NULL);
        !          4843:         }
        !          4844:     } else if (IS_RELAXNG(node, "zeroOrMore")) {
        !          4845:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4846:         if (def == NULL)
        !          4847:             return (NULL);
        !          4848:         def->type = XML_RELAXNG_ZEROORMORE;
        !          4849:         if (node->children == NULL) {
        !          4850:             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
        !          4851:                        "Element %s is empty\n", node->name, NULL);
        !          4852:         } else {
        !          4853:             def->content =
        !          4854:                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
        !          4855:         }
        !          4856:     } else if (IS_RELAXNG(node, "oneOrMore")) {
        !          4857:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4858:         if (def == NULL)
        !          4859:             return (NULL);
        !          4860:         def->type = XML_RELAXNG_ONEORMORE;
        !          4861:         if (node->children == NULL) {
        !          4862:             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
        !          4863:                        "Element %s is empty\n", node->name, NULL);
        !          4864:         } else {
        !          4865:             def->content =
        !          4866:                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
        !          4867:         }
        !          4868:     } else if (IS_RELAXNG(node, "optional")) {
        !          4869:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4870:         if (def == NULL)
        !          4871:             return (NULL);
        !          4872:         def->type = XML_RELAXNG_OPTIONAL;
        !          4873:         if (node->children == NULL) {
        !          4874:             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
        !          4875:                        "Element %s is empty\n", node->name, NULL);
        !          4876:         } else {
        !          4877:             def->content =
        !          4878:                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
        !          4879:         }
        !          4880:     } else if (IS_RELAXNG(node, "choice")) {
        !          4881:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4882:         if (def == NULL)
        !          4883:             return (NULL);
        !          4884:         def->type = XML_RELAXNG_CHOICE;
        !          4885:         if (node->children == NULL) {
        !          4886:             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
        !          4887:                        "Element %s is empty\n", node->name, NULL);
        !          4888:         } else {
        !          4889:             def->content =
        !          4890:                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
        !          4891:         }
        !          4892:     } else if (IS_RELAXNG(node, "group")) {
        !          4893:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4894:         if (def == NULL)
        !          4895:             return (NULL);
        !          4896:         def->type = XML_RELAXNG_GROUP;
        !          4897:         if (node->children == NULL) {
        !          4898:             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
        !          4899:                        "Element %s is empty\n", node->name, NULL);
        !          4900:         } else {
        !          4901:             def->content =
        !          4902:                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
        !          4903:         }
        !          4904:     } else if (IS_RELAXNG(node, "ref")) {
        !          4905:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4906:         if (def == NULL)
        !          4907:             return (NULL);
        !          4908:         def->type = XML_RELAXNG_REF;
        !          4909:         def->name = xmlGetProp(node, BAD_CAST "name");
        !          4910:         if (def->name == NULL) {
        !          4911:             xmlRngPErr(ctxt, node, XML_RNGP_REF_NO_NAME, "ref has no name\n",
        !          4912:                        NULL, NULL);
        !          4913:         } else {
        !          4914:             xmlRelaxNGNormExtSpace(def->name);
        !          4915:             if (xmlValidateNCName(def->name, 0)) {
        !          4916:                 xmlRngPErr(ctxt, node, XML_RNGP_REF_NAME_INVALID,
        !          4917:                            "ref name '%s' is not an NCName\n", def->name,
        !          4918:                            NULL);
        !          4919:             }
        !          4920:         }
        !          4921:         if (node->children != NULL) {
        !          4922:             xmlRngPErr(ctxt, node, XML_RNGP_REF_NOT_EMPTY, "ref is not empty\n",
        !          4923:                        NULL, NULL);
        !          4924:         }
        !          4925:         if (ctxt->grammar->refs == NULL)
        !          4926:             ctxt->grammar->refs = xmlHashCreate(10);
        !          4927:         if (ctxt->grammar->refs == NULL) {
        !          4928:             xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
        !          4929:                        "Could not create references hash\n", NULL, NULL);
        !          4930:             def = NULL;
        !          4931:         } else {
        !          4932:             int tmp;
        !          4933: 
        !          4934:             tmp = xmlHashAddEntry(ctxt->grammar->refs, def->name, def);
        !          4935:             if (tmp < 0) {
        !          4936:                 xmlRelaxNGDefinePtr prev;
        !          4937: 
        !          4938:                 prev = (xmlRelaxNGDefinePtr)
        !          4939:                     xmlHashLookup(ctxt->grammar->refs, def->name);
        !          4940:                 if (prev == NULL) {
        !          4941:                     if (def->name != NULL) {
        !          4942:                        xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
        !          4943:                                   "Error refs definitions '%s'\n",
        !          4944:                                   def->name, NULL);
        !          4945:                     } else {
        !          4946:                        xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
        !          4947:                                   "Error refs definitions\n",
        !          4948:                                   NULL, NULL);
        !          4949:                     }
        !          4950:                     def = NULL;
        !          4951:                 } else {
        !          4952:                     def->nextHash = prev->nextHash;
        !          4953:                     prev->nextHash = def;
        !          4954:                 }
        !          4955:             }
        !          4956:         }
        !          4957:     } else if (IS_RELAXNG(node, "data")) {
        !          4958:         def = xmlRelaxNGParseData(ctxt, node);
        !          4959:     } else if (IS_RELAXNG(node, "value")) {
        !          4960:         def = xmlRelaxNGParseValue(ctxt, node);
        !          4961:     } else if (IS_RELAXNG(node, "list")) {
        !          4962:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4963:         if (def == NULL)
        !          4964:             return (NULL);
        !          4965:         def->type = XML_RELAXNG_LIST;
        !          4966:         if (node->children == NULL) {
        !          4967:             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
        !          4968:                        "Element %s is empty\n", node->name, NULL);
        !          4969:         } else {
        !          4970:             def->content =
        !          4971:                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
        !          4972:         }
        !          4973:     } else if (IS_RELAXNG(node, "interleave")) {
        !          4974:         def = xmlRelaxNGParseInterleave(ctxt, node);
        !          4975:     } else if (IS_RELAXNG(node, "externalRef")) {
        !          4976:         def = xmlRelaxNGProcessExternalRef(ctxt, node);
        !          4977:     } else if (IS_RELAXNG(node, "notAllowed")) {
        !          4978:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          4979:         if (def == NULL)
        !          4980:             return (NULL);
        !          4981:         def->type = XML_RELAXNG_NOT_ALLOWED;
        !          4982:         if (node->children != NULL) {
        !          4983:             xmlRngPErr(ctxt, node, XML_RNGP_NOTALLOWED_NOT_EMPTY,
        !          4984:                        "xmlRelaxNGParse: notAllowed element is not empty\n",
        !          4985:                        NULL, NULL);
        !          4986:         }
        !          4987:     } else if (IS_RELAXNG(node, "grammar")) {
        !          4988:         xmlRelaxNGGrammarPtr grammar, old;
        !          4989:         xmlRelaxNGGrammarPtr oldparent;
        !          4990: 
        !          4991: #ifdef DEBUG_GRAMMAR
        !          4992:         xmlGenericError(xmlGenericErrorContext,
        !          4993:                         "Found <grammar> pattern\n");
        !          4994: #endif
        !          4995: 
        !          4996:         oldparent = ctxt->parentgrammar;
        !          4997:         old = ctxt->grammar;
        !          4998:         ctxt->parentgrammar = old;
        !          4999:         grammar = xmlRelaxNGParseGrammar(ctxt, node->children);
        !          5000:         if (old != NULL) {
        !          5001:             ctxt->grammar = old;
        !          5002:             ctxt->parentgrammar = oldparent;
        !          5003: #if 0
        !          5004:             if (grammar != NULL) {
        !          5005:                 grammar->next = old->next;
        !          5006:                 old->next = grammar;
        !          5007:             }
        !          5008: #endif
        !          5009:         }
        !          5010:         if (grammar != NULL)
        !          5011:             def = grammar->start;
        !          5012:         else
        !          5013:             def = NULL;
        !          5014:     } else if (IS_RELAXNG(node, "parentRef")) {
        !          5015:         if (ctxt->parentgrammar == NULL) {
        !          5016:             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_PARENT,
        !          5017:                        "Use of parentRef without a parent grammar\n", NULL,
        !          5018:                        NULL);
        !          5019:             return (NULL);
        !          5020:         }
        !          5021:         def = xmlRelaxNGNewDefine(ctxt, node);
        !          5022:         if (def == NULL)
        !          5023:             return (NULL);
        !          5024:         def->type = XML_RELAXNG_PARENTREF;
        !          5025:         def->name = xmlGetProp(node, BAD_CAST "name");
        !          5026:         if (def->name == NULL) {
        !          5027:             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_NAME,
        !          5028:                        "parentRef has no name\n", NULL, NULL);
        !          5029:         } else {
        !          5030:             xmlRelaxNGNormExtSpace(def->name);
        !          5031:             if (xmlValidateNCName(def->name, 0)) {
        !          5032:                 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NAME_INVALID,
        !          5033:                            "parentRef name '%s' is not an NCName\n",
        !          5034:                            def->name, NULL);
        !          5035:             }
        !          5036:         }
        !          5037:         if (node->children != NULL) {
        !          5038:             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NOT_EMPTY,
        !          5039:                        "parentRef is not empty\n", NULL, NULL);
        !          5040:         }
        !          5041:         if (ctxt->parentgrammar->refs == NULL)
        !          5042:             ctxt->parentgrammar->refs = xmlHashCreate(10);
        !          5043:         if (ctxt->parentgrammar->refs == NULL) {
        !          5044:             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
        !          5045:                        "Could not create references hash\n", NULL, NULL);
        !          5046:             def = NULL;
        !          5047:         } else if (def->name != NULL) {
        !          5048:             int tmp;
        !          5049: 
        !          5050:             tmp =
        !          5051:                 xmlHashAddEntry(ctxt->parentgrammar->refs, def->name, def);
        !          5052:             if (tmp < 0) {
        !          5053:                 xmlRelaxNGDefinePtr prev;
        !          5054: 
        !          5055:                 prev = (xmlRelaxNGDefinePtr)
        !          5056:                     xmlHashLookup(ctxt->parentgrammar->refs, def->name);
        !          5057:                 if (prev == NULL) {
        !          5058:                     xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
        !          5059:                                "Internal error parentRef definitions '%s'\n",
        !          5060:                                def->name, NULL);
        !          5061:                     def = NULL;
        !          5062:                 } else {
        !          5063:                     def->nextHash = prev->nextHash;
        !          5064:                     prev->nextHash = def;
        !          5065:                 }
        !          5066:             }
        !          5067:         }
        !          5068:     } else if (IS_RELAXNG(node, "mixed")) {
        !          5069:         if (node->children == NULL) {
        !          5070:             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, "Mixed is empty\n",
        !          5071:                        NULL, NULL);
        !          5072:             def = NULL;
        !          5073:         } else {
        !          5074:             def = xmlRelaxNGParseInterleave(ctxt, node);
        !          5075:             if (def != NULL) {
        !          5076:                 xmlRelaxNGDefinePtr tmp;
        !          5077: 
        !          5078:                 if ((def->content != NULL) && (def->content->next != NULL)) {
        !          5079:                     tmp = xmlRelaxNGNewDefine(ctxt, node);
        !          5080:                     if (tmp != NULL) {
        !          5081:                         tmp->type = XML_RELAXNG_GROUP;
        !          5082:                         tmp->content = def->content;
        !          5083:                         def->content = tmp;
        !          5084:                     }
        !          5085:                 }
        !          5086: 
        !          5087:                 tmp = xmlRelaxNGNewDefine(ctxt, node);
        !          5088:                 if (tmp == NULL)
        !          5089:                     return (def);
        !          5090:                 tmp->type = XML_RELAXNG_TEXT;
        !          5091:                 tmp->next = def->content;
        !          5092:                 def->content = tmp;
        !          5093:             }
        !          5094:         }
        !          5095:     } else {
        !          5096:         xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_CONSTRUCT,
        !          5097:                    "Unexpected node %s is not a pattern\n", node->name,
        !          5098:                    NULL);
        !          5099:         def = NULL;
        !          5100:     }
        !          5101:     return (def);
        !          5102: }
        !          5103: 
        !          5104: /**
        !          5105:  * xmlRelaxNGParseAttribute:
        !          5106:  * @ctxt:  a Relax-NG parser context
        !          5107:  * @node:  the element node
        !          5108:  *
        !          5109:  * parse the content of a RelaxNG attribute node.
        !          5110:  *
        !          5111:  * Returns the definition pointer or NULL in case of error.
        !          5112:  */
        !          5113: static xmlRelaxNGDefinePtr
        !          5114: xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          5115: {
        !          5116:     xmlRelaxNGDefinePtr ret, cur;
        !          5117:     xmlNodePtr child;
        !          5118:     int old_flags;
        !          5119: 
        !          5120:     ret = xmlRelaxNGNewDefine(ctxt, node);
        !          5121:     if (ret == NULL)
        !          5122:         return (NULL);
        !          5123:     ret->type = XML_RELAXNG_ATTRIBUTE;
        !          5124:     ret->parent = ctxt->def;
        !          5125:     child = node->children;
        !          5126:     if (child == NULL) {
        !          5127:         xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_EMPTY,
        !          5128:                    "xmlRelaxNGParseattribute: attribute has no children\n",
        !          5129:                    NULL, NULL);
        !          5130:         return (ret);
        !          5131:     }
        !          5132:     old_flags = ctxt->flags;
        !          5133:     ctxt->flags |= XML_RELAXNG_IN_ATTRIBUTE;
        !          5134:     cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
        !          5135:     if (cur != NULL)
        !          5136:         child = child->next;
        !          5137: 
        !          5138:     if (child != NULL) {
        !          5139:         cur = xmlRelaxNGParsePattern(ctxt, child);
        !          5140:         if (cur != NULL) {
        !          5141:             switch (cur->type) {
        !          5142:                 case XML_RELAXNG_EMPTY:
        !          5143:                 case XML_RELAXNG_NOT_ALLOWED:
        !          5144:                 case XML_RELAXNG_TEXT:
        !          5145:                 case XML_RELAXNG_ELEMENT:
        !          5146:                 case XML_RELAXNG_DATATYPE:
        !          5147:                 case XML_RELAXNG_VALUE:
        !          5148:                 case XML_RELAXNG_LIST:
        !          5149:                 case XML_RELAXNG_REF:
        !          5150:                 case XML_RELAXNG_PARENTREF:
        !          5151:                 case XML_RELAXNG_EXTERNALREF:
        !          5152:                 case XML_RELAXNG_DEF:
        !          5153:                 case XML_RELAXNG_ONEORMORE:
        !          5154:                 case XML_RELAXNG_ZEROORMORE:
        !          5155:                 case XML_RELAXNG_OPTIONAL:
        !          5156:                 case XML_RELAXNG_CHOICE:
        !          5157:                 case XML_RELAXNG_GROUP:
        !          5158:                 case XML_RELAXNG_INTERLEAVE:
        !          5159:                 case XML_RELAXNG_ATTRIBUTE:
        !          5160:                     ret->content = cur;
        !          5161:                     cur->parent = ret;
        !          5162:                     break;
        !          5163:                 case XML_RELAXNG_START:
        !          5164:                 case XML_RELAXNG_PARAM:
        !          5165:                 case XML_RELAXNG_EXCEPT:
        !          5166:                     xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CONTENT,
        !          5167:                                "attribute has invalid content\n", NULL,
        !          5168:                                NULL);
        !          5169:                     break;
        !          5170:                 case XML_RELAXNG_NOOP:
        !          5171:                     xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_NOOP,
        !          5172:                                "RNG Internal error, noop found in attribute\n",
        !          5173:                                NULL, NULL);
        !          5174:                     break;
        !          5175:             }
        !          5176:         }
        !          5177:         child = child->next;
        !          5178:     }
        !          5179:     if (child != NULL) {
        !          5180:         xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CHILDREN,
        !          5181:                    "attribute has multiple children\n", NULL, NULL);
        !          5182:     }
        !          5183:     ctxt->flags = old_flags;
        !          5184:     return (ret);
        !          5185: }
        !          5186: 
        !          5187: /**
        !          5188:  * xmlRelaxNGParseExceptNameClass:
        !          5189:  * @ctxt:  a Relax-NG parser context
        !          5190:  * @node:  the except node
        !          5191:  * @attr:  1 if within an attribute, 0 if within an element
        !          5192:  *
        !          5193:  * parse the content of a RelaxNG nameClass node.
        !          5194:  *
        !          5195:  * Returns the definition pointer or NULL in case of error.
        !          5196:  */
        !          5197: static xmlRelaxNGDefinePtr
        !          5198: xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt,
        !          5199:                                xmlNodePtr node, int attr)
        !          5200: {
        !          5201:     xmlRelaxNGDefinePtr ret, cur, last = NULL;
        !          5202:     xmlNodePtr child;
        !          5203: 
        !          5204:     if (!IS_RELAXNG(node, "except")) {
        !          5205:         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MISSING,
        !          5206:                    "Expecting an except node\n", NULL, NULL);
        !          5207:         return (NULL);
        !          5208:     }
        !          5209:     if (node->next != NULL) {
        !          5210:         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MULTIPLE,
        !          5211:                    "exceptNameClass allows only a single except node\n",
        !          5212:                    NULL, NULL);
        !          5213:     }
        !          5214:     if (node->children == NULL) {
        !          5215:         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_EMPTY, "except has no content\n",
        !          5216:                    NULL, NULL);
        !          5217:         return (NULL);
        !          5218:     }
        !          5219: 
        !          5220:     ret = xmlRelaxNGNewDefine(ctxt, node);
        !          5221:     if (ret == NULL)
        !          5222:         return (NULL);
        !          5223:     ret->type = XML_RELAXNG_EXCEPT;
        !          5224:     child = node->children;
        !          5225:     while (child != NULL) {
        !          5226:         cur = xmlRelaxNGNewDefine(ctxt, child);
        !          5227:         if (cur == NULL)
        !          5228:             break;
        !          5229:         if (attr)
        !          5230:             cur->type = XML_RELAXNG_ATTRIBUTE;
        !          5231:         else
        !          5232:             cur->type = XML_RELAXNG_ELEMENT;
        !          5233: 
        !          5234:         if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) {
        !          5235:             if (last == NULL) {
        !          5236:                 ret->content = cur;
        !          5237:             } else {
        !          5238:                 last->next = cur;
        !          5239:             }
        !          5240:             last = cur;
        !          5241:         }
        !          5242:         child = child->next;
        !          5243:     }
        !          5244: 
        !          5245:     return (ret);
        !          5246: }
        !          5247: 
        !          5248: /**
        !          5249:  * xmlRelaxNGParseNameClass:
        !          5250:  * @ctxt:  a Relax-NG parser context
        !          5251:  * @node:  the nameClass node
        !          5252:  * @def:  the current definition
        !          5253:  *
        !          5254:  * parse the content of a RelaxNG nameClass node.
        !          5255:  *
        !          5256:  * Returns the definition pointer or NULL in case of error.
        !          5257:  */
        !          5258: static xmlRelaxNGDefinePtr
        !          5259: xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
        !          5260:                          xmlRelaxNGDefinePtr def)
        !          5261: {
        !          5262:     xmlRelaxNGDefinePtr ret, tmp;
        !          5263:     xmlChar *val;
        !          5264: 
        !          5265:     ret = def;
        !          5266:     if ((IS_RELAXNG(node, "name")) || (IS_RELAXNG(node, "anyName")) ||
        !          5267:         (IS_RELAXNG(node, "nsName"))) {
        !          5268:         if ((def->type != XML_RELAXNG_ELEMENT) &&
        !          5269:             (def->type != XML_RELAXNG_ATTRIBUTE)) {
        !          5270:             ret = xmlRelaxNGNewDefine(ctxt, node);
        !          5271:             if (ret == NULL)
        !          5272:                 return (NULL);
        !          5273:             ret->parent = def;
        !          5274:             if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE)
        !          5275:                 ret->type = XML_RELAXNG_ATTRIBUTE;
        !          5276:             else
        !          5277:                 ret->type = XML_RELAXNG_ELEMENT;
        !          5278:         }
        !          5279:     }
        !          5280:     if (IS_RELAXNG(node, "name")) {
        !          5281:         val = xmlNodeGetContent(node);
        !          5282:         xmlRelaxNGNormExtSpace(val);
        !          5283:         if (xmlValidateNCName(val, 0)) {
        !          5284:            if (node->parent != NULL)
        !          5285:                xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
        !          5286:                           "Element %s name '%s' is not an NCName\n",
        !          5287:                           node->parent->name, val);
        !          5288:            else
        !          5289:                xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
        !          5290:                           "name '%s' is not an NCName\n",
        !          5291:                           val, NULL);
        !          5292:         }
        !          5293:         ret->name = val;
        !          5294:         val = xmlGetProp(node, BAD_CAST "ns");
        !          5295:         ret->ns = val;
        !          5296:         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
        !          5297:             (val != NULL) &&
        !          5298:             (xmlStrEqual(val, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
        !          5299:            xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
        !          5300:                         "Attribute with namespace '%s' is not allowed\n",
        !          5301:                         val, NULL);
        !          5302:         }
        !          5303:         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
        !          5304:             (val != NULL) &&
        !          5305:             (val[0] == 0) && (xmlStrEqual(ret->name, BAD_CAST "xmlns"))) {
        !          5306:            xmlRngPErr(ctxt, node, XML_RNGP_XMLNS_NAME,
        !          5307:                        "Attribute with QName 'xmlns' is not allowed\n",
        !          5308:                        val, NULL);
        !          5309:         }
        !          5310:     } else if (IS_RELAXNG(node, "anyName")) {
        !          5311:         ret->name = NULL;
        !          5312:         ret->ns = NULL;
        !          5313:         if (node->children != NULL) {
        !          5314:             ret->nameClass =
        !          5315:                 xmlRelaxNGParseExceptNameClass(ctxt, node->children,
        !          5316:                                                (def->type ==
        !          5317:                                                 XML_RELAXNG_ATTRIBUTE));
        !          5318:         }
        !          5319:     } else if (IS_RELAXNG(node, "nsName")) {
        !          5320:         ret->name = NULL;
        !          5321:         ret->ns = xmlGetProp(node, BAD_CAST "ns");
        !          5322:         if (ret->ns == NULL) {
        !          5323:             xmlRngPErr(ctxt, node, XML_RNGP_NSNAME_NO_NS,
        !          5324:                        "nsName has no ns attribute\n", NULL, NULL);
        !          5325:         }
        !          5326:         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
        !          5327:             (ret->ns != NULL) &&
        !          5328:             (xmlStrEqual
        !          5329:              (ret->ns, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
        !          5330:             xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
        !          5331:                        "Attribute with namespace '%s' is not allowed\n",
        !          5332:                        ret->ns, NULL);
        !          5333:         }
        !          5334:         if (node->children != NULL) {
        !          5335:             ret->nameClass =
        !          5336:                 xmlRelaxNGParseExceptNameClass(ctxt, node->children,
        !          5337:                                                (def->type ==
        !          5338:                                                 XML_RELAXNG_ATTRIBUTE));
        !          5339:         }
        !          5340:     } else if (IS_RELAXNG(node, "choice")) {
        !          5341:         xmlNodePtr child;
        !          5342:         xmlRelaxNGDefinePtr last = NULL;
        !          5343: 
        !          5344:         ret = xmlRelaxNGNewDefine(ctxt, node);
        !          5345:         if (ret == NULL)
        !          5346:             return (NULL);
        !          5347:         ret->parent = def;
        !          5348:         ret->type = XML_RELAXNG_CHOICE;
        !          5349: 
        !          5350:         if (node->children == NULL) {
        !          5351:             xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,
        !          5352:                        "Element choice is empty\n", NULL, NULL);
        !          5353:         } else {
        !          5354: 
        !          5355:             child = node->children;
        !          5356:             while (child != NULL) {
        !          5357:                 tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);
        !          5358:                 if (tmp != NULL) {
        !          5359:                     if (last == NULL) {
        !          5360:                         last = ret->nameClass = tmp;
        !          5361:                     } else {
        !          5362:                         last->next = tmp;
        !          5363:                         last = tmp;
        !          5364:                     }
        !          5365:                 }
        !          5366:                 child = child->next;
        !          5367:             }
        !          5368:         }
        !          5369:     } else {
        !          5370:         xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT,
        !          5371:                    "expecting name, anyName, nsName or choice : got %s\n",
        !          5372:                    (node == NULL ? (const xmlChar *) "nothing" : node->name),
        !          5373:                   NULL);
        !          5374:         return (NULL);
        !          5375:     }
        !          5376:     if (ret != def) {
        !          5377:         if (def->nameClass == NULL) {
        !          5378:             def->nameClass = ret;
        !          5379:         } else {
        !          5380:             tmp = def->nameClass;
        !          5381:             while (tmp->next != NULL) {
        !          5382:                 tmp = tmp->next;
        !          5383:             }
        !          5384:             tmp->next = ret;
        !          5385:         }
        !          5386:     }
        !          5387:     return (ret);
        !          5388: }
        !          5389: 
        !          5390: /**
        !          5391:  * xmlRelaxNGParseElement:
        !          5392:  * @ctxt:  a Relax-NG parser context
        !          5393:  * @node:  the element node
        !          5394:  *
        !          5395:  * parse the content of a RelaxNG element node.
        !          5396:  *
        !          5397:  * Returns the definition pointer or NULL in case of error.
        !          5398:  */
        !          5399: static xmlRelaxNGDefinePtr
        !          5400: xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          5401: {
        !          5402:     xmlRelaxNGDefinePtr ret, cur, last;
        !          5403:     xmlNodePtr child;
        !          5404:     const xmlChar *olddefine;
        !          5405: 
        !          5406:     ret = xmlRelaxNGNewDefine(ctxt, node);
        !          5407:     if (ret == NULL)
        !          5408:         return (NULL);
        !          5409:     ret->type = XML_RELAXNG_ELEMENT;
        !          5410:     ret->parent = ctxt->def;
        !          5411:     child = node->children;
        !          5412:     if (child == NULL) {
        !          5413:         xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_EMPTY,
        !          5414:                    "xmlRelaxNGParseElement: element has no children\n",
        !          5415:                    NULL, NULL);
        !          5416:         return (ret);
        !          5417:     }
        !          5418:     cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
        !          5419:     if (cur != NULL)
        !          5420:         child = child->next;
        !          5421: 
        !          5422:     if (child == NULL) {
        !          5423:         xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NO_CONTENT,
        !          5424:                    "xmlRelaxNGParseElement: element has no content\n",
        !          5425:                    NULL, NULL);
        !          5426:         return (ret);
        !          5427:     }
        !          5428:     olddefine = ctxt->define;
        !          5429:     ctxt->define = NULL;
        !          5430:     last = NULL;
        !          5431:     while (child != NULL) {
        !          5432:         cur = xmlRelaxNGParsePattern(ctxt, child);
        !          5433:         if (cur != NULL) {
        !          5434:             cur->parent = ret;
        !          5435:             switch (cur->type) {
        !          5436:                 case XML_RELAXNG_EMPTY:
        !          5437:                 case XML_RELAXNG_NOT_ALLOWED:
        !          5438:                 case XML_RELAXNG_TEXT:
        !          5439:                 case XML_RELAXNG_ELEMENT:
        !          5440:                 case XML_RELAXNG_DATATYPE:
        !          5441:                 case XML_RELAXNG_VALUE:
        !          5442:                 case XML_RELAXNG_LIST:
        !          5443:                 case XML_RELAXNG_REF:
        !          5444:                 case XML_RELAXNG_PARENTREF:
        !          5445:                 case XML_RELAXNG_EXTERNALREF:
        !          5446:                 case XML_RELAXNG_DEF:
        !          5447:                 case XML_RELAXNG_ZEROORMORE:
        !          5448:                 case XML_RELAXNG_ONEORMORE:
        !          5449:                 case XML_RELAXNG_OPTIONAL:
        !          5450:                 case XML_RELAXNG_CHOICE:
        !          5451:                 case XML_RELAXNG_GROUP:
        !          5452:                 case XML_RELAXNG_INTERLEAVE:
        !          5453:                     if (last == NULL) {
        !          5454:                         ret->content = last = cur;
        !          5455:                     } else {
        !          5456:                         if ((last->type == XML_RELAXNG_ELEMENT) &&
        !          5457:                             (ret->content == last)) {
        !          5458:                             ret->content = xmlRelaxNGNewDefine(ctxt, node);
        !          5459:                             if (ret->content != NULL) {
        !          5460:                                 ret->content->type = XML_RELAXNG_GROUP;
        !          5461:                                 ret->content->content = last;
        !          5462:                             } else {
        !          5463:                                 ret->content = last;
        !          5464:                             }
        !          5465:                         }
        !          5466:                         last->next = cur;
        !          5467:                         last = cur;
        !          5468:                     }
        !          5469:                     break;
        !          5470:                 case XML_RELAXNG_ATTRIBUTE:
        !          5471:                     cur->next = ret->attrs;
        !          5472:                     ret->attrs = cur;
        !          5473:                     break;
        !          5474:                 case XML_RELAXNG_START:
        !          5475:                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
        !          5476:                                "RNG Internal error, start found in element\n",
        !          5477:                                NULL, NULL);
        !          5478:                     break;
        !          5479:                 case XML_RELAXNG_PARAM:
        !          5480:                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
        !          5481:                                "RNG Internal error, param found in element\n",
        !          5482:                                NULL, NULL);
        !          5483:                     break;
        !          5484:                 case XML_RELAXNG_EXCEPT:
        !          5485:                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
        !          5486:                                "RNG Internal error, except found in element\n",
        !          5487:                                NULL, NULL);
        !          5488:                     break;
        !          5489:                 case XML_RELAXNG_NOOP:
        !          5490:                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
        !          5491:                                "RNG Internal error, noop found in element\n",
        !          5492:                                NULL, NULL);
        !          5493:                     break;
        !          5494:             }
        !          5495:         }
        !          5496:         child = child->next;
        !          5497:     }
        !          5498:     ctxt->define = olddefine;
        !          5499:     return (ret);
        !          5500: }
        !          5501: 
        !          5502: /**
        !          5503:  * xmlRelaxNGParsePatterns:
        !          5504:  * @ctxt:  a Relax-NG parser context
        !          5505:  * @nodes:  list of nodes
        !          5506:  * @group:  use an implicit <group> for elements
        !          5507:  *
        !          5508:  * parse the content of a RelaxNG start node.
        !          5509:  *
        !          5510:  * Returns the definition pointer or NULL in case of error.
        !          5511:  */
        !          5512: static xmlRelaxNGDefinePtr
        !          5513: xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes,
        !          5514:                         int group)
        !          5515: {
        !          5516:     xmlRelaxNGDefinePtr def = NULL, last = NULL, cur, parent;
        !          5517: 
        !          5518:     parent = ctxt->def;
        !          5519:     while (nodes != NULL) {
        !          5520:         if (IS_RELAXNG(nodes, "element")) {
        !          5521:             cur = xmlRelaxNGParseElement(ctxt, nodes);
        !          5522:             if (def == NULL) {
        !          5523:                 def = last = cur;
        !          5524:             } else {
        !          5525:                 if ((group == 1) && (def->type == XML_RELAXNG_ELEMENT) &&
        !          5526:                     (def == last)) {
        !          5527:                     def = xmlRelaxNGNewDefine(ctxt, nodes);
        !          5528:                     def->type = XML_RELAXNG_GROUP;
        !          5529:                     def->content = last;
        !          5530:                 }
        !          5531:                 last->next = cur;
        !          5532:                 last = cur;
        !          5533:             }
        !          5534:             cur->parent = parent;
        !          5535:         } else {
        !          5536:             cur = xmlRelaxNGParsePattern(ctxt, nodes);
        !          5537:             if (cur != NULL) {
        !          5538:                 if (def == NULL) {
        !          5539:                     def = last = cur;
        !          5540:                 } else {
        !          5541:                     last->next = cur;
        !          5542:                     last = cur;
        !          5543:                 }
        !          5544:             }
        !          5545:         }
        !          5546:         nodes = nodes->next;
        !          5547:     }
        !          5548:     return (def);
        !          5549: }
        !          5550: 
        !          5551: /**
        !          5552:  * xmlRelaxNGParseStart:
        !          5553:  * @ctxt:  a Relax-NG parser context
        !          5554:  * @nodes:  start children nodes
        !          5555:  *
        !          5556:  * parse the content of a RelaxNG start node.
        !          5557:  *
        !          5558:  * Returns 0 in case of success, -1 in case of error
        !          5559:  */
        !          5560: static int
        !          5561: xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
        !          5562: {
        !          5563:     int ret = 0;
        !          5564:     xmlRelaxNGDefinePtr def = NULL, last;
        !          5565: 
        !          5566:     if (nodes == NULL) {
        !          5567:         xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY, "start has no children\n",
        !          5568:                    NULL, NULL);
        !          5569:         return (-1);
        !          5570:     }
        !          5571:     if (IS_RELAXNG(nodes, "empty")) {
        !          5572:         def = xmlRelaxNGNewDefine(ctxt, nodes);
        !          5573:         if (def == NULL)
        !          5574:             return (-1);
        !          5575:         def->type = XML_RELAXNG_EMPTY;
        !          5576:         if (nodes->children != NULL) {
        !          5577:             xmlRngPErr(ctxt, nodes, XML_RNGP_EMPTY_CONTENT,
        !          5578:                        "element empty is not empty\n", NULL, NULL);
        !          5579:         }
        !          5580:     } else if (IS_RELAXNG(nodes, "notAllowed")) {
        !          5581:         def = xmlRelaxNGNewDefine(ctxt, nodes);
        !          5582:         if (def == NULL)
        !          5583:             return (-1);
        !          5584:         def->type = XML_RELAXNG_NOT_ALLOWED;
        !          5585:         if (nodes->children != NULL) {
        !          5586:             xmlRngPErr(ctxt, nodes, XML_RNGP_NOTALLOWED_NOT_EMPTY,
        !          5587:                        "element notAllowed is not empty\n", NULL, NULL);
        !          5588:         }
        !          5589:     } else {
        !          5590:         def = xmlRelaxNGParsePatterns(ctxt, nodes, 1);
        !          5591:     }
        !          5592:     if (ctxt->grammar->start != NULL) {
        !          5593:         last = ctxt->grammar->start;
        !          5594:         while (last->next != NULL)
        !          5595:             last = last->next;
        !          5596:         last->next = def;
        !          5597:     } else {
        !          5598:         ctxt->grammar->start = def;
        !          5599:     }
        !          5600:     nodes = nodes->next;
        !          5601:     if (nodes != NULL) {
        !          5602:         xmlRngPErr(ctxt, nodes, XML_RNGP_START_CONTENT,
        !          5603:                    "start more than one children\n", NULL, NULL);
        !          5604:         return (-1);
        !          5605:     }
        !          5606:     return (ret);
        !          5607: }
        !          5608: 
        !          5609: /**
        !          5610:  * xmlRelaxNGParseGrammarContent:
        !          5611:  * @ctxt:  a Relax-NG parser context
        !          5612:  * @nodes:  grammar children nodes
        !          5613:  *
        !          5614:  * parse the content of a RelaxNG grammar node.
        !          5615:  *
        !          5616:  * Returns 0 in case of success, -1 in case of error
        !          5617:  */
        !          5618: static int
        !          5619: xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
        !          5620:                               xmlNodePtr nodes)
        !          5621: {
        !          5622:     int ret = 0, tmp;
        !          5623: 
        !          5624:     if (nodes == NULL) {
        !          5625:         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_EMPTY,
        !          5626:                    "grammar has no children\n", NULL, NULL);
        !          5627:         return (-1);
        !          5628:     }
        !          5629:     while (nodes != NULL) {
        !          5630:         if (IS_RELAXNG(nodes, "start")) {
        !          5631:             if (nodes->children == NULL) {
        !          5632:                 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY,
        !          5633:                            "start has no children\n", NULL, NULL);
        !          5634:             } else {
        !          5635:                 tmp = xmlRelaxNGParseStart(ctxt, nodes->children);
        !          5636:                 if (tmp != 0)
        !          5637:                     ret = -1;
        !          5638:             }
        !          5639:         } else if (IS_RELAXNG(nodes, "define")) {
        !          5640:             tmp = xmlRelaxNGParseDefine(ctxt, nodes);
        !          5641:             if (tmp != 0)
        !          5642:                 ret = -1;
        !          5643:         } else if (IS_RELAXNG(nodes, "include")) {
        !          5644:             tmp = xmlRelaxNGParseInclude(ctxt, nodes);
        !          5645:             if (tmp != 0)
        !          5646:                 ret = -1;
        !          5647:         } else {
        !          5648:             xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
        !          5649:                        "grammar has unexpected child %s\n", nodes->name,
        !          5650:                        NULL);
        !          5651:             ret = -1;
        !          5652:         }
        !          5653:         nodes = nodes->next;
        !          5654:     }
        !          5655:     return (ret);
        !          5656: }
        !          5657: 
        !          5658: /**
        !          5659:  * xmlRelaxNGCheckReference:
        !          5660:  * @ref:  the ref
        !          5661:  * @ctxt:  a Relax-NG parser context
        !          5662:  * @name:  the name associated to the defines
        !          5663:  *
        !          5664:  * Applies the 4.17. combine attribute rule for all the define
        !          5665:  * element of a given grammar using the same name.
        !          5666:  */
        !          5667: static void
        !          5668: xmlRelaxNGCheckReference(xmlRelaxNGDefinePtr ref,
        !          5669:                          xmlRelaxNGParserCtxtPtr ctxt,
        !          5670:                          const xmlChar * name)
        !          5671: {
        !          5672:     xmlRelaxNGGrammarPtr grammar;
        !          5673:     xmlRelaxNGDefinePtr def, cur;
        !          5674: 
        !          5675:     /*
        !          5676:      * Those rules don't apply to imported ref from xmlRelaxNGParseImportRef
        !          5677:      */
        !          5678:     if (ref->dflags & IS_EXTERNAL_REF)
        !          5679:         return;
        !          5680: 
        !          5681:     grammar = ctxt->grammar;
        !          5682:     if (grammar == NULL) {
        !          5683:         xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
        !          5684:                    "Internal error: no grammar in CheckReference %s\n",
        !          5685:                    name, NULL);
        !          5686:         return;
        !          5687:     }
        !          5688:     if (ref->content != NULL) {
        !          5689:         xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
        !          5690:                    "Internal error: reference has content in CheckReference %s\n",
        !          5691:                    name, NULL);
        !          5692:         return;
        !          5693:     }
        !          5694:     if (grammar->defs != NULL) {
        !          5695:         def = xmlHashLookup(grammar->defs, name);
        !          5696:         if (def != NULL) {
        !          5697:             cur = ref;
        !          5698:             while (cur != NULL) {
        !          5699:                 cur->content = def;
        !          5700:                 cur = cur->nextHash;
        !          5701:             }
        !          5702:         } else {
        !          5703:             xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
        !          5704:                        "Reference %s has no matching definition\n", name,
        !          5705:                        NULL);
        !          5706:         }
        !          5707:     } else {
        !          5708:         xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
        !          5709:                    "Reference %s has no matching definition\n", name,
        !          5710:                    NULL);
        !          5711:     }
        !          5712: }
        !          5713: 
        !          5714: /**
        !          5715:  * xmlRelaxNGCheckCombine:
        !          5716:  * @define:  the define(s) list
        !          5717:  * @ctxt:  a Relax-NG parser context
        !          5718:  * @name:  the name associated to the defines
        !          5719:  *
        !          5720:  * Applies the 4.17. combine attribute rule for all the define
        !          5721:  * element of a given grammar using the same name.
        !          5722:  */
        !          5723: static void
        !          5724: xmlRelaxNGCheckCombine(xmlRelaxNGDefinePtr define,
        !          5725:                        xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * name)
        !          5726: {
        !          5727:     xmlChar *combine;
        !          5728:     int choiceOrInterleave = -1;
        !          5729:     int missing = 0;
        !          5730:     xmlRelaxNGDefinePtr cur, last, tmp, tmp2;
        !          5731: 
        !          5732:     if (define->nextHash == NULL)
        !          5733:         return;
        !          5734:     cur = define;
        !          5735:     while (cur != NULL) {
        !          5736:         combine = xmlGetProp(cur->node, BAD_CAST "combine");
        !          5737:         if (combine != NULL) {
        !          5738:             if (xmlStrEqual(combine, BAD_CAST "choice")) {
        !          5739:                 if (choiceOrInterleave == -1)
        !          5740:                     choiceOrInterleave = 1;
        !          5741:                 else if (choiceOrInterleave == 0) {
        !          5742:                     xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
        !          5743:                                "Defines for %s use both 'choice' and 'interleave'\n",
        !          5744:                                name, NULL);
        !          5745:                 }
        !          5746:             } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
        !          5747:                 if (choiceOrInterleave == -1)
        !          5748:                     choiceOrInterleave = 0;
        !          5749:                 else if (choiceOrInterleave == 1) {
        !          5750:                     xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
        !          5751:                                "Defines for %s use both 'choice' and 'interleave'\n",
        !          5752:                                name, NULL);
        !          5753:                 }
        !          5754:             } else {
        !          5755:                 xmlRngPErr(ctxt, define->node, XML_RNGP_UNKNOWN_COMBINE,
        !          5756:                            "Defines for %s use unknown combine value '%s''\n",
        !          5757:                            name, combine);
        !          5758:             }
        !          5759:             xmlFree(combine);
        !          5760:         } else {
        !          5761:             if (missing == 0)
        !          5762:                 missing = 1;
        !          5763:             else {
        !          5764:                 xmlRngPErr(ctxt, define->node, XML_RNGP_NEED_COMBINE,
        !          5765:                            "Some defines for %s needs the combine attribute\n",
        !          5766:                            name, NULL);
        !          5767:             }
        !          5768:         }
        !          5769: 
        !          5770:         cur = cur->nextHash;
        !          5771:     }
        !          5772: #ifdef DEBUG
        !          5773:     xmlGenericError(xmlGenericErrorContext,
        !          5774:                     "xmlRelaxNGCheckCombine(): merging %s defines: %d\n",
        !          5775:                     name, choiceOrInterleave);
        !          5776: #endif
        !          5777:     if (choiceOrInterleave == -1)
        !          5778:         choiceOrInterleave = 0;
        !          5779:     cur = xmlRelaxNGNewDefine(ctxt, define->node);
        !          5780:     if (cur == NULL)
        !          5781:         return;
        !          5782:     if (choiceOrInterleave == 0)
        !          5783:         cur->type = XML_RELAXNG_INTERLEAVE;
        !          5784:     else
        !          5785:         cur->type = XML_RELAXNG_CHOICE;
        !          5786:     tmp = define;
        !          5787:     last = NULL;
        !          5788:     while (tmp != NULL) {
        !          5789:         if (tmp->content != NULL) {
        !          5790:             if (tmp->content->next != NULL) {
        !          5791:                 /*
        !          5792:                  * we need first to create a wrapper.
        !          5793:                  */
        !          5794:                 tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node);
        !          5795:                 if (tmp2 == NULL)
        !          5796:                     break;
        !          5797:                 tmp2->type = XML_RELAXNG_GROUP;
        !          5798:                 tmp2->content = tmp->content;
        !          5799:             } else {
        !          5800:                 tmp2 = tmp->content;
        !          5801:             }
        !          5802:             if (last == NULL) {
        !          5803:                 cur->content = tmp2;
        !          5804:             } else {
        !          5805:                 last->next = tmp2;
        !          5806:             }
        !          5807:             last = tmp2;
        !          5808:         }
        !          5809:         tmp->content = cur;
        !          5810:         tmp = tmp->nextHash;
        !          5811:     }
        !          5812:     define->content = cur;
        !          5813:     if (choiceOrInterleave == 0) {
        !          5814:         if (ctxt->interleaves == NULL)
        !          5815:             ctxt->interleaves = xmlHashCreate(10);
        !          5816:         if (ctxt->interleaves == NULL) {
        !          5817:             xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
        !          5818:                        "Failed to create interleaves hash table\n", NULL,
        !          5819:                        NULL);
        !          5820:         } else {
        !          5821:             char tmpname[32];
        !          5822: 
        !          5823:             snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
        !          5824:             if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
        !          5825:                 0) {
        !          5826:                 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
        !          5827:                            "Failed to add %s to hash table\n",
        !          5828:                           (const xmlChar *) tmpname, NULL);
        !          5829:             }
        !          5830:         }
        !          5831:     }
        !          5832: }
        !          5833: 
        !          5834: /**
        !          5835:  * xmlRelaxNGCombineStart:
        !          5836:  * @ctxt:  a Relax-NG parser context
        !          5837:  * @grammar:  the grammar
        !          5838:  *
        !          5839:  * Applies the 4.17. combine rule for all the start
        !          5840:  * element of a given grammar.
        !          5841:  */
        !          5842: static void
        !          5843: xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt,
        !          5844:                        xmlRelaxNGGrammarPtr grammar)
        !          5845: {
        !          5846:     xmlRelaxNGDefinePtr starts;
        !          5847:     xmlChar *combine;
        !          5848:     int choiceOrInterleave = -1;
        !          5849:     int missing = 0;
        !          5850:     xmlRelaxNGDefinePtr cur;
        !          5851: 
        !          5852:     starts = grammar->start;
        !          5853:     if ((starts == NULL) || (starts->next == NULL))
        !          5854:         return;
        !          5855:     cur = starts;
        !          5856:     while (cur != NULL) {
        !          5857:         if ((cur->node == NULL) || (cur->node->parent == NULL) ||
        !          5858:             (!xmlStrEqual(cur->node->parent->name, BAD_CAST "start"))) {
        !          5859:             combine = NULL;
        !          5860:             xmlRngPErr(ctxt, cur->node, XML_RNGP_START_MISSING,
        !          5861:                        "Internal error: start element not found\n", NULL,
        !          5862:                        NULL);
        !          5863:         } else {
        !          5864:             combine = xmlGetProp(cur->node->parent, BAD_CAST "combine");
        !          5865:         }
        !          5866: 
        !          5867:         if (combine != NULL) {
        !          5868:             if (xmlStrEqual(combine, BAD_CAST "choice")) {
        !          5869:                 if (choiceOrInterleave == -1)
        !          5870:                     choiceOrInterleave = 1;
        !          5871:                 else if (choiceOrInterleave == 0) {
        !          5872:                     xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
        !          5873:                                "<start> use both 'choice' and 'interleave'\n",
        !          5874:                                NULL, NULL);
        !          5875:                 }
        !          5876:             } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
        !          5877:                 if (choiceOrInterleave == -1)
        !          5878:                     choiceOrInterleave = 0;
        !          5879:                 else if (choiceOrInterleave == 1) {
        !          5880:                     xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
        !          5881:                                "<start> use both 'choice' and 'interleave'\n",
        !          5882:                                NULL, NULL);
        !          5883:                 }
        !          5884:             } else {
        !          5885:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_UNKNOWN_COMBINE,
        !          5886:                            "<start> uses unknown combine value '%s''\n",
        !          5887:                            combine, NULL);
        !          5888:             }
        !          5889:             xmlFree(combine);
        !          5890:         } else {
        !          5891:             if (missing == 0)
        !          5892:                 missing = 1;
        !          5893:             else {
        !          5894:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_NEED_COMBINE,
        !          5895:                            "Some <start> element miss the combine attribute\n",
        !          5896:                            NULL, NULL);
        !          5897:             }
        !          5898:         }
        !          5899: 
        !          5900:         cur = cur->next;
        !          5901:     }
        !          5902: #ifdef DEBUG
        !          5903:     xmlGenericError(xmlGenericErrorContext,
        !          5904:                     "xmlRelaxNGCombineStart(): merging <start>: %d\n",
        !          5905:                     choiceOrInterleave);
        !          5906: #endif
        !          5907:     if (choiceOrInterleave == -1)
        !          5908:         choiceOrInterleave = 0;
        !          5909:     cur = xmlRelaxNGNewDefine(ctxt, starts->node);
        !          5910:     if (cur == NULL)
        !          5911:         return;
        !          5912:     if (choiceOrInterleave == 0)
        !          5913:         cur->type = XML_RELAXNG_INTERLEAVE;
        !          5914:     else
        !          5915:         cur->type = XML_RELAXNG_CHOICE;
        !          5916:     cur->content = grammar->start;
        !          5917:     grammar->start = cur;
        !          5918:     if (choiceOrInterleave == 0) {
        !          5919:         if (ctxt->interleaves == NULL)
        !          5920:             ctxt->interleaves = xmlHashCreate(10);
        !          5921:         if (ctxt->interleaves == NULL) {
        !          5922:             xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
        !          5923:                        "Failed to create interleaves hash table\n", NULL,
        !          5924:                        NULL);
        !          5925:         } else {
        !          5926:             char tmpname[32];
        !          5927: 
        !          5928:             snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
        !          5929:             if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
        !          5930:                 0) {
        !          5931:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
        !          5932:                            "Failed to add %s to hash table\n",
        !          5933:                           (const xmlChar *) tmpname, NULL);
        !          5934:             }
        !          5935:         }
        !          5936:     }
        !          5937: }
        !          5938: 
        !          5939: /**
        !          5940:  * xmlRelaxNGCheckCycles:
        !          5941:  * @ctxt:  a Relax-NG parser context
        !          5942:  * @nodes:  grammar children nodes
        !          5943:  * @depth:  the counter
        !          5944:  *
        !          5945:  * Check for cycles.
        !          5946:  *
        !          5947:  * Returns 0 if check passed, and -1 in case of error
        !          5948:  */
        !          5949: static int
        !          5950: xmlRelaxNGCheckCycles(xmlRelaxNGParserCtxtPtr ctxt,
        !          5951:                       xmlRelaxNGDefinePtr cur, int depth)
        !          5952: {
        !          5953:     int ret = 0;
        !          5954: 
        !          5955:     while ((ret == 0) && (cur != NULL)) {
        !          5956:         if ((cur->type == XML_RELAXNG_REF) ||
        !          5957:             (cur->type == XML_RELAXNG_PARENTREF)) {
        !          5958:             if (cur->depth == -1) {
        !          5959:                 cur->depth = depth;
        !          5960:                 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
        !          5961:                 cur->depth = -2;
        !          5962:             } else if (depth == cur->depth) {
        !          5963:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_CYCLE,
        !          5964:                            "Detected a cycle in %s references\n",
        !          5965:                            cur->name, NULL);
        !          5966:                 return (-1);
        !          5967:             }
        !          5968:         } else if (cur->type == XML_RELAXNG_ELEMENT) {
        !          5969:             ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth + 1);
        !          5970:         } else {
        !          5971:             ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
        !          5972:         }
        !          5973:         cur = cur->next;
        !          5974:     }
        !          5975:     return (ret);
        !          5976: }
        !          5977: 
        !          5978: /**
        !          5979:  * xmlRelaxNGTryUnlink:
        !          5980:  * @ctxt:  a Relax-NG parser context
        !          5981:  * @cur:  the definition to unlink
        !          5982:  * @parent:  the parent definition
        !          5983:  * @prev:  the previous sibling definition
        !          5984:  *
        !          5985:  * Try to unlink a definition. If not possble make it a NOOP
        !          5986:  *
        !          5987:  * Returns the new prev definition
        !          5988:  */
        !          5989: static xmlRelaxNGDefinePtr
        !          5990: xmlRelaxNGTryUnlink(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
        !          5991:                     xmlRelaxNGDefinePtr cur,
        !          5992:                     xmlRelaxNGDefinePtr parent, xmlRelaxNGDefinePtr prev)
        !          5993: {
        !          5994:     if (prev != NULL) {
        !          5995:         prev->next = cur->next;
        !          5996:     } else {
        !          5997:         if (parent != NULL) {
        !          5998:             if (parent->content == cur)
        !          5999:                 parent->content = cur->next;
        !          6000:             else if (parent->attrs == cur)
        !          6001:                 parent->attrs = cur->next;
        !          6002:             else if (parent->nameClass == cur)
        !          6003:                 parent->nameClass = cur->next;
        !          6004:         } else {
        !          6005:             cur->type = XML_RELAXNG_NOOP;
        !          6006:             prev = cur;
        !          6007:         }
        !          6008:     }
        !          6009:     return (prev);
        !          6010: }
        !          6011: 
        !          6012: /**
        !          6013:  * xmlRelaxNGSimplify:
        !          6014:  * @ctxt:  a Relax-NG parser context
        !          6015:  * @nodes:  grammar children nodes
        !          6016:  *
        !          6017:  * Check for simplification of empty and notAllowed
        !          6018:  */
        !          6019: static void
        !          6020: xmlRelaxNGSimplify(xmlRelaxNGParserCtxtPtr ctxt,
        !          6021:                    xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent)
        !          6022: {
        !          6023:     xmlRelaxNGDefinePtr prev = NULL;
        !          6024: 
        !          6025:     while (cur != NULL) {
        !          6026:         if ((cur->type == XML_RELAXNG_REF) ||
        !          6027:             (cur->type == XML_RELAXNG_PARENTREF)) {
        !          6028:             if (cur->depth != -3) {
        !          6029:                 cur->depth = -3;
        !          6030:                 xmlRelaxNGSimplify(ctxt, cur->content, cur);
        !          6031:             }
        !          6032:         } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
        !          6033:             cur->parent = parent;
        !          6034:             if ((parent != NULL) &&
        !          6035:                 ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
        !          6036:                  (parent->type == XML_RELAXNG_LIST) ||
        !          6037:                  (parent->type == XML_RELAXNG_GROUP) ||
        !          6038:                  (parent->type == XML_RELAXNG_INTERLEAVE) ||
        !          6039:                  (parent->type == XML_RELAXNG_ONEORMORE) ||
        !          6040:                  (parent->type == XML_RELAXNG_ZEROORMORE))) {
        !          6041:                 parent->type = XML_RELAXNG_NOT_ALLOWED;
        !          6042:                 break;
        !          6043:             }
        !          6044:             if ((parent != NULL) && (parent->type == XML_RELAXNG_CHOICE)) {
        !          6045:                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
        !          6046:             } else
        !          6047:                 prev = cur;
        !          6048:         } else if (cur->type == XML_RELAXNG_EMPTY) {
        !          6049:             cur->parent = parent;
        !          6050:             if ((parent != NULL) &&
        !          6051:                 ((parent->type == XML_RELAXNG_ONEORMORE) ||
        !          6052:                  (parent->type == XML_RELAXNG_ZEROORMORE))) {
        !          6053:                 parent->type = XML_RELAXNG_EMPTY;
        !          6054:                 break;
        !          6055:             }
        !          6056:             if ((parent != NULL) &&
        !          6057:                 ((parent->type == XML_RELAXNG_GROUP) ||
        !          6058:                  (parent->type == XML_RELAXNG_INTERLEAVE))) {
        !          6059:                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
        !          6060:             } else
        !          6061:                 prev = cur;
        !          6062:         } else {
        !          6063:             cur->parent = parent;
        !          6064:             if (cur->content != NULL)
        !          6065:                 xmlRelaxNGSimplify(ctxt, cur->content, cur);
        !          6066:             if ((cur->type != XML_RELAXNG_VALUE) && (cur->attrs != NULL))
        !          6067:                 xmlRelaxNGSimplify(ctxt, cur->attrs, cur);
        !          6068:             if (cur->nameClass != NULL)
        !          6069:                 xmlRelaxNGSimplify(ctxt, cur->nameClass, cur);
        !          6070:             /*
        !          6071:              * On Elements, try to move attribute only generating rules on
        !          6072:              * the attrs rules.
        !          6073:              */
        !          6074:             if (cur->type == XML_RELAXNG_ELEMENT) {
        !          6075:                 int attronly;
        !          6076:                 xmlRelaxNGDefinePtr tmp, pre;
        !          6077: 
        !          6078:                 while (cur->content != NULL) {
        !          6079:                     attronly =
        !          6080:                         xmlRelaxNGGenerateAttributes(ctxt, cur->content);
        !          6081:                     if (attronly == 1) {
        !          6082:                         /*
        !          6083:                          * migrate cur->content to attrs
        !          6084:                          */
        !          6085:                         tmp = cur->content;
        !          6086:                         cur->content = tmp->next;
        !          6087:                         tmp->next = cur->attrs;
        !          6088:                         cur->attrs = tmp;
        !          6089:                     } else {
        !          6090:                         /*
        !          6091:                          * cur->content can generate elements or text
        !          6092:                          */
        !          6093:                         break;
        !          6094:                     }
        !          6095:                 }
        !          6096:                 pre = cur->content;
        !          6097:                 while ((pre != NULL) && (pre->next != NULL)) {
        !          6098:                     tmp = pre->next;
        !          6099:                     attronly = xmlRelaxNGGenerateAttributes(ctxt, tmp);
        !          6100:                     if (attronly == 1) {
        !          6101:                         /*
        !          6102:                          * migrate tmp to attrs
        !          6103:                          */
        !          6104:                         pre->next = tmp->next;
        !          6105:                         tmp->next = cur->attrs;
        !          6106:                         cur->attrs = tmp;
        !          6107:                     } else {
        !          6108:                         pre = tmp;
        !          6109:                     }
        !          6110:                 }
        !          6111:             }
        !          6112:             /*
        !          6113:              * This may result in a simplification
        !          6114:              */
        !          6115:             if ((cur->type == XML_RELAXNG_GROUP) ||
        !          6116:                 (cur->type == XML_RELAXNG_INTERLEAVE)) {
        !          6117:                 if (cur->content == NULL)
        !          6118:                     cur->type = XML_RELAXNG_EMPTY;
        !          6119:                 else if (cur->content->next == NULL) {
        !          6120:                     if ((parent == NULL) && (prev == NULL)) {
        !          6121:                         cur->type = XML_RELAXNG_NOOP;
        !          6122:                     } else if (prev == NULL) {
        !          6123:                         parent->content = cur->content;
        !          6124:                         cur->content->next = cur->next;
        !          6125:                         cur = cur->content;
        !          6126:                     } else {
        !          6127:                         cur->content->next = cur->next;
        !          6128:                         prev->next = cur->content;
        !          6129:                         cur = cur->content;
        !          6130:                     }
        !          6131:                 }
        !          6132:             }
        !          6133:             /*
        !          6134:              * the current node may have been transformed back
        !          6135:              */
        !          6136:             if ((cur->type == XML_RELAXNG_EXCEPT) &&
        !          6137:                 (cur->content != NULL) &&
        !          6138:                 (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) {
        !          6139:                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
        !          6140:             } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
        !          6141:                 if ((parent != NULL) &&
        !          6142:                     ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
        !          6143:                      (parent->type == XML_RELAXNG_LIST) ||
        !          6144:                      (parent->type == XML_RELAXNG_GROUP) ||
        !          6145:                      (parent->type == XML_RELAXNG_INTERLEAVE) ||
        !          6146:                      (parent->type == XML_RELAXNG_ONEORMORE) ||
        !          6147:                      (parent->type == XML_RELAXNG_ZEROORMORE))) {
        !          6148:                     parent->type = XML_RELAXNG_NOT_ALLOWED;
        !          6149:                     break;
        !          6150:                 }
        !          6151:                 if ((parent != NULL) &&
        !          6152:                     (parent->type == XML_RELAXNG_CHOICE)) {
        !          6153:                     prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
        !          6154:                 } else
        !          6155:                     prev = cur;
        !          6156:             } else if (cur->type == XML_RELAXNG_EMPTY) {
        !          6157:                 if ((parent != NULL) &&
        !          6158:                     ((parent->type == XML_RELAXNG_ONEORMORE) ||
        !          6159:                      (parent->type == XML_RELAXNG_ZEROORMORE))) {
        !          6160:                     parent->type = XML_RELAXNG_EMPTY;
        !          6161:                     break;
        !          6162:                 }
        !          6163:                 if ((parent != NULL) &&
        !          6164:                     ((parent->type == XML_RELAXNG_GROUP) ||
        !          6165:                      (parent->type == XML_RELAXNG_INTERLEAVE) ||
        !          6166:                      (parent->type == XML_RELAXNG_CHOICE))) {
        !          6167:                     prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
        !          6168:                 } else
        !          6169:                     prev = cur;
        !          6170:             } else {
        !          6171:                 prev = cur;
        !          6172:             }
        !          6173:         }
        !          6174:         cur = cur->next;
        !          6175:     }
        !          6176: }
        !          6177: 
        !          6178: /**
        !          6179:  * xmlRelaxNGGroupContentType:
        !          6180:  * @ct1:  the first content type
        !          6181:  * @ct2:  the second content type
        !          6182:  *
        !          6183:  * Try to group 2 content types
        !          6184:  *
        !          6185:  * Returns the content type
        !          6186:  */
        !          6187: static xmlRelaxNGContentType
        !          6188: xmlRelaxNGGroupContentType(xmlRelaxNGContentType ct1,
        !          6189:                            xmlRelaxNGContentType ct2)
        !          6190: {
        !          6191:     if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
        !          6192:         (ct2 == XML_RELAXNG_CONTENT_ERROR))
        !          6193:         return (XML_RELAXNG_CONTENT_ERROR);
        !          6194:     if (ct1 == XML_RELAXNG_CONTENT_EMPTY)
        !          6195:         return (ct2);
        !          6196:     if (ct2 == XML_RELAXNG_CONTENT_EMPTY)
        !          6197:         return (ct1);
        !          6198:     if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) &&
        !          6199:         (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
        !          6200:         return (XML_RELAXNG_CONTENT_COMPLEX);
        !          6201:     return (XML_RELAXNG_CONTENT_ERROR);
        !          6202: }
        !          6203: 
        !          6204: /**
        !          6205:  * xmlRelaxNGMaxContentType:
        !          6206:  * @ct1:  the first content type
        !          6207:  * @ct2:  the second content type
        !          6208:  *
        !          6209:  * Compute the max content-type
        !          6210:  *
        !          6211:  * Returns the content type
        !          6212:  */
        !          6213: static xmlRelaxNGContentType
        !          6214: xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1,
        !          6215:                          xmlRelaxNGContentType ct2)
        !          6216: {
        !          6217:     if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
        !          6218:         (ct2 == XML_RELAXNG_CONTENT_ERROR))
        !          6219:         return (XML_RELAXNG_CONTENT_ERROR);
        !          6220:     if ((ct1 == XML_RELAXNG_CONTENT_SIMPLE) ||
        !          6221:         (ct2 == XML_RELAXNG_CONTENT_SIMPLE))
        !          6222:         return (XML_RELAXNG_CONTENT_SIMPLE);
        !          6223:     if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) ||
        !          6224:         (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
        !          6225:         return (XML_RELAXNG_CONTENT_COMPLEX);
        !          6226:     return (XML_RELAXNG_CONTENT_EMPTY);
        !          6227: }
        !          6228: 
        !          6229: /**
        !          6230:  * xmlRelaxNGCheckRules:
        !          6231:  * @ctxt:  a Relax-NG parser context
        !          6232:  * @cur:  the current definition
        !          6233:  * @flags:  some accumulated flags
        !          6234:  * @ptype:  the parent type
        !          6235:  *
        !          6236:  * Check for rules in section 7.1 and 7.2
        !          6237:  *
        !          6238:  * Returns the content type of @cur
        !          6239:  */
        !          6240: static xmlRelaxNGContentType
        !          6241: xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt,
        !          6242:                      xmlRelaxNGDefinePtr cur, int flags,
        !          6243:                      xmlRelaxNGType ptype)
        !          6244: {
        !          6245:     int nflags;
        !          6246:     xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY;
        !          6247: 
        !          6248:     while (cur != NULL) {
        !          6249:         ret = XML_RELAXNG_CONTENT_EMPTY;
        !          6250:         if ((cur->type == XML_RELAXNG_REF) ||
        !          6251:             (cur->type == XML_RELAXNG_PARENTREF)) {
        !          6252:            /*
        !          6253:             * This should actually be caught by list//element(ref) at the
        !          6254:             * element boundaries, c.f. Bug #159968 local refs are dropped
        !          6255:             * in step 4.19.
        !          6256:             */
        !          6257: #if 0
        !          6258:             if (flags & XML_RELAXNG_IN_LIST) {
        !          6259:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_REF,
        !          6260:                            "Found forbidden pattern list//ref\n", NULL,
        !          6261:                            NULL);
        !          6262:             }
        !          6263: #endif
        !          6264:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6265:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_REF,
        !          6266:                            "Found forbidden pattern data/except//ref\n",
        !          6267:                            NULL, NULL);
        !          6268:             }
        !          6269:             if (cur->content == NULL) {
        !          6270:                 if (cur->type == XML_RELAXNG_PARENTREF)
        !          6271:                     xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,
        !          6272:                                "Internal found no define for parent refs\n",
        !          6273:                                NULL, NULL);
        !          6274:                 else
        !          6275:                     xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,
        !          6276:                                "Internal found no define for ref %s\n",
        !          6277:                                (cur->name ? cur->name: BAD_CAST "null"), NULL);
        !          6278:             }
        !          6279:             if (cur->depth > -4) {
        !          6280:                 cur->depth = -4;
        !          6281:                 ret = xmlRelaxNGCheckRules(ctxt, cur->content,
        !          6282:                                            flags, cur->type);
        !          6283:                 cur->depth = ret - 15;
        !          6284:             } else if (cur->depth == -4) {
        !          6285:                 ret = XML_RELAXNG_CONTENT_COMPLEX;
        !          6286:             } else {
        !          6287:                 ret = (xmlRelaxNGContentType) (cur->depth + 15);
        !          6288:             }
        !          6289:         } else if (cur->type == XML_RELAXNG_ELEMENT) {
        !          6290:             /*
        !          6291:              * The 7.3 Attribute derivation rule for groups is plugged there
        !          6292:              */
        !          6293:             xmlRelaxNGCheckGroupAttrs(ctxt, cur);
        !          6294:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6295:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ELEM,
        !          6296:                            "Found forbidden pattern data/except//element(ref)\n",
        !          6297:                            NULL, NULL);
        !          6298:             }
        !          6299:             if (flags & XML_RELAXNG_IN_LIST) {
        !          6300:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ELEM,
        !          6301:                            "Found forbidden pattern list//element(ref)\n",
        !          6302:                            NULL, NULL);
        !          6303:             }
        !          6304:             if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
        !          6305:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
        !          6306:                            "Found forbidden pattern attribute//element(ref)\n",
        !          6307:                            NULL, NULL);
        !          6308:             }
        !          6309:             if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
        !          6310:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
        !          6311:                            "Found forbidden pattern attribute//element(ref)\n",
        !          6312:                            NULL, NULL);
        !          6313:             }
        !          6314:             /*
        !          6315:              * reset since in the simple form elements are only child
        !          6316:              * of grammar/define
        !          6317:              */
        !          6318:             nflags = 0;
        !          6319:             ret =
        !          6320:                 xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type);
        !          6321:             if (ret != XML_RELAXNG_CONTENT_EMPTY) {
        !          6322:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_EMPTY,
        !          6323:                            "Element %s attributes have a content type error\n",
        !          6324:                            cur->name, NULL);
        !          6325:             }
        !          6326:             ret =
        !          6327:                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
        !          6328:                                      cur->type);
        !          6329:             if (ret == XML_RELAXNG_CONTENT_ERROR) {
        !          6330:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_ERROR,
        !          6331:                            "Element %s has a content type error\n",
        !          6332:                            cur->name, NULL);
        !          6333:             } else {
        !          6334:                 ret = XML_RELAXNG_CONTENT_COMPLEX;
        !          6335:             }
        !          6336:         } else if (cur->type == XML_RELAXNG_ATTRIBUTE) {
        !          6337:             if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
        !          6338:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ATTR,
        !          6339:                            "Found forbidden pattern attribute//attribute\n",
        !          6340:                            NULL, NULL);
        !          6341:             }
        !          6342:             if (flags & XML_RELAXNG_IN_LIST) {
        !          6343:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ATTR,
        !          6344:                            "Found forbidden pattern list//attribute\n",
        !          6345:                            NULL, NULL);
        !          6346:             }
        !          6347:             if (flags & XML_RELAXNG_IN_OOMGROUP) {
        !          6348:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_GROUP_ATTR,
        !          6349:                            "Found forbidden pattern oneOrMore//group//attribute\n",
        !          6350:                            NULL, NULL);
        !          6351:             }
        !          6352:             if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) {
        !          6353:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR,
        !          6354:                            "Found forbidden pattern oneOrMore//interleave//attribute\n",
        !          6355:                            NULL, NULL);
        !          6356:             }
        !          6357:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6358:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ATTR,
        !          6359:                            "Found forbidden pattern data/except//attribute\n",
        !          6360:                            NULL, NULL);
        !          6361:             }
        !          6362:             if (flags & XML_RELAXNG_IN_START) {
        !          6363:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ATTR,
        !          6364:                            "Found forbidden pattern start//attribute\n",
        !          6365:                            NULL, NULL);
        !          6366:             }
        !          6367:             if ((!(flags & XML_RELAXNG_IN_ONEORMORE))
        !          6368:                 && (cur->name == NULL)) {
        !          6369:                 if (cur->ns == NULL) {
        !          6370:                     xmlRngPErr(ctxt, cur->node, XML_RNGP_ANYNAME_ATTR_ANCESTOR,
        !          6371:                                "Found anyName attribute without oneOrMore ancestor\n",
        !          6372:                                NULL, NULL);
        !          6373:                 } else {
        !          6374:                     xmlRngPErr(ctxt, cur->node, XML_RNGP_NSNAME_ATTR_ANCESTOR,
        !          6375:                                "Found nsName attribute without oneOrMore ancestor\n",
        !          6376:                                NULL, NULL);
        !          6377:                 }
        !          6378:             }
        !          6379:             nflags = flags | XML_RELAXNG_IN_ATTRIBUTE;
        !          6380:             xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
        !          6381:             ret = XML_RELAXNG_CONTENT_EMPTY;
        !          6382:         } else if ((cur->type == XML_RELAXNG_ONEORMORE) ||
        !          6383:                    (cur->type == XML_RELAXNG_ZEROORMORE)) {
        !          6384:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6385:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ONEMORE,
        !          6386:                            "Found forbidden pattern data/except//oneOrMore\n",
        !          6387:                            NULL, NULL);
        !          6388:             }
        !          6389:             if (flags & XML_RELAXNG_IN_START) {
        !          6390:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ONEMORE,
        !          6391:                            "Found forbidden pattern start//oneOrMore\n",
        !          6392:                            NULL, NULL);
        !          6393:             }
        !          6394:             nflags = flags | XML_RELAXNG_IN_ONEORMORE;
        !          6395:             ret =
        !          6396:                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
        !          6397:                                      cur->type);
        !          6398:             ret = xmlRelaxNGGroupContentType(ret, ret);
        !          6399:         } else if (cur->type == XML_RELAXNG_LIST) {
        !          6400:             if (flags & XML_RELAXNG_IN_LIST) {
        !          6401:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_LIST,
        !          6402:                            "Found forbidden pattern list//list\n", NULL,
        !          6403:                            NULL);
        !          6404:             }
        !          6405:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6406:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_LIST,
        !          6407:                            "Found forbidden pattern data/except//list\n",
        !          6408:                            NULL, NULL);
        !          6409:             }
        !          6410:             if (flags & XML_RELAXNG_IN_START) {
        !          6411:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_LIST,
        !          6412:                            "Found forbidden pattern start//list\n", NULL,
        !          6413:                            NULL);
        !          6414:             }
        !          6415:             nflags = flags | XML_RELAXNG_IN_LIST;
        !          6416:             ret =
        !          6417:                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
        !          6418:                                      cur->type);
        !          6419:         } else if (cur->type == XML_RELAXNG_GROUP) {
        !          6420:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6421:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_GROUP,
        !          6422:                            "Found forbidden pattern data/except//group\n",
        !          6423:                            NULL, NULL);
        !          6424:             }
        !          6425:             if (flags & XML_RELAXNG_IN_START) {
        !          6426:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_GROUP,
        !          6427:                            "Found forbidden pattern start//group\n", NULL,
        !          6428:                            NULL);
        !          6429:             }
        !          6430:             if (flags & XML_RELAXNG_IN_ONEORMORE)
        !          6431:                 nflags = flags | XML_RELAXNG_IN_OOMGROUP;
        !          6432:             else
        !          6433:                 nflags = flags;
        !          6434:             ret =
        !          6435:                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
        !          6436:                                      cur->type);
        !          6437:             /*
        !          6438:              * The 7.3 Attribute derivation rule for groups is plugged there
        !          6439:              */
        !          6440:             xmlRelaxNGCheckGroupAttrs(ctxt, cur);
        !          6441:         } else if (cur->type == XML_RELAXNG_INTERLEAVE) {
        !          6442:             if (flags & XML_RELAXNG_IN_LIST) {
        !          6443:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_INTERLEAVE,
        !          6444:                            "Found forbidden pattern list//interleave\n",
        !          6445:                            NULL, NULL);
        !          6446:             }
        !          6447:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6448:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
        !          6449:                            "Found forbidden pattern data/except//interleave\n",
        !          6450:                            NULL, NULL);
        !          6451:             }
        !          6452:             if (flags & XML_RELAXNG_IN_START) {
        !          6453:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
        !          6454:                            "Found forbidden pattern start//interleave\n",
        !          6455:                            NULL, NULL);
        !          6456:             }
        !          6457:             if (flags & XML_RELAXNG_IN_ONEORMORE)
        !          6458:                 nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE;
        !          6459:             else
        !          6460:                 nflags = flags;
        !          6461:             ret =
        !          6462:                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
        !          6463:                                      cur->type);
        !          6464:         } else if (cur->type == XML_RELAXNG_EXCEPT) {
        !          6465:             if ((cur->parent != NULL) &&
        !          6466:                 (cur->parent->type == XML_RELAXNG_DATATYPE))
        !          6467:                 nflags = flags | XML_RELAXNG_IN_DATAEXCEPT;
        !          6468:             else
        !          6469:                 nflags = flags;
        !          6470:             ret =
        !          6471:                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
        !          6472:                                      cur->type);
        !          6473:         } else if (cur->type == XML_RELAXNG_DATATYPE) {
        !          6474:             if (flags & XML_RELAXNG_IN_START) {
        !          6475:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_DATA,
        !          6476:                            "Found forbidden pattern start//data\n", NULL,
        !          6477:                            NULL);
        !          6478:             }
        !          6479:             xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
        !          6480:             ret = XML_RELAXNG_CONTENT_SIMPLE;
        !          6481:         } else if (cur->type == XML_RELAXNG_VALUE) {
        !          6482:             if (flags & XML_RELAXNG_IN_START) {
        !          6483:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_VALUE,
        !          6484:                            "Found forbidden pattern start//value\n", NULL,
        !          6485:                            NULL);
        !          6486:             }
        !          6487:             xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
        !          6488:             ret = XML_RELAXNG_CONTENT_SIMPLE;
        !          6489:         } else if (cur->type == XML_RELAXNG_TEXT) {
        !          6490:             if (flags & XML_RELAXNG_IN_LIST) {
        !          6491:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_TEXT,
        !          6492:                            "Found forbidden pattern list//text\n", NULL,
        !          6493:                            NULL);
        !          6494:             }
        !          6495:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6496:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_TEXT,
        !          6497:                            "Found forbidden pattern data/except//text\n",
        !          6498:                            NULL, NULL);
        !          6499:             }
        !          6500:             if (flags & XML_RELAXNG_IN_START) {
        !          6501:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_TEXT,
        !          6502:                            "Found forbidden pattern start//text\n", NULL,
        !          6503:                            NULL);
        !          6504:             }
        !          6505:             ret = XML_RELAXNG_CONTENT_COMPLEX;
        !          6506:         } else if (cur->type == XML_RELAXNG_EMPTY) {
        !          6507:             if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
        !          6508:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_EMPTY,
        !          6509:                            "Found forbidden pattern data/except//empty\n",
        !          6510:                            NULL, NULL);
        !          6511:             }
        !          6512:             if (flags & XML_RELAXNG_IN_START) {
        !          6513:                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_EMPTY,
        !          6514:                            "Found forbidden pattern start//empty\n", NULL,
        !          6515:                            NULL);
        !          6516:             }
        !          6517:             ret = XML_RELAXNG_CONTENT_EMPTY;
        !          6518:         } else if (cur->type == XML_RELAXNG_CHOICE) {
        !          6519:             xmlRelaxNGCheckChoiceDeterminism(ctxt, cur);
        !          6520:             ret =
        !          6521:                 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
        !          6522:         } else {
        !          6523:             ret =
        !          6524:                 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
        !          6525:         }
        !          6526:         cur = cur->next;
        !          6527:         if (ptype == XML_RELAXNG_GROUP) {
        !          6528:             val = xmlRelaxNGGroupContentType(val, ret);
        !          6529:         } else if (ptype == XML_RELAXNG_INTERLEAVE) {
        !          6530:             /*
        !          6531:              * TODO: scan complain that tmp is never used, seems on purpose
        !          6532:              *       need double-checking
        !          6533:              */
        !          6534:             tmp = xmlRelaxNGGroupContentType(val, ret);
        !          6535:             if (tmp != XML_RELAXNG_CONTENT_ERROR)
        !          6536:                 tmp = xmlRelaxNGMaxContentType(val, ret);
        !          6537:         } else if (ptype == XML_RELAXNG_CHOICE) {
        !          6538:             val = xmlRelaxNGMaxContentType(val, ret);
        !          6539:         } else if (ptype == XML_RELAXNG_LIST) {
        !          6540:             val = XML_RELAXNG_CONTENT_SIMPLE;
        !          6541:         } else if (ptype == XML_RELAXNG_EXCEPT) {
        !          6542:             if (ret == XML_RELAXNG_CONTENT_ERROR)
        !          6543:                 val = XML_RELAXNG_CONTENT_ERROR;
        !          6544:             else
        !          6545:                 val = XML_RELAXNG_CONTENT_SIMPLE;
        !          6546:         } else {
        !          6547:             val = xmlRelaxNGGroupContentType(val, ret);
        !          6548:         }
        !          6549: 
        !          6550:     }
        !          6551:     return (val);
        !          6552: }
        !          6553: 
        !          6554: /**
        !          6555:  * xmlRelaxNGParseGrammar:
        !          6556:  * @ctxt:  a Relax-NG parser context
        !          6557:  * @nodes:  grammar children nodes
        !          6558:  *
        !          6559:  * parse a Relax-NG <grammar> node
        !          6560:  *
        !          6561:  * Returns the internal xmlRelaxNGGrammarPtr built or
        !          6562:  *         NULL in case of error
        !          6563:  */
        !          6564: static xmlRelaxNGGrammarPtr
        !          6565: xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
        !          6566: {
        !          6567:     xmlRelaxNGGrammarPtr ret, tmp, old;
        !          6568: 
        !          6569: #ifdef DEBUG_GRAMMAR
        !          6570:     xmlGenericError(xmlGenericErrorContext, "Parsing a new grammar\n");
        !          6571: #endif
        !          6572: 
        !          6573:     ret = xmlRelaxNGNewGrammar(ctxt);
        !          6574:     if (ret == NULL)
        !          6575:         return (NULL);
        !          6576: 
        !          6577:     /*
        !          6578:      * Link the new grammar in the tree
        !          6579:      */
        !          6580:     ret->parent = ctxt->grammar;
        !          6581:     if (ctxt->grammar != NULL) {
        !          6582:         tmp = ctxt->grammar->children;
        !          6583:         if (tmp == NULL) {
        !          6584:             ctxt->grammar->children = ret;
        !          6585:         } else {
        !          6586:             while (tmp->next != NULL)
        !          6587:                 tmp = tmp->next;
        !          6588:             tmp->next = ret;
        !          6589:         }
        !          6590:     }
        !          6591: 
        !          6592:     old = ctxt->grammar;
        !          6593:     ctxt->grammar = ret;
        !          6594:     xmlRelaxNGParseGrammarContent(ctxt, nodes);
        !          6595:     ctxt->grammar = ret;
        !          6596:     if (ctxt->grammar == NULL) {
        !          6597:         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
        !          6598:                    "Failed to parse <grammar> content\n", NULL, NULL);
        !          6599:     } else if (ctxt->grammar->start == NULL) {
        !          6600:         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_NO_START,
        !          6601:                    "Element <grammar> has no <start>\n", NULL, NULL);
        !          6602:     }
        !          6603: 
        !          6604:     /*
        !          6605:      * Apply 4.17 mergingd rules to defines and starts
        !          6606:      */
        !          6607:     xmlRelaxNGCombineStart(ctxt, ret);
        !          6608:     if (ret->defs != NULL) {
        !          6609:         xmlHashScan(ret->defs, (xmlHashScanner) xmlRelaxNGCheckCombine,
        !          6610:                     ctxt);
        !          6611:     }
        !          6612: 
        !          6613:     /*
        !          6614:      * link together defines and refs in this grammar
        !          6615:      */
        !          6616:     if (ret->refs != NULL) {
        !          6617:         xmlHashScan(ret->refs, (xmlHashScanner) xmlRelaxNGCheckReference,
        !          6618:                     ctxt);
        !          6619:     }
        !          6620: 
        !          6621: 
        !          6622:     /* @@@@ */
        !          6623: 
        !          6624:     ctxt->grammar = old;
        !          6625:     return (ret);
        !          6626: }
        !          6627: 
        !          6628: /**
        !          6629:  * xmlRelaxNGParseDocument:
        !          6630:  * @ctxt:  a Relax-NG parser context
        !          6631:  * @node:  the root node of the RelaxNG schema
        !          6632:  *
        !          6633:  * parse a Relax-NG definition resource and build an internal
        !          6634:  * xmlRelaxNG struture which can be used to validate instances.
        !          6635:  *
        !          6636:  * Returns the internal XML RelaxNG structure built or
        !          6637:  *         NULL in case of error
        !          6638:  */
        !          6639: static xmlRelaxNGPtr
        !          6640: xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          6641: {
        !          6642:     xmlRelaxNGPtr schema = NULL;
        !          6643:     const xmlChar *olddefine;
        !          6644:     xmlRelaxNGGrammarPtr old;
        !          6645: 
        !          6646:     if ((ctxt == NULL) || (node == NULL))
        !          6647:         return (NULL);
        !          6648: 
        !          6649:     schema = xmlRelaxNGNewRelaxNG(ctxt);
        !          6650:     if (schema == NULL)
        !          6651:         return (NULL);
        !          6652: 
        !          6653:     olddefine = ctxt->define;
        !          6654:     ctxt->define = NULL;
        !          6655:     if (IS_RELAXNG(node, "grammar")) {
        !          6656:         schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children);
        !          6657:     } else {
        !          6658:         xmlRelaxNGGrammarPtr tmp, ret;
        !          6659: 
        !          6660:         schema->topgrammar = ret = xmlRelaxNGNewGrammar(ctxt);
        !          6661:         if (schema->topgrammar == NULL) {
        !          6662:             return (schema);
        !          6663:         }
        !          6664:         /*
        !          6665:          * Link the new grammar in the tree
        !          6666:          */
        !          6667:         ret->parent = ctxt->grammar;
        !          6668:         if (ctxt->grammar != NULL) {
        !          6669:             tmp = ctxt->grammar->children;
        !          6670:             if (tmp == NULL) {
        !          6671:                 ctxt->grammar->children = ret;
        !          6672:             } else {
        !          6673:                 while (tmp->next != NULL)
        !          6674:                     tmp = tmp->next;
        !          6675:                 tmp->next = ret;
        !          6676:             }
        !          6677:         }
        !          6678:         old = ctxt->grammar;
        !          6679:         ctxt->grammar = ret;
        !          6680:         xmlRelaxNGParseStart(ctxt, node);
        !          6681:         if (old != NULL)
        !          6682:             ctxt->grammar = old;
        !          6683:     }
        !          6684:     ctxt->define = olddefine;
        !          6685:     if (schema->topgrammar->start != NULL) {
        !          6686:         xmlRelaxNGCheckCycles(ctxt, schema->topgrammar->start, 0);
        !          6687:         if ((ctxt->flags & XML_RELAXNG_IN_EXTERNALREF) == 0) {
        !          6688:             xmlRelaxNGSimplify(ctxt, schema->topgrammar->start, NULL);
        !          6689:             while ((schema->topgrammar->start != NULL) &&
        !          6690:                    (schema->topgrammar->start->type == XML_RELAXNG_NOOP) &&
        !          6691:                    (schema->topgrammar->start->next != NULL))
        !          6692:                 schema->topgrammar->start =
        !          6693:                     schema->topgrammar->start->content;
        !          6694:             xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start,
        !          6695:                                  XML_RELAXNG_IN_START, XML_RELAXNG_NOOP);
        !          6696:         }
        !          6697:     }
        !          6698: #ifdef DEBUG
        !          6699:     if (schema == NULL)
        !          6700:         xmlGenericError(xmlGenericErrorContext,
        !          6701:                         "xmlRelaxNGParseDocument() failed\n");
        !          6702: #endif
        !          6703: 
        !          6704:     return (schema);
        !          6705: }
        !          6706: 
        !          6707: /************************************************************************
        !          6708:  *                                                                     *
        !          6709:  *                     Reading RelaxNGs                                *
        !          6710:  *                                                                     *
        !          6711:  ************************************************************************/
        !          6712: 
        !          6713: /**
        !          6714:  * xmlRelaxNGNewParserCtxt:
        !          6715:  * @URL:  the location of the schema
        !          6716:  *
        !          6717:  * Create an XML RelaxNGs parse context for that file/resource expected
        !          6718:  * to contain an XML RelaxNGs file.
        !          6719:  *
        !          6720:  * Returns the parser context or NULL in case of error
        !          6721:  */
        !          6722: xmlRelaxNGParserCtxtPtr
        !          6723: xmlRelaxNGNewParserCtxt(const char *URL)
        !          6724: {
        !          6725:     xmlRelaxNGParserCtxtPtr ret;
        !          6726: 
        !          6727:     if (URL == NULL)
        !          6728:         return (NULL);
        !          6729: 
        !          6730:     ret =
        !          6731:         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
        !          6732:     if (ret == NULL) {
        !          6733:         xmlRngPErrMemory(NULL, "building parser\n");
        !          6734:         return (NULL);
        !          6735:     }
        !          6736:     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
        !          6737:     ret->URL = xmlStrdup((const xmlChar *) URL);
        !          6738:     ret->error = xmlGenericError;
        !          6739:     ret->userData = xmlGenericErrorContext;
        !          6740:     return (ret);
        !          6741: }
        !          6742: 
        !          6743: /**
        !          6744:  * xmlRelaxNGNewMemParserCtxt:
        !          6745:  * @buffer:  a pointer to a char array containing the schemas
        !          6746:  * @size:  the size of the array
        !          6747:  *
        !          6748:  * Create an XML RelaxNGs parse context for that memory buffer expected
        !          6749:  * to contain an XML RelaxNGs file.
        !          6750:  *
        !          6751:  * Returns the parser context or NULL in case of error
        !          6752:  */
        !          6753: xmlRelaxNGParserCtxtPtr
        !          6754: xmlRelaxNGNewMemParserCtxt(const char *buffer, int size)
        !          6755: {
        !          6756:     xmlRelaxNGParserCtxtPtr ret;
        !          6757: 
        !          6758:     if ((buffer == NULL) || (size <= 0))
        !          6759:         return (NULL);
        !          6760: 
        !          6761:     ret =
        !          6762:         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
        !          6763:     if (ret == NULL) {
        !          6764:         xmlRngPErrMemory(NULL, "building parser\n");
        !          6765:         return (NULL);
        !          6766:     }
        !          6767:     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
        !          6768:     ret->buffer = buffer;
        !          6769:     ret->size = size;
        !          6770:     ret->error = xmlGenericError;
        !          6771:     ret->userData = xmlGenericErrorContext;
        !          6772:     return (ret);
        !          6773: }
        !          6774: 
        !          6775: /**
        !          6776:  * xmlRelaxNGNewDocParserCtxt:
        !          6777:  * @doc:  a preparsed document tree
        !          6778:  *
        !          6779:  * Create an XML RelaxNGs parser context for that document.
        !          6780:  * Note: since the process of compiling a RelaxNG schemas modifies the
        !          6781:  *       document, the @doc parameter is duplicated internally.
        !          6782:  *
        !          6783:  * Returns the parser context or NULL in case of error
        !          6784:  */
        !          6785: xmlRelaxNGParserCtxtPtr
        !          6786: xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc)
        !          6787: {
        !          6788:     xmlRelaxNGParserCtxtPtr ret;
        !          6789:     xmlDocPtr copy;
        !          6790: 
        !          6791:     if (doc == NULL)
        !          6792:         return (NULL);
        !          6793:     copy = xmlCopyDoc(doc, 1);
        !          6794:     if (copy == NULL)
        !          6795:         return (NULL);
        !          6796: 
        !          6797:     ret =
        !          6798:         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
        !          6799:     if (ret == NULL) {
        !          6800:         xmlRngPErrMemory(NULL, "building parser\n");
        !          6801:         return (NULL);
        !          6802:     }
        !          6803:     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
        !          6804:     ret->document = copy;
        !          6805:     ret->freedoc = 1;
        !          6806:     ret->userData = xmlGenericErrorContext;
        !          6807:     return (ret);
        !          6808: }
        !          6809: 
        !          6810: /**
        !          6811:  * xmlRelaxNGFreeParserCtxt:
        !          6812:  * @ctxt:  the schema parser context
        !          6813:  *
        !          6814:  * Free the resources associated to the schema parser context
        !          6815:  */
        !          6816: void
        !          6817: xmlRelaxNGFreeParserCtxt(xmlRelaxNGParserCtxtPtr ctxt)
        !          6818: {
        !          6819:     if (ctxt == NULL)
        !          6820:         return;
        !          6821:     if (ctxt->URL != NULL)
        !          6822:         xmlFree(ctxt->URL);
        !          6823:     if (ctxt->doc != NULL)
        !          6824:         xmlRelaxNGFreeDocument(ctxt->doc);
        !          6825:     if (ctxt->interleaves != NULL)
        !          6826:         xmlHashFree(ctxt->interleaves, NULL);
        !          6827:     if (ctxt->documents != NULL)
        !          6828:         xmlRelaxNGFreeDocumentList(ctxt->documents);
        !          6829:     if (ctxt->includes != NULL)
        !          6830:         xmlRelaxNGFreeIncludeList(ctxt->includes);
        !          6831:     if (ctxt->docTab != NULL)
        !          6832:         xmlFree(ctxt->docTab);
        !          6833:     if (ctxt->incTab != NULL)
        !          6834:         xmlFree(ctxt->incTab);
        !          6835:     if (ctxt->defTab != NULL) {
        !          6836:         int i;
        !          6837: 
        !          6838:         for (i = 0; i < ctxt->defNr; i++)
        !          6839:             xmlRelaxNGFreeDefine(ctxt->defTab[i]);
        !          6840:         xmlFree(ctxt->defTab);
        !          6841:     }
        !          6842:     if ((ctxt->document != NULL) && (ctxt->freedoc))
        !          6843:         xmlFreeDoc(ctxt->document);
        !          6844:     xmlFree(ctxt);
        !          6845: }
        !          6846: 
        !          6847: /**
        !          6848:  * xmlRelaxNGNormExtSpace:
        !          6849:  * @value:  a value
        !          6850:  *
        !          6851:  * Removes the leading and ending spaces of the value
        !          6852:  * The string is modified "in situ"
        !          6853:  */
        !          6854: static void
        !          6855: xmlRelaxNGNormExtSpace(xmlChar * value)
        !          6856: {
        !          6857:     xmlChar *start = value;
        !          6858:     xmlChar *cur = value;
        !          6859: 
        !          6860:     if (value == NULL)
        !          6861:         return;
        !          6862: 
        !          6863:     while (IS_BLANK_CH(*cur))
        !          6864:         cur++;
        !          6865:     if (cur == start) {
        !          6866:         do {
        !          6867:             while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
        !          6868:                 cur++;
        !          6869:             if (*cur == 0)
        !          6870:                 return;
        !          6871:             start = cur;
        !          6872:             while (IS_BLANK_CH(*cur))
        !          6873:                 cur++;
        !          6874:             if (*cur == 0) {
        !          6875:                 *start = 0;
        !          6876:                 return;
        !          6877:             }
        !          6878:         } while (1);
        !          6879:     } else {
        !          6880:         do {
        !          6881:             while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
        !          6882:                 *start++ = *cur++;
        !          6883:             if (*cur == 0) {
        !          6884:                 *start = 0;
        !          6885:                 return;
        !          6886:             }
        !          6887:             /* don't try to normalize the inner spaces */
        !          6888:             while (IS_BLANK_CH(*cur))
        !          6889:                 cur++;
        !          6890:             if (*cur == 0) {
        !          6891:                 *start = 0;
        !          6892:                 return;
        !          6893:             }
        !          6894:             *start++ = *cur++;
        !          6895:         } while (1);
        !          6896:     }
        !          6897: }
        !          6898: 
        !          6899: /**
        !          6900:  * xmlRelaxNGCleanupAttributes:
        !          6901:  * @ctxt:  a Relax-NG parser context
        !          6902:  * @node:  a Relax-NG node
        !          6903:  *
        !          6904:  * Check all the attributes on the given node
        !          6905:  */
        !          6906: static void
        !          6907: xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
        !          6908: {
        !          6909:     xmlAttrPtr cur, next;
        !          6910: 
        !          6911:     cur = node->properties;
        !          6912:     while (cur != NULL) {
        !          6913:         next = cur->next;
        !          6914:         if ((cur->ns == NULL) ||
        !          6915:             (xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
        !          6916:             if (xmlStrEqual(cur->name, BAD_CAST "name")) {
        !          6917:                 if ((!xmlStrEqual(node->name, BAD_CAST "element")) &&
        !          6918:                     (!xmlStrEqual(node->name, BAD_CAST "attribute")) &&
        !          6919:                     (!xmlStrEqual(node->name, BAD_CAST "ref")) &&
        !          6920:                     (!xmlStrEqual(node->name, BAD_CAST "parentRef")) &&
        !          6921:                     (!xmlStrEqual(node->name, BAD_CAST "param")) &&
        !          6922:                     (!xmlStrEqual(node->name, BAD_CAST "define"))) {
        !          6923:                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
        !          6924:                                "Attribute %s is not allowed on %s\n",
        !          6925:                                cur->name, node->name);
        !          6926:                 }
        !          6927:             } else if (xmlStrEqual(cur->name, BAD_CAST "type")) {
        !          6928:                 if ((!xmlStrEqual(node->name, BAD_CAST "value")) &&
        !          6929:                     (!xmlStrEqual(node->name, BAD_CAST "data"))) {
        !          6930:                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
        !          6931:                                "Attribute %s is not allowed on %s\n",
        !          6932:                                cur->name, node->name);
        !          6933:                 }
        !          6934:             } else if (xmlStrEqual(cur->name, BAD_CAST "href")) {
        !          6935:                 if ((!xmlStrEqual(node->name, BAD_CAST "externalRef")) &&
        !          6936:                     (!xmlStrEqual(node->name, BAD_CAST "include"))) {
        !          6937:                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
        !          6938:                                "Attribute %s is not allowed on %s\n",
        !          6939:                                cur->name, node->name);
        !          6940:                 }
        !          6941:             } else if (xmlStrEqual(cur->name, BAD_CAST "combine")) {
        !          6942:                 if ((!xmlStrEqual(node->name, BAD_CAST "start")) &&
        !          6943:                     (!xmlStrEqual(node->name, BAD_CAST "define"))) {
        !          6944:                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
        !          6945:                                "Attribute %s is not allowed on %s\n",
        !          6946:                                cur->name, node->name);
        !          6947:                 }
        !          6948:             } else if (xmlStrEqual(cur->name, BAD_CAST "datatypeLibrary")) {
        !          6949:                 xmlChar *val;
        !          6950:                 xmlURIPtr uri;
        !          6951: 
        !          6952:                 val = xmlNodeListGetString(node->doc, cur->children, 1);
        !          6953:                 if (val != NULL) {
        !          6954:                     if (val[0] != 0) {
        !          6955:                         uri = xmlParseURI((const char *) val);
        !          6956:                         if (uri == NULL) {
        !          6957:                             xmlRngPErr(ctxt, node, XML_RNGP_INVALID_URI,
        !          6958:                                        "Attribute %s contains invalid URI %s\n",
        !          6959:                                        cur->name, val);
        !          6960:                         } else {
        !          6961:                             if (uri->scheme == NULL) {
        !          6962:                                 xmlRngPErr(ctxt, node, XML_RNGP_URI_NOT_ABSOLUTE,
        !          6963:                                            "Attribute %s URI %s is not absolute\n",
        !          6964:                                            cur->name, val);
        !          6965:                             }
        !          6966:                             if (uri->fragment != NULL) {
        !          6967:                                 xmlRngPErr(ctxt, node, XML_RNGP_URI_FRAGMENT,
        !          6968:                                            "Attribute %s URI %s has a fragment ID\n",
        !          6969:                                            cur->name, val);
        !          6970:                             }
        !          6971:                             xmlFreeURI(uri);
        !          6972:                         }
        !          6973:                     }
        !          6974:                     xmlFree(val);
        !          6975:                 }
        !          6976:             } else if (!xmlStrEqual(cur->name, BAD_CAST "ns")) {
        !          6977:                 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_ATTRIBUTE,
        !          6978:                            "Unknown attribute %s on %s\n", cur->name,
        !          6979:                            node->name);
        !          6980:             }
        !          6981:         }
        !          6982:         cur = next;
        !          6983:     }
        !          6984: }
        !          6985: 
        !          6986: /**
        !          6987:  * xmlRelaxNGCleanupTree:
        !          6988:  * @ctxt:  a Relax-NG parser context
        !          6989:  * @root:  an xmlNodePtr subtree
        !          6990:  *
        !          6991:  * Cleanup the subtree from unwanted nodes for parsing, resolve
        !          6992:  * Include and externalRef lookups.
        !          6993:  */
        !          6994: static void
        !          6995: xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root)
        !          6996: {
        !          6997:     xmlNodePtr cur, delete;
        !          6998: 
        !          6999:     delete = NULL;
        !          7000:     cur = root;
        !          7001:     while (cur != NULL) {
        !          7002:         if (delete != NULL) {
        !          7003:             xmlUnlinkNode(delete);
        !          7004:             xmlFreeNode(delete);
        !          7005:             delete = NULL;
        !          7006:         }
        !          7007:         if (cur->type == XML_ELEMENT_NODE) {
        !          7008:             /*
        !          7009:              * Simplification 4.1. Annotations
        !          7010:              */
        !          7011:             if ((cur->ns == NULL) ||
        !          7012:                 (!xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
        !          7013:                 if ((cur->parent != NULL) &&
        !          7014:                     (cur->parent->type == XML_ELEMENT_NODE) &&
        !          7015:                     ((xmlStrEqual(cur->parent->name, BAD_CAST "name")) ||
        !          7016:                      (xmlStrEqual(cur->parent->name, BAD_CAST "value")) ||
        !          7017:                      (xmlStrEqual(cur->parent->name, BAD_CAST "param")))) {
        !          7018:                     xmlRngPErr(ctxt, cur, XML_RNGP_FOREIGN_ELEMENT,
        !          7019:                                "element %s doesn't allow foreign elements\n",
        !          7020:                                cur->parent->name, NULL);
        !          7021:                 }
        !          7022:                 delete = cur;
        !          7023:                 goto skip_children;
        !          7024:             } else {
        !          7025:                 xmlRelaxNGCleanupAttributes(ctxt, cur);
        !          7026:                 if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) {
        !          7027:                     xmlChar *href, *ns, *base, *URL;
        !          7028:                     xmlRelaxNGDocumentPtr docu;
        !          7029:                     xmlNodePtr tmp;
        !          7030:                    xmlURIPtr uri;
        !          7031: 
        !          7032:                     ns = xmlGetProp(cur, BAD_CAST "ns");
        !          7033:                     if (ns == NULL) {
        !          7034:                         tmp = cur->parent;
        !          7035:                         while ((tmp != NULL) &&
        !          7036:                                (tmp->type == XML_ELEMENT_NODE)) {
        !          7037:                             ns = xmlGetProp(tmp, BAD_CAST "ns");
        !          7038:                             if (ns != NULL)
        !          7039:                                 break;
        !          7040:                             tmp = tmp->parent;
        !          7041:                         }
        !          7042:                     }
        !          7043:                     href = xmlGetProp(cur, BAD_CAST "href");
        !          7044:                     if (href == NULL) {
        !          7045:                         xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
        !          7046:                                    "xmlRelaxNGParse: externalRef has no href attribute\n",
        !          7047:                                    NULL, NULL);
        !          7048:                         if (ns != NULL)
        !          7049:                             xmlFree(ns);
        !          7050:                         delete = cur;
        !          7051:                         goto skip_children;
        !          7052:                     }
        !          7053:                    uri = xmlParseURI((const char *) href);
        !          7054:                    if (uri == NULL) {
        !          7055:                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
        !          7056:                                    "Incorrect URI for externalRef %s\n",
        !          7057:                                    href, NULL);
        !          7058:                         if (ns != NULL)
        !          7059:                             xmlFree(ns);
        !          7060:                         if (href != NULL)
        !          7061:                             xmlFree(href);
        !          7062:                         delete = cur;
        !          7063:                         goto skip_children;
        !          7064:                    }
        !          7065:                    if (uri->fragment != NULL) {
        !          7066:                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
        !          7067:                               "Fragment forbidden in URI for externalRef %s\n",
        !          7068:                                    href, NULL);
        !          7069:                         if (ns != NULL)
        !          7070:                             xmlFree(ns);
        !          7071:                        xmlFreeURI(uri);
        !          7072:                         if (href != NULL)
        !          7073:                             xmlFree(href);
        !          7074:                         delete = cur;
        !          7075:                         goto skip_children;
        !          7076:                    }
        !          7077:                    xmlFreeURI(uri);
        !          7078:                     base = xmlNodeGetBase(cur->doc, cur);
        !          7079:                     URL = xmlBuildURI(href, base);
        !          7080:                     if (URL == NULL) {
        !          7081:                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
        !          7082:                                    "Failed to compute URL for externalRef %s\n",
        !          7083:                                    href, NULL);
        !          7084:                         if (ns != NULL)
        !          7085:                             xmlFree(ns);
        !          7086:                         if (href != NULL)
        !          7087:                             xmlFree(href);
        !          7088:                         if (base != NULL)
        !          7089:                             xmlFree(base);
        !          7090:                         delete = cur;
        !          7091:                         goto skip_children;
        !          7092:                     }
        !          7093:                     if (href != NULL)
        !          7094:                         xmlFree(href);
        !          7095:                     if (base != NULL)
        !          7096:                         xmlFree(base);
        !          7097:                     docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns);
        !          7098:                     if (docu == NULL) {
        !          7099:                         xmlRngPErr(ctxt, cur, XML_RNGP_EXTERNAL_REF_FAILURE,
        !          7100:                                    "Failed to load externalRef %s\n", URL,
        !          7101:                                    NULL);
        !          7102:                         if (ns != NULL)
        !          7103:                             xmlFree(ns);
        !          7104:                         xmlFree(URL);
        !          7105:                         delete = cur;
        !          7106:                         goto skip_children;
        !          7107:                     }
        !          7108:                     if (ns != NULL)
        !          7109:                         xmlFree(ns);
        !          7110:                     xmlFree(URL);
        !          7111:                     cur->psvi = docu;
        !          7112:                 } else if (xmlStrEqual(cur->name, BAD_CAST "include")) {
        !          7113:                     xmlChar *href, *ns, *base, *URL;
        !          7114:                     xmlRelaxNGIncludePtr incl;
        !          7115:                     xmlNodePtr tmp;
        !          7116: 
        !          7117:                     href = xmlGetProp(cur, BAD_CAST "href");
        !          7118:                     if (href == NULL) {
        !          7119:                         xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
        !          7120:                                    "xmlRelaxNGParse: include has no href attribute\n",
        !          7121:                                    NULL, NULL);
        !          7122:                         delete = cur;
        !          7123:                         goto skip_children;
        !          7124:                     }
        !          7125:                     base = xmlNodeGetBase(cur->doc, cur);
        !          7126:                     URL = xmlBuildURI(href, base);
        !          7127:                     if (URL == NULL) {
        !          7128:                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
        !          7129:                                    "Failed to compute URL for include %s\n",
        !          7130:                                    href, NULL);
        !          7131:                         if (href != NULL)
        !          7132:                             xmlFree(href);
        !          7133:                         if (base != NULL)
        !          7134:                             xmlFree(base);
        !          7135:                         delete = cur;
        !          7136:                         goto skip_children;
        !          7137:                     }
        !          7138:                     if (href != NULL)
        !          7139:                         xmlFree(href);
        !          7140:                     if (base != NULL)
        !          7141:                         xmlFree(base);
        !          7142:                     ns = xmlGetProp(cur, BAD_CAST "ns");
        !          7143:                     if (ns == NULL) {
        !          7144:                         tmp = cur->parent;
        !          7145:                         while ((tmp != NULL) &&
        !          7146:                                (tmp->type == XML_ELEMENT_NODE)) {
        !          7147:                             ns = xmlGetProp(tmp, BAD_CAST "ns");
        !          7148:                             if (ns != NULL)
        !          7149:                                 break;
        !          7150:                             tmp = tmp->parent;
        !          7151:                         }
        !          7152:                     }
        !          7153:                     incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns);
        !          7154:                     if (ns != NULL)
        !          7155:                         xmlFree(ns);
        !          7156:                     if (incl == NULL) {
        !          7157:                         xmlRngPErr(ctxt, cur, XML_RNGP_INCLUDE_FAILURE,
        !          7158:                                    "Failed to load include %s\n", URL,
        !          7159:                                    NULL);
        !          7160:                         xmlFree(URL);
        !          7161:                         delete = cur;
        !          7162:                         goto skip_children;
        !          7163:                     }
        !          7164:                     xmlFree(URL);
        !          7165:                     cur->psvi = incl;
        !          7166:                 } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) ||
        !          7167:                            (xmlStrEqual(cur->name, BAD_CAST "attribute")))
        !          7168:                 {
        !          7169:                     xmlChar *name, *ns;
        !          7170:                     xmlNodePtr text = NULL;
        !          7171: 
        !          7172:                     /*
        !          7173:                      * Simplification 4.8. name attribute of element
        !          7174:                      * and attribute elements
        !          7175:                      */
        !          7176:                     name = xmlGetProp(cur, BAD_CAST "name");
        !          7177:                     if (name != NULL) {
        !          7178:                         if (cur->children == NULL) {
        !          7179:                             text =
        !          7180:                                 xmlNewChild(cur, cur->ns, BAD_CAST "name",
        !          7181:                                             name);
        !          7182:                         } else {
        !          7183:                             xmlNodePtr node;
        !          7184: 
        !          7185:                             node = xmlNewDocNode(cur->doc, cur->ns,
        !          7186:                                                 BAD_CAST "name", NULL);
        !          7187:                             if (node != NULL) {
        !          7188:                                 xmlAddPrevSibling(cur->children, node);
        !          7189:                                 text = xmlNewText(name);
        !          7190:                                 xmlAddChild(node, text);
        !          7191:                                 text = node;
        !          7192:                             }
        !          7193:                         }
        !          7194:                         if (text == NULL) {
        !          7195:                             xmlRngPErr(ctxt, cur, XML_RNGP_CREATE_FAILURE,
        !          7196:                                        "Failed to create a name %s element\n",
        !          7197:                                        name, NULL);
        !          7198:                         }
        !          7199:                         xmlUnsetProp(cur, BAD_CAST "name");
        !          7200:                         xmlFree(name);
        !          7201:                         ns = xmlGetProp(cur, BAD_CAST "ns");
        !          7202:                         if (ns != NULL) {
        !          7203:                             if (text != NULL) {
        !          7204:                                 xmlSetProp(text, BAD_CAST "ns", ns);
        !          7205:                                 /* xmlUnsetProp(cur, BAD_CAST "ns"); */
        !          7206:                             }
        !          7207:                             xmlFree(ns);
        !          7208:                         } else if (xmlStrEqual(cur->name,
        !          7209:                                                BAD_CAST "attribute")) {
        !          7210:                             xmlSetProp(text, BAD_CAST "ns", BAD_CAST "");
        !          7211:                         }
        !          7212:                     }
        !          7213:                 } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) ||
        !          7214:                            (xmlStrEqual(cur->name, BAD_CAST "nsName")) ||
        !          7215:                            (xmlStrEqual(cur->name, BAD_CAST "value"))) {
        !          7216:                     /*
        !          7217:                      * Simplification 4.8. name attribute of element
        !          7218:                      * and attribute elements
        !          7219:                      */
        !          7220:                     if (xmlHasProp(cur, BAD_CAST "ns") == NULL) {
        !          7221:                         xmlNodePtr node;
        !          7222:                         xmlChar *ns = NULL;
        !          7223: 
        !          7224:                         node = cur->parent;
        !          7225:                         while ((node != NULL) &&
        !          7226:                                (node->type == XML_ELEMENT_NODE)) {
        !          7227:                             ns = xmlGetProp(node, BAD_CAST "ns");
        !          7228:                             if (ns != NULL) {
        !          7229:                                 break;
        !          7230:                             }
        !          7231:                             node = node->parent;
        !          7232:                         }
        !          7233:                         if (ns == NULL) {
        !          7234:                             xmlSetProp(cur, BAD_CAST "ns", BAD_CAST "");
        !          7235:                         } else {
        !          7236:                             xmlSetProp(cur, BAD_CAST "ns", ns);
        !          7237:                             xmlFree(ns);
        !          7238:                         }
        !          7239:                     }
        !          7240:                     if (xmlStrEqual(cur->name, BAD_CAST "name")) {
        !          7241:                         xmlChar *name, *local, *prefix;
        !          7242: 
        !          7243:                         /*
        !          7244:                          * Simplification: 4.10. QNames
        !          7245:                          */
        !          7246:                         name = xmlNodeGetContent(cur);
        !          7247:                         if (name != NULL) {
        !          7248:                             local = xmlSplitQName2(name, &prefix);
        !          7249:                             if (local != NULL) {
        !          7250:                                 xmlNsPtr ns;
        !          7251: 
        !          7252:                                 ns = xmlSearchNs(cur->doc, cur, prefix);
        !          7253:                                 if (ns == NULL) {
        !          7254:                                     xmlRngPErr(ctxt, cur,
        !          7255:                                                XML_RNGP_PREFIX_UNDEFINED,
        !          7256:                                                "xmlRelaxNGParse: no namespace for prefix %s\n",
        !          7257:                                                prefix, NULL);
        !          7258:                                 } else {
        !          7259:                                     xmlSetProp(cur, BAD_CAST "ns",
        !          7260:                                                ns->href);
        !          7261:                                     xmlNodeSetContent(cur, local);
        !          7262:                                 }
        !          7263:                                 xmlFree(local);
        !          7264:                                 xmlFree(prefix);
        !          7265:                             }
        !          7266:                             xmlFree(name);
        !          7267:                         }
        !          7268:                     }
        !          7269:                     /*
        !          7270:                      * 4.16
        !          7271:                      */
        !          7272:                     if (xmlStrEqual(cur->name, BAD_CAST "nsName")) {
        !          7273:                         if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
        !          7274:                             xmlRngPErr(ctxt, cur,
        !          7275:                                        XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME,
        !          7276:                                        "Found nsName/except//nsName forbidden construct\n",
        !          7277:                                        NULL, NULL);
        !          7278:                         }
        !          7279:                     }
        !          7280:                 } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) &&
        !          7281:                            (cur != root)) {
        !          7282:                     int oldflags = ctxt->flags;
        !          7283: 
        !          7284:                     /*
        !          7285:                      * 4.16
        !          7286:                      */
        !          7287:                     if ((cur->parent != NULL) &&
        !          7288:                         (xmlStrEqual
        !          7289:                          (cur->parent->name, BAD_CAST "anyName"))) {
        !          7290:                         ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT;
        !          7291:                         xmlRelaxNGCleanupTree(ctxt, cur);
        !          7292:                         ctxt->flags = oldflags;
        !          7293:                         goto skip_children;
        !          7294:                     } else if ((cur->parent != NULL) &&
        !          7295:                                (xmlStrEqual
        !          7296:                                 (cur->parent->name, BAD_CAST "nsName"))) {
        !          7297:                         ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT;
        !          7298:                         xmlRelaxNGCleanupTree(ctxt, cur);
        !          7299:                         ctxt->flags = oldflags;
        !          7300:                         goto skip_children;
        !          7301:                     }
        !          7302:                 } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) {
        !          7303:                     /*
        !          7304:                      * 4.16
        !          7305:                      */
        !          7306:                     if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) {
        !          7307:                         xmlRngPErr(ctxt, cur,
        !          7308:                                    XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME,
        !          7309:                                    "Found anyName/except//anyName forbidden construct\n",
        !          7310:                                    NULL, NULL);
        !          7311:                     } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
        !          7312:                         xmlRngPErr(ctxt, cur,
        !          7313:                                    XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME,
        !          7314:                                    "Found nsName/except//anyName forbidden construct\n",
        !          7315:                                    NULL, NULL);
        !          7316:                     }
        !          7317:                 }
        !          7318:                 /*
        !          7319:                  * Thisd is not an else since "include" is transformed
        !          7320:                  * into a div
        !          7321:                  */
        !          7322:                 if (xmlStrEqual(cur->name, BAD_CAST "div")) {
        !          7323:                     xmlChar *ns;
        !          7324:                     xmlNodePtr child, ins, tmp;
        !          7325: 
        !          7326:                     /*
        !          7327:                      * implements rule 4.11
        !          7328:                      */
        !          7329: 
        !          7330:                     ns = xmlGetProp(cur, BAD_CAST "ns");
        !          7331: 
        !          7332:                     child = cur->children;
        !          7333:                     ins = cur;
        !          7334:                     while (child != NULL) {
        !          7335:                         if (ns != NULL) {
        !          7336:                             if (!xmlHasProp(child, BAD_CAST "ns")) {
        !          7337:                                 xmlSetProp(child, BAD_CAST "ns", ns);
        !          7338:                             }
        !          7339:                         }
        !          7340:                         tmp = child->next;
        !          7341:                         xmlUnlinkNode(child);
        !          7342:                         ins = xmlAddNextSibling(ins, child);
        !          7343:                         child = tmp;
        !          7344:                     }
        !          7345:                     if (ns != NULL)
        !          7346:                         xmlFree(ns);
        !          7347:                    /*
        !          7348:                     * Since we are about to delete cur, if it's nsDef is non-NULL we
        !          7349:                     * need to preserve it (it contains the ns definitions for the
        !          7350:                     * children we just moved).  We'll just stick it on to the end
        !          7351:                     * of cur->parent's list, since it's never going to be re-serialized
        !          7352:                     * (bug 143738).
        !          7353:                     */
        !          7354:                    if (cur->nsDef != NULL) {
        !          7355:                        xmlNsPtr parDef = (xmlNsPtr)&cur->parent->nsDef;
        !          7356:                        while (parDef->next != NULL)
        !          7357:                            parDef = parDef->next;
        !          7358:                        parDef->next = cur->nsDef;
        !          7359:                        cur->nsDef = NULL;
        !          7360:                    }
        !          7361:                     delete = cur;
        !          7362:                     goto skip_children;
        !          7363:                 }
        !          7364:             }
        !          7365:         }
        !          7366:         /*
        !          7367:          * Simplification 4.2 whitespaces
        !          7368:          */
        !          7369:         else if ((cur->type == XML_TEXT_NODE) ||
        !          7370:                  (cur->type == XML_CDATA_SECTION_NODE)) {
        !          7371:             if (IS_BLANK_NODE(cur)) {
        !          7372:                 if (cur->parent->type == XML_ELEMENT_NODE) {
        !          7373:                     if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value"))
        !          7374:                         &&
        !          7375:                         (!xmlStrEqual
        !          7376:                          (cur->parent->name, BAD_CAST "param")))
        !          7377:                         delete = cur;
        !          7378:                 } else {
        !          7379:                     delete = cur;
        !          7380:                     goto skip_children;
        !          7381:                 }
        !          7382:             }
        !          7383:         } else {
        !          7384:             delete = cur;
        !          7385:             goto skip_children;
        !          7386:         }
        !          7387: 
        !          7388:         /*
        !          7389:          * Skip to next node
        !          7390:          */
        !          7391:         if (cur->children != NULL) {
        !          7392:             if ((cur->children->type != XML_ENTITY_DECL) &&
        !          7393:                 (cur->children->type != XML_ENTITY_REF_NODE) &&
        !          7394:                 (cur->children->type != XML_ENTITY_NODE)) {
        !          7395:                 cur = cur->children;
        !          7396:                 continue;
        !          7397:             }
        !          7398:         }
        !          7399:       skip_children:
        !          7400:         if (cur->next != NULL) {
        !          7401:             cur = cur->next;
        !          7402:             continue;
        !          7403:         }
        !          7404: 
        !          7405:         do {
        !          7406:             cur = cur->parent;
        !          7407:             if (cur == NULL)
        !          7408:                 break;
        !          7409:             if (cur == root) {
        !          7410:                 cur = NULL;
        !          7411:                 break;
        !          7412:             }
        !          7413:             if (cur->next != NULL) {
        !          7414:                 cur = cur->next;
        !          7415:                 break;
        !          7416:             }
        !          7417:         } while (cur != NULL);
        !          7418:     }
        !          7419:     if (delete != NULL) {
        !          7420:         xmlUnlinkNode(delete);
        !          7421:         xmlFreeNode(delete);
        !          7422:         delete = NULL;
        !          7423:     }
        !          7424: }
        !          7425: 
        !          7426: /**
        !          7427:  * xmlRelaxNGCleanupDoc:
        !          7428:  * @ctxt:  a Relax-NG parser context
        !          7429:  * @doc:  an xmldocPtr document pointer
        !          7430:  *
        !          7431:  * Cleanup the document from unwanted nodes for parsing, resolve
        !          7432:  * Include and externalRef lookups.
        !          7433:  *
        !          7434:  * Returns the cleaned up document or NULL in case of error
        !          7435:  */
        !          7436: static xmlDocPtr
        !          7437: xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc)
        !          7438: {
        !          7439:     xmlNodePtr root;
        !          7440: 
        !          7441:     /*
        !          7442:      * Extract the root
        !          7443:      */
        !          7444:     root = xmlDocGetRootElement(doc);
        !          7445:     if (root == NULL) {
        !          7446:         xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
        !          7447:                    ctxt->URL, NULL);
        !          7448:         return (NULL);
        !          7449:     }
        !          7450:     xmlRelaxNGCleanupTree(ctxt, root);
        !          7451:     return (doc);
        !          7452: }
        !          7453: 
        !          7454: /**
        !          7455:  * xmlRelaxNGParse:
        !          7456:  * @ctxt:  a Relax-NG parser context
        !          7457:  *
        !          7458:  * parse a schema definition resource and build an internal
        !          7459:  * XML Shema struture which can be used to validate instances.
        !          7460:  *
        !          7461:  * Returns the internal XML RelaxNG structure built from the resource or
        !          7462:  *         NULL in case of error
        !          7463:  */
        !          7464: xmlRelaxNGPtr
        !          7465: xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
        !          7466: {
        !          7467:     xmlRelaxNGPtr ret = NULL;
        !          7468:     xmlDocPtr doc;
        !          7469:     xmlNodePtr root;
        !          7470: 
        !          7471:     xmlRelaxNGInitTypes();
        !          7472: 
        !          7473:     if (ctxt == NULL)
        !          7474:         return (NULL);
        !          7475: 
        !          7476:     /*
        !          7477:      * First step is to parse the input document into an DOM/Infoset
        !          7478:      */
        !          7479:     if (ctxt->URL != NULL) {
        !          7480:         doc = xmlReadFile((const char *) ctxt->URL,NULL,0);
        !          7481:         if (doc == NULL) {
        !          7482:             xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
        !          7483:                        "xmlRelaxNGParse: could not load %s\n", ctxt->URL,
        !          7484:                        NULL);
        !          7485:             return (NULL);
        !          7486:         }
        !          7487:     } else if (ctxt->buffer != NULL) {
        !          7488:         doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0);
        !          7489:         if (doc == NULL) {
        !          7490:             xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
        !          7491:                        "xmlRelaxNGParse: could not parse schemas\n", NULL,
        !          7492:                        NULL);
        !          7493:             return (NULL);
        !          7494:         }
        !          7495:         doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
        !          7496:         ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
        !          7497:     } else if (ctxt->document != NULL) {
        !          7498:         doc = ctxt->document;
        !          7499:     } else {
        !          7500:         xmlRngPErr(ctxt, NULL, XML_RNGP_EMPTY,
        !          7501:                    "xmlRelaxNGParse: nothing to parse\n", NULL, NULL);
        !          7502:         return (NULL);
        !          7503:     }
        !          7504:     ctxt->document = doc;
        !          7505: 
        !          7506:     /*
        !          7507:      * Some preprocessing of the document content
        !          7508:      */
        !          7509:     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
        !          7510:     if (doc == NULL) {
        !          7511:         xmlFreeDoc(ctxt->document);
        !          7512:         ctxt->document = NULL;
        !          7513:         return (NULL);
        !          7514:     }
        !          7515: 
        !          7516:     /*
        !          7517:      * Then do the parsing for good
        !          7518:      */
        !          7519:     root = xmlDocGetRootElement(doc);
        !          7520:     if (root == NULL) {
        !          7521:         xmlRngPErr(ctxt, (xmlNodePtr) doc,
        !          7522:                   XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
        !          7523:                    (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL);
        !          7524:        
        !          7525:         xmlFreeDoc(ctxt->document);
        !          7526:         ctxt->document = NULL;
        !          7527:         return (NULL);
        !          7528:     }
        !          7529:     ret = xmlRelaxNGParseDocument(ctxt, root);
        !          7530:     if (ret == NULL) {
        !          7531:         xmlFreeDoc(ctxt->document);
        !          7532:         ctxt->document = NULL;
        !          7533:         return (NULL);
        !          7534:     }
        !          7535: 
        !          7536:     /*
        !          7537:      * Check the ref/defines links
        !          7538:      */
        !          7539:     /*
        !          7540:      * try to preprocess interleaves
        !          7541:      */
        !          7542:     if (ctxt->interleaves != NULL) {
        !          7543:         xmlHashScan(ctxt->interleaves,
        !          7544:                     (xmlHashScanner) xmlRelaxNGComputeInterleaves, ctxt);
        !          7545:     }
        !          7546: 
        !          7547:     /*
        !          7548:      * if there was a parsing error return NULL
        !          7549:      */
        !          7550:     if (ctxt->nbErrors > 0) {
        !          7551:         xmlRelaxNGFree(ret);
        !          7552:         ctxt->document = NULL;
        !          7553:         xmlFreeDoc(doc);
        !          7554:         return (NULL);
        !          7555:     }
        !          7556: 
        !          7557:     /*
        !          7558:      * try to compile (parts of) the schemas
        !          7559:      */
        !          7560:     if ((ret->topgrammar != NULL) && (ret->topgrammar->start != NULL)) {
        !          7561:         if (ret->topgrammar->start->type != XML_RELAXNG_START) {
        !          7562:             xmlRelaxNGDefinePtr def;
        !          7563: 
        !          7564:             def = xmlRelaxNGNewDefine(ctxt, NULL);
        !          7565:             if (def != NULL) {
        !          7566:                 def->type = XML_RELAXNG_START;
        !          7567:                 def->content = ret->topgrammar->start;
        !          7568:                 ret->topgrammar->start = def;
        !          7569:             }
        !          7570:         }
        !          7571:         xmlRelaxNGTryCompile(ctxt, ret->topgrammar->start);
        !          7572:     }
        !          7573: 
        !          7574:     /*
        !          7575:      * Transfer the pointer for cleanup at the schema level.
        !          7576:      */
        !          7577:     ret->doc = doc;
        !          7578:     ctxt->document = NULL;
        !          7579:     ret->documents = ctxt->documents;
        !          7580:     ctxt->documents = NULL;
        !          7581: 
        !          7582:     ret->includes = ctxt->includes;
        !          7583:     ctxt->includes = NULL;
        !          7584:     ret->defNr = ctxt->defNr;
        !          7585:     ret->defTab = ctxt->defTab;
        !          7586:     ctxt->defTab = NULL;
        !          7587:     if (ctxt->idref == 1)
        !          7588:         ret->idref = 1;
        !          7589: 
        !          7590:     return (ret);
        !          7591: }
        !          7592: 
        !          7593: /**
        !          7594:  * xmlRelaxNGSetParserErrors:
        !          7595:  * @ctxt:  a Relax-NG validation context
        !          7596:  * @err:  the error callback
        !          7597:  * @warn:  the warning callback
        !          7598:  * @ctx:  contextual data for the callbacks
        !          7599:  *
        !          7600:  * Set the callback functions used to handle errors for a validation context
        !          7601:  */
        !          7602: void
        !          7603: xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
        !          7604:                           xmlRelaxNGValidityErrorFunc err,
        !          7605:                           xmlRelaxNGValidityWarningFunc warn, void *ctx)
        !          7606: {
        !          7607:     if (ctxt == NULL)
        !          7608:         return;
        !          7609:     ctxt->error = err;
        !          7610:     ctxt->warning = warn;
        !          7611:     ctxt->serror = NULL;
        !          7612:     ctxt->userData = ctx;
        !          7613: }
        !          7614: 
        !          7615: /**
        !          7616:  * xmlRelaxNGGetParserErrors:
        !          7617:  * @ctxt:  a Relax-NG validation context
        !          7618:  * @err:  the error callback result
        !          7619:  * @warn:  the warning callback result
        !          7620:  * @ctx:  contextual data for the callbacks result
        !          7621:  *
        !          7622:  * Get the callback information used to handle errors for a validation context
        !          7623:  *
        !          7624:  * Returns -1 in case of failure, 0 otherwise.
        !          7625:  */
        !          7626: int
        !          7627: xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
        !          7628:                           xmlRelaxNGValidityErrorFunc * err,
        !          7629:                           xmlRelaxNGValidityWarningFunc * warn, void **ctx)
        !          7630: {
        !          7631:     if (ctxt == NULL)
        !          7632:         return (-1);
        !          7633:     if (err != NULL)
        !          7634:         *err = ctxt->error;
        !          7635:     if (warn != NULL)
        !          7636:         *warn = ctxt->warning;
        !          7637:     if (ctx != NULL)
        !          7638:         *ctx = ctxt->userData;
        !          7639:     return (0);
        !          7640: }
        !          7641: 
        !          7642: /**
        !          7643:  * xmlRelaxNGSetParserStructuredErrors:
        !          7644:  * @ctxt:  a Relax-NG parser context
        !          7645:  * @serror:  the error callback
        !          7646:  * @ctx:  contextual data for the callbacks
        !          7647:  *
        !          7648:  * Set the callback functions used to handle errors for a parsing context
        !          7649:  */
        !          7650: void
        !          7651: xmlRelaxNGSetParserStructuredErrors(xmlRelaxNGParserCtxtPtr ctxt,
        !          7652:                                    xmlStructuredErrorFunc serror,
        !          7653:                                    void *ctx)
        !          7654: {
        !          7655:     if (ctxt == NULL)
        !          7656:         return;
        !          7657:     ctxt->serror = serror;
        !          7658:     ctxt->error = NULL;
        !          7659:     ctxt->warning = NULL;
        !          7660:     ctxt->userData = ctx;
        !          7661: }
        !          7662: 
        !          7663: #ifdef LIBXML_OUTPUT_ENABLED
        !          7664: 
        !          7665: /************************************************************************
        !          7666:  *                                                                     *
        !          7667:  *                     Dump back a compiled form                       *
        !          7668:  *                                                                     *
        !          7669:  ************************************************************************/
        !          7670: static void xmlRelaxNGDumpDefine(FILE * output,
        !          7671:                                  xmlRelaxNGDefinePtr define);
        !          7672: 
        !          7673: /**
        !          7674:  * xmlRelaxNGDumpDefines:
        !          7675:  * @output:  the file output
        !          7676:  * @defines:  a list of define structures
        !          7677:  *
        !          7678:  * Dump a RelaxNG structure back
        !          7679:  */
        !          7680: static void
        !          7681: xmlRelaxNGDumpDefines(FILE * output, xmlRelaxNGDefinePtr defines)
        !          7682: {
        !          7683:     while (defines != NULL) {
        !          7684:         xmlRelaxNGDumpDefine(output, defines);
        !          7685:         defines = defines->next;
        !          7686:     }
        !          7687: }
        !          7688: 
        !          7689: /**
        !          7690:  * xmlRelaxNGDumpDefine:
        !          7691:  * @output:  the file output
        !          7692:  * @define:  a define structure
        !          7693:  *
        !          7694:  * Dump a RelaxNG structure back
        !          7695:  */
        !          7696: static void
        !          7697: xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define)
        !          7698: {
        !          7699:     if (define == NULL)
        !          7700:         return;
        !          7701:     switch (define->type) {
        !          7702:         case XML_RELAXNG_EMPTY:
        !          7703:             fprintf(output, "<empty/>\n");
        !          7704:             break;
        !          7705:         case XML_RELAXNG_NOT_ALLOWED:
        !          7706:             fprintf(output, "<notAllowed/>\n");
        !          7707:             break;
        !          7708:         case XML_RELAXNG_TEXT:
        !          7709:             fprintf(output, "<text/>\n");
        !          7710:             break;
        !          7711:         case XML_RELAXNG_ELEMENT:
        !          7712:             fprintf(output, "<element>\n");
        !          7713:             if (define->name != NULL) {
        !          7714:                 fprintf(output, "<name");
        !          7715:                 if (define->ns != NULL)
        !          7716:                     fprintf(output, " ns=\"%s\"", define->ns);
        !          7717:                 fprintf(output, ">%s</name>\n", define->name);
        !          7718:             }
        !          7719:             xmlRelaxNGDumpDefines(output, define->attrs);
        !          7720:             xmlRelaxNGDumpDefines(output, define->content);
        !          7721:             fprintf(output, "</element>\n");
        !          7722:             break;
        !          7723:         case XML_RELAXNG_LIST:
        !          7724:             fprintf(output, "<list>\n");
        !          7725:             xmlRelaxNGDumpDefines(output, define->content);
        !          7726:             fprintf(output, "</list>\n");
        !          7727:             break;
        !          7728:         case XML_RELAXNG_ONEORMORE:
        !          7729:             fprintf(output, "<oneOrMore>\n");
        !          7730:             xmlRelaxNGDumpDefines(output, define->content);
        !          7731:             fprintf(output, "</oneOrMore>\n");
        !          7732:             break;
        !          7733:         case XML_RELAXNG_ZEROORMORE:
        !          7734:             fprintf(output, "<zeroOrMore>\n");
        !          7735:             xmlRelaxNGDumpDefines(output, define->content);
        !          7736:             fprintf(output, "</zeroOrMore>\n");
        !          7737:             break;
        !          7738:         case XML_RELAXNG_CHOICE:
        !          7739:             fprintf(output, "<choice>\n");
        !          7740:             xmlRelaxNGDumpDefines(output, define->content);
        !          7741:             fprintf(output, "</choice>\n");
        !          7742:             break;
        !          7743:         case XML_RELAXNG_GROUP:
        !          7744:             fprintf(output, "<group>\n");
        !          7745:             xmlRelaxNGDumpDefines(output, define->content);
        !          7746:             fprintf(output, "</group>\n");
        !          7747:             break;
        !          7748:         case XML_RELAXNG_INTERLEAVE:
        !          7749:             fprintf(output, "<interleave>\n");
        !          7750:             xmlRelaxNGDumpDefines(output, define->content);
        !          7751:             fprintf(output, "</interleave>\n");
        !          7752:             break;
        !          7753:         case XML_RELAXNG_OPTIONAL:
        !          7754:             fprintf(output, "<optional>\n");
        !          7755:             xmlRelaxNGDumpDefines(output, define->content);
        !          7756:             fprintf(output, "</optional>\n");
        !          7757:             break;
        !          7758:         case XML_RELAXNG_ATTRIBUTE:
        !          7759:             fprintf(output, "<attribute>\n");
        !          7760:             xmlRelaxNGDumpDefines(output, define->content);
        !          7761:             fprintf(output, "</attribute>\n");
        !          7762:             break;
        !          7763:         case XML_RELAXNG_DEF:
        !          7764:             fprintf(output, "<define");
        !          7765:             if (define->name != NULL)
        !          7766:                 fprintf(output, " name=\"%s\"", define->name);
        !          7767:             fprintf(output, ">\n");
        !          7768:             xmlRelaxNGDumpDefines(output, define->content);
        !          7769:             fprintf(output, "</define>\n");
        !          7770:             break;
        !          7771:         case XML_RELAXNG_REF:
        !          7772:             fprintf(output, "<ref");
        !          7773:             if (define->name != NULL)
        !          7774:                 fprintf(output, " name=\"%s\"", define->name);
        !          7775:             fprintf(output, ">\n");
        !          7776:             xmlRelaxNGDumpDefines(output, define->content);
        !          7777:             fprintf(output, "</ref>\n");
        !          7778:             break;
        !          7779:         case XML_RELAXNG_PARENTREF:
        !          7780:             fprintf(output, "<parentRef");
        !          7781:             if (define->name != NULL)
        !          7782:                 fprintf(output, " name=\"%s\"", define->name);
        !          7783:             fprintf(output, ">\n");
        !          7784:             xmlRelaxNGDumpDefines(output, define->content);
        !          7785:             fprintf(output, "</parentRef>\n");
        !          7786:             break;
        !          7787:         case XML_RELAXNG_EXTERNALREF:
        !          7788:             fprintf(output, "<externalRef>");
        !          7789:             xmlRelaxNGDumpDefines(output, define->content);
        !          7790:             fprintf(output, "</externalRef>\n");
        !          7791:             break;
        !          7792:         case XML_RELAXNG_DATATYPE:
        !          7793:         case XML_RELAXNG_VALUE:
        !          7794:             TODO break;
        !          7795:         case XML_RELAXNG_START:
        !          7796:         case XML_RELAXNG_EXCEPT:
        !          7797:         case XML_RELAXNG_PARAM:
        !          7798:             TODO break;
        !          7799:         case XML_RELAXNG_NOOP:
        !          7800:             xmlRelaxNGDumpDefines(output, define->content);
        !          7801:             break;
        !          7802:     }
        !          7803: }
        !          7804: 
        !          7805: /**
        !          7806:  * xmlRelaxNGDumpGrammar:
        !          7807:  * @output:  the file output
        !          7808:  * @grammar:  a grammar structure
        !          7809:  * @top:  is this a top grammar 
        !          7810:  *
        !          7811:  * Dump a RelaxNG structure back
        !          7812:  */
        !          7813: static void
        !          7814: xmlRelaxNGDumpGrammar(FILE * output, xmlRelaxNGGrammarPtr grammar, int top)
        !          7815: {
        !          7816:     if (grammar == NULL)
        !          7817:         return;
        !          7818: 
        !          7819:     fprintf(output, "<grammar");
        !          7820:     if (top)
        !          7821:         fprintf(output, " xmlns=\"http://relaxng.org/ns/structure/1.0\"");
        !          7822:     switch (grammar->combine) {
        !          7823:         case XML_RELAXNG_COMBINE_UNDEFINED:
        !          7824:             break;
        !          7825:         case XML_RELAXNG_COMBINE_CHOICE:
        !          7826:             fprintf(output, " combine=\"choice\"");
        !          7827:             break;
        !          7828:         case XML_RELAXNG_COMBINE_INTERLEAVE:
        !          7829:             fprintf(output, " combine=\"interleave\"");
        !          7830:             break;
        !          7831:         default:
        !          7832:             fprintf(output, " <!-- invalid combine value -->");
        !          7833:     }
        !          7834:     fprintf(output, ">\n");
        !          7835:     if (grammar->start == NULL) {
        !          7836:         fprintf(output, " <!-- grammar had no start -->");
        !          7837:     } else {
        !          7838:         fprintf(output, "<start>\n");
        !          7839:         xmlRelaxNGDumpDefine(output, grammar->start);
        !          7840:         fprintf(output, "</start>\n");
        !          7841:     }
        !          7842:     /* TODO ? Dump the defines ? */
        !          7843:     fprintf(output, "</grammar>\n");
        !          7844: }
        !          7845: 
        !          7846: /**
        !          7847:  * xmlRelaxNGDump:
        !          7848:  * @output:  the file output
        !          7849:  * @schema:  a schema structure
        !          7850:  *
        !          7851:  * Dump a RelaxNG structure back
        !          7852:  */
        !          7853: void
        !          7854: xmlRelaxNGDump(FILE * output, xmlRelaxNGPtr schema)
        !          7855: {
        !          7856:     if (output == NULL)
        !          7857:         return;
        !          7858:     if (schema == NULL) {
        !          7859:         fprintf(output, "RelaxNG empty or failed to compile\n");
        !          7860:         return;
        !          7861:     }
        !          7862:     fprintf(output, "RelaxNG: ");
        !          7863:     if (schema->doc == NULL) {
        !          7864:         fprintf(output, "no document\n");
        !          7865:     } else if (schema->doc->URL != NULL) {
        !          7866:         fprintf(output, "%s\n", schema->doc->URL);
        !          7867:     } else {
        !          7868:         fprintf(output, "\n");
        !          7869:     }
        !          7870:     if (schema->topgrammar == NULL) {
        !          7871:         fprintf(output, "RelaxNG has no top grammar\n");
        !          7872:         return;
        !          7873:     }
        !          7874:     xmlRelaxNGDumpGrammar(output, schema->topgrammar, 1);
        !          7875: }
        !          7876: 
        !          7877: /**
        !          7878:  * xmlRelaxNGDumpTree:
        !          7879:  * @output:  the file output
        !          7880:  * @schema:  a schema structure
        !          7881:  *
        !          7882:  * Dump the transformed RelaxNG tree.
        !          7883:  */
        !          7884: void
        !          7885: xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema)
        !          7886: {
        !          7887:     if (output == NULL)
        !          7888:         return;
        !          7889:     if (schema == NULL) {
        !          7890:         fprintf(output, "RelaxNG empty or failed to compile\n");
        !          7891:         return;
        !          7892:     }
        !          7893:     if (schema->doc == NULL) {
        !          7894:         fprintf(output, "no document\n");
        !          7895:     } else {
        !          7896:         xmlDocDump(output, schema->doc);
        !          7897:     }
        !          7898: }
        !          7899: #endif /* LIBXML_OUTPUT_ENABLED */
        !          7900: 
        !          7901: /************************************************************************
        !          7902:  *                                                                     *
        !          7903:  *             Validation of compiled content                          *
        !          7904:  *                                                                     *
        !          7905:  ************************************************************************/
        !          7906: static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
        !          7907:                                         xmlRelaxNGDefinePtr define);
        !          7908: 
        !          7909: /**
        !          7910:  * xmlRelaxNGValidateCompiledCallback:
        !          7911:  * @exec:  the regular expression instance
        !          7912:  * @token:  the token which matched
        !          7913:  * @transdata:  callback data, the define for the subelement if available
        !          7914:  @ @inputdata:  callback data, the Relax NG validation context
        !          7915:  *
        !          7916:  * Handle the callback and if needed validate the element children.
        !          7917:  */
        !          7918: static void
        !          7919: xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
        !          7920:                                    const xmlChar * token,
        !          7921:                                    void *transdata, void *inputdata)
        !          7922: {
        !          7923:     xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
        !          7924:     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
        !          7925:     int ret;
        !          7926: 
        !          7927: #ifdef DEBUG_COMPILE
        !          7928:     xmlGenericError(xmlGenericErrorContext,
        !          7929:                     "Compiled callback for: '%s'\n", token);
        !          7930: #endif
        !          7931:     if (ctxt == NULL) {
        !          7932:         fprintf(stderr, "callback on %s missing context\n", token);
        !          7933:         return;
        !          7934:     }
        !          7935:     if (define == NULL) {
        !          7936:         if (token[0] == '#')
        !          7937:             return;
        !          7938:         fprintf(stderr, "callback on %s missing define\n", token);
        !          7939:         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
        !          7940:             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
        !          7941:         return;
        !          7942:     }
        !          7943:     if ((ctxt == NULL) || (define == NULL)) {
        !          7944:         fprintf(stderr, "callback on %s missing info\n", token);
        !          7945:         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
        !          7946:             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
        !          7947:         return;
        !          7948:     } else if (define->type != XML_RELAXNG_ELEMENT) {
        !          7949:         fprintf(stderr, "callback on %s define is not element\n", token);
        !          7950:         if (ctxt->errNo == XML_RELAXNG_OK)
        !          7951:             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
        !          7952:         return;
        !          7953:     }
        !          7954:     ret = xmlRelaxNGValidateDefinition(ctxt, define);
        !          7955:     if (ret != 0)
        !          7956:         ctxt->perr = ret;
        !          7957: }
        !          7958: 
        !          7959: /**
        !          7960:  * xmlRelaxNGValidateCompiledContent:
        !          7961:  * @ctxt:  the RelaxNG validation context
        !          7962:  * @regexp:  the regular expression as compiled
        !          7963:  * @content:  list of children to test against the regexp
        !          7964:  *
        !          7965:  * Validate the content model of an element or start using the regexp
        !          7966:  *
        !          7967:  * Returns 0 in case of success, -1 in case of error.
        !          7968:  */
        !          7969: static int
        !          7970: xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt,
        !          7971:                                   xmlRegexpPtr regexp, xmlNodePtr content)
        !          7972: {
        !          7973:     xmlRegExecCtxtPtr exec;
        !          7974:     xmlNodePtr cur;
        !          7975:     int ret = 0;
        !          7976:     int oldperr;
        !          7977: 
        !          7978:     if ((ctxt == NULL) || (regexp == NULL))
        !          7979:         return (-1);
        !          7980:     oldperr = ctxt->perr;
        !          7981:     exec = xmlRegNewExecCtxt(regexp,
        !          7982:                              xmlRelaxNGValidateCompiledCallback, ctxt);
        !          7983:     ctxt->perr = 0;
        !          7984:     cur = content;
        !          7985:     while (cur != NULL) {
        !          7986:         ctxt->state->seq = cur;
        !          7987:         switch (cur->type) {
        !          7988:             case XML_TEXT_NODE:
        !          7989:             case XML_CDATA_SECTION_NODE:
        !          7990:                 if (xmlIsBlankNode(cur))
        !          7991:                     break;
        !          7992:                 ret = xmlRegExecPushString(exec, BAD_CAST "#text", ctxt);
        !          7993:                 if (ret < 0) {
        !          7994:                     VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG,
        !          7995:                                cur->parent->name);
        !          7996:                 }
        !          7997:                 break;
        !          7998:             case XML_ELEMENT_NODE:
        !          7999:                 if (cur->ns != NULL) {
        !          8000:                     ret = xmlRegExecPushString2(exec, cur->name,
        !          8001:                                                 cur->ns->href, ctxt);
        !          8002:                 } else {
        !          8003:                     ret = xmlRegExecPushString(exec, cur->name, ctxt);
        !          8004:                 }
        !          8005:                 if (ret < 0) {
        !          8006:                     VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, cur->name);
        !          8007:                 }
        !          8008:                 break;
        !          8009:             default:
        !          8010:                 break;
        !          8011:         }
        !          8012:         if (ret < 0)
        !          8013:             break;
        !          8014:         /*
        !          8015:          * Switch to next element
        !          8016:          */
        !          8017:         cur = cur->next;
        !          8018:     }
        !          8019:     ret = xmlRegExecPushString(exec, NULL, NULL);
        !          8020:     if (ret == 1) {
        !          8021:         ret = 0;
        !          8022:         ctxt->state->seq = NULL;
        !          8023:     } else if (ret == 0) {
        !          8024:         /*
        !          8025:          * TODO: get some of the names needed to exit the current state of exec
        !          8026:          */
        !          8027:         VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
        !          8028:         ret = -1;
        !          8029:         if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
        !          8030:             xmlRelaxNGDumpValidError(ctxt);
        !          8031:     } else {
        !          8032:         ret = -1;
        !          8033:     }
        !          8034:     xmlRegFreeExecCtxt(exec);
        !          8035:     /*
        !          8036:      * There might be content model errors outside of the pure
        !          8037:      * regexp validation, e.g. for attribute values.
        !          8038:      */
        !          8039:     if ((ret == 0) && (ctxt->perr != 0)) {
        !          8040:         ret = ctxt->perr;
        !          8041:     }
        !          8042:     ctxt->perr = oldperr;
        !          8043:     return (ret);
        !          8044: }
        !          8045: 
        !          8046: /************************************************************************
        !          8047:  *                                                                     *
        !          8048:  *             Progressive validation of when possible                 *
        !          8049:  *                                                                     *
        !          8050:  ************************************************************************/
        !          8051: static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
        !          8052:                                            xmlRelaxNGDefinePtr defines);
        !          8053: static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt,
        !          8054:                                         int dolog);
        !          8055: static void xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt);
        !          8056: 
        !          8057: /**
        !          8058:  * xmlRelaxNGElemPush:
        !          8059:  * @ctxt:  the validation context
        !          8060:  * @exec:  the regexp runtime for the new content model
        !          8061:  *
        !          8062:  * Push a new regexp for the current node content model on the stack
        !          8063:  *
        !          8064:  * Returns 0 in case of success and -1 in case of error.
        !          8065:  */
        !          8066: static int
        !          8067: xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec)
        !          8068: {
        !          8069:     if (ctxt->elemTab == NULL) {
        !          8070:         ctxt->elemMax = 10;
        !          8071:         ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlMalloc(ctxt->elemMax *
        !          8072:                                                         sizeof
        !          8073:                                                         (xmlRegExecCtxtPtr));
        !          8074:         if (ctxt->elemTab == NULL) {
        !          8075:             xmlRngVErrMemory(ctxt, "validating\n");
        !          8076:             return (-1);
        !          8077:         }
        !          8078:     }
        !          8079:     if (ctxt->elemNr >= ctxt->elemMax) {
        !          8080:         ctxt->elemMax *= 2;
        !          8081:         ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlRealloc(ctxt->elemTab,
        !          8082:                                                          ctxt->elemMax *
        !          8083:                                                          sizeof
        !          8084:                                                          (xmlRegExecCtxtPtr));
        !          8085:         if (ctxt->elemTab == NULL) {
        !          8086:             xmlRngVErrMemory(ctxt, "validating\n");
        !          8087:             return (-1);
        !          8088:         }
        !          8089:     }
        !          8090:     ctxt->elemTab[ctxt->elemNr++] = exec;
        !          8091:     ctxt->elem = exec;
        !          8092:     return (0);
        !          8093: }
        !          8094: 
        !          8095: /**
        !          8096:  * xmlRelaxNGElemPop:
        !          8097:  * @ctxt:  the validation context
        !          8098:  *
        !          8099:  * Pop the regexp of the current node content model from the stack
        !          8100:  *
        !          8101:  * Returns the exec or NULL if empty
        !          8102:  */
        !          8103: static xmlRegExecCtxtPtr
        !          8104: xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt)
        !          8105: {
        !          8106:     xmlRegExecCtxtPtr ret;
        !          8107: 
        !          8108:     if (ctxt->elemNr <= 0)
        !          8109:         return (NULL);
        !          8110:     ctxt->elemNr--;
        !          8111:     ret = ctxt->elemTab[ctxt->elemNr];
        !          8112:     ctxt->elemTab[ctxt->elemNr] = NULL;
        !          8113:     if (ctxt->elemNr > 0)
        !          8114:         ctxt->elem = ctxt->elemTab[ctxt->elemNr - 1];
        !          8115:     else
        !          8116:         ctxt->elem = NULL;
        !          8117:     return (ret);
        !          8118: }
        !          8119: 
        !          8120: /**
        !          8121:  * xmlRelaxNGValidateProgressiveCallback:
        !          8122:  * @exec:  the regular expression instance
        !          8123:  * @token:  the token which matched
        !          8124:  * @transdata:  callback data, the define for the subelement if available
        !          8125:  @ @inputdata:  callback data, the Relax NG validation context
        !          8126:  *
        !          8127:  * Handle the callback and if needed validate the element children.
        !          8128:  * some of the in/out informations are passed via the context in @inputdata.
        !          8129:  */
        !          8130: static void
        !          8131: xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec
        !          8132:                                       ATTRIBUTE_UNUSED,
        !          8133:                                       const xmlChar * token,
        !          8134:                                       void *transdata, void *inputdata)
        !          8135: {
        !          8136:     xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
        !          8137:     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
        !          8138:     xmlRelaxNGValidStatePtr state, oldstate;
        !          8139:     xmlNodePtr node;
        !          8140:     int ret = 0, oldflags;
        !          8141: 
        !          8142: #ifdef DEBUG_PROGRESSIVE
        !          8143:     xmlGenericError(xmlGenericErrorContext,
        !          8144:                     "Progressive callback for: '%s'\n", token);
        !          8145: #endif
        !          8146:     if (ctxt == NULL) {
        !          8147:         fprintf(stderr, "callback on %s missing context\n", token);
        !          8148:         return;
        !          8149:     }
        !          8150:     node = ctxt->pnode;
        !          8151:     ctxt->pstate = 1;
        !          8152:     if (define == NULL) {
        !          8153:         if (token[0] == '#')
        !          8154:             return;
        !          8155:         fprintf(stderr, "callback on %s missing define\n", token);
        !          8156:         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
        !          8157:             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
        !          8158:         ctxt->pstate = -1;
        !          8159:         return;
        !          8160:     }
        !          8161:     if ((ctxt == NULL) || (define == NULL)) {
        !          8162:         fprintf(stderr, "callback on %s missing info\n", token);
        !          8163:         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
        !          8164:             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
        !          8165:         ctxt->pstate = -1;
        !          8166:         return;
        !          8167:     } else if (define->type != XML_RELAXNG_ELEMENT) {
        !          8168:         fprintf(stderr, "callback on %s define is not element\n", token);
        !          8169:         if (ctxt->errNo == XML_RELAXNG_OK)
        !          8170:             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
        !          8171:         ctxt->pstate = -1;
        !          8172:         return;
        !          8173:     }
        !          8174:     if (node->type != XML_ELEMENT_NODE) {
        !          8175:         VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
        !          8176:         if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
        !          8177:             xmlRelaxNGDumpValidError(ctxt);
        !          8178:         ctxt->pstate = -1;
        !          8179:         return;
        !          8180:     }
        !          8181:     if (define->contModel == NULL) {
        !          8182:         /*
        !          8183:          * this node cannot be validated in a streamable fashion
        !          8184:          */
        !          8185: #ifdef DEBUG_PROGRESSIVE
        !          8186:         xmlGenericError(xmlGenericErrorContext,
        !          8187:                         "Element '%s' validation is not streamable\n",
        !          8188:                         token);
        !          8189: #endif
        !          8190:         ctxt->pstate = 0;
        !          8191:         ctxt->pdef = define;
        !          8192:         return;
        !          8193:     }
        !          8194:     exec = xmlRegNewExecCtxt(define->contModel,
        !          8195:                              xmlRelaxNGValidateProgressiveCallback, ctxt);
        !          8196:     if (exec == NULL) {
        !          8197:         ctxt->pstate = -1;
        !          8198:         return;
        !          8199:     }
        !          8200:     xmlRelaxNGElemPush(ctxt, exec);
        !          8201: 
        !          8202:     /*
        !          8203:      * Validate the attributes part of the content.
        !          8204:      */
        !          8205:     state = xmlRelaxNGNewValidState(ctxt, node);
        !          8206:     if (state == NULL) {
        !          8207:         ctxt->pstate = -1;
        !          8208:         return;
        !          8209:     }
        !          8210:     oldstate = ctxt->state;
        !          8211:     ctxt->state = state;
        !          8212:     if (define->attrs != NULL) {
        !          8213:         ret = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
        !          8214:         if (ret != 0) {
        !          8215:             ctxt->pstate = -1;
        !          8216:             VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
        !          8217:         }
        !          8218:     }
        !          8219:     if (ctxt->state != NULL) {
        !          8220:         ctxt->state->seq = NULL;
        !          8221:         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
        !          8222:         if (ret != 0) {
        !          8223:             ctxt->pstate = -1;
        !          8224:         }
        !          8225:         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          8226:     } else if (ctxt->states != NULL) {
        !          8227:         int tmp = -1, i;
        !          8228: 
        !          8229:         oldflags = ctxt->flags;
        !          8230: 
        !          8231:         for (i = 0; i < ctxt->states->nbState; i++) {
        !          8232:             state = ctxt->states->tabState[i];
        !          8233:             ctxt->state = state;
        !          8234:             ctxt->state->seq = NULL;
        !          8235: 
        !          8236:             if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
        !          8237:                 tmp = 0;
        !          8238:                 break;
        !          8239:             }
        !          8240:         }
        !          8241:         if (tmp != 0) {
        !          8242:             /*
        !          8243:              * validation error, log the message for the "best" one
        !          8244:              */
        !          8245:             ctxt->flags |= FLAGS_IGNORABLE;
        !          8246:             xmlRelaxNGLogBestError(ctxt);
        !          8247:         }
        !          8248:         for (i = 0; i < ctxt->states->nbState; i++) {
        !          8249:             xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[i]);
        !          8250:         }
        !          8251:         xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          8252:         ctxt->states = NULL;
        !          8253:         if ((ret == 0) && (tmp == -1))
        !          8254:             ctxt->pstate = -1;
        !          8255:         ctxt->flags = oldflags;
        !          8256:     }
        !          8257:     if (ctxt->pstate == -1) {
        !          8258:         if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
        !          8259:             xmlRelaxNGDumpValidError(ctxt);
        !          8260:         }
        !          8261:     }
        !          8262:     ctxt->state = oldstate;
        !          8263: }
        !          8264: 
        !          8265: /**
        !          8266:  * xmlRelaxNGValidatePushElement:
        !          8267:  * @ctxt:  the validation context
        !          8268:  * @doc:  a document instance
        !          8269:  * @elem:  an element instance
        !          8270:  *
        !          8271:  * Push a new element start on the RelaxNG validation stack.
        !          8272:  *
        !          8273:  * returns 1 if no validation problem was found or 0 if validating the
        !          8274:  *         element requires a full node, and -1 in case of error.
        !          8275:  */
        !          8276: int
        !          8277: xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt,
        !          8278:                               xmlDocPtr doc ATTRIBUTE_UNUSED,
        !          8279:                               xmlNodePtr elem)
        !          8280: {
        !          8281:     int ret = 1;
        !          8282: 
        !          8283:     if ((ctxt == NULL) || (elem == NULL))
        !          8284:         return (-1);
        !          8285: 
        !          8286: #ifdef DEBUG_PROGRESSIVE
        !          8287:     xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name);
        !          8288: #endif
        !          8289:     if (ctxt->elem == 0) {
        !          8290:         xmlRelaxNGPtr schema;
        !          8291:         xmlRelaxNGGrammarPtr grammar;
        !          8292:         xmlRegExecCtxtPtr exec;
        !          8293:         xmlRelaxNGDefinePtr define;
        !          8294: 
        !          8295:         schema = ctxt->schema;
        !          8296:         if (schema == NULL) {
        !          8297:             VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
        !          8298:             return (-1);
        !          8299:         }
        !          8300:         grammar = schema->topgrammar;
        !          8301:         if ((grammar == NULL) || (grammar->start == NULL)) {
        !          8302:             VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
        !          8303:             return (-1);
        !          8304:         }
        !          8305:         define = grammar->start;
        !          8306:         if (define->contModel == NULL) {
        !          8307:             ctxt->pdef = define;
        !          8308:             return (0);
        !          8309:         }
        !          8310:         exec = xmlRegNewExecCtxt(define->contModel,
        !          8311:                                  xmlRelaxNGValidateProgressiveCallback,
        !          8312:                                  ctxt);
        !          8313:         if (exec == NULL) {
        !          8314:             return (-1);
        !          8315:         }
        !          8316:         xmlRelaxNGElemPush(ctxt, exec);
        !          8317:     }
        !          8318:     ctxt->pnode = elem;
        !          8319:     ctxt->pstate = 0;
        !          8320:     if (elem->ns != NULL) {
        !          8321:         ret =
        !          8322:             xmlRegExecPushString2(ctxt->elem, elem->name, elem->ns->href,
        !          8323:                                   ctxt);
        !          8324:     } else {
        !          8325:         ret = xmlRegExecPushString(ctxt->elem, elem->name, ctxt);
        !          8326:     }
        !          8327:     if (ret < 0) {
        !          8328:         VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, elem->name);
        !          8329:     } else {
        !          8330:         if (ctxt->pstate == 0)
        !          8331:             ret = 0;
        !          8332:         else if (ctxt->pstate < 0)
        !          8333:             ret = -1;
        !          8334:         else
        !          8335:             ret = 1;
        !          8336:     }
        !          8337: #ifdef DEBUG_PROGRESSIVE
        !          8338:     if (ret < 0)
        !          8339:         xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n",
        !          8340:                         elem->name);
        !          8341: #endif
        !          8342:     return (ret);
        !          8343: }
        !          8344: 
        !          8345: /**
        !          8346:  * xmlRelaxNGValidatePushCData:
        !          8347:  * @ctxt:  the RelaxNG validation context
        !          8348:  * @data:  some character data read
        !          8349:  * @len:  the lenght of the data
        !          8350:  *
        !          8351:  * check the CData parsed for validation in the current stack
        !          8352:  *
        !          8353:  * returns 1 if no validation problem was found or -1 otherwise
        !          8354:  */
        !          8355: int
        !          8356: xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt,
        !          8357:                             const xmlChar * data, int len ATTRIBUTE_UNUSED)
        !          8358: {
        !          8359:     int ret = 1;
        !          8360: 
        !          8361:     if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL))
        !          8362:         return (-1);
        !          8363: 
        !          8364: #ifdef DEBUG_PROGRESSIVE
        !          8365:     xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len);
        !          8366: #endif
        !          8367: 
        !          8368:     while (*data != 0) {
        !          8369:         if (!IS_BLANK_CH(*data))
        !          8370:             break;
        !          8371:         data++;
        !          8372:     }
        !          8373:     if (*data == 0)
        !          8374:         return (1);
        !          8375: 
        !          8376:     ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt);
        !          8377:     if (ret < 0) {
        !          8378:         VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO ");
        !          8379: #ifdef DEBUG_PROGRESSIVE
        !          8380:         xmlGenericError(xmlGenericErrorContext, "CDATA failed\n");
        !          8381: #endif
        !          8382: 
        !          8383:         return (-1);
        !          8384:     }
        !          8385:     return (1);
        !          8386: }
        !          8387: 
        !          8388: /**
        !          8389:  * xmlRelaxNGValidatePopElement:
        !          8390:  * @ctxt:  the RelaxNG validation context
        !          8391:  * @doc:  a document instance
        !          8392:  * @elem:  an element instance
        !          8393:  *
        !          8394:  * Pop the element end from the RelaxNG validation stack.
        !          8395:  *
        !          8396:  * returns 1 if no validation problem was found or 0 otherwise
        !          8397:  */
        !          8398: int
        !          8399: xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,
        !          8400:                              xmlDocPtr doc ATTRIBUTE_UNUSED,
        !          8401:                              xmlNodePtr elem)
        !          8402: {
        !          8403:     int ret;
        !          8404:     xmlRegExecCtxtPtr exec;
        !          8405: 
        !          8406:     if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL))
        !          8407:         return (-1);
        !          8408: #ifdef DEBUG_PROGRESSIVE
        !          8409:     xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name);
        !          8410: #endif
        !          8411:     /*
        !          8412:      * verify that we reached a terminal state of the content model.
        !          8413:      */
        !          8414:     exec = xmlRelaxNGElemPop(ctxt);
        !          8415:     ret = xmlRegExecPushString(exec, NULL, NULL);
        !          8416:     if (ret == 0) {
        !          8417:         /*
        !          8418:          * TODO: get some of the names needed to exit the current state of exec
        !          8419:          */
        !          8420:         VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
        !          8421:         ret = -1;
        !          8422:     } else if (ret < 0) {
        !          8423:         ret = -1;
        !          8424:     } else {
        !          8425:         ret = 1;
        !          8426:     }
        !          8427:     xmlRegFreeExecCtxt(exec);
        !          8428: #ifdef DEBUG_PROGRESSIVE
        !          8429:     if (ret < 0)
        !          8430:         xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n",
        !          8431:                         elem->name);
        !          8432: #endif
        !          8433:     return (ret);
        !          8434: }
        !          8435: 
        !          8436: /**
        !          8437:  * xmlRelaxNGValidateFullElement:
        !          8438:  * @ctxt:  the validation context
        !          8439:  * @doc:  a document instance
        !          8440:  * @elem:  an element instance
        !          8441:  *
        !          8442:  * Validate a full subtree when xmlRelaxNGValidatePushElement() returned
        !          8443:  * 0 and the content of the node has been expanded.
        !          8444:  *
        !          8445:  * returns 1 if no validation problem was found or -1 in case of error.
        !          8446:  */
        !          8447: int
        !          8448: xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt,
        !          8449:                               xmlDocPtr doc ATTRIBUTE_UNUSED,
        !          8450:                               xmlNodePtr elem)
        !          8451: {
        !          8452:     int ret;
        !          8453:     xmlRelaxNGValidStatePtr state;
        !          8454: 
        !          8455:     if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL))
        !          8456:         return (-1);
        !          8457: #ifdef DEBUG_PROGRESSIVE
        !          8458:     xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name);
        !          8459: #endif
        !          8460:     state = xmlRelaxNGNewValidState(ctxt, elem->parent);
        !          8461:     if (state == NULL) {
        !          8462:         return (-1);
        !          8463:     }
        !          8464:     state->seq = elem;
        !          8465:     ctxt->state = state;
        !          8466:     ctxt->errNo = XML_RELAXNG_OK;
        !          8467:     ret = xmlRelaxNGValidateDefinition(ctxt, ctxt->pdef);
        !          8468:     if ((ret != 0) || (ctxt->errNo != XML_RELAXNG_OK))
        !          8469:         ret = -1;
        !          8470:     else
        !          8471:         ret = 1;
        !          8472:     xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          8473:     ctxt->state = NULL;
        !          8474: #ifdef DEBUG_PROGRESSIVE
        !          8475:     if (ret < 0)
        !          8476:         xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n",
        !          8477:                         elem->name);
        !          8478: #endif
        !          8479:     return (ret);
        !          8480: }
        !          8481: 
        !          8482: /************************************************************************
        !          8483:  *                                                                     *
        !          8484:  *             Generic interpreted validation implementation           *
        !          8485:  *                                                                     *
        !          8486:  ************************************************************************/
        !          8487: static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
        !          8488:                                    xmlRelaxNGDefinePtr define);
        !          8489: 
        !          8490: /**
        !          8491:  * xmlRelaxNGSkipIgnored:
        !          8492:  * @ctxt:  a schema validation context
        !          8493:  * @node:  the top node.
        !          8494:  *
        !          8495:  * Skip ignorable nodes in that context
        !          8496:  *
        !          8497:  * Returns the new sibling or NULL in case of error.
        !          8498:  */
        !          8499: static xmlNodePtr
        !          8500: xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
        !          8501:                       xmlNodePtr node)
        !          8502: {
        !          8503:     /*
        !          8504:      * TODO complete and handle entities
        !          8505:      */
        !          8506:     while ((node != NULL) &&
        !          8507:            ((node->type == XML_COMMENT_NODE) ||
        !          8508:             (node->type == XML_PI_NODE) ||
        !          8509:            (node->type == XML_XINCLUDE_START) ||
        !          8510:            (node->type == XML_XINCLUDE_END) ||
        !          8511:             (((node->type == XML_TEXT_NODE) ||
        !          8512:               (node->type == XML_CDATA_SECTION_NODE)) &&
        !          8513:              ((ctxt->flags & FLAGS_MIXED_CONTENT) ||
        !          8514:               (IS_BLANK_NODE(node)))))) {
        !          8515:         node = node->next;
        !          8516:     }
        !          8517:     return (node);
        !          8518: }
        !          8519: 
        !          8520: /**
        !          8521:  * xmlRelaxNGNormalize:
        !          8522:  * @ctxt:  a schema validation context
        !          8523:  * @str:  the string to normalize
        !          8524:  *
        !          8525:  * Implements the  normalizeWhiteSpace( s ) function from
        !          8526:  * section 6.2.9 of the spec
        !          8527:  *
        !          8528:  * Returns the new string or NULL in case of error.
        !          8529:  */
        !          8530: static xmlChar *
        !          8531: xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str)
        !          8532: {
        !          8533:     xmlChar *ret, *p;
        !          8534:     const xmlChar *tmp;
        !          8535:     int len;
        !          8536: 
        !          8537:     if (str == NULL)
        !          8538:         return (NULL);
        !          8539:     tmp = str;
        !          8540:     while (*tmp != 0)
        !          8541:         tmp++;
        !          8542:     len = tmp - str;
        !          8543: 
        !          8544:     ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
        !          8545:     if (ret == NULL) {
        !          8546:         xmlRngVErrMemory(ctxt, "validating\n");
        !          8547:         return (NULL);
        !          8548:     }
        !          8549:     p = ret;
        !          8550:     while (IS_BLANK_CH(*str))
        !          8551:         str++;
        !          8552:     while (*str != 0) {
        !          8553:         if (IS_BLANK_CH(*str)) {
        !          8554:             while (IS_BLANK_CH(*str))
        !          8555:                 str++;
        !          8556:             if (*str == 0)
        !          8557:                 break;
        !          8558:             *p++ = ' ';
        !          8559:         } else
        !          8560:             *p++ = *str++;
        !          8561:     }
        !          8562:     *p = 0;
        !          8563:     return (ret);
        !          8564: }
        !          8565: 
        !          8566: /**
        !          8567:  * xmlRelaxNGValidateDatatype:
        !          8568:  * @ctxt:  a Relax-NG validation context
        !          8569:  * @value:  the string value
        !          8570:  * @type:  the datatype definition
        !          8571:  * @node:  the node
        !          8572:  *
        !          8573:  * Validate the given value against the dataype
        !          8574:  *
        !          8575:  * Returns 0 if the validation succeeded or an error code.
        !          8576:  */
        !          8577: static int
        !          8578: xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt,
        !          8579:                            const xmlChar * value,
        !          8580:                            xmlRelaxNGDefinePtr define, xmlNodePtr node)
        !          8581: {
        !          8582:     int ret, tmp;
        !          8583:     xmlRelaxNGTypeLibraryPtr lib;
        !          8584:     void *result = NULL;
        !          8585:     xmlRelaxNGDefinePtr cur;
        !          8586: 
        !          8587:     if ((define == NULL) || (define->data == NULL)) {
        !          8588:         return (-1);
        !          8589:     }
        !          8590:     lib = (xmlRelaxNGTypeLibraryPtr) define->data;
        !          8591:     if (lib->check != NULL) {
        !          8592:         if ((define->attrs != NULL) &&
        !          8593:             (define->attrs->type == XML_RELAXNG_PARAM)) {
        !          8594:             ret =
        !          8595:                 lib->check(lib->data, define->name, value, &result, node);
        !          8596:         } else {
        !          8597:             ret = lib->check(lib->data, define->name, value, NULL, node);
        !          8598:         }
        !          8599:     } else
        !          8600:         ret = -1;
        !          8601:     if (ret < 0) {
        !          8602:         VALID_ERR2(XML_RELAXNG_ERR_TYPE, define->name);
        !          8603:         if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
        !          8604:             lib->freef(lib->data, result);
        !          8605:         return (-1);
        !          8606:     } else if (ret == 1) {
        !          8607:         ret = 0;
        !          8608:     } else if (ret == 2) {
        !          8609:         VALID_ERR2P(XML_RELAXNG_ERR_DUPID, value);
        !          8610:     } else {
        !          8611:         VALID_ERR3P(XML_RELAXNG_ERR_TYPEVAL, define->name, value);
        !          8612:         ret = -1;
        !          8613:     }
        !          8614:     cur = define->attrs;
        !          8615:     while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) {
        !          8616:         if (lib->facet != NULL) {
        !          8617:             tmp = lib->facet(lib->data, define->name, cur->name,
        !          8618:                              cur->value, value, result);
        !          8619:             if (tmp != 0)
        !          8620:                 ret = -1;
        !          8621:         }
        !          8622:         cur = cur->next;
        !          8623:     }
        !          8624:     if ((ret == 0) && (define->content != NULL)) {
        !          8625:         const xmlChar *oldvalue, *oldendvalue;
        !          8626: 
        !          8627:         oldvalue = ctxt->state->value;
        !          8628:         oldendvalue = ctxt->state->endvalue;
        !          8629:         ctxt->state->value = (xmlChar *) value;
        !          8630:         ctxt->state->endvalue = NULL;
        !          8631:         ret = xmlRelaxNGValidateValue(ctxt, define->content);
        !          8632:         ctxt->state->value = (xmlChar *) oldvalue;
        !          8633:         ctxt->state->endvalue = (xmlChar *) oldendvalue;
        !          8634:     }
        !          8635:     if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
        !          8636:         lib->freef(lib->data, result);
        !          8637:     return (ret);
        !          8638: }
        !          8639: 
        !          8640: /**
        !          8641:  * xmlRelaxNGNextValue:
        !          8642:  * @ctxt:  a Relax-NG validation context
        !          8643:  *
        !          8644:  * Skip to the next value when validating within a list
        !          8645:  *
        !          8646:  * Returns 0 if the operation succeeded or an error code.
        !          8647:  */
        !          8648: static int
        !          8649: xmlRelaxNGNextValue(xmlRelaxNGValidCtxtPtr ctxt)
        !          8650: {
        !          8651:     xmlChar *cur;
        !          8652: 
        !          8653:     cur = ctxt->state->value;
        !          8654:     if ((cur == NULL) || (ctxt->state->endvalue == NULL)) {
        !          8655:         ctxt->state->value = NULL;
        !          8656:         ctxt->state->endvalue = NULL;
        !          8657:         return (0);
        !          8658:     }
        !          8659:     while (*cur != 0)
        !          8660:         cur++;
        !          8661:     while ((cur != ctxt->state->endvalue) && (*cur == 0))
        !          8662:         cur++;
        !          8663:     if (cur == ctxt->state->endvalue)
        !          8664:         ctxt->state->value = NULL;
        !          8665:     else
        !          8666:         ctxt->state->value = cur;
        !          8667:     return (0);
        !          8668: }
        !          8669: 
        !          8670: /**
        !          8671:  * xmlRelaxNGValidateValueList:
        !          8672:  * @ctxt:  a Relax-NG validation context
        !          8673:  * @defines:  the list of definitions to verify
        !          8674:  *
        !          8675:  * Validate the given set of definitions for the current value
        !          8676:  *
        !          8677:  * Returns 0 if the validation succeeded or an error code.
        !          8678:  */
        !          8679: static int
        !          8680: xmlRelaxNGValidateValueList(xmlRelaxNGValidCtxtPtr ctxt,
        !          8681:                             xmlRelaxNGDefinePtr defines)
        !          8682: {
        !          8683:     int ret = 0;
        !          8684: 
        !          8685:     while (defines != NULL) {
        !          8686:         ret = xmlRelaxNGValidateValue(ctxt, defines);
        !          8687:         if (ret != 0)
        !          8688:             break;
        !          8689:         defines = defines->next;
        !          8690:     }
        !          8691:     return (ret);
        !          8692: }
        !          8693: 
        !          8694: /**
        !          8695:  * xmlRelaxNGValidateValue:
        !          8696:  * @ctxt:  a Relax-NG validation context
        !          8697:  * @define:  the definition to verify
        !          8698:  *
        !          8699:  * Validate the given definition for the current value
        !          8700:  *
        !          8701:  * Returns 0 if the validation succeeded or an error code.
        !          8702:  */
        !          8703: static int
        !          8704: xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
        !          8705:                         xmlRelaxNGDefinePtr define)
        !          8706: {
        !          8707:     int ret = 0, oldflags;
        !          8708:     xmlChar *value;
        !          8709: 
        !          8710:     value = ctxt->state->value;
        !          8711:     switch (define->type) {
        !          8712:         case XML_RELAXNG_EMPTY:{
        !          8713:                 if ((value != NULL) && (value[0] != 0)) {
        !          8714:                     int idx = 0;
        !          8715: 
        !          8716:                     while (IS_BLANK_CH(value[idx]))
        !          8717:                         idx++;
        !          8718:                     if (value[idx] != 0)
        !          8719:                         ret = -1;
        !          8720:                 }
        !          8721:                 break;
        !          8722:             }
        !          8723:         case XML_RELAXNG_TEXT:
        !          8724:             break;
        !          8725:         case XML_RELAXNG_VALUE:{
        !          8726:                 if (!xmlStrEqual(value, define->value)) {
        !          8727:                     if (define->name != NULL) {
        !          8728:                         xmlRelaxNGTypeLibraryPtr lib;
        !          8729: 
        !          8730:                         lib = (xmlRelaxNGTypeLibraryPtr) define->data;
        !          8731:                         if ((lib != NULL) && (lib->comp != NULL)) {
        !          8732:                             ret = lib->comp(lib->data, define->name,
        !          8733:                                             define->value, define->node,
        !          8734:                                             (void *) define->attrs,
        !          8735:                                             value, ctxt->state->node);
        !          8736:                         } else
        !          8737:                             ret = -1;
        !          8738:                         if (ret < 0) {
        !          8739:                             VALID_ERR2(XML_RELAXNG_ERR_TYPECMP,
        !          8740:                                        define->name);
        !          8741:                             return (-1);
        !          8742:                         } else if (ret == 1) {
        !          8743:                             ret = 0;
        !          8744:                         } else {
        !          8745:                             ret = -1;
        !          8746:                         }
        !          8747:                     } else {
        !          8748:                         xmlChar *nval, *nvalue;
        !          8749: 
        !          8750:                         /*
        !          8751:                          * TODO: trivial optimizations are possible by
        !          8752:                          * computing at compile-time
        !          8753:                          */
        !          8754:                         nval = xmlRelaxNGNormalize(ctxt, define->value);
        !          8755:                         nvalue = xmlRelaxNGNormalize(ctxt, value);
        !          8756: 
        !          8757:                         if ((nval == NULL) || (nvalue == NULL) ||
        !          8758:                             (!xmlStrEqual(nval, nvalue)))
        !          8759:                             ret = -1;
        !          8760:                         if (nval != NULL)
        !          8761:                             xmlFree(nval);
        !          8762:                         if (nvalue != NULL)
        !          8763:                             xmlFree(nvalue);
        !          8764:                     }
        !          8765:                 }
        !          8766:                 if (ret == 0)
        !          8767:                     xmlRelaxNGNextValue(ctxt);
        !          8768:                 break;
        !          8769:             }
        !          8770:         case XML_RELAXNG_DATATYPE:{
        !          8771:                 ret = xmlRelaxNGValidateDatatype(ctxt, value, define,
        !          8772:                                                  ctxt->state->seq);
        !          8773:                 if (ret == 0)
        !          8774:                     xmlRelaxNGNextValue(ctxt);
        !          8775: 
        !          8776:                 break;
        !          8777:             }
        !          8778:         case XML_RELAXNG_CHOICE:{
        !          8779:                 xmlRelaxNGDefinePtr list = define->content;
        !          8780:                 xmlChar *oldvalue;
        !          8781: 
        !          8782:                 oldflags = ctxt->flags;
        !          8783:                 ctxt->flags |= FLAGS_IGNORABLE;
        !          8784: 
        !          8785:                 oldvalue = ctxt->state->value;
        !          8786:                 while (list != NULL) {
        !          8787:                     ret = xmlRelaxNGValidateValue(ctxt, list);
        !          8788:                     if (ret == 0) {
        !          8789:                         break;
        !          8790:                     }
        !          8791:                     ctxt->state->value = oldvalue;
        !          8792:                     list = list->next;
        !          8793:                 }
        !          8794:                 ctxt->flags = oldflags;
        !          8795:                 if (ret != 0) {
        !          8796:                     if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
        !          8797:                         xmlRelaxNGDumpValidError(ctxt);
        !          8798:                 } else {
        !          8799:                     if (ctxt->errNr > 0)
        !          8800:                         xmlRelaxNGPopErrors(ctxt, 0);
        !          8801:                 }
        !          8802:                 break;
        !          8803:             }
        !          8804:         case XML_RELAXNG_LIST:{
        !          8805:                 xmlRelaxNGDefinePtr list = define->content;
        !          8806:                 xmlChar *oldvalue, *oldend, *val, *cur;
        !          8807: 
        !          8808: #ifdef DEBUG_LIST
        !          8809:                 int nb_values = 0;
        !          8810: #endif
        !          8811: 
        !          8812:                 oldvalue = ctxt->state->value;
        !          8813:                 oldend = ctxt->state->endvalue;
        !          8814: 
        !          8815:                 val = xmlStrdup(oldvalue);
        !          8816:                 if (val == NULL) {
        !          8817:                     val = xmlStrdup(BAD_CAST "");
        !          8818:                 }
        !          8819:                 if (val == NULL) {
        !          8820:                     VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
        !          8821:                     return (-1);
        !          8822:                 }
        !          8823:                 cur = val;
        !          8824:                 while (*cur != 0) {
        !          8825:                     if (IS_BLANK_CH(*cur)) {
        !          8826:                         *cur = 0;
        !          8827:                         cur++;
        !          8828: #ifdef DEBUG_LIST
        !          8829:                         nb_values++;
        !          8830: #endif
        !          8831:                         while (IS_BLANK_CH(*cur))
        !          8832:                             *cur++ = 0;
        !          8833:                     } else
        !          8834:                         cur++;
        !          8835:                 }
        !          8836: #ifdef DEBUG_LIST
        !          8837:                 xmlGenericError(xmlGenericErrorContext,
        !          8838:                                 "list value: '%s' found %d items\n",
        !          8839:                                 oldvalue, nb_values);
        !          8840:                 nb_values = 0;
        !          8841: #endif
        !          8842:                 ctxt->state->endvalue = cur;
        !          8843:                 cur = val;
        !          8844:                 while ((*cur == 0) && (cur != ctxt->state->endvalue))
        !          8845:                     cur++;
        !          8846: 
        !          8847:                 ctxt->state->value = cur;
        !          8848: 
        !          8849:                 while (list != NULL) {
        !          8850:                     if (ctxt->state->value == ctxt->state->endvalue)
        !          8851:                         ctxt->state->value = NULL;
        !          8852:                     ret = xmlRelaxNGValidateValue(ctxt, list);
        !          8853:                     if (ret != 0) {
        !          8854: #ifdef DEBUG_LIST
        !          8855:                         xmlGenericError(xmlGenericErrorContext,
        !          8856:                                         "Failed to validate value: '%s' with %d rule\n",
        !          8857:                                         ctxt->state->value, nb_values);
        !          8858: #endif
        !          8859:                         break;
        !          8860:                     }
        !          8861: #ifdef DEBUG_LIST
        !          8862:                     nb_values++;
        !          8863: #endif
        !          8864:                     list = list->next;
        !          8865:                 }
        !          8866: 
        !          8867:                 if ((ret == 0) && (ctxt->state->value != NULL) &&
        !          8868:                     (ctxt->state->value != ctxt->state->endvalue)) {
        !          8869:                     VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA,
        !          8870:                                ctxt->state->value);
        !          8871:                     ret = -1;
        !          8872:                 }
        !          8873:                 xmlFree(val);
        !          8874:                 ctxt->state->value = oldvalue;
        !          8875:                 ctxt->state->endvalue = oldend;
        !          8876:                 break;
        !          8877:             }
        !          8878:         case XML_RELAXNG_ONEORMORE:
        !          8879:             ret = xmlRelaxNGValidateValueList(ctxt, define->content);
        !          8880:             if (ret != 0) {
        !          8881:                 break;
        !          8882:             }
        !          8883:             /* no break on purpose */
        !          8884:         case XML_RELAXNG_ZEROORMORE:{
        !          8885:                 xmlChar *cur, *temp;
        !          8886: 
        !          8887:                 oldflags = ctxt->flags;
        !          8888:                 ctxt->flags |= FLAGS_IGNORABLE;
        !          8889:                 cur = ctxt->state->value;
        !          8890:                 temp = NULL;
        !          8891:                 while ((cur != NULL) && (cur != ctxt->state->endvalue) &&
        !          8892:                        (temp != cur)) {
        !          8893:                     temp = cur;
        !          8894:                     ret =
        !          8895:                         xmlRelaxNGValidateValueList(ctxt, define->content);
        !          8896:                     if (ret != 0) {
        !          8897:                         ctxt->state->value = temp;
        !          8898:                         ret = 0;
        !          8899:                         break;
        !          8900:                     }
        !          8901:                     cur = ctxt->state->value;
        !          8902:                 }
        !          8903:                 ctxt->flags = oldflags;
        !          8904:                if (ctxt->errNr > 0)
        !          8905:                    xmlRelaxNGPopErrors(ctxt, 0);
        !          8906:                 break;
        !          8907:             }
        !          8908:         case XML_RELAXNG_EXCEPT:{
        !          8909:                 xmlRelaxNGDefinePtr list;
        !          8910: 
        !          8911:                 list = define->content;
        !          8912:                 while (list != NULL) {
        !          8913:                     ret = xmlRelaxNGValidateValue(ctxt, list);
        !          8914:                     if (ret == 0) {
        !          8915:                         ret = -1;
        !          8916:                         break;
        !          8917:                     } else
        !          8918:                         ret = 0;
        !          8919:                     list = list->next;
        !          8920:                 }
        !          8921:                 break;
        !          8922:             }
        !          8923:         case XML_RELAXNG_DEF:
        !          8924:         case XML_RELAXNG_GROUP:{
        !          8925:                 xmlRelaxNGDefinePtr list;
        !          8926: 
        !          8927:                 list = define->content;
        !          8928:                 while (list != NULL) {
        !          8929:                     ret = xmlRelaxNGValidateValue(ctxt, list);
        !          8930:                     if (ret != 0) {
        !          8931:                         ret = -1;
        !          8932:                         break;
        !          8933:                     } else
        !          8934:                         ret = 0;
        !          8935:                     list = list->next;
        !          8936:                 }
        !          8937:                 break;
        !          8938:             }
        !          8939:         case XML_RELAXNG_REF:
        !          8940:         case XML_RELAXNG_PARENTREF:
        !          8941:            if (define->content == NULL) {
        !          8942:                 VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
        !          8943:                 ret = -1;
        !          8944:            } else {
        !          8945:                 ret = xmlRelaxNGValidateValue(ctxt, define->content);
        !          8946:             }
        !          8947:             break;
        !          8948:         default:
        !          8949:             TODO ret = -1;
        !          8950:     }
        !          8951:     return (ret);
        !          8952: }
        !          8953: 
        !          8954: /**
        !          8955:  * xmlRelaxNGValidateValueContent:
        !          8956:  * @ctxt:  a Relax-NG validation context
        !          8957:  * @defines:  the list of definitions to verify
        !          8958:  *
        !          8959:  * Validate the given definitions for the current value
        !          8960:  *
        !          8961:  * Returns 0 if the validation succeeded or an error code.
        !          8962:  */
        !          8963: static int
        !          8964: xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt,
        !          8965:                                xmlRelaxNGDefinePtr defines)
        !          8966: {
        !          8967:     int ret = 0;
        !          8968: 
        !          8969:     while (defines != NULL) {
        !          8970:         ret = xmlRelaxNGValidateValue(ctxt, defines);
        !          8971:         if (ret != 0)
        !          8972:             break;
        !          8973:         defines = defines->next;
        !          8974:     }
        !          8975:     return (ret);
        !          8976: }
        !          8977: 
        !          8978: /**
        !          8979:  * xmlRelaxNGAttributeMatch:
        !          8980:  * @ctxt:  a Relax-NG validation context
        !          8981:  * @define:  the definition to check
        !          8982:  * @prop:  the attribute
        !          8983:  *
        !          8984:  * Check if the attribute matches the definition nameClass
        !          8985:  *
        !          8986:  * Returns 1 if the attribute matches, 0 if no, or -1 in case of error
        !          8987:  */
        !          8988: static int
        !          8989: xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt,
        !          8990:                          xmlRelaxNGDefinePtr define, xmlAttrPtr prop)
        !          8991: {
        !          8992:     int ret;
        !          8993: 
        !          8994:     if (define->name != NULL) {
        !          8995:         if (!xmlStrEqual(define->name, prop->name))
        !          8996:             return (0);
        !          8997:     }
        !          8998:     if (define->ns != NULL) {
        !          8999:         if (define->ns[0] == 0) {
        !          9000:             if (prop->ns != NULL)
        !          9001:                 return (0);
        !          9002:         } else {
        !          9003:             if ((prop->ns == NULL) ||
        !          9004:                 (!xmlStrEqual(define->ns, prop->ns->href)))
        !          9005:                 return (0);
        !          9006:         }
        !          9007:     }
        !          9008:     if (define->nameClass == NULL)
        !          9009:         return (1);
        !          9010:     define = define->nameClass;
        !          9011:     if (define->type == XML_RELAXNG_EXCEPT) {
        !          9012:         xmlRelaxNGDefinePtr list;
        !          9013: 
        !          9014:         list = define->content;
        !          9015:         while (list != NULL) {
        !          9016:             ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);
        !          9017:             if (ret == 1)
        !          9018:                 return (0);
        !          9019:             if (ret < 0)
        !          9020:                 return (ret);
        !          9021:             list = list->next;
        !          9022:         }
        !          9023:     } else {
        !          9024:     TODO}
        !          9025:     return (1);
        !          9026: }
        !          9027: 
        !          9028: /**
        !          9029:  * xmlRelaxNGValidateAttribute:
        !          9030:  * @ctxt:  a Relax-NG validation context
        !          9031:  * @define:  the definition to verify
        !          9032:  *
        !          9033:  * Validate the given attribute definition for that node
        !          9034:  *
        !          9035:  * Returns 0 if the validation succeeded or an error code.
        !          9036:  */
        !          9037: static int
        !          9038: xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
        !          9039:                             xmlRelaxNGDefinePtr define)
        !          9040: {
        !          9041:     int ret = 0, i;
        !          9042:     xmlChar *value, *oldvalue;
        !          9043:     xmlAttrPtr prop = NULL, tmp;
        !          9044:     xmlNodePtr oldseq;
        !          9045: 
        !          9046:     if (ctxt->state->nbAttrLeft <= 0)
        !          9047:         return (-1);
        !          9048:     if (define->name != NULL) {
        !          9049:         for (i = 0; i < ctxt->state->nbAttrs; i++) {
        !          9050:             tmp = ctxt->state->attrs[i];
        !          9051:             if ((tmp != NULL) && (xmlStrEqual(define->name, tmp->name))) {
        !          9052:                 if ((((define->ns == NULL) || (define->ns[0] == 0)) &&
        !          9053:                      (tmp->ns == NULL)) ||
        !          9054:                     ((tmp->ns != NULL) &&
        !          9055:                      (xmlStrEqual(define->ns, tmp->ns->href)))) {
        !          9056:                     prop = tmp;
        !          9057:                     break;
        !          9058:                 }
        !          9059:             }
        !          9060:         }
        !          9061:         if (prop != NULL) {
        !          9062:             value = xmlNodeListGetString(prop->doc, prop->children, 1);
        !          9063:             oldvalue = ctxt->state->value;
        !          9064:             oldseq = ctxt->state->seq;
        !          9065:             ctxt->state->seq = (xmlNodePtr) prop;
        !          9066:             ctxt->state->value = value;
        !          9067:             ctxt->state->endvalue = NULL;
        !          9068:             ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
        !          9069:             if (ctxt->state->value != NULL)
        !          9070:                 value = ctxt->state->value;
        !          9071:             if (value != NULL)
        !          9072:                 xmlFree(value);
        !          9073:             ctxt->state->value = oldvalue;
        !          9074:             ctxt->state->seq = oldseq;
        !          9075:             if (ret == 0) {
        !          9076:                 /*
        !          9077:                  * flag the attribute as processed
        !          9078:                  */
        !          9079:                 ctxt->state->attrs[i] = NULL;
        !          9080:                 ctxt->state->nbAttrLeft--;
        !          9081:             }
        !          9082:         } else {
        !          9083:             ret = -1;
        !          9084:         }
        !          9085: #ifdef DEBUG
        !          9086:         xmlGenericError(xmlGenericErrorContext,
        !          9087:                         "xmlRelaxNGValidateAttribute(%s): %d\n",
        !          9088:                         define->name, ret);
        !          9089: #endif
        !          9090:     } else {
        !          9091:         for (i = 0; i < ctxt->state->nbAttrs; i++) {
        !          9092:             tmp = ctxt->state->attrs[i];
        !          9093:             if ((tmp != NULL) &&
        !          9094:                 (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) {
        !          9095:                 prop = tmp;
        !          9096:                 break;
        !          9097:             }
        !          9098:         }
        !          9099:         if (prop != NULL) {
        !          9100:             value = xmlNodeListGetString(prop->doc, prop->children, 1);
        !          9101:             oldvalue = ctxt->state->value;
        !          9102:             oldseq = ctxt->state->seq;
        !          9103:             ctxt->state->seq = (xmlNodePtr) prop;
        !          9104:             ctxt->state->value = value;
        !          9105:             ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
        !          9106:             if (ctxt->state->value != NULL)
        !          9107:                 value = ctxt->state->value;
        !          9108:             if (value != NULL)
        !          9109:                 xmlFree(value);
        !          9110:             ctxt->state->value = oldvalue;
        !          9111:             ctxt->state->seq = oldseq;
        !          9112:             if (ret == 0) {
        !          9113:                 /*
        !          9114:                  * flag the attribute as processed
        !          9115:                  */
        !          9116:                 ctxt->state->attrs[i] = NULL;
        !          9117:                 ctxt->state->nbAttrLeft--;
        !          9118:             }
        !          9119:         } else {
        !          9120:             ret = -1;
        !          9121:         }
        !          9122: #ifdef DEBUG
        !          9123:         if (define->ns != NULL) {
        !          9124:             xmlGenericError(xmlGenericErrorContext,
        !          9125:                             "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",
        !          9126:                             define->ns, ret);
        !          9127:         } else {
        !          9128:             xmlGenericError(xmlGenericErrorContext,
        !          9129:                             "xmlRelaxNGValidateAttribute(anyName): %d\n",
        !          9130:                             ret);
        !          9131:         }
        !          9132: #endif
        !          9133:     }
        !          9134: 
        !          9135:     return (ret);
        !          9136: }
        !          9137: 
        !          9138: /**
        !          9139:  * xmlRelaxNGValidateAttributeList:
        !          9140:  * @ctxt:  a Relax-NG validation context
        !          9141:  * @define:  the list of definition to verify
        !          9142:  *
        !          9143:  * Validate the given node against the list of attribute definitions
        !          9144:  *
        !          9145:  * Returns 0 if the validation succeeded or an error code.
        !          9146:  */
        !          9147: static int
        !          9148: xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
        !          9149:                                 xmlRelaxNGDefinePtr defines)
        !          9150: {
        !          9151:     int ret = 0, res;
        !          9152:     int needmore = 0;
        !          9153:     xmlRelaxNGDefinePtr cur;
        !          9154: 
        !          9155:     cur = defines;
        !          9156:     while (cur != NULL) {
        !          9157:         if (cur->type == XML_RELAXNG_ATTRIBUTE) {
        !          9158:             if (xmlRelaxNGValidateAttribute(ctxt, cur) != 0)
        !          9159:                 ret = -1;
        !          9160:         } else
        !          9161:             needmore = 1;
        !          9162:         cur = cur->next;
        !          9163:     }
        !          9164:     if (!needmore)
        !          9165:         return (ret);
        !          9166:     cur = defines;
        !          9167:     while (cur != NULL) {
        !          9168:         if (cur->type != XML_RELAXNG_ATTRIBUTE) {
        !          9169:             if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
        !          9170:                 res = xmlRelaxNGValidateDefinition(ctxt, cur);
        !          9171:                 if (res < 0)
        !          9172:                     ret = -1;
        !          9173:             } else {
        !          9174:                 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
        !          9175:                 return (-1);
        !          9176:             }
        !          9177:             if (res == -1)      /* continues on -2 */
        !          9178:                 break;
        !          9179:         }
        !          9180:         cur = cur->next;
        !          9181:     }
        !          9182: 
        !          9183:     return (ret);
        !          9184: }
        !          9185: 
        !          9186: /**
        !          9187:  * xmlRelaxNGNodeMatchesList:
        !          9188:  * @node:  the node
        !          9189:  * @list:  a NULL terminated array of definitions
        !          9190:  *
        !          9191:  * Check if a node can be matched by one of the definitions
        !          9192:  *
        !          9193:  * Returns 1 if matches 0 otherwise
        !          9194:  */
        !          9195: static int
        !          9196: xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr * list)
        !          9197: {
        !          9198:     xmlRelaxNGDefinePtr cur;
        !          9199:     int i = 0, tmp;
        !          9200: 
        !          9201:     if ((node == NULL) || (list == NULL))
        !          9202:         return (0);
        !          9203: 
        !          9204:     cur = list[i++];
        !          9205:     while (cur != NULL) {
        !          9206:         if ((node->type == XML_ELEMENT_NODE) &&
        !          9207:             (cur->type == XML_RELAXNG_ELEMENT)) {
        !          9208:             tmp = xmlRelaxNGElementMatch(NULL, cur, node);
        !          9209:             if (tmp == 1)
        !          9210:                 return (1);
        !          9211:         } else if (((node->type == XML_TEXT_NODE) ||
        !          9212:                     (node->type == XML_CDATA_SECTION_NODE)) &&
        !          9213:                    (cur->type == XML_RELAXNG_TEXT)) {
        !          9214:             return (1);
        !          9215:         }
        !          9216:         cur = list[i++];
        !          9217:     }
        !          9218:     return (0);
        !          9219: }
        !          9220: 
        !          9221: /**
        !          9222:  * xmlRelaxNGValidateInterleave:
        !          9223:  * @ctxt:  a Relax-NG validation context
        !          9224:  * @define:  the definition to verify
        !          9225:  *
        !          9226:  * Validate an interleave definition for a node.
        !          9227:  *
        !          9228:  * Returns 0 if the validation succeeded or an error code.
        !          9229:  */
        !          9230: static int
        !          9231: xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt,
        !          9232:                              xmlRelaxNGDefinePtr define)
        !          9233: {
        !          9234:     int ret = 0, i, nbgroups;
        !          9235:     int errNr = ctxt->errNr;
        !          9236:     int oldflags;
        !          9237: 
        !          9238:     xmlRelaxNGValidStatePtr oldstate;
        !          9239:     xmlRelaxNGPartitionPtr partitions;
        !          9240:     xmlRelaxNGInterleaveGroupPtr group = NULL;
        !          9241:     xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem;
        !          9242:     xmlNodePtr *list = NULL, *lasts = NULL;
        !          9243: 
        !          9244:     if (define->data != NULL) {
        !          9245:         partitions = (xmlRelaxNGPartitionPtr) define->data;
        !          9246:         nbgroups = partitions->nbgroups;
        !          9247:     } else {
        !          9248:         VALID_ERR(XML_RELAXNG_ERR_INTERNODATA);
        !          9249:         return (-1);
        !          9250:     }
        !          9251:     /*
        !          9252:      * Optimizations for MIXED
        !          9253:      */
        !          9254:     oldflags = ctxt->flags;
        !          9255:     if (define->dflags & IS_MIXED) {
        !          9256:         ctxt->flags |= FLAGS_MIXED_CONTENT;
        !          9257:         if (nbgroups == 2) {
        !          9258:             /*
        !          9259:              * this is a pure <mixed> case
        !          9260:              */
        !          9261:             if (ctxt->state != NULL)
        !          9262:                 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
        !          9263:                                                          ctxt->state->seq);
        !          9264:             if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT)
        !          9265:                 ret = xmlRelaxNGValidateDefinition(ctxt,
        !          9266:                                                    partitions->groups[1]->
        !          9267:                                                    rule);
        !          9268:             else
        !          9269:                 ret = xmlRelaxNGValidateDefinition(ctxt,
        !          9270:                                                    partitions->groups[0]->
        !          9271:                                                    rule);
        !          9272:             if (ret == 0) {
        !          9273:                 if (ctxt->state != NULL)
        !          9274:                     ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
        !          9275:                                                              ctxt->state->
        !          9276:                                                              seq);
        !          9277:             }
        !          9278:             ctxt->flags = oldflags;
        !          9279:             return (ret);
        !          9280:         }
        !          9281:     }
        !          9282: 
        !          9283:     /*
        !          9284:      * Build arrays to store the first and last node of the chain
        !          9285:      * pertaining to each group
        !          9286:      */
        !          9287:     list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
        !          9288:     if (list == NULL) {
        !          9289:         xmlRngVErrMemory(ctxt, "validating\n");
        !          9290:         return (-1);
        !          9291:     }
        !          9292:     memset(list, 0, nbgroups * sizeof(xmlNodePtr));
        !          9293:     lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
        !          9294:     if (lasts == NULL) {
        !          9295:         xmlRngVErrMemory(ctxt, "validating\n");
        !          9296:         return (-1);
        !          9297:     }
        !          9298:     memset(lasts, 0, nbgroups * sizeof(xmlNodePtr));
        !          9299: 
        !          9300:     /*
        !          9301:      * Walk the sequence of children finding the right group and
        !          9302:      * sorting them in sequences.
        !          9303:      */
        !          9304:     cur = ctxt->state->seq;
        !          9305:     cur = xmlRelaxNGSkipIgnored(ctxt, cur);
        !          9306:     start = cur;
        !          9307:     while (cur != NULL) {
        !          9308:         ctxt->state->seq = cur;
        !          9309:         if ((partitions->triage != NULL) &&
        !          9310:             (partitions->flags & IS_DETERMINIST)) {
        !          9311:             void *tmp = NULL;
        !          9312: 
        !          9313:             if ((cur->type == XML_TEXT_NODE) ||
        !          9314:                 (cur->type == XML_CDATA_SECTION_NODE)) {
        !          9315:                 tmp = xmlHashLookup2(partitions->triage, BAD_CAST "#text",
        !          9316:                                      NULL);
        !          9317:             } else if (cur->type == XML_ELEMENT_NODE) {
        !          9318:                 if (cur->ns != NULL) {
        !          9319:                     tmp = xmlHashLookup2(partitions->triage, cur->name,
        !          9320:                                          cur->ns->href);
        !          9321:                     if (tmp == NULL)
        !          9322:                         tmp = xmlHashLookup2(partitions->triage,
        !          9323:                                              BAD_CAST "#any",
        !          9324:                                              cur->ns->href);
        !          9325:                 } else
        !          9326:                     tmp =
        !          9327:                         xmlHashLookup2(partitions->triage, cur->name,
        !          9328:                                        NULL);
        !          9329:                 if (tmp == NULL)
        !          9330:                     tmp =
        !          9331:                         xmlHashLookup2(partitions->triage, BAD_CAST "#any",
        !          9332:                                        NULL);
        !          9333:             }
        !          9334: 
        !          9335:             if (tmp == NULL) {
        !          9336:                 i = nbgroups;
        !          9337:             } else {
        !          9338:                 i = ((long) tmp) - 1;
        !          9339:                 if (partitions->flags & IS_NEEDCHECK) {
        !          9340:                     group = partitions->groups[i];
        !          9341:                     if (!xmlRelaxNGNodeMatchesList(cur, group->defs))
        !          9342:                         i = nbgroups;
        !          9343:                 }
        !          9344:             }
        !          9345:         } else {
        !          9346:             for (i = 0; i < nbgroups; i++) {
        !          9347:                 group = partitions->groups[i];
        !          9348:                 if (group == NULL)
        !          9349:                     continue;
        !          9350:                 if (xmlRelaxNGNodeMatchesList(cur, group->defs))
        !          9351:                     break;
        !          9352:             }
        !          9353:         }
        !          9354:         /*
        !          9355:          * We break as soon as an element not matched is found
        !          9356:          */
        !          9357:         if (i >= nbgroups) {
        !          9358:             break;
        !          9359:         }
        !          9360:         if (lasts[i] != NULL) {
        !          9361:             lasts[i]->next = cur;
        !          9362:             lasts[i] = cur;
        !          9363:         } else {
        !          9364:             list[i] = cur;
        !          9365:             lasts[i] = cur;
        !          9366:         }
        !          9367:         if (cur->next != NULL)
        !          9368:             lastchg = cur->next;
        !          9369:         else
        !          9370:             lastchg = cur;
        !          9371:         cur = xmlRelaxNGSkipIgnored(ctxt, cur->next);
        !          9372:     }
        !          9373:     if (ret != 0) {
        !          9374:         VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
        !          9375:         ret = -1;
        !          9376:         goto done;
        !          9377:     }
        !          9378:     lastelem = cur;
        !          9379:     oldstate = ctxt->state;
        !          9380:     for (i = 0; i < nbgroups; i++) {
        !          9381:         ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate);
        !          9382:         group = partitions->groups[i];
        !          9383:         if (lasts[i] != NULL) {
        !          9384:             last = lasts[i]->next;
        !          9385:             lasts[i]->next = NULL;
        !          9386:         }
        !          9387:         ctxt->state->seq = list[i];
        !          9388:         ret = xmlRelaxNGValidateDefinition(ctxt, group->rule);
        !          9389:         if (ret != 0)
        !          9390:             break;
        !          9391:         if (ctxt->state != NULL) {
        !          9392:             cur = ctxt->state->seq;
        !          9393:             cur = xmlRelaxNGSkipIgnored(ctxt, cur);
        !          9394:             xmlRelaxNGFreeValidState(ctxt, oldstate);
        !          9395:             oldstate = ctxt->state;
        !          9396:             ctxt->state = NULL;
        !          9397:             if (cur != NULL) {
        !          9398:                 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
        !          9399:                 ret = -1;
        !          9400:                 ctxt->state = oldstate;
        !          9401:                 goto done;
        !          9402:             }
        !          9403:         } else if (ctxt->states != NULL) {
        !          9404:             int j;
        !          9405:             int found = 0;
        !          9406:            int best = -1;
        !          9407:            int lowattr = -1;
        !          9408: 
        !          9409:            /*
        !          9410:             * PBM: what happen if there is attributes checks in the interleaves
        !          9411:             */
        !          9412: 
        !          9413:             for (j = 0; j < ctxt->states->nbState; j++) {
        !          9414:                 cur = ctxt->states->tabState[j]->seq;
        !          9415:                 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
        !          9416:                 if (cur == NULL) {
        !          9417:                    if (found == 0) {
        !          9418:                        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
        !          9419:                        best = j;
        !          9420:                    }
        !          9421:                     found = 1;
        !          9422:                    if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) {
        !          9423:                        /* try  to keep the latest one to mach old heuristic */
        !          9424:                        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
        !          9425:                        best = j;
        !          9426:                    }
        !          9427:                     if (lowattr == 0)
        !          9428:                        break;
        !          9429:                 } else if (found == 0) {
        !          9430:                     if (lowattr == -1) {
        !          9431:                        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
        !          9432:                        best = j;
        !          9433:                    } else
        !          9434:                    if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr)  {
        !          9435:                        /* try  to keep the latest one to mach old heuristic */
        !          9436:                        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
        !          9437:                        best = j;
        !          9438:                    }
        !          9439:                }
        !          9440:             }
        !          9441:            /*
        !          9442:             * BIG PBM: here we pick only one restarting point :-(
        !          9443:             */
        !          9444:             if (ctxt->states->nbState > 0) {
        !          9445:                 xmlRelaxNGFreeValidState(ctxt, oldstate);
        !          9446:                if (best != -1) {
        !          9447:                    oldstate = ctxt->states->tabState[best];
        !          9448:                    ctxt->states->tabState[best] = NULL;
        !          9449:                } else {
        !          9450:                    oldstate =
        !          9451:                        ctxt->states->tabState[ctxt->states->nbState - 1];
        !          9452:                     ctxt->states->tabState[ctxt->states->nbState - 1] = NULL;
        !          9453:                     ctxt->states->nbState--;
        !          9454:                }
        !          9455:             }
        !          9456:             for (j = 0; j < ctxt->states->nbState ; j++) {
        !          9457:                 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[j]);
        !          9458:             }
        !          9459:             xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          9460:             ctxt->states = NULL;
        !          9461:             if (found == 0) {
        !          9462:                 if (cur == NULL) {
        !          9463:                    VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA,
        !          9464:                               (const xmlChar *) "noname");
        !          9465:                 } else {
        !          9466:                     VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
        !          9467:                 }
        !          9468:                 ret = -1;
        !          9469:                 ctxt->state = oldstate;
        !          9470:                 goto done;
        !          9471:             }
        !          9472:         } else {
        !          9473:             ret = -1;
        !          9474:             break;
        !          9475:         }
        !          9476:         if (lasts[i] != NULL) {
        !          9477:             lasts[i]->next = last;
        !          9478:         }
        !          9479:     }
        !          9480:     if (ctxt->state != NULL)
        !          9481:         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          9482:     ctxt->state = oldstate;
        !          9483:     ctxt->state->seq = lastelem;
        !          9484:     if (ret != 0) {
        !          9485:         VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
        !          9486:         ret = -1;
        !          9487:         goto done;
        !          9488:     }
        !          9489: 
        !          9490:   done:
        !          9491:     ctxt->flags = oldflags;
        !          9492:     /*
        !          9493:      * builds the next links chain from the prev one
        !          9494:      */
        !          9495:     cur = lastchg;
        !          9496:     while (cur != NULL) {
        !          9497:         if ((cur == start) || (cur->prev == NULL))
        !          9498:             break;
        !          9499:         cur->prev->next = cur;
        !          9500:         cur = cur->prev;
        !          9501:     }
        !          9502:     if (ret == 0) {
        !          9503:         if (ctxt->errNr > errNr)
        !          9504:             xmlRelaxNGPopErrors(ctxt, errNr);
        !          9505:     }
        !          9506: 
        !          9507:     xmlFree(list);
        !          9508:     xmlFree(lasts);
        !          9509:     return (ret);
        !          9510: }
        !          9511: 
        !          9512: /**
        !          9513:  * xmlRelaxNGValidateDefinitionList:
        !          9514:  * @ctxt:  a Relax-NG validation context
        !          9515:  * @define:  the list of definition to verify
        !          9516:  *
        !          9517:  * Validate the given node content against the (list) of definitions
        !          9518:  *
        !          9519:  * Returns 0 if the validation succeeded or an error code.
        !          9520:  */
        !          9521: static int
        !          9522: xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt,
        !          9523:                                  xmlRelaxNGDefinePtr defines)
        !          9524: {
        !          9525:     int ret = 0, res;
        !          9526: 
        !          9527: 
        !          9528:     if (defines == NULL) {
        !          9529:         VALID_ERR2(XML_RELAXNG_ERR_INTERNAL,
        !          9530:                    BAD_CAST "NULL definition list");
        !          9531:         return (-1);
        !          9532:     }
        !          9533:     while (defines != NULL) {
        !          9534:         if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
        !          9535:             res = xmlRelaxNGValidateDefinition(ctxt, defines);
        !          9536:             if (res < 0)
        !          9537:                 ret = -1;
        !          9538:         } else {
        !          9539:             VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
        !          9540:             return (-1);
        !          9541:         }
        !          9542:         if (res == -1)          /* continues on -2 */
        !          9543:             break;
        !          9544:         defines = defines->next;
        !          9545:     }
        !          9546: 
        !          9547:     return (ret);
        !          9548: }
        !          9549: 
        !          9550: /**
        !          9551:  * xmlRelaxNGElementMatch:
        !          9552:  * @ctxt:  a Relax-NG validation context
        !          9553:  * @define:  the definition to check
        !          9554:  * @elem:  the element
        !          9555:  *
        !          9556:  * Check if the element matches the definition nameClass
        !          9557:  *
        !          9558:  * Returns 1 if the element matches, 0 if no, or -1 in case of error
        !          9559:  */
        !          9560: static int
        !          9561: xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
        !          9562:                        xmlRelaxNGDefinePtr define, xmlNodePtr elem)
        !          9563: {
        !          9564:     int ret = 0, oldflags = 0;
        !          9565: 
        !          9566:     if (define->name != NULL) {
        !          9567:         if (!xmlStrEqual(elem->name, define->name)) {
        !          9568:             VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name);
        !          9569:             return (0);
        !          9570:         }
        !          9571:     }
        !          9572:     if ((define->ns != NULL) && (define->ns[0] != 0)) {
        !          9573:         if (elem->ns == NULL) {
        !          9574:             VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name);
        !          9575:             return (0);
        !          9576:         } else if (!xmlStrEqual(elem->ns->href, define->ns)) {
        !          9577:             VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS,
        !          9578:                        elem->name, define->ns);
        !          9579:             return (0);
        !          9580:         }
        !          9581:     } else if ((elem->ns != NULL) && (define->ns != NULL) &&
        !          9582:                (define->name == NULL)) {
        !          9583:         VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name);
        !          9584:         return (0);
        !          9585:     } else if ((elem->ns != NULL) && (define->name != NULL)) {
        !          9586:         VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name);
        !          9587:         return (0);
        !          9588:     }
        !          9589: 
        !          9590:     if (define->nameClass == NULL)
        !          9591:         return (1);
        !          9592: 
        !          9593:     define = define->nameClass;
        !          9594:     if (define->type == XML_RELAXNG_EXCEPT) {
        !          9595:         xmlRelaxNGDefinePtr list;
        !          9596: 
        !          9597:         if (ctxt != NULL) {
        !          9598:             oldflags = ctxt->flags;
        !          9599:             ctxt->flags |= FLAGS_IGNORABLE;
        !          9600:         }
        !          9601: 
        !          9602:         list = define->content;
        !          9603:         while (list != NULL) {
        !          9604:             ret = xmlRelaxNGElementMatch(ctxt, list, elem);
        !          9605:             if (ret == 1) {
        !          9606:                 if (ctxt != NULL)
        !          9607:                     ctxt->flags = oldflags;
        !          9608:                 return (0);
        !          9609:             }
        !          9610:             if (ret < 0) {
        !          9611:                 if (ctxt != NULL)
        !          9612:                     ctxt->flags = oldflags;
        !          9613:                 return (ret);
        !          9614:             }
        !          9615:             list = list->next;
        !          9616:         }
        !          9617:         ret = 1;
        !          9618:         if (ctxt != NULL) {
        !          9619:             ctxt->flags = oldflags;
        !          9620:         }
        !          9621:     } else if (define->type == XML_RELAXNG_CHOICE) {
        !          9622:         xmlRelaxNGDefinePtr list;
        !          9623: 
        !          9624:         if (ctxt != NULL) {
        !          9625:             oldflags = ctxt->flags;
        !          9626:             ctxt->flags |= FLAGS_IGNORABLE;
        !          9627:         }
        !          9628: 
        !          9629:         list = define->nameClass;
        !          9630:         while (list != NULL) {
        !          9631:             ret = xmlRelaxNGElementMatch(ctxt, list, elem);
        !          9632:             if (ret == 1) {
        !          9633:                 if (ctxt != NULL)
        !          9634:                     ctxt->flags = oldflags;
        !          9635:                 return (1);
        !          9636:             }
        !          9637:             if (ret < 0) {
        !          9638:                 if (ctxt != NULL)
        !          9639:                     ctxt->flags = oldflags;
        !          9640:                 return (ret);
        !          9641:             }
        !          9642:             list = list->next;
        !          9643:         }
        !          9644:         if (ctxt != NULL) {
        !          9645:             if (ret != 0) {
        !          9646:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
        !          9647:                     xmlRelaxNGDumpValidError(ctxt);
        !          9648:             } else {
        !          9649:                 if (ctxt->errNr > 0)
        !          9650:                     xmlRelaxNGPopErrors(ctxt, 0);
        !          9651:             }
        !          9652:         }
        !          9653:         ret = 0;
        !          9654:         if (ctxt != NULL) {
        !          9655:             ctxt->flags = oldflags;
        !          9656:         }
        !          9657:     } else {
        !          9658:         TODO ret = -1;
        !          9659:     }
        !          9660:     return (ret);
        !          9661: }
        !          9662: 
        !          9663: /**
        !          9664:  * xmlRelaxNGBestState:
        !          9665:  * @ctxt:  a Relax-NG validation context
        !          9666:  *
        !          9667:  * Find the "best" state in the ctxt->states list of states to report
        !          9668:  * errors about. I.e. a state with no element left in the child list
        !          9669:  * or the one with the less attributes left.
        !          9670:  * This is called only if a falidation error was detected
        !          9671:  *
        !          9672:  * Returns the index of the "best" state or -1 in case of error
        !          9673:  */
        !          9674: static int
        !          9675: xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt)
        !          9676: {
        !          9677:     xmlRelaxNGValidStatePtr state;
        !          9678:     int i, tmp;
        !          9679:     int best = -1;
        !          9680:     int value = 1000000;
        !          9681: 
        !          9682:     if ((ctxt == NULL) || (ctxt->states == NULL) ||
        !          9683:         (ctxt->states->nbState <= 0))
        !          9684:         return (-1);
        !          9685: 
        !          9686:     for (i = 0; i < ctxt->states->nbState; i++) {
        !          9687:         state = ctxt->states->tabState[i];
        !          9688:         if (state == NULL)
        !          9689:             continue;
        !          9690:         if (state->seq != NULL) {
        !          9691:             if ((best == -1) || (value > 100000)) {
        !          9692:                 value = 100000;
        !          9693:                 best = i;
        !          9694:             }
        !          9695:         } else {
        !          9696:             tmp = state->nbAttrLeft;
        !          9697:             if ((best == -1) || (value > tmp)) {
        !          9698:                 value = tmp;
        !          9699:                 best = i;
        !          9700:             }
        !          9701:         }
        !          9702:     }
        !          9703:     return (best);
        !          9704: }
        !          9705: 
        !          9706: /**
        !          9707:  * xmlRelaxNGLogBestError:
        !          9708:  * @ctxt:  a Relax-NG validation context
        !          9709:  *
        !          9710:  * Find the "best" state in the ctxt->states list of states to report
        !          9711:  * errors about and log it.
        !          9712:  */
        !          9713: static void
        !          9714: xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt)
        !          9715: {
        !          9716:     int best;
        !          9717: 
        !          9718:     if ((ctxt == NULL) || (ctxt->states == NULL) ||
        !          9719:         (ctxt->states->nbState <= 0))
        !          9720:         return;
        !          9721: 
        !          9722:     best = xmlRelaxNGBestState(ctxt);
        !          9723:     if ((best >= 0) && (best < ctxt->states->nbState)) {
        !          9724:         ctxt->state = ctxt->states->tabState[best];
        !          9725: 
        !          9726:         xmlRelaxNGValidateElementEnd(ctxt, 1);
        !          9727:     }
        !          9728: }
        !          9729: 
        !          9730: /**
        !          9731:  * xmlRelaxNGValidateElementEnd:
        !          9732:  * @ctxt:  a Relax-NG validation context
        !          9733:  * @dolog:  indicate that error logging should be done
        !          9734:  *
        !          9735:  * Validate the end of the element, implements check that
        !          9736:  * there is nothing left not consumed in the element content
        !          9737:  * or in the attribute list.
        !          9738:  *
        !          9739:  * Returns 0 if the validation succeeded or an error code.
        !          9740:  */
        !          9741: static int
        !          9742: xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int dolog)
        !          9743: {
        !          9744:     int i;
        !          9745:     xmlRelaxNGValidStatePtr state;
        !          9746: 
        !          9747:     state = ctxt->state;
        !          9748:     if (state->seq != NULL) {
        !          9749:         state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq);
        !          9750:         if (state->seq != NULL) {
        !          9751:             if (dolog) {
        !          9752:                 VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT,
        !          9753:                            state->node->name, state->seq->name);
        !          9754:             }
        !          9755:             return (-1);
        !          9756:         }
        !          9757:     }
        !          9758:     for (i = 0; i < state->nbAttrs; i++) {
        !          9759:         if (state->attrs[i] != NULL) {
        !          9760:             if (dolog) {
        !          9761:                 VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR,
        !          9762:                            state->attrs[i]->name, state->node->name);
        !          9763:             }
        !          9764:             return (-1 - i);
        !          9765:         }
        !          9766:     }
        !          9767:     return (0);
        !          9768: }
        !          9769: 
        !          9770: /**
        !          9771:  * xmlRelaxNGValidateState:
        !          9772:  * @ctxt:  a Relax-NG validation context
        !          9773:  * @define:  the definition to verify
        !          9774:  *
        !          9775:  * Validate the current state against the definition
        !          9776:  *
        !          9777:  * Returns 0 if the validation succeeded or an error code.
        !          9778:  */
        !          9779: static int
        !          9780: xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
        !          9781:                         xmlRelaxNGDefinePtr define)
        !          9782: {
        !          9783:     xmlNodePtr node;
        !          9784:     int ret = 0, i, tmp, oldflags, errNr;
        !          9785:     xmlRelaxNGValidStatePtr oldstate = NULL, state;
        !          9786: 
        !          9787:     if (define == NULL) {
        !          9788:         VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
        !          9789:         return (-1);
        !          9790:     }
        !          9791: 
        !          9792:     if (ctxt->state != NULL) {
        !          9793:         node = ctxt->state->seq;
        !          9794:     } else {
        !          9795:         node = NULL;
        !          9796:     }
        !          9797: #ifdef DEBUG
        !          9798:     for (i = 0; i < ctxt->depth; i++)
        !          9799:         xmlGenericError(xmlGenericErrorContext, " ");
        !          9800:     xmlGenericError(xmlGenericErrorContext,
        !          9801:                     "Start validating %s ", xmlRelaxNGDefName(define));
        !          9802:     if (define->name != NULL)
        !          9803:         xmlGenericError(xmlGenericErrorContext, "%s ", define->name);
        !          9804:     if ((node != NULL) && (node->name != NULL))
        !          9805:         xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name);
        !          9806:     else
        !          9807:         xmlGenericError(xmlGenericErrorContext, "\n");
        !          9808: #endif
        !          9809:     ctxt->depth++;
        !          9810:     switch (define->type) {
        !          9811:         case XML_RELAXNG_EMPTY:
        !          9812:             node = xmlRelaxNGSkipIgnored(ctxt, node);
        !          9813:             ret = 0;
        !          9814:             break;
        !          9815:         case XML_RELAXNG_NOT_ALLOWED:
        !          9816:             ret = -1;
        !          9817:             break;
        !          9818:         case XML_RELAXNG_TEXT:
        !          9819:             while ((node != NULL) &&
        !          9820:                    ((node->type == XML_TEXT_NODE) ||
        !          9821:                     (node->type == XML_COMMENT_NODE) ||
        !          9822:                     (node->type == XML_PI_NODE) ||
        !          9823:                     (node->type == XML_CDATA_SECTION_NODE)))
        !          9824:                 node = node->next;
        !          9825:             ctxt->state->seq = node;
        !          9826:             break;
        !          9827:         case XML_RELAXNG_ELEMENT:
        !          9828:             errNr = ctxt->errNr;
        !          9829:             node = xmlRelaxNGSkipIgnored(ctxt, node);
        !          9830:             if (node == NULL) {
        !          9831:                 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name);
        !          9832:                 ret = -1;
        !          9833:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
        !          9834:                     xmlRelaxNGDumpValidError(ctxt);
        !          9835:                 break;
        !          9836:             }
        !          9837:             if (node->type != XML_ELEMENT_NODE) {
        !          9838:                 VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
        !          9839:                 ret = -1;
        !          9840:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
        !          9841:                     xmlRelaxNGDumpValidError(ctxt);
        !          9842:                 break;
        !          9843:             }
        !          9844:             /*
        !          9845:              * This node was already validated successfully against
        !          9846:              * this definition.
        !          9847:              */
        !          9848:             if (node->psvi == define) {
        !          9849:                 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
        !          9850:                 if (ctxt->errNr > errNr)
        !          9851:                     xmlRelaxNGPopErrors(ctxt, errNr);
        !          9852:                 if (ctxt->errNr != 0) {
        !          9853:                     while ((ctxt->err != NULL) &&
        !          9854:                            (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME)
        !          9855:                              && (xmlStrEqual(ctxt->err->arg2, node->name)))
        !          9856:                             ||
        !          9857:                             ((ctxt->err->err ==
        !          9858:                               XML_RELAXNG_ERR_ELEMEXTRANS)
        !          9859:                              && (xmlStrEqual(ctxt->err->arg1, node->name)))
        !          9860:                             || (ctxt->err->err == XML_RELAXNG_ERR_NOELEM)
        !          9861:                             || (ctxt->err->err ==
        !          9862:                                 XML_RELAXNG_ERR_NOTELEM)))
        !          9863:                         xmlRelaxNGValidErrorPop(ctxt);
        !          9864:                 }
        !          9865:                 break;
        !          9866:             }
        !          9867: 
        !          9868:             ret = xmlRelaxNGElementMatch(ctxt, define, node);
        !          9869:             if (ret <= 0) {
        !          9870:                 ret = -1;
        !          9871:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
        !          9872:                     xmlRelaxNGDumpValidError(ctxt);
        !          9873:                 break;
        !          9874:             }
        !          9875:             ret = 0;
        !          9876:             if (ctxt->errNr != 0) {
        !          9877:                 if (ctxt->errNr > errNr)
        !          9878:                     xmlRelaxNGPopErrors(ctxt, errNr);
        !          9879:                 while ((ctxt->err != NULL) &&
        !          9880:                        (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) &&
        !          9881:                          (xmlStrEqual(ctxt->err->arg2, node->name))) ||
        !          9882:                         ((ctxt->err->err == XML_RELAXNG_ERR_ELEMEXTRANS) &&
        !          9883:                          (xmlStrEqual(ctxt->err->arg1, node->name))) ||
        !          9884:                         (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) ||
        !          9885:                         (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM)))
        !          9886:                     xmlRelaxNGValidErrorPop(ctxt);
        !          9887:             }
        !          9888:             errNr = ctxt->errNr;
        !          9889: 
        !          9890:             oldflags = ctxt->flags;
        !          9891:             if (ctxt->flags & FLAGS_MIXED_CONTENT) {
        !          9892:                 ctxt->flags -= FLAGS_MIXED_CONTENT;
        !          9893:             }
        !          9894:             state = xmlRelaxNGNewValidState(ctxt, node);
        !          9895:             if (state == NULL) {
        !          9896:                 ret = -1;
        !          9897:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
        !          9898:                     xmlRelaxNGDumpValidError(ctxt);
        !          9899:                 break;
        !          9900:             }
        !          9901: 
        !          9902:             oldstate = ctxt->state;
        !          9903:             ctxt->state = state;
        !          9904:             if (define->attrs != NULL) {
        !          9905:                 tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
        !          9906:                 if (tmp != 0) {
        !          9907:                     ret = -1;
        !          9908:                     VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
        !          9909:                 }
        !          9910:             }
        !          9911:             if (define->contModel != NULL) {
        !          9912:                 xmlRelaxNGValidStatePtr nstate, tmpstate = ctxt->state;
        !          9913:                 xmlRelaxNGStatesPtr tmpstates = ctxt->states;
        !          9914:                 xmlNodePtr nseq;
        !          9915: 
        !          9916:                 nstate = xmlRelaxNGNewValidState(ctxt, node);
        !          9917:                 ctxt->state = nstate;
        !          9918:                 ctxt->states = NULL;
        !          9919: 
        !          9920:                 tmp = xmlRelaxNGValidateCompiledContent(ctxt,
        !          9921:                                                         define->contModel,
        !          9922:                                                         ctxt->state->seq);
        !          9923:                 nseq = ctxt->state->seq;
        !          9924:                 ctxt->state = tmpstate;
        !          9925:                 ctxt->states = tmpstates;
        !          9926:                 xmlRelaxNGFreeValidState(ctxt, nstate);
        !          9927: 
        !          9928: #ifdef DEBUG_COMPILE
        !          9929:                 xmlGenericError(xmlGenericErrorContext,
        !          9930:                                 "Validating content of '%s' : %d\n",
        !          9931:                                 define->name, tmp);
        !          9932: #endif
        !          9933:                 if (tmp != 0)
        !          9934:                     ret = -1;
        !          9935: 
        !          9936:                 if (ctxt->states != NULL) {
        !          9937:                     tmp = -1;
        !          9938: 
        !          9939:                     for (i = 0; i < ctxt->states->nbState; i++) {
        !          9940:                         state = ctxt->states->tabState[i];
        !          9941:                         ctxt->state = state;
        !          9942:                         ctxt->state->seq = nseq;
        !          9943: 
        !          9944:                         if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
        !          9945:                             tmp = 0;
        !          9946:                             break;
        !          9947:                         }
        !          9948:                     }
        !          9949:                     if (tmp != 0) {
        !          9950:                         /*
        !          9951:                          * validation error, log the message for the "best" one
        !          9952:                          */
        !          9953:                         ctxt->flags |= FLAGS_IGNORABLE;
        !          9954:                         xmlRelaxNGLogBestError(ctxt);
        !          9955:                     }
        !          9956:                     for (i = 0; i < ctxt->states->nbState; i++) {
        !          9957:                         xmlRelaxNGFreeValidState(ctxt,
        !          9958:                                                  ctxt->states->
        !          9959:                                                  tabState[i]);
        !          9960:                     }
        !          9961:                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          9962:                     ctxt->flags = oldflags;
        !          9963:                     ctxt->states = NULL;
        !          9964:                     if ((ret == 0) && (tmp == -1))
        !          9965:                         ret = -1;
        !          9966:                 } else {
        !          9967:                     state = ctxt->state;
        !          9968:                    if (ctxt->state != NULL)
        !          9969:                        ctxt->state->seq = nseq;
        !          9970:                     if (ret == 0)
        !          9971:                         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
        !          9972:                     xmlRelaxNGFreeValidState(ctxt, state);
        !          9973:                 }
        !          9974:             } else {
        !          9975:                 if (define->content != NULL) {
        !          9976:                     tmp = xmlRelaxNGValidateDefinitionList(ctxt,
        !          9977:                                                            define->
        !          9978:                                                            content);
        !          9979:                     if (tmp != 0) {
        !          9980:                         ret = -1;
        !          9981:                         if (ctxt->state == NULL) {
        !          9982:                             ctxt->state = oldstate;
        !          9983:                             VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
        !          9984:                                        node->name);
        !          9985:                             ctxt->state = NULL;
        !          9986:                         } else {
        !          9987:                             VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
        !          9988:                                        node->name);
        !          9989:                         }
        !          9990: 
        !          9991:                     }
        !          9992:                 }
        !          9993:                 if (ctxt->states != NULL) {
        !          9994:                     tmp = -1;
        !          9995: 
        !          9996:                     for (i = 0; i < ctxt->states->nbState; i++) {
        !          9997:                         state = ctxt->states->tabState[i];
        !          9998:                         ctxt->state = state;
        !          9999: 
        !          10000:                         if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
        !          10001:                             tmp = 0;
        !          10002:                             break;
        !          10003:                         }
        !          10004:                     }
        !          10005:                     if (tmp != 0) {
        !          10006:                         /*
        !          10007:                          * validation error, log the message for the "best" one
        !          10008:                          */
        !          10009:                         ctxt->flags |= FLAGS_IGNORABLE;
        !          10010:                         xmlRelaxNGLogBestError(ctxt);
        !          10011:                     }
        !          10012:                     for (i = 0; i < ctxt->states->nbState; i++) {
        !          10013:                         xmlRelaxNGFreeValidState(ctxt,
        !          10014:                                                  ctxt->states->tabState[i]);
        !          10015:                         ctxt->states->tabState[i] = NULL;
        !          10016:                     }
        !          10017:                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          10018:                     ctxt->flags = oldflags;
        !          10019:                     ctxt->states = NULL;
        !          10020:                     if ((ret == 0) && (tmp == -1))
        !          10021:                         ret = -1;
        !          10022:                 } else {
        !          10023:                     state = ctxt->state;
        !          10024:                     if (ret == 0)
        !          10025:                         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
        !          10026:                     xmlRelaxNGFreeValidState(ctxt, state);
        !          10027:                 }
        !          10028:             }
        !          10029:             if (ret == 0) {
        !          10030:                 node->psvi = define;
        !          10031:             }
        !          10032:             ctxt->flags = oldflags;
        !          10033:             ctxt->state = oldstate;
        !          10034:             if (oldstate != NULL)
        !          10035:                 oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
        !          10036:             if (ret != 0) {
        !          10037:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
        !          10038:                     xmlRelaxNGDumpValidError(ctxt);
        !          10039:                     ret = 0;
        !          10040: #if 0
        !          10041:                 } else {
        !          10042:                     ret = -2;
        !          10043: #endif
        !          10044:                 }
        !          10045:             } else {
        !          10046:                 if (ctxt->errNr > errNr)
        !          10047:                     xmlRelaxNGPopErrors(ctxt, errNr);
        !          10048:             }
        !          10049: 
        !          10050: #ifdef DEBUG
        !          10051:             xmlGenericError(xmlGenericErrorContext,
        !          10052:                             "xmlRelaxNGValidateDefinition(): validated %s : %d",
        !          10053:                             node->name, ret);
        !          10054:             if (oldstate == NULL)
        !          10055:                 xmlGenericError(xmlGenericErrorContext, ": no state\n");
        !          10056:             else if (oldstate->seq == NULL)
        !          10057:                 xmlGenericError(xmlGenericErrorContext, ": done\n");
        !          10058:             else if (oldstate->seq->type == XML_ELEMENT_NODE)
        !          10059:                 xmlGenericError(xmlGenericErrorContext, ": next elem %s\n",
        !          10060:                                 oldstate->seq->name);
        !          10061:             else
        !          10062:                 xmlGenericError(xmlGenericErrorContext, ": next %s %d\n",
        !          10063:                                 oldstate->seq->name, oldstate->seq->type);
        !          10064: #endif
        !          10065:             break;
        !          10066:         case XML_RELAXNG_OPTIONAL:{
        !          10067:                 errNr = ctxt->errNr;
        !          10068:                 oldflags = ctxt->flags;
        !          10069:                 ctxt->flags |= FLAGS_IGNORABLE;
        !          10070:                 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
        !          10071:                 ret =
        !          10072:                     xmlRelaxNGValidateDefinitionList(ctxt,
        !          10073:                                                      define->content);
        !          10074:                 if (ret != 0) {
        !          10075:                     if (ctxt->state != NULL)
        !          10076:                         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10077:                     ctxt->state = oldstate;
        !          10078:                     ctxt->flags = oldflags;
        !          10079:                     ret = 0;
        !          10080:                     if (ctxt->errNr > errNr)
        !          10081:                         xmlRelaxNGPopErrors(ctxt, errNr);
        !          10082:                     break;
        !          10083:                 }
        !          10084:                 if (ctxt->states != NULL) {
        !          10085:                     xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
        !          10086:                 } else {
        !          10087:                     ctxt->states = xmlRelaxNGNewStates(ctxt, 1);
        !          10088:                     if (ctxt->states == NULL) {
        !          10089:                         xmlRelaxNGFreeValidState(ctxt, oldstate);
        !          10090:                         ctxt->flags = oldflags;
        !          10091:                         ret = -1;
        !          10092:                         if (ctxt->errNr > errNr)
        !          10093:                             xmlRelaxNGPopErrors(ctxt, errNr);
        !          10094:                         break;
        !          10095:                     }
        !          10096:                     xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
        !          10097:                     xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state);
        !          10098:                     ctxt->state = NULL;
        !          10099:                 }
        !          10100:                 ctxt->flags = oldflags;
        !          10101:                 ret = 0;
        !          10102:                 if (ctxt->errNr > errNr)
        !          10103:                     xmlRelaxNGPopErrors(ctxt, errNr);
        !          10104:                 break;
        !          10105:             }
        !          10106:         case XML_RELAXNG_ONEORMORE:
        !          10107:             errNr = ctxt->errNr;
        !          10108:             ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
        !          10109:             if (ret != 0) {
        !          10110:                 break;
        !          10111:             }
        !          10112:             if (ctxt->errNr > errNr)
        !          10113:                 xmlRelaxNGPopErrors(ctxt, errNr);
        !          10114:             /* no break on purpose */
        !          10115:         case XML_RELAXNG_ZEROORMORE:{
        !          10116:                 int progress;
        !          10117:                 xmlRelaxNGStatesPtr states = NULL, res = NULL;
        !          10118:                 int base, j;
        !          10119: 
        !          10120:                 errNr = ctxt->errNr;
        !          10121:                 res = xmlRelaxNGNewStates(ctxt, 1);
        !          10122:                 if (res == NULL) {
        !          10123:                     ret = -1;
        !          10124:                     break;
        !          10125:                 }
        !          10126:                 /*
        !          10127:                  * All the input states are also exit states
        !          10128:                  */
        !          10129:                 if (ctxt->state != NULL) {
        !          10130:                     xmlRelaxNGAddStates(ctxt, res,
        !          10131:                                         xmlRelaxNGCopyValidState(ctxt,
        !          10132:                                                                  ctxt->
        !          10133:                                                                  state));
        !          10134:                 } else {
        !          10135:                     for (j = 0; j < ctxt->states->nbState; j++) {
        !          10136:                         xmlRelaxNGAddStates(ctxt, res,
        !          10137:                             xmlRelaxNGCopyValidState(ctxt,
        !          10138:                                             ctxt->states->tabState[j]));
        !          10139:                     }
        !          10140:                 }
        !          10141:                 oldflags = ctxt->flags;
        !          10142:                 ctxt->flags |= FLAGS_IGNORABLE;
        !          10143:                 do {
        !          10144:                     progress = 0;
        !          10145:                     base = res->nbState;
        !          10146: 
        !          10147:                     if (ctxt->states != NULL) {
        !          10148:                         states = ctxt->states;
        !          10149:                         for (i = 0; i < states->nbState; i++) {
        !          10150:                             ctxt->state = states->tabState[i];
        !          10151:                             ctxt->states = NULL;
        !          10152:                             ret = xmlRelaxNGValidateDefinitionList(ctxt,
        !          10153:                                                                    define->
        !          10154:                                                                    content);
        !          10155:                             if (ret == 0) {
        !          10156:                                 if (ctxt->state != NULL) {
        !          10157:                                     tmp = xmlRelaxNGAddStates(ctxt, res,
        !          10158:                                                               ctxt->state);
        !          10159:                                     ctxt->state = NULL;
        !          10160:                                     if (tmp == 1)
        !          10161:                                         progress = 1;
        !          10162:                                 } else if (ctxt->states != NULL) {
        !          10163:                                     for (j = 0; j < ctxt->states->nbState;
        !          10164:                                          j++) {
        !          10165:                                         tmp =
        !          10166:                                             xmlRelaxNGAddStates(ctxt, res,
        !          10167:                                                    ctxt->states->tabState[j]);
        !          10168:                                         if (tmp == 1)
        !          10169:                                             progress = 1;
        !          10170:                                     }
        !          10171:                                     xmlRelaxNGFreeStates(ctxt,
        !          10172:                                                          ctxt->states);
        !          10173:                                     ctxt->states = NULL;
        !          10174:                                 }
        !          10175:                             } else {
        !          10176:                                 if (ctxt->state != NULL) {
        !          10177:                                     xmlRelaxNGFreeValidState(ctxt,
        !          10178:                                                              ctxt->state);
        !          10179:                                     ctxt->state = NULL;
        !          10180:                                 }
        !          10181:                             }
        !          10182:                         }
        !          10183:                     } else {
        !          10184:                         ret = xmlRelaxNGValidateDefinitionList(ctxt,
        !          10185:                                                                define->
        !          10186:                                                                content);
        !          10187:                         if (ret != 0) {
        !          10188:                             xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10189:                             ctxt->state = NULL;
        !          10190:                         } else {
        !          10191:                             base = res->nbState;
        !          10192:                             if (ctxt->state != NULL) {
        !          10193:                                 tmp = xmlRelaxNGAddStates(ctxt, res,
        !          10194:                                                           ctxt->state);
        !          10195:                                 ctxt->state = NULL;
        !          10196:                                 if (tmp == 1)
        !          10197:                                     progress = 1;
        !          10198:                             } else if (ctxt->states != NULL) {
        !          10199:                                 for (j = 0; j < ctxt->states->nbState; j++) {
        !          10200:                                     tmp = xmlRelaxNGAddStates(ctxt, res,
        !          10201:                                                ctxt->states->tabState[j]);
        !          10202:                                     if (tmp == 1)
        !          10203:                                         progress = 1;
        !          10204:                                 }
        !          10205:                                 if (states == NULL) {
        !          10206:                                     states = ctxt->states;
        !          10207:                                 } else {
        !          10208:                                     xmlRelaxNGFreeStates(ctxt,
        !          10209:                                                          ctxt->states);
        !          10210:                                 }
        !          10211:                                 ctxt->states = NULL;
        !          10212:                             }
        !          10213:                         }
        !          10214:                     }
        !          10215:                     if (progress) {
        !          10216:                         /*
        !          10217:                          * Collect all the new nodes added at that step
        !          10218:                          * and make them the new node set
        !          10219:                          */
        !          10220:                         if (res->nbState - base == 1) {
        !          10221:                             ctxt->state = xmlRelaxNGCopyValidState(ctxt,
        !          10222:                                                                    res->
        !          10223:                                                                    tabState
        !          10224:                                                                    [base]);
        !          10225:                         } else {
        !          10226:                             if (states == NULL) {
        !          10227:                                 xmlRelaxNGNewStates(ctxt,
        !          10228:                                                     res->nbState - base);
        !          10229:                                states = ctxt->states;
        !          10230:                                if (states == NULL) {
        !          10231:                                    progress = 0;
        !          10232:                                    break;
        !          10233:                                }
        !          10234:                             }
        !          10235:                             states->nbState = 0;
        !          10236:                             for (i = base; i < res->nbState; i++)
        !          10237:                                 xmlRelaxNGAddStates(ctxt, states,
        !          10238:                                                     xmlRelaxNGCopyValidState
        !          10239:                                                     (ctxt, res->tabState[i]));
        !          10240:                             ctxt->states = states;
        !          10241:                         }
        !          10242:                     }
        !          10243:                 } while (progress == 1);
        !          10244:                 if (states != NULL) {
        !          10245:                     xmlRelaxNGFreeStates(ctxt, states);
        !          10246:                 }
        !          10247:                 ctxt->states = res;
        !          10248:                 ctxt->flags = oldflags;
        !          10249: #if 0
        !          10250:                 /*
        !          10251:                  * errors may have to be propagated back...
        !          10252:                  */
        !          10253:                 if (ctxt->errNr > errNr)
        !          10254:                     xmlRelaxNGPopErrors(ctxt, errNr);
        !          10255: #endif
        !          10256:                 ret = 0;
        !          10257:                 break;
        !          10258:             }
        !          10259:         case XML_RELAXNG_CHOICE:{
        !          10260:                 xmlRelaxNGDefinePtr list = NULL;
        !          10261:                 xmlRelaxNGStatesPtr states = NULL;
        !          10262: 
        !          10263:                 node = xmlRelaxNGSkipIgnored(ctxt, node);
        !          10264: 
        !          10265:                 errNr = ctxt->errNr;
        !          10266:                 if ((define->dflags & IS_TRIABLE) && (define->data != NULL) &&
        !          10267:                    (node != NULL)) {
        !          10268:                    /*
        !          10269:                     * node == NULL can't be optimized since IS_TRIABLE
        !          10270:                     * doesn't account for choice which may lead to
        !          10271:                     * only attributes.
        !          10272:                     */
        !          10273:                     xmlHashTablePtr triage =
        !          10274:                         (xmlHashTablePtr) define->data;
        !          10275: 
        !          10276:                     /*
        !          10277:                      * Something we can optimize cleanly there is only one
        !          10278:                      * possble branch out !
        !          10279:                      */
        !          10280:                     if ((node->type == XML_TEXT_NODE) ||
        !          10281:                         (node->type == XML_CDATA_SECTION_NODE)) {
        !          10282:                         list =
        !          10283:                             xmlHashLookup2(triage, BAD_CAST "#text", NULL);
        !          10284:                     } else if (node->type == XML_ELEMENT_NODE) {
        !          10285:                         if (node->ns != NULL) {
        !          10286:                             list = xmlHashLookup2(triage, node->name,
        !          10287:                                                   node->ns->href);
        !          10288:                             if (list == NULL)
        !          10289:                                 list =
        !          10290:                                     xmlHashLookup2(triage, BAD_CAST "#any",
        !          10291:                                                    node->ns->href);
        !          10292:                         } else
        !          10293:                             list =
        !          10294:                                 xmlHashLookup2(triage, node->name, NULL);
        !          10295:                         if (list == NULL)
        !          10296:                             list =
        !          10297:                                 xmlHashLookup2(triage, BAD_CAST "#any",
        !          10298:                                                NULL);
        !          10299:                     }
        !          10300:                     if (list == NULL) {
        !          10301:                         ret = -1;
        !          10302:                        VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, node->name);
        !          10303:                         break;
        !          10304:                     }
        !          10305:                     ret = xmlRelaxNGValidateDefinition(ctxt, list);
        !          10306:                     if (ret == 0) {
        !          10307:                     }
        !          10308:                     break;
        !          10309:                 }
        !          10310: 
        !          10311:                 list = define->content;
        !          10312:                 oldflags = ctxt->flags;
        !          10313:                 ctxt->flags |= FLAGS_IGNORABLE;
        !          10314: 
        !          10315:                 while (list != NULL) {
        !          10316:                     oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
        !          10317:                     ret = xmlRelaxNGValidateDefinition(ctxt, list);
        !          10318:                     if (ret == 0) {
        !          10319:                         if (states == NULL) {
        !          10320:                             states = xmlRelaxNGNewStates(ctxt, 1);
        !          10321:                         }
        !          10322:                         if (ctxt->state != NULL) {
        !          10323:                             xmlRelaxNGAddStates(ctxt, states, ctxt->state);
        !          10324:                         } else if (ctxt->states != NULL) {
        !          10325:                             for (i = 0; i < ctxt->states->nbState; i++) {
        !          10326:                                 xmlRelaxNGAddStates(ctxt, states,
        !          10327:                                                     ctxt->states->
        !          10328:                                                     tabState[i]);
        !          10329:                             }
        !          10330:                             xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          10331:                             ctxt->states = NULL;
        !          10332:                         }
        !          10333:                     } else {
        !          10334:                         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10335:                     }
        !          10336:                     ctxt->state = oldstate;
        !          10337:                     list = list->next;
        !          10338:                 }
        !          10339:                 if (states != NULL) {
        !          10340:                     xmlRelaxNGFreeValidState(ctxt, oldstate);
        !          10341:                     ctxt->states = states;
        !          10342:                     ctxt->state = NULL;
        !          10343:                     ret = 0;
        !          10344:                 } else {
        !          10345:                     ctxt->states = NULL;
        !          10346:                 }
        !          10347:                 ctxt->flags = oldflags;
        !          10348:                 if (ret != 0) {
        !          10349:                     if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
        !          10350:                         xmlRelaxNGDumpValidError(ctxt);
        !          10351:                     }
        !          10352:                 } else {
        !          10353:                     if (ctxt->errNr > errNr)
        !          10354:                         xmlRelaxNGPopErrors(ctxt, errNr);
        !          10355:                 }
        !          10356:                 break;
        !          10357:             }
        !          10358:         case XML_RELAXNG_DEF:
        !          10359:         case XML_RELAXNG_GROUP:
        !          10360:             ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
        !          10361:             break;
        !          10362:         case XML_RELAXNG_INTERLEAVE:
        !          10363:             ret = xmlRelaxNGValidateInterleave(ctxt, define);
        !          10364:             break;
        !          10365:         case XML_RELAXNG_ATTRIBUTE:
        !          10366:             ret = xmlRelaxNGValidateAttribute(ctxt, define);
        !          10367:             break;
        !          10368:         case XML_RELAXNG_START:
        !          10369:         case XML_RELAXNG_NOOP:
        !          10370:         case XML_RELAXNG_REF:
        !          10371:         case XML_RELAXNG_EXTERNALREF:
        !          10372:         case XML_RELAXNG_PARENTREF:
        !          10373:             ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
        !          10374:             break;
        !          10375:         case XML_RELAXNG_DATATYPE:{
        !          10376:                 xmlNodePtr child;
        !          10377:                 xmlChar *content = NULL;
        !          10378: 
        !          10379:                 child = node;
        !          10380:                 while (child != NULL) {
        !          10381:                     if (child->type == XML_ELEMENT_NODE) {
        !          10382:                         VALID_ERR2(XML_RELAXNG_ERR_DATAELEM,
        !          10383:                                    node->parent->name);
        !          10384:                         ret = -1;
        !          10385:                         break;
        !          10386:                     } else if ((child->type == XML_TEXT_NODE) ||
        !          10387:                                (child->type == XML_CDATA_SECTION_NODE)) {
        !          10388:                         content = xmlStrcat(content, child->content);
        !          10389:                     }
        !          10390:                     /* TODO: handle entities ... */
        !          10391:                     child = child->next;
        !          10392:                 }
        !          10393:                 if (ret == -1) {
        !          10394:                     if (content != NULL)
        !          10395:                         xmlFree(content);
        !          10396:                     break;
        !          10397:                 }
        !          10398:                 if (content == NULL) {
        !          10399:                     content = xmlStrdup(BAD_CAST "");
        !          10400:                     if (content == NULL) {
        !          10401:                         xmlRngVErrMemory(ctxt, "validating\n");
        !          10402:                         ret = -1;
        !          10403:                         break;
        !          10404:                     }
        !          10405:                 }
        !          10406:                 ret = xmlRelaxNGValidateDatatype(ctxt, content, define,
        !          10407:                                                  ctxt->state->seq);
        !          10408:                 if (ret == -1) {
        !          10409:                     VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name);
        !          10410:                 } else if (ret == 0) {
        !          10411:                     ctxt->state->seq = NULL;
        !          10412:                 }
        !          10413:                 if (content != NULL)
        !          10414:                     xmlFree(content);
        !          10415:                 break;
        !          10416:             }
        !          10417:         case XML_RELAXNG_VALUE:{
        !          10418:                 xmlChar *content = NULL;
        !          10419:                 xmlChar *oldvalue;
        !          10420:                 xmlNodePtr child;
        !          10421: 
        !          10422:                 child = node;
        !          10423:                 while (child != NULL) {
        !          10424:                     if (child->type == XML_ELEMENT_NODE) {
        !          10425:                         VALID_ERR2(XML_RELAXNG_ERR_VALELEM,
        !          10426:                                    node->parent->name);
        !          10427:                         ret = -1;
        !          10428:                         break;
        !          10429:                     } else if ((child->type == XML_TEXT_NODE) ||
        !          10430:                                (child->type == XML_CDATA_SECTION_NODE)) {
        !          10431:                         content = xmlStrcat(content, child->content);
        !          10432:                     }
        !          10433:                     /* TODO: handle entities ... */
        !          10434:                     child = child->next;
        !          10435:                 }
        !          10436:                 if (ret == -1) {
        !          10437:                     if (content != NULL)
        !          10438:                         xmlFree(content);
        !          10439:                     break;
        !          10440:                 }
        !          10441:                 if (content == NULL) {
        !          10442:                     content = xmlStrdup(BAD_CAST "");
        !          10443:                     if (content == NULL) {
        !          10444:                         xmlRngVErrMemory(ctxt, "validating\n");
        !          10445:                         ret = -1;
        !          10446:                         break;
        !          10447:                     }
        !          10448:                 }
        !          10449:                 oldvalue = ctxt->state->value;
        !          10450:                 ctxt->state->value = content;
        !          10451:                 ret = xmlRelaxNGValidateValue(ctxt, define);
        !          10452:                 ctxt->state->value = oldvalue;
        !          10453:                 if (ret == -1) {
        !          10454:                     VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name);
        !          10455:                 } else if (ret == 0) {
        !          10456:                     ctxt->state->seq = NULL;
        !          10457:                 }
        !          10458:                 if (content != NULL)
        !          10459:                     xmlFree(content);
        !          10460:                 break;
        !          10461:             }
        !          10462:         case XML_RELAXNG_LIST:{
        !          10463:                 xmlChar *content;
        !          10464:                 xmlNodePtr child;
        !          10465:                 xmlChar *oldvalue, *oldendvalue;
        !          10466:                 int len;
        !          10467: 
        !          10468:                 /*
        !          10469:                  * Make sure it's only text nodes
        !          10470:                  */
        !          10471: 
        !          10472:                 content = NULL;
        !          10473:                 child = node;
        !          10474:                 while (child != NULL) {
        !          10475:                     if (child->type == XML_ELEMENT_NODE) {
        !          10476:                         VALID_ERR2(XML_RELAXNG_ERR_LISTELEM,
        !          10477:                                    node->parent->name);
        !          10478:                         ret = -1;
        !          10479:                         break;
        !          10480:                     } else if ((child->type == XML_TEXT_NODE) ||
        !          10481:                                (child->type == XML_CDATA_SECTION_NODE)) {
        !          10482:                         content = xmlStrcat(content, child->content);
        !          10483:                     }
        !          10484:                     /* TODO: handle entities ... */
        !          10485:                     child = child->next;
        !          10486:                 }
        !          10487:                 if (ret == -1) {
        !          10488:                     if (content != NULL)
        !          10489:                         xmlFree(content);
        !          10490:                     break;
        !          10491:                 }
        !          10492:                 if (content == NULL) {
        !          10493:                     content = xmlStrdup(BAD_CAST "");
        !          10494:                     if (content == NULL) {
        !          10495:                         xmlRngVErrMemory(ctxt, "validating\n");
        !          10496:                         ret = -1;
        !          10497:                         break;
        !          10498:                     }
        !          10499:                 }
        !          10500:                 len = xmlStrlen(content);
        !          10501:                 oldvalue = ctxt->state->value;
        !          10502:                 oldendvalue = ctxt->state->endvalue;
        !          10503:                 ctxt->state->value = content;
        !          10504:                 ctxt->state->endvalue = content + len;
        !          10505:                 ret = xmlRelaxNGValidateValue(ctxt, define);
        !          10506:                 ctxt->state->value = oldvalue;
        !          10507:                 ctxt->state->endvalue = oldendvalue;
        !          10508:                 if (ret == -1) {
        !          10509:                     VALID_ERR(XML_RELAXNG_ERR_LIST);
        !          10510:                 } else if ((ret == 0) && (node != NULL)) {
        !          10511:                     ctxt->state->seq = node->next;
        !          10512:                 }
        !          10513:                 if (content != NULL)
        !          10514:                     xmlFree(content);
        !          10515:                 break;
        !          10516:             }
        !          10517:         case XML_RELAXNG_EXCEPT:
        !          10518:         case XML_RELAXNG_PARAM:
        !          10519:             TODO ret = -1;
        !          10520:             break;
        !          10521:     }
        !          10522:     ctxt->depth--;
        !          10523: #ifdef DEBUG
        !          10524:     for (i = 0; i < ctxt->depth; i++)
        !          10525:         xmlGenericError(xmlGenericErrorContext, " ");
        !          10526:     xmlGenericError(xmlGenericErrorContext,
        !          10527:                     "Validating %s ", xmlRelaxNGDefName(define));
        !          10528:     if (define->name != NULL)
        !          10529:         xmlGenericError(xmlGenericErrorContext, "%s ", define->name);
        !          10530:     if (ret == 0)
        !          10531:         xmlGenericError(xmlGenericErrorContext, "suceeded\n");
        !          10532:     else
        !          10533:         xmlGenericError(xmlGenericErrorContext, "failed\n");
        !          10534: #endif
        !          10535:     return (ret);
        !          10536: }
        !          10537: 
        !          10538: /**
        !          10539:  * xmlRelaxNGValidateDefinition:
        !          10540:  * @ctxt:  a Relax-NG validation context
        !          10541:  * @define:  the definition to verify
        !          10542:  *
        !          10543:  * Validate the current node lists against the definition
        !          10544:  *
        !          10545:  * Returns 0 if the validation succeeded or an error code.
        !          10546:  */
        !          10547: static int
        !          10548: xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
        !          10549:                              xmlRelaxNGDefinePtr define)
        !          10550: {
        !          10551:     xmlRelaxNGStatesPtr states, res;
        !          10552:     int i, j, k, ret, oldflags;
        !          10553: 
        !          10554:     /*
        !          10555:      * We should NOT have both ctxt->state and ctxt->states
        !          10556:      */
        !          10557:     if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
        !          10558:         TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10559:         ctxt->state = NULL;
        !          10560:     }
        !          10561: 
        !          10562:     if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) {
        !          10563:         if (ctxt->states != NULL) {
        !          10564:             ctxt->state = ctxt->states->tabState[0];
        !          10565:             xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          10566:             ctxt->states = NULL;
        !          10567:         }
        !          10568:         ret = xmlRelaxNGValidateState(ctxt, define);
        !          10569:         if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
        !          10570:             TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10571:             ctxt->state = NULL;
        !          10572:         }
        !          10573:         if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) {
        !          10574:             ctxt->state = ctxt->states->tabState[0];
        !          10575:             xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          10576:             ctxt->states = NULL;
        !          10577:         }
        !          10578:         return (ret);
        !          10579:     }
        !          10580: 
        !          10581:     states = ctxt->states;
        !          10582:     ctxt->states = NULL;
        !          10583:     res = NULL;
        !          10584:     j = 0;
        !          10585:     oldflags = ctxt->flags;
        !          10586:     ctxt->flags |= FLAGS_IGNORABLE;
        !          10587:     for (i = 0; i < states->nbState; i++) {
        !          10588:         ctxt->state = states->tabState[i];
        !          10589:         ctxt->states = NULL;
        !          10590:         ret = xmlRelaxNGValidateState(ctxt, define);
        !          10591:         /*
        !          10592:          * We should NOT have both ctxt->state and ctxt->states
        !          10593:          */
        !          10594:         if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
        !          10595:             TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10596:             ctxt->state = NULL;
        !          10597:         }
        !          10598:         if (ret == 0) {
        !          10599:             if (ctxt->states == NULL) {
        !          10600:                 if (res != NULL) {
        !          10601:                     /* add the state to the container */
        !          10602:                     xmlRelaxNGAddStates(ctxt, res, ctxt->state);
        !          10603:                     ctxt->state = NULL;
        !          10604:                 } else {
        !          10605:                     /* add the state directly in states */
        !          10606:                     states->tabState[j++] = ctxt->state;
        !          10607:                     ctxt->state = NULL;
        !          10608:                 }
        !          10609:             } else {
        !          10610:                 if (res == NULL) {
        !          10611:                     /* make it the new container and copy other results */
        !          10612:                     res = ctxt->states;
        !          10613:                     ctxt->states = NULL;
        !          10614:                     for (k = 0; k < j; k++)
        !          10615:                         xmlRelaxNGAddStates(ctxt, res,
        !          10616:                                             states->tabState[k]);
        !          10617:                 } else {
        !          10618:                     /* add all the new results to res and reff the container */
        !          10619:                     for (k = 0; k < ctxt->states->nbState; k++)
        !          10620:                         xmlRelaxNGAddStates(ctxt, res,
        !          10621:                                             ctxt->states->tabState[k]);
        !          10622:                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          10623:                     ctxt->states = NULL;
        !          10624:                 }
        !          10625:             }
        !          10626:         } else {
        !          10627:             if (ctxt->state != NULL) {
        !          10628:                 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10629:                 ctxt->state = NULL;
        !          10630:             } else if (ctxt->states != NULL) {
        !          10631:                 for (k = 0; k < ctxt->states->nbState; k++)
        !          10632:                     xmlRelaxNGFreeValidState(ctxt,
        !          10633:                                              ctxt->states->tabState[k]);
        !          10634:                 xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          10635:                 ctxt->states = NULL;
        !          10636:             }
        !          10637:         }
        !          10638:     }
        !          10639:     ctxt->flags = oldflags;
        !          10640:     if (res != NULL) {
        !          10641:         xmlRelaxNGFreeStates(ctxt, states);
        !          10642:         ctxt->states = res;
        !          10643:         ret = 0;
        !          10644:     } else if (j > 1) {
        !          10645:         states->nbState = j;
        !          10646:         ctxt->states = states;
        !          10647:         ret = 0;
        !          10648:     } else if (j == 1) {
        !          10649:         ctxt->state = states->tabState[0];
        !          10650:         xmlRelaxNGFreeStates(ctxt, states);
        !          10651:         ret = 0;
        !          10652:     } else {
        !          10653:         ret = -1;
        !          10654:         xmlRelaxNGFreeStates(ctxt, states);
        !          10655:         if (ctxt->states != NULL) {
        !          10656:             xmlRelaxNGFreeStates(ctxt, ctxt->states);
        !          10657:             ctxt->states = NULL;
        !          10658:         }
        !          10659:     }
        !          10660:     if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
        !          10661:         TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10662:         ctxt->state = NULL;
        !          10663:     }
        !          10664:     return (ret);
        !          10665: }
        !          10666: 
        !          10667: /**
        !          10668:  * xmlRelaxNGValidateDocument:
        !          10669:  * @ctxt:  a Relax-NG validation context
        !          10670:  * @doc:  the document
        !          10671:  *
        !          10672:  * Validate the given document
        !          10673:  *
        !          10674:  * Returns 0 if the validation succeeded or an error code.
        !          10675:  */
        !          10676: static int
        !          10677: xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
        !          10678: {
        !          10679:     int ret;
        !          10680:     xmlRelaxNGPtr schema;
        !          10681:     xmlRelaxNGGrammarPtr grammar;
        !          10682:     xmlRelaxNGValidStatePtr state;
        !          10683:     xmlNodePtr node;
        !          10684: 
        !          10685:     if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL))
        !          10686:         return (-1);
        !          10687: 
        !          10688:     ctxt->errNo = XML_RELAXNG_OK;
        !          10689:     schema = ctxt->schema;
        !          10690:     grammar = schema->topgrammar;
        !          10691:     if (grammar == NULL) {
        !          10692:         VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
        !          10693:         return (-1);
        !          10694:     }
        !          10695:     state = xmlRelaxNGNewValidState(ctxt, NULL);
        !          10696:     ctxt->state = state;
        !          10697:     ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start);
        !          10698:     if ((ctxt->state != NULL) && (state->seq != NULL)) {
        !          10699:         state = ctxt->state;
        !          10700:         node = state->seq;
        !          10701:         node = xmlRelaxNGSkipIgnored(ctxt, node);
        !          10702:         if (node != NULL) {
        !          10703:             if (ret != -1) {
        !          10704:                 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
        !          10705:                 ret = -1;
        !          10706:             }
        !          10707:         }
        !          10708:     } else if (ctxt->states != NULL) {
        !          10709:         int i;
        !          10710:         int tmp = -1;
        !          10711: 
        !          10712:         for (i = 0; i < ctxt->states->nbState; i++) {
        !          10713:             state = ctxt->states->tabState[i];
        !          10714:             node = state->seq;
        !          10715:             node = xmlRelaxNGSkipIgnored(ctxt, node);
        !          10716:             if (node == NULL)
        !          10717:                 tmp = 0;
        !          10718:             xmlRelaxNGFreeValidState(ctxt, state);
        !          10719:         }
        !          10720:         if (tmp == -1) {
        !          10721:             if (ret != -1) {
        !          10722:                 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
        !          10723:                 ret = -1;
        !          10724:             }
        !          10725:         }
        !          10726:     }
        !          10727:     if (ctxt->state != NULL) {
        !          10728:         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
        !          10729:         ctxt->state = NULL;
        !          10730:     }
        !          10731:     if (ret != 0)
        !          10732:         xmlRelaxNGDumpValidError(ctxt);
        !          10733: #ifdef DEBUG
        !          10734:     else if (ctxt->errNr != 0) {
        !          10735:         ctxt->error(ctxt->userData,
        !          10736:                     "%d Extra error messages left on stack !\n",
        !          10737:                     ctxt->errNr);
        !          10738:         xmlRelaxNGDumpValidError(ctxt);
        !          10739:     }
        !          10740: #endif
        !          10741: #ifdef LIBXML_VALID_ENABLED
        !          10742:     if (ctxt->idref == 1) {
        !          10743:         xmlValidCtxt vctxt;
        !          10744: 
        !          10745:         memset(&vctxt, 0, sizeof(xmlValidCtxt));
        !          10746:         vctxt.valid = 1;
        !          10747:         vctxt.error = ctxt->error;
        !          10748:         vctxt.warning = ctxt->warning;
        !          10749:         vctxt.userData = ctxt->userData;
        !          10750: 
        !          10751:         if (xmlValidateDocumentFinal(&vctxt, doc) != 1)
        !          10752:             ret = -1;
        !          10753:     }
        !          10754: #endif /* LIBXML_VALID_ENABLED */
        !          10755:     if ((ret == 0) && (ctxt->errNo != XML_RELAXNG_OK))
        !          10756:         ret = -1;
        !          10757: 
        !          10758:     return (ret);
        !          10759: }
        !          10760: 
        !          10761: /**
        !          10762:  * xmlRelaxNGCleanPSVI:
        !          10763:  * @node:  an input element or document
        !          10764:  *
        !          10765:  * Call this routine to speed up XPath computation on static documents.
        !          10766:  * This stamps all the element nodes with the document order
        !          10767:  * Like for line information, the order is kept in the element->content
        !          10768:  * field, the value stored is actually - the node number (starting at -1)
        !          10769:  * to be able to differentiate from line numbers.
        !          10770:  *
        !          10771:  * Returns the number of elements found in the document or -1 in case
        !          10772:  *    of error.
        !          10773:  */
        !          10774: static void
        !          10775: xmlRelaxNGCleanPSVI(xmlNodePtr node) {
        !          10776:     xmlNodePtr cur;
        !          10777: 
        !          10778:     if ((node == NULL) ||
        !          10779:         ((node->type != XML_ELEMENT_NODE) &&
        !          10780:          (node->type != XML_DOCUMENT_NODE) &&
        !          10781:          (node->type != XML_HTML_DOCUMENT_NODE)))
        !          10782:        return;
        !          10783:     if (node->type == XML_ELEMENT_NODE)
        !          10784:         node->psvi = NULL;
        !          10785: 
        !          10786:     cur = node->children;
        !          10787:     while (cur != NULL) {
        !          10788:        if (cur->type == XML_ELEMENT_NODE) {
        !          10789:            cur->psvi = NULL;
        !          10790:            if (cur->children != NULL) {
        !          10791:                cur = cur->children;
        !          10792:                continue;
        !          10793:            }
        !          10794:        }
        !          10795:        if (cur->next != NULL) {
        !          10796:            cur = cur->next;
        !          10797:            continue;
        !          10798:        }
        !          10799:        do {
        !          10800:            cur = cur->parent;
        !          10801:            if (cur == NULL)
        !          10802:                break;
        !          10803:            if (cur == node) {
        !          10804:                cur = NULL;
        !          10805:                break;
        !          10806:            }
        !          10807:            if (cur->next != NULL) {
        !          10808:                cur = cur->next;
        !          10809:                break;
        !          10810:            }
        !          10811:        } while (cur != NULL);
        !          10812:     }
        !          10813:     return;
        !          10814: }
        !          10815: /************************************************************************
        !          10816:  *                                                                     *
        !          10817:  *                     Validation interfaces                           *
        !          10818:  *                                                                     *
        !          10819:  ************************************************************************/
        !          10820: 
        !          10821: /**
        !          10822:  * xmlRelaxNGNewValidCtxt:
        !          10823:  * @schema:  a precompiled XML RelaxNGs
        !          10824:  *
        !          10825:  * Create an XML RelaxNGs validation context based on the given schema
        !          10826:  *
        !          10827:  * Returns the validation context or NULL in case of error
        !          10828:  */
        !          10829: xmlRelaxNGValidCtxtPtr
        !          10830: xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema)
        !          10831: {
        !          10832:     xmlRelaxNGValidCtxtPtr ret;
        !          10833: 
        !          10834:     ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt));
        !          10835:     if (ret == NULL) {
        !          10836:         xmlRngVErrMemory(NULL, "building context\n");
        !          10837:         return (NULL);
        !          10838:     }
        !          10839:     memset(ret, 0, sizeof(xmlRelaxNGValidCtxt));
        !          10840:     ret->schema = schema;
        !          10841:     ret->error = xmlGenericError;
        !          10842:     ret->userData = xmlGenericErrorContext;
        !          10843:     ret->errNr = 0;
        !          10844:     ret->errMax = 0;
        !          10845:     ret->err = NULL;
        !          10846:     ret->errTab = NULL;
        !          10847:     if (schema != NULL)
        !          10848:        ret->idref = schema->idref;
        !          10849:     ret->states = NULL;
        !          10850:     ret->freeState = NULL;
        !          10851:     ret->freeStates = NULL;
        !          10852:     ret->errNo = XML_RELAXNG_OK;
        !          10853:     return (ret);
        !          10854: }
        !          10855: 
        !          10856: /**
        !          10857:  * xmlRelaxNGFreeValidCtxt:
        !          10858:  * @ctxt:  the schema validation context
        !          10859:  *
        !          10860:  * Free the resources associated to the schema validation context
        !          10861:  */
        !          10862: void
        !          10863: xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt)
        !          10864: {
        !          10865:     int k;
        !          10866: 
        !          10867:     if (ctxt == NULL)
        !          10868:         return;
        !          10869:     if (ctxt->states != NULL)
        !          10870:         xmlRelaxNGFreeStates(NULL, ctxt->states);
        !          10871:     if (ctxt->freeState != NULL) {
        !          10872:         for (k = 0; k < ctxt->freeState->nbState; k++) {
        !          10873:             xmlRelaxNGFreeValidState(NULL, ctxt->freeState->tabState[k]);
        !          10874:         }
        !          10875:         xmlRelaxNGFreeStates(NULL, ctxt->freeState);
        !          10876:     }
        !          10877:     if (ctxt->freeStates != NULL) {
        !          10878:         for (k = 0; k < ctxt->freeStatesNr; k++) {
        !          10879:             xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]);
        !          10880:         }
        !          10881:         xmlFree(ctxt->freeStates);
        !          10882:     }
        !          10883:     if (ctxt->errTab != NULL)
        !          10884:         xmlFree(ctxt->errTab);
        !          10885:     if (ctxt->elemTab != NULL) {
        !          10886:         xmlRegExecCtxtPtr exec;
        !          10887: 
        !          10888:         exec = xmlRelaxNGElemPop(ctxt);
        !          10889:         while (exec != NULL) {
        !          10890:             xmlRegFreeExecCtxt(exec);
        !          10891:             exec = xmlRelaxNGElemPop(ctxt);
        !          10892:         }
        !          10893:         xmlFree(ctxt->elemTab);
        !          10894:     }
        !          10895:     xmlFree(ctxt);
        !          10896: }
        !          10897: 
        !          10898: /**
        !          10899:  * xmlRelaxNGSetValidErrors:
        !          10900:  * @ctxt:  a Relax-NG validation context
        !          10901:  * @err:  the error function
        !          10902:  * @warn: the warning function
        !          10903:  * @ctx: the functions context
        !          10904:  *
        !          10905:  * Set the error and warning callback informations
        !          10906:  */
        !          10907: void
        !          10908: xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
        !          10909:                          xmlRelaxNGValidityErrorFunc err,
        !          10910:                          xmlRelaxNGValidityWarningFunc warn, void *ctx)
        !          10911: {
        !          10912:     if (ctxt == NULL)
        !          10913:         return;
        !          10914:     ctxt->error = err;
        !          10915:     ctxt->warning = warn;
        !          10916:     ctxt->userData = ctx;
        !          10917:     ctxt->serror = NULL;
        !          10918: }
        !          10919: 
        !          10920: /**
        !          10921:  * xmlRelaxNGSetValidStructuredErrors:
        !          10922:  * @ctxt:  a Relax-NG validation context
        !          10923:  * @serror:  the structured error function
        !          10924:  * @ctx: the functions context
        !          10925:  *
        !          10926:  * Set the structured error callback
        !          10927:  */
        !          10928: void
        !          10929: xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt,
        !          10930:                                    xmlStructuredErrorFunc serror, void *ctx)
        !          10931: {
        !          10932:     if (ctxt == NULL)
        !          10933:         return;
        !          10934:     ctxt->serror = serror;
        !          10935:     ctxt->error = NULL;
        !          10936:     ctxt->warning = NULL;
        !          10937:     ctxt->userData = ctx;
        !          10938: }
        !          10939: 
        !          10940: /**
        !          10941:  * xmlRelaxNGGetValidErrors:
        !          10942:  * @ctxt:  a Relax-NG validation context
        !          10943:  * @err:  the error function result
        !          10944:  * @warn: the warning function result
        !          10945:  * @ctx: the functions context result
        !          10946:  *
        !          10947:  * Get the error and warning callback informations
        !          10948:  *
        !          10949:  * Returns -1 in case of error and 0 otherwise
        !          10950:  */
        !          10951: int
        !          10952: xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
        !          10953:                          xmlRelaxNGValidityErrorFunc * err,
        !          10954:                          xmlRelaxNGValidityWarningFunc * warn, void **ctx)
        !          10955: {
        !          10956:     if (ctxt == NULL)
        !          10957:         return (-1);
        !          10958:     if (err != NULL)
        !          10959:         *err = ctxt->error;
        !          10960:     if (warn != NULL)
        !          10961:         *warn = ctxt->warning;
        !          10962:     if (ctx != NULL)
        !          10963:         *ctx = ctxt->userData;
        !          10964:     return (0);
        !          10965: }
        !          10966: 
        !          10967: /**
        !          10968:  * xmlRelaxNGValidateDoc:
        !          10969:  * @ctxt:  a Relax-NG validation context
        !          10970:  * @doc:  a parsed document tree
        !          10971:  *
        !          10972:  * Validate a document tree in memory.
        !          10973:  *
        !          10974:  * Returns 0 if the document is valid, a positive error code
        !          10975:  *     number otherwise and -1 in case of internal or API error.
        !          10976:  */
        !          10977: int
        !          10978: xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
        !          10979: {
        !          10980:     int ret;
        !          10981: 
        !          10982:     if ((ctxt == NULL) || (doc == NULL))
        !          10983:         return (-1);
        !          10984: 
        !          10985:     ctxt->doc = doc;
        !          10986: 
        !          10987:     ret = xmlRelaxNGValidateDocument(ctxt, doc);
        !          10988:     /*
        !          10989:      * Remove all left PSVI
        !          10990:      */
        !          10991:     xmlRelaxNGCleanPSVI((xmlNodePtr) doc);
        !          10992: 
        !          10993:     /*
        !          10994:      * TODO: build error codes
        !          10995:      */
        !          10996:     if (ret == -1)
        !          10997:         return (1);
        !          10998:     return (ret);
        !          10999: }
        !          11000: 
        !          11001: #define bottom_relaxng
        !          11002: #include "elfgcchack.h"
        !          11003: #endif /* LIBXML_SCHEMAS_ENABLED */

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