cfmfile.py revision 0a8c90248264a8b26970b4473770bcc3df8515f
10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""codefragments.py -- wrapper to modify code fragments."""
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# (c) 1998, Just van Rossum, Letterror
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__version__ = "0.8b3"
60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__author__ = "jvr"
70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
80a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport warnings
90a8c90248264a8b26970b4473770bcc3df8515fJosh Gaowarnings.warnpy3k("the cfmfile module is deprecated and is removed in 3,0",
100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao              stacklevel=2)
110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
120a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport Carbon.File
130a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport struct
140a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import Res
150a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os
160a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys
170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
180a8c90248264a8b26970b4473770bcc3df8515fJosh GaoDEBUG = 0
190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
200a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoerror = "cfm.error"
210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
220a8c90248264a8b26970b4473770bcc3df8515fJosh GaoBUFSIZE = 0x80000
230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
240a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef mergecfmfiles(srclist, dst, architecture = 'fat'):
250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Merge all files in srclist into a new file dst.
260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    If architecture is given, only code fragments of that type will be used:
280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    "pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic"
290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    68k code, since it does not use code fragments to begin with.
300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    If architecture is None, all fragments will be used, enabling FAT binaries.
310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    srclist = list(srclist)
340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for i in range(len(srclist)):
350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        srclist[i] = Carbon.File.pathname(srclist[i])
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    dst = Carbon.File.pathname(dst)
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    dstfile = open(dst, "wb")
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    rf = Res.FSpOpenResFile(dst, 3)
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        dstcfrg = CfrgResource()
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for src in srclist:
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            srccfrg = CfrgResource(src)
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            for frag in srccfrg.fragments:
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if frag.architecture == 'pwpc' and architecture == 'm68k':
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    continue
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if frag.architecture == 'm68k' and architecture == 'pwpc':
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    continue
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                dstcfrg.append(frag)
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                frag.copydata(dstfile)
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        cfrgres = Res.Resource(dstcfrg.build())
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Res.UseResFile(rf)
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        cfrgres.AddResource('cfrg', 0, "")
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    finally:
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        dstfile.close()
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        rf = Res.CloseResFile(rf)
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass CfrgResource:
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, path = None):
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.version = 1
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.fragments = []
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.path = path
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if path is not None and os.path.exists(path):
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            currentresref = Res.CurResFile()
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            resref = Res.FSpOpenResFile(path, 1)
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            Res.UseResFile(resref)
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                try:
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    data = Res.Get1Resource('cfrg', 0).data
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                except Res.Error:
750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    raise Res.Error, "no 'cfrg' resource found", sys.exc_traceback
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            finally:
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                Res.CloseResFile(resref)
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                Res.UseResFile(currentresref)
790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.parse(data)
800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if self.version != 1:
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                raise error, "unknown 'cfrg' resource format"
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def parse(self, data):
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        (res1, res2, self.version,
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            res3, res4, res5, res6,
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.memberCount) = struct.unpack("8l", data[:32])
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = data[32:]
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        while data:
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            frag = FragmentDescriptor(self.path, data)
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            data = data[frag.memberSize:]
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.fragments.append(frag)
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def build(self):
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.memberCount = len(self.fragments)
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount)
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for frag in self.fragments:
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            data = data + frag.build()
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return data
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def append(self, frag):
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.fragments.append(frag)
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass FragmentDescriptor:
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, path, data = None):
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.path = path
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if data is not None:
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.parse(data)
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def parse(self, data):
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.architecture = data[:4]
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        (   self.updatelevel,
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.currentVersion,
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.oldDefVersion,
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.stacksize,
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.applibdir,
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.fragtype,
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.where,
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.offset,
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.length,
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.res1, self.res2,
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42])
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        pname = data[42:self.memberSize]
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.name = pname[1:1+ord(pname[0])]
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def build(self):
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = self.architecture
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = data + struct.pack("4lhBB4l",
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.updatelevel,
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.currentVersion,
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.oldDefVersion,
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.stacksize,
1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.applibdir,
1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.fragtype,
1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.where,
1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.offset,
1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.length,
1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.res1, self.res2)
1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.memberSize = len(data) + 2 + 1 + len(self.name)
1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # pad to 4 byte boundaries
1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.memberSize % 4:
1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.memberSize = self.memberSize + 4 - (self.memberSize % 4)
1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = data + struct.pack("hb", self.memberSize, len(self.name))
1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = data + self.name
1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = data + '\000' * (self.memberSize - len(data))
1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return data
1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def getfragment(self):
1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.where != 1:
1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise error, "can't read fragment, unsupported location"
1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        f = open(self.path, "rb")
1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        f.seek(self.offset)
1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.length:
1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            frag = f.read(self.length)
1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            frag = f.read()
1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        f.close()
1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return frag
1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def copydata(self, outfile):
1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.where != 1:
1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise error, "can't read fragment, unsupported location"
1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        infile = open(self.path, "rb")
1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.length == 0:
1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            infile.seek(0, 2)
1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.length = infile.tell()
1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Position input file and record new offset from output file
1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        infile.seek(self.offset)
1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # pad to 16 byte boundaries
1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        offset = outfile.tell()
1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if offset % 16:
1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            offset = offset + 16 - (offset % 16)
1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        outfile.seek(offset)
1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.offset = offset
1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        l = self.length
1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        while l:
1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if l > BUFSIZE:
1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                outfile.write(infile.read(BUFSIZE))
1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                l = l - BUFSIZE
1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                outfile.write(infile.read(l))
1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                l = 0
1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        infile.close()
188