Bladeren bron

scheme: kaction and kparam

Serj Kalichev 3 jaren geleden
bovenliggende
commit
3bca03bd31
7 gewijzigde bestanden met toevoegingen van 415 en 101 verwijderingen
  1. 27 5
      klish/kaction.h
  2. 24 3
      klish/kparam.h
  3. 192 21
      klish/kscheme/kaction.c
  4. 4 6
      klish/kscheme/kcommand.c
  5. 161 55
      klish/kscheme/kparam.c
  6. 4 6
      klish/kscheme/kptype.c
  7. 3 5
      klish/kscheme/kview.c

+ 27 - 5
klish/kaction.h

@@ -6,6 +6,7 @@
 #ifndef _klish_kaction_h
 #define _klish_kaction_h
 
+#include <faux/error.h>
 
 typedef struct kaction_s kaction_t;
 
@@ -21,10 +22,17 @@ typedef struct iaction_s {
 
 typedef enum {
 	KACTION_ERROR_OK,
-	KACTION_ERROR_MALLOC,
-	KACTION_ERROR_LIST
+	KACTION_ERROR_INTERNAL,
+	KACTION_ERROR_ALLOC,
+	KACTION_ERROR_ATTR_SYM,
+	KACTION_ERROR_ATTR_LOCK,
+	KACTION_ERROR_ATTR_INTERRUPT,
+	KACTION_ERROR_ATTR_INTERACTIVE,
+	KACTION_ERROR_ATTR_EXEC_ON,
+	KACTION_ERROR_ATTR_UPDATE_RETCODE,
 } kaction_error_e;
 
+
 typedef enum {
 	KACTION_COND_FAIL,
 	KACTION_COND_SUCCESS,
@@ -34,11 +42,25 @@ typedef enum {
 
 C_DECL_BEGIN
 
-kaction_t *kaction_new(iaction_t info);
-kaction_t *kaction_new_static(iaction_t info);
+kaction_t *kaction_new(const iaction_t *info, kaction_error_e *error);
 void kaction_free(kaction_t *action);
+const char *kaction_strerror(kaction_error_e error);
+bool_t kaction_parse(kaction_t *action, const iaction_t *info, kaction_error_e *error);
+
+const char *kaction_sym_ref(const kaction_t *action);
+bool_t kaction_set_sym_ref(kaction_t *action, const char *sym_ref);
+const char *kaction_lock(const kaction_t *action);
+bool_t kaction_set_lock(kaction_t *action, const char *lock);
+bool_t kaction_interrupt(const kaction_t *action);
+bool_t kaction_set_interrupt(kaction_t *action, bool_t interrupt);
+bool_t kaction_interactive(const kaction_t *action);
+bool_t kaction_set_interactive(kaction_t *action, bool_t interactive);
+kaction_cond_e kaction_exec_on(const kaction_t *action);
+bool_t kaction_set_exec_on(kaction_t *action, kaction_cond_e exec_on);
+bool_t kaction_update_retcode(const kaction_t *action);
+bool_t kaction_set_update_retcode(kaction_t *action, bool_t update_retcode);
 
-const char *kaction_name(const kaction_t *action);
+kaction_t *kaction_from_iaction(iaction_t *iaction, faux_error_t *error_stack);
 
 C_DECL_END
 

+ 24 - 3
klish/kparam.h

@@ -17,15 +17,36 @@ struct iparam_s {
 };
 
 
+typedef enum {
+	KPARAM_ERROR_OK,
+	KPARAM_ERROR_INTERNAL,
+	KPARAM_ERROR_ALLOC,
+	KPARAM_ERROR_ATTR_NAME,
+	KPARAM_ERROR_ATTR_HELP,
+	KPARAM_ERROR_ATTR_PTYPE,
+} kparam_error_e;
+
+
 C_DECL_BEGIN
 
-kparam_t *kparam_new(iparam_t info);
-kparam_t *kparam_new_static(iparam_t info);
+kparam_t *kparam_new(const iparam_t *info, kparam_error_e *error);
 void kparam_free(kparam_t *param);
+const char *kparam_strerror(kparam_error_e error);
+bool_t kparam_parse(kparam_t *param, const iparam_t *info, kparam_error_e *error);
 
 const char *kparam_name(const kparam_t *param);
+bool_t kparam_set_name(kparam_t *param, const char *name);
 const char *kparam_help(const kparam_t *param);
-const char *kparam_ptype_str(const kparam_t *param);
+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);
+
+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_nested_from_iparam(kparam_t *kparam, iparam_t *iparam,
+	faux_error_t *error_stack);
+kparam_t *kparam_from_iparam(iparam_t *iparam, faux_error_t *error_stack);
 
 C_DECL_END
 

+ 192 - 21
klish/kscheme/kaction.c

@@ -4,20 +4,51 @@
 #include <assert.h>
 
 #include <faux/str.h>
+#include <faux/conv.h>
 #include <faux/list.h>
 #include <klish/khelper.h>
 #include <klish/kaction.h>
 
 
 struct kaction_s {
-	bool_t is_static;
-	kaction_error_e error;
-	iaction_t info;
-	faux_list_t *commands;
+	char *sym_ref; // Text reference to symbol
+	char *lock; // Named lock
+	bool_t interrupt;
+	bool_t interactive;
+	kaction_cond_e exec_on;
+	bool_t update_retcode;
+	//ksym_t *sym; // Symbol
 };
 
 
-static kaction_t *kaction_new_internal(iaction_t info, bool_t is_static)
+// Simple methods
+
+// Sym reference (must be resolved later)
+KGET_STR(action, sym_ref);
+KSET_STR_ONCE(action, sym_ref);
+
+// Lock
+KGET_STR(action, lock);
+KSET_STR(action, lock);
+
+// Interrupt
+KGET_BOOL(action, interrupt);
+KSET_BOOL(action, interrupt);
+
+// Interactive
+KGET_BOOL(action, interactive);
+KSET_BOOL(action, interactive);
+
+// Exec_on
+KGET(action, kaction_cond_e, exec_on);
+KSET(action, kaction_cond_e, exec_on);
+
+// Update_retcode
+KGET_BOOL(action, update_retcode);
+KSET_BOOL(action, update_retcode);
+
+
+static kaction_t *kaction_new_empty(void)
 {
 	kaction_t *action = NULL;
 
@@ -27,23 +58,38 @@ static kaction_t *kaction_new_internal(iaction_t info, bool_t is_static)
 		return NULL;
 
 	// Initialize
-	action->is_static = is_static;
-	action->error = KACTION_ERROR_OK;
-	action->info = info;
+	action->sym_ref = NULL;
+	action->lock = NULL;
+	action->interrupt = BOOL_FALSE;
+	action->interactive = BOOL_FALSE;
+	action->exec_on = KACTION_COND_SUCCESS;
+	action->update_retcode = BOOL_TRUE;
 
 	return action;
 }
 
 
-kaction_t *kaction_new(iaction_t info)
+kaction_t *kaction_new(const iaction_t *info, kaction_error_e *error)
 {
-	return kaction_new_internal(info, BOOL_FALSE);
-}
+	kaction_t *action = NULL;
 
+	action = kaction_new_empty();
+	assert(action);
+	if (!action) {
+		if (error)
+			*error = KACTION_ERROR_ALLOC;
+		return NULL;
+	}
 
-kaction_t *kaction_new_static(iaction_t info)
-{
-	return kaction_new_internal(info, BOOL_TRUE);
+	if (!info)
+		return action;
+
+	if (!kaction_parse(action, info, error)) {
+		kaction_free(action);
+		return NULL;
+	}
+
+	return action;
 }
 
 
@@ -52,19 +98,144 @@ void kaction_free(kaction_t *action)
 	if (!action)
 		return;
 
-	if (!action->is_static) {
-		faux_str_free(action->info.sym);
-	}
+	faux_str_free(action->sym_ref);
+	faux_str_free(action->lock);
 
 	faux_free(action);
 }
 
 
-const char *kaction_sym_str(const kaction_t *action)
+const char *kaction_strerror(kaction_error_e error)
 {
-	assert(action);
-	if (!action)
+	const char *str = NULL;
+
+	switch (error) {
+	case KACTION_ERROR_OK:
+		str = "Ok";
+		break;
+	case KACTION_ERROR_INTERNAL:
+		str = "Internal error";
+		break;
+	case KACTION_ERROR_ALLOC:
+		str = "Memory allocation error";
+		break;
+	case KACTION_ERROR_ATTR_SYM:
+		str = "Illegal 'sym' attribute";
+		break;
+	case KACTION_ERROR_ATTR_LOCK:
+		str = "Illegal 'lock' attribute";
+		break;
+	case KACTION_ERROR_ATTR_INTERRUPT:
+		str = "Illegal 'interrupt' attribute";
+		break;
+	case KACTION_ERROR_ATTR_INTERACTIVE:
+		str = "Illegal 'interactive' attribute";
+		break;
+	case KACTION_ERROR_ATTR_UPDATE_RETCODE:
+		str = "Illegal 'update_retcode' attribute";
+		break;
+	default:
+		str = "Unknown error";
+		break;
+	}
+
+	return str;
+}
+
+
+bool_t kaction_parse(kaction_t *action, const iaction_t *info, kaction_error_e *error)
+{
+	// Sym
+	if (!faux_str_is_empty(info->sym)) {
+		if (!kaction_set_sym_ref(action, info->sym)) {
+			if (error)
+				*error = KACTION_ERROR_ATTR_SYM;
+			return BOOL_FALSE;
+		}
+	}
+
+	// Lock
+	if (!faux_str_is_empty(info->lock)) {
+		if (!kaction_set_lock(action, info->lock)) {
+			if (error)
+				*error = KACTION_ERROR_ATTR_LOCK;
+			return 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)) {
+			if (error)
+				*error = KACTION_ERROR_ATTR_INTERRUPT;
+			return 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)) {
+			if (error)
+				*error = KACTION_ERROR_ATTR_INTERACTIVE;
+			return BOOL_FALSE;
+		}
+	}
+
+	// Exec_on
+	if (!faux_str_is_empty(info->exec_on)) {
+		kaction_cond_e c = KACTION_COND_SUCCESS;
+		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;
+		else {
+			if (error)
+				*error = KACTION_ERROR_ATTR_EXEC_ON;
+			return BOOL_FALSE;
+		}
+		if (!kaction_set_exec_on(action, c)) {
+			if (error)
+				*error = KACTION_ERROR_ATTR_EXEC_ON;
+			return 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)) {
+			if (error)
+				*error = KACTION_ERROR_ATTR_UPDATE_RETCODE;
+			return BOOL_FALSE;
+		}
+	}
+
+	return BOOL_TRUE;
+}
+
+
+kaction_t *kaction_from_iaction(iaction_t *iaction, faux_error_t *error_stack)
+{
+	kaction_t *kaction = NULL;
+	kaction_error_e kaction_error = KACTION_ERROR_OK;
+
+	kaction = kaction_new(iaction, &kaction_error);
+	if (!kaction) {
+		char *msg = NULL;
+		msg = faux_str_sprintf("ACTION : %s",
+			kaction_strerror(kaction_error));
+		faux_error_add(error_stack, msg);
+		faux_str_free(msg);
 		return NULL;
+	}
+	printf("action\n");
 
-	return action->info.sym;
+	return kaction;
 }

