Generalize loader searching algorithm

Allow loader to shorten the name word by word to the point where only single word is left.
This commit is contained in:
Paweł Bylica 2018-08-30 22:52:35 +02:00
parent 4955ebfba1
commit a0bffe9523
No known key found for this signature in database
GPG Key ID: 7A0C037434FE77EF
2 changed files with 22 additions and 23 deletions

View File

@ -60,15 +60,16 @@ enum evmc_loader_error_code
* "libexample-interpreter.so",
* - the "lib" prefix and file extension are stripped from the name:
* "example-interpreter"
* - all "-" are replaced with "_" to construct _full name_:
* - all "-" are replaced with "_" to construct _base name_:
* "example_interpreter",
* - the _full name_ is split by "_" char and the last item is taken to form the _short name_:
* "interpreter",
* - the name "evmc_create_" + _full name_ is checked in the library:
* - the function name "evmc_create_" + _base name_ is searched in the library:
* "evmc_create_example_interpreter",
* - then, the name "evmc_create_" + _short name_ is checked in the library:
* "evmc_create_interpreter".
* - lastly, the name "evmc_create" is checked in the library
* - if function not found, the _base name_ is shorten by skipping the first word separated by "_":
* "interpreter",
* - then, the function of the shorter name "evmc_create_" + _base name_ is searched in the library:
* "evmc_create_interpreter",
* - the name shortening continues until a function is found or the name cannot be shorten more,
* - lastly, when no function found, the function name "evmc_create" is searched in the library.
*
* If the create function is found in the library, the pointer to the function is returned.
* Otherwise, the ::EVMC_LOADER_SYMBOL_NOT_FOUND error code is signaled and NULL is returned.

View File

@ -69,8 +69,8 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
// Create name buffer with the prefix.
const char prefix[] = "evmc_create_";
const size_t prefix_length = strlen(prefix);
char name[sizeof(prefix) + PATH_MAX_LENGTH];
strcpy_s(name, sizeof(name), prefix);
char prefixed_name[sizeof(prefix) + PATH_MAX_LENGTH];
strcpy_s(prefixed_name, sizeof(prefixed_name), prefix);
// Find filename in the path.
const char* sep_pos = strrchr(filename, '/');
@ -87,30 +87,28 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
if (strncmp(name_pos, lib_prefix, lib_prefix_length) == 0)
name_pos += lib_prefix_length;
strcpy_s(name + prefix_length, PATH_MAX_LENGTH, name_pos);
char* base_name = prefixed_name + prefix_length;
strcpy_s(base_name, PATH_MAX_LENGTH, name_pos);
// Trim the file extension.
char* ext_pos = strrchr(name, '.');
char* ext_pos = strrchr(prefixed_name, '.');
if (ext_pos)
*ext_pos = 0;
// Replace all "-" with "_".
char* dash_pos = name;
char* dash_pos = base_name;
while ((dash_pos = strchr(dash_pos, '-')) != NULL)
*dash_pos++ = '_';
// Search for the "full name" based function name.
create_fn = DLL_GET_CREATE_FN(handle, name);
if (!create_fn)
// Search for the built function name.
while ((create_fn = DLL_GET_CREATE_FN(handle, prefixed_name)) == NULL)
{
// Try the "short name" based function name.
const char* short_name_pos = strrchr(name, '_');
if (short_name_pos)
{
short_name_pos += 1;
memmove(name + prefix_length, short_name_pos, strlen(short_name_pos) + 1);
create_fn = DLL_GET_CREATE_FN(handle, name);
}
// Shorten the base name by skipping the `word_` segment.
const char* shorter_name_pos = strchr(base_name, '_');
if (!shorter_name_pos)
break;
memmove(base_name, shorter_name_pos + 1, strlen(shorter_name_pos) + 1);
}
if (!create_fn)