Initial revision

diff --git a/libasn1fix/asn1fix_enum.c b/libasn1fix/asn1fix_enum.c
new file mode 100644
index 0000000..8a90a43
--- /dev/null
+++ b/libasn1fix/asn1fix_enum.c
@@ -0,0 +1,136 @@
+#include "asn1fix_internal.h"
+
+/*
+ * Check the validity of an enumeration.
+ */
+int
+asn1f_fix_enum(arg_t *arg) {
+	asn1p_expr_t *expr = arg->expr;
+	asn1p_expr_t *ev;
+	asn1_integer_t max_value = -1;
+	int rvalue = 0;
+	asn1p_expr_t *ext_marker = NULL;	/* "..." position */
+	int ret;
+
+	if(expr->expr_type != ASN_BASIC_ENUMERATED)
+		return 0;	/* Just ignore it */
+
+	DEBUG("%s(%s)", __func__, expr->Identifier);
+
+	/*
+	 * 1. Scan the enumeration values in search for inconsistencies.
+	 */
+	TQ_FOR(ev, &(expr->members), next) {
+		asn1_integer_t eval;
+
+		if(ev->value)
+			DEBUG("\tItem %s(%s)", ev->Identifier,
+				asn1f_printable_value(ev->value));
+		else
+			DEBUG("\tItem %s", ev->Identifier);
+
+		/*
+		 * 1.1 Found an extension mark "...", check correctness.
+		 */
+		if(ev->expr_type == A1TC_EXTENSIBLE) {
+			if(ext_marker) {
+				arg->eh(1,
+				"Enumeration %s at line %d: "
+				"Second extension marker is not allowed",
+				expr->Identifier,
+				ev->_lineno);
+				rvalue = -1;
+			} else {
+				/*
+				 * Remember the marker's position.
+				 */
+				ext_marker = ev;
+			}
+			continue;
+		} else if(ev->Identifier == NULL
+			|| ev->expr_type != A1TC_UNIVERVAL) {
+			FATAL(
+				"Enumeration %s at line %d: "
+				"Unsupported enumeration element %s",
+				expr->Identifier,
+				ev->_lineno,
+				ev->Identifier?ev->Identifier:"<anonymous>");
+			rvalue = -1;
+			continue;
+		}
+
+		/*
+		 * 1.2 Compute the value of the enumeration element.
+		 */
+		if(ev->value) {
+			switch(ev->value->type) {
+			case ATV_INTEGER:
+				eval = ev->value->value.v_integer;
+				break;
+			case ATV_REFERENCED:
+				FATAL("HERE HERE HERE", 1);
+				rvalue = -1;
+				continue;
+				break;
+			default:
+				FATAL("ENUMERATED type %s at line %d "
+					"contain element %s(%s) at line %d",
+					expr->Identifier, expr->_lineno,
+					ev->Identifier,
+					asn1f_printable_value(ev->value),
+					ev->_lineno);
+				rvalue = -1;
+				continue;
+			}
+		} else {
+			eval = max_value + 1;
+			ev->value = asn1p_value_fromint(eval);
+			if(ev->value == NULL) {
+				rvalue = -1;
+				continue;
+			}
+		}
+
+		/*
+		 * 1.3 Check the applicability of this value.
+		 */
+		if(eval <= max_value) {
+			if(ext_marker) {
+				/*
+				 * Enumeration is allowed to be unordered
+				 * before the first marker.
+				 */
+				FATAL(
+					"Enumeration %s at line %d: "
+					"Explicit value \"%s(%lld)\" "
+					"is not greater "
+					"than previous values (max %lld)",
+					expr->Identifier,
+					ev->_lineno,
+					ev->Identifier,
+					eval,
+					max_value);
+				rvalue = -1;
+			}
+		} else if(eval > max_value) {
+			max_value = eval;
+		}
+
+		/*
+		 * 1.4 Check that all identifiers before the current one
+		 * differs from it.
+		 */
+		ret = asn1f_check_unique_expr_child(arg, ev, NULL);
+		RET2RVAL(ret, rvalue);
+	}
+
+
+	/*
+	 * 2. Reorder the first half (before optional "...") of the
+	 * identifiers alphabetically.
+	 */
+	// TODO
+
+	return rvalue;
+}
+