From 1e2cbc9c68344b72c1808a3334836f781248c0c9 Mon Sep 17 00:00:00 2001 From: Michael Wiebusch Date: Thu, 3 Jul 2014 19:06:37 +0200 Subject: [PATCH] progress on table tool --- mvdsensorcontrol/tables/maketable.pl | 254 -------------------- mvdsensorcontrol/tables/xmldb2tex.pl | 346 +++++++++++++++++++++++++++ 2 files changed, 346 insertions(+), 254 deletions(-) delete mode 100755 mvdsensorcontrol/tables/maketable.pl create mode 100755 mvdsensorcontrol/tables/xmldb2tex.pl diff --git a/mvdsensorcontrol/tables/maketable.pl b/mvdsensorcontrol/tables/maketable.pl deleted file mode 100755 index 7981c57..0000000 --- a/mvdsensorcontrol/tables/maketable.pl +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/perl -w - - -# my $me = "adcmon.pl"; - -use strict; -use warnings; -use POSIX; -# use CGI ':standard'; -# use CGI::Carp qw(fatalsToBrowser); -# use HTML::Entities; -use Data::Dumper; -use FileHandle; - - - -use FindBin; -use lib "$FindBin::Bin/.."; -# my $entityFile = "../../daqtools/xml-db/cache/CbController.entity"; -# my $xmldb = AccessXmlDb->new( entityFile => $entityFile ); -# print any2hex(1234); -# print join(":",@{$xmldb->channelList()}); -# print "\n"; -# - -my $xml_cbctrl_entity = "/home/micha/mnt/55local1/htdocs/daqtools/xml-db/cache/CbController.entity"; - -my $daqopserver="jspc55:88"; -$ENV{'DAQOPSERVER'} = $daqopserver; - - -my $xmldb = xmlDbMethods->new( entityFile => $xml_cbctrl_entity); - - - - - -$xmldb->dumpItem('EnaA'); -$xmldb->dumpItem('MiscConf'); - -my $list = $xmldb->unfoldTree('CbUcRegs'); -# my $list = $xmldb->unfoldTree('MiscConf'); - -my $data = []; - -for my $name (@$list) { # processing the list - my $node = $xmldb->{entity}->{$name}; - my $type = $node->{type}; - my $repeat = $node->{repeat} || 1; - my $stepsize = $node->{stepsize}||0; - - my $bits = ""; - if ($type ne 'register'){ - my $start = $node->{start}; - my $stop = $node->{start}+$node->{bits}-1; - if ($start == $stop){ - $bits = $start; - } else { - $bits = "$start--$stop"; - } - } - - #indent register fields - if ($type eq 'field'){ - $name= '\quad '.$name; - } - - for (my $i=0;$i<$repeat;$i++){ - my $name_ = $name; - if ($repeat > 1) { - $name_ = $name.".$i"; - } - my $addr_ = $node->{address}+$i*$stepsize; - my $hexaddr = sprintf("0x%04x",$addr_ ); - push(@{$data},{%$node, name => $name_, addr => $hexaddr, bits => $bits}); - } -} - -@$data = sort { $a->{bits} cmp $b->{bits} } @$data; -@$data = sort { $a->{addr} cmp $b->{addr} } @$data; - -my $table = textabular->new(); - -for my $item (@$data){ -$table->addData(%$item); -} - - - - - - -$table->{dataKeys} = [ 'name', 'addr', 'bits', 'description' ]; -$table->{format} = '@{} l l l p{8cm} @{}'; -$table->{caption} = 'registers, maan'; - -my $tablefile = FileHandle->new("./table.tex", 'w'); -print $tablefile $table->generateString(); -$tablefile->close(); - -print $table->generateString(); - -package xmlDbMethods; - -use Storable qw(lock_store lock_retrieve); -use Data::Dumper; - -sub new { - my $class = shift; - my %options = @_; - my $self = { - entityFile => '/dev/null', - %options - }; - bless($self, $class); - $self->{entity} = lock_retrieve($self->{entityFile}); - die "cannot open xml-db entity file ".$self->{entityFile}."\n" unless defined $self->{entity}; - return $self; -} - -sub channelParm { - my $self = shift; - my $chip = shift; - my $channel = shift; - - my $parm; - %{$parm}= %{$self->{entity}->{$channel."D"}}; - - die "entry $channel does not exist for chip=".$chip."\n" if ($chip ge $parm->{repeat}); - - $parm->{address} += $chip * $parm->{stepsize}; - return $parm; -} - -sub dumpItem { # for debug - my $self = shift; - my $item = shift; - unless (defined($item)){ - print Dumper $self->{entity}; - } else { - print Dumper $self->{entity}->{$item}; - } -} - -sub channelList { - my $self = shift; - return $self->{entity}->{AdcSensor}->{children};# returns a reference to an array -} - -sub unfoldTree { - my $self = shift; - my $name = shift; - my $depth = shift||0; - my $list = shift || []; - - my $node = $self->{entity}->{$name}; - -# for (my $i = 0; $i<$depth; $i++){ -# print " "; -# } -# print $node->{type}."\t$name\n"; - unless($node->{type} eq 'group'){ - push(@{$list},$name); - } - - if ($node->{type} eq 'group' || $node->{type} eq 'register' ){ - for my $child (@{$node->{'children'}}){ -# print $child."\n"; - $self->unfoldTree($child,$depth+1,$list); - } - } - - return $list; -} - -1; - -package textabular; - - -sub new { - my $class = shift; - my %options = @_; - my $self = { -# entityFile => '/dev/null', - dataKeys => [], - header => [], - data => [], - %options - }; - bless($self, $class); - return $self; -} - -sub addData { - my $self = shift; - my %data = @_; - push(@{$self->{data}}, \%data); - return $self; -} - -sub generateString { - my $self = shift; - my $str = ""; - -# $str.='\begin{table}[tbp] -# \centering'; -# $str .= '\begin{center}'; - - - $str .= '\begin{longtable}'."\n"; - $str .="{".($self->{format}||"")."}\n"; - -# $str.='\caption{'.$self->{caption}.'}' if defined $self->{caption}."\n"; - $str .= '\\\\'; - $str.='\toprule'."\n"; -# $str.='\hline'."\n"; - if ( @{$self->{header}} ){ # if no header list ... - $str.= " ".join(" & ",@{$self->{header}}).' \\\\'."\n"; - } else { # print the keys instead - $str.= " ".join(" & ",@{$self->{dataKeys}}).' \\\\'."\n"; - } - $str.='\midrule'."\n"; - $str.='\hline'."\n"; - $str.='\endfirsthead'; - - - $str.='\hline \multicolumn{'.scalar(@{$self->{dataKeys}}).'}{r}{\textit{Continued on next page}} \\\\ - \endfoot - \hline - \endlastfoot'; - - for my $data (@{$self->{data}}){ - my @line; - for my $dataKey (@{$self->{dataKeys}}){ - push(@line,$data->{$dataKey}); - } - my $line = " ".join(" & ", @line) . ' \\\\'."\n"; - $line =~ s/_/\\_/g; # remove all stupid underscores - $str.=$line; - } - $str.='\bottomrule'."\n"; -# $str.='\hline'."\n"; - - $str .='\caption{aoeiaeoi}'."\n"; - $str .='\label{tab:long}'."\n"; - - $str.='\end{longtable}'."\n"; - -# $str.='\label{'.$self->{label}.'}' if defined $self->{label}."\n"; -# $str.='\end{table}'."\n"; -# $str .= '\end{center}'; - return $str; -} \ No newline at end of file diff --git a/mvdsensorcontrol/tables/xmldb2tex.pl b/mvdsensorcontrol/tables/xmldb2tex.pl new file mode 100755 index 0000000..0a18f13 --- /dev/null +++ b/mvdsensorcontrol/tables/xmldb2tex.pl @@ -0,0 +1,346 @@ +#!/usr/bin/perl -w + + +package xmldb2tex; + +# my $me = "adcmon.pl"; + +use strict; +use warnings; +use POSIX; +use Data::Dumper; +use FileHandle; +use Getopt::Long; +use File::Basename; +# use Cwd; + +my $opt; + +Getopt::Long::Configure(qw(gnu_getopt)); +GetOptions( + 'help|h' => \$opt->{help}, + 'caption|c=s' => \$opt->{caption}, + 'label|l=s' => \$opt->{label}, + 'group|g=s' => \$opt->{group}, + 'entity|e=s' => \$opt->{entity}, + 'output|o=s' => \$opt->{output}, + 'pdf' => \$opt->{pdf}, + 'standalone' => \$opt->{standalone} + ); + +printHelpMessage() unless $opt->{entity} && $opt->{group}; + + +my $me = xmldb2tex->new(); + +$me->setEntity($opt->{entity}); +# $me->{entityFile} = "/home/micha/mnt/55local1/htdocs/daqtools/xml-db/cache/CbController.entity"; +$me->{group} = $opt->{group}; +$me->{table}->{label} = $opt->{label}||""; +$me->{table}->{caption} = $opt->{caption}||""; +$me->produceTable(); + + + +if ($opt->{output}){ + $me->writeTexFile($opt->{output}, $opt->{standalone} ); +} else { + $me->printTex(); +} + +if ($opt->{pdf}){ + $me->pdflatex(); +} + +########### simple subs ######## + +sub printHelpMessage{ +print < -g [-o ] [OPTIONS] + +Generates a latex table of an xml-db group. + +Options: + -h, --help brief help/usage message + -e, --entity enter entity name or /path/to/entityName.entity + -g, --group the xml-db group to be transformed into a table + -o, --output write tex output to this file, if left out, + print to STDOUT + -c, --caption caption of the table + -l, --label latex label of the table + + --standalone generate standalone compilable latex file + --pdf compile directly to pdf + + +EOF +exit; +} + + +########### object methods ######## + +sub new { + my $class = shift; + my %options = @_; + + my $self = {}; + + $self->{table} = textabular->new(); # create new latex table object + + # default formatting of the table + $self->{table}->{dataKeys} = [ 'name', 'addr', 'bits', 'description' ]; + $self->{table}->{format} = '@{} l l l p{8cm} @{}'; + + $self = { + %$self, + %options + }; + bless($self, $class); + return $self; +} + +sub setEntity { + my $self=shift; + my $entity=shift; + + if(-e $entity) { # treat as /path/to/File + $self->{entityFile} = $entity; + } elsif (-e dirname($0)."/cache/".$entity.".entity"){ + $self->{entityFile} = dirname($0)."/cache/".$entity.".entity"; + } else { + die "Entity $entity not found (not even in xml-db/cache)\n"; + } +} + +sub produceTable { + my $self= shift; + my $xmldb = xmlDbMethods->new( entityFile => $self->{entityFile} ); + my $list = $xmldb->unfoldTree($self->{group}); + my $data = []; + for my $name (@$list) { # processing the list + my $node = $xmldb->{entity}->{$name}; + my $type = $node->{type}; + my $repeat = $node->{repeat} || 1; + my $stepsize = $node->{stepsize}||0; + my $bits = ""; + if ($type ne 'register'){ + my $start = $node->{start}; + my $stop = $node->{start}+$node->{bits}-1; + if ($start == $stop){ + $bits = $start; + } else { + $bits = "$start--$stop"; + } + } + #indent register fields + if ($type eq 'field'){ + $name= '\quad '.$name; + } + for (my $i=0;$i<$repeat;$i++){ + my $name_ = $name; + if ($repeat > 1) { + $name_ = $name.".$i"; + } + my $addr_ = $node->{address}+$i*$stepsize; + my $hexaddr = sprintf("0x%04x",$addr_ ); + push(@{$data},{%$node, name => $name_, addr => $hexaddr, bits => $bits}); + } + } + + @$data = sort { $a->{bits} cmp $b->{bits} } @$data; # bit fields in ascending order + @$data = sort { $a->{addr} cmp $b->{addr} } @$data; # addresses in ascending order + + + + for my $item (@$data){ + $self->{table}->addData(%$item); # fill it with the sorted data + } + +} + +sub printTex { + my $self = shift; + print $self->{table}->generateString(); +} + + +sub writeTexFile { + my $self = shift; + my $pathToFile = shift; + my $standalone = shift; + + my $tablefile = FileHandle->new($pathToFile, 'w'); + if ($standalone){ + print $tablefile q% + \documentclass[a4paper,11pt]{article} + \usepackage[T1]{fontenc} + \usepackage{lmodern} + \usepackage{booktabs} + \usepackage{longtable} + \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=3cm,rmargin=3cm} + \begin{document} + %; + } + print $tablefile $self->{table}->generateString(); + + print $tablefile '\end{document}' if $standalone; + $tablefile->close(); +} + +sub pdflatex{ + + my $here = qx("pwd"); + my $directory = "/dev/shm/xmldb2tex".rand(); + unless(-e $directory or mkdir $directory) { + die "Unable to create $directory\n"; + } + my $texfile = $me->{group}.".tex"; + my $pdffile = $me->{group}.".pdf"; + system("cd $directory"); + $me->writeTexFile($texfile, "standalone"); + system("pdflatex $texfile"); + system("pdflatex $texfile"); + system("cp $pdffile $here/"); + system("cd $here"); + unlink $directory; + +} + + + +package xmlDbMethods; + +use Storable qw(lock_store lock_retrieve); +use Data::Dumper; + +sub new { + my $class = shift; + my %options = @_; + my $self = { + entityFile => '/dev/null', + %options + }; + bless($self, $class); + $self->{entity} = lock_retrieve($self->{entityFile}); + die "cannot open xml-db entity file ".$self->{entityFile}."\n" unless defined $self->{entity}; + return $self; +} + + + +sub dumpItem { # for debug + my $self = shift; + my $item = shift; + unless (defined($item)){ + print Dumper $self->{entity}; + } else { + print Dumper $self->{entity}->{$item}; + } +} + + +sub unfoldTree { + my $self = shift; + my $name = shift; + my $depth = shift||0; + my $list = shift || []; + + my $node = $self->{entity}->{$name}; + unless($node->{type} eq 'group'){ + push(@{$list},$name); + } + + if ($node->{type} eq 'group' || $node->{type} eq 'register' ){ + for my $child (@{$node->{'children'}}){ +# print $child."\n"; + $self->unfoldTree($child,$depth+1,$list); + } + } + + return $list; +} + +1; + +package textabular; + + +sub new { + my $class = shift; + my %options = @_; + my $self = { + dataKeys => [], + header => [], + data => [], + caption => '', + label => '', + %options + }; + bless($self, $class); + return $self; +} + +sub addData { + my $self = shift; + my %data = @_; + push(@{$self->{data}}, \%data); + return $self; +} + +sub generateString { + my $self = shift; + my $str = '% remember to include the following latex packages: + % booktabs + % longtable'."\n"; + + my $header; + + if ( @{$self->{header}} ){ # if no header list ... + $header= " ".join(" & ",map { '\textbf{'.$_.'}' } @{$self->{header}}).' \\\\'."\n"; + } else { # print the keys instead + $header= " ".join(" & ",map { '\textbf{'.$_.'}' } @{$self->{dataKeys}}).' \\\\'."\n"; + } + + $str .= '\begin{longtable}'."\n"; + $str .="{".($self->{format}||"")."}\n"; + + + # define first header + $str.='\toprule'."\n"; + $str.= $header; + $str.='\midrule'."\n"; + $str.='\endfirsthead'; + + # define (continued) header + $str.='\multicolumn{'.@{$self->{dataKeys}}.'}{c}'; + $str.='{\tablename\ \thetable\ -- \textit{Continued from previous page}} \\\\'; + $str.='\toprule'."\n"; + $str.= $header; + $str.='\midrule'."\n"; + $str.='\endhead'; + + $str.='\multicolumn{'.scalar(@{$self->{dataKeys}}).'}{r}{\textit{Continued on next page}} \\\\ + \endfoot + \endlastfoot'; + + for my $data (@{$self->{data}}){ + my @line; + for my $dataKey (@{$self->{dataKeys}}){ + push(@line,$data->{$dataKey}); + } + my $line = " ".join(" & ", @line) . ' \\\\'."\n"; + $line =~ s/_/\\_/g; # remove all stupid underscores + $str.=$line; + } + $str.='\bottomrule'."\n"; +# $str.='\hline'."\n"; + + $str.='\caption{'.$self->{caption}.'}' if $self->{caption}."\n"; + $str.='\label{'.$self->{label}.'}' if $self->{label}."\n"; + + $str.='\end{longtable}'."\n"; + +# $str.='\end{table}'."\n"; + return $str; +} \ No newline at end of file -- 2.43.0