-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.