Browse Source

xml: Unfinished work on common load.c

Serj Kalichev 3 years ago
parent
commit
25db0b8757
6 changed files with 164 additions and 174 deletions
  1. 3 1
      klish/Makefile.am
  2. 2 52
      klish/kdb/Makefile.am
  3. 7 0
      klish/kdb/libxml2/Makefile.am
  4. 0 0
      klish/kdb/libxml2/kdb_api_libxml2.c
  5. 138 102
      klish/kdb/xml-common/load.c
  6. 14 19
      klish/kxml.h

+ 3 - 1
klish/Makefile.am

@@ -38,12 +38,14 @@ EXTRA_DIST += \
 	klish/ktp/Makefile.am \
 	klish/kscheme/Makefile.am \
 	klish/ischeme/Makefile.am \
-	klish/ksession/Makefile.am
+	klish/ksession/Makefile.am \
+	klish/kdb/Makefile.am
 
 include $(top_srcdir)/klish/ktp/Makefile.am
 include $(top_srcdir)/klish/kscheme/Makefile.am
 include $(top_srcdir)/klish/ischeme/Makefile.am
 include $(top_srcdir)/klish/ksession/Makefile.am
+include $(top_srcdir)/klish/kdb/Makefile.am
 
 #if TESTC
 #include $(top_srcdir)/klish/testc_module/Makefile.am

+ 2 - 52
klish/kdb/Makefile.am

@@ -1,54 +1,4 @@
-lib_LTLIBRARIES += libklish.la
-libklish_la_SOURCES =
-libklish_la_LDFLAGS = $(AM_LDFLAGS) $(VERSION_INFO)
-
-#if TESTC
-#libklish_la_CFLAGS += -DTESTC
-#endif
-
-# Common
-nobase_include_HEADERS += \
-	klish/khelper.h
-
-# KTP
-nobase_include_HEADERS += \
-	klish/ktp.h \
-	klish/ktp_session.h
-
-# Scheme
-nobase_include_HEADERS += \
-	klish/kscheme.h \
-	klish/kview.h \
-	klish/kcommand.h \
-	klish/kparam.h \
-	klish/kplugin.h \
-	klish/kaction.h \
-	klish/kptype.h \
-	klish/ksym.h
-
-# Session
-nobase_include_HEADERS += \
-	klish/kudata.h \
-	klish/kustore.h
-
-# Database
-nobase_include_HEADERS += \
-	klish/kdb.h
-
-#noinst_HEADERS += \
-#	klish/khelper.h
-
 EXTRA_DIST += \
-	klish/ktp/Makefile.am \
-	klish/ischeme/Makefile.am \
-	klish/kscheme/Makefile.am \
-	klish/ksession/Makefile.am
-
-include $(top_srcdir)/klish/ktp/Makefile.am
-include $(top_srcdir)/klish/ischeme/Makefile.am
-include $(top_srcdir)/klish/kscheme/Makefile.am
-include $(top_srcdir)/klish/ksession/Makefile.am
+	klish/kdb/libxml2/Makefile.am
 
-#if TESTC
-#include $(top_srcdir)/klish/testc_module/Makefile.am
-#endif
+include $(top_srcdir)/klish/kdb/libxml2/Makefile.am

+ 7 - 0
klish/kdb/libxml2/Makefile.am

@@ -0,0 +1,7 @@
+lib_LTLIBRARIES += kdb-libxml2.la
+kdb_libxml2_la_SOURCES =
+kdb_libxml2_la_LDFLAGS = $(AM_LDFLAGS) $(VERSION_INFO)
+
+kdb_libxml2_la_SOURCES += \
+	klish/kdb/xml-common/load.c \
+	klish/kdb/libxml2/kdb_api_libxml2.c

+ 0 - 0
klish/kdb/libxml2/shell_libxml2.c → klish/kdb/libxml2/kdb_api_libxml2.c


+ 138 - 102
klish/kdb/xml-common/load.c

@@ -16,20 +16,24 @@
 #include <faux/str.h>
 #include <faux/error.h>
 #include <klish/kscheme.h>
