void near * _vector_vnew_(void near *ptr, // address of array, 0 means allocate
                 size_t size,             // size of each object
                 unsigned count,          // how many objects
                 unsigned mode,           // actual type of constructor
                 ...
                 )
/* This routine is used to initialize an array of class type.  If ptr is
   NULL, it allocates the space for the array first.  Since the constructor
   for the class may be of either memory model, and take an argument of any
   memory model, we are forced to pass a mode parameter to tell us how to
   cast it.  Since we must pass a near pointer for near functions and a
   far call for far functions, we can't even know the argument type until
   runtime, so we have to use varargs to get at it.  This version passes the
   second argument needed for a class with virtual bases.

   If the constructor pointer is NULL no constructors are called.

   The interpretation of the mode parameter is:
       far function    0x01     VFARCALL
       pascal call     0x02     VPASCAL
       far pointer     0x04     VFARPTR
       deallocate      0x08     VDEALLOC
       stored count    0x10     VSTORECNT
       fastcall        0x20     VFASTCALL
       huge vector     0x40     VHUGEVECT
       fastthis        0x80     VFASTTHIS
       this last       0x100    VTHISLAST
*/
{
#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
    abort();
    return 0;
#else
    va_list ap;         // for access to parameters
    consvNNC np;        // near call version
    consvFNC fp;        // far call version
    int construct = 1;  // flag whether to call constructors

    va_start(ap, mode);

    if (mode & VFARCALL)
        {
        fp = va_arg(ap, consvFNC);
        if (!fp)
            construct = 0;
        }
    else
        {
        np = va_arg(ap, consvNNC);
        if (!np)
            construct = 0;
        }

    if( ptr == 0 )
        {
        unsigned long Length = size * count;

        if (mode & VSTORECNT)   // stored count
            Length += sizeof(count);

        // check that additional bytes don't make it go over 64K
        if (Length > 0xFFFF)
            return 0;

        ptr = operator new((unsigned)Length);

        if (!ptr)
            return 0;

        // have ptr at either final location or count before
        if (mode & VSTORECNT)   // store count
            {
            *(unsigned *)ptr = count;
            ((unsigned *)ptr)++;
            }
        }

    mode &= VCALLTYPE;   // strip out all flags except call type

    if (mode & VFASTTHIS)   // this-last has no effect with fast-this
        mode &= ~(VTHISLAST);

    if (construct)
        {
        for( char *p = (char *) ptr;  count-- > 0;  p += size )
            switch (mode)
                {
                case 0:
                    (*(consvNNC) np)((void near *) p, 0); break;
                case (VFARCALL):
                    (*(consvFNC) fp)((void near *) p, 0); break;
                case (VPASCAL):
                    (*(consvNNP) np)((void near *) p, 0); break;
                case (VPASCAL | VTHISLAST):
                    (*(consvNNPL) np)(0, (void near *) p); break;
                case (VFARCALL | VPASCAL):
                    (*(consvFNP) fp)((void near *) p, 0); break;
                case (VFARCALL | VPASCAL | VTHISLAST):
                    (*(consvFNPL) fp)(0, (void near *) p); break;
                case (VFASTCALL):
                    (*(consvNNF) np)((void near *) p, 0); break;
                case (VFASTCALL | VTHISLAST):
                    (*(consvNNFL) np)(0, (void near *) p); break;
                case (VFARCALL | VFASTCALL):
                    (*(consvFNF) fp)((void near *) p, 0); break;
                case (VFARCALL | VFASTCALL | VTHISLAST):
                    (*(consvFNFL) fp)(0, (void near *) p); break;
                case (0 | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(consvNNCT) np)(0);
                    END_NEAR_THIS();
                    break;
                case (VFARCALL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(consvFNCT) fp)(0);
                    END_NEAR_THIS();
                    break;
                case (VPASCAL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(consvNNPT) np)(0);
                    END_NEAR_THIS();
                    break;
                case (VFARCALL | VPASCAL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(consvFNPT) fp)(0);
                    END_NEAR_THIS();
                    break;
                case (VFASTCALL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(consvNNFT) np)(0);
                    END_NEAR_THIS();
                    break;
                case (VFARCALL | VFASTCALL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(consvFNFT) fp)(0);
                    END_NEAR_THIS();
                    break;
                default:
                    abort(); break;
                }
        }
    return ptr;
#endif
}
void _vector_delete_(void near *ptr,    // address of array (always needed)
             size_t size,               // size of each object
             unsigned count,            // how many objects
             unsigned mode,             // How to call
             ...
            )
