Merge pull request #445 from CESNET/yang-data-extensions

CHANGE support for yang-data extension
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f20ffdb..ff57197 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,7 +11,7 @@
 # set version
 set(LIBYANG_MAJOR_VERSION 0)
 set(LIBYANG_MINOR_VERSION 15)
-set(LIBYANG_MICRO_VERSION 38)
+set(LIBYANG_MICRO_VERSION 43)
 set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION})
 set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION})
 
@@ -291,6 +291,9 @@
     if(CMOCKA_FOUND)
         enable_testing()
         add_subdirectory(tests)
+    else(CMOCKA_FOUND)
+        message(STATUS "Disabling tests because of missing CMocka")
+        set(ENABLE_BUILD_TESTS NO)
     endif(CMOCKA_FOUND)
 endif(ENABLE_BUILD_TESTS)
 
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 568e5f3..700f895 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -197,7 +197,7 @@
         case LY_TYPE_UINT64:
             if (attr->value_str) {
                 /* xml_expr can contain transformed xpath */
-                lyxml_dump_text(out, xml_expr ? xml_expr : attr->value_str);
+                lyxml_dump_text(out, xml_expr ? xml_expr : attr->value_str, LYXML_DATA_ATTR);
             }
             break;
 
@@ -210,7 +210,7 @@
             len = p - attr->value_str;
             mod_name = attr->annotation->module->name;
             if (!strncmp(attr->value_str, mod_name, len) && !mod_name[len]) {
-                lyxml_dump_text(out, ++p);
+                lyxml_dump_text(out, ++p, LYXML_DATA_ATTR);
             } else {
                 /* avoid code duplication - use instance-identifier printer which gets necessary namespaces to print */
                 goto printinst;
@@ -232,7 +232,7 @@
             free(prefs);
             free(nss);
 
-            lyxml_dump_text(out, xml_expr);
+            lyxml_dump_text(out, xml_expr, LYXML_DATA_ATTR);
             lydict_remove(node->schema->module->ctx, xml_expr);
             break;
 
@@ -322,7 +322,7 @@
             ly_print(out, "/>");
         } else {
             ly_print(out, ">");
-            lyxml_dump_text(out, leaf->value_str);
+            lyxml_dump_text(out, leaf->value_str, LYXML_DATA_ELEM);
             ly_print(out, "</%s>", node->schema->name);
         }
         break;
