2014-11-10 3 views
1

Я пытаюсь создать текстовый синтаксический анализатор с использованием структуры. Кажется, что это работает отлично для более мелкой структуры, которую я использовал для ее проверки, но большая стойка, требуемая для моего последнего приложения (управление модемом), кажется, не представляется так, как хотелось бы в памяти.Инициализация структуры с массивом вложенных структур

Я думаю, что проблема заключается в инициализации эту структуру:

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; 
}; 

С помощью этого макроса:

#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__}} 

где next_state является:

#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; 
}; 

Тестовый пример, который работает так:

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; 
} 

выход:

id: 1 
id: 2 
id: 3 

И чем больше структура, которая не работает:

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, "")) 
}; 

выход:

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 

Казалось бы, что больше примеров не существует в памяти , Если кто-нибудь может указать, что я делаю неправильно, это было бы потрясающе.

+0

Хммм. Работает для меня, за исключением того, что мне нужно изменить '% d' на'% zu' в формате печати, потому что 'id' является' size_t'. –

ответ

1

Так что проблема в том, что вы не передаете достаточно аргументов sm_state в декларации states[0].

Если вы объявляете, как это работает:

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, "")) 
}; 

Пока мы на эту тему, я бы настоятельно рекомендовал сбросив эти макросы. Они не предоставляют ничего, кроме вопросов, связанных с stackoverflow, потому что сообщения об ошибках компилятора не могут быть расшифрованы. Я бы рекомендовал инициализировать каждую из ваших переменных, как и в случае с states[0].

Смежные вопросы