Serj Kalichev 1 år sedan
förälder
incheckning
287a0f90b7
2 ändrade filer med 68 tillägg och 34 borttagningar
  1. 11 9
      klish/kpargv.h
  2. 57 25
      klish/ksession/ksession_parse.c

+ 11 - 9
klish/kpargv.h

@@ -12,17 +12,19 @@
 
 
 typedef enum {
-	KPARSE_NONE,
-	KPARSE_OK,
-	KPARSE_INPROGRESS,
-	KPARSE_NOTFOUND,
-	KPARSE_INCOMPLETED,
-	KPARSE_ILLEGAL,
-	KPARSE_ERROR,
-	KPARSE_NOACTION,
-	KPARSE_MAX,
+	KPARSE_NONE = 0x00,
+	KPARSE_OK = 0x01,
+	KPARSE_INPROGRESS = 0x02,
+	KPARSE_NOTFOUND = 0x04,
+	KPARSE_INCOMPLETED = 0x08,
+	KPARSE_ILLEGAL = 0x10,
+	KPARSE_ERROR = 0x20,
+	KPARSE_NOACTION = 0x40,
+	KPARSE_MAX = 8,
 } kpargv_status_e;
 
+#define KPARSE_NOTFIT (KPARSE_NOTFOUND | KPARSE_INCOMPLETED)
+
 
 typedef enum {
 	KPURPOSE_NONE,

+ 57 - 25
klish/ksession/ksession_parse.c

@@ -72,8 +72,8 @@ static kpargv_status_e ksession_parse_arg(ksession_t *session,
 	faux_argv_node_t *saved_argv_iter = NULL;
 	kpargv_purpose_e purpose = KPURPOSE_NONE;
 
-fprintf(stderr, "PARSE: name=%s, ref=%s, arg=%s, pargs=%d\n",
-kentry_name(entry), kentry_ref_str(entry), faux_argv_current(*argv_iter),
+fprintf(stderr, "PARSE: name=%s, arg=%s, pargs=%d\n",
+kentry_name(entry), faux_argv_current(*argv_iter),
 kpargv_pargs_len(pargv));
 
 	assert(current_entry);
@@ -123,7 +123,7 @@ kpargv_pargs_len(pargv));
 				// That's time to add entry to completions list.
 				if (!kpargv_continuable(pargv))
 					kpargv_add_completions(pargv, entry);
-				return KPARSE_NOTFOUND;
+				return KPARSE_INCOMPLETED;
 			// Add entry to completions if it's last incompleted arg.
 			} else if (faux_argv_is_last(*argv_iter) &&
 				kpargv_continuable(pargv)) {
@@ -134,8 +134,8 @@ kpargv_pargs_len(pargv));
 
 		// If all arguments are resolved already then return INCOMPLETED
 		if (!*argv_iter)
-			return KPARSE_NOTFOUND;
-//			return KPARSE_INCOMPLETED;
+//			return KPARSE_NOTFOUND;
+			return KPARSE_INCOMPLETED;
 
 		// Validate argument
 		current_arg = faux_argv_current(*argv_iter);
@@ -157,6 +157,8 @@ kpargv_pargs_len(pargv));
 		}
 	}
 
+fprintf(stderr, "ITSELF: name=%s, retcode=%s\n", kentry_name(entry), kpargv_status_decode(retcode));
+
 	// ENTRY has no nested ENTRYs so return
 	if (kentry_entrys_is_empty(entry))
 		return retcode;
@@ -184,31 +186,38 @@ kpargv_pargs_len(pargv));
 		kentry_entrys_node_t *iter = kentry_entrys_iter(entry);
 		const kentry_t *nested = NULL;
 
+if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
+fprintf(stderr, "SWITCH: name=%s, arg %s\n", kentry_name(entry),
+*argv_iter ? faux_argv_current(*argv_iter) : "<empty>");
 		while ((nested = kentry_entrys_each(&iter))) {
 			kpargv_status_e res = KPARSE_NOTFOUND;
-//printf("SWITCH arg: %s, entry %s\n", *argv_iter ? faux_argv_current(*argv_iter) : "<empty>", kentry_name(nested));
 			// Ignore entries with non-COMMON purpose.
 			if (kentry_purpose(nested) != KENTRY_PURPOSE_COMMON)
 				continue;
+if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
+fprintf(stderr, "SWITCH-nested name=%s, nested=%s\n",
+kentry_name(entry), kentry_name(nested));
 			res = ksession_parse_arg(session, nested, argv_iter,
 				pargv, BOOL_FALSE, is_filter);
-//printf("%s\n", kpargv_status_decode(rc));
+if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
+fprintf(stderr, "SWITCH-nested-answer: name=%s, nested=%s, res=%s\n",
+kentry_name(entry), kentry_name(nested), kpargv_status_decode(res));
 			// If some arguments was consumed then we will not check
 			// next SWITCH's entries in any case.
 //			if (saved_argv_iter != *argv_iter)
 //				break;
-			// Try next entries if current status is NOTFOUND.
-			// The INCOMPLETED status is for completion list. In this
-			// case all next statuses will be INCOMPLETED too.
-//			if ((rc != KPARSE_NOTFOUND) && (rc != KPARSE_INCOMPLETED))
 			if ((res == KPARSE_INPROGRESS) && kentry_container(entry)) {
 				kparg_t *parg = kparg_new(entry, kentry_name(nested));
 				kpargv_add_pargs(pargv, parg);
 			}
-			if (res != KPARSE_NOTFOUND) {
+			// Try next entries if current status is NOTFOUND.
+			// The INCOMPLETED status is for completion list. In this
+			// case all next statuses will be INCOMPLETED too.
+//			if ((res != KPARSE_NOTFOUND) && (res != KPARSE_INCOMPLETED))
+			if (res != KPARSE_NOTFOUND)
 				rc = res;
+			if (!(res & KPARSE_NOTFIT))
 				break;
-			}
 		}
 
 	// SEQUENCE mode