+ 4 - 6
klish/kscheme/kcommand.c

@@ -123,18 +123,16 @@ const char *kcommand_strerror(kcommand_error_e error)
 
 bool_t kcommand_parse(kcommand_t *command, const icommand_t *info, kcommand_error_e *error)
 {
-	bool_t retval = BOOL_TRUE;
-
 	// Name [mandatory]
 	if (faux_str_is_empty(info->name)) {
 		if (error)
 			*error = KCOMMAND_ERROR_ATTR_NAME;
-		retval = BOOL_FALSE;
+		return BOOL_FALSE;
 	} else {
 		if (!kcommand_set_name(command, info->name)) {
 			if (error)
 				*error = KCOMMAND_ERROR_ATTR_NAME;
-			retval = BOOL_FALSE;
+			return BOOL_FALSE;
 		}
 	}
 
@@ -143,11 +141,11 @@ bool_t kcommand_parse(kcommand_t *command, const icommand_t *info, kcommand_erro
 		if (!kcommand_set_help(command, info->help)) {
 			if (error)
 				*error = KCOMMAND_ERROR_ATTR_HELP;
-			retval = BOOL_FALSE;
+			return BOOL_FALSE;
 		}
 	}
 
-	return retval;
+	return BOOL_TRUE;
 }
 
 

