205 lines
6.8 KiB
C
205 lines
6.8 KiB
C
/*
|
|
* argsparse.h
|
|
*
|
|
* Copyright 2026
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*
|
|
*
|
|
*/
|
|
|
|
#if (!defined(__LIB_argsparse_H_))
|
|
#define __LIB_argsparse_H_
|
|
|
|
#define ArgsGetSimpleFlags() simple_flags
|
|
#define ArgsGetNamesVals() names_vals
|
|
#define ArgsGetNamesFlags() names_flags
|
|
#define ArgsGetDefault() default_arg
|
|
#define ArgsGetSimpleSize() simple_size
|
|
#define ArgsGetNamesSize() names_size
|
|
#define ArgsGetSimpleNumbers() options_numbers_simple
|
|
#define ArgsGetNamesNumbers() options_numbers_names
|
|
|
|
typedef struct {
|
|
char** simple_flags;
|
|
char** names_vals;
|
|
char** names_flags;
|
|
char* default_arg;
|
|
size_t* options_numbers_simple;
|
|
size_t* options_numbers_names;
|
|
size_t simple_size;
|
|
size_t names_size;
|
|
} __args_parse_t;
|
|
|
|
int _lib_argparse_emulated_main(__args_parse_t* arg_list_named);
|
|
|
|
__args_parse_t __sfdgssg_parse_result;
|
|
|
|
#define arg_property_t char*
|
|
|
|
/* Simulate array type */
|
|
#define args_config_t
|
|
#define args_config_size_t (size_t)
|
|
|
|
/* Macro for parsing the arguments of the main function */
|
|
#define __arglist(arg_list_named, conf, size) { \
|
|
__sfdgssg_parse_result.ArgsGetDefault() = NULL; \
|
|
__sfdgssg_parse_result.ArgsGetSimpleNumbers() = NULL; \
|
|
__sfdgssg_parse_result.ArgsGetNamesNumbers() = NULL; \
|
|
_lib_argsparse_main(__argc__, __argv__, (conf), (size)); \
|
|
int stat = _lib_argparse_emulated_main( \
|
|
&__sfdgssg_parse_result); \
|
|
size_t __flags = __conf_flags_size((conf), (size)); \
|
|
__free_string_array( \
|
|
__sfdgssg_parse_result.ArgsGetSimpleFlags(), \
|
|
__flags); \
|
|
__free_string_array( \
|
|
__sfdgssg_parse_result.ArgsGetNamesFlags(), \
|
|
(size) - __flags); \
|
|
__free_string_array( \
|
|
__sfdgssg_parse_result.ArgsGetNamesVals(), \
|
|
(size) - __flags); \
|
|
free(__sfdgssg_parse_result.ArgsGetDefault()); \
|
|
free(__sfdgssg_parse_result.ArgsGetSimpleNumbers()); \
|
|
free(__sfdgssg_parse_result.ArgsGetNamesNumbers()); \
|
|
return stat; \
|
|
} \
|
|
int _lib_argparse_emulated_main(__args_parse_t* arg_list_named)
|
|
|
|
/* Data type instead of argc and argv in the main function */
|
|
#define args_t int __argc__, char** __argv__) __arglist(
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
size_t __conf_flags_size(char** conf, size_t size) {
|
|
unsigned int d = 0;
|
|
size_t s = 0;
|
|
while (d < size) {
|
|
if (strchr(conf[d], '=') == NULL) {
|
|
s ++;
|
|
}
|
|
d ++;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
void __free_string_array(char** arr, size_t size) {
|
|
unsigned int d = 0;
|
|
while (d < size) {
|
|
free(arr[d]);
|
|
d ++;
|
|
}
|
|
free(arr);
|
|
}
|
|
|
|
static void* __sized_malloc(size_t size) {
|
|
void* ptr = malloc(size);
|
|
memset(ptr, ((int)(unsigned long)NULL), size);
|
|
return ptr;
|
|
}
|
|
|
|
static unsigned char __compile_and_equals_sflag(char* flags, char* str) {
|
|
if (strlen(str) > strlen(flags)) return 0;
|
|
size_t i = 0;
|
|
size_t slashes = 0;
|
|
while (i < strlen(flags)) {
|
|
if (flags[i] == '/') {
|
|
slashes ++;
|
|
}
|
|
i ++;
|
|
}
|
|
i = 0;
|
|
size_t f = 0;
|
|
while (f < (slashes + 1)) {
|
|
char st[32];
|
|
size_t d = i;
|
|
char* slt = &flags[i];
|
|
while (flags[d] != '/' && flags[d] != '=' && flags[d] != '\0') {
|
|
d ++;
|
|
}
|
|
strncpy(st, slt, d - i);
|
|
st[d - i] = '\0';
|
|
i = d + 1;
|
|
f ++;
|
|
if (strncmp(st, str, strlen(st)) == 0) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void* malloc_str(char* str) {
|
|
char* ptr = malloc((strlen(str)) * sizeof(char) + sizeof(char));
|
|
strcpy(ptr, str);
|
|
return ptr;
|
|
}
|
|
|
|
int _lib_argsparse_main(int argc, char** argv, char** config, size_t size) {
|
|
int i = 1;
|
|
size_t flags = __conf_flags_size(config, size);
|
|
__sfdgssg_parse_result.ArgsGetSimpleFlags() =
|
|
__sized_malloc((flags) * sizeof(char**));
|
|
__sfdgssg_parse_result.ArgsGetNamesFlags() =
|
|
__sized_malloc((size - flags) * sizeof(char**));
|
|
__sfdgssg_parse_result.ArgsGetNamesVals() =
|
|
__sized_malloc((size - flags) * sizeof(char**));
|
|
__sfdgssg_parse_result.ArgsGetNamesNumbers() =
|
|
__sized_malloc((size - flags) * sizeof(size_t));
|
|
__sfdgssg_parse_result.ArgsGetSimpleNumbers() =
|
|
__sized_malloc((flags) * sizeof(size_t));
|
|
__args_parse_t* out = &__sfdgssg_parse_result;
|
|
size_t simple_flags_count = 0;
|
|
size_t names_flags_count = 0;
|
|
unsigned char named_flag = 0;
|
|
while (i < argc) {
|
|
char* str = argv[i];
|
|
if (named_flag == 1) {
|
|
out->ArgsGetNamesVals()[names_flags_count] = malloc_str(str);
|
|
named_flag = 0;
|
|
names_flags_count ++;
|
|
i ++;
|
|
continue;
|
|
}
|
|
unsigned int d = 0;
|
|
while (d < size) {
|
|
if (__compile_and_equals_sflag(config[d], str)) {
|
|
if (strchr(config[d], '=') == NULL) {
|
|
out->ArgsGetSimpleFlags()[simple_flags_count] = malloc_str(str);
|
|
out->ArgsGetSimpleNumbers()[simple_flags_count] = d;
|
|
simple_flags_count ++;
|
|
} else {
|
|
out->ArgsGetNamesFlags()[names_flags_count] = malloc_str(str);
|
|
out->ArgsGetNamesNumbers()[names_flags_count] = d;
|
|
named_flag = 1;
|
|
}
|
|
} else {
|
|
free(out->ArgsGetDefault());
|
|
out->ArgsGetDefault() = malloc_str(str);
|
|
}
|
|
d ++;
|
|
}
|
|
i ++;
|
|
}
|
|
out->simple_size = simple_flags_count;
|
|
out->names_size = names_flags_count;
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
#endif /* __LIB_argsparse_H_ */
|
|
|