xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
			 xmlSchemaBucketPtr rootBucket)
{
    xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
    xmlSchemaTreeItemPtr item, *items;
    int nbItems, i, ret = 0;
    xmlSchemaBucketPtr oldbucket = con->bucket;
    xmlSchemaElementPtr elemDecl;

#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;

    if ((con->pending == NULL) ||
	(con->pending->nbItems == 0))
	return(0);

    /*
    * Since xmlSchemaFixupComplexType() will create new particles
    * (local components), and those particle components need a bucket
    * on the constructor, we'll assure here that the constructor has
    * a bucket.
    * TODO: Think about storing locals _only_ on the main bucket.
    */
    if (con->bucket == NULL)
	con->bucket = rootBucket;

    /* TODO:
    * SPEC (src-redefine):
    * (6.2) "If it has no such self-reference, then all of the
    * following must be true:"

    * (6.2.2) The {model group} of the model group definition which
    * corresponds to it per XML Representation of Model Group
    * Definition Schema Components ($3.7.2) must be a `valid
    * restriction` of the {model group} of that model group definition
    * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
    */
    xmlSchemaCheckSRCRedefineFirst(pctxt);

    /*
    * Add global components to the schemata's hash tables.
    */
    xmlSchemaAddComponents(pctxt, rootBucket);

    pctxt->ctxtType = NULL;
    items = (xmlSchemaTreeItemPtr *) con->pending->items;
    nbItems = con->pending->nbItems;
    /*
    * Now that we have parsed *all* the schema document(s) and converted
    * them to schema components, we can resolve references, apply component
    * constraints, create the FSA from the content model, etc.
    */
    /*
    * Resolve references of..
    *
    * 1. element declarations:
    *   - the type definition
    *   - the substitution group affiliation
    * 2. simple/complex types:
    *   - the base type definition
    *   - the memberTypes of union types
    *   - the itemType of list types
    * 3. attributes declarations and attribute uses:
    *   - the type definition
    *   - if an attribute use, then the attribute declaration
    * 4. attribute group references:
    *   - the attribute group definition
    * 5. particles:
    *   - the term of the particle (e.g. a model group)
    * 6. IDC key-references:
    *   - the referenced IDC 'key' or 'unique' definition
    * 7. Attribute prohibitions which had a "ref" attribute.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
	    case XML_SCHEMA_TYPE_ELEMENT:
		xmlSchemaResolveElementReferences(
		    (xmlSchemaElementPtr) item, pctxt);
		FIXHFAILURE;
		break;
	    case XML_SCHEMA_TYPE_COMPLEX:
	    case XML_SCHEMA_TYPE_SIMPLE:
		xmlSchemaResolveTypeReferences(
		    (xmlSchemaTypePtr) item, pctxt);
		FIXHFAILURE;
		break;
	    case XML_SCHEMA_TYPE_ATTRIBUTE:
		xmlSchemaResolveAttrTypeReferences(
		    (xmlSchemaAttributePtr) item, pctxt);
		FIXHFAILURE;
		break;
	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
		xmlSchemaResolveAttrUseReferences(
		    (xmlSchemaAttributeUsePtr) item, pctxt);
		FIXHFAILURE;
		break;
	    case XML_SCHEMA_EXTRA_QNAMEREF:
		if ((WXS_QNAME_CAST item)->itemType ==
		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
		{
		    xmlSchemaResolveAttrGroupReferences(
			WXS_QNAME_CAST item, pctxt);
		}
		FIXHFAILURE;
		break;
	    case XML_SCHEMA_TYPE_SEQUENCE:
	    case XML_SCHEMA_TYPE_CHOICE:
	    case XML_SCHEMA_TYPE_ALL:
		xmlSchemaResolveModelGroupParticleReferences(pctxt,
		    WXS_MODEL_GROUP_CAST item);
		FIXHFAILURE;
		break;
	    case XML_SCHEMA_TYPE_IDC_KEY:
	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
	    case XML_SCHEMA_TYPE_IDC_KEYREF:
		xmlSchemaResolveIDCKeyReferences(
		    (xmlSchemaIDCPtr) item, pctxt);
		FIXHFAILURE;
		break;
	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
		/*
		* Handle attribue prohibition which had a
		* "ref" attribute.
		*/
		xmlSchemaResolveAttrUseProhibReferences(
		    WXS_ATTR_PROHIB_CAST item, pctxt);
		FIXHFAILURE;
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;

    /*
    * Now that all references are resolved we
    * can check for circularity of...
    * 1. the base axis of type definitions
    * 2. nested model group definitions
    * 3. nested attribute group definitions
    * TODO: check for circual substitution groups.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	/*
	* Let's better stop on the first error here.
	*/
	switch (item->type) {
	    case XML_SCHEMA_TYPE_COMPLEX:
	    case XML_SCHEMA_TYPE_SIMPLE:
		xmlSchemaCheckTypeDefCircular(
		    (xmlSchemaTypePtr) item, pctxt);
		FIXHFAILURE;
		if (pctxt->nberrors != 0)
		    goto exit_error;
		break;
	    case XML_SCHEMA_TYPE_GROUP:
		xmlSchemaCheckGroupDefCircular(
		    (xmlSchemaModelGroupDefPtr) item, pctxt);
		FIXHFAILURE;
		if (pctxt->nberrors != 0)
		    goto exit_error;
		break;
	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
		xmlSchemaCheckAttrGroupCircular(
		    (xmlSchemaAttributeGroupPtr) item, pctxt);
		FIXHFAILURE;
		if (pctxt->nberrors != 0)
		    goto exit_error;
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;
    /*
    * Model group definition references:
    * Such a reference is reflected by a particle at the component
    * level. Until now the 'term' of such particles pointed
    * to the model group definition; this was done, in order to
    * ease circularity checks. Now we need to set the 'term' of
    * such particles to the model group of the model group definition.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
	    case XML_SCHEMA_TYPE_SEQUENCE:
	    case XML_SCHEMA_TYPE_CHOICE:
		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
		    WXS_MODEL_GROUP_CAST item);
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;
    /*
    * Expand attribute group references of attribute group definitions.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
            case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
		    WXS_ATTR_GROUP_HAS_REFS(item))
		{
		    xmlSchemaAttributeGroupExpandRefs(pctxt,
			WXS_ATTR_GROUP_CAST item);
		    FIXHFAILURE;
		}
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;
    /*
    * First compute the variety of simple types. This is needed as
    * a seperate step, since otherwise we won't be able to detect
    * circular union types in all cases.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
            case XML_SCHEMA_TYPE_SIMPLE:
		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
			(xmlSchemaTypePtr) item);
		    FIXHFAILURE;
		}
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;
    /*
    * Detect circular union types. Note that this needs the variety to
    * be already computed.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
            case XML_SCHEMA_TYPE_SIMPLE:
		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
			(xmlSchemaTypePtr) item);
		    FIXHFAILURE;
		}
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;

    /*
    * Do the complete type fixup for simple types.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
            case XML_SCHEMA_TYPE_SIMPLE:
		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
		    FIXHFAILURE;
		}
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;
    /*
    * At this point we need build and check all simple types.
    */
    /*
    * Apply contraints for attribute declarations.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
	    case XML_SCHEMA_TYPE_ATTRIBUTE:
		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
		FIXHFAILURE;
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;
    /*
    * Apply constraints for attribute uses.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
			WXS_ATTR_USE_CAST item);
		    FIXHFAILURE;
		}
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;

    /*
    * Apply constraints for attribute group definitions.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
	    {
		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
		FIXHFAILURE;
	    }
	    break;
	default:
	    break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;

    /*
    * Apply constraints for redefinitions.
    */
    if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
	xmlSchemaCheckSRCRedefineSecond(pctxt);
    if (pctxt->nberrors != 0)
	goto exit_error;

    /*
    * Complex types are builded and checked.
    */
    for (i = 0; i < nbItems; i++) {
	item = con->pending->items[i];
	switch (item->type) {
	    case XML_SCHEMA_TYPE_COMPLEX:
		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
		    FIXHFAILURE;
		}
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;

    /*
    * The list could have changed, since xmlSchemaFixupComplexType()
    * will create particles and model groups in some cases.
    */
    items = (xmlSchemaTreeItemPtr *) con->pending->items;
    nbItems = con->pending->nbItems;

    /*
    * Apply some constraints for element declarations.
    */
    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
	    case XML_SCHEMA_TYPE_ELEMENT:
		elemDecl = (xmlSchemaElementPtr) item;

		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
		{
		    xmlSchemaCheckElementDeclComponent(
			(xmlSchemaElementPtr) elemDecl, pctxt);
		    FIXHFAILURE;
		}

#ifdef WXS_ELEM_DECL_CONS_ENABLED
		/*
		* Schema Component Constraint: Element Declarations Consistent
		* Apply this constraint to local types of element declarations.
		*/
		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
		{
		    xmlSchemaCheckElementDeclConsistent(pctxt,
			WXS_BASIC_CAST elemDecl,
			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
			NULL, NULL, 0);
		}
#endif
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;

    /*
    * Finally we can build the automaton from the content model of
    * complex types.
    */

    for (i = 0; i < nbItems; i++) {
	item = items[i];
	switch (item->type) {
	    case XML_SCHEMA_TYPE_COMPLEX:
		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
		/* FIXHFAILURE; */
		break;
	    default:
		break;
	}
    }
    if (pctxt->nberrors != 0)
	goto exit_error;
    /*
    * URGENT TODO: cos-element-consistent
    */
    goto exit;

exit_error:
    ret = pctxt->err;
    goto exit;

exit_failure:
    ret = -1;

exit:
    /*
    * Reset the constructor. This is needed for XSI acquisition, since
    * those items will be processed over and over again for every XSI
    * if not cleared here.
    */
    con->bucket = oldbucket;
    con->pending->nbItems = 0;
    if (con->substGroups != NULL) {
	xmlHashFree(con->substGroups,
	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
	con->substGroups = NULL;
    }
    if (con->redefs != NULL) {
	xmlSchemaRedefListFree(con->redefs);
	con->redefs = NULL;
    }
    return(ret);
}