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);
                     }
             }
         }

Reply via email to