ncc: call ts_addop() only for += and -=
[neatcc.git] / tok.c
blob9493f6a9e84e3474e0833ad764b24ecbcd915ea8
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 static char buf[BUFSIZE];
9 static int len;
10 static int cur;
11 static char name[NAMELEN];
12 static int next = -1;
13 static int pre;
15 static struct {
16 char *name;
17 unsigned id;
18 } kwds[] = {
19 {"void", TOK_VOID},
20 {"static", TOK_STATIC},
21 {"extern", TOK_EXTERN},
22 {"return", TOK_RETURN},
23 {"unsigned", TOK_UNSIGNED},
24 {"signed", TOK_SIGNED},
25 {"short", TOK_SHORT},
26 {"long", TOK_LONG},
27 {"int", TOK_INT},
28 {"char", TOK_CHAR},
29 {"struct", TOK_STRUCT},
30 {"union", TOK_UNION},
31 {"enum", TOK_ENUM},
32 {"typedef", TOK_TYPEDEF},
33 {"if", TOK_IF},
34 {"else", TOK_ELSE},
35 {"for", TOK_FOR},
36 {"while", TOK_WHILE},
37 {"do", TOK_DO},
38 {"switch", TOK_SWITCH},
39 {"case", TOK_CASE},
40 {"sizeof", TOK_SIZEOF},
41 {"break", TOK_BREAK},
42 {"continue", TOK_CONTINUE},
43 {"default", TOK_DEFAULT},
44 {"goto", TOK_GOTO},
47 static char *tok3[] = {
48 "<<=", ">>=", "...", "<<", ">>", "++", "--", "+=", "-=", "*=", "/=",
49 "%=", "|=", "&=", "^=", "&&", "||", "==", "!=", "<=", ">=", "->"
52 static int get_tok3(int num)
54 int i;
55 for (i = 0; i < ARRAY_SIZE(tok3); i++)
56 if (num == TOK3(tok3[i]))
57 return num;
58 return 0;
61 static char *esc_code = "abefnrtv";
62 static char *esc = "\a\b\e\f\n\r\t\v";
63 static char *digs = "0123456789abcdef";
65 static int esc_char(int *c, char *s)
67 if (*s != '\\') {
68 *c = *s;
69 return 1;
71 if (strchr(esc_code, s[1])) {
72 *c = esc[strchr(esc_code, s[1]) - esc_code];
73 return 2;
75 if (isdigit(s[1]) || s[1] == 'x') {
76 int ret = 0;
77 int base = 8;
78 int i = 1;
79 char *d;
80 if (s[1] == 'x') {
81 base = 16;
82 i++;
84 while ((d = strchr(digs, s[i]))) {
85 ret *= base;
86 ret += d - digs;
87 i++;
89 *c = ret;
90 return i;
92 *c = s[1];
93 return 2;
96 static long num;
97 static int num_bt;
99 int tok_num(long *n)
101 *n = num;
102 return num_bt;
105 static void readnum(void)
107 int base = 10;
108 num_bt = 4 | BT_SIGNED;
109 if (buf[cur] == '0' && buf[cur + 1] == 'x') {
110 num_bt &= ~BT_SIGNED;
111 base = 16;
112 cur += 2;
114 if (strchr(digs, tolower(buf[cur]))) {
115 long result = 0;
116 char *c;
117 if (base == 10 && buf[cur] == '0')
118 base = 8;
119 while (cur < len && (c = strchr(digs, tolower(buf[cur])))) {
120 result *= base;
121 result += c - digs;
122 cur++;
124 num = result;
125 while (cur < len) {
126 int c = tolower(buf[cur]);
127 if (c != 'u' && c != 'l')
128 break;
129 if (c == 'u')
130 num_bt &= ~BT_SIGNED;
131 if (c == 'l')
132 num_bt = (num_bt & BT_SIGNED) | LONGSZ;
133 cur++;
135 return;
137 if (buf[cur] == '\'') {
138 int ret;
139 cur += 2 + esc_char(&ret, buf + cur + 1);
140 num = ret;
141 return;
143 num = -1;
146 static char str[BUFSIZE];
147 static int str_len;
149 int tok_str(char *buf)
151 if (buf)
152 memcpy(buf, str, str_len);
153 return str_len;
156 static int readstr(char *out)
158 char *s = out;
159 char *r = buf + cur;
160 char *e = buf + len;
161 r++;
162 while (r < e && *r != '"') {
163 if (*r == '\\') {
164 int c;
165 r += esc_char(&c, r);
166 *s++ = c;
167 } else {
168 *s++ = *r++;
171 *s++ = '\0';
172 cur = r - buf + 1;
173 return s - out - 1;
176 static int id_char(int c)
178 return isalnum(c) || c == '_';
181 static int skipws(void)
183 while (1) {
184 if (cur == len) {
185 int r;
186 while (!(r = cpp_read(buf + cur)))
188 if (r == -1)
189 return 1;
190 len += r;
192 while (cur < len && isspace(buf[cur]))
193 cur++;
194 if (cur == len)
195 continue;
196 if (buf[cur] == '\\' && buf[cur + 1] == '\n') {
197 cur += 2;
198 continue;
200 if (buf[cur] == '/' && buf[cur + 1] == '/') {
201 while (cur < len && buf[cur] != '\n')
202 cur++;
203 continue;
205 if (buf[cur] == '/' && buf[cur + 1] == '*') {
206 while (++cur < len) {
207 if (buf[cur] == '*' && buf[cur + 1] == '/') {
208 cur += 2;
209 break;
212 continue;
214 break;
216 return 0;
219 int tok_get(void)
221 int num;
222 if (next != -1) {
223 int tok = next;
224 next = -1;
225 return tok;
227 pre = cur;
228 if (skipws())
229 return TOK_EOF;
230 if (buf[cur] == '"') {
231 str_len = 0;
232 while (buf[cur] == '"') {
233 str_len += readstr(str + str_len);
234 if (skipws())
235 return TOK_EOF;
237 str_len++;
238 return TOK_STR;
240 if (isdigit(buf[cur]) || buf[cur] == '\'') {
241 readnum();
242 return TOK_NUM;
244 if (id_char(buf[cur])) {
245 char *s = name;
246 int i;
247 while (cur < len && id_char(buf[cur]))
248 *s++ = buf[cur++];
249 *s = '\0';
250 for (i = 0; i < ARRAY_SIZE(kwds); i++)
251 if (!strcmp(kwds[i].name, name))
252 return kwds[i].id;
253 return TOK_NAME;
255 if (cur + 3 <= len && (num = get_tok3(TOK3(buf + cur)))) {
256 cur += 3;
257 return num;
259 if ((num = get_tok3(TOK2(buf + cur)))) {
260 cur += 2;
261 return num;
263 if (strchr(";,{}()[]<>*&!=+-/%?:|^~.", buf[cur]))
264 return buf[cur++];
265 return -1;
268 int tok_see(void)
270 if (next == -1)
271 next = tok_get();
272 return next;
275 char *tok_id(void)
277 return name;
280 long tok_addr(void)
282 return next == -1 ? cur : pre;
285 void tok_jump(long addr)
287 cur = addr;
288 pre = cur - 1;
289 next = -1;