//genMethods "-g" "-t" "Testobj*" "-I" "LINK/userobj/Testobj.h" "-d" "userobj" "-y" "display_testobjptr" "-m" "mark_testobjptr" "-w" "free_testobjptr" 
#include <stk.h>
#include <LINK/stkWrapper/LINK_STk.h>

#include <LINK/userobj/Testobj.h>

#include <LINK/stkWrapper/Wrapper.h>
#include <LINK/stkWrapper/Register.h>

void display_testobjptr(SCM, SCM, int);
void mark_testobjptr(SCM);
void free_testobjptr(SCM);

typedef Testobj* _Testobj_;

#define _Testobj_DATA(x) ((Testobj**) (EXTDATA(x)))
#define _Testobj_IS_DATA(x) (TYPEP(x, tc_CXXwrapper) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Testobj* >::type))
#define _Testobj_ISNT_DATA(x) (!_Testobj_IS_DATA(x))

#define _Testobj_CXX_DATA(x) (*(Testobj**) (EXTDATA(VAL(x))))
#define _Testobj_CXX_IS_DATA(x) (INSTANCEP(x) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Testobj* >::type))
#define _Testobj_CXX_ISNT_DATA(x) (!_Testobj_CXX_IS_DATA(x))

#include<strstream.h>

void display_testobjptr(SCM c, SCM port, int mode)
{
        ostrstream oss;
        if (*_Testobj_DATA(c))
        	oss << **_Testobj_DATA(c);
        oss << ends;
        char *buffer = oss.str();
        Puts(buffer, FILEPTR(port));
        delete buffer;
}

void mark_testobjptr(SCM p)
{
        //cout << "mark_testobjptr" << endl;
        Register<Testobj>::markEntry(*_Testobj_DATA(p));
}

void free_testobjptr(SCM p)
{
        //cout << "free_testobjptr" << endl;
        if (!EXTSTATICP(p)) {
                delete _Testobj_DATA(p);
        }
}

static PRIMITIVE MakeTestobjCmd(SCM num)
{
        Tcl_HashEntry *p;
        SCM objptr;
        Testobj *ap, **app;
        int not_found;

        if (NINTEGERP(num))
                Err("usage:  make-testobj <integer>", NIL);
        ap = new Testobj(INTEGER(num));
        //Register<Testobj>::createEntry(ap);
        Register<Testobj>::createEntry(Wrapper<Testobj>::type, 
				       Wrapper<Testobj>::name, ap);
        app = new Testobj *(ap);
        return STk_make_CXXwrapper(Wrapper<Testobj*>::type,
                        Wrapper<Testobj*>::name, (void *) app, LINK_DYNAMIC);
}

static PRIMITIVE eqvTestobj(SCM a, SCM b)
{
  if (Wrapper<Testobj*>::compareItems(a, b) == 0)
        return Truth;
  return Ntruth;
}

static PRIMITIVE lthTestobj(SCM a, SCM b)
{
  if (Wrapper<Testobj*>::compareItems(a, b) < 0)
        return Truth;
  return Ntruth;
}

static PRIMITIVE leTestobj(SCM a, SCM b)
{
  if (Wrapper<Testobj*>::compareItems(a, b) <= 0)
        return Truth;
  return Ntruth;
}

static PRIMITIVE grTestobj(SCM a, SCM b)
{
  if (Wrapper<Testobj*>::compareItems(a, b) > 0)
        return Truth;
  return Ntruth;
}

static PRIMITIVE geTestobj(SCM a, SCM b)
{
  if (Wrapper<Testobj*>::compareItems(a, b) >= 0)
        return Truth;
  return Ntruth;
}

static PRIMITIVE GetTestobjSize(SCM a)
{
  SCM z;
  struct stat *info;

  if (_Testobj_CXX_ISNT_DATA(a))
    Err("testobj-size: bad structure ", a);
  NEWCELL(z, tc_integer);
  SET_INTEGER(z, _Testobj_CXX_DATA(a)->current_size);
  return z;
}

static SCM TestobjpCmd(SCM ctr)
{
        return _Testobj_CXX_IS_DATA(ctr) ? Truth : Ntruth;
}

// define methods above, register below

void genExtra_Testobj_Methods() 
{
        STk_add_new_cpp_primitive("make-testobj", tc_subr_1,
                                        (PRIMITIVE (*)(...))MakeTestobjCmd);
        STk_add_new_cpp_primitive("testobj-eqv?", tc_subr_2,
                                        (PRIMITIVE (*)(...))eqvTestobj);
        STk_add_new_cpp_primitive("testobj-<", tc_subr_2,
                                        (PRIMITIVE (*)(...))lthTestobj);
        STk_add_new_cpp_primitive("testobj-<=", tc_subr_2,
                                        (PRIMITIVE (*)(...))leTestobj);
        STk_add_new_cpp_primitive("testobj->", tc_subr_2,
                                        (PRIMITIVE (*)(...))grTestobj);
        STk_add_new_cpp_primitive("testobj->=", tc_subr_2,
                                        (PRIMITIVE (*)(...))geTestobj);
        STk_add_new_cpp_primitive("testobj?", tc_subr_1,
                                        (PRIMITIVE (*)(...))TestobjpCmd);
        STk_add_new_cpp_primitive("size-testobj", tc_subr_1,
                                        (PRIMITIVE (*)(...))GetTestobjSize);
        addTwoArgMethod("eqv?", Wrapper<Testobj*>::name,
                        Wrapper<Testobj*>::name, "testobj-eqv?", LINK_OVL);
        addBooleanMethod("<",
                        Wrapper<Testobj*>::name, "testobj-<", LINK_OVL);
        addBooleanMethod("<=",
                        Wrapper<Testobj*>::name, "testobj-<=", LINK_OVL);
        addBooleanMethod(">",
                        Wrapper<Testobj*>::name, "testobj->", LINK_OVL);
        addBooleanMethod(">=",
                        Wrapper<Testobj*>::name, "testobj->=", LINK_OVL);
}

