delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2004/06/21/04:30:26

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
From: <alexbodn AT 012 DOT net DOT il>
To: djgpp AT delorie DOT com
Subject: BTRIEVE support in DJGPP
Date: Mon, 21 Jun 2004 11:29:26 +0300
MIME-Version: 1.0
Message-Id: <20040621082759.SBBU15248.fep15@[212.117.129.234]>
Reply-To: djgpp AT delorie DOT com

after more than a decade of programming using application generators that save 
their code using btrieve, i am glad to announce the DJGPP port of the BTRV 
infrastructure routine.

included here are a header file the source file, and a small readme file.

p.s. i have ported the btrieve v6.xx also, but i will first upload the source 
to the site of pervasive, and post a link on this list.

well formed djgpp packages are later to come.

####### btr.h ##########

#ifndef __btr_h__
#define __btr_h__

     /**************************************************/
     /* 	BTRIEVE OPERATION CODES  (BTRV.H)      */
     /**************************************************/
short	   b_op_code;
#define    B_OPEN	       0
#define    B_CLOSE	       1
#define    B_INSERT	       2
#define    B_UPDATE	       3
#define    B_DELETE	       4
#define    B_GET_EQUAL	       5
#define    B_GET_NEXT	       6
#define    B_GET_PREVIOUS      7
#define    B_GET_GR	       8
#define    B_GET_GR_EQ	       9
#define    B_GET_LESS	       10
#define    B_GET_LESS_EQ       11
#define    B_GET_LOWEST        12
#define    B_GET_HIGHEST       13
#define    B_CREATE	       14
#define    B_STAT	       15
#define    B_EXTEND	       16
#define    B_SET_DIRECTORY     17
#define    B_GET_DIRECTORY     18
#define    B_BT 	       19
#define    B_ET 	       20
#define    B_AT 	       21
#define    B_GET_POSITION      22
#define    B_GET_DIRECT        23
#define    B_STEP_DIRECT       24
#define    B_STOP	       25
#define    B_VERSION	       26
#define    B_UNLOCK	       27
#define    B_RESET	       28
#define    B_SET_OWNER	       29
#define    B_CLEAR_OWNER       30
#define    B_CREATE_INDEX      31
#define    B_DROP_INDEX        32
#define    B_GET_EQUAL_KEY     55
#define    B_GET_NEXT_KEY      56
#define    B_GET_PREVIOUS_KEY  57
#define    B_GET_GR_KEY        58
#define    B_GET_GR_EQ_KEY     59
#define    B_GET_LESS_KEY      60
#define    B_GET_LESS_EQ_KEY   61
#define    B_GET_LOWEST_KEY    62
#define    B_GET_HIGHEST_KEY   63

#define    B_WAIT	       100
#define    B_NOWAIT	       200
#define    B_MUL_WAIT	       300
#define    B_MUL_NOWAIT        400

     /**************************************************/
     /* 	BTRIEVE STATUS PARAMETERS	       */
     /**************************************************/
short	   b_status;
#define    B_NO_ERROR          0
#define    B_I_O_ERROR	       2
#define    B_NO_OPEN	       3
#define    B_NOT_FOUND	       4
#define    B_DUPLICATE	       5
#define    B_INVALID_KEY       6
#define    B_EOF	       9
#define    B_FILE_NOT_FOUND    12
#define    B_DISK_FULL	       18
#define BTR_ERR     20			  /* record manager not started */
#define    B_BTR_NAME_ERROR    30
#define    B_VAR_PAGE_ERROR    54
#define    B_CONFLICT	       80
#define    B_RECORD_IN_USE     84
#define    B_FILE_IN_USE       85
#define    B_FILE_FULL	       86
#define    B_MODE_ERROR        88
#define    B_SERVER_ERROR      91
#define    B_FILE_BUSY	       85

     /**************************************************/
     /* 	BTRIEVE FLAGS  PARAMETERS	       */
     /**************************************************/
#define NOR_TYPE    0
#define DUP	    1
#define MOD	    2
#define BIN	    4
#define NUL         8
#define SEG	    16
#define DESC	    64
#define EXT_TYPE    256

     /**************************************************/
     /* 	BTRIEVE TYPES  PARAMETERS	       */
     /**************************************************/
#define B_INT_TYPE  1
#define B_STR_TYPE  0
#define B_ZSTR_TYPE 11

short BTRV (short OP, char POS_BLK[], char DATA_BUF[], short *DATA_LEN,
            char KEY_BUF[], short KEY_NUM);


#endif /*__btr_h__*/

###### btrv.c #########
/*									*/
/*	     DJGPP Version 2.xx interface to the               */
/*		Btrieve Record Manager, version 4, 5, 5.1		*/

