all repos — openbox @ d1ceea89bd811d776050d2f6a04370d30a0932b3

openbox fork - make it a bit more like ryudo

obcl/README (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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.