[PATCH v2 2/2] Preserve datatype markers when emitting dts format

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



From: Grant Likely <grant@xxxxxxxxxxxxxxxxxxxxxxxxx>

If datatype markers are present in the property value, use them to
output the data in the correct format instead of trying to guess the
datatype. This also will preserve data grouping, such as in an
interrupts list.

This is a step forward for preserving and using datatype information
when processing DTS/DTB files. Schema validation tools can use the
datatype information to make sure a DT is correctly formed and
intepreted.

Signed-off-by: Grant Likely <grant.likely@xxxxxxxxxxxx>
---
 dtc.h        |   1 +
 treesource.c | 227 ++++++++++++++++++++++++++++++++---------------------------
 2 files changed, 125 insertions(+), 103 deletions(-)

diff --git a/dtc.h b/dtc.h
index 8734f47..1d5a60a 100644
--- a/dtc.h
+++ b/dtc.h
@@ -73,6 +73,7 @@ typedef uint32_t cell_t;
 
 /* Data blobs */
 enum markertype {
+	MARKER_NONE,
 	REF_PHANDLE,
 	REF_PATH,
 	LABEL,
diff --git a/treesource.c b/treesource.c
index 2461a3d..7b3edbc 100644
--- a/treesource.c
+++ b/treesource.c
@@ -61,24 +61,14 @@ static bool isstring(char c)
 		|| strchr("\a\b\t\n\v\f\r", c));
 }
 
