home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddjcspec.arc
/
STARR.LST
< prev
next >
Wrap
File List
|
1989-11-21
|
21KB
|
885 lines
_C LIST MANAGER_
by Robert Starr
[LISTING ONE]
/* makelist- list management package
RF Starr
2639 Valley Field Dr.
SugarLand, TX 77479
*/
#include <stdio.h>
#include <varargs.h>
#ifdef MSDOS
#include <stdlib.h>
#include <malloc.h>
#else
#define void char
extern char *malloc();
#endif
/*#define DEBUG*/
#ifdef DEBUG
#define Debug(x) x
#else
#define Debug(x)
#endif
typedef struct data DATA;
typedef struct list LIST;
typedef struct prop PROP;
struct data {
void *data; /* space for list->nentries instances of data */
DATA *next; /* next list->nentries collection of data */
};
struct prop {
void *dataptr; /* to what data item this property associates */
void *propval; /* property value to associate with the data */
void *propsym; /* optional symbol (usually char *) to associate */
PROP *next;
};
struct list {
int entrysize; /* size of each data entry in bytes */
int nentries; /* # entries to grab per malloc call */
int empty_slots; /* empty slots left in current data block */
int nitems; /* total items saved in this list */
int ecount; /* where we are when reading back list */
int fblock;
DATA *fdata;
PROP *prop; /* optional property list for this list */
DATA *data; /* linked list for the actual data of this list */
DATA *hidata; /* highest allocated data block (for efficiency) */
};
/* Internal malloc routine */
/*#define MEMCHK*/
#ifdef MEMCHK
static FILE *memfp = NULL;
#endif
static void *
imalloc(size)
int size; {
void *ptr = malloc(size);
#ifdef MEMCHK
if (!memfp) memfp = fopen("meminfo","w");
#endif
if (!ptr) {
fprintf(stderr,"malloc error: no free memory left.\n");
fflush(stderr);
}
#ifdef MEMCHK
fprintf(memfp,"%x malloc\n",ptr);
fflush(memfp);
#endif
return ptr;
}
static void *
ifree(addr)
void *addr; {
free(addr);
#ifdef MEMCHK
fprintf(memfp,"%x free\n",addr);
fflush(memfp);
#endif
}
/* Build, initialize, and return an empty list */
void *
makelist(esize,nentries)
int esize,nentries; {
LIST *list = imalloc(sizeof(LIST)+sizeof(DATA)+esize*nentries);
void *dp = imalloc(sizeof(DATA)+esize*nentries);
if (!list || !dp) return NULL;
list->data = (DATA *)dp;
list->data->data = (char *)dp + sizeof(DATA);
list->entrysize = esize;
list->nentries = nentries;
list->empty_slots = nentries;
list->nitems = 0;
list->ecount = 0;
list->fblock = 0;
list->fdata = NULL;
list->prop = (PROP *)NULL;
list->hidata = list->data;
list->data->next = NULL;
return (void *)list;
}
/* Put items on property list for this data item. Propsym is the
property symbol, and val is a pointer to a _static_ are where the
data for this property resides.
*/
putproplist(list,dataptr,propsym,val)
LIST *list;
void *dataptr,*val;
char *propsym; {
PROP *newprop = (PROP *)imalloc(sizeof(PROP));
PROP *topprop = list->prop;
if (!list) return NULL;
if (!newprop) return;
newprop->dataptr = dataptr;
newprop->propsym = propsym;
newprop->propval = val;
newprop->next = topprop;
list->prop = newprop;
}
/* Read an item off of the property list for a particular data
item. NULL returned if there is none.
*/
void *
getproplist(list,dataptr,propsym)
LIST *list;
void *dataptr,*propsym; {
PROP *p;
void *propval = NULL;
if (!list) return NULL;
p = list->prop;
while (p) {
int fsym = !strcmp(p->propsym,propsym);
if ((!dataptr && fsym) || (p->dataptr == dataptr && fsym)) {
propval = p->propval;
break;
}
p = p->next;
}
return propval;
}
/* Find data item associated with a property name */
void *
findprop(list,propsym)
LIST *list;
char *propsym; {
PROP *p;
if (!list) return NULL;
p = list->prop;
while (p) {
if (!strcmp(p->propsym,propsym)) return p->dataptr;
p = p->next;
}
return NULL;
}
/* Append data to the specified list */
static void
whereis(list,ndx,walk,put)
LIST *list;
int *walk,*put; {
*walk = ndx / list->nentries;
*put = ndx % list->nentries;
}
/* Remove last entry on the specified list... adjust struct accordingly */
void *
poplist(list)
LIST *list; {
DATA *org;
void *dp = NULL;
unsigned char *data;
int put;
if (!list) return NULL;
if (!list->nitems) return dp;
org = list->data;
list->empty_slots++;
list->nitems--;
if (list->empty_slots == list->nentries) {
while (org->next) org = org->next;
put = list->nitems % list->nentries;
data = (unsigned char *)org->data;
dp = (void *)(data+(list->entrysize*put));
if (org->next) ifree(org->next), org->next = NULL;
list->hidata = org;
}
return dp;
}
/* calculate data pointer for the ndx entry */
static void *
calcdp(list,ndx)
LIST *list;
int ndx; {
DATA *pdata;
unsigned char *dp;
int size = (list) ? list->entrysize :0;
int max = (list) ? list->nitems : 0;
int walk,put;
if (!list || ndx >= max) return (void *)NULL;
whereis(list,ndx,&walk,&put);
pdata = list->data;
while (walk--) pdata = pdata->next;
dp = (unsigned char *)pdata->data;
return (char *)(dp+(size*put));
}
/* Return pointer to data which is last on the list */
void *
toplist(list)
LIST *list; {
void *dp = NULL;
void *fetchlist();
unsigned char *data;
int put;
if (!list || !list->nitems) return NULL;
return calcdp(list,list->nitems-1);
}
/* append a data item onto specified list */
void *
appendlist(list,data)
LIST *list;
void *data; {
DATA *pdata;
void *where;
unsigned char *dp;
int walk,put,size;
if (!list) return NULL;
size = list->entrysize;
whereis(list,list->nitems,&walk,&put);
pdata = list->hidata;
if (!list->empty_slots) {
void *mem = imalloc(sizeof(DATA)+size*list->nentries);
if (!mem) return NULL;
list->hidata = pdata = pdata->next = (DATA *)mem;
pdata->data = (void *)((char *)mem+sizeof(DATA));
pdata->next = NULL;
list->empty_slots = list->nentries;
}
dp = (unsigned char *)pdata->data;
where = (char *)(dp+(put*size));
memcpy(where,data,size);
list->empty_slots--;
list->nitems++;
return where;
}
/* return index of NEXT list entry */
listindex(list)
LIST *list; {
return list->nitems;
}
/* append a data item onto specified list with property value information */
void *
pappendlist(list,data,propsym,val)
LIST *list;
void *data,*val;
char *propsym; {
void *dataptr = appendlist(list,data);
if (dataptr) putproplist(list,dataptr,propsym,val);
return dataptr;
}
/* Just like appendlist... new name for compatibility with poplist */
void *
pushlist(list,data)
LIST *list;
void *data; {
if (!list) return NULL;
return appendlist(list,data);
}
/* Fetch a specific data item off of list... ndx is 0-based */
void *
fetchlist(list,ndx)
LIST *list;
int ndx; {
DATA *pdata;
unsigned char *dp;
int size = list->entrysize;
int max = list->nitems;
int walk,put;
if (!list) return NULL;
if (ndx >= max) return (void *)NULL;
whereis(list,ndx,&walk,&put);
if (walk == list->fblock)
list->fdata = pdata = (list->fdata) ? list->fdata : list->data;
else {
pdata = list->data;
list->fblock = walk;
while (walk--)
pdata = pdata->next;
list->fdata = pdata;
}
dp = (unsigned char *)pdata->data;
Debug(printf("fetchlist: getting data from %x\n",dp+(size*put)));
return (char *)(dp+(size*put));
}
/* reset pointer used by walklist */
rewindlist(list)
LIST *list; {
if (list) list->ecount = 0;
}
/* walk down the list, returning each data item 'till there ain't no more */
void *
walklist(list)
LIST *list; {
DATA *pdata;
unsigned char *dp;
int size = list->entrysize;
int max = list->nitems;
int index = list->ecount;
int walk,put;
if (!list) return NULL;
dp = (unsigned char *)fetchlist(list,index);
if (!dp)
list->ecount = 0;
else
list->ecount++;
return (list->ecount) ? (void *)dp : (void *)NULL;
}
/* malloc size bytes, and add address of malloced space to the list */
void *
malloclist(list,size)
LIST *list;
int size; {
void *dp;
if (!list) return NULL;
dp = imalloc(size);
if (dp) appendlist(list,&dp);
return dp;
}
/* Free up all malloced data associated with the specified list */
freelist(list)
LIST *list; {
fl(list,0);
}
/* garbage collect list... assume all data in list is malloced ptrs */
gclist(list)
LIST *list; {
fl(list,1);
}
/* Free the list up. If freedp != 0, free each data pointer as well */
static
fl(list,freedp)
LIST *list; {
DATA *pdata,*ppd;
PROP *p = list->prop;
if (!list) return;
pdata = list->data;
if (freedp) {
void *dp;
rewindlist(list);
while (dp=walklist(list))
ifree(*(char **)dp);
}
/* free all malloced data */
while (pdata) {
DATA *next = pdata->next;
ifree(pdata);
pdata = next;
}
/* free all malloced property info */
while (p) {
PROP *n = p->next;
ifree(p);
p = n;
}
ifree(list);
}
/* given a list of functions, invoke the function with the specified
property tag with the arguments supplied.
*/
/*funclist(list,prop,args) (actual calling argument list)*/
int
funclist(va_alist)
va_dcl {
void *list;
void *prop;
void *vp;
int (*func)();
va_list argmark;
va_start(argmark);
list = va_arg(argmark,void *);
prop = va_arg(argmark,void *);
vp = findprop(list,prop);
if (!vp) return 0;
func = *(int (**)())vp;
return (*func)(argmark);
}
[LISTING TWO]
/* Header file for makelist */
/* Remove this if you don't have ANSI C compiler */
#define ANSIC
#ifndef ANSIC
#define void char
#endif
/* Usage: e.g. deref(int,x) or deref(char *,x) */
#define deref(type,x) *((type*)(x))
/* Function prototypes/declarations */
/*----------------------------------------------------------------------*/
#ifdef ANSIC
extern void *makelist(int esize,int nentries);
extern int putproplist(void *list,void *dataptr,char *propsym,void *val);
extern void *getproplist(void *list,void *dataptr,void *propsym);
extern void *toplist(void *list);
extern void *poplist(void *list);
extern void *appendlist(void *list,void *data);
extern void *pappendlist(void *list,void *data,char *propsym,char *val);
extern void *pushlist(void *list,void *data);
extern void *fetchlist(void *list,int ndx);
extern void *walklist(void *list);
extern void rewindlist(void *list);
extern void *malloclist(void *list,int size);
extern int freelist(void *list);
extern int gclist(void *list);
extern int funclist(void *,...);
extern int listindex(void *list);
#else
extern void *makelist();
extern int putproplist();
extern void *getproplist();
extern void *toplist();
extern void *poplist();
extern void *appendlist();
extern void *pappendlist();
extern void *pushlist();
extern void *fetchlist();
extern void *walklist();
extern void rewindlist();
extern void *malloclist();
extern int freelist();
extern int gclist();
extern int funclist();
extern int listindex();
#endif
/*----------------------------------------------------------------------*/
Example 1: A list of integers
#ifdef Explanation
----------------------------------------------------------------------
Make a list to hold integers, and put 100 integers onto the list.
Then, play back the list.
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include "makelist.h"
main() {
void *list,*dp;
int ii;
/* make a list to hold integers */
list = makelist(sizeof(int),10);
/* put 100 integers on list */
for (ii=0 ; ii < 100 ; ii++)
appendlist(list,&ii);
/* use fetchlist to read back list */
for (ii=0 ; ii < 100 ; ii++) {
void *dp = fetchlist(list,ii);
printf("Entry %2d = %d\n",ii,*(int *)dp);
}
freelist(list);
}
Example 2: A list of strings
#ifdef Explanation
----------------------------------------------------------------------
Demonstrates the putting of strings on a list and use of gclist.
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include "makelist.h"
extern char *strdup();
main() {
char buffer[132];
void *list,*dp,*ptr;
int ii;
int cnt;
/* make list to hold strings */
list = makelist(sizeof(char *),10);
/* build the list of strings */
for (ii=0 ; ii < 30 ; ii++) {
sprintf(buffer,"text string %d",ii);
dp = strdup(buffer);
appendlist(list,&dp);
}
/* use walklist to view each string saved in list */
while (dp = walklist(list))
printf("%s\n",*((char **)dp));
/* free up list, as well as all malloced data */
gclist(list);
}
Example 3: A list of structures
#ifdef Explanation
----------------------------------------------------------------------
Saving and retrieving structures on lists.
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include "makelist.h"
extern char *strdup();
/* here is our data structure */
struct foo {
char *name;
int ndx;
} foo;
main() {
void *list;
void *vp;
struct foo *fp;
int ii,jj,kk;
char buffer[256];
/* make list to hold struct foo */
list = makelist(sizeof(struct foo),10);
/* build list of 30 instances of struct foo */
for (ii=0 ; ii < 30 ; ii++) {
sprintf(buffer,"foo element %d",ii);
foo.name = strdup(buffer);
foo.ndx = ii;
appendlist(list,&foo);
}
/* play back list. note that vp is merely cast */
while (vp=walklist(list)) {
fp = (struct foo *)vp;
printf("%2d) %s\n",fp->ndx,fp->name);
}
/* free up each string malloced during list creation */
while (vp=walklist(list)) {
fp = (struct foo *)vp;
free(fp->name);
}
/* free the list itself */
freelist(list);
}
Example 4: Using malloclist()
#ifdef Explanation
----------------------------------------------------------------------
We use malloclist to get memory space, rather than malloc. This will
automatically append malloced data onto a list (which you must provide),
so that a single call to gclist will free not only the list, but all
malloced space as well.
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include "makelist.h"
main() {
void *list,*dp,*ptr;
printf("Exercising malloclist...\n");
list = makelist(sizeof(void *),10);
ptr = "string #1";
dp = malloclist(list,strlen(ptr)+1);
strcpy(dp,ptr);
ptr = "string #2";
dp = malloclist(list,strlen(ptr)+1);
strcpy(dp,ptr);
ptr = "string #3";
dp = malloclist(list,strlen(ptr)+1);
strcpy(dp,ptr);
/* play back list */
while (dp = walklist(list))
printf("%s\n",*(char **)dp);
/* free up the list */
gclist(list);
}
Example 5: Pushing and poping a list
#ifdef Explanation
----------------------------------------------------------------------
Demonstrate how to push & pop data off of a list.
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include "makelist.h"
main() {
void *list,*dp,*ptr;
int ii,jj,kk;
int cnt;
/* build list to hold integers */
list = makelist(sizeof(int),5);
/* push 10 integers onto list */
for (ii=0 ; ii < 10 ; ii++)
pushlist(list,&ii);
/* walk down list 10 times, popping an entry each time */
for (ii=0 ; ii < 10 ; ii++) {
extern void *toplist();
while (dp = walklist(list))
printf("%d\n",*(int *)dp);
dp = toplist(list);
printf("popping off %d\n",*(int *)dp);
poplist(list);
}
/* list is now empty */
printf("pushing onto list again\n");
for (ii=0 ; ii < 10 ; ii++)
pushlist(list,&ii);
/* veryify entire list */
while (dp = walklist(list))
printf("%d\n",*(int *)dp);
/* pop off an item at a time off list */
for (ii=0 ; ii < 10 ; ii++) {
extern void *toplist();
dp = toplist(list);
printf("popping off %d\n",*(int *)dp);
poplist(list);
}
/* ensure list is indeed empty */
printf("walking list again... should be empty\n");
while (dp = walklist(list))
printf("%d\n",*(int *)dp);
freelist(list);
}
Example 6: Property list usage
#ifdef Explanation
----------------------------------------------------------------------
Put 100 integers on a list. Every 5th element on the list, add a
special property value.
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include "makelist.h"
extern char *strdup();
main() {
void *list,*dp,*ptr;
int jj;
int cnt;
void *nl = makelist(sizeof(int),20);
for (jj=0 ; jj < 100 ; jj++) {
void *dp = appendlist(nl,&jj);
/* every 5th element, put something on property list */
if (!(jj%5)) {
char buffer[80];
sprintf(buffer,"list[%d]",jj);
putproplist(nl,dp,"MSG",strdup(buffer));
}
}
for (jj=0 ; jj < 100 ; jj++) {
void *dp = fetchlist(nl,jj);
char *ptr;
printf("%d\n",*(int *)dp);
if (!(jj%5)) {
void *p = (jj) ? dp : (void *)NULL;
printf("PROP: %s\n",ptr = getproplist(nl,p,"MSG"));
free(ptr);
}
}
freelist(nl);
}
Example 7: Property list usage w/pappendlist
#ifdef Explanation
----------------------------------------------------------------------
Make a list to hold integers, and put 100 integers onto the list.
Then, play back the list. For each integer put on the list, add
a property value which uniquely identifies the data value.
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include "makelist.h"
extern char *strdup();
main() {
void *list,*dp;
char *ptr,buffer[80];
int ii;
list = makelist(sizeof(int),10);
/* put 100 integers on list, w/ prop to tell their index in ASCII */
for (ii=0 ; ii < 100 ; ii++) {
sprintf(buffer,"index %d",ii);
pappendlist(list,&ii,"OP",strdup(buffer));
}
/* get each integer off list, and show its property */
for (ii=0 ; ii < 100 ; ii++) {
void *dp = fetchlist(list,ii);
ptr = getproplist(list,dp,"OP");
printf("Entry %2d = %d, prop = %s\n",ii,*(int *)dp,ptr);
free(ptr);
}
freelist(list);
}
Example 8: A list of lists
#ifdef Explanation
----------------------------------------------------------------------
Build and populate a list of lists
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include "makelist.h"
main() {
void *listlist;
int ii,jj,kk;
/* create a list of lists */
listlist = makelist(sizeof(void *),10);
/* build 10 lists to hold integers */
for (ii=0 ; ii < 10 ; ii++) {
void *vp = makelist(sizeof(int),10);
appendlist(listlist,&vp);
}
/* populate each of the 10 lists */
for (ii=0 ; ii < 10 ; ii++) {
void *list = *(void **)fetchlist(listlist,ii);
for (jj=0 ; jj < 20 ; jj++) {
kk = ii*100 + jj;
appendlist(list,&kk);
}
}
/* replay each of the 10 lists */
for (ii=0 ; ii < 10 ; ii++) {
void *list = *(void **)fetchlist(listlist,ii);
for (jj=0 ; jj < 20 ; jj++)
printf("List %d, data = %d\n",ii,*(int *)fetchlist(list,jj));
}
/* free all lists */
for (ii=0 ; ii < 10 ; ii++) {
void *list = *(void **)fetchlist(listlist,ii);
freelist(list);
}
freelist(listlist);
}
Example 9: A list of functions
#ifdef Explanation
----------------------------------------------------------------------
Demonstrate how to use build a list of functions and call them
directly off of the list, with arguments.
----------------------------------------------------------------------
#endif
#include <stdio.h>
#include <varargs.h>
#include "makelist.h"
/* This function expects integer arguments, zero terminated */
static
foo(argmark)
va_list argmark; {
int i;
while (1) {
i = va_arg(argmark,int);
if (!i) break;
printf("%d\n",i);
}
}
/* This function expects string arguments, NULL terminated */
static
goo(argmark)
va_list argmark; {
char *ptr;
while (1) {
ptr = va_arg(argmark,char *);
if (!ptr) break;
printf("%s\n",ptr);
}
}
/* This function expects a string, followed by an integer */
static
poo(argmark)
va_list argmark; {
char *ptr;
int i;
ptr = va_arg(argmark,char *);
i = va_arg(argmark,int);
printf("string = %s, int = %d\n",ptr,i);
}
/* build list for functions internal to proc, and return pointer to list */
static void *flist = NULL;
void *
f_proc() {
int (*func)();
if (!flist) flist = makelist(sizeof(int (*)()),10);
/* put functions on flist, and give 'em names */
func = foo; pappendlist(flist,&func,"FOO",NULL);
func = goo; pappendlist(flist,&func,"GOO",NULL);
func = poo; pappendlist(flist,&func,"POO",NULL);
return flist;
}
/* our proc function */
void
proc() {
printf("In function proc\n");
}
main() {
void *l_proc;
/* get list of proc's functions */
l_proc = f_proc();
/* invoke each of the functions with arguments */
funclist(l_proc,"FOO",1,2,3,4,0);
funclist(l_proc,"GOO","line 1", "line 2", "line 3", NULL);
funclist(l_proc,"POO","some text", 666);
/* finally, call proc */
proc();
}