/*
   Port to djgpp (BTI_DOS_32D) Copyright (C) 2004 Alex Bodnaru.

Report problems and direct all questions on this port to:

  alexbodn AT 012 DOT net DOT il
*/

#include <dos.h>
#include <stdlib.h>
#include <dpmi.h>
#include <go32.h>

#include "btr.h"

#define BTR_INT     0x7B		    /* Btrieve interrupt vector */
#define BTR2_INT    0x2F		 /* multi-user interrupt vector */
#define BTR_VECTOR  BTR_INT * 4 		/* offset for interrupt */
#define BTR_OFFSET  0x33	       /* Btrieve offset within segment */
#define VARIABLE_ID 0x6176     /* id for variable length records - 'va' */
#define _2FCODE     0xAB00	 /* function code for int 2F to btrieve */


/* ProcId is used for communicating with the Multi Tasking Version of  */
/* Btrieve. It contains the process id returned from BMulti and should */
/* not be changed once it has been set. 			       */

static unsigned ProcId = 0;		/* initialize to no process id */
static char MULTI = 0;		      /* flag set to true if MultiUser */
static char VSet = 0;		/* flag set to true if checked version */


enum reqparms
{
   in_pos =      0x0001,
   in_databuf =  0x0002,
   in_datalen =  0x0004,
   in_keybuf =   0x0008,
   out_pos =     0x0010,
   out_databuf = 0x0020,
   out_datalen = 0x0040,
   out_keybuf =  0x0080
};

static unsigned short bufparms[75];

#define has_op_parms(op, parms) (bufparms[(op) % 100] & (parms))

static void bufparms_init()
{
   static int reqparms_init = 0;
   int c;
#define op_parms(op, parms) bufparms[op] = parms
   if (reqparms_init)
      return;
   for (c = sizeof(bufparms) / sizeof(bufparms[0]) - 1; c >= 0; --c)
      bufparms[c] = 0xffff;
   op_parms( B_OPEN, in_databuf | in_datalen | in_keybuf | out_pos );
   op_parms( B_CLOSE, in_pos );
   op_parms( B_INSERT, in_pos | in_databuf | in_datalen | out_pos | out_keybuf 
);
   op_parms( B_UPDATE, in_pos | in_databuf | in_datalen | out_pos | out_keybuf 
);
   op_parms( B_DELETE, in_pos | out_pos );
   op_parms( B_GET_EQUAL,    in_pos | in_datalen | in_keybuf | out_pos | 
out_databuf | out_datalen );
   op_parms( B_GET_NEXT,     in_pos | in_datalen | in_keybuf | out_pos | 
out_databuf | out_datalen | out_keybuf );
   op_parms( B_GET_PREVIOUS, in_pos | in_datalen | in_keybuf | out_pos | 
out_databuf | out_datalen | out_keybuf );
   op_parms( B_GET_GR,       in_pos | in_datalen | in_keybuf | out_pos | 
out_databuf | out_datalen | out_keybuf );
   op_parms( B_GET_GR_EQ,    in_pos | in_datalen | in_keybuf | out_pos | 
out_databuf | out_datalen | out_keybuf );
   op_parms( B_GET_LESS,     in_pos | in_datalen | in_keybuf | out_pos | 
out_databuf | out_datalen | out_keybuf );
   op_parms( B_GET_LESS_EQ,  in_pos | in_datalen | in_keybuf | out_pos | 
out_databuf | out_datalen | out_keybuf );
   op_parms( B_GET_LOWEST,  in_pos | in_datalen | out_pos | out_databuf | 
out_datalen | out_keybuf );
   op_parms( B_GET_HIGHEST, in_pos | in_datalen | out_pos | out_databuf | 
out_datalen | out_keybuf );
   
   op_parms( B_GET_EQUAL_KEY,    in_pos | in_keybuf | out_pos | out_keybuf );
   op_parms( B_GET_NEXT_KEY,     in_pos | in_keybuf | out_pos | out_keybuf );
   op_parms( B_GET_PREVIOUS_KEY, in_pos | in_keybuf | out_pos | out_keybuf );
   op_parms( B_GET_GR_KEY,       in_pos | in_keybuf | out_pos | out_keybuf );
   op_parms( B_GET_GR_EQ_KEY,    in_pos | in_keybuf | out_pos | out_keybuf );
   op_parms( B_GET_LESS_KEY,     in_pos | in_keybuf | out_pos | out_keybuf );
   op_parms( B_GET_LESS_EQ_KEY,  in_pos | in_keybuf | out_pos | out_keybuf );
   op_parms( B_GET_LOWEST_KEY,  in_pos | out_pos | out_keybuf );
   op_parms( B_GET_HIGHEST_KEY, in_pos | out_pos | out_keybuf );
   
   op_parms( B_CREATE, in_databuf | in_datalen | in_keybuf );
   op_parms( B_STAT, in_pos | in_databuf | in_datalen | in_keybuf | out_databuf 
| out_datalen | out_keybuf );
   op_parms( B_EXTEND, 0xffff );
   op_parms( B_SET_DIRECTORY, in_keybuf );
   op_parms( B_GET_DIRECTORY, out_keybuf );
   op_parms( B_BT, 0 );
   op_parms( B_ET, 0 );
   op_parms( B_AT, 0 );
   op_parms( B_GET_POSITION, in_pos | in_datalen | out_pos | out_databuf | 
out_datalen );
   op_parms( B_GET_DIRECT, in_pos | in_databuf | in_datalen | out_pos | 
out_databuf | out_datalen | out_keybuf );
   op_parms( B_STEP_DIRECT, in_pos | in_datalen | out_pos | out_databuf | 
out_datalen );
   op_parms( B_STOP, 0 );
   op_parms( B_VERSION, in_datalen | out_databuf | out_datalen );
   op_parms( B_UNLOCK, in_pos | in_databuf | in_datalen );
   op_parms( B_RESET, in_keybuf );
   op_parms( B_SET_OWNER, in_pos | in_databuf | in_datalen | in_keybuf | 
out_pos );
   op_parms( B_CLEAR_OWNER, in_pos | out_pos );
   op_parms( B_CREATE_INDEX, in_pos | in_databuf | in_datalen );
   op_parms( B_DROP_INDEX, in_pos);
   reqparms_init = 1;
}

