1
0
mirror of https://github.com/mnaberez/py65.git synced 2024-06-06 20:29:34 +00:00

Do not allow negative numbers for addresses

This commit is contained in:
Mike Naberezny 2012-09-09 14:53:43 -07:00
parent 8c2f88f93d
commit be2a1e59b4
4 changed files with 37 additions and 17 deletions

View File

@ -1,5 +1,8 @@
0.13-dev *Next Release*
- Fixed a bug where negative numbers could be entered
for addresses in the monitor.
0.12 (2012-02-16)
- Fixed a bug that caused ``help cd`` to raise an exception

View File

@ -132,6 +132,14 @@ class MonitorTests(unittest.TestCase):
out = stdout.getvalue()
self.assertEqual("$4000 70 03 BVS $4005\n", out)
def test_do_assemble_constrains_address_to_valid_range(self):
stdout = StringIO()
mon = Monitor(stdout=stdout)
mon.do_assemble("-1 lda #$ab")
out = stdout.getvalue()
self.assertEqual("$0000 a9 ab LDA #$ab\n", out)
def test_help_assemble(self):
stdout = StringIO()
mon = Monitor(stdout=stdout)

View File

@ -97,12 +97,16 @@ class AddressParserTests(unittest.TestCase):
except KeyError, why:
self.assertEqual('Label not found: bad_label', why[0])
def test_number_truncates_address_at_maxwidth_16(self):
def test_number_constrains_address_at_zero_or_above(self):
parser = AddressParser()
self.assertEqual(0x0000, parser.number('-1'))
def test_number_constrains_address_at_maxwidth_16(self):
parser = AddressParser()
parser.labels = {'foo': 0xFFFF}
self.assertEqual(0xFFFF, parser.number('foo+5'))
def test_number_truncates_address_at_maxwidth_24(self):
def test_number_constrains_address_at_maxwidth_24(self):
parser = AddressParser()
parser.maxwidth = 24
parser.labels = {'foo': 0xFFFFFF}

View File

@ -11,18 +11,21 @@ class AddressParser(object):
names that can be substituted for addresses.
"""
self.radix = radix
self.labels = labels
self.maxwidth = maxwidth
self.labels = {}
for k, v in labels.items():
self.labels[k] = self._constrain(v)
def _get_maxwidth(self):
return self._maxwidth
return self._maxwidth
def _set_maxwidth(self, width):
self._maxwidth = width
self._maxaddr = pow(2, width) - 1
maxwidth = property(_get_maxwidth, _set_maxwidth)
def label_for(self, address, default=None):
"""Given an address, return the corresponding label or a default.
"""
@ -35,17 +38,17 @@ class AddressParser(object):
"""Parse a string containing a label or number into an address.
"""
if num.startswith('$'):
return int(num[1:], 16)
return self._constrain(int(num[1:], 16))
elif num.startswith('+'):
return int(num[1:], 10)
return self._constrain(int(num[1:], 10))
elif num.startswith('%'):
return int(num[1:], 2)
return self._constrain(int(num[1:], 2))
elif num in self.labels:
return self.labels[num]
else:
matches = re.match('^([^\s+-]+)\s*([+\-])\s*([$+%]?\d+)$', num)
if matches:
@ -62,15 +65,11 @@ class AddressParser(object):
else:
address = base - offset
if address < 0:
address = 0
if address > self._maxaddr:
address = self._maxaddr
return address
return self._constrain(address)
else:
try:
return int(num, self.radix)
return self._constrain(int(num, self.radix))
except ValueError:
raise KeyError("Label not found: %s" % num)
@ -85,5 +84,11 @@ class AddressParser(object):
start = end = self.number(addresses)
if start > end:
start, end = end, start
start, end = end, start
return (start, end)
def _constrain(self, address):
"""Constrains a number to be within the address range"""
address = max(address, 0)
address = min(address, self._maxaddr)
return address