/* This routine is used to destroy an array of class type.  If mode is
   set, it deallocates the space for the array afterwards. Since the
   destructor for the class may be of either memory model, and take
   an argument of any memory model, we are forced to pass a mode parameter
   to tell us how to cast it.  Since we must pass a near pointer for near
   functions and a far pointer for far functions, we can't even know the
   argument type until runtime, so we have to use varargs to get at it.

   If the destructor pointer is NULL no destructors are called.

   The interpretation of the mode parameter is:
       far function    0x01     VFARCALL
       pascal call     0x02     VPASCAL
       far pointer     0x04     VFARPTR
       deallocate      0x08     VDEALLOC
       stored count    0x10     VSTORECNT
       fastcall        0x20     VFASTCALL
       huge vector     0x40     VHUGEVECT
       fastthis        0x80     VFASTTHIS
       this last       0x100    VTHISLAST
*/
{
#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
    abort();
#else
    va_list ap;         // for access to parameters
    destNNC np;         // near call version
    destFNC fp;         // far call version
    int destruct = 1;   // flag whether to call destructors

    if (!ptr)
        return;

    va_start(ap, mode);

    if (mode & VFARCALL)
        {
        fp = va_arg(ap, destFNC);
        if (!fp)
            destruct = 0;
        }
    else
        {
        np = va_arg(ap, destNNC);
        if (!np)
            destruct = 0;
        }

    if (mode & VSTORECNT)   // if stored count
        count = *((unsigned *) ((char *)ptr - sizeof(count)));

    if (destruct)
        {
        // get call type
        unsigned CallType = mode & VCALLTYPE;

        // this-last has no effect with fast-this
        if (CallType & VFASTTHIS)
            CallType &= ~(VTHISLAST);

        for(char near *p = (char near *) ptr + size * (count - 1);
            count-- > 0; p -= size)
            {
            switch (CallType)
                {
                case 0:
                    (*(destNNC) np)((void near *) p, 2); break;
                case (VFARCALL):
                    (*(destFNC) fp)((void near *) p, 2); break;
                case (VPASCAL):
                    (*(destNNP) np)((void near *) p, 2); break;
                case (VPASCAL | VTHISLAST):
                    (*(destNNPL) np)(2, (void near *) p); break;
                case (VFARCALL | VPASCAL):
                    (*(destFNP) fp)((void near *) p, 2); break;
                case (VFARCALL | VPASCAL | VTHISLAST):
                    (*(destFNPL) fp)(2, (void near *) p); break;
                case (VFASTCALL):
                    (*(destNNF) np)((void near *) p, 2); break;
                case (VFASTCALL | VTHISLAST):
                    (*(destNNFL) np)(2, (void near *) p); break;
                case (VFARCALL | VFASTCALL):
                    (*(destFNF) fp)((void near *) p, 2); break;
                case (VFARCALL | VFASTCALL | VTHISLAST):
                    (*(destFNFL) fp)(2, (void near *) p); break;
                case (0 | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(destNNCT) np)(2);
                    END_NEAR_THIS();
                    break;
                case (VFARCALL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(destFNCT) fp)(2);
                    END_NEAR_THIS();
                    break;
                case (VPASCAL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(destNNPT) np)(2);
                    END_NEAR_THIS();
                    break;
                case (VFARCALL | VPASCAL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(destFNPT) fp)(2);
                    END_NEAR_THIS();
                    break;
                case (VFASTCALL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(destNNFT) np)(2);
                    END_NEAR_THIS();
                    break;
                case (VFARCALL | VFASTCALL | VFASTTHIS):
                    LOAD_NEAR_THIS(p);
                    (*(destFNFT) fp)(2);
                    END_NEAR_THIS();
                    break;
                default:
                    abort(); break;
                }
            }
        }

    if (mode & VDEALLOC)
        {
        if (mode & VSTORECNT)   // stored count
            ptr = (char *)ptr - sizeof(count);

        operator delete((void near *)ptr);
        }
#endif
}
void  _vector_applyv_(void far * dest,  // address of destination array
                      void far * src,   // address of source array
                      size_t size,      // size of each object
                      unsigned count,   // number of objects
                      unsigned mode,    // type of function to call
                      ...
                     )

