home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / sources / misc / 3902 < prev    next >
Encoding:
Text File  |  1992-09-03  |  56.0 KB  |  2,550 lines

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