2019-05-27 09:55:05 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2007-12-18 07:06:42 +03:00
/*
* ( C ) Copyright David Gibson < dwg @ au1 . ibm . com > , IBM Corporation . 2005.
*/
# include "dtc.h"
# include "srcpos.h"
extern FILE * yyin ;
extern int yyparse ( void ) ;
2012-09-29 01:25:59 +04:00
extern YYLTYPE yylloc ;
2007-12-18 07:06:42 +03:00
2017-01-04 19:45:20 +03:00
struct dt_info * parser_output ;
2015-04-30 00:00:05 +03:00
bool treesource_error ;
2007-12-18 07:06:42 +03:00
2017-01-04 19:45:20 +03:00
struct dt_info * dt_from_source ( const char * fname )
2007-12-18 07:06:42 +03:00
{
2017-01-04 19:45:20 +03:00
parser_output = NULL ;
2015-04-30 00:00:05 +03:00
treesource_error = false ;
2007-12-18 07:06:42 +03:00
2010-11-18 02:28:20 +03:00
srcfile_push ( fname ) ;
yyin = current_srcfile - > f ;
2012-09-29 01:25:59 +04:00
yylloc . file = current_srcfile ;
2007-12-18 07:06:42 +03:00
if ( yyparse ( ) ! = 0 )
2008-08-07 06:24:17 +04:00
die ( " Unable to parse input tree \n " ) ;
2007-12-18 07:06:42 +03:00
2008-08-07 06:24:17 +04:00
if ( treesource_error )
die ( " Syntax error parsing input tree \n " ) ;
2007-12-18 07:06:42 +03:00
2017-01-04 19:45:20 +03:00
return parser_output ;
2007-12-18 07:06:42 +03:00
}
static void write_prefix ( FILE * f , int level )
{
int i ;
for ( i = 0 ; i < level ; i + + )
fputc ( ' \t ' , f ) ;
}
2015-04-30 00:00:05 +03:00
static bool isstring ( char c )
2007-12-18 07:06:42 +03:00
{
2015-04-30 00:00:05 +03:00
return ( isprint ( ( unsigned char ) c )
2007-12-18 07:06:42 +03:00
| | ( c = = ' \0 ' )
| | strchr ( " \a \b \t \n \v \f \r " , c ) ) ;
}
2018-09-13 16:59:25 +03:00
static void write_propval_string ( FILE * f , const char * s , size_t len )
2007-12-18 07:06:42 +03:00
{
2018-09-13 16:59:25 +03:00
const char * end = s + len - 1 ;
2018-11-29 03:37:35 +03:00
if ( ! len )
return ;
2018-09-13 16:59:25 +03:00
assert ( * end = = ' \0 ' ) ;
2007-12-18 07:06:42 +03:00
2010-11-18 02:28:20 +03:00
fprintf ( f , " \" " ) ;
2018-09-13 16:59:25 +03:00
while ( s < end ) {
char c = * s + + ;
2007-12-18 07:06:42 +03:00
switch ( c ) {
case ' \a ' :
fprintf ( f , " \\ a " ) ;
break ;
case ' \b ' :
fprintf ( f , " \\ b " ) ;
break ;
case ' \t ' :
fprintf ( f , " \\ t " ) ;
break ;
case ' \n ' :
fprintf ( f , " \\ n " ) ;
break ;
case ' \v ' :
fprintf ( f , " \\ v " ) ;
break ;
case ' \f ' :
fprintf ( f , " \\ f " ) ;
break ;
case ' \r ' :
fprintf ( f , " \\ r " ) ;
break ;
case ' \\ ' :
fprintf ( f , " \\ \\ " ) ;
break ;
case ' \" ' :
fprintf ( f , " \\ \" " ) ;
break ;
case ' \0 ' :
2018-09-13 16:59:25 +03:00
fprintf ( f , " \\ 0 " ) ;
2007-12-18 07:06:42 +03:00
break ;
default :
2015-04-30 00:00:05 +03:00
if ( isprint ( ( unsigned char ) c ) )
2007-12-18 07:06:42 +03:00
fprintf ( f , " %c " , c ) ;
else
2018-09-13 16:59:25 +03:00
fprintf ( f , " \\ x%02 " PRIx8 , c ) ;
2007-12-18 07:06:42 +03:00
}
}
fprintf ( f , " \" " ) ;
}
2018-09-13 16:59:25 +03:00
static void write_propval_int ( FILE * f , const char * p , size_t len , size_t width )
2007-12-18 07:06:42 +03:00
{
2018-09-13 16:59:25 +03:00
const char * end = p + len ;
assert ( len % width = = 0 ) ;
2007-12-18 07:06:42 +03:00
2018-09-13 16:59:25 +03:00
for ( ; p < end ; p + = width ) {
switch ( width ) {
case 1 :
2018-11-29 03:37:35 +03:00
fprintf ( f , " %02 " PRIx8 , * ( const uint8_t * ) p ) ;
2018-09-13 16:59:25 +03:00
break ;
case 2 :
2018-11-29 03:37:35 +03:00
fprintf ( f , " 0x%02 " PRIx16 , fdt16_to_cpu ( * ( const fdt16_t * ) p ) ) ;
2018-09-13 16:59:25 +03:00
break ;
case 4 :
2018-11-29 03:37:35 +03:00
fprintf ( f , " 0x%02 " PRIx32 , fdt32_to_cpu ( * ( const fdt32_t * ) p ) ) ;
2018-09-13 16:59:25 +03:00
break ;
case 8 :
2018-11-29 03:37:35 +03:00
fprintf ( f , " 0x%02 " PRIx64 , fdt64_to_cpu ( * ( const fdt64_t * ) p ) ) ;
2007-12-18 07:06:42 +03:00
break ;
2018-09-13 16:59:25 +03:00
}
2018-11-29 03:37:35 +03:00
if ( p + width < end )
fputc ( ' ' , f ) ;
2007-12-18 07:06:42 +03:00
}
2018-09-13 16:59:25 +03:00
}
2007-12-18 07:06:42 +03:00
2018-09-13 16:59:25 +03:00
static bool has_data_type_information ( struct marker * m )
{
return m - > type > = TYPE_UINT8 ;
2007-12-18 07:06:42 +03:00
}
2018-09-13 16:59:25 +03:00
static struct marker * next_type_marker ( struct marker * m )
2007-12-18 07:06:42 +03:00
{
2018-09-13 16:59:25 +03:00
while ( m & & ! has_data_type_information ( m ) )
m = m - > next ;
return m ;
}
2007-12-18 07:06:42 +03:00
2018-09-13 16:59:25 +03:00
size_t type_marker_length ( struct marker * m )
{
struct marker * next = next_type_marker ( m - > next ) ;
2007-12-18 07:06:42 +03:00
2018-09-13 16:59:25 +03:00
if ( next )
return next - > offset - m - > offset ;
return 0 ;
2007-12-18 07:06:42 +03:00
}
2018-09-13 16:59:25 +03:00
static const char * delim_start [ ] = {
[ TYPE_UINT8 ] = " [ " ,
[ TYPE_UINT16 ] = " /bits/ 16 < " ,
[ TYPE_UINT32 ] = " < " ,
[ TYPE_UINT64 ] = " /bits/ 64 < " ,
[ TYPE_STRING ] = " " ,
} ;
static const char * delim_end [ ] = {
2018-11-29 03:37:35 +03:00
[ TYPE_UINT8 ] = " ] " ,
[ TYPE_UINT16 ] = " > " ,
[ TYPE_UINT32 ] = " > " ,
[ TYPE_UINT64 ] = " > " ,
2018-09-13 16:59:25 +03:00
[ TYPE_STRING ] = " " ,
} ;
static enum markertype guess_value_type ( struct property * prop )
2007-12-18 07:06:42 +03:00
{
int len = prop - > val . len ;
const char * p = prop - > val . val ;
struct marker * m = prop - > val . markers ;
int nnotstring = 0 , nnul = 0 ;
int nnotstringlbl = 0 , nnotcelllbl = 0 ;
int i ;
for ( i = 0 ; i < len ; i + + ) {
if ( ! isstring ( p [ i ] ) )
nnotstring + + ;
if ( p [ i ] = = ' \0 ' )
nnul + + ;
}
for_each_marker_of_type ( m , LABEL ) {
if ( ( m - > offset > 0 ) & & ( prop - > val . val [ m - > offset - 1 ] ! = ' \0 ' ) )
nnotstringlbl + + ;
if ( ( m - > offset % sizeof ( cell_t ) ) ! = 0 )
nnotcelllbl + + ;
}
if ( ( p [ len - 1 ] = = ' \0 ' ) & & ( nnotstring = = 0 ) & & ( nnul < ( len - nnul ) )
& & ( nnotstringlbl = = 0 ) ) {
2018-09-13 16:59:25 +03:00
return TYPE_STRING ;
2007-12-18 07:06:42 +03:00
} else if ( ( ( len % sizeof ( cell_t ) ) = = 0 ) & & ( nnotcelllbl = = 0 ) ) {
2018-09-13 16:59:25 +03:00
return TYPE_UINT32 ;
2007-12-18 07:06:42 +03:00
}
2018-09-13 16:59:25 +03:00
return TYPE_UINT8 ;
}
static void write_propval ( FILE * f , struct property * prop )
{
size_t len = prop - > val . len ;
struct marker * m = prop - > val . markers ;
struct marker dummy_marker ;
enum markertype emit_type = TYPE_NONE ;
2018-11-29 03:37:35 +03:00
char * srcstr ;
2018-09-13 16:59:25 +03:00
if ( len = = 0 ) {
2018-11-29 03:37:35 +03:00
fprintf ( f , " ; " ) ;
if ( annotate ) {
srcstr = srcpos_string_first ( prop - > srcpos , annotate ) ;
if ( srcstr ) {
fprintf ( f , " /* %s */ " , srcstr ) ;
free ( srcstr ) ;
}
}
fprintf ( f , " \n " ) ;
2018-09-13 16:59:25 +03:00
return ;
}
2018-11-29 03:37:35 +03:00
fprintf ( f , " = " ) ;
2018-09-13 16:59:25 +03:00
if ( ! next_type_marker ( m ) ) {
/* data type information missing, need to guess */
dummy_marker . type = guess_value_type ( prop ) ;
dummy_marker . next = prop - > val . markers ;
dummy_marker . offset = 0 ;
dummy_marker . ref = NULL ;
m = & dummy_marker ;
}
for_each_marker ( m ) {
2018-11-29 03:37:35 +03:00
size_t chunk_len = ( m - > next ? m - > next - > offset : len ) - m - > offset ;
size_t data_len = type_marker_length ( m ) ? : len - m - > offset ;
2018-09-13 16:59:25 +03:00
const char * p = & prop - > val . val [ m - > offset ] ;
2018-11-29 03:37:35 +03:00
if ( has_data_type_information ( m ) ) {
emit_type = m - > type ;
fprintf ( f , " %s " , delim_start [ emit_type ] ) ;
} else if ( m - > type = = LABEL )
fprintf ( f , " %s: " , m - > ref ) ;
else if ( m - > offset )
fputc ( ' ' , f ) ;
2018-09-13 16:59:25 +03:00
2018-11-29 03:37:35 +03:00
if ( emit_type = = TYPE_NONE ) {
assert ( chunk_len = = 0 ) ;
2018-09-13 16:59:25 +03:00
continue ;
2018-11-29 03:37:35 +03:00
}
2018-09-13 16:59:25 +03:00
switch ( emit_type ) {
case TYPE_UINT16 :
write_propval_int ( f , p , chunk_len , 2 ) ;
break ;
case TYPE_UINT32 :
write_propval_int ( f , p , chunk_len , 4 ) ;
break ;
case TYPE_UINT64 :
write_propval_int ( f , p , chunk_len , 8 ) ;
break ;
case TYPE_STRING :
write_propval_string ( f , p , chunk_len ) ;
break ;
default :
write_propval_int ( f , p , chunk_len , 1 ) ;
}
2018-11-29 03:37:35 +03:00
if ( chunk_len = = data_len ) {
size_t pos = m - > offset + chunk_len ;
fprintf ( f , pos = = len ? " %s " : " %s, " ,
delim_end [ emit_type ] ? : " " ) ;
emit_type = TYPE_NONE ;
}
2018-09-13 16:59:25 +03:00
}
2018-11-29 03:37:35 +03:00
fprintf ( f , " ; " ) ;
if ( annotate ) {
srcstr = srcpos_string_first ( prop - > srcpos , annotate ) ;
if ( srcstr ) {
fprintf ( f , " /* %s */ " , srcstr ) ;
free ( srcstr ) ;
}
}
fprintf ( f , " \n " ) ;
2007-12-18 07:06:42 +03:00
}
static void write_tree_source_node ( FILE * f , struct node * tree , int level )
{
struct property * prop ;
struct node * child ;
2010-11-18 02:28:20 +03:00
struct label * l ;
2018-11-29 03:37:35 +03:00
char * srcstr ;
2007-12-18 07:06:42 +03:00
write_prefix ( f , level ) ;
2010-11-18 02:28:20 +03:00
for_each_label ( tree - > labels , l )
fprintf ( f , " %s: " , l - > label ) ;
2007-12-18 07:06:42 +03:00
if ( tree - > name & & ( * tree - > name ) )
2018-11-29 03:37:35 +03:00
fprintf ( f , " %s { " , tree - > name ) ;
2007-12-18 07:06:42 +03:00
else
2018-11-29 03:37:35 +03:00
fprintf ( f , " / { " ) ;
if ( annotate ) {
srcstr = srcpos_string_first ( tree - > srcpos , annotate ) ;
if ( srcstr ) {
fprintf ( f , " /* %s */ " , srcstr ) ;
free ( srcstr ) ;
}
}
fprintf ( f , " \n " ) ;
2007-12-18 07:06:42 +03:00
for_each_property ( tree , prop ) {
write_prefix ( f , level + 1 ) ;
2010-11-18 02:28:20 +03:00
for_each_label ( prop - > labels , l )
fprintf ( f , " %s: " , l - > label ) ;
2007-12-18 07:06:42 +03:00
fprintf ( f , " %s " , prop - > name ) ;
write_propval ( f , prop ) ;
}
for_each_child ( tree , child ) {
fprintf ( f , " \n " ) ;
write_tree_source_node ( f , child , level + 1 ) ;
}
write_prefix ( f , level ) ;
2018-11-29 03:37:35 +03:00
fprintf ( f , " }; " ) ;
if ( annotate ) {
srcstr = srcpos_string_last ( tree - > srcpos , annotate ) ;
if ( srcstr ) {
fprintf ( f , " /* %s */ " , srcstr ) ;
free ( srcstr ) ;
}
}
fprintf ( f , " \n " ) ;
2007-12-18 07:06:42 +03:00
}
2017-01-04 19:45:20 +03:00
void dt_to_source ( FILE * f , struct dt_info * dti )
2007-12-18 07:06:42 +03:00
{
struct reserve_info * re ;
fprintf ( f , " /dts-v1/; \n \n " ) ;
2017-01-04 19:45:20 +03:00
for ( re = dti - > reservelist ; re ; re = re - > next ) {
2010-11-18 02:28:20 +03:00
struct label * l ;
for_each_label ( re - > labels , l )
fprintf ( f , " %s: " , l - > label ) ;
2007-12-18 07:06:42 +03:00
fprintf ( f , " /memreserve/ \t 0x%016llx 0x%016llx; \n " ,
2017-03-21 17:01:08 +03:00
( unsigned long long ) re - > address ,
( unsigned long long ) re - > size ) ;
2007-12-18 07:06:42 +03:00
}
2017-01-04 19:45:20 +03:00
write_tree_source_node ( f , dti - > dt , 0 ) ;
2007-12-18 07:06:42 +03:00
}