Implement minimal support for varargs
diff --git a/fakegen.rb b/fakegen.rb
index 85fa9e8..790c287 100644
--- a/fakegen.rb
+++ b/fakegen.rb
@@ -161,31 +161,31 @@
   $current_depth = $current_depth - 4
 end
 
-def output_macro(arg_count, is_value_function, is_vararg)
+def output_macro(arg_count, has_varargs, is_value_function)
 
-  vararg_name = is_vararg ? "_VARARG" : ""
-  fake_macro_name = is_value_function ? "FAKE_VALUE_FUNC#{arg_count}#{vararg_name}" : "FAKE_VOID_FUNC#{arg_count}#{vararg_name}";
+  vararg_name = has_varargs ? "_VARARG" : ""
+  fake_macro_name = is_value_function ? "FAKE_VALUE_FUNC#{arg_count}#{vararg_name}" : "FAKE_VOID_FUNC#{arg_count}#{vararg_name}"
   declare_macro_name = "DECLARE_#{fake_macro_name}"
   define_macro_name = "DEFINE_#{fake_macro_name}"
-    
+  saved_arg_count = arg_count - (has_varargs ? 1 : 0)
   return_type = is_value_function ? "RETURN_TYPE" : ""
 
   putd ""
-  output_macro_header(declare_macro_name, arg_count, return_type)
+  output_macro_header(declare_macro_name, saved_arg_count, has_varargs, return_type)
   pushd
     extern_c {  # define argument capture variables
-      output_variables(arg_count, is_value_function)
+      output_variables(saved_arg_count, has_varargs, is_value_function)
     }
   popd
   
   putd ""
