CCL Home Page
Up Directory CCL abstree.c
/* abstree.c
 * RasMol2 Molecular Graphics
 * Roger Sayle, October 1994
 * Version 2.5
 */
#include "rasmol.h"

#ifdef IBMPC
#include 
#endif
#ifndef sun386
#include 
#endif
#include 
#include 
#include 
#include 

#define ABSTREE
#include "molecule.h"
#include "abstree.h"


#define ExprPool    16
#define SetPool     4

typedef struct _SymEntry {
                struct _SymEntry __far *lft;
                struct _SymEntry __far *rgt;
                AtomSet __far *defn;
                char *ident;
                } SymEntry;

static SymEntry __far *SymbolTable;
static SymEntry __far *FreeEntry;
static AtomSet __far *FreeSet;
static Expr *FreeExpr;
static Expr FalseExpr;
static Expr TrueExpr;

/* Macros for commonly used loops */
#define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
                     for(group=chain->glist;group;group=group->gnext)    \
                     for(aptr=group->alist;aptr;aptr=aptr->anext)


#define BitAcidic       0x001
#define BitAliphatic    0x002
#define BitAromatic     0x004
#define BitBasic        0x008
#define BitBuried       0x010
#define BitCyclic       0x020
#define BitHydrophobic  0x040
#define BitMedium       0x080
#define BitNeutral      0x100
#define BitSmall        0x200

#define BitCharged      0x009
#define BitNotLarge     0x280

/* Acyclic = !Cyclic         */
/* Large = !Medium && !Small */
/* Polar = !Hydrophobic      */
/* Surface = !Buried         */


static int AminoProp[] = {
        /*ALA*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral |
                 BitSmall,
        /*GLY*/  BitAliphatic | BitHydrophobic | BitNeutral | BitSmall,
        /*LEU*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral,
        /*SER*/  BitNeutral | BitSmall,
        /*VAL*/  BitAliphatic | BitBuried | BitHydrophobic | BitMedium |
                 BitNeutral,
        /*THR*/  BitMedium | BitNeutral,
        /*LYS*/  BitBasic,
        /*ASP*/  BitAcidic | BitMedium,
        /*ILE*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral,
        /*ASN*/  BitMedium | BitNeutral,
        /*GLU*/  BitAcidic,
        /*PRO*/  BitCyclic | BitHydrophobic | BitMedium | BitNeutral,
        /*ARG*/  BitBasic,
        /*PHE*/  BitAromatic | BitBuried | BitCyclic | BitHydrophobic |
                 BitNeutral,
        /*GLN*/  BitNeutral,
        /*TYR*/  BitAromatic | BitCyclic | BitNeutral,
        /*HIS*/  BitAromatic | BitBasic | BitCyclic | BitNeutral,
        /*CYS*/  BitBuried | BitMedium | BitNeutral,
        /*MET*/  BitBuried | BitHydrophobic | BitNeutral,
        /*TRP*/  BitAromatic | BitBuried | BitCyclic | BitHydrophobic |
                 BitNeutral,

        /*ASX*/  BitMedium | BitNeutral,
        /*GLX*/  BitNeutral,
        /*PCA*/  BitCyclic | BitHydrophobic | BitMedium | BitNeutral,
        /*HYP*/  BitCyclic | BitMedium | BitNeutral
        };


static void FatalExprError(ptr)
    char *ptr;
{
    char buffer[80];

    sprintf(buffer,"Expression Error: %s!",ptr);
    RasMolFatalExit(buffer);
}


#ifdef FUNCPROTO
/* Function Prototypes */
static AtomSet __far *SetInsert( AtomSet __far*, Atom __far* );
static int IsWithinRadius( AtomSet __far*, Long );
static int IsSetMember( AtomSet __far* );
#endif


