1
0
Fork 0
mirror of https://github.com/tailix/libclayer.git synced 2024-11-20 11:06:24 -05:00

Remove command line parser

This commit is contained in:
Alex Kotov 2022-12-25 13:23:20 +04:00
parent e6181321b1
commit e780eb67b7
Signed by: kotovalexarian
GPG key ID: 553C0EBBEB5D5F08
14 changed files with 0 additions and 566 deletions

View file

@ -77,9 +77,6 @@ endif
# Default packages #
####################
if WITH_CMDLINE
libkernaux_la_SOURCES += src/cmdline.c
endif
if WITH_ELF
libkernaux_la_SOURCES += src/elf.c
endif

View file

@ -49,7 +49,6 @@ zero). Work-in-progress APIs can change at any time.
* [Mutex](/include/kernaux/generic/mutex.h) (*non-breaking since* **0.5.0**)
* Algorithms
* [Free list memory allocator](/include/kernaux/free_list.h) (*non-breaking since* **0.5.0**)
* [Simple command line parser](/include/kernaux/cmdline.h) (*non-breaking since* **0.2.0**)
* [Page Frame Allocator](/include/kernaux/pfa.h) (*work in progress*)
* Data formats
* [ELF](/include/kernaux/elf.h) (*work in progress*)
@ -143,7 +142,6 @@ explicitly included, use `--without-all`.
* `--with[out]-arch-riscv64` - architecture riscv64
* `--with[out]-arch-x86-64` - architecture x86-64
* `--with[out]-asm` - kernel assembler helpers
* `--with[out]-cmdline` - command line parser
* `--with[out]-free-list` - free list memory allocator
* `--with[out]-memmap` - memory map
* `--with[out]-ntoa` - itoa/ftoa

View file

