]> Dogcows Code - chaz/openbox/blob - obcl/README
thoughts and shit
[chaz/openbox] / obcl / README
1 Note: this is not really a README but more of a thought dump, for now.
2
3 overall
4 -------
5
6 obcl wants to be a generic configuration file loader. generic not in
7 the sense that it will parse every single configuration format on the
8 planet, but in the sense that it will parse a versatile, multi purpose
9 format.
10
11 parser
12 ------
13
14 this is the part of obcl that when given a configuration file, it will
15 return a parse tree. the parse tree can be mucked with by the
16 programmer, or it can be checked and processed using the handy checker
17 and processor. (for the most part; the programmer will do some
18 processing work.)
19
20 GList *config = cl_parse_file("foo.conf");
21
22 checker
23 -------
24
25 the checker is supposed to help the programmer/application ensure that
26 the configuration file is in the correct format. since obcl has a very
27 general, the parser itself cannot guarantee that the user will enter a
28 correct config file:
29
30 foo { }
31 fpp { }
32
33 will both be parsed, but 'fpp' might be a mistake. the checker is
34 intended to fix this.
35
36 foo 5;
37 blef "foo";
38 bar 5, "foo", "hi", 43.4;
39
40 woop "hello" {
41 foo 5;
42 }
43
44 CLChecker *check = cl_checker_new();
45 cl_checker_add(check, "foo", CL_NUM, 0);
46 cl_checker_add(check, "blef", CL_STRING, 0);
47 cl_checker_add(check, "bar", CL_NUM, CL_STRING, CL_STRING, CL_NUM, 0);
48 cl_checker_add(check, "woop", CL_STRING, CL_BLOCK, 0);
49 cl_checker_add_checker(check, "woop", check); /* add checker for block */
50
51 int val = cl_check(checker, config, stderr); /* write errors to stderr */
52 if (!val) {
53 fprintf(stderr, "Parse errors found. Loading default settings\n");
54 ...
55 }
56
57 cl_checker_free(check);
58
59 processor
60 ---------
61
62 the processor is intended to be run after the checker, to do actual
63 'stuff' with the parse tree. once the parse tree has been checked, we
64 know that we can just access stuff in the parse tree willy nilly
65 without sprinkling asserts all over the code. the processing is done
66 via callbacks.
67
68 typedef gpointer (*CLCallback)(CLNode *node, gpointer val);
69
70 gpointer handle_foo(CLNode *node, gpointer conf)
71 {
72 /* here numval is a macro that expands to something like
73 node->u.num. we know we can access this safely since the checker
74 has verified that 'foo' nodes indeed contain numbers.
75 same with NTH. it expands to somethign that we don't have to
76 worry about. */
77 ((Config*)conf)->foo = NUMVAL(NTH(node, 1));
78 return 0;
79 }
80
81 gpointer handle_woop(CLNode *node, gpointer conf, CLProc *proc)
82 {
83 Config *conf1 = new_conf();
84 conf1->name = STRVAL(NTH(node,1));
85 cl_process(proc, BLOCK(node), conf1);
86 conf_add_child((Config*)conf, conf1);
87 return 0;
88 }
89
90 ...
91
92 Config *process_config_file(char *file)
93 {
94 Config *conf;
95 GList *parse_tree;
96 CLProc *proc;
97 CLChecker *check;
98 int err;
99
100 config = new_conf();
101 parse_tree = cl_parse_file(file);
102
103 if (!parse_tree) {
104 fprintf(stderr, "your config file is completely borked. loading defaults\n");
105 conf_load_defaults(conf);
106 return conf;
107 }
108
109 checker = checker_new();
110 ...
111 /* add checker stuff to checker, as per above */
112
113 err = cl_check(checker, parse_tree);
114
115 if (err) {
116 fprintf(stderr, "you fucked up. loading defaults\n");
117 config_load_defaults(conf);
118 return conf;
119 }
120
121 CLProc *proc = cl_proc_new();
122 cl_proc_add(proc, "foo", handle_foo, conf); /* conf will be passed to callback */
123 ...
124 cl_proc_add_block(proc, "woop", handle_woop, conf, proc);
125 cl_process(proc, parse_tree);
126
127 return conf;
128 }
129
130 something like that. lalala.
This page took 0.041369 seconds and 4 git commands to generate.