Преглед на файлове

xml: Unfinished common parsing

Serj Kalichev преди 3 години
родител
ревизия
cbf6ec054c
променени са 1 файла, в които са добавени 123 реда и са изтрити 172 реда
  1. 123 172
      klish/kdb/xml-common/load.c

+ 123 - 172
klish/kdb/xml-common/xml_common.c → klish/kdb/xml-common/load.c

@@ -1,4 +1,4 @@
-/** @file xml_common.c
+/** @file load.c
  * @brief Common part for XML parsing.
  *
  * Different XML parsing engines can provide a functions in a form of
@@ -18,6 +18,7 @@
 #include <klish/kscheme.h>
 #include <klish/kxml.h>
 
+#define TAG "XML"
 
 typedef bool_t (kxml_process_f)(kxml_node_t *element, void *parent);
 
@@ -70,173 +71,157 @@ static kxml_cb_t xml_elements[] = {
 /** @brief Default path to get XML files from.
  */
 const char *default_path = "/etc/klish;~/.klish";
-const char *path_separators = ":;";
+static const char *path_separators = ":;";
 
 
-static bool_t process_node(kxml_node_t *node,
-	void *parent);
+static bool_t process_node(kxml_node_t *node, void *parent, faux_error_t *error);
 
 
-bool_t kxml_load_scheme(clish_shell_t *this, const char *xml_path, const char *xslt_path)
+static bool_t kxml_load_file(kscheme_t *scheme, const char *filename, faux_error_t *error)
 {
-	const char *path = xml_path;
-	char *buffer;
-	char *dirname;
-	char *saveptr = NULL;
 	int res = -1;
 	kxml_doc_t *doc = NULL;
-	DIR *dir;
+	kxml_node_t *root = NULL;
+	bool_t r = BOOL_FALSE;
+
+	if (!scheme)
+		return BOOL_FALSE;
+	if (!filename)
+		return BOOL_FALSE;
+
+	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);
+		if ((errcaps & kxml_ERR_LINE) == kxml_ERR_LINE)
+			printf(", at line %d", kxml_doc_get_err_line(doc));
+		if ((errcaps & kxml_ERR_COL) == kxml_ERR_COL)
+			printf(", at column %d", kxml_doc_get_err_col(doc));
+		if ((errcaps & kxml_ERR_DESC) == kxml_ERR_DESC)
+			printf(", message is %s", kxml_doc_get_err_msg(doc));
+		printf("\n");
+*/		kxml_doc_release(doc);
+		return BOOL_FALSE;
+	}
+	root = kxml_doc_get_root(doc);
+	r = process_node(root, scheme, error);
+	kxml_doc_release(doc);
+	if (!r) {
+		faux_error_sprintf(error, TAG": Illegal file %s", filename);
+		return BOOL_FALSE;
+	}
+
+	return BOOL_TRUE;
+}
 
