diff --git a/src/profile.c b/src/profile.c index 537b520..436f14f 100644 --- a/src/profile.c +++ b/src/profile.c @@ -31,46 +31,60 @@ #include "portab.h" #include "profile.h" -static char **profile_name = NULL, **profile_value = NULL; +struct profile_kv { + char *name; + char *value; +}; + +static struct profile_kv *profile = NULL; static int profile_values = 0; -static int profile_ready = FALSE; -int load_profile(char *path) +static struct profile_kv *check_profile(const char *name) { - FILE *fp = NULL; - char *home_dir = NULL, profile_path[PATH_MAX], rc_line[RC_LINE_CHARS_MAX]; - char *p, *q; - int now_values = 0, is_flag, line = 0; - - /* 指定の path をまず探す */ - if (path) { - - } else { - + for (int i = 0; i < profile_values; i++) { + if (!strcmp(name, profile[i].name)) + return &profile[i]; + } + return NULL; +} + +static boolean insert_profile(const char *name, const char *value) +{ + struct profile_kv *kv; + + if ((kv = check_profile(name))) { + free(kv->value); + kv->value = strdup(value); + return TRUE; } - /* $(HOME)/.xsys35rc を探す */ - home_dir = getenv("HOME"); - if (home_dir) { - sprintf(profile_path, "%s/%s", home_dir, RC_NAME); - fp = fopen(profile_path, "r"); + profile = realloc(profile, sizeof(struct profile_kv) * (profile_values + 1)); + if (!profile) { + perror("realloc()"); + return FALSE; } - - if (!fp) { - /* 見つからなかったら、CWD から .gicqjarc を探す */ - strcpy(profile_path, RC_NAME); - fp = fopen(RC_NAME, "r"); - if (!fp) { - /* CWD からも見つからなかったら、エラーを表示して終了 */ - char *error_msg; - error_msg = malloc(strlen(profile_path) + 12); - sprintf(error_msg, "fopen() '%s'", profile_path); - perror(error_msg); - free(error_msg); - return 1; - } + + profile[profile_values].name = strdup(name); + profile[profile_values].value = strdup(value); + profile_values++; + return TRUE; +} + +static int load_rc_file(const char *profile_path) +{ + FILE *fp; + char rc_line[RC_LINE_CHARS_MAX]; + char *p, *q; + int is_flag, line = 0; + + if (!(fp = fopen(profile_path, "r"))) { + char *error_msg = malloc(strlen(profile_path) + 12); + sprintf(error_msg, "fopen() '%s'", profile_path); + perror(error_msg); + free(error_msg); + return 1; } - + while (1) { if (!fgets(rc_line, sizeof(rc_line), fp)) { if (feof(fp)) @@ -81,78 +95,61 @@ int load_profile(char *path) } } line++; - + /* 読み込んだ行をパースする */ p = q = rc_line; is_flag = FALSE; - + while (*q) { if (*q == ':') is_flag = TRUE; - - if (iscntrl(*q) || (is_flag == TRUE)?*q == '\n':isspace(*q)) + + if (iscntrl(*q) || (!is_flag && isspace(*q))) q++; else *p++ = *q++; } - + *p = '\0'; - + /* 行頭が # だった場合と、空行の場合は記憶しない */ if (rc_line[0] == '#' || rc_line[0] == '\0') continue; - + if (!(p = strchr(rc_line, ':'))) { fprintf(stderr, "XSYSTEM35: Syntax Error in '%s' line %d.\n", profile_path, line); return 1; } - + *p = '\0'; - + while (*++p) if (!isspace(*p) && !iscntrl(*p)) break; - - /* ANSI の realloc と glib の g_realloc は ptr に NULL ポインタが */ - /* 含まれていた場合の挙動が違うようだ */ - profile_name = realloc(profile_name, sizeof(char *) * (now_values + 1)); - if (!profile_name) { - perror("realloc()"); + + if (!insert_profile(rc_line, p)) return 1; - } - - profile_value = realloc(profile_value, sizeof(char *) * (now_values + 1)); - if (!profile_value) { - perror("realloc()"); - return 1; - } - - *(profile_name + now_values) = malloc(strlen(rc_line) + 1); - strcpy(*(profile_name + now_values), rc_line); - *(profile_value + now_values) = malloc(strlen(p) + 1); - strcpy(*(profile_value + now_values), p); - now_values++; } - - profile_values = now_values; - profile_ready = TRUE; return 0; } +int load_profile(void) +{ + char *home_dir; + + if ((home_dir = getenv("HOME"))) { + char profile_path[PATH_MAX]; + sprintf(profile_path, "%s/%s", home_dir, RC_NAME); + load_rc_file(profile_path); + } + load_rc_file(RC_NAME); +} + char *get_profile(const char *name) { - int i; - - if (profile_ready == FALSE) - return NULL; - - for (i = 0; i < profile_values; i++) - if (strcmp(name, *(profile_name + i)) == 0) - break; - - if (i == profile_values) - return NULL; - - return *(profile_value + i); -} + struct profile_kv *kv; + if (!(kv = check_profile(name))) + return NULL; + return kv->value; +} diff --git a/src/profile.h b/src/profile.h index cb7d94d..ae928a1 100644 --- a/src/profile.h +++ b/src/profile.h @@ -30,7 +30,7 @@ /* 一行は 256 文字を越えない */ #define RC_LINE_CHARS_MAX 256 -int load_profile(char *path); +int load_profile(void); char *get_profile(const char *name); #endif /* __PROFILE_H__ */ diff --git a/src/xsystem35.c b/src/xsystem35.c index d21b893..63a1b22 100644 --- a/src/xsystem35.c +++ b/src/xsystem35.c @@ -800,7 +800,7 @@ int main(int argc, char **argv) { saved_argc = argc; saved_argv = argv; - load_profile(NULL); + load_profile(); check_profile(); sys35_ParseOption(&argc, argv);