Browse Source

kentry: Fix 'order' field

Serj Kalichev 2 years ago
parent
commit
43349ee8cf
6 changed files with 42 additions and 5 deletions
  1. 11 1
      bin/klishd/klishd.c
  2. 1 0
      klish/ientry.h
  3. 11 0
      klish/ischeme/ientry.c
  4. 2 0
      klish/kpargv.h
  5. 15 4
      klish/ksession/ksession_parse.c
  6. 2 0
      klish/xml-helper/load.c

+ 11 - 1
bin/klishd/klishd.c

@@ -40,6 +40,7 @@
 #include <klish/kcontext.h>
 #include <klish/ksession.h>
 #include <klish/kdb.h>
+#include <klish/kpargv.h>
 
 #include "private.h"
 
@@ -177,8 +178,10 @@ int main(int argc, char **argv)
 	{
 	kparse_status_e pstatus = KPARSE_NONE;
 	char *s = NULL;
-	const char *line = "cmd m8 e1";
+	const char *line = "cmd o4 o3 o5 m8 e1";
 	kpargv_t *pargv = NULL;
+	kpargv_pargs_node_t *p_iter = NULL;
+	
 	session = ksession_new(scheme, NULL);
 	pstatus = ksession_parse_line(session, line, &pargv);
 	switch (pstatus) {
@@ -205,6 +208,13 @@ int main(int argc, char **argv)
 		break;
 	}
 	printf("Line '%s': %s\n", line, s);
+
+	kparg_t *parg = NULL;
+	p_iter = kpargv_pargs_iter(pargv);
+	while ((parg = kpargv_pargs_each(&p_iter))) {
+		printf("%s(%s) ", kparg_value(parg), kentry_name(kparg_entry(parg)));
+	}
+	printf("\n");
 	}
 
 goto err; // Test purposes

+ 1 - 0
klish/ientry.h

@@ -23,6 +23,7 @@ struct ientry_s {
 	char *ref;
 	char *value;
 	char *restore;
+	char *order;
 	ientry_t * (*entrys)[]; // Nested entrys
 	iaction_t * (*actions)[];
 };

+ 11 - 0
klish/ischeme/ientry.c

@@ -110,6 +110,16 @@ bool_t ientry_parse(const ientry_t *info, kentry_t *entry, faux_error_t *error)
 		}
 	}
 
+	// Order
+	if (!faux_str_is_empty(info->order)) {
+		bool_t b = BOOL_FALSE;
+		if (!faux_conv_str2bool(info->order, &b) ||
+			!kentry_set_order(entry, b)) {
+			faux_error_add(error, TAG": Illegal 'order' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
 	return retcode;
 }
 
@@ -292,6 +302,7 @@ char *ientry_deploy(const kentry_t *kentry, int level)
 		attr2ctext(&str, "ptype", kentry_ptype_str(kentry), level + 1);
 		attr2ctext(&str, "value", kentry_value(kentry), level + 1);
 		attr2ctext(&str, "restore", faux_conv_bool2str(kentry_restore(kentry)), level + 1);
+		attr2ctext(&str, "order", faux_conv_bool2str(kentry_order(kentry)), level + 1);
 
 		// ENTRY list
 		entrys_iter = kentry_entrys_iter(kentry);

+ 2 - 0
klish/kpargv.h

@@ -35,6 +35,8 @@ faux_list_t *kpargv_pargs(const kpargv_t *pargv);
 ssize_t kpargv_pargs_len(const kpargv_t *pargv);
 bool_t kpargv_pargs_is_empty(const kpargv_t *pargv);
 bool_t kpargv_add_parg(kpargv_t *pargv, kparg_t *parg);
+kpargv_pargs_node_t *kpargv_pargs_iter(const kpargv_t *pargv);
+kparg_t *kpargv_pargs_each(kpargv_pargs_node_t **iter);
 kparg_t *kpargv_pargs_last(const kpargv_t *pargv);
 kparg_t *kpargv_entry_exists(const kpargv_t *pargv, const void *entry);
 

+ 15 - 4
klish/ksession/ksession_parse.c

@@ -108,19 +108,26 @@ static kparse_status_e ksession_parse_arg(kentry_t *current_entry,
 		while ((nested = kentry_entrys_each(&iter))) {
 			kparse_status_e nrc = KPARSE_NOTFOUND;
 			size_t num = 0;
+			size_t min = kentry_min(nested);
+
+printf("Arg: %s, entry %s\n", faux_argv_current(*argv_iter), kentry_name(nested));
+			// Filter out double parsing for optional entries.
 			if (kpargv_entry_exists(pargv, nested))
 				continue;
+			// Try to match argument and current entry
+			// (from 'min' to 'max' times)
 			for (num = 0; num < kentry_max(nested); num++) {
 				nrc = ksession_parse_arg(nested, argv_iter, pargv);
 				if (nrc != KPARSE_INPROGRESS)
 					break;
 			}
+			// All errors will break the loop
 			if ((nrc != KPARSE_INPROGRESS) && (nrc != KPARSE_NOTFOUND)) {
 				rc = nrc;
 				break;
 			}
 			// Not found all mandatory instances (NOTFOUND)
-			if (num < kentry_min(nested)) {
+			if (num < min) {
 				rc = KPARSE_NOTFOUND;
 				break;
 			}
@@ -128,10 +135,14 @@ static kparse_status_e ksession_parse_arg(kentry_t *current_entry,
 			rc = KPARSE_INPROGRESS;
 
 			// Mandatory or ordered parameter
-			if ((kentry_min(nested) > 0) ||
-				kentry_order(nested))
+			if ((min > 0) || kentry_order(nested))
 				saved_iter = iter;
-			iter = saved_iter;
+
+			// If optional entry is found then go back to nearest
+			// non-optional (or ordered) entry to try to find
+			// another optional entries.
+			if ((0 == min) && (num > 0))
+				iter = saved_iter;
 		}
 	
 	}

+ 2 - 0
klish/xml-helper/load.c

@@ -727,6 +727,7 @@ static bool_t process_entry(const kxml_node_t *element, void *parent,
 	ientry.ref = kxml_node_attr(element, "ref");
 	ientry.value = kxml_node_attr(element, "value");
 	ientry.restore = kxml_node_attr(element, "restore");
+	ientry.order = kxml_node_attr(element, "order");
 
 	// Parent must be a KLISH or ENTRY tag
 	if ((parent_tag != KTAG_KLISH) && (parent_tag != KTAG_ENTRY)) {
@@ -796,6 +797,7 @@ err:
 	kxml_node_attr_free(ientry.ref);
 	kxml_node_attr_free(ientry.value);
 	kxml_node_attr_free(ientry.restore);
+	kxml_node_attr_free(ientry.order);
 
 	return res;
 }