@ -66,7 +66,6 @@ AC_ARG_WITH( [arch-i386], AS_HELP_STRING([--without-arch-i386], [wit
AC_ARG_WITH( [arch-riscv64], AS_HELP_STRING([--without-arch-riscv64], [without architecture riscv64]))
AC_ARG_WITH( [arch-x86-64], AS_HELP_STRING([--without-arch-x86-64], [without architecture x86-64]))
AC_ARG_WITH( [asm], AS_HELP_STRING([--without-asm], [without kernel assembler helpers]))
AC_ARG_WITH( [cmdline], AS_HELP_STRING([--without-cmdline], [without command line parser]))
AC_ARG_WITH( [elf], AS_HELP_STRING([--without-elf], [without ELF utils]))
AC_ARG_WITH( [free-list], AS_HELP_STRING([--without-free-list], [without free list memory allocator]))
AC_ARG_WITH( [mbr], AS_HELP_STRING([--without-mbr], [without MBR utils]))
@ -107,7 +106,6 @@ if test -z "$with_arch_i386"; then with_arch_i386=no; fi
if test -z "$with_arch_riscv64"; then with_arch_riscv64=no; fi
if test -z "$with_arch_x86_64"; then with_arch_x86_64=no; fi
if test -z "$with_asm"; then with_asm=no; fi
if test -z "$with_cmdline"; then with_cmdline=no; fi
if test -z "$with_elf"; then with_elf=no; fi
if test -z "$with_free_list"; then with_free_list=no; fi
if test -z "$with_mbr"; then with_mbr=no; fi
@ -149,7 +147,6 @@ AS_IF([test "$with_arch_i386" = no ], [with_arch_i386=no], [wit
AS_IF([test "$with_arch_riscv64" = no ], [with_arch_riscv64=no], [with_arch_riscv64=yes])
AS_IF([test "$with_arch_x86_64" = no ], [with_arch_x86_64=no], [with_arch_x86_64=yes])
AS_IF([test "$with_asm" = no ], [with_asm=no], [with_asm=yes])
AS_IF([test "$with_cmdline" = no ], [with_cmdline=no], [with_cmdline=yes])
AS_IF([test "$with_elf" = no ], [with_elf=no], [with_elf=yes])
AS_IF([test "$with_free_list" = no ], [with_free_list=no], [with_free_list=yes])
AS_IF([test "$with_mbr" = no ], [with_mbr=no], [with_mbr=yes])
@ -209,7 +206,6 @@ AM_CONDITIONAL([WITH_ARCH_I386], [test "$with_arch_i386" = yes])
AM_CONDITIONAL([WITH_ARCH_RISCV64], [test "$with_arch_riscv64" = yes])
AM_CONDITIONAL([WITH_ARCH_X86_64], [test "$with_arch_x86_64" = yes])
AM_CONDITIONAL([WITH_ASM], [test "$with_asm" = yes])
AM_CONDITIONAL([WITH_CMDLINE], [test "$with_cmdline" = yes])
AM_CONDITIONAL([WITH_ELF], [test "$with_elf" = yes])
AM_CONDITIONAL([WITH_FREE_LIST], [test "$with_free_list" = yes])
AM_CONDITIONAL([WITH_MBR], [test "$with_mbr" = yes])
@ -257,7 +253,6 @@ AS_IF([test "$with_arch_i386" = yes], [AC_DEFINE([WITH_ARCH_I386],
AS_IF([test "$with_arch_riscv64" = yes], [AC_DEFINE([WITH_ARCH_RISCV64], [1], [with architecture riscv64])])
AS_IF([test "$with_arch_x86_64" = yes], [AC_DEFINE([WITH_ARCH_X86_64], [1], [with architecture x86_64])])
AS_IF([test "$with_asm" = yes], [AC_DEFINE([WITH_ASM], [1], [with kernel assembler helpers])])
AS_IF([test "$with_cmdline" = yes], [AC_DEFINE([WITH_CMDLINE], [1], [with command line parser])])
AS_IF([test "$with_elf" = yes], [AC_DEFINE([WITH_ELF], [1], [with ELF utils])])
AS_IF([test "$with_free_list" = yes], [AC_DEFINE([WITH_FREE_LIST], [1], [with free list memory allocator])])
AS_IF([test "$with_mbr" = yes], [AC_DEFINE([WITH_MBR], [1], [with MBR utils])])
@ -288,7 +283,6 @@ dnl Packages (enabled by default)
AS_IF([test "$with_arch_i386" = no], [AC_SUBST([comment_line_arch_i386], [//])])
AS_IF([test "$with_arch_riscv64" = no], [AC_SUBST([comment_line_arch_riscv64], [//])])
AS_IF([test "$with_arch_x86_64" = no], [AC_SUBST([comment_line_arch_x86_64], [//])])
AS_IF([test "$with_cmdline" = no], [AC_SUBST([comment_line_cmdline], [//])])
AS_IF([test "$with_elf" = no], [AC_SUBST([comment_line_elf], [//])])
AS_IF([test "$with_free_list" = no], [AC_SUBST([comment_line_free_list], [//])])
AS_IF([test "$with_mbr" = no], [AC_SUBST([comment_line_mbr], [//])])

View file

@ -9,7 +9,6 @@ nobase_include_HEADERS = \
kernaux/asm/riscv64.h \
kernaux/asm/x86_64.h \
kernaux/asm/x86.h \
kernaux/cmdline.h \
kernaux/elf.h \
kernaux/free_list.h \
kernaux/generic/display.h \

View file

@ -6,7 +6,6 @@
#include <kernaux/arch/i386.h>
#include <kernaux/arch/riscv64.h>
#include <kernaux/arch/x86_64.h>
#include <kernaux/cmdline.h>
#include <kernaux/elf.h>
#include <kernaux/free_list.h>
#include <kernaux/generic/display.h>

View file

@ -1,29 +0,0 @@
#ifndef KERNAUX_INCLUDED_CMDLINE
#define KERNAUX_INCLUDED_CMDLINE
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#define KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX 256
#define KERNAUX_CMDLINE_ERROR_MSG_SLEN_MAX \
(KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX - 1)
bool kernaux_cmdline(
const char *cmdline,
char *error_msg,
size_t *argc,
char **argv,
char *buffer,
size_t arg_count_max,
size_t buffer_size
);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,7 +1,6 @@
#ifndef KERNAUX_INCLUDED_VERSION
#define KERNAUX_INCLUDED_VERSION
@comment_line_cmdline@#define KERNAUX_VERSION_WITH_CMDLINE
@comment_line_elf@#define KERNAUX_VERSION_WITH_ELF
@comment_line_free_list@#define KERNAUX_VERSION_WITH_FREE_LIST
@comment_line_mbr@#define KERNAUX_VERSION_WITH_MBR

View file

@ -8,7 +8,6 @@ include/kernaux/asm/i386.h
include/kernaux/asm/riscv64.h
include/kernaux/asm/x86.h
include/kernaux/asm/x86_64.h
include/kernaux/cmdline.h
include/kernaux/elf.h
include/kernaux/free_list.h
include/kernaux/generic/display.h

View file

@ -1,291 +0,0 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "assert.h"
#include <kernaux/cmdline.h>
#include <kernaux/macro.h>
#include <stddef.h>
#include <string.h>
enum State {
INITIAL,
FINAL,
WHITESPACE,
TOKEN,
BACKSLASH,
QUOTE,
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 *arg_idxs,
size_t arg_count_max,
size_t buffer_size
);
static bool kernaux_cmdline_iter(
char cur,
enum State *state,
size_t *buffer_or_file_pos,
char *error_msg,
size_t *argc,
char arg_terminator,
char **argv,
char *buffer,
size_t *arg_idxs,
size_t arg_count_max,
size_t buffer_size
);
/*******************************
* Implementations: public API *
*******************************/
bool kernaux_cmdline(
const char *const cmdline,
char *const error_msg,
size_t *const argc,
char **const argv,
char *const buffer,
const size_t arg_count_max,
const size_t buffer_size
) {
KERNAUX_NOTNULL(cmdline);
KERNAUX_NOTNULL(error_msg);
KERNAUX_ASSERT(argc);
KERNAUX_NOTNULL(argv);
KERNAUX_ASSERT(arg_count_max > 0);
KERNAUX_ASSERT(buffer_size > 0);
return kernaux_cmdline_common(
cmdline,
error_msg,
argc,
'\0', // arg_terminator
argv,
buffer,
NULL,
arg_count_max,
buffer_size
);
}
/*********************************
* Implementation: main function *
*********************************/
#define CLEAR do { \
*argc = 0; \
if (argv) memset(argv, 0, sizeof(char*) * arg_count_max); \
if (buffer) memset(buffer, '\0', buffer_size); \
if (arg_idxs) memset(arg_idxs, 0, sizeof(size_t) * arg_count_max); \
} 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,
size_t *const arg_idxs,
const size_t arg_count_max,
const size_t buffer_size
) {
KERNAUX_NOTNULL(cmdline);
KERNAUX_NOTNULL(error_msg);
KERNAUX_ASSERT(argc);
(void)arg_idxs;
memset(error_msg, '\0', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
CLEAR;
if (cmdline[0] == '\0') return true;
enum State state = INITIAL;
size_t buffer_or_file_pos = 0;
for (size_t index = 0; state != FINAL; ++index) {
const bool result = kernaux_cmdline_iter(
cmdline[index],
&state,
&buffer_or_file_pos,
error_msg,
argc,
arg_terminator,
argv,
buffer,
arg_idxs,
arg_count_max,
buffer_size
);
if (!result) goto fail;
}
return true;
fail:
CLEAR;
return false;
}
/**************************************
* Implementation: iteration function *
**************************************/
#define FAIL(msg) do { \
strcpy(error_msg, msg); \
return false; \
} while (0)
#define PUT_CHAR(char) do { \
if (buffer_size && *buffer_or_file_pos >= buffer_size) { \
FAIL("EOF or buffer overflow"); \
} \
if (buffer) { \
buffer[*buffer_or_file_pos] = char; \
} \
++(*buffer_or_file_pos); \
} while (0)
#define PUT_ARG do { \
if (arg_count_max && *argc >= arg_count_max) { \
FAIL("too many args"); \
} \
if (argv && buffer) { \
argv[*argc] = &buffer[*buffer_or_file_pos]; \
} \
if (arg_idxs) { \
arg_idxs[*argc] = *buffer_or_file_pos; \
} \
++(*argc); \
} while (0)
#define PUT_ARG_AND_CHAR(char) do { \
if (arg_count_max && *argc >= arg_count_max) { \
FAIL("too many args"); \
} \
if (buffer_size && *buffer_or_file_pos >= buffer_size) { \
FAIL("EOF or buffer overflow"); \
} \
if (argv && buffer) { \
argv[*argc] = &buffer[*buffer_or_file_pos]; \
buffer[*buffer_or_file_pos] = char; \
} \
if (arg_idxs) { \
arg_idxs[*argc] = *buffer_or_file_pos; \
} \
++(*argc); \
++(*buffer_or_file_pos); \
} while (0)
bool kernaux_cmdline_iter(
const char cur,
enum State *const state,
size_t *const buffer_or_file_pos,
char *const error_msg,
size_t *const argc,
char arg_terminator,
char **const argv,
char *const buffer,
size_t *const arg_idxs,
const size_t arg_count_max,
const size_t buffer_size
) {
switch (*state) {
case FINAL:
break;
case INITIAL:
if (cur == '\0') {
*state = FINAL;
} else if (cur == ' ') {
*state = WHITESPACE;
} else if (cur == '\\') {
*state = BACKSLASH;
PUT_ARG;
} else if (cur == '"') {
*state = QUOTE;
PUT_ARG;
} else {
*state = TOKEN;
PUT_ARG_AND_CHAR(cur);
}
break;
case WHITESPACE:
if (cur == '\0') {
*state = FINAL;
} else if (cur == ' ') {
// do nothing
} else if (cur == '\\') {
*state = BACKSLASH;
PUT_ARG;
} else if (cur == '"') {
*state = QUOTE;
PUT_ARG;
} else {
*state = TOKEN;
PUT_ARG_AND_CHAR(cur);
}
break;
case TOKEN:
if (cur == '\0') {
*state = FINAL;
PUT_CHAR(arg_terminator);
} else if (cur == ' ') {
*state = WHITESPACE;
PUT_CHAR(arg_terminator);
} else if (cur == '\\') {
*state = BACKSLASH;
} else if (cur == '"') {
FAIL("unescaped quotation mark");
} else {
PUT_CHAR(cur);
}
break;
case BACKSLASH:
if (cur == '\0') {
FAIL("EOL after backslash");
} else {
*state = TOKEN;
PUT_CHAR(cur);
}
break;
case QUOTE:
if (cur == '\0') {
FAIL("EOL inside quote");
} else if (cur == '\\') {
*state = QUOTE_BACKSLASH;
} else if (cur == '"') {
*state = WHITESPACE;
PUT_CHAR(arg_terminator);
} else {
PUT_CHAR(cur);
}
break;
case QUOTE_BACKSLASH:
if (cur == '\0') {
FAIL("EOL after backslash inside quote");
} else {
*state = QUOTE;
PUT_CHAR(cur);
}
break;
}
return true;
}

1
tests/.gitignore vendored
View file

@ -1,5 +1,4 @@
/test_arch_i386
/test_cmdline
/test_elf
/test_free_list
/test_mbr

View file

@ -16,20 +16,6 @@ test_arch_i386_SOURCES = \
test_arch_i386.c
endif
################
# test_cmdline #
################
if WITH_CMDLINE
TESTS += test_cmdline
test_cmdline_LDADD = $(top_builddir)/libkernaux.la
test_cmdline_SOURCES = \
main.c \
test_cmdline.c \
cmdline_test.h \
cmdline_test.c
endif
############
# test_elf #
############

View file

@ -1,71 +0,0 @@
#include "cmdline_test.h"
#include <kernaux/cmdline.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define ARG_COUNT_MAX 100
#define BUFFER_SIZE 4096
void test(
const char *const cmdline,
size_t arg_count_max,
size_t buffer_size,
const bool expected_result,
const char *const expected_error_msg,
size_t expected_argc,
const char *const *const expected_argv
) {
if (arg_count_max == 0) arg_count_max = ARG_COUNT_MAX;
if (buffer_size == 0) buffer_size = BUFFER_SIZE;
char *error_msg = malloc(KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
size_t argc = 1234;
char **const argv = malloc(sizeof(char*) * arg_count_max);
size_t *arg_idxs = malloc(sizeof(size_t) * arg_count_max);
char *const buffer = malloc(buffer_size);
assert(error_msg);
assert(argv);
assert(buffer);
{
memset(error_msg, 'x', KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX);
memset(argv, 0, sizeof(char*) * arg_count_max);
memset(arg_idxs, 0, sizeof(size_t) * arg_count_max);
memset(buffer, 'x', buffer_size);
assert(
kernaux_cmdline(
cmdline,
error_msg,
&argc,
argv,
buffer,
arg_count_max,
buffer_size
) == !!expected_result
);
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);
}
}
for (size_t index = argc; index < arg_count_max; ++index) {
assert(argv[index] == NULL);
}
}
free(error_msg);
free(argv);
free(arg_idxs);
free(buffer);
}

View file

@ -1,26 +0,0 @@
#ifndef KERNAUX_INCLUDED_TESTS_CMDLINE_TEST
#define KERNAUX_INCLUDED_TESTS_CMDLINE_TEST
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
void test(
const char *cmdline,
size_t arg_count_max,
size_t buffer_size,
bool expected_result,
const char *expected_error_msg,
size_t expected_argc,
const char *const *const expected_argv
);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,119 +0,0 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cmdline_test.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
static const char *const argv_spaceX3_X3[] = {" ", " ", " "};
static const char *const argv_backslashX3_X3[] = {"\\\\\\", "\\\\\\", "\\\\\\"};
static const char *const argv_quotmarkX3_X3[] = {"\"\"\"", "\"\"\"", "\"\"\""};
static const char *const argv_aX50[] = {
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
};
static const char *const argv_a_X1[] = { "a" };
static const char *const argv_a_X2[] = { "a", "a" };
static const char *const argv_a_X3[] = { "a", "a", "a" };
static const char *const argv_a_X4[] = { "a", "a", "a", "a" };
static const char *const argv_a_X5[] = { "a", "a", "a", "a", "a" };
static const char *const argv_a_X6[] = { "a", "a", "a", "a", "a", "a" };
void test_main()
{
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 3, 0, true, "", 3, argv_spaceX3_X3);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 3, 0, true, "", 3, argv_backslashX3_X3);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 3, 0, true, "", 3, argv_quotmarkX3_X3);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 0, 12, true, "", 3, argv_spaceX3_X3);
test("\\\\\\\\\\\\ \\\\\\\\\\\\ \\\\\\\\\\\\", 0, 12, true, "", 3, argv_backslashX3_X3);
test("\\\"\\\"\\\" \\\"\\\"\\\" \\\"\\\"\\\"", 0, 12, true, "", 3, argv_quotmarkX3_X3);
test("\\ \\ \\ \\ \\ \\ \\ \\ \\ ", 3, 12, true, "", 3, argv_spaceX3_X3);
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, "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);
test("\\ \\", 0, 0, false, "EOL after backslash", 0, NULL);
test("\\\\\\", 0, 0, false, "EOL after backslash", 0, NULL);
test("\\\"\\", 0, 0, false, "EOL after backslash", 0, NULL);
test("foo\\", 0, 0, false, "EOL after backslash", 0, NULL);
test("\"\\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\" \\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\"\\ \\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\"\\\\\\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\"\\\"\\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("\"foo\\", 0, 0, false, "EOL after backslash inside quote", 0, NULL);
test("foo\"", 0, 0, false, "unescaped quotation mark", 0, NULL);
test("foo\"bar", 0, 0, false, "unescaped quotation mark", 0, NULL);
test("\"", 0, 0, false, "EOL inside quote", 0, NULL);
test("\"foo", 0, 0, false, "EOL inside quote", 0, NULL);
test(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
0,
0,
true,
"",
1,
argv_aX50
);
test("a", 1, 0, true, "", 1, argv_a_X1);
test("a ", 1, 0, true, "", 1, argv_a_X1);
test("a a", 1, 0, false, "too many args", 0, NULL);
test("a a ", 1, 0, false, "too many args", 0, NULL);
test("a a", 2, 0, true, "", 2, argv_a_X2);
test("a a ", 2, 0, true, "", 2, argv_a_X2);
test("a a a", 2, 0, false, "too many args", 0, NULL);
test("a a a ", 2, 0, false, "too many args", 0, NULL);
test("a a a", 3, 0, true, "", 3, argv_a_X3);
test("a a a ", 3, 0, true, "", 3, argv_a_X3);
test("a a a a", 3, 0, false, "too many args", 0, NULL);
test("a a a a ", 3, 0, false, "too many args", 0, NULL);
test("a a a a", 4, 0, true, "", 4, argv_a_X4);
test("a a a a ", 4, 0, true, "", 4, argv_a_X4);
test("a a a a a", 4, 0, false, "too many args", 0, NULL);
test("a a a a a ", 4, 0, false, "too many args", 0, NULL);
test("a a a a a", 5, 0, true, "", 5, argv_a_X5);
test("a a a a a ", 5, 0, true, "", 5, argv_a_X5);
test("a a a a a a", 5, 0, false, "too many args", 0, NULL);
test("a a a a a a ", 5, 0, false, "too many args", 0, NULL);
test("a a a a a a", 6, 0, true, "", 6, argv_a_X6);
test("a a a a a a ", 6, 0, true, "", 6, argv_a_X6);
{
char *const buffer = malloc(4096);
memset(buffer, 'a', 4096 - 1);
buffer[4096 - 1] = '\0';
// 4095 of "a"
test(buffer, 256, 4096, true, "", 1, NULL);
free(buffer);
}
{
char *const buffer = malloc(4096 + 1);
memset(buffer, 'a', 4096);
buffer[4096] = '\0';
// 4096 of "a"
test(buffer, 256, 4096, false, "EOF or buffer overflow", 0, NULL);
free(buffer);
}
}