mirror of
1
0
Fork 0

options »rows« added, calculations in value-fields

This commit is contained in:
Sebastian Walz 2018-10-21 05:03:08 +02:00 committed by GitHub
parent be7078f82a
commit 926e95143c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 76 additions and 67 deletions

143
protocol
View File

@ -56,7 +56,7 @@
################################################################################
# STANDARD LIBRARY IMPORTS
import sys
import sys, re
from datetime import date
# INTERNAL IMPORTS
@ -88,17 +88,18 @@ class Protocol():
Class constructor.
@param spec is the textual specification that describes the protocol.
"""
self.hdr_char_start="+" # Character for start of the border line
self.hdr_char_end="+" # Character for end of the border line
self.hdr_char_fill_odd="+" # Fill character for border odd positions
self.hdr_char_fill_even="-" # Fill character for border even positions
self.hdr_char_sep="|" # Field separator character
self.bits_per_line=32 # Number of bits per line
self.base_of_top_tens=10 # Base of top numbers
self.do_print_top_tens=True # True: print top numbers for bit tens
self.do_print_top_units=True # True: print top numbers for bit units
self.field_list=[] # Header fields to be printed out
self.parse_spec(spec) # Parse the received spec and populate self.field_list
self.hdr_char_start = "+" # Character for start of the border line
self.hdr_char_end = "+" # Character for end of the border line
self.hdr_char_fill_odd = "+" # Fill character for border odd positions
self.hdr_char_fill_even = "-" # Fill character for border even positions
self.hdr_char_sep = "|" # Field separator character
self.bits_per_line = 32 # Number of bits per line
self.base_of_top_tens = 10 # Base of top numbers
self.do_print_top_tens = True # True: print top numbers for bit tens
self.do_print_top_units = True # True: print top numbers for bit units
self.do_print_line_number = 0 # >0: print line numbers on left side
self.field_list = [] # Header fields to be printed out
self.parse_spec(spec) # Parse the received spec and populate self.field_list
def parse_spec(self, spec):
@ -120,19 +121,44 @@ class Protocol():
fields=spec
opts=None
# Parse field spec
items=fields.split(",")
for item in items:
try:
text, bits = item.split(":")
bits=int(bits)
if bits<=0:
raise ProtocolException("FATAL: Fields must be at least one bit long (%s)" %spec)
parts = item.split(":")
if len(parts)==1:
if item in specs.protocols:
self.parse_spec(specs.protocols[item])
else:
start_with_the_same=[]
for spec in specs.protocols:
if spec.startswith(item):
start_with_the_same.append(spec)
if len(start_with_the_same)==1:
self.parse_spec(specs.protocols[start_with_the_same[0]])
elif len(start_with_the_same)==0:
raise ProtocolException("FATAL: neither does supplied protocol '%s' exist nor does any known protocol start with that." % item)
else:
fail = "Ambiguous protocol specifier '%s'. Did you mean any of these?" % item
for spec in start_with_the_same:
fail += "\n %s" % spec
raise ProtocolException(fail)
else:
text = parts[0]
for item in range(1, len(parts)-1):
text += ":" + parts[item]
bits = parts[-1]
bits = bits.replace("bytes", "8").replace("qwords", "64").replace("dwords", "32").replace("words", "16").replace("double", "64").replace("floats", "32")
if re.match("^[0-9+-/\*~|&^<>()]+$", bits):
bits=eval(bits)
if bits<=0:
raise ProtocolException("FATAL: Fields must be at least one bit long (%s)" % spec)
else:
raise ProtocolException("FATAL: invalid number of bits (%s)" % bits)
self.field_list.append({"text":text, "len":bits})
except ProtocolException:
raise
except:
raise ProtocolException("FATAL: Invalid field_list specification (%s)" %spec)
self.field_list.append({"text":text, "len":bits})
raise ProtocolException("FATAL: Invalid field_list specification (%s)" % spec)
# Parse options
if opts is not None:
@ -141,13 +167,23 @@ class Protocol():
try:
var, value = opt.replace(':','=').split("=")
if var.lower()=="bits":
self.bits_per_line=int(value)
if self.bits_per_line<=0:
value = value.replace("bytes", "8").replace("qwords", "64").replace("dwords", "32").replace("words", "16").replace("double", "64").replace("floats", "32")
if re.match("^[0-9+-/\*~|&^<>()]+$", value):
self.bits_per_line=eval(value)
if self.bits_per_line<=0:
raise ProtocolException("FATAL: Invalid value for 'bits' option (%s)" % value)
else:
raise ProtocolException("FATAL: invalid number of bits (%s)" % value)
elif var.lower()=="base":
self.base_of_top_tens=int(value)
if self.base_of_top_tens<=0 or self.base_of_top_tens>16:
raise ProtocolException("FATAL: Invalid value for 'base' option (%s)" % value)
elif var.lower()=="rows":
self.do_print_line_number=int(value)
if self.do_print_line_number<0:
raise ProtocolException("FATAL: Invalid value for 'rows' option (%s)" % value)
if self.do_print_line_number > 0:
self.do_print_line_number += 1
elif var.lower()=="numbers":
if value.lower() in ["0", "n", "no", "none", "false"]:
self.do_print_top_tens=False
@ -189,17 +225,18 @@ class Protocol():
"""
lines=["", ""]
chars="0123456789abcdef"
lines[0]+=" "*self.do_print_line_number
if self.do_print_top_tens is True:
for i in range(0, self.bits_per_line):
if i%self.base_of_top_tens==0:
if i%self.base_of_top_tens == 0:
lines[0]+=" %s" % chars[int(i/self.base_of_top_tens)%self.base_of_top_tens]
else:
lines[0]+=" "
lines[0]+="\n"
lines[0]+=" "*self.do_print_line_number
if self.do_print_top_units is True:
for i in range(0, self.bits_per_line):
lines[1]+=" %s" % chars[i%self.base_of_top_tens]
#lines[1]+="\n"
result = "".join(lines)
return result if len(result)>0 else None
@ -216,9 +253,9 @@ class Protocol():
if width<=0:
return ""
else:
a="%s" % self.hdr_char_start
b=(self.hdr_char_fill_even+self.hdr_char_fill_odd)*(width-1)
c="%s%s" % (self.hdr_char_fill_even, self.hdr_char_end)
a = "%s" % self.hdr_char_start
b = (self.hdr_char_fill_even+self.hdr_char_fill_odd)*(width-1)
c = "%s%s" % (self.hdr_char_fill_even, self.hdr_char_end)
return a+b+c
@ -310,13 +347,14 @@ class Protocol():
numbers=self._get_top_numbers()
if numbers is not None:
lines.append(numbers)
lines.append(self._get_horizontal())
lines.append(" "*self.do_print_line_number+self._get_horizontal())
# Print all protocol fields
bits_in_line=0
current_line=""
fields_done=0
p=-1
line_number=0
while p < len(proto_fields)-1:
p+=1
@ -339,7 +377,10 @@ class Protocol():
# If this is the first thing we print on a line, add the
# starting character
if bits_in_line==0:
current_line+=self._get_separator()
if self.do_print_line_number:
current_line+=str(line_number).rjust(self.do_print_line_number-1)+" "
line_number+=1
current_line+=self._get_separator()
# Add the whole field
current_line+=str.center(field_text, (field_len*2)-1)
@ -369,6 +410,7 @@ class Protocol():
line_left=self._get_horizontal(self.bits_per_line - field_len)
if len(line_left)==0:
line_left=self.hdr_char_start
line_left=" "*self.do_print_line_number+line_left
# Now print some empty space to cover the part that
# we can join with the field below.
@ -389,7 +431,7 @@ class Protocol():
else:
lines.append(self._get_horizontal())
else:
lines.append(self._get_horizontal())
lines.append(" "*self.do_print_line_number+self._get_horizontal())
# If this is not the last character of the line but we have no
@ -420,10 +462,11 @@ class Protocol():
# Let's figure out which character we need to use
# to start and end the current line
if i%2==1:
start_line=self.hdr_char_start
start_line=" "*self.do_print_line_number+self.hdr_char_start
end_line=self.hdr_char_end
else:
start_line=self.hdr_char_sep
start_line=str(line_number).rjust(self.do_print_line_number-1)+" "+self.hdr_char_sep
line_number+=1
end_line=self.hdr_char_sep
# This is the line where we need to print the field
@ -435,7 +478,7 @@ class Protocol():
lines.append(start_line + (" " * ((self.bits_per_line*2)-1)) + end_line)
# If we just added the last line, add a horizontal separator
if i==lines_to_print-1:
lines.append(self._get_horizontal())
lines.append(" "*self.do_print_line_number+self._get_horizontal())
# Case 2: We are not at the beginning of the line and we need
# to print something that does not fit in the current line
@ -637,46 +680,12 @@ class Main():
# Protocol name or protocol spec
else:
# If it contains ":" characters, we have a protocol spec
if argv[i].count(":")>0:
spec = argv[i]
# Otherwise, the user meant to display an existing protocol
else:
# If we got an exact match, end of story
if argv[i] in specs.protocols:
spec = specs.protocols[argv[i]]
# Otherwise, we may have received a partial match so
# we need to figure out which protocol the user meant.
# If the specification is ambiguous, we will error
else:
start_with_the_same=[]
for spec in specs.protocols:
if spec.startswith(argv[i]):
start_with_the_same.append(spec)
# If we only have one entry, it means we got some
# shortened version of the protocol name but no
# ambiguity. In that case, we will use the match.
if len(start_with_the_same)==1:
spec=specs.protocols[start_with_the_same[0]]
elif len(start_with_the_same)==0:
print("ERROR: supplied protocol '%s' does not exist." % argv[i]);
sys.exit(1)
else:
print("Ambiguous protocol specifier '%s'. Did you mean any of these?" % argv[i])
for spec in start_with_the_same:
print(" %s" % spec)
sys.exit(1)
# Finally, based on the spec, instance an actual protocol.
# Note that if the spec is incorect, the Protocol() consutrctor
# will call sys.exit() itself, so there is no need to do
# error checking here.
try:
proto = Protocol(spec)
proto = Protocol(argv[i])
self.protocols.append(proto)
except ProtocolException as e:
print("ERROR: %s" % str(e))
sys.exit(1)
if len(self.protocols)==0:
print("ERROR: Missing protocol")
sys.exit(1)