diff options
author | vlm <vlm@59561ff5-6e30-0410-9f3c-9617f08c8826> | 2004-06-03 03:38:44 +0000 |
---|---|---|
committer | vlm <vlm@59561ff5-6e30-0410-9f3c-9617f08c8826> | 2004-06-03 03:38:44 +0000 |
commit | fa67ddcad9ce4ce04668d8ce46f4ac0057c914c2 (patch) | |
tree | 33461d45122896c6dde35f82f5c7d19b62004a6b /libasn1fix/check_fixer.c | |
parent | 4cc3ff02fa66f711b10608e46a509bfcec57a876 (diff) |
Initial revision
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@2 59561ff5-6e30-0410-9f3c-9617f08c8826
Diffstat (limited to 'libasn1fix/check_fixer.c')
-rw-r--r-- | libasn1fix/check_fixer.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/libasn1fix/check_fixer.c b/libasn1fix/check_fixer.c new file mode 100644 index 00000000..21c5b12f --- /dev/null +++ b/libasn1fix/check_fixer.c @@ -0,0 +1,313 @@ +#undef NDEBUG +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <dirent.h> +#include <errno.h> +#include <sysexits.h> + +#include "asn1fix.h" +#include "asn1fix_internal.h" + +static int check(const char *fname, + enum asn1p_flags parser_flags, + enum asn1f_flags fixer_flags); +static int post_fix_check(asn1p_t *asn); +static int post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *expr); + +int +main(int ac, char **av) { + struct dirent *dp; + DIR *dir; + int failed = 0; + int completed = 0; + enum asn1p_flags parser_flags = A1P_NOFLAGS; + enum asn1f_flags fixer_flags = A1F_NOFLAGS; + int ret; + + /* + * Just in case when one decides that some flags better be + * enabled during `ASN1_FIXER_FLAGS=1 make check` or some + * similar usage. + */ + if(getenv("ASN1_PARSER_FLAGS")) + parser_flags = atoi(getenv("ASN1_PARSER_FLAGS")); + if(getenv("ASN1_FIXER_FLAGS")) + fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS")); + + /* + * Go into a directory with tests. + */ + if(ac <= 1) { + fprintf(stderr, "Testing in ./tests...\n"); + ret = chdir("../tests"); + assert(ret == 0); + dir = opendir("."); + assert(dir); + } else { + dir = 0; + } + + /* + * Scan every *.asn1 file and try to parse and fix it. + */ + if(dir) { + while((dp = readdir(dir))) { + int len = strlen(dp->d_name); + if(len && strcmp(dp->d_name + len - 5, ".asn1") == 0) { + ret = check(dp->d_name, + parser_flags, fixer_flags); + if(ret) { + fprintf(stderr, + "FAILED: %s\n", + dp->d_name); + failed++; + } + completed++; + } + } + closedir(dir); + + fprintf(stderr, + "Tests COMPLETED: %d\n" + "Tests FAILED: %d\n" + , + completed, failed + ); + } else { + int i; + for(i = 1; i < ac; i++) { + ret = check(av[i], parser_flags, fixer_flags); + if(ret) { + fprintf(stderr, "FAILED: %s\n", av[i]); + failed++; + } + completed++; + } + } + + if(completed == 0) { + fprintf(stderr, "No tests defined?!\n"); + exit(EX_NOINPUT); + } + + if(failed) + exit(EX_DATAERR); + return 0; +} + +static int +check(const char *fname, + enum asn1p_flags parser_flags, + enum asn1f_flags fixer_flags) { + asn1p_t *asn; + int expected_parseable; /* Is it expected to be parseable? */ + int expected_fix_code; /* What code a fixer must return */ + int r_value = 0; + + /* + * Figure out how the processing should go by inferring + * expectations from the file name. + */ + if(strstr(fname, "-OK.")) { + expected_parseable = 1; + expected_fix_code = 0; + } else if(strstr(fname, "-NP.")) { + expected_parseable = 0; + expected_fix_code = 123; /* Does not matter */ + } else if(strstr(fname, "-SE.")) { + expected_parseable = 1; + expected_fix_code = -1; /* Semantically incorrect */ + } else if(strstr(fname, "-SW.")) { + expected_parseable = 1; + expected_fix_code = 1; /* Semantically suspicious */ + } else { + fprintf(stderr, "%s: Invalid file name format\n", fname); + return -1; + } + + fprintf(stderr, "[=> %s]\n", fname); + + /* + * Perform low-level parsing. + */ + if(!expected_parseable) + fprintf(stderr, "Expecting error...\n"); + asn = asn1p_parse_file(fname, parser_flags); + if(asn == NULL) { + if(expected_parseable) { + fprintf(stderr, "Cannot parse file \"%s\"\n", fname); + r_value = -1; + } else { + fprintf(stderr, + "Previous error is EXPECTED, no worry\n"); + } + } else if(!expected_parseable) { + fprintf(stderr, + "The file \"%s\" is not expected to be parseable, " + "yet parsing was successfull!\n", fname); + r_value = -1; + } + + /* + * Perform semantical checks and fixes. + */ + if(asn && r_value == 0) { + int ret; + + if(expected_fix_code) + fprintf(stderr, "Expecting some problems...\n"); + + ret = asn1f_process(asn, fixer_flags, 0); + if(ret) { + if(ret == expected_fix_code) { + fprintf(stderr, + "Previous error is EXPECTED, " + "no worry\n"); + } else { + fprintf(stderr, + "Cannot process file \"%s\": %d\n", + fname, ret); + r_value = -1; + } + } else if(ret != expected_fix_code) { + fprintf(stderr, + "File \"%s\" is expected " + "to be semantically incorrect, " + "yet processing was successful!\n", + fname); + r_value = -1; + } + } + + /* + * Check validity of some values, if grammar has special + * instructions for that. + */ + if(asn && r_value == 0) { + if(post_fix_check(asn)) + r_value = -1; + } + + /* + * TODO: destroy the asn. + */ + + return r_value; +} + + +static int +post_fix_check(asn1p_t *asn) { + asn1p_module_t *mod; + asn1p_expr_t *expr; + int r_value = 0; + + TQ_FOR(mod, &(asn->modules), mod_next) { + TQ_FOR(expr, &(mod->members), next) { + assert(expr->Identifier); + if(strncmp(expr->Identifier, "check-", 6) == 0) { + if(post_fix_check_element(mod, expr)) + r_value = -1; + } + } + } + + return r_value; +} + + +static int +post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) { + asn1p_expr_t *expr = NULL; + char *name; + asn1p_value_t *value; + + if(check_expr->expr_type != ASN_BASIC_INTEGER + || check_expr->meta_type != AMT_VALUE) { + fprintf(stderr, + "CHECKER: Unsupported type of \"%s\" value: " + "%d at line %d of %s\n", + check_expr->Identifier, + check_expr->expr_type, + check_expr->_lineno, + mod->source_file_name + ); + return -1; + } + + assert(check_expr->meta_type == AMT_VALUE); + + value = check_expr->value; + if(value == NULL || value->type != ATV_INTEGER) { + fprintf(stderr, + "CHECKER: Unsupported value type of \"%s\": " + "%d at line %d of %s\n", + check_expr->Identifier, + value?value->type:-1, + expr->_lineno, + mod->source_file_name + ); + return -1; + } + + name = check_expr->Identifier + sizeof("check-") - 1; + + /* + * Scan in search for the original. + */ + TQ_FOR(expr, &(mod->members), next) { + if(strcmp(expr->Identifier, name) == 0) + break; + } + + if(expr == NULL) { + fprintf(stderr, + "CHECKER: Value \"%s\" requested by " + "\"check-%s\" at line %d of %s is not found!\n", + name, name, check_expr->_lineno, + mod->source_file_name + ); + return -1; + } + + if(0 && expr->expr_type != check_expr->expr_type) { + fprintf(stderr, + "CHECKER: Value type of \"%s\" (=%d) at line %d " + "does not have desired type %d as requested by " + "\"check-%s\" in %s\n", + expr->Identifier, + expr->expr_type, + expr->_lineno, + check_expr->expr_type, + name, + mod->source_file_name + ); + return -1; + } + + if(expr->value == NULL + || expr->value->type != value->type) { + fprintf(stderr, + "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d " + "does not have desired type %d as requested by " + "\"check-%s\" in %s\n", + expr->Identifier, + asn1f_printable_value(expr->value), + expr->value->type, + expr->_lineno, + value->type, + name, + mod->source_file_name + ); + return -1; + } + + assert(value->type = ATV_INTEGER); + + return 0; +} + + |