--- /dev/null
+#include "parse.h"
+#include "config.h"
+
+static GHashTable *reg = NULL;
+static ParseFunc func = NULL;
+
+/* parse tokens from the [openbox] section of the rc file */
+static void parse_rc_token(ParseTokenType type, union ParseToken token);
+
+void destkey(gpointer key) { g_free(key); }
+
+void parse_startup()
+{
+ reg = g_hash_table_new_full(g_str_hash, g_str_equal, destkey, NULL);
+ func = NULL;
+
+ parse_reg_section("openbox", parse_rc_token);
+}
+
+void parse_shutdown()
+{
+ g_hash_table_destroy(reg);
+}
+
+void parse_reg_section(char *section, ParseFunc func)
+{
+ if (g_hash_table_lookup(reg, section) != NULL)
+ g_warning("duplicate request for section '%s' in the rc file",
+ section);
+ else
+ g_hash_table_insert(reg, g_ascii_strdown(section, -1), (void*)func);
+}
+
+void parse_free_token(ParseTokenType type, union ParseToken token)
+{
+ switch (type) {
+ case TOKEN_STRING:
+ g_free(token.string);
+ break;
+ case TOKEN_IDENTIFIER:
+ g_free(token.identifier);
+ break;
+ case TOKEN_REAL:
+ case TOKEN_INTEGER:
+ case TOKEN_BOOL:
+ case TOKEN_LBRACKET:
+ case TOKEN_RBRACKET:
+ case TOKEN_LBRACE:
+ case TOKEN_RBRACE:
+ case TOKEN_EQUALS:
+ case TOKEN_COMMA:
+ case TOKEN_NEWLINE:
+ break;
+ }
+}
+
+void parse_set_section(char *section)
+{
+ func = (ParseFunc)g_hash_table_lookup(reg, section);
+}
+
+void parse_token(ParseTokenType type, union ParseToken token)
+{
+ if (func != NULL)
+ func(type, token);
+}
+
+static void parse_rc_token(ParseTokenType type, union ParseToken token)
+{
+ static int got_eq = FALSE;
+ static ParseTokenType got_val = 0;
+ static char *id = NULL, *s = NULL;
+ static int i;
+ static gboolean b;
+
+ if (id == NULL) {
+ if (type == TOKEN_IDENTIFIER) {
+ id = token.identifier;
+ return;
+ } else {
+ yyerror("syntax error");
+ }
+ } else if (!got_eq) {
+ if (type == TOKEN_EQUALS) {
+ got_eq = TRUE;
+ return;
+ } else {
+ yyerror("syntax error");
+ }
+ } else if (!got_val) {
+ if (type == TOKEN_STRING) {
+ s = token.string;
+ got_val = type;
+ return;
+ } else if (type == TOKEN_BOOL) {
+ b = token.bool;
+ got_val = type;
+ return;
+ } else if (type == TOKEN_INTEGER) {
+ i = token.integer;
+ got_val = type;
+ return;
+ } else
+ yyerror("syntax error");
+ } else if (type != TOKEN_NEWLINE) {
+ yyerror("syntax error");
+ } else {
+ ConfigValue v;
+
+ switch (got_val) {
+ case TOKEN_STRING:
+ v.string = s;
+ if (!config_set(id, Config_String, v))
+ yyerror("invalid value type");
+ break;
+ case TOKEN_BOOL:
+ v.bool = b;
+ if (!config_set(id, Config_Bool, v))
+ yyerror("invalid value type");
+ break;
+ case TOKEN_INTEGER:
+ v.integer = i;
+ if (!config_set(id, Config_Integer, v))
+ yyerror("invalid value type");
+ break;
+ default:
+ g_assert_not_reached(); /* unhandled type got parsed */
+ }
+ }
+
+ g_free(id);
+ g_free(s);
+ id = s = NULL;
+ got_eq = FALSE;
+ got_val = 0;
+ parse_free_token(type, token);
+}