static AtomSet __far *SetInsert( ptr, item )
    AtomSet __far *ptr;  Atom __far *item;
{
    register AtomSet __far *temp;
    register int i;

    if( ptr && (ptr->countdata[ptr->count] = item;
        ptr->count++;
        return( ptr );
    }

    if( !FreeSet )
    {   temp = (AtomSet __far*)_fmalloc( SetPool*sizeof(AtomSet) );
        if( !temp ) FatalExprError("Memory allocation failed");
        for( i=1; inext = FreeSet;
             FreeSet = temp++;
        }
    } else
    {   temp = FreeSet;
        FreeSet = temp->next;
    }

    temp->data[0] = item;
    temp->next = ptr;
    temp->count = 1;
    return( temp );
}


static int IsWithinRadius( ptr, limit )
    AtomSet __far *ptr;
    Long limit;
{
    register Atom __far *aptr;
    register Long dx,dy,dz;
    register Long dist;
    register int i;

    while( ptr )
    {   for( i=0; icount; i++ )
        {    aptr = ptr->data[i];
             dx = QAtom->xorg-aptr->xorg; if( (dist=dx*dx)>limit ) continue;
             dy = QAtom->yorg-aptr->yorg; if( (dist+=dy*dy)>limit ) continue;
             dz = QAtom->zorg-aptr->zorg; if( (dist+=dz*dz)>limit ) continue;
             return( True );
        }
        ptr = ptr->next;
    }
    return( False );
}


static int IsSetMember( ptr )
    AtomSet __far *ptr;
{
    register int i;

    while( ptr )
    {   for( i=0; icount; i++ )
            if( ptr->data[i] == QAtom )
                return( True );
        ptr = ptr->next;
    }
    return( False );
}


void DeleteAtomSet( ptr )
    AtomSet __far *ptr;
{
    register AtomSet __far *temp;

    if( (temp = ptr) )
    {   while( temp->next )
            temp = temp->next;
        temp->next = FreeSet;
        FreeSet = ptr;
    }
}


Expr *AllocateNode()
{
    register Expr *ptr;
    register int i;

    if( !FreeExpr )
    {   ptr = (Expr*)malloc( ExprPool*sizeof(Expr) );
        if( !ptr ) FatalExprError("Memory allocation failed");
        for( i=1; irgt.ptr = FreeExpr;
            FreeExpr = ptr++;
        }
    } else
    {   ptr = FreeExpr;
        FreeExpr = ptr->rgt.ptr;
    }
    ptr->rgt.ptr = NULL;
    ptr->lft.ptr = NULL;
    return( ptr );
}


void DeAllocateExpr( expr )
    Expr *expr;
{
    if( !expr ) return;
    if( (expr == &FalseExpr) ||
        (expr == &TrueExpr) ) 
        return;

    if( expr->type!=OpWithin )
    {   if( !(expr->type&(OpLftProp|OpLftVal)) )
            DeAllocateExpr( expr->lft.ptr );
        if( !(expr->type&(OpRgtProp|OpRgtVal)) )
            DeAllocateExpr( expr->rgt.ptr );
    } else DeleteAtomSet( expr->rgt.set );
        
    expr->rgt.ptr = FreeExpr;
    FreeExpr = expr;
}


int GetElemNumber( aptr )
    Atom __far *aptr;
{
    register char *ptr;
    register char ch;

    ptr = ElemDesc[aptr->refno];
    ch = ptr[1];

    switch( *ptr )
    {   case(' '):  switch( ch )
                    {   case('B'):  return(  5 );
                        case('C'):  return(  6 );
                        case('D'):  return(  1 );
                        case('F'):  return(  9 );
                        case('H'):  return(  1 );
                        case('I'):  return( 53 );
                        case('K'):  return( 19 );
                        case('L'):  return(  1 );
                        case('N'):  return(  7 );
                        case('O'):  return(  8 );
                        case('P'):  return( 15 );
                        case('S'):  return( 16 );
                        case('U'):  return( 92 );
                        case('V'):  return( 23 );
                        case('W'):  return( 74 );
                        case('Y'):  return( 39 );
                    }
                    break;

        case('A'):  switch( ch )
                    {   case('C'):  return( 89 );
                        case('G'):  return( 47 );
                        case('L'):  return( 13 );
                        case('M'):  return( 95 );
                        case('R'):  return( 18 );
                        case('S'):  return( 33 );
                        case('T'):  return( 85 );
                        case('U'):  return( 79 );
                    }
                    break;

        case('B'):  switch( ch )
                    {   case('A'):  return( 56 );
                        case('E'):  return(  4 );
                        case('I'):  return( 83 );
                        case('K'):  return( 97 );
                        case('R'):  return( 35 );
                    }
                    break;

        case('C'):  switch( ch )
                    {   case('A'):  return( 20 );
                        case('D'):  return( 48 );
                        case('E'):  return( 58 );
                        case('F'):  return( 98 );
                        case('L'):  return( 17 );
                        case('M'):  return( 96 );
                        case('O'):  return( 27 );
                        case('R'):  return( 24 );
                        case('S'):  return( 55 );
                        case('U'):  return( 29 );
                    }
                    break;

        case('D'):  if( ch=='Y' )
                        return( 66 );
                    break;

        case('E'):  if( ch=='R' )
                    {   return( 68 );
                    } else if( ch=='S' )
                    {   return( 99 );
                    } else if( ch=='U' )
                        return( 63 );
                    break;

        case('F'):  if( ch=='E' )
                    {   return(  26 );
                    } else if( ch=='M' )
                    {   return( 100 );
                    } else if( ch=='R' )
                        return(  87 );
                    break;

        case('G'):  if( ch=='A' )
                    {   return( 31 );
                    } else if( ch=='D' )
                    {   return( 64 );
                    } else if( ch=='E' )
                        return( 32 );
                    break;

        case('H'):  if( ch=='E' )
                    {   return(  2 );
                    } else if( ch=='F' )
                    {   return( 72 );
                    } else if( ch=='G' )
                    {   return( 80 );
                    } else if( ch=='O' )
                        return( 67 );
                    break;

        case('I'):  if( ch=='N' )
                    {   return( 49 );
                    } else if( ch=='R' )
                        return( 77 );
                    break;

        case('K'):  if( ch=='R' )
                        return( 36 );
                    break;

        case('L'):  if( ch=='A' )
                    {   return(  57 );
                    } else if( ch=='I' )
                    {   return(   3 );
                    } else if( (ch=='R') || (ch=='W') )
                    {   return( 103 );
                    } else if( ch=='U' )
                        return(  71 );
                    break;

        case('M'):  if( ch=='D' )
                    {   return( 101 );
                    } else if( ch=='G' )
                    {   return(  12 );
                    } else if( ch=='N' )
                    {   return(  25 );
                    } else if( ch=='O' )
                        return(  42 );
                    break;

        case('N'):  switch( ch )
                    {   case('A'):  return(  11 );
                        case('B'):  return(  41 );
                        case('D'):  return(  60 );
                        case('E'):  return(  10 );
                        case('I'):  return(  28 );
                        case('O'):  return( 102 );
                        case('P'):  return(  93 );
                    }
                    break;

        case('O'):  if( ch=='S' )
                        return( 76 );
                    break;

        case('P'):  switch( ch )
                    {   case('A'):  return( 91 );
                        case('B'):  return( 82 );
                        case('D'):  return( 46 );
                        case('M'):  return( 61 );
                        case('O'):  return( 84 );
                        case('R'):  return( 59 );
                        case('T'):  return( 78 );
                        case('U'):  return( 94 );
                    }
                    break;

        case('R'):  switch( ch )
                    {   case('A'):  return( 88 );
                        case('B'):  return( 37 );
                        case('E'):  return( 75 );
                        case('H'):  return( 45 );
                        case('N'):  return( 86 );
                        case('U'):  return( 44 );
                    }
                    break;
                    break;

        case('S'):  switch( ch )
                    {   case('B'):  return( 51 );
                        case('C'):  return( 21 );
                        case('E'):  return( 34 );
                        case('I'):  return( 14 );
                        case('M'):  return( 62 );
                        case('N'):  return( 50 );
                        case('R'):  return( 38 );
                    }
                    break;

        case('T'):  switch( ch )
                    {   case('A'):  return( 73 );
                        case('B'):  return( 65 );
                        case('C'):  return( 43 );
                        case('E'):  return( 52 );
                        case('H'):  return( 90 );
                        case('I'):  return( 22 );
                        case('L'):  return( 81 );
                        case('M'):  return( 69 );
                    }
                    break;

        case('X'):  if( ch=='E' )
                        return( 54 );
                    break;

        case('Y'):  if( ch=='B' )
                        return( 70 );
                    break;

        case('Z'):  if( ch=='N' )
                    {   return( 30 );
                    } else if( ch=='R' )
                        return( 40 );
                    break;
    }

    if( (*ptr>='0') && (*ptr<='9') )
        if( (ch=='H') || (ch=='D') )
            return( 1 ); /* Hydrogen */

    return( 0 );
}


int ElemVDWRadius( elem )
    int elem;
{
    if( !HasHydrogen )
        switch( elem )
        {   case(  6 ):  return( VDWCarbon );
            case(  7 ):  return( VDWNitrogen );
            case(  8 ):  return( VDWOxygen );    
            case( 16 ):  return( VDWSulphur );
        }
    return( Element[elem].vdwrad );
}


static int EvaluateProperty( prop )
    int prop;
{
    switch( prop )
    {   case( PropIdent ):    return( QAtom->serno );
        case( PropXCord ):    return( (int)QAtom->xorg );
        case( PropYCord ):    return( (int)QAtom->yorg );
        case( PropZCord ):    return( (int)QAtom->zorg );
        case( PropTemp ):     return( QAtom->temp );
        case( PropName ):     return( QAtom->refno );
        case( PropResId ):    return( QGroup->serno );
        case( PropResName ):  return( QGroup->refno );
        case( PropChain ):    return( QChain->ident );
        case( PropSelect ):   return( QAtom->flag&SelectFlag );
        case( PropElemNo ):   return( GetElemNumber(QAtom) );
        case( PropRad ):      if( QAtom->flag&SphereFlag )
                              {   return( QAtom->radius );
                              } else return( 0 );

        
        /* Predicates stored in flags */
        case( PredBonded ):       return( !(QAtom->flag&NonBondFlag) );
        case( PredHydrogen ):     return( QAtom->flag&HydrogenFlag );
        case( PredHetero ):       return( QAtom->flag&HeteroFlag );
        case( PredCystine ):      return( QGroup->flag&CystineFlag );
        case( PredHelix ):        return( QGroup->struc&HelixFlag );
        case( PredSheet ):        return( QGroup->struc&SheetFlag );
        case( PredTurn ):         return( QGroup->struc&TurnFlag );

        /* Residue type predicates */
        case( PredDNA ):
        case( PredRNA ):
        case( PredNucleic ):      return( IsNucleo(QGroup->refno) );
        case( PredProtein ):      return( IsProtein(QGroup->refno) );
        case( PredAmino ):        return( IsAmino(QGroup->refno) );
        case( PredWater ):        return( IsWater(QGroup->refno) );
        case( PredSolvent ):      return( IsSolvent(QGroup->refno) );
        case( PredIon ):          return( IsIon(QGroup->refno) );

        /* General Predicates */
        case( PredAlpha ):        return( IsAmino(QGroup->refno) &&
                                          IsAlphaCarbon(QAtom->refno) );
        case( PredMainChain ):    return( (IsAmino(QGroup->refno) && 
                                           IsAminoBackbone(QAtom->refno)) ||
                                          (IsNucleo(QGroup->refno) &&
                                           IsNucleicBackbone(QAtom->refno)) );
        case( PredSidechain ):    return( IsAmino(QGroup->refno) &&
                                          !IsAminoBackbone(QAtom->refno) );
        case( PredLigand ):       return( (QAtom->flag&HeteroFlag) &&
                                          !IsSolvent(QGroup->refno) );

        /* Nucleic Acid Classifications */
        case( PredAT ):           return( IsAdenine(QGroup->refno) ||
                                          IsThymine(QGroup->refno) );
        case( PredCG ):           return( IsCytosine(QGroup->refno) ||
                                          IsGuanine(QGroup->refno) );
        case( PredPyrimidine ):   return( IsPyrimidine(QGroup->refno) );
        case( PredPurine ):       return( IsPurine(QGroup->refno) );


        /* Amino Acid Classifications */
        case( PredAcidic ):       return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitAcidic );

        case( PredAcyclic ):      return( IsAmino(QGroup->refno) &&
                                  !(AminoProp[QGroup->refno]&BitCyclic) );

        case( PredAliphatic ):    return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitAliphatic );

        case( PredAromatic ):     return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitAromatic );

        case( PredBasic ):        return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitBasic );

        case( PredBuried ):       return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitBuried );

        case( PredCharged ):      return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitCharged );

        case( PredCyclic ):       return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitCyclic );

        case( PredHydrophobic ):  return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitHydrophobic );
                 
        case( PredLarge ):        return( IsAmino(QGroup->refno) &&
                                  !(AminoProp[QGroup->refno]&BitNotLarge) );

        case( PredMedium ):       return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitMedium );

        case( PredNeutral ):      return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitNeutral );

        case( PredPolar ):        return( IsAmino(QGroup->refno) &&
                                  !(AminoProp[QGroup->refno]&BitHydrophobic) );

        case( PredSmall ):        return( IsAmino(QGroup->refno) &&
                                  AminoProp[QGroup->refno]&BitSmall );

        case( PredSurface ):      return( IsAmino(QGroup->refno) &&
                                  !(AminoProp[QGroup->refno]&BitBuried) );

    }
    return( True );
}


