1204431Sraj/*
2204431Sraj * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3204431Sraj *
4204431Sraj *
5204431Sraj * This program is free software; you can redistribute it and/or
6204431Sraj * modify it under the terms of the GNU General Public License as
7204431Sraj * published by the Free Software Foundation; either version 2 of the
8204431Sraj * License, or (at your option) any later version.
9204431Sraj *
10204431Sraj *  This program is distributed in the hope that it will be useful,
11204431Sraj *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12204431Sraj *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13204431Sraj *  General Public License for more details.
14204431Sraj *
15204431Sraj *  You should have received a copy of the GNU General Public License
16204431Sraj *  along with this program; if not, write to the Free Software
17204431Sraj *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18204431Sraj *                                                                   USA
19204431Sraj */
20204431Sraj
21204431Sraj#include "dtc.h"
22204431Sraj#include "srcpos.h"
23204431Sraj
24204431Srajextern FILE *yyin;
25204431Srajextern int yyparse(void);
26238742Simpextern YYLTYPE yylloc;
27204431Sraj
28318102Sgonzostruct dt_info *parser_output;
29261215Simpbool treesource_error;
30204431Sraj
31318102Sgonzostruct dt_info *dt_from_source(const char *fname)
32204431Sraj{
33318102Sgonzo	parser_output = NULL;
34261215Simp	treesource_error = false;
35204431Sraj
36238742Simp	srcfile_push(fname);
37238742Simp	yyin = current_srcfile->f;
38238742Simp	yylloc.file = current_srcfile;
39204431Sraj
40204431Sraj	if (yyparse() != 0)
41204431Sraj		die("Unable to parse input tree\n");
42204431Sraj
43204431Sraj	if (treesource_error)
44204431Sraj		die("Syntax error parsing input tree\n");
45204431Sraj
46318102Sgonzo	return parser_output;
47204431Sraj}
48204431Sraj
49204431Srajstatic void write_prefix(FILE *f, int level)
50204431Sraj{
51204431Sraj	int i;
52204431Sraj
53204431Sraj	for (i = 0; i < level; i++)
54204431Sraj		fputc('\t', f);
55204431Sraj}
56204431Sraj
57261215Simpstatic bool isstring(char c)
58204431Sraj{
59261215Simp	return (isprint((unsigned char)c)
60204431Sraj		|| (c == '\0')
61204431Sraj		|| strchr("\a\b\t\n\v\f\r", c));
62204431Sraj}
63204431Sraj
64204431Srajstatic void write_propval_string(FILE *f, struct data val)
65204431Sraj{
66204431Sraj	const char *str = val.val;
67204431Sraj	int i;
68204431Sraj	struct marker *m = val.markers;
69204431Sraj
70204431Sraj	assert(str[val.len-1] == '\0');
71204431Sraj
72204433Sraj	while (m && (m->offset == 0)) {
73204433Sraj		if (m->type == LABEL)
74204433Sraj			fprintf(f, "%s: ", m->ref);
75204433Sraj		m = m->next;
76204433Sraj	}
77204433Sraj	fprintf(f, "\"");
78204433Sraj
79204431Sraj	for (i = 0; i < (val.len-1); i++) {
80204431Sraj		char c = str[i];
81204431Sraj
82204431Sraj		switch (c) {
83204431Sraj		case '\a':
84204431Sraj			fprintf(f, "\\a");
85204431Sraj			break;
86204431Sraj		case '\b':
87204431Sraj			fprintf(f, "\\b");
88204431Sraj			break;
89204431Sraj		case '\t':
90204431Sraj			fprintf(f, "\\t");
91204431Sraj			break;
92204431Sraj		case '\n':
93204431Sraj			fprintf(f, "\\n");
94204431Sraj			break;
95204431Sraj		case '\v':
96204431Sraj			fprintf(f, "\\v");
97204431Sraj			break;
98204431Sraj		case '\f':
99204431Sraj			fprintf(f, "\\f");
100204431Sraj			break;
101204431Sraj		case '\r':
102204431Sraj			fprintf(f, "\\r");
103204431Sraj			break;
104204431Sraj		case '\\':
105204431Sraj			fprintf(f, "\\\\");
106204431Sraj			break;
107204431Sraj		case '\"':
108204431Sraj			fprintf(f, "\\\"");
109204431Sraj			break;
110204431Sraj		case '\0':
111204431Sraj			fprintf(f, "\", ");
112318102Sgonzo			while (m && (m->offset <= (i + 1))) {
113204433Sraj				if (m->type == LABEL) {
114204433Sraj					assert(m->offset == (i+1));
115204433Sraj					fprintf(f, "%s: ", m->ref);
116204433Sraj				}
117204433Sraj				m = m->next;
118204433Sraj			}
119204433Sraj			fprintf(f, "\"");
120204431Sraj			break;
121204431Sraj		default:
122261215Simp			if (isprint((unsigned char)c))
123204431Sraj				fprintf(f, "%c", c);
124204431Sraj			else
125204431Sraj				fprintf(f, "\\x%02hhx", c);
126204431Sraj		}
127204431Sraj	}
128204431Sraj	fprintf(f, "\"");
129204431Sraj
130204431Sraj	/* Wrap up any labels at the end of the value */
131204431Sraj	for_each_marker_of_type(m, LABEL) {
132204431Sraj		assert (m->offset == val.len);
133204431Sraj		fprintf(f, " %s:", m->ref);
134204431Sraj	}
135204431Sraj}
136204431Sraj
137204431Srajstatic void write_propval_cells(FILE *f, struct data val)
138204431Sraj{
139204431Sraj	void *propend = val.val + val.len;
140204431Sraj	cell_t *cp = (cell_t *)val.val;
141204431Sraj	struct marker *m = val.markers;
142204431Sraj
143204431Sraj	fprintf(f, "<");
144204431Sraj	for (;;) {
145204431Sraj		while (m && (m->offset <= ((char *)cp - val.val))) {
146204431Sraj			if (m->type == LABEL) {
147204431Sraj				assert(m->offset == ((char *)cp - val.val));
148204431Sraj				fprintf(f, "%s: ", m->ref);
149204431Sraj			}
150204431Sraj			m = m->next;
151204431Sraj		}
152204431Sraj
153204431Sraj		fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
154204431Sraj		if ((void *)cp >= propend)
155204431Sraj			break;
156204431Sraj		fprintf(f, " ");
157204431Sraj	}
158204431Sraj
159204431Sraj	/* Wrap up any labels at the end of the value */
160204431Sraj	for_each_marker_of_type(m, LABEL) {
161204431Sraj		assert (m->offset == val.len);
162204431Sraj		fprintf(f, " %s:", m->ref);
163204431Sraj	}
164204431Sraj	fprintf(f, ">");
165204431Sraj}
166204431Sraj
167204431Srajstatic void write_propval_bytes(FILE *f, struct data val)
168204431Sraj{
169204431Sraj	void *propend = val.val + val.len;
170204431Sraj	const char *bp = val.val;
171204431Sraj	struct marker *m = val.markers;
172204431Sraj
173204431Sraj	fprintf(f, "[");
174204431Sraj	for (;;) {
175204431Sraj		while (m && (m->offset == (bp-val.val))) {
176204431Sraj			if (m->type == LABEL)
177204431Sraj				fprintf(f, "%s: ", m->ref);
178204431Sraj			m = m->next;
179204431Sraj		}
180204431Sraj
181318102Sgonzo		fprintf(f, "%02hhx", (unsigned char)(*bp++));
182204431Sraj		if ((const void *)bp >= propend)
183204431Sraj			break;
184204431Sraj		fprintf(f, " ");
185204431Sraj	}
186204431Sraj
187204431Sraj	/* Wrap up any labels at the end of the value */
188204431Sraj	for_each_marker_of_type(m, LABEL) {
189204431Sraj		assert (m->offset == val.len);
190204431Sraj		fprintf(f, " %s:", m->ref);
191204431Sraj	}
192204431Sraj	fprintf(f, "]");
193204431Sraj}
194204431Sraj
195204431Srajstatic void write_propval(FILE *f, struct property *prop)
196204431Sraj{
197204431Sraj	int len = prop->val.len;
198204431Sraj	const char *p = prop->val.val;
199204431Sraj	struct marker *m = prop->val.markers;
200204431Sraj	int nnotstring = 0, nnul = 0;
201204431Sraj	int nnotstringlbl = 0, nnotcelllbl = 0;
202204431Sraj	int i;
203204431Sraj
204204431Sraj	if (len == 0) {
205204431Sraj		fprintf(f, ";\n");
206204431Sraj		return;
207204431Sraj	}
208204431Sraj
209204431Sraj	for (i = 0; i < len; i++) {
210204431Sraj		if (! isstring(p[i]))
211204431Sraj			nnotstring++;
212204431Sraj		if (p[i] == '\0')
213204431Sraj			nnul++;
214204431Sraj	}
215204431Sraj
216204431Sraj	for_each_marker_of_type(m, LABEL) {
217204431Sraj		if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
218204431Sraj			nnotstringlbl++;
219204431Sraj		if ((m->offset % sizeof(cell_t)) != 0)
220204431Sraj			nnotcelllbl++;
221204431Sraj	}
222204431Sraj
223204431Sraj	fprintf(f, " = ");
224204431Sraj	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
225204431Sraj	    && (nnotstringlbl == 0)) {
226204431Sraj		write_propval_string(f, prop->val);
227204431Sraj	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
228204431Sraj		write_propval_cells(f, prop->val);
229204431Sraj	} else {
230204431Sraj		write_propval_bytes(f, prop->val);
231204431Sraj	}
232204431Sraj
233204431Sraj	fprintf(f, ";\n");
234204431Sraj}
235204431Sraj
236204431Srajstatic void write_tree_source_node(FILE *f, struct node *tree, int level)
237204431Sraj{
238204431Sraj	struct property *prop;
239204431Sraj	struct node *child;
240238742Simp	struct label *l;
241204431Sraj
242204431Sraj	write_prefix(f, level);
243238742Simp	for_each_label(tree->labels, l)
244238742Simp		fprintf(f, "%s: ", l->label);
245204431Sraj	if (tree->name && (*tree->name))
246204431Sraj		fprintf(f, "%s {\n", tree->name);
247204431Sraj	else
248204431Sraj		fprintf(f, "/ {\n");
249204431Sraj
250204431Sraj	for_each_property(tree, prop) {
251204431Sraj		write_prefix(f, level+1);
252238742Simp		for_each_label(prop->labels, l)
253238742Simp			fprintf(f, "%s: ", l->label);
254204431Sraj		fprintf(f, "%s", prop->name);
255204431Sraj		write_propval(f, prop);
256204431Sraj	}
257204431Sraj	for_each_child(tree, child) {
258204431Sraj		fprintf(f, "\n");
259204431Sraj		write_tree_source_node(f, child, level+1);
260204431Sraj	}
261204431Sraj	write_prefix(f, level);
262204431Sraj	fprintf(f, "};\n");
263204431Sraj}
264204431Sraj
265204431Sraj
266318102Sgonzovoid dt_to_source(FILE *f, struct dt_info *dti)
267204431Sraj{
268204431Sraj	struct reserve_info *re;
269204431Sraj
270204431Sraj	fprintf(f, "/dts-v1/;\n\n");
271204431Sraj
272318102Sgonzo	for (re = dti->reservelist; re; re = re->next) {
273238742Simp		struct label *l;
274238742Simp
275238742Simp		for_each_label(re->labels, l)
276238742Simp			fprintf(f, "%s: ", l->label);
277204431Sraj		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
278204431Sraj			(unsigned long long)re->re.address,
279204431Sraj			(unsigned long long)re->re.size);
280204431Sraj	}
281204431Sraj
282318102Sgonzo	write_tree_source_node(f, dti->dt, 0);
283204431Sraj}
284204431Sraj
285