From: Willy Tarreau Date: Fri, 14 Sep 2012 09:40:36 +0000 (+0200) Subject: MINOR: config: add a function to indent error messages X-Git-Tag: v1.5-dev13~291 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=21c705b0f8eedcc853643f3010e8d14f835348fa;p=thirdparty%2Fhaproxy.git MINOR: config: add a function to indent error messages Bind parsers may return multiple errors, so let's make use of a new function to re-indent multi-line error messages so that they're all reported in their context. --- diff --git a/include/common/standard.h b/include/common/standard.h index 93b9e363d2..2d67faf6fe 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -706,6 +706,15 @@ char *gmt2str_log(char *dst, struct tm *tm, size_t size); char *memprintf(char **out, const char *format, ...) __attribute__ ((format(printf, 2, 3))); +/* Used to add spaces before each line of , unless there is only one line. + * The input argument is automatically freed and reassigned. The result will have to be + * freed by the caller. + * Example of use : + * parse(cmd, &err); (callee: memprintf(&err, ...)) + * fprintf(stderr, "Parser said: %s\n", indent_error(&err)); + * free(err); + */ +char *indent_msg(char **out, int level); /* debugging macro to emit messages using write() on fd #-1 so that strace sees * them. diff --git a/src/standard.c b/src/standard.c index e7bc070008..31f4ddd6fb 100644 --- a/src/standard.c +++ b/src/standard.c @@ -1834,6 +1834,74 @@ char *memprintf(char **out, const char *format, ...) return ret; } +/* Used to add spaces before each line of , unless there is only one line. + * The input argument is automatically freed and reassigned. The result will have to be + * freed by the caller. + * Example of use : + * parse(cmd, &err); (callee: memprintf(&err, ...)) + * fprintf(stderr, "Parser said: %s\n", indent_error(&err)); + * free(err); + */ +char *indent_msg(char **out, int level) +{ + char *ret, *in, *p; + int needed = 0; + int lf = 0; + int lastlf = 0; + int len; + + in = *out - 1; + while ((in = strchr(in + 1, '\n')) != NULL) { + lastlf = in - *out; + lf++; + } + + if (!lf) /* single line, no LF, return it as-is */ + return *out; + + len = strlen(*out); + + if (lf == 1 && lastlf == len - 1) { + /* single line, LF at end, strip it and return as-is */ + (*out)[lastlf] = 0; + return *out; + } + + /* OK now we have at least one LF, we need to process the whole string + * as a multi-line string. What we'll do : + * - prefix with an LF if there is none + * - add spaces before each line + * This means at most ( 1 + level + (len-lf) + lf*<1+level) ) = + * 1 + level + len + lf * level = 1 + level * (lf + 1) + len. + */ + + needed = 1 + level * (lf + 1) + len + 1; + p = ret = malloc(needed); + in = *out; + + /* skip initial LFs */ + while (*in == '\n') + in++; + + /* copy each line, prefixed with LF and spaces, and without the trailing LF */ + while (*in) { + *p++ = '\n'; + memset(p, ' ', level); + p += level; + do { + *p++ = *in++; + } while (*in && *in != '\n'); + if (*in) + in++; + } + *p = 0; + + free(*out); + *out = ret; + + return ret; +} + /* * Local variables: * c-indent-level: 8