📄 tcc.c
字号:
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);}/* 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) sh_num = section->sh_num; else sh_num = SHN_UNDEF; 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) break; if (ts->len == len && !memcmp(ts->str, str, len)) return ts; pts = &(ts->hash_next); } return tok_alloc_new(pts, str, len);}/* CString handling */static void cstr_realloc(CString *cstr, int new_size){ int size; void *data; size = cstr->size_allocated; if (size == 0) size = 8; /* no need to allocate a too small first string */ while (size < new_size) size = size * 2; data = tcc_realloc(cstr->data_allocated, size); if (!data) error("memory full"); cstr->data_allocated = data; cstr->size_allocated = size; cstr->data = data;}/* add a byte */static void cstr_ccat(CString *cstr, int ch){ int size; size = cstr->size + 1; if (size > cstr->size_allocated) cstr_realloc(cstr, size); ((unsigned char *)cstr->data)[size - 1] = ch; cstr->size = size;}static void cstr_cat(CString *cstr, const char *str){ int c; for(;;) { c = *str; if (c == '\0') break; cstr_ccat(cstr, c); str++; }}/* add a wide char */static void cstr_wccat(CString *cstr, int ch){ int size; size = cstr->size + sizeof(int); if (size > cstr->size_allocated) cstr_realloc(cstr, size); *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch; cstr->size = size;}static void cstr_new(CString *cstr){ memset(cstr, 0, sizeof(CString));}/* free string and reset it to NULL */static void cstr_free(CString *cstr){ tcc_free(cstr->data_allocated); cstr_new(cstr);}#define cstr_reset(cstr) cstr_free(cstr)static CString *cstr_dup(CString *cstr1){ CString *cstr; int size; cstr = tcc_malloc(sizeof(CString)); size = cstr1->size; cstr->size = size; cstr->size_allocated = size; cstr->data_allocated = tcc_malloc(size); cstr->data = cstr->data_allocated; memcpy(cstr->data_allocated, cstr1->data_allocated, size); return cstr;}/* XXX: unicode ? */static void add_char(CString *cstr, int c){ if (c == '\'' || c == '\"' || c == '\\') { /* XXX: could be more precise if char or string */ cstr_ccat(cstr, '\\'); } if (c >= 32 && c <= 126) { cstr_ccat(cstr, c); } else { cstr_ccat(cstr, '\\'); if (c == '\n') { cstr_ccat(cstr, 'n'); } else { cstr_ccat(cstr, '0' + ((c >> 6) & 7)); cstr_ccat(cstr, '0' + ((c >> 3) & 7)); cstr_ccat(cstr, '0' + (c & 7)); } }}/* XXX: buffer overflow *//* XXX: float tokens */char *get_tok_str(int v, CValue *cv){ static char buf[STRING_MAX_SIZE + 1]; static CString cstr_buf; CString *cstr; unsigned char *q; char *p; int i, len; /* NOTE: to go faster, we give a fixed buffer for small strings */ cstr_reset(&cstr_buf); cstr_buf.data = buf; cstr_buf.size_allocated = sizeof(buf); p = buf; switch(v) { case TOK_CINT: case TOK_CUINT: /* XXX: not quite exact, but only useful for testing */ sprintf(p, "%u", cv->ui); break; case TOK_CLLONG: case TOK_CULLONG: /* XXX: not quite exact, but only useful for testing */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -