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

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

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