Fix xsd generation in ddsconf

Signed-off-by: Jeroen Koekkoek <jeroen@koekkoek.nl>
This commit is contained in:
Jeroen Koekkoek 2020-06-26 09:32:24 +02:00
parent 93c75186f0
commit f4e99f41f6
13 changed files with 132 additions and 101 deletions

View file

@ -1626,7 +1626,9 @@ static struct cfgelem discovery_peers_cfgelems[] = {
"<p>This element statically configures a fault tolerant group of "
"addresses for discovery. Each member of the group is tried in "
"sequence until one succeeds.</p>"
)),
),
MAXIMUM(0)), /* Group element can occur more than once, but 1 is required
because of the way its processed (for now) */
END_MARKER
};
@ -1849,7 +1851,9 @@ static struct cfgelem domain_cfgelems[] = {
DESCRIPTION(
"<p>This element is used to configure Cyclone DDS with the DDS Security "
"specification plugins and settings.</p>"
)),
),
MAXIMUM(1)), /* Security must occur at most once, but INT_MAX is required
because of the way its processed (for now) */
#endif
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
GROUP("Partitioning", partitioning_cfgelems, NULL, 1,

View file

@ -230,6 +230,8 @@ DI(if_omg_security);
#define RANGE(...) /* drop */
#define UNIT(...) /* drop */
#define VALUES(...) /* drop */
#define MAXIMUM(...) /* drop */
#define MINIMUM(...) /* drop */
#define NOMEMBER 0, 0
#define NOFUNCTIONS 0, 0, 0, 0
@ -269,6 +271,12 @@ static const struct cfgelem root_cfgelem = {
#undef MEMBER
#undef MEMBEROF
#undef FUNCTIONS
#undef DESCRIPTION
#undef RANGE
#undef UNIT
#undef VALUES
#undef MAXIMUM
#undef MINIMUM
#undef NOMEMBER
#undef NOFUNCTIONS
#undef NODATA

View file

@ -50,10 +50,12 @@
#define RANGE(str) .range = str
#define UNIT(str) .unit = str
#define VALUES(...) .values = (const char *[]){ __VA_ARGS__, NULL }
#define MAXIMUM(num) .force_maximum = 1, .maximum = num
#define MINIMUM(num) .force_minimum = 1, .minimum = num
#define NOMEMBER /* drop */
#define NOFUNCTIONS /* drop */
#define NOMETADATA { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL }
#define NOMETADATA { NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
#define END_MARKER { NULL, NULL, NULL, 0, NULL, NULL, NOMETADATA }
#define ELEMENT(name, elems, attrs, multip, dflt, desc, ...) \
@ -76,8 +78,8 @@
EXPAND(ELEMENT, (name, NULL, attrs, multip, dflt, desc, .type = "string", __VA_ARGS__))
#define LIST(name, attrs, multip, dflt, ofst, funcs, desc, ...) \
EXPAND(ELEMENT, (name, NULL, attrs, multip, dflt, desc, .type = "list", __VA_ARGS__))
#define GROUP(name, elems, attrs, multip, ofst, funcs, desc) \
EXPAND(ELEMENT, (name, elems, attrs, multip, NULL, desc, .type = "group"))
#define GROUP(name, elems, attrs, multip, ofst, funcs, desc, ...) \
EXPAND(ELEMENT, (name, elems, attrs, multip, NULL, desc, .type = "group", __VA_ARGS__))
#include "dds/ddsi/ddsi_cfgelems.h"
/* undefine element macros */
@ -89,6 +91,8 @@
#undef RANGE
#undef UNIT
#undef VALUES
#undef MAXIMUM
#undef MINIMUM
#undef NOMEMBER
#undef NOFUNCTIONS
#undef NOMETADATA
@ -228,27 +232,35 @@ int islist(const struct cfgelem *elem)
int minimum(const struct cfgelem *elem)
{
switch (elem->multiplicity) {
case 0: /* special case, treat as-if 1 */
case 1: /* required if there is no default */
if (isgroup(elem))
if (elem->meta.force_minimum) {
return elem->meta.minimum;
} else {
switch (elem->multiplicity) {
case 0: /* special case, treat as-if 1 */
case 1: /* required if there is no default */
if (isgroup(elem))
return 0;
return (!elem->value);
default:
return 0;
return (!elem->value);
default:
return 0;
}
}
}
int maximum(const struct cfgelem *elem)
{
switch (elem->multiplicity) {
case INT_MAX:
return 0;
case 0:
case 1:
return 1;
default:
return elem->multiplicity;
if (elem->meta.force_maximum) {
return elem->meta.maximum;
} else {
switch (elem->multiplicity) {
case INT_MAX:
return 0;
case 0:
case 1:
return 1;
default:
return elem->multiplicity;
}
}
}

View file

@ -31,6 +31,8 @@ struct cfgmeta {
char *pattern;
char *description;
unsigned int flags;
const int force_maximum, maximum;
const int force_minimum, minimum;
const char *type;
const char *unit;
const char *range;

View file

@ -103,32 +103,32 @@ static void printtype(
(void)units;
assert(!isgroup(elem));
if (isbool(elem)) {
fprintf(out, "Boolean\n");
fputs("Boolean\n", out);
} else if (islist(elem)) {
assert(elem->meta.values);
fprintf(out, "One of:\n");
fputs("One of:\n", out);
if (elem->value && strlen(elem->value))
fprintf(out, "* Keyword: %s\n", elem->value);
fprintf(out, "* Comma-separated list of: ");
fputs("* Comma-separated list of: ", out);
for (const char **v = elem->meta.values; *v; v++) {
fprintf(out, "%s%s", v == elem->meta.values ? "" : ", ", *v);
}
fprintf(out, "\n");
fputs("\n", out);
if (!elem->value || !strlen(elem->value))
fprintf(out, "* Or empty\n");
fputs("* Or empty\n", out);
} else if (isenum(elem)) {
assert(elem->meta.values);
fprintf(out, "One of: ");
fputs("One of: ", out);
for (const char **v = elem->meta.values; *v; v++) {
fprintf(out, "%s%s", v == elem->meta.values ? "" : ", ", *v);
}
fprintf(out, "\n");
fputs("\n", out);
} else if (isint(elem)) {
fprintf(out, "Integer\n");
fputs("Integer\n", out);
} else if (elem->meta.unit) {
fprintf(out, "Number-with-unit\n");
fputs("Number-with-unit\n", out);
} else if (isstring(elem)) {
fprintf(out, "Text\n");
fputs("Text\n", out);
}
}
@ -142,12 +142,14 @@ static void printattr(
const struct cfgunit *units)
{
if (flags & FLAG_LF)
fputs("\n\n\n", out);
fputs("\n\n", out);
printhead(out, level, flags, elem, units);
printtype(out, level, flags, elem, units);
fputs("\n", out);
if (elem->description)
if (elem->description) {
fputs(elem->meta.description, out);
fputs("\n", out);
}
}
static void printelem(
@ -158,7 +160,7 @@ static void printelem(
const struct cfgunit *units)
{
if (flags & FLAG_LF)
fprintf(out, "\n\n\n");
fputs("\n\n", out);
printhead(out, level, flags, elem, units);
flags &= ~FLAG_LF;
if (hasattributes(elem)) {
@ -176,7 +178,7 @@ static void printelem(
ce = nextelem(elem->attributes, ce);
}
if (cnt != 0) {
fprintf(out, "\n");
fputs("\n", out);
flags |= FLAG_LF;
}
}
@ -190,18 +192,19 @@ static void printelem(
sep = ", ";
ce = nextelem(elem->children, ce);
}
fprintf(out, "\n");
fputs("\n", out);
flags |= FLAG_LF;
} else if (!isgroup(elem)) {
if (flags & FLAG_LF)
fprintf(out, "\n");
fputs("\n", out);
printtype(out, level+1, flags, elem, units);
flags |= FLAG_LF;
}
if (elem->description) {
if (flags & FLAG_LF)
fprintf(out, "\n");
fputs("\n", out);
fputs(elem->meta.description, out);
fputs("\n", out);
}
if (hasattributes(elem)) {
struct cfgelem *ce = firstelem(elem->attributes);

View file

@ -158,6 +158,6 @@ int printrnc(FILE *out, struct cfgelem *elem, const struct cfgunit *units)
static const char *fmt = " %s = xsd:token { pattern = \"%s\" }\n";
print(out, 0, fmt, cu->name, cu->pattern);
}
print(out, 0, "}");
print(out, 0, "}\n");
return 0;
}

View file

@ -165,7 +165,7 @@ printref(
snprintf(minattr, sizeof(minattr), "minOccurs=\"%d\" ", minimum(elem));
if (!(flags & FLAG_NOMAX) && maximum(elem) == 0)
snprintf(maxattr, sizeof(maxattr), "maxOccurs=\"unbounded\" ");
else if (!(FLAG_NOMAX) && maximum(elem) != 1)
else if (!(flags & FLAG_NOMAX) && maximum(elem) != 1)
snprintf(maxattr, sizeof(maxattr), "maxOccurs=\"%d\" ", maximum(elem));
print(out, cols, fmt, minattr, maxattr, schema(), name(elem));
}
@ -185,11 +185,11 @@ printcomplextype(
assert(!ismoved(elem) && !isdeprecated(elem));
if (flags & FLAG_REFERENCE) {
if (minimum(elem) != 1)
if (!(flags & FLAG_NOMIN) && minimum(elem) != 1)
snprintf(minattr, sizeof(minattr), "minOccurs=\"%d\" ", minimum(elem));
if (maximum(elem) == 0)
if (!(flags & FLAG_NOMAX) && maximum(elem) == 0)
snprintf(maxattr, sizeof(maxattr), "maxOccurs=\"unbounded\" ");
else if (maximum(elem) != 1)
else if (!(flags & FLAG_NOMAX) && maximum(elem) != 1)
snprintf(maxattr, sizeof(maxattr), "maxOccurs=\"%d\" ", maximum(elem));
}
@ -208,58 +208,63 @@ printcomplextype(
if ((cnt = haschildren(elem))) {
const char *cont = NULL;
struct cfgelem *ce;
int min[2], max[2], eq[2] = { 1, 1 };
int min[3], max[3];
int mineq, maxeq;
assert(isgroup(elem));
minattr[0] = '\0';
maxattr[0] = '\0';
if (cnt == 1) {
/* minOccurs and maxOccurs placed in element */
cont = "sequence";
} else {
assert(cnt > 1);
ce = firstelem(elem->children);
assert(ce);
min[0] = min[1] = minimum(ce);
max[0] = max[1] = maximum(ce);
min[0] = min[1] = min[2] = minimum(ce);
max[0] = max[1] = max[2] = maximum(ce);
assert(min[1] <= max[1] || max[1] == 0);
mineq = maxeq = 1;
ce = nextelem(elem->children, ce);
assert(ce);
while (ce) {
min[1] = minimum(ce);
max[1] = maximum(ce);
assert(min[1] <= max[1] || max[1] == 0);
min[2] += minimum(ce);
max[2] += maximum(ce);
if (min[1] != min[0]) {
eq[0] = 0;
if (min[1] < min[0])
mineq = 0;
if (min[1] > min[0])
min[0] = min[1];
}
if (max[1] != max[0]) {
eq[1] = 0;
maxeq = 0;
if ((max[0] != 0 && max[1] > max[0]) || max[1] == 0)
max[0] = max[1];
}
ce = nextelem(elem->children, ce);
}
if (min[0] > 1 || max[0] != 1 /* unbounded or >1 */) {
cont = "choice";
if (eq[0]) {
if (min[0] != 1)
snprintf(minattr, sizeof(minattr), " minOccurs=\"%d\"", min[0]);
flags |= FLAG_NOMIN;
}
if (eq[1]) {
if (max[0] == 0)
snprintf(maxattr, sizeof(maxattr), " maxOccurs=\"unbounded\"");
else if (max[0] != 1)
snprintf(maxattr, sizeof(maxattr), " maxOccurs=\"%d\"", max[0]);
flags |= FLAG_NOMAX;
}
} else {
/* xsd generation becomes significantly more difficult if the minimum
number of occurences for an element is more non-zero and the
maximum number of occurences of it (or one of its siblings) is more
than one, but that is not likely to occur */
if (min[0] <= 1 && max[0] == 1) {
/* any order, each zero or one time */
/* minOccurs placed in element maxOccurs always one */
cont = "all";
} else {
cont = "choice";
if (min[0] == 0)
snprintf(minattr, sizeof(minattr), " minOccurs=\"0\"");
else if (min[0] != 1) /* incorrect, but make the most of it */
snprintf(minattr, sizeof(minattr), " minOccurs=\"%d\"", min[2]);
if (max[0] == 0)
snprintf(maxattr, sizeof(maxattr), " maxOccurs=\"unbounded\"");
else if (max[0] != 1)
snprintf(maxattr, sizeof(maxattr), " maxOccurs=\"%d\"", max[2]);
if (mineq)
flags |= FLAG_NOMIN;
if (maxeq)
flags |= FLAG_NOMAX;
}
}
@ -270,7 +275,6 @@ printcomplextype(
ce = nextelem(elem->children, ce);
}
print(out, cols+4, "</xs:%s>\n", cont);
flags &= ~(FLAG_NOMIN | FLAG_NOMAX);
} else if (!isgroup(elem) && (!isstring(elem) || elem->meta.unit)) {
ofst = 4;
print(out, cols+4, "<xs:simpleContent>\n");
@ -288,6 +292,7 @@ printcomplextype(
print(out, cols+6, extfmt, "xs", isbuiltintype(elem));
}
}
flags &= ~(FLAG_NOMIN | FLAG_NOMAX);
if (hasattributes(elem)) {
struct cfgelem *ce;
ce = firstelem(elem->attributes);
@ -417,6 +422,6 @@ int printxsd(FILE *out, struct cfgelem *elem, const struct cfgunit *units)
print(out, 4, "</xs:restriction>\n");
print(out, 2, "</xs:simpleType>\n");
}
print(out, 0, "</xs:schema>");
print(out, 0, "</xs:schema>\n");
return 0;
}