gwion-util
utilities for the Gwion project
Loading...
Searching...
No Matches
Data Structures | Macros | Typedefs | Functions
cmdapp.h File Reference
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>

Go to the source code of this file.

Data Structures

struct  cmdopt_t
 
struct  cmdapp_info_t
 
struct  cmdargs_t
 
struct  cmdapp_t
 

Macros

#define EXIT_FAILURE   1
 
#define EXIT_SUCCESS   0
 
#define CMDOPT_EXISTS   0b00000001
 
#define CMDOPT_OPTIONAL   0b00000010
 
#define CMDOPT_TAKESARG   0b00000100
 
#define CMDOPT_MAYTAKEARG   0b00001000
 
#define CMDAPP_MODE_MULTIFLAG   0b00000000
 
#define CMDAPP_MODE_SHORTARG   0b00000001
 
#define CMDAPP_MODE_SILENT   0b00000000
 
#define CMDAPP_MODE_PRINT   0b00000010
 
#define _CMDAPP_MODE_EXIT   0b10000000
 
#define cmdopt_exists(opt)   ((opt).flags & CMDOPT_EXISTS)
 
#define cmdopt_is_optional(opt)   ((opt).flags | CMDOPT_OPTIONAL)
 
#define cmdapp_should_exit(app)   ((app)->_mode & _CMDAPP_MODE_EXIT)
 

Typedefs

typedef uint8_t cmdopt_flags_t
 
typedef uint8_t cmdapp_mode_t
 
typedef struct _cmdopt_internal_t cmdopt_internal_t
 
typedef void(* cmdapp_procedure_t) (void *data, cmdopt_t *option, const char *arg)
 

Functions

void cmdapp_init (cmdapp_t *app, int argc, char **argv, cmdapp_mode_t mode, const cmdapp_info_t *info)
 
void cmdapp_destroy (cmdapp_t *app)
 
void cmdapp_set (cmdapp_t *app, char shorto, const char *longo, uint8_t flags, cmdopt_t **conflicts, const char *description, const char *argtype, cmdopt_t *option)
 
void cmdapp_print_help (cmdapp_t *app)
 
void cmdapp_print_version (cmdapp_t *app)
 
void cmdapp_enable_procedure (cmdapp_t *app, cmdapp_procedure_t proc, void *user_data)
 
int cmdapp_run (cmdapp_t *app)
 
cmdargs_tcmdapp_getargs (cmdapp_t *app)
 
void cmdapp_error (cmdapp_t *app, const char *fmt,...)
 

Macro Definition Documentation

◆ _CMDAPP_MODE_EXIT

#define _CMDAPP_MODE_EXIT   0b10000000

Definition at line 53 of file cmdapp.h.

◆ CMDAPP_MODE_MULTIFLAG

#define CMDAPP_MODE_MULTIFLAG   0b00000000

Definition at line 49 of file cmdapp.h.

◆ CMDAPP_MODE_PRINT

#define CMDAPP_MODE_PRINT   0b00000010

Definition at line 52 of file cmdapp.h.

◆ CMDAPP_MODE_SHORTARG

#define CMDAPP_MODE_SHORTARG   0b00000001

Definition at line 50 of file cmdapp.h.

◆ CMDAPP_MODE_SILENT

#define CMDAPP_MODE_SILENT   0b00000000

Definition at line 51 of file cmdapp.h.

◆ cmdapp_should_exit

#define cmdapp_should_exit ( app)    ((app)->_mode & _CMDAPP_MODE_EXIT)

Definition at line 96 of file cmdapp.h.

◆ CMDOPT_EXISTS

#define CMDOPT_EXISTS   0b00000001

Definition at line 44 of file cmdapp.h.

◆ cmdopt_exists

#define cmdopt_exists ( opt)    ((opt).flags & CMDOPT_EXISTS)

Definition at line 56 of file cmdapp.h.

◆ cmdopt_is_optional

#define cmdopt_is_optional ( opt)    ((opt).flags | CMDOPT_OPTIONAL)

