makempy.pl /size: 10 Kb    last modification: 2020-07-01 14:35
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