gen: change stack alignment to 4
[neatcc.git] / tok.c
blob8320024c46af2cc6d27b6cebd75c6510bb17acac
1 #include <ctype.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "gen.h"
6 #include "tok.h"
8 extern int cpp_read(char *s);
10 static char buf[BUFSIZE];
11 static int len;
12 static int cur;
13 static char name[NAMELEN];
14 static int next = -1;
15 static int pre;
17 static struct {
18 char *name;
19 unsigned id;
20 } kwds[] = {
21 {"void", TOK_VOID},
22 {"static", TOK_STATIC},
23 {"extern", TOK_EXTERN},
24 {"return", TOK_RETURN},
25 {"unsigned", TOK_UNSIGNED},
26 {"signed", TOK_SIGNED},
27 {"short", TOK_SHORT},
28 {"long", TOK_LONG},
29 {"int", TOK_INT},
30 {"char", TOK_CHAR},
31 {"struct", TOK_STRUCT},
32 {"union", TOK_UNION},
33 {"enum", TOK_ENUM},
34 {"typedef", TOK_TYPEDEF},
35 {"if", TOK_IF},
36 {"else", TOK_ELSE},
37 {"for", TOK_FOR},
38 {"while", TOK_WHILE},
39 {"do", TOK_DO},
40 {"switch", TOK_SWITCH},
41 {"case", TOK_CASE},
42 {"sizeof", TOK_SIZEOF},
43 {"break", TOK_BREAK},
44 {"continue", TOK_CONTINUE},
45 {"default", TOK_DEFAULT},
46 {"goto", TOK_GOTO},
49 static char *tok3[] = {
50 "<<", ">>", "++", "--", "<<=", ">>=", "...", "+=", "-=", "*=", "/=",
51 "%=", "|=", "&=", "^=", "&&", "||", "==", "!=", "<=", ">=", "->", "/*"
54 static int get_tok3(int num)
56 int i;
57 for (i = 0; i < ARRAY_SIZE(tok3); i++)
58 if (num == TOK3(tok3[i]))
59 return num;
60 return 0;
63 static char *esc_code = "abefnrtv";
64 static char *esc = "\a\b\e\f\n\r\t\v";
65 static char *digs = "0123456789abcdef";
67 static int esc_char(int *c, char *s)
69 if (*s != '\\') {
70 *c = *s;
71 return 1;
73 if (strchr(esc_code, s[1])) {
74 *c = esc[strchr(esc_code, s[1]) - esc_code];
75 return 2;
77 if (isdigit(s[1]) || s[1] == 'x') {
78 int ret = 0;
79 int base = 8;
80 int i = 1;
81 char *d;
82 if (s[1] == 'x') {
83 base = 16;
84 i++;
86 while ((d = strchr(digs, s[i]))) {
87 ret *= base;
88 ret += d - digs;
89 i++;
91 *c = ret;
92 return i;
94 *c = s[1];
95 return 2;
98 static long num;
99 static int num_bt;
101 int tok_num(long *n)
103 *n = num;
104 return num_bt;
107 static void readnum(void)
109 int base = 10;
110 num_bt = 4 | BT_SIGNED;
111 if (buf[cur] == '0' && buf[cur + 1] == 'x') {
112 num_bt &= ~BT_SIGNED;
113 base = 16;
114 cur += 2;
116 if (strchr(digs, buf[cur])) {
117 long result = 0;
118 char *c;
119 if (base == 10 && buf[cur] == '0')
120 base = 8;
121 while (cur < len && (c = strchr(digs, tolower(buf[cur])))) {
122 result *= base;
123 result += c - digs;
124 cur++;
126 num = result;
127 while (cur < len) {
128 int c = tolower(buf[cur]);
129 if (c != 'u' && c != 'l')
130 break;
131 if (c == 'u')
132 num_bt &= ~BT_SIGNED;
133 if (c == 'l')
134 num_bt = (num_bt & BT_SIGNED) | LONGSZ;
135 cur++;
137 return;
139 if (buf[cur] == '\'') {
140 int ret;
141 cur += 2 + esc_char(&ret, buf + cur + 1);
142 num = ret;
143 return;
145 num = -1;
148 static char str[BUFSIZE];
149 static int str_len;
151 int tok_str(char *buf)
153 if (buf)
154 memcpy(buf, str, str_len);
155 return str_len;
158 static int readstr(char *out)
160 char *s = out;
161 char *r = buf + cur;
162 char *e = buf + len;
163 r++;
164 while (r < e && *r != '"') {
165 if (*r == '\\') {
166 int c;
167 r += esc_char(&c, r);
168 *s++ = c;
169 } else {
170 *s++ = *r++;
173 *s++ = '\0';
174 cur = r - buf + 1;
175 return s - out - 1;
178 static int id_char(int c)
180 return isalnum(c) || c == '_';
183 static int skipws(void)
185 while (1) {
186 if (cur == len) {
187 int r;
188 while (!(r = cpp_read(buf + cur)))
190 if (r == -1)
191 return 1;
192 len += r;
194 while (cur < len && isspace(buf[cur]))
195 cur++;
196 if (cur == len)
197 continue;
198 if (TOK2(buf + cur) != TOK2("/*"))
199 return 0;
200 while (++cur < len) {
201 if (buf[cur] == '*' && buf[cur + 1] == '/') {
202 cur += 2;
203 break;
207 return 0;
210 int tok_get(void)
212 int num;
213 if (next != -1) {
214 int tok = next;
215 next = -1;
216 return tok;
218 pre = cur;
219 if (skipws())
220 return TOK_EOF;
221 if (buf[cur] == '"') {
222 str_len = 0;
223 while (buf[cur] == '"') {
224 str_len += readstr(str + str_len);
225 if (skipws())
226 return TOK_EOF;
228 str_len++;
229 return TOK_STR;
231 if (isdigit(buf[cur]) || buf[cur] == '\'') {
232 readnum();
233 return TOK_NUM;
235 if (id_char(buf[cur])) {
236 char *s = name;
237 int i;
238 while (cur < len && id_char(buf[cur]))
239 *s++ = buf[cur++];
240 *s = '\0';
241 for (i = 0; i < ARRAY_SIZE(kwds); i++)
242 if (!strcmp(kwds[i].name, name))
243 return kwds[i].id;
244 return TOK_NAME;
246 if ((num = get_tok3(TOK3(buf + cur)))) {
247 cur += 3;
248 return num;
250 if ((num = get_tok3(TOK2(buf + cur)))) {
251 cur += 2;
252 return num;
254 if (strchr(";,{}()[]<>*&!=+-/%?:|^~.", buf[cur]))
255 return buf[cur++];
256 return -1;
259 int tok_see(void)
261 if (next == -1)
262 next = tok_get();
263 return next;
266 char *tok_id(void)
268 return name;
271 long tok_addr(void)
273 return next == -1 ? cur : pre;
276 void tok_jump(long addr)
278 cur = addr;
279 pre = cur - 1;
280 next = -1;