thoughts and shit
This commit is contained in:
parent
1594828ec5
commit
60065663ba
1 changed files with 130 additions and 0 deletions
130
obcl/README
Normal file
130
obcl/README
Normal file
|
@ -0,0 +1,130 @@
|
|||
Note: this is not really a README but more of a thought dump, for now.
|
||||
|
||||
overall
|
||||
-------
|
||||
|
||||
obcl wants to be a generic configuration file loader. generic not in
|
||||
the sense that it will parse every single configuration format on the
|
||||
planet, but in the sense that it will parse a versatile, multi purpose
|
||||
format.
|
||||
|
||||
parser
|
||||
------
|
||||
|
||||
this is the part of obcl that when given a configuration file, it will
|
||||
return a parse tree. the parse tree can be mucked with by the
|
||||
programmer, or it can be checked and processed using the handy checker
|
||||
and processor. (for the most part; the programmer will do some
|
||||
processing work.)
|
||||
|
||||
GList *config = cl_parse_file("foo.conf");
|
||||
|
||||
checker
|
||||
-------
|
||||
|
||||
the checker is supposed to help the programmer/application ensure that
|
||||
the configuration file is in the correct format. since obcl has a very
|
||||
general, the parser itself cannot guarantee that the user will enter a
|
||||
correct config file:
|
||||
|
||||
foo { }
|
||||
fpp { }
|
||||
|
||||
will both be parsed, but 'fpp' might be a mistake. the checker is
|
||||
intended to fix this.
|
||||
|
||||
foo 5;
|
||||
blef "foo";
|
||||
bar 5, "foo", "hi", 43.4;
|
||||
|
||||
woop "hello" {
|
||||
foo 5;
|
||||
}
|
||||
|
||||
CLChecker *check = cl_checker_new();
|
||||
cl_checker_add(check, "foo", CL_NUM, 0);
|
||||
cl_checker_add(check, "blef", CL_STRING, 0);
|
||||
cl_checker_add(check, "bar", CL_NUM, CL_STRING, CL_STRING, CL_NUM, 0);
|
||||
cl_checker_add(check, "woop", CL_STRING, CL_BLOCK, 0);
|
||||
cl_checker_add_checker(check, "woop", check); /* add checker for block */
|
||||
|
||||
int val = cl_check(checker, config, stderr); /* write errors to stderr */
|
||||
if (!val) {
|
||||
fprintf(stderr, "Parse errors found. Loading default settings\n");
|
||||
...
|
||||
}
|
||||
|
||||
cl_checker_free(check);
|
||||
|
||||
processor
|
||||
---------
|
||||
|
||||
the processor is intended to be run after the checker, to do actual
|
||||
'stuff' with the parse tree. once the parse tree has been checked, we
|
||||
know that we can just access stuff in the parse tree willy nilly
|
||||
without sprinkling asserts all over the code. the processing is done
|
||||
via callbacks.
|
||||
|
||||
typedef gpointer (*CLCallback)(CLNode *node, gpointer val);
|
||||
|
||||
gpointer handle_foo(CLNode *node, gpointer conf)
|
||||
{
|
||||
/* here numval is a macro that expands to something like
|
||||
node->u.num. we know we can access this safely since the checker
|
||||
has verified that 'foo' nodes indeed contain numbers.
|
||||
same with NTH. it expands to somethign that we don't have to
|
||||
worry about. */
|
||||
((Config*)conf)->foo = NUMVAL(NTH(node, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
gpointer handle_woop(CLNode *node, gpointer conf, CLProc *proc)
|
||||
{
|
||||
Config *conf1 = new_conf();
|
||||
conf1->name = STRVAL(NTH(node,1));
|
||||
cl_process(proc, BLOCK(node), conf1);
|
||||
conf_add_child((Config*)conf, conf1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
Config *process_config_file(char *file)
|
||||
{
|
||||
Config *conf;
|
||||
GList *parse_tree;
|
||||
CLProc *proc;
|
||||
CLChecker *check;
|
||||
int err;
|
||||
|
||||
config = new_conf();
|
||||
parse_tree = cl_parse_file(file);
|
||||
|
||||
if (!parse_tree) {
|
||||
fprintf(stderr, "your config file is completely borked. loading defaults\n");
|
||||
conf_load_defaults(conf);
|
||||
return conf;
|
||||
}
|
||||
|
||||
checker = checker_new();
|
||||
...
|
||||
/* add checker stuff to checker, as per above */
|
||||
|
||||
err = cl_check(checker, parse_tree);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "you fucked up. loading defaults\n");
|
||||
config_load_defaults(conf);
|
||||
return conf;
|
||||
}
|
||||
|
||||
CLProc *proc = cl_proc_new();
|
||||
cl_proc_add(proc, "foo", handle_foo, conf); /* conf will be passed to callback */
|
||||
...
|
||||
cl_proc_add_block(proc, "woop", handle_woop, conf, proc);
|
||||
cl_process(proc, parse_tree);
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
something like that. lalala.
|
Loading…
Reference in a new issue