home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / corelib / ncbimem.c < prev    next >
Encoding:
Text File  |  1996-07-05  |  23.3 KB  |  968 lines  |  [TEXT/R*ch]

  1. /*   ncbimem.c
  2. * ===========================================================================
  3. *
  4. *                            PUBLIC DOMAIN NOTICE                          
  5. *               National Center for Biotechnology Information
  6. *                                                                          
  7. *  This software/database is a "United States Government Work" under the   
  8. *  terms of the United States Copyright Act.  It was written as part of    
  9. *  the author's official duties as a United States Government employee and 
  10. *  thus cannot be copyrighted.  This software/database is freely available 
  11. *  to the public for use. The National Library of Medicine and the U.S.    
  12. *  Government have not placed any restriction on its use or reproduction.  
  13. *                                                                          
  14. *  Although all reasonable efforts have been taken to ensure the accuracy  
  15. *  and reliability of the software and data, the NLM and the U.S.          
  16. *  Government do not and cannot warrant the performance or results that    
  17. *  may be obtained by using this software or data. The NLM and the U.S.    
  18. *  Government disclaim all warranties, express or implied, including       
  19. *  warranties of performance, merchantability or fitness for any particular
  20. *  purpose.                                                                
  21. *                                                                          
  22. *  Please cite the author in any work or product based on this material.   
  23. *
  24. * ===========================================================================
  25. *
  26. * File Name:  ncbimem.c
  27. *
  28. * Author:  Gish, Kans, Ostell, Schuler
  29. *
  30. * Version Creation Date:   6/4/91
  31. *
  32. * $Revision: 2.20 $
  33. *
  34. * File Description: 
  35. *       portable memory handlers for Mac, PC, Unix
  36. *
  37. * Modifications:  
  38. * --------------------------------------------------------------------------
  39. * Date     Name        Description of modification
  40. * -------  ----------  -----------------------------------------------------
  41. * 2/11/91  Kans        MemMore now frees old memory block
  42. * 3/12/91  Kans        MemGet, HandGet will not clear if allocation failed
  43. * 6/4/91   Kans        Macintosh version uses malloc, realloc, free
  44. * 6/6/91   Schuler     New versions of MemGet, MemMore, MemFree for Windows
  45. * 8/12/91  Ostell      Protection from NULL ptrs to MemFill, MemCopy
  46. * 09-19-91 Schuler     Modified for closer resemblance to ANSI functions
  47. * 09-19-91 Schuler     Changed all functions to _cdecl calling convention
  48. * 04-15-93 Schuler     Changed _cdecl to LIBCALL
  49. * 05-21-93 Schuler     win_Free checks now for invalid pointers
  50. * 05-21-93 Schuler     Nlm_MemFreeTrace added for debugging MemFree
  51. * 06-14-93 Schuler     Added dll_Malloc and dll_Free
  52. * 12-20-93 Schuler     Converted ERRPOST to ErrPostEx
  53. *
  54. * ==========================================================================
  55. */
  56.  
  57. #undef  THIS_MODULE
  58. #define THIS_MODULE g_corelib
  59. #undef  THIS_FILE
  60. #define THIS_FILE  _this_file
  61.  
  62.  
  63. #include <ncbi.h>
  64. #include <ncbiwin.h>
  65.  
  66. #ifdef WIN16
  67.  
  68. struct heapnode 
  69. {
  70.     struct heapnode *next;
  71.     HGLOBAL hSeg;
  72.     WORD    wSeg;
  73.     WORD    wFree;
  74.     int     nItems;
  75.     int        sn;
  76. };
  77.  
  78. Nlm_sizeT    g_nMemHeap = ((Nlm_sizeT)4*KBYTE);
  79. #define HEAPSIZE    g_nMemHeap
  80. Nlm_sizeT    g_nMemThresh = ((Nlm_sizeT)128);
  81. #define THRESHOLD    g_nMemThresh
  82.  
  83. struct heapnode  headFirst;
  84. struct heapnode *headPtr = &headFirst;
  85.  
  86. static BOOL NEAR  HeapNew(struct heapnode *pNode);
  87. static VOID NEAR  HeapFree(struct heapnode *pNode);
  88.  
  89. #endif  /* WIN16 */
  90.  
  91. short    g_bBadPtr;
  92.  
  93. extern char *g_corelib;
  94. static char * _this_file = __FILE__;
  95.  
  96. static char * _msgMemory  = "Ran out of memory";
  97. static char * _msgNullPtr = "NULL pointer passed as an argument";
  98. static char * _msgNullHnd = "NULL handle passed as an argument";
  99.  
  100.  
  101.  
  102. /*****************************************************************************
  103. *
  104. *   Nlm_MemGet(size, clear_out)
  105. *     size:  number of bytes to allocate
  106. *     flags: any of the following bits may be set
  107. *         MGET_CLEAR     clear to zeros
  108. *         MGET_ERRPOST   post error on allocaion failure
  109. *
  110. *****************************************************************************/
  111.  
  112. void * LIBCALL  Nlm_MemGet (Nlm_sizeT size, unsigned int flags)
  113. {
  114.     void *ptr;
  115.     
  116.     if (size == 0)
  117.         return NULL;
  118.  
  119.     if ((ptr = Nlm_Malloc(size)) !=NULL)
  120.         memset(ptr,0,size);
  121.     else if (flags & MGET_ERRPOST)
  122.         ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
  123.     return ptr;
  124. }
  125.  
  126.  
  127. /*****************************************************************************
  128. *
  129. *   Nlm_MemNew(size)
  130. *
  131. *****************************************************************************/
  132.  
  133. void * LIBCALL  Nlm_MemNew (Nlm_sizeT size)
  134. {
  135.     void *ptr;
  136.     
  137.     if (size == 0)
  138.         return NULL;
  139.     
  140.     if ((ptr = Nlm_Calloc (size, 1)) == NULL)
  141.         ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
  142.  
  143.     return  ptr;
  144. }
  145.  
  146. /*****************************************************************************
  147. *
  148. *   Nlm_MemMore(ptr, size)
  149. *
  150. *****************************************************************************/
  151.  
  152. void * LIBCALL  Nlm_MemMore (void *ptr, Nlm_sizeT size)
  153. {
  154.     void *ptr2;
  155.     
  156.     if (ptr == NULL) 
  157.     {
  158.         ErrPostEx(SEV_WARNING,E_Programmer,0,"MemMore: %s", _msgNullPtr);
  159.         return NULL;
  160.     }
  161.     if (size == 0) 
  162.         return MemFree(ptr);
  163.     
  164.     if ((ptr2 = Nlm_Realloc (ptr, size)) == NULL) 
  165.         ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
  166.     
  167.     return ptr2;
  168. }
  169.  
  170.  
  171. /*****************************************************************************
  172. *
  173. *   Nlm_MemExtend(ptr, size, oldsize)
  174. *
  175. *****************************************************************************/
  176.  
  177. void * LIBCALL  Nlm_MemExtend (void *ptr, Nlm_sizeT size, Nlm_sizeT oldsize)
  178. {
  179.     void *ptr2;
  180.     
  181.     if (ptr == NULL) 
  182.     {
  183.         ErrPostEx(SEV_WARNING,E_Programmer,0,"MemExtend: %s", _msgNullPtr);
  184.         return NULL;
  185.     }
  186.     if (size == 0)
  187.         return MemFree(ptr);
  188.     
  189.     if ((ptr2 = Nlm_Realloc (ptr, size)) == NULL) 
  190.         ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
  191.     
  192.     if (size > oldsize)
  193.         memset((char*)ptr2 + oldsize, 0, size - oldsize);
  194.     
  195.     return ptr2;
  196. }
  197.  
  198.  
  199. /*****************************************************************************
  200. *
  201. *   Nlm_MemFree(ptr)
  202. *       frees allocated memory
  203. *
  204. *****************************************************************************/
  205.  
  206. void * LIBCALL  Nlm_MemFree (void *ptr)
  207. {
  208.     if (ptr != NULL) 
  209.         Nlm_Free (ptr);
  210.  
  211.     return NULL;
  212. }
  213.  
  214.  
  215. #ifdef WIN_MSWIN
  216. void * LIBCALL  Nlm_MemFreeTrace (void *ptr, const char *module, 
  217.             const char *filename, int linenum)
  218. {
  219.     if (ptr != NULL)
  220.     {
  221.         Nlm_Free(ptr);
  222.         if (g_bBadPtr)
  223.         {
  224.             Nlm_ErrSetContext(module,filename,linenum,TRUE);
  225.             Nlm_ErrPostEx(SEV_WARNING,E_Programmer,0,
  226.                         "MemFree: attempt to free invalid pointer");
  227.         }
  228.     }
  229.     return NULL;
  230. }
  231. #endif
  232.  
  233.  
  234. /*****************************************************************************
  235. *
  236. *    void Nlm_MemCopy(Pointer to, Pointer from, Uint4 bytes)
  237. *       WARNING: no check on overlapping regions
  238. *
  239. *****************************************************************************/
  240.  
  241. void * LIBCALL  Nlm_MemCopy (void *dst, const void *src, Nlm_sizeT bytes)
  242. {
  243.     return (dst&&src) ? Nlm_MemCpy (dst, src, bytes) : NULL;
  244. }
  245.  
  246. /*****************************************************************************
  247. *
  248. *    void Nlm_MemDup (Pointer orig, Uint4 bytes)
  249. *       Duplicate the region of memory pointed to by 'orig' for 'size' length
  250. *
  251. *****************************************************************************/
  252.  
  253. void * LIBCALL  Nlm_MemDup (const void *orig, Nlm_sizeT size)
  254. {
  255.     Nlm_VoidPtr    copy;
  256.         
  257.     if (orig == NULL || size == 0)
  258.         return NULL;
  259.         
  260.     if ((copy = Nlm_Malloc (size)) == NULL)
  261.         ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
  262.         
  263.     Nlm_MemCpy(copy, orig, size);
  264.         return copy;
  265. }
  266.  
  267. /*****************************************************************************
  268. *
  269. *    void Nlm_MemMove (Pointer to, Pointer from, Uint4 bytes)
  270. *       This code will work on overlapping regions
  271. *
  272. *****************************************************************************/
  273.  
  274. void * LIBCALL  Nlm_MemMove (void * dst, const void *src, Nlm_sizeT bytes)
  275. {
  276.     register char *dest = (char *)dst;
  277.     register const char *sorc = (char *)src;
  278.     
  279.     if (dest > sorc) {
  280.         sorc += bytes;
  281.         dest += bytes;
  282.         while (bytes-- != 0) {
  283.             *--dest = *--sorc;
  284.         }
  285.         } else {
  286.         while (bytes-- != 0) {
  287.             *dest++ = *sorc++;
  288.         }
  289.     }
  290.     return dst;
  291. }
  292.  
  293. /*****************************************************************************
  294. *
  295. *   void Nlm_MemFill(to, value, bytes)
  296. *       set a block of memory to a value
  297. *
  298. *****************************************************************************/
  299.  
  300. void * LIBCALL  Nlm_MemFill (void *buf, int value, Nlm_sizeT bytes)
  301. {
  302.     return  buf ? Nlm_MemSet (buf, value, bytes) : NULL;
  303. }
  304.  
  305.  
  306.  
  307. #if (defined(OS_MAC) || defined(WIN_MSWIN) || defined(MSC_VIRT))
  308. /***** Handle functions are for Macintosh and Windows only *****/
  309. /***** or Microsoft virtual memory manager ****/
  310.  
  311. #ifdef MSC_VIRT
  312. Nlm_Boolean wrote_to_handle;   /* used by ncbibs write routines */
  313. #endif
  314.  
  315. /*****************************************************************************
  316. *
  317. *   Nlm_HandGet(size, clear_out)
  318. *       returns handle to allocated memory
  319. *       if (clear_out) clear memory to 0
  320. *
  321. *****************************************************************************/
  322.  
  323. Nlm_Handle LIBCALL  Nlm_HandGet (Nlm_sizeT size, Nlm_Boolean clear_out)
  324.  
  325. {
  326.     Nlm_VoidPtr ptr;
  327.     Nlm_Handle  hnd;
  328.  
  329.     if (size == 0) return NULL;
  330.  
  331. #ifdef OS_MAC
  332.     hnd = (Nlm_Handle) NewHandle (size);
  333. #endif
  334.  
  335. #ifdef WIN_MSWIN
  336.     hnd = (Nlm_Handle) GlobalAlloc (GMEM_MOVEABLE, size);
  337. #endif
  338.  
  339. #ifdef MSC_VIRT
  340.     hnd = (Nlm_Handle) _vmalloc ((unsigned long)size);
  341. #endif
  342.  
  343.     if (hnd == NULL) 
  344.         ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
  345.  
  346.     else if (clear_out)    {
  347. #ifdef MSC_VIRT
  348.         wrote_to_handle = TRUE;
  349. #endif
  350.         if ((ptr = HandLock (hnd)) != NULL)
  351.             Nlm_MemSet (ptr, 0, size);
  352.         HandUnlock (hnd);
  353.     }
  354.  
  355.     return  hnd;
  356. }
  357.  
  358. /*****************************************************************************
  359. *
  360. *   Nlm_HandNew(size)
  361. *
  362. *****************************************************************************/
  363.  
  364. Nlm_Handle LIBCALL  Nlm_HandNew (Nlm_sizeT size)
  365.  
  366. {
  367.     Nlm_Handle  hnd;
  368.  
  369.     if (size == 0)  return NULL;
  370.   
  371.     if ((hnd = HandGet (size, TRUE)) == NULL)
  372.         ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
  373.   
  374.     return hnd;
  375. }
  376.  
  377. /*****************************************************************************
  378. *
  379. *   Nlm_HandMore(hnd, size)
  380. *
  381. *****************************************************************************/
  382.  
  383. Nlm_Handle LIBCALL  Nlm_HandMore (Nlm_Handle hnd, Nlm_sizeT size)
  384.  
  385. {
  386.     Nlm_Handle  hnd2;
  387.  
  388.     if (size == 0) {
  389.         Nlm_HandFree (hnd);
  390.         return NULL;
  391.     }
  392.  
  393.     if (hnd == NULL) {
  394.         ErrPostEx(SEV_WARNING,E_Programmer,0,"HandMore: %s", _msgNullHnd);
  395.         return NULL;
  396.     }
  397.  
  398. #ifdef OS_MAC
  399.     SetHandleSize ((Handle)hnd, (Size)size);
  400.     hnd2 = hnd;
  401.     if (MemError() != noErr)  
  402.         hnd2 = NULL;
  403. #endif
  404.  
  405. #ifdef WIN_MSWIN
  406.     hnd2 = (Nlm_Handle) GlobalReAlloc ((HANDLE)hnd, size, GHND);
  407. #endif
  408.  
  409. #ifdef MSC_VIRT
  410.     hnd2 = (Nlm_Handle) _vrealloc ((_vmhnd_t)hnd, (unsigned long)size);
  411. #endif
  412.  
  413.     if (hnd2 == NULL)
  414.         ErrPostEx(SEV_FATAL,E_NoMemory,0,_msgMemory);
  415.  
  416.     return  hnd2;
  417. }
  418.  
  419.  
  420. /*****************************************************************************
  421. *
  422. *   Nlm_HandFree (hnd)
  423. *
  424. *****************************************************************************/
  425.  
  426. Nlm_Handle LIBCALL  Nlm_HandFree (Nlm_Handle hnd)
  427. {
  428. #ifdef MSC_VIRT
  429.     _vmhnd_t x;
  430. #endif
  431.  
  432.     if (hnd) {
  433.  
  434. #ifdef OS_MAC
  435.         DisposHandle ((Handle) hnd);
  436. #endif
  437.  
  438. #ifdef WIN_MSWIN
  439.         GlobalFree ((HANDLE) hnd);
  440. #endif
  441.  
  442. #ifdef MSC_VIRT
  443.         x = (_vmhnd_t)hnd;
  444.         while (_vlockcnt(x))
  445.             _vunlock(x, _VM_CLEAN);
  446.         _vfree(x);
  447. #endif
  448.     }
  449.     else
  450.         ErrPostEx(SEV_WARNING,E_Programmer,0,"HandFree: %s", _msgNullHnd);
  451.  
  452.     return NULL;
  453. }
  454.  
  455.  
  456. /*****************************************************************************
  457. *
  458. *   Nlm_HandLock (hnd)
  459. *
  460. *****************************************************************************/
  461.  
  462. Nlm_VoidPtr LIBCALL  Nlm_HandLock (Nlm_Handle hnd)
  463. {
  464.     Nlm_VoidPtr ptr;
  465.  
  466.     if (hnd == NULL) {
  467.         ErrPostEx(SEV_WARNING,E_Programmer,0,"HandLock: %s", _msgNullHnd);
  468.         return NULL;
  469.     }
  470.  
  471. #ifdef OS_MAC
  472.     HLock ((Handle) hnd);
  473.     ptr = *((Handle) hnd);
  474. #endif
  475.  
  476. #ifdef WIN_MSWIN
  477.     ptr = GlobalLock ((HANDLE) hnd);
  478. #endif
  479.  
  480. #ifdef MSC_VIRT
  481.     ptr = _vlock((_vmhnd_t) hnd);
  482. #endif
  483.  
  484.     return  ptr;
  485. }
  486.  
  487. /*****************************************************************************
  488. *
  489. *   Nlm_HandUnlock(hnd)
  490. *
  491. *****************************************************************************/
  492.  
  493. Nlm_VoidPtr LIBCALL  Nlm_HandUnlock (Nlm_Handle hnd)
  494. {
  495. #ifdef MSC_VIRT
  496.     int dirty = _VM_CLEAN;
  497. #endif
  498.  
  499.     if (hnd == NULL) 
  500.         ErrPostEx(SEV_WARNING,E_Programmer,0,"HandUnlock: %s", _msgNullHnd);
  501.     else {
  502. #ifdef OS_MAC
  503.         HUnlock ((Handle) hnd);
  504. #endif
  505.  
  506. #ifdef WIN_MSWIN
  507.         GlobalUnlock ((HANDLE) hnd);
  508. #endif
  509.  
  510. #ifdef MSC_VIRT
  511.         if (wrote_to_handle == TRUE)
  512.             dirty = _VM_DIRTY;
  513.         _vunlock ((_vmhnd_t) hnd, dirty);  /* always assume dirty */
  514.         wrote_to_handle = FALSE;
  515. #endif
  516.     }
  517.  
  518.     return NULL;
  519. }
  520.  
  521. #endif /* Mac or Win */
  522.  
  523.  
  524.  
  525.  
  526. #ifdef WIN_MAC
  527. #ifdef USE_MAC_MEMORY
  528. /*****************************************************************************
  529. *
  530. *   Macintosh-specific functions (using Mac Toolbox calls):
  531. *   
  532. *   mac_Malloc     Macintosh version of malloc
  533. *   mac_Calloc     Macintosh version of calloc
  534. *   mac_Realloc    Macintosh version of realloc
  535. *   mac_Free       Macintosh version of free
  536. *   
  537. *****************************************************************************/
  538.  
  539. void *mac_Malloc (Nlm_sizeT size)
  540.  
  541. {
  542.     return NewPtr (size);
  543. }
  544.  
  545. void *mac_Calloc (Nlm_sizeT nmemb, Nlm_sizeT size)
  546.  
  547. {
  548.     return NewPtrClear (nmemb * size);
  549. }
  550.  
  551. void *mac_Realloc (void *ptr, Nlm_sizeT size)
  552.  
  553. {
  554.     void *ptr2;
  555.  
  556.     ptr2 = NewPtrClear (size);
  557.     if (ptr2 != NULL && ptr != NULL) {
  558.       Nlm_MemCpy (ptr2, ptr, size);
  559.       DisposPtr (ptr);
  560.     }
  561.     return ptr2;
  562. }
  563.  
  564. void mac_Free (void *ptr)
  565.  
  566. {
  567.     DisposPtr (ptr);
  568. }
  569. #endif
  570. #endif
  571.  
  572.  
  573.  
  574. #ifdef WIN16
  575. /*****************************************************************************
  576. *
  577. *   Windows-specific functions:
  578. *   
  579. *   win16_Malloc     Windows version of malloc
  580. *   win16_Calloc     Windows version of calloc
  581. *   win16_Realloc    Windows version of realloc
  582. *   win16_Free       Windows version of free
  583. *   
  584. *   The following fucntions are not exported. 
  585. *
  586. *   HeapNew     allocates an auxilliary local heap
  587. *   HeapFree    frees an auxilliary local heap
  588. *
  589. *****************************************************************************/
  590.  
  591. LPVOID LIBCALL  win16_Malloc (Nlm_sizeT size) 
  592.     struct heapnode *pNode; 
  593.     WORD      wSeg, wSize, wFree, wOfs; 
  594.     HGLOBAL   hSeg; 
  595.     LPVOID    pMem;
  596.  
  597.     if (size == 0)  return NULL;
  598.  
  599.    /*
  600.     * Two allocation strategies are used depending on the reguested
  601.     * size of the new block.  Large objects (size >= THRESHOLD) are
  602.     * allocated as independent blocks from the global heap in the
  603.     * usual way and then locked.  Small objects (lSize < THRESHOLD)
  604.     * are allocated from auxilliary local heaps that are created as 
  605.     * needed.  References to these heaps are maintained in a linked
  606.     * list structure (located in the default data segment).
  607.     */
  608.  
  609.     if (size < THRESHOLD) 
  610.     {
  611.         wSize = (WORD)size;
  612.  
  613.         for (pNode=headPtr; pNode; pNode=pNode->next) 
  614.         {
  615.  
  616.            /* 
  617.             * If the current node is empty, we allocate a new heap. 
  618.             * On failure, break out of the loop to do an error return.
  619.             */
  620.  
  621.             if ((wSeg = pNode->wSeg) ==0) 
  622.             {
  623.                 if (!HeapNew (pNode))  break;
  624.                 wSeg = pNode->wSeg;
  625.             }
  626.  
  627.             if (wSize <= pNode->wFree) 
  628.             {
  629.  
  630.                /*
  631.                 * Attempt to allocate memory from this node's heap.  To do
  632.                 * this, we need to switch the DS register to the heap's
  633.                 * segment, then do a LocalAlloc, and of course restore
  634.                 * the DS register afterwards (some assembly required).
  635.                 * If this is successful, we construct a far pointer to the 
  636.                 * allocated block and return it as the function result.
  637.                 * Otherwise, we continue around the cycle...
  638.                 */
  639.  
  640.                 _asm {
  641.                     push  ds
  642.                     mov   ax, wSeg
  643.                     mov   ds, ax   
  644.                 }
  645.  
  646.                 wOfs = (WORD) LocalAlloc(LMEM_FIXED, wSize);
  647.                 wFree = LocalCompact(0);
  648.  
  649.                 _asm {
  650.                        pop   ds 
  651.                 }
  652.  
  653.                 if (wOfs) 
  654.                 {
  655.                     pNode->nItems +=1;
  656.                     pNode->wFree = wFree;
  657.                     pMem = (LPVOID) MAKELONG(wOfs, wSeg);
  658.                     return  pMem;
  659.                 }
  660.             }
  661.  
  662.            /* 
  663.             * If we are at the end of the chain, create a new node and
  664.             * add it to the chain.  The new node becomes the current 
  665.             * node in the next loop iteration.  If the allocation fails
  666.             * we will drop out of the loop and do an error return.
  667.             */
  668.  
  669.             if ( ! pNode->next )
  670.             {
  671.                 pNode->next = (struct heapnode*) calloc(sizeof(struct heapnode),1);
  672.                 pNode->next->sn = pNode->sn +1;
  673.             }
  674.         }
  675.  
  676.         return  NULL;
  677.     }
  678.     else 
  679.     {
  680.         /* 
  681.              *  Large memory objects are allocated from the global heap as
  682.          *  independent moveable blocks.  They are then locked to generate 
  683.          *  the far pointer and they remain locked until freed.
  684.          */
  685.  
  686.         if ((hSeg = GlobalAlloc(GMEM_MOVEABLE,size)) != NULL) 
  687.         {
  688.             pMem = GlobalLock(hSeg);
  689.             ASSERT(OFFSETOF(pMem)==0);
  690.             return  pMem;
  691.         }
  692.     }
  693.     return NULL;
  694. }
  695.  
  696.  
  697. LPVOID LIBCALL  win16_Calloc (Nlm_sizeT items, Nlm_sizeT size)
  698. {
  699.     LPVOID ptr;
  700.     unsigned long bytes = (unsigned long) items * size;
  701.  
  702.      if (bytes > (unsigned long) SIZE_MAX)  return NULL;
  703.  
  704.     if ((ptr = win16_Malloc((Nlm_sizeT) bytes)) != NULL)
  705.         _fmemset(ptr,0,(Nlm_sizeT) bytes);
  706.  
  707.     return ptr;
  708. }
  709.  
  710.  
  711. LPVOID LIBCALL  win16_Realloc (LPVOID pMem, Nlm_sizeT size)
  712. {
  713.     WORD wSeg1 = SELECTOROF(pMem);
  714.     HGLOBAL   hSeg1, hSeg2;
  715.  
  716.     if (size ==0) 
  717.     {
  718.         win16_Free(pMem);
  719.         return NULL;
  720.     }
  721.  
  722.     if (OFFSETOF(pMem) ==0) 
  723.     {
  724.        /*
  725.         *  The existing block was not allocated from one of the
  726.         *  auxilliary local heaps, so it must be an independent
  727.         *  global block.  Use the normal GlobalReAlloc strategy.
  728.         */
  729.  
  730.         hSeg1 = (HGLOBAL) LOWORD(GlobalHandle(wSeg1));
  731.         GlobalUnlock (hSeg1);
  732.         if ((hSeg2 = GlobalReAlloc(hSeg1,size,GMEM_MOVEABLE)) != NULL)
  733.             return GlobalLock(hSeg2);
  734.             /*
  735.         else
  736.             pMem = NULL;
  737.         return  pMem;
  738.         */
  739.     }
  740.     else
  741.     {
  742.         struct heapnode *pNode;
  743.         WORD      wSize1, wOfs1;
  744.         WORD      wSize2, wOfs2, wFree;
  745.         LPVOID    pMem2;
  746.         
  747.        /*
  748.         *  Scan the linked list to see if the segment of the pointer
  749.         *  to be freed matches any of the auxilliary local heaps.
  750.         *  If so, LocalFree from that heap.  Otherwise we assume that
  751.         *  it is a normal global memory object and GlobalFree.
  752.         */
  753.  
  754.         for (pNode=headPtr; pNode; pNode=pNode->next) 
  755.         {
  756.             if (pNode->wSeg == wSeg1)
  757.             {
  758.                 wSize2 = (WORD) size;
  759.                 wOfs1 = LOWORD((DWORD)pMem);
  760.  
  761.                 _asm {
  762.                     push  ds
  763.                     mov   ax, wSeg1
  764.                     mov   ds, ax   
  765.                 }
  766.  
  767.                 wSize1 = LocalSize((HLOCAL)wSeg1);
  768.                 wOfs2 = (WORD) LocalReAlloc((HLOCAL)wOfs1,wSize2,LMEM_MOVEABLE);
  769.                 wFree = LocalCompact(0);
  770.  
  771.                 _asm { 
  772.                     pop   ds 
  773.                 }
  774.  
  775.                 if (wOfs2)     /* successfully realloc'ed within same heap */
  776.                 {
  777.                     pNode->wFree = wFree;
  778.                     pMem = (LPVOID) MAKELONG(wOfs2,wSeg1);
  779.                     return  pMem;
  780.                 }
  781.  
  782.                /*
  783.                 *  We couldn't realloc the object within the same heap, so
  784.                 *  we will now attempt to allocate a new pointer and copy
  785.                 *  contents of the existing block to the new one.  If
  786.                 *  successful, the old block is freed.
  787.                 */
  788.  
  789.                 if ((pMem2 = win16_Malloc(size)) != NULL) 
  790.                 {
  791.                     _fmemcpy(pMem2,pMem,MIN(wSize1,wSize2));
  792.                     win16_Free(pMem);
  793.                 }
  794.                 return  pMem2;
  795.             }
  796.         }
  797.     }
  798.  
  799.     return NULL;
  800. }
  801.  
  802.  
  803. VOID LIBCALL  win16_Free (LPVOID pMem)
  804. {
  805.     WORD wSeg = SELECTOROF(pMem);
  806.     WORD wOfs = OFFSETOF(pMem);
  807.  
  808.     g_bBadPtr = FALSE;
  809.  
  810.     if (wOfs ==0)
  811.     {
  812.         HGLOBAL hSeg = (HGLOBAL) LOWORD(GlobalHandle(wSeg));
  813.         if (GlobalSize(hSeg))
  814.         {
  815.             GlobalUnlock(hSeg);
  816.             GlobalFree(hSeg);
  817.             return;
  818.         }
  819.     }
  820.     else
  821.     {
  822.         struct heapnode *pNode;
  823.         
  824.         /*
  825.          *  Scan the linked list to see if the segment of the pointer
  826.          *  to be freed matches any of the auxilliary local heaps.
  827.          *  If so, LocalFree from that heap.  Otherwise we assume that
  828.          *  it is a normal global memory object and GlobalFree.
  829.          */
  830.  
  831.         for (pNode=headPtr; pNode; pNode=pNode->next) 
  832.         {
  833.             if (pNode->wSeg == wSeg)
  834.             {
  835.                 WORD wFree;
  836.  
  837.                    _asm {
  838.                        push  ds
  839.                        mov   ax, wSeg
  840.                     mov   ds, ax   
  841.                    }
  842.  
  843.                 if (LocalSize((HLOCAL)wOfs))
  844.                 {
  845.                     wOfs = (WORD) LocalFree((HLOCAL)wOfs);
  846.                     wFree = LocalCompact(0);
  847.                 }
  848.  
  849.                    _asm { 
  850.                        pop   ds 
  851.                    }
  852.  
  853.                 if (wOfs == NULL)         /* NULL means success here */
  854.                 {
  855.                     pNode->nItems -= 1;
  856.                     pNode->wFree = wFree;
  857.                     if (pNode->nItems ==0)  
  858.                     {
  859.                         HeapFree(pNode);  /* free the heap, but keep the node */
  860.                     }
  861.                     return;
  862.                 }
  863.                 goto BAD_POINTER;
  864.             }
  865.         }
  866.         goto BAD_POINTER;
  867.     }
  868.     
  869.     
  870. BAD_POINTER :
  871.     g_bBadPtr = TRUE;
  872.     TRACE("win16_Free(%04X:%04X)  *** invalid pointer ***\n",wSeg,wOfs);
  873. }
  874.  
  875.  
  876. static BOOL NEAR  HeapNew (struct heapnode *pNode)
  877. {
  878.     HGLOBAL hMem;
  879.  
  880.     pNode->nItems = 0;
  881.     pNode->hSeg = NULL;
  882.     pNode->wSeg = NULL;
  883.     if ((hMem = GlobalAlloc(GMEM_MOVEABLE,HEAPSIZE)) != NULL) 
  884.     {
  885.         LPSTR pMem = GlobalLock(hMem);
  886.         WORD  wSeg = SELECTOROF(pMem);
  887.         WORD  wSize = (WORD) GlobalSize(hMem) -16;
  888.  
  889.         if (LocalInit(wSeg,0,wSize)) 
  890.         {
  891.             pNode->hSeg = hMem;
  892.             pNode->wSeg = wSeg;
  893.             pNode->wFree = wSize;
  894.             GlobalUnlock(hMem);    /* remove LocalInit's lock */
  895.  
  896.             return TRUE;
  897.         }
  898.         GlobalUnlock(hMem);
  899.         GlobalFree(hMem);    
  900.     }
  901.     TRACE("HeapNew: ** unable to allocate %ld bytes\n",HEAPSIZE);
  902.     return FALSE;
  903. }
  904.  
  905. static VOID NEAR  HeapFree (struct heapnode *pNode)
  906. {   
  907.     HGLOBAL hMem;
  908.  
  909.     if (pNode->nItems==0 && ((hMem=pNode->hSeg) != NULL)) 
  910.     {
  911.         GlobalUnlock(hMem);
  912.         GlobalFree(hMem);
  913.         pNode->hSeg = NULL;
  914.         pNode->wSeg = 0;
  915.     }
  916. }
  917.  
  918.  
  919. #endif /* WIN16 */
  920.  
  921.  
  922. #ifdef _WINDLL
  923. /*****************************************************************************
  924. *
  925. *   Windows DLL-specific functions (shared memory)
  926. *   
  927. *   dll_Malloc
  928. *   dll_Calloc    (not yet)
  929. *   dll_Realloc    (not yet)
  930. *   dll_Free   
  931. *   
  932. *****************************************************************************/
  933.  
  934.  
  935. void * dll_Malloc (Nlm_sizeT bytes)
  936. {
  937.     HGLOBAL hMem;
  938.     void *pMem;
  939.  
  940.     if (bytes >0 && (hMem = GlobalAlloc(GMEM_DDESHARE,bytes)))
  941.     {
  942.         if (pMem = GlobalLock(hMem))
  943.             return pMem;
  944.         else
  945.             GlobalFree(hMem);
  946.     }
  947.  
  948.     TRACE("dll_Malloc(%ld) failed\n",bytes);
  949.     return NULL;
  950. }
  951.  
  952. void   dll_Free (void *pMem)
  953. {
  954.     HGLOBAL hMem;
  955. #ifdef WIN16
  956.     DWORD dwHandle = GlobalHandle(SELECTOROF(pMem));
  957.     hMem = (HGLOBAL)LOWORD(dwHandle);
  958. #else
  959.     hMem = GlobalHandle(pMem);
  960. #endif
  961.  
  962.     GlobalUnlock(hMem);
  963.     GlobalFree(hMem);
  964. }
  965.  
  966. #endif
  967.