'define': 'DEFINE',
'typedef': 'TYPEDEF',
'enum': 'ENUM',
+ 'enumflag': 'ENUMFLAG',
'typeonly': 'TYPEONLY',
'manual_print': 'MANUAL_PRINT',
'manual_endian': 'MANUAL_ENDIAN',
return vla
-class Service():
+class Processable:
+ type = "<Invalid>"
+
+ def process(self, result): # -> Dict
+ result[self.type].append(self)
+
+
+class Service(Processable):
+ type = 'Service'
+
def __init__(self, caller, reply, events=None, stream_message=None,
stream=False):
self.caller = caller
self.events = [] if events is None else events
-class Typedef():
+class Typedef(Processable):
+ type = 'Typedef'
+
def __init__(self, name, flags, block):
self.name = name
- self.type = 'Typedef'
self.flags = flags
self.block = block
self.crc = str(block).encode()
self.vla = vla_is_last_check(name, block)
vla_mark_length_field(self.block)
+ def process(self, result):
+ result['types'].append(self)
+
def __repr__(self):
return self.name + str(self.flags) + str(self.block)
-class Using():
+class Using(Processable):
+ type = 'Using'
+
def __init__(self, name, flags, alias):
self.name = name
- self.type = 'Using'
self.vla = False
self.block = []
self.manual_print = True
self.crc = str(self.block).encode()
global_type_add(name, self)
+ def process(self, result): # -> Dict
+ result['types'].append(self)
+
def __repr__(self):
return self.name + str(self.alias)
-class Union():
+class Union(Processable):
+ type = 'Union'
+
def __init__(self, name, flags, block):
- self.type = 'Union'
self.manual_print = False
self.manual_endian = False
self.name = name
global_type_add(name, self)
+ def process(self, result):
+ result['types'].append(self)
+
def __repr__(self):
return str(self.block)
-class Define():
+class Define(Processable):
+ type = 'Define'
+
def __init__(self, name, flags, block):
self.name = name
- self.type = 'Define'
self.flags = flags
self.block = block
self.dont_trace = False
self.manual_print = False
self.manual_endian = False
self.autoreply = False
- self.singular = False
self.options = {}
for f in flags:
if f == 'dont_trace':
remove = []
for b in block:
if isinstance(b, Option):
- if b[1] == 'singular' and b[2] == 'true':
- self.singular = True
- else:
- self.options[b.option] = b.value
+ self.options[b.option] = b.value
remove.append(b)
block = [x for x in block if x not in remove]
self.crc = str(block).encode()
+ def autoreply_block(self, name, parent):
+ block = [Field('u32', 'context'),
+ Field('i32', 'retval')]
+ # inherit the parent's options
+ for k, v in parent.options.items():
+ block.append(Option(k, v))
+ return Define(name + '_reply', [], block)
+
+ def process(self, result): # -> Dict
+ tname = self.__class__.__name__
+ result[tname].append(self)
+ if self.autoreply:
+ result[tname].append(self.autoreply_block(self.name, self))
+
def __repr__(self):
return self.name + str(self.flags) + str(self.block)
-class Enum():
+class Enum(Processable):
+ type = 'Enum'
+
def __init__(self, name, block, enumtype='u32'):
self.name = name
self.enumtype = enumtype
self.vla = False
- self.type = 'Enum'
self.manual_print = False
count = 0
self.crc = str(block3).encode()
global_type_add(name, self)
+ def process(self, result):
+ result['types'].append(self)
+
def __repr__(self):
return self.name + str(self.block)
-class Import():
+class EnumFlag(Enum):
+ type = 'EnumFlag'
+
+ def __init__(self, name, block, enumtype='u32'):
+ super(EnumFlag, self).__init__(name, block, enumtype)
+
+ for b in self.block:
+ if bin(b[1])[2:].count("1") > 1:
+ raise TypeError("%s is not a flag enum. No element in a "
+ "flag enum may have more than a "
+ "single bit set." % self.name)
+
+
+class Import(Processable):
+ type = 'Import'
_initialized = False
+
def __new__(cls, *args, **kwargs):
if args[0] not in seen_imports:
instance = super().__new__(cls)
return self.filename
-class Option():
+class Option(Processable):
+ type = 'Option'
+
def __init__(self, option, value=None):
- self.type = 'Option'
self.option = option
self.value = value
self.crc = str(option).encode()
+ def process(self, result): # -> Dict
+ result[self.type][self.option] = self.value
+
def __repr__(self):
return str(self.option)
return self.option[index]
-class Array():
+class Array(Processable):
+ type = 'Array'
+
def __init__(self, fieldtype, name, length, modern_vla=False):
- self.type = 'Array'
self.fieldtype = fieldtype
self.fieldname = name
self.modern_vla = modern_vla
self.lengthfield])
-class Field():
+class Field(Processable):
+ type = 'Field'
+
def __init__(self, fieldtype, name, limit=None):
- self.type = 'Field'
+ # limit field has been expanded to an options dict.
+
self.fieldtype = fieldtype
self.is_lengthfield = False
return str([self.fieldtype, self.fieldname])
-class Counter():
+class Counter(Processable):
+ type = 'Counter'
+
def __init__(self, path, counter):
- self.type = 'Counter'
self.name = path
self.block = counter
+ def process(self, result): # -> Dict
+ result['Counters'].append(self)
+
+
+class Paths(Processable):
+ type = 'Paths'
-class Paths():
def __init__(self, pathset):
- self.type = 'Paths'
self.paths = pathset
+ def __repr__(self):
+ return "%s(paths=%s)" % (
+ self.__class__.__name__, self.paths
+ )
+
class Coord(object):
""" Coordinates of a syntactic element. Consists of:
| option
| import
| enum
+ | enumflag
| union
| service
| paths
else:
p[0] = Enum(p[2], p[4])
+ def p_enumflag(self, p):
+ '''enumflag : ENUMFLAG ID '{' enum_statements '}' ';' '''
+ p[0] = EnumFlag(p[2], p[4])
+
+ def p_enumflag_type(self, p):
+ ''' enumflag : ENUMFLAG ID ':' enum_size '{' enum_statements '}' ';' ''' # noqa : E502
+ if len(p) == 9:
+ p[0] = EnumFlag(p[2], p[6], enumtype=p[4])
+ else:
+ p[0] = EnumFlag(p[2], p[4])
+
def p_enum_size(self, p):
''' enum_size : U8
| U16
print('File not found: {}'.format(filename), file=sys.stderr)
sys.exit(2)
- def autoreply_block(self, name, parent):
- block = [Field('u32', 'context'),
- Field('i32', 'retval')]
- # inherhit the parent's options
- for k, v in parent.options.items():
- block.append(Option(k, v))
- return Define(name + '_reply', [], block)
-
def process(self, objs):
s = {}
s['Option'] = {}
s['Paths'] = []
crc = 0
for o in objs:
- tname = o.__class__.__name__
try:
crc = binascii.crc32(o.crc, crc) & 0xffffffff
except AttributeError:
pass
- if isinstance(o, Define):
- s[tname].append(o)
- if o.autoreply:
- s[tname].append(self.autoreply_block(o.name, o))
- elif isinstance(o, Option):
- s[tname][o.option] = o.value
- elif type(o) is list:
+
+ if type(o) is list:
for o2 in o:
if isinstance(o2, Service):
- s['Service'].append(o2)
- elif isinstance(o, (Enum, Typedef, Union, Using)):
- s['types'].append(o)
- elif isinstance(o, Counter):
- s['Counters'].append(o)
- elif isinstance(o, Paths):
- s['Paths'].append(o)
+ o2.process(s)
else:
- if tname not in s:
- raise ValueError('Unknown class type: {} {}'
- .format(tname, o))
- s[tname].append(o)
+ o.process(s)
msgs = {d.name: d for d in s['Define']}
svcs = {s.caller: s for s in s['Service']}
for d in msgs:
if d in seen_services:
continue
- if msgs[d].singular is True:
- continue
if d.endswith('_reply'):
if d[:-6] in svcs:
continue
return s
- def process_imports(self, objs, in_import, result):
+ def process_imports(self, objs, in_import, result): # -> List
for o in objs:
# Only allow the following object types from imported file
if in_import and not isinstance(o, (Enum, Import, Typedef,