Skip to content

Enum parsing#18

Merged
andreax79 merged 12 commits into
andreax79:mainfrom
tyalie:enum-parsing
Nov 1, 2022
Merged

Enum parsing#18
andreax79 merged 12 commits into
andreax79:mainfrom
tyalie:enum-parsing

Conversation

@tyalie

@tyalie tyalie commented Nov 1, 2022

Copy link
Copy Markdown
Contributor

This merge would implement extensive enum support in python-cstruct. Named, unnamed, inline, ... enum definitions are possible with this. All enums are subclasses from Python enum.IntEnum and can be used as such without any further thought, they just contain an additional .parse and .size method / property.

One big issue I've hit upon is that I'm unsure about the underlying data type of enums / how they are stored in a buffer. This seems to be pretty much compiler and environment defined. I've used the __size__ parameter that is exposed through the .size property in order to state how many bytes the enum will take. This will default to 4 bytes if not further specified. I'm also assuming a signed case.
There is a bit of contradicting information out there on what exactly the underlying data type of an enum is, I'm not fully sure what the best way forward is from here.

Examples

Possible __def__ for an MemCStruct

struct {
  enum Type_A a;  // externally defined using CEnum
  enum Type_B {A, B, C} b;
  enum {A, B, C} c;
}

There is also a cstruct.CEnum class with which one can easily define enums like the following

class Type_A(cstruct.CEnum):
  __size__ = 2
  __enum__ = """
    A,
    B,
    C = 5,
    D,
    E = 7 + #SOME_DEFINE
  """

# this is a nice gimmick that works, but wasn't really planned to be supported
class Type_C(cstruct.CEnum):
  A = 0,
  B = 1,
  C = 2,
  D = 3

tyalie added 10 commits October 31, 2022 19:54
using the CEnum class one create Python Enums easily using a C style syntax.

```
class Test(CEnum):
  __enum__ = """
    A = 1,
    B = 2,
    C
  """
```

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
- renamed `parse_def` to `parse_struct_def` to allow for
  `parse_enum_def` function

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
Using Pythons metaclass new function, we look for valid C Enum classes
(__enum__ = True) and register them there in the `base.ENUMS` variable

- `__size__` is a required parameter for Enums
- introduced `CEnumException`

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
It wasn't used so far and I'm not sure if that will change. Enum parsing
is far more simple than struct parsing in this regard

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
Previously defined named CEnums are correctly parsed when used in a
struct definition now.

It is unclear whether unnamed and `AbstractCEnum.parse` enums can also
be used. Presumably not.

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
Parser couldn't handle the case that an enum-constant without explicit
value and no following `,` was the last thing in the enum definition.

Example error case
```
enum {
  A
}
```

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
This function was not in a working state previously. While making the
function work a few things needed to be changed too. For example should
`len(enum)` return the number of elements instead of the size for CEnums
and such.

Introduced default enum size of 4 bytes

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
A warning will now be displayed and the enum size will be set to
`base.DEFAULT_ENUM_SIZE` instead

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
This includes named and unnamed enums that are defined in a struct,
similar to this:
```
struct {
  enum {A, B, C} v;
}
```

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
I'm not fully sure what the test case was that would have resulted in an
error, but looking over the code there was a break at the wrong position
that could have resulted in an unparsed enum constant.

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
@tyalie

tyalie commented Nov 1, 2022

Copy link
Copy Markdown
Contributor Author

And yeah I'm missing test cases for now

This hits upon a larger issue. It doesn't seem fully clear what type a
compiler will use to represent an enum, but signed integer seems to be a
good enough solution as enum-constants (not the enum itself) are
defined as int signed. See following patch note

https://gcc.gnu.org/legacy-ml/gcc-patches/2000-07/msg00993.html

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
Python 3.10 supports using `type[…]` or `tuple[…]` as type hints. This
is relatively new and as such not support in older pythons

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
@andreax79 andreax79 merged commit 3b5bc77 into andreax79:main Nov 1, 2022
@tyalie tyalie deleted the enum-parsing branch November 1, 2022 13:53
@tyalie tyalie mentioned this pull request Nov 1, 2022
@tyalie tyalie restored the enum-parsing branch November 1, 2022 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants