summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hangul/hangulkeyboard.c33
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);