quick and dirty hex editor in Pure Python

Mitchell Morris mmorris at mindspring.com
Thu Mar 9 23:26:22 CET 2000


I needed a hex editor recently for reasons completely uninteresting to anyone
else, and thought it would be interesting to write one in Pure Python
(tm and patent pending, no doubt) to see how painful it was. In an effort
to acquire even more abuse, I decided to post it here for criticism and
general slagging.

Enjoy!

+Mitchell

P.S. Extra old-timer points will be awarded for recognizing the
free-with-purchase app this derives from.

--- cut here (duh) --------------------------------------------------
#! /usr/bin/python -O

import sys, string, StringIO, cmd

class EOFException: pass

#----------------------------------------------------------------------
class Interpreter(cmd.Cmd):
#----------------------------------------------------------------------
	#--------------------------------------------------
	def __init__(self, name):
	#--------------------------------------------------
		cmd.Cmd.__init__(self)
		self.prompt = '-'
		self.name = name
		self.data = StringIO.StringIO(open(name, 'rb').read())

	#--------------------------------------------------
	def do_help(self, args):
	#--------------------------------------------------
		print """d addr [length]    dump values starting at "addr" for length bytes
e address          enter new data starting at address
w [filename]       save as filename (default = original filename)
q                  quit
x [filename]       save and quit (default = original filename)
"""

	#--------------------------------------------------
	def emptyline(self):
	#--------------------------------------------------
		pass

	#--------------------------------------------------
	def do_q(self, args):
	#--------------------------------------------------
		raise EOFException

	#--------------------------------------------------
	def do_w(self, args):
	#--------------------------------------------------
		args = string.split(args)
		if len(args):
			name = args[0]
		else:
			name = self.name
		open(name, 'wb').write(self.data.getvalue())

	#--------------------------------------------------
	def do_x(self, args):
	#--------------------------------------------------
		self.do_w(args)
		self.do_q(args)

	#--------------------------------------------------
	def dump(self, addr, length):
	#--------------------------------------------------
		self.data.seek(addr)
		data = self.data.read(length)
		for i in range(0, min(length, len(data)), 16):
			print '%08X:' % (addr+i),
			for j in range(0, 16):
				if i+j >= len(data):
					break
				print '%02X' % ord(data[i+j]),
			print ''

	#--------------------------------------------------
	def do_d(self, args):
	#--------------------------------------------------
		args = string.split(args)
		try:
			addr = string.atoi(args[0], 16)
		except IndexError:
			print "missing address arg"
			self.do_help(args)
			return
		try:
			length = string.atoi(args[1], 16)
		except IndexError:
			length = 64
		self.dump(addr, length)

	#--------------------------------------------------
	def do_e(self, args):
	#--------------------------------------------------
		class Inner(cmd.Cmd):
			def __init__(self, addr, data):
				cmd.Cmd.__init__(self)
				self.data = data
				self.addr = addr
				self.set_prompt()
			def set_prompt(self):
				self.data.seek(self.addr)
				ch = self.data.read(1)
				self.prompt = '%08X: %02X ' % (self.addr, ord(ch))
			def do_help(self, args):
				print "enter a blank line to quit"
			def emptyline(self):
				raise EOFException
			def default(self, line):
				try:
					for str in string.split(line):
						self.data.seek(self.addr)
						self.data.write(chr(string.atoi(str, 16)))
						self.addr = self.addr + 1
				except ValueError:
					raise EOFException
				self.set_prompt()
		inner = Inner(string.atoi(args, 16), self.data)
		try:
			inner.cmdloop()
		except EOFException:
			pass

#----------------------------------------------------------------------
if __name__ == "__main__":
#----------------------------------------------------------------------
	try:
		interp = Interpreter(sys.argv[1])
		interp.cmdloop()
	except IndexError:
		print "Usage: %s filename" % sys.argv[0]
	except EOFException:
		pass



More information about the Python-list mailing list