Clean changes introduced by 47abdbd

* Replace the save/load_buffer_state by a dynarray approach:
  - Filename and libname are added to a dynarray when first encountered
  - Load repeatedly the files in the dynarray until no new undefined
    symbol are encountered
* Replace snprintf by sprintf in libname_to_filename
* Use tcc_fileextension in filename_to_libname
* Introduce a tcc_strcpy_part fonction to copy only a subset of a
  string
* Move new_undef_syms declaration from tcc.h to tccelf.c
master
Thomas Preud'homme 2010-04-20 15:49:34 +02:00
parent 809f489662
commit 3ad3168125
3 changed files with 86 additions and 89 deletions

2
tcc.h
View File

@ -225,8 +225,6 @@ typedef struct Sym {
struct Sym *prev_tok; /* previous symbol for this token */ struct Sym *prev_tok; /* previous symbol for this token */
} Sym; } Sym;
static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
/* section definition */ /* section definition */
/* XXX: use directly ELF structure for parameters ? */ /* XXX: use directly ELF structure for parameters ? */
/* special flag to indicate that the section should not be linked to /* special flag to indicate that the section should not be linked to

148
tccelf.c
View File

@ -32,6 +32,8 @@
#define REL_SECTION_FMT ".rel%s" #define REL_SECTION_FMT ".rel%s"
#endif #endif
static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
/* XXX: DLL with PLT would only work with x86-64 for now */ /* XXX: DLL with PLT would only work with x86-64 for now */
//#define TCC_OUTPUT_DLL_WITH_PLT //#define TCC_OUTPUT_DLL_WITH_PLT
@ -2809,49 +2811,49 @@ static int ld_next(TCCState *s1, char *name, int name_size)
return c; return c;
} }
char *tcc_strcpy_part(char *out, const char *in, size_t num)
{
memcpy(out, in, num);
out[num] = '\0';
return out;
}
/* /*
* Extract the library name from the file name * Extract the library name from the file name
* Return 0 if the file isn't a library * Return 0 if the file isn't a library
* *
* /!\ No test on filename capacity, be careful * /!\ No test on filename capacity, be careful
*/ */
static int filename_to_libname(TCCState *s1, char filename[], char libname[]) static int filename_to_libname(TCCState *s1, const char filename[], char libname[])
{ {
char *ext, *base; char *ext;
int libprefix; int libprefix;
/* already converted to library name */ /* already converted to library name */
if (filename[0] == '\0') if (libname[0] == '\0')
return 1; return 1;
base = tcc_basename(filename); ext = tcc_fileextension(filename);
if (base != filename) if (*ext == '\0')
return 0; return 0;
ext = strrchr(base, '.');
if (ext == NULL)
return 0;
ext++;
libprefix = !strncmp(filename, "lib", 3); libprefix = !strncmp(filename, "lib", 3);
if (!s1->static_link) { if (!s1->static_link) {
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
if (!strncmp(ext, "def", 3)) { if (!strcmp(ext, ".def")) {
*(--ext) = '\0'; size_t len = ext - filename;
strcpy(libname, filename); tcc_strcpy_part(libname, filename, len);
*ext = '.';
return 1; return 1;
} }
#else #else
if (libprefix && (!strncmp(ext, "so", 2))) { if (libprefix && (!strcmp(ext, ".so"))) {
*(--ext) = '\0'; size_t len = ext - filename - 3;
strcpy(libname, filename + 3); tcc_strcpy_part(libname, filename + 3, len);
*ext = '.';
return 1; return 1;
} }
#endif #endif
} else { } else {
if (libprefix && (!strncmp(ext, "a", 1))) { if (libprefix && (!strcmp(ext, ".a"))) {
*(--ext) = '\0'; size_t len = ext - filename - 3;
strcpy(libname, filename + 3); tcc_strcpy_part(libname, filename + 3, len);
*ext = '.';
return 1; return 1;
} }
} }
@ -2863,25 +2865,48 @@ static int filename_to_libname(TCCState *s1, char filename[], char libname[])
* *
* /!\ No test on filename capacity, be careful * /!\ No test on filename capacity, be careful
*/ */
static void libname_to_filename(TCCState *s1, char libname[], char filename[]) static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
{ {
if (!s1->static_link) { if (!s1->static_link) {
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
snprintf(filename, strlen(libname) + 5, "%s.def", libname); sprintf(filename, "%s.def", libname);
#else #else
snprintf(filename, strlen(libname) + 7, "lib%s.so", libname); sprintf(filename, "lib%s.so", libname);
#endif #endif
} else { } else {
snprintf(filename, strlen(libname) + 6, "lib%s.a", libname); sprintf(filename, "lib%s.a", libname);
} }
} }
static int ld_add_file_list(TCCState *s1, int as_needed) static int ld_add_file(TCCState *s1, const char filename[], char libname[])
{ {
char filename[1024]; int ret;
char libname[1024];
int t, ret;
ret = tcc_add_file_internal(s1, filename, 0);
if (ret) {
if (filename_to_libname(s1, filename, libname))
ret = tcc_add_library(s1, libname);
}
return ret;
}
static inline int new_undef_syms(void)
{
int ret = 0;
ret = new_undef_sym;
new_undef_sym = 0;
return ret;
}
static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
{
char filename[1024], libname[1024];
int t, group, nblibs = 0, ret = 0;
char **libs = NULL;
group = !strcmp(cmd, "GROUP");
if (!as_needed)
new_undef_syms();
t = ld_next(s1, filename, sizeof(filename)); t = ld_next(s1, filename, sizeof(filename));
if (t != '(') if (t != '(')
expect("("); expect("(");
@ -2890,34 +2915,44 @@ static int ld_add_file_list(TCCState *s1, int as_needed)
libname[0] = '\0'; libname[0] = '\0';
if (t == LD_TOK_EOF) { if (t == LD_TOK_EOF) {
error_noabort("unexpected end of file"); error_noabort("unexpected end of file");
return -1; ret = -1;
goto lib_parse_error;
} else if (t == ')') { } else if (t == ')') {
break; break;
} else if (t == '-') { } else if (t == '-') {
t = ld_next(s1, filename, sizeof(filename)); t = ld_next(s1, filename, sizeof(filename));
if ((t != LD_TOK_NAME) || (filename[0] != 'l')) { if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
error_noabort("library name expected"); error_noabort("library name expected");
return -1; ret = -1;
goto lib_parse_error;
} }
strcpy(libname, &filename[1]); strcpy(libname, &filename[1]);
libname_to_filename(s1, libname, filename); libname_to_filename(s1, libname, filename);
} else if (t != LD_TOK_NAME) { } else if (t != LD_TOK_NAME) {
error_noabort("filename expected"); error_noabort("filename expected");
return -1; ret = -1;
goto lib_parse_error;
} }
if (!strcmp(filename, "AS_NEEDED")) { if (!strcmp(filename, "AS_NEEDED")) {
ret = ld_add_file_list(s1, 1); ret = ld_add_file_list(s1, cmd, 1);
if (ret) if (ret)
return ret; goto lib_parse_error;
} else { } else {
/* TODO: Implement AS_NEEDED support. Ignore it for now */ /* TODO: Implement AS_NEEDED support. Ignore it for now */
if (!as_needed) { if (!as_needed) {
ret = tcc_add_file_internal(s1, filename, 0); ret = ld_add_file(s1, filename, libname);
if (ret) {
if (filename_to_libname(s1, filename, libname))
ret = tcc_add_library(s1, libname);
if (ret) if (ret)
return ret; goto lib_parse_error;
if (group) {
char *file_name, *lib_name;
/* Add the filename and the libname to avoid future conversions */
file_name = tcc_malloc(sizeof(char) * (strlen(filename) + 1));
strcpy(file_name, filename);
dynarray_add((void ***) &libs, &nblibs, file_name);
lib_name = tcc_malloc(sizeof(char) * (strlen(libname) + 1));
strcpy(lib_name, libname);
dynarray_add((void ***) &libs, &nblibs, lib_name);
} }
} }
} }
@ -2926,14 +2961,16 @@ static int ld_add_file_list(TCCState *s1, int as_needed)
t = ld_next(s1, filename, sizeof(filename)); t = ld_next(s1, filename, sizeof(filename));
} }
} }
return 0; if (group && !as_needed) {
} while (new_undef_syms()) {
int i;
static int new_undef_syms(void) for (i = 0; i < nblibs; i += 2)
{ ld_add_file(s1, libs[i], libs[i+1]);
int ret = 0; }
ret = new_undef_sym; }
new_undef_sym = 0; lib_parse_error:
dynarray_reset(&libs, &nblibs);
return ret; return ret;
} }
@ -2955,24 +2992,7 @@ ST_FUNC int tcc_load_ldscript(TCCState *s1)
return -1; return -1;
if (!strcmp(cmd, "INPUT") || if (!strcmp(cmd, "INPUT") ||
!strcmp(cmd, "GROUP")) { !strcmp(cmd, "GROUP")) {
if (!strcmp(cmd, "GROUP")) { ret = ld_add_file_list(s1, cmd, 0);
BufferedFile *buf_state;
int off;
buf_state = tcc_save_buffer_state(&off);
new_undef_syms();
ret = ld_add_file_list(s1, 0);
if (ret)
goto free_bufstate;
while (!ret && new_undef_syms()) {
tcc_load_buffer_state(buf_state, off);
ret = ld_add_file_list(s1, 0);
}
free_bufstate:
tcc_free_buffer_state(buf_state);
} else {
ret = ld_add_file_list(s1, 0);
}
if (ret) if (ret)
return ret; return ret;
} else if (!strcmp(cmd, "OUTPUT_FORMAT") || } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||

21
tccpp.c
View File

@ -378,27 +378,6 @@ static int tcc_peekc_slow(BufferedFile *bf)
} }
} }
BufferedFile *tcc_save_buffer_state(int *offset)
{
BufferedFile *state;
state = tcc_malloc(sizeof(BufferedFile));
memcpy(state, file, sizeof(BufferedFile));
*offset = lseek(file->fd, 0, SEEK_CUR);
return state;
}
void tcc_load_buffer_state(BufferedFile *buf_state, int offset)
{
memcpy(file, buf_state, sizeof(BufferedFile));
lseek(file->fd, offset, SEEK_SET);
}
void tcc_free_buffer_state(BufferedFile *buf_state)
{
tcc_free(buf_state);
}
/* return the current character, handling end of block if necessary /* return the current character, handling end of block if necessary
(but not stray) */ (but not stray) */
ST_FUNC int handle_eob(void) ST_FUNC int handle_eob(void)