maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
marge.h
1
2#ifndef MARGE_H
3#define MARGE_H
4
5#include <merror.h>
6
7#ifdef MAUG_NO_CLI
8
9# define maug_add_arg( arg, arg_sz, help, help_sz, arg_cb, data ) (0)
10
11#else
12
18
19/*
20 * | ::MAUG_CLI_SIGIL | Specify the sigil prepended to command-line args. |
21 * | MAUG_NO_CLI_SZ | Disable ::MAUG_CLI_SZ command-line args. |
22 */
23
24#ifndef MAUG_CLI_SIGIL_SZ
25# define MAUG_CLI_SIGIL_SZ 1
26#endif /* !MAUG_CLI_SIGIL_SZ */
27
28#if !defined( MAUG_CLI_SIGIL ) && defined( MAUG_OS_WIN )
29# define MAUG_CLI_SIGIL "/"
30#elif !defined( MAUG_CLI_SIGIL ) && defined( MAUG_OS_DOS )
31# define MAUG_CLI_SIGIL "/"
32#elif !defined( MAUG_CLI_SIGIL ) && defined( MAUG_OS_DOS_REAL )
33# define MAUG_CLI_SIGIL "/"
34#elif !defined( MAUG_CLI_SIGIL )
39# define MAUG_CLI_SIGIL "-"
40#endif /* !MAUG_CLI_SIGIL */
41
42#define MAUG_CLI_ARG_C_DEFAULT -1
43
44#ifndef MAUG_CLI_ARG_HELP_SZ_MAX
45# define MAUG_CLI_ARG_HELP_SZ_MAX 127
46#endif /* !MAUG_CLI_ARG_HELP_SZ_MAX */
47
48#ifndef MAUG_CLI_ARG_SZ_MAX
49# define MAUG_CLI_ARG_SZ_MAX 20
50#endif /* !MAUG_CLI_ARG_SZ_MAX */
51
52#ifndef MAUG_CLI_TRACE_LVL
53# define MAUG_CLI_TRACE_LVL 0
54#endif /* !MAUG_CLI_TRACE_LVL */
55
56typedef
57MERROR_RETVAL (*maug_cli_cb)( const char* arg, ssize_t arg_c, void* data );
58
59struct MARGE_ARG {
60 char arg[MAUG_CLI_ARG_SZ_MAX];
61 size_t arg_sz;
62 char help[MAUG_CLI_ARG_HELP_SZ_MAX];
63 maug_cli_cb callback;
64 void* data;
65 uint8_t called;
66};
67
68MERROR_RETVAL maug_cli_h( const char* arg, ssize_t arg_c, void* args );
69
70int maug_parse_args( int argc, char* argv[] );
71
81 const char* arg, int arg_sz, const char* help, int help_sz,
82 maug_cli_cb arg_cb, void* data );
83
84#ifdef MARGE_C
85
86/* == Global Tables == */
87
88struct MDATA_VECTOR g_marge_args;
89
90/* == Function Definitions = = */
91
92MERROR_RETVAL maug_cli_h( const char* arg, ssize_t arg_c, void* args ) {
93 size_t i = 0;
94 struct MARGE_ARG* arg_p = NULL;
95
96 if( 0 > arg_c ) {
97 /* Just pass by on default case. */
98 return 0;
99 }
100
101 error_printf( "usage:" );
102 error_printf( "---" );
103
104 /* Display help for all available options. */
105 for( i = 0 ; mdata_vector_ct( &g_marge_args ) > i ; i++ ) {
106 arg_p = mdata_vector_get( &g_marge_args, i, struct MARGE_ARG );
107 error_printf( "\t%s\t%s", arg_p->arg, arg_p->help );
108 }
109
110 error_printf( "---" );
111
112 /* Return an error so we quit. */
113 return MERROR_GUI;
114}
115
116/* === */
117
118MERROR_RETVAL maug_parse_args( int argc, char* argv[] ) {
119 MERROR_RETVAL retval = MERROR_OK;
120 int arg_i = 0,
121 const_i = 0,
122 last_i = 0;
123 struct MARGE_ARG* arg = NULL;
124
125 debug_printf( MAUG_CLI_TRACE_LVL, "parsing %d args...", argc );
126
127 mdata_vector_lock( &g_marge_args );
128 for( arg_i = 1 ; argc > arg_i ; arg_i++ ) {
129 debug_printf( MAUG_CLI_TRACE_LVL, "found CLI: %s", argv[arg_i] );
130
131 /* Hunt through the list of available args to see if the current argv
132 * index matches.
133 */
134 const_i = 0;
135 for(
136 const_i = 0 ; mdata_vector_ct( &g_marge_args ) > const_i ; const_i++
137 ) {
138 arg = mdata_vector_get( &g_marge_args, const_i, struct MARGE_ARG );
139
140 if( 0 == strncmp( arg->arg, argv[arg_i], arg->arg_sz ) ) {
141 debug_printf( MAUG_CLI_TRACE_LVL, "arg matched: %s", arg->arg );
142
143 /* Save this matched index for the next pass. */
144 last_i = const_i;
145
146 /* Increment called count and run the callback. */
147 arg->called++;
148 retval = arg->callback( argv[arg_i], arg->called, arg->data );
149 if( MERROR_OK != retval ) {
150 error_printf( "error calling arg!" );
151 goto cleanup;
152 }
153
154 /* We found a match, so go to the next arg. */
155 debug_printf(
156 MAUG_CLI_TRACE_LVL, "arg parsed, moving on to next..." );
157 break;
158 } else {
159 debug_printf( MAUG_CLI_TRACE_LVL, "arg NOT matched: %s", arg->arg );
160 }
161 }
162
163 /* No valid arg was found, so we must be passing data to the last one!
164 */
165 arg = mdata_vector_get( &g_marge_args, last_i, struct MARGE_ARG );
166 if( NULL != arg ) {
167 debug_printf(
168 MAUG_CLI_TRACE_LVL, "passing data to previous arg..." );
169 arg->called++;
170 retval = arg->callback( argv[arg_i], arg->called, arg->data );
171 if( MERROR_OK != retval ) {
172 error_printf( "error calling arg!" );
173 goto cleanup;
174 }
175 }
176 }
177
178 debug_printf( MAUG_CLI_TRACE_LVL, "calling defaults for uncalled args..." );
179
180 /* Run default callbacks for any args not called. */
181 const_i = 0;
182 for( const_i = 0 ; mdata_vector_ct( &g_marge_args ) > const_i ; const_i++ ) {
183 arg = mdata_vector_get( &g_marge_args, const_i, struct MARGE_ARG );
184
185 debug_printf( MAUG_CLI_TRACE_LVL,
186 "checking arg %d: %s (" SIZE_T_FMT "): callback: %p",
187 const_i, arg->arg, arg->arg_sz, arg->callback );
188 if( NULL == arg->callback ) {
189 debug_printf(
190 MAUG_CLI_TRACE_LVL, "arg %d callback is NULL!", const_i );
191 continue;
192 }
193 if( 0 != arg->called ) {
194 debug_printf(
195 MAUG_CLI_TRACE_LVL, "arg %d was called; NOT calling default...",
196 const_i );
197 continue;
198 }
199 debug_printf( MAUG_CLI_TRACE_LVL,
200 "calling default arg for uncalled \"%s\"...", arg->arg );
201 retval = arg->callback( "", MAUG_CLI_ARG_C_DEFAULT, arg->data );
202 if( MERROR_OK != retval ) {
203 error_printf( "error calling arg default!" );
204 goto cleanup;
205 }
206 }
207
208cleanup:
209
210 mdata_vector_unlock( &g_marge_args );
211
212 return retval;
213}
214
215/* === */
216
218 const char* arg, int arg_sz, const char* help, int help_sz,
219 maug_cli_cb arg_cb, void* data
220) {
221 MERROR_RETVAL retval = MERROR_OK;
222 ssize_t idx = 0;
223 struct MARGE_ARG new_arg;
224
225 /* TODO: Check for duplicate arg. */
226
227 debug_printf( MAUG_CLI_TRACE_LVL, "adding arg: \"%s\"", arg );
228
229 maug_strncpy( new_arg.arg, arg, MAUG_CLI_ARG_SZ_MAX );
230 maug_strncpy( new_arg.help, help, MAUG_CLI_ARG_HELP_SZ_MAX );
231 new_arg.arg_sz = arg_sz;
232 new_arg.callback = arg_cb;
233 new_arg.called = 0;
234 new_arg.data = data;
235
236 idx = mdata_vector_append(
237 &g_marge_args, &new_arg, sizeof( struct MARGE_ARG ) );
238
239 if( 0 > idx ) {
240 retval = mdata_retval( idx );
241 }
242
243 return retval;
244}
245
246#endif /* MARGE_C */
247 /* maug_cli */
249
250#endif /* MAUG_NO_CLI */
251
252#endif /* MARGE_H */
253
MERROR_RETVAL maug_add_arg(const char *arg, int arg_sz, const char *help, int help_sz, maug_cli_cb arg_cb, void *data)
Add a command-line argument to the built-in parser.
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
Definition marge.h:59
A vector of uniformly-sized objects, stored contiguously.
Definition mdata.h:85