/*-----------------------------------------------------------------------*
 * filename - intdos.cas
 *
 * function(s)
 *        intdos  - general MS-DOS interrupt interface
 *        intdosx - general MS-DOS interrupt interface
 *-----------------------------------------------------------------------*/

/*
 *      C/C++ Run Time Library - Version 5.0
 *
 *      Copyright (c) 1987, 1992 by Borland International
 *      All Rights Reserved.
 *
 */

#pragma inline
#include <asmrules.h>
#include <dos.h>
#include <_io.h>

#if defined(_Windows)
void far pascal DOS3Call(void);
#endif

/*-----------------------------------------------------------------------*

Name            intdos - general MS-DOS interrupt interface

Usage           #include <dos.h>
                int intdos(union REGS * inregs, union REGS * outregs);

Related
functions usage int intdosx(union REGS *inregs, union REGS *outregs,
                            struct SREGS *segregs);

Prototype in    dos.h

Description     Both of these functions execute DOS interrupt 0x21
                to invoke a specified DOS function. The value of
                inregs->h.al specifies the DOS function to be invoked.

                In addition, intdosx copies the segregs->x.ds and
                segregs->x.es values into the corresponding registers
                before invoking the DOS function. This feature allows
                programs that use far pointers, or that use a large
                data memory model, to specify which segment is
                to be used during the function execution.

                After the interrupt 0x21 returns, both functions copy the
                current register values to outregs, copy the status of the
                system carry flag to the x.cflag field in outregs, and
                copy the value of the 8086 flags register to the x.flags
                field in outregs.  In addition, intdosx restores DS, and
                sets the segregs->es and segregs->ds fields to the values
                of the corresponding segment registers.

                If the carry flag is set, it indicates that an error occurred.

                intdosx allows you to invoke a DOS function that takes a value
                of DS different from the default data segment, and/or that takes
                an argument in ES.

                Note that inregs can point to the same structure that outregs
                points to.

Return value    intdos and intdosx return the value of AX after completion
                of the DOS function call. If the carry flag is set
                (outregs->x.cflag != 0), indicating an error, these
                functions set   _doserrno to the error code.

*------------------------------------------------------------------------*/
int intdos(union REGS *inregs, union REGS *outregs)
{
        struct  SREGS   s;

        segread(&s);
        return(intdosx(inregs, outregs, &s));
}


/*-----------------------------------------------------------------------*

Name            intdosx - general MS-DOS interrupt interface

Usage           #include <dos.h>
                int intdosx(union REGS *inregs, union REGS *outregs,
                            struct SREGS *segregs);

Prototype in    dos.h

Description     see intdos.

*------------------------------------------------------------------------*/

int intdosx(union REGS _FAR *inregs,
            union REGS _FAR *outregs,
            struct SREGS _FAR *segregs
           )
{
        /* Save caller context */

asm     push    ds

        /* Set registers with register structure content */

asm     LDS_    si, segregs
asm     push    [si].es
asm     push    [si].ds
asm     LDS_    si, inregs
asm     mov     ax, [si].ax
asm     mov     bx, [si].bx
asm     mov     cx, [si].cx
asm     mov     dx, [si].dx
asm     mov     di, [si].di
asm     mov     si, [si].si
asm     pop     ds
asm     pop     es

        /* Call DOS */

asm     push    bp              /* just to be safe */
#if !defined( _Windows )
asm     int     021h
#else
        DOS3Call();
#endif
asm     pop     bp

        /* Set register structure with registers */

asm     pushf
asm     pushf
asm     push    si
asm     push    ds
asm     push    es
#if     !LDATA
asm     mov     ds, [bp-6]
#endif
asm     LDS_    si, segregs
asm     pop     [si].es
asm     pop     [si].ds
asm     LDS_    si, outregs
asm     pop     [si].si
asm     pop     [si].flags
asm     pop     [si].cflag
asm     and     word ptr [si].cflag, 1
asm     mov     [si].di, di
asm     mov     [si].dx, dx
asm     mov     [si].cx, cx
asm     mov     [si].bx, bx
asm     mov     [si].ax, ax
asm     pop     ds
asm     jz      intdosOk
asm     push    ax
        __IOerror(_AX);
asm     pop     ax

intdosOk:
        return(_AX);
}
