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