Category : Dbase (Clipper, FoxBase, etc) Languages Source Code
Archive   : DBTOC.ZIP
Filename : DBTOC.C

 
Output of file : DBTOC.C contained in archive : DBTOC.ZIP
/*-------------------------------------------------------------------------

*******This source was originally compiled with Lattice C V-3.11**********

These functions have been released into the public domain for
personal use only. If you find them of some use or would like to
use them for commercial purposes please send a donation of
$15.00 to the address below. The money will be used to
finance the BBS run by myself (LOGITEK). Good luck and happy
computing !

Paul McDonald
2200 Columbia Pike
Apt. 917
Arlington Va. 22204


---------------------------------------------------------------------------
Name: DBTOC

Description: This file contains the basic routines to read/write
dbase III files. A good understanding of the functions
can be gained by studying the header file DBASE.H, which
defines the data structures used.

Date Author Explanation
------------ ----------------- --------------------
11/18/87 Paul McDonald Original Author


----------------------------------------------------------------------------*/
#include "\lc\header\stdlib.h"
#include "\switch\c\dbase.h"

#define NULL 0
#define ERROR -1

/*---------------------------------------------------------------------------
Name: OPENDBF
Description: Opens a dbf file as r/w file, fills in the structure info
and returns a pointer to the DBF structure.
-----------------------------------------------------------------------------*/

DBF *opendbf(filename)

char *filename;
{

char *getmem();
FIELD *current;

DBF *tmp_ptr;
long offset;
int cntr;


/* attempt memory allocation for header struct */
if(!(tmp_ptr = (DBF *)getmem(sizeof(DBF)))){
return(NULL);
}


if( (tmp_ptr->fh = o_pen(filename,2) ) == ERROR) /* attempt to open the file for read/write access */
return(NULL);
cntr = 0;

while(filename[cntr])
tmp_ptr->filename[cntr] = filename[cntr++];
tmp_ptr->filename[cntr] = 0;

offset = 0; /* start from top of file */

l_seek(tmp_ptr->fh,offset,0);

r_ead(tmp_ptr->fh,&(tmp_ptr->header),sizeof(DBF_HEAD)); /* fill in the header struct from the file */

tmp_ptr->no_fields = ((tmp_ptr->header.head_len - 1)/32 - 1);

/* allocate memory for the first field structure */

if( ! ( tmp_ptr->fields = (FIELD *)getmem(sizeof(FIELD) ) ) )
printstr(0,0,"ERROR ALLOCATING MEMORY !!!");

r_ead(tmp_ptr->fh,tmp_ptr->fields,32); /* read in the first field */
tmp_ptr->fields->prev = (FIELD *)0L; /* start the list */
current = tmp_ptr->fields; /* current node on the list */
current->offset = 0L; /* first field is at offset 0 */
offset = current->fld_len;
/* allocate space for the fields actual value */
if(current->type != 'D'){
if( !(current->fld_val = getmem(current->fld_len + 1)))
printstr(0,0,"ERROR ALLOCATING MEMORY !!");
}else{ /* for dates allocate space for the slashes */
if( !(current->fld_val = getmem(current->fld_len + 3)))
printstr(0,0,"ERROR ALLOCATING MEMORY !!");
}
/* make the rest of the list */
for(cntr = 1; cntr < tmp_ptr->no_fields; ++cntr){
if( ! ( current->next = (FIELD *)getmem( sizeof(FIELD) ) ) )
printstr(0,0,"ERROR ALLOCATING MEMORY !!!");
r_ead(tmp_ptr->fh,current->next,32);
current->next->prev = current;
current = current->next;
current->offset = offset; /* offset of this field from beg. of the record */
/* allocate space for the fields actual value */
if(current->type != 'D'){
if( !(current->fld_val = getmem(current->fld_len + 1)))
printstr(0,0,"ERROR ALLOCATING MEMORY !!");
}else{ /* for dates allocate space for the slashes */
if( !(current->fld_val = getmem(current->fld_len + 3)))
printstr(0,0,"ERROR ALLOCATING MEMORY !!");
}

offset += current->fld_len; /* update next fields offset in record */
}
current->next = (FIELD *)0L; /* end of list = NULL */

/* allocate memory for the record buffer and read the first record */
if(!(tmp_ptr->record = getmem(tmp_ptr->header.rec_len)))
printstr(0,0,"ERROR ALLOCATING MEMORY !!!");

tmp_ptr->curr_rec = 0;
tmp_ptr->updated = 0; /* set the updated flag to false */
return(tmp_ptr);

}

