home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QBasic & Borland Pascal & C
/
Delphi5.iso
/
C
/
Samples
/
CSAPE32.ARJ
/
EXAMPLES
/
OAKMEMOK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-09
|
13KB
|
559 lines
/*
oakmemok.c
DEBUGGING version 'oakland' insulated malloc functions
C-scape version
In this version, each allocated block has a header
containing the tag number of the call that allocated it,
the size of the block, and a guard byte.
There is a trailing guard byte after each block.
In addition, a list is kept of all the calls to malloc and free.
This list consists of two linked lists, one of used (malloc'd) pointers
and the other unused (freed) pointers.
Copyright (c) 1986, 1987, 1988 by Oakland Group, Inc.
ALL RIGHTS RESERVED.
Revision History:
-----------------
6/12/89 jmd Now returns NULL if fails
9/10/89 pmcm Updated tag list for CS3.1 release
5/12/90 pmcm Ansi-fied
8/12/90 bkd Fixed alist_Add, alist_Remove and oak_FindTagName
declarations, added OA_KLEX, OA_BTREE and OA_USER
10/02/90 pmcm Updated tag list for CS3.2 release
added ID_BDMOUSE2, ID_ODIR, ID_SFTEXT, ID_SPDWIN,
ID_USERWIN, OA_CURSBLANK (curses), ID_LNFWIN (LNF),
OA_SMGLINEBUF, OA_SMGTERMCAPBUF (VMS)
10/05/90 ted Modified alloc_test to report errors in any mode, and to
allow printing of the tag name.
12/17/90 bkd added special definition for OA_CURSBLANK
*/
#include <stdio.h>
#include <string.h>
/* include all libraries you wish to test */
#include "cscape.h"
#include "ostdlib.h"
#include "oakalloc.h"
#include "oaktag.h"
#include "debug.h"
/* Tags ---------------------------------------------------------------------*/
#ifdef OAK_UNIX
# define OA_CURSBLANK 900
#endif
#ifdef CSCAPE_3 /* !!! define with and without the version number */
#include <cserror.h> /* C-scape tag values */
#endif
#ifdef CCELL_1
#include <ccerror.h> /* C-cell tag values */
#endif
struct tag_name {
int val;
char *tag;
};
/* -------------------------------------------------------------------------- */
static struct tag_name taglist[] = { /* tags should be 9 or less chars */
{ OA_NOTAG, "no tag" },
/**** Oakland tags ******************/
{ ID_BCWIN, "idbc win" },
{ ID_BD1, "idbd_1" },
{ ID_BD123, "idbd_123" },
{ ID_BD2, "idbd_2" },
{ ID_BDBAR, "idbd_bar" },
{ ID_BDBOX, "idbd_box" },
{ ID_BDBOXLIGHT, "idbd_boxl" },
{ ID_BDEDIT, "idbd edit" },
{ ID_BDHEAD, "idbd head" },
{ ID_BDMOUSE, "idbd_mous" },
{ ID_BDMOUSE2, "idbd_mou2" },
{ ID_BDNULL, "idbd_null" },
{ ID_BDPLAIN, "idbd_plai" },
{ ID_BDPROMPT, "idbd_prom" },
{ ID_BDSIDEBAR, "idbd_sbid" },
{ ID_BDSTD, "idbd_std" },
{ ID_BDTITLE, "idbd_titl" },
{ ID_BDXREF, "idbd_xref" },
{ ID_BLWIN, "idbl win" },
{ ID_BOB, "idbob" },
{ ID_BORDER, "idborder" },
{ ID_CMWIN, "idcm win" },
{ ID_COMMON, "idcommon" },
{ ID_GRWIN, "idgr win" },
{ ID_MSGWIN, "idmsg win" },
{ ID_NPWIN, "idnp win" },
{ ID_ODIR, "idoddir" },
{ ID_PMWIN, "idpm win" },
{ ID_SEDWIN, "idsed win" },
{ ID_SFTEXT, "idsf text" },
{ ID_SLEDWIN, "idsledwin" },
{ ID_SPDWIN, "idspd win" },
{ ID_UFUNC, "idufunc" },
{ ID_USERWIN, "idusr win" },
{ ID_WIN, "idwin" },
{ OA_BBCHAIN, "chain" },
{ OA_BBDATA, "bb data" },
{ OA_BBLOCK, "bb block" },
{ OA_BDTITLE, "bd_title" },
{ OA_BFILE, "bfile" },
{ OA_BFPUSH, "bf push" },
{ OA_BTREE, "btree" },
{ OA_CMAP, "cmap" },
{ OA_CMAPBUF, "cmap buf" },
{ OA_DIGATTRMAP, "digattmp" },
{ OA_DIGCOLMAP, "digcolmp" },
{ OA_DIGDATA, "digdata" },
{ OA_DIGFONT, "digfont" },
{ OA_FONT, "font" },
{ OA_FRW, "frw" },
{ OA_IARR, "iarray" },
{ OA_IARRA, "iarray a" },
{ OA_KLEX, "klex" },
{ OA_LARR, "larray" },
{ OA_LARRA, "larray a" },
{ OA_LIST, "list" },
{ OA_LSYM, "lsym" },
{ OA_OBJ, "obj" },
{ OA_OCOLMAP, "ocol map" },
{ OA_OGL, "ogl" },
{ OA_OS2KMDATA, "os2kmdat" },
{ OA_PMAP, "pmap" },
{ OA_PMAPBUF, "pmap buf" },
{ OA_SAVDISP, "savedisp" },
{ OA_SFILE, "sfile" },
{ OA_SFTEXT, "sfiletext" },
{ OA_STRWRAP, "strwrap" },
{ OA_TILE, "tile" },
{ OA_VARRAY, "varray" },
{ OA_VIA, "via" },
{ OA_WIN, "win" },
{ OA_XARR, "xarray" },
{ OA_XARRA, "xarray a" },
/**** Oakland tags UNIX port ********/
#ifdef OAK_UNIX
{ OA_CURSBLANK, "blank buf" },
#endif
/**** Oakland tags VAX/VMS port *****/
#ifdef OAK_VMS
{ OA_SMGLINEBUF, "SMGlinbuf" },
{ OA_SMGTERMCAPBUF, "SMGcapbuf" },
#endif
/**** Look & Feel tags **************/
#ifdef LNF
{ ID_LNFWIN, "idlnf win" },
#endif
/**** C-scape tags ******************/
#ifdef CSCAPE_3
{ CSA_FIELD, "field" },
{ CSA_FLDNAME, "fld name" },
{ CSA_FRAME, "frame" },
{ CSA_FRAMESED, "frame sed" },
{ CSA_HELP, "help" },
{ CSA_HELPINDEX, "help indx" },
{ CSA_HELPSPACE, "help spac" },
{ CSA_HELPTEXT, "help text" },
{ CSA_MCOPYFLD, "mcopy fld" },
{ CSA_MCREATE, "mcreate" },
{ CSA_MENU, "menu" },
{ CSA_SED, "sed" },
{ CSA_SLEDBLANK, "sledblank" },
{ CSA_SLUG, "slug" },
{ CSA_SLUGCHILD, "slugchild" },
{ CSA_TEDREADF, "tedread f" },
{ CSA_TEXTBUF, "text buf" },
{ CSA_TOKBUF, "token buf" },
{ CSA_VARBLOCK, "var block" },
#endif
/**** C-cell tags ******************/
#ifdef CCELL_1
{ CCA_ARR2, "arr2" },
{ CCA_ARR2A, "arr2a" },
{ CCA_FORMSTR, "formstr" },
{ CCA_NRANGE, "nrange" },
{ CCA_READBUF, "readbuf" },
{ CCA_SPAR2, "spar2" },
{ CCA_SPAR2A, "spar2a" },
{ CCA_SPAR2ELT, "spar2elt" },
{ CCA_SPD, "spd" },
{ CCA_WKSBOX, "wksbox" },
{ CCA_WKSBOXH, "wksboxh" },
{ CCA_WKSBOXW, "wksboxw" },
{ CCA_WKSCELLS, "wkscells" },
{ CCA_WKSCELL, "wkscell" },
{ CCA_WKSFILE, "wksfile" },
{ CCA_WKSWIN, "wkswin" },
{ CCA_WKS, "wks" },
#endif
{ 0, NULL }
};
/* -------------------------------------------------------------------------- */
char *oak_FindTagName(int val)
/*
Given a tag value, lookup the tag name
"unknown" if not found
*/
{
int i;
static char uname[20];
char *p;
if (val >= 10000) {
sprintf(uname, "user code %d", val - 10000);
p = uname;
}
else {
for(i = 0; taglist[i].val != 0; i++) {
if (taglist[i].val == val) {
break;
}
}
p = (taglist[i].val == 0) ? "unknown" : taglist[i].tag;
}
return(p);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* The real code */
struct alist_struct {
VOID *ptr; /* allocated block */
struct alist_struct *next; /* next entry in list */
};
#define ALIST_SIZE 2000
#define HEADER (1 + (2 * sizeof(int)))
#define FOOTER 1
#define GUARD 0x22
#define ptr_SetGuard1(ptr) \
(*((char *) ((char *)(ptr) + (2 * sizeof(int)))) = GUARD)
#define ptr_SetGuard2(ptr, size) \
(*((char *) ((char *)(ptr) + (size) + HEADER)) = GUARD)
#define ptr_SetTag(ptr, tag) \
(*((int *) (ptr)) = (tag))
#define ptr_SetSize(ptr, size) \
(*((int *) ((char *)(ptr) + sizeof(int))) = (size))
#define ptr_GetGuard1(ptr) \
(*((char *) ((char *)(ptr) + (2 * sizeof(int)))))
#define ptr_GetGuard2(ptr, size) \
(*((char *) ((char *)(ptr) + (size) + HEADER)))
#define ptr_GetTag(ptr) \
(*((int *) (ptr)))
#define ptr_GetSize(ptr) \
(*((int *) ((char *)(ptr) + sizeof(int))))
/***/
static struct alist_struct alist[ALIST_SIZE];
static struct alist_struct *alist_used = NULL; /* list of free entries */
static struct alist_struct *alist_free = NULL; /* list of used entries */
static boolean alist_init = FALSE; /* has the list been initialized? */
OSTATIC void alist_Add(VOID *);
OSTATIC void alist_Remove(VOID *);
VOID *omalloc(int tag, SIZE_T size)
/*
Call malloc with the given size.
Return the result.
If malloc fails, sets oak_errno to tag
*/
{
VOID *m;
int x;
if ((m = malloc(size + HEADER + FOOTER)) == NULL) {
oak_SetErrno(tag);
return(NULL);
}
/* Set up guard bytes */
ptr_SetTag(m, tag);
ptr_SetSize(m, size);
ptr_SetGuard1(m);
ptr_SetGuard2(m, size);
/* Add it to the list */
alist_Add(m);
/* Test the heap */
if ((x = alloc_test(NULL, 0)) != 0) {
/* !!! disp_Close... */
printf("Heap error with tag %d\n", x);
exit(1);
}
return((VOID *) ((char *) m + HEADER));
}
/* -------------------------------------------------------------------------- */
VOID *ocalloc(int tag, SIZE_T n, SIZE_T size)
/*
Call calloc with the given size.
Return the result.
If calloc fails, sets oak_errno to tag
*/
{
VOID *m;
int x;
if ((m = calloc(n, size + HEADER + FOOTER)) == NULL) {
oak_SetErrno(tag);
return(NULL);
}
/* Set up guard bytes */
ptr_SetTag(m, tag);
ptr_SetSize(m, size * n);
ptr_SetGuard1(m);
ptr_SetGuard2(m, size * n);
/* Add it to the list */
alist_Add(m);
/* Test the heap */
if ((x = alloc_test(NULL, 0)) != 0) {
printf("Heap error with tag %d\n", x);
exit(1);
}
return((VOID *) ((char *) m + HEADER));
}
/* -------------------------------------------------------------------------- */
VOID *orealloc(int tag, VOID *buffer, SIZE_T size)
/*
Call realloc with the given size and buffer.
Return the result.
If realloc fails, sets oak_errno to tag
*/
{
VOID *m;
int x;
buffer = (VOID *) ((char *) buffer - HEADER);
if ((m = realloc(buffer, size + HEADER + FOOTER)) == NULL) {
oak_SetErrno(tag);
return(NULL);
}
/* move trailing guard byte, readjust size */
ptr_SetSize(m, size);
ptr_SetGuard2(m, size);
/* Remove and re-add it to the list */
alist_Remove(buffer);
alist_Add(m);
/* Test the heap */
if ((x = alloc_test(NULL, 0)) != 0) {
printf("Heap error with tag %d\n", x);
exit(1);
}
return((VOID *) ((char *) m + HEADER));
}
/* -------------------------------------------------------------------------- */
void ofree(int tag, VOID *buffer)
/*
Call free with the given buffer.
Return the result.
*/
{
VOID *m;
int x;
/* Test the heap */
if ((x = alloc_test(NULL, 0)) != 0) {
printf("Heap error with tag %d\n", x);
exit(1);
}
m = (VOID *) ((char *) buffer - HEADER);
free(m);
/* Remove block from the list */
alist_Remove(m);
}
/* -------------------------------------------------------------------------- */
/*** alist routines ***/
static void alist_Add(VOID *ptr)
/*
Add a new entry to the used list. (from the unused list)
*/
{
register int i;
struct alist_struct *temp;
/* If list hasn't been set up, then set it up */
if (!alist_init) {
for (i = 0; i < ALIST_SIZE; i++) {
alist[i].ptr = NULL;
alist[i].next = &alist[i+1];
}
alist[ALIST_SIZE - 1].next = NULL;
alist_used = NULL;
alist_free = &alist[0];
alist_init = TRUE;
}
/* Get a slot from the free list */
if (alist_free != NULL) {
temp = alist_free;
alist_free = alist_free->next;
temp->next = alist_used;
temp->ptr = ptr;
alist_used = temp;
}
}
/* -------------------------------------------------------------------------- */
static void alist_Remove(VOID *ptr)
/*
Remove an entry from the used list. (add it to the unused list)
*/
{
struct alist_struct *temp, *last;
/* If list hasn't been set up, then don't do anything */
if (alist_init) {
/* find the ptr in the used list */
for (temp = alist_used, last = NULL;
temp != NULL;
last = temp, temp = temp->next) {
if (temp->ptr == ptr) {
/* remove this slot from the used list */
if (last == NULL) {
alist_used = temp->next;
}
else {
last->next = temp->next;
}
/* put the slot at the top of the free list */
temp->ptr = NULL;
temp->next = alist_free;
alist_free = temp;
break;
}
}
}
}
/* -------------------------------------------------------------------------- */
int alloc_test(char *msg, int mode)
/*
Tests integrity of allocated storage.
mode can have the following values:
0 silent
1 print summaries
2 print dump list
returns 0 if the heap is OK.
else the tag value of the bad block.
*/
{
int error = 0;
int size;
long used_total = 0L;
char g1, g2;
struct alist_struct *temp;
if (msg != NULL && mode > 0) {
printf("%s\n", msg);
}
/* loop through the used list */
for (temp = alist_used; temp != NULL; temp = temp->next) {
size = ptr_GetSize(temp->ptr);
used_total += size;
/* test the block */
g1 = ptr_GetGuard1(temp->ptr);
g2 = ptr_GetGuard2(temp->ptr, size);
if (g1 != GUARD || g2 != GUARD) {
error = ptr_GetTag(temp->ptr);
break;
}
if (mode > 1) {
printf("Used block %p of size %4.4X (%5d) %10.10s (%4d)\n",
temp->ptr, size, size,
oak_FindTagName(ptr_GetTag(temp->ptr)),
ptr_GetTag(temp->ptr));
}
}
if (mode > 0) {
printf(" total used %ld\n", used_total);
if (error == 0) {
printf("OK heap\n\n");
}
}
if (error != 0) {
if (msg != NULL && mode <= 0) {
printf("%s\n", msg);
}
printf("ERROR - block with tag %d : %s is bad\n\n", error, oak_FindTagName(error));
}
return(error);
}
/* -------------------------------------------------------------------------- */