Add better error reporting for MemoryErrors caused by str->float conversions.
[python.git] / Lib / plat-mac / cfmfile.py
blobddbd46829707d8785f12990f21bcfec6fc9c9dfb
1 """codefragments.py -- wrapper to modify code fragments."""
3 # (c) 1998, Just van Rossum, Letterror
5 __version__ = "0.8b3"
6 __author__ = "jvr"
8 import warnings
9 warnings.warnpy3k("the cfmfile module is deprecated and is removed in 3,0",
10 stacklevel=2)
12 import Carbon.File
13 import struct
14 from Carbon import Res
15 import os
16 import sys
18 DEBUG = 0
20 error = "cfm.error"
22 BUFSIZE = 0x80000
24 def mergecfmfiles(srclist, dst, architecture = 'fat'):
25 """Merge all files in srclist into a new file dst.
27 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 """
33 srclist = list(srclist)
34 for i in range(len(srclist)):
35 srclist[i] = Carbon.File.pathname(srclist[i])
36 dst = Carbon.File.pathname(dst)
38 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)
51 frag.copydata(dstfile)
53 cfrgres = Res.Resource(dstcfrg.build())
54 Res.UseResFile(rf)
55 cfrgres.AddResource('cfrg', 0, "")
56 finally:
57 dstfile.close()
58 rf = Res.CloseResFile(rf)
61 class CfrgResource:
63 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:
81 raise error, "unknown 'cfrg' resource format"
83 def parse(self, data):
84 (res1, res2, self.version,
85 res3, res4, res5, res6,
86 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)
93 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
100 def append(self, frag):
101 self.fragments.append(frag)
104 class FragmentDescriptor:
106 def __init__(self, path, data = None):
107 self.path = path
108 if data is not None:
109 self.parse(data)
111 def parse(self, data):
112 self.architecture = data[:4]
113 ( self.updatelevel,
114 self.currentVersion,
115 self.oldDefVersion,
116 self.stacksize,
117 self.applibdir,
118 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])]
127 def build(self):
128 data = self.architecture
129 data = data + struct.pack("4lhBB4l",
130 self.updatelevel,
131 self.currentVersion,
132 self.oldDefVersion,
133 self.stacksize,
134 self.applibdir,
135 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
149 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
161 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()
169 # Position input file and record new offset from output file
170 infile.seek(self.offset)
172 # 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
179 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()