-	/* Use the default path */
+
+kscheme_t *kxml_load_scheme(const char *xml_path, faux_error_t *error)
+{
+	kscheme_t *scheme = NULL;
+	const char *path = xml_path;
+	char *realpath = NULL;
+	char *fn = NULL;
+	char *saveptr = NULL;
+	bool_t ret = BOOL_TRUE;
+
+	// New kscheme instance
+	scheme = kscheme_new();
+	if (!scheme)
+		return NULL;
+
+	// Use the default path if not specified
 	if (!path)
 		path = default_path;
-	buffer = lub_system_tilde_expand(path);
-
-	/* Loop though each directory */
-	for (dirname = strtok_r(buffer, path_separators, &saveptr);
-		dirname; dirname = strtok_r(NULL, path_separators, &saveptr)) {
-		struct dirent *entry;
+	realpath = faux_expand_tilde(path);
+
+	// Loop through each directory
+	for (fn = strtok_r(realpath, path_separators, &saveptr);
+		fn; fn = strtok_r(NULL, path_separators, &saveptr)) {
+		DIR *dir = NULL;
+		struct dirent *entry = NULL;
+
+		// Regular file
+		if (faux_isfile(fn)) {
+			if (!kxml_load_file(scheme, fn, error)) {
+				ret = BOOL_FALSE;
+				continue;
+			}
+		}
 
-		/* Search this directory for any XML files */
-		dir = opendir(dirname);
-		if (NULL == dir) {
+		// Search this directory for any XML files
+		dir = opendir(fn);
+		if (!dir)
 			continue;
-		}
 		for (entry = readdir(dir); entry; entry = readdir(dir)) {
 			const char *extension = strrchr(entry->d_name, '.');
 			char *filename = NULL;
-			kxml_node_t *root;
-			int r;
 
-			/* Check the filename */
+			// Check the filename
 			if (!extension || strcmp(".xml", extension))
 				continue;
-
-			/* Build the filename */
-			lub_string_cat(&filename, dirname);
-			lub_string_cat(&filename, "/");
-			lub_string_cat(&filename, entry->d_name);
-
-			/* Load current XML file */
-			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);
-				if ((errcaps & kxml_ERR_LINE) == kxml_ERR_LINE)
-					printf(", at line %d", kxml_doc_get_err_line(doc));
-				if ((errcaps & kxml_ERR_COL) == kxml_ERR_COL)
-					printf(", at column %d", kxml_doc_get_err_col(doc));
-				if ((errcaps & kxml_ERR_DESC) == kxml_ERR_DESC)
-					printf(", message is %s", kxml_doc_get_err_msg(doc));
-				printf("\n");
-				goto error;
-			}
-
-			root = kxml_doc_get_root(doc);
-			r = process_node(this, root, NULL);
-			kxml_doc_release(doc);
-
-			/* Error message */
-			if (r) {
-				fprintf(stderr, kxml__ERROR_STR"File %s\n",
-					filename);
-				lub_string_free(filename);
-				goto error;
+			filename = faux_str_sprintf("%s/%s", fn, entry->d_name);
+			if (!kxml_load_file(scheme, filename, error)) {
+				ret = BOOL_FALSE;
+				continue;
 			}
-			lub_string_free(filename);
+			faux_str_free(filename);
 		}
 		closedir(dir);
 	}
 
-/* To don't free memory twice on cleanup */
-	doc = NULL;
-	dir = NULL;
-	res = 0; /* Success */
-error:
-	lub_string_free(buffer);
-	if (dir)
-		closedir(dir);
-	if (kxml_doc_is_valid(doc))
-		kxml_doc_release(doc);
+	faux_str_free(realpath);
+	if (!ret) { // Some errors while XML parsing
+		kscheme_free(scheme);
+		return NULL;
+	}
 
-	return res;
+	return scheme;
 }
 
 
 /** @brief Reads an element from the XML stream and processes it.
  */
-static bool_t process_node(kxml_node_t *node,
-	void *parent)
+static bool_t process_node(kxml_node_t *node, void *parent, faux_error_t *error)
 {
-	int res = 0;
-
-	switch (kxml_node_get_type(node)) {
-	case kxml_NODE_ELM: {
-			kxml__cb_t * cb;
-			char name[128];
-			unsigned int namelen = sizeof(name);
-			if (kxml_node_get_name(node, name, &namelen) == 0) {
-				for (cb = &xml_elements[0]; cb->element; cb++) {
-					if (0 == strcmp(name, cb->element)) {
-#ifdef DEBUG
-						fprintf(stderr, "NODE:");
-						kxml_node_print(node, stderr);
-						fprintf(stderr, "\n");
-#endif
-						/* process the elements at this level */
-						res = cb->handler(shell, node, parent);
-
-						/* Error message */
-						if (res) {
-							char *ename = kxml_node_attr(node, "name");
-							char *eref = kxml_node_attr(node, "ref");
-							char *ekey = kxml_node_attr(node, "key");
-							char *efile = kxml_node_attr(node, "file");
-							fprintf(stderr, kxml__ERROR_STR"Node %s", name);
-							if (ename)
-								fprintf(stderr, ", name=\"%s\"", ename);
-							if (eref)
-								fprintf(stderr, ", ref=\"%s\"", eref);
-							if (ekey)
-								fprintf(stderr, ", key=\"%s\"", ekey);
-							if (efile)
-								fprintf(stderr, ", file=\"%s\"", efile);
-							fprintf(stderr, "\n");
-							kxml_node_attr_free(ename);
-							kxml_node_attr_free(eref);
-							kxml_node_attr_free(ekey);
-							kxml_node_attr_free(efile);
-						}
-						break;
-					}
-				}
-			}
+	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;
 		}
-	case kxml_NODE_DOC:
-	case kxml_NODE_TEXT:
-	case kxml_NODE_ATTR:
-	case kxml_NODE_PI:
-	case kxml_NODE_COMMENT:
-	case kxml_NODE_DECL:
-	case kxml_NODE_UNKNOWN:
-	default:
-		break;
 	}
+	kxml_node_name_free(name);
+	if (!handler)
+		return BOOL_TRUE; // Unknown element
 
-	return res;
+	return handler(node, parent, error);
 }
 
 
 /** @brief Iterate through element's children.
  */
