add the keyboard plugin into the build systems
[dana/openbox.git] / openbox / parse.c
1 #include "parse.h"
2 #include "config.h"
3
4 static GHashTable *reg = NULL;
5 static ParseFunc func = NULL;
6
7 /* parse tokens from the [openbox] section of the rc file */
8 static void parse_rc_token(ParseToken *token);
9
10 void destkey(gpointer key) { g_free(key); }
11
12 void parse_startup()
13 {
14     reg = g_hash_table_new_full(g_str_hash, g_str_equal, destkey, NULL);
15     func = NULL;
16
17     parse_reg_section("openbox", parse_rc_token);
18 }
19
20 void parse_shutdown()
21 {
22     g_hash_table_destroy(reg);
23 }
24
25 void parse_reg_section(char *section, ParseFunc func)
26 {
27     if (g_hash_table_lookup(reg, section) != NULL)
28         g_warning("duplicate request for section '%s' in the rc file",
29                   section);
30     else
31         g_hash_table_insert(reg, g_ascii_strdown(section, -1), (void*)func);
32 }
33
34 void parse_free_token(ParseToken *token)
35 {
36     GList *it;
37
38     switch (token->type) {
39     case TOKEN_STRING:
40         g_free(token->data.string);
41         break;
42     case TOKEN_IDENTIFIER:
43         g_free(token->data.identifier);
44         break;
45     case TOKEN_LIST:
46         for (it = token->data.list; it; it = it->next) {
47             parse_free_token(it->data);
48             g_free(it->data);
49         }
50         g_list_free(token->data.list);
51         break;
52     case TOKEN_REAL:
53     case TOKEN_INTEGER:
54     case TOKEN_BOOL:
55     case TOKEN_LBRACE:
56     case TOKEN_RBRACE:
57     case TOKEN_EQUALS:
58     case TOKEN_COMMA:
59     case TOKEN_NEWLINE:
60         break;
61     }
62 }
63
64 void parse_set_section(char *section)
65 {
66     func = (ParseFunc)g_hash_table_lookup(reg, section);
67 }
68
69 void parse_token(ParseToken *token)
70 {
71     if (func != NULL)
72         func(token);
73 }
74
75 static void parse_rc_token(ParseToken *token)
76 {
77     static int got_eq = FALSE;
78     static ParseTokenType got_val = 0;
79     static char *id = NULL, *s = NULL;
80     static int i;
81     static gboolean b;
82
83     if (id == NULL) {
84         if (token->type == TOKEN_IDENTIFIER) {
85             id = token->data.identifier;
86             return;
87         } else {
88             yyerror("syntax error");
89         }
90     } else if (!got_eq) {
91         if (token->type == TOKEN_EQUALS) {
92             got_eq = TRUE;
93             return;
94         } else {
95             yyerror("syntax error");
96         }
97     } else if (!got_val) {
98         if (token->type == TOKEN_STRING) {
99             s = token->data.string;
100             got_val = token->type;
101             return;
102         } else if (token->type == TOKEN_BOOL) {
103             b = token->data.bool;
104             got_val = token->type;
105             return;
106         } else if (token->type == TOKEN_INTEGER) {
107             i = token->data.integer;
108             got_val = token->type;
109             return;
110         } else
111             yyerror("syntax error");
112     } else if (token->type != TOKEN_NEWLINE) {
113         yyerror("syntax error");
114     } else {
115         ConfigValue v;
116
117         switch (got_val) {
118         case TOKEN_STRING:
119             v.string = s;
120             if (!config_set(id, Config_String, v))
121                 yyerror("invalid value type");
122             break;
123         case TOKEN_BOOL:
124             v.bool = b;
125             if (!config_set(id, Config_Bool, v))
126                 yyerror("invalid value type");
127             break;
128         case TOKEN_INTEGER:
129             v.integer = i;
130             if (!config_set(id, Config_Integer, v))
131                 yyerror("invalid value type");
132             break;
133         default:
134             g_assert_not_reached(); /* unhandled type got parsed */
135         }
136     }
137
138     g_free(id);
139     g_free(s);
140     id = s = NULL;
141     got_eq = FALSE;
142     got_val = 0;
143     parse_free_token(token);
144 }