Browse Source

scheme: ischeme refactoring

Serj Kalichev 3 years ago
parent
commit
509cb2b39e

+ 1 - 1
klish/iaction.h

@@ -7,7 +7,7 @@
 #define _klish_iaction_h
 
 #include <faux/error.h>
-
+#include <klish/kaction.h>
 
 typedef struct iaction_s {
 	char *sym;

+ 7 - 1
klish/icommand.h

@@ -8,6 +8,7 @@
 
 #include <klish/iparam.h>
 #include <klish/iaction.h>
+#include <klish/kcommand.h>
 
 typedef struct icommand_s {
 	char *name;
@@ -18,7 +19,12 @@ typedef struct icommand_s {
 
 C_DECL_BEGIN
 
-char *icommand_to_text(const icommand_t *icommand, int level);
+bool_t icommand_parse(const icommand_t *info, kcommand_t *command,
+	faux_error_t *error);
+bool_t icommand_parse_nested(const icommand_t *icommand, kcommand_t *kcommand,
+	faux_error_t *error);
+kcommand_t *icommand_load(icommand_t *icommand, faux_error_t *error);
+char *icommand_deploy(const kcommand_t *kcommand, int level);
 
 C_DECL_END
 

+ 7 - 2
klish/iparam.h

@@ -6,6 +6,8 @@
 #ifndef _klish_iparam_h
 #define _klish_iparam_h
 
+#include <faux/error.h>
+#include <klish/kparam.h>
 
 typedef struct iparam_s iparam_t;
 
@@ -18,8 +20,11 @@ struct iparam_s {
 
 C_DECL_BEGIN
 
-// iparam_t
-char *iparam_to_text(const iparam_t *iparam, int level);
+bool_t iparam_parse(const iparam_t *info, kparam_t *param, faux_error_t *error);
+bool_t iparam_parse_nested(const iparam_t *iparam, kparam_t *kparam,
+	faux_error_t *error);
+kparam_t *iparam_load(const iparam_t *iparam, faux_error_t *error);
+char *iparam_deploy(const kparam_t *kparam, int level);
 
 C_DECL_END
 

+ 6 - 1
klish/iptype.h

@@ -6,6 +6,7 @@
 #ifndef _klish_iptype_h
 #define _klish_iptype_h
 
+#include <faux/error.h>
 #include <klish/iaction.h>
 
 typedef struct iptype_s {
@@ -16,7 +17,11 @@ typedef struct iptype_s {
 
 C_DECL_BEGIN
 
-char *iptype_to_text(const iptype_t *iptype, int level);
+bool_t iptype_parse(const iptype_t *info, kptype_t *ptype, faux_error_t *error);
+bool_t iptype_parse_nested(const iptype_t *iptype, kptype_t *kptype,
+	faux_error_t *error_stack);
+kptype_t *iptype_load(const iptype_t *iptype, faux_error_t *error_stack);
+char *iptype_deploy(const kptype_t *kptype, int level);
 
 C_DECL_END
 

+ 5 - 1
klish/ischeme.h

@@ -6,6 +6,7 @@
 #ifndef _klish_ischeme_h
 #define _klish_ischeme_h
 
+#include <faux/error.h>
 #include <klish/iptype.h>
 #include <klish/iplugin.h>
 #include <klish/iview.h>
@@ -45,7 +46,10 @@ typedef struct ischeme_s {
 
 C_DECL_BEGIN
 
-char *ischeme_to_text(const ischeme_t *ischeme, int level);
+bool_t ischeme_parse_nested(const ischeme_t *ischeme, kscheme_t *kscheme,
+	faux_error_t *error);
+kscheme_t *ischeme_load(const ischeme_t *ischeme, faux_error_t *error);
+char *ischeme_deploy(const kscheme_t *scheme, int level);
 
 C_DECL_END
 

+ 6 - 7
klish/ischeme/Makefile.am

@@ -1,9 +1,8 @@
 libklish_la_SOURCES += \
 	klish/ischeme/iaction.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
+	klish/ischeme/iplugin.c \
+	klish/ischeme/iparam.c \
+	klish/ischeme/icommand.c \
+	klish/ischeme/iptype.c \
+	klish/ischeme/iview.c \
+	klish/ischeme/ischeme.c

+ 32 - 22
klish/ischeme/icommand.c

@@ -7,6 +7,8 @@
 #include <faux/list.h>
 #include <faux/error.h>
 #include <klish/khelper.h>
+#include <klish/iparam.h>
+#include <klish/iaction.h>
 #include <klish/icommand.h>
 #include <klish/kparam.h>
 #include <klish/kaction.h>
@@ -14,11 +16,16 @@
 
 #define TAG "COMMAND"
 
-bool_t kcommand_parse(kcommand_t *command, const icommand_t *info,
+bool_t icommand_parse(const icommand_t *info, kcommand_t *command,
 	faux_error_t *error)
 {
 	bool_t retcode = BOOL_TRUE;
 
+	if (!info)
+		return BOOL_FALSE;
+	if (!command)
+		return BOOL_FALSE;
+
 	// Help
 	if (!faux_str_is_empty(info->help)) {
 		if (!kcommand_set_help(command, info->help)) {
@@ -31,7 +38,7 @@ bool_t kcommand_parse(kcommand_t *command, const icommand_t *info,
 }
 
 
-bool_t kcommand_nested_from_icommand(kcommand_t *kcommand, icommand_t *icommand,
+bool_t icommand_parse_nested(const icommand_t *icommand, kcommand_t *kcommand,
 	faux_error_t *error)
 {
 	bool_t retval = BOOL_TRUE;
@@ -49,7 +56,7 @@ bool_t kcommand_nested_from_icommand(kcommand_t *kcommand, icommand_t *icommand,
 			kparam_t *kparam = NULL;
 			iparam_t *iparam = *p_iparam;
 
-			kparam = kparam_from_iparam(iparam, error);
+			kparam = iparam_load(iparam, error);
 			if (!kparam) {
 				retval = BOOL_FALSE;
 				continue;
@@ -80,7 +87,7 @@ bool_t kcommand_nested_from_icommand(kcommand_t *kcommand, icommand_t *icommand,
 			kaction_t *kaction = NULL;
 			iaction_t *iaction = *p_iaction;
 
-			kaction = kaction_from_iaction(iaction, error);
+			kaction = iaction_load(iaction, error);
 			if (!kaction) {
 				retval = BOOL_FALSE;
 				continue;
@@ -104,7 +111,7 @@ bool_t kcommand_nested_from_icommand(kcommand_t *kcommand, icommand_t *icommand,
 }
 
 
-kcommand_t *kcommand_from_icommand(icommand_t *icommand, faux_error_t *error)
+kcommand_t *icommand_load(icommand_t *icommand, faux_error_t *error)
 {
 	kcommand_t *kcommand = NULL;
 
@@ -121,13 +128,13 @@ kcommand_t *kcommand_from_icommand(icommand_t *icommand, faux_error_t *error)
 		return NULL;
 	}
 
-	if (!kcommand_parse(kcommand, icommand, error)) {
+	if (!icommand_parse(icommand, kcommand, error)) {
 		kcommand_free(kcommand);
 		return NULL;
 	}
 
 	// Parse nested elements
-	if (!kcommand_nested_from_icommand(kcommand, icommand, error)) {
+	if (!icommand_parse_nested(icommand, kcommand, error)) {
 		kcommand_free(kcommand);
 		return NULL;
 	}
@@ -136,30 +143,34 @@ kcommand_t *kcommand_from_icommand(icommand_t *icommand, faux_error_t *error)
 }
 
 
-char *icommand_to_text(const icommand_t *icommand, int level)
+char *icommand_deploy(const kcommand_t *kcommand, int level)
 {
 	char *str = NULL;
 	char *tmp = NULL;
+	kcommand_params_node_t *params_iter = NULL;
+	kcommand_actions_node_t *actions_iter = NULL;
+
+	if (!kcommand)
+		return NULL;
 
 	tmp = faux_str_sprintf("%*cCOMMAND {\n", level, ' ');
 	faux_str_cat(&str, tmp);
 	faux_str_free(tmp);
 
-	attr2ctext(&str, "name", icommand->name, level + 1);
-	attr2ctext(&str, "help", icommand->help, level + 1);
+	attr2ctext(&str, "name", kcommand_name(kcommand), level + 1);
+	attr2ctext(&str, "help", kcommand_help(kcommand), level + 1);
 
 	// PARAM list
-	if (icommand->params) {
-		iparam_t **p_iparam = NULL;
+	params_iter = kcommand_params_iter(kcommand);
+	if (params_iter) {
+		kparam_t *param = NULL;
 
 		tmp = faux_str_sprintf("\n%*cPARAM_LIST\n\n", level + 1, ' ');
 		faux_str_cat(&str, tmp);
 		faux_str_free(tmp);
 
-		for (p_iparam = *icommand->params; *p_iparam; p_iparam++) {
-			iparam_t *iparam = *p_iparam;
-
-			tmp = iparam_to_text(iparam, level + 2);
+		while ((param = kcommand_params_each(&params_iter))) {
+			tmp = iparam_deploy(param, level + 2);
 			faux_str_cat(&str, tmp);
 			faux_str_free(tmp);
 		}
@@ -170,17 +181,16 @@ char *icommand_to_text(const icommand_t *icommand, int level)
 	}
 
 	// ACTION list
-	if (icommand->actions) {
-		iaction_t **p_iaction = NULL;
+	actions_iter = kcommand_actions_iter(kcommand);
+	if (actions_iter) {
+		kaction_t *action = NULL;
 
 		tmp = faux_str_sprintf("\n%*cACTION_LIST\n\n", level + 1, ' ');
 		faux_str_cat(&str, tmp);
 		faux_str_free(tmp);
 
-		for (p_iaction = *icommand->actions; *p_iaction; p_iaction++) {
-			iaction_t *iaction = *p_iaction;
-
-			tmp = iaction_to_text(iaction, level + 2);
+		while ((action = kcommand_actions_each(&actions_iter))) {
+			tmp = iaction_deploy(action, level + 2);
 			faux_str_cat(&str, tmp);
 			faux_str_free(tmp);
 		}

+ 24 - 16
klish/ischeme/iparam.c

@@ -12,10 +12,15 @@
 
 #define TAG "PARAM"
 
-bool_t kparam_parse(kparam_t *param, const iparam_t *info, faux_error_t *error)
+bool_t iparam_parse(const iparam_t *info, kparam_t *param, faux_error_t *error)
 {
 	bool_t retcode = BOOL_TRUE;
 
+	if (!info)
+		return BOOL_FALSE;
+	if (!param)
+		return BOOL_FALSE;
+
 	// Help
 	if (!faux_str_is_empty(info->help)) {
 		if (!kparam_set_help(param, info->help)) {
@@ -36,7 +41,7 @@ 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,
+bool_t iparam_parse_nested(const iparam_t *iparam, kparam_t *kparam,
 	faux_error_t *error)
 {
 	bool_t retval = BOOL_TRUE;
@@ -53,7 +58,7 @@ bool_t kparam_nested_from_iparam(kparam_t *kparam, iparam_t *iparam,
 			kparam_t *nkparam = NULL;
 			iparam_t *niparam = *p_iparam;
 
-			nkparam = kparam_from_iparam(niparam, error);
+			nkparam = iparam_load(niparam, error);
 			if (!nkparam) {
 				retval = BOOL_FALSE;
 				continue;
@@ -85,10 +90,13 @@ bool_t kparam_nested_from_iparam(kparam_t *kparam, iparam_t *iparam,
 }
 
 
-kparam_t *kparam_from_iparam(iparam_t *iparam, faux_error_t *error)
+kparam_t *iparam_load(const iparam_t *iparam, faux_error_t *error)
 {
 	kparam_t *kparam = NULL;
 
+	if (!iparam)
+		return NULL;
+
 	// Name [mandatory]
 	if (faux_str_is_empty(iparam->name)) {
 		faux_error_add(error, TAG": Empty 'name' attribute");
@@ -102,13 +110,13 @@ kparam_t *kparam_from_iparam(iparam_t *iparam, faux_error_t *error)
 		return NULL;
 	}
 
-	if (!kparam_parse(kparam, iparam, error)) {
+	if (!iparam_parse(iparam, kparam, error)) {
 		kparam_free(kparam);
 		return NULL;
 	}
 
 	// Parse nested elements
-	if (!kparam_nested_from_iparam(kparam, iparam, error)) {
+	if (!iparam_parse_nested(iparam, kparam, error)) {
 		kparam_free(kparam);
 		return NULL;
 	}
@@ -117,31 +125,31 @@ kparam_t *kparam_from_iparam(iparam_t *iparam, faux_error_t *error)
 }
 
 
-char *iparam_to_text(const iparam_t *iparam, int level)
+char *iparam_deploy(const kparam_t *kparam, int level)
 {
 	char *str = NULL;
 	char *tmp = NULL;
+	kparam_params_node_t *params_iter = NULL;
 
 	tmp = faux_str_sprintf("%*cPARAM {\n", level, ' ');
 	faux_str_cat(&str, tmp);
 	faux_str_free(tmp);
 
-	attr2ctext(&str, "name", iparam->name, level + 1);
-	attr2ctext(&str, "help", iparam->help, level + 1);
-	attr2ctext(&str, "ptype", iparam->ptype, level + 1);
+	attr2ctext(&str, "name", kparam_name(kparam), level + 1);
+	attr2ctext(&str, "help", kparam_help(kparam), level + 1);
+	attr2ctext(&str, "ptype", kparam_ptype_ref(kparam), level + 1);
 
 	// PARAM list
-	if (iparam->params) {
-		iparam_t **p_iparam = NULL;
+	params_iter = kparam_params_iter(kparam);
+	if (params_iter) {
+		kparam_t *nparam = NULL;
 
 		tmp = faux_str_sprintf("\n%*cPARAM_LIST\n\n", level + 1, ' ');
 		faux_str_cat(&str, tmp);
 		faux_str_free(tmp);
 
-		for (p_iparam = *iparam->params; *p_iparam; p_iparam++) {
-			iparam_t *niparam = *p_iparam;
-
-			tmp = iparam_to_text(niparam, level + 2);
+		while ((nparam = kparam_params_each(&params_iter))) {
+			tmp = iparam_deploy(nparam, level + 2);
 			faux_str_cat(&str, tmp);
 			faux_str_free(tmp);
 		}

+ 44 - 157
klish/ischeme/iptype.c

@@ -9,153 +9,39 @@
 #include <klish/khelper.h>
 #include <klish/kptype.h>
 #include <klish/kaction.h>
+#include <klish/iptype.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;
-}
+#define TAG "PTYPE"
 
 
-kptype_t *kptype_new(const iptype_t *info, kptype_error_e *error)
+bool_t iptype_parse(const iptype_t *info, kptype_t *ptype, faux_error_t *error)
 {
-	kptype_t *ptype = NULL;
-
-	ptype = kptype_new_empty();
-	assert(ptype);
-	if (!ptype) {
-		if (error)
-			*error = KPTYPE_ERROR_ALLOC;
-		return NULL;
-	}
+	bool_t retcode = BOOL_TRUE;
 
 	if (!info)
-		return ptype;
-
-	if (!kptype_parse(ptype, info, error)) {
-		kptype_free(ptype);
-		return NULL;
-	}
-
-	return ptype;
-}
-
-
-void kptype_free(kptype_t *ptype)
-{
+		return BOOL_FALSE;
 	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;
+			faux_error_add(error, TAG": Illegal 'help' attribute");
+			retcode = BOOL_FALSE;
 		}
 	}
 
-	return BOOL_TRUE;
+	return retcode;
 }
 
 
-bool_t kptype_nested_from_iptype(kptype_t *kptype, iptype_t *iptype,
-	faux_error_t *error_stack)
+bool_t iptype_parse_nested(const iptype_t *iptype, kptype_t *kptype,
+	faux_error_t *error)
 {
 	bool_t retval = BOOL_TRUE;
 
 	if (!kptype || !iptype) {
-		faux_error_add(error_stack,
-			kptype_strerror(KPTYPE_ERROR_INTERNAL));
+		faux_error_add(error, TAG": Internal error");
 		return BOOL_FALSE;
 	}
 
@@ -166,15 +52,15 @@ bool_t kptype_nested_from_iptype(kptype_t *kptype, iptype_t *iptype,
 			kaction_t *kaction = NULL;
 			iaction_t *iaction = *p_iaction;
 
-			kaction = kaction_from_iaction(iaction, error_stack);
+			kaction = iaction_load(iaction, error);
 			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);
+				faux_error_sprintf(error,
+					TAG": Can't add ACTION #%d",
+					kptype_actions_len(kptype) + 1);
 				kaction_free(kaction);
 				retval = BOOL_FALSE;
 				continue;
@@ -183,7 +69,7 @@ bool_t kptype_nested_from_iptype(kptype_t *kptype, iptype_t *iptype,
 	}
 
 	if (!retval)
-		faux_error_sprintf(error_stack,
+		faux_error_sprintf(error,
 			"PTYPE \"%s\": Illegal nested elements",
 			kptype_name(kptype));
 
@@ -191,21 +77,33 @@ bool_t kptype_nested_from_iptype(kptype_t *kptype, iptype_t *iptype,
 }
 
 
-kptype_t *kptype_from_iptype(iptype_t *iptype, faux_error_t *error_stack)
+kptype_t *iptype_load(const iptype_t *iptype, faux_error_t *error)
 {
 	kptype_t *kptype = NULL;
-	kptype_error_e kptype_error = KPTYPE_ERROR_OK;
 
-	kptype = kptype_new(iptype, &kptype_error);
+	if (!iptype)
+		return NULL;
+
+	// Name [mandatory]
+	if (faux_str_is_empty(iptype->name)) {
+		faux_error_add(error, TAG": Empty 'name' attribute");
+		return NULL;
+	}
+
+	kptype = kptype_new(iptype->name);
 	if (!kptype) {
-		faux_error_sprintf(error_stack, "PTYPE \"%s\": %s",
-			iptype->name ? iptype->name : "(null)",
-			kptype_strerror(kptype_error));
+		faux_error_sprintf(error, TAG" \"%s\": Can't create object",
+			iptype->name);
+		return NULL;
+	}
+
+	if (!iptype_parse(iptype, kptype, error)) {
+		kptype_free(kptype);
 		return NULL;
 	}
 
 	// Parse nested elements
-	if (!kptype_nested_from_iptype(kptype, iptype, error_stack)) {
+	if (!iptype_parse_nested(iptype, kptype, error)) {
 		kptype_free(kptype);
 		return NULL;
 	}
@@ -214,41 +112,30 @@ kptype_t *kptype_from_iptype(iptype_t *iptype, faux_error_t *error_stack)
 }
 
 
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <faux/str.h>
-#include <klish/khelper.h>
-#include <klish/iptype.h>
-
-
-char *iptype_to_text(const iptype_t *iptype, int level)
+char *iptype_deploy(const kptype_t *kptype, int level)
 {
 	char *str = NULL;
 	char *tmp = NULL;
+	kptype_actions_node_t *actions_iter = NULL;
 
 	tmp = faux_str_sprintf("%*cPTYPE {\n", level, ' ');
 	faux_str_cat(&str, tmp);
 	faux_str_free(tmp);
 
-	attr2ctext(&str, "name", iptype->name, level + 1);
-	attr2ctext(&str, "help", iptype->help, level + 1);
+	attr2ctext(&str, "name", kptype_name(kptype), level + 1);
+	attr2ctext(&str, "help", kptype_help(kptype), level + 1);
 
 	// ACTION list
-	if (iptype->actions) {
-		iaction_t **p_iaction = NULL;
+	actions_iter = kptype_actions_iter(kptype);
+	if (actions_iter) {
+		kaction_t *action = NULL;
 
 		tmp = faux_str_sprintf("\n%*cACTION_LIST\n\n", level + 1, ' ');
 		faux_str_cat(&str, tmp);
 		faux_str_free(tmp);
 
-		for (p_iaction = *iptype->actions; *p_iaction; p_iaction++) {
-			iaction_t *iaction = *p_iaction;
-
-			tmp = iaction_to_text(iaction, level + 2);
+		while ((action = kptype_actions_each(&actions_iter))) {
+			tmp = iaction_deploy(action, level + 2);
 			faux_str_cat(&str, tmp);
 			faux_str_free(tmp);
 		}

+ 29 - 28
klish/ischeme/ischeme.c

@@ -6,16 +6,17 @@
 #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>
+#include <klish/iview.h>
+#include <klish/ischeme.h>
 
 #define TAG "SCHEME"
 
 
-bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
+bool_t ischeme_parse_nested(const ischeme_t *ischeme, kscheme_t *kscheme,
 	faux_error_t *error)
 {
 	bool_t retval = BOOL_TRUE;
@@ -32,7 +33,7 @@ bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
 			kplugin_t *kplugin = NULL;
 			iplugin_t *iplugin = *p_iplugin;
 
-			kplugin = kplugin_from_iplugin(iplugin, error);
+			kplugin = iplugin_load(iplugin, error);
 			if (!kplugin) {
 				retval = BOOL_FALSE; // Don't stop
 				continue;
@@ -62,7 +63,7 @@ bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
 			kptype_t *kptype = NULL;
 			iptype_t *iptype = *p_iptype;
 
-			kptype = kptype_from_iptype(iptype, error);
+			kptype = iptype_load(iptype, error);
 			if (!kptype) {
 				retval = BOOL_FALSE; // Don't stop
 				continue;
@@ -103,11 +104,11 @@ bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
 
 			// VIEW already exists
 			if (kview) {
-				if (!kview_parse(kview, iview, error)) {
+				if (!iview_parse(iview, kview, error)) {
 					retval = BOOL_FALSE;
 					continue;
 				}
-				if (!kview_nested_from_iview(kview, iview,
+				if (!iview_parse_nested(iview, kview,
 					error)) {
 					retval = BOOL_FALSE;
 					continue;
@@ -116,7 +117,7 @@ bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
 			}
 
 			// New VIEW
-			kview = kview_from_iview(iview, error);
+			kview = iview_load(iview, error);
 			if (!kview) {
 				retval = BOOL_FALSE;
 				continue;
@@ -139,7 +140,7 @@ bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
 }
 
 
-kscheme_t *kscheme_from_ischeme(ischeme_t *ischeme, faux_error_t *error)
+kscheme_t *ischeme_load(const ischeme_t *ischeme, faux_error_t *error)
 {
 	kscheme_t *kscheme = NULL;
 
@@ -150,7 +151,7 @@ kscheme_t *kscheme_from_ischeme(ischeme_t *ischeme, faux_error_t *error)
 	}
 
 	// Parse nested elements
-	if (!kscheme_nested_from_ischeme(kscheme, ischeme, error)) {
+	if (!ischeme_parse_nested(ischeme, kscheme, error)) {
 		kscheme_free(kscheme);
 		return NULL;
 	}
@@ -159,27 +160,29 @@ kscheme_t *kscheme_from_ischeme(ischeme_t *ischeme, faux_error_t *error)
 }
 
 
-char *ischeme_to_text(const ischeme_t *ischeme, int level)
+char *ischeme_deploy(const kscheme_t *scheme, int level)
 {
 	char *str = NULL;
 	char *tmp = NULL;
+	kscheme_plugins_node_t *plugins_iter = NULL;
+	kscheme_ptypes_node_t *ptypes_iter = NULL;
+	kscheme_views_node_t *views_iter = NULL;
 
 	tmp = faux_str_sprintf("ischeme_t sch = {\n");
 	faux_str_cat(&str, tmp);
 	faux_str_free(tmp);
 
 	// PLUGIN list
-	if (ischeme->plugins) {
-		iplugin_t **p_iplugin = NULL;
+	plugins_iter = kscheme_plugins_iter(scheme);
+	if (plugins_iter) {
+		kplugin_t *plugin = NULL;
 
 		tmp = faux_str_sprintf("\n%*cPLUGIN_LIST\n\n", level, ' ');
 		faux_str_cat(&str, tmp);
 		faux_str_free(tmp);
 
-		for (p_iplugin = *ischeme->plugins; *p_iplugin; p_iplugin++) {
-			iplugin_t *iplugin = *p_iplugin;
-
-			tmp = iplugin_to_text(iplugin, level + 2);
+		while ((plugin = kscheme_plugins_each(&plugins_iter))) {
+			tmp = iplugin_deploy(plugin, level + 2);
 			faux_str_cat(&str, tmp);
 			faux_str_free(tmp);
 		}
@@ -190,17 +193,16 @@ char *ischeme_to_text(const ischeme_t *ischeme, int level)
 	}
 
 	// PTYPE list
-	if (ischeme->ptypes) {
-		iptype_t **p_iptype = NULL;
+	ptypes_iter = kscheme_ptypes_iter(scheme);
+	if (ptypes_iter) {
+		kptype_t *ptype = NULL;
 
 		tmp = faux_str_sprintf("\n%*cPTYPE_LIST\n\n", level, ' ');
 		faux_str_cat(&str, tmp);
 		faux_str_free(tmp);
 
-		for (p_iptype = *ischeme->ptypes; *p_iptype; p_iptype++) {
-			iptype_t *iptype = *p_iptype;
-
-			tmp = iptype_to_text(iptype, level + 2);
+		while ((ptype = kscheme_ptypes_each(&ptypes_iter))) {
+			tmp = iptype_deploy(ptype, level + 2);
 			faux_str_cat(&str, tmp);
 			faux_str_free(tmp);
 		}
@@ -211,17 +213,16 @@ char *ischeme_to_text(const ischeme_t *ischeme, int level)
 	}
 
 	// VIEW list
-	if (ischeme->views) {
-		iview_t **p_iview = NULL;
+	views_iter = kscheme_views_iter(scheme);
+	if (views_iter) {
+		kview_t *view = NULL;
 
 		tmp = faux_str_sprintf("\n%*cVIEW_LIST\n\n", level + 1, ' ');
 		faux_str_cat(&str, tmp);
 		faux_str_free(tmp);
 
-		for (p_iview = *ischeme->views; *p_iview; p_iview++) {
-			iview_t *iview = *p_iview;
-
-			tmp = iview_to_text(iview, level + 2);
+		while ((view = kscheme_views_each(&views_iter))) {
+			tmp = iview_deploy(view, level + 2);
 			faux_str_cat(&str, tmp);
 			faux_str_free(tmp);
 		}

+ 26 - 14
klish/ischeme/iview.c

@@ -9,14 +9,20 @@
 #include <klish/khelper.h>
 #include <klish/kcommand.h>
 #include <klish/kview.h>
+#include <klish/iview.h>
 
 #define TAG "VIEW"
 
 
-bool_t kview_parse(kview_t *view, const iview_t *info, faux_error_t *error)
+bool_t iview_parse(const iview_t *info, kview_t *view, faux_error_t *error)
 {
 	bool_t retcode = BOOL_TRUE;
 
+	if (!info)
+		return BOOL_FALSE;
+	if (!view)
+		return BOOL_FALSE;
+
 	view = view;
 	info = info;
 	error = error;
@@ -25,7 +31,7 @@ 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,
+bool_t iview_parse_nested(const iview_t *iview, kview_t *kview,
 	faux_error_t *error)
 {
 	bool_t retval = BOOL_TRUE;
@@ -41,7 +47,7 @@ bool_t kview_nested_from_iview(kview_t *kview, iview_t *iview,
 		for (p_icommand = *iview->commands; *p_icommand; p_icommand++) {
 			kcommand_t *kcommand = NULL;
 			icommand_t *icommand = *p_icommand;
-			kcommand = kcommand_from_icommand(icommand, error);
+			kcommand = icommand_load(icommand, error);
 			if (!kcommand) {
 				retval = BOOL_FALSE;
 				continue;
@@ -73,10 +79,13 @@ bool_t kview_nested_from_iview(kview_t *kview, iview_t *iview,
 }
 
 
-kview_t *kview_from_iview(iview_t *iview, faux_error_t *error)
+kview_t *iview_load(const iview_t *iview, faux_error_t *error)
 {
 	kview_t *kview = NULL;
 
+	if (!iview)
+		return NULL;
+
 	// Name [mandatory]
 	if (faux_str_is_empty(iview->name)) {
 		faux_error_add(error, TAG": Empty 'name' attribute");
@@ -90,13 +99,13 @@ kview_t *kview_from_iview(iview_t *iview, faux_error_t *error)
 		return NULL;
 	}
 
-	if (!kview_parse(kview, iview, error)) {
+	if (!iview_parse(iview, kview, error)) {
 		kview_free(kview);
 		return NULL;
 	}
 
 	// Parse nested elements
-	if (!kview_nested_from_iview(kview, iview, error)) {
+	if (!iview_parse_nested(iview, kview, error)) {
 		kview_free(kview);
 		return NULL;
 	}
@@ -105,29 +114,32 @@ kview_t *kview_from_iview(iview_t *iview, faux_error_t *error)
 }
 
 
-char *iview_to_text(const iview_t *iview, int level)
+char *iview_deploy(const kview_t *kview, int level)
 {
 	char *str = NULL;
 	char *tmp = NULL;
+	kview_commands_node_t *commands_iter = NULL;
+
+	if (!kview)
+		return NULL;
 
 	tmp = faux_str_sprintf("%*cVIEW {\n", level, ' ');
 	faux_str_cat(&str, tmp);
 	faux_str_free(tmp);
 
-	attr2ctext(&str, "name", iview->name, level + 1);
+	attr2ctext(&str, "name", kview_name(kview), level + 1);
 
 	// COMMAND list
-	if (iview->commands) {
-		icommand_t **p_icommand = NULL;
+	commands_iter = kview_commands_iter(kview);
+	if (commands_iter) {
+		kcommand_t *command = NULL;
 
 		tmp = faux_str_sprintf("\n%*cCOMMAND_LIST\n\n", level + 1, ' ');
 		faux_str_cat(&str, tmp);
 		faux_str_free(tmp);
 
-		for (p_icommand = *iview->commands; *p_icommand; p_icommand++) {
-			icommand_t *icommand = *p_icommand;
-
-			tmp = icommand_to_text(icommand, level + 2);
+		while ((command = kview_commands_each(&commands_iter))) {
+			tmp = icommand_deploy(command, level + 2);
 			faux_str_cat(&str, tmp);
 			faux_str_free(tmp);
 		}

+ 6 - 1
klish/iview.h

@@ -6,6 +6,7 @@
 #ifndef _klish_iview_h
 #define _klish_iview_h
 
+#include <faux/error.h>
 #include <klish/icommand.h>
 
 typedef struct iview_s {
@@ -15,7 +16,11 @@ typedef struct iview_s {
 
 C_DECL_BEGIN
 
-char *iview_to_text(const iview_t *iview, int level);
+bool_t iview_parse(const iview_t *info, kview_t *view, faux_error_t *error);
+bool_t iview_parse_nested(const iview_t *iview, kview_t *kview,
+	faux_error_t *error);
+kview_t *iview_load(const iview_t *iview, faux_error_t *error);
+char *iview_deploy(const kview_t *kview, int level);
 
 C_DECL_END
 

+ 9 - 0
klish/kcommand.h

@@ -6,12 +6,15 @@
 #ifndef _klish_kcommand_h
 #define _klish_kcommand_h
 
+#include <faux/list.h>
 #include <klish/kparam.h>
 #include <klish/kaction.h>
 
 
 typedef struct kcommand_s kcommand_t;
 
+typedef faux_list_node_t kcommand_params_node_t;
+typedef faux_list_node_t kcommand_actions_node_t;
 
 C_DECL_BEGIN
 
@@ -22,11 +25,17 @@ const char *kcommand_name(const kcommand_t *command);
 const char *kcommand_help(const kcommand_t *command);
 bool_t kcommand_set_help(kcommand_t *command, const char *help);
 
+// params
 bool_t kcommand_add_param(kcommand_t *command, kparam_t *param);
 kparam_t *kcommand_find_param(const kcommand_t *command, const char *name);
 ssize_t kcommand_params_len(const kcommand_t *command);
+kcommand_params_node_t *kcommand_params_iter(const kcommand_t *command);
+kparam_t *kcommand_params_each(kcommand_params_node_t **iter);
+// actions
 bool_t kcommand_add_action(kcommand_t *command, kaction_t *action);
 ssize_t kcommand_actions_len(const kcommand_t *command);
+kcommand_actions_node_t *kcommand_actions_iter(const kcommand_t *command);
+kaction_t *kcommand_actions_each(kcommand_actions_node_t **iter);
 
 C_DECL_END
 

+ 17 - 0
klish/khelper.h

@@ -136,6 +136,23 @@
 	return faux_list_len(inst->nested##s); \
 }
 
+#define _KNESTED_ITER(obj, nested) \
+	k##obj##_##nested##s_node_t *k##obj##_##nested##s_iter(const k##obj##_t *inst)
+#define KNESTED_ITER(obj, nested) \
+	_KNESTED_ITER(obj, nested) { \
+	assert(inst); \
+	if (!inst) \
+		return NULL; \
+	return (k##obj##_##nested##s_node_t *)faux_list_head(inst->nested##s); \
+}
+
+#define _KNESTED_EACH(obj, nested) \
+	k##nested##_t *k##obj##_##nested##s_each(k##obj##_##nested##s_node_t **iter)
+#define KNESTED_EACH(obj, nested) \
+	_KNESTED_EACH(obj, nested) { \
+	return (k##nested##_t *)faux_list_each((faux_list_node_t **)iter); \
+}
+
 
 C_DECL_BEGIN
 

+ 7 - 2
klish/kparam.h

@@ -6,11 +6,13 @@
 #ifndef _klish_kparam_h
 #define _klish_kparam_h
 
-#include <faux/error.h>
-
+#include <faux/list.h>
+#include <klish/ksym.h>
 
 typedef struct kparam_s kparam_t;
 
+typedef faux_list_node_t kparam_params_node_t;
+
 
 C_DECL_BEGIN
 
@@ -23,8 +25,11 @@ bool_t kparam_set_help(kparam_t *param, const char *help);
 const char *kparam_ptype_ref(const kparam_t *param);
 bool_t kparam_set_ptype_ref(kparam_t *param, const char *ptype_ref);
 
+// params
 bool_t kparam_add_param(kparam_t *param, kparam_t *nested_param);
 kparam_t *kparam_find_param(const kparam_t *param, const char *name);
+kparam_params_node_t *kparam_params_iter(const kparam_t *param);
+kparam_t *kparam_params_each(kparam_params_node_t **iter);
 
 C_DECL_END
 

+ 6 - 1
klish/kplugin.h

@@ -7,8 +7,8 @@
 #define _klish_kplugin_h
 
 #include <stdint.h>
-#include <faux/error.h>
 
+#include <faux/list.h>
 #include <klish/ksym.h>
 
 // Current API version
@@ -32,6 +32,8 @@
 
 typedef struct kplugin_s kplugin_t;
 
+typedef faux_list_node_t kplugin_syms_node_t;
+
 
 C_DECL_BEGIN
 
@@ -54,9 +56,12 @@ bool_t kplugin_set_minor(kplugin_t *plugin, uint8_t minor);
 void *kplugin_udata(const kplugin_t *plugin);
 bool_t kplugin_set_udata(kplugin_t *plugin, void *udata);
 
+// syms
 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);
+kplugin_syms_node_t *kplugin_syms_iter(const kplugin_t *plugin);
+ksym_t *kplugin_syms_each(kplugin_syms_node_t **iter);
 
 C_DECL_END
 

+ 8 - 1
klish/kptype.h

@@ -6,11 +6,12 @@
 #ifndef _klish_kptype_h
 #define _klish_kptype_h
 
-#include <faux/error.h>
+#include <faux/list.h>
 #include <klish/kaction.h>
 
 typedef struct kptype_s kptype_t;
 
+typedef faux_list_node_t kptype_actions_node_t;
 
 C_DECL_BEGIN
 
@@ -21,6 +22,12 @@ const char *kptype_name(const kptype_t *ptype);
 const char *kptype_help(const kptype_t *ptype);
 bool_t kptype_set_help(kptype_t *ptype, const char *help);
 
+// actions
+bool_t kptype_add_action(kptype_t *plugin, kaction_t *action);
+ssize_t kptype_actions_len(const kptype_t *plugin);
+kptype_actions_node_t *kptype_actions_iter(const kptype_t *plugin);
+kaction_t *kptype_actions_each(kptype_actions_node_t **iter);
+
 C_DECL_END
 
 #endif // _klish_kptype_h

+ 17 - 2
klish/kscheme.h

@@ -6,8 +6,7 @@
 #ifndef _klish_kscheme_h
 #define _klish_kscheme_h
 
-#include <faux/error.h>
-
+#include <faux/list.h>
 #include <klish/kplugin.h>
 #include <klish/kptype.h>
 #include <klish/kview.h>
@@ -15,18 +14,34 @@
 
 typedef struct kscheme_s kscheme_t;
 
+typedef faux_list_node_t kscheme_views_node_t;
+typedef faux_list_node_t kscheme_ptypes_node_t;
+typedef faux_list_node_t kscheme_plugins_node_t;
+
 
 C_DECL_BEGIN
 
 kscheme_t *kscheme_new(void);
 void kscheme_free(kscheme_t *scheme);
 
+// views
 bool_t kscheme_add_view(kscheme_t *scheme, kview_t *view);
 kview_t *kscheme_find_view(const kscheme_t *scheme, const char *name);
+ssize_t kscheme_views_len(const kscheme_t *scheme);
+kscheme_views_node_t *kscheme_views_iter(const kscheme_t *scheme);
+kview_t *kscheme_views_each(kscheme_views_node_t **iter);
+// ptypes
 bool_t kscheme_add_ptype(kscheme_t *scheme, kptype_t *ptype);
 kptype_t *kscheme_find_ptype(const kscheme_t *scheme, const char *name);
+ssize_t kscheme_ptypes_len(const kscheme_t *scheme);
+kscheme_ptypes_node_t *kscheme_ptypes_iter(const kscheme_t *scheme);
+kptype_t *kscheme_ptypes_each(kscheme_ptypes_node_t **iter);
+// plugins
 bool_t kscheme_add_plugin(kscheme_t *scheme, kplugin_t *plugin);
 kplugin_t *kscheme_find_plugin(const kscheme_t *scheme, const char *name);
+ssize_t kscheme_plugins_len(const kscheme_t *scheme);
+kscheme_plugins_node_t *kscheme_plugins_iter(const kscheme_t *scheme);
+kplugin_t *kscheme_plugins_each(kscheme_plugins_node_t **iter);
 
 C_DECL_END
 

+ 4 - 0
klish/kscheme/kcommand.c

@@ -33,10 +33,14 @@ static KCMP_NESTED_BY_KEY(command, param, name);
 KADD_NESTED(command, param);
 KFIND_NESTED(command, param);
 KNESTED_LEN(command, param);
+KNESTED_ITER(command, param);
+KNESTED_EACH(command, param);
 
 // ACTION list
 KADD_NESTED(command, action);
 KNESTED_LEN(command, action);
+KNESTED_ITER(command, action);
+KNESTED_EACH(command, action);
 
 
 kcommand_t *kcommand_new(const char *name)

+ 2 - 0
klish/kscheme/kparam.c

@@ -40,6 +40,8 @@ static KCMP_NESTED(param, param, name);
 static KCMP_NESTED_BY_KEY(param, param, name);
 KADD_NESTED(param, param);
 KFIND_NESTED(param, param);
+KNESTED_ITER(param, param);
+KNESTED_EACH(param, param);
 
 
 kparam_t *kparam_new(const char *name)

+ 2 - 0
klish/kscheme/kplugin.c

@@ -69,6 +69,8 @@ static KCMP_NESTED_BY_KEY(plugin, sym, name);
 KADD_NESTED(plugin, sym);
 KFIND_NESTED(plugin, sym);
 KNESTED_LEN(plugin, sym);
+KNESTED_ITER(plugin, sym);
+KNESTED_EACH(plugin, sym);
 
 
 kplugin_t *kplugin_new(const char *name)

+ 3 - 0
klish/kscheme/kptype.c

@@ -29,6 +29,9 @@ KSET_STR(ptype, help);
 
 // ACTION list
 KADD_NESTED(ptype, action);
+KNESTED_LEN(ptype, action);
+KNESTED_ITER(ptype, action);
+KNESTED_EACH(ptype, action);
 
 
 kptype_t *kptype_new(const char *name)

+ 9 - 0
klish/kscheme/kscheme.c

@@ -25,18 +25,27 @@ KCMP_NESTED(scheme, plugin, name);
 KCMP_NESTED_BY_KEY(scheme, plugin, name);
 KADD_NESTED(scheme, plugin);
 KFIND_NESTED(scheme, plugin);
+KNESTED_LEN(scheme, plugin);
+KNESTED_ITER(scheme, plugin);
+KNESTED_EACH(scheme, plugin);
 
 // PTYPE list
 KCMP_NESTED(scheme, ptype, name);
 KCMP_NESTED_BY_KEY(scheme, ptype, name);
 KADD_NESTED(scheme, ptype);
 KFIND_NESTED(scheme, ptype);
+KNESTED_LEN(scheme, ptype);
+KNESTED_ITER(scheme, ptype);
+KNESTED_EACH(scheme, ptype);
 
 // VIEW list
 KCMP_NESTED(scheme, view, name);
 KCMP_NESTED_BY_KEY(scheme, view, name);
 KADD_NESTED(scheme, view);
 KFIND_NESTED(scheme, view);
+KNESTED_LEN(scheme, view);
+KNESTED_ITER(scheme, view);
+KNESTED_EACH(scheme, view);
 
 
 kscheme_t *kscheme_new(void)

+ 3 - 0
klish/kscheme/kview.c

@@ -26,6 +26,9 @@ KCMP_NESTED(view, command, name);
 KCMP_NESTED_BY_KEY(view, command, name);
 KADD_NESTED(view, command);
 KFIND_NESTED(view, command);
+KNESTED_LEN(view, command);
+KNESTED_ITER(view, command);
+KNESTED_EACH(view, command);
 
 
 kview_t *kview_new(const char *name)

+ 7 - 1
klish/kview.h

@@ -7,12 +7,14 @@
 #define _klish_kview_h
 
 #include <faux/faux.h>
-#include <faux/error.h>
+#include <faux/list.h>
 #include <klish/kcommand.h>
 
 
 typedef struct kview_s kview_t;
 
+typedef faux_list_node_t kview_commands_node_t;
+
 
 C_DECL_BEGIN
 
@@ -21,8 +23,12 @@ void kview_free(kview_t *view);
 
 const char *kview_name(const kview_t *view);
 
+// commands
 bool_t kview_add_command(kview_t *view, kcommand_t *command);
 kcommand_t *kview_find_command(const kview_t *view, const char *name);
+ssize_t kview_commands_len(const kview_t *view);
+kview_commands_node_t *kview_commands_iter(const kview_t *view);
+kcommand_t *kview_commands_each(kview_commands_node_t **iter);
 
 C_DECL_END