2 * A judge comparing two sequences of tokens
4 * (c) 2007 Martin Krulis <bobrik@matfyz.cz>
5 * (c) 2007 Martin Mares <mj@ucw.cz>
16 static int ignore_nl, ignore_trailing_nl, ignore_case;
18 static double rel_eps = 1e-5;
19 static double abs_eps = 1e-30;
21 static int tokens_equal(struct tokenizer *t1, struct tokenizer *t2)
26 if (to_double(t1, &x1) && to_double(t2, &x2))
30 double eps = fabs(x2 * rel_eps);
33 return (fabs(x1-x2) <= eps);
35 // If they fail to convert, compare them as strings.
37 return !(ignore_case ? strcasecmp : strcmp)(t1->token, t2->token);
40 static int trailing_nl(struct tokenizer *t)
42 // Ignore empty lines at the end of file
43 if (t->token[0] || !ignore_trailing_nl)
45 t->flags &= ~TF_REPORT_LINES;
49 static void usage(void)
51 fprintf(stderr, "Usage: judge-tok [<options>] <output> <correct>\n\
54 -n\t\tIgnore newlines\n\
55 -t\t\tIgnore newlines at the end of file\n\
57 -r\t\tMatch tokens as real numbers and allow small differences:\n\
58 -e <epsilon>\tSet maximum allowed relative error (default: %g)\n\
59 -E <epsilon>\tSet maximum allowed absolute error (default: %g)\n\
64 int main(int argc, char **argv)
66 struct tokenizer t1, t2;
69 while ((opt = getopt(argc, argv, "ntire:E:")) >= 0)
85 rel_eps = atof(optarg);
88 abs_eps = atof(optarg);
93 if (optind + 2 != argc)
96 tok_init(&t1, sopen_read(argv[optind]));
97 tok_init(&t2, sopen_read(argv[optind+1]));
99 t1.flags = t2.flags = TF_REPORT_LINES;
103 char *a = get_token(&t1), *b = get_token(&t2);
106 if (b && !trailing_nl(&t2))
107 tok_err(&t1, "Ends too early");
112 if (a && !trailing_nl(&t1))
113 tok_err(&t2, "Garbage at the end");
116 else if (!tokens_equal(&t1, &t2))
117 tok_err(&t1, "Found <%s>, expected <%s>", a, b);