forked from 3rd-party/fff
On some contexts, we need to call one function to free some resource allocated by another function based on the return value of the second function. For example, every time pthread_mutex_trylock suceeds, you need to unlock it, and only in those cases. While this could be done with the return value sequence, it does not really work for a sequence of custom fakes. Now we save the return values in the member return_val_history, which works pretty much like arg_history, only for the return values.
530 lines
17 KiB
Ruby
530 lines
17 KiB
Ruby
|
|
# fakegen.rb
|
|
# A simple code generator to create some C macros for defining test fake functions
|
|
|
|
|
|
$cpp_output = true
|
|
$MAX_ARGS = 20
|
|
$DEFAULT_ARG_HISTORY = 50
|
|
$MAX_CALL_HISTORY = 50
|
|
|
|
def include_dependencies
|
|
putd "#include <stdarg.h>"
|
|
putd "#include <string.h> /* For memset and memcpy */"
|
|
putd ""
|
|
end
|
|
|
|
def output_constants
|
|
putd "#define FFF_MAX_ARGS (#{$MAX_ARGS}u)"
|
|
putd "#ifndef FFF_ARG_HISTORY_LEN"
|
|
putd " #define FFF_ARG_HISTORY_LEN (#{$DEFAULT_ARG_HISTORY}u)"
|
|
putd "#endif"
|
|
putd "#ifndef FFF_CALL_HISTORY_LEN"
|
|
putd " #define FFF_CALL_HISTORY_LEN (#{$MAX_CALL_HISTORY}u)"
|
|
putd "#endif"
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# ------ Helper macros to use internally ------ #
|
|
def output_internal_helper_macros
|
|
putd "/* -- INTERNAL HELPER MACROS -- */"
|
|
|
|
define_return_sequence_helper
|
|
define_custom_fake_sequence_helper
|
|
define_reset_fake_macro
|
|
define_declare_arg_helper
|
|
define_declare_all_func_common_helper
|
|
define_declare_return_value_history
|
|
define_save_arg_helper
|
|
define_room_for_more_history
|
|
define_save_ret_history_helper
|
|
define_save_arg_history_helper
|
|
define_history_dropped_helper
|
|
define_value_function_variables_helper
|
|
define_custom_fake_seq_variables_helper
|
|
define_increment_call_count_helper
|
|
define_return_fake_result_helper
|
|
define_extern_c_helper
|
|
define_reset_fake_helper
|
|
|
|
putd "/* -- END INTERNAL HELPER MACROS -- */"
|
|
putd ""
|
|
end
|
|
|
|
def define_return_sequence_helper
|
|
putd "#define SET_RETURN_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \\"
|
|
putd " FUNCNAME##_fake.return_val_seq = ARRAY_POINTER; \\"
|
|
putd " FUNCNAME##_fake.return_val_seq_len = ARRAY_LEN;"
|
|
end
|
|
|
|
def define_custom_fake_sequence_helper
|
|
putd "#define SET_CUSTOM_FAKE_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \\"
|
|
putd " FUNCNAME##_fake.custom_fake_seq = ARRAY_POINTER; \\"
|
|
putd " FUNCNAME##_fake.custom_fake_seq_len = ARRAY_LEN;"
|
|
end
|
|
|
|
def define_reset_fake_macro
|
|
putd ""
|
|
putd "/* Defining a function to reset a fake function */"
|
|
putd "#define RESET_FAKE(FUNCNAME) { \\"
|
|
putd " FUNCNAME##_reset(); \\"
|
|
putd "} \\"
|
|
putd ""
|
|
end
|
|
|
|
def define_declare_arg_helper
|
|
putd ""
|
|
putd "#define DECLARE_ARG(type, n, FUNCNAME) \\"
|
|
putd " type arg##n##_val; \\"
|
|
putd " type arg##n##_history[FFF_ARG_HISTORY_LEN];"
|
|
end
|
|
|
|
def define_declare_all_func_common_helper
|
|
putd ""
|
|
putd "#define DECLARE_ALL_FUNC_COMMON \\"
|
|
putd " unsigned int call_count; \\"
|
|
putd " unsigned int arg_history_len;\\"
|
|
putd " unsigned int arg_histories_dropped; \\"
|
|
end
|
|
|
|
def define_declare_return_value_history
|
|
putd ""
|
|
putd "#define DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \\"
|
|
putd " RETURN_TYPE return_val_history[FFF_ARG_HISTORY_LEN];"
|
|
end
|
|
|
|
def define_save_arg_helper
|
|
putd ""
|
|
putd "#define SAVE_ARG(FUNCNAME, n) \\"
|
|
putd " memcpy((void*)&FUNCNAME##_fake.arg##n##_val, (void*)&arg##n, sizeof(arg##n));"
|
|
end
|
|
|
|
def define_save_ret_history_helper
|
|
putd ""
|
|
putd "#define SAVE_RET_HISTORY(FUNCNAME, RETVAL) \\"
|
|
putd " if ((FUNCNAME##_fake.call_count - 1) < FFF_ARG_HISTORY_LEN) \\"
|
|
putd " memcpy((void *)&FUNCNAME##_fake.return_val_history[FUNCNAME##_fake.call_count - 1], (const void *) &RETVAL, sizeof(RETVAL)); \\"
|
|
end
|
|
|
|
def define_room_for_more_history
|
|
putd ""
|
|
putd "#define ROOM_FOR_MORE_HISTORY(FUNCNAME) \\"
|
|
putd " FUNCNAME##_fake.call_count < FFF_ARG_HISTORY_LEN"
|
|
end
|
|
|
|
def define_save_arg_history_helper
|
|
putd ""
|
|
putd "#define SAVE_ARG_HISTORY(FUNCNAME, ARGN) \\"
|
|
putd " memcpy((void*)&FUNCNAME##_fake.arg##ARGN##_history[FUNCNAME##_fake.call_count], (void*)&arg##ARGN, sizeof(arg##ARGN));"
|
|
end
|
|
|
|
def define_history_dropped_helper
|
|
putd ""
|
|
putd "#define HISTORY_DROPPED(FUNCNAME) \\"
|
|
putd " FUNCNAME##_fake.arg_histories_dropped++"
|
|
end
|
|
|
|
def define_value_function_variables_helper
|
|
putd ""
|
|
putd "#define DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \\"
|
|
putd " RETURN_TYPE return_val; \\"
|
|
putd " int return_val_seq_len; \\"
|
|
putd " int return_val_seq_idx; \\"
|
|
putd " RETURN_TYPE * return_val_seq; \\"
|
|
end
|
|
|
|
def define_custom_fake_seq_variables_helper
|
|
putd ""
|
|
putd "#define DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \\"
|
|
putd " int custom_fake_seq_len; \\"
|
|
putd " int custom_fake_seq_idx; \\"
|
|
end
|
|
|
|
def define_increment_call_count_helper
|
|
putd ""
|
|
putd "#define INCREMENT_CALL_COUNT(FUNCNAME) \\"
|
|
putd " FUNCNAME##_fake.call_count++"
|
|
end
|
|
|
|
def define_return_fake_result_helper
|
|
putd ""
|
|
putd "#define RETURN_FAKE_RESULT(FUNCNAME) \\"
|
|
putd " if (FUNCNAME##_fake.return_val_seq_len){ /* then its a sequence */ \\"
|
|
putd " if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) { \\"
|
|
putd " SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx]) \\"
|
|
putd " return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++]; \\"
|
|
putd " } \\"
|
|
putd " SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]) \\"
|
|
putd " return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */ \\"
|
|
putd " } \\"
|
|
putd " SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val) \\"
|
|
putd " return FUNCNAME##_fake.return_val; \\"
|
|
end
|
|
|
|
def define_extern_c_helper
|
|
putd ""
|
|
putd "#ifdef __cplusplus"
|
|
putd " #define FFF_EXTERN_C extern \"C\"{"
|
|
putd " #define FFF_END_EXTERN_C } "
|
|
putd "#else /* ansi c */"
|
|
putd " #define FFF_EXTERN_C "
|
|
putd " #define FFF_END_EXTERN_C "
|
|
putd "#endif /* cpp/ansi c */"
|
|
end
|
|
|
|
def define_reset_fake_helper
|
|
putd ""
|
|
putd "#define DEFINE_RESET_FUNCTION(FUNCNAME) \\"
|
|
putd " void FUNCNAME##_reset(void){ \\"
|
|
putd " memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake)); \\"
|
|
putd " FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;\\"
|
|
putd " }"
|
|
end
|
|
# ------ End Helper macros ------ #
|
|
|
|
#fakegen helpers to print at levels of indentation
|
|
$current_depth = 0
|
|
def putd(str)
|
|
$current_depth.times {|not_used| print " "}
|
|
puts str
|
|
end
|
|
|
|
def pushd
|
|
$current_depth = $current_depth + 4
|
|
end
|
|
|
|
def popd
|
|
$current_depth = $current_depth - 4
|
|
end
|
|
|
|
def output_macro(arg_count, has_varargs, is_value_function)
|
|
|
|
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, saved_arg_count, has_varargs, return_type)
|
|
pushd
|
|
extern_c { # define argument capture variables
|
|
output_variables(saved_arg_count, has_varargs, is_value_function)
|
|
}
|
|
popd
|
|
|
|
putd ""
|
|
output_macro_header(define_macro_name, saved_arg_count, has_varargs, return_type)
|
|
pushd
|
|
extern_c {
|
|
putd "FUNCNAME##_Fake FUNCNAME##_fake;\\"
|
|
putd function_signature(saved_arg_count, has_varargs, is_value_function) + "{ \\"
|
|
pushd
|
|
output_function_body(saved_arg_count, has_varargs, is_value_function)
|
|
popd
|
|
putd "} \\"
|
|
putd "DEFINE_RESET_FUNCTION(FUNCNAME) \\"
|
|
}
|
|
popd
|
|
|
|
putd ""
|
|
|
|
output_macro_header(fake_macro_name, saved_arg_count, has_varargs, return_type)
|
|
pushd
|
|
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, 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, 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, has_varargs, return_type)
|
|
parameter_list = "#{macro_name}("
|
|
if return_type != ""
|
|
parameter_list += return_type
|
|
parameter_list += ", "
|
|
end
|
|
parameter_list += "FUNCNAME"
|
|
|
|
arg_count.times { |i| parameter_list += ", ARG#{i}_TYPE" }
|
|
|
|
parameter_list += ", ..." if has_varargs
|
|
|
|
parameter_list += ") \\"
|
|
|
|
parameter_list
|
|
end
|
|
|
|
def output_argument_capture_variables(argN)
|
|
putd " DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME) \\"
|
|
end
|
|
|
|
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
|
|
putd "DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \\" unless not is_value_function
|
|
putd "DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \\"
|
|
output_custom_function_signature(arg_count, has_varargs, is_value_function)
|
|
output_custom_function_array(arg_count, has_varargs, is_value_function)
|
|
}
|
|
putd "extern FUNCNAME##_Fake FUNCNAME##_fake;\\"
|
|
putd "void FUNCNAME##_reset(void); \\"
|
|
end
|
|
|
|
#example: ARG0_TYPE arg0, ARG1_TYPE arg1
|
|
def arg_val_list(args_count)
|
|
return "void" if (args_count == 0)
|
|
arguments = []
|
|
args_count.times { |i| arguments << "ARG#{i}_TYPE arg#{i}" }
|
|
arguments.join(", ")
|
|
end
|
|
|
|
#example: arg0, arg1
|
|
def arg_list(args_count)
|
|
arguments = []
|
|
args_count.times { |i| arguments << "arg#{i}" }
|
|
arguments.join(", ")
|
|
end
|
|
|
|
# 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, has_varargs, is_value_function)
|
|
return_type = is_value_function ? "RETURN_TYPE" : "void"
|
|
ap_list = has_varargs ? ", va_list ap" : ""
|
|
signature = "(*custom_fake)(#{arg_val_list(arg_count)}#{ap_list}); \\"
|
|
putd return_type + signature
|
|
end
|
|
|
|
def output_custom_function_array(arg_count, has_varargs, is_value_function)
|
|
return_type = is_value_function ? "RETURN_TYPE" : "void"
|
|
ap_list = has_varargs ? ", va_list ap" : ""
|
|
custom_array = "(**custom_fake_seq)(#{arg_val_list(arg_count)}#{ap_list}); \\"
|
|
putd return_type + custom_array
|
|
end
|
|
|
|
# example: RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1)
|
|
def function_signature(arg_count, has_varargs, is_value_function)
|
|
return_type = is_value_function ? "RETURN_TYPE" : "void"
|
|
varargs = has_varargs ? ", ..." : ""
|
|
"#{return_type} FUNCNAME(#{arg_val_list(arg_count)}#{varargs})"
|
|
end
|
|
|
|
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}); \\" }
|
|
putd "}\\"
|
|
putd "else{\\"
|
|
putd " HISTORY_DROPPED(FUNCNAME);\\"
|
|
putd "}\\"
|
|
putd "INCREMENT_CALL_COUNT(FUNCNAME); \\"
|
|
putd "REGISTER_CALL(FUNCNAME); \\"
|
|
|
|
if has_varargs
|
|
putd "if(FUNCNAME##_fake.custom_fake){\\"
|
|
putd " RETURN_TYPE ret;\\" if is_value_function
|
|
putd " va_list ap;\\"
|
|
putd " va_start(ap, arg#{arg_count-1});\\"
|
|
custom_fake_call = "FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)}, ap);"
|
|
if is_value_function
|
|
putd " ret = #{custom_fake_call}\\"
|
|
else
|
|
putd " #{custom_fake_call}\\"
|
|
end
|
|
putd " va_end(ap);\\"
|
|
putd " SAVE_RET_HISTORY(FUNCNAME, ret); \\" unless not is_value_function
|
|
putd " return ret;\\" if is_value_function
|
|
putd "}\\"
|
|
else
|
|
return_type = is_value_function ? "return " : ""
|
|
putd "if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \\"
|
|
putd " if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \\"
|
|
putd " RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)}); \\" unless not is_value_function
|
|
putd " SAVE_RET_HISTORY(FUNCNAME, ret); \\" unless not is_value_function
|
|
putd " return ret; \\" unless not is_value_function
|
|
putd " #{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)}); \\" unless is_value_function
|
|
putd " } \\"
|
|
putd " else{ \\"
|
|
putd " RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](#{arg_list(arg_count)}); \\" unless not is_value_function
|
|
putd " SAVE_RET_HISTORY(FUNCNAME, ret); \\" unless not is_value_function
|
|
putd " return ret; \\" unless not is_value_function
|
|
putd " #{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](#{arg_list(arg_count)}); \\"
|
|
putd " } \\"
|
|
putd "} \\"
|
|
putd "if (FUNCNAME##_fake.custom_fake) #{return_type}FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)}); \\"
|
|
end
|
|
|
|
putd "RETURN_FAKE_RESULT(FUNCNAME) \\" if is_value_function
|
|
end
|
|
|
|
def output_reset_function(arg_count, is_value_function)
|
|
putd "void FUNCNAME##_reset(void){ \\"
|
|
putd " memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake)); \\"
|
|
putd " FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;\\"
|
|
putd "} \\"
|
|
end
|
|
|
|
def define_fff_globals
|
|
putd "typedef void (*fff_function_t)(void);"
|
|
putd "typedef struct { "
|
|
putd " fff_function_t call_history[FFF_CALL_HISTORY_LEN];"
|
|
putd " unsigned int call_history_idx;"
|
|
putd "} fff_globals_t;"
|
|
putd ""
|
|
putd "FFF_EXTERN_C \\"
|
|
putd "extern fff_globals_t fff;"
|
|
putd "FFF_END_EXTERN_C \\"
|
|
putd ""
|
|
putd "#define DEFINE_FFF_GLOBALS \\"
|
|
putd " FFF_EXTERN_C \\"
|
|
putd " fff_globals_t fff; \\"
|
|
putd " FFF_END_EXTERN_C"
|
|
putd ""
|
|
putd "#define FFF_RESET_HISTORY() fff.call_history_idx = 0;"
|
|
putd ""
|
|
putd "#define REGISTER_CALL(function) \\"
|
|
putd " if(fff.call_history_idx < FFF_CALL_HISTORY_LEN) \\"
|
|
putd " fff.call_history[fff.call_history_idx++] = (fff_function_t)function;"
|
|
end
|
|
|
|
def extern_c
|
|
putd "FFF_EXTERN_C \\"
|
|
pushd
|
|
yield
|
|
popd
|
|
putd "FFF_END_EXTERN_C \\"
|
|
end
|
|
|
|
def in_struct
|
|
putd "typedef struct FUNCNAME##_Fake { \\"
|
|
pushd
|
|
yield
|
|
popd
|
|
putd "} FUNCNAME##_Fake;\\"
|
|
end
|
|
|
|
def include_guard
|
|
putd "#ifndef FAKE_FUNCTIONS"
|
|
putd "#define FAKE_FUNCTIONS"
|
|
putd ""
|
|
|
|
yield
|
|
|
|
putd ""
|
|
putd "#endif /* FAKE_FUNCTIONS */"
|
|
end
|
|
|
|
def generate_arg_sequence(args, prefix, do_reverse, joinstr)
|
|
fmap = (0..args).flat_map {|i| [prefix + i.to_s]}
|
|
if do_reverse then fmap.reverse.join(joinstr) else fmap.join(", ") end
|
|
end
|
|
|
|
def counting_macro_instance(type, vararg = :non_vararg, prefix = "")
|
|
appendix = (vararg == :vararg) ? "_VARARG" : ""
|
|
minus_count = (type == :VOID) ? 1 : 2
|
|
|
|
<<-MACRO_COUNTING_INSTANCE
|
|
#define #{prefix}FAKE_#{type.to_s}_FUNC#{appendix}(...) \
|
|
#{prefix}FUNC_#{type.to_s}#{appendix}_(PP_NARG_MINUS#{minus_count}(__VA_ARGS__), __VA_ARGS__)
|
|
|
|
#define #{prefix}FUNC_#{type.to_s}#{appendix}_(N,...) \
|
|
#{prefix}FUNC_#{type.to_s}#{appendix}_N(N,__VA_ARGS__)
|
|
|
|
#define #{prefix}FUNC_#{type.to_s}#{appendix}_N(N,...) \
|
|
#{prefix}FAKE_#{type.to_s}_FUNC ## N#{" ## _VARARG" if vararg == :vararg}(__VA_ARGS__)
|
|
|
|
MACRO_COUNTING_INSTANCE
|
|
end
|
|
|
|
def output_macro_counting_shortcuts
|
|
putd <<-MACRO_COUNTING
|
|
|
|
#define PP_NARG_MINUS2(...) \
|
|
PP_NARG_MINUS2_(__VA_ARGS__, PP_RSEQ_N_MINUS2())
|
|
|
|
#define PP_NARG_MINUS2_(...) \
|
|
PP_ARG_MINUS2_N(__VA_ARGS__)
|
|
|
|
#define PP_ARG_MINUS2_N(returnVal, #{generate_arg_sequence($MAX_ARGS, '_', false, ", ")}, N, ...) N
|
|
|
|
#define PP_RSEQ_N_MINUS2() \
|
|
#{generate_arg_sequence($MAX_ARGS, '', true, ',')}
|
|
|
|
|
|
#define PP_NARG_MINUS1(...) \
|
|
PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1())
|
|
|
|
#define PP_NARG_MINUS1_(...) \
|
|
PP_ARG_MINUS1_N(__VA_ARGS__)
|
|
|
|
#define PP_ARG_MINUS1_N(#{generate_arg_sequence($MAX_ARGS, '_', false, ", ")}, N, ...) N
|
|
|
|
#define PP_RSEQ_N_MINUS1() \
|
|
#{generate_arg_sequence($MAX_ARGS, '', true, ',')}
|
|
|
|
|
|
|
|
/* DECLARE AND DEFINE FAKE FUNCTIONS - PLACE IN TEST FILES */
|
|
|
|
#{counting_macro_instance(:VALUE)}
|
|
#{counting_macro_instance(:VOID)}
|
|
#{counting_macro_instance(:VALUE, :vararg)}
|
|
#{counting_macro_instance(:VOID, :vararg)}
|
|
|
|
/* DECLARE FAKE FUNCTIONS - PLACE IN HEADER FILES */
|
|
|
|
#{counting_macro_instance(:VALUE, :non_vararg, "DECLARE_")}
|
|
#{counting_macro_instance(:VOID, :non_vararg, "DECLARE_")}
|
|
#{counting_macro_instance(:VALUE, :vararg, "DECLARE_")}
|
|
#{counting_macro_instance(:VOID, :vararg, "DECLARE_")}
|
|
|
|
/* DEFINE FAKE FUNCTIONS - PLACE IN SOURCE FILES */
|
|
|
|
#{counting_macro_instance(:VALUE, :non_vararg, "DEFINE_")}
|
|
#{counting_macro_instance(:VOID, :non_vararg, "DEFINE_")}
|
|
#{counting_macro_instance(:VALUE, :vararg, "DEFINE_")}
|
|
#{counting_macro_instance(:VOID, :vararg, "DEFINE_")}
|
|
|
|
MACRO_COUNTING
|
|
end
|
|
|
|
def output_c_and_cpp
|
|
|
|
include_guard {
|
|
include_dependencies
|
|
output_constants
|
|
output_internal_helper_macros
|
|
yield
|
|
output_macro_counting_shortcuts
|
|
}
|
|
end
|
|
|
|
# lets generate!!
|
|
output_c_and_cpp{
|
|
define_fff_globals
|
|
# Create fake generators for 0..MAX_ARGS
|
|
num_fake_generators = $MAX_ARGS + 1
|
|
num_fake_generators.times {|arg_count| output_macro(arg_count, false, false)}
|
|
num_fake_generators.times {|arg_count| output_macro(arg_count, false, 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)}
|
|
}
|