home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Jason Aller Floppy Collection
/
125.img
/
PRO-C4.ZIP
/
BENCH1.ZIP
/
BENCH
/
IDBC3.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-28
|
42KB
|
1,506 lines
/* ==( io/src/idbc3.c )== */
/* ----------------------------------------------- */
/* Pro-C Copyright (C) 1988 - 1990 Vestronix Inc. */
/* Modification to this source is not supported */
/* by Vestronix Inc. */
/* All Rights Reserved */
/* ----------------------------------------------- */
/* Written NA 24-Feb-88 */
/* Modified VV 12-Apr-90 See comments below */
/* ----------------------------------------------- */
/* %W% (%H% %T%) */
/*
* Modifications
*
* 12-Apr-90 VvA - corrections to next/prev fn for EOF/TOF
* 28-Mar-90 VvA - adjustments for locking modes, transactions
* 14-Mar-90 VvA - fixed blank dBASE field bug
* 01-Feb-90 VvA - fld_cnt now in iogen.c, fd[] struct
* 01-Feb-90 VvA - Enabled openmode in open_file()
* 14-Dec-89 VvA - V.2 modifications
* 01-Sep_89 VvA - Modified for generic I/O interface
* 01-Sep_88 VvA - Adapted from existing IO modules
*/
/* dBC III+ I/O calls via general IOGEN.C interface */
# include <stdio.h>
# include <dbc3plus.h>
# include <iodef.h>
# include <iomsg.h>
# include <proc.io>
# include <bench.h>
# include <iosup.h>
/* Function prototypes */
# ifdef ANSI
static int i_addrec(int, char *);
static int i_close_file(int, char *);
static int i_commit(int, char *);
static int i_delrec(int, char *);
static int i_filename(int, char *);
static int i_findkey(int, char *);
static int i_firstkey(int, char *);
static int i_init_file(int, char *);
static int i_lastkey(int, char *);
static int i_lockrec(int, char *);
static int i_login(int, char *);
static int i_logoff(int, char *);
static int i_nextrec(int, char *);
static int i_open_file(int, char *);
static int i_prevrec(int, char *);
static int i_rereadrec(int, char *);
static int i_rollback(int, char *);
static int i_selectinx(int, char *);
static int i_transact(int, char *);
static int i_unlock_rec(int, char *);
static int i_updrec(int, char *);
static int create_file(int, char *);
static int load_memos(int, int);
static int load_keys(int, int);
static int length_check(int);
static int get_record(int, char *, int);
static int update_keys(int, char *, int);
static int lock_sizebyte(int, char *);
static int lock_ndx(int);
static int unlock_ndx(int, char *);
static int lock_mem(int);
static int io_xlate(int, int, char *);
static void unlock_mem(int);
static void unlock_sizebyte(int);
static void setupkey(int, char *, char *);
static void buff2db(int, char *, char *);
static void db2buff(int, char *, char *);
# else
static int i_addrec();
static int i_close_file();
static int i_commit();
static int i_delrec();
static int i_filename();
static int i_findkey();
static int i_firstkey();
static int i_init_file();
static int i_lastkey();
static int i_lockrec();
static int i_login();
static int i_logoff();
static int i_nextrec();
static int i_open_file();
static int i_prevrec();
static int i_rereadrec();
static int i_rollback();
static int i_selectinx();
static int i_transact();
static int i_unlock_rec();
static int i_updrec();
static int create_file();
static int load_memos();
static int load_keys();
static int length_check();
static int get_record();
static int update_keys();
static int lock_sizebyte();
static int lock_ndx();
static int unlock_ndx();
static int lock_mem();
static int io_xlate();
static void unlock_mem();
static void unlock_sizebyte();
static void setupkey();
static void buff2db();
static void db2buff();
# endif
extern RECNUM _appnded; /* allows use of APPEND in dBputr function */
extern int _dlock;
/*
* structure for dBC III+ specific values
*/
struct dbc_def
{
char *dbf_num; /* data file descriptor */
char *mm_num; /* memo file descriptor */
char *ix_num[MAX_KEYS]; /* index file descriptors */
int dbrec_len; /* record length seen by dBC file */
};
static struct dbc_def fdbf[MAX_FILES];
static char keybuff[MAX_FLDLEN * MAX_SEGS + MAX_SEGS];
static char xkeybuff[MAX_FLDLEN * MAX_SEGS + MAX_SEGS];
static char oldbuff[MAX_RECLEN];
static char storbuff[MAX_RECLEN];
static char memobuff[5000];
static int dberrno; /* dBC III error code */
static RECNUM recnum; /* record number in dBC III form */
static int DBCMODE; /* file open mode, shared or exclusive */
/*
*
* Interface Functions
*
*/
/*
* Sets up File Name extension.
*/
static int i_filename(fd_sys, buffer)
int fd_sys;
char *buffer;
{
for ( ; (*buffer != '.') && (*buffer != NULL); buffer++)
;
*buffer = NULL;
return(IOGOOD);
}
/*
* File initialization
*/
static int i_init_file(fd_sys, buffer)
int fd_sys;
char *buffer;
{
return(IOGOOD);
}
/*
* File open function
*/
static int i_open_file(fd_sys, buffer)
int fd_sys;
char *buffer;
{
int n;
char *dbfdesc;
char dbfname[FILENAME_LEN];
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
strcpy(dbfname, fptr->filname);
strcat(dbfname, ".DBF"); /* dBASE III type filename from filname */
dptr->mm_num = NULL;
_dlock = d_TLOCK; /* dBC3+ no-wait locking */
if (fptr->openmode & OUTPUT_FLAG)
create_file(fd_sys, dbfname); /* if OUTPUT, delete existing files */
DBCMODE = (fptr->openmode & P_SHARED) ? d_SHARED : d_SINGLE;
if ((dberrno = dBopen(dbfname, DBCMODE | d_MINBUF, &dbfdesc)) != SUCCESS)
{
if ((DBCMODE == d_SHARED) && (dberrno == d_LOCKED))
{
errmsg(FileShareReqd); /* unconditional exit if SHARE not run */
return(IOERROR);
}
/* exit if file to be read-only OR already exists */
if ((fptr->openmode & INPUT_FLAG) || !access(dbfname, 00))
return(io_xlate(fd_sys, dberrno, "dBC OPEN1"));
if (create_file(fd_sys, dbfname) != IOGOOD)
return(IOERROR);
if ((dberrno = dBopen(dbfname, DBCMODE | d_MINBUF, &dbfdesc)) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC OPEN2"));
}
/* file has been opened successfully */
dptr->dbf_num = dbfdesc;
if (length_check(fd_sys) != IOGOOD)
{
i_close_file(fd_sys, buffer);
return(IOERROR);
}
return(IOGOOD);
}
/*
* dBC III+ create file function - file will be opened by the create call
*/
static int create_file(fd_sys, dfname)
int fd_sys; /* index into fd table */
char *dfname;
{
int j;
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
dBFIELD *fldtmp;
fldtmp = (dBFIELD *)alloc(sizeof(dBFIELD) * fptr->fld_cnt);
for (j = 0; j < fptr->fld_cnt; j++) /* load field descriptions */
{
strcpy(fldtmp[j].fieldnm, cvt_upper(fptr->flds[j].fldname));
fldtmp[j].dec = (FLDDEC)0;
switch(fptr->flds[j].fldtype)
{
case CHRTYP :
fldtmp[j].type = 'C';
fldtmp[j].width = (FLDWIDTH)fptr->flds[j].fldlen;
break;
case INTTYP :
case LNGTYP :
case FLTTYP :
case DBLTYP :
fldtmp[j].type = 'N';
fldtmp[j].width = (FLDWIDTH)nummasklen(fptr->flds[j].fldmask);
fldtmp[j].dec = (FLDDEC)decmasklen(fptr->flds[j].fldmask);
break;
case DATTYP :
if (fptr->flds[j].fldlen == 6)
{
fldtmp[j].type = 'D';
fldtmp[j].width = (FLDWIDTH)8;
}
else
{
fldtmp[j].type = 'N';
fldtmp[j].width = (FLDWIDTH)10;
fldtmp[j].dec = (FLDDEC)0;
}
break;
case LOGTYP :
fldtmp[j].type = 'L';
fldtmp[j].width = (FLDWIDTH)1;
break;
case MEMTYP :
fldtmp[j].type = 'M';
fldtmp[j].width = (FLDWIDTH)10;
break;
}
}
if ((dberrno = dBcreat(dfname, (FLDNUM)fptr->fld_cnt, fldtmp)) != SUCCESS)
{
free(fldtmp);
return(io_xlate(fd_sys, dberrno, "dBC CRT"));
}
free(fldtmp);
if (load_memos(fd_sys, TRUE) != IOGOOD)
return(IOERROR);
return((load_keys(fd_sys, TRUE) > 0) ? IOGOOD : IOERROR);
}
/*
* dBC III+ memo load function - creates or opens memo files
* - if creatmemo is TRUE, file will be created, otherwise it is opened
* - one memo file will do for all memo fields
*/
static int load_memos(fd_sys, creatmemo)
int fd_sys, creatmemo;
{
int j;
char *memdesc, memname[FILENAME_LEN];
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
strcpy(memname, fptr->filname); /* memo names match their file names */
strcat(memname, ".DBT");
for (j = 0; j < fptr->fld_cnt; j++) /* load field descriptions */
if (fptr->flds[j].fldtype == MEMTYP)
{
if (creatmemo)
{
if ((dberrno = dBmcreat(memname)) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC MEMCRTE"));
}
if ((dberrno = dBmopen(memname, DBCMODE, &memdesc)) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC MEMOPEN"));
fdbf[fd_sys].mm_num = memdesc;
break;
}
return(IOGOOD);
}
/*
* dBC III+ key load function - creates or opens indexes for new files
* - if creatndx is TRUE, index will be created, otherwise it is opened
*/
static int load_keys(fd_sys, creatndx)
int fd_sys, creatndx;
{
int ndxid, n, m, fx;
char keytype, *ndxdesc;
char ndxname[FILENAME_LEN], keyname[FLDNAME_LEN * MAX_SEGS * 3], fmtstr[12];
struct fd_def *fptr = &fd[fd_sys];
KEYLEN keylen;
strcpy(ndxname, fptr->filname); /* index names match their file names */
if ((ndxid = strlen(ndxname)) > 7) /* ndxid is index id offset */
ndxid = 7;
ndxname[ndxid] = '\0';
strcat(ndxname, "0.NDX");
n = 0;
while (fptr->keys[n].segcount != -1)
{
ndxname[ndxid] = (char)(n + 49); /* sequential index name suffix */
if (creatndx) /* create the indexes */
{
keyname[0] = '\0';
keylen = (KEYLEN)0;
keytype = 'C';
for (m = 0; m < fptr->keys[n].segcount; m++)
{ /* requires conversions for mixed type keys !!! */
fx = fptr->keys[n].fldindex[m];
if (m > 0)
strcat(keyname, "+");
if ((fptr->keys[n].segcount == 1) || (fptr->flds[fx].fldtype == CHRTYP))
{
if ((fptr->flds[fx].fldtype == CHRTYP) &&
(fptr->flds[fx].fldlen != fptr->keys[n].seglen[m]))
{
strcat(keyname, "SUBSTR(");
strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
zerorec(fmtstr, 12);
sprintf(fmtstr, ",%d,%d)",
(fptr->keys[n].segstart[m]+1 - fptr->flds[fx].fldstart),
fptr->keys[n].seglen[m]);
strcat(keyname, fmtstr);
}
else
strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
keylen += (KEYLEN)fptr->keys[n].seglen[m];
}
else if (fptr->flds[fx].fldtype == DATTYP)
{
if (fptr->flds[fx].fldlen == 6)
{
strcat(keyname, "DTOC(");
strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
strcat(keyname, ")");
keylen += (KEYLEN)8;
}
else
{
strcat(keyname, "STR(");
strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
strcat(keyname, ",10,0)");
keylen += (KEYLEN)10;
}
}
else
{
zerorec(fmtstr, 12);
sprintf(fmtstr, ",%d,%d)", nummasklen(fptr->flds[fx].fldmask), decmasklen(fptr->flds[fx].fldmask));
strcat(keyname, "STR(");
strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
strcat(keyname, fmtstr);
keylen += (KEYLEN)nummasklen(fptr->flds[fx].fldmask);
}
}
if (fptr->keys[n].segcount == 1) /* compound keys all type 'C' */
{
fx = fptr->keys[n].fldindex[0];
switch(fptr->flds[fx].fldtype)
{
case CHRTYP :
keytype = 'C';
break;
case DATTYP :
if (fptr->flds[fx].fldlen == 6)
{
keytype = 'D';
break;
} /* long int dates fall through to 'N' type */
case INTTYP :
case LNGTYP :
case FLTTYP :
case DBLTYP :
keytype = 'N';
break;
}
}
if ((dberrno = dBicreat(ndxname, keyname, keylen, keytype)) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC IXCRTE"));
}
else /* just open the indexes */
{
if ((dberrno = dBiopen(ndxname, DBCMODE, &ndxdesc)) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC IXOPEN"));
fdbf[fd_sys].ix_num[n] = ndxdesc;
}
n++;
}
return(n); /* value returned is the number of keys */
}
/*
* Length check function
* - checks record length against that expected by PRO-C
*/
static int length_check(fd_sys)
int fd_sys;
{
int i;
RECLEN chkreclen;
FLDNUM chkfldcnt;
char cm, cd, cy;
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
dBFIELD *flds;
flds = (dBFIELD *)alloc(sizeof(dBFIELD) * fptr->fld_cnt);
dptr->dbrec_len = 0; /* what PRO-C thinks DBF record length is... */
for (i = 0; i < fptr->fld_cnt; i++)
{
switch (fptr->flds[i].fldtype)
{
case DATTYP :
if (fptr->flds[i].fldlen == 6)
dptr->dbrec_len += 8;
else
dptr->dbrec_len += 10;
break;
case INTTYP :
case LNGTYP :
case FLTTYP :
case DBLTYP :
dptr->dbrec_len += nummasklen(fptr->flds[i].fldmask);
break;
case CHRTYP :
dptr->dbrec_len += fptr->flds[i].fldlen;
break;
case LOGTYP :
dptr->dbrec_len += 1;
break;
case MEMTYP :
dptr->dbrec_len += 10;
break;
}
} /* dbrec_len is field length as defined in application */
if ((dberrno = dBgetf(dptr->dbf_num, &chkreclen, &cm, &cd, &cy, &chkfldcnt, flds)) != SUCCESS)
{
free(flds);
return(io_xlate(fd_sys, dberrno, "dBC LCHK"));
}
free(flds);
if (dptr->dbrec_len != (int)chkreclen)
{ /* if file length has been changed... */
errmsg(FileRecLenChg_s, fptr->filname);
return(IOERROR);
}
if (load_memos(fd_sys, FALSE) != IOGOOD)
return(IOERROR);
return((load_keys(fd_sys, FALSE) > 0) ? IOGOOD : IOERROR);
}
/*
* File close function - including index files
* - with manual locking, files must be locked, flushed and unlocked
* before closing
*/
static int i_close_file(fd_sys, buffer)
int fd_sys;
char *buffer;
{
int n;
struct dbc_def *dptr = &fdbf[fd_sys];
n = 0;
while (fd[fd_sys].keys[n].segcount != -1)
{
if ((dberrno = dBiclose(dptr->ix_num[n])) != SUCCESS)
io_xlate(fd_sys, dberrno, "dBC ICLS");
n++;
}
if (dptr->mm_num) /* close the memo file */
if ((dberrno = dBmclose(dptr->mm_num)) != SUCCESS)
io_xlate(fd_sys, dberrno, "dBC MCLS");
if ((dberrno = dBclose(dptr->dbf_num)) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC DCLS"));
fd[fd_sys].active = NO;
return(IOGOOD);
}
/*
* Select an index to perform processing on - already done in IOGEN.C
*/
static int i_selectinx(fd_sys, buffer)
int fd_sys;
char *buffer;
{
return(IOGOOD);
}
/*
* Find a record by key value
*/
static int i_findkey(fd_sys, buffer)
int fd_sys;
char *buffer;
{
int errcode;
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
setupkey(fd_sys, buffer, keybuff);
dberrno = dBtkey(dptr->ix_num[fptr->cur_key], keybuff, &recnum);
if ((dberrno != SUCCESS) && (fptr->exact || (dberrno != d_MAYBE)))
return(io_xlate(fd_sys, dberrno, "dBC FIND"));
errcode = get_record(fd_sys, buffer, NEXT);
return((fptr->exact && (errcode == IOEOF)) ? IONOKEY : errcode);
}
/*
* Find first record in the file
*/
static int i_firstkey(fd_sys, buffer)
int fd_sys;
char *buffer;
{
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
if ((dberrno = dBrewind(dptr->ix_num[fptr->cur_key])) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC FRST1"));
if ((dberrno = dBnkey(dptr->ix_num[fptr->cur_key], keybuff, &recnum)) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC FRST2"));
return(get_record(fd_sys, buffer, NEXT));
}
/*
* Find last physical record in the file
*/
static int i_lastkey(fd_sys, buffer)
int fd_sys;
char *buffer;
{
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
if ((dberrno = dBfwd(dptr->ix_num[fptr->cur_key])) != SUCCESS)
return(io_xlate(fd_sys, dberrno, "dBC LAST1"));
if ((dberrno = dBpkey(dptr->ix_num[fptr->cur_key], keybuff, &recnum)) != SUCCESS)
{
if ((dberrno == d_NOKEY) || (dberrno == d_TOPKEY))
return(IOEOF);
return(io_xlate(fd_sys, dberrno, "dBC LAST2"));
}
return(get_record(fd_sys, buffer, PREV));
}
/*
* Find next record in the file
*/
static int i_nextrec(fd_sys, buffer)
int fd_sys;
char *buffer;
{
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
i_unlock_rec(fd_sys, buffer); /* unlock current rec before proceeding */
if ((dberrno = dBnkey(dptr->ix_num[fptr->cur_key], xkeybuff, &recnum)) != SUCCESS)
{
if (dberrno == d_ENDKEY)
return(IOEOF);
return(io_xlate(fd_sys, dberrno, "dBC NEXT"));
}
return(get_record(fd_sys, buffer, NEXT));
}
/*
* Find previous record in the file
*/
static int i_prevrec(fd_sys, buffer)
int fd_sys;
char *buffer;
{
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
i_unlock_rec(fd_sys, buffer); /* unlock current rec before proceeding */
if ((dberrno = dBpkey(dptr->ix_num[fptr->cur_key], xkeybuff, &recnum)) != SUCCESS)
{
if (dberrno == d_TOPKEY)
return(IOTOF);
return(io_xlate(fd_sys, dberrno, "dBC PREV"));
}
return(get_record(fd_sys, buffer, PREV));
}
/*
* Retrieve a record
* - record locking is taken care of here
* - if nextone is TRUE, will try next record when passing over a deleted
* record; otherwise will try previous record
*/
static int get_record(fd_sys, buffer, nextone)
int fd_sys, nextone;
char *buffer;
{
char stat;
struct dbc_def *dptr = &fdbf[fd_sys];
if (i_lockrec(fd_sys, buffer) != IOGOOD)
return(IOERROR);
if ((dberrno = dBflush(dptr->dbf_num)) != SUCCESS)
{
i_unlock_rec(fd_sys, buffer);
return(io_xlate(fd_sys, dberrno, "dBC GETREC1"));
}
if ((dberrno = dBgetr(dptr->dbf_num, recnum, storbuff, &stat)) != SUCCESS)
{
i_unlock_rec(fd_sys, buffer);
return(io_xlate(fd_sys, dberrno, "dBC GETREC2"));
}
if (stat == INACTIVE) /* skip over record if flagged as deleted */
return(nextone ? i_nextrec(fd_sys, buffer) : i_prevrec(fd_sys, buffer));
db2buff(fd_sys, storbuff, buffer); /* back to PRO-C form */
bytecpy(oldbuff, buffer, fd[fd_sys].rec_len); /* copy original rec */
return(IOGOOD);
}
/*
* Re-read/reposition record pointer function - if required
*/
static int i_rereadrec(fd_sys, buffer)
int fd_sys;
char *buffer;
{
return(i_findkey(fd_sys, buffer));
}
/*
* Add a new record.
*/
static int i_addrec(fd_sys, buffer)
int fd_sys;
char *buffer;
{
struct dbc_def *dptr = &fdbf[fd_sys];
buff2db(fd_sys, buffer, storbuff);
if (!lock_sizebyte(fd_sys, buffer)) /* append only if sizebyte locked */
return(IOERROR);
if (!lock_ndx(fd_sys)) /* index lock failure */
{
unlock_sizebyte(fd_sys);
return(IOERROR);
}
if (!lock_mem(fd_sys))
{
unlock_sizebyte(fd_sys);
unlock_ndx(fd_sys, buffer);
return(IOERROR);
}
if ((dberrno = dBputr(dptr->dbf_num, APPEND, storbuff)) != SUCCESS)
{
unlock_sizebyte(fd_sys);
unlock_ndx(fd_sys, buffer); /* also unlocks record */
return(io_xlate(fd_sys, dberrno, "dBC ADD1"));
}
if ((dberrno = dBflush(dptr->dbf_num)) != SUCCESS)
{
unlock_sizebyte(fd_sys);
unlock_ndx(fd_sys, buffer);
return(io_xlate(fd_sys, dberrno, "dBC ADD2"));
}
unlock_sizebyte(fd_sys);
recnum = _appnded; /* external dBC variable rec number */
return(update_keys(fd_sys, buffer, FALSE)); /* now add key to indexes */
}
/*
* Update the current record.
*/
static int i_updrec(fd_sys, buffer)
int fd_sys;
char *buffer;
{
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
if (i_lockrec(fd_sys, buffer) == IOGOOD)
{
if ((dberrno = dBckey(dptr->ix_num[fptr->cur_key], xkeybuff, &recnum)) != SUCCESS)
{
i_unlock_rec(fd_sys, buffer);
return(io_xlate(fd_sys, dberrno, "dBC UPD1"));
}
if (!lock_ndx(fd_sys)) /* index lock failure */
i_unlock_rec(fd_sys, buffer);
else /* update only if indexes locked successfully */
{
if (!lock_mem(fd_sys))
{
unlock_ndx(fd_sys, buffer);
return(IOERROR);
}
buff2db(fd_sys, buffer, storbuff);
if ((dberrno = dBupdr(dptr->dbf_num, recnum, storbuff)) != SUCCESS)
{
unlock_ndx(fd_sys, buffer); /* also unlocks record */
return(io_xlate(fd_sys, dberrno, "dBC UPD2"));
}
if ((dberrno = dBflush(dptr->dbf_num)) != SUCCESS)
{
unlock_ndx(fd_sys, buffer);
return(io_xlate(fd_sys, dberrno, "dBC UPD3"));
}
return(update_keys(fd_sys, buffer, TRUE)); /* now update indexes */
}
}
return(IOERROR);
}
/*
* Index key update function
* - if updating argument = TRUE, old key occurrences are removed first
*/
static int update_keys(fd_sys, buffer, updating)
int fd_sys, updating;
char *buffer;
{
int ck, j = 0, result = IOGOOD;
struct dbc_def *dptr = &fdbf[fd_sys];
ck = fd[fd_sys].cur_key;
while (fd[fd_sys].keys[j].segcount != -1)
{
fd[fd_sys].cur_key = j;
if (updating) /* removes old key values from the indexes */
{
setupkey(fd_sys, oldbuff, xkeybuff); /* old key value */
if ((dberrno = dBrmvkey(dptr->ix_num[j], xkeybuff, recnum)) != SUCCESS)
{
result = io_xlate(fd_sys, dberrno, "dBC KEYRMV");
break;
}
}
setupkey(fd_sys, buffer, keybuff); /* new key value */
if ((dberrno = dBakey(dptr->ix_num[j], keybuff, recnum)) != SUCCESS)
{
result = io_xlate(fd_sys, dberrno, "dBC KEYADD1");
break;
}
if ((dberrno = dBiflsh(dptr->ix_num[j])) != SUCCESS)
{
result = io_xlate(fd_sys, dberrno, "dBC KEYADD2");
break;
}
j++;
}
unlock_ndx(fd_sys, buffer); /* also unlocks data record */
fd[fd_sys].cur_key = ck;
return(result);
}
/*
* dBC III delete record function
* - this only marks records inactive; no PACK is available with dBC III+
* - indexes are not changed; relies on detection of inactive flag to skip
* deleted records in retrievals
*/
static int i_delrec(fd_sys, buffer)
int fd_sys;
char *buffer;
{
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
if (i_lockrec(fd_sys, buffer) != IOGOOD)
return(IOERROR);
if ((dberrno = dBckey(dptr->ix_num[fptr->cur_key], keybuff, &recnum)) != SUCCESS)
{
i_unlock_rec(fd_sys, buffer);
return(io_xlate(fd_sys, dberrno, "dBC DEL1"));
}
if ((dBdelete(dptr->dbf_num, recnum)) != SUCCESS)
{
i_unlock_rec(fd_sys, buffer);
return(io_xlate(fd_sys, dberrno, "dBC DEL2"));
}
if ((dberrno = dBflush(dptr->dbf_num)) != SUCCESS)
{
i_unlock_rec(fd_sys, buffer);
return(io_xlate(fd_sys, dberrno, "dBC DEL3"));
}
i_unlock_rec(fd_sys, buffer);
return(IOGOOD);
}
/*
* Lock Record - gets number of current record first
*/
static int i_lockrec(fd_sys, buffer)
int fd_sys;
char *buffer;
{
struct fd_def *fptr = &fd[fd_sys];
struct dbc_def *dptr = &fdbf[fd_sys];
if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
return(IOGOOD);
if ((dberrno = dBckey(dptr->ix_num[fptr->cur_key], xkeybuff, &recnum)) != SUCCESS)
{
if ((dberrno == d_TOPKEY) || (dberrno == d_ENDKEY))
return(IOGOOD); /* bypass retry count if EOF/TOF */
return(io_xlate(fd_sys, dberrno, "dBC LOCK1"));
}
dberrno = dBlockr(dptr->dbf_num, recnum, (RECNUM)1, d_TLOCK);
if ((dberrno != SUCCESS) && (dberrno != d_SELFLK))
return(io_xlate(fd_sys, dberrno, "dBC LOCK2"));
return(IOGOOD);
}
/*
* Unlock Record
*/
static int i_unlock_rec(fd_sys, buffer)
int fd_sys;
char *buffer;
{
if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
return(IOGOOD);
dberrno = dBlockr(fdbf[fd_sys].dbf_num, recnum, (RECNUM)1, d_TEST);
if (dberrno == d_FREE)
return(IOGOOD);
dberrno = dBlockr(fdbf[fd_sys].dbf_num, recnum, (RECNUM)1, d_ULOCK);
if ((dberrno != SUCCESS) && (dberrno != d_FREE))
return(io_xlate(fd_sys, dberrno, "dBC ULOCK"));
return(IOGOOD);
}
/*
* Lock Size Bytes of .DBF file for record append
*/
static int lock_sizebyte(fd_sys, buffer)
int fd_sys;
char *buffer;
{
int timeout;
if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
return(TRUE);
timeout = fd[fd_sys].lockmode;
do
{
dberrno = dBlocksz(fdbf[fd_sys].dbf_num, d_TLOCK);
if ((dberrno == SUCCESS) || (dberrno == d_SELFLK))
return(TRUE);
}
while (--timeout > 0);
i_unlock_rec(fd_sys, buffer); /* no add if sizebyte unavailable */
io_xlate(fd_sys, dberrno, "dBC LCKSIZ");
return(FALSE);
}
/*
* Unlock Size Bytes of .DBF file for record append
*/
static void unlock_sizebyte(fd_sys)
int fd_sys;
{
if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
return;
dberrno = dBlocksz(fdbf[fd_sys].dbf_num, d_TEST);
if (dberrno == d_FREE)
return;
dberrno = dBlocksz(fdbf[fd_sys].dbf_num, d_ULOCK);
if ((dberrno != SUCCESS) && (dberrno != d_FREE))
io_xlate(fd_sys, dberrno, "dBC ULCKSIZ");
}
/*
* Lock all indexes associated with a file for append/update
*/
static int lock_ndx(fd_sys)
int fd_sys;
{
int j = 0, k, timeout;
struct dbc_def *dptr = &fdbf[fd_sys];
if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
return(TRUE);
while (fd[fd_sys].keys[j].segcount != -1)
{
timeout = fd[fd_sys].lockmode;
do
{
dberrno = dBlocki(dptr->ix_num[j], d_TLOCK);
if ((dberrno == SUCCESS) || (dberrno == d_SELFLK))
break;
}
while (--timeout > 0);
if ((dberrno != SUCCESS) && (dberrno != d_SELFLK))
{
io_xlate(fd_sys, dberrno, "dBC LCKNDX");
for (k = 0; k < j; k++) /* unlock any already locked */
dBlocki(dptr->ix_num[k], d_ULOCK);
return(FALSE);
}
j++;
}
return(TRUE);
}
/*
* Unlock all index files associated with a datafile
* - calls record unlock function afterwards
*/
static int unlock_ndx(fd_sys, buffer)
int fd_sys;
char *buffer;
{
int j = 0;
if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
return(IOGOOD);
while (fd[fd_sys].keys[j].segcount != -1)
{
dberrno = dBlocki(fdbf[fd_sys].ix_num[j], d_TEST);
if (dberrno != d_FREE)
{
dberrno = dBlocki(fdbf[fd_sys].ix_num[j], d_ULOCK);
if ((dberrno != SUCCESS) && (dberrno != d_FREE))
io_xlate(fd_sys, dberrno, "dBC ULCKNDX");
}
j++;
}
unlock_mem(fd_sys);
return(i_unlock_rec(fd_sys, buffer));
}
/*
* Lock memo file associated with a file for append/update
*/
static int lock_mem(fd_sys)
int fd_sys;
{
int timeout;
struct dbc_def *dptr = &fdbf[fd_sys];
if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
return(TRUE);
if (!dptr->mm_num) /* no memos */
return(TRUE);
timeout = fd[fd_sys].lockmode;
do
{
dberrno = dBlockm(dptr->mm_num, d_TLOCK);
if ((dberrno == SUCCESS) || (dberrno == d_SELFLK))
break;
}
while (--timeout > 0);
if ((dberrno != SUCCESS) && (dberrno != d_SELFLK))
{
io_xlate(fd_sys, dberrno, "dBC LCKMEM");
return(FALSE);
}
return(TRUE);
}
/*
* Unlock memo file associated with a datafile
*/
static void unlock_mem(fd_sys)
int fd_sys;
{
if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
return;
if (!fdbf[fd_sys].mm_num)
return;
dberrno = dBlockm(fdbf[fd_sys].mm_num, d_TEST);
if (dberrno == d_FREE)
return;
dberrno = dBlockm(fdbf[fd_sys].mm_num, d_ULOCK);
if ((dberrno != SUCCESS) && (dberrno != d_FREE))
io_xlate(fd_sys, dberrno, "dBC ULCKMEM");
}
/*
* Set up target key
* - sets up a key string for record retrieval on current index
* - compound keys allowed only for character field types, so numerical
* segments are converted to strings and set up according to fmt mask
*/
static void setupkey(fd_sys, recbuf, keybuf)
int fd_sys;
char *recbuf, *keybuf;
{
int i, ofs, tlen, len, fx, so = 0, nnum, ndec;
int itmp;
long ltmp;
float ftmp;
double dtmp;
char tbuff[MAX_FLDLEN], *tptr;
struct fd_def *fptr = &fd[fd_sys];
struct keyinfo *kptr = &fd[fd_sys].keys[fd[fd_sys].cur_key];
memset(keybuf, (int)' ', MAX_FLDLEN * MAX_SEGS);
keybuf[0] = '\0';
for (i = 0; i < kptr->segcount; i++)
{
ofs = kptr->segstart[i];
tlen = kptr->seglen[i];
fx = kptr->fldindex[i];
if (fptr->flds[fx].fldtype == CHRTYP)
{
dBstrcpy(&keybuf[so], 'L', tlen, &recbuf[ofs]);
so += tlen;
}
else /* numerical or date keys conversion */
{
zerorec(tbuff, MAX_FLDLEN);
keybuf[so] = 'N';
switch(fptr->flds[fx].fldtype)
{
case DATTYP :
if (tlen == 6)
{
strncpy(tbuff, "19", 2);
strncpy(&tbuff[2], &recbuf[ofs], tlen);
keybuf[so] = 'D';
break;
} /* else fall through to LNGTYP for long int dates */
case LNGTYP : /* don't move this */
bytecpy(<mp, &recbuf[ofs], tlen);
ltoa(ltmp, tbuff, 10);
strcat(tbuff,".");
break;
case INTTYP :
bytecpy(&itmp, &recbuf[ofs], tlen);
itoa(itmp, tbuff, 10);
break;
case FLTTYP:
bytecpy(&ftmp, &recbuf[ofs], tlen);
gcvt((double)ftmp, 15, tbuff);
break;
case DBLTYP :
bytecpy(&dtmp, &recbuf[ofs], tlen);
gcvt(dtmp, 15, tbuff);
break;
}
if (kptr->segcount == 1)
{
dBatokey(tbuff, &keybuf[so]);
so += 8;
}
else /* part of compound key, so keep in string form */
{
if ((fptr->flds[fx].fldtype == DATTYP) && (fptr->flds[fx].fldlen == 6))
{
dBstrcpy(&keybuf[so], 'L', 8, tbuff);
so += 8;
}
else /* store value as ASCII using length/decimals of field */
{
if (fptr->flds[fx].fldtype == DATTYP) /* long int date */
{
nnum = 10;
ndec = 0;
}
else
{
nnum = nummasklen(fptr->flds[fx].fldmask);
ndec = decmasklen(fptr->flds[fx].fldmask);
}
/* now format number string using mask lengths */
if ((tptr = strchr(tbuff, (int)'.')) == NULL)
{
strcat(tbuff, ".00000");
tptr = strchr(tbuff, (int)'.');
}
len = strlen(tbuff) - strlen(tptr);
if (ndec > 0)
tbuff[len + ndec + 1] = '\0';
else
tbuff[len] = '\0';
memset(&keybuf[so], (int)' ', nnum);
if (nnum >= strlen(tbuff))
{
so += nnum - strlen(tbuff);
bytecpy(&keybuf[so], tbuff, strlen(tbuff));
so += strlen(tbuff);
}
else
so += nnum; /* if reaches this, does not store key */
}
}
}
}
}
/*
* Convert record to dBC III+ form from PRO-C buffer format before storing
*/
static void buff2db(fd_sys, P_buff, DB_buff)
int fd_sys;
char *P_buff, *DB_buff;
{
int ofst, ftyp, flen, lnum, ldec, i, so = 0, k = 0;
int itmp;
long ltmp;
float ftmp;
double dtmp;
char tstr[50];
struct fd_def *fptr = &fd[fd_sys];
memset(DB_buff, (int)' ', fdbf[fd_sys].dbrec_len);
for (i = 0; i < fd[fd_sys].fld_cnt; i++)
{
ftyp = fptr->flds[i].fldtype;
ofst = fptr->flds[i].fldstart;
flen = fptr->flds[i].fldlen;
lnum = nummasklen(fptr->flds[i].fldmask);
ldec = decmasklen(fptr->flds[i].fldmask);
if (ftyp == CHRTYP)
{
dBstrcpy(&DB_buff[so], 'L', flen, &P_buff[ofst]);
so += flen; /* offset for next field */
}
else if ((ftyp == DATTYP) && (flen == 6))
{
strncpy(&DB_buff[so], "19", 2); /* dBASE date format */
so += 2;
dBstrcpy(&DB_buff[so], 'L', flen, &P_buff[ofst]);
so += flen; /* offset for next field */
}
else if (ftyp == LOGTYP)
{
DB_buff[so] = P_buff[ofst];
so++;
}
else if (ftyp == MEMTYP)
{
if (P_buff[ofst]) /* write memo only if one exists */
{
zerorec(memobuff, 5000);
strncpy(memobuff, &P_buff[ofst], flen);
if (dBputm(fdbf[fd_sys].mm_num, memobuff, &DB_buff[so]) != SUCCESS)
errmsg(FileMemoNoWrite_ss, fptr->flds[i].fldname, fptr->filname);
}
k++; /* uses memo files in original field order */
so += 10;
}
else
{
switch(ftyp)
{
case INTTYP :
bytecpy(&itmp, &P_buff[ofst], flen);
itoa(itmp, tstr, 10);
strcat(tstr,".");
break;
case DATTYP : /* long int date type */
lnum = 10;
ldec = 0;
case LNGTYP : /* don't move this - long int date falls thru */
bytecpy(<mp, &P_buff[ofst], flen);
ltoa(ltmp, tstr, 10);
strcat(tstr,".");
break;
case FLTTYP :
bytecpy(&ftmp, &P_buff[ofst], flen);
gcvt((double)ftmp, lnum, tstr);
break;
case DBLTYP :
bytecpy(&dtmp, &P_buff[ofst], flen);
gcvt(dtmp, lnum, tstr);
break;
}
dBatofld(tstr, lnum, ldec, &DB_buff[so]);
so += lnum;
}
}
}
/*
* Convert record to PRO-C buffer format from dBC III+ form before returning
*/
static void db2buff(fd_sys, DB_buff, P_buff)
int fd_sys;
char *DB_buff, *P_buff;
{
int ftyp, ofst, flen, lnum, i, so = 0, k = 0;
int itmp;
long ltmp;
float ftmp;
double dtmp;
char tstr[50];
struct fd_def *fptr = &fd[fd_sys];
zerorec(P_buff, fptr->rec_len);
for (i = 0; i < fd[fd_sys].fld_cnt; i++)
{
ftyp = fptr->flds[i].fldtype;
ofst = fptr->flds[i].fldstart;
flen = fptr->flds[i].fldlen;
lnum = nummasklen(fptr->flds[i].fldmask);
if (ftyp == CHRTYP)
{
strncpy(&P_buff[ofst], &DB_buff[so], flen);
stripright(&P_buff[ofst], flen);
so += flen; /* offset for next field */
}
else if ((ftyp == DATTYP) && (flen == 6))
{
so += 2; /* ignore the "19" in the date */
strncpy(&P_buff[ofst], &DB_buff[so], flen);
stripright(&P_buff[ofst], flen);
so += flen; /* offset for next field */
}
else if (ftyp == LOGTYP)
{
P_buff[ofst] = DB_buff[so];
so++;
}
else if (ftyp == MEMTYP)
{
zerorec(memobuff, 5000);
if (dBgetm(fdbf[fd_sys].mm_num, &DB_buff[so], memobuff) != SUCCESS)
errmsg(FileMemoNoRead_ss, fptr->flds[i].fldname, fptr->filname);
strncpy(&P_buff[ofst], memobuff, flen);
k++;
so += 10;
}
else
{
if (ftyp == DATTYP) /* special case for long int date type */
lnum = 10;
zerorec(tstr, 50);
dBfldtoa(&DB_buff[so], lnum, tstr);
switch(ftyp)
{
case INTTYP :
itmp = atoi(tstr);
bytecpy(&P_buff[ofst], &itmp, flen);
break;
case DATTYP :
case LNGTYP :
ltmp = atol(tstr);
bytecpy(&P_buff[ofst], <mp, flen);
break;
case FLTTYP :
ftmp = (float)atof(tstr);
bytecpy(&P_buff[ofst], &ftmp, flen);
break;
case DBLTYP :
dtmp = atof(tstr);
bytecpy(&P_buff[ofst], &dtmp, flen);
break;
}
so += lnum;
}
}
}
/*
* Login
*/
static int i_login(fd_sys, buffer)
int fd_sys;
char *buffer;
{
return(IOGOOD);
}
/*
* Logoff
*/
static int i_logoff(fd_sys, buffer)
int fd_sys;
char *buffer;
{
return(IOGOOD);
}
/*
* End (Commit) transaction
*/
static int i_commit(fd_sys, buffer)
int fd_sys;
char *buffer;
{
return(IOGOOD);
}
/*
* Rollback transaction
*/
static int i_rollback(fd_sys, buffer)
int fd_sys;
char *buffer;
{
return(IOGOOD);
}
/*
* Start transaction
*/
static int i_transact(fd_sys, buffer)
int fd_sys;
char *buffer;
{
return(IOGOOD);
}
/*
* This routine translates dBC III+ Error codes into PRO-C error codes.
* If no PRO-C equivalent, displays the error number.
*/
static int io_xlate(fd_sys, ernum, rtnname)
int fd_sys;
int ernum;
char *rtnname;
{
switch(ernum)
{
case d_WTFAIL :
return IOBADOPEN;
case d_NODBF :
case d_NONDX :
return IONOFILE;
case d_MAYBE :
case d_NOTFND :
case d_TOPKEY :
case d_ENDKEY :
case d_NOKEY :
return IONOKEY;
case d_LOCKED :
return IOLOCKED;
case d_FREE :
return IONOLOCK;
}
if (fd_sys >= 0)
errmsg(FileDbgError_sdss, "dBC III Plus", ernum, fd[fd_sys].filname, rtnname);
else /* if routines called from generated apps without valid fd_sys */
errmsg(FileDbgError_sds, "dBC III Plus", ernum, rtnname);
errmsg(FileDbgError_sds, "dBC III Internal", _dbcerr, rtnname);
return(IOERROR);
}
/*
* Assign section
*/
void assign_IO_DB(dbnum)
int dbnum;
{
Fntab[dbnum - 1][0] = (int(*)())0; /* Empty */
Fntab[dbnum - 1][1] = i_init_file;
Fntab[dbnum - 1][2] = i_open_file;
Fntab[dbnum - 1][3] = i_close_file;
Fntab[dbnum - 1][4] = i_addrec;
Fntab[dbnum - 1][5] = i_delrec;
Fntab[dbnum - 1][6] = i_findkey;
Fntab[dbnum - 1][7] = i_firstkey;
Fntab[dbnum - 1][8] = i_lastkey;
Fntab[dbnum - 1][9] = i_lockrec;
Fntab[dbnum - 1][10] = i_nextrec;
Fntab[dbnum - 1][11] = i_prevrec;
Fntab[dbnum - 1][12] = i_unlock_rec;
Fntab[dbnum - 1][13] = i_updrec;
Fntab[dbnum - 1][14] = i_commit;
Fntab[dbnum - 1][15] = i_login;
Fntab[dbnum - 1][16] = i_logoff;
Fntab[dbnum - 1][17] = i_rollback;
Fntab[dbnum - 1][18] = i_transact;
Fntab[dbnum - 1][19] = i_selectinx;
Fntab[dbnum - 1][20] = i_rereadrec;
Fntab[dbnum - 1][21] = i_filename;
}