X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fopt%2Fusage.c;h=12f44a48752e0e0d4e0d722c74b7513561334733;hp=494b179bfde97ccb93c8969ce066f1b5860b5097;hb=7d1f0c73e4d321561abb74f82c8be97f10d69836;hpb=13b374859ed7564c5945ff9e18c7bc0e98d7532e diff --git a/ccan/opt/usage.c b/ccan/opt/usage.c index 494b179b..12f44a48 100644 --- a/ccan/opt/usage.c +++ b/ccan/opt/usage.c @@ -1,14 +1,17 @@ -/* Licensed under GPLv3+ - see LICENSE file for details */ +/* Licensed under GPLv2+ - see LICENSE file for details */ #include #if HAVE_SYS_TERMIOS_H #include #include /* Required on Solaris for struct winsize */ #endif +#if HAVE_SYS_UNISTD_H #include /* Required on Solaris for ioctl */ +#endif #include #include #include #include +#include #include "private.h" /* We only use this for pointer comparisons. */ @@ -41,27 +44,35 @@ static unsigned int get_columns(void) /* Return number of chars of words to put on this line. * Prefix is set to number to skip at start, maxlen is max width, returns - * length (after prefix) to put on this line. */ -static size_t consume_words(const char *words, size_t maxlen, size_t *prefix) + * length (after prefix) to put on this line. + * start is set if we start a new line in the source description. */ +static size_t consume_words(const char *words, size_t maxlen, size_t *prefix, + bool *start) { size_t oldlen, len; - /* Swallow leading whitespace. */ + /* Always swollow leading whitespace. */ *prefix = strspn(words, " \n"); words += *prefix; - /* Use at least one word, even if it takes us over maxlen. */ - oldlen = len = strcspn(words, " "); - while (len <= maxlen) { - oldlen = len; - len += strspn(words+len, " "); - if (words[len] == '\n') - break; - len += strcspn(words+len, " \n"); - if (len == oldlen) - break; + /* Leading whitespace at start of line means literal. */ + if (*start && *prefix) { + oldlen = strcspn(words, "\n"); + } else { + /* Use at least one word, even if it takes us over maxlen. */ + oldlen = len = strcspn(words, " "); + while (len <= maxlen) { + oldlen = len; + len += strspn(words+len, " "); + if (words[len] == '\n') + break; + len += strcspn(words+len, " \n"); + if (len == oldlen) + break; + } } + *start = (words[oldlen - 1] == '\n'); return oldlen; } @@ -95,11 +106,11 @@ static char *add_desc(char *base, size_t *len, size_t *max, { size_t off, prefix, l; const char *p; - bool same_line = false; + bool same_line = false, start = true; base = add_str(base, len, max, opt->names); off = strlen(opt->names); - if (opt->type == OPT_HASARG + if ((opt->type & OPT_HASARG) && !strchr(opt->names, ' ') && !strchr(opt->names, '=')) { base = add_str(base, len, max, " "); @@ -118,7 +129,7 @@ static char *add_desc(char *base, size_t *len, size_t *max, /* Indent description. */ p = opt->desc; - while ((l = consume_words(p, width - indent, &prefix)) != 0) { + while ((l = consume_words(p, width - indent, &prefix, &start)) != 0) { if (!same_line) base = add_indent(base, len, max, indent); p += prefix; @@ -219,3 +230,17 @@ char *opt_usage(const char *argv0, const char *extra) ret[len] = '\0'; return ret; } + +void opt_usage_exit_fail(const char *msg, ...) +{ + va_list ap; + + if (opt_argv0) + fprintf(stderr, "%s: ", opt_argv0); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fprintf(stderr, "\n%s", + opt_usage(opt_argv0 ? opt_argv0 : "", NULL)); + exit(1); +}