383 lines · 14.1 KB · Python
RawDownload
#! /usr/bin/env 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, osif os.name <> 'mac':    sys.path.append(os.path.join(os.environ['HOME'],                                 'src/python/Tools/modulator')) from Tkinter import *from Tkextra import *from ScrolledListbox import ScrolledListboximport sysimport genmoduleimport string oops = 'oops' IDENTSTARTCHARS = string.letters + '_'IDENTCHARS = string.letters + string.digits + '_' # Check that string is a legal C identifierdef checkid(str):    if not str: return 0    if not str[0] in IDENTSTARTCHARS:        return 0    for c in str[1:]:        if not c in IDENTCHARS:            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%d' % (i+1)            rv = rv + objects[i].gencode(oname)            onames.append(oname)        rv = rv + '%s = genmodule.module()\n' % (name,)        rv = rv + '%s.name = %r\n' % (name, self.name_entry.get())        rv = rv + '%s.abbrev = %r\n' % (name, self.abbrev_entry.get())        rv = rv + '%s.methodlist = %r\n' % (name, getlistlist(self.method_list))        rv = rv + '%s.objects = [%s]\n' % (name, ','.join(onames))        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%r_' % 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 + '%s = genmodule.object()\n' % (name,)        rv = rv + '%s.name = %r\n' % (name, self.name_entry.get())        rv = rv + '%s.abbrev = %r\n' % (name, self.abbrev_entry.get())        rv = rv + '%s.methodlist = %r\n' % (name, getlistlist(self.method_list))        fl = []        for fn in genmodule.FUNCLIST:            vname = self.vpref + fn            if self.f5.getvar(vname) == '1':                fl.append(fn)        rv = rv + '%s.funclist = %r\n' % (name, fl)         fl = []        for fn in genmodule.TYPELIST:            vname = self.vpref + fn            if self.f5.getvar(vname) == '1':                fl.append(fn)         rv = rv + '%s.typelist = %r\n' % (name, fl)         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()