Browse Source

scheme: ischeme transformation. Unfinished

Serj Kalichev 3 years ago
parent
commit
4c642f304a

+ 1 - 1
Makefile.am

@@ -43,7 +43,7 @@ EXTRA_DIST =
 #	ISSUES
 
 include $(top_srcdir)/klish/Makefile.am
-include $(top_srcdir)/bin/Makefile.am
+#include $(top_srcdir)/bin/Makefile.am
 
 #include $(top_srcdir)/tinyrl/module.am
 #include $(top_srcdir)/konf/module.am

+ 2 - 2
klish/Makefile.am

@@ -36,13 +36,13 @@ nobase_include_HEADERS += \
 
 EXTRA_DIST += \
 	klish/ktp/Makefile.am \
-	klish/ischeme/Makefile.am \
 	klish/kscheme/Makefile.am \
+	klish/ischeme/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/ischeme/Makefile.am
 include $(top_srcdir)/klish/ksession/Makefile.am
 
 #if TESTC

+ 4 - 1
klish/iaction.h

@@ -22,7 +22,10 @@ typedef struct iaction_s {
 
 C_DECL_BEGIN
 
-char *iaction_to_text(const iaction_t *iaction, int level);
+bool_t iaction_parse(const iaction_t *info, kaction_t *action,
+	faux_error_t *error);
+kaction_t *iaction_load(const iaction_t *iaction, faux_error_t *error);
+char *iaction_deploy(const kaction_t *kaction, int level);
 
 C_DECL_END
 

+ 4 - 1
klish/iplugin.h

@@ -17,7 +17,10 @@ typedef struct iplugin_s {
 
 C_DECL_BEGIN
 
-char *iplugin_to_text(const iplugin_t *iplugin, int level);
+bool_t iplugin_parse(const iplugin_t *info, kplugin_t *plugin,
+	faux_error_t *error);
+kplugin_t *iplugin_load(iplugin_t *iplugin, faux_error_t *error);
+char *iplugin_deploy(const kplugin_t *kplugin, int level);
 
 C_DECL_END
 

+ 6 - 5
klish/ischeme/Makefile.am

@@ -1,8 +1,9 @@
 libklish_la_SOURCES += \
-	klish/ischeme/ischeme.c \
-	klish/ischeme/iptype.c \
 	klish/ischeme/iaction.c \
-	klish/ischeme/iview.c \
-	klish/ischeme/icommand.c \
-	klish/ischeme/iparam.c \
 	klish/ischeme/iplugin.c
+
+#	klish/ischeme/ischeme.c
+#	klish/ischeme/iptype.c
+#	klish/ischeme/iview.c
+#	klish/ischeme/icommand.c
+#	klish/ischeme/iparam.c

+ 118 - 8
klish/ischeme/iaction.c

@@ -4,25 +4,135 @@
 #include <assert.h>
 
 #include <faux/str.h>
+#include <faux/conv.h>
+#include <faux/list.h>
+#include <faux/error.h>
 #include <klish/khelper.h>
+#include <klish/kaction.h>
 #include <klish/iaction.h>
 
-char *iaction_to_text(const iaction_t *iaction, int level)
+#define TAG "ACTION"
+
+
+bool_t iaction_parse(const iaction_t *info, kaction_t *action, faux_error_t *error)
+{
+	bool_t retcode = BOOL_TRUE;
+
+	if (!info)
+		return BOOL_FALSE;
+	if (!action)
+		return BOOL_FALSE;
+
+	// Sym
+	if (!faux_str_is_empty(info->sym)) {
+		if (!kaction_set_sym_ref(action, info->sym)) {
+			faux_error_add(error, TAG": Illegal 'sym' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// Lock
+	if (!faux_str_is_empty(info->lock)) {
+		if (!kaction_set_lock(action, info->lock)) {
+			faux_error_add(error, TAG": Illegal 'lock' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// Interrupt
+	if (!faux_str_is_empty(info->interrupt)) {
+		bool_t b = BOOL_FALSE;
+		if (!faux_conv_str2bool(info->interrupt, &b) ||
+			!kaction_set_interrupt(action, b)) {
+			faux_error_add(error, TAG": Illegal 'interrupt' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// Interactive
+	if (!faux_str_is_empty(info->interactive)) {
+		bool_t b = BOOL_FALSE;
+		if (!faux_conv_str2bool(info->interactive, &b) ||
+			!kaction_set_interactive(action, b)) {
+			faux_error_add(error, TAG": Illegal 'interactive' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// Exec_on
+	if (!faux_str_is_empty(info->exec_on)) {
+		kaction_cond_e c = KACTION_COND_NONE;
+		if (faux_str_casecmp(info->exec_on, "fail"))
+			c = KACTION_COND_FAIL;
+		else if (faux_str_casecmp(info->exec_on, "success"))
+			c = KACTION_COND_SUCCESS;
+		else if (faux_str_casecmp(info->exec_on, "always"))
+			c = KACTION_COND_ALWAYS;
+		if ((KACTION_COND_NONE == c) || !kaction_set_exec_on(action, c)) {
+			faux_error_add(error, TAG": Illegal 'exec_on' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// Update_retcode
+	if (!faux_str_is_empty(info->update_retcode)) {
+		bool_t b = BOOL_FALSE;
+		if (!faux_conv_str2bool(info->update_retcode, &b) ||
+			!kaction_set_update_retcode(action, b)) {
+			faux_error_add(error, TAG": Illegal 'update_retcode' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// Script
+	if (!faux_str_is_empty(info->script)) {
+		if (!kaction_set_script(action, info->script)) {
+			faux_error_add(error, TAG": Illegal 'script' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	return retcode;
+}
+
+
+kaction_t *iaction_load(const iaction_t *iaction, faux_error_t *error)
+{
+	kaction_t *kaction = NULL;
+
+	kaction = kaction_new();
+	if (!kaction) {
+		faux_error_add(error, TAG": Can't create object");
+		return NULL;
+	}
+	if (!iaction_parse(iaction, kaction, error)) {
+		kaction_free(kaction);
+		return NULL;
+	}
+
+	return kaction;
+}
+
+
+char *iaction_deploy(const kaction_t *kaction, int level)
 {
 	char *str = NULL;
 	char *tmp = NULL;
 
+	if (!kaction)
+		return NULL;
+
 	tmp = faux_str_sprintf("%*cACTION {\n", level, ' ');
 	faux_str_cat(&str, tmp);
 	faux_str_free(tmp);
 
-	attr2ctext(&str, "sym", iaction->sym, level + 1);
-	attr2ctext(&str, "lock", iaction->lock, level + 1);
-	attr2ctext(&str, "interrupt", iaction->interrupt, level + 1);
-	attr2ctext(&str, "interactive", iaction->interactive, level + 1);
-	attr2ctext(&str, "exec_on", iaction->exec_on, level + 1);
-	attr2ctext(&str, "update_retcode", iaction->update_retcode, level + 1);
-	attr2ctext(&str, "script", iaction->script, level + 1);
+	attr2ctext(&str, "sym", kaction_sym_ref(kaction), level + 1);
+	attr2ctext(&str, "lock", kaction_lock(kaction), level + 1);
+	attr2ctext(&str, "interrupt", faux_conv_bool2str(kaction_interrupt(kaction)), level + 1);
+	attr2ctext(&str, "interactive", faux_conv_bool2str(kaction_interactive(kaction)), level + 1);
+	attr2ctext(&str, "exec_on", faux_conv_bool2str(kaction_exec_on(kaction)), level + 1);
+	attr2ctext(&str, "update_retcode", faux_conv_bool2str(kaction_update_retcode(kaction)), level + 1);
+	attr2ctext(&str, "script", kaction_script(kaction), level + 1);
 
 	tmp = faux_str_sprintf("%*c},\n\n", level, ' ');
 	faux_str_cat(&str, tmp);

+ 128 - 0
klish/ischeme/icommand.c

@@ -4,8 +4,136 @@
 #include <assert.h>
 
 #include <faux/str.h>
+#include <faux/list.h>
+#include <faux/error.h>
 #include <klish/khelper.h>
 #include <klish/icommand.h>
+#include <klish/kparam.h>
+#include <klish/kaction.h>
+#include <klish/kcommand.h>
+
+#define TAG "COMMAND"
+
+bool_t kcommand_parse(kcommand_t *command, const icommand_t *info,
+	faux_error_t *error)
+{
+	bool_t retcode = BOOL_TRUE;
+
+	// Help
+	if (!faux_str_is_empty(info->help)) {
+		if (!kcommand_set_help(command, info->help)) {
+			faux_error_add(error, TAG": Illegal 'help' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	return retcode;
+}
+
+
+bool_t kcommand_nested_from_icommand(kcommand_t *kcommand, icommand_t *icommand,
+	faux_error_t *error)
+{
+	bool_t retval = BOOL_TRUE;
+
+	if (!kcommand || !icommand) {
+		faux_error_add(error, TAG": Internal error");
+		return BOOL_FALSE;
+	}
+
+
+	// PARAM list
+	if (icommand->params) {
+		iparam_t **p_iparam = NULL;
+		for (p_iparam = *icommand->params; *p_iparam; p_iparam++) {
+			kparam_t *kparam = NULL;
+			iparam_t *iparam = *p_iparam;
+
+			kparam = kparam_from_iparam(iparam, error);
+			if (!kparam) {
+				retval = BOOL_FALSE;
+				continue;
+			}
+			if (!kcommand_add_param(kcommand, kparam)) {
+				// Search for PARAM duplicates
+				if (kcommand_find_param(kcommand,
+					kparam_name(kparam))) {
+					faux_error_sprintf(error,
+						TAG": Can't add duplicate PARAM "
+						"\"%s\"", kparam_name(kparam));
+				} else {
+					faux_error_sprintf(error,
+						TAG": Can't add PARAM \"%s\"",
+						kparam_name(kparam));
+				}
+				kparam_free(kparam);
+				retval = BOOL_FALSE;
+				continue;
+			}
+		}
+	}
+
+	// ACTION list
+	if (icommand->actions) {
+		iaction_t **p_iaction = NULL;
+		for (p_iaction = *icommand->actions; *p_iaction; p_iaction++) {
+			kaction_t *kaction = NULL;
+			iaction_t *iaction = *p_iaction;
+
+			kaction = kaction_from_iaction(iaction, error);
+			if (!kaction) {
+				retval = BOOL_FALSE;
+				continue;
+			}
+			if (!kcommand_add_action(kcommand, kaction)) {
+				faux_error_sprintf(error,
+					TAG": Can't add ACTION #%d",
+					kcommand_actions_len(kcommand) + 1);
+				kaction_free(kaction);
+				retval = BOOL_FALSE;
+				continue;
+			}
+		}
+	}
+
+	if (!retval)
+		faux_error_sprintf(error, TAG" \"%s\": Illegal nested elements",
+			kcommand_name(kcommand));
+
+	return retval;
+}
+
+
+kcommand_t *kcommand_from_icommand(icommand_t *icommand, faux_error_t *error)
+{
+	kcommand_t *kcommand = NULL;
+
+	// Name [mandatory]
+	if (faux_str_is_empty(icommand->name)) {
+		faux_error_add(error, TAG": Empty 'name' attribute");
+		return NULL;
+	}
+
+	kcommand = kcommand_new(icommand->name);
+	if (!kcommand) {
+		faux_error_sprintf(error, TAG" \"%s\": Can't create object",
+			icommand->name);
+		return NULL;
+	}
+
+	if (!kcommand_parse(kcommand, icommand, error)) {
+		kcommand_free(kcommand);
+		return NULL;
+	}
+
+	// Parse nested elements
+	if (!kcommand_nested_from_icommand(kcommand, icommand, error)) {
+		kcommand_free(kcommand);
+		return NULL;
+	}
+
+	return kcommand;
+}
 
 
 char *icommand_to_text(const icommand_t *icommand, int level)

+ 109 - 0
klish/ischeme/iparam.c

@@ -4,8 +4,117 @@
 #include <assert.h>
 
 #include <faux/str.h>
+#include <faux/list.h>
 #include <klish/khelper.h>
 #include <klish/iparam.h>
+#include <klish/kptype.h>
+#include <klish/kparam.h>
+
+#define TAG "PARAM"
+
+bool_t kparam_parse(kparam_t *param, const iparam_t *info, faux_error_t *error)
+{
+	bool_t retcode = BOOL_TRUE;
+
+	// Help
+	if (!faux_str_is_empty(info->help)) {
+		if (!kparam_set_help(param, info->help)) {
+			faux_error_add(error, TAG": Illegal 'help' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// PTYPE reference
+	if (!faux_str_is_empty(info->ptype)) {
+		if (!kparam_set_ptype_ref(param, info->ptype)) {
+			faux_error_add(error, TAG": Illegal 'ptype' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	return retcode;
+}
+
+
+bool_t kparam_nested_from_iparam(kparam_t *kparam, iparam_t *iparam,
+	faux_error_t *error)
+{
+	bool_t retval = BOOL_TRUE;
+
+	if (!kparam || !iparam) {
+		faux_error_add(error, TAG": Internal error");
+		return BOOL_FALSE;
+	}
+
+	// Nested PARAM list
+	if (iparam->params) {
+		iparam_t **p_iparam = NULL;
+		for (p_iparam = *iparam->params; *p_iparam; p_iparam++) {
+			kparam_t *nkparam = NULL;
+			iparam_t *niparam = *p_iparam;
+
+			nkparam = kparam_from_iparam(niparam, error);
+			if (!nkparam) {
+				retval = BOOL_FALSE;
+				continue;
+			}
+			if (!kparam_add_param(kparam, nkparam)) {
+				// Search for PARAM duplicates
+				if (kparam_find_param(kparam,
+					kparam_name(nkparam))) {
+					faux_error_sprintf(error,
+						TAG": Can't add duplicate PARAM "
+						"\"%s\"", kparam_name(nkparam));
+				} else {
+					faux_error_sprintf(error,
+						TAG": Can't add PARAM \"%s\"",
+						kparam_name(nkparam));
+				}
+				kparam_free(nkparam);
+				retval = BOOL_FALSE;
+				continue;
+			}
+		}
+	}
+
+	if (!retval)
+		faux_error_sprintf(error, TAG" \"%s\": Illegal nested elements",
+			kparam_name(kparam));
+
+	return retval;
+}
+
+
+kparam_t *kparam_from_iparam(iparam_t *iparam, faux_error_t *error)
+{
+	kparam_t *kparam = NULL;
+
+	// Name [mandatory]
+	if (faux_str_is_empty(iparam->name)) {
+		faux_error_add(error, TAG": Empty 'name' attribute");
+		return NULL;
+	}
+
+	kparam = kparam_new(iparam->name);
+	if (!kparam) {
+		faux_error_sprintf(error, TAG" \"%s\": Can't create object",
+			iparam->name);
+		return NULL;
+	}
+
+	if (!kparam_parse(kparam, iparam, error)) {
+		kparam_free(kparam);
+		return NULL;
+	}
+
+	// Parse nested elements
+	if (!kparam_nested_from_iparam(kparam, iparam, error)) {
+		kparam_free(kparam);
+		return NULL;
+	}
+
+	return kparam;
+}
 
 
 char *iparam_to_text(const iparam_t *iparam, int level)

+ 93 - 6
klish/ischeme/iplugin.c

@@ -1,27 +1,114 @@
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <string.h>
 #include <assert.h>
+#include <dlfcn.h>
 
 #include <faux/str.h>
+#include <faux/list.h>
+#include <faux/conv.h>
+#include <faux/error.h>
 #include <klish/khelper.h>
+#include <klish/kplugin.h>
+#include <klish/ksym.h>
 #include <klish/iplugin.h>
 
+#define TAG "PLUGIN"
 
-char *iplugin_to_text(const iplugin_t *iplugin, int level)
+
+bool_t iplugin_parse(const iplugin_t *info, kplugin_t *plugin,
+	faux_error_t *error)
+{
+	bool_t retcode = BOOL_TRUE;
+
+	if (!info)
+		return BOOL_FALSE;
+	if (!plugin)
+		return BOOL_FALSE;
+
+	// ID
+	if (!faux_str_is_empty(info->id)) {
+		if (!kplugin_set_id(plugin, info->id)) {
+			faux_error_add(error, TAG": Illegal 'id' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// File
+	if (!faux_str_is_empty(info->file)) {
+		if (!kplugin_set_file(plugin, info->file)) {
+			faux_error_add(error, TAG": Illegal 'file' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// Global
+	if (!faux_str_is_empty(info->global)) {
+		bool_t b = BOOL_FALSE;
+		if (!faux_conv_str2bool(info->global, &b) ||
+			!kplugin_set_global(plugin, b)) {
+			faux_error_add(error, TAG": Illegal 'global' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	// Conf
+	if (!faux_str_is_empty(info->conf)) {
+		if (!kplugin_set_conf(plugin, info->conf)) {
+			faux_error_add(error, TAG": Illegal 'conf' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
+	return retcode;
+}
+
+
+kplugin_t *iplugin_load(iplugin_t *iplugin, faux_error_t *error)
+{
+	kplugin_t *kplugin = NULL;
+
+	if (!iplugin)
+		return NULL;
+
+	// Name [mandatory]
+	if (faux_str_is_empty(iplugin->name))
+		return NULL;
+
+	kplugin = kplugin_new(iplugin->name);
+	if (!kplugin) {
+		faux_error_sprintf(error, TAG" \"%s\": Can't create object",
+			iplugin->name);
+		return NULL;
+	}
+
+	if (!iplugin_parse(iplugin, kplugin, error)) {
+		kplugin_free(kplugin);
+		return NULL;
+	}
+
+	return kplugin;
+}
+
+
+char *iplugin_deploy(const kplugin_t *kplugin, int level)
 {
 	char *str = NULL;
 	char *tmp = NULL;
 
+	if (!kplugin)
+		return NULL;
+
 	tmp = faux_str_sprintf("%*cPLUGIN {\n", level, ' ');
 	faux_str_cat(&str, tmp);
 	faux_str_free(tmp);
 
-	attr2ctext(&str, "name", iplugin->name, level + 1);
-	attr2ctext(&str, "id", iplugin->id, level + 1);
-	attr2ctext(&str, "file", iplugin->file, level + 1);
-	attr2ctext(&str, "global", iplugin->global, level + 1);
-	attr2ctext(&str, "conf", iplugin->conf, level + 1);
+	attr2ctext(&str, "name", kplugin_name(kplugin), level + 1);
+	attr2ctext(&str, "id", kplugin_id(kplugin), level + 1);
+	attr2ctext(&str, "file", kplugin_file(kplugin), level + 1);
+	attr2ctext(&str, "global", faux_conv_bool2str(kplugin_global(kplugin)), level + 1);
+	attr2ctext(&str, "conf", kplugin_conf(kplugin), level + 1);
 
 	tmp = faux_str_sprintf("%*c},\n\n", level, ' ');
 	faux_str_cat(&str, tmp);

+ 217 - 0
klish/ischeme/iptype.c

@@ -1,3 +1,220 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <faux/str.h>
+#include <faux/list.h>
+#include <faux/error.h>
+#include <klish/khelper.h>
+#include <klish/kptype.h>
+#include <klish/kaction.h>
+
+
+struct kptype_s {
+	char *name;
+	char *help;
+	faux_list_t *actions;
+};
+
+
+// Simple methods
+
+// Name
+KGET_STR(ptype, name);
+KSET_STR_ONCE(ptype, name);
+
+// Help
+KGET_STR(ptype, help);
+KSET_STR(ptype, help);
+
+// ACTION list
+KADD_NESTED(ptype, action);
+
+
+static kptype_t *kptype_new_empty(void)
+{
+	kptype_t *ptype = NULL;
+
+	ptype = faux_zmalloc(sizeof(*ptype));
+	assert(ptype);
+	if (!ptype)
+		return NULL;
+
+	// Initialize
+	ptype->name = NULL;
+	ptype->help = NULL;
+
+	// ACTION list
+	ptype->actions = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
+		NULL, NULL, (void (*)(void *))kaction_free);
+	assert(ptype->actions);
+
+	return ptype;
+}
+
+
+kptype_t *kptype_new(const iptype_t *info, kptype_error_e *error)
+{
+	kptype_t *ptype = NULL;
+
+	ptype = kptype_new_empty();
+	assert(ptype);
+	if (!ptype) {
+		if (error)
+			*error = KPTYPE_ERROR_ALLOC;
+		return NULL;
+	}
+
+	if (!info)
+		return ptype;
+
+	if (!kptype_parse(ptype, info, error)) {
+		kptype_free(ptype);
+		return NULL;
+	}
+
+	return ptype;
+}
+
+
+void kptype_free(kptype_t *ptype)
+{
+	if (!ptype)
+		return;
+
+	faux_str_free(ptype->name);
+	faux_str_free(ptype->help);
+	faux_list_free(ptype->actions);
+
+	faux_free(ptype);
+}
+
+
+const char *kptype_strerror(kptype_error_e error)
+{
+	const char *str = NULL;
+
+	switch (error) {
+	case KPTYPE_ERROR_OK:
+		str = "Ok";
+		break;
+	case KPTYPE_ERROR_INTERNAL:
+		str = "Internal error";
+		break;
+	case KPTYPE_ERROR_ALLOC:
+		str = "Memory allocation error";
+		break;
+	case KPTYPE_ERROR_ATTR_NAME:
+		str = "Illegal 'name' attribute";
+		break;
+	case KPTYPE_ERROR_ATTR_HELP:
+		str = "Illegal 'help' attribute";
+		break;
+	default:
+		str = "Unknown error";
+		break;
+	}
+
+	return str;
+}
+
+
+bool_t kptype_parse(kptype_t *ptype, const iptype_t *info, kptype_error_e *error)
+{
+	// Name [mandatory]
+	if (faux_str_is_empty(info->name)) {
+		if (error)
+			*error = KPTYPE_ERROR_ATTR_NAME;
+		return BOOL_FALSE;
+	} else {
+		if (!kptype_set_name(ptype, info->name)) {
+			if (error)
+				*error = KPTYPE_ERROR_ATTR_NAME;
+			return BOOL_FALSE;
+		}
+	}
+
+	// Help
+	if (!faux_str_is_empty(info->name)) {
+		if (!kptype_set_help(ptype, info->help)) {
+			if (error)
+				*error = KPTYPE_ERROR_ATTR_HELP;
+			return BOOL_FALSE;
+		}
+	}
+
+	return BOOL_TRUE;
+}
+
+
+bool_t kptype_nested_from_iptype(kptype_t *kptype, iptype_t *iptype,
+	faux_error_t *error_stack)
+{
+	bool_t retval = BOOL_TRUE;
+
+	if (!kptype || !iptype) {
+		faux_error_add(error_stack,
+			kptype_strerror(KPTYPE_ERROR_INTERNAL));
+		return BOOL_FALSE;
+	}
+
+	// ACTION list
+	if (iptype->actions) {
+		iaction_t **p_iaction = NULL;
+		for (p_iaction = *iptype->actions; *p_iaction; p_iaction++) {
+			kaction_t *kaction = NULL;
+			iaction_t *iaction = *p_iaction;
+
+			kaction = kaction_from_iaction(iaction, error_stack);
+			if (!kaction) {
+				retval = BOOL_FALSE;
+				continue;
+			}
+			if (!kptype_add_action(kptype, kaction)) {
+				faux_error_sprintf(error_stack, "PTYPE: "
+					"Can't add ACTION #%d",
+					faux_list_len(kptype->actions) + 1);
+				kaction_free(kaction);
+				retval = BOOL_FALSE;
+				continue;
+			}
+		}
+	}
+
+	if (!retval)
+		faux_error_sprintf(error_stack,
+			"PTYPE \"%s\": Illegal nested elements",
+			kptype_name(kptype));
+
+	return retval;
+}
+
+
+kptype_t *kptype_from_iptype(iptype_t *iptype, faux_error_t *error_stack)
+{
+	kptype_t *kptype = NULL;
+	kptype_error_e kptype_error = KPTYPE_ERROR_OK;
+
+	kptype = kptype_new(iptype, &kptype_error);
+	if (!kptype) {
+		faux_error_sprintf(error_stack, "PTYPE \"%s\": %s",
+			iptype->name ? iptype->name : "(null)",
+			kptype_strerror(kptype_error));
+		return NULL;
+	}
+
+	// Parse nested elements
+	if (!kptype_nested_from_iptype(kptype, iptype, error_stack)) {
+		kptype_free(kptype);
+		return NULL;
+	}
+
+	return kptype;
+}
+
+
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>

+ 151 - 0
klish/ischeme/ischeme.c

@@ -4,8 +4,159 @@
 #include <assert.h>
 
 #include <faux/str.h>
+#include <faux/list.h>
 #include <klish/khelper.h>
 #include <klish/ischeme.h>
+#include <klish/kplugin.h>
+#include <klish/kptype.h>
+#include <klish/kview.h>
+#include <klish/kscheme.h>
+
+#define TAG "SCHEME"
+
+
+bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
+	faux_error_t *error)
+{
+	bool_t retval = BOOL_TRUE;
+
+	if (!kscheme || !ischeme) {
+		faux_error_add(error, TAG": Internal error");
+		return BOOL_FALSE;
+	}
+
+	// PLUGIN list
+	if (ischeme->plugins) {
+		iplugin_t **p_iplugin = NULL;
+		for (p_iplugin = *ischeme->plugins; *p_iplugin; p_iplugin++) {
+			kplugin_t *kplugin = NULL;
+			iplugin_t *iplugin = *p_iplugin;
+
+			kplugin = kplugin_from_iplugin(iplugin, error);
+			if (!kplugin) {
+				retval = BOOL_FALSE; // Don't stop
+				continue;
+			}
+			if (!kscheme_add_plugin(kscheme, kplugin)) {
+				// Search for PLUGIN duplicates
+				if (kscheme_find_plugin(kscheme,
+					kplugin_name(kplugin))) {
+					faux_error_sprintf(error,
+						TAG": Can't add duplicate PLUGIN "
+						"\"%s\"", kplugin_name(kplugin));
+				} else {
+					faux_error_sprintf(error,
+						TAG": Can't add PLUGIN \"%s\"",
+						kplugin_name(kplugin));
+				}
+				kplugin_free(kplugin);
+				retval = BOOL_FALSE;
+			}
+		}
+	}
+
+	// PTYPE list
+	if (ischeme->ptypes) {
+		iptype_t **p_iptype = NULL;
+		for (p_iptype = *ischeme->ptypes; *p_iptype; p_iptype++) {
+			kptype_t *kptype = NULL;
+			iptype_t *iptype = *p_iptype;
+
+			kptype = kptype_from_iptype(iptype, error);
+			if (!kptype) {
+				retval = BOOL_FALSE; // Don't stop
+				continue;
+			}
+			if (!kscheme_add_ptype(kscheme, kptype)) {
+				// Search for PTYPE duplicates
+				if (kscheme_find_ptype(kscheme,
+					kptype_name(kptype))) {
+					faux_error_sprintf(error,
+						TAG": Can't add duplicate PTYPE "
+						"\"%s\"", kptype_name(kptype));
+				} else {
+					faux_error_sprintf(error,
+						TAG": Can't add PTYPE \"%s\"",
+						kptype_name(kptype));
+				}
+				kptype_free(kptype);
+				retval = BOOL_FALSE;
+			}
+		}
+	}
+
+	// VIEW list
+	// VIEW entries can be duplicate. Duplicated entries will add nested
+	// elements to existent VIEW. Also it can overwrite VIEW attributes.
+	// So there is no special rule which attribute value will be "on top".
+	// It's a random. Technically later VIEW entries will rewrite previous
+	// values.
+	if (ischeme->views) {
+		iview_t **p_iview = NULL;
+		for (p_iview = *ischeme->views; *p_iview; p_iview++) {
+			kview_t *kview = NULL;
+			iview_t *iview = *p_iview;
+			const char *view_name = iview->name;
+
+			if (view_name)
+				kview = kscheme_find_view(kscheme, view_name);
+
+			// VIEW already exists
+			if (kview) {
+				if (!kview_parse(kview, iview, error)) {
+					retval = BOOL_FALSE;
+					continue;
+				}
+				if (!kview_nested_from_iview(kview, iview,
+					error)) {
+					retval = BOOL_FALSE;
+					continue;
+				}
+				continue;
+			}
+
+			// New VIEW
+			kview = kview_from_iview(iview, error);
+			if (!kview) {
+				retval = BOOL_FALSE;
+				continue;
+			}
+			if (!kscheme_add_view(kscheme, kview)) {
+				faux_error_sprintf(error,
+					TAG": Can't add VIEW \"%s\"",
+					kview_name(kview));
+				kview_free(kview);
+				retval = BOOL_FALSE;
+				continue;
+			}
+		}
+	}
+
+	if (!retval)
+		faux_error_sprintf(error, TAG": Illegal nested elements");
+
+	return retval;
+}
+
+
+kscheme_t *kscheme_from_ischeme(ischeme_t *ischeme, faux_error_t *error)
+{
+	kscheme_t *kscheme = NULL;
+
+	kscheme = kscheme_new();
+	if (!kscheme) {
+		faux_error_sprintf(error, TAG": Can't create object");
+		return NULL;
+	}
+
+	// Parse nested elements
+	if (!kscheme_nested_from_ischeme(kscheme, ischeme, error)) {
+		kscheme_free(kscheme);
+		return NULL;
+	}
+
+	return kscheme;
+}
 
 
 char *ischeme_to_text(const ischeme_t *ischeme, int level)

+ 98 - 1
klish/ischeme/iview.c

@@ -4,8 +4,105 @@
 #include <assert.h>
 
 #include <faux/str.h>
+#include <faux/list.h>
+#include <faux/error.h>
 #include <klish/khelper.h>
-#include <klish/iview.h>
+#include <klish/kcommand.h>
+#include <klish/kview.h>
+
+#define TAG "VIEW"
+
+
+bool_t kview_parse(kview_t *view, const iview_t *info, faux_error_t *error)
+{
+	bool_t retcode = BOOL_TRUE;
+
+	view = view;
+	info = info;
+	error = error;
+
+	return retcode;
+}
+
+
+bool_t kview_nested_from_iview(kview_t *kview, iview_t *iview,
+	faux_error_t *error)
+{
+	bool_t retval = BOOL_TRUE;
+
+	if (!kview || !iview) {
+		faux_error_add(error, TAG": Internal error");
+		return BOOL_FALSE;
+	}
+
+	// COMMAND list
+	if (iview->commands) {
+		icommand_t **p_icommand = NULL;
+		for (p_icommand = *iview->commands; *p_icommand; p_icommand++) {
+			kcommand_t *kcommand = NULL;
+			icommand_t *icommand = *p_icommand;
+			kcommand = kcommand_from_icommand(icommand, error);
+			if (!kcommand) {
+				retval = BOOL_FALSE;
+				continue;
+			}
+			if (!kview_add_command(kview, kcommand)) {
+				// Search for COMMAND duplicates
+				if (kview_find_command(kview,
+					kcommand_name(kcommand))) {
+					faux_error_sprintf(error,
+						TAG": Can't add duplicate COMMAND "
+						"\"%s\"", kcommand_name(kcommand));
+				} else {
+					faux_error_sprintf(error,
+						TAG": Can't add COMMAND \"%s\"",
+						kcommand_name(kcommand));
+				}
+				kcommand_free(kcommand);
+				retval = BOOL_FALSE;
+				continue;
+			}
+		}
+	}
+
+	if (!retval)
+		faux_error_sprintf(error, TAG" \"%s\": Illegal nested elements",
+			kview_name(kview));
+
+	return retval;
+}
+
+
+kview_t *kview_from_iview(iview_t *iview, faux_error_t *error)
+{
+	kview_t *kview = NULL;
+
+	// Name [mandatory]
+	if (faux_str_is_empty(iview->name)) {
+		faux_error_add(error, TAG": Empty 'name' attribute");
+		return NULL;
+	}
+
+	kview = kview_new(iview->name);
+	if (!kview) {
+		faux_error_sprintf(error, TAG": \"%s\": Can't create object",
+			iview->name);
+		return NULL;
+	}
+
+	if (!kview_parse(kview, iview, error)) {
+		kview_free(kview);
+		return NULL;
+	}
+
+	// Parse nested elements
+	if (!kview_nested_from_iview(kview, iview, error)) {
+		kview_free(kview);
+		return NULL;
+	}
+
+	return kview;
+}
 
 
 char *iview_to_text(const iview_t *iview, int level)

+ 0 - 4
klish/kaction.h

@@ -7,7 +7,6 @@
 #define _klish_kaction_h
 
 #include <faux/error.h>
-#include <klish/iaction.h>
 
 
 typedef struct kaction_s kaction_t;
@@ -40,9 +39,6 @@ bool_t kaction_set_update_retcode(kaction_t *action, bool_t update_retcode);
 const char *kaction_script(const kaction_t *action);
 bool_t kaction_set_script(kaction_t *action, const char *script);
 
-bool_t kaction_parse(kaction_t *action, const iaction_t *info, faux_error_t *error);
-kaction_t *kaction_from_iaction(iaction_t *iaction, faux_error_t *error);
-
 C_DECL_END
 
 #endif // _klish_kaction_h

+ 0 - 7
klish/kcommand.h

@@ -6,7 +6,6 @@
 #ifndef _klish_kcommand_h
 #define _klish_kcommand_h
 
-#include <klish/icommand.h>
 #include <klish/kparam.h>
 #include <klish/kaction.h>
 
@@ -29,12 +28,6 @@ ssize_t kcommand_params_len(const kcommand_t *command);
 bool_t kcommand_add_action(kcommand_t *command, kaction_t *action);
 ssize_t kcommand_actions_len(const kcommand_t *command);
 
-bool_t kcommand_parse(kcommand_t *command, const icommand_t *info,
-	faux_error_t *error);
-bool_t kcommand_nested_from_icommand(kcommand_t *kcommand, icommand_t *icommand,
-	faux_error_t *error);
-kcommand_t *kcommand_from_icommand(icommand_t *icommand, faux_error_t *error);
-
 C_DECL_END
 
 #endif // _klish_kcommand_h

+ 54 - 0
klish/kdb/Makefile.am

@@ -0,0 +1,54 @@
+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
+
+#if TESTC
+#include $(top_srcdir)/klish/testc_module/Makefile.am
+#endif

+ 0 - 6
klish/kparam.h

@@ -7,7 +7,6 @@
 #define _klish_kparam_h
 
 #include <faux/error.h>
-#include <klish/iparam.h>
 
 
 typedef struct kparam_s kparam_t;
@@ -27,11 +26,6 @@ bool_t kparam_set_ptype_ref(kparam_t *param, const char *ptype_ref);
 bool_t kparam_add_param(kparam_t *param, kparam_t *nested_param);
 kparam_t *kparam_find_param(const kparam_t *param, const char *name);
 
-bool_t kparam_parse(kparam_t *param, const iparam_t *info, faux_error_t *error);
-bool_t kparam_nested_from_iparam(kparam_t *kparam, iparam_t *iparam,
-	faux_error_t *error);
-kparam_t *kparam_from_iparam(iparam_t *iparam, faux_error_t *error);
-
 C_DECL_END
 
 #endif // _klish_kparam_h

+ 0 - 4
klish/kplugin.h

@@ -9,7 +9,6 @@
 #include <stdint.h>
 #include <faux/error.h>
 
-#include <klish/iplugin.h>
 #include <klish/ksym.h>
 
 // Current API version
@@ -59,9 +58,6 @@ bool_t kplugin_add_sym(kplugin_t *plugin, ksym_t *sym);
 ksym_t *kplugin_find_sym(const kplugin_t *plugin, const char *name);
 ssize_t kplugin_syms_len(const kplugin_t *plugin);
 
-bool_t kplugin_parse(kplugin_t *plugin, const iplugin_t *info, faux_error_t *error);
-kplugin_t *kplugin_from_iplugin(iplugin_t *iplugin, faux_error_t *error);
-
 C_DECL_END
 
 #endif // _klish_kplugin_h

+ 1 - 17
klish/kptype.h

@@ -7,36 +7,20 @@
 #define _klish_kptype_h
 
 #include <faux/error.h>
-#include <klish/iptype.h>
 #include <klish/kaction.h>
 
 typedef struct kptype_s kptype_t;
 
-typedef enum {
-	KPTYPE_ERROR_OK,
-	KPTYPE_ERROR_INTERNAL,
-	KPTYPE_ERROR_ALLOC,
-	KPTYPE_ERROR_ATTR_NAME,
-	KPTYPE_ERROR_ATTR_HELP,
-} kptype_error_e;
-
 
 C_DECL_BEGIN
 
+kptype_t *kptype_new(const char *name);
 void kptype_free(kptype_t *ptype);
-bool_t kptype_parse(kptype_t *ptype, const iptype_t *info, kptype_error_e *error);
-kptype_t *kptype_new(const iptype_t *info, kptype_error_e *error);
-const char *kptype_strerror(kptype_error_e error);
 
 const char *kptype_name(const kptype_t *ptype);
-bool_t kptype_set_name(kptype_t *ptype, const char *name);
 const char *kptype_help(const kptype_t *ptype);
 bool_t kptype_set_help(kptype_t *ptype, const char *help);
 
-bool_t kptype_nested_from_iptype(kptype_t *kptype, iptype_t *iptype,
-	faux_error_t *error_stack);
-kptype_t *kptype_from_iptype(iptype_t *iptype, faux_error_t *error_stack);
-
 C_DECL_END
 
 #endif // _klish_kptype_h

+ 0 - 5
klish/kscheme.h

@@ -8,7 +8,6 @@
 
 #include <faux/error.h>
 
-#include <klish/ischeme.h>
 #include <klish/kplugin.h>
 #include <klish/kptype.h>
 #include <klish/kview.h>
@@ -29,10 +28,6 @@ kptype_t *kscheme_find_ptype(const kscheme_t *scheme, const char *name);
 bool_t kscheme_add_plugin(kscheme_t *scheme, kplugin_t *plugin);
 kplugin_t *kscheme_find_plugin(const kscheme_t *scheme, const char *name);
 
-bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
-	faux_error_t *error);
-kscheme_t *kscheme_from_ischeme(ischeme_t *ischeme, faux_error_t *error);
-
 C_DECL_END
 
 #endif // _klish_kscheme_h

+ 1 - 7
klish/kscheme/Makefile.am

@@ -2,15 +2,9 @@ libklish_la_SOURCES += \
 	klish/kscheme/khelper.c \
 	klish/kscheme/ksym.c \
 	klish/kscheme/kplugin.c \
-	klish/kscheme/kplugin_parse.c \
 	klish/kscheme/kptype.c \
 	klish/kscheme/kaction.c \
-	klish/kscheme/kaction_parse.c \
 	klish/kscheme/kparam.c \
-	klish/kscheme/kparam_parse.c \
 	klish/kscheme/kcommand.c \
-	klish/kscheme/kcommand_parse.c \
 	klish/kscheme/kview.c \
-	klish/kscheme/kview_parse.c \
-	klish/kscheme/kscheme.c \
-	klish/kscheme/kscheme_parse.c
+	klish/kscheme/kscheme.c

+ 0 - 107
klish/kscheme/kaction_parse.c

@@ -1,107 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <faux/str.h>
-#include <faux/conv.h>
-#include <faux/list.h>
-#include <faux/error.h>
-#include <klish/khelper.h>
-#include <klish/kaction.h>
-
-#define TAG "ACTION"
-
-bool_t kaction_parse(kaction_t *action, const iaction_t *info, faux_error_t *error)
-{
-	bool_t retcode = BOOL_TRUE;
-
-	// Sym
-	if (!faux_str_is_empty(info->sym)) {
-		if (!kaction_set_sym_ref(action, info->sym)) {
-			faux_error_add(error, TAG": Illegal 'sym' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// Lock
-	if (!faux_str_is_empty(info->lock)) {
-		if (!kaction_set_lock(action, info->lock)) {
-			faux_error_add(error, TAG": Illegal 'lock' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// Interrupt
-	if (!faux_str_is_empty(info->interrupt)) {
-		bool_t b = BOOL_FALSE;
-		if (!faux_conv_str2bool(info->interrupt, &b) ||
-			!kaction_set_interrupt(action, b)) {
-			faux_error_add(error, TAG": Illegal 'interrupt' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// Interactive
-	if (!faux_str_is_empty(info->interactive)) {
-		bool_t b = BOOL_FALSE;
-		if (!faux_conv_str2bool(info->interactive, &b) ||
-			!kaction_set_interactive(action, b)) {
-			faux_error_add(error, TAG": Illegal 'interactive' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// Exec_on
-	if (!faux_str_is_empty(info->exec_on)) {
-		kaction_cond_e c = KACTION_COND_NONE;
-		if (faux_str_casecmp(info->exec_on, "fail"))
-			c = KACTION_COND_FAIL;
-		else if (faux_str_casecmp(info->exec_on, "success"))
-			c = KACTION_COND_SUCCESS;
-		else if (faux_str_casecmp(info->exec_on, "always"))
-			c = KACTION_COND_ALWAYS;
-		if ((KACTION_COND_NONE == c) || !kaction_set_exec_on(action, c)) {
-			faux_error_add(error, TAG": Illegal 'exec_on' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// Update_retcode
-	if (!faux_str_is_empty(info->update_retcode)) {
-		bool_t b = BOOL_FALSE;
-		if (!faux_conv_str2bool(info->update_retcode, &b) ||
-			!kaction_set_update_retcode(action, b)) {
-			faux_error_add(error, TAG": Illegal 'update_retcode' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// Script
-	if (!faux_str_is_empty(info->script)) {
-		if (!kaction_set_script(action, info->script)) {
-			faux_error_add(error, TAG": Illegal 'script' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	return retcode;
-}
-
-
-kaction_t *kaction_from_iaction(iaction_t *iaction, faux_error_t *error)
-{
-	kaction_t *kaction = NULL;
-
-	kaction = kaction_new();
-	if (!kaction) {
-		faux_error_add(error, TAG": Can't create object");
-		return NULL;
-	}
-	if (!kaction_parse(kaction, iaction, error)) {
-		kaction_free(kaction);
-		return NULL;
-	}
-
-	return kaction;
-}

+ 0 - 136
klish/kscheme/kcommand_parse.c

@@ -1,136 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <faux/str.h>
-#include <faux/list.h>
-#include <faux/error.h>
-#include <klish/khelper.h>
-#include <klish/icommand.h>
-#include <klish/kparam.h>
-#include <klish/kaction.h>
-#include <klish/kcommand.h>
-
-#define TAG "COMMAND"
-
-bool_t kcommand_parse(kcommand_t *command, const icommand_t *info,
-	faux_error_t *error)
-{
-	bool_t retcode = BOOL_TRUE;
-
-	// Help
-	if (!faux_str_is_empty(info->help)) {
-		if (!kcommand_set_help(command, info->help)) {
-			faux_error_add(error, TAG": Illegal 'help' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	return retcode;
-}
-
-
-bool_t kcommand_nested_from_icommand(kcommand_t *kcommand, icommand_t *icommand,
-	faux_error_t *error)
-{
-	bool_t retval = BOOL_TRUE;
-
-	if (!kcommand || !icommand) {
-		faux_error_add(error, TAG": Internal error");
-		return BOOL_FALSE;
-	}
-
-
-	// PARAM list
-	if (icommand->params) {
-		iparam_t **p_iparam = NULL;
-		for (p_iparam = *icommand->params; *p_iparam; p_iparam++) {
-			kparam_t *kparam = NULL;
-			iparam_t *iparam = *p_iparam;
-
-			kparam = kparam_from_iparam(iparam, error);
-			if (!kparam) {
-				retval = BOOL_FALSE;
-				continue;
-			}
-			if (!kcommand_add_param(kcommand, kparam)) {
-				// Search for PARAM duplicates
-				if (kcommand_find_param(kcommand,
-					kparam_name(kparam))) {
-					faux_error_sprintf(error,
-						TAG": Can't add duplicate PARAM "
-						"\"%s\"", kparam_name(kparam));
-				} else {
-					faux_error_sprintf(error,
-						TAG": Can't add PARAM \"%s\"",
-						kparam_name(kparam));
-				}
-				kparam_free(kparam);
-				retval = BOOL_FALSE;
-				continue;
-			}
-		}
-	}
-
-	// ACTION list
-	if (icommand->actions) {
-		iaction_t **p_iaction = NULL;
-		for (p_iaction = *icommand->actions; *p_iaction; p_iaction++) {
-			kaction_t *kaction = NULL;
-			iaction_t *iaction = *p_iaction;
-
-			kaction = kaction_from_iaction(iaction, error);
-			if (!kaction) {
-				retval = BOOL_FALSE;
-				continue;
-			}
-			if (!kcommand_add_action(kcommand, kaction)) {
-				faux_error_sprintf(error,
-					TAG": Can't add ACTION #%d",
-					kcommand_actions_len(kcommand) + 1);
-				kaction_free(kaction);
-				retval = BOOL_FALSE;
-				continue;
-			}
-		}
-	}
-
-	if (!retval)
-		faux_error_sprintf(error, TAG" \"%s\": Illegal nested elements",
-			kcommand_name(kcommand));
-
-	return retval;
-}
-
-
-kcommand_t *kcommand_from_icommand(icommand_t *icommand, faux_error_t *error)
-{
-	kcommand_t *kcommand = NULL;
-
-	// Name [mandatory]
-	if (faux_str_is_empty(icommand->name)) {
-		faux_error_add(error, TAG": Empty 'name' attribute");
-		return NULL;
-	}
-
-	kcommand = kcommand_new(icommand->name);
-	if (!kcommand) {
-		faux_error_sprintf(error, TAG" \"%s\": Can't create object",
-			icommand->name);
-		return NULL;
-	}
-
-	if (!kcommand_parse(kcommand, icommand, error)) {
-		kcommand_free(kcommand);
-		return NULL;
-	}
-
-	// Parse nested elements
-	if (!kcommand_nested_from_icommand(kcommand, icommand, error)) {
-		kcommand_free(kcommand);
-		return NULL;
-	}
-
-	return kcommand;
-}

+ 0 - 117
klish/kscheme/kparam_parse.c

@@ -1,117 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <faux/str.h>
-#include <faux/list.h>
-#include <klish/khelper.h>
-#include <klish/iparam.h>
-#include <klish/kptype.h>
-#include <klish/kparam.h>
-
-#define TAG "PARAM"
-
-bool_t kparam_parse(kparam_t *param, const iparam_t *info, faux_error_t *error)
-{
-	bool_t retcode = BOOL_TRUE;
-
-	// Help
-	if (!faux_str_is_empty(info->help)) {
-		if (!kparam_set_help(param, info->help)) {
-			faux_error_add(error, TAG": Illegal 'help' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// PTYPE reference
-	if (!faux_str_is_empty(info->ptype)) {
-		if (!kparam_set_ptype_ref(param, info->ptype)) {
-			faux_error_add(error, TAG": Illegal 'ptype' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	return retcode;
-}
-
-
-bool_t kparam_nested_from_iparam(kparam_t *kparam, iparam_t *iparam,
-	faux_error_t *error)
-{
-	bool_t retval = BOOL_TRUE;
-
-	if (!kparam || !iparam) {
-		faux_error_add(error, TAG": Internal error");
-		return BOOL_FALSE;
-	}
-
-	// Nested PARAM list
-	if (iparam->params) {
-		iparam_t **p_iparam = NULL;
-		for (p_iparam = *iparam->params; *p_iparam; p_iparam++) {
-			kparam_t *nkparam = NULL;
-			iparam_t *niparam = *p_iparam;
-
-			nkparam = kparam_from_iparam(niparam, error);
-			if (!nkparam) {
-				retval = BOOL_FALSE;
-				continue;
-			}
-			if (!kparam_add_param(kparam, nkparam)) {
-				// Search for PARAM duplicates
-				if (kparam_find_param(kparam,
-					kparam_name(nkparam))) {
-					faux_error_sprintf(error,
-						TAG": Can't add duplicate PARAM "
-						"\"%s\"", kparam_name(nkparam));
-				} else {
-					faux_error_sprintf(error,
-						TAG": Can't add PARAM \"%s\"",
-						kparam_name(nkparam));
-				}
-				kparam_free(nkparam);
-				retval = BOOL_FALSE;
-				continue;
-			}
-		}
-	}
-
-	if (!retval)
-		faux_error_sprintf(error, TAG" \"%s\": Illegal nested elements",
-			kparam_name(kparam));
-
-	return retval;
-}
-
-
-kparam_t *kparam_from_iparam(iparam_t *iparam, faux_error_t *error)
-{
-	kparam_t *kparam = NULL;
-
-	// Name [mandatory]
-	if (faux_str_is_empty(iparam->name)) {
-		faux_error_add(error, TAG": Empty 'name' attribute");
-		return NULL;
-	}
-
-	kparam = kparam_new(iparam->name);
-	if (!kparam) {
-		faux_error_sprintf(error, TAG" \"%s\": Can't create object",
-			iparam->name);
-		return NULL;
-	}
-
-	if (!kparam_parse(kparam, iparam, error)) {
-		kparam_free(kparam);
-		return NULL;
-	}
-
-	// Parse nested elements
-	if (!kparam_nested_from_iparam(kparam, iparam, error)) {
-		kparam_free(kparam);
-		return NULL;
-	}
-
-	return kparam;
-}

+ 0 - 83
klish/kscheme/kplugin_parse.c

@@ -1,83 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <assert.h>
-#include <dlfcn.h>
-
-#include <faux/str.h>
-#include <faux/list.h>
-#include <faux/conv.h>
-#include <faux/error.h>
-#include <klish/khelper.h>
-#include <klish/iplugin.h>
-#include <klish/kplugin.h>
-#include <klish/ksym.h>
-
-#define TAG "PLUGIN"
-
-
-bool_t kplugin_parse(kplugin_t *plugin, const iplugin_t *info, faux_error_t *error)
-{
-	bool_t retcode = BOOL_TRUE;
-
-	// ID
-	if (!faux_str_is_empty(info->id)) {
-		if (!kplugin_set_id(plugin, info->id)) {
-			faux_error_add(error, TAG": Illegal 'id' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// File
-	if (!faux_str_is_empty(info->file)) {
-		if (!kplugin_set_file(plugin, info->file)) {
-			faux_error_add(error, TAG": Illegal 'file' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// Global
-	if (!faux_str_is_empty(info->global)) {
-		bool_t b = BOOL_FALSE;
-		if (!faux_conv_str2bool(info->global, &b) ||
-			!kplugin_set_global(plugin, b)) {
-			faux_error_add(error, TAG": Illegal 'global' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	// Conf
-	if (!faux_str_is_empty(info->conf)) {
-		if (!kplugin_set_conf(plugin, info->conf)) {
-			faux_error_add(error, TAG": Illegal 'conf' attribute");
-			retcode = BOOL_FALSE;
-		}
-	}
-
-	return retcode;
-}
-
-
-kplugin_t *kplugin_from_iplugin(iplugin_t *iplugin, faux_error_t *error)
-{
-	kplugin_t *kplugin = NULL;
-
-	// Name [mandatory]
-	if (faux_str_is_empty(iplugin->name))
-		return NULL;
-
-	kplugin = kplugin_new(iplugin->name);
-	if (!kplugin) {
-		faux_error_sprintf(error, TAG" \"%s\": Can't create object",
-			iplugin->name);
-		return NULL;
-	}
-
-	if (!kplugin_parse(kplugin, iplugin, error)) {
-		kplugin_free(kplugin);
-		return NULL;
-	}
-
-	return kplugin;
-}

+ 5 - 150
klish/kscheme/kptype.c

@@ -22,7 +22,6 @@ struct kptype_s {
 
 // Name
 KGET_STR(ptype, name);
-KSET_STR_ONCE(ptype, name);
 
 // Help
 KGET_STR(ptype, help);
@@ -32,17 +31,20 @@ KSET_STR(ptype, help);
 KADD_NESTED(ptype, action);
 
 
-static kptype_t *kptype_new_empty(void)
+kptype_t *kptype_new(const char *name)
 {
 	kptype_t *ptype = NULL;
 
+	if (faux_str_is_empty(name))
+		return NULL;
+
 	ptype = faux_zmalloc(sizeof(*ptype));
 	assert(ptype);
 	if (!ptype)
 		return NULL;
 
 	// Initialize
-	ptype->name = NULL;
+	ptype->name = faux_str_dup(name);
 	ptype->help = NULL;
 
 	// ACTION list
@@ -54,30 +56,6 @@ static kptype_t *kptype_new_empty(void)
 }
 
 
-kptype_t *kptype_new(const iptype_t *info, kptype_error_e *error)
-{
-	kptype_t *ptype = NULL;
-
-	ptype = kptype_new_empty();
-	assert(ptype);
-	if (!ptype) {
-		if (error)
-			*error = KPTYPE_ERROR_ALLOC;
-		return NULL;
-	}
-
-	if (!info)
-		return ptype;
-
-	if (!kptype_parse(ptype, info, error)) {
-		kptype_free(ptype);
-		return NULL;
-	}
-
-	return ptype;
-}
-
-
 void kptype_free(kptype_t *ptype)
 {
 	if (!ptype)
@@ -89,126 +67,3 @@ void kptype_free(kptype_t *ptype)
 
 	faux_free(ptype);
 }
-
-
-const char *kptype_strerror(kptype_error_e error)
-{
-	const char *str = NULL;
-
-	switch (error) {
-	case KPTYPE_ERROR_OK:
-		str = "Ok";
-		break;
-	case KPTYPE_ERROR_INTERNAL:
-		str = "Internal error";
-		break;
-	case KPTYPE_ERROR_ALLOC:
-		str = "Memory allocation error";
-		break;
-	case KPTYPE_ERROR_ATTR_NAME:
-		str = "Illegal 'name' attribute";
-		break;
-	case KPTYPE_ERROR_ATTR_HELP:
-		str = "Illegal 'help' attribute";
-		break;
-	default:
-		str = "Unknown error";
-		break;
-	}
-
-	return str;
-}
-
-
-bool_t kptype_parse(kptype_t *ptype, const iptype_t *info, kptype_error_e *error)
-{
-	// Name [mandatory]
-	if (faux_str_is_empty(info->name)) {
-		if (error)
-			*error = KPTYPE_ERROR_ATTR_NAME;
-		return BOOL_FALSE;
-	} else {
-		if (!kptype_set_name(ptype, info->name)) {
-			if (error)
-				*error = KPTYPE_ERROR_ATTR_NAME;
-			return BOOL_FALSE;
-		}
-	}
-
-	// Help
-	if (!faux_str_is_empty(info->name)) {
-		if (!kptype_set_help(ptype, info->help)) {
-			if (error)
-				*error = KPTYPE_ERROR_ATTR_HELP;
-			return BOOL_FALSE;
-		}
-	}
-
-	return BOOL_TRUE;
-}
-
-
-bool_t kptype_nested_from_iptype(kptype_t *kptype, iptype_t *iptype,
-	faux_error_t *error_stack)
-{
-	bool_t retval = BOOL_TRUE;
-
-	if (!kptype || !iptype) {
-		faux_error_add(error_stack,
-			kptype_strerror(KPTYPE_ERROR_INTERNAL));
-		return BOOL_FALSE;
-	}
-
-	// ACTION list
-	if (iptype->actions) {
-		iaction_t **p_iaction = NULL;
-		for (p_iaction = *iptype->actions; *p_iaction; p_iaction++) {
-			kaction_t *kaction = NULL;
-			iaction_t *iaction = *p_iaction;
-
-			kaction = kaction_from_iaction(iaction, error_stack);
-			if (!kaction) {
-				retval = BOOL_FALSE;
-				continue;
-			}
-			if (!kptype_add_action(kptype, kaction)) {
-				faux_error_sprintf(error_stack, "PTYPE: "
-					"Can't add ACTION #%d",
-					faux_list_len(kptype->actions) + 1);
-				kaction_free(kaction);
-				retval = BOOL_FALSE;
-				continue;
-			}
-		}
-	}
-
-	if (!retval)
-		faux_error_sprintf(error_stack,
-			"PTYPE \"%s\": Illegal nested elements",
-			kptype_name(kptype));
-
-	return retval;
-}
-
-
-kptype_t *kptype_from_iptype(iptype_t *iptype, faux_error_t *error_stack)
-{
-	kptype_t *kptype = NULL;
-	kptype_error_e kptype_error = KPTYPE_ERROR_OK;
-
-	kptype = kptype_new(iptype, &kptype_error);
-	if (!kptype) {
-		faux_error_sprintf(error_stack, "PTYPE \"%s\": %s",
-			iptype->name ? iptype->name : "(null)",
-			kptype_strerror(kptype_error));
-		return NULL;
-	}
-
-	// Parse nested elements
-	if (!kptype_nested_from_iptype(kptype, iptype, error_stack)) {
-		kptype_free(kptype);
-		return NULL;
-	}
-
-	return kptype;
-}

+ 0 - 159
klish/kscheme/kscheme_parse.c

@@ -1,159 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <faux/str.h>
-#include <faux/list.h>
-#include <klish/khelper.h>
-#include <klish/ischeme.h>
-#include <klish/kplugin.h>
-#include <klish/kptype.h>
-#include <klish/kview.h>
-#include <klish/kscheme.h>
-
-#define TAG "SCHEME"
-
-
-bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
-	faux_error_t *error)
-{
-	bool_t retval = BOOL_TRUE;
-
-	if (!kscheme || !ischeme) {
-		faux_error_add(error, TAG": Internal error");
-		return BOOL_FALSE;
-	}
-
-	// PLUGIN list
-	if (ischeme->plugins) {
-		iplugin_t **p_iplugin = NULL;
-		for (p_iplugin = *ischeme->plugins; *p_iplugin; p_iplugin++) {
-			kplugin_t *kplugin = NULL;
-			iplugin_t *iplugin = *p_iplugin;
-
-			kplugin = kplugin_from_iplugin(iplugin, error);
-			if (!kplugin) {
-				retval = BOOL_FALSE; // Don't stop
-				continue;
-			}
-			if (!kscheme_add_plugin(kscheme, kplugin)) {
-				// Search for PLUGIN duplicates
-				if (kscheme_find_plugin(kscheme,
-					kplugin_name(kplugin))) {
-					faux_error_sprintf(error,
-						TAG": Can't add duplicate PLUGIN "
-						"\"%s\"", kplugin_name(kplugin));
-				} else {
-					faux_error_sprintf(error,
-						TAG": Can't add PLUGIN \"%s\"",
-						kplugin_name(kplugin));
-				}
-				kplugin_free(kplugin);
-				retval = BOOL_FALSE;
-			}
-		}
-	}
-
-	// PTYPE list
-	if (ischeme->ptypes) {
-		iptype_t **p_iptype = NULL;
-		for (p_iptype = *ischeme->ptypes; *p_iptype; p_iptype++) {
-			kptype_t *kptype = NULL;
-			iptype_t *iptype = *p_iptype;
-
-			kptype = kptype_from_iptype(iptype, error);
-			if (!kptype) {
-				retval = BOOL_FALSE; // Don't stop
-				continue;
-			}
-			if (!kscheme_add_ptype(kscheme, kptype)) {
-				// Search for PTYPE duplicates
-				if (kscheme_find_ptype(kscheme,
-					kptype_name(kptype))) {
-					faux_error_sprintf(error,
-						TAG": Can't add duplicate PTYPE "
-						"\"%s\"", kptype_name(kptype));
-				} else {
-					faux_error_sprintf(error,
-						TAG": Can't add PTYPE \"%s\"",
-						kptype_name(kptype));
-				}
-				kptype_free(kptype);
-				retval = BOOL_FALSE;
-			}
-		}
-	}
-
-	// VIEW list
-	// VIEW entries can be duplicate. Duplicated entries will add nested
-	// elements to existent VIEW. Also it can overwrite VIEW attributes.
-	// So there is no special rule which attribute value will be "on top".
-	// It's a random. Technically later VIEW entries will rewrite previous
-	// values.
-	if (ischeme->views) {
-		iview_t **p_iview = NULL;
-		for (p_iview = *ischeme->views; *p_iview; p_iview++) {
-			kview_t *kview = NULL;
-			iview_t *iview = *p_iview;
-			const char *view_name = iview->name;
-
-			if (view_name)
-				kview = kscheme_find_view(kscheme, view_name);
-
-			// VIEW already exists
-			if (kview) {
-				if (!kview_parse(kview, iview, error)) {
-					retval = BOOL_FALSE;
-					continue;
-				}
-				if (!kview_nested_from_iview(kview, iview,
-					error)) {
-					retval = BOOL_FALSE;
-					continue;
-				}
-				continue;
-			}
-
-			// New VIEW
-			kview = kview_from_iview(iview, error);
-			if (!kview) {
-				retval = BOOL_FALSE;
-				continue;
-			}
-			if (!kscheme_add_view(kscheme, kview)) {
-				faux_error_sprintf(error,
-					TAG": Can't add VIEW \"%s\"",
-					kview_name(kview));
-				kview_free(kview);
-				retval = BOOL_FALSE;
-				continue;
-			}
-		}
-	}
-
-	if (!retval)
-		faux_error_sprintf(error, TAG": Illegal nested elements");
-
-	return retval;
-}
-
-
-kscheme_t *kscheme_from_ischeme(ischeme_t *ischeme, faux_error_t *error)
-{
-	kscheme_t *kscheme = NULL;
-
-	kscheme = kscheme_new();
-	if (!kscheme) {
-		faux_error_sprintf(error, TAG": Can't create object");
-		return NULL;
-	}
-
-	// Parse nested elements
-	if (!kscheme_nested_from_ischeme(kscheme, ischeme, error)) {
-		kscheme_free(kscheme);
-		return NULL;
-	}
-
-	return kscheme;
-}

+ 0 - 105
klish/kscheme/kview_parse.c

@@ -1,105 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <faux/str.h>
-#include <faux/list.h>
-#include <faux/error.h>
-#include <klish/khelper.h>
-#include <klish/kcommand.h>
-#include <klish/kview.h>
-
-#define TAG "VIEW"
-
-
-bool_t kview_parse(kview_t *view, const iview_t *info, faux_error_t *error)
-{
-	bool_t retcode = BOOL_TRUE;
-
-	view = view;
-	info = info;
-	error = error;
-
-	return retcode;
-}
-
-
-bool_t kview_nested_from_iview(kview_t *kview, iview_t *iview,
-	faux_error_t *error)
-{
-	bool_t retval = BOOL_TRUE;
-
-	if (!kview || !iview) {
-		faux_error_add(error, TAG": Internal error");
-		return BOOL_FALSE;
-	}
-
-	// COMMAND list
-	if (iview->commands) {
-		icommand_t **p_icommand = NULL;
-		for (p_icommand = *iview->commands; *p_icommand; p_icommand++) {
-			kcommand_t *kcommand = NULL;
-			icommand_t *icommand = *p_icommand;
-			kcommand = kcommand_from_icommand(icommand, error);
-			if (!kcommand) {
-				retval = BOOL_FALSE;
-				continue;
-			}
-			if (!kview_add_command(kview, kcommand)) {
-				// Search for COMMAND duplicates
-				if (kview_find_command(kview,
-					kcommand_name(kcommand))) {
-					faux_error_sprintf(error,
-						TAG": Can't add duplicate COMMAND "
-						"\"%s\"", kcommand_name(kcommand));
-				} else {
-					faux_error_sprintf(error,
-						TAG": Can't add COMMAND \"%s\"",
-						kcommand_name(kcommand));
-				}
-				kcommand_free(kcommand);
-				retval = BOOL_FALSE;
-				continue;
-			}
-		}
-	}
-
-	if (!retval)
-		faux_error_sprintf(error, TAG" \"%s\": Illegal nested elements",
-			kview_name(kview));
-
-	return retval;
-}
-
-
-kview_t *kview_from_iview(iview_t *iview, faux_error_t *error)
-{
-	kview_t *kview = NULL;
-
-	// Name [mandatory]
-	if (faux_str_is_empty(iview->name)) {
-		faux_error_add(error, TAG": Empty 'name' attribute");
-		return NULL;
-	}
-
-	kview = kview_new(iview->name);
-	if (!kview) {
-		faux_error_sprintf(error, TAG": \"%s\": Can't create object",
-			iview->name);
-		return NULL;
-	}
-
-	if (!kview_parse(kview, iview, error)) {
-		kview_free(kview);
-		return NULL;
-	}
-
-	// Parse nested elements
-	if (!kview_nested_from_iview(kview, iview, error)) {
-		kview_free(kview);
-		return NULL;
-	}
-
-	return kview;
-}

+ 0 - 6
klish/kview.h

@@ -8,7 +8,6 @@
 
 #include <faux/faux.h>
 #include <faux/error.h>
-#include <klish/iview.h>
 #include <klish/kcommand.h>
 
 
@@ -25,11 +24,6 @@ const char *kview_name(const kview_t *view);
 bool_t kview_add_command(kview_t *view, kcommand_t *command);
 kcommand_t *kview_find_command(const kview_t *view, const char *name);
 
-bool_t kview_parse(kview_t *view, const iview_t *info, faux_error_t *error);
-bool_t kview_nested_from_iview(kview_t *kview, iview_t *iview,
-	faux_error_t *error);
-kview_t *kview_from_iview(iview_t *iview, faux_error_t *error);
-
 C_DECL_END
 
 #endif // _klish_kview_h