+ 161 - 55
klish/kscheme/kparam.c

@@ -5,35 +5,44 @@
 
 #include <faux/str.h>
 #include <faux/list.h>
+#include <klish/khelper.h>
+#include <klish/kptype.h>
 #include <klish/kparam.h>
 
 
 struct kparam_s {
-	bool_t is_static;
-	iparam_t info;
+	char *name;
+	char *help;
+	char *ptype_ref; // Text reference to PTYPE
+	kptype_t *ptype; // Resolved PARAM's PTYPE
 	faux_list_t *params; // Nested parameters
 };
 
+// Simple methods
 
-static int kparam_param_compare(const void *first, const void *second)
-{
-	const kparam_t *f = (const kparam_t *)first;
-	const kparam_t *s = (const kparam_t *)second;
+// Name
+KGET_STR(param, name);
+KSET_STR_ONCE(param, name);
 
-	return strcmp(kparam_name(f), kparam_name(s));
-}
+// Help
+KGET_STR(param, help);
+KSET_STR(param, help);
 
+// PTYPE reference (must be resolved later)
+KGET_STR(param, ptype_ref);
+KSET_STR(param, ptype_ref);
 
-static int kparam_param_kcompare(const void *key, const void *list_item)
-{
-	const char *f = (const char *)key;
-	const kparam_t *s = (const kparam_t *)list_item;
+// PTYPE (resolved)
+KGET(param, kptype_t *, ptype);
+KSET(param, kptype_t *, ptype);
 
-	return strcmp(f, kparam_name(s));
-}
+// PARAM list
+KCMP_NESTED_BY_KEY(param, param, name);
+KADD_NESTED(param, param);
+KFIND_NESTED(param, param);
 
 
-static kparam_t *kparam_new_internal(iparam_t info, bool_t is_static)
+static kparam_t *kparam_new_empty(void)
 {
 	kparam_t *param = NULL;
 
@@ -43,11 +52,13 @@ static kparam_t *kparam_new_internal(iparam_t info, bool_t is_static)
 		return NULL;
 
 	// Initialize
-	param->is_static = is_static;
-	param->info = info;
+	param->name = NULL;
+	param->help = NULL;
+	param->ptype_ref = NULL;
+	param->ptype = NULL;
 
 	param->params = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_UNIQUE,
-		kparam_param_compare, kparam_param_kcompare,
+		NULL, kparam_param_kcompare,
 		(void (*)(void *))kparam_free);
 	assert(param->params);
 
