This commit was manufactured by cvs2svn to create tag 'r221c2'.
[python/dscho.git] / Mac / scripts / gensuitemodule.py
blob5a4c806ab18ca89d027c8435deb140f50140af7f
1 """
2 gensuitemodule - Generate an AE suite module from an aete/aeut resource
4 Based on aete.py.
6 Reading and understanding this code is left as an exercise to the reader.
7 """
9 import MacOS
10 import os
11 import string
12 import sys
13 import types
14 import StringIO
15 import macfs
16 import keyword
18 from Carbon.Res import *
20 def main():
21 fss, ok = macfs.PromptGetFile('Select file with aeut/aete resource:')
22 if not ok:
23 sys.exit(0)
24 processfile(fss.as_pathname())
26 def processfile(fullname):
27 """Process all resources in a single file"""
28 cur = CurResFile()
29 print fullname
30 rf = OpenRFPerm(fullname, 0, 1)
31 try:
32 UseResFile(rf)
33 resources = []
34 for i in range(Count1Resources('aete')):
35 res = Get1IndResource('aete', 1+i)
36 resources.append(res)
37 for i in range(Count1Resources('aeut')):
38 res = Get1IndResource('aeut', 1+i)
39 resources.append(res)
40 print "\nLISTING aete+aeut RESOURCES IN", `fullname`
41 aetelist = []
42 for res in resources:
43 print "decoding", res.GetResInfo(), "..."
44 data = res.data
45 aete = decode(data)
46 aetelist.append((aete, res.GetResInfo()))
47 finally:
48 if rf <> cur:
49 CloseResFile(rf)
50 UseResFile(cur)
51 # switch back (needed for dialogs in Python)
52 UseResFile(cur)
53 compileaetelist(aetelist, fullname)
55 def compileaetelist(aetelist, fullname):
56 for aete, resinfo in aetelist:
57 compileaete(aete, resinfo, fullname)
59 def decode(data):
60 """Decode a resource into a python data structure"""
61 f = StringIO.StringIO(data)
62 aete = generic(getaete, f)
63 aete = simplify(aete)
64 processed = f.tell()
65 unprocessed = len(f.read())
66 total = f.tell()
67 if unprocessed:
68 sys.stderr.write("%d processed + %d unprocessed = %d total\n" %
69 (processed, unprocessed, total))
70 return aete
72 def simplify(item):
73 """Recursively replace singleton tuples by their constituent item"""
74 if type(item) is types.ListType:
75 return map(simplify, item)
76 elif type(item) == types.TupleType and len(item) == 2:
77 return simplify(item[1])
78 else:
79 return item
82 # Here follows the aete resource decoder.
83 # It is presented bottom-up instead of top-down because there are direct
84 # references to the lower-level part-decoders from the high-level part-decoders.
86 def getbyte(f, *args):
87 c = f.read(1)
88 if not c:
89 raise EOFError, 'in getbyte' + str(args)
90 return ord(c)
92 def getword(f, *args):
93 getalign(f)
94 s = f.read(2)
95 if len(s) < 2:
96 raise EOFError, 'in getword' + str(args)
97 return (ord(s[0])<<8) | ord(s[1])
99 def getlong(f, *args):
100 getalign(f)
101 s = f.read(4)
102 if len(s) < 4:
103 raise EOFError, 'in getlong' + str(args)
104 return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
106 def getostype(f, *args):
107 getalign(f)
108 s = f.read(4)
109 if len(s) < 4:
110 raise EOFError, 'in getostype' + str(args)
111 return s
113 def getpstr(f, *args):
114 c = f.read(1)
115 if len(c) < 1:
116 raise EOFError, 'in getpstr[1]' + str(args)
117 nbytes = ord(c)
118 if nbytes == 0: return ''
119 s = f.read(nbytes)
120 if len(s) < nbytes:
121 raise EOFError, 'in getpstr[2]' + str(args)
122 return s
124 def getalign(f):
125 if f.tell() & 1:
126 c = f.read(1)
127 ##if c <> '\0':
128 ## print 'align:', `c`
130 def getlist(f, description, getitem):
131 count = getword(f)
132 list = []
133 for i in range(count):
134 list.append(generic(getitem, f))
135 getalign(f)
136 return list
138 def alt_generic(what, f, *args):
139 print "generic", `what`, args
140 res = vageneric(what, f, args)
141 print '->', `res`
142 return res
144 def generic(what, f, *args):
145 if type(what) == types.FunctionType:
146 return apply(what, (f,) + args)
147 if type(what) == types.ListType:
148 record = []
149 for thing in what:
150 item = apply(generic, thing[:1] + (f,) + thing[1:])
151 record.append((thing[1], item))
152 return record
153 return "BAD GENERIC ARGS: %s" % `what`
155 getdata = [
156 (getostype, "type"),
157 (getpstr, "description"),
158 (getword, "flags")
160 getargument = [
161 (getpstr, "name"),
162 (getostype, "keyword"),
163 (getdata, "what")
165 getevent = [
166 (getpstr, "name"),
167 (getpstr, "description"),
168 (getostype, "suite code"),
169 (getostype, "event code"),
170 (getdata, "returns"),
171 (getdata, "accepts"),
172 (getlist, "optional arguments", getargument)
174 getproperty = [
175 (getpstr, "name"),
176 (getostype, "code"),
177 (getdata, "what")
179 getelement = [
180 (getostype, "type"),
181 (getlist, "keyform", getostype)
183 getclass = [
184 (getpstr, "name"),
185 (getostype, "class code"),
186 (getpstr, "description"),
187 (getlist, "properties", getproperty),
188 (getlist, "elements", getelement)
190 getcomparison = [
191 (getpstr, "operator name"),
192 (getostype, "operator ID"),
193 (getpstr, "operator comment"),
195 getenumerator = [
196 (getpstr, "enumerator name"),
197 (getostype, "enumerator ID"),
198 (getpstr, "enumerator comment")
200 getenumeration = [
201 (getostype, "enumeration ID"),
202 (getlist, "enumerator", getenumerator)
204 getsuite = [
205 (getpstr, "suite name"),
206 (getpstr, "suite description"),
207 (getostype, "suite ID"),
208 (getword, "suite level"),
209 (getword, "suite version"),
210 (getlist, "events", getevent),
211 (getlist, "classes", getclass),
212 (getlist, "comparisons", getcomparison),
213 (getlist, "enumerations", getenumeration)
215 getaete = [
216 (getword, "major/minor version in BCD"),
217 (getword, "language code"),
218 (getword, "script code"),
219 (getlist, "suites", getsuite)
222 def compileaete(aete, resinfo, fname):
223 """Generate code for a full aete resource. fname passed for doc purposes"""
224 [version, language, script, suites] = aete
225 major, minor = divmod(version, 256)
226 fss = macfs.FSSpec(fname)
227 creatorsignature, dummy = fss.GetCreatorType()
228 packagename = identify(os.path.basename(fname))
229 if language:
230 packagename = packagename+'_lang%d'%language
231 if script:
232 packagename = packagename+'_script%d'%script
233 if len(packagename) > 27:
234 packagename = packagename[:27]
235 macfs.SetFolder(os.path.join(sys.prefix, ':Mac:Lib:lib-scriptpackages'))
236 fss, ok = macfs.GetDirectory('Package folder for %s'%packagename)
237 if not ok:
238 return
239 pathname = fss.as_pathname()
240 packagename = os.path.split(os.path.normpath(pathname))[1]
241 fss, ok = macfs.GetDirectory('Package folder for base suite (usually StdSuites)')
242 if ok:
243 dirname, basepkgname = os.path.split(os.path.normpath(fss.as_pathname()))
244 if not dirname in sys.path:
245 sys.path.insert(0, dirname)
246 basepackage = __import__(basepkgname)
247 else:
248 basepackage = None
249 macfs.SetFolder(pathname)
250 suitelist = []
251 allprecompinfo = []
252 allsuites = []
253 for suite in suites:
254 code, suite, fss, modname, precompinfo = precompilesuite(suite, basepackage)
255 if not code:
256 continue
257 allprecompinfo = allprecompinfo + precompinfo
258 suiteinfo = suite, fss, modname
259 suitelist.append((code, modname))
260 allsuites.append(suiteinfo)
261 for suiteinfo in allsuites:
262 compilesuite(suiteinfo, major, minor, language, script, fname, basepackage, allprecompinfo)
263 fss, ok = macfs.StandardPutFile('Package module', '__init__.py')
264 if not ok:
265 return
266 fp = open(fss.as_pathname(), 'w')
267 fss.SetCreatorType('Pyth', 'TEXT')
268 fp.write('"""\n')
269 fp.write("Package generated from %s\n"%fname)
270 fp.write("Resource %s resid %d %s\n"%(resinfo[1], resinfo[0], resinfo[2]))
271 fp.write('"""\n')
272 fp.write('import aetools\n')
273 fp.write('Error = aetools.Error\n')
274 for code, modname in suitelist:
275 fp.write("import %s\n" % modname)
276 fp.write("\n\n_code_to_module = {\n")
277 for code, modname in suitelist:
278 fp.write("\t'%s' : %s,\n"%(code, modname))
279 fp.write("}\n\n")
280 fp.write("\n\n_code_to_fullname = {\n")
281 for code, modname in suitelist:
282 fp.write("\t'%s' : ('%s.%s', '%s'),\n"%(code, packagename, modname, modname))
283 fp.write("}\n\n")
284 for code, modname in suitelist:
285 fp.write("from %s import *\n"%modname)
286 if suitelist:
287 fp.write("\n\nclass %s(%s_Events"%(packagename, suitelist[0][1]))
288 for code, modname in suitelist[1:]:
289 fp.write(",\n\t\t%s_Events"%modname)
290 fp.write(",\n\t\taetools.TalkTo):\n")
291 fp.write("\t_signature = '%s'\n\n"%creatorsignature)
292 fp.close()
294 def precompilesuite(suite, basepackage=None):
295 """Parse a single suite without generating the output. This step is needed
296 so we can resolve recursive references by suites to enums/comps/etc declared
297 in other suites"""
298 [name, desc, code, level, version, events, classes, comps, enums] = suite
300 modname = identify(name)
301 if len(modname) > 28:
302 modname = modname[:27]
303 fss, ok = macfs.StandardPutFile('Python output file', modname+'.py')
304 if not ok:
305 return None, None, None, None, None
307 pathname = fss.as_pathname()
308 modname = os.path.splitext(os.path.split(pathname)[1])[0]
310 if basepackage and basepackage._code_to_module.has_key(code):
311 # We are an extension of a baseclass (usually an application extending
312 # Standard_Suite or so). Import everything from our base module
313 basemodule = basepackage._code_to_module[code]
314 else:
315 # We are not an extension.
316 basemodule = None
318 enumsneeded = {}
319 for event in events:
320 findenumsinevent(event, enumsneeded)
322 objc = ObjectCompiler(None, basemodule)
323 for cls in classes:
324 objc.compileclass(cls)
325 for cls in classes:
326 objc.fillclasspropsandelems(cls)
327 for comp in comps:
328 objc.compilecomparison(comp)
329 for enum in enums:
330 objc.compileenumeration(enum)
332 for enum in enumsneeded.keys():
333 objc.checkforenum(enum)
335 objc.dumpindex()
337 precompinfo = objc.getprecompinfo(modname)
339 return code, suite, fss, modname, precompinfo
341 def compilesuite((suite, fss, modname), major, minor, language, script, fname, basepackage, precompinfo):
342 """Generate code for a single suite"""
343 [name, desc, code, level, version, events, classes, comps, enums] = suite
345 pathname = fss.as_pathname()
346 fp = open(fss.as_pathname(), 'w')
347 fss.SetCreatorType('Pyth', 'TEXT')
349 fp.write('"""Suite %s: %s\n' % (name, desc))
350 fp.write("Level %d, version %d\n\n" % (level, version))
351 fp.write("Generated from %s\n"%fname)
352 fp.write("AETE/AEUT resource version %d/%d, language %d, script %d\n" % \
353 (major, minor, language, script))
354 fp.write('"""\n\n')
356 fp.write('import aetools\n')
357 fp.write('import MacOS\n\n')
358 fp.write("_code = %s\n\n"% `code`)
359 if basepackage and basepackage._code_to_module.has_key(code):
360 # We are an extension of a baseclass (usually an application extending
361 # Standard_Suite or so). Import everything from our base module
362 fp.write('from %s import *\n'%basepackage._code_to_fullname[code][0])
363 basemodule = basepackage._code_to_module[code]
364 elif basepackage and basepackage._code_to_module.has_key(code.lower()):
365 # This is needed by CodeWarrior and some others.
366 fp.write('from %s import *\n'%basepackage._code_to_fullname[code.lower()][0])
367 basemodule = basepackage._code_to_module[code.lower()]
368 else:
369 # We are not an extension.
370 basemodule = None
371 compileclassheader(fp, modname, basemodule)
373 enumsneeded = {}
374 if events:
375 for event in events:
376 compileevent(fp, event, enumsneeded)
377 else:
378 fp.write("\tpass\n\n")
380 objc = ObjectCompiler(fp, basemodule, precompinfo)
381 for cls in classes:
382 objc.compileclass(cls)
383 for cls in classes:
384 objc.fillclasspropsandelems(cls)
385 for comp in comps:
386 objc.compilecomparison(comp)
387 for enum in enums:
388 objc.compileenumeration(enum)
390 for enum in enumsneeded.keys():
391 objc.checkforenum(enum)
393 objc.dumpindex()
395 return code, modname
397 def compileclassheader(fp, name, module=None):
398 """Generate class boilerplate"""
399 classname = '%s_Events'%name
400 if module:
401 modshortname = string.split(module.__name__, '.')[-1]
402 baseclassname = '%s_Events'%modshortname
403 fp.write("class %s(%s):\n\n"%(classname, baseclassname))
404 else:
405 fp.write("class %s:\n\n"%classname)
407 def compileevent(fp, event, enumsneeded):
408 """Generate code for a single event"""
409 [name, desc, code, subcode, returns, accepts, arguments] = event
410 funcname = identify(name)
412 # generate name->keyword map
414 if arguments:
415 fp.write("\t_argmap_%s = {\n"%funcname)
416 for a in arguments:
417 fp.write("\t\t%s : %s,\n"%(`identify(a[0])`, `a[1]`))
418 fp.write("\t}\n\n")
421 # Generate function header
423 has_arg = (not is_null(accepts))
424 opt_arg = (has_arg and is_optional(accepts))
426 fp.write("\tdef %s(self, "%funcname)
427 if has_arg:
428 if not opt_arg:
429 fp.write("_object, ") # Include direct object, if it has one
430 else:
431 fp.write("_object=None, ") # Also include if it is optional
432 else:
433 fp.write("_no_object=None, ") # For argument checking
434 fp.write("_attributes={}, **_arguments):\n") # include attribute dict and args
436 # Generate doc string (important, since it may be the only
437 # available documentation, due to our name-remaping)
439 fp.write('\t\t"""%s: %s\n'%(name, desc))
440 if has_arg:
441 fp.write("\t\tRequired argument: %s\n"%getdatadoc(accepts))
442 elif opt_arg:
443 fp.write("\t\tOptional argument: %s\n"%getdatadoc(accepts))
444 for arg in arguments:
445 fp.write("\t\tKeyword argument %s: %s\n"%(identify(arg[0]),
446 getdatadoc(arg[2])))
447 fp.write("\t\tKeyword argument _attributes: AppleEvent attribute dictionary\n")
448 if not is_null(returns):
449 fp.write("\t\tReturns: %s\n"%getdatadoc(returns))
450 fp.write('\t\t"""\n')
452 # Fiddle the args so everything ends up in 'arguments' dictionary
454 fp.write("\t\t_code = %s\n"% `code`)
455 fp.write("\t\t_subcode = %s\n\n"% `subcode`)
457 # Do keyword name substitution
459 if arguments:
460 fp.write("\t\taetools.keysubst(_arguments, self._argmap_%s)\n"%funcname)
461 else:
462 fp.write("\t\tif _arguments: raise TypeError, 'No optional args expected'\n")
464 # Stuff required arg (if there is one) into arguments
466 if has_arg:
467 fp.write("\t\t_arguments['----'] = _object\n")
468 elif opt_arg:
469 fp.write("\t\tif _object:\n")
470 fp.write("\t\t\t_arguments['----'] = _object\n")
471 else:
472 fp.write("\t\tif _no_object != None: raise TypeError, 'No direct arg expected'\n")
473 fp.write("\n")
475 # Do enum-name substitution
477 for a in arguments:
478 if is_enum(a[2]):
479 kname = a[1]
480 ename = a[2][0]
481 if ename <> '****':
482 fp.write("\t\taetools.enumsubst(_arguments, %s, _Enum_%s)\n" %
483 (`kname`, identify(ename)))
484 enumsneeded[ename] = 1
485 fp.write("\n")
487 # Do the transaction
489 fp.write("\t\t_reply, _arguments, _attributes = self.send(_code, _subcode,\n")
490 fp.write("\t\t\t\t_arguments, _attributes)\n")
492 # Error handling
494 fp.write("\t\tif _arguments.has_key('errn'):\n")
495 fp.write("\t\t\traise aetools.Error, aetools.decodeerror(_arguments)\n")
496 fp.write("\t\t# XXXX Optionally decode result\n")
498 # Decode result
500 fp.write("\t\tif _arguments.has_key('----'):\n")
501 if is_enum(returns):
502 fp.write("\t\t\t# XXXX Should do enum remapping here...\n")
503 fp.write("\t\t\treturn _arguments['----']\n")
504 fp.write("\n")
506 # print "\n# Command %s -- %s (%s, %s)" % (`name`, `desc`, `code`, `subcode`)
507 # print "# returns", compiledata(returns)
508 # print "# accepts", compiledata(accepts)
509 # for arg in arguments:
510 # compileargument(arg)
512 def compileargument(arg):
513 [name, keyword, what] = arg
514 print "# %s (%s)" % (name, `keyword`), compiledata(what)
516 def findenumsinevent(event, enumsneeded):
517 """Find all enums for a single event"""
518 [name, desc, code, subcode, returns, accepts, arguments] = event
519 for a in arguments:
520 if is_enum(a[2]):
521 ename = a[2][0]
522 if ename <> '****':
523 enumsneeded[ename] = 1
526 # This class stores the code<->name translations for a single module. It is used
527 # to keep the information while we're compiling the module, but we also keep these objects
528 # around so if one suite refers to, say, an enum in another suite we know where to
529 # find it. Finally, if we really can't find a code, the user can add modules by
530 # hand.
532 class CodeNameMapper:
534 def __init__(self):
535 self.code2name = {
536 "property" : {},
537 "class" : {},
538 "enum" : {},
539 "comparison" : {},
541 self.name2code = {
542 "property" : {},
543 "class" : {},
544 "enum" : {},
545 "comparison" : {},
547 self.modulename = None
548 self.star_imported = 0
550 def addnamecode(self, type, name, code):
551 self.name2code[type][name] = code
552 if not self.code2name[type].has_key(code):
553 self.code2name[type][code] = name
555 def hasname(self, type, name):
556 return self.name2code[type].has_key(name)
558 def hascode(self, type, code):
559 return self.code2name[type].has_key(code)
561 def findcodename(self, type, code):
562 if not self.hascode(type, code):
563 return None, None, None
564 name = self.code2name[type][code]
565 if self.modulename and not self.star_imported:
566 qualname = '%s.%s'%(self.modulename, name)
567 else:
568 qualname = name
569 return name, qualname, self.modulename
571 def getall(self, type):
572 return self.code2name[type].items()
574 def addmodule(self, module, name, star_imported):
575 self.modulename = name
576 self.star_imported = star_imported
577 for code, name in module._propdeclarations.items():
578 self.addnamecode('property', name, code)
579 for code, name in module._classdeclarations.items():
580 self.addnamecode('class', name, code)
581 for code in module._enumdeclarations.keys():
582 self.addnamecode('enum', '_Enum_'+identify(code), code)
583 for code, name in module._compdeclarations.items():
584 self.addnamecode('comparison', name, code)
586 def prepareforexport(self, name=None):
587 if not self.modulename:
588 self.modulename = name
589 return self
591 class ObjectCompiler:
592 def __init__(self, fp, basesuite=None, othernamemappers=None):
593 self.fp = fp
594 self.basesuite = basesuite
595 self.namemappers = [CodeNameMapper()]
596 if othernamemappers:
597 self.othernamemappers = othernamemappers[:]
598 else:
599 self.othernamemappers = []
600 if basesuite:
601 basemapper = CodeNameMapper()
602 basemapper.addmodule(basesuite, '', 1)
603 self.namemappers.append(basemapper)
605 def getprecompinfo(self, modname):
606 list = []
607 for mapper in self.namemappers:
608 emapper = mapper.prepareforexport(modname)
609 if emapper:
610 list.append(emapper)
611 return list
613 def findcodename(self, type, code):
614 while 1:
615 # First try: check whether we already know about this code.
616 for mapper in self.namemappers:
617 if mapper.hascode(type, code):
618 return mapper.findcodename(type, code)
619 # Second try: maybe one of the other modules knows about it.
620 for mapper in self.othernamemappers:
621 if mapper.hascode(type, code):
622 self.othernamemappers.remove(mapper)
623 self.namemappers.append(mapper)
624 if self.fp:
625 self.fp.write("import %s\n"%mapper.modulename)
626 break
627 else:
628 # If all this has failed we ask the user for a guess on where it could
629 # be and retry.
630 if self.fp:
631 m = self.askdefinitionmodule(type, code)
632 else:
633 m = None
634 if not m: return None, None, None
635 mapper = CodeNameMapper()
636 mapper.addmodule(m, m.__name__, 0)
637 self.namemappers.append(mapper)
639 def askdefinitionmodule(self, type, code):
640 fss, ok = macfs.PromptGetFile('Where is %s %s declared?'%(type, code))
641 if not ok: return
642 path, file = os.path.split(fss.as_pathname())
643 modname = os.path.splitext(file)[0]
644 if not path in sys.path:
645 sys.path.insert(0, path)
646 m = __import__(modname)
647 self.fp.write("import %s\n"%modname)
648 return m
650 def compileclass(self, cls):
651 [name, code, desc, properties, elements] = cls
652 pname = identify(name)
653 if self.namemappers[0].hascode('class', code):
654 # plural forms and such
655 othername, dummy, dummy = self.namemappers[0].findcodename('class', code)
656 if self.fp:
657 self.fp.write("\n%s = %s\n"%(pname, othername))
658 else:
659 if self.fp:
660 self.fp.write('\nclass %s(aetools.ComponentItem):\n' % pname)
661 self.fp.write('\t"""%s - %s """\n' % (name, desc))
662 self.fp.write('\twant = %s\n' % `code`)
663 self.namemappers[0].addnamecode('class', pname, code)
664 for prop in properties:
665 self.compileproperty(prop)
666 for elem in elements:
667 self.compileelement(elem)
669 def compileproperty(self, prop):
670 [name, code, what] = prop
671 if code == 'c@#!':
672 # Something silly with plurals. Skip it.
673 return
674 pname = identify(name)
675 if self.namemappers[0].hascode('property', code):
676 # plural forms and such
677 othername, dummy, dummy = self.namemappers[0].findcodename('property', code)
678 if pname == othername:
679 return
680 if self.fp:
681 self.fp.write("\n%s = %s\n"%(pname, othername))
682 else:
683 if self.fp:
684 self.fp.write("class %s(aetools.NProperty):\n" % pname)
685 self.fp.write('\t"""%s - %s """\n' % (name, what[1]))
686 self.fp.write("\twhich = %s\n" % `code`)
687 self.fp.write("\twant = %s\n" % `what[0]`)
688 self.namemappers[0].addnamecode('property', pname, code)
690 def compileelement(self, elem):
691 [code, keyform] = elem
692 if self.fp:
693 self.fp.write("# element %s as %s\n" % (`code`, keyform))
695 def fillclasspropsandelems(self, cls):
696 [name, code, desc, properties, elements] = cls
697 cname = identify(name)
698 if self.namemappers[0].hascode('class', code) and \
699 self.namemappers[0].findcodename('class', code)[0] != cname:
700 # This is an other name (plural or so) for something else. Skip.
701 return
702 plist = []
703 elist = []
704 for prop in properties:
705 [pname, pcode, what] = prop
706 if pcode == 'c@#!':
707 continue
708 pname = identify(pname)
709 plist.append(pname)
710 for elem in elements:
711 [ecode, keyform] = elem
712 if ecode == 'c@#!':
713 continue
714 name, ename, module = self.findcodename('class', ecode)
715 if not name:
716 if self.fp:
717 self.fp.write("# XXXX %s element %s not found!!\n"%(cname, `ecode`))
718 else:
719 elist.append((name, ename))
721 if self.fp:
722 self.fp.write("%s._propdict = {\n"%cname)
723 for n in plist:
724 self.fp.write("\t'%s' : %s,\n"%(n, n))
725 self.fp.write("}\n")
726 self.fp.write("%s._elemdict = {\n"%cname)
727 for n, fulln in elist:
728 self.fp.write("\t'%s' : %s,\n"%(n, fulln))
729 self.fp.write("}\n")
731 def compilecomparison(self, comp):
732 [name, code, comment] = comp
733 iname = identify(name)
734 self.namemappers[0].addnamecode('comparison', iname, code)
735 if self.fp:
736 self.fp.write("class %s(aetools.NComparison):\n" % iname)
737 self.fp.write('\t"""%s - %s """\n' % (name, comment))
739 def compileenumeration(self, enum):
740 [code, items] = enum
741 name = "_Enum_%s" % identify(code)
742 if self.fp:
743 self.fp.write("%s = {\n" % name)
744 for item in items:
745 self.compileenumerator(item)
746 self.fp.write("}\n\n")
747 self.namemappers[0].addnamecode('enum', name, code)
748 return code
750 def compileenumerator(self, item):
751 [name, code, desc] = item
752 self.fp.write("\t%s : %s,\t# %s\n" % (`identify(name)`, `code`, desc))
754 def checkforenum(self, enum):
755 """This enum code is used by an event. Make sure it's available"""
756 name, fullname, module = self.findcodename('enum', enum)
757 if not name:
758 if self.fp:
759 self.fp.write("_Enum_%s = None # XXXX enum %s not found!!\n"%(identify(enum), enum))
760 return
761 if module:
762 if self.fp:
763 self.fp.write("from %s import %s\n"%(module, name))
765 def dumpindex(self):
766 if not self.fp:
767 return
768 self.fp.write("\n#\n# Indices of types declared in this module\n#\n")
769 self.fp.write("_classdeclarations = {\n")
770 for k, v in self.namemappers[0].getall('class'):
771 self.fp.write("\t%s : %s,\n" % (`k`, v))
772 self.fp.write("}\n")
773 self.fp.write("\n_propdeclarations = {\n")
774 for k, v in self.namemappers[0].getall('property'):
775 self.fp.write("\t%s : %s,\n" % (`k`, v))
776 self.fp.write("}\n")
777 self.fp.write("\n_compdeclarations = {\n")
778 for k, v in self.namemappers[0].getall('comparison'):
779 self.fp.write("\t%s : %s,\n" % (`k`, v))
780 self.fp.write("}\n")
781 self.fp.write("\n_enumdeclarations = {\n")
782 for k, v in self.namemappers[0].getall('enum'):
783 self.fp.write("\t%s : %s,\n" % (`k`, v))
784 self.fp.write("}\n")
786 def compiledata(data):
787 [type, description, flags] = data
788 return "%s -- %s %s" % (`type`, `description`, compiledataflags(flags))
790 def is_null(data):
791 return data[0] == 'null'
793 def is_optional(data):
794 return (data[2] & 0x8000)
796 def is_enum(data):
797 return (data[2] & 0x2000)
799 def getdatadoc(data):
800 [type, descr, flags] = data
801 if descr:
802 return descr
803 if type == '****':
804 return 'anything'
805 if type == 'obj ':
806 return 'an AE object reference'
807 return "undocumented, typecode %s"%`type`
809 dataflagdict = {15: "optional", 14: "list", 13: "enum", 12: "mutable"}
810 def compiledataflags(flags):
811 bits = []
812 for i in range(16):
813 if flags & (1<<i):
814 if i in dataflagdict.keys():
815 bits.append(dataflagdict[i])
816 else:
817 bits.append(`i`)
818 return '[%s]' % string.join(bits)
820 def identify(str):
821 """Turn any string into an identifier:
822 - replace space by _
823 - replace other illegal chars by _xx_ (hex code)
824 - prepend _ if the result is a python keyword
826 if not str:
827 return "_empty_ae_name"
828 rv = ''
829 ok = string.ascii_letters + '_'
830 ok2 = ok + string.digits
831 for c in str:
832 if c in ok:
833 rv = rv + c
834 elif c == ' ':
835 rv = rv + '_'
836 else:
837 rv = rv + '_%02.2x_'%ord(c)
838 ok = ok2
839 if keyword.iskeyword(rv):
840 rv = '_' + rv
841 return rv
843 # Call the main program
845 if __name__ == '__main__':
846 main()
847 sys.exit(1)
848 print identify('for')