"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 ©_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 }