home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------
-
- *******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;cntr<dbf_ptr->no_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);
- }
-
-