Skip to content

Commit b7788a5

Browse files
author
cabrol
committed
Revert "Feature/comment block to struct (#3)"
* breaks some of the parsing logic for older version of .h files This reverts commit a87bf6e.
1 parent a87bf6e commit b7788a5

File tree

2 files changed

+54
-143
lines changed

2 files changed

+54
-143
lines changed

dissect/cstruct/cstruct.py

Lines changed: 48 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class {name}(Structure):
7070
def __init__(self, cstruct, structure, source=None):
7171
self.structure = structure
7272
self.source = source
73-
super({name}, self).__init__(cstruct, structure.name, structure.fields, structure.commentAttributes)
73+
super({name}, self).__init__(cstruct, structure.name, structure.fields)
7474
7575
def _read(self, stream):
7676
r = OrderedDict()
@@ -333,57 +333,43 @@ def _constants(self, data):
333333

334334
def _enums(self, data):
335335
r = re.finditer(
336-
r'(?P<commentBlock>\/\*(\*(?!\/)|[^*])*\*\/)?[ \t\r\n]*enum\s+(?P<name>[^\s:{]+)\s*(:\s*(?P<type>[^\s]+)\s*)?\{(?P<values>[^}]+)\}\s*;',
336+
r'enum\s+(?P<name>[^\s:{]+)\s*(:\s*(?P<type>[^\s]+)\s*)?\{(?P<values>[^}]+)\}\s*;',
337337
data,
338338
)
339339
for t in r:
340340
d = t.groupdict()
341341

342-
if not d['type']:
343-
d['type'] = 'uint32'
342+
nextval = 0
343+
values = {}
344+
for line in d['values'].split('\n'):
345+
line, sep, comment = line.partition("//")
346+
for v in line.split(","):
347+
key, sep, val = v.partition("=")
348+
key = key.strip()
349+
val = val.strip()
350+
if not key:
351+
continue
352+
if not val:
353+
val = nextval
354+
else:
355+
val = Expression(self.cstruct, val).evaluate({})
344356

345-
values, valuesDetails = self._parse_fields_enums(d['values'])
357+
nextval = val + 1
346358

347-
commentAttributes = self.parse_comment_block(d['commentBlock'])
359+
values[key] = val
360+
361+
if not d['type']:
362+
d['type'] = 'uint32'
348363

349364
enum = Enum(
350-
self.cstruct, d['name'], self.cstruct.resolve(d['type']), values, valuesDetails, commentAttributes
365+
self.cstruct, d['name'], self.cstruct.resolve(d['type']), values
351366
)
352367
self.cstruct.addtype(enum.name, enum)
353368

354-
def _parse_fields_enums(self, s):
355-
nextval = 0
356-
values = {}
357-
valuesDetails = {}
358-
fields = re.finditer(
359-
r'(\n?[ ]*\/\/[^\n]*\n)*[ ]*(?P<commentBlock>\/\*(\*(?!\/)|[^*])*\*\/)?[ \t\r\n]*(?P<value>[a-zA-z][^\n,/]*),?[ ]*(?P<commentBlockAfter>\/\*(\*(?!\/)|[^*])*\*\/)?(\n?[ ]*\/\/[^\n]*\n*)*',
360-
s,
361-
)
362-
363-
for f in fields:
364-
d = f.groupdict()
365-
366-
# Ignore fo now
367-
commentAttributes = self.parse_comment_block(d['commentBlock'])
368-
369-
field = re.finditer(
370-
r'(?P<key>[a-zA-z][^ =]*)[ ]*=?[ ]*(?P<value>[^ ]+)?',
371-
d["value"],
372-
)
373-
374-
f = list(field)[0].groupdict()
375-
376-
values[f["key"]] = Expression(self.cstruct, f["value"]).evaluate({}) if f["value"] != None else nextval
377-
378-
nextval = values[f["key"]] + 1
379-
valuesDetails[f["key"]] = {"value":values[f["key"]], "commentAttributes":commentAttributes}
380-
381-
return values, valuesDetails
382-
383369
def _structs(self, data):
384370
compiler = Compiler(self.cstruct)
385371
r = re.finditer(
386-
r'(?P<commentBlock>\/\*(\*(?!\/)|[^*])*\*\/)?[ \t\r\n]*(#(?P<flags>(?:compile))\s+)?((?P<typedef>typedef)\s+)?(?P<type>[^\s]+)\s+(__attribute__\(\([^)]+\)\)\s*)?(?P<name>[^\s]+)?(?P<fields>\s*\{(\s*//[^\n]*|/\*[^*]*\*/|[^}])+\}(?P<defs>\s+[^;\n]+)?)?\s*;',
372+
r'(#(?P<flags>(?:compile))\s+)?((?P<typedef>typedef)\s+)?(?P<type>[^\s]+)\s+(__attribute__\(\([^)]+\)\)\s*)?(?P<name>[^\s]+)?(?P<fields>\s*\{(\s*//[^\n]*|/\*[^*]*\*/|[^}])+\}(?P<defs>\s+[^;\n]+)?)?\s*;',
387373
data,
388374
)
389375
for t in r:
@@ -397,9 +383,8 @@ def _structs(self, data):
397383
raise ParserError("No name for struct")
398384

