"Fossies" - the Fresh Open Source Software Archive

Member "fig2ps-1.5/bin/fig2ps" (2 Feb 2010, 17554 Bytes) of package /linux/privat/old/fig2ps-1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/usr/bin/perl -w 
    2 
    3 =pod
    4     fig2ps : convert xfig files to ps/eps/pdf processing text with LaTeX
    5     Copyright (C) 2004-2006, 2008, 2009, 2010  Vincent Fourmond
    6     
    7     This program is free software; you can redistribute it and/or modify
    8     it under the terms of the GNU General Public License as published by
    9     the Free Software Foundation; either version 2 of the License, or
   10     (at your option) any later version.
   11 
   12     This program is distributed in the hope that it will be useful,
   13     but WITHOUT ANY WARRANTY; without even the implied warranty of
   14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15     GNU General Public License for more details.
   16 
   17     You should have received a copy of the GNU General Public License along
   18     with this program; if not, write to the Free Software Foundation, Inc.,
   19     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   20 =cut
   21 
   22 # TODO-list:
   23 # * switch to the geometry package (done, Vincent Fourmond 31/12/2008)
   24 # * use proper temporary files to avoid problems
   25 #   (done, Vincent Fourmond 31/12/2008)
   26 # * add --verbose/--quiet/--silent options ?
   27 # * add the possibility to include a given file (say, by default, .fig2ps.ins)
   28 #   found in the directory where each file is.
   29 # * rewrite the add/packages stuff, confusing and not very useful
   30 # * add the possibility to write a part of the preamble directly within
   31 #   XFIG comments (using a special syntax ???)
   32 # * FIX BUG: image inclusion does not work anymore !!!!!!!!
   33 #
   34 # There are a fair number of TODOs as well in the file.
   35 
   36 use Getopt::Long qw(:config  bundling);
   37 use File::Temp qw/tempdir/;
   38 use File::Path;         # For rmtree
   39 use Cwd qw(getcwd realpath);    # To get the current directory and
   40                 # resolve files names
   41 use File::Copy;
   42 use File::Basename;         # For dirname
   43 
   44 my $help = 0;
   45 my $packages = "";
   46 my $packages_add = "";
   47 my $gv = 1;
   48 # The viewer to use, if not GV
   49 my $viewer;
   50 my $doc_class = "article";
   51 
   52 # Now using geometry for margins specifications.
   53 my $pre_beg_commands = "\\usepackage[a0paper, margin=5cm]{geometry}\n";
   54 
   55 my $post_beg_commands = "\\pagestyle{empty}%\n";
   56 my $keep_ps = 0;
   57 
   58 # whether the extension of the target file is ps or eps.
   59 my $eps_output = 0;
   60 
   61 my $manual_ps2pdf = 0;
   62 my $ps2pdf_options;
   63 
   64 my $inputfile = 0;
   65 
   66 my $force_special = 0;
   67 
   68 # Whether to keep temporary files or not.
   69 my $keep = 0;
   70 
   71 my $bbox = "gs";
   72 
   73 my $dvips_options = "";
   74 my $dvips_additional_options = "";
   75 
   76 my $fig2dev_options = "";
   77 
   78 my $pdf = 0;
   79 
   80 my $pre_add = "";
   81 
   82 # Now versioning using SVN's keywords and the like.
   83 my $svn_url = '$HeadURL: https://fig2ps.svn.sourceforge.net/svnroot/fig2ps/tags/fig2ps-1.5/bin/fig2ps $';
   84 '$Revision: 38 $' =~ /(\d+)/;
   85 my $svn_revision = $1 || 0;
   86 
   87 my $version;
   88 if($svn_url =~ /tags\/fig2ps-([^\/]+)/) {
   89     $version = $1;
   90 } else {
   91     $version = "svn r$svn_revision";
   92 }
   93 
   94 my $banner = << "EOB;" ;
   95 This is fig2ps $version, Copyright (C) 2004-2006, 2008-2010 by Vincent Fourmond
   96 
   97 fig2ps comes with ABSOLUTELY NO WARRANTY. This is free software, and
   98 you are welcome to redistribute it under the conditions stated in the
   99 GPL.txt file in the source archive.
  100 
  101 EOB;
  102 
  103 
  104 my $help_text = << "EOH;" ;
  105 Usage: 
  106 fig2ps [-h|--help]\tPrints this help
  107 fig2ps [options] file.fig [[options] file2.fig ...]
  108 Converts file.fig into ps using LaTeX for texts.
  109     --[no]gv runs or not gv at the end;
  110     --packages=pack1,pack2,... redefine packages to be used
  111     --add=pack1,pack2,... supplementary packages to be used
  112     -k|--keep  whether to keep or not the temporary files
  113     --bbox=dvips|gs|a,b,c,d method for the bounding box
  114     --input=file use file as a TeX template (\\input file)
  115     --dvips=s options to go to dvips
  116     --fig2dev=s options to go to fig2dev
  117     --preamble=s add string to the preamble
  118     --[no]pdf whether fig2ps should produce ps or pdf output
  119     --eps whether the extension of the target file is eps or ps for postscript
  120     --keepps when producing pdf, tells to keep the intermediary ps file
  121     --[no]forcespecial forces every text object to be exported as special, that 
  122       is processed with LaTeX.
  123 
  124   See the man page for more details.
  125 EOH;
  126 
  127 
  128 
  129 
  130  
  131 ###############################################################################
  132 #############################  read config ####################################
  133 ###############################################################################
  134 
  135 
  136 
  137 
  138 my $sysconfigfile = "/etc/fig2ps/fig2ps.rc";
  139 
  140 my %conffilehash = ( 'PACKAGES' => \$packages, 
  141              'ADD' => \$packages_add,
  142              'DOC_CLASS' => \$doc_class, 
  143              'DOC_OPTIONS' => \$doc_option,
  144              'FORCE_SPECIAL' => \$force_special, 
  145              'INPUT' => \$inputfile, 
  146              'GV' => \$gv,
  147              'RUNGV' => \$gv,
  148              'PREAMBLE' => \$pre_add,
  149              'KEEP_PS' => \$keep_ps);
  150 
  151 
  152 if(-f $sysconfigfile) {
  153     &readconfig($sysconfigfile,%conffilehash); 
  154 }
  155 else {
  156     print STDERR "Warning : the system-wide configuration file is missing\n";
  157 }
  158 
  159 my $persoconfigfile = $ENV{'HOME'}."/.fig2ps.rc";
  160 
  161 if(-f $persoconfigfile) {
  162     &readconfig($persoconfigfile,%conffilehash); 
  163 }
  164 
  165 
  166 # We now set a few default values which can be overridden by command-line
  167 # arguments
  168 
  169 # first, we choose the output depending on program name:
  170 if ($0 =~ /pdf/ ){ $pdf = 1;}
  171 if ($0 =~ /eps/ ){ $eps_output = 1;}
  172 
  173 # second, we disable gv if STDIN is not a terminal
  174 
  175 if(! -t STDIN) {
  176     $gv = 0;
  177 }
  178 
  179 GetOptions('help|h' => \$help,
  180        'version|V' => sub {
  181            print STDERR $banner;
  182            exit 0;
  183        },
  184        'packages=s' => sub {
  185            # Reset the added packages as well.
  186            $packages_add = "";
  187            $packages = $_[1];
  188        },
  189        'add=s' => sub {
  190            if($packages_add) {
  191            $packages_add .= "," . $_[1];
  192            }
  193            else {
  194            $packages_add = $_[1];
  195            }
  196        },
  197        'gv!' => \$gv,
  198        'viewer=s' => \$viewer,
  199        'xpdf' => sub {
  200            $viewer = "xpdf";
  201        },
  202        'keep|k' => \$keep,
  203        'keepps' => \$keep_ps,
  204        'bbox|b=s' => \$bbox,
  205        'input|i=s' => \$inputfile,
  206        'dvips=s' =>  \$dvips_additional_options,
  207        'fig2dev=s' =>  \$fig2dev_options,
  208        'pdf!' => \$pdf,
  209        'eps' => \$eps_output,
  210        'manual-ps2pdf' => \$manual_ps2pdf,
  211        'ps2pdf-options=s' => \$ps2pdf_options,
  212        'preamble=s' => sub {
  213            $pre_add .= $_[1] . "\n";
  214        },
  215        'forcespecial!' => \$force_special
  216        );
  217 
  218 print STDERR $banner;
  219 
  220 if ($help) { print $help_text;exit;}
  221 # added 23/04/04, Vincent Fourmond
  222 $pre_beg_commands.= $pre_add;
  223 
  224 
  225 my @Packages = (split (/,/,$packages));
  226 my @Add =  (split (/,/,$packages_add));
  227 
  228 my $header;
  229 
  230 # Prepares the $header variable... Ugly.
  231 prepareTex();
  232  
  233 
  234 # modified (Vincent Fourmond 20/10/2004), to account for several
  235 # file conversions in the command line :
  236 
  237 if(@ARGV <=0) 
  238 { 
  239     print STDERR "No files specified\n\n";
  240     print STDERR $help_text;
  241 }
  242 
  243 # We need to save the current directory;
  244 my $current_directory = &getcwd;
  245 
  246 # We create the temporary directory used for temporary files:
  247 my $tmpdir = &tempdir();
  248 END {
  249     if($tmpdir && -d $tmpdir) {
  250     if($keep) {
  251         print STDERR "Temporary files kept in directory: $tmpdir\n";
  252     }
  253     else {
  254         &rmtree($tmpdir);
  255     }
  256     }
  257 }
  258 
  259 # We number the jobs.
  260 my $job = 0;
  261 
  262  MAINLOOP:
  263     foreach my $file (@ARGV) {
  264     # We first make sure we are in the original directory:
  265     chdir $current_directory;
  266     
  267     $job++;
  268     print STDERR "Job $job -- file $file\n";
  269 
  270     if (! (-r $file)) {
  271         print STDERR " -> not readable\n";
  272         next MAINLOOP;
  273     }
  274 
  275     $base = sprintf("job-%03d", $job);
  276     
  277     # Copying the original to the temporary directory:
  278     &copy_fig_file($file, "$tmpdir/$base.fig", 
  279                {'forcespecial' => $force_special});
  280 
  281     # Now, we cd to the temporary dir:
  282     chdir $tmpdir;
  283     my $source_fig = "$base.fig";
  284 
  285     # We now run fig2dev to get the ps part:
  286     my $fig2dev_ps = "$base.fig2dev.ps";
  287     if(system "fig2dev -L pstex $fig2dev_options $source_fig > $fig2dev_ps")
  288     { 
  289         print STDERR " -> Problems with fig2dev: command returned $?";
  290         next MAINLOOP;
  291     }
  292     
  293 
  294     # We now run fig2dev to get the LaTeX part of the game:
  295     my $textmp = "$base.tex";
  296     $command = "fig2dev -L pstex_t $fig2dev_options -p $fig2dev_ps $source_fig |";
  297     open PSTEX, $command;
  298     open TEX, "> $textmp";
  299     
  300     my $tail = "\\end{document}\n";
  301     
  302     print TEX $header;
  303     
  304     while(<PSTEX>)
  305     {
  306         print TEX;
  307     }
  308     print TEX $tail;
  309     close PSTEX;
  310     close TEX;
  311     
  312     # we use batchmode so that latex doesn't ask the user on error
  313     if(system "latex -interaction batchmode $textmp </dev/null")
  314     {
  315         print STDERR " -> Problems with latex: command returned $?";
  316         next MAINLOOP;
  317     }
  318 
  319     # Now, we create a PS file using the right bounding box:
  320     my $tmpdvi = "$base.dvi";
  321     my $tmpps = "$base.ps";
  322     my $intermediate_ps = "$base.dvips.ps";
  323     &make_PS($tmpdvi, $tmpps, $intermediate_ps) || 
  324         next MAINLOOP;
  325 
  326     # Setting up the target names:
  327     my $psfile = $file;
  328     if($eps_output) {
  329         # Really, this is just a naming convention.
  330         $psfile =~ s/(\.fig)?$/.eps/;
  331     }
  332     else {
  333         $psfile =~ s/(\.fig)?$/.ps/;
  334     }
  335     my $pdffile = $file;
  336     $pdffile =~ s/(\.fig)?$/.pdf/;
  337 
  338     # Now, we copy the file back to its source directory:
  339     chdir $current_directory;
  340     copy("$tmpdir/$tmpps", $psfile);
  341 
  342     if($pdf) {
  343         &make_PDF($psfile, $pdffile) || next MAINLOOP;
  344         unlink $psfile unless $keep_ps;
  345     }
  346 
  347     if($gv || $viewer) {
  348         $viewer ||= "gv";
  349         print STDERR "Starting $viewer\n";
  350         if($pdf) {
  351         system($viewer,$pdffile);
  352         }
  353         else {
  354         system($viewer,$pdffile);
  355         }
  356     }
  357     }
  358 
  359 
  360 
  361 
  362 # copy_fig_file:
  363 # This function takes :
  364 # * a source fig file
  365 # * a target fig file
  366 # * an optional options hash
  367 #
  368 # It copies the fig file from source to target, mangles and symlinks
  369 # the included images if applicable and modifies the tex file according
  370 # to the options.
  371 
  372 sub copy_fig_file {
  373     my $source = &realpath(shift);
  374     my $target = &realpath(shift);
  375     my $options = shift || {};
  376 
  377     my $source_dir = &dirname($source);
  378     my $target_dir = &dirname($target);
  379     my $target_name = &basename($target, ".fig");
  380 
  381     my $old_dir = &getcwd();
  382     # We change into the source file's directory, to make life easier
  383     chdir $source_dir;
  384     
  385     
  386     open SOURCE, $source;
  387     open TARGET, "> $target"; 
  388     
  389     my $next_is_image = 0;
  390     my $image_number = 0;
  391     while(<SOURCE>) {
  392     # If we force all text to be special and this line
  393     # is a text line:
  394     if($options->{'forcespecial'} && /^4 /) # if this is a text
  395     {
  396         my @data = split ' '; # One space exactly, in order not to disturb
  397                 # any text afterwards, where spaces might
  398                 # be significant (although the probability is
  399                 # rather small)...
  400         if ($data[8] & 2) { # Already special
  401         print TARGET;
  402         }
  403         else {      # Make is special !
  404         $data[8] ^= 2;
  405         print TARGET join ' ', @data;
  406         }
  407     }
  408     elsif($next_is_image) {
  409         $next_is_image = 0;
  410         /^(\s+\d+\s+)(.*)/;
  411         my $start = $1;
  412         my $filename = &realpath($2);
  413         # We give a dummy extension; we'll see if XFIG has to
  414         # complain about that
  415         my $target_image_name = $target_name . "-" . 
  416         $image_number . ".img";
  417         $image_number++;
  418         # We symlink the file:
  419         symlink $filename, $target_dir . "/" . $target_image_name;
  420         # And print the modified line:
  421         print TARGET $start.$target_image_name."\n";
  422     }
  423     elsif(/^2\s+5/) {   # Next line will hold an image file.
  424         print TARGET;
  425         $next_is_image = 1;
  426     }
  427     else {
  428         print TARGET;
  429     }
  430     }
  431     close SOURCE;
  432     close TARGET;
  433 }
  434  
  435 
  436 
  437 ###############################################################################
  438 ############################# prepare header ##################################
  439 ###############################################################################
  440 
  441 
  442 sub prepareTex {
  443 
  444     if($inputfile) # use a common style
  445     {
  446     my $file = `kpsewhich $inputfile`;
  447     chomp $file; # we need to remove the trailing \n left by kpsewhich
  448     open FILE,$file;
  449     my @lines = <FILE>;
  450     close FILE;
  451     # Vincent Fourmond, 03/07/05: corrected bad parentheses.
  452     if(grep (/\\documentclass/,@lines) > 0) {
  453         # we have already document class
  454         $header = "\\input{$inputfile}\n";
  455     }
  456     else {
  457         $header = "\\documentclass[".$doc_option.
  458         "]{".$doc_class."}\n";
  459         $header.= "\\input{$inputfile}\n";
  460     }
  461 
  462     # adds the add packages, (Teteph...)
  463     foreach(@Add) {
  464         if(/\[(\S+)\](\S+)/)
  465         {
  466         $header .=  "\\usepackage[$1]{$2}\n";
  467         }
  468         else {
  469         my @_add = split ':';
  470         my $pack = pop @_add;
  471         if(@add> 0)
  472         {
  473             $header.= "\\usepackage[".join(',',@add)."]{$pack}\n";
  474         }
  475         else 
  476         {
  477             $header.= "\\usepackage{$_}\n";
  478         }
  479         
  480         }
  481     }
  482     
  483     # for the use of colors...
  484     $header.= "\\usepackage{color}\n";
  485     #if($pdf) {
  486     #    $header.= "\\usepackage{aeguill}\n";
  487     #}
  488         
  489     }
  490     else # builds "by hand" the package list
  491     {
  492     $header = "\\documentclass[".$doc_option.
  493         "]{".$doc_class."}\n";
  494     
  495     foreach(@Packages,@Add) {
  496         if(/\[(\S+)\](\S+)/)
  497         {
  498         $header .=  "\\usepackage[$1]{$2}\n";
  499         }
  500         else {
  501         my @add = split ':';
  502         my $pack = pop @add;
  503         if(@add> 0)
  504         {
  505             $header.= "\\usepackage[".join(',',@add)."]{$pack}\n";
  506         }
  507         else 
  508         {
  509             $header.= "\\usepackage{$_}\n";
  510         }
  511         
  512         }
  513     }
  514     
  515     }
  516     $header.=  $pre_beg_commands."\n\\begin{document}".$post_beg_commands;
  517 }
  518 
  519 
  520 ###############################################################################
  521 ############################# make PS #########################################
  522 ###############################################################################
  523 
  524 
  525 # Note that the files must not have fancy characters, as they are used
  526 # unquoted ! Use only with normal names.
  527 sub make_PS {
  528     my $dvifile = shift;    # The DVI file on which to work.
  529     my $psfile = shift;     # The target PS file
  530     my $tmpps = shift;      # A temporary PS file
  531 
  532     my $current_dvips_options = 
  533     "$dvips_options $dvips_additional_options";
  534     if($pdf) {
  535     # (Vincent Fourmond 31/12/2008) I'm not sure this really
  536     # is necessary anymore...
  537     $current_dvips_options = "-Ppdf ".$current_dvips_options;
  538     }
  539     if($bbox eq "dvips") {
  540     # We're using the -E option of dvips to get the bbox
  541     if(system "dvips $current_dvips_options -E $dvifile -o $psfile") {
  542         print STDERR " -> dvips returned error code $?";
  543         return 0;
  544     }
  545     print STDERR "-> using divps for the bounding box\n";
  546     }
  547     else {
  548     if(system "dvips $current_dvips_options $dvifile -o $tmpps") {
  549         print STDERR " -> dvips failed with error code $?";
  550         return 0;
  551     }
  552     # Now getting the bounding box !
  553     my ($LLX, $LLY, $URX, $URY);
  554     if($bbox eq "gs") { # we let gs compute the Bounding box
  555         # we specify the paper size to be b0 so that there is no problems
  556         # with outbound items
  557         $command = "gs -dNOPAUSE -dSAFER -q -sDEVICE=bbox -sPAPERSIZE=b0 ".
  558         "$tmpps < /dev/null 2>& 1 |";
  559         open BBOX, $command;
  560         my $found = 0;
  561         while(<BBOX>) {
  562         if(/^%%BoundingBox:/) {
  563             s/%%BoundingBox:\s+//;
  564             ($LLX, $LLY, $URX, $URY) = split /\s+/;
  565             $found = 1;
  566         }
  567         }
  568         close BBOX;
  569         die "Problems with gs" unless ($found == 1);
  570 
  571         # TODO: here, check that the BBox is not null.
  572 
  573         # We're adding 1 point around the bounding box in order to
  574         # make the viewing easier.
  575         --$LLX; --$LLY; ++$URX; ++$URY;
  576     }
  577     # TODO: here, a method based on convert -- faster and more reliable
  578     # than gs ???
  579     else {
  580         # Manual specification of the bounding box
  581         ($LLX, $LLY, $URX, $URY) = split /\s*,\s*/, $bbox ;
  582     }
  583 
  584     open IN, $tmpps;
  585     open OUT, "> $psfile";
  586     my $skipping = 0;
  587     while (<IN>) {
  588         if (/^%%BoundingBox/) {
  589         print OUT "%%BoundingBox: $LLX $LLY $URX $URY\n";
  590         }
  591         elsif(/^%%DocumentPaperSizes/) {
  592         # We skip that, as it probably is the cause of
  593         # our troubles
  594         }
  595         elsif(/^%%BeginPaperSize/) {
  596         $skipping = 1;
  597         # We also skip everything inbetween a
  598         # BeginPaperSize/EndPaperSize declaration
  599         }
  600         elsif(/^%%EndPaperSize/) {
  601         $skipping = 0;
  602         }
  603         else {
  604         print OUT unless $skipping;
  605         }
  606     }
  607     close OUT;
  608     close IN;
  609     print STDERR "Using $LLX $LLY $URX $URY for the bounding box\n";
  610     # (Vincent Fourmond 4/10/2004) : print the actual size of the image
  611 
  612     # Conversion to centimeters:
  613     my $factor = (596.0/21.);
  614     my $width = (-$LLX + $URX)/$factor; 
  615     my $height = ( - $LLY + $URY)/$factor; 
  616     print STDERR sprintf(" -> image is %.1fcm wide".
  617                  " and %.1fcm high\n", 
  618                  $width, $height);
  619     }
  620     return 1;
  621 }
  622 
  623 sub make_PDF {
  624     my $psfile = shift;
  625     my $pdffile = shift;
  626 
  627     if($manual_ps2pdf || $ps2pdf_options) {
  628     my $tmpps = "$pdffile.tmpfile.ps";
  629     if(system("epstopdf", "--nogs", $psfile, "--outfile=$tmpps")) {
  630         print STDERR " -> epstopdf returned $?";
  631         return 0;
  632     }
  633     if(system("ps2pdf ".($ps2pdf_options || "")." '$tmpps' '$pdffile'")) {
  634         print STDERR " -> ps2pdf returned $?";
  635         return 0;
  636     }
  637     unlink $tmpps;
  638     }
  639     else {
  640     if(system("epstopdf",$psfile, "--outfile=$pdffile")) {
  641         print STDERR " -> epstopdf returned $?";
  642         return 0;
  643     }
  644     }
  645     return 1;
  646 }
  647 
  648 
  649 ###############################################################################
  650 ############################ read config files ################################
  651 ###############################################################################
  652 
  653 
  654 sub readconfig {
  655     my $file = shift @_;
  656     my %options = @_;
  657 
  658     open CONFIG, "$file";
  659     my $line = 0;
  660     while(<CONFIG>)
  661     {
  662     $line ++;
  663     while( /\\$/)
  664     {
  665         chop;
  666         chop;
  667         $_.=<CONFIG>;
  668     }
  669     if ((!/^\#.*$/) && (!/^\s*$/) )
  670     {
  671         (my $name, my $vals) = /(\S*)\s*=\s*(\S*)$/;
  672         if((grep /$name/,keys(%options)) > 0)
  673         {
  674         ${$options{$name}} = $vals;
  675         }
  676         else {
  677         print "Warning : line ".$line." of file ".
  678             $file." not understood\n";
  679         }
  680     }
  681     }
  682     close CONFIG;
  683 }