thoughts and shit
authorMarius Nita <marius@cs.pdx.edu>
Wed, 30 Apr 2003 18:42:32 +0000 (18:42 +0000)
committerMarius Nita <marius@cs.pdx.edu>
Wed, 30 Apr 2003 18:42:32 +0000 (18:42 +0000)
obcl/README [new file with mode: 0644]

diff --git a/obcl/README b/obcl/README
new file mode 100644 (file)
index 0000000..b291b7b
--- /dev/null
@@ -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.