blob: e19071d966e81f3d15c9ec810a0ef4fb34a8fff0 [file] [log] [blame]
Lev Walkincb4cd5b2006-03-14 15:23:06 +00001#include "asn1fix_internal.h"
Lev Walkinaa7f5302006-03-14 15:53:59 +00002#include "asn1fix_cws.h"
Lev Walkin9d542d22006-03-14 16:31:37 +00003
Lev Walkind370e9f2006-03-16 10:03:35 +00004static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass,
5 struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
6 uint8_t *buf, const uint8_t *bend,
7 int optional_mode, uint8_t **newpos);
8static 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);
Lev Walkin9d542d22006-03-14 16:31:37 +00009
Lev Walkind370e9f2006-03-16 10:03:35 +000010int
11asn1f_parse_class_object(arg_t *arg) {
12 asn1p_expr_t *expr = arg->expr;
13 asn1p_expr_t *eclass;
14 asn1p_ioc_row_t *row;
15 void *new_rows_ptr;
16 int ret;
17
18 if(expr->meta_type != AMT_VALUE
19 || expr->expr_type != A1TC_REFERENCE
20 || !expr->value
21 || expr->value->type != ATV_UNPARSED)
Lev Walkin9d542d22006-03-14 16:31:37 +000022 return 0;
23
Lev Walkind370e9f2006-03-16 10:03:35 +000024 /*
25 * Find the governing class.
26 */
27 eclass = asn1f_find_terminal_type(arg, expr);
28 if(!eclass
29 || eclass->meta_type != AMT_OBJECTCLASS
30 || eclass->expr_type != A1TC_CLASSDEF) {
31 return 0;
32 }
33
34 DEBUG("Value %s of CLASS %s found at line %d",
35 expr->Identifier, eclass->Identifier, expr->_lineno);
36
37 if(!eclass->with_syntax) {
38 DEBUG("Can't process classes without WITH SYNTAX just yet");
39 return 0;
40 }
41
42 row = asn1p_ioc_row_new(eclass);
43 assert(row);
44
45 ret = _asn1f_parse_class_object_data(arg, eclass, row,
46 eclass->with_syntax,
47 expr->value->value.string.buf + 1,
48 expr->value->value.string.buf
49 + expr->value->value.string.size - 1,
50 0, 0);
51 if(ret) {
52 LOG((ret < 0),
53 "Cannot parse %s of CLASS %s found at line %d",
54 expr->Identifier, eclass->Identifier, expr->_lineno);
55 asn1p_ioc_row_delete(row);
56 return ret;
57 }
58
59 new_rows_ptr = realloc(eclass->object_class_matrix.row,
60 (eclass->object_class_matrix.rows + 1)
61 * sizeof(eclass->object_class_matrix.row[0]));
62 assert(new_rows_ptr);
63 eclass->object_class_matrix.row = new_rows_ptr;
64 eclass->object_class_matrix.row[eclass->object_class_matrix.rows] = row;
65 eclass->object_class_matrix.rows++;
66 /* Propagate max identifier length */
67 if(eclass->object_class_matrix.max_identifier_length
68 < row->max_identifier_length)
69 eclass->object_class_matrix.max_identifier_length
70 = row->max_identifier_length;
Lev Walkin9d542d22006-03-14 16:31:37 +000071
72 return 0;
73}
Lev Walkind370e9f2006-03-16 10:03:35 +000074
75#define SKIPSPACES for(; buf < bend && isspace(*buf); buf++)
76
77static int
78_asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
79 struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
80 uint8_t *buf, const uint8_t *bend,
81 int optional_mode, uint8_t **newpos) {
82 struct asn1p_wsyntx_chunk_s *chunk;
83 int ret;
84
85 TQ_FOR(chunk, (&syntax->chunks), next) {
86 switch(chunk->type) {
87 case WC_LITERAL: {
88 int token_len = strlen(chunk->content.token);
89 SKIPSPACES;
90 if(bend - buf < token_len
91 || memcmp(buf, chunk->content.token, token_len)) {
92 if(!optional_mode) {
93 FATAL("While parsing object class value %s at line %d: Expected: \"%s\", found: \"%s\"",
94 arg->expr->Identifier, arg->expr->_lineno, chunk->content.token, buf);
95 }
96 if(newpos) *newpos = buf;
97 return -1;
98 }
99 buf += token_len;
100 } break;
101 case WC_WHITESPACE: break; /* Ignore whitespace */
102 case WC_FIELD: {
103 struct asn1p_ioc_cell_s *cell;
104 uint8_t *p;
105 SKIPSPACES;
106 int lbraces = 0;
107 p = buf;
108 if(p < bend && *p == '{')
109 lbraces = 1, p++;
110 for(; p < bend; p++) {
111 if(lbraces) {
112 /* Search the terminating brace */
113 switch(*p) {
114 case '}': lbraces--; break;
115 case '{': lbraces++; break;
116 }
117 } else if(isspace(*p)) {
118 break;
119 }
120 }
121 if(lbraces) {
122 FATAL("Field reference %s found in class value definition for %s at line %d can not be satisfied by broken value \"%s\"",
123 chunk->content.token,
124 arg->expr->Identifier, arg->expr->_lineno, buf);
125 if(newpos) *newpos = buf;
126 return -1;
127 }
128 cell = asn1p_ioc_row_cell_fetch(row,
129 chunk->content.token);
130 if(cell == NULL) {
131 FATAL("Field reference %s found in WITH SYNAX {} clause does not match actual field in Object Class %s",
132 chunk->content.token,
133 eclass->Identifier, eclass->_lineno);
134 if(newpos) *newpos = buf;
135 return -1;
136 }
137 DEBUG("Reference %s satisfied by %s (%d)",
138 chunk->content.token,
139 buf, p - buf);
140 ret = _asn1f_assign_cell_value(arg, row, cell, buf, p);
Lev Walkindc4376d2006-03-16 11:04:55 +0000141 if(ret) return ret;
Lev Walkind370e9f2006-03-16 10:03:35 +0000142 buf = p;
Lev Walkindc4376d2006-03-16 11:04:55 +0000143 if(newpos) *newpos = buf;
Lev Walkind370e9f2006-03-16 10:03:35 +0000144 } break;
145 case WC_OPTIONALGROUP: {
146 uint8_t *np = 0;
147 SKIPSPACES;
148 ret = _asn1f_parse_class_object_data(arg, eclass, row,
149 chunk->content.syntax, buf, bend, 1, &np);
150 if(newpos) *newpos = np;
151 if(ret && np != buf)
152 return ret;
Lev Walkindc4376d2006-03-16 11:04:55 +0000153 buf = np;
Lev Walkind370e9f2006-03-16 10:03:35 +0000154 } break;
155 }
156 }
157
158
159 if(newpos) *newpos = buf;
160 return 0;
161}
162
163
164static int
165_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell,
166 uint8_t *buf, const uint8_t *bend) {
167 asn1p_expr_t *expr;
168 asn1p_ref_t *ref;
169 char *p;
170
171 if((bend - buf) <= 0) {
172 FATAL("Assignment warning: empty string is being assigned into %s for %s at line %d",
173 cell->field->Identifier,
174 arg->expr->Identifier, arg->expr->_lineno);
175 return -1;
176 }
177
178 p = malloc(bend - buf + 1);
179 assert(p);
180 memcpy(p, buf, bend - buf);
181 p[bend - buf] = '\0';
182
183 if(!isalpha(*p)) {
184
185 if(isdigit(*p)) {
186 asn1c_integer_t value;
187 if(asn1p_atoi(p, &value)) {
188 FATAL("Value %s at line %d is too large for this compiler! Please contact the asn1c author.\n", p, arg->expr->_lineno);
189 return -1;
190 }
191 expr = asn1p_expr_new(arg->expr->_lineno);
192 expr->Identifier = p;
193 expr->meta_type = AMT_VALUE;
194 expr->expr_type = ASN_BASIC_INTEGER;
195 expr->value = asn1p_value_fromint(value);
196 } else {
197 WARNING("asn1c is not yet able to parse arbitrary direct values; please convert %s at line %d to a reference.", p, arg->expr->_lineno);
198 free(p);
199 return 1;
200 }
201 } else {
202 ref = asn1p_ref_new(arg->expr->_lineno);
203 asn1p_ref_add_component(ref, p, RLT_UNKNOWN);
204 assert(ref);
205
206 expr = asn1f_lookup_symbol(arg, arg->mod, ref);
207 if(!expr) {
208 FATAL("Cannot find %s referenced by %s at line %d",
209 p, arg->expr->Identifier,
210 arg->expr->_lineno);
211 return -1;
212 }
213 }
214
215 DEBUG("Field %s assignment of %s got %s",
216 cell->field->Identifier, p, expr->Identifier);
217
218 cell->value = expr;
219
220 if(row->max_identifier_length < strlen(expr->Identifier))
221 row->max_identifier_length = strlen(expr->Identifier);
222
223 return 0;
224}
225