mirror of https://github.com/tailix/libkernaux.git
Implement backslash in command line parser
This commit is contained in:
parent
f4007c541f
commit
b2c10342f2
|
@ -7,6 +7,7 @@ enum State {
|
||||||
FINAL,
|
FINAL,
|
||||||
WHITESPACE,
|
WHITESPACE,
|
||||||
TOKEN,
|
TOKEN,
|
||||||
|
BACKSLASHED,
|
||||||
};
|
};
|
||||||
|
|
||||||
kernaux_bool kernaux_cmdline_parse(
|
kernaux_bool kernaux_cmdline_parse(
|
||||||
|
@ -52,6 +53,7 @@ kernaux_bool kernaux_cmdline_parse(
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case FINAL:
|
case FINAL:
|
||||||
break; // Case break; loop break after switch.
|
break; // Case break; loop break after switch.
|
||||||
|
|
||||||
case INITIAL:
|
case INITIAL:
|
||||||
if (cur == '\0') {
|
if (cur == '\0') {
|
||||||
state = FINAL;
|
state = FINAL;
|
||||||
|
@ -59,6 +61,15 @@ kernaux_bool kernaux_cmdline_parse(
|
||||||
else if (cur == ' ') {
|
else if (cur == ' ') {
|
||||||
state = WHITESPACE;
|
state = WHITESPACE;
|
||||||
}
|
}
|
||||||
|
else if (cur == '\\') {
|
||||||
|
if (*argc >= argv_count_max) {
|
||||||
|
kernaux_strncpy(error_msg, "too many args", 13);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = BACKSLASHED;
|
||||||
|
argv[(*argc)++] = buffer;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (*argc >= argv_count_max) {
|
if (*argc >= argv_count_max) {
|
||||||
kernaux_strncpy(error_msg, "too many args", 13);
|
kernaux_strncpy(error_msg, "too many args", 13);
|
||||||
|
@ -76,12 +87,22 @@ kernaux_bool kernaux_cmdline_parse(
|
||||||
++buffer_size;
|
++buffer_size;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WHITESPACE:
|
case WHITESPACE:
|
||||||
if (cur == '\0') {
|
if (cur == '\0') {
|
||||||
state = FINAL;
|
state = FINAL;
|
||||||
}
|
}
|
||||||
else if (cur == ' ') {
|
else if (cur == ' ') {
|
||||||
}
|
}
|
||||||
|
else if (cur == '\\') {
|
||||||
|
if (*argc >= argv_count_max) {
|
||||||
|
kernaux_strncpy(error_msg, "too many args", 13);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = BACKSLASHED;
|
||||||
|
argv[(*argc)++] = buffer;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (*argc >= argv_count_max) {
|
if (*argc >= argv_count_max) {
|
||||||
kernaux_strncpy(error_msg, "too many args", 13);
|
kernaux_strncpy(error_msg, "too many args", 13);
|
||||||
|
@ -99,6 +120,7 @@ kernaux_bool kernaux_cmdline_parse(
|
||||||
++buffer_size;
|
++buffer_size;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN:
|
case TOKEN:
|
||||||
if (cur == '\0') {
|
if (cur == '\0') {
|
||||||
if (buffer_size >= arg_size_max) {
|
if (buffer_size >= arg_size_max) {
|
||||||
|
@ -120,6 +142,9 @@ kernaux_bool kernaux_cmdline_parse(
|
||||||
*(buffer++) = '\0';
|
*(buffer++) = '\0';
|
||||||
buffer_size = 0;
|
buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
else if (cur == '\\') {
|
||||||
|
state = BACKSLASHED;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (buffer_size >= arg_size_max) {
|
if (buffer_size >= arg_size_max) {
|
||||||
kernaux_strncpy(error_msg, "arg too long", 12);
|
kernaux_strncpy(error_msg, "arg too long", 12);
|
||||||
|
@ -130,6 +155,23 @@ kernaux_bool kernaux_cmdline_parse(
|
||||||
++buffer_size;
|
++buffer_size;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BACKSLASHED:
|
||||||
|
if (cur == '\0') {
|
||||||
|
kernaux_strncpy(error_msg, "EOL after backslash", 19);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (buffer_size >= arg_size_max) {
|
||||||
|
kernaux_strncpy(error_msg, "arg too long", 12);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = TOKEN;
|
||||||
|
*(buffer++) = cur;
|
||||||
|
++buffer_size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == FINAL) {
|
if (state == FINAL) {
|
||||||
|
|
|
@ -26,6 +26,54 @@ static const char *const argv_foo_bar[] = {"foo", "bar"};
|
||||||
|
|
||||||
static const char *const argv_foo_bar_car[] = {"foo", "bar", "car"};
|
static const char *const argv_foo_bar_car[] = {"foo", "bar", "car"};
|
||||||
|
|
||||||
|
static const char *const argv_space[] = {" "};
|
||||||
|
|
||||||
|
static const char *const argv_backslash[] = {"\\"};
|
||||||
|
|
||||||
|
static const char *const argv_foospace[] = {"foo "};
|
||||||
|
|
||||||
|
static const char *const argv_foobackslash[] = {"foo\\"};
|
||||||
|
|
||||||
|
static const char *const argv_spacefoo[] = {" foo"};
|
||||||
|
|
||||||
|
static const char *const argv_backslashfoo[] = {"\\foo"};
|
||||||
|
|
||||||
|
static const char *const argv_spacefoospace[] = {" foo "};
|
||||||
|
|
||||||
|
static const char *const argv_backslashfoobackslash[] = {"\\foo\\"};
|
||||||
|
|
||||||
|
static const char *const argv_foospacebar[] = {"foo bar"};
|
||||||
|
|
||||||
|
static const char *const argv_foobackslashbar[] = {"foo\\bar"};
|
||||||
|
|
||||||
|
static const char *const argv_spaceX3_X3[] = {" ", " ", " "};
|
||||||
|
|
||||||
|
static const char *const argv_backslashX3_X3[] = {"\\\\\\", "\\\\\\", "\\\\\\"};
|
||||||
|
|
||||||
|
static const char *const argv_spacefoo_bar[] = {" foo", "bar"};
|
||||||
|
|
||||||
|
static const char *const argv_backslashfoo_bar[] = {"\\foo", "bar"};
|
||||||
|
|
||||||
|
static const char *const argv_foospace_bar[] = {"foo ", "bar"};
|
||||||
|
|
||||||
|
static const char *const argv_foobackslash_bar[] = {"foo\\", "bar"};
|
||||||
|
|
||||||
|
static const char *const argv_spacefoospace_bar[] = {" foo ", "bar"};
|
||||||
|
|
||||||
|
static const char *const argv_backslashfoobackslash_bar[] = {"\\foo\\", "bar"};
|
||||||
|
|
||||||
|
static const char *const argv_foo_spacebar[] = {"foo", " bar"};
|
||||||
|
|
||||||
|
static const char *const argv_foo_backslashbar[] = {"foo", "\\bar"};
|
||||||
|
|
||||||
|
static const char *const argv_foo_barspace[] = {"foo", "bar "};
|
||||||
|
|
||||||
|
static const char *const argv_foo_barbackslash[] = {"foo", "bar\\"};
|
||||||
|
|
||||||
|
static const char *const argv_foo_spacebarspace[] = {"foo", " bar "};
|
||||||
|
|
||||||
|
static const char *const argv_foo_backslashbarbackslash[] = {"foo", "\\bar\\"};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
test("", 0, 0, true, "", 0, argv0);
|
test("", 0, 0, true, "", 0, argv0);
|
||||||
|
@ -49,6 +97,43 @@ int main()
|
||||||
test("foo bar car", 0, 3, false, "arg too long", 0, argv0);
|
test("foo bar car", 0, 3, false, "arg too long", 0, argv0);
|
||||||
test("foo bar car", 2, 3, false, "arg too long", 0, argv0);
|
test("foo bar car", 2, 3, false, "arg too long", 0, argv0);
|
||||||
|
|
||||||
|
test("\\ ", 0, 0, true, "", 1, argv_space);
|
||||||
|
test("\\\\", 0, 0, true, "", 1, argv_backslash);
|
||||||
|
test("foo\\ ", 0, 0, true, "", 1, argv_foospace);
|
||||||
|
test("foo\\\\", 0, 0, true, "", 1, argv_foobackslash);
|
||||||
|
test("\\ foo", 0, 0, true, "", 1, argv_spacefoo);
|
||||||
|
test("\\\\foo", 0, 0, true, "", 1, argv_backslashfoo);
|
||||||
|
test("\\ foo\\ ", 0, 0, true, "", 1, argv_spacefoospace);
|
||||||
|
test("\\\\foo\\\\", 0, 0, true, "", 1, argv_backslashfoobackslash);
|
||||||
|
test("foo\\ bar", 0, 0, true, "", 1, argv_foospacebar);
|
||||||
|
test("foo\\\\bar", 0, 0, true, "", 1, argv_foobackslashbar);
|
||||||
|
test("\\ foo bar", 0, 0, true, "", 2, argv_spacefoo_bar);
|
||||||
|
test("\\\\foo bar", 0, 0, true, "", 2, argv_backslashfoo_bar);
|
||||||
|
test("foo\\ bar", 0, 0, true, "", 2, argv_foospace_bar);
|
||||||
|
test("foo\\\\ bar", 0, 0, true, "", 2, argv_foobackslash_bar);
|
||||||
|
test("\\ foo\\ bar", 0, 0, true, "", 2, argv_spacefoospace_bar);
|
||||||
|
test("\\\\foo\\\\ bar", 0, 0, true, "", 2, argv_backslashfoobackslash_bar);
|
||||||
|
test("foo \\ bar", 0, 0, true, "", 2, argv_foo_spacebar);
|
||||||
|
test("foo \\\\bar", 0, 0, true, "", 2, argv_foo_backslashbar);
|
||||||
|
test("foo bar\\ ", 0, 0, true, "", 2, argv_foo_barspace);
|
||||||
|
test("foo bar\\\\", 0, 0, true, "", 2, argv_foo_barbackslash);
|
||||||
|
test("foo \\ bar\\ ", 0, 0, true, "", 2, argv_foo_spacebarspace);
|
||||||
|
test("foo \\\\bar\\\\", 0, 0, true, "", 2, argv_foo_backslashbarbackslash);
|
||||||
|
|
||||||
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 3, 0, true, "", 3, argv_spaceX3_X3);
|
||||||
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 3, 0, true, "", 3, argv_backslashX3_X3);
|
||||||
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 4, true, "", 3, argv_spaceX3_X3);
|
||||||
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 4, true, "", 3, argv_backslashX3_X3);
|
||||||
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 3, 4, true, "", 3, argv_spaceX3_X3);
|
||||||
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 3, 4, true, "", 3, argv_backslashX3_X3);
|
||||||
|
|
||||||
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 0, false, "too many args", 0, argv0);
|
||||||
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 0, false, "too many args", 0, argv0);
|
||||||
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 3, false, "arg too long", 0, argv0);
|
||||||
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 3, false, "arg too long", 0, argv0);
|
||||||
|
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 3, false, "arg too long", 0, argv0);
|
||||||
|
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 3, false, "arg too long", 0, argv0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue