简体   繁体   中英

Struct initialization with array of nested structs

I am trying to create a text parsing state machine using a struct. It seems to work fine for the smaller struct I was using to test it, but the larger strut I require for my final application (modem control) seems to not be represented as I would like in memory.

I think the problem lies with initializing this struct:

struct state
{
    size_t const id;
    size_t(* const callback)(void*);
    void* const callback_arg;
    char const* const out_pattern;
    size_t const out_pattern_length;
    unsigned long int timeout;
    size_t const timeout_state;
    size_t const next_states_length;
    struct next_state const* next_states;
};

With this macro:

#define sm_state(id, callback, callback_arg, out_str, out_str_length, timeout, \
timeout_state, next_states_length, ...) \
{id, callback, callback_arg, out_str, out_str_length, timeout, \
timeout_state, next_states_length, \
(struct next_state const[next_states_length]){__VA_ARGS__}}

where next_state is:

#define sm_next_state(next_state_id, in_pattern_length, in_pattern) \
{next_state_id, in_pattern_length, in_pattern}

struct next_state
{
    size_t const next_state;
    size_t const in_pattern_length;
    char const* in_pattern;
};

The test case that works is:

enum states_enum
{
    fruit = 1,
    vegitable,
    error,
};

struct state const states[] = {
    //          id          callback        callback argument   pattern to be sent on entry         patlen  timeout     t/o state   next states count   next_states
    sm_state(   fruit,      NULL,           NULL,               "hello, pick a fruit\n",            20,     100000UL,   1,          3,                  sm_next_state(fruit, 4, "pear"),        sm_next_state(vegitable, 5, "apple"),       sm_next_state(error, 6, "turnip")),
    sm_state(   vegitable,  NULL,           NULL,               "now pick a vegetable\n",           21,     100000UL,   3,          3,                  sm_next_state(fruit, 7, "cabbage"),     sm_next_state(vegitable, 6, "potato"),      sm_next_state(error, 6, "turnip")),
    sm_state(   error,      NULL,           NULL,               "error, you entered turnip...\n",   29,     100000UL,   1,          3,                  sm_next_state(fruit, 3, "one"),         sm_next_state(vegitable, 3, "two"),         sm_next_state(error, 6, "turnip"))
};

int i = 0;
while (i < 3)
{
    printf("id: %d\n", states[i].id);
    ++i;
}

output:

id: 1
id: 2
id: 3

And the larger struct that does not work:

enum bluetooth_states_enum
{
    bt_off = 1,
    bt_on,
    bt_set_echo_off,
    bt_set_auto_answer,
    bt_set_ignore_dsr,
    bt_set_spp,
    bt_set_io_cap,
    bt_set_mitm_protection,
    bt_write,
    bt_reset,
    bt_set_firendly_name,
    bt_set_connectable,
    bt_set_key,
    bt_listening,
    bt_answer,
    bt_in_call,
    bt_hup,
    bt_error,
};

struct state const states[] = {
    sm_state(   bt_off,                 NULL, NULL, "",             0,      -1,         bt_off,     0,),
    sm_state(   bt_on,                  NULL, NULL, "AT\r",         3,      100000UL,   bt_error,   2,          sm_next_state(bt_set_echo_off, 2, "OK"),            sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_echo_off,        NULL, NULL, "ATE0\r",       5,      100000UL,   bt_error,   2,          sm_next_state(bt_set_auto_answer, 2, "OK"),         sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_auto_answer,     NULL, NULL, "ATS0=2\r",     7,       100000UL,  bt_error,   2,          sm_next_state(bt_set_ignore_dsr, 2, "OK"),          sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_ignore_dsr,      NULL, NULL, "ATS102=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_spp, 2, "OK"),                 sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_spp,             NULL, NULL, "ATS102=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_io_cap, 2, "OK"),              sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_io_cap,          NULL, NULL, "ATS321=0\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_mitm_protection, 2, "OK"),     sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_mitm_protection, NULL, NULL, "ATS322=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_write, 2, "OK"),                   sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_write,               NULL, NULL, "AT&W\r",       5,      100000UL,   bt_error,   2,          sm_next_state(bt_reset, 2, "OK"),                   sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_reset,               NULL, NULL, "ATZ\r",        4,      100000UL,   bt_error,   2,          sm_next_state(bt_set_firendly_name, 2, "OK"),       sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_firendly_name,   NULL, NULL, "AT+BTF=\"Friendly Name\"\r", 18, 100000UL, bt_error, 2,    sm_next_state(bt_set_connectable, 2, "OK"),         sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_connectable,     NULL, NULL, "AT+BTP\r",     7,      100000UL,   bt_error,   2,          sm_next_state(bt_set_key, 2, "OK"),                 sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_key,             NULL, NULL, "AT+BTK=\"8475\"\r", 14, 100000UL, bt_error, 2,          sm_next_state(bt_listening, 2, "OK"),               sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_listening,           NULL, NULL, "",             0,      -1,     0,          1,          sm_next_state(bt_answer, 4, "RING")),
    sm_state(   bt_answer,              NULL, NULL, "ATA\r",        4,      100000UL,   bt_error,   2,          sm_next_state(bt_in_call, 7, "CONNECT"),            sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_in_call,             NULL, NULL, "",             0,      100000UL, bt_error, 2,          sm_next_state(bt_set_connectable, 10, "NO CONNECT"), sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_error,               NULL, NULL, "",             0,      -1,         bt_off,     1,          sm_next_state(bt_off, 0, ""))
};

