#include <string.h>
-#include <iostream>
+
 #include <algorithm>
+#include <iostream>
+#include <map>
 
 #include "image.hpp"
 #include "json.hpp"
 }
 
 
+// Mapping from shader type to shader source, used to accumulated the sources
+// of different shaders with same type.
+typedef std::map<std::string, std::string> ShaderMap;
+
+
 static void
-dumpShader(JSONWriter &json, GLuint shader)
+getShaderSource(ShaderMap &shaderMap, GLuint shader)
 {
     if (!shader) {
         return;
     source[0] = 0;
     glGetShaderSource(shader, source_length, &length, source);
 
-    json.beginMember(enumToString(shader_type));
-    json.writeString(source);
-    json.endMember();
+    shaderMap[enumToString(shader_type)] += source;
 
     delete [] source;
 }
 
 
 static void
-dumpShaderObj(JSONWriter &json, GLhandleARB shaderObj)
+getShaderObjSource(ShaderMap &shaderMap, GLhandleARB shaderObj)
 {
     if (!shaderObj) {
         return;
     source[0] = 0;
     glGetShaderSource(shaderObj, source_length, &length, source);
 
-    json.beginMember(enumToString(shader_type));
-    json.writeString(source);
-    json.endMember();
+    shaderMap[enumToString(shader_type)] += source;
 
     delete [] source;
 }
         return;
     }
 
+    ShaderMap shaderMap;
+
     GLuint *shaders = new GLuint[attached_shaders];
     GLsizei count = 0;
     glGetAttachedShaders(program, attached_shaders, &count, shaders);
     for (GLsizei i = 0; i < count; ++ i) {
-       dumpShader(json, shaders[i]);
+       getShaderSource(shaderMap, shaders[i]);
     }
     delete [] shaders;
+
+    for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
+        json.beginMember(it->first);
+        json.writeString(it->second);
+        json.endMember();
+    }
 }
 
 
         return;
     }
 
+    ShaderMap shaderMap;
+
     GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders];
     GLsizei count = 0;
     glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs);
     for (GLsizei i = 0; i < count; ++ i) {
-       dumpShaderObj(json, shaderObjs[i]);
+       getShaderObjSource(shaderMap, shaderObjs[i]);
     }
     delete [] shaderObjs;
+
+    for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
+        json.beginMember(it->first);
+        json.writeString(it->second);
+        json.endMember();
+    }
 }
 
 
 
 #include <stddef.h>
 #include <wchar.h>
 
-#include <ostream>
 #include <iomanip>
+#include <ostream>
+#include <string>
 
 
 class JSONWriter
         value = false;
     }
 
+    inline void beginMember(const std::string &name) {
+        beginMember(name.c_str());
+    }
+
     inline void endMember(void) {
         assert(value);
         value = true;
         space = ' ';
     }
 
+    inline void writeString(const std::string &s) {
+        writeString(s.c_str());
+    }
+
     inline void writeBase64(const void *bytes, size_t size) {
         separator();
         encodeBase64String((const unsigned char *)bytes, size);