]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-ly.py
* scripts/convert-ly.py (conv): add ancient rules.
[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--2004  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+([^. ]+)\s*\.\s*([^\\=]+)\s*\\(set|override)',
1844                       r"\\overrid@ \1.\2 ", str)
1845         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*=\s*',
1846                       r'\\s@t \1.\2 = ', str)
1847         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\unset',
1848                       r'\\uns@t \1.\2 ', str)
1849         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\revert'
1850                       + r"\s*#'([-a-z0-9_]+)",
1851                       r"\\rev@rt \1.\2 #'\3", str)
1852         str = re.sub (r'Voice\.', '', str)
1853         str = re.sub (r'Lyrics\.', '', str)
1854         str = re.sub (r'ChordNames\.', '', str)
1855         
1856         str = re.sub ('rev@rt', 'revert',str)
1857         str = re.sub ('s@t', 'set',str)
1858         str = re.sub ('overrid@', 'override',str)
1859
1860         str = re.sub ('molecule', 'stencil', str)
1861         str = re.sub ('Molecule', 'Stencil', str)
1862         return str
1863
1864 conversions.append (((2,1,22), conv, """new syntax for property settings:
1865         \\set A.B = #C , \\unset A.B
1866         \\override A.B #C = #D, \\revert A.B #C
1867
1868 """))
1869
1870 def conv (str):
1871         def subst_in_trans (match):
1872                 s = match.group (0)
1873                 s = re.sub (r'\s([a-zA-Z]+)\s*\\override',
1874                               r' \\override \1', s)
1875                 s = re.sub (r'\s([a-zA-Z]+)\s*\\set',
1876                               r' \\override \1', s)
1877                 s = re.sub (r'\s([a-zA-Z]+)\s*\\revert',
1878                               r' \\revert \1', s)
1879                 return s
1880         str = re.sub (r'\\(translator|with)\s*{[^}]+}',  subst_in_trans, str)
1881
1882         def sub_abs (m):
1883                 
1884                 context = m.group ('context')
1885                 d = m.groupdict ()
1886                 if context:
1887                         context = " '%s" % context[:-1] # -1: remove . 
1888                 else:
1889                         context = ''
1890
1891                 d['context'] = context
1892                 
1893                 return r"""#(override-auto-beam-setting %(prop)s %(num)s %(den)s%(context)s)""" % d
1894
1895         str = re.sub (r"""\\override\s*(?P<context>[a-zA-Z]+\s*\.\s*)?autoBeamSettings"""
1896                       +r"""\s*#(?P<prop>[^=]+)\s*=\s*#\(ly:make-moment\s+(?P<num>\d+)\s+(?P<den>\d)\s*\)""",
1897                       sub_abs, str)
1898         
1899         return str
1900         
1901 conversions.append (((2,1,23), conv, """Property setting syntax in \\translator{ }"""))
1902 def conv (str):
1903         str = re.sub (r'music-list\?', 'ly:music-list?', str)
1904         str = re.sub (r'\|\s*~', '~ |', str)   
1905         return str
1906
1907 conversions.append (((2,1,24), conv, """music-list? -> ly:music-list?"""))
1908
1909 def conv (str):
1910         str = re.sub (r'ly:get-spanner-bound', 'ly:spanner-get-bound', str)
1911         str = re.sub (r'ly:get-extent', 'ly:grob-extent', str)
1912         str = re.sub (r'ly:get-system', 'ly:grob-system', str)
1913         str = re.sub (r'ly:get-original', 'ly:grob-original', str)
1914         str = re.sub (r'ly:get-parent', 'ly:grob-parent', str)
1915         str = re.sub (r'ly:get-broken-into', 'ly:spanner-broken-into', str)
1916         str = re.sub (r'Melisma_engraver', 'Melisma_translator', str)
1917         if re.search ("ly:get-paper-variable", str):
1918                 sys.stderr.write ('use (ly:paper-lookup (ly:grob-paper ))')
1919                 raise FatalConversionError()
1920
1921         str = re.sub (r'\\defaultAccidentals', "#(set-accidental-style 'default)", str)
1922         str = re.sub (r'\\voiceAccidentals', "#(set-accidental-style 'voice)", str)
1923         str = re.sub (r'\\modernAccidentals', "#(set-accidental-style 'modern)", str)
1924         str = re.sub (r'\\modernCautionaries', "#(set-accidental-style 'modern-cautionary)", str)
1925         str = re.sub (r'\\modernVoiceAccidental', "#(set-accidental-style 'modern-voice)", str)
1926         str = re.sub (r'\\modernVoiceCautionaries', "#(set-accidental-style 'modern-voice-cautionary)", str)
1927         str = re.sub (r'\\pianoAccidentals', "#(set-accidental-style 'piano)", str)
1928         str = re.sub (r'\\pianoCautionaries', "#(set-accidental-style 'piano-cautionary)", str)
1929         str = re.sub (r'\\forgetAccidentals', "#(set-accidental-style 'forget)", str)
1930         str = re.sub (r'\\noResetKey', "#(set-accidental-style 'no-reset)", str)
1931         
1932         return str
1933
1934 conversions.append (((2,1,25), conv, """Scheme grob function renaming"""))
1935
1936
1937 def conv (str):
1938         str = re.sub ('ly:set-grob-property!', 'ly:grob-set-property!',str)
1939         str = re.sub ('ly:set-mus-property!', 'ly:music-set-property!',str)     
1940         str = re.sub ('ly:set-context-property!', 'ly:context-set-property!', str)      
1941         str = re.sub ('ly:get-grob-property', 'ly:grob-property',str)
1942         str = re.sub ('ly:get-mus-property', 'ly:music-property',str)
1943         str = re.sub ('ly:get-context-property', 'ly:context-property',str)
1944         
1945         return str
1946
1947 conversions.append (((2,1,26), conv, """More Scheme function renaming"""))
1948
1949 def conv (str):
1950         def subst (m):
1951                 g = string.atoi (m.group (2))
1952                 o = g / 12
1953                 g -= o * 12
1954                 if g <  0:
1955                         g += 12
1956                         o -= 1
1957
1958
1959                 lower_pitches = filter (lambda x : x <= g, [0, 2, 4, 5, 7, 9, 11, 12])
1960                 s = len (lower_pitches) -1 
1961                 a = g - lower_pitches [-1]
1962
1963
1964                 print s , lower_pitches, g, a, s 
1965                 str = 'cdefgab' [s]
1966                 str += ['eses', 'es', '', 'is', 'isis'][a + 2]
1967                 if o < 0:
1968                         str += ',' * (-o - 1)
1969                 elif o >= 0:
1970                         str += "'" * (o + 1)
1971                         
1972                 return '\\transposition %s ' % str
1973
1974         
1975         str = re.sub (r"\\set ([A-Za-z]+\s*\.\s*)?transposing\s*=\s*#([-0-9]+)",
1976                       subst, str)
1977         return str
1978
1979 conversions.append (((2,1,27), conv, """property transposing -> tuning"""))
1980
1981 def conv (str):
1982         str = re.sub (r'make-music-by-name', 'make-music', str)
1983         str = re.sub (r"\\override\s+.*Arpeggio\s+#.print-function\s+=\s+\\arpeggioBracket", r"\\arpeggioBracket", str)
1984         return str
1985
1986 conversions.append (((2,1,28), conv,
1987                      """make-music-by-name -> make-music,
1988 new syntax for setting \\arpeggioBracket"""))
1989
1990 def conv (str):
1991         str = re.sub (r'\\center([^-])', '\\center-align\\1', str)
1992         str = re.sub (r'\\translator', '\\context', str)
1993         return str
1994
1995 conversions.append (((2,1,29), conv,
1996                      '\\center -> \\center-align, \\translator -> \\context'))
1997
1998
1999 def conv (str):
2000         str = re.sub (r'\\threeq(flat|sharp)', r'\\sesqui\1', str)
2001         str = re.sub (r'ly:stencil-get-extent',
2002                       'ly:stencil-extent', str)
2003         str = re.sub (r'ly:translator-find',
2004                       'ly:context-find', str)
2005         str = re.sub ('ly:unset-context-property','ly:context-unset-property',
2006                       str)
2007                      
2008         str = re.sub (r'ly:get-mutable-properties',
2009                       'ly:mutable-music-properties',str)
2010         str = re.sub (r'centralCPosition',
2011                       'middleCPosition',str)
2012         return str
2013
2014 conversions.append (((2,1,30), conv,
2015                      '''\\threeq{flat,sharp} -> \\sesqui{flat,sharp}
2016 ly:get-mutable-properties -> ly:mutable-music-properties
2017 centralCPosition -> middleCPosition
2018 ly:unset-context-property -> ly:context-unset-property
2019 ly:translator-find -> ly:context-find
2020 ly:get-stencil-extent -> ly:stencil-extent
2021 '''))
2022
2023
2024 def conv (str):
2025         str = re.sub (r'\\alias\s*"?Timing"?', '', str)
2026         return str
2027
2028 conversions.append (((2,1,31), conv,
2029                      '''remove \\alias Timing'''))
2030
2031 def conv (str):
2032         str = re.sub (r"(\\set\s+)?(?P<context>(Score\.)?)breakAlignOrder\s*=\s*#'(?P<list>[^\)]+)",
2033                       r"\n\\override \g<context>BreakAlignment #'break-align-orders = "
2034                       + "#(make-vector 3 '\g<list>)", str)
2035                       
2036         return str
2037
2038 conversions.append (((2,1,33), conv,
2039                      '''breakAlignOrder -> break-align-orders.'''))
2040
2041 def conv (str):
2042         str = re.sub (r"\(set-paper-size",
2043                       "(set-default-paper-size",str)
2044         return str
2045
2046 conversions.append (((2,1,34), conv,
2047                      '''set-paper-size -> set-default-paper-size.'''))
2048
2049 def conv (str):
2050         str = re.sub (r"ly:mutable-music-properties",
2051                       "ly:music-mutable-properties", str)
2052         return str
2053
2054 conversions.append (((2,1, 36), conv,
2055                      '''ly:mutable-music-properties -> ly:music-mutable-properties'''))
2056
2057
2058
2059 def conv (str):
2060         return str
2061
2062 conversions.append (((2, 2, 0), conv,
2063                      '''clean up version. '''))
2064
2065 def conv (str):
2066         return re.sub (r'\\apply\b', r'\\applymusic', str)
2067
2068 conversions.append (((2, 3, 1), conv,
2069                      '''\\apply -> \\applymusic'''))
2070
2071 def conv (str):
2072         if re.search ('textheight', str):
2073                 sys.stderr.write("\nWarning: tuning of page layout has changed. See reference manual.\n")
2074                 
2075         str = re.sub (r'\\OrchestralScoreContext', '\\Score', str)
2076         def func(m):
2077                 if m.group(1) not in ['RemoveEmptyStaff',
2078                                       'AncientRemoveEmptyStaffContext',
2079                                       'EasyNotation']:
2080                         return '\\' + m.group (1)
2081                 else:
2082                         return m.group (0)
2083                 
2084                 
2085         str = re.sub (r'\\([a-zA-Z]+)Context\b', func, str)
2086
2087         str = re.sub ('ly:paper-lookup', 'ly:output-def-lookup', str)
2088         return str
2089
2090 conversions.append (((2, 3, 2), conv,
2091                      '''\\FooContext -> \\Foo'''))
2092
2093 def conv (str):
2094         str = re.sub (r'\\notes\b', '', str)
2095         
2096         return str
2097
2098 conversions.append (((2, 3, 4), conv,
2099                      '''remove \\notes'''))
2100
2101
2102
2103 def conv (str):
2104         str = re.sub (r'lastpagefill\s*=\s*"?1"', 'raggedlastbottom = ##t', str)
2105         return str
2106
2107 conversions.append (((2, 3, 6), conv,
2108                      '''lastpagefill -> raggedlastbottom'''))
2109
2110
2111
2112 def conv (str):
2113         str = re.sub (r'\\consistsend', '\\consists', str)
2114         str = re.sub (r'\\lyricsto\s+("?[a-zA-Z]+"?)(\s*\\new Lyrics\s*)?\\lyrics',
2115                       r'\\lyricsto \1 \2', str)
2116         return str
2117
2118 conversions.append (((2, 3, 8), conv,
2119                      '''remove \\consistsend, strip \\lyrics from \\lyricsto.'''))
2120
2121 def conv (str):
2122         str = re.sub (r'neo_mensural', 'neomensural', str)
2123         str = re.sub (r'if-text-padding', 'bound-padding', str)
2124         return str
2125
2126 conversions.append (((2, 3, 9), conv,
2127                      '''neo_mensural -> neomensural, if-text-padding -> bound-padding'''))
2128
2129
2130
2131 def conv (str):
2132         str = re.sub (r'\\addlyrics', r'\\oldaddlyrics', str)
2133         str = re.sub (r'\\newlyrics', r'\\addlyrics', str)
2134         if re.search (r"\\override\s*TextSpanner", str):
2135                 sys.stderr.write ("\nWarning: TextSpanner has been split into DynamicTextSpanner and TextSpanner\n") 
2136         return str
2137
2138 conversions.append (((2, 3, 10), conv,
2139                      '''\\addlyrics -> \\oldaddlyrics, \\newlyrics -> \\addlyrics'''))
2140
2141 def conv (str):
2142         str = re.sub (r'\\setMmRestFermata\s+(R[0-9.*/]*)',
2143                       r'\1^\\fermataMarkup', str)
2144         return str
2145
2146 conversions.append (((2, 3, 11), conv,
2147                      '''\\setMmRestFermata -> ^\\fermataMarkup'''))
2148
2149 def conv (str):
2150         str = re.sub (r'\\newpage', r'\\pageBreak', str)
2151         str = re.sub (r'\\scriptUp', r"""{
2152   \\override TextScript  #'direction = #1
2153   \\override Script  #'direction = #1
2154 }""", str)
2155         str = re.sub (r'\\scriptDown', r"""{
2156   \\override TextScript  #'direction = #-1
2157   \\override Script  #'direction = #-1
2158 }""", str)
2159         str = re.sub (r'\\scriptBoth', r"""{
2160   \\revert TextScript  #'direction
2161   \\revert Script  #'direction
2162 }""", str)
2163         str = re.sub ('soloADue', 'printPartCombineTexts', str)
2164         str = re.sub (r'\\applymusic\s*#notes-to-clusters',
2165                       '\\makeClusters', str)
2166
2167         str = re.sub (r'pagenumber\s*=', 'firstpagenumber', str)
2168         return str
2169
2170 conversions.append (((2, 3, 12), conv,
2171                      '''\\newpage -> \\pageBreak, junk \\script{up,down,both},
2172 soloADue -> printPartCombineTexts, #notes-to-clusters -> \\makeClusters
2173 '''))
2174
2175
2176 def conv (str):
2177         str = re.sub (r'\\chords\b', r'\\chordmode', str)
2178         str = re.sub (r'\\lyrics\b', r'\\lyricmode', str)
2179         str = re.sub (r'\\figures\b', r'\\figuremode', str)
2180         str = re.sub (r'\\notes\b', r'\\notemode', str)
2181         str = re.sub (r'\\drums\b', r'\\drummode', str)
2182         str = re.sub (r'\\chordmode\s*\\new ChordNames', r'\\chords', str)
2183         str = re.sub (r'\\new ChordNames\s*\\chordmode', r'\\chords', str)
2184         str = re.sub (r'\\new FiguredBass\s*\\figuremode', r'\\figures', str)
2185         str = re.sub (r'\\figuremode\s*\new FiguredBass', r'\\figures', str)
2186         str = re.sub (r'\\new DrumStaff\s*\\drummode', r'\\drums', str)
2187         str = re.sub (r'\\drummode\s*\\new DrumStaff', r'\\drums', str)
2188
2189         return str
2190
2191 conversions.append (((2, 3, 16), conv,
2192                      '''\foo -> \foomode (for chords, notes, etc.)
2193 fold \new FooContext \foomode into \foo.'''))
2194
2195 def conv (str):
2196         str = re.sub (r'(slur|stem|phrasingSlur|tie|dynamic|dots|tuplet|arpeggio|)Both', r'\1Neutral', str)
2197         str = re.sub (r"\\applymusic\s*#\(remove-tag\s*'([a-z-0-9]+)\)",
2198                       r"\\removeWithTag #'\1", str)
2199         return str
2200
2201 conversions.append (((2, 3, 17), conv,
2202                      '''\foo -> \foomode (for chords, notes, etc.)
2203 fold \new FooContext \foomode into \foo.'''))
2204
2205
2206 def conv (str):
2207         str = re.sub (r'Text_item', 'Text_interface', str)
2208         return str
2209
2210 conversions.append (((2, 3, 18),
2211                      conv,
2212                      '''Text_item -> Text_interface''' ))
2213
2214 def conv (str):
2215         str = re.sub (r'\\paper', r'\\layout', str)
2216         str = re.sub (r'\\bookpaper', r'\\paper', str)
2217         if re.search ('paper-set-staff-size', str):
2218                 sys.stderr.write ('''\nWarning: staff size should be changed at top-level
2219 with
2220
2221   #(set-global-staff-size <STAFF-HEIGHT-IN-POINT>)
2222
2223 ''')
2224                 
2225                 
2226         str = re.sub (r'#\(paper-set-staff-size', '%Use set-global-staff-size at toplevel\n% #(layout-set-staff-size', str)
2227         return str
2228
2229 conversions.append (((2, 3, 22),
2230                      conv,
2231                      '''paper -> layout
2232  bookpaper -> paper''' ))
2233
2234
2235 def conv (str):
2236         str = re.sub (r'\\context\s+([a-zA-Z]+)\s*=\s*([a-z]+)\s',
2237                       r'\\context \1 = "\2" ',
2238                       str )
2239         return str
2240
2241 conversions.append (((2, 3, 23),
2242                      conv,
2243                      '''\context Foo = NOTENAME -> \context Foo = "NOTENAME"'''))
2244
2245
2246 def conv (str):
2247         return str
2248
2249 conversions.append (((2, 4, 0),
2250                      conv,
2251                      ''))
2252
2253
2254 def conv (str):
2255         str = re.sub (r'\\quote\s+"?([a-zA-Z0-9]+)"?\s+([0-9.*/]+)',
2256                       r'\\quoteDuring #"\1" { \skip \2 }',
2257                       str
2258                       )
2259         return str
2260
2261 conversions.append (((2, 5, 0),
2262                      conv,
2263                      ''))
2264
2265
2266 def conv (str):
2267         str = re.sub (r'ly:import-module',
2268                       r'ly:module-copy', str) 
2269         return str
2270
2271 conversions.append (((2, 5, 1),
2272                      conv,
2273                      'ly:import-module -> ly:module-copy'))
2274
2275 def conv (str):
2276         str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<([^<]*)>',
2277                       r'\\\1 {\2}', str)
2278         str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<([^<]*)>',
2279                       r'\\\1 {\2}', str)
2280         str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<([^<]*)>',
2281                       r'\\\1 {\2}', str)
2282         return str
2283
2284 conversions.append (((2, 5, 2),
2285                      conv,
2286                      '\markup .. < .. > .. -> \markup .. { .. } ..'))
2287
2288 def conv (str):
2289         str = re.sub ('ly:find-glyph-by-name', 'ly:font-get-glyph', str)
2290         str = re.sub ('"(scripts|clefs|accidentals)-', r'"\1.', str)
2291         str = re.sub ("'hufnagel-do-fa", "'hufnagel.do.fa", str) 
2292         str = re.sub ("'(vaticana|hufnagel|medicaea|petrucci|neomensural|mensural)-", r"'\1.", str) 
2293         return str
2294
2295 conversions.append (((2, 5, 2),
2296                      conv,
2297                      'ly:find-glyph-by-name -> ly:font-get-glyph, remove - from glyphnames.'))
2298
2299
2300 ################################
2301 #       END OF CONVERSIONS      
2302 ################################
2303
2304 def get_conversions (from_version, to_version):
2305         def version_b (v, f = from_version, t = to_version):
2306                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
2307         return filter (version_b, conversions)
2308
2309
2310 def latest_version ():
2311         return conversions[-1][0]
2312
2313 def do_conversion (infile, from_version, outfile, to_version):
2314         conv_list = get_conversions (from_version, to_version)
2315
2316         sys.stderr.write ('Applying conversions: ')
2317         str = infile.read ()
2318         last_conversion = ()
2319         try:
2320                 for x in conv_list:
2321                         sys.stderr.write (tup_to_str (x[0]) + ', ')
2322                         str = x[1] (str)
2323                         last_conversion = x[0]
2324
2325         except FatalConversionError:
2326                 sys.stderr.write ('Error while converting; I won\'t convert any further')
2327
2328         if last_conversion:
2329                 sys.stderr.write ('\n')
2330                 new_ver =  '\\version \"%s\"' % tup_to_str (last_conversion)
2331
2332                 if re.search (lilypond_version_re_str, str):
2333                         str = re.sub (lilypond_version_re_str,'\\'+new_ver, str)
2334                 elif add_version:
2335                         str = new_ver + '\n' + str
2336
2337                 outfile.write (str)
2338
2339         return last_conversion
2340         
2341 class UnknownVersion:
2342         pass
2343
2344 def do_one_file (infile_name):
2345         sys.stderr.write ('Processing `%s\' ... '% infile_name)
2346         outfile_name = ''
2347         if __main__.edit:
2348                 outfile_name = infile_name + '.NEW'
2349         elif __main__.outfile_name:
2350                 outfile_name = __main__.outfile_name
2351
2352         if __main__.from_version:
2353                 from_version = __main__.from_version
2354         else:
2355                 guess = guess_lilypond_version (infile_name)
2356                 if not guess:
2357                         raise UnknownVersion ()
2358                 from_version = str_to_tuple (guess)
2359
2360         if __main__.to_version:
2361                 to_version = __main__.to_version
2362         else:
2363                 to_version = latest_version ()
2364
2365
2366         if infile_name:
2367                 infile = open (infile_name,'r')
2368         else:
2369                 infile = sys.stdin
2370
2371         if outfile_name:
2372                 outfile =  open (outfile_name, 'w')
2373         else:
2374                 outfile = sys.stdout
2375
2376         touched = do_conversion (infile, from_version, outfile, to_version)
2377
2378         if infile_name:
2379                 infile.close ()
2380
2381         if outfile_name:
2382                 outfile.close ()
2383
2384         if __main__.edit and touched:
2385                 try:
2386                         os.remove(infile_name + '~')
2387                 except:
2388                         pass
2389                 os.rename (infile_name, infile_name + '~')
2390                 os.rename (infile_name + '.NEW', infile_name)
2391
2392         sys.stderr.write ('\n')
2393         sys.stderr.flush ()
2394
2395 edit = 0
2396 assume_old = 0
2397 to_version = ()
2398 from_version = ()
2399 outfile_name = ''
2400 show_rules_p = 0
2401
2402 (options, files) = getopt.getopt (sys.argv[1:], 'ao:f:t:senh',
2403                                   ['no-version', 'version', 'output',
2404                                   'show-rules', 'help', 'edit',
2405                                   'from=', 'to='])
2406
2407 for opt in options:
2408         o = opt[0]
2409         a = opt[1]
2410         if o == '--help' or o == '-h':
2411                 usage ()
2412                 sys.exit (0)
2413         elif o == '--version' or o == '-v':
2414                 print_version ()
2415                 sys.exit (0)
2416         elif o== '--from' or o=='-f':
2417                 from_version = str_to_tuple (a)
2418         elif o== '--to' or o=='-t':
2419                 to_version = str_to_tuple (a)
2420         elif o== '--edit' or o == '-e':
2421                 edit = 1
2422         elif o== '--show-rules' or o == '-s':
2423                 show_rules_p = 1
2424         elif o == '--output' or o == '-o':
2425                 outfile_name = a
2426         elif o == '--no-version' or o == '-n':
2427                 add_version = 0
2428         else:
2429                 print o
2430                 raise getopt.error
2431
2432 # should parse files[] to read \version?
2433 if show_rules_p:
2434         show_rules (sys.stdout)
2435         sys.exit (0)
2436                 
2437 identify ()
2438 for f in files:
2439         if f == '-':
2440                 f = ''
2441         elif not os.path.isfile (f):
2442                 continue
2443         try:
2444                 do_one_file (f)
2445         except UnknownVersion:
2446                 sys.stderr.write ('\n')
2447                 sys.stderr.write ("%s: can't determine version for `%s'" % (program_name, f))
2448                 sys.stderr.write ('\n')
2449                 if assume_old:
2450                         fv = from_version
2451                         from_version = (0, 0, 0)
2452                         do_one_file (f)
2453                         from_version = fv
2454                 else:
2455                         sys.stderr.write ("%s: skipping: `%s' " % (program_name,  f))
2456                 pass
2457
2458 sys.stderr.write ('\n')