/*-----------------------------------------------------------------------------
Name: READREC()

Description: - returns the given record in the DBF structure
will return 1 if successful, 0 if rec not in DBF.
-1 if read error;

Syntax: success = readrec(dbf_ptr,rec_num)
DBF *dbf_ptr;
long rec_num;
------------------------------------------------------------------------------*/

int readrec(dbf_ptr,rec_num)

DBF *dbf_ptr;
unsigned long rec_num;
{

long offset;

if(rec_num > dbf_ptr->header.no_recs)
return(0);

offset = dbf_ptr->header.head_len + ((rec_num - 1) * dbf_ptr->header.rec_len);

l_seek(dbf_ptr->fh,offset,0);

if( r_ead(dbf_ptr->fh,dbf_ptr->record,dbf_ptr->header.rec_len) < dbf_ptr->header.rec_len)
return(-1);
else
readbuf(dbf_ptr); /* read the i/o buffer and put the values
in the indiv. field buffers */
dbf_ptr->curr_rec = rec_num;

return(1);
}


/*-----------------------------------------------------------------------------
Name: WRITEREC()

Description: - writes record that is contained in the current record
structure to the specified record.
0 if record not found in dbf
1 if successfull
-1 if write error.

Syntax: success = writerec(dbf_ptr,rec_num)
DBF *dbf_ptr;
long rec_num;
------------------------------------------------------------------------------*/

int writerec(dbf_ptr,rec_num)

DBF *dbf_ptr;
unsigned long rec_num;
{

long offset;

if(rec_num > dbf_ptr->header.no_recs || rec_num < 1)
return(0);

offset = dbf_ptr->header.head_len + ((rec_num - 1) * dbf_ptr->header.rec_len);
l_seek(dbf_ptr->fh,offset,0);

writebuf(dbf_ptr); /* write the buffers back to the x-fer area */

if( w_rite(dbf_ptr->fh,dbf_ptr->record,dbf_ptr->header.rec_len) < dbf_ptr->header.rec_len)
return(-1);
dbf_ptr->curr_rec = rec_num;
dbf_ptr->updated = 1;
return(1);
}


/*----------------------------------------------------------------------------
Name: READBUF()

Description: Reads the record buffer and places the individual
field values in each fields buffer area.
Syntax: readbuf(dbf_ptr);
DBF *dbf_ptr;
---------------------------------------------------------------------------*/
int readbuf(dbf_ptr)
DBF *dbf_ptr;
{

int cntr,
buf_ptr,
fld_buf;

FIELD *work_ptr;

work_ptr = dbf_ptr->fields; /* get pointer to first field */
buf_ptr = 1; /* start at the second char of the buffer,
the first char is the logical deleted,
character either '*' or ' ' */
if(dbf_ptr->record[0] == '*')
dbf_ptr->deleted = 1;
else
dbf_ptr->deleted = 0;

for(cntr = 0; cntr< dbf_ptr->no_fields; ++cntr){
fld_buf = 0;

while(fld_buf < work_ptr->fld_len)
work_ptr->fld_val[fld_buf++] = dbf_ptr->record[buf_ptr++];

work_ptr->fld_val[fld_buf] = 0; /* put NULL at end */

work_ptr = work_ptr->next; /* goto next field */

}

return(0);

}


/*----------------------------------------------------------------------------
Name: WRITEBUF()

Description: Writes the record buffer and places the individual
field values in the record buffer.
Syntax: writebuf(dbf_ptr);
DBF *dbf_ptr;
---------------------------------------------------------------------------*/
int writebuf(dbf_ptr)
DBF *dbf_ptr;
{

int cntr,
buf_ptr,
fld_buf;
char null_flg;

FIELD *work_ptr;

work_ptr = dbf_ptr->fields; /* get pointer to first field */
buf_ptr = 1; /* start at the second character, first is
the deletion marker */

for(cntr = 0; cntr< dbf_ptr->no_fields; ++cntr){
fld_buf = 0;
null_flg = 0; /* if end of valid data in fld buff is hit */

while(fld_buf < work_ptr->fld_len){
if(!work_ptr->fld_val[fld_buf])
null_flg = 1;
if(!null_flg)
dbf_ptr->record[buf_ptr++] = work_ptr->fld_val[fld_buf++];
else
dbf_ptr->record[buf_ptr++] = ' '; /* pad with spaces */
}

work_ptr = work_ptr->next; /* goto next field */

}

return(0);

}


