Generic (file) cmdline (#102)

This commit is contained in:
Alex Kotov 2022-06-27 17:46:29 +03:00 committed by GitHub
parent 6d5c3740a9
commit f39383128f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 453 additions and 174 deletions

4
.gitignore vendored
View File

@ -108,11 +108,13 @@
/examples/assert
/examples/cmdline
/examples/cmdline_file
/examples/generic_file
/examples/generic_malloc
/examples/generic_mutex
/examples/macro_container_of
/examples/memmap
/examples/memory_file
/examples/ntoa
/examples/panic
/examples/pfa
@ -145,9 +147,9 @@
/tests/test_ntoa_assert
/tests/test_pfa
/tests/test_pfa_assert
/tests/test_printf
/tests/test_printf_fmt_gen
/tests/test_printf_fmt_gen.c
/tests/test_printf_gen
/tests/test_printf_gen.c
/tests/test_printf_reg
/tests/test_units_human

View File

@ -1,3 +1,7 @@
2022-06-27 Alex Kotov <kotovalexarian@gmail.com>
* include/kernaux/memory_file.h: Added
2022-06-25 Alex Kotov <kotovalexarian@gmail.com>
* configure.ac: Removed package "io"

View File

@ -33,7 +33,8 @@ libkernaux_la_SOURCES = \
src/libc.h \
src/generic/file.c \
src/generic/malloc.c \
src/generic/mutex.c
src/generic/mutex.c \
src/memory_file.c
########
# libc #

View File

@ -47,6 +47,8 @@ zero). Work-in-progress APIs can change at any time.
* Architecture-specific code (*work in progress*)
* [Declarations](/include/kernaux/arch/)
* [Functions](/include/kernaux/asm/)
* [Memory file](/include/kernaux/memory_file.h) (*non-breaking since* **?.?.?**)
* [Example](/examples/memory_file.c)
* Generic types
* [File](/include/kernaux/generic/file.h) (*non-breaking since* **?.?.?**)
* [Example](/examples/generic_file.c)
@ -57,7 +59,8 @@ zero). Work-in-progress APIs can change at any time.
* Algorithms
* [Free list memory allocator](/include/kernaux/free_list.h) (*non-breaking since* **?.?.?**)
* [Simple command line parser](/include/kernaux/cmdline.h) (*non-breaking since* **0.2.0**)
* [Example](/examples/cmdline.c)
* [Example: buffer](/examples/cmdline.c)
* [Example: file](/examples/cmdline_file.c)
* [Page Frame Allocator](/include/kernaux/pfa.h) (*work in progress*)
* [Example](/examples/pfa.c)
* Data formats

View File

@ -65,7 +65,7 @@ if KernAux::Version.with_cmdline?
end
assert 'when args cause buffer overflow' do
assert_raise KernAux::CmdlineError, 'buffer overflow' do
assert_raise KernAux::CmdlineError, 'EOF or buffer overflow' do
KernAux.cmdline 'a' * 4096
end
end

View File

@ -87,7 +87,7 @@ KernAux::Version.with_cmdline? and RSpec.describe KernAux, '.cmdline' do
specify do
expect { cmdline }.to \
raise_error described_class::CmdlineError, 'buffer overflow'
raise_error described_class::CmdlineError, 'EOF or buffer overflow'
end
end

View File

@ -66,7 +66,7 @@
error: 'too many args'
- cmdline: 'foo bar car'
buffer_size: 11
error: 'buffer overflow'
error: 'EOF or buffer overflow'
- cmdline: 'foo bar car'
argv_count_max: 2
buffer_size: 11
@ -88,7 +88,7 @@
error: 'too many args'
- cmdline: '\"foo\" \"bar\" \"car\"'
buffer_size: 11
error: 'buffer overflow'
error: 'EOF or buffer overflow'
- cmdline: '\"foo\" \"bar\" \"car\"'
argv_count_max: 2
buffer_size: 11

View File