399385
if d['type'] == 'struct':
400-
data = self._parse_fields_struct(d['fields'][1:-1].strip())
401-
commentAttributes = self.parse_comment_block(d['commentBlock'])
402-
st = Structure(self.cstruct, name, data, commentAttributes)
386+
data = self._parse_fields(d['fields'][1:-1].strip())
387+
st = Structure(self.cstruct, name, data)
403388
if d['flags'] == 'compile' or self.compiled:
404389
st = compiler.compile(st)
405390
elif d['typedef'] == 'typedef':
@@ -415,9 +400,10 @@ def _structs(self, data):
415400
td = td.strip()
416401
self.cstruct.addtype(td, st)
417402

418-
def _parse_fields_struct(self, s):
403+
def _parse_fields(self, s):
404+
commentAttributes = {}
419405
fields = re.finditer(
420-
r'(\n?[ ]*\/\/[^\n]*\n)*[ ]*(?P<commentBlock>\/\*(\*(?!\/)|[^*])*\*\/)?[ \t\r\n]*(?P<type>[^\s]+)\s+(?P<name>[^\s\[:]+)(\s*:\s*(?P<bits>\d+))?(\[(?P<count>[^;\n]*)\])?;[ ]*(?P<commentBlockAfter>\/\*(\*(?!\/)|[^*])*\*\/)?(\n?[ ]*\/\/[^\n]*\n*)*',
406+
r'(?P<commentBlock>\/\*(\*(?!\/)|[^*])*\*\/)?[ \t\r\n]*(?P<type>[^\s]+)\s+(?P<name>[^\s\[:]+)(\s*:\s*(?P<bits>\d+))?(\[(?P<count>[^;\n]*)\])?;',
421407
s,
422408
)
423409
r = []
@@ -426,7 +412,20 @@ def _parse_fields_struct(self, s):
426412
if d['type'].startswith('//'):
427413
continue
428414

429-
commentAttributes = self.parse_comment_block(d['commentBlock'])
415+
commentAttributes={}
416+
417+
#parse the comment header
418+
if d['commentBlock'] is not None and d['commentBlock'].startswith('/*'):
419+
commentfields = re.finditer(
420+
r'@(?P<commentType>[^@,;:\\]+):[ \t]*(?P<commentVal>[^@,;:\s\\]+)',
421+
d['commentBlock'],
422+
)
423+
for cf in commentfields:
424+
cd=cf.groupdict()
425+
try:
426+
commentAttributes[cd['commentType']]=cd['commentVal']
427+
except Exception:
428+
pass
430429

431430
type_ = self.cstruct.resolve(d['type'])
432431

@@ -450,32 +449,11 @@ def _parse_fields_struct(self, s):
450449
d['name'] = d['name'][1:]
451450
type_ = Pointer(self.cstruct, type_)
452451

