Browse Source

PTYPEs INT and UINT

Serj Kalichev 1 year ago
parent
commit
3c0b603d96
6 changed files with 149 additions and 13 deletions
  1. 3 0
      klish/kcontext.h
  2. 20 0
      klish/ksession/kcontext.c
  3. 1 1
      plugins/klish/nav.c
  4. 4 2
      plugins/klish/plugin_init.c
  5. 5 2
      plugins/klish/private.h
  6. 116 8
      plugins/klish/ptypes.c

+ 3 - 0
klish/kcontext.h

@@ -56,8 +56,11 @@ FAUX_HIDDEN bool_t kcontext_set_session(kcontext_t *context, ksession_t *session
 // Done
 bool_t kcontext_done(const kcontext_t *context);
 FAUX_HIDDEN bool_t kcontext_set_done(kcontext_t *context, bool_t done);
+
 // Wrappers
 kparg_t *kcontext_candidate_parg(const kcontext_t *context);
+const 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);
 const char *kcontext_script(const kcontext_t *context);
 

+ 20 - 0
klish/ksession/kcontext.c

@@ -144,6 +144,26 @@ kparg_t *kcontext_candidate_parg(const kcontext_t *context)
 }
 
 
+const kentry_t *kcontext_candidate_entry(const kcontext_t *context)
+{
+	assert(context);
+	if (!context)
+		return NULL;
+
+	return kparg_entry(kcontext_candidate_parg(context));
+}
+
+
+const char *kcontext_candidate_value(const kcontext_t *context)
+{
+	assert(context);
+	if (!context)
+		return NULL;
+
+	return kparg_value(kcontext_candidate_parg(context));
+}
+
+
 const kaction_t *kcontext_action(const kcontext_t *context)
 {
 	faux_list_node_t *node = NULL;

+ 1 - 1
plugins/klish/nav.c

@@ -46,7 +46,7 @@ int klish_nav(kcontext_t *context)
 	assert(kcontext_type(context) == KCONTEXT_ACTION);
 
 	script = kcontext_script(context);
-	if (!script) // No navigation commands. Probably it's not an error.
+	if (faux_str_is_empty(script)) // No navigation commands. It's not an error.
 		return 0;
 	session = kcontext_session(context);
 	assert(session);

+ 4 - 2
plugins/klish/plugin_init.c

@@ -43,8 +43,10 @@ int kplugin_klish_init(kcontext_t *context)
 		KSYM_USERDEFINED_PERMANENT, KSYM_SYNC));
 	kplugin_add_syms(plugin, ksym_new_ext("COMMAND_CASE", klish_ptype_COMMAND_CASE,
 		KSYM_USERDEFINED_PERMANENT, KSYM_SYNC));
-
-	context = context; // Happy compiler
+	kplugin_add_syms(plugin, ksym_new_ext("INT", klish_ptype_INT,
+		KSYM_USERDEFINED_PERMANENT, KSYM_SYNC));
+	kplugin_add_syms(plugin, ksym_new_ext("UINT", klish_ptype_UINT,
+		KSYM_USERDEFINED_PERMANENT, KSYM_SYNC));
 
 	return 0;
 }

+ 5 - 2
plugins/klish/private.h

@@ -15,12 +15,15 @@ C_DECL_BEGIN
 int klish_nop(kcontext_t *context);
 int klish_tsym(kcontext_t *context);
 
+// Navigation
+int klish_nav(kcontext_t *context);
+
 // PTYPEs
 int klish_ptype_COMMAND(kcontext_t *context);
 int klish_ptype_COMMAND_CASE(kcontext_t *context);
+int klish_ptype_INT(kcontext_t *context);
+int klish_ptype_UINT(kcontext_t *context);
 
-// Navigation
-int klish_nav(kcontext_t *context);
 
 C_DECL_END
 

+ 116 - 8
plugins/klish/ptypes.c

@@ -11,20 +11,23 @@
 
 #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: Consider ENTRY's name (or "value" field) as a command
+ *
+ */
 int klish_ptype_COMMAND(kcontext_t *context)
 {
-	kparg_t *parg = NULL;
 	const kentry_t *entry = NULL;
 	const char *value = NULL;
 	const char *command_name = NULL;
 
-	parg = kcontext_candidate_parg(context);
-	entry = kparg_entry(parg);
-	value = kparg_value(parg);
+	entry = kcontext_candidate_entry(context);
+	value = kcontext_candidate_value(context);
 
 	command_name = kentry_value(entry);
 	if (!command_name)
@@ -36,16 +39,17 @@ int klish_ptype_COMMAND(kcontext_t *context)
 }
 
 
+/** @brief PTYPE: ENTRY's name (or "value" field) as a case sensitive command
+ *
+ */
 int klish_ptype_COMMAND_CASE(kcontext_t *context)
 {
-	kparg_t *parg = NULL;
 	const kentry_t *entry = NULL;
 	const char *value = NULL;
 	const char *command_name = NULL;
 
-	parg = kcontext_candidate_parg(context);
-	entry = kparg_entry(parg);
-	value = kparg_value(parg);
+	entry = kcontext_candidate_entry(context);
+	value = kcontext_candidate_value(context);
 
 	command_name = kentry_value(entry);
 	if (!command_name)
@@ -55,3 +59,107 @@ int klish_ptype_COMMAND_CASE(kcontext_t *context)
 
 	return strcmp(value, command_name);
 }
+
+
+/** @brief 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 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;
+}