/*--------------------------------------------------------------------------
Name: APPEND()

Description: Adds a record to a dbase file, the entire record is filled
with spaces to initialize it.
Syntax: int append(dbf_ptr)
DBF *dbf_ptr;
returns 1 - successful
-1 - disk i/o
---------------------------------------------------------------------------*/
int append(dbf_ptr)

DBF *dbf_ptr;
{

unsigned int cntr;
long offset;
char eof_mark;

eof_mark = 26;

for(cntr=0; cntr < dbf_ptr->header.rec_len;++cntr)
dbf_ptr->record[cntr] = 0x20; /* fill with spaces */

offset = dbf_ptr->header.head_len + ((dbf_ptr->header.no_recs) * dbf_ptr->header.rec_len);
l_seek(dbf_ptr->fh,offset,0);


if( (w_rite(dbf_ptr->fh,dbf_ptr->record,dbf_ptr->header.rec_len)) < dbf_ptr->header.rec_len)
return(-1); /* error writing to disk */

++(dbf_ptr->header.no_recs);
dbf_ptr->curr_rec = dbf_ptr->header.no_recs;

offset += (dbf_ptr->header.rec_len);
l_seek(dbf_ptr->fh,offset,0); /* goto new EOF */
w_rite(dbf_ptr->fh,&eof_mark,1); /* put eof marker at eof */

readrec(dbf_ptr,dbf_ptr->curr_rec); /* read in the new record */

return(1); /* success */

}
/*---------------------------------------------------------------------------
Name: CLOSEDBF()

Description: Closes the dbf file updateing the header info.

Syntax: closedbf(dbf_ptr);
DBF *dbf_ptr;
----------------------------------------------------------------------------*/
int closedbf(dbf_ptr)

DBF *dbf_ptr;
{

FIELD *tmpfield,
*workptr;
unsigned int packdate,
sysdate();


if(dbf_ptr->updated){
packdate = sysdate(); /* get the system date */
dbf_ptr->header.dd = packdate & 0x001f; /* update file date */
dbf_ptr->header.mm = (packdate >> 5) & 0x000f;
dbf_ptr->header.yy = (packdate >> 9) + 80;
}

l_seek(dbf_ptr->fh,(long)0,0); /* go to BOF */
/* write updated header to disk */

w_rite(dbf_ptr->fh,&(dbf_ptr->header),sizeof(DBF_HEAD));

c_lose(dbf_ptr->fh);

tmpfield = dbf_ptr->fields;

workptr = tmpfield;
while(workptr){
workptr = tmpfield->next;
rlsmem(tmpfield->fld_val,tmpfield->fld_len + 1);
rlsmem((char *)tmpfield,sizeof(FIELD));
tmpfield = workptr;
}

rlsmem(dbf_ptr->record,dbf_ptr->header.rec_len);
rlsmem((char *)dbf_ptr,sizeof(DBF));

return(0);
}

/*-----------------------------------------------------------------------------
Name: DELETE()

Description: Logically deletes the given record

Syntax: success = delete(dbf_ptr,rec_num)
DBF *dbf_ptr;
long rec_num;
int success - 1 = successful
0 = record not found
(-1) = File i/o error
---------------------------------------------------------------------------*/
int delete(dbf_ptr,rec_num)

DBF *dbf_ptr;
long rec_num;
{

long offset;

if(dbf_ptr->header.no_recs < rec_num)
return(0);

dbf_ptr->curr_rec = rec_num;
dbf_ptr->deleted = 1;

offset = dbf_ptr->header.head_len + ((rec_num - 1) * dbf_ptr->header.rec_len);
l_seek(dbf_ptr->fh,offset,0); /* seek to the record */

if(w_rite(dbf_ptr->fh,"*",1) != 1) /* an asterisk logically deletes the record */
return(-1); /* must be a file i/o error */
else
return(1); /* it worked */

}

/*-----------------------------------------------------------------------------
Name: UNDELETE()

Description: Logically undeletes the given record

Syntax: success = undelete(dbf_ptr,rec_num)
DBF *dbf_ptr;
long rec_num;
int success - 1 = successful
0 = record not found
(-1) = File i/o error
---------------------------------------------------------------------------*/
int undelete(dbf_ptr,rec_num)

DBF *dbf_ptr;
long rec_num;
{

long offset;

if(dbf_ptr->header.no_recs < rec_num)
return(0);

dbf_ptr->curr_rec = rec_num; /* this becomes the curr record */
dbf_ptr->deleted = 0; /* reset deleted flag */

offset = dbf_ptr->header.head_len + ((rec_num - 1) * dbf_ptr->header.rec_len);
l_seek(dbf_ptr->fh,offset,0); /* seek to the record */

if(w_rite(dbf_ptr->fh," ",1) != 1) /* clear the asterisk */
return(-1); /* must be a file i/o error */
else
return(1); /* it worked */

}