-  output_macro_header(define_macro_name, arg_count, return_type)
+  output_macro_header(define_macro_name, saved_arg_count, has_varargs, return_type)
   pushd
     extern_c {
       putd "FUNCNAME##_Fake FUNCNAME##_fake;\\"
-      putd function_signature(arg_count, is_value_function) + "{ \\"
+      putd function_signature(saved_arg_count, has_varargs, is_value_function) + "{ \\"
       pushd
-        output_function_body(arg_count, is_value_function)
+        output_function_body(saved_arg_count, has_varargs, is_value_function)
       popd
       putd "} \\"
       putd "DEFINE_RESET_FUNCTION(FUNCNAME) \\"
@@ -194,25 +194,25 @@
   
   putd ""
   
-  output_macro_header(fake_macro_name, arg_count, return_type)
+  output_macro_header(fake_macro_name, saved_arg_count, has_varargs, return_type)
   pushd
-    putd macro_signature_for(declare_macro_name, arg_count, return_type)
-    putd macro_signature_for(define_macro_name, arg_count, return_type)
+    putd macro_signature_for(declare_macro_name, saved_arg_count, has_varargs, return_type)
+    putd macro_signature_for(define_macro_name, saved_arg_count, has_varargs, return_type)
     putd ""
   popd
 end
 
-def output_macro_header(macro_name, arg_count, return_type)
-  output_macro_name(macro_name, arg_count, return_type)
+def output_macro_header(macro_name, arg_count, has_varargs, return_type)
+  output_macro_name(macro_name, arg_count, has_varargs, return_type)
 end
 
 # #define #macro_name(RETURN_TYPE, FUNCNAME, ARG0,...)
-def output_macro_name(macro_name, arg_count, return_type)
-  putd "#define " + macro_signature_for(macro_name, arg_count, return_type)
+def output_macro_name(macro_name, arg_count, has_varargs, return_type)
+  putd "#define " + macro_signature_for(macro_name, arg_count, has_varargs, return_type)
 end
 
 # #macro_name(RETURN_TYPE, FUNCNAME, ARG0,...)
-def macro_signature_for(macro_name, arg_count, return_type)
+def macro_signature_for(macro_name, arg_count, has_varargs, return_type)
   parameter_list = "#{macro_name}("
   if return_type != ""
     parameter_list += return_type
@@ -222,6 +222,8 @@
 
   arg_count.times { |i| parameter_list += ", ARG#{i}_TYPE" }
 
+  parameter_list += ", ..." if has_varargs
+
   parameter_list +=  ") \\"
   
   parameter_list
@@ -231,14 +233,14 @@
   putd "    DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME) \\"
 end
 
-def output_variables(arg_count, is_value_function)
+def output_variables(arg_count, has_varargs, is_value_function)
   in_struct{
     arg_count.times { |argN| 
       putd "DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME) \\"
     }
     putd "DECLARE_ALL_FUNC_COMMON \\"
     putd "DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \\" unless not is_value_function
-    output_custom_function_signature(arg_count, is_value_function)
+    output_custom_function_signature(arg_count, has_varargs, is_value_function)
   }
   putd "extern FUNCNAME##_Fake FUNCNAME##_fake;\\"
   putd "void FUNCNAME##_reset(); \\"
@@ -260,19 +262,20 @@
 
 # RETURN_TYPE (*custom_fake)(ARG0_TYPE arg0);\
 # void (*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2);\
-def output_custom_function_signature(arg_count, is_value_function)
+def output_custom_function_signature(arg_count, has_varargs, is_value_function)
   return_type = is_value_function ? "RETURN_TYPE" : "void"
   signature = "(*custom_fake)(#{arg_val_list(arg_count)}); \\"
   putd return_type + signature
 end
 
 # example: RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1)
-def function_signature(arg_count, is_value_function)
+def function_signature(arg_count, has_varargs, is_value_function)
   return_type = is_value_function ? "RETURN_TYPE" : "void"
-  "#{return_type} FUNCNAME(#{arg_val_list(arg_count)})"
+  varargs = has_varargs ? ", ..." : ""
+  "#{return_type} FUNCNAME(#{arg_val_list(arg_count)}#{varargs})"
 end
 
-def output_function_body(arg_count, is_value_function)
+def output_function_body(arg_count, has_varargs, is_value_function)
   arg_count.times { |i| putd "SAVE_ARG(FUNCNAME, #{i}); \\" }
   putd "if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\\"
   arg_count.times { |i| putd "    SAVE_ARG_HISTORY(FUNCNAME, #{i}); \\" }
@@ -408,7 +411,8 @@
 output_c_and_cpp{
   define_fff_globals
   $MAX_ARGS.times {|arg_count| output_macro(arg_count, false, false)}
-  $MAX_ARGS.times {|arg_count| output_macro(arg_count, true, false)}
   $MAX_ARGS.times {|arg_count| output_macro(arg_count, false, true)}
-  $MAX_ARGS.times {|arg_count| output_macro(arg_count, true, true)}
+  # generate the varargs variants
+  (2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, false)}
+  (2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, true)}
 }
diff --git a/fff.h b/fff.h
index e62e403..b94f4dd 100644
--- a/fff.h
+++ b/fff.h
@@ -1003,6 +1003,852 @@
     DEFINE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
     
 
