COMPONENTS OF support

diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c
index 2a78aa1..4810079 100644
--- a/libasn1fix/asn1fix.c
+++ b/libasn1fix/asn1fix.c
@@ -117,7 +117,9 @@
 
 	switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {
 	case MSF_NOFLAGS:
-		//arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
+		/*
+		 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;
+		 */
 		break;
 	case MSF_unk_INSTRUCTIONS:
 		WARNING("Module %s defined with unrecognized "
@@ -277,6 +279,10 @@
 	ret = asn1f_fix_constr_tag(arg);
 	RET2RVAL(ret, rvalue);
 
+	/* Import COMPONENTS OF stuff */
+	ret = asn1f_pull_components_of(arg);
+	RET2RVAL(ret, rvalue);
+
 	return rvalue;
 }
 
@@ -287,12 +293,13 @@
 	int rvalue = 0;
 	int ret;
 
-	top_parent = asn1f_find_terminal_type(arg, arg->expr, NULL);
+	top_parent = asn1f_find_terminal_type(arg, arg->expr);
 	if(top_parent)
 		etype = top_parent->expr_type;
 	else	etype = A1TC_INVALID;
 
-	ret = asn1constraint_resolve(arg, arg->expr->constraints, etype, 0);
+	ret = asn1constraint_resolve(arg, arg->expr->module,
+		arg->expr->constraints, etype, 0);
 	RET2RVAL(ret, rvalue);
 
 	ret = asn1constraint_pullup(arg);
diff --git a/libasn1fix/asn1fix_constr.c b/libasn1fix/asn1fix_constr.c
index 4db233f..1574c81 100644
--- a/libasn1fix/asn1fix_constr.c
+++ b/libasn1fix/asn1fix_constr.c
@@ -3,6 +3,79 @@
 static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
 static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
 
+int
+asn1f_pull_components_of(arg_t *arg) {
+	TQ_HEAD(asn1p_expr_t) list;
+	asn1p_expr_t *expr = arg->expr;
+	asn1p_expr_t *memb;
+	int r_value = 0;
+
+	switch(expr->expr_type) {
+	case ASN_CONSTR_SEQUENCE:
+	case ASN_CONSTR_SET:
+		break;
+	default:
+		return 0;
+	}
+
+	TQ_INIT(&list);
+
+	/*
+	 * Look into
+	 */
+	while((memb = TQ_REMOVE(&(expr->members), next))) {
+		asn1p_expr_t *coft;	/* COMPONENTS OF thing itself */
+		asn1p_expr_t *terminal;	/* Terminal of the referenced type */
+
+		if(memb->expr_type != A1TC_COMPONENTS_OF) {
+			TQ_ADD(&list, memb, next);
+			continue;
+		}
+
+		coft = TQ_FIRST(&memb->members);
+		assert(coft);
+		assert(!TQ_NEXT(coft, next));
+
+		/*
+		 * Find the referenced type.
+		 */
+		terminal = asn1f_find_terminal_type(arg, coft);
+		if(!terminal || (terminal->expr_type != expr->expr_type)) {
+			FATAL("COMPONENTS OF at line %d "
+				"must reference a %s type",
+				coft->_lineno,
+				expr->expr_type==ASN_CONSTR_SET
+					? "SET" : "SEQUENCE"
+			);
+			TQ_ADD(&list, memb, next);
+			r_value = -1;
+			continue;
+		}
+
+		/*
+		 * Clone the final structure.
+		 */
+
+		coft = asn1p_expr_clone(terminal, 1 /* Skip extensions */);
+		if(!coft) return -1;	/* ENOMEM */
+
+		asn1p_expr_free(memb);	/* Don't need it anymore*/
+
+		/*
+		 * Move all components of the cloned structure
+		 * into the current one.
+		 */
+		while((memb = TQ_REMOVE(&(coft->members), next)))
+			TQ_ADD(&list, memb, next);
+
+		asn1p_expr_free(coft);	/* Remove wrapper */
+	}
+
+	/* Move the stuff back */
+	TQ_HEAD_COPY(&(expr->members), &list);
+
+	return r_value;
+}
 
 int
 asn1f_fix_constr_ext(arg_t *arg) {
@@ -203,7 +276,10 @@
 		if(v->expr_type == A1TC_EXTENSIBLE)
 			break;
 
-		assert(v->tag.tag_class == TC_NOCLASS);
+		if(0) {
+			/* This may be not true in case COMPONENTS OF */
+			assert(v->tag.tag_class == TC_NOCLASS);
+		}
 
 		must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
 
@@ -259,7 +335,7 @@
 _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
 	asn1p_expr_t *reft;
 
-	reft = asn1f_find_terminal_type(arg, v, 0);
+	reft = asn1f_find_terminal_type(arg, v);
 	if(reft) {
 		switch(reft->expr_type) {
 		case ASN_CONSTR_CHOICE:
@@ -329,13 +405,12 @@
 		b->Identifier, b->expr_type);
 
 	if(a->meta_type == AMT_TYPEREF) {
-		asn1p_module_t *mod;
 
 		DEBUG(" %s is a type reference", a->Identifier);
 
-		a = asn1f_lookup_symbol(arg, a->reference, &mod);
+		a = asn1f_lookup_symbol(arg, a->module, a->reference);
 		if(!a) return 0;	/* Already FATAL()'ed somewhere else */
-		WITH_MODULE(mod, ret = _asn1f_compare_tags(arg, a, b));
+		WITH_MODULE(a->module, ret = _asn1f_compare_tags(arg, a, b));
 		return ret;
 	}
 
diff --git a/libasn1fix/asn1fix_constr.h b/libasn1fix/asn1fix_constr.h
index aeb05c0..59970ad 100644
--- a/libasn1fix/asn1fix_constr.h
+++ b/libasn1fix/asn1fix_constr.h
@@ -2,6 +2,11 @@
 #define	_ASN1FIX_CONSTRUCTED_H_
 
 /*
+ * Pull in COMPONENTS OF.
+ */
+int asn1f_pull_components_of(arg_t *);
+
+/*
  * Fix extensions in constructed types.
  */
 int asn1f_fix_constr_ext(arg_t *);