home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dbmalloc.zip / malloc.c < prev    next >
C/C++ Source or Header  |  1993-07-27  |  37KB  |  1,719 lines

  1. /*
  2.  * (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
  3.  *
  4.  * This software may be distributed freely as long as the following conditions
  5.  * are met:
  6.  *         * the distribution, or any derivative thereof, may not be
  7.  *          included as part of a commercial product
  8.  *        * full source code is provided including this copyright
  9.  *        * there is no charge for the software itself (there may be
  10.  *          a minimal charge for the copying or distribution effort)
  11.  *        * this copyright notice is not modified or removed from any
  12.  *          source file
  13.  */
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <sys/types.h>
  17. #include <signal.h>
  18.  
  19. #include "sysdefs.h"
  20.  
  21. #ifdef NEED_WAIT
  22. #include <sys/wait.h>
  23. #endif
  24.  
  25. /* 
  26.  * make sure mallocin.h doesn't include sys/types.h since we have already
  27.  * included it.
  28.  */
  29. #ifndef SYS_TYPES_H_INCLUDED
  30. #define SYS_TYPES_H_INCLUDED 1
  31. #endif
  32.  
  33. #include "mallocin.h"
  34. #include "tostring.h"
  35.  
  36. #include "debug.h"
  37.  
  38. #ifndef lint
  39. static char rcs_hdr[] = "$Id: malloc.c,v 1.43 1992/09/03 22:24:33 cpcahil Exp $";
  40. #endif
  41.  
  42. int          in_malloc_code;
  43. SIZETYPE      malloc_align;
  44. int          malloc_boundsize = M_DFLT_BSIZE;
  45. DATATYPE    * malloc_data_start;
  46. DATATYPE    * malloc_data_end;
  47. struct mlist     * malloc_end;
  48. int          malloc_errfd = 2;
  49. int          malloc_errno;
  50. int          malloc_fatal_level = M_HANDLE_ABORT;
  51. int          malloc_fill;
  52. int          malloc_fillbyte = M_DFLT_FILL;
  53. int          malloc_freebyte = M_DFLT_FREE_FILL;
  54. struct mlist    * malloc_freelist;
  55. long          malloc_hist_id;
  56. int          malloc_opts = MOPT_MFILL  | MOPT_FFILL | MOPT_DFILL | 
  57.                 MOPT_CKDATA | MOPT_REUSE | MOPT_FREEMARK |
  58.                 MOPT_ZERO;
  59. int          malloc_round = M_RND-1;
  60. struct mlist      malloc_start;
  61. int          malloc_warn_level;
  62.  
  63. /*
  64.  * perform string copy, but make sure that we don't go beyond the end of the
  65.  * buffer (leaving room for trailing info (5 bytes) like the return and a null
  66.  */
  67. #define COPY(s,t,buf,len)    while( (*(s) = *((t)++) ) \
  68.                        && ( (s) < ((buf)+(len)-5) ) ) { (s)++; }
  69.  
  70. #define DUMP_PTR    0
  71. #define DUMP_NEXT    1
  72. #define DUMP_PREV    2
  73.  
  74. #define ERRBUFSIZE    1024
  75.  
  76. /*
  77.  * Function:    malloc()
  78.  *
  79.  * Purpose:    low-level interface to the debug malloc lib.  This should only
  80.  *         be called from code that is not recompilable.  The recompilable
  81.  *        code should include malloc.h and therefore its calls to malloc
  82.  *        will be #defined to be calls to debug_malloc with the
  83.  *        appropriate arguments.
  84.  *
  85.  * Arguments:    size    - size of data area needed
  86.  *
  87.  * Returns:    whatever debug_malloc returns.
  88.  *
  89.  * Narrative:
  90.  *
  91.  */
  92. DATATYPE *
  93. malloc(size)
  94.     SIZETYPE      size;
  95. {
  96.     return( debug_malloc(NULL,-1,size) );
  97. }
  98.  
  99. /*
  100.  * Function:    debug_malloc()
  101.  *
  102.  * Purpose:    the real memory allocator
  103.  *
  104.  * Arguments:    size    - size of data area needed
  105.  *
  106.  * Returns:    pointer to allocated area, or NULL if unable
  107.  *        to allocate addtional data.
  108.  *
  109.  * Narrative:
  110.  *
  111.  */
  112. DATATYPE *
  113. debug_malloc(file,line,size)
  114.     CONST char    * file;
  115.     int          line;
  116.     SIZETYPE      size;
  117. {
  118.     static IDTYPE      call_counter;
  119.  
  120.     /*
  121.      * increment the counter for the number of calls to this func.
  122.      */
  123.     call_counter++;
  124.  
  125.     return( DBFmalloc("malloc",M_T_MALLOC,call_counter,file,line,size) );
  126.  
  127. } /* debug_malloc(... */
  128.  
  129. char *
  130. DBFmalloc(func,type,call_counter,file,line,size)
  131.     CONST char        * func;
  132.     int              type;
  133.     IDTYPE              call_counter;
  134.     CONST char        * file;
  135.     int              line;
  136.     SIZETYPE          size;
  137. {
  138.     char            * cptr;
  139.     SIZETYPE          fill;
  140.     SIZETYPE          fit = 0;
  141.     SIZETYPE          lastfit;
  142.     struct mlist        * lastptr;
  143.     SIZETYPE          need;
  144.     int              newmalloc = 0;
  145.     register struct mlist    * oldptr;
  146.     register struct mlist    * ptr;
  147.     SIZETYPE          r_size;
  148.  
  149.     MALLOC_INIT();
  150.  
  151.     /*
  152.      * If malloc chain checking is on, go do it.
  153.      */
  154.     if( malloc_opts & MOPT_CKCHAIN )
  155.     {
  156.         VOIDCAST DBFmalloc_chain_check(func,file,line,1);
  157.     }
  158.  
  159.     /*
  160.      * if the user wants to be warned about zero length mallocs, do so
  161.      */
  162.     if( ((malloc_opts & MOPT_ZERO) != 0) && (size == 0) )
  163.     {
  164.         malloc_errno = M_CODE_ZERO_ALLOC;
  165.         malloc_warning(func,file,line,(struct mlist *) NULL);
  166.     }
  167.  
  168.     /*
  169.      * save the original requested size;
  170.      */
  171.     r_size = size;
  172.  
  173.     /*
  174.      * always make sure there is at least on extra byte in the malloc
  175.      * area so that we can verify that the user does not overrun the
  176.      * data area.
  177.      */
  178.     size += malloc_boundsize;
  179.  
  180.     /*
  181.      * Now look for a free area of memory of size bytes...
  182.      */
  183.     oldptr = NULL;
  184.     ptr = malloc_freelist;
  185.  
  186.     /*
  187.      * if low fragmentation has been turned on, look for a best fit
  188.      * segment (otherwise, for performance reasons, we will look for
  189.      * a first fit)
  190.      */
  191.     if( malloc_opts & MOPT_LOWFRAG )
  192.     {  
  193.         lastfit = -1;
  194.         lastptr = NULL;
  195.         /*
  196.          * until we run out of segments, or find an exact match
  197.          */
  198.         for(; (ptr != NULL) && (lastfit != 0); ptr=ptr->freenext)
  199.         {
  200.             /*
  201.              * quick check to make sure our free-list hasn't been
  202.              * broken.
  203.              */
  204.             if((oldptr != NULL) && (ptr->freeprev != oldptr) )
  205.             {
  206.                 malloc_errno = M_CODE_CHAIN_BROKE;
  207.                 malloc_fatal(func,file,line,oldptr);
  208.                 return(NULL);
  209.             }
  210.  
  211.             /*
  212.              * if this is to be an aligned segment and the pointer
  213.              * is not already aligned on the correct boundry
  214.              */
  215.             if(    (type == M_T_ALIGNED)
  216.                 && ((((SIZETYPE)ptr->data)&(malloc_align-1)) != 0)    
  217.                 && (ptr->s.size > size ) )
  218.             {
  219.                 fit = AlignedFit(ptr,malloc_align,size);
  220.             }
  221.             /*
  222.              * else if this segment is big enough for our needs
  223.              */
  224.             else if( ptr->s.size > size )
  225.             {
  226.                 /*
  227.                   * calculate how close we fit. 
  228.                  */
  229.                 fit = ptr->s.size - size;
  230.             }
  231.             else
  232.             {
  233.                 fit = -1;
  234.             }
  235.  
  236.             if( fit == 0 )
  237.             {
  238.                 break;
  239.             }
  240.             else if( fit > 0 )
  241.             {    
  242.                 /*
  243.                   * if this is the first one we fit int, or
  244.                  * if this a closer fit
  245.                   */
  246.                 if( (lastfit == -1) || (fit < lastfit) )
  247.                 {
  248.                     lastptr = ptr;
  249.                     lastfit = fit;
  250.                 }
  251.             }
  252.             oldptr = ptr;
  253.  
  254.         } /* for(... */
  255.  
  256.         /*
  257.          * if we found an entry, use it
  258.          */
  259.         if( (fit != 0) && (lastptr != NULL) )
  260.         {
  261.             ptr = lastptr;
  262.         }
  263.     }
  264.     else
  265.     {
  266.         /*
  267.          * until we run out of free entries, or find an entry that has
  268.          * enough room
  269.          */
  270.         for( ; (ptr != NULL) ; ptr=ptr->freenext)
  271.         {
  272.             if((oldptr != NULL) && (ptr->freeprev != oldptr) )
  273.             {
  274.                 malloc_errno = M_CODE_CHAIN_BROKE;
  275.                 malloc_fatal(func,file,line,oldptr);
  276.                 return(NULL);
  277.             }
  278.  
  279.             /*
  280.              * if this is an aligned request and it isn't already
  281.              * aligned and it appears to be big enough
  282.              */
  283.             if(    (type == M_T_ALIGNED)
  284.                 && ((((SIZETYPE)ptr->data)&(malloc_align-1)) != 0)    
  285.                 && (ptr->s.size >= size ) )
  286.             {
  287.                 /*
  288.                  * if an aligned segment does fit within the
  289.                  * specified segment, break out of loop
  290.                  */
  291.                 if( AlignedFit(ptr,malloc_align,size) >= 0)
  292.                 {
  293.                     break;
  294.                 }
  295.             }
  296.             /*
  297.              * else if this segment is big enough
  298.              */
  299.             else if( ptr->s.size >= size )
  300.             {
  301.                 break;
  302.             }
  303.  
  304.             oldptr = ptr;
  305.  
  306.         } /* for(... */
  307.     }
  308.  
  309.     /*
  310.      * If ptr is null, we have run out of memory and must sbrk more
  311.      */
  312.     if( ptr == NULL )
  313.     {
  314.         /*
  315.          * calculate how much space we need.  If they ask for more
  316.          * than 100k, get exactly what they want.  Otherwise get
  317.          * twice what they ask for so that we are ready for the
  318.          * next allocation they ask for
  319.          */
  320.         need = size + sizeof(struct mlist);
  321.         if( size < 100*1024 )
  322.         {
  323.             need <<= 1;
  324.         }
  325.  
  326.         /*
  327.          * figure out any additional bytes we might need in order to
  328.          * obtain the correct alignment
  329.          */
  330.         cptr = sbrk(0);
  331.  
  332.         fill = ((SIZETYPE)cptr) & (M_RND-1);
  333.         if( fill )
  334.         {
  335.             fill = M_RND - fill;
  336.         }
  337.  
  338.         /*
  339.          * if this is an aligned request, then make sure we have 
  340.          * enough room for the aligment 
  341.          */
  342.         if( type == M_T_ALIGNED )
  343.         {
  344.             cptr += fill + M_SIZE;
  345.  
  346.             /*
  347.              * if this new value will not be on a valid 
  348.              * alignment, add malloc_align + sizeof(struct mlist)
  349.              * to the amount of space that we need to make sure 
  350.              * that we have enough for the aligned allocation.
  351.              */
  352.             if( (((SIZETYPE)cptr) & (malloc_align-1)) != 0 )
  353.             {
  354.                 need += malloc_align + sizeof(struct mlist);
  355.             }
  356.         }
  357.  
  358.         /*
  359.          * if the need is less than the minimum block size,
  360.          *     get the minimum block size
  361.           */
  362.         if( need < M_BLOCKSIZE )
  363.         {
  364.             need = M_BLOCKSIZE;
  365.         }
  366.         /*
  367.          * else if the need is not an even multiple of the block size,
  368.          *     round it up to an even multiple
  369.          */
  370.         else if( need & (M_BLOCKSIZE-1) )
  371.         {
  372.             need &= ~(M_BLOCKSIZE-1);
  373.             need += M_BLOCKSIZE;
  374.         }
  375.  
  376.         /*
  377.          * add in that fill space we determined before so that after
  378.          * this allocation, future allocations should be alligned
  379.          * appropriately
  380.           */
  381.         need += fill;
  382.  
  383.         /*
  384.          * get the space from the os
  385.           */
  386.         cptr = sbrk((int)need);
  387.  
  388.         /*
  389.          * if we failed to get the space, tell the user about it
  390.          */
  391.         if( cptr == (char *) -1 )
  392.         {
  393.             malloc_errno = M_CODE_NOMORE_MEM;
  394.             malloc_fatal(func,file,line, (struct mlist *)NULL);
  395.             return(NULL);
  396.         }
  397.  
  398.         /*
  399.          * make sure that the pointer returned by sbrk is on the
  400.          * correct alignment boundry.
  401.          */
  402.         DEBUG2(10,"sbrk() returned 0x%lx, skipping %d bytes to align",
  403.             cptr, fill);
  404.         ptr = (struct mlist *) (cptr + fill);
  405.  
  406.         /*
  407.          * readjust the amount of space we obtained to reflect the fill
  408.          * area we are skipping.
  409.          */
  410.         need -= fill;
  411.     
  412.         /*
  413.          * mark our end point
  414.          */
  415.         malloc_data_end = sbrk((int)0);
  416.  
  417.         /*
  418.          * hook the new segment into the malloc chain
  419.          */
  420.         InitMlist(ptr,M_T_SPLIT);
  421.         ptr->prev     = malloc_end;
  422.         ptr->s.size   = need - M_SIZE;
  423.         ptr->r_size   = ptr->s.size;
  424.     
  425.         malloc_end->next = ptr;
  426.         malloc_end = ptr;
  427.  
  428.         newmalloc = 1;
  429.  
  430.     } /* if( ptr ==... */
  431.     /*
  432.      * else we found a free slot that has enough room,
  433.      *    so take it off the free list
  434.      */
  435.     else
  436.     {
  437.         /*
  438.          * if this module is already in use
  439.          */
  440.         if( (ptr->flag & M_INUSE) != 0 )
  441.         {
  442.             malloc_errno = M_CODE_FREELIST_BAD;
  443.             malloc_fatal(func,file,line,ptr);
  444.             return(NULL);
  445.         }
  446.         
  447.     }
  448.         
  449.  
  450.     /*
  451.      * Now ptr points to a memory location that can store
  452.      * this data, so lets go to work.
  453.      */
  454.  
  455.     /*
  456.      * if this is an aligned request and the data is not already on the
  457.      * correct alignment
  458.      */
  459.     if(    (type == M_T_ALIGNED)
  460.         && ((((SIZETYPE)(ptr->data)) & (malloc_align-1)) != 0) )
  461.     {
  462.         /*
  463.          * if this is a new allocation, we have to check to see if
  464.          * the new segment can be joined to the previous segment 
  465.          * before we pull out the aligned segment.  This is required
  466.          * since the previous segment may be free and we would end
  467.          * up with two adjacent free segments if we didn't do this.
  468.          */
  469.         if( newmalloc )
  470.         {
  471.             /*
  472.              * if there is a previous segment
  473.              */
  474.             if( (oldptr = ptr->prev) != NULL )
  475.             {
  476.                 /*
  477.                  * attempt to join the previous segment with
  478.                  * the new segment (if the prev seg is free).
  479.                  */
  480.                 malloc_join(ptr->prev,ptr, NOTINUSE, DOFILL);
  481.  
  482.                 /*
  483.                  * if they were joined, use the new pointer.
  484.                  */
  485.                 if( oldptr->next != ptr )
  486.                 {
  487.                     ptr = oldptr;
  488.                 }
  489.             }
  490.  
  491.             /*
  492.              * if this segment did not get joined to a previous
  493.              * segment, add the new segment to the free list.
  494.              */
  495.             if( oldptr != ptr )
  496.             {
  497.                 malloc_freeseg(M_FREE_ADD, ptr);
  498.             }
  499.         }
  500.  
  501.         /*
  502.          * break out the new segment.  Note that AlignedMakeSeg depends
  503.          * upon the fact that ptr points to a segment that will have
  504.          * enough room for the alignment within the segment.
  505.          */
  506.         ptr = AlignedMakeSeg(ptr,malloc_align);
  507.     }
  508.     /*
  509.      * else we are going to use the indicated segment, so let's remove it
  510.      * from the free list.
  511.      */
  512.     else if( ! newmalloc )
  513.     {
  514.         /*
  515.          * remove the segment from the free list
  516.          */
  517.         malloc_freeseg(M_FREE_REMOVE,ptr);
  518.     }
  519.  
  520.     /*
  521.      * for the purpose of splitting, have the requested size appear to be
  522.      * the same as the actualsize
  523.      */
  524.     ptr->r_size = size;        /* save requested size    */
  525.  
  526.     /*
  527.      * split off unneeded data area in this block, if possible...
  528.      */
  529.     malloc_split(ptr);
  530.  
  531.     /*
  532.      * set inuse flag after split, so that the split routine knows that
  533.      * this module can see that the module was free and therefore won't 
  534.      * re-fill it if not necessary.
  535.      */
  536.     ptr->flag |= M_INUSE;
  537.  
  538.     /*
  539.      * save the real requested size
  540.      */
  541.     ptr->r_size = r_size;
  542.  
  543.     /*
  544.      * fill in the buffer areas (and possibly the data area) in
  545.      * order to track underflow, overflow, and uninitialized use
  546.      */
  547.     FILLDATA(ptr, FILL_MALLOC, (SIZETYPE)0, (struct mlist *) NULL);
  548.  
  549.     /*
  550.      * store the identification information
  551.      */
  552.     ptr->file      = file;
  553.     ptr->line      = line;
  554.     ptr->id        = call_counter;
  555.     ptr->hist_id   = malloc_hist_id++;
  556.     ptr->stack     = StackCurrent();
  557.     ptr->freestack = NULL;
  558.     ptr->freenext  = NULL;
  559.     ptr->freeprev  = NULL;
  560.  
  561.     SETTYPE(ptr,type);
  562.  
  563.     /*
  564.      * return the pointer to the data area for the user.
  565.      */
  566.     return( ptr->data );
  567.  
  568.  
  569. } /* DBFmalloc(... */
  570.  
  571. /*
  572.  * Function:    malloc_split()
  573.  *
  574.  * Purpose:    to split a malloc segment if there is enough room at the
  575.  *        end of the segment that isn't being used
  576.  *
  577.  * Arguments:    ptr    - pointer to segment to split
  578.  *
  579.  * Returns:    nothing of any use.
  580.  *
  581.  * Narrative:
  582.  *        get the needed size of the module
  583.  *         round the size up to appropriat boundry
  584.  *        calculate amount of left over space
  585.  *        if there is enough left over space
  586.  *            create new malloc block out of remainder
  587.  *            if next block is free 
  588.  *            join the two blocks together
  589.  *            fill new empty block with free space filler
  590.  *             re-adjust pointers and size of current malloc block
  591.  *        
  592.  *        
  593.  *
  594.  * Mod History:    
  595.  *   90/01/27    cpcahil        Initial revision.
  596.  */
  597. VOIDTYPE
  598. malloc_split(ptr)
  599.     struct mlist        * ptr;
  600. {
  601.     SIZETYPE          rest;
  602.     SIZETYPE          size;
  603.     struct mlist        * tptr;
  604.     static int          call_counter;
  605.  
  606.     size = ptr->r_size;
  607.  
  608.     /*
  609.      * roundup size to the appropriate boundry
  610.      */
  611.     M_ROUNDUP(size);
  612.  
  613.     /*
  614.      * figure out how much room is left in the array.
  615.      * if there is enough room, create a new mlist 
  616.      *     structure there.
  617.      */
  618.     if( ptr->s.size > size )
  619.     {
  620.         rest = ptr->s.size - size;
  621.     }
  622.     else
  623.     {
  624.         rest = 0;
  625.     }
  626.  
  627.     /*
  628.      * if there is at least enough room to create another malloc block
  629.      */
  630.     if( rest > sizeof(struct mlist) )
  631.     {
  632.         tptr = (struct mlist *) (ptr->data+size);
  633.         tptr->file  = NULL;
  634.         tptr->ffile  = NULL;
  635.         tptr->stack = NULL;
  636.         tptr->prev  = ptr;
  637.         tptr->next  = ptr->next;
  638.         tptr->flag  = M_MAGIC;
  639.         SETTYPE(tptr,M_T_SPLIT);
  640.         tptr->s.size = rest - M_SIZE;
  641.         tptr->r_size = tptr->s.size;
  642.         tptr->freenext = NULL;
  643.         tptr->freeprev = NULL;
  644.         tptr->id    = ++call_counter;
  645.  
  646.         /*
  647.          * if this area is not already free-filled
  648.          */
  649.         if( ((ptr->flag& M_INUSE) != 0) || ((ptr->flag&M_FILLED) == 0) )
  650.         {
  651.             /*
  652.              * fill freed areas
  653.              */
  654.             FILLDATA(tptr,FILL_SPLIT,(SIZETYPE)0,
  655.                     (struct mlist *) NULL);
  656.         }
  657.         else if( (ptr->flag&M_INUSE) == 0 )
  658.         {
  659.             /*
  660.              * since it was already free-filled, just set the flag
  661.              */
  662.             tptr->flag |= M_FILLED;
  663.         }
  664.  
  665.         /*
  666.          * If possible, join this segment with the next one
  667.          */
  668.         malloc_join(tptr, tptr->next,NOTINUSE,DOFILL);
  669.  
  670.         if( tptr->next )
  671.         {
  672.             tptr->next->prev = tptr;
  673.         }
  674.  
  675.         ptr->next = tptr;
  676.         ptr->s.size = size;
  677.  
  678.         if( malloc_end == ptr )
  679.         {
  680.             malloc_end = tptr;
  681.         }
  682.  
  683.         /*
  684.          * add the new segment to the free list
  685.          */
  686.         malloc_freeseg(M_FREE_ADD,tptr);
  687.  
  688.     }
  689.  
  690. } /* malloc_split(... */
  691.  
  692. /*
  693.  * Function:    malloc_join()
  694.  *
  695.  * Purpose:    to join two malloc segments together (if possible)
  696.  *
  697.  * Arguments:    ptr    - pointer to segment to join to.
  698.  *         nextptr    - pointer to next segment to join to ptr.
  699.  *
  700.  * Returns:    nothing of any values.
  701.  *
  702.  * Narrative:
  703.  *
  704.  * Mod History:    
  705.  *   90/01/27    cpcahil        Initial revision.
  706.  */
  707. VOIDTYPE
  708. malloc_join(ptr,nextptr, inuse_override, fill_flag)
  709.     struct mlist    * ptr;
  710.     struct mlist    * nextptr;
  711.     int          inuse_override;
  712.     int          fill_flag;
  713. {
  714.     SIZETYPE      newsize;
  715.     SIZETYPE      start;
  716.  
  717.     /*
  718.      * if      the current segment exists
  719.      *    AND  it is not inuse (or if we don't care that it is inuse)
  720.       *    AND  the next segment exits
  721.      *    AND  it is not in use
  722.      *    AND  it is adjacent to this segment
  723.      *    THEN we can join the two together
  724.      */
  725.     if(    ( ptr != NULL )
  726.         && ((inuse_override & INUSEOK) || ! (ptr->flag & M_INUSE))
  727.         && ( nextptr != NULL )
  728.         && ((inuse_override&NEXTPTR_INUSEOK) || !(nextptr->flag & M_INUSE))
  729.         && ((ptr->data+ptr->s.size) == (char *) nextptr) )
  730.     {
  731.         /*
  732.          * remove nextptr from the freelist
  733.          */
  734.         malloc_freeseg(M_FREE_REMOVE,nextptr);
  735.  
  736.         /*
  737.          * if the segment was the end pointer
  738.          */
  739.         if( malloc_end == nextptr )
  740.         {
  741.             malloc_end = ptr;
  742.         }
  743.         ptr->next = nextptr->next;
  744.         newsize = nextptr->s.size + M_SIZE;
  745.  
  746.         start = ptr->s.size;
  747.  
  748.         ptr->s.size += newsize;
  749.         if( ptr->next )
  750.         {
  751.             ptr->next->prev = ptr;
  752.         }
  753.  
  754.         /*
  755.          * if the segment is free, set the requested size to include
  756.          * the requested size within the next segment.
  757.          */
  758.         if( ! (ptr->flag & M_INUSE) )
  759.         {
  760.             ptr->r_size = start + M_SIZE + nextptr->r_size;
  761.         }
  762.  
  763.         /*
  764.          * if we should fill in the segment
  765.           */
  766.         if( fill_flag )
  767.         {
  768.             FILLDATA(ptr,FILL_JOIN,start,nextptr);
  769.         }
  770.  
  771.     }
  772.  
  773. } /* malloc_join(... */
  774.  
  775.  
  776. /*
  777.  * The following mess is just to ensure that the versions of these functions in
  778.  * the current library are included (to make sure that we don't accidentaly get 
  779.  * the libc versions. (This is the lazy man's -u ld directive)
  780.  */
  781.  
  782. VOIDTYPE    (*malloc_void_funcs[])() =
  783. {
  784.     free,
  785. };
  786.  
  787. int        (*malloc_int_funcs[])() =
  788. {
  789.     strcmp,
  790.     memcmp,
  791. };
  792.  
  793. DATATYPE    * (*malloc_char_star_funcs[])() =
  794. {
  795.     _malloc,
  796.     debug_realloc,
  797.     debug_calloc,
  798. };
  799.  
  800. /*
  801.  * Function:    malloc_fatal()
  802.  *
  803.  * Purpose:    to display fatal error message and take approrpriate action
  804.  *
  805.  * Arguments:    funcname - name of function calling this routine
  806.  *        mptr     - pointer to malloc block associated with error
  807.  *
  808.  * Returns:    nothing of any value
  809.  *
  810.  * Narrative:
  811.  *
  812.  * Notes:    This routine does not make use of any libc functions to build
  813.  *        and/or disply the error message.  This is due to the fact that
  814.  *        we are probably at a point where malloc is having a real problem
  815.  *        and we don't want to call any function that may use malloc.
  816.  */
  817. VOIDTYPE
  818. malloc_fatal(funcname,file,line,mptr)
  819.     CONST char        * funcname;
  820.     CONST char        * file;
  821.     int              line;
  822.     CONST struct mlist    * mptr;
  823. {
  824.     char          errbuf[ERRBUFSIZE];
  825.     char        * s;
  826.     CONST char    * t;
  827.  
  828.     s = errbuf;
  829.     t = "MALLOC Fatal error from ";
  830.     COPY(s,t,errbuf,ERRBUFSIZE);
  831.  
  832.     t = funcname;
  833.     COPY(s,t,errbuf,ERRBUFSIZE);
  834.  
  835.     t = "()";
  836.     COPY(s,t,errbuf,ERRBUFSIZE);
  837.  
  838.     /*
  839.      * if we have a file and line number, show it
  840.       */
  841.     if( file != NULL )
  842.     {
  843.         t = " (called from ";
  844.         COPY(s,t,errbuf,ERRBUFSIZE);
  845.         
  846.         t = file;
  847.         COPY(s,t,errbuf,ERRBUFSIZE);
  848.  
  849.         t = " line ";
  850.         COPY(s,t,errbuf,ERRBUFSIZE);
  851.  
  852.         s += tostring(s,(ULONG)line,0,10,' ');
  853.  
  854.         *s++ = ')';
  855.  
  856.     }
  857.  
  858.     *s++ = ':';
  859.     *s++ = '\n';
  860.  
  861.     t = malloc_err_strings[malloc_errno];
  862.     COPY(s,t,errbuf,ERRBUFSIZE);
  863.  
  864.     *(s++) = '\n';
  865.  
  866.     if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf)) != (s-errbuf))
  867.     {
  868.         VOIDCAST write(2,"I/O error to error file\n",(WRTSIZE)24);
  869.         exit(110);
  870.     }
  871.  
  872.     /*
  873.      * if this error was associated with an identified malloc block,
  874.      * dump the malloc info for the block.
  875.      */
  876.     if( mptr )
  877.     {
  878.         malloc_dump_info_block(mptr,DUMP_PTR);
  879.     }
  880.  
  881.     malloc_err_handler(malloc_fatal_level);
  882.  
  883. } /* malloc_fatal(... */
  884.  
  885. /*
  886.  * Function:    malloc_warning()
  887.  *
  888.  * Purpose:    to display warning error message and take approrpriate action
  889.  *
  890.  * Arguments:    funcname - name of function calling this routine
  891.  *        mptr     - pointer to malloc block associated with error
  892.  *
  893.  * Returns:    nothing of any value
  894.  *
  895.  * Narrative:
  896.  *
  897.  * Notes:    This routine does not make use of any libc functions to build
  898.  *        and/or disply the error message.  This is due to the fact that
  899.  *        we are probably at a point where malloc is having a real problem
  900.  *        and we don't want to call any function that may use malloc.
  901.  */
  902. VOIDTYPE
  903. malloc_warning(funcname,file,line,mptr)
  904.     CONST char        * funcname;
  905.     CONST char        * file;
  906.     int              line;
  907.     CONST struct mlist    * mptr;
  908. {
  909.     char          errbuf[ERRBUFSIZE];
  910.     char        * s;
  911.     CONST char    * t;
  912.  
  913.     s = errbuf;
  914.     t = "MALLOC Warning from ";
  915.     COPY(s,t,errbuf,ERRBUFSIZE);
  916.  
  917.     t = funcname;
  918.     COPY(s,t,errbuf,ERRBUFSIZE);
  919.  
  920.     t = "()";
  921.     COPY(s,t,errbuf,ERRBUFSIZE);
  922.  
  923.     /*
  924.      * if we have a file and line number, show it
  925.       */
  926.     if( file != NULL )
  927.     {
  928.         t = " (called from ";
  929.         COPY(s,t,errbuf,ERRBUFSIZE);
  930.         
  931.         t = file;
  932.         COPY(s,t,errbuf,ERRBUFSIZE);
  933.  
  934.         t = " line ";
  935.         COPY(s,t,errbuf,ERRBUFSIZE);
  936.  
  937.         s += tostring(s,(ULONG)line,0,10,' ');
  938.  
  939.         *s++ = ')';
  940.  
  941.     }
  942.  
  943.     *s++ = ':';
  944.     *s++ = '\n';
  945.  
  946.     t = malloc_err_strings[malloc_errno];
  947.     COPY(s,t,errbuf,ERRBUFSIZE);
  948.  
  949.     *(s++) = '\n';
  950.  
  951.     if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf)) != (s-errbuf))
  952.     {
  953.         VOIDCAST write(2,"I/O error to error file\n",(WRTSIZE)24);
  954.         exit(110);
  955.     }
  956.  
  957.     /*
  958.      * if this error was associated with an identified malloc block,
  959.      * dump the malloc info for the block.
  960.      */
  961.     if( mptr )
  962.     {
  963.         malloc_dump_info_block(mptr,DUMP_PTR);
  964.     }
  965.  
  966.         
  967.     malloc_err_handler(malloc_warn_level);
  968.  
  969. } /* malloc_warning(... */
  970.  
  971. /*
  972.  * Function:    malloc_dump_info_block()
  973.  *
  974.  * Purpose:    to display identifying information on an offending malloc
  975.  *        block to help point the user in the right direction
  976.  *
  977.  * Arguments:    mptr - pointer to malloc block
  978.  *
  979.  * Returns:    nothing of any value
  980.  *
  981.  * Narrative:
  982.  *
  983.  * Notes:    This routine does not make use of any libc functions to build
  984.  *        and/or disply the error message.  This is due to the fact that
  985.  *        we are probably at a point where malloc is having a real
  986.  *        problem and we don't want to call any function that may use
  987.  *         malloc.
  988.  */
  989. VOIDTYPE
  990. malloc_dump_info_block(mptr,id)
  991.     CONST struct mlist    * mptr;
  992.     int              id;
  993. {
  994.     char          errbuf[ERRBUFSIZE];
  995.     CONST char    * funcname;
  996.     char        * s;
  997.     CONST char    * t;
  998.  
  999.     /*
  1000.      * if the mlist struct does not have a valid magic number, skip it
  1001.      * because we probably have gotten clobbered.
  1002.      */
  1003.     if( (mptr->flag&M_MAGIC_BITS) != M_MAGIC )
  1004.     {
  1005.         return;
  1006.     }
  1007.  
  1008.     s = errbuf;
  1009.  
  1010.     if( id == DUMP_PTR )
  1011.     {
  1012.         t = "This error is *probably* associated with the following";
  1013.         COPY(s,t,errbuf,ERRBUFSIZE);
  1014.  
  1015.         t = " allocation:\n\n\tA call to ";
  1016.     }
  1017.     else if( id == DUMP_PREV )
  1018.     {
  1019.         if( mptr == NULL || (mptr == &malloc_start) )
  1020.         {
  1021.             t = "\tThere is no malloc chain element prior to the";
  1022.             COPY(s,t,errbuf,ERRBUFSIZE);
  1023.  
  1024.             t = " suspect\n\t element identified above";
  1025.         }
  1026.         else
  1027.         {
  1028.             t = "\tThe malloc chain element prior to the suspect";
  1029.             COPY(s,t,errbuf,ERRBUFSIZE);
  1030.  
  1031.             t = " allocation is from:\n\n\tA call to ";
  1032.         }
  1033.     }
  1034.     else
  1035.     {
  1036.         if( (mptr == NULL) ||
  1037.             ((mptr == malloc_end) && (GETTYPE(mptr) == M_T_SPLIT)) )
  1038.         {
  1039.             t = "\tThere is no malloc chain element after the";
  1040.             COPY(s,t,errbuf,ERRBUFSIZE);
  1041.  
  1042.             t = " suspect\n\t element identified above";
  1043.         }
  1044.         else
  1045.         {
  1046.             t ="\tThe malloc chain element following the suspect";
  1047.             COPY(s,t,errbuf,ERRBUFSIZE);
  1048.         
  1049.             t = " allocation is from:\n\n\tA call to ";
  1050.         }
  1051.     }
  1052.     COPY(s,t,errbuf,ERRBUFSIZE);
  1053.  
  1054.     /*
  1055.      * if this is a real-live malloc block (the starting block and
  1056.      * the last block (if it was generated by a malloc split) don't
  1057.      * count as real blocks since the user never allocated them.
  1058.      */
  1059.     if( (mptr != NULL) && (mptr != &malloc_start)  &&
  1060.         ((mptr != malloc_end) || (GETTYPE(mptr) != M_T_SPLIT)) )
  1061.     {
  1062.  
  1063.         funcname = t = MallocFuncName(mptr);
  1064.         COPY(s,t,errbuf,ERRBUFSIZE);
  1065.  
  1066.         t = " for ";
  1067.         COPY(s,t,errbuf,ERRBUFSIZE);
  1068.  
  1069.         s += tostring(s,(ULONG)mptr->r_size,0,10,' ');
  1070.  
  1071.         t = " bytes in ";
  1072.         COPY(s,t,errbuf,ERRBUFSIZE);
  1073.  
  1074.         /*
  1075.          * if we don't have file info
  1076.           */
  1077.         if( (mptr->file == NULL) || (mptr->file[0] == EOS) )
  1078.         {
  1079.             t = "an unknown file";
  1080.             COPY(s,t,errbuf,ERRBUFSIZE);
  1081.         }
  1082.         else
  1083.         {
  1084.             t = mptr->file;
  1085.             COPY(s,t,errbuf,ERRBUFSIZE);
  1086.  
  1087.             t = " on line ";
  1088.             COPY(s,t,errbuf,ERRBUFSIZE);
  1089.             
  1090.             s += tostring(s,(ULONG)mptr->line,0,10,' ');
  1091.         }
  1092.  
  1093.         t = ".\n\tThis was the ";
  1094.         COPY(s,t,errbuf,ERRBUFSIZE);
  1095.  
  1096.         s += tostring(s,(ULONG)mptr->id,0,10,' ');
  1097.  
  1098.         t = malloc_int_suffix(mptr->id);
  1099.         COPY(s,t,errbuf,ERRBUFSIZE);
  1100.  
  1101.         t = " call to ";
  1102.         COPY(s,t,errbuf,ERRBUFSIZE);
  1103.  
  1104.         t = funcname;
  1105.         COPY(s,t,errbuf,ERRBUFSIZE);
  1106.  
  1107.         t = ".\n";
  1108.         COPY(s,t,errbuf,ERRBUFSIZE);
  1109.         
  1110.         if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf))!=(s-errbuf))
  1111.         {
  1112.             VOIDCAST write(2,"I/O error to error file\n",
  1113.                     (WRTSIZE)24);
  1114.             exit(110);
  1115.         }
  1116.  
  1117.         StackDump(malloc_errfd, "\tStack from where allocated:\n",
  1118.                   mptr->stack);
  1119.  
  1120.         s = errbuf;
  1121.         *s++ = '\n';
  1122.         
  1123.         /*
  1124.          * if the block is not currently in use
  1125.          */
  1126.         if(  (mptr->flag & M_INUSE) == 0 )
  1127.         {
  1128.             t="\tThis block was freed on the ";
  1129.             COPY(s,t,errbuf,ERRBUFSIZE);
  1130.  
  1131.             s += tostring(s,(ULONG)mptr->fid,0,10,' ');
  1132.  
  1133.             t = malloc_int_suffix(mptr->fid);
  1134.             COPY(s,t,errbuf,ERRBUFSIZE);
  1135.  
  1136.             t = " call to ";
  1137.             COPY(s,t,errbuf,ERRBUFSIZE);
  1138.  
  1139.             t = FreeFuncName(mptr);
  1140.             COPY(s,t,errbuf,ERRBUFSIZE);
  1141.  
  1142.             t = "()";
  1143.             COPY(s,t,errbuf,ERRBUFSIZE);
  1144.  
  1145.             /*
  1146.              * if we know where it was freed
  1147.              */
  1148.             if( mptr->ffile != NULL )
  1149.             {
  1150.                 t = "\n\tin ";
  1151.                 COPY(s,t,errbuf,ERRBUFSIZE);
  1152.  
  1153.                 t = mptr->ffile;
  1154.                 COPY(s,t,errbuf,ERRBUFSIZE);
  1155.  
  1156.                 t = " on line ";
  1157.                 COPY(s,t,errbuf,ERRBUFSIZE);
  1158.             
  1159.                 s += tostring(s,(ULONG)mptr->fline,0,10,' ');
  1160.             }
  1161.  
  1162.             t = ".\n";
  1163.             COPY(s,t,errbuf,ERRBUFSIZE);
  1164.         
  1165.             if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf))
  1166.                 != (s-errbuf))
  1167.             {
  1168.                 VOIDCAST write(2,"I/O error to error file\n",
  1169.                     (WRTSIZE)24);
  1170.                 exit(110);
  1171.             }
  1172.  
  1173.             StackDump(malloc_errfd, "\tStack from where freed:\n",
  1174.                   mptr->freestack);
  1175.  
  1176.             s = errbuf;
  1177.             *s++ = '\n';
  1178.         }
  1179.         
  1180.     }
  1181.     else
  1182.     {
  1183.         t = ".\n\n";
  1184.         COPY(s,t,errbuf,ERRBUFSIZE);
  1185.     }
  1186.  
  1187.         
  1188.     if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf)) != (s-errbuf))
  1189.     {
  1190.         VOIDCAST write(2,"I/O error to error file\n", (WRTSIZE)24);
  1191.         exit(110);
  1192.     }
  1193.  
  1194.     /*
  1195.      * if this is the primary suspect and we are showing links
  1196.      */
  1197.     if( (malloc_opts & MOPT_SLINKS) && (id == DUMP_PTR ) )
  1198.     {
  1199.         /*
  1200.          * show the previous and next malloc regions.
  1201.          */
  1202.         malloc_dump_info_block(mptr->prev,DUMP_PREV);
  1203.         malloc_dump_info_block(mptr->next,DUMP_NEXT);
  1204.     }
  1205.         
  1206. } /* malloc_dump_info_block(... */
  1207.  
  1208. /*
  1209.  * Function:    malloc_err_handler()
  1210.  *
  1211.  * Purpose:    to take the appropriate action for warning and/or fatal 
  1212.  *        error conditions.
  1213.  *
  1214.  * Arguments:    level - error handling level 
  1215.  *
  1216.  * Returns:    nothing of any value
  1217.  *
  1218.  * Narrative:
  1219.  *
  1220.  * Notes:    This routine does not make use of any libc functions to build
  1221.  *        and/or disply the error message.  This is due to the fact that
  1222.  *        we are probably at a point where malloc is having a real problem
  1223.  *        and we don't want to call any function that may use malloc.
  1224.  */
  1225. VOIDTYPE
  1226. malloc_err_handler(level)
  1227.     int          level;
  1228. {
  1229.  
  1230.     if( level & M_HANDLE_DUMP )
  1231.     {
  1232.         malloc_dump(malloc_errfd);
  1233.     }
  1234.  
  1235.     switch( level & ~M_HANDLE_DUMP )
  1236.     {
  1237.         /*
  1238.          * If we are to drop a core file and exit
  1239.          */
  1240.         case M_HANDLE_ABORT:
  1241.             VOIDCAST signal(ABORT_SIGNAL, SIG_DFL);
  1242.  
  1243.             /*
  1244.              * first try the generic abort function
  1245.               */
  1246.             VOIDCAST malloc_abort();
  1247.  
  1248.             /*
  1249.               * if we are still here, then use the real abort
  1250.              */
  1251.             VOIDCAST abort();
  1252.  
  1253.             /*
  1254.               * and if we are still here, just exit.
  1255.              */
  1256.             exit(201);
  1257.             break;
  1258.  
  1259.         /*
  1260.          * If we are to exit..
  1261.          */
  1262.         case M_HANDLE_EXIT:
  1263.             exit(200);
  1264.             break;
  1265.  
  1266.         /*
  1267.          * If we are to dump a core, but keep going on our merry way
  1268.          */
  1269.         case M_HANDLE_CORE:
  1270.             {
  1271.                 int      pid;
  1272.  
  1273.                 /*
  1274.                  * fork so child can abort (and dump core)
  1275.                  */
  1276.                 if( (pid = fork()) == 0 )
  1277.                 {
  1278.                     VOIDCAST write(malloc_errfd,
  1279.                             "Child dumping core\n",
  1280.                             (WRTSIZE)19);
  1281.                     VOIDCAST signal(ABORT_SIGNAL, SIG_DFL);
  1282.                     /*
  1283.                      * first try the generic abort function
  1284.                      */
  1285.                     VOIDCAST malloc_abort();
  1286.                     /*
  1287.                      * then try the real abort
  1288.                      */
  1289.                     VOIDCAST abort();
  1290.                     /*
  1291.                      * if the abort doesn't cause us to
  1292.                      * die, then we may as well just exit
  1293.                      */
  1294.                     exit(201);
  1295.                 }
  1296.  
  1297.                 /*
  1298.                   * wait for child to finish dumping core
  1299.                  */
  1300.                 while( wait((int *)0) != pid)
  1301.                 {
  1302.                 }
  1303.  
  1304.                 /*
  1305.                  * Move core file to core.pid.cnt so 
  1306.                  * multiple cores don't overwrite each
  1307.                  * other.
  1308.                  */
  1309.                 if( access("core",0) == 0 )
  1310.                 {
  1311.                     static int      corecnt;
  1312.                     char            filenam[32];
  1313.                     filenam[0] = 'c';
  1314.                     filenam[1] = 'o';
  1315.                     filenam[2] = 'r';
  1316.                     filenam[3] = 'e';
  1317.                     filenam[4] = '.';
  1318.                     VOIDCAST tostring(filenam+5,
  1319.                         (ULONG)getpid(),
  1320.                         5, B_DEC, '0');
  1321.                     filenam[10] = '.';
  1322.                     VOIDCAST tostring(filenam+11,
  1323.                         (ULONG)corecnt++,
  1324.                         3, B_DEC, '0');
  1325.                     filenam[14] = '\0';
  1326.                     VOIDCAST unlink(filenam);
  1327.                     if( rename("core",filenam) == 0)
  1328.                     {
  1329.                         VOIDCAST unlink("core");
  1330.                     }
  1331.                 }
  1332.             }
  1333.  
  1334.  
  1335.         /* 
  1336.          * If we are to just ignore the error and keep on processing
  1337.          */
  1338.         case M_HANDLE_IGNORE:
  1339.             break;
  1340.  
  1341.     } /* switch(... */
  1342.  
  1343. } /* malloc_err_handler(... */
  1344.  
  1345. /*
  1346.  * Function:    malloc_int_suffix()
  1347.  *
  1348.  * Purpose:    determine the correct suffix for the integer passed 
  1349.  *        (i.e. the st on 1st, nd on 2nd).
  1350.  *
  1351.  * Arguments:    i - the integer whose suffix is desired.
  1352.  *
  1353.  * Returns:    pointer to the suffix
  1354.  *
  1355.  * Narrative:
  1356.  *
  1357.  */
  1358. CONST char *
  1359. malloc_int_suffix(i)
  1360.     IDTYPE      i;
  1361. {
  1362.     int          j;
  1363.     CONST char    * rtn;
  1364.  
  1365.     /*
  1366.      * since the suffixes repeat for the same number within a
  1367.      * given 100 block (i.e. 111 and 211 use the same suffix), get the 
  1368.      * integer moded by 100.
  1369.      */
  1370.     i = i % 100;
  1371.     j = i % 10;
  1372.  
  1373.     /*
  1374.      * if the number is 11, or 12, or 13 or its singles digit is
  1375.      * not a 1, 2, or 3, the suffix must be th.
  1376.      */
  1377.     if( (i == 11) || (i == 12) || (i == 13) ||
  1378.         ( (j != 1) && (j != 2) && (j != 3) ) )
  1379.     {
  1380.         rtn = "th";
  1381.     }
  1382.     else 
  1383.     {
  1384.         switch(j)
  1385.         {
  1386.             case 1:
  1387.                 rtn = "st";
  1388.                 break;
  1389.             case 2:
  1390.                 rtn = "nd";
  1391.                 break;
  1392.             case 3:
  1393.                 rtn = "rd";
  1394.                 break;
  1395.             default:
  1396.                 rtn = "th";
  1397.                 break;
  1398.         }
  1399.     }
  1400.  
  1401.     return(rtn);
  1402.     
  1403. } /* malloc_int_suffix(... */
  1404.  
  1405. /*
  1406.  * Function:    malloc_freeseg()
  1407.  *
  1408.  * Purpose:    to add or remove a segment from the list of free segments
  1409.  *
  1410.  * Arguments:    op  - operation (M_FREE_REMOVE or M_FREE_ADD)
  1411.  *        ptr - ptr to segment to be added/removed
  1412.  *
  1413.  * Returns:    nothing of any value
  1414.  *
  1415.  * Narrative:
  1416.  *
  1417.  */
  1418. VOIDTYPE
  1419. malloc_freeseg(op,ptr)
  1420.     int          op;
  1421.     struct mlist    * ptr;
  1422. {
  1423.  
  1424.     /*
  1425.      * if we are to remove it from the list
  1426.      */
  1427.     if( op == M_FREE_REMOVE )
  1428.     {
  1429.         /*
  1430.          * if this is the head of the list, get a new head pointer
  1431.          */
  1432.         if( ptr == malloc_freelist )
  1433.         {
  1434.             malloc_freelist = malloc_freelist->freenext;
  1435.         }
  1436.  
  1437.         /*
  1438.          * if there is an item after this one in the free list,
  1439.          *    link it to our prev item (which may be null)
  1440.          */
  1441.         if( ptr->freenext != (struct mlist *) NULL)
  1442.         {
  1443.             ptr->freenext->freeprev = ptr->freeprev;
  1444.         }
  1445.  
  1446.         /*
  1447.          * if there is an item before this one in the free list,
  1448.          *    link it to the next item (which may also be NULL)
  1449.           */
  1450.         if( ptr->freeprev != (struct mlist *) NULL)
  1451.         {
  1452.             ptr->freeprev->freenext = ptr->freenext;
  1453.         }
  1454.  
  1455.         /*
  1456.          * disable the free list pointers on the segment that was
  1457.          * removed from the list.
  1458.          */
  1459.         ptr->freenext = ptr->freeprev = (struct mlist *) NULL;
  1460.  
  1461.     }
  1462.     else /* it is an add */
  1463.     {
  1464.         /*
  1465.          * setup the new links for the new head pointer (new items are
  1466.           * always placed at the begining of the list.  However, they may
  1467.          * be removed from anywhere in the list (hence the double
  1468.          * linking))
  1469.          */
  1470.         ptr->freeprev = (struct mlist *) NULL;
  1471.         ptr->freenext = malloc_freelist;
  1472.         
  1473.  
  1474.         /*
  1475.           * if there was already a valid head pointer
  1476.          */
  1477.         if( malloc_freelist != (struct mlist *) NULL )
  1478.         {
  1479.             /*
  1480.              * link it back to the new head pointer
  1481.              */
  1482.             malloc_freelist->freeprev = ptr;
  1483.         }
  1484.         /*
  1485.          * store the new head pointer
  1486.          */
  1487.         malloc_freelist = ptr;
  1488.  
  1489.     }
  1490.  
  1491. } /* malloc_freeseg(... */
  1492.  
  1493. CONST char *
  1494. MallocFuncName(mptr)
  1495.     CONST struct mlist    * mptr;
  1496. {
  1497.     CONST char            * rtn;
  1498.  
  1499.     /*
  1500.      * get the function name 
  1501.      */
  1502.     switch(GETTYPE(mptr))
  1503.     {
  1504.         case M_T_MALLOC:
  1505.             rtn = "malloc";
  1506.             break;
  1507.         case M_T_REALLOC:
  1508.             rtn = "realloc";
  1509.             break;
  1510.         case M_T_CALLOC:
  1511.             rtn = "calloc";
  1512.             break;
  1513.         case M_T_SPLIT:
  1514.             rtn = "splitfunc";
  1515.             break;
  1516.         case M_T_XTMALLOC:
  1517.             rtn = "XtMalloc";
  1518.             break;
  1519.         case M_T_XTREALLOC:
  1520.             rtn = "XtRealloc";
  1521.             break;
  1522.         case M_T_XTCALLOC:
  1523.             rtn = "XtCalloc";
  1524.             break;
  1525.         case M_T_ALIGNED:
  1526.             rtn = "memalign";
  1527.             break;
  1528.         default:
  1529.             rtn = "Unknown";
  1530.             break;
  1531.     }
  1532.  
  1533.     return( rtn );
  1534.  
  1535. } /* MallocFuncName(... */
  1536.  
  1537. CONST char *
  1538. FreeFuncName(mptr)
  1539.     CONST struct mlist    * mptr;
  1540. {
  1541.     CONST char        * rtn;
  1542.  
  1543.     /*
  1544.      * get the function name 
  1545.      */
  1546.     switch(GETFTYPE(mptr))
  1547.     {
  1548.         case F_T_FREE:
  1549.             rtn = "free";
  1550.             break;
  1551.         case F_T_CFREE:
  1552.             rtn = "cfree";
  1553.             break;
  1554.         case F_T_XTFREE:
  1555.             rtn = "XtFree";
  1556.             break;
  1557.         case F_T_REALLOC:
  1558.             rtn = "realloc";
  1559.             break;
  1560.         default:
  1561.             rtn = "Unknown";
  1562.             break;
  1563.     }
  1564.  
  1565.     return(rtn);
  1566.  
  1567. } /* FreeFuncName(... */
  1568.  
  1569. void
  1570. InitMlist(mptr,type)
  1571.     struct mlist    * mptr;
  1572.     int          type;
  1573. {
  1574.     DataMS((MEMDATA *) mptr,'\0', sizeof( struct mlist));
  1575.  
  1576.     mptr->flag = M_MAGIC;
  1577.     SETTYPE(mptr,type);
  1578.  
  1579.     mptr->hist_id = malloc_hist_id++;
  1580.  
  1581. }
  1582.  
  1583. /*
  1584.  * $Log: malloc.c,v $
  1585.  * Revision 1.43  1992/09/03  22:24:33  cpcahil
  1586.  * final changes for PL14
  1587.  *
  1588.  * Revision 1.42  1992/08/22  16:27:13  cpcahil
  1589.  * final changes for pl14
  1590.  *
  1591.  * Revision 1.41  1992/07/31  11:47:30  cpcahil
  1592.  * added setting of free-file pointer when splitting off a segment
  1593.  *
  1594.  * Revision 1.40  1992/07/12  15:30:58  cpcahil
  1595.  * Merged in Jonathan I Kamens' changes
  1596.  *
  1597.  * Revision 1.39  1992/07/03  00:03:25  cpcahil
  1598.  * more fixes for pl13, several suggestons from Rich Salz.
  1599.  *
  1600.  * Revision 1.38  1992/06/30  13:06:39  cpcahil
  1601.  * added support for aligned allocations
  1602.  *
  1603.  * Revision 1.37  1992/06/22  23:40:10  cpcahil
  1604.  * many fixes for working on small int systems
  1605.  *
  1606.  * Revision 1.36  1992/05/09  00:16:16  cpcahil
  1607.  * port to hpux and lots of fixes
  1608.  *
  1609.  * Revision 1.35  1992/05/08  02:39:58  cpcahil
  1610.  * minor fixups
  1611.  *
  1612.  * Revision 1.34  1992/05/08  02:30:35  cpcahil
  1613.  * minor cleanups from minix/atari port
  1614.  *
  1615.  * Revision 1.33  1992/05/06  05:37:44  cpcahil
  1616.  * added overriding of fill characters and boundary size
  1617.  *
  1618.  * Revision 1.32  1992/05/06  04:53:29  cpcahil
  1619.  * performance enhancments
  1620.  *
  1621.  * Revision 1.31  1992/04/24  12:09:13  cpcahil
  1622.  * (hopefully) final cleanup for patch 10
  1623.  *
  1624.  * Revision 1.30  1992/04/24  11:18:52  cpcahil
  1625.  * Fixes from Denny Page and Better integration of Xt alloc hooks
  1626.  *
  1627.  * Revision 1.29  1992/04/22  18:17:32  cpcahil
  1628.  * added support for Xt Alloc functions, linted code
  1629.  *
  1630.  * Revision 1.28  1992/04/20  22:29:14  cpcahil
  1631.  * changes to fix problems introduced by insertion of size_t
  1632.  *
  1633.  * Revision 1.27  1992/04/20  22:03:44  cpcahil
  1634.  * added setting of filled flag.
  1635.  *
  1636.  * Revision 1.26  1992/04/15  12:51:06  cpcahil
  1637.  * fixes per testing of patch 8
  1638.  *
  1639.  * Revision 1.25  1992/04/13  17:26:25  cpcahil
  1640.  * minor portability changes
  1641.  *
  1642.  * Revision 1.24  1992/04/13  13:56:02  cpcahil
  1643.  * added auto-determination of abort signal to ensure that we have
  1644.  * a valid signal for this system.
  1645.  *
  1646.  * Revision 1.23  1992/04/13  03:06:33  cpcahil
  1647.  * Added Stack support, marking of non-leaks, auto-config, auto-testing
  1648.  *
  1649.  * Revision 1.22  1992/03/01  12:42:38  cpcahil
  1650.  * added support for managing freed areas and fixed doublword bndr problems
  1651.  *
  1652.  * Revision 1.21  1992/02/19  02:33:07  cpcahil
  1653.  * added code to ensure that aborts really happen.
  1654.  *
  1655.  * Revision 1.20  1992/01/30  12:23:06  cpcahil
  1656.  * renamed mallocint.h -> mallocin.h
  1657.  *
  1658.  * Revision 1.19  1992/01/28  16:35:37  cpcahil
  1659.  * increased size of error string buffers and added overflow checks
  1660.  *
  1661.  * Revision 1.18  1992/01/10  17:51:03  cpcahil
  1662.  * more void stuff that slipped by
  1663.  *
  1664.  * Revision 1.17  1992/01/10  17:28:03  cpcahil
  1665.  * Added support for overriding void datatype
  1666.  *
  1667.  * Revision 1.16  1992/01/08  19:40:07  cpcahil
  1668.  * fixed write() count to display entire message.
  1669.  *
  1670.  * Revision 1.15  1991/12/31  21:31:26  cpcahil
  1671.  * changes for patch 6.  See CHANGES file for more info
  1672.  *
  1673.  * Revision 1.14  1991/12/06  08:50:48  cpcahil
  1674.  * fixed bug in malloc_safe_memset introduced in last change.
  1675.  *
  1676.  * Revision 1.13  91/12/04  18:01:21  cpcahil
  1677.  * cleand up some aditional warnings from gcc -Wall
  1678.  * 
  1679.  * Revision 1.12  91/12/04  09:23:39  cpcahil
  1680.  * several performance enhancements including addition of free list
  1681.  * 
  1682.  * Revision 1.11  91/12/02  19:10:10  cpcahil
  1683.  * changes for patch release 5
  1684.  * 
  1685.  * Revision 1.10  91/11/25  14:41:59  cpcahil
  1686.  * Final changes in preparation for patch 4 release
  1687.  * 
  1688.  * Revision 1.9  91/11/24  16:56:41  cpcahil
  1689.  * porting changes for patch level 4
  1690.  * 
  1691.  * Revision 1.8  91/11/24  00:49:27  cpcahil
  1692.  * first cut at patch 4
  1693.  * 
  1694.  * Revision 1.7  91/11/20  11:54:09  cpcahil
  1695.  * interim checkin
  1696.  * 
  1697.  * Revision 1.6  90/05/11  00:13:09  cpcahil
  1698.  * added copyright statment
  1699.  * 
  1700.  * Revision 1.5  90/02/25  11:01:18  cpcahil
  1701.  * added support for malloc chain checking.
  1702.  * 
  1703.  * Revision 1.4  90/02/24  21:50:21  cpcahil
  1704.  * lots of lint fixes
  1705.  * 
  1706.  * Revision 1.3  90/02/24  14:51:18  cpcahil
  1707.  * 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed
  1708.  *    the function name as a parameter.
  1709.  * 2. Added several function headers.
  1710.  * 3. Changed uses of malloc_fatal/warning to conform to new usage.
  1711.  * 
  1712.  * Revision 1.2  90/02/23  18:05:23  cpcahil
  1713.  * fixed open of error log to use append mode.
  1714.  * 
  1715.  * Revision 1.1  90/02/22  23:17:43  cpcahil
  1716.  * Initial revision
  1717.  * 
  1718.  */
  1719.