Repository navigation
Conversation
…a comment - Keeps track of the whitespece between the value and the comment - Will keep track of a single qouted character
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #170 +/- ##
=====================================
Coverage 0.00% 0.00%
=====================================
Files 22 22
Lines 2798 2888 +90
=====================================
- Misses 2798 2888 +90
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
This was the first one that got through all the tests, I will think of a better solution for the quoted string as it will break if you add a single quote somewhere between double quotes |
|
I can replace it with dissect.cstruct/tests/test_parser.py Line 254 in 3032ad7 oterwise |
|
What about multiline defines with quotes at the end of each (or some) line? Note that I'm not sure how that'd work in C, just a thought. Worth a test. |
Do you mean something like this: #define HELP " \
#define NLD "it won't work without the backslash according to some tests with godbolt |
|
I mean something like this: |
it will error in that case in c: main.c:4:13: error: expected identifier or ‘(’ before string constant
4 | "zomg" \ // and here
| ^~~~~~
main.c:4:20: error: stray ‘\’ in program
4 | "zomg" \ // and here
| ^
main.c:3:19: error: stray ‘\’ in program
3 | #define foo "bar" \ // comment here
| ^
main.c:8:12: note: in expansion of macro ‘foo’
8 | printf(foo);and in cstruct it creates a lexer error for an unexpected |
|
This is valid C though: #define foo "bar" /* comment */ \
"zomg"Might be nice to at least put something like this in the unit test. |
I'll add it and see whether I can make that work :) |
|
In def test_preprocessor_define_substitute_define(cs: cstruct) -> None:
"""Test whether we can concatinate defines with other strings."""
c_def = """
#define DATA1 "world"
#define CONCAT "hello" \\
DATA1
"""
cs.load(c_def)
assert cs.consts["CONCAT"] == "helloworld" |
Was because it recognized 'b"' as a word, and attempted to parse the remaining part as normal
| assert cs.consts["IGNORE_DEFINE_IN_COMMENT"] == "data4" | ||
| assert cs.consts["TEXT_CONTAINING_COMMENT"] == "text with comments /* data5 */" | ||
| assert cs.consts["IGNORE_STRING_AFTER_COMMENT"] == "data6" | ||
| assert cs.consts["NO_COMMENT_BETWEEN_CONCATINATION"] == 'data7" "should get concatinated' |
There was a problem hiding this comment.
From my understanting and test the value should be ``'data7should get concatinated'and not'data7" "should get concatinated'`
E.g link on compiler exporer/godbolt
❯ cat test.c
#include <stdio.h>
#define NO_COMMENT_BETWEEN_CONCATINATION "data7" /* Comment */ \
"should get concatinated"
int main(void) {
printf(NO_COMMENT_BETWEEN_CONCATINATION);
printf("\n");
return 0;
}
❯ gcc test.c
❯ ./a.out
data7should get concatinated
| assert cs.consts["TEXT_CONTAINING_COMMENT"] == "text with comments /* data5 */" | ||
| assert cs.consts["IGNORE_STRING_AFTER_COMMENT"] == "data6" | ||
| assert cs.consts["NO_COMMENT_BETWEEN_CONCATINATION"] == 'data7" "should get concatinated' | ||
|
|
There was a problem hiding this comment.
| assert "TEST_NO" not in cs.consts | |
Ensure TEST_NO is actually ignored
| assert cs.consts["IGNORE_DEFINE_IN_COMMENT"] == "data4" | ||
| assert cs.consts["TEXT_CONTAINING_COMMENT"] == "text with comments /* data5 */" | ||
| assert cs.consts["IGNORE_STRING_AFTER_COMMENT"] == "data6" | ||
| assert cs.consts["NO_COMMENT_BETWEEN_CONCATINATION"] == 'data7" "should get concatinated' |
There was a problem hiding this comment.
| assert cs.consts["NO_COMMENT_BETWEEN_CONCATINATION"] == 'data7" "should get concatinated' | |
| assert cs.consts["NO_COMMENT_BETWEEN_CONCATINATION"] == '"data7should get concatinated"' |
There was a problem hiding this comment.
This is true, I currently kept them separate in the define parsing because of a different issue:
#define DATA1 "world"
#define CONCAT "hello" \
DATA1where CONCAT should ideally resolve to helloworld. It currently doesn't of course and resolves to hello DATA1 where it cannot resolve DATA1 yet.
If we remove / join the strings, it would result in helloDATA1 and we would not be a clear separation of the string part and the part that needs to be resolved. So with that in mind, i decided to keep it separate for now.
There was a problem hiding this comment.
Few comment/question.
I will try to propose a fix for raised issues next week, as some suggestion make test fail, does not hesitates to tell me if you do not consider these points as valid issues.
Sorry for messy comment order, I'm not used to github suggestion interface.
| #define IGNORE_DEFINE_IN_COMMENT data4 /* define | ||
| #define TEST_NO data_no inside | ||
| comment | ||
| */ |
There was a problem hiding this comment.
Technically this does not compile as it is compiler explorer link
Maybe change with integer for something more correct in C?
There was a problem hiding this comment.
only using L530 does indeed not compile, as the comment is not closed. using the full comment does work no? https://godbolt.org/z/zvfT8T4cT
There was a problem hiding this comment.
The issue was more related to the quoted /unquoted 'data4' vs '"data4"' (I was not really clear), but this is related to #170 (comment)
There was a problem hiding this comment.
oh that, yeah cstruct sees everything as a string after the define. I think we kept it that way for backwards compatibility with <5.0
| assert cs.consts["IGNORE_MULTILINE_COMMENT"] == "data3" | ||
| assert cs.consts["IGNORE_DEFINE_IN_COMMENT"] == "data4" | ||
| assert cs.consts["TEXT_CONTAINING_COMMENT"] == "text with comments /* data5 */" | ||
| assert cs.consts["IGNORE_STRING_AFTER_COMMENT"] == "data6" |
There was a problem hiding this comment.
We lost the difference between quoted and unquoted value (which is the difference between and int, a char and a string. I don't known dissect.cstruct enough but a first glance it's look like a potential issue
| assert cs.consts["IGNORE_STRING_AFTER_COMMENT"] == "data6" | |
| assert cs.consts["IGNORE_STRING_AFTER_COMMENT"] == '"data6"' | |
| # to add in cdef | |
| #define A_SIMPLE_INT 1 // | |
| #define A_INT_AS_STRING "1" | |
| #define A_INT_AS_CHAR '1' | |
| assert cs.consts["A_SIMPLE_INT"] == "1" | |
| assert cs.consts["A_INT_AS_STRING"] == '"1"' | |
| assert cs.consts["A_INT_AS_CHAR"] == "'1'" |
There was a problem hiding this comment.
i will take a look whether that will be an issue
There was a problem hiding this comment.
There is no difference between char and string in cstruct. As for an int, it is properly resolved:
Python 3.14.3 (main, Feb 3 2026, 22:52:18) [Clang 21.1.4 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dissect.cstruct import cstruct
>>> cstruct()
<dissect.cstruct.cstruct.cstruct object at 0x7c966b671a90>
>>> x = cstruct()
>>> xxx = """
... #define A_SIMPLE_INT 1 //
... #define A_INT_AS_STRING "1"
... #define A_INT_AS_CHAR '1'
... """
>>> x.load(xxx)
<dissect.cstruct.cstruct.cstruct object at 0x7c966b732710>
>>> x.A_SIMPLE_INT
1
>>> x.A_INT_AS_STRING
'1'
>>> x.A_INT_AS_CHAR
'1'| assert cs.consts["IGNORE_LINE_COMMENT"] == "data2" | ||
| assert cs.consts["IGNORE_MULTILINE_COMMENT"] == "data3" | ||
| assert cs.consts["IGNORE_DEFINE_IN_COMMENT"] == "data4" | ||
| assert cs.consts["TEXT_CONTAINING_COMMENT"] == "text with comments /* data5 */" |
There was a problem hiding this comment.
Cf comment below, I didn't find how to make a suggestion edit from Github gui for two lines....
| assert cs.consts["TEXT_CONTAINING_COMMENT"] == "text with comments /* data5 */" | |
| assert cs.consts["TEXT_CONTAINING_COMMENT"] == '"text with comments /* data5 */"' |
fixes #169