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