35 #include <ndb_global.h>
38 #include <basestring_vsnprintf.h>
42 strlcpy (
char *dst,
const char *src,
size_t dst_sz)
47 n + 1 < dst_sz && *src !=
'\0';
54 return n + strlen (src);
59 strlcat (
char *dst,
const char *src,
size_t dst_sz)
61 size_t len = strlen(dst);
62 return len + strlcpy (dst + len, src, dst_sz - len);
66 #define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag)
69 #define max(a, b) (a) > (b) ? (a) : (b)
72 #ifdef HAVE___PROGNAME
73 extern char *__progname;
95 print_arg (
char *
string,
size_t len,
int mdoc,
int longp,
struct getargs *arg)
101 if (ISFLAG(*arg) || (!longp && arg->type == arg_counter))
106 strlcat(
string,
"= Ns", len);
107 strlcat(
string,
" Ar ", len);
110 strlcat (
string,
"=", len);
112 strlcat (
string,
" ", len);
116 else if (arg->type == arg_integer || arg->type == arg_counter)
118 else if (arg->type == arg_string)
120 else if (arg->type == arg_double)
125 strlcat(
string, s, len);
126 return 1 + strlen(s);
131 mandoc_template(
struct getargs *args,
133 const char *progname,
134 const char *extra_string)
137 char timestr[64], cmd[64];
142 printf(
".\\\" Things to fix:\n");
143 printf(
".\\\" * correct section, and operating system\n");
144 printf(
".\\\" * remove Op from mandatory flags\n");
145 printf(
".\\\" * use better macros for arguments (like .Pa for files)\n");
148 strftime(timestr,
sizeof(timestr),
"%B %e, %Y", localtime(&t));
149 printf(
".Dd %s\n", timestr);
150 p = strrchr(progname,
'/');
151 if(p) p++;
else p = progname;
152 strlcpy(cmd, p,
sizeof(cmd));
155 printf(
".Dt %s SECTION\n", cmd);
156 printf(
".Os OPERATING_SYSTEM\n");
157 printf(
".Sh NAME\n");
158 printf(
".Nm %s\n", p);
160 printf(
"in search of a description\n");
161 printf(
".Sh SYNOPSIS\n");
163 for(i = 0; i < num_args; i++){
166 if(ISFLAG(args[i]) ||
167 args[i].short_name == 0 || args[i].long_name == NULL) {
170 if(args[i].short_name) {
171 print_arg(buf,
sizeof(buf), 1, 0, args + i);
172 printf(
"Fl %c%s", args[i].short_name, buf);
173 if(args[i].long_name)
176 if(args[i].long_name) {
177 print_arg(buf,
sizeof(buf), 1, 1, args + i);
179 args[i].
type == arg_negative_flag ?
"no-" :
"",
180 args[i].long_name, buf);
184 print_arg(buf,
sizeof(buf), 1, 0, args + i);
185 printf(
".Oo Fl %c%s \\*(Ba Xo\n", args[i].short_name, buf);
186 print_arg(buf,
sizeof(buf), 1, 1, args + i);
187 printf(
".Fl -%s%s Oc\n.Xc\n", args[i].long_name, buf);
194 if (extra_string && *extra_string)
195 printf (
".Ar %s\n", extra_string);
196 printf(
".Sh DESCRIPTION\n");
197 printf(
"Supported options:\n");
198 printf(
".Bl -tag -width Ds\n");
199 for(i = 0; i < num_args; i++){
201 if(args[i].short_name){
202 printf(
".Fl %c", args[i].short_name);
203 print_arg(buf,
sizeof(buf), 1, 0, args + i);
205 if(args[i].long_name)
209 if(args[i].long_name){
211 args[i].
type == arg_negative_flag ?
"no-" :
"",
213 print_arg(buf,
sizeof(buf), 1, 1, args + i);
218 printf(
"%s\n", args[i].help);
225 printf(
".\\\".Sh ENVIRONMENT\n");
226 printf(
".\\\".Sh FILES\n");
227 printf(
".\\\".Sh EXAMPLES\n");
228 printf(
".\\\".Sh DIAGNOSTICS\n");
229 printf(
".\\\".Sh SEE ALSO\n");
230 printf(
".\\\".Sh STANDARDS\n");
231 printf(
".\\\".Sh HISTORY\n");
232 printf(
".\\\".Sh AUTHORS\n");
233 printf(
".\\\".Sh BUGS\n");
238 check_column(FILE *f,
int col,
int len,
int columns)
240 if(col + len > columns) {
242 col = fprintf(f,
" ");
248 arg_printusage (
struct getargs *args,
250 const char *progname,
251 const char *extra_string)
256 int col = 0, columns;
258 #ifdef HAVE___PROGNAME
259 if (progname == NULL)
260 progname = __progname;
262 if (progname == NULL)
266 if(getenv(
"GETARGMANDOC")){
267 mandoc_template(args, num_args, progname, extra_string);
274 col += fprintf (stderr,
"Usage: %s", progname);
275 for (i = 0; i < num_args; ++
i) {
278 if (args[i].long_name) {
280 strlcat(buf,
"[--",
sizeof(buf));
282 if(args[i].
type == arg_negative_flag) {
283 strlcat(buf,
"no-",
sizeof(buf));
286 strlcat(buf, args[i].long_name,
sizeof(buf));
287 len += strlen(args[i].long_name);
288 len += print_arg(buf + strlen(buf),
sizeof(buf) - strlen(buf),
290 strlcat(buf,
"]",
sizeof(buf));
291 if(args[i].
type == arg_strings)
292 strlcat(buf,
"...",
sizeof(buf));
293 col = check_column(stderr, col, strlen(buf) + 1, columns);
294 col += fprintf(stderr,
" %s", buf);
296 if (args[i].short_name) {
297 basestring_snprintf(buf,
sizeof(buf),
"[-%c", args[i].short_name);
299 len += print_arg(buf + strlen(buf),
sizeof(buf) - strlen(buf),
301 strlcat(buf,
"]",
sizeof(buf));
302 if(args[i].
type == arg_strings)
303 strlcat(buf,
"...",
sizeof(buf));
304 col = check_column(stderr, col, strlen(buf) + 1, columns);
305 col += fprintf(stderr,
" %s", buf);
307 if (args[i].long_name && args[i].short_name)
309 max_len = max(max_len, len);
312 col = check_column(stderr, col, strlen(extra_string) + 1, columns);
313 fprintf (stderr,
" %s\n", extra_string);
315 fprintf (stderr,
"\n");
316 for (i = 0; i < num_args; ++
i) {
320 if (args[i].short_name) {
321 count += fprintf (stderr,
"-%c", args[i].short_name);
322 print_arg (buf,
sizeof(buf), 0, 0, &args[i]);
323 count += fprintf(stderr,
"%s", buf);
325 if (args[i].short_name && args[i].long_name)
326 count += fprintf (stderr,
", ");
327 if (args[i].long_name) {
328 count += fprintf (stderr,
"--");
329 if (args[i].
type == arg_negative_flag)
330 count += fprintf (stderr,
"no-");
331 count += fprintf (stderr,
"%s", args[i].long_name);
332 print_arg (buf,
sizeof(buf), 0, 1, &args[i]);
333 count += fprintf(stderr,
"%s", buf);
335 while(count++ <= max_len)
337 fprintf (stderr,
"%s\n", args[i].help);
345 s->strings = realloc(s->strings, (s->num_strings + 1) *
sizeof(*s->strings));
346 s->strings[s->num_strings] = value;
351 arg_match_long(
struct getargs *args,
size_t num_args,
352 char *argv,
int argc,
const char **rargv,
int *optind)
355 const char *optarg = NULL;
357 int partial_match = 0;
358 struct getargs *partial = NULL;
359 struct getargs *current = NULL;
363 argv_len = strlen(argv);
364 p = strchr (argv,
'=');
368 for (i = 0; i < num_args; ++
i) {
369 if(args[i].long_name) {
370 int len = strlen(args[i].long_name);
372 int p_len = argv_len;
376 if (strncmp (args[i].long_name, p, p_len) == 0) {
384 }
else if (ISFLAG(args[i]) && strncmp (p,
"no-", 3) == 0) {
396 if (current == NULL) {
397 if (partial_match == 1)
400 return ARG_ERR_NO_MATCH;
405 && current->type != arg_collect
406 && current->type != arg_counter)
407 return ARG_ERR_NO_MATCH;
408 switch(current->type){
412 if(sscanf(optarg + 1,
"%d", &tmp) != 1)
413 return ARG_ERR_BAD_ARG;
414 *(
int*)current->value = tmp;
419 *(
char**)current->value = (
char*)optarg + 1;
428 case arg_negative_flag:
430 int *flag = current->value;
431 if(*optarg ==
'\0' ||
432 strcmp(optarg + 1,
"yes") == 0 ||
433 strcmp(optarg + 1,
"true") == 0){
436 }
else if (*optarg && strcmp(optarg + 1,
"maybe") == 0) {
442 return ARG_ERR_BAD_ARG;
453 val = strtol (optarg, &endstr, 0);
454 if (endstr == optarg)
455 return ARG_ERR_BAD_ARG;
457 *(
int *)current->value += val;
463 if(sscanf(optarg + 1,
"%lf", &tmp) != 1)
464 return ARG_ERR_BAD_ARG;
465 *(
double*)current->value = tmp;
470 int o = argv - rargv[*optind];
471 return (*c->func)(FALSE, argc, rargv, optind, &o, c->data);
476 return ARG_ERR_BAD_ARG;
481 arg_match_short (
struct getargs *args,
size_t num_args,
482 char *argv,
int argc,
const char **rargv,
int *optind)
486 for(j = 1; j > 0 && j < (int)strlen(rargv[*optind]); j++) {
487 for(k = 0; k < (int)num_args; k++) {
490 if(args[k].short_name == 0)
492 if(argv[j] == args[k].short_name) {
493 if(args[k].
type == arg_flag) {
494 *(
int*)args[k].value = 1;
497 if(args[k].
type == arg_negative_flag) {
498 *(
int*)args[k].value = 0;
501 if(args[k].
type == arg_counter) {
502 ++*(
int *)args[k].value;
505 if(args[k].
type == arg_collect) {
508 if((*c->func)(TRUE, argc, rargv, optind, &j, c->data))
509 return ARG_ERR_BAD_ARG;
514 optarg = &argv[j + 1];
517 optarg = (
char *) rargv[*optind];
521 return ARG_ERR_NO_ARG;
523 if(args[k].
type == arg_integer) {
525 if(sscanf(optarg,
"%d", &tmp) != 1)
526 return ARG_ERR_BAD_ARG;
527 *(
int*)args[k].value = tmp;
529 }
else if(args[k].
type == arg_string) {
530 *(
char**)args[k].value = optarg;
532 }
else if(args[k].
type == arg_strings) {
535 }
else if(args[k].
type == arg_double) {
537 if(sscanf(optarg,
"%lf", &tmp) != 1)
538 return ARG_ERR_BAD_ARG;
539 *(
double*)args[k].value = tmp;
542 return ARG_ERR_BAD_ARG;
545 if (k == (
int)num_args)
546 return ARG_ERR_NO_MATCH;
552 getarg(
struct getargs *args,
size_t num_args,
553 int argc,
const char **argv,
int *optind)
558 srand ((
unsigned int)time(NULL));
560 for(i = *optind; i < argc; i++) {
561 if(argv[i][0] !=
'-')
563 if(argv[i][1] ==
'-'){
568 ret = arg_match_long (args, num_args, (
char *) argv[i] + 2,
571 ret = arg_match_short (args, num_args, (
char *) argv[i],
590 { NULL,
'1', arg_flag, &flag1,
"one", NULL },
591 { NULL,
'2', arg_flag, &flag2,
"two", NULL },
592 {
"foo",
'f', arg_negative_flag, &foo_flag,
"foo", NULL },
593 {
"bar",
'b', arg_integer, &bar_int,
"bar",
"seconds"},
594 {
"baz",
'x', arg_string, &baz_string,
"baz",
"name" },
597 int main(
int argc,
char **argv)
600 while(getarg(args, 5, argc, argv, &optind))
601 printf(
"Bad arg: %s\n", argv[optind]);
602 printf(
"flag1 = %d\n", flag1);
603 printf(
"flag2 = %d\n", flag2);
604 printf(
"foo_flag = %d\n", foo_flag);
605 printf(
"bar_int = %d\n", bar_int);
606 printf(
"baz_flag = %s\n", baz_string);
607 arg_printusage (args, 5, argv[0],
"nothing here");