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