xref: /netbsd-src/external/gpl2/dtc/dist/treesource.c (revision cc7d2833ecf67da5a5ddc470841931eb9f6723e4)
1*cc7d2833Sskrll /*	$NetBSD: treesource.c,v 1.1.1.3 2019/12/22 12:34:03 skrll Exp $	*/
2d89652e2Sskrll 
3*cc7d2833Sskrll // SPDX-License-Identifier: GPL-2.0-or-later
4b8ae3907Smacallan /*
5b8ae3907Smacallan  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
6b8ae3907Smacallan  */
7b8ae3907Smacallan 
8b8ae3907Smacallan #include "dtc.h"
9b8ae3907Smacallan #include "srcpos.h"
10b8ae3907Smacallan 
11b8ae3907Smacallan extern FILE *yyin;
12b8ae3907Smacallan extern int yyparse(void);
13b8ae3907Smacallan extern YYLTYPE yylloc;
14b8ae3907Smacallan 
15d89652e2Sskrll struct dt_info *parser_output;
16b8ae3907Smacallan bool treesource_error;
17b8ae3907Smacallan 
dt_from_source(const char * fname)18d89652e2Sskrll struct dt_info *dt_from_source(const char *fname)
19b8ae3907Smacallan {
20d89652e2Sskrll 	parser_output = NULL;
21b8ae3907Smacallan 	treesource_error = false;
22b8ae3907Smacallan 
23b8ae3907Smacallan 	srcfile_push(fname);
24b8ae3907Smacallan 	yyin = current_srcfile->f;
25b8ae3907Smacallan 	yylloc.file = current_srcfile;
26b8ae3907Smacallan 
27b8ae3907Smacallan 	if (yyparse() != 0)
28b8ae3907Smacallan 		die("Unable to parse input tree\n");
29b8ae3907Smacallan 
30b8ae3907Smacallan 	if (treesource_error)
31b8ae3907Smacallan 		die("Syntax error parsing input tree\n");
32b8ae3907Smacallan 
33d89652e2Sskrll 	return parser_output;
34b8ae3907Smacallan }
35b8ae3907Smacallan 
write_prefix(FILE * f,int level)36b8ae3907Smacallan static void write_prefix(FILE *f, int level)
37b8ae3907Smacallan {
38b8ae3907Smacallan 	int i;
39b8ae3907Smacallan 
40b8ae3907Smacallan 	for (i = 0; i < level; i++)
41b8ae3907Smacallan 		fputc('\t', f);
42b8ae3907Smacallan }
43b8ae3907Smacallan 
isstring(char c)44b8ae3907Smacallan static bool isstring(char c)
45b8ae3907Smacallan {
46b8ae3907Smacallan 	return (isprint((unsigned char)c)
47b8ae3907Smacallan 		|| (c == '\0')
48b8ae3907Smacallan 		|| strchr("\a\b\t\n\v\f\r", c));
49b8ae3907Smacallan }
50b8ae3907Smacallan 
write_propval_string(FILE * f,const char * s,size_t len)51*cc7d2833Sskrll static void write_propval_string(FILE *f, const char *s, size_t len)
52b8ae3907Smacallan {
53*cc7d2833Sskrll 	const char *end = s + len - 1;
54b8ae3907Smacallan 
55*cc7d2833Sskrll 	if (!len)
56*cc7d2833Sskrll 		return;
57b8ae3907Smacallan 
58*cc7d2833Sskrll 	assert(*end == '\0');
59*cc7d2833Sskrll 
60b8ae3907Smacallan 	fprintf(f, "\"");
61*cc7d2833Sskrll 	while (s < end) {
62*cc7d2833Sskrll 		char c = *s++;
63b8ae3907Smacallan 		switch (c) {
64b8ae3907Smacallan 		case '\a':
65b8ae3907Smacallan 			fprintf(f, "\\a");
66b8ae3907Smacallan 			break;
67b8ae3907Smacallan 		case '\b':
68b8ae3907Smacallan 			fprintf(f, "\\b");
69b8ae3907Smacallan 			break;
70b8ae3907Smacallan 		case '\t':
71b8ae3907Smacallan 			fprintf(f, "\\t");
72b8ae3907Smacallan 			break;
73b8ae3907Smacallan 		case '\n':
74b8ae3907Smacallan 			fprintf(f, "\\n");
75b8ae3907Smacallan 			break;
76b8ae3907Smacallan 		case '\v':
77b8ae3907Smacallan 			fprintf(f, "\\v");
78b8ae3907Smacallan 			break;
79b8ae3907Smacallan 		case '\f':
80b8ae3907Smacallan 			fprintf(f, "\\f");
81b8ae3907Smacallan 			break;
82b8ae3907Smacallan 		case '\r':
83b8ae3907Smacallan 			fprintf(f, "\\r");
84b8ae3907Smacallan 			break;
85b8ae3907Smacallan 		case '\\':
86b8ae3907Smacallan 			fprintf(f, "\\\\");
87b8ae3907Smacallan 			break;
88b8ae3907Smacallan 		case '\"':
89b8ae3907Smacallan 			fprintf(f, "\\\"");
90b8ae3907Smacallan 			break;
91b8ae3907Smacallan 		case '\0':
92*cc7d2833Sskrll 			fprintf(f, "\\0");
93b8ae3907Smacallan 			break;
94b8ae3907Smacallan 		default:
95b8ae3907Smacallan 			if (isprint((unsigned char)c))
96b8ae3907Smacallan 				fprintf(f, "%c", c);
97b8ae3907Smacallan 			else
98*cc7d2833Sskrll 				fprintf(f, "\\x%02"PRIx8, c);
99b8ae3907Smacallan 		}
100b8ae3907Smacallan 	}
101b8ae3907Smacallan 	fprintf(f, "\"");
102b8ae3907Smacallan }
103b8ae3907Smacallan 
write_propval_int(FILE * f,const char * p,size_t len,size_t width)104*cc7d2833Sskrll static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
105b8ae3907Smacallan {
106*cc7d2833Sskrll 	const char *end = p + len;
107*cc7d2833Sskrll 	assert(len % width == 0);
108b8ae3907Smacallan 
109*cc7d2833Sskrll 	for (; p < end; p += width) {
110*cc7d2833Sskrll 		switch (width) {
111*cc7d2833Sskrll 		case 1:
112*cc7d2833Sskrll 			fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
113b8ae3907Smacallan 			break;
114*cc7d2833Sskrll 		case 2:
115*cc7d2833Sskrll 			fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
116*cc7d2833Sskrll 			break;
117*cc7d2833Sskrll 		case 4:
118*cc7d2833Sskrll 			fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
119*cc7d2833Sskrll 			break;
120*cc7d2833Sskrll 		case 8:
121*cc7d2833Sskrll 			fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
122*cc7d2833Sskrll 			break;
123*cc7d2833Sskrll 		}
124*cc7d2833Sskrll 		if (p + width < end)
125*cc7d2833Sskrll 			fputc(' ', f);
126*cc7d2833Sskrll 	}
127b8ae3907Smacallan }
128b8ae3907Smacallan 
has_data_type_information(struct marker * m)129*cc7d2833Sskrll static bool has_data_type_information(struct marker *m)
130b8ae3907Smacallan {
131*cc7d2833Sskrll 	return m->type >= TYPE_UINT8;
132*cc7d2833Sskrll }
133b8ae3907Smacallan 
next_type_marker(struct marker * m)134*cc7d2833Sskrll static struct marker *next_type_marker(struct marker *m)
135*cc7d2833Sskrll {
136*cc7d2833Sskrll 	while (m && !has_data_type_information(m))
137b8ae3907Smacallan 		m = m->next;
138*cc7d2833Sskrll 	return m;
139b8ae3907Smacallan }
140b8ae3907Smacallan 
type_marker_length(struct marker * m)141*cc7d2833Sskrll size_t type_marker_length(struct marker *m)
142*cc7d2833Sskrll {
143*cc7d2833Sskrll 	struct marker *next = next_type_marker(m->next);
144*cc7d2833Sskrll 
145*cc7d2833Sskrll 	if (next)
146*cc7d2833Sskrll 		return next->offset - m->offset;
147*cc7d2833Sskrll 	return 0;
148b8ae3907Smacallan }
149b8ae3907Smacallan 
150*cc7d2833Sskrll static const char *delim_start[] = {
151*cc7d2833Sskrll 	[TYPE_UINT8] = "[",
152*cc7d2833Sskrll 	[TYPE_UINT16] = "/bits/ 16 <",
153*cc7d2833Sskrll 	[TYPE_UINT32] = "<",
154*cc7d2833Sskrll 	[TYPE_UINT64] = "/bits/ 64 <",
155*cc7d2833Sskrll 	[TYPE_STRING] = "",
156*cc7d2833Sskrll };
157*cc7d2833Sskrll static const char *delim_end[] = {
158*cc7d2833Sskrll 	[TYPE_UINT8] = "]",
159*cc7d2833Sskrll 	[TYPE_UINT16] = ">",
160*cc7d2833Sskrll 	[TYPE_UINT32] = ">",
161*cc7d2833Sskrll 	[TYPE_UINT64] = ">",
162*cc7d2833Sskrll 	[TYPE_STRING] = "",
163*cc7d2833Sskrll };
164b8ae3907Smacallan 
guess_value_type(struct property * prop)165*cc7d2833Sskrll static enum markertype guess_value_type(struct property *prop)
166b8ae3907Smacallan {
167b8ae3907Smacallan 	int len = prop->val.len;
168b8ae3907Smacallan 	const char *p = prop->val.val;
169b8ae3907Smacallan 	struct marker *m = prop->val.markers;
170b8ae3907Smacallan 	int nnotstring = 0, nnul = 0;
171b8ae3907Smacallan 	int nnotstringlbl = 0, nnotcelllbl = 0;
172b8ae3907Smacallan 	int i;
173b8ae3907Smacallan 
174b8ae3907Smacallan 	for (i = 0; i < len; i++) {
175b8ae3907Smacallan 		if (! isstring(p[i]))
176b8ae3907Smacallan 			nnotstring++;
177b8ae3907Smacallan 		if (p[i] == '\0')
178b8ae3907Smacallan 			nnul++;
179b8ae3907Smacallan 	}
180b8ae3907Smacallan 
181b8ae3907Smacallan 	for_each_marker_of_type(m, LABEL) {
182b8ae3907Smacallan 		if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
183b8ae3907Smacallan 			nnotstringlbl++;
184b8ae3907Smacallan 		if ((m->offset % sizeof(cell_t)) != 0)
185b8ae3907Smacallan 			nnotcelllbl++;
186b8ae3907Smacallan 	}
187b8ae3907Smacallan 
188b8ae3907Smacallan 	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
189b8ae3907Smacallan 	    && (nnotstringlbl == 0)) {
190*cc7d2833Sskrll 		return TYPE_STRING;
191b8ae3907Smacallan 	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
192*cc7d2833Sskrll 		return TYPE_UINT32;
193b8ae3907Smacallan 	}
194b8ae3907Smacallan 
195*cc7d2833Sskrll 	return TYPE_UINT8;
196*cc7d2833Sskrll }
197*cc7d2833Sskrll 
write_propval(FILE * f,struct property * prop)198*cc7d2833Sskrll static void write_propval(FILE *f, struct property *prop)
199*cc7d2833Sskrll {
200*cc7d2833Sskrll 	size_t len = prop->val.len;
201*cc7d2833Sskrll 	struct marker *m = prop->val.markers;
202*cc7d2833Sskrll 	struct marker dummy_marker;
203*cc7d2833Sskrll 	enum markertype emit_type = TYPE_NONE;
204*cc7d2833Sskrll 	char *srcstr;
205*cc7d2833Sskrll 
206*cc7d2833Sskrll 	if (len == 0) {
207*cc7d2833Sskrll 		fprintf(f, ";");
208*cc7d2833Sskrll 		if (annotate) {
209*cc7d2833Sskrll 			srcstr = srcpos_string_first(prop->srcpos, annotate);
210*cc7d2833Sskrll 			if (srcstr) {
211*cc7d2833Sskrll 				fprintf(f, " /* %s */", srcstr);
212*cc7d2833Sskrll 				free(srcstr);
213*cc7d2833Sskrll 			}
214*cc7d2833Sskrll 		}
215*cc7d2833Sskrll 		fprintf(f, "\n");
216*cc7d2833Sskrll 		return;
217*cc7d2833Sskrll 	}
218*cc7d2833Sskrll 
219*cc7d2833Sskrll 	fprintf(f, " =");
220*cc7d2833Sskrll 
221*cc7d2833Sskrll 	if (!next_type_marker(m)) {
222*cc7d2833Sskrll 		/* data type information missing, need to guess */
223*cc7d2833Sskrll 		dummy_marker.type = guess_value_type(prop);
224*cc7d2833Sskrll 		dummy_marker.next = prop->val.markers;
225*cc7d2833Sskrll 		dummy_marker.offset = 0;
226*cc7d2833Sskrll 		dummy_marker.ref = NULL;
227*cc7d2833Sskrll 		m = &dummy_marker;
228*cc7d2833Sskrll 	}
229*cc7d2833Sskrll 
230*cc7d2833Sskrll 	for_each_marker(m) {
231*cc7d2833Sskrll 		size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
232*cc7d2833Sskrll 		size_t data_len = type_marker_length(m) ? : len - m->offset;
233*cc7d2833Sskrll 		const char *p = &prop->val.val[m->offset];
234*cc7d2833Sskrll 
235*cc7d2833Sskrll 		if (has_data_type_information(m)) {
236*cc7d2833Sskrll 			emit_type = m->type;
237*cc7d2833Sskrll 			fprintf(f, " %s", delim_start[emit_type]);
238*cc7d2833Sskrll 		} else if (m->type == LABEL)
239*cc7d2833Sskrll 			fprintf(f, " %s:", m->ref);
240*cc7d2833Sskrll 		else if (m->offset)
241*cc7d2833Sskrll 			fputc(' ', f);
242*cc7d2833Sskrll 
243*cc7d2833Sskrll 		if (emit_type == TYPE_NONE) {
244*cc7d2833Sskrll 			assert(chunk_len == 0);
245*cc7d2833Sskrll 			continue;
246*cc7d2833Sskrll 		}
247*cc7d2833Sskrll 
248*cc7d2833Sskrll 		switch(emit_type) {
249*cc7d2833Sskrll 		case TYPE_UINT16:
250*cc7d2833Sskrll 			write_propval_int(f, p, chunk_len, 2);
251*cc7d2833Sskrll 			break;
252*cc7d2833Sskrll 		case TYPE_UINT32:
253*cc7d2833Sskrll 			write_propval_int(f, p, chunk_len, 4);
254*cc7d2833Sskrll 			break;
255*cc7d2833Sskrll 		case TYPE_UINT64:
256*cc7d2833Sskrll 			write_propval_int(f, p, chunk_len, 8);
257*cc7d2833Sskrll 			break;
258*cc7d2833Sskrll 		case TYPE_STRING:
259*cc7d2833Sskrll 			write_propval_string(f, p, chunk_len);
260*cc7d2833Sskrll 			break;
261*cc7d2833Sskrll 		default:
262*cc7d2833Sskrll 			write_propval_int(f, p, chunk_len, 1);
263*cc7d2833Sskrll 		}
264*cc7d2833Sskrll 
265*cc7d2833Sskrll 		if (chunk_len == data_len) {
266*cc7d2833Sskrll 			size_t pos = m->offset + chunk_len;
267*cc7d2833Sskrll 			fprintf(f, pos == len ? "%s" : "%s,",
268*cc7d2833Sskrll 			        delim_end[emit_type] ? : "");
269*cc7d2833Sskrll 			emit_type = TYPE_NONE;
270*cc7d2833Sskrll 		}
271*cc7d2833Sskrll 	}
272*cc7d2833Sskrll 	fprintf(f, ";");
273*cc7d2833Sskrll 	if (annotate) {
274*cc7d2833Sskrll 		srcstr = srcpos_string_first(prop->srcpos, annotate);
275*cc7d2833Sskrll 		if (srcstr) {
276*cc7d2833Sskrll 			fprintf(f, " /* %s */", srcstr);
277*cc7d2833Sskrll 			free(srcstr);
278*cc7d2833Sskrll 		}
279*cc7d2833Sskrll 	}
280*cc7d2833Sskrll 	fprintf(f, "\n");
281b8ae3907Smacallan }
282b8ae3907Smacallan 
write_tree_source_node(FILE * f,struct node * tree,int level)283b8ae3907Smacallan static void write_tree_source_node(FILE *f, struct node *tree, int level)
284b8ae3907Smacallan {
285b8ae3907Smacallan 	struct property *prop;
286b8ae3907Smacallan 	struct node *child;
287b8ae3907Smacallan 	struct label *l;
288*cc7d2833Sskrll 	char *srcstr;
289b8ae3907Smacallan 
290b8ae3907Smacallan 	write_prefix(f, level);
291b8ae3907Smacallan 	for_each_label(tree->labels, l)
292b8ae3907Smacallan 		fprintf(f, "%s: ", l->label);
293b8ae3907Smacallan 	if (tree->name && (*tree->name))
294*cc7d2833Sskrll 		fprintf(f, "%s {", tree->name);
295b8ae3907Smacallan 	else
296*cc7d2833Sskrll 		fprintf(f, "/ {");
297*cc7d2833Sskrll 
298*cc7d2833Sskrll 	if (annotate) {
299*cc7d2833Sskrll 		srcstr = srcpos_string_first(tree->srcpos, annotate);
300*cc7d2833Sskrll 		if (srcstr) {
301*cc7d2833Sskrll 			fprintf(f, " /* %s */", srcstr);
302*cc7d2833Sskrll 			free(srcstr);
303*cc7d2833Sskrll 		}
304*cc7d2833Sskrll 	}
305*cc7d2833Sskrll 	fprintf(f, "\n");
306b8ae3907Smacallan 
307b8ae3907Smacallan 	for_each_property(tree, prop) {
308b8ae3907Smacallan 		write_prefix(f, level+1);
309b8ae3907Smacallan 		for_each_label(prop->labels, l)
310b8ae3907Smacallan 			fprintf(f, "%s: ", l->label);
311b8ae3907Smacallan 		fprintf(f, "%s", prop->name);
312b8ae3907Smacallan 		write_propval(f, prop);
313b8ae3907Smacallan 	}
314b8ae3907Smacallan 	for_each_child(tree, child) {
315b8ae3907Smacallan 		fprintf(f, "\n");
316b8ae3907Smacallan 		write_tree_source_node(f, child, level+1);
317b8ae3907Smacallan 	}
318b8ae3907Smacallan 	write_prefix(f, level);
319*cc7d2833Sskrll 	fprintf(f, "};");
320*cc7d2833Sskrll 	if (annotate) {
321*cc7d2833Sskrll 		srcstr = srcpos_string_last(tree->srcpos, annotate);
322*cc7d2833Sskrll 		if (srcstr) {
323*cc7d2833Sskrll 			fprintf(f, " /* %s */", srcstr);
324*cc7d2833Sskrll 			free(srcstr);
325b8ae3907Smacallan 		}
326*cc7d2833Sskrll 	}
327*cc7d2833Sskrll 	fprintf(f, "\n");
328*cc7d2833Sskrll }
329b8ae3907Smacallan 
dt_to_source(FILE * f,struct dt_info * dti)330d89652e2Sskrll void dt_to_source(FILE *f, struct dt_info *dti)
331b8ae3907Smacallan {
332b8ae3907Smacallan 	struct reserve_info *re;
333b8ae3907Smacallan 
334b8ae3907Smacallan 	fprintf(f, "/dts-v1/;\n\n");
335b8ae3907Smacallan 
336d89652e2Sskrll 	for (re = dti->reservelist; re; re = re->next) {
337b8ae3907Smacallan 		struct label *l;
338b8ae3907Smacallan 
339b8ae3907Smacallan 		for_each_label(re->labels, l)
340b8ae3907Smacallan 			fprintf(f, "%s: ", l->label);
341b8ae3907Smacallan 		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
342d89652e2Sskrll 			(unsigned long long)re->address,
343d89652e2Sskrll 			(unsigned long long)re->size);
344b8ae3907Smacallan 	}
345b8ae3907Smacallan 
346d89652e2Sskrll 	write_tree_source_node(f, dti->dt, 0);
347b8ae3907Smacallan }
348