3 Commits b742f5d798 ... b6f9108206

Auteur SHA1 Message Date
  Serj Kalichev b6f9108206 plugin-klish: INT and UINT PTYPEs use lazy range parsing. il y a 4 mois
  Serj Kalichev e2794a087e plugin-klish: Store compiled regex within ACTION's udata. il y a 4 mois
  Serj Kalichev bb6f618181 Add user data to kaction_t structure. il y a 4 mois

+ 7 - 0
klish/kaction.h

@@ -30,6 +30,9 @@ typedef enum {
 } kaction_io_e;
 
 
+typedef void (*kaction_udata_free_fn)(void *data);
+
+
 C_DECL_BEGIN
 
 kaction_t *kaction_new(void);
@@ -74,6 +77,10 @@ tri_t kaction_sync(const kaction_t *action);
 bool_t kaction_set_sync(kaction_t *action, tri_t sync);
 bool_t kaction_is_sync(const kaction_t *action);
 
+void *kaction_udata(const kaction_t *action);
+bool_t kaction_set_udata(kaction_t *action, void *data,
+	kaction_udata_free_fn udata_free_fn);
+
 C_DECL_END
 
 #endif // _klish_kaction_h

+ 1 - 1
klish/kcontext.h

@@ -116,7 +116,7 @@ int kcontext_printf(const kcontext_t *context, const char *fmt, ...);
 kparg_t *kcontext_candidate_parg(const kcontext_t *context);
 kentry_t *kcontext_candidate_entry(const kcontext_t *context);
 const char *kcontext_candidate_value(const kcontext_t *context);
-const kaction_t *kcontext_action(const kcontext_t *context);
+kaction_t *kcontext_action(const kcontext_t *context);
 const char *kcontext_script(const kcontext_t *context);
 bool_t kcontext_named_udata_new(kcontext_t *context,
 	const char *name, void *data, kudata_data_free_fn free_fn);

+ 38 - 0
klish/kscheme/kaction.c

@@ -25,6 +25,8 @@ struct kaction_s {
 	tri_t permanent;
 	tri_t sync;
 	char *script;
+	void *udata;
+	kaction_udata_free_fn udata_free_fn;
 };
 
 
@@ -97,6 +99,8 @@ kaction_t *kaction_new(void)
 	action->script = NULL;
 	action->sym = NULL;
 	action->plugin = NULL;
+	action->udata = NULL;
+	action->udata_free_fn = NULL;
 
 	return action;
 }
@@ -110,6 +114,8 @@ void kaction_free(kaction_t *action)
 	faux_str_free(action->sym_ref);
 	faux_str_free(action->lock);
 	faux_str_free(action->script);
+	if (action->udata && action->udata_free_fn)
+		action->udata_free_fn(action->udata);
 
 	faux_free(action);
 }
@@ -189,3 +195,35 @@ bool_t kaction_is_sync(const kaction_t *action)
 
 	return BOOL_FALSE; // Default if not set
 }
+
+
+void *kaction_udata(const kaction_t *action)
+{
+	assert(action);
+	if (!action)
+		return NULL;
+
+	return action->udata;
+}
+
+
+bool_t kaction_set_udata(kaction_t *action, void *data,
+	kaction_udata_free_fn free_fn)
+{
+	assert(action);
+	if (!action)
+		return BOOL_FALSE;
+
+	// Free old udata value
+	if (action->udata) {
+		if (action->udata_free_fn)
+			action->udata_free_fn(action->udata);
+		else if (free_fn)
+			free_fn(action->udata);
+	}
+
+	action->udata = data;
+	action->udata_free_fn = free_fn;
+
+	return BOOL_TRUE;
+}

+ 2 - 2
klish/ksession/kcontext.c

@@ -230,7 +230,7 @@ const char *kcontext_candidate_value(const kcontext_t *context)
 }
 
 
-const kaction_t *kcontext_action(const kcontext_t *context)
+kaction_t *kcontext_action(const kcontext_t *context)
 {
 	faux_list_node_t *node = NULL;
 
@@ -242,7 +242,7 @@ const kaction_t *kcontext_action(const kcontext_t *context)
 	if (!node)
 		return NULL;
 
-	return (const kaction_t *)faux_list_data(node);
+	return (kaction_t *)faux_list_data(node);
 }
 
 

+ 1 - 1
plugins/klish/Makefile.am

@@ -9,8 +9,8 @@ libklish_plugin_klish_la_SOURCES += \
 	plugins/klish/private.h \
 	plugins/klish/plugin_init.c \
 	plugins/klish/ptype_command.c \
+	plugins/klish/ptype_int.c \
 	plugins/klish/ptype_string.c \
-	plugins/klish/ptypes.c \
 	plugins/klish/misc.c \
 	plugins/klish/nav.c \
 	plugins/klish/log.c

+ 206 - 0
plugins/klish/ptype_int.c

