173 lines
5.8 KiB
C
173 lines
5.8 KiB
C
/*
|
||
This program is the Microsoft C (ver. 4.0) implementation of the
|
||
transcendental functions. The official implementation used by PC SCHEME
|
||
was done under the Lattice C version. This purpose of this program is to
|
||
show you what is needed to communicate with XLI via MS C. The
|
||
lines containing comments that start out with @@ designate lines that
|
||
will need to be modified by you when you use this template program
|
||
for your own purpose.
|
||
|
||
Note: Before linking this program you will need to use the Macro
|
||
Assembler to assemble the file GLUE_MS.ASM. The output of
|
||
the assembler, GLUE_MS.OBJ will then be linked with the object
|
||
of this file created by MSC.
|
||
|
||
The command line to compile is:
|
||
MSC trig_ms;
|
||
|
||
The command line to assemble is:
|
||
MASM glue_ms;
|
||
|
||
The command line to link this program is:
|
||
LINK trig_ms+glue_ms;
|
||
*/
|
||
|
||
#include "dos.h"
|
||
#include "math.h"
|
||
#include "stdlib.h"
|
||
|
||
#define F_NEAR 0x0001 /* Set model flag to near. USED */
|
||
#define F_INT 0x0002 /* Set integer flag to 16 bits. NOT-USED */
|
||
#define F_REL 0x0004 /* Set release env block by extern pgm flag. N-U */
|
||
#define F_PAD 0x0008 /* Set parm blocking flag to unblocked. USED */
|
||
|
||
#define RT_INTEGER 0 /* Set return type to be an integer. NOT-USED */
|
||
#define RT_BOOLEAN 1 /* Set return type to be boolean. NOT-USED */
|
||
#define RT_STRING 2 /* Set return type to be a string. NOT-USED */
|
||
#define RT_DOUBLE 3 /* Set the return type to be a float num. USED */
|
||
|
||
typedef unsigned short WORD; /* 16-bit unsigned value */
|
||
|
||
/*
|
||
Xwait and xbye will contain the actual addresses, XLI entry points, that
|
||
we'll jump to when we call XLI so they need to be big enough to hold FAR
|
||
pointers.
|
||
*/
|
||
WORD xwait[2];
|
||
WORD xbye[2];
|
||
|
||
WORD tsize; /* Will contain the length of this program in paragraphs. */
|
||
|
||
struct xli_file_struct {
|
||
WORD id;
|
||
WORD flags;
|
||
WORD table[2]; /* offset in 0, segment in 1 */
|
||
WORD parm_block[2];
|
||
WORD reserved[8];
|
||
} file_block;
|
||
|
||
struct xli_routine_struct {
|
||
WORD select;
|
||
WORD special_service;
|
||
WORD ss_args[8];
|
||
WORD reserved[8];
|
||
WORD return_type;
|
||
double return_value;
|
||
double arg1; /* @@ Add as many args as you need. */
|
||
double arg2;
|
||
} parm_block;
|
||
|
||
char table[] =
|
||
/*
|
||
@@ The following string contains the names of the functions that can
|
||
be called from within SCHEME when this file is loaded thru XLI.
|
||
|
||
0 1 2 3 4 5 6 7 8 9 10 11 12
|
||
*/
|
||
"sqrt/sin/cos/tan/asin/acos/atan/atan2/exp/expt/ln/log10/log//";
|
||
|
||
|
||
void main()
|
||
/*
|
||
Within the main body of code the only portions that you will need to
|
||
change are:
|
||
1) The value of the FILE-BLOCK.FLAGS and
|
||
2) The functions that you will call from within the CASE stmts.
|
||
*/
|
||
{
|
||
struct SREGS segregs;
|
||
|
||
/*
|
||
These function are defined in the assembly file GLUE_MS.ASM and are
|
||
the functions that interface with Schemes XLI.
|
||
*/
|
||
int xli_wait();
|
||
void xli_bye();
|
||
|
||
|
||
union {
|
||
WORD far * psp_ptr; /* declare as a far 32 bit pointer. */
|
||
WORD half_ptrs[2]; /* declare two 16 bit words for Seg & Off. */
|
||
} ptr;
|
||
|
||
/*
|
||
The following code will initialize the File Block as needed.
|
||
*/
|
||
file_block.id = 0x4252;
|
||
file_block.flags = F_NEAR+F_PAD; /* @@ Set flags as appropiate. */
|
||
|
||
segread(&segregs); /* Obtain the register information. */
|
||
file_block.table[0] = (WORD) table;
|
||
file_block.table[1] = segregs.ds;
|
||
file_block.parm_block[0] = (WORD) &parm_block;
|
||
file_block.parm_block[1] = segregs.ds;
|
||
|
||
|
||
/*
|
||
The word at the PSP+2 is set by MS C to contain the next available
|
||
paragraph number after this program. So if we subtract from this
|
||
address the address of the PSP then we get the size of this program
|
||
in paragraphs.
|
||
*/
|
||
ptr.half_ptrs[0] = 2; /* Set the offset to two, */
|
||
ptr.half_ptrs[1] = _psp; /* and the segment to the PSP. */
|
||
tsize = *(ptr.psp_ptr) - _psp;
|
||
|
||
|
||
ptr.half_ptrs[0] = 0; /* Set the offset to zero, */
|
||
ptr.half_ptrs[1] = _psp; /* and the segment to the PSP. */
|
||
|
||
/*
|
||
Establish the connection between C and the PSP.
|
||
*/
|
||
ptr.psp_ptr[46] = (WORD far) &file_block; /* Set into the PSP the offset and */
|
||
ptr.psp_ptr[47] = segregs.ds; /* segment address of file_block */
|
||
|
||
xwait[0] = ptr.psp_ptr[5]; /* Store into XWAIT the offset and */
|
||
xwait[1] = ptr.psp_ptr[6]; /* segment address of DOS's terminate routine. */
|
||
|
||
xbye[0] = xwait[0]; /* Copy the termination segment and */
|
||
xbye[1] = xwait[1]; /* offset address, from above, into here. */
|
||
|
||
xwait[0] += 3; /* incr by 3 for normal call */
|
||
xbye[0] += 6; /* incr by 6 for termination */
|
||
|
||
while (xli_wait()) {
|
||
switch (parm_block.select) {
|
||
case 0: parm_block.return_value = sqrt(parm_block.arg1); break;
|
||
case 1: parm_block.return_value = sin(parm_block.arg1); break;
|
||
case 2: parm_block.return_value = cos(parm_block.arg1); break;
|
||
case 3: parm_block.return_value = tan(parm_block.arg1); break;
|
||
case 4: parm_block.return_value = asin(parm_block.arg1); break;
|
||
case 5: parm_block.return_value = acos(parm_block.arg1); break;
|
||
case 6: parm_block.return_value = atan(parm_block.arg1); break;
|
||
case 7: parm_block.return_value =
|
||
atan2(parm_block.arg1,parm_block.arg2); break;
|
||
case 8: parm_block.return_value = exp(parm_block.arg1); break;
|
||
case 9: parm_block.return_value =
|
||
pow(parm_block.arg1,parm_block.arg2); break;
|
||
case 10: parm_block.return_value = log(parm_block.arg1); break;
|
||
case 11: parm_block.return_value = log10(parm_block.arg1); break;
|
||
case 12: parm_block.return_value =
|
||
log(parm_block.arg1) / log(parm_block.arg2); break;
|
||
default: ;
|
||
} /* end switch */
|
||
|
||
parm_block.return_type = RT_DOUBLE;
|
||
|
||
} /* end while */
|
||
|
||
xli_bye();
|
||
|
||
} /* end main */
|
||
|