2 * TCC - Tiny C Compiler
4 * Copyright (c) 2001 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* preprocessor debug */
26 /* these sizes are dummy for unix, because malloc() does not use
27 memory when the pages are not used */
28 #define TEXT_SIZE (4*1024*1024)
29 #define DATA_SIZE (4*1024*1024)
31 #define INCLUDE_STACK_SIZE 32
32 #define IFDEF_STACK_SIZE 64
33 #define VSTACK_SIZE 64
34 #define STRING_MAX_SIZE 1024
35 #define INCLUDE_PATHS_MAX 32
37 #define TOK_HASH_SIZE 521
38 #define TOK_ALLOC_INCR 256 /* must be a power of two */
39 #define SYM_HASH_SIZE 263
41 /* number of available temporary registers */
43 /* return register for functions */
44 #define FUNC_RET_REG 0
45 /* defined if function parameters must be evaluated in reverse order */
46 #define INVERT_FUNC_PARAMS
47 /* defined if structures are passed as pointers. Otherwise structures
48 are directly pushed on stack. */
49 //#define FUNC_STRUCT_PARAM_AS_PTR
51 /* token symbol management */
52 typedef struct TokenSym
{
53 struct TokenSym
*hash_next
;
54 int tok
; /* token number */
59 /* symbol management */
61 int v
; /* symbol token */
62 int t
; /* associated type */
63 int c
; /* associated number */
64 struct Sym
*next
; /* next related symbol */
65 struct Sym
*prev
; /* prev symbol in stack */
66 struct Sym
*hash_next
; /* next symbol in hash table */
69 typedef struct SymStack
{
71 struct Sym
*hash
[SYM_HASH_SIZE
];
74 /* relocation entry (currently only used for functions or variables */
75 typedef struct Reloc
{
76 int type
; /* type of relocation */
77 int addr
; /* address of relocation */
78 struct Reloc
*next
; /* next relocation */
81 #define RELOC_ADDR32 1 /* 32 bits relocation */
82 #define RELOC_REL32 2 /* 32 bits relative relocation */
85 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
86 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
88 #define FUNC_NEW 1 /* ansi function prototype */
89 #define FUNC_OLD 2 /* old function prototype */
90 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
92 /* field 'Sym.t' for macros */
93 #define MACRO_OBJ 0 /* object like macro */
94 #define MACRO_FUNC 1 /* function like macro */
96 /* type_decl() types */
97 #define TYPE_ABSTRACT 1 /* type without variable */
98 #define TYPE_DIRECT 2 /* type with variable */
106 /* loc : local variable index
107 glo : global variable index
108 ind : output code ptr
111 anon_sym: anonymous symbol index
114 int tok
, tok1
, tokc
, rsym
, anon_sym
,
115 prog
, ind
, loc
, glo
, vt
, vc
, const_wanted
, line_num
;
116 int global_expr
; /* true if compound literals must be allocated
117 globally (used during initializers parsing */
118 int func_vt
, func_vc
; /* current function return type (used by
119 return instruction) */
121 TokenSym
**table_ident
;
122 TokenSym
*hash_ident
[521];
123 char token_buf
[STRING_MAX_SIZE
+ 1];
124 char *filename
, *funcname
;
125 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
127 int vstack
[VSTACK_SIZE
], *vstack_ptr
;
128 int *macro_ptr
, *macro_ptr_allocated
;
129 IncludeFile include_stack
[INCLUDE_STACK_SIZE
], *include_stack_ptr
;
130 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
131 char *include_paths
[INCLUDE_PATHS_MAX
];
132 int nb_include_paths
;
134 /* The current value can be: */
135 #define VT_VALMASK 0x000f
136 #define VT_CONST 0x000a /* constant in vc
137 (must be first non register value) */
138 #define VT_LLOCAL 0x000b /* lvalue, offset on stack */
139 #define VT_LOCAL 0x000c /* offset on stack */
140 #define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */
141 #define VT_JMP 0x000e /* value is the consequence of jmp true */
142 #define VT_JMPI 0x000f /* value is the consequence of jmp false */
143 #define VT_LVAL 0x0010 /* var is an lvalue */
144 #define VT_LVALN -17 /* ~VT_LVAL */
145 #define VT_FORWARD 0x0020 /* value is forward reference
146 (only used for functions) */
150 #define VT_VOID 0x00040
151 #define VT_BYTE 0x00080 /* signed byte type */
152 #define VT_PTR 0x00100 /* pointer increment */
153 #define VT_UNSIGNED 0x00200 /* unsigned type */
154 #define VT_ARRAY 0x00400 /* array type (only used in parsing) */
155 #define VT_ENUM 0x00800 /* enum definition */
156 #define VT_FUNC 0x01000 /* function type */
157 #define VT_STRUCT 0x002000 /* struct/union definition */
158 #define VT_SHORT 0x004000 /* short type */
159 #define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
162 #define VT_EXTERN 0x00008000 /* extern definition */
163 #define VT_STATIC 0x00010000 /* static variable */
164 #define VT_TYPEDEF 0x00020000 /* typedef definition */
166 #define VT_TYPE 0xfffc7fc0 /* type mask */
167 #define VT_TYPEN 0x0000003f /* ~VT_TYPE */
168 #define VT_FUNCN -4097 /* ~VT_FUNC */
172 /* warning: the following compare tokens depend on i386 asm code */
184 #define TOK_LAND 0xa0
188 #define TOK_MID 0xa3 /* inc/dec, to void constant */
190 #define TOK_ARROW 0xa7
191 #define TOK_DOTS 0xa8 /* three dots */
192 #define TOK_SHR 0xa9 /* unsigned shift right */
193 #define TOK_UDIV 0xb0 /* unsigned division */
194 #define TOK_UMOD 0xb1 /* unsigned modulo */
195 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
196 #define TOK_NUM 0xb3 /* number in tokc */
197 #define TOK_CCHAR 0xb4 /* char constant in tokc */
198 #define TOK_STR 0xb5 /* pointer to string in tokc */
199 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
200 #define TOK_LCHAR 0xb7
201 #define TOK_LSTR 0xb8
203 #define TOK_SHL 0x01 /* shift left */
204 #define TOK_SAR 0x02 /* signed shift right */
206 /* assignement operators : normal operator or 0x80 */
207 #define TOK_A_MOD 0xa5
208 #define TOK_A_AND 0xa6
209 #define TOK_A_MUL 0xaa
210 #define TOK_A_ADD 0xab
211 #define TOK_A_SUB 0xad
212 #define TOK_A_DIV 0xaf
213 #define TOK_A_XOR 0xde
214 #define TOK_A_OR 0xfc
215 #define TOK_A_SHL 0x81
216 #define TOK_A_SAR 0x82
218 /* all identificators and strings have token above that */
219 #define TOK_IDENT 256
240 /* ignored types Must have contiguous values */
250 /* unsupported type */
262 /* preprocessor only */
279 /* special identifiers */
291 void decl_initializer(int t
, int c
, int first
, int size_only
);
292 int decl_initializer_alloc(int t
, int has_init
);
298 void macro_subst(int **tok_str
, int *tok_len
,
299 Sym
**nested_list
, int *macro_str
);
300 int save_reg_forced(int r
);
302 int type_size(int t
, int *a
);
303 int pointed_type(int t
);
304 int pointed_size(int t
);
306 int type_decl(int *v
, int t
, int td
);
309 /* dummy function for profiling */
310 void *dlopen(const char *filename
, int flag
)
314 const char *dlerror(void)
319 void *dlsym(void *handle
, char *symbol
)
328 return (c
>= 'a' && c
<= 'z') ||
329 (c
>= 'A' && c
<= 'Z') ||
335 return c
>= '0' & c
<= '9';
341 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
342 fprintf(stderr
, "In file included from %s:%d:\n",
343 f
->filename
, f
->line_num
);
344 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
347 void error(const char *fmt
, ...)
352 vfprintf(stderr
, fmt
, ap
);
353 fprintf(stderr
, "\n");
358 void expect(const char *msg
)
360 error("%s expected", msg
);
363 void warning(const char *msg
)
366 fprintf(stderr
, "warning: %s\n", msg
);
372 error("'%c' expected", c
);
382 TokenSym
*tok_alloc(char *str
, int len
)
384 TokenSym
*ts
, **pts
, **ptable
;
391 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
393 pts
= &hash_ident
[h
];
398 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
400 pts
= &(ts
->hash_next
);
402 /* expand token table if needed */
403 i
= tok_ident
- TOK_IDENT
;
404 if ((i
% TOK_ALLOC_INCR
) == 0) {
405 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
407 error("memory full");
408 table_ident
= ptable
;
410 ts
= malloc(sizeof(TokenSym
) + len
);
412 error("memory full");
414 ts
->tok
= tok_ident
++;
416 ts
->hash_next
= NULL
;
417 memcpy(ts
->str
, str
, len
+ 1);
422 void add_char(char **pp
, int c
)
426 if (c
== '\'' || c
== '\"' || c
== '\\') {
427 /* XXX: could be more precise if char or string */
430 if (c
>= 32 && c
<= 126) {
437 *p
++ = '0' + ((c
>> 6) & 7);
438 *p
++ = '0' + ((c
>> 3) & 7);
439 *p
++ = '0' + (c
& 7);
445 /* XXX: buffer overflow */
446 char *get_tok_str(int v
, int c
)
448 static char buf
[STRING_MAX_SIZE
+ 1];
454 sprintf(buf
, "%d", c
);
456 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
463 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
467 for(i
=0;i
<ts
->len
;i
++)
468 add_char(&p
, ts
->str
[i
]);
472 } else if (v
< TOK_IDENT
) {
477 } else if (v
< tok_ident
) {
478 return table_ident
[v
- TOK_IDENT
]->str
;
480 /* should never happen */
485 /* push, without hashing */
486 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
489 s
= malloc(sizeof(Sym
));
491 error("memory full");
502 /* find a symbol and return its associated structure. 's' is the top
503 of the symbol stack */
504 Sym
*sym_find2(Sym
*s
, int v
)
514 /* find a symbol and return its associated structure. 'st' is the
516 Sym
*sym_find1(SymStack
*st
, int v
)
520 s
= st
->hash
[v
% SYM_HASH_SIZE
];
529 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
532 s
= sym_push2(&st
->top
, v
, t
, c
);
533 /* add in hash table */
534 ps
= &st
->hash
[s
->v
% SYM_HASH_SIZE
];
540 /* find a symbol in the right symbol space */
544 s
= sym_find1(&local_stack
, v
);
546 s
= sym_find1(&global_stack
, v
);
550 /* push a given symbol on the symbol stack */
551 Sym
*sym_push(int v
, int t
, int c
)
554 return sym_push1(&local_stack
, v
, t
, c
);
556 return sym_push1(&global_stack
, v
, t
, c
);
559 /* pop symbols until top reaches 'b' */
560 void sym_pop(SymStack
*st
, Sym
*b
)
567 /* free hash table entry */
568 st
->hash
[s
->v
% SYM_HASH_SIZE
] = s
->hash_next
;
577 /* read next char from current input file */
583 if (include_stack_ptr
== include_stack
)
585 /* pop include stack */
589 file
= include_stack_ptr
->file
;
590 filename
= include_stack_ptr
->filename
;
591 line_num
= include_stack_ptr
->line_num
;
596 // printf("ch1=%c 0x%x\n", ch1, ch1);
599 /* input with '\\n' handling */
605 if (ch
== '\\' && ch1
== '\n') {
609 //printf("ch=%c 0x%x\n", ch, ch);
612 /* same as minp, but also skip comments */
620 /* single line C++ comments */
622 while (ch1
!= '\n' && ch1
!= -1)
625 ch
= ' '; /* return space */
626 } else if (ch1
== '*') {
632 if (c
== '*' && ch1
== '/') {
634 ch
= ' '; /* return space */
648 while (ch
== ' ' || ch
== '\t')
652 /* skip block of text until #else, #elif or #endif. skip also pairs of
654 void preprocess_skip()
670 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
672 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
674 else if (tok
== TOK_ENDIF
)
680 inline int is_long_tok(int t
)
682 return (t
== TOK_NUM
||
683 t
== TOK_CCHAR
|| t
== TOK_LCHAR
||
684 t
== TOK_STR
|| t
== TOK_LSTR
);
687 void tok_add(int **tok_str
, int *tok_len
, int t
)
692 if ((len
& 63) == 0) {
693 str
= realloc(str
, (len
+ 64) * sizeof(int));
702 void tok_add2(int **tok_str
, int *tok_len
, int t
, int c
)
704 tok_add(tok_str
, tok_len
, t
);
706 tok_add(tok_str
, tok_len
, c
);
709 /* eval an expression for #if/#elif */
710 int expr_preprocess()
720 next(); /* do macro subst */
721 if (tok
== TOK_DEFINED
) {
726 c
= sym_find1(&define_stack
, tok
) != 0;
731 } else if (tok
>= TOK_IDENT
) {
732 /* if undefined macro */
736 tok_add2(&str
, &len
, tok
, tokc
);
738 tok_add(&str
, &len
, -1); /* simulate end of file */
739 tok_add(&str
, &len
, 0);
740 /* now evaluate C constant expression */
750 void tok_print(int *str
)
761 printf(" %s", get_tok_str(t
, c
));
767 /* XXX: should be more factorized */
768 void define_symbol(char *sym
)
773 ts
= tok_alloc(sym
, 0);
776 tok_add2(&str
, &len
, TOK_NUM
, 1);
777 tok_add(&str
, &len
, 0);
778 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
783 int size
, i
, c
, v
, t
, *str
, len
;
784 char buf
[1024], *q
, *p
;
787 Sym
**ps
, *first
, *s
;
792 if (tok
== TOK_DEFINE
) {
795 /* XXX: should check if same macro (ANSI) */
798 /* '(' must be just after macro definition for MACRO_FUNC */
805 tok
= TOK___VA_ARGS__
;
806 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
820 if (ch
== '\n' || ch
== -1)
823 tok_add2(&str
, &len
, tok
, tokc
);
825 tok_add(&str
, &len
, 0);
827 printf("define %s %d: ", get_tok_str(v
, 0), t
);
830 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
832 } else if (tok
== TOK_UNDEF
) {
834 s
= sym_find1(&define_stack
, tok
);
835 /* undefine symbol by putting an invalid name */
838 } else if (tok
== TOK_INCLUDE
) {
843 } else if (ch
== '\"') {
848 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
849 if ((q
- buf
) < sizeof(buf
) - 1)
857 error("#include syntax error");
858 /* XXX: buffer overflow */
859 strcpy(buf
, get_tok_str(tok
, tokc
));
862 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
863 error("memory full");
865 /* first search in current dir if "header.h" */
866 /* XXX: buffer overflow */
868 p
= strrchr(filename
, '/');
870 size
= p
+ 1 - filename
;
871 memcpy(buf1
, filename
, size
);
874 f
= fopen(buf1
, "r");
878 /* now search in standard include path */
879 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
880 strcpy(buf1
, include_paths
[i
]);
883 f
= fopen(buf1
, "r");
887 error("include file not found");
890 /* push current file in stack */
891 /* XXX: fix current line init */
892 include_stack_ptr
->file
= file
;
893 include_stack_ptr
->filename
= filename
;
894 include_stack_ptr
->line_num
= line_num
;
897 filename
= strdup(buf1
);
899 } else if (tok
== TOK_IFNDEF
) {
902 } else if (tok
== TOK_IF
) {
903 c
= expr_preprocess();
905 } else if (tok
== TOK_IFDEF
) {
909 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
911 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
912 error("memory full");
913 *ifdef_stack_ptr
++ = c
;
915 } else if (tok
== TOK_ELSE
) {
916 if (ifdef_stack_ptr
== ifdef_stack
||
917 (ifdef_stack_ptr
[-1] & 2))
918 error("#else after #else");
919 c
= (ifdef_stack_ptr
[-1] ^= 3);
921 } else if (tok
== TOK_ELIF
) {
922 if (ifdef_stack_ptr
== ifdef_stack
||
923 ifdef_stack_ptr
[-1] > 1)
924 error("#elif after #else");
925 c
= expr_preprocess();
926 ifdef_stack_ptr
[-1] = c
;
932 } else if (tok
== TOK_ENDIF
) {
933 if (ifdef_stack_ptr
== ifdef_stack
)
936 } else if (tok
== TOK_LINE
) {
946 /* XXX: potential memory leak */
947 filename
= strdup(get_tok_str(tok
, tokc
));
949 } else if (tok
== TOK_ERROR
) {
952 /* ignore other preprocess commands or #! for C scripts */
953 while (ch
!= '\n' && ch
!= -1)
957 /* read a number in base b */
963 if (ch
>= 'a' & ch
<= 'f')
965 else if (ch
>= 'A' & ch
<= 'F')
979 /* read a character for string or char constant and eval escape codes */
988 /* at most three octal digits */
992 c
= c
* 8 + ch
- '0';
995 c
= c
* 8 + ch
- '0';
1000 } else if (ch
== 'x') {
1026 /* return next token without macro substitution */
1027 void next_nomacro1()
1035 while (ch
== '\n') {
1037 while (ch
== ' ' || ch
== 9)
1040 /* preprocessor command if # at start of line after
1045 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1054 /* XXX: not supported entirely (needs different
1055 preprocessor architecture) */
1065 while (isid(ch
) | isnum(ch
)) {
1066 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1067 error("ident too long");
1072 ts
= tok_alloc(token_buf
, q
- token_buf
);
1074 } else if (isnum(ch
)) {
1080 if (ch
== 'x' || ch
== 'X') {
1083 } else if (ch
== 'b' || ch
== 'B') {
1089 /* XXX: add unsigned constant support (ANSI) */
1090 while (ch
== 'L' || ch
== 'l' || ch
== 'U' || ch
== 'u')
1093 } else if (ch
== '\'') {
1101 } else if (ch
== '\"') {
1106 while (ch
!= '\"') {
1109 error("unterminated string");
1110 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1111 error("string too long");
1115 tokc
= (int)tok_alloc(token_buf
, q
- token_buf
);
1118 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1123 if (*q
== tok
& q
[1] == ch
) {
1126 /* three chars tests */
1127 if (tok
== TOK_SHL
| tok
== TOK_SAR
) {
1132 } else if (tok
== TOK_DOTS
) {
1134 error("parse error");
1141 /* single char substitutions */
1144 else if (tok
== '>')
1149 /* return next token without macro substitution. Can read input from
1157 if (is_long_tok(tok
))
1158 tokc
= *macro_ptr
++;
1165 /* substitute args in macro_str and return allocated string */
1166 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1168 int *st
, last_tok
, t
, c
, notfirst
, *str
, len
;
1184 s
= sym_find2(args
, t
);
1186 token_buf
[0] = '\0';
1188 /* XXX: buffer overflow */
1192 strcat(token_buf
, " ");
1197 strcat(token_buf
, get_tok_str(t
, c
));
1201 printf("stringize: %s\n", token_buf
);
1204 ts
= tok_alloc(token_buf
, 0);
1205 tok_add2(&str
, &len
, TOK_STR
, (int)ts
);
1207 tok_add(&str
, &len
, t
);
1209 } else if (is_long_tok(t
)) {
1210 tok_add2(&str
, &len
, t
, *macro_str
++);
1212 s
= sym_find2(args
, t
);
1215 /* if '##' is present before or after , no arg substitution */
1216 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1218 tok_add(&str
, &len
, *st
++);
1220 macro_subst(&str
, &len
, nested_list
, st
);
1223 tok_add(&str
, &len
, t
);
1228 tok_add(&str
, &len
, 0);
1232 /* handle the '##' operator */
1233 int *macro_twosharps(int *macro_str
)
1236 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1247 if (*macro_ptr
== TOK_TWOSHARPS
) {
1249 macro_ptr1
= macro_ptr
;
1256 /* XXX: we handle only most common cases:
1257 ident + ident or ident + number */
1258 if (tok
>= TOK_IDENT
&&
1259 (t
>= TOK_IDENT
|| t
== TOK_NUM
)) {
1260 /* XXX: buffer overflow */
1261 p
= get_tok_str(tok
, tokc
);
1262 strcpy(token_buf
, p
);
1263 p
= get_tok_str(t
, c
);
1264 strcat(token_buf
, p
);
1265 ts
= tok_alloc(token_buf
, 0);
1266 tok_add2(¯o_str1
, ¯o_str1_len
, ts
->tok
, 0);
1268 /* cannot merge tokens: skip '##' */
1269 macro_ptr
= macro_ptr1
;
1273 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, tokc
);
1276 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1282 /* do macro substitution of macro_str and add result to
1283 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1284 substituted. 'nested_list' is the list of all macros we got inside
1285 to avoid recursing. */
1286 void macro_subst(int **tok_str
, int *tok_len
,
1287 Sym
**nested_list
, int *macro_str
)
1289 Sym
*s
, *args
, *sa
, *sa1
;
1290 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
1291 int mstr_allocated
, *macro_str1
;
1293 saved_macro_ptr
= macro_ptr
;
1294 macro_ptr
= macro_str
;
1297 /* first scan for '##' operator handling */
1298 macro_str1
= macro_twosharps(macro_str
);
1299 macro_ptr
= macro_str1
;
1306 /* special macros */
1307 if (tok
== TOK___LINE__
) {
1308 tok_add2(tok_str
, tok_len
, TOK_NUM
, line_num
);
1309 } else if (tok
== TOK___FILE__
) {
1310 tok_add2(tok_str
, tok_len
, TOK_STR
,
1311 (int)tok_alloc(filename
, 0));
1312 } else if (tok
== TOK___DATE__
) {
1313 tok_add2(tok_str
, tok_len
, TOK_STR
,
1314 (int)tok_alloc("Jan 1 1970", 0));
1315 } else if (tok
== TOK___TIME__
) {
1316 tok_add2(tok_str
, tok_len
, TOK_STR
,
1317 (int)tok_alloc("00:00:00", 0));
1318 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
1319 /* if symbol is a macro, prepare substitution */
1320 /* if nested substitution, do nothing */
1321 if (sym_find2(*nested_list
, tok
))
1325 if (s
->t
== MACRO_FUNC
) {
1326 /* NOTE: we do not use next_nomacro to avoid eating the
1327 next token. XXX: find better solution */
1331 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
1335 if (t
!= '(') /* no macro subst */
1338 /* argument macro */
1343 while (tok
!= ')' && sa
) {
1347 while ((parlevel
> 0 ||
1350 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
1354 else if (tok
== ')')
1356 tok_add2(&str
, &len
, tok
, tokc
);
1359 tok_add(&str
, &len
, 0);
1360 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
1368 /* now subst each arg */
1369 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
1380 sym_push2(nested_list
, s
->v
, 0, 0);
1381 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
1382 /* pop nested defined symbol */
1384 *nested_list
= sa1
->prev
;
1390 /* no need to add if reading input stream */
1393 tok_add2(tok_str
, tok_len
, tok
, tokc
);
1395 /* only replace one macro while parsing input stream */
1399 macro_ptr
= saved_macro_ptr
;
1404 /* return next token with macro substitution */
1410 /* special 'ungettok' case for label parsing */
1417 /* if not reading from macro substuted string, then try to substitute */
1421 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
1423 tok_add(&ptr
, &len
, 0);
1425 macro_ptr_allocated
= ptr
;
1433 /* end of macro string: free it */
1434 free(macro_ptr_allocated
);
1441 printf("token = %s\n", get_tok_str(tok
, tokc
));
1445 void swap(int *p
, int *q
)
1459 /******************************************************/
1460 /* X86 code generator */
1462 typedef struct GFuncContext
{
1479 void gen_le32(int c
)
1487 /* add a new relocation entry to symbol 's' */
1488 void greloc(Sym
*s
, int addr
, int type
)
1491 p
= malloc(sizeof(Reloc
));
1493 error("memory full");
1496 p
->next
= (Reloc
*)s
->c
;
1500 /* patch each relocation entry with value 'val' */
1501 void greloc_patch(Sym
*s
, int val
)
1510 *(int *)p
->addr
= val
;
1513 *(int *)p
->addr
= val
- p
->addr
- 4;
1522 /* output a symbol and patch all calls to it */
1523 void gsym_addr(t
, a
)
1527 n
= *(int *)t
; /* next value */
1528 *(int *)t
= a
- t
- 4;
1538 /* psym is used to put an instruction with a data field which is a
1539 reference to a symbol. It is in fact the same as oad ! */
1542 /* instruction + 4 bytes data. Return the address of the data */
1543 int oad(int c
, int s
)
1552 /* output constant with relocation if 't & VT_FORWARD' is true */
1553 void gen_addr32(int c
, int t
)
1555 if (!(t
& VT_FORWARD
)) {
1558 greloc((Sym
*)c
, ind
, RELOC_ADDR32
);
1563 /* XXX: generate correct pointer for forward references to functions */
1565 void load(r
, ft
, fc
)
1569 v
= ft
& VT_VALMASK
;
1571 if (v
== VT_LLOCAL
) {
1572 load(r
, VT_LOCAL
| VT_LVAL
, fc
);
1575 if ((ft
& VT_TYPE
) == VT_BYTE
)
1576 o(0xbe0f); /* movsbl */
1577 else if ((ft
& VT_TYPE
) == (VT_BYTE
| VT_UNSIGNED
))
1578 o(0xb60f); /* movzbl */
1579 else if ((ft
& VT_TYPE
) == VT_SHORT
)
1580 o(0xbf0f); /* movswl */
1581 else if ((ft
& VT_TYPE
) == (VT_SHORT
| VT_UNSIGNED
))
1582 o(0xb70f); /* movzwl */
1585 if (v
== VT_CONST
) {
1586 o(0x05 + r
* 8); /* 0xXX, r */
1588 } else if (v
== VT_LOCAL
) {
1589 oad(0x85 + r
* 8, fc
); /* xx(%ebp), r */
1591 g(0x00 + r
* 8 + v
); /* (v), r */
1594 if (v
== VT_CONST
) {
1595 o(0xb8 + r
); /* mov $xx, r */
1597 } else if (v
== VT_LOCAL
) {
1599 oad(0x85 + r
* 8, fc
); /* lea xxx(%ebp), r */
1600 } else if (v
== VT_CMP
) {
1601 oad(0xb8 + r
, 0); /* mov $0, r */
1602 o(0x0f); /* setxx %br */
1605 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1607 oad(0xb8 + r
, t
); /* mov $1, r */
1608 oad(0xe9, 5); /* jmp after */
1610 oad(0xb8 + r
, t
^ 1); /* mov $0, r */
1611 } else if (v
!= r
) {
1613 o(0xc0 + r
+ v
* 8); /* mov v, r */
1619 /* WARNING: r must not be allocated on the stack */
1620 void store(r
, ft
, fc
)
1624 fr
= ft
& VT_VALMASK
;
1625 b
= (ft
& VT_TYPE
) == VT_BYTE
;
1626 /* XXX: incorrect if reg to reg */
1630 if (fr
== VT_CONST
) {
1631 o(0x05 + r
* 8); /* mov r,xxx */
1633 } else if (fr
== VT_LOCAL
) {
1634 oad(0x85 + r
* 8, fc
); /* mov r,xxx(%ebp) */
1635 } else if (ft
& VT_LVAL
) {
1636 g(fr
+ r
* 8); /* mov r, (fr) */
1637 } else if (fr
!= r
) {
1638 o(0xc0 + fr
+ r
* 8); /* mov r, fr */
1642 /* start function call and return function call context */
1643 void gfunc_start(GFuncContext
*c
)
1648 /* push function parameter which is in (vt, vc) */
1649 void gfunc_param(GFuncContext
*c
)
1651 int size
, align
, ft
, fc
, r
;
1653 if ((vt
& (VT_STRUCT
| VT_LVAL
)) == (VT_STRUCT
| VT_LVAL
)) {
1654 size
= type_size(vt
, &align
);
1655 /* align to stack align size */
1656 size
= (size
+ 3) & ~3;
1657 /* allocate the necessary size on stack */
1658 oad(0xec81, size
); /* sub $xxx, %esp */
1659 /* generate structure store */
1661 o(0x89); /* mov %esp, r */
1665 vset(VT_INT
| r
, 0);
1670 c
->args_size
+= size
;
1672 /* simple type (currently always same size) */
1673 /* XXX: implicit cast ? */
1675 o(0x50 + r
); /* push r */
1680 /* generate function call with address in (ft, fc) and free function */
1681 void gfunc_call(GFuncContext
*c
, int ft
, int fc
)
1684 r
= ft
& VT_VALMASK
;
1685 if (r
== VT_CONST
) {
1686 /* forward reference */
1687 if (ft
& VT_FORWARD
) {
1688 greloc((Sym
*)fc
, ind
+ 1, RELOC_REL32
);
1691 oad(0xe8, fc
- ind
- 5);
1693 } else if (r
== VT_LOCAL
) {
1694 oad(0x95ff, fc
); /* call *xxx(%ebp) */
1696 /* not actually used */
1697 o(0xff); /* call *r */
1701 oad(0xc481, c
->args_size
); /* add $xxx, %esp */
1706 return psym(0xe9, t
);
1709 /* generate a test. set 'inv' to invert test */
1713 v
= vt
& VT_VALMASK
;
1715 /* fast case : can jump directly since flags are set */
1717 t
= psym((vc
- 16) ^ inv
, t
);
1718 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1719 /* && or || optimization */
1720 if ((v
& 1) == inv
) {
1721 /* insert vc jump list in t */
1731 } else if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1732 /* constant jmp optimization */
1733 if ((vc
!= 0) != inv
)
1740 t
= psym(0x85 ^ inv
, t
);
1745 /* generate a binary operation 'v = r op fr' instruction and modifies
1746 (vt,vc) if needed */
1747 void gen_op1(op
, r
, fr
)
1752 o(0xc0 + r
+ fr
* 8);
1753 } else if (op
== '-') {
1755 o(0xc0 + r
+ fr
* 8);
1756 } else if (op
== '&') {
1758 o(0xc0 + r
+ fr
* 8);
1759 } else if (op
== '^') {
1761 o(0xc0 + r
+ fr
* 8);
1762 } else if (op
== '|') {
1764 o(0xc0 + r
+ fr
* 8);
1765 } else if (op
== '*') {
1766 o(0xaf0f); /* imul fr, r */
1767 o(0xc0 + fr
+ r
* 8);
1768 } else if (op
== TOK_SHL
| op
== TOK_SHR
| op
== TOK_SAR
) {
1774 o(0x87); /* xchg r, %ecx */
1779 o(0xd3); /* shl/shr/sar %cl, r */
1782 else if (op
== TOK_SHR
)
1786 vt
= (vt
& VT_TYPE
) | r
;
1787 } else if (op
== '/' | op
== TOK_UDIV
| op
== TOK_PDIV
|
1788 op
== '%' | op
== TOK_UMOD
) {
1789 save_reg(2); /* save edx */
1790 t
= save_reg_forced(fr
); /* save fr and get op2 location */
1791 move_reg(0, r
); /* op1 is %eax */
1792 if (op
== TOK_UDIV
| op
== TOK_UMOD
) {
1793 o(0xf7d231); /* xor %edx, %edx, div t(%ebp), %eax */
1796 o(0xf799); /* cltd, idiv t(%ebp), %eax */
1799 if (op
== '%' | op
== TOK_UMOD
)
1803 vt
= (vt
& VT_TYPE
) | r
;
1806 o(0xc0 + r
+ fr
* 8); /* cmp fr, r */
1811 /* end of X86 code generator */
1812 /*************************************************************/
1814 int save_reg_forced(int r
)
1817 /* store register */
1818 loc
= (loc
- 4) & -3;
1819 store(r
, VT_LOCAL
, loc
);
1822 /* modify all stack values */
1823 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1824 i
= p
[0] & VT_VALMASK
;
1830 p
[0] = (p
[0] & VT_TYPE
) | VT_LVAL
| t
;
1837 /* save r to memory. and mark it as being free */
1842 /* modify all stack values */
1843 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1844 i
= p
[0] & VT_VALMASK
;
1852 /* find a free register. If none, save one register */
1857 /* find a free register */
1858 for(r
=0;r
<NB_REGS
;r
++) {
1859 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1860 i
= p
[0] & VT_VALMASK
;
1868 /* no register left : free the first one on the stack (very
1869 important to start from the bottom to ensure that we don't
1870 spill registers used in gen_op()) */
1871 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1872 r
= p
[0] & VT_VALMASK
;
1884 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1885 r
= p
[0] & VT_VALMASK
;
1892 /* move register 's' to 'r', and flush previous value of r to memory
1902 /* convert a stack entry in register. lvalues are converted as
1903 values. Cannot be used if cannot be converted to register value
1904 (such as structures). */
1908 r
= p
[0] & VT_VALMASK
;
1909 if (r
>= VT_CONST
|| (p
[0] & VT_LVAL
))
1911 /* NOTE: get_reg can modify p[] */
1912 load(r
, p
[0], p
[1]);
1913 p
[0] = (p
[0] & VT_TYPE
) | r
;
1919 if (vstack_ptr
>= vstack
+ VSTACK_SIZE
)
1920 error("memory full");
1923 /* cannot let cpu flags if other instruction are generated */
1924 if ((vt
& VT_VALMASK
) == VT_CMP
)
1925 gvp(vstack_ptr
- 2);
1928 void vpop(int *ft
, int *fc
)
1930 *fc
= *--vstack_ptr
;
1931 *ft
= *--vstack_ptr
;
1934 /* generate a value in a register from vt and vc */
1939 r
= gvp(vstack_ptr
- 2);
1944 /* handle constant optimizations and various machine independant opt */
1947 int fr
, ft
, fc
, r
, c1
, c2
, n
;
1951 c1
= (vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
;
1952 c2
= (ft
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
;
1955 case '+': vc
+= fc
; break;
1956 case '-': vc
-= fc
; break;
1957 case '&': vc
&= fc
; break;
1958 case '^': vc
^= fc
; break;
1959 case '|': vc
|= fc
; break;
1960 case '*': vc
*= fc
; break;
1962 case '/': vc
/= fc
; break; /* XXX: zero case ? */
1963 case '%': vc
%= fc
; break; /* XXX: zero case ? */
1964 case TOK_UDIV
: vc
= (unsigned)vc
/ fc
; break; /* XXX: zero case ? */
1965 case TOK_UMOD
: vc
= (unsigned)vc
% fc
; break; /* XXX: zero case ? */
1966 case TOK_SHL
: vc
<<= fc
; break;
1967 case TOK_SHR
: vc
= (unsigned)vc
>> fc
; break;
1968 case TOK_SAR
: vc
>>= fc
; break;
1970 case TOK_ULT
: vc
= (unsigned)vc
< (unsigned)fc
; break;
1971 case TOK_UGE
: vc
= (unsigned)vc
>= (unsigned)fc
; break;
1972 case TOK_EQ
: vc
= vc
== fc
; break;
1973 case TOK_NE
: vc
= vc
!= fc
; break;
1974 case TOK_ULE
: vc
= (unsigned)vc
<= (unsigned)fc
; break;
1975 case TOK_UGT
: vc
= (unsigned)vc
> (unsigned)fc
; break;
1976 case TOK_LT
: vc
= vc
< fc
; break;
1977 case TOK_GE
: vc
= vc
>= fc
; break;
1978 case TOK_LE
: vc
= vc
<= fc
; break;
1979 case TOK_GT
: vc
= vc
> fc
; break;
1981 case TOK_LAND
: vc
= vc
&& fc
; break;
1982 case TOK_LOR
: vc
= vc
|| fc
; break;
1987 /* if commutative ops, put c2 as constant */
1988 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
1989 op
== '|' || op
== '*')) {
1994 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
1997 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
1998 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2002 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2003 /* try to use shifts instead of muls or divs */
2004 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2013 else if (op
== TOK_PDIV
)
2025 r
= gvp(vstack_ptr
- 4);
2026 fr
= gvp(vstack_ptr
- 2);
2029 /* call low level op generator */
2035 int pointed_size(int t
)
2037 return type_size(pointed_type(t
), &t
);
2040 /* generic gen_op: handles types problems */
2046 t1
= vstack_ptr
[-4];
2047 t2
= vstack_ptr
[-2];
2048 if (op
== '+' | op
== '-') {
2049 if ((t1
& VT_PTR
) && (t2
& VT_PTR
)) {
2051 error("invalid type");
2052 /* XXX: check that types are compatible */
2053 u
= pointed_size(t1
);
2056 vstack_ptr
[-2] &= ~VT_TYPE
; /* set to integer */
2059 } else if ((t1
| t2
) & VT_PTR
) {
2061 swap(vstack_ptr
- 4, vstack_ptr
- 2);
2062 swap(vstack_ptr
- 3, vstack_ptr
- 1);
2065 /* stack-4 contains pointer, stack-2 value to add */
2066 vset(VT_CONST
, pointed_size(vstack_ptr
[-4]));
2070 /* put again type if gen_opc() swaped operands */
2071 vt
= (vt
& VT_TYPEN
) | (t1
& VT_TYPE
);
2076 /* XXX: test types and compute returned value */
2077 if ((t1
| t2
) & (VT_UNSIGNED
| VT_PTR
)) {
2084 else if (op
== TOK_LT
)
2086 else if (op
== TOK_GT
)
2088 else if (op
== TOK_LE
)
2090 else if (op
== TOK_GE
)
2097 /* cast (vt, vc) to 't' type */
2098 void gen_cast(int t
)
2101 r
= vt
& VT_VALMASK
;
2102 if (!(t
& VT_LVAL
)) {
2103 /* if not lvalue, then we convert now */
2104 if ((t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_BYTE
)
2106 else if ((t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_SHORT
)
2111 if (t
& VT_UNSIGNED
) {
2112 vset(VT_CONST
, (1 << bits
) - 1);
2116 vset(VT_CONST
, bits
);
2119 vset(VT_CONST
, bits
);
2124 vt
= (vt
& VT_TYPEN
) | t
;
2127 /* return type size. Put alignment at 'a' */
2128 int type_size(int t
, int *a
)
2132 /* int, enum or pointer */
2133 if (t
& VT_STRUCT
) {
2135 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2136 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
2138 } else if (t
& VT_ARRAY
) {
2139 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2140 return type_size(s
->t
, a
) * s
->c
;
2141 } else if ((t
& VT_PTR
) |
2142 (t
& VT_TYPE
) == 0 |
2146 } else if (t
& VT_SHORT
) {
2155 /* return the pointed type of t */
2156 int pointed_type(int t
)
2159 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2160 return s
->t
| (t
& VT_TYPEN
);
2163 int mk_pointer(int t
)
2168 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& VT_TYPEN
);
2171 /* store value in lvalue pushed on stack */
2174 int ft
, fc
, r
, t
, size
, align
;
2177 if (vt
& VT_STRUCT
) {
2178 /* if structure, only generate pointer */
2179 /* structure assignment : generate memcpy */
2180 /* XXX: optimize if small size */
2186 size
= type_size(vt
, &align
);
2187 vset(VT_CONST
, size
);
2199 gfunc_call(&gf
, VT_CONST
, (int)&memcpy
);
2201 /* generate again current type */
2205 r
= gv(); /* generate value */
2207 ft
= vstack_ptr
[-4];
2208 fc
= vstack_ptr
[-3];
2209 /* if lvalue was saved on stack, must read it */
2210 if ((ft
& VT_VALMASK
) == VT_LLOCAL
) {
2212 load(t
, VT_LOCAL
| VT_LVAL
, fc
);
2213 ft
= (ft
& ~VT_VALMASK
) | t
;
2220 /* post defines POST/PRE add. c is the token ++ or -- */
2226 vpush(); /* room for returned value */
2227 vpush(); /* save lvalue */
2229 vpush(); /* save value */
2231 /* duplicate value */
2233 load(r1
, r
, 0); /* move r to r1 */
2234 vstack_ptr
[-6] = (vt
& VT_TYPE
) | r1
;
2238 vset(VT_CONST
, c
- TOK_MID
);
2240 vstore(); /* store value */
2245 /* enum/struct/union declaration */
2246 int struct_decl(int u
)
2248 int a
, t
, b
, v
, size
, align
, maxalign
, c
;
2251 a
= tok
; /* save decl type */
2256 /* struct already defined ? return it */
2257 /* XXX: check consistency */
2258 if (s
= sym_find(v
| SYM_STRUCT
)) {
2260 error("invalid type");
2266 s
= sym_push(v
| SYM_STRUCT
, a
, 0);
2267 /* put struct/union/enum name in type */
2269 u
= u
| (v
<< VT_STRUCT_SHIFT
);
2274 error("struct/union/enum already defined");
2275 /* cannot be empty */
2280 if (a
== TOK_ENUM
) {
2287 sym_push(v
, VT_CONST
, c
);
2294 t
= type_decl(&v
, b
, TYPE_DIRECT
);
2295 if (t
& (VT_FUNC
| VT_TYPEDEF
))
2296 error("invalid type");
2297 /* XXX: align & correct type size */
2299 size
= type_size(t
, &align
);
2300 if (a
== TOK_STRUCT
) {
2301 c
= (c
+ align
- 1) & -align
;
2302 ss
= sym_push(v
, t
, c
);
2305 ss
= sym_push(v
, t
, 0);
2309 if (align
> maxalign
)
2313 if (tok
== ';' || tok
== -1)
2323 /* size for struct/union, dummy for enum */
2324 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
2329 /* return 0 if no type declaration. otherwise, return the basic type
2331 XXX: A '2' is ored to ensure non zero return if int type.
2340 if (tok
== TOK_ENUM
) {
2341 t
|= struct_decl(VT_ENUM
);
2342 } else if (tok
== TOK_STRUCT
|| tok
== TOK_UNION
) {
2343 t
|= struct_decl(VT_STRUCT
);
2345 if (tok
== TOK_CHAR
) {
2347 } else if (tok
== TOK_VOID
) {
2349 } else if (tok
== TOK_SHORT
) {
2351 } else if (tok
== TOK_INT
|
2352 (tok
>= TOK_CONST
& tok
<= TOK_INLINE
)) {
2354 } else if (tok
== TOK_FLOAT
|| tok
== TOK_DOUBLE
) {
2355 /* We allow that to compile standard headers */
2356 // warning("floats not supported");
2357 } else if (tok
== TOK_EXTERN
) {
2359 } else if (tok
== TOK_STATIC
) {
2361 } else if (tok
== TOK_UNSIGNED
) {
2363 } else if (tok
== TOK_TYPEDEF
) {
2367 if (!s
|| !(s
->t
& VT_TYPEDEF
))
2369 t
|= (s
->t
& ~VT_TYPEDEF
);
2381 Sym
**plast
, *s
, *first
;
2384 /* function declaration */
2389 while (tok
!= ')') {
2390 /* read param name and compute offset */
2391 if (l
!= FUNC_OLD
) {
2392 if (!(pt
= ist())) {
2394 error("invalid type");
2400 if (pt
& VT_VOID
&& tok
== ')')
2403 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
2410 /* array must be transformed to pointer according to ANSI C */
2412 s
= sym_push(n
| SYM_FIELD
, pt
, 0);
2417 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
2426 /* we push a anonymous symbol which will contain the function prototype */
2428 s
= sym_push(p
, t
, l
);
2430 t
= VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
2431 } else if (tok
== '[') {
2432 /* array definition */
2438 error("invalid array size");
2441 /* parse next post type */
2444 /* we push a anonymous symbol which will contain the array
2448 t
= VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
2453 /* Read a type declaration (except basic type), and return the
2454 type. If v is true, then also put variable name in 'vc' */
2455 int type_decl(int *v
, int t
, int td
)
2460 t
= t
& -3; /* suppress the ored '2' */
2461 while (tok
== '*') {
2463 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
2468 /* recursive type */
2469 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2472 u
= type_decl(v
, 0, td
);
2476 /* type identifier */
2477 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
2481 if (!(td
& TYPE_ABSTRACT
))
2482 expect("identifier");
2486 /* append t at the end of u */
2492 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
2502 /* define a new external reference to a function 'v' of type 'u' */
2503 Sym
*external_sym(int v
, int u
)
2508 /* push forward reference */
2509 s
= sym_push1(&global_stack
,
2510 v
, u
| VT_CONST
| VT_FORWARD
, 0);
2521 vt
= pointed_type(vt
);
2522 if (!(vt
& VT_ARRAY
)) /* an array is never an lvalue */
2528 int n
, t
, ft
, fc
, p
, align
, size
;
2532 if (tok
== TOK_NUM
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
2533 vset(VT_CONST
, tokc
);
2535 } else if (tok
== TOK___FUNC__
) {
2536 /* special function name identifier */
2537 /* generate (char *) type */
2538 vset(VT_CONST
| mk_pointer(VT_BYTE
), glo
);
2539 strcpy((void *)glo
, funcname
);
2540 glo
+= strlen(funcname
) + 1;
2541 } else if (tok
== TOK_LSTR
) {
2544 } else if (tok
== TOK_STR
) {
2545 /* string parsing */
2548 type_size(t
, &align
);
2549 glo
= (glo
+ align
- 1) & -align
;
2551 /* we must declare it as an array first to use initializer parser */
2552 t
= VT_CONST
| VT_ARRAY
| mk_pointer(t
);
2553 decl_initializer(t
, glo
, 1, 0);
2554 glo
+= type_size(t
, &align
);
2555 /* put it as pointer */
2556 vset(t
& ~VT_ARRAY
, fc
);
2563 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2565 /* check ISOC99 compound literal */
2567 /* data is allocated locally by default */
2572 /* all except arrays are lvalues */
2573 if (!(ft
& VT_ARRAY
))
2575 fc
= decl_initializer_alloc(ft
, 1);
2585 } else if (t
== '*') {
2588 } else if (t
== '&') {
2590 /* functions names must be treated as function pointers,
2591 except for unary '&' and sizeof. Since we consider that
2592 functions are not lvalues, we only have to handle it
2593 there and in function calls. */
2594 if (!(vt
& VT_FUNC
))
2596 vt
= mk_pointer(vt
& VT_LVALN
);
2600 if ((vt
& (VT_CONST
| VT_LVAL
)) == VT_CONST
)
2602 else if ((vt
& VT_VALMASK
) == VT_CMP
)
2605 vset(VT_JMP
, gtst(1, 0));
2616 if (t
== TOK_SIZEOF
) {
2617 /* XXX: some code can be generated */
2621 vt
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2628 vset(VT_CONST
, type_size(vt
, &t
));
2630 if (t
== TOK_INC
| t
== TOK_DEC
) {
2633 } else if (t
== '-') {
2643 error("'%s' undeclared", get_tok_str(t
, 0));
2644 /* for simple function calls, we tolerate undeclared
2645 external reference */
2647 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
2648 /* int() function */
2649 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
));
2652 /* if forward reference, we must point to s */
2653 if (vt
& VT_FORWARD
)
2658 /* post operations */
2660 if (tok
== TOK_INC
| tok
== TOK_DEC
) {
2663 } else if (tok
== '.' | tok
== TOK_ARROW
) {
2665 if (tok
== TOK_ARROW
)
2670 /* expect pointer on structure */
2671 if (!(vt
& VT_STRUCT
))
2672 expect("struct or union");
2673 s
= sym_find(((unsigned)vt
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2676 while (s
= s
->next
) {
2681 error("field not found");
2682 /* add field offset to pointer */
2683 vt
= vt
& VT_TYPEN
; /* change type to int */
2685 vset(VT_CONST
, s
->c
);
2687 /* change type to field type, and set to lvalue */
2688 vt
= (vt
& VT_TYPEN
) | s
->t
;
2689 /* an array is never an lvalue */
2690 if (!(vt
& VT_ARRAY
))
2693 } else if (tok
== '[') {
2700 } else if (tok
== '(') {
2704 if (!(vt
& VT_FUNC
)) {
2705 if ((vt
& (VT_PTR
| VT_ARRAY
)) == VT_PTR
) {
2706 vt
= pointed_type(vt
);
2707 if (!(vt
& VT_FUNC
))
2711 expect("function type");
2714 /* get return type */
2715 s
= sym_find((unsigned)vt
>> VT_STRUCT_SHIFT
);
2717 vt
&= ~VT_LVAL
; /* no lvalue */
2718 vpush(); /* push function address */
2719 save_regs(); /* save used temporary registers */
2722 #ifdef INVERT_FUNC_PARAMS
2724 int *str
, len
, parlevel
, *saved_macro_ptr
;
2727 /* read each argument and store it on a stack */
2728 /* XXX: merge it with macro args ? */
2730 while (tok
!= ')') {
2734 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
2738 else if (tok
== ')')
2740 tok_add2(&str
, &len
, tok
, tokc
);
2743 tok_add(&str
, &len
, -1); /* end of file added */
2744 tok_add(&str
, &len
, 0);
2745 sym_push2(&args
, 0, 0, (int)str
);
2753 /* now generate code in reverse order by reading the stack */
2754 saved_macro_ptr
= macro_ptr
;
2756 macro_ptr
= (int *)args
->c
;
2761 free((int *)args
->c
);
2765 macro_ptr
= saved_macro_ptr
;
2770 /* compute first implicit argument if a structure is returned */
2771 if (s
->t
& VT_STRUCT
) {
2772 /* get some space for the returned structure */
2773 size
= type_size(s
->t
, &align
);
2774 loc
= (loc
- size
) & -align
;
2775 rett
= s
->t
| VT_LOCAL
| VT_LVAL
;
2776 /* pass it as 'int' to avoid structure arg passing
2778 vset(VT_INT
| VT_LOCAL
, loc
);
2782 rett
= s
->t
| FUNC_RET_REG
; /* return in register */
2785 #ifndef INVERT_FUNC_PARAMS
2786 while (tok
!= ')') {
2795 gfunc_call(&gf
, ft
, fc
);
2805 /* check if types are compatible for assignation */
2806 int same_types(int t1
, int t2
)
2811 /* XXX: zero test ? */
2814 t1
= pointed_type(t1
);
2815 t2
= pointed_type(t2
);
2816 /* void matches everything */
2817 if (t1
== VT_VOID
|| t2
== VT_VOID
)
2819 return same_types(t1
, t2
);
2820 } else if (t1
& VT_STRUCT
) {
2823 /* XXX: not complete */
2835 (tok
>= TOK_A_MOD
& tok
<= TOK_A_DIV
) |
2836 tok
== TOK_A_XOR
| tok
== TOK_A_OR
|
2837 tok
== TOK_A_SHL
| tok
== TOK_A_SAR
) {
2844 if (!same_types(vt
, vstack_ptr
[-2]))
2845 error("incompatible types");
2863 while ((l
== 0 & (tok
== '*' | tok
== '/' | tok
== '%')) |
2864 (l
== 1 & (tok
== '+' | tok
== '-')) |
2865 (l
== 2 & (tok
== TOK_SHL
| tok
== TOK_SAR
)) |
2866 (l
== 3 & ((tok
>= TOK_ULE
& tok
<= TOK_GT
) |
2867 tok
== TOK_ULT
| tok
== TOK_UGE
)) |
2868 (l
== 4 & (tok
== TOK_EQ
| tok
== TOK_NE
)) |
2869 (l
== 5 & tok
== '&') |
2870 (l
== 6 & tok
== '^') |
2871 (l
== 7 & tok
== '|') |
2872 (l
== 8 & tok
== TOK_LAND
) |
2873 (l
== 9 & tok
== TOK_LOR
)) {
2883 /* only used if non constant */
2891 if (tok
!= TOK_LAND
) {
2911 if (tok
!= TOK_LOR
) {
2924 /* XXX: better constant handling */
2927 int t
, u
, c
, r1
, r2
;
2954 vt
= (vt
& VT_TYPE
) | r1
;
2976 if ((vt
& (VT_CONST
| VT_LVAL
)) != VT_CONST
)
2982 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
2987 if (tok
== TOK_IF
) {
2994 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
2996 if (c
== TOK_ELSE
) {
3000 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3001 gsym(d
); /* patch else jmp */
3004 } else if (tok
== TOK_WHILE
) {
3012 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3013 oad(0xe9, d
- ind
- 5); /* jmp */
3016 } else if (tok
== '{') {
3019 s
= local_stack
.top
;
3020 while (tok
!= '}') {
3023 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3025 /* pop locally defined symbols */
3026 sym_pop(&local_stack
, s
);
3028 } else if (tok
== TOK_RETURN
) {
3031 if (func_vt
& VT_STRUCT
) {
3032 /* if returning structure, must copy it to implicit
3033 first pointer arg location */
3034 vset(mk_pointer(func_vt
) | VT_LOCAL
| VT_LVAL
, func_vc
);
3039 if (func_vt
& VT_STRUCT
) {
3040 /* copy structure value to pointer */
3043 /* move return value to standard return register */
3044 move_reg(FUNC_RET_REG
, gv());
3048 rsym
= gjmp(rsym
); /* jmp */
3049 } else if (tok
== TOK_BREAK
) {
3052 error("cannot break");
3053 *bsym
= gjmp(*bsym
);
3056 } else if (tok
== TOK_CONTINUE
) {
3059 error("cannot continue");
3060 *csym
= gjmp(*csym
);
3063 } else if (tok
== TOK_FOR
) {
3083 oad(0xe9, d
- ind
- 5); /* jmp */
3087 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3088 oad(0xe9, c
- ind
- 5); /* jmp */
3092 if (tok
== TOK_DO
) {
3097 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3108 if (tok
== TOK_SWITCH
) {
3117 block(&a
, csym
, &b
, &c
, case_reg
);
3118 /* if no default, jmp after switch */
3126 if (tok
== TOK_CASE
) {
3136 *case_sym
= gtst(1, 0);
3138 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3140 if (tok
== TOK_DEFAULT
) {
3146 error("too many 'default'");
3148 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3150 if (tok
== TOK_GOTO
) {
3152 s
= sym_find1(&label_stack
, tok
);
3153 /* put forward definition if needed */
3155 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
3156 /* label already defined */
3157 if (s
->t
& VT_FORWARD
)
3158 s
->c
= gjmp(s
->c
); /* jmp xxx */
3160 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
3169 s
= sym_find1(&label_stack
, b
);
3171 if (!(s
->t
& VT_FORWARD
))
3172 error("multiple defined label");
3177 sym_push1(&label_stack
, b
, 0, ind
);
3179 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3181 /* expression case: go backward of one token */
3182 /* XXX: currently incorrect if number/string/char */
3193 /* t is the array or struct type. c is the array or struct
3194 address. cur_index/cur_field is the pointer to the current
3195 value. 'size_only' is true if only size info is needed (only used
3197 void decl_designator(int t
, int c
,
3198 int *cur_index
, Sym
**cur_field
,
3202 int notfirst
, index
, align
;
3205 while (tok
== '[' || tok
== '.') {
3207 if (!(t
& VT_ARRAY
))
3208 expect("array type");
3209 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3211 index
= expr_const();
3212 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
3213 expect("invalid index");
3217 t
= pointed_type(t
);
3218 c
+= index
* type_size(t
, &align
);
3220 if (!(t
& VT_STRUCT
))
3221 expect("struct/union type");
3223 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3236 t
= f
->t
| (t
& VT_TYPEN
);
3246 t
= pointed_type(t
);
3247 c
+= index
* type_size(t
, &align
);
3251 error("too many field init");
3252 t
= f
->t
| (t
& VT_TYPEN
);
3256 decl_initializer(t
, c
, 0, size_only
);
3259 /* store a value or an expression directly in global data or in local array */
3261 void init_putv(int t
, int c
, int v
, int is_expr
)
3263 int saved_global_expr
;
3265 if ((t
& VT_VALMASK
) == VT_CONST
) {
3267 /* compound literals must be allocated globally in this case */
3268 saved_global_expr
= global_expr
;
3271 global_expr
= saved_global_expr
;
3275 else if (t
& VT_SHORT
)
3291 /* put zeros for variable based init */
3292 void init_putz(int t
, int c
, int size
)
3296 if ((t
& VT_VALMASK
) == VT_CONST
) {
3297 /* nothing to do because global are already set to zero */
3300 vset(VT_CONST
, size
);
3306 gfunc_call(&gf
, VT_CONST
, (int)&memset
);
3310 /* 't' contains the type and storage info. c is the address of the
3311 object. 'first' is true if array '{' must be read (multi dimension
3312 implicit array init handling). 'size_only' is true if size only
3313 evaluation is wanted (only for arrays). */
3314 void decl_initializer(int t
, int c
, int first
, int size_only
)
3316 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
3317 int t1
, size1
, align1
;
3322 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3325 t1
= pointed_type(t
);
3326 size1
= type_size(t1
, &align1
);
3329 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
3335 /* only parse strings here if correct type (otherwise: handle
3336 them as ((w)char *) expressions */
3337 if ((tok
== TOK_LSTR
&&
3338 (t1
& VT_TYPE
& ~VT_UNSIGNED
) == VT_INT
) ||
3340 (t1
& VT_TYPE
& ~VT_UNSIGNED
) == VT_BYTE
)) {
3341 /* XXX: move multiple string parsing in parser ? */
3342 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
3343 ts
= (TokenSym
*)tokc
;
3344 /* compute maximum number of chars wanted */
3346 if (n
>= 0 && nb
> (n
- array_length
))
3347 nb
= n
- array_length
;
3350 warning("initializer-string for array is too long");
3352 init_putv(t1
, c
+ (array_length
+ i
) * size1
,
3359 /* only add trailing zero if enough storage (no
3360 warning in this case since it is standard) */
3361 if (n
< 0 || array_length
< n
) {
3363 init_putv(t1
, c
+ (array_length
* size1
), 0, 0);
3369 while (tok
!= '}') {
3370 decl_designator(t
, c
, &index
, NULL
, size_only
);
3371 if (n
>= 0 && index
>= n
)
3372 error("index too large");
3373 /* must put zero in holes (note that doing it that way
3374 ensures that it even works with designators) */
3375 if (!size_only
&& array_length
< index
) {
3376 init_putz(t1
, c
+ array_length
* size1
,
3377 (index
- array_length
) * size1
);
3380 if (index
> array_length
)
3381 array_length
= index
;
3382 /* special test for multi dimensional arrays (may not
3383 be strictly correct if designators are used at the
3385 if (index
>= n
&& no_oblock
)
3394 /* put zeros at the end */
3395 if (!size_only
&& n
>= 0 && array_length
< n
) {
3396 init_putz(t1
, c
+ array_length
* size1
,
3397 (n
- array_length
) * size1
);
3399 /* patch type size if needed */
3401 s
->c
= array_length
;
3402 } else if ((t
& VT_STRUCT
) && tok
== '{') {
3403 /* XXX: union needs only one init */
3405 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3410 while (tok
!= '}') {
3411 decl_designator(t
, c
, NULL
, &f
, size_only
);
3412 /* fill with zero between fields */
3414 if (!size_only
&& array_length
< index
) {
3415 init_putz(t
, c
+ array_length
,
3416 index
- array_length
);
3418 index
= index
+ type_size(f
->t
, &align1
);
3419 if (index
> array_length
)
3420 array_length
= index
;
3426 /* put zeros at the end */
3427 if (!size_only
&& array_length
< n
) {
3428 init_putz(t
, c
+ array_length
,
3432 } else if (tok
== '{') {
3434 decl_initializer(t
, c
, first
, size_only
);
3436 } else if (size_only
) {
3437 /* just skip expression */
3439 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
3443 else if (tok
== ')')
3448 init_putv(t
, c
, 0, 1);
3452 /* parse an initializer for type 't' if 'has_init' is true, and
3453 allocate space in local or global data space. The allocated address
3455 int decl_initializer_alloc(int t
, int has_init
)
3457 int size
, align
, addr
, tok1
;
3458 int *init_str
, init_len
, level
, *saved_macro_ptr
;
3460 size
= type_size(t
, &align
);
3461 /* If unknown size, we must evaluate it before
3462 evaluating initializers because
3463 initializers can generate global data too
3464 (e.g. string pointers or ISOC99 compound
3465 literals). It also simplifies local
3466 initializers handling */
3469 saved_macro_ptr
= NULL
; /* avoid warning */
3473 error("unknown type size");
3474 /* get all init string */
3476 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
3478 error("unexpect end of file in initializer");
3479 tok_add2(&init_str
, &init_len
, tok
, tokc
);
3482 else if (tok
== '}') {
3490 tok_add(&init_str
, &init_len
, -1);
3491 tok_add(&init_str
, &init_len
, 0);
3494 saved_macro_ptr
= macro_ptr
;
3495 macro_ptr
= init_str
;
3497 decl_initializer(t
, 0, 1, 1);
3498 /* prepare second initializer parsing */
3499 macro_ptr
= init_str
;
3502 /* if still unknown size, error */
3503 size
= type_size(t
, &align
);
3505 error("unknown type size");
3507 if ((t
& VT_VALMASK
) == VT_LOCAL
) {
3508 loc
= (loc
- size
) & -align
;
3511 glo
= (glo
+ align
- 1) & -align
;
3513 /* very important to increment global
3514 pointer at this time because
3515 initializers themselves can create new
3520 decl_initializer(t
, addr
, 1, 0);
3521 /* restore parse state if needed */
3524 macro_ptr
= saved_macro_ptr
;
3532 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3535 int *a
, t
, b
, v
, u
, addr
, has_init
, size
, align
;
3541 /* skip redundant ';' */
3542 /* XXX: find more elegant solution */
3547 /* special test for old K&R protos without explicit int
3548 type. Only accepted when defining global data */
3549 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
3553 if ((b
& (VT_ENUM
| VT_STRUCT
)) && tok
== ';') {
3554 /* we accept no variable after */
3558 while (1) { /* iterate thru each declaration */
3559 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3562 error("cannot use local functions");
3564 expect("function definition");
3565 /* patch forward references */
3566 if ((sym
= sym_find(v
)) && (sym
->t
& VT_FORWARD
)) {
3567 greloc_patch(sym
, ind
);
3568 sym
->t
= VT_CONST
| t
;
3570 /* put function address */
3571 sym_push1(&global_stack
, v
, VT_CONST
| t
, ind
);
3573 funcname
= get_tok_str(v
, 0);
3574 /* push a dummy symbol to enable local sym storage */
3575 sym_push1(&local_stack
, 0, 0, 0);
3576 /* define parameters */
3577 sym
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3578 /* XXX: the following is x86 dependant -> move it to
3581 /* if the function returns a structure, then add an
3582 implicit pointer parameter */
3584 if (func_vt
& VT_STRUCT
) {
3588 while (sym
= sym
->next
) {
3590 sym_push(sym
->v
& ~SYM_FIELD
,
3591 u
| VT_LOCAL
| VT_LVAL
,
3593 if (u
& VT_STRUCT
) {
3594 #ifdef FUNC_STRUCT_PARAM_AS_PTR
3595 /* structs are passed as pointer */
3598 /* structs are directly put on stack (x86
3600 size
= type_size(u
, &align
);
3601 size
= (size
+ 3) & ~3;
3604 /* XXX: size will be different someday */
3610 o(0xe58955); /* push %ebp, mov %esp, %ebp */
3611 a
= (int *)oad(0xec81, 0); /* sub $xxx, %esp */
3613 block(0, 0, 0, 0, 0);
3615 o(0xc3c9); /* leave, ret */
3616 *a
= (-loc
+ 3) & -4; /* align local size to word &
3617 save local variables */
3618 sym_pop(&label_stack
, 0); /* reset label stack */
3619 sym_pop(&local_stack
, 0); /* reset local stack */
3620 funcname
= ""; /* for safety */
3621 func_vt
= VT_VOID
; /* for safety */
3624 if (b
& VT_TYPEDEF
) {
3625 /* save typedefed type */
3626 sym_push(v
, t
| VT_TYPEDEF
, 0);
3627 } else if (t
& VT_FUNC
) {
3628 /* external function definition */
3631 /* not lvalue if array */
3632 if (!(t
& VT_ARRAY
))
3634 if (b
& VT_EXTERN
) {
3635 /* external variable */
3642 has_init
= (tok
== '=');
3645 addr
= decl_initializer_alloc(u
, has_init
);
3646 sym_push(v
, u
, addr
);
3659 /* open a dynamic library so that its symbol are available for
3660 compiled programs */
3661 void open_dll(char *libname
)
3666 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
3667 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
3669 error((char *)dlerror());
3672 void reloc_external_syms(void)
3678 s
= global_stack
.top
;
3681 if (s
->t
& VT_FORWARD
) {
3682 /* if there is at least one relocation to do, then find it
3685 str
= get_tok_str(s
->v
, 0);
3686 addr
= (int)dlsym(NULL
, str
);
3688 error("unresolved external reference '%s'", str
);
3689 greloc_patch(s
, addr
);
3696 /* output a binary file (for testing) */
3697 void build_exe(char *filename
)
3700 f
= fopen(filename
, "w");
3701 fwrite((void *)prog
, 1, ind
- prog
, f
);
3705 int main(int argc
, char **argv
)
3709 char *p
, *r
, *outfile
;
3712 include_paths
[0] = "/usr/include";
3713 include_paths
[1] = "/usr/lib/tcc";
3714 include_paths
[2] = "/usr/local/lib/tcc";
3715 nb_include_paths
= 3;
3717 /* add all tokens */
3718 tok_ident
= TOK_IDENT
;
3719 p
= "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0auto\0inline\0restrict\0float\0double\0short\0struct\0union\0typedef\0default\0enum\0sizeof\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0undef\0error\0line\0__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0__func__\0main\0";
3723 tok_alloc(p
, r
- p
- 1);
3727 /* standard defines */
3728 define_symbol("__STDC__");
3730 define_symbol("__i386__");
3736 if (optind
>= argc
) {
3738 printf("tcc version 0.9.1 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
3739 "usage: tcc [-Idir] [-Dsym] [-llib] infile [infile_arg...]\n");
3747 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
3748 error("too many include paths");
3749 include_paths
[nb_include_paths
++] = r
+ 2;
3750 } else if (r
[1] == 'D') {
3751 define_symbol(r
+ 2);
3752 } else if (r
[1] == 'l') {
3754 } else if (r
[1] == 'o') {
3755 /* currently, only for testing, so not documented */
3758 outfile
= argv
[optind
++];
3760 fprintf(stderr
, "invalid option -- '%s'\n", r
);
3765 filename
= argv
[optind
];
3768 file
= fopen(filename
, "r");
3773 include_stack_ptr
= include_stack
;
3774 ifdef_stack_ptr
= ifdef_stack
;
3776 glo
= (int)malloc(DATA_SIZE
);
3777 memset((void *)glo
, 0, DATA_SIZE
);
3778 prog
= (int)malloc(TEXT_SIZE
);
3779 vstack_ptr
= vstack
;
3780 anon_sym
= 1 << (31 - VT_STRUCT_SHIFT
);
3783 ch
= '\n'; /* needed to parse correctly first preprocessor command */
3787 expect("declaration");
3788 reloc_external_syms();
3793 s
= sym_find(TOK_MAIN
);
3795 error("main() not defined");
3796 t
= (int (*)())s
->c
;
3800 return (*t
)(argc
- optind
, argv
+ optind
);