static int tipc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	struct sock *sk = sock->sk;
	struct tipc_sioc_ln_req lnr;
	void __user *argp = (void __user *)arg;

	switch (cmd) {
	case SIOCGETLINKNAME:
		if (copy_from_user(&lnr, argp, sizeof(lnr)))
			return -EFAULT;
		if (!tipc_node_get_linkname(sock_net(sk),
					    lnr.bearer_id & 0xffff, lnr.peer,
					    lnr.linkname, TIPC_MAX_LINK_NAME)) {
			if (copy_to_user(argp, &lnr, sizeof(lnr)))
				return -EFAULT;
			return 0;
		}
		return -EADDRNOTAVAIL;
	default:
		return -ENOIOCTLCMD;
	}
}


static int tipc_getname(struct socket *sock, struct sockaddr *uaddr,
			int *uaddr_len, int peer)
{
	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
	struct tipc_sock *tsk = tipc_sk(sock->sk);
	struct tipc_net *tn = net_generic(sock_net(sock->sk), tipc_net_id);

	memset(addr, 0, sizeof(*addr));
	if (peer) {
		if ((sock->state != SS_CONNECTED) &&
			((peer != 2) || (sock->state != SS_DISCONNECTING)))
			return -ENOTCONN;
		addr->addr.id.ref = tsk_peer_port(tsk);
		addr->addr.id.node = tsk_peer_node(tsk);
	} else {
		addr->addr.id.ref = tsk->portid;
		addr->addr.id.node = tn->own_addr;
	}

	*uaddr_len = sizeof(*addr);
	addr->addrtype = TIPC_ADDR_ID;
	addr->family = AF_TIPC;
	addr->scope = 0;
	addr->addr.name.domain = 0;

	return 0;
}


static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
{
	struct sock *sk = sock->sk;
	DEFINE_WAIT(wait);
	long timeo = *timeop;
	int err;

	for (;;) {
		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
			if (sock->state == SS_DISCONNECTING) {
				err = -ENOTCONN;
				break;
			}
			release_sock(sk);
			timeo = schedule_timeout(timeo);
			lock_sock(sk);
		}
		err = 0;
		if (!skb_queue_empty(&sk->sk_receive_queue))
			break;
		err = -EAGAIN;
		if (!timeo)
			break;
		err = sock_intr_errno(timeo);
		if (signal_pending(current))
			break;
	}
	finish_wait(sk_sleep(sk), &wait);
	*timeop = timeo;
	return err;
}


static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
{
	struct sock *new_sk, *sk = sock->sk;
	struct sk_buff *buf;
	struct tipc_sock *new_tsock;
	struct tipc_msg *msg;
	long timeo;
	int res;

	lock_sock(sk);

	if (sock->state != SS_LISTENING) {
		res = -EINVAL;
		goto exit;
	}
	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
	res = tipc_wait_for_accept(sock, timeo);
	if (res)
		goto exit;

	buf = skb_peek(&sk->sk_receive_queue);

	res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
	if (res)
		goto exit;
	security_sk_clone(sock->sk, new_sock->sk);

	new_sk = new_sock->sk;
	new_tsock = tipc_sk(new_sk);
	msg = buf_msg(buf);

	/* we lock on new_sk; but lockdep sees the lock on sk */
	lock_sock_nested(new_sk, SINGLE_DEPTH_NESTING);

	/*
	 * Reject any stray messages received by new socket
	 * before the socket lock was taken (very, very unlikely)
	 */
	tsk_rej_rx_queue(new_sk);

	/* Connect new socket to it's peer */
	tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg));
	new_sock->state = SS_CONNECTED;

	tsk_set_importance(new_tsock, msg_importance(msg));
	if (msg_named(msg)) {
		new_tsock->conn_type = msg_nametype(msg);
		new_tsock->conn_instance = msg_nameinst(msg);
	}

	/*
	 * Respond to 'SYN-' by discarding it & returning 'ACK'-.
	 * Respond to 'SYN+' by queuing it on new socket.
	 */
	if (!msg_data_sz(msg)) {
		struct msghdr m = {NULL,};

		tsk_advance_rx_queue(sk);
		__tipc_send_stream(new_sock, &m, 0);
	} else {
		__skb_dequeue(&sk->sk_receive_queue);
		__skb_queue_head(&new_sk->sk_receive_queue, buf);
		skb_set_owner_r(buf, new_sk);
	}
	release_sock(new_sk);
exit:
	release_sock(sk);
	return res;
}


xmlNextChar(xmlParserCtxtPtr ctxt)
{
    if ((ctxt == NULL) || (ctxt->instate == XML_PARSER_EOF) ||
        (ctxt->input == NULL))
        return;

    if (!(VALID_CTXT(ctxt))) {
        xmlErrInternal(ctxt, "Parser input data memory error\n", NULL);
	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
        xmlStopParser(ctxt);
	return;
    }

    if ((*ctxt->input->cur == 0) &&
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) {
        if ((ctxt->instate != XML_PARSER_COMMENT))
            xmlPopInput(ctxt);
        return;
    }

    if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
        const unsigned char *cur;
        unsigned char c;

        /*
         *   2.11 End-of-Line Handling
         *   the literal two-character sequence "#xD#xA" or a standalone
         *   literal #xD, an XML processor must pass to the application
         *   the single character #xA.
         */
        if (*(ctxt->input->cur) == '\n') {
            ctxt->input->line++; ctxt->input->col = 1;
        } else
            ctxt->input->col++;

        /*
         * We are supposed to handle UTF8, check it's valid
         * From rfc2044: encoding of the Unicode values on UTF-8:
         *
         * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
         * 0000 0000-0000 007F   0xxxxxxx
         * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
         * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
         *
         * Check for the 0x110000 limit too
         */
        cur = ctxt->input->cur;

        c = *cur;
        if (c & 0x80) {
        if (c == 0xC0)
	    goto encoding_error;
            if (cur[1] == 0) {
                xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
                cur = ctxt->input->cur;
            }
            if ((cur[1] & 0xc0) != 0x80)
                goto encoding_error;
            if ((c & 0xe0) == 0xe0) {
                unsigned int val;

                if (cur[2] == 0) {
                    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
                    cur = ctxt->input->cur;
                }
                if ((cur[2] & 0xc0) != 0x80)
                    goto encoding_error;
                if ((c & 0xf0) == 0xf0) {
                    if (cur[3] == 0) {
                        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
                        cur = ctxt->input->cur;
                    }
                    if (((c & 0xf8) != 0xf0) ||
                        ((cur[3] & 0xc0) != 0x80))
                        goto encoding_error;
                    /* 4-byte code */
                    ctxt->input->cur += 4;
                    val = (cur[0] & 0x7) << 18;
                    val |= (cur[1] & 0x3f) << 12;
                    val |= (cur[2] & 0x3f) << 6;
                    val |= cur[3] & 0x3f;
                } else {
                    /* 3-byte code */
                    ctxt->input->cur += 3;
                    val = (cur[0] & 0xf) << 12;
                    val |= (cur[1] & 0x3f) << 6;
                    val |= cur[2] & 0x3f;
                }
                if (((val > 0xd7ff) && (val < 0xe000)) ||
                    ((val > 0xfffd) && (val < 0x10000)) ||
                    (val >= 0x110000)) {
		xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
				  "Char 0x%X out of allowed range\n",
				  val);
                }
            } else
                /* 2-byte code */
                ctxt->input->cur += 2;
        } else
            /* 1-byte code */
            ctxt->input->cur++;

        ctxt->nbChars++;
        if (*ctxt->input->cur == 0)
            xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
    } else {
        /*
         * Assume it's a fixed length encoding (1) with
         * a compatible encoding for the ASCII set, since
         * XML constructs only use < 128 chars
         */

        if (*(ctxt->input->cur) == '\n') {
            ctxt->input->line++; ctxt->input->col = 1;
        } else
            ctxt->input->col++;
        ctxt->input->cur++;
        ctxt->nbChars++;
        if (*ctxt->input->cur == 0)
            xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
    }
    if ((*ctxt->input->cur == '%') && (!ctxt->html))
        xmlParserHandlePEReference(ctxt);
    if ((*ctxt->input->cur == 0) &&
        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
        xmlPopInput(ctxt);
    return;
encoding_error:
    /*
     * If we detect an UTF8 error that probably mean that the
     * input encoding didn't get properly advertised in the
     * declaration header. Report the error and switch the encoding
     * to ISO-Latin-1 (if you don't like this policy, just declare the
     * encoding !)
     */
    if ((ctxt == NULL) || (ctxt->input == NULL) ||
        (ctxt->input->end - ctxt->input->cur < 4)) {
	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
		     "Input is not proper UTF-8, indicate encoding !\n",
		     NULL, NULL);
    } else {
        char buffer[150];

	snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
			ctxt->input->cur[0], ctxt->input->cur[1],
			ctxt->input->cur[2], ctxt->input->cur[3]);
	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
		     "Input is not proper UTF-8, indicate encoding !\n%s",
		     BAD_CAST buffer, NULL);
    }
    ctxt->charset = XML_CHAR_ENCODING_8859_1;
    ctxt->input->cur++;
    return;
}


htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
    size_t len = 0, startPosition = 0;
    xmlChar *ret = NULL;

    if (CUR == '"') {
        NEXT;

        if (CUR_PTR < BASE_PTR)
            return(ret);
        startPosition = CUR_PTR - BASE_PTR;

	while ((IS_CHAR_CH(CUR)) && (CUR != '"')) {
	    NEXT;
	    len++;
	}
	if (!IS_CHAR_CH(CUR)) {
	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
			 "Unfinished SystemLiteral\n", NULL, NULL);
	} else {
	    ret = xmlStrndup((BASE_PTR+startPosition), len);
	    NEXT;
        }
    } else if (CUR == '\'') {
        NEXT;

        if (CUR_PTR < BASE_PTR)
            return(ret);
        startPosition = CUR_PTR - BASE_PTR;

	while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) {
	    NEXT;
	    len++;
	}
	if (!IS_CHAR_CH(CUR)) {
	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
			 "Unfinished SystemLiteral\n", NULL, NULL);
	} else {
	    ret = xmlStrndup((BASE_PTR+startPosition), len);
	    NEXT;
        }
    } else {
	htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
	             " or ' expected\n", NULL, NULL);
    }

    return(ret);
}


xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
			xmlNodePtr node,
			xmlSchemaTypePtr type,
			xmlSchemaValType valType,
			const xmlChar * value,
			xmlSchemaValPtr val,
			unsigned long length,
			int fireErrors)
{
    int ret, error = 0;

    xmlSchemaTypePtr tmpType;
    xmlSchemaFacetLinkPtr facetLink;
    xmlSchemaFacetPtr facet;
    unsigned long len = 0;
    xmlSchemaWhitespaceValueType ws;

    /*
    * In Libxml2, derived built-in types have currently no explicit facets.
    */
    if (type->type == XML_SCHEMA_TYPE_BASIC)
	return (0);

    /*
    * NOTE: Do not jump away, if the facetSet of the given type is
    * empty: until now, "pattern" and "enumeration" facets of the
    * *base types* need to be checked as well.
    */
    if (type->facetSet == NULL)
	goto pattern_and_enum;

    if (! WXS_IS_ATOMIC(type)) {
	if (WXS_IS_LIST(type))
	    goto WXS_IS_LIST;
	else
	    goto pattern_and_enum;
    }

    /*
    * Whitespace handling is only of importance for string-based
    * types.
    */
    tmpType = xmlSchemaGetPrimitiveType(type);
    if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
    } else
	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;

    /*
    * If the value was not computed (for string or
    * anySimpleType based types), then use the provided
    * type.
    */
    if (val != NULL)
	valType = xmlSchemaGetValType(val);

    ret = 0;
    for (facetLink = type->facetSet; facetLink != NULL;
	facetLink = facetLink->next) {
	/*
	* Skip the pattern "whiteSpace": it is used to
	* format the character content beforehand.
	*/
	switch (facetLink->facet->type) {
	    case XML_SCHEMA_FACET_WHITESPACE:
	    case XML_SCHEMA_FACET_PATTERN:
	    case XML_SCHEMA_FACET_ENUMERATION:
		continue;
	    case XML_SCHEMA_FACET_LENGTH:
	    case XML_SCHEMA_FACET_MINLENGTH:
	    case XML_SCHEMA_FACET_MAXLENGTH:
		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
		    valType, value, val, &len, ws);
		break;
	    default:
		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
		    valType, value, val, ws);
		break;
	}
	if (ret < 0) {
	    AERROR_INT("xmlSchemaValidateFacets",
		"validating against a atomic type facet");
	    return (-1);
	} else if (ret > 0) {
	    if (fireErrors)
		xmlSchemaFacetErr(actxt, ret, node,
		value, len, type, facetLink->facet, NULL, NULL, NULL);
	    else
		return (ret);
	    if (error == 0)
		error = ret;
	}
	ret = 0;
    }

WXS_IS_LIST:
    if (! WXS_IS_LIST(type))
	goto pattern_and_enum;
    /*
    * "length", "minLength" and "maxLength" of list types.
    */
    ret = 0;
    for (facetLink = type->facetSet; facetLink != NULL;
	facetLink = facetLink->next) {

	switch (facetLink->facet->type) {
	    case XML_SCHEMA_FACET_LENGTH:
	    case XML_SCHEMA_FACET_MINLENGTH:
	    case XML_SCHEMA_FACET_MAXLENGTH:
		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
		    value, length, NULL);
		break;
	    default:
		continue;
	}
	if (ret < 0) {
	    AERROR_INT("xmlSchemaValidateFacets",
		"validating against a list type facet");
	    return (-1);
	} else if (ret > 0) {
	    if (fireErrors)
		xmlSchemaFacetErr(actxt, ret, node,
		value, length, type, facetLink->facet, NULL, NULL, NULL);
	    else
		return (ret);
	    if (error == 0)
		error = ret;
	}
	ret = 0;
    }

pattern_and_enum:
    if (error >= 0) {
	int found = 0;
	/*
	* Process enumerations. Facet values are in the value space
	* of the defining type's base type. This seems to be a bug in the
	* XML Schema 1.0 spec. Use the whitespace type of the base type.
	* Only the first set of enumerations in the ancestor-or-self axis
	* is used for validation.
	*/
	ret = 0;
	tmpType = type;
	do {
	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
		    continue;
		found = 1;
		ret = xmlSchemaAreValuesEqual(facet->val, val);
		if (ret == 1)
		    break;
		else if (ret < 0) {
		    AERROR_INT("xmlSchemaValidateFacets",
			"validating against an enumeration facet");
		    return (-1);
		}
	    }
	    if (ret != 0)
		break;
	    /*
	    * Break on the first set of enumerations. Any additional
	    *  enumerations which might be existent on the ancestors
	    *  of the current type are restricted by this set; thus
	    *  *must* *not* be taken into account.
	    */
	    if (found)
		break;
	    tmpType = tmpType->baseType;
	} while ((tmpType != NULL) &&
	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
	if (found && (ret == 0)) {
	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
	    if (fireErrors) {
		xmlSchemaFacetErr(actxt, ret, node,
		    value, 0, type, NULL, NULL, NULL, NULL);
	    } else
		return (ret);
	    if (error == 0)
		error = ret;
	}
    }

    if (error >= 0) {
	int found;
	/*
	* Process patters. Pattern facets are ORed at type level
	* and ANDed if derived. Walk the base type axis.
	*/
	tmpType = type;
	facet = NULL;
	do {
	    found = 0;
	    for (facetLink = tmpType->facetSet; facetLink != NULL;
		facetLink = facetLink->next) {
		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
		    continue;
		found = 1;
		/*
		* NOTE that for patterns, @value needs to be the
		* normalized vaule.
		*/
		ret = xmlRegexpExec(facetLink->facet->regexp, value);
		if (ret == 1)
		    break;
		else if (ret < 0) {
		    AERROR_INT("xmlSchemaValidateFacets",
			"validating against a pattern facet");
		    return (-1);
		} else {
		    /*
		    * Save the last non-validating facet.
		    */
		    facet = facetLink->facet;
		}
	    }
	    if (found && (ret != 1)) {
		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
		if (fireErrors) {
		    xmlSchemaFacetErr(actxt, ret, node,
			value, 0, type, facet, NULL, NULL, NULL);
		} else
		    return (ret);
		if (error == 0)
		    error = ret;
		break;
	    }
	    tmpType = tmpType->baseType;
	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
    }

    return (error);
}


xmlFdRead (void * context, char * buffer, int len) {
    int ret;

    ret = read((int) (long) context, &buffer[0], len);
    if (ret < 0) xmlIOErr(0, "read()");
    return(ret);
}


xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
                      xmlNodePtr node, int *isElemRef, int topLevel)
{
    xmlSchemaElementPtr decl = NULL;
    xmlSchemaParticlePtr particle = NULL;
    xmlSchemaAnnotPtr annot = NULL;
    xmlNodePtr child = NULL;
    xmlAttrPtr attr, nameAttr;
    int min, max, isRef = 0;
    xmlChar *des = NULL;

    /* 3.3.3 Constraints on XML Representations of Element Declarations */
    /* TODO: Complete implementation of 3.3.6 */

    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
        return (NULL);

    if (isElemRef != NULL)
	*isElemRef = 0;
    /*
    * If we get a "ref" attribute on a local <element> we will assume it's
    * a reference - even if there's a "name" attribute; this seems to be more
    * robust.
    */
    nameAttr = xmlSchemaGetPropNode(node, "name");
    attr = xmlSchemaGetPropNode(node, "ref");
    if ((topLevel) || (attr == NULL)) {
	if (nameAttr == NULL) {
	    xmlSchemaPMissingAttrErr(ctxt,
		XML_SCHEMAP_S4S_ATTR_MISSING,
		NULL, node, "name", NULL);
	    return (NULL);
	}
    } else
	isRef = 1;

    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
    child = node->children;
    if (IS_SCHEMA(child, "annotation")) {
	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
	child = child->next;
    }
    /*
    * Skip particle part if a global declaration.
    */
    if (topLevel)
	goto declaration_part;
    /*
    * The particle part ==================================================
    */
    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
    particle = xmlSchemaAddParticle(ctxt, node, min, max);
    if (particle == NULL)
	goto return_null;

    /* ret->flags |= XML_SCHEMAS_ELEM_REF; */

    if (isRef) {
	const xmlChar *refNs = NULL, *ref = NULL;
	xmlSchemaQNameRefPtr refer = NULL;
	/*
	* The reference part =============================================
	*/
	if (isElemRef != NULL)
	    *isElemRef = 1;

	xmlSchemaPValAttrNodeQName(ctxt, schema,
	    NULL, attr, &refNs, &ref);
	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
	/*
	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
	*/
	if (nameAttr != NULL) {
	    xmlSchemaPMutualExclAttrErr(ctxt,
		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
	}
	/*
	* Check for illegal attributes.
	*/
	attr = node->properties;
	while (attr != NULL) {
	    if (attr->ns == NULL) {
		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
		    xmlStrEqual(attr->name, BAD_CAST "name") ||
		    xmlStrEqual(attr->name, BAD_CAST "id") ||
		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
		{
		    attr = attr->next;
		    continue;
		} else {
		    /* SPEC (3.3.3 : 2.2) */
		    xmlSchemaPCustomAttrErr(ctxt,
			XML_SCHEMAP_SRC_ELEMENT_2_2,
			NULL, NULL, attr,
			"Only the attributes 'minOccurs', 'maxOccurs' and "
			"'id' are allowed in addition to 'ref'");
		    break;
		}
	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
		xmlSchemaPIllegalAttrErr(ctxt,
		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
	    }
	    attr = attr->next;
	}
	/*
	* No children except <annotation> expected.
	*/
	if (child != NULL) {
	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
		NULL, node, child, NULL, "(annotation?)");
	}
	if ((min == 0) && (max == 0))
	    goto return_null;
	/*
	* Create the reference item and attach it to the particle.
	*/
	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
	    ref, refNs);
	if (refer == NULL)
	    goto return_null;
	particle->children = (xmlSchemaTreeItemPtr) refer;
	particle->annot = annot;
	/*
	* Add the particle to pending components, since the reference
	* need to be resolved.
	*/
	WXS_ADD_PENDING(ctxt, particle);
	return ((xmlSchemaBasicItemPtr) particle);
    }
    /*
    * The declaration part ===============================================
    */
declaration_part:
    {
	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;

	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
	    goto return_null;
	/*
	* Evaluate the target namespace.
	*/
	if (topLevel) {
	    ns = ctxt->targetNamespace;
	} else {
	    attr = xmlSchemaGetPropNode(node, "form");
	    if (attr != NULL) {
		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
		    ns = ctxt->targetNamespace;
		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
		    xmlSchemaPSimpleTypeErr(ctxt,
			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
			NULL, (xmlNodePtr) attr,
			NULL, "(qualified | unqualified)",
			attrValue, NULL, NULL, NULL);
		}
	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
		ns = ctxt->targetNamespace;
	}
	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
	if (decl == NULL) {
	    goto return_null;
	}
	/*
	* Check for illegal attributes.
	*/
	attr = node->properties;
	while (attr != NULL) {
	    if (attr->ns == NULL) {
		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
		{
		    if (topLevel == 0) {
			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
			{
			    xmlSchemaPIllegalAttrErr(ctxt,
				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
			}
		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {

			xmlSchemaPIllegalAttrErr(ctxt,
			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
		    }
		}
	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {

		xmlSchemaPIllegalAttrErr(ctxt,
		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
	    }
	    attr = attr->next;
	}
	/*
	* Extract/validate attributes.
	*/
	if (topLevel) {
	    /*
	    * Process top attributes of global element declarations here.
	    */
	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
	    xmlSchemaPValAttrQName(ctxt, schema,
		NULL, node, "substitutionGroup",
		&(decl->substGroupNs), &(decl->substGroup));
	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
	    /*
	    * Attribute "final".
	    */
	    attr = xmlSchemaGetPropNode(node, "final");
	    if (attr == NULL) {
		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
	    } else {
		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
		    -1,
		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
		    xmlSchemaPSimpleTypeErr(ctxt,
			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
			NULL, (xmlNodePtr) attr,
			NULL, "(#all | List of (extension | restriction))",
			attrValue, NULL, NULL, NULL);
		}
	    }
	}
	/*
	* Attribute "block".
	*/
	attr = xmlSchemaGetPropNode(node, "block");
	if (attr == NULL) {
	    /*
	    * Apply default "block" values.
	    */
	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
	} else {
	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
		-1,
		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
		xmlSchemaPSimpleTypeErr(ctxt,
		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
		    NULL, (xmlNodePtr) attr,
		    NULL, "(#all | List of (extension | "
		    "restriction | substitution))", attrValue,
		    NULL, NULL, NULL);
	    }
	}
	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;

	attr = xmlSchemaGetPropNode(node, "type");
	if (attr != NULL) {
	    xmlSchemaPValAttrNodeQName(ctxt, schema,
		NULL, attr,
		&(decl->namedTypeNs), &(decl->namedType));
	    xmlSchemaCheckReference(ctxt, schema, node,
		attr, decl->namedTypeNs);
	}
	decl->value = xmlSchemaGetProp(ctxt, node, "default");
	attr = xmlSchemaGetPropNode(node, "fixed");
	if (attr != NULL) {
	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
	    if (decl->value != NULL) {
		/*
		* 3.3.3 : 1
		* default and fixed must not both be present.
		*/
		xmlSchemaPMutualExclAttrErr(ctxt,
		    XML_SCHEMAP_SRC_ELEMENT_1,
		    NULL, attr, "default", "fixed");
	    } else {
		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
		decl->value = fixed;
	    }
	}
	/*
	* And now for the children...
	*/
	if (IS_SCHEMA(child, "complexType")) {
	    /*
	    * 3.3.3 : 3
	    * "type" and either <simpleType> or <complexType> are mutually
	    * exclusive
	    */
	    if (decl->namedType != NULL) {
		xmlSchemaPContentErr(ctxt,
		    XML_SCHEMAP_SRC_ELEMENT_3,
		    NULL, node, child,
		    "The attribute 'type' and the <complexType> child are "
		    "mutually exclusive", NULL);
	    } else
		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
	    child = child->next;
	} else if (IS_SCHEMA(child, "simpleType")) {
	    /*
	    * 3.3.3 : 3
	    * "type" and either <simpleType> or <complexType> are
	    * mutually exclusive
	    */
	    if (decl->namedType != NULL) {
		xmlSchemaPContentErr(ctxt,
		    XML_SCHEMAP_SRC_ELEMENT_3,
		    NULL, node, child,
		    "The attribute 'type' and the <simpleType> child are "
		    "mutually exclusive", NULL);
	    } else
		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
	    child = child->next;
	}
	while ((IS_SCHEMA(child, "unique")) ||
	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
	    if (IS_SCHEMA(child, "unique")) {
		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
	    } else if (IS_SCHEMA(child, "key")) {
		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
	    } else if (IS_SCHEMA(child, "keyref")) {
		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
	    }
	    if (lastIDC != NULL)
		lastIDC->next = curIDC;
	    else
		decl->idcs = (void *) curIDC;
	    lastIDC = curIDC;
	    child = child->next;
	}
	if (child != NULL) {
	    xmlSchemaPContentErr(ctxt,
		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
		NULL, node, child,
		NULL, "(annotation?, ((simpleType | complexType)?, "
		"(unique | key | keyref)*))");
	}
	decl->annot = annot;
    }
    /*
    * NOTE: Element Declaration Representation OK 4. will be checked at a
    * different layer.
    */
    FREE_AND_NULL(des)
    if (topLevel)
	return ((xmlSchemaBasicItemPtr) decl);
    else {
	particle->children = (xmlSchemaTreeItemPtr) decl;
	return ((xmlSchemaBasicItemPtr) particle);
    }

return_null:
    FREE_AND_NULL(des);
    if (annot != NULL) {
	if (particle != NULL)
	    particle->annot = NULL;
	if (decl != NULL)
	    decl->annot = NULL;
	xmlSchemaFreeAnnot(annot);
    }
    return (NULL);
}


unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
		   const xmlChar *publicId, const xmlChar *systemId,
		   const xmlChar *notationName)
{
    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
        (ctxt->user_sax->unparsedEntityDecl != NULL))
	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
	                                   systemId, notationName);
}


