Fix config and file modules, add debug output
This commit is contained in:
parent
17ce2c5753
commit
2f5c10cf5d
89
config.c
89
config.c
|
@ -12,15 +12,20 @@
|
||||||
*
|
*
|
||||||
* @see https://lowenware.com/
|
* @see https://lowenware.com/
|
||||||
*/
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <cStuff/file.h>
|
#include <cStuff/file.h>
|
||||||
#include <cStuff/config.h>
|
#include <cStuff/config.h>
|
||||||
|
|
||||||
static const char
|
static const char
|
||||||
m_mixed_line_indent[] = "Line indent contains tabs and spaces"
|
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_incomplete_key[] = "Incomplete key"
|
||||||
, m_parser_error[] = "Parser error"
|
, m_parser_error[] = "Parser error"
|
||||||
|
, m_indent_error[] = "Indent error"
|
||||||
, m_out_of_memory[] = "Out of memory"
|
, m_out_of_memory[] = "Out of memory"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -29,7 +34,7 @@ struct config_path {
|
||||||
int size;
|
int size;
|
||||||
int indent;
|
int indent;
|
||||||
int level;
|
int level;
|
||||||
bool is_block;
|
bool is_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct config_ctx {
|
struct config_ctx {
|
||||||
|
@ -50,14 +55,13 @@ config_get_indent(char *line)
|
||||||
if (c == ' ' || c == '\t') {
|
if (c == ' ' || c == '\t') {
|
||||||
if (!chr) {
|
if (!chr) {
|
||||||
chr = c;
|
chr = c;
|
||||||
} else {
|
}
|
||||||
if (chr == c) {
|
if (chr == c) {
|
||||||
result++;
|
result++;
|
||||||
} else {
|
} else {
|
||||||
/* mixed indent */
|
/* mixed indent */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -73,30 +77,35 @@ config_read_line(char *line, ssize_t length, struct cstuff_config *cfg)
|
||||||
{
|
{
|
||||||
const char *err = NULL;
|
const char *err = NULL;
|
||||||
CStuffConfigEvent evt = CSTUFF_CONFIG_NONE;
|
CStuffConfigEvent evt = CSTUFF_CONFIG_NONE;
|
||||||
ssize_t i;
|
ssize_t i = 0;
|
||||||
int k_len = 0, eq = -1, v_len = 0, last_ch = -1, tab = 0;
|
int k_len = 0, v_len = 0, indent = 0;
|
||||||
char c, *key, *val = NULL;
|
char c, *key = NULL, *val = NULL;
|
||||||
|
|
||||||
cfg->line_num++;
|
cfg->line_num++;
|
||||||
|
fprintf(stderr, "cfg:%d ", cfg->line_num);
|
||||||
|
|
||||||
if ((indent = config_get_indent(line)) != -1) {
|
if ((indent = config_get_indent(line)) != -1) {
|
||||||
|
fprintf(stderr, "indent=%d ", indent);
|
||||||
key = &line[indent];
|
key = &line[indent];
|
||||||
|
|
||||||
for (i = indent; i < length; i++) {
|
for (i = indent; i < length; i++) {
|
||||||
c = line[i];
|
c = line[i];
|
||||||
if (islanum(c) || c == '_' || c == '-') {
|
if (isalnum(c) || c == '_' || c == '-') {
|
||||||
|
k_len++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
k_len++;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i < length) {
|
while (i < length) {
|
||||||
switch ((c = line[i++])) {
|
switch ((c = line[i++])) {
|
||||||
case ':':
|
case ':':
|
||||||
evt = CSTUFF_CONFIG_NODE;
|
evt = CSTUFF_CONFIG_NODE;
|
||||||
|
fprintf(stderr, "node! ");
|
||||||
continue;
|
continue;
|
||||||
case '=':
|
case '=':
|
||||||
evt = CSTUFF_CONFIG_PAIR;
|
evt = CSTUFF_CONFIG_PAIR;
|
||||||
|
fprintf(stderr, "pair! ");
|
||||||
continue;
|
continue;
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
|
@ -114,8 +123,7 @@ config_read_line(char *line, ssize_t length, struct cstuff_config *cfg)
|
||||||
err = m_incomplete_key;
|
err = m_incomplete_key;
|
||||||
}
|
}
|
||||||
} else if (evt == CSTUFF_CONFIG_PAIR) {
|
} else if (evt == CSTUFF_CONFIG_PAIR) {
|
||||||
int l = i;
|
val = &line[i - 1];
|
||||||
val = &line[i];
|
|
||||||
while (i < length) {
|
while (i < length) {
|
||||||
switch (line[i++]) {
|
switch (line[i++]) {
|
||||||
case ';':
|
case ';':
|
||||||
|
@ -125,7 +133,7 @@ config_read_line(char *line, ssize_t length, struct cstuff_config *cfg)
|
||||||
case '\t':
|
case '\t':
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
v_len = &line[i - 1];
|
v_len = (int) (&line[i] - val) - 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -135,30 +143,32 @@ config_read_line(char *line, ssize_t length, struct cstuff_config *cfg)
|
||||||
err = m_parser_error;
|
err = m_parser_error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
evt = cSTUFF_CONFIG_ERROR;
|
evt = CSTUFF_CONFIG_ERROR;
|
||||||
err = m_mixed_line_indent;
|
err = m_mixed_line_indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Key ! */
|
/* Key ! */
|
||||||
|
if (key)
|
||||||
key[k_len] = 0;
|
key[k_len] = 0;
|
||||||
|
|
||||||
|
fprintf(stderr, "\n");
|
||||||
switch ((cfg->evt = evt)) {
|
switch ((cfg->evt = evt)) {
|
||||||
case CSTUFF_CONFIG_PAIR:
|
case CSTUFF_CONFIG_PAIR:
|
||||||
cfg->data.pair.key = key;
|
cfg->data.pair.key = key;
|
||||||
cfg->data.pair.value = val;
|
cfg->data.pair.val = val;
|
||||||
cfg->data.pair.value_len = v_len;
|
cfg->data.pair.val_len = v_len;
|
||||||
cfg->data.pair.key_len = k_len;
|
cfg->data.pair.key_len = k_len;
|
||||||
val[v_len] = 0;
|
val[v_len] = 0;
|
||||||
return indent;
|
return indent;
|
||||||
case CSTUFF_CONFIG_NODE:
|
case CSTUFF_CONFIG_NODE:
|
||||||
cfg->data.pair.node = key;
|
cfg->data.node.name = key;
|
||||||
cfg->data.pair.node_len = k_len;
|
cfg->data.node.name_len = k_len;
|
||||||
return indent;
|
return indent;
|
||||||
case CSTUFF_CONFIG_ERROR:
|
case CSTUFF_CONFIG_ERROR:
|
||||||
default:
|
default:
|
||||||
cfg->data.error.char_num = i;
|
cfg->data.error.char_num = i;
|
||||||
cfg->data.error.line_text = line;
|
cfg->data.error.line_txt = line;
|
||||||
cfg->data.error.err_text = err;
|
cfg->data.error.err_txt = err;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +178,8 @@ static void
|
||||||
config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node)
|
config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node)
|
||||||
{
|
{
|
||||||
struct config_path *path = &ctx->path;
|
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;
|
int i, len, level, k_len = ctx->cfg.data.pair.key_len;
|
||||||
|
|
||||||
if (line_indent) {
|
if (line_indent) {
|
||||||
|
@ -183,11 +194,14 @@ config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node)
|
||||||
level = 0;
|
level = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level > path->level && !path->is_node ||
|
if (level > path->level && (!path->is_node ||
|
||||||
level - path->level != path->indent) {
|
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.evt = CSTUFF_CONFIG_ERROR;
|
||||||
ctx->cfg.data.error.line_text = NULL;
|
ctx->cfg.data.error.line_txt = NULL;
|
||||||
ctx->cfg.data.error.err_text = m_indent_error;
|
ctx->cfg.data.error.err_txt = m_indent_error;
|
||||||
ctx->cfg.data.error.char_num = 0;
|
ctx->cfg.data.error.char_num = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +209,8 @@ config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node)
|
||||||
ptr = ctx->path.key;
|
ptr = ctx->path.key;
|
||||||
for (i = 0; i < level; i++) {
|
for (i = 0; i < level; i++) {
|
||||||
int l = strcspn(ptr, ".");
|
int l = strcspn(ptr, ".");
|
||||||
ptr += (l + 1);
|
ptr += l;
|
||||||
|
fprintf(stderr, "l = %d\n", l);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = (ptr - ctx->path.key) + 1 + k_len + 1;
|
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;
|
char *new_key;
|
||||||
if (!(new_key = realloc(ctx->path.key, len))) {
|
if (!(new_key = realloc(ctx->path.key, len))) {
|
||||||
ctx->cfg.evt = CSTUFF_CONFIG_ERROR;
|
ctx->cfg.evt = CSTUFF_CONFIG_ERROR;
|
||||||
ctx->cfg.data.error.line_text = NULL;
|
ctx->cfg.data.error.line_txt = NULL;
|
||||||
ctx->cfg.data.error.err_text = m_out_of_memory;
|
ctx->cfg.data.error.err_txt = m_out_of_memory;
|
||||||
ctx->cfg.data.error.char_num = 0;
|
ctx->cfg.data.error.char_num = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -212,9 +227,14 @@ config_set_path_key(struct config_ctx *ctx, int line_indent, bool is_node)
|
||||||
ctx->path.size = len;
|
ctx->path.size = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (level) {
|
||||||
*(ptr++) = '.';
|
*(ptr++) = '.';
|
||||||
|
} else {
|
||||||
|
*ptr = 0;
|
||||||
|
}
|
||||||
strcpy(ptr, key);
|
strcpy(ptr, key);
|
||||||
path->level = level;
|
path->level = level;
|
||||||
|
path->is_node = is_node;
|
||||||
|
|
||||||
ctx->cfg.data.pair.key = ctx->path.key;
|
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)
|
config_get_line(char *line, ssize_t length, void *p_ctx)
|
||||||
{
|
{
|
||||||
int result;
|
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));
|
memset(&ctx->cfg.data, 0, sizeof (ctx->cfg.data));
|
||||||
if ((result = config_read_line(line, length, &ctx->cfg)) != -1) {
|
if ((result = config_read_line(line, length, &ctx->cfg)) != -1) {
|
||||||
bool is_node = (ctx->cfg.evt == CSTUFF_CONFIG_NODE);
|
bool is_node = (ctx->cfg.evt == CSTUFF_CONFIG_NODE);
|
||||||
/* result == indent */
|
/* result == indent */
|
||||||
config_set_path_key(ctx, indent, is_node);
|
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);
|
result = ctx->callback(&ctx->cfg, ctx->u_ptr);
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,14 +273,16 @@ cstuff_config_parse(const char *file, CStuffConfigCallback callback, void *u_ptr
|
||||||
return CSTUFF_MALLOC_ERROR;
|
return CSTUFF_MALLOC_ERROR;
|
||||||
} else {
|
} else {
|
||||||
ctx.path.size = CSTUFF_CONFIG_PATH_SIZE;
|
ctx.path.size = CSTUFF_CONFIG_PATH_SIZE;
|
||||||
ctx.path.indent = 0;
|
|
||||||
ctx.path.in_chr = 0;
|
|
||||||
}
|
}
|
||||||
ctx.u_ptr = u_ptr;
|
ctx.u_ptr = u_ptr;
|
||||||
ctx.callback = callback;
|
ctx.callback = callback;
|
||||||
|
|
||||||
rc = cstuff_file_get_lines(file, config_get_line, (void *)&ctx);
|
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)
|
if (ctx.path.key)
|
||||||
free(ctx.path.key);
|
free(ctx.path.key);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
19
config.h
19
config.h
|
@ -13,6 +13,9 @@
|
||||||
* @see https://lowenware.com/
|
* @see https://lowenware.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "retcode.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef CSTUFF_CONFIG_H_6207A85E_26F1_4B64_818F_92C6286FC5F0
|
#ifndef CSTUFF_CONFIG_H_6207A85E_26F1_4B64_818F_92C6286FC5F0
|
||||||
#define CSTUFF_CONFIG_H_6207A85E_26F1_4B64_818F_92C6286FC5F0
|
#define CSTUFF_CONFIG_H_6207A85E_26F1_4B64_818F_92C6286FC5F0
|
||||||
|
|
||||||
|
@ -28,30 +31,30 @@ typedef enum {
|
||||||
} CStuffConfigEvent;
|
} CStuffConfigEvent;
|
||||||
|
|
||||||
struct cstuff_config_node {
|
struct cstuff_config_node {
|
||||||
const char *node;
|
const char *name;
|
||||||
int node_len;
|
int name_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cstuff_config_pair {
|
struct cstuff_config_pair {
|
||||||
const char *key;
|
const char *key;
|
||||||
const char *value;
|
const char *val;
|
||||||
int key_len;
|
int key_len;
|
||||||
int value_len;
|
int val_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cstuff_config_error {
|
struct cstuff_config_error {
|
||||||
const char *line_text;
|
const char *line_txt;
|
||||||
const char *err_text;
|
const char *err_txt;
|
||||||
int char_num;
|
int char_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cstuff_config {
|
struct cstuff_config {
|
||||||
CStuffConfigEvent evt;
|
CStuffConfigEvent evt;
|
||||||
int line_number;
|
int line_num;
|
||||||
union {
|
union {
|
||||||
struct cstuff_config_node node;
|
struct cstuff_config_node node;
|
||||||
struct cstuff_config_pair pair;
|
struct cstuff_config_pair pair;
|
||||||
struct cstuff_config_ierror error;
|
struct cstuff_config_error error;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
4
file.c
4
file.c
|
@ -86,7 +86,7 @@ cstuff_file_move(const char *src, const char *dest)
|
||||||
|
|
||||||
|
|
||||||
CStuffRetcode
|
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;
|
FILE *f = NULL;
|
||||||
size_t sz = 256;
|
size_t sz = 256;
|
||||||
|
@ -101,7 +101,7 @@ cstuff_file_get_lines(const char *src, CStuffFileGetLine get_line)
|
||||||
goto e_syscall;
|
goto e_syscall;
|
||||||
|
|
||||||
while ((rs = getdelim(&line, &sz, '\n', f)) != -1) {
|
while ((rs = getdelim(&line, &sz, '\n', f)) != -1) {
|
||||||
if (!get_line(line, rc)) {
|
if (!get_line(line, rs, ctx)) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
goto e_input;
|
goto e_input;
|
||||||
|
|
1
file.h
1
file.h
|
@ -17,6 +17,7 @@
|
||||||
#define CSTUFF_FILE_H_3C3D5EDC_A624_4550_98A4_29AD5A41301D
|
#define CSTUFF_FILE_H_3C3D5EDC_A624_4550_98A4_29AD5A41301D
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include "retcode.h"
|
#include "retcode.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
#define CSTUFF_RETCODE_H_CBA3C16B_88D6_49F4_966D_DBDA727583FE
|
#define CSTUFF_RETCODE_H_CBA3C16B_88D6_49F4_966D_DBDA727583FE
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CSTUFF_MALLOC_ERROR = -2
|
CSTUFF_INPUT_ERROR = -3
|
||||||
|
, CSTUFF_MALLOC_ERROR = -2
|
||||||
, CSTUFF_SYSCALL_ERROR = -1
|
, CSTUFF_SYSCALL_ERROR = -1
|
||||||
, CSTUFF_SUCCESS = 0
|
, CSTUFF_SUCCESS = 0
|
||||||
, CSTUFF_IDLE = 1
|
, CSTUFF_IDLE = 1
|
||||||
|
|
Loading…
Reference in New Issue