Browse Source

ptype: Untested ACTION for PTYPEs

Serj Kalichev 4 years ago
parent
commit
1590374975
5 changed files with 83 additions and 2 deletions
  1. 1 0
      clish/pargv/private.h
  2. 1 0
      clish/ptype.h
  3. 9 0
      clish/ptype/ptype.c
  4. 1 0
      clish/shell/shell_execute.c
  5. 71 2
      clish/shell/shell_parse.c

+ 1 - 0
clish/pargv/private.h

@@ -9,6 +9,7 @@ struct clish_parg_s {
 	const clish_param_t *param;
 	char *value;
 };
+
 struct clish_pargv_s {
 	unsigned pargc;
 	clish_parg_t **pargv;

+ 1 - 0
clish/ptype.h

@@ -90,6 +90,7 @@ _CLISH_GET_STR(ptype, text);
 _CLISH_SET_ONCE(ptype, clish_ptype_preprocess_e, preprocess);
 _CLISH_GET_STR(ptype, range);
 _CLISH_GET(ptype, clish_action_t *, action);
+_CLISH_GET(ptype, clish_ptype_method_e, method);
 
 void clish_ptype__set_pattern(clish_ptype_t * instance,
 	const char *pattern, clish_ptype_method_e method);

+ 9 - 0
clish/ptype/ptype.c

@@ -190,6 +190,10 @@ static void clish_ptype__set_range(clish_ptype_t * this)
 		break;
 	}
 	/*------------------------------------------------- */
+	case CLISH_PTYPE_METHOD_CODE:
+		// Nothing to do
+		break;
+	/*------------------------------------------------- */
 	default:
 		break;
 	/*------------------------------------------------- */
@@ -453,6 +457,7 @@ CLISH_GET_STR(ptype, text);
 CLISH_SET_ONCE(ptype, clish_ptype_preprocess_e, preprocess);
 CLISH_GET_STR(ptype, range);
 CLISH_GET(ptype, clish_action_t *, action);
+CLISH_GET(ptype, clish_ptype_method_e, method);
 
 /*--------------------------------------------------------- */
 void clish_ptype__set_pattern(clish_ptype_t * this,
@@ -500,6 +505,10 @@ void clish_ptype__set_pattern(clish_ptype_t * this,
 		this->u.select.items = lub_argv_new(this->pattern, 0);
 		break;
 	/*------------------------------------------------- */
+	case CLISH_PTYPE_METHOD_CODE:
+		// Nothing to do
+		break;
+	/*------------------------------------------------- */
 	default:
 		break;
 	}

+ 1 - 0
clish/shell/shell_execute.c

@@ -434,6 +434,7 @@ char *clish_shell_mkfifo(clish_shell_t * this, char *name, size_t n)
 /*----------------------------------------------------------- */
 int clish_shell_rmfifo(clish_shell_t * this, const char *name)
 {
+	this = this; // Happy compiler
 	return unlink(name);
 }
 

+ 71 - 2
clish/shell/shell_parse.c

@@ -9,6 +9,72 @@
 #include "lub/system.h"
 #include "private.h"
 
+
+/*----------------------------------------------------------- */
+/* The standard clish_param_validate() is not enough when PTYPE can
+ * contain ACTION. So we need context etc. to really validate param.
+ */
+static char *clish_shell_param_validate(const clish_param_t *param, const char *text,
+	clish_context_t *context)
+{
+	clish_ptype_t *ptype = NULL;
+	clish_ptype_method_e method = CLISH_PTYPE_METHOD_MAX;
+	char *out = NULL;
+	clish_context_t ctx = {};
+	clish_pargv_t *pargv = NULL;
+	clish_param_t *value_param = NULL;
+	int retval = 0;
+
+	assert(param);
+	assert(context);
+	if (!param || !context)
+		return NULL;
+
+	ptype = clish_param__get_ptype(param);
+	assert(ptype);
+	if (!ptype)
+		return NULL;
+	method = clish_ptype__get_method(ptype);
+
+	// Check is it common non-code PTYPE
+	if (method != CLISH_PTYPE_METHOD_CODE)
+		return clish_param_validate(param, text);
+
+	// Prepare dummy pargv structure to provide 'value' parameter to the
+	// ACTION script. This parameter contain current value to check.
+	value_param = clish_param_new("value", "Dummy param for PTYPE's ACTION",
+		clish_param__get_ptype_name(param));
+	assert(value_param);
+	if (!value_param)
+		return NULL;
+	clish_param__set_ptype(value_param, ptype);
+	pargv = clish_pargv_new(); // Dummy pargv
+	assert(pargv);
+	if (!pargv)
+		return NULL;
+	clish_pargv_insert(pargv, value_param, text);
+
+	// Prepare context for ACTION execution
+	clish_context_dup(&ctx, context);
+	clish_context__set_action(&ctx, clish_ptype__get_action(ptype));
+	clish_context__set_pargv(&ctx, pargv);
+
+	// Try to execute ACTION
+	retval = clish_shell_exec_action(&ctx, &out);
+	// Cleanup dummy structures
+	clish_pargv_delete(pargv);
+	clish_param_delete(value_param);
+
+	if (retval) {
+		lub_string_free(out);
+		return NULL; // Fail on bad ACTION retval
+	}
+	if (out)
+		return out;
+
+	return lub_string_dup(text);
+}
+
 /*----------------------------------------------------------- */
 clish_pargv_status_e clish_shell_parse(
 	clish_shell_t *this, const char *line,
@@ -181,7 +247,9 @@ clish_pargv_status_e clish_shell_parse_pargv(clish_pargv_t *pargv,
 					if (!line_test(cparam, context))
 						continue;
 					if ((validated = arg ?
-						clish_param_validate(cparam, arg) : NULL)) {
+						clish_shell_param_validate(
+							cparam, arg, context) :
+							NULL)) {
 						rec_paramv = clish_param__get_paramv(cparam);
 						rec_paramc = clish_param__get_param_count(cparam);
 						break;
@@ -189,7 +257,8 @@ clish_pargv_status_e clish_shell_parse_pargv(clish_pargv_t *pargv,
 				}
 			} else {
 				validated = arg ?
-					clish_param_validate(param, arg) : NULL;
+					clish_shell_param_validate(
+						param, arg, context) : NULL;
 			}
 
 			if (validated) {