home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Tools / modulator / modulator.py < prev    next >
Encoding:
Python Source  |  2000-10-25  |  14.1 KB  |  381 lines

  1. #! /usr/bin/env python
  2. #
  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.  
  19. import sys, os
  20. if os.name <> 'mac':
  21.     sys.path.append(os.path.join(os.environ['HOME'],
  22.                                  'src/python/Tools/modulator'))
  23.  
  24. from Tkinter import *
  25. from Tkextra import *
  26. from ScrolledListbox import ScrolledListbox
  27. import sys
  28. import genmodule
  29. import string
  30.  
  31. oops = 'oops'
  32.  
  33. # Check that string is a legal C identifier
  34. def checkid(str):
  35.     if not str: return 0
  36.     if not str[0] in string.letters+'_':
  37.         return 0
  38.     for c in str[1:]:
  39.         if not c in string.letters+string.digits+'_':
  40.             return 0
  41.     return 1
  42.  
  43. def getlistlist(list):
  44.     rv = []
  45.     n = list.size()
  46.     for i in range(n):
  47.         rv.append(list.get(i))
  48.     return rv
  49.     
  50. class UI:
  51.     def __init__(self):
  52.         self.main = Frame()
  53.         self.main.pack()
  54.         self.main.master.title('Modulator: Module view')
  55.         self.cmdframe = Frame(self.main, {'relief':'raised', 'bd':'0.5m',
  56.                                           Pack:{'side':'top',
  57.                                                  'fill':'x'}})
  58.         self.objframe = Frame(self.main, {Pack:{'side':'top', 'fill':'x',
  59.                                                 'expand':1}})
  60.  
  61.  
  62.         self.check_button = Button(self.cmdframe,
  63.                                   {'text':'Check', 'command':self.cb_check,
  64.                                    Pack:{'side':'left', 'padx':'0.5m'}})
  65.         self.save_button = Button(self.cmdframe,
  66.                                   {'text':'Save...', 'command':self.cb_save,
  67.                                    Pack:{'side':'left', 'padx':'0.5m'}})
  68.         self.code_button = Button(self.cmdframe,
  69.                                   {'text':'Generate code...',
  70.                                    'command':self.cb_gencode,
  71.                                    Pack:{'side':'left', 'padx':'0.5m'}})
  72.         self.quit_button = Button(self.cmdframe,
  73.                                   {'text':'Quit',
  74.                                    'command':self.cb_quit,
  75.                                    Pack:{'side':'right', 'padx':'0.5m'}})
  76.  
  77.         self.module = UI_module(self)
  78.         self.objects = []
  79.         self.modified = 0
  80.  
  81.     def run(self):
  82.         self.main.mainloop()
  83.  
  84.     def cb_quit(self, *args):
  85.         if self.modified:
  86.             if not askyn('You have not saved\nAre you sure you want to quit?'):
  87.                 return
  88.         sys.exit(0)
  89.  
  90.     def cb_check(self, *args):
  91.         try:
  92.             self.module.synchronize()
  93.             for o in self.objects:
  94.                 o.synchronize()
  95.         except oops:
  96.             pass
  97.         
  98.     def cb_save(self, *args):
  99.         try:
  100.             pycode = self.module.gencode('m', self.objects)
  101.         except oops:
  102.             return
  103.  
  104.         fn = askfile('Python file name: ')
  105.         if not fn:
  106.             return
  107.  
  108.         fp = open(fn, 'w')
  109.  
  110.         fp.write(pycode)
  111.         fp.close()
  112.  
  113.     def cb_gencode(self, *args):
  114.         try:
  115.             pycode = self.module.gencode('m', self.objects)
  116.         except oops:
  117.             pass
  118.  
  119.         fn = askfile('C file name: ')
  120.         if not fn:
  121.             return
  122.  
  123.         fp = open(fn, 'w')
  124.  
  125.         try:
  126.             exec pycode
  127.         except:
  128.             message('An error occurred:-)')
  129.             return
  130.         genmodule.write(fp, m)
  131.         fp.close()
  132.  
  133. class UI_module:
  134.     def __init__(self, parent):
  135.         self.parent = parent
  136.         self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
  137.                                              Pack:{'side':'top',
  138.                                                    'fill':'x'}})
  139.         self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
  140.                                            'fill':'x'}})
  141.         self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
  142.                                            'fill':'x'}})
  143.         self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
  144.                                            'fill':'x'}})
  145.         self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
  146.                                            'fill':'x'}})
  147.  
  148.         self.l1 = Label(self.f1, {'text':'Module:', Pack:{'side':'left',
  149.                                                         'padx':'0.5m'}})
  150.         self.name_entry = Entry(self.f1, {'relief':'sunken',
  151.                               Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
  152.         self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
  153.                                                         'padx':'0.5m'}})
  154.         self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
  155.                               Pack:{'side':'left', 'padx':'0.5m'}})
  156.  
  157.         self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
  158.                                                         'padx':'0.5m'}})
  159.         self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
  160.                                       Pack:{'side':'left', 'expand':1,
  161.                                             'padx':'0.5m', 'fill':'both'}})
  162.  
  163.         self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
  164.                                                               'padx':'0.5m'}})
  165.         self.method_entry = Entry(self.f3, {'relief':'sunken',
  166.                              Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
  167.         self.method_entry.bind('<Return>', self.cb_method)
  168.         self.delete_button = Button(self.f3, {'text':'Delete method',
  169.                                               'command':self.cb_delmethod,
  170.                                               Pack:{'side':'left',
  171.                                                     'padx':'0.5m'}})
  172.  
  173.         self.newobj_button = Button(self.f4, {'text':'new object',
  174.                                               'command':self.cb_newobj,
  175.                                               Pack:{'side':'left',
  176.                                                     'padx':'0.5m'}})
  177.         
  178.     def cb_delmethod(self, *args):
  179.         list = self.method_list.curselection()
  180.         for i in list:
  181.             self.method_list.delete(i)
  182.         
  183.     def cb_newobj(self, *arg):
  184.         self.parent.objects.append(UI_object(self.parent))
  185.  
  186.     def cb_method(self, *arg):
  187.         name = self.method_entry.get()
  188.         if not name:
  189.             return
  190.         self.method_entry.delete('0', 'end')
  191.         self.method_list.insert('end', name)
  192.  
  193.     def synchronize(self):
  194.         n = self.name_entry.get()
  195.         if not n:
  196.             message('Module name not set')
  197.             raise oops
  198.         if not checkid(n):
  199.             message('Module name not an identifier:\n'+n)
  200.             raise oops
  201.         if not self.abbrev_entry.get():
  202.             self.abbrev_entry.insert('end', n)
  203.         m = getlistlist(self.method_list)
  204.         for n in m:
  205.             if not checkid(n):
  206.                 message('Method name not an identifier:\n'+n)
  207.                 raise oops
  208.             
  209.     def gencode(self, name, objects):
  210.         rv = ''
  211.         self.synchronize()
  212.         for o in objects:
  213.             o.synchronize()
  214.         onames = []
  215.         for i in range(len(objects)):
  216.             oname = 'o'+`i+1`
  217.             rv = rv + objects[i].gencode(oname)
  218.             onames.append(oname)
  219.         rv = rv + (name+' = genmodule.module()\n')
  220.         rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
  221.         rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
  222.         rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
  223.         rv = rv + (name+'.objects = ['+string.joinfields(onames, ',')+']\n')
  224.         rv = rv + ('\n')
  225.         return rv
  226.         
  227. object_number = 0
  228.  
  229. class UI_object:
  230.     def __init__(self, parent):
  231.         global object_number
  232.  
  233.         object_number = object_number + 1
  234.         self.num = object_number
  235.         self.vpref = 'o'+`self.num`+'_'
  236.         self.frame = Toplevel(parent.objframe)
  237. #       self.frame.pack()
  238.         self.frame.title('Modulator: object view')
  239. #       self.frame = Frame(parent.objframe, {'relief':'raised', 'bd':'0.2m',
  240. #                                            Pack:{'side':'top',
  241. #                                                  'fill':'x'}})
  242.         self.f1 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
  243.                                            'fill':'x'}})
  244.         self.f2 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
  245.                                            'fill':'x'}})
  246.         self.f3 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
  247.                                            'fill':'x'}})
  248.         self.f4 = Frame(self.frame, {Pack:{'side':'top', 'pady':'0.5m',
  249.                                            'fill':'x'}})
  250.         
  251.  
  252.         self.l1 = Label(self.f1, {'text':'Object:', Pack:{'side':'left',
  253.                                                         'padx':'0.5m'}})
  254.         self.name_entry = Entry(self.f1, {'relief':'sunken',
  255.                               Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
  256.         self.l2 = Label(self.f1, {'text':'Abbrev:', Pack:{'side':'left',
  257.                                                         'padx':'0.5m'}})
  258.         self.abbrev_entry = Entry(self.f1, {'relief':'sunken', 'width':5,
  259.                               Pack:{'side':'left', 'padx':'0.5m'}})
  260.  
  261.         self.l3 = Label(self.f2, {'text':'Methods:', Pack:{'side':'left',
  262.                                                         'padx':'0.5m'}})
  263.         self.method_list = ScrolledListbox(self.f2, {'relief':'sunken','bd':2,
  264.                                       Pack:{'side':'left', 'expand':1,
  265.                                             'padx':'0.5m', 'fill':'both'}})
  266.  
  267.         self.l4 = Label(self.f3, {'text':'Add method:', Pack:{'side':'left',
  268.                                                               'padx':'0.5m'}})
  269.         self.method_entry = Entry(self.f3, {'relief':'sunken',
  270.                              Pack:{'side':'left', 'padx':'0.5m', 'expand':1}})
  271.         self.method_entry.bind('<Return>', self.cb_method)
  272.         self.delete_button = Button(self.f3, {'text':'Delete method',
  273.                                               'command':self.cb_delmethod,
  274.                                               Pack:{'side':'left',
  275.                                                     'padx':'0.5m'}})
  276.  
  277.  
  278.         self.l5 = Label(self.f4, {'text':'functions:',
  279.                                   Pack:{'side':'left',
  280.                                         'padx':'0.5m'}})
  281.         self.f5 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
  282.                                            'fill':'both'}})
  283.         self.l6 = Label(self.f4, {'text':'Types:',
  284.                                   Pack:{'side':'left', 'padx':'0.5m'}})
  285.         self.f6 = Frame(self.f4, {Pack:{'side':'left', 'pady':'0.5m',
  286.                                            'fill':'x'}})
  287.         self.funcs = {}
  288.         for i in genmodule.FUNCLIST:
  289.             vname = self.vpref+i
  290.             self.f5.setvar(vname, 0)
  291.             b = Checkbutton(self.f5, {'variable':vname, 'text':i,
  292.                                       Pack:{'side':'top', 'pady':'0.5m',
  293.                                             'anchor':'w','expand':1}})
  294.             self.funcs[i] = b
  295.         self.f5.setvar(self.vpref+'new', 1)
  296.  
  297.         self.types = {}
  298.         for i in genmodule.TYPELIST:
  299.             vname = self.vpref + i
  300.             self.f6.setvar(vname, 0)
  301.             b = Checkbutton(self.f6, {'variable':vname, 'text':i,
  302.                                       Pack:{'side':'top', 'pady':'0.5m',
  303.                                             'anchor':'w'}})
  304.             self.types[i] = b
  305.         
  306.     def cb_method(self, *arg):
  307.         name = self.method_entry.get()
  308.         if not name:
  309.             return
  310.         self.method_entry.delete('0', 'end')
  311.         self.method_list.insert('end', name)
  312.  
  313.     def cb_delmethod(self, *args):
  314.         list = self.method_list.curselection()
  315.         for i in list:
  316.             self.method_list.delete(i)
  317.         
  318.     def synchronize(self):
  319.         n = self.name_entry.get()
  320.         if not n:
  321.             message('Object name not set')
  322.             raise oops
  323.         if not self.abbrev_entry.get():
  324.             self.abbrev_entry.insert('end', n)
  325.         n = self.abbrev_entry.get()
  326.         if not checkid(n):
  327.             message('Abbreviation not an identifier:\n'+n)
  328.             raise oops
  329.         m = getlistlist(self.method_list)
  330.         for n in m:
  331.             if not checkid(n):
  332.                 message('Method name not an identifier:\n'+n)
  333.                 raise oops
  334.         if m:
  335.             self.f5.setvar(self.vpref+'tp_getattr', 1)
  336.         pass
  337.         
  338.     def gencode(self, name):
  339.         rv = ''
  340.         rv = rv + (name+' = genmodule.object()\n')
  341.         rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
  342.         rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
  343.         rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
  344.         fl = []
  345.         for fn in genmodule.FUNCLIST:
  346.             vname = self.vpref + fn
  347.             if self.f5.getvar(vname) == '1':
  348.                 fl.append(fn)
  349.         rv = rv + (name+'.funclist = '+`fl`+'\n')
  350.  
  351.         fl = []
  352.         for fn in genmodule.TYPELIST:
  353.             vname = self.vpref + fn
  354.             if self.f5.getvar(vname) == '1':
  355.                 fl.append(fn)
  356.                 
  357.         rv = rv + (name+'.typelist = '+`fl`+'\n')
  358.  
  359.         rv = rv + ('\n')
  360.         return rv
  361.         
  362.  
  363. def main():
  364.     if len(sys.argv) < 2:
  365.         ui = UI()
  366.         ui.run()
  367.     elif len(sys.argv) == 2:
  368.         fp = open(sys.argv[1])
  369.         pycode = fp.read()
  370.         try:
  371.             exec pycode
  372.         except:
  373.             sys.stderr.write('An error occurred:-)\n')
  374.             sys.exit(1)
  375.         ##genmodule.write(sys.stdout, m)
  376.     else:
  377.         sys.stderr.write('Usage: modulator [file]\n')
  378.         sys.exit(1)
  379.         
  380. main()
  381.