diff options
-rw-r--r-- | hangul/hangulkeyboard.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/hangul/hangulkeyboard.c b/hangul/hangulkeyboard.c index 53b9d74..caaae29 100644 --- a/hangul/hangulkeyboard.c +++ b/hangul/hangulkeyboard.c @@ -220,14 +220,15 @@ static unsigned int hangul_builtin_keyboard_count = countof(hangul_builtin_keybo static HangulKeyboardList hangul_keyboards = { 0, 0, NULL }; typedef struct _HangulKeyboardLoadContext { - const char* path; + const char* path_stack[64]; + int path_stack_top; HangulKeyboard* keyboard; int current_id; const char* current_element; bool save_name; } HangulKeyboardLoadContext; -static void hangul_keyboard_parse_file(const char* path, void* user_data); +static void hangul_keyboard_parse_file(const char* path, HangulKeyboardLoadContext* context); static bool hangul_keyboard_list_append(HangulKeyboard* keyboard); HangulCombination* @@ -657,7 +658,11 @@ on_element_start(void* data, const XML_Char* element, const XML_Char** attr) if (file == NULL) return; - size_t n = strlen(file) + strlen(context->path) + 1; + int top = context->path_stack_top; + if (top < 0) + return; + + size_t n = strlen(file) + strlen(context->path_stack[top]) + 1; char* path = malloc(n); if (path == NULL) return; @@ -665,7 +670,7 @@ on_element_start(void* data, const XML_Char* element, const XML_Char** attr) if (file[0] == '/') { strncpy(path, file, n); } else { - char* orig_path = strdup(context->path); + char* orig_path = strdup(context->path_stack[top]); char* dir = dirname(orig_path); snprintf(path, n, "%s/%s", dir, file); free(orig_path); @@ -707,7 +712,7 @@ on_char_data(void* data, const XML_Char* s, int len) if (context->keyboard == NULL) return; - if (strcmp(context->current_element, "name") == 0) { + if (context->current_element != NULL && strcmp(context->current_element, "name") == 0) { if (context->save_name) { char buf[1024]; if (len >= sizeof(buf)) @@ -720,11 +725,19 @@ on_char_data(void* data, const XML_Char* s, int len) } static void -hangul_keyboard_parse_file(const char* path, void* user_data) +hangul_keyboard_parse_file(const char* path, HangulKeyboardLoadContext* context) { + int top = context->path_stack_top + 1; + if (top >= sizeof(context->path_stack) / sizeof(context->path_stack[0])) { + return; + } + + context->path_stack[top] = path; + context->path_stack_top = top; + XML_Parser parser = XML_ParserCreate(NULL); - XML_SetUserData(parser, user_data); + XML_SetUserData(parser, context); XML_SetElementHandler(parser, on_element_start, on_element_end); XML_SetCharacterDataHandler(parser, on_char_data); @@ -750,12 +763,16 @@ close: fclose(file); done: XML_ParserFree(parser); + + context->path_stack_top--; } static HangulKeyboard* hangul_keyboard_new_from_file(const char* path) { - HangulKeyboardLoadContext context = { path, NULL, 0, "" }; + HangulKeyboardLoadContext context; + memset(&context, 0, sizeof(context)); + context.path_stack_top = -1; hangul_keyboard_parse_file(path, &context); |