+#define DECLARE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0, arg1); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            SAVE_ARG(FUNCNAME, 5); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+                SAVE_ARG_HISTORY(FUNCNAME, 5); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+            DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            SAVE_ARG(FUNCNAME, 5); \
+            SAVE_ARG(FUNCNAME, 6); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+                SAVE_ARG_HISTORY(FUNCNAME, 5); \
+                SAVE_ARG_HISTORY(FUNCNAME, 6); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+            DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+            DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            SAVE_ARG(FUNCNAME, 5); \
+            SAVE_ARG(FUNCNAME, 6); \
+            SAVE_ARG(FUNCNAME, 7); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+                SAVE_ARG_HISTORY(FUNCNAME, 5); \
+                SAVE_ARG_HISTORY(FUNCNAME, 6); \
+                SAVE_ARG_HISTORY(FUNCNAME, 7); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+            DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+            DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+            DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            SAVE_ARG(FUNCNAME, 5); \
+            SAVE_ARG(FUNCNAME, 6); \
+            SAVE_ARG(FUNCNAME, 7); \
+            SAVE_ARG(FUNCNAME, 8); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+                SAVE_ARG_HISTORY(FUNCNAME, 5); \
+                SAVE_ARG_HISTORY(FUNCNAME, 6); \
+                SAVE_ARG_HISTORY(FUNCNAME, 7); \
+                SAVE_ARG_HISTORY(FUNCNAME, 8); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake)  FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    DECLARE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    DEFINE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            SAVE_ARG(FUNCNAME, 5); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+                SAVE_ARG_HISTORY(FUNCNAME, 5); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+            DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            SAVE_ARG(FUNCNAME, 5); \
+            SAVE_ARG(FUNCNAME, 6); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+                SAVE_ARG_HISTORY(FUNCNAME, 5); \
+                SAVE_ARG_HISTORY(FUNCNAME, 6); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+            DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+            DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            SAVE_ARG(FUNCNAME, 5); \
+            SAVE_ARG(FUNCNAME, 6); \
+            SAVE_ARG(FUNCNAME, 7); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+                SAVE_ARG_HISTORY(FUNCNAME, 5); \
+                SAVE_ARG_HISTORY(FUNCNAME, 6); \
+                SAVE_ARG_HISTORY(FUNCNAME, 7); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+    
+
+#define DECLARE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    EXTERN_C \
+        typedef struct FUNCNAME##_Fake { \
+            DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+            DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+            DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+            DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+            DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+            DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+            DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+            DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+            DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+            DECLARE_ALL_FUNC_COMMON \
+            DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+            RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \
+        } FUNCNAME##_Fake;\
+        extern FUNCNAME##_Fake FUNCNAME##_fake;\
+        void FUNCNAME##_reset(); \
+    END_EXTERN_C \
+
+#define DEFINE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    EXTERN_C \
+        FUNCNAME##_Fake FUNCNAME##_fake;\
+        RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...){ \
+            SAVE_ARG(FUNCNAME, 0); \
+            SAVE_ARG(FUNCNAME, 1); \
+            SAVE_ARG(FUNCNAME, 2); \
+            SAVE_ARG(FUNCNAME, 3); \
+            SAVE_ARG(FUNCNAME, 4); \
+            SAVE_ARG(FUNCNAME, 5); \
+            SAVE_ARG(FUNCNAME, 6); \
+            SAVE_ARG(FUNCNAME, 7); \
+            SAVE_ARG(FUNCNAME, 8); \
+            if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\
+                SAVE_ARG_HISTORY(FUNCNAME, 0); \
+                SAVE_ARG_HISTORY(FUNCNAME, 1); \
+                SAVE_ARG_HISTORY(FUNCNAME, 2); \
+                SAVE_ARG_HISTORY(FUNCNAME, 3); \
+                SAVE_ARG_HISTORY(FUNCNAME, 4); \
+                SAVE_ARG_HISTORY(FUNCNAME, 5); \
+                SAVE_ARG_HISTORY(FUNCNAME, 6); \
+                SAVE_ARG_HISTORY(FUNCNAME, 7); \
+                SAVE_ARG_HISTORY(FUNCNAME, 8); \
+            }\
+            else{\
+                HISTORY_DROPPED(FUNCNAME);\
+            }\
+            INCREMENT_CALL_COUNT(FUNCNAME); \
+            REGISTER_CALL(FUNCNAME); \
+            if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+            RETURN_FAKE_RESULT(FUNCNAME)  \
+        } \
+        DEFINE_RESET_FUNCTION(FUNCNAME) \
+    END_EXTERN_C \
+
+#define FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    DECLARE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    DEFINE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+    
+
 #define PP_NARG_MINUS2(...)     PP_NARG_MINUS2_(__VA_ARGS__, PP_RSEQ_N_MINUS2())
 
 #define PP_NARG_MINUS2_(...)     PP_ARG_MINUS2_N(__VA_ARGS__)
diff --git a/test/fff_test_c.c b/test/fff_test_c.c
index fc3bd50..ff0d47c 100644
--- a/test/fff_test_c.c
+++ b/test/fff_test_c.c
@@ -27,6 +27,7 @@
 FAKE_VALUE_FUNC(long, longfunc0);
 FAKE_VALUE_FUNC(enum MYBOOL, enumfunc0);
 FAKE_VALUE_FUNC(struct MyStruct, structfunc0);
