OSDN Git Service

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