diff --git a/args.c b/args.c new file mode 100644 index 0000000..35d0005 --- /dev/null +++ b/args.c @@ -0,0 +1,26 @@ + +#include "args.h" + +const pargs_t* parsed_args = NULL; +static const pargs_t default_args[1] = { A_DEFAULT_ARGS }; //A_DEFAULT_ARGS_P; + +const pargs_t* a_get_program_args() { + return parsed_args ?: default_args; +} + +bool a_is_parsed() { return parsed_args != NULL; } + +enum arg_parse_result a_parse_into(pargs_t *restrict parsed, int *restrict argc, char** *restrict p_argv, char** *restrict p_envp) +{ + //TODO + return A_PF_UNKNOWN; +} + +enum arg_parse_result a_parse(int *restrict argc, char** *restrict p_argv, char** *restrict p_envp) +{ + _Thread_local static pargs_t glob_parsed_args; + enum arg_parse_result r = a_parse_into(&glob_parsed_args, argc, p_argv, p_envp); + + if(!r) parsed_args = &glob_parsed_args; // A_P_OK + return r; +} diff --git a/args.h b/args.h new file mode 100644 index 0000000..f09d4be --- /dev/null +++ b/args.h @@ -0,0 +1,68 @@ +#ifndef _ARGS_H +#define _ARGS_H +#define _a_inline_proto __attribute__((__gnu_inline__, __always_inline__)) extern inline + +#include +#include +#include + +enum arg_parse_result { + A_PF_UNKNOWN = -1, + A_P_OK = 0, + + // TODO: specific errors... +}; + +typedef struct { + struct { + bool in,out,err; + } replace; // { 1, 1, 0 } + + const char* target; // NULL -> default "/dev/null" + + struct { + /*struct _Alignas(uint64_t) { + int64_t n : 63; + bool all : 1; + } __attribute__((packed, aligned(uint64_t)));*/ + size_t n; + + int fds[]; + }* restrict fd_pass; // A_FD_PASS_NONE + +} pargs_t; + +#define A_FD_PASS_ALL ((void*)(~((uintptr_t)0ul))) +#define A_FD_PASS_NONE NULL + +#define A_DEFAULT_ARGS ((pargs_t){ { true, true, false}, NULL, A_FD_PASS_NONE }) +#define A_DEFAULT_ARGS_P ((pargs_t[1]) { A_DEFAULT_ARGS } ) + +extern const pargs_t* parsed_args; + +/// Return parsed args or default args if no parsed args have been set. +_a_inline_proto const pargs_t* a_get_program_args() +{ + __attribute__((section(".text#"))) // Does this give any actual benefit? + static const pargs_t default_args = A_DEFAULT_ARGS; + + return parsed_args ?: &default_args;//A_DEFAULT_ARGS_P; +} + +/// Have the program's arguments been parsed? +_a_inline_proto bool a_is_parsed() +{ return parsed_args != NULL; } + +enum arg_parse_result a_parse_into(pargs_t *restrict parsed, int *restrict argc, char** *restrict p_argv, char** *restrict p_envp); + +_a_inline_proto // TODO: XXX: Is this worth it? +enum arg_parse_result a_parse(int *restrict argc, char** *restrict p_argv, char** *restrict p_envp) +{ + static pargs_t glob_parsed_args; //XXX: Wth is this an error? + enum arg_parse_result r = a_parse_into(&glob_parsed_args, argc, p_argv, p_envp); + + if(!r) parsed_args = &glob_parsed_args; // A_P_OK + return r; +} +#undef _a_inline_proto +#endif /* _ARGS_H */ diff --git a/sink.c b/sink.c index 962ee7b..2296367 100644 --- a/sink.c +++ b/sink.c @@ -8,6 +8,8 @@ #include "comp_features.h" +#include "args.h" + __attribute__((used)) // For loading debug binary symbol const enum compiled_features sink_compiled_features = FEATURE_FLAGS; @@ -206,8 +208,15 @@ static void print_debug_info(int argc, char* const* argv, char* const* envp) #define print_debug_info(a,b,c) ((void)((void)(a), (void)(b), (void)(c))) #endif +static bool parse_args(int *restrict argc, char** *restrict argv, char** *restrict envp) +{ + return a_parse(argc, argv, envp) == A_P_OK || true; //TODO: Print proper error messages on failures. +} + int main(int argc, char** argv, char** envp) { + if(!parse_args(&argc, &argv, &envp)) return 1; + #if FEATURE_HAS_FLAG(NO_ENV) (void)envp; #define GET_ENV ((char*[]){NULL})