X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fopt%2Fusage.c;h=b71fb334627f174fbc8bfd2022e87c0304d43fd8;hp=d9b2ee59cc3e4ba9a10df5a5eb358a74b5b4fb89;hb=ecf907f7e6b41ba69a10b20b2cb5743ed9cdf919;hpb=3d45cf27cf586c9afe078ceb06fee115ea246a92 diff --git a/ccan/opt/usage.c b/ccan/opt/usage.c index d9b2ee59..b71fb334 100644 --- a/ccan/opt/usage.c +++ b/ccan/opt/usage.c @@ -1,6 +1,10 @@ -/* 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 +#include /* Required on Solaris for ioctl */ #include #include #include @@ -15,42 +19,57 @@ const char opt_hidden[1]; static unsigned int get_columns(void) { - struct winsize w; + int ws_col = 0; const char *env = getenv("COLUMNS"); - w.ws_col = 0; if (env) - w.ws_col = atoi(env); - if (!w.ws_col) - if (ioctl(0, TIOCGWINSZ, &w) == -1) - w.ws_col = 0; - if (!w.ws_col) - w.ws_col = 80; - - return w.ws_col; + ws_col = atoi(env); + +#ifdef TIOCGWINSZ + if (!ws_col) + { + struct winsize w; + if (ioctl(0, TIOCGWINSZ, &w) != -1) + ws_col = w.ws_col; + } +#endif + if (!ws_col) + ws_col = 80; + + return ws_col; } /* 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. */ - *prefix = strspn(words, " "); + /* 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, " "); - len += strcspn(words+len, " "); - 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; } @@ -58,7 +77,7 @@ static char *add_str_len(char *base, size_t *len, size_t *max, const char *str, size_t slen) { if (slen >= *max - *len) - base = realloc(base, *max = (*max * 2 + slen + 1)); + base = opt_alloc.realloc(base, *max = (*max * 2 + slen + 1)); memcpy(base + *len, str, slen); *len += slen; return base; @@ -72,7 +91,7 @@ static char *add_str(char *base, size_t *len, size_t *max, const char *str) static char *add_indent(char *base, size_t *len, size_t *max, size_t indent) { if (indent >= *max - *len) - base = realloc(base, *max = (*max * 2 + indent + 1)); + base = opt_alloc.realloc(base, *max = (*max * 2 + indent + 1)); memset(base + *len, ' ', indent); *len += indent; return base; @@ -84,7 +103,7 @@ 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); @@ -107,7 +126,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;