@@ -0,0 +1,206 @@
+/*
+ * Implementation of standard PTYPEs
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <faux/str.h>
+#include <faux/list.h>
+#include <faux/conv.h>
+#include <faux/argv.h>
+#include <klish/kcontext.h>
+#include <klish/kentry.h>
+
+
+typedef struct {
+	bool_t is_range;
+	long long int min;
+	long long int max;
+} klish_ptype_INT_t;
+
+typedef struct {
+	bool_t is_range;
+	unsigned long long int min;
+	unsigned long long int max;
+} klish_ptype_UINT_t;
+
+
+klish_ptype_INT_t *klish_ptype_INT_init(kaction_t *action)
+{
+	klish_ptype_INT_t *udata = NULL;
+	const char *line = NULL;
+	faux_argv_t *argv = NULL;
+
+	udata = faux_malloc(sizeof(*udata));
+	assert(udata);
+	if (!udata)
+		return NULL;
+
+	line = kaction_script(action);
+
+	if (faux_str_is_empty(line)) {
+		udata->is_range = BOOL_FALSE;
+
+	} else {
+		const char *str = NULL;
+
+		udata->is_range = BOOL_TRUE;
+
+		argv = faux_argv_new();
+		faux_argv_parse(argv, line);
+		if (faux_argv_len(argv) < 2)
+			goto err;
+
+		// Min
+		str = faux_argv_index(argv, 0);
+		if (!faux_conv_atoll(str, &udata->min, 0))
+			goto err;
+
+		// Max
+		str = faux_argv_index(argv, 1);
+		if (!faux_conv_atoll(str, &udata->max, 0))
+			goto err;
+
+		faux_argv_free(argv);
+	}
+
+	kaction_set_udata(action, udata, faux_free);
+
+	return udata;
+
+err:
+	faux_argv_free(argv);
+	faux_free(udata);
+
+	return NULL;
+}
+
+
+/** @brief PTYPE: Signed int with optional range
+ *
+ * Use long long int for conversion from text.
+ *
+ * <ACTION sym="INT">-30 80</ACTION>
+ * Means range from "-30" to "80"
+ */
+int klish_ptype_INT(kcontext_t *context)
+{
+	kaction_t *action = NULL;
+	klish_ptype_INT_t *udata = NULL;
+	const char *value_str = NULL;
+	long long int value = 0;
+
+	value_str = kcontext_candidate_value(context);
+
+	if (!faux_conv_atoll(value_str, &value, 0))
+		return -1;
+
+	action = kcontext_action(context);
+	udata = (klish_ptype_INT_t *)kaction_udata(action);
+	if (!udata) {
+		udata = klish_ptype_INT_init(action);
+		if (!udata)
+			return -1;
+	}
+
+	if (!udata->is_range)
+		return 0;
+
+	if (value < udata->min || value > udata->max)
+		return -1;
+
+	return 0;
+}
+
+
+klish_ptype_UINT_t *klish_ptype_UINT_init(kaction_t *action)
+{
+	klish_ptype_UINT_t *udata = NULL;
+	const char *line = NULL;
+	faux_argv_t *argv = NULL;
+
+	udata = faux_malloc(sizeof(*udata));
+	assert(udata);
+	if (!udata)
+		return NULL;
+
+	line = kaction_script(action);
+
+	if (faux_str_is_empty(line)) {
+		udata->is_range = BOOL_FALSE;
+
+	} else {
+		const char *str = NULL;
+
+		udata->is_range = BOOL_TRUE;
+
+		argv = faux_argv_new();
+		faux_argv_parse(argv, line);
+		if (faux_argv_len(argv) < 2)
+			goto err;
+
+		// Min
+		str = faux_argv_index(argv, 0);
+		if (!faux_conv_atoull(str, &udata->min, 0))
+			goto err;
+
+		// Max
+		str = faux_argv_index(argv, 1);
+		if (!faux_conv_atoull(str, &udata->max, 0))
+			goto err;
+
+		faux_argv_free(argv);
+	}
+
+	kaction_set_udata(action, udata, faux_free);
+
+	return udata;
+
+err:
+	faux_argv_free(argv);
+	faux_free(udata);
+
+	return NULL;
+}
+
+
+/** @brief PTYPE: Unsigned int with optional range
+ *
+ * Use unsigned long long int for conversion from text.
+ *
+ * <ACTION sym="UINT">30 80</ACTION>
+ * Means range from "30" to "80"
+ */
+int klish_ptype_UINT(kcontext_t *context)
+{
+	kaction_t *action = NULL;
+	klish_ptype_UINT_t *udata = NULL;
+	const char *value_str = NULL;
+	unsigned long long int value = 0;
+
+	value_str = kcontext_candidate_value(context);
+
+	if (!faux_conv_atoull(value_str, &value, 0))
+		return -1;
+
+	action = kcontext_action(context);
+	udata = (klish_ptype_UINT_t *)kaction_udata(action);
+	if (!udata) {
+		udata = klish_ptype_UINT_init(action);
+		if (!udata)
+			return -1;
+	}
+
+	if (!udata->is_range)
+		return 0;
+
+	if (value < udata->min || value > udata->max)
+		return -1;
+
+	return 0;
+}

+ 11 - 9
plugins/klish/ptype_string.c