@@ -55,15 +66,27 @@ static kparam_t *kparam_new_internal(iparam_t info, bool_t is_static)
 }
 
 
-kparam_t *kparam_new(iparam_t info)
+kparam_t *kparam_new(const iparam_t *info, kparam_error_e *error)
 {
-	return kparam_new_internal(info, BOOL_FALSE);
-}
+	kparam_t *param = NULL;
 
+	param = kparam_new_empty();
+	assert(param);
+	if (!param) {
+		if (error)
+			*error = KPARAM_ERROR_ALLOC;
+		return NULL;
+	}
 
-kparam_t *kparam_new_static(iparam_t info)
-{
-	return kparam_new_internal(info, BOOL_TRUE);
+	if (!info)
+		return param;
+
+	if (!kparam_parse(param, info, error)) {
+		kparam_free(param);
+		return NULL;
+	}
+
+	return param;
 }
 
 
@@ -72,58 +95,141 @@ void kparam_free(kparam_t *param)
 	if (!param)
 		return;
 
-	if (!param->is_static) {
-		faux_str_free(param->info.name);
-		faux_str_free(param->info.help);
-		faux_str_free(param->info.ptype);
-	}
+	faux_str_free(param->name);
+	faux_str_free(param->help);
+	faux_str_free(param->ptype_ref);
 	faux_list_free(param->params);
 
 	faux_free(param);
 }
 
 
