blob: cdf6afe5e3bc6c76fdb13e66f3546bb8e9fa75fe [file] [log] [blame]
Guido van Rossumf06ee5f1996-11-27 19:52:01 +00001#! /usr/bin/env python
Guido van Rossumd2112201995-03-02 14:05:29 +00002#
3# Modulator - Generate skeleton modules.
4#
5# The user fills out some forms with information about what the module
6# should support (methods, objects), names of these things, prefixes to
7# use for C code, whether the objects should also support access as numbers,
8# etc etc etc.
9# When the user presses 'Generate code' we generate a complete skeleton
10# module in C.
11#
12# Alternatively, the selections made can be save to a python sourcefile and
13# this sourcefile can be passed on the command line (resulting in the same
14# skeleton C code).
15#
16# Jack Jansen, CWI, October 1994.
17#
18
19import sys, os
Guido van Rossuma0e24221996-03-07 16:16:54 +000020if os.name <> 'mac':
Guido van Rossuma16a5091998-04-10 19:15:27 +000021 sys.path.append(os.path.join(os.environ['HOME'],
22 'src/python/Tools/modulator'))
Guido van Rossumd2112201995-03-02 14:05:29 +000023
24from Tkinter import *
25from Tkextra import *
Guido van Rossumd2112201995-03-02 14:05:29 +000026from ScrolledListbox import ScrolledListbox
27import sys
28import genmodule
29import string
30
31oops = 'oops'
32
Jack Jansen9aaee932001-12-27 23:35:43 +000033IDENTSTARTCHARS = string.letters + '_'
34IDENTCHARS = string.letters + string.digits + '_'
Fred Drakecd694c42001-07-20 18:58:42 +000035
Guido van Rossumd2112201995-03-02 14:05:29 +000036# Check that string is a legal C identifier
37def checkid(str):
38 if not str: return 0
Fred Drakecd694c42001-07-20 18:58:42 +000039 if not str[0] in IDENTSTARTCHARS:
Guido van Rossuma16a5091998-04-10 19:15:27 +000040 return 0
Guido van Rossumd2112201995-03-02 14:05:29 +000041 for c in str[1:]:
Fred Drakecd694c42001-07-20 18:58:42 +000042 if not c in IDENTCHARS:
Guido van Rossuma16a5091998-04-10 19:15:27 +000043 return 0
Guido van Rossumd2112201995-03-02 14:05:29 +000044 return 1
45
46def getlistlist(list):
47 rv = []
48 n = list.size()
49 for i in range(n):
Guido van Rossuma16a5091998-04-10 19:15:27 +000050 rv.append(list.get(i))
Guido van Rossumd2112201995-03-02 14:05:29 +000051 return rv
52
53class UI:
54 def __init__(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +000055 self.main = Frame()
56 self.main.pack()
57 self.main.master.title('Modulator: Module view')
58 self.cmdframe = Frame(self.main, {'relief':'raised', 'bd':'0.5m',
59 Pack:{'side':'top',
60 'fill':'x'}})
61 self.objframe = Frame(self.main, {Pack:{'side':'top', 'fill':'x',
62 'expand':1}})
Guido van Rossumd2112201995-03-02 14:05:29 +000063
64
Guido van Rossuma16a5091998-04-10 19:15:27 +000065 self.check_button = Button(self.cmdframe,
66 {'text':'Check', 'command':self.cb_check,
67 Pack:{'side':'left', 'padx':'0.5m'}})
68 self.save_button = Button(self.cmdframe,
69 {'text':'Save...', 'command':self.cb_save,
70 Pack:{'side':'left', 'padx':'0.5m'}})
71 self.code_button = Button(self.cmdframe,
72 {'text':'Generate code...',
73 'command':self.cb_gencode,
74 Pack:{'side':'left', 'padx':'0.5m'}})
75 self.quit_button = Button(self.cmdframe,
76 {'text':'Quit',
77 'command':self.cb_quit,
78 Pack:{'side':'right', 'padx':'0.5m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +000079
Guido van Rossuma16a5091998-04-10 19:15:27 +000080 self.module = UI_module(self)
81 self.objects = []
82 self.modified = 0
Guido van Rossumd2112201995-03-02 14:05:29 +000083
84 def run(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +000085 self.main.mainloop()
Guido van Rossumd2112201995-03-02 14:05:29 +000086
87 def cb_quit(self, *args):
Guido van Rossuma16a5091998-04-10 19:15:27 +000088 if self.modified:
89 if not askyn('You have not saved\nAre you sure you want to quit?'):
90 return
91 sys.exit(0)
Guido van Rossumd2112201995-03-02 14:05:29 +000092
93 def cb_check(self, *args):
Guido van Rossuma16a5091998-04-10 19:15:27 +000094 try:
95 self.module.synchronize()
96 for o in self.objects:
97 o.synchronize()
98 except oops:
99 pass
100
Guido van Rossumd2112201995-03-02 14:05:29 +0000101 def cb_save(self, *args):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000102 try:
103 pycode = self.module.gencode('m', self.objects)
104 except oops:
105 return
Guido van Rossumd2112201995-03-02 14:05:29 +0000106
Guido van Rossuma16a5091998-04-10 19:15:27 +0000107 fn = askfile('Python file name: ')
108 if not fn:
109 return
Guido van Rossumd2112201995-03-02 14:05:29 +0000110
Guido van Rossuma16a5091998-04-10 19:15:27 +0000111 fp = open(fn, 'w')
Guido van Rossumd2112201995-03-02 14:05:29 +0000112
Guido van Rossuma16a5091998-04-10 19:15:27 +0000113 fp.write(pycode)
114 fp.close()
Guido van Rossumd2112201995-03-02 14:05:29 +0000115
116 def cb_gencode(self, *args):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000117 try:
118 pycode = self.module.gencode('m', self.objects)
119 except oops:
120 pass
Guido van Rossumd2112201995-03-02 14:05:29 +0000121
Guido van Rossuma16a5091998-04-10 19:15:27 +0000122 fn = askfile('C file name: ')
123 if not fn:
124 return
Guido van Rossumd2112201995-03-02 14:05:29 +0000125
Guido van Rossuma16a5091998-04-10 19:15:27 +0000126 fp = open(fn, 'w')
Guido van Rossumd2112201995-03-02 14:05:29 +0000127
Guido van Rossuma16a5091998-04-10 19:15:27 +0000128 try:
129 exec pycode
130 except:
131 message('An error occurred:-)')
132 return
133 genmodule.write(fp, m)
134 fp.close()
Guido van Rossumd2112201995-03-02 14:05:29 +0000135
136class UI_module:
137 def __init__(self, parent):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000138 self.parent = parent
139 self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
140 Pack:{'side':'top',
141 'fill':'x'}})
142 self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
143 'fill':'x'}})
144 self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
145 'fill':'x'}})
146 self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
147 'fill':'x'}})
148 self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
149 'fill':'x'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000150
Guido van Rossuma16a5091998-04-10 19:15:27 +0000151 self.l1 = Label(self.f1, {'text':'Module:', Pack:{'side':'left',
152 'padx':'0.5m'}})
153 self.name_entry = Entry(self.f1, {'relief':'sunken',
154 Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
155 self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
156 'padx':'0.5m'}})
157 self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
158 Pack:{'side':'left', 'padx':'0.5m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000159
Guido van Rossuma16a5091998-04-10 19:15:27 +0000160 self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
161 'padx':'0.5m'}})
162 self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
163 Pack:{'side':'left', 'expand':1,
164 'padx':'0.5m', 'fill':'both'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000165
Guido van Rossuma16a5091998-04-10 19:15:27 +0000166 self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
167 'padx':'0.5m'}})
168 self.method_entry = Entry(self.f3, {'relief':'sunken',
169 Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
170 self.method_entry.bind('<Return>', self.cb_method)
171 self.delete_button = Button(self.f3, {'text':'Delete method',
172 'command':self.cb_delmethod,
173 Pack:{'side':'left',
174 'padx':'0.5m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000175
Guido van Rossuma16a5091998-04-10 19:15:27 +0000176 self.newobj_button = Button(self.f4, {'text':'new object',
177 'command':self.cb_newobj,
178 Pack:{'side':'left',
179 'padx':'0.5m'}})
180
Guido van Rossumd2112201995-03-02 14:05:29 +0000181 def cb_delmethod(self, *args):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000182 list = self.method_list.curselection()
183 for i in list:
184 self.method_list.delete(i)
185
Guido van Rossumd2112201995-03-02 14:05:29 +0000186 def cb_newobj(self, *arg):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000187 self.parent.objects.append(UI_object(self.parent))
Guido van Rossumd2112201995-03-02 14:05:29 +0000188
189 def cb_method(self, *arg):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000190 name = self.method_entry.get()
191 if not name:
192 return
193 self.method_entry.delete('0', 'end')
194 self.method_list.insert('end', name)
Guido van Rossumd2112201995-03-02 14:05:29 +0000195
196 def synchronize(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000197 n = self.name_entry.get()
198 if not n:
199 message('Module name not set')
200 raise oops
201 if not checkid(n):
202 message('Module name not an identifier:\n'+n)
203 raise oops
204 if not self.abbrev_entry.get():
205 self.abbrev_entry.insert('end', n)
206 m = getlistlist(self.method_list)
207 for n in m:
208 if not checkid(n):
209 message('Method name not an identifier:\n'+n)
210 raise oops
211
Guido van Rossumd2112201995-03-02 14:05:29 +0000212 def gencode(self, name, objects):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000213 rv = ''
214 self.synchronize()
215 for o in objects:
216 o.synchronize()
217 onames = []
218 for i in range(len(objects)):
219 oname = 'o'+`i+1`
220 rv = rv + objects[i].gencode(oname)
221 onames.append(oname)
222 rv = rv + (name+' = genmodule.module()\n')
223 rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
224 rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
225 rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
226 rv = rv + (name+'.objects = ['+string.joinfields(onames, ',')+']\n')
227 rv = rv + ('\n')
228 return rv
229
Guido van Rossumd2112201995-03-02 14:05:29 +0000230object_number = 0
231
232class UI_object:
233 def __init__(self, parent):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000234 global object_number
Guido van Rossumd2112201995-03-02 14:05:29 +0000235
Guido van Rossuma16a5091998-04-10 19:15:27 +0000236 object_number = object_number + 1
237 self.num = object_number
238 self.vpref = 'o'+`self.num`+'_'
239 self.frame = Toplevel(parent.objframe)
240# self.frame.pack()
241 self.frame.title('Modulator: object view')
242# self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
243# Pack:{'side':'top',
244# 'fill':'x'}})
245 self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
246 'fill':'x'}})
247 self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
248 'fill':'x'}})
249 self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
250 'fill':'x'}})
251 self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
252 'fill':'x'}})
253
Guido van Rossumd2112201995-03-02 14:05:29 +0000254
Guido van Rossuma16a5091998-04-10 19:15:27 +0000255 self.l1 = Label(self.f1, {'text':'Object:', Pack:{'side':'left',
256 'padx':'0.5m'}})
257 self.name_entry = Entry(self.f1, {'relief':'sunken',
258 Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
259 self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
260 'padx':'0.5m'}})
261 self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
262 Pack:{'side':'left', 'padx':'0.5m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000263
Guido van Rossuma16a5091998-04-10 19:15:27 +0000264 self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
265 'padx':'0.5m'}})
266 self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
267 Pack:{'side':'left', 'expand':1,
268 'padx':'0.5m', 'fill':'both'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000269
Guido van Rossuma16a5091998-04-10 19:15:27 +0000270 self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
271 'padx':'0.5m'}})
272 self.method_entry = Entry(self.f3, {'relief':'sunken',
273 Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
274 self.method_entry.bind('<Return>', self.cb_method)
275 self.delete_button = Button(self.f3, {'text':'Delete method',
276 'command':self.cb_delmethod,
277 Pack:{'side':'left',
278 'padx':'0.5m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000279
280
Guido van Rossuma16a5091998-04-10 19:15:27 +0000281 self.l5 = Label(self.f4, {'text':'functions:',
282 Pack:{'side':'left',
283 'padx':'0.5m'}})
284 self.f5 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
285 'fill':'both'}})
286 self.l6 = Label(self.f4, {'text':'Types:',
287 Pack:{'side':'left', 'padx':'0.5m'}})
288 self.f6 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
289 'fill':'x'}})
290 self.funcs = {}
291 for i in genmodule.FUNCLIST:
292 vname = self.vpref+i
293 self.f5.setvar(vname, 0)
294 b = Checkbutton(self.f5, {'variable':vname, 'text':i,
295 Pack:{'side':'top', 'pady':'0.5m',
296 'anchor':'w','expand':1}})
297 self.funcs[i] = b
298 self.f5.setvar(self.vpref+'new', 1)
Guido van Rossumd2112201995-03-02 14:05:29 +0000299
Guido van Rossuma16a5091998-04-10 19:15:27 +0000300 self.types = {}
301 for i in genmodule.TYPELIST:
302 vname = self.vpref + i
303 self.f6.setvar(vname, 0)
304 b = Checkbutton(self.f6, {'variable':vname, 'text':i,
305 Pack:{'side':'top', 'pady':'0.5m',
306 'anchor':'w'}})
307 self.types[i] = b
308
Guido van Rossumd2112201995-03-02 14:05:29 +0000309 def cb_method(self, *arg):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000310 name = self.method_entry.get()
311 if not name:
312 return
313 self.method_entry.delete('0', 'end')
314 self.method_list.insert('end', name)
Guido van Rossumd2112201995-03-02 14:05:29 +0000315
316 def cb_delmethod(self, *args):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000317 list = self.method_list.curselection()
318 for i in list:
319 self.method_list.delete(i)
320
Guido van Rossumd2112201995-03-02 14:05:29 +0000321 def synchronize(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000322 n = self.name_entry.get()
323 if not n:
324 message('Object name not set')
325 raise oops
326 if not self.abbrev_entry.get():
327 self.abbrev_entry.insert('end', n)
328 n = self.abbrev_entry.get()
329 if not checkid(n):
330 message('Abbreviation not an identifier:\n'+n)
331 raise oops
332 m = getlistlist(self.method_list)
333 for n in m:
334 if not checkid(n):
335 message('Method name not an identifier:\n'+n)
336 raise oops
337 if m:
338 self.f5.setvar(self.vpref+'tp_getattr', 1)
339 pass
340
Guido van Rossumd2112201995-03-02 14:05:29 +0000341 def gencode(self, name):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000342 rv = ''
343 rv = rv + (name+' = genmodule.object()\n')
344 rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
345 rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
346 rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
347 fl = []
348 for fn in genmodule.FUNCLIST:
349 vname = self.vpref + fn
350 if self.f5.getvar(vname) == '1':
351 fl.append(fn)
352 rv = rv + (name+'.funclist = '+`fl`+'\n')
Guido van Rossumd2112201995-03-02 14:05:29 +0000353
Guido van Rossuma16a5091998-04-10 19:15:27 +0000354 fl = []
355 for fn in genmodule.TYPELIST:
356 vname = self.vpref + fn
357 if self.f5.getvar(vname) == '1':
358 fl.append(fn)
359
360 rv = rv + (name+'.typelist = '+`fl`+'\n')
Guido van Rossumd2112201995-03-02 14:05:29 +0000361
Guido van Rossuma16a5091998-04-10 19:15:27 +0000362 rv = rv + ('\n')
363 return rv
364
Guido van Rossumd2112201995-03-02 14:05:29 +0000365
366def main():
367 if len(sys.argv) < 2:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000368 ui = UI()
369 ui.run()
Guido van Rossumd2112201995-03-02 14:05:29 +0000370 elif len(sys.argv) == 2:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000371 fp = open(sys.argv[1])
372 pycode = fp.read()
373 try:
374 exec pycode
375 except:
376 sys.stderr.write('An error occurred:-)\n')
377 sys.exit(1)
Guido van Rossumb0f99a61999-02-18 14:22:05 +0000378 ##genmodule.write(sys.stdout, m)
Guido van Rossumd2112201995-03-02 14:05:29 +0000379 else:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000380 sys.stderr.write('Usage: modulator [file]\n')
381 sys.exit(1)
382
Guido van Rossumd2112201995-03-02 14:05:29 +0000383main()