Definition at line 58 of file cmdapp.h.

◆ CMDOPT_MAYTAKEARG

#define CMDOPT_MAYTAKEARG   0b00001000

Definition at line 47 of file cmdapp.h.

◆ CMDOPT_OPTIONAL

#define CMDOPT_OPTIONAL   0b00000010

Definition at line 45 of file cmdapp.h.

◆ CMDOPT_TAKESARG

#define CMDOPT_TAKESARG   0b00000100

Definition at line 46 of file cmdapp.h.

◆ EXIT_FAILURE

#define EXIT_FAILURE   1

Definition at line 27 of file cmdapp.h.

◆ EXIT_SUCCESS

#define EXIT_SUCCESS   0

Definition at line 30 of file cmdapp.h.

Typedef Documentation

◆ cmdapp_mode_t

typedef uint8_t cmdapp_mode_t

Definition at line 34 of file cmdapp.h.

◆ cmdapp_procedure_t

typedef void(* cmdapp_procedure_t) (void *data, cmdopt_t *option, const char *arg)

Definition at line 78 of file cmdapp.h.

◆ cmdopt_flags_t

typedef uint8_t cmdopt_flags_t

Definition at line 33 of file cmdapp.h.

◆ cmdopt_internal_t

Definition at line 60 of file cmdapp.h.

Function Documentation

◆ cmdapp_destroy()

void cmdapp_destroy ( cmdapp_t * app)

Definition at line 59 of file cmdapp.c.

59 {
60 for (size_t i = 0; i < app->_length; i++) {
61 free(app->_start[i]);
62 }
63 free(app->_start);
64 free(app->_args.contents);
65 app->_args.contents = NULL;
66}
cmdargs_t _args
Definition cmdapp.h:90
size_t _length
Definition cmdapp.h:87
cmdopt_internal_t ** _start
Definition cmdapp.h:89
const char ** contents
Definition cmdapp.h:75

◆ cmdapp_enable_procedure()

void cmdapp_enable_procedure ( cmdapp_t * app,
cmdapp_procedure_t proc,
void * user_data )

Definition at line 111 of file cmdapp.c.

111 {
112 app->_proc = proc;
113 app->_user_data = user_data;
114}
void * _user_data
Definition cmdapp.h:92
cmdapp_procedure_t _proc
Definition cmdapp.h:91

◆ cmdapp_error()

void cmdapp_error ( cmdapp_t * app,
const char * fmt,
... )

Definition at line 364 of file cmdapp.c.

364 {
365 #ifdef _POSIX_VERSION
366 if (isatty(STDERR_FILENO) || (getenv("CMDAPP_COLOR_ALWAYS") != NULL)) {
367 fprintf(stderr, "%s: {R+}error:{0} ", app->_info.program);
368 } else {
369 fprintf(stderr, "%s: error: ", app->_info.program);
370 }
371 #else
372 fprintf(stderr, "%s: error: ", app->_info.program);
373 #endif /* _POSIX_VERSION */
374 va_list valist;
375 va_start(valist, fmt);
376 vfprintf(stderr, fmt, valist);
377 va_end(valist);
378}
char const char * fmt
Definition gwion_print.h:2
const char * program
Definition cmdapp.h:63
cmdapp_info_t _info
Definition cmdapp.h:84

◆ cmdapp_getargs()

cmdargs_t * cmdapp_getargs ( cmdapp_t * app)

Definition at line 352 of file cmdapp.c.

352 {
353 if (app->_args.contents == NULL) {
354 return NULL;
355 }
356 return &app->_args;
357}

◆ cmdapp_init()

void cmdapp_init ( cmdapp_t * app,
int argc,
char ** argv,
cmdapp_mode_t mode,
const cmdapp_info_t * info )

Definition at line 43 of file cmdapp.c.

