Category : C Source Code
Archive   : GHLNKLST.ZIP
Filename : LLBASE.C

 
Output of file : LLBASE.C contained in archive : GHLNKLST.ZIP
/*
* L I N K E D L I S T T O O L K I T
*
* Copyright (C) 1990 by Garyl Lee Hester
*
* llbase.c
*
* Routines for Internal Linked list management
*/
#include
#ifdef __TURBOC__
#include
#include
#else
#include
#include
#endif
#include "ll.h"

/*
* ll_appatom - appends atom to end of list
*/
void ll_appatom( PATOM pAtom, PLLENDS pEnds )
{
PLLBIND pBind;

if( pAtom && pEnds )
{
pBind = MAKEPBIND( pAtom );
if( pEnds->pHead == NULL )
pEnds->pHead = (PGEN)pBind;
if( pEnds->pTail )
((PLLBIND)(pEnds->pTail))->pNext = pBind;
pBind->pPrev = (PLLBIND)(pEnds->pTail);
pBind->pNext = NULL;
pEnds->pTail = (PGEN)pBind;
}
}

/*
* ll_mkblock - create a new atom block
*/
void ll_mkblock( PLLCB pLL )
{
unsigned usBlockSize;
unsigned usIndex;
unsigned usTrueAtomSize;
PLLBC pBlock;
PLLBIND pBind;

/*
* The size of an atom is the size of the user data PLUS the
* size of the bindary information, or
*
* sizeof( LLBIND ) + pLL->usAtomSize
*
* The size of a block is the number of atoms per block times
* the true size of an atom, plus the size of the block header
*/
usTrueAtomSize = sizeof( LLBIND ) + pLL->usAtomSize;
usBlockSize = ( usTrueAtomSize * pLL->usAtomCnt )
+ sizeof( LLBC );

if( ( pBlock = (PLLBC)malloc( usBlockSize ) ) != NULL )
{
memset( (char *)pBlock, 0x00, usBlockSize );

/*
* add the new block to the block chain
*/
ll_appatom( MAKEPATOM( pBlock ), &pLL->Block );

/*
* now it gets tricky...
*
* What we have is an unformatted block of memory of the
* proper size to hold a block bindary (LLBC) plus
* pLL->usAtomCnt atoms. Since each of the atoms are
* all unused, they will be part of the free chain. We
* can save a substantial amount of time by linking all
* of the atoms together here, and then fitting the
* entire block into the free atom list.
*
* To do this, we first calculate the address of the first
* atom bindary, which will be the first byte following
* the block header, or:
*/
pBind = (PLLBIND)( (char *)pBlock + sizeof( LLBC ) );

/*
* Now that we have the address of the first bindary, we'll
* go ahead and add it to the end of the Free list:
*/
ll_fappend( pLL, MAKEPATOM( pBind ) );

/*
* Now we "sew" the subsequent links together by:
* 1) Calculating the address of the next atom bindary;
* 2) Setting the pNext ptr of the current bindary to
* that address;
* 3) Setting the pPrev ptr of the next bindary to the
* current bindary; and then
* 4) Setting the current bindary to the next bindary
*/
for( usIndex = 1; usIndex < pLL->usAtomCnt; usIndex++ )
{
pBind->pNext = (PLLBIND)( (char *)pBind + usTrueAtomSize );
pBind->pNext->pPrev = pBind;
pBind = pBind->pNext;
}

/*
* pBind now references the last atom in the list. Since
* it is, in fact, the end of the free list, set its pNext
* member to NULL to terminate the list. Then, set the
* Free list tail pointer to the last bindary.
*/
pBind->pNext = NULL;
pLL->Free.pTail = (PGEN)pBind;
}
}