xmlSchemaFreeElement(xmlSchemaElementPtr elem)
{
    if (elem == NULL)
        return;
    if (elem->annot != NULL)
        xmlSchemaFreeAnnot(elem->annot);
    if (elem->contModel != NULL)
        xmlRegFreeRegexp(elem->contModel);
    if (elem->defVal != NULL)
	xmlSchemaFreeValue(elem->defVal);
    xmlFree(elem);
}


xmlGetUTF8Char(const unsigned char *utf, int *len) {
    unsigned int c;

    if (utf == NULL)
        goto error;
    if (len == NULL)
        goto error;
    if (*len < 1)
        goto error;

    c = utf[0];
    if (c & 0x80) {
        if (*len < 2)
            goto error;
        if ((utf[1] & 0xc0) != 0x80)
            goto error;
        if ((c & 0xe0) == 0xe0) {
            if (*len < 3)
                goto error;
            if ((utf[2] & 0xc0) != 0x80)
                goto error;
            if ((c & 0xf0) == 0xf0) {
                if (*len < 4)
                    goto error;
                if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
                    goto error;
                *len = 4;
                /* 4-byte code */
                c = (utf[0] & 0x7) << 18;
                c |= (utf[1] & 0x3f) << 12;
                c |= (utf[2] & 0x3f) << 6;
                c |= utf[3] & 0x3f;
            } else {
              /* 3-byte code */
                *len = 3;
                c = (utf[0] & 0xf) << 12;
                c |= (utf[1] & 0x3f) << 6;
                c |= utf[2] & 0x3f;
            }
        } else {
          /* 2-byte code */
            *len = 2;
            c = (utf[0] & 0x1f) << 6;
            c |= utf[1] & 0x3f;
        }
    } else {
        /* 1-byte code */
        *len = 1;
    }
    return(c);

error:
    if (len != NULL)
	*len = 0;
    return(-1);
}


xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
		 xmlSchemaTypeType type,
                 const xmlChar * name, const xmlChar * nsName,
		 xmlNodePtr node, int topLevel)
{
    xmlSchemaTypePtr ret = NULL;

    if ((ctxt == NULL) || (schema == NULL))
        return (NULL);

    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
    if (ret == NULL) {
        xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
        return (NULL);
    }
    memset(ret, 0, sizeof(xmlSchemaType));
    ret->type = type;
    ret->name = name;
    ret->targetNamespace = nsName;
    ret->node = node;
    if (topLevel) {
	if (ctxt->isRedefine) {
	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
		ret, name, nsName);
	    if (ctxt->redef == NULL) {
		xmlFree(ret);
		return(NULL);
	    }
	    ctxt->redefCounter = 0;
	}
	WXS_ADD_GLOBAL(ctxt, ret);
    } else
	WXS_ADD_LOCAL(ctxt, ret);
    WXS_ADD_PENDING(ctxt, ret);
    return (ret);
}


xmlUTF8Charcmp(const xmlChar *utf1, const xmlChar *utf2) {

    if (utf1 == NULL ) {
        if (utf2 == NULL)
            return 0;
        return -1;
    }
    return xmlStrncmp(utf1, utf2, xmlUTF8Size(utf1));
}


xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
                       xmlNodePtr node)
{
    int res;

    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
	XML_SCHEMA_SCHEMA_INCLUDE);
    if (res != 0)
	return(res);
    return(0);
}


xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
{
    if (ctxt == NULL)
        return(NULL);
    return (ctxt->parserCtxt);
}


endOfInput (void * context ATTRIBUTE_UNUSED,
	    char * buffer ATTRIBUTE_UNUSED,
	    int len ATTRIBUTE_UNUSED) {
    return(0);
}


xmlOutputBufferFlush(xmlOutputBufferPtr out) {
    int nbchars = 0, ret = 0;

    if ((out == NULL) || (out->error)) return(-1);
    /*
     * first handle encoding stuff.
     */
    if ((out->conv != NULL) && (out->encoder != NULL)) {
	/*
	 * convert as much as possible to the parser output buffer.
	 */
	do {
	    nbchars = xmlCharEncOutput(out, 0);
	    if (nbchars < 0) {
		xmlIOErr(XML_IO_ENCODER, NULL);
		out->error = XML_IO_ENCODER;
		return(-1);
	    }
	} while (nbchars);
    }

    /*
     * second flush the stuff to the I/O channel
     */
    if ((out->conv != NULL) && (out->encoder != NULL) &&
	(out->writecallback != NULL)) {
	ret = out->writecallback(out->context,
                                 (const char *)xmlBufContent(out->conv),
                                 xmlBufUse(out->conv));
	if (ret >= 0)
	    xmlBufShrink(out->conv, ret);
    } else if (out->writecallback != NULL) {
	ret = out->writecallback(out->context,
                                 (const char *)xmlBufContent(out->buffer),
                                 xmlBufUse(out->buffer));
	if (ret >= 0)
	    xmlBufShrink(out->buffer, ret);
    }
    if (ret < 0) {
	xmlIOErr(XML_IO_FLUSH, NULL);
	out->error = XML_IO_FLUSH;
	return(ret);
    }
    out->written += ret;

#ifdef DEBUG_INPUT
    xmlGenericError(xmlGenericErrorContext,
	    "I/O: flushed %d chars\n", ret);
#endif
    return(ret);
}


xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
			    xmlSchemaWildcardPtr completeWild,
			    xmlSchemaWildcardPtr curWild)
{
    xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;

    /*
    * 1 If O1 and O2 are the same value, then that value must be the
    * value.
    */
    if ((completeWild->any == curWild->any) &&
	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {

	if ((completeWild->negNsSet == NULL) ||
	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {

	    if (completeWild->nsSet != NULL) {
		int found = 0;

		/*
		* Check equality of sets.
		*/
		cur = completeWild->nsSet;
		while (cur != NULL) {
		    found = 0;
		    curB = curWild->nsSet;
		    while (curB != NULL) {
			if (cur->value == curB->value) {
			    found = 1;
			    break;
			}
			curB = curB->next;
		    }
		    if (!found)
			break;
		    cur = cur->next;
		}
		if (found)
		    return(0);
	    } else
		return(0);
	}
    }
    /*
    * 2 If either O1 or O2 is any, then the other must be the value.
    */
    if ((completeWild->any != curWild->any) && (completeWild->any)) {
	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
	    return(-1);
	return(0);
    }
    /*
    * 3 If either O1 or O2 is a pair of not and a value (a namespace
    * name or `absent`) and the other is a set of (namespace names or
    * `absent`), then that set, minus the negated value if it was in
    * the set, minus `absent` if it was in the set, must be the value.
    */
    if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
	const xmlChar *neg;

	if (completeWild->nsSet == NULL) {
	    neg = completeWild->negNsSet->value;
	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
		return(-1);
	} else
	    neg = curWild->negNsSet->value;
	/*
	* Remove absent and negated.
	*/
	prev = NULL;
	cur = completeWild->nsSet;
	while (cur != NULL) {
	    if (cur->value == NULL) {
		if (prev == NULL)
		    completeWild->nsSet = cur->next;
		else
		    prev->next = cur->next;
		xmlFree(cur);
		break;
	    }
	    prev = cur;
	    cur = cur->next;
	}
	if (neg != NULL) {
	    prev = NULL;
	    cur = completeWild->nsSet;
	    while (cur != NULL) {
		if (cur->value == neg) {
		    if (prev == NULL)
			completeWild->nsSet = cur->next;
		    else
			prev->next = cur->next;
		    xmlFree(cur);
		    break;
		}
		prev = cur;
		cur = cur->next;
	    }
	}

	return(0);
    }
    /*
    * 4 If both O1 and O2 are sets of (namespace names or `absent`),
    * then the intersection of those sets must be the value.
    */
    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
	int found;

	cur = completeWild->nsSet;
	prev = NULL;
	while (cur != NULL) {
	    found = 0;
	    curB = curWild->nsSet;
	    while (curB != NULL) {
		if (cur->value == curB->value) {
		    found = 1;
		    break;
		}
		curB = curB->next;
	    }
	    if (!found) {
		if (prev == NULL)
		    completeWild->nsSet = cur->next;
		else
		    prev->next = cur->next;
		tmp = cur->next;
		xmlFree(cur);
		cur = tmp;
		continue;
	    }
	    prev = cur;
	    cur = cur->next;
	}

	return(0);
    }
    /* 5 If the two are negations of different namespace names,
    * then the intersection is not expressible
    */
    if ((completeWild->negNsSet != NULL) &&
	(curWild->negNsSet != NULL) &&
	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
	(completeWild->negNsSet->value != NULL) &&
	(curWild->negNsSet->value != NULL)) {

	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
	    "The intersection of the wilcard is not expressible.\n",
	    NULL, NULL);
	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
    }
    /*
    * 6 If the one is a negation of a namespace name and the other
    * is a negation of `absent`, then the one which is the negation
    * of a namespace name must be the value.
    */
    if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
	(completeWild->negNsSet->value == NULL)) {
	completeWild->negNsSet->value =  curWild->negNsSet->value;
    }
    return(0);
}


xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
		     xmlNodePtr node, int min, int max)
{
    xmlSchemaParticlePtr ret = NULL;
    if (ctxt == NULL)
        return (NULL);

#ifdef DEBUG
    fprintf(stderr, "Adding particle component\n");
#endif
    ret = (xmlSchemaParticlePtr)
	xmlMalloc(sizeof(xmlSchemaParticle));
    if (ret == NULL) {
	xmlSchemaPErrMemory(ctxt, "allocating particle component",
	    NULL);
	return (NULL);
    }
    ret->type = XML_SCHEMA_TYPE_PARTICLE;
    ret->annot = NULL;
    ret->node = node;
    ret->minOccurs = min;
    ret->maxOccurs = max;
    ret->next = NULL;
    ret->children = NULL;

    WXS_ADD_LOCAL(ctxt, ret);
    /*
    * Note that addition to pending components will be done locally
    * to the specific parsing function, since the most particles
    * need not to be fixed up (i.e. the reference to be resolved).
    * REMOVED: WXS_ADD_PENDING(ctxt, ret);
    */
    return (ret);
}


xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
{
    xmlSchemaIDCMatcherPtr matcher;
    xmlSchemaPSVIIDCBindingPtr bind;

    matcher = vctxt->inode->idcMatchers;
    /*
    * Find a keyref.
    */
    while (matcher != NULL) {
	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
	    matcher->targets &&
	    matcher->targets->nbItems)
	{
	    int i, j, k, res, nbFields, hasDupls;
	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
	    xmlSchemaPSVIIDCNodePtr refNode = NULL;

	    nbFields = matcher->aidc->def->nbFields;

	    /*
	    * Find the IDC node-table for the referenced IDC key/unique.
	    */
	    bind = vctxt->inode->idcTable;
	    while (bind != NULL) {
		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
		    bind->definition)
		    break;
		bind = bind->next;
	    }
	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
	    /*
	    * Search for a matching key-sequences.
	    */
	    for (i = 0; i < matcher->targets->nbItems; i++) {
		res = 0;
		refNode = matcher->targets->items[i];
		if (bind != NULL) {
		    refKeys = refNode->keys;
		    for (j = 0; j < bind->nbNodes; j++) {
			keys = bind->nodeTable[j]->keys;
			for (k = 0; k < nbFields; k++) {
			    res = xmlSchemaAreValuesEqual(keys[k]->val,
				refKeys[k]->val);
			    if (res == 0)
				break;
			    else if (res == -1) {
				return (-1);
			    }
			}
			if (res == 1) {
			    /*
			    * Match found.
			    */
			    break;
			}
		    }
		    if ((res == 0) && hasDupls) {
			/*
			* Search in duplicates
			*/
			for (j = 0; j < bind->dupls->nbItems; j++) {
			    keys = ((xmlSchemaPSVIIDCNodePtr)
				bind->dupls->items[j])->keys;
			    for (k = 0; k < nbFields; k++) {
				res = xmlSchemaAreValuesEqual(keys[k]->val,
				    refKeys[k]->val);
				if (res == 0)
				    break;
				else if (res == -1) {
				    return (-1);
				}
			    }
			    if (res == 1) {
				/*
				* Match in duplicates found.
				*/
				xmlChar *str = NULL, *strB = NULL;
				xmlSchemaKeyrefErr(vctxt,
				    XML_SCHEMAV_CVC_IDC, refNode,
				    (xmlSchemaTypePtr) matcher->aidc->def,
				    "More than one match found for "
				    "key-sequence %s of keyref '%s'",
				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
					refNode->keys, nbFields),
				    xmlSchemaGetComponentQName(&strB,
					matcher->aidc->def));
				FREE_AND_NULL(str);
				FREE_AND_NULL(strB);
				break;
			    }
			}
		    }
		}

		if (res == 0) {
		    xmlChar *str = NULL, *strB = NULL;
		    xmlSchemaKeyrefErr(vctxt,
			XML_SCHEMAV_CVC_IDC, refNode,
			(xmlSchemaTypePtr) matcher->aidc->def,
			"No match found for key-sequence %s of keyref '%s'",
			xmlSchemaFormatIDCKeySequence(vctxt, &str,
			    refNode->keys, nbFields),
			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
		    FREE_AND_NULL(str);
		    FREE_AND_NULL(strB);
		}
	    }
	}
	matcher = matcher->next;
    }
    /* TODO: Return an error if any error encountered. */
    return (0);
}


xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
	      int error, xmlNodePtr node, const char *msg,
	      const xmlChar *str1, const xmlChar *str2,
	      const xmlChar *str3, const xmlChar *str4)
{
    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
	msg, str1, str2, str3, str4);
}


xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
				     int *fixed,
				     const xmlChar **value,
				     xmlSchemaValPtr *val)
{
    *fixed = 0;
    *value = NULL;
    if (val != 0)
	*val = NULL;

    if (attruse->defValue != NULL) {
	*value = attruse->defValue;
	if (val != NULL)
	    *val = attruse->defVal;
	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
	    *fixed = 1;
	return(1);
    } else if ((attruse->attrDecl != NULL) &&
	(attruse->attrDecl->defValue != NULL)) {
	*value = attruse->attrDecl->defValue;
	if (val != NULL)
	    *val = attruse->attrDecl->defVal;
	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
	    *fixed = 1;
	return(1);
    }
    return(0);
}


xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
                       xmlNodePtr node)
{
    int res;
#ifndef ENABLE_REDEFINE
    TODO
    return(0);
#endif
    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
	XML_SCHEMA_SCHEMA_REDEFINE);
    if (res != 0)
	return(res);
    return(0);
}


xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
#ifdef LIBXML_HTTP_ENABLED
    if ((ret != NULL) && (ret->buf != NULL) &&
        (ret->buf->readcallback == xmlIOHTTPRead) &&
        (ret->buf->context != NULL)) {
        const char *encoding;
        const char *redir;
        const char *mime;
        int code;

        code = xmlNanoHTTPReturnCode(ret->buf->context);
        if (code >= 400) {
            /* fatal error */
	    if (ret->filename != NULL)
		__xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
                         (const char *) ret->filename);
	    else
		__xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
            xmlFreeInputStream(ret);
            ret = NULL;
        } else {

            mime = xmlNanoHTTPMimeType(ret->buf->context);
            if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) ||
                (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) {
                encoding = xmlNanoHTTPEncoding(ret->buf->context);
                if (encoding != NULL) {
                    xmlCharEncodingHandlerPtr handler;

                    handler = xmlFindCharEncodingHandler(encoding);
                    if (handler != NULL) {
                        xmlSwitchInputEncoding(ctxt, ret, handler);
                    } else {
                        __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
                                         "Unknown encoding %s",
                                         BAD_CAST encoding, NULL);
                    }
                    if (ret->encoding == NULL)
                        ret->encoding = xmlStrdup(BAD_CAST encoding);
                }
#if 0
            } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
#endif
            }
            redir = xmlNanoHTTPRedir(ret->buf->context);
            if (redir != NULL) {
                if (ret->filename != NULL)
                    xmlFree((xmlChar *) ret->filename);
                if (ret->directory != NULL) {
                    xmlFree((xmlChar *) ret->directory);
                    ret->directory = NULL;
                }
                ret->filename =
                    (char *) xmlStrdup((const xmlChar *) redir);
            }
        }
    }
#endif
    return(ret);
}


xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
				  xmlSchemaParticlePtr r,
				  xmlSchemaParticlePtr b)
{
    int ret = 0;

    /*part = WXS_TYPE_PARTICLE(type);
    basePart = WXS_TYPE_PARTICLE(base);
    */

    TODO

    /*
    * SPEC (1) "They are the same particle."
    */
    if (r == b)
	return (0);

    return (0);
}


xmlStrQEqual(const xmlChar *pref, const xmlChar *name, const xmlChar *str) {
    if (pref == NULL) return(xmlStrEqual(name, str));
    if (name == NULL) return(0);
    if (str == NULL) return(0);

    do {
        if (*pref++ != *str) return(0);
    } while ((*str++) && (*pref));
    if (*str++ != ':') return(0);
    do {
        if (*name++ != *str) return(0);
    } while (*str++);
    return(1);
}


xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
{
    xmlChar *str = NULL;
    xmlSchemaTreeItemPtr term;
    char shift[100];
    int i;

    if (particle == NULL)
	return;
    for (i = 0;((i < depth) && (i < 25));i++)
        shift[2 * i] = shift[2 * i + 1] = ' ';
    shift[2 * i] = shift[2 * i + 1] = 0;
    fprintf(output, "%s", shift);
    if (particle->children == NULL) {
	fprintf(output, "MISSING particle term\n");
	return;
    }
    term = particle->children;
    if (term == NULL) {
	fprintf(output, "(NULL)");
    } else {
	switch (term->type) {
	    case XML_SCHEMA_TYPE_ELEMENT:
		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
		    ((xmlSchemaElementPtr)term)->targetNamespace,
		    ((xmlSchemaElementPtr)term)->name));
		FREE_AND_NULL(str);
		break;
	    case XML_SCHEMA_TYPE_SEQUENCE:
		fprintf(output, "SEQUENCE");
		break;
	    case XML_SCHEMA_TYPE_CHOICE:
		fprintf(output, "CHOICE");
		break;
	    case XML_SCHEMA_TYPE_ALL:
		fprintf(output, "ALL");
		break;
	    case XML_SCHEMA_TYPE_ANY:
		fprintf(output, "ANY");
		break;
	    default:
		fprintf(output, "UNKNOWN\n");
		return;
	}
    }
    if (particle->minOccurs != 1)
	fprintf(output, " min: %d", particle->minOccurs);
    if (particle->maxOccurs >= UNBOUNDED)
	fprintf(output, " max: unbounded");
    else if (particle->maxOccurs != 1)
	fprintf(output, " max: %d", particle->maxOccurs);
    fprintf(output, "\n");
    if (term &&
	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
	 (term->children != NULL)) {
	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
	    output, depth +1);
    }
    if (particle->next != NULL)
	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
		output, depth);
}


xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
			   xmlSchemaNodeInfoPtr ielem)
{
    xmlSchemaPSVIIDCBindingPtr bind;
    int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
    xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
    xmlSchemaPSVIIDCNodePtr *targets, *dupls;

    xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
    /* vctxt->createIDCNodeTables */
    while (matcher != NULL) {
	/*
	* Skip keyref IDCs and empty IDC target-lists.
	*/
	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
	    WXS_ILIST_IS_EMPTY(matcher->targets))
	{
	    matcher = matcher->next;
	    continue;
	}
	/*
	* If we _want_ the IDC node-table to be created in any case
	* then do so. Otherwise create them only if keyrefs need them.
	*/
	if ((! vctxt->createIDCNodeTables) &&
	    ((matcher->aidc->keyrefDepth == -1) ||
	     (matcher->aidc->keyrefDepth > vctxt->depth)))
	{
	    matcher = matcher->next;
	    continue;
	}
	/*
	* Get/create the IDC binding on this element for the IDC definition.
	*/
	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);

	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
	    nbDupls = bind->dupls->nbItems;
	} else {
	    dupls = NULL;
	    nbDupls = 0;
	}
	if (bind->nodeTable != NULL) {
	    nbNodeTable = bind->nbNodes;
	} else {
	    nbNodeTable = 0;
	}

	if ((nbNodeTable == 0) && (nbDupls == 0)) {
	    /*
	    * Transfer all IDC target-nodes to the IDC node-table.
	    */
	    bind->nodeTable =
		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
	    bind->sizeNodes = matcher->targets->sizeItems;
	    bind->nbNodes = matcher->targets->nbItems;

	    matcher->targets->items = NULL;
	    matcher->targets->sizeItems = 0;
	    matcher->targets->nbItems = 0;
	} else {
	    /*
	    * Compare the key-sequences and add to the IDC node-table.
	    */
	    nbTargets = matcher->targets->nbItems;
	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
	    nbFields = matcher->aidc->def->nbFields;
	    i = 0;
	    do {
		keys = targets[i]->keys;
		if (nbDupls) {
		    /*
		    * Search in already found duplicates first.
		    */
		    j = 0;
		    do {
			if (nbFields == 1) {
			    res = xmlSchemaAreValuesEqual(keys[0]->val,
				dupls[j]->keys[0]->val);
			    if (res == -1)
				goto internal_error;
			    if (res == 1) {
				/*
				* Equal key-sequence.
				*/
				goto next_target;
			    }
			} else {
			    res = 0;
			    ntkeys = dupls[j]->keys;
			    for (k = 0; k < nbFields; k++) {
				res = xmlSchemaAreValuesEqual(keys[k]->val,
				    ntkeys[k]->val);
				if (res == -1)
				    goto internal_error;
				if (res == 0) {
				    /*
				    * One of the keys differs.
				    */
				    break;
				}
			    }
			    if (res == 1) {
				/*
				* Equal key-sequence found.
				*/
				goto next_target;
			    }
			}
			j++;
		    } while (j < nbDupls);
		}
		if (nbNodeTable) {
		    j = 0;
		    do {
			if (nbFields == 1) {
			    res = xmlSchemaAreValuesEqual(keys[0]->val,
				bind->nodeTable[j]->keys[0]->val);
			    if (res == -1)
				goto internal_error;
			    if (res == 0) {
				/*
				* The key-sequence differs.
				*/
				goto next_node_table_entry;
			    }
			} else {
			    res = 0;
			    ntkeys = bind->nodeTable[j]->keys;
			    for (k = 0; k < nbFields; k++) {
				res = xmlSchemaAreValuesEqual(keys[k]->val,
				    ntkeys[k]->val);
				if (res == -1)
				    goto internal_error;
				if (res == 0) {
				    /*
				    * One of the keys differs.
				    */
				    goto next_node_table_entry;
				}
			    }
			}
			/*
			* Add the duplicate to the list of duplicates.
			*/
			if (bind->dupls == NULL) {
			    bind->dupls = xmlSchemaItemListCreate();
			    if (bind->dupls == NULL)
				goto internal_error;
			}
			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
			    goto internal_error;
			/*
			* Remove the duplicate entry from the IDC node-table.
			*/
			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
			bind->nbNodes--;

			goto next_target;

next_node_table_entry:
			j++;
		    } while (j < nbNodeTable);
		}
		/*
		* If everything is fine, then add the IDC target-node to
		* the IDC node-table.
		*/
		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
		    goto internal_error;

next_target:
		i++;
	    } while (i < nbTargets);
	}
	matcher = matcher->next;
    }
    return(0);

internal_error:
    return(-1);
}


xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
				  xmlSchemaAttributeGroupPtr attrGr)
{
    if ((attrGr->attrUses == NULL) ||
	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
	return(0);

    attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
    if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
	return(-1);
    return(0);
}


xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
		       xmlSchemaTypePtr typeB)
{
    /*
    * TODO: This should implement component-identity
    * in the future.
    */
    if ((typeA == NULL) || (typeB == NULL))
	return (0);
    return (typeA == typeB);
}


xmlIOFTPClose (void * context) {
    return ( xmlNanoFTPClose(context) );
}


xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
				xmlSchemaSchemaRelationPtr rel)
{
    xmlSchemaSchemaRelationPtr cur = bucket->relations;

    if (cur == NULL) {
	bucket->relations = rel;
	return;
    }
    while (cur->next != NULL)
	cur = cur->next;
    cur->next = rel;
}


xmlSchemaItemListClear(xmlSchemaItemListPtr list)
{
    if (list->items != NULL) {
	xmlFree(list->items);
	list->items = NULL;
    }
    list->nbItems = 0;
    list->sizeItems = 0;
}


xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
{
    int i;
    xmlSchemaAttrInfoPtr attr;

    if (vctxt->nbAttrInfos == 0)
	return;
    for (i = 0; i < vctxt->nbAttrInfos; i++) {
	attr = vctxt->attrInfos[i];
	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
	    if (attr->localName != NULL)
		xmlFree((xmlChar *) attr->localName);
	    if (attr->nsName != NULL)
		xmlFree((xmlChar *) attr->nsName);
	}
	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
	    if (attr->value != NULL)
		xmlFree((xmlChar *) attr->value);
	}
	if (attr->val != NULL) {
	    xmlSchemaFreeValue(attr->val);
	    attr->val = NULL;
	}
	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
    }
    vctxt->nbAttrInfos = 0;
}


static xmlChar *
xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
    xmlChar buf[XML_MAX_NAMELEN + 5];
    int len = 0, l;
    int c;

    /*
     * Handler for more complex cases
     */
    c = CUR_CHAR(l);
    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
        (c == '[') || (c == ']') || (c == '@') || /* accelerators */
        (c == '*') || /* accelerators */
	(!IS_LETTER(c) && (c != '_') &&
         ((!qualified) || (c != ':')))) {
	return(NULL);
    }

    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
            (c == '.') || (c == '-') ||
	    (c == '_') || ((qualified) && (c == ':')) ||
	    (IS_COMBINING(c)) ||
	    (IS_EXTENDER(c)))) {
	COPY_BUF(l,buf,len,c);
	NEXTL(l);
	c = CUR_CHAR(l);
	if (len >= XML_MAX_NAMELEN) {
	    /*
	     * Okay someone managed to make a huge name, so he's ready to pay
	     * for the processing speed.
	     */
	    xmlChar *buffer;
	    int max = len * 2;

            if (len > XML_MAX_NAME_LENGTH) {
                XP_ERRORNULL(XPATH_EXPR_ERROR);
            }
	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
	    if (buffer == NULL) {
		XP_ERRORNULL(XPATH_MEMORY_ERROR);
	    }
	    memcpy(buffer, buf, len);
	    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
		   (c == '.') || (c == '-') ||
		   (c == '_') || ((qualified) && (c == ':')) ||
		   (IS_COMBINING(c)) ||
		   (IS_EXTENDER(c))) {
		if (len + 10 > max) {
                    if (max > XML_MAX_NAME_LENGTH) {
                        XP_ERRORNULL(XPATH_EXPR_ERROR);
                    }
		    max *= 2;
		    buffer = (xmlChar *) xmlRealloc(buffer,
			                            max * sizeof(xmlChar));
		    if (buffer == NULL) {
			XP_ERRORNULL(XPATH_MEMORY_ERROR);
		    }
		}
		COPY_BUF(l,buffer,len,c);
		NEXTL(l);
		c = CUR_CHAR(l);
	    }
	    buffer[len] = 0;
	    return(buffer);
	}
    }
    if (len == 0)
	return(NULL);


xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
    if ((xmlParserInputBufferCreateFilenameValue)) {
		return xmlParserInputBufferCreateFilenameValue(URI, enc);
	}
	return __xmlParserInputBufferCreateFilename(URI, enc);
}


xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
                          xmlNodePtr node, int topLevel)
{
    xmlSchemaTypePtr type, ctxtType;
    xmlNodePtr child = NULL;
    const xmlChar *name = NULL;
    xmlAttrPtr attr;
    const xmlChar *attrValue;
#ifdef ENABLE_NAMED_LOCALS
    char buf[40];
#endif
    int final = 0, block = 0, hasRestrictionOrExtension = 0;

    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
        return (NULL);

    ctxtType = ctxt->ctxtType;

    if (topLevel) {
	attr = xmlSchemaGetPropNode(node, "name");
	if (attr == NULL) {
	    xmlSchemaPMissingAttrErr(ctxt,
		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
	    return (NULL);
	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
	    return (NULL);
	}
    }

    if (topLevel == 0) {
	/*
	* Parse as local complex type definition.
	*/
#ifdef ENABLE_NAMED_LOCALS
        snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
	type = xmlSchemaAddType(ctxt, schema,
	    XML_SCHEMA_TYPE_COMPLEX,
	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
	    ctxt->targetNamespace, node, 0);
#else
	type = xmlSchemaAddType(ctxt, schema,
	    XML_SCHEMA_TYPE_COMPLEX,
	    NULL, ctxt->targetNamespace, node, 0);
#endif
	if (type == NULL)
	    return (NULL);
	name = type->name;
	type->node = node;
	type->type = XML_SCHEMA_TYPE_COMPLEX;
	/*
	* TODO: We need the target namespace.
	*/
    } else {
	/*
	* Parse as global complex type definition.
	*/
	type = xmlSchemaAddType(ctxt, schema,
	    XML_SCHEMA_TYPE_COMPLEX,
	    name, ctxt->targetNamespace, node, 1);
	if (type == NULL)
	    return (NULL);
	type->node = node;
	type->type = XML_SCHEMA_TYPE_COMPLEX;
	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
    }
    type->targetNamespace = ctxt->targetNamespace;
    /*
    * Handle attributes.
    */
    attr = node->properties;
    while (attr != NULL) {
	if (attr->ns == NULL) {
	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
		/*
		* Attribute "id".
		*/
		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
		/*
		* Attribute "mixed".
		*/
		if (xmlSchemaPGetBoolNodeValue(ctxt,
			NULL, (xmlNodePtr) attr))
		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
	    } else if (topLevel) {
		/*
		* Attributes of global complex type definitions.
		*/
		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
		    /* Pass. */
		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
		    /*
		    * Attribute "abstract".
		    */
		    if (xmlSchemaPGetBoolNodeValue(ctxt,
			    NULL, (xmlNodePtr) attr))
			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
		    /*
		    * Attribute "final".
		    */
		    attrValue = xmlSchemaGetNodeContent(ctxt,
			(xmlNodePtr) attr);
		    if (xmlSchemaPValAttrBlockFinal(attrValue,
			&(type->flags),
			-1,
			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
			-1, -1, -1) != 0)
		    {
			xmlSchemaPSimpleTypeErr(ctxt,
			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
			    NULL, (xmlNodePtr) attr, NULL,
			    "(#all | List of (extension | restriction))",
			    attrValue, NULL, NULL, NULL);
		    } else
			final = 1;
		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
		    /*
		    * Attribute "block".
		    */
		    attrValue = xmlSchemaGetNodeContent(ctxt,
			(xmlNodePtr) attr);
		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
			-1,
			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
			-1, -1, -1) != 0) {
			xmlSchemaPSimpleTypeErr(ctxt,
			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
			    NULL, (xmlNodePtr) attr, NULL,
			    "(#all | List of (extension | restriction)) ",
			    attrValue, NULL, NULL, NULL);
		    } else
			block = 1;
		} else {
			xmlSchemaPIllegalAttrErr(ctxt,
			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
		}
	    } else {
		xmlSchemaPIllegalAttrErr(ctxt,
		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
	    }
	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
	    xmlSchemaPIllegalAttrErr(ctxt,
		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
	}
	attr = attr->next;
    }
    if (! block) {
	/*
	* Apply default "block" values.
	*/
	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
    }
    if (! final) {
	/*
	* Apply default "block" values.
	*/
	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
    }
    /*
    * And now for the children...
    */
    child = node->children;
    if (IS_SCHEMA(child, "annotation")) {
        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
        child = child->next;
    }
    ctxt->ctxtType = type;
    if (IS_SCHEMA(child, "simpleContent")) {
	/*
	* <complexType><simpleContent>...
	* 3.4.3 : 2.2
	* Specifying mixed='true' when the <simpleContent>
	* alternative is chosen has no effect
	*/
	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
        xmlSchemaParseSimpleContent(ctxt, schema, child,
	    &hasRestrictionOrExtension);
        child = child->next;
    } else if (IS_SCHEMA(child, "complexContent")) {
	/*
	* <complexType><complexContent>...
	*/
	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
        xmlSchemaParseComplexContent(ctxt, schema, child,
	    &hasRestrictionOrExtension);
        child = child->next;
    } else {
	/*
	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
	*
	* SPEC
	* "...the third alternative (neither <simpleContent> nor
	* <complexContent>) is chosen. This case is understood as shorthand
	* for complex content restricting the `ur-type definition`, and the
	* details of the mappings should be modified as necessary.
	*/
	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
	/*
	* Parse model groups.
	*/
        if (IS_SCHEMA(child, "all")) {
            type->subtypes = (xmlSchemaTypePtr)
		xmlSchemaParseModelGroup(ctxt, schema, child,
		    XML_SCHEMA_TYPE_ALL, 1);
            child = child->next;
        } else if (IS_SCHEMA(child, "choice")) {
            type->subtypes = (xmlSchemaTypePtr)
		xmlSchemaParseModelGroup(ctxt, schema, child,
		    XML_SCHEMA_TYPE_CHOICE, 1);
            child = child->next;
        } else if (IS_SCHEMA(child, "sequence")) {
            type->subtypes = (xmlSchemaTypePtr)
		xmlSchemaParseModelGroup(ctxt, schema, child,
		    XML_SCHEMA_TYPE_SEQUENCE, 1);
            child = child->next;
        } else if (IS_SCHEMA(child, "group")) {
            type->subtypes = (xmlSchemaTypePtr)
		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
	    /*
	    * Note that the reference will be resolved in
	    * xmlSchemaResolveTypeReferences();
	    */
            child = child->next;
        }
	/*
	* Parse attribute decls/refs.
	*/
        if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
	    (xmlSchemaItemListPtr *) &(type->attrUses),
	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
	    return(NULL);
	/*
	* Parse attribute wildcard.
	*/
	if (IS_SCHEMA(child, "anyAttribute")) {
	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
	    child = child->next;
	}
    }
    if (child != NULL) {
	xmlSchemaPContentErr(ctxt,
	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
	    NULL, node, child,
	    NULL, "(annotation?, (simpleContent | complexContent | "
	    "((group | all | choice | sequence)?, ((attribute | "
	    "attributeGroup)*, anyAttribute?))))");
    }
    /*
    * REDEFINE: SPEC src-redefine (5)
    */
    if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
	    NULL, node, "This is a redefinition, thus the "
	    "<complexType> must have a <restriction> or <extension> "
	    "grand-child", NULL);
    }
    ctxt->ctxtType = ctxtType;
    return (type);
}


xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
			xmlSchemaAttrInfoPtr iattr,
			xmlSchemaTypePtr *localType,
			xmlSchemaElementPtr elemDecl)
{
    int ret = 0;
    /*
    * cvc-elt (3.3.4) : (4)
    * AND
    * Schema-Validity Assessment (Element) (cvc-assess-elt)
    *   (1.2.1.2.1) - (1.2.1.2.4)
    * Handle 'xsi:type'.
    */
    if (localType == NULL)
	return (-1);
    *localType = NULL;
    if (iattr == NULL)
	return (0);
    else {
	const xmlChar *nsName = NULL, *local = NULL;
	/*
	* TODO: We should report a *warning* that the type was overriden
	* by the instance.
	*/
	ACTIVATE_ATTRIBUTE(iattr);
	/*
	* (cvc-elt) (3.3.4) : (4.1)
	* (cvc-assess-elt) (1.2.1.2.2)
	*/
	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
	    &nsName, &local);
	if (ret != 0) {
	    if (ret < 0) {
		VERROR_INT("xmlSchemaValidateElementByDeclaration",
		    "calling xmlSchemaQNameExpand() to validate the "
		    "attribute 'xsi:type'");
		goto internal_error;
	    }
	    goto exit;
	}
	/*
	* (cvc-elt) (3.3.4) : (4.2)
	* (cvc-assess-elt) (1.2.1.2.3)
	*/
	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
	if (*localType == NULL) {
	    xmlChar *str = NULL;

	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
		XML_SCHEMAV_CVC_ELT_4_2, NULL,
		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
		"The QName value '%s' of the xsi:type attribute does not "
		"resolve to a type definition",
		xmlSchemaFormatQName(&str, nsName, local), NULL);
	    FREE_AND_NULL(str);
	    ret = vctxt->err;
	    goto exit;
	}
	if (elemDecl != NULL) {
	    int set = 0;

	    /*
	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
	    * "The `local type definition` must be validly
	    * derived from the {type definition} given the union of
	    * the {disallowed substitutions} and the {type definition}'s
	    * {prohibited substitutions}, as defined in
	    * Type Derivation OK (Complex) ($3.4.6)
	    * (if it is a complex type definition),
	    * or given {disallowed substitutions} as defined in Type
	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
	    * definition)."
	    *
	    * {disallowed substitutions}: the "block" on the element decl.
	    * {prohibited substitutions}: the "block" on the type def.
	    */
	    /*
	    * OPTIMIZE TODO: We could map types already evaluated
	    * to be validly derived from other types to avoid checking
	    * this over and over for the same types.
	    */
	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
		(elemDecl->subtypes->flags &
		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
		set |= SUBSET_EXTENSION;

	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
		(elemDecl->subtypes->flags &
		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
		set |= SUBSET_RESTRICTION;

	    /*
	    * REMOVED and CHANGED since this produced a parser context
	    * which adds to the string dict of the schema. So this would
	    * change the schema and we don't want this. We don't need
	    * the parser context anymore.
	    *
	    * if ((vctxt->pctxt == NULL) &&
	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
	    *	    return (-1);
	    */

	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
		elemDecl->subtypes, set) != 0) {
		xmlChar *str = NULL;

		xmlSchemaCustomErr(ACTXT_CAST vctxt,
		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
		    "The type definition '%s', specified by xsi:type, is "
		    "blocked or not validly derived from the type definition "
		    "of the element declaration",
		    xmlSchemaFormatQName(&str,
			(*localType)->targetNamespace,
			(*localType)->name),
		    NULL);
		FREE_AND_NULL(str);
		ret = vctxt->err;
		*localType = NULL;
	    }
	}
    }
exit:
    ACTIVATE_ELEM;
    return (ret);
internal_error:
    ACTIVATE_ELEM;
    return (-1);
}


xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
{
    if (ctxt == NULL)
        return(-1);
    return(ctxt->err == 0);
}


xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
			    xmlSchemaWildcardPtr completeWild,
			    xmlSchemaWildcardPtr curWild)
{
    xmlSchemaWildcardNsPtr cur, curB, tmp;

    /*
    * 1 If O1 and O2 are the same value, then that value must be the
    * value.
    */
    if ((completeWild->any == curWild->any) &&
	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {

	if ((completeWild->negNsSet == NULL) ||
	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {

	    if (completeWild->nsSet != NULL) {
		int found = 0;

		/*
		* Check equality of sets.
		*/
		cur = completeWild->nsSet;
		while (cur != NULL) {
		    found = 0;
		    curB = curWild->nsSet;
		    while (curB != NULL) {
			if (cur->value == curB->value) {
			    found = 1;
			    break;
			}
			curB = curB->next;
		    }
		    if (!found)
			break;
		    cur = cur->next;
		}
		if (found)
		    return(0);
	    } else
		return(0);
	}
    }
    /*
    * 2 If either O1 or O2 is any, then any must be the value
    */
    if (completeWild->any != curWild->any) {
	if (completeWild->any == 0) {
	    completeWild->any = 1;
	    if (completeWild->nsSet != NULL) {
		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
		completeWild->nsSet = NULL;
	    }
	    if (completeWild->negNsSet != NULL) {
		xmlFree(completeWild->negNsSet);
		completeWild->negNsSet = NULL;
	    }
	}
	return (0);
    }
    /*
    * 3 If both O1 and O2 are sets of (namespace names or `absent`),
    * then the union of those sets must be the value.
    */
    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
	int found;
	xmlSchemaWildcardNsPtr start;

	cur = curWild->nsSet;
	start = completeWild->nsSet;
	while (cur != NULL) {
	    found = 0;
	    curB = start;
	    while (curB != NULL) {
		if (cur->value == curB->value) {
		    found = 1;
		    break;
		}
		curB = curB->next;
	    }
	    if (!found) {
		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
		if (tmp == NULL)
		    return (-1);
		tmp->value = cur->value;
		tmp->next = completeWild->nsSet;
		completeWild->nsSet = tmp;
	    }
	    cur = cur->next;
	}

	return(0);
    }
    /*
    * 4 If the two are negations of different values (namespace names
    * or `absent`), then a pair of not and `absent` must be the value.
    */
    if ((completeWild->negNsSet != NULL) &&
	(curWild->negNsSet != NULL) &&
	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
	completeWild->negNsSet->value = NULL;

	return(0);
    }
    /*
     * 5.
     */
    if (((completeWild->negNsSet != NULL) &&
	(completeWild->negNsSet->value != NULL) &&
	(curWild->nsSet != NULL)) ||
	((curWild->negNsSet != NULL) &&
	(curWild->negNsSet->value != NULL) &&
	(completeWild->nsSet != NULL))) {

	int nsFound, absentFound = 0;

	if (completeWild->nsSet != NULL) {
	    cur = completeWild->nsSet;
	    curB = curWild->negNsSet;
	} else {
	    cur = curWild->nsSet;
	    curB = completeWild->negNsSet;
	}
	nsFound = 0;
	while (cur != NULL) {
	    if (cur->value == NULL)
		absentFound = 1;
	    else if (cur->value == curB->value)
		nsFound = 1;
	    if (nsFound && absentFound)
		break;
	    cur = cur->next;
	}

	if (nsFound && absentFound) {
	    /*
	    * 5.1 If the set S includes both the negated namespace
	    * name and `absent`, then any must be the value.
	    */
	    completeWild->any = 1;
	    if (completeWild->nsSet != NULL) {
		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
		completeWild->nsSet = NULL;
	    }
	    if (completeWild->negNsSet != NULL) {
		xmlFree(completeWild->negNsSet);
		completeWild->negNsSet = NULL;
	    }
	} else if (nsFound && (!absentFound)) {
	    /*
	    * 5.2 If the set S includes the negated namespace name
	    * but not `absent`, then a pair of not and `absent` must
	    * be the value.
	    */
	    if (completeWild->nsSet != NULL) {
		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
		completeWild->nsSet = NULL;
	    }
	    if (completeWild->negNsSet == NULL) {
		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
		if (completeWild->negNsSet == NULL)
		    return (-1);
	    }
	    completeWild->negNsSet->value = NULL;
	} else if ((!nsFound) && absentFound) {
	    /*
	    * 5.3 If the set S includes `absent` but not the negated
	    * namespace name, then the union is not expressible.
	    */
	    xmlSchemaPErr(ctxt, completeWild->node,
		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
		"The union of the wilcard is not expressible.\n",
		NULL, NULL);
	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
	} else if ((!nsFound) && (!absentFound)) {
	    /*
	    * 5.4 If the set S does not include either the negated namespace
	    * name or `absent`, then whichever of O1 or O2 is a pair of not
	    * and a namespace name must be the value.
	    */
	    if (completeWild->negNsSet == NULL) {
		if (completeWild->nsSet != NULL) {
		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
		    completeWild->nsSet = NULL;
		}
		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
		if (completeWild->negNsSet == NULL)
		    return (-1);
		completeWild->negNsSet->value = curWild->negNsSet->value;
	    }
	}
	return (0);
    }
    /*
     * 6.
     */
    if (((completeWild->negNsSet != NULL) &&
	(completeWild->negNsSet->value == NULL) &&
	(curWild->nsSet != NULL)) ||
	((curWild->negNsSet != NULL) &&
	(curWild->negNsSet->value == NULL) &&
	(completeWild->nsSet != NULL))) {

	if (completeWild->nsSet != NULL) {
	    cur = completeWild->nsSet;
	} else {
	    cur = curWild->nsSet;
	}
	while (cur != NULL) {
	    if (cur->value == NULL) {
		/*
		* 6.1 If the set S includes `absent`, then any must be the
		* value.
		*/
		completeWild->any = 1;
		if (completeWild->nsSet != NULL) {
		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
		    completeWild->nsSet = NULL;
		}
		if (completeWild->negNsSet != NULL) {
		    xmlFree(completeWild->negNsSet);
		    completeWild->negNsSet = NULL;
		}
		return (0);
	    }
	    cur = cur->next;
	}
	if (completeWild->negNsSet == NULL) {
	    /*
	    * 6.2 If the set S does not include `absent`, then a pair of not
	    * and `absent` must be the value.
	    */
	    if (completeWild->nsSet != NULL) {
		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
		completeWild->nsSet = NULL;
	    }
	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
	    if (completeWild->negNsSet == NULL)
		return (-1);
	    completeWild->negNsSet->value = NULL;
	}
	return (0);
    }
    return (0);

}


xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
    xmlParserInputBufferPtr ret;

    if (fd < 0) return(NULL);

    ret = xmlAllocParserInputBuffer(enc);
    if (ret != NULL) {
        ret->context = (void *) (long) fd;
	ret->readcallback = xmlFdRead;
	ret->closecallback = xmlFdClose;
    }

    return(ret);
}


xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
		  int nodeType, const xmlChar *value, int len,
		  int mode, int *consumed)
{
    /*
    * Unfortunately we have to duplicate the text sometimes.
    * OPTIMIZE: Maybe we could skip it, if:
    *   1. content type is simple
    *   2. whitespace is "collapse"
    *   3. it consists of whitespace only
    *
    * Process character content.
    */
    if (consumed != NULL)
	*consumed = 0;
    if (INODE_NILLED(vctxt->inode)) {
	/*
	* SPEC cvc-elt (3.3.4 - 3.2.1)
	* "The element information item must have no character or
	* element information item [children]."
	*/
	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
	    "Neither character nor element content is allowed "
	    "because the element is 'nilled'");
	return (vctxt->err);
    }
    /*
    * SPEC (2.1) "If the {content type} is empty, then the
    * element information item has no character or element
    * information item [children]."
    */
    if (vctxt->inode->typeDef->contentType ==
	    XML_SCHEMA_CONTENT_EMPTY) {
	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
	    "Character content is not allowed, "
	    "because the content type is empty");
	return (vctxt->err);
    }

    if (vctxt->inode->typeDef->contentType ==
	    XML_SCHEMA_CONTENT_ELEMENTS) {
	if ((nodeType != XML_TEXT_NODE) ||
	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
	    /*
	    * SPEC cvc-complex-type (2.3)
	    * "If the {content type} is element-only, then the
	    * element information item has no character information
	    * item [children] other than those whose [character
	    * code] is defined as a white space in [XML 1.0 (Second
	    * Edition)]."
	    */
	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
		"Character content other than whitespace is not allowed "
		"because the content type is 'element-only'");
	    return (vctxt->err);
	}
	return (0);
    }

    if ((value == NULL) || (value[0] == 0))
	return (0);
    /*
    * Save the value.
    * NOTE that even if the content type is *mixed*, we need the
    * *initial value* for default/fixed value constraints.
    */
    if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
	((vctxt->inode->decl == NULL) ||
	(vctxt->inode->decl->value == NULL)))
	return (0);

    if (vctxt->inode->value == NULL) {
	/*
	* Set the value.
	*/
	switch (mode) {
	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
		/*
		* When working on a tree.
		*/
		vctxt->inode->value = value;
		break;
	    case XML_SCHEMA_PUSH_TEXT_CREATED:
		/*
		* When working with the reader.
		* The value will be freed by the element info.
		*/
		vctxt->inode->value = value;
		if (consumed != NULL)
		    *consumed = 1;
		vctxt->inode->flags |=
		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
		break;
	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
		/*
		* When working with SAX.
		* The value will be freed by the element info.
		*/
		if (len != -1)
		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
		else
		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
		vctxt->inode->flags |=
		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
		break;
	    default:
		break;
	}
    } else {
	if (len < 0)
	    len = xmlStrlen(value);
	/*
	* Concat the value.
	*/
	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
	    vctxt->inode->value = BAD_CAST xmlStrncat(
		(xmlChar *) vctxt->inode->value, value, len);
	} else {
	    vctxt->inode->value =
		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
	}
    }

    return (0);
}


xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
			  xmlSchemaTypePtr type)
{
    int ret;
    /*
    * Complex Type Definition Properties Correct
    */
    ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
    if (ret != 0)
	return (ret);
    if (WXS_IS_EXTENSION(type))
	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
    else
	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
    return (ret);
}


xmlXzfileOpen (const char *filename) {
    char *unescaped;
    void *retval;

    retval = xmlXzfileOpen_real(filename);
    if (retval == NULL) {
	unescaped = xmlURIUnescapeString(filename, 0, NULL);
	if (unescaped != NULL) {
	    retval = xmlXzfileOpen_real(unescaped);
	}
	xmlFree(unescaped);
    }

    return retval;
}


xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
{
    switch (item->type) {
	case XML_SCHEMA_TYPE_ELEMENT:
	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
	case XML_SCHEMA_TYPE_ATTRIBUTE:
	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
	case XML_SCHEMA_TYPE_COMPLEX:
	case XML_SCHEMA_TYPE_SIMPLE:
	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
	case XML_SCHEMA_TYPE_ANY:
	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
	    return (NULL);
	case XML_SCHEMA_TYPE_PARTICLE:
	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
	case XML_SCHEMA_TYPE_SEQUENCE:
	case XML_SCHEMA_TYPE_CHOICE:
	case XML_SCHEMA_TYPE_ALL:
	    return (NULL);
	case XML_SCHEMA_TYPE_GROUP:
	    return (NULL);
	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
	case XML_SCHEMA_TYPE_IDC_UNIQUE:
	case XML_SCHEMA_TYPE_IDC_KEY:
	case XML_SCHEMA_TYPE_IDC_KEYREF:
	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
	default:
	    return (NULL);
    }
}


xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
                          xmlNodePtr node, xmlSchemaTypeType parentType)
{
    xmlSchemaTypePtr type;
    xmlNodePtr child = NULL;
    xmlAttrPtr attr;

    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
        return (NULL);
    /* Not a component, don't create it. */
    type = ctxt->ctxtType;
    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;

    /*
    * Check for illegal attributes.
    */
    attr = node->properties;
    while (attr != NULL) {
	if (attr->ns == NULL) {
	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
		xmlSchemaPIllegalAttrErr(ctxt,
		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
	    }
	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
	    xmlSchemaPIllegalAttrErr(ctxt,
		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
	}
	attr = attr->next;
    }
    /*
    * Extract and validate attributes.
    */
    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
    /*
    * Attribute
    */
    /*
    * Extract the base type. The "base" attribute is mandatory if inside
    * a complex type or if redefining.
    *
    * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
    * among its [children]), the simple type definition which is
    * the {content type} of the type definition `resolved` to by
    * the `actual value` of the base [attribute]"
    */
    if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
	&(type->baseNs), &(type->base)) == 0)
    {
	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
	    xmlSchemaPMissingAttrErr(ctxt,
		XML_SCHEMAP_S4S_ATTR_MISSING,
		NULL, node, "base", NULL);
	} else if ((ctxt->isRedefine) &&
	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
	{
	    if (type->base == NULL) {
		xmlSchemaPMissingAttrErr(ctxt,
		    XML_SCHEMAP_S4S_ATTR_MISSING,
		    NULL, node, "base", NULL);
	    } else if ((! xmlStrEqual(type->base, type->name)) ||
		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
	    {
		xmlChar *str1 = NULL, *str2 = NULL;
		/*
		* REDEFINE: SPEC src-redefine (5)
		* "Within the [children], each <simpleType> must have a
		* <restriction> among its [children] ... the `actual value` of
		* whose base [attribute] must be the same as the `actual value`
		* of its own name attribute plus target namespace;"
		*/
		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
		    NULL, node, "This is a redefinition, but the QName "
		    "value '%s' of the 'base' attribute does not match the "
		    "type's designation '%s'",
		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
		    xmlSchemaFormatQName(&str2, type->targetNamespace,
			type->name), NULL);
		FREE_AND_NULL(str1);
		FREE_AND_NULL(str2);
		/* Avoid confusion and erase the values. */
		type->base = NULL;
		type->baseNs = NULL;
	    }
	}
    }
    /*
    * And now for the children...
    */
    child = node->children;
    if (IS_SCHEMA(child, "annotation")) {
	/*
	* Add the annotation to the simple type ancestor.
	*/
	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
	    xmlSchemaParseAnnotation(ctxt, child, 1));
        child = child->next;
    }
    if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
	/*
	* Corresponds to <simpleType><restriction><simpleType>.
	*/
	if (IS_SCHEMA(child, "simpleType")) {
	    if (type->base != NULL) {
		/*
		* src-restriction-base-or-simpleType
		* Either the base [attribute] or the simpleType [child] of the
		* <restriction> element must be present, but not both.
		*/
		xmlSchemaPContentErr(ctxt,
		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
		    NULL, node, child,
		    "The attribute 'base' and the <simpleType> child are "
		    "mutually exclusive", NULL);
	    } else {
		type->baseType = (xmlSchemaTypePtr)
		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
	    }
	    child = child->next;
	} else if (type->base == NULL) {
	    xmlSchemaPContentErr(ctxt,
		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
		NULL, node, child,
		"Either the attribute 'base' or a <simpleType> child "
		"must be present", NULL);
	}
    } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
	/*
	* Corresponds to <complexType><complexContent><restriction>...
	* followed by:
	*
	* Model groups <all>, <choice> and <sequence>.
	*/
	if (IS_SCHEMA(child, "all")) {
	    type->subtypes = (xmlSchemaTypePtr)
		xmlSchemaParseModelGroup(ctxt, schema, child,
		    XML_SCHEMA_TYPE_ALL, 1);
	    child = child->next;
	} else if (IS_SCHEMA(child, "choice")) {
	    type->subtypes = (xmlSchemaTypePtr)
		xmlSchemaParseModelGroup(ctxt,
		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
	    child = child->next;
	} else if (IS_SCHEMA(child, "sequence")) {
	    type->subtypes = (xmlSchemaTypePtr)
		xmlSchemaParseModelGroup(ctxt, schema, child,
		    XML_SCHEMA_TYPE_SEQUENCE, 1);
	    child = child->next;
	/*
	* Model group reference <group>.
	*/
	} else if (IS_SCHEMA(child, "group")) {
	    type->subtypes = (xmlSchemaTypePtr)
		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
	    /*
	    * Note that the reference will be resolved in
	    * xmlSchemaResolveTypeReferences();
	    */
	    child = child->next;
	}
    } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
	/*
	* Corresponds to <complexType><simpleContent><restriction>...
	*
	* "1.1 the simple type definition corresponding to the <simpleType>
	* among the [children] of <restriction> if there is one;"
	*/
	if (IS_SCHEMA(child, "simpleType")) {
	    /*
	    * We will store the to-be-restricted simple type in
	    * type->contentTypeDef *temporarily*.
	    */
	    type->contentTypeDef = (xmlSchemaTypePtr)
		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
	    if ( type->contentTypeDef == NULL)
		return (NULL);
	    child = child->next;
	}
    }

    if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
	xmlSchemaFacetPtr facet, lastfacet = NULL;
	/*
	* Corresponds to <complexType><simpleContent><restriction>...
	* <simpleType><restriction>...
	*/

	/*
	* Add the facets to the simple type ancestor.
	*/
	/*
	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
	* Simple Type Definition Schema Representation Constraint:
	* *Single Facet Value*
	*/
	while ((IS_SCHEMA(child, "minInclusive")) ||
	    (IS_SCHEMA(child, "minExclusive")) ||
	    (IS_SCHEMA(child, "maxInclusive")) ||
	    (IS_SCHEMA(child, "maxExclusive")) ||
	    (IS_SCHEMA(child, "totalDigits")) ||
	    (IS_SCHEMA(child, "fractionDigits")) ||
	    (IS_SCHEMA(child, "pattern")) ||
	    (IS_SCHEMA(child, "enumeration")) ||
	    (IS_SCHEMA(child, "whiteSpace")) ||
	    (IS_SCHEMA(child, "length")) ||
	    (IS_SCHEMA(child, "maxLength")) ||
	    (IS_SCHEMA(child, "minLength"))) {
	    facet = xmlSchemaParseFacet(ctxt, schema, child);
	    if (facet != NULL) {
		if (lastfacet == NULL)
		    type->facets = facet;
		else
		    lastfacet->next = facet;
		lastfacet = facet;
		lastfacet->next = NULL;
	    }
	    child = child->next;
	}
	/*
	* Create links for derivation and validation.
	*/
	if (type->facets != NULL) {
	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;

	    facet = type->facets;
	    do {
		facetLink = (xmlSchemaFacetLinkPtr)
		    xmlMalloc(sizeof(xmlSchemaFacetLink));
		if (facetLink == NULL) {
		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
		    xmlFree(facetLink);
		    return (NULL);
		}
		facetLink->facet = facet;
		facetLink->next = NULL;
		if (lastFacetLink == NULL)
		    type->facetSet = facetLink;
		else
		    lastFacetLink->next = facetLink;
		lastFacetLink = facetLink;
		facet = facet->next;
	    } while (facet != NULL);
	}
    }
    if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
	/*
	* Attribute uses/declarations.
	*/
	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
	    (xmlSchemaItemListPtr *) &(type->attrUses),
	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
	    return(NULL);
	/*
	* Attribute wildcard.
	*/
	if (IS_SCHEMA(child, "anyAttribute")) {
	    type->attributeWildcard =
		xmlSchemaParseAnyAttribute(ctxt, schema, child);
	    child = child->next;
	}
    }
    if (child != NULL) {
	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
	    xmlSchemaPContentErr(ctxt,
		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
		NULL, node, child, NULL,
		"annotation?, (group | all | choice | sequence)?, "
		"((attribute | attributeGroup)*, anyAttribute?))");
	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
	     xmlSchemaPContentErr(ctxt,
		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
		NULL, node, child, NULL,
		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
		"length | minLength | maxLength | enumeration | whiteSpace | "
		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
	} else {
	    /* Simple type */
	    xmlSchemaPContentErr(ctxt,
		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
		NULL, node, child, NULL,
		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
		"length | minLength | maxLength | enumeration | whiteSpace | "
		"pattern)*))");
	}
    }
    return (NULL);
}


xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
                  const xmlChar *name, const xmlChar *nsName,
		  int category, xmlNodePtr node)
{
    xmlSchemaIDCPtr ret = NULL;

    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
        return (NULL);

    ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
    if (ret == NULL) {
        xmlSchemaPErrMemory(ctxt,
	    "allocating an identity-constraint definition", NULL);
        return (NULL);
    }
    memset(ret, 0, sizeof(xmlSchemaIDC));
    /* The target namespace of the parent element declaration. */
    ret->targetNamespace = nsName;
    ret->name = name;
    ret->type = category;
    ret->node = node;

    WXS_ADD_GLOBAL(ctxt, ret);
    /*
    * Only keyrefs need to be fixup up.
    */
    if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
	WXS_ADD_PENDING(ctxt, ret);
    return (ret);
}


xmlSchemaGetComponentQName(xmlChar **buf,
			   void *item)
{
    return (xmlSchemaFormatQName(buf,
	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
}


xmlLoadExternalEntity(const char *URL, const char *ID,
                      xmlParserCtxtPtr ctxt) {
    if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) {
	char *canonicFilename;
	xmlParserInputPtr ret;

	canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL);
	if (canonicFilename == NULL) {
            xmlIOErrMemory("building canonical path\n");
	    return(NULL);
	}

	ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt);
	xmlFree(canonicFilename);
	return(ret);
    }
    return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
}


xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
    xmlOutputBufferPtr ret;

    if (fd < 0) return(NULL);

    ret = xmlAllocOutputBufferInternal(encoder);
    if (ret != NULL) {
        ret->context = (void *) (long) fd;
	ret->writecallback = xmlFdWrite;
	ret->closecallback = NULL;
    }

    return(ret);
}


xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
{
    if (type == NULL)
	return (0);
    if (WXS_IS_COMPLEX(type))
	return (0);
    if (type->type == XML_SCHEMA_TYPE_BASIC) {
	if (type->builtInType == valType)
	    return(1);
	return (0);
    } else
	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));

    return (0);
}