mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 13:11:29 +00:00 
			
		
		
		
	
		
			
	
	
		
			187 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			187 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | """codefragments.py -- wrapper to modify code fragments.""" | |||
|  | 
 | |||
|  | # <20> 1998, Just van Rossum, Letterror | |||
|  | 
 | |||
|  | __version__ = "0.8b3" | |||
|  | __author__ = "jvr" | |||
|  | 
 | |||
|  | import macfs | |||
|  | import struct | |||
|  | import Res | |||
|  | import os | |||
|  | import sys | |||
|  | 
 | |||
|  | DEBUG = 0 | |||
|  | 
 | |||
|  | error = "cfm.error" | |||
|  | 
 | |||
|  | BUFSIZE = 0x80000 | |||
|  | 
 | |||
|  | def mergecfmfiles(srclist, dst, architecture = 'fat'): | |||
|  | 	"""Merge all files in srclist into a new file dst. 
 | |||
|  | 	 | |||
|  | 	If architecture is given, only code fragments of that type will be used: | |||
|  | 	"pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic" | |||
|  | 	68k code, since it does not use code fragments to begin with. | |||
|  | 	If architecture is None, all fragments will be used, enabling FAT binaries. | |||
|  | 	"""
 | |||
|  | 	 | |||
|  | 	srclist = list(srclist) | |||
|  | 	for i in range(len(srclist)): | |||
|  | 		if type(srclist[i]) == macfs.FSSpecType: | |||
|  | 			srclist[i] = srclist[i].as_pathname() | |||
|  | 	if type(dst) == macfs.FSSpecType: | |||
|  | 		dst = dst.as_pathname() | |||
|  | 	 | |||
|  | 	dstfile = open(dst, "wb") | |||
|  | 	rf = Res.OpenResFile(dst) | |||
|  | 	try: | |||
|  | 		dstcfrg = CfrgResource() | |||
|  | 		for src in srclist: | |||
|  | 			srccfrg = CfrgResource(src) | |||
|  | 			for frag in srccfrg.fragments: | |||
|  | 				if frag.architecture == 'pwpc' and architecture == 'm68k': | |||
|  | 					continue | |||
|  | 				if frag.architecture == 'm68k' and architecture == 'pwpc': | |||
|  | 					continue | |||
|  | 				dstcfrg.append(frag) | |||
|  | 				 | |||
|  | 				frag.copydata(dstfile) | |||
|  | 				 | |||
|  | 		cfrgres = Res.Resource(dstcfrg.build()) | |||
|  | 		Res.UseResFile(rf) | |||
|  | 		cfrgres.AddResource('cfrg', 0, "") | |||
|  | 	finally: | |||
|  | 		dstfile.close() | |||
|  | 		rf = Res.CloseResFile(rf) | |||
|  | 
 | |||
|  | 
 | |||
|  | class CfrgResource: | |||
|  | 	 | |||
|  | 	def __init__(self, path = None): | |||
|  | 		self.version = 1 | |||
|  | 		self.fragments = [] | |||
|  | 		self.path = path | |||
|  | 		if path is not None and os.path.exists(path): | |||
|  | 			currentresref = Res.CurResFile() | |||
|  | 			resref = Res.OpenResFile(path) | |||
|  | 			Res.UseResFile(resref) | |||
|  | 			try: | |||
|  | 				try: | |||
|  | 					data = Res.Get1Resource('cfrg', 0).data | |||
|  | 				except Res.Error: | |||
|  | 					raise Res.Error, "no <20>cfrg<72> resource found", sys.exc_traceback | |||
|  | 			finally: | |||
|  | 				Res.CloseResFile(resref) | |||
|  | 				Res.UseResFile(currentresref) | |||
|  | 			self.parse(data) | |||
|  | 			if self.version <> 1: | |||
|  | 				raise error, "unknown 'cfrg' resource format"	 | |||
|  | 	 | |||
|  | 	def parse(self, data): | |||
|  | 		(res1, res2, self.version,  | |||
|  | 			res3, res4, res5, res6,  | |||
|  | 			self.memberCount) = struct.unpack("8l", data[:32]) | |||
|  | 		data = data[32:] | |||
|  | 		while data: | |||
|  | 			frag = FragmentDescriptor(self.path, data) | |||
|  | 			data = data[frag.memberSize:] | |||
|  | 			self.fragments.append(frag) | |||
|  | 	 | |||
|  | 	def build(self): | |||
|  | 		self.memberCount = len(self.fragments) | |||
|  | 		data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount) | |||
|  | 		for frag in self.fragments: | |||
|  | 			data = data + frag.build() | |||
|  | 		return data | |||
|  | 	 | |||
|  | 	def append(self, frag): | |||
|  | 		self.fragments.append(frag) | |||
|  | 
 | |||