@ -21,6 +21,16 @@ cmdline_LDADD = $(top_builddir)/libkernaux.la
cmdline_SOURCES = main.c cmdline.c
endif
################
# cmdline_file #
################
if WITH_CMDLINE
TESTS += cmdline_file
cmdline_file_LDADD = $(top_builddir)/libkernaux.la
cmdline_file_SOURCES = main.c cmdline_file.c
endif
################
# generic_file #
################
@ -63,6 +73,14 @@ memmap_LDADD = $(top_builddir)/libkernaux.la
memmap_SOURCES = main.c memmap.c
endif
###############
# memory_file #
###############
TESTS += memory_file
memory_file_LDADD = $(top_builddir)/libkernaux.la
memory_file_SOURCES = main.c memory_file.c
########
# ntoa #
########

View File

@ -1,6 +1,7 @@
#include <kernaux/cmdline.h>
#include <assert.h>
#include <stddef.h>
#include <string.h>
#define ARGV_COUNT_MAX 100

31
examples/cmdline_file.c Normal file
View File

@ -0,0 +1,31 @@
#include <kernaux/cmdline.h>
#include <kernaux/memory_file.h>
#include <assert.h>
#include <stddef.h>
#include <string.h>
static const char *const cmdline = "foo bar\\ baz \"car cdr\"";
static char buffer[4096];
void example_main()
{
char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX];
size_t argc;
struct KernAux_MemoryFile memory_file =
KernAux_MemoryFile_create(buffer, sizeof(buffer), NULL);
assert(kernaux_cmdline_file(
cmdline,
error_msg,
&argc,
&memory_file.file
));
assert(strcmp(error_msg, "") == 0);
assert(argc == 3);
assert(strcmp(&buffer[0], "foo") == 0);
assert(strcmp(&buffer[4], "bar baz") == 0);
assert(strcmp(&buffer[12], "car cdr") == 0);
}

16
examples/memory_file.c Normal file
View File

@ -0,0 +1,16 @@
#include <kernaux/memory_file.h>
#include <assert.h>
#include <string.h>
static char buffer[4096];
void example_main()
{
struct KernAux_MemoryFile memory_file =
KernAux_MemoryFile_create(buffer, sizeof(buffer), NULL);
KernAux_File_puts(&memory_file.file, "Hello, World!");
assert(strcmp(buffer, "Hello, World!") == 0);
}

View File

@ -11,7 +11,8 @@ nobase_include_HEADERS = \
kernaux/version.h \
kernaux/generic/file.h \
kernaux/generic/malloc.h \
kernaux/generic/mutex.h
kernaux/generic/mutex.h \
kernaux/memory_file.h
########
# ARCH #

View File

@ -6,6 +6,7 @@
#include <kernaux/assert.h>
#include <kernaux/macro.h>
#include <kernaux/version.h>
#include <kernaux/memory_file.h>
#include <kernaux/generic/file.h>
#include <kernaux/generic/malloc.h>

View File

