Improve error message for invalid CB_VCatF specifiers Obsoletes the old hack that wrote an error message directly to stderr.
Fixes CLOWNFISH-97. Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/5c7f068a Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/5c7f068a Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/5c7f068a Branch: refs/heads/master Commit: 5c7f068ad3e63785a78d3d12f9a6039b64edf24a Parents: 06b9823 Author: Nick Wellnhofer <[email protected]> Authored: Thu May 12 16:24:29 2016 +0200 Committer: Nick Wellnhofer <[email protected]> Committed: Fri May 13 15:59:17 2016 +0200 ---------------------------------------------------------------------- runtime/core/Clownfish/CharBuf.c | 46 +++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5c7f068a/runtime/core/Clownfish/CharBuf.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/CharBuf.c b/runtime/core/Clownfish/CharBuf.c index 33bbca6..8661c7b 100644 --- a/runtime/core/Clownfish/CharBuf.c +++ b/runtime/core/Clownfish/CharBuf.c @@ -57,9 +57,9 @@ S_grow_and_oversize(CharBuf *self, size_t min_size); static void S_overflow_error(); -// Helper function for throwing invalid pattern error. +// Helper function for throwing invalid format specifier error. static void -S_die_invalid_pattern(const char *pattern); +S_die_invalid_specifier(const char *specifier); CharBuf* CB_new(size_t size) { @@ -94,12 +94,27 @@ CB_Grow_IMP(CharBuf *self, size_t size) { } static void -S_die_invalid_pattern(const char *pattern) { - size_t pattern_len = strlen(pattern); - fprintf(stderr, "Invalid pattern, aborting: '"); - fwrite(pattern, sizeof(char), pattern_len, stderr); - fprintf(stderr, "'\n"); - THROW(ERR, "Invalid pattern."); +S_die_invalid_specifier(const char *specifier) { + char buf[4]; + buf[0] = specifier[0]; + buf[1] = '\0'; + + if (specifier[0] == 'i' || specifier[0] == 'u' || specifier[0] == 'x' + || specifier[0] == 'f' + ) { + if (specifier[1] < '0' || specifier[1] > '9') { + THROW(ERR, "Specifier %%%s must be followed by width", buf); + } + else { + size_t size = specifier[2] >= '0' && specifier[2] <= '9' ? 3 : 2; + memcpy(buf, specifier, size); + buf[size] = '\0'; + THROW(ERR, "Specifier %%%s has invalid width", buf); + } + } + else { + THROW(ERR, "Invalid specifier %%%s", buf); + } } void @@ -112,9 +127,8 @@ CB_catf(CharBuf *self, const char *pattern, ...) { void CB_VCatF_IMP(CharBuf *self, const char *pattern, va_list args) { - size_t pattern_len = strlen(pattern); - const char *pattern_start = pattern; - const char *pattern_end = pattern + pattern_len; + size_t pattern_len = strlen(pattern); + const char *pattern_end = pattern + pattern_len; char buf[64]; for (; pattern < pattern_end; pattern++) { @@ -167,7 +181,7 @@ CB_VCatF_IMP(CharBuf *self, const char *pattern, va_list args) { pattern += 2; } else { - S_die_invalid_pattern(pattern_start); + S_die_invalid_specifier(pattern); } int size = sprintf(buf, "%" PRId64, val); S_cat_utf8(self, buf, (size_t)size); @@ -188,7 +202,7 @@ CB_VCatF_IMP(CharBuf *self, const char *pattern, va_list args) { pattern += 2; } else { - S_die_invalid_pattern(pattern_start); + S_die_invalid_specifier(pattern); } int size = sprintf(buf, "%" PRIu64, val); S_cat_utf8(self, buf, (size_t)size); @@ -203,7 +217,7 @@ CB_VCatF_IMP(CharBuf *self, const char *pattern, va_list args) { pattern += 2; } else { - S_die_invalid_pattern(pattern_start); + S_die_invalid_specifier(pattern); } } break; @@ -215,7 +229,7 @@ CB_VCatF_IMP(CharBuf *self, const char *pattern, va_list args) { pattern += 2; } else { - S_die_invalid_pattern(pattern_start); + S_die_invalid_specifier(pattern); } } break; @@ -235,7 +249,7 @@ CB_VCatF_IMP(CharBuf *self, const char *pattern, va_list args) { // Assume NULL-terminated pattern string, which // eliminates the need for bounds checking if '%' is // the last visible character. - S_die_invalid_pattern(pattern_start); + S_die_invalid_specifier(pattern); } } }