@@ -38,16 +38,18 @@ static void klish_ptype_STRING_free(void *data)
 }
 
 
-klish_ptype_STRING_t *klish_ptype_STRING_init(kentry_t *entry,
-	const char *pattern)
+klish_ptype_STRING_t *klish_ptype_STRING_init(kaction_t *action)
 {
 	klish_ptype_STRING_t *udata = NULL;
+	const char *pattern = NULL;
 
 	udata = faux_malloc(sizeof(*udata));
 	assert(udata);
 	if (!udata)
 		return NULL;
 
+	pattern = kaction_script(action);
+
 	if (faux_str_is_empty(pattern)) {
 		udata->is_regex = BOOL_FALSE;
 	} else {
@@ -60,27 +62,27 @@ klish_ptype_STRING_t *klish_ptype_STRING_init(kentry_t *entry,
 		}
 	}
 
-	kentry_set_udata(entry, udata, klish_ptype_STRING_free);
+	kaction_set_udata(action, udata, klish_ptype_STRING_free);
 
 	return udata;
 }
 
-/** @brief PTYPE: Arbitrary string
+
+/** @brief PTYPE: String
  */
 int klish_ptype_STRING(kcontext_t *context)
 {
-	kentry_t *entry = NULL;
+	kaction_t *action = NULL;
 	const char *value = NULL;
 	klish_ptype_STRING_t *udata = NULL;
 	size_t len = 0;
 
-	entry = kcontext_candidate_entry(context);
+	action = kcontext_action(context);
 	value = kcontext_candidate_value(context);
 
-	udata = (klish_ptype_STRING_t *)kentry_udata(entry);
+	udata = (klish_ptype_STRING_t *)kaction_udata(action);
 	if (!udata) {
-		const char *pattern = kcontext_script(context);
-		udata = klish_ptype_STRING_init(entry, pattern);
+		udata = klish_ptype_STRING_init(action);
 		if (!udata)
 			return -1;
 	}

+ 0 - 121
plugins/klish/ptypes.c

@@ -1,121 +0,0 @@
-/*
- * Implementation of standard PTYPEs
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <faux/str.h>
-#include <faux/list.h>
-#include <faux/conv.h>
-#include <faux/argv.h>
-#include <klish/kcontext.h>
-#include <klish/kentry.h>
-
-
-/** @brief PTYPE: Signed int with optional range
- *
- * Use long long int for conversion from text.
- *
- * <ACTION sym="INT">-30 80</ACTION>
- * Means range from "-30" to "80"
- */
-int klish_ptype_INT(kcontext_t *context)
-{
-	const char *script = NULL;
-	const char *value_str = NULL;
-	long long int value = 0;
-
-	script = kcontext_script(context);
-	value_str = kcontext_candidate_value(context);
-
-	if (!faux_conv_atoll(value_str, &value, 0))
-		return -1;
-
-	// Range is specified
-	if (!faux_str_is_empty(script)) {
-		faux_argv_t *argv = faux_argv_new();
-		const char *str = NULL;
-		faux_argv_parse(argv, script);
-
-		// Min
-		str = faux_argv_index(argv, 0);
-		if (str) {
-			long long int min = 0;
-			if (!faux_conv_atoll(str, &min, 0) || (value < min)) {
-				faux_argv_free(argv);
-				return -1;
-			}
-		}
-
-		// Max
-		str = faux_argv_index(argv, 1);
-		if (str) {
-			long long int max = 0;
-			if (!faux_conv_atoll(str, &max, 0) || (value > max)) {
-				faux_argv_free(argv);
-				return -1;
-			}
-		}
-
-		faux_argv_free(argv);
-	}
-
-	return 0;
-}
-
-
-/** @brief PTYPE: Unsigned int with optional range
- *
- * Use unsigned long long int for conversion from text.
- *
- * <ACTION sym="UINT">30 80</ACTION>
- * Means range from "30" to "80"
- */
-int klish_ptype_UINT(kcontext_t *context)
-{
-	const char *script = NULL;
-	const char *value_str = NULL;
-	unsigned long long int value = 0;
-
-	script = kcontext_script(context);
-	value_str = kcontext_candidate_value(context);
-
-	if (!faux_conv_atoull(value_str, &value, 0))
-		return -1;
-
-	// Range is specified
-	if (!faux_str_is_empty(script)) {
-		faux_argv_t *argv = faux_argv_new();
-		const char *str = NULL;
-		faux_argv_parse(argv, script);
-
-		// Min
-		str = faux_argv_index(argv, 0);
-		if (str) {
-			unsigned long long int min = 0;
-			if (!faux_conv_atoull(str, &min, 0) || (value < min)) {
-				faux_argv_free(argv);
-				return -1;
-			}
-		}
-
-		// Max
-		str = faux_argv_index(argv, 1);
-		if (str) {
-			unsigned long long int max = 0;
-			if (!faux_conv_atoull(str, &max, 0) || (value > max)) {
-				faux_argv_free(argv);
-				return -1;
-			}
-		}
-
-		faux_argv_free(argv);
-	}
-
-	return 0;
-}