blob: a64d9bd1785c5621e528127fdeae1d2772289b86 [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;
188 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next)))
189 TQ_ADD(&(asn->modules), mod, mod_next);
190 asn1p_free(std_asn);
191 }
192 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000193
194 /*
195 * Perform semantical checks and fixes.
196 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000197 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000198 int ret;
199
200 if(expected_fix_code)
201 fprintf(stderr, "Expecting some problems...\n");
202
203 ret = asn1f_process(asn, fixer_flags, 0);
204 if(ret) {
205 if(ret == expected_fix_code) {
206 fprintf(stderr,
207 "Previous error is EXPECTED, "
208 "no worry\n");
209 } else {
210 fprintf(stderr,
211 "Cannot process file \"%s\": %d\n",
212 fname, ret);
213 r_value = -1;
214 }
215 } else if(ret != expected_fix_code) {
216 fprintf(stderr,
217 "File \"%s\" is expected "
218 "to be semantically incorrect, "
219 "yet processing was successful!\n",
220 fname);
221 r_value = -1;
222 }
223 }
224
225 /*
226 * Check validity of some values, if grammar has special
227 * instructions for that.
228 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000229 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000230 if(post_fix_check(asn))
231 r_value = -1;
232 }
233
234 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000235 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000236 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000237 asn1p_free(asn);
Lev Walkinf15320b2004-06-03 03:38:44 +0000238
239 return r_value;
240}
241
242
243static int
244post_fix_check(asn1p_t *asn) {
245 asn1p_module_t *mod;
246 asn1p_expr_t *expr;
247 int r_value = 0;
248
249 TQ_FOR(mod, &(asn->modules), mod_next) {
250 TQ_FOR(expr, &(mod->members), next) {
251 assert(expr->Identifier);
252 if(strncmp(expr->Identifier, "check-", 6) == 0) {
253 if(post_fix_check_element(mod, expr))
254 r_value = -1;
255 }
256 }
257 }
258
259 return r_value;
260}
261
262
263static int
264post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
265 asn1p_expr_t *expr = NULL;
266 char *name;
267 asn1p_value_t *value;
268
269 if(check_expr->expr_type != ASN_BASIC_INTEGER
270 || check_expr->meta_type != AMT_VALUE) {
271 fprintf(stderr,
272 "CHECKER: Unsupported type of \"%s\" value: "
273 "%d at line %d of %s\n",
274 check_expr->Identifier,
275 check_expr->expr_type,
276 check_expr->_lineno,
277 mod->source_file_name
278 );
279 return -1;
280 }
281
282 assert(check_expr->meta_type == AMT_VALUE);
283
284 value = check_expr->value;
285 if(value == NULL || value->type != ATV_INTEGER) {
286 fprintf(stderr,
287 "CHECKER: Unsupported value type of \"%s\": "
288 "%d at line %d of %s\n",
289 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000290 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000291 expr->_lineno,
292 mod->source_file_name
293 );
294 return -1;
295 }
296
297 name = check_expr->Identifier + sizeof("check-") - 1;
298
299 /*
300 * Scan in search for the original.
301 */
302 TQ_FOR(expr, &(mod->members), next) {
303 if(strcmp(expr->Identifier, name) == 0)
304 break;
305 }
306
307 if(expr == NULL) {
308 fprintf(stderr,
309 "CHECKER: Value \"%s\" requested by "
310 "\"check-%s\" at line %d of %s is not found!\n",
311 name, name, check_expr->_lineno,
312 mod->source_file_name
313 );
314 return -1;
315 }
316
317 if(0 && expr->expr_type != check_expr->expr_type) {
318 fprintf(stderr,
319 "CHECKER: Value type of \"%s\" (=%d) at line %d "
320 "does not have desired type %d as requested by "
321 "\"check-%s\" in %s\n",
322 expr->Identifier,
323 expr->expr_type,
324 expr->_lineno,
325 check_expr->expr_type,
326 name,
327 mod->source_file_name
328 );
329 return -1;
330 }
331
332 if(expr->value == NULL
333 || expr->value->type != value->type) {
334 fprintf(stderr,
335 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
336 "does not have desired type %d as requested by "
337 "\"check-%s\" in %s\n",
338 expr->Identifier,
339 asn1f_printable_value(expr->value),
340 expr->value->type,
341 expr->_lineno,
342 value->type,
343 name,
344 mod->source_file_name
345 );
346 return -1;
347 }
348
349 assert(value->type = ATV_INTEGER);
350
351 return 0;
352}
353
354