argsparse/argsparse.h
2026-04-30 15:57:21 +04:00

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_ */