diff options
author | katherine <ageha@airen-no-jikken.icu> | 2019-07-10 20:24:08 -0700 |
---|---|---|
committer | katherine <ageha@airen-no-jikken.icu> | 2019-07-10 20:24:08 -0700 |
commit | 06cb82a8ccc3587dff728321dff5416b18090483 (patch) | |
tree | 95dc02df244856b5ede95a3a1a44ea756e850203 /src | |
parent | 34271c906a2de43a68d2fa764d31e6f5b2c3299f (diff) | |
download | confconf-06cb82a8ccc3587dff728321dff5416b18090483.tar.gz |
implement deftype get
Diffstat (limited to 'src')
-rw-r--r-- | src/analyse.c | 273 | ||||
-rw-r--r-- | src/analyse.h | 22 | ||||
-rw-r--r-- | src/gen-consts.h | 691 | ||||
-rw-r--r-- | src/gen.c | 788 | ||||
-rw-r--r-- | src/gen.h | 2 | ||||
-rw-r--r-- | src/main.c | 33 | ||||
-rw-r--r-- | src/opt.c | 42 | ||||
-rw-r--r-- | src/parse.c | 395 | ||||
-rw-r--r-- | src/parse.h | 11 | ||||
-rw-r--r-- | src/tok.c | 4 |
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" -; @@ -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"); } @@ -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 @@ -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; } @@ -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 @@ -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; |