/*
 * This file was generated automatically by xsubpp version 1.938 from the 
 * contents of ODBM_File.xs. Do not edit this file, edit ODBM_File.xs instead.
 *
 *	ANY CHANGES MADE HERE WILL BE LOST! 
 *
 */

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#ifdef NULL
#undef NULL
#endif
#ifdef I_DBM
#  include <dbm.h>
#else
#  ifdef I_RPCSVC_DBM
#    include <rpcsvc/dbm.h>
#  endif
#endif

#ifdef DBM_BUG_DUPLICATE_FREE 
/*
 * DBM on at least Ultrix and HPUX call dbmclose() from dbminit(),
 * resulting in duplicate free() because dbmclose() does *not*
 * check if it has already been called for this DBM.
 * If some malloc/free calls have been done between dbmclose() and
 * the next dbminit(), the memory might be used for something else when
 * it is freed.
 * Verified to work on ultrix4.3.  Probably will work on HP/UX.
 * Set DBM_BUG_DUPLICATE_FREE in the extension hint file.
 */
/* Close the previous dbm, and fail to open a new dbm */
#define dbmclose()	((void) dbminit("/tmp/x/y/z/z/y"))
#endif

#include <fcntl.h>

typedef void* ODBM_File;

#define odbm_FETCH(db,key)			fetch(key)
#define odbm_STORE(db,key,value,flags)		store(key,value)
#define odbm_DELETE(db,key)			delete(key)
#define odbm_FIRSTKEY(db)			firstkey()
#define odbm_NEXTKEY(db,key)			nextkey(key)

static int dbmrefcnt;

#ifndef DBM_REPLACE
#define DBM_REPLACE 0
#endif

XS(XS_ODBM_File_odbm_TIEHASH)
{
    dXSARGS;
    if (items != 4)
	croak("Usage: ODBM_File::TIEHASH(dbtype, filename, flags, mode)");
    {
	char *	dbtype = (char *)SvPV(ST(0),na);
	char *	filename = (char *)SvPV(ST(1),na);
	int	flags = (int)SvIV(ST(2));
	int	mode = (int)SvIV(ST(3));
	ODBM_File	RETVAL;
	{
	    char tmpbuf[1025];
	    if (dbmrefcnt++)
		croak("Old dbm can only open one database");
	    sprintf(tmpbuf,"%s.dir",filename);
	    if (stat(tmpbuf, &statbuf) < 0) {
		if (flags & O_CREAT) {
		    if (mode < 0 || close(creat(tmpbuf,mode)) < 0)
			croak("ODBM_File: Can't create %s", filename);
		    sprintf(tmpbuf,"%s.pag",filename);
		    if (close(creat(tmpbuf,mode)) < 0)
			croak("ODBM_File: Can't create %s", filename);
		}
		else
		    croak("ODBM_FILE: Can't open %s", filename);
	    }
	    RETVAL = (void*)(dbminit(filename) >= 0 ? &dbmrefcnt : 0);
	    ST(0) = sv_mortalcopy(&sv_undef);
	    sv_setptrobj(ST(0), RETVAL, "ODBM_File");
	}
    }
    XSRETURN(1);
}

XS(XS_ODBM_File_DESTROY)
{
    dXSARGS;
    if (items != 1)
	croak("Usage: ODBM_File::DESTROY(db)");
    {
	ODBM_File	db;

	if (SvROK(ST(0))) {
	    IV tmp = SvIV((SV*)SvRV(ST(0)));
	    db = (ODBM_File) tmp;
	}
	else
	    croak("db is not a reference");
	dbmrefcnt--;
	dbmclose();
    }
    XSRETURN(1);
}

XS(XS_ODBM_File_odbm_FETCH)
{
    dXSARGS;
    if (items != 2)
	croak("Usage: ODBM_File::FETCH(db, key)");
    {
	ODBM_File	db;
	datum	key;
	datum	RETVAL;

	if (sv_isa(ST(0), "ODBM_File")) {
	    IV tmp = SvIV((SV*)SvRV(ST(0)));
	    db = (ODBM_File) tmp;
	}
	else
	    croak("db is not of type ODBM_File");

	key.dptr = SvPV(ST(1), na);
	key.dsize = (int)na;;

	RETVAL = odbm_FETCH(db, key);
	ST(0) = sv_newmortal();
	sv_setpvn(ST(0), RETVAL.dptr, RETVAL.dsize);
    }
    XSRETURN(1);
}