+FAKE_VOID_FUNC3_VARARG(voidfunc3var, char *, int, ...);
 
 
 void setup()
@@ -36,6 +37,7 @@
     RESET_FAKE(longfunc0);
     RESET_FAKE(enumfunc0);
     RESET_FAKE(structfunc0);
+    RESET_FAKE(voidfunc3var);
     FFF_RESET_HISTORY();
 }
 
@@ -91,6 +93,8 @@
     RUN_TEST(FFFTestSuite, can_register_custom_fake);
     RUN_TEST(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return_value);
 
+    RUN_TEST(FFFTestSuite, use_vararg_fake_with_different_number_of_arguments);
+
     printf("\n-------------\n");
     printf("Complete\n");
     printf("-------------\n\n");
diff --git a/test/fff_test_global_c.c b/test/fff_test_global_c.c
index 6f6d640..62f1e55 100644
--- a/test/fff_test_global_c.c
+++ b/test/fff_test_global_c.c
@@ -13,6 +13,7 @@
     RESET_FAKE(longfunc0);
     RESET_FAKE(enumfunc0);
     RESET_FAKE(structfunc0);
+    RESET_FAKE(voidfunc3var);
 
     FFF_RESET_HISTORY();
 }
@@ -61,6 +62,8 @@
     RUN_TEST(FFFTestSuite, can_register_custom_fake);
     RUN_TEST(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return_value);
 
+    RUN_TEST(FFFTestSuite, use_vararg_fake_with_different_number_of_arguments);
+
     printf("\n-------------\n");
     printf("Complete\n");
     printf("-------------\n\n");
diff --git a/test/global_fakes.c b/test/global_fakes.c
index b64aaf9..8da82fc 100644
--- a/test/global_fakes.c
+++ b/test/global_fakes.c
@@ -6,3 +6,4 @@
 DEFINE_FAKE_VALUE_FUNC0(long, longfunc0);
 DEFINE_FAKE_VALUE_FUNC0(enum MYBOOL, enumfunc0);
 DEFINE_FAKE_VALUE_FUNC0(struct MyStruct, structfunc0);
+DEFINE_FAKE_VOID_FUNC3_VARARG(voidfunc3var, const char *, int, ...);
diff --git a/test/global_fakes.h b/test/global_fakes.h
index c899649..e530260 100644
--- a/test/global_fakes.h
+++ b/test/global_fakes.h
@@ -9,6 +9,7 @@
 void voidfunc1(int);
 void voidfunc2(char, char);
 long longfunc0();
+void voidfunc3var(const char *fmt, int argc, ...);
 
 enum MYBOOL { FALSE = 899, TRUE };
 struct MyStruct {
@@ -24,5 +25,6 @@
 DECLARE_FAKE_VALUE_FUNC0(long, longfunc0);
 DECLARE_FAKE_VALUE_FUNC0(enum MYBOOL, enumfunc0);
 DECLARE_FAKE_VALUE_FUNC0(struct MyStruct, structfunc0);
+DECLARE_FAKE_VOID_FUNC3_VARARG(voidfunc3var, const char *, int, ...);
 
 #endif /* GLOBAL_FAKES_H_ */
diff --git a/test/test_cases.include b/test/test_cases.include
index 1cb4c29..4a804f9 100644
--- a/test/test_cases.include
+++ b/test/test_cases.include
@@ -229,3 +229,13 @@
     long retval = longfunc0();
     ASSERT_EQ(MEANING_OF_LIFE, retval);
 }
+
+#ifndef __cplusplus
+TEST_F(FFFTestSuite, use_vararg_fake_with_different_number_of_arguments)
+{
+   voidfunc3var("0 parameters", 0);
+   voidfunc3var("1 parameter",  1, 10);
+   voidfunc3var("2 parameters", 2, 10, 20);
+   voidfunc3var("3 parameters", 3, 10, 20, 30);
+}
+#endif /* __cplusplus */