|  | 
 | |||
|  | class FragmentDescriptor: | |||
|  | 	 | |||
|  | 	def __init__(self, path, data = None): | |||
|  | 		self.path = path | |||
|  | 		if data is not None: | |||
|  | 			self.parse(data) | |||
|  | 	 | |||
|  | 	def parse(self, data): | |||
|  | 		self.architecture = data[:4] | |||
|  | 		(	self.updatelevel,  | |||
|  | 			self.currentVersion,  | |||
|  | 			self.oldDefVersion,  | |||
|  | 			self.stacksize, | |||
|  | 			self.applibdir,  | |||
|  | 			self.fragtype, | |||
|  | 			self.where, | |||
|  | 			self.offset, | |||
|  | 			self.length, | |||
|  | 			self.res1, self.res2, | |||
|  | 			self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42]) | |||
|  | 		pname = data[42:self.memberSize] | |||
|  | 		self.name = pname[1:1+ord(pname[0])] | |||
|  | 	 | |||
|  | 	def build(self): | |||
|  | 		data = self.architecture | |||
|  | 		data = data + struct.pack("4lhBB4l", | |||
|  | 				self.updatelevel,  | |||
|  | 				self.currentVersion,  | |||
|  | 				self.oldDefVersion,  | |||
|  | 				self.stacksize, | |||
|  | 				self.applibdir,  | |||
|  | 				self.fragtype, | |||
|  | 				self.where, | |||
|  | 				self.offset, | |||
|  | 				self.length, | |||
|  | 				self.res1, self.res2) | |||
|  | 		self.memberSize = len(data) + 2 + 1 + len(self.name) | |||
|  | 		# pad to 4 byte boundaries | |||
|  | 		if self.memberSize % 4: | |||
|  | 			self.memberSize = self.memberSize + 4 - (self.memberSize % 4) | |||
|  | 		data = data + struct.pack("hb", self.memberSize, len(self.name)) | |||
|  | 		data = data + self.name | |||
|  | 		data = data + '\000' * (self.memberSize - len(data)) | |||
|  | 		return data | |||
|  | 	 | |||
|  | 	def getfragment(self): | |||
|  | 		if self.where <> 1: | |||
|  | 			raise error, "can<EFBFBD>t read fragment, unsupported location" | |||
|  | 		f = open(self.path, "rb") | |||
|  | 		f.seek(self.offset) | |||
|  | 		if self.length: | |||
|  | 			frag = f.read(self.length) | |||
|  | 		else: | |||
|  | 			frag = f.read() | |||
|  | 		f.close() | |||
|  | 		return frag | |||
|  | 	 | |||
|  | 	def copydata(self, outfile): | |||
|  | 		if self.where <> 1: | |||
|  | 			raise error, "can<EFBFBD>t read fragment, unsupported location" | |||
|  | 		infile = open(self.path, "rb") | |||
|  | 		if self.length == 0: | |||
|  | 			infile.seek(0, 2) | |||
|  | 			self.length = infile.tell() | |||
|  | 		 | |||
|  | 		# Position input file and record new offset from output file | |||
|  | 		infile.seek(self.offset) | |||
|  | 		 | |||
|  | 		# pad to 16 byte boundaries | |||
|  | 		offset = outfile.tell() | |||
|  | 		if offset % 16: | |||
|  | 			offset = offset + 16 - (offset % 16) | |||
|  | 		outfile.seek(offset) | |||
|  | 		self.offset = offset | |||
|  | 		 | |||
|  | 		l = self.length | |||
|  | 		while l: | |||
|  | 			if l > BUFSIZE: | |||
|  | 				outfile.write(infile.read(BUFSIZE)) | |||
|  | 				l = l - BUFSIZE | |||
|  | 			else: | |||
|  | 				outfile.write(infile.read(l)) | |||
|  | 				l = 0 | |||
|  | 		infile.close() | |||
|  | 
 |