/*---------------------------------------------------------------------------
Name: MAKHEAD()

Description: This function creates the first part of the dbf's header
on disk, subsequent calls to ADDFIELD() will allow you to
customize the rest of the header to your needs.
----------------------------------------------------------------------------*/
DBF *makhead(filename)

char *filename;
{

char *getmem();
DBF *tmp_ptr;
long offset;
int cntr;
unsigned int packdate,
sysdate();

/* attempt memory allocation for header struct */

if(!(tmp_ptr = (DBF *)getmem(sizeof(DBF)))){
return(NULL);
}
if( (tmp_ptr->fh = c_reate(filename,0) ) == ERROR) /* create file with NO special attributes */
return(NULL);
cntr = 0;
while(filename[cntr])
tmp_ptr->filename[cntr] = filename[cntr++];
tmp_ptr->filename[cntr] = 0;

tmp_ptr->header.vers = 3;
tmp_ptr->header.no_recs = 0;
tmp_ptr->header.head_len = sizeof(DBF_HEAD);
tmp_ptr->header.rec_len = 0; /* account for logical deletion char */
for(cntr=0; cntr<20; ++cntr)
tmp_ptr->header.reserved[cntr] = 0; /* clear out the reserved area */

packdate = sysdate(); /* get the system date */
tmp_ptr->header.dd = packdate & 0x001f;
tmp_ptr->header.mm = (packdate >> 5) & 0x000f;
tmp_ptr->header.yy = (packdate >> 9) + 80;

offset = 0; /* write the structure to disk */
l_seek(tmp_ptr->fh,offset,0);
w_rite(tmp_ptr->fh,&(tmp_ptr->header),sizeof(DBF_HEAD));

tmp_ptr->fields = NULL;
tmp_ptr->curr_rec = 0;
tmp_ptr->record = NULL; /* no record buffer allocated yet */
tmp_ptr->no_fields = 0;

return(tmp_ptr);

}

/*-----------------------------------------------------------------------------
Name: ADDFIELD()

Description: Adds a field descriptor structure to the structure
already written to disk. This function ONLY works
for files that have NO records in them.
Syntax: int addfield(dbf_ptr,fieldname,type,length,dec_cnt)
DBF *dbf_ptr;
char *fieldname,
type;
int length,
dec_cnt;
returns 1 - successful
0 - improper field type
-1 - file i/o error, or memory error


Note: This function has NOT been tested !!

------------------------------------------------------------------------------*/
int addfield(dbf_ptr,fieldname,type,length,dec_cnt)

DBF *dbf_ptr;
char *fieldname,
type;
unsigned int length,
dec_cnt;

