]> git.donarmstrong.com Git - lilypond.git/blob - scripts/mup2ly.py
release: 1.3.142
[lilypond.git] / scripts / mup2ly.py
1 #!@PYTHON@
2 # mup2ly.py -- mup input converter
3
4 # source file of the GNU LilyPond music typesetter
5 #
6 # (c) 2001
7
8 '''
9 TODO:
10
11    WIP:lots of stuff
12    
13 '''
14
15 import os
16 import fnmatch
17 import stat
18 import string
19 import re
20 import getopt
21 import sys
22 import __main__
23 import operator
24 import tempfile
25
26
27 sys.path.append ('@datadir@/python')
28 import gettext
29 gettext.bindtextdomain ('lilypond', '@localedir@')
30 gettext.textdomain('lilypond')
31 _ = gettext.gettext
32
33
34 program_name = 'mup2ly'
35 help_summary = _("Convert mup to ly")
36 output = 0
37
38 # lily_py.py -- options and stuff
39
40 # source file of the GNU LilyPond music typesetter
41
42 # BEGIN Library for these?
43 # cut-n-paste from ly2dvi
44
45 program_version = '@TOPLEVEL_VERSION@'
46 if program_version == '@' + 'TOPLEVEL_VERSION' + '@':
47         program_version = '1.3.142'
48
49
50 original_dir = os.getcwd ()
51 temp_dir = '%s.dir' % program_name
52 keep_temp_dir_p = 0
53 verbose_p = 0
54
55 def identify ():
56         sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
57
58 def warranty ():
59         identify ()
60         sys.stdout.write ('\n')
61         sys.stdout.write (_ ('Copyright (c) %s by' % ' 2001'))
62         sys.stdout.write ('\n')
63         sys.stdout.write ('  Han-Wen Nienhuys')
64         sys.stdout.write ('  Jan Nieuwenhuizen')
65         sys.stdout.write ('\n')
66         sys.stdout.write (_ (r'''
67 Distributed under terms of the GNU General Public License. It comes with
68 NO WARRANTY.'''))
69         sys.stdout.write ('\n')
70
71 def progress (s):
72         if s[-1] != '\n':
73                 s = s + '\n'
74         sys.stderr.write (s)
75
76 def warning (s):
77         sys.stderr.write (_ ("warning: ") + s)
78         sys.stderr.write ('\n')
79         
80                 
81 def error (s):
82         sys.stderr.write (_ ("error: ") + s)
83         sys.stderr.write ('\n')
84         raise _ ("Exiting ... ")
85
86 def getopt_args (opts):
87         '''Construct arguments (LONG, SHORT) for getopt from  list of options.'''
88         short = ''
89         long = []
90         for o in opts:
91                 if o[1]:
92                         short = short + o[1]
93                         if o[0]:
94                                 short = short + ':'
95                 if o[2]:
96                         l = o[2]
97                         if o[0]:
98                                 l = l + '='
99                         long.append (l)
100         return (short, long)
101
102 def option_help_str (o):
103         '''Transform one option description (4-tuple ) into neatly formatted string'''
104         sh = '  '       
105         if o[1]:
106                 sh = '-%s' % o[1]
107
108         sep = ' '
109         if o[1] and o[2]:
110                 sep = ','
111                 
112         long = ''
113         if o[2]:
114                 long= '--%s' % o[2]
115
116         arg = ''
117         if o[0]:
118                 if o[2]:
119                         arg = '='
120                 arg = arg + o[0]
121         return '  ' + sh + sep + long + arg
122
123
124 def options_help_str (opts):
125         '''Convert a list of options into a neatly formatted string'''
126         w = 0
127         strs =[]
128         helps = []
129
130         for o in opts:
131                 s = option_help_str (o)
132                 strs.append ((s, o[3]))
133                 if len (s) > w:
134                         w = len (s)
135
136         str = ''
137         for s in strs:
138                 str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0])  + 3), s[1])
139         return str
140
141 def help ():
142         sys.stdout.write (_ ("Usage: %s [OPTION]... FILE") % program_name)
143         sys.stdout.write ('\n\n')
144         sys.stdout.write (help_summary)
145         sys.stdout.write ('\n\n')
146         sys.stdout.write (_ ("Options:"))
147         sys.stdout.write ('\n')
148         sys.stdout.write (options_help_str (option_definitions))
149         sys.stdout.write ('\n\n')
150         sys.stdout.write (_ ("Report bugs to %s") % 'bug-gnu-music@gnu.org')
151         sys.stdout.write ('\n')
152         sys.exit (0)
153
154
155 def setup_temp ():
156         global temp_dir
157         if not keep_temp_dir_p:
158                 temp_dir = tempfile.mktemp (program_name)
159         try:
160                 os.mkdir (temp_dir, 0777)
161         except OSError:
162                 pass
163                 
164         
165 def system (cmd, ignore_error = 0):
166         if verbose_p:
167                 progress (_ ("Invoking `%s\'") % cmd)
168         st = os.system (cmd)
169         if st:
170                 msg =  ( _ ("error: ") + _ ("command exited with value %d") % st)
171                 if ignore_error:
172                         sys.stderr.write (msg + ' ' + _ ("(ignored)") + ' ')
173                 else:
174                         error (msg)
175
176         return st
177
178
179 def cleanup_temp ():
180         if not keep_temp_dir_p:
181                 if verbose_p:
182                         progress (_ ('Cleaning up `%s\'') % temp_dir)
183                 system ('rm -rf %s' % temp_dir)
184
185
186 def set_setting (dict, key, val):
187         try:
188                 val = string.atof (val)
189         except ValueError:
190                 #warning (_ ("invalid value: %s") % `val`)
191                 pass
192
193         try:
194                 dict[key].append (val)
195         except KeyError:
196                 warning (_ ("no such setting: %s") % `key`)
197                 dict[key] = [val]
198
199 # END Library
200
201
202 #
203 # PMX cut and paste
204 #
205
206 def encodeint (i):
207         return chr (i  + ord ('A'))
208
209         
210 actab = {-2: 'eses', -1: 'es', 0 : '', 1: 'is', 2:'isis'}
211
212 def pitch_to_lily_string (tup):
213         (o,n,a) = tup
214
215         nm = chr((n + 2) % 7 + ord ('a'))
216         nm = nm + actab[a]
217         if o > 0:
218                 nm = nm + "'" * o
219         elif o < 0:
220                 nm = nm + "," * -o
221         return nm
222
223 def gcd (a,b):
224         if b == 0:
225                 return a
226         c = a
227         while c: 
228                 c = a % b
229                 a = b
230                 b = c
231         return a
232
233 def rat_simplify (r):
234         (n,d) = r
235         if d < 0:
236                 d = -d
237                 n = -n
238         if n == 0:
239                 return (0,1)
240         else:
241                 g = gcd (n, d)
242                 return (n/g, d/g)
243         
244 def rat_multiply (a,b):
245         (x,y) = a
246         (p,q) = b
247
248         return rat_simplify ((x*p, y*q))
249
250 def rat_divide (a,b):
251         (p,q) = b
252         return rat_multiply (a, (q,p))
253
254 tuplet_table = {
255         2: 3,
256         3: 2,
257         5: 4
258 }
259
260
261 def rat_add (a,b):
262         (x,y) = a
263         (p,q) = b
264
265         return rat_simplify ((x*q + p*y, y*q))
266
267 def rat_neg (a):
268         (p,q) = a
269         return (-p,q)
270
271
272 def rat_larger (a,b):
273         return rat_subtract (a, b )[0] > 0
274
275 def rat_subtract (a,b ):
276         return rat_add (a, rat_neg (b))
277
278 def rat_to_duration (frac):
279         log = 1
280         d = (1,1)
281         while rat_larger (d, frac):
282                 d = rat_multiply (d, (1,2))
283                 log = log << 1
284
285         frac = rat_subtract (frac, d)
286         dots = 0
287         if frac == rat_multiply (d, (1,2)):
288                 dots = 1
289         elif frac == rat_multiply (d, (3,4)):
290                 dots = 2
291         return (log, dots)      
292
293
294 class Barcheck :
295         def __init__ (self):
296                 pass
297         def dump (self):
298                 return '|\n'
299
300
301 class Meter :
302         def __init__ (self,nums):
303                 self.nums = nums
304         def dump (self):
305                 return ' %{ FIXME: meter change %} '
306                 
307 class Beam:
308         def __init__ (self, ch):
309                 self.char = ch
310         def dump (self):
311                 return self.char
312
313 class Slur:
314         def __init__ (self,id):
315                 self.id = id
316                 self.start_chord = None
317                 self.end_chord = None
318         def calculate (self):
319                 s =self.start_chord
320                 e= self.end_chord
321
322                 if e and s:
323                         s.note_suffix = s.note_suffix + '('
324                         e.note_prefix = ')' + e.note_prefix
325                 else:
326                         sys.stderr.write ("\nOrphaned slur")
327                         
328 class Voice:
329         def __init__ (self, n):
330                 self.number = n
331                 self.entries = []
332                 self.chords = []
333                 self.staff = None
334                 self.current_slurs = []
335                 self.slurs = []
336                 
337         def toggle_slur (self, id):
338                 
339                 for s in self.current_slurs:
340                         if s.id == id:
341                                 self.current_slurs.remove (s)
342                                 s.end_chord = self.chords[-1]
343                                 return
344                 s = Slur (id)
345                 s.start_chord = self.chords[-1]
346                 self.current_slurs.append (s)
347                 self.slurs.append (s)
348                 
349         def last_chord (self):
350                 if len (self.chords):
351                         return self.chords[-1]
352                 else:
353                         ch = Chord ()
354                         ch.basic_duration = 4
355                         return ch
356                 
357         def add_chord (self, ch):
358                 self.chords.append (ch)
359                 self.entries.append (ch)
360                 
361         def add_nonchord (self, nch):
362                 self.entries.append (nch)
363
364         def idstring (self):
365                 return 'staff%svoice%s ' % (encodeint (self.staff.number) , encodeint(self.number))
366         
367         def dump (self):
368                 str = ''
369                 if not self.entries:
370                         #return '\n'
371                         #ugh ugh
372                         return '\n%s = {}\n\n' % self.idstring ()
373                 ln = '  '
374                 one_two = ("One", "Two")
375                 if self.staff.voices [1 - self.number].entries:
376                         ln = ln + '\\voice%s\n  ' % one_two[self.number]
377                 for e in self.entries:
378                         next = e.dump ()
379                         if next[-1] == '\n':
380                                 str  = str + ln + next + ' '
381                                 ln = '  '
382                                 continue
383                         
384                         if len (ln) +len (next) > 72:
385                                 str = str+ ln + '\n'
386                                 ln = '  '
387                         ln = ln + next + ' '
388                         
389                         
390                 str = str  + ln
391                 id = self.idstring ()
392                         
393                 str = '''%s = \\notes {
394 %s
395 }
396
397 '''% (id, str)
398                 return str
399         
400         def calculate_graces (self):
401                 lastgr = 0
402                 lastc = None
403                 for c in self.chords:
404                         if c.grace and  not lastgr:
405                                 c.chord_prefix = c.chord_prefix + '\\grace { '
406                         elif not c.grace and lastgr:
407                                 lastc.chord_suffix = lastc.chord_suffix + ' } '
408                         lastgr = c.grace
409                         lastc = c
410                         
411         def calculate (self):
412                 self.calculate_graces ()
413                 for s in self.slurs:
414                         s.calculate ()
415
416 class Clef:
417         def __init__ (self, cl):
418                 self.type = cl
419         def dump(self):
420                 return '\\clef %s;' % self.type
421
422 clef_table = {
423         'b':'bass'  ,
424         'r':'baritone',
425         'n':'tenor',
426         'a':'alto',
427         'm':'mezzosoprano',
428         's':'soprano',
429         't':'treble',
430         'f':'frenchviolin',
431         }
432
433 class Staff:
434         def __init__ (self, n):
435                 # ugh
436                 self.voices = (Voice (0), Voice (1))
437                 
438                 # self.voice_idx = 0
439                 self.clef = None
440                 self.instrument = 0
441                 self.number = n
442                 
443                 i = 0
444                 for v in self.voices:
445                         v.staff = self
446                         v.number = i
447                         i = i+1
448                         
449         def set_clef (self, letter):
450                 clstr = clef_table[letter]
451                 self.voices[0].add_nonchord (Clef (clstr))
452                 
453         #def current_voice (self):
454         #       return self.voices[self.voice_idx]
455         #
456         #def next_voice (self):
457         #       self.voice_idx = (self.voice_idx + 1)%len (self.voices)
458
459         def calculate (self):
460                 for v in self.voices:
461                         v.calculate ()
462                         
463         def idstring (self):
464                 return 'staff%s' % encodeint (self.number)
465         
466         def dump (self):
467                 str = ''
468
469                 refs = ''
470                 for v in self.voices:
471                         str = str + v.dump()
472                         refs = refs + '\n  \\' + v.idstring ()
473                 
474                 str = str + '''
475 %s = \context Staff = %s <%s
476 >
477
478 ''' % (self.idstring (), self.idstring (), refs)
479                 return str
480
481 class Tuplet:
482         def __init__ (self, number, base, dots):
483                 self.chords = []
484                 self.number = number
485                 self.replaces = tuplet_table[number]
486                 self.base = base
487                 self.dots = dots
488                 
489                 length = (1,base)
490                 if dots == 1:
491                         length = rat_multiply (length, (3,2))
492                 elif dots == 2:
493                         length = rat_multiply (length, (7,4))
494
495                 length = rat_multiply (length, (1,self.replaces))
496
497                 (nb,nd) =rat_to_duration (length)
498
499                 self.note_base = nb
500                 self.note_dots = nd
501
502         def add_chord (self, ch):
503                 ch.dots = self.note_dots
504                 ch.basic_duration = self.note_base
505                 self.chords.append (ch)
506
507                 if len (self.chords) == 1:
508                         ch.chord_prefix = '\\times %d/%d { ' % (self.replaces, self.number)
509                 elif len (self.chords) == self.number:
510                         ch.chord_suffix = ' }' 
511                 
512 class Chord:
513         def __init__ (self):
514                 self.pitches = []
515                 self.multimeasure = 0
516                 self.dots = 0
517                 self.basic_duration = 0
518                 self.scripts = []
519                 self.grace = 0
520                 self.chord_prefix = ''
521                 self.chord_suffix = ''
522                 self.note_prefix = ''
523                 self.note_suffix = ''
524                 
525         def dump (self):
526                 str = ''
527
528                 sd = ''
529                 if self.basic_duration == 0.5:
530                         sd = '\\breve'
531                 else:
532                         sd = '%d' % self.basic_duration
533                 sd = sd + '.' * self.dots 
534                 for p in self.pitches:
535                         if str:
536                                 str = str + ' ' 
537                         str = str + pitch_to_lily_string (p) + sd
538
539                 for s in self.scripts:
540                         str = str + '-' + s
541
542                 str = self.note_prefix +str  + self.note_suffix
543                 
544                 if len (self.pitches) > 1:
545                         str = '<%s>' % str
546                 elif self.multimeasure:
547                         str = 'R' + sd
548                 elif len (self.pitches) == 0:
549                         str = 'r' + sd
550
551                 str = self.chord_prefix + str + self.chord_suffix
552                 
553                 return str
554                 
555 SPACE=' \t\n'
556 DIGITS ='0123456789'
557 basicdur_table = {
558         9: 0.5,
559         0: 0 ,
560         2: 2 ,
561         4: 4 ,
562         8: 8 ,
563         1: 16,
564         3: 32,
565         6: 64
566         }
567
568
569 ornament_table = {
570         't': '\\prall',
571         'm': '\\mordent',
572         'x': '"x"',
573         '+': '+',
574         'u': '"pizz"',
575         'p': '|',
576         '(': '"paren"',
577         ')': '"paren"',
578         'g': '"segno"',
579         '.': '.',
580         'fd': '\\fermata',
581         'f': '\\fermata',
582         '_': '-',
583         'T': '\\trill',
584         '>': '>',
585         '^': '^',
586         }
587
588 # http://www.arkkra.com/doc/uguide/contexts.html
589
590 contexts = [
591         'header', 
592         'footer', 
593         'header2', 
594         'footer2', 
595         'score', 
596         'staff',
597         'voice',
598         'grids', 
599         'music',
600         ] 
601
602 class Parser:
603         def __init__ (self, filename):
604                 self.parse_function = self.parse_context_music
605                 self.staffs = []
606                 self.current_voices = []
607                 self.forced_duration = None
608                 self.last_name = 0
609                 self.last_oct = 0               
610                 self.tuplets_expected = 0
611                 self.tuplets = []
612                 self.last_basic_duration = 4
613
614                 self.parse (filename)
615                 
616         #def set_staffs (self, number):
617         #       self.staffs = map (lambda x: Staff (x), range (0, number))
618                 
619         #def current_staff (self):
620         #       return self.staffs[self.staff_idx]
621
622         #def current_voice (self):
623         #       return self.current_staff ().current_voice ()
624         
625         #def next_staff (self):
626         #       self.staff_idx = (self.staff_idx + 1)% len (self.staffs)
627                 
628         def parse_compound_location (self, line):
629                 colon = string.index (line, ':')
630                 s = line[:colon]
631                 debug (s)
632                 line = line[colon + 1:]
633                 debug (line)
634                 self.current_voices = []
635                 ##self.current_staffs = []
636                 map (self.parse_location, string.split (s, '&'))
637                 return line
638
639         def parse_location (self, line):
640                 m = re.match ('^([-,0-9]+) *([-,0-9]*)', string.lstrip (line))
641                 
642                 def range_list_to_idxs (s):
643                         
644                         # duh
645                         def flatten (l):
646                                 f = []
647                                 for i in l:
648                                         for j in i:
649                                                 f.append (j)
650                                 return f
651                                         
652                         def range_to_list (s):
653                                 if string.find (s, '-') >= 0:
654                                         debug ('s: ' + s)
655                                         l = map (string.lstrip,
656                                                  string.split (s, '-'))
657                                         r = range (string.atoi (l[0]) - 1,
658                                                    string.atoi (l[1]))
659                                 else:
660                                         r = (string.atoi (s) - 1,)
661                                 return r
662                         
663                         ranges = string.split (s, ',')
664                         l = flatten (map (range_to_list, ranges))
665                         l.sort ()
666                         return l
667                 
668                 staff_idxs = range_list_to_idxs (m.group (1))
669                 if m.group (2):
670                         voice_idxs = range_list_to_idxs (m.group (2))
671                 else:
672                         voice_idxs = [0]
673                 for s in staff_idxs:
674                         while s > len (self.staffs) - 1:
675                                 self.staffs.append (Staff (s))
676                         for v in voice_idxs:
677                                 self.current_voices.append (self.staffs[s].voices[v])
678                         
679         def parse_note (self, line):
680                 # FIXME: 1?
681                 oct = 1
682                 name = (ord (line[0]) - ord ('a') + 5) % 7
683                 # FIXME: does key play any role in this?
684                 alteration = 0
685                 line = string.lstrip (line[1:])
686                 while line:
687                         if len (line) > 1 and line[:2] == '//':
688                                 line = 0
689                                 break
690                         elif line[0] == '#':
691                                 alteration = alteration + 1
692                         elif line[0] == '&':
693                                 alteration = alteration - 1
694                         elif line[0] == '+':
695                                 oct = oct + 1 
696                         elif line[0] == '-':
697                                 oct = oct - 1
698                         else:
699                                 skipping (_ ("%s") % line[0])
700                         line = string.lstrip (line[1:])
701                 return (oct, name, alteration)
702                         
703         def parse_chord (self, line):
704                 line = string.lstrip (line)
705                 ch = Chord ()
706                 if not line:
707                         ch = self.current_voices[0].last_chord ()
708                 else:
709                         m = re.match ('^([0-9]+)([.]*)', line)
710                         if m:
711                                 ch.basic_duration = string.atoi (m.group (1))
712                                 line = line[len (m.group (1)):]
713                                 if m.group (2):
714                                         ch.basic_duration = len (m.group (2))
715                                         line = line[len (m.group (1)):]
716                         else:
717                                 ch.basic_duration = self.current_voices[0].last_chord ().basic_duration
718                                 
719                         line = string.lstrip (line)
720                         if len (line) > 1 and line[:2] == '//':
721                                 line = 0
722                         #ugh
723                         if not line:
724                                 duration = ch.basic_duration
725                                 ch = self.current_voices[0].last_chord ()
726                                 ch.basic_duration = duration
727                                 
728                         while line:
729                                 if len (line) > 1 and line[:2] == '//':
730                                         line = 0
731                                         break
732                                 elif line[:1] == 'mr':
733                                         ch.multimeasure = 1
734                                         line = line[1:]
735                                 elif line[:1] == 'ms':
736                                         ch.multimeasure = 1
737                                         line = line[1:]
738                                 elif line[0] in 'rs':
739                                         pass
740                                 elif line[0] in 'abcdefg':
741                                         pitch = self.parse_note (line)
742                                         debug ('PITCH: ' + `pitch`)
743                                         ch.pitches.append (pitch)
744                                         line = 0
745                                         break
746                                 else:
747                                         skipping (_ ("%s") % line[0])
748                                 line = string.lstrip (line[1:])
749                 map (lambda x, ch=ch: x.add_chord (ch), self.current_voices)
750
751         def parse_voice (self, line):
752                 chords = string.split (line, ';')
753                 map (self.parse_chord, chords)
754
755         def init_context_header (self, line):
756                 self.parse_function = self.parse_context_header
757                                         
758         def parse_context_header (self, line):
759                 debug ('header: ' + line)
760
761         def init_context_footer (self, line):
762                 self.parse_function = self.parse_context_footer
763
764         def parse_context_footer (self, line):
765                 debug ('footer: ' + line)
766
767         def init_context_header2 (self, line):
768                 self.parse_function = self.parse_context_header2
769
770         def parse_context_header2 (self, line):
771                 debug ('header2: ' + line)
772
773         def init_context_footer2 (self, line):
774                 self.parse_function = self.parse_context_footer2
775
776         def parse_context_footer2 (self, line):
777                 debug ('footer2: ' + line)
778
779         def init_context_score (self, line):
780                 self.parse_function = self.parse_context_score
781
782         def parse_context_score (self, line):
783                 debug ('score: ' + line)
784
785         def init_context_staff (self, line):
786                 self.parse_function = self.parse_context_staff
787
788         def parse_context_staff (self, line):
789                 debug ('staff: ' + line)
790
791         def init_context_voice (self, line):
792                 self.parse_function = self.parse_context_voice
793
794         def parse_context_voice (self, line):
795                 debug ('voice: ' + line)
796
797         def init_context_grids (self, line):
798                 self.parse_function = self.parse_context_line
799
800         def parse_context_grids (self, line):
801                 debug ('grids: ' + line)
802
803         def init_context_music (self, line):
804                 self.parse_function = self.parse_context_music
805
806         def parse_context_music (self, line):
807                 debug ('music: ' + line)
808                 line = string.lstrip (line)
809                 if line and line[0] in '0123456789':
810                         line = string.lstrip (self.parse_compound_location (line))
811                         self.parse_voice (line)
812                 else:
813                         skipping (_ ("%s") % line)
814         
815         def parse (self, file):
816                 # shortcut: set to official mup maximum (duh)
817                 # self.set_staffs (40)
818                 lines = open (file).readlines ()
819                 for line in lines:
820                         debug ('LINE: ' + line)
821                         m = re.match ('^([a-z]+2?)', line)
822                         
823                         if m:
824                                 word = m.group (1)
825                                 if word in contexts:
826                                         eval ('self.init_context_%s (line)' % word)
827                                         continue
828                                 else:
829                                         warning (_ ("no such context: %s") % word)
830                                         skipping (line)
831                         else:
832                                 debug ('FUNC: ' + `self.parse_function`)
833                                 self.parse_function (line)
834                                 
835                 for c in self.staffs:
836                         c.calculate ()
837
838         def dump (self):
839                 str = ''
840
841                 refs = ''
842                 for s in self.staffs:
843                         str = str +  s.dump ()
844                         refs = refs + '\n    \\' + s.idstring ()
845
846                 str = str + '''
847
848 \score {
849   <%s
850    >
851 }
852 ''' % refs 
853                 return str
854
855                 
856 option_definitions = [
857         ('', 'd', 'debug', _ ("debug")),
858         ('', 'h', 'help', _ ("this help")),
859         ('FILE', 'o', 'output', _ ("write output to FILE")),
860         ('', 'V', 'verbose', _ ("verbose")),
861         ('', 'v', 'version', _ ("print version number")),
862         ('', 'w', 'warranty', _ ("show warranty and copyright")),
863         ]
864
865 debug_p = 0
866 def debug (s):
867         if debug_p:
868                 progress ('DEBUG: ' + s)
869 def skipping (s):
870         if debug_p:
871                 progress ('SKIPPING: ' + s)
872
873 (sh, long) = getopt_args (__main__.option_definitions)
874 try:
875         (options, files) = getopt.getopt (sys.argv[1:], sh, long)
876 except:
877         help ()
878         sys.exit (2)
879
880
881 for opt in options:
882         o = opt[0]
883         a = opt[1]
884         if 0:
885                 pass
886         elif o== '--debug' or o == '-d':
887                 debug_p = 1
888         elif o== '--help' or o == '-h':
889                 help ()
890                 sys.exit (0)
891         elif o== '--verbose' or o == '-V':
892                 verbose_p = 1
893         elif o == '--version' or o == '-v':
894                 identify ()
895                 sys.exit (0)
896         elif o == '--output' or o == '-o':
897                 output = a
898         else:
899                 print o
900                 raise getopt.error
901
902 # writes to stdout for help2man
903 # don't call 
904 # identify ()
905 # sys.stdout.flush ()
906
907 # handy emacs testing
908 if not files:
909         files = ['template.mup']
910
911 for f in files:
912         if f == '-':
913                 f = ''
914
915         progress ( _("Processing %s..." % f))
916         e = Parser (f)
917         if not output:
918                 output = os.path.basename (re.sub ('(?i).mup$', '.ly', f))
919                 
920         if output == f:
921                 output = os.path.basename (f + '.ly')
922                 
923         progress (_ ("Writing %s...") % output)
924
925         tag = '%% Lily was here -- automatically converted by %s from %s' % ( program_name, f)
926         ly = tag + '\n' + e.dump ()
927
928         o = open (output, 'w')
929         o.write (ly)
930         o.close ()
931         print ly
932