tok: accept uppercase hex digits
[neatcc.git] / tok.c
blob473b4a182a0b7369b235390fbc29efdf6f9dfd21
1 #include <ctype.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "tok.h"
7 extern int cpp_read(char *s);
9 static char buf[BUFSIZE];
10 static int len;
11 static int cur;
12 static char name[NAMELEN];
13 static int next = -1;
14 static int pre;
16 static struct {
17 char *name;
18 unsigned id;
19 } kwds[] = {
20 {"void", TOK_VOID},
21 {"static", TOK_STATIC},
22 {"extern", TOK_EXTERN},
23 {"return", TOK_RETURN},
24 {"unsigned", TOK_UNSIGNED},
25 {"signed", TOK_SIGNED},
26 {"short", TOK_SHORT},
27 {"long", TOK_LONG},
28 {"int", TOK_INT},
29 {"char", TOK_CHAR},
30 {"struct", TOK_STRUCT},
31 {"union", TOK_UNION},
32 {"enum", TOK_ENUM},
33 {"typedef", TOK_TYPEDEF},
34 {"if", TOK_IF},
35 {"else", TOK_ELSE},
36 {"for", TOK_FOR},
37 {"while", TOK_WHILE},
38 {"do", TOK_DO},
39 {"switch", TOK_SWITCH},
40 {"case", TOK_CASE},
41 {"sizeof", TOK_SIZEOF},
42 {"break", TOK_BREAK},
43 {"continue", TOK_CONTINUE},
44 {"default", TOK_DEFAULT},
45 {"goto", TOK_GOTO},
48 static char *tok3[] = {
49 "<<", ">>", "++", "--", "<<=", ">>=", "...", "+=", "-=", "*=", "/=",
50 "%=", "|=", "&=", "^=", "&&", "||", "==", "!=", "<=", ">=", "->", "/*"
53 static int get_tok3(int num)
55 int i;
56 for (i = 0; i < ARRAY_SIZE(tok3); i++)
57 if (num == TOK3(tok3[i]))
58 return num;
59 return 0;
62 static char *esc_code = "abefnrtv";
63 static char *esc = "\a\b\e\f\n\r\t\v";
64 static char *digs = "0123456789abcdef";
66 static int esc_char(int *c, char *s)
68 if (*s != '\\') {
69 *c = *s;
70 return 1;
72 if (strchr(esc_code, s[1])) {
73 *c = esc[strchr(esc_code, s[1]) - esc_code];
74 return 2;
76 if (isdigit(s[1]) || s[1] == 'x') {
77 int ret = 0;
78 int base = 8;
79 int i = 1;
80 char *d;
81 if (s[1] == 'x') {
82 base = 16;
83 i++;
85 while ((d = strchr(digs, s[i]))) {
86 ret *= base;
87 ret += d - digs;
88 i++;
90 *c = ret;
91 return i;
93 *c = s[1];
94 return 2;
97 static long num;
99 long tok_num(void)
101 return num;
104 static void readnum(void)
106 int base = 10;
107 if (buf[cur] == '0' && buf[cur + 1] == 'x') {
108 base = 16;
109 cur += 2;
111 if (strchr(digs, buf[cur])) {
112 long result = 0;
113 char *c;
114 if (base == 10 && buf[cur] == '0')
115 base = 8;
116 while (cur < len && (c = strchr(digs, tolower(buf[cur])))) {
117 result *= base;
118 result += c - digs;
119 cur++;
121 num = result;
122 while (cur < len && tolower(buf[cur]) == 'u' ||
123 tolower(buf[cur]) == 'l')
124 cur++;
125 return;
127 if (buf[cur] == '\'') {
128 int ret;
129 cur += 2 + esc_char(&ret, buf + cur + 1);
130 num = ret;
131 return;
133 num = -1;
136 static char str[BUFSIZE];
137 static int str_len;
139 int tok_str(char *buf)
141 if (buf)
142 memcpy(buf, str, str_len);
143 return str_len;
146 static int readstr(char *out)
148 char *s = out;
149 char *r = buf + cur;
150 char *e = buf + len;
151 r++;
152 while (r < e && *r != '"') {
153 if (*r == '\\') {
154 int c;
155 r += esc_char(&c, r);
156 *s++ = c;
157 } else {
158 *s++ = *r++;
161 *s++ = '\0';
162 cur = r - buf + 1;
163 return s - out - 1;
166 static int id_char(int c)
168 return isalnum(c) || c == '_';
171 static int skipws(void)
173 while (1) {
174 if (cur == len) {
175 int r;
176 while (!(r = cpp_read(buf + cur)))
178 if (r == -1)
179 return 1;
180 len += r;
182 while (cur < len && isspace(buf[cur]))
183 cur++;
184 if (cur == len)
185 continue;
186 if (TOK2(buf + cur) != TOK2("/*"))
187 return 0;
188 while (++cur < len) {
189 if (buf[cur] == '*' && buf[cur + 1] == '/') {
190 cur += 2;
191 break;
195 return 0;
198 int tok_get(void)
200 int num;
201 if (next != -1) {
202 int tok = next;
203 next = -1;
204 return tok;
206 pre = cur;
207 if (skipws())
208 return TOK_EOF;
209 if (buf[cur] == '"') {
210 str_len = 0;
211 while (buf[cur] == '"') {
212 str_len += readstr(str + str_len);
213 if (skipws())
214 return TOK_EOF;
216 str_len++;
217 return TOK_STR;
219 if (isdigit(buf[cur]) || buf[cur] == '\'') {
220 readnum();
221 return TOK_NUM;
223 if (id_char(buf[cur])) {
224 char *s = name;
225 int i;
226 while (cur < len && id_char(buf[cur]))
227 *s++ = buf[cur++];
228 *s = '\0';
229 for (i = 0; i < ARRAY_SIZE(kwds); i++)
230 if (!strcmp(kwds[i].name, name))
231 return kwds[i].id;
232 return TOK_NAME;
234 if ((num = get_tok3(TOK3(buf + cur)))) {
235 cur += 3;
236 return num;
238 if ((num = get_tok3(TOK2(buf + cur)))) {
239 cur += 2;
240 return num;
242 if (strchr(";,{}()[]<>*&!=+-/%?:|^~.", buf[cur]))
243 return buf[cur++];
244 return -1;
247 int tok_see(void)
249 if (next == -1)
250 next = tok_get();
251 return next;
254 char *tok_id(void)
256 return name;
259 long tok_addr(void)
261 return next == -1 ? cur : pre;
264 void tok_jump(long addr)
266 cur = addr;
267 pre = cur - 1;
268 next = -1;