/*
* ll_unbatom - unbind pAtom from list - does not relocate atom
*/
void ll_unbatom( PATOM pAtom, PLLENDS pEnds )
{
PLLBIND pBind;

if( pAtom )
{
pBind = MAKEPBIND( pAtom );
if( pBind->pNext )
pBind->pNext->pPrev = pBind->pPrev;
if( pBind->pPrev )
pBind->pPrev->pNext = pBind->pNext;

if( pEnds->pHead == (PGEN)pBind )
pEnds->pHead = (PGEN)( pBind->pNext );
if( pEnds->pTail == (PGEN)pBind )
pEnds->pTail = (PGEN)( pBind->pPrev );
}
}

/*
* ll_inblock - Answer relative block number that contains pAtom,
* Answer -1 if no block is found;
*/
PLLBC ll_inblock( PLLCB pLL, PATOM pAtom )
{
PLLBC pBlock;
unsigned usBlockSize;

usBlockSize =
( pLL->usAtomCnt * ( sizeof( LLBIND ) + pLL->usAtomSize ) )
+ sizeof( LLBC );

for( pBlock = pLL->Block.pHead;
pBlock;
pBlock = pBlock->pNext
)
if( pAtom >= (PATOM)pBlock
&& pAtom <= (PATOM)((char *)pBlock + usBlockSize )
)
break;

/*
* if the block was found, and the block pointer is desired
* (inferred by ppBlock != NULL), then set ppBlock to reference
* the block containing pAtom...
*/
return( pBlock );
}

/*
* ll_frstatom - Answer first atom in list
*/
PATOM ll_frstatom( PLLST pList, PLLBIND pBindHead )
{
return( (pList && pBindHead) ? MAKEPATOM( pBindHead )
: NULL
);
}

/*
* ll_lastatom - Answer last atom in list
*/
PATOM ll_lastatom( PLLST pList, PLLBIND pBindTail )
{
return( (pList && pBindTail) ? MAKEPATOM( pBindTail )
: NULL
);
}

/*
* ll_getbind - get link binding in indicated direction
*/
PATOM ll_getbind( unsigned usDirection, PATOM pAtom )
{
PLLBIND pBind;

if( pAtom )
{
pBind = MAKEPBIND( pAtom );
pBind = ( usDirection == _LL_NEXT )
? pBind->pNext
: pBind->pPrev;
pAtom = ( pBind ) ? MAKEPATOM( pBind ) : NULL;
}
return( pAtom );
}

/*
* ll_rmblock - remove block
*/
void ll_rmblock( PLLCB pLL, PLLBC pBlock )
{
unsigned usBlockSize;
unsigned usIndex;
unsigned usTrueAtomSize;
PLLBIND pBind;

if( pLL && pBlock )
{
/*
* we could be destroying a block for two reasons:
*
* 1) the list is being destroyed, or
* 2) all of the atoms in this block are free
*
* If the list is being destroyed, we don't much care about
* the integrity of it, so just free() the block. Else, we
* need to dealloc all of the free atoms in the block before
* we snuff it.
*/
if( !pBlock->usUsageCnt )
{
/*
* What we do here is similar to what is being done in
* ll_mkblock(). Refer to that bit of code for
* an explanation of how this works.
*/
usTrueAtomSize = sizeof( LLBIND ) + pLL->usAtomSize;
usBlockSize = ( usTrueAtomSize * pLL->usAtomCnt )
+ sizeof( LLBC );

pBind = (PLLBIND)( (char *)pBlock + sizeof( LLBC ) );
ll_funbind( pLL, MAKEPATOM( pBind ) );

for( usIndex = 1; usIndex < pLL->usAtomCnt; usIndex++ )
{
pBind = (PLLBIND)( (char *)pBind + usTrueAtomSize );
ll_funbind( pLL, MAKEPATOM( pBind ) );
}
}
ll_unbatom( MAKEPATOM( pBlock ), &pLL->Block );
free( pBlock );
}
}





  3 Responses to “Category : C Source Code
Archive   : GHLNKLST.ZIP
Filename : LLBASE.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/