aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/analyse.c65
-rw-r--r--src/analyse.h3
-rw-r--r--src/gen-consts.h380
-rw-r--r--src/gen.c121
-rw-r--r--src/main.c6
-rw-r--r--src/parse.c83
-rw-r--r--src/parse.h8
-rw-r--r--src/tok.c10
-rw-r--r--src/tok.h4
9 files changed, 433 insertions, 247 deletions
diff --git a/src/analyse.c b/src/analyse.c
index e454f6c..e0e5fa6 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -7,6 +7,8 @@
struct analyse_result_s analyse(struct parse_result_s pr)
{
struct analyse_result_s ar = {
+ .uses_array = false,
+ .uses_hash = false,
.uses_bool = false,
.uses_string = false,
.uses_id = false,
@@ -20,8 +22,8 @@ struct analyse_result_s analyse(struct parse_result_s pr)
.uses_double = false,
.uses_doublel = false,
};
- struct parse_deftype_s *dtp, *tmp_dtp;
- struct parse_var_s *vtp, *tmp_vtp;
+ struct parse_deftype_s *dcur, *dtmp;
+ struct parse_var_s *vcur, *vtmp;
struct analyse_tree_s *cur;
unsigned i;
@@ -29,17 +31,17 @@ struct analyse_result_s analyse(struct parse_result_s pr)
ar.deftype_tree.is_terminal = false;
if (pr.deftypes != NULL) {
- HASH_ITER(hh, pr.deftypes, dtp, tmp_dtp) {
+ HASH_ITER(hh, pr.deftypes, dcur, dtmp) {
cur = &(ar.deftype_tree);
/* walk down the tree, creating nodes when necessary */
- for (i = 0; dtp->name[i] != '\0'; i++) {
+ for (i = 0; dcur->name[i] != '\0'; i++) {
if (cur->branch_count == 0
|| cur->branch_chars[cur->branch_count - 1]
- != dtp->name[i]
+ != dcur->name[i]
) {
cur->branch_count++;
- cur->branch_chars[cur->branch_count - 1] = dtp->name[i];
+ cur->branch_chars[cur->branch_count - 1] = dcur->name[i];
TRYALLOC(cur->branches[cur->branch_count - 1], 1);
cur = cur->branches[cur->branch_count - 1];
cur->branch_count = 0;
@@ -50,7 +52,7 @@ struct analyse_result_s analyse(struct parse_result_s pr)
}
cur->is_terminal = true;
- strcpy(cur->name, dtp->name);
+ strcpy(cur->name, dcur->name);
}
}
@@ -58,17 +60,17 @@ struct analyse_result_s analyse(struct parse_result_s pr)
ar.var_tree.is_terminal = false;
if (pr.vars != NULL) {
- HASH_ITER(hh, pr.vars, vtp, tmp_vtp) {
+ HASH_ITER(hh, pr.vars, vcur, vtmp) {
cur = &(ar.var_tree);
/* walk down the tree, creating nodes when necessary */
- for (i = 0; vtp->name[i] != '\0'; i++) {
+ for (i = 0; vcur->name[i] != '\0'; i++) {
if (cur->branch_count == 0
|| cur->branch_chars[cur->branch_count - 1]
- != vtp->name[i]
+ != vcur->name[i]
) {
cur->branch_count++;
- cur->branch_chars[cur->branch_count - 1] = vtp->name[i];
+ cur->branch_chars[cur->branch_count - 1] = vcur->name[i];
TRYALLOC(cur->branches[cur->branch_count - 1], 1);
cur = cur->branches[cur->branch_count - 1];
cur->branch_count = 0;
@@ -79,14 +81,25 @@ struct analyse_result_s analyse(struct parse_result_s pr)
}
cur->is_terminal = true;
- strcpy(cur->name, vtp->name);
+ strcpy(cur->name, vcur->name);
}
}
- HASH_ITER(hh, pr.vars, vtp, tmp_vtp) {
- switch (vtp->type
- - (PARSE_TYPE_ARRAY_BOOL * (vtp->type >= PARSE_TYPE_ARRAY_BOOL))
- - (PARSE_TYPE_ARRAY_BOOL * (vtp->type >= PARSE_TYPE_HASH_BOOL))
+ for (i = 0; i < PARSE_TYPE_ARRAY_BOOL; i++)
+ ar.hash_types[i] = false;
+
+ HASH_ITER(hh, pr.vars, vcur, vtmp) {
+ if (vcur->type >= PARSE_TYPE_HASH_BOOL) {
+ ar.uses_hash = true;
+ ar.uses_id = true;
+ ar.hash_types[vcur->type - PARSE_TYPE_HASH_BOOL] = true;
+ } else if (vcur->type >= PARSE_TYPE_ARRAY_BOOL) {
+ ar.uses_array = true;
+ }
+
+ switch (vcur->type
+ - (PARSE_TYPE_ARRAY_BOOL * (vcur->type >= PARSE_TYPE_ARRAY_BOOL))
+ - (PARSE_TYPE_ARRAY_BOOL * (vcur->type >= PARSE_TYPE_HASH_BOOL))
) {
case PARSE_TYPE_BOOL:
ar.uses_bool = true;
@@ -125,16 +138,16 @@ struct analyse_result_s analyse(struct parse_result_s pr)
ar.uses_doublel = true;
break;
default:
- HASH_FIND_STR(pr.deftypes, vtp->deftype_name, dtp);
- assert(dtp != NULL);
- for (i = 0; i < dtp->member_list_len; i++) {
- switch (dtp->member_type_list[i]
- - (PARSE_TYPE_ARRAY_BOOL *
- (dtp->member_type_list[i] >= PARSE_TYPE_ARRAY_BOOL)
- )
- - (PARSE_TYPE_ARRAY_BOOL *
- (dtp->member_type_list[i] >= PARSE_TYPE_HASH_BOOL)
- )
+ HASH_FIND_STR(pr.deftypes, vcur->deftype_name, dcur);
+ assert(dcur != NULL);
+ for (i = 0; i < dcur->member_list_len; i++) {
+ switch (dcur->member_type_list[i]
+ - (PARSE_TYPE_ARRAY_BOOL *
+ (dcur->member_type_list[i] >= PARSE_TYPE_ARRAY_BOOL)
+ )
+ - (PARSE_TYPE_ARRAY_BOOL *
+ (dcur->member_type_list[i] >= PARSE_TYPE_HASH_BOOL)
+ )
) {
case PARSE_TYPE_BOOL:
ar.uses_bool = true;
diff --git a/src/analyse.h b/src/analyse.h
index 19f1b96..77594c2 100644
--- a/src/analyse.h
+++ b/src/analyse.h
@@ -18,6 +18,8 @@ struct analyse_tree_s {
};
struct analyse_result_s {
+ bool uses_array;
+ bool uses_hash;
bool uses_bool;
bool uses_string;
bool uses_id;
@@ -30,6 +32,7 @@ struct analyse_result_s {
bool uses_float;
bool uses_double;
bool uses_doublel;
+ bool hash_types[PARSE_TYPE_ARRAY_BOOL];
struct analyse_tree_s deftype_tree;
struct analyse_tree_s var_tree;
};
diff --git a/src/gen-consts.h b/src/gen-consts.h
index 035e3d2..e3b1b16 100644
--- a/src/gen-consts.h
+++ b/src/gen-consts.h
@@ -1,4 +1,4 @@
-static const char sheader[] =
+static const char sheaderp1[] =
"#ifndef CONFCONF_HEAD_H\n"
"#define CONFCONF_HEAD_H\n"
"\n"
@@ -14,7 +14,7 @@ static const char sheader[] =
" CONFCONF_SUCCESS = 0,\n"
" CONFCONF_ERR_UNEXPECTED_EOF,\n"
" CONFCONF_ERR_UNEXPECTED_TOKEN,\n"
-" CONFCONF_ERR_HASH_KEY_TOO_LONG,\n"
+" CONFCONF_ERR_HASH_DUPLICATE_KEY,\n"
" CONFCONF_ERR_RANGE,\n"
" CONFCONF_ERR_MISSING_VARIABLE,\n"
" CONFCONF_ERR_MEMORY,\n"
@@ -40,7 +40,7 @@ static const char sheader[] =
" float f;\n"
" double d;\n"
" long double dl;\n"
-" };\n"
+" } val;\n"
"};\n"
"\n"
"static int confconf_priv_gcp_file(void *fp)\n"
@@ -111,72 +111,108 @@ static const char sheader[] =
" }\n"
"}\n"
"\n"
+;
+
+static const char sheaderp2[] =
"static enum confconf_result_type confconf_priv_get_tok(\n"
" struct confconf_priv_state *st)\n"
"{\n"
-" size_t len = 0, mlen = 0;\n"
+" size_t len = 0, mlen = CONFCONF_ALLOCWIDTH;\n"
" char *stmp;\n"
" int c;\n"
"\n"
-" st->s = NULL;\n"
+" st->val.s = NULL;\n"
"\n"
" c = (*(st->gcp))(st->fp);\n"
"\n"
" if (c == EOF)\n"
" return CONFCONF_ERR_UNEXPECTED_EOF;\n"
"\n"
+" st->val.s = realloc(st->val.s, mlen);\n"
+" if (st->val.s == NULL)\n"
+" return CONFCONF_ERR_MEMORY;\n"
+" st->val.s[0] = '\\0';\n"
+"\n"
" while (c != ' ' && c != '\\f' && c != '\\n'\n"
" && c != '\\r' && c != '\\t' && c != '\\v'\n"
-" && c != ']' && c != '}' && c != ','\n"
+" && c != ']' && c != '}'\n"
+" && c != '[' && c != '{'\n"
+" && c != ',' && c != ':'\n"
" && c != EOF) {\n"
" if (len == mlen) {\n"
" mlen += CONFCONF_ALLOCWIDTH;\n"
"\n"
" if (mlen < len) {\n"
-" if (st->s != NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" if (st->val.s != NULL) {\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" }\n"
" return CONFCONF_ERR_MEMORY;\n"
" }\n"
"\n"
-" stmp = realloc(st->s, mlen);\n"
+" stmp = realloc(st->val.s, mlen);\n"
" if (stmp == NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" return CONFCONF_ERR_MEMORY;\n"
" }\n"
-" st->s = stmp;\n"
+" st->val.s = stmp;\n"
" }\n"
"\n"
-" st->s[len] = c;\n"
+" st->val.s[len] = c;\n"
" len++;\n"
" c = (*(st->gcp))(st->fp);\n"
" }\n"
"\n"
+" if (st->val.s[0] == '\\0') {\n"
+" st->val.s[0] = c;\n"
+" len++;\n"
+" if (len == mlen) {\n"
+" mlen += CONFCONF_ALLOCWIDTH;\n"
+"\n"
+" if (mlen < len) {\n"
+" if (st->val.s != NULL) {\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
+" }\n"
+" return CONFCONF_ERR_MEMORY;\n"
+" }\n"
+"\n"
+" stmp = realloc(st->val.s, mlen);\n"
+" if (stmp == NULL) {\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
+" return CONFCONF_ERR_MEMORY;\n"
+" }\n"
+" st->val.s = stmp;\n"
+" }\n"
+" st->val.s[1] = '\\0';\n"
+" return CONFCONF_SUCCESS;\n"
+" }\n"
+"\n"
" if (len == mlen) {\n"
" mlen += CONFCONF_ALLOCWIDTH;\n"
"\n"
" if (mlen < len) {\n"
-" if (st->s != NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" if (st->val.s != NULL) {\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" }\n"
" return CONFCONF_ERR_MEMORY;\n"
" }\n"
"\n"
-" stmp = realloc(st->s, mlen);\n"
+" stmp = realloc(st->val.s, mlen);\n"
" if (stmp == NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" return CONFCONF_ERR_MEMORY;\n"
" }\n"
-" st->s = stmp;\n"
+" st->val.s = stmp;\n"
" }\n"
"\n"
" (*(st->ugcp))(c, st->fp);\n"
"\n"
-" st->s[len] = '\\0';\n"
+" st->val.s[len] = '\\0';\n"
"\n"
" st->col += len;\n"
" st->byte += len;\n"
@@ -184,6 +220,50 @@ static const char sheader[] =
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
+"static enum confconf_result_type confconf_priv_get_id(\n"
+" struct confconf_priv_state *st)\n"
+"{\n"
+" enum confconf_result_type r;\n"
+" char *off;\n"
+"\n"
+" r = confconf_priv_get_tok(st);\n"
+"\n"
+" if (r != CONFCONF_SUCCESS)\n"
+" return r;\n"
+"\n"
+" for (off = st->val.s; *off != '\\0'; off++) {\n"
+" if (*off >= '0' && *off <= '9')\n"
+" continue;\n"
+" if (\n"
+" *off == 'a' || *off == 'b' || *off == 'c' ||\n"
+" *off == 'd' || *off == 'e' || *off == 'f' ||\n"
+" *off == 'g' || *off == 'h' || *off == 'i' ||\n"
+" *off == 'j' || *off == 'k' || *off == 'l' ||\n"
+" *off == 'm' || *off == 'n' || *off == 'o' ||\n"
+" *off == 'p' || *off == 'q' || *off == 'r' ||\n"
+" *off == 's' || *off == 't' || *off == 'u' ||\n"
+" *off == 'v' || *off == 'w' || *off == 'x' ||\n"
+" *off == 'y' || *off == 'z' ||\n"
+" *off == 'A' || *off == 'B' || *off == 'C' ||\n"
+" *off == 'D' || *off == 'E' || *off == 'F' ||\n"
+" *off == 'G' || *off == 'H' || *off == 'I' ||\n"
+" *off == 'J' || *off == 'K' || *off == 'L' ||\n"
+" *off == 'M' || *off == 'N' || *off == 'O' ||\n"
+" *off == 'P' || *off == 'Q' || *off == 'R' ||\n"
+" *off == 'S' || *off == 'T' || *off == 'U' ||\n"
+" *off == 'V' || *off == 'W' || *off == 'X' ||\n"
+" *off == 'Y' || *off == 'Z' ||\n"
+" *off == '-' || *off == '_'\n"
+" ) {\n"
+" continue;\n"
+" }\n"
+" \n"
+" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
+"\n"
+" return CONFCONF_SUCCESS;\n"
+"}\n"
+"\n"
"#endif\n"
"\n"
;
@@ -203,7 +283,7 @@ static const char sbool[] =
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
-" off = st->s;\n"
+" off = st->val.s;\n"
"\n"
" if (*off == 't' || *off == 'T') {\n"
" if (\n"
@@ -212,8 +292,8 @@ static const char sbool[] =
" (*(++off) == 'e' || *off == 'E') &&\n"
" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->s);\n"
-" st->b = true;\n"
+" free(st->val.s);\n"
+" st->val.b = true;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
@@ -226,8 +306,8 @@ static const char sbool[] =
" (*(++off) == 's' || *off == 'S') &&\n"
" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->s);\n"
-" st->b = true;\n"
+" free(st->val.s);\n"
+" st->val.b = true;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
@@ -239,8 +319,8 @@ static const char sbool[] =
" (*(++off) == 'o' || *off == 'O') &&\n"
" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->s);\n"
-" st->b = false;\n"
+" free(st->val.s);\n"
+" st->val.b = false;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
@@ -255,8 +335,8 @@ static const char sbool[] =
" (*(++off) == 'e' || *off == 'E') &&\n"
" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->s);\n"
-" st->b = false;\n"
+" free(st->val.s);\n"
+" st->val.b = false;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
@@ -268,8 +348,8 @@ static const char sbool[] =
" (*(off+1) == 'n' || *(off+1) == 'N') &&\n"
" (*(off+2) == '\\0')\n"
" ) {\n"
-" free(st->s);\n"
-" st->b = true;\n"
+" free(st->val.s);\n"
+" st->val.b = true;\n"
" return CONFCONF_SUCCESS;\n"
" }\n"
"\n"
@@ -278,8 +358,8 @@ static const char sbool[] =
" (*(++off) == 'f' || *off == 'F') &&\n"
" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->s);\n"
-" st->b = false;\n"
+" free(st->val.s);\n"
+" st->val.b = false;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
@@ -305,7 +385,7 @@ static const char sstring[] =
" int c, endc;\n"
" bool escape = false;\n"
"\n"
-" st->s = NULL;\n"
+" st->val.s = NULL;\n"
"\n"
" c = (*(st->gcp))(st->fp);\n"
" if (c == EOF)\n"
@@ -342,9 +422,9 @@ static const char sstring[] =
" }\n"
"\n"
" if (c == EOF) {\n"
-" if (st->s != NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" if (st->val.s != NULL) {\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" }\n"
" return CONFCONF_ERR_UNEXPECTED_EOF;\n"
" }\n"
@@ -353,23 +433,23 @@ static const char sstring[] =
" mlen += CONFCONF_ALLOCWIDTH;\n"
"\n"
" if (mlen < len) {\n"
-" if (st->s != NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" if (st->val.s != NULL) {\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" }\n"
" return CONFCONF_ERR_MEMORY;\n"
" }\n"
"\n"
-" stmp = realloc(st->s, mlen);\n"
+" stmp = realloc(st->val.s, mlen);\n"
" if (stmp == NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" return CONFCONF_ERR_MEMORY;\n"
" }\n"
-" st->s = stmp;\n"
+" st->val.s = stmp;\n"
" }\n"
"\n"
-" st->s[len] = c;\n"
+" st->val.s[len] = c;\n"
" len++;\n"
" }\n"
"\n"
@@ -377,75 +457,23 @@ static const char sstring[] =
" mlen += CONFCONF_ALLOCWIDTH;\n"
"\n"
" if (mlen < len) {\n"
-" if (st->s != NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" if (st->val.s != NULL) {\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" }\n"
" return CONFCONF_ERR_MEMORY;\n"
" }\n"
"\n"
-" stmp = realloc(st->s, mlen);\n"
+" stmp = realloc(st->val.s, mlen);\n"
" if (stmp == NULL) {\n"
-" free(st->s);\n"
-" st->s = NULL;\n"
+" free(st->val.s);\n"
+" st->val.s = NULL;\n"
" return CONFCONF_ERR_MEMORY;\n"
" }\n"
-" st->s = stmp;\n"
-" }\n"
-"\n"
-" st->s[len] = '\\0';\n"
-" return CONFCONF_SUCCESS;\n"
-"}\n"
-"\n"
-"#endif\n"
-"\n"
-;
-
-static const char sid[] =
-"#ifndef CONFCONF_ID_H\n"
-"#define CONFCONF_ID_H\n"
-"\n"
-"static enum confconf_result_type confconf_priv_get_id(\n"
-" struct confconf_priv_state *st)\n"
-"{\n"
-" enum confconf_result_type r;\n"
-" char *off;\n"
-"\n"
-" r = confconf_priv_get_tok(st);\n"
-"\n"
-" if (r != CONFCONF_SUCCESS)\n"
-" return r;\n"
-"\n"
-" for (off = st->s; *off != '\\0'; off++) {\n"
-" if (*off >= '0' && *off <= '9')\n"
-" continue;\n"
-" if (\n"
-" *off == 'a' || *off == 'b' || *off == 'c' ||\n"
-" *off == 'd' || *off == 'e' || *off == 'f' ||\n"
-" *off == 'g' || *off == 'h' || *off == 'i' ||\n"
-" *off == 'j' || *off == 'k' || *off == 'l' ||\n"
-" *off == 'm' || *off == 'n' || *off == 'o' ||\n"
-" *off == 'p' || *off == 'q' || *off == 'r' ||\n"
-" *off == 's' || *off == 't' || *off == 'u' ||\n"
-" *off == 'v' || *off == 'w' || *off == 'x' ||\n"
-" *off == 'y' || *off == 'z' ||\n"
-" *off == 'A' || *off == 'B' || *off == 'C' ||\n"
-" *off == 'D' || *off == 'E' || *off == 'F' ||\n"
-" *off == 'G' || *off == 'H' || *off == 'I' ||\n"
-" *off == 'J' || *off == 'K' || *off == 'L' ||\n"
-" *off == 'M' || *off == 'N' || *off == 'O' ||\n"
-" *off == 'P' || *off == 'Q' || *off == 'R' ||\n"
-" *off == 'S' || *off == 'T' || *off == 'U' ||\n"
-" *off == 'V' || *off == 'W' || *off == 'X' ||\n"
-" *off == 'Y' || *off == 'Z' ||\n"
-" *off == '-' || *off == '_'\n"
-" ) {\n"
-" continue;\n"
-" }\n"
-" \n"
-" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" st->val.s = stmp;\n"
" }\n"
"\n"
+" st->val.s[len] = '\\0';\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -473,7 +501,7 @@ static const char sint[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" i = strtol(st->s, &check, 0);\n"
+" i = strtol(st->val.s, &check, 0);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -484,8 +512,8 @@ static const char sint[] =
" if (i > INT_MAX || i < INT_MIN)\n"
" return CONFCONF_ERR_RANGE;\n"
"\n"
-" free(st->s);\n"
-" st->i = (int)i;\n"
+" free(st->val.s);\n"
+" st->val.i = (int)i;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -512,7 +540,7 @@ static const char sintl[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" il = strtol(st->s, &check, 0);\n"
+" il = strtol(st->val.s, &check, 0);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -520,8 +548,8 @@ static const char sintl[] =
" if (*check != '\\0')\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
"\n"
-" free(st->s);\n"
-" st->il = il;\n"
+" free(st->val.s);\n"
+" st->val.il = il;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -548,7 +576,7 @@ static const char sintll[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" ill = strtoll(st->s, &check, 0);\n"
+" ill = strtoll(st->val.s, &check, 0);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -556,8 +584,8 @@ static const char sintll[] =
" if (*check != '\\0')\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
"\n"
-" free(st->s);\n"
-" st->ill = ill;\n"
+" free(st->val.s);\n"
+" st->val.ill = ill;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -585,7 +613,7 @@ static const char suint[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" u = strtoul(st->s, &check, 0);\n"
+" u = strtoul(st->val.s, &check, 0);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -596,8 +624,8 @@ static const char suint[] =
" if (u > UINT_MAX)\n"
" return CONFCONF_ERR_RANGE;\n"
"\n"
-" free(st->s);\n"
-" st->u = (unsigned)u;\n"
+" free(st->val.s);\n"
+" st->val.u = (unsigned)u;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -624,7 +652,7 @@ static const char suintl[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" ul = strtoul(st->s, &check, 0);\n"
+" ul = strtoul(st->val.s, &check, 0);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -632,8 +660,8 @@ static const char suintl[] =
" if (*check != '\\0')\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
"\n"
-" free(st->s);\n"
-" st->ul = ul;\n"
+" free(st->val.s);\n"
+" st->val.ul = ul;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -660,7 +688,7 @@ static const char suintll[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" ull = strtoull(st->s, &check, 0);\n"
+" ull = strtoull(st->val.s, &check, 0);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -668,8 +696,8 @@ static const char suintll[] =
" if (*check != '\\0')\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
"\n"
-" free(st->s);\n"
-" st->ull = ull;\n"
+" free(st->val.s);\n"
+" st->val.ull = ull;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -696,7 +724,7 @@ static const char sfloat[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" f = strtof(st->s, &check);\n"
+" f = strtof(st->val.s, &check);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -704,8 +732,8 @@ static const char sfloat[] =
" if (*check != '\\0')\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
"\n"
-" free(st->s);\n"
-" st->f = f;\n"
+" free(st->val.s);\n"
+" st->val.f = f;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -732,7 +760,7 @@ static const char sdouble[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" d = strtod(st->s, &check);\n"
+" d = strtod(st->val.s, &check);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -740,8 +768,8 @@ static const char sdouble[] =
" if (*check != '\\0')\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
"\n"
-" free(st->s);\n"
-" st->d = d;\n"
+" free(st->val.s);\n"
+" st->val.d = d;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -768,7 +796,7 @@ static const char sdoublel[] =
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" dl = strtold(st->s, &check);\n"
+" dl = strtold(st->val.s, &check);\n"
"\n"
" if (errno == ERANGE)\n"
" return CONFCONF_ERR_RANGE;\n"
@@ -776,11 +804,95 @@ static const char sdoublel[] =
" if (*check != '\\0')\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
"\n"
-" free(st->s);\n"
-" st->dl = dl;\n"
+" free(st->val.s);\n"
+" st->val.dl = dl;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
"#endif\n"
"\n"
;
+
+static const char shash[] =
+"#ifndef CONFCONF_HASH_H\n"
+"#define CONFCONF_HASH_H\n"
+"\n"
+"#include <uthash.h>\n"
+"\n"
+"#define CONFCONF_PRIV_GET_HASH_main(h, htmp, fun, mem) \\\n"
+" do { \\\n"
+" int c; \\\n"
+" char *hash_swp; \\\n"
+" (h) = NULL; \\\n"
+" c = (*(st.gcp))(st.fp); \\\n"
+" if (c != '[') { \\\n"
+" if (c == EOF) { \\\n"
+" r = CONFCONF_ERR_UNEXPECTED_EOF; \\\n"
+" st.val.s = NULL; \\\n"
+" break; \\\n"
+" } \\\n"
+" (*(st.ugcp))(c, st.fp); \\\n"
+" confconf_priv_get_tok(&st); \\\n"
+" r = CONFCONF_ERR_UNEXPECTED_TOKEN; \\\n"
+" } \\\n"
+" st.col++; \\\n"
+" st.byte++; \\\n"
+" while (1) { \\\n"
+" confconf_priv_eat_space(&st); \\\n"
+" r = confconf_priv_get_id(&st); \\\n"
+" if (r != CONFCONF_SUCCESS) \\\n"
+" break; \\\n"
+" HASH_FIND_STR((h), st.val.s, (htmp)); \\\n"
+" if ((htmp) != NULL) { \\\n"
+" r = CONFCONF_ERR_HASH_DUPLICATE_KEY; \\\n"
+" break; \\\n"
+" } \\\n"
+" hash_swp = st.val.s; \\\n"
+" confconf_priv_eat_space(&st); \\\n"
+" c = (*(st.gcp))(st.fp); \\\n"
+" if (c == ':') { \\\n"
+" st.col++; \\\n"
+" st.byte++; \\\n"
+" confconf_priv_eat_space(&st); \\\n"
+" } else { \\\n"
+" (*(st.ugcp))(c, st.fp); \\\n"
+" free(hash_swp); \\\n"
+" r = confconf_priv_get_tok(&st); \\\n"
+" if (r == CONFCONF_SUCCESS) \\\n"
+" r = CONFCONF_ERR_UNEXPECTED_TOKEN; \\\n"
+" break; \\\n"
+" } \\\n"
+" r = confconf_priv_get_ ## fun (&st); \\\n"
+" if (r != CONFCONF_SUCCESS) { \\\n"
+" free(hash_swp); \\\n"
+" break; \\\n"
+" } \\\n"
+" (htmp) = malloc(sizeof(*(htmp))); \\\n"
+" if ((htmp) == NULL) { \\\n"
+" free(hash_swp); \\\n"
+" r = CONFCONF_ERR_MEMORY; \\\n"
+" break; \\\n"
+" } \\\n"
+" (htmp)->key = hash_swp; \\\n"
+" (htmp)->val.mem = st.val.mem; \\\n"
+" HASH_ADD_STR((h), key, (htmp)); \\\n"
+" confconf_priv_eat_space(&st); \\\n"
+" c = (*(st.gcp))(st.fp); \\\n"
+" if (c == ',') { \\\n"
+" st.col++; \\\n"
+" st.byte++; \\\n"
+" confconf_priv_eat_space(&st); \\\n"
+" } else if (c == ']') { \\\n"
+" st.col++; \\\n"
+" st.byte++; \\\n"
+" r = CONFCONF_SUCCESS; \\\n"
+" break; \\\n"
+" } else { \\\n"
+" (*(st.ugcp))(c, st.fp); \\\n"
+" } \\\n"
+" } \\\n"
+" } while (0)\n"
+"\n"
+"#endif\n"
+"\n"
+;
diff --git a/src/gen.c b/src/gen.c
index fdad6e8..d2c1aeb 100644
--- a/src/gen.c
+++ b/src/gen.c
@@ -1,8 +1,10 @@
#include "gen.h"
#include "version.h"
+#include "parse.h"
#include <time.h>
+#include <assert.h>
#include "gen-consts.h"
@@ -11,20 +13,29 @@ void gen(FILE *f, struct parse_result_s pr, struct analyse_result_s ar)
time_t t;
struct tm *ti;
+ struct parse_deftype_s *dcur, *dtmp;
+ struct parse_var_s *vcur, *vtmp;
+
+ unsigned i;
+
time(&t);
ti = localtime(&t);
+ /********
+ * HEAD *
+ ********/
+
fprintf(f, "/* generated by %s on %04d-%02d-%02d */\n",
VERSION, ti->tm_year + 1900, ti->tm_mon + 1, ti->tm_mday);
- fprintf(f, sheader);
+ fprintf(f, sheaderp1);
+ fprintf(f, sheaderp2);
+ /* built-in types */
if (ar.uses_bool)
fprintf(f, sbool);
if (ar.uses_string)
fprintf(f, sstring);
- if (ar.uses_id)
- fprintf(f, sid);
if (ar.uses_int)
fprintf(f, sint);
if (ar.uses_intl)
@@ -43,5 +54,109 @@ void gen(FILE *f, struct parse_result_s pr, struct analyse_result_s ar)
fprintf(f, sdouble);
if (ar.uses_doublel)
fprintf(f, sdoublel);
+ if (ar.uses_hash)
+ fprintf(f, shash);
+
+ /********
+ * BODY *
+ ********/
+
+ fprintf(f,
+ "#ifndef CONFCONF_BODY_%s_H\n"
+ "#define CONFCONF_BODY_%s_H\n\n",
+ pr.suffix, pr.suffix
+ );
+
+ /* structs */
+ HASH_ITER(hh, pr.deftypes, dcur, dtmp) {
+ fprintf(f, "struct confconf_type_%s_%s {\n",
+ dcur->name, pr.suffix);
+
+ for (i = 0; i < dcur->member_list_len; i++) {
+ switch (dcur->member_type_list[i]) {
+ case PARSE_TYPE_BOOL:
+ fprintf(f, " bool ");
+ break;
+ case PARSE_TYPE_STRING:
+ fprintf(f, " char *");
+ break;
+ case PARSE_TYPE_ID:
+ fprintf(f, " char *");
+ break;
+ case PARSE_TYPE_INT:
+ fprintf(f, " int ");
+ break;
+ case PARSE_TYPE_INTL:
+ fprintf(f, " long int ");
+ break;
+ case PARSE_TYPE_INTLL:
+ fprintf(f, " long long int ");
+ break;
+ case PARSE_TYPE_UINT:
+ fprintf(f, " unsigned ");
+ break;
+ case PARSE_TYPE_UINTL:
+ fprintf(f, " long unsigned ");
+ break;
+ case PARSE_TYPE_UINTLL:
+ fprintf(f, " long long unsigned ");
+ break;
+ case PARSE_TYPE_FLOAT:
+ fprintf(f, " float ");
+ break;
+ case PARSE_TYPE_DOUBLE:
+ fprintf(f, " double ");
+ break;
+ case PARSE_TYPE_DOUBLEL:
+ fprintf(f, " long double ");
+ break;
+ default:
+ assert(0);
+ }
+
+ fprintf(f, "%s;\n", dcur->member_name_list[i]);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* array */
+
+ /* hash */
+ if (ar.uses_hash) {
+ fprintf(f,
+ "#include <uthash.h>\n\n"
+ "struct confconf_hash_%s {\n"
+ " char *key;\n"
+ " union {\n"
+ "%s%s%s%s%s%s%s%s%s%s%s",
+ pr.suffix,
+ (ar.uses_bool ? " bool b;\n" : ""),
+ (ar.uses_string ? " char *s;\n" : ""),
+ (ar.uses_int ? " int i;\n" : ""),
+ (ar.uses_intl ? " long int il;\n" : ""),
+ (ar.uses_intll ? " long long int ill;\n" : ""),
+ (ar.uses_uint ? " unsigned u;\n" : ""),
+ (ar.uses_uintl ? " long unsigned ul;\n" : ""),
+ (ar.uses_uintll ? " long long unsigned ull;\n" : ""),
+ (ar.uses_float ? " float f;\n" : ""),
+ (ar.uses_double ? " double d;\n" : ""),
+ (ar.uses_doublel ? " long double dl;\n" : "")
+ );
+ HASH_ITER(hh, pr.deftypes, dcur, dtmp) {
+ if (dcur->is_used) {
+ fprintf(f, " %s confconf_type_%s_%s type_%s;\n",
+ (dcur->is_union ? "union" : "struct"),
+ dcur->name, pr.suffix, dcur->name);
+ }
+ }
+ fprintf(f,
+ " } val;\n"
+ " UT_hash_handle hh;\n"
+ "};\n\n"
+ );
+
+ }
+ fprintf(f, "#endif\n");
}
diff --git a/src/main.c b/src/main.c
index 4ec0e75..16fd3d7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -29,7 +29,6 @@ int main(int argc, char **argv)
FILE *fo = stdout;
FILE *fi = stdin;
const char *finame = "stdin";
- const char *foname;
struct parse_result_s pr;
struct analyse_result_s ar;
@@ -42,9 +41,8 @@ int main(int argc, char **argv)
}
if (opt_outfile_str() != NULL) {
- foname = opt_infile_str();
- fo = fopen(foname, "w");
- TRY(fo != NULL, "could not write to file `%s`", foname);
+ fo = fopen(opt_outfile_str(), "w");
+ TRY(fo != NULL, "could not write to file `%s`", opt_outfile_str());
}
pr = parse(fi, finame);
diff --git a/src/parse.c b/src/parse.c
index cb459e5..57db35c 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -172,10 +172,11 @@ static void sub_parse_deftype(size_t line, size_t col, bool is_union)
type = sub_parse_type();
- if (type == PARSE_TYPE_DEFTYPE
- || type == PARSE_TYPE_ARRAY_DEFTYPE
- || type == PARSE_TYPE_HASH_DEFTYPE
- ) {
+ if (type >= PARSE_TYPE_ARRAY_BOOL) {
+ ERR_AT(t.line, t.col, "defined types may not contain arrays or hashes");
+ }
+
+ if (type == PARSE_TYPE_DEFTYPE) {
t = tok_get();
ERR_AT(t.line, t.col, "defined types may not contain other defined types");
}
@@ -231,11 +232,11 @@ static bool sub_parse_op(void)
sub_parse_deftype(t.line, t.col, true);
return true;
- case TOK_OP_FUN_SUF:
- if (r.fun_suf_seen) {
+ case TOK_OP_SUFFIX:
+ if (r.suffix_seen) {
WARN_AT(t.line, t.col,
"function-suffix redefined (previous value was `%s`)",
- r.fun_suf);
+ r.suffix);
}
t = tok_get();
@@ -243,52 +244,9 @@ static bool sub_parse_op(void)
if (t.type != TOK_ID)
ERR_AT(t.line, t.col, "invalid function-suffix `%s`", t.val);
- strcpy(r.fun_suf, t.val);
-
- r.fun_suf_seen = true;
-
- return true;
-
- case TOK_OP_HKEY_SIZE:
- if (r.hkey_size_seen) {
- WARN_AT(t.line, t.col,
- "hkey_size redefined (previous value was %lu)",
- r.hkey_size);
- }
-
- t = tok_get();
- ERR_END(t);
- if (t.type != TOK_UINT)
- ERR_AT(t.line, t.col, "invalid hkey_size `%s`", t.val);
-
- errno = EILSEQ;
- r.hkey_size = strtoul(t.val, NULL, 10);
-
- if (errno == ERANGE)
- ERR_AT(t.line, t.col, "hkey_size `%s` too large", t.val);
-
- if (r.hkey_size == 0)
- ERR_AT(t.line, t.col, "hkey_size cannot be 0");
-
- r.hkey_size_seen = true;
-
- return true;
-
- case TOK_OP_HKEY_NAME:
- if (r.hkey_name_seen) {
- ERR_AT(t.line, t.col,
- "hkey_name redefined (previous value was `%s`)",
- r.hkey_name);
- }
-
- t = tok_get();
- ERR_END(t);
- if (t.type != TOK_ID)
- ERR_AT(t.line, t.col, "invalid hkey_name `%s`", t.val);
-
- strcpy(r.hkey_name, t.val);
+ strcpy(r.suffix, t.val);
- r.hkey_name_seen = true;
+ r.suffix_seen = true;
return true;
@@ -374,11 +332,7 @@ struct parse_result_s parse(FILE *f, const char *fname)
struct parse_var_s *vcur, *vtmp;
struct parse_deftype_s *dcur, *dtmp;
- r.hkey_size = 16;
- strcpy(r.hkey_name, "key");
- r.hkey_name_seen = false;
- r.hkey_size_seen = false;
- r.fun_suf_seen = false;
+ r.suffix_seen = false;
r.deftypes = NULL;
r.vars = NULL;
curfname = fname;
@@ -420,12 +374,12 @@ struct parse_result_s parse(FILE *f, const char *fname)
HASH_ITER(hh, r.deftypes, dcur, dtmp) {
if (!dcur->is_used) {
WARN_AT(dcur->line, dcur->col,
- "struct `%s` defined but not used",
+ "type `%s` defined but not used",
dcur->name);
}
}
- if (!r.fun_suf_seen) {
+ if (!r.suffix_seen) {
j = 0;
@@ -434,24 +388,23 @@ struct parse_result_s parse(FILE *f, const char *fname)
j = i + (fname[i] == '/' || fname[i] == '\\');
- for (i = j; fname[i] != '\0' && fname[i] != '.'
- && i - j < r.hkey_size; i++) {
+ for (i = j; fname[i] != '\0' && fname[i] != '.'; i++) {
if (!isalnum(fname[i]) && fname[i] != '_') {
fprintf(stderr, "\x1B[1m%s:\x1B[0m ", fname);
ERR("no function suffix specified, and could not generate one");
}
- r.fun_suf[i - j] = fname[i];
+ r.suffix[i - j] = fname[i];
}
- r.fun_suf[i - j] = '\0';
+ r.suffix[i - j] = '\0';
- if (r.fun_suf[0] == '\0') {
+ if (r.suffix[0] == '\0') {
fprintf(stderr, "\x1B[1m%s:\x1B[0m ", fname);
ERR("no function suffix specified, and could not generate one");
}
fprintf(stderr, "\x1B[1m%s:\x1B[0m ", fname);
- WARN("no function suffix specified. using `%s`...", r.fun_suf);
+ WARN("no function suffix specified. using `%s`...", r.suffix);
}
HASH_SORT(r.deftypes, sub_sort_deftypes);
diff --git a/src/parse.h b/src/parse.h
index b9f2ceb..094d808 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -78,12 +78,8 @@ struct parse_var_s {
};
struct parse_result_s {
- unsigned long hkey_size;
- bool hkey_size_seen;
- char hkey_name[TOK_MAX_LEN];
- bool hkey_name_seen;
- char fun_suf[TOK_MAX_LEN];
- bool fun_suf_seen;
+ char suffix[TOK_MAX_LEN];
+ bool suffix_seen;
struct parse_deftype_s *deftypes;
struct parse_var_s *vars;
};
diff --git a/src/tok.c b/src/tok.c
index 04d1eb8..177507a 100644
--- a/src/tok.c
+++ b/src/tok.c
@@ -70,11 +70,9 @@ static void sub_match_op(void)
enum tok_type_e type;
char name[(32 < TOK_MAX_LEN ? 32 : TOK_MAX_LEN)];
} ops[] = {
- { true, TOK_OP_STRUCT, ".struct" },
- { true, TOK_OP_UNION, ".union" },
- { true, TOK_OP_HKEY_SIZE, ".hash-key-size" },
- { true, TOK_OP_HKEY_NAME, ".hash-key-name" },
- { true, TOK_OP_FUN_SUF, ".function-suffix" },
+ { true, TOK_OP_SUFFIX, ".suffix" },
+ { true, TOK_OP_STRUCT, ".struct" },
+ { true, TOK_OP_UNION, ".union" },
};
unsigned i, j;
bool again;
@@ -97,7 +95,7 @@ static void sub_match_op(void)
val[vlen] = c;
vlen++;
- for (j = 0; j < 5; j++) {
+ for (j = 0; j < 3; j++) {
if (!ops[j].possible)
continue;
diff --git a/src/tok.h b/src/tok.h
index 08099b3..7558508 100644
--- a/src/tok.h
+++ b/src/tok.h
@@ -13,11 +13,9 @@ enum tok_type_e {
TOK_BANG,
TOK_QMARK,
TOK_ASTERISK,
+ TOK_OP_SUFFIX,
TOK_OP_STRUCT,
TOK_OP_UNION,
- TOK_OP_HKEY_SIZE,
- TOK_OP_HKEY_NAME,
- TOK_OP_FUN_SUF,
TOK_UINT,
TOK_ID,
TOK_UNKNWN,