-const char *kparam_name(const kparam_t *param)
+const char *kparam_strerror(kparam_error_e error)
 {
-	assert(param);
-	if (!param)
-		return NULL;
+	const char *str = NULL;
+
+	switch (error) {
+	case KPARAM_ERROR_OK:
+		str = "Ok";
+		break;
+	case KPARAM_ERROR_INTERNAL:
+		str = "Internal error";
+		break;
+	case KPARAM_ERROR_ALLOC:
+		str = "Memory allocation error";
+		break;
+	case KPARAM_ERROR_ATTR_NAME:
+		str = "Illegal 'name' attribute";
+		break;
+	case KPARAM_ERROR_ATTR_HELP:
+		str = "Illegal 'help' attribute";
+		break;
+	case KPARAM_ERROR_ATTR_PTYPE:
+		str = "Illegal 'ptype' attribute";
+		break;
+	default:
+		str = "Unknown error";
+		break;
+	}
 
-	return param->info.name;
+	return str;
 }
 
 
-const char *kparam_help(const kparam_t *param)
+bool_t kparam_parse(kparam_t *param, const iparam_t *info, kparam_error_e *error)
 {
-	assert(param);
-	if (!param)
-		return NULL;
+	// Name [mandatory]
+	if (faux_str_is_empty(info->name)) {
+		if (error)
+			*error = KPARAM_ERROR_ATTR_NAME;
+		return BOOL_FALSE;
+	} else {
+		if (!kparam_set_name(param, info->name)) {
+			if (error)
+				*error = KPARAM_ERROR_ATTR_NAME;
+			return BOOL_FALSE;
+		}
+	}
 
-	return param->info.help;
+	// Help
+	if (!faux_str_is_empty(info->name)) {
+		if (!kparam_set_help(param, info->help)) {
+			if (error)
+				*error = KPARAM_ERROR_ATTR_HELP;
+			return BOOL_FALSE;
+		}
+	}
+
+	// PTYPE reference
+	if (!faux_str_is_empty(info->ptype)) {
+		if (!kparam_set_ptype_ref(param, info->ptype)) {
+			if (error)
+				*error = KPARAM_ERROR_ATTR_PTYPE;
+			return BOOL_FALSE;
+		}
+	}
+
+	return BOOL_TRUE;
 }
 
 
-const char *kparam_ptype_str(const kparam_t *param)
+bool_t kparam_nested_from_iparam(kparam_t *kparam, iparam_t *iparam,
+	faux_error_t *error_stack)
 {
-	assert(param);
-	if (!param)
-		return NULL;
+	bool_t retval = BOOL_TRUE;
+
+	if (!kparam || !iparam) {
+		faux_error_add(error_stack,
+			kparam_strerror(KPARAM_ERROR_INTERNAL));
+		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;
+printf("subparam\n");
+			nkparam = kparam_from_iparam(niparam, error_stack);
+			if (!nkparam) {
+				retval = BOOL_FALSE;
+				continue;
+			}
+		}
+	}
 
