aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorkatherine <ageha@airen-no-jikken.icu>2019-07-10 20:24:08 -0700
committerkatherine <ageha@airen-no-jikken.icu>2019-07-10 20:24:08 -0700
commit06cb82a8ccc3587dff728321dff5416b18090483 (patch)
tree95dc02df244856b5ede95a3a1a44ea756e850203 /src
parent34271c906a2de43a68d2fa764d31e6f5b2c3299f (diff)
downloadconfconf-06cb82a8ccc3587dff728321dff5416b18090483.tar.gz
implement deftype get
Diffstat (limited to 'src')
-rw-r--r--src/analyse.c273
-rw-r--r--src/analyse.h22
-rw-r--r--src/gen-consts.h691
-rw-r--r--src/gen.c788
-rw-r--r--src/gen.h2
-rw-r--r--src/main.c33
-rw-r--r--src/opt.c42
-rw-r--r--src/parse.c395
-rw-r--r--src/parse.h11
-rw-r--r--src/tok.c4
10 files changed, 1428 insertions, 833 deletions
diff --git a/src/analyse.c b/src/analyse.c
index 416b10a..e5d1cb9 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -1,149 +1,244 @@
-#include "err.h"
#include "analyse.h"
+#include "err.h"
+
#include <assert.h>
#include <string.h>
-struct analyse_result_s analyse(struct parse_result_s pr)
+static void sub_trie_insert(struct analyse_trie_s *t,
+ const char *s, char *sv)
+{
+ const char *si = s;
+ struct analyse_trie_s *parent = NULL;
+ unsigned i;
+
+ /* walk down the trie, creating nodes when necessary */
+ for (; *si != '\0'; si++) {
+ for (i = 0; i < t->branch_count && *si != t->branch_chars[i]; i++);
+ if (t->branch_count == 0
+ || i == t->branch_count
+ ) {
+ t->branch_count++;
+ t->branch_chars[t->branch_count - 1] = *si;
+ TRYALLOC(t->branches[t->branch_count - 1], 1);
+ parent = t;
+ t = t->branches[t->branch_count - 1];
+ t->parent = parent;
+ t->branch_count = 0;
+ t->sval = NULL;
+ } else {
+ t = t->branches[i];
+ }
+ }
+
+ TRYALLOC(t->sval, strlen(sv) + 1);
+ strcpy(t->sval, sv);
+}
+
+/* tries used to generate static jump-based token matching */
+static inline void sub_build_tries(struct parse_result_s *pr,
+ struct analyse_result_s *ar)
{
- struct analyse_result_s ar = {
- .uses_hash = false,
- .uses_array = false,
- };
struct parse_deftype_s *dcur, *dtmp;
struct parse_var_s *vcur, *vtmp;
- struct analyse_tree_s *cur;
- unsigned i;
+ unsigned i, j;
+ /* dtype sval == TOK_MAX_LEN
+ * dtype member == TOK_MAX_LEN
+ * suffix == TOK_MAX_LEN
+ * 32 == padding for "CONFCONF_TYPE_" + "_" + "_" + "\0" */
+ char sbuf[TOK_MAX_LEN * 3 + 32];
+
+ /* variable trie */
+ ar->var_trie.branch_count = 0;
+ ar->var_trie.sval = NULL;
+ ar->var_trie.parent = NULL;
+
+ if (pr->vars != NULL) {
+ HASH_ITER(hh, pr->vars, vcur, vtmp) {
+ sprintf(sbuf, "%s", vcur->name);
+ sub_trie_insert(&(ar->var_trie), vcur->name, sbuf);
+ }
+ }
+
+ ar->deftype_mem_tries = NULL;
+ if (pr->deftypes != NULL) {
+ TRYALLOC(
+ ar->deftype_mem_tries,
+ HASH_COUNT(pr->deftypes)
+ );
- /***************
- * BUILD TREES *
- ***************/
+ ar->deftype_mem_trie_count = HASH_COUNT(pr->deftypes);
- ar.deftype_tree.branch_count = 0;
- ar.deftype_tree.is_terminal = false;
+ i = 0;
+ HASH_ITER(hh, pr->deftypes, dcur, dtmp) {
+ ar->deftype_mem_tries[i].branch_count = 0;
+ ar->deftype_mem_tries[i].sval = NULL;
+ ar->deftype_mem_tries[i].parent = NULL;
- if (pr.deftypes != NULL) {
- HASH_ITER(hh, pr.deftypes, dcur, dtmp) {
- if (!dcur->is_used)
+ if (!dcur->is_used) {
+ i++;
continue;
+ }
+
+ /* union types */
+ if (dcur->type == PARSE_DEFTYPE_UNION) {
+ for (j = 0; j < dcur->member_list_len; j++) {
+ sprintf(sbuf, "%u", j);
- cur = &(ar.deftype_tree);
-
- /* walk down the tree, creating nodes when necessary */
- for (i = 0; dcur->name[i] != '\0'; i++) {
- if (cur->branch_count == 0
- || cur->branch_chars[cur->branch_count - 1]
- != dcur->name[i]
- ) {
- cur->branch_count++;
- 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;
- cur->is_terminal = false;
- } else {
- cur = cur->branches[cur->branch_count - 1];
+ sub_trie_insert(
+ &(ar->deftype_mem_tries[i]),
+ dcur->member_name_list[j],
+ sbuf
+ );
}
}
- cur->is_terminal = true;
- strcpy(cur->name, dcur->name);
- }
- }
-
- ar.var_tree.branch_count = 0;
- ar.var_tree.is_terminal = false;
-
- if (pr.vars != NULL) {
- HASH_ITER(hh, pr.vars, vcur, vtmp) {
- cur = &(ar.var_tree);
-
- /* walk down the tree, creating nodes when necessary */
- for (i = 0; vcur->name[i] != '\0'; i++) {
- if (cur->branch_count == 0
- || cur->branch_chars[cur->branch_count - 1]
- != vcur->name[i]
- ) {
- cur->branch_count++;
- 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;
- cur->is_terminal = false;
- } else {
- cur = cur->branches[cur->branch_count - 1];
+ /* enum mems */
+ if (dcur->type == PARSE_DEFTYPE_ENUM) {
+ for (j = 0; j < dcur->member_list_len; j++) {
+ sprintf(sbuf,
+ "CONFCONF_TYPE_%s_%s_%s",
+ dcur->name,
+ dcur->member_name_list[j],
+ pr->suffix
+ );
+ sub_trie_insert(
+ &(ar->deftype_mem_tries[i]),
+ dcur->member_name_list[j],
+ sbuf
+ );
}
}
- cur->is_terminal = true;
- strcpy(cur->name, vcur->name);
+ i++;
}
}
+}
-
- /************************
- * CALCULATE USED TYPES *
- ************************/
+static inline void sub_calculate_used_types(struct parse_result_s *pr,
+ struct analyse_result_s *ar)
+{
+ struct parse_deftype_s *dcur, *dtmp;
+ struct parse_var_s *vcur, *vtmp;
+ unsigned i;
for (i = PARSE_TYPE_BOOL; i < PARSE_TYPE_HASH_DEFTYPE; i++)
- ar.uses_type[i] = false;
+ ar->uses_type[i] = false;
- HASH_ITER(hh, pr.deftypes, dcur, dtmp) {
+ HASH_ITER(hh, pr->deftypes, dcur, dtmp) {
if (!dcur->is_used)
continue;
+ if (dcur->type == PARSE_DEFTYPE_ENUM)
+ continue;
+
for (i = 0; i < dcur->member_list_len; i++) {
if (dcur->member_type_list[i] >= PARSE_TYPE_HASH_BOOL) {
- ar.uses_hash = true;
- ar.uses_type[dcur->member_type_list[i]
+ ar->uses_hash = true;
+ ar->uses_type[dcur->member_type_list[i]
- PARSE_TYPE_HASH_BOOL] = true;
} else if (dcur->member_type_list[i] >= PARSE_TYPE_ARRAY_BOOL) {
- ar.uses_array = true;
- ar.uses_type[dcur->member_type_list[i]
+ ar->uses_array = true;
+ ar->uses_type[dcur->member_type_list[i]
- PARSE_TYPE_ARRAY_BOOL] = true;
}
- ar.uses_type[dcur->member_type_list[i]] = true;
+ ar->uses_type[dcur->member_type_list[i]] = true;
}
}
- HASH_ITER(hh, pr.vars, vcur, vtmp) {
+ HASH_ITER(hh, pr->vars, vcur, vtmp) {
if (vcur->type >= PARSE_TYPE_HASH_BOOL) {
- ar.uses_hash = true;
- ar.uses_type[vcur->type - PARSE_TYPE_HASH_BOOL] = true;
+ ar->uses_hash = true;
+ ar->uses_type[vcur->type - PARSE_TYPE_HASH_BOOL] = true;
} else if (vcur->type >= PARSE_TYPE_ARRAY_BOOL) {
- ar.uses_array = true;
- ar.uses_type[vcur->type - PARSE_TYPE_ARRAY_BOOL] = true;
+ ar->uses_array = true;
+ ar->uses_type[vcur->type - PARSE_TYPE_ARRAY_BOOL] = true;
}
if (vcur->type == PARSE_TYPE_DEFTYPE
- || vcur->type == PARSE_TYPE_ARRAY_DEFTYPE
- || vcur->type == PARSE_TYPE_HASH_DEFTYPE
+ || vcur->type == PARSE_TYPE_ARRAY_DEFTYPE
+ || vcur->type == PARSE_TYPE_HASH_DEFTYPE
) {
continue;
}
- ar.uses_type[vcur->type] = true;
+ ar->uses_type[vcur->type] = true;
}
+}
+
+struct analyse_result_s* analyse(struct parse_result_s *pr)
+{
+ struct analyse_result_s *ar;
+
+ assert(pr != NULL);
+
+ TRYALLOC(ar, 1);
+ ar->uses_hash = false;
+ ar->uses_array = false;
+
+ sub_build_tries(pr, ar);
+
+ sub_calculate_used_types(pr, ar);
return ar;
}
-static void sub_recurse_free(struct analyse_tree_s *t)
+static void sub_wipe_trie(struct analyse_trie_s *t)
{
- unsigned i;
+ struct analyse_trie_s *cur = t, *prev = NULL;
- for (i = 0; i < t->branch_count; i++) {
- sub_recurse_free(t->branches[i]);
- free(t->branches[i]);
- }
+ assert(t != NULL);
+
+ t->parent = NULL;
+ t->idx = 0;
+
+ /* do nothing for an empty trie */
+ if (t->branch_count == 0)
+ return;
+
+ do {
+ /* drop into a branch to its tail */
+ if (cur->idx != cur->branch_count) {
+ prev = cur;
+ cur = cur->branches[cur->idx];
+ cur->idx = 0;
+ prev->idx++;
+ continue;
+ }
+
+ /* break at the head node */
+ if (cur->parent == NULL)
+ break;
+
+ /* at a tail. jump up to its parent */
+ prev = cur;
+ cur = cur->parent;
+
+ /* prev guaranteed to have no more children here */
+ if (prev->sval != NULL)
+ free(prev->sval);
+
+ free(prev);
+ } while (true);
}
-void analyse_result_wipe(struct analyse_result_s *r)
+void analyse_result_free(struct analyse_result_s *ar)
{
- assert(r != NULL);
+ unsigned i;
+
+ assert(ar != NULL);
+
+ sub_wipe_trie(&(ar->var_trie));
+
+ if (ar->deftype_mem_tries != NULL) {
+ for (i = 0; i < ar->deftype_mem_trie_count; i++) {
+ sub_wipe_trie(&(ar->deftype_mem_tries[i]));
+ }
+
+ free(ar->deftype_mem_tries);
+ }
- sub_recurse_free(&(r->deftype_tree));
- sub_recurse_free(&(r->var_tree));
+ free(ar);
}
diff --git a/src/analyse.h b/src/analyse.h
index 539e003..2e1556e 100644
--- a/src/analyse.h
+++ b/src/analyse.h
@@ -4,29 +4,35 @@
#include "tok.h"
#include "parse.h"
+#include "../reqs/uthash/include/uthash.h"
+
#include <stdbool.h>
/* 26 letters * 2 for case + 1 for '_' */
#define ANALYSE_MAX_BRANCH (26 * 2 + 1)
-struct analyse_tree_s {
- bool is_terminal;
- char name[TOK_MAX_LEN];
+struct analyse_trie_s {
+ /* NULL for non-terminals */
+ char *sval;
unsigned branch_count;
char branch_chars[ANALYSE_MAX_BRANCH];
- struct analyse_tree_s *branches[ANALYSE_MAX_BRANCH];
+ struct analyse_trie_s *branches[ANALYSE_MAX_BRANCH];
+ /* these two used for traversal */
+ struct analyse_trie_s *parent;
+ unsigned idx;
};
struct analyse_result_s {
bool uses_type[PARSE_TYPE_HASH_DEFTYPE];
bool uses_array;
bool uses_hash;
- struct analyse_tree_s deftype_tree;
- struct analyse_tree_s var_tree;
+ struct analyse_trie_s var_trie;
+ unsigned deftype_mem_trie_count;
+ struct analyse_trie_s *deftype_mem_tries;
};
-struct analyse_result_s analyse(struct parse_result_s pr);
+struct analyse_result_s* analyse(struct parse_result_s *pr);
-void analyse_result_wipe(struct analyse_result_s *r);
+void analyse_result_free(struct analyse_result_s *ar);
#endif
diff --git a/src/gen-consts.h b/src/gen-consts.h
index 72c1a46..90c2d9c 100644
--- a/src/gen-consts.h
+++ b/src/gen-consts.h
@@ -28,39 +28,32 @@ static const char sheadp1[] =
" size_t line;\n"
" size_t col;\n"
" size_t byte;\n"
-" union {\n"
-" bool b;\n"
-" char *s;\n"
-" int i;\n"
-" long int il;\n"
-" long long int ill;\n"
-" unsigned u;\n"
-" long unsigned ul;\n"
-" long long unsigned ull;\n"
-" float f;\n"
-" double d;\n"
-" long double dl;\n"
-" } val;\n"
+" size_t sbuf_len;\n"
+" size_t sbuf_mlen;\n"
+" char *sbuf;\n"
+" void *vp;\n"
"};\n"
"\n"
-"static int confconf_priv_gcp_file(void *fp)\n"
+"static int\n"
+"confconf_priv_gcp_file(void *fp)\n"
"{\n"
" return getc((FILE *)fp);\n"
"}\n"
"\n"
-"static int confconf_priv_ugcp_file(int c, void *fp)\n"
+"static int\n"
+"confconf_priv_ugcp_file(int c, void *fp)\n"
"{\n"
" return ungetc(c, (FILE *)fp);\n"
"}\n"
"\n"
-"static void confconf_priv_eat_space(struct confconf_priv_state *st)\n"
+"static void\n"
+"confconf_priv_eat_space(struct confconf_priv_state *st)\n"
"{\n"
" int c;\n"
"\n"
" while (true) {\n"
" c = (*(st->gcp))(st->fp);\n"
"\n"
-" /* comment */\n"
" if (c == '#') {\n"
" st->col++;\n"
" st->byte++;\n"
@@ -82,11 +75,12 @@ static const char sheadp1[] =
" }\n"
" }\n"
"\n"
-" /* space */\n"
" if (c == ' ' || c == '\\f' || c == '\\n'\n"
-" || c == '\\r' || c == '\\t' || c == '\\v') {\n"
+" || c == '\\r' || c == '\\t' || c == '\\v'\n"
+" ) {\n"
" while (c == ' ' || c == '\\f' || c == '\\n'\n"
-" || c == '\\r' || c == '\\t' || c == '\\v') {\n"
+" || c == '\\r' || c == '\\t' || c == '\\v'\n"
+" ) {\n"
" if (c == '\\n') {\n"
" st->col = 1;\n"
" st->line++;\n"
@@ -111,153 +105,153 @@ static const char sheadp1[] =
" }\n"
"}\n"
"\n"
+"static bool\n"
+"confconf_priv_push_char(struct confconf_priv_state *st, char c)\n"
+"{\n"
+" char *stmp;\n"
+"\n"
+" if (st->sbuf_len == st->sbuf_mlen\n"
+" || st->sbuf_len + 1 == st->sbuf_mlen\n"
+" ) {\n"
+" st->sbuf_mlen += CONFCONF_ALLOCWIDTH;\n"
+" stmp = realloc(st->sbuf, st->sbuf_mlen * sizeof(char));\n"
+" \n"
+" if (stmp == NULL) {\n"
+" if (st->sbuf != NULL)\n"
+" free(st->sbuf);\n"
+" st->sbuf = NULL;\n"
+" return false;\n"
+" }\n"
+"\n"
+" st->sbuf = stmp;\n"
+" }\n"
+"\n"
+" st->sbuf[st->sbuf_len] = c;\n"
+" st->sbuf_len++;\n"
+" st->sbuf[st->sbuf_len] = '\\0';\n"
+"\n"
+" return true;\n"
+"}\n"
+"\n"
;
static const char sheadp2[] =
-"static enum confconf_result_type confconf_priv_get_tok(\n"
-" struct confconf_priv_state *st)\n"
+"struct confconf_priv_pos {\n"
+" size_t line;\n"
+" size_t col;\n"
+" size_t byte;\n"
+"};\n"
+"\n"
+"static struct confconf_priv_pos\n"
+"confconf_priv_pos_get(struct confconf_priv_state *st)\n"
+"{\n"
+" struct confconf_priv_pos pos = {\n"
+" .line = st->line,\n"
+" .col = st->col,\n"
+" .byte = st->byte,\n"
+" };\n"
+"\n"
+" return pos;\n"
+"}\n"
+"static void\n"
+"confconf_priv_pos_set(struct confconf_priv_state *st,\n"
+" struct confconf_priv_pos pos)\n"
+"{\n"
+" st->line = pos.line;\n"
+" st->col = pos.col;\n"
+" st->byte = pos.byte;\n"
+"}\n"
+"\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_tok(struct confconf_priv_state *st)\n"
"{\n"
-" size_t len = 0, mlen = CONFCONF_ALLOCWIDTH;\n"
-" char *stmp;\n"
" int c;\n"
"\n"
-" st->val.s = NULL;\n"
+" st->sbuf_len = 0;\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 != '}'\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->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"
+" && c != '\\r' && c != '\\t' && c != '\\v'\n"
+" && c != ']' && c != '}'\n"
+" && c != '[' && c != '{'\n"
+" && c != ',' && c != ':'\n"
+" && c != '\\'' && c != '\"'\n"
+" && c != '=' && c != EOF\n"
+" ) {\n"
+" if ( !confconf_priv_push_char(st, (char)c) )\n"
+" return CONFCONF_ERR_MEMORY;\n"
"\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"
+" if (st->sbuf_len == 0) {\n"
+" if (c == ' ' || c == '\\f' || c == '\\n'\n"
+" || c == '\\r' || c == '\\t' || c == '\\v'\n"
+" ) {\n"
+" (*(st->ugcp))(c, st->fp);\n"
+" if ( !confconf_priv_push_char(st, '\\0') )\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"
+" } else {\n"
+" if ( !confconf_priv_push_char(st, (char)c) )\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->val.s != NULL) {\n"
-" free(st->val.s);\n"
-" st->val.s = NULL;\n"
-" }\n"
-" return CONFCONF_ERR_MEMORY;\n"
+" st->sbuf_len = 1;\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"
+" } else {\n"
+" (*(st->ugcp))(c, st->fp);\n"
" }\n"
"\n"
-" (*(st->ugcp))(c, st->fp);\n"
-"\n"
-" st->val.s[len] = '\\0';\n"
-"\n"
-" st->col += len;\n"
-" st->byte += len;\n"
+" st->col += st->sbuf_len;\n"
+" st->byte += st->sbuf_len;\n"
"\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_id(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_id(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
" char *off;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\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"
+" for (off = st->sbuf; *off != '\\0'; off++) {\n"
" if (*off >= '0' && *off <= '9')\n"
" continue;\n"
+"\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"
+" *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"
+" continue;\n"
" }\n"
-" \n"
+"\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
" }\n"
"\n"
@@ -272,100 +266,103 @@ static const char sbool[] =
"#ifndef CONFCONF_BOOL_H\n"
"#define CONFCONF_BOOL_H\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_bool(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_bool(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
+" bool *b = st->vp;\n"
" char *off;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
-" off = st->val.s;\n"
+" off = st->sbuf;\n"
"\n"
" if (*off == 't' || *off == 'T') {\n"
" if (\n"
-" (*(++off) == 'r' || *off == 'R') &&\n"
-" (*(++off) == 'u' || *off == 'U') &&\n"
-" (*(++off) == 'e' || *off == 'E') &&\n"
-" (*(++off) == '\\0')\n"
+" (*(++off) == 'r' || *off == 'R') &&\n"
+" (*(++off) == 'u' || *off == 'U') &&\n"
+" (*(++off) == 'e' || *off == 'E') &&\n"
+" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->val.s);\n"
-" st->val.b = true;\n"
+" *b = true;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
" }\n"
" }\n"
"\n"
" if (*off == 'y' || *off == 'Y') {\n"
" if (\n"
-" (*(++off) == 'e' || *off == 'E') &&\n"
-" (*(++off) == 's' || *off == 'S') &&\n"
-" (*(++off) == '\\0')\n"
+" (*(++off) == 'e' || *off == 'E') &&\n"
+" (*(++off) == 's' || *off == 'S') &&\n"
+" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->val.s);\n"
-" st->val.b = true;\n"
+" *b = true;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
" }\n"
" }\n"
"\n"
" if (*off == 'n' || *off == 'N') {\n"
" if (\n"
-" (*(++off) == 'o' || *off == 'O') &&\n"
-" (*(++off) == '\\0')\n"
+" (*(++off) == 'o' || *off == 'O') &&\n"
+" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->val.s);\n"
-" st->val.b = false;\n"
+" *b = false;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
" }\n"
" }\n"
"\n"
" if (*off == 'f' || *off == 'F') {\n"
" if (\n"
-" (*(++off) == 'a' || *off == 'A') &&\n"
-" (*(++off) == 'l' || *off == 'L') &&\n"
-" (*(++off) == 's' || *off == 'S') &&\n"
-" (*(++off) == 'e' || *off == 'E') &&\n"
-" (*(++off) == '\\0')\n"
+" (*(++off) == 'a' || *off == 'A') &&\n"
+" (*(++off) == 'l' || *off == 'L') &&\n"
+" (*(++off) == 's' || *off == 'S') &&\n"
+" (*(++off) == 'e' || *off == 'E') &&\n"
+" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->val.s);\n"
-" st->val.b = false;\n"
+" *b = false;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
" }\n"
" }\n"
"\n"
" if (*off == 'o' || *off == 'O') {\n"
" if (\n"
-" (*(off+1) == 'n' || *(off+1) == 'N') &&\n"
-" (*(off+2) == '\\0')\n"
+" (*(off+1) == 'n' || *(off+1) == 'N') &&\n"
+" (*(off+2) == '\\0')\n"
" ) {\n"
-" free(st->val.s);\n"
-" st->val.b = true;\n"
+" *b = true;\n"
" return CONFCONF_SUCCESS;\n"
" }\n"
"\n"
" if (\n"
-" (*(++off) == 'f' || *off == 'F') &&\n"
-" (*(++off) == 'f' || *off == 'F') &&\n"
-" (*(++off) == '\\0')\n"
+" (*(++off) == 'f' || *off == 'F') &&\n"
+" (*(++off) == 'f' || *off == 'F') &&\n"
+" (*(++off) == '\\0')\n"
" ) {\n"
-" free(st->val.s);\n"
-" st->val.b = false;\n"
+" *b = false;\n"
" return CONFCONF_SUCCESS;\n"
" } else {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
" }\n"
" }\n"
"\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
"}\n"
"\n"
@@ -377,32 +374,63 @@ static const char sstring[] =
"#ifndef CONFCONF_STRING_H\n"
"#define CONFCONF_STRING_H\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_str(\n"
-" struct confconf_priv_state *st)\n"
+"#include <string.h>\n"
+"\n"
+"static char*\n"
+"confconf_priv_dup_sbuf(struct confconf_priv_state *st)\n"
+"{\n"
+" char *s;\n"
+"\n"
+" s = malloc((st->sbuf_len + 1) * sizeof(char));\n"
+"\n"
+" if (s == NULL)\n"
+" return NULL;\n"
+"\n"
+" if (st->sbuf_len == 0)\n"
+" s[0] = '\\0';\n"
+" else\n"
+" strcpy(s, st->sbuf);\n"
+"\n"
+" return s;\n"
+"}\n"
+"\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_str(struct confconf_priv_state *st)\n"
"{\n"
-" size_t len = 0, mlen = 0;\n"
-" char *stmp;\n"
" int c, endc;\n"
" bool escape = false;\n"
-"\n"
-" st->val.s = NULL;\n"
+" enum confconf_result_type r;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
" c = (*(st->gcp))(st->fp);\n"
+"\n"
" if (c == EOF)\n"
" return CONFCONF_ERR_UNEXPECTED_EOF;\n"
"\n"
" if (c != '\\'' && c != '\\\"') {\n"
" (*(st->ugcp))(c, st->fp);\n"
+" pos = confconf_priv_pos_get(st);\n"
+" r = confconf_priv_get_tok(st);\n"
+"\n"
+" if (r != CONFCONF_SUCCESS)\n"
+" return r;\n"
+"\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
" }\n"
"\n"
" endc = c;\n"
-"\n"
" st->col++;\n"
" st->byte++;\n"
"\n"
+" st->sbuf_len = 0;\n"
+"\n"
" while (true) {\n"
" c = (*(st->gcp))(st->fp);\n"
+"\n"
+" if (c == EOF)\n"
+" return CONFCONF_ERR_UNEXPECTED_EOF;\n"
+"\n"
" st->col++;\n"
" st->byte++;\n"
"\n"
@@ -421,59 +449,10 @@ static const char sstring[] =
" st->line++;\n"
" }\n"
"\n"
-" if (c == EOF) {\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"
-"\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"
-"\n"
-" st->val.s[len] = c;\n"
-" len++;\n"
-" }\n"
-"\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"
+" if ( !confconf_priv_push_char(st, (char)c) )\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"
"\n"
-" st->val.s[len] = '\\0';\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -488,32 +467,40 @@ static const char sint[] =
"#include <errno.h>\n"
"#include <limits.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_int(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_int(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" long int i;\n"
+" int *i = st->vp;\n"
+" long int local_i;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" i = strtol(st->val.s, &check, 0);\n"
+" local_i = strtol(st->sbuf, &check, 0);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\n"
-" if (i > INT_MAX || i < INT_MIN)\n"
+" if (local_i > INT_MAX || local_i < INT_MIN) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" free(st->val.s);\n"
-" st->val.i = (int)i;\n"
+" *i = (int)local_i;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -527,29 +514,33 @@ static const char sintl[] =
"\n"
"#include <errno.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_intl(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_intl(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" long int il;\n"
+" long int *il = st->vp;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" il = strtol(st->val.s, &check, 0);\n"
+" *il = strtol(st->sbuf, &check, 0);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\n"
-" free(st->val.s);\n"
-" st->val.il = il;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -563,29 +554,33 @@ static const char sintll[] =
"\n"
"#include <errno.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_intll(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_intll(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" long long int ill;\n"
+" long long int *ill = st->vp;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" ill = strtoll(st->val.s, &check, 0);\n"
+" *ill = strtoll(st->sbuf, &check, 0);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\n"
-" free(st->val.s);\n"
-" st->val.ill = ill;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -600,32 +595,40 @@ static const char suint[] =
"#include <errno.h>\n"
"#include <limits.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_uint(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_uint(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" long unsigned u;\n"
+" unsigned *u = st->vp;\n"
+" long unsigned u_local;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" u = strtoul(st->val.s, &check, 0);\n"
+" u_local = strtoul(st->sbuf, &check, 0);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\n"
-" if (u > UINT_MAX)\n"
+" if (u_local > UINT_MAX) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" free(st->val.s);\n"
-" st->val.u = (unsigned)u;\n"
+" *u = (unsigned)u_local;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -639,29 +642,33 @@ static const char suintl[] =
"\n"
"#include <errno.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_uintl(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_uintl(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" long unsigned ul;\n"
+" long unsigned *ul = st->vp;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" ul = strtoul(st->val.s, &check, 0);\n"
+" *ul = strtoul(st->sbuf, &check, 0);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\n"
-" free(st->val.s);\n"
-" st->val.ul = ul;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -675,29 +682,33 @@ static const char suintll[] =
"\n"
"#include <errno.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_uintll(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_uintll(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" long long unsigned ull;\n"
+" long long unsigned *ull = st->vp;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" ull = strtoull(st->val.s, &check, 0);\n"
+" *ull = strtoull(st->sbuf, &check, 0);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\n"
-" free(st->val.s);\n"
-" st->val.ull = ull;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -711,29 +722,33 @@ static const char sfloat[] =
"\n"
"#include <errno.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_float(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_float(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" double f;\n"
+" float *f = st->vp;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" f = strtof(st->val.s, &check);\n"
+" *f = strtof(st->sbuf, &check);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\n"
-" free(st->val.s);\n"
-" st->val.f = f;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -747,29 +762,33 @@ static const char sdouble[] =
"\n"
"#include <errno.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_double(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_double(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" double d;\n"
+" double *d = st->vp;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" d = strtod(st->val.s, &check);\n"
+" *d = strtod(st->sbuf, &check);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\n"
-" free(st->val.s);\n"
-" st->val.d = d;\n"
" return CONFCONF_SUCCESS;\n"
"}\n"
"\n"
@@ -783,116 +802,36 @@ static const char sdoublel[] =
"\n"
"#include <errno.h>\n"
"\n"
-"static enum confconf_result_type confconf_priv_get_doublel(\n"
-" struct confconf_priv_state *st)\n"
+"static enum confconf_result_type\n"
+"confconf_priv_get_doublel(struct confconf_priv_state *st)\n"
"{\n"
" enum confconf_result_type r;\n"
-" double dl;\n"
+" long double *dl = st->vp;\n"
" char *check;\n"
+" struct confconf_priv_pos pos;\n"
"\n"
+" pos = confconf_priv_pos_get(st);\n"
" r = confconf_priv_get_tok(st);\n"
"\n"
" if (r != CONFCONF_SUCCESS)\n"
" return r;\n"
"\n"
" errno = EILSEQ;\n"
-" dl = strtold(st->val.s, &check);\n"
+" *dl = strtold(st->sbuf, &check);\n"
"\n"
-" if (errno == ERANGE)\n"
+" if (errno == ERANGE) {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_RANGE;\n"
+" }\n"
"\n"
-" if (*check != '\\0')\n"
+" if (*check != '\\0') {\n"
+" confconf_priv_pos_set(st, pos);\n"
" return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+" }\n"
"\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 %s\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 846f122..ff93dd5 100644
--- a/src/gen.c
+++ b/src/gen.c
@@ -4,197 +4,695 @@
#include "parse.h"
#include "opt.h"
+#include "../reqs/uthash/include/uthash.h"
+
#include <time.h>
#include <assert.h>
#include "gen-consts.h"
-void gen(FILE *f, struct parse_result_s pr, struct analyse_result_s ar)
+static inline void sub_head(FILE *f, 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, sheadp1);
fprintf(f, sheadp2);
- if (ar.uses_type[PARSE_TYPE_BOOL])
+ if (ar->uses_type[PARSE_TYPE_BOOL])
fprintf(f, sbool);
- if (ar.uses_type[PARSE_TYPE_STRING])
+ if (ar->uses_type[PARSE_TYPE_STRING])
fprintf(f, sstring);
- if (ar.uses_type[PARSE_TYPE_INT])
+ if (ar->uses_type[PARSE_TYPE_INT])
fprintf(f, sint);
- if (ar.uses_type[PARSE_TYPE_INTL])
+ if (ar->uses_type[PARSE_TYPE_INTL])
fprintf(f, sintl);
- if (ar.uses_type[PARSE_TYPE_INTLL])
+ if (ar->uses_type[PARSE_TYPE_INTLL])
fprintf(f, sintll);
- if (ar.uses_type[PARSE_TYPE_UINT])
+ if (ar->uses_type[PARSE_TYPE_UINT])
fprintf(f, suint);
- if (ar.uses_type[PARSE_TYPE_UINTL])
+ if (ar->uses_type[PARSE_TYPE_UINTL])
fprintf(f, suintl);
- if (ar.uses_type[PARSE_TYPE_UINTLL])
+ if (ar->uses_type[PARSE_TYPE_UINTLL])
fprintf(f, suintll);
- if (ar.uses_type[PARSE_TYPE_FLOAT])
+ if (ar->uses_type[PARSE_TYPE_FLOAT])
fprintf(f, sfloat);
- if (ar.uses_type[PARSE_TYPE_DOUBLE])
+ if (ar->uses_type[PARSE_TYPE_DOUBLE])
fprintf(f, sdouble);
- if (ar.uses_type[PARSE_TYPE_DOUBLEL])
+ if (ar->uses_type[PARSE_TYPE_DOUBLEL])
fprintf(f, sdoublel);
+}
- /* if (ar.uses_array) */
- /* fprintf(f, sarray); */
- if (ar.uses_hash)
- fprintf(f, shash, (opt_header_str() ? opt_header_str() : pr.header));
+static inline void sub_deftypes_type(FILE *f, struct parse_result_s *pr,
+ struct parse_deftype_s *dcur)
+{
+ unsigned i;
- /********
- * BODY *
- ********/
+ /* enum for indicating which union elem is used */
+ if (dcur->type == PARSE_DEFTYPE_UNION) {
+ fprintf(f,
+ "enum confconf_utype_%s_%s {\n",
+ dcur->name,
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix)
+ );
+
+ for (i = 0; i < dcur->member_list_len; i++) {
+ fprintf(f,
+ " CONFCONF_UTYPE_%s_%s_%s,\n",
+ dcur->name,
+ dcur->member_name_list[i],
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix)
+ );
+ }
+
+ fprintf(f, "};\n\n");
+ }
fprintf(f,
- "#ifndef CONFCONF_BODY_%s_H\n"
- "#define CONFCONF_BODY_%s_H\n\n",
- (opt_suffix_str() ? opt_suffix_str() : pr.suffix),
- (opt_suffix_str() ? opt_suffix_str() : pr.suffix)
+ "%s confconf_type_%s_%s {\n",
+ (dcur->type == PARSE_DEFTYPE_ENUM ? "enum" : "struct"),
+ dcur->name,
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix)
);
- /* deftypes */
- HASH_ITER(hh, pr.deftypes, dcur, dtmp) {
- if (!dcur->is_used)
- continue;
+ if (dcur->type == PARSE_DEFTYPE_UNION) {
+ fprintf(f,
+ " enum confconf_utype_%s_%s type;\n"
+ " union {\n",
+ dcur->name,
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix)
+ );
+ }
- fprintf(f, "%s confconf_type_%s_%s {\n",
- (dcur->type == PARSE_DEFTYPE_ENUM ? "enum" :
- (dcur->type == PARSE_DEFTYPE_UNION ?
- "union" : "struct")
- ),
+ for (i = 0; i < dcur->member_list_len; i++) {
+ if (dcur->type == PARSE_DEFTYPE_UNION) {
+ fprintf(f, " ");
+ }
+
+ if (dcur->type == PARSE_DEFTYPE_ENUM) {
+ fprintf(f,
+ " CONFCONF_TYPE_%s_%s_%s,\n",
dcur->name,
- (opt_suffix_str() ? opt_suffix_str() : pr.suffix)
- );
+ dcur->member_name_list[i],
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix)
+ );
+ continue;
+ }
+
+ 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]);
+ }
+ if (dcur->type == PARSE_DEFTYPE_UNION) {
+ fprintf(f, " } val;\n");
+ }
+
+ fprintf(f, "};\n\n");
+}
+
+static inline void sub_deftypes_get_struct(FILE *f,
+ struct parse_deftype_s *dcur)
+{
+ unsigned i;
+
+ fprintf(f, " int c;\n");
+
+ /* add stmp for alloc-swap and set all string elements to NULL */
+ if (dcur->contains_heap) {
+ fprintf(f, " char *stmp;\n");
for (i = 0; i < dcur->member_list_len; i++) {
- if (dcur->type == PARSE_DEFTYPE_ENUM) {
- fprintf(f, " CONFCONF_TYPE_%s_%s_%s,\n",
- dcur->name,
- dcur->member_name_list[i],
- (opt_suffix_str() ? opt_suffix_str() : pr.suffix)
+ if (dcur->member_type_list[i] == PARSE_TYPE_STRING) {
+ fprintf(f,
+ "\n"
+ " t->%s = NULL;\n",
+ dcur->member_name_list[i]
);
- continue;
}
+ }
+ }
- 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,
+ "\n"
+ " c = (*(st->gcp))(st->fp);\n"
+ "\n"
+ " if (c == EOF)\n"
+ " return CONFCONF_ERR_UNEXPECTED_EOF;\n"
+ "\n"
+ " if (c != '{') {\n"
+ " (*(st->ugcp))(c, st->fp);\n"
+ " pos = confconf_priv_pos_get(st);\n"
+ " r = confconf_priv_get_tok(st);\n"
+ " if (r != CONFCONF_SUCCESS)\n"
+ " return r;\n"
+ " confconf_priv_pos_set(st, pos);\n"
+ " return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+ " }\n"
+ "\n"
+ " st->col++;\n"
+ " st->byte++;\n"
+ "\n"
+ " confconf_priv_eat_space(st);\n"
+ );
- fprintf(f, "%s;\n", dcur->member_name_list[i]);
+ for (i = 0; i < dcur->member_list_len; i++) {
+ if (i != 0) {
+ fprintf(f,
+ "\n"
+ " confconf_priv_eat_space(st);\n"
+ "\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"
+ " }\n"
+ );
}
- fprintf(f, "};\n\n");
- }
+ fprintf(f, "\n");
+
+ if (dcur->member_type_list[i] != PARSE_TYPE_STRING) {
+ fprintf(f,
+ " st->vp = &(t->%s);\n",
+ dcur->member_name_list[i]
+ );
+ }
+
+ switch (dcur->member_type_list[i]) {
+ case PARSE_TYPE_BOOL:
+ fprintf(f, " r = confconf_priv_get_bool(st);\n");
+ break;
+ case PARSE_TYPE_STRING:
+ fprintf(f, " r = confconf_priv_get_str(st);\n");
+ break;
+ case PARSE_TYPE_ID:
+ fprintf(f, " r = confconf_priv_get_id(st);\n");
+ break;
+ case PARSE_TYPE_INT:
+ fprintf(f, " r = confconf_priv_get_int(st);\n");
+ break;
+ case PARSE_TYPE_INTL:
+ fprintf(f, " r = confconf_priv_get_intl(st);\n");
+ break;
+ case PARSE_TYPE_INTLL:
+ fprintf(f, " r = confconf_priv_get_intll(st);\n");
+ break;
+ case PARSE_TYPE_UINT:
+ fprintf(f, " r = confconf_priv_get_uint(st);\n");
+ break;
+ case PARSE_TYPE_UINTL:
+ fprintf(f, " r = confconf_priv_get_uintl(st);\n");
+ break;
+ case PARSE_TYPE_UINTLL:
+ fprintf(f, " r = confconf_priv_get_uintll(st);\n");
+ break;
+ case PARSE_TYPE_FLOAT:
+ fprintf(f, " r = confconf_priv_get_float(st);\n");
+ break;
+ case PARSE_TYPE_DOUBLE:
+ fprintf(f, " r = confconf_priv_get_double(st);\n");
+ break;
+ case PARSE_TYPE_DOUBLEL:
+ fprintf(f, " r = confconf_priv_get_doublel(st);\n");
+ break;
+ default:
+ assert(0);
+ }
- /* hash type */
- if (ar.uses_hash) {
fprintf(f,
- "#include %s\n\n"
- "struct confconf_hash_%s {\n"
- " char *key;\n"
- " union {\n"
- "%s%s%s%s%s%s%s%s%s%s%s",
- (opt_header_str() ? opt_header_str() : pr.header),
- (opt_suffix_str() ? opt_suffix_str() : pr.suffix),
- (ar.uses_type[PARSE_TYPE_HASH_BOOL]
- ? " bool b;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_STRING]
- ? " char *s;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_INT]
- ? " int i;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_INTL]
- ? " long int il;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_INTLL]
- ? " long long int ill;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_UINT]
- ? " unsigned u;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_UINTL]
- ? " long unsigned ul;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_UINTLL]
- ? " long long unsigned ull;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_FLOAT]
- ? " float f;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_DOUBLE]
- ? " double d;\n" : ""),
- (ar.uses_type[PARSE_TYPE_HASH_DOUBLEL]
- ? " long double dl;\n" : "")
+ " if (r != CONFCONF_SUCCESS)\n"
+ " %s;\n",
+ (dcur->contains_heap ? "goto err" : "return r")
);
- HASH_ITER(hh, pr.deftypes, dcur, dtmp) {
- if (dcur->is_used && dcur->is_in_hash) {
- fprintf(f, " %s confconf_type_%s_%s type_%s;\n",
- (dcur->type == PARSE_DEFTYPE_ENUM ? "enum" :
- (dcur->type == PARSE_DEFTYPE_UNION ?
- "union" : "struct")
- ),
- dcur->name,
- (opt_suffix_str() ? opt_suffix_str() : pr.suffix),
- dcur->name
+
+ if (dcur->member_type_list[i] == PARSE_TYPE_STRING) {
+ fprintf(f,
+ "\n"
+ " stmp = confconf_priv_dup_sbuf(st);\n"
+ " if (stmp == NULL)\n"
+ " goto err;\n"
+ " t->%s = stmp;\n",
+ dcur->member_name_list[i]
+ );
+ }
+ }
+
+ fprintf(f,
+ "\n"
+ " c = (*(st->gcp))(st->fp);\n"
+ "\n"
+ " if (c == EOF)\n"
+ " return CONFCONF_ERR_UNEXPECTED_EOF;\n"
+ "\n"
+ " if (c != '}') {\n"
+ " (*(st->ugcp))(c, st->fp);\n"
+ " pos = confconf_priv_pos_get(st);\n"
+ " r = confconf_priv_get_tok(st);\n"
+ " if (r != CONFCONF_SUCCESS)\n"
+ " %s;\n"
+ " confconf_priv_pos_set(st, pos);\n"
+ " return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+ " %s;\n"
+ " }\n"
+ "\n"
+ " return CONFCONF_SUCCESS;\n",
+ (dcur->contains_heap ? "goto err" : "return r"),
+ (dcur->contains_heap ? "goto err" : "return r")
+ );
+
+ if (dcur->contains_heap) {
+ fprintf(f, "\nerr:\n");
+ for (i = 0; i < dcur->member_list_len; i++) {
+ if (dcur->member_type_list[i] == PARSE_TYPE_STRING
+ || dcur->member_type_list[i] == PARSE_TYPE_ID
+ ) {
+ fprintf(f,
+ " if (t->%s != NULL)\n"
+ " free(t->%s);\n"
+ "\n",
+ dcur->member_name_list[i],
+ dcur->member_name_list[i]
);
}
}
+ fprintf(f, " return r;\n");
+ }
+}
+
+/* emit a switch statement dfa to char-by-char recognise a string */
+static void sub_print_switch(FILE *f, struct analyse_trie_s *cur,
+ unsigned depth, const char *dest, const char *stmt)
+{
+ unsigned i;
+
+ cur->idx = 0;
+ do {
+ /* skip leaves */
+ if (cur->branch_count == 0) {
+ for (i = 0; i < depth; i++)
+ fprintf(f, "\t");
+ fprintf(f, "if (*stmp == '\\0') {\n");
+ for (i = 0; i < depth + 1; i++)
+ fprintf(f, "\t");
+ fprintf(f, "%s = %s;\n", dest, cur->sval);
+ for (i = 0; i < depth + 1; i++)
+ fprintf(f, "\t");
+ fprintf(f, "%s;\n", stmt);
+ for (i = 0; i < depth; i++)
+ fprintf(f, "\t");
+ fprintf(f, "}\n");
+ for (i = 0; i < depth; i++)
+ fprintf(f, "\t");
+ fprintf(f, "break;\n");
+ depth--;
+ } else {
+ if (cur->idx == 0) {
+ for (i = 0; i < depth; i++)
+ fprintf(f, "\t");
+ fprintf(f, "switch ( *(stmp++) ) {\n");
+ }
+
+ if (cur->idx == cur->branch_count) {
+ for (i = 0; i < depth; i++)
+ fprintf(f, "\t");
+ fprintf(f, "}\n");
+ /* skip break for final '}' */
+ if (cur->parent != NULL || cur->idx != cur->branch_count) {
+ for (i = 0; i < depth; i++)
+ fprintf(f, "\t");
+ fprintf(f, "break;\n");
+ }
+ depth--;
+ } else {
+ /* match prefix terminals */
+ if (cur->idx == 0 && cur->sval != NULL) {
+ for (i = 0; i < depth; i++)
+ fprintf(f, "\t");
+ fprintf(f, "case '\\0':\n");
+ for (i = 0; i < depth + 1; i++)
+ fprintf(f, "\t");
+ fprintf(f, "%s = %s;\n", dest, cur->sval);
+ for (i = 0; i < depth + 1; i++)
+ fprintf(f, "\t");
+ fprintf(f, "%s;\n", stmt);
+ for (i = 0; i < depth + 1; i++)
+ fprintf(f, "\t");
+ fprintf(f, "break;\n");
+ }
+ for (i = 0; i < depth; i++)
+ fprintf(f, "\t");
+ fprintf(f, "case '%c':\n", cur->branch_chars[cur->idx]);
+ depth++;
+ }
+ }
+
+ /* next node in the trie, iterating depth-first */
+ if (cur->idx == cur->branch_count) {
+ cur = cur->parent;
+ } else {
+ cur->idx++;
+ cur = cur->branches[cur->idx - 1];
+ cur->idx = 0;
+ }
+ } while (cur != NULL);
+
+}
+
+static inline void sub_deftypes_get_union(FILE *f, struct parse_result_s *pr,
+ struct analyse_result_s *ar, struct parse_deftype_s *dcur, unsigned idx)
+{
+ struct analyse_trie_s *t = &(ar->deftype_mem_tries[idx]);
+ unsigned i;
+
+ fprintf(f,
+ " char *stmp;\n"
+ " unsigned mem;\n"
+ "\n"
+ " confconf_priv_eat_space(st);\n"
+ "\n"
+ " pos = confconf_priv_pos_get(st);\n"
+ " r = confconf_priv_get_tok(st);\n"
+ " if (r != CONFCONF_SUCCESS)\n"
+ " return r;\n"
+ " stmp = st->sbuf;\n"
+ "\n"
+ );
+
+ sub_print_switch(f, t, 1, "mem", "goto match");
+
+ fprintf(f,
+ "\n"
+ " confconf_priv_pos_set(st, pos);\n"
+ " return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+ "\n"
+ "match:\n"
+ " pos = confconf_priv_pos_get(st);\n"
+ "\n"
+ " switch (mem) {\n"
+ );
+
+ for (i = 0; i < dcur->member_list_len; i++) {
fprintf(f,
- " } val;\n"
- " UT_hash_handle hh;\n"
- "};\n\n"
+ " case %u:\n"
+ " st->vp = &(t->val.%s);\n"
+ " r = confconf_priv_get_%s(st);\n"
+ " t->type = CONFCONF_UTYPE_%s_%s_%s;\n"
+ " break;\n",
+ i,
+ dcur->member_name_list[i],
+ parse_typestrs[dcur->member_type_list[i]],
+ dcur->name,
+ dcur->member_name_list[i],
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix)
);
+ }
+
+ fprintf(f,
+ " }\n"
+ "\n"
+ " if (r != CONFCONF_SUCCESS)\n"
+ " return r;\n"
+ "\n"
+ " return CONFCONF_SUCCESS;\n"
+ );
+}
+
+static inline void sub_deftypes_get_enum(FILE *f, struct analyse_result_s *ar,
+ struct parse_deftype_s *dcur, unsigned idx)
+{
+ struct analyse_trie_s *t = &(ar->deftype_mem_tries[idx]);
+
+ fprintf(f,
+ " char *stmp;\n"
+ "\n"
+ " confconf_priv_eat_space(st);\n"
+ "\n"
+ " pos = confconf_priv_pos_get(st);\n"
+ " r = confconf_priv_get_tok(st);\n"
+ " if (r != CONFCONF_SUCCESS)\n"
+ " return r;\n"
+ " stmp = st->sbuf;\n"
+ "\n"
+ );
+
+ sub_print_switch(f, t, 1, "*t", "return CONFCONF_SUCCESS");
+
+ fprintf(f,
+ "\n"
+ " confconf_priv_pos_set(st, pos);\n"
+ " return CONFCONF_ERR_UNEXPECTED_TOKEN;\n"
+ );
+}
+
+static inline void sub_deftypes_get(FILE *f, struct parse_result_s *pr,
+ struct analyse_result_s *ar, struct parse_deftype_s *dcur, unsigned idx)
+{
+ fprintf(f,
+ "static enum confconf_result_type\n"
+ "confconf_priv_get_%s_%s(struct confconf_priv_state *st)\n"
+ "{\n"
+ " enum confconf_result_type r;\n"
+ " %s confconf_type_%s_%s *t = st->vp;\n"
+ " struct confconf_priv_pos pos;\n",
+ dcur->name,
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix),
+ (dcur->type == PARSE_DEFTYPE_ENUM ? "enum" : "struct"),
+ dcur->name,
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix)
+ );
+
+ switch (dcur->type) {
+ case PARSE_DEFTYPE_STRUCT:
+ sub_deftypes_get_struct(f, dcur);
+ break;
+
+ case PARSE_DEFTYPE_UNION:
+ sub_deftypes_get_union(f, pr, ar, dcur, idx);
+ break;
+
+ case PARSE_DEFTYPE_ENUM:
+ sub_deftypes_get_enum(f, ar, dcur, idx);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ fprintf(f, "}\n\n");
+}
+
+static inline void sub_deftypes(FILE *f, struct parse_result_s *pr,
+ struct analyse_result_s *ar)
+{
+ struct parse_deftype_s *dcur, *dtmp;
+ unsigned i = 0;
+
+ HASH_ITER(hh, pr->deftypes, dcur, dtmp) {
+
+ if (!dcur->is_used) {
+ i++;
+ continue;
+ }
+
+ /* print the type definition */
+ sub_deftypes_type(f, pr, dcur);
+ /* print it's get function */
+ sub_deftypes_get(f, pr, ar, dcur, i);
+ i++;
+ }
+
+}
+
+static inline void sub_arraytype(FILE *f, struct parse_result_s *pr,
+ struct analyse_result_s *ar)
+{
+ struct parse_deftype_s *dcur, *dtmp;
+
+ fprintf(f,
+ "struct confconf_array_%s {\n"
+ " size_t len;\n"
+ " union {\n"
+ "%s%s%s%s%s%s%s%s%s%s%s",
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix),
+ (ar->uses_type[PARSE_TYPE_ARRAY_BOOL]
+ ? " bool b;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_STRING]
+ ? " char *s;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_INT]
+ ? " int i;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_INTL]
+ ? " long int il;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_INTLL]
+ ? " long long int ill;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_UINT]
+ ? " unsigned u;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_UINTL]
+ ? " long unsigned ul;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_UINTLL]
+ ? " long long unsigned ull;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_FLOAT]
+ ? " float f;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_DOUBLE]
+ ? " double d;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_ARRAY_DOUBLEL]
+ ? " long double dl;\n" : "")
+ );
+
+ HASH_ITER(hh, pr->deftypes, dcur, dtmp) {
+ if (dcur->is_used && dcur->is_in_array) {
+ fprintf(f,
+ " %s confconf_type_%s_%s type_%s;\n",
+ (dcur->type == PARSE_DEFTYPE_ENUM ? "enum" :
+ (dcur->type == PARSE_DEFTYPE_UNION ? "union" : "struct")
+ ),
+ dcur->name, pr->suffix, dcur->name
+ );
+ }
+ }
+
+ fprintf(f,
+ " } *arr;\n"
+ "};\n\n"
+ );
+}
+
+static inline void sub_hashtype(FILE *f, struct parse_result_s *pr,
+ struct analyse_result_s *ar)
+{
+ struct parse_deftype_s *dcur, *dtmp;
+
+ fprintf(f,
+ "#include %s\n\n"
+ "struct confconf_hash_%s {\n"
+ " char *key;\n"
+ " union {\n"
+ "%s%s%s%s%s%s%s%s%s%s%s",
+ (opt_header_str() ? opt_header_str() : pr->header),
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix),
+ (ar->uses_type[PARSE_TYPE_HASH_BOOL]
+ ? " bool b;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_STRING]
+ ? " char *s;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_INT]
+ ? " int i;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_INTL]
+ ? " long int il;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_INTLL]
+ ? " long long int ill;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_UINT]
+ ? " unsigned u;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_UINTL]
+ ? " long unsigned ul;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_UINTLL]
+ ? " long long unsigned ull;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_FLOAT]
+ ? " float f;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_DOUBLE]
+ ? " double d;\n" : ""),
+ (ar->uses_type[PARSE_TYPE_HASH_DOUBLEL]
+ ? " long double dl;\n" : "")
+ );
+ HASH_ITER(hh, pr->deftypes, dcur, dtmp) {
+ if (dcur->is_used && dcur->is_in_hash) {
+ fprintf(f,
+ " %s confconf_type_%s_%s type_%s;\n",
+ (dcur->type == PARSE_DEFTYPE_ENUM ? "enum" :
+ (dcur->type == PARSE_DEFTYPE_UNION ? "union" : "struct")
+ ),
+ dcur->name,
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix),
+ dcur->name
+ );
+ }
}
+ fprintf(f,
+ " } val;\n"
+ " UT_hash_handle hh;\n"
+ "};\n\n"
+ );
+}
+
+static inline void sub_body(FILE *f, struct parse_result_s *pr,
+ struct analyse_result_s *ar)
+{
+ struct parse_var_s *vcur, *vtmp;
+
+}
+
+void gen(FILE *f, struct parse_result_s *pr, struct analyse_result_s *ar)
+{
+ time_t t;
+ struct tm *ti;
+
+ assert(pr != NULL);
+ assert(ar != NULL);
+
+ time(&t);
+ ti = localtime(&t);
+
+ fprintf(f, "/* generated by %s on %04d-%02d-%02d */\n\n",
+ VERSION, ti->tm_year + 1900, ti->tm_mon + 1, ti->tm_mday);
+
+ /* conditionally include static subroutines from gen-consts.h */
+ sub_head(f, ar);
+
+ fprintf(f,
+ "#ifndef CONFCONF_BODY_%s_H\n"
+ "#define CONFCONF_BODY_%s_H\n\n",
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix),
+ (opt_suffix_str() ? opt_suffix_str() : pr->suffix)
+ );
+
+ /* define struct/enum/unions and their get functions */
+ sub_deftypes(f, pr, ar);
+
+ if (ar->uses_array)
+ sub_arraytype(f, pr, ar);
+
+ if (ar->uses_hash)
+ sub_hashtype(f, pr, ar);
+
+ sub_body(f, pr, ar);
+
fprintf(f, "#endif\n");
}
diff --git a/src/gen.h b/src/gen.h
index a5b2899..3b941dd 100644
--- a/src/gen.h
+++ b/src/gen.h
@@ -4,6 +4,6 @@
#include "parse.h"
#include "analyse.h"
-void gen(FILE *f, struct parse_result_s pr, struct analyse_result_s ar);
+void gen(FILE *f, struct parse_result_s *pr, struct analyse_result_s *ar);
#endif
diff --git a/src/main.c b/src/main.c
index aca8ce4..bd2398f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,33 +4,15 @@
#include "analyse.h"
#include "gen.h"
-/* static void print_tree(struct analyse_tree_s *t) */
-/* { */
-/* unsigned i; */
-/* if (t->is_terminal) */
-/* printf("!"); */
-/* */
-/* if (t->branch_count > 1) */
-/* printf("("); */
-/* */
-/* for (i = 0; i < t->branch_count; i++) { */
-/* printf("%c", t->branch_chars[i]); */
-/* print_tree(t->branches[i]); */
-/* if (t->branch_count > 1 && i < t->branch_count - 1) */
-/* printf("|"); */
-/* } */
-/* */
-/* if (t->branch_count > 1) */
-/* printf(")"); */
-/* } */
+#include <stdio.h>
int main(int argc, char **argv)
{
FILE *fo = stdout;
FILE *fi = stdin;
const char *finame = "stdin";
- struct parse_result_s pr;
- struct analyse_result_s ar;
+ struct parse_result_s *pr;
+ struct analyse_result_s *ar;
opt_parse(argc, argv);
@@ -52,18 +34,13 @@ int main(int argc, char **argv)
ar = analyse(pr);
- /* print_tree(&ar.deftype_tree); */
- /* puts(""); */
- /* print_tree(&ar.var_tree); */
- /* puts(""); */
-
gen(fo, pr, ar);
if (fo != stdout)
fclose(fo);
- parse_result_wipe(&pr);
- analyse_result_wipe(&ar);
+ parse_result_free(pr);
+ analyse_result_free(ar);
return 0;
}
diff --git a/src/opt.c b/src/opt.c
index a50f4ca..9aea49b 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -43,9 +43,9 @@ void opt_parse(int argc, char **argv)
/* help */
if (options[0].was_seen) {
simple_opt_print_usage(stdout, 80, argv[0],
- "[-i input.confconf] [-o output.h]",
- "confconf is a config file parser generator for C",
- options);
+ "[-i input.confconf] [-o output.h]",
+ "confconf is a config file parser generator for C",
+ options);
exit(EXIT_SUCCESS);
}
@@ -61,7 +61,7 @@ void opt_parse(int argc, char **argv)
if (cend != '"' && cend != '<') {
fprintf(stderr, "%s: err: badly-formatted uthash header `%s`\n",
- argv[0], options[4].val.v_string);
+ argv[0], options[4].val.v_string);
exit(EXIT_FAILURE);
}
@@ -69,33 +69,33 @@ void opt_parse(int argc, char **argv)
cend = '>';
for (i = 1, c = options[4].val.v_string[1];
- c && c != cend && c != '\n';
- c = options[4].val.v_string[++i]
+ c && c != cend && c != '\n';
+ c = options[4].val.v_string[++i]
);
if (c != cend
- || options[4].val.v_string[i+1] != '\0'
- || strlen(options[4].val.v_string) > TOK_MAX_LEN
- || options[4].val.v_string[2] == '\0'
+ || options[4].val.v_string[i+1] != '\0'
+ || strlen(options[4].val.v_string) > TOK_MAX_LEN
+ || options[4].val.v_string[2] == '\0'
) {
fprintf(stderr, "%s: err: badly-formatted uthash header `%s`\n",
- argv[0], options[4].val.v_string);
+ argv[0], options[4].val.v_string);
exit(EXIT_FAILURE);
}
}
/* check suffix */
if (options[5].was_seen) {
- if (options[5].val.v_string[i] == '\0') {
+ if (options[5].val.v_string[0] == '\0') {
fprintf(stderr, "%s: err: badly-formatted name suffix ``\n",
- argv[0]);
+ argv[0]);
exit(EXIT_FAILURE);
}
for (i = 0; options[5].val.v_string[i] != '\0'; i++) {
if (!isalnum(options[5].val.v_string[i]) ) {
fprintf(stderr, "%s: err: badly-formatted name suffix `%s`\n",
- argv[0], options[5].val.v_string);
+ argv[0], options[5].val.v_string);
exit(EXIT_FAILURE);
}
}
@@ -106,27 +106,27 @@ void opt_parse(int argc, char **argv)
const char* opt_infile_str(void)
{
return (options[2].was_seen
- ? options[2].val.v_string
- : NULL);
+ ? options[2].val.v_string
+ : NULL);
}
const char* opt_outfile_str(void)
{
return (options[3].was_seen
- ? options[3].val.v_string
- : NULL);
+ ? options[3].val.v_string
+ : NULL);
}
const char* opt_header_str(void)
{
return (options[4].was_seen
- ? options[4].val.v_string
- : NULL);
+ ? options[4].val.v_string
+ : NULL);
}
const char* opt_suffix_str(void)
{
return (options[5].was_seen
- ? options[5].val.v_string
- : NULL);
+ ? options[5].val.v_string
+ : NULL);
}
diff --git a/src/parse.c b/src/parse.c
index 9e0a29b..05524a8 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1,4 +1,5 @@
#include "parse.h"
+
#include "err.h"
#include <assert.h>
@@ -14,7 +15,7 @@ static const char *curfname;
#define ERR_AT(l, c, ...) \
do { \
fprintf(stderr, "\x1B[1m%s:%zu:%zu:\x1B[0m ", \
- curfname, (l), (c)); \
+ curfname, (l), (c)); \
ERR(__VA_ARGS__); \
} while (0)
@@ -29,23 +30,111 @@ static const char *curfname;
do { \
if ((t).type == TOK_END) { \
ERR_AT((t).line, (t).col, "unexpected end of file (expected %s)", \
- (m) ); \
+ (m) ); \
} \
} while (0)
#define WARN_AT(l, c, ...) \
do { \
fprintf(stderr, "\x1B[1m%s:%zu:%zu:\x1B[0m ", \
- curfname, (l), (c)); \
+ curfname, (l), (c)); \
WARN(__VA_ARGS__); \
} while (0)
-static struct parse_result_s r;
+static struct parse_result_s prs;
+
+const char *parse_typestrs[] = {
+ [PARSE_TYPE_BOOL] = "bool",
+ [PARSE_TYPE_STRING] = "string",
+ [PARSE_TYPE_ID] = "id",
+ [PARSE_TYPE_INT] = "int",
+ [PARSE_TYPE_INTL] = "intl",
+ [PARSE_TYPE_INTLL] = "intll",
+ [PARSE_TYPE_UINT] = "uint",
+ [PARSE_TYPE_UINTL] = "uintl",
+ [PARSE_TYPE_UINTLL] = "uintll",
+ [PARSE_TYPE_FLOAT] = "float",
+ [PARSE_TYPE_DOUBLE] = "double",
+ [PARSE_TYPE_DOUBLEL] = "doublel"
+};
+
+int parse_typestr_to_type(const char *s)
+{
+ if (*s == 'b'
+ && *(++s) == 'o' && *(++s) == 'o'
+ && *(++s) == 'l' && *(++s) == '\0'
+ ) {
+ return PARSE_TYPE_BOOL;
+ } else if (*s == 's'
+ && *(++s) == 't' && *(++s) == 'r'
+ && *(++s) == 'i' && *(++s) == 'n'
+ && *(++s) == 'g' && *(++s) == '\0'
+ ) {
+ return PARSE_TYPE_STRING;
+ } else if (*s == 'i') {
+ s++;
+ if (*s == 'd' && *(++s) == '\0') {
+ return PARSE_TYPE_ID;
+ } else if (*s == 'n' && *(++s) == 't') {
+ s++;
+ if (*s == '\0') {
+ return PARSE_TYPE_INT;
+ } else if (*s == 'l') {
+ s++;
+ if (*s == '\0') {
+ return PARSE_TYPE_INTL;
+ } else if (*s == 'l' && *(++s) == '\0') {
+ return PARSE_TYPE_INTLL;
+ } else {
+ return -1;
+ }
+ }
+ }
+ } else if (*s == 'u'
+ && *(++s) == 'i' && *(++s) == 'n'
+ && *(++s) == 't'
+ ) {
+ s++;
+ if (*s == '\0') {
+ return PARSE_TYPE_UINT;
+ } else if (*s == 'l') {
+ s++;
+ if (*s == '\0') {
+ return PARSE_TYPE_UINTL;
+ } else if (*s == 'l' && *(++s) == '\0') {
+ return PARSE_TYPE_UINTLL;
+ } else {
+ return -1;
+ }
+ }
+ } else if (*s == 'f'
+ && *(++s) == 'l' && *(++s) == 'o'
+ && *(++s) == 'a' && *(++s) == 't'
+ && *(++s) == '\0'
+ ) {
+ return PARSE_TYPE_FLOAT;
+ } else if (*s == 'd'
+ && *(++s) == 'o' && *(++s) == 'u'
+ && *(++s) == 'b' && *(++s) == 'l'
+ && *(++s) == 'e'
+ ) {
+ s++;
+ if (*s == '\0') {
+ return PARSE_TYPE_DOUBLE;
+ } else if (*s == 'l' && *(++s) == '\0') {
+ return PARSE_TYPE_DOUBLEL;
+ } else {
+ return -1;
+ }
+ }
+
+ return -1;
+}
-static enum parse_type_e sub_parse_type(void)
+static int sub_parse_type(void)
{
struct tok_s t = tok_get();
- enum parse_type_e type = PARSE_TYPE_BOOL;
+ enum parse_type_e type = PARSE_TYPE_BOOL, tswp;
size_t l, c;
l = t.line;
@@ -71,41 +160,10 @@ static enum parse_type_e sub_parse_type(void)
ERR_AT(l, c, "invalid type `%s`", t.val);
}
- if (!strcmp(t.val, "bool"))
- return type;
-
- if (!strcmp(t.val, "string"))
- return type + PARSE_TYPE_STRING;
-
- if (!strcmp(t.val, "id"))
- return type + PARSE_TYPE_ID;
-
- if (!strcmp(t.val, "int"))
- return type + PARSE_TYPE_INT;
-
- if (!strcmp(t.val, "intl"))
- return type + PARSE_TYPE_INTL;
-
- if (!strcmp(t.val, "intll"))
- return type + PARSE_TYPE_INTLL;
+ tswp = parse_typestr_to_type(t.val);
- if (!strcmp(t.val, "uint"))
- return type + PARSE_TYPE_UINT;
-
- if (!strcmp(t.val, "uintl"))
- return type + PARSE_TYPE_UINTL;
-
- if (!strcmp(t.val, "uintll"))
- return type + PARSE_TYPE_UINTLL;
-
- if (!strcmp(t.val, "float"))
- return type + PARSE_TYPE_FLOAT;
-
- if (!strcmp(t.val, "double"))
- return type + PARSE_TYPE_DOUBLE;
-
- if (!strcmp(t.val, "doublel"))
- return type + PARSE_TYPE_DOUBLEL;
+ if (tswp != -1)
+ return type + tswp;
tok_unget(t);
@@ -113,7 +171,7 @@ static enum parse_type_e sub_parse_type(void)
}
static void sub_parse_deftype(size_t line, size_t col,
- enum parse_deftype_e dtype)
+ enum parse_deftype_e dtype)
{
struct tok_s t;
enum parse_type_e type;
@@ -125,68 +183,62 @@ static void sub_parse_deftype(size_t line, size_t col,
.type = dtype,
.is_in_array = false,
.is_in_hash = false,
+ .contains_heap = false,
.member_list_len = 0,
};
unsigned i, j;
+ /* name */
+
t = tok_get();
ERR_END(t,
- (dt.type == PARSE_DEFTYPE_UNION ? "union name" :
- (dt.type == PARSE_DEFTYPE_STRUCT ?
- "struct name" : "enum name"
- )
+ (dt.type == PARSE_DEFTYPE_UNION ? "union name" :
+ (dt.type == PARSE_DEFTYPE_STRUCT ?
+ "struct name" : "enum name"
)
+ )
);
ERR_LONG(t);
if (t.type != TOK_ID) {
- ERR_AT(t.line, t.col, "unexpected token `%s` (expected %s name)",
- t.val,
- (dt.type == PARSE_DEFTYPE_UNION ? "union"
- : (dt.type == PARSE_DEFTYPE_STRUCT ? "struct" : "enum")
- )
- );
+ ERR_AT(t.line, t.col, "unexpected token `%s` (expected %s name)",
+ t.val,
+ (dt.type == PARSE_DEFTYPE_UNION ? "union"
+ : (dt.type == PARSE_DEFTYPE_STRUCT ? "struct" : "enum")
+ )
+ );
}
- if (
- dt.type != PARSE_DEFTYPE_ENUM && (
- !strcmp(t.val, "hash") || !strcmp(t.val, "array") ||
- !strcmp(t.val, "bool") ||
- !strcmp(t.val, "string") || !strcmp(t.val, "id") ||
- !strcmp(t.val, "int") || !strcmp(t.val, "intl") ||
- !strcmp(t.val, "intll") ||
- !strcmp(t.val, "uint") || !strcmp(t.val, "uintl") ||
- !strcmp(t.val, "uintll") ||
- !strcmp(t.val, "float") || !strcmp(t.val, "double") ||
- !strcmp(t.val, "doublell")
- )
- ) {
+ if (parse_typestr_to_type(t.val) != -1) {
ERR_AT(dt.line, dt.col,
- "defined type conflicts with builtin type `%s`", t.val);
+ "defined type conflicts with builtin type `%s`", t.val);
}
- HASH_FIND_STR(r.deftypes, t.val, dtp);
+ HASH_FIND_STR(prs.deftypes, t.val, dtp);
if (dtp != NULL) {
ERR_AT(dt.line, dt.col,
- "type `%s` redefined (previous definition was at line %zu)",
- t.val, dtp->line);
+ "type `%s` redefined (previous definition was at line %zu)",
+ t.val, dtp->line);
}
strcpy(dt.name, t.val);
+ /* { */
+
t = tok_get();
ERR_END(t, "`{`");
if (t.type != TOK_LBRACE)
ERR_AT(t.line, t.col, "unexpected token `%s` (expected `{`)", t.val);
+ /* body */
+
while (true) {
if (dt.member_list_len == PARSE_DEFTYPE_MAX_LEN) {
ERR_AT(dt.line, dt.col, "%s %s has too many %s",
- (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
- (dt.type == PARSE_DEFTYPE_UNION ?
- "union" : "struct")
- ),
- dt.name,
- (dt.type == PARSE_DEFTYPE_ENUM ? "ids" : "members")
+ (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
+ (dt.type == PARSE_DEFTYPE_UNION ? "union" : "struct")
+ ),
+ dt.name,
+ (dt.type == PARSE_DEFTYPE_ENUM ? "ids" : "members")
);
}
@@ -194,12 +246,11 @@ static void sub_parse_deftype(size_t line, size_t col,
if (t.type == TOK_RBRACE) {
if (dt.member_list_len < 2) {
ERR_AT(dt.line, dt.col, "%s `%s` must specify at fewest two %s",
- (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
- (dt.type == PARSE_DEFTYPE_UNION ?
- "union" : "struct")
- ),
- dt.name,
- (dt.type == PARSE_DEFTYPE_ENUM ? "ids" : "members")
+ (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
+ (dt.type == PARSE_DEFTYPE_UNION ? "union" : "struct")
+ ),
+ dt.name,
+ (dt.type == PARSE_DEFTYPE_ENUM ? "ids" : "members")
);
}
@@ -209,51 +260,55 @@ static void sub_parse_deftype(size_t line, size_t col,
if (dt.type != PARSE_DEFTYPE_ENUM) {
tok_unget(t);
- ERR_END(t, "type or `}`");
+ ERR_END(t,
+ (dt.member_list_len < 2 ? "type" : "type or `}`")
+ );
type = sub_parse_type();
if (type >= PARSE_TYPE_ARRAY_BOOL) {
ERR_AT(t.line, t.col,
- "defined types may not contain arrays or hashes");
+ "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");
+ "defined types may not contain other defined types");
}
+ if (type == PARSE_TYPE_STRING || type == PARSE_TYPE_ID)
+ dt.contains_heap = true;
+
t = tok_get();
}
- ERR_END(t, (dt.type == PARSE_DEFTYPE_ENUM ? "id or `}`"
- : "member name"));
+ ERR_END(t,
+ (dt.type == PARSE_DEFTYPE_ENUM
+ ? (dt.member_list_len > 1 ? "id or `}`" : "id")
+ : "member name"
+ )
+ );
ERR_LONG(t);
if (t.type != TOK_ID) {
if (t.type == TOK_RBRACE || t.type == TOK_COMMA) {
ERR_AT(t.line, t.col, "missing %s in %s `%s'",
- (dt.type == PARSE_DEFTYPE_ENUM ? "id" : "member name"),
- (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
- (dt.type == PARSE_DEFTYPE_UNION ?
- "union" : "struct"
- )
- ),
- dt.name
+ (dt.type == PARSE_DEFTYPE_ENUM ? "id" : "member name"),
+ (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
+ (dt.type == PARSE_DEFTYPE_UNION ? "union" : "struct")
+ ),
+ dt.name
);
}
ERR_AT(t.line, t.col, "bad %s `%s` in %s %s",
- (dt.type == PARSE_DEFTYPE_ENUM ? "id" : "member name"),
- t.val,
- (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
- (dt.type == PARSE_DEFTYPE_UNION ?
- "union" : "struct"
- )
- ),
- dt.name
+ (dt.type == PARSE_DEFTYPE_ENUM ? "id" : "member name"),
+ t.val,
+ (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
+ (dt.type == PARSE_DEFTYPE_UNION ? "union" : "struct")
+ ),
+ dt.name
);
}
@@ -270,24 +325,32 @@ static void sub_parse_deftype(size_t line, size_t col,
for (j = i + 1; j < dt.member_list_len; j++) {
if (!strcmp(dt.member_name_list[i], dt.member_name_list[j]) ) {
ERR_AT(dt.line, dt.col,
- "%s `%s` contains multiple %s named `%s`",
- (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
- (dt.type == PARSE_DEFTYPE_UNION ?
- "union" : "struct")
- ),
- dt.name,
- (dt.type == PARSE_DEFTYPE_ENUM ? "ids" : "members"),
- dt.member_name_list[i]
+ "%s `%s` contains multiple %s named `%s`",
+ (dt.type == PARSE_DEFTYPE_ENUM ? "enum" :
+ (dt.type == PARSE_DEFTYPE_UNION ? "union" : "struct")
+ ),
+ dt.name,
+ (dt.type == PARSE_DEFTYPE_ENUM ? "ids" : "members"),
+ dt.member_name_list[i]
);
}
+ if (dt.type == PARSE_DEFTYPE_UNION
+ && dt.member_type_list[i] == dt.member_type_list[j]
+ ) {
+ ERR_AT(dt.line, dt.col,
+ "union `%s` contains multiple members of type %s",
+ dt.name,
+ parse_typestrs[dt.member_type_list[i]]
+ );
+ }
}
}
TRYALLOC(dtp, 1);
memcpy(dtp, &dt, sizeof(*dtp));
- HASH_ADD_STR(r.deftypes, name, dtp);
+ HASH_ADD_STR(prs.deftypes, name, dtp);
}
static bool sub_parse_op(void)
@@ -306,10 +369,10 @@ static bool sub_parse_op(void)
return true;
case TOK_OP_NAMING_SUFFIX:
- if (r.suffix_seen) {
+ if (prs.suffix_seen) {
WARN_AT(t.line, t.col,
- "naming suffix redefined (previous value was `%s`)",
- r.suffix);
+ "naming suffix redefined (previous value was `%s`)",
+ prs.suffix);
}
t = tok_get();
@@ -318,17 +381,17 @@ static bool sub_parse_op(void)
if (t.type != TOK_ID)
ERR_AT(t.line, t.col, "invalid naming suffix `%s`", t.val);
- strcpy(r.suffix, t.val);
+ strcpy(prs.suffix, t.val);
- r.suffix_seen = true;
+ prs.suffix_seen = true;
return true;
case TOK_OP_UTHASH_HEADER:
- if (r.header_seen) {
+ if (prs.header_seen) {
WARN_AT(t.line, t.col,
- "uthash header redefined (previous value was %s)",
- r.header);
+ "uthash header redefined (previous value was %s)",
+ prs.header);
}
t = tok_get();
@@ -337,9 +400,9 @@ static bool sub_parse_op(void)
if (t.type != TOK_HEADER)
ERR_AT(t.line, t.col, "invalid uthash header `%s`", t.val);
- strcpy(r.header, t.val);
+ strcpy(prs.header, t.val);
- r.header_seen = true;
+ prs.header_seen = true;
return true;
@@ -376,14 +439,14 @@ static bool sub_parse_rule(void)
ERR_LONG(t);
if (t.type != TOK_ID) {
ERR_AT(t.line, t.col,
- "unexpected token `%s`, (expected variable name)", t.val);
+ "unexpected token `%s`, (expected variable name)", t.val);
}
- HASH_FIND_STR(r.vars, t.val, vp);
+ HASH_FIND_STR(prs.vars, t.val, vp);
if (vp != NULL) {
ERR_AT(v.line, v.col,
- "`%s` redefined (previous definition was at line %zu)",
- t.val, vp->line);
+ "`%s` redefined (previous definition was at line %zu)",
+ t.val, vp->line);
}
strcpy(v.name, t.val);
@@ -396,8 +459,8 @@ static bool sub_parse_rule(void)
v.type = sub_parse_type();
if (v.type == PARSE_TYPE_DEFTYPE
- || v.type == PARSE_TYPE_ARRAY_DEFTYPE
- || v.type == PARSE_TYPE_HASH_DEFTYPE
+ || v.type == PARSE_TYPE_ARRAY_DEFTYPE
+ || v.type == PARSE_TYPE_HASH_DEFTYPE
) {
t = tok_get();
strcpy(v.deftype_name, t.val);
@@ -405,13 +468,13 @@ static bool sub_parse_rule(void)
TRYALLOC(vp, 1);
memcpy(vp, &v, sizeof(*vp));
- HASH_ADD_STR(r.vars, name, vp);
+ HASH_ADD_STR(prs.vars, name, vp);
return true;
}
static int sub_sort_deftypes(struct parse_deftype_s *d1,
- struct parse_deftype_s *d2)
+ struct parse_deftype_s *d2)
{
return strcmp(d1->name, d2->name);
}
@@ -421,7 +484,7 @@ static int sub_sort_vars(struct parse_var_s *v1, struct parse_var_s *v2)
return strcmp(v1->name, v2->name);
}
-struct parse_result_s parse(FILE *f, const char *fname)
+struct parse_result_s* parse(FILE *f, const char *fname)
{
size_t i, j;
struct tok_s t;
@@ -429,10 +492,17 @@ struct parse_result_s parse(FILE *f, const char *fname)
struct parse_var_s *vcur, *vtmp;
struct parse_deftype_s *dcur, *dtmp;
- r.suffix_seen = false;
- r.header_seen = false;
- r.deftypes = NULL;
- r.vars = NULL;
+ struct parse_result_s *pr;
+
+ assert(f != NULL);
+ assert(fname != NULL);
+
+ TRYALLOC(pr, 1);
+
+ prs.suffix_seen = false;
+ prs.header_seen = false;
+ prs.deftypes = NULL;
+ prs.vars = NULL;
curfname = fname;
tok_reset(f);
@@ -448,22 +518,22 @@ struct parse_result_s parse(FILE *f, const char *fname)
}
/* err >0 rules */
- if (r.vars == NULL) {
+ if (prs.vars == NULL) {
fprintf(stderr, "\x1B[1m%s:\x1B[0m ", fname);
ERR("config must specify at fewest one variable rule");
}
/* err undefined type */
- HASH_ITER(hh, r.vars, vcur, vtmp) {
+ HASH_ITER(hh, prs.vars, vcur, vtmp) {
switch (vcur->type) {
case PARSE_TYPE_DEFTYPE:
case PARSE_TYPE_ARRAY_DEFTYPE:
case PARSE_TYPE_HASH_DEFTYPE:
- HASH_FIND_STR(r.deftypes, vcur->deftype_name, dcur);
+ HASH_FIND_STR(prs.deftypes, vcur->deftype_name, dcur);
if (dcur == NULL) {
ERR_AT(vcur->line, vcur->col,
- "rule for variable `%s` references undefined type `%s`",
- vcur->name, vcur->deftype_name);
+ "rule for variable `%s` references undefined type `%s`",
+ vcur->name, vcur->deftype_name);
}
dcur->is_used = true;
if (vcur->type == PARSE_TYPE_ARRAY_DEFTYPE)
@@ -477,31 +547,31 @@ struct parse_result_s parse(FILE *f, const char *fname)
}
/* warn type use */
- HASH_ITER(hh, r.deftypes, dcur, dtmp) {
+ HASH_ITER(hh, prs.deftypes, dcur, dtmp) {
if (!dcur->is_used) {
WARN_AT(dcur->line, dcur->col,
- "type `%s` defined but not used",
- dcur->name);
+ "type `%s` defined but not used",
+ dcur->name);
}
}
/* warn hash header */
- HASH_ITER(hh, r.vars, vcur, vtmp) {
- if (vcur->type >= PARSE_TYPE_HASH_BOOL && !r.header_seen) {
+ HASH_ITER(hh, prs.vars, vcur, vtmp) {
+ if (vcur->type >= PARSE_TYPE_HASH_BOOL && !prs.header_seen) {
fprintf(stderr, "\x1B[1m%s:\x1B[0m ", fname);
WARN("no uthash location header specified. using `<uthash.h>`");
- strcpy(r.header, "<uthash.h>");
+ strcpy(prs.header, "<uthash.h>");
break;
}
}
/* warn/err suffix */
- if (!r.suffix_seen) {
+ if (!prs.suffix_seen) {
j = 0;
for (i = strlen(fname); i > 0 && fname[i] != '/'
- && fname[i] != '\\'; i--);
+ && fname[i] != '\\'; i--);
j = i + (fname[i] == '/' || fname[i] == '\\');
@@ -510,45 +580,48 @@ struct parse_result_s parse(FILE *f, const char *fname)
fprintf(stderr, "\x1B[1m%s:\x1B[0m ", fname);
ERR("no function suffix specified, and could not generate one");
}
- r.suffix[i - j] = fname[i];
+ prs.suffix[i - j] = fname[i];
}
- r.suffix[i - j] = '\0';
+ prs.suffix[i - j] = '\0';
- if (r.suffix[0] == '\0') {
+ if (prs.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.suffix);
+ WARN("no function suffix specified. using `%s`...", prs.suffix);
}
- HASH_SORT(r.deftypes, sub_sort_deftypes);
- HASH_SORT(r.vars, sub_sort_vars);
+ HASH_SORT(prs.deftypes, sub_sort_deftypes);
+ HASH_SORT(prs.vars, sub_sort_vars);
+
+ memcpy(pr, &prs, sizeof(struct parse_result_s));
- return r;
+ return pr;
}
-void parse_result_wipe(struct parse_result_s *r)
+void parse_result_free(struct parse_result_s *pr)
{
struct parse_var_s *vcur, *vtmp;
struct parse_deftype_s *dcur, *dtmp;
- assert(r != NULL);
+ assert(pr != NULL);
- if (r->vars != NULL) {
- HASH_ITER(hh, r->vars, vcur, vtmp) {
- HASH_DEL(r->vars, vcur);
+ if (pr->vars != NULL) {
+ HASH_ITER(hh, pr->vars, vcur, vtmp) {
+ HASH_DEL(pr->vars, vcur);
free(vcur);
}
}
- if (r->deftypes != NULL) {
- HASH_ITER(hh, r->deftypes, dcur, dtmp) {
- HASH_DEL(r->deftypes, dcur);
+ if (pr->deftypes != NULL) {
+ HASH_ITER(hh, pr->deftypes, dcur, dtmp) {
+ HASH_DEL(pr->deftypes, dcur);
free(dcur);
}
}
+ free(pr);
}
diff --git a/src/parse.h b/src/parse.h
index 4f2645d..1ab2a19 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -7,7 +7,7 @@
#include <stdbool.h>
-#define PARSE_DEFTYPE_MAX_LEN 32
+#define PARSE_DEFTYPE_MAX_LEN 128
/* very important these stay in order.
* things like ">= PARSE_TYPE_ARRAY_BOOL" used */
@@ -69,6 +69,7 @@ struct parse_deftype_s {
bool is_used;
bool is_in_array;
bool is_in_hash;
+ bool contains_heap;
unsigned member_list_len;
enum parse_type_e member_type_list[PARSE_DEFTYPE_MAX_LEN];
char member_name_list[PARSE_DEFTYPE_MAX_LEN][TOK_MAX_LEN];
@@ -94,8 +95,12 @@ struct parse_result_s {
struct parse_var_s *vars;
};
-struct parse_result_s parse(FILE *f, const char *fname);
+extern const char *parse_typestrs[];
-void parse_result_wipe(struct parse_result_s *r);
+int parse_typestr_to_type(const char *s);
+
+struct parse_result_s* parse(FILE *f, const char *fname);
+
+void parse_result_free(struct parse_result_s *pr);
#endif
diff --git a/src/tok.c b/src/tok.c
index 9b57459..e6b385d 100644
--- a/src/tok.c
+++ b/src/tok.c
@@ -236,6 +236,8 @@ static void sub_match_header(void)
void tok_reset(FILE *f)
{
+ assert(f != NULL);
+
curf = f;
curtok.line = 1;
curtok.col = 1;
@@ -252,7 +254,7 @@ struct tok_s tok_get(void)
if (unget) {
unget = false;
return curtok;
- }
+ }
curtok.col += vlen;
vlen = 0;