int EvaluateExpr( expr )
    Expr *expr;
{
    register int lft, rgt;

    if( !expr )
        return( True );

    if( expr->type==OpWithin )
    {   if( expr->lft.limit )
        {   return( IsWithinRadius(expr->rgt.set,expr->lft.limit) );
        } else return( IsSetMember(expr->rgt.set) );
    } else if( expr->type==OpMember )
        return( IsSetMember(expr->rgt.set) );

    if( expr->type & OpLftVal )
    {   lft = expr->lft.val;
    } else if( expr->type & OpLftProp )
    {   lft = EvaluateProperty( expr->lft.val );
    } else lft = EvaluateExpr( expr->lft.ptr );

    if( OpCode(expr)==OpConst ) return( lft );
    if( (OpCode(expr)==OpAnd) && !lft ) return( False );
    if( (OpCode(expr)==OpOr) && lft ) return( True );
    if( OpCode(expr)==OpNot ) return( !lft );

    if( expr->type & OpRgtVal )
    {   rgt = expr->rgt.val;
    } else if( expr->type & OpRgtProp )
    {   rgt = EvaluateProperty( expr->rgt.val );
    } else rgt = EvaluateExpr( expr->rgt.ptr );

    switch( OpCode(expr) )
    {   case(OpOr):
        case(OpAnd):     return( rgt );
        case(OpLess):    return( lftrgt );
        case(OpEqual):   return( lft==rgt );
        case(OpNotEq):   return( lft!=rgt );
        case(OpLessEq):  return( lft<=rgt );
        case(OpMoreEq):  return( lft>=rgt );
    }
    return( True );
}


