|
@@ -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;
|
|
|
}
|