a small cc
[neatcc.git] / cc.c
blob05e8ad3bb7cbcf80c0c3164969f5b15adee3554e
1 #include <fcntl.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include "out.h"
7 #include "tok.h"
9 #define MAXLOCALS (1 << 10)
10 #define print(s) write(2, (s), strlen(s));
12 static struct local {
13 char name[NAMELEN];
14 long addr;
15 } locals[MAXLOCALS];
16 static int nlocals;
18 static void die(char *s)
20 print(s);
21 exit(1);
24 static int tok_jmp(int tok)
26 if (tok_see() != tok)
27 return 1;
28 tok_get();
29 return 0;
32 static void tok_expect(int tok)
34 if (tok_get() != tok)
35 die("syntax error\n");
38 static void readexpr(void);
40 static int readtype(void)
42 int found = 0;
43 while (!found) {
44 switch (tok_see()) {
45 case TOK_VOID:
46 case TOK_INT:
47 case TOK_CHAR:
48 found = 1;
49 tok_get();
50 break;
51 case TOK_SHORT:
52 case TOK_LONG:
53 case TOK_UNSIGNED:
54 found = 1;
55 tok_get();
56 break;
57 case TOK_ENUM:
58 case TOK_STRUCT:
59 found = 1;
60 tok_get();
61 tok_expect(TOK_NAME);
62 break;
63 case TOK_EOF:
64 default:
65 return 1;
68 while (!tok_jmp('*'))
70 return 0;
73 static void readprimary(void)
75 int i;
76 if (!tok_jmp(TOK_NUM)) {
77 o_num(atoi(tok_id()));
78 return;
80 if (!tok_jmp(TOK_NAME)) {
81 for (i = 0; i < nlocals; i++) {
82 if (!strcmp(locals[i].name, tok_id())) {
83 o_local(locals[i].addr);
84 return;
87 return;
89 if (!tok_jmp('(')) {
90 readexpr();
91 tok_expect(')');
92 return;
96 static void readpost(void)
98 readprimary();
99 if (!tok_jmp('[')) {
100 readexpr();
101 tok_expect(']');
102 return;
104 if (!tok_jmp('(')) {
105 readexpr();
106 while (!tok_jmp(',')) {
107 readexpr();
109 tok_expect(')');
113 static void readexpr(void)
115 readpost();
116 if (!tok_jmp('=')) {
117 readexpr();
118 o_assign();
122 static void readstmt(void)
124 if (!tok_jmp('{')) {
125 while (tok_jmp('}'))
126 readstmt();
127 return;
129 if (!readtype()) {
130 tok_expect(TOK_NAME);
131 strcpy(locals[nlocals].name, tok_id());
132 locals[nlocals].addr = o_mklocal();
133 nlocals++;
134 /* initializer */
135 if (!tok_jmp('=')) {
136 o_local(locals[nlocals - 1].addr);
137 readexpr();
138 o_assign();
139 tok_expect(';');
141 return;
143 if (!tok_jmp(TOK_IF)) {
144 long l1, l2;
145 tok_expect('(');
146 readexpr();
147 tok_expect(')');
148 l1 = o_stubjz();
149 readstmt();
150 if (!tok_jmp(TOK_ELSE)) {
151 l2 = o_stubjz();
152 o_filljz(l1);
153 readstmt();
154 o_filljz(l2);
155 } else {
156 o_filljz(l1);
158 return;
160 if (!tok_jmp(TOK_WHILE)) {
161 long l1, l2;
162 l1 = o_mklabel();
163 tok_expect('(');
164 readexpr();
165 tok_expect(')');
166 l1 = o_stubjz();
167 readstmt();
168 o_jz(l1);
169 o_filljz(l1);
170 return;
172 if (!tok_jmp(TOK_RETURN)) {
173 int ret = tok_see() != ';';
174 if (ret)
175 readexpr();
176 tok_expect(';');
177 o_ret(ret);
178 return;
180 readexpr();
181 tok_expect(';');
184 static void readdecl(void)
186 char name[NAMELEN];
187 readtype();
188 tok_expect(TOK_NAME);
189 strcpy(name, tok_id());
190 if (!tok_jmp(';'))
191 return;
192 if (!tok_jmp('(')) {
193 /* read args */
194 while (tok_get() != ')')
196 if (!tok_jmp(';'))
197 return;
198 o_func_beg(name);
199 readstmt();
200 o_func_end();
201 return;
203 die("syntax error\n");
206 static void parse(void)
208 while (tok_see() != TOK_EOF)
209 readdecl();
212 int main(int argc, char *argv[])
214 char obj[128];
215 char *src = argv[1];
216 int ifd, ofd;
217 ifd = open(src, O_RDONLY);
218 tok_init(ifd);
219 close(ifd);
220 out_init();
221 parse();
223 strcpy(obj, src);
224 obj[strlen(obj) - 1] = 'o';
225 ofd = open(obj, O_WRONLY | O_TRUNC | O_CREAT, 0600);
226 out_write(ofd);
227 close(ofd);
228 return 0;