blob: 309af8754a3a4153e627a2a67fd4b7832ba2d7c3 [file] [log] [blame]
Jack Jansen87440e41998-07-31 09:41:59 +00001"""codefragments.py -- wrapper to modify code fragments."""
2
Jack Jansen3a70e3f2002-09-06 20:43:28 +00003# (c) 1998, Just van Rossum, Letterror
Jack Jansen87440e41998-07-31 09:41:59 +00004
5__version__ = "0.8b3"
6__author__ = "jvr"
7
Benjamin Peterson23681932008-05-12 21:42:13 +00008import warnings
9warnings.warn("the cfmfile module is deprecated and is removed in 3,0",
10 DeprecationWarning, 2)
11
Jack Jansend66071b2003-02-05 15:44:03 +000012import Carbon.File
Jack Jansen87440e41998-07-31 09:41:59 +000013import struct
Jack Jansen5a6fdcd2001-08-25 12:15:04 +000014from Carbon import Res
Jack Jansen87440e41998-07-31 09:41:59 +000015import os
16import sys
17
18DEBUG = 0
19
20error = "cfm.error"
21
22BUFSIZE = 0x80000
23
24def mergecfmfiles(srclist, dst, architecture = 'fat'):
Tim Peters182b5ac2004-07-18 06:16:08 +000025 """Merge all files in srclist into a new file dst.
26
Jack Jansen0ae32202003-04-09 13:25:43 +000027 If architecture is given, only code fragments of that type will be used:
28 "pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic"
29 68k code, since it does not use code fragments to begin with.
30 If architecture is None, all fragments will be used, enabling FAT binaries.
31 """
Tim Peters182b5ac2004-07-18 06:16:08 +000032
Jack Jansen0ae32202003-04-09 13:25:43 +000033 srclist = list(srclist)
34 for i in range(len(srclist)):
35 srclist[i] = Carbon.File.pathname(srclist[i])
36 dst = Carbon.File.pathname(dst)
Tim Peters182b5ac2004-07-18 06:16:08 +000037
Jack Jansen0ae32202003-04-09 13:25:43 +000038 dstfile = open(dst, "wb")
39 rf = Res.FSpOpenResFile(dst, 3)
40 try:
41 dstcfrg = CfrgResource()
42 for src in srclist:
43 srccfrg = CfrgResource(src)
44 for frag in srccfrg.fragments:
45 if frag.architecture == 'pwpc' and architecture == 'm68k':
46 continue
47 if frag.architecture == 'm68k' and architecture == 'pwpc':
48 continue
49 dstcfrg.append(frag)
Tim Peters182b5ac2004-07-18 06:16:08 +000050
Jack Jansen0ae32202003-04-09 13:25:43 +000051 frag.copydata(dstfile)
Tim Peters182b5ac2004-07-18 06:16:08 +000052
Jack Jansen0ae32202003-04-09 13:25:43 +000053 cfrgres = Res.Resource(dstcfrg.build())
54 Res.UseResFile(rf)
55 cfrgres.AddResource('cfrg', 0, "")
56 finally:
57 dstfile.close()
58 rf = Res.CloseResFile(rf)
Jack Jansen87440e41998-07-31 09:41:59 +000059
60
61class CfrgResource:
Tim Peters182b5ac2004-07-18 06:16:08 +000062
Jack Jansen0ae32202003-04-09 13:25:43 +000063 def __init__(self, path = None):
64 self.version = 1
65 self.fragments = []
66 self.path = path
67 if path is not None and os.path.exists(path):
68 currentresref = Res.CurResFile()
69 resref = Res.FSpOpenResFile(path, 1)
70 Res.UseResFile(resref)
71 try:
72 try:
73 data = Res.Get1Resource('cfrg', 0).data
74 except Res.Error:
75 raise Res.Error, "no 'cfrg' resource found", sys.exc_traceback
76 finally:
77 Res.CloseResFile(resref)
78 Res.UseResFile(currentresref)
79 self.parse(data)
80 if self.version <> 1:
Tim Peters182b5ac2004-07-18 06:16:08 +000081 raise error, "unknown 'cfrg' resource format"
82
Jack Jansen0ae32202003-04-09 13:25:43 +000083 def parse(self, data):
Tim Peters182b5ac2004-07-18 06:16:08 +000084 (res1, res2, self.version,
85 res3, res4, res5, res6,
Jack Jansen0ae32202003-04-09 13:25:43 +000086 self.memberCount) = struct.unpack("8l", data[:32])
87 data = data[32:]
88 while data:
89 frag = FragmentDescriptor(self.path, data)
90 data = data[frag.memberSize:]
91 self.fragments.append(frag)
Tim Peters182b5ac2004-07-18 06:16:08 +000092
Jack Jansen0ae32202003-04-09 13:25:43 +000093 def build(self):
94 self.memberCount = len(self.fragments)
95 data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount)
96 for frag in self.fragments:
97 data = data + frag.build()
98 return data
Tim Peters182b5ac2004-07-18 06:16:08 +000099
Jack Jansen0ae32202003-04-09 13:25:43 +0000100 def append(self, frag):
101 self.fragments.append(frag)
Jack Jansen87440e41998-07-31 09:41:59 +0000102
103
104class FragmentDescriptor:
Tim Peters182b5ac2004-07-18 06:16:08 +0000105
Jack Jansen0ae32202003-04-09 13:25:43 +0000106 def __init__(self, path, data = None):
107 self.path = path
108 if data is not None:
109 self.parse(data)
Tim Peters182b5ac2004-07-18 06:16:08 +0000110
Jack Jansen0ae32202003-04-09 13:25:43 +0000111 def parse(self, data):
112 self.architecture = data[:4]
Tim Peters182b5ac2004-07-18 06:16:08 +0000113 ( self.updatelevel,
114 self.currentVersion,
115 self.oldDefVersion,
Jack Jansen0ae32202003-04-09 13:25:43 +0000116 self.stacksize,
Tim Peters182b5ac2004-07-18 06:16:08 +0000117 self.applibdir,
Jack Jansen0ae32202003-04-09 13:25:43 +0000118 self.fragtype,
119 self.where,
120 self.offset,
121 self.length,
122 self.res1, self.res2,
123 self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42])
124 pname = data[42:self.memberSize]
125 self.name = pname[1:1+ord(pname[0])]
Tim Peters182b5ac2004-07-18 06:16:08 +0000126
Jack Jansen0ae32202003-04-09 13:25:43 +0000127 def build(self):
128 data = self.architecture
129 data = data + struct.pack("4lhBB4l",
Tim Peters182b5ac2004-07-18 06:16:08 +0000130 self.updatelevel,
131 self.currentVersion,
132 self.oldDefVersion,
Jack Jansen0ae32202003-04-09 13:25:43 +0000133 self.stacksize,
Tim Peters182b5ac2004-07-18 06:16:08 +0000134 self.applibdir,
Jack Jansen0ae32202003-04-09 13:25:43 +0000135 self.fragtype,
136 self.where,
137 self.offset,
138 self.length,
139 self.res1, self.res2)
140 self.memberSize = len(data) + 2 + 1 + len(self.name)
141 # pad to 4 byte boundaries
142 if self.memberSize % 4:
143 self.memberSize = self.memberSize + 4 - (self.memberSize % 4)
144 data = data + struct.pack("hb", self.memberSize, len(self.name))
145 data = data + self.name
146 data = data + '\000' * (self.memberSize - len(data))
147 return data
Tim Peters182b5ac2004-07-18 06:16:08 +0000148
Jack Jansen0ae32202003-04-09 13:25:43 +0000149 def getfragment(self):
150 if self.where <> 1:
151 raise error, "can't read fragment, unsupported location"
152 f = open(self.path, "rb")
153 f.seek(self.offset)
154 if self.length:
155 frag = f.read(self.length)
156 else:
157 frag = f.read()
158 f.close()
159 return frag
Tim Peters182b5ac2004-07-18 06:16:08 +0000160
Jack Jansen0ae32202003-04-09 13:25:43 +0000161 def copydata(self, outfile):
162 if self.where <> 1:
163 raise error, "can't read fragment, unsupported location"
164 infile = open(self.path, "rb")
165 if self.length == 0:
166 infile.seek(0, 2)
167 self.length = infile.tell()
Tim Peters182b5ac2004-07-18 06:16:08 +0000168
Jack Jansen0ae32202003-04-09 13:25:43 +0000169 # Position input file and record new offset from output file
170 infile.seek(self.offset)
Tim Peters182b5ac2004-07-18 06:16:08 +0000171
Jack Jansen0ae32202003-04-09 13:25:43 +0000172 # pad to 16 byte boundaries
173 offset = outfile.tell()
174 if offset % 16:
175 offset = offset + 16 - (offset % 16)
176 outfile.seek(offset)
177 self.offset = offset
Tim Peters182b5ac2004-07-18 06:16:08 +0000178
Jack Jansen0ae32202003-04-09 13:25:43 +0000179 l = self.length
180 while l:
181 if l > BUFSIZE:
182 outfile.write(infile.read(BUFSIZE))
183 l = l - BUFSIZE
184 else:
185 outfile.write(infile.read(l))
186 l = 0
187 infile.close()