#!/usr/bin/perl -w
# File : csvtools.pl
# Author : Dr Nicola Talbot
# Date : 26 June 2007
# Description : Perl script to accompany csvtools.sty
# : Allows you to substitute \CSVtotabular, \CSVtolongtable and \applyCSVfile commands with the appropriate LaTeX code
# Version : 0.6b (1 September 2006).
# usage : csvtools <in-file> <out-file>
if ($#ARGV != 1)
{
die "Syntax : $0 <in-file> <out-file>\n";
}
($FILENAME,$OUTPUT) = @ARGV;
open FILENAME or die "Can't open '$FILENAME'\n";
$ext = substr($FILENAME, -4);
if (($ext eq ".tex") or ($ext eq ".dtx") or ($ext eq ".ltx"))
{
$LOGFILE = substr($FILENAME,0,length($FILENAME)-4) . ".log";
}
else
{
$LOGFILE = $FILENAME . ".log";
}
open LOGFILE or die "Can't open log file '$LOGFILE'. Make sure you run LaTeX before using $0\n";
while (<LOGFILE>)
{
if (/\\c@([a-zA-Z]+)=\\count/)
{
$counter{$1} = 0;
}
}
$counter{'csvrownumber'} = 0;
close LOGFILE;
open OUTPUT, ">$OUTPUT" or die;
# global csvsort options
$globalsort{'verbose'}=1;
$globalsort{'sort'}='alphabetical ascending';
$globalsort{'variable'}='\field{1}';
$globalsort{'sfirstdataline'}=1;
$globalsort{'firstdataline'}=2;
$keyvaldefaults{'verbose'}='true';
$csvpieouterlabel="\\field{1}";
$csvpieinnerlabel="\\field{2}\\%";
$separator=",";
while (<FILENAME>)
{
$restofline = $_;
local($comment) = "";
if ($restofline=~m/(\\*)%/)
{
$n = length($1);
if ($n%2 == 0)
{
$restofline = "$`$1";
$comment = "%$'";
$_ = $restofline;
}
}
if ($restofline=~/\\setcsvseparator\s*{([^}]*)}/)
{
$separator=$1 if defined($1);
}
if ($restofline=~/\\renewcommand\*?\s*{?\\csvpieinnerlabel}?/)
{
print OUTPUT $`;
$restofline=$';
$lineno=$.;
($csvpieinnerlabel,$restofline,$done)=&getnextgroup($restofline);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$restofline .= $nextline;
($csvpieinnerlabel,$restofline,$done)=&getnextgroup($restofline);
}
else
{
die "Unexpected EOF while parsing \\renewcommand on line $lineno\n";
}
}
$_ = $restofline;
}
if ($restofline=~/\\renewcommand\*?\s*{?\\csvpieouterlabel}?/)
{
print OUTPUT $`;
$restofline=$';
$lineno=$.;
($csvpieouterlabel,$restofline,$done)=&getnextgroup($restofline);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$restofline .= $nextline;
($csvpieouterlabel,$restofline,$done)=&getnextgroup($restofline);
}
else
{
die "Unexpected EOF while parsing \\renewcommand on line $lineno\n";
}
}
$_ = $restofline;
}
while ($restofline=~/\\stepcounter(.*)/)
{
$line = $_;
($ctr,$restofline,$done) = &getnextgroup($1);
$startline=$.;
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
$restofline = $restofline . $nextline;
($ctr,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n";
}
}
$counter{$ctr}++;
$_ = $line;
}
$restofline = $_;
while ($restofline=~/\\refstepcounter(.*)/)
{
$line = $_;
($ctr,$restofline,$done) = &getnextgroup($1);
$startline=$.;
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
$restofline = $restofline . $nextline;
($ctr,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n";
}
}
$counter{$ctr}++;
$_ = $line;
}
$restofline = $_;
while ($restofline=~/\\setcounter(.*)/)
{
$line = $_;
($ctr,$restofline,$done) = &getnextgroup($1);
$startline=$.;
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
$restofline = $restofline . $nextline;
($ctr,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n";
}
}
($num,$restofline,$done) = &getnextgroup($restofline);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
$restofline = $restofline . $nextline;
($num,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning second argument to \\stepcounter on line $startline\n";
}
}
$num=~s/\\value{(.+)}/$counter{$1}/;
$counter{$ctr} = $num;
$_ = $line;
}
$restofline = $_;
while ($restofline=~/\\addtocounter(.*)/)
{
$line = $_;
($ctr,$restofline,$done) = &getnextgroup($1);
$startline=$.;
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
$restofline = $restofline . $nextline;
($ctr,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning first argument to \\stepcounter on line $startline\n";
}
}
($num,$restofline,$done) = &getnextgroup($restofline);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
$restofline = $restofline . $nextline;
($num,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning second argument to \\stepcounter on line $startline\n";
}
}
$num=~s/\\value{(.+)}/$counter{$1}/;
$counter{$ctr} = $counter{$ctr} + $num;
$_ = $line;
}
$restofline = $_;
while ($restofline=~/^(.*)\\csvGetEntry(.*)$/)
{
$start = $1;
$restofline = $2;
($ctr,$restofline,$done) = &getnextgroup($restofline);
$startline=$.;
while (!$done)
{
if ($nextline = <FILENAME>)
{
$restofline = $restofline . $nextline;
($ctr,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning first argument to \\csvGetEntry on line $startline\n";
}
}
($entry,$restofline,$done) = &getnextgroup($restofline);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$restofline = $restofline . $nextline;
($entry,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning first argument to \\csvGetEntry on line $startline\n";
}
}
$_ = $start . "\\csname $entry\\roman{$ctr}\\endcsname" . $restofline;
#$_ = $start. $data{$entry}[$counter{$ctr}] . $restofline;
}
$restofline = $_;
while ($restofline=~/\\usepackage(.*)/)
{
$line = $_;
$startline=$.;
$restofline = $1;
$options = '';
if ($restofline=~/^\s*\[/)
{
($options,$restofline,$done) = &getnextoptionalgroup($restofline);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
$restofline = $restofline . $nextline;
($options,$restofline,$done) = &getnextoptionalgroup($restofline);
}
else
{
die "EOF found whilst scanning optional argument to \\usepackage on line $startline\n";
}
}
}
($package,$restofline,$done) = &getnextgroup($restofline);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
$restofline = $restofline . $nextline;
($package,$restofline,$done) = &getnextgroup($restofline);
}
else
{
die "EOF found whilst scanning argument to \\usepackage on line $startline\n";
}
}
if ($package eq 'csvsort' and $options)
{
%hash = &getKeyValues($options,%keyvaldefaults);
foreach $key (keys(%hash))
{
$globalsort{$key}=$hash{$key};
}
}
$_ = $line;
}
$restofline = $_;
if (/^(.*)\\CSVtotabular(.*)$/)
{
print OUTPUT "$1$comment";
$comment="";
$line = $2;
$lineno = $.;
($csvname,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
($csvname,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for CVS filename on line $lineno\n";
}
}
$csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/;
$line = $restofline;
($alignment,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $restofline . $nextline;
($alignment,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for CVS column alignment on line $lineno\n";
}
}
$line = $restofline;
($FIRST,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $restofline . $nextline;
($FIRST,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\CSVtotabular third argument on line $lineno\n";
}
}
$line = $restofline;
($MIDDLE,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $restofline . $nextline;
($MIDDLE,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\CSVtotabular fourth argument on line $lineno\n";
}
}
$line = $restofline;
($LAST,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $restofline . $nextline;
($LAST,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\CSVtotabular fifth argument on line $lineno\n";
}
}
&csvtotabular($csvname, $alignment, $FIRST, $MIDDLE, $LAST,
"tabular");
print OUTPUT "$restofline\n";
}
elsif (/^(.*)\\CSVtolongtable(.*)$/)
{
print OUTPUT "$1$comment";
$comment="";
$line = $2;
$lineno = $.;
($csvname,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $line . $nextline;
($csvname,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for CVS filename on line $lineno\n";
}
}
$csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/;
$line = $restofline;
($alignment,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $restofline . $nextline;
($alignment,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for CVS column alignment on line $.\n";
}
}
$line = $restofline;
($FIRST,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $restofline . $nextline;
($FIRST,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\CSVtolongtable third argument on line $.\n";
}
}
$line = $restofline;
($MIDDLE,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $restofline . $nextline;
($MIDDLE,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\CSVtolongtable fourth argument on line $.\n";
}
}
$line = $restofline;
($LAST,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline = <FILENAME>)
{
$line = $restofline . $nextline;
($LAST,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\CSVtolongtable fifth argument on line $.\n";
}
}
&csvtotabular($csvname, $alignment, $FIRST, $MIDDLE, $LAST,
"longtable");
print OUTPUT "$restofline\n";
}
elsif (/^(.*)\\applyCSVfile(\*)?(.*)$/)
{
print OUTPUT "$1$comment";
$comment="";
$starred = defined($2);
$restofline = $3;
$lineno = $.;
$restofline = &eatinitialspaces($restofline);
$restofline = &eatcomments($restofline);
$startrow = $starred ? 1 : 2;
if (/^\[([0-9]+)\](.*)/)
{
$startrow = $1;
$restofline = $2;
}
$line=$restofline;
($csvname,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($csvname,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\applyCSVfile*[$startrow] first argument on line $lineno\n";
}
}
$csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/;
$line=$restofline;
($body,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($body,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\applyCSVfile*[$startrow] second argument on line $lineno\n";
}
}
if ($starred)
{
&applyCSVfilestar($csvname, $body, $startrow);
}
else
{
&applyCSVfile($csvname, $body, $startrow);
}
print OUTPUT "$restofline\n";
}
elsif (/^(.*)\\sortapplyCSVfile(\*)?(.*)$/)
{
print OUTPUT "$1$comment";
$comment="";
$starred = defined($2);
$restofline = $3;
$lineno = $.;
$restofline = &eatinitialspaces($restofline);
$restofline = &eatcomments($restofline);
$line=$restofline;
$options = '';
if ($restofline=~/^\s*\[/)
{
($options,$restofline,$done) = &getnextoptionalgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($options,$restofline,$done) = &getnextoptionalgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortapplyCSVfile optional argument on line $lineno\n";
}
}
}
$line=$restofline;
($csvname,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($csvname,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortapplyCSVfile argument on line $lineno\n";
}
}
$csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/;
$line=$restofline;
($body,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($body,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortapplyCSVfile argument on line $lineno\n";
}
}
if ($starred)
{
&sortapplyCSVfilestar($csvname, $body, $options);
}
else
{
&sortapplyCSVfile($csvname, $body, $options);
}
print OUTPUT "$restofline\n";
}
elsif (/^(.*)\\sortCSVto(tabular|longtable)(.*)$/)
{
print OUTPUT "$1$comment";
$comment="";
$envname = $2;
$restofline = $3;
$lineno = $.;
$restofline = &eatinitialspaces($restofline);
$restofline = &eatcomments($restofline);
$line=$restofline;
$options = '';
if ($restofline=~/^\s*\[/)
{
($options,$restofline,$done) = &getnextoptionalgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($options,$restofline,$done) = &getnextoptionalgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortCSVto$envname first argument on line $lineno\n";
}
}
}
$line=$restofline;
($csvname,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($csvname,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n";
}
}
$csvname=~s/\\csname (.*)\\roman{(.*)}\\endcsname/$data{$1}[$counter{$2}]/;
$line=$restofline;
($align,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($align,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n";
}
}
$line=$restofline;
($headrow,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($headrow,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n";
}
}
$line=$restofline;
($midrows,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($midrows,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n";
}
}
$line=$restofline;
($lastrow,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($lastrow,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\sortCSVto$envname argument on line $lineno\n";
}
}
&sortCSVtotabular($csvname,$align,$headrow,$midrows,$lastrow,
$envname,$options);
print OUTPUT "$restofline\n";
}
elsif (/^(.*)\\csvpiechart(\*)?(.*)$/)
{
print OUTPUT "$1$comment";
$comment="";
$lineno = $.;
$starred = defined($2);
$restofline = $3;
$restofline = &eatinitialspaces($restofline);
$restofline = &eatcomments($restofline);
$startrow= $starred ? 1 : 2;
$line=$restofline;
($options,$restofline,$done) = &getnextoptionalgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($options,$restofline,$done) = &getnextoptionalgroup($line);
}
else
{
die "EOF found whilst scanning for \\csvpiechart optional argument on line $lineno\n";
}
}
$line=$restofline;
($label,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($label,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\csvpiechart second argument on line $lineno\n";
}
}
$line=$restofline;
($csvname,$restofline,$done) = &getnextgroup($line);
while (!$done)
{
if ($nextline= <FILENAME>)
{
$line = $restofline . $nextline;
($csvname,$restofline,$done) = &getnextgroup($line);
}
else
{
die "EOF found whilst scanning for \\csvpiechart second argument on line $lineno\n";
}
}
print OUTPUT "\\csvpiesetkeys{$options}%\n";
if ($options=~m/firstrow\s*=\s*(\d+)/)
{
$startrow=$1;
}
if ($starred)
{
&csvpiechartstar($label, $csvname, $startrow);
}
else
{
&csvpiechart($label, $csvname, $startrow);
}
print OUTPUT "$restofline\n";
}
else
{
print OUTPUT "$_$comment";
}
}
sub doapplyCSV{
local($csvrow, $body, @idx, %HoH) = @_;
local($row, $entry);
$counter{'csvrownumber'} = 0;
print OUTPUT "\\setcounter{csvrownumber}{0}\\relax\n";
foreach ($row=1; $row <= $csvrow; $row++)
{
print ".";
local($THISROW) = $body;
$THISROW = &csvSaveEntry($THISROW,$row,%HoH);
foreach $entry ( keys %{$HoH[$row]})
{
$replacementval=$HoH[$row]{$entry};
$THISROW =~ s/\\insertbyname{$entry}/$replacementval/g;
$THISROW =~ s/\\insert$entry/$replacementval/g;
local($column) = $idx{$entry}+1;
$THISROW =~ s/\\field{(\d+)}/$1eq$column?$replacementval:$&/emg;
$THISROW = &ifnextrowlast($THISROW, ($row==$csvrow-1));
}
print OUTPUT "\\refstepcounter{csvrownumber}\\relax\n$THISROW";
$counter{'csvrownumber'}++;
}
}
sub doapplyCSVstar{
local($body, $csvrow, $numcols, @entry) = @_;
local($row,$column);
print OUTPUT "\\setcounter{csvrownumber}{0}\\relax\n";
$counter{'csvrownumber'} = 0;
for ($row=0; $row < $csvrow; $row++)
{
print ".";
$THISROW = $body;
for ($column=0; $column < $numcols; $column++)
{
$replacementval=$entry[$row][$column];
$THISROW =~ s/\\field{(\d+)}/$1eq$column+1?$replacementval:$&/emg;
$THISROW = &ifnextrowlast($THISROW, ($row==$csvrow-1));
}
print OUTPUT "\\refstepcounter{csvrownumber}$THISROW";
$counter{'csvrownumber'}++;
}
}
sub getCSVvalues{
local($CSVFILE, $startrow) = @_;
local(@idx, %HoH, @fields);
open FH, $CSVFILE or die "Can't open file '$CSVFILE'\n";
local ($csvrow)=0;
while (<FH>)
{
if ($. == 1)
{
# get header row
chop;
@fields = &getEntries($_);
local($numcols) = 0;
foreach $field (@fields)
{
$idx{$field} = $numcols;
$numcols++;
}
}
elsif ($. >= $startrow)
{
next unless /$separator/;
chop;
$csvrow++;
$rec = {};
$HoH[$csvrow] = $rec;
local(@entries) = &getEntries($_);
local ($i) = 0;
foreach $e (@entries)
{
$rec->{$fields[$i]} = $e;
$i++;
}
}
}
close FH;
return ($csvrow, @idx, %HoH);
}
sub getCSVvaluesstar
{
local($CSVFILE, $startrow) = @_;
open FH, $CSVFILE or die "Can't open file '$CSVFILE'\n";
$csvrow=0;
while (<FH>)
{
if ($. >= $startrow)
{
chop;
@fields = &getEntries($_);
$numcols = 0;
foreach $field (@fields)
{
$entry[$csvrow][$numcols] = $field;
$numcols++;
}
$csvrow++;
}
}
close FH;
return ($csvrow, $numcols, @entry);
}
sub csvpiechart
{
local($value, $CSVFILE, $startrow) = @_;
print "Converting \\csvpiechart[$options]{$label}{$csvname}\n";
print OUTPUT "% \\csvpiechart[$options]{$label}{$csvname} converted using csvtools.pl\n";
print OUTPUT "%>> START INSERT\n";
# read in data from CSV file
local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,$startrow);
# first compute parameters
print OUTPUT "\\edef\\csvstartang{\\thecsvstartangle}\\relax\n";
$body = "\\csvsetsegmentparams{\\thecsvrownumber}{$value}\\relax\n";
&doapplyCSV($csvrow, $body, @idx, %HoH);
print OUTPUT "\\setcounter{csvstartangle}{\\csvstartang}\\relax\n";
# compute offsets for cutaway segments
print OUTPUT "\\ifthenelse{\\equal{\\csvpiecutaways}{}}{}{\\csvcomputeoffsets}\\relax\n";
# now do the pie chart
print OUTPUT "\\begin{tikzpicture}\n";
$body = "\\renewcommand*{\\csvpieinnerlabel}{$csvpieinnerlabel}\n";
$body .= "\\renewcommand*{\\csvpieouterlabel}{$csvpieouterlabel}\n";
$body .= "\\csvpiesegment{$value}\n";
&doapplyCSV($csvrow, $body, %HoH);
print OUTPUT "\\end{tikzpicture}";
print OUTPUT "%<< END INSERT\n";
print "\n";
}
sub csvpiechartstar
{
local($value, $CSVFILE, $startrow) = @_;
print "Converting \\csvpiechart*[$options]{$label}{$csvname}\n";
print OUTPUT "% \\csvpiechart*[$options]{$label}{$csvname} converted using csvtools.pl\n";
print OUTPUT "%>> START INSERT\n";
local($csvrow, $numcols, @entry) = &getCSVvaluesstar($CSVFILE, $startrow);
# first compute parameters
print OUTPUT "\\edef\\csvstartang{\\thecsvstartangle}\\relax\n";
$body = "\\csvsetsegmentparams{\\thecsvrownumber}{$value}\\relax\n";
&doapplyCSVstar($body, $csvrow, $numcols, @entry);
print OUTPUT "\\setcounter{csvstartangle}{\\csvstartang}\\relax\n";
# compute offsets for cutaway segments
print OUTPUT "\\ifthenelse{\\equal{\\csvpiecutaways}{}}{}{\\csvcomputeoffsets}\\relax\n";
$body = "\\renewcommand*{\\csvpieinnerlabel}{$csvpieinnerlabel}\\relax\n";
$body .= "\\renewcommand*{\\csvpieouterlabel}{$csvpieouterlabel}\\relax\n";
$body .= "\\csvpiesegment{$value}\\relax\n";
print OUTPUT "\\begin{tikzpicture}\n";
&doapplyCSVstar($body, $csvrow, $numcols, @entry);
print OUTPUT "\\end{tikzpicture}";
print OUTPUT "%<< END INSERT\n";
print "\n";
}
sub applyCSVfile
{
my ($CSVFILE,$body,$startrow) = @_;
print "Converting \\applyCSVfile{$CSVFILE}";
print OUTPUT "\% \\applyCSVfile{$CSVFILE}... converted using csvtools.pl\n";
print OUTPUT "\%>> START INSERT\n";
# read in data from CSV file
local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,$startrow);
# apply data
&doapplyCSV($csvrow, $body, @idx, %HoH);
print "\n";
print OUTPUT "\%<< END INSERT\n";
}
sub sortapplyCSVfile
{
my ($CSVFILE,$body,$options) = @_;
print "Converting \\sortapplyCSVfile{$CSVFILE}";
print OUTPUT "\% \\sortapplyCSVfile{$CSVFILE}... converted using csvtools.pl\n";
print OUTPUT "\%>> START INSERT\n";
# get options
%hash = &getKeyValues($options) if $options;
local($startrow) = defined($hash{'firstdataline'})
? $hash{'firstdataline'}
: $globalsort{'firstdataline'};
local ($sortorder) = $hash{'sort'};
# read in data from CSV file
local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,$startrow);
# get sort variable
local($variable) = defined($hash{'variable'})
? $hash{'variable'}
: $globalsort{'variable'};
local(@rowdata)=();
print OUTPUT "\\bgroup\n";
# set field labels
foreach $entry (keys %{$HoH[1]})
{
print OUTPUT "\\setcsvfieldlabel{";
print OUTPUT ($idx{$entry}+1).'}{';
print OUTPUT "$entry}%\n";
}
print OUTPUT "\\def\\csvsortlist{%\n";
# construct list
foreach ($row=1; $row <= $csvrow; $row++)
{
print ".";
local($sortkey) = $variable;
$sortkey = &csvSaveEntry($sortkey,$row,%HoH);
foreach $entry ( keys %{$HoH[$row]})
{
$replacementval=$HoH[$row]{$entry};
$sortkey =~ s/\\insertbyname{$entry}/$replacementval/g;
$sortkey =~ s/\\insert$entry/$replacementval/g;
local($column) = $idx{$entry}+1;
$rowdata[$idx{$entry}] = $replacementval;
$sortkey =~ s/\\field{(\d+)}/$1eq$column?$replacementval:$&/emg;
}
print OUTPUT "{$sortkey}{".join($separator,@rowdata)."}";
print OUTPUT ($row == $csvrow ? "%\n" : ",%\n");
}
print OUTPUT "}%\n";
print OUTPUT "\\sortapplyCSVdata";
if (defined($sortorder))
{
print OUTPUT "[$sortorder]";
}
print OUTPUT "{\\csvsortlist}{%\n";
print OUTPUT "$body}%\n";
print OUTPUT "\\egroup\n";
print OUTPUT "\%<< END INSERT\n";
print "\n";
}
sub sortapplyCSVfilestar
{
my ($CSVFILE,$body,$options) = @_;
print "Converting \\sortapplyCSVfile*{$CSVFILE}";
print OUTPUT "\% \\sortapplyCSVfile*{$CSVFILE}... converted using csvtools.pl\n";
print OUTPUT "\%>> START INSERT\n";
# get options
%hash = &getKeyValues($options) if $options;
local($startrow) = defined($hash{'sfirstdataline'})
? $hash{'sfirstdataline'}
: $globalsort{'sfirstdataline'};
local ($sortorder) = $hash{'sort'};
local($csvrow, $numcols, @entry) = &getCSVvaluesstar($CSVFILE, $startrow);
# get sort variable
local($variable) = defined($hash{'variable'})
? $hash{'variable'}
: $globalsort{'variable'};
local(@rowdata)=();
print OUTPUT "\\bgroup\n";
print OUTPUT "\\def\\csvsortlist{%\n";
# construct list
for ($row=0; $row < $csvrow; $row++)
{
print ".";
local($sortkey) = $variable;
for ($column=0; $column < $numcols; $column++)
{
$replacementval=$entry[$row][$column];
$sortkey =~ s/\\field{(\d+)}/$1eq$column+1?$replacementval:$&/emg;
$rowdata[$column] = $replacementval;
}
print OUTPUT "{$sortkey}{".join($separator,@rowdata)."}";
print OUTPUT ($row == $csvrow-1 ? "%\n" : ",%\n");
}
print OUTPUT "}%\n";
print OUTPUT "\\sortapplyCSVdata*";
if (defined($sortorder))
{
print OUTPUT "[$sortorder]";
}
print OUTPUT "{\\csvsortlist}{%\n";
print OUTPUT "$body}%\n";
print OUTPUT "\\egroup\n";
print "\n";
print OUTPUT "\%<< END INSERT\n";
}
sub sortCSVtotabular
{
my ($CSVFILE,$align,$headrow,$midrows,$lastrow,$envname,$options) = @_;
print "Converting \\sortCSVto${envname}{$CSVFILE}";
print OUTPUT "\% \\sortCSVto${envname}{$CSVFILE}... converted using csvtools.pl\n";
print OUTPUT "\%>> START INSERT\n";
# get options
%hash = &getKeyValues($options) if $options;
local($startrow) = defined($hash{'firstdataline'})
? $hash{'firstdataline'}
: $globalsort{'firstdataline'};
local ($sortorder) = $hash{'sort'};
# read in data from CSV file
local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,$startrow);
# get sort variable
local($variable) = defined($hash{'variable'})
? $hash{'variable'}
: $globalsort{'variable'};
local(@rowdata)=();
print OUTPUT "\\bgroup\n";
# set field labels
foreach $entry (keys %{$HoH[1]})
{
print OUTPUT "\\setcsvfieldlabel{";
print OUTPUT ($idx{$entry}+1).'}{';
print OUTPUT "$entry}%\n";
}
print OUTPUT "\\def\\csvsortlist{%\n";
# construct list
foreach ($row=1; $row <= $csvrow; $row++)
{
print ".";
local($sortkey) = $variable;
$sortkey = &csvSaveEntry($sortkey,$row,%HoH);
foreach $entry ( keys %{$HoH[$row]})
{
$replacementval=$HoH[$row]{$entry};
$sortkey =~ s/\\insertbyname{$entry}/$replacementval/g;
$sortkey =~ s/\\insert$entry/$replacementval/g;
local($column) = $idx{$entry}+1;
$rowdata[$idx{$entry}] = $replacementval;
$sortkey =~ s/\\field{(\d+)}/$1eq$column?$replacementval:$&/emg;
}
print OUTPUT "{$sortkey}{".join($separator,@rowdata)."}";
print OUTPUT ($row == $csvrow ? "%\n" : ",%\n");
}
print OUTPUT "}%\n";
if (defined($sortorder))
{
print OUTPUT "\\setkeys{csvsort.sty}{sort=$sortorder}";
}
print OUTPUT "\\sortCSVdatatotabular";
print OUTPUT "{$csvrow}{\\csvsortlist}{$align}%\n";
print OUTPUT "{$headrow}%\n";
print OUTPUT "{$midrows}%\n";
print OUTPUT "{$lastrow}%\n";
print OUTPUT "{$envname}%\n";
print OUTPUT "\\egroup\n";
print OUTPUT "\%<< END INSERT\n";
print "\n";
}
sub csvSaveEntry
{
my ($STR,$row,%HoH) = @_;
$rowctr = "csvrownumber";
while (($pos = index($STR, "\\csvSaveEntry")) > -1)
{
$start = substr($STR,0,$pos);
$restofline = substr($STR,$pos+13);
$restofline = &eatcomments($restofline);
$restofline = &eatinitialspaces($restofline);
if (substr($restofline,0,1) eq "[")
{
if (($i = index($restofline,"]")) > -1)
{
$rowctr = substr($restofline, 1, $i-1);
$restofline = substr($restofline, $i+1);
}
else
{
die "unmatched [ in \\csvSaveEntry\n";
}
$row = $counter{$rowctr};
}
($group,$restofline,$done) = &getnextgroup($restofline);
if (!$done)
{
die "argument to \\csvSaveEntry[$rowctr] not found in >>$restofline<<\n";
}
$val = $HoH[$row]{$group};
$STR = $start . "\\expandafter\\gdef\\csname $group\\roman{$rowctr}\\endcsname{$val}" . $restofline;
$data{$group}[$row] = $HoH[$row]{$group};
}
return $STR;
}
sub applyCSVfilestar
{
my ($CSVFILE,$body,$startrow) = @_;
print "Converting \\applyCSVfile*{$CSVFILE}";
$counter{'csvrownumber'} = 0;
local($csvrow, $numcols, @entry) = &getCSVvaluesstar($CSVFILE, $startrow);
&doapplyCSVstar($body, $csvrow, $numcols, @entry);
print "\n";
print OUTPUT "\%<< END INSERT\n";
}
sub csvtotabular
{
my ($CSVFILE,$ALIGN,$START,$MID,$END,$environment) = @_;
print "Converting \\CSVtotabular{$CSVFILE}";
print OUTPUT "\% \\CSVtotabular{$CSVFILE}... converted using $0\n";
print OUTPUT "\%>> START INSERT\n";
# read in data from CSV file
local($csvrow, @idx, %HoH) = &getCSVvalues($CSVFILE,2);
print OUTPUT "\\setcounter{csvrownumber}{0}%\n";
$counter{csvrownumber} = 0;
print OUTPUT "\\begin{$environment}{$ALIGN}\n";
print OUTPUT "$START";
foreach ($row=1; $row <= $csvrow; $row++ )
{
print ".";
if ($row == $csvrow)
{
$THISROW=$END;
}
else
{
$THISROW=$MID;
}
foreach $entry ( keys %{$HoH[$row]})
{
$replacementval=$HoH[$row]{$entry};
$THISROW =~ s/\\insertbyname{$entry}/$replacementval/g;
$THISROW =~ s/\\insert$entry/$replacementval/g;
$column = $idx{$entry};
$THISROW =~ s/\\field{$column}/$replacementval/g;
$THISROW = &ifnextrowlast($THISROW, ($row==$csvrow-1));
}
print OUTPUT "\\refstepcounter{csvrownumber}$THISROW";
$counter{csvrownumber}++;
}
print OUTPUT "\\end{$environment}";
print OUTPUT "\%<< END INSERT\n";
print "\n";
}
sub ifnextrowlast
{
my ($STR, $nextislast) = @_;
if (($pos = index($STR, "\\ifnextrowlast")) > -1)
{
$strbegin = substr($STR,0,$pos);
$strend = substr($STR,$pos+14);
($firstarg,$strend,$done) = &getnextgroup($strend);
if (!$done)
{
die "Can't find first argument to \\ifnextrowlast\n";
}
($secondarg,$strend,$done) = &getnextgroup($strend);
if (!$done)
{
die "Can't find second argument to \\ifnextrowlast\n";
}
if ($nextislast)
{
$STR = $strbegin . $firstarg . $strend;
}
else
{
$STR = $strbegin . $secondarg . $strend;
}
}
return $STR;
}
sub eatcomments
{
local ($_) = @_;
if (m/(\\{1}%[^%]*)*(\\*)%/)
{
$pre = $`;
$pre .= $1 if defined($1);
$pre .= $2;
local($n) = length($2);
if ($n%2 == 0)
{
$_ = $pre;
}
}
return $_;
}
sub eatinitialspaces
{
local ($_) = @_;
# while (substr($STR,0,1) eq " " or substr($STR,0,1) eq "\n"
# or substr($STR,0,1) eq "\r" or substr($STR,0,1) eq "\t")
# {
# $STR = substr($STR,1);
# }
s/^(\s)*//sg;
return $_;
}
sub getnextgroup
{
my($curline) = @_;
$curline = &eatcomments($curline);
$curline = &eatinitialspaces($curline);
# check to see if current string is blank
if ($curline!~/[^\s]+/m)
{
return ("",$curline,0);
}
if (($group = substr($curline,0,1)) ne "{")
{
# next group hasn't been delimited with braces
# return first non-whitespace character
$curline = substr($curline,1);
# unless it's a backslash, in which case get command name
if ($group eq "\\")
{
if ($curline=~/([a-zA-Z]+)(^[a-zA-Z].*)/m)
{
$group = $1;
$curline = $2;
}
else
{
# command is made up of backslash followed by symbol
$curline=~/([\W_0-9\s\\])(.*)/m;
$group = $1;
$curline = $2;
}
}
return ($group,$curline,1);
}
my $pos=index($curline, "{");
my $startpos=$pos;
my $posopen=0;
my $posclose=0;
my $bracelevel = 1;
my $done=0;
while (!$done)
{
$pos++;
$posopen = index($curline, "{", $pos);
# check to make sure it's not a \{
while ((substr($curline, $posopen-1,1) eq "\\") and ($posopen > 0))
{
# count how many backlashes come before it.
$i = $posopen-1;
$numbs = 1;
while ((substr($curline, $i-1,1) eq "\\") and ($i > 0))
{
$numbs++;
$i--;
}
# is $numbs is odd, we have a \{, otherwise we have \\{
if ($numbs%2 == 0)
{
last;
}
else
{
$posopen = index($curline, "{", $posopen+1);
}
}
$posclose= index($curline, "}", $pos);
# check to make sure it's not a \}
while ((substr($curline, $posclose-1,1) eq "\\") and ($posclose > 0))
{
# count how many backlashes come before it.
$i = $posclose-1;
$numbs = 1;
while ((substr($curline, $i-1,1) eq "\\") and ($i > 0))
{
$numbs++;
$i--;
}
# is $numbs is odd, we have a \}, otherwise we have \\}
if ($numbs%2 == 0)
{
last;
}
else
{
$posclose = index($curline, "}", $posclose+1);
}
}
if (($posopen==-1) and ($posclose==-1))
{
$done=1;
}
elsif ($posopen==-1)
{
$pos=$posclose;
$bracelevel--;
if ($bracelevel==0)
{
$group = substr($curline, $startpos+1, $pos-$startpos-1);
$curline = substr($curline, $pos+1);
return ($group,$curline,1);
}
}
elsif ($posclose==-1)
{
$pos=$posopen;
$bracelevel++;
}
elsif ($posopen<$posclose)
{
$pos=$posopen;
$bracelevel++;
}
elsif ($posclose<$posopen)
{
$pos=$posclose;
$bracelevel--;
if ($bracelevel==0)
{
$group = substr($curline, $startpos+1, $pos-$startpos-1);
$curline = substr($curline, $pos+1);
return ($group,$curline,1);
}
}
}
# closing brace must be on another line
return ("", $curline, 0);
}
sub getnextoptionalgroup
{
my($curline) = @_;
$curline = &eatcomments($curline);
$curline = &eatinitialspaces($curline);
# check to see if current string is blank
if ($curline!~/[^\s]+/m)
{
return ("","",0);
}
if (($group = substr($curline,0,1)) ne "[")
{
# no optional argument present
return ("", $curline, 1);
}
$posopen = index($curline, "[");
# search for first occurance of ]
$posclose = index($curline, "]");
if ($posclose < 0)
{
# closing bracket not on this line
return ("", $curline, 0);
}
# is there a { in the substring?
$group = substr($curline, $posopen, $posclose+1);
$contents = $group;
$restofline = substr($curline, $posclose+$posopen+1);
while (($idx=index($group, "{")) > 0)
{
$post = substr($group, $idx);
$subgroup="";
($subgroup,$remainder,$done) = &getnextgroup($post);
if ($done)
{
$group = $remainder;
}
else
{
# ] is in a group, so look for next one
$posclose = index($restofline, "]");
if ($posclose < 0)
{
# closing bracket not on this line
return ("", $curline, 0);
}
else
{
$contents .= substr($restofline,0,$posclose);
$group = $contents;
}
}
}
$contents=~s/^\[(.*)\]$/$1/;
return ($contents, $restofline, 1);
}
# get all entries in a row
# modified version of code given in Perl FAQ
sub getEntries{
local($row)=@_;
@entries = ();
push(@entries, $+) while $row =~ m{
"([^\"\\]*(?:\\.[^\"\\]*)*)"$separator? # groups the phrase inside the quotes
| ([^$separator]+)$separator?
| $separator
}gx;
push(@entries, undef) if substr($row,-1,1) eq $separator;
@entries;
}
# extract key=value pairs from list
sub getKeyValues{
local($list,%defaults)=@_;
local(%hash)=();
# remove leading commas and spaces
$list=~s/^[\s,]*//;
while ($list=~/^\s*([^,=]+)\s*/)
{
$key=$1;
$value = '';
if ($list=~s/^\s*$key\s*=\s*{/{/)
{
($value,$list,$done) = &getnextgroup($list);
}
elsif ($list=~s/^\s*$key\s*=\s*([^,]*)\s*//)
{
$value = $1;
}
elsif ($list=~s/^\s*$key\s*(,|$)//)
{
if (defined($defaults{$key}))
{
$value = $defaults{$key};
}
else
{
print "don't know default value for $key key\n";
}
}
$hash{$key} = $value;
# remove trailing commas
$list=~s/^[\s,]*//;
}
%hash;
}
1;