XS(XS_ODBM_File_odbm_STORE)
{
    dXSARGS;
    if (items < 3 || items > 4)
	croak("Usage: ODBM_File::STORE(db, key, value, flags = DBM_REPLACE)");
    {
	ODBM_File	db;
	datum	key;
	datum	value;
	int	flags;
	int	RETVAL;

	if (sv_isa(ST(0), "ODBM_File")) {
	    IV tmp = SvIV((SV*)SvRV(ST(0)));
	    db = (ODBM_File) tmp;
	}
	else
	    croak("db is not of type ODBM_File");

	key.dptr = SvPV(ST(1), na);
	key.dsize = (int)na;;

	value.dptr = SvPV(ST(2), na);
	value.dsize = (int)na;;

	if (items < 4)
	    flags = DBM_REPLACE;
	else {
	    flags = (int)SvIV(ST(3));
	}

	RETVAL = odbm_STORE(db, key, value, flags);
	ST(0) = sv_newmortal();
	sv_setiv(ST(0), (IV)RETVAL);
	if (RETVAL) {
	    if (RETVAL < 0 && errno == EPERM)
		croak("No write permission to odbm file");
	    croak("odbm store returned %d, errno %d, key \"%s\"",
			RETVAL,errno,key.dptr);
	}
    }
    XSRETURN(1);
}

XS(XS_ODBM_File_odbm_DELETE)
{
    dXSARGS;
    if (items != 2)
	croak("Usage: ODBM_File::DELETE(db, key)");
    {
	ODBM_File	db;
	datum	key;
	int	RETVAL;

	if (sv_isa(ST(0), "ODBM_File")) {
	    IV tmp = SvIV((SV*)SvRV(ST(0)));
	    db = (ODBM_File) tmp;
	}
	else
	    croak("db is not of type ODBM_File");

	key.dptr = SvPV(ST(1), na);
	key.dsize = (int)na;;

	RETVAL = odbm_DELETE(db, key);
	ST(0) = sv_newmortal();
	sv_setiv(ST(0), (IV)RETVAL);
    }
    XSRETURN(1);
}

XS(XS_ODBM_File_odbm_FIRSTKEY)
{
    dXSARGS;
    if (items != 1)
	croak("Usage: ODBM_File::FIRSTKEY(db)");
    {
	ODBM_File	db;
	datum	RETVAL;

	if (sv_isa(ST(0), "ODBM_File")) {
	    IV tmp = SvIV((SV*)SvRV(ST(0)));
	    db = (ODBM_File) tmp;
	}
	else
	    croak("db is not of type ODBM_File");

	RETVAL = odbm_FIRSTKEY(db);
	ST(0) = sv_newmortal();
	sv_setpvn(ST(0), RETVAL.dptr, RETVAL.dsize);
    }
    XSRETURN(1);
}

XS(XS_ODBM_File_odbm_NEXTKEY)
{
    dXSARGS;
    if (items != 2)
	croak("Usage: ODBM_File::NEXTKEY(db, key)");
    {
	ODBM_File	db;
	datum	key;
	datum	RETVAL;

	if (sv_isa(ST(0), "ODBM_File")) {
	    IV tmp = SvIV((SV*)SvRV(ST(0)));
	    db = (ODBM_File) tmp;
	}
	else
	    croak("db is not of type ODBM_File");

	key.dptr = SvPV(ST(1), na);
	key.dsize = (int)na;;

	RETVAL = odbm_NEXTKEY(db, key);
	ST(0) = sv_newmortal();
	sv_setpvn(ST(0), RETVAL.dptr, RETVAL.dsize);
    }
    XSRETURN(1);
}

#ifdef __cplusplus
extern "C"
#endif
XS(boot_ODBM_File)
{
    dXSARGS;
    char* file = __FILE__;

    XS_VERSION_BOOTCHECK ;

        newXS("ODBM_File::TIEHASH", XS_ODBM_File_odbm_TIEHASH, file);
        newXS("ODBM_File::DESTROY", XS_ODBM_File_DESTROY, file);
        newXS("ODBM_File::FETCH", XS_ODBM_File_odbm_FETCH, file);
        newXS("ODBM_File::STORE", XS_ODBM_File_odbm_STORE, file);
        newXS("ODBM_File::DELETE", XS_ODBM_File_odbm_DELETE, file);
        newXS("ODBM_File::FIRSTKEY", XS_ODBM_File_odbm_FIRSTKEY, file);
        newXS("ODBM_File::NEXTKEY", XS_ODBM_File_odbm_NEXTKEY, file);
    ST(0) = &sv_yes;
    XSRETURN(1);
}
