home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c160 / 1.ddi / SOURCE / H4.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-22  |  12.5 KB  |  504 lines

  1.  
  2. /* h4.c  Memory Handler
  3.    (c)Copyright Sequiter Software Inc., 1987-1990.  All rights reserved.
  4. */
  5.  
  6. #include "d4all.h"
  7. #include "h4memory.h"
  8. #include "u4error.h"
  9. #include "p4misc.h"
  10.  
  11. #ifdef WINDOWS_L
  12. #define  WINDOWS
  13. #endif
  14.  
  15. #ifdef WINDOWS_G
  16. #define  WINDOWS
  17. #endif
  18.  
  19. #ifdef WINDOWS
  20. #include "windows.h"
  21. #endif
  22.  
  23. #ifdef NO_ALLOC
  24. #include <dos.h>
  25. #endif
  26.  
  27. #include <stdlib.h>
  28. #include <string.h>
  29.  
  30. int  h4add( char **ptr_ptr, int mem_ref, int add_ref, int add_before )
  31. {
  32.    MEMORY *memory ;
  33.    UNIT   *mem_ptr, *add_ptr, *next_ptr ;
  34.  
  35.    if ( add_ref == mem_ref || add_ref < 0 )  return add_ref;
  36.  
  37.    if ( add_before && mem_ref >= 0 )
  38.    {
  39.       h4add( ptr_ptr, mem_ref, add_ref, 0 ) ;
  40.       h4remove( ptr_ptr, mem_ref ) ;
  41.       h4add( ptr_ptr, add_ref, mem_ref, 0 ) ;
  42.  
  43.       return  add_ref ;
  44.    }
  45.  
  46.    memory = (MEMORY *) (*ptr_ptr -sizeof(MEMORY)) ;
  47.  
  48.    add_ptr = (UNIT *) (*ptr_ptr + memory->len_unit* add_ref) ;
  49.    add_ptr->prev =  mem_ref ;
  50.    if ( mem_ref < 0 )
  51.    {
  52.       add_ptr->next =  -1 ;
  53.       return  add_ref ;
  54.    }
  55.  
  56.    mem_ptr  = (UNIT *) (*ptr_ptr + memory->len_unit* mem_ref) ;
  57.    next_ptr = (UNIT *) (*ptr_ptr + memory->len_unit* mem_ptr->next) ;
  58.  
  59.    add_ptr->next =  mem_ptr->next ;
  60.    mem_ptr->next =  add_ref ;
  61.  
  62.    if ( add_ptr->next < 0 )  return  add_ref ;
  63.    next_ptr->prev =  add_ref ;
  64.  
  65.    return  add_ref ;
  66. }
  67.  
  68.  
  69. int  h4remove( char **ptr_ptr, int mem_ref ) 
  70. {
  71.    MEMORY *memory ;
  72.    UNIT   *mem_ptr, *previous_ptr, *next_ptr ;
  73.    int     return_unit ;
  74.  
  75.    if ( mem_ref < 0 )  return -1 ;
  76.    memory = (MEMORY *) (*ptr_ptr -sizeof(MEMORY)) ;
  77.  
  78.    mem_ptr = (UNIT *) (*ptr_ptr + memory->len_unit* mem_ref) ;
  79.    if ( mem_ptr->next >= 0 )
  80.    {
  81.       return_unit    =  mem_ptr->next ;
  82.       next_ptr       = (UNIT *) (*ptr_ptr + memory->len_unit* mem_ptr->next) ;
  83.       next_ptr->prev =  mem_ptr->prev ;
  84.    }
  85.    else
  86.       return_unit    =  -1 ;
  87.  
  88.    if ( mem_ptr->prev >= 0 )
  89.    {
  90.       return_unit        =  mem_ptr->prev ;
  91.       previous_ptr       = (UNIT *) (*ptr_ptr + memory->len_unit*mem_ptr->prev);
  92.       previous_ptr->next =  mem_ptr->next ;
  93.    }
  94.    mem_ptr->prev =  -1 ;
  95.    mem_ptr->next =  -1 ;
  96.  
  97.    return( return_unit ) ;
  98. }
  99.  
  100.  
  101. /* h4alloc.c
  102.  
  103.    Memory allocation routine.
  104.    Calls u4error if there is not enough memory.
  105.    Zeros the memory with NULL's
  106. */
  107.  
  108. #ifdef H4TEST
  109.    void *  h4malloc_test(unsigned int) ;
  110. #endif
  111.  
  112. char * h4alloc( int num )
  113. {
  114.    char * ptr ;
  115.  
  116.    #ifdef WINDOWS
  117.       ptr =  (char *) h4alloc_try(num) ;
  118.    #else
  119.       #ifdef H4TEST
  120.          ptr =  (char *) h4malloc_test((unsigned) num) ;
  121.       #else
  122.          ptr =  (char *) h4alloc_try( num ) ;
  123.       #endif
  124.    #endif
  125.  
  126.    if (ptr==  ((char *)0) )
  127.    {
  128.       u4error( E_MEMORY, (char *) 0) ;
  129.       return( (char *) 0 ) ;
  130.    }
  131.    else
  132.       memset(ptr, 0, (size_t) num) ;
  133.  
  134.    return( ptr) ;
  135. }
  136.  
  137. char * h4alloc_try( int num )
  138. {
  139.    #ifdef WINDOWS
  140.       HANDLE  handle, *handle_ptr ;
  141.  
  142.       handle_ptr =  (HANDLE *) 0 ;
  143.  
  144.       #ifdef WINDOWS_G
  145.          handle =  GlobalAlloc( GMEM_FIXED, (DWORD) num+ sizeof(HANDLE) ) ;
  146.      if ( handle != (HANDLE) 0 )
  147.      {
  148.         handle_ptr =  (HANDLE *) GlobalLock( handle ) ;
  149.         *handle_ptr++ =  handle ;
  150.      }
  151.       #else
  152.          handle =  LocalAlloc( LMEM_FIXED, (WORD) num+ sizeof(HANDLE) ) ;
  153.      if ( handle != (HANDLE) 0 )
  154.      {
  155.         handle_ptr =  (HANDLE *) LocalLock( handle ) ;
  156.         *handle_ptr++ =  handle ;
  157.      }
  158.       #endif
  159.  
  160.       return( (char *) handle_ptr ) ;
  161.    #else
  162.       #ifdef H4TEST
  163.          #ifdef NO_ALLOC
  164.             Forced Compile Error:  H4TEST Cannot be used with NO_ALLOC
  165.          #else
  166.             return( h4malloc_test((unsigned) num) ) ;
  167.          #endif
  168.       #else
  169.          #ifdef NO_ALLOC
  170.             unsigned int num_par ;
  171.             static   union  memory_ptr_st
  172.             {
  173.                char  *far_ptr ;
  174.                struct ptr_st { unsigned int off ; unsigned int seg ; } p ;
  175.             }  memory_ptr ;
  176.  
  177.             if ( sizeof(char *) != sizeof(char far *) )
  178.             {
  179.                u4error( 0, "Large Memory Model Only",(char *) 0 ) ;
  180.                exit(1) ;
  181.             }
  182.  
  183.             memory_ptr.far_ptr =  0 ;
  184.             num_par =   ( ((unsigned int) num) -1)/16 + 1 ;
  185.  
  186.             _AH =  0x48 ;
  187.             _BX =  num_par ;
  188.             geninterrupt(0x21) ;
  189.             if ( _FLAGS & 1 )  return( 0 ) ;
  190.  
  191.             memory_ptr.p.seg =  _AX ;
  192.             return( memory_ptr.far_ptr ) ;
  193.          #else
  194.             return( (char *) malloc((size_t) num) ) ;
  195.          #endif
  196.       #endif
  197.    #endif
  198. }
  199.  
  200. void  h4free_memory( void *ptr )
  201. {
  202.    #ifdef WINDOWS
  203.       #ifdef WINDOWS_G
  204.          HANDLE  hand ;
  205.  
  206.      hand =  ((HANDLE *) ptr)[-1] ;
  207.  
  208.       /* rc   =  GlobalUnlock( hand ) ;
  209.      if ( rc )    u4error( E_INTERNAL, "h4free_memory", (char *) 0 ) ;
  210.       */
  211.  
  212.      hand =  GlobalFree( hand ) ;
  213.      if ( hand != (HANDLE) 0 )    
  214.               u4error( E_INTERNAL, "h4free_memory", (char *) 0 ) ;
  215.       #else
  216.          HANDLE  hand ;
  217.  
  218.      hand =  ((HANDLE *) ptr)[-1] ;
  219.  
  220.       /* rc   =  LocalUnlock( hand ) ;
  221.      if ( ! rc )   u4error( E_INTERNAL, "h4free_memory", (char *) 0 ) ;
  222.       */
  223.  
  224.      hand =  LocalFree( hand ) ;
  225.      if ( hand != (HANDLE) 0 )    
  226.               u4error( E_INTERNAL, "h4free_memory", (char *) 0 ) ;
  227.       #endif
  228.    #else
  229.       #ifdef H4TEST
  230.          #ifdef NO_ALLOC
  231.             Forced Compile Error:  H4TEST Cannot be used with NO_ALLOC
  232.          #else
  233.             h4free_test(ptr) ;
  234.          #endif
  235.       #else
  236.          #ifdef NO_ALLOC
  237.             unsigned int  save_es ;
  238.    
  239.             save_es =  _ES ;
  240.             _AH =  0x49 ;
  241.             _ES =  FP_SEG(ptr) ;
  242.             geninterrupt( 0x21 ) ;
  243.             _ES =  save_es ;
  244.  
  245.             if ( _FLAGS & 1 )  
  246.                u4error( E_INTERNAL, "Freeing Memory", (char *) 0 ) ;
  247.          #else
  248.             free(ptr) ;
  249.          #endif
  250.       #endif
  251.    #endif
  252. }
  253.  
  254.  
  255. /*  h4get.c
  256.  
  257.     Allocates a block of memory from the predefined memory array.
  258.     Adds it to the end of the linked list.
  259. */
  260.  
  261. int h4get( char **ptr_ptr, int previous_ref)
  262. {
  263.    char   *new_ptr ;
  264.    int      i, unit_ref ;
  265.    long   new_size ;
  266.    MEMORY *memory ;
  267.    UNIT   *unit_ptr, *previous_ptr, *next_ptr ;
  268.  
  269.    memory= (MEMORY *) (*ptr_ptr -sizeof(MEMORY)) ;
  270.  
  271.    if (memory->first_free >= memory->num_unit)
  272.    {
  273.       /*  Must allocate some additional memory for the new unit */
  274.  
  275.       new_size = (unsigned int) memory->len_unit*
  276.        ((unsigned long)memory->num_unit+memory->add_unit)+sizeof(MEMORY);
  277.       if ( new_size > 0xFFE0L )
  278.       {
  279.          u4error( E_ALLOCATE, "h4create()", (char *) 0 ) ;
  280.      return -1 ;
  281.       }
  282.       new_ptr  = h4alloc((unsigned int) new_size) ;
  283.       if ( new_ptr == (char *) 0 )  return -1 ;
  284.  
  285.       memcpy( new_ptr, (char *) memory, (size_t) 
  286.            (memory->len_unit*(unsigned long) memory->num_unit)+ sizeof(MEMORY)) ;
  287.       h4free_memory((char *) memory) ;
  288.  
  289.       /* update  memory and  *ptr_ptr  to the new memory block */
  290.       memory      = (MEMORYPTR) new_ptr ;
  291.       new_ptr     += sizeof(MEMORY) ;
  292.       *ptr_ptr      = new_ptr ;
  293.  
  294.       /*  Create some pointers to keep track of the newly memory units */
  295.       unit_ptr      = (UNIT *) (*ptr_ptr + memory->len_unit* memory->num_unit) ;
  296.  
  297.       for (i= memory->num_unit+1; i<= memory->num_unit+ memory->add_unit; i++)
  298.       {
  299.      unit_ptr->next = i ;
  300.      unit_ptr    = (UNIT *) ((char *)unit_ptr +    memory->len_unit) ;
  301.       }
  302.  
  303.       /* There is new number of memory units in the memory block */
  304.       memory->num_unit += memory->add_unit ;
  305.    }
  306.  
  307.    /*  Unallocate from the chain of unallocated units */
  308.    unit_ptr          = (UNIT *) (*ptr_ptr + memory->len_unit* memory->first_free) ;
  309.    unit_ref          =  memory->first_free ;
  310.    memory->first_free =  unit_ptr->next  ;
  311.  
  312.    /*  Add to the new double linked list */
  313.    if (previous_ref >= 0)
  314.    {
  315.       unit_ptr->prev     =  previous_ref ;
  316.       previous_ptr     = (UNIT *) (*ptr_ptr + memory->len_unit* previous_ref) ;
  317.       unit_ptr->next     =  previous_ptr->next ;
  318.       previous_ptr->next = unit_ref ;
  319.  
  320.       if ( unit_ptr->next >= 0 )
  321.       {
  322.      next_ptr     = (UNIT *) (*ptr_ptr + memory->len_unit* previous_ptr->next) ;
  323.      next_ptr->prev  = unit_ref ;
  324.       }
  325.    }
  326.    else
  327.    {
  328.       unit_ptr->next  =  -1 ;
  329.       unit_ptr->prev  =  -1 ;
  330.    }
  331.    memset( (char *)unit_ptr+sizeof(UNIT), 0, (size_t) memory->len_unit-sizeof(UNIT) ) ;
  332.  
  333.    return( unit_ref ) ;
  334. }
  335.  
  336. /* h4create.c */
  337.  
  338. int  h4create( char **ptr_ptr, int num, int len, int add )
  339. {
  340.    int    i ;
  341.    unsigned long  total ;
  342.    MEMORYPTR   mem_stru ;
  343.    union 
  344.    {
  345.       int   *int_ptr  ;
  346.       char  *char_ptr ;
  347.    }  ptr ;
  348.  
  349.    if (len<= 0) len = 1 ;
  350.    if (num<= 0) num = 1 ;
  351.    if (add<=0)    add = 1 ;
  352.  
  353.    total =  (unsigned long) len * num + sizeof(MEMORY) ;
  354.    if (total > 0xFFE0L )
  355.       u4error( E_ALLOCATE, "h4create()", (char *) 0 ) ;
  356.    ptr.char_ptr =  h4alloc( (unsigned int) total ) ;
  357.    if ( ptr.char_ptr == (char *) 0 )  return -1 ;
  358.  
  359.    mem_stru = (MEMORYPTR) ptr.char_ptr ;
  360.    ptr.char_ptr += sizeof(MEMORY) ;
  361.    *ptr_ptr = ptr.char_ptr ;
  362.  
  363.    mem_stru->first_free= 0 ;
  364.    mem_stru->len_unit  = len ;
  365.    mem_stru->num_unit  = num ;
  366.    mem_stru->add_unit  = add ;
  367.  
  368.    for (i=1; i<=num; i++)
  369.    {
  370.       *ptr.int_ptr  =  i ;
  371.       ptr.char_ptr +=  len ;
  372.    }
  373.  
  374.    return 0 ;
  375. }
  376.  
  377. /*
  378.     h4free.c
  379.  
  380.     Frees a memory unit.
  381.     Maintains the double linked list.
  382.  
  383.     Returns
  384.        Returns the a reference to the previous memory unit.
  385.        If the previous memory unit does not exist, return a reference
  386.        to the next memory unit.  If a next memory unit does not exist,
  387.        return -1.
  388.  
  389.        On error return -2.
  390. */
  391.  
  392. h4free( char **ptr_ptr, int unit_ref )
  393. {
  394.    MEMORY *memory ;
  395.    UNIT   *unit_ptr, *next_ptr, *previous_ptr ;
  396.    int       return_unit ;
  397.  
  398.    memory = (MEMORY *) ( *ptr_ptr - sizeof(MEMORY) ) ;
  399.    if (unit_ref>= memory->num_unit || unit_ref<0)
  400.    {
  401.       u4error( E_INTERNAL, "H4FREE", (char *) 0) ;
  402.       return(-2) ;
  403.    }
  404.  
  405.    unit_ptr     = (UNIT *) (*ptr_ptr +  memory->len_unit* unit_ref) ;
  406.  
  407.    /*  Maintain the double linked list */
  408.    if ( unit_ptr->next >= 0)
  409.    {
  410.       next_ptr        = (UNIT *) (*ptr_ptr +  memory->len_unit* unit_ptr->next) ;
  411.       next_ptr->prev=  unit_ptr->prev ;
  412.    }
  413.    if ( unit_ptr->prev >= 0)
  414.    {
  415.       previous_ptr    = (UNIT *) (*ptr_ptr +    memory->len_unit* unit_ptr->prev);
  416.       previous_ptr->next= unit_ptr->next ;
  417.  
  418.       return_unit    = unit_ptr->prev ;
  419.    }
  420.    else
  421.       return_unit    = unit_ptr->next ;
  422.  
  423.  
  424.    /*  Fix up the pointer to the released memory */
  425.  
  426.    unit_ptr->next     =  memory->first_free ;
  427.    memory->first_free =  unit_ref ;
  428.  
  429.    return( return_unit ) ;
  430. }
  431.  
  432.  
  433. void  h4free_chain( char **ptr_ref_ptr, int mem_ref )
  434. {
  435.    while ( mem_ref >= 0 )
  436.       mem_ref =  h4free( ptr_ref_ptr, mem_ref ) ;
  437. }
  438.  
  439.  
  440. #ifdef H4TEST
  441. /* This test code ensures that only allocated pointers are freed.
  442.    In addition, it is possible to check that all pointers have
  443.    been freed.  This is a useful test for Code Base after it
  444.    has been uninitialized by calling 'd4init_undo', ...
  445. */
  446.  
  447. static void **h4test_pointers ;
  448. static int    h4num_pointer =  -1 ;
  449. static int    h4num_used =  0 ;
  450.  
  451. void *  h4malloc_test( unsigned int num_bytes )
  452. {
  453.    void *ptr ;
  454.  
  455.    if ( h4num_pointer < 0 )
  456.    {
  457.       h4test_pointers =  (void **)  malloc( sizeof(void *) * 100 ) ;
  458.       h4num_pointer =  100 ;
  459.    }
  460.    if ( h4num_pointer == h4num_used )
  461.    {
  462.       h4num_pointer += 100 ;
  463.       if ( h4num_pointer > 10000 )
  464.          u4error( E_INTERNAL, "h4malloc_test()", "Too many pointers", (char *) 0 ) ;
  465.  
  466.       h4test_pointers = (void **) realloc( h4test_pointers, sizeof(void *) *h4num_pointer ) ;
  467.    }
  468.  
  469.    if ( h4test_pointers == (void **) 0 )
  470.       u4error( E_INTERNAL, "h4malloc_test()", "Out of Memory", (char *) 0 ) ;
  471.  
  472.    ptr =  malloc( num_bytes ) ;
  473.    if ( ptr != (void *) 0 )   
  474.       h4test_pointers[h4num_used++] =  ptr ;
  475.  
  476.    return( ptr ) ;
  477. }
  478.  
  479. void  h4free_test( void *ptr )
  480. {
  481.    int  i ;
  482.  
  483.    for ( i=h4num_used-1; i>=0; i-- )
  484.       if ( h4test_pointers[i] == ptr )
  485.       {
  486.      free( ptr ) ;
  487.      /* This 'memmove' may create compile warning */
  488.      memmove( h4test_pointers+i, h4test_pointers+i+1, (size_t) (sizeof(void *) * h4num_used-i-1)) ;
  489.      h4num_used-- ;
  490.      return ;
  491.       }
  492.  
  493.    u4error( E_INTERNAL, "h4free_test()", "Free value not found", (char *) 0 ) ;
  494. }
  495.  
  496. int  h4free_check( int max_left )
  497. {
  498.    if ( h4num_used > max_left )
  499.       u4error( E_INTERNAL, "h4free_test()", "Free value not found", (char *) 0 ) ;
  500.  
  501.    return ( h4num_used ) ;
  502. }
  503. #endif
  504.