#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

// PRIMARY FFI
# ifndef NOSYM
typedef struct {
  int numargs;
  int args[10];
}ffi_group;

int ffi_init() {
  ffi_group* f = (ffi_group*)malloc(sizeof(ffi_group));
  return (int)f;
}

void set_arg_count(int id, int count) {
  ffi_group* f = (ffi_group*)id;
  f->numargs = count;
}

void set_arg(int id, int argnum, int val) {
  ffi_group* f = (ffi_group*)id;
  f->args[argnum] = val;
}

int call(int id, char* funname) {
  void* fun;
  int retval=0;
  int isfix=0;
  char* c;
  ffi_group* f = (ffi_group*)id;

  fun = dlsym(NULL,funname);
  if (fun == NULL) {
    printf("Function %s did not initialize. Aborting.\n",funname);
    exit(3);
  }
  switch(f->numargs) {
  case 0:
    retval = ((int (*)())fun)();
    break;
  case 1:
    retval = ((int (*)(int))fun)(f->args[0]);
    break;
  case 2:
    retval = ((int (*)(int,int))fun)(f->args[0],f->args[1]);
    break;
  case 3:
    retval = ((int (*)(int,int,int))fun)(f->args[0],f->args[1],f->args[2]);
    break;
  case 4:
    retval = ((int (*)(int,int,int,int))fun)(f->args[0],f->args[1],f->args[2],f->args[3]);
    break;
  case 5:
    retval = ((int (*)(int,int,int,int,int))fun)(f->args[0],f->args[1],f->args[2],f->args[3],f->args[4]);
    break;
  case 6:
    retval = ((int (*)(int,int,int,int,int,int))fun)(f->args[0],f->args[1],f->args[2],f->args[3],f->args[4],f->args[5]);
    break;
  }
  free(f);
  return retval;
}
#endif

// END OF PRIMARY FFI

// SPECIAL STUFF

int begin_string() {
  unsigned char *str;
  str = (unsigned char*)malloc(100 * sizeof(unsigned char));
  str[0] = '\0';
}

void add_string(int s, int ch) {
  int len;
  unsigned char* str = (unsigned char*)s;
  len = strlen(str);
  str[len] = (unsigned char)ch;
  str[len+1] = '\0';
}

void stop_string(int s) {
  free((unsigned char*)s);
}