+#include <klish/ischeme.h>
 #include <klish/kxml.h>
 
 #define TAG "XML"
 
-typedef bool_t (kxml_process_f)(kxml_node_t *element, void *parent);
+typedef bool_t (kxml_process_fn)(const kxml_node_t *element,
+	void *parent, faux_error_t *error);
 
 static kxml_process_fn
-	process_scheme,
-	process_startup,
-	process_view,
-	process_command,
-	process_param,
 	process_action,
+	process_param,
+	process_command,
+	process_view,
 	process_ptype,
+	process_plugin,
+	process_klish;
+
+/*	process_startup,
 	process_overview,
 	process_detail,
 	process_namespace,
@@ -37,49 +41,93 @@ static kxml_process_fn
 	process_var,
 	process_wdog,
 	process_hotkey,
-	process_plugin,
 	process_hook;
-
-
-typedef struct kxml_cb_s kxml_cb_t;
-struct kxml_cb_s {
-	const char *element;
-	kxml_process_fn *handler;
+*/
+
+// Different TAGs types
+typedef enum {
+	KTAG_NONE,
+	KTAG_ACTION,
+	KTAG_PARAM,
+	KTAG_COMMAND,
+	KTAG_VIEW,
+	KTAG_PTYPE,
+	KTAG_PLUGIN,
+	KTAG_KLISH,
+	KTAG_MAX
+} ktags_e;
+
+static const char *kxml_tags[] = {
+	NULL,
+	"ACTION",
+	"PARAM",
+	"COMMAND",
+	"VIEW",
+	"PTYPE",
+	"PLUGIN",
+	"KLISH"
 };
 
