Advertisement
enfiskutensykkel

Functional programming in C

Jun 11th, 2016
308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.24 KB | None | 0 0
  1. //let (^) x y = pown y x
  2. //
  3. //let fs = List.map
  4. //let f1 = (*) 2
  5. //let f2 = (^) 2
  6. //let fsf1 = fs f1
  7. //let fsf2 = fs f2
  8. //
  9. //printfn "%A" (fsf1 [0; 1; 2; 3])
  10. //printfn "%A" (fsf1 [2; 4; 6; 8])
  11. //printfn "%A" (fsf2 [0; 1; 2; 3])
  12. //printfn "%A" (fsf2 [2; 4; 6; 8])
  13.  
  14. #include <stdio.h>
  15. #include <stdint.h>
  16. #include <stdarg.h>
  17. #include <string.h>
  18. #include <sys/mman.h>
  19. #include <unistd.h>
  20.  
  21.  
  22. void __end();
  23. void __call(uintptr_t addr, size_t size, size_t nmemb, const void* in, void* out)
  24. {
  25.     uintptr_t offs = ((uintptr_t) &__end) - ((uintptr_t) &__call);
  26.     uintptr_t func = *((uintptr_t*) (addr + offs));
  27.     uintptr_t data = *((uintptr_t*) (addr + offs + sizeof(uintptr_t)));
  28.  
  29.     ((void (*)(void*, size_t, size_t, const void*, void*)) func) ((void*) data, size, nmemb, in, out);
  30. }
  31. void __end() {}
  32.  
  33.  
  34. void* bind(uintptr_t func, void* data)
  35. {
  36.     size_t page_size = getpagesize(); // assumes that the size of __call is less than a page
  37.  
  38.     char* ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
  39.     if (ptr == NULL)
  40.     {
  41.         perror("mmap");
  42.         return NULL;
  43.     }
  44.  
  45.     size_t func_size = ((uintptr_t) &__end) - ((uintptr_t) &__call);
  46.     uintptr_t func_addr = (uintptr_t) &__call;
  47.  
  48.     memcpy(ptr, (const void*) func_addr, func_size);
  49.     *((uintptr_t*) (ptr + func_size)) = func;
  50.     *((uintptr_t*) (ptr + func_size + sizeof(uintptr_t))) = (uintptr_t) data;
  51.  
  52.     return ptr;
  53. }
  54.  
  55.  
  56. void unbind(void* bound)
  57. {
  58.     munmap(bound, getpagesize());
  59. }
  60.  
  61.  
  62. void call(void* bound, size_t size, size_t nmemb, const void* in, void* out)
  63. {
  64.     uintptr_t func = (uintptr_t) bound;
  65.     ((void (*)(uintptr_t, size_t, size_t, const void*, void*)) func) (func, size, nmemb, in, out);
  66. }
  67.  
  68.  
  69. void map(uintptr_t func, size_t size, size_t nmemb, const void* in, void* out)
  70. {
  71.     if (nmemb > 0)
  72.     {
  73.         ((void (*)(size_t, const void*, void*)) func)(size, in, out);
  74.  
  75.         map(func, size, nmemb - 1, ((const char*) in) + size, ((char*) out) + size);
  76.     }
  77. }
  78.  
  79.  
  80. void f1(size_t size, const void* in, void* out)
  81. {
  82.     int* x = (int*) out;
  83.     *x = *((const int*) in) * 2;
  84. }
  85.  
  86.  
  87. void f2(size_t size, const void* in, void* out)
  88. {
  89.     const int* x = (const int*) in;
  90.     *((int*) out) = *x * *x;
  91. }
  92.  
  93.  
  94. void print(int* list)
  95. {
  96.     // HACK: pass 4 to function somehow, maybe as an additional arg to bind
  97.     printf("[%d", list[0]);
  98.     for (int i = 1; i < 4; ++i)
  99.     {
  100.         printf("; %d", list[i]);
  101.     }
  102.     printf("]\n");
  103. }
  104.  
  105.  
  106. int main()
  107. {
  108.     int list_lo[] = {0, 1, 2, 3};
  109.     int list_hi[] = {2, 4, 6, 8};
  110.     int result[4];
  111.  
  112.     void* print_result = bind((uintptr_t) &print, result);
  113.  
  114.     uintptr_t fs = (uintptr_t) &map;
  115.     void* fsf1 = bind(fs, (void*) &f1);
  116.     void* fsf2 = bind(fs, (void*) &f2);
  117.  
  118.     call(fsf1, sizeof(int), 4, list_lo, result);
  119.     call(print_result, 0, 0, NULL, NULL);
  120.  
  121.     call(fsf1, sizeof(int), 4, list_hi, result);
  122.     call(print_result, 0, 0, NULL, NULL);
  123.  
  124.     call(fsf2, sizeof(int), 4, list_lo, result);
  125.     call(print_result, 0, 0, NULL, NULL);
  126.  
  127.     call(fsf2, sizeof(int), 4, list_hi, result);
  128.     call(print_result, 0, 0, NULL, NULL);
  129.  
  130.     unbind(print_result);
  131.     unbind(fsf1);
  132.     unbind(fsf2);
  133.  
  134.     return 0;
  135. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement