#!/usr/bin/perl sub UsageShort() { print "Usage: tabfmt [ -h | --help ] | [ format.tab [variables1.var ... variablesN.var] ]\n" ; } sub UsageLong() { print " Escapes in the format file are:\n" ; print " _ \$(var_name) : variable content is simply printed\n" ; print " _ \${expression} : the expression is evaluated\n" ; print " An additionnal imperative size can be specified by using\n" ; print " \$(var_name):size or \${expression}:size\n" ; print " The variables file contains one variable definition by line:\n" ; print " _ VAR = no_whitespace_string\n" ; print " _ VAR = \"any words without double quotes\"\n" ; print " A dash ('-') stands for the standard input\n" ; } if(scalar(@ARGV)==0) { UsageShort() ; exit 1 ; } if(($ARGV[0] eq '-h')||($ARGV[0] eq '--help')) { UsageShort() ; UsageLong() ; exit 0 ; } # FormatString # Formats a string, according to alignment, into a string of fixed length # Args: # _str : string to format # _fil : character filler # _len : total final length # _aln : c|r|l , horizontal alignment # Returns: # _the formatted string sub FormatString($$$$) { my $str = shift ; my $fil = shift ; my $len = shift ; my $aln = shift ; if(length($fil)==0) { $fil = ' ' ; } $fil = substr($fil,0,1) ; if(!defined $str) { return $fil x $len ; } if(length($str)>=$len) { return $str ; } if($aln eq 'l') { return $str . ($fil x ($len-length($str))) ; } elsif($aln eq 'r') { return ($fil x ($len-length($str))) . $str ; } elsif($aln eq 'c') { return ($fil x (($len-length($str))/2)) . $str . ($fil x (($len+1-length($str))/2)) ; } else { return $str ; } } # InterpretString # Parses and rewrite a variable or expression definition # Args: # _var : reference to a variables hash # _str : string to parse # _len : length of result string [optional] # Returns: # _an interpreted string, if the hash ref was valid and '$(..)' or '${..}' # patterns were found # _a '*' (star) only string if the hash ref was invalid # _the original string otherwise sub InterpretString($$;$) { my $var = shift ; my $str = shift ; my $len = length($str) ; my $alg = 'c' ; if(scalar(@_)) { my $tmp = shift ; if($tmp=~/^([rcl])(\d+)/) { $alg = $1 ; $len = $2 ; } else { $len = $tmp ; } } if(ref($var) ne 'HASH') { return '*' x $len ; } if($str=~m/^\s*\$\(([^\)]+)\)\s*$/) { #print stderr "Format \"$str\"\n" ; return FormatString($var->{$1},' ',$len,$alg) ; } elsif($str=~m/^\s*\$\{([^\}]+)\}\s*$/) { #print stderr "Interp \"$str\"\n" ; $str = $1 ; if($str =~ /\$/) { $str =~ s/\$\(([^\)]+)\)/$var->{$1}/g ; local $SIG{__WARN__} = sub { } ; $str = eval($str) ; } if(length($str)>$len) { $str = substr($str,0,$len) ; } return FormatString($str,' ',$len,$alg) ; } #print stderr "Reject \"$str\"\n" ; return $str ; } # LoadVarFile # Loads a variables definition file into a hash # Args: # _var : reference to a variables hash # _file : the file to read # Returns: # _the original hash ref if it was defined and valid # _a ref to a new hash if the first argument was undef # _'undef' if the hash ref was invalid sub LoadVarFile($$) { my $var = shift ; my $file = shift ; if(defined $var) { if(ref($var) ne 'HASH') { return undef ; } } else { $var = { } ; } if($file ne '-') { local *F ; open(F,'<',$file) ; while() { if(/^#/) { next ; } if(/^\s*$/) { next ; } if( (/^\s*([^\s]+)\s*=\s*([^'"\s][^\s]*)/) || (/^\s*([^\s]+)\s*=\s*"([^"]+)"/) || (/^\s*([^\s]+)\s*=\s*'([^']+)'/) ) { $var->{$1} = $2 ; } } close(F) ; } else { while() { if(/^#/) { next ; } if(/^\s*$/) { next ; } if( (/^\s*([^\s]+)\s*=\s*([^'"\s][^\s]*)/) || (/^\s*([^\s]+)\s*=\s*"([^"]+)"/) || (/^\s*([^\s]+)\s*=\s*'([^']+)'/) ) { $var->{$1} = $2 ; } } } return $var ; } my %allvars = ( '_processed_with_' => "$0" ) ; sub PrintFile($) { my $file = shift ; if($file ne '-') { local *F ; open(F,'<',$file) ; while() { s/(?<=\|)(\s*\$(?:(?:\([^\)]+\))|(?:\{[^\}]+\}))\s*)(?=\|)/InterpretString(\%allvars,$1)/eg ; s/(?<=[^\s])\s*(\$(?:(?:\([^\)]+\))|(?:\{[^\}]+\}))):([rcl]?\d+)\s*(?=[^\s])/InterpretString(\%allvars,$1,$2)/eg ; s/(?) { s/(?<=\|)(\s*\$(?:(?:\([^\)]+\))|(?:\{[^\}]+\}))\s*)(?=\|)/InterpretString(\%allvars,$1)/eg ; s/(?<=[^\s])\s*(\$(?:(?:\([^\)]+\))|(?:\{[^\}]+\}))):([rcl]?\d+)\s*(?=[^\s])/InterpretString(\%allvars,$1,$2)/eg ; s/(?