1eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' && eval 'exec perl -S $0 $argv:q'
2 if 0;
3
4#D \module
5#D [ file=makempy.pl,
6#D version=2000.12.14,
7#D title=\METAFUN,
8#D subtitle=\METAPOST\ Text Graphics,
9#D author=Hans Hagen,
10#D date=\currentdate,
11#D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
12#C
13#C This module is part of the \CONTEXT\ macro||package and is
14#C therefore copyrighted by \PRAGMA. See licen-en.pdf for
15#C details.
16
17# Tobias Burnus provided the code needed to proper testing
18# of binaries on UNIX as well as did some usefull suggestions
19# to improve the functionality.
20
21# This script uses GhostScript and PStoEdit as well as
22# pdfTeX, and if requested TeXEdit and ConTeXt.
23
24# todo: we can nowadays do without the intermediate step, because GS
25# can now handle PDF quite good
26
27use Getopt::Long ;
28use Config ;
29use strict ;
30
31$Getopt::Long::passthrough = 1 ; # no error message
32$Getopt::Long::autoabbrev = 1 ; # partial switch accepted
33
34my $help = 0 ;
35my $silent = 0 ;
36my $force = 0 ;
37my $noclean = 0 ;
38
39my $amethod = my $pmethod = my $gmethod = 0 ;
40
41my $format = "plain" ; # can be "context" for plain users too
42
43&GetOptions
44 ( "help" => \$help ,
45 "silent" => \$silent ,
46 "force" => \$force ,
47 "pdftops" => \$pmethod ,
48 "xpdf" => \$pmethod ,
49 "gs" => \$gmethod ,
50 "ghostscript" => \$gmethod ,
51 "noclean" => \$noclean ) ;
52
53my $mpochecksum = 0 ;
54
55my %tex ; my %start ; my %stop ;
56
57$tex{plain} = "pdftex" ;
58$tex{latex} = "pdflatex" ;
59$tex{context} = "texexec --batch --once --interface=en --pdf" ;
60
61$start{plain} = '' ;
62$stop{plain} = '\end' ;
63
64$start{latex} = '\begin{document}' ;
65$stop{latex} = '\end{document}' ;
66
67$start{context} = '\starttext' ;
68$stop{context} = '\stoptext' ;
69
70my $ghostscript = "" ;
71my $pstoedit = "" ;
72my $pdftops = "" ;
73my $acroread = "" ;
74
75my $wereondos = ($Config{'osname'} =~ /dos|mswin/io) ;
76
77# Unix only: assume that "gs" in the path. We could also
78# use $ghostscipt = system "which gs" but this would require
79# that which is installedd on the system.
80
81sub checkenv
82 { my ($var, $env) = @_ ;
83 if ($var)
84 { return $var }
85 elsif ($ENV{$env})
86 { return $ENV{$env} }
87 else
88 { return $var } }
89
90$ghostscript = checkenv ($ghostscript, "GS_PROG" ) ;
91$ghostscript = checkenv ($ghostscript, "GS" ) ;
92$pstoedit = checkenv ($pstoedit , "PSTOEDIT") ;
93$pdftops = checkenv ($pdftops , "PDFTOPS" ) ;
94$acroread = checkenv ($acroread , "ACROREAD") ;
95
96sub setenv
97 { my ($var, $unix, $win) = @_ ;
98 if ($var)
99 { return $var }
100 elsif ($wereondos)
101 { return $win }
102 else
103 { return $unix } }
104
105$ghostscript = setenv($ghostscript, "gs" , "gswin32c") ;
106$pstoedit = setenv($pstoedit , "pstoedit", "pstoedit") ;
107$pdftops = setenv($pdftops , "pdftops" , "pdftops" ) ;
108$acroread = setenv($acroread , "acroread", "" ) ;
109
110# Force a method if unknown.
111
112unless ($pmethod||$amethod||$gmethod)
113 { if ($wereondos) { $pmethod = 1 } else { $amethod = 1 } }
114
115# Set the error redirection used under Unix:
116# stderr -> stdout
117
118my $logredirection = '>>' ;
119
120# This unfortunally doesn't work with the ksh and simple sh
121#
122# if (!$wereondos)
123# { $logredirection = '2>&1 >>' ; # Bash
124# $logredirection = '>>&' ; # tcsh, Bash
125# default $logredirection. }
126
127# Some TeX Code Snippets.
128
129my $macros = '
130
131% auxiliary macros
132
133\input supp-mis.tex
134
135\def\startTEXpage[scale=#1]%
136 {\output{}
137 \batchmode
138 \pdfoutput=1
139 \pdfcompresslevel=9
140 \hoffset=-1in
141 \voffset=\hoffset
142 \scratchcounter=#1
143 \divide\scratchcounter1000
144 \edef\TEXscale{\the\scratchcounter\space}
145 \forgetall
146 \setbox0=\vbox\bgroup}
147
148\def\stopTEXpage
149 {\egroup
150 \dimen0=\ht0 \advance\dimen0 \dp0
151 \setbox2=\vbox to 10\dimen0
152 {\pdfliteral{\TEXscale 0 0 \TEXscale 0 0 cm}
153 \copy0
154 \pdfliteral{1 0 0 1 0 0 cm}
155 \vfill}
156 \wd2=10\wd0
157 \pdfpageheight=\ht2
158 \pdfpagewidth=\wd2
159 \ScaledPointsToBigPoints{\number\pdfpageheight}\pdfcropheight
160 \ScaledPointsToBigPoints{\number\pdfpagewidth }\pdfcropwidth
161 \expanded{\pdfpageattr{/CropBox [0 0 \pdfcropwidth \space \pdfcropheight]}}
162 \shipout\hbox{\box2}}
163
164% end of auxiliary macros' ;
165
166sub report
167 { return if $silent ;
168 my $str = shift ;
169 if ($str =~ /(.*?)\s+([\:\/])\s+(.*)/o)
170 { if ($1 eq "") { $str = " " } else { $str = $2 }
171 print sprintf("%22s $str %s\n",$1,$3) } }
172
173sub error
174 { report("processing aborted : " . shift) ;
175 exit }
176
177sub process
178 { report("generating : " . shift) }
179
180sub banner
181 { return if $silent ;
182 print "\n" ;
183 report ("MakeMPY 1.1 - MetaFun / PRAGMA ADE 2000-2004") ;
184 print "\n" }
185
186my $metfile = "" ; # main metapost file
187my $mpofile = "" ; # metapost text specifiation file (provided)
188my $mpyfile = "" ; # metapost text picture file (generated)
189my $texfile = "" ; # temporary tex file
190my $pdffile = "" ; # temporary pdf file
191my $tmpfile = "" ; # temporary metapost file
192my $posfile = "" ; # temporary postscript file
193my $logfile = "" ; # temporary log file
194my $errfile = "" ; # final log file (with suffix log)
195
196sub show_help_info
197 { banner ;
198 report ("--help : this message" ) ;
199 report ("--noclean : don't remove temporary files" ) ;
200 report ("--force : force processing (ignore checksum)" ) ;
201 report ("--silent : don't show messages" ) ;
202 print "\n" ;
203 report ("--pdftops : use pdftops (xpdf) pdf->ps") ;
204 report ("--ghostscript : use ghostscript (gs) for pdf->ps") ;
205 print "\n" ;
206 report ("input file : metapost file with graphics") ;
207 report ("programs needed : texexec and english context") ;
208 report (" : pdftops from the xpdf suite, or") ; # page size buggy
209 report (" : pdf2ps and ghostscript, and") ;
210 report (" : pstoedit and ghostscript") ;
211 report ("output file : metapost file with pictures") ;
212 exit }
213
214sub check_input_file
215 { my $file = $ARGV[0] ;
216 if ((!defined($file))||($file eq ""))
217 { banner ; error("no filename given") }
218 else
219 { $file =~ s/\.mp.*$//o ;
220 $metfile = "$file.mp" ;
221 $mpofile = "$file.mpo" ;
222 $mpyfile = "$file.mpy" ;
223 $logfile = "$file.log" ;
224 $texfile = "mpy-$file.tex" ;
225 $pdffile = "mpy-$file.pdf" ;
226 $posfile = "mpy-$file.pos" ;
227 $tmpfile = "mpy-$file.tmp" ;
228 $errfile = "mpy-$file.log" ;
229 if (! -f $metfile)
230 { banner ; error("$metfile is empty") }
231 elsif (-s $mpofile < 32)
232 { unlink $mpofile ; # may exist with zero length
233 unlink $mpyfile ; # get rid of left overs
234 exit }
235 else
236 { banner ; report("processing file : $mpofile") } } }
237
238sub verify_check_sum # checksum calculation from perl documentation
239 { return unless (open (MPO,"$mpofile")) ;
240 $mpochecksum = do { local $/ ; unpack("%32C*",) % 65535 } ;
241 close (MPO) ;
242 return unless open (MPY,"$mpyfile") ;
243 my $str = ; chomp $str ;
244 close (MPY) ;
245 if ($str =~ /^\%\s*mpochecksum\s*\:\s*(\d+)/o)
246 { if ($mpochecksum eq $1)
247 { report("mpo checksum : $mpochecksum / unchanged") ;
248 exit unless $force }
249 else
250 { report("mpo checksum : $mpochecksum / changed") } } }
251
252sub cleanup_files
253 { my @files = ;
254 foreach (@files) { unless (/\.log/o) { unlink $_ } } }
255
256sub construct_tex_file
257 { my $n = 0 ;
258 unless (open (MPO, "<$mpofile"))
259 { error("unable to open $mpofile") }
260 unless (open (TEX, ">$texfile"))
261 { error("unable to open $texfile") }
262 my $textext = "" ;
263 while ()
264 { s/\s*$//mois ;
265 if (/\%\s*format=(\w+)/)
266 { $format = $1 }
267 else # if (!/^\%/)
268 { if (/startTEXpage/o)
269 { ++$n ;
270 $textext .= "$start{$format}\n" ;
271 $start{$format} = "" }
272 $textext .= "$_\n" } }
273 unless (defined($tex{$format})) { $format = "plain" }
274 if ($format eq "context") { $macros = "" }
275 # print TEX "$start{$format}\n$macros\n$textext\n$stop{$format}\n" ;
276 print TEX "$start{$format}\n\n" if $start{$format} ;
277 print TEX "$macros\n" if $macros ;
278 print TEX "$textext\n" if $textext ;
279 print TEX "$stop{$format}\n" if $stop{$format} ;
280 close (MPO) ;
281 close (TEX) ;
282 report("tex format : $format") ;
283 report("requested texts : $n") }
284
285sub construct_mpy_file
286 { unless (open (TMP, "<$tmpfile"))
287 { error("unable to open $tmpfile file") }
288 unless (open (MPY, ">$mpyfile"))
289 { error("unable to open $mpyfile file") }
290 print MPY "% mpochecksum : $mpochecksum\n" ;
291 my $copying = my $n = 0 ;
292 while () # a simple sub is faster
293 { if (s/beginfig/begingraphictextfig/o)
294 { print MPY $_ ; $copying = 1 ; ++$n }
295 elsif (s/endfig/endgraphictextfig/o)
296 { print MPY $_ ; $copying = 0 }
297 elsif ($copying)
298 { print MPY $_ } }
299 close (TMP) ;
300 close (MPY) ;
301 report("processed texts : $n") ;
302 report("produced file : $mpyfile") }
303
304sub run
305 { my ($resultfile, $program,$arguments) = @_ ;
306 my $result = system("$program $arguments $logredirection $logfile") ;
307 unless (-f $resultfile) { error("invalid `$program' run") } }
308
309sub make_pdf_pages
310 { process ("pdf file") ;
311 run ($pdffile, "$tex{$format}", "$texfile") }
312
313sub make_mp_figures
314 { process ("postscript file") ;
315 if ($pmethod) { run($posfile, "$pdftops",
316 "-paper match $pdffile $posfile") }
317 if ($gmethod) { run($posfile, "$ghostscript",
318 "-q -sOutputFile=$posfile -dNOPAUSE -dBATCH -dSAFER -sDEVICE=pswrite $pdffile") }
319 if ($amethod) { run($posfile, "$acroread",
320 "-toPostScript -pairs $pdffile $posfile") } }
321
322sub make_mp_pictures_ps
323 { process ("metapost file") ;
324 run ($tmpfile, "$pstoedit", "-ssp -dt -f mpost $posfile $tmpfile") }
325
326sub make_mp_pictures_pdf
327 { process ("metapost file") ;
328 run ($tmpfile, "$pstoedit", "-ssp -dt -f mpost $pdffile $tmpfile") }
329
330if ($help) { show_help_info }
331
332check_input_file ;
333verify_check_sum ;
334cleanup_files ;
335construct_tex_file ;
336make_pdf_pages ;
337if (1)
338 { make_mp_pictures_pdf ; }
339else
340 { make_mp_figures ;
341 make_mp_pictures_ps ; }
342construct_mpy_file ; # less save : rename $tmpfile, $mpyfile ;
343unless ($noclean) { cleanup_files }
344
345# a simple test file (needs context)
346#
347# % output=pdftex
348#
349# \starttext
350#
351# \startMPpage
352# graphictext
353# "\bf MAKE"
354# scaled 8
355# zscaled (1,2)
356# withdrawcolor \MPcolor{blue}
357# withfillcolor \MPcolor{gray}
358# withpen pencircle scaled 5pt ;
359# \stopMPpage
360#
361# \stoptext
362