confetti-20120731/0000755000000000000000000000000012006156037012264 5ustar rootrootconfetti-20120731/confetti.c0000664000000000000000000000542512005741242014250 0ustar rootroot#include #include #include #include #include #include static void usage() { fputs( "Copyright (c) 2010 Teodor Sigaev . All rights reserved.\n" "Usage:\n" "confetti -i INPUTFILE [-D] (-c COUTFILE -n NAME | -h HOUTFILE -n NAME | -f CFGOUTFILE | -p PARSEROUTFILE | -H HPARSEOUTFILE)\n", stdout ); exit(1); } extern char *optarg; extern int opterr; int main(int argc, char* argv[]) { char *ifn = NULL, *cfn = NULL, *hfn = NULL, *cfgfn = NULL, *pfn = NULL, *Hfn = NULL; FILE *fh; char *name = NULL; int i, debug = 0;; ParamDef *def; opterr=0; while((i=getopt(argc,argv,"i:c:h:f:n:p:H:D")) != EOF) { switch(i) { case 'i': ifn = strdup(optarg); break; case 'c': cfn = strdup(optarg); break; case 'h': hfn = strdup(optarg); break; case 'f': cfgfn = strdup(optarg); break; case 'p': pfn = strdup(optarg); break; case 'H': Hfn = strdup(optarg); break; case 'n': name = strdup(optarg); break; case 'D': debug = 1; break; default: usage(); } } if ( !ifn ) usage(); if ( (fh = fopen(ifn, "r")) == NULL ) { fprintf(stderr, "Could not open file '%s': %s\n", ifn, strerror(errno)); exit(1); } if ( (def = parseCfgDef(fh)) == NULL ) { fprintf(stderr, "Could not parse file '%s'\n", ifn); exit(1); } fclose(fh); if (debug) dDump(def); if ( hfn ) { if (!name) usage(); if (strcmp(hfn, "-") == 0) { fh = stdout; } else if ((fh = fopen(hfn, "w")) == NULL ) { fprintf(stderr, "Could not open file '%s': %s\n", hfn, strerror(errno)); exit(1); } hDump(fh, name, def); if (fh != stdout) fclose(fh); } if ( cfn ) { if (!name) usage(); if (strcmp(cfn, "-") == 0) { fh = stdout; } else if ((fh = fopen(cfn, "w")) == NULL ) { fprintf(stderr, "Could not open file '%s': %s\n", cfn, strerror(errno)); exit(1); } cDump(fh, name, def); if (fh != stdout) fclose(fh); } if ( cfgfn ) { if (strcmp(cfgfn, "-") == 0) { fh = stdout; } else if ((fh = fopen(cfgfn, "w")) == NULL ) { fprintf(stderr, "Could not open file '%s': %s\n", cfgfn, strerror(errno)); exit(1); } fDump(fh, def); if (fh != stdout) fclose(fh); } if ( pfn ) { if (strcmp(pfn, "-") == 0) { fh = stdout; } else if ((fh = fopen(pfn, "w")) == NULL ) { fprintf(stderr, "Could not open file '%s': %s\n", pfn, strerror(errno)); exit(1); } pDump(fh, def); if (fh != stdout) fclose(fh); } if ( Hfn ) { if (strcmp(Hfn, "-") == 0) { fh = stdout; } else if ((fh = fopen(Hfn, "w")) == NULL ) { fprintf(stderr, "Could not open file '%s': %s\n", Hfn, strerror(errno)); exit(1); } HDump(fh); if (fh != stdout) fclose(fh); } exit(0); } confetti-20120731/INSTALL0000664000000000000000000000003512005741242013312 0ustar rootrootTo build, just type 'make'. confetti-20120731/p_dump.c0000664000000000000000000000202712005741242013714 0ustar rootroot#include #include static char* parserSource[] = { "#include \n\n" "typedef struct prscfg_yy_extra_type {\n" " char *strbuf;\n" " int length;\n" " int total;\n" " int lineno;\n" " int commentCounter;\n" "} prscfg_yy_extra_type;\n" "typedef void *prscfg_yyscan_t;\n" "static prscfg_yyscan_t prscfgScannerInit(FILE *fh, prscfg_yy_extra_type *yyext);\n" "static prscfg_yyscan_t prscfgScannerInitBuffer(char *buffer, prscfg_yy_extra_type *yyext);\n" "static void prscfgScannerFinish(prscfg_yyscan_t scanner);\n" "static int prscfgGetLineNo(prscfg_yyscan_t yyscanner);\n\n", #include "parse_source.c" NULL }; static char* headerSource[] = { #include "header_source.c" NULL }; void pDump(FILE *fh, ParamDef *def) { char **source = parserSource; if (def->paramType == builtinType) fputs(def->paramValue.stringval, fh); while(*source) { fputs(*source, fh); source++; } } void HDump(FILE *fh) { char **source = headerSource; while(*source) { fputs(*source, fh); source++; } } confetti-20120731/example/0000775000000000000000000000000012005741242013716 5ustar rootrootconfetti-20120731/example/example.c0000664000000000000000000000472112005741242015521 0ustar rootroot#include #include #include #include #include static int useStdout = 0; void out_warning(ConfettyError r __attribute__ ((unused)), char *format, ...) { va_list args; va_start(args, format); vfprintf(useStdout ? stdout : stderr, format, args); va_end(args); if (useStdout) fputc('\n', stdout); } int main(int argc, char* argv[]) { my_product cfg, dup_cfg; my_product_iterator_t *i; char *key, *value; fill_default_my_product(&cfg); if (argc > 1) { cfg.array_of_ro_structs = malloc((1 + 1) * sizeof(cfg.array_of_ro_structs)); cfg.array_of_ro_structs[0] = malloc(sizeof(**cfg.array_of_ro_structs)); cfg.array_of_ro_structs[0]->__confetti_flags = 0; cfg.array_of_ro_structs[0]->f1 = 1; cfg.array_of_ro_structs[0]->f2 = 2; cfg.array_of_ro_structs[1] = NULL; } if (argc > 1) { int nAccepted, nSkipped, nOptional; FILE *fh = fopen(argv[1], "r"); if (!fh) { fprintf(stderr, "Could not open file %s\n", argv[1]); return 1; } useStdout = 1; parse_cfg_file_my_product(&cfg, fh, 1, &nAccepted, &nSkipped, &nOptional); printf("==========Accepted: %d; Skipped: %d; Optional: %d===========\n", nAccepted, nSkipped, nOptional); fclose(fh); } i = my_product_iterator_init(); while ( (key = my_product_iterator_next(i, &cfg, &value)) != NULL ) { if (value) { printf("%s => '%s'\n", key, value); free(value); } else { printf("%s => (null)\n", key); } } printf("==========Check===========\n"); useStdout = 1; printf("Missed required: %d\n", check_cfg_my_product(&cfg)); typeof(cfg.root_array) root_array = cfg.root_array; unsigned k = 0; while (root_array && *root_array) { if (!CNF_STRUCT_DEFINED(*root_array)) printf("root_array[%u] is not defined\n", k); ++k; ++root_array; } printf("==========Dup=============\n"); dup_my_product(&dup_cfg, &cfg); i = my_product_iterator_init(); while ( (key = my_product_iterator_next(i, &dup_cfg, &value)) != NULL ) { if (value) { printf("%s => '%s'\n", key, value); free(value); } else { printf("%s => (null)\n", key); } } printf("==========Compare=========\n"); if (cmp_my_product(&cfg, &dup_cfg, 0) != 0) printf("total: differ\n"); else printf("total: equal\n"); if (cmp_my_product(&cfg, &dup_cfg, 1) != 0) printf("only_rdonly: differ\n"); else printf("only_rdonly: equal\n"); printf("==========Destroy=========\n"); destroy_my_product(&cfg); destroy_my_product(&dup_cfg); return 0; } confetti-20120731/example/example.cfgtmpl0000664000000000000000000000173212005741242016732 0ustar rootroot%{ #include #include void out_warning(ConfettyError r, char *format, ...); %} # foo value is responsible1 foo=1234U, required bar=-54321L asdf= { # asdfffffas asdd k1 = "as\"d" # lkjhsdfiuher # =========================r k2 = NULL, required # substruct array = [ qwerty=123.9, ro qwer1=123 substruct = { sss = "asdf.array.substruct.sss", required } subarray = [ subkey = 12 subke12 = 7654UL, required ], ro ] k3 = NULL } root_array = [ ra = -1.344e-08, required ], required test = [ #checl reqelem { e=1 }, required ] empty = [ wow=NULL ], required ro_struct = { f1 = 1 f2 = 2 }, ro array_of_ro_structs = [ { f1 = 1 f2 = 2 }, ro ] required_struct_with_structs = { f1 = 1 f2 = 2 s1 = { f1 = 1 f2 = 2 ss1 = { f1 = 1 f2 = 2 } } }, required array_with_required_structs_with_structs = [ { f1 = 1 f2 = 2 s = { f1 = 1 f2 = 2 f3 = false } }, required ] flsb = false flst = true confetti-20120731/example/Makefile0000664000000000000000000000204112005741242015353 0ustar rootrootCONFETTI=../confetti NAME=my_product CFG=example.cfgtmpl CC=gcc CFLAGS=-Wall -g -O0 -Werror -std=gnu99 INCLUDE=-I. LIB= example_OBJS=example.o my_product_cfg.o prscfg.o example_buffer_OBJS=example_buffer.o my_product_cfg.o prscfg.o all: $(NAME).cfg example example_buffer example.c: $(NAME)_cfg.h prscfg.h example_buffer.c: $(NAME)_cfg.h prscfg.h .SUFFIXES: .o.c .c.o: $(CC) $(CFLAGS) $(INCLUDE) -c $< example: $(example_OBJS) $(CC) -o $@ $(example_OBJS) $(LIB) example_buffer: $(example_buffer_OBJS) $(CC) -o $@ $(example_buffer_OBJS) $(LIB) $(NAME).cfg: $(CFG) $(CONFETTI) -i $< -n $(NAME) -f $@ $(NAME)_cfg.c: $(CFG) $(CONFETTI) -i $< -n $(NAME) -c $@ $(NAME)_cfg.h: $(CFG) $(CONFETTI) -i $< -n $(NAME) -h $@ prscfg.c: $(CFG) $(CONFETTI) -i $< -p $@ prscfg.h: $(CFG) $(CONFETTI) -i $< -H $@ prscfg.c: prscfg.h $(NAME)_cfg.h $(NAME)_cfg.c: prscfg.h $(NAME)_cfg.h clean: rm -f $(NAME).cfg $(NAME)_cfg.c $(NAME)_cfg.h rm -f prscfg.c prscfg.h rm -f $(example_OBJS) $(example_buffer_OBJS) rm -f example example_buffer *core confetti-20120731/example/example_buffer.c0000664000000000000000000000205712005741242017052 0ustar rootroot#include #include #include #include #include void out_warning(ConfettyError r __attribute__ ((unused)), char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); } int main(int argc __attribute__ ((unused)), char* argv[] __attribute__ ((unused))) { my_product cfg; my_product_iterator_t *i; char *key, *value; int nAccepted, nSkipped, nOptional; fill_default_my_product(&cfg); parse_cfg_buffer_my_product( &cfg, "asdf.array[2].subarray[3].subkey = 123456789 " "root_array[3].ra = 12 " "asdf.k2=\"NEWVALUE\" " "opt no_such_param = 123", 0, &nAccepted, &nSkipped, &nOptional ); printf("==========Accepted: %d; Skipped: %d; Optional: %d===========\n", nAccepted, nSkipped, nOptional); i = my_product_iterator_init(); while ( (key = my_product_iterator_next(i, &cfg, &value)) != NULL ) { if (value) { printf("%s => '%s'\n", key, value); free(value); } else { printf("%s => (null)\n", key); } } return 0; } confetti-20120731/example/my_my_product.cfg0000664000000000000000000000315612005741242017276 0ustar rootroot # foo value is responsible1 foo = 1234 bar = -54321 bar = -987654 asdf = { # asdfffffas asdd k1 = "as\"d" # lkjhsdfiuher # =========================r k2 = NULL # substruct array = [ { qwerty = 121.9 qwer1 = -123 substruct = { sss = HEY } subarray = [ { subkey = 12 subke12 = 7654 } { subkey = 15, subke12 = 111 }, ] }, { qwerty = 1 qwer1 = 2 substruct = { sss = FOO } subarray = [ { subkey = 1123, subke12 = 12233, } ] } ] } asdf.k2="NEWVALUE" asdf.array[2].subarray[3].subkey = 123456789 asdf.array[2].substruct = { sss = /path-to/something/%d._log, } asdf.array[1].subarray = [ { subke12 = 10001 }, { subke12 = 10002 } { subke12 = 10003 } ] asdf.array[2] = { qwerty = 100001 qwer1 = 100002 , } root_array = [ { ra = -1e-08 } ] root_array[0].ra = -1e-9 root_array[3].ra = 12 test[0].e = 0 test[2].e = 2 empty=[] ro_struct = { f1 = 2 } array_of_ro_structs = [ { f1 = 2 } ] required_struct_with_structs = { s1 = { ss1 = { f2 = 2 } } } array_with_required_structs_with_structs[0].s.f1 = 1 array_with_required_structs_with_structs[2].f2 = 2 array_with_required_structs_with_structs[2].s.f3 = enable [asdf] k3=NOTNULL [root_array[4]] ra = 13 confetti-20120731/prscfg.y0000664000000000000000000002166612005741242013754 0ustar rootroot%{ #undef yylval #undef yylloc #include #include #include #include #include #include static int prscfg_yyerror(prscfg_yyscan_t yyscanner, const char *msg); extern int prscfg_yylex (YYSTYPE * yylval_param, prscfg_yyscan_t yyscanner); static NameAtom* prependName(NameAtom *prep, NameAtom *name); static void freeName(NameAtom *atom); static OptDef *output; #define MakeAtom(r, n) do { \ (r) = malloc(sizeof(NameAtom)); \ if (!(r)) { \ prscfg_yyerror(yyscanner, "No memory"); \ YYERROR; \ } \ (r)->name = (n); \ (r)->index = -1; \ (r)->next = NULL; \ } while(0) #define MakeScalarParam(r, t, n, v, p) do { \ (r) = malloc(sizeof(OptDef)); \ if (!(r)) { \ prscfg_yyerror(yyscanner, "No memory"); \ YYERROR; \ } \ (r)->paramType = t##Type; \ (r)->optional = p; \ (r)->paramValue.t##val = (v); \ (r)->name = (n); \ (r)->parent = NULL; \ (r)->next = NULL; \ } while(0) #define MakeList(r, f, l) \ if (f) { \ (f)->next = (l); \ (r) = (f); \ } else { \ (r) = (l); \ } #define SetParent(p, l) do { \ OptDef *i = (l); \ while(i) { \ i->parent = (p); \ i = i->next; \ } \ } while(0) #define SetIndex(l, in) do { \ OptDef *i = (l); \ while(i) { \ i->name->index = (in); \ i = i->next; \ } \ } while(0) #define SetSection(out, in, sec) do { \ OptDef *opt; \ opt = (out) = (in); \ \ while(opt) { \ opt->name = prependName((sec), opt->name); \ \ opt = opt->next; \ } \ freeName(sec); \ } while(0) %} %pure-parser %expect 0 %name-prefix="prscfg_yy" %error-verbose %parse-param {prscfg_yyscan_t yyscanner} %lex-param {prscfg_yyscan_t yyscanner} %union { char *str; OptDef *node; NameAtom *atom; int flag; } %type cfg section_list section named_section %type param param_list struct_list %type identifier elem_identifier keyname array_keyname %type section_name %type opt; %type comma_opt %token NULL_P OPT_P KEY_P NATURAL_P STRING_P %% cfg: section_list { output = $$ = $1; } ; section_list: section { $$ = $1; } | section_list named_section { MakeList($$, $2, $1); } ; section: /* empty */ { $$ = NULL; } | param_list { $$ = $1; } named_section: '[' section_name ']' section { SetSection($$, $4, $2); } ; section_name: keyname { $$ = $1; } | array_keyname { $$ = $1; } param_list: param { $$ = $1; } | param_list comma_opt param { MakeList($$, $3, $1); /* plainOptDef will revert the list */ } ; identifier: KEY_P { MakeAtom($$, $1); } | NULL_P { MakeAtom($$, $1); } ; elem_identifier: identifier { $$ = $1; } | identifier '[' NATURAL_P ']' { $$ = $1; $$->index = atoi($3); /* XXX check !*/ free($3); } ; keyname: identifier { $$ = $1; } | elem_identifier '.' keyname { MakeList($$, $1, $3); } ; array_keyname: identifier '[' NATURAL_P ']' { $$ = $1; $$->index = atoi($3); /* XXX check !*/ free($3); } | elem_identifier '.' array_keyname { MakeList($$, $1, $3); } ; param: opt keyname '=' NULL_P { MakeScalarParam($$, scalar, $2, NULL, $1); free($4); } | opt keyname '=' OPT_P { MakeScalarParam($$, scalar, $2, $4, $1); } | opt keyname '=' KEY_P { MakeScalarParam($$, scalar, $2, $4, $1); } | opt keyname '=' NATURAL_P { MakeScalarParam($$, scalar, $2, $4, $1); } | opt keyname '=' STRING_P { MakeScalarParam($$, scalar, $2, $4, $1); } | opt keyname '=' '{' param_list comma_opt '}' { MakeScalarParam($$, struct, $2, $5, $1); SetParent( $$, $5 ); } | opt keyname '=' '[' struct_list comma_opt ']' { $5->name = $2; $5->optional = $1; $$ = $5; } | opt keyname '=' '[' ']' { MakeScalarParam($$, array, $2, NULL, $1); } | opt array_keyname '=' '{' param_list comma_opt '}' { MakeScalarParam($$, struct, $2, $5, $1); SetParent( $$, $5 ); } ; opt: /* empty */ { $$ = 0; } | OPT_P { $$ = 1; free($1); } comma_opt: ',' { $$=NULL; } | /* EMPTY */ { $$=NULL; } ; struct_list: '{' param_list comma_opt '}' { OptDef *str; NameAtom *idx; MakeAtom(idx, NULL); MakeScalarParam(str, struct, idx, $2, 0); SetParent( str, $2 ); SetIndex( str, 0 ); MakeScalarParam($$, array, NULL, str, 0); SetParent( $$, str ); } | struct_list comma_opt '{' param_list comma_opt '}' { OptDef *str; NameAtom *idx; MakeAtom(idx, NULL); MakeScalarParam(str, struct, idx, $4, 0); SetParent(str, $4); SetIndex(str, $1->paramValue.arrayval->name->index + 1); MakeList($1->paramValue.arrayval, str, $1->paramValue.arrayval); SetParent($1, str); $$ = $1; } ; %% static int prscfg_yyerror(prscfg_yyscan_t yyscanner, const char *msg) { out_warning(CNF_SYNTAXERROR, "gram_yyerror: %s at line %d", msg, prscfgGetLineNo(yyscanner)); return 0; } static NameAtom* cloneName(NameAtom *list, NameAtom **end) { NameAtom *newList = NULL, *ptr, *endptr = NULL; while(list) { ptr = *end = malloc(sizeof(*ptr)); if (!ptr) { out_warning(CNF_NOMEMORY, "No memory"); return NULL; } *ptr = *list; if (ptr->name) { ptr->name = strdup(ptr->name); if (!ptr->name) { out_warning(CNF_NOMEMORY, "No memory"); free(ptr); return NULL; } } if (newList) { endptr->next = ptr; endptr = ptr; } else { newList = endptr = ptr; } list = list->next; } return newList; } static NameAtom* prependName(NameAtom *prep, NameAtom *name) { NameAtom *b, *e; b = cloneName(prep, &e); if (!b) { out_warning(CNF_NOMEMORY, "No memory"); return NULL; } e->next = name; return b; } static void freeName(NameAtom *atom) { NameAtom *p; while(atom) { free(atom->name); p = atom->next; free(atom); atom = p; } } static int compileName(OptDef *def) { NameAtom *beginPtr = NULL, *endPtr, *list; OptDef *c = def; int index = -1; list = NULL; while(c) { if (c->name->name) { beginPtr = cloneName(c->name, &endPtr); if (!beginPtr) return 1; if (index >= 0) { endPtr->index = index; index = -1; } endPtr->next = list; list = beginPtr; } else { index = c->name->index; } c = c->parent; } def->name = list; return 0; } static OptDef* plainOptDef(OptDef *def, OptDef *list) { OptDef *ptr; while(def) { switch(def->paramType) { case scalarType: ptr = malloc(sizeof(*ptr)); if (!ptr) { out_warning(CNF_NOMEMORY, "No memory"); freeCfgDef(def); freeCfgDef(list); return NULL; } *ptr = *def; if (compileName(ptr)) { freeName(ptr->name); free(ptr); freeCfgDef(def); freeCfgDef(list); return NULL; } ptr->parent = NULL; ptr->next = list; list = ptr; break; case structType: list = plainOptDef(def->paramValue.structval, list); break; case arrayType: if (def->paramValue.arrayval == NULL) { ptr = malloc(sizeof(*ptr)); if (!ptr) { out_warning(CNF_NOMEMORY, "No memory"); freeCfgDef(def); freeCfgDef(list); return NULL; } *ptr = *def; if (compileName(ptr)) { freeName(ptr->name); free(ptr); freeCfgDef(def); freeCfgDef(list); return NULL; } ptr->parent = NULL; ptr->next = list; list = ptr; } else { list = plainOptDef(def->paramValue.arrayval, list); } break; default: out_warning(CNF_INTERNALERROR, "Unkown paramType: %d", def->paramType); } ptr = def->next; freeName(def->name); free(def); def = ptr; } return list; } void freeCfgDef(OptDef *def) { OptDef *ptr; while(def) { switch(def->paramType) { case scalarType: free(def->paramValue.scalarval); break; case structType: freeCfgDef(def->paramValue.structval); break; case arrayType: freeCfgDef(def->paramValue.arrayval); break; default: break; } ptr = def->next; freeName(def->name); free(def); def = ptr; } } OptDef* parseCfgDef(FILE *fh) { prscfg_yyscan_t yyscanner; prscfg_yy_extra_type yyextra; int yyresult; yyscanner = prscfgScannerInit(fh, &yyextra); output = NULL; yyresult = prscfg_yyparse(yyscanner); prscfgScannerFinish(yyscanner); if (yyresult != 0) return NULL; return plainOptDef(output, NULL); } OptDef* parseCfgDefBuffer(char *buffer) { prscfg_yyscan_t yyscanner; prscfg_yy_extra_type yyextra; int yyresult; yyscanner = prscfgScannerInitBuffer(buffer, &yyextra); output = NULL; yyresult = prscfg_yyparse(yyscanner); prscfgScannerFinish(yyscanner); if (yyresult != 0) return NULL; return plainOptDef(output, NULL); } confetti-20120731/f_dump.c0000664000000000000000000000470512005741242013707 0ustar rootroot#include #include #include #include void printPrefix(FILE *fh, int level) { int i; for(i=0; i < level*4; i++) fputc(' ', fh); } static void dumpComment(FILE *fh, int level, ParamDef *def) { if (def->comment) { ParamDef *i = def->comment; fputc('\n', fh); while(i) { printPrefix(fh, level); fprintf(fh, "# %s\n", i->paramValue.commentval); i = i->next; } } } static void dumpParamDef(FILE *fh, int level, ParamDef *def) { while(def) { if (def->paramType == builtinType) { def = def->next; continue; } dumpComment(fh, level, def); printPrefix(fh, level); fprintf(fh, "%s = ", def->name); switch(def->paramType) { case int32Type: fprintf(fh, "%"PRId32, def->paramValue.int32val); break; case uint32Type: fprintf(fh, "%"PRIu32, def->paramValue.int32val); break; case int64Type: fprintf(fh, "%"PRId64, def->paramValue.int64val); break; case uint64Type: fprintf(fh, "%"PRIu64, def->paramValue.uint64val); break; case doubleType: fprintf(fh, "%g", def->paramValue.doubleval); break; case stringType: if ( def->paramValue.stringval) { char *ptr = def->paramValue.stringval; fputc('\"', fh); while(*ptr) { if (*ptr == '"') fputc('\\', fh); fputc(*ptr, fh); ptr++; } fputc('\"', fh); } else { fputs("NULL", fh); } break; case boolType: fprintf(fh, "%s", def->paramValue.boolval ? "true" : "false"); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: fputs("{\n", fh); dumpParamDef(fh, level+1, def->paramValue.structval); printPrefix(fh, level); fputs("}", fh); break; case arrayType: fputs("[", fh); dumpComment(fh, level+1, def->paramValue.arrayval); printPrefix(fh, level+1); fputs("{\n", fh); dumpParamDef(fh, level+2, def->paramValue.arrayval->paramValue.structval); printPrefix(fh, level+1); fputs("}\n", fh); printPrefix(fh, level); fputs("]", fh); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } fputc('\n', fh); def = def->next; } } void fDump(FILE *fh, ParamDef *def) { ParamDef root; root.paramType = structType; root.paramValue.structval = def; root.name = NULL; root.parent = NULL; root.next = NULL; def->parent = &root; dumpParamDef(fh, 0, def); def->parent = NULL; } confetti-20120731/tests/0000775000000000000000000000000012005741242013425 5ustar rootrootconfetti-20120731/tests/buffer0000664000000000000000000000003112005741242014613 0ustar rootroot./example/example_buffer confetti-20120731/tests/defcfg0000664000000000000000000000005312005741242014564 0ustar rootroot./example/example ./example/my_product.cfg confetti-20120731/tests/default0000664000000000000000000000002212005741242014766 0ustar rootroot./example/example confetti-20120731/tests/custom0000664000000000000000000000005612005741242014663 0ustar rootroot./example/example ./example/my_my_product.cfg confetti-20120731/tests/dump0000664000000000000000000000005112005741242014311 0ustar rootroot./confetti -i example/example.cfgtmpl -D confetti-20120731/expected/0000775000000000000000000000000012005741242014064 5ustar rootrootconfetti-20120731/expected/buffer0000664000000000000000000000242312005741242015261 0ustar rootroot==========Accepted: 3; Skipped: 0; Optional: 1=========== foo => '1234' bar => '-54321' asdf.k1 => 'as"d' asdf.k2 => 'NEWVALUE' asdf.array[0].qwerty => '123.9' asdf.array[0].qwer1 => '123' asdf.array[0].substruct.sss => 'asdf.array.substruct.sss' asdf.array[1].qwerty => '123.9' asdf.array[1].qwer1 => '123' asdf.array[1].substruct.sss => 'asdf.array.substruct.sss' asdf.array[2].qwerty => '123.9' asdf.array[2].qwer1 => '123' asdf.array[2].substruct.sss => 'asdf.array.substruct.sss' asdf.array[2].subarray[0].subkey => '12' asdf.array[2].subarray[0].subke12 => '7654' asdf.array[2].subarray[1].subkey => '12' asdf.array[2].subarray[1].subke12 => '7654' asdf.array[2].subarray[2].subkey => '12' asdf.array[2].subarray[2].subke12 => '7654' asdf.array[2].subarray[3].subkey => '123456789' asdf.array[2].subarray[3].subke12 => '7654' asdf.k3 => (null) root_array[0].ra => '-1.344e-08' root_array[1].ra => '-1.344e-08' root_array[2].ra => '-1.344e-08' root_array[3].ra => '12' ro_struct.f1 => '1' ro_struct.f2 => '2' required_struct_with_structs.f1 => '1' required_struct_with_structs.f2 => '2' required_struct_with_structs.s1.f1 => '1' required_struct_with_structs.s1.f2 => '2' required_struct_with_structs.s1.ss1.f1 => '1' required_struct_with_structs.s1.ss1.f2 => '2' flsb => 'false' flst => 'true' confetti-20120731/expected/defcfg0000664000000000000000000000504612005741242015232 0ustar rootroot==========Accepted: 30; Skipped: 0; Optional: 0=========== foo => '1234' bar => '-54321' asdf.k1 => 'as"d' asdf.k2 => (null) asdf.array[0].qwerty => '123.9' asdf.array[0].qwer1 => '123' asdf.array[0].substruct.sss => 'asdf.array.substruct.sss' asdf.array[0].subarray[0].subkey => '12' asdf.array[0].subarray[0].subke12 => '7654' asdf.k3 => (null) root_array[0].ra => '-1.344e-08' test[0].e => '1' empty[0].wow => (null) ro_struct.f1 => '1' ro_struct.f2 => '2' array_of_ro_structs[0].f1 => '1' array_of_ro_structs[0].f2 => '2' required_struct_with_structs.f1 => '1' required_struct_with_structs.f2 => '2' required_struct_with_structs.s1.f1 => '1' required_struct_with_structs.s1.f2 => '2' required_struct_with_structs.s1.ss1.f1 => '1' required_struct_with_structs.s1.ss1.f2 => '2' array_with_required_structs_with_structs[0].f1 => '1' array_with_required_structs_with_structs[0].f2 => '2' array_with_required_structs_with_structs[0].s.f1 => '1' array_with_required_structs_with_structs[0].s.f2 => '2' array_with_required_structs_with_structs[0].s.f3 => 'false' flsb => 'false' flst => 'true' ==========Check=========== Option 'foo' is not set (or has a default value) Option 'asdf.k2' is not set (or has a default value) Option 'asdf.array[0].substruct.sss' is not set (or has a default value) Option 'asdf.array[0].subarray[0].subke12' is not set (or has a default value) Option 'root_array[0].ra' is not set (or has a default value) Missed required: 5 ==========Dup============= foo => '1234' bar => '-54321' asdf.k1 => 'as"d' asdf.k2 => (null) asdf.array[0].qwerty => '123.9' asdf.array[0].qwer1 => '123' asdf.array[0].substruct.sss => 'asdf.array.substruct.sss' asdf.array[0].subarray[0].subkey => '12' asdf.array[0].subarray[0].subke12 => '7654' asdf.k3 => (null) root_array[0].ra => '-1.344e-08' test[0].e => '1' empty[0].wow => (null) ro_struct.f1 => '1' ro_struct.f2 => '2' array_of_ro_structs[0].f1 => '1' array_of_ro_structs[0].f2 => '2' required_struct_with_structs.f1 => '1' required_struct_with_structs.f2 => '2' required_struct_with_structs.s1.f1 => '1' required_struct_with_structs.s1.f2 => '2' required_struct_with_structs.s1.ss1.f1 => '1' required_struct_with_structs.s1.ss1.f2 => '2' array_with_required_structs_with_structs[0].f1 => '1' array_with_required_structs_with_structs[0].f2 => '2' array_with_required_structs_with_structs[0].s.f1 => '1' array_with_required_structs_with_structs[0].s.f2 => '2' array_with_required_structs_with_structs[0].s.f3 => 'false' flsb => 'false' flst => 'true' ==========Compare========= total: equal only_rdonly: equal ==========Destroy========= confetti-20120731/expected/default0000664000000000000000000000223612005741242015436 0ustar rootrootfoo => '1234' bar => '-54321' asdf.k1 => 'as"d' asdf.k2 => (null) asdf.k3 => (null) ro_struct.f1 => '1' ro_struct.f2 => '2' required_struct_with_structs.f1 => '1' required_struct_with_structs.f2 => '2' required_struct_with_structs.s1.f1 => '1' required_struct_with_structs.s1.f2 => '2' required_struct_with_structs.s1.ss1.f1 => '1' required_struct_with_structs.s1.ss1.f2 => '2' flsb => 'false' flst => 'true' ==========Check=========== Option 'foo' is not set (or has a default value) Option 'root_array' is not set (or has a default value) Option 'empty' is not set (or has a default value) Option 'required_struct_with_structs' is not set Missed required: 4 ==========Dup============= foo => '1234' bar => '-54321' asdf.k1 => 'as"d' asdf.k2 => (null) asdf.k3 => (null) ro_struct.f1 => '1' ro_struct.f2 => '2' required_struct_with_structs.f1 => '1' required_struct_with_structs.f2 => '2' required_struct_with_structs.s1.f1 => '1' required_struct_with_structs.s1.f2 => '2' required_struct_with_structs.s1.ss1.f1 => '1' required_struct_with_structs.s1.ss1.f2 => '2' flsb => 'false' flst => 'true' ==========Compare========= total: equal only_rdonly: equal ==========Destroy========= confetti-20120731/expected/custom0000664000000000000000000001350012005741242015320 0ustar rootrootCould not accept read only 'ro_struct.f1' option Could not accept read only 'array_of_ro_structs[0].f1' option ==========Accepted: 37; Skipped: 2; Optional: 0=========== foo => '1234' bar => '-987654' asdf.k1 => 'as"d' asdf.k2 => 'NEWVALUE' asdf.array[0].qwerty => '121.9' asdf.array[0].qwer1 => '-123' asdf.array[0].substruct.sss => 'HEY' asdf.array[0].subarray[0].subkey => '12' asdf.array[0].subarray[0].subke12 => '7654' asdf.array[0].subarray[1].subkey => '15' asdf.array[0].subarray[1].subke12 => '111' asdf.array[1].qwerty => '1' asdf.array[1].qwer1 => '2' asdf.array[1].substruct.sss => 'FOO' asdf.array[1].subarray[0].subkey => '1123' asdf.array[1].subarray[0].subke12 => '10001' asdf.array[1].subarray[1].subkey => '12' asdf.array[1].subarray[1].subke12 => '10002' asdf.array[1].subarray[2].subkey => '12' asdf.array[1].subarray[2].subke12 => '10003' asdf.array[2].qwerty => '100001' asdf.array[2].qwer1 => '100002' asdf.array[2].substruct.sss => '/path-to/something/%d._log' asdf.array[2].subarray[0].subkey => '12' asdf.array[2].subarray[0].subke12 => '7654' asdf.array[2].subarray[1].subkey => '12' asdf.array[2].subarray[1].subke12 => '7654' asdf.array[2].subarray[2].subkey => '12' asdf.array[2].subarray[2].subke12 => '7654' asdf.array[2].subarray[3].subkey => '123456789' asdf.array[2].subarray[3].subke12 => '7654' asdf.k3 => 'NOTNULL' root_array[0].ra => '-1e-09' root_array[1].ra => '-1.344e-08' root_array[2].ra => '-1.344e-08' root_array[3].ra => '12' root_array[4].ra => '13' test[0].e => '0' test[1].e => '1' test[2].e => '2' empty[0].wow => (null) ro_struct.f1 => '1' ro_struct.f2 => '2' array_of_ro_structs[0].f1 => '1' array_of_ro_structs[0].f2 => '2' required_struct_with_structs.f1 => '1' required_struct_with_structs.f2 => '2' required_struct_with_structs.s1.f1 => '1' required_struct_with_structs.s1.f2 => '2' required_struct_with_structs.s1.ss1.f1 => '1' required_struct_with_structs.s1.ss1.f2 => '2' array_with_required_structs_with_structs[0].f1 => '1' array_with_required_structs_with_structs[0].f2 => '2' array_with_required_structs_with_structs[0].s.f1 => '1' array_with_required_structs_with_structs[0].s.f2 => '2' array_with_required_structs_with_structs[0].s.f3 => 'false' array_with_required_structs_with_structs[1].f1 => '1' array_with_required_structs_with_structs[1].f2 => '2' array_with_required_structs_with_structs[1].s.f1 => '1' array_with_required_structs_with_structs[1].s.f2 => '2' array_with_required_structs_with_structs[1].s.f3 => 'false' array_with_required_structs_with_structs[2].f1 => '1' array_with_required_structs_with_structs[2].f2 => '2' array_with_required_structs_with_structs[2].s.f1 => '1' array_with_required_structs_with_structs[2].s.f2 => '2' array_with_required_structs_with_structs[2].s.f3 => 'true' flsb => 'false' flst => 'true' ==========Check=========== Option 'foo' is not set (or has a default value) Option 'asdf.array[0].subarray[0].subke12' is not set (or has a default value) Option 'asdf.array[2].subarray[3].subke12' is not set (or has a default value) Option 'test[1]' is not set Option 'array_with_required_structs_with_structs[1]' is not set Missed required: 5 root_array[1] is not defined root_array[2] is not defined ==========Dup============= foo => '1234' bar => '-987654' asdf.k1 => 'as"d' asdf.k2 => 'NEWVALUE' asdf.array[0].qwerty => '121.9' asdf.array[0].qwer1 => '-123' asdf.array[0].substruct.sss => 'HEY' asdf.array[0].subarray[0].subkey => '12' asdf.array[0].subarray[0].subke12 => '7654' asdf.array[0].subarray[1].subkey => '15' asdf.array[0].subarray[1].subke12 => '111' asdf.array[1].qwerty => '1' asdf.array[1].qwer1 => '2' asdf.array[1].substruct.sss => 'FOO' asdf.array[1].subarray[0].subkey => '1123' asdf.array[1].subarray[0].subke12 => '10001' asdf.array[1].subarray[1].subkey => '12' asdf.array[1].subarray[1].subke12 => '10002' asdf.array[1].subarray[2].subkey => '12' asdf.array[1].subarray[2].subke12 => '10003' asdf.array[2].qwerty => '100001' asdf.array[2].qwer1 => '100002' asdf.array[2].substruct.sss => '/path-to/something/%d._log' asdf.array[2].subarray[0].subkey => '12' asdf.array[2].subarray[0].subke12 => '7654' asdf.array[2].subarray[1].subkey => '12' asdf.array[2].subarray[1].subke12 => '7654' asdf.array[2].subarray[2].subkey => '12' asdf.array[2].subarray[2].subke12 => '7654' asdf.array[2].subarray[3].subkey => '123456789' asdf.array[2].subarray[3].subke12 => '7654' asdf.k3 => 'NOTNULL' root_array[0].ra => '-1e-09' root_array[1].ra => '-1.344e-08' root_array[2].ra => '-1.344e-08' root_array[3].ra => '12' root_array[4].ra => '13' test[0].e => '0' test[1].e => '1' test[2].e => '2' empty[0].wow => (null) ro_struct.f1 => '1' ro_struct.f2 => '2' array_of_ro_structs[0].f1 => '1' array_of_ro_structs[0].f2 => '2' required_struct_with_structs.f1 => '1' required_struct_with_structs.f2 => '2' required_struct_with_structs.s1.f1 => '1' required_struct_with_structs.s1.f2 => '2' required_struct_with_structs.s1.ss1.f1 => '1' required_struct_with_structs.s1.ss1.f2 => '2' array_with_required_structs_with_structs[0].f1 => '1' array_with_required_structs_with_structs[0].f2 => '2' array_with_required_structs_with_structs[0].s.f1 => '1' array_with_required_structs_with_structs[0].s.f2 => '2' array_with_required_structs_with_structs[0].s.f3 => 'false' array_with_required_structs_with_structs[1].f1 => '1' array_with_required_structs_with_structs[1].f2 => '2' array_with_required_structs_with_structs[1].s.f1 => '1' array_with_required_structs_with_structs[1].s.f2 => '2' array_with_required_structs_with_structs[1].s.f3 => 'false' array_with_required_structs_with_structs[2].f1 => '1' array_with_required_structs_with_structs[2].f2 => '2' array_with_required_structs_with_structs[2].s.f1 => '1' array_with_required_structs_with_structs[2].s.f2 => '2' array_with_required_structs_with_structs[2].s.f3 => 'true' flsb => 'false' flst => 'true' ==========Compare========= total: equal only_rdonly: equal ==========Destroy========= confetti-20120731/expected/dump0000664000000000000000000000207212005741242014755 0ustar rootrootBUILTIN u_int32_t (RW, REQ) foo int64_t (RW) bar struct (RW) asdf char* (RW) k1 char* (RW, REQ) k2 array (RW) array struct (RW) (null) double (RO) qwerty int32_t (RW) qwer1 struct (RW) substruct char* (RW, REQ) sss array (RO) subarray struct (RW) (null) int32_t (RW) subkey u_int64_t (RW, REQ) subke12 char* (RW) k3 array (RW, REQ) root_array struct (RW) (null) double (RW, REQ) ra array (RW) test struct (RW, REQ) (null) int32_t (RW) e array (RW, REQ) empty struct (RW) (null) char* (RW) wow struct (RO) ro_struct int32_t (RO) f1 int32_t (RO) f2 array (RW) array_of_ro_structs struct (RO) (null) int32_t (RO) f1 int32_t (RO) f2 struct (RW, REQ) required_struct_with_structs int32_t (RW) f1 int32_t (RW) f2 struct (RW) s1 int32_t (RW) f1 int32_t (RW) f2 struct (RW) ss1 int32_t (RW) f1 int32_t (RW) f2 array (RW) array_with_required_structs_with_structs struct (RW, REQ) (null) int32_t (RW) f1 int32_t (RW) f2 struct (RW) s int32_t (RW) f1 int32_t (RW) f2 bool (RW) f3 bool (RW) flsb bool (RW) flst confetti-20120731/prscfl.l0000664000000000000000000001313512005741242013734 0ustar rootroot%{ #include #include #include #include #define YY_EXTRA_TYPE prscfl_yy_extra_type * static int scan_yyerror(char *s, int lineno); static void addstring(prscfl_yyscan_t yyscanner, char *s, int l); static void addchar(prscfl_yyscan_t yyscanner, char s); static char * strdupn(char *src, size_t size); static YY_BUFFER_STATE buf = NULL; %} %option 8bit %option never-interactive %option nodefault %option noyywrap %option nounput %option prefix="prscfl_yy" %option reentrant %option noinput %option bison-bridge %option warn %x xQUOTED %x COMMENT %x BUILTIN KEYCHARSTART [a-zA-Z_] KEYCHAR [a-zA-Z0-9_] DIGIT [0-9] %% [Nn][Uu][Ll][Ll] { yylval->str = strdupn(yytext, yyleng); return NULL_P; } [Tt][Rr][Uu][Ee] { yylval->str = strdupn(yytext, yyleng); return TRUE_P; } [Ff][Aa][Ll][Ss][Ee] { yylval->str = strdupn(yytext, yyleng); return FALSE_P; } [Rr][Oo] { yylval->str = strdupn(yytext, yyleng); return RDONLY_P; } [Rr][Ww] { yylval->str = strdupn(yytext, yyleng); return RDWR_P; } [Rr][Ee][Qq][Uu][Ii][Rr][Ee][Dd] { yylval->str = strdupn(yytext, yyleng); return REQUIRED_P; } {KEYCHARSTART}{KEYCHAR}* { yylval->str = strdupn(yytext, yyleng); return KEY_P; } #[ \t]* { BEGIN COMMENT; yyextra->total = 256; yyextra->strbuf = malloc(yyextra->total); yyextra->length = 0; } [\=\[\]\{\}\,] { return *yytext; } \%\{ { yyextra->total = 256; yyextra->strbuf = malloc(yyextra->total); yyextra->length = 0; BEGIN BUILTIN; } \" { yyextra->total = 256; yyextra->strbuf = malloc(yyextra->total); yyextra->length = 0; BEGIN xQUOTED; } [\-\+]?{DIGIT}+L { yylval->int64val = strtoll(yytext, NULL, 10); return INT64_P; } {DIGIT}+UL { yylval->uint64val = strtoull(yytext, NULL, 10); return UINT64_P; } {DIGIT}+U { yylval->uint32val = strtoul(yytext, NULL, 10); return UINT32_P; } [\-\+]?{DIGIT}+ { yylval->int32val = strtol(yytext, NULL, 10); return INT32_P; } [\-\+]?{DIGIT}+"."{DIGIT}+ { yylval->doubleval = strtod(yytext, NULL); return DOUBLE_P; } [\-\+]?{DIGIT}+[eE][\+\-]?{DIGIT}+ { yylval->doubleval = strtod(yytext, NULL); return DOUBLE_P; } [\-\+]?{DIGIT}+"."{DIGIT}+[eE][\+\-]?{DIGIT}+ { yylval->doubleval = strtod(yytext, NULL); return DOUBLE_P; } \\. { addchar(yyscanner, yytext[1]); } \\\n { yyextra->lineno++; } \" { yyextra->strbuf[yyextra->length] = '\0'; yylval->str = yyextra->strbuf; BEGIN INITIAL; yyextra->strbuf = NULL; return STRING_P; } \\ { /* This is only needed for \ just before EOF */ } <> { return scan_yyerror("Unexpected end of string", yyextra->lineno); } [^\\\"\n]+ { addstring(yyscanner, yytext, yyleng); } \n { addchar(yyscanner, yytext[0]); yyextra->lineno++; } \r { /* ignore */ } .+ { addstring(yyscanner, yytext, yyleng); } \n { yyextra->strbuf[yyextra->length] = '\0'; yylval->str = yyextra->strbuf; BEGIN INITIAL; yyextra->strbuf = NULL; yyextra->lineno++; return COMMENT_P; } \n { yyextra->lineno++; addchar(yyscanner, yytext[0]); } \%\} { yyextra->strbuf[yyextra->length] = '\0'; yylval->str = yyextra->strbuf; BEGIN INITIAL; yyextra->strbuf = NULL; return BUILTIN_P; } . { addchar(yyscanner, yytext[0]); } <> { return scan_yyerror("Unexpected end of file", yyextra->lineno); } <> { yyterminate(); } [ \t\r\f]+ { /* ignore */ } \n { yyextra->lineno++; } . { return scan_yyerror("syntax error: Unknown character", yyextra->lineno); } %% static int scan_yyerror(char *msg, int lineno) { fprintf(stderr, "scan_yyerror: %s at line %d\n", msg, lineno); return 0; } prscfl_yyscan_t prscflScannerInit(FILE *fh, prscfl_yy_extra_type *yyext) { yyscan_t scanner; memset(yyext, 0, sizeof(*yyext)); yyext->lineno = 1; yylex_init_extra(yyext, &scanner); buf = yy_create_buffer( fh, YY_BUF_SIZE, scanner ); yy_switch_to_buffer( buf, scanner ); return scanner; } void prscflScannerFinish(prscfl_yyscan_t scanner) { if (buf) yy_delete_buffer( buf, scanner ); buf = NULL; } /* * Arrange access to yyextra for subroutines of the main yylex() function. * We expect each subroutine to have a yyscanner parameter. Rather than * use the yyget_xxx functions, which might or might not get inlined by the * compiler, we cheat just a bit and cast yyscanner to the right type. */ #undef yyextra #define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) int prscflGetLineNo(prscfl_yyscan_t yyscanner) { return yyextra->lineno; } static void addstring(prscfl_yyscan_t yyscanner, char *s, int l) { while( yyextra->length + l + 1 >= yyextra->total ) { yyextra->total *= 2; yyextra->strbuf=realloc(yyextra->strbuf, yyextra->total); } memcpy( yyextra->strbuf+yyextra->length, s, l); yyextra->length+=l; } static void addchar(prscfl_yyscan_t yyscanner, char s) { if( yyextra->length + 2 >= yyextra->total ) { yyextra->total*=2; yyextra->strbuf=realloc(yyextra->strbuf, yyextra->total); } yyextra->strbuf[ yyextra->length++ ] = s; } static char * strdupn(char *src, size_t size) { char *dst = malloc(size + 1); if (!dst) return NULL; memcpy(dst, src, size); dst[size] = '\0'; return dst; } confetti-20120731/cfgdef.cfl0000664000000000000000000000040012005741242014161 0ustar rootroot%{ #include %} # foo value is responsible1 foo=1234U bar=54321L asdf= { # asdfffffas asdd k1 = "as\"d" # lkjhsdfiuher # =========================r k2 = NULL # substruct array = [ qwerty=123.9 qwer1=123 ] } zxcvbnm = { aaaa = NULL } confetti-20120731/makec.pl0000664000000000000000000000031012005741242013672 0ustar rootroot$len = 0; while(<>) { chomp $_; $_=~s/(["\\])/\\$1/g; $txt = "\t\"$_\\n\"\n"; print $txt; $len += length($txt); if ($len > 1000) { print "\t,\n"; $len=0; } } print "\t,\n" if $len != 0; confetti-20120731/prscfg.l0000664000000000000000000001360412005741242013730 0ustar rootroot%{ #undef yylval #undef yylloc #include #include #define YY_EXTRA_TYPE prscfg_yy_extra_type * static int scan_yyerror(char *s, int lineno); static int addstring(prscfg_yyscan_t yyscanner, char *s, int l); static int addchar(prscfg_yyscan_t yyscanner, char s); static char * strdupn(char *src, size_t size); static YY_BUFFER_STATE buf = NULL; %} %option 8bit %option never-interactive %option nodefault %option noyywrap %option nounput %option prefix="prscfg_yy" %option reentrant %option noinput %option bison-bridge %option warn %x xQUOTED %x CCOMMENT KEYCHARSTART [a-zA-Z_] KEYCHAR [a-zA-Z0-9_] DIGIT [0-9] /* Chars that may comprise a non-quoted string. */ STRINGCHAR [^ \t\f\r\n\[\]{}\"=,.#] /* Chars that may comprise a non-quoted path string. A path is identified by the presence of a slash and it allows dots in addition to regular non-quoted string chars. */ PATHCHAR [^ \t\f\r\n\[\]{}\"=,] %% [Nn][Uu][Ll][Ll] { yylval->str = strdup("NULL"); if (!yylval->str) scan_yyerror("No memory", yyextra->lineno); return NULL_P; } [Oo][Pp][Tt] { yylval->str = strdup("OPT"); if (!yylval->str) scan_yyerror("No memory", yyextra->lineno); return OPT_P; } {KEYCHARSTART}{KEYCHAR}* { yylval->str = strdupn(yytext, yyleng); if (!yylval->str) scan_yyerror("No memory", yyextra->lineno); return KEY_P; } {DIGIT}+ { yylval->str = strdupn(yytext, yyleng); if (!yylval->str) scan_yyerror("No memory", yyextra->lineno); return NATURAL_P; } \" { yyextra->total = 256; yyextra->strbuf = malloc(yyextra->total); if (!yyextra->strbuf) scan_yyerror("No memory", yyextra->lineno); yyextra->length = 0; BEGIN xQUOTED; } \/\* { yyextra->commentCounter=1; BEGIN CCOMMENT; } {PATHCHAR}*(\/{PATHCHAR}*)+ { /* Accept an unquoted path-like string. */ yylval->str = strdupn(yytext, yyleng); if (!yylval->str) scan_yyerror("No memory", yyextra->lineno); return STRING_P; } [+-]?{DIGIT}+"."{STRINGCHAR}+ { /* Accept an unquoted fpnum-like string. */ yylval->str = strdupn(yytext, yyleng); if (!yylval->str) scan_yyerror("No memory", yyextra->lineno); return STRING_P; } {STRINGCHAR}+ { /* Accept an unquoted string. */ yylval->str = strdupn(yytext, yyleng); if (!yylval->str) scan_yyerror("No memory", yyextra->lineno); return STRING_P; } [\=\[\]\{\}\.\,] { return *yytext; } #[^\n]* { /* ignore single-line comment */ } [ \t\r\f]+ { /* ignore whitespace */ } \n { yyextra->lineno++; } <> { yyterminate(); } . { return scan_yyerror("syntax error: Unknown character", yyextra->lineno); } \\. { if (addchar(yyscanner, yytext[1])) scan_yyerror("No memory", yyextra->lineno); } \\\n { yyextra->lineno++; } \" { yyextra->strbuf[yyextra->length] = '\0'; yylval->str = yyextra->strbuf; BEGIN INITIAL; yyextra->strbuf = NULL; return STRING_P; } \\ { /* This is only needed for \ just before EOF */ } [^\\\"\n]+ { if (addstring(yyscanner, yytext, yyleng)) scan_yyerror("No memory", yyextra->lineno); } \n { if (addchar(yyscanner, yytext[0])) scan_yyerror("No memory", yyextra->lineno); yyextra->lineno++; } <> { return scan_yyerror("Unexpected end of string", yyextra->lineno); } \/\* { yyextra->commentCounter++; } \*\/ { yyextra->commentCounter--; if (yyextra->commentCounter == 0) BEGIN INITIAL; } \n { yyextra->lineno++; } .+ { /* ignore */ } <> { return scan_yyerror("Unexpected end of string (inside comment)", yyextra->lineno); } %% static int scan_yyerror(char *msg, int lineno) { out_warning(CNF_SYNTAXERROR, "scan_yyerror: %s at line %d", msg, lineno); return 0; } prscfg_yyscan_t prscfgScannerInit(FILE *fh, prscfg_yy_extra_type *yyext) { yyscan_t scanner; memset(yyext, 0, sizeof(*yyext)); yyext->lineno = 1; yylex_init_extra(yyext, &scanner); buf = yy_create_buffer( fh, YY_BUF_SIZE, scanner ); yy_switch_to_buffer( buf, scanner ); return scanner; } prscfg_yyscan_t prscfgScannerInitBuffer(char *buffer, prscfg_yy_extra_type *yyext) { yyscan_t scanner; memset(yyext, 0, sizeof(*yyext)); yyext->lineno = 1; yylex_init_extra(yyext, &scanner); buf = yy_scan_string( buffer, scanner ); yy_switch_to_buffer( buf, scanner ); return scanner; } void prscfgScannerFinish(prscfg_yyscan_t scanner) { if (buf) yy_delete_buffer( buf, scanner ); yylex_destroy(scanner); buf = NULL; } /* * Arrange access to yyextra for subroutines of the main yylex() function. * We expect each subroutine to have a yyscanner parameter. Rather than * use the yyget_xxx functions, which might or might not get inlined by the * compiler, we cheat just a bit and cast yyscanner to the right type. */ #undef yyextra #define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) int prscfgGetLineNo(prscfg_yyscan_t yyscanner) { return yyextra->lineno; } static int addstring(prscfg_yyscan_t yyscanner, char *s, int l) { while( yyextra->length + l + 1 >= yyextra->total ) { yyextra->total *= 2; yyextra->strbuf=realloc(yyextra->strbuf, yyextra->total); } if (!yyextra->strbuf) return 1; memcpy( yyextra->strbuf+yyextra->length, s, l); yyextra->length+=l; return 0; } static int addchar(prscfg_yyscan_t yyscanner, char s) { if( yyextra->length + 2 >= yyextra->total ) { yyextra->total*=2; yyextra->strbuf=realloc(yyextra->strbuf, yyextra->total); } if (!yyextra->strbuf) return 1; yyextra->strbuf[ yyextra->length++ ] = s; return 0; } static char * strdupn(char *src, size_t size) { char *dst = malloc(size + 1); if (!dst) return NULL; memcpy(dst, src, size); dst[size] = '\0'; return dst; } confetti-20120731/prscfg.h0000664000000000000000000000142412005741242013721 0ustar rootroot#ifndef PRSCFG_H #define PRSCFG_H #include typedef struct NameAtom { char *name; int index; struct NameAtom *next; } NameAtom; typedef struct OptDef { enum { scalarType = 0, structType = 1, arrayType = 2 } paramType; int optional; union { char *scalarval; struct OptDef *structval; struct OptDef *arrayval; } paramValue; NameAtom *name; struct OptDef *parent; struct OptDef *next; } OptDef; OptDef* parseCfgDef(FILE *fh); OptDef* parseCfgDefBuffer(char *buffer); void freeCfgDef(OptDef *def); typedef enum ConfettyError { CNF_OK = 0, CNF_MISSED, CNF_WRONGTYPE, CNF_WRONGINDEX, CNF_RDONLY, CNF_WRONGINT, CNF_WRONGRANGE, CNF_NOMEMORY, CNF_SYNTAXERROR, CNF_NOTSET, CNF_OPTIONAL, CNF_INTERNALERROR } ConfettyError; #endif confetti-20120731/h_dump.c0000664000000000000000000001217412005741242013710 0ustar rootroot#include #include #include #include void dumpStructName(FILE *fh, ParamDef *def, char *delim) { if (def && def->parent) { ParamDef *p = def->parent; if (p->name == NULL) p = p->parent; if (p != NULL) { dumpStructName(fh, p, delim); fputs(delim, fh); fputs(p->name, fh); } } } static void dumpComment(FILE *fh, ParamDef *def, int istab) { if (def->comment) { ParamDef *i = def->comment; if (i->next) { /* multiline comment */ fprintf(fh, "\n%s/*\n", istab ? "\t" : ""); while(i) { fprintf(fh, "%s * %s\n", istab ? "\t" : "", i->paramValue.commentval); i = i->next; } fprintf(fh, "%s */\n", istab ? "\t" : ""); } else { /* single line comment */ fprintf(fh, "\n%s/* %s */\n", istab ? "\t" : "", i->paramValue.commentval); } } } static void dumpParamDef(FILE *fh, char* name, ParamDef *def) { dumpComment(fh, def, 1); switch(def->paramType) { case int32Type: fprintf(fh, "\tint32_t\t%s;\n", def->name); break; case uint32Type: fprintf(fh, "\tu_int32_t\t%s;\n", def->name); break; case int64Type: fprintf(fh, "\tint64_t\t%s;\n", def->name); break; case uint64Type: fprintf(fh, "\tu_int64_t\t%s;\n", def->name); break; case doubleType: fprintf(fh, "\tdouble\t%s;\n", def->name); break; case stringType: fprintf(fh, "\tchar*\t%s;\n", def->name); break; case boolType: fprintf(fh, "\tconfetti_bool_t\t%s;\n", def->name); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: fprintf(fh, "\t%s", name); dumpStructName(fh, def->paramValue.structval, "_"); fprintf(fh, "*\t%s;\n", def->name); break; case arrayType: fprintf(fh, "\t%s", name); dumpStructName(fh, def->paramValue.arrayval->paramValue.structval, "_"); fprintf(fh, "**\t%s;\n", def->name); break; case builtinType: break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } } static void dumpParamList(FILE *fh, char* name, ParamDef *def) { while(def) { dumpParamDef(fh, name, def); def = def->next; } } static void dumpStruct(FILE *fh, char* name, ParamDef *def) { ParamDef *list = NULL; switch(def->paramType) { case structType: list = def->paramValue.structval; break; case arrayType: list = def->paramValue.arrayval->paramValue.structval; break; default: fprintf(stderr,"Non-struct paramType (%d)\n", def->paramType); exit(1); break; } fprintf(fh, "typedef struct %s", name); dumpStructName(fh, list, "_"); fputs(" {\n", fh); fputs("\tunsigned char __confetti_flags;\n\n", fh); dumpParamList(fh, name, list); fprintf(fh, "} %s", name); dumpStructName(fh, list, "_"); fputs(";\n\n", fh); } static void dumpRecursive(FILE *fh, char* name, ParamDef *def) { while(def) { switch(def->paramType) { case structType: dumpRecursive(fh, name, def->paramValue.structval); dumpStruct(fh, name, def); break; case arrayType: dumpComment(fh, def->paramValue.arrayval, 0); dumpRecursive(fh, name, def->paramValue.arrayval->paramValue.structval); dumpStruct(fh, name, def); break; default: break; } def = def->next; } } void hDump(FILE *fh, char* name, ParamDef *def) { ParamDef root; root.paramType = structType; root.paramValue.structval = def; root.name = NULL; root.parent = NULL; root.next = NULL; def->parent = &root; fprintf(fh, "#ifndef %s_CFG_H\n", name); fprintf(fh, "#define %s_CFG_H\n\n", name); fputs( "#include \n" "#include \n" "#include \n\n" "#ifndef confetti_bool_t\n" "#define confetti_bool_t char\n" "#endif\n\n" "/*\n" " * Autogenerated file, do not edit it!\n" " */\n\n", fh ); dumpRecursive(fh, name, &root); fprintf(fh, "#ifndef CNF_FLAG_STRUCT_NEW\n" "#define CNF_FLAG_STRUCT_NEW\t0x01\n" "#endif\n" "#ifndef CNF_FLAG_STRUCT_NOTSET\n" "#define CNF_FLAG_STRUCT_NOTSET\t0x02\n" "#endif\n" "#ifndef CNF_STRUCT_DEFINED\n" "#define CNF_STRUCT_DEFINED(s) ((s) != NULL && ((s)->__confetti_flags & CNF_FLAG_STRUCT_NOTSET) == 0)\n" "#endif\n\n" ); fprintf(fh, "void init_%s(%s *c);\n\n", name, name); fprintf(fh, "int fill_default_%s(%s *c);\n\n", name, name); fprintf(fh, "void swap_%s(struct %s *c1, struct %s *c2);\n\n", name, name, name); fprintf(fh, "void parse_cfg_file_%s(%s *c, FILE *fh, int check_rdonly, int *n_accepted, int *n_skipped, int *n_optional);\n\n", name, name); fprintf(fh, "void parse_cfg_buffer_%s(%s *c, char *buffer, int check_rdonly, int *n_accepted, int *n_skipped, int *n_optional);\n\n", name, name); fprintf(fh, "int check_cfg_%s(%s *c);\n\n", name, name); fprintf(fh, "int dup_%s(%s *dst, %s *src);\n\n", name, name, name); fprintf(fh, "void destroy_%s(%s *c);\n\n", name, name); fprintf(fh, "char *cmp_%s(%s* c1, %s* c2, int only_check_rdonly);\n\n", name, name, name); fprintf(fh, "typedef struct %s_iterator_t %s_iterator_t;\n", name, name); fprintf(fh, "%s_iterator_t* %s_iterator_init();\n", name, name); fprintf(fh, "char* %s_iterator_next(%s_iterator_t* i, %s *c, char **v);\n\n", name, name, name); fputs("#endif\n", fh); def->parent = NULL; } confetti-20120731/prscfl.y0000664000000000000000000001146512005741242013755 0ustar rootroot%{ #include #include #include #include #include #include #include #include static int prscfl_yyerror(prscfl_yyscan_t yyscanner, const char *msg); extern int prscfl_yylex (YYSTYPE * yylval_param, prscfl_yyscan_t yyscanner); static ParamDef *output; #define MakeScalarParam(r, t, n, v) do { \ (r) = malloc(sizeof(ParamDef)); \ (r)->paramType = t##Type; \ (r)->paramValue.t##val = (v); \ (r)->name = (n); \ (r)->comment = NULL; \ (r)->flags = 0; \ (r)->parent = NULL; \ (r)->next = NULL; \ } while(0) #define MakeList(r, f, l) \ if (f) { \ (f)->next = (l); \ (r) = (f); \ } else { \ (r) = (l); \ } #define SetParent(p, l) do { \ ParamDef *i = (l); \ while(i) { \ i->parent = (p); \ i = i->next; \ } \ } while(0) #define PropagateStructFlags(s, f) do { \ if ((s)->paramType == structType && ((f) & PARAMDEF_RDONLY)) { \ ParamDef *child_def = (s)->paramValue.structval; \ \ while(child_def) { \ child_def->flags |= PARAMDEF_RDONLY; \ \ child_def = child_def->next; \ } \ } \ } while(0) %} %pure-parser %expect 0 %name-prefix="prscfl_yy" %error-verbose %parse-param {prscfl_yyscan_t yyscanner} %lex-param {prscfl_yyscan_t yyscanner} %union { int32_t int32val; u_int32_t uint32val; int64_t int64val; u_int64_t uint64val; double doubleval; char *str; ParamDef *node; } %type identifier %type param param_list %type commented_param %type comment comment_opt %type cfg %type flags_opt flag flag_list %token KEY_P NULL_P STRING_P COMMENT_P RDONLY_P RDWR_P BUILTIN_P REQUIRED_P FALSE_P TRUE_P %token INT32_P %token UINT32_P %token INT64_P %token UINT64_P %token DOUBLE_P %% cfg: BUILTIN_P param_list { ParamDef *b; MakeScalarParam(b, builtin, NULL, $1); MakeList($$, b, $2); output = $$; } | param_list { output = $$ = $1; } ; identifier: KEY_P { $$ = $1; } | NULL_P { $$ = $1; } | TRUE_P { $$ = $1; } | FALSE_P { $$ = $1; } | RDONLY_P { $$ = $1; } | RDWR_P { $$ = $1; } | REQUIRED_P { $$ = $1; } ; param_list: commented_param { $$ = $1; } | commented_param param_list { MakeList($$, $1, $2); } ; comment: COMMENT_P { MakeScalarParam($$, comment, NULL, $1); } | COMMENT_P comment { ParamDef *comment; MakeScalarParam(comment, comment, NULL, $1); MakeList($$, comment, $2); } ; comment_opt: comment { $$ = $1; } | /* EMPTY */ { $$ = NULL; } ; flag: RDWR_P { $$ = 0; } | RDONLY_P { $$ = PARAMDEF_RDONLY; } | REQUIRED_P { $$ = PARAMDEF_REQUIRED; } ; flag_list: flag { $$ = $1; } | flag_list ',' flag { $$ |= $3; } ; flags_opt: ',' flag_list { $$ = $2; } | /* EMPTY */ { $$ = 0; } ; commented_param: comment_opt param flags_opt { $$ = $2; $$->comment = $1; $$->flags = $3; PropagateStructFlags($2, $3); } ; param: identifier '=' INT32_P { MakeScalarParam($$, int32, $1, $3); } | identifier '=' UINT32_P { MakeScalarParam($$, uint32, $1, $3); } | identifier '=' INT64_P { MakeScalarParam($$, int64, $1, $3); } | identifier '=' UINT64_P { MakeScalarParam($$, uint64, $1, $3); } | identifier '=' DOUBLE_P { MakeScalarParam($$, double, $1, $3); } | identifier '=' STRING_P { MakeScalarParam($$, string, $1, $3); } | identifier '=' NULL_P { MakeScalarParam($$, string, $1, NULL); } | identifier '=' TRUE_P { MakeScalarParam($$, bool, $1, true); } | identifier '=' FALSE_P { MakeScalarParam($$, bool, $1, false); } | identifier '=' '{' param_list '}' { MakeScalarParam($$, struct, $1, $4); SetParent( $$, $4 ); } | identifier '=' '[' param_list ']' { ParamDef *s; MakeScalarParam(s, struct, NULL, $4); SetParent( s, $4 ); MakeScalarParam($$, array, $1, s); SetParent( $$, s ); } | identifier '=' '[' comment_opt '{' param_list '}' flags_opt ']' { ParamDef *s; MakeScalarParam(s, struct, NULL, $6); SetParent( s, $6 ); s->comment = $4; s->flags = $8; MakeScalarParam($$, array, $1, s); SetParent( $$, s ); PropagateStructFlags(s, $8); } ; %% static int prscfl_yyerror(prscfl_yyscan_t yyscanner, const char *msg) { fprintf(stderr, "gram_yyerror: %s at line %d\n", msg, prscflGetLineNo(yyscanner)); return 0; } ParamDef* parseCfgDef(FILE *fh) { prscfl_yyscan_t yyscanner; prscfl_yy_extra_type yyextra; int yyresult; yyscanner = prscflScannerInit(fh, &yyextra); output = NULL; yyresult = prscfl_yyparse(yyscanner); prscflScannerFinish(yyscanner); if (yyresult != 0) return NULL; return output; } confetti-20120731/Makefile0000664000000000000000000000332112005741242013722 0ustar rootrootCC=gcc AR=ar RANLIB=ranlib LD=ld BISON=bison -y -d FLEX=flex ARFLAGS=rcv LDFLAGS=-r CFLAGS=-Wall -g -O0 -Werror -pedantic -std=gnu99 INCLUDE=-I. LIB= OBJS=confetti.o h_dump.o f_dump.o c_dump.o p_dump.o d_dump.o PRSSRC = prscfl all: confetti ifdef PRSSRC OBJS += $(PRSSRC:%=%_scan.o) OBJS += $(PRSSRC:%=%_gram.o) $(PRSSRC:%=%_scan.o): $(PRSSRC:%=%_gram.c) $(PRSSRC:%=%_scan.c): $(PRSSRC:%=%.l) $(FLEX) -o$@ $< $(PRSSRC:%=%_gram.c): $(PRSSRC:%=%.y) $(BISON) $< mv -f y.tab.c $@ mv -f y.tab.h $(@:%.c=%.h) endif .SUFFIXES: .o.c .c.o: $(CC) $(CFLAGS) $(INCLUDE) -c $< confetti: $(OBJS) $(CC) -o $@ $(OBJS) $(LIB) example: all $(MAKE) -C example -f Makefile all p_dump.c: parse_source.c header_source.c p_dump.o: p_dump.c parse_source.c header_source.c parse_source.c: prscfg_gram.c prscfg_gram.h prscfg_scan.c cat prscfg_gram.h prscfg_gram.c prscfg_scan.c | \ perl ./makec.pl \ > $@ header_source.c: prscfg.h perl ./makec.pl < $< > $@ prscfg_scan.c: prscfg.l $(FLEX) -o$@ $< prscfg_gram.c: prscfg.y $(BISON) $< mv -f y.tab.c $@ mv -f y.tab.h $(@:%.c=%.h) test: example @[ -d results ] || mkdir results @[ -d diffs ] || mkdir diffs @for FILE in dump default defcfg custom buffer ; do \ printf "%-12s ........ " $$FILE ; \ if sh tests/$$FILE > results/$$FILE 2>results/$$FILE.errout && diff -c expected/$$FILE results/$$FILE > diffs/$$FILE ; then \ echo ok ; \ else \ echo FAILED ; \ fi ; \ done clean: rm -rf confetti $(OBJS) rm -rf *core y.tab.* rm -rf results diffs ifdef PRSSRC for prs in $(PRSSRC); do rm -rf $${prs}_gram.c $${prs}_scan.c $${prs}_gram.h ; done endif rm -f prscfg_gram.c prscfg_gram.h prscfg_scan.c parse_source.c header_source.c $(MAKE) -C example -f Makefile clean confetti-20120731/d_dump.c0000664000000000000000000000262212005741242013701 0ustar rootroot#include #include #include #include static void putt(int level) { while(level--) putchar('\t'); } static void printDef(char *type, ParamDef *def) { printf("%s (%s%s)\t%s\n", type, (def->flags & PARAMDEF_RDONLY) ? "RO" : "RW", (def->flags & PARAMDEF_REQUIRED) ? ", REQ" : "", def->name); } static void debugParamDef(ParamDef *def, int level) { while(def) { putt(level); switch(def->paramType) { case int32Type: printDef("int32_t", def); break; case uint32Type: printDef("u_int32_t", def); break; case int64Type: printDef("int64_t", def); break; case uint64Type: printDef("u_int64_t", def); break; case doubleType: printDef("double", def); break; case stringType: printDef("char*", def); break; case boolType: printDef("bool", def); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: printDef("struct", def); debugParamDef(def->paramValue.structval, level+1); break; case arrayType: printDef("array", def); debugParamDef(def->paramValue.arrayval, level+1); break; case builtinType: printf("BUILTIN\n"); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } void dDump(ParamDef *def) { debugParamDef(def, 0); } confetti-20120731/c_dump.c0000664000000000000000000014624112005741242013706 0ustar rootroot#include #include #include #include static void dumpParamDefCName(FILE *fh, ParamDef *def) { fputs("_name", fh); dumpStructName(fh, def, "__"); if (def->name) { fputc('_', fh); fputc('_', fh); fputs(def->name, fh); } } static int dumpParamDefNameList(FILE *fh, ParamDef *def, ParamDef *odef, int level) { if (def) { int maxlevel; if (def->name == NULL) def = def->parent; maxlevel = dumpParamDefNameList(fh, def->parent, odef, level + 1); fprintf(fh,"\t{ \"%s\", -1, ", def->name); if (level == 0) { fputs("NULL }\n", fh); } else { dumpParamDefCName(fh, odef); fprintf(fh, " + %d },\n", maxlevel - level); } return maxlevel; } return level; } static void dumpParamDefCNameRecursive(FILE *fh, ParamDef *def) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case stringType: case boolType: fputs("static NameAtom ", fh); dumpParamDefCName(fh, def); fputs("[] = {\n", fh); dumpParamDefNameList(fh, def, def, 0); fputs("};\n", fh); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: if (def->flags & PARAMDEF_REQUIRED) { fputs("static NameAtom ", fh); dumpParamDefCName(fh, def); fputs("[] = {\n", fh); dumpParamDefNameList(fh, def, def, 0); fputs("};\n", fh); } dumpParamDefCNameRecursive(fh, def->paramValue.structval); break; case arrayType: fputs("static NameAtom ", fh); dumpParamDefCName(fh, def); fputs("[] = {\n", fh); dumpParamDefNameList(fh, def, def, 0); fputs("};\n", fh); dumpParamDefCNameRecursive(fh, def->paramValue.arrayval->paramValue.structval); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void dumpStructPath(FILE *fh, ParamDef *def, char *name) { fprintf(fh, "%s", name); dumpStructName(fh, def, "->"); fputs("->", fh); fputs(def->name, fh); } static void dumpInit(FILE *fh, ParamDef *def) { while(def) { fputs("\t", fh); switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: dumpStructPath(fh, def, "c"); fprintf(fh, " = %"PRId32";\n", 0); break; case stringType: dumpStructPath(fh, def, "c"); fputs(" = NULL;\n", fh); break; case boolType: dumpStructPath(fh, def, "c"); fputs(" = false;\n", fh); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: dumpStructPath(fh, def, "c"); fputs(" = NULL;\n", fh); break; case arrayType: dumpStructPath(fh, def, "c"); fprintf(fh, " = NULL;\n"); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void dumpDefault(FILE *fh, ParamDef *def) { while(def) { fputs("\t", fh); switch(def->paramType) { case int32Type: dumpStructPath(fh, def, "c"); fprintf(fh, " = %"PRId32";\n", def->paramValue.int32val); break; case uint32Type: dumpStructPath(fh, def, "c"); fprintf(fh, " = %"PRIu32"U;\n", def->paramValue.uint32val); break; case int64Type: dumpStructPath(fh, def, "c"); fprintf(fh, " = %"PRId64"LL;\n", def->paramValue.int64val); break; case uint64Type: dumpStructPath(fh, def, "c"); fprintf(fh, " = %"PRIu64"ULL;\n", def->paramValue.uint64val); break; case doubleType: dumpStructPath(fh, def, "c"); fprintf(fh, " = %g;\n", def->paramValue.doubleval); break; case stringType: dumpStructPath(fh, def, "c"); if (def->paramValue.stringval == NULL) { fputs(" = NULL;\n", fh); } else { char *ptr = def->paramValue.stringval; fputs(" = strdup(\"", fh); while(*ptr) { if (*ptr == '"') fputc('\\', fh); fputc(*ptr, fh); ptr++; } fputs("\");\n", fh); fputs("\tif (", fh); dumpStructPath(fh, def, "c"); fputs(" == NULL) return CNF_NOMEMORY;\n", fh); } break; case boolType: dumpStructPath(fh, def, "c"); fprintf(fh, " = %s;\n", def->flags & PARAMDEF_REQUIRED ? "-1" : def->paramValue.boolval ? "true" : "false"); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: dumpStructPath(fh, def, "c"); fputs(" = malloc(sizeof( *(", fh); dumpStructPath(fh, def, "c"); fputs(") ));\n", fh); fputs("\tif (", fh); dumpStructPath(fh, def, "c"); fputs(" == NULL) return CNF_NOMEMORY;\n", fh); fputs("\t", fh); dumpStructPath(fh, def, "c"); fputs("->__confetti_flags = CNF_FLAG_STRUCT_NOTSET;\n", fh); dumpDefault(fh, def->paramValue.structval); break; case arrayType: dumpStructPath(fh, def, "c"); fprintf(fh, " = NULL;\n"); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void dumpDefaultArray(FILE *fh, char *name, ParamDef *def) { while(def) { if (def->paramType == arrayType) { ParamDef *ptr; fputs("static int\nacceptDefault", fh); dumpParamDefCName(fh, def); fputs("(", fh); fputs(name, fh); dumpStructName(fh, def->paramValue.arrayval->paramValue.structval, "_"); fputs(" *c) {\n",fh); /* reset parent */ ptr = def->paramValue.arrayval->paramValue.structval; while(ptr) { ptr->parent = NULL; ptr = ptr->next; } dumpDefault(fh, def->paramValue.arrayval->paramValue.structval); /* restore parent */ ptr = def->paramValue.arrayval->paramValue.structval; while(ptr) { ptr->parent = def->paramValue.arrayval; ptr = ptr->next; } fputs("\treturn 0;\n", fh); fputs("}\n\n", fh); dumpDefaultArray(fh, name, def->paramValue.arrayval->paramValue.structval); } else if (def->paramType == structType) { dumpDefaultArray(fh, name, def->paramValue.structval); } def = def->next; } } static void dumpArrayIndex(FILE *fh, int n) { fputs("opt->name", fh); while(n-- > 0) fputs("->next", fh); fputs("->index", fh); } static int dumpStructFullPath(FILE *fh, char *name, char *itername, ParamDef *def, int innerCall, int isiterator, int show_index) { if (def) { int n; if (def->name == NULL) def = def->parent; n = dumpStructFullPath(fh, name, itername, def->parent, 1, isiterator, show_index); fputs("->", fh); fputs(def->name, fh); if (def->paramType == arrayType && innerCall) { fputs("[", fh); if (show_index) { if (isiterator) { fprintf(fh, "%s->idx", itername); dumpParamDefCName(fh, def); } else dumpArrayIndex(fh, n); } fputs("]", fh); } return n + 1; } else { fputs(name, fh); return 0; } } static void arrangeArray(FILE *fh, ParamDef *def) { if (def) { arrangeArray(fh, def->parent); if (def->paramType == arrayType) { int n; fputs("\t\tARRAYALLOC(", fh); n = dumpStructFullPath(fh, "c", "i", def, 0, 0, 1); fputs(", ", fh); dumpArrayIndex(fh, n-1); fputs(" + 1, ", fh); dumpParamDefCName(fh, def); if (def->flags & PARAMDEF_RDONLY) fputs(", check_rdonly, CNF_FLAG_STRUCT_NEW | CNF_FLAG_STRUCT_NOTSET);\n", fh); else fputs(", 0, CNF_FLAG_STRUCT_NEW | CNF_FLAG_STRUCT_NOTSET);\n", fh); fputs("\t\tif (", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs("->__confetti_flags & CNF_FLAG_STRUCT_NEW)\n", fh); fputs("\t\t\tcheck_rdonly = 0;\n", fh); } else { fputs("\t\t", fh); dumpStructFullPath(fh, "c", "i", def->parent, 1, 0, 1); fputs("->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;\n", fh); } } } static void printIf(FILE *fh, ParamDef *def, int i) { if (i) fputs("\telse ", fh); else fputs("\t", fh); fputs("if ( cmpNameAtoms( opt->name, ", fh); dumpParamDefCName(fh, def); fputs(") ) {\n", fh); fputs("\t\tif (opt->paramType != ", fh); switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case stringType: case boolType: fputs("scalarType", fh); break; case arrayType: fputs("arrayType", fh); break; default: fprintf(stderr,"Unexpected def type: %d", def->paramType); break; } fputs(" )\n\t\t\treturn CNF_WRONGTYPE;\n", fh); if (def->paramType != arrayType) { arrangeArray(fh, def); } else { arrangeArray(fh, def->parent); fputs("\t\tARRAYALLOC(", fh); dumpStructFullPath(fh, "c", "i", def, 0, 0, 1); fputs(", 1, ", fh); dumpParamDefCName(fh, def); if (def->flags & PARAMDEF_RDONLY) fputs(", check_rdonly, CNF_FLAG_STRUCT_NEW | CNF_FLAG_STRUCT_NOTSET);\n", fh); else fputs(", 0, CNF_FLAG_STRUCT_NEW | CNF_FLAG_STRUCT_NOTSET);\n", fh); } } static int makeAccept(FILE *fh, ParamDef *def, int i) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case stringType: case boolType: printIf(fh, def, i); fputs("\t\terrno = 0;\n", fh); switch(def->paramType) { case int32Type: fputs("\t\tlong int i32 = strtol(opt->paramValue.scalarval, NULL, 10);\n", fh); fputs("\t\tif (i32 == 0 && errno == EINVAL)\n\t\t\treturn CNF_WRONGINT;\n", fh); fputs("\t\tif ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)\n\t\t\treturn CNF_WRONGRANGE;\n", fh); if (def->flags & PARAMDEF_RDONLY) { fputs("\t\tif (check_rdonly && ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" != i32)\n\t\t\treturn CNF_RDONLY;\n", fh); } fputs("\t\t", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" = i32;\n", fh); break; case uint32Type: fputs("\t\tunsigned long int u32 = strtoul(opt->paramValue.scalarval, NULL, 10);\n", fh); fputs("\t\tif (u32 == 0 && errno == EINVAL)\n\t\t\treturn CNF_WRONGINT;\n", fh); fputs("\t\tif ( u32 == ULONG_MAX && errno == ERANGE)\n\t\t\treturn CNF_WRONGRANGE;\n", fh); if (def->flags & PARAMDEF_RDONLY) { fputs("\t\tif (check_rdonly && ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" != u32)\n\t\t\treturn CNF_RDONLY;\n", fh); } fputs("\t\t", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" = u32;\n", fh); break; case int64Type: fputs("\t\tlong long int i64 = strtoll(opt->paramValue.scalarval, NULL, 10);\n", fh); fputs("\t\tif (i64 == 0 && errno == EINVAL)\n\t\t\treturn CNF_WRONGINT;\n", fh); fputs("\t\tif ( (i64 == LLONG_MIN || i64 == LLONG_MAX) && errno == ERANGE)\n\t\t\treturn CNF_WRONGRANGE;\n", fh); if (def->flags & PARAMDEF_RDONLY) { fputs("\t\tif (check_rdonly && ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" != i64)\n\t\t\treturn CNF_RDONLY;\n", fh); } fputs("\t\t", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" = i64;\n", fh); break; case uint64Type: fputs("\t\tunsigned long long int u64 = strtoull(opt->paramValue.scalarval, NULL, 10);\n", fh); fputs("\t\tif (u64 == 0 && errno == EINVAL)\n\t\t\treturn CNF_WRONGINT;\n", fh); fputs("\t\tif ( u64 == ULLONG_MAX && errno == ERANGE)\n\t\t\treturn CNF_WRONGRANGE;\n", fh); if (def->flags & PARAMDEF_RDONLY) { fputs("\t\tif (check_rdonly && ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" != u64)\n\t\t\treturn CNF_RDONLY;\n", fh); } fputs("\t\t", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" = u64;\n", fh); break; case doubleType: fputs("\t\tdouble dbl = strtod(opt->paramValue.scalarval, NULL);\n", fh); fputs("\t\tif ( (dbl == 0 || dbl == -HUGE_VAL || dbl == HUGE_VAL) && errno == ERANGE)\n\t\t\treturn CNF_WRONGRANGE;\n", fh); if (def->flags & PARAMDEF_RDONLY) { fputs("\t\tif (check_rdonly && ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" != dbl)\n\t\t\treturn CNF_RDONLY;\n", fh); } fputs("\t\t", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" = dbl;\n", fh); break; case stringType: if (def->flags & PARAMDEF_RDONLY) { fputs("\t\tif (check_rdonly && ( (opt->paramValue.scalarval == NULL && ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" == NULL) || strcmp(opt->paramValue.scalarval, ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(") != 0))\n\t\t\treturn CNF_RDONLY;\n", fh); } fputs("\t\t if (", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(") free(", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(");\n", fh); fputs("\t\t", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" = (opt->paramValue.scalarval) ? strdup(opt->paramValue.scalarval) : NULL;\n", fh); fputs("\t\tif (opt->paramValue.scalarval && ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" == NULL)\n\t\t\treturn CNF_NOMEMORY;\n", fh); break; case boolType: fputs("\t\tbool bln;\n\n", fh); fputs("\t\tif (strcasecmp(opt->paramValue.scalarval, \"true\") == 0 ||\n", fh); fputs("\t\t\t\tstrcasecmp(opt->paramValue.scalarval, \"yes\") == 0 ||\n", fh); fputs("\t\t\t\tstrcasecmp(opt->paramValue.scalarval, \"enable\") == 0 ||\n", fh); fputs("\t\t\t\tstrcasecmp(opt->paramValue.scalarval, \"on\") == 0 ||\n", fh); fputs("\t\t\t\tstrcasecmp(opt->paramValue.scalarval, \"1\") == 0 )\n", fh); fputs("\t\t\tbln = true;\n", fh); fputs("\t\telse if (strcasecmp(opt->paramValue.scalarval, \"false\") == 0 ||\n", fh); fputs("\t\t\t\tstrcasecmp(opt->paramValue.scalarval, \"no\") == 0 ||\n", fh); fputs("\t\t\t\tstrcasecmp(opt->paramValue.scalarval, \"disable\") == 0 ||\n", fh); fputs("\t\t\t\tstrcasecmp(opt->paramValue.scalarval, \"off\") == 0 ||\n", fh); fputs("\t\t\t\tstrcasecmp(opt->paramValue.scalarval, \"0\") == 0 )\n", fh); fputs("\t\t\tbln = false;\n", fh); fputs("\t\telse\n", fh); fputs("\t\t\treturn CNF_WRONGRANGE;\n", fh); if (def->flags & PARAMDEF_RDONLY) { fputs("\t\tif (check_rdonly && ", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" != bln)\n\t\t\treturn CNF_RDONLY;\n", fh); } fputs("\t\t", fh); dumpStructFullPath(fh, "c", "i", def, 1, 0, 1); fputs(" = bln;\n", fh); break; default: break; } fputs("\t}\n",fh); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: i = makeAccept(fh, def->paramValue.structval, i); break; case arrayType: printIf(fh, def, i); fputs("\t}\n",fh); i = makeAccept(fh, def->paramValue.arrayval, i); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } i++; def = def->next; } return i; } static void makeIteratorStates(FILE *fh, ParamDef *def) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case stringType: case boolType: fputs("\tS", fh); dumpParamDefCName(fh, def); fputs(",\n", fh); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: fputs("\tS", fh); dumpParamDefCName(fh, def); fputs(",\n", fh); makeIteratorStates(fh, def->paramValue.structval); break; case arrayType: fputs("\tS", fh); dumpParamDefCName(fh, def); fputs(",\n", fh); makeIteratorStates(fh, def->paramValue.arrayval->paramValue.structval); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void makeArrayIndexes(FILE *fh, ParamDef *def) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case stringType: case boolType: break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: makeArrayIndexes(fh, def->paramValue.structval); break; case arrayType: fputs("\tint\tidx", fh); dumpParamDefCName(fh, def); fputs(";\n", fh); makeArrayIndexes(fh, def->paramValue.arrayval->paramValue.structval); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void fputt(FILE *fh, int level) { while(level--) fputc('\t', fh); } static void fputts(FILE *fh, int level, char *str) { while(level--) fputc('\t', fh); fputs(str, fh); } static void makeSwitchArrayList(FILE *fh, ParamDef *def, int level) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case stringType: case boolType: fputt(fh, level+2); fputs( "case S", fh); dumpParamDefCName(fh, def); fputs(":\n", fh); break; case structType: fputt(fh, level+2); fputs( "case S", fh); dumpParamDefCName(fh, def); fputs(":\n", fh); makeSwitchArrayList(fh, def->paramValue.structval, level); break; case arrayType: fputt(fh, level+2); fputs( "case S", fh); dumpParamDefCName(fh, def); fputs(":\n", fh); makeSwitchArrayList(fh, def->paramValue.arrayval->paramValue.structval, level); break; default: break; } def = def->next; } } static void strdupValue(FILE *fh, ParamDef *def, int level) { switch(def->paramType) { case int32Type: fputt(fh, level); fputs("*v = malloc(32);\n", fh); fputt(fh, level); fputs("if (*v == NULL) {\n", fh); fputt(fh, level+1); fputs("free(i);\n",fh); fputt(fh, level+1); fputs("out_warning(CNF_NOMEMORY, \"No memory to output value\");\n", fh); fputt(fh, level+1); fputs("return NULL;\n",fh); fputt(fh, level); fputs("}\n",fh); fputt(fh, level); fputs("sprintf(*v, \"%\"PRId32, ", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(");\n", fh); break; case uint32Type: fputt(fh, level); fputs("*v = malloc(32);\n", fh); fputt(fh, level); fputs("if (*v == NULL) {\n", fh); fputt(fh, level+1); fputs("free(i);\n",fh); fputt(fh, level+1); fputs("out_warning(CNF_NOMEMORY, \"No memory to output value\");\n", fh); fputt(fh, level+1); fputs("return NULL;\n",fh); fputt(fh, level); fputs("}\n",fh); fputt(fh, level); fputs("sprintf(*v, \"%\"PRIu32, ", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(");\n", fh); break; case int64Type: fputt(fh, level); fputs("*v = malloc(32);\n", fh); fputt(fh, level); fputs("if (*v == NULL) {\n", fh); fputt(fh, level+1); fputs("free(i);\n",fh); fputt(fh, level+1); fputs("out_warning(CNF_NOMEMORY, \"No memory to output value\");\n", fh); fputt(fh, level+1); fputs("return NULL;\n",fh); fputt(fh, level); fputs("}\n",fh); fputt(fh, level); fputs("sprintf(*v, \"%\"PRId64, ", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(");\n", fh); break; case uint64Type: fputt(fh, level); fputs("*v = malloc(32);\n", fh); fputt(fh, level); fputs("if (*v == NULL) {\n", fh); fputt(fh, level+1); fputs("free(i);\n",fh); fputt(fh, level+1); fputs("out_warning(CNF_NOMEMORY, \"No memory to output value\");\n", fh); fputt(fh, level+1); fputs("return NULL;\n",fh); fputt(fh, level); fputs("}\n",fh); fputt(fh, level); fputs("sprintf(*v, \"%\"PRIu64, ", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(");\n", fh); break; case doubleType: fputt(fh, level); fputs("*v = malloc(32);\n", fh); fputt(fh, level); fputs("if (*v == NULL) {\n", fh); fputt(fh, level+1); fputs("free(i);\n",fh); fputt(fh, level+1); fputs("out_warning(CNF_NOMEMORY, \"No memory to output value\");\n", fh); fputt(fh, level+1); fputs("return NULL;\n",fh); fputt(fh, level); fputs("}\n",fh); fputt(fh, level); fputs("sprintf(*v, \"%g\", ", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(");\n", fh); break; case stringType: fputt(fh, level); fputs("*v = (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(") ? strdup(", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(") : NULL;\n", fh); fputt(fh, level); fputs("if (*v == NULL && ", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(") {\n", fh); fputt(fh, level+1); fputs("free(i);\n",fh); fputt(fh, level+1); fputs("out_warning(CNF_NOMEMORY, \"No memory to output value\");\n", fh); fputt(fh, level+1); fputs("return NULL;\n",fh); fputt(fh, level); fputs("}\n",fh); break; case boolType: fputt(fh, level); fputs("*v = malloc(8);\n", fh); fputt(fh, level); fputs("if (*v == NULL) {\n", fh); fputt(fh, level+1); fputs("free(i);\n",fh); fputt(fh, level+1); fputs("out_warning(CNF_NOMEMORY, \"No memory to output value\");\n", fh); fputt(fh, level+1); fputs("return NULL;\n",fh); fputt(fh, level); fputs("}\n",fh); fputt(fh, level); fputs("sprintf(*v, \"%s\", ", fh); if (def->flags & PARAMDEF_REQUIRED) { dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" == -1 ? ", fh); fputs(def->paramValue.boolval ? "\"true\"" : "\"false\"", fh); fputs(" : ", fh); } dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" ? \"true\" : \"false\");\n", fh); break; default: break; } } static void resetSubArray(FILE *fh, ParamDef *def, int level) { while(def) { switch(def->paramType) { case structType: resetSubArray(fh, def->paramValue.structval, level); break; case arrayType: fputt(fh, level + 3); fputs("i->idx", fh); dumpParamDefCName(fh, def); fputs(" = 0;\n", fh); resetSubArray(fh, def->paramValue.arrayval->paramValue.structval, level); break; default: break; } def = def->next; } } static int dumpStructNameFullPath(FILE *fh, ParamDef *def, int innerCall) { if (def) { int n; if (def->name == NULL) def = def->parent; n = dumpStructNameFullPath(fh, def->parent, 1); if (n!=0) fputs(".", fh); fputs(def->name, fh); if (def->paramType == arrayType && innerCall) { fputs("[%d]", fh); } return n + 1; } else { return 0; } } static int dumpArrayIndexes(FILE *fh, ParamDef *def, int innerCall) { if (def) { int n; if (def->name == NULL) def = def->parent; n = dumpArrayIndexes(fh, def->parent, 1); if (def->paramType == arrayType && innerCall) { fputs(", ", fh); fputs("i->idx", fh); dumpParamDefCName(fh, def); } return n + 1; } else { return 0; } } static void makeSwitch(FILE *fh, ParamDef *def, ParamDef *parent, int level, ParamDef *next) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case stringType: case boolType: /* case */ fputt(fh, level+2); fputs( "case S", fh); dumpParamDefCName(fh, def); fputs(":\n", fh); /* make val */ strdupValue(fh, def, level+3); /* make name */ fputt(fh, level + 3); fputs("snprintf(buf, PRINTBUFLEN-1, \"", fh); dumpStructNameFullPath(fh, def, 0); fputs("\"", fh); dumpArrayIndexes(fh, def, 0); fputs(");\n", fh); /* extra work to switch to the next state */ if (def->next || next) { fputt(fh, level + 3); fputs("i->state = S", fh); dumpParamDefCName(fh, def->next ? def->next : next); fputs(";\n", fh); } else { if (parent) { fputt(fh, level + 3); fputs("i->state = S", fh); dumpParamDefCName(fh, parent); fputs(";\n", fh); fputt(fh, level + 3); fputs("i->idx", fh); dumpParamDefCName(fh, parent); fputs("++;\n", fh); resetSubArray(fh, parent->paramValue.arrayval->paramValue.structval, level); } else { fputt(fh, level + 3); fputs("i->state = _S_Finished;\n", fh); } } fputt(fh, level + 3); fputs("return buf;\n", fh); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: fputt(fh, level+2); fputs( "case S", fh); dumpParamDefCName(fh, def); fputs(":\n", fh); makeSwitch(fh, def->paramValue.structval, parent, level, def->next ? def->next : next); break; case arrayType: fputt(fh, level+2); fputs( "case S", fh); dumpParamDefCName(fh, def); fputs(":\n", fh); fputt(fh, level+3); fputs( "i->state = S", fh); dumpParamDefCName(fh, def); fputs(";\n", fh); makeSwitchArrayList(fh, def->paramValue.arrayval->paramValue.structval, level); fputt(fh, level+3); fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" && ", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs("[i->idx", fh); dumpParamDefCName(fh, def); fputs("]) {\n", fh); fputt(fh, level+4); fputs("switch(i->state) {\n", fh); fputt(fh, level+5); fputs( "case S", fh); dumpParamDefCName(fh, def); fputs(":\n", fh); makeSwitch(fh, def->paramValue.arrayval->paramValue.structval, def, level+3, NULL); fputt(fh, level+5); fputs("default:\n", fh); fputt(fh, level+6); fputs("break;\n", fh); fputt(fh, level+4); fputs("}\n", fh); fputt(fh, level+3); fputs("}\n", fh); if (parent && !def->next) { fputt(fh, level+3); fputs("else {\n", fh); fputt(fh, level+4); fputs( "i->state = S", fh); dumpParamDefCName(fh, parent); fputs(";\n", fh); fputt(fh, level+4); fputs("i->idx", fh); dumpParamDefCName(fh, parent); fputs("++;\n", fh); resetSubArray(fh, parent->paramValue.arrayval->paramValue.structval, level+1); fputt(fh, level+4); fputs("goto again;\n", fh); fputt(fh, level+3); fputs("}\n", fh); } break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static int countParents(ParamDef *def) { int n = 0; while(def) { if (def->name != NULL) n++; def = def->parent; } return n; } static void dumpCheckArrayIndexes(FILE *fh, ParamDef *def, int level) { ParamDef *parent = def->parent; int i, n; while(parent) { if (parent->name == NULL) parent = parent->parent; if (parent->paramType == arrayType) { fputt(fh, level+2); dumpParamDefCName(fh, def); n = countParents(parent->parent); for(i=0; inext", fh); fputs("->index = i->idx", fh); dumpParamDefCName(fh, parent); fputs(";\n", fh); } parent = parent->parent; } } static void makeOutCheck(FILE *fh, ParamDef *def, int level) { fputt(fh, level+2); fputs("res++;\n", fh); dumpCheckArrayIndexes(fh, def, level); fputt(fh, level+2); fputs("out_warning(CNF_NOTSET, \"Option '%s' is not set (or has a default value)\", dumpOptDef(", fh); dumpParamDefCName(fh, def); fputs("));\n", fh); fputt(fh, level+1); fputs("}\n", fh); } static void makeCheck(FILE *fh, ParamDef *def, int level) { while(def) { switch(def->paramType) { case int32Type: if ((def->flags & PARAMDEF_REQUIRED) == 0) break; fputt(fh, level+1); fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fprintf(fh, " == %"PRId32") {\n", def->paramValue.int32val); makeOutCheck(fh, def, level); break; case uint32Type: if ((def->flags & PARAMDEF_REQUIRED) == 0) break; fputt(fh, level+1); fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fprintf(fh, " == %"PRIu32") {\n", def->paramValue.uint32val); makeOutCheck(fh, def, level); break; case int64Type: if ((def->flags & PARAMDEF_REQUIRED) == 0) break; fputt(fh, level+1); fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fprintf(fh, " == %"PRId64") {\n", def->paramValue.int64val); makeOutCheck(fh, def, level); break; case uint64Type: if ((def->flags & PARAMDEF_REQUIRED) == 0) break; fputt(fh, level+1); fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fprintf(fh, " == %"PRIu64") {\n", def->paramValue.uint64val); makeOutCheck(fh, def, level); break; case doubleType: if ((def->flags & PARAMDEF_REQUIRED) == 0) break; fputt(fh, level+1); fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fprintf(fh, " == %g) {\n", def->paramValue.doubleval); makeOutCheck(fh, def, level); break; case stringType: if ((def->flags & PARAMDEF_REQUIRED) == 0) break; fputt(fh, level+1); if (def->paramValue.stringval == NULL) { fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" == NULL) {\n", fh); } else { char *ptr = def->paramValue.stringval; fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" != NULL && strcmp(", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(", \"", fh); while(*ptr) { if (*ptr == '"') fputc('\\', fh); fputc(*ptr, fh); ptr++; } fputs("\") == 0) {\n", fh); } makeOutCheck(fh, def, level); break; case boolType: if ((def->flags & PARAMDEF_REQUIRED) == 0) break; fputt(fh, level+1); fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" == -1) {\n", fh); makeOutCheck(fh, def, level); break; case commentType: fprintf(stderr, "Unexpected comment"); break; case structType: fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "c", "i", def, 1, 1, 1); fputs("->__confetti_flags & CNF_FLAG_STRUCT_NOTSET) {\n", fh); if (def->flags & PARAMDEF_REQUIRED) { fputts(fh, level + 2, "res++;\n"); dumpCheckArrayIndexes(fh, def, level); fputts(fh, level + 2, "out_warning(CNF_NOTSET, \"Option '%s' is not set\", dumpOptDef("); dumpParamDefCName(fh, def); fputs("));\n", fh); } else { fputts(fh, level + 2, "(void)0;\n"); } fputts(fh, level + 1, "} else {\n"); makeCheck(fh, def->paramValue.structval, level + 1); fputts(fh, level + 1, "}\n\n"); break; case arrayType: if (def->flags & PARAMDEF_REQUIRED) { fputt(fh, level+1); fputs("if (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" == NULL) {\n", fh); makeOutCheck(fh, def, level); } fputt(fh, level+1); fputs("i->idx", fh); dumpParamDefCName(fh, def); fputs(" = 0;\n", fh); fputt(fh, level+1); fputs("while (", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" && ", fh); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs("[i->idx", fh); dumpParamDefCName(fh, def); fputs("]) {\n", fh); makeCheck(fh, def->paramValue.arrayval, level+1); fputt(fh, level+2); fputs("i->idx", fh); dumpParamDefCName(fh, def); fputs("++;\n", fh); fputt(fh, level+1); fputs("}\n\n", fh); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void makeCleanFlags(FILE *fh, ParamDef *def, int level) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case stringType: case boolType: break; case commentType: break; case structType: fputt(fh, level + 1); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs("->__confetti_flags &= ~CNF_FLAG_STRUCT_NEW;\n", fh); makeCleanFlags(fh, def->paramValue.structval, level); break; case arrayType: fputs("\n", fh); fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" != NULL) {\n", fh); fputts(fh, level + 1, "\ti->idx"); dumpParamDefCName(fh, def); fputs(" = 0;\n", fh); fputts(fh, level + 1, "\twhile ("); dumpStructFullPath(fh, "c", "i", def, 1, 1, 1); fputs(" != NULL) {\n", fh); fputt(fh, level + 1); dumpStructFullPath(fh, "\t\tc", "i", def, 1, 1, 1); fputs("->__confetti_flags &= ~CNF_FLAG_STRUCT_NEW;\n\n", fh); makeCleanFlags(fh, def->paramValue.arrayval->paramValue.structval, level + 2); fputs("\n", fh); fputts(fh, level + 1, "\t\ti->idx"); dumpParamDefCName(fh, def); fputs("++;\n", fh); fputts(fh, level + 1, "\t}\n"); fputts(fh, level + 1, "}\n"); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void makeDup(FILE *fh, ParamDef *def, int level) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case boolType: fputt(fh, level + 1); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs(" = ", fh); dumpStructFullPath(fh, "src", "i", def, 1, 1, 1); fputs(";\n", fh); break; case stringType: fputt(fh, level + 1); fputs("if (", fh); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs(") free(", fh); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs(");", fh); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs(" = ", fh); dumpStructFullPath(fh, "src", "i", def, 1, 1, 1); fputs(" == NULL ? NULL : strdup(", fh); dumpStructFullPath(fh, "src", "i", def, 1, 1, 1); fputs(");\n", fh); fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "src", "i", def, 1, 1, 1); fputs(" != NULL && ", fh); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs(" == NULL)\n", fh); fputts(fh, level + 1, "\treturn CNF_NOMEMORY;\n"); break; case commentType: break; case structType: fputs("\n", fh); fputt(fh, level + 1); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs(" = calloc(1, sizeof(*(", fh); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs(") ));\n", fh); fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs(" == NULL)\n", fh); fputts(fh, level + 1, "\treturn CNF_NOMEMORY;\n"); makeDup(fh, def->paramValue.structval, level); break; case arrayType: fputs("\n", fh); fputt(fh, level + 1); dumpStructFullPath(fh, "dst", "i", def, 0, 1, 1); fputs(" = NULL;\n", fh); fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "src", "i", def, 0, 1, 1); fputs(" != NULL) {\n", fh); fputts(fh, level + 1, "\ti->idx"); dumpParamDefCName(fh, def); fputs(" = 0;\n", fh); fputts(fh, level, "\t\tARRAYALLOC("); dumpStructFullPath(fh, "dst", "i", def, 0, 1, 1); fputs(", 1, ", fh); dumpParamDefCName(fh, def); fputs(", 0, 0);\n\n", fh); fputts(fh, level + 1, "\twhile ("); dumpStructFullPath(fh, "src", "i", def, 1, 1, 1); fputs(" != NULL) {\n", fh); fputts(fh, level + 1, "\t\tARRAYALLOC("); dumpStructFullPath(fh, "dst", "i", def, 0, 1, 1); fputs(", ", fh); fputs("i->idx", fh); dumpParamDefCName(fh, def); fputs(" + 1, ", fh); dumpParamDefCName(fh, def); fputs(", 0, 0);\n\n", fh); fputt(fh, level + 3); dumpStructFullPath(fh, "dst", "i", def, 1, 1, 1); fputs("->__confetti_flags = ", fh); dumpStructFullPath(fh, "src", "i", def, 1, 1, 1); fputs("->__confetti_flags;\n", fh); makeDup(fh, def->paramValue.arrayval->paramValue.structval, level + 2); fputs("\n", fh); fputts(fh, level + 1, "\t\ti->idx"); dumpParamDefCName(fh, def); fputs("++;\n", fh); fputts(fh, level + 1, "\t}\n"); fputts(fh, level + 1, "}\n"); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void makeDestroy(FILE *fh, ParamDef *def, int level) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case boolType: case commentType: break; case stringType: fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "c", "i", def, 1, 1, 1); fputs(" != NULL)\n", fh); fputts(fh, level + 1, "\tfree("); dumpStructFullPath(fh, "c", "i", def, 1, 1, 1); fputs(");\n", fh); break; case structType: fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "c", "i", def, 1, 1, 1); fputs(" != NULL) {\n", fh); makeDestroy(fh, def->paramValue.structval, level + 1); fputs("\n", fh); fputts(fh, level + 1, "\tfree("); dumpStructFullPath(fh, "c", "i", def, 1, 1, 1); fputs(");\n", fh); fputts(fh, level + 1, "}\n"); break; case arrayType: fputs("\n", fh); fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(" != NULL) {\n", fh); fputts(fh, level + 1, "\ti->idx"); dumpParamDefCName(fh, def); fputs(" = 0;\n", fh); fputts(fh, level + 1, "\twhile ("); dumpStructFullPath(fh, "c", "i", def, 1, 1, 1); fputs(" != NULL) {\n", fh); makeDestroy(fh, def->paramValue.arrayval->paramValue.structval, level + 2); fputs("\n", fh); fputts(fh, level + 1, "\t\tfree("); dumpStructFullPath(fh, "c", "i", def, 1, 1, 1); fputs(");\n\n", fh); fputts(fh, level + 1, "\t\ti->idx"); dumpParamDefCName(fh, def); fputs("++;\n", fh); fputts(fh, level + 1, "\t}\n\n"); fputts(fh, level + 1, "\tfree("); dumpStructFullPath(fh, "c", "i", def, 0, 1, 1); fputs(");\n", fh); fputts(fh, level + 1, "}\n"); break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } static void makeCmp(FILE *fh, ParamDef *def, int level) { while(def) { switch(def->paramType) { case int32Type: case uint32Type: case int64Type: case uint64Type: case doubleType: case boolType: if (!(def->flags & PARAMDEF_RDONLY)) { fputts(fh, level + 1, "if (!only_check_rdonly) {\n"); level++; } fputts(fh, level + 1, "if ("); dumpStructFullPath(fh, "c1", "i1", def, 1, 1, 1); fputs(" != ", fh); dumpStructFullPath(fh, "c2", "i2", def, 1, 1, 1); fputs(") {\n", fh); fputts(fh, level + 1, "\tsnprintf(diff, PRINTBUFLEN - 1, \"%s\", \""); dumpStructFullPath(fh, "c", "i", def, 1, 1, 0); fputs("\");\n\n", fh); fputts(fh, level + 1, "\treturn diff;\n"); fputts(fh, level + 1, "}\n"); if (!(def->flags & PARAMDEF_RDONLY)) { level--; fputts(fh, level + 1, "}\n"); } break; case commentType: break; case stringType: if (!(def->flags & PARAMDEF_RDONLY)) { fputts(fh, level + 1, "if (!only_check_rdonly) {\n"); level++; } fputts(fh, level + 1, "if (confetti_strcmp("); dumpStructFullPath(fh, "c1", "i1", def, 1, 1, 1); fputs(", ", fh); dumpStructFullPath(fh, "c2", "i2", def, 1, 1, 1); fputs(") != 0) {\n", fh); fputts(fh, level + 1, "\tsnprintf(diff, PRINTBUFLEN - 1, \"%s\", \""); dumpStructFullPath(fh, "c", "i", def, 1, 1, 0); fputs("\");\n\n", fh); fputts(fh, level + 1, "\treturn diff;\n"); fputs("}\n", fh); if (!(def->flags & PARAMDEF_RDONLY)) { level--; fputts(fh, level + 1, "}\n"); } break; case structType: makeCmp(fh, def->paramValue.structval, level); break; case arrayType: fputs("\n", fh); fputts(fh, level + 1, "i1->idx"); dumpParamDefCName(fh, def); fputs(" = 0;\n", fh); fputts(fh, level + 1, "i2->idx"); dumpParamDefCName(fh, def); fputs(" = 0;\n", fh); fputts(fh, level + 1, "while ("); dumpStructFullPath(fh, "c1", "i1", def, 0, 1, 1); fputs(" != NULL && ", fh); dumpStructFullPath(fh, "c1", "i1", def, 1, 1, 1); fputs(" != NULL && ", fh); dumpStructFullPath(fh, "c2", "i2", def, 0, 1, 1); fputs(" != NULL && " , fh); dumpStructFullPath(fh, "c2", "i2", def, 1, 1, 1); fputs(" != NULL) {\n", fh); makeCmp(fh, def->paramValue.arrayval->paramValue.structval, level + 1); fputs("\n", fh); fputts(fh, level + 1, "\ti1->idx"); dumpParamDefCName(fh, def); fputs("++;\n", fh); fputts(fh, level + 1, "\ti2->idx"); dumpParamDefCName(fh, def); fputs("++;\n", fh); fputts(fh, level + 1, "}\n"); if (!(def->flags & PARAMDEF_RDONLY)) { fputts(fh, level + 1, "if (!only_check_rdonly) {\n"); level++; } fputts(fh, level + 1, "if (!("); dumpStructFullPath(fh, "c1", "i1", def, 0, 1, 1); fputs(" == ", fh); dumpStructFullPath(fh, "c2", "i2", def, 0, 1, 1); fputs(" && ", fh); dumpStructFullPath(fh, "c1", "i1", def, 0, 1, 1); fputs(" == NULL) && (", fh); dumpStructFullPath(fh, "c1", "i1", def, 0, 1, 1); fputs(" == NULL || ", fh); dumpStructFullPath(fh, "c2", "i2", def, 0, 1, 1); fputs(" == NULL || ", fh); dumpStructFullPath(fh, "c1", "i1", def, 1, 1, 1); fputs(" != NULL || ", fh); dumpStructFullPath(fh, "c2", "i2", def, 1, 1, 1); fputs(" != NULL)) {\n", fh); fputts(fh, level + 1, "\tsnprintf(diff, PRINTBUFLEN - 1, \"%s\", \""); dumpStructFullPath(fh, "c", "i", def, 1, 1, 0); fputs("\");\n\n", fh); fputts(fh, level + 1, "\treturn diff;\n"); fputts(fh, level + 1, "}\n"); if (!(def->flags & PARAMDEF_RDONLY)) { level--; fputts(fh, level + 1, "}\n"); } break; default: fprintf(stderr,"Unknown paramType (%d)\n", def->paramType); exit(1); } def = def->next; } } void cDump(FILE *fh, char* name, ParamDef *def) { fputs( "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n\n" "/*\n" " * Autogenerated file, do not edit it!\n" " */\n\n", fh ); if (def->paramType == builtinType) { fputs(def->paramValue.stringval, fh); def = def->next; } fputs( "static int\n" "cmpNameAtoms(NameAtom *a, NameAtom *b) {\n" " while(a && b) {\n" " if (strcasecmp(a->name, b->name) != 0)\n" " return 0;\n" " a = a->next;\n" " b = b->next;\n" " }\n" " return (a == NULL && b == NULL) ? 1 : 0;\n" "}\n" "\n", fh ); fprintf(fh, "void\n" "init_%s(%s *c) {\n" "\tc->__confetti_flags = 0;\n\n" , name, name); dumpInit(fh, def); fputs("}\n\n", fh); fprintf(fh, "int\n" "fill_default_%s(%s *c) {\n" "\tc->__confetti_flags = 0;\n\n" , name, name ); dumpDefault(fh, def); fputs("\treturn 0;\n}\n\n", fh); fprintf(fh, "void\n" "swap_%s(struct %s *c1, struct %s *c2) {\n" , name, name, name); fprintf(fh, "\tstruct %s tmpcfg = *c1;\n" "\t*c1 = *c2;\n" "\t*c2 = tmpcfg;\n" "}\n\n", name); dumpDefaultArray(fh, name, def); dumpParamDefCNameRecursive(fh, def); fputs( "\n" "#define ARRAYALLOC(x,n,t,_chk_ro, __flags) do { \\\n" " int l = 0, ar; \\\n" " __typeof__(x) y = (x), t; \\\n" " if ( (n) <= 0 ) return CNF_WRONGINDEX; /* wrong index */ \\\n" " while(y && *y) { \\\n" " l++; y++; \\\n" " } \\\n" " if ( (n) >= (l + 1) ) { \\\n" " if (_chk_ro) return CNF_RDONLY; \\\n" " if ( (x) == NULL ) \\\n" " t = y = malloc( ((n)+1) * sizeof( __typeof__(*(x))) ); \\\n" " else { \\\n" " t = realloc((x), ((n)+1) * sizeof( __typeof__(*(x))) ); \\\n" " y = t + l; \\\n" " } \\\n" " if (t == NULL) return CNF_NOMEMORY; \\\n" " (x) = t; \\\n" " memset(y, 0, (((n)+1) - l) * sizeof( __typeof__(*(x))) ); \\\n" " while ( y - (x) < (n) ) { \\\n" " *y = malloc( sizeof( __typeof__(**(x))) ); \\\n" " if (*y == NULL) return CNF_NOMEMORY; \\\n" " if ( (ar = acceptDefault##t(*y)) != 0 ) return ar; \\\n" " (*y)->__confetti_flags = __flags; \\\n" " y++; \\\n" " } \\\n" " } \\\n" "} while(0)\n\n" , fh ); fprintf(fh, "static ConfettyError\n" "acceptValue(%s* c, OptDef* opt, int check_rdonly) {\n\n" , name); makeAccept(fh, def, 0); fputs( "\telse {\n" "\t\treturn opt->optional ? CNF_OPTIONAL : CNF_MISSED;\n" "\t}\n" "\treturn CNF_OK;\n" "}\n\n", fh ); fprintf(fh, "static void cleanFlags(%s* c, OptDef* opt);\n\n" , name); fputs( "#define PRINTBUFLEN 8192\n" "static char*\n" "dumpOptDef(NameAtom *atom) {\n" "\tstatic char buf[PRINTBUFLEN], *ptr;\n" "\tint i = 0;\n\n" "\tptr = buf;\n" "\twhile(atom) {\n" "\t\tif (i) ptr += snprintf(ptr, PRINTBUFLEN - 1 - (ptr - buf), \".\");\n" "\t\tptr += snprintf(ptr, PRINTBUFLEN - 1 - (ptr - buf), \"%s\", atom->name);\n" "\t\tif (atom->index >= 0)\n" "\t\t\tptr += snprintf(ptr, PRINTBUFLEN - 1 - (ptr - buf), \"[%d]\", atom->index);\n" "\t\ti = 1;\n" "\t\tatom = atom->next;\n" "\t}\n" "\treturn buf;\n" "}\n\n" , fh ); fprintf(fh, "static void\n" "acceptCfgDef(%s *c, OptDef *opt, int check_rdonly, int *n_accepted, int *n_skipped, int *n_optional) {\n" "\tConfettyError r;\n" "\tOptDef *orig_opt = opt;\n\n" "\tif (n_accepted) *n_accepted=0;\n" "\tif (n_skipped) *n_skipped=0;\n" "\tif (n_optional) *n_optional=0;\n" "\n" "\twhile(opt) {\n" "\t\tr = acceptValue(c, opt, check_rdonly);\n" "\t\tswitch(r) {\n" "\t\t\tcase CNF_OK:\n" "\t\t\t\tif (n_accepted) (*n_accepted)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_OPTIONAL:\n" "\t\t\t\tout_warning(r, \"Option '%cs' is not supported\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_optional) (*n_optional)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_MISSED:\n" "\t\t\t\tout_warning(r, \"Could not find '%cs' option\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_WRONGTYPE:\n" "\t\t\t\tout_warning(r, \"Wrong value type for '%cs' option\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_WRONGINDEX:\n" "\t\t\t\tout_warning(r, \"Wrong array index in '%cs' option\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_RDONLY:\n" "\t\t\t\tout_warning(r, \"Could not accept read only '%cs' option\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_WRONGINT:\n" "\t\t\t\tout_warning(r, \"Could not parse integer value for '%cs' option\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_WRONGRANGE:\n" "\t\t\t\tout_warning(r, \"Wrong range for '%cs' option\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_NOMEMORY:\n" "\t\t\t\tout_warning(r, \"Not enough memory to accept '%cs' option\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t\tcase CNF_NOTSET:\n" "\t\t\t\tout_warning(r, \"Option '%cs' is not set (or has a default value)\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t\tdefault:\n" "\t\t\t\tout_warning(r, \"Unknown error for '%cs' option\", dumpOptDef(opt->name));\n" "\t\t\t\tif (n_skipped) (*n_skipped)++;\n" "\t\t\t\tbreak;\n" "\t\t}\n\n" "\t\topt = opt->next;\n" "\t}\n" "\n" "\tcleanFlags(c, orig_opt);\n" "}\n\n" , name, '%', '%', '%', '%', '%', '%', '%', '%', '%', '%' ); fprintf(fh, "void\n" "parse_cfg_file_%s(%s *c, FILE *fh, int check_rdonly, int *n_accepted, int *n_skipped, int *n_optional) {\n" "\tOptDef *option;\n\n" "\toption = parseCfgDef(fh);\n" "\tacceptCfgDef(c, option, check_rdonly, n_accepted, n_skipped, n_optional);\n" "\tfreeCfgDef(option);\n" "}\n\n" , name, name ); fprintf(fh, "void\n" "parse_cfg_buffer_%s(%s *c, char *buffer, int check_rdonly, int *n_accepted, int *n_skipped, int *n_optional) {\n" "\tOptDef *option;\n\n" "\toption = parseCfgDefBuffer(buffer);\n" "\tacceptCfgDef(c, option, check_rdonly, n_accepted, n_skipped, n_optional);\n" "\tfreeCfgDef(option);\n" "}\n\n" , name, name ); fputs( "/************** Iterator **************/\n" "typedef enum IteratorState {\n" "\t_S_Initial = 0,\n" , fh ); makeIteratorStates(fh, def); fputs( "\t_S_Finished\n" "} IteratorState;\n\n" , fh); fprintf( fh, "struct %s_iterator_t {\n\tIteratorState\tstate;\n" , name); makeArrayIndexes(fh, def); fprintf( fh, "};\n\n"); fprintf(fh, "%s_iterator_t*\n" "%s_iterator_init() {\n" "\t%s_iterator_t *i = malloc(sizeof(*i));\n" "\tif (i == NULL) return NULL;\n" "\tmemset(i, 0, sizeof(*i));\n" "\treturn i;\n" "}\n\n" "char*\n" "%s_iterator_next(%s_iterator_t* i, %s *c, char **v) {\n" "\tstatic char\tbuf[PRINTBUFLEN];\n\n" "\t*v = NULL;\n" "\tgoto again; /* keep compiler quiet */\n" "again:\n" "\tswitch(i->state) {\n" "\t\tcase _S_Initial:\n" , name, name, name, name, name, name); makeSwitch(fh, def, NULL, 0, NULL); fprintf(fh, "\t\tcase _S_Finished:\n" "\t\t\tfree(i);\n" "\t\t\tbreak;\n" "\t\tdefault:\n" "\t\t\tout_warning(CNF_INTERNALERROR, \"Unknown state for %s_iterator_t: %cd\", i->state);\n" "\t\t\tfree(i);\n" "\t}\n" "\treturn NULL;\n" "}\n\n" , name, '%' ); fprintf(fh, "/************** Checking of required fields **************/\nint\ncheck_cfg_%s(%s *c) {\n", name, name); fprintf( fh, "\t%s_iterator_t iterator, *i = &iterator;\n" , name); fputs("\tint\tres = 0;\n\n", fh); makeCheck(fh, def, 0); fputs("\treturn res;\n}\n\n", fh); fprintf(fh, "static void\n" "cleanFlags(%s* c, OptDef* opt) {\n" , name); fprintf(fh, "\t%s_iterator_t iterator, *i = &iterator;\n\n", name); makeCleanFlags(fh, def, 0); fputs( "}\n\n", fh ); fputs("/************** Duplicate config **************/\n\n", fh); fprintf(fh, "int\n" "dup_%s(%s* dst, %s* src) {\n" , name, name, name); fprintf(fh, "\t%s_iterator_t iterator, *i = &iterator;\n\n", name); makeDup(fh, def, 0); fputs("\n\treturn CNF_OK;\n", fh); fputs("}\n\n", fh); fputs("/************** Destroy config **************/\n\n", fh); fprintf(fh, "void\n" "destroy_%s(%s* c) {\n" , name, name); fprintf(fh, "\t%s_iterator_t iterator, *i = &iterator;\n\n", name); makeDestroy(fh, def, 0); fputs("}\n\n", fh); fputs("/************** Compare config **************/\n\n", fh); fprintf(fh, "int\n" "confetti_strcmp(char *s1, char *s2) {\n" "\tif (s1 == NULL || s2 == NULL) {\n" "\t\tif (s1 != s2)\n" "\t\t\treturn s1 == NULL ? -1 : 1;\n" "\t\telse\n" "\t\t\treturn 0;\n" "\t}\n\n" "\treturn strcmp(s1, s2);\n" "}\n\n"); fprintf(fh, "char *\n" "cmp_%s(%s* c1, %s* c2, int only_check_rdonly) {\n" , name, name, name); fprintf(fh, "\t%s_iterator_t iterator1, iterator2, *i1 = &iterator1, *i2 = &iterator2;\n" "\tstatic char diff[PRINTBUFLEN];\n\n", name); makeCmp(fh, def, 0); fputs("\n\treturn 0;\n", fh); fputs("}\n\n", fh); } confetti-20120731/README0000664000000000000000000000010712005741242013141 0ustar rootrootconfetti -- configuration file parser generator Author: Teodor Sigaev confetti-20120731/prscfl.h0000664000000000000000000000276112005741242013733 0ustar rootroot#ifndef PRSCFL_H #define PRSCFL_H #include #include typedef struct prscfl_yy_extra_type { /* * string */ char *strbuf; int length; int total; int lineno; } prscfl_yy_extra_type; /* * The type of yyscanner is opaque outside scan.l. */ typedef void *prscfl_yyscan_t; int prscflGetLineNo(prscfl_yyscan_t scanner); prscfl_yyscan_t prscflScannerInit(FILE *fh, prscfl_yy_extra_type *yyext); void prscflScannerFinish(prscfl_yyscan_t scanner); typedef struct ParamDef { enum { int32Type = 0, int64Type = 1, uint32Type = 2, uint64Type = 3, doubleType = 4, stringType = 5, boolType = 6, commentType = 7, structType = 8, arrayType = 9, builtinType = 10 } paramType; union { int32_t int32val; int64_t int64val; u_int32_t uint32val; u_int64_t uint64val; double doubleval; bool boolval; char *stringval; char *commentval; struct ParamDef *structval; struct ParamDef *arrayval; char *builtinval; } paramValue; char *name; int flags; struct ParamDef *comment; struct ParamDef *parent; struct ParamDef *next; } ParamDef; #define PARAMDEF_RDONLY (0x01) #define PARAMDEF_REQUIRED (0x02) ParamDef* parseCfgDef(FILE *fh); void hDump(FILE *fh, char *name, ParamDef *def); void dumpStructName(FILE *fh, ParamDef *def, char *delim); void cDump(FILE *fh, char *name, ParamDef *def); void fDump(FILE *fh, ParamDef *def); void pDump(FILE *fh, ParamDef *def); void HDump(FILE *fh); void dDump(ParamDef *def); #endif confetti-20120731/LICENSE0000664000000000000000000000240512005741242013271 0ustar rootrootCopyright (c) 2011, Teodor Sigaev All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.