2 gensuitemodule - Generate an AE suite module from an aete/aeut resource
6 Reading and understanding this code is left as an exercise to the reader.
19 from Carbon
.Res
import *
21 DEFAULT_PACKAGEFOLDER
=os
.path
.join(sys
.prefix
, 'Mac', 'Lib', 'lib-scriptpackages')
25 for filename
in sys
.argv
[1:]:
28 fss
, ok
= macfs
.PromptGetFile('Select file with aeut/aete resource:')
31 processfile(fss
.as_pathname())
33 def processfile(fullname
):
34 """Process all resources in a single file"""
36 print "Processing", fullname
37 rf
= macresource
.open_pathname(fullname
)
41 for i
in range(Count1Resources('aete')):
42 res
= Get1IndResource('aete', 1+i
)
44 for i
in range(Count1Resources('aeut')):
45 res
= Get1IndResource('aeut', 1+i
)
47 print "\nLISTING aete+aeut RESOURCES IN", `fullname`
50 print "decoding", res
.GetResInfo(), "..."
53 aetelist
.append((aete
, res
.GetResInfo()))
58 # switch back (needed for dialogs in Python)
60 compileaetelist(aetelist
, fullname
)
62 def compileaetelist(aetelist
, fullname
):
63 for aete
, resinfo
in aetelist
:
64 compileaete(aete
, resinfo
, fullname
)
67 """Decode a resource into a python data structure"""
68 f
= StringIO
.StringIO(data
)
69 aete
= generic(getaete
, f
)
72 unprocessed
= len(f
.read())
75 sys
.stderr
.write("%d processed + %d unprocessed = %d total\n" %
76 (processed
, unprocessed
, total
))
80 """Recursively replace singleton tuples by their constituent item"""
81 if type(item
) is types
.ListType
:
82 return map(simplify
, item
)
83 elif type(item
) == types
.TupleType
and len(item
) == 2:
84 return simplify(item
[1])
89 # Here follows the aete resource decoder.
90 # It is presented bottom-up instead of top-down because there are direct
91 # references to the lower-level part-decoders from the high-level part-decoders.
93 def getbyte(f
, *args
):
96 raise EOFError, 'in getbyte' + str(args
)
99 def getword(f
, *args
):
103 raise EOFError, 'in getword' + str(args
)
104 return (ord(s
[0])<<8) |
ord(s
[1])
106 def getlong(f
, *args
):
110 raise EOFError, 'in getlong' + str(args
)
111 return (ord(s
[0])<<24) |
(ord(s
[1])<<16) |
(ord(s
[2])<<8) |
ord(s
[3])
113 def getostype(f
, *args
):
117 raise EOFError, 'in getostype' + str(args
)
120 def getpstr(f
, *args
):
123 raise EOFError, 'in getpstr[1]' + str(args
)
125 if nbytes
== 0: return ''
128 raise EOFError, 'in getpstr[2]' + str(args
)
135 ## print 'align:', `c`
137 def getlist(f
, description
, getitem
):
140 for i
in range(count
):
141 list.append(generic(getitem
, f
))
145 def alt_generic(what
, f
, *args
):
146 print "generic", `what`
, args
147 res
= vageneric(what
, f
, args
)
151 def generic(what
, f
, *args
):
152 if type(what
) == types
.FunctionType
:
153 return apply(what
, (f
,) + args
)
154 if type(what
) == types
.ListType
:
157 item
= apply(generic
, thing
[:1] + (f
,) + thing
[1:])
158 record
.append((thing
[1], item
))
160 return "BAD GENERIC ARGS: %s" % `what`
164 (getpstr
, "description"),
169 (getostype
, "keyword"),
174 (getpstr
, "description"),
175 (getostype
, "suite code"),
176 (getostype
, "event code"),
177 (getdata
, "returns"),
178 (getdata
, "accepts"),
179 (getlist
, "optional arguments", getargument
)
188 (getlist
, "keyform", getostype
)
192 (getostype
, "class code"),
193 (getpstr
, "description"),
194 (getlist
, "properties", getproperty
),
195 (getlist
, "elements", getelement
)
198 (getpstr
, "operator name"),
199 (getostype
, "operator ID"),
200 (getpstr
, "operator comment"),
203 (getpstr
, "enumerator name"),
204 (getostype
, "enumerator ID"),
205 (getpstr
, "enumerator comment")
208 (getostype
, "enumeration ID"),
209 (getlist
, "enumerator", getenumerator
)
212 (getpstr
, "suite name"),
213 (getpstr
, "suite description"),
214 (getostype
, "suite ID"),
215 (getword
, "suite level"),
216 (getword
, "suite version"),
217 (getlist
, "events", getevent
),
218 (getlist
, "classes", getclass
),
219 (getlist
, "comparisons", getcomparison
),
220 (getlist
, "enumerations", getenumeration
)
223 (getword
, "major/minor version in BCD"),
224 (getword
, "language code"),
225 (getword
, "script code"),
226 (getlist
, "suites", getsuite
)
229 def compileaete(aete
, resinfo
, fname
):
230 """Generate code for a full aete resource. fname passed for doc purposes"""
231 [version
, language
, script
, suites
] = aete
232 major
, minor
= divmod(version
, 256)
233 fss
= macfs
.FSSpec(fname
)
234 creatorsignature
, dummy
= fss
.GetCreatorType()
235 packagename
= identify(os
.path
.splitext(os
.path
.basename(fname
))[0])
237 packagename
= packagename
+'_lang%d'%language
239 packagename
= packagename
+'_script%d'%script
240 if len(packagename
) > 27:
241 packagename
= packagename
[:27]
242 macfs
.SetFolder(DEFAULT_PACKAGEFOLDER
)
243 fss
, ok
= macfs
.GetDirectory('Create and select package folder for %s'%packagename
)
246 pathname
= fss
.as_pathname()
247 packagename
= os
.path
.split(os
.path
.normpath(pathname
))[1]
248 fss
, ok
= macfs
.GetDirectory('Package folder for base suite (usually StdSuites)')
250 dirname
, basepkgname
= os
.path
.split(os
.path
.normpath(fss
.as_pathname()))
251 if not dirname
in sys
.path
:
252 sys
.path
.insert(0, dirname
)
253 basepackage
= __import__(basepkgname
)
256 macfs
.SetFolder(pathname
)
261 code
, suite
, fss
, modname
, precompinfo
= precompilesuite(suite
, basepackage
)
264 allprecompinfo
= allprecompinfo
+ precompinfo
265 suiteinfo
= suite
, fss
, modname
266 suitelist
.append((code
, modname
))
267 allsuites
.append(suiteinfo
)
268 for suiteinfo
in allsuites
:
269 compilesuite(suiteinfo
, major
, minor
, language
, script
, fname
, basepackage
, allprecompinfo
)
270 fss
, ok
= macfs
.StandardPutFile('Package module', '__init__.py')
273 fp
= open(fss
.as_pathname(), 'w')
274 fss
.SetCreatorType('Pyth', 'TEXT')
276 fp
.write("Package generated from %s\n"%fname
)
277 fp
.write("Resource %s resid %d %s\n"%(resinfo
[1], resinfo
[0], resinfo
[2]))
279 fp
.write('import aetools\n')
280 fp
.write('Error = aetools.Error\n')
281 for code
, modname
in suitelist
:
282 fp
.write("import %s\n" % modname
)
283 fp
.write("\n\n_code_to_module = {\n")
284 for code
, modname
in suitelist
:
285 fp
.write("\t'%s' : %s,\n"%(code
, modname
))
287 fp
.write("\n\n_code_to_fullname = {\n")
288 for code
, modname
in suitelist
:
289 fp
.write("\t'%s' : ('%s.%s', '%s'),\n"%(code
, packagename
, modname
, modname
))
291 for code
, modname
in suitelist
:
292 fp
.write("from %s import *\n"%modname
)
294 fp
.write("\n\nclass %s(%s_Events"%(packagename
, suitelist
[0][1]))
295 for code
, modname
in suitelist
[1:]:
296 fp
.write(",\n\t\t%s_Events"%modname
)
297 fp
.write(",\n\t\taetools.TalkTo):\n")
298 fp
.write("\t_signature = %s\n\n"%`creatorsignature`
)
301 def precompilesuite(suite
, basepackage
=None):
302 """Parse a single suite without generating the output. This step is needed
303 so we can resolve recursive references by suites to enums/comps/etc declared
305 [name
, desc
, code
, level
, version
, events
, classes
, comps
, enums
] = suite
307 modname
= identify(name
)
308 if len(modname
) > 28:
309 modname
= modname
[:27]
310 fss
, ok
= macfs
.StandardPutFile('Python output file', modname
+'.py')
312 return None, None, None, None, None
314 pathname
= fss
.as_pathname()
315 modname
= os
.path
.splitext(os
.path
.split(pathname
)[1])[0]
317 if basepackage
and basepackage
._code
_to
_module
.has_key(code
):
318 # We are an extension of a baseclass (usually an application extending
319 # Standard_Suite or so). Import everything from our base module
320 basemodule
= basepackage
._code
_to
_module
[code
]
322 # We are not an extension.
327 findenumsinevent(event
, enumsneeded
)
329 objc
= ObjectCompiler(None, basemodule
)
331 objc
.compileclass(cls
)
333 objc
.fillclasspropsandelems(cls
)
335 objc
.compilecomparison(comp
)
337 objc
.compileenumeration(enum
)
339 for enum
in enumsneeded
.keys():
340 objc
.checkforenum(enum
)
344 precompinfo
= objc
.getprecompinfo(modname
)
346 return code
, suite
, fss
, modname
, precompinfo
348 def compilesuite((suite
, fss
, modname
), major
, minor
, language
, script
, fname
, basepackage
, precompinfo
):
349 """Generate code for a single suite"""
350 [name
, desc
, code
, level
, version
, events
, classes
, comps
, enums
] = suite
352 pathname
= fss
.as_pathname()
353 fp
= open(fss
.as_pathname(), 'w')
354 fss
.SetCreatorType('Pyth', 'TEXT')
356 fp
.write('"""Suite %s: %s\n' % (name
, desc
))
357 fp
.write("Level %d, version %d\n\n" % (level
, version
))
358 fp
.write("Generated from %s\n"%fname
)
359 fp
.write("AETE/AEUT resource version %d/%d, language %d, script %d\n" % \
360 (major
, minor
, language
, script
))
363 fp
.write('import aetools\n')
364 fp
.write('import MacOS\n\n')
365 fp
.write("_code = %s\n\n"% `code`
)
366 if basepackage
and basepackage
._code
_to
_module
.has_key(code
):
367 # We are an extension of a baseclass (usually an application extending
368 # Standard_Suite or so). Import everything from our base module
369 fp
.write('from %s import *\n'%basepackage
._code
_to
_fullname
[code
][0])
370 basemodule
= basepackage
._code
_to
_module
[code
]
371 elif basepackage
and basepackage
._code
_to
_module
.has_key(code
.lower()):
372 # This is needed by CodeWarrior and some others.
373 fp
.write('from %s import *\n'%basepackage
._code
_to
_fullname
[code
.lower()][0])
374 basemodule
= basepackage
._code
_to
_module
[code
.lower()]
376 # We are not an extension.
378 compileclassheader(fp
, modname
, basemodule
)
383 compileevent(fp
, event
, enumsneeded
)
385 fp
.write("\tpass\n\n")
387 objc
= ObjectCompiler(fp
, basemodule
, precompinfo
)
389 objc
.compileclass(cls
)
391 objc
.fillclasspropsandelems(cls
)
393 objc
.compilecomparison(comp
)
395 objc
.compileenumeration(enum
)
397 for enum
in enumsneeded
.keys():
398 objc
.checkforenum(enum
)
404 def compileclassheader(fp
, name
, module
=None):
405 """Generate class boilerplate"""
406 classname
= '%s_Events'%name
408 modshortname
= string
.split(module
.__name
__, '.')[-1]
409 baseclassname
= '%s_Events'%modshortname
410 fp
.write("class %s(%s):\n\n"%(classname
, baseclassname
))
412 fp
.write("class %s:\n\n"%classname
)
414 def compileevent(fp
, event
, enumsneeded
):
415 """Generate code for a single event"""
416 [name
, desc
, code
, subcode
, returns
, accepts
, arguments
] = event
417 funcname
= identify(name
)
419 # generate name->keyword map
422 fp
.write("\t_argmap_%s = {\n"%funcname
)
424 fp
.write("\t\t%s : %s,\n"%(`
identify(a
[0])`
, `a
[1]`
))
428 # Generate function header
430 has_arg
= (not is_null(accepts
))
431 opt_arg
= (has_arg
and is_optional(accepts
))
433 fp
.write("\tdef %s(self, "%funcname
)
436 fp
.write("_object, ") # Include direct object, if it has one
438 fp
.write("_object=None, ") # Also include if it is optional
440 fp
.write("_no_object=None, ") # For argument checking
441 fp
.write("_attributes={}, **_arguments):\n") # include attribute dict and args
443 # Generate doc string (important, since it may be the only
444 # available documentation, due to our name-remaping)
446 fp
.write('\t\t"""%s: %s\n'%(name
, desc
))
448 fp
.write("\t\tRequired argument: %s\n"%getdatadoc
(accepts
))
450 fp
.write("\t\tOptional argument: %s\n"%getdatadoc
(accepts
))
451 for arg
in arguments
:
452 fp
.write("\t\tKeyword argument %s: %s\n"%(identify(arg
[0]),
454 fp
.write("\t\tKeyword argument _attributes: AppleEvent attribute dictionary\n")
455 if not is_null(returns
):
456 fp
.write("\t\tReturns: %s\n"%getdatadoc
(returns
))
457 fp
.write('\t\t"""\n')
459 # Fiddle the args so everything ends up in 'arguments' dictionary
461 fp
.write("\t\t_code = %s\n"% `code`
)
462 fp
.write("\t\t_subcode = %s\n\n"% `subcode`
)
464 # Do keyword name substitution
467 fp
.write("\t\taetools.keysubst(_arguments, self._argmap_%s)\n"%funcname
)
469 fp
.write("\t\tif _arguments: raise TypeError, 'No optional args expected'\n")
471 # Stuff required arg (if there is one) into arguments
474 fp
.write("\t\t_arguments['----'] = _object\n")
476 fp
.write("\t\tif _object:\n")
477 fp
.write("\t\t\t_arguments['----'] = _object\n")
479 fp
.write("\t\tif _no_object != None: raise TypeError, 'No direct arg expected'\n")
482 # Do enum-name substitution
489 fp
.write("\t\taetools.enumsubst(_arguments, %s, _Enum_%s)\n" %
490 (`kname`
, identify(ename
)))
491 enumsneeded
[ename
] = 1
496 fp
.write("\t\t_reply, _arguments, _attributes = self.send(_code, _subcode,\n")
497 fp
.write("\t\t\t\t_arguments, _attributes)\n")
501 fp
.write("\t\tif _arguments.get('errn', 0):\n")
502 fp
.write("\t\t\traise aetools.Error, aetools.decodeerror(_arguments)\n")
503 fp
.write("\t\t# XXXX Optionally decode result\n")
507 fp
.write("\t\tif _arguments.has_key('----'):\n")
509 fp
.write("\t\t\t# XXXX Should do enum remapping here...\n")
510 fp
.write("\t\t\treturn _arguments['----']\n")
513 # print "\n# Command %s -- %s (%s, %s)" % (`name`, `desc`, `code`, `subcode`)
514 # print "# returns", compiledata(returns)
515 # print "# accepts", compiledata(accepts)
516 # for arg in arguments:
517 # compileargument(arg)
519 def compileargument(arg
):
520 [name
, keyword
, what
] = arg
521 print "# %s (%s)" % (name
, `keyword`
), compiledata(what
)
523 def findenumsinevent(event
, enumsneeded
):
524 """Find all enums for a single event"""
525 [name
, desc
, code
, subcode
, returns
, accepts
, arguments
] = event
530 enumsneeded
[ename
] = 1
533 # This class stores the code<->name translations for a single module. It is used
534 # to keep the information while we're compiling the module, but we also keep these objects
535 # around so if one suite refers to, say, an enum in another suite we know where to
536 # find it. Finally, if we really can't find a code, the user can add modules by
539 class CodeNameMapper
:
554 self
.modulename
= None
555 self
.star_imported
= 0
557 def addnamecode(self
, type, name
, code
):
558 self
.name2code
[type][name
] = code
559 if not self
.code2name
[type].has_key(code
):
560 self
.code2name
[type][code
] = name
562 def hasname(self
, type, name
):
563 return self
.name2code
[type].has_key(name
)
565 def hascode(self
, type, code
):
566 return self
.code2name
[type].has_key(code
)
568 def findcodename(self
, type, code
):
569 if not self
.hascode(type, code
):
570 return None, None, None
571 name
= self
.code2name
[type][code
]
572 if self
.modulename
and not self
.star_imported
:
573 qualname
= '%s.%s'%(self
.modulename
, name
)
576 return name
, qualname
, self
.modulename
578 def getall(self
, type):
579 return self
.code2name
[type].items()
581 def addmodule(self
, module
, name
, star_imported
):
582 self
.modulename
= name
583 self
.star_imported
= star_imported
584 for code
, name
in module
._propdeclarations
.items():
585 self
.addnamecode('property', name
, code
)
586 for code
, name
in module
._classdeclarations
.items():
587 self
.addnamecode('class', name
, code
)
588 for code
in module
._enumdeclarations
.keys():
589 self
.addnamecode('enum', '_Enum_'+identify(code
), code
)
590 for code
, name
in module
._compdeclarations
.items():
591 self
.addnamecode('comparison', name
, code
)
593 def prepareforexport(self
, name
=None):
594 if not self
.modulename
:
595 self
.modulename
= name
598 class ObjectCompiler
:
599 def __init__(self
, fp
, basesuite
=None, othernamemappers
=None):
601 self
.basesuite
= basesuite
602 self
.namemappers
= [CodeNameMapper()]
604 self
.othernamemappers
= othernamemappers
[:]
606 self
.othernamemappers
= []
608 basemapper
= CodeNameMapper()
609 basemapper
.addmodule(basesuite
, '', 1)
610 self
.namemappers
.append(basemapper
)
612 def getprecompinfo(self
, modname
):
614 for mapper
in self
.namemappers
:
615 emapper
= mapper
.prepareforexport(modname
)
620 def findcodename(self
, type, code
):
622 # First try: check whether we already know about this code.
623 for mapper
in self
.namemappers
:
624 if mapper
.hascode(type, code
):
625 return mapper
.findcodename(type, code
)
626 # Second try: maybe one of the other modules knows about it.
627 for mapper
in self
.othernamemappers
:
628 if mapper
.hascode(type, code
):
629 self
.othernamemappers
.remove(mapper
)
630 self
.namemappers
.append(mapper
)
632 self
.fp
.write("import %s\n"%mapper
.modulename
)
635 # If all this has failed we ask the user for a guess on where it could
638 m
= self
.askdefinitionmodule(type, code
)
641 if not m
: return None, None, None
642 mapper
= CodeNameMapper()
643 mapper
.addmodule(m
, m
.__name
__, 0)
644 self
.namemappers
.append(mapper
)
646 def askdefinitionmodule(self
, type, code
):
647 fss
, ok
= macfs
.PromptGetFile('Where is %s %s declared?'%(type, code
))
649 path
, file = os
.path
.split(fss
.as_pathname())
650 modname
= os
.path
.splitext(file)[0]
651 if not path
in sys
.path
:
652 sys
.path
.insert(0, path
)
653 m
= __import__(modname
)
654 self
.fp
.write("import %s\n"%modname
)
657 def compileclass(self
, cls
):
658 [name
, code
, desc
, properties
, elements
] = cls
659 pname
= identify(name
)
660 if self
.namemappers
[0].hascode('class', code
):
661 # plural forms and such
662 othername
, dummy
, dummy
= self
.namemappers
[0].findcodename('class', code
)
664 self
.fp
.write("\n%s = %s\n"%(pname
, othername
))
667 self
.fp
.write('\nclass %s(aetools.ComponentItem):\n' % pname
)
668 self
.fp
.write('\t"""%s - %s """\n' % (name
, desc
))
669 self
.fp
.write('\twant = %s\n' % `code`
)
670 self
.namemappers
[0].addnamecode('class', pname
, code
)
671 for prop
in properties
:
672 self
.compileproperty(prop
)
673 for elem
in elements
:
674 self
.compileelement(elem
)
676 def compileproperty(self
, prop
):
677 [name
, code
, what
] = prop
679 # Something silly with plurals. Skip it.
681 pname
= identify(name
)
682 if self
.namemappers
[0].hascode('property', code
):
683 # plural forms and such
684 othername
, dummy
, dummy
= self
.namemappers
[0].findcodename('property', code
)
685 if pname
== othername
:
688 self
.fp
.write("\n%s = %s\n"%(pname
, othername
))
691 self
.fp
.write("class %s(aetools.NProperty):\n" % pname
)
692 self
.fp
.write('\t"""%s - %s """\n' % (name
, what
[1]))
693 self
.fp
.write("\twhich = %s\n" % `code`
)
694 self
.fp
.write("\twant = %s\n" % `what
[0]`
)
695 self
.namemappers
[0].addnamecode('property', pname
, code
)
697 def compileelement(self
, elem
):
698 [code
, keyform
] = elem
700 self
.fp
.write("# element %s as %s\n" % (`code`
, keyform
))
702 def fillclasspropsandelems(self
, cls
):
703 [name
, code
, desc
, properties
, elements
] = cls
704 cname
= identify(name
)
705 if self
.namemappers
[0].hascode('class', code
) and \
706 self
.namemappers
[0].findcodename('class', code
)[0] != cname
:
707 # This is an other name (plural or so) for something else. Skip.
711 for prop
in properties
:
712 [pname
, pcode
, what
] = prop
715 pname
= identify(pname
)
717 for elem
in elements
:
718 [ecode
, keyform
] = elem
721 name
, ename
, module
= self
.findcodename('class', ecode
)
724 self
.fp
.write("# XXXX %s element %s not found!!\n"%(cname
, `ecode`
))
726 elist
.append((name
, ename
))
729 self
.fp
.write("%s._propdict = {\n"%cname
)
731 self
.fp
.write("\t'%s' : %s,\n"%(n
, n
))
733 self
.fp
.write("%s._elemdict = {\n"%cname
)
734 for n
, fulln
in elist
:
735 self
.fp
.write("\t'%s' : %s,\n"%(n
, fulln
))
738 def compilecomparison(self
, comp
):
739 [name
, code
, comment
] = comp
740 iname
= identify(name
)
741 self
.namemappers
[0].addnamecode('comparison', iname
, code
)
743 self
.fp
.write("class %s(aetools.NComparison):\n" % iname
)
744 self
.fp
.write('\t"""%s - %s """\n' % (name
, comment
))
746 def compileenumeration(self
, enum
):
748 name
= "_Enum_%s" % identify(code
)
750 self
.fp
.write("%s = {\n" % name
)
752 self
.compileenumerator(item
)
753 self
.fp
.write("}\n\n")
754 self
.namemappers
[0].addnamecode('enum', name
, code
)
757 def compileenumerator(self
, item
):
758 [name
, code
, desc
] = item
759 self
.fp
.write("\t%s : %s,\t# %s\n" % (`
identify(name
)`
, `code`
, desc
))
761 def checkforenum(self
, enum
):
762 """This enum code is used by an event. Make sure it's available"""
763 name
, fullname
, module
= self
.findcodename('enum', enum
)
766 self
.fp
.write("_Enum_%s = None # XXXX enum %s not found!!\n"%(identify(enum
), enum
))
770 self
.fp
.write("from %s import %s\n"%(module
, name
))
775 self
.fp
.write("\n#\n# Indices of types declared in this module\n#\n")
776 self
.fp
.write("_classdeclarations = {\n")
777 for k
, v
in self
.namemappers
[0].getall('class'):
778 self
.fp
.write("\t%s : %s,\n" % (`k`
, v
))
780 self
.fp
.write("\n_propdeclarations = {\n")
781 for k
, v
in self
.namemappers
[0].getall('property'):
782 self
.fp
.write("\t%s : %s,\n" % (`k`
, v
))
784 self
.fp
.write("\n_compdeclarations = {\n")
785 for k
, v
in self
.namemappers
[0].getall('comparison'):
786 self
.fp
.write("\t%s : %s,\n" % (`k`
, v
))
788 self
.fp
.write("\n_enumdeclarations = {\n")
789 for k
, v
in self
.namemappers
[0].getall('enum'):
790 self
.fp
.write("\t%s : %s,\n" % (`k`
, v
))
793 def compiledata(data
):
794 [type, description
, flags
] = data
795 return "%s -- %s %s" % (`
type`
, `description`
, compiledataflags(flags
))
798 return data
[0] == 'null'
800 def is_optional(data
):
801 return (data
[2] & 0x8000)
804 return (data
[2] & 0x2000)
806 def getdatadoc(data
):
807 [type, descr
, flags
] = data
813 return 'an AE object reference'
814 return "undocumented, typecode %s"%`
type`
816 dataflagdict
= {15: "optional", 14: "list", 13: "enum", 12: "mutable"}
817 def compiledataflags(flags
):
821 if i
in dataflagdict
.keys():
822 bits
.append(dataflagdict
[i
])
825 return '[%s]' % string
.join(bits
)
828 """Turn any string into an identifier:
830 - replace other illegal chars by _xx_ (hex code)
831 - prepend _ if the result is a python keyword
834 return "_empty_ae_name"
836 ok
= string
.ascii_letters
+ '_'
837 ok2
= ok
+ string
.digits
844 rv
= rv
+ '_%02.2x_'%ord(c
)
846 if keyword
.iskeyword(rv
):
850 # Call the main program
852 if __name__
== '__main__':
855 print identify('for')