AtomSet __far *BuildAtomSet( expr )
    Expr *expr;
{
    register AtomSet __far *ptr;

    ptr = (AtomSet __far*)0;

    if( Database )
        for( QChain=Database->clist; QChain; QChain=QChain->cnext )
            for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext )
                for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext )
                    if( EvaluateExpr(expr) )
                        ptr = SetInsert( ptr, QAtom );

    return( ptr );
}



int DefineSetExpr( ident, expr )
    char *ident;  Expr *expr;
{
    register SymEntry __far * __far *prev;
    register SymEntry __far *ptr;
    register AtomSet __far *set;
    register int result;

    result = True;
    prev = &SymbolTable;
    while( (ptr = *prev) )
    {   result = strcmp(ident,ptr->ident);
        if( !result ) break;  /* Entry Exists! */
        prev = (result<0)? &(ptr->lft) : &(ptr->rgt);
    }

    if( result )
    {   if( FreeEntry )
        {   ptr = FreeEntry;
            FreeEntry = ptr->rgt;
        } else /* Allocate SymEntry! */
            if( !(ptr = (SymEntry __far*)_fmalloc(sizeof(SymEntry))) )
                return( False );

        *prev = ptr;
        ptr->ident = ident;
        ptr->defn = (void __far*)0;
        ptr->lft = (void __far*)0;
        ptr->rgt = (void __far*)0;
    } else free(ident);

    if( expr )
    {   set = BuildAtomSet(expr);
        if( ptr->defn )
            DeleteAtomSet(ptr->defn);
        DeAllocateExpr(expr);
        ptr->defn = set;
    } else ptr->defn = (void __far*)0;
    return( True );
}