-	return param->info.ptype;
+	return retval;
 }
 
 
-bool_t kparam_add_param(kparam_t *param, kparam_t *nested_param)
+kparam_t *kparam_from_iparam(iparam_t *iparam, faux_error_t *error_stack)
 {
-	assert(param);
-	if (!param)
-		return BOOL_FALSE;
-	assert(nested_param);
-	if (!nested_param)
-		return BOOL_FALSE;
-
-	if (!faux_list_add(param->params, nested_param))
-		return BOOL_FALSE;
+	kparam_t *kparam = NULL;
+	kparam_error_e kparam_error = KPARAM_ERROR_OK;
+
+	kparam = kparam_new(iparam, &kparam_error);
+	if (!kparam) {
+		char *msg = NULL;
+		msg = faux_str_sprintf("PARAM \"%s\": %s",
+			iparam->name ? iparam->name : "(null)",
+			kparam_strerror(kparam_error));
+		faux_error_add(error_stack, msg);
+		faux_str_free(msg);
+		return NULL;
+	}
+	printf("param %s\n", kparam_name(kparam));
+
+	// Parse nested elements
+	if (!kparam_nested_from_iparam(kparam, iparam, error_stack)) {
+		char *msg = NULL;
+		msg = faux_str_sprintf("PARAM \"%s\": Illegal nested elements",
+			kparam_name(kparam));
+		faux_error_add(error_stack, msg);
+		faux_str_free(msg);
+		kparam_free(kparam);
+		return NULL;
+	}
 
-	return BOOL_TRUE;
+	return kparam;
 }

+ 4 - 6
klish/kscheme/kptype.c

@@ -111,18 +111,16 @@ const char *kptype_strerror(kptype_error_e error)
 
 bool_t kptype_parse(kptype_t *ptype, const iptype_t *info, kptype_error_e *error)
 {
-	bool_t retval = BOOL_TRUE;
-
 	// Name [mandatory]
 	if (faux_str_is_empty(info->name)) {
 		if (error)
 			*error = KPTYPE_ERROR_ATTR_NAME;
-		retval = BOOL_FALSE;
+		return BOOL_FALSE;
 	} else {
 		if (!kptype_set_name(ptype, info->name)) {
 			if (error)
 				*error = KPTYPE_ERROR_ATTR_NAME;
-			retval = BOOL_FALSE;
+			return BOOL_FALSE;
 		}
 	}
 
@@ -131,11 +129,11 @@ bool_t kptype_parse(kptype_t *ptype, const iptype_t *info, kptype_error_e *error
 		if (!kptype_set_help(ptype, info->help)) {
 			if (error)
 				*error = KPTYPE_ERROR_ATTR_HELP;
-			retval = BOOL_FALSE;
+			return BOOL_FALSE;
 		}
 	}
 
-	return retval;
+	return BOOL_TRUE;
 }
 
 

+ 3 - 5
klish/kscheme/kview.c

@@ -114,22 +114,20 @@ const char *kview_strerror(kview_error_e error)
 
 bool_t kview_parse(kview_t *view, const iview_t *info, kview_error_e *error)
 {
-	bool_t retval = BOOL_TRUE;
-
 	// Name [mandatory]
 	if (faux_str_is_empty(info->name)) {
 		if (error)
 			*error = KVIEW_ERROR_ATTR_NAME;
-		retval = BOOL_FALSE;
+		return BOOL_FALSE;
 	} else {
 		if (!kview_set_name(view, info->name)) {
 			if (error)
 				*error = KVIEW_ERROR_ATTR_NAME;
-			retval = BOOL_FALSE;
+			return BOOL_FALSE;
 		}
 	}
 
-	return retval;
+	return BOOL_TRUE;
 }