#!/usr/local/bin/perl # # $Id: ebcdic2ascii.pl,v 1.1.1.1 2002/03/01 21:50:52 valerio Exp $ # # This script is copyrighted # Copyright (c) 2002 Valerio Di Giampietro # Valerio@DiGiampietro.com # # All rights reserved. This program is free software; you can # redistribute it and/or modify it under the same terms as Perl # itself. # # # # $Log: ebcdic2ascii.pl,v $ # Revision 1.1.1.1 2002/03/01 21:50:52 valerio # Imported sources # # # use Getopt::Std; use Convert::EBCDIC; $translator = new Convert::EBCDIC; $debug=0; $status=0; #====================================================================== # data related to file.layout format; a tipical row has the following # format: # # field field description type len dec. len start end # name log phy # ITNBR ITEM NUMBER A 15 15 1 15 # # each array has 2 element the starting row and the length of related # field #====================================================================== @campo=(0,10); #field name @descr=(11,35); #field description @dacol=(70,4); #from column @len =(63,4); #field length in bytes @loglen = (52,4); #field logical length @type=(49,1); #field type @decimals=(56,3); #number of decimals # #====================================================================== # packed2ascii converts a packed decimal to ascii # input parameters: # $str the packed decimal string # $decimals number of decimals # example: $str=0x123456d; $decimals=2; # packed2asci($str,$decimals) would return -1234.56 #====================================================================== # sub packed2ascii { my $decimals=$_[1]; my $str=unpack("H*",$_[0]); if ($debug > 2) { print STDERR "===> packed2ascii input str: ", uc $str,"\n"; print STDERR " decimals: $decimals\n"; } my $n; my $sign=chop $str; if ($decimals > 0) { $str=substr($str,0,-$decimals) . '.' . substr($str,-$decimals); $n= $str + 0.0; } else { $n= $str + 0; } if ($sign eq 'd') { $n= -$n; } if ($decimalpoint ne '.') { $n=~s/\./$decimalpoint/; } if ($debug > 2) { print STDERR " coverted: $n\n"; } return $n; } # #====================================================================== # signed2ascii converts asigned decimal to ascii # input parameters: # $str the signed decimal string # $decimals number of decimals # # example: $str=0xf1f2f3f4d5; $decimals=2; # packed2asci($str,$decimals) would return -1234.56 #====================================================================== # sub signed2ascii { my $decimals=$_[1]; my $str=unpack("H*",$_[0]); if ($debug > 2) { print STDERR "===> signed2ascii input str: ", uc $str,"\n"; print STDERR " decimals: $decimals\n"; } $str=~s/f//g; my $n; if ($str=~s/d//g) { $sign='d'; } else { $sign='c'; $str=~s/c//g; } if ($decimals > 0) { $str=substr($str,0,-$decimals) . '.' . substr($str,-$decimals); $n= $str + 0.0; } else { $n= $str + 0; } if ($sign eq 'd') { $n= -$n; } if ($decimalpoint ne '.') { $n=~s/\./$decimalpoint/; } if ($debug > 2) { print STDERR " coverted: $n\n"; } return $n; } #====================================================================== # autocrop strips leading and trailing spaces from a string # input parameter # $str string # returnd value # $str with leading and trailing spaces tripped #====================================================================== sub autocrop { my $s=$_[0]; $s=~s/^\s*//; $s=~s/\s*$//; return $s; } #====================================================================== # usage print usage message and exit #====================================================================== sub usage { print "Usage: $0 [-s c] [-d lev] [-f|-b] file.layout file.ebcdic\n"; print " -d lev set debug level\n"; print " -f use field names instead of descriptions\n"; print " -b use both field names and descriptions\n"; print " -s c use c as field separator (default is '|')\n"; print " -a no '.' -> ',' translation for decimal point\n"; exit; } # #====================================================================== # main program #====================================================================== # getopts('d:s:fba'); $decimalpoint=","; #default value (here in Italy) for the decimal point if ($opt_a) { $decimalpoint="."; } $csep = $opt_s || "|"; if (defined $opt_d) { $debug=$opt_d; } if ($#ARGV < 1) { usage(); } $ftracciato=$ARGV[0]; $fdati=$ARGV[1]; $dirtracciati="/prj/as400imm/formats2"; if (not -e $ftracciato) { $ftracciato="$dirtracciati/$ftracciato"; } print "ftracciato: $ftracciato\n" if $debug; print "fdati: $fdati\n" if $debug; #====================================================================== # read the layout file and fill in related data structure #====================================================================== open(FTRA,$ftracciato) || die "Error opening $ftracciato\n"; $status=2; while () { if (/^\s*-+\s*$/) { $status++; print "# status: $status\n" if $debug; } else { if ($status==2) { $campo=lc autocrop(substr $_, $campo[0], $campo[1]); $descr=autocrop(substr $_, $descr[0], $descr[1]); $dacol=autocrop(substr $_, $dacol[0], $dacol[1]) - 1; $len =autocrop(substr $_, $len[0], $len[1]); $loglen =autocrop(substr $_, $loglen[0], $loglen[1]); $type=substr $_, $type[0],$type[1]; $decimals=substr $_, $decimals[0],$decimals[1]; $dacol{$campo}=$dacol; $len{$campo}=$len || $loglen; if ($loglen > $len) { $len{$campo}=$loglen if ($type ne 'P'); } $descr{$campo}=$descr; $type{$campo}=$type; $decimals{$campo}=$decimals; push @campi,$campo; print "# $campo ($descr{$campo},$dacol{$campo},$len{$campo},", "$type{$campo},$decimals{$campo})\n" if $debug; } } } print "--- Second part\n" if $debug; print "---campi: @campi\n" if $debug; @outcampi=@campi; $totlen=0; for $i (@outcampi) { $dscr=$descr{$i} || $i; if ($opt_f) { print "$i",$csep; } elsif ($opt_b) { print "$i: $dscr",$csep; } else { print "$dscr",$csep; } $totlen = $totlen + $len{$i}; print " -> $i ($totlen= $totlen)\n" if $debug; } print "\n"; print "-->Total record length = $totlen \n\n" if $debug; #====================================================================== # process the ebcdic file #====================================================================== open (FDAT,$ARGV[1]) || die "error opening $ARGV[1]\n"; while (read(FDAT,$_,$totlen)) { ################## fill in the %s hash for $i (@campi) { $sebcdic=substr $_,$dacol{$i},$len{$i}; if ($type{$i} eq 'P') { #### Packed field $s=packed2ascii($sebcdic,$decimals{$i}); } elsif ($type{$i} eq 'S') { #### Signed field $s=signed2ascii($sebcdic,$decimals{$i}); } else { #### Normal field $sascii=$translator->toascii($sebcdic); $s=autocrop($sascii); } $s{$i}=$s; } ################ printout the %s hash; for $i (@outcampi) { print $s{$i},$csep; } print "\n"; }