better type decl - added -l and -D options - added PROFILE defines

tcc-xref
bellard 2001-11-11 16:07:43 +00:00
parent b536ac3068
commit d261452977
1 changed files with 107 additions and 67 deletions

174
tcc.c
View File

@ -57,10 +57,14 @@ typedef struct Sym {
#define FUNC_OLD 2 /* old function prototype */
#define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
/* field t for macros */
/* field 'Sym.t' for macros */
#define MACRO_OBJ 0 /* object like macro */
#define MACRO_FUNC 1 /* function like macro */
/* type_decl() types */
#define TYPE_ABSTRACT 1 /* type without variable */
#define TYPE_DIRECT 2 /* type with variable */
typedef struct {
FILE *file;
char *filename;
@ -244,7 +248,25 @@ int type_size(int t, int *a);
int pointed_type(int t);
int pointed_size(int t);
int ist(void);
int typ(int *v, int t);
int type_decl(int *v, int t, int td);
#ifdef PROFILE
/* dummy function for profiling */
void *dlopen(const char *filename, int flag)
{
return (void *)1;
}
const char *dlerror(void)
{
return "error";
}
void *dlsym(void *handle, char *symbol)
{
return (void *)1;
}
#endif
int isid(c)
{
@ -262,38 +284,37 @@ void printline()
{
IncludeFile *f;
for(f = include_stack; f < include_stack_ptr; f++)
printf("In file included from %s:%d:\n", f->filename, f->line_num);
printf("%s:%d: ", filename, line_num);
fprintf(stderr, "In file included from %s:%d:\n",
f->filename, f->line_num);
fprintf(stderr, "%s:%d: ", filename, line_num);
}
/* XXX: use stderr ? */
void error(char *msg)
void error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
printline();
printf("%s\n", msg);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
exit(1);
va_end(ap);
}
void expect(char *msg)
void expect(const char *msg)
{
printline();
printf("%s expected\n", msg);
exit(1);
error("%s expected", msg);
}
void warning(char *msg)
void warning(const char *msg)
{
printline();
printf("warning: %s\n", msg);
fprintf(stderr, "warning: %s\n", msg);
}
void skip(c)
{
if (tok != c) {
printline();
printf("'%c' expected\n", c);
exit(1);
}
if (tok != c)
error("'%c' expected", c);
next();
}
@ -563,33 +584,6 @@ void preprocess_skip()
}
}
/* 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;
}
void tok_add(int **tok_str, int *tok_len, int t)
{
int len, *str;
@ -616,7 +610,6 @@ void tok_add2(int **tok_str, int *tok_len, int t, int c)
int expr_preprocess()
{
int *str, len, c, t;
int *saved_macro_ptr;
str = NULL;
len = 0;
@ -645,11 +638,10 @@ int expr_preprocess()
tok_add(&str, &len, -1); /* simulate end of file */
tok_add(&str, &len, 0);
/* now evaluate C constant expression */
saved_macro_ptr = macro_ptr;
macro_ptr = str;
next();
c = expr_const();
macro_ptr = saved_macro_ptr;
macro_ptr = NULL;
free(str);
return c != 0;
}
@ -672,6 +664,20 @@ void tok_print(int *str)
}
#endif
/* XXX: should be more factorized */
void define_symbol(char *sym)
{
TokenSym *ts;
int *str, len;
ts = tok_alloc(sym, strlen(sym));
str = NULL;
len = 0;
tok_add2(&str, &len, TOK_NUM, 1);
tok_add(&str, &len, 0);
sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
}
void preprocess()
{
int size, i, c, v, t, *str, len;
@ -687,8 +693,6 @@ void preprocess()
next_nomacro();
v = tok;
/* XXX: should check if same macro (ANSI) */
if (sym_find1(define_stack, v))
warning("macro redefinition");
first = NULL;
t = MACRO_OBJ;
/* '(' must be just after macro definition for MACRO_FUNC */
@ -1874,18 +1878,20 @@ int struct_decl(u)
if (s = sym_find(v | SYM_STRUCT)) {
if (s->t != a)
error("invalid type");
u = u | (v << VT_STRUCT_SHIFT);
return u;
goto do_decl;
}
} else {
v = anon_sym++;
}
s = sym_push(v | SYM_STRUCT, a, 0);
/* put struct/union/enum name in type */
do_decl:
u = u | (v << VT_STRUCT_SHIFT);
if (tok == '{') {
next();
if (s->c)
error("struct/union/enum already defined");
/* cannot be empty */
c = 0;
maxalign = 0;
@ -1905,7 +1911,7 @@ int struct_decl(u)
} else {
b = ist();
while (1) {
t = typ(&v, b);
t = type_decl(&v, b, TYPE_DIRECT);
if (t & (VT_FUNC | VT_TYPEDEF))
error("invalid type");
/* XXX: align & correct type size */
@ -1965,7 +1971,8 @@ int ist(void)
(tok >= TOK_CONST & tok <= TOK_INLINE)) {
/* ignored types */
} else if (tok == TOK_FLOAT || tok == TOK_DOUBLE) {
warning("floats not supported");
/* We allow that to compile standard headers */
// warning("floats not supported");
} else if (tok == TOK_EXTERN) {
t |= VT_EXTERN;
} else if (tok == TOK_STATIC) {
@ -1978,7 +1985,7 @@ int ist(void)
s = sym_find(tok);
if (!s || !(s->t & VT_TYPEDEF))
break;
t = s->t & ~VT_TYPEDEF;
t |= (s->t & ~VT_TYPEDEF);
}
next();
}
@ -2012,8 +2019,7 @@ int post_type(t)
if (pt & VT_VOID && tok == ')')
break;
l = FUNC_NEW;
pt = typ(&n, pt); /* XXX: should accept
both arg/non arg if v == 0 */
pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
} else {
old_proto:
n = tok;
@ -2067,7 +2073,7 @@ int post_type(t)
/* Read a type declaration (except basic type), and return the
type. If v is true, then also put variable name in 'vc' */
int typ(int *v, int t)
int type_decl(int *v, int t, int td)
{
int u, p;
Sym *s;
@ -2075,6 +2081,8 @@ int typ(int *v, int t)
t = t & -3; /* suppress the ored '2' */
while (tok == '*') {
next();
while (tok == TOK_CONST || tok == TOK_VOLATILE)
next();
t = mk_pointer(t);
}
@ -2082,14 +2090,18 @@ int typ(int *v, int t)
/* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
if (tok == '(') {
next();
u = typ(v, 0);
u = type_decl(v, 0, td);
skip(')');
} else {
u = 0;
/* type identifier */
if (v) {
if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
*v = tok;
next();
} else {
if (!(td & TYPE_ABSTRACT))
expect("identifier");
*v = 0;
}
}
/* append t at the end of u */
@ -2165,7 +2177,7 @@ void unary()
if (t == '(') {
/* cast ? */
if (t = ist()) {
ft = typ(0, t);
ft = type_decl(&n, t, TYPE_ABSTRACT);
skip(')');
unary();
vt = (vt & VT_TYPEN) | ft;
@ -2204,7 +2216,7 @@ void unary()
if (tok == '(') {
next();
if (t = ist())
vt = typ(0, t);
vt = type_decl(&n, t, TYPE_ABSTRACT);
else
expr();
skip(')');
@ -2699,7 +2711,7 @@ void decl(l)
continue;
}
while (1) { /* iterate thru each declaration */
t = typ(&v, b);
t = type_decl(&v, b, TYPE_DIRECT);
if (tok == '{') {
if (!(t & VT_FUNC))
expect("function defintion");
@ -2743,7 +2755,7 @@ void decl(l)
/* not lvalue if array */
if (!(t & VT_ARRAY))
t |= VT_LVAL;
if (t & VT_EXTERN) {
if (b & VT_EXTERN) {
/* external variable */
/* XXX: factorize with external function def */
n = (int)dlsym(NULL, get_tok_str(v, 0));
@ -2780,6 +2792,19 @@ void decl(l)
}
}
/* open a dynamic library so that its symbol are available for
compiled programs */
void open_dll(char *libname)
{
char buf[1024];
void *h;
snprintf(buf, sizeof(buf), "lib%s.so", libname);
h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
if (!h)
error((char *)dlerror());
}
int main(int argc, char **argv)
{
Sym *s;
@ -2801,10 +2826,16 @@ int main(int argc, char **argv)
p = r;
}
/* standard defines */
define_symbol("__STDC__");
#ifdef __i386__
define_symbol("__i386__");
#endif
optind = 1;
while (1) {
if (optind >= argc) {
printf("usage: tcc [-Idir] infile [infile_arg...]\n");
printf("usage: tcc [-Idir] [-Dsym] [-llib] infile [infile_arg...]\n");
return 1;
}
r = argv[optind];
@ -2814,8 +2845,13 @@ int main(int argc, char **argv)
if (nb_include_paths >= INCLUDE_PATHS_MAX)
error("too many include paths");
include_paths[nb_include_paths++] = r + 2;
} else if (r[1] == 'D') {
define_symbol(r + 2);
} else if (r[1] == 'l') {
open_dll(r + 2);
} else {
error("invalid option");
fprintf(stderr, "invalid option -- '%s'\n", r);
exit(1);
}
optind++;
}
@ -2845,7 +2881,7 @@ int main(int argc, char **argv)
#ifdef TEST
{
FILE *f;
f = fopen(v[1], "w");
f = fopen(argv[optind + 1], "w");
fwrite((void *)prog, 1, ind - prog, f);
fclose(f);
return 0;
@ -2855,6 +2891,10 @@ int main(int argc, char **argv)
if (!s)
error("main() not defined");
t = s->c;
#ifdef PROFILE
return 1;
#else
return (*t)(argc - optind, argv + optind);
#endif
#endif
}