#!/usr/bin/perl # This is gnucap2gnuplot, which is Copyright 2004 Ian Jackson. # It's a script to postprocess the output from gnucap and then run gnuplot. # # gnucap2gnuplot and its documentation are free software; you can # redistribute them and/or modify them under the terms of the GNU # General Public License as published by the Free Software Foundation; # either version 2, or (at your option) any later version. # # gnucap2gnuplot and its documentation are distributed in the hope that # they will be useful, but WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # usage: # gnucap2gnuplot [] input-file # # Input file should be a .cir file (will be put through gnucap) # or an output file from gnucap. # # Produces various output files: # .gnuplots.sh run this to display results # ,.gnuplot-cmd gnuplot script for displaying: # ,-.gnuplot-data gnuplot-format input data # ,gnuplot-fifo working fifo for .gnuplots.sh # where # is Freq or Time (according to the type of analysis) # is the count, starting at 0, of which report this is from gnucap # is the individual column of Y data # # Options # -g do run gnucap ) default is run gnucap # -G don't run gnucap ) if input file ends in .cir # -o use instead of in output filenames # If the input file is `-' then you may not specify -g and must use -o. # # Limitations # # Only Freq (.AC) and Time (.TRAN) plots have been tested. If # other types go wrong they can probably be fixed by adding code for # them to startplot(). # # Displaying voltages and currents on the same .TRAN graph won't work # well because they currently have to have the same Y scale. This # could be fixed by assigning carefully to $mmm in startplot(). # # It's a bit clumsy. # # There's no easy way to mess with the gnuplot settings. sub fail ($) { die "gnucap2gnuplot: $_[0]\n"; } while ($ARGV[0] =~ m/^\-./) { if (m/^\-\-$/) { last; } elsif (m/^\-g$/) { $rungnucap= 1; } elsif (m/^\-G$/) { $rungnucap= 0; } elsif (m/^\-o(.+)$/) { $ofb= $1; } else { fail("unknown option $_\n"); } } if (@ARGV) { @ARGV==1 or fail("one input file only please"); $if= shift @ARGV; $ofb= $if unless defined $ofb; $rungnucap= $if =~ m/\.cir$/i unless defined $rungnucap; open STDIN, $rungnucap ? "gnucap -b $if |" : "< $if" or fail("open $if: $!"); } else { fail("cannot run gnucap on stdin, run it yourself") if $rungnucap; fail("you must specify -o... when running from stdin") unless defined $ofb; } %facttimes= qw(f 1e-15 p 1e-12 n 1e-9 u 1e-6 m 1e-3 K 1e3 Meg 1e6 G 1e9 T 1e12); $sof= "$ofb.gnuplots.sh"; open A, "> $sof" or die $!; system 'chmod','+x',"$sof"; $? and die $?; print A < $ofb,$cplot.gnuplot-cmd" or die $!; print S < $ofb,$cplot-$yn.gnuplot-data" or die $!; } } sub endplot () { return unless defined $kind; foreach $mmm (keys %min) { print S "set ${mmm}range [$min{$mmm}:$max{$mmm}]\n" or die $!; } $sep= "plot "; for ($yn=1; $yn<=$#columns; $yn++) { close "O$yn" or die $!; $mmm[$yn] =~ m/^y2?$/ or die "$mmm[$yn]"; $axes= $mmm[$yn]; $axes =~ s/^y$/y1/; $yoff= 1-$yn; print S "$sep\\\n". " '$ofb,$cplot-$yn.gnuplot-data'". " axes x1$axes title '$columns[$yn]'" or die $!; $sep= ','; } print S "\n\npause -1\n" or die $!; close S or die $!; print A " gnuplot $ofb,$cplot.gnuplot-cmd <\$fi &\n" or die $!; $kind= undef; } $readahead= ; for (;;) { $linesofar= $readahead; for (;;) { $readahead= ; last unless $readahead =~ s/^\+//; die unless length $linesofar; $linesofar =~ s/\n$//; $linesofar .= $readahead; } $_= $linesofar; last unless length; s/\s+$//; if (m/^\#(\w+)/) { endplot(); $kind= $1; @columns= split /\s+/; $cplot= $kind.($counter{$kind}++); startplot(); next; } elsif (!defined $kind) { next; } elsif (s/^\s+//) { @numbers= split /\s+/; die unless @numbers == @columns; for ($yn=0; $yn<=$#columns; $yn++) { $_= $numbers[$yn]; if (m/^(\-?\d+\.\d*)([A-Za-z]+)$/) { die "factor $2" unless exists $facttimes{$2}; $_= $1*$facttimes{$2}; $numbers[$yn]= $_; } $mmm= $mmm[$yn]; $min{$mmm}= $_ unless exists($min{$mmm}) && $min{$mmm} <= $_; $max{$mmm}= $_ unless exists($max{$mmm}) && $max{$mmm} >= $_; if ($yn) { printf {"O$yn"} "%s %s\n", $numbers[0], $_ or die $!; } } } else { die "$_ ?"; } } die "no plots" unless defined $kind; endplot(); print A <\$fi printf 'hit return to quit: ' read exec 3>&- END or die $!; close A or die $!; $?=0; close STDIN; $? and fail("gnucap failed (code $?)"); $sof= "./$sof" unless $sof =~ m,/,; print ": generated ; $sof\n" or die $!; # $Id: gnucap2gnuplot,v 1.3 2004-03-24 01:00:50 ianmdlvl Exp $