Expr *LookUpSetExpr( ident )
    char *ident;
{
    register SymEntry __far *ptr;
    register Expr *expr;
    register int result;

    result = True;
    ptr = SymbolTable;
    while( ptr )
    {   result = strcmp(ident,ptr->ident);
        if( !result ) break;  /* Entry Exists! */
        ptr = (result<0)? ptr->lft : ptr->rgt;
    }

    if( !result )
    {   expr = AllocateNode();
        expr->type = OpMember;
        expr->rgt.set = ptr->defn;
    } else expr = (Expr*)0;
    return( expr );
}


static int ElemCompare( ident, elem )
    char *ident, *elem;
{
    while( *elem )
        if( *elem++ != *ident++ )
            return( False );

    /* Handle Plurals */
    if( (ident[0]=='S') && !ident[1] )
        return( (elem[-1]!='S') && (elem[-1]!='Y') );
    return( !*ident );
}


Expr *LookUpElement( ident )
    char *ident;
{
    register Expr *expr;
    register int elem;

    for( elem=1; elemtype = OpEqual|OpLftProp|OpRgtVal;
        expr->lft.val = PropElemNo;
        expr->rgt.val = elem;
    } else expr = (Expr*)0;
    return( expr );
}



static int MatchWildName( src, dst, size, len )
    char *src, *dst; int size, len;
{
    register int i, left;

    left = size;
    while( *dst==' ' )
    {   dst++; left--;
    }

    for( i=0; itype = OpEqual | OpLftProp | OpRgtVal;
                tmp1->lft.val = PropResName;
                tmp1->rgt.val = j;

                tmp2 = AllocateNode();
                tmp2->type = OpOr;
                tmp2->lft.ptr = tmp1;
                tmp2->rgt.ptr = wild;
                wild = tmp2;
            }
        QueryExpr = wild;
    } else ch = *ptr++;

    if( ch != '*' )
    {   if( ch == '-' )
        {   ch = *ptr++;
            neg = True;
        } else neg = False;

        if( isdigit(ch) )
        {   i = ch-'0';
            while( isdigit(*ptr) )
                i = 10*i + (*ptr++)-'0';

            tmp1 = AllocateNode();
            tmp1->type = OpEqual | OpLftProp | OpRgtVal;
            tmp1->rgt.val = neg? -i : i;
            tmp1->lft.val = PropResId;
            if( QueryExpr != &TrueExpr )
            {   tmp2 = AllocateNode();
                tmp2->type = OpAnd;
                tmp2->rgt.ptr = QueryExpr;
                tmp2->lft.ptr = tmp1;
                QueryExpr = tmp2;
            } else QueryExpr = tmp1;
            ch = *ptr++;
        } else if( neg )
            return( False );
    } else ch = *ptr++;

    if( ch==':' )
        ch = *ptr++;

    if( isalnum(ch) )
    {   ch = ToUpper(ch);

        tmp1 = AllocateNode();
        tmp1->type = OpEqual | OpLftProp | OpRgtVal;
        tmp1->lft.val = PropChain;
        tmp1->rgt.val = ch;
        if( QueryExpr != &TrueExpr )
        {   tmp2 = AllocateNode();
            tmp2->type = OpAnd;
            tmp2->rgt.ptr = QueryExpr;
            tmp2->lft.ptr = tmp1;
            QueryExpr = tmp2;
        } else QueryExpr = tmp1;
        ch = *ptr++;
    } else if( (ch=='?') || (ch=='%') || (ch=='*') )
        ch = *ptr++;

    if( ch == '.' )
    {   ch = *ptr++;
        if( ch!='*' )
        {   for( i=0; i<4; i++ )
                if( isalnum(ch) || ch=='\'' || ch=='*' )
                {   NameBuf[i] = ToUpper(ch);
                    ch = *ptr++;
                } else if( (ch=='?') || (ch=='%') || (ch=='#') )
                {   NameBuf[i] = '?';
                    ch = *ptr++;
                } else break;
            if( !i ) return( False );


            wild = &FalseExpr;
            for( j=0; jtype = OpEqual | OpLftProp | OpRgtVal;
                    tmp1->lft.val = PropName;
                    tmp1->rgt.val = j;

                    tmp2 = AllocateNode();
                    tmp2->type = OpOr;
                    tmp2->lft.ptr = tmp1;
                    tmp2->rgt.ptr = wild;
                    wild = tmp2;
                }

            if( (QueryExpr == &TrueExpr) || (wild == &FalseExpr) )
            {   DeAllocateExpr(QueryExpr);
                QueryExpr=wild;
            } else
            {   tmp1 = AllocateNode();
                tmp1->type = OpAnd;
                tmp1->lft.ptr = QueryExpr;
                tmp1->rgt.ptr = wild;
                QueryExpr = tmp1;
            }
        } else ch = *ptr++;
    }
    *orig = --ptr;
    return( !ch || isspace(ch) || ispunct(ch) );
}