@@ -338,7 +338,7 @@
         mod_name = leaf->schema->module->name;
         if (!strncmp(leaf->value_str, mod_name, len) && !mod_name[len]) {
             ly_print(out, ">");
-            lyxml_dump_text(out, ++p);
+            lyxml_dump_text(out, ++p, LYXML_DATA_ELEM);
             ly_print(out, "</%s>", node->schema->name);
         } else {
             /* avoid code duplication - use instance-identifier printer which gets necessary namespaces to print */
@@ -363,7 +363,7 @@
 
         if (xml_expr[0]) {
             ly_print(out, ">");
-            lyxml_dump_text(out, xml_expr);
+            lyxml_dump_text(out, xml_expr, LYXML_DATA_ELEM);
             ly_print(out, "</%s>", node->schema->name);
         } else {
             ly_print(out, "/>");
@@ -527,7 +527,7 @@
         /* ... and print anydata content */
         switch (any->value_type) {
         case LYD_ANYDATA_CONSTSTRING:
-            lyxml_dump_text(out, any->value.str);
+            lyxml_dump_text(out, any->value.str, LYXML_DATA_ELEM);
             break;
         case LYD_ANYDATA_DATATREE:
             if (any->value.tree) {
diff --git a/src/printer_yin.c b/src/printer_yin.c
index 58a1f41..3fc12e1 100644
--- a/src/printer_yin.c
+++ b/src/printer_yin.c
@@ -47,7 +47,7 @@
 
     if (attr_name) {
         ly_print(out, " %s=\"", attr_name);
-        lyxml_dump_text(out, attr_value);
+        lyxml_dump_text(out, attr_value, LYXML_DATA_ATTR);
         ly_print(out, "\"%s", endflag == -1 ? "/>\n" : endflag == 1 ? ">\n" : "");
     } else if (endflag) {
         ly_print(out, endflag == -1 ? "/>\n" : ">\n");
@@ -91,7 +91,7 @@
 yin_print_arg(struct lyout *out, int level, const char *arg, const char *text)
 {
     ly_print(out, "%*s<%s>", LEVEL, INDENT, arg);
-    lyxml_dump_text(out, text);
+    lyxml_dump_text(out, text, LYXML_DATA_ELEM);
     ly_print(out, "</%s>\n", arg);
 }
 
@@ -371,7 +371,7 @@
     }
 
     ly_print(out, "%*s<when condition=\"", LEVEL, INDENT);
-    lyxml_dump_text(out, str);
+    lyxml_dump_text(out, str, LYXML_DATA_ATTR);
     ly_print(out, "\"");
     lydict_remove(module->ctx, str);
 
@@ -601,7 +601,7 @@
     }
 
     ly_print(out, "%*s<must condition=\"", LEVEL, INDENT);
-    lyxml_dump_text(out, str);
+    lyxml_dump_text(out, str, LYXML_DATA_ATTR);
     ly_print(out, "\"");
     lydict_remove(module->ctx, str);
 
@@ -1984,7 +1984,7 @@
                 yin_print_open(out, level, prefix, ext[u]->def->name, NULL, NULL, content);
                 level++;
                 ly_print(out, "%*s<%s:%s>", LEVEL, INDENT, prefix, ext[u]->def->argument);
-                lyxml_dump_text(out, ext[u]->arg_value);
+                lyxml_dump_text(out, ext[u]->arg_value, LYXML_DATA_ELEM);
                 ly_print(out, "</%s:%s>\n", prefix, ext[u]->def->argument);
                 level--;
             } else {
diff --git a/src/resolve.c b/src/resolve.c
index 2332ebd..176fb97 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -4808,11 +4808,6 @@
     /* check that the grouping is resolved (no unresolved uses inside) */
     assert(!uses->grp->unres_count);
 
-    if (!uses->grp->child) {
-        /* grouping without children, warning was already displayed */
-        return EXIT_SUCCESS;
-    }
-
     /* copy the data nodes from grouping into the uses context */
     LY_TREE_FOR(uses->grp->child, node_aux) {
         if (node_aux->nodetype & LYS_GROUPING) {
@@ -6968,8 +6963,8 @@
         break;
     case UNRES_TYPEDEF_DFLT:
     case UNRES_TYPE_DFLT:
-        if (str_node) {
-            LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "type default", (char *)str_node);
+        if (*(char **)str_node) {
+            LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "type default", *(char **)str_node);
         }   /* else no default value in the type itself, but we are checking some restrictions against
              *  possible default value of some base type. The failure is caused by not resolved base type,
              *  so it was already reported */
diff --git a/src/xml.c b/src/xml.c
index 9dc9132..62c755f 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -1246,7 +1246,7 @@
 }
 
 int
-lyxml_dump_text(struct lyout *out, const char *text)
+lyxml_dump_text(struct lyout *out, const char *text, LYXML_DATA_TYPE type)
 {
     unsigned int i, n;
 
@@ -1267,8 +1267,11 @@
             n += ly_print(out, "&gt;");
             break;
         case '"':
-            n += ly_print(out, "&quot;");
-            break;
+            if (type == LYXML_DATA_ATTR) {
+                n += ly_print(out, "&quot;");
+                break;
+            }
+            /* falls through */
         default:
             ly_write(out, &text[i], 1);
             n++;
@@ -1290,7 +1293,7 @@
     if (!e->name) {
         /* mixed content */
         if (e->content) {
-            return lyxml_dump_text(out, e->content);
+            return lyxml_dump_text(out, e->content, LYXML_DATA_ELEM);
         } else {
             return 0;
         }
@@ -1354,7 +1357,7 @@
         ly_print(out, ">");
         size++;
 
-        size += lyxml_dump_text(out, e->content);
+        size += lyxml_dump_text(out, e->content, LYXML_DATA_ELEM);
 
         if (e->ns && e->ns->prefix) {
             size += ly_print(out, "</%s:%s>%s", e->ns->prefix, e->name, delim);
diff --git a/src/xml_internal.h b/src/xml_internal.h
index 8ee302d..d489fd6 100644
--- a/src/xml_internal.h
+++ b/src/xml_internal.h
@@ -128,12 +128,20 @@
 int lyxml_getutf8(struct ly_ctx *ctx, const char *buf, unsigned int *read);
 
 /**
+ * @brief Types of the XML data
+ */
+typedef enum lyxml_data_type {
+    LYXML_DATA_ATTR = 1,   /**< XML attribute data */
+    LYXML_DATA_ELEM = 2    /**< XML element data */
+} LYXML_DATA_TYPE;
+
+/**
  * @brief Dump XML text. Converts special characters to their equivalent
  * starting with '&'.
  * @param[in] out Output structure.
  * @param[in] text Text to dump.
  * @return Number of dumped characters.
  */
-int lyxml_dump_text(struct lyout *out, const char *text);
+int lyxml_dump_text(struct lyout *out, const char *text, LYXML_DATA_TYPE type);
 
 #endif /* LY_XML_INTERNAL_H_ */
diff --git a/swig/python/CMakeLists.txt b/swig/python/CMakeLists.txt
index d7e8aa3..af10c30 100644
--- a/swig/python/CMakeLists.txt
+++ b/swig/python/CMakeLists.txt
@@ -24,7 +24,7 @@
 file(RELATIVE_PATH _REL_PYTHON_MODULE_PATH ${CMAKE_INSTALL_PREFIX} ${_ABS_PYTHON_MODULE_PATH})
 set(PYTHON_MODULE_PATH ${_REL_PYTHON_MODULE_PATH})
 
-install( FILES "${CMAKE_CURRENT_BINARY_DIR}/_${PYTHON_SWIG_BINDING}.so" DESTINATION ${PYTHON_MODULE_PATH})
+install( TARGETS _${PYTHON_SWIG_BINDING} DESTINATION ${PYTHON_MODULE_PATH})
 install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PYTHON_SWIG_BINDING}.py" DESTINATION ${PYTHON_MODULE_PATH})
 install( FILES "${CMAKE_CURRENT_BINARY_DIR}/swigpyrun.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libyang)
 
diff --git a/tests/api/test_tree_data.c b/tests/api/test_tree_data.c
index 4f1e839..7a8a27c 100644
--- a/tests/api/test_tree_data.c
+++ b/tests/api/test_tree_data.c
@@ -590,7 +590,7 @@
     str = NULL;
     lyd_print_mem(&str, root, LYD_XML, 0);
     assert_non_null(root);
-    assert_string_equal(str, "<any xmlns=\"urn:a\">test &lt;&amp;&gt;&quot;</any>");
+    assert_string_equal(str, "<any xmlns=\"urn:a\">test &lt;&amp;&gt;\"</any>");
     free(str);
     lyd_free(root);