@@ -222,6 +231,8 @@ kpargv_pargs_len(pargv));
 			kpargv_status_e res = KPARSE_NOTFOUND;
 			size_t num = 0;
 			size_t min = kentry_min(nested);
+			bool_t break_loop = BOOL_FALSE;
+			bool_t consumed = BOOL_FALSE;
 
 			// Ignore entries with non-COMMON purpose.
 			if (kentry_purpose(nested) != KENTRY_PURPOSE_COMMON)
@@ -229,20 +240,35 @@ kpargv_pargs_len(pargv));
 			// Filter out double parsing for optional entries.
 			if (kpargv_entry_exists(cur_level_pargv, nested))
 				continue;
-fprintf(stderr, "SEQ arg: %s, entry %s\n", *argv_iter ? faux_argv_current(*argv_iter) : "<empty>", kentry_name(nested));
+if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
+fprintf(stderr, "SEQ name=%s, arg=%s\n",
+kentry_name(entry), *argv_iter ? faux_argv_current(*argv_iter) : "<empty>");
 			// Try to match argument and current entry
 			// (from 'min' to 'max' times)
 			for (num = 0; num < kentry_max(nested); num++) {
 //				faux_argv_node_t *iter_before_parse = *argv_iter;
+if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
+fprintf(stderr, "SEQ-nested: name=%s, nested=%s\n",
+kentry_name(entry), kentry_name(nested));
 				res = ksession_parse_arg(session, nested,
 					argv_iter, pargv, BOOL_FALSE, is_filter);
-fprintf(stderr, "%s: %s\n", kentry_name(nested), kpargv_status_decode(res));
-				if (res != KPARSE_INPROGRESS)
+if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
+fprintf(stderr, "SEQ-nested-answer: name=%s, nested=%s, res=%s\n",
+kentry_name(entry), kentry_name(nested), kpargv_status_decode(res));
+				if (!(res & KPARSE_NOTFIT) || (num < min)) {
+					break_loop = BOOL_TRUE;
+					rc = res;
+				}
+				if (res == KPARSE_INPROGRESS)
+					consumed = BOOL_TRUE;
+				else
 					break;
 //				if (iter_before_parse == *argv_iter)
 //					break;
 			}
-			// All errors will break the loop
+			if (break_loop)
+				break;
+/*			// All errors will break the loop
 			if ((res != KPARSE_INPROGRESS) && (res != KPARSE_NOTFOUND)) {
 //			if ((KPARSE_ERROR == res) ||
 //				(KPARSE_ILLEGAL == res) ||
@@ -264,7 +290,7 @@ fprintf(stderr, "%s: %s\n", kentry_name(nested), kpargv_status_decode(res));
 			}
 			// It's not an error if optional parameter is absend
 //			rc = KPARSE_INPROGRESS;
-			if (res == KPARSE_INPROGRESS) {
+*/			if (consumed) {
 				kparg_t *tmp_parg = kparg_new(nested, NULL);
 				kpargv_add_pargs(cur_level_pargv, tmp_parg);
 				if (kentry_container(entry)) {
@@ -273,17 +299,22 @@ fprintf(stderr, "%s: %s\n", kentry_name(nested), kpargv_status_decode(res));
 					kpargv_add_pargs(pargv, parg);
 					rc = res;
 				}
+				// Mandatory or ordered parameter
+				if ((min > 0) || kentry_order(nested))
+					saved_iter = 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;
 			}
-			// Mandatory or ordered parameter
-			if ((min > 0) || kentry_order(nested))
-				saved_iter = iter;
 
 			// If optional entry is found then go back to nearest
 			// non-optional (or ordered) entry to try to find
 			// another optional entries.
-fprintf(stderr, "%s: min=%d, num=%d\n", kentry_name(nested), min, num);
-			if ((0 == min) && (num > 0))
-				iter = saved_iter;
+//fprintf(stderr, "%s: min=%d, num=%d\n", kentry_name(nested), min, num);
+//			if ((0 == min) && (num > 0))
+//				iter = saved_iter;
 		}
 		kpargv_free(cur_level_pargv);
 	}
@@ -295,7 +326,8 @@ fprintf(stderr, "%s: min=%d, num=%d\n", kentry_name(nested), min, num);
 //		((saved_argv_iter != *argv_iter) || !kentry_container(entry)))
 //		rc = KPARSE_ILLEGAL;
 
-fprintf(stderr, "Return %s: %s\n", kentry_name(entry), kpargv_status_decode(rc));
+if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
+fprintf(stderr, "RET: name=%s, rc=%s\n", kentry_name(entry), kpargv_status_decode(rc));
 	return rc;
 }