blob: c4e3f9951c9c35843718061eba04ad95109c8596 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#undef NDEBUG
Lev Walkin4efbfb72005-02-25 14:20:30 +00002#include "asn1fix_internal.h"
3
4#ifdef WIN32
5#include <io.h>
6#include <direct.h>
7#define chdir _chdir
8#else
Lev Walkinf15320b2004-06-03 03:38:44 +00009#include <dirent.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000010#include <sysexits.h>
Lev Walkin4efbfb72005-02-25 14:20:30 +000011#endif
12#include <errno.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000013
14#include "asn1fix.h"
Lev Walkinf15320b2004-06-03 03:38:44 +000015
16static int check(const char *fname,
17 enum asn1p_flags parser_flags,
18 enum asn1f_flags fixer_flags);
19static int post_fix_check(asn1p_t *asn);
20static int post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *expr);
21
22int
23main(int ac, char **av) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000024#ifdef WIN32
25 intptr_t dir;
26 struct _finddata_t c_file;
27#else
Lev Walkinf15320b2004-06-03 03:38:44 +000028 struct dirent *dp;
29 DIR *dir;
Lev Walkin4efbfb72005-02-25 14:20:30 +000030#endif
Lev Walkinf15320b2004-06-03 03:38:44 +000031 int failed = 0;
32 int completed = 0;
33 enum asn1p_flags parser_flags = A1P_NOFLAGS;
34 enum asn1f_flags fixer_flags = A1F_NOFLAGS;
Lev Walkin4efbfb72005-02-25 14:20:30 +000035 const char *filename;
Lev Walkin07721d52005-02-25 14:35:02 +000036 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000037 int ret;
38
39 /*
40 * Just in case when one decides that some flags better be
41 * enabled during `ASN1_FIXER_FLAGS=1 make check` or some
42 * similar usage.
43 */
44 if(getenv("ASN1_PARSER_FLAGS"))
45 parser_flags = atoi(getenv("ASN1_PARSER_FLAGS"));
46 if(getenv("ASN1_FIXER_FLAGS"))
47 fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS"));
48
49 /*
50 * Go into a directory with tests.
51 */
52 if(ac <= 1) {
53 fprintf(stderr, "Testing in ./tests...\n");
54 ret = chdir("../tests");
55 assert(ret == 0);
Lev Walkin4efbfb72005-02-25 14:20:30 +000056#ifdef WIN32
57 dir = _findfirst("*.asn1", &c_file);
58 assert(dir != -1L);
59#else
Lev Walkinf15320b2004-06-03 03:38:44 +000060 dir = opendir(".");
61 assert(dir);
Lev Walkin4efbfb72005-02-25 14:20:30 +000062#endif /* WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +000063 } else {
64 dir = 0;
65 }
66
67 /*
68 * Scan every *.asn1 file and try to parse and fix it.
69 */
70 if(dir) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000071#ifdef WIN32
72 do {
73 filename = c_file.name;
74#else
Lev Walkinf15320b2004-06-03 03:38:44 +000075 while((dp = readdir(dir))) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000076 filename = dp->d_name;
77#endif /* WIN32 */
Lev Walkin07721d52005-02-25 14:35:02 +000078 len = strlen(filename);
Lev Walkin4b553412005-08-14 14:45:44 +000079 if(len <= 5 || strcmp(filename + len - 5, ".asn1"))
80 continue;
81 ret = check(filename, parser_flags, fixer_flags);
82 if(ret) {
83 fprintf(stderr, "FAILED: %s\n",
84 filename);
85 failed++;
Lev Walkinf15320b2004-06-03 03:38:44 +000086 }
Lev Walkin4b553412005-08-14 14:45:44 +000087 completed++;
Lev Walkin4efbfb72005-02-25 14:20:30 +000088#ifdef WIN32
89 } while(_findnext(dir, &c_file) == 0);
90 _findclose(dir);
91#else
Lev Walkinf15320b2004-06-03 03:38:44 +000092 }
93 closedir(dir);
Lev Walkin4efbfb72005-02-25 14:20:30 +000094#endif /* WIN32 */
95
Lev Walkinf15320b2004-06-03 03:38:44 +000096
97 fprintf(stderr,
98 "Tests COMPLETED: %d\n"
99 "Tests FAILED: %d\n"
100 ,
101 completed, failed
102 );
103 } else {
104 int i;
105 for(i = 1; i < ac; i++) {
106 ret = check(av[i], parser_flags, fixer_flags);
107 if(ret) {
108 fprintf(stderr, "FAILED: %s\n", av[i]);
109 failed++;
110 }
111 completed++;
112 }
113 }
114
115 if(completed == 0) {
116 fprintf(stderr, "No tests defined?!\n");
117 exit(EX_NOINPUT);
118 }
119
120 if(failed)
121 exit(EX_DATAERR);
122 return 0;
123}
124
125static int
126check(const char *fname,
127 enum asn1p_flags parser_flags,
128 enum asn1f_flags fixer_flags) {
129 asn1p_t *asn;
130 int expected_parseable; /* Is it expected to be parseable? */
131 int expected_fix_code; /* What code a fixer must return */
132 int r_value = 0;
133
134 /*
135 * Figure out how the processing should go by inferring
136 * expectations from the file name.
137 */
138 if(strstr(fname, "-OK.")) {
139 expected_parseable = 1;
140 expected_fix_code = 0;
141 } else if(strstr(fname, "-NP.")) {
142 expected_parseable = 0;
143 expected_fix_code = 123; /* Does not matter */
144 } else if(strstr(fname, "-SE.")) {
145 expected_parseable = 1;
146 expected_fix_code = -1; /* Semantically incorrect */
147 } else if(strstr(fname, "-SW.")) {
148 expected_parseable = 1;
149 expected_fix_code = 1; /* Semantically suspicious */
150 } else {
151 fprintf(stderr, "%s: Invalid file name format\n", fname);
152 return -1;
153 }
154
Lev Walkin4b553412005-08-14 14:45:44 +0000155 /* Flag modifiers */
156 if(strstr(fname, "-blessSize-"))
157 fixer_flags |= A1F_EXTENDED_SizeConstraint;
158
Lev Walkinf15320b2004-06-03 03:38:44 +0000159 fprintf(stderr, "[=> %s]\n", fname);
160
161 /*
162 * Perform low-level parsing.
163 */
164 if(!expected_parseable)
165 fprintf(stderr, "Expecting error...\n");
166 asn = asn1p_parse_file(fname, parser_flags);
167 if(asn == NULL) {
168 if(expected_parseable) {
169 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
170 r_value = -1;
171 } else {
172 fprintf(stderr,
173 "Previous error is EXPECTED, no worry\n");
174 }
175 } else if(!expected_parseable) {
176 fprintf(stderr,
177 "The file \"%s\" is not expected to be parseable, "
178 "yet parsing was successfull!\n", fname);
179 r_value = -1;
180 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000181 if(!asn) return r_value;
182
183 if(r_value == 0) {
184 asn1p_t *std_asn;
185 std_asn = asn1p_parse_file("../skeletons/standard-modules/ASN1C-UsefulInformationObjectClasses.asn1", A1P_NOFLAGS);
186 if(std_asn) {
187 asn1p_module_t *mod;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000188 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next))) {
189 mod->_tags |= MT_STANDARD_MODULE;
Lev Walkin6b3ff542006-03-06 14:51:00 +0000190 TQ_ADD(&(asn->modules), mod, mod_next);
Lev Walkin9c2285a2006-03-09 08:49:26 +0000191 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000192 asn1p_free(std_asn);
193 }
194 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000195
196 /*
197 * Perform semantical checks and fixes.
198 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000199 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000200 int ret;
201
202 if(expected_fix_code)
203 fprintf(stderr, "Expecting some problems...\n");
204
205 ret = asn1f_process(asn, fixer_flags, 0);
206 if(ret) {
207 if(ret == expected_fix_code) {
208 fprintf(stderr,
209 "Previous error is EXPECTED, "
210 "no worry\n");
211 } else {
212 fprintf(stderr,
213 "Cannot process file \"%s\": %d\n",
214 fname, ret);
215 r_value = -1;
216 }
217 } else if(ret != expected_fix_code) {
218 fprintf(stderr,
219 "File \"%s\" is expected "
220 "to be semantically incorrect, "
221 "yet processing was successful!\n",
222 fname);
223 r_value = -1;
224 }
225 }
226
227 /*
228 * Check validity of some values, if grammar has special
229 * instructions for that.
230 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000231 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000232 if(post_fix_check(asn))
233 r_value = -1;
234 }
235
236 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000237 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000238 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000239 asn1p_free(asn);
Lev Walkinf15320b2004-06-03 03:38:44 +0000240
241 return r_value;
242}
243
244
245static int
246post_fix_check(asn1p_t *asn) {
247 asn1p_module_t *mod;
248 asn1p_expr_t *expr;
249 int r_value = 0;
250
251 TQ_FOR(mod, &(asn->modules), mod_next) {
252 TQ_FOR(expr, &(mod->members), next) {
253 assert(expr->Identifier);
254 if(strncmp(expr->Identifier, "check-", 6) == 0) {
255 if(post_fix_check_element(mod, expr))
256 r_value = -1;
257 }
258 }
259 }
260
261 return r_value;
262}
263
264
265static int
266post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
267 asn1p_expr_t *expr = NULL;
268 char *name;
269 asn1p_value_t *value;
270
271 if(check_expr->expr_type != ASN_BASIC_INTEGER
272 || check_expr->meta_type != AMT_VALUE) {
273 fprintf(stderr,
274 "CHECKER: Unsupported type of \"%s\" value: "
275 "%d at line %d of %s\n",
276 check_expr->Identifier,
277 check_expr->expr_type,
278 check_expr->_lineno,
279 mod->source_file_name
280 );
281 return -1;
282 }
283
284 assert(check_expr->meta_type == AMT_VALUE);
285
286 value = check_expr->value;
287 if(value == NULL || value->type != ATV_INTEGER) {
288 fprintf(stderr,
289 "CHECKER: Unsupported value type of \"%s\": "
290 "%d at line %d of %s\n",
291 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000292 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000293 expr->_lineno,
294 mod->source_file_name
295 );
296 return -1;
297 }
298
299 name = check_expr->Identifier + sizeof("check-") - 1;
300
301 /*
302 * Scan in search for the original.
303 */
304 TQ_FOR(expr, &(mod->members), next) {
305 if(strcmp(expr->Identifier, name) == 0)
306 break;
307 }
308
309 if(expr == NULL) {
310 fprintf(stderr,
311 "CHECKER: Value \"%s\" requested by "
312 "\"check-%s\" at line %d of %s is not found!\n",
313 name, name, check_expr->_lineno,
314 mod->source_file_name
315 );
316 return -1;
317 }
318
319 if(0 && expr->expr_type != check_expr->expr_type) {
320 fprintf(stderr,
321 "CHECKER: Value type of \"%s\" (=%d) at line %d "
322 "does not have desired type %d as requested by "
323 "\"check-%s\" in %s\n",
324 expr->Identifier,
325 expr->expr_type,
326 expr->_lineno,
327 check_expr->expr_type,
328 name,
329 mod->source_file_name
330 );
331 return -1;
332 }
333
334 if(expr->value == NULL
335 || expr->value->type != value->type) {
336 fprintf(stderr,
337 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
338 "does not have desired type %d as requested by "
339 "\"check-%s\" in %s\n",
340 expr->Identifier,
341 asn1f_printable_value(expr->value),
342 expr->value->type,
343 expr->_lineno,
344 value->type,
345 name,
346 mod->source_file_name
347 );
348 return -1;
349 }
350
351 assert(value->type = ATV_INTEGER);
352
353 return 0;
354}
355
356