home *** CD-ROM | disk | FTP | other *** search
- From: zeppelin@login.dknet.dk (Thomas B. Pedersen)
- Newsgroups: comp.sources.misc
- Subject: v44i060: typhoon - Typhoon Relational Database Management System, Part04/09
- Date: 17 Sep 1994 21:45:32 -0500
- Organization: Sterling Software
- Sender: kent@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <35g9kc$ohr@sparky.sterling.com>
- X-Md4-Signature: fdbca861c8379026e4074aaa3fd4d708
-
- Submitted-by: zeppelin@login.dknet.dk (Thomas B. Pedersen)
- Posting-number: Volume 44, Issue 60
- Archive-name: typhoon/part04
- Environment: SCO UNIX, Tandem NonStop UNIX, Sun Solaris, AIX, Linux, OS/2
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: typhoon/src/record.c typhoon/src/ty_auxfn.c
- # typhoon/src/ty_find.c typhoon/src/ty_refin.c typhoon/src/unix.c
- # typhoon/src/util/export.c
- # Wrapped by kent@sparky on Sat Sep 17 21:38:16 1994
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 4 (of 9)."'
- if test -f 'typhoon/src/record.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/record.c'\"
- else
- echo shar: Extracting \"'typhoon/src/record.c'\" \(9702 characters\)
- sed "s/^X//" >'typhoon/src/record.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : record.c
- X * Library : typhoon
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X * Contains record file functions.
- X *
- X * Functions:
- X * rec_open - Open a record file.
- X * rec_close - Close a record file.
- X * rec_add - Add a record to a file.
- X * rec_write - Write a record to a file.
- X * rec_delete - Delete a record.
- X * rec_read - Read a record.
- X * rec_frst - Read the first record in a file.
- X * rec_last - Read the last record in a file.
- X * rec_next - Read the next record in a file.
- X * rec_prev - Read the previous record in a file.
- X * rec_numrecords - Return the number of records in a file.
- X * rec_reccurr - Return the record number of the current record.
- X *
- X * $Log: record.c,v $
- X * Revision 1.2 1994/09/17 16:00:14 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:32 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: record.c,v 1.2 1994/09/17 16:00:14 tbp Exp $";
- X
- X#include <fcntl.h>
- X#include <errno.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <errno.h>
- X#ifdef UNIX
- X# include <unistd.h>
- X# ifdef __STDC__
- X# include <stdlib.h>
- X# endif
- X#else
- X# include <stdlib.h>
- X# include <io.h>
- X# include <sys\stat.h>
- X# include <stddef.h>
- X#endif
- X
- X#include <typhoon.h>
- X#include "ty_dbd.h"
- X#include "ty_type.h"
- X#include "ty_prot.h"
- X#include "ty_glob.h"
- X
- X
- X/*--------------------------- Function prototypes --------------------------*/
- Xstatic void putheader PRM( (RECORD *); )
- Xstatic void getheader PRM( (RECORD *); )
- X
- X/*--------------------------------- Macros ---------------------------------*/
- X#define recseek(R,pos) lseek(R->fh, R->H.recsize * (pos), SEEK_SET)
- X#define RECVERSION_ID "RecMan120"
- X#define RECVERSION_NUM 120
- X
- X
- Xstatic void putheader(R)
- XRECORD *R;
- X{
- X recseek(R, 0L);
- X write(R->fh, &R->H, sizeof(R->H));
- X}
- X
- X
- Xstatic void getheader(R)
- XRECORD *R;
- X{
- X recseek(R, 0L);
- X read(R->fh, &R->H, sizeof(R->H));
- X}
- X
- X
- X/*-------------------------------- rec_open ----=---------------------------*\
- X *
- X * Purpose : Opens a record file.
- X *
- X * Parameters: fname - File name.
- X * recsize - Record size.
- X * shared - Open file in shared mode?
- X *
- X * Returns : NULL - File could not be opened. db_status contains reason.
- X * else - Pointer to record file descriptor.
- X *
- X */
- X
- XRECORD *rec_open(fname, recsize, shared)
- Xchar *fname;
- Xunsigned recsize;
- Xint shared;
- X{
- X RECORD *R;
- X int isnew, fh;
- X
- X /* if file exists then read header record, otherwise create */
- X isnew = access(fname, 0);
- X
- X if( (fh=os_open(fname, O_BINARY|O_RDWR|O_CREAT,CREATMASK)) == -1 )
- X {
- X db_status = S_IOFATAL;
- X return NULL;
- X }
- X
- X /* Lock the file if it is not opened in shared mode */
- X if( !shared )
- X if( os_lock(fh, 0L, 1, 't') == -1 )
- X {
- X db_status = S_NOTAVAIL;
- X return NULL;
- X }
- X
- X if( (R=(RECORD *)malloc(sizeof(RECORD)+recsize)) == NULL )
- X {
- X os_close(fh);
- X db_status = S_NOMEM;
- X return NULL;
- X }
- X
- X R->fh = fh;
- X R->recno = 0;
- X
- X if( isnew )
- X {
- X unsigned headersize;
- X
- X R->H.datasize = recsize;
- X R->H.recsize = recsize + (int)offsetof(RECORDHEAD, data[0]);
- X R->H.first_deleted = 0;
- X R->H.first = 0;
- X R->H.last = 0;
- X R->H.numrecords = 0;
- X R->H.version = RECVERSION_NUM;
- X strcpy(R->H.id, RECVERSION_ID);
- X
- X R->first_possible_rec = (sizeof(R->H) + R->H.recsize - 1) / R->H.recsize;
- X
- X /* Beware that the record can be smaller than the header */
- X if( R->H.recsize < sizeof(R->H) )
- X headersize = R->first_possible_rec * R->H.recsize;
- X else
- X headersize = R->H.recsize;
- X
- X recseek(R, 0L);
- X write(fh, &R->H, headersize);
- X }
- X else
- X {
- X getheader(R);
- X
- X R->first_possible_rec = (sizeof(R->H) + R->H.recsize - 1) / R->H.recsize;
- X
- X if( R->H.version != RECVERSION_NUM )
- X {
- X db_status = S_VERSION;
- X os_close(fh);
- X free(R);
- X return NULL;
- X }
- X }
- X
- X strcpy(R->fname, fname);
- X
- X db_status = S_OKAY;
- X
- X return R;
- X}
- X
- X
- Xrec_close(R)
- XRECORD *R;
- X{
- X if( R->fh != -1 )
- X os_close(R->fh);
- X free(R);
- X R = NULL;
- X
- X RETURN S_OKAY;
- X}
- X
- X
- Xrec_dynclose(R)
- XRECORD *R;
- X{
- X if( R->fh != -1 )
- X {
- X close(R->fh);
- X R->fh = -1;
- X }
- X
- X RETURN S_OKAY;
- X}
- X
- Xrec_dynopen(R)
- XRECORD *R;
- X{
- X if( R->fh == -1 )
- X if( (R->fh=os_open(R->fname, O_BINARY|O_RDWR|O_CREAT,CREATMASK)) == -1 )
- X RETURN S_IOFATAL;
- X
- X RETURN S_OKAY;
- X}
- X
- X
- Xrec_add(R,data,rec)
- XRECORD *R; /* record file */
- Xvoid *data;
- Xulong *rec;
- X{
- X long recno;
- X
- X getheader(R);
- X
- X if( R->H.first_deleted )
- X {
- X recno = R->H.first_deleted;
- X
- X /* Get recno of next deleted */
- X lseek(R->fh, recno * R->H.recsize + (long)offsetof(RECORDHEAD, next), SEEK_SET);
- X read(R->fh, &R->H.first_deleted, sizeof(R->H.first_deleted));
- X }
- X else
- X recno = (lseek(R->fh, 0L, SEEK_END) + R->H.recsize - 1) / R->H.recsize;
- X
- X if( R->H.numrecords )
- X {
- X long pos;
- X
- X /* Adjust next-pointer of last record */
- X pos = R->H.last * R->H.recsize;
- X pos += offsetof(RECORDHEAD, next);
- X
- X lseek(R->fh, pos, SEEK_SET);
- X write(R->fh, &recno, sizeof recno);
- X
- X /* Set prev-pointer of new record */
- X R->rec.prev = R->H.last;
- X }
- X else
- X {
- X R->H.first = recno; /* Set new first pointer */
- X R->rec.prev = 0; /* There's no previous record */
- X }
- X
- X R->rec.next = 0; /* No next record since at end of chain */
- X
- X R->H.last = recno; /* Set last-pointer to new record */
- X R->H.numrecords++;
- X
- X R->rec.flags = 0;
- X memcpy(R->rec.data, data, R->H.datasize); /* Copy data to buffer */
- X lseek(R->fh, recno * R->H.recsize, SEEK_SET);
- X if( write(R->fh, &R->rec, R->H.recsize) != R->H.recsize ) /* Write chain and record */
- X RETURN S_IOFATAL;
- X
- X putheader(R);
- X *rec = recno;
- X
- X return S_OKAY;
- X}
- X
- X
- Xrec_write(R, data, recno)
- XRECORD *R;
- Xvoid *data;
- Xulong recno;
- X{
- X if( recno < R->first_possible_rec )
- X RETURN S_INVADDR;
- X
- X lseek(R->fh, R->H.recsize * recno + (long)offsetof(RECORDHEAD, data[0]), SEEK_SET);
- X write(R->fh, data, R->H.datasize);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- Xrec_delete(R, recno)
- XRECORD *R;
- Xulong recno;
- X{
- X getheader(R);
- X
- X /* Get previous and next pointers of record to be deleted */
- X lseek(R->fh, R->H.recsize * recno, SEEK_SET);
- X read(R->fh, &R->rec, sizeof R->rec);
- X
- X if( R->rec.flags & BIT_DELETED )
- X RETURN S_DELETED;
- X
- X /* Adjust previous pointer */
- X if( R->H.first == recno )
- X R->H.first = R->rec.next;
- X else
- X {
- X lseek(R->fh, R->H.recsize * R->rec.prev + (long)offsetof(RECORDHEAD, next), SEEK_SET);
- X write(R->fh, &R->rec.next, sizeof R->rec.next);
- X }
- X
- X /* Adjust next pointer */
- X if( R->H.last == recno )
- X R->H.last = R->rec.prev;
- X else
- X {
- X lseek(R->fh, R->H.recsize * R->rec.next + (long)offsetof(RECORDHEAD, prev), SEEK_SET);
- X write(R->fh, &R->rec.prev, sizeof R->rec.prev);
- X }
- X
- X /* Delete-mark the record and insert it in delete chain */
- X R->rec.flags |= BIT_DELETED;
- X R->rec.next = R->H.first_deleted;
- X R->rec.prev = 0;
- X
- X lseek(R->fh, R->H.recsize * recno, SEEK_SET);
- X write(R->fh, &R->rec, sizeof R->rec);
- X R->H.first_deleted = recno;
- X R->H.numrecords--;
- X
- X putheader(R);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- Xrec_read(R,data,recno)
- XRECORD *R;
- Xvoid *data;
- Xulong recno;
- X{
- X if( recno < R->first_possible_rec )
- X RETURN S_INVADDR;
- X
- X recseek(R, recno);
- X if( read(R->fh, &R->rec, R->H.recsize) < R->H.recsize )
- X RETURN S_NOTFOUND;
- X
- X if( R->rec.flags & BIT_DELETED )
- X RETURN S_DELETED;
- X
- X memcpy(data, R->rec.data, R->H.datasize);
- X R->recno = recno;
- X
- X RETURN S_OKAY;
- X}
- X
- X
- Xrec_frst(R, data)
- XRECORD *R;
- Xvoid *data;
- X{
- X getheader(R);
- X
- X return rec_read(R, data, R->H.first);
- X}
- X
- X
- Xrec_last(R, data)
- XRECORD *R;
- Xvoid *data;
- X{
- X getheader(R);
- X
- X return rec_read(R, data, R->H.last);
- X}
- X
- X
- Xrec_next(R, data)
- XRECORD *R;
- Xvoid *data;
- X{
- X if( CURR_REC )
- X return rec_read(R, data, R->rec.next);
- X else
- X return rec_frst(R, data);
- X}
- X
- X
- Xrec_prev(R, data)
- XRECORD *R;
- Xvoid *data;
- X{
- X if( CURR_REC )
- X return rec_read(R, data, R->rec.prev);
- X else
- X return rec_last(R, data);
- X}
- X
- X
- Xulong rec_numrecords(R, number)
- XRECORD *R;
- Xulong *number;
- X{
- X getheader(R);
- X
- X if( number )
- X *number = R->H.numrecords;
- X
- X return R->H.numrecords;
- X}
- X
- X
- Xrec_curr(R, recno)
- XRECORD *R;
- Xulong *recno;
- X{
- X if( recno )
- X *recno = R->recno;
- X
- X RETURN R->recno ? S_OKAY : S_NOCR;
- X}
- X
- X/* end-of-file */
- X
- X
- END_OF_FILE
- if test 9702 -ne `wc -c <'typhoon/src/record.c'`; then
- echo shar: \"'typhoon/src/record.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/record.c'
- fi
- if test -f 'typhoon/src/ty_auxfn.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/ty_auxfn.c'\"
- else
- echo shar: Extracting \"'typhoon/src/ty_auxfn.c'\" \(10481 characters\)
- sed "s/^X//" >'typhoon/src/ty_auxfn.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : ty_auxfn.c
- X * Library : typhoon
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X * Auxiliary functions for the API functions.
- X *
- X * Functions:
- X * set_keyptr - Return a pointer to a key or compound key.
- X * reckeycmp - Compare two (compound) keys in separate records.
- X * set_subcode - Set <db_subcode>.
- X * set_recfld -
- X * keyfind
- X * keyadd
- X * keydel
- X *
- X * $Log: ty_auxfn.c,v $
- X * Revision 1.2 1994/09/17 16:00:15 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:32 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: ty_auxfn.c,v 1.2 1994/09/17 16:00:15 tbp Exp $";
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <typhoon.h>
- X#include "ty_dbd.h"
- X#include "ty_type.h"
- X#include "ty_glob.h"
- X#include "ty_prot.h"
- X
- Xaux_getkey(id, key)
- XId id;
- XKey **key;
- X{
- X Field *fld;
- X int rc;
- X
- X /* Determine whether this id is a key id or a compound key id */
- X if( id < REC_FACTOR )
- X {
- X if( id >= DB->header.keys )
- X RETURN_RAP(S_NOTKEY);
- X
- X *key = &DB->key[id];
- X }
- X else
- X {
- X if( (rc = set_recfld(id, NULL, &fld)) != S_OKAY )
- X return rc;
- X
- X if( !(fld->type & FT_KEY) )
- X RETURN_RAP(S_NOTKEY);
- X
- X *key = &DB->key[fld->keyid];
- X }
- X
- X return S_OKAY;
- X}
- X
- X
- X
- X/*------------------------------- set_keyptr -------------------------------*\
- X *
- X * Purpose : Returns a pointer to the key value of <key>. This function
- X * is necessary because the fields of a compound can be spread
- X * all over the record.
- X *
- X * Parameters: key - Pointer to key table entry.
- X * buf - Buffer to store key value in.
- X *
- X *
- X * Returns : A pointer to the key value.
- X *
- X */
- X
- Xvoid *set_keyptr(key, buf)
- XKey *key;
- Xvoid *buf;
- X{
- X static char keybuf[KEYSIZE_MAX];
- X int n;
- X
- X CURR_KEY = key - DB->key;
- X
- X if( (n = key->fields) > 1 )
- X {
- X KeyField *keyfld = DB->keyfield + key->first_keyfield;
- X
- X /* Build compound key from record */
- X while( n-- )
- X {
- X memcpy(keybuf + keyfld->offset,
- X (char *)buf + DB->field[ keyfld->field ].offset,
- X DB->field[ keyfld->field ].size);
- X keyfld++;
- X }
- X
- X return (void *)keybuf;
- X }
- X
- X return (void *)((char *)buf + DB->field[ DB->keyfield[ key->first_keyfield ].field ].offset);
- X}
- X
- X
- X
- X
- X
- X/*-------------------------------- reckeycmp -------------------------------*\
- X *
- X * Purpose : The function compares two fields in separate records. This
- X * function is necessary because the fields of a compound can be
- X * spread all over the record (i.e. compound key).
- X *
- X * Parameters: key - Pointer to key struct.
- X * a - Pointer to first record buffer.
- X * b - Pointer to seconds record buffer.
- X *
- X * Returns : 0 - The keys match.
- X * !=0 - The keys do not match.
- X *
- X */
- X
- Xreckeycmp(key, a, b)
- XKey *key;
- Xvoid *a, *b;
- X{
- X KeyField *keyfld = DB->keyfield + key->first_keyfield;
- X Field *field;
- X int fields = key->fields;
- X int type, diff;
- X
- X CURR_KEY = key - DB->key;
- X
- X /* An optional key is regarded as changed if
- X * a) One and only one of the null determinatator is not set
- X * b) If both null determinators are set and the key values different
- X */
- X if( key->type & KT_OPTIONAL )
- X {
- X int a_null = null_indicator(key, a);
- X int b_null = null_indicator(key, b);
- X
- X if( a_null && b_null )
- X return 0;
- X
- X if( a_null || b_null )
- X return 1;
- X
- X /* Otherwise both keys are not null - compare */
- X }
- X
- X do
- X {
- X field = DB->field + keyfld->field;
- X type = field->type & (FT_BASIC|FT_UNSIGNED);
- X
- X if( diff = (*keycmp[type])((char *)a + field->offset, (char *)b + field->offset) )
- X break;
- X
- X keyfld++;
- X }
- X while( --fields );
- X
- X /* Ascending or descending is not significant here */
- X return diff;
- X}
- X
- X
- X
- X/*------------------------------- set_subcode ------------------------------*\
- X *
- X * Purpose : This function sets <db_subcode> to the id of <key>. The id
- X * can either be a compound key id or a field id.
- X *
- X * Parameters: key - Pointer to key table entry.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid set_subcode(key)
- XKey *key;
- X{
- X Field *fld;
- X
- X if( key->fields > 1 )
- X db_subcode = key - DB->key /* + 1 */;
- X else
- X {
- X fld = DB->field + DB->keyfield[ key->first_keyfield ].field;
- X
- X db_subcode = (fld->recid + 1) * REC_FACTOR +
- X (fld - DB->field) - DB->record[ fld->recid ].first_field + 1;
- X }
- X}
- X
- X
- X
- X/*------------------------------- set_recfld -------------------------------*\
- X *
- X * Purpose : This function sets the pointers <recptr> and <fldptr> to the
- X * record and field denoted by <id>. The following calls are
- X * legal:
- X *
- X * If <id> is -1, <rec> will be set to the current record (<CURR_RECID>) a
- X * <fld> to the first field of that record.
- X *
- X * Both <rec> and <fld> may be NULL.
- X *
- X * Parameters: id - Record or field id.
- X * recptr - Pointer to record pointer.
- X * fldptr - Pointer to field pointer.
- X *
- X * Returns : S_OKAY - recid and fldid were okay, recptr and fldptr set.
- X * S_NOCD - No current database.
- X * S_INVREC - Invalid record id.
- X * S_INVFLD - Invalid field id.
- X *
- X */
- X
- Xset_recfld(id, recptr, fldptr)
- XId id;
- XRecord **recptr;
- XField **fldptr;
- X{
- X Id recid, fldid;
- X
- X if( CURR_DB == -1 )
- X RETURN_RAP(S_NOCD);
- X
- X /* If is -1 the return pointers to the current record */
- X if( id == -1 )
- X {
- X recid = CURR_RECID;
- X fldid = DB->record[recid].first_field;
- X }
- X else
- X {
- X /* Remove record factor */
- X recid = id / REC_FACTOR - 1;
- X
- X if( fldid = id % REC_FACTOR )
- X fldid--;
- X
- X /* Validate record id */
- X if( recid >= DB->header.records )
- X RETURN_RAP(S_INVREC);
- X
- X /* Validate field id */
- X if( fldid >= DB->record[recid].fields )
- X RETURN_RAP(S_INVFLD);
- X
- X fldid += DB->record[recid].first_field;
- X CURR_RECID = recid;
- X }
- X
- X if( recptr )
- X *recptr = DB->record + recid;
- X
- X if( fldptr )
- X *fldptr = DB->field + fldid;
- X
- X RETURN S_OKAY;
- X}
- X
- X
- Xkeyfind(key, buf, ref)
- XKey *key;
- Xvoid *buf;
- Xulong *ref;
- X{
- X CURR_KEY = key - DB->key;
- X
- X return ty_keyfind(key, set_keyptr(key, buf), ref);
- X}
- X
- X
- Xkeyadd(key, buf, ref)
- XKey *key;
- Xvoid *buf;
- Xulong ref;
- X{
- X CURR_KEY = key - DB->key;
- X
- X return ty_keyadd(key, set_keyptr(key, buf), ref);
- X}
- X
- X
- Xkeydel(key, buf, ref)
- XKey *key;
- Xvoid *buf;
- Xulong ref;
- X{
- X CURR_KEY = key - DB->key;
- X
- X return ty_keydel(key, set_keyptr(key, buf), ref);
- X}
- X
- X
- X/*------------------------------ compress_vlr ------------------------------*\
- X *
- X * Purpose : Compresses or uncompresses a the variable length record
- X * defined by <rec>.
- X *
- X * Parameters: action - COMPRESS/UNCOMPRESS.
- X * rec - Pointer to record table entry.
- X * src - Pointer to source buffer.
- X * dest - Pointer to destination buffer.
- X * size - Will contain compressed size when the function returns.
- X *
- X * Returns : -1 - Error. db_status set to cause.
- X * > 0 - Size of compress record in <dest>.
- X *
- X */
- Xcompress_vlr(action, rec, dest, src, size)
- Xint action;
- XRecord *rec;
- Xvoid *src, *dest;
- Xunsigned *size;
- X{
- X Field *fld;
- X unsigned offset;
- X ushort count;
- X int fields = rec->fields;
- X int fldno = 0;
- X
- X /* Find the first variable length field (this cannot be 0)*/
- X fld = &DB->field[rec->first_field];
- X
- X while( fields )
- X if( fld->type & FT_VARIABLE )
- X break;
- X else
- X fld++, fields--;
- X
- X /* Copy the static part of the record */
- X memcpy(dest, src, offset = fld->offset);
- X
- X while( fields )
- X {
- X /* Get the value of the size field (stored in keyid) */
- X count = *(ushort *)((char *)src + DB->field[ fld->keyid ].offset) * fld->elemsize;
- X
- X /* If the size value is too high report an error to the user */
- X if( count > fld->size )
- X {
- X db_subcode = (fld->recid + 1) * REC_FACTOR + fld->keyid + 1;
- X RETURN S_RECSIZE;
- X }
- X
- X if( action == COMPRESS )
- X memcpy((char *)dest + offset, (char *)src + fld->offset, count);
- X else
- X memcpy((char *)dest + fld->offset, (char *)src + offset, count);
- X
- X offset += count;
- X
- X /* Find next variable length field */
- X if( !--fields )
- X break;
- X
- X fld++;
- X while( fld->nesting )
- X fld++, fields--;
- X }
- X
- X if( action == COMPRESS )
- X *size = offset;
- X
- X return S_OKAY;
- X}
- X
- X
- X/*----------------------------- null_indicator -----------------------------*\
- X *
- X * Purpose : This function checks whether the null indicator of an optional
- X * key is set.
- X *
- X * Parameters: key - Pointer to key.
- X * buf - Pointer to record buffer.
- X *
- X * Returns : 0 - The null indicator is set.
- X * 1 - The null indicator is not set.
- X *
- X */
- Xnull_indicator(key, buf)
- XKey *key;
- Xvoid *buf;
- X{
- X return !(((char *)buf)[ DB->field[ key->null_indicator ].offset ]);
- X}
- X
- X
- X
- X/*------------------------------ update_recbuf -----------------------------*\
- X *
- X * Purpose : Makes sure that the contents of the current record is the same
- X * in DB->recbuf as on the disk.
- X *
- X * Parameters: None.
- X *
- X * Returns : None.
- X *
- X */
- X
- Xupdate_recbuf()
- X{
- X Record *rec = DB->record + CURR_RECID;
- X int rc;
- X unsigned recsize;
- X
- X/* if( curr_bufrec == CURR_REC && curr_bufrecid == CURR_RECID )
- X return S_OKAY;*/
- X
- X DB->recbuf = DB->real_recbuf + rec->preamble;
- X
- X if( rec->is_vlr )
- X rc = ty_vlrread(rec, DB->real_recbuf, CURR_REC, &recsize);
- X else
- X rc = ty_recread(rec, DB->real_recbuf, CURR_REC);
- X
- X CURR_BUFREC = CURR_REC;
- X CURR_BUFRECID = CURR_RECID;
- X
- X return rc;
- X}
- X
- X/* end-of-file */
- END_OF_FILE
- if test 10481 -ne `wc -c <'typhoon/src/ty_auxfn.c'`; then
- echo shar: \"'typhoon/src/ty_auxfn.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/ty_auxfn.c'
- fi
- if test -f 'typhoon/src/ty_find.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/ty_find.c'\"
- else
- echo shar: Extracting \"'typhoon/src/ty_find.c'\" \(10221 characters\)
- sed "s/^X//" >'typhoon/src/ty_find.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : ty_find.c
- X * Library : typhoon
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X * Contains API functions.
- X *
- X * Functions:
- X * report_err - Report an error to the user.
- X * d_keyread - Read the value of the last retrieved key.
- X * d_keyfind - Find a key.
- X * d_keymove - Perform a d_keyfrst(), d_keylast(), d_keyprev() or
- X * d_keynext().
- X * d_recmove - Perform a d_recfrst(), d_reclast(), d_recprev() or
- X * d_recnext().
- X * d_crread - Read the value of a field of the current record.
- X * d_recwrite - Update a record.
- X * d_recread - Read the current record.
- X * d_fillnew - Add a new record to the database.
- X * d_delete - Delete the current record.
- X * d_crget - Get the database address of the current record.
- X * d_crset - Set the database address of the current record.
- X * d_records - Return the number of records in a file.
- X * d_getkeysize - Return the size of a key.
- X * d_getrecsize - Return the size of a record.
- X *
- X * $Log: ty_find.c,v $
- X * Revision 1.2 1994/09/17 16:00:15 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:33 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: ty_find.c,v 1.2 1994/09/17 16:00:15 tbp Exp $";
- X
- X#ifdef UNIX
- X# include <unistd.h>
- X#endif
- X#include <string.h>
- X#include <stdio.h>
- X#include <typhoon.h>
- X#include "ty_dbd.h"
- X#include "ty_type.h"
- X#include "ty_glob.h"
- X#include "ty_prot.h"
- X
- X/*--------------------------- Function prototypes --------------------------*/
- Xstatic int d_keymove PRM( (Id, int); )
- Xstatic int d_recmove PRM( (Id, int); )
- X
- X
- X/*-------------------------------- d_keyread -------------------------------*\
- X *
- X * Purpose : Copies the contents of the current key into the buffer <buf>.
- X *
- X * Parameters: buf - Pointer to key buffer. This buffer must be large
- X * enough to hold the entire key.
- X *
- X * Returns : S_NOCR - No current record.
- X * S_OKAY - Key copied ok.
- X *
- X */
- X
- XFNCLASS d_keyread(buf)
- Xvoid *buf;
- X{
- X /* Make sure that we have a current record */
- X if( db_status != S_OKAY )
- X RETURN_RAP(S_NOCR);
- X
- X /* Make sure that we have performed a key operation ....
- X
- X ?????????????????????????????????????
- X
- X RETURN_RAP(S_KEYSEQ);
- X
- X */
- X
- X /*return db_keyread(&db->key[curr-key], buf);*/
- X
- X memcpy(buf, typhoon.curr_keybuf, DB->key[CURR_KEY].size);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X
- X/*-------------------------------- d_keyfind -------------------------------*\
- X *
- X * Purpose : Find a key in an index.
- X *
- X * Parameters: id - Either key id or field id that is also a key.
- X *
- X * Returns : S_OKAY - The key was found. The record can be read by
- X * d_recread().
- X * S_NOTFOUND - The key could not be found.
- X * S_NOCD - No current database.
- X * S_NOTKEY - The id is not a key id.
- X *
- X */
- X
- XFNCLASS d_keyfind(id, keyptr)
- XId id;
- Xvoid *keyptr;
- X{
- X Key *key;
- X int rc;
- X
- X /* Make sure that a database is open */
- X if( CURR_DB == -1 )
- X RETURN_RAP(S_NOCD);
- X
- X /* Determine whether this id is a key id or a compound key id */
- X if( id < REC_FACTOR )
- X {
- X if( id >= DB->header.keys )
- X RETURN_RAP(S_NOTKEY);
- X
- X key = &DB->key[id];
- X
- X CURR_RECID = DB->field[ DB->keyfield[ key->first_keyfield ].field ].recid;
- X }
- X else
- X {
- X Field *fld;
- X
- X if( (rc = set_recfld(id, NULL, &fld)) != S_OKAY )
- X return rc;
- X
- X if( !(fld->type & FT_KEY) )
- X RETURN_RAP(S_NOTKEY);
- X
- X key = &DB->key[ fld->keyid ];
- X }
- X
- X ty_lock();
- X
- X CURR_KEY = key - DB->key;
- X
- X rc = ty_keyfind(key, keyptr, &CURR_REC);
- X
- X ty_unlock();
- X
- X RETURN rc;
- X}
- X
- X
- X
- X/*-------------------------------- d_keymove -------------------------------*\
- X *
- X * Purpose : Perform a d_keyfrst(), d_keylast(), d_keyprev() or d_keylast()
- X * on an index. This function is called the macros defined in
- X * typhoon.h.
- X *
- X * Parameters: id - Field id.
- X * direction - 0 = next, 1 = prev, 2 = first, 3 = last
- X *
- X * Returns : S_OKAY - Operation performed successfully.
- X * S_NOTFOUND - Not found.
- X * S_NOTKEY - The id is not a key.
- X * S_NOCD - No current database.
- X *
- X */
- X
- Xstatic d_keymove(id, direction)
- XId id;
- Xint direction;
- X{
- X static int (*movefunc[])_PRM((Key *, ulong *)) =
- X { ty_keynext, ty_keyprev, ty_keyfrst, ty_keylast };
- X Key *key;
- X int rc;
- X
- X if( CURR_DB == -1 )
- X RETURN_RAP(S_NOCD);
- X
- X /* Determine whether this id is a key id or a compound key id */
- X if( id < REC_FACTOR )
- X {
- X if( id >= DB->header.keys )
- X RETURN_RAP(S_NOTKEY);
- X
- X key = &DB->key[id];
- X
- X CURR_RECID = DB->field[ DB->keyfield[ key->first_keyfield ].field ].recid;
- X }
- X else
- X {
- X Field *fld;
- X
- X if( (rc = set_recfld(id, NULL, &fld)) != S_OKAY )
- X return rc;
- X
- X if( !(fld->type & FT_KEY) )
- X RETURN_RAP(S_NOTKEY);
- X
- X key = &DB->key[ fld->keyid ];
- X }
- X
- X ty_lock();
- X CURR_KEY = key - DB->key;
- X rc = (*movefunc[direction])(key, &CURR_REC);
- X ty_unlock();
- X
- X RETURN rc;
- X}
- X
- X
- XFNCLASS d_keyfrst(field)
- Xulong field;
- X{
- X RETURN d_keymove(field, 2);
- X}
- X
- XFNCLASS d_keylast(field)
- Xulong field;
- X{
- X RETURN d_keymove(field, 3);
- X}
- X
- XFNCLASS d_keynext(field)
- Xulong field;
- X{
- X RETURN d_keymove(field, 0);
- X}
- X
- XFNCLASS d_keyprev(field)
- Xulong field;
- X{
- X RETURN d_keymove(field, 1);
- X}
- X
- X
- X/*-------------------------------- d_recmove -------------------------------*\
- X *
- X * Purpose : Perform a d_recnext(), d_recprev(), d_recfrst() or d_reclast()
- X * on a data file.
- X *
- X * Parameters: record - Record id.
- X * direction - 0 = next, 1 = prev, 2 = first, 3 = last
- X *
- X * Returns : S_OKAY - Operation performed successfully.
- X * S_NOTFOUND - Not found.
- X * S_NOCD - No current database.
- X *
- X */
- X
- Xd_recmove(record, direction)
- XId record;
- Xint direction;
- X{
- X static int (*movefunc[])_PRM((Record *, void *)) =
- X { ty_recnext, ty_recprev, ty_recfrst, ty_reclast };
- X Record *rec;
- X int rc;
- X
- X if( (rc = set_recfld(record, &rec, NULL)) != S_OKAY )
- X return rc;
- X
- X ty_lock();
- X if( (rc = (*movefunc[direction])(rec, DB->recbuf)) == S_OKAY )
- X {
- X ty_reccurr(rec, &CURR_REC);
- X CURR_BUFREC = CURR_REC; /* Mark buffer as updated */
- X }
- X else
- X CURR_REC = 0;
- X ty_unlock();
- X
- X RETURN rc;
- X}
- X
- X
- XFNCLASS d_recfrst(record)
- Xulong record;
- X{
- X RETURN d_recmove(record, 2);
- X}
- X
- XFNCLASS d_reclast(record)
- Xulong record;
- X{
- X RETURN d_recmove(record, 3);
- X}
- X
- XFNCLASS d_recnext(record)
- Xulong record;
- X{
- X RETURN d_recmove(record, 0);
- X}
- X
- XFNCLASS d_recprev(record)
- Xulong record;
- X{
- X RETURN d_recmove(record, 1);
- X}
- X
- X
- X
- X/*-------------------------------- d_crread --------------------------------*\
- X *
- X * Purpose : Read the contents of a field of the current record.
- X *
- X * Parameters: field - Field id.
- X * buf - Pointer to buffer where field will be stored.
- X *
- X * Returns : S_OKAY - Operation performed successfully.
- X * S_NOCD - No current database.
- X * S_NOCR - No current record.
- X * S_DELETED - The record has been deleted.
- X *
- X */
- X
- XFNCLASS d_crread(field, buf)
- XId field;
- Xvoid *buf;
- X{
- X Record *rec;
- X Field *fld;
- X int size, rc;
- X
- X if( (rc = set_recfld(field, &rec, &fld)) != S_OKAY )
- X return rc;
- X
- X if( !CURR_REC )
- X RETURN_RAP(S_NOCR);
- X
- X if( (rc = update_recbuf()) != S_OKAY )
- X return rc;
- X
- X if( fld->type & FT_VARIABLE )
- X /* Get the value of the size field (stored in keyid) */
- X size = *(ushort *)((char *)buf + DB->field[ fld->keyid ].offset) * fld->elemsize;
- X else
- X size = fld->size;
- X
- X memcpy(buf, (char *)DB->recbuf + fld->offset, size);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X
- X/*--------------------------------- d_crget --------------------------------*\
- X *
- X * Purpose : Get the database of the current record.
- X *
- X * Parameters: addr - Pointer to location where address will be stored.
- X *
- X * Returns : S_OKAY - Successful.
- X *
- X */
- X
- XFNCLASS d_crget(addr)
- XDB_ADDR *addr;
- X{
- X addr->recno = CURR_REC;
- X addr->recid = INTERN_TO_RECID(CURR_RECID);
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X
- X/*--------------------------------- d_crset --------------------------------*\
- X *
- X * Purpose : Set the database of the current record.
- X *
- X * Parameters: addr - Pointer to address of new record.
- X *
- X * Returns : S_OKAY - Successful.
- X *
- X */
- X
- XFNCLASS d_crset(addr)
- XDB_ADDR *addr;
- X{
- X ulong recid = addr->recid;
- X
- X recid = RECID_TO_INTERN(addr->recid);
- X
- X /* Validate record id */
- X if( recid >= DB->header.records )
- X RETURN S_INVREC;
- X
- X CURR_REC = addr->recno;
- X CURR_RECID = recid;
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X
- X/*-------------------------------- d_records -------------------------------*\
- X *
- X * Purpose : Return the number of records in a file.
- X *
- X * Parameters: record - Record id.
- X * number - Pointer to location where the value will be stored.
- X *
- X * Returns : S_OKAY - Number of records stored in <number>.
- X * S_NOCD - No current database.
- X * S_INVREC - Invalid record id.
- X *
- X */
- X
- XFNCLASS d_records(record, number)
- XId record;
- Xulong *number;
- X{
- X Record *rec;
- X int rc;
- X
- X if( (rc = set_recfld(record, &rec, NULL)) != S_OKAY )
- X return rc;
- X
- X RETURN ty_reccount(rec, number);
- X}
- X
- X
- XFNCLASS d_seterrfn(fn)
- Xvoid (*fn) PRM( (int, long); )
- X{
- X typhoon.ty_errfn = fn;
- X}
- X
- X
- X/* end-of-file */
- END_OF_FILE
- if test 10221 -ne `wc -c <'typhoon/src/ty_find.c'`; then
- echo shar: \"'typhoon/src/ty_find.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/ty_find.c'
- fi
- if test -f 'typhoon/src/ty_refin.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/ty_refin.c'\"
- else
- echo shar: Extracting \"'typhoon/src/ty_refin.c'\" \(9607 characters\)
- sed "s/^X//" >'typhoon/src/ty_refin.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : bt_refin
- X * Library : typhoon
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X * This file contains function for handling referential integrity.
- X *
- X * Functions:
- X * update_foreign_keys
- X * check_foreign_keys
- X * delete_foreign_keys
- X * check_dependent_tables
- X *
- X * $Log: ty_refin.c,v $
- X * Revision 1.2 1994/09/17 16:00:19 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:37 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: ty_refin.c,v 1.2 1994/09/17 16:00:19 tbp Exp $";
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <typhoon.h>
- X#include "ty_dbd.h"
- X#include "ty_type.h"
- X#include "ty_glob.h"
- X#include "ty_prot.h"
- X
- X
- X/*--------------------------- Function prototypes --------------------------*/
- X
- X/*---------------------------- Global variables ----------------------------*/
- X/* The ca[] table is a Communications Area used to pass information between
- X check_foreign_keys() and modify_refentries(). Because foreign keys
- X are modified in two steps, this table is necessary
- X*/
- Xstruct {
- X ulong ref_file; /* Id of reference file. 0=skip this entry */
- X ulong del_parent; /* If a foreign key has been changed this */
- X /* entry contains the recno of the old */
- X /* parent. This should be used to remove */
- X /* the old. REFENTRY. 0=no parent to delete */
- X uchar null; /* Determines whether a reference should be */
- X /* inserted, e.g. the key is not null */
- X} ca[RECKEYS_MAX];
- X
- X
- X
- X
- X/*--------------------------- update_foreign_keys --------------------------*\
- X *
- X * Purpose : This function is called after check_foreign_keys has set up
- X * the communications area (ca) with the foreign keys that should
- X * be updated, removed or added.
- X *
- X * Parameters: rec - Pointer to record.
- X * is_new - Called by d_fillnew() or d_recwrite().
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid update_foreign_keys(rec, is_new)
- XRecord *rec;
- Xint is_new;
- X{
- X int n;
- X Key key;
- X REF_ENTRY refentry;
- X
- X /* If the record has no foreign keys we'll just return now */
- X if( rec->first_foreign == -1 )
- X return;
- X
- X key.size = sizeof(REF_ENTRY);
- X n = rec->keys - (rec->first_foreign - rec->first_key);
- X
- X refentry.dependent.recid = CURR_RECID;
- X refentry.dependent.recno = CURR_REC;
- X
- X while( n-- )
- X {
- X if( ca[n].ref_file )
- X {
- X key.fileid = ca[n].ref_file;
- X
- X if( !is_new )
- X {
- X if( refentry.parent = ca[n].del_parent )
- X ty_keydel(&key, &refentry, CURR_REC);
- X }
- X
- X if( !ca[n].null )
- X {
- X refentry.parent = ((ulong *)DB->real_recbuf)[n];
- X ty_keyadd(&key, &refentry, CURR_REC);
- X }
- X }
- X }
- X
- X}
- X
- X
- X
- X/*--------------------------- check_foreign_keys ---------------------------*\
- X *
- X * Purpose : This function checks whether the foreign keys of a record
- X * exist in its parent tables.
- X *
- X * First the existence of all foreign keys are checked. Only
- X * the necessary checks are performed. If is_new all foreign
- X * keys are checked, otherwise only foreign keys which have
- X * changed are checked. Null keys are never checked.
- X *
- X * The record numbers of the parents record are stored in the
- X * preamble. For each entry in the preamble, the corresponding
- X * entries in save_ref[] and old_preamble[] contains the file id
- X * of the parent's reference file and the old preamble value,
- X * respectively.
- X *
- X * Parameters: rec - Pointer to record.
- X * buf - Buffer of dependent record.
- X * new - Is this record being created? This is set to 1
- X * d_fillnew().
- X *
- X * Returns : S_OKAY - All foreign keys existed.
- X * S_NOTFOUND - A foreign did not exist. db_subcode contains the
- X * ID of the parent table.
- X */
- Xcheck_foreign_keys(rec, buf, is_new)
- XRecord *rec;
- Xvoid *buf;
- Xint is_new;
- X{
- X Key *key;
- X int n;
- X int foreign_keys;
- X ulong ref;
- X
- X /* If the record has no foreign keys we'll just return now */
- X if( rec->first_foreign == -1 )
- X return S_OKAY;
- X
- X key = DB->key + rec->first_foreign;
- X foreign_keys = rec->keys - (rec->first_foreign - rec->first_key);
- X
- X /* If this is a new record the preamble must be cleared */
- X if( is_new )
- X memset(DB->real_recbuf, 0, foreign_keys * sizeof(ulong));
- X
- X for( n=0; KEY_ISFOREIGN(key) && n < foreign_keys; n++, key++ )
- X {
- X Key *primary_key = DB->key + DB->record[key->parent].first_key;
- X
- X ca[n].null = 0;
- X
- X if( is_new || reckeycmp(key, buf, DB->recbuf) )
- X {
- X if( KEY_ISOPTIONAL(key) )
- X {
- X ca[n].ref_file = DB->record[key->parent].ref_file;
- X
- X /* If the record is being created or the old value was null
- X * no key need to be deleted
- X */
- X if( is_new || null_indicator(key, DB->recbuf) )
- X ca[n].del_parent = 0;
- X else
- X ca[n].del_parent = ((ulong *)DB->real_recbuf)[n];
- X
- X if( null_indicator(key, buf) )
- X {
- X ca[n].null = 1;
- X continue;
- X }
- X }
- X
- X CURR_REC = primary_key - DB->key;
- X
- X if( ty_keyfind(primary_key, set_keyptr(key, buf), &ref) != S_OKAY )
- X {
- X db_subcode = (key->parent+1) * REC_FACTOR;
- X RETURN S_FOREIGN;
- X }
- X
- X ca[n].del_parent = ((ulong *)DB->real_recbuf)[n];
- X ca[n].ref_file = DB->record[key->parent].ref_file;
- X
- X /* Store the reference to the parent record in the preamble */
- X ((ulong *)DB->real_recbuf)[n] = ref;
- X }
- X else
- X ca[n].ref_file = 0;
- X }
- X
- X return S_OKAY;
- X}
- X
- X
- X
- X/*-------------------------- delete_foreign_keys ---------------------------*\
- X *
- X * Purpose : This function removes all refentries from a dependent record's
- X * parent reference files.
- X *
- X * Parameters: rec - Pointer to record.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid delete_foreign_keys(rec)
- XRecord *rec;
- X{
- X Key *key, refkey;
- X REF_ENTRY refentry;
- X int n;
- X int foreign_keys;
- X
- X /* If the record has no foreign keys we'll just return now */
- X if( rec->first_foreign == -1 )
- X return;
- X
- X key = DB->key + rec->first_foreign;
- X foreign_keys = rec->keys - (rec->first_foreign - rec->first_key);
- X refkey.size = sizeof(REF_ENTRY);
- X
- X refentry.dependent.recid = CURR_RECID;
- X refentry.dependent.recno = CURR_REC;
- X
- X for( n=0; KEY_ISFOREIGN(key) && n < foreign_keys; n++, key++ )
- X {
- X if( !(key->type & KT_OPTIONAL) || !null_indicator(key, DB->recbuf) )
- X {
- X refentry.parent = ((ulong *)DB->real_recbuf)[n];
- X refkey.fileid = DB->record[key->parent].ref_file;
- X
- X ty_keydel(&refkey, &refentry, CURR_REC);
- X }
- X }
- X}
- X
- X
- X
- X/*------------------------- check_dependent_tables -------------------------*\
- X *
- X * Purpose : This function is called by d_fillnew() and d_delete() to check
- X * whether this update/delete operation will have any effect on
- X * records in dependent tables.
- X *
- X * Parameters: parent - Pointer to parent table's record pointer.
- X * buf - Buffer of dependent record.
- X * for_action - 'd'=delete, 'u'=update
- X *
- X * Returns : S_OKAY - No conflicts.
- X * S_RESTRICT - A dependent table with restrict rule has rows
- X * which referenced the parent table. db_subcode
- X * contains the ID of the dependent table.
- X *
- X */
- Xcheck_dependent_tables(parent, buf, for_action)
- XRecord *parent;
- Xvoid *buf;
- Xint for_action;
- X{
- X Key *primary_key, refkey;
- X REF_ENTRY refentry;
- X ulong ref;
- X int rc;
- X
- X /* Does this table have any dependent tables? */
- X if( !parent->dependents )
- X return S_OKAY;
- X
- X /* If the table has dependent tables, it follows that it must also have
- X * a primary key, i.e. no need to check for that.
- X */
- X primary_key = DB->key + parent->first_key;
- X
- X /* Only perform check if the primary key has changed (if update) */
- X if( for_action == 'u' )
- X if( !reckeycmp(primary_key, buf, DB->recbuf) )
- X return S_OKAY;
- X
- X refentry.parent = CURR_REC;
- X refentry.dependent.recid = 0;
- X refentry.dependent.recno = 0;
- X
- X refkey.size = sizeof(REF_ENTRY);
- X refkey.fileid = parent->ref_file;
- X
- X if( (rc = ty_keyfind(&refkey, &refentry, &ref)) != S_OKAY )
- X rc = ty_keynext(&refkey, &ref);
- X
- X if( rc != S_OKAY )
- X return S_OKAY;
- X
- X refentry = *(REF_ENTRY *)CURR_KEYBUF;
- X
- X if( refentry.parent == CURR_REC )
- X {
- X /* Set db_subcode to the ID of the dependent table */
- X db_subcode = (refentry.dependent.recid+1) * REC_FACTOR;
- X RETURN S_RESTRICT;
- X }
- X
- X return S_OKAY;
- X}
- X
- X/* end-of-file */
- END_OF_FILE
- if test 9607 -ne `wc -c <'typhoon/src/ty_refin.c'`; then
- echo shar: \"'typhoon/src/ty_refin.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/ty_refin.c'
- fi
- if test -f 'typhoon/src/unix.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/unix.c'\"
- else
- echo shar: Extracting \"'typhoon/src/unix.c'\" \(5678 characters\)
- sed "s/^X//" >'typhoon/src/unix.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : unix.c
- X * Library : typhoon
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X * Contiains functions specific to UNIX.
- X *
- X * Functions:
- X * ty_openlock - Create/open the locking resource.
- X * ty_closelock - Close the locking resource.
- X * ty_lock - Obtain the lock.
- X * ty_unlock - Release the lock.
- X *
- X * $Log: unix.c,v $
- X * Revision 1.3 1994/09/17 16:21:13 tbp
- X * /tmp/typhoonsem was created even though SEMLOCK was defined.
- X *
- X * Revision 1.2 1994/09/17 16:00:22 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:39 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: unix.c,v 1.3 1994/09/17 16:21:13 tbp Exp $";
- X
- X#include <sys/types.h>
- X#include <sys/ipc.h>
- X#include <sys/sem.h>
- X#include <sys/shm.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <stdio.h>
- X#include <errno.h>
- X#include <typhoon.h>
- X#include "ty_dbd.h"
- X#include "ty_type.h"
- X
- X#define SEMLOCK
- X
- X#define TIMEOUT 10000L /* Wait maximum 10 seconds for excl. access */
- X
- X/*---------------------------- Global variables ----------------------------*/
- Xstatic struct sembuf sem_wait_buf[2] = {
- X 0, 0, 0, /* wait for sem to become 0 */
- X 0, 1, SEM_UNDO /* then increment sem by 1 */
- X};
- X
- Xstatic struct sembuf sem_clear_buf[1] = {
- X 0,-1, IPC_NOWAIT | SEM_UNDO, /* decrease sem by 1 */
- X};
- X
- X
- Xstatic int sem_id;
- X
- Xstatic int lock_fh = -1;
- X
- X/*------------------------------ ty_openlock ------------------------------*\
- X *
- X * Purpose : This function ensures that only one instance of a Typhoon
- X * function is active at the time, at least in its critical
- X * section.
- X *
- X * Parameters: None.
- X *
- X * Returns : -1 - Semaphore could not be created.
- X * 0 - Successful.
- X *
- X */
- X
- Xty_openlock()
- X{
- X#ifndef SEMLOCK
- X static char lockfname[] = "/tmp/typhoonsem";
- X int pid = getpid();
- X
- X if( lock_fh == -1 )
- X {
- X if( (lock_fh = open(lockfname, O_RDWR|O_CREAT, 0666)) == -1 )
- X {
- X printf("Cannot open %s\n", lockfname);
- X return -1;
- X }
- X
- X write(lock_fh, &pid, sizeof pid);
- X }
- X#endif
- X return 0;
- X}
- X
- X
- Xty_closelock()
- X{
- X close(lock_fh);
- X lock_fh = -1;
- X
- X return 0;
- X}
- X
- X
- Xty_lock()
- X{
- X#ifdef SEMLOCK
- X#if 1
- X while( semop(sem_id, sem_wait_buf, 2) == -1 && errno == EINTR )
- X puts("ty_lock EAGAIN");
- X#else
- X if( sem_wait(sem_id) == -1 )
- X puts("ty_lock failed");
- X#endif
- X#endif
- X
- X#ifndef SEMLOCK
- X lseek(lock_fh, 0, SEEK_SET);
- X
- X while( lockf(lock_fh, F_LOCK, 1) == -1 )
- X {
- X if( errno != EINTR && errno != EAGAIN )
- X {
- X printf("ty_lock failed (errno %d, lock_fh %d)\n", errno, lock_fh);
- X break;
- X }
- X }
- X#endif
- X}
- X
- X
- Xty_unlock()
- X{
- X#ifdef SEMLOCK
- X#if 1
- X while( semop(sem_id, sem_clear_buf, 1) == -1 && errno == EINTR )
- X puts("ty_unlock EAGAIN");
- X#else
- X if( sem_clear(sem_id) == -1 )
- X puts("ty_unlock failed");
- X#endif
- X#endif
- X
- X#ifndef SEMLOCK
- X lseek(lock_fh, 0, SEEK_SET);
- X
- X while( lockf(lock_fh, F_ULOCK, 1) == -1 )
- X {
- X if( errno != EINTR && errno != EAGAIN )
- X {
- X printf("ty_unlock failed (errno %d, lock_fh %d)\n", errno, lock_fh);
- X break;
- X }
- X }
- X#endif
- X
- X
- X return 0;
- X}
- X
- X
- X
- X
- Xshm_alloc(db)
- XDbentry *db;
- X{
- X char dbdname[128];
- X key_t key;
- X long flags = IPC_CREAT|0770;
- X int created = 0;
- X
- X sprintf(dbdname, "%s.dbd", db->name);
- X key = ftok(dbdname, 30);
- X
- X if( (db->shm_id = shmget(key, sizeof(*db->shm), 0)) == -1 )
- X if( (db->shm_id = shmget(key, sizeof(*db->shm), flags)) == -1 )
- X return -1;
- X else
- X created = 1;
- X#ifdef SEMLOCK
- X#if 1
- X if( (sem_id = semget(key, 1, 0)) == -1 )
- X if( (sem_id = semget(key, 1, IPC_CREAT|0660)) == -1 )
- X {
- X shmdt((char *)db->shm);
- X if( created )
- X shmctl(db->shm_id, IPC_RMID, NULL);
- X return -1;
- X }
- X#else
- X if( (sem_id = sem_open(key)) == -1 )
- X if( (sem_id = sem_create(key, 1)) == -1 )
- X {
- X shmdt((char *)db->shm);
- X if( created )
- X shmctl(db->shm_id, IPC_RMID, NULL);
- X return -1;
- X }
- X#endif
- X#endif
- X
- X if( (db->shm = (SharedMemory *)shmat(db->shm_id,0,0)) == NULL )
- X {
- X if( created )
- X shmctl(db->shm_id, IPC_RMID, NULL);
- X return -1;
- X }
- X
- X if( created )
- X memset(db->shm, 0, sizeof *db->shm);
- X db->shm->use_count++;
- X
- X return 0;
- X}
- X
- X
- Xshm_free(db)
- XDbentry *db;
- X{
- X if( --db->shm->use_count == 0 )
- X {
- X shmdt((char *)db->shm);
- X shmctl(db->shm_id, IPC_RMID, NULL);
- X#ifdef SEMLOCK
- X semctl(sem_id, 0, IPC_RMID, 0);
- X#endif
- X }
- X else
- X shmdt((char *)db->shm);
- X#if 0
- X sem_close(sem_id);
- X#endif
- X}
- X
- X
- X/* end-of-file */
- END_OF_FILE
- if test 5678 -ne `wc -c <'typhoon/src/unix.c'`; then
- echo shar: \"'typhoon/src/unix.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/unix.c'
- fi
- if test -f 'typhoon/src/util/export.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/util/export.c'\"
- else
- echo shar: Extracting \"'typhoon/src/util/export.c'\" \(9427 characters\)
- sed "s/^X//" >'typhoon/src/util/export.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : export.c
- X * Program : tyexport
- X * OS : UNIX, OS/2, DOS
- X * Author : Thomas B. Pedersen
- X *
- X * Copyright (c) 1994 Thomas B. Pedersen. All rights reserved.
- X *
- X * Permission is hereby granted, without written agreement and without
- X * license or royalty fees, to use, copy, modify, and distribute this
- X * software and its documentation for any purpose, provided that the above
- X * copyright notice and the following two paragraphs appear (1) in all
- X * source copies of this software and (2) in accompanying documentation
- X * wherever the programatic interface of this software, or any derivative
- X * of it, is described.
- X *
- X * IN NO EVENT SHALL THOMAS B. PEDERSEN BE LIABLE TO ANY PARTY FOR DIRECT,
- X * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
- X * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF HE HAS BEEN
- X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- X *
- X * THOMAS B. PEDERSEN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
- X * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- X * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- X * BASIS, AND THOMAS B. PEDERSEN HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
- X * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- X *
- X * Description:
- X * Typhoon export utility.
- X *
- X * $Log: export.c,v $
- X * Revision 1.2 1994/09/17 16:00:52 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:55 tbp
- X * Added to repository.
- X *
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: export.c,v 1.2 1994/09/17 16:00:52 tbp Exp $";
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <ctype.h>
- X#include <fcntl.h>
- X#include <stdarg.h>
- X#ifndef UNIX
- X# include <sys\types.h>
- X# include <sys\stat.h>
- X# include <stdlib.h>
- X# include <io.h>
- X#endif
- X#define DEFINE_GLOBALS
- X#include <typhoon.h>
- X#include "../ty_dbd.h"
- X#include "../ty_type.h"
- X#include "export.h"
- X
- X
- X/*-------------------------------- prototypes ------------------------------*/
- Xstatic void PrintString PRM( (uchar *, Field *fld); )
- Xstatic void PrintField PRM( (Field *, unsigned); )
- Xstatic int GetControlField PRM( (Structdef *, unsigned); )
- Xstatic int PrintFields PRM( (Structdef *, int, unsigned, int); )
- Xstatic void Export PRM( (char *); )
- X int yyparse PRM( (void); )
- X
- X/*------------------------------ public variables --------------------------*/
- Xint dbdfile;
- Xint nocomma=0;
- Xint nonull=0;
- Xchar *recbuf;
- XFILE *outfile;
- XFILE *lex_file;
- X
- X/*------------------------------ local variables ---------------------------*/
- Xstatic char paramhelp[] = "\
- XSyntax: tyexport [option]... database[.dbd]\n\
- XOptions:\n\
- X -f<path> Specify data files path\n\
- X -g Generate export specification\n\
- X -n Strings are not null-terminated\n";
- X
- X
- X
- Xistrcmp(s1, s2)
- Xchar *s1, *s2;
- X{
- X while( tolower(*s1) == tolower(*s2) && *s1 && *s2 )
- X s1++, s2++;
- X
- X return tolower(*s1) - tolower(*s2);
- X}
- X
- X
- X
- X
- X#ifdef PROTOTYPES
- Xvoid err_quit(char *s, ...)
- X#else
- Xvoid err_quit(s)
- Xchar *s;
- X#endif
- X{
- X va_list ap;
- X
- X va_start(ap, s);
- X vfprintf(stderr, s, ap);
- X puts("");
- X va_end(ap);
- X exit(1);
- X}
- X
- Xstatic void PrintString(s, fld)
- Xuchar *s;
- XField *fld;
- X{
- X int len;
- X
- X if( fld->type & FT_VARIABLE )
- X len = *(ushort *)(recbuf + dbd.field[ fld->keyid ].offset) * fld->elemsize;
- X else
- X len = fld->size;
- X
- X putc('"', outfile);
- X
- X while( len-- )
- X {
- X if( isprint(*s) )
- X {
- X if( *s == '"' )
- X fputs("\\\"", outfile);
- X else
- X if( *s == '\\' )
- X fputs("\\\\", outfile);
- X else
- X putc(*s, outfile);
- X }
- X else
- X {
- X if( !*s && !nonull )
- X break;
- X
- X fprintf(outfile, "\\x%02X", *s);
- X }
- X s++;
- X }
- X putc('"', outfile);
- X}
- X
- X
- Xstatic void PrintField(fld, offset)
- XField *fld;
- Xunsigned offset;
- X{
- X void *ptr = (void *)(recbuf + offset);
- X
- X /*
- X Check for nonprintable characters in strings and character constants
- X */
- X
- X if( nocomma )
- X nocomma = 0;
- X else
- X fprintf(outfile, ", ");
- X
- X if( fld->type & FT_UNSIGNED )
- X {
- X switch( FT_GETBASIC(fld->type) )
- X {
- X case FT_CHARSTR:
- X PrintString(ptr, fld);
- X break;
- X case FT_CHAR:
- X fprintf(outfile, "%u", (unsigned)*(uchar *)ptr);
- X break;
- X case FT_SHORT:
- X fprintf(outfile, "%hu", *(ushort *)ptr);
- X break;
- X case FT_INT:
- X fprintf(outfile, "%u", *(unsigned *)ptr);
- X break;
- X case FT_LONG:
- X fprintf(outfile, "%lu", *(ulong *)ptr);
- X break;
- X }
- X }
- X else
- X switch( FT_GETBASIC(fld->type) )
- X {
- X case FT_CHARSTR:
- X PrintString(ptr, fld);
- X break;
- X case FT_CHAR:
- X fprintf(outfile, "%d", (int)*(char *)ptr);
- X break;
- X case FT_SHORT:
- X fprintf(outfile, "%hd", *(short *)ptr);
- X break;
- X case FT_INT:
- X fprintf(outfile, "%d", *(int *)ptr);
- X break;
- X case FT_UNSIGNED:
- X fprintf(outfile, "%u", *(int *)ptr);
- X break;
- X case FT_LONG:
- X fprintf(outfile, "%ld", *(long *)ptr);
- X break;
- X case FT_FLOAT:
- X fprintf(outfile, "%f", *(float *)ptr);
- X break;
- X case FT_DOUBLE:
- X fprintf(outfile, "%f", *(double *)ptr);
- X break;
- X }
- X}
- X
- X
- Xstatic GetControlField(str, offset)
- XStructdef *str;
- Xunsigned offset;
- X{
- X unsigned id = recbuf[offset + dbd.field[str->control_field].offset];
- X
- X if( id >= str->members )
- X {
- X printf("Setting invalid control filed to 0\n");
- X id = 0;
- X }
- X
- X return id;
- X}
- X
- X
- Xstatic PrintFields(str, nest, offset, control_value)
- XStructdef *str;
- Xint nest;
- Xunsigned offset;
- X{
- X Field *fld = dbd.field + str->first_member;
- X int fields = str->members;
- X int old_fields = fields;
- X int i, n, rc;
- X
- X if( str->is_union )
- X fld += control_value;
- X
- X while( fields-- )
- X {
- X if( fld->size != fld->elemsize && FT_GETBASIC(fld->type) != FT_CHARSTR )
- X {
- X if( fld->type & FT_VARIABLE )
- X n = *(ushort *)(recbuf + dbd.field[ fld->keyid ].offset);
- X else
- X n = fld->size / fld->elemsize;
- X }
- X else
- X n = 1;
- X
- X for( i=0; i<n; i++ )
- X {
- X if( FT_GETBASIC(fld->type) == FT_STRUCT )
- X {
- X Structdef *struc = dbd.structdef + fld->structid;
- X
- X if( !nocomma )
- X fprintf(outfile, ", ");
- X if( fld->type & FT_INCLUDE )
- X fprintf(outfile, "{ ");
- X nocomma = 1;
- X
- X rc = PrintFields(struc, nest+1,
- X offset + fld->offset + i * fld->elemsize,
- X struc->is_union ? GetControlField(struc, offset) : 0);
- X
- X if( fld->type & FT_INCLUDE )
- X fprintf(outfile, " }");
- X }
- X else if( fld->nesting == nest && fld->type & FT_INCLUDE )
- X PrintField(fld, offset + fld->offset + fld->elemsize * i);
- X }
- X
- X /* If n was 0 this array was a variable length array of size 0.
- X * Move fld to the next field at the same nesting.
- X */
- X if( n == 0 )
- X {
- X fprintf(outfile, ", { }");
- X rc = 0;
- X
- X if( !fields )
- X break;
- X
- X do
- X rc++;
- X while( fld[rc].nesting != fld->nesting );
- X rc--;
- X }
- X
- X
- X if( FT_GETBASIC(fld->type) == FT_STRUCT )
- X {
- X old_fields += rc;
- X fld += rc;
- X }
- X
- X fld++;
- X
- X if( str->is_union )
- X break;
- X }
- X
- X return old_fields;
- X}
- X
- X
- Xstatic void ExportTable(recid)
- Xulong recid;
- X{
- X Record *rec = &dbd.record[recid];
- X Id keyid;
- X
- X recid = INTERN_TO_RECID(recid);
- X keyid = rec->first_key;
- X
- X for( d_keyfrst(keyid); db_status == S_OKAY; d_keynext(keyid) )
- X {
- X d_recread(recbuf);
- X
- X nocomma = 1;
- X PrintFields(&dbd.structdef[rec->structid], 0, 0, 0);
- X fprintf(outfile, "\n");
- X }
- X}
- X
- X
- Xstatic void Export(dbname)
- Xchar *dbname;
- X{
- X char export_fname[256];
- X int i;
- X
- X if( d_open(dbname, "s") != S_OKAY )
- X err_quit("Cannot open database '%s'", dbname);
- X
- X for( i=0; i<dbd.header.records; i++ )
- X {
- X if( dbd.record[i].aux )
- X {
- X sprintf(export_fname, "%s.kom", dbd.record[i].name);
- X
- X if( !(outfile = fopen(export_fname, "w")) )
- X err_quit("Cannot write to '%s'", export_fname);
- X
- X printf("exporting to '%s'\n", export_fname);
- X ExportTable(i);
- X fclose(outfile);
- X }
- X }
- X
- X d_close();
- X}
- X
- X
- X
- Xmain(argc, argv)
- Xchar *argv[];
- X{
- X char *p, *realname;
- X int i;
- X long n=0, prev;
- X unsigned biggest_rec=0;
- X
- X puts("Typhoon Export Utility version 1.05");
- X
- X if( argc == 1 )
- X {
- X printf(paramhelp);
- X exit(1);
- X }
- X
- X /* Extract the real name of the file */
- X if( (realname = strrchr(argv[argc-1], DIR_SWITCH)) != NULL )
- X realname++;
- X else
- X realname = argv[argc-1];
- X
- X /* remove extension if present */
- X if( p = strstr(realname, ".") )
- X *p = 0;
- X
- X /* generate file names for .ddl-file, .dbd-file and header file */
- X sprintf(dbd_fname, "%s.dbd", realname);
- X sprintf(spec_fname, "%s.exp", realname);
- X
- X if( read_dbdfile(&dbd, dbd_fname) != S_OKAY )
- X err_quit("Cannot open '%s'\n", dbd_fname);
- X
- X /* Find the size of the biggest record */
- X for( i=0; i<dbd.header.records; i++ )
- X if( biggest_rec < dbd.record[i].size )
- X biggest_rec = dbd.record[i].size;
- X
- X /* Allocate record buffer */
- X if( !(recbuf = (char *)malloc(biggest_rec)) )
- X err_quit("Out of memory");
- X
- X /* process command line options */
- X for( i=1; i<argc-1; i++ )
- X {
- X if( argv[i][0] == '-' || argv[i][0] == '/' )
- X {
- X switch( argv[i][1] )
- X {
- X case 'f':
- X d_dbfpath(argv[i]+2);
- X break;
- X case 'g':
- X GenerateExportSpec(realname);
- X exit(1);
- X case 'n':
- X nonull = 1;
- X break;
- X default:
- X err_quit("unknown command line option");
- X }
- X }
- X else
- X err_quit("unknown command line option");
- X }
- X
- X /* Read the export specification */
- X ReadExportSpec(realname);
- X
- X if( !errors )
- X Export(realname);
- X
- X free(dbd.dbd);
- X free(recbuf);
- X}
- X
- X/* end-of-file */
- END_OF_FILE
- if test 9427 -ne `wc -c <'typhoon/src/util/export.c'`; then
- echo shar: \"'typhoon/src/util/export.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/util/export.c'
- fi
- echo shar: End of archive 4 \(of 9\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 9 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-