home *** CD-ROM | disk | FTP | other *** search
- From: zeppelin@login.dknet.dk (Thomas B. Pedersen)
- Newsgroups: comp.sources.misc
- Subject: v44i059: typhoon - Typhoon Relational Database Management System, Part03/09
- Date: 17 Sep 1994 21:45:26 -0500
- Organization: Sterling Software
- Sender: kent@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <35g9k6$ohf@sparky.sterling.com>
- X-Md4-Signature: 523b50b89b972700c8495c636ca5f5fc
-
- Submitted-by: zeppelin@login.dknet.dk (Thomas B. Pedersen)
- Posting-number: Volume 44, Issue 59
- Archive-name: typhoon/part03
- 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/bt_del.c typhoon/src/bt_open.c
- # typhoon/src/ty_ins.c typhoon/src/ty_io.c
- # typhoon/src/util/ddlpsym.c typhoon/src/util/imp_y.h
- # 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 3 (of 9)."'
- if test -f 'typhoon/src/bt_del.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/bt_del.c'\"
- else
- echo shar: Extracting \"'typhoon/src/bt_del.c'\" \(12035 characters\)
- sed "s/^X//" >'typhoon/src/bt_del.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : bt_del
- 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 function for removing a tuple from a B-tree index file.
- X * The algorithm is the one is described in "Data structures in Pascal",
- X * Horowitz & Sahni, Computer Science Press.
- X *
- X * Functions:
- X * delchain_insert - Add a node to the delete chain.
- X * merge_siblings - Merge two sibling nodes to a single node.
- X * move_parentkey - Move a parent key to another tuple.
- X * find_ref - Find tuple with correct reference.
- X * replace_with_leftmost_tuple- Copy the leftmost tuple in a subtree.
- X * btree_del -
- X *
- X * $Log: bt_del.c,v $
- X * Revision 1.2 1994/09/17 16:00:11 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:27 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: bt_del.c,v 1.2 1994/09/17 16:00:11 tbp Exp $";
- X
- X#include <string.h>
- X#include <stdio.h>
- X#include <fcntl.h>
- X#ifndef UNIX
- X# include <io.h>
- X# include <stdlib.h>
- X#else
- X# include <unistd.h>
- X# ifdef __STDC__
- X# include <stdlib.h>
- X# endif
- X#endif
- 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#include "btree.h"
- X
- X
- X/*--------------------------- Function prototypes ---------------------------*/
- Xstatic void delchain_insert PRM( (INDEX *, ix_addr); )
- Xstatic void merge_siblings PRM( (INDEX *I,
- X ix_addr lsib,
- X ix_addr rsib,
- X ix_addr z,
- X int zi,
- X char *znode,
- X ix_addr *y,
- X char *ynode,
- X ix_addr *p,
- X int *i); )
- X
- Xstatic void move_parentkey PRM( (INDEX *I,
- X ix_addr rsib,
- X int zi,
- X ix_addr z,
- X char *znode,
- X ix_addr y,
- X char *ynode); )
- X
- Xstatic find_ref PRM( (INDEX *I,
- X ulong ref,
- X ix_addr *addr,
- X int *idx,
- X void *key); )
- X
- Xstatic void replace_with_leftmost_tuple
- X PRM( (INDEX *I,
- X ix_addr *y,
- X char *ynode,
- X ix_addr *p,
- X int *i); )
- X
- X
- X/*----------------------------- delchain_insert ----------------------------*\
- X *
- X * Purpose : Inserts a deleted B-tree node in the delete chain.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * addr - Address of node to insert in delete chain.
- X *
- X * Returns : Nothing.
- X *
- X */
- X
- Xstatic void delchain_insert(I, addr)
- XINDEX *I;
- Xix_addr addr;
- X{
- X lseek(I->fh, (ulong)I->H.nodesize * (ulong)addr, SEEK_SET);
- X write(I->fh, &I->H.first_deleted, sizeof I->H.first_deleted);
- X I->H.first_deleted = addr;
- X}
- X
- X
- X
- X/*--------------------------------------------------------------------------*\
- X *
- X * Function : merge_siblings
- X *
- X * Purpose : Merge two siblings nodes.
- X *
- X * Parameters: I - Index handle.
- X * lsib - Address of left sibling node.
- X * rsib - Address of right sibling node.
- X * z -
- X * zi -
- X * znode -
- X * y -
- X * ynode -
- X * p -
- X * i -
- X *
- X * Returns : Nothing.
- X *
- X */
- Xstatic void merge_siblings(I, lsib, rsib, z, zi, znode, y, ynode, p, i)
- XINDEX *I;
- Xix_addr lsib, rsib, *y, z, *p;
- Xint zi, *i;
- Xchar *znode;
- Xchar *ynode;
- X{
- X if( rsib )
- X {
- X /* copy parent key */
- X keycopy(I->node, NSIZE(I->node), znode, zi);
- X
- X /* copy sibling keys */
- X tuplecopy(I->node, NSIZE(I->node)+1, ynode, 0, NSIZE(ynode));
- X
- X CHILD(I->node,NSIZE(I->node)+1+NSIZE(ynode)) = CHILD(ynode,NSIZE(ynode));
- X
- X delchain_insert(I, *p);
- X }
- X else
- X {
- X /* make room for left sibling */
- X tupleins(I->node, 0, NSIZE(ynode)+1);
- X
- X /* copy parent key */
- X keycopy(I->node, NSIZE(ynode), znode, zi);
- X
- X /* copy sibling keys */
- X tuplecopy(I->node, 0, ynode, 0, NSIZE(ynode));
- X
- X CHILD(I->node,NSIZE(ynode)) = CHILD(ynode,NSIZE(ynode));
- X *y = *p;
- X
- X delchain_insert(I, lsib);
- X }
- X
- X tupledel(znode, zi); /* remove parent key */
- X NSIZE(znode)--;
- X NSIZE(I->node) += 1 + NSIZE(ynode);
- X
- X nodewrite(I, I->node, *y);
- X
- X /* create new root? */
- X if( z == 1 && !NSIZE(znode) )
- X {
- X *p = 1;
- X delchain_insert(I, *y);
- X }
- X else
- X {
- X /* process parent */
- X nodecopy(I->node, znode);
- X *p = z;
- X *i = zi;
- X I->level--;
- X }
- X}
- X
- X
- X/*--------------------------------------------------------------------------*\
- X *
- X * Function : move_parentkey
- X *
- X * Purpose :
- X *
- X * Parameters: I -
- X * rsib -
- X * zi -
- X * z -
- X * znode -
- X * y -
- X * ynode -
- X *
- X * Returns : Nothing.
- X *
- X */
- Xstatic void move_parentkey(I, rsib, zi, z, znode, y, ynode)
- XINDEX *I;
- Xix_addr rsib, y, z;
- Xint zi;
- Xchar *znode, *ynode;
- X{
- X if( rsib )
- X {
- X /* copy key from parent to p */
- X keycopy(I->node, NSIZE(I->node), znode, zi);
- X
- X /* copy reference of sibling moved to parent */
- X CHILD(I->node, NSIZE(I->node)+1) = CHILD(ynode,0);
- X
- X /* copy sibling key to parent */
- X keycopy(znode, zi, ynode, 0);
- X tupledel(ynode, 0);
- X }
- X else
- X {
- X tupleins(I->node, 0, 1);
- X
- X /* copy key from parent */
- X keycopy(I->node, 0, znode, zi);
- X
- X /* copy reference of sibling moved to parent */
- X CHILD(I->node,0) = CHILD(ynode, NSIZE(ynode));
- X
- X /* copy sibling key to parent */
- X keycopy(znode, zi, ynode, NSIZE(ynode)-1);
- X }
- X
- X NSIZE(ynode)--;
- X NSIZE(I->node)++;
- X
- X nodewrite(I, ynode, y); /* update nodes */
- X nodewrite(I, znode, z);
- X}
- X
- X
- X/*--------------------------------------------------------------------------*\
- X *
- X * Function : find_ref
- X *
- X * Purpose : Find a tuple with a specified reference.
- X *
- X * Parameters: I - INDEX handle.
- X * ref - Reference number.
- X * addr - Address of node to start search in. If the tuple
- X * is found, the address of the tuple is returned herein
- X *
- X * Returns : S_OKAY - Reference found.
- X *
- X */
- X
- X#define Keys NSIZE(I->node)
- X#define Child(i) CHILD(I->node, (i))
- X#define Key(i) KEY(I->node, (i))
- X#define Ref(i) REF(I->node, (i))
- X#define Pos (I->path[I->level].i)
- X#define Addr (I->path[I->level].a)
- X#define Level (I->level)
- X
- X
- X
- X
- Xstatic find_ref(I, ref, addr, idx, key)
- XINDEX *I;
- Xulong ref;
- Xix_addr *addr;
- Xint *idx;
- Xvoid *key;
- X{
- X for( ;; )
- X {
- X *idx = Pos;
- X *addr = Addr;
- X
- X if( (*I->cmpfunc)(key, Key(*idx)) )
- X {
- X puts("key mismatch");
- X break;
- X }
- X
- X if( Ref(*idx) == ref )
- X return S_OKAY;
- X
- X if( Child(Pos) > 0 ) /* Non-leaf node */
- X {
- X /* Get the leftmost child in the left subtree */
- X Pos++;
- X get_leftmostchild(I, Child(Pos));
- X }
- X else if( Pos >= Keys-1 ) /* Leaf node at first pos */
- X {
- X if( Pos >= Keys-1 && Addr == 1 )
- X {
- X I->curr = 0;
- X RETURN S_NOTFOUND;
- X }
- X
- X /* Move upward until a node with Pos<Keys-1 or root is reached */
- X do
- X {
- X Level--;
- X noderead(I, I->node, Addr);
- X }
- X while( Pos >= Keys && Addr != 1 );
- X
- X if( Pos == Keys && Addr == 1 )
- X {
- X I->curr = 0;
- X RETURN S_NOTFOUND;
- X }
- X }
- X else /* Leaf node */
- X Pos++;
- X }
- X
- X RETURN S_NOTFOUND;
- X}
- X
- X#undef Keys
- X#undef Child
- X#undef Key
- X#undef Ref
- X#undef Pos
- X#undef Addr
- X#undef Level
- X
- X
- X
- X
- X/*--------------------------------------------------------------------------*\
- X *
- X * Function : replace_with_leftmost_tuple
- X *
- X * Purpose : Replaces the current tuple [p, I->node, i] with the leftmost
- X * key in the right subtree (of the current tuple).
- X *
- X * Parameters: I - Index handle.
- X * y -
- X * ynode -
- X * p - Address of I->node.
- X * i - Index of I->node.
- X *
- X * Returns :
- X *
- X */
- Xstatic void replace_with_leftmost_tuple(I, y, ynode, p, i)
- XINDEX *I;
- Xix_addr *y;
- Xix_addr *p;
- Xchar *ynode;
- Xint *i;
- X{
- X I->path[I->level].i++;
- X
- X *y = noderead(I, ynode, CHILD(I->node, *i+1));
- X
- X I->path[++I->level].a = CHILD(I->node, *i+1);
- X I->path[ I->level].i = 0;
- X
- X while( CHILD(ynode,0) )
- X {
- X *y = noderead(I, ynode, CHILD(ynode, 0));
- X
- X I->path[++I->level].a = *y;
- X I->path[ I->level].i = 0;
- X }
- X
- X keycopy(I->node, *i, ynode, 0); /* copy leftmost key to p,i */
- X
- X nodewrite(I, I->node, *p); /* update node p */
- X nodecopy(I->node, ynode);
- X
- X *p = *y;
- X *i = 0;
- X}
- X
- X
- X
- X
- X/*-------------------------------- btree_del -------------------------------*\
- X *
- X * Purpose : Deletes a key in a B-tree. If the deletion causes underflow in
- X * a node, two nodes are merged and the B-tree possibly shrunk.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * key - Key value to delete.
- X * ref - Reference of key value. Only used if the B-tree
- X * contains duplicates.
- X *
- X * Returns : S_OKAY - Key value successfully deleted.
- X * S_NOTFOUND - The key was not in the B-tree.
- X *
- X */
- Xbtree_del(I, key, ref)
- XINDEX *I;
- Xvoid *key;
- Xulong ref;
- X{
- X ix_addr p, y, z, lsib, rsib;
- X int i, zi, rc;
- X char *ynode, *znode;
- X
- X I->curr = 0;
- X I->hold = 0;
- X
- X btree_getheader(I);
- X
- X if( !d_search(I, key, &p, &i) )
- X RETURN S_NOTFOUND;
- X
- X if( I->H.dups )
- X if( (rc = find_ref(I, ref, &p, &i, key)) != S_OKAY )
- X return rc;
- X
- X /* Allocate temporaty node buffers */
- X if( !(ynode = (char *)malloc(I->H.nodesize + I->tsize)) )
- X RETURN S_NOMEM;
- X if( !(znode = (char *)malloc(I->H.nodesize + I->tsize)) )
- X {
- X free(ynode);
- X RETURN S_NOMEM;
- X }
- X
- X /* if node is a nonleaf, replace key with leftmost key in right subtree */
- X if( CHILD(I->node, 0) )
- X replace_with_leftmost_tuple(I, &y, ynode, &p, &i);
- X
- X tupledel(I->node, i); /* remove key from leaf */
- X NSIZE(I->node)--; /* decrease node size by 1 */
- X
- X /* run loop as long there is underflow in p and p is not root */
- X while( NSIZE(I->node) < (ulong)I->H.order/2 && p != 1 )
- X {
- X z = I->path[I->level-1].a; /* set z = parent */
- X zi = I->path[I->level-1].i; /* set zi = parent i */
- X
- X noderead(I,znode,z); /* read parent node from disk */
- X
- X lsib = zi ? CHILD(znode, zi-1) : 0;
- X rsib = zi < NSIZE(znode) ? CHILD(znode, zi+1) : 0;
- X
- X y = rsib ? rsib : lsib;
- X
- X noderead(I, ynode, y);
- X
- X if( !rsib )
- X zi--;
- X
- X if( NSIZE(ynode) > (ulong)I->H.order/2 )
- X {
- X /* move parent key to p, move nearest key in sibling to p */
- X move_parentkey(I, rsib, zi, z, znode, y, ynode);
- X
- X goto out;
- X }
- X else
- X {
- X /* there is underflow in leaf p - merge with a sibling */
- X merge_siblings(I, lsib, rsib, z, zi, znode, &y, ynode, &p, &i);
- X }
- X }
- X
- X I->H.keys--;
- X
- Xout:
- X
- X if( !NSIZE(I->node) ) /* if index is empty, truncate */
- X {
- X I->H.first_deleted = 0;
- X I->H.keys = 0;
- X#if defined(DOS) || defined(OS2)
- X chsize(I->fh, 0);
- X#else
- X#ifdef SCO
- X os_close(os_open(I->fname, O_RDWR|O_TRUNC, CREATMASK));
- X#else
- X ftruncate(I->fh, I->H.nodesize);
- X#endif
- X#endif
- X }
- X else
- X nodewrite(I, I->node, p); /* else update node p */
- X
- X I->H.timestamp++;
- X btree_putheader(I);
- X
- X free(znode);
- X free(ynode);
- X
- X RETURN S_OKAY;
- X}
- X
- X/* end-of-file */
- END_OF_FILE
- if test 12035 -ne `wc -c <'typhoon/src/bt_del.c'`; then
- echo shar: \"'typhoon/src/bt_del.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/bt_del.c'
- fi
- if test -f 'typhoon/src/bt_open.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/bt_open.c'\"
- else
- echo shar: Extracting \"'typhoon/src/bt_open.c'\" \(11821 characters\)
- sed "s/^X//" >'typhoon/src/bt_open.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : bt_open.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 functions for opening and closing B-tree index files.
- X *
- X * Functions:
- X * db_keygetheader - Read B-tree inde xfile header.
- X * db_keyputheader - Write B-tree index file header.
- X * d_keyopen - Open a B-tree index file.
- X * d_keyclose - Close a B-tree index file.
- X * nodesearch - Perform binary search in the node.
- X * d_search - Find a key.
- X *
- X * $Log: bt_open.c,v $
- X * Revision 1.2 1994/09/17 16:00:13 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:29 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: bt_open.c,v 1.2 1994/09/17 16:00:13 tbp Exp $";
- X
- X#include <string.h>
- X#include <stdio.h>
- X#include <fcntl.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 <sys/stat.h>
- X# include <stdlib.h>
- X# include <io.h>
- X#endif
- 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#include "btree.h"
- X
- X
- Xint find_firstoccurrence PRM( (INDEX *, void *, ix_addr *, int *); )
- X
- X/*----------------------------- btree_getheader ----------------------------*\
- X *
- X * Purpose : Reads the header of a B-tree index file.
- X *
- X * Parameters: I - Pointer to index file descriptor.
- X *
- X * Returns : Nothing.
- X *
- X */
- X
- Xvoid btree_getheader(I)
- XINDEX *I;
- X{
- X lseek(I->fh, 0L, SEEK_SET);
- X read(I->fh, &I->H, sizeof I->H);
- X}
- X
- X
- X/*----------------------------- btree_getheader ----------------------------*\
- X *
- X * Purpose : Writes the header of a B-tree index file.
- X *
- X * Parameters: I - Pointer to index file descriptor.
- X *
- X * Returns : Nothing.
- X *
- X */
- X
- Xvoid btree_putheader(I)
- XINDEX *I;
- X{
- X lseek(I->fh, 0L, SEEK_SET);
- X write(I->fh, &I->H, sizeof I->H);
- X}
- X
- X
- X/*-------------------------------- btree_open -------------------------------*\
- X *
- X * Purpose : Opens a B-tree index file with the name <fname>. If the file
- X * does not already exist, the file is created. If the version of
- X * the existing file does not match the version of the B-tree
- X * library db_status is set to S_VERSION, and NULL is returned.
- X *
- X * Parameters: fname - File name.
- X * keysize - Key size.
- X * nodesize - Node size. Multiples of 512 are recommended.
- X * cmpfunc - Comparison function. This function must take two
- X * parameters, i.e. like strcmp().
- X * dups - True if duplicates are allowed.
- X * shared - Open the index file in shared mode?.
- X *
- X * Returns : If the file was successfully opened, a pointer to a B-tree
- X * index file descriptor is returned, otherwise NULL is returned
- X * and db_status is set to one of following:
- X *
- X * S_NOMEM - Out of memory.
- X * S_IOFATAL - File could not be opened.
- X * S_VERSION - B-tree file on disk has wrong version.
- X * S_UNAVAIL - The file is already opened in non-shared mode.
- X *
- X */
- X
- XINDEX *btree_open(fname, keysize, nodesize, cmpfunc, dups, shared)
- Xchar *fname;
- Xint keysize, dups, nodesize, shared;
- XCMPFUNC cmpfunc;
- X{
- X INDEX *I;
- X int tuplesize, isnew, fh;
- X int aligned_keysize;
- X
- X /* See if file exists and then open it */
- X isnew = access(fname, 0);
- X if( (fh=os_open(fname, O_BINARY|O_CREAT|O_RDWR,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 /* Ensure that the size of a tuple is multiple of four */
- X aligned_keysize = keysize;
- X#ifdef RISC
- X if( aligned_keysize & 3 )
- X aligned_keysize += 4 - (aligned_keysize & 3);
- X#endif
- X
- X /* calculate memory requirements */
- X tuplesize = sizeof(A_type) + sizeof(R_type) + aligned_keysize;
- X
- X /* allocate memory for INDEX structure */
- X if( (I = (INDEX *)calloc(sizeof(*I) + nodesize + tuplesize,1)) == NULL )
- X {
- X os_close(fh);
- X db_status = S_NOMEM;
- X return NULL;
- X }
- X
- X /* allocate memory for current key */
- X if( (I->curkey = (char *)malloc(keysize)) == NULL )
- X {
- X os_close(fh);
- X free(I);
- X db_status = S_NOMEM;
- X return NULL;
- X }
- X
- X I->fh = fh;
- X
- X if( isnew )
- X {
- X I->H.version = KEYVERSION_NUM;
- X I->H.first_deleted = 0;
- X I->H.order = ((nodesize-sizeof(N_type)-sizeof(A_type)) / tuplesize) & 0xfffe;
- X I->H.keysize = keysize;
- X I->H.dups = dups;
- X I->H.nodesize = nodesize;
- X I->H.keys = 0;
- X strcpy(I->H.id, KEYVERSION_ID);
- X memset(I->H.spare, 0, sizeof I->H.spare);
- X btree_putheader(I);
- X }
- X else
- X {
- X btree_getheader(I);
- X
- X if( I->H.version != KEYVERSION_NUM )
- X {
- X db_status = S_VERSION;
- X os_close(fh);
- X free(I->curkey);
- X free(I);
- X return NULL;
- X }
- X }
- X
- X I->cmpfunc = cmpfunc;
- X I->tsize = tuplesize;
- X I->hold = 0;
- X I->shared = shared;
- X I->aligned_keysize = aligned_keysize;
- X strcpy(I->fname, fname);
- X
- X db_status = S_OKAY;
- X
- X return I;
- X}
- X
- X
- X/*-------------------------------- btree_close ------------------------------*\
- X *
- X * Purpose : Closes a B-tree index file previously opened with d_keyopen().
- X * All nodes that might be in the cache are written to disk.
- X *
- X * Parameters: I - Index file descriptor.
- X *
- X * Returns : Nothing.
- X *
- X */
- Xvoid btree_close(I)
- XINDEX *I;
- X{
- X int i;
- X
- X if( I->fh != -1 )
- X {
- X btree_putheader(I);
- X os_close(I->fh);
- X }
- X
- X free(I->curkey);
- X free(I);
- X}
- X
- X
- Xbtree_dynclose(I)
- XINDEX *I;
- X{
- X if( I->fh != -1 )
- X {
- X close(I->fh);
- X I->fh = -1;
- X }
- X
- X RETURN S_OKAY;
- X}
- X
- X
- Xbtree_dynopen(I)
- XINDEX *I;
- X{
- X if( I->fh == -1 )
- X if( (I->fh=os_open(I->fname, O_BINARY|O_CREAT|O_RDWR,CREATMASK)) == -1 )
- X RETURN S_IOFATAL;
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X/*------------------------------- nodesearch -------------------------------*\
- X *
- X * Purpose : Performs a binary search for the key value pointed to by <key>
- X * in the node in I. When the function returned <i> contains the
- X * entry in the node where the searched stopped. If the key was
- X * found REF(i) contains the reference to be returned by the
- X * calling, otherwise CHILD(i) contains the node address of the
- X * child to be processed next.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * key - Key value being searched for.
- X * i - Contains node index when function returns.
- X *
- X * Returns : 0 - The key was found.
- X * not 0 - The key was not found.
- X *
- X */
- Xnodesearch(I, key, i)
- XINDEX *I;
- Xvoid *key;
- Xint *i;
- X{
- X int cmp, mid, upr, lwr;
- X
- X upr = NSIZE(I->node) - 1;
- X lwr = 0;
- X
- X /* Perform binary search in node */
- X while( lwr <= upr )
- X {
- X mid = (lwr + upr) >> 1;
- X cmp = (*I->cmpfunc)(key, KEY(I->node, mid));
- X
- X if( cmp > 0 )
- X lwr = mid + 1;
- X else if( cmp < 0 )
- X upr = mid - 1;
- X else
- X {
- X if( I->H.dups )
- X {
- X /* Find the leftmost occurrence */
- X while( mid > 0 )
- X {
- X mid--;
- X if( cmp = (*I->cmpfunc)(key, KEY(I->node, mid)) )
- X break;
- X }
- X if( cmp )
- X mid++;
- X
- X *i = mid;
- X return 0;
- X }
- X break;
- X }
- X }
- X
- X /* If the comparison yielded greater than, move a step to the right */
- X if( cmp > 0 )
- X mid++;
- X
- X *i = mid;
- X return cmp;
- X}
- X
- X
- X/*-------------------------------- d_search --------------------------------*\
- X *
- X * Purpose : Searches a B-tree for the key value pointed to by <key>. If
- X * the key is found the reference is in REF(i). The path from the
- X * root to the last access node is stored in I->path[], which
- X * enables key traversal from the current point in the tree.
- X *
- X * The search starts at the root, which is always at address 1. For
- X * each node nodesearch is called to perform a binary search in the
- X * node. If the key is not found, the search ends in a leaf node.
- X *
- X * If duplicates are allowed, the first occurrence of the key
- X * value must be found.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * key - Key value being searched for.
- X * addr - Contains node address when function returns.
- X * i - Contains node index when function returns.
- X *
- X * Returns : 0 - The key was found.
- X * 1 - The key was not found.
- X *
- X */
- Xd_search(I, key, addr, i)
- XINDEX *I;
- Xvoid *key;
- Xix_addr *addr;
- Xint *i;
- X{
- X int cmp;
- X
- X /* Start the search at the root */
- X *addr = 1;
- X *i = 0;
- X I->level = 0;
- X
- X
- X for( ;; )
- X {
- X /* Save the addresses and indexes of the traversed nodes */
- X I->path[++I->level].a = *addr;
- X
- X if( noderead(I, I->node, *addr) == (ix_addr)-1 )
- X {
- X /* The node could not be read - zero the number of keys */
- X NSIZE(I->node) = 0;
- X return 0;
- X }
- X
- X cmp = nodesearch(I,key,i);
- X
- X I->path[I->level].i = *i;
- X
- X if( !cmp )
- X {
- X if( I->H.dups )
- X return find_firstoccurrence(I, key, addr, i);
- X return 1;
- X }
- X
- X if( CHILD(I->node, *i) )
- X *addr = CHILD(I->node, *i);
- X else
- X return 0;
- X }
- X}
- X
- X
- X/*-------------------------- find_firstoccurrence --------------------------*\
- X *
- X * Purpose : This function is called in order to find the first occurrence
- X * of a duplicate key in a non-unique index.
- X *
- X * Parameters: I - B-tree index file descriptor.
- X * key - Key value being searched for.
- X * addr - Contains node address when function returns.
- X * i - Contains node index when function returns.
- X *
- X * Returns : 0 - The key was found.
- X * 1 - The key was not found.
- X *
- X */
- Xfind_firstoccurrence(I, key, addr, i)
- XINDEX *I;
- Xvoid *key;
- Xix_addr *addr;
- Xint *i;
- X{
- X int first_occurlevel = I->level;
- X int cmp = 0;
- X
- X while( CHILD(I->node, 0) )
- X {
- X I->level++;
- X I->path[I->level].a = CHILD(I->node, *i);
- X I->path[I->level].i = *i;
- X
- X noderead(I, I->node, I->path[I->level].a);
- X
- X cmp = nodesearch(I,key,i);
- X
- X I->path[I->level].i = *i;
- X
- X /* If the key was found in the current node we search the left
- X * subtree of the key. Otherwise, we search the right subtree of
- X * the rightmost key.
- X */
- X
- X if( !cmp )
- X first_occurlevel = I->level;
- X else
- X *i = NSIZE(I->node);
- X }
- X
- X if( cmp )
- X {
- X I->level = first_occurlevel;
- X *i = I->path[I->level].i;
- X *addr = I->path[I->level].a;
- X
- X noderead(I, I->node, I->path[I->level].a);
- X }
- X else
- X {
- X *i = I->path[I->level].i;
- X *addr = I->path[I->level].a;
- X }
- X
- X return 1;
- X}
- X
- X/* end-of-file */
- X
- END_OF_FILE
- if test 11821 -ne `wc -c <'typhoon/src/bt_open.c'`; then
- echo shar: \"'typhoon/src/bt_open.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/bt_open.c'
- fi
- if test -f 'typhoon/src/ty_ins.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/ty_ins.c'\"
- else
- echo shar: Extracting \"'typhoon/src/ty_ins.c'\" \(12105 characters\)
- sed "s/^X//" >'typhoon/src/ty_ins.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : ty_ins.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_ins.c,v $
- X * Revision 1.2 1994/09/17 16:00:16 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:34 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: ty_ins.c,v 1.2 1994/09/17 16:00:16 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#define DEFINE_GLOBALS
- X#include "ty_glob.h"
- X#include "ty_prot.h"
- X
- X
- Xreport_err(v)
- Xint v;
- X{
- X if( typhoon.ty_errfn )
- X typhoon.ty_errfn(db_status, db_subcode);
- X else
- X {
- X#ifdef UNIX
- X printf("** pid %d - db_status = %d **\n", getpid(), db_status = v);
- X#endif
- X#ifdef OS2
- X printf("** db_status = %d **\n", db_status = v);
- X#endif
- X }
- X
- X return v;
- X}
- X
- X
- X
- X/*--------------------------------- d_block ---------------------------------*\
- X *
- X * Purpose : Requests exclusive access to the API. The second time another
- X * thread in a program calls this function it will block, until
- X * d_unblock() is called.
- X *
- X * Parameters: None.
- X *
- X * Returns : S_OKAY - Ok.
- X *
- X */
- X
- XFNCLASS d_block()
- X{
- X#ifdef OS2
- X os2_block();
- X#endif
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X
- XFNCLASS d_unblock()
- X{
- X#ifdef OS2
- X os2_unblock();
- X#endif
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X/*------------------------------- d_recwrite -------------------------------*\
- X *
- X * Purpose : Updates the contents of the current record.
- X *
- X * Parameters: buf - Buffer containing current record.
- X *
- X * Returns : S_OKAY - Operation performed successfully.
- X * S_DUPLICATE - The record contained a duplicate key. db_subcode
- X * contains the id of the conflicting field or key.
- X * S_NOCD - No current database.
- X * S_NOCR - No current record.
- X * S_RECSIZE - Invalid record size (if variable size).
- X * db_subcode contains the ID of the size field.
- X * S_FOREIGN - A foreign key was not found (db_subcode holds
- X * the foreing key ID).
- X * S_RESTRICT - The primary key was updated, but a dependent
- X * table with restrict rule had a record which
- X * referenced the record to be deleted.
- X * (db_subcode holds the foreign key ID).
- X *
- X */
- XFNCLASS d_recwrite(buf)
- Xvoid *buf;
- X{
- X Record *rec;
- X Key *key;
- X Key *keyptr[RECKEYS_MAX];
- X int keys_changed=0, rc;
- X int i, n;
- X ulong ref;
- X
- X /* Set pointers to current record and first field */
- X if( (rc = set_recfld(-1, &rec, NULL)) != S_OKAY )
- X return rc;
- X
- X ty_lock();
- X if( (rc = update_recbuf()) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X /* Check foreign keys (if any) */
- X if( (rc = check_foreign_keys(rec, buf, 0)) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X /* Check dependent tables (if any) */
- X if( (rc = check_dependent_tables(rec, buf, 'u')) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X /* Have any keys changed? */
- X key = DB->key + rec->first_key;
- X
- X /* Find out which keys have changed and must be updated. An optional key
- X * that has changed from null to not null, or not null to null, or
- X * has changed its value is regarded as changed.
- X */
- X
- X for( n = rec->keys; n-- && KT_GETBASIC(key->type) != KT_FOREIGN; key++ )
- X {
- X if( reckeycmp(key, buf, DB->recbuf) )
- X {
- X keyptr[keys_changed++] = key;
- X
- X if( key->type & KT_UNIQUE )
- X {
- X if( (key->type & KT_OPTIONAL) && null_indicator(key, buf) )
- X continue;
- X
- X if( keyfind(key, buf, &ref) == S_OKAY )
- X {
- X set_subcode(key);
- X ty_unlock();
- X RETURN S_DUPLICATE;
- X }
- X }
- X }
- X }
- X
- X for( n=0; n<keys_changed; n++ )
- X {
- X key = keyptr[n];
- X
- X if( reckeycmp(key, buf, DB->recbuf) )
- X {
- X /* Don't remove null keys */
- X if( !(key->type & KT_OPTIONAL) || !null_indicator(key, DB->recbuf) )
- X keydel(key, DB->recbuf, CURR_REC);
- X
- X /* Don't insert null keys */
- X if( (key->type & KT_OPTIONAL) && null_indicator(key, buf) )
- X continue;
- X
- X if( (rc = keyadd(key, buf, CURR_REC)) != S_OKAY )
- X {
- X set_subcode(key);
- X ty_unlock();
- X RETURN rc;
- X }
- X }
- X }
- X
- X if( rec->is_vlr )
- X {
- X unsigned size;
- X
- X if( (rc = compress_vlr(COMPRESS, rec, DB->recbuf, buf, &size)) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X ty_vlrwrite(rec, DB->real_recbuf, size, CURR_REC);
- X }
- X else
- X {
- X memcpy(DB->recbuf, buf, rec->size);
- X
- X ty_recwrite(rec, DB->real_recbuf, CURR_REC);
- X }
- X
- X /* Store changed references to parent records */
- X update_foreign_keys(rec, 0);
- X
- X if( DB->logging )
- X ty_log('u');
- X
- X log_update(CURR_RECID, CURR_REC, rec->size, buf);
- X
- X ty_unlock();
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X
- X/*-------------------------------- d_recread -------------------------------*\
- X *
- X * Purpose : Read contents of the current record.
- X *
- X * Parameters: buf - Buffer containing current record.
- X *
- X * Returns : S_OKAY - Operation performed successfully.
- X * S_DELETED - Record has been deleted since last accessed.
- X * S_NOCD - No current database.
- X * S_NOCR - No current record.
- X *
- X */
- X
- XFNCLASS d_recread(buf)
- Xvoid *buf;
- X{
- X Record *rec;
- X int rc;
- X
- X if( CURR_DB == -1 )
- X RETURN_RAP(S_NOCD);
- X
- X if( CURR_REC == 0 )
- X RETURN_RAP(S_NOCR);
- X
- X ty_lock();
- X rec = DB->record + CURR_RECID;
- X
- X if( (rc = update_recbuf()) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X if( rec->is_vlr )
- X rc = compress_vlr(UNCOMPRESS, rec, buf, DB->recbuf, NULL);
- X else
- X {
- X memcpy(buf, DB->recbuf, rec->size);
- X rc = S_OKAY;
- X }
- X
- X ty_unlock();
- X
- X RETURN rc;
- X}
- X
- X
- X
- X/*------------------------------- d_fillnew --------------------------------*\
- X *
- X * Purpose : Adds a new record to the current database and updates indexes.
- X *
- X * Parameters: record - Record id.
- X * buf - Pointer to record buffer.
- X *
- X * Returns : S_OKAY - Ok.
- X * S_NOCD - No current database.
- X * S_INVREC - Invalid record id.
- X * S_DUPLICATE - The record contained a duplicate key. The id
- X * of the field or compound key is stored in
- X * db_subcode.
- X * S_RECSIZE - Invalid record size (if variable size).
- X * db_subcode contains the ID of the size field.
- X * S_FOREIGN - A foreign key was not found (db_subcode holds
- X * the foreing key ID.
- X *
- X */
- X
- XFNCLASS d_fillnew(record, buf)
- XId record;
- Xvoid *buf;
- X{
- X Record *rec;
- X Field *fld;
- X Key *key;
- X ulong ref;
- X int i, rc, n;
- X
- X if( (rc = set_recfld(record, &rec, &fld)) != S_OKAY )
- X return rc;
- X
- X /* So far we have no current record */
- X CURR_REC = 0;
- X
- X ty_lock();
- X
- X /* Set pointer to actual data */
- X DB->recbuf = DB->real_recbuf + rec->preamble;
- X
- X /* Check foreign keys (if any) */
- X if( (rc = check_foreign_keys(rec, buf, 1)) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X /* Make sure that there are no duplicate keys in this record */
- X key = DB->key + rec->first_key;
- X
- X for( n = rec->keys; n-- && !KEY_ISFOREIGN(key); key++ )
- X {
- X if( key->type & KT_UNIQUE )
- X {
- X if( KEY_ISOPTIONAL(key) && null_indicator(key, buf) )
- X continue;
- X
- X if( keyfind(key, buf, &ref) == S_OKAY )
- X {
- X set_subcode(key);
- X ty_unlock();
- X RETURN S_DUPLICATE;
- X }
- X }
- X }
- X
- X /* Update data and index files */
- X if( rec->is_vlr )
- X {
- X unsigned size;
- X
- X if( (rc = compress_vlr(COMPRESS, rec, DB->recbuf, buf, &size)) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X if( (rc = ty_vlradd(rec, DB->real_recbuf, size, &CURR_REC)) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X /* The record in DB->recbuf is still compressed */
- X }
- X else
- X {
- X memcpy(DB->recbuf, buf, rec->size);
- X if( (rc=ty_recadd(rec, DB->real_recbuf, &CURR_REC)) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X }
- X
- X CURR_RECID = rec - DB->record;
- X n = rec->keys;
- X key = DB->key + rec->first_key;
- X
- X for( n=rec->keys; n-- && !KEY_ISFOREIGN(key); key++ )
- X {
- X /* Don't store null keys */
- X if( KEY_ISOPTIONAL(key) && null_indicator(key, buf) )
- X continue;
- X
- X if( (rc = keyadd(key, buf, CURR_REC)) != S_OKAY )
- X {
- X ty_unlock();
- X RETURN rc;
- X }
- X }
- X
- X /* Store references to parent records */
- X update_foreign_keys(rec, 1);
- X
- X if( DB->logging )
- X ty_log('u');
- X
- X log_update(CURR_RECID, CURR_REC, rec->size, buf);
- X
- X ty_unlock();
- X
- X RETURN S_OKAY;
- X}
- X
- X
- X/*-------------------------------- d_delete --------------------------------*\
- X *
- X * Purpose : Delete the current record.
- X *
- X * Parameters: None.
- X *
- X * Returns : S_OKAY - The was successfully deleted.
- X * S_NOCD - No current database.
- X * S_NOCR - No current record.
- X * S_RESTRICT - A dependent table had a foreign key which
- X * referenced the primary key of the record to
- X * to be deleted. db_subcode holds the foreign
- X * key ID.
- X *
- X */
- X
- XFNCLASS d_delete()
- X{
- X Record *rec;
- X Key *key;
- X int n, rc;
- X
- X if( CURR_DB == -1 )
- X RETURN_RAP(S_NOCD);
- X
- X if( CURR_REC == 0 )
- X RETURN_RAP(S_NOCR);
- X
- X /* We must update recbuf in order to access the record's keys */
- X ty_lock();
- X
- X rec = DB->record + CURR_RECID;
- X DB->recbuf = DB->real_recbuf + rec->preamble;
- X
- X if( (rc = update_recbuf()) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X /* Check dependent tables (if any) */
- X if( (rc = check_dependent_tables(rec, DB->recbuf, 'd')) != S_OKAY )
- X {
- X ty_unlock();
- X return rc;
- X }
- X
- X key = DB->key + rec->first_key;
- X
- X if( DB->fh[rec->fileid].any->type == 'd' )
- X rc = ty_recdelete(rec, CURR_REC);
- X else
- X rc = ty_vlrdel(rec, CURR_REC);
- X
- X if( rc != S_OKAY )
- X {
- X ty_unlock();
- X RETURN rc;
- X }
- X
- X for( n=rec->keys; n-- && !KEY_ISFOREIGN(key); key++ )
- X {
- X if( KEY_ISOPTIONAL(key) && null_indicator(key, DB->recbuf) )
- X continue;
- X
- X if( (rc = keydel(key, DB->recbuf, CURR_REC)) != S_OKAY )
- X {
- X printf("typhoon: could not delete key %s.%s (db_status %d)\n",
- X rec->name, key->name, rc);
- X ty_unlock();
- X RETURN rc;
- X }
- X }
- X
- X delete_foreign_keys(rec);
- X
- X if( DB->logging )
- X ty_log('d');
- X
- X log_delete(CURR_RECID, CURR_REC);
- X
- X CURR_REC = 0;
- X
- X ty_unlock();
- X
- X RETURN S_OKAY;
- X}
- X
- X/* end-of-file */
- END_OF_FILE
- if test 12105 -ne `wc -c <'typhoon/src/ty_ins.c'`; then
- echo shar: \"'typhoon/src/ty_ins.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/ty_ins.c'
- fi
- if test -f 'typhoon/src/ty_io.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/ty_io.c'\"
- else
- echo shar: Extracting \"'typhoon/src/ty_io.c'\" \(12101 characters\)
- sed "s/^X//" >'typhoon/src/ty_io.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : bt_io
- 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 the layer between the low-level B-tree and record
- X * routines and the Typhoon API functions. The low-level routines are never
- X * called directly from the API functions.
- X *
- X * +-----------------------------+
- X * | Typhoon API functions |
- X * +-----------------------------+
- X * | Dynamic open files layer | <----- this layer
- X * +----------+------------------+
- X * | B-tree | Record | VLR |
- X * +----------+------------------+
- X * | C language read/write |
- X * +-----------------------------+
- X *
- X * Functions:
- X *
- X * $Log: ty_io.c,v $
- X * Revision 1.2 1994/09/17 16:00:16 tbp
- X * typhoon.h and environ.h are now included from <>.
- X *
- X * Revision 1.1 1994/09/13 21:28:34 tbp
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: ty_io.c,v 1.2 1994/09/17 16:00:16 tbp Exp $";
- X
- X#ifdef UNIX
- X# include <unistd.h>
- X#endif
- X#include <string.h>
- X#include <stdio.h>
- X#include <errno.h>
- X#include <stdarg.h>
- X#include <time.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#define PTRTORECID(rec) ((((rec) - DB->record)+1) * REC_FACTOR)
- X
- X/*-------------------------- Function prototypes ---------------------------*/
- Xstatic int checkfile PRM( (int); )
- X
- X/*---------------------------- Global variables ----------------------------*/
- Xstatic ulong seqno = 1; /* Current sequence number (always > 0) */
- X
- X
- X
- X
- Xty_closeafile()
- X{
- X ulong lowest_seqno = seqno;
- X int dbs, fhs; /* Used for scanning tables */
- X Dbentry *db =typhoon.dbtab; /* Used for scanning tables */
- X Fh *fh; /* Used for scanning tables */
- X Fh *foundfh = NULL; /* The filehandle found to be closed */
- X
- X /* Find the file least recently accessed open file */
- X dbs = DB_MAX;
- X while( dbs-- )
- X {
- X if( DB->clients )
- X {
- X fh = DB->fh;
- X fhs = DB->header.files;
- X
- X while( fhs-- )
- X {
- X if( fh->any && fh->any->fh != -1 )
- X {
- X if( lowest_seqno > fh->any->seqno )
- X {
- X lowest_seqno = fh->any->seqno;
- X foundfh = fh;
- X }
- X }
- X fh++;
- X }
- X }
- X db++;
- X }
- X
- X if( foundfh == NULL )
- X {
- X printf("\a*** Could not close a file **");
- X return -1;
- X }
- X
- X /* If the file is already closed, we just return */
- X if( foundfh->any->fh == -1 )
- X return S_OKAY;
- X
- X switch( foundfh->any->type )
- X {
- X case 'k':
- X case 'r':
- X btree_dynclose(foundfh->key);
- X break;
- X case 'd':
- X rec_dynclose(foundfh->rec);
- X break;
- X case 'v':
- X vlr_dynclose(foundfh->vlr);
- X break;
- X }
- X
- X /* Mark the file as closed */
- X typhoon.cur_open--;
- X
- X return 0;
- X}
- X
- X
- X
- X
- Xstatic checkfile(fileid)
- Xint fileid;
- X{
- X Fh *fh;
- X int rc;
- X
- X fh = &DB->fh[fileid];
- X
- X /* If the file is open we set the file's sequence number to seqno to
- X * indicate that it is the most recently accessed file.
- X */
- X if( fh->any->fh != -1 )
- X {
- X fh->any->seqno = seqno++;
- X return S_OKAY;
- X }
- X
- X if( ty_closeafile() == -1 )
- X {
- X puts("checkfile: could not find a file to close");
- X RETURN S_IOFATAL;
- X }
- X
- X /* Now <cur_open> should be less than <max_open> so we can call
- X * ty_openfile() to reopen the file. If ty_openfile() cannot open the
- X * file the API function will return S_IOFATAL.
- X */
- X
- X switch( fh->any->type )
- X {
- X case 'k':
- X case 'r':
- X rc = btree_dynopen(fh->key);
- X break;
- X case 'd':
- X rc = rec_dynopen(fh->rec);
- X break;
- X case 'v':
- X rc = vlr_dynopen(fh->vlr);
- X break;
- X }
- X
- X fh->any->seqno = seqno++;
- X typhoon.cur_open++;
- X
- X return rc;
- X}
- X
- X
- X/*------------------------------ ty_openfile -------------------------------*\
- X *
- X * Purpose : Opens a database file.
- X *
- X * Parameters: fp - Pointer to file definition table entry.
- X * fh - Pointer to file handle table entry.
- X * shared - Open in shared mode?
- X *
- X * Returns : db_status from d_keyopen(), d_recopen() or vlr_open().
- X *
- X */
- X
- Xty_openfile(fp, fh, shared)
- XFile *fp;
- XFh *fh;
- Xint shared;
- X{
- X char fname[255];
- X Key *key;
- X CMPFUNC cmp;
- X int rc;
- X
- X /* If the maximum number of open files has been reached we return the
- X * CLOSEDPTR to indicate to the other ty_.. functions that the file
- X * descriptor points to a closed file and must be reopened.
- X */
- X if( typhoon.cur_open == typhoon.max_open )
- X {
- X if( ty_closeafile() == -1 )
- X {
- X puts("ty_openfile: could not find a file to close");
- X RETURN S_IOFATAL;
- X }
- X }
- X
- X /* File is located in <DB->dbfpath> */
- X sprintf(fname, "%s%s", DB->dbfpath, fp->name);
- X
- X switch( fp->type )
- X {
- X case 'r':
- X fh->key = btree_open(fname, sizeof(REF_ENTRY), fp->pagesize, (CMPFUNC)refentrycmp, 0, shared);
- X break;
- X case 'k':
- X key = DB->key + fp->id;
- X
- X /* If the key has multiple fields or is sorted in descending order
- X * we use the compoundkeycmp function for key value comparisons.
- X */
- X if( key->fields > 1 || !DB->keyfield[key->first_keyfield ].asc )
- X cmp = compoundkeycmp;
- X else
- X {
- X Field *fld = &DB->field[ DB->keyfield[key->first_keyfield].field ];
- X
- X cmp = keycmp[ fld->type & (FT_BASIC|FT_UNSIGNED) ];
- X }
- X
- X fh->key = btree_open(fname, key->size, fp->pagesize, cmp,
- X (key->type & KT_UNIQUE) ? 0 : 1, shared);
- X break;
- X case 'd':
- X /* Add the preamble to the size of the record */
- X fh->rec = rec_open(fname, DB->record[fp->id].size +
- X DB->record[fp->id].preamble, shared);
- X break;
- X case 'v':
- X fh->vlr = vlr_open(fname, fp->pagesize, shared);
- X break;
- X }
- X
- X if( db_status == S_OKAY )
- X {
- X fh->any->type = fp->type;
- X fh->any->seqno = seqno++;
- X typhoon.cur_open++;
- X }
- X/*
- X else
- X printf("cannot open '%s' (db_status %d, errno %d)\n", fname, db_status, errno);
- X*/
- X return db_status;
- X}
- X
- X
- X/*------------------------------- d_closefile ------------------------------*\
- X *
- X * Purpose : Closes a database file.
- X *
- X * Parameters: fh - Pointer to file handle table entry.
- X *
- X * Returns : db_status from d_keyclose(), d_recclose() or vlr_close().
- X *
- X */
- X
- Xty_closefile(fh)
- XFh *fh;
- X{
- X /* If the file is already closed, we just return */
- X if( fh->any->fh != -1 )
- X typhoon.cur_open--;
- X
- X switch( fh->any->type )
- X {
- X case 'k':
- X case 'r':
- X btree_close(fh->key);
- X break;
- X case 'd':
- X rec_close(fh->rec);
- X break;
- X case 'v':
- X vlr_close(fh->vlr);
- X break;
- X }
- X
- X /* Mark the file as closed */
- X fh->any->fh = -1;
- X
- X return db_status;
- X}
- X
- X
- X
- Xty_keyadd(key, value, ref)
- XKey *key;
- Xvoid *value;
- Xulong ref;
- X{
- X INDEX *idx;
- X int rc;
- X
- X if( (rc = checkfile(key->fileid)) != S_OKAY )
- X return rc;
- X
- X idx = DB->fh[key->fileid].key;
- X rc = btree_add(idx, value, ref);
- X btree_keyread(idx, CURR_KEYBUF);
- X
- X return rc;
- X}
- X
- X
- Xty_keyfind(key, value, ref)
- XKey *key;
- Xvoid *value;
- Xulong *ref;
- X{
- X INDEX *idx;
- X int rc;
- X
- X if( (rc = checkfile(key->fileid)) != S_OKAY )
- X return rc;
- X
- X idx = DB->fh[key->fileid].key;
- X rc = btree_find(idx, value, ref);
- X btree_keyread(idx, CURR_KEYBUF);
- X
- X return rc;
- X}
- X
- X
- X
- Xty_keyfrst(key, ref)
- XKey *key;
- Xulong *ref;
- X{
- X INDEX *idx;
- X int rc;
- X
- X if( (rc = checkfile(key->fileid)) != S_OKAY )
- X return rc;
- X
- X idx = DB->fh[key->fileid].key;
- X rc = btree_frst(idx, ref);
- X btree_keyread(idx, CURR_KEYBUF);
- X
- X return rc;
- X}
- X
- X
- Xty_keylast(key, ref)
- XKey *key;
- Xulong *ref;
- X{
- X INDEX *idx;
- X int rc;
- X
- X if( (rc = checkfile(key->fileid)) != S_OKAY )
- X return rc;
- X
- X idx = DB->fh[key->fileid].key;
- X rc = btree_last(idx, ref);
- X btree_keyread(idx, CURR_KEYBUF);
- X
- X return rc;
- X}
- X
- X
- Xty_keyprev(key, ref)
- XKey *key;
- Xulong *ref;
- X{
- X INDEX *idx;
- X int rc;
- X
- X if( (rc = checkfile(key->fileid)) != S_OKAY )
- X return rc;
- X
- X idx = DB->fh[key->fileid].key;
- X rc = btree_prev(idx, ref);
- X btree_keyread(idx, CURR_KEYBUF);
- X
- X return rc;
- X}
- X
- X
- Xty_keynext(key, ref)
- XKey *key;
- Xulong *ref;
- X{
- X INDEX *idx;
- X int rc;
- X
- X if( (rc = checkfile(key->fileid)) != S_OKAY )
- X return rc;
- X
- X idx = DB->fh[key->fileid].key;
- X rc = btree_next(idx, ref);
- X btree_keyread(idx, CURR_KEYBUF);
- X
- X return rc;
- X}
- X
- X
- Xty_keydel(key, value, ref)
- XKey *key;
- Xvoid *value;
- Xulong ref;
- X{
- X INDEX *idx;
- X int rc;
- X
- X if( (rc = checkfile(key->fileid)) != S_OKAY )
- X return rc;
- X
- X idx = DB->fh[key->fileid].key;
- X rc = btree_del(idx, value, ref);
- X btree_keyread(idx, CURR_KEYBUF);
- X
- X return rc;
- X}
- X
- X
- Xty_recadd(rec, buf, recno)
- XRecord *rec;
- Xvoid *buf;
- Xulong *recno;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_add(DB->fh[rec->fileid].rec, buf, recno);
- X}
- X
- X
- Xty_recwrite(rec, buf, recno)
- XRecord *rec;
- Xvoid *buf;
- Xulong recno;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_write(DB->fh[rec->fileid].rec, buf, recno);
- X}
- X
- X
- Xty_recread(rec, buf, recno)
- XRecord *rec;
- Xvoid *buf;
- Xulong recno;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_read(DB->fh[rec->fileid].rec, buf, recno);
- X}
- X
- X
- Xty_recdelete(rec, recno)
- XRecord *rec;
- Xulong recno;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_delete(DB->fh[rec->fileid].rec, recno);
- X}
- X
- X
- Xty_recfrst(rec, buf)
- XRecord *rec;
- Xvoid *buf;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_frst(DB->fh[rec->fileid].rec, buf);
- X}
- X
- X
- Xty_reclast(rec, buf)
- XRecord *rec;
- Xvoid *buf;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_last(DB->fh[rec->fileid].rec, buf);
- X}
- X
- X
- Xty_recnext(rec, buf)
- XRecord *rec;
- Xvoid *buf;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_next(DB->fh[rec->fileid].rec, buf);
- X}
- X
- Xty_recprev(rec, buf)
- XRecord *rec;
- Xvoid *buf;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_prev(DB->fh[rec->fileid].rec, buf);
- X}
- X
- Xulong ty_reccount(rec, count)
- XRecord *rec;
- Xulong *count;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_numrecords(DB->fh[rec->fileid].rec, count);
- X}
- X
- Xty_reccurr(rec, recno)
- XRecord *rec;
- Xulong *recno;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return rec_curr(DB->fh[rec->fileid].rec, recno);
- X}
- X
- Xty_vlradd(rec, buf, size, recno)
- XRecord *rec;
- Xvoid *buf;
- Xunsigned size;
- Xulong *recno;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return vlr_add(DB->fh[rec->fileid].vlr, buf, size, recno);
- X}
- X
- Xty_vlrwrite(rec, buf, size, recno)
- XRecord *rec;
- Xvoid *buf;
- Xunsigned size;
- Xulong recno;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return vlr_write(DB->fh[rec->fileid].vlr, buf, size + rec->preamble, recno);
- X}
- X
- X
- Xunsigned ty_vlrread(rec, buf, recno, size)
- XRecord *rec;
- Xvoid *buf;
- Xulong recno;
- Xunsigned *size;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return vlr_read(DB->fh[rec->fileid].vlr, buf, recno, size);
- X}
- X
- Xty_vlrdel(rec, recno)
- XRecord *rec;
- Xulong recno;
- X{
- X int rc;
- X
- X if( (rc = checkfile(rec->fileid)) != S_OKAY )
- X return rc;
- X
- X return vlr_del(DB->fh[rec->fileid].vlr, recno);
- X}
- X
- X/* end-of-file */
- END_OF_FILE
- if test 12101 -ne `wc -c <'typhoon/src/ty_io.c'`; then
- echo shar: \"'typhoon/src/ty_io.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/ty_io.c'
- fi
- if test -f 'typhoon/src/util/ddlpsym.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/util/ddlpsym.c'\"
- else
- echo shar: Extracting \"'typhoon/src/util/ddlpsym.c'\" \(6862 characters\)
- sed "s/^X//" >'typhoon/src/util/ddlpsym.c' <<'END_OF_FILE'
- X/*----------------------------------------------------------------------------
- X * File : ddlpsym.c
- X * Program : ddlp
- 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 * Symbol table functions for ddlp.
- X *
- X * $Log: ddlpsym.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:53 tbp
- X * Added to repository.
- X *
- X * Added to repository.
- X *
- X *
- X *--------------------------------------------------------------------------*/
- X
- Xstatic char rcsid[] = "$Id: ddlpsym.c,v 1.2 1994/09/17 16:00:52 tbp Exp $";
- X
- X#include <stdio.h>
- X#include <string.h>
- X#ifndef UNIX
- X# include <stdlib.h>
- X#endif
- X#include <environ.h>
- X#include "../ty_dbd.h"
- X#include "ddlp.h"
- X#include "ddlpsym.h"
- X#include "ddlpglob.h"
- X
- X/*-------------------------- Function prototypes ---------------------------*/
- Xstatic void print_struct PRM( (sym_struct *, int); )
- X
- X/*---------------------------- Global variables ----------------------------*/
- Xsym_struct *first_str = NULL; /* Pointer to start of struct table */
- Xsym_struct *last_str = NULL; /* Pointer to last struct */
- Xsym_struct *cur_str = NULL; /* Pointer to current struct */
- Xsym_struct *structnest[NEST_MAX]; /* Structure nesting table */
- Xint curnest = -1; /* Current structure nesting */
- X
- X
- X/*------------------------------ sym_addmember -----------------------------*\
- X *
- X * Purpose: This function adds a member to the structure currently
- X * being defined. The member is aligned according to <align>.
- X *
- X * Params : name - struct member name.
- X * type - member type, see FT_.. constants.
- X * ... - If <type> == FT_STRUCT the 3rd parameter is a
- X * pointer to a structdef record, otherwise it is
- X * the size of the field.
- X *
- X * Returns : Nothing
- X *
- X */
- X
- Xvoid sym_addmember(name, type, struc)
- Xchar *name;
- Xint type;
- Xsym_struct *struc;
- X{
- X sym_struct *str = structnest[curnest];
- X sym_member *mem;
- X
- X /* Make sure that this member name is not already used in this struct */
- X for( mem = str->first_member; mem; mem = mem->next )
- X if( !strcmp(name, mem->name) )
- X {
- X yyerror("duplicate member name '%s'", name);
- X return;
- X }
- X
- X if( !(mem = (sym_member *)calloc(1,sizeof(*mem) + (dims-1) * sizeof(*mem->dim))) )
- X err_quit("out of memory");
- X
- X if( type == FT_STRUCT )
- X {
- X mem->struc = struc;
- X mem->size = struc->size;
- X }
- X else
- X mem->size = typeinfo[(type & FT_BASIC)-1].size;
- X
- X strcpy(mem->name, name);
- X mem->type = type;
- X mem->dims = dims;
- X mem->elemsize = mem->size;
- X
- X /* If this member has arrays they must be stored and the size adjusted */
- X if( dims )
- X {
- X memcpy(mem->dim, dim, sizeof(*dim) * dims);
- X
- X while( --dims )
- X dim[0] *= dim[dims];
- X mem->size *= dim[0];
- X }
- X
- X /* Add the new member to the member list */
- X if( str->last_member )
- X str->last_member->next = mem;
- X else
- X str->first_member = mem;
- X str->last_member = mem;
- X str->members++;
- X
- X /*
- X * If the structure is a union all members must be at offset 0, and
- X * the union must have the size of the biggest member.
- X */
- X if( str->is_union )
- X {
- X if( mem->size > str->size )
- X str->size = mem->size;
- X }
- X else
- X {
- X align_offset(&str->size, type);
- X mem->offset = str->size;
- X str->size += mem->size;
- X }
- X}
- X
- X
- Xvoid sym_addstruct(name, is_union)
- Xchar *name;
- Xint is_union;
- X{
- X sym_struct *str;
- X
- X /* Allocate new structdef and clear all fields */
- X if( !(str = (sym_struct *)calloc(1, sizeof *str)) )
- X err_quit("out of memory");
- X
- X strcpy(str->name, name);
- X str->is_union = is_union;
- X
- X /* Insert structure in list */
- X if( !first_str )
- X first_str = str;
- X else
- X last_str->next = str;
- X cur_str = last_str = str;
- X
- X structnest[++curnest] = str;
- X}
- X
- X
- Xvoid sym_endstruct()
- X{
- X /* The size of a structure depends depends on the type of the last member
- X */
- X/* align_offset(&structnest[curnest]->size, FT_LONG);*/
- X align_offset(&structnest[curnest]->size, cur_str->last_member->type);
- X
- X cur_str = structnest[--curnest];
- X}
- X
- X
- Xsym_struct *sym_findstruct(name, is_union)
- Xchar *name;
- Xint is_union;
- X{
- X sym_struct *str = first_str;
- X
- X while( str )
- X {
- X if( !strcmp(name, str->name) && str->is_union == is_union )
- X return str;
- X
- X str = str->next;
- X }
- X
- X yyerror("unknown struct '%s'", name);
- X return NULL;
- X}
- X
- X
- Xsym_member *sym_findmember(str, name)
- Xsym_struct *str;
- Xchar *name;
- X{
- X sym_member *mem = str->first_member;
- X
- X while( mem )
- X {
- X if( !strcmp(name, mem->name) )
- X return mem;
- X
- X mem = mem->next;
- X }
- X
- X return NULL;
- X}
- X
- X
- Xstatic void print_struct(str, nesting)
- Xsym_struct *str;
- X{
- X static char *type[] = { "struct", "union" };
- X sym_member *mem = str->first_member;
- X extern FILE *hfile;
- X int i;
- X
- X fprintf(hfile, "%*s%s %s { /* size %d */\n", nesting * 4, "",
- X type[str->is_union],
- X str->name,
- X str->size);
- X
- X while( mem )
- X {
- X if( mem->type == FT_STRUCT )
- X {
- X if( mem->struc->printed )
- X {
- X fprintf(hfile, "%*s%s %s ",
- X (nesting+1)*4, "",
- X type[mem->struc->is_union],
- X mem->struc->name);
- X }
- X else
- X {
- X mem->struc->printed = 1;
- X print_struct(mem->struc, nesting+1);
- X fprintf(hfile, "%*s} ", (nesting+1)*4, "");
- X }
- X }
- X else
- X {
- X fprintf(hfile, "%*s", (nesting+1) * 4, "");
- X if( mem->type & FT_UNSIGNED )
- X fprintf(hfile, "unsigned ");
- X fprintf(hfile, "%-8s", typeinfo[(mem->type & FT_BASIC) - 1].name);
- X }
- X
- X fprintf(hfile, "%s", mem->name);
- X
- X for( i=0; i<mem->dims; i++ )
- X fprintf(hfile, "[%d]", mem->dim[i]);
- X
- X fprintf(hfile, ";\n");
- X mem = mem->next;
- X }
- X
- X if( nesting == 0 )
- X fprintf(hfile, "};\n\n");
- X}
- X
- X
- Xvoid print_structures()
- X{
- X sym_struct *str = first_str;
- X
- X while( str )
- X {
- X if( !str->printed )
- X print_struct(str, 0);
- X str = str->next;
- X }
- X}
- X
- X
- X/* end-of-file */
- END_OF_FILE
- if test 6862 -ne `wc -c <'typhoon/src/util/ddlpsym.c'`; then
- echo shar: \"'typhoon/src/util/ddlpsym.c'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/util/ddlpsym.c'
- fi
- if test -f 'typhoon/src/util/imp_y.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'typhoon/src/util/imp_y.h'\"
- else
- echo shar: Extracting \"'typhoon/src/util/imp_y.h'\" \(215 characters\)
- sed "s/^X//" >'typhoon/src/util/imp_y.h' <<'END_OF_FILE'
- X#define T_IMPORT 257
- X#define T_RECORD 258
- X#define T_STRUCT 259
- X#define T_UNION 260
- X#define T_IN 261
- X#define T_IDENT 262
- X#define T_STRING 263
- Xtypedef union {
- X char s[IDENT_LEN+1];
- X} YYSTYPE;
- Xextern YYSTYPE yylval;
- END_OF_FILE
- if test 215 -ne `wc -c <'typhoon/src/util/imp_y.h'`; then
- echo shar: \"'typhoon/src/util/imp_y.h'\" unpacked with wrong size!
- fi
- # end of 'typhoon/src/util/imp_y.h'
- fi
- echo shar: End of archive 3 \(of 9\).
- cp /dev/null ark3isdone
- 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...
-