-static kxml_cb_t xml_elements[] = {
-	{"KLISH", process_scheme},
-	{"STARTUP", process_startup},
-	{"VIEW", process_view},
-	{"COMMAND", process_command},
-	{"PARAM", process_param},
-	{"ACTION", process_action},
-	{"PTYPE", process_ptype},
-	{"OVERVIEW", process_overview},
-	{"DETAIL", process_detail},
-	{"NAMESPACE", process_namespace},
-	{"CONFIG", process_config},
-	{"VAR", process_var},
-	{"WATCHDOG", process_wdog},
-	{"HOTKEY", process_hotkey},
-	{"PLUGIN", process_plugin},
-	{"HOOK", process_hook},
-	{NULL, NULL}
+static kxml_process_fn *kxml_handlers[] = {
+	NULL,
+	process_action,
+	process_param,
+	process_command,
+	process_view,
+	process_ptype,
+	process_plugin,
+	process_klish
 };
 
 
-/** @brief Default path to get XML files from.
+static ktags_e kxml_node_tag(const kxml_node_t *node)
+{
+	ktags_e tag = KTAG_NONE;
+	char *name = NULL;
+
+	if (!node)
+		return KTAG_NONE;
+
+	if (kxml_node_type(node) != KXML_NODE_ELM)
+		return KTAG_NONE;
+	name = kxml_node_name(node);
+	if (!name)
+		return KTAG_NONE; // Strange case
+	for (tag = KTAG_NONE; tag < KTAG_MAX; tag++) {
+		if (faux_str_casecmp(name, kxml_tags[tag]))
+			break;
+	}
+	kxml_node_name_free(name);
+	if (tag >= KTAG_MAX)
+		return KTAG_NONE;
+
+	return tag;
+}
+
+
+static kxml_process_fn *kxml_node_handler(const kxml_node_t *node)
+{
+	return kxml_handlers[kxml_node_tag(node)];
+}
+
+
+/** @brief Reads an element from the XML stream and processes it.
  */
-const char *default_path = "/etc/klish;~/.klish";
-static const char *path_separators = ":;";
+static bool_t process_node(const kxml_node_t *node, void *parent, faux_error_t *error)
+{
+	kxml_process_fn *handler = kxml_node_handler(node);
 
+	if (!handler)
+		return BOOL_TRUE; // Unknown element
 
-static bool_t process_node(kxml_node_t *node, void *parent, faux_error_t *error);
+	return handler(node, parent, error);
+}
 
 
-static bool_t kxml_load_file(kscheme_t *scheme, const char *filename, faux_error_t *error)
+
+static bool_t kxml_load_file(kscheme_t *scheme, const char *filename,
+	faux_error_t *error)
 {
-	int res = -1;
 	kxml_doc_t *doc = NULL;
 	kxml_node_t *root = NULL;
 	bool_t r = BOOL_FALSE;
@@ -91,19 +139,19 @@ static bool_t kxml_load_file(kscheme_t *scheme, const char *filename, faux_error
 
 	doc = kxml_doc_read(filename);
 	if (!kxml_doc_is_valid(doc)) {
-		int errcaps = kxml_doc_error_caps(doc);
-/*		printf("Unable to open file '%s'", filename);
+/*		int errcaps = kxml_doc_error_caps(doc);
+		printf("Unable to open file '%s'", filename);
 		if ((errcaps & kxml_ERR_LINE) == kxml_ERR_LINE)
-			printf(", at line %d", kxml_doc_get_err_line(doc));
+			printf(", at line %d", kxml_doc_err_line(doc));
 		if ((errcaps & kxml_ERR_COL) == kxml_ERR_COL)
-			printf(", at column %d", kxml_doc_get_err_col(doc));
+			printf(", at column %d", kxml_doc_err_col(doc));
 		if ((errcaps & kxml_ERR_DESC) == kxml_ERR_DESC)
-			printf(", message is %s", kxml_doc_get_err_msg(doc));
+			printf(", message is %s", kxml_doc_err_msg(doc));
 		printf("\n");
 */		kxml_doc_release(doc);
 		return BOOL_FALSE;
 	}
-	root = kxml_doc_get_root(doc);
+	root = kxml_doc_root(doc);
 	r = process_node(root, scheme, error);
 	kxml_doc_release(doc);
 	if (!r) {
@@ -115,6 +163,12 @@ static bool_t kxml_load_file(kscheme_t *scheme, const char *filename, faux_error
 }
 
 
+/** @brief Default path to get XML files from.
+ */
+const char *default_path = "/etc/klish;~/.klish";
+static const char *path_separators = ":;";
+
+
 kscheme_t *kxml_load_scheme(const char *xml_path, faux_error_t *error)
 {
 	kscheme_t *scheme = NULL;
@@ -179,45 +233,13 @@ kscheme_t *kxml_load_scheme(const char *xml_path, faux_error_t *error)
 }
 
 
-/** @brief Reads an element from the XML stream and processes it.
- */
-static bool_t process_node(kxml_node_t *node, void *parent, faux_error_t *error)
-{
-	kxml_cb_t *cb = NULL;
-	char *name = NULL;
-	kxml_process_fn *handler = NULL;
-
-	if (!node)
-		return BOOL_FALSE;
-	if (!parent)
-		return BOOL_FALSE;
-
-	if (kxml_node_type(node) != KXML_NODE_ELM)
-		return BOOL_TRUE;
-
-	name = kxml_node_name(node);
-	if (!name)
-		return BOOL_TRUE; // Strange case
-	// Find element handler
-	for (cb = &xml_elements[0]; cb->element; cb++) {
-		if (faux_str_casecmp(name, cb->element)) {
-			handler = cb->handler;
-			break;
-		}
-	}
-	kxml_node_name_free(name);
-	if (!handler)
-		return BOOL_TRUE; // Unknown element
-
-	return handler(node, parent, error);
-}
-
 
 /** @brief Iterate through element's children.
  */
-static bool_t process_children(kxml_node_t *element, void *parent, faux_error_t *error)
+static bool_t process_children(const kxml_node_t *element, void *parent,
+	faux_error_t *error)
 {
-	kxml_node_t *node = NULL;
+	const kxml_node_t *node = NULL;
 
 	while ((node = kxml_node_next_child(element, node)) != NULL) {
 		bool_t res = BOOL_FALSE;
@@ -230,38 +252,51 @@ static bool_t process_children(kxml_node_t *element, void *parent, faux_error_t
 }
 
 
-static bool_t process_scheme(kxml_node_t *element, void *parent, faux_error_t *error)
+static bool_t process_klish(const kxml_node_t *element, void *parent,
+	faux_error_t *error)
 {
-	parent = parent; // Happy compiler
-
 	return process_children(element, parent, error);
 }
 
 
-static bool_t process_view(kxml_node_t *element, void *parent, faux_error_t *error)
+static bool_t process_view(const kxml_node_t *element, void *parent,
+	faux_error_t *error)
 {
 	iview_t iview = {};
-	clish_view_t *view = NULL;
+	kview_t *view = NULL;
 	bool_t res = BOOL_FALSE;
+	ktags_e parent_tag = kxml_node_tag(kxml_node_parent(element));
+
+	if (parent_tag != KTAG_KLISH) {
+		faux_error_add(error, TAG": Only KLISH tag can contain VIEW tag");
+		return BOOL_FALSE;
+	}
 
 	iview.name = kxml_node_attr(element, "name");
 
-	view = iview_load(iview, error);
+	view = iview_load(&iview, error);
 	if (!view)
 		goto err;
-	if (!process_children(shell, element, view))
+
+	if (!kscheme_add_view((kscheme_t *)parent, view)) {
+		faux_error_sprintf(error, TAG": Can't add VIEW \"%s\"",
+			kview_name(view));
+		kview_free(view);
+		goto err;
+	}
+
+	if (!process_children(element, view, error))
 		goto err;
 
 	res = BOOL_TRUE;
 err:
-	kxml_node_attr_free(name);
-
-	parent = parent; /* Happy compiler */
+	kxml_node_attr_free(iview.name);
 
 	return res;
 }
 
 
+/*
 static int process_ptype(kxml_node_t *element,
 	void *parent)
 {
@@ -277,7 +312,7 @@ static int process_ptype(kxml_node_t *element,
 	char *preprocess_name =	kxml_node_attr(element, "preprocess");
 	char *completion = kxml_node_attr(element, "completion");
 
-	/* Check syntax */
+	// Check syntax
 	if (!name) {
 		fprintf(stderr, kxml__ERROR_ATTR("name"));
 		goto error;
@@ -309,12 +344,12 @@ error:
 	kxml_node_attr_free(preprocess_name);
 	kxml_node_attr_free(completion);
 
-	parent = parent; /* Happy compiler */
+	parent = parent; // Happy compiler
 
 	return res;
 }
-
-
+*/
+#if 0
 static int process_overview(kxml_node_t *element,
 	void *parent)
 {
@@ -337,7 +372,7 @@ static int process_overview(kxml_node_t *element,
 			return -1;
 		}
 		content = new;
-		result = kxml_node_get_content(element, content,
+		result = kxml_node_content(element, content,
 			&content_len);
 	} while (result == -E2BIG);
 
@@ -561,7 +596,7 @@ static int process_param(kxml_node_t *element,
 
 	/* The PARAM can be child of COMMAND or another PARAM */
 	pelement = kxml_node_parent(element);
-	pname = kxml_node_get_all_name(pelement);
+	pname = kxml_node_all_name(pelement);
 	if (pname && lub_string_nocasecmp(pname, "PARAM") == 0)
 		p_param = (clish_param_t *)parent;
 	else
@@ -723,21 +758,21 @@ static int process_action(kxml_node_t *element,
 	char *expand = kxml_node_attr(element, "expand");
 
 	kxml_node_t *pelement = kxml_node_parent(element);
-	char *pname = kxml_node_get_all_name(pelement);
+	char *pname = kxml_node_all_name(pelement);
 	char *text;
 	clish_sym_t *sym = NULL;
 
 	if (pname && lub_string_nocasecmp(pname, "VAR") == 0)
-		action = clish_var__get_action((clish_var_t *)parent);
+		action = clish_var__action((clish_var_t *)parent);
 	else if (pname && lub_string_nocasecmp(pname, "PTYPE") == 0)
-		action = clish_ptype__get_action((clish_ptype_t *)parent);
+		action = clish_ptype__action((clish_ptype_t *)parent);
 	else
-		action = clish_command__get_action((clish_command_t *)parent);
+		action = clish_command__action((clish_command_t *)parent);
 
 	if (pname)
 		free(pname);
 
-	text = kxml_node_get_all_content(element);
+	text = kxml_node_all_content(element);
 
 	if (text && *text) {
 		/* store the action */
@@ -789,7 +824,7 @@ static int process_detail(kxml_node_t *element,
 	clish_command_t *cmd = (clish_command_t *) parent;
 
 	/* read the following text element */
-	char *text = kxml_node_get_all_content(element);
+	char *text = kxml_node_all_content(element);
 
 	if (text && *text) {
 		/* store the action */
@@ -895,7 +930,7 @@ static int process_config(kxml_node_t *element,
 
 	if (!cmd)
 		return 0;
-	config = clish_command__get_config(cmd);
+	config = clish_command__config(cmd);
 
 	/* read the following text element */
 	char *operation = kxml_node_attr(element, "operation");
@@ -1104,7 +1139,7 @@ static int process_plugin(kxml_node_t *element,
 		clish_plugin__set_rtld_global(plugin, BOOL_TRUE);
 
 	/* Get PLUGIN body content */
-	text = kxml_node_get_all_content(element);
+	text = kxml_node_all_content(element);
 	if (text && *text)
 		clish_plugin__set_conf(plugin, text);
 	if (text)
@@ -1168,3 +1203,4 @@ error:
 
 	return res;
 }
+#endif

+ 14 - 19
klish/kxml.h

@@ -16,6 +16,13 @@
 typedef struct kxml_doc_s kxml_doc_t;
 
 
+/* @brief XML node (opaque type).
+ *
+ * The real type is defined by the selected external API.
+ */
+typedef struct kxml_node_s kxml_node_t;
+
+
 /** @brief Start and Stop XML parser engine.
  *
  * Some parsers need a global cleanup at the end of the programm.
@@ -53,14 +60,6 @@ int kxml_doc_err_col(kxml_doc_t *doc);
 const char *kxml_doc_err_msg(kxml_doc_t *doc);
 
 
-
-/* @brief XML node (opaque type).
- *
- * The real type is defined by the selected external API.
- */
-typedef struct kxml_node_s kxml_node_t;
-
-
 /** @brief Node types.
  */
 typedef enum {
@@ -77,32 +76,33 @@ typedef enum {
 
 /** @brief Gets the node type.
  */
-int kxml_node_type(kxml_node_t *node);
+int kxml_node_type(const kxml_node_t *node);
 
 
 /** @brief Gets the next child or NULL.
  *
  * If curchild is NULL, then the function returns the first child.
  */
-kxml_node_t *kxml_node_next_child(kxml_node_t *parent, kxml_node_t *curchild);
+const kxml_node_t *kxml_node_next_child(const kxml_node_t *parent,
+	const kxml_node_t *curchild);
 
 
 /** @brief Gets the parent node.
  *
  * Returns NULL if node is the document root node.
  */
-kxml_node_t *kxml_node_parent(kxml_node_t *node);
+kxml_node_t *kxml_node_parent(const kxml_node_t *node);
 
 
 /** @brief Gets the node name.
  */
-char *kxml_node_name(kxml_node_t *node);
+char *kxml_node_name(const kxml_node_t *node);
 void kxml_node_name_free(char *str);
 
 
 /** @brief Gets the node content.
  */
-char *kxml_node_content(kxml_node_t *node);
+char *kxml_node_content(const kxml_node_t *node);
 void kxml_node_content_free(char *str);
 
 
@@ -110,13 +110,8 @@ void kxml_node_content_free(char *str);
  *
  * May return NULL if the attribute is not found
  */
-char *kxml_node_attr(kxml_node_t *node, const char *attrname);
+char *kxml_node_attr(const kxml_node_t *node, const char *attrname);
 void kxml_node_attr_free(char *str);
 
 
-/** @brief Frees a pointer allocated by the XML backend.
- */
-void kxml_release(void *p);
-
-
 #endif // _klish_kxml_h