home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 1.ddi / CLIBSRC.ZIP / VNEWVF.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  6.5 KB  |  181 lines

  1. /*-----------------------------------------------------------------------*
  2.  * filename - vnewvf.cpp
  3.  * C++ VECTOR_NEW for virtual base classes.
  4.  * Called internally by the compiler to allocate arrays of classes
  5.  *  having constructors
  6.  *-----------------------------------------------------------------------*/
  7.  
  8. /*
  9.  *      C/C++ Run Time Library - Version 5.0
  10.  *
  11.  *      Copyright (c) 1990, 1992 by Borland International
  12.  *      All Rights Reserved.
  13.  *
  14.  */
  15.  
  16.  
  17. #include <stdlib.h>
  18. #include <stdarg.h>
  19. #include <dos.h>
  20. #include <_vector.h>
  21.  
  22. void far * _vector_vnew_(void far* ptr, // address of array, 0 means allocate it
  23.                  size_t size,           // size of each object
  24.                  unsigned long count,   // how many objects
  25.                  unsigned mode,         // actual type of constructor
  26.                  ...
  27.                  )
  28. /* This routine is used to initialize an array of class type.  If ptr is
  29.    NULL, it allocates the space for the array first.  Since the constructor
  30.    for the class may be of either memory model, and take an argument of any
  31.    memory model, we are forced to pass a mode parameter to tell us how to
  32.    cast it.  Since we must pass a near pointer for near functions and a
  33.    far call for far functions, we can't even know the argument type until
  34.    runtime, so we have to use varargs to get at it.  This version passes the
  35.    second argument needed for a class with virtual bases.
  36.  
  37.    If the constructor pointer is NULL no constructors are called.
  38.  
  39.    The interpretation of the mode parameter is:
  40.        far function    0x01     VFARCALL
  41.        pascal call     0x02     VPASCAL
  42.        far pointer     0x04     VFARPTR
  43.        deallocate      0x08     VDEALLOC
  44.        stored count    0x10     VSTORECNT
  45.        fastcall        0x20     VFASTCALL
  46.        huge vector     0x40     VHUGEVECT
  47.        fastthis        0x80     VFASTTHIS
  48.        this last       0x100    VTHISLAST
  49. */
  50. {
  51.     va_list ap;         // for access to parameters
  52.     consvNNC np;        // near call version
  53.     consvFNC fp;        // far call version
  54.     int construct = 1;  // flag whether to call constructors
  55.  
  56.     va_start(ap, mode);
  57.  
  58.     if (mode & VFARCALL)
  59.         {
  60.         fp = va_arg(ap, consvFNC);
  61.         if (!fp)
  62.             construct = 0;
  63.         }
  64.     else
  65.         {
  66.         np = va_arg(ap, consvNNC);
  67.         if (!np)
  68.             construct = 0;
  69.         }
  70.  
  71.     if (ptr == 0)               // should we allocate it?
  72.         {
  73.         unsigned Header;
  74.         unsigned Overhead = 0;
  75.         unsigned PadFromZero;
  76.  
  77.         if (mode & VSTORECNT)   // stored count
  78.             Overhead = sizeof(count);
  79.  
  80.         if (mode & VHUGEVECT)   // huge vector
  81.             {
  82.             Overhead += sizeof(Header);
  83.             ptr = operator new((unsigned long)count * size + Overhead + size);
  84.             if (!ptr)
  85.                 return 0;
  86.             PadFromZero = (unsigned) (65536L % size);
  87.             Header = FP_OFF(ptr);
  88.             while (PadFromZero < Overhead + Header)
  89.                 PadFromZero += size;
  90.  
  91.             (char far *)ptr += PadFromZero - Header - Overhead;
  92.             *(unsigned far *)ptr = Header;
  93.             ((unsigned far *)ptr)++;
  94.             }
  95.         else
  96.             {
  97.             unsigned long Length = size * count + Overhead;
  98.             if (Length > 0xFFFF)
  99.                 return 0;
  100.  
  101.             ptr = operator new((unsigned long)Length);
  102.             if (!ptr)
  103.                 return 0;
  104.             }
  105.  
  106.         // have ptr at either final location or count before
  107.  
  108.         if (mode & VSTORECNT)   // store count
  109.             {
  110.             *(unsigned long far *)ptr = count;
  111.             ((unsigned long far *)ptr)++;
  112.             }
  113.         }
  114.  
  115.     mode &= VCALLTYPE;   // strip out all flags except call type
  116.  
  117.     if (mode & VFASTTHIS)   // this-last has no effect with fast-this
  118.         mode &= ~(VTHISLAST);
  119.  
  120.     if (construct)
  121.         {
  122.         for( char huge *p = (char huge *) ptr;  count-- > 0;  p += size )
  123.             switch (mode)
  124.                 {
  125.                 case (VFARPTR):
  126.                     (*(consvNFC) np)((void far *) p, 0); break;
  127.                 case (VFARCALL | VFARPTR):
  128.                     (*(consvFFC) fp)((void far *) p, 0); break;
  129.                 case (VFARPTR | VPASCAL):
  130.                     (*(consvNFP) np)((void far *) p, 0); break;
  131.                 case (VFARPTR | VPASCAL | VTHISLAST):
  132.                     (*(consvNFPL) np)(0, (void far *) p); break;
  133.                 case (VFARCALL | VFARPTR | VPASCAL):
  134.                     (*(consvFFP) fp)((void far *) p, 0); break;
  135.                 case (VFARCALL | VFARPTR | VPASCAL | VTHISLAST):
  136.                     (*(consvFFPL) fp)(0, (void far *) p); break;
  137.                 case (VFARPTR | VFASTCALL):
  138.                     (*(consvNFF) np)((void far *) p, 0); break;
  139.                 case (VFARPTR | VFASTCALL | VTHISLAST):
  140.                     (*(consvNFFL) np)(0, (void far *) p); break;
  141.                 case (VFARCALL | VFARPTR | VFASTCALL):
  142.                     (*(consvFFF) fp)((void far *) p, 0); break;
  143.                 case (VFARCALL | VFARPTR | VFASTCALL | VTHISLAST):
  144.                     (*(consvFFFL) fp)(0, (void far *) p); break;
  145.                 case (VFARPTR | VFASTTHIS):
  146.                     LOAD_FAR_THIS(p);
  147.                     (*(consvNFCT) np)(0);
  148.                     END_FAR_THIS();
  149.                     break;
  150.                 case (VFARCALL | VFARPTR | VFASTTHIS):
  151.                     LOAD_FAR_THIS(p);
  152.                     (*(consvFFCT) fp)(0);
  153.                     END_FAR_THIS();
  154.                     break;
  155.                 case (VFARPTR | VPASCAL | VFASTTHIS):
  156.                     LOAD_FAR_THIS(p);
  157.                     (*(consvNFPT) np)(0);
  158.                     END_FAR_THIS();
  159.                     break;
  160.                 case (VFARCALL | VFARPTR | VPASCAL | VFASTTHIS):
  161.                     LOAD_FAR_THIS(p);
  162.                     (*(consvFFPT) fp)(0);
  163.                     END_FAR_THIS();
  164.                     break;
  165.                 case (VFARPTR | VFASTCALL | VFASTTHIS):
  166.                     LOAD_FAR_THIS(p);
  167.                     (*(consvNFFT) np)(0);
  168.                     END_FAR_THIS();
  169.                     break;
  170.                 case (VFARCALL | VFARPTR | VFASTCALL | VFASTTHIS):
  171.                     LOAD_FAR_THIS(p);
  172.                     (*(consvFFFT) fp)(0);
  173.                     END_FAR_THIS();
  174.                     break;
  175.                 default:
  176.                     abort(); break;
  177.                 }
  178.         }
  179.     return ptr;
  180. }
  181.