44 {
45 app->_argc = argc;
46 app->_argv = argv;
47 app->_mode = mode;
48 app->_custom_help = 0;
49 app->_custom_ver = 0;
50 app->_length = 0;
51 app->_capacity = 4;
52 app->_start = malloc(sizeof(cmdarg_internal_t*) * app->_capacity);
53 app->_args.length = 0;
54 app->_args.contents = NULL;
55 app->_info = *info;
56 app->_proc = NULL;
57}
int _argc
Definition cmdapp.h:81
size_t _capacity
Definition cmdapp.h:88
int _custom_help
Definition cmdapp.h:85
char ** _argv
Definition cmdapp.h:82
int _custom_ver
Definition cmdapp.h:86
cmdapp_mode_t _mode
Definition cmdapp.h:83
size_t length
Definition cmdapp.h:74

◆ cmdapp_print_help()

void cmdapp_print_help ( cmdapp_t * app)

Definition at line 116 of file cmdapp.c.

116 {
117 if (app->_info.synopses && *app->_info.synopses) {
118 tcol_printf("{Y}Usage:{0} {+}%s{0} %s\n", app->_argv[0], *app->_info.synopses);
119 for (size_t i = 1; app->_info.synopses[i]; i++) {
120 printf(" or: {+}%s{0} %s\n", app->_argv[0], app->_info.synopses[i]);
121 }
122 } else {
123 tcol_printf("{Y}Usage:{0} {+}%s{0} {G}[OPTION]{-}...{0} {M}ARG {-}...{0}\n", app->_argv[0]);
124 }
125 printf("\n");
126 tcol_printf("{-}%s{0}\n", app->_info.description);
127 if (!app->_length)
128 return;
129 printf("\n");
130 tcol_printf("{Y}Options:{0}\n");
131 for (size_t i = 0; i < app->_length; i++) {
132 cmdarg_internal_t* arg_int = app->_start[i];
133 tcol_printf("%*s", app->_info.help_des_offset, "");
134 tcol_printf(arg_int->description);
135 tcol_printf("\r");
136 if(arg_int->result->shorto) {
137 tcol_printf(" {G}-%c{0}", arg_int->result->shorto);
138 } else {
139 tcol_printf(" {G}-{0}");
140 }
141 if (arg_int->result->longo) {
142 tcol_printf(", {G}--%s{0}", arg_int->result->longo);
143 }
144 if (arg_int->result->flags & CMDOPT_TAKESARG) {
145 tcol_printf("{M}=");
146 if (!arg_int->result->argtype)
147 tcol_printf("ARG");
148 else
149 tcol_printf(arg_int->result->argtype);
150 tcol_printf("{0}");
151 }
152 else if (arg_int->result->flags & CMDOPT_MAYTAKEARG) {
153 tcol_printf("{M}(=");
154 if (!arg_int->result->argtype)
155 tcol_printf("ARG");
156 else
157 tcol_printf(arg_int->result->argtype);
158 tcol_printf("){0}");
159 }
160 fputc('\n', stdout);
161 }
162 if (!app->_custom_help) {
163 tcol_printf("%*s%s\r {+G}--help{0}\n", app->_info.help_des_offset, "",
164 "Display this information");
165 }
166 if (!app->_custom_ver) {
167 tcol_printf("%*s%s\r {+G}--version{0}\n", app->_info.help_des_offset, "",
168 "Display program version information");
169 }
170}
#define CMDOPT_TAKESARG
Definition cmdapp.h:46
#define CMDOPT_MAYTAKEARG
Definition cmdapp.h:47
cmdopt_t * result
Definition cmdapp.c:28
const char * description
Definition cmdapp.c:31
int help_des_offset
Definition cmdapp.h:69
const char * description
Definition cmdapp.h:68
const char ** synopses
Definition cmdapp.h:64
cmdopt_flags_t flags
Definition cmdapp.h:41
const char * longo
Definition cmdapp.h:38
char shorto
Definition cmdapp.h:37
const char * argtype
Definition cmdapp.h:40
int tcol_printf(const char *fmt,...)
Definition termcolor.c:373

◆ cmdapp_print_version()

void cmdapp_print_version ( cmdapp_t * app)

Definition at line 172 of file cmdapp.c.