-static bool_t process_children(kxml_node_t *element, void *parent)
+static bool_t process_children(kxml_node_t *element, void *parent, faux_error_t *error)
 {
 	kxml_node_t *node = NULL;
 
 	while ((node = kxml_node_next_child(element, node)) != NULL) {
 		bool_t res = BOOL_FALSE;
-		res = process_node(node, parent);
+		res = process_node(node, parent, error);
 		if (!res)
 			return res;
 	}
@@ -245,65 +230,31 @@ static bool_t process_children(kxml_node_t *element, void *parent)
 }
 
 
-static int process_scheme(kxml_node_t *element, void *parent)
+static bool_t process_scheme(kxml_node_t *element, void *parent, faux_error_t *error)
 {
-	/* Create the global view */
-	if (!shell->global)
-		shell->global = clish_shell_find_create_view(shell, "__view_global");
+	parent = parent; // Happy compiler
 
-	parent = parent; /* Happy compiler */
-
-	return process_children(shell, element, shell->global);
+	return process_children(element, parent, error);
 }
 
 
-static int process_view(kxml_node_t *element,
-	void *parent)
+static bool_t process_view(kxml_node_t *element, void *parent, faux_error_t *error)
 {
+	iview_t iview = {};
 	clish_view_t *view = NULL;
-	clish_view_restore_e restore_e = CLISH_RESTORE_NONE;
-	int res = -1;
-
-	char *name = kxml_node_attr(element, "name");
-	char *prompt = kxml_node_attr(element, "prompt");
-	char *depth = kxml_node_attr(element, "depth");
-	char *restore = kxml_node_attr(element, "restore");
-	char *access = kxml_node_attr(element, "access");
-
-	/* Check syntax */
-	if (!name) {
-		fprintf(stderr, kxml__ERROR_ATTR("name"));
-		goto error;
-	}
+	bool_t res = BOOL_FALSE;
 
-	/* re-use a view if it already exists */
-	view = clish_shell_find_create_view(shell, name);
+	iview.name = kxml_node_attr(element, "name");
 
-	if (prompt)
-		clish_view__set_prompt(view, prompt);
+	view = iview_load(iview, error);
+	if (!view)
+		goto err;
+	if (!process_children(shell, element, view))
+		goto err;
 
-	if (depth && (lub_ctype_isdigit(*depth))) {
-		unsigned int res = 0;
-		lub_conv_atoui(depth, &res, 0);
-		clish_view__set_depth(view, res);
-	}
-
-	if (restore) {
-		restore_e = clish_view_restore_resolve(restore);
-		clish_view__set_restore(view, restore_e);
-	}
-
-	if (access)
-		clish_view__set_access(view, access);
-
-//process_view_end:
-	res = process_children(shell, element, view);
-error:
+	res = BOOL_TRUE;
+err:
 	kxml_node_attr_free(name);
-	kxml_node_attr_free(prompt);
-	kxml_node_attr_free(depth);
-	kxml_node_attr_free(restore);
-	kxml_node_attr_free(access);
 
 	parent = parent; /* Happy compiler */