blob: 8808f28dbc842e2106e0bd320b111db0e355356d [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;
36 int 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 */
78 int len = strlen(filename);
79 if(len && strcmp(filename + len - 5, ".asn1") == 0) {
80 ret = check(filename, parser_flags,fixer_flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000081 if(ret) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000082 fprintf(stderr, "FAILED: %s\n",
83 filename);
Lev Walkinf15320b2004-06-03 03:38:44 +000084 failed++;
85 }
86 completed++;
87 }
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
155 fprintf(stderr, "[=> %s]\n", fname);
156
157 /*
158 * Perform low-level parsing.
159 */
160 if(!expected_parseable)
161 fprintf(stderr, "Expecting error...\n");
162 asn = asn1p_parse_file(fname, parser_flags);
163 if(asn == NULL) {
164 if(expected_parseable) {
165 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
166 r_value = -1;
167 } else {
168 fprintf(stderr,
169 "Previous error is EXPECTED, no worry\n");
170 }
171 } else if(!expected_parseable) {
172 fprintf(stderr,
173 "The file \"%s\" is not expected to be parseable, "
174 "yet parsing was successfull!\n", fname);
175 r_value = -1;
176 }
177
178 /*
179 * Perform semantical checks and fixes.
180 */
181 if(asn && r_value == 0) {
182 int ret;
183
184 if(expected_fix_code)
185 fprintf(stderr, "Expecting some problems...\n");
186
187 ret = asn1f_process(asn, fixer_flags, 0);
188 if(ret) {
189 if(ret == expected_fix_code) {
190 fprintf(stderr,
191 "Previous error is EXPECTED, "
192 "no worry\n");
193 } else {
194 fprintf(stderr,
195 "Cannot process file \"%s\": %d\n",
196 fname, ret);
197 r_value = -1;
198 }
199 } else if(ret != expected_fix_code) {
200 fprintf(stderr,
201 "File \"%s\" is expected "
202 "to be semantically incorrect, "
203 "yet processing was successful!\n",
204 fname);
205 r_value = -1;
206 }
207 }
208
209 /*
210 * Check validity of some values, if grammar has special
211 * instructions for that.
212 */
213 if(asn && r_value == 0) {
214 if(post_fix_check(asn))
215 r_value = -1;
216 }
217
218 /*
219 * TODO: destroy the asn.
220 */
221
222 return r_value;
223}
224
225
226static int
227post_fix_check(asn1p_t *asn) {
228 asn1p_module_t *mod;
229 asn1p_expr_t *expr;
230 int r_value = 0;
231
232 TQ_FOR(mod, &(asn->modules), mod_next) {
233 TQ_FOR(expr, &(mod->members), next) {
234 assert(expr->Identifier);
235 if(strncmp(expr->Identifier, "check-", 6) == 0) {
236 if(post_fix_check_element(mod, expr))
237 r_value = -1;
238 }
239 }
240 }
241
242 return r_value;
243}
244
245
246static int
247post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
248 asn1p_expr_t *expr = NULL;
249 char *name;
250 asn1p_value_t *value;
251
252 if(check_expr->expr_type != ASN_BASIC_INTEGER
253 || check_expr->meta_type != AMT_VALUE) {
254 fprintf(stderr,
255 "CHECKER: Unsupported type of \"%s\" value: "
256 "%d at line %d of %s\n",
257 check_expr->Identifier,
258 check_expr->expr_type,
259 check_expr->_lineno,
260 mod->source_file_name
261 );
262 return -1;
263 }
264
265 assert(check_expr->meta_type == AMT_VALUE);
266
267 value = check_expr->value;
268 if(value == NULL || value->type != ATV_INTEGER) {
269 fprintf(stderr,
270 "CHECKER: Unsupported value type of \"%s\": "
271 "%d at line %d of %s\n",
272 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000273 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000274 expr->_lineno,
275 mod->source_file_name
276 );
277 return -1;
278 }
279
280 name = check_expr->Identifier + sizeof("check-") - 1;
281
282 /*
283 * Scan in search for the original.
284 */
285 TQ_FOR(expr, &(mod->members), next) {
286 if(strcmp(expr->Identifier, name) == 0)
287 break;
288 }
289
290 if(expr == NULL) {
291 fprintf(stderr,
292 "CHECKER: Value \"%s\" requested by "
293 "\"check-%s\" at line %d of %s is not found!\n",
294 name, name, check_expr->_lineno,
295 mod->source_file_name
296 );
297 return -1;
298 }
299
300 if(0 && expr->expr_type != check_expr->expr_type) {
301 fprintf(stderr,
302 "CHECKER: Value type of \"%s\" (=%d) at line %d "
303 "does not have desired type %d as requested by "
304 "\"check-%s\" in %s\n",
305 expr->Identifier,
306 expr->expr_type,
307 expr->_lineno,
308 check_expr->expr_type,
309 name,
310 mod->source_file_name
311 );
312 return -1;
313 }
314
315 if(expr->value == NULL
316 || expr->value->type != value->type) {
317 fprintf(stderr,
318 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
319 "does not have desired type %d as requested by "
320 "\"check-%s\" in %s\n",
321 expr->Identifier,
322 asn1f_printable_value(expr->value),
323 expr->value->type,
324 expr->_lineno,
325 value->type,
326 name,
327 mod->source_file_name
328 );
329 return -1;
330 }
331
332 assert(value->type = ATV_INTEGER);
333
334 return 0;
335}
336
337