/* This routine is used to copy an array of class type.

   Since the routine used for the class may be of either memory model, and
   take arguments of any memory model, we are forced to pass a mode
   parameter to tell us how to cast it.  Since we must pass a near pointer
   for near functions and a far call for far functions, we can't even know
   the argument type until runtime, so we have to use varargs to get at it.
   We do assume that both source and destination have the same distance
   modifier, and the compiler enforces that.

   The interpretation of the mode parameter is:
       far function    0x01     VFARCALL
       pascal call     0x02     VPASCAL
       far pointer     0x04     VFARPTR
       fastcall        0x20     VFASTCALL
       fastthis        0x80     VFASTTHIS
       this last       0x100    VTHISLAST
*/
{
    va_list ap;         /* for access to parameters */
    appvNNC np;         /* Near pointer version */
    appvFNC fp;         /* Far pointer version */

    va_start(ap, mode);

    if (mode & 1)
        fp = va_arg(ap, appvFNC);
    else
        np = va_arg(ap, appvNNC);

    if (mode & VFASTTHIS)   // this-last has no effect with fast-this
        mode &= ~(VTHISLAST);

    do
        {
        switch (mode)
            {
            case 0:
                (*(appvNNC) np)((void near *)dest, 0, (void near *)src); break;
            case (VFARCALL):
                (*(appvFNC) fp)((void near *)dest, 0, (void near *)src); break;
            case (VPASCAL):
                (*(appvNNP) np)((void near *)dest, 0, (void near *)src); break;
            case (VPASCAL | VTHISLAST):
                (*(appvNNPL) np)(0, (void near *)src, (void near *)dest); break;
            case (VFARCALL | VPASCAL):
                (*(appvFNP) fp)((void near *)dest, 0, (void near *)src); break;
            case (VFARCALL | VPASCAL | VTHISLAST):
                (*(appvFNPL) fp)(0, (void near *)src, (void near *)dest); break;
            case (VFASTCALL):
                (*(appvNNF) np)((void near *)dest, 0, (void near *)src); break;
            case (VFASTCALL | VTHISLAST):
                (*(appvNNFL) np)(0, (void near *)src, (void near *)dest); break;
            case (VFARCALL | VFASTCALL):
                (*(appvFNF) fp)((void near *)dest, 0, (void near *)src); break;
            case (VFARCALL | VFASTCALL | VTHISLAST):
                (*(appvFNFL) fp)(0, (void near *)src, (void near *)dest); break;
            case (VFARPTR):
                (*(appvNFC) np)((void far  *)dest, 0, (void far  *)src); break;
            case (VFARCALL | VFARPTR):
                (*(appvFFC) fp)((void far  *)dest, 0, (void far  *)src); break;
            case (VFARPTR | VPASCAL):
                (*(appvNFP) np)((void far  *)dest, 0, (void far  *)src); break;
            case (VFARPTR | VPASCAL | VTHISLAST):
                (*(appvNFPL) np)(0, (void far  *)src, (void far  *)dest); break;
            case (VFARCALL | VFARPTR | VPASCAL):
                (*(appvFFP) fp)((void far  *)dest, 0, (void far  *)src); break;
            case (VFARCALL | VFARPTR | VPASCAL | VTHISLAST):
                (*(appvFFPL) fp)(0, (void far  *)src, (void far  *)dest); break;
            case (VFARPTR | VFASTCALL):
                (*(appvNFF) np)((void far  *)dest, 0, (void far  *)src); break;
            case (VFARPTR | VFASTCALL | VTHISLAST):
                (*(appvNFFL) np)(0, (void far  *)src, (void far  *)dest); break;
            case (VFARCALL | VFARPTR | VFASTCALL):
                (*(appvFFF) fp)((void far  *)dest, 0, (void far  *)src); break;
            case (VFARCALL | VFARPTR | VFASTCALL | VTHISLAST):
                (*(appvFFFL) fp)(0, (void far  *)src, (void far *)dest); break;
            case (0 | VFASTTHIS):
                LOAD_NEAR_THIS(dest);
                (*(appvNNCT) np)(0, (void near *)src);
                END_NEAR_THIS();
                break;
            case (VFARCALL | VFASTTHIS):
                LOAD_NEAR_THIS(dest);
                (*(appvFNCT) fp)(0, (void near *)src);
                END_NEAR_THIS();
                break;
            case (VPASCAL | VFASTTHIS):
                LOAD_NEAR_THIS(dest);
                (*(appvNNPT) np)(0, (void near *)src);
                END_NEAR_THIS();
                break;
            case (VFARCALL | VPASCAL | VFASTTHIS):
                LOAD_NEAR_THIS(dest);
                (*(appvFNPT) fp)(0, (void near *)src);
                END_NEAR_THIS();
                break;
            case (VFASTCALL | VFASTTHIS):
                LOAD_NEAR_THIS(dest);
                (*(appvNNFT) np)(0, (void near *)src);
                END_NEAR_THIS();
                break;
            case (VFARCALL | VFASTCALL | VFASTTHIS):
                LOAD_NEAR_THIS(dest);
                (*(appvFNFT) fp)(0, (void near *)src);
                END_NEAR_THIS();
                break;
            case (VFARPTR | VFASTTHIS):
                LOAD_FAR_THIS(dest);
                (*(appvNFCT) np)(0, (void far  *)src);
                END_FAR_THIS();
                break;
            case (VFARCALL | VFARPTR | VFASTTHIS):
                LOAD_FAR_THIS(dest);
                (*(appvFFCT) fp)(0, (void far  *)src);
                END_FAR_THIS();
                break;
            case (VFARPTR | VPASCAL | VFASTTHIS):
                LOAD_FAR_THIS(dest);
                (*(appvNFPT) np)(0, (void far  *)src);
                END_FAR_THIS();
                break;
            case (VFARCALL | VFARPTR | VPASCAL | VFASTTHIS):
                LOAD_FAR_THIS(dest);
                (*(appvFFPT) fp)(0, (void far  *)src);
                END_FAR_THIS();
                break;
            case (VFARPTR | VFASTCALL | VFASTTHIS):
                LOAD_FAR_THIS(dest);
                (*(appvNFFT) np)(0, (void far  *)src);
                END_FAR_THIS();
                break;
            case (VFARCALL | VFARPTR | VFASTCALL | VFASTTHIS):
                LOAD_FAR_THIS(dest);
                (*(appvFFFT) fp)(0, (void far  *)src);
                END_FAR_THIS();
                break;
            default:
                abort(); break;
            }
        (char far *) dest += size;
        (char far *) src += size;
        } while (--count > 0);
}