Mail Archives: djgpp/2004/06/21/04:30:26
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, ®s);
if ((regs.x.ax & 0x00FF) >= 3) /* if DOS version 3 or later */
{
regs.x.ax = _2FCODE;
__dpmi_int (BTR2_INT, ®s);
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, ®s);
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, ®s);
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, ®s); /* will switch processes */
}
if (ProcId == 0)
ProcId = regs.x.bx;
}
else __dpmi_int (BTR_INT, ®s);
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 -