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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
87
88
89
90
95
96
101
102
103
104
105
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
156
157
158
159
160
161
177
178
179
180
181
182
183
184
185
204
205
206
207
208
209
210
211
212
213
214
215
220
221
222
223
224
225
226
227
228
229
230
252
253
254
257
258
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/* ... */
/* ... */
#include "argtable3.h"
#ifndef ARG_AMALGAMATION
#include "argtable3_private.h"
#endif
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
static void arg_int_resetfn(struct arg_int* parent) {
ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
parent->count = 0;
}{ ... }
static long int strtol0X(const char* str, const char** endptr, char X, int base) {
long int val;
int s = 1;
const char* ptr = str;
while (isspace((int)(*ptr)))
ptr++;
switch (*ptr) {
case '+':
ptr++;
s = 1;
break;...
case '-':
ptr++;
s = -1;
break;...
default:
s = 1;
break;...
}{...}
if ((*ptr++) != '0') {
*endptr = str;
return 0;
}{...}
if (toupper(*ptr++) != toupper(X)) {
*endptr = str;
return 0;
}{...}
val = strtol(ptr, (char**)endptr, base);
if (*endptr == ptr) {
*endptr = str;
return 0;
}{...}
return s * val;
}{ ... }
static int detectsuffix(const char* str, const char* suffix) {
while (toupper(*str) == toupper(*suffix)) {
if (*str == '\0')
return 1;
str++;
suffix++;
}{...}
if (*suffix != 0)
return 0;
while (isspace((int)(*str)))
str++;
return (*str == '\0') ? 1 : 0;
}{ ... }
static int arg_int_scanfn(struct arg_int* parent, const char* argval) {
int errorcode = 0;
if (parent->count == parent->hdr.maxcount) {
errorcode = ARG_ERR_MAXCOUNT;
}{...} else if (!argval) {
parent->count++;
}{...} else {
long int val;
const char* end;
val = strtol0X(argval, &end, 'X', 16);
if (end == argval) {
val = strtol0X(argval, &end, 'O', 8);
if (end == argval) {
val = strtol0X(argval, &end, 'B', 2);
if (end == argval) {
val = strtol(argval, (char**)&end, 10);
if (end == argval) {
return ARG_ERR_BADINT;
}{...}
}{...}
}{...}
}{...}
if (val > INT_MAX || val < INT_MIN)
errorcode = ARG_ERR_OVERFLOW;
if (detectsuffix(end, "KB"))
{
if (val > (INT_MAX / 1024) || val < (INT_MIN / 1024))
errorcode = ARG_ERR_OVERFLOW;
else
val *= 1024;
}{...} else if (detectsuffix(end, "MB"))
{
if (val > (INT_MAX / 1048576) || val < (INT_MIN / 1048576))
errorcode = ARG_ERR_OVERFLOW;
else
val *= 1048576;
}{...} else if (detectsuffix(end, "GB"))
{
if (val > (INT_MAX / 1073741824) || val < (INT_MIN / 1073741824))
errorcode = ARG_ERR_OVERFLOW;
else
val *= 1073741824;
}{...} else if (!detectsuffix(end, ""))
errorcode = ARG_ERR_BADINT;
if (errorcode == 0)
parent->ival[parent->count++] = (int)val;
}{...}
return errorcode;
}{ ... }
static int arg_int_checkfn(struct arg_int* parent) {
int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0;
return errorcode;
}{ ... }
static void arg_int_errorfn(struct arg_int* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) {
const char* shortopts = parent->hdr.shortopts;
const char* longopts = parent->hdr.longopts;
const char* datatype = parent->hdr.datatype;
argval = argval ? argval : "";
arg_dstr_catf(ds, "%s: ", progname);
switch (errorcode) {
case ARG_ERR_MINCOUNT:
arg_dstr_cat(ds, "missing option ");
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
...
case ARG_ERR_MAXCOUNT:
arg_dstr_cat(ds, "excess option ");
arg_print_option_ds(ds, shortopts, longopts, argval, "\n");
break;
...
case ARG_ERR_BADINT:
arg_dstr_catf(ds, "invalid argument \"%s\" to option ", argval);
arg_print_option_ds(ds, shortopts, longopts, datatype, "\n");
break;
...
case ARG_ERR_OVERFLOW:
arg_dstr_cat(ds, "integer overflow at option ");
arg_print_option_ds(ds, shortopts, longopts, datatype, " ");
arg_dstr_catf(ds, "(%s is too large)\n", argval);
break;...
}{...}
}{ ... }
struct arg_int* arg_int0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_intn(shortopts, longopts, datatype, 0, 1, glossary);
}{ ... }
struct arg_int* arg_int1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) {
return arg_intn(shortopts, longopts, datatype, 1, 1, glossary);
}{ ... }
struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) {
size_t nbytes;
struct arg_int* result;
maxcount = (maxcount < mincount) ? mincount : maxcount;
nbytes = sizeof(struct arg_int)
+ (size_t)maxcount * sizeof(int);
result = (struct arg_int*)xmalloc(nbytes);
result->hdr.flag = ARG_HASVALUE;
result->hdr.shortopts = shortopts;
result->hdr.longopts = longopts;
result->hdr.datatype = datatype ? datatype : "<int>";
result->hdr.glossary = glossary;
result->hdr.mincount = mincount;
result->hdr.maxcount = maxcount;
result->hdr.parent = result;
result->hdr.resetfn = (arg_resetfn*)arg_int_resetfn;
result->hdr.scanfn = (arg_scanfn*)arg_int_scanfn;
result->hdr.checkfn = (arg_checkfn*)arg_int_checkfn;
result->hdr.errorfn = (arg_errorfn*)arg_int_errorfn;
result->ival = (int*)(result + 1);
result->count = 0;
ARG_TRACE(("arg_intn() returns %p\n", result));
return result;
}{ ... }