parsing WITH SYNTAX clauses

diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c
index dbe18c2..21a5621 100644
--- a/libasn1fix/asn1fix.c
+++ b/libasn1fix/asn1fix.c
@@ -188,8 +188,9 @@
 			/* Do not process the parametrized type just yet */
 			continue;
 
-		DEBUG("=== Now processing \"%s\" at line %d ===",
-			expr->Identifier, expr->_lineno);
+		DEBUG("=== Now processing \"%s\" (%d/0x%x) at line %d ===",
+			expr->Identifier, expr->meta_type, expr->expr_type,
+			expr->_lineno);
 		assert(expr->meta_type != AMT_INVALID);
 
 		/*
@@ -223,9 +224,10 @@
 		RET2RVAL(ret, rvalue);
 
 		/*
-		 * Parse WITH SYNTAX in CLASSes.
+		 * Parse class objects and fill up the object class with data.
 		 */
-		ret = asn1f_parse_class_with_syntax(arg);
+		ret = asn1f_parse_class_object(arg);
+		RET2RVAL(ret, rvalue);
 
 		/*
 		 * Resolve references in constraints.
@@ -294,6 +296,9 @@
 	int ret;
 
 	TQ_FOR(expr, &(arg->mod->members), next) {
+	}
+
+	TQ_FOR(expr, &(arg->mod->members), next) {
 		arg->expr = expr;
 
 		if(expr->meta_type == AMT_PARAMTYPE)
diff --git a/libasn1fix/asn1fix_cws.c b/libasn1fix/asn1fix_cws.c
index a605c24..3d7b8aa 100644
--- a/libasn1fix/asn1fix_cws.c
+++ b/libasn1fix/asn1fix_cws.c
@@ -1,15 +1,226 @@
 #include "asn1fix_internal.h"
 #include "asn1fix_cws.h"
 
-int
-asn1f_parse_class_with_syntax(arg_t *arg) {
-	asn1p_expr_t *expr = arg->expr;
+static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass,
+		struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
+		uint8_t *buf, const uint8_t *bend,
+		int optional_mode, uint8_t **newpos);
+static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, uint8_t *buf, const uint8_t *bend);
 
-	if(expr->expr_type != A1TC_CLASSDEF
-	|| expr->with_syntax == NULL)
+int
+asn1f_parse_class_object(arg_t *arg) {
+	asn1p_expr_t *expr = arg->expr;
+	asn1p_expr_t *eclass;
+	asn1p_ioc_row_t *row;
+	void *new_rows_ptr;
+	int ret;
+
+	if(expr->meta_type != AMT_VALUE
+	|| expr->expr_type != A1TC_REFERENCE
+	|| !expr->value
+	|| expr->value->type != ATV_UNPARSED)
 		return 0;
 
-	DEBUG("Class %s: checking WITH SYNTAX", expr->Identifier);
+	/*
+	 * Find the governing class.
+	 */
+	eclass = asn1f_find_terminal_type(arg, expr);
+	if(!eclass
+	|| eclass->meta_type != AMT_OBJECTCLASS
+	|| eclass->expr_type != A1TC_CLASSDEF) {
+		return 0;
+	}
+
+	DEBUG("Value %s of CLASS %s found at line %d",
+		expr->Identifier, eclass->Identifier, expr->_lineno);
+
+	if(!eclass->with_syntax) {
+		DEBUG("Can't process classes without WITH SYNTAX just yet");
+		return 0;
+	}
+
+	row = asn1p_ioc_row_new(eclass);
+	assert(row);
+
+	ret = _asn1f_parse_class_object_data(arg, eclass, row,
+		eclass->with_syntax,
+		expr->value->value.string.buf + 1,
+		expr->value->value.string.buf
+			+ expr->value->value.string.size - 1,
+		0, 0);
+	if(ret) {
+		LOG((ret < 0),
+			"Cannot parse %s of CLASS %s found at line %d",
+			expr->Identifier, eclass->Identifier, expr->_lineno);
+		asn1p_ioc_row_delete(row);
+		return ret;
+	}
+
+	new_rows_ptr = realloc(eclass->object_class_matrix.row,
+			(eclass->object_class_matrix.rows + 1)
+			* sizeof(eclass->object_class_matrix.row[0]));
+	assert(new_rows_ptr);
+	eclass->object_class_matrix.row = new_rows_ptr;
+	eclass->object_class_matrix.row[eclass->object_class_matrix.rows] = row;
+	eclass->object_class_matrix.rows++;
+	/* Propagate max identifier length */
+	if(eclass->object_class_matrix.max_identifier_length
+			< row->max_identifier_length)
+		eclass->object_class_matrix.max_identifier_length
+			= row->max_identifier_length;
 
 	return 0;
 }
