int hdr_constructed, hdr_tag, hdr_class;
int hdr_constructed = 0, hdr_tag, hdr_class;
ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)	{	ASN1_TYPE *ret;	tag_exp_arg asn1_tags;	tag_exp_type *etmp;	int i, len;	unsigned char *orig_der = NULL, *new_der = NULL;	unsigned char *cpy_start, *p;	int cpy_len;	long hdr_len;	int hdr_constructed, hdr_tag, hdr_class;	int r;	asn1_tags.imp_tag = -1;	asn1_tags.imp_class = -1;	asn1_tags.format = ASN1_GEN_FORMAT_ASCII;	asn1_tags.exp_count = 0;	if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)		return NULL;	if ((asn1_tags.utype == V_ASN1_SEQUENCE) || (asn1_tags.utype == V_ASN1_SET))		{		if (!cnf)			{			ASN1err(ASN1_F_ASN1_GENERATE_V3, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);			return NULL;			}		ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);		}	else		ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);	if (!ret)		return NULL;	/* If no tagging return base type */	if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))		return ret;	/* Generate the encoding */	cpy_len = i2d_ASN1_TYPE(ret, &orig_der);	ASN1_TYPE_free(ret);	ret = NULL;	/* Set point to start copying for modified encoding */	cpy_start = orig_der;	/* Do we need IMPLICIT tagging? */	if (asn1_tags.imp_tag != -1)		{		/* If IMPLICIT we will replace the underlying tag */		/* Skip existing tag+len */		r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len);		if (r & 0x80)			goto err;		/* Update copy length */		cpy_len -= cpy_start - orig_der;		/* For IMPLICIT tagging the length should match the		 * original length and constructed flag should be		 * consistent.		 */		if (r & 0x1)			{			/* Indefinite length constructed */			hdr_constructed = 2;			hdr_len = 0;			}		else			/* Just retain constructed flag */			hdr_constructed = r & V_ASN1_CONSTRUCTED;		/* Work out new length with IMPLICIT tag: ignore constructed		 * because it will mess up if indefinite length		 */		len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);		}	else		len = cpy_len;	/* Work out length in any EXPLICIT, starting from end */	for(i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; i < asn1_tags.exp_count; i++, etmp--)		{		/* Content length: number of content octets + any padding */		len += etmp->exp_pad;		etmp->exp_len = len;		/* Total object length: length including new header */		len = ASN1_object_size(0, len, etmp->exp_tag);		}	/* Allocate buffer for new encoding */	new_der = OPENSSL_malloc(len);	/* Generate tagged encoding */	p = new_der;	/* Output explicit tags first */	for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; i++, etmp++)		{		ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,					etmp->exp_tag, etmp->exp_class);		if (etmp->exp_pad)			*p++ = 0;		}	/* If IMPLICIT, output tag */	if (asn1_tags.imp_tag != -1)		ASN1_put_object(&p, hdr_constructed, hdr_len,					asn1_tags.imp_tag, asn1_tags.imp_class);	/* Copy across original encoding */	memcpy(p, cpy_start, cpy_len);	p = new_der;	/* Obtain new ASN1_TYPE structure */	ret = d2i_ASN1_TYPE(NULL, &p, len);	err:	if (orig_der)		OPENSSL_free(orig_der);	if (new_der)		OPENSSL_free(new_der);	return ret;	}