453-
field = StructureField(d['name'], type_, int(d['bits']) if d['bits'] else None, commentAttributes=commentAttributes)
452+
field = Field(d['name'], type_, int(d['bits']) if d['bits'] else None, commentAttributes=commentAttributes)
454453
r.append(field)
455454

456455
return r
457456

458-
def parse_comment_block(self,s):
459-
commentAttributes={}
460-
461-
#parse the comment header
462-
if s is not None and s.startswith('/*'):
463-
commentfields = re.finditer(
464-
r'@(?P<commentType>[^@,;:\\]+):[ \t]*(?P<commentVal>[^@\n]+)',
465-
s,
466-
)
467-
for cf in commentfields:
468-
cd=cf.groupdict()
469-
try:
470-
oldData = commentAttributes.get(cd['commentType'],"")
471-
if "" != oldData:
472-
oldData += " "
473-
commentAttributes[cd['commentType']]=oldData + cd['commentVal']
474-
except Exception:
475-
pass
476-
477-
return commentAttributes
478-
479457
def _lookups(self, data, consts):
480458
r = re.finditer(r'\$(?P<name>[^\s]+) = ({[^}]+})\w*\n', data)
481459

@@ -779,12 +757,11 @@ def __repr__(self):
779757
class Structure(BaseType):
780758
"""Type class for structures."""
781759

782-
def __init__(self, cstruct, name, fields=None, commentAttributes={}):
760+
def __init__(self, cstruct, name, fields=None):
783761
self.name = name
784762
self.size = None
785763
self.lookup = OrderedDict()
786764
self.fields = fields if fields else []
787-
self.commentAttributes = commentAttributes
788765

789766

790767
for f in self.fields:
@@ -908,7 +885,7 @@ def add_fields(self, name, type_, offset=None, commentAttributes={}):
908885
type_: The field type.
909886
offset: The field offset.
910887
"""
911-
field = StructureField(name, type_, offset=offset, commentAttributes=commentAttributes)
888+
field = Field(name, type_, offset=offset, commentAttributes=commentAttributes)
912889
self.fields.append(field)
913890
self.lookup[name] = field
914891
self.size = None
@@ -938,7 +915,7 @@ def __repr__(self):
938915
def show(self, indent=0):
939916
"""Pretty print this structure."""
940917
if indent == 0:
941-
print("{} struct {}".format(self.commentAttributes, self.name))
918+
print("struct {}".format(self.name))
942919

943920
for field in self.fields:
944921
if field.offset is None:
@@ -1006,7 +983,7 @@ def reset(self):
1006983
self._remaining = 0
1007984

1008985

1009-
class StructureField(object):
986+
class Field(object):
1010987
"""Holds a structure field."""
1011988

1012989
def __init__(self, name, type_, bits=None, offset=None, commentAttributes={}):
@@ -1335,11 +1312,9 @@ class Enum(RawType):
13351312
};
13361313
"""
13371314

1338-
def __init__(self, cstruct, name, type_, values, valuesDetails, commentAttributes={}):
1315+
def __init__(self, cstruct, name, type_, values):
13391316
self.type = type_
13401317
self.values = values
1341-
self.valuesDetails = valuesDetails
1342-
self.commentAttributes = commentAttributes
13431318
self.reverse = {}
13441319

13451320
for k, v in values.items():
@@ -1390,9 +1365,6 @@ def __getattr__(self, attr):
13901365
def __contains__(self, attr):
13911366
return attr in self.values
13921367

1393-
def __repr__(self):
1394-
return '<Enum {}>'.format(self.name)
1395-
13961368

13971369
class EnumInstance(object):
13981370
"""Implements a value instance of an Enum"""

tests/test_basic.py

Lines changed: 6 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -257,15 +257,6 @@ def test_enum_comments():
257257
assert c.Inline.foo == 9
258258
assert c.Inline.bar == 10
259259

