PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_SKIP | SEC_ASN1_INNER | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
sec_asn1e_init_state_based_on_template (sec_asn1e_state *state){    PRBool isExplicit, is_string, may_stream, optional, universal;     PRBool disallowStreaming;    unsigned char tag_modifiers;    unsigned long encode_kind, under_kind;    unsigned long tag_number;    encode_kind = state->theTemplate->kind;    universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)		? PR_TRUE : PR_FALSE;    isExplicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;    encode_kind &= ~SEC_ASN1_EXPLICIT;    optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;    encode_kind &= ~SEC_ASN1_OPTIONAL;    PORT_Assert (!(isExplicit && universal));	/* bad templates */    may_stream = (encode_kind & SEC_ASN1_MAY_STREAM) ? PR_TRUE : PR_FALSE;    encode_kind &= ~SEC_ASN1_MAY_STREAM;    disallowStreaming = (encode_kind & SEC_ASN1_NO_STREAM) ? PR_TRUE : PR_FALSE;    encode_kind &= ~SEC_ASN1_NO_STREAM;    /* Just clear this to get it out of the way; we do not need it here */    encode_kind &= ~SEC_ASN1_DYNAMIC;    if( encode_kind & SEC_ASN1_CHOICE ) {      under_kind = SEC_ASN1_CHOICE;    } else    if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) ||         (!universal && !isExplicit)) {	const SEC_ASN1Template *subt;	void *src;	PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);	sec_asn1e_scrub_state (state);	if (encode_kind & SEC_ASN1_POINTER) {	    /*	     * XXX This used to PORT_Assert (encode_kind == SEC_ASN1_POINTER);	     * but that was too restrictive.  This needs to be fixed,	     * probably copying what the decoder now checks for, and	     * adding a big comment here to explain what the checks mean.	     */	    src = *(void **)state->src;	    state->place = afterPointer;	    if (src == NULL) {		/*		 * If this is optional, but NULL, then the field does		 * not need to be encoded.  In this case we are done;		 * we do not want to push a subtemplate.		 */		if (optional)		    return state;		/*		 * XXX this is an error; need to figure out		 * how to handle this		 */	    }	} else {	    src = state->src;	    if (encode_kind & SEC_ASN1_INLINE) {		/* check that there are no extraneous bits */		PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional);		state->place = afterInline;	    } else {		/*		 * Save the tag modifiers and tag number here before moving		 * on to the next state in case this is a member of a		 * SEQUENCE OF		 */		state->tag_modifiers = (unsigned char)		    (encode_kind & (SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK));		state->tag_number = (unsigned char)		    (encode_kind & SEC_ASN1_TAGNUM_MASK);				state->place = afterImplicit;		state->optional = optional;	    }	}	subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->src, PR_TRUE);	state = sec_asn1e_push_state (state->top, subt, src, PR_FALSE);	if (state == NULL)	    return NULL;	if (universal) {	    /*	     * This is a POINTER or INLINE; just init based on that	     * and we are done.	     */	    return sec_asn1e_init_state_based_on_template (state);	}	/*	 * This is an implicit, non-universal (meaning, application-private	 * or context-specific) field.  This results in a "magic" tag but	 * encoding based on the underlying type.  We pushed a new state	 * that is based on the subtemplate (the underlying type), but	 * now we will sort of alias it to give it some of our properties	 * (tag, optional status, etc.).	 */	under_kind = state->theTemplate->kind;	if (under_kind & SEC_ASN1_MAY_STREAM) {	    if (!disallowStreaming)	      may_stream = PR_TRUE;	    under_kind &= ~SEC_ASN1_MAY_STREAM;	}    } else {	under_kind = encode_kind;    }    /*     * Sanity check that there are no unwanted bits marked in under_kind.     * These bits were either removed above (after we recorded them) or     * they simply should not be found (signalling a bad/broken template).     * XXX is this the right set of bits to test here? (i.e. need to add     * or remove any?)     */    PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL				| SEC_ASN1_SKIP | SEC_ASN1_INNER				| SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM				| SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);    if (encode_kind & SEC_ASN1_ANY) {	PORT_Assert (encode_kind == under_kind);	tag_modifiers = 0;	tag_number = 0;	is_string = PR_TRUE;    } else {	tag_modifiers = (unsigned char)		(encode_kind & (SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK));	/*	 * XXX This assumes only single-octet identifiers.  To handle	 * the HIGH TAG form we would need to do some more work, especially	 * in how to specify them in the template, because right now we	 * do not provide a way to specify more *tag* bits in encode_kind.	 */	tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;	is_string = PR_FALSE;	switch (under_kind & SEC_ASN1_TAGNUM_MASK) {	  case SEC_ASN1_SET:	    /*	     * XXX A plain old SET (as opposed to a SET OF) is not implemented.	     * If it ever is, remove this assert...	     */	    PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0);	    /* fallthru */	  case SEC_ASN1_SEQUENCE:	    tag_modifiers |= SEC_ASN1_CONSTRUCTED;	    break;	  case SEC_ASN1_BIT_STRING:	  case SEC_ASN1_BMP_STRING: 	  case SEC_ASN1_GENERALIZED_TIME:	  case SEC_ASN1_IA5_STRING:	  case SEC_ASN1_OCTET_STRING:	  case SEC_ASN1_PRINTABLE_STRING:	  case SEC_ASN1_T61_STRING:	  case SEC_ASN1_UNIVERSAL_STRING: 	  case SEC_ASN1_UTC_TIME:	  case SEC_ASN1_UTF8_STRING:	  case SEC_ASN1_VISIBLE_STRING: 	    /*	     * We do not yet know if we will be constructing the string,	     * so we have to wait to do this final tag modification.	     */	    is_string = PR_TRUE;	    break;	}    }    state->tag_modifiers = tag_modifiers;    state->tag_number = (unsigned char)tag_number;    state->underlying_kind = under_kind;    state->isExplicit = isExplicit;    state->may_stream = may_stream;    state->is_string = is_string;    state->optional = optional;    state->disallowStreaming = disallowStreaming;    sec_asn1e_scrub_state (state);    return state;}