blob: 8931a92cf5e662edd4662fffe3c85fda10d76bef [file] [log] [blame]
vlmeafceff2006-03-14 15:23:06 +00001#include "asn1fix_internal.h"
vlm51aed882006-03-14 15:53:59 +00002#include "asn1fix_cws.h"
vlm808411d2006-03-14 16:31:37 +00003
vlma6a84d72006-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);
vlm808411d2006-03-14 16:31:37 +00009
vlma6a84d72006-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)
vlm808411d2006-03-14 16:31:37 +000022 return 0;
23
vlma6a84d72006-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) {
vlmc286cb52006-03-16 13:37:03 +000038 DEBUG("Can't process classes without %s just yet",
39 "WITH SYNTAX");
vlma6a84d72006-03-16 10:03:35 +000040 return 0;
41 }
42
43 row = asn1p_ioc_row_new(eclass);
44 assert(row);
45
46 ret = _asn1f_parse_class_object_data(arg, eclass, row,
47 eclass->with_syntax,
48 expr->value->value.string.buf + 1,
49 expr->value->value.string.buf
50 + expr->value->value.string.size - 1,
51 0, 0);
52 if(ret) {
53 LOG((ret < 0),
54 "Cannot parse %s of CLASS %s found at line %d",
55 expr->Identifier, eclass->Identifier, expr->_lineno);
56 asn1p_ioc_row_delete(row);
57 return ret;
58 }
59
60 new_rows_ptr = realloc(eclass->object_class_matrix.row,
61 (eclass->object_class_matrix.rows + 1)
62 * sizeof(eclass->object_class_matrix.row[0]));
63 assert(new_rows_ptr);
64 eclass->object_class_matrix.row = new_rows_ptr;
65 eclass->object_class_matrix.row[eclass->object_class_matrix.rows] = row;
66 eclass->object_class_matrix.rows++;
67 /* Propagate max identifier length */
68 if(eclass->object_class_matrix.max_identifier_length
69 < row->max_identifier_length)
70 eclass->object_class_matrix.max_identifier_length
71 = row->max_identifier_length;
vlm808411d2006-03-14 16:31:37 +000072
73 return 0;
74}
vlma6a84d72006-03-16 10:03:35 +000075
76#define SKIPSPACES for(; buf < bend && isspace(*buf); buf++)
77
78static int
79_asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
80 struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
81 uint8_t *buf, const uint8_t *bend,
82 int optional_mode, uint8_t **newpos) {
83 struct asn1p_wsyntx_chunk_s *chunk;
84 int ret;
85
86 TQ_FOR(chunk, (&syntax->chunks), next) {
87 switch(chunk->type) {
88 case WC_LITERAL: {
89 int token_len = strlen(chunk->content.token);
90 SKIPSPACES;
91 if(bend - buf < token_len
92 || memcmp(buf, chunk->content.token, token_len)) {
93 if(!optional_mode) {
94 FATAL("While parsing object class value %s at line %d: Expected: \"%s\", found: \"%s\"",
95 arg->expr->Identifier, arg->expr->_lineno, chunk->content.token, buf);
96 }
97 if(newpos) *newpos = buf;
98 return -1;
99 }
100 buf += token_len;
101 } break;
102 case WC_WHITESPACE: break; /* Ignore whitespace */
103 case WC_FIELD: {
104 struct asn1p_ioc_cell_s *cell;
vlma6a84d72006-03-16 10:03:35 +0000105 int lbraces = 0;
vlmc286cb52006-03-16 13:37:03 +0000106 uint8_t *p;
107
108 SKIPSPACES;
109
vlma6a84d72006-03-16 10:03:35 +0000110 p = buf;
111 if(p < bend && *p == '{')
112 lbraces = 1, p++;
113 for(; p < bend; p++) {
114 if(lbraces) {
115 /* Search the terminating brace */
116 switch(*p) {
117 case '}': lbraces--; break;
118 case '{': lbraces++; break;
119 }
120 } else if(isspace(*p)) {
121 break;
122 }
123 }
124 if(lbraces) {
125 FATAL("Field reference %s found in class value definition for %s at line %d can not be satisfied by broken value \"%s\"",
126 chunk->content.token,
127 arg->expr->Identifier, arg->expr->_lineno, buf);
128 if(newpos) *newpos = buf;
129 return -1;
130 }
131 cell = asn1p_ioc_row_cell_fetch(row,
132 chunk->content.token);
133 if(cell == NULL) {
134 FATAL("Field reference %s found in WITH SYNAX {} clause does not match actual field in Object Class %s",
135 chunk->content.token,
136 eclass->Identifier, eclass->_lineno);
137 if(newpos) *newpos = buf;
138 return -1;
139 }
140 DEBUG("Reference %s satisfied by %s (%d)",
141 chunk->content.token,
142 buf, p - buf);
143 ret = _asn1f_assign_cell_value(arg, row, cell, buf, p);
vlmd938e0b2006-03-16 11:04:55 +0000144 if(ret) return ret;
vlma6a84d72006-03-16 10:03:35 +0000145 buf = p;
vlmd938e0b2006-03-16 11:04:55 +0000146 if(newpos) *newpos = buf;
vlma6a84d72006-03-16 10:03:35 +0000147 } break;
148 case WC_OPTIONALGROUP: {
149 uint8_t *np = 0;
150 SKIPSPACES;
151 ret = _asn1f_parse_class_object_data(arg, eclass, row,
152 chunk->content.syntax, buf, bend, 1, &np);
153 if(newpos) *newpos = np;
154 if(ret && np != buf)
155 return ret;
vlmd938e0b2006-03-16 11:04:55 +0000156 buf = np;
vlma6a84d72006-03-16 10:03:35 +0000157 } break;
158 }
159 }
160
161
162 if(newpos) *newpos = buf;
163 return 0;
164}
165
166
167static int
168_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell,
169 uint8_t *buf, const uint8_t *bend) {
170 asn1p_expr_t *expr;
171 asn1p_ref_t *ref;
vlm1fcf7592006-08-18 02:27:55 +0000172 int idLength;
vlma6a84d72006-03-16 10:03:35 +0000173 char *p;
174
175 if((bend - buf) <= 0) {
176 FATAL("Assignment warning: empty string is being assigned into %s for %s at line %d",
177 cell->field->Identifier,
178 arg->expr->Identifier, arg->expr->_lineno);
179 return -1;
180 }
181
182 p = malloc(bend - buf + 1);
183 assert(p);
184 memcpy(p, buf, bend - buf);
185 p[bend - buf] = '\0';
186
187 if(!isalpha(*p)) {
188
189 if(isdigit(*p)) {
190 asn1c_integer_t value;
191 if(asn1p_atoi(p, &value)) {
vlmc03306f2006-03-18 05:06:57 +0000192 FATAL("Value %s at line %d is too large for this compiler! Contact the asn1c author.\n", p, arg->expr->_lineno);
vlma6a84d72006-03-16 10:03:35 +0000193 return -1;
194 }
vlm43c8ac52006-09-17 04:52:50 +0000195 expr = asn1p_expr_new(arg->expr->_lineno, arg->expr->module);
vlma6a84d72006-03-16 10:03:35 +0000196 expr->Identifier = p;
197 expr->meta_type = AMT_VALUE;
198 expr->expr_type = ASN_BASIC_INTEGER;
199 expr->value = asn1p_value_fromint(value);
200 } else {
vlmc03306f2006-03-18 05:06:57 +0000201 WARNING("asn1c is not yet able to parse arbitrary direct values; try converting %s at line %d to a reference.", p, arg->expr->_lineno);
vlma6a84d72006-03-16 10:03:35 +0000202 free(p);
203 return 1;
204 }
205 } else {
206 ref = asn1p_ref_new(arg->expr->_lineno);
207 asn1p_ref_add_component(ref, p, RLT_UNKNOWN);
208 assert(ref);
209
vlm0c6d3812006-03-21 03:40:38 +0000210 expr = asn1f_lookup_symbol(arg, arg->mod, arg->expr->rhs_pspecs, ref);
vlma6a84d72006-03-16 10:03:35 +0000211 if(!expr) {
212 FATAL("Cannot find %s referenced by %s at line %d",
213 p, arg->expr->Identifier,
214 arg->expr->_lineno);
215 return -1;
216 }
217 }
218
219 DEBUG("Field %s assignment of %s got %s",
220 cell->field->Identifier, p, expr->Identifier);
221
222 cell->value = expr;
223
vlm1fcf7592006-08-18 02:27:55 +0000224 idLength = strlen(expr->Identifier);
225 if(row->max_identifier_length < idLength)
226 row->max_identifier_length = idLength;
vlma6a84d72006-03-16 10:03:35 +0000227
228 return 0;
229}
230