@ -5,6 +5,8 @@
extern "C" {
#endif
#include <kernaux/generic/file.h>
#include <stdbool.h>
#include <stddef.h>
@ -22,6 +24,13 @@ bool kernaux_cmdline(
size_t buffer_size
);
bool kernaux_cmdline_file(
const char *cmdline,
char *error_msg,
size_t *argc,
KernAux_File file
);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,37 @@
#ifndef KERNAUX_INCLUDED_MEMORY_FILE
#define KERNAUX_INCLUDED_MEMORY_FILE
#ifdef __cplusplus
extern "C" {
#endif
#include <kernaux/generic/file.h>
#include <kernaux/generic/mutex.h>
#include <kernaux/macro.h>
#include <stddef.h>
typedef struct KernAux_MemoryFile {
struct KernAux_File file;
KernAux_Mutex KERNAUX_PRIVATE_FIELD(mutex);
char *KERNAUX_PRIVATE_FIELD(ptr);
size_t KERNAUX_PRIVATE_FIELD(size);
size_t KERNAUX_PRIVATE_FIELD(pos);
} *KernAux_MemoryFile;
struct KernAux_MemoryFile
KernAux_MemoryFile_create(void *ptr, size_t size, KernAux_Mutex mutex);
void KernAux_MemoryFile_init(
KernAux_MemoryFile memory_file,
void *ptr,
size_t size,
KernAux_Mutex mutex
);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -4,6 +4,7 @@
#include <kernaux/assert.h>
#include <kernaux/cmdline.h>
#include <kernaux/generic/file.h>
#include "libc.h"
@ -17,6 +18,22 @@ enum State {
QUOTE_BACKSLASH,
};
static bool kernaux_cmdline_common(
const char *cmdline,
char *error_msg,
size_t *argc,
char arg_terminator,
char **argv,
char *buffer,
size_t argv_count_max,
size_t buffer_size,
KernAux_File file
);
/*****************************
* Implementations: main API *
*****************************/
bool kernaux_cmdline(
const char *const cmdline,
char *const error_msg,
@ -33,10 +50,114 @@ bool kernaux_cmdline(
KERNAUX_ASSERT(argv_count_max > 0);
KERNAUX_ASSERT(buffer_size > 0);
return kernaux_cmdline_common(
cmdline,
error_msg,
argc,
'\0', // arg_terminator
argv,
buffer,
argv_count_max,
buffer_size,
NULL
);
}
bool kernaux_cmdline_file(
const char *const cmdline,
char *const error_msg,
size_t *const argc,
const KernAux_File file
) {
KERNAUX_ASSERT(cmdline);
KERNAUX_ASSERT(error_msg);
KERNAUX_ASSERT(argc);
KERNAUX_ASSERT(file);
return kernaux_cmdline_common(
cmdline,
error_msg,
argc,
'\0', // arg_terminator
NULL,
NULL,
0,
0,
file
);
}
/******************************************
* Implementation: main internal function *
******************************************/
#define FAIL(msg) do { \
strcpy(error_msg, msg); \
goto fail; \
} while (0)
#define PUT_CHAR(char) do { \
if (buffer_size && buffer_pos >= buffer_size) { \
FAIL("EOF or buffer overflow"); \
} \
if (buffer) { \
buffer[buffer_pos++] = char; \
} \
if (file) { \
if (KernAux_File_putc(file, char) == KERNAUX_EOF) { \
FAIL("EOF or buffer overflow"); \
} \
} \
} while (0)
#define PUT_ARG do { \
if (argv_count_max && *argc >= argv_count_max) { \
FAIL("too many args"); \
} \
if (argv && buffer) { \
argv[*argc] = &buffer[buffer_pos]; \
} \
++(*argc); \
} while (0)
#define PUT_ARG_AND_CHAR(char) do { \
if (argv_count_max && *argc >= argv_count_max) { \
FAIL("too many args"); \
} \
if (buffer_size && buffer_pos >= buffer_size) { \
FAIL("EOF or buffer overflow"); \
} \
if (argv && buffer) { \
argv[*argc] = &buffer[buffer_pos]; \
buffer[buffer_pos++] = char; \
} \
if (file) { \
if (KernAux_File_putc(file, char) == KERNAUX_EOF) { \
FAIL("EOF or buffer overflow"); \
} \
} \
++(*argc); \
} while (0)
bool kernaux_cmdline_common(
const char *const cmdline,
char *const error_msg,
size_t *const argc,
char arg_terminator,
char **const argv,
char *const buffer,
const size_t argv_count_max,
const size_t buffer_size,
const KernAux_File file
) {
KERNAUX_ASSERT(cmdline);
KERNAUX_ASSERT(error_msg);
KERNAUX_ASSERT(argc);
memset(error_msg, '\0', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
*argc = 0;
memset(argv, 0, sizeof(char*) * argv_count_max);
memset(buffer, '\0', buffer_size);
if (argv) memset(argv, 0, sizeof(char*) * argv_count_max);
if (buffer) memset(buffer, '\0', buffer_size);
if (cmdline[0] == '\0') return true;
@ -56,35 +177,14 @@ bool kernaux_cmdline(
} else if (cur == ' ') {
state = WHITESPACE;
} else if (cur == '\\') {
if (*argc >= argv_count_max) {
strcpy(error_msg, "too many args");
goto fail;
}
state = BACKSLASH;
argv[(*argc)++] = &buffer[buffer_pos];
PUT_ARG;
} else if (cur == '"') {
if (*argc >= argv_count_max) {
strcpy(error_msg, "too many args");
goto fail;
}
state = QUOTE;
argv[(*argc)++] = &buffer[buffer_pos];
PUT_ARG;
} else {
if (*argc >= argv_count_max) {
strcpy(error_msg, "too many args");
goto fail;
}
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
state = TOKEN;
argv[(*argc)++] = &buffer[buffer_pos];
buffer[buffer_pos++] = cur;
PUT_ARG_AND_CHAR(cur);
}
break;
@ -94,121 +194,61 @@ bool kernaux_cmdline(
} else if (cur == ' ') {
// do nothing
} else if (cur == '\\') {
if (*argc >= argv_count_max) {
strcpy(error_msg, "too many args");
goto fail;
}
state = BACKSLASH;
argv[(*argc)++] = &buffer[buffer_pos];
PUT_ARG;
} else if (cur == '"') {
if (*argc >= argv_count_max) {
strcpy(error_msg, "too many args");
goto fail;
}
state = QUOTE;
argv[(*argc)++] = &buffer[buffer_pos];
PUT_ARG;
} else {
if (*argc >= argv_count_max) {
strcpy(error_msg, "too many args");
goto fail;
}
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
state = TOKEN;
argv[(*argc)++] = &buffer[buffer_pos];
buffer[buffer_pos++] = cur;
PUT_ARG_AND_CHAR(cur);
}
break;
case TOKEN:
if (cur == '\0') {
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
state = FINAL;
buffer[buffer_pos++] = '\0';
PUT_CHAR(arg_terminator);
} else if (cur == ' ') {
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
state = WHITESPACE;
buffer[buffer_pos++] = '\0';
PUT_CHAR(arg_terminator);
} else if (cur == '\\') {
state = BACKSLASH;
} else if (cur == '"') {
strcpy(error_msg, "unescaped quotation mark");
goto fail;
FAIL("unescaped quotation mark");
} else {
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
buffer[buffer_pos++] = cur;
PUT_CHAR(cur);
}
break;
case BACKSLASH:
if (cur == '\0') {
strcpy(error_msg, "EOL after backslash");
goto fail;
FAIL("EOL after backslash");
} else {
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
state = TOKEN;
buffer[buffer_pos++] = cur;
PUT_CHAR(cur);
}
break;
case QUOTE:
if (cur == '\0') {
strcpy(error_msg, "EOL inside quote");
goto fail;
FAIL("EOL inside quote");
} else if (cur == '\\') {
state = QUOTE_BACKSLASH;
} else if (cur == '"') {
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
state = WHITESPACE;
buffer[buffer_pos++] = '\0';
PUT_CHAR(arg_terminator);
} else {
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
buffer[buffer_pos++] = cur;
PUT_CHAR(cur);
}
break;
case QUOTE_BACKSLASH:
if (cur == '\0') {
strcpy(error_msg, "EOL after backslash inside quote");
goto fail;
FAIL("EOL after backslash inside quote");
} else {
if (buffer_pos >= buffer_size) {
strcpy(error_msg, "buffer overflow");
goto fail;
}
state = QUOTE;
buffer[buffer_pos++] = cur;
PUT_CHAR(cur);
}
break;
}
@ -220,7 +260,7 @@ bool kernaux_cmdline(
fail:
*argc = 0;
memset(argv, 0, sizeof(char*) * argv_count_max);
memset(buffer, '\0', buffer_size);
if (argv) memset(argv, 0, sizeof(char*) * argv_count_max);
if (buffer) memset(buffer, '\0', buffer_size);
return false;
}

51
src/memory_file.c Normal file
View File

@ -0,0 +1,51 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <kernaux/assert.h>
#include <kernaux/generic/file.h>
#include <kernaux/generic/mutex.h>
#include <kernaux/memory_file.h>
static int KernAux_MemoryFile_putc(void *file, unsigned char c);
struct KernAux_MemoryFile KernAux_MemoryFile_create(
void *const ptr,
const size_t size,
const KernAux_Mutex mutex
) {
struct KernAux_MemoryFile memory_file;
KernAux_MemoryFile_init(&memory_file, ptr, size, mutex);
return memory_file;
}
void KernAux_MemoryFile_init(
const KernAux_MemoryFile memory_file,
void *const ptr,
const size_t size,
const KernAux_Mutex mutex
) {
KERNAUX_ASSERT(memory_file);
KERNAUX_ASSERT(ptr);
KERNAUX_ASSERT(size);
memory_file->file.putc = KernAux_MemoryFile_putc;
memory_file->file.puts = NULL;
memory_file->file.write = NULL;
memory_file->mutex = mutex;
memory_file->ptr = ptr;
memory_file->size = size;
memory_file->pos = 0;
}
int KernAux_MemoryFile_putc(void *const file, const unsigned char c)
{
const KernAux_MemoryFile memory_file = file;
KERNAUX_ASSERT(memory_file);
KERNAUX_ASSERT(memory_file->ptr);
KERNAUX_ASSERT(memory_file->size);
if (memory_file->pos >= memory_file->size) return KERNAUX_EOF;
memory_file->ptr[memory_file->pos++] = c;
return c;
}

View File

@ -290,6 +290,18 @@ test_pfa_assert_SOURCES = \
endif
endif
###############
# test_printf #
###############
if WITH_PRINTF
TESTS += test_printf
test_printf_LDADD = $(top_builddir)/libkernaux.la
test_printf_SOURCES = \
main.c \
test_printf.c
endif
#######################
# test_printf_fmt_gen #
#######################
@ -335,18 +347,6 @@ CLEANFILES += test_printf_gen.c
test_printf_gen.c: printf_gen.py printf_gen.jinja $(top_srcdir)/common/printf.yml $(top_srcdir)/common/printf_orig.yml
python3 printf_gen.py
###################
# test_printf_reg #
###################
if WITH_PRINTF
TESTS += test_printf_reg
test_printf_reg_LDADD = $(top_builddir)/libkernaux.la
test_printf_reg_SOURCES = \
main.c \
test_printf_reg.c
endif
####################
# test_units_human #
####################

View File

@ -3,6 +3,7 @@
#endif
#include <kernaux/cmdline.h>
#include <kernaux/memory_file.h>
#include <assert.h>
#include <stdbool.h>
@ -82,33 +83,64 @@ void test(
assert(argv);
assert(buffer);
memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
memset(argv, 'x', sizeof(char*) * argv_count_max);
memset(buffer, 'x', buffer_size);
{
memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
memset(argv, 'x', sizeof(char*) * argv_count_max);
memset(buffer, 'x', buffer_size);
assert(
kernaux_cmdline(
cmdline,
error_msg,
&argc,
argv,
buffer,
argv_count_max,
buffer_size
) == !!expected_result
);
assert(
kernaux_cmdline(
cmdline,
error_msg,
&argc,
argv,
buffer,
argv_count_max,
buffer_size
) == !!expected_result
);
assert(strcmp(error_msg, expected_error_msg) == 0);
assert(argc == expected_argc);
assert(strcmp(error_msg, expected_error_msg) == 0);
assert(argc == expected_argc);
if (expected_argv) {
for (size_t index = 0; index < argc; ++index) {
assert(strcmp(argv[index], expected_argv[index]) == 0);
if (expected_argv) {
for (size_t index = 0; index < argc; ++index) {
assert(strcmp(argv[index], expected_argv[index]) == 0);
}
}
for (size_t index = argc; index < argv_count_max; ++index) {
assert(argv[index] == NULL);
}
}
for (size_t index = argc; index < argv_count_max; ++index) {
assert(argv[index] == NULL);
if (strcmp(expected_error_msg, "too many args") != 0) {
memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
memset(argv, 'x', sizeof(char*) * argv_count_max);
memset(buffer, 'x', buffer_size);
struct KernAux_MemoryFile memory_file =
KernAux_MemoryFile_create(buffer, buffer_size, NULL);
assert(
kernaux_cmdline_file(
cmdline,
error_msg,
&argc,
&memory_file.file
) == !!expected_result
);
assert(strcmp(error_msg, expected_error_msg) == 0);
assert(argc == expected_argc);
if (expected_argv) {
const char *arg = buffer;
for (size_t index = 0; index < argc; ++index) {
assert(strcmp(expected_argv[index], arg) == 0);
arg += strlen(arg) + 1;
}
}
}
free(error_msg);

View File

@ -3,6 +3,7 @@
#endif
#include <kernaux/cmdline.h>
#include <kernaux/memory_file.h>
#include <assert.h>
#include <stdbool.h>
@ -51,15 +52,15 @@ void test_main()
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 3, 12, true, "", 3, argv_backslashX3_X3);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 3, 12, true, "", 3, argv_quotmarkX3_X3);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 0, false, "too many args", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 0, false, "too many args", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 2, 0, false, "too many args", 0, NULL);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 11, false, "buffer overflow", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 11, false, "buffer overflow", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 0, 11, false, "buffer overflow", 0, NULL);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 11, false, "too many args", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 11, false, "too many args", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 2, 11, false, "too many args", 0, NULL);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 0, false, "too many args", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 0, false, "too many args", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 2, 0, false, "too many args", 0, NULL);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 11, false, "EOF or buffer overflow", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 11, false, "EOF or buffer overflow", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 0, 11, false, "EOF or buffer overflow", 0, NULL);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 2, 11, false, "too many args", 0, NULL);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 2, 11, false, "too many args", 0, NULL);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 2, 11, false, "too many args", 0, NULL);
test("\\", 0, 0, false, "EOL after backslash", 0, NULL);
test(" \\", 0, 0, false, "EOL after backslash", 0, NULL);
@ -128,7 +129,7 @@ void test_main()
memset(buffer, 'a', 4096);
buffer[4096] = '\0';
// 4096 of "a"
test(buffer, 256, 4096, false, "buffer overflow", 0, NULL);
test(buffer, 256, 4096, false, "EOF or buffer overflow", 0, NULL);
free(buffer);
}
}
@ -155,33 +156,64 @@ void test(
assert(argv);
assert(buffer);
memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
memset(argv, 'x', sizeof(char*) * argv_count_max);
memset(buffer, 'x', buffer_size);
{
memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
memset(argv, 'x', sizeof(char*) * argv_count_max);
memset(buffer, 'x', buffer_size);
assert(
kernaux_cmdline(
cmdline,
error_msg,
&argc,
argv,
buffer,
argv_count_max,
buffer_size
) == !!expected_result
);
assert(
kernaux_cmdline(
cmdline,
error_msg,
&argc,
argv,
buffer,
argv_count_max,
buffer_size
) == !!expected_result
);
assert(strcmp(error_msg, expected_error_msg) == 0);
assert(argc == expected_argc);
assert(strcmp(error_msg, expected_error_msg) == 0);
assert(argc == expected_argc);
if (expected_argv) {
for (size_t index = 0; index < argc; ++index) {
assert(strcmp(argv[index], expected_argv[index]) == 0);
if (expected_argv) {
for (size_t index = 0; index < argc; ++index) {
assert(strcmp(argv[index], expected_argv[index]) == 0);
}
}
for (size_t index = argc; index < argv_count_max; ++index) {
assert(argv[index] == NULL);
}
}
for (size_t index = argc; index < argv_count_max; ++index) {
assert(argv[index] == NULL);
if (strcmp(expected_error_msg, "too many args") != 0) {
memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
memset(argv, 'x', sizeof(char*) * argv_count_max);
memset(buffer, 'x', buffer_size);
struct KernAux_MemoryFile memory_file =
KernAux_MemoryFile_create(buffer, buffer_size, NULL);
assert(
kernaux_cmdline_file(
cmdline,
error_msg,
&argc,
&memory_file.file
) == !!expected_result
);
assert(strcmp(error_msg, expected_error_msg) == 0);
assert(argc == expected_argc);
if (expected_argv) {
const char *arg = buffer;
for (size_t index = 0; index < argc; ++index) {
assert(strcmp(expected_argv[index], arg) == 0);
arg += strlen(arg) + 1;
}
}
}
free(error_msg);