Я себе сделал "универсальный command line парсер"
Примерно так.
Хедер:
Код
#define PARAM_CHAR 0x01
#define PARAM_STRING 0x02
#define PARAM_UINT8 0x04
#define PARAM_UINT16 0x08
#define PARAM_UINT32 0x10
#define PARAM_ARRAY_CNT 0x40
#define PARAM_ARRAY 0x80
typedef struct sCmd {
const char *name;
void *params;
void *parsed;
const char *help; //help string
char *stoppedAt;
uint8_t num_parsed;
}tCmd;
int8_t process_cmd(char *line, tCmd *cmd);
И пользую в сурсе:
Код
#define CMD_PING "ping "
#define CMD_ADDR "addr"
#define CMD_SEND "send " // panId is used current, first 0x04X dest addr, then arbitrary number of bytes
#define CMD_ACK "ack"
#define CMD_RESET "reset"
#define CMD_ID "id"
#define CMD_VERSION "version"
#define CMD_HELP "help"
uint8_t paramsPing[] = {PARAM_UINT16, PARAM_UINT16, 0};
uint8_t paramsAddr[] = {PARAM_UINT16, 0};
uint8_t paramsSend[] = {PARAM_UINT16, PARAM_UINT16, PARAM_ARRAY_CNT, PARAM_ARRAY | PARAM_UINT8, 0};
//...
tCmd cmds[] = {
{CMD_ADDR, paramsAddr, &parsedAddr, "[address]"},
{CMD_SEND, paramsSend, &parsedSend, "panId address byte byte ..."},
{CMD_ACK, NULL, NULL, NULL},
{CMD_RESET, NULL, NULL, NULL},
{CMD_PING, paramsPing, parsedPing, "destinationPanID destinationAddr"},
{CMD_ID, NULL, NULL, NULL},
{CMD_VERSION, NULL, NULL, NULL},
{CMD_HELP, NULL, NULL, NULL},
{NULL, NULL, NULL, NULL}
};
void mailn_loop()
{
int indx = = process_cmd((char*) read_buffer, &cmds[0]);
switch (index) {
case -1:
{
printf( "Unknown cmd\n>");
}
break;
case 0:
// empty string
break;
case 1: // 1- based index..
if (cmds[index - 1].num_parsed) {
cmd_set_addr(parsedAddr);
} else {
cmd_get_addr();
}
cmds[index-1].num_parsed = 0;
//......
}
}
Код фактически не растет с добавлением комманд, только структуры добавляются.
И не болит голова у дятла с разборкой параметров.
Указываешь тип параметра, если сможет, распарсит.
Цитата(Сергей Борщ @ Apr 13 2015, 06:01)

Чем не устраивает классический вариант - каждая функция получает первым параметром количество аргументов и вторым - массив указателей на аргументы?
Все функции имеют вид error_code_type (*function)(int argc, char *argv[]), поиск по названию в цикле, необходимое количество аргументов можно держать в массиве вместе с имененм и проверять соответствие фактическому количеству аргументов перед вызовом. Тогда и первый параметр функции не нужен.
Не всегда комманд лайн приходит в классической форме.
Частенько это стрим характеров, которые надо просто читать с сериал порта или сокета.
И с количеством параметров таким образом будут проблемы.
Верить нельзя никому, даже себе. Мне - можно.