blob: 86caa6cae728f49053cd9d6b9f4200dc17f423b0 [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
Lev Walkin93659562010-11-20 09:47:13 -08004#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +00005#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
Lev Walkine0d321a2014-09-11 01:28:57 -070016#ifndef TOP_SRCDIR
17#define TOP_SRCDIR_S ".."
18#else
19#define STRINGIFY_MACRO2(x) #x
20#define STRINGIFY_MACRO(x) STRINGIFY_MACRO2(x)
21#define TOP_SRCDIR_S STRINGIFY_MACRO(TOP_SRCDIR)
22#endif
23
Lev Walkinf15320b2004-06-03 03:38:44 +000024static int check(const char *fname,
25 enum asn1p_flags parser_flags,
26 enum asn1f_flags fixer_flags);
27static int post_fix_check(asn1p_t *asn);
28static int post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *expr);
29
30int
31main(int ac, char **av) {
Lev Walkin93659562010-11-20 09:47:13 -080032#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000033 intptr_t dir;
34 struct _finddata_t c_file;
35#else
Lev Walkinf15320b2004-06-03 03:38:44 +000036 struct dirent *dp;
37 DIR *dir;
Lev Walkin4efbfb72005-02-25 14:20:30 +000038#endif
Lev Walkinf15320b2004-06-03 03:38:44 +000039 int failed = 0;
40 int completed = 0;
41 enum asn1p_flags parser_flags = A1P_NOFLAGS;
42 enum asn1f_flags fixer_flags = A1F_NOFLAGS;
Lev Walkin4efbfb72005-02-25 14:20:30 +000043 const char *filename;
Lev Walkin07721d52005-02-25 14:35:02 +000044 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000045 int ret;
46
47 /*
48 * Just in case when one decides that some flags better be
49 * enabled during `ASN1_FIXER_FLAGS=1 make check` or some
50 * similar usage.
51 */
52 if(getenv("ASN1_PARSER_FLAGS"))
53 parser_flags = atoi(getenv("ASN1_PARSER_FLAGS"));
54 if(getenv("ASN1_FIXER_FLAGS"))
55 fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS"));
56
57 /*
58 * Go into a directory with tests.
59 */
60 if(ac <= 1) {
61 fprintf(stderr, "Testing in ./tests...\n");
62 ret = chdir("../tests");
63 assert(ret == 0);
Lev Walkin93659562010-11-20 09:47:13 -080064#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000065 dir = _findfirst("*.asn1", &c_file);
66 assert(dir != -1L);
67#else
Lev Walkinf15320b2004-06-03 03:38:44 +000068 dir = opendir(".");
69 assert(dir);
Lev Walkin93659562010-11-20 09:47:13 -080070#endif /* _WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +000071 } else {
72 dir = 0;
73 }
74
75 /*
76 * Scan every *.asn1 file and try to parse and fix it.
77 */
78 if(dir) {
Lev Walkin93659562010-11-20 09:47:13 -080079#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000080 do {
81 filename = c_file.name;
82#else
Lev Walkinf15320b2004-06-03 03:38:44 +000083 while((dp = readdir(dir))) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000084 filename = dp->d_name;
Lev Walkin93659562010-11-20 09:47:13 -080085#endif /* _WIN32 */
Lev Walkin07721d52005-02-25 14:35:02 +000086 len = strlen(filename);
Lev Walkin4b553412005-08-14 14:45:44 +000087 if(len <= 5 || strcmp(filename + len - 5, ".asn1"))
88 continue;
89 ret = check(filename, parser_flags, fixer_flags);
90 if(ret) {
91 fprintf(stderr, "FAILED: %s\n",
92 filename);
93 failed++;
Lev Walkinf15320b2004-06-03 03:38:44 +000094 }
Lev Walkin4b553412005-08-14 14:45:44 +000095 completed++;
Lev Walkin93659562010-11-20 09:47:13 -080096#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000097 } while(_findnext(dir, &c_file) == 0);
98 _findclose(dir);
99#else
Lev Walkinf15320b2004-06-03 03:38:44 +0000100 }
101 closedir(dir);
Lev Walkin93659562010-11-20 09:47:13 -0800102#endif /* _WIN32 */
Lev Walkin4efbfb72005-02-25 14:20:30 +0000103
Lev Walkinf15320b2004-06-03 03:38:44 +0000104
105 fprintf(stderr,
106 "Tests COMPLETED: %d\n"
107 "Tests FAILED: %d\n"
108 ,
109 completed, failed
110 );
111 } else {
112 int i;
113 for(i = 1; i < ac; i++) {
114 ret = check(av[i], parser_flags, fixer_flags);
115 if(ret) {
116 fprintf(stderr, "FAILED: %s\n", av[i]);
117 failed++;
118 }
119 completed++;
120 }
121 }
122
123 if(completed == 0) {
124 fprintf(stderr, "No tests defined?!\n");
125 exit(EX_NOINPUT);
126 }
127
128 if(failed)
129 exit(EX_DATAERR);
130 return 0;
131}
132
133static int
134check(const char *fname,
135 enum asn1p_flags parser_flags,
136 enum asn1f_flags fixer_flags) {
137 asn1p_t *asn;
138 int expected_parseable; /* Is it expected to be parseable? */
139 int expected_fix_code; /* What code a fixer must return */
140 int r_value = 0;
141
142 /*
143 * Figure out how the processing should go by inferring
144 * expectations from the file name.
145 */
146 if(strstr(fname, "-OK.")) {
147 expected_parseable = 1;
148 expected_fix_code = 0;
149 } else if(strstr(fname, "-NP.")) {
150 expected_parseable = 0;
151 expected_fix_code = 123; /* Does not matter */
152 } else if(strstr(fname, "-SE.")) {
153 expected_parseable = 1;
154 expected_fix_code = -1; /* Semantically incorrect */
155 } else if(strstr(fname, "-SW.")) {
156 expected_parseable = 1;
157 expected_fix_code = 1; /* Semantically suspicious */
158 } else {
159 fprintf(stderr, "%s: Invalid file name format\n", fname);
160 return -1;
161 }
162
Lev Walkin4b553412005-08-14 14:45:44 +0000163 /* Flag modifiers */
164 if(strstr(fname, "-blessSize-"))
165 fixer_flags |= A1F_EXTENDED_SizeConstraint;
166
Lev Walkinf15320b2004-06-03 03:38:44 +0000167 fprintf(stderr, "[=> %s]\n", fname);
168
169 /*
170 * Perform low-level parsing.
171 */
172 if(!expected_parseable)
173 fprintf(stderr, "Expecting error...\n");
174 asn = asn1p_parse_file(fname, parser_flags);
175 if(asn == NULL) {
176 if(expected_parseable) {
177 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
178 r_value = -1;
179 } else {
180 fprintf(stderr,
181 "Previous error is EXPECTED, no worry\n");
182 }
183 } else if(!expected_parseable) {
184 fprintf(stderr,
185 "The file \"%s\" is not expected to be parseable, "
186 "yet parsing was successfull!\n", fname);
187 r_value = -1;
188 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000189 if(!asn) return r_value;
190
191 if(r_value == 0) {
192 asn1p_t *std_asn;
Lev Walkine0d321a2014-09-11 01:28:57 -0700193 std_asn = asn1p_parse_file(TOP_SRCDIR_S "/skeletons/standard-modules/ASN1C-UsefulInformationObjectClasses.asn1", A1P_NOFLAGS);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000194 if(std_asn) {
195 asn1p_module_t *mod;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000196 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next))) {
197 mod->_tags |= MT_STANDARD_MODULE;
Lev Walkin6b3ff542006-03-06 14:51:00 +0000198 TQ_ADD(&(asn->modules), mod, mod_next);
Lev Walkin9c2285a2006-03-09 08:49:26 +0000199 }
Lev Walkin223000a2006-09-13 00:21:58 +0000200 asn1p_delete(std_asn);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000201 }
202 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000203
204 /*
205 * Perform semantical checks and fixes.
206 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000207 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000208 int ret;
209
210 if(expected_fix_code)
211 fprintf(stderr, "Expecting some problems...\n");
212
213 ret = asn1f_process(asn, fixer_flags, 0);
214 if(ret) {
215 if(ret == expected_fix_code) {
216 fprintf(stderr,
217 "Previous error is EXPECTED, "
218 "no worry\n");
219 } else {
220 fprintf(stderr,
221 "Cannot process file \"%s\": %d\n",
222 fname, ret);
223 r_value = -1;
224 }
225 } else if(ret != expected_fix_code) {
226 fprintf(stderr,
227 "File \"%s\" is expected "
228 "to be semantically incorrect, "
229 "yet processing was successful!\n",
230 fname);
231 r_value = -1;
232 }
233 }
234
235 /*
236 * Check validity of some values, if grammar has special
237 * instructions for that.
238 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000239 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000240 if(post_fix_check(asn))
241 r_value = -1;
242 }
243
244 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000245 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000246 */
Lev Walkin55f106a2006-09-15 16:34:12 +0000247#ifdef CLEAN_EVERYTHING
Lev Walkin223000a2006-09-13 00:21:58 +0000248 asn1p_delete(asn);
Lev Walkin55f106a2006-09-15 16:34:12 +0000249#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000250
251 return r_value;
252}
253
254
255static int
256post_fix_check(asn1p_t *asn) {
257 asn1p_module_t *mod;
258 asn1p_expr_t *expr;
259 int r_value = 0;
260
261 TQ_FOR(mod, &(asn->modules), mod_next) {
262 TQ_FOR(expr, &(mod->members), next) {
263 assert(expr->Identifier);
264 if(strncmp(expr->Identifier, "check-", 6) == 0) {
265 if(post_fix_check_element(mod, expr))
266 r_value = -1;
267 }
268 }
269 }
270
271 return r_value;
272}
273
274
275static int
276post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
277 asn1p_expr_t *expr = NULL;
278 char *name;
279 asn1p_value_t *value;
280
281 if(check_expr->expr_type != ASN_BASIC_INTEGER
282 || check_expr->meta_type != AMT_VALUE) {
283 fprintf(stderr,
284 "CHECKER: Unsupported type of \"%s\" value: "
285 "%d at line %d of %s\n",
286 check_expr->Identifier,
287 check_expr->expr_type,
288 check_expr->_lineno,
289 mod->source_file_name
290 );
291 return -1;
292 }
293
294 assert(check_expr->meta_type == AMT_VALUE);
295
296 value = check_expr->value;
297 if(value == NULL || value->type != ATV_INTEGER) {
298 fprintf(stderr,
299 "CHECKER: Unsupported value type of \"%s\": "
300 "%d at line %d of %s\n",
301 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000302 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000303 expr->_lineno,
304 mod->source_file_name
305 );
306 return -1;
307 }
308
309 name = check_expr->Identifier + sizeof("check-") - 1;
310
311 /*
312 * Scan in search for the original.
313 */
314 TQ_FOR(expr, &(mod->members), next) {
315 if(strcmp(expr->Identifier, name) == 0)
316 break;
317 }
318
319 if(expr == NULL) {
320 fprintf(stderr,
321 "CHECKER: Value \"%s\" requested by "
322 "\"check-%s\" at line %d of %s is not found!\n",
323 name, name, check_expr->_lineno,
324 mod->source_file_name
325 );
326 return -1;
327 }
328
329 if(0 && expr->expr_type != check_expr->expr_type) {
330 fprintf(stderr,
331 "CHECKER: Value type of \"%s\" (=%d) at line %d "
332 "does not have desired type %d as requested by "
333 "\"check-%s\" in %s\n",
334 expr->Identifier,
335 expr->expr_type,
336 expr->_lineno,
337 check_expr->expr_type,
338 name,
339 mod->source_file_name
340 );
341 return -1;
342 }
343
344 if(expr->value == NULL
345 || expr->value->type != value->type) {
346 fprintf(stderr,
347 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
348 "does not have desired type %d as requested by "
349 "\"check-%s\" in %s\n",
350 expr->Identifier,
351 asn1f_printable_value(expr->value),
352 expr->value->type,
353 expr->_lineno,
354 value->type,
355 name,
356 mod->source_file_name
357 );
358 return -1;
359 }
360
361 assert(value->type = ATV_INTEGER);
362
363 return 0;
364}
365
366