172 {
173 printf("%s %s\n", app->_info.program, app->_info.version);
174 printf("Copyright (C) %d %s\n", app->_info.year, app->_info.author);
175 printf("%s", app->_info.ver_extra);
176}
const char * ver_extra
Definition cmdapp.h:70
const char * version
Definition cmdapp.h:65
const char * author
Definition cmdapp.h:66

◆ cmdapp_run()

int cmdapp_run ( cmdapp_t * app)

Definition at line 222 of file cmdapp.c.

222 {
223 if (app->_args.contents != NULL) {
224 app->_args.contents = realloc(app->_args.contents, sizeof(char*) * 4);
225 app->_args.length = 0;
226 } else {
227 app->_args.contents = malloc(sizeof(char*) * 4);
228 }
229 size_t args_cap = 4;
230 #define APPEND_ARG(arg) if (app->_args.length + 1 > args_cap) { \
231 args_cap += (args_cap / 2); \
232 app->_args.contents = realloc(app->_args.contents, \
233 sizeof(char*) * args_cap); \
234 } \
235 if (app->_proc) { \
236 app->_proc(app->_user_data, NULL, arg); \
237 } \
238 app->_args.contents[app->_args.length++] = arg;
239
240 bool only_args = false;
241 for (int i = 0; i < app->_argc; i++) {
242 char* current = app->_argv[i];
243 if (only_args) {
244 APPEND_ARG(current);
245 continue;
246 }
247 const char* next = app->_argv[i + 1];
248 if (IS_END_OF_FLAGS(current)) {
249 only_args = true;
250 continue;
251 }
252 cmdarg_internal_t* arg_int;
253 if (IS_LONG_FLAG(current)) {
254 // Find the `=` for longopt args.
255 char* arg = strchr(current, '=');
256 // Move the pointer to the start of the longopt's args
257 if (arg) {
258 *arg = 0;
259 arg++;
260 }
261 if ((arg_int = cmdapp_search(app, 0, current + 2))) {
262 if (arg_int->result->flags & CMDOPT_TAKESARG) {
263 if (arg == NULL || *arg == 0) {
264 eprintf("%s expects an argument\n", current);
265 return EXIT_FAILURE;
266 }
267 arg_int->result->value = arg;
268 } else if (arg_int->result->flags & CMDOPT_MAYTAKEARG) {
269 arg_int->result->value = arg;
270 } else {
271 if (arg != NULL) {
272 eprintf("%s does not take arguments\n", current);
273 return EXIT_FAILURE;
274 }
275 }
276 } else {
277 if (strncmp(current, "--help", 7) == 0) {
279 app->_mode |= _CMDAPP_MODE_EXIT;
280 return EXIT_SUCCESS;
281 } else if (strncmp(current, "--version", 10) == 0) {
283 app->_mode |= _CMDAPP_MODE_EXIT;
284 return EXIT_SUCCESS;
285 }
286 eprintf("Unrecognized command line option %s, try --help\n", current);
287 return EXIT_FAILURE;
288 }
289 arg_int->result->flags |= CMDOPT_EXISTS;
290 if (app->_proc) {
291 app->_proc(app->_user_data, arg_int->result, NULL);
292 }
293 } else if (IS_SHORT_FLAG(current)) {
294 if (app->_mode & CMDAPP_MODE_SHORTARG) {
295 if ((arg_int = cmdapp_search(app, current[1], NULL))) {
296 arg_int->result->value = NULL;
297 if (arg_int->result->flags | CMDOPT_TAKESARG) {
298 arg_int->result->value = current + 2;
299 if (!current[2] && next && next[0] != '-') {
300 arg_int->result->value = next;
301 i++;
302 } else if (current[2] == 0) {
303 eprintf("-%c expects an argument\n", current[1]);
304 return EXIT_FAILURE;
305 }
306 } else if ((current[2] != 0) || (next && next[0] != '-')) {
307 eprintf("-%c does not take arguments\n", current[1]);
308 return EXIT_FAILURE;
309 }
310 } else {
311 eprintf("Unrecognized command line option -%c, try --help\n",
312 current[1]);
313 return EXIT_FAILURE;
314 }
315 arg_int->result->flags |= CMDOPT_EXISTS;
316 if (app->_proc) {
317 app->_proc(app->_user_data, arg_int->result, NULL);
318 }
319 } else /* app->_mode | CMDAPP_MODE_MULTIFLAG */ {
320 for (size_t j = 1; current[j]; j++) {
321 if ((arg_int = cmdapp_search(app, current[1], NULL))) {
322 arg_int->result->value = current + 2;
323 if (arg_int->result->value[2] == 0) {
324 if (next && next[0] != '-') {
325 arg_int->result->value = next;
326 i++;
327 } else {
328 eprintf("-%c expects an argument\n", current[1]);
329 return EXIT_FAILURE;
330 }
331 }
332 } else {
333 eprintf("Unrecognized command line option -%c\n",
334 current[1]);
335 return EXIT_FAILURE;
336 }
337 }
338 }
339 } else {
340 APPEND_ARG(current);
341 }
342 }
343 #undef APPEND_ARG
344
346 return EXIT_FAILURE;
347 }
348
349 return EXIT_SUCCESS;
350}
#define APPEND_ARG(arg)
static int cmdapp_resolve_options(cmdapp_t *app)
Definition cmdapp.c:200
void cmdapp_print_version(cmdapp_t *app)
Definition cmdapp.c:172
#define IS_LONG_FLAG(str)
Definition cmdapp.c:197
#define IS_END_OF_FLAGS(str)
Definition cmdapp.c:195
#define IS_SHORT_FLAG(str)
Definition cmdapp.c:198
void cmdapp_print_help(cmdapp_t *app)
Definition cmdapp.c:116
#define eprintf(fmt,...)
Definition cmdapp.c:23
static cmdarg_internal_t * cmdapp_search(cmdapp_t *app, char shorto, const char *longo)
Definition cmdapp.c:178
#define CMDOPT_EXISTS
Definition cmdapp.h:44
#define _CMDAPP_MODE_EXIT
Definition cmdapp.h:53
#define EXIT_SUCCESS
Definition cmdapp.h:30
#define EXIT_FAILURE
Definition cmdapp.h:27
#define CMDAPP_MODE_SHORTARG
Definition cmdapp.h:50
const char * value
Definition cmdapp.h:39
void void * arg
Definition threadpool.h:27

