home *** CD-ROM | disk | FTP | other *** search
- /*
- 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);
- }
- /* -------------------------------------------------------------------------- */
-
-