out: exit if there is no room for more relocations or symbols
[neatcc.git] / tok.c
blobebae9e6cb93f03412724d37d7e274468f6faf801
1 /* neatcc tokenizer */
2 #include <ctype.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "gen.h"
7 #include "mem.h"
8 #include "ncc.h"
9 #include "tok.h"
11 static struct mem tok_mem; /* the data read via cpp_read() so far */
12 static struct mem str; /* the last tok_str() string */
13 static char *buf;
14 static int len;
15 static int cur;
16 static char name[NAMELEN];
17 static int next = -1;
18 static int pre;
20 static struct {
21 char *name;
22 unsigned id;
23 } kwds[] = {
24 {"void", TOK_VOID},
25 {"static", TOK_STATIC},
26 {"extern", TOK_EXTERN},
27 {"return", TOK_RETURN},
28 {"unsigned", TOK_UNSIGNED},
29 {"signed", TOK_SIGNED},
30 {"short", TOK_SHORT},
31 {"long", TOK_LONG},
32 {"int", TOK_INT},
33 {"char", TOK_CHAR},
34 {"struct", TOK_STRUCT},
35 {"union", TOK_UNION},
36 {"enum", TOK_ENUM},
37 {"typedef", TOK_TYPEDEF},
38 {"if", TOK_IF},
39 {"else", TOK_ELSE},
40 {"for", TOK_FOR},
41 {"while", TOK_WHILE},
42 {"do", TOK_DO},
43 {"switch", TOK_SWITCH},
44 {"case", TOK_CASE},
45 {"sizeof", TOK_SIZEOF},
46 {"break", TOK_BREAK},
47 {"continue", TOK_CONTINUE},
48 {"default", TOK_DEFAULT},
49 {"goto", TOK_GOTO},
52 static char *tok3[] = {
53 "<<=", ">>=", "...", "<<", ">>", "++", "--", "+=", "-=", "*=", "/=",
54 "%=", "|=", "&=", "^=", "&&", "||", "==", "!=", "<=", ">=", "->"
57 static int get_tok3(int num)
59 int i;
60 for (i = 0; i < LEN(tok3); i++)
61 if (num == TOK3(tok3[i]))
62 return num;
63 return 0;
66 static char *esc_code = "abefnrtv";
67 static char *esc = "\a\b\e\f\n\r\t\v";
68 static char *digs = "0123456789abcdef";
70 static int esc_char(int *c, char *s)
72 if (*s != '\\') {
73 *c = (unsigned char) *s;
74 return 1;
76 if (strchr(esc_code, s[1])) {
77 *c = esc[strchr(esc_code, s[1]) - esc_code];
78 return 2;
80 if (isdigit(s[1]) || s[1] == 'x') {
81 int ret = 0;
82 int base = 8;
83 int i = 1;
84 char *d;
85 if (s[1] == 'x') {
86 base = 16;
87 i++;
89 while ((d = memchr(digs, s[i], base))) {
90 ret *= base;
91 ret += d - digs;
92 i++;
94 *c = ret;
95 return i;
97 *c = (unsigned char) s[1];
98 return 2;
101 static long num;
102 static int num_bt;
104 int tok_num(long *n)
106 *n = num;
107 return num_bt;
110 static void readnum(void)
112 int base = 10;
113 num_bt = 4 | BT_SIGNED;
114 if (buf[cur] == '0' && buf[cur + 1] == 'x') {
115 num_bt &= ~BT_SIGNED;
116 base = 16;
117 cur += 2;
119 if (strchr(digs, tolower(buf[cur]))) {
120 long result = 0;
121 char *c;
122 if (base == 10 && buf[cur] == '0')
123 base = 8;
124 while (cur < len && (c = strchr(digs, tolower(buf[cur])))) {
125 result *= base;
126 result += c - digs;
127 cur++;
129 num = result;
130 while (cur < len) {
131 int c = tolower(buf[cur]);
132 if (c != 'u' && c != 'l')
133 break;
134 if (c == 'u')
135 num_bt &= ~BT_SIGNED;
136 if (c == 'l')
137 num_bt = (num_bt & BT_SIGNED) | LONGSZ;
138 cur++;
140 return;
142 if (buf[cur] == '\'') {
143 int ret;
144 cur += 2 + esc_char(&ret, buf + cur + 1);
145 num = ret;
146 return;
148 num = -1;
151 void tok_str(char **buf, int *len)
153 if (len)
154 *len = mem_len(&str) + 1;
155 if (buf)
156 *buf = mem_buf(&str);
159 static void readstr(struct mem *mem)
161 char *s = buf + cur;
162 char *e = buf + len;
163 int c;
164 s++;
165 while (s < e && *s != '"') {
166 if (*s == '\\') {
167 s += esc_char(&c, s);
168 mem_putc(mem, c);
169 } else {
170 mem_putc(mem, (unsigned char) *s++);
173 cur = s - buf + 1;
176 static int id_char(int c)
178 return isalnum(c) || c == '_';
181 static int skipws(void)
183 int clen;
184 char *cbuf;
185 while (1) {
186 if (cur == len) {
187 clen = 0;
188 while (!clen)
189 if (cpp_read(&cbuf, &clen))
190 return 1;
191 mem_put(&tok_mem, cbuf, clen);
192 buf = mem_buf(&tok_mem);
193 len = mem_len(&tok_mem);
195 while (cur < len && isspace(buf[cur]))
196 cur++;
197 if (cur == len)
198 continue;
199 if (buf[cur] == '\\' && buf[cur + 1] == '\n') {
200 cur += 2;
201 continue;
203 if (buf[cur] == '/' && buf[cur + 1] == '/') {
204 while (cur < len && buf[cur] != '\n')
205 cur++;
206 continue;
208 if (buf[cur] == '/' && buf[cur + 1] == '*') {
209 while (++cur < len) {
210 if (buf[cur] == '*' && buf[cur + 1] == '/') {
211 cur += 2;
212 break;
215 continue;
217 break;
219 return 0;
222 int tok_get(void)
224 int num;
225 if (next != -1) {
226 int tok = next;
227 next = -1;
228 return tok;
230 pre = cur;
231 if (skipws())
232 return TOK_EOF;
233 if (buf[cur] == '"') {
234 mem_cut(&str, 0);
235 while (buf[cur] == '"') {
236 readstr(&str);
237 if (skipws())
238 return TOK_EOF;
240 return TOK_STR;
242 if (isdigit(buf[cur]) || buf[cur] == '\'') {
243 readnum();
244 return TOK_NUM;
246 if (id_char(buf[cur])) {
247 char *s = name;
248 int i;
249 while (cur < len && id_char(buf[cur]))
250 *s++ = buf[cur++];
251 *s = '\0';
252 for (i = 0; i < LEN(kwds); i++)
253 if (!strcmp(kwds[i].name, name))
254 return kwds[i].id;
255 return TOK_NAME;
257 if (cur + 3 <= len && (num = get_tok3(TOK3(buf + cur)))) {
258 cur += 3;
259 return num;
261 if ((num = get_tok3(TOK2(buf + cur)))) {
262 cur += 2;
263 return num;
265 if (strchr(";,{}()[]<>*&!=+-/%?:|^~.", buf[cur]))
266 return buf[cur++];
267 return -1;
270 int tok_see(void)
272 if (next == -1)
273 next = tok_get();
274 return next;
277 char *tok_id(void)
279 return name;
282 long tok_addr(void)
284 return next == -1 ? cur : pre;
287 void tok_jump(long addr)
289 cur = addr;
290 pre = cur - 1;
291 next = -1;