Home | History | Annotate | Line # | Download | only in dist
      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 (at) au1.ibm.com>, IBM Corporation.  2005.
      6  */
      7 
      8 #include "dtc.h"
      9 #include "srcpos.h"
     10 
     11 extern FILE *yyin;
     12 extern int yyparse(void);
     13 extern YYLTYPE yylloc;
     14 
     15 struct dt_info *parser_output;
     16 bool treesource_error;
     17 
     18 struct 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 
     36 static 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 
     44 static 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 
     51 static 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 
    104 static 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 
    129 static bool has_data_type_information(struct marker *m)
    130 {
    131 	return m->type >= TYPE_UINT8;
    132 }
    133 
    134 static 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 
    141 size_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 
    150 static const char *delim_start[] = {
    151 	[TYPE_UINT8] = "[",
    152 	[TYPE_UINT16] = "/bits/ 16 <",
    153 	[TYPE_UINT32] = "<",
    154 	[TYPE_UINT64] = "/bits/ 64 <",
    155 	[TYPE_STRING] = "",
    156 };
    157 static const char *delim_end[] = {
    158 	[TYPE_UINT8] = "]",
    159 	[TYPE_UINT16] = ">",
    160 	[TYPE_UINT32] = ">",
    161 	[TYPE_UINT64] = ">",
    162 	[TYPE_STRING] = "",
    163 };
    164 
    165 static 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 
    198 static 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 
    283 static 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 
    330 void 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