handle -I include paths
[neatcc.git] / cpp.c
bloba96dfb294d8c165ffc3c7db44011713a4ee45cf3
1 #include <ctype.h>
2 #include <fcntl.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include "tok.h"
8 static char *buf;
9 static int len;
10 static int cur;
12 #define MAXDEFS (1 << 10)
13 #define MACROLEN (1 << 10)
15 static struct define {
16 char name[NAMELEN];
17 char def[MACROLEN];
18 } defines[MAXDEFS];
19 static int ndefines;
21 #define MAXBUFS (1 << 3)
23 static struct buf {
24 char buf[BUFSIZE];
25 int len;
26 int cur;
27 } bufs[MAXBUFS];
28 static int nbufs;
30 static void buf_new(void)
32 bufs[nbufs - 1].cur = cur;
33 bufs[nbufs - 1].len = len;
34 nbufs++;
35 cur = 0;
36 len = 0;
37 buf = bufs[nbufs - 1].buf;
40 static void buf_pop(void)
42 nbufs--;
43 cur = bufs[nbufs - 1].cur;
44 len = bufs[nbufs - 1].len;
45 buf = bufs[nbufs - 1].buf;
48 static void include(int fd)
50 int n = 0;
51 buf_new();
52 while ((n = read(fd, buf + len, BUFSIZE - len)) > 0)
53 len += n;
56 void cpp_init(int fd)
58 include(fd);
61 static void jumpws(void)
63 while (cur < len && isspace(buf[cur]))
64 cur++;
67 static void read_word(char *dst)
69 jumpws();
70 while (cur < len && isalnum(buf[cur]) || buf[cur] == '_')
71 *dst++ = buf[cur++];
72 *dst = '\0';
75 static void read_tilleol(char *dst)
77 while (cur < len && buf[cur] != '\n') {
78 if (buf[cur] == '\\')
79 cur += 2;
80 else
81 *dst++ = buf[cur++];
83 *dst = '\0';
86 static char *putstr(char *d, char *s)
88 while (*s)
89 *d++ = *s++;
90 *d = '\0';
91 return d;
94 #define MAXLOCS (1 << 10)
96 static char *locs[MAXLOCS] = {".", NULL, "/usr/include"};
97 static int nlocs = 3;
99 void cpp_addpath(char *s)
101 locs[nlocs++] = s;
104 static int include_find(char *name, int std)
106 int i;
107 int fd;
108 for (i = std ? 1 : 0; i < nlocs; i++) {
109 char path[1 << 10];
110 char *s;
111 if (!locs[i] && *name != '/')
112 continue;
113 s = putstr(path, locs[i]);
114 if (locs[i])
115 *s++ = '/';
116 s = putstr(s, name);
117 fd = open(path, O_RDONLY);
118 if (fd != -1)
119 return fd;
121 return -1;
124 static void cpp_cmd(void)
126 char cmd[NAMELEN];
127 cur++;
128 read_word(cmd);
129 if (!strcmp("define", cmd)) {
130 struct define *d = &defines[ndefines++];
131 read_word(d->name);
132 read_tilleol(d->def);
133 return;
135 if (!strcmp("include", cmd)) {
136 char file[NAMELEN];
137 char *s, *e;
138 int fd;
139 jumpws();
140 s = buf + cur + 1;
141 e = strchr(buf + cur + 1, buf[cur] == '"' ? '"' : '>');
142 memcpy(file, s, e - s);
143 file[e - s] = '\0';
144 cur += e - s + 2;
145 fd = include_find(file, *e == '>');
146 if (fd == -1)
147 return;
148 include(fd);
149 close(fd);
150 return;
154 static int macro_find(char *name)
156 int i;
157 for (i = 0; i < ndefines; i++)
158 if (!strcmp(name, defines[i].name))
159 return i;
160 return -1;
163 static void macro_expand(void)
165 char name[NAMELEN];
166 struct define *m;
167 read_word(name);
168 buf_new();
169 m = &defines[macro_find(name)];
170 strcpy(buf, m->def);
171 len = strlen(m->def);
174 static void jumpstr(void)
176 if (buf[cur] == '\'') {
177 while (cur < len && buf[++cur] != '\'')
178 if (buf[cur] == '\\')
179 cur++;
180 cur++;
181 return;
183 if (buf[cur] == '"') {
184 while (cur < len && buf[++cur] != '"')
185 if (buf[cur] == '\\')
186 cur++;
187 cur++;
188 return;
192 static void jumpcomment(void)
194 while (++cur < len) {
195 if (buf[cur] == '*' && buf[cur + 1] == '/') {
196 cur += 2;
197 break;
202 static int definedword;
204 int cpp_read(char *s)
206 int old;
207 if (definedword) {
208 definedword = 0;
209 macro_expand();
211 if (cur == len) {
212 if (nbufs < 2)
213 return -1;
214 buf_pop();
216 old = cur;
217 if (buf[cur] == '#') {
218 cpp_cmd();
219 return 0;
221 while (cur < len) {
222 if (buf[cur] == '#')
223 break;
224 if (buf[cur] == '/' && buf[cur + 1] == '*')
225 jumpcomment();
226 if (strchr("'\"", buf[cur]))
227 jumpstr();
228 if (isalpha(buf[cur]) || buf[cur] == '_') {
229 char word[NAMELEN];
230 read_word(word);
231 if (macro_find(word) != -1) {
232 cur -= strlen(word);
233 definedword = 1;
234 break;
237 cur++;
239 memcpy(s, buf + old, cur - old);
240 return cur - old;