Branch
Hash :
a0d14d15
Author :
Date :
2011-07-06T16:47:25
1 2 3 4 5 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
#include <ccan/opt/opt.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "private.h"
/* We only use this for pointer comparisons. */
const char opt_hidden[1];
static unsigned write_short_options(char *str)
{
unsigned int i, num = 0;
const char *p;
for (p = first_sopt(&i); p; p = next_sopt(p, &i)) {
if (opt_table[i].desc != opt_hidden)
str[num++] = *p;
}
return num;
}
#define OPT_SPACE_PAD " "
/* FIXME: Get all purdy. */
char *opt_usage(const char *argv0, const char *extra)
{
unsigned int i, num, len;
char *ret, *p;
if (!extra) {
extra = "";
for (i = 0; i < opt_count; i++) {
if (opt_table[i].cb == (void *)opt_usage_and_exit
&& opt_table[i].u.carg) {
extra = opt_table[i].u.carg;
break;
}
}
}
/* An overestimate of our length. */
len = strlen("Usage: %s ") + strlen(argv0)
+ strlen("[-%.*s]") + opt_num_short + 1
+ strlen(" ") + strlen(extra)
+ strlen("\n");
for (i = 0; i < opt_count; i++) {
if (opt_table[i].type == OPT_SUBTABLE) {
len += strlen("\n") + strlen(opt_table[i].desc)
+ strlen(":\n");
} else if (opt_table[i].desc != opt_hidden) {
len += strlen(opt_table[i].names) + strlen(" <arg>");
len += strlen(OPT_SPACE_PAD)
+ strlen(opt_table[i].desc) + 1;
if (opt_table[i].show) {
len += strlen("(default: %s)")
+ OPT_SHOW_LEN + sizeof("...");
}
len += strlen("\n");
}
}
p = ret = malloc(len);
if (!ret)
return NULL;
p += sprintf(p, "Usage: %s", argv0);
p += sprintf(p, " [-");
num = write_short_options(p);
if (num) {
p += num;
p += sprintf(p, "]");
} else {
/* Remove start of single-entry options */
p -= 3;
}
if (extra)
p += sprintf(p, " %s", extra);
p += sprintf(p, "\n");
for (i = 0; i < opt_count; i++) {
if (opt_table[i].desc == opt_hidden)
continue;
if (opt_table[i].type == OPT_SUBTABLE) {
p += sprintf(p, "%s:\n", opt_table[i].desc);
continue;
}
len = sprintf(p, "%s", opt_table[i].names);
if (opt_table[i].type == OPT_HASARG
&& !strchr(opt_table[i].names, ' ')
&& !strchr(opt_table[i].names, '='))
len += sprintf(p + len, " <arg>");
len += sprintf(p + len, "%.*s",
len < strlen(OPT_SPACE_PAD)
? (unsigned)strlen(OPT_SPACE_PAD) - len : 1,
OPT_SPACE_PAD);
len += sprintf(p + len, "%s", opt_table[i].desc);
if (opt_table[i].show) {
char buf[OPT_SHOW_LEN + sizeof("...")];
strcpy(buf + OPT_SHOW_LEN, "...");
opt_table[i].show(buf, opt_table[i].u.arg);
len += sprintf(p + len, " (default: %s)", buf);
}
p += len;
p += sprintf(p, "\n");
}
*p = '\0';
return ret;
}