home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c185 / 1.ddi / EXAMPLE.EXE / CSCAPE / EXAMPLE / OAKMEMOK.C < prev   
Encoding:
C/C++ Source or Header  |  1989-09-10  |  11.3 KB  |  524 lines

  1. /*
  2.     oakmemok.c
  3.  
  4.     DEBUGGING version 'oakland'  insulated malloc functions
  5.  
  6.     C-scape version
  7.  
  8.     In this version, each allocated block has a header
  9.     containing the tag number of the call that allocated it,
  10.     the size of the block, and a guard byte.
  11.     There is a trailing guard byte after each block.
  12.  
  13.     In addition, a list is kept of all the calls to malloc and free.
  14.     This list consists of two linked lists, one of used (malloc'd) pointers
  15.     and the other unused (freed) pointers.
  16.  
  17.     Copyright (c) 1986, 1987, 1988 by Oakland Group, Inc.
  18.     ALL RIGHTS RESERVED.
  19.  
  20.     Revision History:
  21.     -----------------
  22.      6/12/89 jmd    Now returns NULL if fails
  23.      9/10/89 pmc    Update tag list for CS3.1 release
  24. */
  25.  
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29.  
  30. /* include all libraries you wish to test */
  31.  
  32. #include "cscape.h"
  33.  
  34. #include "oakalloc.h"
  35. #include "oaktag.h"
  36.  
  37. #include "debug.h"
  38.  
  39. /* Tags ---------------------------------------------------------------------*/
  40.  
  41. #ifdef CSCAPE_3            /* !!! define with and without the version number */
  42. #include <cserror.h>    /* C-scape tag values */
  43. #endif
  44.  
  45. #ifdef CCELL_1
  46. #include <ccerror.h>    /* C-cell tag values */
  47. #endif
  48.  
  49. char *oak_FindTagName(int);
  50.  
  51. struct tag_name {
  52.     int            val;
  53.     char          *tag;
  54. };
  55. /* -------------------------------------------------------------------------- */
  56.  
  57. static struct tag_name taglist[] = {     /* tags should be 9 or less chars */
  58.  
  59.     { OA_NOTAG,            "no tag"      },
  60.  
  61. /**** Oakland tags ******************/
  62.  
  63.     { ID_BCWIN,            "idbc win"    },
  64.     { ID_BD1,            "idbd_1"    },
  65.     { ID_BD123,            "idbd_123"    },
  66.     { ID_BD2,            "idbd_2"    },
  67.     { ID_BDBAR,            "idbd_bar"    },
  68.     { ID_BDBOX,            "idbd_box"    },
  69.     { ID_BDBOXLIGHT,    "idbd_boxl"    },
  70.     { ID_BDEDIT,        "idbd edit"    },
  71.     { ID_BDHEAD,        "idbd head"    },
  72.     { ID_BDMOUSE,        "idbd_mous"    },
  73.     { ID_BDNULL,        "idbd_null"    },
  74.     { ID_BDPLAIN,        "idbd_plai"    },
  75.     { ID_BDPROMPT,        "idbd_prom"    },
  76.     { ID_BDSIDEBAR,        "idbd_sbid"    },
  77.     { ID_BDSTD,            "idbd_std"    },
  78.     { ID_BDTITLE,        "idbd_titl"    },
  79.     { ID_BDXREF,        "idbd_xref"    },
  80.     { ID_BLWIN,            "idbl win"    },
  81.     { ID_BOB,            "idbob"         },
  82.     { ID_BORDER,        "idborder"    },
  83.     { ID_CMWIN,            "idcm win"    },
  84.     { ID_COMMON,        "idcommon"    },
  85.     { ID_GRWIN,            "idgr win"    },
  86.     { ID_MSGWIN,        "idmsg win"    },
  87.     { ID_NPWIN,            "idnp win"    },
  88.     { ID_PMWIN,            "idpm win"    },
  89.     { ID_SEDWIN,        "idsed win"    },
  90.     { ID_SLEDWIN,        "idsledwin" },
  91.     { ID_UFUNC,            "idufunc"    },
  92.     { ID_WIN,            "idwin"        },
  93.  
  94.     { OA_BBCHAIN,        "chain"        },
  95.     { OA_BBDATA,        "bb data"    },
  96.     { OA_BBLOCK,        "bb block"    },
  97.     { OA_BDTITLE,        "bd_title"    },
  98.     { OA_BFILE,            "bfile"        },
  99.     { OA_BFPUSH,        "bf push"    },
  100.     { OA_CMAP,            "cmap"        },
  101.     { OA_CMAPBUF,        "cmap buf"    },
  102.     { OA_DIGATTRMAP,    "digattmp"    },
  103.     { OA_DIGCOLMAP,        "digcolmp"    },
  104.     { OA_DIGDATA,        "digdata"    },
  105.     { OA_FONT,            "font"        },
  106.     { OA_FRW,            "frw"     },
  107.     { OA_IARR,            "iarray"     },
  108.     { OA_IARRA,            "iarray a"     },
  109.     { OA_LARR,            "larray"     },
  110.     { OA_LARRA,            "larray a"     },
  111.     { OA_LIST,            "list"     },
  112.     { OA_LSYM,            "lsym"     },
  113.     { OA_OBJ,            "obj"         },
  114.     { OA_OCOLMAP,        "ocol map"    },
  115.     { OA_OGL,            "ogl"        },
  116.     { OA_OS2KMDATA,        "os2kmdat"    },
  117.     { OA_PMAP,            "pmap"        },
  118.     { OA_PMAPBUF,        "pmap buf"    },
  119.     { OA_SAVDISP,        "savedisp"    },
  120.     { OA_SFILE,            "sfile"        },
  121.     { OA_STRWRAP,        "strwrap"    },
  122.     { OA_TILE,            "tile"         },
  123.     { OA_VARRAY,        "varray"    },
  124.     { OA_VIA,            "via"         },
  125.     { OA_WIN,            "win"         },
  126.     { OA_XARR,            "xarray"     },
  127.     { OA_XARRA,            "xarray a"     },
  128.  
  129. /**** C-scape tags ******************/
  130.  
  131. #ifdef CSCAPE_3
  132.     { CSA_FIELD,        "field"         },
  133.     { CSA_FLDNAME,        "fld name"    },
  134.     { CSA_FRAME,        "frame"         },
  135.     { CSA_FRAMESED,        "frame sed"    },
  136.     { CSA_HELP,            "help"         },
  137.     { CSA_HELPINDEX,    "help indx"    },
  138.     { CSA_HELPSPACE,    "help spac"    },
  139.     { CSA_HELPTEXT,        "help text"    },
  140.     { CSA_MCOPYFLD,        "mcopy fld"    },
  141.     { CSA_MCREATE,        "mcreate"    },
  142.     { CSA_MENU,            "menu"         },
  143.     { CSA_SED,            "sed"         },
  144.     { CSA_SLEDBLANK,    "sledblank"    },
  145.     { CSA_SLUG,            "slug"         },
  146.     { CSA_SLUGCHILD,    "slugchild"    },
  147.     { CSA_TEDREADF,        "tedread f"    },
  148.     { CSA_TEXTBUF,        "text buf"    },
  149.     { CSA_TOKBUF,        "token buf"    },
  150.     { CSA_VARBLOCK,        "var block"    },
  151. #endif
  152.  
  153. /**** C-cell tags ******************/
  154.  
  155. #ifdef CCELL_1
  156.     {    CCA_ARR2,        "arr2"         },
  157.     {    CCA_ARR2A,        "arr2a"     },
  158.     {    CCA_FORMSTR,    "formstr"     },
  159.     {    CCA_NRANGE,        "nrange"     },
  160.     {    CCA_READBUF,    "readbuf"     },
  161.     {    CCA_SPAR2,        "spar2"     },
  162.     {    CCA_SPAR2A,        "spar2a"     },
  163.     {    CCA_SPAR2ELT,    "spar2elt"     },
  164.     {    CCA_SPD,        "spd"         },
  165.     {    CCA_WKSBOX,        "wksbox"     },
  166.     {    CCA_WKSBOXH,    "wksboxh"     },
  167.     {    CCA_WKSBOXW,    "wksboxw"     },
  168.     {    CCA_WKSCELLS,    "wkscells"     },
  169.     {    CCA_WKSCELL,    "wkscell"     },
  170.     {    CCA_WKSFILE,    "wksfile"     },
  171.     {    CCA_WKSWIN,        "wkswin"     },
  172.     {    CCA_WKS,        "wks"         },
  173. #endif
  174.  
  175.     { 0,                NULL         }
  176.  
  177. };
  178.  
  179. /* -------------------------------------------------------------------------- */
  180.  
  181. char *oak_FindTagName(val)
  182.     int val;
  183. /*
  184.     Given a tag value, lookup the tag name
  185.  
  186.     "unknown" if not found
  187. */
  188. {
  189.     int i;
  190.     char *p;
  191.     
  192.     for(i = 0; taglist[i].val != 0;i++) {
  193.         if (taglist[i].val == val) {
  194.             break;
  195.         }
  196.     }
  197.  
  198.     p = (taglist[i].val == 0) ? "unknown" : taglist[i].tag;
  199.     return(p);
  200. }
  201. /* -------------------------------------------------------------------------- */
  202. /* -------------------------------------------------------------------------- */
  203. /* -------------------------------------------------------------------------- */
  204.  
  205. /* The real code */
  206.  
  207.  
  208. struct alist_struct {
  209.  
  210.     VOID                 *ptr;        /* allocated block */
  211.     struct alist_struct *next;        /* next entry in list */
  212. };
  213.  
  214. #define ALIST_SIZE    2000
  215. #define HEADER    (1 + (2 * sizeof(int)))
  216. #define FOOTER    1
  217. #define GUARD    0x22
  218.  
  219. #define ptr_SetGuard1(ptr)    \
  220.         (*((char *) ((char *)(ptr) + (2 * sizeof(int)))) = GUARD)
  221.  
  222. #define ptr_SetGuard2(ptr, size)    \
  223.         (*((char *) ((char *)(ptr) + (size) + HEADER)) = GUARD)
  224.  
  225. #define ptr_SetTag(ptr, tag) \
  226.         (*((int *) (ptr)) = (tag))
  227.  
  228. #define ptr_SetSize(ptr, size)    \
  229.         (*((int *) ((char *)(ptr) + sizeof(int))) = (size))
  230.  
  231. #define ptr_GetGuard1(ptr)    \
  232.         (*((char *) ((char *)(ptr) + (2 * sizeof(int)))))
  233.  
  234. #define ptr_GetGuard2(ptr, size)    \
  235.         (*((char *) ((char *)(ptr) + (size) + HEADER)))
  236.  
  237. #define ptr_GetTag(ptr) \
  238.         (*((int *) (ptr)))
  239.  
  240. #define ptr_GetSize(ptr)    \
  241.         (*((int *) ((char *)(ptr) + sizeof(int))))
  242.  
  243. /***/
  244.  
  245. static struct alist_struct alist[ALIST_SIZE];
  246. static struct alist_struct *alist_used = NULL;         /* list of free entries */
  247. static struct alist_struct *alist_free = NULL;         /* list of used entries */
  248.  
  249. static boolean alist_init = FALSE;                 /* has the list been initialized? */
  250.  
  251. static void alist_Add(_arg1(VOID *));
  252. static void alist_Remove(_arg1(VOID *));
  253.  
  254. VOID *omalloc(tag, size)
  255.     int tag;
  256.     SIZE_T size;
  257. /*
  258.     Call malloc with the given size.
  259.     Return the result.
  260.     If malloc fails, sets oak_errno to tag
  261. */
  262. {
  263.     VOID *m;
  264.     int  x;
  265.  
  266.     if ((m = malloc(size + HEADER + FOOTER)) == NULL) {
  267.         oak_SetErrno(tag);
  268.         return(NULL);
  269.     }
  270.  
  271.     /* Set up guard bytes */
  272.     ptr_SetTag(m, tag);
  273.     ptr_SetSize(m, size);
  274.     ptr_SetGuard1(m);
  275.     ptr_SetGuard2(m, size);
  276.  
  277.     /* Add it to the list */
  278.     alist_Add(m);
  279.  
  280.     /* Test the heap */
  281.     if ((x = alloc_test(NULL, 0)) != 0) {
  282.         /* !!! disp_Close... */
  283.         printf("Heap error with tag %d\n", x);
  284.         exit(1);
  285.     }
  286.  
  287.     return((VOID *) ((char *) m + HEADER));
  288. }
  289.  
  290. VOID *ocalloc(tag, n, size)
  291.     int tag;
  292.     SIZE_T n;
  293.     SIZE_T size;
  294. /*
  295.     Call calloc with the given size.
  296.     Return the result.
  297.     If calloc fails, sets oak_errno to tag
  298. */
  299. {
  300.     VOID *m;
  301.     int x;
  302.  
  303.     if ((m = calloc(n, size + HEADER + FOOTER)) == NULL) {
  304.         oak_SetErrno(tag);
  305.         return(NULL);
  306.     }
  307.  
  308.     /* Set up guard bytes */
  309.     ptr_SetTag(m, tag);
  310.     ptr_SetSize(m, size * n);
  311.     ptr_SetGuard1(m);
  312.     ptr_SetGuard2(m, size * n);
  313.  
  314.     /* Add it to the list */
  315.     alist_Add(m);
  316.  
  317.     /* Test the heap */
  318.     if ((x = alloc_test(NULL, 0)) != 0) {
  319.         printf("Heap error with tag %d\n", x);
  320.         exit(1);
  321.     }
  322.  
  323.     return((VOID *) ((char *) m + HEADER));
  324. }
  325.  
  326. VOID *orealloc(tag, buffer, size)
  327.     int tag;
  328.     VOID *buffer;
  329.     SIZE_T size;
  330. /*
  331.     Call realloc with the given size and buffer.
  332.     Return the result.
  333.     If realloc fails, sets oak_errno to tag
  334. */
  335. {
  336.     VOID *m;
  337.     int x;
  338.  
  339.     buffer = (VOID *) ((char *) buffer - HEADER);
  340.  
  341.     if ((m = realloc(buffer, size + HEADER + FOOTER)) == NULL) {
  342.         oak_SetErrno(tag);
  343.         return(NULL);
  344.     }
  345.  
  346.     /* move trailing guard byte, readjust size */
  347.     ptr_SetSize(m, size);
  348.     ptr_SetGuard2(m, size);
  349.  
  350.     /* Remove and re-add it to the list */
  351.     alist_Remove(buffer);
  352.     alist_Add(m);
  353.  
  354.     /* Test the heap */
  355.     if ((x = alloc_test(NULL, 0)) != 0) {
  356.         printf("Heap error with tag %d\n", x);
  357.         exit(1);
  358.     }
  359.  
  360.     return((VOID *) ((char *) m + HEADER));
  361. }
  362.  
  363. void ofree(tag, buffer)
  364.     int tag;
  365.     VOID *buffer;
  366. /*
  367.     Call free with the given buffer.
  368.     Return the result.
  369. */
  370. {
  371.     VOID *m;
  372.     int x;
  373.  
  374.     /* Test the heap */
  375.     if ((x = alloc_test(NULL, 0)) != 0) {
  376.         printf("Heap error with tag %d\n", x);
  377.         exit(1);
  378.     }
  379.  
  380.     m = (VOID *) ((char *) buffer - HEADER);
  381.     free(m);
  382.  
  383.     /* Remove block from the list */
  384.     alist_Remove(m);
  385. }
  386.  
  387.  
  388. /*** alist routines ***/
  389.  
  390. void alist_Add(ptr)
  391.     VOID *ptr;
  392. /*
  393.     Add a new entry to the used list.  (from the unused list)
  394. */
  395. {
  396.     register int i;
  397.     struct alist_struct *temp;
  398.  
  399.     /* If list hasn't been set up, then set it up */
  400.     if (!alist_init) {
  401.         for (i = 0; i < ALIST_SIZE; i++) {
  402.             alist[i].ptr = NULL;
  403.             alist[i].next = &alist[i+1];
  404.         }
  405.  
  406.         alist[ALIST_SIZE - 1].next = NULL;
  407.         alist_used = NULL;
  408.         alist_free = &alist[0];
  409.  
  410.         alist_init = TRUE;
  411.     }
  412.  
  413.     /* Get a slot from the free list */
  414.     if (alist_free != NULL) {
  415.         temp = alist_free;
  416.         alist_free = alist_free->next;
  417.  
  418.         temp->next = alist_used;
  419.         temp->ptr  = ptr;
  420.         alist_used = temp;
  421.     }
  422. }
  423.  
  424.  
  425. void alist_Remove(ptr)
  426.     VOID *ptr;
  427. /*
  428.     Remove an entry from the used list.  (add it to the unused list)
  429. */
  430. {
  431.     struct alist_struct *temp, *last;
  432.  
  433.     /* If list hasn't been set up, then don't do anything */
  434.     if (alist_init) {
  435.  
  436.         /* find the ptr in the used list */
  437.         for (temp = alist_used, last = NULL; 
  438.              temp != NULL; 
  439.              last = temp, temp = temp->next) {
  440.  
  441.             if (temp->ptr == ptr) {
  442.                 /* remove this slot from the used list */
  443.                 if (last == NULL) {
  444.                     alist_used = temp->next;
  445.                 }
  446.                 else {
  447.                     last->next = temp->next;
  448.                 }
  449.  
  450.                 /* put the slot at the top of the free list */
  451.                 temp->ptr = NULL;
  452.                 temp->next = alist_free;
  453.                 alist_free = temp;
  454.                 break;
  455.             }
  456.         }
  457.     }
  458. }
  459.  
  460. int alloc_test(msg, mode)
  461.     char *msg;
  462.     int mode;
  463. /*
  464.     Tests integrity of allocated storage.
  465.  
  466.     mode can have the following values:
  467.  
  468.     0    silent
  469.     1    print summaries
  470.     2    print dump list
  471.  
  472.     returns 0 if the heap is OK.
  473.     else the tag value of the bad block.
  474. */
  475. {
  476.     int     error = 0;
  477.     int        size;
  478.     long    used_total = 0L;
  479.     char     g1, g2;
  480.  
  481.     struct alist_struct *temp;
  482.  
  483.     if (msg != NULL && mode > 0) {
  484.         printf("%s\n", msg);
  485.     }
  486.  
  487.     /* loop through the used list */
  488.     for (temp = alist_used; temp != NULL; temp = temp->next) {
  489.  
  490.         size = ptr_GetSize(temp->ptr);
  491.         used_total += size;
  492.  
  493.         /* test the block */
  494.         g1 = ptr_GetGuard1(temp->ptr);
  495.         g2 = ptr_GetGuard2(temp->ptr, size);
  496.  
  497.         if (g1 != GUARD || g2 != GUARD) {
  498.             error = ptr_GetTag(temp->ptr);
  499.             break;
  500.         }
  501.  
  502.         if (mode > 1) {
  503.             printf("Used block %p of size %4.4X (%5d) %10.10s (%4d)\n", 
  504.                 temp->ptr, size, size, 
  505.                 oak_FindTagName(ptr_GetTag(temp->ptr)),
  506.                 ptr_GetTag(temp->ptr));
  507.         }
  508.     }
  509.  
  510.     if (mode > 0) {
  511.         printf("       total used %ld\n", used_total);
  512.  
  513.         if (error == 0) {
  514.             printf("OK heap\n\n");
  515.         }
  516.         else {
  517.             printf("ERROR - block with tag %d is bad\n\n", error);
  518.         }
  519.     }
  520.  
  521.     return(error);
  522.  
  523.