]> git.donarmstrong.com Git - lilypond.git/blob - bin/mf-to-table.py
release: 0.1.57
[lilypond.git] / bin / mf-to-table.py
1 #!@PYTHON@
2
3
4 # mf-to-table.py -- convert spacing info in  MF logs .ly and .tex
5
6 # source file of the GNU LilyPond music typesetter
7
8 # (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
9
10
11 import getopt
12 from string import *
13 import regex
14 import regsub
15 import os
16 import sys
17 import time
18
19
20
21 lilypath =''
22 try:
23         lilypath = os.environ['LILYPOND_SOURCEDIR'] + '/'
24 except KeyError:
25         try:
26                 lilypath = os.environ['top_srcdir'] + '/'
27         except KeyError:
28             print 'Please set LILYPOND_SOURCEDIR to the toplevel source, eg LILYPOND_SOURCEDIR=/home/foobar/lilypond-1.2.3/'
29
30             sys.exit(1)
31
32 lilypath = lilypath + '/bin/'
33 sys.path.append(lilypath)
34  
35 from flower import *
36
37 begin_autometric_re = regex.compile('@{')
38 end_autometric_re = regex.compile('@}')
39 include_re = regex.compile ('(\([a-zA-Z_0-9-]+\.mf\)')
40 autometric_re = regex.compile('@{\(.*\)@}')
41 version = '0.6'
42 postfixes = ['log', 'dvi', '2602gf', 'tfm']
43
44 class Feta_file(File):
45     """Read Feta metrics from a metafont log-file."""
46
47     def include_scan (self, line):
48         include_pos =  include_re.search (line)
49         while include_pos <> -1:
50             self.dependencies.append (include_re.group (1))
51
52             line = line[include_pos + 1:]
53             include_pos =  include_re.search (line)
54
55     def read_autometricline(self):
56         line = ''
57         while end_autometric_re.search(line) == -1 and not self.eof():
58             suf = File.readline(self)
59             self.include_scan (suf)
60             if begin_autometric_re.search(line) == -1:
61                 line = ''
62             line = line + regsub.sub('\n','', suf)
63
64         if self.eof():
65            return ''
66
67         return line;
68     def readline(self):
69         """return what is enclosed in one @{ @} pair"""
70         line = '';
71         while autometric_re.search(line) == -1 and not self.eof():
72             line = self.read_autometricline()
73
74         if self.eof():
75             return '';
76
77         return autometric_re.group(1);
78     def __init__(self, nm):
79         File.__init__(self, nm)
80         self.dependencies = []
81     def do_file(infile_nm):
82         infile = readline();
83
84 #
85 # FIXME: should parse output for {} to do indenting.
86 #
87 class Indentable_file(File):
88     """Output file with support for indentation"""
89     def __init__(self,nm, mode):
90         File.__init__(self,nm,mode)
91         self.current_indent_ = 0
92         self.delta_indent_ = 4
93     def writeline (self, str):
94         File.write(self, str)
95     def writeeol(self):
96         File.write(self, '\n')
97         File.write(self, ' '* self.current_indent_)
98
99     def indent(self):
100         self.current_indent_ = self.delta_indent_ + self.current_indent_;
101     def dedent(self):
102         self.current_indent_ = self.current_indent_ - self.delta_indent_;
103         if self.current_indent_ < 0:
104             raise 'Nesting!'
105
106     def write(self, str):
107         lines = split(str, '\n')
108         for l in lines[:-1]:
109             self.writeline(l)
110             self.writeeol()
111         self.writeline (lines[-1])
112
113 class Ly_file(Indentable_file):
114     """extra provisions for mozarella quirks"""
115     def print_lit(self, str):
116         self.write('\"%s\"\t' % str)
117
118     def print_f_dimen(self, f):
119         dimstr = '%.2f' % f
120
121         # try to mask rounding errors
122         if (dimstr == '-0.00'):
123                 dimstr = '0.00'
124         self.write( dimstr  +'\\pt\t');
125
126     def print_dimen(self, str):
127         self.print_f_dimen(atof(str))
128     
129     def neg_print_dimen(self, str):
130         self.print_f_dimen(-atof(str));
131         
132     def def_symbol(self, lily_id, tex_id, dims):
133         self.print_lit(lily_id)
134         self.print_lit('\\\\' + tex_id)
135
136         self.neg_print_dimen(dims [0])
137         self.print_dimen(dims [1])
138         self.neg_print_dimen(dims [2])
139         self.print_dimen(dims [3])
140         self.write('\n')
141         
142         
143 class Log_reader:
144     """Read logs, destill info, and put into output files"""
145     def output_label(self, line):
146
147         if not line:
148             return;
149         tags = split(line, '@:')
150         label = tags[0]
151         name = tags[1]
152         ly = self.lyfile        
153         if tags[0] == 'font':
154             ly.indent()
155             ly.write("% name=\\symboltables {\n")
156             self.texfile.write("% name\n")
157         elif label == "group":
158             ly.indent()
159             ly.print_lit(name)
160             ly.write(' = \\table {\n')
161             self.texfile.write("% " + name + "\n")
162         elif label == "puorg":
163             ly.dedent()
164             ly.write("}\n")
165             self.texfile.write("\n")
166         elif label == "tnof":
167             ly.dedent()
168             ly.write("%  } % $name\n")
169         elif label == "char":
170             code = tags[2]
171             id = tags [7]
172             texstr = tags [8]
173             
174             ly.def_symbol(id, texstr, tags[3:7])
175             
176             self.texfile.write("\\fetdef\\%s{%s}\n" % (texstr, code))
177         else:
178             raise 'unknown label: ' + label
179
180     def writedeps (self, deps):
181         
182         filename = deps[0]
183         split = os.path.splitext(filename)      
184         basename=split[0];
185
186         targets =  map (lambda x,y = basename, z = self.outdir: z + '/' + y + '.' + x, postfixes)
187         depstring = reduce(lambda x,y: x + ' ' + y, deps) 
188         dependencies = map (lambda x, y=depstring: x + ': ' + y, targets)
189         for x in dependencies: 
190             self.depfile.write (x + '\n')
191         
192     def do_file(self,filenm):
193         self.lyfile.write ('\n% input from ' + filenm + '\n')
194         self.texfile.write ('\n% input from ' + filenm + '\n')
195         feta = Feta_file(filenm)
196         while not feta.eof():
197             line = feta.readline()
198             self.output_label(line)
199         feta.close()
200         
201         self.writedeps (feta.dependencies)
202
203     def __init__(self, lyfile_nm, texfile_nm, depfile_nm):          
204         self.lyfile = Ly_file(lyfile_nm, 'w')
205         self.texfile = Indentable_file(texfile_nm, 'w')
206         self.depfile = File (depfile_nm, 'w')
207
208         headerstr = '%% Creator: %s\n%% Automatically generated on\n%% Do not edit' % \
209                    (program_id() )
210
211         self.lyfile.write(headerstr)
212         self.texfile.write(headerstr)
213         self.depfile.write ('# automatically generated by %s\n' % program_id ())
214
215     def close(self):
216         self.lyfile.close()
217         self.texfile.close()
218         self.depfile.close ()
219
220     def __del__(self):
221         self.close()
222
223 def today_str():
224     return time.asctime(time.localtime(time.time()))
225         
226 def program_id():
227     return 'mf-to-table.py version ' + version;
228
229 def identify():
230     sys.stdout.write(program_id() + '\n')
231     
232 def help():
233     sys.stdout.write("Usage: mf-to-table [options] LOGFILEs\n"
234                  + "Generate mozarella metrics table from preparated feta log\n\n"
235                  + "Options:\n"
236                  + "  -h, --help             print this help\n"
237                  + "  -l, --ly=FILE          name output table\n"
238                  + "  -d, --dep=FILE         print dependency info to FILE\n"
239                  + "  -o, --outdir=DIR       prefix for dependency info\n"
240                  + "  -t, --tex=FILE         name output tex chardefs\n")
241     sys.exit (0)
242
243
244 def main():
245     identify()
246     (options, files) = getopt.getopt(
247         sys.argv[1:], 'ho:l:t:d:', ['outdir=', 'dep=', 'ly=', 'tex=', 'debug', 'help'])
248
249     lyfile_nm = texfile_nm = '';
250     depfile_nm = ''
251     outdir_prefix = '.'
252     for opt in options:
253         o = opt[0]
254         a = opt[1]
255         if o == '--dep' or o == '-d':
256             depfile_nm = a
257         elif o == '--outdir' or o == '-o':
258             outdir_prefix = a
259         elif o == '--ly' or o == '-l':
260             lyfile_nm = a
261         elif o == '--tex' or o == '-t':
262             texfile_nm = a
263         elif o== '--help' or o == '-h':
264             help()
265         elif o == '--debug':
266             debug_b = 1
267         else:
268             print o
269             raise getopt.error
270
271     log_reader = Log_reader(lyfile_nm, texfile_nm, depfile_nm)
272     log_reader.outdir = outdir_prefix
273     for filenm in files:
274         log_reader.do_file(filenm)
275     log_reader.close()
276
277
278 main()