]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-ly.py
new slur dash patch by Bertalan Fodor.
[lilypond.git] / scripts / convert-ly.py
1 #!@PYTHON@
2 #
3 # convert-ly.py -- Update old LilyPond input files (fix name?)
4 #
5 # source file of the GNU LilyPond music typesetter
6 #
7 # (c) 1998--2005  Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 #                 Jan Nieuwenhuizen <janneke@gnu.org>
9
10 import os
11 import sys
12 import __main__
13 import getopt
14 import  string
15 import re
16 import time
17
18 program_name = sys.argv[0]
19
20 version = '@TOPLEVEL_VERSION@'
21
22 # Did we ever have \mudela-version?  I doubt it.
23 # lilypond_version_re_str = '\\\\version *\"(.*)\"'
24 lilypond_version_re_str = '\\\\(mudela-)?version *\"([^"]+)\"'
25 lilypond_version_re = re.compile (lilypond_version_re_str)
26 add_version = 1
27
28
29 def program_id ():
30         return '%s (GNU LilyPond) %s' % (program_name, version)
31
32 def identify ():
33         sys.stderr.write (program_id () + '\n')
34
35 def usage ():
36         sys.stdout.write (
37                 r"""Usage: %s [OPTIONS]... [FILE]...
38 Try to convert to newer lilypond-versions.  The version number of the
39 input is guessed by default from \version directive.
40
41 Options:
42   -h, --help             print this help
43   -e, --edit             edit in place
44   -f, --from=VERSION     start from version [default: \version found in file]
45   -s, --show-rules       print all rules
46   -t, --to=VERSION       end at version [default: @TOPLEVEL_VERSION@]
47   -n, --no-version       don't add new version stamp
48       --version          print program version
49
50 Report bugs to bugs-gnu-music@gnu.org.
51
52 """ % program_name)
53         
54         
55         sys.exit (0)
56
57 def print_version ():
58         
59         sys.stdout.write (r"""%s
60
61 This is free software.  It is covered by the GNU General Public
62 License, and you are welcome to change it and/or distribute copies of
63 it under certain conditions.  invoke as `%s --warranty' for more
64 information.
65
66 """ % (program_id (), program_name))
67         
68 def str_to_tuple (s):
69         return tuple (map (string.atoi, string.split (s, '.')))
70
71 def tup_to_str (t):
72         return string.join (map (lambda x: '%s' % x, list (t)), '.')
73
74 def version_cmp (t1, t2):
75         for x in [0, 1, 2]:
76                 if t1[x] - t2[x]:
77                         return t1[x] - t2[x]
78         return 0
79
80 def guess_lilypond_version (filename):
81         s = open (filename).read ()
82         m = lilypond_version_re.search (s)
83         if m:
84                 return m.group (2)
85         else:
86                 return ''
87
88 class FatalConversionError:
89         pass
90
91 conversions = []
92
93 def show_rules (file):
94         for x in conversions:
95                 if (not from_version or x[0] > from_version) \
96                    and (not to_version or x[0] <= to_version):
97                         file.write  ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
98
99 ############################
100                 
101 if 1:
102         def conv(str):
103                 if re.search ('\\\\multi', str):
104                         sys.stderr.write ('\nNot smart enough to convert \\multi')
105                 return str
106         
107         conversions.append (((0,1,9), conv, '\\header { key = concat + with + operator }'))
108
109 if 1:                                   # need new a namespace
110         def conv (str):
111                 if re.search ('\\\\octave', str):
112                         sys.stderr.write ('\nNot smart enough to convert \\octave')
113                 #       raise FatalConversionError()
114                 
115                 return str
116
117         conversions.append ((
118                 ((0,1,19), conv, 'deprecated \\octave; can\'t convert automatically')))
119
120
121 if 1:                                   # need new a namespace
122         def conv (str):
123                 str = re.sub ('\\\\textstyle([^;]+);',
124                                          '\\\\property Lyrics . textstyle = \\1', str)
125                 # harmful to current .lys
126                 # str = re.sub ('\\\\key([^;]+);', '\\\\accidentals \\1;', str)
127                         
128                 return str
129
130         conversions.append ((
131                 ((0,1,20), conv, 'deprecated \\textstyle, new \\key syntax')))
132
133
134 if 1:
135         def conv (str):
136                 str = re.sub ('\\\\musical_pitch', '\\\\musicalpitch',str)
137                 str = re.sub ('\\\\meter', '\\\\time',str)
138                         
139                 return str
140
141         conversions.append ((
142                 ((0,1,21), conv, '\\musical_pitch -> \\musicalpitch, '+
143                  '\\meter -> \\time')))
144
145 if 1:
146         def conv (str):
147                 return str
148
149         conversions.append ((
150                 ((1,0,0), conv, '0.1.21 -> 1.0.0 ')))
151
152
153 if 1:
154         def conv (str):
155                 str = re.sub ('\\\\accidentals', '\\\\keysignature',str)
156                 str = re.sub ('specialaccidentals *= *1', 'keyoctaviation = 0',str)
157                 str = re.sub ('specialaccidentals *= *0', 'keyoctaviation = 1',str)
158                         
159                 return str
160
161         conversions.append ((
162                 ((1,0,1), conv, '\\accidentals -> \\keysignature, ' +
163                  'specialaccidentals -> keyoctaviation')))
164
165 if 1:
166         def conv(str):
167                 if re.search ('\\\\header', str):
168                         sys.stderr.write ('\nNot smart enough to convert to new \\header format')
169                 return str
170         
171         conversions.append (((1,0,2), conv, '\\header { key = concat + with + operator }'))
172
173 if 1:
174         def conv(str):
175                 str =  re.sub ('\\\\melodic([^a-zA-Z])', '\\\\notes\\1',str)
176                 return str
177         
178         conversions.append (((1,0,3), conv, '\\melodic -> \\notes'))
179
180 if 1:
181         def conv(str):
182                 str =  re.sub ('default_paper *=', '',str)
183                 str =  re.sub ('default_midi *=', '',str)
184                 return str
185         
186         conversions.append (((1,0,4), conv, 'default_{paper,midi}'))
187
188 if 1:
189         def conv(str):
190                 str =  re.sub ('ChoireStaff', 'ChoirStaff',str)
191                 str =  re.sub ('\\\\output', 'output = ',str)
192                         
193                 return str
194         
195         conversions.append (((1,0,5), conv, 'ChoireStaff -> ChoirStaff'))
196
197 if 1:
198         def conv(str):
199                 if re.search ('[a-zA-Z]+ = *\\translator',str):
200                         sys.stderr.write ('\nNot smart enough to change \\translator syntax')
201                 #       raise FatalConversionError()
202                 return str
203         
204         conversions.append (((1,0,6), conv, 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }'))
205
206
207 if 1:
208         def conv(str):
209                 str =  re.sub ('\\\\lyrics*', '\\\\lyrics',str)
210                         
211                 return str
212         
213         conversions.append (((1,0,7), conv, '\\lyric -> \\lyrics'))
214
215 if 1:
216         def conv(str):
217                 str =  re.sub ('\\\\\\[/3+', '\\\\times 2/3 { ',str)
218                 str =  re.sub ('\\[/3+', '\\\\times 2/3 { [',str)
219                 str =  re.sub ('\\\\\\[([0-9/]+)', '\\\\times \\1 {',str)
220                 str =  re.sub ('\\[([0-9/]+)', '\\\\times \\1 { [',str)
221                 str =  re.sub ('\\\\\\]([0-9/]+)', '}', str)
222                 str =  re.sub ('\\\\\\]', '}',str)
223                 str =  re.sub ('\\]([0-9/]+)', '] }', str)
224                 return str
225         
226         conversions.append (((1,0,10), conv, '[2/3 ]1/1 -> \\times 2/3 '))
227
228 if 1:
229         def conv(str):
230                 return str
231         conversions.append (((1,0,12), conv, 'Chord syntax stuff'))
232
233
234 if 1:
235         def conv(str):
236                 
237                 
238                 str =  re.sub ('<([^>~]+)~([^>]*)>','<\\1 \\2> ~', str)
239                         
240                 return str
241         
242         conversions.append (((1,0,13), conv, '<a ~ b> c -> <a b> ~ c'))
243
244 if 1:
245         def conv(str):
246                 str =  re.sub ('<\\[','[<', str)
247                 str =  re.sub ('\\]>','>]', str)
248                         
249                 return str
250         
251         conversions.append (((1,0,14), conv, '<[a b> <a b]>c -> [<a b> <a b>]'))
252
253
254 if 1:
255         def conv(str):
256                 str =  re.sub ('\\\\type([^\n]*engraver)','\\\\TYPE\\1', str)
257                 str =  re.sub ('\\\\type([^\n]*performer)','\\\\TYPE\\1', str)
258                 str =  re.sub ('\\\\type','\\\\context', str)
259                 str =  re.sub ('\\\\TYPE','\\\\type', str)
260                 str =  re.sub ('textstyle','textStyle', str)
261                         
262                 return str
263         
264         conversions.append (((1,0,16), conv, '\\type -> \\context, textstyle -> textStyle'))
265
266
267 if 1:
268         def conv(str):
269                 if re.search ('\\\\repeat',str):
270                         sys.stderr.write ('\nNot smart enough to convert \\repeat')
271                 #       raise FatalConversionError()
272                 return str
273         
274         conversions.append (((1,0,18), conv,
275                 '\\repeat NUM Music Alternative -> \\repeat FOLDSTR Music Alternative'))
276
277 if 1:
278         def conv(str):
279                 str =  re.sub ('SkipBars','skipBars', str)
280                 str =  re.sub ('fontsize','fontSize', str)
281                 str =  re.sub ('midi_instrument','midiInstrument', str)                 
282                         
283                 return str
284
285         conversions.append (((1,0,19), conv,
286                 'fontsize -> fontSize, midi_instrument -> midiInstrument, SkipBars -> skipBars'))
287
288
289 if 1:
290         def conv(str):
291                 str =  re.sub ('tieydirection','tieVerticalDirection', str)
292                 str =  re.sub ('slurydirection','slurVerticalDirection', str)
293                 str =  re.sub ('ydirection','verticalDirection', str)                   
294                         
295                 return str
296
297         conversions.append (((1,0,20), conv,
298                 '{,tie,slur}ydirection -> {v,tieV,slurV}erticalDirection'))
299
300
301 if 1:
302         def conv(str):
303                 str =  re.sub ('hshift','horizontalNoteShift', str)
304                         
305                 return str
306
307         conversions.append (((1,0,21), conv,
308                 'hshift -> horizontalNoteShift'))
309
310
311 if 1:
312         def conv(str):
313                 str =  re.sub ('\\\\grouping[^;]*;','', str)
314                         
315                 return str
316
317         conversions.append (((1,1,52), conv,
318                 'deprecate \\grouping'))
319
320
321 if 1:
322         def conv(str):
323                 str =  re.sub ('\\\\wheel','\\\\coda', str)
324                         
325                 return str
326
327         conversions.append (((1,1,55), conv,
328                 '\\wheel -> \\coda'))
329
330 if 1:
331         def conv(str):
332                 str =  re.sub ('keyoctaviation','keyOctaviation', str)
333                 str =  re.sub ('slurdash','slurDash', str)
334                         
335                 return str
336
337         conversions.append (((1,1,65), conv,
338                 'slurdash -> slurDash, keyoctaviation -> keyOctaviation'))
339
340 if 1:
341         def conv(str):
342                 str =  re.sub ('\\\\repeat *\"?semi\"?','\\\\repeat "volta"', str)
343                         
344                 return str
345
346         conversions.append (((1,1,66), conv,
347                 'semi -> volta'))
348
349
350 if 1:
351         def conv(str):
352                 str =  re.sub ('\"?beamAuto\"? *= *\"?0?\"?','noAutoBeaming = "1"', str)
353                         
354                 return str
355
356         conversions.append (((1,1,67), conv,
357                 'beamAuto -> noAutoBeaming'))
358
359 if 1:
360         def conv(str):
361                 str =  re.sub ('automaticMelismas', 'automaticMelismata', str)
362                         
363                 return str
364
365         conversions.append (((1,2,0), conv,
366                 'automaticMelismas -> automaticMelismata'))
367
368 if 1:
369         def conv(str):
370                 str =  re.sub ('dynamicDir\\b', 'dynamicDirection', str)
371                         
372                 return str
373
374         conversions.append (((1,2,1), conv,
375                 'dynamicDir -> dynamicDirection'))
376
377 if 1:
378         def conv(str):
379                 str =  re.sub ('\\\\cadenza *0 *;', '\\\\cadenzaOff', str)
380                 str =  re.sub ('\\\\cadenza *1 *;', '\\\\cadenzaOn', str)               
381                         
382                 return str
383
384         conversions.append (((1,3,4), conv,
385                 '\\cadenza -> \\cadenza{On|Off}'))
386
387 if 1:
388         def conv (str):
389                 str = re.sub ('"?beamAuto([^"=]+)"? *= *"([0-9]+)/([0-9]+)" *;*',
390                               'beamAuto\\1 = #(make-moment \\2 \\3)',
391                               str)
392                 return str
393
394         conversions.append (((1,3,5), conv, 'beamAuto moment properties'))
395
396 if 1:
397         def conv (str):
398                 str = re.sub ('stemStyle',
399                               'flagStyle',
400                               str)
401                 return str
402
403         conversions.append (((1,3,17), conv, 'stemStyle -> flagStyle'))
404
405 if 1:
406         def conv (str):
407                 str = re.sub ('staffLineLeading',
408                               'staffSpace',
409                               str)
410                 return str
411
412         conversions.append (((1,3,18), conv, 'staffLineLeading -> staffSpace'))
413
414
415 if 1:
416         def conv(str):
417                 if re.search ('\\\\repetitions',str):
418                         sys.stderr.write ('\nNot smart enough to convert \\repetitions')
419                 #       raise FatalConversionError()
420                 return str
421         
422         conversions.append (((1,3,23), conv,
423                 '\\\\repetitions feature dropped'))
424
425
426 if 1:
427         def conv (str):
428                 str = re.sub ('textEmptyDimension *= *##t',
429                               'textNonEmpty = ##f',
430                               str)
431                 str = re.sub ('textEmptyDimension *= *##f',
432                               'textNonEmpty = ##t',
433                               str)
434                 return str
435
436         conversions.append (((1,3,35), conv, 'textEmptyDimension -> textNonEmpty'))
437
438 if 1:
439         def conv (str):
440                 str = re.sub ("([a-z]+)[ \t]*=[ \t]*\\\\musicalpitch *{([- 0-9]+)} *\n",
441                               "(\\1 . (\\2))\n", str)
442                 str = re.sub ("\\\\musicalpitch *{([0-9 -]+)}",
443                               "\\\\musicalpitch #'(\\1)", str)
444                 if re.search ('\\\\notenames',str):
445                         sys.stderr.write ('\nNot smart enough to convert to new \\notenames format')
446                 return str
447
448         conversions.append (((1,3,38), conv, '\musicalpitch { a b c } -> #\'(a b c)'))
449
450 if 1:
451         def conv (str):
452                 def replace (match):
453                         return '\\key %s;' % string.lower (match.group (1))
454                 
455                 str = re.sub ("\\\\key ([^;]+);",  replace, str)
456                 return str
457         
458         conversions.append (((1,3,39), conv, '\\key A ;  ->\\key a;'))
459
460 if 1:
461         def conv (str):
462                 if re.search ('\\[:',str):
463                         sys.stderr.write ('\nNot smart enough to convert to new tremolo format')
464                 return str
465
466         conversions.append (((1,3,41), conv,
467                 '[:16 c4 d4 ] -> \\repeat "tremolo" 2 { c16 d16 }'))
468
469 if 1:
470         def conv (str):
471                 str = re.sub ('Staff_margin_engraver' , 'Instrument_name_engraver', str)
472                 return str
473
474         conversions.append (((1,3,42), conv,
475                 'Staff_margin_engraver deprecated, use Instrument_name_engraver'))
476
477 if 1:
478         def conv (str):
479                 str = re.sub ('note[hH]eadStyle\\s*=\\s*"?(\\w+)"?' , "noteHeadStyle = #'\\1", str)
480                 return str
481
482         conversions.append (((1,3,49), conv,
483                 'noteHeadStyle value: string -> symbol'))
484
485 if 1:
486         def conv (str):
487                 if re.search ('\\\\keysignature', str):
488                         sys.stderr.write ('\nNot smart enough to convert to new tremolo format')
489                 return str
490
491
492         conversions.append (((1,3,58), conv,
493                 'noteHeadStyle value: string -> symbol'))
494
495 if 1:
496         def conv (str):
497                 str = re.sub (r"""\\key *([a-z]+) *;""", r"""\\key \1 \major;""",str);
498                 return str
499         conversions.append (((1,3,59), conv,
500                 '\key X ; -> \key X major; '))
501
502 if 1:
503         def conv (str):
504                 str = re.sub (r'latexheaders *= *"\\\\input ',
505                               'latexheaders = "',
506                               str)
507                 return str
508         conversions.append (((1,3,68), conv, 'latexheaders = "\\input global" -> latexheaders = "global"'))
509
510
511
512
513 # TODO: lots of other syntax change should be done here as well
514 if 1:
515         def conv (str):
516                 str = re.sub ('basicCollisionProperties', 'NoteCollision', str)
517                 str = re.sub ('basicVoltaSpannerProperties' , "VoltaBracket", str)
518                 str = re.sub ('basicKeyProperties' , "KeySignature", str)
519
520                 str = re.sub ('basicClefItemProperties' ,"Clef", str)
521
522
523                 str = re.sub ('basicLocalKeyProperties' ,"Accidentals", str)
524                 str = re.sub ('basicMarkProperties' ,"Accidentals", str)
525                 str = re.sub ('basic([A-Za-z_]+)Properties', '\\1', str)
526
527                 str = re.sub ('Repeat_engraver' ,'Volta_engraver', str)
528                 return str
529         
530         conversions.append (((1,3,92), conv, 'basicXXXProperties -> XXX, Repeat_engraver -> Volta_engraver'))
531
532 if 1:
533         def conv (str):
534                 # Ugh, but meaning of \stemup changed too
535                 # maybe we should do \stemup -> \stemUp\slurUp\tieUp ?
536                 str = re.sub ('\\\\stemup', '\\\\stemUp', str)
537                 str = re.sub ('\\\\stemdown', '\\\\stemDown', str)
538                 str = re.sub ('\\\\stemboth', '\\\\stemBoth', str)
539                 
540                 str = re.sub ('\\\\slurup', '\\\\slurUp', str)
541                 str = re.sub ('\\\\slurboth', '\\\\slurBoth', str)
542                 str = re.sub ('\\\\slurdown', '\\\\slurDown', str)
543                 str = re.sub ('\\\\slurdotted', '\\\\slurDotted', str)
544                 str = re.sub ('\\\\slurnormal', '\\\\slurNoDots', str)          
545                 
546                 str = re.sub ('\\\\shiftoff', '\\\\shiftOff', str)
547                 str = re.sub ('\\\\shifton', '\\\\shiftOn', str)
548                 str = re.sub ('\\\\shiftonn', '\\\\shiftOnn', str)
549                 str = re.sub ('\\\\shiftonnn', '\\\\shiftOnnn', str)
550
551                 str = re.sub ('\\\\onevoice', '\\\\oneVoice', str)
552                 str = re.sub ('\\\\voiceone', '\\\\voiceOne', str)
553                 str = re.sub ('\\\\voicetwo', '\\\\voiceTwo', str)
554                 str = re.sub ('\\\\voicethree', '\\\\voiceThree', str)
555                 str = re.sub ('\\\\voicefour', '\\\\voiceFour', str)
556
557                 # I don't know exactly when these happened...
558                 # ugh, we loose context setting here...
559                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\stemUp\\\\slurUp\\\\tieUp', str)
560                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\stemDown\\\\slurDown\\\\tieDown', str)
561                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\stemBoth\\\\slurBoth\\\\tieBoth', str)
562
563                 str = re.sub ('verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #1', str)
564                 str = re.sub ('verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #-1', str)
565                 str = re.sub ('verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #0', str)
566                 
567                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\\\1Up', str)
568                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\\\1Down', str)
569                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\\\1Both', str)
570
571                 # (lacks capitalisation slur -> Slur)
572                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\1 \\\\override #\'direction = #1', str)
573                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\1 \\override #\'direction = #-1', str)
574                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\1 \\\\override #\'direction = #0', str)
575
576                 ## dynamic..
577                 str = re.sub ('\\\\property *[^ .]*[.]?dynamicDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\dynamicUp', str)
578                 str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\dynamicDown', str)
579                 str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?(0|(\\\\center))"?', '\\\\dynamicBoth', str)
580
581                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?(0|(""))"?', '\\\\\\1NoDots', str)
582                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?([1-9]+)"?', '\\\\\\1Dotted', str)
583
584                 str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?(0|(""))"?', '\\\\autoBeamOn', str)
585                 str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?([1-9]+)"?', '\\\\autoBeamOff', str)
586
587
588
589                 return str
590         
591         conversions.append (((1,3,93), conv,
592                 'property definiton case (eg. onevoice -> oneVoice)'))
593
594
595 if 1:
596         def conv (str):
597                 str = re.sub ('ChordNames*', 'ChordNames', str)
598                 if re.search ('\\\\textscript "[^"]* *"[^"]*"', str):
599                         sys.stderr.write ('\nNot smart enough to convert to new \\textscript markup text')
600
601                 str = re.sub ('\\textscript +("[^"]*")', '\\textscript #\\1', str)
602
603                 return str
604         
605         conversions.append (((1,3,97), conv, 'ChordName -> ChordNames'))
606
607
608 # TODO: add lots of these
609         
610 if 1:
611         def conv (str):
612                 str = re.sub ('\\\\property *"?Voice"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Voice.TextScript \\\\set #\'font-style = #\'\\1', str)
613                 str = re.sub ('\\\\property *"?Lyrics"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Lyrics.LyricText \\\\set #\'font-style = #\'\\1', str)
614
615                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?timeSignatureStyle"? *= *"([^"]*)"', '\\\\property \\1.TimeSignature \\\\override #\'style = #\'\\2', str)
616
617                 str = re.sub ('"?timeSignatureStyle"? *= *#?""', 'TimeSignature \\\\override #\'style = ##f', str)
618                 
619                 str = re.sub ('"?timeSignatureStyle"? *= *#?"([^"]*)"', 'TimeSignature \\\\override #\'style = #\'\\1', str)
620                 
621                 str = re.sub ('#\'style *= #*"([^"])"', '#\'style = #\'\\1', str)
622                 
623                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?horizontalNoteShift"? *= *"?#?([-0-9]+)"?', '\\\\property \\1.NoteColumn \\\\override #\'horizontal-shift = #\\2', str)
624
625                 # ugh
626                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *""', '\\\\property \\1.Stem \\\\override #\'flag-style = ##f', str)
627                 
628                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *"([^"]*)"', '\\\\property \\1.Stem \\\\override #\'flag-style = #\'\\2', str)
629                 return str
630         
631         conversions.append (((1,3,98), conv, 'CONTEXT.textStyle -> GROB.#font-style '))
632
633 if 1:
634         def conv (str):
635                 str = re.sub ('"?beamAutoEnd_([0-9]*)"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end 1 \\1 * *) = \\2', str)
636                 str = re.sub ('"?beamAutoBegin_([0-9]*)"? *= *(#\\([^)]*\))', 'autoBeamSettings \\push #\'(begin 1 \\1 * *) = \\2', str)
637                 str = re.sub ('"?beamAutoEnd"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end * * * *) = \\1', str)
638                 str = re.sub ('"?beamAutoBegin"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(begin * * * *) = \\1', str)
639
640
641                 return str
642         
643         conversions.append (((1,3,102), conv, 'beamAutoEnd -> autoBeamSettings \\push (end * * * *)'))
644
645
646 if 1:
647         def conv (str):
648                 str = re.sub ('\\\\push', '\\\\override', str)
649                 str = re.sub ('\\\\pop', '\\\\revert', str)
650
651                 return str
652         
653         conversions.append (((1,3,111), conv, '\\push -> \\override, \\pop -> \\revert'))
654
655 if 1:
656         def conv (str):
657                 str = re.sub ('LyricVoice', 'LyricsVoice', str)
658                 # old fix
659                 str = re.sub ('Chord[Nn]ames*.Chord[Nn]ames*', 'ChordNames.ChordName', str)
660                 str = re.sub ('Chord[Nn]ames([ \t\n]+\\\\override)', 'ChordName\\1', str)
661                 return str
662         
663         conversions.append (((1,3,113), conv, 'LyricVoice -> LyricsVoice'))
664
665 def regularize_id (str):
666         s = ''
667         lastx = ''
668         for x in str:
669                 if x == '_':
670                         lastx = x
671                         continue
672                 elif x in string.digits:
673                         x = chr(ord (x) - ord ('0')  +ord ('A'))
674                 elif x not in string.letters:
675                         x = 'x'
676                 elif x in string.lowercase and lastx == '_':
677                         x = string.upper (x)
678                 s = s + x
679                 lastx = x
680         return s
681
682 if 1:
683         def conv (str):
684                 
685                 def regularize_dollar_reference (match):
686                         return regularize_id (match.group (1))
687                 def regularize_assignment (match):
688                         return '\n' + regularize_id (match.group (1)) + ' = '
689                 str = re.sub ('\$([^\t\n ]+)', regularize_dollar_reference, str)
690                 str = re.sub ('\n([^ \t\n]+)[ \t]*= *', regularize_assignment, str)
691                 return str
692         
693         conversions.append (((1,3,117), conv, 'identifier names: $!foo_bar_123 -> xfooBarABC'))
694
695
696 if 1:
697         def conv (str):
698                 def regularize_paper (match):
699                         return regularize_id (match.group (1))
700                 
701                 str = re.sub ('(paper_[a-z]+)', regularize_paper, str)
702                 str = re.sub ('sustainup', 'sustainUp', str)
703                 str = re.sub ('nobreak', 'noBreak', str)
704                 str = re.sub ('sustaindown', 'sustainDown', str)
705                 str = re.sub ('sostenutoup', 'sostenutoUp', str)
706                 str = re.sub ('sostenutodown', 'sostenutoDown', str)
707                 str = re.sub ('unachorda', 'unaChorda', str)
708                 str = re.sub ('trechorde', 'treChorde', str)
709         
710                 return str
711         
712         conversions.append (((1,3,120), conv, 'paper_xxx -> paperXxxx, pedalup -> pedalUp.'))
713
714 if 1:
715         def conv (str):
716                 str = re.sub ('drarnChords', 'chordChanges', str)
717                 str = re.sub ('\\musicalpitch', '\\pitch', str)
718                 return str
719         
720         conversions.append (((1,3,122), conv, 'drarnChords -> chordChanges, \\musicalpitch -> \\pitch'))
721
722 if 1:
723         def conv (str):
724                 str = re.sub ('ly-([sg])et-elt-property', 'ly-\\1et-grob-property', str)
725                 return str
726         
727         conversions.append (((1,3,136), conv, 'ly-X-elt-property -> ly-X-grob-property'))
728
729 if 1:
730         def conv (str):
731                 str = re.sub ('point-and-click +#t', 'point-and-click line-column-location', str)
732                 return str
733         
734         conversions.append (((1,3,138), conv, 'point-and-click argument changed to procedure.'))
735
736 if 1:
737         def conv (str):
738                 str = re.sub ('followThread', 'followVoice', str)
739                 str = re.sub ('Thread.FollowThread', 'Voice.VoiceFollower', str)
740                 str = re.sub ('FollowThread', 'VoiceFollower', str)
741                 return str
742         
743         conversions.append (((1,3,138), conv, 'followThread -> followVoice.'))
744
745 if 1:
746         def conv (str):
747                 str = re.sub ('font-point-size', 'font-design-size', str)
748                 return str
749         
750         conversions.append (((1,3,139), conv, 'font-point-size -> font-design-size.'))
751
752 if 1:
753         def conv (str):
754                 str = re.sub ('([a-zA-Z]*)NoDots', '\\1Solid', str)
755                 return str
756         
757         conversions.append (((1,3,141), conv, 'xNoDots -> xSolid'))
758
759 if 1:
760         def conv (str):
761                 str = re.sub ('([Cc])hord([ea])', '\\1ord\\2', str)
762                 return str
763         
764         conversions.append (((1,3,144), conv, 'Chorda -> Corda'))
765
766
767 if 1:
768         def conv (str):
769                 str = re.sub ('([A-Za-z]+)MinimumVerticalExtent', 'MinimumV@rticalExtent', str)
770                 str = re.sub ('([A-Za-z]+)ExtraVerticalExtent', 'ExtraV@rticalExtent', str)
771                 str = re.sub ('([A-Za-z]+)VerticalExtent', 'VerticalExtent', str)
772                 str = re.sub ('ExtraV@rticalExtent', 'ExtraVerticalExtent', str)
773                 str = re.sub ('MinimumV@rticalExtent', 'MinimumVerticalExtent', str)            
774                 return str
775
776         conversions.append (((1,3,145), conv,
777         'ContextNameXxxxVerticalExtent -> XxxxVerticalExtent'))
778
779 if 1:
780         def conv (str):
781                 str = re.sub ('\\\\key[ \t]*;', '\\key \\default;', str)
782                 str = re.sub ('\\\\mark[ \t]*;', '\\mark \\default;', str)
783
784                 # Make sure groups of more than one ; have space before
785                 # them, so that non of them gets removed by next rule
786                 str = re.sub ("([^ \n\t;]);(;+)", "\\1 ;\\2", str)
787                 
788                 # Only remove ; that are not after spaces, # or ;
789                 # Otherwise  we interfere with Scheme comments,
790                 # which is badbadbad.
791                 str = re.sub ("([^ \t;#]);", "\\1", str)
792
793                 return str
794         conversions.append (((1,3,146), conv, 'semicolons removed'))
795
796 if 1:
797         def conv (str):
798                 str = re.sub ('default-neutral-direction', 'neutral-direction',str)
799                 return str
800         conversions.append (((1,3,147), conv, 'default-neutral-direction -> neutral-direction'))
801
802 if 1:
803         def conv (str):
804                 str = re.sub ('\(align', '(axis', str)
805                 str = re.sub ('\(rows', '(columns', str)
806                 return str
807         conversions.append (((1,3,148), conv, '"(align" -> "(axis", "(rows" -> "(columns"'))
808
809
810 if 1:
811         def conv (str):
812                 str = re.sub ('SystemStartDelimiter', 'systemStartDelimiter', str)
813                 return str
814         conversions.append (((1,5,33), conv, 'SystemStartDelimiter -> systemStartDelimiter'))
815
816 if 1:
817         def conv (str):
818                 str = re.sub ('arithmetic-multiplier', 'spacing-increment', str)
819                 str = re.sub ('arithmetic-basicspace', 'shortest-duration-space', str)          
820                 return str
821         
822         conversions.append (((1,5,38), conv, 'SystemStartDelimiter -> systemStartDelimiter'))
823
824
825 if 1:
826         def conv (str):
827         
828                 def func(match):
829                         break_dict = {
830                         "Instrument_name": "instrument-name",
831                         "Left_edge_item": "left-edge",
832                         "Span_bar": "span-bar",
833                         "Breathing_sign": "breathing-sign",
834                         "Staff_bar": "staff-bar",
835                         "Clef_item": "clef",
836                         "Key_item": "key-signature",
837                         "Time_signature": "time-signature",
838                         "Custos": "custos"
839                         }
840                         props =  match.group (1)
841                         for (k,v) in break_dict.items():
842                                 props = re.sub (k, v, props)
843                         return  "breakAlignOrder = #'(%s)" % props
844
845                 str = re.sub ("breakAlignOrder *= *#'\\(([a-z_\n\tA-Z ]+)\\)",
846                               func, str)
847                 return str
848
849         # 40 ?
850         conversions.append (((1,5,40), conv, 'breakAlignOrder property names'))
851         
852
853 if 1:
854         def conv (str):
855                 str = re.sub ('noAutoBeaming *= *##f', 'autoBeaming = ##t', str)
856                 str = re.sub ('noAutoBeaming *= *##t', 'autoBeaming = ##f', str)
857                 return str
858         
859         conversions.append (((1,5,49), conv, 'noAutoBeaming -> autoBeaming'))
860
861 if 1:
862         def conv (str):
863                 str = re.sub ('tuplet-bracket-visibility', 'bracket-visibility', str)
864                 str = re.sub ('tuplet-number-visibility', 'number-visibility', str)             
865                 return str
866         
867         conversions.append (((1,5,52), conv, 'tuplet-X-visibility -> X-visibility'))
868
869 if 1:
870         def conv (str):
871                 str = re.sub ('Pitch::transpose', 'ly-transpose-pitch', str)
872
873                 return str
874         
875         conversions.append (((1,5,56), conv, 'Pitch::transpose -> ly-transpose-pitch'))
876
877 if 1:
878         def conv (str):
879                 str = re.sub ('textNonEmpty *= *##t', "TextScript \\set #'no-spacing-rods = ##f", str)
880                 str = re.sub ('textNonEmpty *= *##f', "TextScript \\set #'no-spacing-rods = ##t", str)
881                 return str
882         
883         conversions.append (((1,5,58), conv, 'deprecate textNonEmpty'))
884
885
886 if 1:
887         def conv (str):
888                 str = re.sub ('MinimumVerticalExtent', 'minimumV@rticalExtent', str)
889                 str = re.sub ('minimumVerticalExtent', 'minimumV@rticalExtent', str)            
890                 str = re.sub ('ExtraVerticalExtent', 'extraV@rticalExtent', str)
891                 str = re.sub ('extraVerticalExtent', 'extraV@rticalExtent', str)                
892                 str = re.sub ('VerticalExtent', 'verticalExtent', str)
893                 str = re.sub ('extraV@rticalExtent', 'extraVerticalExtent', str)
894                 str = re.sub ('minimumV@rticalExtent', 'minimumVerticalExtent', str)            
895                 return str
896
897         conversions.append (((1,5,59), conv,
898         'XxxxVerticalExtent -> xxxVerticalExtent'))
899
900 if 1:
901         def conv (str):
902                 str = re.sub ('visibility-lambda', 'break-visibility', str)
903                 return str
904
905         conversions.append (((1,5,62), conv,
906         'visibility-lambda -> break-visibility'))
907         
908
909 if 1:
910         def conv (str):
911                 if re.search (r'\addlyrics',str) \
912                        and re.search ('automaticMelismata', str)  == None:
913                         sys.stderr.write  ('automaticMelismata is turned on by default since 1.5.67. Please fix this by hand.')
914                         raise FatalConversionError()
915                 return str
916
917         conversions.append (((1,5,67), conv,
918                              'automaticMelismata turned on by default'))
919
920 if 1:
921         def conv (str):
922                 str = re.sub ('ly-set-grob-property([^!])', 'ly-set-grob-property!\1', str)
923                 str = re.sub ('ly-set-mus-property([^!])', 'ly-set-mus-property!\1', str)               
924                 return str
925         
926         conversions.append (((1,5,68), conv, 'ly-set-X-property -> ly-set-X-property!'))
927
928 if 1:
929         def conv (str):
930                 str = re.sub ('extent-X', 'X-extent', str)
931                 str = re.sub ('extent-Y', 'Y-extent', str)              
932                 return str
933         
934         conversions.append (((1,5,71), conv, 'extent-[XY] -> [XY]-extent'))
935
936
937 if 1:
938         def conv (str):
939                 str = re.sub ("""#\(set! +point-and-click +line-column-location\)""",
940                               """#(set-point-and-click! \'line-column)""", str)
941                 str = re.sub ("""#\(set![ \t]+point-and-click +line-location\)""",
942                               '#(set-point-and-click! \'line)', str)
943                 str = re.sub ('#\(set! +point-and-click +#f\)',
944                               '#(set-point-and-click! \'none)', str)
945                 return str
946         
947         conversions.append (((1,5,72), conv, 'set! point-and-click -> set-point-and-click!'))
948
949
950 if 1:
951         def conv (str):
952                 str = re.sub ('flag-style', 'stroke-style', str)
953                 str = re.sub (r"""Stem([ ]+)\\override #'style""", r"""Stem \\override #'flag-style""", str);
954                 str = re.sub (r"""Stem([ ]+)\\set([ ]+)#'style""", r"""Stem \\set #'flag-style""", str);
955                 return str
956         
957         conversions.append (((1,6,5), conv, 'Stems: flag-style -> stroke-style; style -> flag-style'))
958
959
960 if 1:
961         def subst_req_name (match):
962                 return "(make-music-by-name \'%sEvent)" % regularize_id (match.group(1))
963
964         def conv (str):
965                 str = re.sub ('\\(ly-make-music *\"([A-Z][a-z_]+)_req\"\\)', subst_req_name, str)
966                 str = re.sub ('Request_chord', 'EventChord', str)
967                 return str
968         
969         conversions.append (((1,7,1), conv, 'ly-make-music foo_bar_req -> make-music-by-name FooBarEvent'))
970
971
972 if 1:
973         spanner_subst ={
974                 "text" : 'TextSpanEvent',
975                 "decrescendo" : 'DecrescendoEvent',
976                 "crescendo" : 'CrescendoEvent',
977                 "Sustain" : 'SustainPedalEvent',
978                 "slur" : 'SlurEvent',
979                 "UnaCorda" : 'UnaCordaEvent',
980                 "Sostenuto" : 'SostenutoEvent',
981                 }
982         def subst_ev_name (match):
983                 stype = 'STOP'
984                 if re.search ('start', match.group(1)):
985                         stype= 'START'
986
987                 mtype = spanner_subst[match.group(2)]
988                 return "(make-span-event '%s %s)" % (mtype , stype)
989
990         def subst_definition_ev_name(match):
991                 return ' = #%s' % subst_ev_name (match)
992         def subst_inline_ev_name (match):
993                 s = subst_ev_name (match)
994                 return '#(ly-export %s)' % s
995         def subst_csp_definition (match):
996                 return ' = #(make-event-chord (list %s))' % subst_ev_name (match)
997         def subst_csp_inline (match):
998                 return '#(ly-export (make-event-chord (list %s)))' % subst_ev_name (match)
999                 
1000         def conv (str):
1001                 str = re.sub (r' *= *\\spanrequest *([^ ]+) *"([^"]+)"', subst_definition_ev_name, str)
1002                 str = re.sub (r'\\spanrequest *([^ ]+) *"([^"]+)"', subst_inline_ev_name, str)
1003                 str = re.sub (r' *= *\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_definition, str)
1004                 str = re.sub (r'\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_inline, str)
1005                 str = re.sub (r'ly-id ', 'ly-import ', str)
1006
1007                 str = re.sub (r' *= *\\script "([^"]+)"', ' = #(make-articulation "\\1")', str)
1008                 str = re.sub (r'\\script "([^"]+)"', '#(ly-export (make-articulation "\\1"))', str)
1009                 return str
1010
1011         conversions.append (((1,7,2), conv, '\\spanrequest -> #(make-span-event .. ), \script -> #(make-articulation .. )'))
1012
1013 if 1:
1014         def conv(str):
1015                 str = re.sub (r'\(ly-', '(ly:', str)
1016
1017                 changed = [
1018                         r'duration\?',
1019                         r'font-metric\?',
1020                         r'molecule\?',
1021                         r'moment\?',
1022                         r'music\?',
1023                         r'pitch\?',
1024                         'make-duration',
1025                         'music-duration-length',
1026                         'duration-log',
1027                         'duration-dotcount',
1028                         'intlog2',
1029                         'duration-factor',
1030                         'transpose-key-alist',
1031                         'get-system',
1032                         'get-broken-into',
1033                         'get-original',
1034                         'set-point-and-click!',
1035                         'make-moment',
1036                         'make-pitch',
1037                         'pitch-octave',
1038                         'pitch-alteration',
1039                         'pitch-notename',
1040                         'pitch-semitones',
1041                         r'pitch<\?',
1042                         r'dir\?',
1043                         'music-duration-compress',
1044                         'set-point-and-click!'
1045                         ]
1046
1047                 origre = r'\b(%s)' % string.join (changed, '|')
1048                 
1049                 str = re.sub (origre, r'ly:\1',str)
1050                 str = re.sub ('set-point-and-click!', 'set-point-and-click', str)
1051                 
1052                 return str
1053         
1054         conversions.append (((1,7,3), conv, 'ly- -> ly:'))
1055
1056 if 1:
1057         def conv(str):
1058                 if re.search ('new-chords-done',str):
1059                         return str
1060                 
1061                 str = re.sub (r'<<', '< <', str)
1062                 str = re.sub (r'>>', '> >', str)
1063                 return str
1064         
1065         conversions.append (((1,7,4), conv, '<< >> -> < <  > >'))
1066
1067 if 1:
1068         def conv(str):
1069                 str = re.sub (r"\\transpose", r"\\transpose c'", str)
1070                 str = re.sub (r"\\transpose c' *([a-z]+)'", r"\\transpose c \1", str)
1071                 return str
1072         conversions.append (((1,7,5), conv, '\\transpose TO -> \\transpose FROM  TO'))
1073
1074 if 1:
1075         def conv(str):
1076                 kws =   ['arpeggio',
1077                          'sustainDown',
1078                          'sustainUp',
1079                          'f',
1080                          'p',
1081                          'pp',
1082                          'ppp',
1083                          'fp',
1084                          'ff',
1085                          'mf',
1086                          'mp',
1087                          'sfz',
1088                          ]
1089
1090                 origstr = string.join (kws, '|')
1091                 str = re.sub (r'([^_^-])\\(%s)\b' % origstr, r'\1-\\\2', str)
1092                 return str
1093         conversions.append (((1,7,6), conv, 'note\\script -> note-\script'))
1094
1095
1096 if 1:
1097         def conv(str):
1098                 str = re.sub (r"\\property *ChordNames *\. *ChordName *\\(set|override) *#'style *= *#('[a-z]+)",
1099                               r"#(set-chord-name-style \2)", str)
1100                 str = re.sub (r"\\property *ChordNames *\. *ChordName *\\revert *#'style",
1101                               r"", str)
1102                 return str
1103         conversions.append (((1,7,10), conv, "\property ChordName #'style -> #(set-chord-name-style 'style)"))
1104         
1105
1106
1107 if 1:
1108         def conv(str):
1109                 str = re.sub (r"ly:transpose-pitch", "ly:pitch-transpose", str)
1110                 
1111                 return str
1112         conversions.append (((1,7,11), conv, "transpose-pitch -> pitch-transpose"))
1113
1114 if 1:
1115         def conv(str):
1116                 str = re.sub (r"ly:get-molecule-extent", "ly:molecule-get-extent", str)
1117                 str = re.sub (r"ly:set-molecule-extent!", "ly:molecule-set-extent!", str)
1118                 str = re.sub (r"ly:add-molecule", "ly:molecule-add", str)
1119                 str = re.sub (r"ly:combine-molecule-at-edge", "ly:molecule-combine-at-edge", str)
1120                 str = re.sub (r"ly:align-to!", "ly:molecule-align-to!", str)
1121                 
1122                 return str
1123         
1124         conversions.append (((1,7,13), conv, "ly:XX-molecule-YY -> ly:molecule-XX-YY")) 
1125
1126 if 1:
1127         def conv(str):
1128                 str = re.sub (r"linewidth *= *-[0-9.]+ *(\\mm|\\cm|\\in|\\pt)?", 'raggedright = ##t', str )
1129                 return str
1130         
1131         conversions.append (((1,7,15), conv, "linewidth = -1 -> raggedright = ##t"))    
1132
1133 if 1:
1134         def conv(str):
1135                 str = re.sub ("divisiomaior",
1136                               "divisioMaior", str)
1137                 str = re.sub ("divisiominima",
1138                               "divisioMinima", str)
1139                 str = re.sub ("divisiomaxima",
1140                               "divisioMaxima", str)
1141                 return str
1142         
1143         conversions.append (((1,7,16), conv, "divisiomaior -> divisioMaior"))
1144
1145 if 1:
1146         def conv(str):
1147                 str = re.sub ("Skip_req_swallow_translator",
1148                               "Skip_event_swallow_translator", str)
1149                 return str
1150         
1151         conversions.append (((1,7,17), conv, "Skip_req  -> Skip_event"))
1152
1153 if 1:
1154         def conv(str):
1155                 str = re.sub ("groupOpen",
1156                               "startGroup", str)
1157                 str = re.sub ("groupClose",
1158                               "stopGroup", str)
1159                 str = re.sub ("#'outer",
1160                               "#'enclose-bounds", str)
1161
1162                 return str
1163         
1164         conversions.append (((1,7,18), conv,
1165                              """groupOpen/Close  -> start/stopGroup,
1166                              #'outer  -> #'enclose-bounds
1167                              """))
1168
1169 if 1:
1170         def conv(str):
1171                 if re.search( r'\\GraceContext', str):
1172                         sys.stderr.write ("GraceContext has been removed")
1173                         sys.stderr.write ("please use #(add-to-grace-init .. )")
1174                         raise FatalConversionError()
1175
1176                 str = re.sub ('HaraKiriStaffContext', 'RemoveEmptyStaffContext', str)
1177                 return str
1178         
1179         conversions.append (((1,7,19), conv,"remove GraceContext"))
1180
1181
1182
1183 if 1:
1184         def conv(str):
1185                 str = re.sub (
1186                         r"(set|override|revert) *#'type",
1187                         r"\1 #'style",
1188                         str)
1189                 return str
1190         
1191         conversions.append (((1,7,22), conv,"#'type -> #'style"))
1192
1193 if 1:
1194         def conv(str):
1195                 str = re.sub (
1196                         "barNonAuto *= *##t",
1197                         "automaticBars = ##f",
1198                         str)
1199                 str = re.sub (
1200                         "barNonAuto *= *##f",
1201                         "automaticBars = ##t",
1202                         str)
1203                 return str
1204         
1205         conversions.append (((1,7,23), conv,"barNonAuto -> automaticBars"))
1206         
1207
1208 if 1:
1209         def conv(str):
1210                 if re.search( r'-(start|stop)Cluster', str):
1211                         sys.stderr.write ("""Cluster syntax has been changed.
1212 Please refer to the manual for details, and convert manually.
1213 """)
1214                         
1215                         raise FatalConversionError()
1216
1217                 return str
1218         
1219         conversions.append (((1,7,24), conv,"cluster syntax"))
1220
1221 if 1:
1222         def conv(str):
1223                 str = re.sub (r"\\property *Staff\.(Sustain|Sostenuto|UnaCorda)Pedal *\\(override|set) *#'pedal-type *",
1224                                 r"\property Staff.pedal\1Style ", str)
1225                 str = re.sub (r"\\property *Staff\.(Sustain|Sostenuto|UnaCorda)Pedal *\\revert *#'pedal-type", '', str)
1226                 return str
1227         
1228         conversions.append (((1,7,28), conv,"new Pedal style syntax"))
1229
1230
1231
1232 if 1:
1233
1234         def sub_chord (m):
1235                 str = m.group(1)
1236
1237                 origstr =  '<%s>' % str
1238                 if re.search (r'\\\\', str):
1239                         return origstr
1240
1241                 if re.search (r'\\property', str):
1242                         return origstr
1243
1244                 if re.match (r'^\s*\)?\s*\\[a-zA-Z]+', str):
1245                         return origstr
1246
1247                 durs = []
1248                 def sub_durs (m, durs = durs):
1249                         durs.append(m.group(2))
1250                         return m.group (1)
1251
1252                 str = re.sub (r"([a-z]+[,'!? ]*)([0-9]+\.*)", sub_durs, str)
1253                 dur_str = ''
1254
1255                 for d in durs:
1256                         if dur_str == '':
1257                                 dur_str = d
1258                         if dur_str <> d:
1259                                 return '<%s>' % m.group (1)
1260
1261                 pslur_strs = ['']
1262                 dyns = ['']
1263                 slur_strs = ['']
1264
1265                 last_str = ''
1266                 while last_str <> str:
1267                         last_str = str
1268
1269                         def sub_tremolos (m, slur_strs = slur_strs):
1270                                 tr = m.group (2)
1271                                 if tr not in slur_strs:
1272                                         slur_strs.append (tr)
1273                                 return  m.group (1)
1274                         
1275                         str = re.sub (r"([a-z]+[',!? ]*)(:[0-9]+)",
1276                                       sub_tremolos, str)
1277
1278                         def sub_dyn_end (m, dyns = dyns):
1279                                 dyns.append (' \!')
1280                                 return ' ' + m.group(2)
1281
1282                         str = re.sub (r'(\\!)\s*([a-z]+)', sub_dyn_end, str)
1283                         def sub_slurs(m, slur_strs = slur_strs):
1284                                 if '-)' not in slur_strs:
1285                                         slur_strs.append (')')
1286                                 return m.group(1)
1287                         
1288                         def sub_p_slurs(m, slur_strs = slur_strs):
1289                                 if '-\)' not in slur_strs:
1290                                         slur_strs.append ('\)')
1291                                 return m.group(1)
1292                         
1293                         str = re.sub (r"\)[ ]*([a-z]+)", sub_slurs, str)
1294                         str = re.sub (r"\\\)[ ]*([a-z]+)", sub_p_slurs, str)
1295                         def sub_begin_slurs(m, slur_strs = slur_strs):
1296                                 if '-(' not in slur_strs:
1297                                         slur_strs.append ('(')
1298                                 return m.group(1)
1299                         
1300                         str = re.sub (r"([a-z]+[,'!?0-9 ]*)\(",
1301                                       sub_begin_slurs, str)
1302                         def sub_begin_p_slurs(m, slur_strs = slur_strs):
1303                                 if '-\(' not in slur_strs:
1304                                         slur_strs.append ('\(')
1305                                 return m.group(1)
1306
1307                         str = re.sub (r"([a-z]+[,'!?0-9 ]*)\\\(",
1308                                 sub_begin_p_slurs, str)
1309
1310                         def sub_dyns (m, slur_strs = slur_strs):
1311                                 s = m.group(0)
1312                                 if s == '@STARTCRESC@':
1313                                         slur_strs.append ("\\<")
1314                                 elif s == '@STARTDECRESC@':
1315                                         slur_strs.append ("\\>")
1316                                 elif s == r'-?\\!':
1317                                         slur_strs.append ('\\!')
1318                                 return ''
1319
1320                         str = re.sub (r'@STARTCRESC@', sub_dyns, str)
1321                         str = re.sub (r'-?\\!', sub_dyns, str)
1322
1323                         def sub_articulations (m, slur_strs = slur_strs):
1324                                 a = m.group(1)
1325                                 if a not in slur_strs:
1326                                         slur_strs.append (a)
1327                                 return ''
1328
1329                         str = re.sub (r"([_^-]\@ACCENT\@)", sub_articulations,
1330                                       str)
1331                         str = re.sub (r"([_^-]\\[a-z]+)", sub_articulations,
1332                                       str)
1333                         str = re.sub (r"([_^-][>_.+|^-])", sub_articulations,
1334                                       str)
1335                         str = re.sub (r'([_^-]"[^"]+")', sub_articulations,
1336                                       str)
1337
1338                         def sub_pslurs(m, slur_strs = slur_strs):
1339                                 slur_strs.append (' \\)')
1340                                 return m.group(1)
1341                         str = re.sub (r"\\\)[ ]*([a-z]+)", sub_pslurs, str)
1342
1343                 ## end of while <>
1344
1345                 suffix = string.join (slur_strs, '') + string.join (pslur_strs,
1346                                                                     '') \
1347                          + string.join (dyns, '')
1348
1349                 return '@STARTCHORD@%s@ENDCHORD@%s%s' % (str , dur_str, suffix)
1350
1351
1352
1353         def sub_chords (str):
1354                 simend = '>'
1355                 simstart = '<'
1356                 chordstart = '<<'
1357                 chordend = '>>'
1358                 marker_str = '%% new-chords-done %%'
1359
1360                 if re.search (marker_str,str):
1361                         return str
1362                 str = re.sub ('<<', '@STARTCHORD@', str)
1363                 str = re.sub ('>>', '@ENDCHORD@', str)
1364                 
1365                 str = re.sub (r'\\<', '@STARTCRESC@', str)
1366                 str = re.sub (r'\\>', '@STARTDECRESC@', str)
1367                 str = re.sub (r'([_^-])>', r'\1@ACCENT@', str)
1368                 str = re.sub (r'<([^<>{}]+)>', sub_chord, str)
1369
1370                 # add dash: -[, so that [<<a b>> c d] becomes
1371                 #                      <<a b>>-[ c d]
1372                 # and gets skipped by articulation_substitute
1373                 str = re.sub (r'\[ *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1374                               r'\1-[', str)
1375                 str = re.sub (r'\\! *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1376                               r'\1-\\!', str)
1377                 
1378                 str = re.sub (r'<([^?])', r'%s\1' % simstart, str)
1379                 str = re.sub (r'>([^?])', r'%s\1' % simend,  str)
1380                 str = re.sub ('@STARTCRESC@', r'\\<', str)
1381                 str = re.sub ('@STARTDECRESC@', r'\\>' ,str)
1382                 str = re.sub (r'\\context *Voice *@STARTCHORD@',
1383                               '@STARTCHORD@', str)
1384                 str = re.sub ('@STARTCHORD@', chordstart, str)
1385                 str = re.sub ('@ENDCHORD@', chordend, str)
1386                 str = re.sub (r'@ACCENT@', '>', str)
1387                 return str
1388
1389         def text_markup (str):
1390                 str = re.sub (r"""([-_^]) *# *' *\( *music *(\"[^"]*\") *\)""",
1391                                 r"\1\\markup { \\musicglyph #\2 }", str)
1392                 str = re.sub (r"""([-_^]) *# *' *\( *([a-z]+) *([^()]*)\)""",
1393                                 r"\1\\markup { \\\2 \3 }", str)
1394                 str = re.sub (r"""\\mark *# *' *\( *music *(\"[^"]*\") *\)""",
1395                                 r"\\mark \\markup { \\musicglyph #\1 }", str)
1396                 str = re.sub (r"""\\mark *# *' *\( *([a-z]+) *([^()]*)\)""",
1397                                 r"\\mark \\markup { \\\1 \2 }", str)
1398                 return str      
1399
1400         def articulation_substitute (str):
1401                 str = re.sub (r"""([^-])\[ *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1402                               r"\1 \2[", str)
1403                 str = re.sub (r"""([^-])\\\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1404                               r"\1 \2\\)", str)
1405                 str = re.sub (r"""([^-\\])\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1406                               r"\1 \2)", str)
1407                 str = re.sub (r"""([^-])\\! *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1408                               r"\1 \2\\!", str)
1409                 return str
1410         
1411         def conv_relative(str):
1412                 if re.search (r"\\relative", str):
1413                         str= "#(ly:set-option 'old-relative)\n" + str
1414
1415                 return str
1416         
1417         def conv (str):
1418                 str = re.sub (r"#'\(\)", "@SCM_EOL@", str)
1419                 str =  conv_relative (str)
1420                 str = sub_chords (str)
1421
1422                 str = text_markup (str)
1423                 str = articulation_substitute (str)
1424                 str = re.sub ("@SCM_EOL@", "#'()", str)
1425                 
1426                 return str
1427         
1428         conversions.append (((1,9,0), conv, """New relative mode,
1429 Postfix articulations, new text markup syntax, new chord syntax."""))
1430
1431 if 1:
1432         def conv (str):
1433                 if re.search ("font-style",str):
1434                         sys.stderr.write ("font-style is deprecated. Please remove.")
1435                         raise FatalConversionError()
1436                         
1437                 str = re.sub (r'-\\markup', r'@\\markup', str)
1438                 str = re.sub (r'-\\', r'\\', str)
1439                 str = re.sub (r'-\)', ')', str)
1440                 str = re.sub (r'-\(', '(', str)
1441                 str = re.sub ('-\[', '[', str)
1442                 str = re.sub ('-\]', ']', str)
1443                 str = re.sub ('-~', '~', str)
1444                 str = re.sub (r'@\\markup', r'-\\markup', str)
1445                 return str
1446
1447         conversions.append (((1,9,1), conv, """Remove - before articulation"""))
1448 if 1:
1449         def conv (str):
1450                 str = re.sub ('ly:set-context-property',
1451                               'ly:set-context-property!', str)
1452                 str = re.sub ('\\\\newcontext', '\\\\new', str)
1453                 str = re.sub ('\\\\grace[\t\n ]*([^{ ]+)',
1454                               r'\\grace { \1 }', str)
1455                 str = re.sub ("\\\\grace[\t\n ]*{([^}]+)}",
1456                               r"""\\grace {
1457   \\property Voice.Stem \\override #'stroke-style = #"grace"
1458   \1
1459   \\property Voice.Stem \\revert #'stroke-style }
1460 """, str)
1461                 
1462                 return str
1463         
1464         conversions.append (((1,9,2), conv, """\\newcontext -> \\new"""))
1465
1466 if 1:
1467         def conv (str):
1468                 str = re.sub ('accacciatura',
1469                               'acciaccatura', str)
1470
1471                 if re.search ("context-spec-music", str):
1472                         sys.stderr.write ("context-spec-music takes a symbol for the context now. Update by hand.")
1473                                         
1474                         raise FatalConversionError()
1475                 
1476                 str = re.sub ('fingerHorizontalDirection *= *#(LEFT|-1)',
1477                               "fingeringOrientations = #'(up down left)", str)
1478                 str = re.sub ('fingerHorizontalDirection *= *#(RIGHT|1)',
1479                               "fingeringOrientations = #'(up down right)", str)
1480
1481                 return str
1482         
1483         conversions.append (((1,9,3), conv,
1484                              """\\acciaccatura misspelling, fingerHorizontalDirection -> fingeringOrientations"""))
1485
1486
1487 def conv (str):
1488         if re.search ('\\figures', str):
1489                 sys.stderr.write ("Warning: attempting automatic \\figures conversion.  Check results!");
1490                 
1491         
1492         def figures_replace (m):
1493                 s = m.group (1)
1494                 s = re.sub ('<', '@FIGOPEN@',s)
1495                 s = re.sub ('>', '@FIGCLOSE@',s)
1496                 return '\\figures { %s }' % s
1497         
1498         str = re.sub (r'\\figures[ \t\n]*{([^}]+)}', figures_replace, str)
1499         str = re.sub (r'\\<', '@STARTCRESC@', str)
1500         str = re.sub (r'\\>', '@STARTDECRESC@', str)
1501         str = re.sub (r'([-^_])>', r'\1@ACCENT@', str)
1502         str = re.sub (r'<<', '@STARTCHORD@', str)
1503         str = re.sub (r'>>', '@ENDCHORD@', str)
1504         str = re.sub (r'>', '@ENDSIMUL@', str)
1505         str = re.sub (r'<', '@STARTSIMUL@', str)
1506         str = re.sub ('@STARTDECRESC@', '\\>', str)
1507         str = re.sub ('@STARTCRESC@', '\\<', str)
1508         str = re.sub ('@ACCENT@', '>', str)
1509         str = re.sub ('@ENDCHORD@', '>', str)
1510         str = re.sub ('@STARTCHORD@', '<', str)
1511         str = re.sub ('@STARTSIMUL@', '<<', str)
1512         str = re.sub ('@ENDSIMUL@', '>>', str)
1513         str = re.sub ('@FIGOPEN@', '<', str)
1514         str = re.sub ('@FIGCLOSE@', '>', str)
1515
1516         return str
1517
1518 conversions.append (((1,9,4), conv, 'Swap < > and << >>'))
1519
1520
1521 def conv (str):
1522         str = re.sub ('HaraKiriVerticalGroup', 'RemoveEmptyVerticalGroup', str)
1523
1524         return str
1525
1526 conversions.append (((1,9,5), conv, 'HaraKiriVerticalGroup -> RemoveEmptyVerticalGroup'))
1527
1528 def conv (str):
1529         if re.search ("ly:get-font", str) :
1530                 sys.stderr.write (r"(ly:get-font foo ..)  has been replaced by" + \
1531                                   " (ly:paper-get-font (ly:grob-get-paper foo) .. ).\n" +\
1532                                   "please update manually.")
1533                 
1534                 raise FatalConversionError()
1535         
1536         if re.search ("\\pitch *#", str) :
1537                 sys.stderr.write (r"\\pitch has been deprecated. " +\
1538                                   " Use Scheme code to construct arbitrary note events.")
1539                 
1540                 raise FatalConversionError()
1541         
1542         return str
1543                 
1544
1545 conversions.append (((1,9,6), conv, 'ly:get-font deprecated.'))
1546
1547 def conv (str):
1548         def sub_alteration (m):
1549                 alt = m.group (3)
1550                 alt = {
1551                         '-1': 'FLAT',
1552                         '-2': 'DOUBLE-FLAT',
1553                         '0': 'NATURAL',
1554                         '1': 'SHARP',
1555                         '2': 'DOUBLE-SHARP',
1556                         }[alt]
1557                 
1558                 return '(ly:make-pitch %s %s %s)' % (m.group(1), m.group (2),
1559                                                      alt)
1560         
1561         str =re.sub ("\\(ly:make-pitch *([0-9-]+) *([0-9-]+) *([0-9-]+) *\\)",
1562                      sub_alteration, str)
1563
1564
1565         str = re.sub ("ly:verbose", "ly:get-option 'verbose", str)
1566
1567         m= re.search ("\\\\outputproperty #([^#]+)[\t\n ]*#'([^ ]+)", str)
1568         if m:
1569                 sys.stderr.write (\
1570                         r"""\outputproperty found,
1571 Please hand-edit, using
1572
1573   \applyoutput #(outputproperty-compatibility %s '%s <GROB PROPERTY VALUE>)
1574
1575 as a substitution text.""" % (m.group (1), m.group (2)) )
1576                 raise FatalConversionError ()
1577
1578         if re.search ("ly:(make-pitch|pitch-alteration)", str) \
1579                or re.search ("keySignature", str):
1580                 sys.stderr.write (
1581 """The alteration field of Scheme pitches was multiplied by 2
1582 to support quarter tone accidentals. You have to edit the following constructs by hand:
1583
1584 * calls of  ly:make-pitch and ly:pitch-alteration
1585 * keySignature settings made with \property
1586 """)
1587                 raise FatalConversionError ()
1588         
1589         return str
1590 conversions.append (((1,9,7), conv,
1591                      '''use symbolic constants for alterations,
1592 remove \\outputproperty, move ly:verbose into ly:get-option'''))
1593
1594
1595 def conv (str):
1596         if re.search ("dash-length",str):
1597                 sys.stderr.write ("""dash-length has been removed. Use dash-fraction instead.""")
1598                 raise FatalConversionError()
1599         return str
1600
1601 conversions.append (((1,9,8), conv, """dash-length -> dash-fraction"""))
1602
1603
1604 def conv (str):
1605         def func(match):
1606                 return "#'font-size = #%d" % (2*string.atoi (match.group (1))) 
1607                 
1608         str =re.sub (r"#'font-relative-size\s*=\s*#\+?([0-9-]+)", func, str)
1609         str =re.sub (r"#'font-family\s*=\s*#'ancient",
1610                      r"#'font-family = #'music", str)
1611         
1612         return str
1613
1614 conversions.append (((2,1,1), conv, """font-relative-size -> font-size"""))
1615
1616 def conv (str):
1617         str =re.sub (r"ly:get-music-length", "ly:music-length", str)
1618         return str
1619
1620 conversions.append (((2,1,2), conv, """ly:get-music-length -> ly:music-length"""))
1621
1622 def conv (str):
1623         str =re.sub (r"\.\s+stz=", ". instr ", str)
1624         return str
1625
1626 conversions.append (((2,1,3), conv, """stanza -> instrument"""))
1627
1628 def conv (str):
1629         def func (match):
1630                 c = match.group (1)
1631                 b = match.group (2)
1632                 
1633                 if b == 't':
1634                         if c == 'Score':
1635                                 return ''
1636                         else:
1637                                 return r" \property %s.melismaBusyProperties \unset"  % c
1638                 elif b == 'f':
1639                         return r"\property %s.melismaBusyProperties = #'(melismaBusy)"  % c
1640                 
1641         str =re.sub (r"\\property ([a-zA-Z]+)\s*\.\s*automaticMelismata\s*=\s*##([ft])", func, str)
1642         return str
1643
1644 conversions.append (((2,1,4), conv, """removal of automaticMelismata; use melismaBusyProperties instead."""))
1645
1646
1647
1648 def conv (str):
1649         str =re.sub (r"\\translator\s+([a-zA-Z]+)", r"\\change \1", str)
1650         return str
1651
1652 conversions.append (((2,1,7), conv, """\\translator Staff -> \\change Staff"""))
1653
1654 def conv (str):
1655         str =re.sub (r"\\newaddlyrics", r"\\lyricsto", str)
1656         return str
1657
1658 conversions.append (((2,1,10), conv, """\\newaddlyrics -> \\lyricsto"""))
1659
1660 def conv (str):
1661         str = re.sub (r'\\include\s*"paper([0-9]+)(-init)?.ly"',
1662                       r"#(set-staff-size \1)", str)
1663
1664         def sub_note (match):
1665                 dur = ''
1666                 log = string.atoi (match.group (1))
1667                 dots = string.atoi (match.group (2))
1668                 
1669                 if log >= 0:
1670                         dur = '%d' % (1 << log)
1671                 else:
1672                         dur = { -1 : 'breve',
1673                                 -2 : 'longa',
1674                                 -3 : 'maxima'}[log]
1675
1676                 dur += ('.' * dots)
1677                 
1678                 return r'\note #"%s" #%s' % (dur, match.group (3))
1679         
1680         str = re.sub (r'\\note\s+#([0-9-]+)\s+#([0-9]+)\s+#([0-9.-]+)',
1681                       sub_note, str)
1682         return str
1683
1684 conversions.append (((2,1,11), conv, """\\include "paper16.ly" -> #(set-staff-size 16)
1685 \\note #3 #1 #1 -> \\note #"8." #1
1686 """))
1687
1688
1689 def conv (str):
1690         str =re.sub (r"OttavaSpanner", r"OttavaBracket", str)
1691         return str
1692
1693 conversions.append (((2,1,12), conv, """OttavaSpanner -> OttavaBracket"""))
1694
1695
1696 def conv (str):
1697         str =re.sub (r"\(set-staff-size ", r"(set-global-staff-size ", str)
1698         return str
1699
1700 conversions.append (((2,1,13), conv, """set-staff-size -> set-global-staff-size"""))
1701
1702 def conv (str):
1703         str =re.sub (r"#'style\s*=\s*#'dotted-line",
1704                      r"#'dash-fraction = #0.0 ", str)
1705         return str
1706
1707 conversions.append (((2,1,14), conv, """style = dotted -> dash-fraction = 0"""))
1708
1709 def conv (str):
1710         str =re.sub (r'LyricsVoice\s*\.\s*instrument\s*=\s*("[^"]*")',
1711                      r'LyricsVoice . vocalName = \1', str)
1712         
1713         str =re.sub (r'LyricsVoice\s*\.\s*instr\s*=\s*("[^"]*")',
1714                      r'LyricsVoice . vocNam = \1', str)
1715         return str
1716
1717 conversions.append (((2,1,15), conv, """LyricsVoice . instr(ument) -> vocalName"""))
1718
1719 def conv (str):
1720         def sub_acc (m):
1721                 d = {
1722                 '4': 'doublesharp',
1723                 '3': 'threeqsharp',
1724                 '2': 'sharp',
1725                 '1': 'semisharp',
1726                 '0': 'natural',
1727                 '-1': 'semiflat',
1728                 '-2': 'flat',
1729                 '-3': 'threeqflat',
1730                 '-4': 'doubleflat'}
1731                 return '\\%s' %  d[m.group (1)]
1732                      
1733         str = re.sub (r'\\musicglyph\s*#"accidentals-([0-9-]+)"',
1734                       sub_acc, str)
1735         return str
1736
1737 conversions.append (((2,1,16), conv, """\\musicglyph #"accidentals-NUM" -> \\sharp/flat/etc."""))
1738
1739
1740 def conv (str):
1741
1742         if re.search (r'\\partcombine', str):
1743                 sys.stderr.write ('Warning: \\partcombine has been changed. '
1744                                   +'Check conversion manually!')
1745
1746                 raise FatalConversionError()
1747
1748         # this rule doesn't really work,
1749         # too lazy to figure out why.
1750         str = re.sub (r'\\context\s+Voice\s*=\s*one\s*\\partcombine\s+Voice\s*\\context\s+Thread\s*=\s*one(.*)\s*'
1751                       + r'\\context\s+Thread\s*=\s*two',
1752                       '\\\\newpartcombine\n\\1\n', str)
1753         
1754         
1755         return str
1756
1757 conversions.append (((2,1,17), conv, """\\partcombine syntax change to \\newpartcombine"""))
1758
1759
1760 def conv (str):
1761         str = re.sub (r'\\newpartcombine', r'\\partcombine', str)
1762         str = re.sub (r'\\autochange\s+Staff', r'\\autochange ', str)
1763         return str
1764
1765 conversions.append (((2,1,18), conv, """\\newpartcombine -> \\partcombine,
1766 \\autochange Staff -> \\autochange
1767 """))
1768
1769
1770
1771
1772 def conv (str):
1773         str = re.sub (r'\\include "drumpitch-init.ly"','', str)
1774         str = re.sub (r'\\pitchnames ','pitchnames = ', str)
1775         str = re.sub (r'\\chordmodifiers ','chordmodifiers = ', str)
1776         str = re.sub (r'\bdrums\b\s*=','drumContents = ', str)
1777         str = re.sub (r'\\drums\b','\\drumContents ', str)
1778         
1779
1780         if re.search ('drums->paper', str):
1781                 sys.stderr.write ("\nDrum notation found. Check file manually!")
1782                 
1783         str = re.sub (r"""\\apply\s+#\(drums->paper\s+'([a-z]+)\)""",
1784                       r"""\property DrumStaff.drumStyleTable = #\1-style""",
1785                       str)
1786
1787         if re.search ('Thread', str):
1788                 sys.stderr.write ("\nThread found. Check file manually!\n");
1789
1790         str = re.sub (r"""(\\once\s*)?\\property\s+Thread\s*\.\s*NoteHead\s*"""
1791                       + r"""\\(set|override)\s*#'style\s*=\s*#'harmonic"""
1792                       + r"""\s+([a-z]+[,'=]*)([0-9]*\.*)"""                   
1793                       ,r"""<\3\\harmonic>\4""", str)
1794
1795         str = re.sub (r"""\\new Thread""", """\context Voice""", str)
1796         str = re.sub (r"""Thread""", """Voice""", str)
1797
1798         if re.search ('\bLyrics\b', str):
1799                 sys.stderr.write ("\nLyrics found. Check file manually!\n");
1800
1801         str = re.sub (r"""LyricsVoice""", r"""L@ricsVoice""", str)
1802         str = re.sub (r"""\bLyrics\b""", r"""LyricsVoice""", str)
1803         str = re.sub (r"""LyricsContext""", r"""LyricsVoiceContext""", str)
1804         str = re.sub (r"""L@ricsVoice""", r"""LyricsVoice""",str)
1805         
1806         
1807         return str
1808
1809 conversions.append (((2,1,19), conv, """Drum notation changes, Removing \\chordmodifiers, \\notenames.
1810 Harmonic notes. Thread context removed. Lyrics context removed."""))
1811
1812 def conv (str):
1813         str = re.sub (r'nonevent-skip', 'skip-music', str)
1814         return str
1815
1816 conversions.append (((2,1,20), conv, """nonevent-skip -> skip-music""" ))
1817
1818 def conv (str):
1819         str = re.sub (r'molecule-callback', 'print-function', str)
1820         str = re.sub (r'brew_molecule', 'print', str)
1821         str = re.sub (r'brew-new-markup-molecule', 'Text_item::print', str)
1822         str = re.sub (r'LyricsVoice', 'Lyrics', str)
1823         str = re.sub (r'tupletInvisible',
1824                       r"TupletBracket \\set #'transparent", str)
1825 #       str = re.sub (r'molecule', 'collage', str)
1826 #molecule -> collage
1827         str = re.sub (r"\\property\s+[a-zA-Z]+\s*\.\s*[a-zA-Z]+\s*"
1828                       + r"\\set\s*#'X-extent-callback\s*=\s*#Grob::preset_extent",
1829                       "", str)
1830
1831         return str
1832
1833 conversions.append (((2,1,21), conv, """molecule-callback -> print-function,
1834 brew_molecule -> print
1835 brew-new-markup-molecule -> Text_item::print
1836 LyricsVoice -> Lyrics
1837 tupletInvisible -> TupletBracket \set #'transparent
1838 Grob::preset_extent removed.
1839 """ ))
1840
1841
1842 def conv (str):
1843         str = re.sub (r'(\\property[^=]+)=\s*([-0-9]+)',
1844                       r'\1= #\2', str) 
1845         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\=]+)\s*\\(set|override)',
1846                       r"\\overrid@ \1.\2 ", str)
1847         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*=\s*',
1848                       r'\\s@t \1.\2 = ', str)
1849         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\unset',
1850                       r'\\uns@t \1.\2 ', str)
1851         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\revert'
1852                       + r"\s*#'([-a-z0-9_]+)",
1853                       r"\\rev@rt \1.\2 #'\3", str)
1854         str = re.sub (r'Voice\.', '', str)
1855         str = re.sub (r'Lyrics\.', '', str)
1856         str = re.sub (r'ChordNames\.', '', str)
1857         
1858         str = re.sub ('rev@rt', 'revert',str)
1859         str = re.sub ('s@t', 'set',str)
1860         str = re.sub ('overrid@', 'override',str)
1861
1862         str = re.sub ('molecule', 'stencil', str)
1863         str = re.sub ('Molecule', 'Stencil', str)
1864         return str
1865
1866 conversions.append (((2,1,22), conv, """new syntax for property settings:
1867         \\set A.B = #C , \\unset A.B
1868         \\override A.B #C = #D, \\revert A.B #C
1869
1870 """))
1871
1872 def conv (str):
1873         def subst_in_trans (match):
1874                 s = match.group (0)
1875                 s = re.sub (r'\s([a-zA-Z]+)\s*\\override',
1876                               r' \\override \1', s)
1877                 s = re.sub (r'\s([a-zA-Z]+)\s*\\set',
1878                               r' \\override \1', s)
1879                 s = re.sub (r'\s([a-zA-Z]+)\s*\\revert',
1880                               r' \\revert \1', s)
1881                 return s
1882         str = re.sub (r'\\(translator|with)\s*{[^}]+}',  subst_in_trans, str)
1883
1884         def sub_abs (m):
1885                 
1886                 context = m.group ('context')
1887                 d = m.groupdict ()
1888                 if context:
1889                         context = " '%s" % context[:-1] # -1: remove . 
1890                 else:
1891                         context = ''
1892
1893                 d['context'] = context
1894                 
1895                 return r"""#(override-auto-beam-setting %(prop)s %(num)s %(den)s%(context)s)""" % d
1896
1897         str = re.sub (r"""\\override\s*(?P<context>[a-zA-Z]+\s*\.\s*)?autoBeamSettings"""
1898                       +r"""\s*#(?P<prop>[^=]+)\s*=\s*#\(ly:make-moment\s+(?P<num>\d+)\s+(?P<den>\d)\s*\)""",
1899                       sub_abs, str)
1900         
1901         return str
1902         
1903 conversions.append (((2,1,23), conv, """Property setting syntax in \\translator{ }"""))
1904 def conv (str):
1905         str = re.sub (r'music-list\?', 'ly:music-list?', str)
1906         str = re.sub (r'\|\s*~', '~ |', str)   
1907         return str
1908
1909 conversions.append (((2,1,24), conv, """music-list? -> ly:music-list?"""))
1910
1911 def conv (str):
1912         str = re.sub (r'ly:get-spanner-bound', 'ly:spanner-get-bound', str)
1913         str = re.sub (r'ly:get-extent', 'ly:grob-extent', str)
1914         str = re.sub (r'ly:get-system', 'ly:grob-system', str)
1915         str = re.sub (r'ly:get-original', 'ly:grob-original', str)
1916         str = re.sub (r'ly:get-parent', 'ly:grob-parent', str)
1917         str = re.sub (r'ly:get-broken-into', 'ly:spanner-broken-into', str)
1918         str = re.sub (r'Melisma_engraver', 'Melisma_translator', str)
1919         if re.search ("ly:get-paper-variable", str):
1920                 sys.stderr.write ('use (ly:paper-lookup (ly:grob-paper ))')
1921                 raise FatalConversionError()
1922
1923         str = re.sub (r'\\defaultAccidentals', "#(set-accidental-style 'default)", str)
1924         str = re.sub (r'\\voiceAccidentals', "#(set-accidental-style 'voice)", str)
1925         str = re.sub (r'\\modernAccidentals', "#(set-accidental-style 'modern)", str)
1926         str = re.sub (r'\\modernCautionaries', "#(set-accidental-style 'modern-cautionary)", str)
1927         str = re.sub (r'\\modernVoiceAccidental', "#(set-accidental-style 'modern-voice)", str)
1928         str = re.sub (r'\\modernVoiceCautionaries', "#(set-accidental-style 'modern-voice-cautionary)", str)
1929         str = re.sub (r'\\pianoAccidentals', "#(set-accidental-style 'piano)", str)
1930         str = re.sub (r'\\pianoCautionaries', "#(set-accidental-style 'piano-cautionary)", str)
1931         str = re.sub (r'\\forgetAccidentals', "#(set-accidental-style 'forget)", str)
1932         str = re.sub (r'\\noResetKey', "#(set-accidental-style 'no-reset)", str)
1933         
1934         return str
1935
1936 conversions.append (((2,1,25), conv, """Scheme grob function renaming"""))
1937
1938
1939 def conv (str):
1940         str = re.sub ('ly:set-grob-property!', 'ly:grob-set-property!',str)
1941         str = re.sub ('ly:set-mus-property!', 'ly:music-set-property!',str)     
1942         str = re.sub ('ly:set-context-property!', 'ly:context-set-property!', str)      
1943         str = re.sub ('ly:get-grob-property', 'ly:grob-property',str)
1944         str = re.sub ('ly:get-mus-property', 'ly:music-property',str)
1945         str = re.sub ('ly:get-context-property', 'ly:context-property',str)
1946         
1947         return str
1948
1949 conversions.append (((2,1,26), conv, """More Scheme function renaming"""))
1950
1951 def conv (str):
1952         def subst (m):
1953                 g = string.atoi (m.group (2))
1954                 o = g / 12
1955                 g -= o * 12
1956                 if g <  0:
1957                         g += 12
1958                         o -= 1
1959
1960
1961                 lower_pitches = filter (lambda x : x <= g, [0, 2, 4, 5, 7, 9, 11, 12])
1962                 s = len (lower_pitches) -1 
1963                 a = g - lower_pitches [-1]
1964
1965
1966                 print s , lower_pitches, g, a, s 
1967                 str = 'cdefgab' [s]
1968                 str += ['eses', 'es', '', 'is', 'isis'][a + 2]
1969                 if o < 0:
1970                         str += ',' * (-o - 1)
1971                 elif o >= 0:
1972                         str += "'" * (o + 1)
1973                         
1974                 return '\\transposition %s ' % str
1975
1976         
1977         str = re.sub (r"\\set ([A-Za-z]+\s*\.\s*)?transposing\s*=\s*#([-0-9]+)",
1978                       subst, str)
1979         return str
1980
1981 conversions.append (((2,1,27), conv, """property transposing -> tuning"""))
1982
1983 def conv (str):
1984         str = re.sub (r'make-music-by-name', 'make-music', str)
1985         str = re.sub (r"\\override\s+.*Arpeggio\s+#.print-function\s+=\s+\\arpeggioBracket", r"\\arpeggioBracket", str)
1986         return str
1987
1988 conversions.append (((2,1,28), conv,
1989                      """make-music-by-name -> make-music,
1990 new syntax for setting \\arpeggioBracket"""))
1991
1992 def conv (str):
1993         str = re.sub (r'\\center([^-])', '\\center-align\\1', str)
1994         str = re.sub (r'\\translator', '\\context', str)
1995         return str
1996
1997 conversions.append (((2,1,29), conv,
1998                      '\\center -> \\center-align, \\translator -> \\context'))
1999
2000
2001 def conv (str):
2002         str = re.sub (r'\\threeq(flat|sharp)', r'\\sesqui\1', str)
2003         str = re.sub (r'ly:stencil-get-extent',
2004                       'ly:stencil-extent', str)
2005         str = re.sub (r'ly:translator-find',
2006                       'ly:context-find', str)
2007         str = re.sub ('ly:unset-context-property','ly:context-unset-property',
2008                       str)
2009                      
2010         str = re.sub (r'ly:get-mutable-properties',
2011                       'ly:mutable-music-properties',str)
2012         str = re.sub (r'centralCPosition',
2013                       'middleCPosition',str)
2014         return str
2015
2016 conversions.append (((2,1,30), conv,
2017                      '''\\threeq{flat,sharp} -> \\sesqui{flat,sharp}
2018 ly:get-mutable-properties -> ly:mutable-music-properties
2019 centralCPosition -> middleCPosition
2020 ly:unset-context-property -> ly:context-unset-property
2021 ly:translator-find -> ly:context-find
2022 ly:get-stencil-extent -> ly:stencil-extent
2023 '''))
2024
2025
2026 def conv (str):
2027         str = re.sub (r'\\alias\s*"?Timing"?', '', str)
2028         return str
2029
2030 conversions.append (((2,1,31), conv,
2031                      '''remove \\alias Timing'''))
2032
2033 def conv (str):
2034         str = re.sub (r"(\\set\s+)?(?P<context>(Score\.)?)breakAlignOrder\s*=\s*#'(?P<list>[^\)]+)",
2035                       r"\n\\override \g<context>BreakAlignment #'break-align-orders = "
2036                       + "#(make-vector 3 '\g<list>)", str)
2037                       
2038         return str
2039
2040 conversions.append (((2,1,33), conv,
2041                      '''breakAlignOrder -> break-align-orders.'''))
2042
2043 def conv (str):
2044         str = re.sub (r"\(set-paper-size",
2045                       "(set-default-paper-size",str)
2046         return str
2047
2048 conversions.append (((2,1,34), conv,
2049                      '''set-paper-size -> set-default-paper-size.'''))
2050
2051 def conv (str):
2052         str = re.sub (r"ly:mutable-music-properties",
2053                       "ly:music-mutable-properties", str)
2054         return str
2055
2056 conversions.append (((2,1, 36), conv,
2057                      '''ly:mutable-music-properties -> ly:music-mutable-properties'''))
2058
2059
2060
2061 def conv (str):
2062         return str
2063
2064 conversions.append (((2, 2, 0), conv,
2065                      '''clean up version. '''))
2066
2067 def conv (str):
2068         return re.sub (r'\\apply\b', r'\\applymusic', str)
2069
2070 conversions.append (((2, 3, 1), conv,
2071                      '''\\apply -> \\applymusic'''))
2072
2073 def conv (str):
2074         if re.search ('textheight', str):
2075                 sys.stderr.write("\nWarning: tuning of page layout has changed. See reference manual.\n")
2076                 
2077         str = re.sub (r'\\OrchestralScoreContext', '\\Score', str)
2078         def func(m):
2079                 if m.group(1) not in ['RemoveEmptyStaff',
2080                                       'AncientRemoveEmptyStaffContext',
2081                                       'EasyNotation']:
2082                         return '\\' + m.group (1)
2083                 else:
2084                         return m.group (0)
2085                 
2086                 
2087         str = re.sub (r'\\([a-zA-Z]+)Context\b', func, str)
2088
2089         str = re.sub ('ly:paper-lookup', 'ly:output-def-lookup', str)
2090         return str
2091
2092 conversions.append (((2, 3, 2), conv,
2093                      '''\\FooContext -> \\Foo'''))
2094
2095 def conv (str):
2096         str = re.sub (r'\\notes\b', '', str)
2097         
2098         return str
2099
2100 conversions.append (((2, 3, 4), conv,
2101                      '''remove \\notes'''))
2102
2103
2104
2105 def conv (str):
2106         str = re.sub (r'lastpagefill\s*=\s*"?1"', 'raggedlastbottom = ##t', str)
2107         return str
2108
2109 conversions.append (((2, 3, 6), conv,
2110                      '''lastpagefill -> raggedlastbottom'''))
2111
2112
2113
2114 def conv (str):
2115         str = re.sub (r'\\consistsend', '\\consists', str)
2116         str = re.sub (r'\\lyricsto\s+("?[a-zA-Z]+"?)(\s*\\new Lyrics\s*)?\\lyrics',
2117                       r'\\lyricsto \1 \2', str)
2118         return str
2119
2120 conversions.append (((2, 3, 8), conv,
2121                      '''remove \\consistsend, strip \\lyrics from \\lyricsto.'''))
2122
2123 def conv (str):
2124         str = re.sub (r'neo_mensural', 'neomensural', str)
2125         str = re.sub (r'if-text-padding', 'bound-padding', str)
2126         return str
2127
2128 conversions.append (((2, 3, 9), conv,
2129                      '''neo_mensural -> neomensural, if-text-padding -> bound-padding'''))
2130
2131
2132
2133 def conv (str):
2134         str = re.sub (r'\\addlyrics', r'\\oldaddlyrics', str)
2135         str = re.sub (r'\\newlyrics', r'\\addlyrics', str)
2136         if re.search (r"\\override\s*TextSpanner", str):
2137                 sys.stderr.write ("\nWarning: TextSpanner has been split into DynamicTextSpanner and TextSpanner\n") 
2138         return str
2139
2140 conversions.append (((2, 3, 10), conv,
2141                      '''\\addlyrics -> \\oldaddlyrics, \\newlyrics -> \\addlyrics'''))
2142
2143 def conv (str):
2144         str = re.sub (r'\\setMmRestFermata\s+(R[0-9.*/]*)',
2145                       r'\1^\\fermataMarkup', str)
2146         return str
2147
2148 conversions.append (((2, 3, 11), conv,
2149                      '''\\setMmRestFermata -> ^\\fermataMarkup'''))
2150
2151 def conv (str):
2152         str = re.sub (r'\\newpage', r'\\pageBreak', str)
2153         str = re.sub (r'\\scriptUp', r"""{
2154   \\override TextScript  #'direction = #1
2155   \\override Script  #'direction = #1
2156 }""", str)
2157         str = re.sub (r'\\scriptDown', r"""{
2158   \\override TextScript  #'direction = #-1
2159   \\override Script  #'direction = #-1
2160 }""", str)
2161         str = re.sub (r'\\scriptBoth', r"""{
2162   \\revert TextScript  #'direction
2163   \\revert Script  #'direction
2164 }""", str)
2165         str = re.sub ('soloADue', 'printPartCombineTexts', str)
2166         str = re.sub (r'\\applymusic\s*#notes-to-clusters',
2167                       '\\makeClusters', str)
2168
2169         str = re.sub (r'pagenumber\s*=', 'firstpagenumber', str)
2170         return str
2171
2172 conversions.append (((2, 3, 12), conv,
2173                      '''\\newpage -> \\pageBreak, junk \\script{up,down,both},
2174 soloADue -> printPartCombineTexts, #notes-to-clusters -> \\makeClusters
2175 '''))
2176
2177
2178 def conv (str):
2179         str = re.sub (r'\\chords\b', r'\\chordmode', str)
2180         str = re.sub (r'\\lyrics\b', r'\\lyricmode', str)
2181         str = re.sub (r'\\figures\b', r'\\figuremode', str)
2182         str = re.sub (r'\\notes\b', r'\\notemode', str)
2183         str = re.sub (r'\\drums\b', r'\\drummode', str)
2184         str = re.sub (r'\\chordmode\s*\\new ChordNames', r'\\chords', str)
2185         str = re.sub (r'\\new ChordNames\s*\\chordmode', r'\\chords', str)
2186         str = re.sub (r'\\new FiguredBass\s*\\figuremode', r'\\figures', str)
2187         str = re.sub (r'\\figuremode\s*\new FiguredBass', r'\\figures', str)
2188         str = re.sub (r'\\new DrumStaff\s*\\drummode', r'\\drums', str)
2189         str = re.sub (r'\\drummode\s*\\new DrumStaff', r'\\drums', str)
2190
2191         return str
2192
2193 conversions.append (((2, 3, 16), conv,
2194                      '''\foo -> \foomode (for chords, notes, etc.)
2195 fold \new FooContext \foomode into \foo.'''))
2196
2197 def conv (str):
2198         str = re.sub (r'(slur|stem|phrasingSlur|tie|dynamic|dots|tuplet|arpeggio|)Both', r'\1Neutral', str)
2199         str = re.sub (r"\\applymusic\s*#\(remove-tag\s*'([a-z-0-9]+)\)",
2200                       r"\\removeWithTag #'\1", str)
2201         return str
2202
2203 conversions.append (((2, 3, 17), conv,
2204                      '''\foo -> \foomode (for chords, notes, etc.)
2205 fold \new FooContext \foomode into \foo.'''))
2206
2207
2208 def conv (str):
2209         str = re.sub (r'Text_item', 'Text_interface', str)
2210         return str
2211
2212 conversions.append (((2, 3, 18),
2213                      conv,
2214                      '''Text_item -> Text_interface''' ))
2215
2216 def conv (str):
2217         str = re.sub (r'\\paper', r'\\layout', str)
2218         str = re.sub (r'\\bookpaper', r'\\paper', str)
2219         if re.search ('paper-set-staff-size', str):
2220                 sys.stderr.write ('''\nWarning: staff size should be changed at top-level
2221 with
2222
2223   #(set-global-staff-size <STAFF-HEIGHT-IN-POINT>)
2224
2225 ''')
2226                 
2227                 
2228         str = re.sub (r'#\(paper-set-staff-size', '%Use set-global-staff-size at toplevel\n% #(layout-set-staff-size', str)
2229         return str
2230
2231 conversions.append (((2, 3, 22),
2232                      conv,
2233                      '''paper -> layout
2234  bookpaper -> paper''' ))
2235
2236
2237 def conv (str):
2238         str = re.sub (r'\\context\s+([a-zA-Z]+)\s*=\s*([a-z]+)\s',
2239                       r'\\context \1 = "\2" ',
2240                       str )
2241         return str
2242
2243 conversions.append (((2, 3, 23),
2244                      conv,
2245                      '''\context Foo = NOTENAME -> \context Foo = "NOTENAME"'''))
2246
2247 def conv (str):
2248         def sub(m):
2249                 return regularize_id (m.group (1))
2250         str = re.sub (r'(maintainer_email|maintainer_web|midi_stuff|gourlay_maxmeasures)',
2251                       sub, str)
2252         return str
2253
2254 conversions.append (((2, 3, 24),
2255                      conv,
2256                      '''regularize other identifiers.'''))
2257
2258
2259 def conv (str):
2260         return str
2261
2262 conversions.append (((2, 4, 0),
2263                      conv,
2264                      ''))
2265
2266
2267 def conv (str):
2268         str = re.sub (r'\\quote\s+"?([a-zA-Z0-9]+)"?\s+([0-9.*/]+)',
2269                       r'\\quoteDuring #"\1" { \skip \2 }',
2270                       str
2271                       )
2272         return str
2273
2274 conversions.append (((2, 5, 0),
2275                      conv,
2276                      ''))
2277
2278
2279 def conv (str):
2280         str = re.sub (r'ly:import-module',
2281                       r'ly:module-copy', str) 
2282         return str
2283
2284 conversions.append (((2, 5, 1),
2285                      conv,
2286                      'ly:import-module -> ly:module-copy'))
2287
2288 def conv (str):
2289         str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<([^<]*)>',
2290                       r'\\\1 {\2}', str)
2291         str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<([^<]*)>',
2292                       r'\\\1 {\2}', str)
2293         str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<([^<]*)>',
2294                       r'\\\1 {\2}', str)
2295         return str
2296
2297 conversions.append (((2, 5, 2),
2298                      conv,
2299                      '\markup .. < .. > .. -> \markup .. { .. } ..'))
2300
2301 def conv (str):
2302         str = re.sub ('ly:find-glyph-by-name', 'ly:font-get-glyph', str)
2303         str = re.sub ('"(scripts|clefs|accidentals)-', r'"\1.', str)
2304         str = re.sub ("'hufnagel-do-fa", "'hufnagel.do.fa", str) 
2305         str = re.sub ("'(vaticana|hufnagel|medicaea|petrucci|neomensural|mensural)-", r"'\1.", str) 
2306         return str
2307
2308 conversions.append (((2, 5, 3),
2309                      conv,
2310                      'ly:find-glyph-by-name -> ly:font-get-glyph, remove - from glyphnames.'))
2311
2312
2313
2314 def conv (str):
2315         if re.search (r"\\encoding", str):
2316                 sys.stderr.write ("Sorry, input files should be UTF8.\n"
2317                                   + "Please convert by hand.")
2318                 raise FatalConversionError()
2319
2320         return str
2321
2322 conversions.append (((2, 5, 2),
2323                      conv,
2324                      'ly:find-glyph-by-name -> ly:font-get-glyph, remove - from glyphnames.'))
2325
2326 def conv (str):
2327         str = re.sub (r"\\override\s+(Voice\.)?Slur #'dashed\s*=\s*#\d*(\.\d+)?",
2328                       r"\\slurDashed", str)                   
2329         return str
2330
2331 conversions.append (((2, 5, 12),
2332                      conv,
2333                      '\set Slur #\'dashed = #X -> \slurDashed'))
2334
2335
2336 ################################
2337 #       END OF CONVERSIONS      
2338 ################################
2339
2340 def get_conversions (from_version, to_version):
2341         def version_b (v, f = from_version, t = to_version):
2342                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
2343         return filter (version_b, conversions)
2344
2345
2346 def latest_version ():
2347         return conversions[-1][0]
2348
2349 def do_conversion (infile, from_version, outfile, to_version):
2350         conv_list = get_conversions (from_version, to_version)
2351
2352         sys.stderr.write ('Applying conversions: ')
2353         str = infile.read ()
2354         last_conversion = ()
2355         try:
2356                 for x in conv_list:
2357                         sys.stderr.write (tup_to_str (x[0]) + ', ')
2358                         str = x[1] (str)
2359                         last_conversion = x[0]
2360
2361         except FatalConversionError:
2362                 sys.stderr.write ('Error while converting; I won\'t convert any further')
2363
2364         if last_conversion:
2365                 sys.stderr.write ('\n')
2366                 new_ver =  '\\version \"%s\"' % tup_to_str (last_conversion)
2367
2368                 if re.search (lilypond_version_re_str, str):
2369                         str = re.sub (lilypond_version_re_str,'\\'+new_ver, str)
2370                 elif add_version:
2371                         str = new_ver + '\n' + str
2372
2373                 outfile.write (str)
2374
2375         return last_conversion
2376         
2377 class UnknownVersion:
2378         pass
2379
2380 def do_one_file (infile_name):
2381         sys.stderr.write ('Processing `%s\' ... '% infile_name)
2382         outfile_name = ''
2383         if __main__.edit:
2384                 outfile_name = infile_name + '.NEW'
2385         elif __main__.outfile_name:
2386                 outfile_name = __main__.outfile_name
2387
2388         if __main__.from_version:
2389                 from_version = __main__.from_version
2390         else:
2391                 guess = guess_lilypond_version (infile_name)
2392                 if not guess:
2393                         raise UnknownVersion ()
2394                 from_version = str_to_tuple (guess)
2395
2396         if __main__.to_version:
2397                 to_version = __main__.to_version
2398         else:
2399                 to_version = latest_version ()
2400
2401
2402         if infile_name:
2403                 infile = open (infile_name,'r')
2404         else:
2405                 infile = sys.stdin
2406
2407         if outfile_name:
2408                 outfile =  open (outfile_name, 'w')
2409         else:
2410                 outfile = sys.stdout
2411
2412         touched = do_conversion (infile, from_version, outfile, to_version)
2413
2414         if infile_name:
2415                 infile.close ()
2416
2417         if outfile_name:
2418                 outfile.close ()
2419
2420         if __main__.edit and touched:
2421                 try:
2422                         os.remove(infile_name + '~')
2423                 except:
2424                         pass
2425                 os.rename (infile_name, infile_name + '~')
2426                 os.rename (infile_name + '.NEW', infile_name)
2427
2428         sys.stderr.write ('\n')
2429         sys.stderr.flush ()
2430
2431 edit = 0
2432 assume_old = 0
2433 to_version = ()
2434 from_version = ()
2435 outfile_name = ''
2436 show_rules_p = 0
2437
2438 (options, files) = getopt.getopt (sys.argv[1:], 'ao:f:t:senh',
2439                                   ['no-version', 'version', 'output',
2440                                   'show-rules', 'help', 'edit',
2441                                   'from=', 'to='])
2442
2443 for opt in options:
2444         o = opt[0]
2445         a = opt[1]
2446         if o == '--help' or o == '-h':
2447                 usage ()
2448                 sys.exit (0)
2449         elif o == '--version' or o == '-v':
2450                 print_version ()
2451                 sys.exit (0)
2452         elif o== '--from' or o=='-f':
2453                 from_version = str_to_tuple (a)
2454         elif o== '--to' or o=='-t':
2455                 to_version = str_to_tuple (a)
2456         elif o== '--edit' or o == '-e':
2457                 edit = 1
2458         elif o== '--show-rules' or o == '-s':
2459                 show_rules_p = 1
2460         elif o == '--output' or o == '-o':
2461                 outfile_name = a
2462         elif o == '--no-version' or o == '-n':
2463                 add_version = 0
2464         else:
2465                 print o
2466                 raise getopt.error
2467
2468 # should parse files[] to read \version?
2469 if show_rules_p:
2470         show_rules (sys.stdout)
2471         sys.exit (0)
2472                 
2473 identify ()
2474 for f in files:
2475         if f == '-':
2476                 f = ''
2477         elif not os.path.isfile (f):
2478                 continue
2479         try:
2480                 do_one_file (f)
2481         except UnknownVersion:
2482                 sys.stderr.write ('\n')
2483                 sys.stderr.write ("%s: can't determine version for `%s'" % (program_name, f))
2484                 sys.stderr.write ('\n')
2485                 if assume_old:
2486                         fv = from_version
2487                         from_version = (0, 0, 0)
2488                         do_one_file (f)
2489                         from_version = fv
2490                 else:
2491                         sys.stderr.write ("%s: skipping: `%s' " % (program_name,  f))
2492                 pass
2493
2494 sys.stderr.write ('\n')