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