我正在尝试使用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;
};
使用此宏:
#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 :(得分: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, ""))
};
虽然我们已经讨论过此主题,但我强烈建议您删除这些宏。他们不提供任何东西,但堆栈溢出问题会导致编译器错误消息无法解密。我建议您像使用states[0]
一样初始化每个变量。