]> mj.ucw.cz Git - moe.git/blob - judge/token.c
Isolate: Silenced signed/unsigned comparison warning
[moe.git] / judge / token.c
1 /*
2  *      Tokenizer for judges
3  *
4  *      (c) 2007 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <string.h>
11 #include <limits.h>
12 #include <errno.h>
13
14 #include "judge.h"
15
16 #define DEFAULT_MAX_TOKEN (32 << 20)
17
18 void tok_init(struct tokenizer *t, struct stream *s)
19 {
20   memset(t, 0, sizeof(*t));
21   t->stream = s;
22   t->bufsize = 1;
23   t->token = xmalloc(t->bufsize);
24   t->maxsize = DEFAULT_MAX_TOKEN;
25   t->line = 1;
26 }
27
28 void tok_cleanup(struct tokenizer *t)
29 {
30   free(t->token);
31 }
32
33 void tok_err(struct tokenizer *t, char *msg, ...)
34 {
35   va_list args;
36   va_start(args, msg);
37   fprintf(stderr, "Error at %s line %d:\n", t->stream->name, t->line);
38   vfprintf(stderr, msg, args);
39   fputc('\n', stderr);
40   va_end(args);
41   exit(1);
42 }
43
44 static inline int is_white(int c)
45 {
46   return (c == ' ' || c == '\t' || c == '\r' || c == '\n');
47 }
48
49 char *get_token(struct tokenizer *t)
50 {
51   unsigned int len = 0;
52   int c;
53
54   // Skip whitespace
55   do
56     {
57       c = sgetc(t->stream);
58       if (c < 0)
59         return NULL;
60       if (c == '\n')
61         {
62           t->line++;
63           if (t->flags & TF_REPORT_LINES)
64             {
65               t->toksize = 0;
66               t->token[0] = 0;
67               return t->token;
68             }
69         }
70     }
71   while (is_white(c));
72
73   // This is the token itself
74   do
75     {
76       t->token[len++] = c;
77       if (len >= t->bufsize)
78         {
79           if (len > t->maxsize)
80             tok_err(t, "Token too long");
81           t->bufsize *= 2;
82           if (t->bufsize > t->maxsize)
83             t->bufsize = t->maxsize+1;
84           t->token = xrealloc(t->token, t->bufsize);
85         }
86       c = sgetc(t->stream);
87     }
88   while (c >= 0 && !is_white(c));
89   if (c >= 0)
90     sungetc(t->stream);
91
92   t->token[len] = 0;
93   t->toksize = len;
94   return t->token;
95 }
96
97 /*
98  *  Parsing functions. They return 1 if successfully parsed, 0 otherwise.
99  */
100
101 #define PARSE(f, ...)                                           \
102         char *end;                                              \
103         errno = 0;                                              \
104         if (!t->toksize)                                        \
105           return 0;                                             \
106         *x = f(t->token, &end, ##__VA_ARGS__);                  \
107         return !(errno || (unsigned char *) end != t->token + t->toksize)
108
109 int to_long(struct tokenizer *t, long int *x)
110 {
111   PARSE(strtol, 10);
112 }
113
114 int to_ulong(struct tokenizer *t, unsigned long int *x)
115 {
116   if (t->token[0] == '-')               // strtoul accepts negative numbers, but we don't
117     return 0;
118   PARSE(strtoul, 10);
119 }
120
121 int to_double(struct tokenizer *t, double *x)
122 {
123   PARSE(strtod);
124 }
125
126 int to_long_double(struct tokenizer *t, long double *x)
127 {
128   PARSE(strtold);
129 }
130
131 int to_int(struct tokenizer *t, int *x)
132 {
133   long int y;
134   if (!to_long(t, &y) || y > LONG_MAX || y < LONG_MIN)
135     return 0;
136   *x = y;
137   return 1;
138 }
139
140 int to_uint(struct tokenizer *t, unsigned int *x)
141 {
142   unsigned long int y;
143   if (!to_ulong(t, &y) || y > ULONG_MAX)
144     return 0;
145   *x = y;
146   return 1;
147 }
148
149 #define GET(fn, type)                                                                   \
150         type get_##fn(struct tokenizer *t)                                              \
151         {                                                                               \
152           type x;                                                                       \
153           if (!get_token(t))                                                            \
154             tok_err(t, "Unexpected end of file");                                       \
155           if (!to_##fn(t, &x))                                                          \
156             tok_err(t, "Expected " #fn);                                                \
157           return x;                                                                     \
158         }
159
160 GET(int, int)
161 GET(uint, unsigned int)
162 GET(long, long int)
163 GET(ulong, unsigned long int)
164 GET(double, double)
165 GET(long_double, long double)
166
167 void get_nl(struct tokenizer *t)
168 {
169   char *tok = get_token(t);
170   if (tok && *tok)
171     tok_err(t, "Expected end of line");
172 }