/include/CaptainHook/CaptainHook.h

https://bitbucket.org/iamchadcary/iosopendev · C Header · 550 lines · 520 code · 17 blank · 13 comment · 13 complexity · 00ec524e6adbd2f0bc3545751b92067c MD5 · raw file

  1. // Possible defines:
  2. // CHDebug if defined, CHDebugLog is equivalent to CHLog; else, emits no code
  3. // CHUseSubstrate if defined, uses MSMessageHookEx to hook methods, otherwise uses internal hooking routines. Warning! super call closures are only available on ARM platforms for recent releases of MobileSubstrate
  4. // CHEnableProfiling if defined, enables calls to CHProfileScope()
  5. // CHAppName should be set to the name of the application (if not, defaults to "CaptainHook"); used for logging and profiling
  6. #import <objc/runtime.h>
  7. #import <objc/message.h>
  8. #import <Foundation/NSObject.h>
  9. #import <Foundation/NSObjCRuntime.h>
  10. #ifndef CHAppName
  11. #define CHAppName "CaptainHook"
  12. #endif
  13. #ifdef __clang__
  14. #if __has_feature(objc_arc)
  15. #define CHHasARC
  16. #endif
  17. #endif
  18. // Some Debugging/Logging Commands
  19. #define CHStringify_(x) #x
  20. #define CHStringify(x) CHStringify_(x)
  21. #define CHConcat_(a, b) a ## b
  22. #define CHConcat(a, b) CHConcat_(a, b)
  23. #define CHNothing() do { } while(0)
  24. #define CHLocationInSource [NSString stringWithFormat:@CHStringify(__LINE__) " in %s", __FUNCTION__]
  25. #define CHLog(args...) NSLog(@CHAppName ": %@", [NSString stringWithFormat:args])
  26. #define CHLogSource(args...) NSLog(@CHAppName " @ " CHStringify(__LINE__) " in %s: %@", __FUNCTION__, [NSString stringWithFormat:args])
  27. #ifdef CHDebug
  28. #define CHDebugLog(args...) CHLog(args)
  29. #define CHDebugLogSource(args...) CHLogSource(args)
  30. #else
  31. #define CHDebugLog(args...) CHNothing()
  32. #define CHDebugLogSource(args...) CHNothing()
  33. #endif
  34. // Constructor
  35. #define CHConstructor static __attribute__((constructor)) void CHConcat(CHConstructor, __LINE__)()
  36. #define CHInline inline __attribute__((always_inline))
  37. // Cached Class Declaration (allows hooking methods, and fast lookup of classes)
  38. struct CHClassDeclaration_ {
  39. Class class_;
  40. Class metaClass_;
  41. Class superClass_;
  42. };
  43. typedef struct CHClassDeclaration_ CHClassDeclaration_;
  44. #define CHDeclareClass(name) \
  45. @class name; \
  46. static CHClassDeclaration_ name ## $;
  47. // Loading Cached Classes (use CHLoadClass when class is linkable, CHLoadLateClass when it isn't)
  48. static inline Class CHLoadClass_(CHClassDeclaration_ *declaration, Class value)
  49. {
  50. declaration->class_ = value;
  51. declaration->metaClass_ = object_getClass(value);
  52. declaration->superClass_ = class_getSuperclass(value);
  53. return value;
  54. }
  55. #define CHLoadLateClass(name) CHLoadClass_(&name ## $, objc_getClass(#name))
  56. #define CHLoadClass(name) CHLoadClass_(&name ## $, [name class])
  57. // Quick Lookup of cached classes, and common methods on them
  58. #define CHClass(name) name ## $.class_
  59. #define CHMetaClass(name) name ## $.metaClass_
  60. #define CHSuperClass(name) name ## $.superClass_
  61. #define CHAlloc(name) ((name *)[CHClass(name) alloc])
  62. #define CHSharedInstance(name) ((name *)[CHClass(name) sharedInstance])
  63. #define CHIsClass(obj, name) [obj isKindOfClass:CHClass(name)]
  64. #define CHRespondsTo(obj, sel) [obj respondsToSelector:@selector(sel)]
  65. // Replacement Method Definition
  66. #define CHDeclareSig0_(return_type) \
  67. const char *return_ = @encode(return_type); \
  68. size_t return_len = __builtin_strlen(return_); \
  69. char sig[return_len+2]; \
  70. __builtin_memcpy(sig, return_, return_len); \
  71. sig[return_len] = _C_ID; \
  72. sig[return_len+1] = _C_SEL; \
  73. sig[return_len+2] = '\0';
  74. #define CHDeclareSig1_(return_type, type1) \
  75. const char *return_ = @encode(return_type); \
  76. size_t return_len = __builtin_strlen(return_); \
  77. const char *type1_ = @encode(type1); \
  78. size_t type1_len = __builtin_strlen(type1_); \
  79. char sig[return_len+2+type1_len]; \
  80. __builtin_memcpy(sig, return_, return_len); \
  81. sig[return_len] = _C_ID; \
  82. sig[return_len+1] = _C_SEL; \
  83. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  84. sig[return_len+type1_len+2] = '\0';
  85. #define CHDeclareSig2_(return_type, type1, type2) \
  86. const char *return_ = @encode(return_type); \
  87. size_t return_len = __builtin_strlen(return_); \
  88. const char *type1_ = @encode(type1); \
  89. size_t type1_len = __builtin_strlen(type1_); \
  90. const char *type2_ = @encode(type2); \
  91. size_t type2_len = __builtin_strlen(type2_); \
  92. char sig[return_len+2+type1_len+type2_len]; \
  93. __builtin_memcpy(sig, return_, return_len); \
  94. sig[return_len] = _C_ID; \
  95. sig[return_len+1] = _C_SEL; \
  96. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  97. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  98. sig[return_len+type1_len+type2_len+2] = '\0';
  99. #define CHDeclareSig3_(return_type, type1, type2, type3) \
  100. const char *return_ = @encode(return_type); \
  101. size_t return_len = __builtin_strlen(return_); \
  102. const char *type1_ = @encode(type1); \
  103. size_t type1_len = __builtin_strlen(type1_); \
  104. const char *type2_ = @encode(type2); \
  105. size_t type2_len = __builtin_strlen(type2_); \
  106. const char *type3_ = @encode(type3); \
  107. size_t type3_len = __builtin_strlen(type3_); \
  108. char sig[return_len+2+type1_len+type2_len+type3_len]; \
  109. __builtin_memcpy(sig, return_, return_len); \
  110. sig[return_len] = _C_ID; \
  111. sig[return_len+1] = _C_SEL; \
  112. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  113. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  114. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  115. sig[return_len+type1_len+type2_len+type3_len+2] = '\0';
  116. #define CHDeclareSig4_(return_type, type1, type2, type3, type4) \
  117. const char *return_ = @encode(return_type); \
  118. size_t return_len = __builtin_strlen(return_); \
  119. const char *type1_ = @encode(type1); \
  120. size_t type1_len = __builtin_strlen(type1_); \
  121. const char *type2_ = @encode(type2); \
  122. size_t type2_len = __builtin_strlen(type2_); \
  123. const char *type3_ = @encode(type3); \
  124. size_t type3_len = __builtin_strlen(type3_); \
  125. const char *type4_ = @encode(type4); \
  126. size_t type4_len = __builtin_strlen(type4_); \
  127. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len]; \
  128. __builtin_memcpy(sig, return_, return_len); \
  129. sig[return_len] = _C_ID; \
  130. sig[return_len+1] = _C_SEL; \
  131. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  132. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  133. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  134. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  135. sig[return_len+type1_len+type2_len+type3_len+type4_len+2] = '\0';
  136. #define CHDeclareSig5_(return_type, type1, type2, type3, type4, type5) \
  137. const char *return_ = @encode(return_type); \
  138. size_t return_len = __builtin_strlen(return_); \
  139. const char *type1_ = @encode(type1); \
  140. size_t type1_len = __builtin_strlen(type1_); \
  141. const char *type2_ = @encode(type2); \
  142. size_t type2_len = __builtin_strlen(type2_); \
  143. const char *type3_ = @encode(type3); \
  144. size_t type3_len = __builtin_strlen(type3_); \
  145. const char *type4_ = @encode(type4); \
  146. size_t type4_len = __builtin_strlen(type4_); \
  147. const char *type5_ = @encode(type5); \
  148. size_t type5_len = __builtin_strlen(type5_); \
  149. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len]; \
  150. __builtin_memcpy(sig, return_, return_len); \
  151. sig[return_len] = _C_ID; \
  152. sig[return_len+1] = _C_SEL; \
  153. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  154. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  155. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  156. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  157. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  158. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+2] = '\0';
  159. #define CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6) \
  160. const char *return_ = @encode(return_type); \
  161. size_t return_len = __builtin_strlen(return_); \
  162. const char *type1_ = @encode(type1); \
  163. size_t type1_len = __builtin_strlen(type1_); \
  164. const char *type2_ = @encode(type2); \
  165. size_t type2_len = __builtin_strlen(type2_); \
  166. const char *type3_ = @encode(type3); \
  167. size_t type3_len = __builtin_strlen(type3_); \
  168. const char *type4_ = @encode(type4); \
  169. size_t type4_len = __builtin_strlen(type4_); \
  170. const char *type5_ = @encode(type5); \
  171. size_t type5_len = __builtin_strlen(type5_); \
  172. const char *type6_ = @encode(type6); \
  173. size_t type6_len = __builtin_strlen(type6_); \
  174. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len]; \
  175. __builtin_memcpy(sig, return_, return_len); \
  176. sig[return_len] = _C_ID; \
  177. sig[return_len+1] = _C_SEL; \
  178. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  179. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  180. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  181. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  182. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  183. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \
  184. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+2] = '\0';
  185. #define CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7) \
  186. const char *return_ = @encode(return_type); \
  187. size_t return_len = __builtin_strlen(return_); \
  188. const char *type1_ = @encode(type1); \
  189. size_t type1_len = __builtin_strlen(type1_); \
  190. const char *type2_ = @encode(type2); \
  191. size_t type2_len = __builtin_strlen(type2_); \
  192. const char *type3_ = @encode(type3); \
  193. size_t type3_len = __builtin_strlen(type3_); \
  194. const char *type4_ = @encode(type4); \
  195. size_t type4_len = __builtin_strlen(type4_); \
  196. const char *type5_ = @encode(type5); \
  197. size_t type5_len = __builtin_strlen(type5_); \
  198. const char *type6_ = @encode(type6); \
  199. size_t type6_len = __builtin_strlen(type6_); \
  200. const char *type7_ = @encode(type7); \
  201. size_t type7_len = __builtin_strlen(type7_); \
  202. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len]; \
  203. __builtin_memcpy(sig, return_, return_len); \
  204. sig[return_len] = _C_ID; \
  205. sig[return_len+1] = _C_SEL; \
  206. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  207. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  208. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  209. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  210. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  211. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \
  212. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \
  213. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+2] = '\0';
  214. #define CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8) \
  215. const char *return_ = @encode(return_type); \
  216. size_t return_len = __builtin_strlen(return_); \
  217. const char *type1_ = @encode(type1); \
  218. size_t type1_len = __builtin_strlen(type1_); \
  219. const char *type2_ = @encode(type2); \
  220. size_t type2_len = __builtin_strlen(type2_); \
  221. const char *type3_ = @encode(type3); \
  222. size_t type3_len = __builtin_strlen(type3_); \
  223. const char *type4_ = @encode(type4); \
  224. size_t type4_len = __builtin_strlen(type4_); \
  225. const char *type5_ = @encode(type5); \
  226. size_t type5_len = __builtin_strlen(type5_); \
  227. const char *type6_ = @encode(type6); \
  228. size_t type6_len = __builtin_strlen(type6_); \
  229. const char *type7_ = @encode(type7); \
  230. size_t type7_len = __builtin_strlen(type7_); \
  231. const char *type8_ = @encode(type8); \
  232. size_t type8_len = __builtin_strlen(type8_); \
  233. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len]; \
  234. __builtin_memcpy(sig, return_, return_len); \
  235. sig[return_len] = _C_ID; \
  236. sig[return_len+1] = _C_SEL; \
  237. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  238. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  239. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  240. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  241. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  242. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \
  243. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \
  244. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len], type8_, type8_len); \
  245. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+2] = '\0';
  246. #define CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9) \
  247. const char *return_ = @encode(return_type); \
  248. size_t return_len = __builtin_strlen(return_); \
  249. const char *type1_ = @encode(type1); \
  250. size_t type1_len = __builtin_strlen(type1_); \
  251. const char *type2_ = @encode(type2); \
  252. size_t type2_len = __builtin_strlen(type2_); \
  253. const char *type3_ = @encode(type3); \
  254. size_t type3_len = __builtin_strlen(type3_); \
  255. const char *type4_ = @encode(type4); \
  256. size_t type4_len = __builtin_strlen(type4_); \
  257. const char *type5_ = @encode(type5); \
  258. size_t type5_len = __builtin_strlen(type5_); \
  259. const char *type6_ = @encode(type6); \
  260. size_t type6_len = __builtin_strlen(type6_); \
  261. const char *type7_ = @encode(type7); \
  262. size_t type7_len = __builtin_strlen(type7_); \
  263. const char *type8_ = @encode(type8); \
  264. size_t type8_len = __builtin_strlen(type8_); \
  265. const char *type9_ = @encode(type9); \
  266. size_t type9_len = __builtin_strlen(type9_); \
  267. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+type9_len]; \
  268. __builtin_memcpy(sig, return_, return_len); \
  269. sig[return_len] = _C_ID; \
  270. sig[return_len+1] = _C_SEL; \
  271. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  272. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  273. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  274. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  275. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  276. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \
  277. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \
  278. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len], type8_, type8_len); \
  279. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len], type9_, type9_len); \
  280. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+type9_len+2] = '\0';
  281. #ifdef CHUseSubstrate
  282. #import <substrate.h>
  283. #define CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  284. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  285. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  286. __attribute__((always_inline)) \
  287. static inline void $ ## class_name ## _ ## name ## _register() { \
  288. if (class_val) { \
  289. MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \
  290. if (!$ ## class_name ## _ ## name ## _super) { \
  291. sigdef; \
  292. class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \
  293. } \
  294. } \
  295. } \
  296. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  297. #define CHMethod_new_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  298. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  299. __attribute__((always_inline)) \
  300. static inline void $ ## class_name ## _ ## name ## _register() { \
  301. sigdef; \
  302. class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \
  303. } \
  304. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  305. #define CHMethod_super_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  306. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  307. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  308. __attribute__((always_inline)) \
  309. static inline void $ ## class_name ## _ ## name ## _register() { \
  310. if (class_val) { \
  311. MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \
  312. } \
  313. } \
  314. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  315. #define CHMethod_self_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  316. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  317. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  318. __attribute__((always_inline)) \
  319. static inline void $ ## class_name ## _ ## name ## _register() { \
  320. if (class_val) { \
  321. MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \
  322. } \
  323. } \
  324. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  325. #else
  326. #define CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  327. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  328. static return_type $ ## class_name ## _ ## name ## _closure(class_type self, SEL _cmd, ##args) { \
  329. typedef return_type (*supType)(class_type, SEL, ## args); \
  330. supType supFn = (supType)class_getMethodImplementation(super_class_val, _cmd); \
  331. return supFn supercall; \
  332. } \
  333. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  334. __attribute__((always_inline)) \
  335. static inline void $ ## class_name ## _ ## name ## _register() { \
  336. Method method = class_getInstanceMethod(class_val, @selector(sel)); \
  337. if (method) { \
  338. $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \
  339. if (class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, method_getTypeEncoding(method))) { \
  340. $ ## class_name ## _ ## name ## _super = &$ ## class_name ## _ ## name ## _closure; \
  341. } else { \
  342. method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \
  343. } \
  344. } else { \
  345. sigdef; \
  346. class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \
  347. } \
  348. } \
  349. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  350. #define CHMethod_new_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  351. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  352. __attribute__((always_inline)) \
  353. static inline void $ ## class_name ## _ ## name ## _register() { \
  354. sigdef; \
  355. class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \
  356. } \
  357. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  358. #define CHMethod_super_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  359. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  360. static return_type $ ## class_name ## _ ## name ## _closure(class_type self, SEL _cmd, ##args) { \
  361. typedef return_type (*supType)(class_type, SEL, ## args); \
  362. supType supFn = (supType)class_getMethodImplementation(super_class_val, _cmd); \
  363. return supFn supercall; \
  364. } \
  365. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  366. __attribute__((always_inline)) \
  367. static inline void $ ## class_name ## _ ## name ## _register() { \
  368. Method method = class_getInstanceMethod(class_val, @selector(sel)); \
  369. if (method) { \
  370. $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \
  371. if (class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, method_getTypeEncoding(method))) { \
  372. $ ## class_name ## _ ## name ## _super = &$ ## class_name ## _ ## name ## _closure; \
  373. } else { \
  374. method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \
  375. } \
  376. } \
  377. } \
  378. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  379. #define CHMethod_self_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  380. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  381. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  382. __attribute__((always_inline)) \
  383. static inline void $ ## class_name ## _ ## name ## _register() { \
  384. Method method = class_getInstanceMethod(class_val, @selector(sel)); \
  385. if (method) { \
  386. $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \
  387. method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \
  388. } \
  389. } \
  390. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  391. #endif
  392. #define CHMethod(count, args...) \
  393. CHMethod ## count(args)
  394. #define CHMethod0(return_type, class_type, name) \
  395. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  396. #define CHMethod1(return_type, class_type, name1, type1, arg1) \
  397. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  398. #define CHMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  399. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  400. #define CHMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  401. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  402. #define CHMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  403. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  404. #define CHMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  405. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  406. #define CHMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  407. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  408. #define CHMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  409. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  410. #define CHMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  411. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  412. #define CHMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  413. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  414. #define CHClassMethod(count, args...) \
  415. CHClassMethod ## count(args)
  416. #define CHClassMethod0(return_type, class_type, name) \
  417. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  418. #define CHClassMethod1(return_type, class_type, name1, type1, arg1) \
  419. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  420. #define CHClassMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  421. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  422. #define CHClassMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  423. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  424. #define CHClassMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  425. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  426. #define CHClassMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  427. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  428. #define CHClassMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  429. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  430. #define CHClassMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  431. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  432. #define CHClassMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  433. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  434. #define CHClassMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  435. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  436. #define CHOptimizedMethod(count, args...) \
  437. CHOptimizedMethod ## count(args)
  438. #define CHOptimizedMethod0(optimization, return_type, class_type, name) \
  439. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  440. #define CHOptimizedMethod1(optimization, return_type, class_type, name1, type1, arg1) \
  441. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  442. #define CHOptimizedMethod2(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  443. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  444. #define CHOptimizedMethod3(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  445. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  446. #define CHOptimizedMethod4(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  447. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  448. #define CHOptimizedMethod5(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  449. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  450. #define CHOptimizedMethod6(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  451. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  452. #define CHOptimizedMethod7(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  453. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  454. #define CHOptimizedMethod8(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  455. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  456. #define CHOptimizedMethod9(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  457. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  458. #define CHOptimizedClassMethod(count, args...) \
  459. CHOptimizedClassMethod ## count(args)
  460. #define CHOptimizedClassMethod0(optimization, return_type, class_type, name) \
  461. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  462. #define CHOptimizedClassMethod1(optimization, return_type, class_type, name1, type1, arg1) \
  463. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  464. #define CHOptimizedClassMethod2(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  465. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  466. #define CHOptimizedClassMethod3(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  467. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  468. #define CHOptimizedClassMethod4(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  469. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  470. #define CHOptimizedClassMethod5(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  471. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  472. #define CHOptimizedClassMethod6(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  473. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  474. #define CHOptimizedClassMethod7(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  475. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  476. #define CHOptimizedClassMethod8(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  477. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  478. #define CHOptimizedClassMethod9(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  479. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  480. // Replacement Method Registration
  481. #define CHHook_(class_name, name) \
  482. $ ## class_name ## _ ## name ## _register()
  483. #define CHHook(count, args...) CHHook ## count(args)
  484. #define CHHook0(class, name) CHHook_(class, name)
  485. #define CHHook1(class, name1) CHHook_(class, name1 ## $)
  486. #define CHHook2(class, name1, name2) CHHook_(class, name1 ## $ ## name2 ## $)
  487. #define CHHook3(class, name1, name2, name3) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $)
  488. #define CHHook4(class, name1, name2, name3, name4) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $)
  489. #define CHHook5(class, name1, name2, name3, name4, name5) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $)
  490. #define CHHook6(class, name1, name2, name3, name4, name5, name6) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $)
  491. #define CHHook7(class, name1, name2, name3, name4, name5, name6, name7) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $)
  492. #define CHHook8(class, name1, name2, name3, name4, name5, name6, name7, name8) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $)
  493. #define CHHook9(class, name1, name2, name3, name4, name5, name6, name7, name8, name9) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $)
  494. #define CHClassHook(count, args...) CHClassHook ## count(args)
  495. #define CHClassHook0(class, name) CHHook_(class, name)
  496. #define CHClassHook1(class, name1) CHHook_(class, name1 ## $)
  497. #define CHClassHook2(class, name1, name2) CHHook_(class, name1 ## $ ## name2 ## $)
  498. #define CHClassHook3(class, name1, name2, name3) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $)
  499. #define CHClassHook4(class, name1, name2, name3, name4) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $)
  500. #define CHClassHook5(class, name1, name2, name3, name4, name5) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $)
  501. #define CHClassHook6(class, name1, name2, name3, name4, name5, name6) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $)
  502. #define CHClassHook7(class, name1, name2, name3, name4, name5, name6, name7) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $)
  503. #define CHClassHook8(class, name1, name2, name3, name4, name5, name6, name7, name8) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $)
  504. #define CHClassHook9(class, name1, name2, name3, name4, name5, name6, name7, name8, name9) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $)
  505. // Declarative style methods (automatically calls CHHook)
  506. #define CHDeclareMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  507. static inline void $ ## class_name ## _ ## name ## _register(); \
  508. __attribute__((constructor)) \
  509. static inline void $ ## class_name ## _ ## name ## _constructor() { \
  510. CHLoadLateClass(class_name); \
  511. $ ## class_name ## _ ## name ## _register(); \
  512. } \
  513. CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, ##args)
  514. #define CHDeclareMethod(count, args...) \
  515. CHDeclareMethod ## count(args)
  516. #define CHDeclareMethod0(return_type, class_type, name) \
  517. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  518. #define CHDeclareMethod1(return_type, class_type, name1, type1, arg1) \
  519. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  520. #define CHDeclareMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  521. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  522. #define CHDeclareMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  523. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  524. #define CHDeclareMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  525. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  526. #define CHDeclareMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  527. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## arg5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  528. #define CHDeclareMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  529. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  530. #define CHDeclareMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  531. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  532. #define CHDeclareMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  533. CHDeclareMethod_(return_type, class_typ