-static void write_propval_string(FILE *f, struct data val)
+static void write_propval_string(FILE *f, const char *s, size_t len)
 {
-	const char *str = val.val;
-	int i;
-	struct marker *m = val.markers;
-
-	assert(str[val.len-1] == '\0');
+	const char *end = s + len - 1;
+	assert(*end == '\0');
 
-	while (m && (m->offset == 0)) {
-		if (m->type == LABEL)
-			fprintf(f, "%s: ", m->ref);
-		m = m->next;
-	}
 	fprintf(f, "\"");
-
-	for (i = 0; i < (val.len-1); i++) {
-		char c = str[i];
-
+	while (s < end) {
+		char c = *s++;
 		switch (c) {
 		case '\a':
 			fprintf(f, "\\a");
@@ -108,129 +98,160 @@ static void write_propval_string(FILE *f, struct data val)
 			fprintf(f, "\\\"");
 			break;
 		case '\0':
-			fprintf(f, "\", ");
-			while (m && (m->offset <= (i + 1))) {
-				if (m->type == LABEL) {
-					assert(m->offset == (i+1));
-					fprintf(f, "%s: ", m->ref);
-				}
-				m = m->next;
-			}
-			fprintf(f, "\"");
+			fprintf(f, "\", \"");
 			break;
 		default:
 			if (isprint((unsigned char)c))
 				fprintf(f, "%c", c);
 			else
-				fprintf(f, "\\x%02hhx", c);
+				fprintf(f, "\\x%02"PRIx8, c);
 		}
 	}
 	fprintf(f, "\"");
-
-	/* Wrap up any labels at the end of the value */
-	for_each_marker_of_type(m, LABEL) {
-		assert (m->offset == val.len);
-		fprintf(f, " %s:", m->ref);
-	}
 }
 
-static void write_propval_cells(FILE *f, struct data val)
+static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
 {
-	void *propend = val.val + val.len;
-	fdt32_t *cp = (fdt32_t *)val.val;
-	struct marker *m = val.markers;
-
-	fprintf(f, "<");
-	for (;;) {
-		while (m && (m->offset <= ((char *)cp - val.val))) {
-			if (m->type == LABEL) {
-				assert(m->offset == ((char *)cp - val.val));
-				fprintf(f, "%s: ", m->ref);
-			}
-			m = m->next;
-		}
+	const char *end = p + len - (width - 1);
+	assert(len % width == 0);
 
-		fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
-		if ((void *)cp >= propend)
+	for (; p < end; p += width) {
+		switch (width) {
+		case 1:
+			fprintf(f, " %02"PRIx8, *(const uint8_t*)p);
 			break;
-		fprintf(f, " ");
-	}
-
-	/* Wrap up any labels at the end of the value */
-	for_each_marker_of_type(m, LABEL) {
-		assert (m->offset == val.len);
-		fprintf(f, " %s:", m->ref);
+		case 2:
+			fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
+			break;
+		case 4:
+			fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
+			break;
+		case 8:
+			fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
+			break;
+		}
 	}
-	fprintf(f, ">");
 }
 
-static void write_propval_bytes(FILE *f, struct data val)
+static struct marker* next_type_marker(struct marker *m)
 {
-	void *propend = val.val + val.len;
-	const char *bp = val.val;
-	struct marker *m = val.markers;
-
-	fprintf(f, "[");
-	for (;;) {
-		while (m && (m->offset == (bp-val.val))) {
-			if (m->type == LABEL)
-				fprintf(f, "%s: ", m->ref);
-			m = m->next;
-		}
-
-		fprintf(f, "%02hhx", (unsigned char)(*bp++));
-		if ((const void *)bp >= propend)
-			break;
-		fprintf(f, " ");
-	}
-
-	/* Wrap up any labels at the end of the value */
-	for_each_marker_of_type(m, LABEL) {
-		assert (m->offset == val.len);
-		fprintf(f, " %s:", m->ref);
-	}
-	fprintf(f, "]");
+	while (m && (m->type == LABEL || m->type == REF_PHANDLE || m->type == REF_PATH))
+		m = m->next;
+	return m;
 }
 
+const char * delim_start[] = {
+	[MARKER_UINT8] = "[",
+	[MARKER_UINT16] = "/bits/ 16 <",
+	[MARKER_UINT32] = "<",
+	[MARKER_UINT64] = "/bits/ 64 <",
+	[MARKER_STRING] = "",
+};
+const char * delim_end[] = {
+	[MARKER_UINT8] = " ]",
+	[MARKER_UINT16] = " >",
+	[MARKER_UINT32] = " >",
+	[MARKER_UINT64] = " >",
+	[MARKER_STRING] = "",
+};
 static void write_propval(FILE *f, struct property *prop)
 {
-	int len = prop->val.len;
-	const char *p = prop->val.val;
-	struct marker *m = prop->val.markers;
+	size_t len = prop->val.len;
+	size_t chunk_len;
+	struct marker *next_type, *m = prop->val.markers;
+	struct marker dummy_marker;
 	int nnotstring = 0, nnul = 0;
 	int nnotstringlbl = 0, nnotcelllbl = 0;
 	int i;
+	enum markertype emit_type = MARKER_NONE;
 
 	if (len == 0) {
 		fprintf(f, ";\n");
 		return;
 	}
 
-	for (i = 0; i < len; i++) {
-		if (! isstring(p[i]))
-			nnotstring++;
-		if (p[i] == '\0')
-			nnul++;
-	}
+	fprintf(f, " = ");
+
+	next_type = next_type_marker(m);
+	chunk_len = (next_type ? next_type->offset : len);
+	if (chunk_len) {
+		/* data type information missing, need to guess */
+		const char *p = prop->val.val;
+		for (i = 0; i < chunk_len; i++) {
+			if (! isstring(p[i]))
+				nnotstring++;
+			if (p[i] == '\0')
+				nnul++;
+		}
+
+		for_each_marker_of_type(m, LABEL) {
+			if (m->offset >= chunk_len)
+				break;
+			if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
+				nnotstringlbl++;
+			if ((m->offset % sizeof(cell_t)) != 0)
+				nnotcelllbl++;
+		}
 
-	for_each_marker_of_type(m, LABEL) {
-		if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
-			nnotstringlbl++;
-		if ((m->offset % sizeof(cell_t)) != 0)
-			nnotcelllbl++;
+		if ((p[chunk_len-1] == '\0') && (nnotstring == 0) && (nnul < (chunk_len-nnul))
+		    && (nnotstringlbl == 0)) {
+			dummy_marker.type = MARKER_STRING;
+		} else if (((chunk_len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
+			dummy_marker.type = MARKER_UINT32;
+		} else {
+			dummy_marker.type = MARKER_UINT8;
+		}
+
+		dummy_marker.next = prop->val.markers;
+		dummy_marker.offset = 0;
+		dummy_marker.ref = NULL;
+		m = &dummy_marker;
 	}
 
-	fprintf(f, " = ");
-	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
-	    && (nnotstringlbl == 0)) {
-		write_propval_string(f, prop->val);
-	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
-		write_propval_cells(f, prop->val);
-	} else {
-		write_propval_bytes(f, prop->val);
+	for_each_marker(m) {
+		chunk_len = (m->next ? m->next->offset : len) - m->offset;
+		const char *p = &prop->val.val[m->offset];
+
+		switch(m->type) {
+		case MARKER_UINT8:
+		case MARKER_UINT16:
+		case MARKER_UINT32:
+		case MARKER_UINT64:
+		case MARKER_STRING:
+			if (emit_type != MARKER_NONE)
+				fprintf(f, "%s, ", delim_end[emit_type]);
+			emit_type = m->type;
+			fprintf(f, "%s", delim_start[emit_type]);
+			break;
+		case LABEL:
+			fprintf(f, " %s:", m->ref);
+			break;
+		default:
+			break;
+		}
+
+		if (chunk_len <= 0)
+			continue;
+
+		switch(emit_type) {
+		case MARKER_UINT16:
+			write_propval_int(f, p, chunk_len, 2);
+			break;
+		case MARKER_UINT32:
+			write_propval_int(f, p, chunk_len, 4);
+			break;
+		case MARKER_UINT64:
+			write_propval_int(f, p, chunk_len, 8);
+			break;
+		case MARKER_STRING:
+			write_propval_string(f, p, chunk_len);
+			break;
+		default:
+			write_propval_int(f, p, chunk_len, 1);
+		}
 	}
 
-	fprintf(f, ";\n");
+	fprintf(f, "%s;\n", delim_end[emit_type] ? : "");
 }
 
 static void write_tree_source_node(FILE *f, struct node *tree, int level)
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux