spacepaste

  1.  
  2. #include <alloca.h>
  3. #include <assert.h>
  4. #include <stdarg.h>
  5. #include <stdbool.h>
  6. #include <stdio.h>
  7. #include <ffi.h>
  8. void rt_3addiii(int *res, int a, int b)
  9. {
  10. *res = a + b;
  11. }
  12. void rt_3subiii(int *res, int a, int b)
  13. {
  14. *res = a - b;
  15. }
  16. void rt_2eqbii(bool *res, int a, int b)
  17. {
  18. *res = a == b;
  19. }
  20. void rt_2if(bool test, ...)
  21. {
  22. va_list args;
  23. va_start(args, test);
  24. if (!test)
  25. {
  26. int num_skip = va_arg(args, int);
  27. for (int i = 0; i < num_skip; i++)
  28. {
  29. (void) va_arg(args, ffi_type*);
  30. (void) va_arg(args, void*);
  31. }
  32. va_arg(args, void(*)());
  33. }
  34. int num_args = va_arg(args, int);
  35. ffi_cif cif;
  36. ffi_arg ret;
  37. ffi_type **types = alloca(sizeof(ffi_type*) * num_args);
  38. void **values = alloca(sizeof(void(*)()) * num_args);
  39. for (int i = 0; i < num_args; i++)
  40. {
  41. types[i] = va_arg(args, ffi_type*);
  42. values[i] = va_arg(args, void*);
  43. }
  44. void (*fun)() = va_arg(args, void*);
  45. ffi_status result = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, num_args, &ffi_type_void, types);
  46. assert(result == FFI_OK);
  47. ffi_call(&cif, fun, &ret, values);
  48. }
  49. int zero = 0;
  50. int one = 1;
  51. void ack(int *res, int m, int n);
  52. void ack_ret2(int *res, int m)
  53. {
  54. int temp;
  55. rt_3subiii(&temp, m, one);
  56. ack(res, temp, one);
  57. }
  58. void ack_rest2(int *res, int m, int n)
  59. {
  60. int temp1, temp2, temp3;
  61. rt_3subiii(&temp1, n, one);
  62. ack(&temp2, m, temp1);
  63. rt_3subiii(&temp3, m, one);
  64. ack(res, temp3, temp2);
  65. }
  66. void ack_ret1(int *res, int n)
  67. {
  68. rt_3addiii(res, n, one);
  69. }
  70. void ack_rest1(int *res, int m, int n)
  71. {
  72. bool temp;
  73. rt_2eqbii(&temp, n, zero);
  74. rt_2if(temp,
  75. 2, &ffi_type_pointer, &res, &ffi_type_sint32, &m, &ack_ret2,
  76. 3, &ffi_type_pointer, &res, &ffi_type_sint32, &m, &ffi_type_sint32, &n, &ack_rest2
  77. );
  78. }
  79. void ack(int *res, int m, int n)
  80. {
  81. bool temp;
  82. rt_2eqbii(&temp, m, zero);
  83. rt_2if(temp,
  84. 2, &ffi_type_pointer, &res, &ffi_type_sint32, &n, &ack_ret1,
  85. 3, &ffi_type_pointer, &res, &ffi_type_sint32, &m, &ffi_type_sint32, &n, &ack_rest1
  86. );
  87. }
  88. int wrap_ack(int m, int n)
  89. {
  90. int res;
  91. ack(&res, m, n);
  92. return res;
  93. }
  94. int main(int argc, const char *argv[])
  95. {
  96. for (int i = 0; i < 10; ++i)
  97. {
  98. printf("ack(3, 7) = %i\n", wrap_ack(3, 7));
  99. }
  100. }
  101.