1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
128
129
132
133
136
137
138
139
140
141
142
143
144
145
146
147
148
149
153
154
155
156
157
158
160
161
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
183
184
185
186
187
188
189
190
191
192
193
196
197
200
201
204
205
208
209
212
213
216
217
220
221
224
225
231
232
238
239
243
244
245
246
249
250
251
252
253
254
255
256
257
258
259
266
267
268
271
276
277
278
283
284
285
/* ... */
/* ... */
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define MAX_MODULE_VERSION_SIZE 128
static arg_hashtable_t* s_hashtable = NULL;
static char* s_module_name = NULL;
static int s_mod_ver_major = 0;
static int s_mod_ver_minor = 0;
static int s_mod_ver_patch = 0;
static char* s_mod_ver_tag = NULL;
static char* s_mod_ver = NULL;
void arg_set_module_name(const char* name) {
size_t slen;
xfree(s_module_name);
slen = strlen(name);
s_module_name = (char*)xmalloc(slen + 1);
memset(s_module_name, 0, slen + 1);
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s(s_module_name, slen + 1, name, slen);
#else
memcpy(s_module_name, name, slen);
#endif
}{ ... }
void arg_set_module_version(int major, int minor, int patch, const char* tag) {
size_t slen_tag, slen_ds;
arg_dstr_t ds;
s_mod_ver_major = major;
s_mod_ver_minor = minor;
s_mod_ver_patch = patch;
xfree(s_mod_ver_tag);
slen_tag = strlen(tag);
s_mod_ver_tag = (char*)xmalloc(slen_tag + 1);
memset(s_mod_ver_tag, 0, slen_tag + 1);
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s(s_mod_ver_tag, slen_tag + 1, tag, slen_tag);
#else
memcpy(s_mod_ver_tag, tag, slen_tag);
#endif
ds = arg_dstr_create();
arg_dstr_catf(ds, "%d.", s_mod_ver_major);
arg_dstr_catf(ds, "%d.", s_mod_ver_minor);
arg_dstr_catf(ds, "%d.", s_mod_ver_patch);
arg_dstr_cat(ds, s_mod_ver_tag);
xfree(s_mod_ver);
slen_ds = strlen(arg_dstr_cstr(ds));
s_mod_ver = (char*)xmalloc(slen_ds + 1);
memset(s_mod_ver, 0, slen_ds + 1);
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s(s_mod_ver, slen_ds + 1, arg_dstr_cstr(ds), slen_ds);
#else
memcpy(s_mod_ver, arg_dstr_cstr(ds), slen_ds);
#endif
arg_dstr_destroy(ds);
}{ ... }
static unsigned int hash_key(const void* key) {
const char* str = (const char*)key;
int c;
unsigned int hash = 5381;
while ((c = *str++) != 0)
hash = ((hash << 5) + hash) + (unsigned int)c;
return hash;
}{ ... }
static int equal_keys(const void* key1, const void* key2) {
char* k1 = (char*)key1;
char* k2 = (char*)key2;
return (0 == strcmp(k1, k2));
}{ ... }
void arg_cmd_init(void) {
s_hashtable = arg_hashtable_create(32, hash_key, equal_keys);
}{ ... }
void arg_cmd_uninit(void) {
arg_hashtable_destroy(s_hashtable, 1);
}{ ... }
void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description) {
arg_cmd_info_t* cmd_info;
size_t slen_name;
void* k;
assert(strlen(name) < ARG_CMD_NAME_LEN);
assert(strlen(description) < ARG_CMD_DESCRIPTION_LEN);
cmd_info = (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, name);
if (cmd_info) {
arg_hashtable_remove(s_hashtable, name);
cmd_info = NULL;
}{...}
cmd_info = (arg_cmd_info_t*)xmalloc(sizeof(arg_cmd_info_t));
memset(cmd_info, 0, sizeof(arg_cmd_info_t));
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s(cmd_info->name, ARG_CMD_NAME_LEN, name, strlen(name));
strncpy_s(cmd_info->description, ARG_CMD_DESCRIPTION_LEN, description, strlen(description));/* ... */
#else
memcpy(cmd_info->name, name, strlen(name));
memcpy(cmd_info->description, description, strlen(description));/* ... */
#endif
cmd_info->proc = proc;
slen_name = strlen(name);
k = xmalloc(slen_name + 1);
memset(k, 0, slen_name + 1);
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
strncpy_s((char*)k, slen_name + 1, name, slen_name);
#else
memcpy((char*)k, name, slen_name);
#endif
arg_hashtable_insert(s_hashtable, k, cmd_info);
}{ ... }
void arg_cmd_unregister(const char* name) {
arg_hashtable_remove(s_hashtable, name);
}{ ... }
int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res) {
arg_cmd_info_t* cmd_info = arg_cmd_info(name);
assert(cmd_info != NULL);
assert(cmd_info->proc != NULL);
return cmd_info->proc(argc, argv, res);
}{ ... }
arg_cmd_info_t* arg_cmd_info(const char* name) {
return (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, name);
}{ ... }
unsigned int arg_cmd_count(void) {
return arg_hashtable_count(s_hashtable);
}{ ... }
arg_cmd_itr_t arg_cmd_itr_create(void) {
return (arg_cmd_itr_t)arg_hashtable_itr_create(s_hashtable);
}{ ... }
int arg_cmd_itr_advance(arg_cmd_itr_t itr) {
return arg_hashtable_itr_advance((arg_hashtable_itr_t*)itr);
}{ ... }
char* arg_cmd_itr_key(arg_cmd_itr_t itr) {
return (char*)arg_hashtable_itr_key((arg_hashtable_itr_t*)itr);
}{ ... }
arg_cmd_info_t* arg_cmd_itr_value(arg_cmd_itr_t itr) {
return (arg_cmd_info_t*)arg_hashtable_itr_value((arg_hashtable_itr_t*)itr);
}{ ... }
void arg_cmd_itr_destroy(arg_cmd_itr_t itr) {
arg_hashtable_itr_destroy((arg_hashtable_itr_t*)itr);
}{ ... }
int arg_cmd_itr_search(arg_cmd_itr_t itr, void* k) {
return arg_hashtable_itr_search((arg_hashtable_itr_t*)itr, s_hashtable, k);
}{ ... }
static const char* module_name(void) {
if (s_module_name == NULL || strlen(s_module_name) == 0)
return "<name>";
return s_module_name;
}{ ... }
static const char* module_version(void) {
if (s_mod_ver == NULL || strlen(s_mod_ver) == 0)
return "0.0.0.0";
return s_mod_ver;
}{ ... }
void arg_make_get_help_msg(arg_dstr_t res) {
arg_dstr_catf(res, "%s v%s\n", module_name(), module_version());
arg_dstr_catf(res, "Please type '%s help' to get more information.\n", module_name());
}{ ... }
void arg_make_help_msg(arg_dstr_t ds, char* cmd_name, void** argtable) {
arg_cmd_info_t* cmd_info = (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, cmd_name);
if (cmd_info) {
arg_dstr_catf(ds, "%s: %s\n", cmd_name, cmd_info->description);
}{...}
arg_dstr_cat(ds, "Usage:\n");
arg_dstr_catf(ds, " %s", module_name());
arg_print_syntaxv_ds(ds, argtable, "\n \nAvailable options:\n");
arg_print_glossary_ds(ds, argtable, " %-23s %s\n");
arg_dstr_cat(ds, "\n");
}{ ... }
void arg_make_syntax_err_msg(arg_dstr_t ds, void** argtable, struct arg_end* end) {
arg_print_errors_ds(ds, end, module_name());
arg_dstr_cat(ds, "Usage: \n");
arg_dstr_catf(ds, " %s", module_name());
arg_print_syntaxv_ds(ds, argtable, "\n");
arg_dstr_cat(ds, "\n");
}{ ... }
int arg_make_syntax_err_help_msg(arg_dstr_t ds, char* name, int help, int nerrors, void** argtable, struct arg_end* end, int* exitcode) {
/* ... */
if (help > 0) {
arg_make_help_msg(ds, name, argtable);
*exitcode = EXIT_SUCCESS;
return 1;
}{...}
if (nerrors > 0) {
arg_make_syntax_err_msg(ds, argtable, end);
*exitcode = EXIT_FAILURE;
return 1;
}{...}
return 0;
}{ ... }