static char *FormatInteger( ptr, value )
    char *ptr; int value;
{
    auto char buffer[10];
    register char *tmp;

    if( value<0 )
    {   value = -value;
        *ptr++ = '-';
    }

    if( value>9 )
    {   tmp = buffer;
        while( value>9 )
        {   *tmp++ = (value%10) + '0';
            value /= 10;
        }

        *ptr++ = value + '0';
        do { tmp--; 
            *ptr++ = *tmp;
        } while( tmp != buffer );
    } else *ptr++ = value + '0';
    return( ptr );
}


void FormatLabel( chain, group, aptr, label, ptr )
    Chain __far *chain;
    Group __far *group;
    Atom __far *aptr;
    char *label, *ptr;
{
    register char ch;
    register int i,j;

    while( ch = *label++ )
       if( ch=='%' )
       {   ch = *label++;
           if( isupper(ch) )
             ch = tolower(ch);

           switch( ch )
           {   case('a'):  /* Atom Name */
                           i = aptr->refno;
                           for( j=0; j<4; j++ )
                               if( ElemDesc[i][j]!=' ' )
                                   *ptr++ = ElemDesc[i][j];
                           break;

               case('b'):  /* Temperature/B-factor */
               case('t'):  ptr = FormatInteger(ptr,aptr->temp);
                           break;

               case('c'):  /* Chain Identifier */
               case('s'):  *ptr++ = chain->ident;
                           break;

               case('e'):  /* Element Type */
                           i = GetElemNumber(aptr);
                           *ptr++ = Element[i].symbol[0];
                           if( Element[i].symbol[1]!=' ' )
                               *ptr++ = Element[i].symbol[1];
                           break;

               case('i'):  /* Atom Number */
                           ptr = FormatInteger(ptr,aptr->serno);
                           break;

               case('n'):  /* Residue Name   */
                           i = group->refno;
                           for( j=0; j<3; j++ )
                               if( Residue[i][j]!=' ' )
                                   *ptr++ = Residue[i][j];
                           break;

               case('r'):  /* Residue Number */
                           ptr = FormatInteger(ptr,group->serno);
                           break;

               case('%'):  *ptr++ = '%';
                           break;
           }
       } else if( (ch>=' ') && (ch<='~') )
           *ptr++ = ch;
    *ptr = '\0';
}


