Browse Source

scheme: KSET_STR_ONCE can get two equal values more than once

Serj Kalichev 3 years ago
parent
commit
b63efd7076
5 changed files with 82 additions and 29 deletions
  1. 1 1
      bin/klishd/klishd.c
  2. 7 1
      klish/khelper.h
  3. 69 7
      klish/kscheme/ischeme.c
  4. 1 1
      klish/kscheme/kptype.c
  5. 4 19
      klish/kscheme/kview.c

+ 1 - 1
bin/klishd/klishd.c

@@ -170,7 +170,7 @@ int main(int argc, char **argv)
 	{
 	faux_error_t *error = faux_error_new();
 	scheme = kscheme_from_ischeme(&sch, error);
-	if (faux_error(error)) {
+	if (!scheme) {
 		fprintf(stderr, "Scheme errors:\n");
 		faux_error_print(error);
 		goto err;

+ 7 - 1
klish/khelper.h

@@ -61,7 +61,13 @@
 #define KSET_STR_ONCE(obj, name) \
 	_KSET_STR_ONCE(obj, name) { \
 		assert(inst); \
-		assert(!inst->name); \
+		if (inst->name) { \
+			if (NULL == val) \
+				return BOOL_FALSE; \
+			if (strcmp(inst->name, val) == 0) \
+				return BOOL_TRUE; \
+			return BOOL_FALSE; \
+		} \
 		inst->name = faux_str_dup(val); \
 		return BOOL_TRUE; \
 	}

+ 69 - 7
klish/kscheme/ischeme.c

@@ -142,6 +142,8 @@ kptype_t *kptype_from_iptype(iptype_t *iptype, faux_error_t *error_stack)
 bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
 	faux_error_t *error_stack)
 {
+	bool_t retval = BOOL_TRUE;
+
 	if (!kscheme || !ischeme) {
 		if (error_stack)
 			faux_error_add(error_stack,
@@ -157,27 +159,84 @@ bool_t kscheme_nested_from_ischeme(kscheme_t *kscheme, ischeme_t *ischeme,
 			iptype_t *iptype = *p_iptype;
 
 			kptype = kptype_from_iptype(iptype, error_stack);
-			if (!kptype)
+			if (!kptype) {
+				retval = BOOL_FALSE; // Don't stop
 				continue;
-			kscheme_add_ptype(kscheme, kptype);
+			}
+			if (!kscheme_add_ptype(kscheme, kptype)) {
+				if (error_stack) {
+					char *msg = NULL;
+					// Search for PTYPE duplicates
+					if (kscheme_find_ptype(kscheme,
+						kptype_name(kptype))) {
+						msg = faux_str_sprintf("SCHEME: "
+							"Can't add duplicate PTYPE "
+							"\"%s\"",
+							kptype_name(kptype));
+					} else {
+						msg = faux_str_sprintf("SCHEME: "
+							"Can't add PTYPE \"%s\"",
+							kptype_name(kptype));
+					}
+					faux_error_add(error_stack, msg);
+					faux_str_free(msg);
+				}
+				retval = BOOL_FALSE;
+			}
 		}
 	}
 
 	// VIEW list
+	// VIEW entries can be duplicate. Duplicated entries will add nested
+	// elements to existent VIEW. Also it can overwrite VIEW attributes.
+	// So there is no special rule which attribute value will be "on top".
+	// It's a random. Technically later VIEW entries will rewrite previous
+	// values.
 	if (ischeme->views) {
 		iview_t **p_iview = NULL;
 		for (p_iview = *ischeme->views; *p_iview; p_iview++) {
 			kview_t *kview = NULL;
 			iview_t *iview = *p_iview;
+			const char *view_name = iview->name;
 
-			kview = kview_from_iview(iview, error_stack);
-			if (!kview)
+			if (view_name)
+				kview = kscheme_find_view(kscheme, view_name);
+			if (kview) {
+				kview_error_e kview_error = KVIEW_ERROR_OK;
+				if (!kview_parse(kview, iview, &kview_error)) {
+					char *msg = faux_str_sprintf("VIEW \"%s\": %s",
+						iview->name ? iview->name : "(null)",
+						kview_strerror(kview_error));
+					faux_error_add(error_stack, msg);
+					faux_str_free(msg);
+					retval = BOOL_FALSE;
+					continue;
+				}
+				if (!kview_nested_from_iview(kview, iview,
+					error_stack)) {
+					retval = BOOL_FALSE;
+					continue;
+				}
+			} else {
+				kview = kview_from_iview(iview, error_stack);
+			}
+			if (!kview) {
+				retval = BOOL_FALSE;
+				continue;
+			}
+			if (!kscheme_add_view(kscheme, kview) && error_stack) {
+				char *msg = faux_str_sprintf("SCHEME: "
+					"Can't add PTYPE \"%s\"",
+					kview_name(kview));
+				faux_error_add(error_stack, msg);
+				faux_str_free(msg);
+				retval = BOOL_FALSE;
 				continue;
-			kscheme_add_view(kscheme, kview);
+			}
 		}
 	}
 
-	return BOOL_TRUE;
+	return retval;
 }
 
 
@@ -194,7 +253,10 @@ kscheme_t *kscheme_from_ischeme(ischeme_t *ischeme, faux_error_t *error_stack)
 		return NULL;
 	}
 
-	kscheme_nested_from_ischeme(kscheme, ischeme, error_stack);
+	if (!kscheme_nested_from_ischeme(kscheme, ischeme, error_stack)) {
+		kscheme_free(kscheme);
+		return NULL;
+	}
 
 	return kscheme;
 }

+ 1 - 1
klish/kscheme/kptype.c

@@ -15,7 +15,7 @@ struct kptype_s {
 };
 
 
-// Simple attributes
+// Simple methods
 
 // Name
 KGET_STR(ptype, name);

+ 4 - 19
klish/kscheme/kview.c

@@ -21,26 +21,11 @@ struct kview_s {
 KGET_STR(view, name);
 KSET_STR_ONCE(view, name);
 
-// COMMAND's list
+// COMMAND list
+KCMP_NESTED(view, command, name);
+KCMP_NESTED_BY_KEY(view, command, name);
 KADD_NESTED(view, command);
-
-
-static int kview_command_compare(const void *first, const void *second)
-{
-	const kcommand_t *f = (const kcommand_t *)first;
-	const kcommand_t *s = (const kcommand_t *)second;
-
-	return strcmp(kcommand_name(f), kcommand_name(s));
-}
-
-
-static int kview_command_kcompare(const void *key, const void *list_item)
-{
-	const char *f = (const char *)key;
-	const kcommand_t *s = (const kcommand_t *)list_item;
-
-	return strcmp(f, kcommand_name(s));
-}
+KFIND_NESTED(view, command);
 
 
 static kview_t *kview_new_empty(void)