+
+#define	SKIPSPACES	for(; buf < bend && isspace(*buf); buf++)
+
+static int
+_asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
+		struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
+		uint8_t *buf, const uint8_t *bend,
+		int optional_mode, uint8_t **newpos) {
+	struct asn1p_wsyntx_chunk_s *chunk;
+	int ret;
+
+	TQ_FOR(chunk, (&syntax->chunks), next) {
+		switch(chunk->type) {
+		case WC_LITERAL: {
+			int token_len = strlen(chunk->content.token);
+			SKIPSPACES;
+			if(bend - buf < token_len
+			|| memcmp(buf, chunk->content.token, token_len)) {
+				if(!optional_mode) {
+					FATAL("While parsing object class value %s at line %d: Expected: \"%s\", found: \"%s\"",
+					arg->expr->Identifier, arg->expr->_lineno, chunk->content.token, buf);
+				}
+				if(newpos) *newpos = buf;
+				return -1;
+			}
+			buf += token_len;
+		    } break;
+		case WC_WHITESPACE: break;	/* Ignore whitespace */
+		case WC_FIELD: {
+			struct asn1p_ioc_cell_s *cell;
+			uint8_t *p;
+			SKIPSPACES;
+			int lbraces = 0;
+			p = buf;
+			if(p < bend && *p == '{')
+				lbraces = 1, p++;
+			for(; p < bend; p++) {
+				if(lbraces) {
+					/* Search the terminating brace */
+					switch(*p) {
+					case '}': lbraces--; break;
+					case '{': lbraces++; break;
+					}
+				} else if(isspace(*p)) {
+					break;
+				}
+			}
+			if(lbraces) {
+				FATAL("Field reference %s found in class value definition for %s at line %d can not be satisfied by broken value \"%s\"",
+				chunk->content.token,
+				arg->expr->Identifier, arg->expr->_lineno, buf);
+				if(newpos) *newpos = buf;
+				return -1;
+			}
+			cell = asn1p_ioc_row_cell_fetch(row,
+					chunk->content.token);
+			if(cell == NULL) {
+				FATAL("Field reference %s found in WITH SYNAX {} clause does not match actual field in Object Class %s",
+					chunk->content.token,
+					eclass->Identifier, eclass->_lineno);
+				if(newpos) *newpos = buf;
+				return -1;
+			}
+			DEBUG("Reference %s satisfied by %s (%d)",
+				chunk->content.token,
+				buf, p - buf);
+			ret = _asn1f_assign_cell_value(arg, row, cell, buf, p);
+			if(ret) {
+				if(newpos) *newpos = buf;
+				return ret;
+			}
+			buf = p;
+		    } break;
+		case WC_OPTIONALGROUP: {
+			uint8_t *np = 0;
+			SKIPSPACES;
+			ret = _asn1f_parse_class_object_data(arg, eclass, row,
+				chunk->content.syntax, buf, bend, 1, &np);
+			if(newpos) *newpos = np;
+			if(ret && np != buf)
+				return ret;
+		    } break;
+		}
+	}
+
+
+	if(newpos) *newpos = buf;
+	return 0;
+}
+
+
+static int
+_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell,
+		uint8_t *buf, const uint8_t *bend) {
+	asn1p_expr_t *expr;
+	asn1p_ref_t *ref;
+	char *p;
+
+	if((bend - buf) <= 0) {
+		FATAL("Assignment warning: empty string is being assigned into %s for %s at line %d",
+			cell->field->Identifier,
+			arg->expr->Identifier, arg->expr->_lineno);
+		return -1;
+	}
+
+	p = malloc(bend - buf + 1);
+	assert(p);
+	memcpy(p, buf, bend - buf);
+	p[bend - buf] = '\0';
+
+	if(!isalpha(*p)) {
+
+		if(isdigit(*p)) {
+			asn1c_integer_t value;
+			if(asn1p_atoi(p, &value)) {
+				FATAL("Value %s at line %d is too large for this compiler! Please contact the asn1c author.\n", p, arg->expr->_lineno);
+				return -1;
+			}
+			expr = asn1p_expr_new(arg->expr->_lineno);
+			expr->Identifier = p;
+			expr->meta_type = AMT_VALUE; 
+			expr->expr_type = ASN_BASIC_INTEGER;
+			expr->value = asn1p_value_fromint(value);
+		} else {
+			WARNING("asn1c is not yet able to parse arbitrary direct values; please convert %s at line %d to a reference.", p, arg->expr->_lineno);
+			free(p);
+			return 1;
+		}
+	} else {
+		ref = asn1p_ref_new(arg->expr->_lineno);
+		asn1p_ref_add_component(ref, p, RLT_UNKNOWN);
+		assert(ref);
+	
+		expr = asn1f_lookup_symbol(arg, arg->mod, ref);
+		if(!expr) {
+			FATAL("Cannot find %s referenced by %s at line %d",
+				p, arg->expr->Identifier,
+				arg->expr->_lineno);
+			return -1;
+		}
+	}
+
+	DEBUG("Field %s assignment of %s got %s",
+		cell->field->Identifier, p, expr->Identifier);
+
+	cell->value = expr;
+
+	if(row->max_identifier_length < strlen(expr->Identifier))
+		row->max_identifier_length = strlen(expr->Identifier);
+
+	return 0;
+}
+
diff --git a/libasn1fix/asn1fix_cws.h b/libasn1fix/asn1fix_cws.h
index 25fd208..aa76b49 100644
--- a/libasn1fix/asn1fix_cws.h
+++ b/libasn1fix/asn1fix_cws.h
@@ -2,9 +2,8 @@
 #define	_ASN1FIX_CLASS_WITH_SYNTAX_H_
 
 /*
- * CLASS may contain the "WITH SYNTAX" clause, in which case we are
- * going to parse it.
+ * Parse class objects
  */
-int asn1f_parse_class_with_syntax(arg_t *arg);
+int asn1f_parse_class_object(arg_t *arg);
 
 #endif	/* _ASN1FIX_CLASS_WITH_SYNTAX_H_ */