home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tkisrc04.zip / tcl / os2 / tclCkalloc.c < prev    next >
C/C++ Source or Header  |  1998-08-07  |  21KB  |  739 lines

  1. /* 
  2.  * tclCkalloc.c --
  3.  *
  4.  *    Interface to malloc and free that provides support for debugging problems
  5.  *    involving overwritten, double freeing memory and loss of memory.
  6.  *
  7.  * Copyright (c) 1991-1994 The Regents of the University of California.
  8.  * Copyright (c) 1994-1996 Sun Microsystems, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * This code contributed by Karl Lehenbauer and Mark Diekhans
  14.  *
  15.  *
  16.  * SCCS: @(#) tclCkalloc.c 1.17 96/03/14 13:05:56
  17.  */
  18.  
  19. #include "tclInt.h"
  20.  
  21. #define FALSE    0
  22. #define TRUE    1
  23.  
  24. #ifdef TCL_MEM_DEBUG
  25. #ifndef TCL_GENERIC_ONLY
  26. #include "tclPort.h"
  27. #endif
  28.  
  29. /*
  30.  * One of the following structures is allocated each time the
  31.  * "memory tag" command is invoked, to hold the current tag.
  32.  */
  33.  
  34. typedef struct MemTag {
  35.     int refCount;        /* Number of mem_headers referencing
  36.                  * this tag. */
  37.     char string[4];        /* Actual size of string will be as
  38.                  * large as needed for actual tag.  This
  39.                  * must be the last field in the structure. */
  40. } MemTag;
  41.  
  42. #define TAG_SIZE(bytesInString) ((unsigned) sizeof(MemTag) + bytesInString - 3)
  43.  
  44. static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers
  45.                  * (set by "memory tag" command). */
  46.  
  47. /*
  48.  * One of the following structures is allocated just before each
  49.  * dynamically allocated chunk of memory, both to record information
  50.  * about the chunk and to help detect chunk under-runs.
  51.  */
  52.  
  53. #define LOW_GUARD_SIZE (8 + (32 - (sizeof(long) + sizeof(int)))%8)
  54. struct mem_header {
  55.     struct mem_header *flink;
  56.     struct mem_header *blink;
  57.     MemTag *tagPtr;        /* Tag from "memory tag" command;  may be
  58.                  * NULL. */
  59.     char *file;
  60.     long length;
  61.     int line;
  62.     unsigned char low_guard[LOW_GUARD_SIZE];
  63.                 /* Aligns body on 8-byte boundary, plus
  64.                  * provides at least 8 additional guard bytes
  65.                  * to detect underruns. */
  66.     char body[1];        /* First byte of client's space.  Actual
  67.                  * size of this field will be larger than
  68.                  * one. */
  69. };
  70.  
  71. static struct mem_header *allocHead = NULL;  /* List of allocated structures */
  72.  
  73. #define GUARD_VALUE  0141
  74.  
  75. /*
  76.  * The following macro determines the amount of guard space *above* each
  77.  * chunk of memory.
  78.  */
  79.  
  80. #define HIGH_GUARD_SIZE 8
  81.  
  82. /*
  83.  * The following macro computes the offset of the "body" field within
  84.  * mem_header.  It is used to get back to the header pointer from the
  85.  * body pointer that's used by clients.
  86.  */
  87.  
  88. #define BODY_OFFSET \
  89.     ((unsigned long) (&((struct mem_header *) 0)->body))
  90.  
  91. static int total_mallocs = 0;
  92. static int total_frees = 0;
  93. static int current_bytes_malloced = 0;
  94. static int maximum_bytes_malloced = 0;
  95. static int current_malloc_packets = 0;
  96. static int maximum_malloc_packets = 0;
  97. static int break_on_malloc = 0;
  98. static int trace_on_at_malloc = 0;
  99. static int  alloc_tracing = FALSE;
  100. static int  init_malloced_bodies = TRUE;
  101. #ifdef MEM_VALIDATE
  102.     static int  validate_memory = TRUE;
  103. #else
  104.     static int  validate_memory = FALSE;
  105. #endif
  106.  
  107. /*
  108.  * Prototypes for procedures defined in this file:
  109.  */
  110.  
  111. static int        MemoryCmd _ANSI_ARGS_((ClientData clientData,
  112.                 Tcl_Interp *interp, int argc, char **argv));
  113.  
  114. /*
  115.  *----------------------------------------------------------------------
  116.  *
  117.  * dump_memory_info --
  118.  *     Display the global memory management statistics.
  119.  *
  120.  *----------------------------------------------------------------------
  121.  */
  122. static void
  123. dump_memory_info(outFile) 
  124.     FILE *outFile;
  125. {
  126.         fprintf(outFile,"total mallocs             %10d\n", 
  127.                 total_mallocs);
  128.         fprintf(outFile,"total frees               %10d\n", 
  129.                 total_frees);
  130.         fprintf(outFile,"current packets allocated %10d\n", 
  131.                 current_malloc_packets);
  132.         fprintf(outFile,"current bytes allocated   %10d\n", 
  133.                 current_bytes_malloced);
  134.         fprintf(outFile,"maximum packets allocated %10d\n", 
  135.                 maximum_malloc_packets);
  136.         fprintf(outFile,"maximum bytes allocated   %10d\n", 
  137.                 maximum_bytes_malloced);
  138. }
  139.  
  140. /*
  141.  *----------------------------------------------------------------------
  142.  *
  143.  * ValidateMemory --
  144.  *     Procedure to validate allocted memory guard zones.
  145.  *
  146.  *----------------------------------------------------------------------
  147.  */
  148. static void
  149. ValidateMemory (memHeaderP, file, line, nukeGuards)
  150.     struct mem_header *memHeaderP;
  151.     char              *file;
  152.     int                line;
  153.     int                nukeGuards;
  154. {
  155.     unsigned char *hiPtr;
  156.     int   idx;
  157.     int   guard_failed = FALSE;
  158.     int byte;
  159.     
  160.     for (idx = 0; idx < LOW_GUARD_SIZE; idx++) {
  161.         byte = *(memHeaderP->low_guard + idx);
  162.         if (byte != GUARD_VALUE) {
  163.             guard_failed = TRUE;
  164.             fflush (stdout);
  165.         byte &= 0xff;
  166.             fprintf(stderr, "low guard byte %d is 0x%x  \t%c\n", idx, byte,
  167.             (isprint(UCHAR(byte)) ? byte : ' '));
  168.         }
  169.     }
  170.     if (guard_failed) {
  171.         dump_memory_info (stderr);
  172.         fprintf (stderr, "low guard failed at %lx, %s %d\n",
  173.                  (long unsigned int) memHeaderP->body, file, line);
  174.         fflush (stderr);  /* In case name pointer is bad. */
  175.         fprintf (stderr, "%ld bytes allocated at (%s %d)\n", memHeaderP->length,
  176.         memHeaderP->file, memHeaderP->line);
  177.         panic ("Memory validation failure");
  178.     }
  179.  
  180.     hiPtr = (unsigned char *)memHeaderP->body + memHeaderP->length;
  181.     for (idx = 0; idx < HIGH_GUARD_SIZE; idx++) {
  182.         byte = *(hiPtr + idx);
  183.         if (byte != GUARD_VALUE) {
  184.             guard_failed = TRUE;
  185.             fflush (stdout);
  186.         byte &= 0xff;
  187.             fprintf(stderr, "hi guard byte %d is 0x%x  \t%c\n", idx, byte,
  188.             (isprint(UCHAR(byte)) ? byte : ' '));
  189.         }
  190.     }
  191.  
  192.     if (guard_failed) {
  193.         dump_memory_info (stderr);
  194.         fprintf (stderr, "high guard failed at %lx, %s %d\n",
  195.                  (long unsigned int) memHeaderP->body, file, line);
  196.         fflush (stderr);  /* In case name pointer is bad. */
  197.         fprintf (stderr, "%ld bytes allocated at (%s %d)\n",
  198.         memHeaderP->length, memHeaderP->file,
  199.         memHeaderP->line);
  200.         panic ("Memory validation failure");
  201.     }
  202.  
  203.     if (nukeGuards) {
  204.         memset ((char *) memHeaderP->low_guard, 0, LOW_GUARD_SIZE); 
  205.         memset ((char *) hiPtr, 0, HIGH_GUARD_SIZE); 
  206.     }
  207.  
  208. }
  209.  
  210. /*
  211.  *----------------------------------------------------------------------
  212.  *
  213.  * Tcl_ValidateAllMemory --
  214.  *     Validates guard regions for all allocated memory.
  215.  *
  216.  *----------------------------------------------------------------------
  217.  */
  218. void
  219. Tcl_ValidateAllMemory (file, line)
  220.     char  *file;
  221.     int    line;
  222. {
  223.     struct mem_header *memScanP;
  224.  
  225.     for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink)
  226.         ValidateMemory (memScanP, file, line, FALSE);
  227.  
  228. }
  229.  
  230. /*
  231.  *----------------------------------------------------------------------
  232.  *
  233.  * Tcl_DumpActiveMemory --
  234.  *     Displays all allocated memory to stderr.
  235.  *
  236.  * Results:
  237.  *     Return TCL_ERROR if an error accessing the file occures, `errno' 
  238.  *     will have the file error number left in it.
  239.  *----------------------------------------------------------------------
  240.  */
  241. int
  242. Tcl_DumpActiveMemory (fileName)
  243.     char *fileName;
  244. {
  245.     FILE              *fileP;
  246.     struct mem_header *memScanP;
  247.     char              *address;
  248.  
  249.     fileP = fopen(fileName, "w");
  250.     if (fileP == NULL)
  251.         return TCL_ERROR;
  252.  
  253.     for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
  254.         address = &memScanP->body [0];
  255.         fprintf (fileP, "%8lx - %8lx  %7ld @ %s %d %s",
  256.         (long unsigned int) address,
  257.                  (long unsigned int) address + memScanP->length - 1,
  258.          memScanP->length, memScanP->file, memScanP->line,
  259.          (memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
  260.     (void) fputc('\n', fileP);
  261.     }
  262.     fclose (fileP);
  263.     return TCL_OK;
  264. }
  265.  
  266. /*
  267.  *----------------------------------------------------------------------
  268.  *
  269.  * Tcl_DbCkalloc - debugging ckalloc
  270.  *
  271.  *        Allocate the requested amount of space plus some extra for
  272.  *        guard bands at both ends of the request, plus a size, panicing 
  273.  *        if there isn't enough space, then write in the guard bands
  274.  *        and return the address of the space in the middle that the
  275.  *        user asked for.
  276.  *
  277.  *        The second and third arguments are file and line, these contain
  278.  *        the filename and line number corresponding to the caller.
  279.  *        These are sent by the ckalloc macro; it uses the preprocessor
  280.  *        autodefines __FILE__ and __LINE__.
  281.  *
  282.  *----------------------------------------------------------------------
  283.  */
  284. char *
  285. Tcl_DbCkalloc(size, file, line)
  286.     unsigned int size;
  287.     char        *file;
  288.     int          line;
  289. {
  290.     struct mem_header *result;
  291.  
  292.     if (validate_memory)
  293.         Tcl_ValidateAllMemory (file, line);
  294.  
  295.     result = (struct mem_header *)malloc((unsigned)size + 
  296.                               sizeof(struct mem_header) + HIGH_GUARD_SIZE);
  297.     if (result == NULL) {
  298.         fflush(stdout);
  299.         dump_memory_info(stderr);
  300.         panic("unable to alloc %d bytes, %s line %d", size, file, 
  301.               line);
  302.     }
  303.  
  304.     /*
  305.      * Fill in guard zones and size.  Also initialize the contents of
  306.      * the block with bogus bytes to detect uses of initialized data.
  307.      * Link into allocated list.
  308.      */
  309.     if (init_malloced_bodies) {
  310.         memset ((VOID *) result, GUARD_VALUE,
  311.         size + sizeof(struct mem_header) + HIGH_GUARD_SIZE);
  312.     } else {
  313.     memset ((char *) result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
  314.     memset (result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
  315.     }
  316.     result->length = size;
  317.     result->tagPtr = curTagPtr;
  318.     if (curTagPtr != NULL) {
  319.     curTagPtr->refCount++;
  320.     }
  321.     result->file = file;
  322.     result->line = line;
  323.     result->flink = allocHead;
  324.     result->blink = NULL;
  325.     if (allocHead != NULL)
  326.         allocHead->blink = result;
  327.     allocHead = result;
  328.  
  329.     total_mallocs++;
  330.     if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
  331.         (void) fflush(stdout);
  332.         fprintf(stderr, "reached malloc trace enable point (%d)\n",
  333.                 total_mallocs);
  334.         fflush(stderr);
  335.         alloc_tracing = TRUE;
  336.         trace_on_at_malloc = 0;
  337.     }
  338.  
  339.     if (alloc_tracing)
  340.         fprintf(stderr,"ckalloc %lx %d %s %d\n",
  341.         (long unsigned int) result->body, size, file, line);
  342.  
  343.     if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
  344.         break_on_malloc = 0;
  345.         (void) fflush(stdout);
  346.         fprintf(stderr,"reached malloc break limit (%d)\n", 
  347.                 total_mallocs);
  348.         fprintf(stderr, "program will now enter C debugger\n");
  349.         (void) fflush(stderr);
  350.     abort();
  351.     }
  352.  
  353.     current_malloc_packets++;
  354.     if (current_malloc_packets > maximum_malloc_packets)
  355.         maximum_malloc_packets = current_malloc_packets;
  356.     current_bytes_malloced += size;
  357.     if (current_bytes_malloced > maximum_bytes_malloced)
  358.         maximum_bytes_malloced = current_bytes_malloced;
  359.  
  360.     return result->body;
  361. }
  362.  
  363. /*
  364.  *----------------------------------------------------------------------
  365.  *
  366.  * Tcl_DbCkfree - debugging ckfree
  367.  *
  368.  *        Verify that the low and high guards are intact, and if so
  369.  *        then free the buffer else panic.
  370.  *
  371.  *        The guards are erased after being checked to catch duplicate
  372.  *        frees.
  373.  *
  374.  *        The second and third arguments are file and line, these contain
  375.  *        the filename and line number corresponding to the caller.
  376.  *        These are sent by the ckfree macro; it uses the preprocessor
  377.  *        autodefines __FILE__ and __LINE__.
  378.  *
  379.  *----------------------------------------------------------------------
  380.  */
  381.  
  382. int
  383. Tcl_DbCkfree(ptr, file, line)
  384.     char *  ptr;
  385.     char     *file;
  386.     int       line;
  387. {
  388.     /*
  389.      * The following cast is *very* tricky.  Must convert the pointer
  390.      * to an integer before doing arithmetic on it, because otherwise
  391.      * the arithmetic will be done differently (and incorrectly) on
  392.      * word-addressed machines such as Crays (will subtract only bytes,
  393.      * even though BODY_OFFSET is in words on these machines).
  394.      */
  395.  
  396.     struct mem_header *memp = (struct mem_header *)
  397.         (((unsigned long) ptr) - BODY_OFFSET);
  398.  
  399.     if (alloc_tracing)
  400.         fprintf(stderr, "ckfree %lx %ld %s %d\n",
  401.         (long unsigned int) memp->body, memp->length, file, line);
  402.  
  403.     if (validate_memory)
  404.         Tcl_ValidateAllMemory (file, line);
  405.  
  406.     ValidateMemory (memp, file, line, TRUE);
  407.     if (init_malloced_bodies) {
  408.     memset((VOID *) ptr, GUARD_VALUE, (size_t) memp->length);
  409.     }
  410.  
  411.     total_frees++;
  412.     current_malloc_packets--;
  413.     current_bytes_malloced -= memp->length;
  414.  
  415.     if (memp->tagPtr != NULL) {
  416.     memp->tagPtr->refCount--;
  417.     if ((memp->tagPtr->refCount == 0) && (curTagPtr != memp->tagPtr)) {
  418.         free((char *) memp->tagPtr);
  419.     }
  420.     }
  421.  
  422.     /*
  423.      * Delink from allocated list
  424.      */
  425.     if (memp->flink != NULL)
  426.         memp->flink->blink = memp->blink;
  427.     if (memp->blink != NULL)
  428.         memp->blink->flink = memp->flink;
  429.     if (allocHead == memp)
  430.         allocHead = memp->flink;
  431.     free((char *) memp);
  432.     return 0;
  433. }
  434.  
  435. /*
  436.  *--------------------------------------------------------------------
  437.  *
  438.  * Tcl_DbCkrealloc - debugging ckrealloc
  439.  *
  440.  *    Reallocate a chunk of memory by allocating a new one of the
  441.  *    right size, copying the old data to the new location, and then
  442.  *    freeing the old memory space, using all the memory checking
  443.  *    features of this package.
  444.  *
  445.  *--------------------------------------------------------------------
  446.  */
  447. char *
  448. Tcl_DbCkrealloc(ptr, size, file, line)
  449.     char *ptr;
  450.     unsigned int size;
  451.     char *file;
  452.     int line;
  453. {
  454.     char *new;
  455.     unsigned int copySize;
  456.  
  457.     /*
  458.      * See comment from Tcl_DbCkfree before you change the following
  459.      * line.
  460.      */
  461.  
  462.     struct mem_header *memp = (struct mem_header *)
  463.         (((unsigned long) ptr) - BODY_OFFSET);
  464.  
  465.     copySize = size;
  466.     if (copySize > memp->length) {
  467.     copySize = memp->length;
  468.     }
  469.     new = Tcl_DbCkalloc(size, file, line);
  470.     memcpy((VOID *) new, (VOID *) ptr, (size_t) copySize);
  471.     Tcl_DbCkfree(ptr, file, line);
  472.     return(new);
  473. }
  474.  
  475. /*
  476.  *----------------------------------------------------------------------
  477.  *
  478.  * MemoryCmd --
  479.  *     Implements the TCL memory command:
  480.  *       memory info
  481.  *       memory display
  482.  *       break_on_malloc count
  483.  *       trace_on_at_malloc count
  484.  *       trace on|off
  485.  *       validate on|off
  486.  *
  487.  * Results:
  488.  *     Standard TCL results.
  489.  *
  490.  *----------------------------------------------------------------------
  491.  */
  492.     /* ARGSUSED */
  493. static int
  494. MemoryCmd (clientData, interp, argc, argv)
  495.     ClientData  clientData;
  496.     Tcl_Interp *interp;
  497.     int         argc;
  498.     char      **argv;
  499. {
  500.     char *fileName;
  501.     Tcl_DString buffer;
  502.     int result;
  503.  
  504.     if (argc < 2) {
  505.     Tcl_AppendResult(interp, "wrong # args: should be \"",
  506.         argv[0], " option [args..]\"", (char *) NULL);
  507.     return TCL_ERROR;
  508.     }
  509.  
  510.     if (strcmp(argv[1],"active") == 0) {
  511.         if (argc != 3) {
  512.         Tcl_AppendResult(interp, "wrong # args: should be \"",
  513.             argv[0], " active file\"", (char *) NULL);
  514.         return TCL_ERROR;
  515.     }
  516.     fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
  517.     if (fileName == NULL) {
  518.         return TCL_ERROR;
  519.     }
  520.     result = Tcl_DumpActiveMemory (fileName);
  521.     Tcl_DStringFree(&buffer);
  522.     if (result != TCL_OK) {
  523.         Tcl_AppendResult(interp, "error accessing ", argv[2], 
  524.             (char *) NULL);
  525.         return TCL_ERROR;
  526.     }
  527.     return TCL_OK;
  528.     }
  529.     if (strcmp(argv[1],"break_on_malloc") == 0) {
  530.         if (argc != 3) 
  531.             goto argError;
  532.         if (Tcl_GetInt(interp, argv[2], &break_on_malloc) != TCL_OK)
  533.                 return TCL_ERROR;
  534.         return TCL_OK;
  535.     }
  536.     if (strcmp(argv[1],"info") == 0) {
  537.         dump_memory_info(stdout);
  538.         return TCL_OK;
  539.     }
  540.     if (strcmp(argv[1],"init") == 0) {
  541.         if (argc != 3)
  542.             goto bad_suboption;
  543.         init_malloced_bodies = (strcmp(argv[2],"on") == 0);
  544.         return TCL_OK;
  545.     }
  546.     if (strcmp(argv[1],"tag") == 0) {
  547.     if (argc != 3) {
  548.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  549.             " tag string\"", (char *) NULL);
  550.         return TCL_ERROR;
  551.     }
  552.     if ((curTagPtr != NULL) && (curTagPtr->refCount == 0)) {
  553.         free((char *) curTagPtr);
  554.     }
  555.     curTagPtr = (MemTag *) malloc(TAG_SIZE(strlen(argv[2])));
  556.     curTagPtr->refCount = 0;
  557.     strcpy(curTagPtr->string, argv[2]);
  558.     return TCL_OK;
  559.     }
  560.     if (strcmp(argv[1],"trace") == 0) {
  561.         if (argc != 3) 
  562.             goto bad_suboption;
  563.         alloc_tracing = (strcmp(argv[2],"on") == 0);
  564.         return TCL_OK;
  565.     }
  566.  
  567.     if (strcmp(argv[1],"trace_on_at_malloc") == 0) {
  568.         if (argc != 3) 
  569.             goto argError;
  570.         if (Tcl_GetInt(interp, argv[2], &trace_on_at_malloc) != TCL_OK)
  571.                 return TCL_ERROR;
  572.          return TCL_OK;
  573.     }
  574.     if (strcmp(argv[1],"validate") == 0) {
  575.         if (argc != 3)
  576.              goto bad_suboption;
  577.         validate_memory = (strcmp(argv[2],"on") == 0);
  578.         return TCL_OK;
  579.     }
  580.  
  581.     Tcl_AppendResult(interp, "bad option \"", argv[1],
  582.         "\": should be active, break_on_malloc, info, init, ",
  583.         "tag, trace, trace_on_at_malloc, or validate", (char *) NULL);
  584.     return TCL_ERROR;
  585.  
  586. argError:
  587.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  588.         " ", argv[1], " count\"", (char *) NULL);
  589.     return TCL_ERROR;
  590.  
  591. bad_suboption:
  592.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  593.         " ", argv[1], " on|off\"", (char *) NULL);
  594.     return TCL_ERROR;
  595. }
  596.  
  597. /*
  598.  *----------------------------------------------------------------------
  599.  *
  600.  * Tcl_InitMemory --
  601.  *     Initialize the memory command.
  602.  *
  603.  *----------------------------------------------------------------------
  604.  */
  605. void
  606. Tcl_InitMemory(interp)
  607.     Tcl_Interp *interp;
  608. {
  609. Tcl_CreateCommand (interp, "memory", MemoryCmd, (ClientData) NULL, 
  610.                   (Tcl_CmdDeleteProc *) NULL);
  611. }
  612.  
  613. #else
  614.  
  615.  
  616. /*
  617.  *----------------------------------------------------------------------
  618.  *
  619.  * Tcl_Ckalloc --
  620.  *     Interface to malloc when TCL_MEM_DEBUG is disabled.  It does check
  621.  *     that memory was actually allocated.
  622.  *
  623.  *----------------------------------------------------------------------
  624.  */
  625. VOID *
  626. Tcl_Ckalloc (size)
  627.     unsigned int size;
  628. {
  629.         char *result;
  630.  
  631.         result = malloc(size);
  632.         if (result == NULL) 
  633.                 panic("unable to alloc %d bytes", size);
  634.         return result;
  635. }
  636.  
  637.  
  638. char *
  639. Tcl_DbCkalloc(size, file, line)
  640.     unsigned int size;
  641.     char        *file;
  642.     int          line;
  643. {
  644.     char *result;
  645.  
  646.     result = (char *) malloc(size);
  647.  
  648.     if (result == NULL) {
  649.         fflush(stdout);
  650.         panic("unable to alloc %d bytes, %s line %d", size, file, 
  651.               line);
  652.     }
  653.     return result;
  654. }
  655.  
  656. char *
  657. Tcl_DbCkrealloc(ptr, size, file, line)
  658.     char *ptr;
  659.     unsigned int size;
  660.     char *file;
  661.     int line;
  662. {
  663.     char *result;
  664.  
  665.     result = (char *) realloc(ptr, size);
  666.  
  667.     if (result == NULL) {
  668.         fflush(stdout);
  669.         panic("unable to realloc %d bytes, %s line %d", size, file, 
  670.               line);
  671.     }
  672.     return result;
  673. }
  674. /*
  675.  *----------------------------------------------------------------------
  676.  *
  677.  * TckCkfree --
  678.  *     Interface to free when TCL_MEM_DEBUG is disabled.  Done here rather
  679.  *     in the macro to keep some modules from being compiled with 
  680.  *     TCL_MEM_DEBUG enabled and some with it disabled.
  681.  *
  682.  *----------------------------------------------------------------------
  683.  */
  684. void
  685. Tcl_Ckfree (ptr)
  686.     char *ptr;
  687. {
  688.         free (ptr);
  689. }
  690.  
  691. int
  692. Tcl_DbCkfree(ptr, file, line)
  693.     char *  ptr;
  694.     char     *file;
  695.     int       line;
  696. {
  697.     free (ptr);
  698.     return 0;
  699. }
  700.  
  701. /*
  702.  *----------------------------------------------------------------------
  703.  *
  704.  * Tcl_InitMemory --
  705.  *     Dummy initialization for memory command, which is only available 
  706.  *     if TCL_MEM_DEBUG is on.
  707.  *
  708.  *----------------------------------------------------------------------
  709.  */
  710.     /* ARGSUSED */
  711. void
  712. Tcl_InitMemory(interp)
  713.     Tcl_Interp *interp;
  714. {
  715. }
  716.  
  717. #undef Tcl_DumpActiveMemory
  718. #undef Tcl_ValidateAllMemory
  719.  
  720. extern int        Tcl_DumpActiveMemory _ANSI_ARGS_((char *fileName));
  721. extern void        Tcl_ValidateAllMemory _ANSI_ARGS_((char *file,
  722.                 int line));
  723.  
  724. int
  725. Tcl_DumpActiveMemory (fileName)
  726.     char *fileName;
  727. {
  728.     return TCL_OK;
  729. }
  730.  
  731. void
  732. Tcl_ValidateAllMemory (file, line)
  733.     char  *file;
  734.     int    line;
  735. {
  736. }
  737.  
  738. #endif
  739.