/* Copyright (c) 2001-2009 by SoftIntegration, Inc. All Rights Reserved */
#include <stdio.h>
#include "ptfun1_2_c.h" 
#include <ch.h>

/* The maximum number of ptfun1_2_setHandle()
   can be called */ 
#define MAXNUM   3

/* C functions to replace the Ch one */ 
static ChInterp_t interp;
static void (*ptfun1_2_chdl_funarg[MAXNUM])();

/* function pointers to save Ch function pointers */
static void *ptfun1_2_chdl_funptr[MAXNUM]; 

/* index of pointer pairs, from 0 to MAXNUM-1 */
static int index = 0;   

EXPORTCH int ptfun1_2_setHandle_chdl(void *varg){
  int i;
  ChVaList_t ap;
  int id;
  funcHandle handle_ch, handle_c;
  int retval;

  Ch_VaStart(interp, ap, varg);
  id = Ch_VaArg(interp, ap, int);         
  handle_ch = Ch_VaArg(interp, ap, funcHandle);   

  if(handle_ch == NULL) {
    handle_c = NULL;
  }
  else {
    if(index == MAXNUM) {
      printf("Error: Only %d function pointers can be set\n", MAXNUM);
      return -1;
    }
    ptfun1_2_chdl_funptr[index] = (void *)handle_ch;
    handle_c = ptfun1_2_chdl_funarg[index];
    index++;
  }

  printf("in ptfun1_2_setHandle_chdl():\nCh function pointer %p is \
replaced by C function pointer %p\n\n", handle_ch, handle_c);
  retval = ptfun1_2_setHandle(id, handle_c);

  Ch_VaEnd(interp, ap);
  return retval;
}

EXPORTCH funcHandle ptfun1_2_getHandle_chdl(void *varg){
  int i;
  ChVaList_t ap;
  int id;
  funcHandle retval_c = NULL, retval_ch = NULL;

  Ch_VaStart(interp, ap, varg);
  id = Ch_VaArg(interp, ap, int);         

  retval_c = ptfun1_2_getHandle(id);

  /* replace C pointer with corresponding Ch function pointer */
  if(retval_c == NULL)  {
    retval_ch = NULL;
  }
  else {
    for(i = 0; i < index; i++) {
      if(ptfun1_2_chdl_funarg[i] == retval_c) {
        retval_ch = (funcHandle)ptfun1_2_chdl_funptr[i];
      }
    }
  }
  Ch_VaEnd(interp, ap);
  printf("in ptfun1_2_getHandle_chdl():\nC function pointer %p is \
replaced by Ch function pointer %p\n", retval_c, retval_ch);
  return retval_ch;
}

/**** C functions to replace Ch callback functions ****/

static void ptfun1_2_chdl_funarg0() {
  Ch_CallFuncByAddr(interp, ptfun1_2_chdl_funptr[0], NULL);
}

static void ptfun1_2_chdl_funarg1() {
  Ch_CallFuncByAddr(interp, ptfun1_2_chdl_funptr[1], NULL);
}

static void ptfun1_2_chdl_funarg2() {
  Ch_CallFuncByAddr(interp, ptfun1_2_chdl_funptr[2], NULL);
}

/********* initialization routine called in ptfun1_2.h **********/
EXPORTCH int ptfun1_2_setgetHandles_init() {
  /* from 0 to MAXNUM -1 */

   ptfun1_2_chdl_funarg[0] = ptfun1_2_chdl_funarg0;
   ptfun1_2_chdl_funarg[1] = ptfun1_2_chdl_funarg1;
   ptfun1_2_chdl_funarg[2] = ptfun1_2_chdl_funarg2;

   return 0;
}
