2006-03-14 15:23:06 +00:00
|
|
|
#include "asn1fix_internal.h"
|
2006-03-14 15:53:59 +00:00
|
|
|
#include "asn1fix_cws.h"
|
2006-03-14 16:31:37 +00:00
|
|
|
|
2006-03-16 10:03:35 +00:00
|
|
|
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);
|
|
|
|
|
2006-03-14 16:31:37 +00:00
|
|
|
int
|
2006-03-16 10:03:35 +00:00
|
|
|
asn1f_parse_class_object(arg_t *arg) {
|
2006-03-14 16:31:37 +00:00
|
|
|
asn1p_expr_t *expr = arg->expr;
|
2006-03-16 10:03:35 +00:00
|
|
|
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;
|
2006-03-14 16:31:37 +00:00
|
|
|
|
2006-03-16 10:03:35 +00:00
|
|
|
/*
|
|
|
|
* Find the governing class.
|
|
|
|
*/
|
|
|
|
eclass = asn1f_find_terminal_type(arg, expr);
|
|
|
|
if(!eclass
|
|
|
|
|| eclass->meta_type != AMT_OBJECTCLASS
|
|
|
|
|| eclass->expr_type != A1TC_CLASSDEF) {
|
2006-03-14 16:31:37 +00:00
|
|
|
return 0;
|
2006-03-16 10:03:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2006-03-14 16:31:37 +00:00
|
|
|
|
2006-03-16 10:03:35 +00:00
|
|
|
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);
|
2006-03-14 16:31:37 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2006-03-16 10:03:35 +00:00
|
|
|
|