checkin of Jack's original version
diff --git a/Tools/modulator/modulator.py b/Tools/modulator/modulator.py
new file mode 100755
index 0000000..b569ac6
--- /dev/null
+++ b/Tools/modulator/modulator.py
@@ -0,0 +1,379 @@
+#! /usr/local/bin/python
+#
+# Modulator - Generate skeleton modules.
+#
+# The user fills out some forms with information about what the module
+# should support (methods, objects), names of these things, prefixes to
+# use for C code, whether the objects should also support access as numbers,
+# etc etc etc.
+# When the user presses 'Generate code' we generate a complete skeleton
+# module in C.
+#
+# Alternatively, the selections made can be save to a python sourcefile and
+# this sourcefile can be passed on the command line (resulting in the same
+# skeleton C code).
+#
+# Jack Jansen, CWI, October 1994.
+#
+
+import sys, os
+sys.path.append(os.path.join(os.environ['HOME'], 'src/python/Demo/modulator'))
+
+from Tkinter import *
+from Tkextra import *
+import tkinter
+from ScrolledListbox import ScrolledListbox
+import sys
+import genmodule
+import string
+
+oops = 'oops'
+
+# Check that string is a legal C identifier
+def checkid(str):
+ if not str: return 0
+ if not str[0] in string.letters+'_':
+ return 0
+ for c in str[1:]:
+ if not c in string.letters+string.digits+'_':
+ return 0
+ return 1
+
+def getlistlist(list):
+ rv = []
+ n = list.size()
+ for i in range(n):
+ rv.append(list.get(i))
+ return rv
+
+class UI:
+ def __init__(self):
+ self.main = Frame()
+ self.main.pack()
+ self.main.master.title('Modulator: Module view')
+ self.cmdframe = Frame(self.main, {'relief':'raised', 'bd':'0.5m',
+ Pack:{'side':'top',
+ 'fill':'x'}})
+ self.objframe = Frame(self.main, {Pack:{'side':'top', 'fill':'x',
+ 'expand':1}})
+
+
+ self.check_button = Button(self.cmdframe,
+ {'text':'Check', 'command':self.cb_check,
+ Pack:{'side':'left', 'padx':'0.5m'}})
+ self.save_button = Button(self.cmdframe,
+ {'text':'Save...', 'command':self.cb_save,
+ Pack:{'side':'left', 'padx':'0.5m'}})
+ self.code_button = Button(self.cmdframe,
+ {'text':'Generate code...',
+ 'command':self.cb_gencode,
+ Pack:{'side':'left', 'padx':'0.5m'}})
+ self.quit_button = Button(self.cmdframe,
+ {'text':'Quit',
+ 'command':self.cb_quit,
+ Pack:{'side':'right', 'padx':'0.5m'}})
+
+ self.module = UI_module(self)
+ self.objects = []
+ self.modified = 0
+
+ def run(self):
+ self.main.mainloop()
+
+ def cb_quit(self, *args):
+ if self.modified:
+ if not askyn('You have not saved\nAre you sure you want to quit?'):
+ return
+ sys.exit(0)
+
+ def cb_check(self, *args):
+ try:
+ self.module.synchronize()
+ for o in self.objects:
+ o.synchronize()
+ except oops:
+ pass
+
+ def cb_save(self, *args):
+ try:
+ pycode = self.module.gencode('m', self.objects)
+ except oops:
+ return
+
+ fn = askfile('Python file name: ')
+ if not fn:
+ return
+
+ fp = open(fn, 'w')
+
+ fp.write(pycode)
+ fp.close()
+
+ def cb_gencode(self, *args):
+ try:
+ pycode = self.module.gencode('m', self.objects)
+ except oops:
+ pass
+
+ fn = askfile('C file name: ')
+ if not fn:
+ return
+
+ fp = open(fn, 'w')
+
+ try:
+ exec pycode
+ except:
+ message('An error occurred:-)')
+ return
+ genmodule.write(fp, m)
+ fp.close()
+
+class UI_module:
+ def __init__(self, parent):
+ self.parent = parent
+ self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
+ Pack:{'side':'top',
+ 'fill':'x'}})
+ self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+ 'fill':'x'}})
+ self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+ 'fill':'x'}})
+ self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+ 'fill':'x'}})
+ self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+ 'fill':'x'}})
+
+ self.l1 = Label(self.f1, {'text':'Module:', Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.name_entry = Entry(self.f1, {'relief':'sunken',
+ Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
+ self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
+ Pack:{'side':'left', 'padx':'0.5m'}})
+
+ self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
+ Pack:{'side':'left', 'expand':1,
+ 'padx':'0.5m', 'fill':'both'}})
+
+ self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.method_entry = Entry(self.f3, {'relief':'sunken',
+ Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
+ self.method_entry.bind('<Return>', self.cb_method)
+ self.delete_button = Button(self.f3, {'text':'Delete method',
+ 'command':self.cb_delmethod,
+ Pack:{'side':'left',
+ 'padx':'0.5m'}})
+
+ self.newobj_button = Button(self.f4, {'text':'new object',
+ 'command':self.cb_newobj,
+ Pack:{'side':'left',
+ 'padx':'0.5m'}})
+
+ def cb_delmethod(self, *args):
+ list = self.method_list.curselection()
+ for i in list:
+ self.method_list.delete(i)
+
+ def cb_newobj(self, *arg):
+ self.parent.objects.append(UI_object(self.parent))
+
+ def cb_method(self, *arg):
+ name = self.method_entry.get()
+ if not name:
+ return
+ self.method_entry.delete('0', 'end')
+ self.method_list.insert('end', name)
+
+ def synchronize(self):
+ n = self.name_entry.get()
+ if not n:
+ message('Module name not set')
+ raise oops
+ if not checkid(n):
+ message('Module name not an identifier:\n'+n)
+ raise oops
+ if not self.abbrev_entry.get():
+ self.abbrev_entry.insert('end', n)
+ m = getlistlist(self.method_list)
+ for n in m:
+ if not checkid(n):
+ message('Method name not an identifier:\n'+n)
+ raise oops
+
+ def gencode(self, name, objects):
+ rv = ''
+ self.synchronize()
+ for o in objects:
+ o.synchronize()
+ onames = []
+ for i in range(len(objects)):
+ oname = 'o'+`i+1`
+ rv = rv + objects[i].gencode(oname)
+ onames.append(oname)
+ rv = rv + (name+' = genmodule.module()\n')
+ rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
+ rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
+ rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
+ rv = rv + (name+'.objects = ['+string.joinfields(onames, ',')+']\n')
+ rv = rv + ('\n')
+ return rv
+
+object_number = 0
+
+class UI_object:
+ def __init__(self, parent):
+ global object_number
+
+ object_number = object_number + 1
+ self.num = object_number
+ self.vpref = 'o'+`self.num`+'_'
+ self.frame = Toplevel(parent.objframe)
+# self.frame.pack()
+ self.frame.title('Modulator: object view')
+# self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
+# Pack:{'side':'top',
+# 'fill':'x'}})
+ self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+ 'fill':'x'}})
+ self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+ 'fill':'x'}})
+ self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+ 'fill':'x'}})
+ self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
+ 'fill':'x'}})
+
+
+ self.l1 = Label(self.f1, {'text':'Object:', Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.name_entry = Entry(self.f1, {'relief':'sunken',
+ Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
+ self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
+ Pack:{'side':'left', 'padx':'0.5m'}})
+
+ self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
+ Pack:{'side':'left', 'expand':1,
+ 'padx':'0.5m', 'fill':'both'}})
+
+ self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.method_entry = Entry(self.f3, {'relief':'sunken',
+ Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
+ self.method_entry.bind('<Return>', self.cb_method)
+ self.delete_button = Button(self.f3, {'text':'Delete method',
+ 'command':self.cb_delmethod,
+ Pack:{'side':'left',
+ 'padx':'0.5m'}})
+
+
+ self.l5 = Label(self.f4, {'text':'functions:',
+ Pack:{'side':'left',
+ 'padx':'0.5m'}})
+ self.f5 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
+ 'fill':'both'}})
+ self.l6 = Label(self.f4, {'text':'Types:',
+ Pack:{'side':'left', 'padx':'0.5m'}})
+ self.f6 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
+ 'fill':'x'}})
+ self.funcs = {}
+ for i in genmodule.FUNCLIST:
+ vname = self.vpref+i
+ self.f5.setvar(vname, 0)
+ b = Checkbutton(self.f5, {'variable':vname, 'text':i,
+ Pack:{'side':'top', 'pady':'0.5m',
+ 'anchor':'w','expand':1}})
+ self.funcs[i] = b
+ self.f5.setvar(self.vpref+'new', 1)
+
+ self.types = {}
+ for i in genmodule.TYPELIST:
+ vname = self.vpref + i
+ self.f6.setvar(vname, 0)
+ b = Checkbutton(self.f6, {'variable':vname, 'text':i,
+ Pack:{'side':'top', 'pady':'0.5m',
+ 'anchor':'w'}})
+ self.types[i] = b
+
+ def cb_method(self, *arg):
+ name = self.method_entry.get()
+ if not name:
+ return
+ self.method_entry.delete('0', 'end')
+ self.method_list.insert('end', name)
+
+ def cb_delmethod(self, *args):
+ list = self.method_list.curselection()
+ for i in list:
+ self.method_list.delete(i)
+
+ def synchronize(self):
+ n = self.name_entry.get()
+ if not n:
+ message('Object name not set')
+ raise oops
+ if not self.abbrev_entry.get():
+ self.abbrev_entry.insert('end', n)
+ n = self.abbrev_entry.get()
+ if not checkid(n):
+ message('Abbreviation not an identifier:\n'+n)
+ raise oops
+ m = getlistlist(self.method_list)
+ for n in m:
+ if not checkid(n):
+ message('Method name not an identifier:\n'+n)
+ raise oops
+ if m:
+ self.f5.setvar(self.vpref+'tp_getattr', 1)
+ pass
+
+ def gencode(self, name):
+ rv = ''
+ rv = rv + (name+' = genmodule.object()\n')
+ rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
+ rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
+ rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
+ fl = []
+ for fn in genmodule.FUNCLIST:
+ vname = self.vpref + fn
+ if self.f5.getvar(vname) == '1':
+ fl.append(fn)
+ rv = rv + (name+'.funclist = '+`fl`+'\n')
+
+ fl = []
+ for fn in genmodule.TYPELIST:
+ vname = self.vpref + fn
+ if self.f5.getvar(vname) == '1':
+ fl.append(fn)
+
+ rv = rv + (name+'.typelist = '+`fl`+'\n')
+
+ rv = rv + ('\n')
+ return rv
+
+
+def main():
+ if len(sys.argv) < 2:
+ ui = UI()
+ ui.run()
+ elif len(sys.argv) == 2:
+ fp = open(sys.argv[1])
+ pycode = fp.read()
+ try:
+ exec pycode
+ except:
+ sys.stderr.write('An error occurred:-)\n')
+ sys.exit(1)
+ genmodule.write(sys.stdout, m)
+ else:
+ sys.stderr.write('Usage: modulator [file]\n')
+ sys.exit(1)
+
+main()