#ifdef FUNCPROTO
/* Function Prototypes */
static void DeleteSymEntry( SymEntry __far* );
#endif


static void DeleteSymEntry( ptr )
    SymEntry __far *ptr;
{
    if( ptr->lft )
        DeleteSymEntry( ptr->lft );
    if( ptr->rgt )
        DeleteSymEntry( ptr->rgt );

    if( ptr->defn )
        DeleteAtomSet( ptr->defn );
    free( ptr->ident );

    ptr->rgt = FreeEntry;
    FreeEntry = ptr;
}


void ResetSymbolTable()
{
    if( SymbolTable )
    {   DeleteSymEntry(SymbolTable);
        SymbolTable = (void __far*)0;
    }
}


void InitialiseAbstree()
{
    FalseExpr.type = OpConst | OpLftVal | OpRgtVal;
    FalseExpr.rgt.val = FalseExpr.lft.val = 0;

    TrueExpr.type = OpConst | OpLftVal | OpRgtVal;
    TrueExpr.rgt.val = TrueExpr.lft.val = 1;

    QChain = (void __far*)0;
    QGroup = (void __far*)0;
    QAtom = (void __far*)0;

    SymbolTable = (void __far*)0;

    FreeEntry = (void __far*)0;
    FreeSet = (void __far*)0;
    FreeExpr = NULL;
}
Modified: Mon Oct 24 16:00:00 1994 GMT
Page accessed 1276 times since Sat Apr 17 21:38:29 1999 GMT