summaryrefslogtreecommitdiffstats
path: root/Mac/Contrib/PythonScript/getaete.py
diff options
context:
space:
mode:
Diffstat (limited to 'Mac/Contrib/PythonScript/getaete.py')
-rw-r--r--Mac/Contrib/PythonScript/getaete.py406
1 files changed, 406 insertions, 0 deletions
diff --git a/Mac/Contrib/PythonScript/getaete.py b/Mac/Contrib/PythonScript/getaete.py
new file mode 100644
index 0000000..14beb32
--- /dev/null
+++ b/Mac/Contrib/PythonScript/getaete.py
@@ -0,0 +1,406 @@
+"""
+Produces a 3 dictionaries from application aete's
+to be read by PythonScript
+
+v.02 january 31, 1998 added support for inheriting suites from aeut
+v.03 february 16, 1998 changes to identify
+v.04 february 26, 1998 simplified decode
+v.05 23/04/98 simplified _launch
+
+"""
+import baetools
+import macpath
+import sys
+import os
+import MacOS
+import StringIO
+import types
+from MACFS import *
+import macfs
+import string
+from Res import *
+import struct
+
+# for testing only
+app ='CSOm' #'ezVu'# 'nwSP'#MACS'#
+
+#Restrict the application suites to the dialect we want to use.
+LANG = 0 # 0 = English, 1 = French, 11 = Japanese
+lang = {0:'English', 1:'French', 11:'Japanese'}
+
+#The following are neaded to open the application aete
+kASAppleScriptSuite = 'ascr'
+kGetAETE = 'gdte'
+attributes = {}
+arguments = {}
+
+class AETE(baetools.TalkTo):
+ pass
+
+def Getaete(app):
+ try:
+ data = openaete(app)
+ except MacOS.Error, msg:
+ if msg[0] == -609:
+ _launch(app)
+ data = openaete(app)
+ data = decode(data['----'].data)
+ data = compileaete(data)
+ return data
+
+
+def decode(data):
+ """Decode an aete into a python data structure"""
+ f = StringIO.StringIO(data)
+ aete = generic(getaete, f)
+ return aete
+
+def simplify(item):
+ """Recursively replace singleton tuples by their constituent item"""
+ if type(item) is types.ListType:
+ return map(simplify, item)
+ elif type(item) == types.TupleType and len(item) == 2:
+ return simplify(item[1])
+ else:
+ return item
+
+
+## Here follows the aete resource decoder.
+## It is presented bottom-up instead of top-down because there are direct
+## references to the lower-level part-decoders from the high-level part-decoders.
+#
+def getflag(f, *args):
+ m = ''
+ c = f.read(2)
+ print `c`
+ if not c:
+ raise EOFError, 'in getflag' + str(args)
+ for n in c:
+ m = m + `ord(n)`
+
+def getbyte(f, *args):
+ c = f.read(1)
+ if not c:
+ raise EOFError, 'in getbyte' + str(args)
+ return ord(c)
+
+def getword(f, *args):
+ getalign(f)
+ s = f.read(2)
+ if len(s) < 2:
+ raise EOFError, 'in getword' + str(args)
+ return (ord(s[0])<<8) | ord(s[1])
+
+def getlong(f, *args):
+ getalign(f)
+ s = f.read(4)
+ if len(s) < 4:
+ raise EOFError, 'in getlong' + str(args)
+ return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
+
+def getostype(f, *args):
+ getalign(f)
+ s = f.read(4)
+ if len(s) < 4:
+ raise EOFError, 'in getostype' + str(args)
+ return s
+
+def getpstr(f, *args):
+ c = f.read(1)
+ if len(c) < 1:
+ raise EOFError, 'in getpstr[1]' + str(args)
+ nbytes = ord(c)
+ if nbytes == 0: return ''
+ s = f.read(nbytes)
+ if len(s) < nbytes:
+ raise EOFError, 'in getpstr[2]' + str(args)
+ return s
+
+def getalign(f):
+ if f.tell() & 1:
+ c = f.read(1)
+ ##if c <> '\0':
+ ## print 'align:', `c`
+
+def getlist(f, description, getitem):
+ count = getword(f)
+ list = []
+ for i in range(count):
+ list.append(generic(getitem, f))
+ getalign(f)
+ return list
+
+def alt_generic(what, f, *args):
+ print "generic", `what`, args
+ res = vageneric(what, f, args)
+ print '->', `res`
+ return res
+
+def generic(what, f, *args):
+ if type(what) == types.FunctionType:
+ return apply(what, (f,) + args)
+ if type(what) == types.ListType:
+ record = []
+ for thing in what:
+ item = apply(generic, thing[:1] + (f,) + thing[1:])
+ record.append(item)
+ return record
+ return "BAD GENERIC ARGS: %s" % `what`
+
+getdata = [
+ (getostype, "type"),
+ (getpstr, "description"),
+ (getword, "flags")
+ ]
+getargument = [
+ (getpstr, "name"),
+ (getostype, "keyword"),
+ (getdata, "what")
+ ]
+getevent = [
+ (getpstr, "name"),
+ (getpstr, "description"),
+ (getostype, "suite code"),
+ (getostype, "event code"),
+ (getdata, "returns"),
+ (getdata, "accepts"),
+ (getlist, "optional arguments", getargument)
+ ]
+getproperty = [
+ (getpstr, "name"),
+ (getostype, "code"),
+ (getdata, "what")
+ ]
+getelement = [
+ (getostype, "type"),
+ (getlist, "keyform", getostype)
+ ]
+getclass = [
+ (getpstr, "name"),
+ (getostype, "class code"),
+ (getpstr, "description"),
+ (getlist, "properties", getproperty),
+ (getlist, "elements", getelement)
+ ]
+getcomparison = [
+ (getpstr, "operator name"),
+ (getostype, "operator ID"),
+ (getpstr, "operator comment"),
+ ]
+getenumerator = [
+ (getpstr, "enumerator name"),
+ (getostype, "enumerator ID"),
+ (getpstr, "enumerator comment")
+ ]
+getenumeration = [
+ (getostype, "enumeration ID"),
+ (getlist, "enumerator", getenumerator)
+ ]
+getsuite = [
+ (getpstr, "suite name"),
+ (getpstr, "suite description"),
+ (getostype, "suite ID"),
+ (getword, "suite level"),
+ (getword, "suite version"),
+ (getlist, "events", getevent),
+ (getlist, "classes", getclass),
+ (getlist, "comparisons", getcomparison),
+ (getlist, "enumerations", getenumeration)
+ ]
+getaete = [
+ (getbyte, "major version in BCD"),
+ (getbyte, "minor version in BCD"),
+ (getword, "language code"),
+ (getword, "script code"),
+ (getlist, "suites", getsuite)
+ ]
+
+def compileaete(aete):
+ """Generate dictionary for a full aete resource."""
+ [major, minor, language, script, suites] = aete
+ suitedict = {}
+ gsuites = openaeut()
+ for gsuite in gsuites:
+ if gsuite[0] == 'AppleScript Suite':
+ suite = gsuite
+ suite = compilesuite(suite)
+ suitedict[identify(suite[0])] = suite[1:]
+ for suite in suites:
+ if language == LANG:
+ suitecode = suite[2]
+ if suite[5] == []:
+ for gsuite in gsuites:
+ if suitecode == gsuite[2]:
+ suite = gsuite
+ suite = compilesuite(suite)
+ suitedict[identify(suite[0])] = suite[1:]
+ suitedict = combinesuite(suitedict)
+ return suitedict
+
+def compilesuite(suite):
+ """Generate dictionary for a single suite"""
+ [name, desc, code, level, version, events, classes, comps, enums] = suite
+ eventdict ={}
+ classdict = {}
+ enumdict ={}
+ for event in events:
+ if event[6]:
+ for ev in event[6]:
+ ev[0] = identify(ev[:2])
+ eventdict[identify(event[:2])] = event[1:]
+ for klass in classes:
+ if klass[3]:
+ for kl in klass[3]:
+ kl[0] = identify(kl[:2])
+ classdict[identify(klass[:2])] = klass[1:]
+ for enum in enums:
+ enumdict[enum[0]] = enum[1]
+ return name, eventdict, classdict, enumdict
+
+def combinesuite(suite):
+ """Combines suite dictionaries to seperate event, class, enumeration dictionaries
+ """
+
+ suitelist = []
+ eventDict ={}
+ classDict ={}
+ enumDict ={}
+ for value in suite.values():
+ for key in value[0].keys():
+ val = value[0][key]
+ eventDict[key] = val
+ for key in value[1].keys():
+ val = value[1][key]
+ if key in classDict.keys():
+ nval = classDict[key][2]
+ val[2] = val[2] + nval
+ classDict[key] = val
+ for key in value[2].keys():
+ val = value[2][key]
+ enumDict[key] = val
+ return eventDict, classDict, enumDict
+
+
+illegal_ids = [ "for", "in", "from", "and", "or", "not", "print", "class", "return",
+ "def", "name", 'data' ]
+
+def identify(str):
+ """Turn any string into an identifier:
+ - replace space by _
+ - remove ',' and '-'
+ capitalise
+ """
+ if not str[0]:
+ if str[1] == 'c@#!':
+ return "Every"
+ else:
+ return 'Any'
+ rv = string.replace(str[0], ' ', '_')
+ rv = string.replace(rv, '-', '')
+ rv = string.replace(rv, ',', '')
+ rv = string.capitalize(rv)
+ return rv
+
+
+def openaete(app):
+ """open and read the aete of the target application"""
+ arguments['----'] = LANG
+ _aete = AETE(app)
+ _reply, _arguments, _attributes = _aete.send(kASAppleScriptSuite, kGetAETE, arguments, attributes)
+ if _arguments.has_key('errn'):
+ raise baetools.Error, baetools.decodeerror(_arguments)
+ return _arguments
+
+def openaeut():
+ """Open and read a aeut file.
+ XXXXX This has been temporarily hard coded until a Python aeut is written XXXX"""
+
+ fullname = dialect
+ rf = OpenRFPerm(fullname, 0, 1)
+ try:
+ UseResFile(rf)
+ resources = []
+ for i in range(Count1Resources('aeut')):
+ res = Get1IndResource('aeut', 1+i)
+ resources.append(res)
+ for res in resources:
+ data = res.data
+ data = decode(data)[4]
+ finally:
+ CloseResFile(rf)
+ return data
+
+def dialect():
+ """find the correct Dialect file"""
+
+ dialect = lang[LANG] + " Dialect"
+ try:
+ ##System 8
+ vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kScriptingAdditionsFolderType, 0)
+ fss = macfs.FSSpec((vRefNum, dirID, ''))
+ fss = fss.as_pathname()
+ except macfs.error:
+ ##Sytem 7
+ vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0)
+ fss = macfs.FSSpec((vRefNum, dirID, ''))
+ fss = fss.as_pathname()
+ fss = macpath.join(fss, "Scripting Additions")
+ fss = macpath.join(fss, "Dialect")
+ fss = macpath.join(fss, dialect)
+ return fss
+
+
+#def openosax():
+# """Open and read the aetes of osaxen in the scripting additions folder"""
+#
+# # System 7.x
+# aete = []
+# vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0)
+# fss = macfs.FSSpec((vRefNum, dirID, ''))
+# fss = fss.as_pathname()
+# osax = macpath.join(fss, "Scripting Additions")
+# for file in os.listdir(osax):
+# fullname = macpath.join(osax, file)
+# print fullname
+# rf = OpenRFPerm(fullname, 0, 1)
+# try:
+# UseResFile(rf)
+# resources = []
+# for i in range(Count1Resources('aete')):
+# res = Get1IndResource('aete', 1+i)
+# resources.append(res)
+# for res in resources:
+# data = res.data
+# data = decode(data)[4]
+# finally:
+# CloseResFile(rf)
+# aete.append(data)
+# print data
+
+
+#The following should be replaced by direct access to a python 'aeut'
+
+def _launch(appfile):
+ """Open a file thru the finder. Specify file by name or fsspec"""
+
+# from PythonScript import PyScript
+ import baetypes
+ _finder = AETE('MACS')
+ parameters ={}
+ parameters['----'] = eval("baetypes.ObjectSpecifier('%s', '%s', %s)" % ('appf', 'ID ', `appfile`))
+ _reply, _arguments, _attributes = _finder.send( 'aevt', 'odoc', parameters , attributes = {})
+ if _arguments.has_key('errn'):
+ raise baetools.Error, baetools.decodeerror(_arguments)
+ # XXXX Optionally decode result
+ if _arguments.has_key('----'):
+ return _arguments['----']
+
+
+
+if __name__ == '__main__':
+# import profile
+# profile.run('Getaete(app)', 'Getaeteprof')
+ Getaete(app)
+# openosax()
+# openaete('ascr')
+# sys.exit(1)