{

char *getmem(),
cr_ret[2];
FIELD *tempptr,
*workptr;
long offset;
int cntr;
unsigned int packdate,
sysdate();

/* allocate memory for the field descriptor */
if(!(tempptr = (FIELD *)getmem(sizeof(FIELD)))){
return(NULL);
}

for(cntr = 0; cntr < 11 && fieldname[cntr]; ++cntr)
tempptr->name[cntr] = fieldname[cntr];
if(cntr < 10)
while(cntr < 12) /* padd with nulls */
tempptr->name[cntr++] = 0;
/* check for proper field type */
if(type != 'C' && type != 'D' && type != 'N' && type != 'L'){
rlsmem((char *)tempptr,sizeof(FIELD));
return(0);
}

tempptr->type = type;
tempptr->next = NULL;
tempptr->prev = NULL;
tempptr->fld_len = length;
tempptr->decimals = dec_cnt;
tempptr->offset = 0;
tempptr->fld_val = 0;

if(dbf_ptr->no_fields ==0)
offset = 0;
else
offset = -2; /* write over the CR and EOF marker at the end of the field space */

l_seek(dbf_ptr->fh,offset,2);
/* write the field descriptor to disk */

if( (w_rite(dbf_ptr->fh,tempptr,sizeof(FIELD))) != sizeof(FIELD) )
return(-1); /* error writing to file */
/* allocate space for
actual field value */
if( !(tempptr->fld_val = getmem(length + 1)))
return(-1);
tempptr->offset = dbf_ptr->header.rec_len+1; /* offset of field in the record */

dbf_ptr->header.head_len += sizeof(FIELD);
if(dbf_ptr->record) /* release current rec buffer if allocated */
rlsmem(dbf_ptr->record,dbf_ptr->header.rec_len);
dbf_ptr->header.rec_len += length; /* update header info */
++dbf_ptr->no_fields;
/* allocate memory for a new rec buffer */
if(!(dbf_ptr->record = getmem(dbf_ptr->header.rec_len)))
return(-1); /* out of memory !!! */

if(!dbf_ptr->fields){ /* add this field descriptor to the linked list */
dbf_ptr->fields = tempptr;
tempptr->next = NULL;
tempptr->prev = NULL;
}else{
workptr = dbf_ptr->fields;
while(workptr->next)
workptr = workptr->next;

workptr->next = tempptr;
tempptr->prev = workptr;
tempptr->next = NULL;
}

packdate = sysdate(); /* get the system date */
dbf_ptr->header.dd = packdate & 0x001f; /* update file date */
dbf_ptr->header.mm = (packdate >> 5) & 0x000f;
dbf_ptr->header.yy = (packdate >> 9) + 80;

l_seek(dbf_ptr->fh,offset,0); /* goto top of file and rewrite header info */

if( (w_rite(dbf_ptr->fh,&(dbf_ptr->header),sizeof(DBF_HEAD))) != sizeof(DBF_HEAD) )
return(-1);

cr_ret[0] = 13; /* CR marks as a field delimeter */
cr_ret[1] = 26; /* EOF marker */
offset = 0;
l_seek(dbf_ptr->fh,offset,2); /* goto EOF */
if( (w_rite(dbf_ptr->fh,cr_ret,2)) != 2 )
return(-1);

return(1);

}
/*---------------------------------------------------------------------------
Name: ZAP()

Description: Deletes all records in a dbf file

Syntax: int zap(dbf_ptr)
DBF *dbf_ptr;
returns 1 - successful
-1 - file i/o error
---------------------------------------------------------------------------*/
int zap(dbf_ptr)
DBF *dbf_ptr;
{

long offset;
unsigned int packdate,
sysdate(),
tmpoff;

FIELD *workptr,
*tmpprev,
*tmpnext;
char *tmpval,
cr_ret[2];

char nulls[4];
int cntr;

for(cntr=0; cntr<4; ++cntr) /* bytes to write at end of each field descriptor */
*(nulls+cntr) = NULL;

if(c_lose(dbf_ptr->fh)) /* close the file */
return(-1);

if(_del(dbf_ptr->filename))
return(-1); /* delete the file */

if( ( dbf_ptr->fh = c_reate(dbf_ptr->filename,0)) < 0)
return(-1);

dbf_ptr->curr_rec = 0;
dbf_ptr->header.no_recs = 0;

packdate = sysdate(); /* get the system date */
dbf_ptr->header.dd = packdate & 0x001f; /* update file date */
dbf_ptr->header.mm = (packdate >> 5) & 0x000f;
dbf_ptr->header.yy = (packdate >> 9) + 80;

offset = 0;
l_seek(dbf_ptr->fh,offset,0); /* goto top of file and rewrite header info */

if( (w_rite(dbf_ptr->fh,&(dbf_ptr->header),sizeof(DBF_HEAD))) != sizeof(DBF_HEAD) )
return(-1);



workptr = dbf_ptr->fields; /* pointer to list of field descriptors */

for(cntr=0;cntrno_fields; ++cntr){
offset = 0;
l_seek(dbf_ptr->fh,offset,2); /* goto EOF */
tmpprev = workptr->prev;
tmpnext = workptr->next;
tmpoff = workptr->offset;
tmpval = workptr->fld_val;

workptr->prev = NULL;
workptr->next = NULL; /* clear these areas, as they are reserved */
workptr->offset = 0;
workptr->fld_val = 0;

if( (w_rite(dbf_ptr->fh,workptr,(sizeof(FIELD))) ) < (sizeof(FIELD)) )
return(-1);

workptr->prev = tmpprev;
workptr->next = tmpnext;
workptr->offset = tmpoff; /* reset the pointers,values */
workptr->fld_val = tmpval;

workptr=workptr->next;
}
cr_ret[0] = 13; /* CR marks as a field delimeter */
cr_ret[1] = 26; /* EOF marker */
offset = 0;
l_seek(dbf_ptr->fh,offset,2); /* goto EOF */
if( (w_rite(dbf_ptr->fh,cr_ret,2)) != 2 )
return(-1);

return(1);
}



  3 Responses to “Category : Dbase (Clipper, FoxBase, etc) Languages Source Code
Archive   : DBTOC.ZIP
Filename : DBTOC.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/