Skip to content

Commit f922343

Browse files
authored
Add support for #undef (#137)
1 parent bbbb86e commit f922343

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

dissect/cstruct/parser.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def _tokencollection() -> TokenCollection:
5757
TOK = TokenCollection()
5858
TOK.add(r"#\[(?P<values>[^\]]+)\](?=\s*)", "CONFIG_FLAG")
5959
TOK.add(r"#define\s+(?P<name>[^\s]+)(?P<value>[^\r\n]*)", "DEFINE")
60+
TOK.add(r"#undef\s+(?P<name>[^\s]+)\s*", "UNDEF")
6061
TOK.add(r"#ifdef\s+(?P<name>[^\s]+)\s*", "IFDEF")
6162
TOK.add(r"#ifndef\s+(?P<name>[^\s]+)\s*", "IFNDEF")
6263
TOK.add(r"#else\s*", "ELSE")
@@ -154,6 +155,16 @@ def _constant(self, tokens: TokenConsumer) -> None:
154155

155156
self.cstruct.consts[match["name"]] = value
156157

158+
def _undef(self, tokens: TokenConsumer) -> None:
159+
const = tokens.consume()
160+
pattern = self.TOK.patterns[self.TOK.UNDEF]
161+
match = pattern.match(const.value).groupdict()
162+
163+
if match["name"] in self.cstruct.consts:
164+
del self.cstruct.consts[match["name"]]
165+
else:
166+
raise ParserError(f"line {self._lineno(const)}: constant {match['name']!r} not defined")
167+
157168
def _enum(self, tokens: TokenConsumer) -> None:
158169
# We cheat with enums because the entire enum is in the token
159170
etok = tokens.consume()
@@ -443,6 +454,8 @@ def parse(self, data: str) -> None:
443454
self._config_flag(tokens)
444455
elif token == self.TOK.DEFINE:
445456
self._constant(tokens)
457+
elif token == self.TOK.UNDEF:
458+
self._undef(tokens)
446459
elif token == self.TOK.TYPEDEF:
447460
self._typedef(tokens)
448461
elif token == self.TOK.STRUCT:

tests/test_parser.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,19 @@ def test_typedef_pointer(cs: cstruct) -> None:
163163
assert cs.PIMAGE_DATA_DIRECTORY.type == cs._IMAGE_DATA_DIRECTORY
164164

165165

166+
def test_undef(cs: cstruct) -> None:
167+
cdef = """
168+
#define MY_CONST 42
169+
#undef MY_CONST
170+
"""
171+
cs.load(cdef)
172+
173+
assert "MY_CONST" not in cs.consts
174+
175+
with pytest.raises(ParserError, match="line 1: constant 'MY_CONST' not defined"):
176+
cs.load("#undef MY_CONST") # This should raise an error since MY_CONST is not defined
177+
178+
166179
def test_conditional_ifdef(cs: cstruct) -> None:
167180
cdef = """
168181
#define MY_CONST 42

0 commit comments

Comments
 (0)