short BTRV (short OP, char POS_BLK[], char DATA_BUF[], short *DATA_LEN,
            char KEY_BUF[], short KEY_NUM)
{
    static int dosdatamem_init = 0;
    __dpmi_regs regs;
    static _go32_dpmi_seginfo dosdatamem;
    
    struct BTRIEVE_PARMS	  /* structure passed to Btrieve Record Manager */
    {
        short BUF_OFFSET;			  /* callers data buffer offset */
        short	 BUF_SEG;			 /* callers data buffer segment */
        short	 BUF_LEN;			       /* length of data buffer */
        short CUR_OFFSET;			  /* user position block offset */
        short	 CUR_SEG;			 /* user position block segment */
        short FCB_OFFSET;				  /* offset of disk FCB */
        short	 FCB_SEG;				 /* segment of disk FCB */
        short	 FUNCTION;				  /* requested function */
        short KEY_OFFSET;			 /* offset of user's key buffer */
        short	 KEY_SEG;			/* segment of user's key buffer */
        unsigned char KEY_LENGTH;			 /* length of user's key buffer */
        char  KEY_NUMBER;			/* key of reference for request */
        short	STAT_OFFSET;			       /* offset of status word */
        short	 STAT_SEG;			      /* segment of status word */
        short	 XFACE_ID;				 /* language identifier */
    } XDATA;
    
    short STAT = 0;				      /* status of Btrieve call */

    bufparms_init();

    /*  Check to see that the Btrieve Record Manager has been started.	*/
    
    if (!VSet)		     /* if we don't know version of Btrieve yet */
    {
        VSet = 1;
        regs.x.ax = 0x3000; 			   /* check dos version */
        __dpmi_int (0x21, &regs);
        if ((regs.x.ax & 0x00FF) >= 3)	   /* if DOS version 3 or later */
        {
            regs.x.ax = _2FCODE;
            __dpmi_int (BTR2_INT, &regs);
            MULTI = ((regs.x.ax & 0xFF) == 'M');/* if al is M, bmulti is loaded 
*/
        }
    }
    
    if (!MULTI)
    {						/* if bmulti not loaded */
        regs.x.ax = 0x3500 + BTR_INT;
        __dpmi_int (0x21, &regs);
        if (regs.x.bx != BTR_OFFSET)
           return (BTR_ERR);
    }
    
    /*  initialize segment part of addresses to user's data segment.     */
    XDATA.STAT_SEG = __tb / 16;
    XDATA.FCB_SEG = __tb / 16;
    XDATA.KEY_SEG = __tb / 16;
    XDATA.CUR_SEG = __tb / 16;
    if (!dosdatamem_init || dosdatamem.size)
    {
        dosdatamem.size = (4090 + 15) / 16;
        if (_go32_dpmi_allocate_dos_memory(&dosdatamem))
           return -1;
        dosdatamem_init = 1;
    }
    if (DATA_LEN != NULL && (short)dosdatamem.size < (*DATA_LEN + 15) / 16)
    {
        dosdatamem.size = (*DATA_LEN + 15) / 16;
        if (_go32_dpmi_resize_dos_memory(&dosdatamem))
           return -1;
    }
    if (has_op_parms(OP, in_databuf) &&
        DATA_BUF != NULL && DATA_LEN != NULL && *DATA_LEN)
    {
       dosmemput(DATA_BUF, *DATA_LEN, dosdatamem.rm_segment * 16);
    }
    XDATA.BUF_SEG = dosdatamem.rm_segment;
    
    /*  Move user parameters to XDATA, the block where Btrieve expects them.*/
    XDATA.FUNCTION	 = OP;
    XDATA.STAT_OFFSET = __tb % 16 + sizeof(XDATA);
    dosmemput(&STAT, sizeof(STAT), __tb);
    XDATA.FCB_OFFSET  = XDATA.STAT_OFFSET + sizeof(STAT);
    if (has_op_parms(OP, in_pos))
       dosmemput(POS_BLK, 128, __tb + XDATA.FCB_OFFSET);
    XDATA.CUR_OFFSET  = XDATA.FCB_OFFSET + 38;
    XDATA.KEY_OFFSET  = XDATA.FCB_OFFSET + 128;
    XDATA.KEY_LENGTH  = 255;		 /* use max since we don't know */
    if (has_op_parms(OP, in_keybuf) && KEY_BUF != NULL)
        dosmemput(KEY_BUF, XDATA.KEY_LENGTH, __tb + XDATA.KEY_OFFSET);
    XDATA.KEY_NUMBER  = KEY_NUM;
    XDATA.BUF_OFFSET  = 0;
    if (DATA_BUF != NULL && DATA_LEN != NULL)
        XDATA.BUF_LEN	    = *DATA_LEN;
    else XDATA.BUF_LEN	    = 0;
    XDATA.XFACE_ID	 = VARIABLE_ID;
    
    /*  Make call to the Btrieve Record Manager.				*/

    /* parameter block is expected to be in DX */
    dosmemput(&XDATA, sizeof(XDATA), __tb);
    regs.x.dx = __tb % 16;
    regs.x.es = regs.x.ds = regs.x.ss = __tb / 16;
    if (MULTI)
    {							 /* call bmulti */
        while (1)
        {
            regs.x.ax = 1;		     /*  assume no proc id obtained yet */
            if ((regs.x.bx = ProcId) != 0)		/* if we have a proc id */
                regs.x.ax = 2;				    /* tell bmulti that */
            regs.x.ax += _2FCODE;
            __dpmi_int (BTR2_INT, &regs);
            if ((regs.x.ax & 0x00FF) == 0)     /* if call was processed */
                break;                           /* by bmulti, leave loop */
            regs.x.ax = 0x0200;   /* if multilink advanced is loaded, it */
            __dpmi_int (0x7F, &regs); /* will switch processes */
        }
        if (ProcId == 0)
           ProcId = regs.x.bx;
    }
    else __dpmi_int (BTR_INT, &regs);
    
    dosmemget(__tb + XDATA.STAT_OFFSET, sizeof(STAT), &STAT);
    dosmemget(__tb, sizeof(XDATA), &XDATA);
    if (has_op_parms(OP, out_pos))
       dosmemget(__tb + XDATA.FCB_OFFSET, 128, POS_BLK);
    if (has_op_parms(OP, out_keybuf) && KEY_BUF != NULL && XDATA.KEY_LENGTH)
        dosmemget(__tb + XDATA.KEY_OFFSET, XDATA.KEY_LENGTH, KEY_BUF);
    if (has_op_parms(OP, out_databuf) &&
        DATA_BUF != NULL && DATA_LEN != NULL && XDATA.BUF_LEN)
    {
        *DATA_LEN = XDATA.BUF_LEN;
        dosmemget(dosdatamem.rm_segment * 16, *DATA_LEN, DATA_BUF);
    }
    if (0 && OP == B_CLOSE && dosdatamem_init)
    {
       _go32_dpmi_free_dos_memory(&dosdatamem);
       dosdatamem_init = 0;
    }
    return (STAT);					       /* return status */
}

####### readme.dj #########

hello friends,

after more than a decade of using btrieve based application generator, i am
finaly proud to be able to access my older files from c programs.

this software is meant to access btrieve 4, 5, and 5.1 only.

to use with djgpp:

1. ensure key buffer is allways 255 bytes long.

2. to port 16 bit code to djgpp, where the data files are maintained the same,
please use the __attribute__(packed) on the data structures, and substitute
int by short. those are general considerations in migrating from 16 bit dos to
djgpp.

please enjoy, and post your comments and improvements to:

alex

<alexbodn AT 012 DOT net DOT il>

######### end

- Raw text -


  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019