diff --git a/config.c b/config.c index e6c209d..274b234 100644 --- a/config.c +++ b/config.c @@ -12,15 +12,20 @@ * * @see https://lowenware.com/ */ +#include +#include +#include +#include +#include #include #include #include static const char m_mixed_line_indent[] = "Line indent contains tabs and spaces" - , m_mixed_block_indent[] = "Block was initiated with different indent" , m_incomplete_key[] = "Incomplete key" , m_parser_error[] = "Parser error" + , m_indent_error[] = "Indent error" , m_out_of_memory[] = "Out of memory" ; @@ -29,7 +34,7 @@ struct config_path { int size; int indent; int level; - bool is_block; + bool is_node; }; struct config_ctx { @@ -50,13 +55,12 @@ config_get_indent(char *line) if (c == ' ' || c == '\t') { if (!chr) { chr = c; + } + if (chr == c) { + result++; } else { - if (chr == c) { - result++; - } else { - /* mixed indent */ - return -1; - } + /* mixed indent */ + return -1; } } else { break; @@ -73,30 +77,35 @@ config_read_line(char *line, ssize_t length, struct cstuff_config *cfg) { const char *err = NULL; CStuffConfigEvent evt = CSTUFF_CONFIG_NONE; - ssize_t i; - int k_len = 0, eq = -1, v_len = 0, last_ch = -1, tab = 0; - char c, *key, *val = NULL; + ssize_t i = 0; + int k_len = 0, v_len = 0, indent = 0; + char c, *key = NULL, *val = NULL; cfg->line_num++; + fprintf(stderr, "cfg:%d ", cfg->line_num); if ((indent = config_get_indent(line)) != -1) { + fprintf(stderr, "indent=%d ", indent); key = &line[indent]; for (i = indent; i < length; i++) { c = line[i]; - if (islanum(c) || c == '_' || c == '-') { + if (isalnum(c) || c == '_' || c == '-') { + k_len++; continue; } - k_len++; + break; } while (i < length) { switch ((c = line[i++])) { case ':': evt = CSTUFF_CONFIG_NODE; + fprintf(stderr, "node! "); continue; case '=': evt = CSTUFF_CONFIG_PAIR; + fprintf(stderr, "pair! "); continue; case ' ': case '\t': @@ -114,8 +123,7 @@ config_read_line(char *line, ssize_t length, struct cstuff_config *cfg) err = m_incomplete_key; } } else if (evt == CSTUFF_CONFIG_PAIR) { - int l = i; - val = &line[i]; + val = &line[i - 1]; while (i < length) { switch (line[i++]) { case ';': @@ -125,7 +133,7 @@ config_read_line(char *line, ssize_t length, struct cstuff_config *cfg) case '\t': continue; default: - v_len = &line[i - 1]; + v_len = (int) (&line[i] - val) - 1; continue; } break; @@ -135,30 +143,32 @@ config_read_line(char *line, ssize_t length, struct cstuff_config *cfg) err = m_parser_error; } } else { - evt = cSTUFF_CONFIG_ERROR; + evt = CSTUFF_CONFIG_ERROR; err = m_mixed_line_indent; } /* Key ! */ - key[k_len] = 0; + if (key) + key[k_len] = 0; + fprintf(stderr, "\n"); switch ((cfg->evt = evt)) { case CSTUFF_CONFIG_PAIR: cfg->data.pair.key = key; - cfg->data.pair.value = val; - cfg->data.pair.value_len = v_len; + cfg->data.pair.val = val; + cfg->data.pair.val_len = v_len; cfg->data.pair.key_len = k_len; val[v_len] = 0; return indent; case CSTUFF_CONFIG_NODE: - cfg->data.pair.node = key; - cfg->data.pair.node_len = k_len; + cfg->data.node.name = key; + cfg->data.node.name_len = k_len; return indent; case CSTUFF_CONFIG_ERROR: default: cfg->data.error.char_num = i; - cfg->data.error.line_text = line; - cfg->data.error.err_text = err; + cfg->data.error.line_txt = line; + cfg->data.error.err_txt = err; return -1; } } @@ -168,7 +178,8 @@ static void config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node) { struct config_path *path = &ctx->path; - const char *key = ctx->cfg.data.pair.key, ptr; + const char *key = ctx->cfg.data.pair.key; + char *ptr; int i, len, level, k_len = ctx->cfg.data.pair.key_len; if (line_indent) { @@ -183,11 +194,14 @@ config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node) level = 0; } - if (level > path->level && !path->is_node || - level - path->level != path->indent) { + if (level > path->level && (!path->is_node || + level - path->level != path->indent)) { + fprintf(stderr, "cfg:%d ((%d > %d && !%d) || %d - %d != %d)\n", + ctx->cfg.line_num, level, + path->level, path->is_node & 0xFF, level, path->level, path->indent); ctx->cfg.evt = CSTUFF_CONFIG_ERROR; - ctx->cfg.data.error.line_text = NULL; - ctx->cfg.data.error.err_text = m_indent_error; + ctx->cfg.data.error.line_txt = NULL; + ctx->cfg.data.error.err_txt = m_indent_error; ctx->cfg.data.error.char_num = 0; return; } @@ -195,7 +209,8 @@ config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node) ptr = ctx->path.key; for (i = 0; i < level; i++) { int l = strcspn(ptr, "."); - ptr += (l + 1); + ptr += l; + fprintf(stderr, "l = %d\n", l); } len = (ptr - ctx->path.key) + 1 + k_len + 1; @@ -203,8 +218,8 @@ config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node) char *new_key; if (!(new_key = realloc(ctx->path.key, len))) { ctx->cfg.evt = CSTUFF_CONFIG_ERROR; - ctx->cfg.data.error.line_text = NULL; - ctx->cfg.data.error.err_text = m_out_of_memory; + ctx->cfg.data.error.line_txt = NULL; + ctx->cfg.data.error.err_txt = m_out_of_memory; ctx->cfg.data.error.char_num = 0; return; } @@ -212,9 +227,14 @@ config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node) ctx->path.size = len; } - *(ptr++) = '.'; + if (level) { + *(ptr++) = '.'; + } else { + *ptr = 0; + } strcpy(ptr, key); path->level = level; + path->is_node = is_node; ctx->cfg.data.pair.key = ctx->path.key; } @@ -224,16 +244,19 @@ static int config_get_line(char *line, ssize_t length, void *p_ctx) { int result; - struct config_ctx *ctx = (struct config_ctx *)ctx; + struct config_ctx *ctx = (struct config_ctx *)p_ctx; memset(&ctx->cfg.data, 0, sizeof (ctx->cfg.data)); if ((result = config_read_line(line, length, &ctx->cfg)) != -1) { bool is_node = (ctx->cfg.evt == CSTUFF_CONFIG_NODE); /* result == indent */ - config_set_path_key(ctx, indent, is_node); - - result = ctx->callback(&ctx->cfg, ctx->u_ptr); + config_set_path_key(ctx, result, is_node); + } else { + fprintf(stderr, "cfg: read line failed %d\n", result); } + + result = ctx->callback(&ctx->cfg, ctx->u_ptr); + return result; } @@ -250,14 +273,16 @@ cstuff_config_parse(const char *file, CStuffConfigCallback callback, void *u_ptr return CSTUFF_MALLOC_ERROR; } else { ctx.path.size = CSTUFF_CONFIG_PATH_SIZE; - ctx.path.indent = 0; - ctx.path.in_chr = 0; } ctx.u_ptr = u_ptr; ctx.callback = callback; rc = cstuff_file_get_lines(file, config_get_line, (void *)&ctx); + if (rc) { + fprintf(stderr, "cfg: get lines failed %d (%s)\n", rc, strerror(errno)); + } + if (ctx.path.key) free(ctx.path.key); return rc; diff --git a/config.h b/config.h index 1045c41..d774e6f 100644 --- a/config.h +++ b/config.h @@ -13,6 +13,9 @@ * @see https://lowenware.com/ */ +#include "retcode.h" + + #ifndef CSTUFF_CONFIG_H_6207A85E_26F1_4B64_818F_92C6286FC5F0 #define CSTUFF_CONFIG_H_6207A85E_26F1_4B64_818F_92C6286FC5F0 @@ -28,30 +31,30 @@ typedef enum { } CStuffConfigEvent; struct cstuff_config_node { - const char *node; - int node_len; + const char *name; + int name_len; }; struct cstuff_config_pair { const char *key; - const char *value; + const char *val; int key_len; - int value_len; + int val_len; }; struct cstuff_config_error { - const char *line_text; - const char *err_text; + const char *line_txt; + const char *err_txt; int char_num; }; struct cstuff_config { CStuffConfigEvent evt; - int line_number; + int line_num; union { struct cstuff_config_node node; struct cstuff_config_pair pair; - struct cstuff_config_ierror error; + struct cstuff_config_error error; } data; }; diff --git a/file.c b/file.c index dd34e45..ce1c375 100644 --- a/file.c +++ b/file.c @@ -86,7 +86,7 @@ cstuff_file_move(const char *src, const char *dest) CStuffRetcode -cstuff_file_get_lines(const char *src, CStuffFileGetLine get_line) +cstuff_file_get_lines(const char *src, CStuffFileGetLine get_line, void *ctx) { FILE *f = NULL; size_t sz = 256; @@ -101,7 +101,7 @@ cstuff_file_get_lines(const char *src, CStuffFileGetLine get_line) goto e_syscall; while ((rs = getdelim(&line, &sz, '\n', f)) != -1) { - if (!get_line(line, rc)) { + if (!get_line(line, rs, ctx)) { continue; } else { goto e_input; diff --git a/file.h b/file.h index 4d473e1..566cb75 100644 --- a/file.h +++ b/file.h @@ -17,6 +17,7 @@ #define CSTUFF_FILE_H_3C3D5EDC_A624_4550_98A4_29AD5A41301D #include +#include #include "retcode.h" diff --git a/retcode.h b/retcode.h index 554efa2..f1283c5 100644 --- a/retcode.h +++ b/retcode.h @@ -17,7 +17,8 @@ #define CSTUFF_RETCODE_H_CBA3C16B_88D6_49F4_966D_DBDA727583FE typedef enum { - CSTUFF_MALLOC_ERROR = -2 + CSTUFF_INPUT_ERROR = -3 + , CSTUFF_MALLOC_ERROR = -2 , CSTUFF_SYSCALL_ERROR = -1 , CSTUFF_SUCCESS = 0 , CSTUFF_IDLE = 1