output:

id: 1820602156
id: 7
id: -1
id: 1973037073
id: 0
id: 0
id: 123336558
id: 0
id: 0
id: 0
id: 736
id: 760826203
id: 3108
id: -1322777276
id: 1
id: 7916
id: 152

It would seem that the larger example does not exist in memory. If anyone can point out what I'm doing wrong, that would be awesome.

So it looks like the problem is that you are not passing enough arguments to sm_state in the declaration states[0] .

If you declare like this it works:

struct state const states[] = {
    {bt_off, NULL, NULL, "", 0, -1, bt_off, 0},
    sm_state(   bt_on,                  NULL, NULL, "AT\r",         3,      100000UL,   bt_error,   2,          sm_next_state(bt_set_echo_off, 2, "OK"),            sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_echo_off,        NULL, NULL, "ATE0\r",       5,      100000UL,   bt_error,   2,          sm_next_state(bt_set_auto_answer, 2, "OK"),         sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_auto_answer,     NULL, NULL, "ATS0=2\r",     7,       100000UL,  bt_error,   2,          sm_next_state(bt_set_ignore_dsr, 2, "OK"),          sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_ignore_dsr,      NULL, NULL, "ATS102=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_spp, 2, "OK"),                 sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_spp,             NULL, NULL, "ATS102=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_io_cap, 2, "OK"),              sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_io_cap,          NULL, NULL, "ATS321=0\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_mitm_protection, 2, "OK"),     sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_mitm_protection, NULL, NULL, "ATS322=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_write, 2, "OK"),                   sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_write,               NULL, NULL, "AT&W\r",       5,      100000UL,   bt_error,   2,          sm_next_state(bt_reset, 2, "OK"),                   sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_reset,               NULL, NULL, "ATZ\r",        4,      100000UL,   bt_error,   2,          sm_next_state(bt_set_firendly_name, 2, "OK"),       sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_firendly_name,   NULL, NULL, "AT+BTF=\"Friendly Name\"\r", 18, 100000UL, bt_error, 2,    sm_next_state(bt_set_connectable, 2, "OK"),         sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_connectable,     NULL, NULL, "AT+BTP\r",     7,      100000UL,   bt_error,   2,          sm_next_state(bt_set_key, 2, "OK"),                 sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_key,             NULL, NULL, "AT+BTK=\"8475\"\r", 14, 100000UL, bt_error, 2,          sm_next_state(bt_listening, 2, "OK"),               sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_listening,           NULL, NULL, "",             0,      -1,     0,          1,          sm_next_state(bt_answer, 4, "RING")),
    sm_state(   bt_answer,              NULL, NULL, "ATA\r",        4,      100000UL,   bt_error,   2,          sm_next_state(bt_in_call, 7, "CONNECT"),            sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_in_call,             NULL, NULL, "",             0,      100000UL, bt_error, 2,          sm_next_state(bt_set_connectable, 10, "NO CONNECT"), sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_error,               NULL, NULL, "",             0,      -1,         bt_off,     1,          sm_next_state(bt_off, 0, ""))
};

While we're on the subject, I'd strongly recommend dropping these macros. They don't provide anything but stackoverflow questions cause when the compiler error messages can't be deciphered. I'd recommend initializing each of your variables as I did with states[0] .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM