summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
Diffstat (limited to 'parser')
-rw-r--r--parser/.cvsignore6
-rw-r--r--parser/Makefile.am20
-rw-r--r--parser/parse.c190
-rw-r--r--parser/parse.h43
4 files changed, 259 insertions, 0 deletions
diff --git a/parser/.cvsignore b/parser/.cvsignore
new file mode 100644
index 00000000..cb737897
--- /dev/null
+++ b/parser/.cvsignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+libobparser.la
+parse.lo
diff --git a/parser/Makefile.am b/parser/Makefile.am
new file mode 100644
index 00000000..fe80db16
--- /dev/null
+++ b/parser/Makefile.am
@@ -0,0 +1,20 @@
+localedir=$(datadir)/locale
+rcdir=$(datadir)/openbox
+
+CPPFLAGS=$(GLIB_CFLAGS) $(XML_CFLAGS) @CPPFLAGS@ \
+ -DG_LOG_DOMAIN=\"Parser\" \
+ -DLOCALEDIR=\"$(localedir)\" \
+ -DRCDIR=\"$(rcdir)\"
+
+INCLUDES=-I..
+LIBS=$(GLIB_LIBS) $(XML_LIBS) @LIBS@
+
+lib_LTLIBRARIES=libobparser.la
+libobparser_la_SOURCES=parse.c
+
+noinst_HEADERS=parse.h
+
+MAINTAINERCLEANFILES=Makefile.in
+
+distclean-local:
+ $(RM) *\~ *.orig *.rej .\#*
diff --git a/parser/parse.c b/parser/parse.c
new file mode 100644
index 00000000..2b81594a
--- /dev/null
+++ b/parser/parse.c
@@ -0,0 +1,190 @@
+#include "parse.h"
+#include <glib.h>
+
+struct Callback {
+ char *tag;
+ ParseCallback func;
+ void *data;
+};
+
+static GHashTable *callbacks;
+
+static void destfunc(struct Callback *c)
+{
+ g_free(c->tag);
+ g_free(c);
+}
+
+void parse_startup()
+{
+ callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+ (GDestroyNotify)destfunc);
+}
+
+void parse_shutdown()
+{
+ g_hash_table_destroy(callbacks);
+}
+
+void parse_register(const char *tag, ParseCallback func, void *data)
+{
+ struct Callback *c;
+
+ if ((c = g_hash_table_lookup(callbacks, tag))) {
+ g_warning("tag '%s' already registered", tag);
+ return;
+ }
+
+ c = g_new(struct Callback, 1);
+ c->tag = g_strdup(tag);
+ c->func = func;
+ c->data = data;
+ g_hash_table_insert(callbacks, c->tag, c);
+}
+
+gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root)
+{
+ char *path;
+ gboolean r = FALSE;
+
+ path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
+ if (parse_load(path, "openbox_config", doc, root)) {
+ r = TRUE;
+ } else {
+ g_free(path);
+ path = g_build_filename(RCDIR, "rc3", NULL);
+ if (parse_load(path, "openbox_config", doc, root)) {
+ r = TRUE;
+ }
+ }
+ g_free(path);
+ if (!r)
+ g_message("unable to find a valid config file, using defaults");
+ return r;
+}
+
+gboolean parse_load(const char *path, const char *rootname,
+ xmlDocPtr *doc, xmlNodePtr *root)
+{
+
+ xmlLineNumbersDefault(1);
+
+ if ((*doc = xmlParseFile(path))) {
+ *root = xmlDocGetRootElement(*doc);
+ if (!*root) {
+ xmlFreeDoc(*doc);
+ *doc = NULL;
+ g_warning("%s is an empty document", path);
+ } else {
+ if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) {
+ xmlFreeDoc(*doc);
+ *doc = NULL;
+ g_warning("document %s is of wrong type. root *root is "
+ "not 'openbox_config'", path);
+ }
+ }
+ }
+ if (!*doc)
+ return FALSE;
+ return TRUE;
+}
+
+void parse_close(xmlDocPtr doc)
+{
+ xmlFree(doc);
+}
+
+void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing)
+{
+ while (node) {
+ struct Callback *c = g_hash_table_lookup(callbacks, node->name);
+
+ if (c)
+ c->func(doc, node->xmlChildrenNode, c->data);
+
+ node = node->next;
+ }
+}
+
+char *parse_string(xmlDocPtr doc, xmlNodePtr node)
+{
+ xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+ char *s = g_strdup((char*)c);
+ xmlFree(c);
+ return s;
+}
+
+int parse_int(xmlDocPtr doc, xmlNodePtr node)
+{
+ xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+ int i = atoi((char*)c);
+ xmlFree(c);
+ return i;
+}
+
+gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node)
+{
+ xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+ gboolean b = FALSE;
+ if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
+ b = TRUE;
+ else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
+ b = TRUE;
+ else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
+ b = TRUE;
+ xmlFree(c);
+ return b;
+}
+
+gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node)
+{
+ xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+ gboolean r;
+ r = !xmlStrcasecmp(c, (const xmlChar*) val);
+ xmlFree(c);
+ return r;
+}
+
+xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node)
+{
+ while (node) {
+ if (!xmlStrcasecmp(node->name, (const xmlChar*) tag))
+ return node;
+ node = node->next;
+ }
+ return NULL;
+}
+
+gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value)
+{
+ xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+ gboolean r = FALSE;
+ if (c) {
+ *value = atoi((char*)c);
+ r = TRUE;
+ }
+ xmlFree(c);
+ return r;
+}
+
+gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value)
+{
+ xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+ gboolean r = FALSE;
+ if (c) {
+ *value = g_strdup((char*)c);
+ r = TRUE;
+ }
+ xmlFree(c);
+ return r;
+}
+
+gboolean parse_attr_contains(const char *val, xmlNodePtr node,
+ const char *name)
+{
+ xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+ gboolean r;
+ r = !xmlStrcasecmp(c, (const xmlChar*) val);
+ xmlFree(c);
+ return r;
+}
diff --git a/parser/parse.h b/parser/parse.h
new file mode 100644
index 00000000..948bf4ba
--- /dev/null
+++ b/parser/parse.h
@@ -0,0 +1,43 @@
+#ifndef __parse_h
+#define __parse_h
+
+#include <libxml/parser.h>
+#include <glib.h>
+
+typedef void (*ParseCallback)(xmlDocPtr doc, xmlNodePtr node, void *data);
+
+void parse_startup();
+void parse_shutdown();
+
+/* Loads Openbox's rc, from $HOME or $PREFIX as a fallback */
+gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root);
+
+/* callbacks - must call parse_startup to use these */
+
+void parse_register(const char *tag, ParseCallback func, void *data);
+void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing);
+
+
+/* open/close */
+
+gboolean parse_load(const char *path, const char *rootname,
+ xmlDocPtr *doc, xmlNodePtr *root);
+void parse_close(xmlDocPtr doc);
+
+
+/* helpers */
+
+xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node);
+
+char *parse_string(xmlDocPtr doc, xmlNodePtr node);
+int parse_int(xmlDocPtr doc, xmlNodePtr node);
+gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node);
+
+gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node);
+gboolean parse_attr_contains(const char *val, xmlNodePtr node,
+ const char *name);
+
+gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value);
+gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value);
+
+#endif