Parsing C ‘enum’ with Python Regex.

In my previous post I mentioned I find C ‘enum’ a big annoying. An enum value captured in a network track or a packet hexdump is difficult to track backwards to a symbolic value. The nl80211.h header file uses enum extensively. As I continue to learn netlink and nl80211, I’d like a quick way to convert those enum into a human value.

Why not parse the header file and decode the enum? Python is my go-to for small string tasks.  (I mentioned I was parsing C enum in Python to a friend and he said, “That’s a very Dave move.” I’ll take it as a compliment, I suppose.)

C enum is straightforward: start counting as zero and auto increment. If there is an RHS expression, then that enum takes on that value and the auto increment continues from there.

enum nl80211_commands {
     /* don't change the order or add anything between, this is ABI! */
     NL80211_CMD_UNSPEC,

     NL80211_CMD_GET_WIPHY, /* can dump */
     NL80211_CMD_SET_WIPHY,
     NL80211_CMD_NEW_WIPHY,
     NL80211_CMD_DEL_WIPHY,
[snip]

(At some point I wonder if I should spring for the extra WordPress plugin for code formatting. Maybe.)

In the nl80211_commands above, NL80211_CMD_UNSPEC == 0, then NL80211_CMD_GET_WIPHY == 1. Simple counter. But danger lurks.

The RHS can be an expression. The expression can be a simple value.

enum nl80211_user_reg_hint_type {
        NL80211_USER_REG_HINT_USER      = 0,
        NL80211_USER_REG_HINT_CELL_BASE = 1,
        NL80211_USER_REG_HINT_INDOOR    = 2,
};

Or a complicated expression.

enum nl80211_tdls_peer_capability {
        NL80211_TDLS_PEER_HT = 1<<0,
        NL80211_TDLS_PEER_VHT = 1<<1,
        NL80211_TDLS_PEER_WMM = 1<<2,
};

The expression can reference previous values in the same enum as the next example. (Emphasis added.)

enum nl80211_sched_scan_plan {
        __NL80211_SCHED_SCAN_PLAN_INVALID,
        NL80211_SCHED_SCAN_PLAN_INTERVAL,
        NL80211_SCHED_SCAN_PLAN_ITERATIONS,

        /* keep last */
        __NL80211_SCHED_SCAN_PLAN_AFTER_LAST,
        NL80211_SCHED_SCAN_PLAN_MAX =
                __NL80211_SCHED_SCAN_PLAN_AFTER_LAST - 1
};

Here’s my favorite example, showing the enum auto increment counter being reset. The example below adds new symbol identical to an existing symbol’s value and the auto increment continues on its merry way.

enum nl80211_commands {
[snip]
     NL80211_CMD_GET_BEACON,
     NL80211_CMD_SET_BEACON,
     NL80211_CMD_START_AP,
     NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP,
     NL80211_CMD_STOP_AP,
     NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP,
[snip]

I think it would be interesting to create a regex that can parse the enum. There are of course simpler ways to do this: I could just continue to use gdb. Most of the enums are small so not a big deal to manually count them. The large enum I could copy to a new file and manually count. But I like tinkering with regexes. And I’ve had this problem of decoding large enum for as long as I’ve used C (a long time). And it seems like a fun little project.

I’ve had co-workers do woodwork to relax. Several co-workers are mountain bikers (Boise is fantastic for mountain biking.) Video games are always a good way to relax. I like to tinker with small code projects.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s