⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcc.c

📁 小而快的c编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  TCC - Tiny C Compiler *  *  Copyright (c) 2001, 2002, 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#define _GNU_SOURCE#include "config.h"#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <string.h>#include <errno.h>#include <math.h>#include <unistd.h>#include <signal.h>#include <unistd.h>#include <fcntl.h>#include <setjmp.h>#include <time.h>#ifdef WIN32#include <sys/timeb.h>#endif#ifndef WIN32#include <sys/time.h>#include <sys/ucontext.h>#endif#include "elf.h"#include "stab.h"#ifndef CONFIG_TCC_STATIC#include <dlfcn.h>#endif#include "libtcc.h"/* parser debug *///#define PARSE_DEBUG/* preprocessor debug *///#define PP_DEBUG/* include file debug *///#define INC_DEBUG//#define MEM_DEBUG/* assembler debug *///#define ASM_DEBUG/* target selection *///#define TCC_TARGET_I386   /* i386 code generator *//* default target is I386 */#if !defined(TCC_TARGET_I386)#define TCC_TARGET_I386#endif#if !defined(WIN32) && !defined(TCC_UCLIBC)#define CONFIG_TCC_BCHECK /* enable bound checking code */#endif/* define it to include assembler support */#define CONFIG_TCC_ASM/* path to find crt1.o, crti.o and crtn.o. Only needed when generating   executables or dlls */#define CONFIG_TCC_CRT_PREFIX "/usr/lib"#define INCLUDE_STACK_SIZE  32#define IFDEF_STACK_SIZE    64#define VSTACK_SIZE         64#define STRING_MAX_SIZE     1024#define TOK_HASH_SIZE       2048 /* must be a power of two */#define TOK_ALLOC_INCR      512  /* must be a power of two */#define TOK_STR_ALLOC_INCR_BITS 6#define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)#define TOK_MAX_SIZE        4 /* token max size in int unit when stored in string *//* token symbol management */typedef struct TokenSym {    struct TokenSym *hash_next;    struct Sym *sym_define; /* direct pointer to define */    struct Sym *sym_label; /* direct pointer to label */    struct Sym *sym_struct; /* direct pointer to structure */    struct Sym *sym_identifier; /* direct pointer to identifier */    int tok; /* token number */    int len;    char str[1];} TokenSym;typedef struct CString {    int size; /* size in bytes */    void *data; /* either 'char *' or 'int *' */    int size_allocated;    void *data_allocated; /* if non NULL, data has been malloced */} CString;/* type definition */typedef struct CType {    int t;    struct Sym *ref;} CType;/* constant value */typedef union CValue {    long double ld;    double d;    float f;    int i;    unsigned int ui;    unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */    long long ll;    unsigned long long ull;    struct CString *cstr;    void *ptr;    int tab[1];} CValue;/* value on stack */typedef struct SValue {    CType type;      /* type */    unsigned short r;      /* register + flags */    unsigned short r2;     /* second register, used for 'long long'                              type. If not used, set to VT_CONST */    CValue c;              /* constant, if VT_CONST */    struct Sym *sym;       /* symbol, if (VT_SYM | VT_CONST) */} SValue;/* symbol management */typedef struct Sym {    int v;    /* symbol token */    int r;    /* associated register */    int c;    /* associated number */    CType type;    /* associated type */    struct Sym *next; /* next related symbol */    struct Sym *prev; /* prev symbol in stack */    struct Sym *prev_tok; /* previous symbol for this token */} Sym;/* section definition *//* XXX: use directly ELF structure for parameters ? *//* special flag to indicate that the section should not be linked to   the other ones */#define SHF_PRIVATE 0x80000000typedef struct Section {    unsigned long data_offset; /* current data offset */    unsigned char *data;       /* section data */    unsigned long data_allocated; /* used for realloc() handling */    int sh_name;             /* elf section name (only used during output) */    int sh_num;              /* elf section number */    int sh_type;             /* elf section type */    int sh_flags;            /* elf section flags */    int sh_info;             /* elf section info */    int sh_addralign;        /* elf section alignment */    int sh_entsize;          /* elf entry size */    unsigned long sh_size;   /* section size (only used during output) */    unsigned long sh_addr;      /* address at which the section is relocated */    unsigned long sh_offset;      /* address at which the section is relocated */    int nb_hashed_syms;      /* used to resize the hash table */    struct Section *link;    /* link to another section */    struct Section *reloc;   /* corresponding section for relocation, if any */    struct Section *hash;     /* hash table for symbols */    struct Section *next;    char name[1];           /* section name */} Section;typedef struct DLLReference {    int level;    char name[1];} DLLReference;/* GNUC attribute definition */typedef struct AttributeDef {    int aligned;    Section *section;    unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */} AttributeDef;#define SYM_STRUCT     0x40000000 /* struct/union/enum symbol space */#define SYM_FIELD      0x20000000 /* struct/union field symbol space */#define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym *//* stored in 'Sym.c' field */#define FUNC_NEW       1 /* ansi function prototype */#define FUNC_OLD       2 /* old function prototype */#define FUNC_ELLIPSIS  3 /* ansi function prototype with ... *//* stored in 'Sym.r' field */#define FUNC_CDECL     0 /* standard c call */#define FUNC_STDCALL   1 /* pascal c call *//* field 'Sym.t' for macros */#define MACRO_OBJ      0 /* object like macro */#define MACRO_FUNC     1 /* function like macro *//* field 'Sym.r' for C labels */#define LABEL_DEFINED  0 /* label is defined */#define LABEL_FORWARD  1 /* label is forward defined */#define LABEL_DECLARED 2 /* label is declared but never used *//* type_decl() types */#define TYPE_ABSTRACT  1 /* type without variable */#define TYPE_DIRECT    2 /* type with variable */#define IO_BUF_SIZE 8192typedef struct BufferedFile {    uint8_t *buf_ptr;    uint8_t *buf_end;    int fd;    int line_num;    /* current line number - here to simplify code */    int ifndef_macro;  /* #ifndef macro / #endif search */    int ifndef_macro_saved; /* saved ifndef_macro */    int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */    char inc_type;          /* type of include */    char inc_filename[512]; /* filename specified by the user */    char filename[1024];    /* current filename - here to simplify code */    unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */} BufferedFile;#define CH_EOB   '\\'       /* end of buffer or '\0' char in file */#define CH_EOF   (-1)   /* end of file *//* parsing state (used to save parser state to reparse part of the   source several times) */typedef struct ParseState {    int *macro_ptr;    int line_num;    int tok;    CValue tokc;} ParseState;/* used to record tokens */typedef struct TokenString {    int *str;    int len;    int allocated_len;    int last_line_num;} TokenString;/* include file cache, used to find files faster and also to eliminate   inclusion if the include file is protected by #ifndef ... #endif */typedef struct CachedInclude {    int ifndef_macro;    char type; /* '"' or '>' to give include type */    char filename[1]; /* path specified in #include */} CachedInclude;/* parser */static struct BufferedFile *file;static int ch, tok;static CValue tokc;static CString tokcstr; /* current parsed string, if any *//* additional informations about token */static int tok_flags;#define TOK_FLAG_BOL   0x0001 /* beginning of line before */#define TOK_FLAG_BOF   0x0002 /* beginning of file before */#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */static int *macro_ptr, *macro_ptr_allocated;static int *unget_saved_macro_ptr;static int unget_saved_buffer[TOK_MAX_SIZE + 1];static int unget_buffer_enabled;static int parse_flags;#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */#define PARSE_FLAG_TOK_NUM    0x0002 /* return numbers instead of TOK_PPNUM */#define PARSE_FLAG_LINEFEED   0x0004 /* line feed is returned as a                                        token. line feed is also                                        returned at eof */ static Section *text_section, *data_section, *bss_section; /* predefined sections */static Section *cur_text_section; /* current section where function code is                              generated *//* bound check related sections */static Section *bounds_section; /* contains global data bound description */static Section *lbounds_section; /* contains local data bound description *//* symbol sections */static Section *symtab_section, *strtab_section;/* debug sections */static Section *stab_section, *stabstr_section;/* loc : local variable index   ind : output code index   rsym: return symbol   anon_sym: anonymous symbol index*/static int rsym, anon_sym, ind, loc;/* expression generation modifiers */static int const_wanted; /* true if constant wanted */static int nocode_wanted; /* true if no code generation wanted for an expression */static int global_expr;  /* true if compound literals must be allocated                            globally (used during initializers parsing */static CType func_vt; /* current function return type (used by return                         instruction) */static int func_vc;static int last_line_num, last_ind, func_ind; /* debug last line number and pc */static int tok_ident;static TokenSym **table_ident;static TokenSym *hash_ident[TOK_HASH_SIZE];static char token_buf[STRING_MAX_SIZE + 1];static char *funcname;static Sym *global_stack, *local_stack;static Sym *define_stack;static Sym *global_label_stack, *local_label_stack;static SValue vstack[VSTACK_SIZE], *vtop;/* some predefined types */static CType char_pointer_type, func_old_type, int_type;/* true if isid(c) || isnum(c) */static unsigned char isidnum_table[256];/* compile with debug symbol (and use them if error during execution) */static int do_debug = 0;/* compile with built-in memory and bounds checker */static int do_bounds_check = 0;/* display benchmark infos */#if !defined(LIBTCC)static int do_bench = 0;#endifstatic int total_lines;static int total_bytes;/* use GNU C extensions */static int gnu_ext = 1;/* use Tiny C extensions */static int tcc_ext = 1;/* max number of callers shown if error */static int num_callers = 6;static const char **rt_bound_error_msg;/* XXX: get rid of this ASAP */static struct TCCState *tcc_state;/* give the path of the tcc libraries */static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";struct TCCState {    int output_type;     BufferedFile **include_stack_ptr;    int *ifdef_stack_ptr;    /* include file handling */    char **include_paths;    int nb_include_paths;    char **sysinclude_paths;    int nb_sysinclude_paths;    CachedInclude **cached_includes;    int nb_cached_includes;    char **library_paths;    int nb_library_paths;    /* array of all loaded dlls (including those referenced by loaded       dlls) */    DLLReference **loaded_dlls;    int nb_loaded_dlls;    /* sections */    Section **sections;    int nb_sections; /* number of sections, including first dummy section */    /* got handling */    Section *got;    Section *plt;    unsigned long *got_offsets;    int nb_got_offsets;    /* give the correspondance from symtab indexes to dynsym indexes */    int *symtab_to_dynsym;    /* temporary dynamic symbol sections (for dll loading) */    Section *dynsymtab_section;    /* exported dynamic symbol section */    Section *dynsym;    int nostdinc; /* if true, no standard headers are added */    int nostdlib; /* if true, no standard libraries are added */    /* if true, static linking is performed */    int static_link;    /* if true, all symbols are exported */    int rdynamic;    /* if true, only link in referenced objects from archive */    int alacarte_link;    /* warning switches */    int warn_write_strings;    int warn_unsupported;    int warn_error;    int warn_none;    /* error handling */    void *error_opaque;    void (*error_func)(void *opaque, const char *msg);    int error_set_jmp_enabled;    jmp_buf error_jmp_buf;    int nb_errors;    /* tiny assembler state */    Sym *asm_labels;    /* see include_stack_ptr */    BufferedFile *include_stack[INCLUDE_STACK_SIZE];    /* see ifdef_stack_ptr */    int ifdef_stack[IFDEF_STACK_SIZE];};/* The current value can be: */#define VT_VALMASK   0x00ff#define VT_CONST     0x00f0  /* constant in vc                               (must be first non register value) */#define VT_LLOCAL    0x00f1  /* lvalue, offset on stack */#define VT_LOCAL     0x00f2  /* offset on stack */#define VT_CMP       0x00f3  /* the value is stored in processor flags (in vc) */#define VT_JMP       0x00f4  /* value is the consequence of jmp true (even) */#define VT_JMPI      0x00f5  /* value is the consequence of jmp false (odd) */#define VT_LVAL      0x0100  /* var is an lvalue */#define VT_SYM       0x0200  /* a symbol value is added */#define VT_MUSTCAST  0x0400  /* value must be casted to be correct (used for                                char/short stored in integer registers) */#define VT_MUSTBOUND 0x0800  /* bound checking must be done before                                dereferencing value */#define VT_BOUNDED   0x8000  /* value is bounded. The address of the                                bounding function call point is in vc */#define VT_LVAL_BYTE     0x1000  /* lvalue is a byte */#define VT_LVAL_SHORT    0x2000  /* lvalue is a short */#define VT_LVAL_UNSIGNED 0x4000  /* lvalue is unsigned */#define VT_LVAL_TYPE     (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)/* types */#define VT_INT        0  /* integer type */#define VT_BYTE       1  /* signed byte type */#define VT_SHORT      2  /* short type */#define VT_VOID       3  /* void type */#define VT_PTR        4  /* pointer */#define VT_ENUM       5  /* enum definition */#define VT_FUNC       6  /* function type */#define VT_STRUCT     7  /* struct/union definition */#define VT_FLOAT      8  /* IEEE float */#define VT_DOUBLE     9  /* IEEE double */#define VT_LDOUBLE   10  /* IEEE long double */#define VT_BOOL      11  /* ISOC99 boolean type */#define VT_LLONG     12  /* 64 bit integer */#define VT_LONG      13  /* long integer (NEVER USED as type, only                            during parsing) */#define VT_BTYPE      0x000f /* mask for basic type */#define VT_UNSIGNED   0x0010  /* unsigned type */#define VT_ARRAY      0x0020  /* array type (also has VT_PTR) */#define VT_BITFIELD   0x0040  /* bitfield modifier */#define VT_CONSTANT   0x0800  /* const modifier */#define VT_VOLATILE   0x1000  /* volatile modifier *//* storage */#define VT_EXTERN  0x00000080  /* extern definition */#define VT_STATIC  0x00000100  /* static variable */#define VT_TYPEDEF 0x00000200  /* typedef definition */#define VT_INLINE  0x00000400  /* inline definition */#define VT_STRUCT_SHIFT 16   /* shift for bitfield shift values *//* type mask (except storage) */#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -