Category : C Source Code
Archive   : GCOOPE10.ZIP
Filename : LISTMGR.C
dynamic list manager for GCOOPE version 1.0
by Brian Lee Price
Released as Public Domain July, 1994.
these routines are the heart of the GCOOPE version 1.0 kernel --
they provide partial memory management functions for both
ordered and unordered lists as well as maintaining the lists
themselves.
Programmer's Note: yes I use goto where it reduces code size
and doesn't obscure program flow. If you are prejudiced
against the goto statement, feel free to rewrite your copy
of the source code without them... just don't ask me to help
debug it! 🙂
These routines are for internal kernel use only.
*/
/*
if you haven't examined pcstruct.h yet, do so now. I recommend
printing it out and keeping it in hand while examining the
GCOOPE kernel code. Things will get confusing enough without
complicating matters any.
*/
#include
#include "gcstruct.h"
/*
This routine searches the given block of length blockLen at
address blockAdr for all nulls (all 0s). If it is not, this
function returns FALSE.
*/
static boolean nullSrch(char * blockAdr, int blockLen)
{
do
{
if(*blockAdr) return FALSE;
blockAdr++;
blockLen--;
} while(blockLen > 0);
return TRUE;
}
/*
FOR KERNEL USE ONLY!
usage:
newSlotIndex = addItem(&ofa_dynList, elementSize_ofthelist);
this routine adds an item to a dynList type list structure,
if the list does not exist it will create it.
when calling this routine, listAdr is a pointer to a dynList
structure type, elemSize is the size of the slots (elements),
and the index of the new slot is returned normally, a negative
value is returned on error.
*/
#define LISTADR ((dynList *) listAdr)
int addItem(void *listAdr, int elemSize)
{
/* setup x to return a negative value on any error */
int x=-1;
unsigned oldSize;
void * newAdr;
char * ptrA;
if(listAdr==NULL || elemSize<=0) goto end;
if(LISTADR->listPtr==NULL)
{
LISTADR->firstFree=1;
LISTADR->elemSize=elemSize;
LISTADR->maxElems=MIN_LIST_ADD;
if(NULL==(LISTADR->listPtr=s_calloc(MIN_LIST_ADD,elemSize)))
goto end;
x = 0;
goto end;
}
if(elemSize!=LISTADR->elemSize) goto end;
retry:
if(LISTADR->firstFree>=LISTADR->maxElems)
{
if ((LISTADR->maxElems+MIN_LIST_ADD) >=
((MAX_BLOCK_SIZE-(elemSize-1)) / elemSize))
{
outOfElems();
goto retry;
}
oldSize=LISTADR->maxElems;
LISTADR->maxElems+=MIN_LIST_ADD;
if(NULL==(newAdr=s_calloc(LISTADR->maxElems,elemSize))) goto end;
x=oldSize;
memcpy(newAdr,LISTADR->listPtr,x*elemSize);
s_free(LISTADR->listPtr);
LISTADR->listPtr=newAdr;
LISTADR->firstFree=x;
goto end;
}
x=LISTADR->firstFree;
ptrA=LISTADR->listPtr;
ptrA+= elemSize * LISTADR->firstFree;
do {
ptrA+=elemSize;
} while (++LISTADR->firstFree < LISTADR->maxElems &&
! nullSrch(ptrA, elemSize));
end:
return x;
}
/*
FOR KERNEL USE ONLY!
usage:
nextFree=rmvItem(&ofa_dynList, indexToElementToFree);
This routine frees up a previously used slot, note that no effort
is made to reduce the list memory allocation, for that function see
compactList below.
When calling this routine, listAdr is a pointer to a dynList
structure type, elemNdx is the index of the element slot to be freed,
and the routine returns the first free slot index or a negative value
on any error.
*/
int rmvItem(void *listAdr, int elemNdx)
{
char * ptrA;
if(!listAdr || !LISTADR->listPtr
|| (elemNdx>=LISTADR->maxElems) || (elemNdx<0)) return -1;
if(elemNdx < LISTADR->firstFree)
LISTADR->firstFree = elemNdx;
ptrA= LISTADR->listPtr;
ptrA+= elemNdx * LISTADR->elemSize;
memset(ptrA,0,LISTADR->elemSize);
return LISTADR->firstFree;
}
/*
The following routine compacts a list to a multiple of
MIN_LIST_ADD in size. If sorted is FALSE, the routine will
find the beginning of the last contiguous free slot area in
the list. If sorted is TRUE, the routine will fill in empty
slots with the contents of the next higher slot starting at
firstFree and moving through the list until the end. In this
second case, the result is a contiguous list, otherwise it
will just be a minimum length list preserving current index
values (leaving internal free slots).
*/
stat compactList(void *listAdr, boolean sorted)
{
char * ptrA;
int last;
if(!listAdr || !LISTADR->listPtr) return FUNCFAIL;
ptrA=LISTADR->listPtr;
if(!sorted) /* this may be indexed so we can't move elements */
{
last=LISTADR->maxElems;
ptrA+= LISTADR->elemSize * (--last);
for(;last>= LISTADR->firstFree; last--, ptrA-=LISTADR->elemSize)
{
if(!nullSrch(ptrA, LISTADR->elemSize)) break;
}
last=(last
last++;
}
else /* this isn't indexed so move slots downward until contiguous */
{
char * ptrB;
int current;
ptrA+=LISTADR->firstFree * LISTADR->elemSize;
ptrB=ptrA;
current=LISTADR->firstFree;
while(++current < LISTADR->maxElems)
{
ptrB+=LISTADR->elemSize;
if(nullSrch(ptrB,LISTADR->elemSize)) continue;
memcpy(ptrA, ptrB, LISTADR->elemSize);
memset(ptrB,0,LISTADR->elemSize);
do {
ptrA+=LISTADR->elemSize;
LISTADR->firstFree++;
} while(!nullSrch(ptrA,LISTADR->elemSize));
}
last=(LISTADR->firstFree
LISTADR->maxElems;
}
if(last % MIN_LIST_ADD) last= ((last/MIN_LIST_ADD)+1) * MIN_LIST_ADD;
if(last
{
LISTADR->maxElems=last;
LISTADR->listPtr=s_realloc(LISTADR->listPtr, last * LISTADR->elemSize);
}
return FUNCOKAY;
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
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/