Browse Source

Find commands within all path levels

Serj Kalichev 2 years ago
parent
commit
29baf546ba
4 changed files with 40 additions and 12 deletions
  1. 10 7
      bin/klishd/klishd.c
  2. 2 0
      klish/kpath.h
  3. 15 0
      klish/ksession/kpath.c
  4. 13 5
      klish/ksession/ksession_parse.c

+ 10 - 7
bin/klishd/klishd.c

@@ -178,11 +178,12 @@ int main(int argc, char **argv)
 	{
 	kparse_status_e pstatus = KPARSE_NONE;
 	char *s = NULL;
-	const char *line = "cmd o5 m8 o2";
+	const char *line = "cmd1 o1 m7 o2 e1";
 	kpargv_t *pargv = NULL;
 	kpargv_pargs_node_t *p_iter = NULL;
 	
-	session = ksession_new(scheme, NULL);
+	session = ksession_new(scheme, "/lowview");
+	kpath_push(ksession_path(session), klevel_new(kscheme_find_entry_by_path(scheme, "/main")));
 	pstatus = ksession_parse_line(session, line, &pargv);
 	switch (pstatus) {
 	case KPARSE_NONE:
@@ -209,12 +210,14 @@ int main(int argc, char **argv)
 	}
 	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)));
+	if (pargv) {
+		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");
 	}
-	printf("\n");
 	
 	kpargv_free(pargv);
 	ksession_free(session);

+ 2 - 0
klish/kpath.h

@@ -34,6 +34,8 @@ size_t kpath_is_empty(const kpath_t *path);
 bool_t kpath_push(kpath_t *path, klevel_t *level);
 bool_t kpath_pop(kpath_t *path);
 klevel_t *kpath_current(const kpath_t *path);
+kpath_levels_node_t *kpath_iterr(const kpath_t *path);
+klevel_t *kpath_eachr(kpath_levels_node_t **iterr);
 
 C_DECL_END
 

+ 15 - 0
klish/ksession/kpath.c

@@ -101,3 +101,18 @@ klevel_t *kpath_current(const kpath_t *path)
 
 	return (klevel_t *)faux_list_data(faux_list_tail(path->levels));
 }
+
+
+kpath_levels_node_t *kpath_iterr(const kpath_t *path)
+{
+	assert(path);
+	if (!path)
+		return NULL;
+	return (kpath_levels_node_t *)faux_list_tail(path->levels);
+}
+
+
+klevel_t *kpath_eachr(kpath_levels_node_t **iterr)
+{
+	return (klevel_t *)faux_list_eachr((faux_list_node_t **)iterr);
+}

+ 13 - 5
klish/ksession/ksession_parse.c

@@ -161,9 +161,10 @@ kparse_status_e ksession_parse_line(ksession_t *session, const char *line,
 {
 	faux_argv_t *argv = NULL;
 	faux_argv_node_t *argv_iter = NULL;
-	kentry_t *current_entry = NULL;
 	kpargv_t *pargv = NULL;
 	kparse_status_e pstatus = KPARSE_NONE;
+	kpath_levels_node_t *levels_iterr = NULL;
+	klevel_t *level = NULL;
 
 	if (parsed_argv)
 		*parsed_argv = NULL;
@@ -185,11 +186,17 @@ kparse_status_e ksession_parse_line(ksession_t *session, const char *line,
 	}
 	argv_iter = faux_argv_iter(argv);
 
-	current_entry = klevel_entry(kpath_current(ksession_path(session)));
 	pargv = kpargv_new();
 	assert(pargv);
-
-	pstatus = ksession_parse_arg(current_entry, &argv_iter, pargv);
+	// Iterate levels of path from higher to lower. Note the reversed
+	// iterator will be used.
+	levels_iterr = kpath_iterr(ksession_path(session));
+	while ((level = kpath_eachr(&levels_iterr))) {
+		kentry_t *current_entry = klevel_entry(level);
+		pstatus = ksession_parse_arg(current_entry, &argv_iter, pargv);
+		if (pstatus != KPARSE_NOTFOUND)
+			break;
+	}
 	// It's a higher level of parsing, so some statuses can have different
 	// meanings
 	if (KPARSE_NONE == pstatus)
@@ -199,7 +206,8 @@ kparse_status_e ksession_parse_line(ksession_t *session, const char *line,
 			pstatus = KPARSE_OK;
 		else
 			pstatus = KPARSE_ILLEGAL; // Additional not parsable args
-	}
+	} else if (KPARSE_NOTFOUND == pstatus)
+			pstatus = KPARSE_ILLEGAL; // Unknown command
 
 	if (kpargv_pargs_is_empty(pargv)) {
 		kpargv_free(pargv);