260-
assert c.Inline.valuesDetails["hello"]["value"] == 7
261-
assert c.Inline.valuesDetails["hello"]["commentAttributes"] == {}
262-
assert c.Inline.valuesDetails["world"]["value"] == 8
263-
assert c.Inline.valuesDetails["world"]["commentAttributes"] == {}
264-
assert c.Inline.valuesDetails["foo"]["value"] == 9
265-
assert c.Inline.valuesDetails["foo"]["commentAttributes"] == {}
266-
assert c.Inline.valuesDetails["bar"]["value"] == 10
267-
assert c.Inline.valuesDetails["bar"]["commentAttributes"] == {}
268-
269260
assert c.Test.a == 2
270261
assert c.Test.b == 3
271262
assert c.Test.c == 4
@@ -781,87 +772,35 @@ def test_dumpstruct(capsys):
781772
assert captured_1.out == captured_2.out
782773

783774

784-
def test_comment_field_parse_struct(capsys):
775+
def test_commentfieldparse(capsys):
785776
c = cstruct.cstruct()
786777
c.load("""
787-
/*
788-
* @comment: Hello,
789-
* @comment: how are you?
790-
*/
778+
/*discardedCom1*/
791779
struct test{
792-
// int notAnStruct;
793780
/*
794-
* @comment: I am fine.
795-
* @comment: Thank you.
796-
* @scale: 0.001
797-
* @unit: µtestUnit1
798-
*/
781+
* @scale: 0.001
782+
* @unit: µtestUnit1
783+
*/
799784
int testVar1;
800-
// int testVar1;
801785
int testVar2;
802786
/* dicardedCom2
803787
* @scale: 5
804788
* @unit: %testUnit2
805789
*/
806790
int testVar3;
807-
// int notAnStruct;
808791
};
809792
""", compiled=False)
810793

811794
assert c.test.name == 'test'
812-
assert c.test.commentAttributes['comment'] == 'Hello, how are you?'
813795

814796
assert 'testVar1' in c.test.lookup
815797
assert 'testVar2' in c.test.lookup
816798
assert 'testVar2' in c.test.lookup
817799

818-
assert c.test.lookup['testVar1'].commentAttributes['comment'] == 'I am fine. Thank you.'
819800
assert c.test.lookup['testVar1'].commentAttributes['scale'] == '0.001'
820801
assert c.test.lookup['testVar1'].commentAttributes['unit'] == 'µtestUnit1'
821802

822803
assert c.test.lookup['testVar2'].commentAttributes == {}
823804

824805
assert c.test.lookup['testVar3'].commentAttributes['scale'] == '5'
825-
assert c.test.lookup['testVar3'].commentAttributes['unit'] == '%testUnit2'
826-
827-
assert "notAnStruct" not in c.test.lookup
828-
829-
def test_comment_field_parse_enum(capsys):
830-
c = cstruct.cstruct()
831-
c.load("""
832-
/*discardedCom1*/
833-
enum test{
834-
// notAnEnum=4,
835-
/*
836-
* @comment: Comments are working
837-
*/
838-
testEnumVar1=5,
839-
// testEnumVar1,
840-
testEnumVar2,
841-
/*
842-
* @comment: Comments are working 2
843-
*/
844-
testEnumVar3,
845-
// notAnEnum=14,
846-
};
847-
""", compiled=False)
848-
849-
assert c.test.name == 'test'
850-
assert 'comment' not in c.test.commentAttributes
851-
852-
assert 'testEnumVar1' in c.test.values
853-
assert 'testEnumVar1' in c.test.valuesDetails
854-
assert 'testEnumVar2' in c.test.values
855-
assert 'testEnumVar2' in c.test.valuesDetails
856-
assert 'testEnumVar3' in c.test.values
857-
assert 'testEnumVar3' in c.test.valuesDetails
858-
859-
860-
assert c.test.valuesDetails['testEnumVar1']["commentAttributes"]['comment'] == 'Comments are working'
861-
862-
assert c.test.valuesDetails['testEnumVar2']["commentAttributes"] == {}
863-
864-
assert c.test.valuesDetails['testEnumVar3']["commentAttributes"]['comment'] == 'Comments are working 2'
865-
866-
assert "notAnEnum" not in c.test.values
867-
assert "notAnEnum" not in c.test.valuesDetails
806+
assert c.test.lookup['testVar3'].commentAttributes['unit'] == '%testUnit2'

0 commit comments

Comments
 (0)