◆ cmdapp_set()

void cmdapp_set ( cmdapp_t * app,
char shorto,
const char * longo,
uint8_t flags,
cmdopt_t ** conflicts,
const char * description,
const char * argtype,
cmdopt_t * option )

Definition at line 77 of file cmdapp.c.

81{
82
83 if (strncmp(longo, "help", 5) == 0) {
84 app->_custom_help = 1;
85 } else if (strncmp(longo, "version", 8) == 0) {
86 app->_custom_ver = 1;
87 }
88
89 option->shorto = shorto;
90 option->longo = longo;
91 option->argtype = argtype;
92 option->flags = flags;
93 option->value = NULL;
94 const size_t conflict_count = (conflicts == NULL)
95 ? 1
96 : _argvlen((void**)conflicts) + 1;
97 const size_t size = sizeof(cmdarg_internal_t)
98 + conflict_count * sizeof(cmdopt_t*);
99 cmdarg_internal_t* arg_int = malloc(size);
100 arg_int->result = option;
101 arg_int->description = description;
102 if (conflicts == NULL) {
103 arg_int->conflicts[0] = NULL;
104 } else {
105 memcpy(arg_int->conflicts, conflicts, conflict_count
106 * sizeof(cmdopt_t*));
107 }
108 cmdapp_append(app, arg_int);
109}
static size_t _argvlen(void **argv)
Definition cmdapp.c:37
struct _cmdopt_internal_t cmdarg_internal_t
static void cmdapp_append(cmdapp_t *app, cmdarg_internal_t *arg_int)
Definition cmdapp.c:68
cmdopt_t * conflicts[]
Definition cmdapp.c:34