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