aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard>2001-11-08 01:12:31 +0000
committerbellard <bellard>2001-11-08 01:12:31 +0000
commita254461560b55529f730cbd327793b1a1bd39e46 (patch)
tree6d8d96d5e1c8aafd6892a2769835c26e827c4a38
parentb0bdbb14effd93a0e7655f1f3851b4deb597be46 (diff)
downloadtinycc-a254461560b55529f730cbd327793b1a1bd39e46.tar.gz
tinycc-a254461560b55529f730cbd327793b1a1bd39e46.tar.bz2
added #if support
-rw-r--r--tcc.c263
1 files changed, 198 insertions, 65 deletions
diff --git a/tcc.c b/tcc.c
index 7e455a6..773162c 100644
--- a/tcc.c
+++ b/tcc.c
@@ -26,6 +26,7 @@
#define SYM_TABLE_SIZE 10000
#define MACRO_STACK_SIZE 32
#define INCLUDE_STACK_SIZE 32
+#define IFDEF_STACK_SIZE 64
#define NB_REGS 3
@@ -67,6 +68,7 @@ Sym *define_stack, *global_stack, *local_stack, *label_stack;
char *macro_stack[MACRO_STACK_SIZE], **macro_stack_ptr, *macro_ptr;
IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
+int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
/* The current value can be: */
#define VT_VALMASK 0x000f
@@ -103,45 +105,6 @@ IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
/* Special infos */
/* token values */
-#define TOK_INT 256
-#define TOK_VOID 257
-#define TOK_CHAR 258
-#define TOK_IF 259
-#define TOK_ELSE 260
-#define TOK_WHILE 261
-#define TOK_BREAK 262
-#define TOK_RETURN 263
-#define TOK_DEFINE 264
-#define TOK_MAIN 265
-#define TOK_FOR 266
-#define TOK_EXTERN 267
-#define TOK_STATIC 268
-#define TOK_UNSIGNED 269
-#define TOK_GOTO 270
-#define TOK_DO 271
-#define TOK_CONTINUE 272
-#define TOK_SWITCH 273
-#define TOK_CASE 274
-
-/* ignored types Must have contiguous values */
-#define TOK_CONST 275
-#define TOK_VOLATILE 276
-#define TOK_LONG 277
-#define TOK_REGISTER 278
-#define TOK_SIGNED 279
-#define TOK_AUTO 280
-#define TOK_INLINE 281
-
-#define TOK_FLOAT 282 /* unsupported */
-#define TOK_DOUBLE 283 /* unsupported */
-
-#define TOK_STRUCT 284
-#define TOK_UNION 285
-#define TOK_TYPEDEF 286
-#define TOK_DEFAULT 287
-#define TOK_ENUM 288
-#define TOK_SIZEOF 289
-#define TOK_INCLUDE 290
/* warning: the following compare tokens depend on i386 asm code */
#define TOK_ULT 0x92
@@ -184,8 +147,61 @@ IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
#define TOK_A_SHL 0x81
#define TOK_A_SAR 0x82
+enum {
+ TOK_INT = 256,
+ TOK_VOID,
+ TOK_CHAR,
+ TOK_IF,
+ TOK_ELSE,
+ TOK_WHILE,
+ TOK_BREAK,
+ TOK_RETURN,
+ TOK_FOR,
+ TOK_EXTERN,
+ TOK_STATIC,
+ TOK_UNSIGNED,
+ TOK_GOTO,
+ TOK_DO,
+ TOK_CONTINUE,
+ TOK_SWITCH,
+ TOK_CASE,
+
+ /* ignored types Must have contiguous values */
+ TOK_CONST,
+ TOK_VOLATILE,
+ TOK_LONG,
+ TOK_REGISTER,
+ TOK_SIGNED,
+ TOK_AUTO,
+ TOK_INLINE,
+
+ /* unsupported type */
+ TOK_FLOAT,
+ TOK_DOUBLE,
+
+ TOK_STRUCT,
+ TOK_UNION,
+ TOK_TYPEDEF,
+ TOK_DEFAULT,
+ TOK_ENUM,
+ TOK_SIZEOF,
+
+ /* preprocessor only */
+ TOK_DEFINE,
+ TOK_INCLUDE,
+ TOK_IFDEF,
+ TOK_IFNDEF,
+ TOK_ELIF,
+ TOK_ENDIF,
+ TOK_DEFINED,
+
+ /* special identifiers */
+ TOK_MAIN,
+};
+
void sum();
void next();
+int expr_const();
void expr_eq();
void expr();
void decl();
@@ -359,7 +375,7 @@ void inp()
}
if (ch1 == '\n')
line_num++;
- // printf("ch1=%c\n", ch1);
+ // printf("ch1=%c 0x%x\n", ch1, ch1);
}
/* input with '\\n' handling and macro subtitution if in macro state */
@@ -381,9 +397,11 @@ void minp()
goto redo;
}
}
+ // printf("ch=%c 0x%x\n", ch, ch);
}
/* same as minp, but also skip comments */
+/* XXX: skip strings & chars */
void cinp()
{
int c;
@@ -423,6 +441,90 @@ void skip_spaces()
cinp();
}
+/* skip block of text until #else, #elif or #endif. skip also pairs of
+ #if/#endif */
+void preprocess_skip()
+{
+ int a;
+ a = 0;
+ while (1) {
+ while (ch != '\n') {
+ if (ch == -1)
+ expect("#endif");
+ cinp();
+ }
+ cinp();
+ skip_spaces();
+ if (ch == '#') {
+ cinp();
+ next();
+ if (a == 0 &&
+ (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
+ break;
+ if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
+ a++;
+ else if (tok == TOK_ENDIF)
+ a--;
+ }
+ }
+}
+
+/* parse until eol and add given char */
+char *get_str(c)
+{
+ char *str;
+ int size, n;
+
+ str = NULL;
+ size = 0;
+ n = 0;
+ while (1) {
+ if ((n + 1) >= size) {
+ size += 128;
+ str = realloc(str, size);
+ if (!str)
+ error("memory full");
+ }
+ if (ch == -1 || ch == '\n') {
+ str[n++] = c;
+ str[n++] = '\0';
+ break;
+ }
+ str[n++] = ch;
+ cinp();
+ }
+ return str;
+}
+
+/* return 1 if next token is defined, 0 otherwise. */
+int is_defined()
+{
+ Sym *s;
+ /* hack to avoid replacing id by defined value */
+ s = define_stack;
+ define_stack = 0;
+ next();
+ define_stack = s;
+ return sym_find1(define_stack, tok) != 0;
+}
+
+/* XXX: not correct yet (need to ensure it is constant) */
+int expr_preprocess()
+{
+ int c;
+
+ if ((macro_stack_ptr - macro_stack) >= MACRO_STACK_SIZE)
+ error("too many nested macros");
+ *macro_stack_ptr++ = (char *)'\n';
+ *macro_stack_ptr++ = macro_ptr;
+ macro_ptr = get_str(';');
+ cinp();
+ next();
+ c = expr_const();
+ ch = '\n';
+ return c != 0;
+}
+
void preprocess()
{
char *str;
@@ -433,28 +535,13 @@ void preprocess()
cinp();
next(); /* XXX: should pass parameter to avoid macro subst */
+ redo:
if (tok == TOK_DEFINE) {
next(); /* XXX: should pass parameter to avoid macro subst */
skip_spaces();
/* now 'tok' is the macro symbol */
- str = NULL;
- size = 0;
- n = 0;
- while (1) {
- if ((n + 1) >= size) {
- size += 128;
- str = realloc(str, size);
- if (!str)
- error("memory full");
- }
- if (ch == -1 || ch == '\n') {
- str[n++] = ' '; /* a space is inserted after each macro */
- str[n++] = '\0';
- break;
- }
- str[n++] = ch;
- cinp();
- }
+ /* a space is inserted after each macro */
+ str = get_str(' ');
sym_push1(&define_stack, tok, 0, (int)str);
} else if (tok == TOK_INCLUDE) {
skip_spaces();
@@ -497,6 +584,7 @@ void preprocess()
error("include file not found");
found:
/* push current file in stack */
+ /* XXX: fix current line init */
include_stack_ptr->file = file;
include_stack_ptr->filename = filename;
include_stack_ptr->line_num = line_num;
@@ -505,7 +593,41 @@ void preprocess()
filename = strdup(buf1);
line_num = 1;
}
-
+ } else if (tok == TOK_IFNDEF) {
+ c = !is_defined();
+ goto do_ifdef;
+ } else if (tok == TOK_IF) {
+ /* XXX: incorrect constant parsing now */
+ c = expr_preprocess();
+ goto do_ifdef;
+ } else if (tok == TOK_IFDEF) {
+ c = is_defined();
+ do_ifdef:
+ if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
+ error("memory full");
+ *ifdef_stack_ptr++ = c;
+ goto test_skip;
+ } else if (tok == TOK_ELSE) {
+ if (ifdef_stack_ptr == ifdef_stack ||
+ (ifdef_stack_ptr[-1] & 2))
+ error("#else after #else");
+ c = (ifdef_stack_ptr[-1] ^= 3);
+ goto test_skip;
+ } else if (tok == TOK_ELIF) {
+ if (ifdef_stack_ptr == ifdef_stack ||
+ ifdef_stack_ptr[-1] > 1)
+ error("#elif after #else");
+ c = expr_preprocess();
+ ifdef_stack_ptr[-1] = c;
+ test_skip:
+ if (!(c & 1)) {
+ preprocess_skip();
+ goto redo;
+ }
+ } else if (tok == TOK_ENDIF) {
+ if (ifdef_stack_ptr == ifdef_stack)
+ expect("#if");
+ ifdef_stack_ptr--;
}
/* ignore other preprocess commands or #! for C scripts */
while (ch != '\n' && ch != -1)
@@ -639,6 +761,7 @@ void next()
else if (tok == '>')
tok = TOK_GT;
}
+ // printf("tok=%x\n", tok);
}
void swap(int *p, int *q)
@@ -1121,7 +1244,8 @@ void gen_op(op)
gen_opc(op);
}
} else {
- if ((t1 | t2) & VT_UNSIGNED) {
+ /* XXX: test types and compute returned value */
+ if ((t1 | t2) & (VT_UNSIGNED | VT_PTR)) {
if (op == TOK_SAR)
op = TOK_SHR;
else if (op == '/')
@@ -1629,6 +1753,13 @@ void unary()
vpush();
unary();
gen_op('-');
+ } else if (t == TOK_DEFINED) {
+ /* XXX: should only be used in preprocess expr parsing */
+ if (tok != '(')
+ expect("(");
+ vset(VT_CONST, is_defined());
+ next();
+ skip(')');
} else
{
s = sym_find(t);
@@ -2103,9 +2234,8 @@ void decl(l)
sym_push1(&local_stack, 0, 0, 0);
/* define parameters */
sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
- while (sym = sym->next) {
+ while (sym = sym->next)
sym_push(sym->v & ~SYM_FIELD, sym->t, sym->c);
- }
loc = 0;
o(0xe58955); /* push %ebp, mov %esp, %ebp */
a = (int *)oad(0xec81, 0); /* sub $xxx, %esp */
@@ -2185,11 +2315,12 @@ int main(int c, char **v)
exit(1);
}
include_stack_ptr = include_stack;
-
+ ifdef_stack_ptr = ifdef_stack;
+
idtable = malloc(SYM_TABLE_SIZE);
memcpy(idtable,
- "int\0void\0char\0if\0else\0while\0break\0return\0define\0main\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0auto\0inline\0float\0double\0struct\0union\0typedef\0default\0enum\0sizeof\0include", 219);
- idptr = idtable + 219;
+ "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0auto\0inline\0float\0double\0struct\0union\0typedef\0default\0enum\0sizeof\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0main", 251);
+ idptr = idtable + 251;
glo = malloc(DATA_SIZE);
memset((void *)glo, 0, DATA_SIZE);
@@ -2203,6 +2334,8 @@ int main(int c, char **v)
ch = '\n'; /* needed to parse correctly first preprocessor command */
next();
decl(VT_CONST);
+ if (tok != -1)
+ expect("declaration");
#ifdef TEST
{
FILE *f;