static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
								int combine)
	{
	const ASN1_TEMPLATE *tt = NULL;
	const ASN1_COMPAT_FUNCS *cf;
	const ASN1_EXTERN_FUNCS *ef;
	const ASN1_AUX *aux = it->funcs;
	ASN1_aux_cb *asn1_cb;
	ASN1_VALUE **pseqval;
	int i;
	if (aux && aux->asn1_cb)
		asn1_cb = aux->asn1_cb;
	else
		asn1_cb = 0;

	if (!combine) *pval = NULL;

#ifdef CRYPTO_MDEBUG
	if (it->sname)
		CRYPTO_push_info(it->sname);
#endif

	switch(it->itype)
		{

		case ASN1_ITYPE_EXTERN:
		ef = it->funcs;
		if (ef && ef->asn1_ex_new)
			{
			if (!ef->asn1_ex_new(pval, it))
				goto memerr;
			}
		break;

		case ASN1_ITYPE_COMPAT:
		cf = it->funcs;
		if (cf && cf->asn1_new) {
			*pval = cf->asn1_new();
			if (!*pval)
				goto memerr;
		}
		break;

		case ASN1_ITYPE_PRIMITIVE:
		if (it->templates)
			{
			if (!ASN1_template_new(pval, it->templates))
				goto memerr;
			}
		else if (!ASN1_primitive_new(pval, it))
				goto memerr;
		break;

		case ASN1_ITYPE_MSTRING:
		if (!ASN1_primitive_new(pval, it))
				goto memerr;
		break;

		case ASN1_ITYPE_CHOICE:
		if (asn1_cb)
			{
			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
			if (!i)
				goto auxerr;
			if (i==2)
				{
#ifdef CRYPTO_MDEBUG
				if (it->sname)
					CRYPTO_pop_info();
#endif
				return 1;
				}
			}
		if (!combine)
			{
			*pval = OPENSSL_malloc(it->size);
			if (!*pval)
				goto memerr;
			memset(*pval, 0, it->size);
			}
		asn1_set_choice_selector(pval, -1, it);
		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
				goto auxerr;
		break;

		case ASN1_ITYPE_NDEF_SEQUENCE:
		case ASN1_ITYPE_SEQUENCE:
		if (asn1_cb)
			{
			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
			if (!i)
				goto auxerr;
			if (i==2)
				{
#ifdef CRYPTO_MDEBUG
				if (it->sname)
					CRYPTO_pop_info();
#endif
				return 1;
				}
			}
		if (!combine)
			{
			*pval = OPENSSL_malloc(it->size);
			if (!*pval)
				goto memerr;
			memset(*pval, 0, it->size);
			asn1_do_lock(pval, 0, it);
			asn1_enc_init(pval, it);
			}
		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
			{
			pseqval = asn1_get_field_ptr(pval, tt);
			if (!ASN1_template_new(pseqval, tt))
				goto memerr;
			}
		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
				goto auxerr;
		break;
	}
#ifdef CRYPTO_MDEBUG
	if (it->sname) CRYPTO_pop_info();
#endif
	return 1;

	memerr:
	ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
	if (it->sname) CRYPTO_pop_info();
#endif
	return 0;

	auxerr:
	ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ASN1_R_AUX_ERROR);
	ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
	if (it->sname) CRYPTO_pop_info();
#endif
	return 0;

	}