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