Add an SK_PRINTF_LIKE macro, which declares a function to have printf-like
semantics, allowing gcc and clang to check the format string against the
arguments.  Enable its use on SkString (printf, appendf, and prependf).  Also
define an SK_SIZE_T_SPECIFIER macro so there's a cross-platform way of
printing a size_t.

Review URL:  http://codereview.appspot.com/6375043/



git-svn-id: http://skia.googlecode.com/svn/trunk@4485 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/MemoryBench.cpp b/bench/MemoryBench.cpp
index e732687..5fdb7f1 100644
--- a/bench/MemoryBench.cpp
+++ b/bench/MemoryBench.cpp
@@ -22,7 +22,7 @@
 public:
     ChunkAllocBench(void* param, size_t minSize) : INHERITED(param) {
         fMinSize = minSize;
-        fName.printf("chunkalloc_%d", minSize);
+        fName.printf("chunkalloc_" SK_SIZE_T_SPECIFIER, minSize);
     }
     
 protected:
diff --git a/experimental/Debugger/SkDebugDumper.cpp b/experimental/Debugger/SkDebugDumper.cpp
index 64ac2eb..69b1896 100644
--- a/experimental/Debugger/SkDebugDumper.cpp
+++ b/experimental/Debugger/SkDebugDumper.cpp
@@ -28,7 +28,7 @@
 
 static void appendPtr(SkString* str, const void* ptr, const char name[]) {
     if (ptr) {
-        str->appendf("$s: %p\t", name, ptr);
+        str->appendf("%s: %p\t", name, ptr);
     }
 }
 
diff --git a/include/core/SkPostConfig.h b/include/core/SkPostConfig.h
index aea7982..8d52f70 100644
--- a/include/core/SkPostConfig.h
+++ b/include/core/SkPostConfig.h
@@ -290,6 +290,26 @@
 
 //////////////////////////////////////////////////////////////////////
 
+#ifndef SK_PRINTF_LIKE
+#if defined(__clang__) || defined(__GNUC__)
+#define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
+#else
+#define SK_PRINTF_LIKE(A, B)
+#endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#ifndef SK_SIZE_T_SPECIFIER
+#if defined(_MSC_VER)
+#define SK_SIZE_T_SPECIFIER "%Iu"
+#else
+#define SK_SIZE_T_SPECIFIER "%zu"
+#endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
 #ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
 #define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1
 #endif
diff --git a/include/core/SkString.h b/include/core/SkString.h
index baabf0f..5896ef6 100644
--- a/include/core/SkString.h
+++ b/include/core/SkString.h
@@ -142,9 +142,9 @@
     void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); }
     void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
 
-    void printf(const char format[], ...);
-    void appendf(const char format[], ...);
-    void prependf(const char format[], ...);
+    void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+    void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+    void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
 
     void remove(size_t offset, size_t length);
 
diff --git a/samplecode/SampleSlides.cpp b/samplecode/SampleSlides.cpp
index 91f6eb6..1154c76 100644
--- a/samplecode/SampleSlides.cpp
+++ b/samplecode/SampleSlides.cpp
@@ -743,7 +743,7 @@
             gProc[i](&canvas);
             canvas.restore();
             SkString str;
-            str.printf("/skimages/slide_%d.png", i);
+            str.printf("/skimages/slide_" SK_SIZE_T_SPECIFIER ".png", i);
             SkImageEncoder::EncodeFile(str.c_str(), bm, SkImageEncoder::kPNG_Type, 100);
         }
         this->setBGColor(BG_COLOR);
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 8b8a954..fe7c6d5 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -518,7 +518,7 @@
     // the dual source output has no canonical var name, have to
     // declare an output, which is incompatible with gl_FragColor/gl_FragData.
     bool dualSourceOutputWritten = false;
-    segments.fHeader.printf(GrGetGLSLVersionDecl(gl.binding(),
+    segments.fHeader.append(GrGetGLSLVersionDecl(gl.binding(),
                                                  gl.glslGeneration()));
 
     GrGLShaderVar colorOutput;
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index 57ee799..d1db4e2 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -133,15 +133,15 @@
                      SkString* str) {
     switch (enc) {
         case SkPaint::kUTF8_TextEncoding:
-            str->printf("\"%.*s\"%s", SkMax32(len, 32), text,
+            str->printf("\"%.*s\"%s", SkMax32(len, 32), (const char*) text,
                         len > 32 ? "..." : "");
             break;
         case SkPaint::kUTF16_TextEncoding:
-            str->printf("\"%.*S\"%s", SkMax32(len, 32), text,
+            str->printf("\"%.*S\"%s", SkMax32(len, 32), (const wchar_t*) text,
                         len > 64 ? "..." : "");
             break;
         case SkPaint::kUTF32_TextEncoding:
-            str->printf("\"%.*S\"%s", SkMax32(len, 32), text,
+            str->printf("\"%.*S\"%s", SkMax32(len, 32), (const wchar_t*) text,
                         len > 128 ? "..." : "");
             break;
         case SkPaint::kGlyphID_TextEncoding: