]> granicus.if.org Git - python/commitdiff
Module to merge 'cfrg' resources (to create fat ppc/cfm68k programs
authorJack Jansen <jack.jansen@cwi.nl>
Tue, 6 May 1997 16:14:34 +0000 (16:14 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Tue, 6 May 1997 16:14:34 +0000 (16:14 +0000)
and shared libraries).

Mac/scripts/cfmfile.py [new file with mode: 0644]

diff --git a/Mac/scripts/cfmfile.py b/Mac/scripts/cfmfile.py
new file mode 100644 (file)
index 0000000..b39d1bc
--- /dev/null
@@ -0,0 +1,235 @@
+"""cfmfile - Interface to code fragments on file"""
+import struct
+import Res
+import macfs
+import string
+
+Error = 'cfmfile.Error'
+
+READ = 1
+WRITE = 2
+smAllScripts = -3
+BUFSIZE = 0x100000
+
+class FragmentInfo:
+       """Information on a single fragment"""
+       def __init__(self):
+               self.arch = 'pwpc'
+               self.current_version = 0
+               self.oldest_version = 0
+               self.stacksize = 0
+               self.libdir = 0
+               self.fragtype = 1
+               self.location = 1
+               self.offset = 0
+               self.length = 0
+               self.res_0 = 0
+               self.res_1 = 0
+               self.name = ''
+               self.ifp = None
+               
+       def load(self, data):
+               if len(data) < 43:
+                       raise Error, 'Not enough data in cfrg resource'
+               self.arch = data[:4]
+               self.update, self.current_version, self.oldest_version, \
+                       self.stacksize, self.libdir, self.fragtype, self.location, \
+                       self.offset, self.length, self.res_0, self.res_1, length = \
+                       struct.unpack("llllhbbllllh", data[4:42])
+               namelen = ord(data[42])
+               self.name = data[43:43+namelen]
+               if len(self.name) != namelen:
+                       raise Error, 'Not enough data in cfrg resource'
+               return length
+               
+       def save(self):
+               length = (43+len(self.name)+3) & ~3
+               data = self.arch + struct.pack("llllhbbllllh", self.update, \
+                       self.current_version, self.oldest_version, self.stacksize, \
+                       self.libdir, self.fragtype, self.location, self.offset, \
+                       self.length, self.res_0, self.res_1, length)
+               data = data + chr(len(self.name)) + self.name
+               data = data + ('\0'*(length-len(data)))
+               return data
+               
+       def copydata(self, ofp):
+               """Copy fragment data to a new file, updating self.offset"""
+               if self.location != 1:
+                       raise Error, 'Can only copy kOnDiskFlat (data fork) fragments'
+               if not self.ifp:
+                       raise Error, 'No source file for fragment'
+               # Find out real length (if zero)
+               if self.length == 0:
+                       self.ifp.seek(0, 2)
+                       self.length = self.ifp.tell()
+               # Position input file and record new offset from output file
+               self.ifp.seek(self.offset)
+               self.offset = ofp.tell()
+               l = self.length
+               while l:
+                       if l > BUFSIZE:
+                               ofp.write(self.ifp.read(BUFSIZE))
+                               l = l - BUFSIZE
+                       else:
+                               ofp.write(self.ifp.read(l))
+                               l = 0
+               self.ifp = ofp
+               
+       def setfile(self, ifp):
+               self.ifp = ifp
+               
+class FragmentResource:
+
+       def __init__(self, data):
+               self.load(data)
+
+       def load(self, data):
+               r0, r1, version, r3, r4, r5, r6, nfrag = struct.unpack("llllllll", data[:32])
+               if version != 1:
+                       raise Error, 'Unsupported cfrg version number %d'%version
+               data = data[32:]
+               self.fragments = []
+               for i in range(nfrag):
+                       f = FragmentInfo()
+                       len = f.load(data)
+                       data = data[len:]
+                       self.fragments.append(f)
+               if data:
+                       raise Error, 'Spurious data after fragment descriptions'
+                       
+       def save(self):
+               data = struct.pack("llllllll", 0, 0, 1, 0, 0, 0, 0, len(self.fragments))
+               for f in self.fragments:
+                       data = data+f.save()
+               return data
+                       
+       def setfile(self, ifp):
+               for f in self.fragments:
+                       f.setfile(ifp)
+                       
+       def copydata(self, ofp):
+               for f in self.fragments:
+                       f.copydata(ofp)
+                       
+       def getfragments(self):
+               return self.fragments
+               
+       def addfragments(self, fragments):
+               self.fragments = self.fragments + fragments
+
+class ResourceCollection:
+       def __init__(self, fhandle):
+               self.reslist = []
+               self.fhandle = fhandle
+               oldresfile = Res.CurResFile()
+               Res.UseResFile(fhandle)
+               Res.SetResLoad(0)
+               ntypes = Res.Count1Types()
+               for itype in range(1, 1+ntypes):
+                       type = Res.Get1IndType(itype)
+                       nresources = Res.Count1Resources(type)
+                       for ires in range(1, 1+nresources):
+                               res = Res.Get1IndResource(type, ires)
+                               id, type, name = res.GetResInfo()
+                               self.reslist.append((type, id))
+               Res.SetResLoad(1)
+               Res.UseResFile(oldresfile)
+                       
+       def contains(self, type, id):
+               return (type, id) in self.reslist
+               
+       def getresource(self, type, id):
+               oldresfile = Res.CurResFile()
+               Res.UseResFile(self.fhandle)
+               Res.SetResLoad(1)
+               resource = Res.Get1Resource(type, id)
+               Res.UseResFile(oldresfile)
+               return resource
+               
+       def saveresto(self, type, id, fhandle):
+               oldresfile = Res.CurResFile()
+               resource = self.getresource(type, id)
+               id, type, name = resource.GetResInfo()
+               resource.DetachResource()
+               Res.UseResFile(fhandle)
+               resource.AddResource(type, id, name)
+               Res.UseResFile(oldresfile)
+               
+       def getreslist(self):
+               return self.reslist
+               
+class CfmFile(ResourceCollection, FragmentResource):
+       
+       def __init__(self, fsspec):
+               rfork = Res.FSpOpenResFile(fsspec, READ)
+               dfork = open(fsspec.as_pathname(), 'rb')
+               ResourceCollection.__init__(self, rfork)
+               cfrg_resource = self.getresource('cfrg', 0)
+               FragmentResource.__init__(self, cfrg_resource.data)
+               self.setfile(dfork)
+
+def mergecfmfiles(inputs, output):
+       # Convert inputs/outputs to fsspecs
+       for i in range(len(inputs)):
+               if type(inputs[i]) == type(''):
+                       inputs[i] = macfs.FSSpec(inputs[i])
+       if type(output) == type(''):
+               output = macfs.FSSpec(output)
+               
+       input_list = []
+       for i in inputs:
+               input_list.append(CfmFile(i))
+               
+       # Create output file, if needed
+       creator, tp = inputs[0].GetCreatorType()
+       try:
+               Res.FSpCreateResFile(output, creator, tp, smAllScripts)
+       except Res.Error:
+               pass
+               
+       # Copy fragments
+       dfork = open(output.as_pathname(), 'wb')
+       for i in input_list:
+               i.copydata(dfork)
+       dfork.close()
+               
+       # Merge cfrg's
+       for i in input_list[1:]:
+               input_list[0].addfragments(i.getfragments())
+               
+       old_res_file = Res.CurResFile()
+       rfork = Res.FSpOpenResFile(output, WRITE)
+       Res.UseResFile(rfork)
+       
+       # Write cfrg
+       data = input_list[0].save()
+       cfrg_resource = Res.Resource(data)
+       cfrg_resource.AddResource('cfrg', 0, '')
+       resources_done = [('cfrg', 0)]
+       
+       # Write other resources
+       for i in input_list:
+               todo = i.getreslist()
+               for tp, id in todo:
+                       if (tp, id) in resources_done:
+                               continue
+                       i.saveresto(tp, id, rfork)
+                       resources_done.append(tp, id)
+                       
+def main():
+       list = []
+       while 1:
+               fss, ok = macfs.PromptGetFile("Next input file:", "shlb", "APPL")
+               if not ok: break
+               list.append(fss)
+       if not list:
+               sys.exit(0)
+       output, ok = macfs.StandardPutFile("Output file:")
+       if not ok:
+               sys.exit(0)
+       mergecfmfiles(list, output)
+       
+if __name__ == '__main__':
+       main()
+       
+