📄 tcc.c
字号:
q++; } if (ptr) *ptr = p; return 1;}/* memory management */#ifdef MEM_DEBUGint mem_cur_size;int mem_max_size;#endifstatic inline void tcc_free(void *ptr){#ifdef MEM_DEBUG mem_cur_size -= malloc_usable_size(ptr);#endif free(ptr);}static void *tcc_malloc(unsigned long size){ void *ptr; ptr = malloc(size); if (!ptr && size) error("memory full");#ifdef MEM_DEBUG mem_cur_size += malloc_usable_size(ptr); if (mem_cur_size > mem_max_size) mem_max_size = mem_cur_size;#endif return ptr;}static void *tcc_mallocz(unsigned long size){ void *ptr; ptr = tcc_malloc(size); memset(ptr, 0, size); return ptr;}static inline void *tcc_realloc(void *ptr, unsigned long size){ void *ptr1;#ifdef MEM_DEBUG mem_cur_size -= malloc_usable_size(ptr);#endif ptr1 = realloc(ptr, size);#ifdef MEM_DEBUG /* NOTE: count not correct if alloc error, but not critical */ mem_cur_size += malloc_usable_size(ptr1); if (mem_cur_size > mem_max_size) mem_max_size = mem_cur_size;#endif return ptr1;}static char *tcc_strdup(const char *str){ char *ptr; ptr = tcc_malloc(strlen(str) + 1); strcpy(ptr, str); return ptr;}#define free(p) use_tcc_free(p)#define malloc(s) use_tcc_malloc(s)#define realloc(p, s) use_tcc_realloc(p, s)static void dynarray_add(void ***ptab, int *nb_ptr, void *data){ int nb, nb_alloc; void **pp; nb = *nb_ptr; pp = *ptab; /* every power of two we double array size */ if ((nb & (nb - 1)) == 0) { if (!nb) nb_alloc = 1; else nb_alloc = nb * 2; pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); if (!pp) error("memory full"); *ptab = pp; } pp[nb++] = data; *nb_ptr = nb;}/* symbol allocator */static Sym *__sym_malloc(void){ Sym *sym_pool, *sym, *last_sym; int i; sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym)); last_sym = sym_free_first; sym = sym_pool; for(i = 0; i < SYM_POOL_NB; i++) { sym->next = last_sym; last_sym = sym; sym++; } sym_free_first = last_sym; return last_sym;}static inline Sym *sym_malloc(void){ Sym *sym; sym = sym_free_first; if (!sym) sym = __sym_malloc(); sym_free_first = sym->next; return sym;}static inline void sym_free(Sym *sym){ sym->next = sym_free_first; sym_free_first = sym;}Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags){ Section *sec; sec = tcc_mallocz(sizeof(Section) + strlen(name)); strcpy(sec->name, name); sec->sh_type = sh_type; sec->sh_flags = sh_flags; switch(sh_type) { case SHT_HASH: case SHT_REL: case SHT_DYNSYM: case SHT_SYMTAB: case SHT_DYNAMIC: sec->sh_addralign = 4; break; case SHT_STRTAB: sec->sh_addralign = 1; break; default: sec->sh_addralign = 32; /* default conservative alignment */ break; } /* only add section if not private */ if (!(sh_flags & SHF_PRIVATE)) { sec->sh_num = s1->nb_sections; dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec); } return sec;}static void free_section(Section *s){ tcc_free(s->data); tcc_free(s);}/* realloc section and set its content to zero */static void section_realloc(Section *sec, unsigned long new_size){ unsigned long size; unsigned char *data; size = sec->data_allocated; if (size == 0) size = 1; while (size < new_size) size = size * 2; data = tcc_realloc(sec->data, size); if (!data) error("memory full"); memset(data + sec->data_allocated, 0, size - sec->data_allocated); sec->data = data; sec->data_allocated = size;}/* reserve at least 'size' bytes in section 'sec' from sec->data_offset. */static void *section_ptr_add(Section *sec, unsigned long size){ unsigned long offset, offset1; offset = sec->data_offset; offset1 = offset + size; if (offset1 > sec->data_allocated) section_realloc(sec, offset1); sec->data_offset = offset1; return sec->data + offset;}/* return a reference to a section, and create it if it does not exists */Section *find_section(TCCState *s1, const char *name){ Section *sec; int i; for(i = 1; i < s1->nb_sections; i++) { sec = s1->sections[i]; if (!strcmp(name, sec->name)) return sec; } /* sections are created as PROGBITS */ return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);}#define SECTION_ABS ((void *)1)/* update sym->c so that it points to an external symbol in section 'section' with value 'value' */static void put_extern_sym(Sym *sym, Section *section, unsigned long value, unsigned long size){ int sym_type, sym_bind, sh_num, info; Elf32_Sym *esym; const char *name; if (section == NULL) sh_num = SHN_UNDEF; else if (section == SECTION_ABS) sh_num = SHN_ABS; else sh_num = section->sh_num; if (!sym->c) { if ((sym->type.t & VT_BTYPE) == VT_FUNC) sym_type = STT_FUNC; else sym_type = STT_OBJECT; if (sym->type.t & VT_STATIC) sym_bind = STB_LOCAL; else sym_bind = STB_GLOBAL; name = get_tok_str(sym->v, NULL);#ifdef CONFIG_TCC_BCHECK if (do_bounds_check) { char buf[32]; /* XXX: avoid doing that for statics ? */ /* if bound checking is activated, we change some function names by adding the "__bound" prefix */ switch(sym->v) {#if 0 /* XXX: we rely only on malloc hooks */ case TOK_malloc: case TOK_free: case TOK_realloc: case TOK_memalign: case TOK_calloc: #endif case TOK_memcpy: case TOK_memmove: case TOK_memset: case TOK_strlen: case TOK_strcpy: strcpy(buf, "__bound_"); strcat(buf, name); name = buf; break; } }#endif info = ELF32_ST_INFO(sym_bind, sym_type); sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name); } else { esym = &((Elf32_Sym *)symtab_section->data)[sym->c]; esym->st_value = value; esym->st_size = size; esym->st_shndx = sh_num; }}/* add a new relocation entry to symbol 'sym' in section 's' */static void greloc(Section *s, Sym *sym, unsigned long offset, int type){ if (!sym->c) put_extern_sym(sym, NULL, 0, 0); /* now we can add ELF relocation info */ put_elf_reloc(symtab_section, s, offset, type, sym->c);}static inline int isid(int c){ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';}static inline int isnum(int c){ return c >= '0' && c <= '9';}static inline int isoct(int c){ return c >= '0' && c <= '7';}static inline int toup(int c){ if (c >= 'a' && c <= 'z') return c - 'a' + 'A'; else return c;}static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap){ int len; len = strlen(buf); vsnprintf(buf + len, buf_size - len, fmt, ap);}static void strcat_printf(char *buf, int buf_size, const char *fmt, ...){ va_list ap; va_start(ap, fmt); strcat_vprintf(buf, buf_size, fmt, ap); va_end(ap);}void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap){ char buf[2048]; BufferedFile **f; buf[0] = '\0'; if (file) { for(f = s1->include_stack; f < s1->include_stack_ptr; f++) strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", (*f)->filename, (*f)->line_num); if (file->line_num > 0) { strcat_printf(buf, sizeof(buf), "%s:%d: ", file->filename, file->line_num); } else { strcat_printf(buf, sizeof(buf), "%s: ", file->filename); } } else { strcat_printf(buf, sizeof(buf), "tcc: "); } if (is_warning) strcat_printf(buf, sizeof(buf), "warning: "); strcat_vprintf(buf, sizeof(buf), fmt, ap); if (!s1->error_func) { /* default case: stderr */ fprintf(stderr, "%s\n", buf); } else { s1->error_func(s1->error_opaque, buf); } if (!is_warning || s1->warn_error) s1->nb_errors++;}#ifdef LIBTCCvoid tcc_set_error_func(TCCState *s, void *error_opaque, void (*error_func)(void *opaque, const char *msg)){ s->error_opaque = error_opaque; s->error_func = error_func;}#endif/* error without aborting current compilation */void error_noabort(const char *fmt, ...){ TCCState *s1 = tcc_state; va_list ap; va_start(ap, fmt); error1(s1, 0, fmt, ap); va_end(ap);}void error(const char *fmt, ...){ TCCState *s1 = tcc_state; va_list ap; va_start(ap, fmt); error1(s1, 0, fmt, ap); va_end(ap); /* better than nothing: in some cases, we accept to handle errors */ if (s1->error_set_jmp_enabled) { longjmp(s1->error_jmp_buf, 1); } else { /* XXX: eliminate this someday */ exit(1); }}void expect(const char *msg){ error("%s expected", msg);}void warning(const char *fmt, ...){ TCCState *s1 = tcc_state; va_list ap; if (s1->warn_none) return; va_start(ap, fmt); error1(s1, 1, fmt, ap); va_end(ap);}void skip(int c){ if (tok != c) error("'%c' expected", c); next();}static void test_lvalue(void){ if (!(vtop->r & VT_LVAL)) expect("lvalue");}/* allocate a new token */static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len){ TokenSym *ts, **ptable; int i; if (tok_ident >= SYM_FIRST_ANOM) error("memory full"); /* expand token table if needed */ i = tok_ident - TOK_IDENT; if ((i % TOK_ALLOC_INCR) == 0) { ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *)); if (!ptable) error("memory full"); table_ident = ptable; } ts = tcc_malloc(sizeof(TokenSym) + len); table_ident[i] = ts; ts->tok = tok_ident++; ts->sym_define = NULL; ts->sym_label = NULL; ts->sym_struct = NULL; ts->sym_identifier = NULL; ts->len = len; ts->hash_next = NULL; memcpy(ts->str, str, len); ts->str[len] = '\0'; *pts = ts; return ts;}#define TOK_HASH_INIT 1#define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))/* find a token and add it if not found */static TokenSym *tok_alloc(const char *str, int len){ TokenSym *ts, **pts; int i; unsigned int h; h = TOK_HASH_INIT; for(i=0;i<len;i++) h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]); h &= (TOK_HASH_SIZE - 1); pts = &hash_ident[h]; for(;;) { ts = *pts; if (!ts)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -