From: Michael Wiebusch Date: Wed, 10 Jul 2013 13:55:45 +0000 (+0200) Subject: new: ini2xml.pl to decode bertram style ini files to structured xml files X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=d7f70efd963274dbffbdafeaea89dea710c4638b;p=mvdsensorcontrol.git new: ini2xml.pl to decode bertram style ini files to structured xml files --- diff --git a/xml_spielwiese/Common.pm b/xml_spielwiese/Common.pm new file mode 100644 index 0000000..b3be41d --- /dev/null +++ b/xml_spielwiese/Common.pm @@ -0,0 +1,97 @@ +#!/usr/bin/perl -w + + +sub any2hex { + + my $argument = $_[0]; + + # check if hex + if ($argument =~ m/^0[xX]([0-9a-fA-F]+)$/){ + return "0x".stripLeadingZeros($1); + } + # check if binary + if ($argument =~ m/^0[bB]([01]+)$/){ + return "0x".binStr2hexStr($1); + } + # check if decimal + if ($argument =~ m/^[0-9]+$/){ + if ($argument > 4294967295) { + die "Decimal value too big vor 32 bit unsigned integer! Use hex instead."; + } + return sprintf("0x%X",$argument); + } + + # if nothing matches + die "argument is not a recognized numeric value!\n"; + +} + +sub any2dec { # converts numeric expressions 0x, 0b or decimal to decimal + + my $argument = $_[0]; + #print "any2dec input argument $argument\n"; + + if ( $argument =~ m/0[bxBX]/) { + return oct $argument; + } else { + return $argument; + } +} + + + +sub stripLeadingZeros{ + my $string = $_[0]; + $string =~ s/^0+//; + if(length($string) ==0) {$string="0";} + return $string; + +} + + + +sub hexStr2binStr { + + my $hexStr = $_[0]; + my @hexStrArr = split(//,$hexStr); + my @binStrArr; + for my $hexNibble (@hexStrArr){ + my $binNibble = sprintf("%04b",hex $hexNibble); + push(@binStrArr,$binNibble); + } + my $binStr = join("",@binStrArr); + + return $binStr; + +} + +sub binStr2hexStr { + + my $binStr = $_[0]; + my @hexNibbleArr; + my $binStrLen = length($binStr); + my $i; + for ($i=$binStrLen-4;$i>=0;$i-=4){ + my $binNibble = substr $binStr,$i,4; + my $hexNibble = sprintf("%X",oct("0b".$binNibble)); + unshift(@hexNibbleArr,$hexNibble); + } + if($i>(-4)){ + #print VERBOSE "binary string length not multiple of 4, no biggie ...\n"; + my $binNibble = substr $binStr,0,(4+$i); + my $hexNibble = sprintf("%X",oct("0b".$binNibble)); + unshift(@hexNibbleArr,$hexNibble); + } + + my $hexString = join("",@hexNibbleArr); + return stripLeadingZeros($hexString); + +} + + + + + +1; + +__END__ diff --git a/xml_spielwiese/ini2xml.pl b/xml_spielwiese/ini2xml.pl new file mode 100755 index 0000000..6da51f2 --- /dev/null +++ b/xml_spielwiese/ini2xml.pl @@ -0,0 +1,319 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; +use XML::LibXML; +use POSIX; +use Getopt::Long; +use Pod::Usage; +#use bignum qw/hex/; + +require Common; + + + +# TODO: +# decimal option? + +# done: +# check if setting is identical with default value, if true ommit? + + +# manage command line options +my $help=0; +my $ini=0; +my $specFile=0; +my $output=0; +my $verbose=0; +my $decimal=0; +my $testblock=0; +my $redundant=0; + +Getopt::Long::Configure(qw(gnu_getopt)); +GetOptions( + 'help|h' => \$help, + 'verbose|v' => \$verbose, + 'ini|i=s' => \$ini, + 'spec|s=s' => \$specFile, + 'output|o=s' => \$output, + 'decimal|d' => \$decimal, + 'redundant|r' => \$redundant, + 'testblock|t' => \$testblock + ) or pod2usage(2); +pod2usage(1) if $help; +### + +# unless specified by --output/-o, the print OUTPUT commands go to STDOUT +if ($output) { + open(OUTPUT, '>', $output) or die "could not open $output for writing!"; +} else { + *OUTPUT = *STDOUT; +} +# + +# if verbose flag is set, make verbose filehandle equal STDOUT and not /dev/null +# which means: if verbose flag is set, then really print the verbose print directives +unless ($verbose) { + open(VERBOSE, '>', "/dev/null") or die; +} else { + *VERBOSE = *STDOUT; +} + +#### room for testblocks ######################################## + +if($testblock){ + + print any2hex("0x0011")."\n"; + print any2hex("0b0011")."\n"; + print any2hex("009999999999999999999999911")."\n"; + + print "\n"; + exit; + + +} +################################################################# + +# ini and specfile arguments mandatory! +unless ($ini and $specFile) { + pod2usage(1); +} +# + + + + + + + + + + + + + +# initialize the xml parser +my $parser = XML::LibXML->new(); +# read in the JTAG specification file +print VERBOSE "parsing specifications file...\n"; +my $specTree = $parser->parse_file($specFile); + + +# create a new tree document that will become the decoded config file +my $configTree = XML::LibXML->createDocument; + +# create standard content + +$specFile =~ m/([^\/]+\.xml)$/; +my $specFileName = $1; + +my $configMaps = $configTree->createElementNS( "", "MAPS" ); +$configTree->setDocumentElement($configMaps); + +my $specMaps = $specTree->findnodes("/MAPS")->shift(); + +my $mapsType = $specMaps->findvalue("./\@type"); + +$configMaps->setAttribute( "type", $mapsType ); +$configMaps->setAttribute( "specDbFile", $specFileName ); + +# done doing standard content + + + + + + + + + + +# open the ini file, decode the ini file +print VERBOSE "opening ini file...\n"; +open(READ,$ini) + or die "Error while opening : $!\n"; + +while (defined(my $line = )) { + + if($line =~ m/^(\d\d)=([0-9a-fA-F]{2}),(\d+),([0-9a-fA-F]+)/ ){ # match the format of the ini file + + my $registerNumber=$1; + my $registerId=$2; + my $registerSize=$3; + my $hexString=$4; + + print VERBOSE "found settings for register ID=$registerId in ini file...\n"; + + # find register with given ID in the specfile + my $specRegister=$specTree->findnodes("/MAPS/register[\@id='".$registerId."']")->shift(); + if($specRegister eq "") { die "register ID=$registerId not found in given specification file $specFile\n"; } + my $registerName=$specRegister->findvalue("./\@name"); + print VERBOSE "found corresponding entry in specifications file!\n"; + print VERBOSE "register name: $registerName\n"; + + + + my $registerValBinStr = hexStr2binStr($hexString); + + # loop through all fields in the register + for my $specField ( $specRegister->findnodes("./field")){ + + # find field attributes in the specification file + my $fieldName =$specField->findvalue("./\@name"); + my $fieldDefaultValue = $specField->findvalue("./\@defaultValue"); + print VERBOSE "processing data for field $fieldName\n"; + my $fieldStart=$specField->findvalue("./\@start"); + my $fieldSize=$specField->findvalue("./\@size"); + my $fieldEnd=$specField->findvalue("./\@end"); + # just check if size definitions of the field is correct + unless($fieldSize == $fieldEnd-$fieldStart+1) {die "field: start/end/size mismatch\n";} + + # cut field value out of the register value + my $fieldValBinStr = getFieldVal(\$registerValBinStr,$fieldStart,$fieldEnd); + my $fieldValHexStr = binStr2hexStr($fieldValBinStr); + + # check if decoded value is identical with default value from specification + + if( ("0x".$fieldValHexStr ne any2hex($fieldDefaultValue)) or $redundant ) { + + # now that you've reconstructed the desired field value, write it to your config file tree + + my $configRegister = $configTree->findnodes( "/MAPS/register[\@name='" . $registerName . "']" )->shift(); + + unless ( defined($configRegister) ) { + print VERBOSE "created new register $registerName in config file ...\n"; + $configRegister = $configMaps->addNewChild( "", "register" ); + $configRegister->setAttribute( "name", $registerName ); + } + + my $configField = $configRegister->addNewChild( "", "field" ); + $configField->setAttribute( "name", $fieldName ); + $configField->setAttribute( "value", "0x$fieldValHexStr" ); + print VERBOSE "created new field $fieldName in register $registerName with value 0x$fieldValHexStr\n"; + print VERBOSE "\n"; + + } + + # done with field + } + + + + + } + +} + + +# done reading the ini file, now write the xml document to file + + print OUTPUT $configTree->toString(); + + + + + + + +sub getFieldVal { + + my $regStr = $_[0]; # pointer! + my $start = $_[1]; + my $end = $_[2]; + + my $regStrLen = length($$regStr); + + my $substrStart = $regStrLen-1-$end; + my $substrLength = $end-$start+1; + + return substr $$regStr,$substrStart,$substrLength; + + +} + + +# sub register2hex { +# # TODO +# # try catch blocks? +# # good work so far +# my $register = $_[0]; +# my $registerName = $register->findvalue("./\@name"); +# my $registerId = $register->findvalue("./\@id"); +# my $registerSize = $register->findvalue("./\@size"); +# my $stringSize = ceil($registerSize/32)*8; +# +# +# my $result = 0; +# +# my @fields = $register->findnodes("./field"); +# +# for my $field (@fields){ +# my $name = $field->findvalue("./\@name"); +# my $start = $field->findvalue("./\@start"); +# my $end = $field->findvalue("./\@end"); +# my $size = $field->findvalue("./\@size"); +# +# # check for setting in the settings file +# my $value = $settree->findvalue("/MAPS/register[\@name='".$registerName."']/field[\@name='".$name."']/\@value"); +# if ($value ne "") { +# #print "Setting found! $value\n"; +# } else { # if nothing found, then use the default value from the specFile +# $value = $field->findvalue("./\@defaultValue"); +# #print "Use default setting: $value\n"; +# } +# +# $value = any2dec($value); # convert any numeric code to decimal +# my $calcedsize = $end-$start+1; +# if ( $calcedsize != $size) { +# die "start/stop/size mismatch in register $registerName : field $name\n"; +# } +# #print "$name: $start -> $end = $calcedsize/$size\n"; +# $result = $result | ($value<<$start); +# #print "value: $value\n"; +# } +# my $resultstring = sprintf("%0".$stringSize."X",$result); +# print ";$registerName\n"; +# printf ("%02d=%s,%d,%s\n",$registerCounter,$registerId,$registerSize,$resultstring); +# +# } + + + + + + + +############################### +#### Feierabend! +############################### +__END__ + +=head1 NAME + +ini2xml.pl - convert a "Bertram Style" sensor.ini file to an xml file compliant with the database system of Jan and Michael + +=head1 SYNOPSIS + +ini2xml.pl -i file.ini -s specFile.xml [-o output.xml] [-d] + + Options: + -h, --help brief help message + -v, --verbose detailed debugging info about ongoing actions + -i, --ini specifies the input .ini file + -s, --spec specifies the specification xml file by + which the .ini file is to be decoded + -o, --output specifies the output filename, if ommitted, + the generated xml is written to STDOUT + -d, --decimal if this flag is set, the generated xml file will + contain the settings in decimal format instead of hex + !!! not implemented !!! + -r, --redundant write settings to config file that are identical + with the specification defaults + -t, --testblock execute only testblock + + +=back + +=head1 DESCRIPTION + +=cut