]> git.donarmstrong.com Git - lilypond.git/blob - scripts/ly2dvi.py
ab5ce0f5bf919011d6480b2a69311404a096ff28
[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)
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=0pt,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 % the \mbox{} helps latex if people do stupid things in tagline
548 \makeatletter
549 \renewcommand{\@oddfoot}{\parbox{\textwidth}{\mbox{}\makelilypondtagline}}%
550 \makeatother
551 '''
552         s = s + '\\end{document}'
553
554         return s
555
556 def run_latex (files, outbase, extra):
557
558         """Construct latex file, for FILES and EXTRA, dump it into
559 OUTBASE.latex. Run LaTeX on it.
560
561 RETURN VALUE
562
563 None
564         """
565         latex_fn = outbase + '.latex'
566         
567         wfs = find_tex_files (files, extra)
568         s = global_latex_definition (wfs, extra)
569
570         f = open (latex_fn, 'w')
571         f.write (s)
572         f.close ()
573
574         cmd = 'latex \\\\nonstopmode \\\\input %s' % latex_fn
575
576         if not verbose_p and os.name == 'posix':
577                 progress ( _("Running %s...") % 'LaTeX')
578                 cmd = cmd + ' 1> /dev/null 2> /dev/null'
579
580         system (cmd)
581
582 def run_dvips (outbase, extra):
583
584
585         """Run dvips using the correct options taken from EXTRA,
586 leaving a PS file in OUTBASE.ps
587
588 RETURN VALUE
589
590 None.
591 """
592         opts = ''
593         if extra['papersize']:
594                 opts = opts + ' -t%s' % extra['papersize'][0]
595
596         if extra['orientation'] and extra['orientation'][0] == 'landscape':
597                 opts = opts + ' -tlandscape'
598
599         cmd = 'dvips %s -o%s %s' % (opts, outbase + '.ps', outbase + '.dvi')
600         
601         if not verbose_p and os.name == 'posix':
602                 progress ( _("Running %s...") % 'dvips')
603                 cmd = cmd + ' 1> /dev/null 2> /dev/null'
604                 
605         system (cmd)
606
607 def generate_dependency_file (depfile, outname):
608         df = open (depfile, 'w')
609         df.write (outname + ':' )
610         
611         for d in dependency_files:
612                 s = open (d).read ()
613                 s = re.sub ('#[^\n]*\n', '', s)
614                 s = re.sub (r'\\\n', ' ', s)
615                 m = re.search ('.*:(.*)\n', s)
616
617                 # ugh. Different targets?
618                 if m:
619                         df.write ( m.group (1)  + ' ' )
620
621         df.write ('\n')
622         df.close ();
623
624 (sh, long) = getopt_args (__main__.option_definitions)
625 try:
626         (options, files) = getopt.getopt(sys.argv[1:], sh, long)
627 except getopt.error, s: 
628         errorport.write ("\nerror: getopt says `%s\'\n\n" % s)
629         help ()
630         sys.exit (2)
631         
632 for opt in options:     
633         o = opt[0]
634         a = opt[1]
635
636         if 0:
637                 pass
638         elif o == '--help' or o == '-h':
639                 help ()
640                 sys.exit (0)
641         elif o == '--include' or o == '-I':
642                 include_path.append (a)
643         elif o == '--postscript' or o == '-P':
644                 targets['PS'] = 0
645         elif o == '--keep' or o == '-k':
646                 keep_temp_dir_p = 1
647         elif o == '--no-lily':
648                 lily_p = 0
649         elif o == '--no-paper' or o == '-m':
650                 targets = {}
651                 targets['MIDI'] = 0
652                 paper_p = 0
653         elif o == '--output' or o == '-o':
654                 output_name = a
655         elif o == '--set' or o == '-s':
656                 ss = string.split (a, '=')
657                 set_setting (extra_init, ss[0], ss[1])
658         elif o == '--dependencies' or o == '-d':
659                 track_dependencies_p = 1
660         elif o == '--verbose' or o == '-V':
661                 verbose_p = 1
662         elif o == '--version' or o == '-v':
663                 identify ()
664                 sys.exit (0)
665         elif o == '--warranty' or o == '-w':
666                 status = system ('lilypond -w', ignore_error = 1)
667                 if status:
668                         warranty ()
669
670                 sys.exit (0)
671
672
673 def cp_to_dir (pattern, dir):
674         "Copy files matching re PATTERN from cwd to DIR"
675         # Duh.  Python style portable: cp *.EXT OUTDIR
676         # system ('cp *.%s %s' % (ext, outdir), 1)
677         files = filter (lambda x, p=pattern: re.match (p, x), os.listdir ('.'))
678         map (lambda x, d=dir: shutil.copy2 (x, os.path.join (d, x)), files)
679
680 # Python < 1.5.2 compatibility
681 #
682 # On most platforms, this is equivalent to
683 #`normpath(join(os.getcwd()), PATH)'.  *Added in Python version 1.5.2*
684 if os.path.__dict__.has_key ('abspath'):
685         abspath = os.path.abspath
686 else:
687         def abspath (path):
688                 return os.path.normpath (os.path.join (os.getcwd (), path))
689
690 if os.__dict__.has_key ('makedirs'):
691         makedirs = os.makedirs
692 else:
693         def makedirs (dir, mode=0777):
694                 system ('mkdir -p %s' % dir)
695
696 def mkdir_p (dir, mode=0777):
697         if not os.path.isdir (dir):
698                 makedirs (dir, mode)
699
700 include_path = map (abspath, include_path)
701
702 original_output = output_name
703
704 if files and files[0] != '-':
705
706         files = map (lambda x: strip_extension (x, '.ly'), files)
707
708         if not output_name:
709                 output_name = os.path.basename (files[0])
710
711         for i in ('.dvi', '.latex', '.ly', '.ps', '.tex'):
712                 output_name = strip_extension (output_name, i)
713
714         files = map (abspath, files) 
715
716         if os.path.dirname (output_name) != '.':
717                 dep_prefix = os.path.dirname (output_name)
718         else:
719                 dep_prefix = 0
720
721         reldir = os.path.dirname (output_name)
722         (outdir, outbase) = os.path.split (abspath (output_name))
723         
724         setup_environment ()
725         setup_temp ()
726         
727         extra = extra_init
728         
729         if lily_p:
730 ##              try:
731                         run_lilypond (files, outbase, dep_prefix)
732 ## #            except:
733 ##                      # TODO: friendly message about LilyPond setup/failing?
734 ##                      #
735 ##                      # TODO: lilypond should fail with different
736 ##                      # error codes for:
737 ##                      #   - guile setup/startup failure
738 ##                      #   - font setup failure
739 ##                      #   - init.ly setup failure
740 ##                      #   - parse error in .ly
741 ##                      #   - unexpected: assert/core dump
742 ## #                    targets = {}
743
744         if targets.has_key ('DVI') or targets.has_key ('PS'):
745 #               try:
746                         run_latex (files, outbase, extra)
747                         # unless: add --tex, or --latex?
748                         del targets['TEX']
749                         del targets['LATEX']
750 #               except Foobar:
751 #                       # TODO: friendly message about TeX/LaTeX setup,
752 #                       # trying to run tex/latex by hand
753 #                       if targets.has_key ('DVI'):
754 #                               del targets['DVI']
755 #                       if targets.has_key ('PS'):
756 #                               del targets['PS']
757
758         # TODO: does dvips ever fail?
759         if targets.has_key ('PS'):
760                 run_dvips (outbase, extra)
761
762         if outdir != '.' and (track_dependencies_p or targets.keys ()):
763                 mkdir_p (outdir, 0777)
764
765         # add DEP to targets?
766         if track_dependencies_p:
767                 depfile = os.path.join (outdir, outbase + '.dep')
768                 generate_dependency_file (depfile, depfile)
769                 if os.path.isfile (depfile):
770                         progress (_ ("dependencies output to %s...") % depfile)
771
772         for i in targets.keys ():
773                 ext = string.lower (i)
774                 cp_to_dir ('.*\.%s$' % ext, outdir)
775                 outname = outbase + '.' + string.lower (i)
776                 abs = os.path.join (outdir, outname)
777                 if reldir != '.':
778                         outname = os.path.join (reldir, outname)
779                 if os.path.isfile (abs):
780                         progress (_ ("%s output to %s...") % (i, outname))
781                 elif verbose_p:
782                         warning (_ ("can't find file: `%s'") % outname)
783
784         os.chdir (original_dir)
785         cleanup_temp ()
786         
787 else:
788         # FIXME
789         help ()
790         errorport.write ("ly2dvi: error: " + _ ("no files specified on command line.\n"))
791         sys.exit (2)
792
793
794