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

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,
1.1.1.2 ! misho    1564:                                                  xmlDocGetRootElement(inc->doc)->children,
        !          1565:                                                  name) == 1) {
1.1       misho    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);
1.1.1.2 ! misho    3062:                 if (xmlAutomataIsDeterminist(ctxt->am))
        !          3063:                     def->contModel = xmlAutomataCompile(ctxt->am);
1.1       misho    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: 
1.1.1.2 ! misho    8887:                 if ((ctxt->state->value == NULL) ||
        !          8888:                     (*ctxt->state->value == 0)) {
        !          8889:                     ret = 0;
        !          8890:                     break;
        !          8891:                 }
1.1       misho    8892:                 oldflags = ctxt->flags;
                   8893:                 ctxt->flags |= FLAGS_IGNORABLE;
                   8894:                 cur = ctxt->state->value;
                   8895:                 temp = NULL;
                   8896:                 while ((cur != NULL) && (cur != ctxt->state->endvalue) &&
                   8897:                        (temp != cur)) {
                   8898:                     temp = cur;
                   8899:                     ret =
                   8900:                         xmlRelaxNGValidateValueList(ctxt, define->content);
                   8901:                     if (ret != 0) {
                   8902:                         ctxt->state->value = temp;
                   8903:                         ret = 0;
                   8904:                         break;
                   8905:                     }
                   8906:                     cur = ctxt->state->value;
                   8907:                 }
                   8908:                 ctxt->flags = oldflags;
                   8909:                if (ctxt->errNr > 0)
                   8910:                    xmlRelaxNGPopErrors(ctxt, 0);
                   8911:                 break;
                   8912:             }
1.1.1.2 ! misho    8913:         case XML_RELAXNG_OPTIONAL:{
        !          8914:                 xmlChar *temp;
        !          8915: 
        !          8916:                 if ((ctxt->state->value == NULL) ||
        !          8917:                     (*ctxt->state->value == 0)) {
        !          8918:                     ret = 0;
        !          8919:                     break;
        !          8920:                 }
        !          8921:                 oldflags = ctxt->flags;
        !          8922:                 ctxt->flags |= FLAGS_IGNORABLE;
        !          8923:                 temp = ctxt->state->value;
        !          8924:                 ret = xmlRelaxNGValidateValue(ctxt, define->content);
        !          8925:                 ctxt->flags = oldflags;
        !          8926:                 if (ret != 0) {
        !          8927:                     ctxt->state->value = temp;
        !          8928:                     if (ctxt->errNr > 0)
        !          8929:                         xmlRelaxNGPopErrors(ctxt, 0);
        !          8930:                     ret = 0;
        !          8931:                     break;
        !          8932:                 }
        !          8933:                if (ctxt->errNr > 0)
        !          8934:                    xmlRelaxNGPopErrors(ctxt, 0);
        !          8935:                 break;
        !          8936:             }
