X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=judge%2Fjudge-tok.c;h=b55195737155ff605368ea92a9e4f34286033132;hb=16cdbe07d6da578e69dcbc35115abe90ab4b476e;hp=bb4e95f0ed08bb4990bfab5b131998f20d2498c5;hpb=cc2f58454e17a6212a23c27e70e6afcf1e054346;p=moe.git diff --git a/judge/judge-tok.c b/judge/judge-tok.c index bb4e95f..b551957 100644 --- a/judge/judge-tok.c +++ b/judge/judge-tok.c @@ -6,33 +6,96 @@ */ #include +#include #include +#include +#include #include "judge.h" +static int ignore_nl, ignore_trailing_nl, ignore_case; +static int real_mode; +static double rel_eps = 1e-5; +static double abs_eps = 1e-30; + +static int tokens_equal(struct tokenizer *t1, struct tokenizer *t2) +{ + if (real_mode) + { + double x1, x2; + if (to_double(t1, &x1) && to_double(t2, &x2)) + { + if (x1 == x2) + return 1; + double eps = fabs(x2 * rel_eps); + if (eps < abs_eps) + eps = abs_eps; + return (fabs(x1-x2) <= eps); + } + // If they fail to convert, compare them as strings. + } + return !(ignore_case ? strcasecmp : strcmp)(t1->token, t2->token); +} + static int trailing_nl(struct tokenizer *t) { // Ignore empty lines at the end of file - if (t->token[0]) + if (t->token[0] || !ignore_trailing_nl) return 0; t->flags &= ~TF_REPORT_LINES; return !get_token(t); } +static void usage(void) +{ + fprintf(stderr, "Usage: judge-tok [] \n\ +\n\ +Options:\n\ +-n\t\tIgnore newlines\n\ +-t\t\tIgnore newlines at the end of file\n\ +-i\t\tIgnore case\n\ +-r\t\tMatch tokens as real numbers and allow small differences:\n\ +-e \tSet maximum allowed relative error (default: %g)\n\ +-E \tSet maximum allowed absolute error (default: %g)\n\ +", rel_eps, abs_eps); + exit(2); +} + int main(int argc, char **argv) { struct tokenizer t1, t2; - int report_lines = 1; - - if (argc != 3 && argc != 4) - die("Usage: judge-tok [-n] "); + int opt; - // Check for -n parameter - report_lines = !(argc == 4 && !strcmp(argv[1], "-n")); + while ((opt = getopt(argc, argv, "ntire:E:")) >= 0) + switch (opt) + { + case 'n': + ignore_nl++; + break; + case 't': + ignore_trailing_nl++; + break; + case 'i': + ignore_case++; + break; + case 'r': + real_mode++; + break; + case 'e': + rel_eps = atof(optarg); + break; + case 'E': + abs_eps = atof(optarg); + break; + default: + usage(); + } + if (optind + 2 != argc) + usage(); - tok_init(&t1, sopen_read(argv[argc-2])); - tok_init(&t2, sopen_read(argv[argc-1])); - if (report_lines) + tok_init(&t1, sopen_read(argv[optind])); + tok_init(&t2, sopen_read(argv[optind+1])); + if (!ignore_nl) t1.flags = t2.flags = TF_REPORT_LINES; for (;;) @@ -50,7 +113,7 @@ int main(int argc, char **argv) tok_err(&t2, "Garbage at the end"); break; } - else if (strcmp(a, b)) + else if (!tokens_equal(&t1, &t2)) tok_err(&t1, "Found <%s>, expected <%s>", a, b); }