xref: /netbsd-src/external/gpl2/dtc/dist/treesource.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: treesource.c,v 1.1.1.2 2017/06/08 15:59:21 skrll Exp $	*/
2 
3 /*
4  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
5  *
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
20  *                                                                   USA
21  */
22 
23 #include "dtc.h"
24 #include "srcpos.h"
25 
26 extern FILE *yyin;
27 extern int yyparse(void);
28 extern YYLTYPE yylloc;
29 
30 struct dt_info *parser_output;
31 bool treesource_error;
32 
33 struct dt_info *dt_from_source(const char *fname)
34 {
35 	parser_output = NULL;
36 	treesource_error = false;
37 
38 	srcfile_push(fname);
39 	yyin = current_srcfile->f;
40 	yylloc.file = current_srcfile;
41 
42 	if (yyparse() != 0)
43 		die("Unable to parse input tree\n");
44 
45 	if (treesource_error)
46 		die("Syntax error parsing input tree\n");
47 
48 	return parser_output;
49 }
50 
51 static void write_prefix(FILE *f, int level)
52 {
53 	int i;
54 
55 	for (i = 0; i < level; i++)
56 		fputc('\t', f);
57 }
58 
59 static bool isstring(char c)
60 {
61 	return (isprint((unsigned char)c)
62 		|| (c == '\0')
63 		|| strchr("\a\b\t\n\v\f\r", c));
64 }
65 
66 static void write_propval_string(FILE *f, struct data val)
67 {
68 	const char *str = val.val;
69 	int i;
70 	struct marker *m = val.markers;
71 
72 	assert(str[val.len-1] == '\0');
73 
74 	while (m && (m->offset == 0)) {
75 		if (m->type == LABEL)
76 			fprintf(f, "%s: ", m->ref);
77 		m = m->next;
78 	}
79 	fprintf(f, "\"");
80 
81 	for (i = 0; i < (val.len-1); i++) {
82 		char c = str[i];
83 
84 		switch (c) {
85 		case '\a':
86 			fprintf(f, "\\a");
87 			break;
88 		case '\b':
89 			fprintf(f, "\\b");
90 			break;
91 		case '\t':
92 			fprintf(f, "\\t");
93 			break;
94 		case '\n':
95 			fprintf(f, "\\n");
96 			break;
97 		case '\v':
98 			fprintf(f, "\\v");
99 			break;
100 		case '\f':
101 			fprintf(f, "\\f");
102 			break;
103 		case '\r':
104 			fprintf(f, "\\r");
105 			break;
106 		case '\\':
107 			fprintf(f, "\\\\");
108 			break;
109 		case '\"':
110 			fprintf(f, "\\\"");
111 			break;
112 		case '\0':
113 			fprintf(f, "\", ");
114 			while (m && (m->offset <= (i + 1))) {
115 				if (m->type == LABEL) {
116 					assert(m->offset == (i+1));
117 					fprintf(f, "%s: ", m->ref);
118 				}
119 				m = m->next;
120 			}
121 			fprintf(f, "\"");
122 			break;
123 		default:
124 			if (isprint((unsigned char)c))
125 				fprintf(f, "%c", c);
126 			else
127 				fprintf(f, "\\x%02hhx", c);
128 		}
129 	}
130 	fprintf(f, "\"");
131 
132 	/* Wrap up any labels at the end of the value */
133 	for_each_marker_of_type(m, LABEL) {
134 		assert (m->offset == val.len);
135 		fprintf(f, " %s:", m->ref);
136 	}
137 }
138 
139 static void write_propval_cells(FILE *f, struct data val)
140 {
141 	void *propend = val.val + val.len;
142 	fdt32_t *cp = (fdt32_t *)val.val;
143 	struct marker *m = val.markers;
144 
145 	fprintf(f, "<");
146 	for (;;) {
147 		while (m && (m->offset <= ((char *)cp - val.val))) {
148 			if (m->type == LABEL) {
149 				assert(m->offset == ((char *)cp - val.val));
150 				fprintf(f, "%s: ", m->ref);
151 			}
152 			m = m->next;
153 		}
154 
155 		fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
156 		if ((void *)cp >= propend)
157 			break;
158 		fprintf(f, " ");
159 	}
160 
161 	/* Wrap up any labels at the end of the value */
162 	for_each_marker_of_type(m, LABEL) {
163 		assert (m->offset == val.len);
164 		fprintf(f, " %s:", m->ref);
165 	}
166 	fprintf(f, ">");
167 }
168 
169 static void write_propval_bytes(FILE *f, struct data val)
170 {
171 	void *propend = val.val + val.len;
172 	const char *bp = val.val;
173 	struct marker *m = val.markers;
174 
175 	fprintf(f, "[");
176 	for (;;) {
177 		while (m && (m->offset == (bp-val.val))) {
178 			if (m->type == LABEL)
179 				fprintf(f, "%s: ", m->ref);
180 			m = m->next;
181 		}
182 
183 		fprintf(f, "%02hhx", (unsigned char)(*bp++));
184 		if ((const void *)bp >= propend)
185 			break;
186 		fprintf(f, " ");
187 	}
188 
189 	/* Wrap up any labels at the end of the value */
190 	for_each_marker_of_type(m, LABEL) {
191 		assert (m->offset == val.len);
192 		fprintf(f, " %s:", m->ref);
193 	}
194 	fprintf(f, "]");
195 }
196 
197 static void write_propval(FILE *f, struct property *prop)
198 {
199 	int len = prop->val.len;
200 	const char *p = prop->val.val;
201 	struct marker *m = prop->val.markers;
202 	int nnotstring = 0, nnul = 0;
203 	int nnotstringlbl = 0, nnotcelllbl = 0;
204 	int i;
205 
206 	if (len == 0) {
207 		fprintf(f, ";\n");
208 		return;
209 	}
210 
211 	for (i = 0; i < len; i++) {
212 		if (! isstring(p[i]))
213 			nnotstring++;
214 		if (p[i] == '\0')
215 			nnul++;
216 	}
217 
218 	for_each_marker_of_type(m, LABEL) {
219 		if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
220 			nnotstringlbl++;
221 		if ((m->offset % sizeof(cell_t)) != 0)
222 			nnotcelllbl++;
223 	}
224 
225 	fprintf(f, " = ");
226 	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
227 	    && (nnotstringlbl == 0)) {
228 		write_propval_string(f, prop->val);
229 	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
230 		write_propval_cells(f, prop->val);
231 	} else {
232 		write_propval_bytes(f, prop->val);
233 	}
234 
235 	fprintf(f, ";\n");
236 }
237 
238 static void write_tree_source_node(FILE *f, struct node *tree, int level)
239 {
240 	struct property *prop;
241 	struct node *child;
242 	struct label *l;
243 
244 	write_prefix(f, level);
245 	for_each_label(tree->labels, l)
246 		fprintf(f, "%s: ", l->label);
247 	if (tree->name && (*tree->name))
248 		fprintf(f, "%s {\n", tree->name);
249 	else
250 		fprintf(f, "/ {\n");
251 
252 	for_each_property(tree, prop) {
253 		write_prefix(f, level+1);
254 		for_each_label(prop->labels, l)
255 			fprintf(f, "%s: ", l->label);
256 		fprintf(f, "%s", prop->name);
257 		write_propval(f, prop);
258 	}
259 	for_each_child(tree, child) {
260 		fprintf(f, "\n");
261 		write_tree_source_node(f, child, level+1);
262 	}
263 	write_prefix(f, level);
264 	fprintf(f, "};\n");
265 }
266 
267 
268 void dt_to_source(FILE *f, struct dt_info *dti)
269 {
270 	struct reserve_info *re;
271 
272 	fprintf(f, "/dts-v1/;\n\n");
273 
274 	for (re = dti->reservelist; re; re = re->next) {
275 		struct label *l;
276 
277 		for_each_label(re->labels, l)
278 			fprintf(f, "%s: ", l->label);
279 		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
280 			(unsigned long long)re->address,
281 			(unsigned long long)re->size);
282 	}
283 
284 	write_tree_source_node(f, dti->dt, 0);
285 }
286 
287