1.1       misho    8937:         case XML_RELAXNG_EXCEPT:{
                   8938:                 xmlRelaxNGDefinePtr list;
                   8939: 
                   8940:                 list = define->content;
                   8941:                 while (list != NULL) {
                   8942:                     ret = xmlRelaxNGValidateValue(ctxt, list);
                   8943:                     if (ret == 0) {
                   8944:                         ret = -1;
                   8945:                         break;
                   8946:                     } else
                   8947:                         ret = 0;
                   8948:                     list = list->next;
                   8949:                 }
                   8950:                 break;
                   8951:             }
                   8952:         case XML_RELAXNG_DEF:
                   8953:         case XML_RELAXNG_GROUP:{
                   8954:                 xmlRelaxNGDefinePtr list;
                   8955: 
                   8956:                 list = define->content;
                   8957:                 while (list != NULL) {
                   8958:                     ret = xmlRelaxNGValidateValue(ctxt, list);
                   8959:                     if (ret != 0) {
                   8960:                         ret = -1;
                   8961:                         break;
                   8962:                     } else
                   8963:                         ret = 0;
                   8964:                     list = list->next;
                   8965:                 }
                   8966:                 break;
                   8967:             }
                   8968:         case XML_RELAXNG_REF:
                   8969:         case XML_RELAXNG_PARENTREF:
                   8970:            if (define->content == NULL) {
                   8971:                 VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
                   8972:                 ret = -1;
                   8973:            } else {
                   8974:                 ret = xmlRelaxNGValidateValue(ctxt, define->content);
                   8975:             }
                   8976:             break;
                   8977:         default:
                   8978:             TODO ret = -1;
                   8979:     }
                   8980:     return (ret);
                   8981: }
                   8982: 
                   8983: /**
                   8984:  * xmlRelaxNGValidateValueContent:
                   8985:  * @ctxt:  a Relax-NG validation context
                   8986:  * @defines:  the list of definitions to verify
                   8987:  *
                   8988:  * Validate the given definitions for the current value
                   8989:  *
                   8990:  * Returns 0 if the validation succeeded or an error code.
                   8991:  */
                   8992: static int
                   8993: xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt,
                   8994:                                xmlRelaxNGDefinePtr defines)
                   8995: {
                   8996:     int ret = 0;
                   8997: 
                   8998:     while (defines != NULL) {
                   8999:         ret = xmlRelaxNGValidateValue(ctxt, defines);
                   9000:         if (ret != 0)
                   9001:             break;
                   9002:         defines = defines->next;
                   9003:     }
                   9004:     return (ret);
                   9005: }
                   9006: 
                   9007: /**
                   9008:  * xmlRelaxNGAttributeMatch:
                   9009:  * @ctxt:  a Relax-NG validation context
                   9010:  * @define:  the definition to check
                   9011:  * @prop:  the attribute
                   9012:  *
                   9013:  * Check if the attribute matches the definition nameClass
                   9014:  *
                   9015:  * Returns 1 if the attribute matches, 0 if no, or -1 in case of error
                   9016:  */
                   9017: static int
                   9018: xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt,
                   9019:                          xmlRelaxNGDefinePtr define, xmlAttrPtr prop)
                   9020: {
                   9021:     int ret;
                   9022: 
                   9023:     if (define->name != NULL) {
                   9024:         if (!xmlStrEqual(define->name, prop->name))
                   9025:             return (0);
                   9026:     }
                   9027:     if (define->ns != NULL) {
                   9028:         if (define->ns[0] == 0) {
                   9029:             if (prop->ns != NULL)
                   9030:                 return (0);
                   9031:         } else {
                   9032:             if ((prop->ns == NULL) ||
                   9033:                 (!xmlStrEqual(define->ns, prop->ns->href)))
                   9034:                 return (0);
                   9035:         }
                   9036:     }
                   9037:     if (define->nameClass == NULL)
                   9038:         return (1);
                   9039:     define = define->nameClass;
                   9040:     if (define->type == XML_RELAXNG_EXCEPT) {
                   9041:         xmlRelaxNGDefinePtr list;
                   9042: 
                   9043:         list = define->content;
                   9044:         while (list != NULL) {
                   9045:             ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);
                   9046:             if (ret == 1)
                   9047:                 return (0);
                   9048:             if (ret < 0)
                   9049:                 return (ret);
                   9050:             list = list->next;
                   9051:         }
                   9052:     } else {
                   9053:     TODO}
                   9054:     return (1);
                   9055: }
                   9056: 
                   9057: /**
                   9058:  * xmlRelaxNGValidateAttribute:
                   9059:  * @ctxt:  a Relax-NG validation context
                   9060:  * @define:  the definition to verify
                   9061:  *
                   9062:  * Validate the given attribute definition for that node
                   9063:  *
                   9064:  * Returns 0 if the validation succeeded or an error code.
                   9065:  */
                   9066: static int
                   9067: xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
                   9068:                             xmlRelaxNGDefinePtr define)
                   9069: {
                   9070:     int ret = 0, i;
                   9071:     xmlChar *value, *oldvalue;
                   9072:     xmlAttrPtr prop = NULL, tmp;
                   9073:     xmlNodePtr oldseq;
                   9074: 
                   9075:     if (ctxt->state->nbAttrLeft <= 0)
                   9076:         return (-1);
                   9077:     if (define->name != NULL) {
                   9078:         for (i = 0; i < ctxt->state->nbAttrs; i++) {
                   9079:             tmp = ctxt->state->attrs[i];
                   9080:             if ((tmp != NULL) && (xmlStrEqual(define->name, tmp->name))) {
                   9081:                 if ((((define->ns == NULL) || (define->ns[0] == 0)) &&
                   9082:                      (tmp->ns == NULL)) ||
                   9083:                     ((tmp->ns != NULL) &&
                   9084:                      (xmlStrEqual(define->ns, tmp->ns->href)))) {
                   9085:                     prop = tmp;
                   9086:                     break;
                   9087:                 }
                   9088:             }
                   9089:         }
                   9090:         if (prop != NULL) {
                   9091:             value = xmlNodeListGetString(prop->doc, prop->children, 1);
                   9092:             oldvalue = ctxt->state->value;
                   9093:             oldseq = ctxt->state->seq;
                   9094:             ctxt->state->seq = (xmlNodePtr) prop;
                   9095:             ctxt->state->value = value;
                   9096:             ctxt->state->endvalue = NULL;
                   9097:             ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
                   9098:             if (ctxt->state->value != NULL)
                   9099:                 value = ctxt->state->value;
                   9100:             if (value != NULL)
                   9101:                 xmlFree(value);
                   9102:             ctxt->state->value = oldvalue;
                   9103:             ctxt->state->seq = oldseq;
                   9104:             if (ret == 0) {
                   9105:                 /*
                   9106:                  * flag the attribute as processed
                   9107:                  */
                   9108:                 ctxt->state->attrs[i] = NULL;
                   9109:                 ctxt->state->nbAttrLeft--;
                   9110:             }
                   9111:         } else {
                   9112:             ret = -1;
                   9113:         }
                   9114: #ifdef DEBUG
                   9115:         xmlGenericError(xmlGenericErrorContext,
                   9116:                         "xmlRelaxNGValidateAttribute(%s): %d\n",
                   9117:                         define->name, ret);
                   9118: #endif
                   9119:     } else {
                   9120:         for (i = 0; i < ctxt->state->nbAttrs; i++) {
                   9121:             tmp = ctxt->state->attrs[i];
                   9122:             if ((tmp != NULL) &&
                   9123:                 (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) {
                   9124:                 prop = tmp;
                   9125:                 break;
                   9126:             }
                   9127:         }
                   9128:         if (prop != NULL) {
                   9129:             value = xmlNodeListGetString(prop->doc, prop->children, 1);
                   9130:             oldvalue = ctxt->state->value;
                   9131:             oldseq = ctxt->state->seq;
                   9132:             ctxt->state->seq = (xmlNodePtr) prop;
                   9133:             ctxt->state->value = value;
                   9134:             ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
                   9135:             if (ctxt->state->value != NULL)
                   9136:                 value = ctxt->state->value;
                   9137:             if (value != NULL)
                   9138:                 xmlFree(value);
                   9139:             ctxt->state->value = oldvalue;
                   9140:             ctxt->state->seq = oldseq;
                   9141:             if (ret == 0) {
                   9142:                 /*
                   9143:                  * flag the attribute as processed
                   9144:                  */
                   9145:                 ctxt->state->attrs[i] = NULL;
                   9146:                 ctxt->state->nbAttrLeft--;
                   9147:             }
                   9148:         } else {
                   9149:             ret = -1;
                   9150:         }
                   9151: #ifdef DEBUG
                   9152:         if (define->ns != NULL) {
                   9153:             xmlGenericError(xmlGenericErrorContext,
                   9154:                             "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",
                   9155:                             define->ns, ret);
                   9156:         } else {
                   9157:             xmlGenericError(xmlGenericErrorContext,
                   9158:                             "xmlRelaxNGValidateAttribute(anyName): %d\n",
                   9159:                             ret);
                   9160:         }
                   9161: #endif
                   9162:     }
                   9163: 
                   9164:     return (ret);
                   9165: }
                   9166: 
                   9167: /**
                   9168:  * xmlRelaxNGValidateAttributeList:
                   9169:  * @ctxt:  a Relax-NG validation context
                   9170:  * @define:  the list of definition to verify
                   9171:  *
                   9172:  * Validate the given node against the list of attribute definitions
                   9173:  *
                   9174:  * Returns 0 if the validation succeeded or an error code.
                   9175:  */
                   9176: static int
                   9177: xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
                   9178:                                 xmlRelaxNGDefinePtr defines)
                   9179: {
                   9180:     int ret = 0, res;
                   9181:     int needmore = 0;
                   9182:     xmlRelaxNGDefinePtr cur;
                   9183: 
                   9184:     cur = defines;
                   9185:     while (cur != NULL) {
                   9186:         if (cur->type == XML_RELAXNG_ATTRIBUTE) {
                   9187:             if (xmlRelaxNGValidateAttribute(ctxt, cur) != 0)
                   9188:                 ret = -1;
                   9189:         } else
                   9190:             needmore = 1;
                   9191:         cur = cur->next;
                   9192:     }
                   9193:     if (!needmore)
                   9194:         return (ret);
                   9195:     cur = defines;
                   9196:     while (cur != NULL) {
                   9197:         if (cur->type != XML_RELAXNG_ATTRIBUTE) {
                   9198:             if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
                   9199:                 res = xmlRelaxNGValidateDefinition(ctxt, cur);
                   9200:                 if (res < 0)
                   9201:                     ret = -1;
                   9202:             } else {
                   9203:                 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
                   9204:                 return (-1);
                   9205:             }
                   9206:             if (res == -1)      /* continues on -2 */
                   9207:                 break;
                   9208:         }
                   9209:         cur = cur->next;
                   9210:     }
                   9211: 
                   9212:     return (ret);
                   9213: }
                   9214: 
                   9215: /**
                   9216:  * xmlRelaxNGNodeMatchesList:
                   9217:  * @node:  the node
                   9218:  * @list:  a NULL terminated array of definitions
                   9219:  *
                   9220:  * Check if a node can be matched by one of the definitions
                   9221:  *
                   9222:  * Returns 1 if matches 0 otherwise
                   9223:  */
                   9224: static int
                   9225: xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr * list)
                   9226: {
                   9227:     xmlRelaxNGDefinePtr cur;
                   9228:     int i = 0, tmp;
                   9229: 
                   9230:     if ((node == NULL) || (list == NULL))
                   9231:         return (0);
                   9232: 
                   9233:     cur = list[i++];
                   9234:     while (cur != NULL) {
                   9235:         if ((node->type == XML_ELEMENT_NODE) &&
                   9236:             (cur->type == XML_RELAXNG_ELEMENT)) {
                   9237:             tmp = xmlRelaxNGElementMatch(NULL, cur, node);
                   9238:             if (tmp == 1)
                   9239:                 return (1);
                   9240:         } else if (((node->type == XML_TEXT_NODE) ||
                   9241:                     (node->type == XML_CDATA_SECTION_NODE)) &&
                   9242:                    (cur->type == XML_RELAXNG_TEXT)) {
                   9243:             return (1);
                   9244:         }
                   9245:         cur = list[i++];
                   9246:     }
                   9247:     return (0);
                   9248: }
                   9249: 
                   9250: /**
                   9251:  * xmlRelaxNGValidateInterleave:
                   9252:  * @ctxt:  a Relax-NG validation context
                   9253:  * @define:  the definition to verify
                   9254:  *
                   9255:  * Validate an interleave definition for a node.
                   9256:  *
                   9257:  * Returns 0 if the validation succeeded or an error code.
                   9258:  */
                   9259: static int
                   9260: xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt,
                   9261:                              xmlRelaxNGDefinePtr define)
                   9262: {
                   9263:     int ret = 0, i, nbgroups;
                   9264:     int errNr = ctxt->errNr;
                   9265:     int oldflags;
                   9266: 
                   9267:     xmlRelaxNGValidStatePtr oldstate;
                   9268:     xmlRelaxNGPartitionPtr partitions;
                   9269:     xmlRelaxNGInterleaveGroupPtr group = NULL;
                   9270:     xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem;
                   9271:     xmlNodePtr *list = NULL, *lasts = NULL;
                   9272: 
                   9273:     if (define->data != NULL) {
                   9274:         partitions = (xmlRelaxNGPartitionPtr) define->data;
                   9275:         nbgroups = partitions->nbgroups;
                   9276:     } else {
                   9277:         VALID_ERR(XML_RELAXNG_ERR_INTERNODATA);
                   9278:         return (-1);
                   9279:     }
                   9280:     /*
                   9281:      * Optimizations for MIXED
                   9282:      */
                   9283:     oldflags = ctxt->flags;
                   9284:     if (define->dflags & IS_MIXED) {
                   9285:         ctxt->flags |= FLAGS_MIXED_CONTENT;
                   9286:         if (nbgroups == 2) {
                   9287:             /*
                   9288:              * this is a pure <mixed> case
                   9289:              */
                   9290:             if (ctxt->state != NULL)
                   9291:                 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
                   9292:                                                          ctxt->state->seq);
                   9293:             if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT)
                   9294:                 ret = xmlRelaxNGValidateDefinition(ctxt,
                   9295:                                                    partitions->groups[1]->
                   9296:                                                    rule);
                   9297:             else
                   9298:                 ret = xmlRelaxNGValidateDefinition(ctxt,
                   9299:                                                    partitions->groups[0]->
                   9300:                                                    rule);
                   9301:             if (ret == 0) {
                   9302:                 if (ctxt->state != NULL)
                   9303:                     ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
                   9304:                                                              ctxt->state->
                   9305:                                                              seq);
                   9306:             }
                   9307:             ctxt->flags = oldflags;
                   9308:             return (ret);
                   9309:         }
                   9310:     }
                   9311: 
                   9312:     /*
                   9313:      * Build arrays to store the first and last node of the chain
                   9314:      * pertaining to each group
                   9315:      */
                   9316:     list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
                   9317:     if (list == NULL) {
                   9318:         xmlRngVErrMemory(ctxt, "validating\n");
                   9319:         return (-1);
                   9320:     }
                   9321:     memset(list, 0, nbgroups * sizeof(xmlNodePtr));
                   9322:     lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
                   9323:     if (lasts == NULL) {
                   9324:         xmlRngVErrMemory(ctxt, "validating\n");
                   9325:         return (-1);
                   9326:     }
                   9327:     memset(lasts, 0, nbgroups * sizeof(xmlNodePtr));
                   9328: 
                   9329:     /*
                   9330:      * Walk the sequence of children finding the right group and
                   9331:      * sorting them in sequences.
                   9332:      */
                   9333:     cur = ctxt->state->seq;
                   9334:     cur = xmlRelaxNGSkipIgnored(ctxt, cur);
                   9335:     start = cur;
                   9336:     while (cur != NULL) {
                   9337:         ctxt->state->seq = cur;
                   9338:         if ((partitions->triage != NULL) &&
                   9339:             (partitions->flags & IS_DETERMINIST)) {
                   9340:             void *tmp = NULL;
                   9341: 
                   9342:             if ((cur->type == XML_TEXT_NODE) ||
                   9343:                 (cur->type == XML_CDATA_SECTION_NODE)) {
                   9344:                 tmp = xmlHashLookup2(partitions->triage, BAD_CAST "#text",
                   9345:                                      NULL);
                   9346:             } else if (cur->type == XML_ELEMENT_NODE) {
                   9347:                 if (cur->ns != NULL) {
                   9348:                     tmp = xmlHashLookup2(partitions->triage, cur->name,
                   9349:                                          cur->ns->href);
                   9350:                     if (tmp == NULL)
                   9351:                         tmp = xmlHashLookup2(partitions->triage,
                   9352:                                              BAD_CAST "#any",
                   9353:                                              cur->ns->href);
                   9354:                 } else
                   9355:                     tmp =
                   9356:                         xmlHashLookup2(partitions->triage, cur->name,
                   9357:                                        NULL);
                   9358:                 if (tmp == NULL)
                   9359:                     tmp =
                   9360:                         xmlHashLookup2(partitions->triage, BAD_CAST "#any",
                   9361:                                        NULL);
                   9362:             }
                   9363: 
                   9364:             if (tmp == NULL) {
                   9365:                 i = nbgroups;
                   9366:             } else {
                   9367:                 i = ((long) tmp) - 1;
                   9368:                 if (partitions->flags & IS_NEEDCHECK) {
                   9369:                     group = partitions->groups[i];
                   9370:                     if (!xmlRelaxNGNodeMatchesList(cur, group->defs))
                   9371:                         i = nbgroups;
                   9372:                 }
                   9373:             }
                   9374:         } else {
                   9375:             for (i = 0; i < nbgroups; i++) {
                   9376:                 group = partitions->groups[i];
                   9377:                 if (group == NULL)
                   9378:                     continue;
                   9379:                 if (xmlRelaxNGNodeMatchesList(cur, group->defs))
                   9380:                     break;
                   9381:             }
                   9382:         }
                   9383:         /*
                   9384:          * We break as soon as an element not matched is found
                   9385:          */
                   9386:         if (i >= nbgroups) {
                   9387:             break;
                   9388:         }
                   9389:         if (lasts[i] != NULL) {
                   9390:             lasts[i]->next = cur;
                   9391:             lasts[i] = cur;
                   9392:         } else {
                   9393:             list[i] = cur;
                   9394:             lasts[i] = cur;
                   9395:         }
                   9396:         if (cur->next != NULL)
                   9397:             lastchg = cur->next;
                   9398:         else
                   9399:             lastchg = cur;
                   9400:         cur = xmlRelaxNGSkipIgnored(ctxt, cur->next);
                   9401:     }
                   9402:     if (ret != 0) {
                   9403:         VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
                   9404:         ret = -1;
                   9405:         goto done;
                   9406:     }
                   9407:     lastelem = cur;
                   9408:     oldstate = ctxt->state;
                   9409:     for (i = 0; i < nbgroups; i++) {
                   9410:         ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate);
                   9411:         group = partitions->groups[i];
                   9412:         if (lasts[i] != NULL) {
                   9413:             last = lasts[i]->next;
                   9414:             lasts[i]->next = NULL;
                   9415:         }
                   9416:         ctxt->state->seq = list[i];
                   9417:         ret = xmlRelaxNGValidateDefinition(ctxt, group->rule);
                   9418:         if (ret != 0)
                   9419:             break;
                   9420:         if (ctxt->state != NULL) {
                   9421:             cur = ctxt->state->seq;
                   9422:             cur = xmlRelaxNGSkipIgnored(ctxt, cur);
                   9423:             xmlRelaxNGFreeValidState(ctxt, oldstate);
                   9424:             oldstate = ctxt->state;
                   9425:             ctxt->state = NULL;
                   9426:             if (cur != NULL) {
                   9427:                 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
                   9428:                 ret = -1;
                   9429:                 ctxt->state = oldstate;
                   9430:                 goto done;
                   9431:             }
                   9432:         } else if (ctxt->states != NULL) {
                   9433:             int j;
                   9434:             int found = 0;
                   9435:            int best = -1;
                   9436:            int lowattr = -1;
                   9437: 
                   9438:            /*
                   9439:             * PBM: what happen if there is attributes checks in the interleaves
                   9440:             */
                   9441: 
                   9442:             for (j = 0; j < ctxt->states->nbState; j++) {
                   9443:                 cur = ctxt->states->tabState[j]->seq;
                   9444:                 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
                   9445:                 if (cur == NULL) {
                   9446:                    if (found == 0) {
                   9447:                        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
                   9448:                        best = j;
                   9449:                    }
                   9450:                     found = 1;
                   9451:                    if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) {
                   9452:                        /* try  to keep the latest one to mach old heuristic */
                   9453:                        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
                   9454:                        best = j;
                   9455:                    }
                   9456:                     if (lowattr == 0)
                   9457:                        break;
                   9458:                 } else if (found == 0) {
                   9459:                     if (lowattr == -1) {
                   9460:                        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
                   9461:                        best = j;
                   9462:                    } else
                   9463:                    if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr)  {
                   9464:                        /* try  to keep the latest one to mach old heuristic */
                   9465:                        lowattr = ctxt->states->tabState[j]->nbAttrLeft;
                   9466:                        best = j;
                   9467:                    }
                   9468:                }
                   9469:             }
                   9470:            /*
                   9471:             * BIG PBM: here we pick only one restarting point :-(
                   9472:             */
                   9473:             if (ctxt->states->nbState > 0) {
                   9474:                 xmlRelaxNGFreeValidState(ctxt, oldstate);
                   9475:                if (best != -1) {
                   9476:                    oldstate = ctxt->states->tabState[best];
                   9477:                    ctxt->states->tabState[best] = NULL;
                   9478:                } else {
                   9479:                    oldstate =
                   9480:                        ctxt->states->tabState[ctxt->states->nbState - 1];
                   9481:                     ctxt->states->tabState[ctxt->states->nbState - 1] = NULL;
                   9482:                     ctxt->states->nbState--;
                   9483:                }
                   9484:             }
                   9485:             for (j = 0; j < ctxt->states->nbState ; j++) {
                   9486:                 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[j]);
                   9487:             }
                   9488:             xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   9489:             ctxt->states = NULL;
                   9490:             if (found == 0) {
                   9491:                 if (cur == NULL) {
                   9492:                    VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA,
                   9493:                               (const xmlChar *) "noname");
                   9494:                 } else {
                   9495:                     VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
                   9496:                 }
                   9497:                 ret = -1;
                   9498:                 ctxt->state = oldstate;
                   9499:                 goto done;
                   9500:             }
                   9501:         } else {
                   9502:             ret = -1;
                   9503:             break;
                   9504:         }
                   9505:         if (lasts[i] != NULL) {
                   9506:             lasts[i]->next = last;
                   9507:         }
                   9508:     }
                   9509:     if (ctxt->state != NULL)
                   9510:         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   9511:     ctxt->state = oldstate;
                   9512:     ctxt->state->seq = lastelem;
                   9513:     if (ret != 0) {
                   9514:         VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
                   9515:         ret = -1;
                   9516:         goto done;
                   9517:     }
                   9518: 
                   9519:   done:
                   9520:     ctxt->flags = oldflags;
                   9521:     /*
                   9522:      * builds the next links chain from the prev one
                   9523:      */
                   9524:     cur = lastchg;
                   9525:     while (cur != NULL) {
                   9526:         if ((cur == start) || (cur->prev == NULL))
                   9527:             break;
                   9528:         cur->prev->next = cur;
                   9529:         cur = cur->prev;
                   9530:     }
                   9531:     if (ret == 0) {
                   9532:         if (ctxt->errNr > errNr)
                   9533:             xmlRelaxNGPopErrors(ctxt, errNr);
                   9534:     }
                   9535: 
                   9536:     xmlFree(list);
                   9537:     xmlFree(lasts);
                   9538:     return (ret);
                   9539: }
                   9540: 
                   9541: /**
                   9542:  * xmlRelaxNGValidateDefinitionList:
                   9543:  * @ctxt:  a Relax-NG validation context
                   9544:  * @define:  the list of definition to verify
                   9545:  *
                   9546:  * Validate the given node content against the (list) of definitions
                   9547:  *
                   9548:  * Returns 0 if the validation succeeded or an error code.
                   9549:  */
                   9550: static int
                   9551: xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt,
                   9552:                                  xmlRelaxNGDefinePtr defines)
                   9553: {
                   9554:     int ret = 0, res;
                   9555: 
                   9556: 
                   9557:     if (defines == NULL) {
                   9558:         VALID_ERR2(XML_RELAXNG_ERR_INTERNAL,
                   9559:                    BAD_CAST "NULL definition list");
                   9560:         return (-1);
                   9561:     }
                   9562:     while (defines != NULL) {
                   9563:         if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
                   9564:             res = xmlRelaxNGValidateDefinition(ctxt, defines);
                   9565:             if (res < 0)
                   9566:                 ret = -1;
                   9567:         } else {
                   9568:             VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
                   9569:             return (-1);
                   9570:         }
                   9571:         if (res == -1)          /* continues on -2 */
                   9572:             break;
                   9573:         defines = defines->next;
                   9574:     }
                   9575: 
                   9576:     return (ret);
                   9577: }
                   9578: 
                   9579: /**
                   9580:  * xmlRelaxNGElementMatch:
                   9581:  * @ctxt:  a Relax-NG validation context
                   9582:  * @define:  the definition to check
                   9583:  * @elem:  the element
                   9584:  *
                   9585:  * Check if the element matches the definition nameClass
                   9586:  *
                   9587:  * Returns 1 if the element matches, 0 if no, or -1 in case of error
                   9588:  */
                   9589: static int
                   9590: xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
                   9591:                        xmlRelaxNGDefinePtr define, xmlNodePtr elem)
                   9592: {
                   9593:     int ret = 0, oldflags = 0;
                   9594: 
                   9595:     if (define->name != NULL) {
                   9596:         if (!xmlStrEqual(elem->name, define->name)) {
                   9597:             VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name);
                   9598:             return (0);
                   9599:         }
                   9600:     }
                   9601:     if ((define->ns != NULL) && (define->ns[0] != 0)) {
                   9602:         if (elem->ns == NULL) {
                   9603:             VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name);
                   9604:             return (0);
                   9605:         } else if (!xmlStrEqual(elem->ns->href, define->ns)) {
                   9606:             VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS,
                   9607:                        elem->name, define->ns);
                   9608:             return (0);
                   9609:         }
                   9610:     } else if ((elem->ns != NULL) && (define->ns != NULL) &&
                   9611:                (define->name == NULL)) {
                   9612:         VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name);
                   9613:         return (0);
                   9614:     } else if ((elem->ns != NULL) && (define->name != NULL)) {
                   9615:         VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name);
                   9616:         return (0);
                   9617:     }
                   9618: 
                   9619:     if (define->nameClass == NULL)
                   9620:         return (1);
                   9621: 
                   9622:     define = define->nameClass;
                   9623:     if (define->type == XML_RELAXNG_EXCEPT) {
                   9624:         xmlRelaxNGDefinePtr list;
                   9625: 
                   9626:         if (ctxt != NULL) {
                   9627:             oldflags = ctxt->flags;
                   9628:             ctxt->flags |= FLAGS_IGNORABLE;
                   9629:         }
                   9630: 
                   9631:         list = define->content;
                   9632:         while (list != NULL) {
                   9633:             ret = xmlRelaxNGElementMatch(ctxt, list, elem);
                   9634:             if (ret == 1) {
                   9635:                 if (ctxt != NULL)
                   9636:                     ctxt->flags = oldflags;
                   9637:                 return (0);
                   9638:             }
                   9639:             if (ret < 0) {
                   9640:                 if (ctxt != NULL)
                   9641:                     ctxt->flags = oldflags;
                   9642:                 return (ret);
                   9643:             }
                   9644:             list = list->next;
                   9645:         }
                   9646:         ret = 1;
                   9647:         if (ctxt != NULL) {
                   9648:             ctxt->flags = oldflags;
                   9649:         }
                   9650:     } else if (define->type == XML_RELAXNG_CHOICE) {
                   9651:         xmlRelaxNGDefinePtr list;
                   9652: 
                   9653:         if (ctxt != NULL) {
                   9654:             oldflags = ctxt->flags;
                   9655:             ctxt->flags |= FLAGS_IGNORABLE;
                   9656:         }
                   9657: 
                   9658:         list = define->nameClass;
                   9659:         while (list != NULL) {
                   9660:             ret = xmlRelaxNGElementMatch(ctxt, list, elem);
                   9661:             if (ret == 1) {
                   9662:                 if (ctxt != NULL)
                   9663:                     ctxt->flags = oldflags;
                   9664:                 return (1);
                   9665:             }
                   9666:             if (ret < 0) {
                   9667:                 if (ctxt != NULL)
                   9668:                     ctxt->flags = oldflags;
                   9669:                 return (ret);
                   9670:             }
                   9671:             list = list->next;
                   9672:         }
                   9673:         if (ctxt != NULL) {
                   9674:             if (ret != 0) {
                   9675:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
                   9676:                     xmlRelaxNGDumpValidError(ctxt);
                   9677:             } else {
                   9678:                 if (ctxt->errNr > 0)
                   9679:                     xmlRelaxNGPopErrors(ctxt, 0);
                   9680:             }
                   9681:         }
                   9682:         ret = 0;
                   9683:         if (ctxt != NULL) {
                   9684:             ctxt->flags = oldflags;
                   9685:         }
                   9686:     } else {
                   9687:         TODO ret = -1;
                   9688:     }
                   9689:     return (ret);
                   9690: }
                   9691: 
                   9692: /**
                   9693:  * xmlRelaxNGBestState:
                   9694:  * @ctxt:  a Relax-NG validation context
                   9695:  *
                   9696:  * Find the "best" state in the ctxt->states list of states to report
                   9697:  * errors about. I.e. a state with no element left in the child list
                   9698:  * or the one with the less attributes left.
                   9699:  * This is called only if a falidation error was detected
                   9700:  *
                   9701:  * Returns the index of the "best" state or -1 in case of error
                   9702:  */
                   9703: static int
                   9704: xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt)
                   9705: {
                   9706:     xmlRelaxNGValidStatePtr state;
                   9707:     int i, tmp;
                   9708:     int best = -1;
                   9709:     int value = 1000000;
                   9710: 
                   9711:     if ((ctxt == NULL) || (ctxt->states == NULL) ||
                   9712:         (ctxt->states->nbState <= 0))
                   9713:         return (-1);
                   9714: 
                   9715:     for (i = 0; i < ctxt->states->nbState; i++) {
                   9716:         state = ctxt->states->tabState[i];
                   9717:         if (state == NULL)
                   9718:             continue;
                   9719:         if (state->seq != NULL) {
                   9720:             if ((best == -1) || (value > 100000)) {
                   9721:                 value = 100000;
                   9722:                 best = i;
                   9723:             }
                   9724:         } else {
                   9725:             tmp = state->nbAttrLeft;
                   9726:             if ((best == -1) || (value > tmp)) {
                   9727:                 value = tmp;
                   9728:                 best = i;
                   9729:             }
                   9730:         }
                   9731:     }
                   9732:     return (best);
                   9733: }
                   9734: 
                   9735: /**
                   9736:  * xmlRelaxNGLogBestError:
                   9737:  * @ctxt:  a Relax-NG validation context
                   9738:  *
                   9739:  * Find the "best" state in the ctxt->states list of states to report
                   9740:  * errors about and log it.
                   9741:  */
                   9742: static void
                   9743: xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt)
                   9744: {
                   9745:     int best;
                   9746: 
                   9747:     if ((ctxt == NULL) || (ctxt->states == NULL) ||
                   9748:         (ctxt->states->nbState <= 0))
                   9749:         return;
                   9750: 
                   9751:     best = xmlRelaxNGBestState(ctxt);
                   9752:     if ((best >= 0) && (best < ctxt->states->nbState)) {
                   9753:         ctxt->state = ctxt->states->tabState[best];
                   9754: 
                   9755:         xmlRelaxNGValidateElementEnd(ctxt, 1);
                   9756:     }
                   9757: }
                   9758: 
                   9759: /**
                   9760:  * xmlRelaxNGValidateElementEnd:
                   9761:  * @ctxt:  a Relax-NG validation context
                   9762:  * @dolog:  indicate that error logging should be done
                   9763:  *
                   9764:  * Validate the end of the element, implements check that
                   9765:  * there is nothing left not consumed in the element content
                   9766:  * or in the attribute list.
                   9767:  *
                   9768:  * Returns 0 if the validation succeeded or an error code.
                   9769:  */
                   9770: static int
                   9771: xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int dolog)
                   9772: {
                   9773:     int i;
                   9774:     xmlRelaxNGValidStatePtr state;
                   9775: 
                   9776:     state = ctxt->state;
                   9777:     if (state->seq != NULL) {
                   9778:         state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq);
                   9779:         if (state->seq != NULL) {
                   9780:             if (dolog) {
                   9781:                 VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT,
                   9782:                            state->node->name, state->seq->name);
                   9783:             }
                   9784:             return (-1);
                   9785:         }
                   9786:     }
                   9787:     for (i = 0; i < state->nbAttrs; i++) {
                   9788:         if (state->attrs[i] != NULL) {
                   9789:             if (dolog) {
                   9790:                 VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR,
                   9791:                            state->attrs[i]->name, state->node->name);
                   9792:             }
                   9793:             return (-1 - i);
                   9794:         }
                   9795:     }
                   9796:     return (0);
                   9797: }
                   9798: 
                   9799: /**
                   9800:  * xmlRelaxNGValidateState:
                   9801:  * @ctxt:  a Relax-NG validation context
                   9802:  * @define:  the definition to verify
                   9803:  *
                   9804:  * Validate the current state against the definition
                   9805:  *
                   9806:  * Returns 0 if the validation succeeded or an error code.
                   9807:  */
                   9808: static int
                   9809: xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
                   9810:                         xmlRelaxNGDefinePtr define)
                   9811: {
                   9812:     xmlNodePtr node;
                   9813:     int ret = 0, i, tmp, oldflags, errNr;
                   9814:     xmlRelaxNGValidStatePtr oldstate = NULL, state;
                   9815: 
                   9816:     if (define == NULL) {
                   9817:         VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
                   9818:         return (-1);
                   9819:     }
                   9820: 
                   9821:     if (ctxt->state != NULL) {
                   9822:         node = ctxt->state->seq;
                   9823:     } else {
                   9824:         node = NULL;
                   9825:     }
                   9826: #ifdef DEBUG
                   9827:     for (i = 0; i < ctxt->depth; i++)
                   9828:         xmlGenericError(xmlGenericErrorContext, " ");
                   9829:     xmlGenericError(xmlGenericErrorContext,
                   9830:                     "Start validating %s ", xmlRelaxNGDefName(define));
                   9831:     if (define->name != NULL)
                   9832:         xmlGenericError(xmlGenericErrorContext, "%s ", define->name);
                   9833:     if ((node != NULL) && (node->name != NULL))
                   9834:         xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name);
                   9835:     else
                   9836:         xmlGenericError(xmlGenericErrorContext, "\n");
                   9837: #endif
                   9838:     ctxt->depth++;
                   9839:     switch (define->type) {
                   9840:         case XML_RELAXNG_EMPTY:
                   9841:             node = xmlRelaxNGSkipIgnored(ctxt, node);
                   9842:             ret = 0;
                   9843:             break;
                   9844:         case XML_RELAXNG_NOT_ALLOWED:
                   9845:             ret = -1;
                   9846:             break;
                   9847:         case XML_RELAXNG_TEXT:
                   9848:             while ((node != NULL) &&
                   9849:                    ((node->type == XML_TEXT_NODE) ||
                   9850:                     (node->type == XML_COMMENT_NODE) ||
                   9851:                     (node->type == XML_PI_NODE) ||
                   9852:                     (node->type == XML_CDATA_SECTION_NODE)))
                   9853:                 node = node->next;
                   9854:             ctxt->state->seq = node;
                   9855:             break;
                   9856:         case XML_RELAXNG_ELEMENT:
                   9857:             errNr = ctxt->errNr;
                   9858:             node = xmlRelaxNGSkipIgnored(ctxt, node);
                   9859:             if (node == NULL) {
                   9860:                 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name);
                   9861:                 ret = -1;
                   9862:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
                   9863:                     xmlRelaxNGDumpValidError(ctxt);
                   9864:                 break;
                   9865:             }
                   9866:             if (node->type != XML_ELEMENT_NODE) {
                   9867:                 VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
                   9868:                 ret = -1;
                   9869:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
                   9870:                     xmlRelaxNGDumpValidError(ctxt);
                   9871:                 break;
                   9872:             }
                   9873:             /*
                   9874:              * This node was already validated successfully against
                   9875:              * this definition.
                   9876:              */
                   9877:             if (node->psvi == define) {
                   9878:                 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
                   9879:                 if (ctxt->errNr > errNr)
                   9880:                     xmlRelaxNGPopErrors(ctxt, errNr);
                   9881:                 if (ctxt->errNr != 0) {
                   9882:                     while ((ctxt->err != NULL) &&
                   9883:                            (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME)
                   9884:                              && (xmlStrEqual(ctxt->err->arg2, node->name)))
                   9885:                             ||
                   9886:                             ((ctxt->err->err ==
                   9887:                               XML_RELAXNG_ERR_ELEMEXTRANS)
                   9888:                              && (xmlStrEqual(ctxt->err->arg1, node->name)))
                   9889:                             || (ctxt->err->err == XML_RELAXNG_ERR_NOELEM)
                   9890:                             || (ctxt->err->err ==
                   9891:                                 XML_RELAXNG_ERR_NOTELEM)))
                   9892:                         xmlRelaxNGValidErrorPop(ctxt);
                   9893:                 }
                   9894:                 break;
                   9895:             }
                   9896: 
                   9897:             ret = xmlRelaxNGElementMatch(ctxt, define, node);
                   9898:             if (ret <= 0) {
                   9899:                 ret = -1;
                   9900:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
                   9901:                     xmlRelaxNGDumpValidError(ctxt);
                   9902:                 break;
                   9903:             }
                   9904:             ret = 0;
                   9905:             if (ctxt->errNr != 0) {
                   9906:                 if (ctxt->errNr > errNr)
                   9907:                     xmlRelaxNGPopErrors(ctxt, errNr);
                   9908:                 while ((ctxt->err != NULL) &&
                   9909:                        (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) &&
                   9910:                          (xmlStrEqual(ctxt->err->arg2, node->name))) ||
                   9911:                         ((ctxt->err->err == XML_RELAXNG_ERR_ELEMEXTRANS) &&
                   9912:                          (xmlStrEqual(ctxt->err->arg1, node->name))) ||
                   9913:                         (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) ||
                   9914:                         (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM)))
                   9915:                     xmlRelaxNGValidErrorPop(ctxt);
                   9916:             }
                   9917:             errNr = ctxt->errNr;
                   9918: 
                   9919:             oldflags = ctxt->flags;
                   9920:             if (ctxt->flags & FLAGS_MIXED_CONTENT) {
                   9921:                 ctxt->flags -= FLAGS_MIXED_CONTENT;
                   9922:             }
                   9923:             state = xmlRelaxNGNewValidState(ctxt, node);
                   9924:             if (state == NULL) {
                   9925:                 ret = -1;
                   9926:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
                   9927:                     xmlRelaxNGDumpValidError(ctxt);
                   9928:                 break;
                   9929:             }
                   9930: 
                   9931:             oldstate = ctxt->state;
                   9932:             ctxt->state = state;
                   9933:             if (define->attrs != NULL) {
                   9934:                 tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
                   9935:                 if (tmp != 0) {
                   9936:                     ret = -1;
                   9937:                     VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
                   9938:                 }
                   9939:             }
                   9940:             if (define->contModel != NULL) {
                   9941:                 xmlRelaxNGValidStatePtr nstate, tmpstate = ctxt->state;
                   9942:                 xmlRelaxNGStatesPtr tmpstates = ctxt->states;
                   9943:                 xmlNodePtr nseq;
                   9944: 
                   9945:                 nstate = xmlRelaxNGNewValidState(ctxt, node);
                   9946:                 ctxt->state = nstate;
                   9947:                 ctxt->states = NULL;
                   9948: 
                   9949:                 tmp = xmlRelaxNGValidateCompiledContent(ctxt,
                   9950:                                                         define->contModel,
                   9951:                                                         ctxt->state->seq);
                   9952:                 nseq = ctxt->state->seq;
                   9953:                 ctxt->state = tmpstate;
                   9954:                 ctxt->states = tmpstates;
                   9955:                 xmlRelaxNGFreeValidState(ctxt, nstate);
                   9956: 
                   9957: #ifdef DEBUG_COMPILE
                   9958:                 xmlGenericError(xmlGenericErrorContext,
                   9959:                                 "Validating content of '%s' : %d\n",
                   9960:                                 define->name, tmp);
                   9961: #endif
                   9962:                 if (tmp != 0)
                   9963:                     ret = -1;
                   9964: 
                   9965:                 if (ctxt->states != NULL) {
                   9966:                     tmp = -1;
                   9967: 
                   9968:                     for (i = 0; i < ctxt->states->nbState; i++) {
                   9969:                         state = ctxt->states->tabState[i];
                   9970:                         ctxt->state = state;
                   9971:                         ctxt->state->seq = nseq;
                   9972: 
                   9973:                         if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
                   9974:                             tmp = 0;
                   9975:                             break;
                   9976:                         }
                   9977:                     }
                   9978:                     if (tmp != 0) {
                   9979:                         /*
                   9980:                          * validation error, log the message for the "best" one
                   9981:                          */
                   9982:                         ctxt->flags |= FLAGS_IGNORABLE;
                   9983:                         xmlRelaxNGLogBestError(ctxt);
                   9984:                     }
                   9985:                     for (i = 0; i < ctxt->states->nbState; i++) {
                   9986:                         xmlRelaxNGFreeValidState(ctxt,
                   9987:                                                  ctxt->states->
                   9988:                                                  tabState[i]);
                   9989:                     }
                   9990:                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   9991:                     ctxt->flags = oldflags;
                   9992:                     ctxt->states = NULL;
                   9993:                     if ((ret == 0) && (tmp == -1))
                   9994:                         ret = -1;
                   9995:                 } else {
                   9996:                     state = ctxt->state;
                   9997:                    if (ctxt->state != NULL)
                   9998:                        ctxt->state->seq = nseq;
                   9999:                     if (ret == 0)
                   10000:                         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
                   10001:                     xmlRelaxNGFreeValidState(ctxt, state);
                   10002:                 }
                   10003:             } else {
                   10004:                 if (define->content != NULL) {
                   10005:                     tmp = xmlRelaxNGValidateDefinitionList(ctxt,
                   10006:                                                            define->
                   10007:                                                            content);
                   10008:                     if (tmp != 0) {
                   10009:                         ret = -1;
                   10010:                         if (ctxt->state == NULL) {
                   10011:                             ctxt->state = oldstate;
                   10012:                             VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
                   10013:                                        node->name);
                   10014:                             ctxt->state = NULL;
                   10015:                         } else {
                   10016:                             VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
                   10017:                                        node->name);
                   10018:                         }
                   10019: 
                   10020:                     }
                   10021:                 }
                   10022:                 if (ctxt->states != NULL) {
                   10023:                     tmp = -1;
                   10024: 
                   10025:                     for (i = 0; i < ctxt->states->nbState; i++) {
                   10026:                         state = ctxt->states->tabState[i];
                   10027:                         ctxt->state = state;
                   10028: 
                   10029:                         if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
                   10030:                             tmp = 0;
                   10031:                             break;
                   10032:                         }
                   10033:                     }
                   10034:                     if (tmp != 0) {
                   10035:                         /*
                   10036:                          * validation error, log the message for the "best" one
                   10037:                          */
                   10038:                         ctxt->flags |= FLAGS_IGNORABLE;
                   10039:                         xmlRelaxNGLogBestError(ctxt);
                   10040:                     }
                   10041:                     for (i = 0; i < ctxt->states->nbState; i++) {
                   10042:                         xmlRelaxNGFreeValidState(ctxt,
                   10043:                                                  ctxt->states->tabState[i]);
                   10044:                         ctxt->states->tabState[i] = NULL;
                   10045:                     }
                   10046:                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   10047:                     ctxt->flags = oldflags;
                   10048:                     ctxt->states = NULL;
                   10049:                     if ((ret == 0) && (tmp == -1))
                   10050:                         ret = -1;
                   10051:                 } else {
                   10052:                     state = ctxt->state;
                   10053:                     if (ret == 0)
                   10054:                         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
                   10055:                     xmlRelaxNGFreeValidState(ctxt, state);
                   10056:                 }
                   10057:             }
                   10058:             if (ret == 0) {
                   10059:                 node->psvi = define;
                   10060:             }
                   10061:             ctxt->flags = oldflags;
                   10062:             ctxt->state = oldstate;
                   10063:             if (oldstate != NULL)
                   10064:                 oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
                   10065:             if (ret != 0) {
                   10066:                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
                   10067:                     xmlRelaxNGDumpValidError(ctxt);
                   10068:                     ret = 0;
                   10069: #if 0
                   10070:                 } else {
                   10071:                     ret = -2;
                   10072: #endif
                   10073:                 }
                   10074:             } else {
                   10075:                 if (ctxt->errNr > errNr)
                   10076:                     xmlRelaxNGPopErrors(ctxt, errNr);
                   10077:             }
                   10078: 
                   10079: #ifdef DEBUG
                   10080:             xmlGenericError(xmlGenericErrorContext,
                   10081:                             "xmlRelaxNGValidateDefinition(): validated %s : %d",
                   10082:                             node->name, ret);
                   10083:             if (oldstate == NULL)
                   10084:                 xmlGenericError(xmlGenericErrorContext, ": no state\n");
                   10085:             else if (oldstate->seq == NULL)
                   10086:                 xmlGenericError(xmlGenericErrorContext, ": done\n");
                   10087:             else if (oldstate->seq->type == XML_ELEMENT_NODE)
                   10088:                 xmlGenericError(xmlGenericErrorContext, ": next elem %s\n",
                   10089:                                 oldstate->seq->name);
                   10090:             else
                   10091:                 xmlGenericError(xmlGenericErrorContext, ": next %s %d\n",
                   10092:                                 oldstate->seq->name, oldstate->seq->type);
                   10093: #endif
                   10094:             break;
                   10095:         case XML_RELAXNG_OPTIONAL:{
                   10096:                 errNr = ctxt->errNr;
                   10097:                 oldflags = ctxt->flags;
                   10098:                 ctxt->flags |= FLAGS_IGNORABLE;
                   10099:                 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
                   10100:                 ret =
                   10101:                     xmlRelaxNGValidateDefinitionList(ctxt,
                   10102:                                                      define->content);
                   10103:                 if (ret != 0) {
                   10104:                     if (ctxt->state != NULL)
                   10105:                         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10106:                     ctxt->state = oldstate;
                   10107:                     ctxt->flags = oldflags;
                   10108:                     ret = 0;
                   10109:                     if (ctxt->errNr > errNr)
                   10110:                         xmlRelaxNGPopErrors(ctxt, errNr);
                   10111:                     break;
                   10112:                 }
                   10113:                 if (ctxt->states != NULL) {
                   10114:                     xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
                   10115:                 } else {
                   10116:                     ctxt->states = xmlRelaxNGNewStates(ctxt, 1);
                   10117:                     if (ctxt->states == NULL) {
                   10118:                         xmlRelaxNGFreeValidState(ctxt, oldstate);
                   10119:                         ctxt->flags = oldflags;
                   10120:                         ret = -1;
                   10121:                         if (ctxt->errNr > errNr)
                   10122:                             xmlRelaxNGPopErrors(ctxt, errNr);
                   10123:                         break;
                   10124:                     }
                   10125:                     xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
                   10126:                     xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state);
                   10127:                     ctxt->state = NULL;
                   10128:                 }
                   10129:                 ctxt->flags = oldflags;
                   10130:                 ret = 0;
                   10131:                 if (ctxt->errNr > errNr)
                   10132:                     xmlRelaxNGPopErrors(ctxt, errNr);
                   10133:                 break;
                   10134:             }
                   10135:         case XML_RELAXNG_ONEORMORE:
                   10136:             errNr = ctxt->errNr;
                   10137:             ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
                   10138:             if (ret != 0) {
                   10139:                 break;
                   10140:             }
                   10141:             if (ctxt->errNr > errNr)
                   10142:                 xmlRelaxNGPopErrors(ctxt, errNr);
                   10143:             /* no break on purpose */
                   10144:         case XML_RELAXNG_ZEROORMORE:{
                   10145:                 int progress;
                   10146:                 xmlRelaxNGStatesPtr states = NULL, res = NULL;
                   10147:                 int base, j;
                   10148: 
                   10149:                 errNr = ctxt->errNr;
                   10150:                 res = xmlRelaxNGNewStates(ctxt, 1);
                   10151:                 if (res == NULL) {
                   10152:                     ret = -1;
                   10153:                     break;
                   10154:                 }
                   10155:                 /*
                   10156:                  * All the input states are also exit states
                   10157:                  */
                   10158:                 if (ctxt->state != NULL) {
                   10159:                     xmlRelaxNGAddStates(ctxt, res,
                   10160:                                         xmlRelaxNGCopyValidState(ctxt,
                   10161:                                                                  ctxt->
                   10162:                                                                  state));
                   10163:                 } else {
                   10164:                     for (j = 0; j < ctxt->states->nbState; j++) {
                   10165:                         xmlRelaxNGAddStates(ctxt, res,
                   10166:                             xmlRelaxNGCopyValidState(ctxt,
                   10167:                                             ctxt->states->tabState[j]));
                   10168:                     }
                   10169:                 }
                   10170:                 oldflags = ctxt->flags;
                   10171:                 ctxt->flags |= FLAGS_IGNORABLE;
                   10172:                 do {
                   10173:                     progress = 0;
                   10174:                     base = res->nbState;
                   10175: 
                   10176:                     if (ctxt->states != NULL) {
                   10177:                         states = ctxt->states;
                   10178:                         for (i = 0; i < states->nbState; i++) {
                   10179:                             ctxt->state = states->tabState[i];
                   10180:                             ctxt->states = NULL;
                   10181:                             ret = xmlRelaxNGValidateDefinitionList(ctxt,
                   10182:                                                                    define->
                   10183:                                                                    content);
                   10184:                             if (ret == 0) {
                   10185:                                 if (ctxt->state != NULL) {
                   10186:                                     tmp = xmlRelaxNGAddStates(ctxt, res,
                   10187:                                                               ctxt->state);
                   10188:                                     ctxt->state = NULL;
                   10189:                                     if (tmp == 1)
                   10190:                                         progress = 1;
                   10191:                                 } else if (ctxt->states != NULL) {
                   10192:                                     for (j = 0; j < ctxt->states->nbState;
                   10193:                                          j++) {
                   10194:                                         tmp =
                   10195:                                             xmlRelaxNGAddStates(ctxt, res,
                   10196:                                                    ctxt->states->tabState[j]);
                   10197:                                         if (tmp == 1)
                   10198:                                             progress = 1;
                   10199:                                     }
                   10200:                                     xmlRelaxNGFreeStates(ctxt,
                   10201:                                                          ctxt->states);
                   10202:                                     ctxt->states = NULL;
                   10203:                                 }
                   10204:                             } else {
                   10205:                                 if (ctxt->state != NULL) {
                   10206:                                     xmlRelaxNGFreeValidState(ctxt,
                   10207:                                                              ctxt->state);
                   10208:                                     ctxt->state = NULL;
                   10209:                                 }
                   10210:                             }
                   10211:                         }
                   10212:                     } else {
                   10213:                         ret = xmlRelaxNGValidateDefinitionList(ctxt,
                   10214:                                                                define->
                   10215:                                                                content);
                   10216:                         if (ret != 0) {
                   10217:                             xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10218:                             ctxt->state = NULL;
                   10219:                         } else {
                   10220:                             base = res->nbState;
                   10221:                             if (ctxt->state != NULL) {
                   10222:                                 tmp = xmlRelaxNGAddStates(ctxt, res,
                   10223:                                                           ctxt->state);
                   10224:                                 ctxt->state = NULL;
                   10225:                                 if (tmp == 1)
                   10226:                                     progress = 1;
                   10227:                             } else if (ctxt->states != NULL) {
                   10228:                                 for (j = 0; j < ctxt->states->nbState; j++) {
                   10229:                                     tmp = xmlRelaxNGAddStates(ctxt, res,
                   10230:                                                ctxt->states->tabState[j]);
                   10231:                                     if (tmp == 1)
                   10232:                                         progress = 1;
                   10233:                                 }
                   10234:                                 if (states == NULL) {
                   10235:                                     states = ctxt->states;
                   10236:                                 } else {
                   10237:                                     xmlRelaxNGFreeStates(ctxt,
                   10238:                                                          ctxt->states);
                   10239:                                 }
                   10240:                                 ctxt->states = NULL;
                   10241:                             }
                   10242:                         }
                   10243:                     }
                   10244:                     if (progress) {
                   10245:                         /*
                   10246:                          * Collect all the new nodes added at that step
                   10247:                          * and make them the new node set
                   10248:                          */
                   10249:                         if (res->nbState - base == 1) {
                   10250:                             ctxt->state = xmlRelaxNGCopyValidState(ctxt,
                   10251:                                                                    res->
                   10252:                                                                    tabState
                   10253:                                                                    [base]);
                   10254:                         } else {
                   10255:                             if (states == NULL) {
                   10256:                                 xmlRelaxNGNewStates(ctxt,
                   10257:                                                     res->nbState - base);
                   10258:                                states = ctxt->states;
                   10259:                                if (states == NULL) {
                   10260:                                    progress = 0;
                   10261:                                    break;
                   10262:                                }
                   10263:                             }
                   10264:                             states->nbState = 0;
                   10265:                             for (i = base; i < res->nbState; i++)
                   10266:                                 xmlRelaxNGAddStates(ctxt, states,
                   10267:                                                     xmlRelaxNGCopyValidState
                   10268:                                                     (ctxt, res->tabState[i]));
                   10269:                             ctxt->states = states;
                   10270:                         }
                   10271:                     }
                   10272:                 } while (progress == 1);
                   10273:                 if (states != NULL) {
                   10274:                     xmlRelaxNGFreeStates(ctxt, states);
                   10275:                 }
                   10276:                 ctxt->states = res;
                   10277:                 ctxt->flags = oldflags;
                   10278: #if 0
                   10279:                 /*
                   10280:                  * errors may have to be propagated back...
                   10281:                  */
                   10282:                 if (ctxt->errNr > errNr)
                   10283:                     xmlRelaxNGPopErrors(ctxt, errNr);
                   10284: #endif
                   10285:                 ret = 0;
                   10286:                 break;
                   10287:             }
                   10288:         case XML_RELAXNG_CHOICE:{
                   10289:                 xmlRelaxNGDefinePtr list = NULL;
                   10290:                 xmlRelaxNGStatesPtr states = NULL;
                   10291: 
                   10292:                 node = xmlRelaxNGSkipIgnored(ctxt, node);
                   10293: 
                   10294:                 errNr = ctxt->errNr;
                   10295:                 if ((define->dflags & IS_TRIABLE) && (define->data != NULL) &&
                   10296:                    (node != NULL)) {
                   10297:                    /*
                   10298:                     * node == NULL can't be optimized since IS_TRIABLE
                   10299:                     * doesn't account for choice which may lead to
                   10300:                     * only attributes.
                   10301:                     */
                   10302:                     xmlHashTablePtr triage =
                   10303:                         (xmlHashTablePtr) define->data;
                   10304: 
                   10305:                     /*
                   10306:                      * Something we can optimize cleanly there is only one
                   10307:                      * possble branch out !
                   10308:                      */
                   10309:                     if ((node->type == XML_TEXT_NODE) ||
                   10310:                         (node->type == XML_CDATA_SECTION_NODE)) {
                   10311:                         list =
                   10312:                             xmlHashLookup2(triage, BAD_CAST "#text", NULL);
                   10313:                     } else if (node->type == XML_ELEMENT_NODE) {
                   10314:                         if (node->ns != NULL) {
                   10315:                             list = xmlHashLookup2(triage, node->name,
                   10316:                                                   node->ns->href);
                   10317:                             if (list == NULL)
                   10318:                                 list =
                   10319:                                     xmlHashLookup2(triage, BAD_CAST "#any",
                   10320:                                                    node->ns->href);
                   10321:                         } else
                   10322:                             list =
                   10323:                                 xmlHashLookup2(triage, node->name, NULL);
                   10324:                         if (list == NULL)
                   10325:                             list =
                   10326:                                 xmlHashLookup2(triage, BAD_CAST "#any",
                   10327:                                                NULL);
                   10328:                     }
                   10329:                     if (list == NULL) {
                   10330:                         ret = -1;
                   10331:                        VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, node->name);
                   10332:                         break;
                   10333:                     }
                   10334:                     ret = xmlRelaxNGValidateDefinition(ctxt, list);
                   10335:                     if (ret == 0) {
                   10336:                     }
                   10337:                     break;
                   10338:                 }
                   10339: 
                   10340:                 list = define->content;
                   10341:                 oldflags = ctxt->flags;
                   10342:                 ctxt->flags |= FLAGS_IGNORABLE;
                   10343: 
                   10344:                 while (list != NULL) {
                   10345:                     oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
                   10346:                     ret = xmlRelaxNGValidateDefinition(ctxt, list);
                   10347:                     if (ret == 0) {
                   10348:                         if (states == NULL) {
                   10349:                             states = xmlRelaxNGNewStates(ctxt, 1);
                   10350:                         }
                   10351:                         if (ctxt->state != NULL) {
                   10352:                             xmlRelaxNGAddStates(ctxt, states, ctxt->state);
                   10353:                         } else if (ctxt->states != NULL) {
                   10354:                             for (i = 0; i < ctxt->states->nbState; i++) {
                   10355:                                 xmlRelaxNGAddStates(ctxt, states,
                   10356:                                                     ctxt->states->
                   10357:                                                     tabState[i]);
                   10358:                             }
                   10359:                             xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   10360:                             ctxt->states = NULL;
                   10361:                         }
                   10362:                     } else {
                   10363:                         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10364:                     }
                   10365:                     ctxt->state = oldstate;
                   10366:                     list = list->next;
                   10367:                 }
                   10368:                 if (states != NULL) {
                   10369:                     xmlRelaxNGFreeValidState(ctxt, oldstate);
                   10370:                     ctxt->states = states;
                   10371:                     ctxt->state = NULL;
                   10372:                     ret = 0;
                   10373:                 } else {
                   10374:                     ctxt->states = NULL;
                   10375:                 }
                   10376:                 ctxt->flags = oldflags;
                   10377:                 if (ret != 0) {
                   10378:                     if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
                   10379:                         xmlRelaxNGDumpValidError(ctxt);
                   10380:                     }
                   10381:                 } else {
                   10382:                     if (ctxt->errNr > errNr)
                   10383:                         xmlRelaxNGPopErrors(ctxt, errNr);
                   10384:                 }
                   10385:                 break;
                   10386:             }
                   10387:         case XML_RELAXNG_DEF:
                   10388:         case XML_RELAXNG_GROUP:
                   10389:             ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
                   10390:             break;
                   10391:         case XML_RELAXNG_INTERLEAVE:
                   10392:             ret = xmlRelaxNGValidateInterleave(ctxt, define);
                   10393:             break;
                   10394:         case XML_RELAXNG_ATTRIBUTE:
                   10395:             ret = xmlRelaxNGValidateAttribute(ctxt, define);
                   10396:             break;
                   10397:         case XML_RELAXNG_START:
                   10398:         case XML_RELAXNG_NOOP:
                   10399:         case XML_RELAXNG_REF:
                   10400:         case XML_RELAXNG_EXTERNALREF:
                   10401:         case XML_RELAXNG_PARENTREF:
                   10402:             ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
                   10403:             break;
                   10404:         case XML_RELAXNG_DATATYPE:{
                   10405:                 xmlNodePtr child;
                   10406:                 xmlChar *content = NULL;
                   10407: 
                   10408:                 child = node;
                   10409:                 while (child != NULL) {
                   10410:                     if (child->type == XML_ELEMENT_NODE) {
                   10411:                         VALID_ERR2(XML_RELAXNG_ERR_DATAELEM,
                   10412:                                    node->parent->name);
                   10413:                         ret = -1;
                   10414:                         break;
                   10415:                     } else if ((child->type == XML_TEXT_NODE) ||
                   10416:                                (child->type == XML_CDATA_SECTION_NODE)) {
                   10417:                         content = xmlStrcat(content, child->content);
                   10418:                     }
                   10419:                     /* TODO: handle entities ... */
                   10420:                     child = child->next;
                   10421:                 }
                   10422:                 if (ret == -1) {
                   10423:                     if (content != NULL)
                   10424:                         xmlFree(content);
                   10425:                     break;
                   10426:                 }
                   10427:                 if (content == NULL) {
                   10428:                     content = xmlStrdup(BAD_CAST "");
                   10429:                     if (content == NULL) {
                   10430:                         xmlRngVErrMemory(ctxt, "validating\n");
                   10431:                         ret = -1;
                   10432:                         break;
                   10433:                     }
                   10434:                 }
                   10435:                 ret = xmlRelaxNGValidateDatatype(ctxt, content, define,
                   10436:                                                  ctxt->state->seq);
                   10437:                 if (ret == -1) {
                   10438:                     VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name);
                   10439:                 } else if (ret == 0) {
                   10440:                     ctxt->state->seq = NULL;
                   10441:                 }
                   10442:                 if (content != NULL)
                   10443:                     xmlFree(content);
                   10444:                 break;
                   10445:             }
                   10446:         case XML_RELAXNG_VALUE:{
                   10447:                 xmlChar *content = NULL;
                   10448:                 xmlChar *oldvalue;
                   10449:                 xmlNodePtr child;
                   10450: 
                   10451:                 child = node;
                   10452:                 while (child != NULL) {
                   10453:                     if (child->type == XML_ELEMENT_NODE) {
                   10454:                         VALID_ERR2(XML_RELAXNG_ERR_VALELEM,
                   10455:                                    node->parent->name);
                   10456:                         ret = -1;
                   10457:                         break;
                   10458:                     } else if ((child->type == XML_TEXT_NODE) ||
                   10459:                                (child->type == XML_CDATA_SECTION_NODE)) {
                   10460:                         content = xmlStrcat(content, child->content);
                   10461:                     }
                   10462:                     /* TODO: handle entities ... */
                   10463:                     child = child->next;
                   10464:                 }
                   10465:                 if (ret == -1) {
                   10466:                     if (content != NULL)
                   10467:                         xmlFree(content);
                   10468:                     break;
                   10469:                 }
                   10470:                 if (content == NULL) {
                   10471:                     content = xmlStrdup(BAD_CAST "");
                   10472:                     if (content == NULL) {
                   10473:                         xmlRngVErrMemory(ctxt, "validating\n");
                   10474:                         ret = -1;
                   10475:                         break;
                   10476:                     }
                   10477:                 }
                   10478:                 oldvalue = ctxt->state->value;
                   10479:                 ctxt->state->value = content;
                   10480:                 ret = xmlRelaxNGValidateValue(ctxt, define);
                   10481:                 ctxt->state->value = oldvalue;
                   10482:                 if (ret == -1) {
                   10483:                     VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name);
                   10484:                 } else if (ret == 0) {
                   10485:                     ctxt->state->seq = NULL;
                   10486:                 }
                   10487:                 if (content != NULL)
                   10488:                     xmlFree(content);
                   10489:                 break;
                   10490:             }
                   10491:         case XML_RELAXNG_LIST:{
                   10492:                 xmlChar *content;
                   10493:                 xmlNodePtr child;
                   10494:                 xmlChar *oldvalue, *oldendvalue;
                   10495:                 int len;
                   10496: 
                   10497:                 /*
                   10498:                  * Make sure it's only text nodes
                   10499:                  */
                   10500: 
                   10501:                 content = NULL;
                   10502:                 child = node;
                   10503:                 while (child != NULL) {
                   10504:                     if (child->type == XML_ELEMENT_NODE) {
                   10505:                         VALID_ERR2(XML_RELAXNG_ERR_LISTELEM,
                   10506:                                    node->parent->name);
                   10507:                         ret = -1;
                   10508:                         break;
                   10509:                     } else if ((child->type == XML_TEXT_NODE) ||
                   10510:                                (child->type == XML_CDATA_SECTION_NODE)) {
                   10511:                         content = xmlStrcat(content, child->content);
                   10512:                     }
                   10513:                     /* TODO: handle entities ... */
                   10514:                     child = child->next;
                   10515:                 }
                   10516:                 if (ret == -1) {
                   10517:                     if (content != NULL)
                   10518:                         xmlFree(content);
                   10519:                     break;
                   10520:                 }
                   10521:                 if (content == NULL) {
                   10522:                     content = xmlStrdup(BAD_CAST "");
                   10523:                     if (content == NULL) {
                   10524:                         xmlRngVErrMemory(ctxt, "validating\n");
                   10525:                         ret = -1;
                   10526:                         break;
                   10527:                     }
                   10528:                 }
                   10529:                 len = xmlStrlen(content);
                   10530:                 oldvalue = ctxt->state->value;
                   10531:                 oldendvalue = ctxt->state->endvalue;
                   10532:                 ctxt->state->value = content;
                   10533:                 ctxt->state->endvalue = content + len;
                   10534:                 ret = xmlRelaxNGValidateValue(ctxt, define);
                   10535:                 ctxt->state->value = oldvalue;
                   10536:                 ctxt->state->endvalue = oldendvalue;
                   10537:                 if (ret == -1) {
                   10538:                     VALID_ERR(XML_RELAXNG_ERR_LIST);
                   10539:                 } else if ((ret == 0) && (node != NULL)) {
                   10540:                     ctxt->state->seq = node->next;
                   10541:                 }
                   10542:                 if (content != NULL)
                   10543:                     xmlFree(content);
                   10544:                 break;
                   10545:             }
                   10546:         case XML_RELAXNG_EXCEPT:
                   10547:         case XML_RELAXNG_PARAM:
                   10548:             TODO ret = -1;
                   10549:             break;
                   10550:     }
                   10551:     ctxt->depth--;
                   10552: #ifdef DEBUG
                   10553:     for (i = 0; i < ctxt->depth; i++)
                   10554:         xmlGenericError(xmlGenericErrorContext, " ");
                   10555:     xmlGenericError(xmlGenericErrorContext,
                   10556:                     "Validating %s ", xmlRelaxNGDefName(define));
                   10557:     if (define->name != NULL)
                   10558:         xmlGenericError(xmlGenericErrorContext, "%s ", define->name);
                   10559:     if (ret == 0)
                   10560:         xmlGenericError(xmlGenericErrorContext, "suceeded\n");
                   10561:     else
                   10562:         xmlGenericError(xmlGenericErrorContext, "failed\n");
                   10563: #endif
                   10564:     return (ret);
                   10565: }
                   10566: 
                   10567: /**
                   10568:  * xmlRelaxNGValidateDefinition:
                   10569:  * @ctxt:  a Relax-NG validation context
                   10570:  * @define:  the definition to verify
                   10571:  *
                   10572:  * Validate the current node lists against the definition
                   10573:  *
                   10574:  * Returns 0 if the validation succeeded or an error code.
                   10575:  */
                   10576: static int
                   10577: xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
                   10578:                              xmlRelaxNGDefinePtr define)
                   10579: {
                   10580:     xmlRelaxNGStatesPtr states, res;
                   10581:     int i, j, k, ret, oldflags;
                   10582: 
                   10583:     /*
                   10584:      * We should NOT have both ctxt->state and ctxt->states
                   10585:      */
                   10586:     if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
                   10587:         TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10588:         ctxt->state = NULL;
                   10589:     }
                   10590: 
                   10591:     if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) {
                   10592:         if (ctxt->states != NULL) {
                   10593:             ctxt->state = ctxt->states->tabState[0];
                   10594:             xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   10595:             ctxt->states = NULL;
                   10596:         }
                   10597:         ret = xmlRelaxNGValidateState(ctxt, define);
                   10598:         if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
                   10599:             TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10600:             ctxt->state = NULL;
                   10601:         }
                   10602:         if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) {
                   10603:             ctxt->state = ctxt->states->tabState[0];
                   10604:             xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   10605:             ctxt->states = NULL;
                   10606:         }
                   10607:         return (ret);
                   10608:     }
                   10609: 
                   10610:     states = ctxt->states;
                   10611:     ctxt->states = NULL;
                   10612:     res = NULL;
                   10613:     j = 0;
                   10614:     oldflags = ctxt->flags;
                   10615:     ctxt->flags |= FLAGS_IGNORABLE;
                   10616:     for (i = 0; i < states->nbState; i++) {
                   10617:         ctxt->state = states->tabState[i];
                   10618:         ctxt->states = NULL;
                   10619:         ret = xmlRelaxNGValidateState(ctxt, define);
                   10620:         /*
                   10621:          * We should NOT have both ctxt->state and ctxt->states
                   10622:          */
                   10623:         if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
                   10624:             TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10625:             ctxt->state = NULL;
                   10626:         }
                   10627:         if (ret == 0) {
                   10628:             if (ctxt->states == NULL) {
                   10629:                 if (res != NULL) {
                   10630:                     /* add the state to the container */
                   10631:                     xmlRelaxNGAddStates(ctxt, res, ctxt->state);
                   10632:                     ctxt->state = NULL;
                   10633:                 } else {
                   10634:                     /* add the state directly in states */
                   10635:                     states->tabState[j++] = ctxt->state;
                   10636:                     ctxt->state = NULL;
                   10637:                 }
                   10638:             } else {
                   10639:                 if (res == NULL) {
                   10640:                     /* make it the new container and copy other results */
                   10641:                     res = ctxt->states;
                   10642:                     ctxt->states = NULL;
                   10643:                     for (k = 0; k < j; k++)
                   10644:                         xmlRelaxNGAddStates(ctxt, res,
                   10645:                                             states->tabState[k]);
                   10646:                 } else {
                   10647:                     /* add all the new results to res and reff the container */
                   10648:                     for (k = 0; k < ctxt->states->nbState; k++)
                   10649:                         xmlRelaxNGAddStates(ctxt, res,
                   10650:                                             ctxt->states->tabState[k]);
                   10651:                     xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   10652:                     ctxt->states = NULL;
                   10653:                 }
                   10654:             }
                   10655:         } else {
                   10656:             if (ctxt->state != NULL) {
                   10657:                 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10658:                 ctxt->state = NULL;
                   10659:             } else if (ctxt->states != NULL) {
                   10660:                 for (k = 0; k < ctxt->states->nbState; k++)
                   10661:                     xmlRelaxNGFreeValidState(ctxt,
                   10662:                                              ctxt->states->tabState[k]);
                   10663:                 xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   10664:                 ctxt->states = NULL;
                   10665:             }
                   10666:         }
                   10667:     }
                   10668:     ctxt->flags = oldflags;
                   10669:     if (res != NULL) {
                   10670:         xmlRelaxNGFreeStates(ctxt, states);
                   10671:         ctxt->states = res;
                   10672:         ret = 0;
                   10673:     } else if (j > 1) {
                   10674:         states->nbState = j;
                   10675:         ctxt->states = states;
                   10676:         ret = 0;
                   10677:     } else if (j == 1) {
                   10678:         ctxt->state = states->tabState[0];
                   10679:         xmlRelaxNGFreeStates(ctxt, states);
                   10680:         ret = 0;
                   10681:     } else {
                   10682:         ret = -1;
                   10683:         xmlRelaxNGFreeStates(ctxt, states);
                   10684:         if (ctxt->states != NULL) {
                   10685:             xmlRelaxNGFreeStates(ctxt, ctxt->states);
                   10686:             ctxt->states = NULL;
                   10687:         }
                   10688:     }
                   10689:     if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
                   10690:         TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10691:         ctxt->state = NULL;
                   10692:     }
                   10693:     return (ret);
                   10694: }
                   10695: 
                   10696: /**
                   10697:  * xmlRelaxNGValidateDocument:
                   10698:  * @ctxt:  a Relax-NG validation context
                   10699:  * @doc:  the document
                   10700:  *
                   10701:  * Validate the given document
                   10702:  *
                   10703:  * Returns 0 if the validation succeeded or an error code.
                   10704:  */
                   10705: static int
                   10706: xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
                   10707: {
                   10708:     int ret;
                   10709:     xmlRelaxNGPtr schema;
                   10710:     xmlRelaxNGGrammarPtr grammar;
                   10711:     xmlRelaxNGValidStatePtr state;
                   10712:     xmlNodePtr node;
                   10713: 
                   10714:     if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL))
                   10715:         return (-1);
                   10716: 
                   10717:     ctxt->errNo = XML_RELAXNG_OK;
                   10718:     schema = ctxt->schema;
                   10719:     grammar = schema->topgrammar;
                   10720:     if (grammar == NULL) {
                   10721:         VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
                   10722:         return (-1);
                   10723:     }
                   10724:     state = xmlRelaxNGNewValidState(ctxt, NULL);
                   10725:     ctxt->state = state;
                   10726:     ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start);
                   10727:     if ((ctxt->state != NULL) && (state->seq != NULL)) {
                   10728:         state = ctxt->state;
                   10729:         node = state->seq;
                   10730:         node = xmlRelaxNGSkipIgnored(ctxt, node);
                   10731:         if (node != NULL) {
                   10732:             if (ret != -1) {
                   10733:                 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
                   10734:                 ret = -1;
                   10735:             }
                   10736:         }
                   10737:     } else if (ctxt->states != NULL) {
                   10738:         int i;
                   10739:         int tmp = -1;
                   10740: 
                   10741:         for (i = 0; i < ctxt->states->nbState; i++) {
                   10742:             state = ctxt->states->tabState[i];
                   10743:             node = state->seq;
                   10744:             node = xmlRelaxNGSkipIgnored(ctxt, node);
                   10745:             if (node == NULL)
                   10746:                 tmp = 0;
                   10747:             xmlRelaxNGFreeValidState(ctxt, state);
                   10748:         }
                   10749:         if (tmp == -1) {
                   10750:             if (ret != -1) {
                   10751:                 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
                   10752:                 ret = -1;
                   10753:             }
                   10754:         }
                   10755:     }
                   10756:     if (ctxt->state != NULL) {
                   10757:         xmlRelaxNGFreeValidState(ctxt, ctxt->state);
                   10758:         ctxt->state = NULL;
                   10759:     }
                   10760:     if (ret != 0)
                   10761:         xmlRelaxNGDumpValidError(ctxt);
                   10762: #ifdef DEBUG
                   10763:     else if (ctxt->errNr != 0) {
                   10764:         ctxt->error(ctxt->userData,
                   10765:                     "%d Extra error messages left on stack !\n",
                   10766:                     ctxt->errNr);
                   10767:         xmlRelaxNGDumpValidError(ctxt);
                   10768:     }
                   10769: #endif
                   10770: #ifdef LIBXML_VALID_ENABLED
                   10771:     if (ctxt->idref == 1) {
                   10772:         xmlValidCtxt vctxt;
                   10773: 
                   10774:         memset(&vctxt, 0, sizeof(xmlValidCtxt));
                   10775:         vctxt.valid = 1;
                   10776:         vctxt.error = ctxt->error;
                   10777:         vctxt.warning = ctxt->warning;
                   10778:         vctxt.userData = ctxt->userData;
                   10779: 
                   10780:         if (xmlValidateDocumentFinal(&vctxt, doc) != 1)
                   10781:             ret = -1;
                   10782:     }
                   10783: #endif /* LIBXML_VALID_ENABLED */
                   10784:     if ((ret == 0) && (ctxt->errNo != XML_RELAXNG_OK))
                   10785:         ret = -1;
                   10786: 
                   10787:     return (ret);
                   10788: }
                   10789: 
                   10790: /**
                   10791:  * xmlRelaxNGCleanPSVI:
                   10792:  * @node:  an input element or document
                   10793:  *
                   10794:  * Call this routine to speed up XPath computation on static documents.
                   10795:  * This stamps all the element nodes with the document order
                   10796:  * Like for line information, the order is kept in the element->content
                   10797:  * field, the value stored is actually - the node number (starting at -1)
                   10798:  * to be able to differentiate from line numbers.
                   10799:  *
                   10800:  * Returns the number of elements found in the document or -1 in case
                   10801:  *    of error.
                   10802:  */
                   10803: static void
                   10804: xmlRelaxNGCleanPSVI(xmlNodePtr node) {
                   10805:     xmlNodePtr cur;
                   10806: 
                   10807:     if ((node == NULL) ||
                   10808:         ((node->type != XML_ELEMENT_NODE) &&
                   10809:          (node->type != XML_DOCUMENT_NODE) &&
                   10810:          (node->type != XML_HTML_DOCUMENT_NODE)))
                   10811:        return;
                   10812:     if (node->type == XML_ELEMENT_NODE)
                   10813:         node->psvi = NULL;
                   10814: 
                   10815:     cur = node->children;
                   10816:     while (cur != NULL) {
                   10817:        if (cur->type == XML_ELEMENT_NODE) {
                   10818:            cur->psvi = NULL;
                   10819:            if (cur->children != NULL) {
                   10820:                cur = cur->children;
                   10821:                continue;
                   10822:            }
                   10823:        }
                   10824:        if (cur->next != NULL) {
                   10825:            cur = cur->next;
                   10826:            continue;
                   10827:        }
                   10828:        do {
                   10829:            cur = cur->parent;
                   10830:            if (cur == NULL)
                   10831:                break;
                   10832:            if (cur == node) {
                   10833:                cur = NULL;
                   10834:                break;
                   10835:            }
                   10836:            if (cur->next != NULL) {
                   10837:                cur = cur->next;
                   10838:                break;
                   10839:            }
                   10840:        } while (cur != NULL);
                   10841:     }
                   10842:     return;
                   10843: }
                   10844: /************************************************************************
                   10845:  *                                                                     *
                   10846:  *                     Validation interfaces                           *
                   10847:  *                                                                     *
                   10848:  ************************************************************************/
                   10849: 
                   10850: /**
                   10851:  * xmlRelaxNGNewValidCtxt:
                   10852:  * @schema:  a precompiled XML RelaxNGs
                   10853:  *
                   10854:  * Create an XML RelaxNGs validation context based on the given schema
                   10855:  *
                   10856:  * Returns the validation context or NULL in case of error
                   10857:  */
                   10858: xmlRelaxNGValidCtxtPtr
                   10859: xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema)
                   10860: {
                   10861:     xmlRelaxNGValidCtxtPtr ret;
                   10862: 
                   10863:     ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt));
                   10864:     if (ret == NULL) {
                   10865:         xmlRngVErrMemory(NULL, "building context\n");
                   10866:         return (NULL);
                   10867:     }
                   10868:     memset(ret, 0, sizeof(xmlRelaxNGValidCtxt));
                   10869:     ret->schema = schema;
                   10870:     ret->error = xmlGenericError;
                   10871:     ret->userData = xmlGenericErrorContext;
                   10872:     ret->errNr = 0;
                   10873:     ret->errMax = 0;
                   10874:     ret->err = NULL;
                   10875:     ret->errTab = NULL;
                   10876:     if (schema != NULL)
                   10877:        ret->idref = schema->idref;
                   10878:     ret->states = NULL;
                   10879:     ret->freeState = NULL;
                   10880:     ret->freeStates = NULL;
                   10881:     ret->errNo = XML_RELAXNG_OK;
                   10882:     return (ret);
                   10883: }
                   10884: 
                   10885: /**
                   10886:  * xmlRelaxNGFreeValidCtxt:
                   10887:  * @ctxt:  the schema validation context
                   10888:  *
                   10889:  * Free the resources associated to the schema validation context
                   10890:  */
                   10891: void
                   10892: xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt)
                   10893: {
                   10894:     int k;
                   10895: 
                   10896:     if (ctxt == NULL)
                   10897:         return;
                   10898:     if (ctxt->states != NULL)
                   10899:         xmlRelaxNGFreeStates(NULL, ctxt->states);
                   10900:     if (ctxt->freeState != NULL) {
                   10901:         for (k = 0; k < ctxt->freeState->nbState; k++) {
                   10902:             xmlRelaxNGFreeValidState(NULL, ctxt->freeState->tabState[k]);
                   10903:         }
                   10904:         xmlRelaxNGFreeStates(NULL, ctxt->freeState);
                   10905:     }
                   10906:     if (ctxt->freeStates != NULL) {
                   10907:         for (k = 0; k < ctxt->freeStatesNr; k++) {
                   10908:             xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]);
                   10909:         }
                   10910:         xmlFree(ctxt->freeStates);
                   10911:     }
                   10912:     if (ctxt->errTab != NULL)
                   10913:         xmlFree(ctxt->errTab);
                   10914:     if (ctxt->elemTab != NULL) {
                   10915:         xmlRegExecCtxtPtr exec;
                   10916: 
                   10917:         exec = xmlRelaxNGElemPop(ctxt);
                   10918:         while (exec != NULL) {
                   10919:             xmlRegFreeExecCtxt(exec);
                   10920:             exec = xmlRelaxNGElemPop(ctxt);
                   10921:         }
                   10922:         xmlFree(ctxt->elemTab);
                   10923:     }
                   10924:     xmlFree(ctxt);
                   10925: }
                   10926: 
                   10927: /**
                   10928:  * xmlRelaxNGSetValidErrors:
                   10929:  * @ctxt:  a Relax-NG validation context
                   10930:  * @err:  the error function
                   10931:  * @warn: the warning function
                   10932:  * @ctx: the functions context
                   10933:  *
                   10934:  * Set the error and warning callback informations
                   10935:  */
                   10936: void
                   10937: xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
                   10938:                          xmlRelaxNGValidityErrorFunc err,
                   10939:                          xmlRelaxNGValidityWarningFunc warn, void *ctx)
                   10940: {
                   10941:     if (ctxt == NULL)
                   10942:         return;
                   10943:     ctxt->error = err;
                   10944:     ctxt->warning = warn;
                   10945:     ctxt->userData = ctx;
                   10946:     ctxt->serror = NULL;
                   10947: }
                   10948: 
                   10949: /**
                   10950:  * xmlRelaxNGSetValidStructuredErrors:
                   10951:  * @ctxt:  a Relax-NG validation context
                   10952:  * @serror:  the structured error function
                   10953:  * @ctx: the functions context
                   10954:  *
                   10955:  * Set the structured error callback
                   10956:  */
                   10957: void
                   10958: xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt,
                   10959:                                    xmlStructuredErrorFunc serror, void *ctx)
                   10960: {
                   10961:     if (ctxt == NULL)
                   10962:         return;
                   10963:     ctxt->serror = serror;
                   10964:     ctxt->error = NULL;
                   10965:     ctxt->warning = NULL;
                   10966:     ctxt->userData = ctx;
                   10967: }
                   10968: 
                   10969: /**
                   10970:  * xmlRelaxNGGetValidErrors:
                   10971:  * @ctxt:  a Relax-NG validation context
                   10972:  * @err:  the error function result
                   10973:  * @warn: the warning function result
                   10974:  * @ctx: the functions context result
                   10975:  *
                   10976:  * Get the error and warning callback informations
                   10977:  *
                   10978:  * Returns -1 in case of error and 0 otherwise
                   10979:  */
                   10980: int
                   10981: xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
                   10982:                          xmlRelaxNGValidityErrorFunc * err,
                   10983:                          xmlRelaxNGValidityWarningFunc * warn, void **ctx)
                   10984: {
                   10985:     if (ctxt == NULL)
                   10986:         return (-1);
                   10987:     if (err != NULL)
                   10988:         *err = ctxt->error;
                   10989:     if (warn != NULL)
                   10990:         *warn = ctxt->warning;
                   10991:     if (ctx != NULL)
                   10992:         *ctx = ctxt->userData;
                   10993:     return (0);
                   10994: }
                   10995: 
                   10996: /**
                   10997:  * xmlRelaxNGValidateDoc:
                   10998:  * @ctxt:  a Relax-NG validation context
                   10999:  * @doc:  a parsed document tree
                   11000:  *
                   11001:  * Validate a document tree in memory.
                   11002:  *
                   11003:  * Returns 0 if the document is valid, a positive error code
                   11004:  *     number otherwise and -1 in case of internal or API error.
                   11005:  */
                   11006: int
                   11007: xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
                   11008: {
                   11009:     int ret;
                   11010: 
                   11011:     if ((ctxt == NULL) || (doc == NULL))
                   11012:         return (-1);
                   11013: 
                   11014:     ctxt->doc = doc;
                   11015: 
                   11016:     ret = xmlRelaxNGValidateDocument(ctxt, doc);
                   11017:     /*
                   11018:      * Remove all left PSVI
                   11019:      */
                   11020:     xmlRelaxNGCleanPSVI((xmlNodePtr) doc);
                   11021: 
                   11022:     /*
                   11023:      * TODO: build error codes
                   11024:      */
                   11025:     if (ret == -1)
                   11026:         return (1);
                   11027:     return (ret);
                   11028: }
                   11029: 
                   11030: #define bottom_relaxng
                   11031: #include "elfgcchack.h"
                   11032: #endif /* LIBXML_SCHEMAS_ENABLED */

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