home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume32 / dbmalloc / part06 < prev    next >
Encoding:
Text File  |  1992-09-03  |  55.8 KB  |  2,544 lines

  1. Newsgroups: comp.sources.misc
  2. From: cpcahil@vti.com (Conor P. Cahill)
  3. Subject:  v32i011:  dbmalloc - Debug Malloc Library PL14, Part06/10
  4. Message-ID: <1992Sep4.152224.13339@sparky.imd.sterling.com>
  5. X-Md4-Signature: d8090f3fde20ae2cad45f25012f279fc
  6. Date: Fri, 4 Sep 1992 15:22:24 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: cpcahil@vti.com (Conor P. Cahill)
  10. Posting-number: Volume 32, Issue 11
  11. Archive-name: dbmalloc/part06
  12. Environment: C, UNIX
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 6 (of 10)."
  21. # Contents:  malloc.c mallopt.c mchain.c minipatch
  22. # Wrapped by cpcahil@virtech on Thu Sep  3 18:39:20 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'malloc.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'malloc.c'\"
  26. else
  27. echo shar: Extracting \"'malloc.c'\" \(36595 characters\)
  28. sed "s/^X//" >'malloc.c' <<'END_OF_FILE'
  29. X/*
  30. X * (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
  31. X *
  32. X * This software may be distributed freely as long as the following conditions
  33. X * are met:
  34. X *         * the distribution, or any derivative thereof, may not be
  35. X *          included as part of a commercial product
  36. X *        * full source code is provided including this copyright
  37. X *        * there is no charge for the software itself (there may be
  38. X *          a minimal charge for the copying or distribution effort)
  39. X *        * this copyright notice is not modified or removed from any
  40. X *          source file
  41. X */
  42. X#include <stdio.h>
  43. X#include <fcntl.h>
  44. X#include <sys/types.h>
  45. X#include <signal.h>
  46. X
  47. X#include "sysdefs.h"
  48. X
  49. X#ifdef NEED_WAIT
  50. X#include <sys/wait.h>
  51. X#endif
  52. X
  53. X/* 
  54. X * make sure mallocin.h doesn't include sys/types.h since we have already
  55. X * included it.
  56. X */
  57. X#ifndef SYS_TYPES_H_INCLUDED
  58. X#define SYS_TYPES_H_INCLUDED 1
  59. X#endif
  60. X
  61. X#include "mallocin.h"
  62. X#include "tostring.h"
  63. X
  64. X#include "debug.h"
  65. X
  66. X#ifndef lint
  67. Xstatic char rcs_hdr[] = "$Id: malloc.c,v 1.43 1992/09/03 22:24:33 cpcahil Exp $";
  68. X#endif
  69. X
  70. Xint          in_malloc_code;
  71. XSIZETYPE      malloc_align;
  72. Xint          malloc_boundsize = M_DFLT_BSIZE;
  73. XDATATYPE    * malloc_data_start;
  74. XDATATYPE    * malloc_data_end;
  75. Xstruct mlist     * malloc_end;
  76. Xint          malloc_errfd = 2;
  77. Xint          malloc_errno;
  78. Xint          malloc_fatal_level = M_HANDLE_ABORT;
  79. Xint          malloc_fill;
  80. Xint          malloc_fillbyte = M_DFLT_FILL;
  81. Xint          malloc_freebyte = M_DFLT_FREE_FILL;
  82. Xstruct mlist    * malloc_freelist;
  83. Xlong          malloc_hist_id;
  84. Xint          malloc_opts = MOPT_MFILL  | MOPT_FFILL | MOPT_DFILL | 
  85. X                MOPT_CKDATA | MOPT_REUSE | MOPT_FREEMARK |
  86. X                MOPT_ZERO;
  87. Xint          malloc_round = M_RND-1;
  88. Xstruct mlist      malloc_start;
  89. Xint          malloc_warn_level;
  90. X
  91. X/*
  92. X * perform string copy, but make sure that we don't go beyond the end of the
  93. X * buffer (leaving room for trailing info (5 bytes) like the return and a null
  94. X */
  95. X#define COPY(s,t,buf,len)    while( (*(s) = *((t)++) ) \
  96. X                       && ( (s) < ((buf)+(len)-5) ) ) { (s)++; }
  97. X
  98. X#define DUMP_PTR    0
  99. X#define DUMP_NEXT    1
  100. X#define DUMP_PREV    2
  101. X
  102. X#define ERRBUFSIZE    1024
  103. X
  104. X/*
  105. X * Function:    malloc()
  106. X *
  107. X * Purpose:    low-level interface to the debug malloc lib.  This should only
  108. X *         be called from code that is not recompilable.  The recompilable
  109. X *        code should include malloc.h and therefore its calls to malloc
  110. X *        will be #defined to be calls to debug_malloc with the
  111. X *        appropriate arguments.
  112. X *
  113. X * Arguments:    size    - size of data area needed
  114. X *
  115. X * Returns:    whatever debug_malloc returns.
  116. X *
  117. X * Narrative:
  118. X *
  119. X */
  120. XDATATYPE *
  121. Xmalloc(size)
  122. X    SIZETYPE      size;
  123. X{
  124. X    return( debug_malloc(NULL,-1,size) );
  125. X}
  126. X
  127. X/*
  128. X * Function:    debug_malloc()
  129. X *
  130. X * Purpose:    the real memory allocator
  131. X *
  132. X * Arguments:    size    - size of data area needed
  133. X *
  134. X * Returns:    pointer to allocated area, or NULL if unable
  135. X *        to allocate addtional data.
  136. X *
  137. X * Narrative:
  138. X *
  139. X */
  140. XDATATYPE *
  141. Xdebug_malloc(file,line,size)
  142. X    CONST char    * file;
  143. X    int          line;
  144. X    SIZETYPE      size;
  145. X{
  146. X    static IDTYPE      call_counter;
  147. X
  148. X    /*
  149. X     * increment the counter for the number of calls to this func.
  150. X     */
  151. X    call_counter++;
  152. X
  153. X    return( DBFmalloc("malloc",M_T_MALLOC,call_counter,file,line,size) );
  154. X
  155. X} /* debug_malloc(... */
  156. X
  157. Xchar *
  158. XDBFmalloc(func,type,call_counter,file,line,size)
  159. X    CONST char        * func;
  160. X    int              type;
  161. X    IDTYPE              call_counter;
  162. X    CONST char        * file;
  163. X    int              line;
  164. X    SIZETYPE          size;
  165. X{
  166. X    char            * cptr;
  167. X    SIZETYPE          fill;
  168. X    SIZETYPE          fit = 0;
  169. X    SIZETYPE          lastfit;
  170. X    struct mlist        * lastptr;
  171. X    SIZETYPE          need;
  172. X    int              newmalloc = 0;
  173. X    register struct mlist    * oldptr;
  174. X    register struct mlist    * ptr;
  175. X    SIZETYPE          r_size;
  176. X
  177. X    MALLOC_INIT();
  178. X
  179. X    /*
  180. X     * If malloc chain checking is on, go do it.
  181. X     */
  182. X    if( malloc_opts & MOPT_CKCHAIN )
  183. X    {
  184. X        VOIDCAST DBFmalloc_chain_check(func,file,line,1);
  185. X    }
  186. X
  187. X    /*
  188. X     * if the user wants to be warned about zero length mallocs, do so
  189. X     */
  190. X    if( ((malloc_opts & MOPT_ZERO) != 0) && (size == 0) )
  191. X    {
  192. X        malloc_errno = M_CODE_ZERO_ALLOC;
  193. X        malloc_warning(func,file,line,(struct mlist *) NULL);
  194. X    }
  195. X
  196. X    /*
  197. X     * save the original requested size;
  198. X     */
  199. X    r_size = size;
  200. X
  201. X    /*
  202. X     * always make sure there is at least on extra byte in the malloc
  203. X     * area so that we can verify that the user does not overrun the
  204. X     * data area.
  205. X     */
  206. X    size += malloc_boundsize;
  207. X
  208. X    /*
  209. X     * Now look for a free area of memory of size bytes...
  210. X     */
  211. X    oldptr = NULL;
  212. X    ptr = malloc_freelist;
  213. X
  214. X    /*
  215. X     * if low fragmentation has been turned on, look for a best fit
  216. X     * segment (otherwise, for performance reasons, we will look for
  217. X     * a first fit)
  218. X     */
  219. X    if( malloc_opts & MOPT_LOWFRAG )
  220. X    {  
  221. X        lastfit = -1;
  222. X        lastptr = NULL;
  223. X        /*
  224. X         * until we run out of segments, or find an exact match
  225. X         */
  226. X        for(; (ptr != NULL) && (lastfit != 0); ptr=ptr->freenext)
  227. X        {
  228. X            /*
  229. X             * quick check to make sure our free-list hasn't been
  230. X             * broken.
  231. X             */
  232. X            if((oldptr != NULL) && (ptr->freeprev != oldptr) )
  233. X            {
  234. X                malloc_errno = M_CODE_CHAIN_BROKE;
  235. X                malloc_fatal(func,file,line,oldptr);
  236. X                return(NULL);
  237. X            }
  238. X
  239. X            /*
  240. X             * if this is to be an aligned segment and the pointer
  241. X             * is not already aligned on the correct boundry
  242. X             */
  243. X            if(    (type == M_T_ALIGNED)
  244. X                && ((((SIZETYPE)ptr->data)&(malloc_align-1)) != 0)    
  245. X                && (ptr->s.size > size ) )
  246. X            {
  247. X                fit = AlignedFit(ptr,malloc_align,size);
  248. X            }
  249. X            /*
  250. X             * else if this segment is big enough for our needs
  251. X             */
  252. X            else if( ptr->s.size > size )
  253. X            {
  254. X                /*
  255. X                  * calculate how close we fit. 
  256. X                 */
  257. X                fit = ptr->s.size - size;
  258. X            }
  259. X            else
  260. X            {
  261. X                fit = -1;
  262. X            }
  263. X
  264. X            if( fit == 0 )
  265. X            {
  266. X                break;
  267. X            }
  268. X            else if( fit > 0 )
  269. X            {    
  270. X                /*
  271. X                  * if this is the first one we fit int, or
  272. X                 * if this a closer fit
  273. X                  */
  274. X                if( (lastfit == -1) || (fit < lastfit) )
  275. X                {
  276. X                    lastptr = ptr;
  277. X                    lastfit = fit;
  278. X                }
  279. X            }
  280. X            oldptr = ptr;
  281. X
  282. X        } /* for(... */
  283. X
  284. X        /*
  285. X         * if we found an entry, use it
  286. X         */
  287. X        if( (fit != 0) && (lastptr != NULL) )
  288. X        {
  289. X            ptr = lastptr;
  290. X        }
  291. X    }
  292. X    else
  293. X    {
  294. X        /*
  295. X         * until we run out of free entries, or find an entry that has
  296. X         * enough room
  297. X         */
  298. X        for( ; (ptr != NULL) ; ptr=ptr->freenext)
  299. X        {
  300. X            if((oldptr != NULL) && (ptr->freeprev != oldptr) )
  301. X            {
  302. X                malloc_errno = M_CODE_CHAIN_BROKE;
  303. X                malloc_fatal(func,file,line,oldptr);
  304. X                return(NULL);
  305. X            }
  306. X
  307. X            /*
  308. X             * if this is an aligned request and it isn't already
  309. X             * aligned and it appears to be big enough
  310. X             */
  311. X            if(    (type == M_T_ALIGNED)
  312. X                && ((((SIZETYPE)ptr->data)&(malloc_align-1)) != 0)    
  313. X                && (ptr->s.size >= size ) )
  314. X            {
  315. X                /*
  316. X                 * if an aligned segment does fit within the
  317. X                 * specified segment, break out of loop
  318. X                 */
  319. X                if( AlignedFit(ptr,malloc_align,size) >= 0)
  320. X                {
  321. X                    break;
  322. X                }
  323. X            }
  324. X            /*
  325. X             * else if this segment is big enough
  326. X             */
  327. X            else if( ptr->s.size >= size )
  328. X            {
  329. X                break;
  330. X            }
  331. X
  332. X            oldptr = ptr;
  333. X
  334. X        } /* for(... */
  335. X    }
  336. X
  337. X    /*
  338. X     * If ptr is null, we have run out of memory and must sbrk more
  339. X     */
  340. X    if( ptr == NULL )
  341. X    {
  342. X        /*
  343. X         * calculate how much space we need.  If they ask for more
  344. X         * than 100k, get exactly what they want.  Otherwise get
  345. X         * twice what they ask for so that we are ready for the
  346. X         * next allocation they ask for
  347. X         */
  348. X        need = size + sizeof(struct mlist);
  349. X        if( size < 100*1024 )
  350. X        {
  351. X            need <<= 1;
  352. X        }
  353. X
  354. X        /*
  355. X         * figure out any additional bytes we might need in order to
  356. X         * obtain the correct alignment
  357. X         */
  358. X        cptr = sbrk(0);
  359. X
  360. X        fill = ((SIZETYPE)cptr) & (M_RND-1);
  361. X        if( fill )
  362. X        {
  363. X            fill = M_RND - fill;
  364. X        }
  365. X
  366. X        /*
  367. X         * if this is an aligned request, then make sure we have 
  368. X         * enough room for the aligment 
  369. X         */
  370. X        if( type == M_T_ALIGNED )
  371. X        {
  372. X            cptr += fill + M_SIZE;
  373. X
  374. X            /*
  375. X             * if this new value will not be on a valid 
  376. X             * alignment, add malloc_align + sizeof(struct mlist)
  377. X             * to the amount of space that we need to make sure 
  378. X             * that we have enough for the aligned allocation.
  379. X             */
  380. X            if( (((SIZETYPE)cptr) & (malloc_align-1)) != 0 )
  381. X            {
  382. X                need += malloc_align + sizeof(struct mlist);
  383. X            }
  384. X        }
  385. X
  386. X        /*
  387. X         * if the need is less than the minimum block size,
  388. X         *     get the minimum block size
  389. X          */
  390. X        if( need < M_BLOCKSIZE )
  391. X        {
  392. X            need = M_BLOCKSIZE;
  393. X        }
  394. X        /*
  395. X         * else if the need is not an even multiple of the block size,
  396. X         *     round it up to an even multiple
  397. X         */
  398. X        else if( need & (M_BLOCKSIZE-1) )
  399. X        {
  400. X            need &= ~(M_BLOCKSIZE-1);
  401. X            need += M_BLOCKSIZE;
  402. X        }
  403. X
  404. X        /*
  405. X         * add in that fill space we determined before so that after
  406. X         * this allocation, future allocations should be alligned
  407. X         * appropriately
  408. X          */
  409. X        need += fill;
  410. X
  411. X        /*
  412. X         * get the space from the os
  413. X          */
  414. X        cptr = sbrk((int)need);
  415. X
  416. X        /*
  417. X         * if we failed to get the space, tell the user about it
  418. X         */
  419. X        if( cptr == (char *) -1 )
  420. X        {
  421. X            malloc_errno = M_CODE_NOMORE_MEM;
  422. X            malloc_fatal(func,file,line, (struct mlist *)NULL);
  423. X            return(NULL);
  424. X        }
  425. X
  426. X        /*
  427. X         * make sure that the pointer returned by sbrk is on the
  428. X         * correct alignment boundry.
  429. X         */
  430. X        DEBUG2(10,"sbrk() returned 0x%lx, skipping %d bytes to align",
  431. X            cptr, fill);
  432. X        ptr = (struct mlist *) (cptr + fill);
  433. X
  434. X        /*
  435. X         * readjust the amount of space we obtained to reflect the fill
  436. X         * area we are skipping.
  437. X         */
  438. X        need -= fill;
  439. X    
  440. X        /*
  441. X         * mark our end point
  442. X         */
  443. X        malloc_data_end = sbrk((int)0);
  444. X
  445. X        /*
  446. X         * hook the new segment into the malloc chain
  447. X         */
  448. X        InitMlist(ptr,M_T_SPLIT);
  449. X        ptr->prev     = malloc_end;
  450. X        ptr->s.size   = need - M_SIZE;
  451. X        ptr->r_size   = ptr->s.size;
  452. X    
  453. X        malloc_end->next = ptr;
  454. X        malloc_end = ptr;
  455. X
  456. X        newmalloc = 1;
  457. X
  458. X    } /* if( ptr ==... */
  459. X    /*
  460. X     * else we found a free slot that has enough room,
  461. X     *    so take it off the free list
  462. X     */
  463. X    else
  464. X    {
  465. X        /*
  466. X         * if this module is already in use
  467. X         */
  468. X        if( (ptr->flag & M_INUSE) != 0 )
  469. X        {
  470. X            malloc_errno = M_CODE_FREELIST_BAD;
  471. X            malloc_fatal(func,file,line,ptr);
  472. X            return(NULL);
  473. X        }
  474. X        
  475. X    }
  476. X        
  477. X
  478. X    /*
  479. X     * Now ptr points to a memory location that can store
  480. X     * this data, so lets go to work.
  481. X     */
  482. X
  483. X    /*
  484. X     * if this is an aligned request and the data is not already on the
  485. X     * correct alignment
  486. X     */
  487. X    if(    (type == M_T_ALIGNED)
  488. X        && ((((SIZETYPE)(ptr->data)) & (malloc_align-1)) != 0) )
  489. X    {
  490. X        /*
  491. X         * if this is a new allocation, we have to check to see if
  492. X         * the new segment can be joined to the previous segment 
  493. X         * before we pull out the aligned segment.  This is required
  494. X         * since the previous segment may be free and we would end
  495. X         * up with two adjacent free segments if we didn't do this.
  496. X         */
  497. X        if( newmalloc )
  498. X        {
  499. X            /*
  500. X             * if there is a previous segment
  501. X             */
  502. X            if( (oldptr = ptr->prev) != NULL )
  503. X            {
  504. X                /*
  505. X                 * attempt to join the previous segment with
  506. X                 * the new segment (if the prev seg is free).
  507. X                 */
  508. X                malloc_join(ptr->prev,ptr, NOTINUSE, DOFILL);
  509. X
  510. X                /*
  511. X                 * if they were joined, use the new pointer.
  512. X                 */
  513. X                if( oldptr->next != ptr )
  514. X                {
  515. X                    ptr = oldptr;
  516. X                }
  517. X            }
  518. X
  519. X            /*
  520. X             * if this segment did not get joined to a previous
  521. X             * segment, add the new segment to the free list.
  522. X             */
  523. X            if( oldptr != ptr )
  524. X            {
  525. X                malloc_freeseg(M_FREE_ADD, ptr);
  526. X            }
  527. X        }
  528. X
  529. X        /*
  530. X         * break out the new segment.  Note that AlignedMakeSeg depends
  531. X         * upon the fact that ptr points to a segment that will have
  532. X         * enough room for the alignment within the segment.
  533. X         */
  534. X        ptr = AlignedMakeSeg(ptr,malloc_align);
  535. X    }
  536. X    /*
  537. X     * else we are going to use the indicated segment, so let's remove it
  538. X     * from the free list.
  539. X     */
  540. X    else if( ! newmalloc )
  541. X    {
  542. X        /*
  543. X         * remove the segment from the free list
  544. X         */
  545. X        malloc_freeseg(M_FREE_REMOVE,ptr);
  546. X    }
  547. X
  548. X    /*
  549. X     * for the purpose of splitting, have the requested size appear to be
  550. X     * the same as the actualsize
  551. X     */
  552. X    ptr->r_size = size;        /* save requested size    */
  553. X
  554. X    /*
  555. X     * split off unneeded data area in this block, if possible...
  556. X     */
  557. X    malloc_split(ptr);
  558. X
  559. X    /*
  560. X     * set inuse flag after split, so that the split routine knows that
  561. X     * this module can see that the module was free and therefore won't 
  562. X     * re-fill it if not necessary.
  563. X     */
  564. X    ptr->flag |= M_INUSE;
  565. X
  566. X    /*
  567. X     * save the real requested size
  568. X     */
  569. X    ptr->r_size = r_size;
  570. X
  571. X    /*
  572. X     * fill in the buffer areas (and possibly the data area) in
  573. X     * order to track underflow, overflow, and uninitialized use
  574. X     */
  575. X    FILLDATA(ptr, FILL_MALLOC, (SIZETYPE)0, (struct mlist *) NULL);
  576. X
  577. X    /*
  578. X     * store the identification information
  579. X     */
  580. X    ptr->file      = file;
  581. X    ptr->line      = line;
  582. X    ptr->id        = call_counter;
  583. X    ptr->hist_id   = malloc_hist_id++;
  584. X    ptr->stack     = StackCurrent();
  585. X    ptr->freestack = NULL;
  586. X    ptr->freenext  = NULL;
  587. X    ptr->freeprev  = NULL;
  588. X
  589. X    SETTYPE(ptr,type);
  590. X
  591. X    /*
  592. X     * return the pointer to the data area for the user.
  593. X     */
  594. X    return( ptr->data );
  595. X
  596. X
  597. X} /* DBFmalloc(... */
  598. X
  599. X/*
  600. X * Function:    malloc_split()
  601. X *
  602. X * Purpose:    to split a malloc segment if there is enough room at the
  603. X *        end of the segment that isn't being used
  604. X *
  605. X * Arguments:    ptr    - pointer to segment to split
  606. X *
  607. X * Returns:    nothing of any use.
  608. X *
  609. X * Narrative:
  610. X *        get the needed size of the module
  611. X *         round the size up to appropriat boundry
  612. X *        calculate amount of left over space
  613. X *        if there is enough left over space
  614. X *            create new malloc block out of remainder
  615. X *            if next block is free 
  616. X *            join the two blocks together
  617. X *            fill new empty block with free space filler
  618. X *             re-adjust pointers and size of current malloc block
  619. X *        
  620. X *        
  621. X *
  622. X * Mod History:    
  623. X *   90/01/27    cpcahil        Initial revision.
  624. X */
  625. XVOIDTYPE
  626. Xmalloc_split(ptr)
  627. X    struct mlist        * ptr;
  628. X{
  629. X    SIZETYPE          rest;
  630. X    SIZETYPE          size;
  631. X    struct mlist        * tptr;
  632. X    static int          call_counter;
  633. X
  634. X    size = ptr->r_size;
  635. X
  636. X    /*
  637. X     * roundup size to the appropriate boundry
  638. X     */
  639. X    M_ROUNDUP(size);
  640. X
  641. X    /*
  642. X     * figure out how much room is left in the array.
  643. X     * if there is enough room, create a new mlist 
  644. X     *     structure there.
  645. X     */
  646. X    if( ptr->s.size > size )
  647. X    {
  648. X        rest = ptr->s.size - size;
  649. X    }
  650. X    else
  651. X    {
  652. X        rest = 0;
  653. X    }
  654. X
  655. X    /*
  656. X     * if there is at least enough room to create another malloc block
  657. X     */
  658. X    if( rest > sizeof(struct mlist) )
  659. X    {
  660. X        tptr = (struct mlist *) (ptr->data+size);
  661. X        tptr->file  = NULL;
  662. X        tptr->ffile  = NULL;
  663. X        tptr->stack = NULL;
  664. X        tptr->prev  = ptr;
  665. X        tptr->next  = ptr->next;
  666. X        tptr->flag  = M_MAGIC;
  667. X        SETTYPE(tptr,M_T_SPLIT);
  668. X        tptr->s.size = rest - M_SIZE;
  669. X        tptr->r_size = tptr->s.size;
  670. X        tptr->freenext = NULL;
  671. X        tptr->freeprev = NULL;
  672. X        tptr->id    = ++call_counter;
  673. X
  674. X        /*
  675. X         * if this area is not already free-filled
  676. X         */
  677. X        if( ((ptr->flag& M_INUSE) != 0) || ((ptr->flag&M_FILLED) == 0) )
  678. X        {
  679. X            /*
  680. X             * fill freed areas
  681. X             */
  682. X            FILLDATA(tptr,FILL_SPLIT,(SIZETYPE)0,
  683. X                    (struct mlist *) NULL);
  684. X        }
  685. X        else if( (ptr->flag&M_INUSE) == 0 )
  686. X        {
  687. X            /*
  688. X             * since it was already free-filled, just set the flag
  689. X             */
  690. X            tptr->flag |= M_FILLED;
  691. X        }
  692. X
  693. X        /*
  694. X         * If possible, join this segment with the next one
  695. X         */
  696. X        malloc_join(tptr, tptr->next,NOTINUSE,DOFILL);
  697. X
  698. X        if( tptr->next )
  699. X        {
  700. X            tptr->next->prev = tptr;
  701. X        }
  702. X
  703. X        ptr->next = tptr;
  704. X        ptr->s.size = size;
  705. X
  706. X        if( malloc_end == ptr )
  707. X        {
  708. X            malloc_end = tptr;
  709. X        }
  710. X
  711. X        /*
  712. X         * add the new segment to the free list
  713. X         */
  714. X        malloc_freeseg(M_FREE_ADD,tptr);
  715. X
  716. X    }
  717. X
  718. X} /* malloc_split(... */
  719. X
  720. X/*
  721. X * Function:    malloc_join()
  722. X *
  723. X * Purpose:    to join two malloc segments together (if possible)
  724. X *
  725. X * Arguments:    ptr    - pointer to segment to join to.
  726. X *         nextptr    - pointer to next segment to join to ptr.
  727. X *
  728. X * Returns:    nothing of any values.
  729. X *
  730. X * Narrative:
  731. X *
  732. X * Mod History:    
  733. X *   90/01/27    cpcahil        Initial revision.
  734. X */
  735. XVOIDTYPE
  736. Xmalloc_join(ptr,nextptr, inuse_override, fill_flag)
  737. X    struct mlist    * ptr;
  738. X    struct mlist    * nextptr;
  739. X    int          inuse_override;
  740. X    int          fill_flag;
  741. X{
  742. X    SIZETYPE      newsize;
  743. X    SIZETYPE      start;
  744. X
  745. X    /*
  746. X     * if      the current segment exists
  747. X     *    AND  it is not inuse (or if we don't care that it is inuse)
  748. X      *    AND  the next segment exits
  749. X     *    AND  it is not in use
  750. X     *    AND  it is adjacent to this segment
  751. X     *    THEN we can join the two together
  752. X     */
  753. X    if(    ( ptr != NULL )
  754. X        && ((inuse_override & INUSEOK) || ! (ptr->flag & M_INUSE))
  755. X        && ( nextptr != NULL )
  756. X        && ((inuse_override&NEXTPTR_INUSEOK) || !(nextptr->flag & M_INUSE))
  757. X        && ((ptr->data+ptr->s.size) == (char *) nextptr) )
  758. X    {
  759. X        /*
  760. X         * remove nextptr from the freelist
  761. X         */
  762. X        malloc_freeseg(M_FREE_REMOVE,nextptr);
  763. X
  764. X        /*
  765. X         * if the segment was the end pointer
  766. X         */
  767. X        if( malloc_end == nextptr )
  768. X        {
  769. X            malloc_end = ptr;
  770. X        }
  771. X        ptr->next = nextptr->next;
  772. X        newsize = nextptr->s.size + M_SIZE;
  773. X
  774. X        start = ptr->s.size;
  775. X
  776. X        ptr->s.size += newsize;
  777. X        if( ptr->next )
  778. X        {
  779. X            ptr->next->prev = ptr;
  780. X        }
  781. X
  782. X        /*
  783. X         * if the segment is free, set the requested size to include
  784. X         * the requested size within the next segment.
  785. X         */
  786. X        if( ! (ptr->flag & M_INUSE) )
  787. X        {
  788. X            ptr->r_size = start + M_SIZE + nextptr->r_size;
  789. X        }
  790. X
  791. X        /*
  792. X         * if we should fill in the segment
  793. X          */
  794. X        if( fill_flag )
  795. X        {
  796. X            FILLDATA(ptr,FILL_JOIN,start,nextptr);
  797. X        }
  798. X
  799. X    }
  800. X
  801. X} /* malloc_join(... */
  802. X
  803. X
  804. X/*
  805. X * The following mess is just to ensure that the versions of these functions in
  806. X * the current library are included (to make sure that we don't accidentaly get 
  807. X * the libc versions. (This is the lazy man's -u ld directive)
  808. X */
  809. X
  810. XVOIDTYPE    (*malloc_void_funcs[])() =
  811. X{
  812. X    free,
  813. X};
  814. X
  815. Xint        (*malloc_int_funcs[])() =
  816. X{
  817. X    strcmp,
  818. X    memcmp,
  819. X};
  820. X
  821. XDATATYPE    * (*malloc_char_star_funcs[])() =
  822. X{
  823. X    _malloc,
  824. X    debug_realloc,
  825. X    debug_calloc,
  826. X};
  827. X
  828. X/*
  829. X * Function:    malloc_fatal()
  830. X *
  831. X * Purpose:    to display fatal error message and take approrpriate action
  832. X *
  833. X * Arguments:    funcname - name of function calling this routine
  834. X *        mptr     - pointer to malloc block associated with error
  835. X *
  836. X * Returns:    nothing of any value
  837. X *
  838. X * Narrative:
  839. X *
  840. X * Notes:    This routine does not make use of any libc functions to build
  841. X *        and/or disply the error message.  This is due to the fact that
  842. X *        we are probably at a point where malloc is having a real problem
  843. X *        and we don't want to call any function that may use malloc.
  844. X */
  845. XVOIDTYPE
  846. Xmalloc_fatal(funcname,file,line,mptr)
  847. X    CONST char        * funcname;
  848. X    CONST char        * file;
  849. X    int              line;
  850. X    CONST struct mlist    * mptr;
  851. X{
  852. X    char          errbuf[ERRBUFSIZE];
  853. X    char        * s;
  854. X    CONST char    * t;
  855. X
  856. X    s = errbuf;
  857. X    t = "MALLOC Fatal error from ";
  858. X    COPY(s,t,errbuf,ERRBUFSIZE);
  859. X
  860. X    t = funcname;
  861. X    COPY(s,t,errbuf,ERRBUFSIZE);
  862. X
  863. X    t = "()";
  864. X    COPY(s,t,errbuf,ERRBUFSIZE);
  865. X
  866. X    /*
  867. X     * if we have a file and line number, show it
  868. X      */
  869. X    if( file != NULL )
  870. X    {
  871. X        t = " (called from ";
  872. X        COPY(s,t,errbuf,ERRBUFSIZE);
  873. X        
  874. X        t = file;
  875. X        COPY(s,t,errbuf,ERRBUFSIZE);
  876. X
  877. X        t = " line ";
  878. X        COPY(s,t,errbuf,ERRBUFSIZE);
  879. X
  880. X        s += tostring(s,(ULONG)line,0,10,' ');
  881. X
  882. X        *s++ = ')';
  883. X
  884. X    }
  885. X
  886. X    *s++ = ':';
  887. X    *s++ = '\n';
  888. X
  889. X    t = malloc_err_strings[malloc_errno];
  890. X    COPY(s,t,errbuf,ERRBUFSIZE);
  891. X
  892. X    *(s++) = '\n';
  893. X
  894. X    if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf)) != (s-errbuf))
  895. X    {
  896. X        VOIDCAST write(2,"I/O error to error file\n",(WRTSIZE)24);
  897. X        exit(110);
  898. X    }
  899. X
  900. X    /*
  901. X     * if this error was associated with an identified malloc block,
  902. X     * dump the malloc info for the block.
  903. X     */
  904. X    if( mptr )
  905. X    {
  906. X        malloc_dump_info_block(mptr,DUMP_PTR);
  907. X    }
  908. X
  909. X    malloc_err_handler(malloc_fatal_level);
  910. X
  911. X} /* malloc_fatal(... */
  912. X
  913. X/*
  914. X * Function:    malloc_warning()
  915. X *
  916. X * Purpose:    to display warning error message and take approrpriate action
  917. X *
  918. X * Arguments:    funcname - name of function calling this routine
  919. X *        mptr     - pointer to malloc block associated with error
  920. X *
  921. X * Returns:    nothing of any value
  922. X *
  923. X * Narrative:
  924. X *
  925. X * Notes:    This routine does not make use of any libc functions to build
  926. X *        and/or disply the error message.  This is due to the fact that
  927. X *        we are probably at a point where malloc is having a real problem
  928. X *        and we don't want to call any function that may use malloc.
  929. X */
  930. XVOIDTYPE
  931. Xmalloc_warning(funcname,file,line,mptr)
  932. X    CONST char        * funcname;
  933. X    CONST char        * file;
  934. X    int              line;
  935. X    CONST struct mlist    * mptr;
  936. X{
  937. X    char          errbuf[ERRBUFSIZE];
  938. X    char        * s;
  939. X    CONST char    * t;
  940. X
  941. X    s = errbuf;
  942. X    t = "MALLOC Warning from ";
  943. X    COPY(s,t,errbuf,ERRBUFSIZE);
  944. X
  945. X    t = funcname;
  946. X    COPY(s,t,errbuf,ERRBUFSIZE);
  947. X
  948. X    t = "()";
  949. X    COPY(s,t,errbuf,ERRBUFSIZE);
  950. X
  951. X    /*
  952. X     * if we have a file and line number, show it
  953. X      */
  954. X    if( file != NULL )
  955. X    {
  956. X        t = " (called from ";
  957. X        COPY(s,t,errbuf,ERRBUFSIZE);
  958. X        
  959. X        t = file;
  960. X        COPY(s,t,errbuf,ERRBUFSIZE);
  961. X
  962. X        t = " line ";
  963. X        COPY(s,t,errbuf,ERRBUFSIZE);
  964. X
  965. X        s += tostring(s,(ULONG)line,0,10,' ');
  966. X
  967. X        *s++ = ')';
  968. X
  969. X    }
  970. X
  971. X    *s++ = ':';
  972. X    *s++ = '\n';
  973. X
  974. X    t = malloc_err_strings[malloc_errno];
  975. X    COPY(s,t,errbuf,ERRBUFSIZE);
  976. X
  977. X    *(s++) = '\n';
  978. X
  979. X    if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf)) != (s-errbuf))
  980. X    {
  981. X        VOIDCAST write(2,"I/O error to error file\n",(WRTSIZE)24);
  982. X        exit(110);
  983. X    }
  984. X
  985. X    /*
  986. X     * if this error was associated with an identified malloc block,
  987. X     * dump the malloc info for the block.
  988. X     */
  989. X    if( mptr )
  990. X    {
  991. X        malloc_dump_info_block(mptr,DUMP_PTR);
  992. X    }
  993. X
  994. X        
  995. X    malloc_err_handler(malloc_warn_level);
  996. X
  997. X} /* malloc_warning(... */
  998. X
  999. X/*
  1000. X * Function:    malloc_dump_info_block()
  1001. X *
  1002. X * Purpose:    to display identifying information on an offending malloc
  1003. X *        block to help point the user in the right direction
  1004. X *
  1005. X * Arguments:    mptr - pointer to malloc block
  1006. X *
  1007. X * Returns:    nothing of any value
  1008. X *
  1009. X * Narrative:
  1010. X *
  1011. X * Notes:    This routine does not make use of any libc functions to build
  1012. X *        and/or disply the error message.  This is due to the fact that
  1013. X *        we are probably at a point where malloc is having a real
  1014. X *        problem and we don't want to call any function that may use
  1015. X *         malloc.
  1016. X */
  1017. XVOIDTYPE
  1018. Xmalloc_dump_info_block(mptr,id)
  1019. X    CONST struct mlist    * mptr;
  1020. X    int              id;
  1021. X{
  1022. X    char          errbuf[ERRBUFSIZE];
  1023. X    CONST char    * funcname;
  1024. X    char        * s;
  1025. X    CONST char    * t;
  1026. X
  1027. X    /*
  1028. X     * if the mlist struct does not have a valid magic number, skip it
  1029. X     * because we probably have gotten clobbered.
  1030. X     */
  1031. X    if( (mptr->flag&M_MAGIC_BITS) != M_MAGIC )
  1032. X    {
  1033. X        return;
  1034. X    }
  1035. X
  1036. X    s = errbuf;
  1037. X
  1038. X    if( id == DUMP_PTR )
  1039. X    {
  1040. X        t = "This error is *probably* associated with the following";
  1041. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1042. X
  1043. X        t = " allocation:\n\n\tA call to ";
  1044. X    }
  1045. X    else if( id == DUMP_PREV )
  1046. X    {
  1047. X        if( mptr == NULL || (mptr == &malloc_start) )
  1048. X        {
  1049. X            t = "\tThere is no malloc chain element prior to the";
  1050. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1051. X
  1052. X            t = " suspect\n\t element identified above";
  1053. X        }
  1054. X        else
  1055. X        {
  1056. X            t = "\tThe malloc chain element prior to the suspect";
  1057. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1058. X
  1059. X            t = " allocation is from:\n\n\tA call to ";
  1060. X        }
  1061. X    }
  1062. X    else
  1063. X    {
  1064. X        if( (mptr == NULL) ||
  1065. X            ((mptr == malloc_end) && (GETTYPE(mptr) == M_T_SPLIT)) )
  1066. X        {
  1067. X            t = "\tThere is no malloc chain element after the";
  1068. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1069. X
  1070. X            t = " suspect\n\t element identified above";
  1071. X        }
  1072. X        else
  1073. X        {
  1074. X            t ="\tThe malloc chain element following the suspect";
  1075. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1076. X        
  1077. X            t = " allocation is from:\n\n\tA call to ";
  1078. X        }
  1079. X    }
  1080. X    COPY(s,t,errbuf,ERRBUFSIZE);
  1081. X
  1082. X    /*
  1083. X     * if this is a real-live malloc block (the starting block and
  1084. X     * the last block (if it was generated by a malloc split) don't
  1085. X     * count as real blocks since the user never allocated them.
  1086. X     */
  1087. X    if( (mptr != NULL) && (mptr != &malloc_start)  &&
  1088. X        ((mptr != malloc_end) || (GETTYPE(mptr) != M_T_SPLIT)) )
  1089. X    {
  1090. X
  1091. X        funcname = t = MallocFuncName(mptr);
  1092. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1093. X
  1094. X        t = " for ";
  1095. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1096. X
  1097. X        s += tostring(s,(ULONG)mptr->r_size,0,10,' ');
  1098. X
  1099. X        t = " bytes in ";
  1100. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1101. X
  1102. X        /*
  1103. X         * if we don't have file info
  1104. X          */
  1105. X        if( (mptr->file == NULL) || (mptr->file[0] == EOS) )
  1106. X        {
  1107. X            t = "an unknown file";
  1108. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1109. X        }
  1110. X        else
  1111. X        {
  1112. X            t = mptr->file;
  1113. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1114. X
  1115. X            t = " on line ";
  1116. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1117. X            
  1118. X            s += tostring(s,(ULONG)mptr->line,0,10,' ');
  1119. X        }
  1120. X
  1121. X        t = ".\n\tThis was the ";
  1122. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1123. X
  1124. X        s += tostring(s,(ULONG)mptr->id,0,10,' ');
  1125. X
  1126. X        t = malloc_int_suffix(mptr->id);
  1127. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1128. X
  1129. X        t = " call to ";
  1130. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1131. X
  1132. X        t = funcname;
  1133. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1134. X
  1135. X        t = ".\n";
  1136. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1137. X        
  1138. X        if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf))!=(s-errbuf))
  1139. X        {
  1140. X            VOIDCAST write(2,"I/O error to error file\n",
  1141. X                    (WRTSIZE)24);
  1142. X            exit(110);
  1143. X        }
  1144. X
  1145. X        StackDump(malloc_errfd, "\tStack from where allocated:\n",
  1146. X                  mptr->stack);
  1147. X
  1148. X        s = errbuf;
  1149. X        *s++ = '\n';
  1150. X        
  1151. X        /*
  1152. X         * if the block is not currently in use
  1153. X         */
  1154. X        if(  (mptr->flag & M_INUSE) == 0 )
  1155. X        {
  1156. X            t="\tThis block was freed on the ";
  1157. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1158. X
  1159. X            s += tostring(s,(ULONG)mptr->fid,0,10,' ');
  1160. X
  1161. X            t = malloc_int_suffix(mptr->fid);
  1162. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1163. X
  1164. X            t = " call to ";
  1165. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1166. X
  1167. X            t = FreeFuncName(mptr);
  1168. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1169. X
  1170. X            t = "()";
  1171. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1172. X
  1173. X            /*
  1174. X             * if we know where it was freed
  1175. X             */
  1176. X            if( mptr->ffile != NULL )
  1177. X            {
  1178. X                t = "\n\tin ";
  1179. X                COPY(s,t,errbuf,ERRBUFSIZE);
  1180. X
  1181. X                t = mptr->ffile;
  1182. X                COPY(s,t,errbuf,ERRBUFSIZE);
  1183. X
  1184. X                t = " on line ";
  1185. X                COPY(s,t,errbuf,ERRBUFSIZE);
  1186. X            
  1187. X                s += tostring(s,(ULONG)mptr->fline,0,10,' ');
  1188. X            }
  1189. X
  1190. X            t = ".\n";
  1191. X            COPY(s,t,errbuf,ERRBUFSIZE);
  1192. X        
  1193. X            if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf))
  1194. X                != (s-errbuf))
  1195. X            {
  1196. X                VOIDCAST write(2,"I/O error to error file\n",
  1197. X                    (WRTSIZE)24);
  1198. X                exit(110);
  1199. X            }
  1200. X
  1201. X            StackDump(malloc_errfd, "\tStack from where freed:\n",
  1202. X                  mptr->freestack);
  1203. X
  1204. X            s = errbuf;
  1205. X            *s++ = '\n';
  1206. X        }
  1207. X        
  1208. X    }
  1209. X    else
  1210. X    {
  1211. X        t = ".\n\n";
  1212. X        COPY(s,t,errbuf,ERRBUFSIZE);
  1213. X    }
  1214. X
  1215. X        
  1216. X    if( write(malloc_errfd,errbuf,(WRTSIZE)(s-errbuf)) != (s-errbuf))
  1217. X    {
  1218. X        VOIDCAST write(2,"I/O error to error file\n", (WRTSIZE)24);
  1219. X        exit(110);
  1220. X    }
  1221. X
  1222. X    /*
  1223. X     * if this is the primary suspect and we are showing links
  1224. X     */
  1225. X    if( (malloc_opts & MOPT_SLINKS) && (id == DUMP_PTR ) )
  1226. X    {
  1227. X        /*
  1228. X         * show the previous and next malloc regions.
  1229. X         */
  1230. X        malloc_dump_info_block(mptr->prev,DUMP_PREV);
  1231. X        malloc_dump_info_block(mptr->next,DUMP_NEXT);
  1232. X    }
  1233. X        
  1234. X} /* malloc_dump_info_block(... */
  1235. X
  1236. X/*
  1237. X * Function:    malloc_err_handler()
  1238. X *
  1239. X * Purpose:    to take the appropriate action for warning and/or fatal 
  1240. X *        error conditions.
  1241. X *
  1242. X * Arguments:    level - error handling level 
  1243. X *
  1244. X * Returns:    nothing of any value
  1245. X *
  1246. X * Narrative:
  1247. X *
  1248. X * Notes:    This routine does not make use of any libc functions to build
  1249. X *        and/or disply the error message.  This is due to the fact that
  1250. X *        we are probably at a point where malloc is having a real problem
  1251. X *        and we don't want to call any function that may use malloc.
  1252. X */
  1253. XVOIDTYPE
  1254. Xmalloc_err_handler(level)
  1255. X    int          level;
  1256. X{
  1257. X
  1258. X    if( level & M_HANDLE_DUMP )
  1259. X    {
  1260. X        malloc_dump(malloc_errfd);
  1261. X    }
  1262. X
  1263. X    switch( level & ~M_HANDLE_DUMP )
  1264. X    {
  1265. X        /*
  1266. X         * If we are to drop a core file and exit
  1267. X         */
  1268. X        case M_HANDLE_ABORT:
  1269. X            VOIDCAST signal(ABORT_SIGNAL, SIG_DFL);
  1270. X
  1271. X            /*
  1272. X             * first try the generic abort function
  1273. X              */
  1274. X            VOIDCAST malloc_abort();
  1275. X
  1276. X            /*
  1277. X              * if we are still here, then use the real abort
  1278. X             */
  1279. X            VOIDCAST abort();
  1280. X
  1281. X            /*
  1282. X              * and if we are still here, just exit.
  1283. X             */
  1284. X            exit(201);
  1285. X            break;
  1286. X
  1287. X        /*
  1288. X         * If we are to exit..
  1289. X         */
  1290. X        case M_HANDLE_EXIT:
  1291. X            exit(200);
  1292. X            break;
  1293. X
  1294. X        /*
  1295. X         * If we are to dump a core, but keep going on our merry way
  1296. X         */
  1297. X        case M_HANDLE_CORE:
  1298. X            {
  1299. X                int      pid;
  1300. X
  1301. X                /*
  1302. X                 * fork so child can abort (and dump core)
  1303. X                 */
  1304. X                if( (pid = fork()) == 0 )
  1305. X                {
  1306. X                    VOIDCAST write(malloc_errfd,
  1307. X                            "Child dumping core\n",
  1308. X                            (WRTSIZE)19);
  1309. X                    VOIDCAST signal(ABORT_SIGNAL, SIG_DFL);
  1310. X                    /*
  1311. X                     * first try the generic abort function
  1312. X                     */
  1313. X                    VOIDCAST malloc_abort();
  1314. X                    /*
  1315. X                     * then try the real abort
  1316. X                     */
  1317. X                    VOIDCAST abort();
  1318. X                    /*
  1319. X                     * if the abort doesn't cause us to
  1320. X                     * die, then we may as well just exit
  1321. X                     */
  1322. X                    exit(201);
  1323. X                }
  1324. X
  1325. X                /*
  1326. X                  * wait for child to finish dumping core
  1327. X                 */
  1328. X                while( wait((int *)0) != pid)
  1329. X                {
  1330. X                }
  1331. X
  1332. X                /*
  1333. X                 * Move core file to core.pid.cnt so 
  1334. X                 * multiple cores don't overwrite each
  1335. X                 * other.
  1336. X                 */
  1337. X                if( access("core",0) == 0 )
  1338. X                {
  1339. X                    static int      corecnt;
  1340. X                    char            filenam[32];
  1341. X                    filenam[0] = 'c';
  1342. X                    filenam[1] = 'o';
  1343. X                    filenam[2] = 'r';
  1344. X                    filenam[3] = 'e';
  1345. X                    filenam[4] = '.';
  1346. X                    VOIDCAST tostring(filenam+5,
  1347. X                        (ULONG)getpid(),
  1348. X                        5, B_DEC, '0');
  1349. X                    filenam[10] = '.';
  1350. X                    VOIDCAST tostring(filenam+11,
  1351. X                        (ULONG)corecnt++,
  1352. X                        3, B_DEC, '0');
  1353. X                    filenam[14] = '\0';
  1354. X                    VOIDCAST unlink(filenam);
  1355. X                    if( link("core",filenam) == 0)
  1356. X                    {
  1357. X                        VOIDCAST unlink("core");
  1358. X                    }
  1359. X                }
  1360. X            }
  1361. X
  1362. X
  1363. X        /* 
  1364. X         * If we are to just ignore the error and keep on processing
  1365. X         */
  1366. X        case M_HANDLE_IGNORE:
  1367. X            break;
  1368. X
  1369. X    } /* switch(... */
  1370. X
  1371. X} /* malloc_err_handler(... */
  1372. X
  1373. X/*
  1374. X * Function:    malloc_int_suffix()
  1375. X *
  1376. X * Purpose:    determine the correct suffix for the integer passed 
  1377. X *        (i.e. the st on 1st, nd on 2nd).
  1378. X *
  1379. X * Arguments:    i - the integer whose suffix is desired.
  1380. X *
  1381. X * Returns:    pointer to the suffix
  1382. X *
  1383. X * Narrative:
  1384. X *
  1385. X */
  1386. XCONST char *
  1387. Xmalloc_int_suffix(i)
  1388. X    IDTYPE      i;
  1389. X{
  1390. X    int          j;
  1391. X    CONST char    * rtn;
  1392. X
  1393. X    /*
  1394. X     * since the suffixes repeat for the same number within a
  1395. X     * given 100 block (i.e. 111 and 211 use the same suffix), get the 
  1396. X     * integer moded by 100.
  1397. X     */
  1398. X    i = i % 100;
  1399. X    j = i % 10;
  1400. X
  1401. X    /*
  1402. X     * if the number is 11, or 12, or 13 or its singles digit is
  1403. X     * not a 1, 2, or 3, the suffix must be th.
  1404. X     */
  1405. X    if( (i == 11) || (i == 12) || (i == 13) ||
  1406. X        ( (j != 1) && (j != 2) && (j != 3) ) )
  1407. X    {
  1408. X        rtn = "th";
  1409. X    }
  1410. X    else 
  1411. X    {
  1412. X        switch(j)
  1413. X        {
  1414. X            case 1:
  1415. X                rtn = "st";
  1416. X                break;
  1417. X            case 2:
  1418. X                rtn = "nd";
  1419. X                break;
  1420. X            case 3:
  1421. X                rtn = "rd";
  1422. X                break;
  1423. X            default:
  1424. X                rtn = "th";
  1425. X                break;
  1426. X        }
  1427. X    }
  1428. X
  1429. X    return(rtn);
  1430. X    
  1431. X} /* malloc_int_suffix(... */
  1432. X
  1433. X/*
  1434. X * Function:    malloc_freeseg()
  1435. X *
  1436. X * Purpose:    to add or remove a segment from the list of free segments
  1437. X *
  1438. X * Arguments:    op  - operation (M_FREE_REMOVE or M_FREE_ADD)
  1439. X *        ptr - ptr to segment to be added/removed
  1440. X *
  1441. X * Returns:    nothing of any value
  1442. X *
  1443. X * Narrative:
  1444. X *
  1445. X */
  1446. XVOIDTYPE
  1447. Xmalloc_freeseg(op,ptr)
  1448. X    int          op;
  1449. X    struct mlist    * ptr;
  1450. X{
  1451. X
  1452. X    /*
  1453. X     * if we are to remove it from the list
  1454. X     */
  1455. X    if( op == M_FREE_REMOVE )
  1456. X    {
  1457. X        /*
  1458. X         * if this is the head of the list, get a new head pointer
  1459. X         */
  1460. X        if( ptr == malloc_freelist )
  1461. X        {
  1462. X            malloc_freelist = malloc_freelist->freenext;
  1463. X        }
  1464. X
  1465. X        /*
  1466. X         * if there is an item after this one in the free list,
  1467. X         *    link it to our prev item (which may be null)
  1468. X         */
  1469. X        if( ptr->freenext != (struct mlist *) NULL)
  1470. X        {
  1471. X            ptr->freenext->freeprev = ptr->freeprev;
  1472. X        }
  1473. X
  1474. X        /*
  1475. X         * if there is an item before this one in the free list,
  1476. X         *    link it to the next item (which may also be NULL)
  1477. X          */
  1478. X        if( ptr->freeprev != (struct mlist *) NULL)
  1479. X        {
  1480. X            ptr->freeprev->freenext = ptr->freenext;
  1481. X        }
  1482. X
  1483. X        /*
  1484. X         * disable the free list pointers on the segment that was
  1485. X         * removed from the list.
  1486. X         */
  1487. X        ptr->freenext = ptr->freeprev = (struct mlist *) NULL;
  1488. X
  1489. X    }
  1490. X    else /* it is an add */
  1491. X    {
  1492. X        /*
  1493. X         * setup the new links for the new head pointer (new items are
  1494. X          * always placed at the begining of the list.  However, they may
  1495. X         * be removed from anywhere in the list (hence the double
  1496. X         * linking))
  1497. X         */
  1498. X        ptr->freeprev = (struct mlist *) NULL;
  1499. X        ptr->freenext = malloc_freelist;
  1500. X        
  1501. X
  1502. X        /*
  1503. X          * if there was already a valid head pointer
  1504. X         */
  1505. X        if( malloc_freelist != (struct mlist *) NULL )
  1506. X        {
  1507. X            /*
  1508. X             * link it back to the new head pointer
  1509. X             */
  1510. X            malloc_freelist->freeprev = ptr;
  1511. X        }
  1512. X        /*
  1513. X         * store the new head pointer
  1514. X         */
  1515. X        malloc_freelist = ptr;
  1516. X
  1517. X    }
  1518. X
  1519. X} /* malloc_freeseg(... */
  1520. X
  1521. XCONST char *
  1522. XMallocFuncName(mptr)
  1523. X    CONST struct mlist    * mptr;
  1524. X{
  1525. X    CONST char            * rtn;
  1526. X
  1527. X    /*
  1528. X     * get the function name 
  1529. X     */
  1530. X    switch(GETTYPE(mptr))
  1531. X    {
  1532. X        case M_T_MALLOC:
  1533. X            rtn = "malloc";
  1534. X            break;
  1535. X        case M_T_REALLOC:
  1536. X            rtn = "realloc";
  1537. X            break;
  1538. X        case M_T_CALLOC:
  1539. X            rtn = "calloc";
  1540. X            break;
  1541. X        case M_T_SPLIT:
  1542. X            rtn = "splitfunc";
  1543. X            break;
  1544. X        case M_T_XTMALLOC:
  1545. X            rtn = "XtMalloc";
  1546. X            break;
  1547. X        case M_T_XTREALLOC:
  1548. X            rtn = "XtRealloc";
  1549. X            break;
  1550. X        case M_T_XTCALLOC:
  1551. X            rtn = "XtCalloc";
  1552. X            break;
  1553. X        case M_T_ALIGNED:
  1554. X            rtn = "memalign";
  1555. X            break;
  1556. X        default:
  1557. X            rtn = "Unknown";
  1558. X            break;
  1559. X    }
  1560. X
  1561. X    return( rtn );
  1562. X
  1563. X} /* MallocFuncName(... */
  1564. X
  1565. XCONST char *
  1566. XFreeFuncName(mptr)
  1567. X    CONST struct mlist    * mptr;
  1568. X{
  1569. X    CONST char        * rtn;
  1570. X
  1571. X    /*
  1572. X     * get the function name 
  1573. X     */
  1574. X    switch(GETFTYPE(mptr))
  1575. X    {
  1576. X        case F_T_FREE:
  1577. X            rtn = "free";
  1578. X            break;
  1579. X        case F_T_CFREE:
  1580. X            rtn = "cfree";
  1581. X            break;
  1582. X        case F_T_XTFREE:
  1583. X            rtn = "XtFree";
  1584. X            break;
  1585. X        case F_T_REALLOC:
  1586. X            rtn = "realloc";
  1587. X            break;
  1588. X        default:
  1589. X            rtn = "Unknown";
  1590. X            break;
  1591. X    }
  1592. X
  1593. X    return(rtn);
  1594. X
  1595. X} /* FreeFuncName(... */
  1596. X
  1597. Xvoid
  1598. XInitMlist(mptr,type)
  1599. X    struct mlist    * mptr;
  1600. X    int          type;
  1601. X{
  1602. X    DataMS((MEMDATA *) mptr,'\0', sizeof( struct mlist));
  1603. X
  1604. X    mptr->flag = M_MAGIC;
  1605. X    SETTYPE(mptr,type);
  1606. X
  1607. X    mptr->hist_id = malloc_hist_id++;
  1608. X
  1609. X}
  1610. X
  1611. X/*
  1612. X * $Log: malloc.c,v $
  1613. X * Revision 1.43  1992/09/03  22:24:33  cpcahil
  1614. X * final changes for PL14
  1615. X *
  1616. X * Revision 1.42  1992/08/22  16:27:13  cpcahil
  1617. X * final changes for pl14
  1618. X *
  1619. X * Revision 1.41  1992/07/31  11:47:30  cpcahil
  1620. X * added setting of free-file pointer when splitting off a segment
  1621. X *
  1622. X * Revision 1.40  1992/07/12  15:30:58  cpcahil
  1623. X * Merged in Jonathan I Kamens' changes
  1624. X *
  1625. X * Revision 1.39  1992/07/03  00:03:25  cpcahil
  1626. X * more fixes for pl13, several suggestons from Rich Salz.
  1627. X *
  1628. X * Revision 1.38  1992/06/30  13:06:39  cpcahil
  1629. X * added support for aligned allocations
  1630. X *
  1631. X * Revision 1.37  1992/06/22  23:40:10  cpcahil
  1632. X * many fixes for working on small int systems
  1633. X *
  1634. X * Revision 1.36  1992/05/09  00:16:16  cpcahil
  1635. X * port to hpux and lots of fixes
  1636. X *
  1637. X * Revision 1.35  1992/05/08  02:39:58  cpcahil
  1638. X * minor fixups
  1639. X *
  1640. X * Revision 1.34  1992/05/08  02:30:35  cpcahil
  1641. X * minor cleanups from minix/atari port
  1642. X *
  1643. X * Revision 1.33  1992/05/06  05:37:44  cpcahil
  1644. X * added overriding of fill characters and boundary size
  1645. X *
  1646. X * Revision 1.32  1992/05/06  04:53:29  cpcahil
  1647. X * performance enhancments
  1648. X *
  1649. X * Revision 1.31  1992/04/24  12:09:13  cpcahil
  1650. X * (hopefully) final cleanup for patch 10
  1651. X *
  1652. X * Revision 1.30  1992/04/24  11:18:52  cpcahil
  1653. X * Fixes from Denny Page and Better integration of Xt alloc hooks
  1654. X *
  1655. X * Revision 1.29  1992/04/22  18:17:32  cpcahil
  1656. X * added support for Xt Alloc functions, linted code
  1657. X *
  1658. X * Revision 1.28  1992/04/20  22:29:14  cpcahil
  1659. X * changes to fix problems introduced by insertion of size_t
  1660. X *
  1661. X * Revision 1.27  1992/04/20  22:03:44  cpcahil
  1662. X * added setting of filled flag.
  1663. X *
  1664. X * Revision 1.26  1992/04/15  12:51:06  cpcahil
  1665. X * fixes per testing of patch 8
  1666. X *
  1667. X * Revision 1.25  1992/04/13  17:26:25  cpcahil
  1668. X * minor portability changes
  1669. X *
  1670. X * Revision 1.24  1992/04/13  13:56:02  cpcahil
  1671. X * added auto-determination of abort signal to ensure that we have
  1672. X * a valid signal for this system.
  1673. X *
  1674. X * Revision 1.23  1992/04/13  03:06:33  cpcahil
  1675. X * Added Stack support, marking of non-leaks, auto-config, auto-testing
  1676. X *
  1677. X * Revision 1.22  1992/03/01  12:42:38  cpcahil
  1678. X * added support for managing freed areas and fixed doublword bndr problems
  1679. X *
  1680. X * Revision 1.21  1992/02/19  02:33:07  cpcahil
  1681. X * added code to ensure that aborts really happen.
  1682. X *
  1683. X * Revision 1.20  1992/01/30  12:23:06  cpcahil
  1684. X * renamed mallocint.h -> mallocin.h
  1685. X *
  1686. X * Revision 1.19  1992/01/28  16:35:37  cpcahil
  1687. X * increased size of error string buffers and added overflow checks
  1688. X *
  1689. X * Revision 1.18  1992/01/10  17:51:03  cpcahil
  1690. X * more void stuff that slipped by
  1691. X *
  1692. X * Revision 1.17  1992/01/10  17:28:03  cpcahil
  1693. X * Added support for overriding void datatype
  1694. X *
  1695. X * Revision 1.16  1992/01/08  19:40:07  cpcahil
  1696. X * fixed write() count to display entire message.
  1697. X *
  1698. X * Revision 1.15  1991/12/31  21:31:26  cpcahil
  1699. X * changes for patch 6.  See CHANGES file for more info
  1700. X *
  1701. X * Revision 1.14  1991/12/06  08:50:48  cpcahil
  1702. X * fixed bug in malloc_safe_memset introduced in last change.
  1703. X *
  1704. X * Revision 1.13  91/12/04  18:01:21  cpcahil
  1705. X * cleand up some aditional warnings from gcc -Wall
  1706. X * 
  1707. X * Revision 1.12  91/12/04  09:23:39  cpcahil
  1708. X * several performance enhancements including addition of free list
  1709. X * 
  1710. X * Revision 1.11  91/12/02  19:10:10  cpcahil
  1711. X * changes for patch release 5
  1712. X * 
  1713. X * Revision 1.10  91/11/25  14:41:59  cpcahil
  1714. X * Final changes in preparation for patch 4 release
  1715. X * 
  1716. X * Revision 1.9  91/11/24  16:56:41  cpcahil
  1717. X * porting changes for patch level 4
  1718. X * 
  1719. X * Revision 1.8  91/11/24  00:49:27  cpcahil
  1720. X * first cut at patch 4
  1721. X * 
  1722. X * Revision 1.7  91/11/20  11:54:09  cpcahil
  1723. X * interim checkin
  1724. X * 
  1725. X * Revision 1.6  90/05/11  00:13:09  cpcahil
  1726. X * added copyright statment
  1727. X * 
  1728. X * Revision 1.5  90/02/25  11:01:18  cpcahil
  1729. X * added support for malloc chain checking.
  1730. X * 
  1731. X * Revision 1.4  90/02/24  21:50:21  cpcahil
  1732. X * lots of lint fixes
  1733. X * 
  1734. X * Revision 1.3  90/02/24  14:51:18  cpcahil
  1735. X * 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed
  1736. X *    the function name as a parameter.
  1737. X * 2. Added several function headers.
  1738. X * 3. Changed uses of malloc_fatal/warning to conform to new usage.
  1739. X * 
  1740. X * Revision 1.2  90/02/23  18:05:23  cpcahil
  1741. X * fixed open of error log to use append mode.
  1742. X * 
  1743. X * Revision 1.1  90/02/22  23:17:43  cpcahil
  1744. X * Initial revision
  1745. X * 
  1746. X */
  1747. END_OF_FILE
  1748. if test 36595 -ne `wc -c <'malloc.c'`; then
  1749.     echo shar: \"'malloc.c'\" unpacked with wrong size!
  1750. fi
  1751. # end of 'malloc.c'
  1752. fi
  1753. if test -f 'mallopt.c' -a "${1}" != "-c" ; then 
  1754.   echo shar: Will not clobber existing file \"'mallopt.c'\"
  1755. else
  1756. echo shar: Extracting \"'mallopt.c'\" \(5775 characters\)
  1757. sed "s/^X//" >'mallopt.c' <<'END_OF_FILE'
  1758. X
  1759. X/*
  1760. X * (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
  1761. X *
  1762. X * This software may be distributed freely as long as the following conditions
  1763. X * are met:
  1764. X *         * the distribution, or any derivative thereof, may not be
  1765. X *          included as part of a commercial product
  1766. X *        * full source code is provided including this copyright
  1767. X *        * there is no charge for the software itself (there may be
  1768. X *          a minimal charge for the copying or distribution effort)
  1769. X *        * this copyright notice is not modified or removed from any
  1770. X *          source file
  1771. X */
  1772. X#include <stdio.h>
  1773. X#include <fcntl.h>
  1774. X#include "mallocin.h"
  1775. X
  1776. X/*
  1777. X * Function:    dbmallopt()
  1778. X *
  1779. X * Purpose:    to set options for the malloc debugging library
  1780. X *
  1781. X * Arguments:    none
  1782. X *
  1783. X * Returns:    nothing of any value
  1784. X *
  1785. X * Narrative:    
  1786. X *
  1787. X */
  1788. X
  1789. X#ifndef lint
  1790. Xstatic
  1791. Xchar rcs_hdr[] = "$Id: mallopt.c,v 1.21 1992/08/22 16:27:13 cpcahil Exp $";
  1792. X#endif
  1793. X
  1794. Xint
  1795. Xdbmallopt(cmd,value)
  1796. X    int              cmd;
  1797. X    union dbmalloptarg    * value;
  1798. X{
  1799. X    int              baseflags = 0;
  1800. X    int              i;
  1801. X    int              newflag = 0;
  1802. X    register char        * s;
  1803. X    int              turnon = 0;
  1804. X
  1805. X    MALLOC_INIT();
  1806. X
  1807. X    switch(cmd)
  1808. X    {
  1809. X        case MALLOC_CKCHAIN:
  1810. X            newflag = MOPT_CKCHAIN;
  1811. X            turnon = value->i;
  1812. X            break;
  1813. X
  1814. X        case MALLOC_CKDATA:
  1815. X            newflag = MOPT_CKDATA;
  1816. X            turnon = value->i;
  1817. X            break;
  1818. X
  1819. X        case MALLOC_DETAIL:
  1820. X            turnon = value->i;
  1821. X            newflag = MOPT_DETAIL;
  1822. X            break;
  1823. X
  1824. X        case MALLOC_ERRFILE:
  1825. X            
  1826. X            if( strcmp(value->str,"-") != 0 )
  1827. X            {
  1828. X                if( malloc_errfd != 2 )
  1829. X                {
  1830. X                    close(malloc_errfd);    
  1831. X                }
  1832. X                i = open(value->str,
  1833. X                     O_CREAT|O_APPEND|O_WRONLY,0666);
  1834. X                if( i == -1 )
  1835. X                {
  1836. X                    VOIDCAST write(2,
  1837. X                      "Unable to open malloc error file: ",
  1838. X                      (WRTSIZE) 34);
  1839. X                    for(s=value->str; *s; s++)
  1840. X                    {
  1841. X                        /* do nothing */;
  1842. X                    }
  1843. X                    VOIDCAST write(2,value->str,
  1844. X                             (WRTSIZE)(s-(value->str)));
  1845. X                    VOIDCAST write(2,"\n",(WRTSIZE)1);
  1846. X                }
  1847. X                else
  1848. X                {
  1849. X                    if( malloc_errfd != 2 )
  1850. X                    {
  1851. X                        VOIDCAST close(malloc_errfd);
  1852. X                    }
  1853. X                    malloc_errfd = i;
  1854. X                }
  1855. X            }
  1856. X            else
  1857. X            {
  1858. X                if( malloc_errfd != 2 )
  1859. X                {
  1860. X                    close(malloc_errfd);    
  1861. X                }
  1862. X                malloc_errfd = 2;
  1863. X            }
  1864. X            
  1865. X            break;
  1866. X
  1867. X        case MALLOC_FATAL:
  1868. X            malloc_fatal_level = value->i;
  1869. X            break;
  1870. X
  1871. X        case MALLOC_FREEMARK:
  1872. X            turnon = value->i;
  1873. X            newflag = MOPT_FREEMARK;
  1874. X            break;
  1875. X
  1876. X        case MALLOC_FILLAREA:
  1877. X            baseflags = MOPT_MFILL | MOPT_FFILL;
  1878. X            switch(value->i)
  1879. X            {
  1880. X                case 1:
  1881. X                    newflag = MOPT_DFILL;
  1882. X                    break;
  1883. X                case 2:
  1884. X                    newflag = MOPT_MFILL | MOPT_DFILL;
  1885. X                    break;
  1886. X                case 0:
  1887. X                case 3:
  1888. X                default:
  1889. X                    newflag = MOPT_MFILL | MOPT_FFILL
  1890. X                                 | MOPT_DFILL;
  1891. X                    break;
  1892. X            }
  1893. X            turnon = value->i;    
  1894. X
  1895. X            /*
  1896. X             * if we ever enable malloc_checking, then we set the
  1897. X             * malloc_check flag to non-zero.  Then it can never be
  1898. X             * set back to zero.  This is done as a performance 
  1899. X             * increase if filling is never enabled.
  1900. X             */
  1901. X            if( (turnon != 0) && (newflag != 0) )
  1902. X            {
  1903. X                malloc_fill = 1;
  1904. X            }
  1905. X            
  1906. X            break;
  1907. X
  1908. X        case MALLOC_LOWFRAG:
  1909. X            newflag = MOPT_LOWFRAG;
  1910. X            turnon = value->i;    
  1911. X            break;
  1912. X
  1913. X        case MALLOC_REUSE:
  1914. X            turnon = value->i;
  1915. X            newflag = MOPT_REUSE;
  1916. X            break;
  1917. X
  1918. X        case MALLOC_SHOWLINKS:
  1919. X            turnon = value->i;
  1920. X            newflag = MOPT_SLINKS;
  1921. X            break;
  1922. X
  1923. X        case MALLOC_WARN:
  1924. X            malloc_warn_level = value->i;
  1925. X            break;
  1926. X
  1927. X        case MALLOC_ZERO:
  1928. X            turnon = value->i;
  1929. X            newflag = MOPT_ZERO;
  1930. X            break;
  1931. X
  1932. X        default:
  1933. X            return(1);
  1934. X    }
  1935. X
  1936. X    /*
  1937. X     * if there are base flags, remove all of them so that they will
  1938. X     * not remain on forever.
  1939. X     */
  1940. X    if( baseflags )
  1941. X    {
  1942. X        malloc_opts &= ~baseflags;
  1943. X    }
  1944. X
  1945. X    /*
  1946. X     * if we have a new option flag, apply it to the options variable.
  1947. X     */
  1948. X    if( newflag )
  1949. X    {
  1950. X        if( turnon )
  1951. X        {
  1952. X            malloc_opts |= newflag;
  1953. X        }
  1954. X        else
  1955. X        {
  1956. X            malloc_opts &= ~newflag;
  1957. X        }
  1958. X    }
  1959. X
  1960. X    return(0);
  1961. X}
  1962. X
  1963. X/*
  1964. X * $Log: mallopt.c,v $
  1965. X * Revision 1.21  1992/08/22  16:27:13  cpcahil
  1966. X * final changes for pl14
  1967. X *
  1968. X * Revision 1.20  1992/07/03  00:03:25  cpcahil
  1969. X * more fixes for pl13, several suggestons from Rich Salz.
  1970. X *
  1971. X * Revision 1.19  1992/07/02  15:35:52  cpcahil
  1972. X * misc cleanups for PL13
  1973. X *
  1974. X * Revision 1.18  1992/06/30  13:06:39  cpcahil
  1975. X * added support for aligned allocations
  1976. X *
  1977. X * Revision 1.17  1992/06/22  23:40:10  cpcahil
  1978. X * many fixes for working on small int systems
  1979. X *
  1980. X * Revision 1.16  1992/05/06  04:53:29  cpcahil
  1981. X * performance enhancments
  1982. X *
  1983. X * Revision 1.15  1992/04/15  12:51:06  cpcahil
  1984. X * fixes per testing of patch 8
  1985. X *
  1986. X * Revision 1.14  1992/04/13  03:06:33  cpcahil
  1987. X * Added Stack support, marking of non-leaks, auto-config, auto-testing
  1988. X *
  1989. X * Revision 1.13  1992/03/01  12:42:38  cpcahil
  1990. X * added support for managing freed areas and fixed doublword bndr problems
  1991. X *
  1992. X * Revision 1.12  1992/01/30  12:23:06  cpcahil
  1993. X * renamed mallocint.h -> mallocin.h
  1994. X *
  1995. X * Revision 1.11  1992/01/10  17:28:03  cpcahil
  1996. X * Added support for overriding void datatype
  1997. X *
  1998. X * Revision 1.10  1991/12/31  21:31:26  cpcahil
  1999. X * changes for patch 6.  See CHANGES file for more info
  2000. X *
  2001. X * Revision 1.9  1991/12/04  09:23:42  cpcahil
  2002. X * several performance enhancements including addition of free list
  2003. X *
  2004. X * Revision 1.8  91/11/25  14:42:03  cpcahil
  2005. X * Final changes in preparation for patch 4 release
  2006. X * 
  2007. X * Revision 1.7  91/11/24  00:49:30  cpcahil
  2008. X * first cut at patch 4
  2009. X * 
  2010. X * Revision 1.6  90/08/29  22:23:36  cpcahil
  2011. X * fixed mallopt to use a union as an argument.
  2012. X * 
  2013. X * Revision 1.5  90/08/29  21:22:51  cpcahil
  2014. X * miscellaneous lint fixes
  2015. X * 
  2016. X * Revision 1.4  90/05/11  00:13:10  cpcahil
  2017. X * added copyright statment
  2018. X * 
  2019. X * Revision 1.3  90/02/25  11:03:26  cpcahil
  2020. X * changed to return int so that it agrees with l libmalloc.a's mallopt()
  2021. X * 
  2022. X * Revision 1.2  90/02/25  11:01:21  cpcahil
  2023. X * added support for malloc chain checking.
  2024. X * 
  2025. X * Revision 1.1  90/02/24  21:50:24  cpcahil
  2026. X * Initial revision
  2027. X * 
  2028. X * Revision 1.1  90/02/24  17:10:53  cpcahil
  2029. X * Initial revision
  2030. X * 
  2031. X */
  2032. END_OF_FILE
  2033. if test 5775 -ne `wc -c <'mallopt.c'`; then
  2034.     echo shar: \"'mallopt.c'\" unpacked with wrong size!
  2035. fi
  2036. # end of 'mallopt.c'
  2037. fi
  2038. if test -f 'mchain.c' -a "${1}" != "-c" ; then 
  2039.   echo shar: Will not clobber existing file \"'mchain.c'\"
  2040. else
  2041. echo shar: Extracting \"'mchain.c'\" \(5539 characters\)
  2042. sed "s/^X//" >'mchain.c' <<'END_OF_FILE'
  2043. X
  2044. X/*
  2045. X * (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
  2046. X *
  2047. X * This software may be distributed freely as long as the following conditions
  2048. X * are met:
  2049. X *         * the distribution, or any derivative thereof, may not be
  2050. X *          included as part of a commercial product
  2051. X *        * full source code is provided including this copyright
  2052. X *        * there is no charge for the software itself (there may be
  2053. X *          a minimal charge for the copying or distribution effort)
  2054. X *        * this copyright notice is not modified or removed from any
  2055. X *          source file
  2056. X */
  2057. X#include <stdio.h>
  2058. X#include <fcntl.h>
  2059. X#include "mallocin.h"
  2060. X
  2061. X/*
  2062. X * Function:    malloc_chain_check()
  2063. X *
  2064. X * Purpose:    to verify malloc chain is intact
  2065. X *
  2066. X * Arguments:    todo    - 0 - just check and return status
  2067. X *              1 - call malloc_warn if error detected
  2068. X *
  2069. X * Returns:    0    - malloc chain intact & no overflows
  2070. X *        other    - problems detected in malloc chain
  2071. X *
  2072. X * Narrative:
  2073. X *
  2074. X * Notes:    If todo is non-zero the malloc_warn function, when called
  2075. X *        may not return (i.e. it may exit)
  2076. X *
  2077. X */
  2078. X#ifndef lint
  2079. Xstatic
  2080. Xchar rcs_hdr[] = "$Id: mchain.c,v 1.14 1992/08/22 16:27:13 cpcahil Exp $";
  2081. X#endif
  2082. X
  2083. X
  2084. Xint
  2085. Xmalloc_chain_check(todo)
  2086. X    int          todo;
  2087. X{
  2088. X    return( DBmalloc_chain_check( (char *)NULL, 0, todo) );
  2089. X}
  2090. X
  2091. Xint
  2092. XDBmalloc_chain_check(file,line,todo)
  2093. X    CONST char    * file;
  2094. X    int          line;
  2095. X    int          todo;
  2096. X{
  2097. X    return( DBFmalloc_chain_check("malloc_chain_check",file,line,todo) );
  2098. X}
  2099. X
  2100. Xint
  2101. XDBFmalloc_chain_check(func,file,line,todo)
  2102. X    CONST char    * func;
  2103. X    CONST char    * file;
  2104. X    int          line;
  2105. X    int          todo;
  2106. X{
  2107. X    register struct mlist    * oldptr;
  2108. X    register struct mlist    * ptr;
  2109. X    int              rtn = 0;
  2110. X
  2111. X    MALLOC_INIT();
  2112. X
  2113. X    /*
  2114. X     * first check the full malloc chain
  2115. X     */
  2116. X    oldptr = &malloc_start;
  2117. X    for(ptr = malloc_start.next; ; oldptr = ptr, ptr = ptr->next)
  2118. X    {
  2119. X        /*
  2120. X         * Since the malloc chain is a forward only chain, any
  2121. X         * pointer that we get should always be positioned in 
  2122. X         * memory following the previous pointer.  If this is not
  2123. X         * so, we must have a corrupted chain.
  2124. X         */
  2125. X        if( ptr )
  2126. X        {
  2127. X            if(ptr < oldptr )
  2128. X            {
  2129. X                malloc_errno = M_CODE_CHAIN_BROKE;
  2130. X                if( todo )
  2131. X                {
  2132. X                    malloc_fatal(func,file,line,oldptr);
  2133. X                }
  2134. X                rtn++;
  2135. X                break;
  2136. X            }
  2137. X        }
  2138. X        else
  2139. X        {
  2140. X            if( malloc_end && (oldptr != malloc_end) )
  2141. X            {
  2142. X                /*
  2143. X                 * This should never happen.  If it does, then
  2144. X                 * we got a real problem.
  2145. X                 */
  2146. X                malloc_errno = M_CODE_NO_END;
  2147. X                if( todo )
  2148. X                {
  2149. X                    malloc_fatal(func,file,line,oldptr);
  2150. X                }
  2151. X                rtn++;
  2152. X            }
  2153. X            break;
  2154. X        }
  2155. X        
  2156. X        /*
  2157. X         * verify that ptr is within the malloc region...
  2158. X         * since we started within the malloc chain this should never
  2159. X         * happen.
  2160. X         */
  2161. X        if(    ((DATATYPE *)ptr < malloc_data_start)
  2162. X            || ((DATATYPE *)ptr > malloc_data_end) 
  2163. X            || ((((long)ptr) & malloc_round) != 0) )
  2164. X        {
  2165. X            malloc_errno = M_CODE_BAD_PTR;
  2166. X            if( todo )
  2167. X            {
  2168. X                malloc_fatal(func,file,line,oldptr);
  2169. X            }
  2170. X            rtn++;
  2171. X            break;
  2172. X        }
  2173. X
  2174. X        /* 
  2175. X         * verify magic flag is set
  2176. X         */
  2177. X        if( (ptr->flag&M_MAGIC_BITS) != M_MAGIC )
  2178. X        {
  2179. X            malloc_errno = M_CODE_BAD_MAGIC;
  2180. X            if( todo )
  2181. X            {
  2182. X                malloc_warning(func,file,line,
  2183. X                        (struct mlist *)NULL);
  2184. X            }
  2185. X            rtn++;
  2186. X            continue;
  2187. X        }
  2188. X
  2189. X        /* 
  2190. X         * verify segments are correctly linked together
  2191. X         */
  2192. X        if( (ptr->prev && (ptr->prev->next != ptr) ) ||
  2193. X            (ptr->next && (ptr->next->prev != ptr) ) ||
  2194. X            ((ptr->next == NULL) && (ptr->prev == NULL)) )
  2195. X        {
  2196. X            malloc_errno = M_CODE_BAD_CONNECT;
  2197. X            if( todo )
  2198. X            {
  2199. X                malloc_warning(func,file,line,ptr);
  2200. X            }
  2201. X            rtn++;
  2202. X            continue;
  2203. X        }
  2204. X
  2205. X        /*
  2206. X         * check for under and/or overflow on this segment
  2207. X         */
  2208. X        rtn +=  FILLCHECK(func,file,line,ptr,todo);
  2209. X
  2210. X    } /* for(... */
  2211. X
  2212. X    /*
  2213. X     * and now check the free list
  2214. X     */
  2215. X    oldptr = NULL;
  2216. X    for(ptr=malloc_freelist; (rtn == 0) && (ptr != NULL); ptr=ptr->freenext)
  2217. X    {
  2218. X        /*
  2219. X         * Since the malloc chain is a forward only chain, any
  2220. X         * pointer that we get should always be positioned in 
  2221. X         * memory following the previous pointer.  If this is not
  2222. X         * so, we must have a corrupted chain.
  2223. X         */
  2224. X        if( (oldptr != NULL) && (ptr < oldptr) )
  2225. X        {
  2226. X            malloc_errno = M_CODE_CHAIN_BROKE;
  2227. X            if( todo )
  2228. X            {
  2229. X                malloc_fatal(func,file,line,oldptr);
  2230. X            }
  2231. X            rtn++;
  2232. X        }
  2233. X        /*
  2234. X         * verify that ptr is within the malloc region...
  2235. X         * since we started within the malloc chain this should never
  2236. X         * happen.
  2237. X         */
  2238. X        else if(    ((DATATYPE *)ptr < malloc_data_start)
  2239. X                 || ((DATATYPE *)ptr > malloc_data_end) 
  2240. X                      || ((((long)ptr) & malloc_round) != 0) )
  2241. X        {
  2242. X            malloc_errno = M_CODE_BAD_PTR;
  2243. X            if( todo )
  2244. X            {
  2245. X                malloc_fatal(func,file,line,oldptr);
  2246. X            }
  2247. X            rtn++;
  2248. X        }
  2249. X        /* 
  2250. X         * verify magic flag is set
  2251. X         */
  2252. X        else if( (ptr->flag&M_MAGIC_BITS) != M_MAGIC )
  2253. X        {
  2254. X            malloc_errno = M_CODE_BAD_MAGIC;
  2255. X            if( todo )
  2256. X            {
  2257. X                malloc_warning(func,file,line,
  2258. X                        (struct mlist *)NULL);
  2259. X            }
  2260. X            rtn++;
  2261. X        }
  2262. X        /* 
  2263. X         * verify segments are correctly linked together
  2264. X         */
  2265. X        else if(   (ptr->freeprev && (ptr->freeprev->freenext != ptr) )
  2266. X            || (ptr->freenext && (ptr->freenext->freeprev != ptr) ))
  2267. X        {
  2268. X            malloc_errno = M_CODE_BAD_CONNECT;
  2269. X            if( todo )
  2270. X            {
  2271. X                malloc_warning(func,file,line,ptr);
  2272. X            }
  2273. X            rtn++;
  2274. X        }
  2275. X        /*
  2276. X         * else if this segment is in use
  2277. X         */
  2278. X        else if( (ptr->flag & M_INUSE) != 0 )
  2279. X        {
  2280. X            malloc_errno = M_CODE_FREELIST_BAD;
  2281. X            if( todo )
  2282. X            {
  2283. X                malloc_warning(func,file, line,ptr);
  2284. X            }
  2285. X            rtn++;
  2286. X        }
  2287. X        /*
  2288. X         * else we have to check the filled areas.
  2289. X         */
  2290. X        else
  2291. X        {
  2292. X            /*
  2293. X             * check for underflow and/or reuse of this segment
  2294. X             */
  2295. X            rtn +=  FILLCHECK(func,file,line,ptr,todo);
  2296. X        }
  2297. X
  2298. X    } /* for(... */
  2299. X
  2300. X    return(rtn);
  2301. X
  2302. X} /* malloc_chain_check(... */
  2303. END_OF_FILE
  2304. if test 5539 -ne `wc -c <'mchain.c'`; then
  2305.     echo shar: \"'mchain.c'\" unpacked with wrong size!
  2306. fi
  2307. # end of 'mchain.c'
  2308. fi
  2309. if test -f 'minipatch' -a "${1}" != "-c" ; then 
  2310.   echo shar: Will not clobber existing file \"'minipatch'\"
  2311. else
  2312. echo shar: Extracting \"'minipatch'\" \(3654 characters\)
  2313. sed "s/^X//" >'minipatch' <<'END_OF_FILE'
  2314. X#
  2315. X# minipatch - shell script for automatically building miniature patch file
  2316. X#
  2317. X#
  2318. XFREEZE=RCS/.rcsfreeze.log
  2319. XMINIDATA=.minipatch
  2320. X
  2321. Xif [ $# != 0 ]; then
  2322. X    echo "usage: minipatch"
  2323. X    exit 1
  2324. Xfi
  2325. X
  2326. XFILES="`make srclist`"
  2327. X
  2328. X#
  2329. X# see if any files are still locked.  If so, we cannot proceed (they must be
  2330. X# unlocked before a patch file can be built
  2331. X#
  2332. Xif rlog -l $FILES 2>rlog.err | grep "locked by:" >/dev/null; then
  2333. X    echo "all files must be checked in before a patch file can be built"
  2334. X    exit 1
  2335. Xfi
  2336. X
  2337. Xif [ -s rlog.err ]; then
  2338. X    echo "all files must be checked in before a patch file can be built"
  2339. X    exit 1
  2340. Xfi
  2341. X
  2342. X#
  2343. X# get the mini-patch version and the true patchlevel
  2344. X#
  2345. Xif [ -s ${MINIDATA} ]; then
  2346. X    read patchlevel oldlevel < ${MINIDATA}
  2347. Xfi
  2348. Xread title realpatch < patchlevel
  2349. X
  2350. X#
  2351. X# if there is no mini-patch number, or the real patch number has changed
  2352. X#
  2353. X
  2354. Xif [ -z "$oldlevel" -o "x$patchlevel" != "x$realpatch" ]; then
  2355. X
  2356. X    #
  2357. X    # need to clean out old mini-patch freezes
  2358. X    #
  2359. X    OLDREVS=`grep minipatch $FREEZE |
  2360. X             while read version patchname junk
  2361. X            do
  2362. X                oldrev=\`expr "$patchname" : "\(.*\)("\`
  2363. X                echo " -n$oldrev"
  2364. X            done
  2365. X        `
  2366. X
  2367. X    if [ ! -z "$OLDREVS" ]; then
  2368. X
  2369. X        #
  2370. X        # remove the minipatch freeze names
  2371. X        #
  2372. X        rcs $OLDREVS $FILES
  2373. X
  2374. X        #
  2375. X        # change the minipatch lines in the freeze log so that we
  2376. X        # don't think they are still there.
  2377. X        #
  2378. X        sed -e "s/minipatch/oldmpatch/g" $FREEZE > /tmp/ttt
  2379. X        cp /tmp/ttt $FREEZE
  2380. X
  2381. X        #
  2382. X        # remove the old minipatch files
  2383. X        #
  2384. X        rm -f mini.*.*
  2385. X    fi
  2386. X
  2387. X    newlevel=1
  2388. X    version="patchlevel_$realpatch"
  2389. Xelse
  2390. X    version="minipatch_$oldlevel"
  2391. X    newlevel=`expr $oldlevel + 1 `
  2392. Xfi
  2393. X
  2394. X
  2395. X#
  2396. X# create a new, empty patch file and empty directory for old versions of files
  2397. X#
  2398. XPATCH=mini.$realpatch.$newlevel
  2399. X
  2400. Xcat <<-endcat > $PATCH
  2401. X
  2402. X    WARNING: this is a mini-patch that contains a subset of the patches
  2403. X    that will be included in the next full patch release for the library.
  2404. X    if you apply these changes, you will most likely have to manually
  2405. X    apply the next real patch release.
  2406. X
  2407. Xendcat
  2408. X
  2409. Xif [ -d old ]; then
  2410. X    rm -rf old
  2411. Xfi
  2412. Xmkdir old
  2413. X
  2414. X#
  2415. X# process each source file
  2416. X#
  2417. Xecho "Generating diffs"
  2418. Xfor i in $FILES
  2419. Xdo
  2420. X    #
  2421. X    # get the old version of the file
  2422. X    #
  2423. X    co -q -p -r$version $i > old/$i 2>/tmp/ttt
  2424. X
  2425. X    #
  2426. X    # if the file hasn't changed, skip it
  2427. X    #
  2428. X    if cmp -s $i old/$i ; then
  2429. X        continue;
  2430. X    fi
  2431. X
  2432. X    #
  2433. X    # name the file
  2434. X    #
  2435. X    echo "\nIndex: $i" >> $PATCH
  2436. X
  2437. X    #
  2438. X    # if there is an old version, add the prerequisite
  2439. X    #
  2440. X    if [ -s old/$i ]; then
  2441. X        
  2442. X        #
  2443. X        # get old rcs id
  2444. X        #
  2445. X        PREREQ="`rlog -r$version $i |
  2446. X             grep '^revision' | cut -f2 -d' ' 2>/dev/null`"
  2447. X
  2448. X        #
  2449. X        # if the id is in the file, add the prereq line
  2450. X        #
  2451. X        if fgrep "$PREREQ" old/$i > /dev/null 2>&1; then
  2452. X
  2453. X            echo "Prereq: $PREREQ" >> $PATCH
  2454. X
  2455. X        elif [ "$i" = "patchlevel" ]; then
  2456. X
  2457. X            echo "Prereq: $oldlevel" >> $PATCH
  2458. X
  2459. X        fi
  2460. X    fi
  2461. X
  2462. X    # 
  2463. X    # diff the file to generate the patch stuff
  2464. X    #
  2465. X    diff -c old/$i $i >> $PATCH
  2466. X
  2467. X
  2468. Xdone
  2469. X
  2470. X#
  2471. X# and now to check to verify that the patchfile correctly updates the
  2472. X# old code to the current version.  First apply the patch to the old
  2473. X# code and then see if there are any differences between the files.
  2474. X#
  2475. Xecho "Verifying patch..."
  2476. X(
  2477. X    cd old
  2478. X    patch < ../$PATCH > /dev/null 2>&1
  2479. X)
  2480. X
  2481. XFILES="`
  2482. Xfor i in $*
  2483. Xdo
  2484. X    if cmp -s $i old/$i; then
  2485. X        continue;
  2486. X    fi
  2487. X
  2488. X    echo file $i did not patch correctly > /dev/tty
  2489. X    echo $i
  2490. Xdone `"
  2491. X
  2492. Xif [ ! -z "$FILES" ]; then
  2493. X
  2494. X    echo "patch file did not build correctly($FILES)."
  2495. X    exit 1
  2496. X
  2497. Xfi
  2498. X
  2499. Xrm -rf old
  2500. X
  2501. Xecho "Verification complete"
  2502. X
  2503. X#
  2504. X# and now freeze all the files at this patchlevel, and checkout the current
  2505. X# versions of the files
  2506. X#
  2507. X
  2508. Xecho "freezing source at MINI patch level $newlevel"
  2509. Xecho "." | rcsfreeze minipatch_$newlevel  > /dev/null 2>&1 
  2510. X
  2511. Xecho "$realpatch $newlevel" > $MINIDATA
  2512. X
  2513. Xexit 0
  2514. END_OF_FILE
  2515. if test 3654 -ne `wc -c <'minipatch'`; then
  2516.     echo shar: \"'minipatch'\" unpacked with wrong size!
  2517. fi
  2518. chmod +x 'minipatch'
  2519. # end of 'minipatch'
  2520. fi
  2521. echo shar: End of archive 6 \(of 10\).
  2522. cp /dev/null ark6isdone
  2523. MISSING=""
  2524. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  2525.     if test ! -f ark${I}isdone ; then
  2526.     MISSING="${MISSING} ${I}"
  2527.     fi
  2528. done
  2529. if test "${MISSING}" = "" ; then
  2530.     echo You have unpacked all 10 archives.
  2531.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2532. else
  2533.     echo You still need to unpack the following archives:
  2534.     echo "        " ${MISSING}
  2535. fi
  2536. ##  End of shell archive.
  2537. exit 0
  2538. *** SENTINEL(tm) The ultimate Debugging Environment - email for more info ***
  2539.  
  2540. Conor P. Cahill              (703)430-9247            cpcahil@virtech.vti.com
  2541. Virtual Technologies, Inc.  46030 Manekin Plaza          Dulles, VA 21066 
  2542.  
  2543. exit 0 # Just in case...
  2544.