From 60065663ba9dc448dcf90fd200cd459bcdb9ef9c Mon Sep 17 00:00:00 2001 From: Marius Nita Date: Wed, 30 Apr 2003 18:42:32 +0000 Subject: [PATCH] thoughts and shit --- obcl/README | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 obcl/README diff --git a/obcl/README b/obcl/README new file mode 100644 index 00000000..b291b7b8 --- /dev/null +++ b/obcl/README @@ -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. -- 2.39.2