/* File: bsubs.c * Author: Jean Thierry-Mieg (mieg@mrc-lmb.cam.ac.uk) * Copyright (C) J Thierry-Mieg and R Durbin, 1992 * ------------------------------------------------------------------- * Acedb is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt * ------------------------------------------------------------------- * This file is part of the ACEDB genome database package, written by * Richard Durbin (MRC LMB, UK) rd@mrc-lmb.cam.ac.uk, and * Jean Thierry-Mieg (CRBM du CNRS, France) mieg@kaa.cnrs-mop.fr * * Description: * Exported functions: * HISTORY: * Last edited: Sep 24 14:28 1999 (fw) * Created: Sun Jul 5 12:55:14 1992 (mieg) *------------------------------------------------------------------- */ /* $Id: bsubs.c,v 1.11 1999/09/24 13:30:56 fw Exp $ */ /***************************************************************/ /***************************************************************/ /** File Bsubs.c : **/ /** Handles the B blocks of the ACeDB program. **/ /***************************************************************/ /***************************************************************/ /* */ /* 14xs routines are public : */ /* init, get, dump, prune, */ /* Bnode2str/str2node, */ /* Bnextkey, */ /* Bbranchlen, freelen, newnode. */ /* .Durbin & J.Thierry-Mieg. */ /* last modified 4/1/1991 by JTM. */ /* */ /***************************************************************/ #ifdef ACEDB5 void compilersDoNotLike3 (void *emptyFiles) {return ; } #else /* !ACEDB5 */ /* only before ACEDB 5 */ #include "acedb.h" #include "bs_.h" /* Defines BS */ #include "b_.h" #include "lex.h" #include "pick.h" #include "block.h" #include "byteswap.h" static void Bprune2(BP bp, NODE nn); /* #define TESTBSUBS */ #ifdef TESTBSUBS #include "bs.h" /* bsCreate in Bdump */ #endif /* TESTBSUBS */ #ifdef ACEDB4 void swapBBlock(BP bp) { int i; bp->hat.h.disk = swapDISK(bp->hat.h.disk); bp->hat.h.nextdisk = swapDISK(bp->hat.h.nextdisk); bp->hat.h.session = swapInt(bp->hat.h.session); bp->hat.h.key = swapKEY(bp->hat.h.key); bp->hat.top = swapNODE(bp->hat.top); bp->hat.free = swapNODE(bp->hat.free); for( i=0; in[i].d1 = swapNODE(bp->n[i].d1); bp->n[i].d2 = swapNODE(bp->n[i].d2); } } #endif /* ACEDB4 */ /**************************************************************/ /*initialise a new B */ /*called by B2BSstore2 */ /* must not touch the block header */ void Binit (BP bp) { static struct bblock Bnull; int i; static int firstpass=1; if (firstpass) { /*initialise Bnull*/ memset (&Bnull, BLOC_SIZE, 0) ; Bnull.hat.top = 0 ; Bnull.hat.free = 1 ; Bnull.hat.h.type = 'B'; for (i = 1 ; i < BNODEMAX-1 ; i++) Bnull.n[i].d1 = i+1 ; firstpass = 0 ; } *bp = Bnull ; } /**************************************************************/ /*given a key * finds the origin of the correct branch * public; called by Bshow in BSsubs */ void Bget (BP *bp, NODE *nn, KEY key) { NODEP r; if (iskeyold (key)) { blockpinn(key,bp) ; *nn=(*bp)->hat.top; while(*nn) {r=(*bp)->n+*nn; #ifdef ACEDB4 if(maybeSwapKEY(r->ck.key)==key) break; #else /* !ACEDB4 */ if(r->ck.key==key) break; #endif /* !ACEDB4 */ *nn=r->d1; } /* if (*nn==0) on n a pas trouve alors que l on avait le bloc*/ if (!*nn) messcrash("Block error in Bget(%s)", name(key)) ; } else messcrash("Bget called on not old key %s", name(key)) ; } /**************************************************************/ void Bdump (KEY key) { #ifdef TESTBSUBS int j ; BP bp; NODEP r; NODE i; int nblocks ; bp=0; if (!iskeyold(key)) { messout("key %lu=%s never saved",key,name(key)) ; return ; } nblocks = blockpinn(key,&bp) ; do { printf ("Block dump of key %s:%s\n", className(key), name(key)) ; printf( " disk : %d session : %d\n", bp->hat.h.disk, bp->hat.h.session), if (bp->hat.h.type == 'A') printf(" Array\n") ; else if (bp->hat.h.type == 'B') { printf ("Bdump bp=%ld, top=%d,free=%d, freelen=%d searching %lu : \n", bp,bp->hat.top,bp->hat.free,Bfreelen(bp), key) ; for (i = 1 ; i < BNODEMAX ; i++) { r = bp->n + i ; printf ("%3d l=%3d r=%3d ", i, r->d1, r->d2) ; for (j = 0 ; j < NODEX ; j++) printf ("%02x ", r->ck.c[j]) printf (" cp=%6s ",r->ck.c) ; #ifdef ACEDB4 printf (" k=%lu=%s\n", maybeSwapKEY(r->ck.key), maybeSwapKEY(r->ck.key)) ; #else /* !ACEDB4 */ printf (" k=%lu=%s\n", r->ck.key, r->ck.key) ; #endif /* !ACEDB4 */ } } } while (blockNext (&bp)) ; /* do-while construction */ blockunpinn (key) ; if (pickType (key) == 'B') { OBJ obj = bsCreate (key) ; if (obj) bsDump (obj) ; bsDestroy (obj) ; } #else /* !TESTSUBS */ messout ("To see the blocks recompile bsubs.c with #define TESTBSUBS") ; #endif /* !TESTSUBS */ } /**************************************************************/ void Bnode2str(char *cq, BP bp, NODEP *r) { register char *cp; register int i ; /* ((*r)->ck.key <=_LastC) Must be garanteed in the call */ while ((*r)->d2) { *r=bp->n+(*r)->d2 ; cp=(*r)->ck.c; i=NODEX; while (i--) if(*cp) *cq++ = *cp++ ; /* RD: ambiguous without spaces on SGI */ } *cq = 0; /*finishes the cq string*/ } /**************************************************************/ /* Called only from BSsubs*/ void Bstr2node(BS bs, BP bp, NODEP *r) { NODEP rnew ; register char *cp, *cq; register int i=0 ; char nulChar = 0; if(bs->bt && bs->bt->cp) cp = bs->bt->cp ; else cp = &nulChar ; /* This is not while (*cp) because i want to go thru once on an empty string */ while (TRUE) { rnew = Bnewnode(bp) ; (*r)->d2 = (NODE) (rnew - bp->n) ; *r = rnew ; cq=(*r)->ck.c; /* if ((*r)->ck.x.i) invokeDebugger() ; This check fails many times */ i=NODEX; while (*cp && i--) *cq++ = *cp++ ; /* RD: ambiguous without spaces on SGI */ /* recall that Bnewnode memset *cq to 0 */ if (!*cp) break ; } if (i > 0) *cq = 0 ; } /***************************************************************************/ void Bprune(BP bp, NODE nn,BOOL bothsides) { NODEP r=bp->n+nn; NODE n=bp->hat.top, nright = r->d1, n1 ; if(bothsides) nright = 0 ; else r->d1=0; if(n==nn) bp->hat.top = nright ; else { while(n && (nn != (n1 = (bp->n+n)->d1 ))) n = n1 ; if (!n) messcrash ("Link list error in Bprune") ; (bp->n + n)->d1 = nright ; } Bprune2(bp,nn) ; } /***************************************************************************/ static void Bprune2(BP bp, NODE nn) { NODEP r=bp->n+nn; if(r->d2)Bprune2(bp,r->d2); if(r->d1)Bprune2(bp,r->d1); r->d2=0; r->d1=bp->hat.free; bp->hat.free=nn; } /**************************************************************/ NODEP Bnewnode(BP bp) { NODEP r; BHAT b = &(bp->hat); /* RD: ambiguous without spaces on SGI */ if (!b->free) messcrash ("Bnew node : block overflow") ; r = bp->n + b->free ; b->free = r->d1 ; memset ((char *) r, 0, sizeof (NODE)) ; return r ; } /***************************************************************************/ int Bbranchlen(BP bp,NODE nn) { NODEP r=bp->n+nn; return( nn ? ( ( r->d1 ? Bbranchlen(bp,r->d1) : 0 ) +( r->d2 ? Bbranchlen(bp,r->d2) : 0 ) + 1 ) : 0 ); } /***************************************************************************/ int Bfreelen(BP bp) { register int i=0; register NODE nn=bp->hat.free; while(nn) {i++; nn=(bp->n+nn)->d1; } return(i); } /***************************************************************************/ /* Gives, one by one the list of the * keys of p, de la branche ainee. * probably, the objects in p. */ BOOL Bnextkey(void **it, BP p, KEY *kp) { struct iterator { NODE nn; BP bp; } *iterator_real; NODEP r; if (!p) /* Abort iteration */ { iterator_real = (struct iterator *)*it; messfree(iterator_real); *it = NULL; return FALSE; } if (*kp) { iterator_real = (struct iterator *)*it; if (!iterator_real || (iterator_real->bp != p)) messcrash("WARNING : bad call to Bnextkey /n %s", name(*kp)); } else { iterator_real = messalloc(sizeof(struct iterator)); iterator_real->bp = p; iterator_real->nn = p->hat.top; *it= (void *)iterator_real; } if (iterator_real->nn) { r=p->n+iterator_real->nn; iterator_real->nn=r->d1; #ifdef ACEDB4 *kp=maybeSwapKEY(r->ck.key); #else *kp=r->ck.key; #endif return TRUE; } *kp=0; messfree(iterator_real); *it = NULL; return FALSE; } /* Bnextkey */ #endif /* !ACEDB5 */ /************************* eof ******************************/