Changeset 331 for EcnlProtoTool/trunk/tcc-0.9.27/libtcc.c
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/tcc-0.9.27
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/tcc-0.9.27/libtcc.c
r321 r331 1 1 /* 2 2 * TCC - Tiny C Compiler 3 * 3 * 4 4 * Copyright (c) 2001-2004 Fabrice Bellard 5 5 * … … 33 33 ST_DATA struct TCCState *tcc_state; 34 34 35 static int nb_states; 36 35 37 /********************************************************/ 36 38 37 #if defONE_SOURCE39 #if ONE_SOURCE 38 40 #include "tccpp.c" 39 41 #include "tccgen.c" … … 42 44 #ifdef TCC_TARGET_I386 43 45 #include "i386-gen.c" 46 #include "i386-link.c" 47 #include "i386-asm.c" 44 48 #endif 45 49 #ifdef TCC_TARGET_ARM 46 50 #include "arm-gen.c" 51 #include "arm-link.c" 52 #include "arm-asm.c" 53 #endif 54 #ifdef TCC_TARGET_ARM64 55 #include "arm64-gen.c" 56 #include "arm64-link.c" 47 57 #endif 48 58 #ifdef TCC_TARGET_C67 49 59 #include "c67-gen.c" 60 #include "c67-link.c" 61 #include "tcccoff.c" 50 62 #endif 51 63 #ifdef TCC_TARGET_X86_64 52 64 #include "x86_64-gen.c" 53 #endif 54 #ifdef TCC_TARGET_IL 55 #include "il-gen.c" 65 #include "x86_64-link.c" 66 #include "i386-asm.c" 56 67 #endif 57 68 #ifdef CONFIG_TCC_ASM 58 69 #include "tccasm.c" 59 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_6460 #include "i386-asm.c"61 #endif62 #endif63 #ifdef TCC_TARGET_COFF64 #include "tcccoff.c"65 70 #endif 66 71 #ifdef TCC_TARGET_PE … … 82 87 83 88 /********************************************************/ 84 85 89 #ifdef _WIN32 86 char *normalize_slashes(char *path)90 ST_FUNC char *normalize_slashes(char *path) 87 91 { 88 92 char *p; … … 93 97 } 94 98 95 #if 096 99 static HMODULE tcc_module; 97 100 … … 102 105 GetModuleFileNameA(tcc_module, path, sizeof path); 103 106 p = tcc_basename(normalize_slashes(strlwr(path))); 104 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5)) 105 p -= 5; 106 else if (p > path) 107 p--; 107 if (p > path) 108 --p; 108 109 *p = 0; 109 110 tcc_set_lib_path(s, path); … … 119 120 #endif 120 121 121 #ifndef CONFIG_TCC_STATIC122 void dlclose(void *p)123 {124 FreeLibrary((HMODULE)p);125 }126 #endif127 #else128 extern void tcc_set_lib_path_w32(TCCState *s);129 extern void dlclose(void *p);130 #endif131 132 122 #ifdef LIBTCC_AS_DLL 133 BOOL WINAPI DllMain (H ANDLE hDll, DWORD dwReason, LPVOID lpReserved)123 BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) 134 124 { 135 125 if (DLL_PROCESS_ATTACH == dwReason) … … 142 132 /********************************************************/ 143 133 /* copy a string and truncate it. */ 144 PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s)134 ST_FUNC char *pstrcpy(char *buf, int buf_size, const char *s) 145 135 { 146 136 char *q, *q_end; … … 162 152 163 153 /* strcat and truncate. */ 164 PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s)154 ST_FUNC char *pstrcat(char *buf, int buf_size, const char *s) 165 155 { 166 156 int len; 167 157 len = strlen(buf); 168 if (len < buf_size) 158 if (len < buf_size) 169 159 pstrcpy(buf + len, buf_size - len, s); 170 160 return buf; 171 161 } 172 162 173 PUB_FUNC char *pstrncpy(char *out, const char *in, size_t num)163 ST_FUNC char *pstrncpy(char *out, const char *in, size_t num) 174 164 { 175 165 memcpy(out, in, num); … … 205 195 #undef realloc 206 196 207 #ifdef MEM_DEBUG 208 ST_DATA int mem_cur_size; 209 ST_DATA int mem_max_size; 210 unsigned malloc_usable_size(void*); 211 #endif 197 #ifndef MEM_DEBUG 212 198 213 199 PUB_FUNC void tcc_free(void *ptr) 214 200 { 215 #ifdef MEM_DEBUG 216 mem_cur_size -= malloc_usable_size(ptr); 217 #endif 218 free(ptr); 201 free(ptr); 219 202 } 220 203 … … 224 207 ptr = malloc(size); 225 208 if (!ptr && size) 226 tcc_error("memory full"); 227 #ifdef MEM_DEBUG 228 mem_cur_size += malloc_usable_size(ptr); 229 if (mem_cur_size > mem_max_size) 230 mem_max_size = mem_cur_size; 231 #endif 209 tcc_error("memory full (malloc)"); 232 210 return ptr; 233 211 } … … 244 222 { 245 223 void *ptr1; 246 #ifdef MEM_DEBUG247 mem_cur_size -= malloc_usable_size(ptr);248 #endif249 224 ptr1 = realloc(ptr, size); 250 225 if (!ptr1 && size) 251 tcc_error("memory full"); 252 #ifdef MEM_DEBUG 253 /* NOTE: count not correct if alloc error, but not critical */ 254 mem_cur_size += malloc_usable_size(ptr1); 255 if (mem_cur_size > mem_max_size) 256 mem_max_size = mem_cur_size; 257 #endif 226 tcc_error("memory full (realloc)"); 258 227 return ptr1; 259 228 } … … 267 236 } 268 237 269 PUB_FUNC void tcc_memstats(void) 270 { 271 #ifdef MEM_DEBUG 272 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size); 273 #endif 274 } 238 PUB_FUNC void tcc_memcheck(void) 239 { 240 } 241 242 #else 243 244 #define MEM_DEBUG_MAGIC1 0xFEEDDEB1 245 #define MEM_DEBUG_MAGIC2 0xFEEDDEB2 246 #define MEM_DEBUG_MAGIC3 0xFEEDDEB3 247 #define MEM_DEBUG_FILE_LEN 40 248 #define MEM_DEBUG_CHECK3(header) \ 249 ((mem_debug_header_t*)((char*)header + header->size))->magic3 250 #define MEM_USER_PTR(header) \ 251 ((char *)header + offsetof(mem_debug_header_t, magic3)) 252 #define MEM_HEADER_PTR(ptr) \ 253 (mem_debug_header_t *)((char*)ptr - offsetof(mem_debug_header_t, magic3)) 254 255 struct mem_debug_header { 256 unsigned magic1; 257 unsigned size; 258 struct mem_debug_header *prev; 259 struct mem_debug_header *next; 260 int line_num; 261 char file_name[MEM_DEBUG_FILE_LEN + 1]; 262 unsigned magic2; 263 ALIGNED(16) unsigned magic3; 264 }; 265 266 typedef struct mem_debug_header mem_debug_header_t; 267 268 static mem_debug_header_t *mem_debug_chain; 269 static unsigned mem_cur_size; 270 static unsigned mem_max_size; 271 272 static mem_debug_header_t *malloc_check(void *ptr, const char *msg) 273 { 274 mem_debug_header_t * header = MEM_HEADER_PTR(ptr); 275 if (header->magic1 != MEM_DEBUG_MAGIC1 || 276 header->magic2 != MEM_DEBUG_MAGIC2 || 277 MEM_DEBUG_CHECK3(header) != MEM_DEBUG_MAGIC3 || 278 header->size == (unsigned)-1) { 279 fprintf(stderr, "%s check failed\n", msg); 280 if (header->magic1 == MEM_DEBUG_MAGIC1) 281 fprintf(stderr, "%s:%u: block allocated here.\n", 282 header->file_name, header->line_num); 283 exit(1); 284 } 285 return header; 286 } 287 288 PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) 289 { 290 int ofs; 291 mem_debug_header_t *header; 292 293 header = malloc(sizeof(mem_debug_header_t) + size); 294 if (!header) 295 tcc_error("memory full (malloc)"); 296 297 header->magic1 = MEM_DEBUG_MAGIC1; 298 header->magic2 = MEM_DEBUG_MAGIC2; 299 header->size = size; 300 MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3; 301 header->line_num = line; 302 ofs = strlen(file) - MEM_DEBUG_FILE_LEN; 303 strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN); 304 header->file_name[MEM_DEBUG_FILE_LEN] = 0; 305 306 header->next = mem_debug_chain; 307 header->prev = NULL; 308 if (header->next) 309 header->next->prev = header; 310 mem_debug_chain = header; 311 312 mem_cur_size += size; 313 if (mem_cur_size > mem_max_size) 314 mem_max_size = mem_cur_size; 315 316 return MEM_USER_PTR(header); 317 } 318 319 PUB_FUNC void tcc_free_debug(void *ptr) 320 { 321 mem_debug_header_t *header; 322 if (!ptr) 323 return; 324 header = malloc_check(ptr, "tcc_free"); 325 mem_cur_size -= header->size; 326 header->size = (unsigned)-1; 327 if (header->next) 328 header->next->prev = header->prev; 329 if (header->prev) 330 header->prev->next = header->next; 331 if (header == mem_debug_chain) 332 mem_debug_chain = header->next; 333 free(header); 334 } 335 336 PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line) 337 { 338 void *ptr; 339 ptr = tcc_malloc_debug(size,file,line); 340 memset(ptr, 0, size); 341 return ptr; 342 } 343 344 PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line) 345 { 346 mem_debug_header_t *header; 347 int mem_debug_chain_update = 0; 348 if (!ptr) 349 return tcc_malloc_debug(size, file, line); 350 header = malloc_check(ptr, "tcc_realloc"); 351 mem_cur_size -= header->size; 352 mem_debug_chain_update = (header == mem_debug_chain); 353 header = realloc(header, sizeof(mem_debug_header_t) + size); 354 if (!header) 355 tcc_error("memory full (realloc)"); 356 header->size = size; 357 MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3; 358 if (header->next) 359 header->next->prev = header; 360 if (header->prev) 361 header->prev->next = header; 362 if (mem_debug_chain_update) 363 mem_debug_chain = header; 364 mem_cur_size += size; 365 if (mem_cur_size > mem_max_size) 366 mem_max_size = mem_cur_size; 367 return MEM_USER_PTR(header); 368 } 369 370 PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) 371 { 372 char *ptr; 373 ptr = tcc_malloc_debug(strlen(str) + 1, file, line); 374 strcpy(ptr, str); 375 return ptr; 376 } 377 378 PUB_FUNC void tcc_memcheck(void) 379 { 380 if (mem_cur_size) { 381 mem_debug_header_t *header = mem_debug_chain; 382 fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n", 383 mem_cur_size, mem_max_size); 384 while (header) { 385 fprintf(stderr, "%s:%u: error: %u bytes leaked\n", 386 header->file_name, header->line_num, header->size); 387 header = header->next; 388 } 389 #if MEM_DEBUG-0 == 2 390 exit(2); 391 #endif 392 } 393 } 394 #endif /* MEM_DEBUG */ 275 395 276 396 #define free(p) use_tcc_free(p) … … 281 401 /* dynarrays */ 282 402 283 ST_FUNC void dynarray_add(void * **ptab, int *nb_ptr, void *data)403 ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data) 284 404 { 285 405 int nb, nb_alloc; 286 406 void **pp; 287 407 288 408 nb = *nb_ptr; 289 pp = * ptab;409 pp = *(void ***)ptab; 290 410 /* every power of two we double array size */ 291 411 if ((nb & (nb - 1)) == 0) { … … 295 415 nb_alloc = nb * 2; 296 416 pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); 297 * ptab = pp;417 *(void***)ptab = pp; 298 418 } 299 419 pp[nb++] = data; … … 311 431 } 312 432 313 static void tcc_split_path(TCCState *s, void * **p_ary, int *p_nb_ary, const char *in)433 static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in) 314 434 { 315 435 const char *p; … … 319 439 320 440 cstr_new(&str); 321 for (p = in; c = *p, c != '\0' && c != PATHSEP ; ++p) {441 for (p = in; c = *p, c != '\0' && c != PATHSEP[0]; ++p) { 322 442 if (c == '{' && p[1] && p[2] == '}') { 323 443 c = p[1], p += 2; 324 444 if (c == 'B') 325 cstr_cat(&str, s->tcc_lib_path );445 cstr_cat(&str, s->tcc_lib_path, -1); 326 446 } else { 327 447 cstr_ccat(&str, c); 328 448 } 329 449 } 330 cstr_ccat(&str, '\0'); 331 dynarray_add(p_ary, p_nb_ary, str.data); 450 if (str.size) { 451 cstr_ccat(&str, '\0'); 452 dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data)); 453 } 454 cstr_free(&str); 332 455 in = p+1; 333 456 } while (*p); 334 }335 336 /********************************************************/337 338 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)339 {340 Section *sec;341 342 sec = tcc_mallocz(sizeof(Section) + strlen(name));343 strcpy(sec->name, name);344 sec->sh_type = sh_type;345 sec->sh_flags = sh_flags;346 switch(sh_type) {347 case SHT_HASH:348 case SHT_REL:349 case SHT_RELA:350 case SHT_DYNSYM:351 case SHT_SYMTAB:352 case SHT_DYNAMIC:353 sec->sh_addralign = 4;354 break;355 case SHT_STRTAB:356 sec->sh_addralign = 1;357 break;358 default:359 sec->sh_addralign = 32; /* default conservative alignment */360 break;361 }362 363 if (sh_flags & SHF_PRIVATE) {364 dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);365 } else {366 sec->sh_num = s1->nb_sections;367 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);368 }369 370 return sec;371 }372 373 static void free_section(Section *s)374 {375 tcc_free(s->data);376 }377 378 /* realloc section and set its content to zero */379 ST_FUNC void section_realloc(Section *sec, unsigned long new_size)380 {381 unsigned long size;382 unsigned char *data;383 384 size = sec->data_allocated;385 if (size == 0)386 size = 1;387 while (size < new_size)388 size = size * 2;389 data = tcc_realloc(sec->data, size);390 memset(data + sec->data_allocated, 0, size - sec->data_allocated);391 sec->data = data;392 sec->data_allocated = size;393 }394 395 /* reserve at least 'size' bytes in section 'sec' from396 sec->data_offset. */397 ST_FUNC void *section_ptr_add(Section *sec, unsigned long size)398 {399 unsigned long offset, offset1;400 401 offset = sec->data_offset;402 offset1 = offset + size;403 if (offset1 > sec->data_allocated)404 section_realloc(sec, offset1);405 sec->data_offset = offset1;406 return sec->data + offset;407 }408 409 /* reserve at least 'size' bytes from section start */410 ST_FUNC void section_reserve(Section *sec, unsigned long size)411 {412 if (size > sec->data_allocated)413 section_realloc(sec, size);414 if (size > sec->data_offset)415 sec->data_offset = size;416 }417 418 /* return a reference to a section, and create it if it does not419 exists */420 ST_FUNC Section *find_section(TCCState *s1, const char *name)421 {422 Section *sec;423 int i;424 for(i = 1; i < s1->nb_sections; i++) {425 sec = s1->sections[i];426 if (!strcmp(name, sec->name))427 return sec;428 }429 /* sections are created as PROGBITS */430 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);431 }432 433 /* update sym->c so that it points to an external symbol in section434 'section' with value 'value' */435 ST_FUNC void put_extern_sym2(Sym *sym, Section *section,436 addr_t value, unsigned long size,437 int can_add_underscore)438 {439 int sym_type, sym_bind, sh_num, info, other;440 ElfW(Sym) *esym;441 const char *name;442 char buf1[256];443 444 if (section == NULL)445 sh_num = SHN_UNDEF;446 else if (section == SECTION_ABS)447 sh_num = SHN_ABS;448 else449 sh_num = section->sh_num;450 451 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {452 sym_type = STT_FUNC;453 } else if ((sym->type.t & VT_BTYPE) == VT_VOID) {454 sym_type = STT_NOTYPE;455 } else {456 sym_type = STT_OBJECT;457 }458 459 if (sym->type.t & VT_STATIC)460 sym_bind = STB_LOCAL;461 else {462 if (sym->type.t & VT_WEAK)463 sym_bind = STB_WEAK;464 else465 sym_bind = STB_GLOBAL;466 }467 468 if (!sym->c) {469 name = get_tok_str(sym->v, NULL);470 #ifdef CONFIG_TCC_BCHECK471 if (tcc_state->do_bounds_check) {472 char buf[32];473 474 /* XXX: avoid doing that for statics ? */475 /* if bound checking is activated, we change some function476 names by adding the "__bound" prefix */477 switch(sym->v) {478 #ifdef TCC_TARGET_PE479 /* XXX: we rely only on malloc hooks */480 case TOK_malloc:481 case TOK_free:482 case TOK_realloc:483 case TOK_memalign:484 case TOK_calloc:485 #endif486 case TOK_memcpy:487 case TOK_memmove:488 case TOK_memset:489 case TOK_strlen:490 case TOK_strcpy:491 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64492 case TOK_alloca:493 #endif494 strcpy(buf, "__bound_");495 strcat(buf, name);496 name = buf;497 break;498 }499 }500 #endif501 other = 0;502 503 #ifdef TCC_TARGET_PE504 if (sym->type.t & VT_EXPORT)505 other |= 1;506 if (sym_type == STT_FUNC && sym->type.ref) {507 int attr = sym->type.ref->r;508 if (FUNC_EXPORT(attr))509 other |= 1;510 if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) {511 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE);512 name = buf1;513 other |= 2;514 can_add_underscore = 0;515 }516 } else {517 if (find_elf_sym(tcc_state->dynsymtab_section, name))518 other |= 4;519 if (sym->type.t & VT_IMPORT)520 other |= 4;521 }522 #endif523 if (tcc_state->leading_underscore && can_add_underscore) {524 buf1[0] = '_';525 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);526 name = buf1;527 }528 if (sym->asm_label) {529 name = sym->asm_label;530 }531 info = ELFW(ST_INFO)(sym_bind, sym_type);532 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);533 } else {534 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];535 esym->st_value = value;536 esym->st_size = size;537 esym->st_shndx = sh_num;538 }539 }540 541 ST_FUNC void put_extern_sym(Sym *sym, Section *section,542 addr_t value, unsigned long size)543 {544 put_extern_sym2(sym, section, value, size, 1);545 }546 547 /* add a new relocation entry to symbol 'sym' in section 's' */548 ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)549 {550 int c = 0;551 if (sym) {552 if (0 == sym->c)553 put_extern_sym(sym, NULL, 0, 0);554 c = sym->c;555 }556 /* now we can add ELF relocation info */557 put_elf_reloc(symtab_section, s, offset, type, c);558 457 } 559 458 … … 579 478 char buf[2048]; 580 479 BufferedFile **pf, *f; 581 480 582 481 buf[0] = '\0'; 583 482 /* use upper file if inline ":asm:" or token ":paste:" */ 584 for (f = file; f && f->filename[0] == ':'; f = f->prev); 483 for (f = file; f && f->filename[0] == ':'; f = f->prev) 484 ; 585 485 if (f) { 586 486 for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++) 587 487 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", 588 488 (*pf)->filename, (*pf)->line_num); 589 if ( f->line_num > 0) {489 if (s1->error_set_jmp_enabled) { 590 490 strcat_printf(buf, sizeof(buf), "%s:%d: ", 591 f->filename, f->line_num );491 f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL)); 592 492 } else { 593 493 strcat_printf(buf, sizeof(buf), "%s: ", … … 605 505 if (!s1->error_func) { 606 506 /* default case: stderr */ 507 if (s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout) 508 /* print a newline during tcc -E */ 509 printf("\n"), fflush(stdout); 510 fflush(stdout); /* flush -v output */ 607 511 fprintf(stderr, "%s\n", buf); 512 fflush(stderr); /* print error/warning now (win32) */ 608 513 } else { 609 514 s1->error_func(s1->error_opaque, buf); … … 669 574 int buflen = initlen ? initlen : IO_BUF_SIZE; 670 575 671 bf = tcc_malloc (sizeof(BufferedFile) + buflen);576 bf = tcc_mallocz(sizeof(BufferedFile) + buflen); 672 577 bf->buf_ptr = bf->buffer; 673 578 bf->buf_end = bf->buffer + initlen; 674 579 bf->buf_end[0] = CH_EOB; /* put eob symbol */ 675 580 pstrcpy(bf->filename, sizeof(bf->filename), filename); 676 #ifdef _WIN32 677 normalize_slashes(bf->filename); 678 #endif 581 bf->true_filename = bf->filename; 679 582 bf->line_num = 1; 680 bf->ifndef_macro = 0;681 583 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; 682 584 bf->fd = -1; 683 585 bf->prev = file; 684 586 file = bf; 587 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; 685 588 } 686 589 … … 692 595 total_lines += bf->line_num; 693 596 } 597 if (bf->true_filename != bf->filename) 598 tcc_free(bf->true_filename); 694 599 file = bf->prev; 695 600 tcc_free(bf); … … 700 605 int fd; 701 606 if (strcmp(filename, "-") == 0) 702 fd = 0, filename = " stdin";607 fd = 0, filename = "<stdin>"; 703 608 else 704 609 fd = open(filename, O_RDONLY | O_BINARY); … … 708 613 if (fd < 0) 709 614 return -1; 710 711 615 tcc_open_bf(s1, filename, 0); 616 #ifdef _WIN32 617 normalize_slashes(file->filename); 618 #endif 712 619 file->fd = fd; 713 620 return fd; 714 621 } 715 622 716 /* compile the Cfile opened in 'file'. Return non zero if errors. */623 /* compile the file opened in 'file'. Return non zero if errors. */ 717 624 static int tcc_compile(TCCState *s1) 718 625 { 719 626 Sym *define_start; 720 SValue *pvtop; 721 char buf[512]; 722 volatile int section_sym; 723 724 #ifdef INC_DEBUG 725 printf("%s: **** new file\n", file->filename); 726 #endif 727 preprocess_init(s1); 728 729 cur_text_section = NULL; 730 funcname = ""; 731 anon_sym = SYM_FIRST_ANOM; 732 733 /* file info: full path + filename */ 734 section_sym = 0; /* avoid warning */ 735 if (s1->do_debug) { 736 section_sym = put_elf_sym(symtab_section, 0, 0, 737 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, 738 text_section->sh_num, NULL); 739 getcwd(buf, sizeof(buf)); 740 #ifdef _WIN32 741 normalize_slashes(buf); 742 #endif 743 pstrcat(buf, sizeof(buf), "/"); 744 put_stabs_r(buf, N_SO, 0, 0, 745 text_section->data_offset, text_section, section_sym); 746 put_stabs_r(file->filename, N_SO, 0, 0, 747 text_section->data_offset, text_section, section_sym); 748 } 749 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL 750 symbols can be safely used */ 751 put_elf_sym(symtab_section, 0, 0, 752 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, 753 SHN_ABS, file->filename); 754 755 /* define some often used types */ 756 int_type.t = VT_INT; 757 758 char_pointer_type.t = VT_BYTE; 759 mk_pointer(&char_pointer_type); 760 761 #if PTR_SIZE == 4 762 size_type.t = VT_INT; 763 #else 764 size_type.t = VT_LLONG; 765 #endif 766 767 func_old_type.t = VT_FUNC; 768 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); 769 #ifdef TCC_TARGET_ARM 770 arm_init_types(); 771 #endif 772 773 #if 0 774 /* define 'void *alloca(unsigned int)' builtin function */ 775 { 776 Sym *s1; 777 778 p = anon_sym++; 779 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW); 780 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0); 781 s1->next = NULL; 782 sym->next = s1; 783 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); 784 } 785 #endif 627 int filetype, is_asm; 786 628 787 629 define_start = define_stack; 788 nocode_wanted = 1; 630 filetype = s1->filetype; 631 is_asm = filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP; 632 tccelf_begin_file(s1); 789 633 790 634 if (setjmp(s1->error_jmp_buf) == 0) { … … 792 636 s1->error_set_jmp_enabled = 1; 793 637 794 ch = file->buf_ptr[0]; 795 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; 796 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM; 797 pvtop = vtop; 798 next(); 799 decl(VT_CONST); 800 if (tok != TOK_EOF) 801 expect("declaration"); 802 if (pvtop != vtop) 803 tcc_warning("internal compiler error: vstack leak? (%d)", vtop - pvtop); 804 805 /* end of translation unit info */ 806 if (s1->do_debug) { 807 put_stabs_r(NULL, N_SO, 0, 0, 808 text_section->data_offset, text_section, section_sym); 638 preprocess_start(s1, is_asm); 639 if (s1->output_type == TCC_OUTPUT_PREPROCESS) { 640 tcc_preprocess(s1); 641 } else if (is_asm) { 642 #ifdef CONFIG_TCC_ASM 643 tcc_assemble(s1, filetype == AFF_TYPE_ASMPP); 644 #else 645 tcc_error_noabort("asm not supported"); 646 #endif 647 } else { 648 tccgen_compile(s1); 809 649 } 810 650 } 811 812 651 s1->error_set_jmp_enabled = 0; 813 652 814 /* reset define stack, but leave -Dsymbols (may be incorrect if 815 they are undefined) */ 816 free_defines(define_start); 817 818 gen_inline_functions(); 819 820 sym_pop(&global_stack, NULL); 821 sym_pop(&local_stack, NULL); 822 653 preprocess_end(s1); 654 free_inline_functions(s1); 655 /* reset define stack, but keep -D and built-ins */ 656 free_defines(define_start); 657 sym_pop(&global_stack, NULL, 0); 658 sym_pop(&local_stack, NULL, 0); 659 tccelf_end_file(s1); 823 660 return s1->nb_errors != 0 ? -1 : 0; 824 661 } … … 827 664 { 828 665 int len, ret; 666 829 667 len = strlen(str); 830 831 668 tcc_open_bf(s, "<string>", len); 832 669 memcpy(file->buffer, str, len); … … 853 690 854 691 /* parse with define parser */ 855 ch = file->buf_ptr[0];856 692 next_nomacro(); 857 693 parse_define(); 858 859 694 tcc_close(); 860 695 } … … 875 710 static void tcc_cleanup(void) 876 711 { 877 int i, n;878 712 if (NULL == tcc_state) 879 713 return; 714 while (file) 715 tcc_close(); 716 tccpp_delete(tcc_state); 880 717 tcc_state = NULL; 881 882 /* free -D defines */883 free_defines(NULL);884 885 /* free tokens */886 n = tok_ident - TOK_IDENT;887 for(i = 0; i < n; i++)888 tcc_free(table_ident[i]);889 tcc_free(table_ident);890 891 718 /* free sym_pools */ 892 719 dynarray_reset(&sym_pools, &nb_sym_pools); 893 /* string buffer */894 cstr_free(&tokcstr);895 720 /* reset symbol stack */ 896 721 sym_free_first = NULL; 897 /* cleanup from error/setjmp */898 macro_ptr = NULL;899 722 } 900 723 … … 902 725 { 903 726 TCCState *s; 904 char buffer[100];905 int a,b,c;906 727 907 728 tcc_cleanup(); … … 911 732 return NULL; 912 733 tcc_state = s; 734 ++nb_states; 735 736 s->alacarte_link = 1; 737 s->nocommon = 1; 738 s->warn_implicit_function_declaration = 1; 739 s->ms_extensions = 1; 740 741 #ifdef CHAR_IS_UNSIGNED 742 s->char_is_unsigned = 1; 743 #endif 744 #ifdef TCC_TARGET_I386 745 s->seg_size = 32; 746 #endif 747 /* enable this if you want symbols with leading underscore on windows: */ 748 #if 0 /* def TCC_TARGET_PE */ 749 s->leading_underscore = 1; 750 #endif 913 751 #ifdef _WIN32 914 752 tcc_set_lib_path_w32(s); … … 916 754 tcc_set_lib_path(s, CONFIG_TCCDIR); 917 755 #endif 918 s->output_type = TCC_OUTPUT_MEMORY; 919 preprocess_new(); 920 s->include_stack_ptr = s->include_stack; 756 tccelf_new(s); 757 tccpp_new(s); 921 758 922 759 /* we add dummy defines for some special macros to speed up tests … … 926 763 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); 927 764 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); 928 929 /* define __TINYC__ 92X */ 930 sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c); 931 sprintf(buffer, "%d", a*10000 + b*100 + c); 932 tcc_define_symbol(s, "__TINYC__", buffer); 765 define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL); 766 { 767 /* define __TINYC__ 92X */ 768 char buffer[32]; int a,b,c; 769 sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c); 770 sprintf(buffer, "%d", a*10000 + b*100 + c); 771 tcc_define_symbol(s, "__TINYC__", buffer); 772 } 933 773 934 774 /* standard defines */ 935 775 tcc_define_symbol(s, "__STDC__", NULL); 936 776 tcc_define_symbol(s, "__STDC_VERSION__", "199901L"); 777 tcc_define_symbol(s, "__STDC_HOSTED__", NULL); 937 778 938 779 /* target defines */ … … 952 793 tcc_define_symbol(s, "arm", NULL); 953 794 tcc_define_symbol(s, "__APCS_32__", NULL); 795 tcc_define_symbol(s, "__ARMEL__", NULL); 796 #if defined(TCC_ARM_EABI) 797 tcc_define_symbol(s, "__ARM_EABI__", NULL); 798 #endif 799 #if defined(TCC_ARM_HARDFLOAT) 800 s->float_abi = ARM_HARD_FLOAT; 801 tcc_define_symbol(s, "__ARM_PCS_VFP", NULL); 802 #else 803 s->float_abi = ARM_SOFTFP_FLOAT; 804 #endif 805 #elif defined(TCC_TARGET_ARM64) 806 tcc_define_symbol(s, "__aarch64__", NULL); 807 #elif defined TCC_TARGET_C67 808 tcc_define_symbol(s, "__C67__", NULL); 954 809 #endif 955 810 … … 963 818 tcc_define_symbol(s, "__unix", NULL); 964 819 tcc_define_symbol(s, "unix", NULL); 965 # if defined(__linux )820 # if defined(__linux__) 966 821 tcc_define_symbol(s, "__linux__", NULL); 967 822 tcc_define_symbol(s, "__linux", NULL); 968 823 # endif 969 824 # if defined(__FreeBSD__) 970 # define str(s) #s 971 tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));972 # undef str 825 tcc_define_symbol(s, "__FreeBSD__", "__FreeBSD__"); 826 /* No 'Thread Storage Local' on FreeBSD with tcc */ 827 tcc_define_symbol(s, "__NO_TLS", NULL); 973 828 # endif 974 829 # if defined(__FreeBSD_kernel__) 975 830 tcc_define_symbol(s, "__FreeBSD_kernel__", NULL); 976 831 # endif 832 # if defined(__NetBSD__) 833 tcc_define_symbol(s, "__NetBSD__", "__NetBSD__"); 834 # endif 835 # if defined(__OpenBSD__) 836 tcc_define_symbol(s, "__OpenBSD__", "__OpenBSD__"); 837 # endif 977 838 #endif 978 839 979 840 /* TinyCC & gcc defines */ 980 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 841 #if PTR_SIZE == 4 842 /* 32bit systems. */ 843 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int"); 844 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int"); 845 tcc_define_symbol(s, "__ILP32__", NULL); 846 #elif LONG_SIZE == 4 847 /* 64bit Windows. */ 981 848 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long"); 982 849 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long"); 850 tcc_define_symbol(s, "__LLP64__", NULL); 983 851 #else 852 /* Other 64bit systems. */ 984 853 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long"); 985 854 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long"); 855 tcc_define_symbol(s, "__LP64__", NULL); 986 856 #endif 987 857 988 858 #ifdef TCC_TARGET_PE 989 859 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short"); 860 tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short"); 990 861 #else 991 862 tcc_define_symbol(s, "__WCHAR_TYPE__", "int"); 992 #endif 993 994 #ifndef TCC_TARGET_PE 863 /* wint_t is unsigned int by default, but (signed) int on BSDs 864 and unsigned short on windows. Other OSes might have still 865 other conventions, sigh. */ 866 # if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) \ 867 || defined(__NetBSD__) || defined(__OpenBSD__) 868 tcc_define_symbol(s, "__WINT_TYPE__", "int"); 869 # ifdef __FreeBSD__ 870 /* define __GNUC__ to have some useful stuff from sys/cdefs.h 871 that are unconditionally used in FreeBSDs other system headers :/ */ 872 tcc_define_symbol(s, "__GNUC__", "2"); 873 tcc_define_symbol(s, "__GNUC_MINOR__", "7"); 874 tcc_define_symbol(s, "__builtin_alloca", "alloca"); 875 # endif 876 # else 877 tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int"); 995 878 /* glibc defines */ 996 tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)"); 997 tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW"); 998 /* default library paths */ 999 tcc_add_library_path(s, CONFIG_TCC_LIBPATHS); 1000 /* paths for crt objects */ 1001 tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); 1002 #endif 1003 1004 /* no section zero */ 1005 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL); 1006 1007 /* create standard sections */ 1008 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); 1009 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 1010 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); 1011 1012 /* symbols are always generated for linking stage */ 1013 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, 1014 ".strtab", 1015 ".hashtab", SHF_PRIVATE); 1016 strtab_section = symtab_section->link; 1017 s->symtab = symtab_section; 1018 1019 /* private symbol table for dynamic symbols */ 1020 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE, 1021 ".dynstrtab", 1022 ".dynhashtab", SHF_PRIVATE); 1023 s->alacarte_link = 1; 1024 s->nocommon = 1; 1025 s->section_align = ELF_PAGE_SIZE; 1026 1027 #ifdef CHAR_IS_UNSIGNED 1028 s->char_is_unsigned = 1; 1029 #endif 1030 /* enable this if you want symbols with leading underscore on windows: */ 1031 #if 0 //def TCC_TARGET_PE 1032 s->leading_underscore = 1; 1033 #endif 1034 #ifdef TCC_TARGET_I386 1035 s->seg_size = 32; 1036 #endif 879 tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", 880 "name proto __asm__ (#alias)"); 881 tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", 882 "name proto __asm__ (#alias) __THROW"); 883 # endif 884 # if defined(TCC_MUSL) 885 tcc_define_symbol(s, "__DEFINED_va_list", ""); 886 tcc_define_symbol(s, "__DEFINED___isoc_va_list", ""); 887 tcc_define_symbol(s, "__isoc_va_list", "void *"); 888 # endif /* TCC_MUSL */ 889 /* Some GCC builtins that are simple to express as macros. */ 890 tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x"); 891 #endif /* ndef TCC_TARGET_PE */ 1037 892 return s; 1038 893 } … … 1040 895 LIBTCCAPI void tcc_delete(TCCState *s1) 1041 896 { 1042 int i;1043 1044 897 tcc_cleanup(); 1045 898 1046 /* free all sections */ 1047 for(i = 1; i < s1->nb_sections; i++) 1048 free_section(s1->sections[i]); 1049 dynarray_reset(&s1->sections, &s1->nb_sections); 1050 1051 for(i = 0; i < s1->nb_priv_sections; i++) 1052 free_section(s1->priv_sections[i]); 1053 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections); 1054 1055 /* free any loaded DLLs */ 1056 for ( i = 0; i < s1->nb_loaded_dlls; i++) { 1057 DLLReference *ref = s1->loaded_dlls[i]; 1058 if ( ref->handle ) 1059 dlclose(ref->handle); 1060 } 1061 1062 /* free loaded dlls array */ 1063 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); 899 /* free sections */ 900 tccelf_delete(s1); 1064 901 1065 902 /* free library paths */ … … 1071 908 dynarray_reset(&s1->include_paths, &s1->nb_include_paths); 1072 909 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); 910 dynarray_reset(&s1->cmd_include_files, &s1->nb_cmd_include_files); 1073 911 1074 912 tcc_free(s1->tcc_lib_path); … … 1081 919 dynarray_reset(&s1->files, &s1->nb_files); 1082 920 dynarray_reset(&s1->target_deps, &s1->nb_target_deps); 921 dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs); 922 dynarray_reset(&s1->argv, &s1->argc); 1083 923 1084 924 #ifdef TCC_IS_NATIVE 1085 # ifdef HAVE_SELINUX 1086 munmap (s1->write_mem, s1->mem_size); 1087 munmap (s1->runtime_mem, s1->mem_size); 1088 # else 1089 tcc_free(s1->runtime_mem); 925 /* free runtime memory */ 926 tcc_run_free(s1); 927 #endif 928 929 tcc_free(s1); 930 if (0 == --nb_states) 931 tcc_memcheck(); 932 } 933 934 LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) 935 { 936 s->output_type = output_type; 937 938 /* always elf for objects */ 939 if (output_type == TCC_OUTPUT_OBJ) 940 s->output_format = TCC_OUTPUT_FORMAT_ELF; 941 942 if (s->char_is_unsigned) 943 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL); 944 945 if (!s->nostdinc) { 946 /* default include paths */ 947 /* -isystem paths have already been handled */ 948 tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS); 949 } 950 951 #ifdef CONFIG_TCC_BCHECK 952 if (s->do_bounds_check) { 953 /* if bound checking, then add corresponding sections */ 954 tccelf_bounds_new(s); 955 /* define symbol */ 956 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL); 957 } 958 #endif 959 if (s->do_debug) { 960 /* add debug sections */ 961 tccelf_stab_new(s); 962 } 963 964 tcc_add_library_path(s, CONFIG_TCC_LIBPATHS); 965 966 #ifdef TCC_TARGET_PE 967 # ifdef _WIN32 968 if (!s->nostdlib && output_type != TCC_OUTPUT_OBJ) 969 tcc_add_systemdir(s); 1090 970 # endif 1091 #endif 1092 1093 tcc_free(s1); 971 #else 972 /* paths for crt objects */ 973 tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); 974 /* add libc crt1/crti objects */ 975 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && 976 !s->nostdlib) { 977 if (output_type != TCC_OUTPUT_DLL) 978 tcc_add_crt(s, "crt1.o"); 979 tcc_add_crt(s, "crti.o"); 980 } 981 #endif 982 return 0; 1094 983 } 1095 984 1096 985 LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) 1097 986 { 1098 tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname);987 tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname); 1099 988 return 0; 1100 989 } … … 1102 991 LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) 1103 992 { 1104 tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);993 tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); 1105 994 return 0; 1106 995 } … … 1108 997 ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) 1109 998 { 1110 const char *ext; 1111 ElfW(Ehdr) ehdr; 1112 int fd, ret, size; 1113 1114 /* find source file type with extension */ 1115 ext = tcc_fileextension(filename); 1116 if (ext[0]) 1117 ext++; 1118 1119 #ifdef CONFIG_TCC_ASM 1120 /* if .S file, define __ASSEMBLER__ like gcc does */ 1121 if (!strcmp(ext, "S")) 1122 tcc_define_symbol(s1, "__ASSEMBLER__", NULL); 1123 #endif 999 int ret; 1124 1000 1125 1001 /* open the file */ … … 1132 1008 1133 1009 /* update target deps */ 1134 dynarray_add( (void ***)&s1->target_deps, &s1->nb_target_deps,1010 dynarray_add(&s1->target_deps, &s1->nb_target_deps, 1135 1011 tcc_strdup(filename)); 1136 1012 1137 if (flags & AFF_PREPROCESS) { 1138 ret = tcc_preprocess(s1); 1139 goto the_end; 1140 } 1141 1142 if (!ext[0] || !PATHCMP(ext, "c")) { 1143 /* C file assumed */ 1144 ret = tcc_compile(s1); 1145 goto the_end; 1146 } 1147 1148 #ifdef CONFIG_TCC_ASM 1149 if (!strcmp(ext, "S")) { 1150 /* preprocessed assembler */ 1151 ret = tcc_assemble(s1, 1); 1152 goto the_end; 1153 } 1154 1155 if (!strcmp(ext, "s")) { 1156 /* non preprocessed assembler */ 1157 ret = tcc_assemble(s1, 0); 1158 goto the_end; 1159 } 1160 #endif 1161 1162 fd = file->fd; 1163 /* assume executable format: auto guess file type */ 1164 size = read(fd, &ehdr, sizeof(ehdr)); 1165 lseek(fd, 0, SEEK_SET); 1166 if (size <= 0) { 1167 tcc_error_noabort("could not read header"); 1168 goto the_end; 1169 } 1170 1171 if (size == sizeof(ehdr) && 1172 ehdr.e_ident[0] == ELFMAG0 && 1173 ehdr.e_ident[1] == ELFMAG1 && 1174 ehdr.e_ident[2] == ELFMAG2 && 1175 ehdr.e_ident[3] == ELFMAG3) { 1176 1177 /* do not display line number if error */ 1178 file->line_num = 0; 1179 if (ehdr.e_type == ET_REL) { 1013 if (flags & AFF_TYPE_BIN) { 1014 ElfW(Ehdr) ehdr; 1015 int fd, obj_type; 1016 1017 fd = file->fd; 1018 obj_type = tcc_object_type(fd, &ehdr); 1019 lseek(fd, 0, SEEK_SET); 1020 1021 #ifdef TCC_TARGET_MACHO 1022 if (0 == obj_type && 0 == strcmp(tcc_fileextension(filename), ".dylib")) 1023 obj_type = AFF_BINTYPE_DYN; 1024 #endif 1025 1026 switch (obj_type) { 1027 case AFF_BINTYPE_REL: 1180 1028 ret = tcc_load_object_file(s1, fd, 0); 1181 goto the_end; 1182 1183 } 1029 break; 1184 1030 #ifndef TCC_TARGET_PE 1185 if (ehdr.e_type == ET_DYN) {1031 case AFF_BINTYPE_DYN: 1186 1032 if (s1->output_type == TCC_OUTPUT_MEMORY) { 1033 ret = 0; 1187 1034 #ifdef TCC_IS_NATIVE 1188 void *h; 1189 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); 1190 if (h) 1191 #endif 1192 ret = 0; 1035 if (NULL == dlopen(filename, RTLD_GLOBAL | RTLD_LAZY)) 1036 ret = -1; 1037 #endif 1193 1038 } else { 1194 ret = tcc_load_dll(s1, fd, filename, 1039 ret = tcc_load_dll(s1, fd, filename, 1195 1040 (flags & AFF_REFERENCED_DLL) != 0); 1196 1041 } 1197 goto the_end; 1042 break; 1043 #endif 1044 case AFF_BINTYPE_AR: 1045 ret = tcc_load_archive(s1, fd); 1046 break; 1047 #ifdef TCC_TARGET_COFF 1048 case AFF_BINTYPE_C67: 1049 ret = tcc_load_coff(s1, fd); 1050 break; 1051 #endif 1052 default: 1053 #ifdef TCC_TARGET_PE 1054 ret = pe_load_file(s1, filename, fd); 1055 #else 1056 /* as GNU ld, consider it is an ld script if not recognized */ 1057 ret = tcc_load_ldscript(s1); 1058 #endif 1059 if (ret < 0) 1060 tcc_error_noabort("unrecognized file type"); 1061 break; 1198 1062 } 1199 #endif 1200 tcc_error_noabort("unrecognized ELF file"); 1201 goto the_end; 1202 } 1203 1204 if (memcmp((char *)&ehdr, ARMAG, 8) == 0) { 1205 file->line_num = 0; /* do not display line number if error */ 1206 ret = tcc_load_archive(s1, fd); 1207 goto the_end; 1208 } 1209 1210 #ifdef TCC_TARGET_COFF 1211 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) { 1212 ret = tcc_load_coff(s1, fd); 1213 goto the_end; 1214 } 1215 #endif 1216 1217 #ifdef TCC_TARGET_PE 1218 ret = pe_load_file(s1, filename, fd); 1219 #else 1220 /* as GNU ld, consider it is an ld script if not recognized */ 1221 ret = tcc_load_ldscript(s1); 1222 #endif 1223 if (ret < 0) 1224 tcc_error_noabort("unrecognized file type"); 1225 1226 the_end: 1063 } else { 1064 ret = tcc_compile(s1); 1065 } 1227 1066 tcc_close(); 1228 1067 return ret; … … 1231 1070 LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) 1232 1071 { 1233 if (s->output_type == TCC_OUTPUT_PREPROCESS) 1234 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS); 1235 else 1236 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR); 1072 int filetype = s->filetype; 1073 int flags = AFF_PRINT_ERROR; 1074 if (filetype == 0) { 1075 /* use a file extension to detect a filetype */ 1076 const char *ext = tcc_fileextension(filename); 1077 if (ext[0]) { 1078 ext++; 1079 if (!strcmp(ext, "S")) 1080 filetype = AFF_TYPE_ASMPP; 1081 else if (!strcmp(ext, "s")) 1082 filetype = AFF_TYPE_ASM; 1083 else if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i")) 1084 filetype = AFF_TYPE_C; 1085 else 1086 flags |= AFF_TYPE_BIN; 1087 } else { 1088 filetype = AFF_TYPE_C; 1089 } 1090 s->filetype = filetype; 1091 } 1092 return tcc_add_file_internal(s, filename, flags); 1237 1093 } 1238 1094 1239 1095 LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) 1240 1096 { 1241 tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname);1097 tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname); 1242 1098 return 0; 1243 1099 } … … 1251 1107 for(i = 0; i < nb_paths; i++) { 1252 1108 snprintf(buf, sizeof(buf), fmt, paths[i], filename); 1253 if (tcc_add_file_internal(s, buf, flags ) == 0)1109 if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0) 1254 1110 return 0; 1255 1111 } … … 1276 1132 LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) 1277 1133 { 1278 #if defTCC_TARGET_PE1134 #if defined TCC_TARGET_PE 1279 1135 const char *libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL }; 1280 1136 const char **pp = s->static_link ? libs + 4 : libs; 1137 #elif defined TCC_TARGET_MACHO 1138 const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL }; 1139 const char **pp = s->static_link ? libs + 1 : libs; 1281 1140 #else 1282 1141 const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL }; … … 1292 1151 } 1293 1152 1153 PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname) 1154 { 1155 int ret = tcc_add_library(s, libname); 1156 if (ret < 0) 1157 tcc_error_noabort("library '%s' not found", libname); 1158 return ret; 1159 } 1160 1161 /* handle #pragma comment(lib,) */ 1162 ST_FUNC void tcc_add_pragma_libs(TCCState *s1) 1163 { 1164 int i; 1165 for (i = 0; i < s1->nb_pragma_libs; i++) 1166 tcc_add_library_err(s1, s1->pragma_libs[i]); 1167 } 1168 1294 1169 LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val) 1295 1170 { … … 1299 1174 pe_putimport(s, 0, name, (uintptr_t)val); 1300 1175 #else 1301 /* XXX: Same problem on linux but currently "solved" elsewhere 1302 via the rather dirty 'runtime_plt_and_got' hack. */ 1303 add_elf_sym(symtab_section, (uintptr_t)val, 0, 1176 set_elf_sym(symtab_section, (uintptr_t)val, 0, 1304 1177 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1305 1178 SHN_ABS, name); 1306 #endif1307 return 0;1308 }1309 1310 LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)1311 {1312 s->output_type = output_type;1313 1314 if (!s->nostdinc) {1315 /* default include paths */1316 /* -isystem paths have already been handled */1317 tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);1318 }1319 1320 /* if bound checking, then add corresponding sections */1321 #ifdef CONFIG_TCC_BCHECK1322 if (s->do_bounds_check) {1323 /* define symbol */1324 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);1325 /* create bounds sections */1326 bounds_section = new_section(s, ".bounds",1327 SHT_PROGBITS, SHF_ALLOC);1328 lbounds_section = new_section(s, ".lbounds",1329 SHT_PROGBITS, SHF_ALLOC);1330 }1331 #endif1332 1333 if (s->char_is_unsigned) {1334 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);1335 }1336 1337 /* add debug sections */1338 if (s->do_debug) {1339 /* stab symbols */1340 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);1341 stab_section->sh_entsize = sizeof(Stab_Sym);1342 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);1343 put_elf_str(stabstr_section, "");1344 stab_section->link = stabstr_section;1345 /* put first entry */1346 put_stabs("", 0, 0, 0, 0);1347 }1348 1349 #ifdef TCC_TARGET_PE1350 tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);1351 # ifdef _WIN321352 tcc_add_systemdir(s);1353 # endif1354 #else1355 /* add libc crt1/crti objects */1356 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&1357 !s->nostdlib) {1358 if (output_type != TCC_OUTPUT_DLL)1359 tcc_add_crt(s, "crt1.o");1360 tcc_add_crt(s, "crti.o");1361 }1362 1179 #endif 1363 1180 return 0; … … 1379 1196 } FlagDef; 1380 1197 1381 static const FlagDef warning_defs[] = {1382 { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, 1383 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },1384 { offsetof(TCCState, warn_error), 0, "error" },1385 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,1386 "implicit-function-declaration" },1387 };1388 1389 ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, 1390 const char *name, int value)1391 { 1392 int i;1198 static int no_flag(const char **pp) 1199 { 1200 const char *p = *pp; 1201 if (*p != 'n' || *++p != 'o' || *++p != '-') 1202 return 0; 1203 *pp = p + 1; 1204 return 1; 1205 } 1206 1207 ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name) 1208 { 1209 int value, ret; 1393 1210 const FlagDef *p; 1394 1211 const char *r; 1395 1212 1213 value = 1; 1396 1214 r = name; 1397 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') { 1398 r += 3; 1399 value = !value; 1400 } 1401 for(i = 0, p = flags; i < nb_flags; i++, p++) { 1402 if (!strcmp(r, p->name)) 1403 goto found; 1404 } 1405 return -1; 1406 found: 1407 if (p->flags & FD_INVERT) 1408 value = !value; 1409 *(int *)((uint8_t *)s + p->offset) = value; 1410 return 0; 1411 } 1412 1413 /* set/reset a warning */ 1414 static int tcc_set_warning(TCCState *s, const char *warning_name, int value) 1415 { 1416 int i; 1417 const FlagDef *p; 1418 1419 if (!strcmp(warning_name, "all")) { 1420 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) { 1421 if (p->flags & WD_ALL) 1422 *(int *)((uint8_t *)s + p->offset) = 1; 1215 if (no_flag(&r)) 1216 value = 0; 1217 1218 for (ret = -1, p = flags; p->name; ++p) { 1219 if (ret) { 1220 if (strcmp(r, p->name)) 1221 continue; 1222 } else { 1223 if (0 == (p->flags & WD_ALL)) 1224 continue; 1423 1225 } 1424 return 0; 1425 } else { 1426 return set_flag(s, warning_defs, countof(warning_defs), 1427 warning_name, value); 1428 } 1429 } 1430 1431 static const FlagDef flag_defs[] = { 1432 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, 1433 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, 1434 { offsetof(TCCState, nocommon), FD_INVERT, "common" }, 1435 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, 1436 }; 1437 1438 /* set/reset a flag */ 1439 static int tcc_set_flag(TCCState *s, const char *flag_name, int value) 1440 { 1441 return set_flag(s, flag_defs, countof(flag_defs), 1442 flag_name, value); 1443 } 1444 1226 if (p->offset) { 1227 *(int*)((char *)s + p->offset) = 1228 p->flags & FD_INVERT ? !value : value; 1229 if (ret) 1230 return 0; 1231 } else { 1232 ret = 0; 1233 } 1234 } 1235 return ret; 1236 } 1445 1237 1446 1238 static int strstart(const char *val, const char **str) … … 1470 1262 { 1471 1263 const char *p, *q; 1264 int ret; 1472 1265 1473 1266 /* there should be 1 or 2 dashes */ … … 1477 1270 str++; 1478 1271 1479 /* then str & val should match (potential y up to '=') */1272 /* then str & val should match (potentially up to '=') */ 1480 1273 p = str; 1481 1274 q = val; 1275 1276 ret = 1; 1277 if (q[0] == '?') { 1278 ++q; 1279 if (no_flag(&p)) 1280 ret = -1; 1281 } 1482 1282 1483 1283 while (*q != '\0' && *q != '=') { … … 1490 1290 /* '=' near eos means ',' or '=' is ok */ 1491 1291 if (*q == '=') { 1292 if (*p == 0) 1293 *ptr = p; 1492 1294 if (*p != ',' && *p != '=') 1493 1295 return 0; 1494 1296 p++; 1495 q++; 1496 } 1497 1498 if (ptr) 1499 *ptr = p; 1500 return 1; 1297 } else if (*p) { 1298 return 0; 1299 } 1300 *ptr = p; 1301 return ret; 1501 1302 } 1502 1303 … … 1509 1310 } 1510 1311 1511 static char *copy_linker_arg(const char *p) 1512 { 1513 const char *q = p; 1312 static void copy_linker_arg(char **pp, const char *s, int sep) 1313 { 1314 const char *q = s; 1315 char *p = *pp; 1316 int l = 0; 1317 if (p && sep) 1318 p[l = strlen(p)] = sep, ++l; 1514 1319 skip_linker_arg(&q); 1515 return pstrncpy(tcc_malloc(q - p + 1), p, q - p);1320 pstrncpy(l + (*pp = tcc_realloc(p, q - s + l + 1)), s, q - s); 1516 1321 } 1517 1322 … … 1519 1324 static int tcc_set_linker(TCCState *s, const char *option) 1520 1325 { 1521 while ( option &&*option) {1522 1523 const char *p = option;1326 while (*option) { 1327 1328 const char *p = NULL; 1524 1329 char *end = NULL; 1525 1330 int ignoring = 0; 1331 int ret; 1526 1332 1527 1333 if (link_option(option, "Bsymbolic", &p)) { … … 1530 1336 s->nostdlib = 1; 1531 1337 } else if (link_option(option, "fini=", &p)) { 1532 s->fini_symbol = copy_linker_arg(p);1338 copy_linker_arg(&s->fini_symbol, p, 0); 1533 1339 ignoring = 1; 1534 1340 } else if (link_option(option, "image-base=", &p) … … 1537 1343 s->has_text_addr = 1; 1538 1344 } else if (link_option(option, "init=", &p)) { 1539 s->init_symbol = copy_linker_arg(p);1345 copy_linker_arg(&s->init_symbol, p, 0); 1540 1346 ignoring = 1; 1541 1347 } else if (link_option(option, "oformat=", &p)) { 1542 1348 #if defined(TCC_TARGET_PE) 1543 1349 if (strstart("pe-", &p)) { 1544 #elif defined(TCC_TARGET_X86_64)1350 #elif PTR_SIZE == 8 1545 1351 if (strstart("elf64-", &p)) { 1546 1352 #else … … 1557 1363 goto err; 1558 1364 1365 } else if (link_option(option, "as-needed", &p)) { 1366 ignoring = 1; 1367 } else if (link_option(option, "O", &p)) { 1368 ignoring = 1; 1369 } else if (link_option(option, "export-all-symbols", &p)) { 1370 s->rdynamic = 1; 1559 1371 } else if (link_option(option, "rpath=", &p)) { 1560 s->rpath = copy_linker_arg(p); 1372 copy_linker_arg(&s->rpath, p, ':'); 1373 } else if (link_option(option, "enable-new-dtags", &p)) { 1374 s->enable_new_dtags = 1; 1561 1375 } else if (link_option(option, "section-alignment=", &p)) { 1562 1376 s->section_align = strtoul(p, &end, 16); 1563 1377 } else if (link_option(option, "soname=", &p)) { 1564 s->soname = copy_linker_arg(p);1378 copy_linker_arg(&s->soname, p, 0); 1565 1379 #ifdef TCC_TARGET_PE 1380 } else if (link_option(option, "large-address-aware", &p)) { 1381 s->pe_characteristics |= 0x20; 1566 1382 } else if (link_option(option, "file-alignment=", &p)) { 1567 1383 s->pe_file_align = strtoul(p, &end, 16); … … 1574 1390 } else if (!strcmp(p, "console")) { 1575 1391 s->pe_subsystem = 3; 1576 } else if (!strcmp(p, "gui") ) {1392 } else if (!strcmp(p, "gui") || !strcmp(p, "windows")) { 1577 1393 s->pe_subsystem = 2; 1578 1394 } else if (!strcmp(p, "posix")) { … … 1593 1409 goto err; 1594 1410 #endif 1595 } else 1596 goto err; 1597 1598 if (ignoring && s->warn_unsupported) err: { 1599 char buf[100], *e; 1600 pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e); 1601 if (ignoring) 1602 tcc_warning("unsupported linker option '%s'", buf); 1603 else 1604 tcc_error("unsupported linker option '%s'", buf); 1411 } else if (ret = link_option(option, "?whole-archive", &p), ret) { 1412 s->alacarte_link = ret < 0; 1413 } else if (p) { 1414 return 0; 1415 } else { 1416 err: 1417 tcc_error("unsupported linker option '%s'", option); 1605 1418 } 1419 1420 if (ignoring && s->warn_unsupported) 1421 tcc_warning("unsupported linker option '%s'", option); 1422 1606 1423 option = skip_linker_arg(&p); 1607 1424 } 1608 return 0;1425 return 1; 1609 1426 } 1610 1427 … … 1617 1434 enum { 1618 1435 TCC_OPTION_HELP, 1436 TCC_OPTION_HELP2, 1437 TCC_OPTION_v, 1619 1438 TCC_OPTION_I, 1620 1439 TCC_OPTION_D, 1621 1440 TCC_OPTION_U, 1441 TCC_OPTION_P, 1622 1442 TCC_OPTION_L, 1623 1443 TCC_OPTION_B, … … 1628 1448 TCC_OPTION_g, 1629 1449 TCC_OPTION_c, 1450 TCC_OPTION_dumpversion, 1451 TCC_OPTION_d, 1630 1452 TCC_OPTION_static, 1453 TCC_OPTION_std, 1631 1454 TCC_OPTION_shared, 1632 1455 TCC_OPTION_soname, … … 1634 1457 TCC_OPTION_r, 1635 1458 TCC_OPTION_s, 1459 TCC_OPTION_traditional, 1636 1460 TCC_OPTION_Wl, 1461 TCC_OPTION_Wp, 1637 1462 TCC_OPTION_W, 1638 1463 TCC_OPTION_O, 1464 TCC_OPTION_mfloat_abi, 1639 1465 TCC_OPTION_m, 1640 1466 TCC_OPTION_f, 1641 1467 TCC_OPTION_isystem, 1468 TCC_OPTION_iwithprefix, 1469 TCC_OPTION_include, 1642 1470 TCC_OPTION_nostdinc, 1643 1471 TCC_OPTION_nostdlib, 1644 1472 TCC_OPTION_print_search_dirs, 1645 1473 TCC_OPTION_rdynamic, 1474 TCC_OPTION_param, 1646 1475 TCC_OPTION_pedantic, 1647 1476 TCC_OPTION_pthread, 1648 1477 TCC_OPTION_run, 1649 TCC_OPTION_v,1650 1478 TCC_OPTION_w, 1651 1479 TCC_OPTION_pipe, … … 1654 1482 TCC_OPTION_MF, 1655 1483 TCC_OPTION_x, 1656 TCC_OPTION_dumpversion, 1484 TCC_OPTION_ar, 1485 TCC_OPTION_impdef 1657 1486 }; 1658 1487 … … 1664 1493 { "-help", TCC_OPTION_HELP, 0 }, 1665 1494 { "?", TCC_OPTION_HELP, 0 }, 1495 { "hh", TCC_OPTION_HELP2, 0 }, 1496 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1666 1497 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG }, 1667 1498 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG }, 1668 1499 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG }, 1500 { "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1669 1501 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG }, 1670 1502 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG }, … … 1679 1511 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1680 1512 { "c", TCC_OPTION_c, 0 }, 1513 { "dumpversion", TCC_OPTION_dumpversion, 0}, 1514 { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1681 1515 { "static", TCC_OPTION_static, 0 }, 1516 { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1682 1517 { "shared", TCC_OPTION_shared, 0 }, 1683 1518 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG }, 1684 1519 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, 1520 { "-param", TCC_OPTION_param, TCC_OPTION_HAS_ARG }, 1685 1521 { "pedantic", TCC_OPTION_pedantic, 0}, 1686 1522 { "pthread", TCC_OPTION_pthread, 0}, … … 1689 1525 { "r", TCC_OPTION_r, 0 }, 1690 1526 { "s", TCC_OPTION_s, 0 }, 1527 { "traditional", TCC_OPTION_traditional, 0 }, 1691 1528 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1529 { "Wp,", TCC_OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1692 1530 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1693 1531 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1694 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG }, 1532 #ifdef TCC_TARGET_ARM 1533 { "mfloat-abi", TCC_OPTION_mfloat_abi, TCC_OPTION_HAS_ARG }, 1534 #endif 1535 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1695 1536 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1696 1537 { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG }, 1538 { "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG }, 1697 1539 { "nostdinc", TCC_OPTION_nostdinc, 0 }, 1698 1540 { "nostdlib", TCC_OPTION_nostdlib, 0 }, 1699 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 1700 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1541 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 1701 1542 { "w", TCC_OPTION_w, 0 }, 1702 1543 { "pipe", TCC_OPTION_pipe, 0}, … … 1705 1546 { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, 1706 1547 { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, 1707 { "dumpversion", TCC_OPTION_dumpversion, 0}, 1548 { "ar", TCC_OPTION_ar, 0}, 1549 #ifdef TCC_TARGET_PE 1550 { "impdef", TCC_OPTION_impdef, 0}, 1551 #endif 1708 1552 { NULL, 0, 0 }, 1553 }; 1554 1555 static const FlagDef options_W[] = { 1556 { 0, 0, "all" }, 1557 { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, 1558 { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, 1559 { offsetof(TCCState, warn_error), 0, "error" }, 1560 { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" }, 1561 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, 1562 "implicit-function-declaration" }, 1563 { 0, 0, NULL } 1564 }; 1565 1566 static const FlagDef options_f[] = { 1567 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, 1568 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, 1569 { offsetof(TCCState, nocommon), FD_INVERT, "common" }, 1570 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, 1571 { offsetof(TCCState, ms_extensions), 0, "ms-extensions" }, 1572 { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" }, 1573 { 0, 0, NULL } 1574 }; 1575 1576 static const FlagDef options_m[] = { 1577 { offsetof(TCCState, ms_bitfields), 0, "ms-bitfields" }, 1578 #ifdef TCC_TARGET_X86_64 1579 { offsetof(TCCState, nosse), FD_INVERT, "sse" }, 1580 #endif 1581 { 0, 0, NULL } 1709 1582 }; 1710 1583 … … 1719 1592 } 1720 1593 1721 PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) 1594 static void args_parser_add_file(TCCState *s, const char* filename, int filetype) 1595 { 1596 struct filespec *f = tcc_malloc(sizeof *f + strlen(filename)); 1597 f->type = filetype; 1598 f->alacarte = s->alacarte_link; 1599 strcpy(f->name, filename); 1600 dynarray_add(&s->files, &s->nb_files, f); 1601 } 1602 1603 static int args_parser_make_argv(const char *r, int *argc, char ***argv) 1604 { 1605 int ret = 0, q, c; 1606 CString str; 1607 for(;;) { 1608 while (c = (unsigned char)*r, c && c <= ' ') 1609 ++r; 1610 if (c == 0) 1611 break; 1612 q = 0; 1613 cstr_new(&str); 1614 while (c = (unsigned char)*r, c) { 1615 ++r; 1616 if (c == '\\' && (*r == '"' || *r == '\\')) { 1617 c = *r++; 1618 } else if (c == '"') { 1619 q = !q; 1620 continue; 1621 } else if (q == 0 && c <= ' ') { 1622 break; 1623 } 1624 cstr_ccat(&str, c); 1625 } 1626 cstr_ccat(&str, 0); 1627 //printf("<%s>\n", str.data), fflush(stdout); 1628 dynarray_add(argv, argc, tcc_strdup(str.data)); 1629 cstr_free(&str); 1630 ++ret; 1631 } 1632 return ret; 1633 } 1634 1635 /* read list file */ 1636 static void args_parser_listfile(TCCState *s, 1637 const char *filename, int optind, int *pargc, char ***pargv) 1638 { 1639 int fd, i; 1640 size_t len; 1641 char *p; 1642 int argc = 0; 1643 char **argv = NULL; 1644 1645 fd = open(filename, O_RDONLY | O_BINARY); 1646 if (fd < 0) 1647 tcc_error("listfile '%s' not found", filename); 1648 1649 len = lseek(fd, 0, SEEK_END); 1650 p = tcc_malloc(len + 1), p[len] = 0; 1651 lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd); 1652 1653 for (i = 0; i < *pargc; ++i) 1654 if (i == optind) 1655 args_parser_make_argv(p, &argc, &argv); 1656 else 1657 dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i])); 1658 1659 tcc_free(p); 1660 dynarray_reset(&s->argv, &s->argc); 1661 *pargc = s->argc = argc, *pargv = s->argv = argv; 1662 } 1663 1664 PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind) 1722 1665 { 1723 1666 const TCCOption *popt; 1724 1667 const char *optarg, *r; 1725 int run = 0; 1726 int pthread = 0; 1727 int optind = 0; 1728 1729 /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */ 1730 CString linker_arg; 1668 const char *run = NULL; 1669 int last_o = -1; 1670 int x; 1671 CString linker_arg; /* collect -Wl options */ 1672 int tool = 0, arg_start = 0, noaction = optind; 1673 char **argv = *pargv; 1674 int argc = *pargc; 1675 1731 1676 cstr_new(&linker_arg); 1732 1677 1733 1678 while (optind < argc) { 1734 1735 r = argv[optind++]; 1679 r = argv[optind]; 1680 if (r[0] == '@' && r[1] != '\0') { 1681 args_parser_listfile(s, r + 1, optind, &argc, &argv); 1682 continue; 1683 } 1684 optind++; 1685 if (tool) { 1686 if (r[0] == '-' && r[1] == 'v' && r[2] == 0) 1687 ++s->verbose; 1688 continue; 1689 } 1690 reparse: 1736 1691 if (r[0] != '-' || r[1] == '\0') { 1737 /* add a new file*/1738 dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));1692 if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */ 1693 args_parser_add_file(s, r, s->filetype); 1739 1694 if (run) { 1740 optind--;1741 /* argv[0] will be this file */1695 tcc_set_options(s, run); 1696 arg_start = optind - 1; 1742 1697 break; 1743 1698 } … … 1757 1712 if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) { 1758 1713 if (optind >= argc) 1714 arg_err: 1759 1715 tcc_error("argument to '%s' is missing", r); 1760 1716 optarg = argv[optind++]; … … 1767 1723 switch(popt->index) { 1768 1724 case TCC_OPTION_HELP: 1769 return 0; 1725 return OPT_HELP; 1726 case TCC_OPTION_HELP2: 1727 return OPT_HELP2; 1770 1728 case TCC_OPTION_I: 1771 if (tcc_add_include_path(s, optarg) < 0) 1772 tcc_error("too many include paths"); 1729 tcc_add_include_path(s, optarg); 1773 1730 break; 1774 1731 case TCC_OPTION_D: … … 1786 1743 break; 1787 1744 case TCC_OPTION_l: 1788 dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));1745 args_parser_add_file(s, optarg, AFF_TYPE_LIB); 1789 1746 s->nb_libraries++; 1790 1747 break; 1791 1748 case TCC_OPTION_pthread: 1792 1749 parse_option_D(s, "_REENTRANT"); 1793 pthread = 1;1750 s->option_pthread = 1; 1794 1751 break; 1795 1752 case TCC_OPTION_bench: … … 1811 1768 break; 1812 1769 case TCC_OPTION_c: 1813 s->output_type = TCC_OUTPUT_OBJ; 1770 x = TCC_OUTPUT_OBJ; 1771 set_output_type: 1772 if (s->output_type) 1773 tcc_warning("-%s: overriding compiler action already specified", popt->name); 1774 s->output_type = x; 1775 break; 1776 case TCC_OPTION_d: 1777 if (*optarg == 'D') 1778 s->dflag = 3; 1779 else if (*optarg == 'M') 1780 s->dflag = 7; 1781 else if (*optarg == 't') 1782 s->dflag = 16; 1783 else if (isnum(*optarg)) 1784 g_debug = atoi(optarg); 1785 else 1786 goto unsupported_option; 1814 1787 break; 1815 1788 case TCC_OPTION_static: 1816 1789 s->static_link = 1; 1817 1790 break; 1791 case TCC_OPTION_std: 1792 /* silently ignore, a current purpose: 1793 allow to use a tcc as a reference compiler for "make test" */ 1794 break; 1818 1795 case TCC_OPTION_shared: 1819 s->output_type= TCC_OUTPUT_DLL;1820 break;1796 x = TCC_OUTPUT_DLL; 1797 goto set_output_type; 1821 1798 case TCC_OPTION_soname: 1822 1799 s->soname = tcc_strdup(optarg); 1823 1800 break; 1824 case TCC_OPTION_m:1825 s->option_m = tcc_strdup(optarg);1826 break;1827 1801 case TCC_OPTION_o: 1802 if (s->outfile) { 1803 tcc_warning("multiple -o option"); 1804 tcc_free(s->outfile); 1805 } 1828 1806 s->outfile = tcc_strdup(optarg); 1829 1807 break; … … 1831 1809 /* generate a .o merging several output files */ 1832 1810 s->option_r = 1; 1833 s->output_type= TCC_OUTPUT_OBJ;1834 break;1811 x = TCC_OUTPUT_OBJ; 1812 goto set_output_type; 1835 1813 case TCC_OPTION_isystem: 1836 1814 tcc_add_sysinclude_path(s, optarg); 1837 1815 break; 1816 case TCC_OPTION_include: 1817 dynarray_add(&s->cmd_include_files, 1818 &s->nb_cmd_include_files, tcc_strdup(optarg)); 1819 break; 1838 1820 case TCC_OPTION_nostdinc: 1839 1821 s->nostdinc = 1; … … 1842 1824 s->nostdlib = 1; 1843 1825 break; 1844 case TCC_OPTION_print_search_dirs:1845 s->print_search_dirs = 1;1846 break;1847 1826 case TCC_OPTION_run: 1848 s->output_type = TCC_OUTPUT_MEMORY; 1849 tcc_set_options(s, optarg); 1850 run = 1; 1851 break; 1827 #ifndef TCC_IS_NATIVE 1828 tcc_error("-run is not available in a cross compiler"); 1829 #endif 1830 run = optarg; 1831 x = TCC_OUTPUT_MEMORY; 1832 goto set_output_type; 1852 1833 case TCC_OPTION_v: 1853 1834 do ++s->verbose; while (*optarg++ == 'v'); 1835 ++noaction; 1854 1836 break; 1855 1837 case TCC_OPTION_f: 1856 if ( tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)1838 if (set_flag(s, options_f, optarg) < 0) 1857 1839 goto unsupported_option; 1858 1840 break; 1841 #ifdef TCC_TARGET_ARM 1842 case TCC_OPTION_mfloat_abi: 1843 /* tcc doesn't support soft float yet */ 1844 if (!strcmp(optarg, "softfp")) { 1845 s->float_abi = ARM_SOFTFP_FLOAT; 1846 tcc_undefine_symbol(s, "__ARM_PCS_VFP"); 1847 } else if (!strcmp(optarg, "hard")) 1848 s->float_abi = ARM_HARD_FLOAT; 1849 else 1850 tcc_error("unsupported float abi '%s'", optarg); 1851 break; 1852 #endif 1853 case TCC_OPTION_m: 1854 if (set_flag(s, options_m, optarg) < 0) { 1855 if (x = atoi(optarg), x != 32 && x != 64) 1856 goto unsupported_option; 1857 if (PTR_SIZE != x/8) 1858 return x; 1859 ++noaction; 1860 } 1861 break; 1859 1862 case TCC_OPTION_W: 1860 if (tcc_set_warning(s, optarg, 1) < 0 && 1861 s->warn_unsupported) 1863 if (set_flag(s, options_W, optarg) < 0) 1862 1864 goto unsupported_option; 1863 1865 break; … … 1871 1873 if (linker_arg.size) 1872 1874 --linker_arg.size, cstr_ccat(&linker_arg, ','); 1873 cstr_cat(&linker_arg, optarg); 1874 cstr_ccat(&linker_arg, '\0'); 1875 break; 1875 cstr_cat(&linker_arg, optarg, 0); 1876 if (tcc_set_linker(s, linker_arg.data)) 1877 cstr_free(&linker_arg); 1878 break; 1879 case TCC_OPTION_Wp: 1880 r = optarg; 1881 goto reparse; 1876 1882 case TCC_OPTION_E: 1877 s->output_type = TCC_OUTPUT_PREPROCESS; 1883 x = TCC_OUTPUT_PREPROCESS; 1884 goto set_output_type; 1885 case TCC_OPTION_P: 1886 s->Pflag = atoi(optarg) + 1; 1878 1887 break; 1879 1888 case TCC_OPTION_MD: … … 1886 1895 printf ("%s\n", TCC_VERSION); 1887 1896 exit(0); 1897 break; 1898 case TCC_OPTION_x: 1899 if (*optarg == 'c') 1900 s->filetype = AFF_TYPE_C; 1901 else if (*optarg == 'a') 1902 s->filetype = AFF_TYPE_ASMPP; 1903 else if (*optarg == 'n') 1904 s->filetype = AFF_TYPE_NONE; 1905 else 1906 tcc_warning("unsupported language '%s'", optarg); 1907 break; 1888 1908 case TCC_OPTION_O: 1909 last_o = atoi(optarg); 1910 break; 1911 case TCC_OPTION_print_search_dirs: 1912 x = OPT_PRINT_DIRS; 1913 goto extra_action; 1914 case TCC_OPTION_impdef: 1915 x = OPT_IMPDEF; 1916 goto extra_action; 1917 case TCC_OPTION_ar: 1918 x = OPT_AR; 1919 extra_action: 1920 arg_start = optind - 1; 1921 if (arg_start != noaction) 1922 tcc_error("cannot parse %s here", r); 1923 tool = x; 1924 break; 1925 case TCC_OPTION_traditional: 1889 1926 case TCC_OPTION_pedantic: 1890 1927 case TCC_OPTION_pipe: 1891 1928 case TCC_OPTION_s: 1892 case TCC_OPTION_x:1893 1929 /* ignored */ 1894 1930 break; 1895 1931 default: 1896 if (s->warn_unsupported) { 1897 unsupported_option:1932 unsupported_option: 1933 if (s->warn_unsupported) 1898 1934 tcc_warning("unsupported option '%s'", r); 1899 }1900 1935 break; 1901 1936 } 1902 1937 } 1903 1904 if (pthread && s->output_type != TCC_OUTPUT_OBJ) 1905 tcc_set_options(s, "-lpthread"); 1906 1907 tcc_set_linker(s, (const char *)linker_arg.data); 1908 cstr_free(&linker_arg); 1909 1910 return optind; 1911 } 1912 1913 LIBTCCAPI int tcc_set_options(TCCState *s, const char *str) 1914 { 1915 const char *s1; 1916 char **argv, *arg; 1917 int argc, len; 1918 int ret; 1919 1920 argc = 0, argv = NULL; 1921 for(;;) { 1922 while (is_space(*str)) 1923 str++; 1924 if (*str == '\0') 1925 break; 1926 s1 = str; 1927 while (*str != '\0' && !is_space(*str)) 1928 str++; 1929 len = str - s1; 1930 arg = tcc_malloc(len + 1); 1931 pstrncpy(arg, s1, len); 1932 dynarray_add((void ***)&argv, &argc, arg); 1933 } 1934 ret = tcc_parse_args(s, argc, argv); 1938 if (last_o > 0) 1939 tcc_define_symbol(s, "__OPTIMIZE__", NULL); 1940 if (linker_arg.size) { 1941 r = linker_arg.data; 1942 goto arg_err; 1943 } 1944 *pargc = argc - arg_start; 1945 *pargv = argv + arg_start; 1946 if (tool) 1947 return tool; 1948 if (optind != noaction) 1949 return 0; 1950 if (s->verbose == 2) 1951 return OPT_PRINT_DIRS; 1952 if (s->verbose) 1953 return OPT_V; 1954 return OPT_HELP; 1955 } 1956 1957 LIBTCCAPI void tcc_set_options(TCCState *s, const char *r) 1958 { 1959 char **argv = NULL; 1960 int argc = 0; 1961 args_parser_make_argv(r, &argc, &argv); 1962 tcc_parse_args(s, &argc, &argv, 0); 1935 1963 dynarray_reset(&argv, &argc); 1936 return ret; 1937 } 1938 1939 PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time) 1940 { 1941 double tt; 1942 tt = (double)total_time / 1000000.0; 1943 if (tt < 0.001) 1944 tt = 0.001; 1964 } 1965 1966 PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time) 1967 { 1968 if (total_time < 1) 1969 total_time = 1; 1945 1970 if (total_bytes < 1) 1946 1971 total_bytes = 1; 1947 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", 1972 fprintf(stderr, "* %d idents, %d lines, %d bytes\n" 1973 "* %0.3f s, %u lines/s, %0.1f MB/s\n", 1948 1974 tok_ident - TOK_IDENT, total_lines, total_bytes, 1949 tt, (int)(total_lines / tt), 1950 total_bytes / tt / 1000000.0); 1951 } 1975 (double)total_time/1000, 1976 (unsigned)total_lines*1000/total_time, 1977 (double)total_bytes/1000/total_time); 1978 #ifdef MEM_DEBUG 1979 fprintf(stderr, "* %d bytes memory used\n", mem_max_size); 1980 #endif 1981 }
Note:
See TracChangeset
for help on using the changeset viewer.