]> git.donarmstrong.com Git - lilypond.git/blob - scripts/ly2dvi.py
5ac6d69667a601007bb24da29345591c73fe3f6c
[lilypond.git] / scripts / ly2dvi.py
1 #!@PYTHON@
2 # Run lilypond, latex, dvips.
3 #
4 # This is the third incarnation of ly2dvi.
5 #
6 # Earlier incarnations of ly2dvi were written by
7 # Jeffrey B. Reed<daboys@austin.rr.com> (Python version)
8 # Jan Arne Fagertun <Jan.A.Fagertun@@energy.sintef.no> (Bourne shell script)
9 #
10
11
12
13 # TODO: should allow to set a central pk cache directory from the command line.
14 # TODO: should allow to switch off pk cache.
15 #
16
17
18 # Note: gettext work best if we use ' for docstrings and "
19 #       for gettextable strings.
20 #       --> DO NOT USE """ for docstrings.
21
22 '''
23 TODO:
24
25   * figure out which set of command line options should make ly2dvi:
26
27       na: create tex only?  
28       na: create latex only? 
29       na: create tex and latex
30       default: create dvi only
31       na: create tex, latex and dvi
32       -P: create dvi and ps
33       na: * create ps only
34
35      etc.
36
37      for foo.ly, rename ly2dvi.dir to out-ly2dvi, foo.ly2dvi, foo.dir ?
38      
39   * move versatile taglines, 
40   
41      \header {
42         beginfooter=\mutopiaPD
43         endfooter=\tagline  -> 'lily was here <version>'
44      }
45
46      lilytagline (->lily was here), usertagline, copyright etc.
47
48   * head/header tagline/endfooter
49
50   * dvi from lilypond .tex output?  This is hairy, because we create dvi
51     from lilypond .tex *and* header output.
52
53   * multiple \score blocks?
54   
55 '''
56
57
58 import os
59 import stat
60 import string
61 import re
62 import getopt
63 import sys
64 import shutil
65 import __main__
66 import operator
67 import tempfile
68
69 datadir = '@datadir@'
70 sys.path.append (datadir + '/python')
71 try:
72         import gettext
73         gettext.bindtextdomain ('lilypond', '@localedir@')
74         gettext.textdomain('lilypond')
75         _ = gettext.gettext
76 except:
77         def _ (s):
78                 return s
79
80
81 layout_fields = ['dedication', 'title', 'subtitle', 'subsubtitle',
82           'footer', 'head', 'composer', 'arranger', 'instrument',
83           'opus', 'piece', 'metre', 'meter', 'poet', 'texttranslator']
84
85
86 # init to empty; values here take precedence over values in the file
87
88 ## TODO: change name.
89 extra_init = {
90         'language' : [],
91         'latexheaders' : [],
92         'latexpackages' :  ['geometry'],
93         'latexoptions' : [],
94         'papersize' : [],
95         'pagenumber' : [1],
96         'textheight' : [], 
97         'linewidth' : [],
98         'orientation' : []
99 }
100
101 extra_fields = extra_init.keys ()
102
103 fields = layout_fields + extra_fields
104 program_name = 'ly2dvi'
105 help_summary = _ ("Generate .dvi with LaTeX for LilyPond")
106
107 include_path = ['.']
108 lily_p = 1
109 paper_p = 1
110 cache_pks_p = 1
111
112 PK_PATTERN='feta.*\.[0-9]+pk'
113
114 output_name = ''
115 targets = {
116         'DVI' : 0,
117         'LATEX' : 0,
118         'MIDI' : 0,
119         'TEX' : 0,
120         }
121
122 track_dependencies_p = 0
123 dependency_files = []
124
125
126 # lily_py.py -- options and stuff
127
128 # source file of the GNU LilyPond music typesetter
129
130 # BEGIN Library for these?
131 # cut-n-paste from ly2dvi
132
133 program_version = '@TOPLEVEL_VERSION@'
134 if program_version == '@' + 'TOPLEVEL_VERSION' + '@':
135         program_version = '1.3.148'
136
137
138 original_dir = os.getcwd ()
139 temp_dir = os.path.join (original_dir,  '%s.dir' % program_name)
140
141 keep_temp_dir_p = 0
142 verbose_p = 0
143
144 #
145 # Try to cater for bad installations of LilyPond, that have
146 # broken TeX setup.  Just hope this doesn't hurt good TeX
147 # setups.  Maybe we should check if kpsewhich can find
148 # feta16.{afm,mf,tex,tfm}, and only set env upon failure.
149 #
150 environment = {
151         'MFINPUTS' : datadir + '/mf' + ':',
152         'TEXINPUTS': datadir + '/tex:' + datadir + '/ps' + ':',
153         'TFMFONTS' : datadir + '/tfm' + ':',
154         'GS_FONTPATH' : datadir + '/afm:' + datadir + '/pfa',
155         'GS_LIB' : datadir + '/ps',
156 }
157
158 def setup_environment ():
159         for key in environment.keys ():
160                 val = environment[key]
161                 if os.environ.has_key (key):
162                         val = os.environ[key] + os.pathsep + val 
163                 os.environ[key] = val
164
165 def identify ():
166         sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
167
168 def warranty ():
169         identify ()
170         sys.stdout.write ('\n')
171         sys.stdout.write (_ ('Copyright (c) %s by' % ' 2001'))
172         sys.stdout.write ('\n')
173         sys.stdout.write ('  Han-Wen Nienhuys')
174         sys.stdout.write ('  Jan Nieuwenhuizen')
175         sys.stdout.write ('\n')
176         sys.stdout.write (_ (r'''
177 Distributed under terms of the GNU General Public License. It comes with
178 NO WARRANTY.'''))
179         sys.stdout.write ('\n')
180
181 if ( os.name == 'posix' ):
182         errorport=sys.stderr
183 else:
184         errorport=sys.stdout
185
186 def progress (s):
187         errorport.write (s + '\n')
188
189 def warning (s):
190         progress (_ ("warning: ") + s)
191                 
192 def error (s):
193
194
195         '''Report the error S.  Exit by raising an exception. Please
196         do not abuse by trying to catch this error. If you do not want
197         a stack trace, write to the output directly.
198
199         RETURN VALUE
200
201         None
202         
203         '''
204         
205         progress (_ ("error: ") + s)
206         raise _ ("Exiting ... ")
207
208 def getopt_args (opts):
209         '''Construct arguments (LONG, SHORT) for getopt from  list of options.'''
210         short = ''
211         long = []
212         for o in opts:
213                 if o[1]:
214                         short = short + o[1]
215                         if o[0]:
216                                 short = short + ':'
217                 if o[2]:
218                         l = o[2]
219                         if o[0]:
220                                 l = l + '='
221                         long.append (l)
222         return (short, long)
223
224 def option_help_str (o):
225         '''Transform one option description (4-tuple ) into neatly formatted string'''
226         sh = '  '       
227         if o[1]:
228                 sh = '-%s' % o[1]
229
230         sep = ' '
231         if o[1] and o[2]:
232                 sep = ','
233                 
234         long = ''
235         if o[2]:
236                 long= '--%s' % o[2]
237
238         arg = ''
239         if o[0]:
240                 if o[2]:
241                         arg = '='
242                 arg = arg + o[0]
243         return '  ' + sh + sep + long + arg
244
245
246 def options_help_str (opts):
247         '''Convert a list of options into a neatly formatted string'''
248         w = 0
249         strs =[]
250         helps = []
251
252         for o in opts:
253                 s = option_help_str (o)
254                 strs.append ((s, o[3]))
255                 if len (s) > w:
256                         w = len (s)
257
258         str = ''
259         for s in strs:
260                 str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0])  + 3), s[1])
261         return str
262
263 def help ():
264         ls = [(_ ("Usage: %s [OPTION]... FILE") % program_name),
265                 ('\n\n'),
266                 (help_summary),
267                 ('\n\n'),
268                 (_ ("Options:")),
269                 ('\n'),
270                 (options_help_str (option_definitions)),
271                 ('\n\n'),
272                 (_ ("Report bugs to %s") % 'bug-gnu-music@gnu.org'),
273                 ('\n')]
274         map (sys.stdout.write, ls)
275         
276 def setup_temp ():
277         """
278         Create a temporary directory, and return its name. 
279         """
280         global temp_dir
281         if not keep_temp_dir_p:
282                 temp_dir = tempfile.mktemp (program_name)
283         try:
284                 os.mkdir (temp_dir, 0777)
285         except OSError:
286                 pass
287
288         return temp_dir
289
290
291 def system (cmd, ignore_error = 0):
292         """Run CMD. If IGNORE_ERROR is set, don't complain when CMD returns non zero.
293
294         RETURN VALUE
295
296         Exit status of CMD
297         """
298         
299         if ( os.name != 'posix' ):
300                 cmd = re.sub (r'''\\''', r'''\\\\\\''', cmd)
301                 cmd = "sh -c \'%s\'" % cmd
302
303                 
304         if verbose_p:
305                 progress (_ ("Invoking `%s\'") % cmd)
306         st = os.system (cmd)
307         if st:
308                 name = re.match ('[ \t]*([^ \t]*)', cmd).group (1)
309                 msg = name + ': ' + _ ("command exited with value %d") % st
310                 if ignore_error:
311                         warning (msg + ' ' + _ ("(ignored)") + ' ')
312                 else:
313                         error (msg)
314
315         return st
316
317
318 def cleanup_temp ():
319         if not keep_temp_dir_p:
320                 if verbose_p:
321                         progress (_ ("Cleaning %s...") % temp_dir)
322                 shutil.rmtree (temp_dir)
323
324
325 #what a name.
326 def set_setting (dict, key, val):
327         try:
328                 val = string.atof (val)
329         except ValueError:
330                 #warning (_ ("invalid value: %s") % `val`)
331                 pass
332
333         try:
334                 dict[key].append (val)
335         except KeyError:
336                 warning (_ ("no such setting: %s") % `key`)
337                 dict[key] = [val]
338
339
340 def strip_extension (f, ext):
341         (p, e) = os.path.splitext (f)
342         if e == ext:
343                 e = ''
344         return p + e
345
346 # END Library
347
348 option_definitions = [
349         ('', 'd', 'dependencies', _ ("write Makefile dependencies for every input file")),
350         ('', 'h', 'help', _ ("this help")),
351         (_ ("DIR"), 'I', 'include', _ ("add DIR to LilyPond's search path")),
352         ('', 'k', 'keep', _ ("keep all output, and name the directory %s.dir") % program_name),
353         ('', '', 'no-lily', _ ("don't run LilyPond")),
354         ('', 'm', 'no-paper', _ ("produce MIDI output only")),
355         (_ ("FILE"), 'o', 'output', _ ("write ouput to FILE")),
356         # why capital P?
357         ('', 'P', 'postscript', _ ("generate PostScript output")),
358         (_ ("KEY=VAL"), 's', 'set', _ ("change global setting KEY to VAL")),
359         ('', 'V', 'verbose', _ ("verbose")),
360         ('', 'v', 'version', _ ("print version number")),
361         ('', 'w', 'warranty', _ ("show warranty and copyright")),
362         ]
363
364 def run_lilypond (files, outbase, dep_prefix):
365         opts = ''
366 #       opts = opts + '--output=%s.tex' % outbase
367         opts = opts + ' ' + string.join (map (lambda x : '-I ' + x,
368                                               include_path))
369         if paper_p:
370                 opts = opts + ' ' + string.join (map (lambda x : '-H ' + x,
371                                                       fields))
372         else:
373                 opts = opts + ' --no-paper'
374                 
375         if track_dependencies_p:
376                 opts = opts + " --dependencies"
377                 if dep_prefix:
378                         opts = opts + ' --dep-prefix=%s' % dep_prefix
379
380         fs = string.join (files)
381
382         if not verbose_p:
383                 progress ( _("Running %s...") % 'LilyPond')
384                 # cmd = cmd + ' 1> /dev/null 2> /dev/null'
385         else:
386                 opts = opts + ' --verbose'
387         
388         system ('lilypond %s %s ' % (opts, fs))
389
390 def analyse_lilypond_output (filename, extra):
391         
392         # urg
393         '''Grep FILENAME for interesting stuff, and
394         put relevant info into EXTRA.'''
395         filename = filename+'.tex'
396         progress (_ ("Analyzing %s...") % filename)
397         s = open (filename).read ()
398
399         # search only the first 10k
400         s = s[:10240]
401         for x in ('textheight', 'linewidth', 'papersize', 'orientation'):
402                 m = re.search (r'\\def\\lilypondpaper%s{([^}]*)}'%x, s)
403                 if m:
404                         set_setting (extra, x, m.group (1))
405
406 def find_tex_files_for_base (base, extra):
407
408         """
409         Find the \header fields dumped from BASE.
410         """
411         
412         headerfiles = {}
413         for f in layout_fields:
414                 if os.path.exists (base + '.' + f):
415                         headerfiles[f] = base+'.'+f
416
417         if os.path.exists (base  +'.dep'):
418                 dependency_files.append (base + '.dep')
419
420         for f in extra_fields:
421                 if os.path.exists (base + '.' + f):
422                         extra[f].append (open (base + '.' + f).read ())
423         
424         return (base  +'.tex',headerfiles)
425          
426
427 def find_tex_files (files, extra):
428         """
429         Find all .tex files whose prefixes start with some name in FILES. 
430
431         """
432         
433         tfiles = []
434         
435         for f in files:
436                 x = 0
437                 while 1:
438                         fname = os.path.basename (f)
439                         fname = strip_extension (fname, '.ly')
440                         if x:
441                                 fname = fname + '-%d' % x
442
443                         if os.path.exists (fname + '.tex'):
444                                 tfiles.append (find_tex_files_for_base (fname, extra))
445                                 analyse_lilypond_output (fname, extra)
446                         else:
447                                 break
448
449                         x = x + 1
450         if not x:
451                 fstr = string.join (files, ', ')
452                 warning (_ ("no lilypond output found for %s") % fstr)
453         return tfiles
454
455 def one_latex_definition (defn, first):
456         s = '\n'
457         for (k,v) in defn[1].items ():
458                 val = open (v).read ()
459                 if (string.strip (val)):
460                         s = s + r'''\def\lilypond%s{%s}''' % (k, val)
461                 else:
462                         s = s + r'''\let\lilypond%s\relax''' % k
463                 s = s + '\n'
464
465         if first:
466                 s = s + '\\def\\mustmakelilypondtitle{}\n'
467         else:
468                 s = s + '\\def\\mustmakelilypondpiecetitle{}\n'
469                 
470         s = s + '\\input %s\n' % defn[0] # The final \n seems important here. It ensures that the footers and taglines end up on the right page.
471         return s
472
473
474 ly_paper_to_latexpaper =  {
475         'a4' : 'a4paper',
476         'letter' : 'letterpaper', 
477 }
478
479 def global_latex_definition (tfiles, extra):
480
481         '''construct preamble from EXTRA, dump Latex stuff for each
482 lily output file in TFILES after that, and return the Latex file constructed.  '''
483
484
485         s = ""
486         s = s + '% generation tag\n'
487
488         options = ''
489
490         if extra['papersize']:
491                 try:
492                         options = '%s' % ly_paper_to_latexpaper[extra['papersize'][0]]
493                 except KeyError:
494                         warning (_ ("invalid value: %s") % `extra['papersize'][0]`)
495                         pass
496
497         if extra['latexoptions']:
498                 options = options + ',' + extra['latexoptions'][-1]
499
500         s = s + '\\documentclass[%s]{article}\n' % options
501
502         if extra['language']:
503                 s = s + r'\usepackage[%s]{babel}\n' % extra['language'][-1]
504
505
506         s = s + '\\usepackage{%s}\n' \
507                 % string.join (extra['latexpackages'], ',')
508
509         if extra['latexheaders']:
510                 s = s + '\\include{%s}\n' \
511                         % string.join (extra['latexheaders'], '}\n\\include{')
512
513         textheight = ''
514         if extra['textheight']:
515                 textheight = ',textheight=%fpt' % extra['textheight'][0]
516
517         orientation = 'portrait'
518         if extra['orientation']:
519                 orientation = extra['orientation'][0]
520
521         # set sane geometry width (a4-width) for linewidth = -1.
522         maxlw = max (extra['linewidth'] + [-1])
523         if maxlw < 0:
524                 # who the hell is 597 ?
525                 linewidth = '597'
526         else:
527                 linewidth = maxlw
528         s = s + '\geometry{width=%spt%s,headheight=2mm,footskip=2mm,%s}\n' % (linewidth, textheight, orientation)
529
530         if extra['latexoptions']:
531                 s = s + '\geometry{twosideshift=4mm}\n'
532
533         s = s + r'''
534 \usepackage[latin1]{inputenc}
535 \input{titledefs}
536 '''
537         
538         if extra['pagenumber'] and extra['pagenumber'][-1] and extra['pagenumber'][-1] != 'no':
539                 s = s + '\\pagestyle{plain}\n'
540         else:
541                 s = s + '\\pagestyle{empty}\n'
542
543         s = s + '\\begin{document}\n'
544         s = s + '\\thispagestyle{firstpage}\n'
545
546         first = 1
547         for t in tfiles:
548                 s = s + one_latex_definition (t, first)
549                 first = 0
550
551
552         s = s + '\\thispagestyle{lastpage}\n'
553         s = s + '\\end{document}'
554
555         return s
556
557 def run_latex (files, outbase, extra):
558
559         """Construct latex file, for FILES and EXTRA, dump it into
560 OUTBASE.latex. Run LaTeX on it.
561
562 RETURN VALUE
563
564 None
565         """
566         latex_fn = outbase + '.latex'
567         
568         wfs = find_tex_files (files, extra)
569         s = global_latex_definition (wfs, extra)
570
571         f = open (latex_fn, 'w')
572         f.write (s)
573         f.close ()
574
575         cmd = 'latex \\\\nonstopmode \\\\input %s' % latex_fn
576
577         if not verbose_p and os.name == 'posix':
578                 progress ( _("Running %s...") % 'LaTeX')
579                 cmd = cmd + ' 1> /dev/null 2> /dev/null'
580
581         system (cmd)
582
583 def run_dvips (outbase, extra):
584
585
586         """Run dvips using the correct options taken from EXTRA,
587 leaving a PS file in OUTBASE.ps
588
589 RETURN VALUE
590
591 None.
592 """
593         opts = ''
594         if extra['papersize']:
595                 opts = opts + ' -t%s' % extra['papersize'][0]
596
597         if extra['orientation'] and extra['orientation'][0] == 'landscape':
598                 opts = opts + ' -tlandscape'
599
600         cmd = 'dvips %s -o%s %s' % (opts, outbase + '.ps', outbase + '.dvi')
601         
602         if not verbose_p and os.name == 'posix':
603                 progress ( _("Running %s...") % 'dvips')
604                 cmd = cmd + ' 1> /dev/null 2> /dev/null'
605                 
606         system (cmd)
607
608 def generate_dependency_file (depfile, outname):
609         df = open (depfile, 'w')
610         df.write (outname + ':' )
611         
612         for d in dependency_files:
613                 s = open (d).read ()
614                 s = re.sub ('#[^\n]*\n', '', s)
615                 s = re.sub (r'\\\n', ' ', s)
616                 m = re.search ('.*:(.*)\n', s)
617
618                 # ugh. Different targets?
619                 if m:
620                         df.write ( m.group (1)  + ' ' )
621
622         df.write ('\n')
623         df.close ();
624
625 (sh, long) = getopt_args (__main__.option_definitions)
626 try:
627         (options, files) = getopt.getopt(sys.argv[1:], sh, long)
628 except getopt.error, s: 
629         errorport.write ("\nerror: getopt says `%s\'\n\n" % s)
630         help ()
631         sys.exit (2)
632         
633 for opt in options:     
634         o = opt[0]
635         a = opt[1]
636
637         if 0:
638                 pass
639         elif o == '--help' or o == '-h':
640                 help ()
641                 sys.exit (0)
642         elif o == '--include' or o == '-I':
643                 include_path.append (a)
644         elif o == '--postscript' or o == '-P':
645                 targets['PS'] = 0
646         elif o == '--keep' or o == '-k':
647                 keep_temp_dir_p = 1
648         elif o == '--no-lily':
649                 lily_p = 0
650         elif o == '--no-paper' or o == '-m':
651                 targets = {}
652                 targets['MIDI'] = 0
653                 paper_p = 0
654         elif o == '--output' or o == '-o':
655                 output_name = a
656         elif o == '--set' or o == '-s':
657                 ss = string.split (a, '=')
658                 set_setting (extra_init, ss[0], ss[1])
659         elif o == '--dependencies' or o == '-d':
660                 track_dependencies_p = 1
661         elif o == '--verbose' or o == '-V':
662                 verbose_p = 1
663         elif o == '--version' or o == '-v':
664                 identify ()
665                 sys.exit (0)
666         elif o == '--warranty' or o == '-w':
667                 status = system ('lilypond -w', ignore_error = 1)
668                 if status:
669                         warranty ()
670
671                 sys.exit (0)
672
673
674 def cp_to_dir (pattern, dir):
675         "Copy files matching re PATTERN from cwd to DIR"
676         # Duh.  Python style portable: cp *.EXT OUTDIR
677         # system ('cp *.%s %s' % (ext, outdir), 1)
678         files = filter (lambda x, p=pattern: re.match (p, x), os.listdir ('.'))
679         map (lambda x, d=dir: shutil.copy2 (x, os.path.join (d, x)), files)
680
681 # Python < 1.5.2 compatibility
682 #
683 # On most platforms, this is equivalent to
684 #`normpath(join(os.getcwd()), PATH)'.  *Added in Python version 1.5.2*
685 if os.path.__dict__.has_key ('abspath'):
686         abspath = os.path.abspath
687 else:
688         def abspath (path):
689                 return os.path.normpath (os.path.join (os.getcwd (), path))
690
691 if os.__dict__.has_key ('makedirs'):
692         makedirs = os.makedirs
693 else:
694         def makedirs (dir, mode=0777):
695                 system ('mkdir -p %s' % dir)
696
697 def mkdir_p (dir, mode=0777):
698         if not os.path.isdir (dir):
699                 makedirs (dir, mode)
700
701 include_path = map (abspath, include_path)
702
703 original_output = output_name
704
705 if files and files[0] != '-':
706
707         files = map (lambda x: strip_extension (x, '.ly'), files)
708
709         (outdir, outbase) = ('','')
710         if not output_name:
711                 outbase = os.path.basename (files[0])
712                 outdir = abspath('.')
713         elif output_name[-1] == os.sep:
714                 outdir = abspath (output_name)
715                 outbase = os.path.basename (files[0])
716         else:
717                 (outdir, outbase) = os.path.split (abspath (output_name))
718
719         for i in ('.dvi', '.latex', '.ly', '.ps', '.tex'):
720                 output_name = strip_extension (output_name, i)
721
722         files = map (abspath, files) 
723
724         if os.path.dirname (output_name) != '.':
725                 dep_prefix = os.path.dirname (output_name)
726         else:
727                 dep_prefix = 0
728
729         reldir = os.path.dirname (output_name)
730         if outdir != '.' and (track_dependencies_p or targets.keys ()):
731                 mkdir_p (outdir, 0777)
732
733         setup_environment ()
734         tmpdir = setup_temp ()
735         if cache_pks_p :
736                 os.chdir (outdir)
737                 cp_to_dir (PK_PATTERN, tmpdir)
738
739         os.chdir (tmpdir)
740         
741         extra = extra_init
742         
743         if lily_p:
744 ##              try:
745                         run_lilypond (files, outbase, dep_prefix)
746 ## #            except:
747 ##                      # TODO: friendly message about LilyPond setup/failing?
748 ##                      #
749 ##                      # TODO: lilypond should fail with different
750 ##                      # error codes for:
751 ##                      #   - guile setup/startup failure
752 ##                      #   - font setup failure
753 ##                      #   - init.ly setup failure
754 ##                      #   - parse error in .ly
755 ##                      #   - unexpected: assert/core dump
756 ## #                    targets = {}
757
758         if targets.has_key ('DVI') or targets.has_key ('PS'):
759 #               try:
760                         run_latex (files, outbase, extra)
761                         # unless: add --tex, or --latex?
762                         del targets['TEX']
763                         del targets['LATEX']
764 #               except Foobar:
765 #                       # TODO: friendly message about TeX/LaTeX setup,
766 #                       # trying to run tex/latex by hand
767 #                       if targets.has_key ('DVI'):
768 #                               del targets['DVI']
769 #                       if targets.has_key ('PS'):
770 #                               del targets['PS']
771
772         # TODO: does dvips ever fail?
773         if targets.has_key ('PS'):
774                 run_dvips (outbase, extra)
775
776         # add DEP to targets?
777         if track_dependencies_p:
778                 depfile = os.path.join (outdir, outbase + '.dep')
779                 generate_dependency_file (depfile, depfile)
780                 if os.path.isfile (depfile):
781                         progress (_ ("dependencies output to `%s'...") % depfile)
782
783         for i in targets.keys ():
784                 ext = string.lower (i)
785                 cp_to_dir ('.*\.%s$' % ext, outdir)
786                 outname = outbase + '.' + string.lower (i)
787                 abs = os.path.join (outdir, outname)
788                 if reldir != '.':
789                         outname = os.path.join (reldir, outname)
790                 if os.path.isfile (abs):
791                         progress (_ ("%s output to `%s'...") % (i, outname))
792                 elif verbose_p:
793                         warning (_ ("can't find file: `%s'") % outname)
794                         
795                 if cache_pks_p:
796                         cp_to_dir (PK_PATTERN, outdir)
797                 
798         os.chdir (original_dir)
799         cleanup_temp ()
800         
801 else:
802         # FIXME
803         help ()
804         errorport.write ("ly2dvi: " + _ ("error: ") + _ ("no files specified on command line.") + '\n')
805         sys.exit (2)
806
807
808