#!/usr/bin/perl -w
#swap line 1 and 3 to use the perl debugger
#!/usr/bin/perl -w -d:ptkdb
use strict;
use warnings;
#use diagnostics;
$|++;
require 5.006;
our $VERSION = '2.0';
use Getopt::Long qw(GetOptions);
use Cwd;
use File::Basename;
use Tk;
use Tk::WaitBox;
use Tk::HList;
use Tk::ProgressBar;
use Tk::Scale;
use GDS2;
BEGIN
{
use constant TRUE => 1;
use constant FALSE => 0;
}
$\="\n";
## subs used
sub printUsage(;$);
sub printVersion();
sub getHomeDir($);
sub dumpGds($$;$);
our $BGCOLOR='#99ccff';
our $BGCOLOR2='#ffff00';
our $BGCOLOR3='#ffffcc';
our $FGCOLOR='#000000';
our $FileImg;
our $TextFileImg;
our $FoldImg;
our $G_percentDone=0;
our $G_ECHO=1,
our $ActFoldImg;
my $compact = FALSE;
our $MW;
my $gui=FALSE;
my $DEBUG=FALSE;
my $G_outputBufferSize=10000;
my $G_useStatusBar=FALSE;
## process command line...
GetOptions(
'compact!' => \$compact,
'debug!' => \$DEBUG,
'gdt!' => \$compact,
'gui!' => \$gui,
'help!' => \&printUsage,
'obs|outputbuffersize:i' => \$G_outputBufferSize,
'pb|progressbar' => \$G_useStatusBar,
'version' => \&printVersion,
) || printUsage();
my $G_statusBar;
if ($G_useStatusBar)
{
require Term::StatusBar;
}
my $fileNameIn = '';
$fileNameIn = shift if ($#ARGV >= 0);
printUsage() if ($#ARGV >= 0);
my $G_header = '';
if ($compact)
{
$G_header = <<'EOH';
# first line needs to stay as is (read by other tools)
# Key: <required> [optional]
# File format:
# gds2{<ver>
# m=<modificationTimeStamp> a=<acessTimeStamp>
# lib '<libName>' <userUnits> <dataUnits>
# <cellDefine>
# }
# - - - - -
# cellDefine is one of more of:
# cell { c=<creationTimeStamp> m=<modificationTimeStamp> '<cellName>'
# <cellStuff>
# }
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
## <cellStuff>
# cellStuff is one or more of:
# boundary:
# b{<layer> [dt<dataType>] xy(<xyList>)}
#
# path:
# p{<layer> [dt<dataType>] [pt<pathType>] [w<real>] [bx<real>] [ex<real>] xy(<xyList>)}
#
# text:
# t{<layer> [tt<textType>] [f<fontType>] [<textJust>] [pt<pathType>] [fx] [w<real>] [m<magification>] [a<angle>] xy(<xyList>) <'text'> }
#
# sref:
# s{<'cellName'> [fx] [a<angle>] xy(<xyList>)}
#
# aref:
# a{<'cellName'> [fx] [a<angle>] cr(<columns> <rows>) xy(<xyList>)}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# <textJust> two letter combination of bmt (bottom,middle,top) and rcl (right,center,left) e.g. bl (default is tl)
#
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# # as first character on a line is a comment
EOH
}
if (! $gui)
{
## take care of things we need from user that were not
## supplied on command line
if ($fileNameIn eq '')
{
my $notDone = 9; #limit for how many times we will ask
while ($notDone)
{
printf("GDS2 file to read: ");
$fileNameIn = <STDIN>;
chomp $fileNameIn;
$notDone = 0 if ($fileNameIn ne '');
}
printUsage() if ($fileNameIn eq '');
}
dumpGds($fileNameIn,$compact);
}
else
{
my @packList1 = (-side => 'left', -padx => 0, -pady => 3, -fill => 'x');
my @packList2 = (-side => 'left', -padx => 3, -pady => 2, -fill => 'x');
my @packList3 = (-side => 'top', -padx => 0, -pady => 3, -fill => 'x');
my @packList4 = (-side => 'right', -padx => 3, -pady => 3, -fill => 'x');
my @packList5 = (-side => 'top', -padx => 3, -pady => 3, -fill => 'x');
#### create the MainWindow (MW)
$MW = MainWindow -> new(
-background => $BGCOLOR,
-foreground => $FGCOLOR,
);
$MW -> title('dumpgds');
$MW -> iconname('dumpgds');
$MW -> minsize(1, 1);
###### start top menu bar #####
my $wMenu = $MW -> Frame(
-relief => 'raised',
-background => $BGCOLOR,
-borderwidth => 2,
);
$wMenu -> pack(-fill => 'x');
##### options menu #####
my $optionsMenu = $wMenu -> Menubutton(
-activebackground => $BGCOLOR2,
-background => $BGCOLOR,
-text => 'Options',
-underline => FALSE,
);
$optionsMenu -> separator(
-background => $BGCOLOR,
);
$optionsMenu -> radiobutton(
-activebackground => $BGCOLOR,
-variable => \$G_ECHO,
-label => 'Echo to terminal',
-value => TRUE,
);
$optionsMenu -> radiobutton(
-activebackground => $BGCOLOR,
-variable => \$G_ECHO,
-label => 'do not echo to terminal',
-value => FALSE,
);
### quit
$optionsMenu -> command(
-activebackground => 'Red',
-background => $BGCOLOR,
-label => 'Exit',
-command => sub { $MW -> destroy; exit(1); },
);
$optionsMenu -> pack(-side=>'left');
##### Help menu #####
my $textArea;
my $helpMenu = $wMenu -> Menubutton(
-text => 'Help',
-activebackground => $BGCOLOR2,
-background => $BGCOLOR,
-underline => 0
);
$helpMenu -> command(
-activebackground => $BGCOLOR2,
-background => $BGCOLOR,
-label => 'Program Version',
-command => sub {
$textArea -> delete('0.0', 'end');
$textArea -> insert('end', "dumpgds $VERSION\n");
$textArea -> insert('end', "Using Perl $]\n");
},
);
$helpMenu -> separator(
-background => $BGCOLOR,
);
$helpMenu -> command(
-activebackground => $BGCOLOR2,
-background => $BGCOLOR,
-label => 'Print help in text window',
-command => sub { \&printUsage($textArea); },
-activebackground => 'purple',
);
$helpMenu -> pack(-side=>'right');
#### end top menu bar #####################################
my $progress = $MW -> ProgressBar(
-anchor => 'w',
-width => 20,
-length => 400,
-from => 0,
-to => 98,
-troughcolor => '#000000',
-blocks => 20,
-colors => [0 => 'red',14 => 'orange',28 => 'yellow',42 => 'green',56 => 'blue',70 => 'purple',84 => 'violet'],
-resolution => 5,
-variable => \$G_percentDone,
);
$progress -> pack();
#$progress -> pack(@packList5);
##### Create file selection areas ####
## Create Frame for left side
my $mwLeft = $MW -> Frame(
-relief => 'raised',
-background => $BGCOLOR,
-borderwidth => 2,
);
$mwLeft -> pack(@packList1);
$FileImg = $mwLeft -> Pixmap(-file => Tk->findINC('file.xpm'));
$TextFileImg = $mwLeft -> Pixmap(-file => Tk->findINC('textfile.xpm'));
$FoldImg = $mwLeft -> Pixmap(-file => Tk->findINC('folder.xpm'));
$ActFoldImg = $mwLeft -> Pixmap(-file => Tk->findINC('act_folder.xpm'));
#### directory entry
my $directoryLabel = $mwLeft -> Label(
-background => $BGCOLOR,
-text => 'PWD:',
-font => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*",
-anchor => 'w',
);
$directoryLabel -> pack(@packList3);
my $G_DIRECTORY = '';
my $entryDirectory = $mwLeft -> Entry(
-background => '#cccccc',
-font => "-*-courier-medium-r-normal--*-140-*-*-*-*-*-*",
-foreground => $FGCOLOR,
-relief => 'sunken',
-state => 'disabled',
-textvariable => \$G_DIRECTORY,
-width => 20,
);
$entryDirectory -> pack(@packList3);
my $localDir = cwd();
$G_DIRECTORY=basename($localDir);
#### spacer label
my $spacerLabel_1 = $mwLeft -> Label(
-background => $BGCOLOR,
-text => ' ',
-font => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*",
-anchor => 'w',
);
$spacerLabel_1 -> pack(@packList3);;
#### graphics file entry
my $graphicsFileLabel = $mwLeft -> Label(
-text => 'Gds2 File: ',
-font => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*",
-background => $BGCOLOR,
-anchor => 'w',
);
$graphicsFileLabel -> pack(@packList3);
##### Create graphics text display area #####
my $G_GDS2FILE = $fileNameIn;
my $entryGraphicsFile = $mwLeft -> Entry(
-background => '#cccccc',
-font => "-*-courier-medium-r-normal--*-140-*-*-*-*-*-*",
-foreground => $FGCOLOR,
-relief => 'sunken',
-state => 'disabled',
-textvariable => \$G_GDS2FILE,
-width => 22,
);
$entryGraphicsFile -> pack(@packList3);
##$entryGraphicsFile -> focus;
#### spacer label
my $spacerLabel_2 = $mwLeft -> Label(
-background => $BGCOLOR,
-text => ' ',
-font => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*",
-anchor => 'w',
);
$spacerLabel_2 -> pack(@packList3);;
#### gds2 label
my $graphicsFileLabel_1 = $mwLeft -> Label(
-text => " Select Gds2 File: 'double click'",
-font => "-*-times-bold-r-normal--*-140-*-*-*-*-*-*",
-background => $BGCOLOR,
-anchor => 'w',
);
$graphicsFileLabel_1 -> pack(@packList3);;
### -- graphics file listing -- ##
my $graphicsFileList;
$graphicsFileList = $mwLeft -> Scrolled(
'HList',
-scrollbars => 'sw',
-itemtype => 'imagetext',
-separator => '/',
-selectmode => 'single',
-indent => 25,
-background => $BGCOLOR,
-bd => '2',
-font => "-*-courier-medium-r-normal--*-140-*-*-*-*-*-*",
-foreground => $FGCOLOR,
-height => 16,
-relief => 'sunken',
-width => 25,
-command => sub {
my $localDir = cwd();
my $name=setFileName($_[0]);
$G_GDS2FILE=$name;
$G_DIRECTORY=basename($localDir);
chomp $G_GDS2FILE;
my $rootName = $G_GDS2FILE;
$rootName =~ s|\.\w*||;
if ($_[0] eq '.')
{
my $waitBox = $graphicsFileList -> WaitBox;
$waitBox -> configure(
-txt1 => "Please wait while I list items",
-txt2 => "Thank you",
-font => "-*-times-bold-r-normal--*-120-*-*-*-*-*-*",
-foreground => $FGCOLOR,
-background => $BGCOLOR,
);
$waitBox -> Show;
$graphicsFileList -> delete('entry', $_[0]);
$graphicsFileList -> add(
'.',
-text => $localDir,
-image => $ActFoldImg,
);
my $displayName=basename($localDir);
showGdsFiles('.', $displayName, $graphicsFileList);
$waitBox -> unShow;
}
chdir $localDir;
},
);
$graphicsFileList -> grid(qw/-sticky nsew/);
$localDir = cwd();
$graphicsFileList -> add(
'.',
-text => $localDir,
-image => $FoldImg,
);
$graphicsFileList -> pack(@packList3);
### -- end Graphics listing -- ##
#### text areaa
$textArea = $MW -> Text(
-bd => '2',
-font => '-*-courier-medium-r-normal--*-140-*-*-*-*-*-*',
-height => 25,
-relief => 'sunken',
-setgrid => 'true',
-width => 93,
-wrap => 'word',
-background => $BGCOLOR3,
-foreground => $FGCOLOR,
);
#### text scrollbar...attached to MW
my $textScroll = $MW -> Scrollbar(
-command => [$textArea => 'yview'],
-background => $BGCOLOR,
);
$textArea -> configure(
-yscrollcommand => ['set', $textScroll],
);
#### scrollbar goes on the left side
$textScroll -> pack(
-side => 'left',
-fill => 'y',
);
#### display
$textArea -> pack(
-expand => 'yes',
-fill => 'both',
);
#### Create Frame for bottom
my $mwBottom = $MW -> Frame(
-relief => 'raised',
-background => $BGCOLOR,
-borderwidth => 2,
);
$mwBottom -> pack(@packList1);
#### Create 'Dump' Button widget ######
my $dumpButton = $mwBottom -> Button(
-font => '-*-times-bold-r-normal--*-140-*-*-*-*-*-*',
-text => 'Dump',
-height => 1,
-width => 8,
-command => sub { \&dumpGds($G_GDS2FILE,$compact,$textArea); },
-background => $BGCOLOR,
-activebackground => $BGCOLOR2,
);
$dumpButton -> pack(@packList2);
#### Create 'Clear' Button widget ######
my $clearButton = $mwBottom -> Button(
-font => '-*-times-bold-r-normal--*-140-*-*-*-*-*-*',
-text => ' Clear ',
-height => 1,
-width => 8,
-command => sub { \&clear($textArea); },
-background => $BGCOLOR,
-activebackground => $BGCOLOR2,
);
$clearButton -> pack(@packList2);
$progress -> value($G_percentDone);
my $fileSize = (stat $fileNameIn)[7];
MainLoop();
}
## subroutines...
################################################################################
sub dumpGds($$;$)
{
my $fileNameIn = shift;
my $compact = shift;
my $widget = shift;
my $fileSize = (stat $fileNameIn)[7];
my $statusNum = 0;
my $gds2FileIn = new GDS2(-fileName => $fileNameIn);
if (defined $widget)
{
$G_percentDone = 0;
$MW -> update;
}
if ($G_useStatusBar)
{
$G_statusBar = new Term::StatusBar (
fh => \*STDERR,
label => "dumpgds of $fileNameIn",
showTime => TRUE,
startPos => 'bottom',
totalItems => 100,
);
$G_statusBar -> start;
}
my $buffer = '';
my $printString = '';
my $printIt = TRUE;
my $bufferSize = 0;
while ($gds2FileIn -> readGds2Record)
{
$bufferSize += $gds2FileIn -> recordSize;
$printIt = FALSE;
my $tmpString = $gds2FileIn -> returnRecordAsString(-compact=>$compact);
$printString .= $tmpString;
if ($compact)
{
if ( ##{
($printString =~ m/}$/) ||
($printString =~ m/cell\s*{.*'$/) || ##}
($printString =~ m/^gds2\s*{\s*\d/) || ##}
($printString =~ m/^lib\s+'\S+'\s+\S+\s+\S+/) ||
($printString =~ m/^[cm]=\d/)
)
{
if ($printString =~ m/^lib\s/)
{
$printString .= "\n$G_header";
}
else
{
$printString .= "\n";
}
$printIt = TRUE;
}
}
else
{
$printString .= "\n";
$printIt = TRUE;
}
my $filePos = $gds2FileIn -> tellSize;
print STDERR "GDSLENGTH==$filePos bufferSize==$bufferSize" if ($DEBUG);
if ($printIt)
{
if ($compact)
{
$printString =~ s/ m1 cr/ cr/;
$printString =~ s/ m1 xy/ xy/;
$printString =~ s/ m1 a/ a/;
$printString =~ s/ 0 pt/ pt/;
$printString =~ s/ 0 xy/ xy/;
$printString =~ s/ 0 (f[0-3])/ $1/;
$printString =~ s/ pt0 / /;
$printString =~ s/ f0 / /;
$printString =~ s/ tl / /;
$printString =~ s/ w0 / /;
$printString =~ s/ cr (\d+) (\d+)/ cr($1 $2)/;
$printString =~ s/{ /{/; ##}}
$printString =~ s/(\d) (d|t)t0 /$1 /; ##}}
}
if (defined $widget)
{
$widget -> insert('end',"$printString");
$widget -> update;
}
if ($G_ECHO)
{
$buffer .= $printString;
}
$printString = '';
if ($G_ECHO && ($bufferSize > $G_outputBufferSize))
{
printf $buffer;
$buffer = '';
$bufferSize = 0;
}
}
$G_percentDone = int($filePos * 100 / $fileSize);
if ($G_useStatusBar && ($G_percentDone - $statusNum > 1))
{
$G_statusBar -> update($G_percentDone - $statusNum);
$statusNum = $G_percentDone;
}
}
printf $buffer if ($buffer ne '');
$buffer = '';
$bufferSize = 0;
$G_statusBar -> update(100) if ($G_useStatusBar);
}
################################################################################
sub setFileName($)
{
my $file = $_[0];
my $returnString='';
$file =~ s|\./||; ## for now...
chomp $file;
if (-f $file)
{
$returnString=$file;
}
return $returnString;
}
################################################################################
sub showGdsFiles
{
my($entryPath, $text, $widget) = @_;
opendir(DIR, $entryPath);
my(@dirent_1) = grep ! /^\.\.?$/, sort(readdir DIR);
closedir DIR;
my(@dirent_2) = grep ! /~$/, @dirent_1;
my(@dirent) = grep ! /\.swp$/, @dirent_2;
if ($entryPath ne '.')
{
$widget -> add(
$entryPath,
-text => $text,
-image => $ActFoldImg,
);
}
my $file;
my $cnt=0;
while ($file = shift @dirent)
{
my $filePath = "$entryPath/$file";
if (! -d $filePath)
{
if ( ($file =~ /\.gds[2i]*$/i) or ($file =~ /\.sf$/i) )
{
$cnt++;
my $size = -s $filePath;
if (-T $file)
{
$widget -> add(
$filePath,
-text => $file,
-image => $TextFileImg,
-data => $size,
);
}
else
{
$widget -> add(
$filePath,
-text => $file,
-image => $FileImg,
-data => $size,
);
}
}
}
}
if (! $cnt)
{
print "In order to be seen, graphics files must end in \".gds\", \".gds2\", \".gdsii\", \".sf\" ";
}
} # end showGdsFiles
################################################################################
################################################################################
sub clear($;$)
{
my $widget = shift;
$widget -> delete('0.0', 'end');
$G_percentDone = 0;
$widget -> update;
}
################################################################################
sub printVersion()
{
print $main::VERSION;
exit 0;
}
################################################################################
sub printUsage(;$)
{
my $widget = shift;
my $printMethodFront = 'printf("';
my $printMethodBack = '\n");';
if (defined $widget && ($widget ne 'help'))
{
$widget -> delete('0.0', 'end');
$widget -> yview('end');
$widget -> insert('end', "Calling help ....\n");
$widget -> update;
$printMethodFront = "\$widget -> insert(\'end\', \"";
$printMethodBack = '\n"); $widget -> update;';
}
else
{
undef $widget;
}
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront." dumpgds rev $main::VERSION".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront."Usage:".$printMethodBack;
eval $printMethodFront." dumpgds [options] gds_file_to_read > outputFile".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront."Synopsis:".$printMethodBack;
eval $printMethodFront." Dumps GDS2 file out in an ascii format that preserves the data contained ".$printMethodBack;
eval $printMethodFront." therein.".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront."Options:".$printMethodBack;
eval $printMethodFront." -compact".$printMethodBack;
eval $printMethodFront." or".$printMethodBack;
eval $printMethodFront." -gdt".$printMethodBack;
eval $printMethodFront." output compact gdt format".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront." -gui".$printMethodBack;
eval $printMethodFront." run in GUI mode".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront." -help".$printMethodBack;
eval $printMethodFront." print help and exit".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront." -outputbuffersize [integer]".$printMethodBack;
eval $printMethodFront." or".$printMethodBack;
eval $printMethodFront." -obs [integer] ".$printMethodBack;
eval $printMethodFront." set output buffer size. Default is $G_outputBufferSize".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront." -progressBar".$printMethodBack;
eval $printMethodFront." or".$printMethodBack;
eval $printMethodFront." -pb".$printMethodBack;
eval $printMethodFront." display progress bar if able".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront." -version".$printMethodBack;
eval $printMethodFront." print version and exit".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
eval $printMethodFront."Examples:".$printMethodBack;
eval $printMethodFront." dumpgds test.gds > test.gdstxt".$printMethodBack;
eval $printMethodFront." dumpgds -c test.gds > test.gdt".$printMethodBack;
eval $printMethodFront." ".$printMethodBack;
exit 1 if (! defined $widget);
}
################################################################################
__END__