From c7aad48ec8db813775a95a0f0902c9bff31dafcb Mon Sep 17 00:00:00 2001 From: davidly Date: Mon, 1 Jul 2024 15:26:34 -0700 Subject: [PATCH] Mix Power C v1 --- Mix Power C v1/ABSDISK.ASM | 70 ++ Mix Power C v1/ALLOCMEM.C | 47 ++ Mix Power C v1/ARITH.C | 460 +++++++++++ Mix Power C v1/BESSEL.C | 470 +++++++++++ Mix Power C v1/BIOS.C | 204 +++++ Mix Power C v1/BIOSFN.ASM | 166 ++++ Mix Power C v1/CHAIN.C | 304 +++++++ Mix Power C v1/CLOSE.C | 101 +++ Mix Power C v1/CONVERT.C | 224 +++++ Mix Power C v1/DISABLE.ASM | 154 ++++ Mix Power C v1/DIV.ASM | 35 + Mix Power C v1/DOS.H | 236 ++++++ Mix Power C v1/DOSETC.C | 237 ++++++ Mix Power C v1/DSTRING.C | 27 + Mix Power C v1/DTAFAT.ASM | 89 ++ Mix Power C v1/DUP.C | 51 ++ Mix Power C v1/DYSTRING.C | 328 ++++++++ Mix Power C v1/E.C | 30 + Mix Power C v1/ENVIR.ASM | 147 ++++ Mix Power C v1/ENVIR.C | 130 +++ Mix Power C v1/ERROR.C | 53 ++ Mix Power C v1/ERRORS.C | 4 + Mix Power C v1/ETC.C | 128 +++ Mix Power C v1/EXEC.ASM | 692 ++++++++++++++++ Mix Power C v1/EXIT.C | 72 ++ Mix Power C v1/FAR.ASM | 227 ++++++ Mix Power C v1/FARHEAP.ASM | 1212 ++++++++++++++++++++++++++++ Mix Power C v1/FARMEM.ASM | 374 +++++++++ Mix Power C v1/FARSTR.ASM | 1045 ++++++++++++++++++++++++ Mix Power C v1/FARSTR1.ASM | 97 +++ Mix Power C v1/FATAL.ASM | 47 ++ Mix Power C v1/FCNTL.H | 15 + Mix Power C v1/FDB.H | 33 + Mix Power C v1/FILE.C | 344 ++++++++ Mix Power C v1/FILLM.ASM | 519 ++++++++++++ Mix Power C v1/FINDFIRS.C | 38 + Mix Power C v1/FLAGS.C | 104 +++ Mix Power C v1/FLUSH.ASM | 140 ++++ Mix Power C v1/FREE.ASM | 219 +++++ Mix Power C v1/FSTAT.C | 80 ++ Mix Power C v1/GET.ASM | 245 ++++++ Mix Power C v1/GETS.C | 50 ++ Mix Power C v1/GRAPHICS.C | 582 +++++++++++++ Mix Power C v1/INIT.ASM | 380 +++++++++ Mix Power C v1/INIT.C | 166 ++++ Mix Power C v1/INOUT.ASM | 63 ++ Mix Power C v1/INTENT.ASM | 230 ++++++ Mix Power C v1/INTR.ASM | 70 ++ Mix Power C v1/INTRPT.ASM | 48 ++ Mix Power C v1/IO.ASM | 16 + Mix Power C v1/LIB.ASM | 34 + Mix Power C v1/LIB2.ASM | 28 + Mix Power C v1/LIBDEF.ASM | 150 ++++ Mix Power C v1/LOCKING.C | 118 +++ Mix Power C v1/LOCKING.H | 10 + Mix Power C v1/LONG.ASM | 524 ++++++++++++ Mix Power C v1/MEMORY.C | 21 + Mix Power C v1/MERGE.EXE | Bin 0 -> 18512 bytes Mix Power C v1/MIXC.BAT | 10 + Mix Power C v1/MIXC.MIX | Bin 0 -> 5843 bytes Mix Power C v1/MIXC1.C | 277 +++++++ Mix Power C v1/MOVMEM.ASM | 484 +++++++++++ Mix Power C v1/MSDOS.C | 205 +++++ Mix Power C v1/NEW.ASM | 270 +++++++ Mix Power C v1/NHEAP.ASM | 251 ++++++ Mix Power C v1/OPEN.C | 254 ++++++ Mix Power C v1/PC.EXE | Bin 0 -> 155760 bytes Mix Power C v1/PC87.MIX | Bin 0 -> 18590 bytes Mix Power C v1/PCA.EXE | Bin 0 -> 55776 bytes Mix Power C v1/PCAUTO.MIX | Bin 0 -> 44461 bytes Mix Power C v1/PCDMY.MIX | Bin 0 -> 1176 bytes Mix Power C v1/PCIEEE.MIX | Bin 0 -> 29989 bytes Mix Power C v1/PCL.EXE | Bin 0 -> 18944 bytes Mix Power C v1/PCLIB.BAT | 10 + Mix Power C v1/PCLIB.MIX | Bin 0 -> 93173 bytes Mix Power C v1/PCLIB.PRJ | 25 + Mix Power C v1/PCLIB2.BAT | 10 + Mix Power C v1/PCLIB2.MIX | Bin 0 -> 98626 bytes Mix Power C v1/PCLIB2.PRJ | 14 + Mix Power C v1/PCO.EXE | Bin 0 -> 122688 bytes Mix Power C v1/PEEK.ASM | 75 ++ Mix Power C v1/PERROR.C | 95 +++ Mix Power C v1/PRINTF.C | 589 ++++++++++++++ Mix Power C v1/PROCESS.H | 32 + Mix Power C v1/PUT.ASM | 222 +++++ Mix Power C v1/PUTS.C | 60 ++ Mix Power C v1/RAND.C | 51 ++ Mix Power C v1/READ.ASM | 360 +++++++++ Mix Power C v1/SCANF.C | 555 +++++++++++++ Mix Power C v1/SCREEN.ASM | 1571 ++++++++++++++++++++++++++++++++++++ Mix Power C v1/SEEK.ASM | 200 +++++ Mix Power C v1/SETBUF.C | 74 ++ Mix Power C v1/SETJMP.ASM | 124 +++ Mix Power C v1/SETMEM.ASM | 72 ++ Mix Power C v1/SIEVE.C | 35 + Mix Power C v1/SIGNAL.ASM | 293 +++++++ Mix Power C v1/SORT.C | 104 +++ Mix Power C v1/SOUND.ASM | 62 ++ Mix Power C v1/STACK.ASM | 75 ++ Mix Power C v1/STAT.H | 37 + Mix Power C v1/STDARG.H | 12 + Mix Power C v1/STDIO.H | 102 +++ Mix Power C v1/STDLIB | 6 + Mix Power C v1/STDLIB.C | 22 + Mix Power C v1/STDLIB2 | 3 + Mix Power C v1/STDLIB2.C | 20 + Mix Power C v1/STD_LIB.H | 278 +++++++ Mix Power C v1/STRCOLL.C | 23 + Mix Power C v1/STRING.ASM | 1002 +++++++++++++++++++++++ Mix Power C v1/SYS.ASM | 1117 +++++++++++++++++++++++++ Mix Power C v1/TEMPFILE.C | 134 +++ Mix Power C v1/TIME.C | 538 ++++++++++++ Mix Power C v1/TO.ASM | 421 ++++++++++ Mix Power C v1/TTT.C | 527 ++++++++++++ Mix Power C v1/UNGETC.C | 51 ++ Mix Power C v1/WRITE.ASM | 390 +++++++++ Mix Power C v1/m.bat | 9 + 117 files changed, 22839 insertions(+) create mode 100644 Mix Power C v1/ABSDISK.ASM create mode 100644 Mix Power C v1/ALLOCMEM.C create mode 100644 Mix Power C v1/ARITH.C create mode 100644 Mix Power C v1/BESSEL.C create mode 100644 Mix Power C v1/BIOS.C create mode 100644 Mix Power C v1/BIOSFN.ASM create mode 100644 Mix Power C v1/CHAIN.C create mode 100644 Mix Power C v1/CLOSE.C create mode 100644 Mix Power C v1/CONVERT.C create mode 100644 Mix Power C v1/DISABLE.ASM create mode 100644 Mix Power C v1/DIV.ASM create mode 100644 Mix Power C v1/DOS.H create mode 100644 Mix Power C v1/DOSETC.C create mode 100644 Mix Power C v1/DSTRING.C create mode 100644 Mix Power C v1/DTAFAT.ASM create mode 100644 Mix Power C v1/DUP.C create mode 100644 Mix Power C v1/DYSTRING.C create mode 100644 Mix Power C v1/E.C create mode 100644 Mix Power C v1/ENVIR.ASM create mode 100644 Mix Power C v1/ENVIR.C create mode 100644 Mix Power C v1/ERROR.C create mode 100644 Mix Power C v1/ERRORS.C create mode 100644 Mix Power C v1/ETC.C create mode 100644 Mix Power C v1/EXEC.ASM create mode 100644 Mix Power C v1/EXIT.C create mode 100644 Mix Power C v1/FAR.ASM create mode 100644 Mix Power C v1/FARHEAP.ASM create mode 100644 Mix Power C v1/FARMEM.ASM create mode 100644 Mix Power C v1/FARSTR.ASM create mode 100644 Mix Power C v1/FARSTR1.ASM create mode 100644 Mix Power C v1/FATAL.ASM create mode 100644 Mix Power C v1/FCNTL.H create mode 100644 Mix Power C v1/FDB.H create mode 100644 Mix Power C v1/FILE.C create mode 100644 Mix Power C v1/FILLM.ASM create mode 100644 Mix Power C v1/FINDFIRS.C create mode 100644 Mix Power C v1/FLAGS.C create mode 100644 Mix Power C v1/FLUSH.ASM create mode 100644 Mix Power C v1/FREE.ASM create mode 100644 Mix Power C v1/FSTAT.C create mode 100644 Mix Power C v1/GET.ASM create mode 100644 Mix Power C v1/GETS.C create mode 100644 Mix Power C v1/GRAPHICS.C create mode 100644 Mix Power C v1/INIT.ASM create mode 100644 Mix Power C v1/INIT.C create mode 100644 Mix Power C v1/INOUT.ASM create mode 100644 Mix Power C v1/INTENT.ASM create mode 100644 Mix Power C v1/INTR.ASM create mode 100644 Mix Power C v1/INTRPT.ASM create mode 100644 Mix Power C v1/IO.ASM create mode 100644 Mix Power C v1/LIB.ASM create mode 100644 Mix Power C v1/LIB2.ASM create mode 100644 Mix Power C v1/LIBDEF.ASM create mode 100644 Mix Power C v1/LOCKING.C create mode 100644 Mix Power C v1/LOCKING.H create mode 100644 Mix Power C v1/LONG.ASM create mode 100644 Mix Power C v1/MEMORY.C create mode 100644 Mix Power C v1/MERGE.EXE create mode 100644 Mix Power C v1/MIXC.BAT create mode 100644 Mix Power C v1/MIXC.MIX create mode 100644 Mix Power C v1/MIXC1.C create mode 100644 Mix Power C v1/MOVMEM.ASM create mode 100644 Mix Power C v1/MSDOS.C create mode 100644 Mix Power C v1/NEW.ASM create mode 100644 Mix Power C v1/NHEAP.ASM create mode 100644 Mix Power C v1/OPEN.C create mode 100644 Mix Power C v1/PC.EXE create mode 100644 Mix Power C v1/PC87.MIX create mode 100644 Mix Power C v1/PCA.EXE create mode 100644 Mix Power C v1/PCAUTO.MIX create mode 100644 Mix Power C v1/PCDMY.MIX create mode 100644 Mix Power C v1/PCIEEE.MIX create mode 100644 Mix Power C v1/PCL.EXE create mode 100644 Mix Power C v1/PCLIB.BAT create mode 100644 Mix Power C v1/PCLIB.MIX create mode 100644 Mix Power C v1/PCLIB.PRJ create mode 100644 Mix Power C v1/PCLIB2.BAT create mode 100644 Mix Power C v1/PCLIB2.MIX create mode 100644 Mix Power C v1/PCLIB2.PRJ create mode 100644 Mix Power C v1/PCO.EXE create mode 100644 Mix Power C v1/PEEK.ASM create mode 100644 Mix Power C v1/PERROR.C create mode 100644 Mix Power C v1/PRINTF.C create mode 100644 Mix Power C v1/PROCESS.H create mode 100644 Mix Power C v1/PUT.ASM create mode 100644 Mix Power C v1/PUTS.C create mode 100644 Mix Power C v1/RAND.C create mode 100644 Mix Power C v1/READ.ASM create mode 100644 Mix Power C v1/SCANF.C create mode 100644 Mix Power C v1/SCREEN.ASM create mode 100644 Mix Power C v1/SEEK.ASM create mode 100644 Mix Power C v1/SETBUF.C create mode 100644 Mix Power C v1/SETJMP.ASM create mode 100644 Mix Power C v1/SETMEM.ASM create mode 100644 Mix Power C v1/SIEVE.C create mode 100644 Mix Power C v1/SIGNAL.ASM create mode 100644 Mix Power C v1/SORT.C create mode 100644 Mix Power C v1/SOUND.ASM create mode 100644 Mix Power C v1/STACK.ASM create mode 100644 Mix Power C v1/STAT.H create mode 100644 Mix Power C v1/STDARG.H create mode 100644 Mix Power C v1/STDIO.H create mode 100644 Mix Power C v1/STDLIB create mode 100644 Mix Power C v1/STDLIB.C create mode 100644 Mix Power C v1/STDLIB2 create mode 100644 Mix Power C v1/STDLIB2.C create mode 100644 Mix Power C v1/STD_LIB.H create mode 100644 Mix Power C v1/STRCOLL.C create mode 100644 Mix Power C v1/STRING.ASM create mode 100644 Mix Power C v1/SYS.ASM create mode 100644 Mix Power C v1/TEMPFILE.C create mode 100644 Mix Power C v1/TIME.C create mode 100644 Mix Power C v1/TO.ASM create mode 100644 Mix Power C v1/TTT.C create mode 100644 Mix Power C v1/UNGETC.C create mode 100644 Mix Power C v1/WRITE.ASM create mode 100644 Mix Power C v1/m.bat diff --git a/Mix Power C v1/ABSDISK.ASM b/Mix Power C v1/ABSDISK.ASM new file mode 100644 index 0000000..de4561a --- /dev/null +++ b/Mix Power C v1/ABSDISK.ASM @@ -0,0 +1,70 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; absread(drive, nsects, sectno, buffer) +; ------------------------------------------------------- +; int drive; /* disk drive number (a=0, b=1, etc) */ +; int nsects; /* number of sectors */ +; int sectno; /* logical sector number */ +; char *buffer; /* buffer for data */ +; +; returns zero if successful, -1 on error +; ------------------------------------------------------- +; + IDT absread + DEF absread + DREF errno +; +absread PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV CX,[BP][%PARM2] + MOV DX,[BP][%PARM3] + MOV BX,[BP][%PARM4] + INT >25 + JB ERROR + POPF + XOR AX,AX + POP BP + RETSEG +ERROR POPF + MOV [errno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; abswrite(drive, nsects, sectno, buffer) +; ------------------------------------------------------- +; int drive; /* disk drive number (a=0, b=1, etc) */ +; int nsects; /* number of sectors */ +; int sectno; /* logical sector number */ +; char *buffer; /* buffer for data */ +; +; returns zero if successful, -1 on error +; ------------------------------------------------------- +; + IDT abswrite + DEF abswrite + DREF errno +; +abswrite PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV CX,[BP][%PARM2] + MOV DX,[BP][%PARM3] + MOV BX,[BP][%PARM4] + INT >26 + JB ERROR + POPF + XOR AX,AX + POP BP + RETSEG +ERROR POPF + MOV [errno],AX + MOV AX,-1 + POP BP + RETSEG + END diff --git a/Mix Power C v1/ALLOCMEM.C b/Mix Power C v1/ALLOCMEM.C new file mode 100644 index 0000000..185561b --- /dev/null +++ b/Mix Power C v1/ALLOCMEM.C @@ -0,0 +1,47 @@ +/* Copyright (c) Mix Software 1988 */ + +int allocmem(size, seg) + unsigned size; /* size of block requested (in paragraphs) */ + unsigned *seg; /* segment address of result */ +{ + union REGS r; + r.h.ah = 0x48; + r.x.bx = size; + intdos(&r,&r); + if (r.x.cflag) return r.x.bx; + *seg = r.x.ax; + return -1; + } + +int freemem(seg) + unsigned seg; /* segment address of previously allocated block */ +{ + extern int errno; + union REGS r; + struct SREGS sr; + r.h.ah = 0x49; + sr.es = seg; + intdosx(&r,&r,&sr); + if (r.x.cflag == 0) return 0; + errno = ENOMEM; + return -1; + } + +int setblock(seg,newsize) + unsigned seg; /* segment address of previously allocated block */ + unsigned newsize; /* new size (in paragraphs) */ +{ + extern int errno; + extern int _doserrno; + union REGS r; + struct SREGS sr; + r.h.ah = 0x4a; + r.x.bx = newsize; + sr.es = seg; + intdosx(&r,&r,&sr); + if (r.x.cflag == 0) return -1; + _doserrno = r.x.ax; + errno = ENOMEM; + return r.x.bx; + } + diff --git a/Mix Power C v1/ARITH.C b/Mix Power C v1/ARITH.C new file mode 100644 index 0000000..ea17699 --- /dev/null +++ b/Mix Power C v1/ARITH.C @@ -0,0 +1,460 @@ + +/* Arithmetic functions */ +/* Copyright (c) Mix Software 1988 */ + +abs(i) +int i; +{ + return i < 0 ? -i : i; +} + +/* ------------------------------------------------------------ */ + +double cabs(z) +struct complex z; +{ /* complex absolute value */ + double sqrt(); + return sqrt(z.x*z.x + z.y*z.y); +} + +/* ------------------------------------------------------------ */ + +double acos(x) +double x; +{ /* inverse cosine */ + double asin(); + double value; + static double piover2 = 1.5707963267948966; + if (x > 1.0 || x < -1.0) return _domerr("acos",x,x); + value = asin(x); + return piover2 - value; +} + +/* ------------------------------------------------------------ */ + +double asin(x) +double x; +{ /* inverse sine */ + double _domerr(), fabs(), atan(), sqrt(); + static double piover2 = 1.5707963267948966; + double absx = fabs(x); + double value; + if (x > 1.0 || x < -1.0) return _domerr("asin",x,x); + if (absx == 0.0) value = 0.0; + else value = piover2 - atan(sqrt(1-x*x)/absx); + if (x < 0) return -value; else return value; +} + +/* ------------------------------------------------------------ */ + +double atan2(x,y) + double x,y; +{ + /* return arc tangent of y/x + atan2 is useful when converting rectangular to polar coordinates + */ + extern double (far *$0DATN)(); + static double piover2 = 1.5707963267948966; + static double pi = 3.141592653589793; + double atan(), _domerr(); + double value; + if (x == 0.0) { + if (y == 0.0) return _domerr("atan2",x,y); + if (y < 0.0) return pi; else return 0.0; + } + value = $0DATN(y/x); + if (x < 0.0) return -value-piover2; + return piover2 - value; +} + +/* ------------------------------------------------------------ */ + +double atan(x) +double x; +{ /* inverse tangent */ + extern double (far *$0DATN)(); + return $0DATN(x); +} + +/* ------------------------------------------------------------ */ + +double ceil(x) +double x; +{ + extern double (far *$0DFIXR)(); + double r; + r = $0DFIXR(x); + if (r == x) return r; + return r + 1.0; +} + +/* ------------------------------------------------------------ */ + +double tan(x) + double x; +{ + double cos(), sin(), _domerr(); + double c; + c = cos(x); + if (c == 0.0) return _domerr("tan",x,x); + return sin(x)/c; + } /* tan */ + +/* ------------------------------------------------------------ */ + +double cos(x) + double x; +{ + extern double (far *$0DCOS)(); + double _tloss(), _ploss(), fabs(); + static char name[] = "cos"; + double a; + a = fabs(x); + if (a > 6.283185307179586e10) { + if (a > 6.283185307179586e16) return _tloss(name,x,x); + _ploss(name,x,x); + return $0DCOS(x); + } + return $0DCOS(x); +} /* cos */ + +/* ------------------------------------------------------------ */ + +double cosh(x) + double x; +{ + extern double exp(); + return (exp(x) + exp(-x)) / 2.0; +} /* cosh */ + +/* ------------------------------------------------------------ */ + +double sinh(x) + double x; +{ + extern double exp(); + return (exp(x) - exp(-x)) / 2.0; +} /* sinh */ + +/* ------------------------------------------------------------ */ + +double tanh(x) + double x; +{ + extern double exp(); + double xplus, xminus; + xplus = exp(x); + xminus = exp(-x); + return (xplus - xminus) / (xplus + xminus); +} /* tanh */ + +/* ------------------------------------------------------------ */ + +double exp(x) + double x; +{ + extern double (far *$0DEXP)(); + double _rangerr(); + extern double _EXPMAX, _EXPMIN, HUGE; + static char name[] = "exp"; + if (x > _EXPMAX) { + _rangerr(name,x,x); + return HUGE; + } + if (x < _EXPMIN) return _rangerr(name,x,x); + return $0DEXP(x); +} /* exp */ + +/* ------------------------------------------------------------ */ + +double floor(x) +double x; +{ + extern double (far *$0DFIXR)(); + return $0DFIXR(x); +} + +/* ------------------------------------------------------------ */ + +double fmod(x, y) +double x,y; +{ + extern double (far *$0DFIXR)(); + if (y == 0.0) return _domerr("fmod",x,y); + return x - y*$0DFIXR(x/y); +} + +/* ------------------------------------------------------------ */ + +double hypot(x, y) +double x,y; +{ + double sqrt(); + return (sqrt(x*x + y*y)); +} + +/* ------------------------------------------------------------ */ + +double log10(x) +double x; +{ + double log(); + return log(x) / 2.3025850929940457; +} + +/* ------------------------------------------------------------ */ + +double log(x) + double x; +{ + extern double (far *$0DLN)(); + double _domerr(), _singerr(); + extern double HUGE; + static char name[] = "log"; + if (x <= 0.0) { + if (x == 0.0) { _singerr(name,x,x); return -HUGE; } + _domerr(name,x,x); return -HUGE; + } + return $0DLN(x); +} /* log */ + +/* ------------------------------------------------------------ */ + +double pow(x,y) +double x; +double y; +{ + extern double (far *$0DXTOY)(); + static char name[] = "pow"; + double _domerr(), modf(); + double intval; + if (x > 0.0) return $0DXTOY(x,y); + if (x == 0.0) { + if (y >= 0.0) return 0.0; + return _domerr(name,x,y); + } + if (modf(x,&intval) != 0.0) return _domerr(name,x,y); + if (modf(intval/2.0,&intval) != 0) return -($0DXTOY(x,y)); + return $0DXTOY(x,y); +} /* pow */ + +/* ------------------------------------------------------------ */ + +double modf(x, intptr) +double x; +double *intptr; +{ + extern double (far *$0DFIXR)(); + *intptr = $0DFIXR(x); + return x - (*intptr); +} /* modf */ + +/* ------------------------------------------------------------ */ + +double sin(x) + double x; +{ + extern double (far *$0DSIN)(); + double _tloss(), _ploss(), fabs(); + static char name[] = "sin"; + double a; + a = fabs(x); + if (a > 6.283185307179586e10) { + if (a > 6.283185307179586e16) return _tloss(name,x,x); + _ploss(name,x,x); + return $0DSIN(x); + } + return $0DSIN(x); +} /* sin */ + +/* ------------------------------------------------------------ */ + +double sqrt(x) + double x; +{ + extern double (far *$0DSQRT)(); + double _domerr(); + if (x < 0.0) return _domerr("sqrt",x,x); + return $0DSQRT(x); +} /* sqrt */ + +double poly(x, n, c) + double x; + int n; /* highest power of x in polynomial */ + double c[]; /* array of coefficients (n+1 elements) */ +{ + double *coef; + double value; + coef = &c[n-1]; + value = c[n]; + while (n--) { + value = value*x + *coef; + --coef; + } + return value; + } + +/* ------------------------------------------------------------ */ +/* error handling for math errors */ + +double _domerr(name,arg1,arg2) + char *name; + double arg1,arg2; +{ /* indicate a domain error + if matherr returns 0, the answer is 0 */ + extern int errno; + extern char $$ARTERM; + extern char _mathmsg; + struct exception e; + e.type = DOMAIN; + e.name = name; + e.arg1 = arg1; + e.arg2 = arg2; + if (matherr(&e)) return e.retval; + else { + errno = EDOM; + if (_mathmsg) { + fprintf(stderr,"Domain error in %s() at %g, %g\n",name,arg1,arg2); + if ($$ARTERM) abort(); + } + return 0.0; + } + } /* _domerr */ + +/* ------------------------------------------------------------ */ + +double _singerr(name,arg1,arg2) + char *name; + double arg1,arg2; +{ /* indicate a singularity + if matherr returns 0, the answer is HUGE */ + extern int errno; + extern char $$ARTERM; + extern char _mathmsg; + extern double HUGE; + struct exception e; + e.type = SING; + e.name = name; + e.arg1 = arg1; + e.arg2 = arg2; + if (matherr(&e)) return e.retval; + else { + errno = EDOM; + if (_mathmsg) { + fprintf(stderr,"Singularity error in %s() at %g, %g\n",name,arg1,arg2); + if ($$ARTERM) abort(); + } + return HUGE; + } + } /* _domerr */ + +/* ------------------------------------------------------------ */ + +double _tloss(name,arg1,arg2) + char *name; + double arg1,arg2; +{ /* indicate total loss of significance + if matherr returns 0, the answer is 0 */ + extern int errno; + extern char $$ARTERM; + extern char _mathmsg; + struct exception e; + e.type = TLOSS; + e.name = name; + e.arg1 = arg1; + e.arg2 = arg2; + if (matherr(&e)) return e.retval; + else { + errno = ERANGE; + if (_mathmsg) { + fprintf(stderr,"Total loss of signifcance in %s() at %g, %g\n",name,arg1,arg2); + if ($$ARTERM) abort(); + } + return 0.0; + } + } /* _tloss */ + +/* ------------------------------------------------------------ */ + +double _ploss(name,arg1,arg2) + char *name; + double arg1,arg2; +{ /* indicate partial loss of significance + if matherr returns 0, the answer is 0 */ + extern int errno; + struct exception e; + e.type = PLOSS; + e.name = name; + e.arg1 = arg1; + e.arg2 = arg2; + if (matherr(&e)) return e.retval; + return 0.0; + } /* _ploss */ + +/* ------------------------------------------------------------ */ + +double _rangerr(name,arg1,arg2) + char *name; + double arg1,arg2; +{ /* indicate a range error - result of function + is too large or too small to be represented as a double */ + extern int errno; + extern char $$ARTERM; + extern char _mathmsg; + struct exception e; + e.type = OVERFLOW; + e.name = name; + e.arg1 = arg1; + e.arg2 = arg2; + if (matherr(&e)) return e.retval; + else { + errno = ERANGE; + if (_mathmsg) { + fprintf(stderr,"Argument out of range in %s() at %g, %g\n",name,arg1,arg2); + if ($$ARTERM) abort(); + } + return 0.0; + } + } /* _rangerr */ + +/* ------------------------------------------------------------ */ + +int matherr(x) +struct exception *x; +{ + return 0; + } + +/* ------------------------------------------------------------ */ + +void _fpreset() +{ + _clear87(); + } + +/* ------------------------------------------------------------ */ + +unsigned int _clear87() +{ + extern unsigned int (far *$0clr87)(); + return $0clr87(); +} + +/* ------------------------------------------------------------ */ + +unsigned int _control87(new, mask) + unsigned int new; + unsigned int mask; +{ + extern unsigned int (far *$0ctl87)(); + return $0ctl87(new,mask); +} + +/* ------------------------------------------------------------ */ + +unsigned int _status87() +{ + extern unsigned int (far *$0sta87)(); + return $0sta87(); +} + diff --git a/Mix Power C v1/BESSEL.C b/Mix Power C v1/BESSEL.C new file mode 100644 index 0000000..a72bfdd --- /dev/null +++ b/Mix Power C v1/BESSEL.C @@ -0,0 +1,470 @@ + +/* Copyright (c) Mix Software 1988 */ +/* ------------------------------------------------------------ */ +/* bessel functions: j0, j1, jn */ +/* y0, y1, yn */ +double yn(n,x) + int n; + double x; +{ + double y0(), y1(); + double yz, yx, y, fx; + double _domerr(); + extern double HUGE; + int negative = 0; + int i; + if (n == 0) return y0(x); + if (n == 1) return y1(x); + if (n < 0) { + n = -n; + if (n & 0x0001) negative = 1; + } + if (x <= 0.0) {_domerr("yn",x,x); return HUGE;} + yz = y0(x); + yx = y1(x); + fx = 2.0/x; + i = 1; + while (i < n) { + y = fx * i * yx - yz; + yz = yx; + yx = y; + i++; + } + if (negative) return -y; + return y; +} /* yn */ + +double jn(n,x) + int n; + double x; +{ + double j0(), j1(); + double jz, jx, j, fx; + int i; + if (n == 0) return j0(x); + if (n == 1) return j1(x); + if (n < 0) return jn(-n,-x); + jz = j0(x); + jx = j1(x); + fx = 2.0/x; + i = 1; + while (i < n) { + j = fx * i * jx - jz; + jz = jx; + jx = j; + i++; + } + return j; +} /* jn */ + +double y0(x) + double x; +{ + double xsquare, xx, x8, y0; + double p, q; + double sin(), cos(), sqrt(), log(), j0(); + double _domerr(); + extern double HUGE; + void _pandq0(); + static double pi = 3.1415926535897932; + static double piby4 = 0.78539816339744831; + static double twobypi = 0.63661977236758134; + static struct { + int terms; + double tbl[8]; + } y0P = {8, + -0.40421653126104926e19, + 0.96736537146262430e19, + -0.75173702582406051e18, + 0.18702004643462448e17, + -0.20430408868635631e15, + 0.10869647137874908e13, + -0.27725001364628094e10, + 0.27295402301235549e7 + }; + static struct { + int terms; + double tbl[9]; + } y0Q = {9, + 0.54768700204477752e20, + 0.72620404690767952e18, + 0.49441312329373299e16, + 0.22900727639481849e14, + 0.80363630456265291e11, + 0.22400416108570433e9, + 0.50069757439413062e6, + 0.86456632023518903e3, + 0.10000000000000000e1 + }; + + extern double (far *$0DPOWER)(); + if (x <= 0.0) {_domerr("y0",x,x); return HUGE;} + if (x < 8.0) { + xsquare = x*x; + y0 = $0DPOWER(xsquare,&y0P)/$0DPOWER(xsquare,&y0Q); + return y0 + twobypi*j0(x)*log(x); + } + xx = x - piby4; + x8 = 8.0/x; + _pandq0(x8,&p,&q); + return sqrt(2.0/(pi*x)) * (p*sin(xx) + q*cos(xx)); +} /* y0 */ + +double y1(x) + double x; +{ + double xsquare, xx, x8, y1; + double p, q; + double sin(), cos(), sqrt(), log(), j1(); + double _domerr(); + extern double HUGE; + void _pandq1(); + static double pi = 3.1415926535897932; + static double piby34 = 2.35619449019234493; + static double twobypi = 0.63661977236758134; + static struct { + int terms; + double tbl[8]; + } y1P = {8, + -0.29238219615329625e20, + 0.77485206821868396e19, + -0.34410480630841144e18, + 0.59151607604900706e16, + -0.48633169425671751e14, + 0.20496966737456622e12, + -0.42894719688552488e9, + 0.35569240098305261e6 + }; + static struct { + int terms; + double tbl[9]; + } y1Q = {9, + 0.14913115113029204e21, + 0.18186628417061350e19, + 0.11316393826988845e17, + 0.47551735888881377e14, + 0.15002216991567090e12, + 0.37166607986219303e9, + 0.72691473071988846e6, + 0.10726961437789255e4, + 0.10000000000000000e1 + }; + + extern double (far *$0DPOWER)(); + if (x <= 0.0) {_domerr("y1",x,x); return HUGE;} + if (x < 8.0) { + xsquare = x*x; + y1 = x*$0DPOWER(xsquare,&y1P)/$0DPOWER(xsquare,&y1Q); + return y1 + twobypi*(j1(x)*log(x)-1.0/x); + } + xx = x - piby34; + x8 = 8.0/x; + _pandq1(x8,&p,&q); + return sqrt(2.0/(pi*x)) * (p*sin(xx) + q*cos(xx)); +} /* y1 */ + +double j0(x) + double x; +{ + double xsquare, xx, x8; + double p, q; + double sin(), cos(), sqrt(), fabs(); + void _pandq0(); + static double pi = 3.1415926535897932; + static double piby4 = 0.78539816339744831; + static struct { + int terms; + double tbl[12]; + } j0P = {12, + 0.18108389921416431e9, + -0.44464759561502412e8, + 0.26292976097233912e7, + -0.66351202963350577e5, + 0.90000108663859700e3, + -0.74117799951193489e1, + 0.39771954892980604e-1, + -0.14463518634545936e-3, + 0.36127859495623837e-6, + -0.60893587508087894e-9, + 0.64247367849791009e-12, + -0.33133602728361709e-15 + }; + static struct { + int terms; + double tbl[4]; + } j0Q = {4, + 0.18108389921416430e9, + 0.80621524203869792e6, + 0.14154950117074173e4, + 0.10000000000000000e1 + }; + static struct { + int terms; + double tbl[5]; + } j0pP = {5, + 0.21807736478830516e7, + 0.30343163608475270e7, + 0.11035444210405852e7, + 0.11252515255664381e6, + 0.22399036697750965e4 + }; + static struct { + int terms; + double tbl[6]; + } j0pQ = {6, + 0.21807736478830516e7, + 0.30367122303337213e7, + 0.11068209412295708e7, + 0.11366275712613906e6, + 0.23403140106394541e4, + 0.10000000000000000e1 + }; + static struct { + int terms; + double tbl[5]; + } j0qP = {5, + -0.17665456233082465e4, + -0.28720316121456664e4, + -0.12598828601325539e4, + -0.16263421062270593e3, + -0.44237584856933353e1 + }; + static struct { + int terms; + double tbl[6]; + } j0qQ = {6, + 0.11305891989633582e6, + 0.18484510850351025e6, + 0.82274660980144657e5, + 0.11085805836751487e5, + 0.35655140058576331e3, + 0.10000000000000000e1 + }; + + extern double (far *$0DPOWER)(); + x = fabs(x); + if (x < 8.0) { + xsquare = x*x; + return $0DPOWER(xsquare,&j0P)/$0DPOWER(xsquare,&j0Q); + } + xx = x - piby4; + x8 = 8.0/x; + _pandq0(x8,&p,&q); + /* + xsquare = x8*x8; + p = $0DPOWER(xsquare,&j0pP)/$0DPOWER(xsquare,&j0pQ); + q = x8*$0DPOWER(xsquare,&j0qP)/$0DPOWER(xsquare,&j0qQ); + */ + return sqrt(2.0/(pi*x)) * (p*cos(xx) - q*sin(xx)); +} /* j0 */ + +double j1(x) + double x; +{ + double xsquare, xx, x8, value; + double p, q; + int negative = 0; + double sin(), cos(), sqrt(); + void _pandq1(); + static double pi = 3.1415926535897932; + static double piby34 = 2.35619449019234493; + extern double (far *$0DPOWER)(); + static struct { + int terms; + double tbl[8]; + } j1P = {8, + 0.22148878804219631e18, + -0.25123742147032128e17, + 0.84824207447812727e15, + -0.12498203672620249e14, + 0.93165652967246732e11, + -0.36866689870229816e9, + 0.74370238171199964e6, + -0.60795301796074136e3 + }; + static struct { + int terms; + double tbl[8]; + } j1Q = {8, + 0.44297757608439262e18, + 0.51247127164848721e16, + 0.29898363077254872e14, + 0.11581921274668893e12, + 0.32819403445341964e9, + 0.69885861844850757e6, + 0.10777412894333044e4, + 0.10000000000000000e1 + }; +/* static struct { + int terms; + double tbl[5]; + } j1pP = {5, + -0.17469576694409286e7, + -0.23669439140521428e7, + -0.82850363738723775e6, + -0.79574568713505959e5, + -0.14279066288270981e4 + }; + static struct { + int terms; + double tbl[6]; + } j1pQ = {6, + -0.17469576694409286e7, + -0.23637451390226540e7, + -0.82423699065628189e6, + -0.78144050089391111e5, + -0.13084529833390797e4, + 0.10000000000000000e1 + }; + static struct { + int terms; + double tbl[5]; + } j1qP = {5, + 0.14465282874995209e3, + 0.17442916890924259e3, + 0.51736532818365916e2, + 0.37994453796980673e1, + 0.36363466476034711e-1 + }; + static struct { + int terms; + double tbl[5]; + } j1qQ = {5, + 0.30859270133323172e4, + 0.37343401060163018e4, + 0.11191098527047487e4, + 0.85223920643413404e2, + 0.10000000000000000e1 + }; + */ + + if (x < 0.0) { + negative = 1; + x = -x; + } + if (x < 8.0) { + xsquare = x*x; + value = x*$0DPOWER(xsquare,&j1P)/$0DPOWER(xsquare,&j1Q); + if (negative) return -value; else return value; + } + xx = x - piby34; + x8 = 8.0/x; +/* + xsquare = x8*x8; + p = $0DPOWER(xsquare,&j1pP)/$0DPOWER(xsquare,&j1pQ); + q = x8*$0DPOWER(xsquare,&j1qP)/$0DPOWER(xsquare,&j1qQ); + */ + _pandq1(x8,&p,&q); + value = sqrt(2.0/(pi*x)) * (p*cos(xx) - q*sin(xx)); + if (negative) return -value; else return value; +} /* j1 */ + +void _pandq0(x, pptr, qptr) + double x; + double *pptr; + double *qptr; +{ +double xsquare; +static struct { + int terms; + double tbl[5]; + } P0p = {5, + 0.21807736478830516e7, + 0.30343163608475270e7, + 0.11035444210405852e7, + 0.11252515255664381e6, + 0.22399036697750965e4 + }; + static struct { + int terms; + double tbl[6]; + } P0q = {6, + 0.21807736478830516e7, + 0.30367122303337213e7, + 0.11068209412295708e7, + 0.11366275712613906e6, + 0.23403140106394541e4, + 0.10000000000000000e1 + }; + static struct { + int terms; + double tbl[5]; + } Q0p = {5, + -0.17665456233082465e4, + -0.28720316121456664e4, + -0.12598828601325539e4, + -0.16263421062270593e3, + -0.44237584856933353e1 + }; + static struct { + int terms; + double tbl[6]; + } Q0q = {6, + 0.11305891989633582e6, + 0.18484510850351025e6, + 0.82274660980144657e5, + 0.11085805836751487e5, + 0.35655140058576331e3, + 0.10000000000000000e1 + }; + extern double (far *$0DPOWER)(); + + xsquare = x*x; + *pptr = $0DPOWER(xsquare,&P0p)/$0DPOWER(xsquare,&P0q); + *qptr = x*$0DPOWER(xsquare,&Q0p)/$0DPOWER(xsquare,&Q0q); + } + +void _pandq1(x, pptr, qptr) + double x; + double *pptr; + double *qptr; +{ +double xsquare; + static struct { + int terms; + double tbl[5]; + } P1p = {5, + -0.17469576694409286e7, + -0.23669439140521428e7, + -0.82850363738723775e6, + -0.79574568713505959e5, + -0.14279066288270981e4 + }; + static struct { + int terms; + double tbl[6]; + } P1q = {6, + -0.17469576694409286e7, + -0.23637451390226540e7, + -0.82423699065628189e6, + -0.78144050089391111e5, + -0.13084529833390797e4, + 0.10000000000000000e1 + }; + static struct { + int terms; + double tbl[5]; + } Q1p = {5, + 0.14465282874995209e3, + 0.17442916890924259e3, + 0.51736532818365916e2, + 0.37994453796980673e1, + 0.36363466476034711e-1 + }; + static struct { + int terms; + double tbl[5]; + } Q1q = {5, + 0.30859270133323172e4, + 0.37343401060163018e4, + 0.11191098527047487e4, + 0.85223920643413404e2, + 0.10000000000000000e1 + }; + + extern double (far *$0DPOWER)(); + + xsquare = x*x; + *pptr = $0DPOWER(xsquare,&P1p)/$0DPOWER(xsquare,&P1q); + *qptr = x*$0DPOWER(xsquare,&Q1p)/$0DPOWER(xsquare,&Q1q); + } diff --git a/Mix Power C v1/BIOS.C b/Mix Power C v1/BIOS.C new file mode 100644 index 0000000..5c6bacc --- /dev/null +++ b/Mix Power C v1/BIOS.C @@ -0,0 +1,204 @@ + +/* IBM PC BIOS Functions */ +/* Copyright (c) Mix Software 1988 */ + +cursblk() +{ + _setcurs(0, _graphic() ? 7 : 13); +} + +/* ------------------------------------------------------------ */ + +curslin() +{ + int start; + _setcurs((start = _graphic() ? 7 : 13), start); +} + +/* ------------------------------------------------------------ */ + +_graphic() /* returns 1 if graphics display, 0 if monochrome */ +{ + union REGS reg; + int display; + bios(0x11, ®); /* get display type (bits 4 and 5 of ax) */ + if ((reg.x.ax & 0x30) < 0x30) return 1; /* graphics */ + else return 0; /* monochrome */ +} + +/* ------------------------------------------------------------ */ + +curson() /* set bit 5 of start scan line to 0 : IBM PC */ +{ /* set bit 6 of start scan line to 0 : Tandy 2000 + use & 0x00BF */ + unsigned cursor, _getcurs(); + cursor = _getcurs(); + _setcurs((cursor >> 8) & 0x00DF, cursor & 0x00FF); +} + +/* ------------------------------------------------------------ */ + +cursoff() /* set bit 5 of start scan line to 1 : IBM PC */ +{ /* set bit 6 of start scan line to 1 : Tandy 2000 + use | 0x0040 */ + unsigned cursor, _getcurs(); + cursor = _getcurs(); + _setcurs((cursor >> 8) | 0x0020, cursor & 0x00FF); +} + +/* ------------------------------------------------------------ */ + +unsigned _getcurs() +{ + extern int _vapage; + union REGS reg; + reg.h.ah = 3; + reg.h.bh = _vapage; + bios(0x10, ®); + return reg.x.cx; +} + +/* ------------------------------------------------------------ */ + +_setcurs(start, stop) +int start, stop; +{ + union REGS reg; + reg.h.ah = 1; + reg.h.ch = start; + reg.h.cl = stop; + bios(0x10, ®); +} + +/* ------------------------------------------------------------ */ + +clrscrn() +{ + extern int _vattr; + clrscrn2(_vattr); +} + +/* ------------------------------------------------------------ */ + +setcolor(background, palette) +int background, palette; +{ + union REGS reg; + reg.h.ah = 11; + reg.h.bh = 0; + reg.h.bl = background; + bios(0x10, ®); + reg.h.bh = 1; + reg.h.bl = palette; + bios(0x10, ®); +} + +/* ------------------------------------------------------------ */ + +int readch() +{ /* read character at current cursor position */ + extern int _vapage; + union REGS reg; + reg.h.ah = 8; + reg.h.bh = _vapage; + bios(0x10, ®); + return reg.h.al; +} + +/* ------------------------------------------------------------ */ + +int readattr() +{ /* read attribute of character at current cursor position */ + extern int _vapage; + union REGS reg; + reg.h.ah = 8; + reg.h.bh = _vapage; + bios(0x10, ®); + return reg.h.ah; +} + +/* ------------------------------------------------------------ */ + +#ifndef V_ASM + +clrscrn2(attribute) +unsigned int attribute; +{ + union REGS reg; + extern int _vattr; + _vattr = attribute; + reg.h.ah = 6; + reg.h.al = reg.h.ch = reg.h.cl = 0; + reg.h.dh = 24; reg.h.dl = 79; + reg.h.bh = attribute; + bios(0x10, ®); + poscurs(0,0); +} + +curscol() +{ + extern int _vapage; + union REGS reg; + reg.h.ah = 3; + reg.h.bh = _vapage; + bios(0x10, ®); + return reg.h.dl; +} + +cursrow() +{ + extern int _vapage; + union REGS reg; + reg.h.ah = 3; + reg.h.bh = _vapage; + bios(0x10, ®); + return reg.h.dh; +} + +poscurs(row, col) + int row,col; +{ + union REGS reg; + extern int _vapage; + reg.h.ah = 2; + reg.h.bh = _vapage; + reg.h.dh = row; + reg.h.dl = col; + bios(0x10, ®); +} + +writechs(ch, attr, n) + int ch; /* character to write */ + int attr; /* attribute */ + int n; /* number of copies*/ +{ + union REGS reg; + extern int _vapage; + reg.h.ah = 9; + reg.h.bh = _vapage; + reg.h.bl = attr; + reg.x.cx = n; + bios(0x10, ®); +} + +getvmode() +{ + union REGS reg; + reg.h.ah = 15; + bios(0x10, ®); + return reg.h.al; +} + +setvmode(mode) +int mode; +{ + union REGS reg; + reg.h.ah = 0; + reg.h.al = mode; + bios(0x10, ®); +} + +int _vapage = 0; /* current crt page number */ +int _vattr = 7; /* default attribute for scroll functions */ +#endif + diff --git a/Mix Power C v1/BIOSFN.ASM b/Mix Power C v1/BIOSFN.ASM new file mode 100644 index 0000000..44b895f --- /dev/null +++ b/Mix Power C v1/BIOSFN.ASM @@ -0,0 +1,166 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; bioscom(cmd, byte, port) +; ------------------------------------------------------- +; int cmd; /* action to take 0..3 */ +; char byte; /* character to send */ +; int port; /* port number (0 = COM1 etc.) */ +; +; return: upper 8 bits are port status +; lower 8 bits are character or value +; ------------------------------------------------------- +; + IDT bioscom + DEF bioscom +; +bioscom PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV AH,AL + MOV CX,[BP][%PARM2] + MOV AL,CL + MOV DX,[BP][%PARM3] + INT >14 + POP BP + RETFAR + END +; +; ------------------------------------------------------- +; biosdisk(cmd, drive, head, track, sector, nsects, buffer) +; ------------------------------------------------------- +; int cmd; /* action to take 0..5 */ +; int drive; /* disk drive number 0.. */ +; int head; /* head number */ +; int track; /* physical track number */ +; int sector; /* starting sector */ +; int nsects; /* number of sectors (1..9) */ +; char *buffer; /* address of buffer */ +; +; return: status word +; ------------------------------------------------------- +; + IDT biosdisk + DEF biosdisk +; +biosdisk PUSH BP + MOV BP,SP + MOV AH,[BP][%PARM1] + MOV AL,[BP][%PARM4+4] ; # of sectors + MOV BX,[BP][%PARM4+6] ; buffer + MOV CX,DS + MOV ES,CX + MOV CH,[BP][%PARM4] ; track number + MOV CL,[BP][%PARM4+2] ; sector number + MOV DH,[BP][%PARM3] ; head number + MOV DL,[BP][%PARM2] ; drive number + INT >13 + XOR AH,AH + XCHG AL,AH + POP BP + RETFAR + END +; +; ------------------------------------------------------- +; biosequip() +; ------------------------------------------------------- +; return: word describing the equipment connected +; ------------------------------------------------------- +; + IDT biosequi + IF LONGNAME + LDEF biosequip + ENDIF + IF SHORTNAM + DEF biosequi + ENDIF +; +biosequi INT >11 + RETFAR + END +; +; ------------------------------------------------------- +; bioskey(cmd) +; ------------------------------------------------------- +; int cmd; /* action to take 0..2 */ +; return: key value or status +; ------------------------------------------------------- +; + IDT bioskey + DEF bioskey +; +bioskey MOV BX,SP + MOV AH,[BX][%PARM1-2] + INT >16 + RETFAR + END +; +; ------------------------------------------------------- +; biosmemory() +; ------------------------------------------------------- +; return: number of 1k blocks of physical memory +; ------------------------------------------------------- +; + IDT biosmemo + IF LONGNAME + LDEF biosmemory + ENDIF + IF SHORTNAM + DEF biosmemo + ENDIF +; +biosmemo INT >12 + RETFAR + END +; +; ------------------------------------------------------- +; long biosprint(cmd, byte, port) +; ------------------------------------------------------- +; int cmd; /* action to take 0..5 */ +; int byte; /* value of character */ +; int port; /* printer number */ +; ------------------------------------------------------- +; + IDT biosprin + IF LONGNAME + LDEF biosprint + ENDIF + IF SHORTNAM + DEF biosprin + ENDIF +; +biosprin PUSH BP + MOV BP,SP + MOV AH,[BP][%PARM1] + MOV AL,[BP][%PARM2] + MOV DX,[BP][%PARM3] + INT >17 + MOV AL,AH + XOR AH,AH + POP BP + RETFAR + END +; +; ------------------------------------------------------- +; long biostime(cmd, newtime) +; ------------------------------------------------------- +; int cmd; /* action to take 0..5 */ +; int newtime; /* new value of time (if cmd=1) +; return: current timer count +; ------------------------------------------------------- +; + IDT biostime + DEF biostime +; +biostime PUSH BP + MOV BP,SP + MOV AH,[BP][%PARM1] + MOV DX,[BP][%PARM2] + MOV CX,[BP][%PARM2+2] + INT >1A + MOV AX,DX + MOV DX,CX + POP BP + RETFAR + END diff --git a/Mix Power C v1/CHAIN.C b/Mix Power C v1/CHAIN.C new file mode 100644 index 0000000..d965b02 --- /dev/null +++ b/Mix Power C v1/CHAIN.C @@ -0,0 +1,304 @@ + + +/******************* Program chaining functions ********************/ +/* Copyright (c) Mix Software 1988 */ + +system(cmd) + char *cmd; +{ + extern int errno; + static char option[] = "/C"; + char cmdline[130]; + char *comspec; + int _spawn(); + int len; + comspec = getenv("COMSPEC="); + if (comspec == NULL) { errno = ENOENT; return -1; } + if ((cmd == NULL) || (*cmd == '\0')) strcpy(cmdline,"\x00\x0d"); + else { + len = strlen(cmd); + if (len > 124) {errno = E2BIG; return -1; } + strcpy(cmdline," /C "); + strcat(cmdline,cmd); + cmdline[0] = len+3; + cmdline[len+4] = '\x0d'; + } + return _spawn(comspec,cmdline,_copyenv(NULL)); +} /* system */ + +int execl(pathname, arg0) + char *pathname; + char *arg0; +{ + return _spawn1(P_OVERLAY,pathname,&arg0,NULL,0); + } + +int execle(pathname, arg0) + char *pathname; + char *arg0; +{ + char **argptr = &arg0; + while (*argptr != NULL) ++argptr; + return _spawn1(P_OVERLAY,pathname,&arg0,*++argptr,0); + } + +int execlp(pathname, arg0) + char *pathname; + char *arg0; +{ + return _spawn1(P_OVERLAY,pathname,&arg0,NULL,1); + } + +int execlpe(pathname, arg0) + char *pathname; + char *arg0; +{ + char **argptr = &arg0; + while (*argptr != NULL) ++argptr; + return _spawn1(P_OVERLAY,pathname,&arg0,*++argptr,1); + } + +int execv(pathname, argv) + char *pathname; + char **argv; +{ + return _spawn1(P_OVERLAY,pathname,argv,NULL,0); + } + +int execve(pathname, argv, envp) + char *pathname; + char *argv[]; + char *envp[]; +{ + return _spawn1(P_OVERLAY,pathname,argv,envp,0); + } + +int execvp(pathname, argv) + char *pathname; + char *argv[]; +{ + return _spawn1(P_OVERLAY,pathname,argv,NULL,1); + } + +int execvpe(pathname, argv, envp) + char *pathname; + char *argv[]; + char *envp[]; +{ + return _spawn1(P_OVERLAY,pathname,argv,envp,1); + } + +int spawnl(modeflag, pathname, arg0) + int modeflag; + char *pathname; + char *arg0; +{ + return _spawn1(modeflag,pathname,&arg0,NULL,0); + } + +int spawnle(modeflag, pathname, arg0) + int modeflag; + char *pathname; + char *arg0; +{ + char **argptr = &arg0; + while (*argptr != NULL) ++argptr; + return _spawn1(modeflag,pathname,&arg0,*++argptr,0); + } + +int spawnlp(modeflag, pathname, arg0) + int modeflag; + char *pathname; + char *arg0; +{ + return _spawn1(modeflag,pathname,&arg0,NULL,1); + } + +int spawnlpe(modeflag, pathname, arg0) + int modeflag; + char *pathname; + char *arg0; +{ + char **argptr = &arg0; + while (*argptr != NULL) ++argptr; + return _spawn1(modeflag,pathname,&arg0,*++argptr,1); + } + +int spawnv(modeflag, pathname, argv) + int modeflag; + char *pathname; + char *argv[]; +{ + return _spawn1(modeflag,pathname,argv,NULL,0); + } + +int spawnve(modeflag, pathname, argv, envp) + int modeflag; + char *pathname; + char *argv[]; + char *envp[]; +{ + return _spawn1(modeflag,pathname,argv,envp,0); + } + +int spawnvp(modeflag, pathname, argv) + int modeflag; + char *pathname; + char *argv[]; +{ + return _spawn1(modeflag,pathname,argv,NULL,1); + } + +int spawnvpe(modeflag, pathname, argv, envp) + int modeflag; + char *pathname; + char *argv[]; + char *envp[]; +{ + return _spawn1(modeflag,pathname,argv,envp,1); + } + +/* + spawn and exec driver. + */ + +int _spawn1(modeflag, pathname, argv, envp, pathflag) + int modeflag; /* P_WAIT, P_NOWAIT or P_OVERLAY */ + char *pathname; /* name of command or exe file */ + char *argv[]; /* list of arguments */ + char *envp[]; /* pointer to environment */ + int pathflag; /* search path environment string */ +{ + extern int $$ENVALT; + extern unsigned $$ENVIR; + extern char **environ; + extern int errno; + extern int (*_p_chain)(); + extern int (*_p_chenv)(); + char cmdline[128], path[128]; + char *p; + char *pathenv; + int len, handle, status; + if (modeflag == P_NOWAIT) { errno = EINVAL; return -1;} + if (envp == NULL) { /* no environment, use current program's */ + if ($$ENVALT != 0) envp = environ; + } + else if (envp == environ) { /* caller has passed current environment */ + if ($$ENVALT == 0) envp = NULL; + } + /* envp is null if the original environment will be passed */ + if (argv != NULL) { /* make command line from argument list */ + if (*argv != NULL) { + *cmdline = ' '; + p = &cmdline[1]; + *p = '\0'; + len = 1; + while (*++argv != NULL) { + len += strlen(*argv)+1; + if (len > 127) { errno = E2BIG; return -1; } + strcat(cmdline,*argv); + strcat(cmdline," "); + } + cmdline[0] = len-1; + if (len < 127) cmdline[len] = 0x0d; + } + } + /* search for the command or exe file */ + if (pathflag != 0) pathenv = getenv("PATH="); else pathenv = 0; + handle = _openfind(pathname,pathenv,".COM;.EXE",0,1,path); + if (handle == -1) { errno = ENOENT; return -1; } + /* execute task */ + if (modeflag == P_WAIT) { /* execute and wait for completion */ + _sys_ab(0x3e00,handle,&status); + if (envp == NULL) envp = $$ENVIR; else envp = _copyenv(envp); + status = _spawn(path,cmdline,envp); + if (envp != $$ENVIR) free(envp); + return(status); + } + else { /* overlay current program */ + if (_p_chain == NULL) {errno = EINVAL; return -1; } + if (envp == NULL) status = (*_p_chain)(handle,cmdline); + else { + envp = _copyenv(envp); + _sys_ab(0x3e00,handle,&status); + status = (*_p_chenv)(path,cmdline,envp); + if (envp != $$ENVIR) free(envp); + } + return status; + } + } /* _spawn1 */ + +/* Open a file by searching. Name is the basic file name, envir is + a list of possible prefixes and extlist is a list of possible + extensions. Extensions are tried only if the file does not + already have an extension. If the file is succesfully opened, + a file handle is returned, otherwise -1 is returned. + Extensions are tried first, followed by directories. + */ +int _openfind(name, envir, extlist, pathfirst, nonull, newname) + int pathfirst; /* search environment before default directory */ + int nonull; /* do not try file without extension */ + char *extlist; /* list of extensions to try (if none supplied) */ + char *envir; /* list of prefixes to search for file */ + char *name; /* base name of file */ + char *newname; /* return buffer for name found by the search */ +{ + int status; + char *p, *q; + char *extptr, *extloc, *final; + char nul = '\0'; + int tryit; + strcpy(newname,name); + if (extlist == NULL) extlist = &nul; + else { + p = name+strlen(name); + do { /* search for extension */ + if (*p == '.') break; /* found */ + if (*p == '\\') break; /* stop on directory name */ + if (*p == ':') break; /* stop on disk name */ + --p; + } while (p != name); + if (*p == '.') extlist = &nul; /* extension supplied */ + } + if (pathfirst == 0) { + if ((nonull == 0) || (extlist == &nul)) { + if (_sys_acd(0x3d00,0,newname,&status) == 0) return status; + } + final = &nul; + } + else final = ";"; /* to try default directory last */ + + if (envir == NULL) q = &nul; else q = envir; + if (pathfirst == 0) extptr = extlist; else extptr = &nul; + extloc = newname+strlen(newname); + do { /* try all combinations */ + if (*extptr != '\0') { /* try next extension */ + p = extloc; + while ((*extptr != ';') && (*extptr != '\0')) *p++ = *extptr++; + *p = '\0'; + if (*extptr == ';') ++extptr; + tryit = 1; + } + else { /* try next prefix */ + p = newname; + while ((*q != ';') && (*q != '\0')) *p++ = *q++; + if (*q == ';') ++q; + if (p != newname) if (*(p-1) != '\\') *p++ = '\\'; + *p = '\0'; + strcat(p,name); + extptr = extlist; + extloc = newname+strlen(newname); + if ((nonull == 0) || (extlist == &nul)) tryit = 1; else tryit = 0; + } + if (tryit) { /* try to open file with this path */ + if (_sys_acd(0x3d00,0,newname,&status) == 0) return status; + } + if (*q == '\0') { /* try default directory (if not tried already) */ + q = final; + final = &nul; + } + } while ((*q != '\0') || (*extptr != '\0')); + + return -1; /* not found */ +} /* _openfind */ + diff --git a/Mix Power C v1/CLOSE.C b/Mix Power C v1/CLOSE.C new file mode 100644 index 0000000..9368ebf --- /dev/null +++ b/Mix Power C v1/CLOSE.C @@ -0,0 +1,101 @@ + +/* Close files */ +/* Copyright (c) Mix Software 1988 */ + +fcloseall() { + int fd; + int count = 0; + for (fd = 5; fd < MAXFILES; fd++) { + if (_iob[fd] != NULL) { + if (close(fd) == 0) count++; + } + } + return count; +} + +/* ------------------------------------------------------------ */ + +fclose(fp) + FILE *fp; +{ + int fd; + int x; + extern int _dupcnt_; + if (fp == NULL) return EOF; + fd = fp->fd; + if (_dupcnt_ != 0) { + for (x = fd+1; x < MAXFILES; x++) { + if (_iob[x] == fp) fd = x; + } + } + return close(fd); +} + +/* ------------------------------------------------------------ */ + +close(fd) + int fd; +{ + int _fflush(), _sys_ab(), _sysabcd(); + int status = 0; + int i; + FILE *fp; + extern int (*_fileerr)(); + extern int errno; + extern int _dupcnt_; + extern FILE _STDFL1, _STDFL5; + fp = _iob[fd]; + if (fp == NULL) { + if (_sys_ab(0x3e00,fd,&status) == 0) return 0; + errno = EBADF; + return -1; + } + + if (fp->file.dirty & fdwrite) status = _fflush(fp); + if (fp->file.flags & fdctlz) { + if (fp->file.mode == O_WRONLY) { + if (status==0) { + if (_sysabcd(0x4000,fp->file.handle,1,"\032",&status)==0) + status = 0; + } + } + } + if (fp->file.device == 0) { + if (_sys_ab(0x3e00,fd,&status)==0) status = 0; + } + if (status) { + (*_fileerr)(status,fp); + return -1; + } + + _iob[fd] = NULL; + if (_dupcnt_ != 0) { + for (i = MAXFILES-1; i > 4; i--) { + if (_iob[i] == fp) { + fp = NULL; + i = 0; + --_dupcnt_; + } + } + } + if (fp->file.flag2 & fd2temp) _sys_ad(0x4100,fp->file.pathnm,&status); + if (fp != NULL) { + if ((fp > &_STDFL1) || (fp < &_STDFL5)) { + if ((fp->file.flags & fdsetbuf) == 0) free(fp->file.bufr); + free(fp->file.pathnm); + free(fp); + } + } + return 0; +} + +/* ------------------------------------------------------------ */ + +_stdclose(fp) +FILE *fp; +{ + return 0; +} + +int _dupcnt_ = 0; + diff --git a/Mix Power C v1/CONVERT.C b/Mix Power C v1/CONVERT.C new file mode 100644 index 0000000..6f1d28c --- /dev/null +++ b/Mix Power C v1/CONVERT.C @@ -0,0 +1,224 @@ + +/* Numeric conversions. */ +/* Copyright (c) Mix Software 1988 */ + +/* ------------------------------------------------------------ */ +/* convert a string to an integer */ + +atoi(s) /* decode an integer */ +char *s; /* pointer to integer string */ +{ + int sflag = 1, value = 0; + while (isspace(*s)) ++s; + if (*s == '+' || *s == '-') + if (*s++ == '-') sflag = -1; + while (*s > 47 && *s < 58) value = 10 * value + (*s++ - 48); + return value * sflag; +} + +/* ------------------------------------------------------------ */ +/* convert a string to a long integer */ + +long atol(s) /* decode a long integer */ +char *s; /* pointer to integer string */ +{ + int sflag = 1; + long value = 0, base = 10; + while (isspace(*s)) ++s; + if (*s == '+' || *s == '-') + if (*s++ == '-') sflag = -1; + while (*s > 47 && *s < 58) value = base * value + (*s++ - 48); + return value * sflag; +} + +/* ------------------------------------------------------------ */ +/* convert a string to a long integer */ + +long strtol(nptr, endptr, base) /* convert a string to a long */ +char *nptr; /* pointer to string */ +char **endptr; +int base; +{ + int sflag = 0; + long value = 0; + long strtoul(); + int c, v; + while (isspace(*nptr)) ++nptr; /* skip white space */ + if (*nptr == '+' || *nptr == '-') + if (*nptr++ == '-') sflag = -1; + value = strtoul(nptr, endptr, base); + if (sflag) return -value; else return value; +} + +/* ------------------------------------------------------------ */ +/* convert a string to an unsigned long integer */ + +long strtoul(nptr, endptr, base) /* convert a string to a long */ +char *nptr; /* pointer to string */ +char **endptr; +int base; +{ + unsigned long value = 0; + int c, v; + while (isspace(*nptr)) ++nptr; /* skip white space */ + if (*nptr == '0') { + if (toupper(c=*++nptr) == 'X') { + base = 16; + ++nptr; + } + else { + if (base == 0) { + if (c >= '1' && c <= '7') base = 8; + else base = 10; + } + } + } + else if (base == 0) base = 10; + do { + if (isalnum(c = *nptr++)) { + if (isdigit(c)) v = c - 48; else v = toupper(c) - 55; + if (v < base) value = base * value + v; else v = -1; + } + else v = -1; + } + while (v >= 0); + if (endptr) *endptr = nptr-1; + return value; +} + +/* ------------------------------------------------------------ */ +/* convert a string to a double */ + +double strtod(nptr, endptr) + char *nptr; + char **endptr; +{ + char bufr[50]; + char *p, *q; + int c; + double atof(); + p = bufr; + q = p + sizeof(bufr) - 4; + while (isspace(*nptr)) ++nptr; + if (*nptr == '+' || *nptr == '-') *p++ = *nptr++; + while (isdigit(*nptr) && (p < q)) *p++ = *nptr++; + if (*nptr == '.') { + *p++ = *nptr++; + while (isdigit(*nptr) && (p < q)) *p++ = *nptr++; + } + if ((c = toupper(*nptr)) == 'D' || c == 'E') { + *p++ = *nptr++; + if (*nptr == '+' || *nptr == '-') *p++ = *nptr++; + while (isdigit(*nptr) && (p < q)) *p++ = *nptr++; + } + *p = 0; + if (endptr != 0) *endptr = nptr; + return atof(bufr); +} + +/* ------------------------------------------------------------ */ +/* convert an integer to a string */ + +char *itoa(value, string, radix) +int value; +char *string; +int radix; +{ + char *ptr; + char *utoa(); + int flag = 0; + if (radix == 10) { + if (value < 0) { + if (value == 0x8000) return strcpy(string, "-32768"); + flag = '-'; + value = -value; + } + ptr = string; + do { + *(ptr++) = value % 10 + 48; + } while ((value /= 10) != 0); + *ptr++ = flag; + *ptr = 0; + return strrev(string); + } + else return utoa(value,string,radix); +} + +/* ------------------------------------------------------------ */ +/* convert an unsigned integer to a string */ + +utoa(value, string, radix) +unsigned value; +char *string; +int radix; +{ + char *ptr, c; + extern int _hexcaseA; + ptr = string; + do { + c = value % radix; + if (c > 9) c += _hexcaseA; else c += 48; + *(ptr++) = c; + } while ((value /= radix) != 0); + *ptr = '\0'; + return strrev(string); +} + +/* ------------------------------------------------------------ */ +/* convert a long integer to a string */ + +char *ltoa(value, string, radix) +long value; +char *string; +int radix; +{ + char *ptr; + char *ultoa(); + int flag = 0; + if (radix == 10) { + if (value < 0) { + if (value == -2147483648) return strcpy(string, "-2147483648"); + flag = '-'; + value = -value; + } + ptr = string; + do { + *(ptr++) = value % 10 + 48; + } while ((value /= 10) != 0); + *ptr++ = flag; + *ptr = 0; + return strrev(string); + } + else return ultoa(value,string,radix); +} + +/* ------------------------------------------------------------ */ +/* convert an unsigned long integer to a string */ + +ultoa(value, string, radix) +unsigned long value; +char *string; +int radix; +{ + char *ptr, c; + extern int _hexcaseA; + ptr = string; + do { + c = value % radix; + if (c > 9) c += _hexcaseA; else c += 48; + *(ptr++) = c; + } while ((value /= radix) != 0); + *ptr = '\0'; + return strrev(string); +} + +_atoi(ptr) /* decode an integer */ +char **ptr; /* pointer to addr of 1st digit */ +{ + int n = 0; + while (*(*ptr) > 47 && *(*ptr) < 58) n = 10 * n + *(*ptr)++ - 48; + return n; +} + +int _hexcaseA = 'a'-10; /* character value of the digit 10 */ + diff --git a/Mix Power C v1/DISABLE.ASM b/Mix Power C v1/DISABLE.ASM new file mode 100644 index 0000000..95c5936 --- /dev/null +++ b/Mix Power C v1/DISABLE.ASM @@ -0,0 +1,154 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; disable() - disable interrupts +; ------------------------------------------------------- +; + IDT disable + DEF disable +; +disable CLI + RETFAR + END +; +; ------------------------------------------------------- +; enable() - enable interrupts +; ------------------------------------------------------- +; + IDT enable + DEF enable +; +enable STI + RETFAR + END +; +; ------------------------------------------------------- +; geninterrupt(intr_num) +; ------------------------------------------------------- +; int intr_num - interrupt number +; ------------------------------------------------------- +; + IDT geninter + IF LONGNAME + LDEF geninterrupt + ENDIF + IF SHORTNAM + DEF geninter + ENDIF + DREF _AX + DREF _BX + DREF _CX + DREF _DX + DREF _SP + DREF _BP + DREF _DI + DREF _SI + DREF _CS + DREF _DS + DREF _ES + DREF _SS +; +geninter PUSH BP + SUB SP,INSTRSZ + MOV BP,SP + MOV SI,INSTRINT + MOV DI,BP + MOV AX,SS + MOV ES,AX + MOV CX,INSTRSZ + CLD + REP + MOVSB + MOV AX,[BP][%PARM1+INSTRSZ] + MOV [BP][%1],AL + MOV AX,CS + PUSH AX + CALL DOINT + SEGSS + MOV [_AX],AX + SEGSS + MOV [_DS],DS + MOV AX,SS + MOV DS,AX + MOV [_BX],BX + MOV [_CX],CX + MOV [_DX],DX + MOV [_SP],SP + MOV [_BP],BP + MOV [_DI],DI + MOV [_SI],SI + MOV [_CS],CS + MOV [_ES],ES + MOV [_SS],SS + ADD SP,INSTRSZ + POP BP + RETFAR +DOINT MOV AX,SS + PUSH AX + PUSH BP + MOV AX,[_AX] + MOV BX,[_BX] + MOV CX,[_CX] + MOV DX,[_DX] + MOV BP,[_BP] + MOV DI,[_DI] + MOV SI,[_SI] + MOV ES,[_ES] + CMP [_DS],-1 + JZ DOIT + MOV DS,[_DS] +DOIT RETFAR + DORG 0 +INSTRINT INT >21 +INSTRRET RETSEG + DORG 2*(($+1)/2) +INSTRSZ EQU $-INSTRINT + END +; +; global register variables for geninter +; + IDT _AX + DDEF _AX + DDEF _BX + DDEF _CX + DDEF _DX + DDEF _SP + DDEF _BP + DDEF _DI + DDEF _SI + DDEF _CS + DDEF _DS + DDEF _ES + DDEF _SS + DDEF _AL + DDEF _AH + DDEF _BL + DDEF _BH + DDEF _CL + DDEF _CH + DDEF _DL + DDEF _DH +; + DORG 0 +_AX +_AL DB 0-0 +_AH DB 0-0 +_BX +_BL DB 0-0 +_BH DB 0-0 +_CX +_CL DB 0-0 +_CH DB 0-0 +_DX +_DL DB 0-0 +_DH DB 0-0 +_SP DW 0-0 +_BP DW 0-0 +_DI DW 0-0 +_SI DW 0-0 +_CS DW 0-0 +_DS DW -1 +_ES DW 0-0 +_SS DW 0-0 + END diff --git a/Mix Power C v1/DIV.ASM b/Mix Power C v1/DIV.ASM new file mode 100644 index 0000000..6676e2d --- /dev/null +++ b/Mix Power C v1/DIV.ASM @@ -0,0 +1,35 @@ +; +; Copyright (c) Mix Software 1988 +; +; --------------------------------------- +; div - divide and return both +; quotient and reamainder +; --------------------------------------- +; typedef struct { +; int quot; /* quotient */ +; int rem; /* remainder */ +; } div_t; +; +; div_t div(int numer, int denom) +; { +; div_t s; +; s.quot = numer/denom; +; s.rem = numer%denom; +; return s; +; } +; + IDT div + DEF div +NUMER EQU PARM1+4-2 +DENOM EQU PARM2+4-2 +STRUC EQU PARM1+2-2 +div MOV BX,SP + MOV AX,[BX][%NUMER] ; numerator + CWD + IDIV [BX][%DENOM] + MOV SI,[BX][%STRUC] + MOV [SI],AX + MOV [SI][%2],DX + MOV AX,SI + RETFAR + END diff --git a/Mix Power C v1/DOS.H b/Mix Power C v1/DOS.H new file mode 100644 index 0000000..0c037ee --- /dev/null +++ b/Mix Power C v1/DOS.H @@ -0,0 +1,236 @@ +/*$no list*//*$no trace <<< dos.h >>> */ +/* Copyright (c) Mix Software 1988 */ + +#define time_t long + +extern int _doserrno; +extern unsigned char _osmajor; +extern unsigned char _osminor; +extern unsigned int _psp; +extern unsigned int _version; + +extern int _AX; +extern signed char _AH; +extern signed char _AL; +extern int _BX; +extern signed char _BH; +extern signed char _BL; +extern int _CX; +extern signed char _CH; +extern signed char _CL; +extern int _DX; +extern signed char _DH; +extern signed char _DL; +extern int _SI; +extern int _DI; +extern int _BP; +extern int _CS; +extern int _DS; +extern int _ES; + +#define FP_SEG(farptr) (*((unsigned *)&(farptr) + 1)) +#define FP_OFF(farptr) (*((unsigned *)&(farptr))) +#define MK_FP(seg,off) ((char far *)(((long)(seg) << 16) | (off))) + +#define FA_NORMAL 0x0000 +#define FA_RDONLY 0x0001 +#define FA_HIDDEN 0x0002 +#define FA_SYSTEM 0x0004 +#define FA_LABEL 0x0008 +#define FA_DIREC 0x0010 +#define FA_ARCH 0x0020 + + +#if !defined(WORDREGS) +struct WORDREGS { + unsigned int ax; + unsigned int bx; + unsigned int cx; + unsigned int dx; + unsigned int si; + unsigned int di; + unsigned int cflag; +}; +#endif + +#if !defined(BYTEREGS) +struct BYTEREGS { + unsigned char al, ah; + unsigned char bl, bh; + unsigned char cl, ch; + unsigned char dl, dh; +}; +#endif + +#if !defined(REGS) +union REGS { + struct WORDREGS x; + struct BYTEREGS h; + struct WORDREGS word; + struct BYTEREGS byte; +}; +#endif + +#if !defined(SREGS) +struct SREGS { + unsigned int es; + unsigned int cs; + unsigned int ss; + unsigned int ds; +}; +#endif + +#if !defined(REGPACK) +struct REGPACK { + unsigned r_ax, r_bx, r_cx, r_dx; + unsigned r_bp, r_si, r_di; + unsigned r_ds, r_es, r_flags; +}; +#endif + +#if !defined(DOSERROR) +struct DOSERROR { + int exterror; + char class; + char action; + char locus; +}; +#endif + +#if !defined(date) +struct date { + int da_year; + char da_day; + char da_mon; +}; +#endif + +#if !defined(time) +struct time { + unsigned char ti_min; + unsigned char ti_hour; + unsigned char ti_hund; + unsigned char ti_sec; +}; +#endif + +#if !defined(dfree) +struct dfree { + unsigned df_avail; /* available clusters */ + unsigned df_total; /* total clusters */ + unsigned df_bsec; /* bytes per sector */ + unsigned df_sclus; /* sectors per cluster */ +}; +#endif + +#if !defined(fatinfo) +struct fatinfo { + char fi_sclus; /* Sectors per cluster */ + char fi_fatid; /* identification byte */ + int fi_nclus; /* number of clusters */ + int fi_bysec; /* bytes per sector */ +}; +#endif + +#if !defined(ftime) +struct ftime { + unsigned ft_tsec : 5; /* two seconds */ + unsigned ft_min : 6; /* minutes */ + unsigned ft_hour : 5; /* hours */ + unsigned ft_day : 5; /* day of month */ + unsigned ft_month: 4; /* month */ + unsigned ft_year : 7; /* year - 1980 */ +}; +#endif + +#if !defined(fcb) +struct fcb { + char fcb_drive; /* drive number */ + char fcb_name[8]; /* file name */ + char fcb_ext[3]; /* file extension */ + int fcb_curblk; /* block number */ + int fcb_recsize; /* logical record size */ + long fcb_filsize; /* file size */ + int fcb_date; /* Date file was last written */ + char fcb_resv[10]; /* Reserved for DOS */ + char fcb_currec; /* record in block */ + long fcb_random; /* random record number */ +}; +#endif + +#if !defined(country) +struct country { + int co_date; /* date format */ + char co_curr[5]; /* currency symbol string */ + char co_thsep[2]; /* thousands separator character */ + char co_desep[2]; /* decimal separator character */ + char co_dtsep[2]; /* date separator character */ + char co_tmsep[2]; /* time separator character */ + char co_currstyle; /* currency format */ + char co_digits; /* number digits after decimal */ + char co_timestyle; /* time format */ + int (far *co_case)(); /* case map call address */ + char co_dasep; /* data-list separator */ + char co_fill[11]; /* reserved */ +} +#endif + +int absread(int drive, int nsects, int sector, void *buffer); +int abswrite(int drive, int nsects, int sector, void *buffer); +int allocmem(unsigned size, unsigned *seg); +int asm(void *codeptr, void *dataptr); +int bdosptr(int fn, void *address, unsigned al); +struct country *country(int code, struct country *info); +void ctrlbrk(int (*handler)(void)); +void disable(void); +int dosexterr(struct DOSERROR *errinfo); +time_t dostounix(struct date dosdate, struct time dostime); +void enable(void); +int freemem(unsigned seg); +void geninterrupt(int intno); +int getcbrk(void); +int getcseg(void); +void getdate(struct date *datebuf); +void getdfree(int drive, struct dfree *diskdata); +int getdseg(void); +char far *getdta(void); +void getfat(int drive, struct fatinfo *fat); +void getfatd(struct fatinfo *fat); +unsigned getpsp(void); +void gettime(struct time *timebuf); +void interrupt (far *getvect(int intno))(); +int getverify(void); +void harderr(int (*handler)(int error, int ax, int bp, int si)); +void hardresume(int cmd); +void hardretn(int error); +int inp(unsigned port); +int inport(int port); +int inportb(int port); +int int86(int interrupt, union REGS *inregs, union REGS *outregs); +int int86x(int interrupt, union REGS *inregs, union REGS *outregs, + struct SREGS *segregs); +int intdos(union REGS *inregs, union REGS *outregs); +int intdosx(union REGS *inregs, union REGS *outregs, + struct SREGS *segregs); +void intr(int interrupt, struct REGPACK *regs); +void keep(int status, int size); +int outp(unsigned port, int c); +void outport(unsigned port, int word); +void outportb(int port, char c); +char *parsfnm(char *filename, struct fcb *buffer, int option); +int peek(unsigned segment, unsigned offset); +int peekb(unsigned segment, unsigned offset); +void poke(unsigned segment, unsigned offset, int value); +void pokeb(unsigned segment, unsigned offset, char value); +void segread(struct SREGS *sregs); +int setblock(unsigned seg, unsigned size); +int setcbrk(int flag); +void setdate(struct date *datebuf); +void setdta(char far *address); +void settime(struct time *timebuf); +void setvect(int intno, void interrupt (far *handler)()); +void setverify(int flag); +void sleep(unsigned seconds); +void unixtodos(time_t timer, struct date *dosdate, struct time *dostime); + +/*$list*//*$trace <<< dos.h >>> */ diff --git a/Mix Power C v1/DOSETC.C b/Mix Power C v1/DOSETC.C new file mode 100644 index 0000000..f41f2ea --- /dev/null +++ b/Mix Power C v1/DOSETC.C @@ -0,0 +1,237 @@ +/* Copyright (c) Mix Software 1988 */ + +int _chmod(filename, func, attrib) + char *filename; + int func; + int attrib; +{ + extern int errno, _doserrno; + int status; + if (_sysacdc(0x4300+(func & 0x0001),attrib,filename,&status) == 0) + return status; + errno = _doserrno; + return -1; + } + +int getcbrk() +{ + int dxval; + _sys_add(0x3300,0,&dxval); + return dxval & 0x00ff; + } + +int setcbrk(value) + int value; +{ + int dxval; + _sys_add(0x3301,value,&dxval); + return value; + } + +getcurdir(drive, direc) /* get default directory */ + int drive; /* drive (0=default, 1=a, 2=b, etc) */ + char *direc; /* buffer for result */ +{ + int status; + if (_sysdxsi(0x4700,drive,direc,&status) == 0) return 0; + return -1; + } + +void getdfree(drive, dfreep) + int drive; + struct dfree *dfreep; +{ + union REGS r; + r.h.ah = 0x36; + r.x.dx = drive; + intdos(&r,&r); + dfreep->df_avail = r.x.bx; + dfreep->df_total = r.x.dx; + dfreep->df_bsec = r.x.cx; + dfreep->df_sclus = r.x.ax; + } + +int getdisk() +{ + return _sys_al(0x1900); + } + +int setdisk(drive) + int drive; +{ + int result; + _sys_ad(0x0e00,drive,&result); + return result & 0x00ff; + } + +int getftime(handle, ftimep) + int handle; + struct ftime *ftimep; +{ + extern int errno; + struct { + int time; + int date; + } *cvt; + union REGS r; + r.x.ax = 0x5700; + r.x.bx = handle; + intdos(&r,&r); + if (r.x.cflag != 0) { + errno = r.x.ax; + return -1; + } + cvt = ftimep; + cvt->time = r.x.cx; + cvt->date = r.x.dx; + return 0; + } + +int setftime(handle, ftimep) + int handle; + struct ftime *ftimep; +{ + extern int errno; + struct { + int time; + int date; + } *cvt; + union REGS r; + r.x.ax = 0x5701; + r.x.bx = handle; + cvt = ftimep; + r.x.cx = cvt->time; + r.x.dx = cvt->date; + intdos(&r,&r); + if (r.x.cflag != 0) { + errno = r.x.ax; + return -1; + } + return 0; + } + +unsigned getpsp() +{ + union REGS r; + r.x.ax = 0x6200; + intdos(&r,&r); + return r.x.bx; + } + +int getverify() +{ + return _sys_al(0x5400); + } + +void setverify(value) + int value; +{ + _sys_ad(0x2e00+(value & 0x0001),0); + } + +int ioctl(handle,cmd,argdx,argcx) + int handle; + int cmd; + int *argdx; + int argcx; +{ + extern int errno, _doserrno; + union REGS r; + r.h.ah = 0x44; + r.h.al = cmd; + r.x.bx = handle; + r.x.cx = argcx; + r.x.dx = *argdx; + if (cmd == 1) r.h.dh = 0; + intdos(&r,&r); + if (r.x.cflag) { errno = _doserrno; return -1; } + if (cmd < 2) return r.x.dx; + return r.x.ax; + } + +void keep(status,size) /* terminate and stay resident */ + int status; /* status code to return to caller */ + int size; /* total size of memory to retain (in paragraphs) */ +{ + int st; + _sys_ad(0x3100+(status & 0x00ff),size,&st); + } + +struct fcb { + char fcb_drive; /* drive number */ + char fcb_name[8]; /* file name */ + char fcb_ext[3]; /* file extension */ + int fcb_curblk; /* block number */ + int fcb_recsize; /* logical record size */ + long fcb_filsize; /* file size */ + int fcb_date; /* Date file was last written */ + char fcb_resv[10]; /* Reserved for DOS */ + char fcb_currec; /* record in block */ + long fcb_random; /* random record number */ + }; +char *parsfnm(cmdline, fcbptr, option) + char *cmdline; + struct fcb *fcbptr; + int option; +{ + union REGS r; + struct SREGS s; + void segread(); + r.h.ah = 0x29; + r.h.al = option; + r.x.si = cmdline; + r.x.di = fcbptr; + segread(&s); + s.es = s.ds; + intdosx(&r,&r,&s); + if (r.h.al != 0) return 0; + return r.x.si; + } + +int randbrd(fcbptr, reccnt) + struct fcb *fcbptr; + int reccnt; +{ /* random block read */ + int status; + _sys_acd(0x2700,reccnt,fcbptr,&status); + return status&0xff; + } + +int randbwr(fcbptr, reccnt) + struct fcb *fcbptr; + int reccnt; +{ /* random block read */ + int status; + _sys_acd(0x2800,reccnt,fcbptr,&status); + return status&0xff; + } + +struct country { + int co_date; /* date format 0=mdy, 1=dmy, 2=ymd */ + char co_curr[5]; /* currency symbol */ + char co_thsep[2]; /* thousands separator character */ + char co_desep[2]; /* decimal separator character */ + char co_dtsep[2]; /* date separator character */ + char co_tmsep[2]; /* time separator character */ + char co_curstyle; /* currency format */ + char co_digits; /* number of significant digits in currency */ + char co_timestyle; /* time format, 0=12 hour, 1=24 hour clock */ + int (far *co_case)(); /* case conversion function */ + char co_fill[10]; /* fill to 34 bytes */ + } + +struct country *country(countrycode, countryp) + int countrycode; + struct country *countryp; +{ + int opcode = 0x3800; + int bx = 0; + if (countrycode > 254) { + opcode = 0x38ff; + bx = countrycode; + } + else opcode |= countrycode; + _sysabcd(opcode,bx,0,countryp,&bx); + return countryp; + } + diff --git a/Mix Power C v1/DSTRING.C b/Mix Power C v1/DSTRING.C new file mode 100644 index 0000000..5db5900 --- /dev/null +++ b/Mix Power C v1/DSTRING.C @@ -0,0 +1,27 @@ +/* Dynamic string conversion */ +/* Copyright (c) Mix Software 1988 */ + +STRING *stods(s) /* convert string to dynamic string */ +char *s; /* s is a normal C string */ +{ + int length; + STRING *ptr; + STRING *calloc(); + int strlen(); /* get length of string */ + length = strlen(s); + ptr = malloc(sizeof(int) + length); + if (ptr != NULL) { + ptr->length = length; + movmem(s, ptr->string, length); + } + return ptr; +} + +dstos(ptr,s) /* convert dynamic string into normal C string */ +STRING *ptr; /* pointer to dynamic string */ +char *s; /* normal string */ +{ + movmem(ptr->string, s, ptr->length); + *(s + ptr->length) = '\0'; +} + diff --git a/Mix Power C v1/DTAFAT.ASM b/Mix Power C v1/DTAFAT.ASM new file mode 100644 index 0000000..91bf542 --- /dev/null +++ b/Mix Power C v1/DTAFAT.ASM @@ -0,0 +1,89 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; getdta - return disk transfer address +; char far *getdta() +; ------------------------------------------------------- +; + IDT getdta + DEF getdta +; +getdta MOV AH,>2F + INT >21 + MOV DX,ES + MOV AX,BX + RETSEG + END +; +; ------------------------------------------------------- +; setdta - return disk transfer address +; char far *getdta() +; ------------------------------------------------------- +; + IDT setdta + DEF setdta +; +setdta PUSH BP + MOV BP,SP + PUSH DS + MOV DX,[BP][%PARM1] + MOV DS,[BP][%PARM2] + MOV AH,>1A + INT >21 + POP AX + MOV DS,AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; getfat - return file allocation table information +; void getfat(int drive, struct fatinfo *fatblkp); +; ------------------------------------------------------- +; + IDT getfat + DEF getfat +; +getfat PUSH BP + MOV BP,SP + PUSH DS + MOV DX,[BP][%PARM1] + MOV AH,>1C + INT >21 + MOV AH,[BX] + POP BX + MOV DS,BX + MOV BX,[BP][%PARM2] + MOV [BX],AL + MOV [BX][%1],AH + MOV [BX][%2],DX + MOV [BX][%4],CX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; getfatd - return file allocation table information +; void getfat(struct fatinfo *fatblkp); +; ------------------------------------------------------- +; + IDT getfatd + DEF getfatd +; +getfatd PUSH BP + MOV BP,SP + PUSH DS + MOV AH,>1B + INT >21 + MOV AH,[BX] + POP BX + MOV DS,BX + MOV BX,[BP][%PARM1] + MOV [BX],AL + MOV [BX][%1],AH + MOV [BX][%2],DX + MOV [BX][%4],CX + POP BP + RETSEG + END diff --git a/Mix Power C v1/DUP.C b/Mix Power C v1/DUP.C new file mode 100644 index 0000000..6eb687c --- /dev/null +++ b/Mix Power C v1/DUP.C @@ -0,0 +1,51 @@ +/* Duplicate file handle */ +/* Copyright (c) Mix Software 1988 */ + +int dup(fd) + int fd; +{ /* duplicate a file descriptor - both descriptors use the + same file pointer. */ + extern int errno, _doserrno; + extern int _dupcnt_; + int handle; + if (fd < 0 || fd > MAXFILES || _iob[fd] == NULL) { + errno = EBADF; + return -1; + } + if (_sys_ab(0x4500,_iob[fd]->file.handle,&handle) != 0) { + errno = _doserrno; + return -1; + } + if (_iob[handle] != NULL) { + errno = EMFILE; + return -1; + } + _iob[handle] = _iob[fd]; + _dupcnt_++; + return handle; +} /* dup */ + +int dup2(fd1, fd2) + int fd1, fd2; +{ /* duplicate a file descriptor - both descriptors use the + same file pointer. */ + extern int errno, _doserrno; + extern int _dupcnt_; + int handle; + if (fd1 < 0 || fd1 > MAXFILES || _iob[fd1] == NULL || + fd2 < 0 || fd2 > MAXFILES) { + errno = EBADF; + return -1; + } + if (_iob[fd2] != NULL) { + if (close(fd2) != 0) { errno = EBADF; return -1; } + } + if (_sysabcd(0x4600,fd1,fd2,0,&handle) != 0) { + errno = _doserrno; + return -1; + } + _iob[fd2] = _iob[fd1]; + _dupcnt_++; + return 0; +} /* dup2 */ + diff --git a/Mix Power C v1/DYSTRING.C b/Mix Power C v1/DYSTRING.C new file mode 100644 index 0000000..bc3be8a --- /dev/null +++ b/Mix Power C v1/DYSTRING.C @@ -0,0 +1,328 @@ +#define NULL 0 +#define st_alloc(size) malloc((size)+2) + +#if !defined(STRING) +typedef struct { + int length; + char string[80]; +} STRING; +#endif + +enum COMPVALUE {LESS, EQUAL, GREATER}; + +STRING *bldstr(s,len) + char *s; + int len; +{ + STRING *ss; + ss = st_alloc(len); + if (ss != NULL) { + ss->length = len; + memcpy(ss->string,s,len); + } + return ss; + } + +void getstr(str, arr, len) + STRING *str; + char *arr; + int len; +{ + int size; + if (str == NULL) memset(arr,' ',len); + else { + if (str->length > len) size = len; else size = str->length; + memcpy(arr,str->string,size); + if (size < len) memset(&arr[size],' ',len-size); + } + } + +int len(str) + STRING *str; +{ + return str->length; + } + +STRING *left$(str, position) + STRING *str; + int position; +{ + int size; + STRING *s; + if ((str == NULL) || (position < 0)) size = 0; + else { + if (position < str->length) size = position; + else size = str->length; + } + s = st_alloc(size); + if (s != NULL) { + s->length = size; + memcpy(s->string,str->string,size); + } + return s; + } + +STRING *right$(str, position) + STRING *str; + int position; +{ + int size; + STRING *s; + if (str == NULL) size = 0; + else { + if (position <= 0 || position > str->length) size = 0; + else size = str->length-position+1; + } + s = st_alloc(size); + if (s != NULL) { + s->length = size; + memcpy(s->string,&str->string[position-1],size); + } + return s; + } + +STRING *mid$(str, position, length) + STRING *str; + int position; + int length; +{ + int size; + STRING *s; + if (str == NULL) size = 0; + else { + if (position <= 0) size = str->length; + else if (position > str->length) size = 0; + else size = str->length - position + 1; + } + if (length < size) size = length; + s = st_alloc(size); + if (s != NULL) { + s->length = size; + memcpy(s->string,&str->string[position-1],size); + } + return s; + } + +STRING *str$(length, ch) + int length; + int ch; +{ + STRING *s; + s = st_alloc(length); + if (s != NULL) { + s->length = length; + memset(s->string,ch,length); + } + return s; + } + +char character(s, position) + STRING *s; + int position; +{ + if (s == NULL) return '\r'; + if ((s->length <= 0) || (position <= 0) || (position > s->length)) + return '\r'; + return s->string[position-1]; + } + +enum COMPVALUE cmpstr(s1, s2) + STRING *s1; + STRING *s2; +{ + int len; + int cmp; + if (s1 == s2) return EQUAL; + if (s1 == NULL) return LESS; + if (s2 == NULL) return GREATER; + len = s1->length; + if (s2->length < len) len = s2->length; + cmp = memcmp(s1->string,s2->string,len); + if (cmp < 0) return LESS; + if (cmp > 0) return GREATER; + if (s1->length > s2->length) return GREATER; + if (s1->length < s2->length) return LESS; + return EQUAL; + } + +STRING *conc(s1,s2) + STRING *s1; + STRING *s2; +{ + STRING *s; + int size1, size2; + if (s1 == NULL) size1 = 0; else size1 = s1->length; + if (s2 == NULL) size2 = 0; else size2 = s2->length; + s = st_alloc(size1+size2); + if (s != NULL) { + s->length = size1+size2; + if (size1) memcpy(s->string,s1->string,size1); + if (size2) memcpy(&s->string[size1],s2->string,size2); + } + return s; + } + +STRING *insert(substring, s, position) + STRING *substring; + STRING *s; + int position; +{ + STRING *st; + int size1, size2, pos; + if (s == NULL) size1 = 0; else size1 = s->length; + if (substring == NULL) size2 = 0; else size2 = substring->length; + pos = position; + if (pos <= 0) pos = 1; + if (pos > size1) pos = size1+1; + st = st_alloc(size1+size2); + if (st != NULL) { + st->length = size1+size2; + memcpy(st->string,s->string,pos-1); + memcpy(&st->string[pos-1],substring->string,size2); + memcpy(&st->string[pos-1+size2],&s->string[pos-1],size1+1-pos); + } + return st; + } + +STRING *delete(str, position, length) + STRING *str; + int position; + int length; + +{ + STRING *st; + int size; + int pos = position; + if (pos <= 0) { + length = length-pos-1; + pos = 1; + } + if (length < 0) length = 0; + if (str == NULL) size = 0; + else { + if (pos > str->length) size = str->length; + else if (pos+length > str->length) size = pos-1; + else size = str->length-length; + } + st = st_alloc(size); + if (st != NULL) { + st->length = size; + if (pos) memcpy(st->string,str->string,pos-1); + if (size+1-pos) + memcpy(&st->string[pos-1],&str->string[length+pos-1],size+1-pos); + } + return st; + } + +STRING *replace(oldstring, newstring, s) + STRING *oldstring; + STRING *newstring; + STRING *s; +{ + STRING *st; + int loc, size; + int oldsz, newsz; + loc = find(oldstring,s); + if (loc == 0) return cpystr(s); + oldsz = oldstring->length; + newsz = newstring->length; + size = s->length+newsz-oldsz; + st = st_alloc(size); + if (st != NULL) { + st->length = size; + memcpy(st->string,s->string,loc-1); + memcpy(&st->string[loc-1],newstring->string,newsz); + memcpy(&st->string[loc-1+newsz],&s->string[loc-1+oldsz],size-newsz-loc+1); + } + } + +int find(substring, s) + STRING *substring; + STRING *s; +{ + int limit, at, size; + if (s == NULL) return 0; + if (substring == NULL) return (s->length > 0) ? 1 : 0; + if (s->length == 0) return 0; + if (substring->length == 0) return 1; + limit = s->length - substring->length; + at = 0; + size = substring->length; + while (at <= limit) { + if (memcmp(&s->string[at],substring->string,size) == 0) + return at+1; + ++at; + } + return 0; + } + +STRING *cpystr(str) + STRING *str; +{ + STRING *s; + int size; + if (str == NULL) size = 0; else size = str->length; + s = st_alloc(size); + if (s != NULL) { + s->length = size; + memcpy(s->string,str->string,size); + } + return s; + } + +int decodei(str) + STRING *str; +{ + int sflag = 1, value = 0; + int len; + char c, *p; + if (str == NULL) return 0; + len = str->length; + p = str->string; + while (isspace(*p) && len != 0) ++p, --len; + if (len == 0) return 0; + if (*p == '+' || *p == '-') { + if (*p == '-') sflag = -1; + ++p; + --len; + } + while (len--) { + if (*p > 47 && *p < 58) value = 10*value+(*p++ - 48); + else len = 0; + } + return value * sflag; +} + +STRING *encodei(value) + int value; +{ + STRING *st; + char *p; + char sign = ' '; + int i; + st = st_alloc(6); + if (st == NULL) return NULL; + st->length = 6; + if (value < 0) { + if (value == -32768) { + memcpy(st->string,"-32768",6); + return st; + } + sign = '-'; + value = -value; + } + p = &st->string[5]; + *p = (value % 10) + 48; + value /= 10; + for (i = 0; i < 5; ++i) { + if (value == 0) { + *--p = sign; + sign = ' '; + } + else { + *--p = (value % 10) + 48; + value /= 10; + } + } + return st; + } diff --git a/Mix Power C v1/E.C b/Mix Power C v1/E.C new file mode 100644 index 0000000..3c6a84d --- /dev/null +++ b/Mix Power C v1/E.C @@ -0,0 +1,30 @@ +#include + +#define DIGITS_TO_FIND 200 /*9009*/ + +int main() { + + int N = DIGITS_TO_FIND; + int x = 0; + int a[ DIGITS_TO_FIND ]; + int n; + + for (n = N - 1; n > 0; --n) { + a[n] = 1; + } + + a[1] = 2, a[0] = 0; + while (N > 9) { + n = N--; + while (--n) { + a[n] = x % n; + + x = 10 * a[n-1] + x/n; + } + printf("%d", x); + } + + printf( "\ndone\n" ); + + return 0; +} diff --git a/Mix Power C v1/ENVIR.ASM b/Mix Power C v1/ENVIR.ASM new file mode 100644 index 0000000..d1a93b7 --- /dev/null +++ b/Mix Power C v1/ENVIR.ASM @@ -0,0 +1,147 @@ +; +; Copyright (c) Mix Software 1988 +; + IF 0 +; +; getenv - return a pointer to an entry in the environment +; +; char *getenv(varname) +; +; varname is the name of the variable (eg "PATH=") +; + IDT GETENV + DEF GETENV + DEF getenv + DREF environ + FREF _moveenv +; +getenv EQU $ +GETENV PUSH BP + MOV BP,SP + CMP [environ],0 + JNZ INITDONE + CALLFAR _moveenv + JZ NOFIND +INITDONE MOV BX,environ + MOV CX,-1 + MOV AX,DS + MOV ES,AX + CLD +SRCH MOV DI,[BX] + ADD BX,%2 + TEST DI,DI ; End of table? + JZ NOFIND + MOV SI,[BP][%PARM1] + MOV CX,>7FFF + REPZ ; Compare values + CMPSB + TEST %[SI][%-1],%>FF ; Equal to end of string mark? + JNZ SRCH + DEC DI + MOV AX,DI + POP BP + RETSEG +NOFIND XOR AX,AX + POP BP + RETSEG + END +; + ENDIF +; +; +; _moveenv - copy environment to the data segment +; $$ENVIR has the segment pointer to the environment +; environ is created to hold an array of pointers to the +; environment strings. +; + IDT _moveenv + DEF _moveenv + DREF environ + DREF $$ENVIR + DREF $$ENVPX + FREF malloc +PEXTRA EQU 4 ; Number of extra pointer slots +; +_moveenv XOR DX,DX ; Counter for number of strings + MOV ES,[$$ENVIR] + XOR DI,DI + MOV AL,%0 + MOV CX,-1 + CLD +FINDLEN INC DX ; Count this string + SEGES + CMP %[DI],%0 ; end of table? + JZ ENDENV + REPNZ + SCASB + JMPS FINDLEN +ENDENV NOT CX ; CX is size of the environment + INC CX ; Make size even + AND CX,>FFFE + PUSH DX ; Save number of pointers + PUSH CX + CALLFAR malloc + POP CX + POP DX + TEST AX,AX + JZ NOSPACE + MOV DI,AX + PUSH DI + MOV AX,DS + MOV ES,AX + MOV DS,[$$ENVIR] + SHR CX,1 + XOR SI,SI + REP ; Copy environment to heap + MOVSW + MOV AX,ES + MOV DS,AX + MOV CX,DX + ADD CX,CX ; Memory required for array of pointers + ADD CX,PEXTRA*2 ; Space for extra pointers + PUSH DX + PUSH CX + CALLFAR malloc + POP CX + POP DX + POP DI ; Address of environment block + TEST AX,AX + JZ NOSPACE + MOV BX,AX ; Address of pointer array + MOV [environ],AX + MOV AX,DS + MOV ES,AX + MOV CX,-1 + MOV AL,%0 +COPYPTR DEC DX + JZ DONE + MOV [BX],DI + ADD BX,%2 + REPNZ + SCASB + JMPS COPYPTR +DONE MOV CX,PEXTRA+1 +FILL MOV [BX],0 + ADD BX,%2 + LOOP FILL + MOV [$$ENVPX],PEXTRA + MOV AX,[environ] + RETSEG +NOSPACE XOR AX,AX + RETSEG + END +; +; char *(*environ)[]; +; int $$ENVPX; +; int $$ENVALT = 0; +; + IDT environ + DDEF environ + DDEF $$ENVPX + DDEF $$ENVALT + DORG 0 +environ dw 0 +$$ENVPX dw 0 +$$ENVALT dw 0 + END +; diff --git a/Mix Power C v1/ENVIR.C b/Mix Power C v1/ENVIR.C new file mode 100644 index 0000000..11cade9 --- /dev/null +++ b/Mix Power C v1/ENVIR.C @@ -0,0 +1,130 @@ + +/* Environment functions */ +/* Copyright (c) Mix Software 1988 */ + +char *getenvp(varname) /* get a copy of an environment variable */ + char *varname; +{ + char *getenv(); + char *strsave(); + char *s; + s = getenv(varname); + if (s == NULL) return NULL; + return strsave(s); +} /* getenvp */ + +/* ------------------------------------------------------------ */ + +char *getenv(varname) + char *varname; +{ + extern char *(*environ)[]; + char *_moveenv(); + int strlen(), memcmp(); + char **p; + int len; + if (environ == NULL) { + if (_moveenv() == NULL) return NULL; + } + len = strlen(varname); + if (*(varname+len-1) == '=') len--; + p = *environ; + while (*p != 0) { + if (memcmp(*p,varname,len) == 0) { + if (*((*p)+len) == '=') return (*p+len+1); + } + ++p; + } + return NULL; +} /* getenv */ + +/* ------------------------------------------------------------ */ + +int *putenv(envstring) + char *envstring; +{ + extern char **environ; + extern int $$ENVPX, $$ENVALT; + char *_moveenv(), *strchr(), *malloc(); + int strlen(), memcmp(); + char **p, **q; + char *sp; + int len; + if (environ == NULL) { + if (_moveenv() == NULL) return NULL; + } + if ((sp = strchr(envstring,'=')) == NULL) return -1; + sp++; /* pass the '=' */ + $$ENVALT = 1; + len = sp - envstring; + p = environ; + while (*p != 0) { + if (memcmp(*p,envstring,len) == 0) break; + ++p; + } + if (*p != 0) { /* replace existing string */ + if (len == strlen(envstring)) { /* value is null, delete from table */ + q = p+1; + while (*p != NULL) *p++ = *q++; + ++$$ENVPX; + } + else *p = envstring; + return 0; + } + if ($$ENVPX == 0) { /* no slot available in table */ + len = (p - environ); + q = malloc(sizeof(char *)*(len + 5)); + if (q == NULL) return -1; + memcpy(q,environ,sizeof(char *)*len); + memset((q + len),0,5*sizeof(char *)); + free(environ); + environ = q; + $$ENVPX = 4; + p = q+len; + } + *p = envstring; + --$$ENVPX; + return 0; +} /* putenv */ + +/* ------------------------------------------------------------ */ + +unsigned _copyenv(envp) + char **envp; +{ /* copy environment into a single block of memory on a paragraph + boundary. Returns a segment pointer to the block. If the + environment has not been altered, the environment pointer from + the parent is returned. + */ + extern char *(*environ)[]; + extern unsigned $$ENVIR; + extern int $$ENVALT; + unsigned getdseg(); + char **p, *q, **ev; + unsigned paragraph; + int len = 0; + if (envp == NULL) { + if (environ == NULL) return $$ENVIR; + if ($$ENVALT == 0) return $$ENVIR; + ev = environ; + } + else ev = envp; + p = ev; + while (*p != NULL) { + len += strlen(*p)+1; + ++p; + } + q = malloc(len+16); + if (q == NULL) return NULL; + q = ((unsigned)q + 15) & 0xfff0; /* paragraph boundary */ + paragraph = ((unsigned)q >> 4) + getdseg(); + p = ev; + while (*p != NULL) { + strcpy(q,*p); + q += strlen(*p)+1; + ++p; + } + return paragraph; +} /* _copyenv */ + + diff --git a/Mix Power C v1/ERROR.C b/Mix Power C v1/ERROR.C new file mode 100644 index 0000000..4a7ac3f --- /dev/null +++ b/Mix Power C v1/ERROR.C @@ -0,0 +1,53 @@ +/* Low level error processing functions. */ +/* Copyright (c) Mix Software 1988 */ + +extern int _ferror0(); +int (*_fileerr)() = _ferror0; /* set to _ferror1 for full error msg */ + +int _ferror0(syserror,fp) /* error detected during file operation */ + int syserror; /* set error codes and terminate or */ + FILE *fp; /* continue (depending on $$IOTERM) */ +{ + extern char $$IOTERM; + extern FILE *$$LIOERR; + extern int errno; + void $_FATAL(); + if (syserror) { + fp->file.error = syserror; + errno = FILEERR; + $$LIOERR = fp; + if ($$IOTERM) $_FATAL(errno); + } + return syserror; + } + +int _ferror1(syserror,fp) /* error detected during file operation */ + int syserror; /* set error codes and terminate with */ + FILE *fp; /* full message. */ +{ + extern int errno; + extern char $$IOTERM; + extern FILE *$$LIOERR; + extern char *sys_errlist[]; + extern int sys_nerr; + void _exit(); + if (syserror) { + fp->file.error = syserror; + errno = FILEERR; + $$LIOERR = fp; + if ($$IOTERM) { + _errmsg("File IO error\r\l"); + if (syserror <= sys_nerr) _errmsg(sys_errlist[syserror]); + _exit(errno); + } + } + return syserror; + } + +_errmsg(s) + char *s; +{ + int ss; + _sysabcd(0x4000,2,strlen(s),s,&ss); + } + diff --git a/Mix Power C v1/ERRORS.C b/Mix Power C v1/ERRORS.C new file mode 100644 index 0000000..3ee8f19 --- /dev/null +++ b/Mix Power C v1/ERRORS.C @@ -0,0 +1,4 @@ +/* Copyright (c) Mix Software 1988 */ + +#include "std_lib.h" +#include "error.c" diff --git a/Mix Power C v1/ETC.C b/Mix Power C v1/ETC.C new file mode 100644 index 0000000..9d47dbb --- /dev/null +++ b/Mix Power C v1/ETC.C @@ -0,0 +1,128 @@ +/* Copyright (c) Mix Software 1988 */ + +void ctrlbrk(fptr) + int (*fptr)(); +{ + _signal_(SIGINT,fptr); + } + +void fnmerge(path, drive, dir, name, ext) + char *path; /* buffer to constuct file name */ + char *drive; /* disk drive name */ + char *dir; /* directory name */ + char *name; /* file name */ + char *ext; /* file extension */ +{ + if (drive != NULL) strcpy(path,drive); + else *path = '\0'; + if (dir != NULL) strcat(path,dir); + if (name != NULL) strcat(path,name); + if (ext != NULL) strcat(path,ext); + } + +/* flags for fnsplit */ +#define WILDCARDS 0x0001 +#define EXTENSION 0x0002 +#define FILENAME 0x0004 +#define DIRECTORY 0x0008 +#define DRIVE 0x0010 + +void fnsplit(path, drive, dir, name, ext) + char *path; /* buffer containing file name */ + char *drive; /* disk drive name (with ':') */ + char *dir; /* directory name (with '\') */ + char *name; /* file name */ + char *ext; /* file extension (with '.') */ +{ + char *p, *q; + int result = 0; + p = strchr(path,':'); + if (p != NULL) { + if (drive != NULL) memcpy(drive,path,(++p)-path); + result += DRIVE; + } + else p = path; + if (drive != NULL) *(drive+(p-path)) = '\0'; + q = strrchr(path,'\\'); + if (q != NULL) { + if (dir != NULL) { + memcpy(dir,p,q-p+1); + *(dir+(q-p)+1) = '\0'; + } + p = q+1; + result += DIRECTORY; + } + else if (dir != NULL) *dir = '\0'; + q = strchr(p,'.'); + if (q != NULL) { + if (ext != NULL) strcpy(ext,q); + if (name != NULL) { + memcpy(name,p,q-p); + *(name+(q-p)) = '\0'; + if (p != q) result += FILENAME; + } + result += EXTENSION; + } + else { + if (ext != NULL) *ext = '\0'; + if (name != NULL) strcpy(name,p); + if (*p != '\0') result += FILENAME; + } + if (strchr(path,'*')) result += WILDCARD; + else if (strchr(path,'?')) result += WILDCARD; + return result; + } + +char *getpass(prompt) + char *prompt; +{ + static char password[9]; + int count = 0; + int c; + while (*prompt != '\0') putch(*prompt++); + do { + c = getch(); + if (c == '\b') { + if (count > 0) --count; + } + else if (!iscntrl(c)) password[count++] = c; + } while ((c != '\r') && (c != '\l') && (count < 8)); + password[count] = '\0'; + return &password; + } + +char *searchpath(filename) + char *filename; /* name of file */ +{ + void _searchenv(); + static char fname[80]; + _searchenv(filename,"PATH=",fname); + if (fname[0] != '\0') return fname; else return NULL; +} /* searchpath */ + +void _searchenv(name, env_var, path) + char *name; /* name to search for */ + char *env_var; /* name of environment variable */ + char *path; /* buffer to hold result */ +{ + char *getenv(); + char *envptr, *p; + int status; + strcpy(path,name); + /* check default directory */ + if (_sys_acd(0x4300,0,path,&status) == 0) return; + envptr = getenv(env_var); + if (envptr == NULL) {*path = '\0'; return; } + do { /* try all directorys in envptr */ + p = path; + while ((*envptr != ';') && (*envptr != '\0')) *p++ = *envptr++; + if (*envptr == ';') ++envptr; + if (p != path) if (*(p-1) != '\\') *p++ = '\\'; + *p = '\0'; + strcat(p,name); + if (_sys_acd(0x4300,0,path,&status) == 0) return; + } while (*envptr != '\0'); + *path = '\0'; + return; /* not found */ +} /* searchenv */ + diff --git a/Mix Power C v1/EXEC.ASM b/Mix Power C v1/EXEC.ASM new file mode 100644 index 0000000..d91e075 --- /dev/null +++ b/Mix Power C v1/EXEC.ASM @@ -0,0 +1,692 @@ +; +; Copyright (c) Mix Software 1988 +; +; +; Call a program & return to caller +; +; _spawn(progpath,command,envp); +; +; progpath is the address of the program's path name +; command is the command line to pass +; envp is the pointer to the environment +; + IDT _SPAWN + DEF _SPAWN + DEF _spawn + DREF $$PSP + DREF $$TOPSEG + FREF _FMAX +;PARM1 EQU 6 +;PARM2 EQU PARM1+2 +;PARM3 EQU PARM2+2 +; +_spawn equ $ +_SPAWN PUSH BP + MOV BP,SP + CALLFAR _FMAX ; find top of usable memory + MOV BX,AX + SUB BX,[$$PSP] ; Size in use + MOV ES,[$$PSP] ; Shrink memory + MOV AX,>4A00 + INT >21 + MOV AX,DS + MOV ES,AX + MOV DI,EXEBLK + MOV AX,[BP][%PARM3] + STOSW + MOV AX,[BP][%PARM2] + STOSW + MOV AX,DS + STOSW + MOV AX,>5C + STOSW + MOV AX,[$$PSP] + STOSW + MOV AX,>6C + STOSW + MOV AX,[$$PSP] + STOSW + PUSH DS + MOV AX,SS + SEGCS + MOV [SAVESS],AX + MOV AX,SP + SEGCS + MOV [SAVESP],AX + MOV BX,EXEBLK + MOV DX,[BP][%PARM1] + MOV AX,>4B00 + INT >21 + SEGCS + MOV CX,[SAVESS] + SEGCS + MOV DX,[SAVESP] + MOV SS,CX + MOV SP,DX + POP CX + MOV DS,CX + POP BP + JB EXIT + XOR AX,AX +EXIT PUSH AX + MOV ES,[$$PSP] ; Restore memory to original size + SEGES + MOV BX,[$$TOPSEG] + SUB BX,[$$PSP] ; original size + MOV AX,>4A00 + INT >21 + POP AX + RETSEG +SAVESS DW 0-0 +SAVESP DW 0-0 +; + DORG 0 +EXEBLK DW 0 ; Segment of environment + DW >80 ; Command tail + DW 0 ; Command tail segment + DW >5C ; First FCB + DW 0 ; FCB segment + DW >6C ; Second FCB + DW 0 ; FCB segment + END +; +; included if _p_overlay is used +; + IDT _p_chn1 + DDEF _p_chain + DDEF _p_chenv + LDDEF _p_overlay + REF _chain + REF _chainev + DORG 0 +_p_overlay DW 2 +_p_chain DW _chain +_p_chenv DW _chainev + END +; +; included if _p_overlay is not used +; + IDT _p_chain + DDEF _p_chain + DDEF _p_chenv + DORG 0 +_p_chain DW 0 +_p_chenv DW 0 + END +; +; Chain routines for C compiler +; +; _chain(handle,cmdline); +; +; handle is the file handle of the .com or .exe file +; cmdline is the command line to pass to the program +; + IDT _CHAIN + DEF _CHAIN + DEF _chain + FREF _EXELDR + DREF $$PSP + DREF $$ENVIR +;PARM1 EQU 6 +;PARM2 EQU PARM1+2 +;PARM3 EQU PARM2+2 +;PARM4 EQU PARM3+2 +_chain equ $ +_CHAIN PUSH BP + MOV BP,SP + MOV ES,[$$PSP] + CMP [BP][%PARM2],0 + JZ NOCMD + MOV SI,[BP][%PARM2] + MOV DI,>80 + MOV CX,128/2 + CLD + REP + MOVSW + MOV DI,>100 + JMPS LOAD +NOCMD SEGES + MOV [>80],>0D00 +LOAD MOV DI,>0010 + ADD DI,[$$PSP] + MOV BX,[BP][%PARM1] + MOV ES,[$$PSP] + CALLFAR _EXELDR +EXIT MOV AX,-1 + POP BP + RETSEG + END +; +; Chain routines for C compiler +; +; _chainev(handle,cmdline,envir); +; +; handle is the file handle of the .com or .exe file +; cmdline is the command line to pass to the program +; envir is the segment address of the environment +; + IDT _CHAINEV + DEF _CHAINEV + DEF _chainev + FREF _EXELDR + DREF $$PSP + DREF $$ENVIR +;PARM1 EQU 6 +;PARM2 EQU PARM1+2 +;PARM3 EQU PARM2+2 +;PARM4 EQU PARM3+2 +FCBSIZE EQU 38 +_chainev equ $ +_CHAINEV PUSH BP + MOV BP,SP + MOV ES,[$$PSP] + CMP [BP][%PARM2],0 + JZ NOCMD + MOV SI,[BP][%PARM2] + MOV CX,128/2 + MOV DI,>80 + CLD + REP + MOVSW + MOV DI,>100 + JMPS ENVIR +NOCMD SEGES + MOV [>80],>0D00 +ENVIR MOV SI,[BP][%PARM3] + TEST SI,SI + JZ NOENVIR + CMP SI,[$$ENVIR] + JZ NOENVIR + MOV ES,SI + XOR DI,DI + MOV AL,%0 + MOV CX,-1 + CLD +FINDLEN SEGES + CMP %[DI],%0 ; end of table? + JZ ENDENV + REPNZ + SCASB + JMPS FINDLEN +ENDENV NOT CX ; CX is size of the environment + ADD CX,%2 ; Terminating zero & round up + AND CX,>FFFE ; Make size even + SHR CX,1 ; Size in words + MOV ES,[$$PSP] + MOV DS,[BP][%PARM3] + XOR SI,SI + MOV DI,>100+XBLKSIZE+XCODESZ + ADD DI,15 + AND DI,>FFF0 + PUSH DI ; Environment origin + REP + MOVSW + MOV AX,SS + MOV DS,AX + POP DX + MOV CL,4 + SHR DX,CL + ADD DX,[$$PSP] + JMPS LOAD +NOENVIR MOV DX,[$$ENVIR] + MOV DI,>100+XBLKSIZE+XCODESZ +LOAD PUSH DI + PUSH DX + MOV DS,[$$PSP] + MOV ES,[$$PSP] + MOV DI,>5C ; Parse default fcb + MOV SI,>81 + MOV AX,>2900 + INT >21 + SUB SP,FCBSIZE ; Parse 2nd fcb + MOV DI,SP ; use stack for buffer + MOV AX,SS + MOV ES,AX + MOV AX,>2900 + INT >21 + MOV AX,SS + MOV DS,AX + MOV SI,SP + MOV DI,>6C ; Copy 2nd fcb + MOV ES,[$$PSP] + MOV CX,>80->6C + REP + MOVSB + ADD SP,%FCBSIZE +; + MOV SI,XCODE ; Code to shrink memory & exe + MOV DI,>100 + MOV AX,CS + MOV DS,AX + MOV CX,XCODESZ+XBLKSIZE + REP + MOVSB + SEGES ; Set segments in parameter block + MOV [>100+CMDSEG],ES + SEGES + MOV [>100+FCB1SEG],ES + SEGES + MOV [>100+FCB2SEG],ES + POP DX + SEGES + MOV [>100+ENVSEG],DX + POP DI ; End of retained memory + ADD DI,>000F ; round to segment for release + MOV CL,4 + SHR DI,CL + MOV BX,DI + PUSH ES + MOV AX,XCODE1-XCODE+>100 + PUSH AX + MOV AX,>4A00 + RETSEG +; +XCODE DW 0 ; Segment of environment + DW >80 ; Command tail + DW 0 ; Command tail segment + DW >5C ; First FCB + DW 0 ; FCB segment + DW >6C ; Second FCB + DW 0 ; FCB segment +XBLKSIZE EQU $-XCODE +ENVSEG EQU >0 +CMDSEG EQU >4 +FCB1SEG EQU >8 +FCB2SEG EQU >C +; +; +; Address independent code to shrink memory and +; execute the program. +; +; BX = size of memory block +; +XCODE0 EQU $ +ERR MOV DX,ERRMSG + MOV AX,CS + MOV DS,AX + MOV AH,>09 + INT >21 + MOV AX,>4C01 + INT >21 +ERRMSG DB >0D,>0A,'Load error',>0D,>0A,'$' +XCODE1 INT >21 + JB ERR + MOV DX,[BP][%PARM1] ; File name + MOV AX,SS + MOV DS,AX + MOV AX,CS + MOV ES,AX + MOV BX,>100 + MOV AX,>4B00 + INT >21 ; Load and execute program +XCODE2 JB ERR ; Unable to load + MOV AX,CS + MOV SS,AX + MOV SP,XCODE2-XCODE+>100 + MOV AX,>4D00 ; Get return code + INT >21 + MOV AH,>4C + INT >21 ; Back to DOS +XCODESZ EQU $-XCODE0 + END +; +; exe and com file loader +; +; BX = file handle for the file +; DI = segment address for load +; ES = segment address of psp +; +HDRSIZE EQU >1A +FCBSIZE EQU 38 +BUFSZ EQU 512 +HANDLE EQU 0 +PSP EQU 2 +ORG EQU 4 +LOADORG EQU 6 +STACKRES EQU HDRSIZE+8 +EXESIG EQU 8 +EXELENM EQU EXESIG+>2 ; Size of file mod 512 +EXELEN EQU EXESIG+>4 ; Size of file div 512 +EXERELCT EQU EXESIG+>6 ; Count of relocation items +EXEHDRSZ EQU EXESIG+>8 ; Size of header in paragraphs +EXEMIN EQU EXESIG+>A ; Minimum paragraphs needed +EXEMAX EQU EXESIG+>C ; Maximum paragraphs desired +EXESS EQU EXESIG+>E ; Stack segment +EXESP EQU EXESIG+>10 ; Stack pointer +EXECKSUM EQU EXESIG+>12 ; Word checksum +EXEIP EQU EXESIG+>14 ; Starting ip value +EXECS EQU EXESIG+>16 ; Starting code segment +EXEREL EQU EXESIG+>18 ; Offset of first relocation item +; + IDT _EXELDR + DEF _EXELDR +_EXELDR PUSH BP + SUB SP,STACKRES + MOV BP,SP + MOV [BP][%HANDLE],BX + MOV [BP][%ORG],DI + MOV [BP][%PSP],ES + MOV AX,ES + MOV DS,AX + MOV DI,>5C ; Parse default fcb + MOV SI,>81 + MOV AX,>2900 + INT >21 + SUB SP,FCBSIZE ; Parse 2nd fcb + MOV DI,SP ; use stack for buffer + MOV AX,SS + MOV ES,AX + MOV AX,>2900 + INT >21 + MOV AX,SS + MOV DS,AX + MOV SI,SP + MOV DI,>6C ; Copy 2nd fcb + MOV ES,[BP][%PSP] + MOV CX,>80->6C + REP + MOVSB + ADD SP,%FCBSIZE + MOV CX,HDRSIZE + LEA DX,[BP][%EXESIG] + MOV AX,>3F00 + INT >21 ; Read initial header + CMP [BP][%EXESIG],>5A4D ; test for .exe signature + JZ LOADEXE +; +; Load .com file +; +LOADCOM MOV DI,[BP][%ORG] ; Load address + SUB DI,>10 + CMP DI,[BP][%PSP] + JNZ LDERR ; com file must load at >100 + MOV AX,CS + MOV DS,AX ; Copy header for .COM file + MOV SI,COMEXE + MOV AX,SS + MOV ES,AX + LEA DI,[BP][%EXELENM] + MOV CX,(EXECS-EXELENM)/2 + REP + MOVSW + MOV AX,[BP][%PSP] + MOV [BP][%EXESS],AX + MOV [BP][%EXECS],AX + JMPS LOADEXE +; ; mock exe header for .com files +COMEXE DW >100 ; size mod 512 + DW >80 ; size in blocks + DW 0 ; relocation count + DW 0 ; header size + DW 1 ; min paragraphs + DW -1 ; max paragraphs + DW 0-0 ; stack segment + DW >FFFE ; stack pointer + DW 0 ; checksum + DW >100 ; instruction pointer +LDERR MOV AX,-1 +LDEXIT LEA SP,[BP][%STACKRES] + POP BP + RETSEG +MEMERR MOV AX,-2 + JMPS LDEXIT +; +; .exe file loader +; SS:BP points to the parameters +; +LOADEXE MOV DX,[BP][%EXELEN] ; Length of file + MOV AX,[BP][%EXELENM] + CMP AX,0 ; Full page? + JZ FULLPAGE + DEC DX +FULLPAGE MOV CL,5 + SHL DX,CL ; Convert to paragraphs + DEC CL + SHR AX,CL + ADD DX,AX ; DX = size in paragraphs + SUB DX,[BP][%EXEHDRSZ] ; - size of header + AND [BP][%EXELENM],>000F ; fraction + JZ EVEN01 + INC DX +EVEN01 MOV [BP][%EXELEN],DX ; code size in paragraphs + MOV ES,[BP][%PSP] + MOV BX,[BP][%EXEMAX] + CMP BX,LOADSZP ; minimum needed for loader + JAE USEMAX + MOV BX,LOADSZP +USEMAX ADD BX,DX + JNB SETMEM + MOV BX,-1 +SETMEM MOV AH,>4A ; set memory size + PUSH BX + INT >21 + JB TRYMAX + POP BX + JMPS MEMSET +TRYMAX POP AX + MOV AH,>4A ; Get maximum available + PUSH BX + INT >21 + POP BX + JB HAVEMEM ; Try what we already have +MEMSET ADD BX,[BP][%PSP] + SEGES + MOV [2],BX +HAVEMEM MOV AX,[BP][%EXELEN] + ADD AX,[BP][%ORG] + MOV [BP][%LOADORG],AX ; Segment address for loader + MOV DX,[BP][%EXEMIN] ; Minimum memory above code + CMP DX,LOADSZP + JAE USEMIN + MOV DX,LOADSZP +USEMIN ADD AX,DX ; Minimum memory to load + SEGES + CMP AX,[2] + JA MEMERR ; Not enough memory +; +; Move the loader code and branch to it +; Copies the control point and argument block to the +; program's target address before moving the loader. This +; protects against the loader's target conflicting with +; the stack space or code space for the executing program. +; +; SS:BP = location of argument block +; +; +MOVEGO MOV SI,FINAL ; Final move instructions + MOV ES,[BP][%ORG] + XOR DI,DI + MOV AX,CS + MOV DS,AX + MOV CX,EFINAL-FINAL + CLD + REP + MOVSB + MOV SI,BP ; Data block + MOV BP,DI + MOV AX,SS + MOV DS,AX + MOV CX,STACKRES + REP + MOVSB + ADD DI,>100 ; Temporary stack space for + MOV DX,ES ; move routine + MOV SS,DX + MOV SP,DI ; Relocate stack + PUSH [BP][%LOADORG] ; Address of final target + XOR AX,AX + PUSH AX + PUSH DX ; Return to move routine + PUSH AX + MOV DX,CS + MOV DS,DX + MOV SI,EXELOAD + MOV CX,LOADRSZ + MOV DX,DI + REP ; Move loader to low memory + MOVSB + MOV SI,DX + MOV AX,ES + MOV DS,AX + MOV ES,[BP][%LOADORG] + XOR DI,DI + MOV CX,LOADRSZ + RETSEG ; Branch & move loader high +FINAL REP + MOVSB ; Move loader above program + RETSEG ; Transfer to loader +EFINAL EQU $ +; +; +; Relocatable .EXE file loader +; BP points to argument block +; +EXELOAD MOV AX,SS ; Copy stack to local storage + MOV DS,AX + MOV SI,BP + MOV AX,CS + MOV ES,AX + MOV DI,EXESTK-EXELOAD + MOV BP,DI + MOV CX,STACKRES + CLD + REP + MOVSB + MOV DX,EXESTK+256 + MOV SS,AX + MOV SP,DX + MOV BX,[BP][%HANDLE] + MOV DS,[BP][%PSP] + MOV DX,[BP][%EXEHDRSZ] ; Seek file past header + XOR AX,AX + MOV CX,4 +HDRSZ SHL DX,1 + RCL AX,1 + LOOP HDRSZ + MOV CX,AX + MOV BX,[BP][%HANDLE] + MOV AX,>4200 + INT >21 ; Seek to beginning of file + JB EXEERR1 + MOV DS,[BP][%ORG] +READEXE MOV CX,[BP][%EXELEN] + JCXZ DONEREAD + CMP CX,>7FF + JBE ONEREAD + MOV CX,>7FF0 + SUB [BP][%EXELEN],>7FF + JMPS READ1 +ONEREAD CMP [BP][%EXELENM],0 + JZ EVEN02 + DEC CX +EVEN02 MOV AX,CX + MOV CL,4 + SHL AX,CL + ADD AX,[BP][%EXELENM] + MOV CX,AX + MOV [BP][%EXELEN],0 +READ1 MOV AX,>3F00 + XOR DX,DX + INT >21 + JB EXEERR1 + CMP AX,CX + JNZ EXEEND + MOV AX,DS + ADD AX,>7FF + MOV DS,AX + JMPS READEXE +EXEEND CMP [BP][%EXESIG],>5A4D + JNZ EXEERR1 ; EXE file too short +GOCOM1 JMP GOCOM ; .COM file +EXEERR1 JMP EXEERR +; +; Seek to relocation table +; Read relocation data into buffer & apply +; +DONEREAD CMP [BP][%EXESIG],>5A4D + JNZ GOCOM1 + CMP [BP][%EXERELCT],0 + JZ GOEXE + MOV DX,[BP][%EXEREL] + XOR CX,CX ; Seek to relocation table + MOV BX,[BP][%HANDLE] + MOV AX,>4200 + INT >21 + JB EXEERR1 +READTBL MOV CX,[BP][%EXERELCT] + JCXZ GOEXE ; End of relocation table + CMP CX,BUFSZ/4 + JBE ONEBLOCK + MOV CX,BUFSZ/4 +ONEBLOCK SUB [BP][%EXERELCT],CX + SHL CX,1 + SHL CX,1 + MOV BX,[BP][%HANDLE] + MOV AX,SS + MOV DS,AX + MOV AH,>3F + LEA DX,[BP][%EXEREL+2] + INT >21 ; Read a block of relocations + JB EXEERR1 + CMP AX,CX + JNZ EXEERR + SHR CX,1 + SHR CX,1 + LEA SI,[BP][%EXEREL+2] + MOV DX,[BP][%ORG] +RELOC MOV DI,[SI] ; Apply relocations + MOV AX,[SI][%2] + ADD AX,DX + MOV ES,AX + SEGES + ADD [DI],DX + ADD SI,%4 + LOOP RELOC + JMPS READTBL +; +; Load registers from header & transfer to program +; +GOEXE MOV BX,[BP][%HANDLE] + MOV AH,>3E + INT >21 + MOV AX,[BP][%PSP] + MOV DS,AX + MOV ES,AX + MOV AX,[BP][%ORG] + MOV DX,AX + ADD AX,[BP][%EXESS] + ADD DX,[BP][%EXECS] + MOV BX,[BP][%EXESP] + MOV CX,[BP][%EXEIP] + MOV SS,AX + MOV SP,BX + PUSH DX + PUSH CX + RETSEG +; +GOCOM MOV BX,[BP][%HANDLE] + MOV AH,>3E + INT >21 + MOV AX,[BP][%PSP] + MOV DS,AX + MOV ES,AX + MOV BX,>FFFE + MOV [BX],0 + MOV SS,AX + MOV SP,BX + PUSH AX + MOV AX,>100 + PUSH AX + RETSEG +; +; +EXEERR MOV DX,ERRMSG + MOV AH,>09 + INT >21 + MOV AX,>4C01 + INT >21 +ERRMSG DB >0D,>0A,'Load error',>0D,>0A,'$' +LOADRSZ EQU $-EXELOAD +LOADSZP EQU (LOADRSZ+BUFSZ+256)/16 +EXESTK EQU $ + END diff --git a/Mix Power C v1/EXIT.C b/Mix Power C v1/EXIT.C new file mode 100644 index 0000000..9097ba2 --- /dev/null +++ b/Mix Power C v1/EXIT.C @@ -0,0 +1,72 @@ + +/* Exit from program */ +/* Copyright (c) Mix Software 1988 */ + +void abort() +{ + raise(SIGABRT); + _errmsg("Abnormal program terminations\x0d\x0a"); + _exit(3); + } + +/* ------------------------------------------------------------ */ + +exit(status) +int status; +{ + int i; + int _exit(); + extern int (*_fclose)(); + extern onexit_t _on_exit_tbl[32]; + extern int _on_index; + + while (_on_index--) (*(_on_exit_tbl[_on_index]))(); + + i = 0; + while (i < MAXFILES) { + if (_iob[i] != NULL) (*_fclose)(_iob[i]); + i++; + } + _exit(status); +} + +/* ------------------------------------------------------------ */ + +onexit_t onexit(func) + onexit_t func; +{ + extern int _on_index; + extern onexit_t _on_exit_tbl[32]; + if (_on_index > 31) return NULL; + _on_exit_tbl[_on_index] = func; + _on_index++; + return func; +} + +/* ------------------------------------------------------------ */ + +atexit_t atexit(func) + atexit_t func; +{ + extern int _on_index; + extern onexit_t _on_exit_tbl[32]; + if (_on_index > 31) return NULL; + _on_exit_tbl[_on_index] = func; + _on_index++; + return func; +} + +/* ------------------------------------------------------------ */ + +_exit(status) + int status; +{ + extern int $$EXSTAT; + extern void (*$$EXITPT)(); + $$EXSTAT = status; + (*$$EXITPT)(); + } + +onexit_t _on_exit_tbl[32]; +int _on_index = 0; + diff --git a/Mix Power C v1/FAR.ASM b/Mix Power C v1/FAR.ASM new file mode 100644 index 0000000..6e685dd --- /dev/null +++ b/Mix Power C v1/FAR.ASM @@ -0,0 +1,227 @@ +; +; Copyright (c) Mix Software 1988 +; +; -------------------------------------------------------- +; FARSTI8 - Store an 8 byte value via far pointer +; -------------------------------------------------------- +; STACK CONTAINS: value (8 bytes) +; DESTINATION (LONG) +; + IDT $_FARST8 + DEF $_FARST8 +$_FARST8 PUSH BP + MOV BP,SP + LEA SI,[BP][%PARM1] + MOV DI,[BP][%PARM1+8] + MOV ES,[BP][%PARM1+10] + MOV CX,4 + REP + MOVSW + POP BP + RETSEG + END +; +; -------------------------------------------------------- +; FARMOVE - MOVE A BLOCK OF MEMORY +; -------------------------------------------------------- +; STACK CONTAINS: BYTE COUNT +; DESTINATION (LONG) +; SOURCE (LONG) +; + IDT $_FARMOV + DEF $_FARMOV +$_FARMOV PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM1] ; GET COUNT + JCXZ SMOVEEX + MOV DI,[BP][%PARM2] ; DESTINATION + MOV ES,[BP][%PARM3] + MOV SI,[BP][%PARM4] ; GET SOURCE + MOV AX,[BP][%PARM5] + PUSH DS ; SAVE DATA SEGMENT + MOV DS,AX + REP + MOVSB +SMOVEEX POP AX + MOV DS,AX + POP BP + RETSEG + END +; +; -------------------------------------------------------- +; FARMOVER - MOVE A BLOCK OF MEMORY +; -------------------------------------------------------- +; STACK CONTAINS: BYTE COUNT +; SOURCE (LONG) +; DESTINATION (LONG) +; + IDT $_FARMVR + DEF $_FARMVR +$_FARMVR PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM1] ; GET COUNT + JCXZ SMOVEEX + MOV SI,[BP][%PARM2] ; SOURCE + MOV AX,[BP][%PARM3] + PUSH DS ; SAVE DATA SEGMENT + MOV DS,AX + MOV DI,[BP][%PARM4] ; GET DESTINATION + MOV AX,[BP][%PARM5] + MOV ES,AX + REP + MOVSB +SMOVEEX POP AX + MOV DS,AX + POP BP + RETSEG + END +; +; -------------------------------------------------------- +; FAR2LONG - CONVERT FAR ADDRESS TO LONG INTEGER +; -------------------------------------------------------- +; STACK CONTAINS: FAR POINTER +; + IDT fartol + DEF fartol + IF UPPER + DEF FARTOL + ENDIF +fartol equ $ +FARTOL MOV SI,SP + MOV BX,[SI][%PARM1-2] ; GET OFFSET + MOV DX,[SI][%PARM2-2] ; GET SEGMENT + MOV AX,DX + MOV CL,%12 + SHR DX,CL + MOV CL,%4 + SHL AX,CL + ADD AX,BX + ADC DX,%0 + RETSEG + END +; +; -------------------------------------------------------- +; LONG2FAR - CONVERT LONG INTEGER TO FAR ADDRESS +; -------------------------------------------------------- +; STACK CONTAINS: FAR POINTER +; + IDT ltofar + DEF ltofar + IF UPPER + DEF LTOFAR + ENDIF +ltofar EQU $ +LTOFAR MOV SI,SP + MOV BX,[SI][%PARM1-2] ; GET LOWER + MOV DX,[SI][%PARM2-2] ; GET UPPER + MOV CL,%12 + SHL DX,CL + MOV AX,BX + MOV CL,%4 + SHR BX,CL + ADD DX,BX + AND AX,>000F + RETSEG + END +; +; -------------------------------------------------------- +; BITSET - SET A BIT FIELD +; -------------------------------------------------------- +; STACK CONTAINS: SHIFT COUNT +; BIT MASK +; VALUE OF FIELD +; ADDRESS OF WORD CONTAINING FIELD +; + IDT $_BITSET + DEF $_BITSET +$_BITSET MOV SI,SP + MOV CX,[SI][%PARM1-2] + MOV DX,[SI][%PARM2-2] + MOV AX,[SI][%PARM3-2] + JCXZ NOSHIFT + SHL AX,CL +NOSHIFT AND AX,DX + MOV BX,[SI][%PARM4-2] + MOV CX,[BX] + NOT DX + AND CX,DX + OR AX,CX + MOV [BX],AX + RETSEG + END +; +; +; -------------------------------------------------------- +; FBITSET - SET A BIT FIELD +; -------------------------------------------------------- +; STACK CONTAINS: SHIFT COUNT +; BIT MASK +; VALUE OF FIELD +; ADDRESS OF WORD CONTAINING FIELD +; + IDT $_FBITS + DEF $_FBITS +$_FBITS MOV SI,SP + MOV CX,[SI][%PARM1-2] + MOV DX,[SI][%PARM2-2] + MOV AX,[SI][%PARM3-2] + JCXZ NOSHIFT + SHL AX,CL +NOSHIFT AND AX,DX + MOV BX,[SI][%PARM5-2] + MOV ES,BX + MOV BX,[SI][%PARM4-2] + SEGES + MOV CX,[BX] + NOT DX + AND CX,DX + OR AX,CX + SEGES + MOV [BX],AX + RETSEG + END +; +; +; -------------------------------------------------------- +; FARCMP - COMPARE FAR POINTERS +; -------------------------------------------------------- +; STACK CONTAINS: TWO FAR POINTERS +; + IDT $_FARCMP + DEF $_FARCMP +$_FARCMP MOV SI,SP + MOV DX,[SI][%PARM1-2] + MOV CX,[SI][%PARM2-2] + MOV BX,[SI][%PARM3-2] + MOV AX,[SI][%PARM4-2] + CMP AX,CX + JZ SEGNE +CMPOFF CMP BX,DX + JZ EQUAL + JL LESS +GREATER MOV AL,1 ; GREATER THAN + JMPS DONE +LESS MOV AL,>FF ; LESS THAN + JMPS DONE +EQUAL XOR AX,AX +DONE RETSEG +; Segments unequal, normalize +SEGNE PUSH DX + PUSH CX + MOV CL,4 + PUSH BX + SHR BX,CL + ADD AX,BX + POP BX + AND BX,>FFF + SHR DX,CL + POP CX + ADD CX,DX + POP DX + AND DX,>FFF + CMP AX,CX + JL LESS + JG GREATER + JMPS CMPOFF + END +; diff --git a/Mix Power C v1/FARHEAP.ASM b/Mix Power C v1/FARHEAP.ASM new file mode 100644 index 0000000..9387fee --- /dev/null +++ b/Mix Power C v1/FARHEAP.ASM @@ -0,0 +1,1212 @@ +; +; Far heap functions. +; +; Copyright (c) Mix Software 1988 +; +; Extended memory heap +; + GLOBAL +; +MINHEAP EQU 4 ; Minimum size of a heap +; +; Heap descriptor: +; +H$FREE EQU 0 +H$MIN EQU 2 +H$MAX EQU 4 +H$CURUSE EQU 6 +H$MAXUSE EQU 8 +; +; Packet pointer points to previous paragraph +; All packets have length at offset >0E +; Allocated flag is at offset >0D +; Free packets have pointer to prior and next in data area +; +H$LEN EQU >000E ; Length of packet +H$AVAIL EQU >000D ; 1 = available, 0=allocated +H$SUCC EQU >0010 ; Pointer to next packet +H$PRED EQU >0012 ; Pointer to previous packet +; + ENDGLOBAL +; +; +; ---------------------------------------------------------- +; +; FALLOC +; allocate a packet from extended heap +; called as a C function: +; char far *falloc(size) +; unsigned size; /* size in bytes */ +; returns address of packet or 0 if none available +; + IDT falloc + IF UPPER + DEF FALLOC + ENDIF + DEF falloc + FREF _FALLOC + FREF fnewheap + DREF $$FARHP +falloc EQU $ +FALLOC CMP [$$FARHP],0 + JNZ OK + MOV AX,$$FARHP + PUSH AX + MOV AX,-1 + PUSH AX + CALLFAR fnewheap + ADD SP,%4 +OK MOV AX,$$FARHP + PUSH AX + MOV SI,SP + MOV AX,[SI][%PARM1] + ADD AX,2+1+15 ; Reserve two bytes for length, +; ; one byte for available flag, + AND AL,%#F0 ; and round up to paragraph boundary + MOV CL,4 ; Convert size to paragraphs +SHIFT SHR AX,CL + PUSH AX + CALLFAR _FALLOC + ADD SP,%4 + RETSEG + END +; +; ---------------------------------------------------------- +; +; FCALLOC +; allocate a packet from extended heap +; called as a C function: +; char far *fcalloc(number,size) +; unsigned number; /* number of elements */ +; unsigned size; /* size of an element in bytes */ +; returns address of packet or 0 if none available +; + IDT fcalloc + IF UPPER + DEF FCALLOC + ENDIF + DEF fcalloc + FREF _FALLOC + FREF fnewheap + DREF $$FARHP +fcalloc equ $ +FCALLOC CMP [$$FARHP],0 + JNZ OK + MOV AX,$$FARHP + PUSH AX + MOV AX,-1 + PUSH AX + CALLFAR fnewheap + ADD SP,%4 +OK MOV AX,$$FARHP + PUSH AX + MOV SI,SP + MOV AX,[SI][%PARM1] + MUL [SI][%PARM2] + ADD AX,2+1+15 ; Reserve two bytes for length, +; ; one byte for available flag, + ADC DX,%0 + AND AL,%#F0 ; and round up to paragraph boundary + MOV CX,4 ; Convert size to paragraphs +SHIFT SHR DX,1 + RCR AX,1 + LOOP SHIFT + PUSH AX + CALLFAR _FALLOC + ADD SP,%4 + RETSEG + END +; +; ---------------------------------------------------------- +; +; farcalloc +; allocate a packet from extended heap +; called as a C function: +; void far *farcalloc(number,size) +; unsigned long number; /* number of elements */ +; unsigned long size; /* size of an element in bytes */ +; returns address of packet or 0 if none available +; + IDT farcallo + IF LONGNAME + LDEF farcalloc + ENDIF + IF SHORTNAM + DEF Fcalloc + ENDIF + FREF _FALLOC + FREF fnewheap + FREF $_LUMUL + DREF $$FARHP +farcalloc equ $ +Fcalloc PUSH BP + MOV BP,SP + CMP [$$FARHP],0 + JNZ OK + MOV AX,$$FARHP + PUSH AX + MOV AX,-1 + PUSH AX + CALLFAR fnewheap + ADD SP,%4 +OK MOV AX,$$FARHP + PUSH AX + PUSH [BP][%PARM4] + PUSH [BP][%PARM3] + PUSH [BP][%PARM2] + PUSH [BP][%PARM1] + CALLFAR $_LUMUL ; Number of items * size + ADD SP,%8 + ADD AX,2+1+15 ; Reserve two bytes for length, +; ; one byte for available flag, + ADC DX,%0 + AND AL,%#F0 ; and round up to paragraph boundary + MOV CX,4 ; Convert size to paragraphs +SHIFT SHR DX,1 + RCR AX,1 + LOOP SHIFT + PUSH AX + CALLFAR _FALLOC + ADD SP,%4 + POP BP + RETSEG + END +; +; ---------------------------------------------------------- +; +; void far *farrealloc(void far *block, newsize) +; void far *block - previous pointer to block +; unsigned long newsize - requested size +; return the new pointer +; + IDT farreall + IF LONGNAME + LDEF farrealloc + LFREF farmalloc + ENDIF + IF SHORTNAM + DEF Frealloc + FREF Fmalloc + ENDIF + FREF _FFREE + FREF _FALLOC + DREF $$FARHP +farrealloc EQU $ +Frealloc PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + OR AX,[BP][%PARM2] + JZ MALLOC + CMP [$$FARHP],0 + JZ NULL1 + MOV AX,[BP][%PARM3] ; New size + MOV DX,[BP][%PARM4] + ADD AX,2+1+15 ; allow extra for length, flag + ADC DX,%0 + AND AL,%#F0 ; round up to paragraph boundary + MOV CX,4 ; Convert size to paragraphs +SHIFT SHR DX,1 + RCR AX,1 + LOOP SHIFT + MOV BX,[BP][%PARM2] ; segment part of old pointer + DEC BX ; point to block header + MOV ES,BX + SEGES + CMP %[H$AVAIL],0 + JNZ NULL1 ; This is not a valid block + SEGES + MOV DX,[H$LEN] ; Old length + CMP AX,DX + JZ SAME1 + JA EXPAND + JMP SHRINK ; Make smaller +NULL1 JMP NULL +MALLOC PUSH [BP][%PARM4] + PUSH [BP][%PARM3] + IF LONGNAME + CALLFAR farmalloc + ENDIF + IF ~LONGNAME + callfar Fmalloc + ENDIF + ADD SP,%4 + POP BP + RETFAR +EXPAND MOV SI,BX + ADD SI,DX ; Next block header + MOV ES,SI + SEGES + CMP %[H$AVAIL],0 + JZ MOVE + MOV CX,AX + SUB CX,DX ; additional space needed + SEGES + CMP CX,[H$LEN] + JA MOVE ; Not enough space in next block +; +; Expand in place +; CX = size needed, ES is next block, AX = new size +; + SEGES ; Allocate entire next block + MOV AX,[H$PRED] + SEGES + MOV BX,[H$SUCC] + JNZ PARTIAL + SEGES + MOV CX,[H$LEN] + MOV ES,AX + SEGES + MOV [H$SUCC],BX + MOV ES,BX + SEGES + MOV [H$PRED],AX +ADJUST MOV AX,[BP][%PARM2] + DEC AX + MOV ES,AX + SEGES + ADD [H$LEN],CX ; adjust size + MOV SI,[$$FARHP] + MOV AX,[SI][%H$CURUSE] + MOV [SI][%H$CURUSE],CX + CMP AX,[SI][%H$MAXUSE] + JBE ADJDONE + MOV [SI][%H$MAXUSE],CX +SAME1 EQU $ +ADJDONE JMP SAME +; +; Allocate a part of the next block +; ES = next block, AX = predecessor, BX = successor +; +PARTIAL SEGES + MOV DX,[H$LEN] + SUB DX,CX ; New length + MOV SI,ES + ADD SI,CX + MOV ES,SI ; address of reduced block + SEGES + MOV [H$LEN],DX + SEGES + MOV [H$PRED],AX + SEGES + MOV [H$SUCC],BX + SEGES + MOV %[H$AVAIL],%1 + MOV ES,AX + SEGES + MOV [H$SUCC],SI + MOV ES,BX + SEGES + MOV [H$PRED],SI + JMPS ADJUST +; +; relocate the block - ES points to the old block +; AX is the new size (in paragraphs) +; +MOVE PUSH ES + PUSH [$$FARHP] + PUSH AX + CALLFAR _FALLOC ; allocate a new block + ADD SP,%4 + POP BX ; recover original segment + TEST AX,AX + JZ NULL ; Not enough space + MOV ES,BX + SEGES + MOV DX,[H$LEN] ; Length of old data + INC BX ; Segment address of old data + PUSH AX + PUSH DS +COPYBLK MOV DS,BX + MOV ES,AX + CMP DX,>0800 ; Is size > 32k + JB COPYLAST + MOV CX,>4000 ; Move a 32k block + REP + MOVSW + ADD BX,>0800 + ADD AX,>0800 + SUB DX,>0800 + JMPS COPYBLK +COPYLAST CMP DX,%0 ; Move partial block + JZ COPYDONE + SHL DX,1 + SHL DX,1 + SHL DX,1 + MOV CX,DX + REP + MOVSW +COPYDONE POP AX + MOV DS,AX + PUSH [$$FARHP] ; Release old block + PUSH [BX][%PARM2] + CALLFAR _FFREE + ADD SP,%4 + POP DX ; Segment of new block + XOR AX,AX + POP BP + RETFAR +; +; decrease size of block +; DX = old length, AX = new length +; +SHRINK SEGES + MOV [H$LEN],AX ; Adjust length + MOV BX,ES + ADD BX,AX ; Part to be released + MOV ES,BX + SEGES ; Make new allocated block + MOV %[H$AVAIL],%0 ; from excess memory + SUB DX,AX + SEGES + MOV [H$LEN],DX + PUSH [$$FARHP] ; heap descriptor + PUSH ES ; block to be released + CALLFAR _FFREE ; release the excess space + ADD SP,%4 +; return pointer to original block +SAME MOV AX,[BP][%PARM1] + MOV DX,[BP][%PARM2] + POP BP + RETFAR +NULL XOR AX,AX + XOR DX,DX + POP BP + RETFAR + END +; +; ---------------------------------------------------------- +; +; farmalloc +; allocate a packet from extended heap +; called as a C function: +; void far *farmalloc(size) +; unsigned long size; +; returns address of packet or 0 if none available +; + IDT farmalloc + IF LONGNAME + LDEF farmalloc + ENDIF + IF SHORTNAM + DEF Fmalloc + ENDIF + FREF _FALLOC + FREF fnewheap + DREF $$FARHP +farmalloc equ $ +Fmalloc PUSH BP + MOV BP,SP + CMP [$$FARHP],0 + JNZ OK + MOV AX,$$FARHP + PUSH AX + MOV AX,-1 + PUSH AX + CALLFAR fnewheap + ADD SP,%4 +OK MOV AX,$$FARHP + PUSH AX + MOV AX,[BP][%PARM1] + MOV DX,[BP][%PARM2] + ADD AX,2+1+15 ; Reserve two bytes for length, +; ; one byte for available flag, + ADC DX,%0 + AND AL,%#F0 ; and round up to paragraph boundary + MOV CX,4 ; Convert size to paragraphs +SHIFT SHR DX,1 + RCR AX,1 + LOOP SHIFT + PUSH AX + CALLFAR _FALLOC + ADD SP,%4 + POP BP + RETSEG + END +; +; ---------------------------------------------------------- +; +; HALLOC +; allocate a packet from extended heap +; called as a C function: +; char far *halloc(number,size) +; long number; /* number of elements */ +; unsigned size; /* size of an element in bytes */ +; returns address of packet or 0 if none available +; + IDT halloc + IF UPPER + DEF HALLOC + ENDIF + DEF halloc + FREF _FALLOC + FREF fnewheap + DREF $$FARHP +halloc equ $ +HALLOC CMP [$$FARHP],0 + JNZ OK + MOV AX,$$FARHP + PUSH AX + MOV AX,-1 + PUSH AX + CALLFAR fnewheap + ADD SP,%4 +OK MOV AX,$$FARHP + PUSH AX + MOV SI,SP + MOV AX,[SI][%PARM2] + MUL [SI][%PARM3] + MOV CX,AX + MOV AX,[SI][%PARM1] + MUL [SI][%PARM3] + ADD DX,CX + ADD AX,2+1+15 ; Reserve two bytes for length, +; ; one byte for available flag, + ADC DX,%0 + AND AL,%#F0 ; and round up to paragraph boundary + MOV CX,4 ; Convert size to paragraphs +SHIFT SHR DX,1 + RCR AX,1 + LOOP SHIFT + PUSH AX + CALLFAR _FALLOC + ADD SP,%4 + RETSEG + END +; +; ---------------------------------------------------------- +; +; _fmsize(ptr) return size of the block +; char far *ptr; +; + IDT _fmsize + DEF _fmsize +_fmsize MOV SI,SP + MOV BX,[SI][%PARM1-2] + MOV AX,[SI][%PARM2-2] + DEC AX + MOV ES,AX + SEGES + MOV AX,[BX][H$LEN] + MOV CL,4 + SHL AX,CL + SUB AX,3 + RETSEG + END +; +; ---------------------------------------------------------- +; +; long farcoreleft +; return the amount of memory left in far heap +; + IDT farcorel + IF LONGNAME + LDEF farcoreleft + ENDIF + IF SHORTNAM + DEF farcorel + ENDIF + FREF fnewheap + DREF $$FARHP +farcorel CMP [$$FARHP],0 + JNZ OK + MOV AX,$$FARHP + PUSH AX + MOV AX,-1 + PUSH AX + CALLFAR fnewheap + ADD SP,%4 +OK XOR DX,DX + MOV SI,$$FARHP + MOV AX,[SI][H$MAX] + SUB AX,[SI][H$MIN] + SUB AX,[SI][H$CURUSE] + MOV CX,4 +SHIFT SHL AX,1 + RCL DX,1 + LOOP SHIFT +DONE RETFAR + END +; +; ---------------------------------------------------------- +; +; _FALLOC +; allocate a packet from extended heap +; called as a C function: +; int _falloc(size,desc) +; int size; /* size in paragraphs */ +; heapdesc *desc; /* address of heap descriptor */ +; returns address of packet or 0 if none available +; address is a 16 bit segment value +; + IDT _FALLOC + DEF _FALLOC +_FALLOC PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM2] ; SI = Address of descriptor + CMP [SI],0 + JZ NOSPACE + MOV DX,[BP][%PARM1] ; Size requested + TEST DX,DX ; Check for zero + JNZ FALLOC01 + INC DX ; Minimum size is one paragraph +; +; Set BX to point to the current free list +; +FALLOC01 MOV BX,[%H$FREE][SI] +; +; Search free list for a packet of sufficient size +; +NEWLOOP MOV ES,BX + SEGES + CMP DX,[H$LEN] ; COMPARE LENGTHS + JBE FALLOC02 +; +; The current packet in the free list is not large enough +; move to the next packet +; ES contains the address of the current packet +; DX contains the required size +; +FALLOC03 SEGES + MOV BX,[H$SUCC] ; BX = next packet + CMP BX,[SI][%H$FREE] ; All packets checked? + JNZ NEWLOOP ; No packet is large enough +NOSPACE XOR BX,BX + JMP FALLOC08 +; +; The current packet is large enough +; remove needed space & check result for > 0 +; +FALLOC02 SEGES + MOV AX,[H$LEN] ; GET PACKET SIZE + SUB AX,DX ; SUBTRACT NEEDED SPACE + JNZ FALLOC04 +; +; Allocate entire packet +; length is in DX, location is in BX,ES +; + SEGES + MOV AX,[H$SUCC] ; GET SUCCESSOR FIELD + MOV [SI][%H$FREE],AX ; NEW FREE LIST + SEGES + MOV CX,[H$PRED] ; CX = PREDECESSOR +; +; LAST+2 := NEXT +; + MOV ES,CX + SEGES + MOV [H$SUCC],AX +; +; NEXT+4 := LAST +; + MOV ES,AX ; Point to successor + SEGES + MOV [H$PRED],CX ; set next@.lat to cur@.last + JMPS FALLOC05 +; +; Reduce the size of the packet +; AX Contains the new length +; DX Contains the length of the new packet +; BX, ES point to the packet +; +; +FALLOC04 PUSH BX ; SAVE CURRENT PACKET ADDR + SEGES + MOV CX,[H$PRED] ; Get links + PUSH CX + SEGES + MOV CX,[H$SUCC] + ADD BX,DX ; BX <-- ADDR OF NEW FREE PKT + MOV ES,BX + SEGES + MOV [H$LEN],AX ; SET NEW LENGTH + SEGES + MOV %[H$AVAIL],%1 ; MARK NOT ALLOCATED +; +; SET SUCCESSOR OF NEW FREE PACKET TO SUCCESSOR OF OLD +; FREE PACKET & PREDECESSOR OF NEW TO PREDECESSOR OF OLD +; + SEGES + MOV [H$SUCC],CX + POP AX + SEGES + MOV [H$PRED],AX +; +; Link around newly allocated space +; last@.next := newsp +; next@.last := newsp +; + MOV ES,AX + SEGES + MOV [H$SUCC],BX + MOV ES,CX + SEGES + MOV [H$PRED],BX ; NEXT@.PRED = NEW FREE PKT + MOV [SI][%H$FREE],CX + POP BX +; +; AT THIS POINT DX CONTAINS THE LENGTH OF THE NEWLY ALLOCATED +; PACKET, AND BX CONTAINS ITS ADDRESS +; +; SET THE LENGTH OF THE NEWLY ALLOCATED PACKET. +; +FALLOC05 MOV ES,BX + SEGES + MOV [H$LEN],DX + SEGES + MOV %[H$AVAIL],%0 + INC BX ; POINT TO DATA AREA +; +; ADD SIZE OF CURRENT PACKET TO CURRENT HEAP ALLOCATED +; + ADD [SI][%H$CURUSE],DX ; ADD TO CURRENT ALLOCATION + MOV AX,[SI][%H$CURUSE] ; LARGER THAN MAX USED? + CMP AX,[SI][%H$MAXUSE] + JB FALLOC09 + MOV [SI][%H$MAXUSE],AX ; SET MAXIMUM HEAP USED +; +; Zero the memory, BX = segment, DX = length +; +FALLOC09 MOV ES,BX +FALLOC11 TEST DX,>F800 + JZ FALLOC10 + MOV CX,>4000 ; zero 32k bytes (16k words) + XOR DI,DI + XOR AX,AX + REP + STOSW + MOV AX,ES + ADD AX,>0800 + MOV ES,AX + SUB DX,>0800 + JMPS FALLOC11 +FALLOC10 MOV CL,4 + SHL DX,CL + SUB DX,2+1 ; linkage for next packet + MOV CX,DX + XOR DI,DI + XOR AX,AX + REP + STOSB +FALLOC08 MOV DX,BX + XOR AX,AX + POP BP + RETSEG +; + END +; +; ------------------------------------------------------------ +; +; FFREE +; Release a packet in extended heap +; called as a C function: +; int ffree(ptr) +; char far *ptr; /* pointer value */ +; returns 0 if successful, -1 on error +; +; + IDT ffree + IF UPPER + DEF FFREE + ENDIF + DEF ffree + DEF hfree + DEF farfree + DREF $$FARHP + FREF _FFREE +; +ffree EQU $ +hfree EQU $ +farfree EQU $ +FFREE MOV SI,SP + MOV AX,[SI][%PARM2-2] ; segment value + MOV BX,[SI][%PARM1-2] ; Offset + MOV CX,AX + OR CX,BX + JZ NIL +; TEST BX,BX +; JNZ INVALID ; offset must be zero + CMP [$$FARHP],0 + JZ INVALID ; no far heap available + MOV BX,$$FARHP + PUSH BX + PUSH AX + CALLFAR _FFREE + ADD SP,%4 + RETSEG +INVALID MOV AX,-1 + RETSEG +NIL XOR AX,AX + RETSEG + END +; +; +; ------------------------------------------------------------ +; +; _FFREE +; Release a packet in extended heap +; called as a C function: +; int _ffree(ptr,desc) +; int ptr; /* pointer value (segment only) */ +; heapdesc *desc; /* address of heap descriptor */ +; returns 0 if successful, -1 on error +; +; + IDT _FFREE + DEF _FFREE +; +_FFREE PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM2] ; SI = Address of descriptor + MOV BX,[BP][%PARM1] ; Pointer value + TEST BX,BX + JNZ FREE01 + XOR AX,AX + POP BP + RETFAR +FREE01 DEC BX ; POINT TO LENGTH FIELD +; +; CHECK POINTER AGAINST LOWER BOUND OF HEAP - ERROR IF LESS +; + CMP BX,[SI][%H$MIN] + JBE INVPKT1 +; +; GET LENGTH OF THE PACKET +; +FR01 MOV ES,BX + SEGES + MOV CX,[H$LEN] ; Get length + SEGES + TEST %[H$AVAIL],%1 + JNZ INVPKT1 ; NOT ALLOCATED + MOV AX,BX + ADD AX,CX ; AX POINTS TO NEXT PACKET +; +; CHECK PTR + SIZE OF PACKET AGAINST HEAP UPPER BOUND +; + CMP AX,[SI][%H$MAX] + JBE FR02 +INVPKT1 JMP INVPKT +; +; BX = ADDRESS OF RELEASED PACKET +; CX = SIZE OF RELEASED PACKET +; AX = ADDRESS OF NEXT PACKET +; +; PACKET IS VALID, RELEASE IT +; +FR02 SUB [SI][%H$CURUSE],CX ; SUBTRACT FROM CURRENT +; +; Is next packet allocated? +; + CMP AX,[SI][%H$MAX] + JAE FR04 ; Next packet is anchor + MOV ES,AX + SEGES + TEST %[H$AVAIL],%1 ; Check allocation flag + JZ FR03 ; Not available +; +; Next packet is available, merge current and next packets +; + SEGES + MOV DX,[H$LEN] ; Get size of packet + TEST DX,DX ; CHECK FOR ZERO + JZ FR03 ; DON'T MERGE WITH ANCHOR + ADD CX,DX ; CX = SIZE OF COMBINATION +; +; ASSIGN FREELIST TO NEW PACKET +; + MOV [SI][%H$FREE],BX +; +; Find the previous packet that is free and closest +; to the packet being released +; + SEGES + MOV AX,[H$SUCC] ; GET NEXT FIELD FOR CURRENT + SEGES + MOV DX,[H$PRED] ; PREV LINK OF NEXT FREE PKT +; +; AT THIS POINT: +; BX = CURRENT PACKET +; AX = NEXT PACKET +; DX = PREVIOUS PACKET +; CX = NEW LENGTH OF CURRENT +; + JMPS FR06 ; CHECK FOR LAST PACKET FREE +; +; Next packet is not available +; find the next packet that is available to get +; its last packet pointer +; AX = NEXT PACKET +; CX = PACKET SIZE +; BX = CURRENT PACKET +; +FR03 SEGES + MOV DX,[H$LEN] ; GET SIZE OF NEXT PACKET + ADD AX,DX + CMP AX,[SI][H$MAX] ; Top of heap? + JB FR05 +FR04 MOV AX,[SI][%H$MIN] ; Wrap around to anchor +FR05 MOV ES,AX + SEGES + TEST %[H$AVAIL],%1 ; CHECK FOR ALLOCATED + JZ FR03 ; LOOP UNTIL FREE +; +; AX and SI now point to the next free packet +; get the last pointer from the next packet +; + SEGES + MOV DX,[H$PRED] +; +; At this point: +; AX = next free packet +; BX = current packet +; CX = current packet length +; DX = last packet +; +; Check last packet. If the last free packet is contiguous +; with the current packet, they can be merged into a single +; packet. +; +FR06 PUSH AX ; SAVE + MOV ES,DX + SEGES + MOV AX,[H$LEN] ; Length of previous pkt + ADD AX,DX ; AX <-- LAST+SIZE(LAST) + CMP AX,BX + JNZ FR07 ; CAN NOT JOIN +; +; The last packet is contiguous with the current packet, +; merge them. +; + SEGES + ADD [H$LEN],CX ; Add lengths + POP AX + SEGES + MOV [H$SUCC],AX ; Set pointer to next + MOV ES,AX + SEGES + MOV [H$PRED],DX ; Set Next@.last to merged pkt +; +; Set free list to merged packet +; + MOV [SI][%H$FREE],DX + XOR AX,AX + POP BP + RETFAR +; +; +; The last packet is not contiguous with the current packet +; a new packet is created for the packet being released. +; +; TOS = NEXT +; BX = CURRENT +; DX = PREVIOUS +; CX = LENGTH +; +FR07 MOV ES,BX + SEGES + MOV [H$LEN],CX ; SET SIZE + SEGES + MOV %[H$AVAIL],%1 + POP AX + SEGES + MOV [H$SUCC],AX ; SET NEXT POINTER + SEGES + MOV [H$PRED],DX ; SET PREVIOUS + MOV ES,DX + SEGES + MOV [H$SUCC],BX ; SET PREV@.NEXT + MOV ES,AX + SEGES + MOV [H$PRED],BX ; SET NEXT@.LAST + XOR AX,AX + POP BP + RETSEG +; +; INVALID PACKET POINTER +; +INVPKT MOV AX,-1 ; Return -1 to indicate error + POP BP + RETSEG + END +; +; ---------------------------------------------------------- +; +; FNEWHEAP +; Allocate a new heap from the pool of extended memory +; called as a C function: +; int fnewheap(size, desc); +; int size; /* size in paragraphs */ +; descriptor *desc; /* address of descriptor */ +; Fills in descriptor with heap parameters. +; A size of >FFFF indicates allocate as much as possible. +; Returns the size allocated, 0 if none. +; + IDT fnewheap + IF UPPER + DEF FNEWHEAP + ENDIF + DEF fnewheap + DREF $$MAXSEG ; First unavailable paragraph + DREF $$TOPSEG ; First unused paragraph +fnewheap EQU $ +FNEWHEAP PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM2] ; SI = Address of descriptor + MOV CX,[BP][%PARM1] ; CX = requested size + CMP CX,MINHEAP + JAE SIZESET + MOV CX,MINHEAP ; Set minimum size +SIZESET CMP CX,-1 ; Allow for anchor & final blk + JZ MAXSIZE + ADD CX,%2 ; Allow for anchor & final blk +MAXSIZE MOV AX,[$$TOPSEG] ; First unused data + MOV DX,[$$MAXSEG] ; Top of all memory + CMP AX,DX + JAE NOSPACE + SUB DX,AX ; Total size available + CMP CX,DX + JBE ENOUGH ; requested size is available + CMP DX,MINHEAP + JB NOSPACE + MOV CX,DX ; Supply all remaining +ENOUGH ADD [$$TOPSEG],CX ; Add size to top segment + MOV [SI][%H$MIN],AX ; Set heap bounds + MOV DX,[$$TOPSEG] + DEC DX + MOV [SI][%H$MAX],DX + MOV [SI][%H$CURUSE],0 + MOV [SI][%H$MAXUSE],0 + MOV DX,AX ; Point to heap origin + INC AX ; AX points to free space area + MOV [SI][%H$FREE],AX +; +; Create the heap anchor +; + MOV BX,DS + MOV DS,DX ; Point to anchor + MOV %[H$AVAIL],%1 ; Anchor is available + MOV [H$LEN],0 ; Length of packet is 0 + MOV [H$SUCC],AX ; Cicrular link to 2nd packet + MOV [H$PRED],AX ; Cicrular link to 2nd packet + MOV DS,AX + MOV %[H$AVAIL],%1 + SUB CX,%2 ; Remove size of anchor + MOV [H$LEN],CX + MOV [H$SUCC],DX ; Cicrular link to anchor packet + MOV [H$PRED],DX ; Cicrular link to anchor packet + MOV DS,BX +EXIT POP BP + MOV AX,CX + RETSEG +NOSPACE XOR AX,AX ; Return 0 for none available + JMPS EXIT + END +; +; ---------------------------------------------------------- +; +; FRELHEAP +; Release a heap to the pool of extended memory +; called as a C function: +; int frelheap(desc); +; descriptor *desc; /* address of descriptor */ +; Releases heap if it is the last item in extended memory. +; Returns 0 if released, -1 if not at end of memory. +; + IDT frelheap + IF UPPER + DEF FRELHEAP + ENDIF + DEF frelheap + DREF $$MAXSEG ; First unavailable paragraph + DREF $$TOPSEG ; First unused paragraph +frelheap EQU $ +FRELHEAP PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] ; SI = Address of descriptor + MOV CX,[SI][H$MAX] ; Top of this heap + INC CX ; Address expected in $$TOPSEG + CMP CX,[$$TOPSEG] ; Is this the top item? + JNZ NOTLAST + MOV CX,[SI][%H$MIN] ; Release to minimum + MOV [$$TOPSEG],CX + XOR AX,AX + MOV [SI],AX + POP BP + RETSEG +NOTLAST MOV AX,-1 + POP BP + RETSEG + END +; +; ---------------------------------------------------------- +; +; Shrink memory to allow loading other programs and +; for memory resident programs. +; +; int farsetsize(int farheap_needed) +; one argument, amount of far heap requested +; in paragraphs +; Returns address of top of memory (segment) +; + IDT farsetsz + IF LONGNAME + LDEF farsetsize + ENDIF + IF SHORTNAM + def Fsetsize + ENDIF + REF $$PSP + REF $$TOPSEG + REF $$ENDDS + REF $$MAXSEG + REF $$FARHP + REF _doserrno + FREF _FHIGH +; +farsetsize EQU $ +Fsetsize PUSH BP + MOV BP,SP + MOV DX,[BP][%PARM1] + ADD DX,[$$ENDDS] ; Requested top of memory + CMP DX,[$$MAXSEG] ; More than available? + JAE DONE + CMP DX,[$$TOPSEG] ; More than allocated? + JAE SHRINK ; Shrink to size + CMP [$$FARHP],0 ; Far heap in use? + JZ DONE ; No, unable to shrink + MOV SI,$$FARHP + MOV CX,[SI][H$MAX] ; Top of this heap + INC CX ; Address expected in $$TOPSEG + CMP CX,[$$TOPSEG] ; Is this the top item? + JNZ DONE ; Far heap is not top item + PUSH SI + CALLFAR _FHIGH ; find top packet + POP SI + TEST AX,AX + JZ DONE ; No free space in far heap + SUB AX,2 ; header of last free block + MOV DX,AX + MOV ES,AX + MOV CX,[BP][%PARM1] + ADD CX,[$$ENDDS] ; Requested top of memory + CMP CX,DX + JBE MINIMUM ; shrink to minimum size + SUB CX,AX ; space to keep + ADD DX,CX + MOV [SI][%H$MAX],DX + SEGES + MOV [H$LEN],CX + INC DX + JMPS SHRINK +MINIMUM INC DX + MOV [SI][%H$MAX],DX + INC DX + SEGES + MOV [H$LEN],1 +; +; Shrink memory and update system parameters +; DX = top segment +; +SHRINK MOV [$$MAXSEG],DX + CMP DX,[$$TOPSEG] + JAE K1 + MOV [$$TOPSEG],DX +K1 MOV BX,DX + SUB BX,[$$PSP] ; Size in use + MOV ES,[$$PSP] ; Shrink memory + SEGES + MOV [2],DX + MOV AX,>4A00 + INT >21 + JB ERROR +DONE MOV AX,[$$MAXSEG] ; Total program size + SUB AX,[$$PSP] + POP BP + RETFAR +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETFAR + END +; +; ---------------------------------------------------------- +; +; _FMAX +; find the address of free memory +; int _FMAX() +; returns segment address of first usable paragraph +; in extended memory. If the default far heap is at +; the top of memory, any unused part of it is available. +; + IDT _FMAX + DEF _FMAX + DREF $$FARHP + DREF $$TOPSEG + FREF _FHIGH +_FMAX MOV SI,$$FARHP + CMP [SI],0 + JZ USEMEM + MOV CX,[SI][H$MAX] ; Top of this heap + INC CX ; Address expected in $$TOPSEG + CMP CX,[$$TOPSEG] ; Is this the top item? + JNZ USEMEM + PUSH SI + CALLFAR _FHIGH + POP SI + TEST AX,AX + JZ USEMEM + ADD AX,2 ; Preserve packet header + RETSEG +USEMEM MOV AX,[$$TOPSEG] + RETSEG + END +; +; ---------------------------------------------------------- +; +; _FHIGH +; find highest address currently in use +; called as a C function: +; int _FHIGH(desc) +; int size; /* size in bytes */ +; returns address of highest packet or 0 if none +; + IDT _FHIGH + DEF _FHIGH +_FHIGH PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] ; SI = Address of descriptor + MOV BX,[SI][%H$FREE] ; Search free space list +SRCH MOV ES,BX + SEGES + MOV AX,[H$LEN] ; Length of packet + ADD AX,BX ; End of packet + CMP AX,[SI][%H$MAX] ; Does it go to end? + JAE FOUND + SEGES + MOV BX,[H$SUCC] ; Try next packet + CMP BX,[SI][%H$FREE] ; full circle? + JNZ SRCH + XOR AX,AX ; Return 0 for none available + POP BP + RETSEG +; +; Highest block has been found +; return its address +; First available paragraph is two greater +; +FOUND ADD BX,%2 + MOV AX,BX + POP BP + RETSEG + END +; +; ---------------------------------------------------------- +; +; Default far heap data area +; contains descriptor for far heap +; + IDT $$FARHP + DDEF $$FARHP + DORG $ +$$FARHP DW 0,0,0,0,0 + END diff --git a/Mix Power C v1/FARMEM.ASM b/Mix Power C v1/FARMEM.ASM new file mode 100644 index 0000000..5c7ea0d --- /dev/null +++ b/Mix Power C v1/FARMEM.ASM @@ -0,0 +1,374 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; farrepmem(address,data,datasize, copies) +; fill memory with copies of a template +; ------------------------------------------------------- +; + IDT farrepmem + IF LONGNAME + LDEF farrepmem + ENDIF + IF SHORTNAME + DEF Frepmem + ENDIF +; +farrepmem equ $ +Frepmem PUSH BP + MOV BP,SP + MOV DX,[BP][%PARM6] ; number of copies + TEST DX,DX + JZ DONE + MOV CX,[BP][%PARM5] ; size of block + JCXZ DONE + MOV DI,[BP][%PARM1] ; address of data + MOV ES,[BP][%PARM2] + CLD + PUSH DS + MOV DS,[BP][%PARM4] +FILL MOV SI,[BP][%PARM3] ; pattern data + MOV CX,[BP][%PARM5] ; size of block + REP + MOVSB + DEC DX + JNZ FILL + POP CX + MOV DS,CX +DONE POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farmemcpy(destination, source, n) - move block of memory +; does not test for overlapping blocks +; size is limited to 64k +; does not check for segment wrap arround +; ------------------------------------------------------- +; + IDT farmemcpy + IF LONGNAME + LDEF farmemcpy + ENDIF + IF SHORTNAME + DEF Fmemcpy + ENDIF +farmemcpy equ $ +Fmemcpy PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM5] + JCXZ DONE + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + PUSH DS + MOV SI,[BP][%PARM3] + MOV DS,[BP][%PARM4] + CLD + REP + MOVSB + POP AX + MOV DS,AX +DONE MOV AX,[BP][%PARM1] ; Result is ptr to dest + MOV DX,[BP][%PARM2] + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farmemmove(destination, source, n) - move block of memory +; checks for overlapping blocks +; size is limited to 64k +; ------------------------------------------------------- +; + IDT farmemmove + IF LONGNAME + LDEF farmemmove + ENDIF + IF SHORTNAME + DEF Fmemmove + ENDIF +farmemmove equ $ +Fmemmove PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM5] + JCXZ DONE + MOV DI,[BP][%PARM2] ; dest segment + MOV SI,[BP][%PARM4] ; src segment + XOR AX,AX + XOR DX,DX + MOV CX,4 ; convert to 20 bit +SHIFT1 SHL DI,1 + RCL DX,1 + SHL SI,1 + RCL AX,1 + LOOP SHIFT1 + ADD DI,[BP][%PARM1] ; dest offset + ADC DX,0 + ADD SI,[BP][%PARM3] ; src offset + ADC AX,0 + CMP DX,AX + JB DSTLOWER + JA SRCLOWER + CMP DI,SI + JB DSTLOWER + JA SRCLOWER +DONE MOV AX,[BP][%PARM1] ; Result is ptr to dest + MOV DX,[BP][%PARM2] + POP BP + RETFAR +DSTLOWER CLD + MOV CX,[BP][%PARM5] + XOR BX,BX + JMPS MOVE +SRCLOWER STD + MOV CX,[BP][%PARM5] + MOV BX,CX + DEC BX ; length - 1 +MOVE PUSH SI + PUSH DI + MOV CX,4 +SHIFT2 SHR DX,1 ; Normalize pointers + RCR DI,1 + SHR AX,1 + RCR SI,1 + LOOP SHIFT2 + MOV DX,DI + MOV AX,SI + POP DI + AND DI,>F + POP SI + AND SI,>F + ADD DI,BX + ADC DX,0 + ADD SI,BX + ADC AX,0 + MOV ES,DX + PUSH DS + MOV DS,AX + MOV CX,[BP][%PARM5] + REP + MOVSB + POP AX + MOV DS,AX + CLD + JMPS DONE + END +; +; ------------------------------------------------------- +; farmemswap(addr1, addr2, n) - swap two blocks of memory +; ------------------------------------------------------- +; + IDT farmemswap + IF LONGNAME + LDEF farmemswap + ENDIF + IF SHORTNAME + DEF Fmemswap + ENDIF +; +farmemswap equ $ +Fmemswap MOV BX,SP + PUSH DS + MOV SI,[BX][%PARM1-2] + MOV DS,[BX][%PARM2-2] + MOV DI,[BX][%PARM3-2] + MOV ES,[BX][%PARM4-2] + MOV CX,[BX][%PARM5-2] + JCXZ DONE + CLD +SWAP SEGES + MOV AL,[DI] + XCHG AL,[SI] + STOSB + INC SI + LOOP SWAP +DONE POP AX + MOV DS,AX + RETSEG + END +; +; ------------------------------------------------------- +; farmemset(addr, value, count) - fill a block with character +; ------------------------------------------------------- +; + IDT farmemset + IF LONGNAME + LDEF farmemset + ENDIF + IF SHORTNAME + DEF Fmemset + ENDIF +; +farmemset equ $ +Fmemset MOV BX,SP + MOV DI,[BX][%PARM1-2] + MOV ES,[BX][%PARM2-2] + MOV AX,[BX][%PARM3-2] + MOV CX,[BX][%PARM4-2] + JCXZ DONE + CLD + REP + STOSB +DONE RETSEG + END +; +; ------------------------------------------------------- +; farmemccpy(dest, src, c, cnt) - copy up to & including c +; ------------------------------------------------------- +; + IDT farmemccpy + IF LONGNAME + LDEF farmemccpy + ENDIF + IF SHORTNAME + DEF Fmemccpy + ENDIF +; +farmemccpy equ $ +Fmemccpy PUSH BP + MOV BP,SP + PUSH DS + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + MOV SI,[BP][%PARM3] + MOV DS,[BP][%PARM4] + MOV DX,[BP][%PARM5] + MOV CX,[BP][%PARM6] + JCXZ ENDCOUNT + CLD +COPY LODSB + STOSB + CMP AL,DL + JZ FOUND + LOOP COPY +ENDCOUNT XOR AX,AX ; Return null if c not copied +EXIT POP CX + MOV DS,CX + POP BP + RETSEG +FOUND MOV AX,DI ; return address of next after c + JMPS EXIT + END +; +; ------------------------------------------------------- +; farmemchr(buf, c, cnt) - search for c in buffer +; ------------------------------------------------------- +; + IDT farmemchr + IF LONGNAME + LDEF farmemchr + ENDIF + IF SHORTNAME + DEF Fmemchr + ENDIF +; +farmemchr equ $ +Fmemchr PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + MOV AX,[BP][%PARM3] + MOV CX,[BP][%PARM4] + CLD + REPNZ + SCASB + JNZ NOFIND + DEC DI + MOV AX,DI ; Return pointer to c in buf + POP BP + RETSEG +NOFIND XOR AX,AX ; Return null if not found + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farmemcmp(buf1, buf2, cnt) - compare memory +; ------------------------------------------------------- +; + IDT farmemcmp + IF LONGNAME + LDEF farmemcmp + ENDIF + IF SHORTNAME + DEF Fmemcmp + ENDIF +; +farmemcmp equ $ +Fmemcmp PUSH BP + MOV BP,SP + PUSH DS + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM2] + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,[BP][%PARM5] +COMPARE JCXZ EQUAL + CLD + REPZ + CMPSB + JZ EQUAL + MOV AL,[SI][%-1] + SEGES + SUB AL,[DI][%-1] + CBW +EXIT POP CX + MOV DS,CX + POP BP + RETSEG +EQUAL XOR AX,AX ; Return 0 if buffers are equal + JMPS EXIT + END +; +; ------------------------------------------------------- +; farmemicmp(buf1, buf2, cnt) - compare memory +; ------------------------------------------------------- +; + IDT farmemicmp + IF LONGNAME + LDEF farmemicmp + ENDIF + IF SHORTNAME + DEF Fmemicmp + ENDIF +; +farmemicmp equ $ +Fmemicmp PUSH BP + MOV BP,SP + PUSH DS + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM2] + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,[BP][%PARM5] + JCXZ EQUAL + CLD +MATCH REPZ + CMPSB + JZ EQUAL + MOV AL,[SI][%-1] + SEGES + MOV AH,[DI][%-1] + CMP AL,'a' + JB X1 + CMP AL,'z' + JA X1 + SUB AL,>20 +X1 CMP AH,'a' + JB X2 + CMP AH,'z' + JA X2 + SUB AH,>20 +X2 CMP AL,AH + JZ MATCH + MOV AL,[SI][%-1] + SEGES + SUB AL,[DI][%-1] + CBW +EXIT POP CX + MOV DS,CX + POP BP + RETSEG +EQUAL XOR AX,AX + JMPS EXIT + END diff --git a/Mix Power C v1/FARSTR.ASM b/Mix Power C v1/FARSTR.ASM new file mode 100644 index 0000000..6be7e2a --- /dev/null +++ b/Mix Power C v1/FARSTR.ASM @@ -0,0 +1,1045 @@ +; +; Copyright (c) Mix Software 1988 +; +; ============================================================ +; Far string functinos +; ============================================================ +; +; ------------------------------------------------------- +; farstrcat(string1, string2) - concatenate strings +; farstrncat(string1, string2, n) - concatenate strings +; ------------------------------------------------------- +; + IDT farstrcat + IF LONGNAME + LDEF farstrcat + LDEF farstrncat + ENDIF + IF SHORTNAME + DEF Fstrcat + DEF Fstrncat + ENDIF +; +farstrcat equ $ +Fstrcat PUSH BP + MOV BP,SP + MOV CX,-1 ; no limit on length +CAT PUSH DS + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + MOV SI,[BP][%PARM3] + MOV DS,[BP][%PARM4] + CLD + XOR AX,AX + PUSH CX + MOV CX,-1 + REPNZ ; search for zero on string 1 + SCASB + POP CX + DEC DI ; overwrite the '\0' terminator +COPY LODSB + STOSB + TEST AL,AL + JZ DONE + LOOP COPY + MOV %[DI],%0 +DONE POP AX + MOV DS,AX + MOV AX,[BP][%PARM1] ; result is pointer to string1 + MOV DX,ES + POP BP + RETSEG +farstrncat equ $ +Fstrncat PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM5] ; cx = limit on length + JCXZ DONE + JMPS CAT + END +; +; ------------------------------------------------------- +; farstrchr(string1, c) - search string for character +; ------------------------------------------------------- +; char *farstrchr(s, c) +; char far *s; +; int c; +; +; Purpose: Searches for first occurrence of c in s +; Returns: Pointer to c if s contains c +; NULL if s does not contain c +; +; + IDT farstrchr + IF LONGNAME + LDEF farstrchr + ENDIF + IF SHORTNAME + DEF Fstrchr + ENDIF +; +Fstrchr equ $ +farstrch PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ + SCASB + NOT CX ; CX = length including '\0' + MOV DI,[BP][%PARM1] + MOV AL,[BP][%PARM3] + REPNZ + SCASB + JNZ NOFIND + DEC DI + MOV AX,DI + MOV DX,ES + POP BP + RETSEG +NOFIND XOR AX,AX + XOR DX,DX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farstrrchr(string, c) - search string for last occurance of c +; ------------------------------------------------------- +; + IDT farstrrchr + IF LONGNAME + LDEF farstrrchr + ENDIF + IF SHORTNAME + DEF Fstrrchr + ENDIF +; +farstrrchr equ $ +Fstrrchr PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + CLD + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; find end of string + SCASB + NOT CX + STD + MOV DI,[BP][%PARM1] + ADD DI,CX + DEC DI + MOV AX,[BP][%PARM3] + REPNZ + SCASB + CLD + JZ FOUND + XOR AX,AX + XOR DX,DX + POP BP + RETSEG +FOUND INC DI ; Return pointer to c + MOV AX,DI + MOV DX,ES + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farstrncmp(string1, string2,n) - compare strings +; ------------------------------------------------------- +; + IDT farstrncmp + IF LONGNAME + LDEF farstrncmp + ENDIF + IF SHORTNAME + DEF Fstrncmp + ENDIF +; +farstrncmp equ $ +Fstrncmp MOV BX,SP + MOV CX,[BX][%PARM5-2] + JCXZ EQUAL + PUSH DS + MOV SI,[BX][%PARM1-2] + MOV DI,[BX][%PARM3-2] + MOV ES,[BX][%PARM4-2] + MOV DS,[BX][%PARM2-2] + MOV DX,DI + XOR AX,AX + MOV BX,CX + CLD + REPNZ ; search for zero on string 1 + SCASB + NEG CX + ADD CX,BX + MOV DI,DX + REPZ + CMPSB + MOV AL,%[SI][%-1] + SEGES + SUB AL,%[DI][%-1] + CBW + POP CX + MOV DS,CX + RETSEG +EQUAL XOR AX,AX + RETSEG + END +; +; +; ------------------------------------------------------- +; farstrcmp(string1, string2) - compare strings +; ------------------------------------------------------- +; + IDT farstrcmp + IF LONGNAME + LDEF farstrcmp + ENDIF + IF SHORTNAME + DEF Fstrcmp + ENDIF +; +farstrcmp equ $ +Fstrcmp MOV BX,SP + PUSH DS + MOV SI,[BX][%PARM1-2] + MOV DI,[BX][%PARM3-2] + MOV ES,[BX][%PARM4-2] + MOV DS,[BX][%PARM2-2] + CLD + MOV DX,DI + XOR AX,AX + MOV CX,-1 + REPNZ ; search for zero on string 1 + SCASB + INC CX + NEG CX + MOV DI,DX + REPZ + CMPSB + MOV AL,%[SI][%-1] + SEGES + SUB AL,%[DI][%-1] + CBW + POP CX + MOV DS,CX + RETSEG + END +; +; ------------------------------------------------------- +; farstrcmpi(string1, string2) - compare strings, ignore case +; ------------------------------------------------------- +; + IDT farstrcmpi + IF LONGNAME + LDEF farstrcmpi + LDEF farstrnicmp + ENDIF + IF SHORTNAME + DEF Fstrcmpi + DEF Fstrnicm + ENDIF +farstrcmpi equ $ +Fstrcmpi EQU $ + PUSH BP + MOV BP,SP + PUSH DS + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM2] + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,-1 +CMP LODSB + SEGES + MOV BL,[DI] + INC DI + TEST AL,AL ; end of string1? + JZ END1 + TEST BL,BL + JZ END1 + CMP AL,BL + JNZ NOTEQUAL +NEXT LOOP CMP +EQUAL XOR AX,AX ; strings are equal + POP CX + MOV DS,CX + POP BP + RETSEG +END1 XOR AH,AH ; end of both? + XOR BH,BH + SUB AX,BX + POP CX + MOV DS,CX + POP BP + RETSEG +NOTEQUAL CMP AL,'A' + JB NOTAL + CMP AL,'Z' + JA NOTAL + ADD AL,'a'-'A' +NOTAL CMP BL,'A' + JB NOTBL + CMP BL,'Z' + JA NOTBL + ADD BL,'a'-'A' +NOTBL CMP AL,BL + JZ NEXT + MOV AL,[SI][%-1] + SEGES + MOV BL,[DI][%-1] + JMPS END1 +; +farstrnicmp equ $ +Fstrnicm PUSH BP + MOV BP,SP + PUSH DS + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM2] + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,[BP][%PARM5] + JCXZ EQUAL + JMPS CMP + END +; +; ------------------------------------------------------- +; farstrcpy(string1, string2) - copy strings +; ------------------------------------------------------- +; + IDT farstrcpy + IF LONGNAME + LDEF farstrcpy + ENDIF + IF SHORTNAME + DEF Fstrcpy + ENDIF +; +farstrcpy equ $ +Fstrcpy MOV BX,SP + MOV SI,[BX][%PARM3-2] + MOV DI,SI + MOV ES,[BX][%PARM4-2] + MOV CX,-1 + XOR AX,AX + CLD + REPNZ + SCASB + NOT CX + MOV DI,[BX][%PARM1-2] + MOV ES,[BX][%PARM2-2] + MOV DX,DS + MOV DS,[BX][%PARM4-2] + MOV AX,DI + REP + MOVSB + MOV DS,DX + MOV DX,ES + RETSEG + END +; +; ------------------------------------------------------- +; farstrncpy(string1, string2, n) - copy string +; copy exactly n characters from string2 to string1 +; if n < length of string2, no null is appended +; if n > length of string2, string1 padded with '\0' +; ------------------------------------------------------- +; + IDT farstrncpy + IF LONGNAME + LDEF farstrncpy + ENDIF + IF SHORTNAME + DEF Fstrncpy + ENDIF +; +farstrncpy equ $ +Fstrncpy PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + MOV DX,DS + MOV DS,[BP][%PARM2] + MOV SI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,[BP][%PARM5] + JCXZ DONE + CLD +COPY LODSB + STOSB + TEST AL,AL + JZ ENDSTR + LOOP COPY +DONE MOV DS,DX + MOV DX,ES + MOV AX,[BP][%PARM1] + POP BP + RETSEG +ENDSTR DEC CX + JCXZ DONE + XOR AX,AX + REP + STOSB + JMPS DONE + END +; +; ------------------------------------------------------- +; int farstrspn(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches from beginning of s1 +; until a character NOT in s2 is found +; Returns: Length of string segment in s1 consisting +; entirely of characters contained in s2 +; ------------------------------------------------------- +; + IDT farstrspn + IF LONGNAME + LDEF farstrspn + ENDIF + IF SHORTNAME + DEF Fstrspn + ENDIF +; +farstrspn equ $ +Fstrspn PUSH BP + MOV BP,SP + PUSH DS + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM2] + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NOT CX + MOV BX,CX + XOR DX,DX ; initial index + JCXZ DONE +NEXTCH LODSB + TEST AL,AL + JZ DONE + MOV CX,BX + MOV DI,[BP][%PARM3] + REPNZ + SCASB + JNZ DONE + INC DX + JMPS NEXTCH +DONE MOV AX,DX + POP DX + MOV DS,DX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; int farstrcspn(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches from beginning of s1 +; until a character in s2 is found +; Returns: Length of string segment in s1 consisting +; entirely of characters NOT contained in s2 +; ------------------------------------------------------- +; + IDT farstrcspn + IF LONGNAME + LDEF farstrcspn + ENDIF + IF SHORTNAME + DEF Fstrcspn + ENDIF +; +farstrcspn equ $ +Fstrcspn PUSH BP + MOV BP,SP + PUSH DS + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM1] + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NOT CX + MOV BX,CX + XOR DX,DX ; initial index + JCXZ DONE +NEXTCH LODSB + TEST AL,AL + JZ DONE + MOV CX,BX + MOV DI,[BP][%PARM3] + REPNZ + SCASB + JZ DONE + INC DX + JMPS NEXTCH +DONE MOV AX,DX + POP DX + MOV DS,DX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; int farstrpbrk(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches from beginning of s1 +; until a character in s2 is found +; Returns: pointer to first character found +; ------------------------------------------------------- +; + IDT farstrpbrk + IF LONGNAME + LDEF farstrpbrk + ENDIF + IF SHORTNAME + DEF Fstrpbrk + ENDIF +; +farstrpbrk equ $ +Fstrpbrk PUSH BP + MOV BP,SP + PUSH DS + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM2] + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NOT CX + MOV BX,CX + JCXZ DONE +NEXTCH LODSB + TEST AL,AL + JZ NONE + MOV CX,BX + MOV DI,[BP][%PARM3] + REPNZ + SCASB + JZ DONE + JMPS NEXTCH +DONE DEC SI + MOV AX,SI +EXIT POP DX + MOV DS,DX + POP BP + RETSEG +NONE XOR AX,AX + JMPS EXIT + END +; +; ------------------------------------------------------- +; farstrrev(string) - reverse a string +; ------------------------------------------------------- +; + IDT farstrrev + IF LONGNAME + LDEF farstrrev + ENDIF + IF SHORTNAME + DEF Fstrrev + ENDIF +; +farstrrev equ $ +Fstrrev PUSH BP + MOV BP,SP + MOV DX,DS + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; find end of string + SCASB + SUB DI,%2 + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM2] +REV CMP SI,DI + JAE DONE + MOV AL,%[DI] + XCHG AL,%[SI] + MOV %[DI],AL + INC SI + DEC DI + JMPS REV +DONE MOV AX,[BP][%PARM1] + MOV DX,[BP][%PARM2] + MOV DS,DX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farstrsave(string) - copy to heap, NULL if no space +; farstrdup(string) - copy to heap, NULL if no space +; ------------------------------------------------------- +; + IDT farstrdup + IF LONGNAME + LDEF farstrdup + LDEF farstrsave + LFREF farmalloc + ENDIF + IF SHORTNAME + DEF Fstrdup + DEF Fstrsave + FREF Fmalloc + ENDIF +farstrdup equ $ +farstrsave equ $ +Fstrsave EQU $ +Fstrdup PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + TEST DI,DI + JZ NULL + MOV ES,[BP][%PARM2] + MOV CX,-1 + XOR AX,AX + CLD + REPNZ ; get length of string2 + SCASB + NEG CX + PUSH CX + PUSH AX + PUSH CX + IF LONGNAME + callfar farmalloc + ENDIF + IF SHORTNAME&(~LONGNAME) + callfar Fmalloc + ENDIF + ADD SP,%4 + POP CX + TEST AX,AX ; Null? + JNZ OK1 + TEST DX,DX + JZ NULL +OK1 MOV DI,AX + MOV ES,DX + MOV SI,[BP][%PARM1] + MOV DX,DS + MOV DS,[BP][%PARM2] + REP + MOVSB +DONE MOV DS,DX + MOV DX,ES + POP BP + RETSEG +NULL XOR AX,AX + XOR DX,DX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farstrlwr(string) - convert all uppercase letters in +; string to lower case +; ------------------------------------------------------- +; + IDT farstrlwr + IF LONGNAME + LDEF farstrlwr + ENDIF + IF SHORTNAME + DEF Fstrlwr + ENDIF +; +farstrlwr equ $ +Fstrlwr PUSH BP + MOV BP,SP + MOV BX,DS + MOV SI,[BP][%PARM1] + MOV DX,[BP][%PARM2] + MOV DS,DX + CLD +CHECK MOV AL,%[SI] + TEST AL,AL + JZ DONE + CMP AL,'A' + JB OK + CMP AL,'Z' + JA OK + ADD AL,'a'-'A' + MOV %[SI],AL +OK INC SI + JMPS CHECK +DONE MOV DS,BX + MOV AX,[BP][%PARM1] + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farstrupr(string) - convert all lower case letters in +; string to upper case +; ------------------------------------------------------- +; + IDT farstrupr + IF LONGNAME + LDEF farstrupr + ENDIF + IF SHORTNAME + DEF Fstrupr + ENDIF +; +farstrupr equ $ +Fstrupr PUSH BP + MOV BP,SP + MOV BX,DS + MOV SI,[BP][%PARM1] + MOV DX,[BP][%PARM2] + MOV DS,DX +CHECK MOV AL,%[SI] + TEST AL,AL + JZ DONE + CMP AL,'a' + JB OK + CMP AL,'z' + JA OK + ADD AL,'A'-'a' + MOV %[SI],AL +OK INC SI + JMPS CHECK +DONE MOV DS,BX + MOV AX,[BP][%PARM1] + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; farstrset(string,c) - set all but '\0' to c +; farstrnset(string,c,n) - set up to n or '\0' to c +; ------------------------------------------------------- +; + IDT farstrset + IF LONGNAME + LDEF farstrset + LDEF farstrnset + ENDIF + IF SHORTNAME + DEF Fstrset + DEF Fstrnset + ENDIF +farstrset equ $ +Fstrset PUSH BP + MOV BP,SP + MOV CX,-1 ; no limit on length +SET MOV DX,DS + MOV SI,[BP][%PARM1] + MOV DS,[BP][%PARM2] + MOV BX,[BP][%PARM3] +NEXT MOV AL,%[SI] + TEST AL,AL + JZ DONE + MOV %[SI],BL + INC SI + LOOP NEXT +DONE MOV DS,DX +DONE1 MOV AX,[BP][%PARM1] ; result is pointer to string1 + MOV DX,[BP][%PARM2] + POP BP + RETSEG +farstrnset equ $ +Fstrnset PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM4] ; cx = limit on length + JCXZ DONE1 + JMPS SET + END +; +; ------------------------------------------------------- +; int farstrlen(s) +; char *s; +; Purpose: Returns the length of the string, not +; including the NULL character +; ------------------------------------------------------- +; + IDT farstrlen + IF LONGNAME + LDEF farstrlen + ENDIF + IF SHORTNAME + DEF Fstrlen + ENDIF +farstrlen equ $ +Fstrlen MOV BX,SP + MOV DI,[BX][%PARM1-2] + MOV ES,[BX][%PARM2-2] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NOT CX + DEC CX + MOV AX,CX + RETSEG + END +; +; ------------------------------------------------------- +; int farstrstr(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches s1 for the first occurrence +; of s2 +; Returns: pointer to substring if found, +; NULL if not found +; ------------------------------------------------------- +; + IDT farstrstr + IF LONGNAME + LDEF farstrstr + ENDIF + IF SHORTNAME + DEF Fstrstr + ENDIF +; +farstrstr equ $ +Fstrstr PUSH BP + MOV BP,SP + PUSH DS + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ + SCASB + NOT CX + DEC CX + MOV DX,CX ; DX is length of s1 + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,-1 + REPNZ + SCASB + NOT CX + DEC CX ; CX is length of s2 + CMP CX,DX + JA NOFIND ; s2 is longer than s1 + MOV AX,[BP][%PARM1] ; initial s1 pointer + MOV ES,[BP][%PARM2] + MOV DS,[BP][%PARM4] + JCXZ FOUND ; length of s2 is zero + MOV BX,CX ; save s2 length + SUB DX,BX ; number of positions to try + INC DX +NEXTPOS MOV CX,BX ; length of s2 + MOV SI,[BP][%PARM3] ; start of s2 + MOV DI,AX ; current position in s1 + REPZ + CMPSB ; compare + JZ FOUND ; strings match + INC AX ; try next position + DEC DX + JNZ NEXTPOS +NOFIND XOR AX,AX + XOR DX,DX +FOUND POP CX + MOV DS,CX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; int farstristr(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches s1 for the first occurrence +; of s2 (case is ignored) +; Returns: pointer to substring if found, +; NULL if not found +; ------------------------------------------------------- +; + IDT farstristr + IF LONGNAME + LDEF farstristr + ENDIF + IF SHORTNAME + DEF Fstristr + ENDIF +; +farstristr equ $ +Fstristr PUSH BP + MOV BP,SP + SUB SP,%2 + PUSH DS + MOV DI,[BP][%PARM1] + MOV ES,[BP][%PARM2] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ + SCASB + NOT CX + DEC CX + MOV DX,CX ; DX is length of s1 + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + MOV CX,-1 + REPNZ + SCASB + NOT CX + DEC CX ; CX is length of s2 + CMP CX,DX + JA NOFIND ; s2 is longer than s1 + MOV AX,[BP][%PARM1] ; initial s1 pointer + MOV ES,[BP][%PARM2] + MOV DS,[BP][%PARM4] ; s2 segment + JCXZ FOUND ; length of s2 is zero + MOV BX,CX ; save s2 length + SUB DX,BX ; number of positions to try + INC DX + MOV [BP][%-2],DX +NEXTPOS MOV CX,BX ; length of s2 + MOV SI,[BP][%PARM3] ; start of s2 + MOV DI,AX ; current position in s1 +COMP REPZ + CMPSB ; compare + JZ FOUND ; strings match + MOV DL,[SI][%-1] + SEGES + MOV DH,[DI][%-1] + AND DX,>DFDF + CMP DL,DH + JNZ TRYNXT + CMP DL,'A' + JB TRYNXT + CMP DL,'Z' + JA TRYNXT + JCXZ FOUND + JMPS COMP +TRYNXT INC AX ; try next position + DEC [BP][%-2] + JNZ NEXTPOS +NOFIND XOR AX,AX + XOR DX,DX +FOUND POP CX + MOV DS,CX + MOV SP,BP + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; char *farstrtok(s1, s2) +; char far *s1, far *s2; +; +; Purpose: Searches for the beginning of the next token +; in s1. A token is a sequence of one or more +; characters in s1 separated from the next token +; by a sequence of one or more characters contained +; in s2. S1 must point to a string of tokens for +; the first call to strtok. Subsequent calls +; can specify a NULL value for s1 to return the next +; token in the string. +; +; Returns: Pointer to next token in s1 +; NULL if there are no more tokens in s1 +; ------------------------------------------------------- +; + IDT farstrtok + IF LONGNAME + LDEF farstrtok + ENDIF + IF SHORTNAME + DEF Fstrtok + ENDIF +; + DORG 0 +STRPTR DW 0-0 +STRSEG DW 0-0 + ORG $ +farstrtok equ $ +Fstrtok PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM3] + MOV ES,[BP][%PARM4] + CLD + MOV CX,-1 + XOR AL,AL + REPNZ + SCASB ; Find length of s2 + NOT CX + JCXZ NOS2 ; Return null if s2 is empty + MOV DX,CX ; save length of s2 + PUSH DS + MOV SI,[BP][%PARM1] + MOV AX,[BP][%PARM2] + TEST SI,SI ; is s1 null? + JNZ NOTNULL + TEST AX,AX + JNZ NOTNULL + MOV SI,[STRPTR] + TEST SI,SI + JZ EMPTY ; no previous string + MOV AX,[STRSEG] + JZ EMPTY +NOTNULL MOV DS,AX +NEXTCH LODSB ; get s1 character + TEST AL,AL + JZ EMPTY ; end of s1 + MOV CX,DX + MOV DI,[BP][%PARM3] + REPNZ + SCASB ; check in delimiter set + JZ NEXTCH + MOV BX,SI ; address of first non-delimiter + DEC BX +TOKCH LODSB + TEST AL,AL + JZ ENDS1 + MOV CX,DX + MOV DI,[BP][%PARM3] + REPNZ + SCASB + JNZ TOKCH ; not a delimiter + MOV [STRPTR],SI + MOV [STRSEG],DS + MOV %[SI][%-1],%0 ; terminate token + MOV AX,BX + MOV DX,DS + POP CX + MOV DS,CX + POP BP + RETSEG +EMPTY XOR AX,AX + MOV [STRPTR],AX + XOR DX,DX + MOV [STRSEG],AX + POP CX + MOV DS,CX + POP BP + RETSEG +NOS2 MOV CX,[BP][%PARM1] + MOV [STRPTR],CX + MOV CX,[BP][%PARM2] + MOV [STRSEG],CX + XOR AX,AX + XOR DX,DX + POP BP + RETSEG +ENDS1 MOV AX,BX + MOV DX,DS + MOV [STRPTR],0 + MOV [STRSEG],0 + POP CX + MOV DS,CX + POP BP + RETSEG + END diff --git a/Mix Power C v1/FARSTR1.ASM b/Mix Power C v1/FARSTR1.ASM new file mode 100644 index 0000000..a11d3d8 --- /dev/null +++ b/Mix Power C v1/FARSTR1.ASM @@ -0,0 +1,97 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------------ + IDT _fmemcpy + DEF _fmemcpy + IF UPPER + DEF _FMEMCPY + ENDIF +; ------------------------------------------------------------ +; +; char far *_fmemcpy(dest, source, n) +; char far *dest, far *source; +; unsigned n; +; +; Purpose: Copies n characters from source to dest +; Returns: dest +; +; TOS --> RETURN ADDR. OFFSET +; RETURN ADDR. SEGMENT +; SIZE SIZE (UNSIGNED) +; SOURCE SOURCE (FAR *) +; DEST DEST (FAR *) +; +DESTOFF EQU 4+2 +DESTSEG EQU DESTOFF+2 +SRCOFF EQU DESTSEG+2 +SRCSEG EQU SRCOFF+2 +SIZE EQU SRCSEG+2 + SETCPU 8086 +_fmemcpy +_FMEMCPY PUSH BP + MOV BP,SP + MOV CX,[BP][%SIZE] + JCXZ DONE + PUSH DS + MOV AX,[BP][%SRCSEG] + MOV BX,[BP][%DESTSEG] + MOV SI,[BP][%SRCOFF] + MOV DI,[BP][%DESTOFF] + CMP AX,BX + JNE SKIP + CMP SI,DI + JGE SKIP + ADD SI,CX + DEC SI + ADD DI,CX + DEC DI + STD +SKIP: MOV DS,AX + MOV ES,BX + REP + MOVSB + CLD + POP AX + MOV DS,AX +DONE: MOV DX,[BP][%DESTSEG] + MOV AX,[BP][%DESTOFF] + POP BP + RETSEG + END +; +; ------------------------------------------------------------ + IDT _fstrlen ;RETURN LENGTH OF FAR STRING + DEF _fstrlen + IF UPPER + DEF _FSTRLEN + ENDIF +; ------------------------------------------------------------ +; +; int _fstrlen(s) +; char far *s; +; +; Purpose: Find length of string s +; Returns: length of string s +; +; TOS --> RETURN (far *) +; S (far *) +; +SOFFSET EQU 4 +SSEGMENT EQU SOFFSET+2 +; + SETCPU 8086 +_fstrlen +_FSTRLEN MOV BX,SP + MOV DI,[BX][%SOFFSET] + MOV ES,[BX][%SSEGMENT] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NOT CX + DEC CX + MOV AX,CX + RETSEG + END diff --git a/Mix Power C v1/FATAL.ASM b/Mix Power C v1/FATAL.ASM new file mode 100644 index 0000000..8b6b16c --- /dev/null +++ b/Mix Power C v1/FATAL.ASM @@ -0,0 +1,47 @@ +; +; Fatal error processor +; Copyright (c) Mix Software 1988 +; +; Generates a message to stderr and terminates. +; + IDT $_FATAL + DEF $_FATAL + FREF _exit + DREF errno +$_FATAL PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] ; fetch error code + MOV DX,AX + AND AX,>000F + CMP AL,9 + JLE DIGIT + ADD AL,7 +DIGIT ADD AL,'0' + MOV %[DIG0],AL + MOV CL,4 + SHR DL,CL + AND DL,>0F + CMP DL,9 + JLE DIGIT2 + ADD DL,7 +DIGIT2 ADD DL,'0' + MOV %[DIG1],DL + MOV DX,ERRMSG + MOV AX,>4000 + MOV BX,2 + MOV CX,MSGLEN + INT >21 + PUSH [errno] + CALLFAR _exit + POP DX + POP BP + RETFAR +; + DORG 0 +ERRMSG DB 'Fatal error #' +DIG1 DB '0' +DIG0 DB '0' + DB >0D,>0A +MSGLEN EQU $-ERRMSG +; + END diff --git a/Mix Power C v1/FCNTL.H b/Mix Power C v1/FCNTL.H new file mode 100644 index 0000000..e4b6604 --- /dev/null +++ b/Mix Power C v1/FCNTL.H @@ -0,0 +1,15 @@ +/*$no list*//*$no trace <<< fcntl.h >>> */ +/* Copyright (c) Mix Software 1988 */ + +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_APPEND 0x0008 +#define O_CREAT 0x0100 +#define O_TRUNC 0x0200 +#define O_EXCL 0x0400 +#define O_TEXT 0x4000 +#define O_BINARY 0x8000 +#define O_MODEMASK 0x00F3 + +/*$list*//*$trace <<< fcntl.h >>> */ diff --git a/Mix Power C v1/FDB.H b/Mix Power C v1/FDB.H new file mode 100644 index 0000000..b65f8f6 --- /dev/null +++ b/Mix Power C v1/FDB.H @@ -0,0 +1,33 @@ + typedef struct { + char init; /* initialized flag */ + char openflg; /* file open */ + int handle; /* file handle */ + char *bufr; /* start of buffer */ + char *ptr; /* address of next character */ + int count; /* number of characters left in bufr */ + int bufsize; /* size of buffer */ + int reclen; /* record length */ + char device; /* device code */ + char eofflag; /* end of file detected */ + char mode; /* read, write or read/write */ + char dirty; /* buffer written to */ + char error; /* error code */ + char flags; /* control flags */ + char column; /* column (text files */ + char ungetch; /* character from ungetc (unbuffered files) */ + char *gpbufr; /* buffer used by get & put */ + char *pathnm; /* name of file */ + char flag2; /* more flags */ + char fill2[5]; + } fdb; + +#define fdbinary 0x02 +#define fdctlz 0x04 +#define fdfilter 0x08 +#define fdecho 0x10 +#define fdunbufr 0x20 +#define fdappend 0x40 +#define fdsetbuf 0x80 +#define fdwrite 0x01 +#define fdread 0x02 +#define fd2temp 0x01 diff --git a/Mix Power C v1/FILE.C b/Mix Power C v1/FILE.C new file mode 100644 index 0000000..6786eff --- /dev/null +++ b/Mix Power C v1/FILE.C @@ -0,0 +1,344 @@ + +/* File manipulation */ +/* Copyright (c) Mix Software 1988 */ + +int access(pathname, mode) /* can file be accessed in this mode */ + char *pathname; /* name of file */ + int mode; /* mode 02 = write, 04 = read, 06 = r/w, 00 = exists */ +{ + extern int errno; + int curmode; + if (_sysacdc(0x4300, 0, pathname, &curmode) == 0) { + if (curmode & 0x0001) { /* file is read only */ + if ((mode & 0x0002) == 0) return 0; + errno = EACCES; + return -1; + } + return 0; + } + errno = ENOENT; + return -1; + } + +/* ------------------------------------------------------------ */ + +int chmod(pathname, pmode) + char *pathname; + int pmode; +{ + extern int errno; + int mode = 0; + if (pmode & S_IWRITE) mode = 1; + if (_sys_acd(0x4300, 0, pathname, &mode) == 0) return 0; + errno = ENOENT; + return -1; + } + +/* ------------------------------------------------------------ */ + +int eof(fd) + int fd; +{ + extern int errno; + if ((fd < 0) || (fd >= MAXFILES)) { errno = EBADF; return -1; } + return feof(_iob[fd]); +} + +/* ------------------------------------------------------------ */ + +int feof(fp) + FILE *fp; +{ + int c; + extern int errno; + if (fp == NULL) { errno = EBADF; return -1; } + if (fp->file.eofflag) return 1; + c = _getc(fp); + ungetc(c,fp); + if ((fp->file.flags & fdctlz)) { + if (c == CTLZ) return 1; + } + if (c == EOF) { + if ((fp->file.flags & fdfilter) || fp->file.eofflag) return 1; + } + return 0; + } + +/* ------------------------------------------------------------ */ + +getchar() { return fgetc(stdin); } +fgetchar() { return fgetc(stdin); } + +/* ------------------------------------------------------------ */ + +getc(fp) + FILE *fp; +{ return fgetc(fp); } + +/* ------------------------------------------------------------ */ + +putchar(c) int c; { return fputc(c,stdout); } +fputchar(c) int c; { return fputc(c,stdout); } + +/* ------------------------------------------------------------ */ + +putc(c,fp) + int c; + FILE *fp; +{ + return fputc(c,fp); + } + +/* ------------------------------------------------------------ */ + +write(fd, bufptr, n) + int n; + int fd; + char *bufptr; +{ + return _write(_iob[fd],bufptr,n); + } + +/* ------------------------------------------------------------ */ + +fflush(fp) +FILE *fp; +{ + int fseek(); + return fseek(fp, 0L, 1); +} + +/* ------------------------------------------------------------ */ + +flushall() { + int fd; + int count = 0; + int fseek(); + for (fd = 5; fd < MAXFILES; fd++) { + if (_iob[fd] != NULL) { + if (fseek(_iob[fd],0L,1) == 0) count++; + } + } + return count; +} + +/* ------------------------------------------------------------ */ + +rewind(fp) +FILE *fp; +{ + clearerr(fp); + return fseek(fp, 0L, 0); +} + +/* ------------------------------------------------------------ */ + +int chsize(fd, size) + int fd; + long size; +{ + extern int errno, _doserrno; + long lseek(); + long cursize, clear, here; + int st, writesize; + int zero[256]; + int handle = _iob[fd]->file.handle; + if (fd < 0 || fd > MAXFILES) { + errno = EBADF; + return -1L; + } + here = lseek(fd,0l,1); + cursize = lseek(fd,0l,2); + if (cursize > size) { /* truncate to requested length */ + lseek(fd,size,0); + if (_sysabcd(0x4000,handle,0,0,&st) != 0) { + errno = _doserrno; + return -1; + } + } + else { /* extend file by filling with zero */ + memset(zero,0,sizeof(zero)); + clear = size-cursize; + while (clear != 0) { + writesize = (clear > sizeof(zero)) ? sizeof(zero) : clear; + if (_sysabcd(0x4000,handle,writesize,zero,&st) != 0) { + errno = _doserrno; + return -1; + } + if (st != writesize) { + errno = ENOSPC; + return -1; + } + clear -= writesize; + } + } + lseek(fd,here,0); + return 0; + } + +/* ------------------------------------------------------------ */ + +long filelength(fd) + int fd; +{ + long _fseek(); + long here, len; + extern int errno; + if (fd < 0 || fd > MAXFILES) { + errno = EBADF; + return -1L; + } + here = _fseek(_iob[fd],0L,1); + if (here == -1L) { + errno = EBADF; + return -1L; + } + len = _fseek(_iob[fd],0L,2); + _fseek(_iob[fd],here,0); + return len; +} + +/* ------------------------------------------------------------ */ + +long lseek(fd, offset, origin) + int fd; + long offset; + int origin; +{ + long _fseek(); + return _fseek(_iob[fd],offset,origin); + } + +/* ------------------------------------------------------------ */ + +clearerr(fp) +FILE *fp; +{ + union REGS r; + fp->file.error = '\0'; + fp->file.eofflag = '\0'; + r.x.ax = 0x4400; + r.x.bx = fp->file.handle; + r.x.dx = 0; + intdos(&r,&r); + if (r.x.cflag) return; + if ((r.x.dx & 0x80) != 0) { + /* clear eof flag for character device */ + r.h.dh = 0; + r.h.dl |= 0x40; + r.x.ax = 0x4401; + intdos(&r,&r); + } +} + +/* ------------------------------------------------------------ */ + +ferror(fp) +FILE *fp; +{ + return fp->file.error; +} + +/* ------------------------------------------------------------ */ + +fileno(fp) +FILE *fp; +{ + return fp->fd; +} + +/* ------------------------------------------------------------ */ + +long tell(fd) + int fd; +{ + extern int errno; + long ftell(); + if ((fd < 0) || (fd >= MAXFILES) || (_iob[fd] == NULL)) + { errno = EBADF; return -1; } + return ftell(_iob[fd]); +} + +/* ------------------------------------------------------------ */ + +int fgetpos(fp, pos) + FILE *fp; + long *pos; +{ + long ftell(), position; + position = ftell(fp); + if (position == -1) return -1; + *pos = position; + return 0; +} + +/* ------------------------------------------------------------ */ + +int fsetpos(fp,pos) + FILE *fp; + long *pos; +{ + int fseek(); + return fseek(fp, *pos, 0); +} + +/* ------------------------------------------------------------ */ + +int setmode(fd, mode) + int fd; + int mode; +{ + FILE *fp; + int oldmode; + extern int errno; + if ((fd < 0) || (fd >= MAXFILES) || (_iob[fd] == NULL)) + { errno = EBADF; return -1; } + fp = _iob[fd]; + oldmode = fp->file.flags; + if (mode == O_TEXT) fp->file.flags = oldmode | fdfilter; + else if (mode == O_BINARY) fp->file.flags = oldmode & (~fdfilter); + else { errno = EINVAL; return -1; } + if (oldmode & fdfilter) return O_TEXT; else return O_BINARY; +} + +/* ------------------------------------------------------------ */ + +int getw(fp) + FILE *fp; +{ + struct twobyte { + unsigned char lower; + unsigned char upper; + }; + union { + int word; + struct twobyte bytes; + } value; + int c; + if ((c = fgetc(fp)) == EOF) return EOF; + value.bytes.lower = c; + if ((c = fgetc(fp)) == EOF) return EOF; + value.bytes.upper = c; + return value.word; +} + +/* ------------------------------------------------------------ */ + +int putw(binint,fp) + int binint; + FILE *fp; +{ + struct twobyte { + unsigned char lower; + unsigned char upper; + }; + union { + int word; + struct twobyte bytes; + } value; + value.word = binint; + if (fputc(value.bytes.lower,fp) == EOF) return EOF; + if (fputc(value.bytes.upper,fp) == EOF) return EOF; + return binint; +} + diff --git a/Mix Power C v1/FILLM.ASM b/Mix Power C v1/FILLM.ASM new file mode 100644 index 0000000..d977ed5 --- /dev/null +++ b/Mix Power C v1/FILLM.ASM @@ -0,0 +1,519 @@ +; +; Copyright (c) Mix Software 1988 +; +; void _fill_pm(border_color) +; fill a region with a pattern. +; Uses direct access to the screen memory. +; For cga modes 4, 5, and 6 and (hercules monochrome). +; _vxcurs, _vycurs = current coordinate. +; Fill pattern is described by _vf_pat, _vf_wid and _vf_hgt. +; + idt _fill_pm + def _fill_pm + dref _vapage ; active page + dref _vmaxh ; window limits + dref _vminh + dref _vmode + dref _vmaxv + dref _vminv + dref _v_color ; pen color + dref _vxcurs ; current cursor column + dref _vycurs ; current cursor row + dref _vf_pat ; address of fill pattern + dref _vf_wid ; width of fill pattern + dref _vf_hgt ; height of fill pattern + dref $$MAXS + fref $_STKCHK + fref getvmode + fref crt_lock + lfref crt_unlock +CGAHIGH equ 6 +CGALOW equ 4 +CGALOWBW equ 5 +; +; local variables +; +chain equ >0 ; state structure for next level +cy equ 0 ; offsets at next level +cminx equ 2 +cmaxx equ 4 +cnext equ 6 +chainy equ chain+cy ; current y coordinate +minx equ chain+cminx ; minimum x coordinate +maxx equ chain+cmaxx ; minimum x coordinate +lastptr equ chain+cnext ; address of previous frame +local equ lastptr+2 +; +; parameters +; +x equ 4+local +y equ 6+local +previous equ 8+local +bordcol equ 4 +; +; +_fill_pm callfar crt_lock + mov bx,sp + mov ax,[bx][%bordcol] + mov [border],ax ; save border color + mov [bits],1 ; bits per pixel + mov [fill],l1fill ; fill for 1 bit per pixel + callfar getvmode + cmp ax,HERCMODE + jnz notherc + mov [where],whereh ; pointer to address calculation + mov dx,>b000 ; set base address to active page + cmp %[_vapage],0 + jz pageset + mov dx,>b800 ; page 1 +pageset mov es,dx + jmps callfill +notherc mov dx,>b800 ; memory base for cga + mov es,dx + cmp ax,CGAHIGH + jnz nothigh + mov [where],where6 ; address calculation for mode 6 + jmps callfill +nothigh cmp ax,CGALOW + jz lowres + cmp ax,CGALOWBW + jnz badmode +lowres mov [where],where4 ; address calculation function + mov [bits],2 ; 2 bits per pixel + mov [fill],l2fill ; multi-bit fill function +callfill xor ax,ax + push ax ; null previous block list + push [_vycurs] ; starting position + push [_vxcurs] + call fill_m + callfar crt_unlock + add sp,%6 + xor ax,ax + retfar +badmode callfar crt_unlock + mov ax,-1 + retfar +; +fill_m push bp + sub sp,local + cmp sp,[$$MAXS] ; check for stack overflow + jnb noflo + callfar $_STKCHK +noflo mov bp,sp + mov ax,[bp][%y] + xor dx,dx + div [_vf_hgt] ; dx = y mod _vf_hgt + mov ax,dx + mul [_vf_wid] ; ax = offset to row of pattern + add ax,[_vf_pat] + mov [xstart],ax ; start of pattern row + mov bx,ax + add ax,[_vf_wid] + mov [xlimit],ax ; end of pattern row + mov ax,[bp][%x] + xor dx,dx + div [_vf_wid] ; dx = x mod _vf_wid + add bx,dx ; bx = initial pattern pointer + mov [patptr],bx +; +; compute memory address and bit mask for (x,y) +; + call [where] + mov [memaddr],si + mov [bitmask],ax + mov dx,[bp][%x] + mov bx,[patptr] + call [fill] +; + mov ax,[bp][%y] ; values for use by next level + mov [bp][%chainy],ax + mov ax,[bp][%previous] + mov [bp][%lastptr],ax +; +; scan lines above and below for unfilled areas +; + dec [bp][%y] + call scan + add [bp][%y],%2 + call scan + mov ax,[bp][%maxx] + lea sp,[bp][%local] + pop bp + ret +; +; scan a line from (minx+1,y) to (maxx-1,y) +; for any group with a non-border pixel +; check whether visited before and if not, make +; recursive call to fill the line. +; +scan mov ax,[bp][%y] + cmp ax,[_vminv] ; check y for boundary + jb scandone + cmp ax,[_vmaxv] + ja scandone + mov dx,[bp][%minx] + inc dx + mov [bp][%x],dx + call [where] ; get screen memory address + mov dx,[bp][%x] +scannxt cmp dx,[bp][%maxx] + jae scandone + seges + mov ch,%[si] ; read group of pixels + and ch,ah ; select one + cmp ch,al ; compare to border color + jz scaninc ; border color, skip +; ; search for previously visited + mov cx,[bp][%y] + mov bx,[bp][%previous] +srch test bx,bx + jz nextline ; not done before + cmp cx,[bx] ; same value of y? + jnz nextsrch + cmp dx,[bx][%cminx] + jle nextsrch ; not in range + cmp dx,[bx][%cmaxx] + jge nextsrch + mov dx,[bx][%cmaxx] ; skip this region + dec dx + mov [bp][%x],dx + call [where] + mov dx,[bp][%x] + jmps scaninc +nextsrch mov bx,[bx][%cnext] + jmps srch +nextline lea ax,[bp][%chain] ; call for next line + push ax ; link record + push [bp][%y] + push dx + call fill_m + add sp,%6 + mov dx,ax + mov [bp][%x],dx + call [where] + mov dx,[bp][%x] +scaninc inc dx ; next x + mov cl,[bits] + ror al,cl + ror ah,cl ; move to next pixel + jnc nocarry3 + inc si ; first pixel in next byte +nocarry3 jmp scannxt ; find next region +scandone ret +; +; fill dots to the left until boundary or window edge +; Special version for 1 bit per pixel +; bx is the pattern pointer +; dx is the value of x +; es:si is the screen address +; ah is the bit mask +; al is the border color +; +; sets minx and maxx to the edges of the area +; +l1fill cmp dx,[_vminh] + jl l1done + seges + mov ch,[si] ; read 8 dots + mov cl,ch + and cl,ah + cmp cl,al + jz l1done + mov cl,%[bx] ; color of pattern + cmp cl,TRANSPAR ; if transparent, do not set + jz l1next + cmp cl,PENCOLOR ; use pen color + jnz l1set2 + mov cl,%[_v_color] +l1set2 test cl,%1 + jz l1clr + or ch,ah ; set the pixel to 1 + jmps l1put +l1clr not ah + and ch,ah ; set the pixel to 0 + not ah +l1put seges + mov %[si],ch +l1next dec dx ; decrease x coordinate + rol al,1 ; border color to next bit + rol ah,1 ; move to next bit + jnc l1nc + dec si ; last bit in previous byte +l1nc dec bx ; move back one in pattern + cmp bx,[xstart] + jae l1fill + mov bx,[xlimit] ; move to end of pattern + dec bx + jmps l1fill +l1done mov [bp][%minx],dx +; + mov dx,[bp][%x] + mov si,[memaddr] + mov ax,[bitmask] + mov bx,[patptr] + jmps r1next +; +r1fill cmp dx,[_vmaxh] + ja r1done + seges + mov ch,[si] ; read 8 dots + mov cl,ch + and cl,ah + cmp cl,al + jz r1done + mov cl,%[bx] ; color of pattern + cmp cl,TRANSPAR ; if transparent, do not set + jz r1next + cmp cl,PENCOLOR ; use pen color + jnz r1set2 + mov cl,%[_v_color] +r1set2 test cl,%1 + jz r1clr + or ch,ah ; set the pixel to 1 + jmps r1put +r1clr not ah + and ch,ah ; set the pixel to 0 + not ah +r1put seges + mov %[si],ch +r1next inc dx ; increase x coordinate + ror al,1 + ror ah,1 ; move to next bit + jnc r1nc + inc si ; first bit in next byte +r1nc inc bx ; move forward one in pattern + cmp bx,[xlimit] + jnz r1fill + mov bx,[xstart] ; move to end of pattern + jmps r1fill +r1done mov [bp][%maxx],dx + ret +; +; fill dots to the left until boundary or window edge +; Each pixel is 2 bits +; bx is the pattern pointer +; dx is the value of x +; es:si is the screen address +; ah is the bit mask +; al is the border color +; +; sets minx and maxx to the edges of the area +; +l2fill mov di,bx +l2fill0 cmp dx,[_vminh] + jl l2done + seges + mov ch,[si] ; read 4 dots + mov cl,ch + and cl,ah ; isolate this pixel + cmp cl,al + jz l2done ; border color + mov bl,%[di] ; color of pattern + cmp bl,TRANSPAR ; if transparent, do not set + jz l2next + cmp bl,PENCOLOR ; use pen color + jnz l2set2 + mov bl,%[_v_color] +l2set2 and bl,3 + mov cl,dl ; x coordinate + and cl,%3 ; mask bit number + neg cl + add cl,3 + jz l2noshf + add cl,cl ; number of shifts needed + shl bl,cl ; shift color into position +l2noshf not ah + and ch,ah ; mask previous contents + not ah + or ch,bl ; load new color value + seges + mov %[si],ch +l2next dec dx ; decrease x coordinate + rol al,1 ; border color to next position + rol al,1 + rol ah,1 ; move to next pixel + rol ah,1 + jnc l2nc + dec si ; last bit in previous byte +l2nc dec di ; move back one in pattern + cmp di,[xstart] + jae l2fill0 + mov di,[xlimit] ; move to end of pattern + dec di + jmps l2fill0 +l2done mov [bp][%minx],dx +; + mov dx,[bp][%x] + mov si,[memaddr] + mov ax,[bitmask] + mov di,[patptr] + jmps r2next +; +r2fill cmp dx,[_vmaxh] + ja r2done + seges + mov ch,[si] ; read 4 dots + mov cl,ch + and cl,ah + cmp cl,al + jz r2done + mov bl,%[di] ; color of pattern + cmp bl,TRANSPAR ; if transparent, do not set + jz r2next + cmp bl,PENCOLOR ; use pen color + jnz r2set2 + mov bl,%[_v_color] +r2set2 and bl,3 + mov cl,dl ; x coordinate + and cl,3 ; mask bit number + neg cl + add cl,3 + jz r2noshf + add cl,cl ; number of shifts needed + shl bl,cl ; shift color into position +r2noshf not ah + and ch,ah ; mask previous contents + not ah + or ch,bl ; load new color value + seges + mov %[si],ch +r2next inc dx ; increase x coordinate + ror al,1 + ror al,1 + ror ah,1 ; move to next bit + ror ah,1 + jnc r2nc + inc si ; first pixel in next byte +r2nc inc di ; move forward one in pattern + cmp di,[xlimit] + jnz r2fill + mov di,[xstart] ; move to end of pattern + jmps r2fill +r2done mov [bp][%maxx],dx + ret +; +; compute address and bit mask for a pixel (Hercules) +; inputs: +; [bp][y] = y coordinate +; [bp][x] = x coordinate +; outputs: +; si = memory address +; ah = bit mask +; al = border color +; cx, dx are altered +; +whereh mov ax,[bp][%y] + mov si,ax + and si,>0003 + mov cl,13 + shl si,cl ; (y % 4) * 0x2000 + mov cl,2 + shr ax,cl ; y/4 + shl ax,1 ; (y/4) * 0x02 + add si,ax + shl ax,cl ; (y/4) * 0x08 + add si,ax + shl ax,1 ; (y/4) * 0x10 + add si,ax + shl ax,cl ; (y/4) * 0x40 + add si,ax + mov ax,[bp][%x] + mov cx,ax + shr ax,1 ; x/8 + shr ax,1 + shr ax,1 + add si,ax + and cx,>0007 ; x % 8 + mov ah,>80 + mov al,[border] + ror al,1 + jcxz noshifth + shr ax,cl +noshifth ret +; +; compute address and bit mask for a pixel (cga mode 6) +; inputs: +; [bp][y] = y coordinate +; [bp][x] = x coordinate +; outputs: +; si = memory address +; ah = bit mask +; al = border color +; cx is altered +; +where6 mov ax,[bp][%y] + mov si,ax + and si,>0001 + mov cl,13 + shl si,cl ; (y % 2) * 0x2000 + shr ax,1 ; y/2 + mov cl,4 + shl ax,cl ; (y/2) * 0x10 + add si,ax + shl ax,1 + shl ax,1 ; ax = (y/2) * 0x40 + add si,ax + mov ax,[bp][%x] + mov cx,ax + shr ax,1 ; x/8 + shr ax,1 + shr ax,1 + add si,ax + and cx,>0007 ; x % 8 + mov ah,>80 + mov al,[border] + ror al,1 + jcxz noshift6 + shr ax,cl +noshift6 ret +; +; compute address and bit mask for a pixel (cga mode 4 or 5) +; inputs: +; [bp][y] = y coordinate +; [bp][x] = x coordinate +; outputs: +; si = memory address +; ah = bit mask +; al = border color +; cx is altered +; +where4 mov ax,[bp][%y] + mov si,ax + and si,>0001 + mov cl,13 + shl si,cl ; (y % 2) * 0x2000 + shr ax,1 ; y/2 + mov cl,4 + shl ax,cl ; (y/2) * 0x10 + add si,ax + shl ax,1 + shl ax,1 ; ax = (y/2) * 0x40 + add si,ax + mov ax,[bp][%x] + mov cx,ax + shr ax,1 ; x/4 + shr ax,1 + add si,ax + and cx,>0003 ; x % 4 + mov ah,>C0 + mov al,[border] + ror al,1 + ror al,1 + jcxz noshift4 + shr ax,cl + shr ax,cl +noshift4 ret +; +; local static variables +; + dorg 0 +xstart dw 0-0 ; beginning of line of fill pattern +xlimit dw 0-0 ; end of line of fill pattern +memaddr dw 0-0 ; address of pixel in memory +bitmask dw 0-0 ; bit position of pixel +patptr dw 0-0 ; initial fill pattern pointer +border dw 0-0 ; border color +bits dw 0-0 ; number of bits per pixel +where dw 0-0 ; address calculation function +fill dw 0-0 ; fill current line function + end diff --git a/Mix Power C v1/FINDFIRS.C b/Mix Power C v1/FINDFIRS.C new file mode 100644 index 0000000..6d44202 --- /dev/null +++ b/Mix Power C v1/FINDFIRS.C @@ -0,0 +1,38 @@ +/* Directory searching functions */ +/* Copyright (c) Mix Software 1988 */ + +struct ffblk { + char ff_reserved[21]; /* used by dos */ + char ff_attrib; /* attributes of the file */ + int ff_ftime; /* time file last modified */ + int ff_fdate; /* date file last modified */ + long ff_fsize; /* size of file */ + char ff_name[13]; /* name of file (xxxxxxxx.yyy) */ + }; + +int findfirst(pathname, ffblk, attrib) + char *pathname; + struct ffblk *ffblk; + int attrib; +{ + extern int errno; + extern int _doserrno; + int stat; + _sys_ad(0x1a00,ffblk,&stat); /* set dma address */ + if (_sys_acd(0x4e00,attrib,pathname,&stat) == 0) return 0; + errno = _doserrno; + return -1; + } + +int findnext(ffblk) + struct ffblk *ffblk; +{ + extern int errno; + extern int _doserrno; + int stat; + _sys_ad(0x1a00,ffblk,&stat); /* set dma address */ + if (_sys_ad(0x4f00,0,&stat) == 0) return 0; + errno = _doserrno; + return -1; + } + diff --git a/Mix Power C v1/FLAGS.C b/Mix Power C v1/FLAGS.C new file mode 100644 index 0000000..95181d1 --- /dev/null +++ b/Mix Power C v1/FLAGS.C @@ -0,0 +1,104 @@ +/* Flag setting functions */ +/* Copyright (c) Mix Software 1988 */ + +conbuf(flag) +int flag; +{ + int oldflag; + extern char $$UBCON; + oldflag = $$UBCON; + $$UBCON = flag; + return oldflag; +} + +mathtrap(flag) +int flag; +{ + int oldflag; + extern char $$ARTERM; + extern char _mathmsg; + oldflag = $$ARTERM; + $$ARTERM = flag; + _mathmsg = flag; + return oldflag; +} + +char _mathmsg = 0; + +filetrap(flag) +int flag; +{ + int oldflag; + extern char $$IOTERM; + oldflag = $$IOTERM; + $$IOTERM = flag; + return oldflag; +} + +heaptrap(flag) +int flag; +{ + int oldflag; + extern char $$HPTERM; + oldflag = $$HPTERM; + $$HPTERM = flag; + return oldflag; +} + +iofilter(linefeed, ctrlz) +int linefeed, ctrlz; +{ + extern char $$CLFEED; + extern char $$CCTLZ; + $$CLFEED = linefeed; + $$CCTLZ = ctrlz; +} + +exitmsg() +{ + extern void (*$$EXITPT)(); + void _exitmsg(); + extern void (*_exitptr)(); + if (_exitptr == NULL) { + _exitptr = $$EXITPT; + $$EXITPT = _exitmsg; + } + } + +void _exitmsg() +{ + extern void (*_exitptr)(); + extern unsigned $$BOTTOM, $$MAXS, $$LIMIT, $$MAXH, $$HMAX, $$HMIN; + static char msg[] + = "xxxxx bytes of heap space used, xxxxx bytes free\r\l$"; + static char stk[] + = "xxxxx bytes of stack used, xxxxx bytes free\r\l$"; + char *stkptr; + int x; + stkptr = (char *) $$LIMIT; + while (*stkptr == 0) ++stkptr; + _utoa($$BOTTOM - (unsigned) stkptr,&stk[0]); + _utoa((unsigned) stkptr - $$LIMIT,&stk[27]); + _sys_ad(0x0900,stk,&x); + _utoa($$MAXH,&msg[0]); + _utoa($$HMAX-$$HMIN-$$MAXH,&msg[32]); + _sys_ad(0x0900,msg,&x); + (*_exitptr)(); + } + +void (*_exitptr)() = NULL; + + +_utoa(n, s) /* convert unsigned int to fixed size string */ +unsigned n; /* result is 5 characters, right justified */ +char *s; /* with leading zeros suppressed */ +{ + char *ptr; + setmem(s,5,' '); + ptr = s+4; + do { + *(ptr--) = n % 10 + 0x30; + } while ((n /= 10) > 0); + return s; +} + diff --git a/Mix Power C v1/FLUSH.ASM b/Mix Power C v1/FLUSH.ASM new file mode 100644 index 0000000..63b8de4 --- /dev/null +++ b/Mix Power C v1/FLUSH.ASM @@ -0,0 +1,140 @@ +; +; Copyright (c) Mix Software 1988 +; +; flush output buffer +; +; _fflush(fp) /* write any remaining data from buffer to file */ +; fdb *fp; +; + IDT _fflush + DEF _fflush + FREF _seekend + REF _fileerr +_fflush MOV BX,SP + MOV SI,[BX][%PARM1-2] + TEST %[SI][%FD$DIRTY],%FL$WRITE + JNZ DOWRITE + XOR AX,AX + RETSEG +; +; fp->dirty = 0; +; count = fp->bufsize - fp->count; +; +DOWRITE AND %[SI][%FD$DIRTY],%>FF-FL$WRITE + MOV CX,[SI][%FD$BUFSZ] + SUB CX,[SI][%FD$COUNT] +; +; if (count > 0) { +; + JCXZ DONE +; +; if (_sysabcd(0x4000,fp->handle,count,fp->bufr,&status) != 0) +; (*_fileerr)(status,fp); +; +; Seek to end of file if append mode + TEST [SI][%FD$FLAGS],FL$APPEN + JZ W1 + PUSH DI + PUSH CX + PUSH SI + CALLFAR _seekend + POP SI + POP CX + POP DI +W1 MOV AX,>4000 + MOV BX,[SI][%FD$HNDL] + MOV DX,[SI][%FD$BUFR] + PUSH CX + INT >21 + POP CX + JNB OK +FILEERR PUSH SI + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%4 + MOV AL,[SI][%FD$ERR] + XOR AH,AH + RETSEG +; +; else { +; if (status != count) (*_fileerr)(0x9a,fp); +; else fp->error = 0; +; +OK CMP AX,CX + JNZ DISKFULL + MOV [SI][%FD$COUNT],0 +DONE MOV AX,[SI][%FD$BUFR] + MOV [SI][%FD$PTR],AX + XOR AX,AX + RETSEG +; +DISKFULL MOV AX,E$NOSPAC + JMPS FILEERR + END +; +; +; _rflush(fp) /* postion a read file for writing */ +; FILE *fp; +; + IDT _rflush + DEF _rflush + REF _fileerr +_rflush MOV BX,SP + MOV SI,[BX][%PARM1-2] + TEST %[SI][%FD$DIRTY],%FL$READ + JNZ DOREAD + XOR AX,AX + RETSEG +; +; fp->dirty = 0; +; count = fp->ptr - fp->bufr; +; +DOREAD AND %[SI][%FD$DIRTY],%>FF-FL$READ + MOV CX,[SI][%FD$PTR] + SUB CX,[SI][%FD$BUFR] + MOV [SI][%FD$COUNT],0 +; +; if (count > 0) { +; + JCXZ DONE +; +; if (_sysabcd(0x4201,handle,0,count,&status) != 0) +; return (*_fileerr)(status,fp); } +; return 0; +; + MOV AX,>4201 + MOV BX,[SI][%FD$HNDL] + MOV DX,CX + XOR CX,CX + INT >21 + JB FILEERR +DONE MOV AX,[SI][%FD$BUFR] + MOV [SI][%FD$PTR],AX + XOR AX,AX + RETSEG +FILEERR PUSH SI + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%4 + RETSEG + END +; +; Seek to end of file +; _seekend(fdbptr) +; + IDT _seekend + DEF _seekend +; +_seekend PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV AX,>4202 + XOR CX,CX + XOR DX,DX + MOV BX,[SI][%FD$HNDL] + INT >21 + POP BP + RETSEG + END diff --git a/Mix Power C v1/FREE.ASM b/Mix Power C v1/FREE.ASM new file mode 100644 index 0000000..ee7fdcf --- /dev/null +++ b/Mix Power C v1/FREE.ASM @@ -0,0 +1,219 @@ +; +; -------------------------------------------------- +; free - release a block of heap +; -------------------------------------------------- +; + IDT cfree + DEF cfree + DEF free + DEF _nfree + IF UPPER + DEF CFREE + DEF FREE + ENDIF + FREF $$FREE$$ +; +; free(ptr) - release a block of heap +; +cfree equ $ +CFREE EQU $ +free equ $ +_nfree equ $ +FREE MOV SI,SP + MOV BX,[SI][%PARM1-2] + CALLFAR $$FREE$$ + XOR AX,AX + RETSEG + END +; +; $_FREE(ptr); +; ptr is address of a pointer +; block is released and pointer set to nil +; + IDT $_free + DEF $_FREE + FREF $$FREE$$ +$_FREE PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] ; pointer address + MOV BX,[BX] ; value of pointer + CALLFAR $$FREE$$ + MOV BX,[BP][%PARM1] ; pointer address + MOV [BX],0 + POP BP + RETSEG + END +; +; ------------------------------------------------------------ +; +; FREE$$ +; RELEASE A HEAP PACKET +; INPUTS: +; BX - POINTER TO THE PACKET BEGIN RETURNED +; OUTPUTS: +; NONE +; REGISTERS USED: +; DI, SI, BP ARE PRESERVED +; +; + IDT $$FREE$$ + DEF $$FREE$$ + REF $$HPTERM + FREF $_FATAL + REF $$HMIN + REF $$HMAX + REF $$CURH + REF $$FREE + REF errno +; +; CHECK FOR SIZE, NIL POINTER +; +$$FREE$$ TEST BX,BX + JNZ FREE01 + RETSEG ; NIL - EXIT +FREE01 SUB BX,%2 ; POINT TO LENGTH FIELD +; +; CHECK POINTER AGAINST LOWER BOUND OF HEAP - ERROR IF LESS +; + CMP BX,[$$HMIN] + JB INVPKT +; +; GET LENGTH OF THE PACKET +; +FR01 MOV CX,[BX] + TEST CL,%1 ; CHECK ALLOCATED FLAG + JZ INVPKT ; NOT ALLOCATED + AND CL,%>FE ; RESET ALLOCATION FLAG + MOV AX,BX + ADD AX,CX ; AX POINTS TO NEXT PACKET +; +; CHECK PTR + SIZE OF PACKET AGAINST HEAP UPPER BOUND +; + CMP AX,[$$HMAX] + JA INVPKT +; +; BX = ADDRESS OF RELEASED PACKET +; CX = SIZE OF RELEASED PACKET +; AX = ADDRESS OF NEXT PACKET +; +; PACKET IS VALID, RELEASE IT +; +FR02 SUB [$$CURH],CX ; SUBTRACT FROM CURRENT +; +; IS NEXT PACKET ALLOCATED? +; + MOV DX,BX + MOV BX,AX + TEST [BX],%1 ; CHECK ALLOCATION FLAG + JNZ FR03 ; ALLOCATED +; +; NEXT PACKET IS AVAILABLE, MERGE CURRENT AND NEXT PACKETS +; + MOV AX,[BX] ; GET SIZE OF NEXT PACKET + TEST AX,AX ; CHECK FOR ZERO + JZ FR03 ; DON'T MERGE WITH ANCHOR + ADD CX,AX ; CX = SIZE OF COMBINATION +; +; ASSIGN FREELIST TO NEW PACKET +; + MOV [$$FREE],DX +; +; FIND THE PREVIOUS PACKET THAT IS FREE AND CLOSEST +; TO THE PACKET BEING RELEASED +; + MOV AX,[BX][2] ; GET NEXT FIELD FOR CURRENT + MOV BX,[BX][4] ; PREV LINK OF NEXT FREE PKT +; +; AT THIS POINT: +; DX = CURRENT PACKET +; AX = NEXT PACKET +; BX = PREVIOUS PACKET +; CX = LENGTH OF CURRENT +; + JMPS FR05 ; CHECK FOR LAST PACKET FREE +; +; NEXT PACKET IS NOT AVAILABLE +; FIND THE NEXT PACKET THAT IS AVAILABLE TO GET +; ITS LAST PACKET POINTER +; BX = NEXT PACKET +; CX = PACKET SIZE +; DX = CURRENT PACKET +; +FR03 MOV AX,[BX] ; GET SIZE OF NEXT PACKET + AND AL,%>FE ; REMOVE ALLOCATION FLAG + ADD BX,AX ; POINT TO FOLLOWING + TEST [BX],%1 ; CHECK NEXT PACKET ALLOCATION + JNZ FR03 ; LOOP UNTIL FREE +; +; BX NOW POINTS TO THE NEXT FREE PACKET +; GET THE LAST POINTER FROM THE NEXT PACKET +; + MOV AX,BX + MOV BX,[BX][4] ; GET PREV POINTER +; +; AT THIS POINT: +; AX = NEXT PACKET +; CX = PACKET LENGTH +; DX = CURRENT PACKET +; BX = LAST PACKET +; +; +; CHECK LAST PACKET. IF THE LAST FREE PACKET IS CONTIGUOUS +; WITH THE CURRENT PACKET, THEY CAN BE MERGED INTO A SINGLE +; PACKET. +; +FR05 PUSH AX ; SAVE + MOV AX,[BX] ; LENGTH OF PREVIOUS PKT + ADD AX,BX ; AX <-- LAST+SIZE(LAST) + CMP AX,DX + JNZ FR06 ; CAN NOT JOIN +; +; THE LAST PACKET IS CONTIGUOUS WITH THE CURRENT PACKET, +; MERGE THEM. +; + ADD CX,[BX] ; ADD LENGTHS + MOV [BX],CX ; SET TOTAL LENGTH + POP AX + MOV [BX][2],AX ; SET NEXT PKT POINTER + XCHG BX,AX + MOV [BX][4],AX ; SET NEXT@.LAST TO MERGED PKT +; +; SET FREE LIST TO MERGED PACKET +; + MOV [$$FREE],AX + RETSEG ; DONE +; +; +; THE LAST PACKET IS NOT CONTIGUOUS WITH THE CURRENT PACKET +; A NEW PACKET IS CREATED FOR THE PACKET BEING RELEASED. +; +; TOS = NEXT +; DX = CURRENT +; BX = PREVIOUS +; CX = LENGTH +; +FR06 XCHG BX,DX + MOV [BX],CX ; SET SIZE + POP AX + MOV [BX][2],AX ; SET NEXT POINTER + MOV [BX][4],DX ; SET PREVIOUS + XCHG BX,DX + MOV [BX][2],DX ; SET PREV@.NEXT + MOV BX,AX + MOV [BX][4],DX ; SET NEXT@.LAST +; +; DONE +; +FREEX RETSEG +; +; INVALID PACKET POINTER +; +INVPKT MOV AX,E$PACKET + MOV %[errno],AL + TEST %[$$HPTERM],%>FF + JZ FREEX + PUSH AX + CALLFAR $_FATAL + POP AX + RETSEG + END diff --git a/Mix Power C v1/FSTAT.C b/Mix Power C v1/FSTAT.C new file mode 100644 index 0000000..95c3bef --- /dev/null +++ b/Mix Power C v1/FSTAT.C @@ -0,0 +1,80 @@ +/* File status functions */ +/* Copyright (c) Mix Software 1988 */ + +int fstat(fd, buffer) + int fd; + struct statstr *buffer; +{ + union REGS r; + extern errno; + int stat(); + if ((fd < 0) || (fd >= MAXFILES) || (_iob[fd] == NULL)) + { errno = EBADF; return -1; } + r.x.ax = 0x4400; + r.x.bx = fd; + r.x.cx = 0; + r.x.dx = 0; + intdos(&r,&r); + if (r.x.cflag != 0) {errno = EBADF; return -1;} + if (r.x.ax & 0x80) { /* character device */ + buffer->st_mode = S_IFCHR; + buffer->st_nlink = 1; + buffer->st_dev = fd; + buffer->st_rdev = fd; + return 0; + } + if (stat(_iob[fd]->file.pathnm,buffer) == -1) return -1; + buffer->st_size = filelength(fd); + return 0; +} + +int stat(pathname, buffer) + char *pathname; + struct statstr *buffer; +{ + struct statstru { + char res[21]; + char attr; + unsigned time; + unsigned date; + long size; + char name[13]; + } statbufr; + int status; + unsigned flag; + char *p; + long time; + extern int errno, _doserrno; + extern int daylight; + long _timesec(); + _sys_ad(0x1a00,&statbufr,&status); + if (_sys_acd(0x4e00,0x0016,pathname,&status) != 0) + { errno = _doserrno; return -1; } + buffer->st_size = statbufr.size; + if ((p = strchr(pathname,':')) != NULL) + buffer->st_dev = tolower(*--p) - 'a'; + else buffer->st_dev = _sys_al(0x1900); + buffer->st_rdev = buffer->st_dev; + time = _timesec(((statbufr.date >> 9) & 0x7f) + 1980, + (statbufr.date >> 5) & 0x0f, statbufr.date & 0x1f, + (statbufr.time >> 11) & 0x1f, (statbufr.time >> 5) & 0x3f, + statbufr.time & 0x1f); + if (daylight) time += 3600l; + buffer->st_atime = time; + buffer->st_mtime = time; + buffer->st_ctime = time; + _sysacdc(0x4300,0,pathname,&status); + if (status & 0x0010) flag = S_IFDIR; else flag = S_IFREG; + flag |= S_IREAD; + if ((status & 0x0001) == 0) flag |= S_IWRITE; + if ((stristr(pathname,".EXE") != NULL) || + (stristr(pathname,".COM") != NULL)) flag |= S_IEXEC; + flag |= 0x36; + buffer->st_mode = flag; + buffer->st_ino = 0; + buffer->st_uid = 0; + buffer->st_gid = 0; + buffer->st_nlink = 1; + return 0; +} + diff --git a/Mix Power C v1/GET.ASM b/Mix Power C v1/GET.ASM new file mode 100644 index 0000000..56c6a44 --- /dev/null +++ b/Mix Power C v1/GET.ASM @@ -0,0 +1,245 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------------ +; +; fgetc(fp) +; FILE *fp; +; + IDT fgetc + DEF fgetc + FREF _fflush + FREF _getc +fgetc MOV BX,SP + MOV SI,[BX][%PARM1-2] + TEST SI,SI + JZ ENDFL +; +; if (fp == NULL || !fp->file.init || !fp->file.openflg) return EOF; +; +; TEST SI,SI ; File ok? +; JZ ENDFL +; CMP %[SI][%FD$INIT],%0 +; JZ ENDFL +; CMP %[SI][%FD$OPEN],%0 +; JZ ENDFL +; +; if (fp->file.dirty & fdwrite) { +; } +; + TEST %[SI][%FD$DIRTY],%FL$WRITE + JNZ FLUSH +; +; if (fp->file.count) { +; c = *(fp->file.ptr++); +; fp->file.count--; } +; +NOFLUSH MOV CX,[SI][%FD$COUNT] + JCXZ NEEDMORE + DEC CX + MOV [SI][%FD$COUNT],CX + MOV BX,[SI][%FD$PTR] + MOV AL,[BX] + XOR AH,AH + INC BX + MOV [SI][%FD$PTR],BX +; +; if (fp->file.flags & fdbinary) return c; +; +OK TEST %[SI][%FD$FLAGS],%FL$BIN + JNZ DONE +; +; while (c == RETURN && (fp->file.flags & fdfilter)) c = _getc(fp); +; +NOTBIN TEST %[SI][%FD$FLAGS],%FL$LFEED + JZ NOTCR +NEXTCR CMP AX,>000D + JNZ NOTCR + PUSH SI + CALLFAR _getc + POP SI + JMPS NEXTCR +; +; if (c == 0x1a && (fp->file.flags & fdctlz)) return EOF; +; +NOTCR CMP AX,>001A + JNZ NOTCTLZ + TEST %[SI][%FD$FLAGS],%FL$CTLZ + JZ NOTCTLZ +ENDFL MOV AX,-1 + RETFAR +; +; else return c; +; +DONE EQU $ +NOTCTLZ RETFAR +; +; else c = _getc(fp); +; +NEEDMORE PUSH SI + CALLFAR _getc + POP SI + JMPS OK +; +; if (_fflush(fp) != 0) return EOF; +; +FLUSH PUSH SI + CALLFAR _fflush + POP SI + TEST AX,AX + JNZ ENDFL + JMPS NOFLUSH + END +; +; ------------------------------------------------------------ +; _getc(fp) +; FILE *fp; +; + IDT _getc + DEF _getc + REF $$UBCON + REF _fileerr +_getc MOV BX,SP + MOV SI,[BX][%PARM1-2] +; +; if (fp->file.count--) return *(fp->file.ptr++); +; + MOV CX,[SI][%FD$COUNT] + JCXZ NEEDMORE + DEC CX + MOV [SI][%FD$COUNT],CX + MOV BX,[SI][%FD$PTR] + MOV AL,[BX] + XOR AH,AH + INC BX + MOV [SI][%FD$PTR],BX + RETSEG +; +; +; if ((device = fp->file.device) == 'c' || device == 'i') { +; +NEEDMORE MOV AL,[SI][%FD$DEV] + CMP AL,'c' + JZ CONSOLE + CMP AL,'i' + JNZ FILE +; +; if ((fp->file.flags & fdecho) || ($$UBCON & 2)) +; return _sys_al(0x0700); +; +CONSOLE TEST %[SI][%FD$FLAGS],%FL$ECHO + JNZ NOECHO + TEST %[$$UBCON],%>02 + JZ ECHO +NOECHO MOV AX,>0700 +CONDIR INT >21 + XOR AH,AH + RETSEG +; +; if ((fp->file.flags & fdunbufr) || ($$UBCON & 1)) +; return _sys_al(0x0100); +; +ECHO TEST %[SI][%FD$FLAGS],%FL$UNBUF + JNZ UNBUFR + TEST %[$$UBCON],%>01 + JZ FILE +UNBUFR MOV AX,>0100 + JMPS CONDIR +; +; if (fp->file.flags & fdunbufr) { +; +FILE TEST %[SI][%FD$FLAGS],%FL$UNBUF + JZ USEBUFR +; +; Read one character (unbuffered) +; if (_sysabcd(0x3f00,handle,1,&c,&fp->file.count) != 0) { +; (*_fileerr)(fp->file.count,fp); +; fp->file.count = 0; +; return EOF; } +; + MOV BX,[SI][%FD$HNDL] + MOV CX,1 + SUB SP,%2 + MOV DX,SP + MOV AX,>3F00 + INT >21 + JNB READOK + MOV BX,SP + PUSH [BX][%PARM1] + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%6 + MOV AX,-1 + RETSEG +; +; else { +; if (fp->file.count) return c; +; +READOK TEST AX,AX + JZ ATEND + POP AX + XOR AH,AH + RETSEG +; +; else { +; fp->file.eofflag = 1; +; return EOF; } } } +; +ATEND POP AX +FILEEND MOV BX,SP + MOV SI,[BX][%PARM1-2] + MOV %[SI][%FD$EOF],%1 +ENDFL MOV AX,-1 + RETSEG +; +; fp->file.ptr = fp->file.bufr; +; if (_sysabcd(0x3f00,handle,fp->file.bufsize, +; fp->file.bufr,&fp->file.count) != 0) { +; +USEBUFR MOV DX,[SI][%FD$BUFR] + MOV [SI][%FD$PTR],DX + MOV AX,>3F00 + MOV BX,[SI][%FD$HNDL] + MOV CX,[SI][%FD$BUFSZ] + INT >21 + JNB READOK2 +; +; (*_fileerr)(fp->file.count,fp); +; fp->file.count = 0; +; return EOF; } +; + MOV BX,SP + PUSH [BX][%PARM1-2] + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%4 + JMPS ENDFL +READOK2 MOV CX,AX + JCXZ FILEEND +; +; fp->file.dirty = fdread; +; + MOV BX,SP + MOV SI,[BX][%PARM1-2] + OR %[SI][%FD$DIRTY],%FL$READ +; +; if (fp->file.count--) return *(fp->file.ptr++); +; + DEC CX + MOV [SI][%FD$COUNT],CX + MOV BX,[SI][%FD$PTR] + MOV AL,[BX] + XOR AH,AH + INC BX + MOV [SI][%FD$PTR],BX + RETSEG +; +; else { +; fp->file.count = 0; +; fp->file.eofflag = 1; +; return EOF; +; } +; + END diff --git a/Mix Power C v1/GETS.C b/Mix Power C v1/GETS.C new file mode 100644 index 0000000..81301be --- /dev/null +++ b/Mix Power C v1/GETS.C @@ -0,0 +1,50 @@ + +/* String input from files */ +/* Copyright (c) Mix Software 1988 */ +/* ------------------------------------------------------------ */ + +char *gets(s) /* reads one line from stdin */ +char *s; /* into string s */ + /* newline replaced by '\0' */ +{ + int c; + char *sp; + sp = s; + while ((c = fgetc(stdin)) != EOF && c != NEWLINE) *sp++ = c; + *sp = NULL; + if ((c == EOF) && (sp == s)) return NULL; + return s; +} + +/* ------------------------------------------------------------ */ + +char *fgets(s, n, fp) /* read a line from fp */ +char *s; /* into s */ +int n; /* maximum characters */ +FILE *fp; /* is n-1 */ +{ + int c; + char *sp; + sp = s; + if (n <= 0) return NULL; + while (--n && (c = fgetc(fp)) != EOF && c != NEWLINE) *sp++ = c; + if (c == NEWLINE && n) *sp++ = c; + *sp = NULL; + if ((c == EOF) && (sp == s)) return NULL; + return s; + } + +/* ------------------------------------------------------------ */ + +char *cgets(s) /* reads one line from console */ +char *s; /* into string s */ + /* newline replaced by '\0' */ +{ + int status; + int _sys_ad(); + + _sys_ad(0x0a00,s,&status); + *(s + (int)*(s+1)+2) = '\0'; + return s+2; +} + diff --git a/Mix Power C v1/GRAPHICS.C b/Mix Power C v1/GRAPHICS.C new file mode 100644 index 0000000..bf3a176 --- /dev/null +++ b/Mix Power C v1/GRAPHICS.C @@ -0,0 +1,582 @@ +/* Graphics functions */ +/* Copyright (c) Mix Software 1988 */ + +#define NULL 0 +#define HERCMODE 99 +#define CGAHIGH 6 +#define CGALOW 4 +#define CGALOWBW 5 +#define PENCOLOR 0xff +#define TRANSPARENT 0xfe + +struct vconfig { + int xpixels; /* number of pixels in x direction */ + int ypixels; /* number of pixels in y direction */ + int textcols; /* number of text columns */ + int textrows; /* number of text rows */ + int colors; /* number of colors */ + int bitsperpixel; /* number of bits for each pixel */ + int pages; /* number of video pages */ + int colormask; /* value to & with color for bitsperpixel */ + int aspect_v; /* aspect ratio of screen is: */ + int aspect_h; /* aspect_v/aspect_h */ + /* ie y = aspect_v/aspect_h * y0 for 1:1 */ + }; + +struct fillpattern { + int width; + int height; + char *pattern; + }; + +/* ------------------------------------------------------------ */ +/* Pie chart */ +/* Create a pie chart from a set of values. Each value in the array */ +/* determines the relative area of the pie. The pie is drawn as a */ +/* circle in the current pen color. Each segment is bounded by a */ +/* solid line in the current pen color. Each segment is filled using*/ +/* an array of pattern pointers to determine the fill values. */ +/* The center of the pie is at the current graphics cursor. */ +/* Note: pie changes both the line style and the fill style. */ + +int pie(radius,data,datasize,patterns) + int radius; /* radius of the circle */ + double *data; /* values to determine the size of each section */ + int datasize; /* number of sections in the pie */ + struct fillpattern *patterns; +{ + extern int _v_color; /* pen color */ + extern int _vxcurs, _vycurs; + extern struct vconfig _vconfig; + extern double sin(), cos(); + + double total; + double *dataptr; + double angle, section_width; + double aspect; + long s, c; + static double twopi = 6.283185307179586; + static double pi4 = 0.7853981633974483096; + int center_x, center_y; + int i, r, x, y, color; + getvconfig(&_vconfig); + color = _v_color & _vconfig.colormask; + center_x = _vxcurs; + center_y = _vycurs; + if (datasize <= 0 || datasize > radius) return -1; + if (patterns == NULL) return -1; + circle(radius,_v_color); + aspect = (double) _vconfig.aspect_v / (double) _vconfig.aspect_h; + move_to(center_x,center_y); /* first boundary */ + line_style(&_v_color,1); /* solid lines in pen color */ + line_to(center_x+radius,center_y); + for (i = 0, dataptr = data, total = 0.0; i < datasize; ++i) + total += *dataptr++; + for (i = 0, dataptr = data, angle = 0.0; i < datasize; ++dataptr, ++i) { + section_width = (*dataptr * twopi)/total; + angle += section_width; + move_to(center_x,center_y); + line_to(center_x + (int)(radius*cos(angle)+0.5), + center_y + (int)(radius*sin(angle)*aspect+0.5) ); + fill_style(patterns->pattern,patterns->width,patterns->height); + patterns++; + r = radius; + /* locate an interior point to start filling */ + section_width /= 2.0; + c = 32768. * cos(angle-section_width); + s = 32768. * sin(angle-section_width) * aspect; + if ((section_width > pi4) || (2.0 * radius * sin(section_width) >= 3.0)) { + while (--r > 1) { /* find interior point to fill */ + x = center_x + ((r * c + 16384) >> 15); + y = center_y + ((r * s + 16384) >> 15); + if (readdot(y,x) != color) { + move_to(x,y); + fill(_v_color); + r = -1; + } + } + } + } + return 0; + } + +/* ------------------------------------------------------------ */ +/* Set the current pen color. The color is used for set_pixel. */ +/* In line drawing, if any part of the pattern is set to PENCOLOR */ +/* the current pen color is used. */ + +int pen_color(newcolor) + int newcolor; +{ + extern int _v_color; + int oldcolor; + oldcolor = _v_color; + _v_color = newcolor; + return oldcolor; + } + +/* ------------------------------------------------------------ */ +/* Draw a rectangle of the specified size starting with the */ +/* current graphics cursor as the upper left corner. The */ +/* graphics cursor is unchanged. */ + +int box(x_size, y_size, fillflag) + int x_size; /* size of the box in the horizontal direction */ + int y_size; /* size of the box in the vertical direction */ + int fillflag; /* non-zero if box is to be filled */ +{ + if (x_size < 0) { move_by(x_size+1,0); x_size = -x_size; } + if (y_size < 0) { move_by(0,y_size+1); y_size = -y_size; } + line_by(0,y_size-1); + line_by(x_size-1,0); + line_by(0,-y_size+1); + line_by(-x_size+1,0); + if (fillflag) { + if (x_size > 2 && y_size > 2) { + move_by(1,1); + flood(x_size-2,y_size-2); + } + } + } + +/* ------------------------------------------------------------ */ +/* Draw a line from the current cursor for a specified distance. */ + +int line_by(x_offset, y_offset) + int x_offset; /* distance in x (horizonal) direction */ + int y_offset; /* distance in y (vertical) direction */ +{ + extern int _vxcurs, _vycurs; + return line_to(_vxcurs+x_offset,_vycurs+y_offset); + } + +/* ------------------------------------------------------------ */ +/* Draw a line from the current cursor to the specified end */ +/* point. The line style is in the external variable _vl_pat.*/ +/* The pattern is repeated as necessary */ + +int line_to(x_end, y_end) + int x_end, y_end; /* end of line coordinate */ +{ + extern int _vl_psiz; + extern char *_vl_pat; + extern int _vxcurs, _vycurs; + extern int _v_color; + int t; + int x, y; + int x_start, y_start; + int d, incr1, incr2, dx, dy, delta; + int *xp = &x, *yp = &y; /* pointers to coordinates */ + char *pat, *patlimit; + + x_start = _vxcurs; _vxcurs = x_end; + y_start = _vycurs; _vycurs = y_end; + dy = (y_end > y_start) ? (y_end-y_start) : (y_start-y_end); + dx = (x_end > x_start) ? (x_end-x_start) : (x_start-x_end); + if (dy > dx) { /* slope greater than 1 */ + t = y_end; y_end = x_end; x_end = t; /* swap */ + t = y_start; y_start = x_start; x_start = t; + xp = &y; yp = &x; + } + + if (x_start > x_end) { /* start with smaller coordinate */ + t = x_end; x_end = x_start; x_start = t; + t = y_end; y_end = y_start; y_start = t; + } + + dx = x_end-x_start; + delta = 1; + if (y_end > y_start) dy = y_end - y_start; + else { + dy = y_start-y_end; + delta = -1; + } + d = dy+dy - dx; + incr1 = dy+dy; + incr2 = incr1-dx-dx; + x = x_start; y = y_start; + pat = _vl_pat; + patlimit = _vl_pat + _vl_psiz; + + do { + writedot(*yp,*xp,*pat); + ++x; + if (d < 0) d += incr1; + else { y += delta; d += incr2; } + if (++pat >= patlimit) pat = _vl_pat; + } while (x <= x_end); + } + +/* ------------------------------------------------------------ */ +/* move graphics cursor to a specified coordinate */ + +int move_to(x,y) + int x; /* move graphics cursor */ + int y; +{ + extern int _vxcurs, _vycurs; + _vxcurs = x; + _vycurs = y; + } + +/* ------------------------------------------------------------ */ +/* move graphics cursor by a specified offset */ + +int move_by(x,y) + int x; /* move graphics cursor by a specified offset */ + int y; +{ + extern int _vxcurs, _vycurs; + _vxcurs += x; + _vycurs += y; + } + +/* ------------------------------------------------------------ */ +/* Set the style of lines. */ + +int line_style(colors, size) + char *colors; /* List of colors for each unit of line */ + int size; /* Size of a unit (colors for each repetition) */ +{ + extern char *_vl_pat; + extern int _vl_psiz; + _vl_pat = colors; + _vl_psiz = size; + } + +/* ------------------------------------------------------------ */ +/* Draw a circle with center at (x,y) and given radius */ + +circle(radius,color) + int radius; + int color; +{ + int x, y, d; + extern struct vconfig _vconfig; + getvconfig(&_vconfig); + x = 0; + y = radius; + d = 3 - radius+radius; + while (x < y) { + _cpoint(x,y,color); + if (d < 0) d = d + 4*x + 6; + else { + d = d + 4*(x - y) + 10; + y -= 1; + } + ++x; + } + if (x == y) _cpoint(x,y,color); + } + +/* ------------------------------------------------------------ */ +/* Draw the 8 symetric points on a circle. The y coordinate */ +/* is scaled according to the aspect ratio of the screen. */ + +_cpoint(x,y,color) + int x,y; /* coordinate of point in 45 to 90 degree region */ +{ + extern int _vxcurs,_vycurs; /* coordinate of center of circle */ + extern struct vconfig _vconfig; + int x3, y3; + int round; + round = _vconfig.aspect_h >> 1; + y3 = (y * _vconfig.aspect_v + round) / _vconfig.aspect_h; + x3 = (x * _vconfig.aspect_v + round) / _vconfig.aspect_h; + writedot(_vycurs+y3, _vxcurs+x, color); + writedot(_vycurs+x3, _vxcurs+y, color); + writedot(_vycurs-x3, _vxcurs+y, color); + writedot(_vycurs-y3, _vxcurs+x, color); + writedot(_vycurs-y3, _vxcurs-x, color); + writedot(_vycurs-x3, _vxcurs-y, color); + writedot(_vycurs+x3, _vxcurs-y, color); + writedot(_vycurs+y3, _vxcurs-x, color); + } + +/* ------------------------------------------------------------ */ +/* Draw an ellipse with center at (x,y). The ellipse is */ +/* drawn in display coordinates. There is no compensation */ +/* for the aspect ratio of the screen. */ + +ellipse(x_radius,y_radius,color) + int x_radius; /* axis size in x direction */ + int y_radius; /* axis size in y direction */ + int color; +{ + extern int _vxcurs,_vycurs; /* coordinate of center */ + int x = _vxcurs; + int y = _vycurs; + int x0, y0, d, t; + int reverse = 0; + if (x_radius < y_radius) { + t = x; x = y; y = t; + t = x_radius; x_radius = y_radius; y_radius = t; + reverse = 1; + } + x0 = 0; + y0 = x_radius; + d = 3 - x_radius+x_radius; + while (x0 < y0) { + _epoint(x0,y0,x,y,color,x_radius,y_radius,reverse); + if (d < 0) d = d + 4*x0 + 6; + else { + d = d + 4*(x0 - y0) + 10; + --y0; + } + ++x0; + } + if (x0 == y0) _epoint(x0,y0,x,y,color,x_radius,y_radius,reverse); + } + +/* ------------------------------------------------------------ */ +/* Draw the 8 symetric points on an ellipse. */ + +_epoint(x,y,x0,y0,color,x_radius,y_radius,reverse) + int x,y; /* coordinate of point in 45 to 90 degree region */ + int x0,y0; /* coordinate of center */ + int x_radius; /* major axis */ + int y_radius; /* minor axis (x_radius >= y_radius) */ + int reverse; /* flag to reverse x and y coordinates */ +{ + long round = x_radius >> 1; + int yy, xx; + int xpos, ypos; + int *xp, *yp; + yy = ((long)y_radius * y + round) / (long) x_radius; + xx = ((long)y_radius * x + round) / (long) x_radius; + if (reverse) { xp = &ypos; yp = &xpos; } + else { xp = &xpos; yp = &ypos; } + + ypos = y0 + yy; xpos = x0 + x; writedot(*yp,*xp,color); + ypos = y0 + xx; xpos = x0 + y; writedot(*yp,*xp,color); + ypos = y0 - xx; xpos = x0 + y; writedot(*yp,*xp,color); + ypos = y0 - yy; xpos = x0 + x; writedot(*yp,*xp,color); + ypos = y0 - yy; xpos = x0 - x; writedot(*yp,*xp,color); + ypos = y0 - xx; xpos = x0 - y; writedot(*yp,*xp,color); + ypos = y0 + xx; xpos = x0 - y; writedot(*yp,*xp,color); + ypos = y0 + yy; xpos = x0 - x; writedot(*yp,*xp,color); + } + +/* ------------------------------------------------------------ */ +/* Set the pattern for filling areas */ + +int fill_style(colors, width, height) + char *colors; /* 2D array of colors to form fill pattern */ + int width; /* Width of fill pattern */ + int height; /* Height of fill pattern */ +{ + extern char *_vf_pat; + extern int _vf_wid, _vf_hgt; + _vf_pat = colors; + _vf_wid = width; + _vf_hgt = height; + } + +/* ------------------------------------------------------------ */ +/* Fill a bounded area with the current fill pattern. */ +/* The area is enclosed by the boundary color. If the boundary*/ +/* color does not form an enclosed area, the fill will "leak */ +/* through" any holes and result in filling the entire screen. */ + +int fill(boundary_color) + int boundary_color; +{ + extern int _vxcurs; /* graphics cursor */ + extern int _vycurs; + extern char *_vf_pat; /* fill pattern */ + extern int _vf_wid, _vf_hgt; /* pattern dimensions */ + extern int _v_color; /* pen color */ + extern int _vbcolor; /* color of boundary */ + extern int _vminh, _vmaxh; /* horizontal screen boundaries */ + extern int _vminv, _vmaxv; /* vertical screen boundaries */ + extern int _vmode; /* screen mode */ + extern int _vusemem; /* direct memory access */ + extern struct vconfig _vconfig; + + if (boundary_color == PENCOLOR) boundary_color = _v_color; + getvconfig(&_vconfig); + boundary_color = boundary_color & _vconfig.colormask; + if (_vxcurs < _vminh) return -1; /* start point out of window */ + if (_vxcurs > _vmaxh) return -1; + if (_vycurs < _vminv) return -1; + if (_vycurs > _vmaxv) return -1; + if (readdot(_vycurs,_vxcurs) == boundary_color) return -1; + if (_vusemem) { + if (_vmode == HERCMODE) return _fill_pm(boundary_color); + if (_vmode == CGAHIGH) return _fill_pm(boundary_color); + if (_vmode == CGALOW) return _fill_pm(boundary_color); + if (_vmode == CGALOWBW) return _fill_pm(boundary_color); + } + _vbcolor = boundary_color; + return _fill_p(_vxcurs,_vycurs,NULL); /* fill with pattern */ + } + + +struct _fill_chain { + int y; /* vertical coordinate at previous level */ + int xmin; /* start of run */ + int xmax; /* end of run */ + struct _fill_chain *next; /* next level */ + }; + +/*$STACKCHK*/ +/* ------------------------------------------------------------ */ +/* Recursive fill area with pattern. Due to the pattern, the */ +/* areas that have already been filled are not distinguishable */ +/* from areas that have not been touched. The previously */ +/* visited areas are chained together via the stack. There */ +/* is an explicit check for previously visited areas. This */ +/* test is necessary to allow for filling areas that contain */ +/* holes. */ + +int _fill_p(x,y,previous) + int x, y; /* coordinate of starting point */ + struct _fill_chain *previous; /* link to previous line in the pattern */ +{ + struct _fill_chain thisrow; + extern char *_vf_pat; /* fill pattern */ + extern int _vf_wid, _vf_hgt; /* pattern dimensions */ + extern int _vbcolor; /* color of boundary */ + extern int _vminh, _vmaxh; /* horizontal screen boundaries */ + extern int _vminv, _vmaxv; /* vertical screen boundaries */ + + int xmax; /* rightmost edge of fill on this line */ + int xmin; /* left edge of fill on this line */ + static char *xlimit; /* maximum pointer to pattern */ + static char *xstart; /* origin of this row of pattern */ + static char *p; /* fill pattern pointer */ + int nextx, nexty; /* next row coordinates */ + static int dot; + int incr; + struct _fill_chain *prior; + + xstart = _vf_pat + _vf_wid * (y % _vf_hgt); + xlimit = xstart + _vf_wid; + p = xstart + (x % _vf_wid); /* initial pattern pointer */ + + /* set dots to left of start point until boundary reached */ + xmin = x; + p = xstart + (xmin % _vf_wid); /* initial pattern pointer */ + while ((xmin >= _vminh) && (readdot(y,xmin) != _vbcolor)) { + writedot(y,xmin,*p); + --xmin; + if (--p < xstart) p = xlimit-1; + } + + /* set dots to right of start point until boundary reached */ + xmax = x+1; + p = xstart + (xmax % _vf_wid); /* initial pattern pointer */ + while ((xmax <= _vmaxh) && (readdot(y,xmax) != _vbcolor)) { + writedot(y,xmax,*p); + ++xmax; + if (++p >= xlimit) p = xstart; + } + + /* save current line for use as a stop */ + thisrow.y = y; + thisrow.xmin = xmin; + thisrow.xmax = xmax; + thisrow.next = previous; + + /* Expand vertically */ + for (incr = -1; incr <= 1; incr+=2) { + nexty = y + incr; + if (nexty >= _vminv && nexty <= _vmaxv) { + nextx = xmin; + while (nextx < xmax) { + do /* scan past boundary areas on line above or below */ + dot = readdot(nexty,++nextx); + while ((dot == _vbcolor) && nextx < xmax); + /* skip the group that we came from */ + if (nextx < xmax && dot != _vbcolor) { + prior = previous; + while (prior != NULL) { + if (prior->y == nexty) { + if (nextx > prior->xmin && nextx < prior->xmax) { + /* already done */ + nextx = prior->xmax-1; + dot = _vbcolor; + prior = NULL; + } + else prior = prior->next; + } + else prior = prior->next; + } + if (dot != _vbcolor) nextx = _fill_p(nextx,nexty,&thisrow); + } + } + } + } + return xmax; + } + +/* ------------------------------------------------------------ */ +/* return configuration data for the screen. */ + +getvconfig(config) + struct vconfig *config; +{ + static struct vconfig cfgtable[17] = + {{ 0, 0, 40, 25,16, 8, 8, 0xff, 10, 12 }, /* 40 x 25 text BW */ + { 0, 0, 40, 25,16, 8, 8, 0xff, 10, 12 }, /* 40 x 25 text color */ + { 0, 0, 80, 25,16, 8, 4, 0xff, 10, 24 }, /* 80 x 25 text BW */ + { 0, 0, 80, 25,16, 8, 4, 0xff, 10, 24 }, /* 80 x 25 text color */ + {320,200, 0, 0, 4, 2, 1, 0x03, 10, 12 }, /* 320 x 200 graphics */ + {320,200, 0, 0, 4, 2, 1, 0x03, 10, 12 }, /* 320 x 200 BW */ + {640,200, 0, 0, 2, 1, 1, 0x01, 10, 24 }, /* 640 x 200 graphics */ + { 0, 0, 80, 25,16, 8, 1, 0xff, 10, 24 }, /* monochrome */ + {160,200, 0, 0,16, 4, 1, 0x0f, 20, 12 }, /* 160 x 200 pc jr */ + {320,200, 0, 0,16, 4, 1, 0x0f, 10, 12 }, /* 320 x 200 pc jr */ + {640,200, 0, 0, 4, 2, 1, 0x03, 10, 12 }, /* 640 x 200 pc jr */ + { 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0 }, /* undefined */ + { 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0 }, /* undefined */ + {320,200, 0, 0,16, 4, 8, 0x0f, 10, 12 }, /* 320 x 200 EGA */ + {640,200, 0, 0,16, 4, 4, 0x0f, 10, 24 }, /* 640 x 200 EGA */ + {640,350, 0, 0, 2, 1, 1, 0x01, 35, 48 }, /* 640 x 350 BW EGA */ + {640,350, 0, 0,16, 4, 1, 0x0f, 35, 48 } /* 640 x 350 EGA */ + {640,480, 0, 0, 2, 1, 1, 0x01, 2, 2 } /* 640 x 480 VGA, MCGA */ + {640,480, 0, 0,16, 4, 1, 0x0f, 2, 2 } /* 640 x 480 VGA */ + {320,200, 0, 0,256,8, 1, 0xff, 2, 2 } /* 320 x 200 VGA, MCGA */ + }; + static struct vconfig herccfg = + {720,348, 0, 0, 2, 1, 2, 0x1, 2, 3 }; /* Hercules BW */ + int mode; + mode = getvmode(); + if (mode == HERCMODE) memcpy(config,herccfg,sizeof(struct vconfig)); + else if (mode <= 16) memcpy(config,&cfgtable[mode],sizeof(struct vconfig)); + else memset(config,0,sizeof(struct vconfig)); + } + +plots(s) + char *s; +{ + if (s != NULL) { + while (*s != '\0') plotch(*s++); + } + return s; + } + +setpixel(x, y) + int x, y; +{ + extern int _v_color; + writedot(y,x,_v_color); + } + +int getpixel(x, y) + int x, y; +{ + return readdot(y,x); + } + +int setapage(page) /* set active page */ + int page; +{ + extern int _vapage; + int oldpage = _vapage; + _vapage = page; + return oldpage; + } + +int _vbcolor; /* boundary color for fill */ +struct vconfig _vconfig; /* screen configuration */ diff --git a/Mix Power C v1/INIT.ASM b/Mix Power C v1/INIT.ASM new file mode 100644 index 0000000..01ca283 --- /dev/null +++ b/Mix Power C v1/INIT.ASM @@ -0,0 +1,380 @@ +; +; Initialize the runtime environment. +; The block at $$Link$$ contains parameters passed from +; the linker. +; +; Determine memory bounds. Create stack and heap. Initialize +; fundamental parameters. +; +; +BUFSIZ EQU >200 +FALSE EQU 0 +TRUE EQU ~FALSE +ENVIR EQU >2C +DOS EQU >21 +MARGIN EQU >80 +OP$EXIT EQU >4C +OP$PMSG EQU >09 +OP$VERS EQU >30 +OP$TIME EQU >2C +OP$DATE EQU >2A +CMDLINE EQU >80 +CMDLENGTH EQU >80 +ARGV0LEN EQU 64 +LONGNAME EQU >FFFF +SHORTNAM EQU >FFFF + CASE TRUE +; + IDT $_INIT_$ + DEF $_INIT_$ + DEF $_init_$ + DEF $$RETURN +$_init_$ equ $ +$_INIT_$ MOV AX,DS + MOV ES,AX + MOV BX,SS + MOV DS,BX + MOV [$$PSP],AX + SEGES + MOV AX,[ENVIR] + MOV [$$ENVIR],AX + MOV AH,OP$VERS ; Dos version number + INT DOS + MOV [_osmajor],AX + CMP AL,3 ; If 3.0 or greater + JB GETTIME + MOV ES,[$$ENVIR] ; scan environment for argv[0] + XOR DI,DI + MOV AL,%0 + MOV CX,-1 + CLD +ENVNEXT SEGES + CMP %[DI],%0 ; end of table? + JZ ENDENV + REPNZ + SCASB + JMPS ENVNEXT +ENDENV INC DI ; skip terminator + SEGES + CMP [DI],1 + JNZ GETTIME ; no argv[0] + ADD DI,%2 + MOV SI,$$ARGV0 + MOV CX,ARGV0LEN/2 +CPYARG0 SEGES + MOV AX,[DI] + MOV [SI],AX + ADD DI,%2 + ADD SI,%2 + LOOP CPYARG0 +GETTIME MOV AH,OP$DATE + INT DOS + MOV [$$CLOCK],CX + MOV [$$CLOCK2],DX + MOV AH,OP$TIME + INT DOS + MOV [$$CLOCK4],CX + MOV [$$CLOCK6],DX + MOV ES,[$$PSP] + SEGES + MOV SI,[2] ; Top of available memory + MOV [$$MAXSEG],SI + MOV DX,DS + SUB SI,DX + CMP SI,>1000 ; More than 64k available? + JAE DS64K + MOV CL,4 + SHL SI,CL + DEC SI + JMPS DSSET +DS64K MOV SI,>FFFF +DSSET MOV BX,[DSSIZE] ; Size of initialized data + ADD BX,MARGIN + MOV [$$LIMIT],BX ; Lower limit of stack + MOV AX,[STKSIZE] + TEST AX,AX ; Zero means default + JNZ STACKVAL + MOV AX,[HPSIZE] ; Check heap size + TEST AX,AX + JNZ HPSET + MOV AX,SI + SUB AX,BX + SHR AX,1 ; Half of memory for stack + SUB AX,2 + AND AX,>FFFE + MOV [STKSIZE],AX + MOV [HPSIZE],AX + JMPS STACKSET +STACKVAL TEST [HPSIZE],>FFFF + JNZ STACKSET + MOV CX,SI + SUB CX,AX + JB NOMEM1 + SUB CX,BX + JB NOMEM1 + DEC CX + JB NOMEM1 + AND CX,>FFFE + MOV [HPSIZE],CX + JMPS STACKSET +HPSET MOV CX,SI + SUB CX,AX + JB NOMEM1 + SUB CX,BX + JB NOMEM1 + DEC CX + AND CX,>FFFE + JNB MEMOK +NOMEM1 JMP NOMEM +MEMOK MOV [STKSIZE],CX + MOV AX,CX +STACKSET ADD BX,AX + JB NOMEM1 + CMP BX,SI ; Enough memory available + JA NOMEM1 + MOV [$$BOTTOM],BX ; Top limit of stack + MOV [$$MAXS],BX ; Maximum stack used + INC BX + AND BX,>FFFE + POP AX ; Copy return address + POP CX ; to new stack + MOV SP,BX ; Set stack location for program + MOV DX,CS + PUSH DX ; Set final return address + MOV [$$RETIS],DX + MOV DX,$$RETURN + PUSH DX + MOV [$$RETI],DX + MOV BP,SP ; Initial frame + PUSH CX ; Save return to program + PUSH AX + MOV AX,DS ; initialize to zero + MOV ES,AX + MOV DI,[$$LIMIT] + MOV CX,SP + SUB CX,256 + SUB CX,DI + SHR CX,1 + XOR AX,AX + REP + STOSW +; +; Create heap +; + INC BX ; Start heap on word boundary + AND BX,>0FFFE + MOV [$$HMIN],BX + XOR AX,AX + MOV [$$CURH],AX ; No heap used + MOV [$$MAXH],AX + ADD BX,[HPSIZE] + JZ ALLMEM + JB NOMEM1 + JMPS MAKEHEAP +ALLMEM MOV BX,>FFFE +MAKEHEAP AND BX,>FFFE ; Make top of heap a word boundary + MOV [$$HMAX],BX ; STORE HEAP LIMIT + MOV AX,BX + DEC AX ; round up with top-16+15 + MOV CL,4 + SHR AX,CL + INC AX ; add back the 16 + MOV DX,DS + ADD AX,DX + MOV [$$TOPSEG],AX ; First unused extra memory + MOV [$$ENDDS],AX ; Segment of end of ds + SUB AX,DX + SHL AX,CL + MOV [$$TOPDS],AX ; Top of data segment + ADD BX,-6 ; RESERVE DUMMY PACKET + MOV CX,BX ; SAVE POINTER TO DUMMY + MOV DX,BX ; SAVE POINTER TO DUMMY + MOV [BX],0 ; LENGTH OF DUMMY PACKET + MOV AX,[$$HMIN] ; AX=ADDRESS OF INITIAL HEAP + MOV [BX][%2],AX ; SET NEXT PACKET PTR + MOV [BX][%4],AX ; SET PREDECESSOR PTR +; +; SET LENGTH OF INITIAL HEAP PACKET +; + SUB CX,AX ; CALCULATE HEAP SIZE + MOV [$$FREE],AX + MOV BX,AX ; POINT TO BIG HEAP PACKET + MOV [BX],CX ; SET HEAP SIZE + MOV [BX][%2],DX ;NEXT IS DUMMY PACKET + MOV [BX][%4],DX ;PREDECESSOR IS DUMMY PACKET +; +; COPY COMMAND LINE TO DATA SEGMENT +; + MOV SI,CMDLINE + MOV ES,[$$PSP] + SEGES + MOV CL,[SI] ; Length of command line + CMP CL,5 + JB COPYALL ; Too short for trace + SEGES + CMP %[SI][%1],%>0D + JNZ COPYALL ; Not trace + SEGES + MOV AX,[SI][%2] + MOV [$$XTRC],AX + SEGES + MOV AX,[SI][%4] + MOV [$$XTRC2],AX + PUSH AX + PUSH [$$XTRC] + SUB CL,%5 + ADD SI,%5 + SEGES + MOV %[SI],CL +COPYALL MOV DI,$$CMDLIN + MOV CX,CMDLENGTH/2 + MOV AX,DS + MOV ES,AX + MOV DS,[$$PSP] +COPYCMD REP + MOVSW + MOV AX,ES + MOV DS,AX + MOV ES,[$$PSP] + XOR BX,BX + RETSEG +; +$$RETURN MOV AX,[$$EXSTAT] + TEST AH,AH + JZ STOP + MOV AL,%>FF +STOP CMP [$$XTRC2],0 + JZ NOTRC + MOV BX,1 + CALLSEG [$$XTRC] +NOTRC MOV AH,OP$EXIT + INT DOS +NOMEM MOV DX,NOMEMMSG + MOV AH,OP$PMSG + INT DOS + MOV AL,%>FE + JMPS STOP +; +; Data areas. +; $$Link$$ contains information supplied by the linker. +; $$PROCES contains control and status information used +; by the program. +; + DORG 0 +; +; Process control record. Contains status values, limits and +; runtime flags +; +$$PROCES EQU $ +$$EXITPT DW $$RETI ; Exit address +$$BOTTOM DW 0 ; Stack bottom (empty stack) +$$LIMIT DW 0 ; Stack limit (full stack) +$$HMIN DW 0 ; Lower bound of heap +$$HMAX DW 0 ; Upper bound of heap +$$FREE DW 0 ; Free space pointer for heap +$$MAXS DW 0 ; Maximum stack used +$$MAXH DW 0 ; Maximum heap used +$$CURH DW 0 ; Current heap used +$$IOTERM DB 0 ; Terminate on io error +$$HPTERM DB 0 ; Terminate on heap full +$$IOFLG DB 0 ; IO default flags +$$ZFILL DB 0 ; Zero locals & heap packets flag +$$FATAL DW 0 ; Fatal error address + DW 0 ; Fatal error address (segment) +$$CMDPTR DW $$CMDLIN ; Address of command line +$$LIOERR DW 0 ; File for last io error +_psp EQU $ +$$PSP DW 0 ; Program segment prefix segment +$$ENVIR DW 0 ; Environment segment +$$XTRC DW 0 ; Address of ctrace +$$XTRC2 DW 0 ; Address of ctrace (segment) + DW 0,0,0 +; +errno DW 0 ; Error number +_doserrn DW 0 ; Operating system error code +$$FLERR DW 0 ; Floating point error code +$$BUFSIZ DW BUFSIZ ; Default buffer size for files +$$MAXSEG DW 0 ; First unavailable paragraph +$$TOPSEG DW 0 ; First unused paragraph +$$TOPDS DW 0 ; Top address in data segment +$$ENDDS DW 0 ; Segment of end of data segment +$$EXSTAT DW 0 ; Exit status +$$MACHIN DB 0 +$$OPSYS DB >20 +$$SHMSG DB 0 ; Display statistics +$$CLFEED DB 1 ; Filter line feeds (default) +$$CCTLZ DB 0 ; Treat ctl/z as end of file (default) +$$STATSV DB 0 +$$UBCON DB 0 ; Unbuffered console +$$ARTERM DB 0 ; Terminate on arithmetic errors +$$RETI DW 0 ; Far address of exit routine +$$RETIS DW 0 +$$CMDLIN DS >80 ; Copy of command line +_osmajor DB 0 +_osminor DB 0 +$$CLOCK DW 0 +$$CLOCK2 DW 0 +$$CLOCK4 DW 0 +$$CLOCK6 DW 0 +$$ARGV0 DB 0 + DS ARGV0LEN +NOMEMMSG DB 'Not enough memory$' + DDEF $$Link$$ + DORG 2*(($+1)/2) +$$Link$$ EQU $ +STKSIZE DW 0 ; Stack size +HPSIZE DW 0 ; Heap size +DSSIZE DW 0 ; Size of initialized data + DW 0,0,0,0,0 ; Filler for more parameters + DW 0,0,0,0,0,0,0,0 + DDEF $$EXITPT + DDEF $$BOTTOM + DDEF $$LIMIT + DDEF $$HMIN + DDEF $$HMAX + DDEF $$FREE + DDEF $$MAXS + DDEF $$MAXH + DDEF $$CURH + DDEF $$IOTERM + DDEF $$HPTERM + DDEF $$IOFLG + DDEF $$ZFILL + DDEF $$FATAL + DDEF $$CMDPTR + DDEF $$LIOERR + DDEF $$PSP + DDEF _psp + DDEF $$ENVIR + DDEF $$XTRC + DDEF $$XTRC2 + DDEF errno + IF SHORTNAM + DDEF _doserrn + ENDIF + IF LONGNAME + LDDEF _doserrno + ENDIF + DDEF $$FLERR + DDEF $$BUFSIZ + DDEF $$MAXSEG + DDEF $$TOPSEG + DDEF $$TOPDS + DDEF $$ENDDS + DDEF $$EXSTAT + DDEF $$MACHIN + DDEF $$OPSYS + DDEF $$SHMSG + DDEF $$CLFEED + DDEF $$CCTLZ + DDEF $$STATSV + DDEF $$UBCON + DDEF $$ARTERM + DDEF $$RETI + DDEF $$CMDLIN + DDEF _osmajor + DDEF _osminor + DDEF $$CLOCK + DDEF $$ARGV0 + END +; diff --git a/Mix Power C v1/INIT.C b/Mix Power C v1/INIT.C new file mode 100644 index 0000000..511e300 --- /dev/null +++ b/Mix Power C v1/INIT.C @@ -0,0 +1,166 @@ +/* Initialization functions. */ +/* Copyright (c) Mix Software 1988 */ + +/* _INITIO is called by the lowest level initialization + function. It is the first C function executed by a program. + _INITIO opens the standard files, creates argv and argc + and calls main. + */ + + +_INITIO(stdfiles) +int stdfiles; /*stdfiles = 1 says open standard files*/ +{ + extern char *$$CMDPTR; + extern FILE *_iob[MAXFILES]; + extern int (*_fclose)(); + extern char $$ARGV0[]; + register char *cmdline; + register int count; + static char *argv[MAXARGS]; /*pointers to command line arguments*/ + int argc; /*number of command line arguments*/ + int quote; + int main(); + int exit(); + + cmdline = $$CMDPTR; + count = *cmdline++; + argv[0] = $$ARGV0; + argc = 1; + while (count > 0 && argc < MAXARGS) { + while (*cmdline == ' ' && count) { + count--; + cmdline++; + } + if (count) { + quote = 0; + argv[argc] = cmdline; + while (count && (*cmdline != ' ' || quote)) { + if (*cmdline == '"') { + if (quote) {*cmdline = ' '; quote = 0; } + else if (argv[argc] == cmdline) { + quote = 1; + cmdline++, count--; + argv[argc] = cmdline; + } + else cmdline++, count--; + } + else if (*cmdline == '\\' && quote) { + memcpy(cmdline,cmdline+1,count); + cmdline++, count--; + if (count) count--; + } + else cmdline++, count--; /* not " or \ */ + } + argc++; + *cmdline++ = '\0'; + count--; + } + } + exit(main(argc,argv)); + _iob[0]; /* These statements look useless but are not. */ + _fclose; /* They force these variables to be linked into program */ +} + +/* _INITIO3 is called if main requires 3 arguments. In addition to + the functions performed by _INITIO, it also creates the environment + and passes envp to main. + */ + +_INITIO3(stdfiles) +int stdfiles; /*stdfiles = 1 says open standard files*/ +{ + extern char *$$CMDPTR; + extern char *(*environ)[]; + extern FILE *_iob[MAXFILES]; + extern int (*_fclose)(); + extern char $$ARGV0[]; + register char *cmdline; + register int count; + char *argv[MAXARGS]; /*pointers to command line arguments*/ + int argc; /*number of command line arguments*/ + int quote; + int main(); + int exit(); + + cmdline = $$CMDPTR; + count = *cmdline++; + argv[0] = $$ARGV0; + argc = 1; + while (count > 0 && argc < MAXARGS) { + while (*cmdline == ' ' && count) { + count--; + cmdline++; + } + if (count) { + quote = 0; + argv[argc] = cmdline; + while (count && (*cmdline != ' ' || quote)) { + if (*cmdline == '"') { + if (quote) {*cmdline = ' '; quote = 0; } + else if (argv[argc] == cmdline) { + quote = 1; + cmdline++, count--; + argv[argc] = cmdline; + } + else cmdline++, count--; + } + else if (*cmdline == '\\' && quote) { + memcpy(cmdline,cmdline+1,count); + cmdline++, count--; + if (count) count--; + } + else cmdline++, count--; /* not " or \ */ + } + argc++; + *cmdline++ = '\0'; + count--; + } + } + getenv("PATH="); + exit(main(argc,argv,environ)); + _iob[0]; + _fclose; +} + +/* standard files */ + +char _STDINB[128]; +FILE _STDFL1, _STDFL2, _STDFL3, _STDFL4, _STDFL5; + +FILE *_iob[MAXFILES] = {&_STDFL1, &_STDFL2, &_STDFL3, + &_STDFL4, &_STDFL5}; +FILE _STDFL1 = {{'S', '\001', 0, &_STDINB, + &_STDINB, 0, 128, 0, + 'i', '\0', '\0', '\0', + '\0', fdfilter+fdsetbuf, '\0', '\0', + 0, 0, '\0', "\0\0\0\0" }, + 0}; +FILE _STDFL2 = {{'S', '\001', 1, 0, + 0, 0, 0, 0, + 'o', '\0', '\001', '\0', + '\0', fdfilter+fdunbufr, '\0', '\0', + 0, 0, '\0', "\0\0\0\0" }, + 1}; +FILE _STDFL3 = {{'S', '\001', 2, 0, + 0, 0, 0, 0, + 'e', '\0', '\001', '\0', + '\0', fdfilter+fdunbufr, '\0', '\0', + 0, 0, '\0', "\0\0\0\0" }, + 2}; +FILE _STDFL4 = {{'S', '\001', 3, 0, + 0, 0, 0, 0, + 'a', '\0', '\001', '\0', + '\0', fdfilter+fdunbufr, '\0', '\0', + 0, 0, '\0', "\0\0\0\0" }, + 3}; +FILE _STDFL5 = {{'S', '\001', 4, 0, + 0, 0, 0, 0, + 'l', '\0', '\001', '\0', + '\0', fdfilter+fdunbufr, '\0', '\0', + 0, 0, '\0', "\0\0\0\0" }, + 4}; + +extern int _stdclose(); /* Close function for std files only */ +int (*_fclose)() = _stdclose; + diff --git a/Mix Power C v1/INOUT.ASM b/Mix Power C v1/INOUT.ASM new file mode 100644 index 0000000..984498e --- /dev/null +++ b/Mix Power C v1/INOUT.ASM @@ -0,0 +1,63 @@ +; +; Copyright (c) Mix Software 1988 +; + IDT inp + DEF inp + IF UPPER + DEF INP + ENDIF +inp EQU $ +INP MOV BX,SP + MOV DX,[BX][%PARM1-2] + IN AL,DX + XOR AH,AH + RETFAR + END +; + IDT inport + DEF inport +inport MOV BX,SP + MOV DX,[BX][%PARM1-2] + IN AX,DX + RETFAR + END +; + IDT inportb + DEF inportb +inportb MOV BX,SP + MOV DX,[BX][%PARM1-2] + IN AL,DX + XOR AH,AH + RETFAR + END +; + IDT outp + DEF outp + IF UPPER + DEF OUTP + ENDIF +outp EQU $ +OUTP MOV BX,SP + MOV DX,[BX][%PARM1-2] + MOV AX,[BX][%PARM2-2] + OUT DX,AL + RETFAR + END +; + IDT outport + DEF outport +outport MOV BX,SP + MOV DX,[BX][%PARM1-2] + MOV AX,[BX][%PARM2-2] + OUT DX,AX + RETFAR + END +; + IDT outportb + DEF outportb +outportb MOV BX,SP + MOV DX,[BX][%PARM1-2] + MOV AX,[BX][%PARM2-2] + OUT DX,AL + RETFAR + END diff --git a/Mix Power C v1/INTENT.ASM b/Mix Power C v1/INTENT.ASM new file mode 100644 index 0000000..fe8618f --- /dev/null +++ b/Mix Power C v1/INTENT.ASM @@ -0,0 +1,230 @@ +; +; Copyright (c) Mix Software 1988 +; +; Entry from an interrupt +; sets ds and ss to the proper values +; passes registers as arguments +; Called with a far return address followed by an +; interrupt return on the stack. All registers are +; in an unknown state. +; + IDT $_INTENT + DEF $_INTENT + DREF $$LIMIT ; Maximum limit of stack + DREF $$BOTTOM ; Start of stack + FREF $$MAXS +MARGIN EQU >100 ; Minimum stack needed +; +$_INTENT CLI + PUSH AX + MOV AX,SS + SEGCS + CMP AX,[PROGDS] + JNZ DIFFSTK + POP AX ; interrupt uses same stack + PUSH BP ; as the program + MOV BP,SP + XCHG AX,[BP][%4] ; ax = caller cs + XCHG BX,[BP][%2] ; ax = caller ip + POP BP + PUSH CX + PUSH DX + PUSH ES + PUSH DS + PUSH SI + PUSH DI + PUSH BP + MOV CX,CS + PUSH CX ; return to here + MOV CX,RET1 + PUSH CX + PUSH AX ; Caller's address + PUSH BX + MOV AX,SS + MOV DS,AX + STI + RETFAR ; Go to caller with parms set +RET1 POP BP + POP DI + POP SI + POP AX + MOV DS,AX + POP AX + MOV ES,AX + POP DX + POP CX + POP BX + POP AX + IRET +; +DIFFSTK POP AX + PUSH DS + SEGCS + MOV DS,[PROGDS] + CLI + POP [SAVEDS] + MOV [SAVEDI],DI + MOV [SAVEAX],AX + MOV [SAVECX],CX + CMP %[STKLOCK],%0 + JNZ FINDSTK + MOV %[STKLOCK],%1 + MOV DI,[$$LIMIT] + ADD DI,[_INT_STK] + AND DI,>FFFE + MOV AX,SS ; switch stacks + MOV CX,SP + SEGCS + MOV SS,[PROGDS] + MOV SP,DI + MOV DI,CX + MOV DS,AX + MOV CX,RET2 + JMPS NEWSTK +; +RET2 CLI + MOV AX,SS + MOV DS,AX + MOV %[STKLOCK],%0 + POP BP + POP [SAVEDI] + POP SI + POP [SAVEDS] + POP AX + MOV ES,AX + POP DX + POP CX + POP BX + POP [SAVEAX] + ADD SP,%6 ; Remove cs:ip and flags + POP DI ; Interrupted task's sp + ADD DI,%4 ; Remove return from int function + POP AX ; Interrupted task's ss + MOV SS,AX ; Set to prior stack + MOV SP,DI + MOV AX,[SAVEAX] + MOV DI,[SAVEDI] + MOV DS,[SAVEDS] + IRET +; +; Search for stack space +; +FINDSTK MOV [SAVEES],ES + MOV AX,DS + MOV ES,AX + XOR AX,AX + MOV DI,[$$LIMIT] ; Scan for available stack + ADD DI,[_INT_STK] + MOV CX,[$$BOTTOM] + SUB CX,DI + SHR CX,1 + REPZ + SCASW + SUB DI,%2 + DEC DI + AND DI,>FFFE ; round down to word boundary + MOV CX,DI + SUB CX,[$$LIMIT] + CMP CX,MARGIN + JB NOSTACK + MOV ES,[SAVEES] + MOV AX,SS ; switch stacks + MOV CX,SP + SEGCS + MOV SS,[PROGDS] + MOV SP,DI + MOV DI,CX + MOV DS,AX + MOV CX,RET3 +NEWSTK PUSH DS ; save interrupt's stack + PUSH DI + PUSH [DI][%2*4] ; flags + PUSH [DI][%2*3] ; interrupt cs + PUSH [DI][%2*2] ; interrupt ip + MOV AX,DS + PUSH DI + MOV DI,SS + MOV DS,DI + POP DI + PUSH [SAVEAX] ; ax + PUSH BX + PUSH [SAVECX] ; cx + PUSH DX + PUSH ES + PUSH [SAVEDS] ; DS + PUSH SI + PUSH [SAVEDI] ; DI + PUSH BP + MOV DS,AX + MOV AX,CS + PUSH AX ; return segment + PUSH CX ; return address + PUSH [DI][%2*1] ; Caller's address + PUSH [DI][%2*0] + MOV AX,SS + MOV DS,AX + STI + RETFAR ; Go to caller with parms set +; +NOSTACK PUSH DX + PUSH BX + MOV AX,CS + MOV DS,AX + MOV AX,>4000 ; Write message to stderr + MOV BX,2 + MOV CX,MSGLEN + MOV DX,STKMSG + INT >21 + POP BX + POP DX + JMPS GOBACK +; +RET3 CLI + MOV AX,SS + MOV DS,AX + POP BP + POP [SAVEDI] + POP SI + POP [SAVEDS] + POP [SAVEES] + POP DX + POP [SAVECX] + POP BX + POP [SAVEAX] + ADD SP,%6 ; Remove cs:ip and flags + MOV DI,SS + MOV ES,DI + POP DI ; Interrupted task's sp + ADD DI,%4 ; Remove return from int function + POP AX ; Interrupted task's ss + MOV CX,SP + MOV SS,AX ; Set to prior stack + MOV SP,DI + MOV DI,[$$LIMIT] + ADD DI,[_INT_STK] + SUB CX,DI + SHR CX,1 + XOR AX,AX + REP + STOSW +GOBACK MOV AX,[SAVEAX] + MOV CX,[SAVECX] + MOV DI,[SAVEDI] + MOV ES,[SAVEES] + MOV DS,[SAVEDS] + IRET +; +STKMSG DB >0D,>0A,'Out of stack',>0D,>0A +MSGLEN EQU $-STKMSG +PROGDS EQU $+3 + callfar $$MAXS + DORG 0 + DDEF _INT_STK +SAVEAX DW 0-0 +SAVECX DW 0-0 +SAVEDI DW 0-0 +SAVEDS DW 0-0 +SAVEES DW 0-0 +_INT_STK DW >400 +STKLOCK DW 0 + END diff --git a/Mix Power C v1/INTR.ASM b/Mix Power C v1/INTR.ASM new file mode 100644 index 0000000..ce578c4 --- /dev/null +++ b/Mix Power C v1/INTR.ASM @@ -0,0 +1,70 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; int intr(intno, reg); +; int intno; +; union REGPACK reg; +; ------------------------------------------------------- +; + IDT intr + DEF intr +; +intr PUSH BP + MOV BP,SP + SUB SP,INSTRSZ + MOV SI,INSTRINT + MOV DI,SP + MOV AX,SS + MOV ES,AX + MOV CX,INSTRSZ + CLD + REP + MOVSB + MOV BX,SP + MOV AX,[BP][%PARM1] + MOV [BX][%1],AL + MOV BP,[BP][%PARM2] + PUSH BP + MOV AX,CS + PUSH AX ; Return segment + CALL DOINT + PUSH DS + PUSH BP + MOV BP,SS + MOV DS,BP + MOV BP,SP + MOV BP,[BP][%4] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + POP [BP][%8] + MOV [BP][%10],SI + MOV [BP][%12],DI + POP [BP][%14] + MOV [BP][%16],ES + PUSHF + POP [BP][%18] + ADD SP,%INSTRSZ+2 + POP BP + RETFAR +; +DOINT MOV AX,SS + PUSH AX ; Segment of int xx instruction + PUSH BX ; offset of int xx instruction + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%10] + MOV DI,[BP][%12] + MOV DS,[BP][%14] + MOV ES,[BP][%16] + MOV BP,[BP][%8] + RETFAR + DORG 0 +INSTRINT INT >21 +INSTRRET RETSEG +INSTRSZ EQU (($-INSTRINT)+1)|>FFFE + END diff --git a/Mix Power C v1/INTRPT.ASM b/Mix Power C v1/INTRPT.ASM new file mode 100644 index 0000000..37e3d42 --- /dev/null +++ b/Mix Power C v1/INTRPT.ASM @@ -0,0 +1,48 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; getvect - get interrupt vector +; return contents of interrupt vector +; ------------------------------------------------------- +; + IDT getvect + DEF getvect +; +getvect PUSH BP + MOV BP,SP + MOV AL,[BP][%PARM1] + MOV AH,>35 + INT >21 + MOV DX,ES + MOV AX,BX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; setvect - set interrupt vector +; void setvect(int intno, void (*fn)()) +; ------------------------------------------------------- +; + IDT setvect + DEF setvect +; +setvect PUSH BP + MOV BP,SP + PUSH DS + MOV AL,[BP][%PARM1] +; if near pointer +; MOV BX,[BP][%PARM2] +; MOV DX,[BX] +; MOV DS,[BX][%2] +; if far pointer + MOV DX,[BP][%PARM2] + MOV DS,[BP][%PARM3] + MOV AH,>25 + INT >21 + POP AX + MOV DS,AX + POP BP + RETSEG + END diff --git a/Mix Power C v1/IO.ASM b/Mix Power C v1/IO.ASM new file mode 100644 index 0000000..c8a5a82 --- /dev/null +++ b/Mix Power C v1/IO.ASM @@ -0,0 +1,16 @@ +; +; Assembly language file io +; Copyright (c) Mix Software 1988 +; + GLOBAL + INCLUDE LIBDEF.ASM + CASE 1 + ENDGLOBAL +; + INCLUDE READ.ASM + INCLUDE WRITE.ASM + INCLUDE PUT.ASM + INCLUDE GET.ASM + INCLUDE SEEK.ASM + INCLUDE FLUSH.ASM +; diff --git a/Mix Power C v1/LIB.ASM b/Mix Power C v1/LIB.ASM new file mode 100644 index 0000000..c032421 --- /dev/null +++ b/Mix Power C v1/LIB.ASM @@ -0,0 +1,34 @@ +; +; Assembly language functions for Mix C +; Large memory model +; +; Copyright (C) 1988 by Mix Software Inc. +; ALL RIGHTS RESERVED +; + GLOBAL + NOLIST + INCLUDE LIBDEF.ASM + LIST + CASE 1 + ENDGLOBAL + + INCLUDE SYS.ASM + INCLUDE SETMEM.ASM + INCLUDE MOVMEM.ASM + INCLUDE STRING.ASM + INCLUDE TO.ASM + INCLUDE ENVIR.ASM + INCLUDE NHEAP.ASM + INCLUDE NEW.ASM + INCLUDE FREE.ASM + INCLUDE FARSTR1.ASM + INCLUDE FARSTR.ASM + INCLUDE FARHEAP.ASM + INCLUDE DIV.ASM + INCLUDE LONG.ASM + INCLUDE FAR.ASM + INCLUDE SETJMP.ASM + INCLUDE STACK.ASM + INCLUDE INOUT.ASM + INCLUDE FATAL.ASM +; diff --git a/Mix Power C v1/LIB2.ASM b/Mix Power C v1/LIB2.ASM new file mode 100644 index 0000000..70a6c33 --- /dev/null +++ b/Mix Power C v1/LIB2.ASM @@ -0,0 +1,28 @@ +; +; Assembly language functions for Mix C and Pascal +; Large memory model +; +; COPYRIGHT (C) 1986 by Mix Software Inc. +; ALL RIGHTS RESERVED +; + GLOBAL + NOLIST + INCLUDE LIBDEF.ASM + LIST + CASE 1 + ENDGLOBAL + +; INCLUDE FARSTR.ASM + INCLUDE FARMEM.ASM + INCLUDE SOUND.ASM + INCLUDE ABSDISK.ASM + INCLUDE BIOSFN.ASM + INCLUDE DISABLE.ASM + INCLUDE INTENT.ASM + INCLUDE SIGNAL.ASM + INCLUDE EXEC.ASM + INCLUDE DTAFAT.ASM + INCLUDE INTRPT.ASM + INCLUDE INTR.ASM + INCLUDE PEEK.ASM +; diff --git a/Mix Power C v1/LIBDEF.ASM b/Mix Power C v1/LIBDEF.ASM new file mode 100644 index 0000000..d5a4c54 --- /dev/null +++ b/Mix Power C v1/LIBDEF.ASM @@ -0,0 +1,150 @@ +; +; Definitions for Power C assembly language library functions +; Copyright (c) Mix Software 1988 +; +LONGNAME EQU >FFFF ; include long (>8 character) names +SHORTNAM EQU >0 ; include short (8 character) names +UPPER EQU >0 ; include uppercase names +; +; Parameter offsets for large memory +; +PARMORG EQU >6 ; offset to parameters +PARM1 EQU PARMORG ; offset of first word parameter (c) +PARM2 EQU PARMORG+2 +PARM3 EQU PARMORG+4 +PARM4 EQU PARMORG+6 +PARM5 EQU PARMORG+8 +PARM6 EQU PARMORG+10 +; +; typedef struct { +; char init; { initialized flag } +; char openflg; { file open } +; int handle; { file handle } +; char *bufr; { start of buffer } +; char *ptr; { address of next character } +; int count; { number of characters left in bufr } +; int bufsize; { size of buffer } +; int reclen; { record length } +; char device; { device code } +; char eofflag; { end of file detected } +; char mode; { read, write or read/write } +; char dirty; { buffer written to } +; char error; { error code } +; union { +; char flagbyte; +; struct { +; unsigned noblank : 1 ; +; unsigned binary : 1 ; +; unsigned ctlz : 1 ; +; unsigned filter : 1 ; +; unsigned echo : 1 ; +; unsigned unbufr : 1 ; +; unsigned fill : 2 ; +; } flagbits; +; } flags; +; char column; { column (text files } +; char fill1; +; char *gpbufr; { buffer used by get & put } +; char *pathnm; { name of file } +; char fill2[6]; +; } fdb; +; +; FILE DESCRIPTOR DISPLACEMENTS +; +FD$INIT EQU 0 ; File initialized if non-zero +FD$OPEN EQU 1 ; File open if non-zero +FD$HNDL EQU 2 ; File handle +FD$BUFR EQU 4 ; Address of buffer +FD$PTR EQU 6 ; Pointer to next character in buffer +FD$COUNT EQU 8 ; remaining characters in buffer +FD$BUFSZ EQU 10 ; Size of buffer +FD$RECLN EQU 12 ; Record length (pascal only) (-1 for text) +FD$DEV EQU 14 ; DISK OR DEVICE +FD$EOF EQU 15 ; At end of file +FD$MODE EQU 16 ; Read, Write or read/write +FD$DIRTY EQU 17 ; Buffer has been written to +FL$READ EQU >02 ; Buffer has been read +FL$WRITE EQU >01 ; Buffer has been written +FD$ERR EQU 18 ; error code +FD$FLAGS EQU 19 ; flags for console +FL$NOBL EQU >01 ; Flag bit for no blank +FL$BIN EQU >02 ; Flag bit for binary file +FL$CTLZ EQU >04 ; Flag bit for ctl/z = eof +FL$LFEED EQU >08 ; Flag bit for filter line feed +FL$ECHO EQU >10 ; Flag bit for echo to console +FL$UNBUF EQU >20 ; Flag bit for unbuffered +FL$APPEN EQU >40 ; Flag bit for append mode +FL$SETBF EQU >80 ; Flag bit for external buffer +FD$COL EQU 20 ; current column +FD$GPBUF EQU 22 ; buffer for get & put +FD$PATH EQU 24 ; Pointer to path string +FD$SIZE EQU 32 ; size of file descriptor +; +DV$LST EQU 26 +DV$CON EQU 27 +DV$DMY EQU 28 +; +; +; --------------------------------------------------- +; CODES FOR FATAL ERRORS +; +E$STACK EQU >81 ; STACK OVERFLOW +E$HEAP EQU >82 ; HEAP EXHAUSTED +E$PACKET EQU >83 ; INVALID PACKET POINTER +E$LEVEL EQU >84 ; INVALID STATIC LEVEL +E$DIVZ EQU >85 ; DIVIDE BY ZERO +E$NOINS EQU >86 ; INSTRUCTION NOT IMPLEMENTED +E$SET EQU >87 ; SETS NOT COMPATIBLE +E$IERR EQU >88 ; UNDEFINED INTERNAL PROCEDURE +E$IOERR EQU >89 ; IO ERROR +E$SETIX EQU >8A ; SET INDEX OUT OF RANGE +E$WERR EQU >8B ; WRITE TO INPUT FILE +E$NOTOPEN EQU >8C ; FILE NOT OPEN +E$GPERR EQU >8D ; GET, PUT FOR TEXT ONLY +E$OPEN EQU 0ECH ; FILE NOT OPEN +E$READ EQU 0EDH ; FILE NOT OPEN FOR READING +E$WRIT EQU 0EBH ; FILE NOT OPEN FOR WRITING +E$NOHEAP EQU 0EEH ; NO HEAP FOR FILE BUFFER +E$PASTEN EQU >99 +E$NOSPAC EQU >9A +; +EOFCHR EQU >1A +; +EZERO EQU 0 +EPERM EQU 1 +ENOENT EQU 2 +ESRCH EQU 3 +EINTR EQU 4 +EIO EQU 5 +ENXIO EQU 6 +E2BIG EQU 7 +ENOEXEC EQU 8 +EBADF EQU 9 +ECHILD EQU 10 +EAGAIN EQU 11 +ENOMEM EQU 12 +EACCES EQU 13 +EFAULT EQU 14 +ENOTBLK EQU 15 +EBUSY EQU 16 +EEXIST EQU 17 +EXDEV EQU 18 +ENODEV EQU 19 +ENOTDIR EQU 20 +EISDIR EQU 21 +EINVAL EQU 22 +ENFILE EQU 23 +EMFILE EQU 24 +ENOTTY EQU 25 +ETXTBSY EQU 26 +EFBIG EQU 27 +ENOSPC EQU 28 +ESPIPE EQU 29 +EROFS EQU 30 +EMLINK EQU 31 +EPIPE EQU 32 +EDOM EQU 33 +ERANGE EQU 34 +EUCLEAN EQU 35 +EDEADLOCK EQU 36 +; diff --git a/Mix Power C v1/LOCKING.C b/Mix Power C v1/LOCKING.C new file mode 100644 index 0000000..44f7aff --- /dev/null +++ b/Mix Power C v1/LOCKING.C @@ -0,0 +1,118 @@ +/* Record locking */ +/* Copyright (c) Mix Software 1988 */ + +#include "locking.h" + +int locking(fd, mode, nbyte) + int fd; + int mode; + long nbyte; +{ + struct intlong { + unsigned int lower; + unsigned int upper; + }; + union { + long l; + struct intlong words; + } v; + union REGS lock; + union REGS time; + union REGS answer; + extern int errno; + int status; + int trycount, sec; + lock.x.ax = 0x5c00; + lock.x.bx = fd; + v.l = nbyte; + lock.x.si = v.words.upper; + lock.x.di = v.words.lower; + v.l = lseek(fd,0L,1); + lock.x.cx = v.words.upper; + lock.x.dx = v.words.lower; + if (mode == LK_UNLCK) lock.h.al = 0x01; + trycount = (mode == LK_LOCK || mode == LK_RLCK) ? 10 : 1; + do { + status = intdos(&lock,&answer); + if (answer.x.cflag == 0) return 0; + if (status != 0x21) { errno = status; return -1; } + if (--trycount) { + time.h.ah = 0x2c; + intdos(&time,&answer); + sec = answer.h.dh; + do { + intdos(&time,&answer); + } while (sec == answer.h.dh); + } + } while (trycount); + errno = (mode == LK_LOCK || mode == LK_RLCK) ? EDEADLOCK : EACCES; + return -1; +} /* locking */ + +int lock(fd, offset, length) + int fd; + long offset; + long length; +{ + union { + long l; + struct { + unsigned int lower; + unsigned int upper; + } words; + } v; + union REGS lockfl, time, answer; + extern int errno; + int status; + int trycount = 4; + int sec; + lockfl.x.ax = 0x5c00; + lockfl.x.bx = fd; + v.l = length; + lockfl.x.si = v.words.upper; + lockfl.x.di = v.words.lower; + v.l = offset; + lockfl.x.cx = v.words.upper; + lockfl.x.dx = v.words.lower; + while (--trycount) { + status = intdos(&lockfl,&answer); + if (answer.x.cflag == 0) return 0; + if (status != 0x21) { errno = status; return -1; } + time.h.ah = 0x2c; + intdos(&time,&answer); + sec = answer.h.dh; + do { + intdos(&time,&answer); + } while (sec == answer.h.dh); + } + return -1; +} /* lock */ + +int unlock(fd, offset, length) + int fd; + long offset; + long length; +{ + union { + long l; + struct { + unsigned int lower; + unsigned int upper; + } words; + } v; + union REGS lockfl, answer; + extern int errno; + int status; + lockfl.x.ax = 0x5c01; + lockfl.x.bx = fd; + v.l = length; + lockfl.x.si = v.words.upper; + lockfl.x.di = v.words.lower; + v.l = offset; + lockfl.x.cx = v.words.upper; + lockfl.x.dx = v.words.lower; + status = intdos(&lockfl,&answer); + if (answer.x.cflag == 0) return 0; + errno = status; + return -1; +} /* unlock */ diff --git a/Mix Power C v1/LOCKING.H b/Mix Power C v1/LOCKING.H new file mode 100644 index 0000000..9155bfd --- /dev/null +++ b/Mix Power C v1/LOCKING.H @@ -0,0 +1,10 @@ +/*$no list*//*$no trace <<< locking.h >>> */ +/* Copyright (c) Mix Software 1988 */ + +#define LK_UNLCK 0 /* unlock the file region */ +#define LK_LOCK 1 /* lock the file region (10 attempts) */ +#define LK_NBLCK 2 /* lock the file region (1 attempt) */ +#define LK_RLCK 3 /* same as LK_LOCK */ +#define LK_NBRLCK 4 /* same as LK_NBLCK */ + +/*$list*//*$trace <<< locking.h >>> */ diff --git a/Mix Power C v1/LONG.ASM b/Mix Power C v1/LONG.ASM new file mode 100644 index 0000000..ba22085 --- /dev/null +++ b/Mix Power C v1/LONG.ASM @@ -0,0 +1,524 @@ +; +; Copyright (c) Mix Software 1988 +; +; --------------------------------------- +; LONG ABSOLUTE VALUE +; --------------------------------------- +; + IDT LABS + DEF LABS + DEF labs +labs equ $ +LABS MOV BX,SP + MOV AX,[BX][%PARM1-2] ; GET L1 + MOV DX,[BX][%PARM2-2] ; GET H1 + TEST DX,DX + JNS POS + NEG DX + NEG AX + SBB DX,%0 +POS RETSEG + END +; +;---------------------------------------------------- +; LONG MULTIPLY +;---------------------------------------------------- + IDT $_LMUL + DEF $_LMUL +$_LMUL PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] ; LSW OF MULTIPLIER + MOV BX,[BP][%PARM2] ; MSW OF MULTIPLIER + MOV CX,[BP][%PARM3] ; LSW OF MULTIPLICAND + MOV DX,[BP][%PARM4] ; MSW OF MULTIPLICAND + PUSH BX + XOR BX,DX ; SIGN OF RESULT + ROL BX ; SAVE IN CARRY + POP BX + PUSHF + TEST BX,BX ; CHECK SIGN + JNS MUL01 + NEG BX + NEG AX + SBB BX,%0 +MUL01 TEST DX,DX ; CHECK SIGN + JNS MUL02 + NEG DX + NEG CX + SBB DX,%0 +MUL02 PUSH DX + PUSH AX + MUL CX ; LSW*LSW + MOV SI,AX ; SAVE LSW OF RESULT + MOV DI,DX ; MSW PARTIAL + POP AX + POP DX + MUL DX ; L1*H1 + ADD DI,AX + MOV AX,BX + MUL CX ; L2*H1 + ADD AX,DI + MOV DX,SI + POPF + JNB MUL03 ; NOT NEGATIVE + NEG AX + NEG DX + SBB AX,0 +MUL03 XCHG AX,DX + POP BP + RETSEG + END +; +;---------------------------------------------------- +; unsigned long multiply +;---------------------------------------------------- + IDT $_LUMUL + DEF $_LUMUL +$_LUMUL PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] ; LSW OF MULTIPLIER + MOV BX,[BP][%PARM2] ; MSW OF MULTIPLIER + MOV CX,[BP][%PARM3] ; LSW OF MULTIPLICAND + MOV DX,[BP][%PARM4] ; MSW OF MULTIPLICAND + PUSH DX + PUSH AX + MUL CX ; LSW*LSW + MOV SI,AX ; SAVE LSW OF RESULT + MOV DI,DX ; MSW PARTIAL + POP AX + POP DX + MUL DX ; L1*H1 + ADD DI,AX + MOV AX,BX + MUL CX ; L2*H1 + ADD AX,DI + MOV DX,SI + XCHG AX,DX + POP BP + RETSEG + END +; +;----------------------------------------- +; DIVIDE LONG +;----------------------------------------- +; +; +DIVBY0 EQU >85 + IDT $_LDIV + DEF $_LDIV + DREF $$ARTERM + DREF errno + FREF $_FATAL +$_LDIV PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] ;BX=LSW OF DIVISOR + MOV AX,[BP][%PARM2] ;AX=MSW OF DIVISOR + MOV DX,[BP][%PARM3] ;DX=LSW OF DIVIDEND + MOV CX,[BP][%PARM4] ;CX=MSW OF DIVIDEND + CALL DIVIDE + MOV DX,BX + XCHG AX,DX + POP BP + RETSEG +; +;----------------------------------------- +; MOD LONG +;----------------------------------------- +; +; + DEF $_LMOD + DEF $_LBENCO +$_LBENCO EQU $ +$_LMOD PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] ;BX=LSW OF DIVISOR + MOV AX,[BP][%PARM2] ;AX=MSW OF DIVISOR + MOV DX,[BP][%PARM3] ;DX=LSW OF DIVIDEND + MOV CX,[BP][%PARM4] ;CX=MSW OF DIVIDEND + CALL DIVIDE + MOV AX,CX + XCHG AX,DX + POP BP + RETSEG +; + DEF $_LUDIV +$_LUDIV PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] ;BX=LSW OF DIVISOR + MOV AX,[BP][%PARM2] ;AX=MSW OF DIVISOR + MOV DX,[BP][%PARM3] ;DX=LSW OF DIVIDEND + MOV CX,[BP][%PARM4] ;CX=MSW OF DIVIDEND + CALL UDIVIDE + MOV DX,BX + XCHG AX,DX + POP BP + RETSEG +; +;----------------------------------------- +; MOD LONG +;----------------------------------------- +; +; + DEF $_LUMOD +$_LUMOD PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] ;BX=LSW OF DIVISOR + MOV AX,[BP][%PARM2] ;AX=MSW OF DIVISOR + MOV DX,[BP][%PARM3] ;DX=LSW OF DIVIDEND + MOV CX,[BP][%PARM4] ;CX=MSW OF DIVIDEND + CALL UDIVIDE + MOV AX,CX + XCHG AX,DX + POP BP + RETSEG +; +; --------------------------------------- +; ldiv - divide and return both +; quotient and reamainder +; --------------------------------------- +; typedef struct { +; long quot; /* quotient */ +; long rem; /* remainder */ +; } ldiv_t; +; +; ldiv_t div(long numer, long denom) +; { +; ldiv_t s; +; s.quot = numer/denom; +; s.rem = numer%denom; +; return s; +; } +; + IDT ldiv + DEF ldiv +NUMER EQU PARM1+4 +DENOM EQU PARM3+4 +STRUC EQU PARM1+2 +; +ldiv PUSH BP + MOV BP,SP + MOV BX,[BP][%DENOM] ;BX=LSW OF DIVISOR + MOV AX,[BP][%DENOM+2] ;AX=MSW OF DIVISOR + MOV DX,[BP][%NUMER] ;DX=LSW OF DIVIDEND + MOV CX,[BP][%NUMER+2] ;CX=MSW OF DIVIDEND + CALL DIVIDE + MOV SI,[BP][%STRUC] + MOV [SI],BX + MOV [SI][%2],AX + MOV [SI][%4],DX + MOV [SI][%6],CX + MOV AX,SI + POP BP + RETFAR +; +;------------------------------------------- +; LONG DIVIDE ROUTINE +; ------------------- +; INPUT : CXDX=DIVIDEND +; AXBX=DIVISOR +; OUTPUT: AXBX=QUOTIENT +; CXDX=REMAINDER +;-------------------------------------------- +DIVIDE MOV SI,AX + XOR SI,CX ; MSBit of SI = sign of result +DIV04 TEST CX,CX + JNS DIV05 ; DIVIDEND IS POSITIVE + NEG CX + NEG DX + SBB CX,%0 +DIV05 TEST AX,AX + JNS DIV06 + NEG AX + NEG BX + SBB AX,0 +DIV06 CALL UDIVIDE + TEST SI,SI + JNS DONE + NEG AX + NEG BX + SBB AX,0 + NEG CX + NEG DX + SBB CX,%0 +DONE RET +; +;------------------------------------------- +; UNSIGNED LONG DIVIDE ROUTINE +; ------------------- +; INPUT : CXDX=DIVIDEND +; AXBX=DIVISOR +; OUTPUT: AXBX=QUOTIENT +; CXDX=REMAINDER +;-------------------------------------------- +UDIVIDE TEST AX,AX + JNZ UDIV01 + TEST BX,BX + JZ DIVZERO +UDIV01 TEST DX,DX + JNZ UDIV04 + TEST CX,CX + JNZ UDIV04 + XOR AX,AX + XOR BX,BX + RET +UDIV04 TEST AX,AX + JNZ UDIV32 +; ; MS 16 bits of divisor = 0 + MOV AX,CX ; Upper word of dividend + MOV CX,DX + XOR DX,DX + DIV BX ; Divide 0:upper by bx + XCHG AX,CX ; CX = quotient, AX = lsw + DIV BX ; Divide remainder:lower by bx + MOV BX,AX ; CX = quotient MSW, AX = LSW + MOV AX,CX + XOR CX,CX ; remainder is 0:DX +EXIT RET +; +; Divisor is 32 bits long +; since msw of the divisor is non-zero, the upper 16 bits of the +; quotient must be zero, and only 16 cycles are needed to divide. +; +UDIV32 XOR DI,DI + MOV BP,16 +DIVLOOP SHL DX + RCL CX + RCL DI + CMP DI,AX ; Fits in msw? + JB NEXTBIT + JNZ TOOMUCH + CMP CX,BX ; upper words equal, check lower + JB NEXTBIT +TOOMUCH SUB CX,BX + SBB DI,AX + INC DX ; Quotient gets a 1 bit +NEXTBIT DEC BP + JNZ DIVLOOP +; +; Quotient is 0:DX, remainder is DI:CX +; + XOR AX,AX + MOV BX,DX + MOV DX,CX + MOV CX,DI + JMPS EXIT +DIVZERO MOV AX,DIVBY0 + MOV %[errno],AL + TEST %[$$ARTERM],%>01 + JZ IGNORE + PUSH AX + CALLFAR $_FATAL + POP AX +IGNORE MOV AX,>FFFF + MOV BX,>FFFF +POS RET + END +; +; ----------------------------------------- +; COMPARE LONG +; ----------------------------------------- +; PUSHES A RESULT BYTE +; FF FOR LESS THAN +; 00 FOR EQUAL +; 01 FOR GREATER +; + IDT $_LCMP + DEF $_LCMP +$_LCMP PUSH BP + MOV BP,SP + XOR AX,AX + MOV CX,[BP][%PARM3] + MOV DX,[BP][%PARM4] ; GET L2 + SUB CX,[BP][%PARM1] + SBB DX,[BP][%PARM2] ; COMPARE MSW + JG LCMP06 + JL LCMP07 + TEST CX,CX + JNZ LCMP06 + POP BP + RETSEG +LCMP06 INC AX + POP BP + RETSEG +LCMP07 DEC AX + POP BP + RETSEG + END +; +; ----------------------------------------- +; compare unsigned long +; ----------------------------------------- +; PUSHES A RESULT BYTE +; FF FOR LESS THAN +; 00 FOR EQUAL +; 01 FOR GREATER +; + IDT $_LUCMP + DEF $_LUCMP + DEF $_LFIXUL +$_LFIXUL EQU $ +$_LUCMP PUSH BP + MOV BP,SP + XOR AX,AX + MOV CX,[BP][%PARM3] + MOV DX,[BP][%PARM4] ; GET L2 + CMP DX,[BP][%PARM2] ; COMPARE MSW + JA LCMP01 + JB LCMP02 + CMP CX,[BP][%PARM1] ; COMPARE LSW + JZ LCMP03 ; EQUAL + JNA LCMP02 +LCMP01 MOV AL,1 ; GREATER THAN + JMPS LCMP04 +LCMP02 MOV AL,>FF ; LESS THAN + JMPS LCMP04 +LCMP03 XOR AX,AX ; EQUAL +LCMP04 POP BP + RETSEG + END +; +; --------------------------------------- +; LONG BITWISE AND +; --------------------------------------- +; + IDT $_LBITAN + DEF $_LBITAN +$_LBITAN MOV BX,SP + MOV AX,[BX][%PARM1-2] ; GET L1 + MOV DX,[BX][%PARM2-2] ; GET H1 + MOV CX,[BX][%PARM3-2] ; GET L2 + AND AX,CX + MOV CX,[BX][%PARM4-2] ; GET H2 + AND DX,CX + RETSEG + END +; +; --------------------------------------- +; LONG BITWISE INCLUSIVE OR +; --------------------------------------- +; + IDT $_LBITOR + DEF $_LBITOR +$_LBITOR MOV BX,SP + MOV AX,[BX][%PARM1-2] ; GET L1 + MOV DX,[BX][%PARM2-2] ; GET H1 + MOV CX,[BX][%PARM3-2] ; GET L2 + OR AX,CX + MOV CX,[BX][%PARM4-2] + OR DX,CX + RETSEG + END +; +; --------------------------------------- +; LONG BITWISE INVERT +; --------------------------------------- +; + IDT $_LBITNO + DEF $_LBITNO +$_LBITNO MOV BX,SP + MOV AX,[BX][%PARM1-2] ; GET OPERAND + MOV DX,[BX][%PARM2-2] + NOT AX + NOT DX + RETSEG + END +; +; --------------------------------------- +; LONG BITWISE EXCLUSIVE OR +; --------------------------------------- +; + IDT $_LXOR + DEF $_LXOR +$_LXOR MOV BX,SP + MOV AX,[BX][%PARM1-2] ; GET L1 + MOV DX,[BX][%PARM2-2] ; GET H1 + MOV CX,[BX][%PARM3-2] ; GET L2 + XOR AX,CX + MOV CX,[BX][%PARM4-2] + XOR DX,CX + RETSEG + END +; +; --------------------------------------- +; LONG BITWISE IMPLIES (NOT A) OR B +; --------------------------------------- +; + IDT $_LIMPL + DEF $_LIMPL +$_LIMPL MOV BX,SP + MOV AX,[BX][%PARM1-2] ; GET L1 + MOV DX,[BX][%PARM2-2] ; GET H1 + MOV CX,[BX][%PARM3-2] ; GET L2 + NOT AX + OR AX,CX + MOV CX,[BX][%PARM4-2] + NOT DX + OR DX,CX + RETSEG + END +; +; --------------------------------------- +; LONG SHIFT RIGHT WITH ZERO FILL +; TOP OF STACK WORD CONTAINS THE COUNT +; TOP OF STACK-2 IS THE VALUE +; --------------------------------------- +; + IDT $_LSHIFR + DEF $_LSHIFR +$_LSHIFR MOV BX,SP + MOV CX,[BX][%PARM1-2] ; GET SHIFT COUNT + CMP CX,32 + JNA LSHFR01 + MOV CX,32 ; LIMIT TO 32 +LSHFR01 MOV AX,[BX][%PARM2-2] + MOV DX,[BX][%PARM3-2] + JCXZ LSHFR03 +LSHFR02 SHR DX ; SHIFT + RCR AX + LOOP LSHFR02 +LSHFR03 RETSEG + END +; +; --------------------------------------- +; LONG SHIFT LEFT WITH ZERO FILL +; TOP OF STACK WORD CONTAINS THE COUNT +; TOP OF STACK-2 IS THE VALUE +; --------------------------------------- +; + IDT $_LSHIFL + DEF $_LSHIFL +$_LSHIFL MOV BX,SP + MOV CX,[BX][%PARM1-2] ; GET SHIFT COUNT + CMP CX,32 + JNA LSHFL01 + MOV CX,32 ; LIMIT TO 32 +LSHFL01 MOV AX,[BX][%PARM2-2] + MOV DX,[BX][%PARM3-2] + JCXZ LSHFL03 +LSHFL02 SHL AX ; SHIFT + RCL DX + LOOP LSHFL02 +LSHFL03 RETSEG + END +; +; --------------------------------------- +; LONG SHIFT RIGHT WITH SIGN PROPOGATE +; TOP OF STACK WORD CONTAINS THE COUNT +; TOP OF STACK-2 IS THE VALUE +; --------------------------------------- +; + IDT $_LASHIF + DEF $_LASHIF +$_LASHIF MOV BX,SP + MOV CX,[BX][%PARM1-2] ; GET SHIFT COUNT + CMP CX,32 + JNA LASHF01 + MOV CX,32 ; LIMIT TO 32 +LASHF01 MOV AX,[BX][%PARM2-2] + MOV DX,[BX][%PARM3-2] + JCXZ LASHF03 +LASHF02 SAR DX ; SHIFT + RCR AX + LOOP LASHF02 +LASHF03 RETSEG + END diff --git a/Mix Power C v1/MEMORY.C b/Mix Power C v1/MEMORY.C new file mode 100644 index 0000000..4dc91ac --- /dev/null +++ b/Mix Power C v1/MEMORY.C @@ -0,0 +1,21 @@ +/* Copyright (c) Mix Software 1988 */ + +char *realloc(oldptr, newsize) +char *oldptr; +int newsize; +{ + char *newptr, *malloc(); + if (oldptr == NULL) return malloc(newsize); + if (newsize == 0) { + free(newptr); + return NULL; + } + if (newptr = malloc(newsize)) { + if (oldptr == NULL) return newptr; + memcpy(newptr, oldptr, newsize); + free(oldptr); + return newptr; + } + else return NULL; +} + diff --git a/Mix Power C v1/MERGE.EXE b/Mix Power C v1/MERGE.EXE new file mode 100644 index 0000000000000000000000000000000000000000..7ca5e12f8844f4b676b7a27a83f76b0ba3b86cd9 GIT binary patch literal 18512 zcmb_^34B!5z5lt(+_{+~lL>1C3=?(;OF~%G00x8!S{$;}utdg(5`0($Uzka-l|URp zZZ1LF_qx#*A4R*kV%2s+o|q6#z=#^KHGs89uw@*rU}^vb?*IEc_s&d0;MIQqFFMJ+ z=lss^{LXJbzjKD$mlm**j4=`a8^-f86aM3XixtV~XrrGyw2$jQ6hm8>?p5|~XZwD} zUi(lEw#dc$^#z4RCB-}JY_br1Jt-uz`k#me#XFLjEC*kgb&t5L^^V}Dvi9+=S0v3N zYE8z_f*pzMyDa#+h~C^#tq!v_iEUz09EycQCLCIGfmR{L5LJlU z8Smx>{{U)CVx>S8oufjGbZBR4S1KH1i}IYrVkpO4IWZrrHE;Ed3SM?sDf?6wzK#Vi zs~c>1jHIA3;Ls{Y?69%>nAVJrfE1nw0QZK}5^9f4IwF!0ax>7_z3mDR>Lgk*n_e-Z z#xpAGRQCb3J{#J$+FLxLzyJ`D438MB64ecpYJIZg6N_UAUf;TMbm>-mjb}7abSL5v z9|R8OHg5oL%=vmioCxh__32UpM`mY@5~Ma09I6-*7!*>etF}rmC|*Q^9qbS2R?x>K zH-?K=y(SNp|BZ+8HFzk;$(N%%?A`_*c7LTelZPNnuJI_GhcO6?cXCfQm_xd;L5`f@ zD^mH2plI1$5y3-p9}5OZAA&iiT5ScVWzK222dBkITU^Hs=ZlizY!_RUmn4C8*Em?w zE7HDsf;K%0V=8wq7GA{~f}j2$7(npTezZ8^T8}BXai(&^YAMjFx*3+NSBcvBg_|3o z>Ddeesh2ped6e!P1Q_w_y;`5Do$&}wx<}b+kGw%`$<4ir;7lbYI<{i1@p$};{x{6p|lhxTz)G{GvDJ0vi_XdK8sxVfP)kc5_G zzk=V6fV4QTU@;s{BG((oves}BL&u;%N_VM;XR>eeHxP_~RAz4y+iVAo0w7+D z34@n!+^A}2gN^SNM*4C;b|p+RkkrZS$O);rcBPZc9g(xPB2kyU+_7~tOtFSsP`4mR z4v2y&SK|8ip5jice=#m@kF0xLTGQ5)@HiH_Re&YK%aJ;MD3%mQl~D;fuEJ(gM#N!L zZhn>9ih{YUI1eo)e+L0!x>=(o?dBHrvVzchfd?6|x(Qs7^$IaK3y~O3WigzJ(p^SRS(jyBEa4k?@hM4*ft41VX zEV~O9MwWx%^EOFGYk{{R`?(No6k(arGP0{GB_8YGaun^n&B3&$W;c;v`m(8?$B$Utmy21yBnfdryn%kS3C z*hJ)QSesU%!iM4@UiC-an5<8UG!wswp6XA10-}TgBP%9vZ({;-Infk^Ug3n7_D?dV z$q<~A`t3|0Ue@~hP~MkG&jx34r-(;$K>cV5ZlwUc=R+*^lPh_KI$Q-&iJ&RFA^TuK zAy7Ffg$(XnAxI{YhotbFm_x0r7HCBroy4|dDmm(F>z+o}4yzH&AmrU>(YLG=z!Hrs zl3HL?s1}-Jc7TXqA{>~nc^u}Py2p|0A(s>9=wRLFAWty!PUeT;&F7m~jF~pW>xi^~ z9hxr*!!tc90>y9x7^5$cXOiJb(!HwTQAwm^jL1QJNl>xSApv74A>(Tk***{@*UPLp zbjcgJ$t4xm#8Uki`rsXkgXh2N`h``Uyopz`5E?zG-G2buM8cL-1&4 zV^lXXPb|NnY4z=sp*eD!32B{X;^1i25sa%Os`#14RCTJ^G`v z+Oo*hvqjzXY$_~K3=I;mt!Gyi8xr8+`u`HOb|@}o1q=!DZ~5%1xd5yN(7}Qg3@jXMshhWxwafF?dT=9;H(cs7Eq%3?lpz@_*I1X zLlR=#Fc0;Tr^WOu-B2&7{%1_8_r;}}%(jqw3@KNY>RnfnDtW+KARrIeOO<$|733hQ zSdgP<9`s~3iMwbk)vtRDn4;k)yCLRmcO0|MU53c^`vY|QAJ%~3aqS<~cHLjDw{RGYV3t4ZJ+RHn0 zKdk&*ORtl(^d{++>W<6C;w5^=wl|Bk0fw}9kAT0IB>mIE0$QLxt6tLIstz+D^PRSE zPDAH2e1w+%s+7~PyG7dlh9spwA^YX>pGTzn%Lbv-(qEJGrukUg>AY>nr2V@;lXjn# zGWQ=jvHNqWy6G!JZ`F^q*x@o>m9%_O%a=0`>~56wb}dC)Bx;M~eVf>J1zfF3+H}EI zK77=shlJ$7kWuT zClooyTX%IzkDT(0dyMK?$KkB}_IiOC=|`oP7aYpitIIDZ9Lm^pIdamhbk)Bl*H$^T zo9lzhYmX`j^}5$lya*~Gu<3|rs@7~&po%0S!!bw)$VrHPC1hatAe1aNv-s*ymm&#k z@i-U@y(-u494ge=SwV5(jup`&Oh1G)edpamjh(6zYSt;pSqlFMu>j9AM>78;9dTOQ zGEUI9|C>-#qGokbcH0jro0&GtNJ)$>cMEz2p^CiJqPz!vsI79>e;^mvAH(NueA@B( zlbqe4dHQI`Oo0xmEB(d?KAb;#oZa8Lb##05B-Mgg-JWNm*f|cAV+Vr*8&aXjNkjRQ z9Qgn{D>?EfLwQ?{yc-#}7@MK`p~A#myI;jF`efHcWAsGhUU4`xn44W-nXHpdV1H-X zg2@Q1I}0u;l*I}nGS%M}Z}lX^y2epHGJ(;OAtLM|wv6X_pk3cN9)xM0ba{06vaLk6s z8U7A4HRj)0;JT{=hv!=$UKSXP3?&LR*+eU=w;_(2F;pr0vnqmS?F@ZQpL3piV zC?ClBmN8JHX+oU?iJP19wrVvjn8k`Jz5l^U1V3 zKMXbTp^k(-J#-_)C#NKivnG+9f>)7ieIuIfHxVexIXu1Ma3fKSw;=Wz;Pp01RSer%P1ks``FG^cpPuf5ir!@Ou_Td85vMi!R_BBGHIs^L>axMW!?Y^PH zK81zf0iouI*aA{mB5m|gPoMRkO!~Ybx_QM&f1-9K7rd*AX120E?LC|;q-QphA$pUt z4P~iMFN$;v1RQbf$Bz=}e=`y2X?kZTI-nL8{>;&r&s}CyIn#{@5H4IfO0zMk!pu z5Z;9iQVCp{0avDZ21HkfJq`?JTYHR!2}}hG9h6gQTjpXf22i*Dqkj_$i?NTO8VTZ% zL-Gv3zBY{JQ z-F)(^EwoFEDZtxeFPr}6at}X_GJ`wnP;ZM)a~nC-t@c`92DUo;1QuQ;a!d21;W?LE z9iL+Zveoxwg&9yGW7^yJyd_%-Yh%gaprU!wEGgJpJZUh~S$~q5AKUn}>H{ij-f5B4 z;H+b4!e$;#TdB!JjdPkI3X3Sa-h;^wY4Hp~j_nzudk5(yY1-G=)JCaZAlQHjR=xn1 zWK=3frEFA+#`GS9xU#z-6RcJGuxEV#ACLt9fq-+H<&-D(2myWvCnu)EBY{IZlP5Hh z#_*F2?lfX`I3D_cYlpH9xDY~XP##A$W ztSh{fEr!RgUzN}+lX#GwSJ$xP>Pq&A{a#jN&u3nH8S~iZu{rj8*kJoQ_OSc_J1nhd zKam!*|B}|SrBZ;or4{U?xC)QjAb>+y`4{j+1ShX_{Uj}=i7Xx zdjI@hUL&^BUWQxpO$^uc86|>tR{Kid36D|KBMy__FfBrY!-dvIy_w}47JrjD!X;k< zP3^Ci3cNm@hMKkyHI#(lEQBMyBGIqt(+KtMlZKQ&iTcSO)|7K&IGQh=WlPl@CqD@l~xaK|527DrVvik%_d)1oh!(5Y62#%)OHBdYhX-q2Io_D{2BD zWhw#_r=l-M)wkK6)xE*fw;(u+Y)uI*=Bev?_nD zPhzRoaNU;xe!)u>Kn4(XBDNuB*>h|o+`r%j)2gC8iQ|g=4d9Tzx%im-FweizxL9#i z5v+1J)(t`(lQ=FCAs!LCpI~DauW(K=H$!_J?EBi0?8E0ear71CBi|-<>nV!&ShocD z323k?$yF|eZwJeh9P3bub@rGl$(jl$8&(%T;PS{8gJG^ow&~z8C`+>8$^o%C0=k?? zCHA_y(G_L*l|4l`*)c^y^?SNiz^^x8;RuM4b=rDv{K zsDLSrB2#(`rZk33>8Y40RUwvL3kmicR8DeLjj8pGB4MO)1x$mbnS;)?oqKn70NVgB zc98wL+g(ra?sms}2604#xZR=dOa!33OY}=@2Gkjui!1yNG+_)G-}<;&^ovrPc)(Ao z;T4w1kq_a>hj25AH+Y6z%MyDMkj&;q3Gn{&dC4~U9O-;gI4qcdPlO^{Y$1f+_ApS_ zH4O9$gqDGhA_H|ngRFBl7e8ilN7b~}=ivH+!#$`1_;`sbS6qZuqk9??KnqOREcVkS zrP6`E$4YTzI3KFujQ5#%vRIhXeU8zTOmCR^yFzAG}EZxpsQcCxRsB6;bR4$#1Zo6Nw2XxfWa?X=us ze7RG!kDEQ?nLeux$A8(nEgz@$&Dgwvrt#+SfoFn1As#!%jnN&WKOtB(q2Gr1&JEQK z8`Rs~Gga*to&B;mKXM$=`W4z30i|_3Yj`HaN5&8TdW_8X;;{F8zD6g*-tamo6=5I? z%%*}-65EM7w;U?~qgGwN$EKaHT{(rXkY6;SU^$c@Cr;|QlGJ$5O)R=1zZ;f&?(fuv zlV_QqJj>>hFm4|}P4^H3&8URKc)iMrTPg6);zk^+^5bwiw6^1XQy~#3{ALRdCoB3` zRs)5G)rea2Oq7$WWJD-d7TGt}mfP%CQ9b3c(gL!hrbMBF zPOn!3Os3_a%1URj94-H`eS4`*0i%UQsMF4645 zzOgyN*_E`cwbs{t8CCEg2 z)Q1Y$ILd+Y7uWy6#*J6^45~iSiS4thdxz))Ub3A#JiJXSaa5n&#DZUeIDQ#SL4~F; zBH<7PzV)zD& z&v`xC)v%lW_wOjK-pv9@aqtM7i8T~1gg+0@wjN!K9}iZxDzo)pnycO zxxNQ>mx+Y7Vn>XAU_Ay@k*B1?J^@m@5JtLVw-0U(Dp>C0G%;w=E0CARl(+hX z3?MAROShGNSL3Uaac#9dmF7Dx%z+Yqj_FM|6;?R~xfYb=i(3##1;PJW*Ua)(72 zO3S$G0&LDGHfSb1(*L#?a}1wu*e)G)YTP8%OGJtSim3!RB|wb93PFFIU35eq6+;%o z1;f4!H>bREuu7J(Z@8Y+EOxIlw>fYsyNlmKG@OmL$orsiP)}yLK_*($P=(cPb!;}4 zNDH(gBBtifFZ>XeSFhM^Y=@^reZsmyjdE1|b~LVw=jX-52l6(iKsGV5(loT8z5$y> zDy<+een_G*<${@ew{r=`!6?`J zv#!I3(Fy)uhP$!2gerZ!3w+P_LcpmAQBUG3@Thy!cq9{T7q$Y z$IL;@Z`*3iKlxX}(73F%BbBCg%oyZ<8O^u(pF8<^&&hjEd?d0N6S$$~+gZ+GTFU~p zBZE_ud!Ss@4;0c$N_4++vGYm&L*J6I3smh+MMA#l$b7S7TED*M zZ!7u&$DxdM{Ywh;bX}p-DS2tjTonhCSl&`?F5Q>>N93otqoK`Jcn5|80moOQzkevB z{Pm?0V67GRzhcFFu@P&rcR)ryW%F_W{axT!V0BG?-`}_c`8ulkK^R&)2oH@5!ABB5joB!u~Et0h^s3QhF}RO>|;xO z(4u9n#XFqrM^Y)4qecD>VmokiKz(+G!#{ZPsggomwN7E>($dl;K9bX+lOF>Cg!yP+ zrut8yKa`A%LM8|SJdLd%4%%KoNOt7rJ1W0~Ft7rX^j`8nJH)YMEVOE)Lexd&aU1v` z_)EL;`{wymN*1Bszk{)#Nu^7d+~o_gyrNQ4>rV3Brxp#%D)FO;=~N_e@!=d;r>^y5;go-b?p z3Lj1La4OKpDZuQQjf7gFLdK6TYb`1UAw)&Tglo}@5ky_NOW%m2Uk4#Q-&DFZa;CI6 zN-p%Pbm@gA{R3DNHu}q8sAAwYPy$J$lQKJR)fTAwLkg@xdq`<5F}aRmWLc`eUrAgN zzPx}qzZH_`22{eu?9)GhpnnU&x023PsGA;gt_>t3riK_u#HIrZi_4~%FQvzPh)|^b z)ekvWF#i`zV%HUjTWjVzXWZkLXRHd01{PPq-lcpk ziP+3D`=N}6>O9lyKs0OzV&k>;9VuUQ%6zL*#lmHK{(4f^EAvGl5mfL62y!|2}d< z6thKJ7Q>g3JW2Eomh)GIN{&Kd4B7mz2|J%Dk@1|BC#B|Ov5;MiolUG1R41~%ERW)_ zl~TphSeP7)%S#>|#^y`X?Bz1W#@!!F+#tv%0YIJw$IaL1^`RO8?~_C@&TGP43j@Uk za}K@g+C+dvhJW7dU3h7@!7`C-GKC6+hI|R9eTyoQ6U)eDVB}h0i|yNQ2*Y@;oYeG3pS@ zIwNhSWp7mY0R8=(20mi;xug15oxiG?YmA#`{DfPQqF*K$bmuf&{Nnj@ZRD(5I-le# ztx`4{{!v!{WZr+YurRviUIII|>*tYYbw0VQl_ZK;H_AQ0+iukxsX1Ssxtx`&Gr!9! zr3r3kHO;1`rD(!_*=lm*0tXbhJOTc!Qbvvn#I2v?VUy2)asDgkR;uN6I(k?F38J}= zNMc>eo08!_8+sVAne1b6PD7-_9Kc~ChxG%&MrqSWmxC9Sby6L^wv^r|<)&0f;Topf zGaF|rY~4^jMSoOebYb3ciu)u8M95|-^7+5$rT0=qh%MQup`WF_w_roYN?)9(fcAA<3b8`%23Nuk@nDLlQ$P7!Ed*C17}xn7){^= z;J7o(^eTf()Q##xG%fTvZ&~Yn&Z;OtZi!l%P@b6URs4<$d5;iL_81Y-GPQ+r^#wPp zkm}q_&sX$CYKPMHRa^VXuS`4C?uSxq^F&+%)aJ>xm9iF4^h23%YqzV_7Y5L{0W8?! zAO-A@kdQ*VxYx*Cp;V3|gbyj(j&5&6dO+ZngG++V4i4zkS2KNuV)$jlFSb(X4qY}g zE3dO-R661ezH^6~23%HdQy?+-+y=XJ)+=3DcnP<*n>wGoxOjUzygm0=++%FdSKxn4 z|H2){%X#%8s~gPrKBXMWFsALM`a!3-gtm?K=TUe?o>YGUe^rWV;2TS1)#g8k@H~5- z{T_j6AAYy8GwdC9g#8X}PxJqNhv&Wc#NU3$-pAWmL5xmT_&ci$aYxw5Q$ynD^^`^#n$T3RI@9C3o~ShxIM%yWMkjaj|w?(*g34|1^a z1Z)19IB}vm0w{X|=H0S(jlX>DY7bx?Y=reQ5r0`FN||ex-@UpFG`a67FI(=%Q`!9w zaOCE~?qub6vs;$08SO{oniXc_#M^IOe6@BHuCja;;lUy;Qpc=VweCCam4Vf($2w?O zbhx*yG74kj{paJ^Qnq64nli}uKDbNf7KBR@{<1VC2r@kkWCHz({M*N*aC-V#1g;L>|=rl;C6oMHN2=f7U_=*_ik{!+UWL3d?#yh=9NsE@D5+dqGHmkYoLf zt?mUOvsZ0?f`Ac7gP`Y`Qa#@GGl5R^=zOqNk=f5B&vO6r)$X$La;VMl_3M)z?6Tom zy>_{O)tY{e*1?wzqF;h<4ViU%u4&WI<>OD`?g6U88O76POF24fLnsHN&`6)6eVGle}H~;nAP% zP&%KEh@DS9a(MlS7m+ZXd-urcZTmCd-M+v2oim2s%-@gU{aE$eXN*V_O{-61?Ba9S z!hBtQ0Y!t9=cK0X4bSQ4M+w)TJRkY1knUu<)4`-xeSpfUBQCc6`1Yo+wzugg>yy~m z6OBpNK}y3}4*Q?kg{)!r3j9kauh0H2J1~0(dx5>e-kSaH>_5XDMOYtUoG?qcT__dS z3O^TK5L$&cAuOokpJ!)?qs2*LiMU35Sp2^Dg!qzpSZo(RnypCJNgvM+&;D%o3h6#% zC+nrNvwtS-k$x|IIs1>&aj8>El?Tap%GI(s=jZY-<-PJd@*ibo&fT_h+hveSS{)L-2)KlR(G^ZPFD zTie&(e^vkBfL8~c8!&a?&VdaBPYujTyDRON*DV@!YS8_Ij|}cV^pT-WL;o_gkNZ#a zmbok4U%FE=7G?ZL#^H>C!+tQV@9-7FHw}Mj__2A%h7TJteuQU4!HD0FI6m@*(X&T? zI{LveKN|Dun9s*ZV{aV$`q=*CLgP-1OU;~?d2i;<%vUlyGKY*W9)I8Xm&QlNOA`tv zXcP8K*gf%uNnMjxXC3tXHtXZ8IoTE2!zXW={FBMQp8SsI@Z{v2NjVSXyp;1<&Qnuz zr!JkkVd_Uy^QYZ2?fcVynBO_gK0R&vu<1X|4@|F}-sgtQ8>ZYa`Nj)3K9RrZrh9IB mpji@}3LIQ~q4T<$T=g!@o{-7mBOhgi3t!46W6_H!=dfvh3c{*qLEbrw_9OXUS!L#stss8rxyMk}$8a8}j zHAS#-o5-lA2od%k$Bw<+1PRaZm*ti9jVd-ROEEt&2d#xq$+2GRPKcd z9#qz<%2abkrG{1Z!YGdy@K36|)GBY-l1MdM|J)MFyZO9NUx@ZbSiFZn_UTppIpWi< zMw(QsM|>*dKA$4oj=RG=$P4)d@8r+8nlnt{_Z}F1gY<^a%h?!O z%ms$#afzY3_!dLU*jFhcBgBa_;9sJl)Ih_|%Iq9PXqdy!#z* z#5K+XyvwKEVp+&m`ZHU1h_}1Bj9-G-z^o22tA&dVy%1Q`&INqVM~p&Z%iujB)J?;$MqjqrwA&T%Zn0iso9k#be2%T75M}%=ulz%E={3;YdvFuwzC*|R3 z#4QSIhq%X3mrolEeeZ0m!D186u?8k70I~`I#aD7$vZ14OG^F1X&?u%Gwrp)_bg;6^ z0Mk)Ov$U}^DF&3PxP(9PS4NaE)x1_!)TOtl6Ag_Gc?cH?z(}LJ5CIbkMMa&UByQ+l zKD?T|WLsNv3p7`g$X~LW3MSQo3VOSm3ZQ){j(vDIzrDP&p)Hxn1l9)2z}lEv+vi6J zoEY?}ix1iL2_N#i`GoHYKWgEC0m!Z8Ev-qRREX~)rXS4z9i$KtyR1=xed7LPai4PT zXO+uH9i9ZC4pFEl51vcvu*~-i-N&;GJr2Pa)s>hHyc~?^M!s^(|M@H-|DVr}&%zxk zO=DS|ZcTJHgVuS<#el6mt2ZYzLTUk*TRL#NhHGBB|qVCQ%y+Nw25?p1;_IwD$g zdyt-w80zLZhTd0a?nf303eOmeuTAp!XEfT399Rxq2UiaoWLvoUp--JAGIzYlM>8$$ zt*yy6L_V5}Jc>g(vT43o>G_XG=`BPlQm#=tqOh>VB{grONmPEL&iEkA=GYFt?KuTK^B+AH_FKu=poN9YGD@5V$mVvFqXbg+M zs}7FY9(f#vYQ3`rjB(4r`pIg2KdhRBqZBWSaL{pGci`_1Omx%m>qS>!y5)x7W&7^F zP9hlz=ktTS2%Yp2UM5v_F5IlbJS#o0G_S>KT{_d&(7JtWI6SCrLeC3Ju@7%c1CM5w zF(!#wGDsRG={QCi$Hld7?#HPbS|kFOYSxv$ zCp^s9IV6jCL@nF`+w-nUf7k>tTFNAo&k7siWNWYtaJvVm7{lqt^=uu#TrUYW=rV}N z3Pkj*v~#6$RuMVbUOhjFXa_&0C|e6ENx6&ZHL6$nvx7}DA+W1fD9vG$h`gz^2-pcGN->?w7 zBJlhSQq%xKatT=e+>bv8q|6&RL<_lc;LVNF?kk)Vm&-=wl{jQqCfqWBa6akcL8w^R z?nWVv2bt7X2Nqr4z+kCB()hQ4>fj;;A_o>JQJ!RzB7O~1<0<|D_^E}Jha7Cy2IVU# zt`h>x^KFvyBx%F6I68t4de{c+aM ewbBctsHPJg7G%M4EJ8DFjqM}8&Uu=lpZWty^*#0g literal 0 HcmV?d00001 diff --git a/Mix Power C v1/MIXC1.C b/Mix Power C v1/MIXC1.C new file mode 100644 index 0000000..bd04ebd --- /dev/null +++ b/Mix Power C v1/MIXC1.C @@ -0,0 +1,277 @@ +#include +#include +#include +#include +#include + +/* Functions present in Mix C that are not in the Power C + standard libraries. Also includes functions (such as + chmod) whose definition has been changed. For portability + from mix c, this library should be searched first. + It is recommended that these functions not be used in + new programs. + */ + +typedef union { /* register structure used by asm and asmx */ + struct { + char al, ah, bl, bh, cl, ch, dl, dh; + } byte; + struct { + int ax, bx, cx, dx, si, di, bp, es, ds, cs; + } word; +} MREGS; + +int asm(address, bx) + int address; /* address of code (in data segment) */ + int bx; /* value to pass in bx register */ +{ + MREGS r; + r.word.bx = bx; + return asmx(address,&r); + } + +int bdos(fn, dx) + int fn; /* function number */ + int dx; /* value to pass in dx */ +{ + union REGS r; + r.h.ah = fn; + r.x.dx = dx; + intdos(&r, &r); + return r.h.al; + } + +chain(command) + char *command; +{ + static char nullchar = '\0'; + char filename[130]; + char *p, *q; + int argc; + char *argv[32]; + p = command; + q = filename; + while (*p != ' ' && *p != '/' && *p != '\0') *q++ = *p++; + *q = '\0'; + argv[0] = &nullchar; + argc = 1; + while (*p != '\0' && argc < 32) { + while (*p == ' ') ++p; + if (*p != '\0') { + argv[argc] = p; + argc++; + while (*p != ' ' && *p != '\0') ++p; + *p = '\0'; + } + } + return execvp(filename,argv); + } /* chain */ + +chmod(name, mode) + char *name; /* name of file */ + int mode; /* new mode */ +{ + extern int errno, _doserrno; + int status; + if (_sysacdc(0x4301,mode,name,&status) == 0) return 0; + errno = _doserrno; + return -1; + } + +creat(name, mode) +char *name; +int mode; +{ + int fd, status; + fd = open(name,O_CREAT|O_RDWR|O_TRUNC,S_IREAD|S_IWRITE); + if (fd != -1) _sys_acd(0x4300,mode,name,&status); + return fd; + } + +exec(command) + char *command; +{ + static char nullchar = '\0'; + char filename[130]; + char *p, *q; + int argc; + char *argv[32]; + p = command; + q = filename; + while (*p != ' ' && *p != '/' && *p != '\0') *q++ = *p++; + *q = '\0'; + argv[0] = &nullchar; + argc = 1; + while (*p != '\0' && argc < 32) { + while (*p == ' ') ++p; + if (*p != '\0') { + argv[argc] = p; + argc++; + while (*p != ' ' && *p != '\0') ++p; + *p = '\0'; + } + } + return spawnvp(P_WAIT,filename,argv); + } /* exec */ + +getd(dptr, fp) + double *dptr; + FILE *fp; +{ + char buffer[128]; + char *p; + int c; + while (isspace(c = fgetc(fp))); + if (c == '+' || c == '-') *p++ = c; + while (isdigit(c)) { *p++ = c; c = fgetc(fp); } + if (c == '.') { + *p++ = c; + c = fgetc(fp); + while (isdigit(c = fgetc(fp))) {*p++ = c; c = fgetc(fp); } + } + if (toupper(c) == 'E') { + *p++ = c; + c = fgetc(fp); + while (isdigit(c = fgetc(fp))) {*p++ = c; c = fgetc(fp); } + } + if (c != -1) ungetc(c,fp); + *dptr = atof(buffer); + return 0; + } + +geti(iptr, fp) + int *iptr; + FILE *fp; +{ + char buffer[128]; + char *p; + int c; + while (isspace(c = fgetc(fp))); + if (c == '+' || c == '-') *p++ = c; + while (isdigit(c = fgetc(fp))) *p++ = c; + *p = '\0'; + if (p == buffer) return -1; + if (c != -1) ungetc(c,fp); + *iptr = atio(buffer); + return 0; + } + +getmode() +{ + return getvmode(); + } + +int puti(i, fp) + int i; + FILE *fp; +{ + char buffer[16]; + __itoa(i,buffer); + return fputs(buffer,fp); + } + +itoa(n,s) +int n; +char *s; +{ + return __itoa(n,s); + } + +__itoa(n, s) +int n; +char *s; +{ + char buffer[7], flag = '\0', *ptr; + buffer[6] = '\0'; + ptr = &buffer[5]; + if (n < 0) { + if (n == -32768) { + strcpy(s, "-32768"); + return; + } + ++flag; + n = -n; + } + do { + *(ptr--) = n % 10 + 48; + } while ((n /= 10) > 0); + if (flag) *ptr = '-'; + else ptr++; + strcpy(s, ptr); + return; +} + +int open(name, rwmode) + char *name; + int rwmode; +{ + int openmode; + int r; + r = rwmode & 0x03; + if (r == 0) openmode = O_RDONLY; + else if (r == 1) openmode = O_WRONLY; + else openmode = O_RDWR; + if (rwmode & 0x8000) openmode += O_BINARY; + return _open(name,openmode,0); + } + +int peek(address) + char *address; +{ + return *address; + } + +int putd(d, fp) + double d; + FILE *fp; +{ + char buffer[64]; + ftoa(d,buffer,0x8a,1,16); + return fputs(buffer,fp); + } + +setdate(s) +char *s; +{ + int mm, dd, yy; + int result; + mm = (*s++ - '0')*10 + *s++ - '0'; + ++s; + dd = (*s++ - '0')*10 + *s++ - '0'; + ++s; + yy = (*s++ - '0')*10 + *s++ - '0'; + _sys_acd(0x2b00,yy+1900,(mm<<8)+dd,&result); + return; +} + +setmode(mode) + int mode; +{ + return setvmode(mode); + } + +settime(s) +char *s; +{ + int hh, mm, ss; + int result; + hh = (*s++ - '0')*10 + *s++ - '0'; + ++s; + mm = (*s++ - '0')*10 + *s++ - '0'; + ++s; + ss = (*s++ - '0')*10 + *s++ - '0'; + _sys_acd(0x2b00,(hh<<8)+mm,ss<<8,&result); + return; +} + +double sqr(x) + double x; +{ + return x*x; + } + +char *strsave(s) + char *s; +{ + return strdup(s); + } diff --git a/Mix Power C v1/MOVMEM.ASM b/Mix Power C v1/MOVMEM.ASM new file mode 100644 index 0000000..43fda08 --- /dev/null +++ b/Mix Power C v1/MOVMEM.ASM @@ -0,0 +1,484 @@ +; +; ------------------------------------------------------- +; movmem(source, destination, n) - move block of memory +; memcpy(destination, source, n) - move block of memory +; ------------------------------------------------------- +; + IDT movmem + IF UPPER + DEF MOVMEM + ENDIF + DEF movmem +; DEF MEMCPY +; DEF memcpy + DEF $_MOV +; +movmem equ $ +MOVMEM PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] +COPY1 MOV CX,[BP][%PARM3] +COPY2 MOV AX,DI ; result is pointer to dest + JCXZ DONE + CLD + MOV DX,DS + MOV ES,DX + CMP SI,DI + JAE COPY + STD + ADD SI,CX + ADD DI,CX + TEST CL,>01 + JZ EVEN + DEC SI + DEC DI + MOVSB + SHR CX,1 + JCXZ DONE + DEC SI + DEC DI + REP + MOVSW + JMPS DONE +EVEN SUB SI,%2 + SUB DI,%2 + SHR CX,1 + JCXZ DONE + REP + MOVSW + JMPS DONE +COPY PUSH CX + SHR CX,1 + JCXZ LASTCHAR + REP + MOVSW +LASTCHAR POP CX + AND CL,>01 + JZ DONE + MOVSB +DONE CLD + POP BP + RETSEG +memcpy equ $ +MEMCPY PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM2] + MOV DI,[BP][%PARM1] + JMPS COPY1 +$_MOV PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM3] + MOV DI,[BP][%PARM2] + MOV CX,[BP][%PARM1] + JMPS COPY2 + END +; +; ------------------------------------------------------- +; memcpy(destination, source, n) - move block of memory +; ------------------------------------------------------- +; + IDT memcpy + IF UPPER + DEF MEMCPY + ENDIF + DEF memcpy +; +memcpy equ $ +MEMCPY MOV BX,SP + MOV DI,[BX][%PARM1-2] + MOV SI,[BX][%PARM2-2] + MOV CX,[BX][%PARM3-2] + MOV AX,DI ; result is pointer to dest + JCXZ DONE + CLD + MOV DX,DS + MOV ES,DX + CMP SI,DI + JAE COPY + STD + ADD SI,CX + ADD DI,CX + DEC SI + DEC DI +COPY REP + MOVSB + CLD +DONE RETFAR + END +; +; ------------------------------------------------------- +; memmove(destination, source, n) - move block of memory +; ------------------------------------------------------- +; + IDT memmove + DEF memmove +; +memmove MOV BX,SP + MOV DI,[BX][%PARM1-2] + MOV SI,[BX][%PARM2-2] + MOV CX,[BX][%PARM3-2] + MOV AX,DI ; result is pointer to dest + JCXZ DONE + CLD + MOV DX,DS + MOV ES,DX + CMP SI,DI + JAE COPY + STD + ADD SI,CX + ADD DI,CX + DEC SI + DEC DI +COPY REP + MOVSB + CLD +DONE RETFAR + END +; +; ------------------------------------------------------- +; memswap(addr1, addr2, n) - swap two blocks of memory +; ------------------------------------------------------- +; + IDT memswap + IF UPPER + DEF MEMSWAP + ENDIF + DEF memswap +; +memswap equ $ +MEMSWAP MOV BX,SP + MOV SI,[BX][%PARM1-2] + MOV DI,[BX][%PARM2-2] + MOV CX,[BX][%PARM3-2] + JCXZ DONE + CLD + MOV DX,DS + MOV ES,DX +SWAP MOV AL,[DI] + XCHG AL,[SI] + STOSB + INC SI + LOOP SWAP +DONE RETSEG + END +; +; ------------------------------------------------------- +; memset(addr, value, count) - fill a block with character +; ------------------------------------------------------- +; + IDT memset + IF UPPER + DEF MEMSET + ENDIF + DEF memset +; +memset equ $ +MEMSET MOV BX,SP + MOV DI,[BX][%PARM1-2] + MOV AX,[BX][%PARM2-2] + MOV CX,[BX][%PARM3-2] + JCXZ DONE + CLD + MOV DX,DS + MOV ES,DX + REP + STOSB +DONE RETSEG + END +; +; ------------------------------------------------------- +; swab(source, destination, n) - swap bytes in a block of memory +; ------------------------------------------------------- +; + IDT swab + DEF swab +; +swab PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] + MOV CX,[BP][%PARM3] + SHR CX,1 ; word count + CLD + MOV DX,DS + MOV ES,DX + JCXZ DONE +COPY LODSW + XCHG AH,AL + STOSW + LOOP COPY +DONE TEST [BP][%PARM3],1 + JZ EVEN + LODSB + STOSB +EVEN POP BP + RETSEG + END +; +; ------------------------------------------------------- +; $_movarg(source,dest,n) - move block of memory +; source is address of last byte of block +; ------------------------------------------------------- +; + IDT $_MOVARG + DEF $_MOVARG +; +$_MOVARG PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM1] + JCXZ DONE + MOV DI,[BP][%PARM2] + MOV SI,[BP][%PARM3] + SUB SI,CX + INC SI + CLD + MOV DX,DS + MOV ES,DX + REP + MOVSB +DONE POP BP + RETSEG + END +; +; ------------------------------------------------------- +; memccpy(dest, src, c, cnt) - copy up to & including c +; ------------------------------------------------------- +; + IDT memccpy + IF UPPER + DEF MEMCCPY + ENDIF + DEF memccpy +; +memccpy equ $ +MEMCCPY PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + MOV SI,[BP][%PARM2] + MOV DX,[BP][%PARM3] + MOV CX,[BP][%PARM4] + JCXZ ENDCOUNT + MOV DX,DS + MOV ES,DX + CLD +COPY LODSB + STOSB + CMP AL,DL + JZ FOUND + LOOP COPY +ENDCOUNT XOR AX,AX ; Return null if c not copied + POP BP + RETSEG +FOUND MOV AX,DI ; return address of next after c + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; memchr(buf, c, cnt) - search for c in buffer +; ------------------------------------------------------- +; + IDT memchr + IF UPPER + DEF MEMCHR + ENDIF + DEF memchr +; +memchr equ $ +MEMCHR PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + MOV AX,[BP][%PARM2] + MOV CX,[BP][%PARM3] + MOV DX,DS + MOV ES,DX + CLD + REPNZ + SCASB + JNZ NOFIND + DEC DI + MOV AX,DI ; Return pointer to c in buf + POP BP + RETSEG +NOFIND XOR AX,AX ; Return null if not found + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; memcmp(buf1, buf2, cnt) - compare memory +; $_cmp(src, dest, cnt) - compare memory (byte result) +; ------------------------------------------------------- +; + IDT memcmp + IF UPPER + DEF MEMCMP + ENDIF + DEF memcmp + DEF $_CMP +; +$_CMP PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM3] + MOV DI,[BP][%PARM2] + MOV CX,[BP][%PARM1] + JMPS COMPARE +memcmp equ $ +MEMCMP PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] + MOV CX,[BP][%PARM3] +COMPARE JCXZ EQUAL + MOV DX,DS + MOV ES,DX + CLD + REPZ + CMPSB + JZ EQUAL + MOV AL,[SI][%-1] + SUB AL,[DI][%-1] + CBW + POP BP + RETSEG +EQUAL XOR AX,AX ; Return 0 if buffers are equal + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; memicmp(buf1, buf2, cnt) - compare memory +; ------------------------------------------------------- +; + IDT memicmp + IF UPPER + DEF MEMICMP + ENDIF + DEF memicmp +; +memicmp equ $ +MEMICMP PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] + MOV CX,[BP][%PARM3] + JCXZ EQUAL + MOV DX,DS + MOV ES,DX + CLD +MATCH REPZ + CMPSB + JZ EQUAL + MOV AL,[SI][%-1] + MOV AH,[DI][%-1] + CMP AL,'a' + JB X1 + CMP AL,'z' + JA X1 + SUB AL,>20 +X1 CMP AH,'a' + JB X2 + CMP AH,'z' + JA X2 + SUB AH,>20 +X2 CMP AL,AH + JZ MATCH + MOV AL,[SI][%-1] + SUB AL,[DI][%-1] + CBW + POP BP + RETSEG +EQUAL XOR AX,AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; movedata(srcseg, srcoff, destseg, destoff, nbytes); +; move a block of data between segments +; ------------------------------------------------------- +; + IDT movedata + IF UPPER + DEF MOVEDATA + ENDIF + DEF movedata +; +movedata equ $ +MOVEDATA PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM2] + MOV DI,[BP][%PARM4] + CLD + PUSH DS + MOV DS,[BP][%PARM1] + MOV ES,[BP][%PARM3] + MOV CX,[BP][%PARM5] + JCXZ DONE + MOV AX,[BP][%PARM1] + CMP AX,[BP][%PARM3] + JNZ COPY + CMP DI,SI ; Allow overlap if segments equal + JBE COPY + STD + DEC CX + ADD SI,CX ; point to end of data + ADD DI,CX + INC CX + REP + MOVSB + CLD + JMPS DONE +COPY PUSH CX + SHR CX,1 + JCXZ LASTCHAR + REP + MOVSW +LASTCHAR POP CX + AND CX,>0001 + JCXZ DONE + MOVSB +DONE POP AX + MOV DS,AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; xmovmem(xsource, xdest, size); +; ------------------------------------------------------- +; + IDT xmovmem + IF UPPER + DEF XMOVMEM + ENDIF + DEF xmovmem +xmovmem equ $ +XMOVMEM PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] ; lsw of source + MOV CL,%4 + MOV SI,AX + AND SI,>000F + SHR AX,CL + ADD AX,[BP][%PARM2] ; msw of source + MOV DX,[BP][%PARM3] ; lsw of dest + MOV CL,%4 + MOV DI,DX + AND DI,>000F + SHR DX,CL + ADD DX,[BP][%PARM4] ; msw of dest + MOV ES,DX + PUSH DS + MOV DS,AX + MOV CX,[BP][%PARM5] + JCXZ DONE + CLD + REP + MOVSB +DONE POP AX + MOV DS,AX + POP BP + RETSEG + END diff --git a/Mix Power C v1/MSDOS.C b/Mix Power C v1/MSDOS.C new file mode 100644 index 0000000..068e4e9 --- /dev/null +++ b/Mix Power C v1/MSDOS.C @@ -0,0 +1,205 @@ + +/* MSDOS Functions */ +/* Copyright (c) Mix Software 1988 */ + +chdir(dirname) +char *dirname; +{ + extern int errno; + extern int _doserrno; + int result; + int _sys_ad(); + if (_sys_ad(0x3b00,dirname,&result) == 0) return 0; + errno = ENOENT; + return -1; +} + +/* ------------------------------------------------------------ */ + +char *getcwd(pathbuf,n) /* get current working directory */ + char *pathbuf; /* buffer for result */ + int n; /* maximum length of result */ +{ + extern int errno,_doserrno; + int drive; + char buf[64]; + char *path; + union REGS reg; + if (pathbuf == NULL) { + pathbuf = malloc(n); + if (pathbuf == NULL) return NULL; + } + reg.x.ax = 0x4700; + reg.h.dl = 0; + reg.x.si = buf; + intdos(®,®); + if (reg.x.cflag) { errno = _doserrno; return -1; } + if (strlen(buf)+3 >= n) { errno = ERANGE; return -1; } + drive = _sys_al(0x1900); + path = pathbuf; + *path++ = drive + 'A'; + *path++ = ':'; + *path++ = '\\'; + strcpy(path,buf); + return pathbuf; +} + +/* ------------------------------------------------------------ */ + +getch() +{ + extern int _ungetch; + int ch = _ungetch; + if (ch != EOF) { + _ungetch = EOF; + return ch; + } + else return _sys_al(0x0700); +} + +/* ------------------------------------------------------------ */ + +void putch(c) + int c; +{ + int s; + _sys_ad(0x0600,c,&s); +} + +/* ------------------------------------------------------------ */ + +getche() +{ + return _sys_al(0x0100); +} + +/* ------------------------------------------------------------ */ + +getkey() +{ + union REGS reg; + int bdosx(); + reg.h.dl = 0xFF; + if (bdosx(0x06, ®) & 0x40) return EOF; + else return reg.h.al; +} + +/* ------------------------------------------------------------ */ + +int isatty(fd) + int fd; +{ + union REGS reg; + reg.x.ax = 0x4400; + reg.x.bx = fd; + reg.x.cx = 0; + reg.x.dx = 0; + intdos(®,®); + if (reg.x.cflag != 0) return 0; + if ((reg.x.dx & 0x0080) == 0) return 0; else return 1; +} + +/* ------------------------------------------------------------ */ + +int kbhit() +{ + return _sys_al(0x0b00); +} + +/* ------------------------------------------------------------ */ + +keypress() +{ + return _sys_al(0x0b00); +} + +/* ------------------------------------------------------------ */ + +unlink(name) +char *name; +{ + extern int errno, _doserrno; + int _sys_ad(); + int result; + if (_sys_ad(0x4100,name,&result) == 0) return 0; + errno = _doserrno; + return -1; +} + +/* ------------------------------------------------------------ */ + +remove(name) +char *name; +{ + extern int errno, _doserrno; + int _sys_ad(); + int result; + if (_sys_ad(0x4100,name,&result) == 0) return 0; + errno = _doserrno; + return -1; +} + +/* ------------------------------------------------------------ */ + +mkdir(dirname) +char *dirname; +{ + extern int errno, _doserrno; + int _sys_ad(); + int result; + if (_sys_ad(0x3900,dirname,&result) == 0) return 0; + errno = _doserrno; + return -1; +} + +/* ------------------------------------------------------------ */ + +rmdir(dirname) +char *dirname; +{ + extern int errno, _doserrno; + int _sys_ad(); + int result; + if (_sys_ad(0x3A00,dirname,&result) == 0) return 0; + errno = _doserrno; + return -1; +} + +/* ------------------------------------------------------------ */ + +rename(oldname, newname) +char *oldname, *newname; +{ + int _sysdxdi(); + int result; + extern int errno; + return _sysdxdi(0x5600,oldname,newname,&result); +} + +/* ------------------------------------------------------------ */ + +int sbrk(incr) + int incr; +{ return -1; } + +int brk(endds) + int endds; +{ return -1; } + +/* ------------------------------------------------------------ */ + +int getpid() +{ + static unsigned _pid = 0; + extern unsigned char _osmajor; + union REGS reg; + if (_pid != 0) return _pid; + if (_osmajor > 3) _pid = _sys_al(0x8700); + if (_pid == 0) { + reg.h.ah = 0x2c; + intdos(®,®); + _pid = reg.x.dx; + } + return _pid; +} + diff --git a/Mix Power C v1/NEW.ASM b/Mix Power C v1/NEW.ASM new file mode 100644 index 0000000..5825285 --- /dev/null +++ b/Mix Power C v1/NEW.ASM @@ -0,0 +1,270 @@ +; +; Copyright (c) Mix Software 1988 +; + IDT alloc + DEF alloc + IF UPPER + DEF ALLOC + ENDIF + FREF $$ALLOC +alloc equ $ +ALLOC JMPFAR $$ALLOC + END +; + IDT calloc + DEF calloc + IF UPPER + DEF CALLOC + ENDIF + FREF $$CALLOC +calloc equ $ +CALLOC JMPFAR $$CALLOC + END +; + IDT malloc + DEF malloc + IF UPPER + DEF MALLOC + ENDIF + FREF $$MALLOC +malloc equ $ +MALLOC JMPFAR $$MALLOC + END +; +; -------------------------------------------------- +; new - allocate a block of heap +; -------------------------------------------------- +; + IDT $$ALLOC + DEF $$CALLOC + DEF $$MALLOC + DEF $$ALLOC + DEF _nmalloc + REF $$HPTERM + FREF $_FATAL + FREF $$NEW$$ + REF errno +; +; calloc(number,size) - block is number*size bytes in length +; +$$CALLOC PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MUL [BP][%PARM2] + JC NOSPACE ; multiply overflows + CALLFAR $$NEW$$ +RETURN TEST AX,AX ; out of space? + JZ NOSPACE +IGNORE POP BP + RETSEG +NOSPACE MOV [errno],ENOMEM + TEST %[$$HPTERM],%>FF ; teminate on heap full? + JZ IGNORE + MOV AX,E$HEAP + PUSH AX + CALLFAR $_FATAL + POP AX + XOR AX,AX + JMPS IGNORE +; +; alloc(size) - block is size bytes in length +; +_nmalloc EQU $ +$$ALLOC EQU $ +$$MALLOC PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + CALLFAR $$NEW$$ + JMPS RETURN + END +; +; $_NEW(ptr,size) +; ptr is address of a pointer to receive the result +; size is the size of the block in bytes +; + IDT $_NEW + DEF $_NEW + REF $$HPTERM + FREF $$NEW$$ + FREF $_FATAL + REF errno +$_NEW PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] ; size + CALLFAR $$NEW$$ + MOV BX,[BP][%PARM2] ; pointer + MOV [BX],AX + TEST AX,AX ; out of space? + JZ NOSPACE +IGNORE POP BP + RETSEG +NOSPACE MOV [errno],ENOMEM + TEST %[$$HPTERM],%>FF ; teminate on heap full? + JZ IGNORE + MOV AX,E$HEAP + PUSH AX + CALLFAR $_FATAL + POP AX + XOR AX,AX + JMPS IGNORE + END +; +; +; ---------------------------------------------------------- +; NEW$$ - Allocate a block from the heap +; ---------------------------------------------------------- +; inputs: +; AX - required length of the packet +; outputs: +; AX - pointer to the packet; 0 if none available +; REGISTERS USED: +; uses ax, bx, cx, dx, di +; +; + IDT $$NEW$$ + DEF $$NEW$$ + REF $$FREE + REF $$CURH + REF $$MAXH +; +$$NEW$$ MOV CX,AX + ADD CX,%3 ; reserve two bytes for length + AND CL,%#FE ; Round up if size is odd +; +; if size is less than 6, set to 6 +; + CMP CX,%6 + JAE NEW01 + MOV CX,6 ; MINIMUM SIZE IS 6 +; +; SET BX TO POINT TO THE CURRENT FREE LIST +; +NEW01 MOV BX,[$$FREE] +; +; SEARCH FREE LIST FOR A PACKET OF SUFFICIENT SIZE +; +NEWLOOP CMP CX,[BX] ; COMPARE LENGTHS + JBE NEW02 + JMP NEW03 ; NOT LARGE ENOUGH +; +; THE CURRENT PACKET IS LARGE ENOUGH +; REMOVE NEEDED SPACE & CHECK RESULT FOR > 6 +; +NEW02 MOV AX,[BX] ; GET PACKET SIZE + SUB AX,CX ; SUBTRACT NEEDED SPACE + CMP AX,6 ; LARGE ENOUGH? + JAE NEW04 + MOV CX,[BX] ; SET SIZE TO WHOLE PACKET +; +; LESS THAN 6 BYTES ARE LEFT, SO ALLOCATE THE ENTIRE PACKET +; LENGTH IS IN CX, LOCATION IS IN BX +; + MOV AX,[BX][2] ; GET SUCCESSOR FIELD + MOV [$$FREE],AX ; NEW FREE LIST + MOV DX,[BX][4] ; DX = PREDECESSOR +; +; LAST+2 := NEXT +; + XCHG BX,DX + MOV [BX][2],AX ; SET PRED@.NEXT TO CUR@.NEXT + XCHG BX,DX +; +; NEXT+4 := LAST +; + XCHG BX,AX + MOV [BX][4],DX ; SET NEXT@.LAST TO CUR@.LAST + XCHG BX,AX + JMPS NEW05 +; +; THE REMAINDER OF THE CURRENT PACKET IS LONG ENOUGH +; +; REDUCE THE SIZE OF THE PACKET +; AX CONTAINS THE NEW LENGTH +; CX CONTAINS THE LENGTH OF THE REQUESTED PACKET +; BX CONTAINS THE PACKET ADDRESS +; +NEW04 MOV DX,BX ; SAVE CURRENT PACKET ADDR + ADD BX,CX ; BX <-- ADDR OF NEW FREE PKT + MOV [BX],AX ; SET NEW LENGTH +; +; SET SUCCESSOR OF NEW FREE PACKET TO SUCCESSOR OF OLD +; FREE PACKET & PREDECESSOR OF NEW TO PREDECESSOR OF OLD +; IE. MOVE 4 BYTES FROM (DE) TO (HL) +; + MOV DI,DX + MOV AX,[DI][2] ; OLD SUCCESSOR + MOV [BX][2],AX + MOV AX,[DI][4] + MOV [BX][4],AX +; +; DI CONTAINS OLD FREE PACKET +; BX CONTAINS NEW FREE PACKET +; + MOV AX,[BX][2] ; GET SUCCESSOR + MOV [$$FREE],AX ; NEW FREE LIST POINTER + XCHG BX,AX + MOV [BX][4],AX ; NEXT@.PRED = NEW FREE PKT + XCHG AX,BX + MOV AX,[BX][4] ; GET PREDECESSOR + XCHG AX,BX + MOV [BX][2],AX ; PREV@.SUCC = NEW FREE PKT + XCHG AX,BX + MOV BX,DX +; +; AT THIS POINT CX CONTAINS THE LENGTH OF THE NEWLY ALLOCATED +; PACKET, AND BX CONTAINS ITS ADDRESS +; +; SET THE LENGTH OF THE NEWLY ALLOCATED PACKET. LENGTH+1, WHICH +; IS ODD, IS USED TO MARK THE PACKET AS ALLOCATED +; +NEW05 MOV [BX],CX + INC [BX] ; MAKE LENGTH ODD + INC BX ; POINT TO DATA AREA + INC BX +; +; ADD SIZE OF CURRENT PACKET TO CURRENT HEAP ALLOCATED +; + ADD [$$CURH],CX ; ADD TO CURRENT ALLOCATION + MOV AX,[$$CURH] ; LARGER THAN MAX USED? + CMP AX,[$$MAXH] + JB NEW08 + MOV [$$MAXH],AX ; SET MAXIMUM HEAP USED +NEW08 EQU $ +; TEST %[$$ZFILL],>FF ; ZERO FILL? +; JZ NEW10 ; NO ZERO FILL + MOV DX,BX ; SAVE POINTER + MOV DI,BX + CLD + MOV AX,DS + MOV ES,AX + SHR CX,1 ; LENGTH IN WORDS + DEC CX ; ALLOW FOR LENGTH FIELD + MOV AX,0 + REP + STOSW + MOV AX,DX + RETSEG +NEW10 MOV AX,BX + RETSEG ; DONE +; +; +; THE CURRENT PACKET IN THE FREE LIST IS NOT LARGE ENOUGH +; MOVE TO THE NEXT PACKET +; BX CONTAINS THE ADDRESS OF THE CURRENT PACKET +; CX CONTAINS THE REQUIRED SIZE +; +NEW03 MOV BX,[BX][%2] ; POINT TO SUCCESSOR +; +; CHECK THE CURRENT PACKET AGAINST THE FREELIST POINTER. +; IF CURRENT=FREELIST, THEN ALL PACKETS HAVE BEEN EXAMINED, +; AND THE REQUEST CANNOT BE SATISFIED +; + CMP BX,[$$FREE] + JZ NEW11 + JMP NEWLOOP +; +; UNABLE TO ALLOCATE +; +NEW11 MOV AX,0 + RETSEG + END diff --git a/Mix Power C v1/NHEAP.ASM b/Mix Power C v1/NHEAP.ASM new file mode 100644 index 0000000..f160cf0 --- /dev/null +++ b/Mix Power C v1/NHEAP.ASM @@ -0,0 +1,251 @@ +; +; Copyright (c) Mix Software 1988 +; +; -------------------------------------------------- +; _fmalloc - allocate from far heap +; if no memory available, allocate from near heap +; char far *_fmalloc(size) +; unsigned size; +; -------------------------------------------------- +; + IDT _fmalloc + DEF _fmalloc + FREF falloc + FREF malloc +; +_fmalloc MOV SI,SP + PUSH [SI][%PARM1-2] + CALLFAR falloc + ADD SP,%2 + MOV CX,DX + OR CX,AX + JNZ OK + MOV SI,SP + PUSH [SI][%PARM1-2] + CALLFAR malloc + ADD SP,%2 + TEST AX,AX + JZ NULL + MOV DX,DS +OK RETSEG +NULL XOR DX,DX + RETSEG + END +; +; -------------------------------------------------- +; _ffree - release from near or far heap +; void _ffree(ptr) +; char far *ptr; +; -------------------------------------------------- +; + IDT _ffree + DEF _ffree + FREF ffree + FREF free +; +_ffree MOV SI,SP + MOV AX,[SI][%PARM2-2] + MOV CX,DS + CMP AX,CX + JZ NEAR + PUSH AX + PUSH [SI][%PARM1-2] + CALLFAR ffree + ADD SP,%4 + RETSEG +NEAR PUSH [SI][%PARM1-2] + CALLFAR free + ADD SP,%2 + RETSEG + END +; +; -------------------------------------------------- +; _nmsize - return the size of a memory block +; unsigned _nmsize(ptr) +; char near *ptr; +; -------------------------------------------------- +; + IDT _nmsize + DEF _nmsize + DEF _msize +; +_msize EQU $ +_nmsize MOV SI,SP + MOV BX,[SI][%PARM1-2] + MOV AX,[BX][%-2] ; get size and allocated flag + AND AX,>FFFE + SUB AX,%2 + RETSEG + END +; +; -------------------------------------------------- +; _memavl - return the byte count of available memory +; unsigned _memavl() +; -------------------------------------------------- +; + IDT _memavl + REF $$CURH + REF $$HMIN + REF $$HMAX + DEF _memavl +; +_memavl MOV AX,[$$HMAX] + SUB AX,[$$HMIN] + SUB AX,[$$CURH] + SUB AX,6 + RETSEG + END +; +; -------------------------------------------------- +; coreleft - return the byte count of available memory +; unsigned coreleft() +; -------------------------------------------------- +; + IDT coreleft + REF $$CURH + REF $$HMIN + REF $$HMAX + DEF coreleft +; +coreleft MOV AX,[$$HMAX] + SUB AX,[$$HMIN] + SUB AX,[$$CURH] + SUB AX,6 + RETSEG + END +; +; -------------------------------------------------- +; _freect - return the number of items in heap +; unsigned _freect(size) +; unsigned size; +; -------------------------------------------------- +; + IDT _freect + REF $$CURH + REF $$HMIN + REF $$HMAX + DEF _freect +; +_freect MOV AX,[$$HMAX] + SUB AX,[$$HMIN] + SUB AX,[$$CURH] + SUB AX,6 + MOV BX,SP + MOV BX,[BX][%PARM1-2] + XOR DX,DX + TEST BX,BX + JZ EXIT + DIV BX +EXIT RETSEG + END +; +; -------------------------------------------------- +; _expand - expand a block of memory without moving it +; _expand(ptr,size) +; char *ptr; +; unsigned size; /* requested new size */ +; -------------------------------------------------- +; + IDT _expand + DEF _expand + IF UPPER + DEF _EXPAND + ENDIF + REF $$FREE + REF $$CURH + REF $$MAXH + FREF free +; +_EXPAND EQU $ +_expand PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] + MOV CX,[BX][%-2] ; get size and allocated flag + TEST CX,>0001 + JZ AVAIL + SUB CX,%3 ; remove flag and overhead + CMP CX,[BP][%PARM2] + JB EXPAND ; Make larger +; +; Try to shrink the block +; If shrink is by at least 6 bytes, create a new pointer +; and use free to release it. +; +SHRINK SUB CX,[BP][%PARM2] + NEG CX + AND CX,>FFFE ; Must be an even number + CMP CX,%6 + JB FREEOK ; Not enough to free + SUB [BX][%-2],CX ; Remove from this block count + ADD BX,[BX][%-2] ; Point to end of block + DEC BX ; remove allocated flag + INC CX + MOV [BX][%-2],CX ; create allocated block header + PUSH BX + CALLFAR free + POP BX + MOV AX,[BP][%PARM1] + POP BP + RETSEG +; +; Try to expand the block. +; the next higher block must be free +; +EXPAND MOV SI,[$$FREE] ; Start of free list + MOV DX,SI + ADD BX,CX ; Point to next block header +SEARCH CMP SI,BX ; Found next block? + JZ FOUND + MOV SI,[SI][%2] ; Move to next free block + CMP SI,DX ; Full circuit? + JNZ SEARCH + JMPS NULLEXIT ; unable to expand +FOUND CMP [SI],6 + JBE NULLEXIT ; protect anchor + MOV DI,[SI][%4] ; predecessor + MOV BX,[SI][%2] ; successor + MOV [DI][%2],BX + MOV [BX][%4],DI ; block linked out + MOV CX,[SI] ; length of the free block + ADD [$$CURH],CX + MOV AX,[$$CURH] + CMP AX,[$$MAXH] + JBE ADJUST + MOV [$$MAXH],AX +ADJUST MOV BX,[BP][%PARM1] ; merge block + ADD CX,[BX][%-2] + MOV [BX][%-2],CX ; Blocks are merged + SUB CX,%3 + JMPS SHRINK ; Return the excess +; +; Block is free - it has therefore already become as large as +; possible. Check size to generate return value +; +AVAIL SUB CX,%2 + CMP CX,[BP][%PARM2] + JAE FREEOK ; Large enough +NULLEXIT XOR AX,AX + POP BP + RETSEG +FREEOK MOV AX,BX + POP BP + RETSEG + END +; +; -------------------------------------------------- +; heapsiz - return the byte count of available memory +; unsigned heapsiz() +; -------------------------------------------------- +; + IDT heapsiz + REF $$CURH + REF $$HMIN + REF $$HMAX + DEF heapsiz +; +heapsiz MOV AX,[$$HMAX] + SUB AX,[$$HMIN] + SUB AX,[$$CURH] + SUB AX,6 + RETSEG + END diff --git a/Mix Power C v1/OPEN.C b/Mix Power C v1/OPEN.C new file mode 100644 index 0000000..ae947b9 --- /dev/null +++ b/Mix Power C v1/OPEN.C @@ -0,0 +1,254 @@ + +/* Open/Create files */ +/* Copyright (c) Mix Software 1988 */ + +/* ------------------------------------------------------------ */ + +FILE *fdopen(fd, type) +int fd; +char *type; +{ + FILE *fp; + int c; + int mode; + if (fd < 0 || fd > MAXFILES) return NULL; + fp = _iob[fd]; + if (fp == NULL) return NULL; + c = *type; + if (c == 'r') mode = O_RDONLY; else mode = O_WRONLY; + if (*++type == '+') mode = O_RDWR; + if (c == 'a') { + if ((fp->file.flags & fdappend) == 0) return NULL; + } + if (fp->file.mode == mode) return fp; + return NULL; +} + +/* ------------------------------------------------------------ */ + +FILE *freopen(filename, type, old_fp) +char *filename, *type; +FILE *old_fp; +{ + FILE *new_fp; + int old_fd, new_fd; + FILE *fopen(); + old_fd = fileno(old_fp); + if (fclose(old_fp)) return NULL; + if ((new_fp = fopen(filename, type)) == NULL) return NULL; + new_fd = fileno(new_fp); + if (new_fd != old_fd) { /* keep same file number */ + _iob[new_fd] = _iob[old_fd]; + _iob[old_fd] = new_fp; + new_fp->fd = old_fd; + if (_iob[new_fd] != NULL) _iob[new_fd]->fd = new_fd; + } +} + +/* ------------------------------------------------------------ */ + +FILE *fopen(name,modes) +char *name, *modes; +{ + char ch; + int fd, mode, rw; + ch = tolower(*modes); + mode = 0; + if (ch == 'r') rw = O_RDONLY; + else if (ch == 'w') {rw = O_WRONLY; mode = O_CREAT|O_TRUNC;} + else if (ch == 'a') {rw = O_RDWR; mode = O_CREAT|O_APPEND;} + else return NULL; + if (*++modes == '+') { + rw = O_RDWR; + ++modes; + } + ch = tolower(*modes); + if (ch == 'b') mode |= O_BINARY; + else if (ch == 't') mode |= O_TEXT; + fd = _open(name,mode|rw,S_IREAD|S_IWRITE); + if (fd < 0) return NULL; + return _iob[fd]; +} + +/* ------------------------------------------------------------ */ + +creat(name, pmode) +char *name; +int pmode; +{ + return _open(name,O_CREAT|O_WRONLY|O_TRUNC,pmode); + } + +/* ------------------------------------------------------------ */ + +creatnew(name, attrib) +char *name; +int attrib; +{ + int fd, status; + fd = _open(name,O_CREAT|O_RDWR|O_TRUNC|O_EXCL|O_BINARY,S_IREAD|S_IWRITE); + if (fd != -1) _sys_acd(0x4300,attrib,name,&status); + return fd; + } + +/* ------------------------------------------------------------ */ + +_creat(name, attrib) +char *name; +int attrib; +{ + int fd, status; + fd = _open(name,O_CREAT|O_RDWR|O_TRUNC|O_BINARY,S_IREAD|S_IWRITE); + if (fd != -1) _sys_acd(0x4300,attrib,name,&status); + return fd; + } + +/* ------------------------------------------------------------ */ + +sopen(name, oflag, shflag, pmode) + char *name; + int oflag; + int shflag; + int pmode; +{ + return _open(name,oflag|shflag,pmode); +} + +/* ------------------------------------------------------------ */ + +open(name, mode, pmode) + char *name; + int mode; + int pmode; +{ + return _open(name,mode,pmode); +} + +/* ------------------------------------------------------------ */ + +_open(name, mode, pmode) +char *name; +int mode; +int pmode; +{ + int fd; + FILE *fp; + extern int $$BUFSIZ; + extern char $$CCTLZ; + extern int errno, _doserrno; + extern char _fmode; + extern int _umask_; + extern int (*_fileerr)(); + extern int (*_fclose)(); + int fclose(); + int handle; + int flmode; + int crmode; + int chmode = 0; + _fclose = fclose; + flmode = mode & O_MODEMASK; + crmode = pmode & (~_umask_); + crmode = ((crmode & S_IWRITE) == 0) ? 1 : 0; + if (mode & O_TRUNC) { + if ((mode & O_CREAT) == 0) { + if (_sys_ad(0x3d00,name,&handle) != 0) goto doserror; + _sys_ab(0x3e00,handle,&handle); + } + else { + if (mode & O_EXCL) { + if (_sys_ad(0x3d00,name,&handle) == 0) { + _sys_ab(0x3e00,handle,&handle); + errno = EEXIST; + return -1; + } + } + } /* create */ + if (_sys_acd(0x3c00,0,name,&handle) != 0) goto doserror; + chmode = crmode; + if (flmode != O_RDWR) { + _sys_ab(0x3e00,handle,&handle); + if (_sys_ad(0x3d00+flmode,name,&handle) != 0) goto doserror; + } + } /* trunc */ + else { + if (_sys_ad(0x3d00+flmode,name,&handle) != 0) { /* not found */ + if (mode & O_CREAT) { + if (_sys_acd(0x3c00,0,name,&handle) != 0) goto doserror; + chmode = crmode; + if (flmode != O_RDWR) { + _sys_ab(0x3e00,handle,&handle); + if (_sys_ad(0x3d00+flmode,name,&handle) != 0) + goto doserror; + } + } /* create */ + else goto doserror; + } /* file does not exist */ + else { + if (mode & O_CREAT) { + if (mode & O_EXCL) { + _sys_ab(0x3e00,handle,&handle); + errno = EEXIST; + return -1; + } + } + } /* file exists */ + } /* not trunc */ + + /* file is open and file handle is set */ + if (chmode != 0) { + _sys_acd(0x4301,chmode,name,&chmode); + } + fp = malloc(sizeof(FILE)); + fd = handle; + if (fd >= MAXFILES || _iob[fd] != NULL || fp == NULL) { + _sys_ab(0x3e00,handle,&handle); + errno = EMFILE; + return -1; + } + _iob[fd] = fp; + setmem(fp,sizeof(FILE),0); + fp->fd = fd; + fp->file.pathnm = strsave(name); + fp->file.handle = fd; + fp->file.init = 'C'; + fp->file.openflg = 1; + fp->file.mode = flmode & 0x0003; + if (mode & O_BINARY) fp->file.flags = fdbinary; + else if (mode & O_TEXT) fp->file.flags = fdfilter; + else { + if (_fmode == 'b') fp->file.flags = fdbinary; + else fp->file.flags = fdfilter; + } + if (fp->file.flags == fdfilter) { + if ($$CCTLZ) fp->file.flags |= fdctlz; + } + if ($$BUFSIZ == 0) fp->file.flags |= fdunbufr; + else { + fp->file.ptr = fp->file.bufr = malloc($$BUFSIZ); + if (fp->file.ptr == NULL) fp->file.flags |= fdunbufr; + else fp->file.bufsize = $$BUFSIZ; + } + if (mode & O_APPEND) fp->file.flags |= fdappend; + return fd; + +doserror: + errno = _doserrno; + return -1; + +} /* _open */ + +char _fmode = 't'; + +/* ------------------------------------------------------------ */ + +int umask(pmode) + int pmode; +{ + extern int _umask_; + int old; + old = _umask_; + _umask_ = pmode; + return old; +} + +int _umask_ = 0; diff --git a/Mix Power C v1/PC.EXE b/Mix Power C v1/PC.EXE new file mode 100644 index 0000000000000000000000000000000000000000..766983e8203e49b5dd9adeccdda1bfd3decd52d9 GIT binary patch literal 155760 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 literal 0 HcmV?d00001 diff --git a/Mix Power C v1/PC87.MIX b/Mix Power C v1/PC87.MIX new file mode 100644 index 0000000000000000000000000000000000000000..1935ce9aa39910b5dcf1c10ec6a25e8473797c44 GIT binary patch literal 18590 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 BUljlV literal 0 HcmV?d00001 diff --git a/Mix Power C v1/PCAUTO.MIX b/Mix Power C v1/PCAUTO.MIX new file mode 100644 index 0000000000000000000000000000000000000000..441ff4303d68a888862204d0502c09bbd0a50326 GIT binary patch literal 44461 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 literal 0 HcmV?d00001 diff --git a/Mix Power C v1/PCIEEE.MIX b/Mix Power C v1/PCIEEE.MIX new file mode 100644 index 0000000000000000000000000000000000000000..ab074d51787849dcc8a96d487d6109e48661ee12 GIT binary patch literal 29989 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 K!?#O6`u_nx(>4GA literal 0 HcmV?d00001 diff --git a/Mix Power C v1/PCL.EXE b/Mix Power C v1/PCL.EXE new file mode 100644 index 0000000000000000000000000000000000000000..4d3cda63d466897ed4f2b756fb9e2a32bc1980e4 GIT binary patch literal 18944 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

o`Mo5l2L<*C8$Z=?@(ZQ=-6oJ^d|S93~&qFUaP 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 Mwo3o!!l*s}16;xJ?EnA( literal 0 HcmV?d00001 diff --git a/Mix Power C v1/PCLIB.PRJ b/Mix Power C v1/PCLIB.PRJ new file mode 100644 index 0000000..b4a4a0f --- /dev/null +++ b/Mix Power C v1/PCLIB.PRJ @@ -0,0 +1,25 @@ +init init.asm + pca init + +printf printf.c stdarg.h stdio.h dos.h + pc /f- printf + +scanf scanf.c stdarg.h stdio.h + pc /f- scanf + +stdlib std_lib.h fdb.h init.c convert.c rand.c gets.c puts.c open.c \ + exit.c setbuf.c file.c close.c sort.c strcoll.c memory.c msdos.c \ + ungetc.c envir.c bios.c + +io.mix io.asm libdef.asm read.asm write.asm put.asm get.asm \ + seek.asm flush.asm + pca io + +errors std_lib.h error.c + +lib.mix lib.asm libdef.asm sys.asm setmem.asm movmem.asm string.asm \ + to.asm envir.asm nheap.asm new.asm free.asm farstr1.asm farstr.asm \ + farheap.asm div.asm long.asm far.asm setjmp.asm stack.asm inout.asm \ + fatal.asm + pca lib + diff --git a/Mix Power C v1/PCLIB2.BAT b/Mix Power C v1/PCLIB2.BAT new file mode 100644 index 0000000..d127845 --- /dev/null +++ b/Mix Power C v1/PCLIB2.BAT @@ -0,0 +1,10 @@ +echo off +pc pclib2.prj +if errorlevel 1 goto stop +if exist pclib2.mix del pclib2.mix +merge pclib2 graphics screen stdlib2 lib2 +if errorlevel 1 goto stop +goto end +:stop +echo Error creating pclib2 +:end diff --git a/Mix Power C v1/PCLIB2.MIX b/Mix Power C v1/PCLIB2.MIX new file mode 100644 index 0000000000000000000000000000000000000000..2f3e42df398f7c7f0da6a16ef4c0cbf791c27441 GIT binary patch literal 98626 zcmeEv3xHf@dG>c^W-r++NeCeX3}FdNxFm#`+1cG0K;UdP3yH8fxsVx=X4&j)lGRN% zW;dH)F-TEspla>S+V*d2TeVgDi&cL?S}tM(R;yOqikDWZ#YdjelPW#T`LCC;U(O8UI254gOdBAdaek5XtUBVO#vmaUDcz6PWA# z*1+80m;9^!ATZnfWME2odIL(BLi&43CrMfSUn}JkNoeHlvm_;b1f5Y~U4*kAJN?C;DB;ayf2mKYe?(jSOw}LJ!1?07I zUBd=#**h^kIy5x_U|T|9?;*JXL=xp}WvbS;@v(iQLz7dtjF0X#tzkkEd@W!cL>ne? z9YluB%rH;VOR@99)Q=!_x`aovC|hsoA+r=e3l5oO_*rqtoaMjskXc?fOZ%I^rRk2q zYqzK*1Qqhj4!>DYX+;)t<#Dvq36>mqXQP3=bMYQe!UkLX*UHyvzg19fmTO9`Eb&SF zJp__HgzrcF&*1N2d^?01cxAdn!gRg(61MRMb1I1L_xC%ZpISlm+K`5Q67YU7@GkWG z18=Wiiy|wOA{|PRm83{#*{ldD@_I{=cEB`<{zZx`5{fJqTHN6u6KsVdzvMRu-a9HN zaw}TuJ8T6-zaGN(9fCZV11%PV7T4c!oukF#kQQ6P30qJ?ZQ2XZS90qTL1?KUv`i2> zOR_JP>ms=>kZZeK_3JXZUn!NgnB1|Z zY*q<(baw=aHv$Al`3h3V%MIok$aOicH4+QKhzSHt zS_zgV!E$A@))6duT0??q!Ie}ZcU*>C5Oh0DB;D=;qT5i*HINwYeqnf5gfwB6EtHP! zZM(+C$DKHBx0Gu}TMVFxW@I{oI*4m69v8HFkO*ky@dLSe8PU3;YrlfF;1Sr2^-AmokQ2HA6%F1U^AQ^avu$f3&C~U{fmJBG|YgabFHGYk?34kHUlwq zo_)UPD0kGrA>JA4;~*_OXKt>-vQw~JRhLg7!6`0lXtNDwDVky3^?_@KrM4N;{y+LJ zrScaGU`lk~qcFHWDJIiqkTB9?Q%;Wvl?Ro|)au~JEu`|cvKh4en0g;bOxZeUg%j~{a2vwNBz_MFSCUgN@Ktj zU54EL)@wHmkdDhjam23V;3xr#q&%MnSP9pFpA)z!U?Z+L>i>tpNj){-cS7R1Qg+~Z z3urPcHU#1%Q8+ocd!)cq-c%sqPsxmb9rObXXTOY zY&`>%ynsTU+Ht2@U`tN;576b1f`g|2^j8JVoiN6p`_G_hb;I;(nfv)RrH82=Ug(e=RLeWBJSK( zNc5z*J}J6B>o@M4I4p`BCAwRb$CBuSH3NHE(saGZi_N|d>WQWAi373o7GUXx^m{Wn zm1=AN*Qfo*P)BMuO1e=2{%yX_ulDozyCd$HiN!KKS z`2e`hyrpCY0`s>*zl65DBO6-Y-P)Fiua0Pd^T|Ew|7?&2Aa>-#C-9yiSbj)Go?lpb ztRlFCt|Hu8mhBKmBh!$1clgV|nPec|!zC0jT*$z~TXKZ>$Xfx;4u2J1eF>uNC?XBQ z_khkponXQQ1RWF7E_h55w&0m|0{g=fboXP@9QtlGo&vg3fq5yteG0oL{ne5lQH1qy zsSsEw;q4<*$|?~TtzikPBrSabDPud^^=3)gDqmJH7BR#gv0F+RfCWV*P(T}2=mvs2 z08Sw>F0?4bapn6}_C38$hnhNe%t=8*&z1y>NUG#jQlmE=D4FiS{E>x_(UVm%Tp|!$ zRV*+fH>=SK$cY4bFa%ivA+4wVL}2drFAU6=q#j2j=3Fdp@KQ3m7I8T|arO>d(D(C`yNU|p&nuX7kW3SO@7Q-!MwdMYu z2=maM;uFIg>I@D8FT%3pq^Q_Xu)lZzX_3TVaSIT%px#4f7xxP!CR;& zIW)3=Vr(C6ASbh_QdI8~(NxH7&D2OKV80y&ybXH!pCoe7R5Bzsc}#@fMt^BwhNbl? za;*0MwlWuE%gi-M8F@xv4httHP|6<#W^Kt_ADGu#CZLpNNVX;tamWSYz}(@V9+)_T zwkm@myR{rjvHe6%i->YZ4Kv3BE)Y#=u|TE8c4&gjfdlms#TU(= zRzDOEns zMAlN_eAQ2s1y2ILM3EXYe_;7Y`JO_FD2k99 zohjrPf2Kb~QzIe=9UYe5rlO8Q?t7I&u1$s9yZzGw^Ral^qyE1_5PvZy2_P6%#I^aG z0&_3L;^$EIasQVCv$tf*f%!s+wHv}Bd%s|WBY{Zn4Y3Q%V}3U9<_pxybc?K5wB(^! zw6~V&XhPAW8zMeTZ>YvA~%KAoU3Bu%JN%t76x(l_KrP@5(-FM%gS)F=$Xv9X+YJWKM|Xs4j4IXbhzVW*%M3)2z4P zra&-qK;2O>?ZL?l^~|-)H2e1xZVtXue7E~L(|d;xOWI~2W2YoY+H08hdREaAMLb$GTPw1S?VDy5tuv~) zf!SWcDs0+$QiY_QH=~LXrX7RLjrk57564dnDbf~&P2GTvdWFqG=?I_KvVc24m@7A! z`9sqOCr9^=?%izW1CdzN3?JJ8#6%g>CN`UPe?&^5rQgijP8kxu+P^mn(u&U(m|yl! zVdxCSGn-a!vsI;i57U0crA@`Fs7iYu(|*#WZEBeIvrKze$snxrcjTW1L(@C$Oc?S4 zaUj2HG!b?-ole-ku>rw_7C$&(3q#9XOhNa7T3Kn}f@Wu-omYWuot@YFrL9V~Nxuoi z>Kxj-?Pcq(eHnEdW7_C?Zeq|9Q3h>g(^@vTwwKLF8w_J!{XBVtQZPSPi zQWdw62b&^}cj1|+hr0HrFkmjK+%_>9?A)VwGsOEw|GdDw*M@jQ?w1j>wphG~F&f$i zE3GLz1CW-;CTIzn!}ekXPNWybkdS=^vzZ zCL_t$tnf@jX5vy*?+ny1O30n$a@RH)@vN6aXWus?n zVf#2?`x7{@iDMyb)D%zp@K~AaVN~Yi2qIS6I1p7Na}@ulM}OS^tswCi{)!;+9ajL8 zXaNj*9rxcFB!0DIhJwUX^-}y?kbnlA4w6Y~g|I=@?P7N!UUX#`{h_18f#n!q(73Sr zF`5dX2CwR1+x|gvK7?@cQjWU*9WTEbcwZ@br6Adj0-r(e+68-FRIi)qN>kR|kL|WT zF`En8Hx+5$lrP%1DXx8~C}P?-QHJinunbf4%rY#XMP+k}4@JC?ms9-{Wtg8(%BTBK z%P(QNvzhK3raPBO&g12Lrn`XYE@HY%{h(|zOxMM9-AvN!r^=?lbeA*TOZ{bK44ER` zdZxRE={7Lk%b4zZrrX4Ho0)Daq&=pBm0=&^Y#go$sS^|hneip znd}i3_em!El!NXIOz}4a@rz9MB_i<^Ci^=i^IB|a-a?e-or<*HX@Jl>9i@3^Aenb2 zlfA^2=AFl6=QG&_yj;X&tC{Q);NV><$#$R~uNO6X1>RlG%S(B=%0I8{`F^_Wt&0-A zj3r*r!ZtC@W|p{>32$J+qW?J%`6hlDVu{1N8{yq3?{@QU3@CZ8qN>lb}80k*8^K ztM|{2N};5dHw4TQbb6G{9@mEc#%WAp-UMv;k^Q%DYJ-cksKQL3OBoEDp5vd*(Nh+< zNR)yt5CatfrPmS!)xHTvqmW>v&4oSyS#^<6Xo2x*JB?~y+H5qC2p6N%AzVqoH90y( zxSW$_;R;OIKQl0wmy92nBgj!P`(gk1#1toUqN}^x%6^`R`gub8IU-b%mCefN;JR>P z%=p*=DBVyXrdAmnN#bh?SZcxq7)*zvDCk^bnVsShoDn#GQHX|PBVP<42SDLvC3BIR z4#5c2E~pWaT_D2#vBRU|K*-$!ArV>02$iIwl8U3kFh5a&t0&{`(F788t9X@oY9ca2 z<2*ogocMGgfYapGfiOpE&Zy9f3~(06{fwn@&4dGKCz!J0;}BRe-(e%fbV{vzQ-fno3aQHo(c%>z*3fGN%blBO5zxw z0yEw2f42ma9zAF?l=dVlMJ7(`x(jP>)aL5)KM$#f!s)$z9Jfe1AJ!av-ZoN)X&=+) z`FvKJrX3a9d`$dhbUsX=IRzPqVZ>du-)RuhT&5IZ@idWm&v^qh zlz<(lRWeC}4?3MHC6a<;O)7qAg9AvoFnx#hw#h%#cR=b(_OwRSLl#9qa-{Ecxx=t>A5q}s=#90i zIo@{;J`Vw(<9%NO)Wni4NatV+5IV8SHrid#fi=MF18|5Fw1dKr;_uUd*h3+3$9@aA zUrrx3>EGJ7&SG(=|Chkz)4=3WK%GbCg<#JgLWxcFQN8~VRUhn2u~0^Fo`PNO;Zq8- z{JVg#8E^htNWtG#{+mFUjR5RH{Cz^I9`s*^TG74+kM{#L+$Qkuc;80_e6obLv9!AQ z<+i<#_jM`23A9aLO@Mn}41oIp?4$T|v|6VCCxEyG*Z|yn1l*J`(2pWQZmkK|wSenv zkncxA$P47o5fc7H3toH!tbeEf7r6Te+&zW)MXv*KlS14CwEgFiB2HWmz*G`gi5wAn z6QH_M3H`r8Roo{0O@RD84G4`ytw?fJMCdIw5xVBbiI8gmZG@;Hu2F>85Edae#2>~Q zg5CTs7&f>2-{g#t5BjGdlJ-sfCh+@h#L^xIMW4jI{?2@+_@H=s6e*cn|Cr-;{~tXLT{~W(tMn&aS%_5ixfd;MG&H9`)RL(KvuLtEzx zQ1Jld%oVU05B8l2E4bM}Z+sGb$VoaMD=pgu(X~ia$(_`vO+YIluV9NI+X#BnIcP_G z!e|I}Z9CpJH|5Y**~8geJ41N-28cP za2r%CpH(`z=f?qqlym?3jgIoyn09w7HkUK0Fyo9y<0Nb&j4(O#D~uF3u(`&^_Kr3$mS0 zfM&y>!(#L`5nuc|pG4uR%im)n%?JAmLkMgOxsz7ab`G?iJhiuy)cbz}b}+&YABIXJ zr(`iR@%L$WiRy2GPB|A0NAu(>^2bR})JAWod_Jm*vie;U2a!B!Pk|!I_@mrmZt{uf zBS4te_sLS?vo3}A3jc0YCI(;vwY?T1jFz?j`|6lrkqytl#MP3DU&f&SY8P*$yQw+xsB87!A~_hP~7O8lXIZ#zXzqCu2W|93{D} zQ@)BHYnxMgEDLK0EC+rV@`9{%C)(4pQvyixmP8Q)o9?ViC^XsK=(KHkPmAfJXy?1} z@q0AJzPf&+b0&egyPXM{laVLcSwjaY62J3e;@5UY8m%<%Wn%B4zRUHNQnwquU^^s` zSc^1_*XS+HWg5Q>UtA%U%{kJ44?-gTu39yaww{RI)0D|QOnI3ElXoH{@?kaQ*)${~ zDRw8~kG7*no>2lFx56`0c^InONY6Ws4ab9Gf+~(_Y4bN!>D1((hpr(qDFAvxYNS#7 z3Gimh+FhRzdkgajbx2c-AL<5AOZY!}V9chG>5x#L;jawm&va&^6<@tv} zZ&BTL%|{GT+dD?~Oh)BE`(SNGML8rB%i!>kD|4PJv!b~D6O*#h0*Z6D)y3TjFRK~Z zIW67-7PBc}`Cto&0~3dco4c(ngfh@(WbJn%!1yyF9kASpIWR=-GV^wp%pZ?3yX7sY z+1*NJomnoy6rBU9id`lZNHE2PLa@_>3x&Yoa-k5+p$KJ#Bdr8e)FP8$in9_hlL5C9 zj={WzJ%{#;9vI~`h3TBV#Ti|0YV?A*R{a+Ay~PRXi@?N(?IV4@aKqc3d&q%>_6j| zCXtn~l%iy=<9(0g^&l`{w4u*tO0vQxl**7d?Pm)C zA^SE%Soq;$?R$!eH9`e=p@?5Z9~lqA$II=Nsuqidn?f!Ema~tfc8xV8&X83oz ze~jV*Vuo%n#msg1rN_D+zZ5K2;+KNuGB8mm7S@`p!G99bla5RY1JT0JAw|p6ASzs$ zgAlKGpkKB^NDN5EEKK~*!JY^pcSNetcUGxVLd57`-{Z(2!cS)Blczt!%P8B7bKmgO zf*+~732~8}|9?>YeWeoyA%stXiOvHPy&q=O$I(R(!q|EW_0fX)0=nybbjnre4`BNdONLEMUq>a>KF6%z9#_oiN|7KbMuN2?Cuu~_SF>}IRk7| zy#wL)cqWS1e4HtcQOv&gr5G7koF9x z@$aL4W#9iUB;{w(5G(zcLNGmxyEox35;OuZ~KaT?z)`zJk9W!I6Cij_i3D zC3qvAs`#c7fUoy`g$;fmMxSgqMfZ2N4Gbo0RD!_lLeBuhZ$;t6Z_NlNJ_9ahIPn?4 zr@!tQ`KjF>MSh7MI`@RXOfT-ZnEVWi(8UQoZy1P9h6u<`oWSCBVk%rNNP5QLbkWCe z0iJmDQQ>ni&JLRlLp{iq@lLP_Bu>Wtm>@|C)DeXuD4Y!mDBLZYFbXHw=) zg|)a6n%iv_yFlu0v&8AH-DW8l>z1MOcAI6gZWkk?yUkf{3GZ&R+;P}$v%)FD-KN8h zqV6^;o$IjMbUN2Tqc@24zyRj|Cr(6H(*o}h^Uv`=HanAhrg8W9w5Y`OQ5ebB>n6FE zt9Mn&JW|qY;x^tJ{rWpq?_&|_czWdWex@W>GP0_BX$rjse zzi***EuX=MEBsy1&V9IEA>SVcB!4FGaI><7aKIO0#^9&r-(g9;OVTa_bju*vyYQFB zzx{}SJPvbsME*wn-7qg6L|Hc?&$saJ3f#Q|LjG|`qv!DVIPMLs%>~%D>N)&z(A1#B zE2LbOPMBGj{xkT6j|S>|#s69VCGyW8-w5y@$G>2Aiq2l4Cv zF(uy-A7ZG#qypbF75U%<{zz^9W7|F}SABL@zQ5U~dDi~AZ~WzV0~3;zWXcDny>A7S zpTT0;r@$TLPVx;?@*hh%47l5Y#m)GQKeywVt-BnMjpLpzv;xo1qTFY2@4ho9-;iIK z{#pDg1gt^J=NI=~?{1Ye`|;huUHkXu5SN=#n&S|~Ua$Jz;q34s1z4g1&c}c~|FISM zP9Y$ipT_gEp!+VQ;*}+`9ms7D;`a(XKLhNwKaAtvfDSwTJt$)je#w#1^UdgwQU1>$ z*Oho?Eu^ge5|H;yl?^_zHp67=Q2op@$_$0Y3k92VRj!#_TM z6K(tVXk&e5-{jpf{O0l9;m0xvpJM-M@ati;ZS>vM$M27WN0#H4@H`85!9mPt#Y3;8 zSM*HG2oL}LEnxi~e)XATSr z4v1Pw(<^-Ed(8#REuEM(}r(g)l z^hbA#*fe()=5!*R*0>Z^VdAC-TxTwvIfzf3`M4C}H%>8^eLlt}cA`X?M90wLQkb6) z;*Zk>S~y`#w$}|X#rf30oWY$RE=A~Ew&`7qsp%$*C$~*61{4vZ7(H-c--MJ1JBy1G zFu=$ek1}==m>wT1nbu<{3KI}Z{amce#T1NWadCOCe2_s>rf6mTOu;353=VEZ^b2!h zlh_2K%xyiR`J=k|$^xLpx#%*sS+o9Ev;NniLQa6Z-G97<2OBMi=)?EQx+q_FO*C!Fdw(2%5D-I6(I3Hi9cNl zz%dLiw$&%jpateB%L2fhqZphDmqIgv#%$f0#Qr81KL1Mu`~pNzI4f(ZER^EH&(ZPG zeY>ajM9Vc2Ftv1<_BW7k2&KOjXuTCabpj4a1s)i>SAOh(E8=b~Lvl9S6Vh~-pwYAm z?i2M9J zTY;I2){P8ImK;!TE~YQJii}Q2-s7u@`)@1@Ee;(mFIXws&-LbR^nUTUSSQq3G?H zKqBjA=aq+V86VrdXNnUE*oIL9xHjb|^&mW-+x>@13%IYv=a7(?v7iCJJMc!Z*vC60 z;0Wh&@MjP;5Z*38rW5IFah~!Fn3cP4oMaa6cQv;x?8}!RH9ILM_utV%lF&*@3zSnpr4DA{|)zaQ~+u2D+{-j6^gPIP;; z>iUi4gZpV}P+PcLt1Spjv?^m3^Q8^u3)e5!GGE$$Z03tBVF=9^RcQBX z=#*n*YBiC*DXI$+QXlRut#{pnhKowqonWbG;ft^o1%zyYD2p4a^i*%8+btw}X_4Kg zdsMMECaO_qna&bgR#m`TX$k#ytpe)cMICTLw?#nvjqIBmV!&SOj;(3Iw`|nRa(gn( zJcXz;hHcbTWm|`9VdvQ3#F}O<9gt8w5ds=TT#!(~5^u4X?QH8g#CmpP1t(Uh zD+lUc1#TgF8zkj`|}1n;ED_+Tu;kT-)LY9glqFo?WU1ys6vJ92)!e!wb~AE5)IHh%QK(0toY*@& zj=@YOjHbu3Kk8y$(wMT3rg+DkD<|i0;fXV2S=BtyYj~VlBI0u23sQ4|z$N{`J7pX9%Yg0y zf2_>IMivx#U5=gi_xK0PrUTnz6nX8ykm9IcE}Ks5l~Lri6KM|mqh)g;Hqa>YdLgv$ zgukzB)|5?ik=He->mc8x1qPmXQvJVty0UDpC>mU^RPd1P0DSym{}wFLEt|`Vyk4V# zy7z-+lP?-v2Nhi8m~`KYWz$nMxN@p70QdLd8h#xvn_SW0I;==UUqFRy(cn6!$hh+M z1Bar)b-$wI-X9X^4^?AT{YFy06{~!U2G_Ux{eWl$>wU5Kx5(=+gG(p;X{`Ijn&2X@ zZ-+sH!G5g&#ZuuSufK`fM}2_tJ6J(n0L4Uk#-cvTW z7kPb;yg@U(uWW8B^7=ktC$#-Q*}S%BaQy(v+3z2~%3-WjF7o;zNrN{Z#RBFcuO9{d zNBx~;b6?pUD)M?CN*-ndKOopWP>pr<8%g;^tT8ScT)(JvK)HJnwHze`kC)9Cio8Cq z6p4TPPTBlb(ct4>eZikILpRiw4&pDZN0UNl?~HVC8cW zS1+Md1HXAKSQ1^t)oW3@fyq6rkbb0ytJiKR=V3ARpBHiU7AfWYG0@ywiq+LcT)m}A zJ+$ARvWG79P!U&exl$0EdJuFwz}n6S@rt;5=PNCvFPD%~-X%&wxzAw9bkV~#1F>;^ z*~{T`k=Gnxz%zDkqVzffW0=w}4Zl|R-L)~Ma5se+-_A#+_S+_S3z(G*IY$w;2Ic6w z+_S@VxdWJ=!Eb4NqYpXgpM%=f72Sb*E)=7*d=q|;`}YQBwci<-AXG`KWGdNl|8A_? zEtza!UXJ3X;ef*=T_WBNcMgmc12-CmXrq|)q9x6dw05v?X*xC4xwum1@4%hIpPuJ5 zP!u7lmJfDuXa=V+T^84Cpp0l=y2D={#yetuEKHp~snmxmQn$`h_5*WIO;w!*U_>V* zOilfv)-g#ZrXCfi!*&yt6Dd5SnB=@6Dxz$8Y=~Od_KWCIOT}(f7a@|w zuKyA=8Ru6r)UA!z5+w3yyab~}u50OD%rDW1V~a&Wn|?bWoI6qCxNSm@W%xFY{3>mP z&7)dh2nz2Y3cp8nL4d-lsiIkVR+ImedEmv>;|T%1v4 zuhz1qvTRpenYu*`*-Is7o4v0RkClM3UUt@)(3uHCC6KarMP;>dAY157%nIUVF%TK< zogu+1nW2qLTCQMHw;e_(DC00!6<3KdH9`d;XKACBIX6L7#mcdFAl|YFy@;w8PI%MQ zYxWJ(xuE;+7MrO;V$?4A&v37k|3N>I(E<4oB!7s56jD5E5@T6V>D1v+tU;;?9(QV< zs)1u@$n*7<{e{P1B;OFEPKQ5^HaWw;ubAROy~|PN6gZDnr!Xh)DZD%3Um#cPqEa&F z7gN|$;KpL|iIRDFG5H527>UW(luW6ZJg;O97ZaZ>nPM^Vvn7~{iLsKop_n+UWVRN) z|0tRLMenQF&b;VhQP|$1_l}a;So98;%q!)(q3FE~d#)9|i_xG(Zywg}70r_+(^oW) zmCVkfc@P_y6wM!&%y7~CB5_C^EvD`YQm1j#q!i{5-4dj*0`0aSiJ0}fgXHg(%(sH% z;gWZ1kUY2K?FkZ?N%Zj`aZ4$&C`jxsB~}KBWu?Tc5e6+K-WGUYE+sw?c=whPp9{RV zmlFRPc+;gM0>&Fk$*XZ(VJSHrcrB&m&jsdtrQ~no2$53qLxH)!l*E|EyGzM$1gX1V zd88njijl+W; zaaPVX0p?bv-W#Mi^hFaca$DD8>B1vmid~p4Dc+@XJKFCj<`5J zww@{)TwyfR498|rh#(hvT@NaXi?g9@l0}2-1~tpEIh0^`{S2)2Q9iw*jE-P%eFabu z7kdc)XVKs~gkr_ThQoJ5(cn7bTx_^*TZ;zQ-Oj~+6}F!$8eCuHTwztP5@wW zu_pmf(cn6Xy2Qn{o@m*;jZOf9@NdH{#5VtRz`5eT4!EslT=(GLW%A}SxIvS6bBq0l z{lB^UD~w}3HIE`+cSu4Y!tQe9OmEpd635#fGS`DkxX0sN0FP#LG`?yJ;u&2GbHIMD z+A0ZVzZ9YtrWQhbc}5{Bh-iVKs3=T=b9xCYzcR$5P~cb^q>{)=9g{Z9#C1R}6ZacL zrnr^}({VQemySc^_0pXhrlXplk&6AX4Y1yZYZ(biTUt&a!D&b<1BmxCc>3q+3}F*h z3_Wx2)e^+Pu?SUe#rdR^ZyTs4%p9U}Fjwd@4!~8T$?X$kA!g?aKsH2fL0mc@@eVY% z^AMw*n;7V0%uQ5sTZKwS*q-*HKCc08!Xb@WIxa}>SNQ7EFv#Qbfu4b(I~DH6grB_{M(@w zNztXqMIy2%Q7*(oqft2deoK}QPU(4Q7yTTypAJ=1+>P5S-nuu#rqk<4t*%GwvBbZ&dP z6|EHt^+Ytq$5CA!3SN%@TBeQ(TRlUL)V1du9gL{!ZY_0JpcWl%Tm=C~QMX7eQVyo5 zDZNOjZVRXyZy+7q*&JBXNVT+po7P>3vUn&Lx++Z+J+YZ%#J!k5L&oBD8IIZDc@&ph zl5Q20rNTO_=9-x!)jY!C-qK6m7!Ro>S?#zYr_(skrddaM6g_LXr=lq_?EdD00|=qjRWl!?vyK zx3S6Gx#aBSgkLCll=DgcNQj~u1XPUk*@?UBm0qLB!2F?q0Z;Hy&@AY2w!F9GJx)kf z6FP4Uw2XtNxfRGN?uFbv2S|Uu64lBADzYk1P$fyolggD9EVh(;Mkq&5G)B2v#gSaz z`5>3K-WFhCV+Go??k&x=w7}~}2o(EHDk!$3NJ89OYMC3II88-QYe*sf@(k6|tmM&2 zfJIL#Cqo{=Y#!I|8BmbCW&JFp=R+HwnrPZz?##__~_; zO8TR&bnQ%>oOESXXR=eEI7r`O7(3#2bKwLr=@p7>;63KA4iYMt>X#TV#!ZQkQm~Q8 z-cVz@TL>xDl~j$DQiNeC6Bf7|m~oO4HXUNf<8l&j98A;uD7 z*EeDo*+np%&V+?^59dD7(t8I!L}%S{?@|Djig1iVpdyN1f-`Y2q*k-?#x+{AvZB28 z8xQUqJB;Dy3DV5nPg*TOX`wS1^>k(xIhTH8BN6s4$Ze)tm}o-eZzuG46DOYRXidQOYT3VuMAK^%hfi zF(jpFNdiqvvrGe-q`f4gjL>A{15FlBv_#?tnu37TO5sXiS+%|kGz>XZ7L3=-;YPiw z^xc_pY#a0rG^itoZBE)BPoN`!9Nd*qybq2qpHntx`7*AIyA}Qljwj=8CGR?Uw~Chw z`FJt!*6?mE?>KOb9y8!0s)M-LAr!{erZuwzt05xJxTm!Fb(Du5noI2q?gR<%2R$o( zev-3uNOtXA+|z>u=aoAye5~Z{wd#QfG;^MA%mi}!jreho?5kO6Di+dKhlYi5y1`K_ zO;yGB7}7u??v(<=Q=yPROA<(7;zlP|I|gf&?t2j;-DhI9B_ZV?0J|}}wR?XQYdX~1 z)94>H-zISSF;vMJNH}=p4@f`GfOuG7e-d@u11b25Jo^k;b3oqnA%@u_wP&!hUw#|4LxKjdPDZi5Vz1F7(WT++5=jRkp#CHoO+TWFy5}94+WH9@{)F zFX5Xr;IAjw&)_U<7JOab`oVRZ$RSSbwc44yGdZ-fMsO>FpL(3}40pV;!Re~8BXS0R z2)}w!&h7b_N_sVEYVxd`TReb5NNAh{>{x*>cnIr#EQFeq;*Pc^`^QpnD+^>EdVze; z4q<~ZwOO<##Eb|;wZka9qJrX8y-Xn%DB~HifY$-e5)rOuNj!1oY4FB7W^@V`vM|a) zbtp5`y-3%3NK(NwE()?tBcw9IOL=HjU-gt{e2ob3dO0140D`Ls94kyM+Kbp)lEd5Z%VH zKiPY`--Bmmf3o)u43(w9O=SNqcxK3g^kfTdljn=%nYC|2*+VX?bWYj3TN=SK-2vGZ;=XVj#53?kiNydOwaPlY)wxO}5xWxK z#@}gla!FXare->RnU*}9Y#Io=gi@qtJd*0hAuC&3ar0X271l30Tyd=(w z=(_dznX9k3%}*6SlR-`qh9GOr7rK$D+JsJIr?YT(0#GyMOC%+6UWP`~vofV4)nu9K z6H4Pv&O_ZhJJ(&eY2C{()J(U8k{ZLx^kZi>V`ucCvK3cFA1HmJhP*KP&{Xl^;^+gn z)QcMPVrk3^aXkV+DjGA=b+mvht>4HETUud?_GhoD? zsd!cAZ>C|czQ2G?9po$#%@9B1_g)&%5x~5wNFQe=R=Hfj68n|>NkkvRt6B4{sDTbB zG9zZPIcCbZs7VqF;ZDQGowOflZE*Cie$+(xF;p(<)^bGe`%eN^*Q4S{#hHHrnLqHb z+gIReJjE3d*E5o8{YDobqbXrcY1>8UZ9gIYe~Q$_s5XLZ1{(85tU{C_0kxH|LGb9l z>6y0DF<_@NVeIq^8ER%c1k_4I6KvFzP^6+z4+gyVaj-gSbM`UvCk-6_GK?0jmvEv) zR+(@xn@MhSGe0Ofs1w6kA(x0ZO-4w;JbesB@@^n7JJ`4O=p3Lh(AOm99{E@~rG{1y z3nwR8@S4XaF)TVZ1tgr=nh2Kz(x114k!eH^Fm}sB=XB9sH^-pcEJsR-GQ<#d+xQRz z?GAY_q z2MQa=U||AgD{vkS)4LAlrpTb{Lcb-7ywca|_qWN}tER{kSX=RCE8ifFghPVRqp?}m zDBTNpYh}Ws5JmN})w7*(`5>2FKHr%sx29tYWr`jC4b@C#`cjdW`(>FD-cNKgr;qcFg%O<@OSyvh~} z3^%om0I3gReY6yK9riy-;BUbyI{pXtaJQDmt3XfHYFHnsM%Ee_SR`PlXay3K(=9pK zmscJ(?fNdoPp1S3Zb@qek?-3o;z1W!NNGI8``iGt<7mjOfvw00?wm?b+>&vnJMXhb z>6fwen{4Si3!J5|0WJf$s$OGj@JUvqd!fn5s6OzA(a1TfW*9+TjDR-+4%>6W06=LA z^uVYUJPnHH0zuyNH>J~S(;Wd0Or#ufg1Qs&n9g*+MmJ>3KhCE81iEk--B7aA+HF*K zqi--vM1b9bRc0_sJ_iWGR!U+ojJ=o<5HlkdOWf(&8?IST3Ul1Fc1zzVE>5YsP4D*C z2j;1U;M)4*tU;@f_BT~EZ9fVa8orG%g8>`0zB3!?C$RwfFO1$xv&`3Kk$vh9VQ&dE z%c+=(*`La?RlMs^4VNXkwxN+h-aaV2Z4C|v+S2{~8>oY%tr*^CTd`&iS`Wf#X3d;j zGT?V$B`!P{Ivk97uE9cNYtC@d2#c7OA);yI;yp{C?JBgvd2y&~;JQsPCZ#TJh5HE* z$U;b4C*6Pj4c9qXI2D?(L>Mpz%X0OEUOg$BT6P8Z@UBkGZKdh_^U5ZN!Gj&uQOVXD z`dlURVhD5agPV90;ib6Jm0_-0m2%QcLZ-fOD;b(xylRb_YpLX2BG<+8wN0+=a$O)- zHYJ6N911oZc(<0!uLgj?S{3VG*Svn?DIr_>va5slSxGQCnZ}}hO*^!$`<0qpy3qdU`U2-rj6iPj7cV)0OMsfy-z0pLq%LFm^-k*UjN0@&T@bf&8Z#pTn5 zTz@9r(SHWO%l2jq-MMtOE1k)9b$90q{k_I79cv&cuZ zdVvhU$n_M`y*<4Jd~vYn3b|Ycgy_l^x_WUb^k;fBPc~afr+c%#Jza%dK9fgXnVf#f zr@KI2;MENxb!Q7e3RD;PK$>(e1FGh`dx3gaKj_L2K&PkB+ufT(VVSOUPqrVm@I$@_ zrSx=Vfm3%TUr2ZLg9`kRNzeGNKLaaJ_c_bgk^N$^`~d_d49R!n2ZrPy(qegU+5ACh zNS@~e3QsYsFdW$B@AbB{#AjQ5}{rX3?az}lq4Til6;6HLCpCB{i(c|)^BqZLCr97s>l!q zyBgu!;2X~6t(1%NMWd$m94wR5CEcZByA zP7S!RQ2{k`;mlx^8dD{VqBb&930W<36t&ZstJR1Ns3c*>$Yx2wBT~H|=|41%Bb|FW zOMy+}6T8LVi?+ICgqp`PJ!I7?$C1c(V^ExDP3~4-?!!$A%ErZAz^0 z@2AJx7}`cnTdV0R(Q{=3%$CVlAK*MyfZ0-mtET-61<6%%?Ud_Exz=(?P+sfgn40YI zu&%4G4rJ33AfA@+$25#OQuX3SmCPHF{eK8FkMNj7SCE<=yVe9J!`{xx z=vb0n3r(JZ-Yldug=`mop|WU-G_*OgNSe=P3O$)_sM(%ucch$qbNTLUx(8ojCUh0l z8WEcVg~LF}r=e`~xlASpOTgM3-GxkdrU%*__6yW>8kwL`)w+SH(Us{bg3AHw!ZWR@5>viL&_ujFCc5KHuG)&E@k>bHmK&DNwB!@?Gg}7);RI zk;#$C6<|F86ex9In9lWQVG7XX$iQYm6#yH+WxBf6l9DgT0iy!c=qcp$`CPY{OZ<}S z?WU2{jkkH&Y`wi9J7G=74HQKs53;uXPl!3@9a}FjQ$dPa5=+h-%kyrpSWSjBZt^YZ+8J^Rd+g@%Vhgu3lj569eS|(=(B&Czpjq($kA*N^b!Xjsj|e z9di~fFxYHeT|H@pc=9M4HV(dZcla1opQ=f|v@>)7ayA2-Et~E_NU66F##R_G19)km zod)u~U5yMKzo~3~O^Ke#r+Wcqt~XDUFVjP!le93d&}y)9VT>ZW)SGr6GMRK&cP@vZ z8iGvSFlM6<+3svNfP)c<7SGdo)HFwzO zE1=C`lV@`Rxqiv!d(i|4eu2M%ZcmOS3g>0A-7rD3`5wgdK#HzH^aT;LF47IgcyAgE z7IG`7*@eg@T!WqhknQdQw}L|6a-k6IZG=H#*-8hUhRFH$A z3=St#cZVGYjhFAvqclcJGr4^D0bUNwaajInQA7dJU*`~-OT%ZT`b)#NtKs}h3~bl% zPHycA<=|pqQB1l(Q9uV`30eQ%6OQpI>&>bT;N7eK{$Tgu*b zF51OuNivYELxr&+WEX)Chmb1*U-d9*fNkBuM#k#v1iltEid%6`e;D{;ps+^Z>p-Id zI2oxbmkw9P0$*;plBUhY8fqLZnaRL>xgqr%nKlfy#s)21jFE(>7xVErfgTOHT^q8* zhP<)tZF4c7Wn$W-U2_7jx-lPzP`xn{w&6-C?krHRVaz8P#eCeHQH}X{oTm?PcPO|w z6WpC;?g=3m(hhwTC zJL$kua}-!|(;6emP#=BAOb-2ulpznxP;(UXapSkvwBZsEuF`p`?qE~RxDN-F7K=TA z=merBP?;QCf>74sAu%GL0U^urI@g=-%4V`UK13q|!kT&;16RFym=jq9JYdGC<&n)5 zpwS?dId+4GFcwmPj)7=~>C+4SgFzb^ei22}g<+C;UykHoMpF+qHD9R&bhFs7@c^FAi6eo)hP{_GlcUKPN%Q?UqBI?ffVEhT1 zFbznYK0_3z7w|G{1@(v#uSWViKrotp{IWV)Nn*CYBK_C=n)F|s=?&N9H_GN$!hxgn zLrKF)5m_A#j;Rkft0hz)oUo9^5Vp|?EeZg~v@a78U1KyGOeiID962`KLKRcg6=qkG zQZ-NF!Ez@ZAZm#EZz<~B7!zLE?-KRjE1TbPDl-}&68Jzwj6~Eyw?b#utF%#DSQ6Bk zrc+OIHYyQ%X%?;OMOu~H63o=96#~Uc8I;N;I+U3;2dQ|zMO9ICRW0$VH5E#E=nYs^ z#lgsWf;-kMj#nu6a^XyuEGAN8BJ{OB=4_4CEhaw1D0u^K56^OXZ^?W<@QyU>LiLru zW9sK&0$^>sgbS($b9Lm>djKG@JGnNgIsFXif?b`CY-9p(*oRZ1xIGd{y-co^Q>>s{ z6KVo5y5VNg*Dt3=s!?7>{CkwG~(o%j97u5qXfWAMkau> zR3Z^V^iFcvCl#3hwM+`oxRwb(Yvv?|eVQT@V9s_1YHnx({Fn5t#23)F68|RH)*2M9 z?pui;pl>BPM_Jb?aq4D#rDxcKX}LJ76G0hwYb_U=&zvGd2R<>Y`~2f};MdFw!B5PA z-|^qVfj4jZ@9n_T{;%b@Q!Lf_re0}m-WwOZxQP?B++1?}G6-$x3~nGr0Z~(ha`8&& z?$*$zEa2is1=P{OoIMhAce(yEJ_UF#=G6eSwUQ*LLomR0(@DdIvLMYI{hTmIQEz;n zMV&lu6g#pPKqPiDTIK2zN0ECtolN4=)kGMR*Wy5Ii9F z1yM0Xs(LW@42}W@WF=lDdEl0ClsbmGWxF!)(Ci2} zngMed852z-&YRBU-3Q=}cy$4xT}ax2g0Jynzkc6eLFCUUb5k zL$c9i#oBR8maA(!IghP!t(YhYSC~~2x@;geaZi^GM3c|q5qObD5Jlc8?-!G7l=s8d z#%EjD+Zpn{|Fq0n46s1tbY(G>7=va#J>kUMdL3KhD_p^VpX>r6S}zv=cdIl)K!y1% z3}ilgYnhLc5&Ad{nU7vqEtp8YT0>6t&|~Y>D{C%{yxwup>}wQfVdRET%*M#Cb6|ih zU}Q(}uoDR*?<6Dtl4Inzk&%CO1|!!4q7j)QMxMm^X|j6qUS;G&#K=y*a?{6MFsC7c zxXcsBqdfwUYr6zO|Fg9V^B8J$;d9xA&%?14VW9TwwK2Z}T7)7($~a%kxIoLeh-IwC zu@$ZikH=ir9-7kARi4B`H&6DUGj-Tb+E$5F&qZiJLX9rRbcYMK60922mSC%S7V%CX4R7Fs%coPFn=tDJAo+!27U> zw|b1K8>&fp8XOH5Y}M}>LN4l&8OuO*%}6XXuYo6BLM<$;f!4p{R+i7yD+Sw}a2E_+ z0<4VhJ&j;cg3D~{2ZJP~2uje6X9H7E+S|Ek>Hfu4i>T(Nx$BA=3}JC?_Ux*geJ?zm zm~2m0tR<|ab1u`)$z7q*!I!ghV&m9lu5%*pUcn_!N4pN*sC<5_XCFXnb#Mz?obiIc zeHgoe0;U+H28raBGo4g!iK`r#n<=;6B7E2owN;ARg^Jq6L~TvktO`+kUv1RlQkzi^ z_PAQ)i!+u$ChTbblw0ioE$YP5gtZDmS|P|1f*f|`4I$vN%g}oG8-Gb)x=Q9Ff%&I~ z$Tgs=S}C!3i?dAcSEtV3Hpu1j@m{&y&i8MmqU*JyAlaix<`v1yh~yPz)8mlz`sP69 zIyy+TdQ1eUW^J9r@V*N5n6Pz1J)*d`)z1Xp8#FXlyN&C>1&)B4uPV{W3r@JP@`AUJ z7j%T!Z0cWBdl}q%3Wm6Co+$h#+tjewk7D3o1kD@DIVJZL;vYLYccyYgC*5iHG=>wLbzCZ9GF-O z&$jJKsO1|1!0}Q5us{J=L;x0Ji>R6aFuXA7SWKmyBX+13XLJ1&Z@k(vY3zRuLwVxr!Xev7-8>3B;vztxa3q&N4bjK@CsK?b}P{e+A~> z8yBSe(p2RZc|I|@$H{Yh3vQiFO^`815ASEjnln0yRvi_i`ah;hRX#_f)YwZRl3ih- zi{YUf!qeG=4P}?y2KK)>Y^fUzEjF4j{R&0j2ASy}ISGU&pxFsmzeu>+EkrJrjm) zUH^lgakt8))G(v|VY`E0Qba?Y&d6o;-q89|aJ^r$CRq&+WA<5ZP88Rxrhz(&5g0w8sUAR-t%CQ4!3Mi_Ran=d-r?lF zMhG?f=JZY+LxK61{EGwgXAR2*%;XESmYyW+CYpt|`L6Mai35Ae`h7#FXksXmpt`q-{TaopuYD92nMeg$VBD`LvcR#3h zWKHkBet2D4X)SkD8gAH11m^hw+8|$DyVE+;w&`j))1gG+ZfrFoi{W?9K8;B@w=BZ4 zz@A(7PjEK@uziCUUK)qV7C5eeD6TcVzX7S#RCI-f*v(=+P(jri zCbQUMKMh#Kg1x()1NJO5+KHpeq=6OOz~9PW#yLz!}BZ-L;DP;GOn>N{m92kuxFN z4%dqxg>fPa3IcrZ4b0aX!a^+xxo{m~byiC{AHwq4{)t15&)hBe><<6C7{=DoJDk!z z;UAiVuRAAhiv^wQL>)pc?M#w-Mk$%Fp5JX%Vrko^msbR;7J*t}m^9~K#0|b1l_NOK z#>_t(lXhq%XA6>vgveadKcHHmpdk*QJc&K>$nLRv6Xij;tiOA z&k}fMR6W;18f%SW!RS7)NE3@Jr^MNfT7TXlQP+TQG>IK<(8dK(E~CF)6v(;TnNnPa^yeVOY4rRw zVrjQob9PB6Wt~o{r+4NeHqe+u|IH(oTj5mCuouG4gp;^lV8qfH>f~0t$C>Sljk`z# zYunkCv%8~VQ@)TOfb&Tw{a5=3pyc6`@}N`poye?<>`vHPJf#QmftzNNG93Eax_Qes zP(NDp9mWUtPmJF}tq97wTieg&_#$YL0c^6(j)p&jk3Y;af_tTt3iQsn%eOo7P7ftpRo6C}o0?gG zvblV#o`p5HQfR%9rS}d`?a@v19ZT!6HEyF-F14%Gl5y(j8R9w%YYz_>xPwQ%Kop|j zeG_15@Ouff!d}PIx06Gxa_{7B&gA6uFT0aG3AVOQW&F0P&Np_8PXAtv7}0y~hd;9y zQ$;w%tpjn^1Nb+AzYhE6e9Ymz5U1kkl#&kre1A8#KGfefcJ+_QkpV+v6Fb=#)!=_v zT9QY%a*s|>t!dZ(12}nZ7c5w}ByOo<*WB6ZZ`rnf%k>=h*L~cPzGZmlgzWby+dT&6 zGdzajZ6)LLAYZW+JMaU;ekFcjD|XUWT!o1*&f+!SK%?(M_ZMk%d&!LQY+jNWpl}kA&%`d1M;%Ht;Nea^W^_41A<5K;jG-( zf#!2?26%9WRfwYH?ARp9YHw?iRYU6kUy;?H%`W>d5fMH#8+F`XbpCx178DN$?Jvc| z0TB(m{|AVMi&QkMR?%E)0%wTVA292VRj3YhFT%GP|vrO!pIxsPgENw$0dY|vLxtz&K z=gO8aHEv6wdF)2LQx@LIso|-ElX;XiZ^+)eqBJ{R&IDlZtENWxV)ha;xm(oEVT;=5 z_+lR7DLjWlPrw{T$}2gME*79iD4Rz?i{FSV&czkq2geHTAH(3e(u-c=e5?U*C)dx% z-2e_ML}o5}pc8P^|9d$iwS|Yt>8Y*Q#05wX_$^$5hP68VNO}aGa+55PJoKblBu-)HtU@MNkhyk~92GjYf%yf(&)t>=P;^qV z(cwQRk7$1&L_0hhj0XbRfJ_NJy{gU!StlbGKM)c%`I|t87P#hL4$S|N zqu@Ue09Xb+6Wx?!2>|~jD7lW)1LMcYhK-sWn!IIlXn3R?4KB2j1Z=N}1O!KsjS=Bl zo>JNbfS#1&9HV0)c@j8}Q~gIA^ZX|4OYkOW9(_i^ufc&uAE~70`i%$nPLYGj!tU0x za4X7Zhdv>+gj=kDHFH&fFj9g`XhG4_g`x?xM@Uijn8-8r1cL;^KM&&XVLUNba}3#@ zLs3)yKL{o`wvtQr9tKK!@^{7AfS++`IwTE?&{NxpykjjK(mpu~WTGJvauSaKQGU7x zu>WyjmY2*mff+@{XN0vRu!T9(d-v}e8<*on-K`}B4_wpv?kO9LK!Sb4dtHa*77%j8 zuWLI7XdUA&QCIj(GSRu=am9!H)pX)Jg=Kj1sq6F*kBMCq`$xIBDZ+z2`WS{pbSoz| zyd~E|`0y!^Y@xK$sSN0(ajx!N2rZooA@NuE%o9Ult`z*21cp-jNkLk`5~KwYw7?OPj`GC5wR@7POrLB#GSK;qmc_ zkvMYN|J$rYqf|nG14=idp{*s)T3%8z=TU?q`YC~wn{Zm+^(Y(ETnD@dF|&>R4OJx} zYIs^R=;#KwQ$p_qXxZZ5q=y-^&+=&I1=KA%j)J_YgHsd3XaeL-f%DnIZY?*vBXJUR znpnp$=Cnis79Qk>sb9!SW?+1jct*Y~1 z?VlQ$EtUCk;M6>b$h{cPM}ys{aBXLl>83aiY`SswfvD*?R7iN2#*a`>U@;t{%IFQ8 z`OAij_{%k%@>eP@T;t58=aQQ@levBsK(G?_Hws}CC@rj9WL zU{wasAB80Nq>N^62A8o=R?cpCHLj7kL%z$XeFAfg&Ga{JVeMa2#y%EXSc_IT1%?Fp z7ik|CmZt#O9D&>%F{RrJ(}EnBulh>^^8-uC3RI)>z*AArpy*tHxL_m!D0sOCE=bcF zbrN^*w{{Zd;?d>ON#f;7&(OnP*%fWPdVSgOaA;RYc$oA?$I0k0?$&k~ihb_I!1LAMD?blYd zHv45o$^d7-8`rL{V7qSiVGs_*8kcly7s@oNWF6sF6&IAuI>^_O!8pLU6=9mP%E|z` zVp+hj7>U@@S{8)JNp4&I&y(%nD(#if<9HWoM~Qb4oAx)D_V*-h3`Q*GIxsps1&M}c zn&~`yM|58c_ZWh8mP+NzPn6P2r2wYA8 zU^aS<5fKWs6DPoU?`G{1+CST07??|t4F~SN1-V4xRa1cl-sS%`)40xsjwclb<|=YO zri?3Dt|M83SYH5AH~@g7c&88%E_vo;7PXZG=%cLt^+d0xuD7V&rKvQ$u+2Y@bU#6? z-vUC;C?^$(in#hX1|*~^D#KgBph6}YEdudp(&pDln|HHO7M5}DaR(a;SK#nR^>K)^ z*j@e`30;IQFsx~5Xo^Zat#z0bCq)z3S1B>SY5Rcg(&@v%zE_W3i>|@BJR$P=c4{s$-43xpZBI3-K*f4- zP0(V!SfSb<;l96u&@Te=`$t2%?jHqR8GMW+T4UsA>9#Kp_UN4sLfp=1d6JhcuQJ}X zeAqE-l2<~%LRfUiu;`G3sW`~MkwAW)g-5N1t{CqgY_%5%c+_g>d-1YgAmpy6fGqA7 zrPFBiba^GsHE$Wr0P1j$_A;JZBeTzoCc=0nvotbokYCKc(`nkA4>m)-6}}pb5+h1< zcCH`X?q9c!Q^s^Y$(v#KA<BZ06Z;TENGefPu62r*FY12RU&=)>X@xol>+G`0f$tktS@1!~h=1+`(Q)HE}% zw!sXB`fS6{+`KI^H_;|7)ot<@Y?Cj?Ym5v>+GG_q*EAzxsY)zOY*YqCot=%KPCV!l z=b7)6P8`G{l#;TQx}H4`(t*?h_%+Ax*YSp*26Jb&r)s{hDO^n=pvkY78C%2Fig}q-_=3XXb3V9fS(8YcR12R{-v4$!_ zwdz>IPN>i*P!smyN>UM&%APwsCR)0XpkW zv{^DF!Xd0!O9kFnF@%($fD#!Hv7&7x#>pjp)S2e1tYffne&}XMPo-{oi;5D2cR4Z> zt4f%y9=z?l4vfOuW0~zCycOAlM9yCxBpB2Kq@0KPZc155Ngc@c&^7)vNbEqXA%uPk zyq1wY!(;n4!=DKKY&bBrq->&$_D)P`dpjxnPUaM>IIof&l%5wOag_wo>HE6Cik5%? zR{^=gmw1i8CP=(zwx-)@X113w2Pqq;Wn&JEv)wy!h_?^}`d~A5@el~POPDm2Vn#zN z*4~^FtO!wtT7;fYyVh^aly219 zp>}DCsn+Fq?*gti(PZ z6?a_ZX0JQU)v})v_zUea&dRS!ak;i<_1FpHsa2`fV$i1a_7T^eRFwx}?a5*L0YQYb zJ~}un#>Nbe-x%3&oL!AJ=Gt#8$oe#*t2VN$0WC6 zS?*#nEOzd9_y`MIPtRMcYquyRioy~812!Q*M;|otPGeoMTFFzQII@Yc{@wH%i*xiE zZ!FB)D}g7K;@XB&Yp(Iafun}vf=4q+Ye~|(N#P#>h*+Ehh>ctP+Qhs-%$VBF!T#N$ z*I1mR*Q;u0*XzhGK%5vH17Wd9uX1HuxLVKJYu5Mnu8TPDFq{iJJw0pJZoB4sNaNU9 zXumi^nrmh7){zNtBKpQ+=s3iJ=vyYFuAM&vWpT603DDTMt!7RDT_&q)Wl6gRBvvF%C&04mC-|J(z$fp0Z6>;TJ$_Up&+^smj1yE@_ z=7k)fcB?2Qu=5rjPVUG(vT`NK$i+({03PBm1{8Lc0}7?ePp~4lh7@Yn?n<$+La+3L zd^&!ePYd&2n)^V-F~`2uT>ct&(s0qFWShQYp$ zUj!;Bs&JF7xvM3`qVWH)fx9}NnijkmSboNSH%h7~wg{xDZzn}4U z4q(|a_fQrZ{y^4bijkqvyOtY(zicRbO$*HD1G{zzIm~6rRwT#;VKrRO>lJ0nL^_lw ze%emN`+!&!*;)mX0Q}qqUTv-?!A#8w_UOElm$d6So20SyDFTMy1}~7%c2} z%PQTMTL`xI>Isxhe@|5ph_ZzG)zT>_oBknnJy5w7v%My?@~;G;RdJTkzD~+S=2}U5 z#ki8)D-HA7iQi7dhpw2q>2oQ+%`dfTEuQh#@;cm(tjEvZ+ndg?H*H?Zz4Ht@!>Ou@Y2Wz95^rjE_TXWVfUk+q)Cv1YP z1gIq+l*`}~hQ(H17DmN{IbemBZ-@0}bMeL2iO*=>hVyam#mM6~u{7mO9&aRf)RG_1 zkiy#w)QHc%_G_KGV9#;_H5M*qF#K4MAe~JnW%HK$ZO89x6`qRWd8gT z7ibMQ9sT9%DAT{kRokti|D7`WPEU2K-n$9?Ie4p^jf-M=EFg19j?7BqZSqHBOej`I zkV-TZx)6@c=Y&*Tx-38`a;wb{(OGtI^eXu~R)gL3)Y0l!$^MA(bdI8L>~uwXO=0bd zSU#`#q0JPYBw@x6V#m#NQT%YDb$(7UaPKA}_{NmZ5JeM<%r_d!#b;j*`hbedf2h*4_N&o?081~nypY~OKRtAAQq9vI{PSv z)A~lbB0Lfo7HTt{SPbM7g3L;m@~LoGQCuk>z#4WtxSM}Rvzz!Mofc10H}l#cZo-=} zSw8;L@f(xZC52Jo(|$qGi&{C))t7vC^T_ywmK9vnDb_-3biX?e7t74=<_MDWJAB=D z`oix9*34+RSn2&(?0J~v6)ZV;HVKxyvb631Mfv|b)HAY+1lKW`OXeemv@X3|~P zbB)#0b-k_dx-Rc^lVV|zxsBL9kh<%d$t&u5uH#rw@920nOHVgA9i;v)YO2jz2rRjY zm;ct$UY`c2D+q4Ws7*4N)%9$W-(-}Qx=}pB9#doLV!ZmI-Z-?V>p4D0J%3XOwe}%` zbv^gZs+BRWcCmg>c`Xn$z32BelV$aU=lf>0S#NMEwZw#AxR>;8bv^H$RkPP%*Zg)- ziWeSf^Vw#yw65o8XSJ!?z3BloNH@o`P5u*h1Rw35;ALoaJ)f|4rZ?-Lf=X%vYBsg z!Ox-OBEWMS5?be(-WFz2tPlq8@5(64*0<9Q+%nX+&XLA^2N7?rui-IYaPR^I5ayq+#?rc1%)1ple^ZvO4&PYZ(7 zw$FPDEhqR*PuP5wRHF-P(YqEAwcSEJi8l4#AjQZteZxE>)C0F@S&*>hBU~r-m|oXR zuRCLWq(f4TJkufix(GPBOKpMX9a4il(|4Q|ZPL3<1>W6E?>@VBa2!hT!_D-=vlNNu z>Z*1U?u+UK7!R2mJVb%9B&S;PgdMq3yLmC0XtztaJz}cw2!*qQ>KmpAztK#;adz!~ zXln6?&Gd(0wtQQ^keGDZ)ZcV7ot{yrkh9Kag-9|E0_=(+9?lI(5{tpe_C1nzL~Z5( zx(dVS#$ZJ)!+5&fKA-7sNkIXAuE|!*Osue5xW8^ zECxtr%K4>LhjgPsrv2<5j)EhkirkX@r%k`_?&{`^^quIfEgoL&?*wsq7rNYccfT&H z^-{Ksv+}xh6}x$>%MNC6Vu$wgfEL_6Jd(BNwaDB@kjd#KdEBFhqsKC_!WQE)5z8i8o(es4g414} zx`4gBpr19@DcNXq6eogME)?gPT<4ijPP?GbG`7S^vHLBiA1@5$UfnQ{*J>VbnC1Gg zd9;=1A^+~|c@U3fuOVO_u{iHMBG%V>U``hs+HdQGI?aB_I$a!$hzx%7E`nbogBZnq zB4Gj-isLT%g(pDtzc=TSm?^Vac^ zVnQXf&)8tE5ZA1l#np`6lm>NVS~1LXrpmv}#8+-cT}F;t=}c69q0ZY&&adU}{F0Vm zIP+`iKAnXWt}?4Faupu5+{@OxNwXLkk1SzDW}$`PaO0&3j9RFen@hSq`j(2;&^op* zUn$U_k=BbN4T?T>I{CsZ1&~7%Bew)pTQQ(|se$T_$GSTnHPzc$1f!2$npO^4`KLAT zTrN{BR7+T>+_j+vcBXr@aPsD>KnQRTm)_M>=_sBxOh>xtvw13o{?0&^$Y0ihEpKsl zAaUN=xwE=FJ0DW!gm|ks<4|~S7}n#4*$x19+)=j|ayOMBOftHmR_TDUJe z=IZ>*rp)K&=%5itb`4B~ON+7CGV#JVTxUdbiCJ!O7IPVk;(~b}YZkr0R{GD+ zzIA0oE4kV)GQ$)1-WnaHzA=n(X72fDaL$$o*8bD2nZYjIB6qG57fB>5mN`gd^H<4* zIzw93b^(4|?SiR#)8HWNVvhJ&40xNZ=RebUt&^tHNi)s-zZ_QDxrrkyDPL4}_m7Pa zjha;)i(#mlR`CTT60OKdBr~gQCCkX$!xkqhdmZx&jPb!?uD+MGo|XZ<5JL5f#bF*R zI~-`s%8pi>B5;Mb5SHiLgQ#JGq54*>V83Mu_N6q~ourd%?ig#z9*D(x5bS280yAD6 zm3Xm`dQPIK#>I^S$g=UYSOzx6-m!c*iZ3|aul?e~4eXjE+t+OxE*8UZ79Paan%9@k ztoFg7U5(@v|L7{u>!)oRx_KcbV+R7~>rg>7m5$eiv2!_0=U#6u`4yt;66Xv*ds&R~ z^Gjc1)f0gc-x7{UElr47JN-M9&MBf!SXNAo7}Mi$HVu&0B$#Zm$RxBrD=rcTzOH}7 zReEH2wEyP5qQ9VjVC=!MVY~Yli=hvRk}R=!4+Z*Y@zXmot{%_9@ygjfumpp*}~JN{E4@{LAT4_ngWnCFxj*lEdeBAG-| zaky-;c~ zva+vKegj=PU*gQUs*$`l3c14l8B_uIkY&IyCi6z%2oPzT%>Z?wZ4Eui`WNFOu~X!| zP55~GEPUh;Dtp41&{9OM3M;y#By_~w5G8ahW$YY3ik=ZJDn#5mD8h#4Ve%uZ92;d# zC)k&UA)-O{oXw(wx_^Yubg-+)Bv|rejbx4T;AkxUpwWack6}+fU^%^x8*T)fQ+Y?E1L6q6S4H4)!$L|q+31ms+^V? z=Ip7Ko=}MWSF=~vQYAw4nC6gBPG)gGuLMR<#bQ}c;g2-XgbSQ+WD3zKyb|sS4~u8x zL6(K$Q~XT_9VP~fRgmJ2Nb}=p2`^omjiO+LofeG{6`s^r%*CS|7rYkY#d-$i5DF)E^BtE%ui ziM(eP;$MbLw6d%|lKBl(`68V@D0j@9}j^Bli45p_-)y@oZTZhM{P|HWF9A#>A=q2{gAmc zmM3=lk_?TT31N|r-ylOOvQxUoFCr_7k9(0mzQ>Spd7wu6{a@+%eY z*QD0A*mm=KBt_yP37U)}L!|uO5cZ8Wx_mCG1vc7XLJ*$SiwcZgfa7NfUE6xYTyf-?Wh$(3dNS*V#&gn^7tTv@fEpyWGr=sJj@?3>K84uHMG0^6u6^`Zpv9ZD3 z<`-HN%eTOoQ(UBU^Xm7AoSvxqyJZ$<$Ez}1Z-)&Jg6@UcNzOG6GIQUp`5tF6vF0Do zHf595pK!bWVD`0OLiUfDQHBs`C^yjZp|lnpufDjYa}BBsYd*k9>$btCqkK<*Do>?> zF_)=#c*`zHSS;^Rng^eV_kJ;-WUZ^$u51nRx`xRSN7l|p_bL9K;P2b~J)Rw_{uJzK zp8K*VI9um~Ao*n#ui*Ew>XK}4bs6PTlshTQB5VN)-1ri=Ci_PAboHFXurt25e>b(Cq}>!jY3;P`GmPE=eh#AfManH;={S=+nXQDg7G%Fq zy}x3T$Eqhn{{+W5w#VgJ3}nUcV_i=XyrzyfSjQU-@muKlc(si#e?(V#^MQc^v;pk) zKsW(c@LHJ}M0%~u%0zd(x`_ThNq=ty5fgkmR{fcgH|IWTJ`5^OL~sXo7T{uo=X_Eg z%r91IlX{X9hrfoMm4#RxN%M<)N}M-fiTDCr-=ai(VmxPH$%;D|wY8JnNLrjFml`JS z1?pb{#p}=_H@n#3l_g`CZ}vOjMsIeoPE0f>667JAimf z7DS~Q7vcJO1JFstxd*)4gLO6B3+QJe&SkzEJ-= zMs|%4>@tU3EVcl>Kl?XhLtRqT@+IIOV?$xUsf7+B04^3o`qkdYGz)yK13u@M(D@MqF`s)lD^Y6| zTNF-|O|&^lA7ZfgwE`geGKtXRyR7f^$v_Pqol7E$H=Fg!TQfr{NK?26^F z$=wq$16fL8weD{G8GY4QZ0lPai|u{uVsSy=)>^3B(N~SdbNbe84Bsy7+Zv0D`qpj@ z-*)z`i^X&MdSkJxZ>txXx23<7ef7P}uEqsK;T!Z&`!>YK#XC|uJd9}m*J#6(q)(nf`Kl>321j>3}gBSx(p{> zkuJj|<_L5dPL@Qv3@1w?U51nMBVC4*Wsxoh!!<_3VX?_op$Itf+qS-H{1(XKw+s5# z#%}>KehZuUx0>;c|7HdjPEY$cy_uiElnr zPhP`6N`4vjJVHd}J{q~rqvwM}M!k(&Pz{pQHt1rtXsXek=UQQh=fEYnygmDv_IGe0 z`HxuJ_)0$1$?6T*UR3LXnT=mkmIZ#)$;eZU=~FiLRQ8Y7FOhEw`hJSP=NRUwV0<^m z#=96S!Weo>0My2B2igEg8C?6y9akO9NN>t(w^==I0}vE0_k{t@d^C-JVh8}0d>plT zYZ+_>+0v}bQ~6KmsQ<$5((4$W0mED3Y^M0>LQlrNFMF<$CM+#AdJ7$E@Oh`2UJZKX zkDEj%mfy%Ifa-wtRXX|>ld)KLZC9;OG1^+O0|Hy29V!cdu0E8uz^|9d=MfPpVk_^H z>ZtDF#+z|i$b*kAT9VygPyftB_68W>>FSjw63oWDVS6DJt)OcIE%Y>1^aXSJ#NPqW@CjSf*4BO*>}yqN;R)#)$-yl-uq`~9wpmD%gxq}8@8cKTn-jM zfw+~Dx%M7bu7%kitTm#uKtrBTNt(FLj5KWy@5=6y8s3*-+_j@wB|a3FP&CH~6gnvn z%Yy8ql0}p-V#tgT!2kA7njfFOjldsnT>7g;G7R%aip zCrYpIboKLbDoP$QeK7kFbCCN-ZQWqxzL4B>8<4qRA6}_K3b>b;8F!ccW@!6yhZvH8*w@35xbJ?RH z0Y2a(NiD`)i> z|2b!Y08L#yR8amE%wcu*=k;WTDJSe1vFLWjsi6z8O4M&e#X<=WzpI<;ss9Cge!ava zH=vhID6Eb)NAAsVf0yBko`ztdgw0*|ufnqUHFMy~#3O zGsDG}@oigbTYEQ%N!D9_g~%kXqZsEX>jySd$}}v;!r{gyH=W|L^!Kh1Wg~vV;9AJP z`tcKhkCP3Rspj_S=HinJrxE8}G&|ySy4^jyvcq+Jd$kWGk1N+&-bEcOzIt*yzkCG*5YW;=U_LCx=<#f>`vn{5|TlRn|XpkC6^n0ZTB$BGUS<) z4X7fnQ#iJikXk}FpiFdb%3E=8kM&&v4j>5qQANC-_vc;HUxY&gue~Z$N((r=T+I7V z`+6I_*Q|SsTVRojSYYG|C81zodLxu{GY&E4gZg<9$k6%q-|NaCtLdA~vi}P{rwQVC z4%mWW`LXd!i7M$80IY#hnOYMda=fyVHVeH+WgX_hB17YU>2ChMBFl!?+54i3+ zvUmAZug3Dk_HSd#y+HjCEHRC1AYsnf|MGR+sr;Ax+-`oKr*Q?IfRo;1NyztQ|1JYi zmQ5}II~aXf4m&dxpGE2gQ(R%L&+cP!`AYU(P{*ExgCNjq+mkkLTxSun z-A5(%&dlCUFa;OY4mU1vMz>xIOURe;c(;1NNfq{_1D6VR|Av68}?<-Ncyhe17`u%*X7uRs<#KM zJV-zCHqvFMv7puh8BMzQt>-J?y;p*;NFfR-{4Z)vpVHHC88UOMU{QJ$m|%QKgU~M* zrnGsmlv4ct_u(S`3hMS0JGHOi%x=T3x{#_%fOshDlvGSqQygx3Q%DzR6hu-U=TiZ@ zus0jWqQaQ(rRmqh2Ou~^-&+Ii+pv$G#>3kveS3rXDBI|$VhoCZQ2olys<+k2ui#EP z#YgPRo{uBpWYkDspb>jfHQHOf8`0pRpI~b@#ZZzD_ga6Pu7AScGXc}=_ZrCx6CH^J zXgffc2QA;sQ)m{Q#rvY8yfO!}f8e*TYm@;RraGMYsx_WM*+lNr@M<;fRUWkp?&A>i z34qA-2(kKj#-VUu%>DJYPce!%D#!Q}4@*f2DWZm;0cIU~9OF-i9nbUABcbZyM%7u* zH-S3UlCMig0at^*=NjiQDQx-AH12qo&-ncG&C}K8e1PTP9V7EbT75p~yMHr6=t$ua z)({AzO2*(d|kLM^6zx1iOK3)Bs^=mRP34ahHaX^p1EPwqY`>@!@ zmI1px>t>#cAJgnhQ*xiD&YCjXJg2p8550nqJF^SSb@^ppj;B9w8kNkUO!-T;XDb4@ zpAF#du%$rDfuccI*w8}QZ}7Jcl#9RQk64K-L2vDQ2y`B+KEu5345;jpEHEpYFg^FMkxG7>Tn6a3edtSt285)y-OSti`06O`r5IHM#zO0eHBx5dZ)H literal 0 HcmV?d00001 diff --git a/Mix Power C v1/PCLIB2.PRJ b/Mix Power C v1/PCLIB2.PRJ new file mode 100644 index 0000000..b781b15 --- /dev/null +++ b/Mix Power C v1/PCLIB2.PRJ @@ -0,0 +1,14 @@ +graphics + +screen.mix screen.asm fillm.asm + pca screen + +stdlib2 std_lib.h fstat.c dup.c dstring.c time.c bessel.c arith.c \ + tempfile.c chain.c flags.c locking.c perror.c allocmem.c \ + findfirs.c dosetc.c etc.c + +lib2.mix lib2.asm libdef.asm farmem.asm sound.asm absdisk.asm \ + biosfn.asm disable.asm intent.asm signal.asm exec.asm dtafat.asm \ + intrpt.asm intr.asm peek.asm + pca lib2 + diff --git a/Mix Power C v1/PCO.EXE b/Mix Power C v1/PCO.EXE new file mode 100644 index 0000000000000000000000000000000000000000..a5f2f98863abb3ea255af9cacad03c808ec0b18f GIT binary patch literal 122688 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 N5qXEq&HcYm`wu3rxx)Ye literal 0 HcmV?d00001 diff --git a/Mix Power C v1/PEEK.ASM b/Mix Power C v1/PEEK.ASM new file mode 100644 index 0000000..6d4781c --- /dev/null +++ b/Mix Power C v1/PEEK.ASM @@ -0,0 +1,75 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; peek(segment, offset) - read a word from memory +; unsigned segment; +; unsigned offset; +; ------------------------------------------------------- +; + IDT peek + DEF peek +; +peek MOV BX,SP + MOV ES,[BX][%PARM1-2] + MOV SI,[BX][%PARM2-2] + SEGES + MOV AX,[SI] + RETSEG + END +; +; ------------------------------------------------------- +; peekb(segment, offset) - read a byte from memory +; unsigned segment; +; unsigned offset; +; ------------------------------------------------------- +; + IDT peekb + DEF peekb +; +peekb MOV BX,SP + MOV ES,[BX][%PARM1-2] + MOV SI,[BX][%PARM2-2] + SEGES + MOV AL,[SI] + XOR AH,AH + RETSEG + END +; +; ------------------------------------------------------- +; poke(segment, offset, value) - store a word +; unsigned segment; +; unsigned offset; +; int value; +; ------------------------------------------------------- +; + IDT poke + DEF poke +; +poke MOV BX,SP + MOV ES,[BX][%PARM1-2] + MOV SI,[BX][%PARM2-2] + MOV AX,[BX][%PARM3-2] + SEGES + MOV [SI],AX + RETSEG + END +; +; ------------------------------------------------------- +; pokeb(segment, offset, value) - store a byte +; unsigned segment; +; unsigned offset; +; int value; +; ------------------------------------------------------- +; + IDT pokeb + DEF pokeb +; +pokeb MOV BX,SP + MOV ES,[BX][%PARM1-2] + MOV SI,[BX][%PARM2-2] + MOV AL,[BX][%PARM3-2] + SEGES + MOV [SI],AL + RETSEG + END diff --git a/Mix Power C v1/PERROR.C b/Mix Power C v1/PERROR.C new file mode 100644 index 0000000..c809ae5 --- /dev/null +++ b/Mix Power C v1/PERROR.C @@ -0,0 +1,95 @@ +/* Error message functions */ +/* Copyright (c) Mix Software 1988 */ + +dosexterr(struct DOSERROR *buffer) +{ + union REGS reg; + int intdos(); + reg.x.ax = 0x5900; + reg.x.bx = 0; + intdos(®,®); + if (buffer == NULL) return reg.x.ax; + buffer->exterror = reg.x.ax; + buffer->class = reg.h.bh; + buffer->action = reg.h.bl; + buffer->locus = reg.h.ch; + return buffer->exterror; + } + +perror(s) +char *s; +{ + fputs(s, stderr); fputc(':', stderr); + fputs(strerror(NULL),stderr); +} + +#define ERRmaxln 32 +char *strerror(string) + char *string; +{ + extern int errno; + extern int sys_nerr; + extern char *sys_errlist[]; + extern char *int_errlist[]; + static char unknown[] = "Error cause unknown\n"; + static char *buffer = NULL; + char *msg; + if (errno <= sys_nerr) msg = sys_errlist[errno]; + else { + if (errno > 0x80 && errno < 0x97) + msg = int_errlist[errno-0x81]; + else msg = unknown; + } + if (string == NULL) return msg; + if (buffer == NULL) buffer = malloc(94+4+ERRmaxln); + if (buffer == NULL) return NULL; + strncpy(buffer,string,94); + strcat(buffer,": "); + strcat(buffer,msg); + return buffer; +} + +int sys_nerr = 17; +char *sys_errlist[] = {"No Errors\n", + "Invalid Function Number\n", + "File not Found\n", + "Path not Found\n", + "No More File Handles\n", + "File Access Denied\n", + "Invalid File Handle\n", + "Memory Blocks Destroyed\n", + "Insufficient Memory\n", + "Invalid Block Address\n", + "Invalid Environment\n", + "Invalid Format\n", + "Invalid Access Code\n", + "Invalid Data\n", + "Invalid Drive\n", + "Can't Remove Current Directory\n", + "Not Same Device\n", + "No More Files\n" }; + +char *int_errlist[] = {"Out of Stack\n", + "Out of Heap\n", + "Damaged Stack or Heap\n", + "Damaged Stack or Heap\n", + "Divide by Zero\n", + "Invalid Instruction\n", + "Damaged Stack or Heap\n", + "Damaged Stack or Heap\n", + "I/O Error\n", + "Error Cause Unknown\n", + "Attempt to Write Input\n", + "File Not Open\n", + "Attempt to Read Output\n", + "No Memory for File Buffer\n", + "Error Cause Unknown\n", + "Damaged Stack or Heap\n", + "Bad Digit in Number\n", + "Damaged Stack or Heap\n", + "Arithmetic Overflow\n", + "Error Cause Unknown\n", + "Arithmetic Underflow\n", + "Log of Negative Number\n", + "Sqrt of Negative Number\n" }; + diff --git a/Mix Power C v1/PRINTF.C b/Mix Power C v1/PRINTF.C new file mode 100644 index 0000000..091f9f2 --- /dev/null +++ b/Mix Power C v1/PRINTF.C @@ -0,0 +1,589 @@ +/* printf */ +/* Copyright (c) Mix Software 1988 */ + +#include "stdio.h" +#include "stdarg.h" +#include "dos.h" + +static signflag; /* signed value flag */ +static plusflag; /* include + sign for positive values */ +static blankflag; /* include blank for positive values */ +static poundflag; /* numeric format flag */ +static upperflag; /* upper case flag for X, E & G formats */ +static precision; /* precision of numbers */ +static farflag; /* far pointer flag used by _eint */ +static farhalf; /* half of a far pointer */ +static va_list parms; /* pointer to parameters */ + +printf(fs) /* standard routine */ +char *fs; +{ + int fputc(); + int _write(); + int count; + va_start(parms, fs); + count = _output(stdout, fs, fputc, _write); + return ferror(stdout) ? -1 : count; +} + +fprintf(fp, fs) /* standard routine */ +FILE *fp; +char *fs; +{ + int fputc(); + int _write(); + int count; + va_start(parms, fs); + count = _output(fp, fs, fputc, _write); + return ferror(fp) ? -1 : count; +} + +sprintf(s,fs) +char *s; +char *fs; +{ + int _mputc(); + int _mwrite(); + int count; + va_start(parms,fs); + count = _output(&s, fs, _mputc, _mwrite); + *s = '\0'; + return count; +} + +cprintf(fs) +char *fs; +{ + int putch(); + int _cwrite(); + va_start(parms, fs); + return _output(0, fs, putch, _cwrite); +} + +vprintf(fs, argptr) /* standard routine */ +char *fs; +char *argptr; +{ + int fputc(); + int _write(); + int count; + parms = argptr; + count = _output(stdout, fs, fputc, _write); + return ferror(stdout) ? -1 : count; +} + +vfprintf(fp, fs, argptr) /* standard routine */ +FILE *fp; +char *fs; +char *argptr; +{ + int fputc(); + int _write(); + int count; + parms = argptr; + count = _output(fp, fs, fputc, _write); + return ferror(fp) ? -1 : count; +} + +vsprintf(s, fs, argptr) /* standard routine */ +char *s; +char *fs; +char *argptr; +{ + int _mputc(); + int _mwrite(); + int count; + parms = argptr; + count = _output(&s, fs, _mputc, _mwrite); + *s = '\0'; + return count; +} + +_output(fp, format, putc, write) /* output routine for */ + /* printf, sprintf, fprintf */ +char *fp; /* pointer to destination */ +char *format; /* pointer to format string */ +int (*putc)(); /* pointer to output function */ +int (*write)(); /* pointer to output function */ +{ + char *bufptr; /* pointer into buffer */ + char far *fbufptr; /* far pointer into buffer */ + char c; /* current character */ + char padchar; /* pad character */ + int count=0; /* count of characters output */ + int ljflag; /* left justify flag */ + int longflag; /* long ("l") present in format */ + int Nflag; /* near pointer flag */ + int Fflag; /* far pointer flag */ + int length; /* length of output string */ + int len; /* length of output string */ + int flag; /* ftoa edit flag */ + int left; /* number digits left of decimal */ + int right; /* number digits right of decimal */ + int width; /* mimimum field width */ + char buffer[255]; /* encode buffer */ + char null[]="(null)"; /* print this for %s with NULL pointer */ + STRING *dynamic; /* dynamic string pointer */ + int (*enc)(); /* pointer to encode function */ + int _eint(); /* encode integer function */ + int _elong(); /* encode long function */ + int _atoi(); /* convert string to integer */ + int _ftoaflag(); /* get format flag for ftoa function */ + int strlen(); /* determine length of string */ + + while (c = *format) { + if (c != '%') { + (*putc)(c,fp); + count++; + format++; + continue; + } + precision = -1; + bufptr = buffer; + ljflag = signflag = blankflag = poundflag = longflag + = upperflag = plusflag = Nflag = Fflag = 0; + flags: switch (*(++format)) { + case '-': ++ljflag; goto flags; + case '+': ++plusflag; goto flags; + case ' ': ++blankflag; goto flags; + case '#': ++poundflag; goto flags; + } + padchar = (*format == '0') ? '0' : ' '; + if (*format == '*') { + ++format; + if ((width = va_arg(parms, int)) < 0) { + width = -width; + ++ljflag; + } + } + else width = _atoi(&format); + if ((*format) == '.') { + ++format; + if (*format == '*') { + ++format; + precision = va_arg(parms, int); + } + else precision = _atoi(&format); + } + enc = _eint; + if (((c = *format++) == 'l') || c == 'L') { + c = *format++; + enc = _elong; + longflag++; + } + else if (c == 'h') c = *format++; + else if (c == 'N') { + Nflag++; + c = *format++; + } + else if (c == 'F') { + Fflag++; + c = *format++; + } + + switch(c) { + + case 'i': /* signed decimal */ + case 'd': + signflag++; + (*enc)(buffer, 10); + length = strlen(bufptr); + break; + + case 'u': /* unsigned decimal */ + (*enc)(buffer, 10); + length = strlen(bufptr); + break; + + case 'o': /* unsigned octal */ + (*enc)(buffer, 8); + length = strlen(bufptr); + break; + + case 'X': upperflag++; /* unsigned hexadecimal */ + case 'x': + (*enc)(buffer, 16); + length = strlen(bufptr); + break; + + case 'p': /* pointer */ + precision = 4; + upperflag++; + poundflag = 0; + #ifdef LARGE + if (Nflag) { + _eint(buffer, 16); + length = 4; + } + else { + farflag++; + bufptr = va_arg(parms, char*); + farhalf = FP_SEG(bufptr); + _eint(buffer, 16); + buffer[4] = ':'; + farhalf = FP_OFF(bufptr); + _eint(buffer + 5, 16); + length = 9; + farflag = 0; + } + #else + if (Fflag) { + farflag++; + fbufptr = va_arg(parms, char far*); + farhalf = FP_SEG(fbufptr); + _eint(buffer, 16); + buffer[4] = ':'; + farhalf = FP_OFF(fbufptr); + _eint(buffer + 5, 16); + length = 9; + farflag = 0; + } + else { + _eint(buffer, 16); + length = 4; + } + #endif + break; + + case 's': /* string */ + #ifdef LARGE + if (Nflag) bufptr = va_arg(parms, char near*); + else bufptr = va_arg(parms, char*); + if (bufptr == NULL) { + bufptr = null; + length = 6; + break; + } + length = strlen(bufptr); + if (precision >= 0 && length > precision) + length = precision; + break; + #else + if (Fflag) { + fbufptr = va_arg(parms, char far*); + if (fbufptr == NULL) { + bufptr = null; + length = 6; + break; + } + length = _fstrlen(fbufptr); + if (precision >= 0 && length > precision) + length = precision; + width = width - length; + if (!ljflag) { + c = *fbufptr; + if (padchar == '0' && (c == '-' || c == '+')) { + --length; + (*putc)(c, fp); + fbufptr++; + count++; + } + while (width-- > 0) (*putc)(padchar, fp); + } + while (length > 0) { + len = length < 256 ? length : 255; + _fmemcpy((char far*) buffer, fbufptr, len); + (*write)(fp, buffer, len); + count += len; + fbufptr += len; + length -= len; + } + while (width-- > 0) { + (*putc)(padchar,fp); + count++; + } + continue; + } + else { + bufptr = va_arg(parms, char*); + if (bufptr == NULL) { + bufptr = null; + length = 6; + break; + } + length = strlen(bufptr); + if (precision >= 0 && length > precision) + length = precision; + break; + } + #endif + + case 'c': /* character */ + buffer[0] = va_arg(parms, int); + buffer[1] = '\0'; + length = 1; + break; + + case 'E': upperflag++; /* exponential */ + case 'e': + flag = 1; + goto reals; + + case 'G': upperflag++; /* no trailing 0's */ + case 'g': + /* fixed or exponential? */ + if (precision < 0) precision = 6; + flag = _ftoaflag(parms, poundflag, precision); + goto reals; + + case 'f': /* fixed point */ + flag = 0; + + reals: + if (plusflag) flag |= 8; + else if (blankflag) flag |= 136; + if (precision < 0) right = 6; + else right = precision; + left = 1; + ftoa(va_arg(parms, double), bufptr, flag, left, right); + length = 0; + while (c=buffer[length]) { + if (poundflag == 0) { + if (c == '.' && precision == 0) { + strcpy(&buffer[length], &buffer[length+1]); + continue; + } + } + if (c == 'e' && upperflag) buffer[length] = 'E'; + else if (c == 'E' && !upperflag) buffer[length] = 'e'; + ++length; + } + break; + + case 'n': + *(va_arg(parms, int*)) = count; + continue; + + case 'y': /* dynamic string */ + dynamic = va_arg(parms, STRING*); + length = dynamic->length; + bufptr = dynamic->string; + break; + + default : /* format string character */ + (*putc)(c, fp); + count++; + continue; + } + width = width - length; + if (!ljflag) { + if (padchar == '0' && (*bufptr == '-' || *bufptr == '+')) { + --length; + (*putc)(*bufptr++, fp); + count++; + } + while (width-- > 0) { + (*putc)(padchar, fp); + count++; + } + } + (*write)(fp,bufptr,length); + count += length; + while (width-- > 0) { + (*putc)(padchar,fp); + count++; + } + } + return count; +} + +_eint(bufptr, base) /* encode an integer */ +char *bufptr; /* pointer to encode buffer */ +int base; /* number base */ +{ + char buffer[7]; + char *ptr = buffer; + int i; + if (farflag) i = farhalf; + else i = va_arg(parms, int); + if (precision == 0 && i == 0) *bufptr = '\0'; + else { + if (base == 10) { + if (signflag) { + if (i < 0) { + *bufptr++ = '-'; + i = -i; + } + else if (plusflag) *bufptr++ = '+'; + else if (blankflag) *bufptr++ = ' '; + } + _dtoa(i, &ptr); + } + else if (base == 16) { + if (poundflag && i) { + *bufptr++ = '0'; + *bufptr++ = upperflag ? 'X' : 'x'; + } + _htoa(i, &ptr); + } + else { + if (poundflag && i) { + *bufptr++ = '0'; + } + _otoa(i, &ptr); + } + *ptr = '\0'; + for (i=precision-strlen(buffer); i > 0; i--) *bufptr++ = '0'; + strcpy(bufptr, buffer); + } +} + +_dtoa(n, bufptr) /* decimal integer encode routine */ +unsigned n; /* unsigned integer */ +char **bufptr; /* pointer to the buffer pointer */ +{ + if (n < 10) *(*bufptr)++ = n + 48; + else { + _dtoa(n/10, bufptr); + _dtoa(n%10, bufptr); + } +} + +_htoa(n, bufptr) /* hexadecimal integer encode routine */ +unsigned n; /* unsigned integer */ +char **bufptr; /* pointer to the buffer pointer */ +{ + if (n < 16) { + if (n < 10) *(*bufptr)++ = n + 48; + else *(*bufptr)++ = upperflag ? n + 55 : n + 87; + } + else { + _htoa(n/16, bufptr); + _htoa(n%16, bufptr); + } +} + +_otoa(n, bufptr) /* octal integer encode routine */ +unsigned n; /* unsigned integer */ +char **bufptr; /* pointer to the buffer pointer */ +{ + if (n < 8) *(*bufptr)++ = n + 48; + else { + _otoa(n/8, bufptr); + _otoa(n%8, bufptr); + } +} + +_elong(bufptr, base) /* encode a long */ +char *bufptr; /* pointer to encode buffer */ +int base; /* number base */ +{ + char buffer[12]; + char *ptr = buffer; + int i; + long l; + l = va_arg(parms, long); + if (precision == 0 && l == 0) *bufptr = '\0'; + else { + if (base == 10) { + if (signflag) { + if (l < 0) { + *bufptr++ = '-'; + l = -l; + } + else if (plusflag) *bufptr++ = '+'; + else if (blankflag) *bufptr++ = ' '; + } + _ldtoa(l, &ptr); + } + else if (base == 16) { + if (poundflag && l) { + *bufptr++ = '0'; + *bufptr++ = upperflag ? 'X' : 'x'; + } + _lhtoa(l, &ptr); + } + else { + if (poundflag && l) { + *bufptr++ = '0'; + } + _lotoa(l, &ptr); + } + *ptr = '\0'; + for (i = precision - strlen(buffer); i > 0; i--) *bufptr++ = '0'; + strcpy(bufptr, buffer); + } +} + +_ldtoa(l, bufptr) /* long decimal encode routine */ +unsigned long l; /* long integer */ +char **bufptr; /* pointer to the buffer pointer */ +{ + if (l < 10) *(*bufptr)++ = l + 48; + else { + _ldtoa(l/10, bufptr); + _ldtoa(l%10, bufptr); + } +} + +_lhtoa(l, bufptr) /* long hexadecimal encode routine */ +long l; /* long integer */ +char **bufptr; /* pointer to the buffer pointer */ +{ + int i, start; + int digit[9]; + digit[8] = 1; + for (i = 7; i >= 0; i--) { + digit[i] = l & 0xf; + l = l >> 4; + } + start = 0; + while (digit[start] == 0) start++; + if (start == 8) *(*bufptr)++ = '0'; + else { + for (i = start; i < 8; i++) { + if (digit[i] < 10) *(*bufptr)++ = digit[i] + 48; + else *(*bufptr)++ = upperflag ? digit[i] + 55 : digit[i] + 87; + } + } +} + +_lotoa(l, bufptr) /* long octal encode routine */ +long l; /* long integer */ +char **bufptr; /* pointer to the buffer pointer */ +{ + int i, start; + int digit[12]; + digit[11] = 1; + for (i = 10; i > 0; i--) { + digit[i] = l & 7; + l = l >> 3; + } + digit[0] = l & 3; + start = 0; + while (digit[start] == 0) start++; + if (start == 11) *(*bufptr)++ = '0'; + else { + for (i = start; i < 11; i++) + *(*bufptr)++ = digit[i] + 48; + } +} + +_mputc(c, fp) /* write c to fp */ +int c; +char **fp; +{ + *(*fp)++ = c; + return c; +} + +_mwrite(fp, s, n) +char **fp; +char *s; +int n; +{ + int i; + for (i=0; i < n; i++) *(*fp)++ = *s++; + return n; +} + +_cwrite(fp, s, n) +int fp; +char *s; +int n; +{ + int i; + for (i=0; i < n; i++) putch(*s++); + return n; +} + diff --git a/Mix Power C v1/PROCESS.H b/Mix Power C v1/PROCESS.H new file mode 100644 index 0000000..d4b90cf --- /dev/null +++ b/Mix Power C v1/PROCESS.H @@ -0,0 +1,32 @@ +/*$no list*//*$no trace <<< process.h >>> */ +/* Copyright (c) Mix Software 1988 */ + +extern int _p_overlay; + +#define P_WAIT 0 +#define P_NOWAIT 1 +#define P_OVERLAY _p_overlay + +void abort(void); +int execl(char *filename, char *arg0, ...); +int execle(char *filename, char *arg0, ...); +int execlp(char *filename, char *arg0, ...); +int execlpe(char *filename, char *arg0, ...); +int execv(char *filename, char *argv[]); +int execve(char *filename, char *argv[], char *envp[]); +int execvp(char *filename, char *argv[]); +int execvpe(char *filename, char *argv[], char *envp[]); +void exit(int status); +void _exit(int status); +int getpid(void); +int spawnl(int mode, char *filename, char *arg0, ...); +int spawnle(int mode, char *filename, char *arg0, ...); +int spawnlp(int mode, char *filename, char *arg0, ...); +int spawnlpe(int mode, char *filename, char *arg0, ...); +int spawnv(int mode, char *filename, char *argv[]); +int spawnve(int mode, char *filename, char *argv[], char *envp[]); +int spawnvp(int mode, char *filename, char *argv[]); +int spawnvpe(int mode, char *filename, char *argv[], char *envp[]); +int system(char *cmdstring); + +/*$list*//*$trace <<< process.h >>> */ diff --git a/Mix Power C v1/PUT.ASM b/Mix Power C v1/PUT.ASM new file mode 100644 index 0000000..c1d4ab8 --- /dev/null +++ b/Mix Power C v1/PUT.ASM @@ -0,0 +1,222 @@ +; +; Copyright (c) Mix Software 1988 +; +; fputc(c,fp) +; int c; +; FILE *fp; +; + IDT fputc + DEF fputc + FREF _rflush + FREF _putc +fputc MOV BX,SP + MOV SI,[BX][%PARM2-2] + TEST SI,SI + JZ ENDFL +; +; if (fp == NULL || !fp->file.init || !fp->file.openflg) return EOF; +; +; TEST SI,SI ; File ok? +; JZ ENDFL +; CMP %[SI][%FD$INIT],%0 +; JZ ENDFL +; CMP %[SI][%FD$OPEN],%0 +; JZ ENDFL +; +; if (fp->file.dirty & fdread) { +; if (_rflush(fp) != 0) return EOF; +; + TEST %[SI][%FD$DIRTY],%FL$READ + JNZ FLUSH +; +; if (c != NEWLINE) { +; +NOFLUSH MOV AX,[BX][%PARM1-2] + CMP AL,>0A + JZ NEWLINE +; +; if (fp->file.count--) return (*(fp->file.ptr++) = c); +; + MOV CX,[SI][%FD$COUNT] + JCXZ BUFFULL + DEC CX + MOV [SI][%FD$COUNT],CX + MOV DI,[SI][%FD$PTR] + MOV %[DI],AL + INC DI + MOV [SI][%FD$PTR],DI + RETSEG +; +; else { +; fp->file.count++; +; return _putc(c,fp); } } +; +BUFFULL PUSH SI + PUSH AX + CALLFAR _putc + ADD SP,%4 + RETSEG +; +; if ( (fp->file.flags & fdbinary) || +; ((fp->file.flags & fdfilter) == 0) ) return _putc(c,fp); +; +NEWLINE TEST [SI][%FD$FLAGS],%FL$LFEED + JZ NOCR +; +; if (_putc('\r',fp) == EOF) return EOF; +; + PUSH SI + MOV AX,>000D + PUSH AX + CALLFAR _putc + POP DX + POP SI + INC AX + JNZ PUTLF + DEC AX + RETSEG +PUTLF MOV AX,>000A +NOCR PUSH SI + PUSH AX +; +; return _putc(c,fp); +; + CALLFAR _putc + ADD SP,%4 + RETSEG +; +FLUSH PUSH SI + CALLFAR _rflush + POP SI + MOV BX,SP + TEST AX,AX + JZ NOFLUSH +; +ENDFL MOV AX,-1 + RETSEG + END +; +; +; _putc(c,fp) +; int c; +; FILE *fp; +; +; Lowest level file output (one character) +; file validity has already been checked +; + IDT _putc + DEF _putc + FREF _fflush + FREF _seekend + REF _fileerr +DISKFULL EQU >009A +; +_putc PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM2] +; +; if (fp->file.device == 'o') { +; _sys_adx(0x0200,c); +; return c; } +; + CMP %[SI][%FD$DEV],'o' + JNZ NOTSTD + MOV DX,[BP][%PARM1] + MOV AX,>0200 + INT >21 + MOV AX,[BP][%PARM1] + POP BP + RETSEG +; +; if (fp->file.count--) return (*(fp->file.ptr++) = c); +; +NOTSTD MOV AX,[BP][%PARM1] + MOV CX,[SI][%FD$COUNT] + JCXZ BUFFULL + DEC CX + MOV [SI][%FD$COUNT],CX + MOV DI,[SI][%FD$PTR] + MOV %[DI],AL + INC DI + MOV [SI][%FD$PTR],DI +EXIT POP BP + RETSEG +; +; fp->file.count = 0; +; +BUFFULL MOV [SI][%FD$COUNT],0 +; +; if (fp->file.device == 'd') return c; +; + CMP [SI][%FD$DEV],'d' + JZ EXIT +; +; if (fp->file.dirty & fdwrite) { +; if (_fflush(fp) != 0) return EOF; } +; + TEST %[SI][%FD$DIRTY],%FL$WRITE + JZ NOFLUSH + PUSH SI + CALLFAR _fflush + POP SI + TEST AX,AX + JNZ ENDFL +; +; if (fp->file.flags & fdunbufr) { +; if (_sysabcd(0x4000,fp->file.handle,1,&c,&status) != 0) { +; (*_fileerr)(status,fp); +; return EOF; } +; +NOFLUSH TEST %[SI][%FD$FLAGS],%FL$UNBUF + JZ USEBUFR +; Seek to end of file if append mode + TEST [SI][%FD$FLAGS],FL$APPEN + JNZ PUTACHAR + PUSH SI + CALLFAR _seekend + POP SI +PUTACHAR LEA DX,[BP][%PARM1] + MOV BX,[SI][%FD$HNDL] + MOV CX,1 + MOV AX,>4000 + INT >21 + JNB OK1 +ERROR PUSH [BP][%PARM2] + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%4 +ENDFL MOV AX,-1 + POP BP + RETSEG +; +; return c; +; +OK1 EQU $ + CMP AX,1 + JZ OK2 + MOV AX,DISKFULL + JMPS ERROR +OK2 MOV AX,[BP][%PARM1] + POP BP + RETSEG +; +; fp->file.ptr = fp->file.bufr; +; fp->file.count = fp->file.bufsize - 1; +; *fp->file.ptr++ = c; +; fp->file.dirty |= fdwrite; +; return c; +; +USEBUFR MOV BX,[SI][%FD$BUFR] + MOV AX,[SI][%FD$BUFSZ] + DEC AX + MOV [SI][%FD$COUNT],AX + MOV AX,[BP][%PARM1] + MOV %[BX],AL + INC BX + MOV [SI][%FD$PTR],BX + OR %[SI][%FD$DIRTY],%FL$WRITE + POP BP + RETSEG +; + END diff --git a/Mix Power C v1/PUTS.C b/Mix Power C v1/PUTS.C new file mode 100644 index 0000000..18fde88 --- /dev/null +++ b/Mix Power C v1/PUTS.C @@ -0,0 +1,60 @@ + +/* String output to files */ +/* Copyright (c) Mix Software 1988 */ + +/* ------------------------------------------------------------ */ + +char *puts(s) /* write s to stdout */ +char *s; +{ + int _write(); + int strlen(); + int count; + count = strlen(s); + if (_write(stdout, s, count) != count) return EOF; + if (fputc('\n', stdout) != EOF) return s; + else return EOF; +} + +/* ------------------------------------------------------------ */ + +int _printf_(s) /* write s to stdout */ +char *s; +{ + int _write(); + int strlen(); + int count = 0; + if (s == NULL) return 0; + while (*s != '\0') { + if (*s == '%') ++s; + if (fputc(*s,stdout) == EOF) return EOF; + ++count; + ++s; + } + return count; +} + +/* ------------------------------------------------------------ */ + +char *fputs(s, fp) /* write s to fp */ +char *s; +FILE *fp; +{ + int _write(); + int strlen(); + int count; + count = strlen(s); + if (_write(fp, s, count) != count) return EOF; + else return s; +} + +/* ------------------------------------------------------------ */ + +char *cputs(s) /* write s to console */ +char *s; +{ + int putch(); + while (*s) putch(*s++); + return s; +} + diff --git a/Mix Power C v1/RAND.C b/Mix Power C v1/RAND.C new file mode 100644 index 0000000..53c6b7a --- /dev/null +++ b/Mix Power C v1/RAND.C @@ -0,0 +1,51 @@ + +/* Random numbers */ +/* Copyright (c) Mix Software 1988 */ + +/* ------------------------------------------------------------ */ + +double drand(n) + int n; +{ + extern double (far *$0DFIXR)(); + double d; + d = (double) rand() / (double) 0x7FFF; + if (n == 0) return d; + return $0DFIXR(d * n); + } + +/* ------------------------------------------------------------ */ + +rand() +{ + extern long _seed; + _seed = _seed * 15790321; + return (int) ((_seed >> 17) & 0x7FFF); +} + +/* ------------------------------------------------------------ */ + +void srand(seed) + unsigned seed; +{ + extern long _seed; + union REGS r; + union { + long lval; + struct { + unsigned lsword; + unsigned msword; + } words; + } val; + if (seed == 1) _seed = 13849l; + else { + r.x.ax = 0x2c00; + intdos(&r,&r); + val.words.lsword = r.x.dx; + val.words.msword = r.x.cx; + _seed = val.lval; + } +} + +long _seed = 13849; + diff --git a/Mix Power C v1/READ.ASM b/Mix Power C v1/READ.ASM new file mode 100644 index 0000000..48a6a3a --- /dev/null +++ b/Mix Power C v1/READ.ASM @@ -0,0 +1,360 @@ +; +; Copyright (c) Mix Software 1988 +; +; fread(buffer,itemsize,no_of_items,fp) +; char *buffer; +; int itemsize; +; int no_of_items; +; FILE *fp; +; { return (read(fp->fd,buffer,itemsize*no_of_items) / itemsize); } +; + IDT fread + DEF fread + FREF read +fread MOV BX,SP + MOV SI,[BX][%PARM4-2] + MOV AX,[BX][%PARM2-2] + MOV CX,[BX][%PARM3-2] + CMP AX,1 + JZ FREAD1SZ + CMP CX,%1 + JZ FREAD1I + MUL CX + PUSH AX + PUSH [BX][%PARM1-2] + PUSH [SI][FD$SIZE] + CALLFAR read + ADD SP,%6 + MOV BX,SP + MOV CX,[BX][%PARM2-2] + CWD + DIV CX + RETSEG +; +; Item size is 1 +; +FREAD1SZ PUSH CX + PUSH [BX][%PARM1-2] + PUSH [SI][FD$SIZE] + CALLFAR read + ADD SP,%6 + RETSEG +; +; Number of items is 1 +; +FREAD1I PUSH AX + PUSH [BX][%PARM1-2] + PUSH [SI][FD$SIZE] + CALLFAR read + ADD SP,%6 + MOV BX,SP + CMP AX,[BX][%PARM2-2] + JZ ONE + MOV CX,[BX][%PARM2-2] + CWD + DIV CX + RETSEG +ONE MOV AX,1 + RETSEG + END +; +; ------------------------------------------------------------ +; +; read(fd, buffer, n) +; int n; +; int fd; +; char *buffer; +; + IDT read + DEF read + FREF _fflush + FREF _getc + REF _iob + REF _fileerr +read PUSH BP + MOV BP,SP +; +; FILE *fp = _iob[fd]; +; + MOV SI,[BP][%PARM1] + ADD SI,SI + ADD SI,_iob + MOV SI,[SI] +; +; if (fp == NULL || !fp->file.init || !fp->file.openflg) return 0; +; +; TEST SI,SI ; File ok? +; JZ ENDFL +; CMP %[SI][%FD$INIT],%0 +; JZ ENDFL +; CMP %[SI][%FD$OPEN],%0 +; JZ ENDFL +; +; if (fp->file.dirty & fdwrite) { +; if (_fflush(fp) != 0) return 0; +; } +; + TEST %[SI][%FD$DIRTY],%FL$WRITE + JZ NOFLUSH + PUSH SI + CALLFAR _fflush + POP SI + TEST AX,AX + JNZ ENDFL +; +; if (fp->file.flags & fdfilter) { +; if (!(fp->file.flags & fdctlz)) { +; +NOFLUSH MOV AL,[SI][%FD$FLAGS] + TEST AL,%FL$LFEED + JZ NOCR +; +; Read and filter carriage return (but not ctlz) +; +; while (n-- != 0) { +; c = _getc(fp); +; while (c == RETURN) c = _getc(fp); +; if (c==EOF) { +; readcount = readcount-n-1; +; n = 0; +; } +; else *buffer++ = c; +; } +; +; bx = file +; si = file buffer +; di = buffer address +; dx = count remaining +; cx = buffer count +; + MOV BX,SI + MOV DI,[BP][%PARM2] + MOV DX,[BP][%PARM3] ; Requested count + TEST DX,DX + JZ DONE1 + MOV SI,[BX][%FD$PTR] + MOV CX,[BX][%FD$COUNT] + TEST AL,%FL$CTLZ + JNZ CR_CTLZ + JCXZ MORE1 + MOV AX,DS + MOV ES,AX +COPY1 LODSB ; Get a byte +NEXTCH1 CMP AL,>0D + JZ SKIPCR1 + STOSB ; Store in read buffer + DEC DX ; count character read + JZ DONE1A ; read complete +SKIPCR1 LOOP COPY1 +MORE1 MOV [BX][%FD$COUNT],CX ; Use _getc to get more + MOV [BX][%FD$PTR],SI ; into buffer + PUSH DX ; Save context + PUSH DI + PUSH BX ; Pass fp to _getc + CALLFAR _getc + MOV BX,DS + MOV BX,BX + POP BX + POP DI + POP DX + MOV SI,[BX][%FD$PTR] + MOV CX,[BX][%FD$COUNT] + INC CX + CMP AX,-1 + JNZ NEXTCH1 +DONE1 MOV AX,[BP][%PARM3] + SUB AX,DX + POP BP + RETSEG +DONE1A DEC CX +DONE1B MOV [BX][%FD$COUNT],CX + MOV [BX][%FD$PTR],SI + JCXZ DONE1 + MOV %[BX][%FD$DIRTY],%FL$READ + JMPS DONE1 +ENDFL XOR AX,AX + POP BP + RETSEG +; +; No filtering for end of line characters +; +NOCR TEST %[SI][%FD$FLAGS],%FL$CTLZ + JZ BINMODE +; +; while (n-- != 0) { +; c = _getc(fp); +; if ((c==EOF) || (c == 0x1a) { +; readcount = readcount-n-1; +; n = 0; } +; else *buffer++ = c; +; + MOV CX,[BP][%PARM3] + MOV DI,[BP][%PARM2] + JCXZ ENDFL3 +CPYCTLZ PUSH CX + PUSH DI + PUSH SI + CALLFAR _getc + POP SI + POP DI + POP CX + CMP AX,-1 + JZ ENDFL3 + CMP AX,>001A + JZ ENDFL3 + MOV %[DI],AL + INC DI + LOOP CPYCTLZ +ENDFL3 MOV AX,[BP][%PARM3] + SUB AX,CX + POP BP + RETSEG +; +; +CR_CTLZ JCXZ MORE2 +COPY2 LODSB ; Get a byte +NEXTCH2 CMP AL,>0D + JZ SKIPCR2 + CMP AL,>1A + JZ DONE1B + MOV %[DI],AL ; Store in read buffer + INC DI + DEC DX ; count character read + JZ DONE1A ; read complete +SKIPCR2 LOOP COPY2 +MORE2 MOV [BX][%FD$COUNT],CX ; Use _getc to get more + MOV [BX][%FD$PTR],SI ; into buffer + PUSH DX ; Save context + PUSH DI + PUSH BX ; Pass fp to _getc + CALLFAR _getc + POP BX + POP DI + POP DX + MOV SI,[BX][%FD$PTR] + MOV CX,[BX][%FD$COUNT] + INC CX + CMP AX,-1 + JNZ NEXTCH2 + JMPS DONE1 +; +; if (movcount = fp->file.count) { +; if (movcount > n) movcount = n; +; movmem(fp->file.ptr,buffer,movcount); +; buffer += movcount; +; fp->file.ptr += movcount; +; fp->file.count -= movcount; +; n -= movcount; +; } +; +BINMODE TEST [SI][%FD$FLAGS],%FL$UNBUF + JZ BUFR + JMP NOBUFR +BUFR XOR DX,DX ; already read is 0 + MOV DI,[BP][%PARM2] ; buffer pointer +BINMOVE MOV CX,[SI][%FD$COUNT] + JCXZ NOMOVE + MOV AX,[BP][%PARM3] + SUB AX,DX ; Additional needed + CMP CX,AX + JB MOVEALL + MOV CX,AX ; Use only part of buffer +MOVEALL PUSH CX + MOV AX,DS + MOV ES,AX + PUSH SI + MOV SI,[SI][%FD$PTR] + CLD + REP + MOVSB + MOV BX,SI + POP SI + POP CX + SUB [SI][%FD$COUNT],CX + MOV [SI][%FD$PTR],BX +; +; CX contains count of moved characters +; +; if (n) { +; if (_sysabcd(0x3f00,fp->file.handle,n,buffer,&readcount) != 0) { +; (*_fileerr)(readcount,fp); +; return 0; +; } +; else { +; if (readcount==0) fp->file.eofflag = 1; +; return movcount+readcount; +; } +; } +; +NOMOVE ADD DX,CX + MOV CX,[BP][%PARM3] + SUB CX,DX ; Characters left + JCXZ DONE4 + CMP CX,[SI][%FD$BUFSZ] + JA READDIR + MOV BX,[SI][%FD$HNDL] + MOV AX,>3F00 + PUSH DX + MOV DX,[SI][%FD$BUFR] + MOV [SI][%FD$PTR],DX + MOV CX,[SI][%FD$BUFSZ] + INT >21 + JNB READOK1 +FLERROR PUSH SI + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%4 + POP DX + MOV [SI][%FD$COUNT],0 +DONE4 MOV AX,DX + POP BP + RETSEG +READOK1 POP DX + MOV [SI][%FD$COUNT],AX + TEST AX,AX + JZ DONE4 + JMPS BINMOVE +; +READDIR MOV AX,[SI][%FD$BUFR] + MOV [SI][%FD$PTR],AX + MOV [SI][%FD$COUNT],0 + MOV AX,>3F00 + MOV BX,[SI][%FD$HNDL] + MOV CX,[BP][%PARM3] + SUB CX,DX + PUSH DX + MOV DX,DI + INT >21 + JB FLERROR + POP DX + ADD AX,DX + POP BP + RETSEG +; +NOBUFR MOV DI,[BP][%PARM2] + TEST [SI][%FD$FLAGS],FL$BIN + JZ NOBUFR0 + XOR DX,DX + JMPS READDIR +NOBUFR0 MOV CX,[BP][%PARM3] + JCXZ ENDFL5 +UNBUF PUSH CX + PUSH DI + PUSH SI + CALLFAR _getc + POP SI + POP DI + POP CX + CMP AX,-1 + JZ ENDFL5 +; CMP AX,>001A +; JZ ENDFL5 + MOV %[DI],AL + INC DI + LOOP UNBUF +ENDFL5 MOV AX,[BP][%PARM3] + SUB AX,CX + POP BP + RETSEG + END diff --git a/Mix Power C v1/SCANF.C b/Mix Power C v1/SCANF.C new file mode 100644 index 0000000..9368d01 --- /dev/null +++ b/Mix Power C v1/SCANF.C @@ -0,0 +1,555 @@ +/* scanf */ +/* Copyright (c) Mix Software 1988 */ + +#include "stdio.h" +#include "stdarg.h" + +static va_list parms; /* pointer to parameters */ +static int base; /* number base */ +static int ch; /* input character */ + +scanf(fs) /* standard routine */ +char *fs; +{ + int getc(); + int ungetc(); + va_start(parms, fs); + return _input(stdin, fs, getc, ungetc); +} + +fscanf(fp, fs) /* standard routine */ +char *fp, *fs; +{ + int getc(); + int ungetc(); + va_start(parms, fs); + return _input(fp, fs, getc, ungetc); +} + +sscanf(s,fs) /* standard routine */ +char *s, *fs; +{ + int _mread(); + int _mungetc(); + va_start(parms, fs); + return _input(&s, fs, _mread, _mungetc); +} + +cscanf(fs) +char *fs; +{ + static int _getche(); + static int _un_getche(); + va_start(parms, fs); + return _input(stdin, fs, _getche, _un_getche); +} + + +_input(fp, format, read, ungetc) /* input routine for */ + /* scanf, sscanf, fscanf */ +char *fp; /* pointer to input */ +char *format; /* pointer to format string */ +int (*read)(); /* character read function */ +int (*ungetc)(); /* character unget function */ +{ + char c; /* format string character */ + char *bufptr; /* pointer to buffer */ + char far *fptr; /* far pointer to character */ + int value; /* value of current digit */ + int asflag; /* assignment supression flag */ + int sflag; /* sign flag */ + int lflag; /* long flag */ + int iflag; /* flag for %i format */ + int Nflag; /* Near pointer flag */ + int Fflag; /* Far pointer flag */ + int i; /* loop counter */ + int width; /* maximum field width */ + int valid; /* valid real number format */ + int caret; /* flag for %[^ format */ + int count=0; /* character count */ + int number=0; /* number of characters read */ + union { + int i; + long l; + char *ptr; + char near *nptr; + char far *fptr; + struct { + int offset; + int segment; + } half; + } accum; /* accumulator */ + char buffer[256]; /* floating point string buffer */ + int _digit(); /* decode digit function */ + int _atoi(); /* convert string to integer */ + int isspace(); /* isspace function */ + int isdigit(); /* isdigit function */ + char *strchr(); /* search for character in string */ + double atof(); /* atof function */ + STRING *stods(); /* convert string to dynamic string */ + + while (c = *format++) { + if (isspace(c)) { + while (isspace(*format)) format++; + while (isspace(ch = (*read)(fp))) number++; + (*ungetc)(ch, fp); + continue; + } + if (c != '%') { + number++; + if ((ch = (*read)(fp)) == c) continue; + else { + if (ch == EOF) return EOF; + else { + (*ungetc)(ch,fp); + return count; + } + } + } + sflag = asflag = lflag = Nflag = Fflag = iflag = 0; + if ((*format) == '*') { /* check for assignment suppression */ + ++asflag; + ++format; + } + if (isdigit(*format)) width = _atoi(&format); + else width = -1; + if (*format == 'N') { + format++; + Nflag++; + } + else if (*format == 'F') { + format++; + Fflag++; + } + if (*format == 'l' || *format == 'L') { /* check for double precision */ + format++; + lflag++; + } + else if (*format == 'h') format++; + if (width == 0) { + format++; + continue; + } + switch (*format++) { + case 'o': /* unsigned octal */ + base = 8; + goto decode; + + case 'X': + case 'x': /* unsigned hexadecimal */ + base = 16; + goto decode; + + case 'i': /* signed decimal, 0 or 0x prefix OK */ + iflag++; + base = 10; + goto decode; + + case 'd': /* signed decimal */ + case 'u': + base = 10; + decode: + while (isspace(ch=(*read)(fp))) number++; + if (ch == EOF) return EOF; + number++; + width--; + if (width && (ch == '+' || ch == '-')) { + if (ch == '-') ++sflag; + if ((ch = (*read)(fp)) == EOF) return EOF; + number++; + width--; + } + if (iflag) { + if ((ch == '0') && width) { + base = 8; + if ((ch = (*read)(fp)) == 'x' || ch == 'X') { + number++; + width--; + base = 16; + if (width) { + ch = (*read)(fp); + number++; + width--; + } + if (ch == EOF) return EOF; + } + else { + (*ungetc)(ch, fp); + ch = '0'; + } + } + } + accum.l = _digit(); + if (accum.i == -1) { + (*ungetc)(ch,fp); + return count; + } + while (width) { + ch = (*read)(fp); + if ((value = _digit()) == -1) { + (*ungetc)(ch, fp); + break; + } + width--; + number++; + if (lflag) + accum.l = accum.l * base + value; + else + accum.i = accum.i * base + value; + } + if (!asflag) { + if (lflag) { + if (sflag) accum.l = -accum.l; + #ifdef LARGE + if (Nflag) *(va_arg(parms, long near*)) = accum.l; + #else + if (Fflag) *(va_arg(parms, long far*)) = accum.l; + #endif + else *(va_arg(parms, long*)) = accum.l; + } + else { + if (sflag) accum.i = -accum.i; + #ifdef LARGE + if (Nflag) *(va_arg(parms, int near*)) = accum.i; + #else + if (Fflag) *(va_arg(parms, int far*)) = accum.i; + #endif + else *(va_arg(parms, int*)) = accum.i; + } + count++; + } + break; + + case 's': /* string */ + while (isspace(ch=(*read)(fp))) number++; + if (ch == EOF) return EOF; + if (!asflag) { + #ifdef LARGE + if (Nflag) fptr = va_arg(parms, char near*); + #else + if (Fflag) fptr = va_arg(parms, char far*); + #endif + else fptr = va_arg(parms, char*); + } + while (!isspace(ch) && ch != EOF && width) { + if (!asflag) *fptr++ = ch; + ch = (*read)(fp); + number++; + width--; + } + (*ungetc)(ch,fp); + if (!asflag) { + *fptr = '\0'; + ++count; + } + break; + + case '[': /* string delimited by [character set] */ + if (!asflag) { + #ifdef LARGE + if (Nflag) fptr = va_arg(parms, char near*); + #else + if (Fflag) fptr = va_arg(parms, char far*); + #endif + else fptr = va_arg(parms, char*); + } + i = caret = 0; + if (*format == '^') { + caret++; + format++; + } + if (*format == ']' || *format == '-') + buffer[i++] = *format++; + while (i < 255 && *format != ']') { + if (*format == '-') { + format++; + c = buffer[i-1]; + if (*format != ']' && *format > c) { + for (c++; i < 255 && c <= *format; c++) + buffer[i++] = c; + format++; + } + else buffer[i++] = '-'; + } + else buffer[i++] = *format++; + } + format++; + buffer[i] = '\0'; + i = number; + while (((caret && strchr(buffer, ch=(*read)(fp))==NULL) || + (!caret && strchr(buffer, ch=(*read)(fp))!=NULL)) && + ch != EOF && width) { + if (!asflag) *fptr++ = ch; + number++; + width--; + } + (*ungetc)(ch,fp); + if (number == i) return count; + if (!asflag) { + *fptr = '\0'; + ++count; + } + break; + + case 'c': /* character */ + if ((ch = (*read)(fp)) == EOF) return EOF; + number++; + if (!asflag) { + #ifdef LARGE + if (Nflag) fptr = va_arg(parms, char near*); + #else + if (Fflag) fptr = va_arg(parms, char far*); + #endif + else fptr = va_arg(parms, char*); + *fptr = ch; + ++count; + } + if (width > 0) { + width--; + while (width > 0) { + if ((ch = (*read)(fp)) == EOF) return EOF; + number++; + width--; + if (!asflag) *(++fptr) = ch; + } + } + break; + + case 'n': + if (lflag) { + #ifdef LARGE + if (Nflag) *(va_arg(parms, int near*)) = number; + #else + if (Fflag) *(va_arg(parms, int far*)) = number; + #endif + else *(va_arg(parms, int*)) = number; + } + else { + #ifdef LARGE + if (Nflag) *(va_arg(parms, long near*)) = number; + #else + if (Fflag) *(va_arg(parms, long far*)) = number; + #endif + else *(va_arg(parms, long*)) = number; + } + break; + + case 'p': + while (isspace(ch=(*read)(fp))) number++; + if (ch == EOF) return EOF; + number++; + width--; + base = 16; + accum.half.segment = 0; + accum.i = _digit(); + if (accum.i == -1) { + (*ungetc)(ch,fp); + return count; + } + while (width) { + ch = (*read)(fp); + if ((value = _digit()) == -1) { + (*ungetc)(ch, fp); + break; + } + width--; + number++; + accum.l = (accum.l << 4) + value; + } + #ifdef LARGE + if (!Nflag && ch == ':') { + #else + if (Fflag && ch == ':') { + #endif + (*read)(fp); /* consume the ':' */ + accum.half.segment = accum.half.offset; + accum.half.offset = 0; + while (width) { + ch = (*read)(fp); + if ((value = _digit()) == -1) { + (*ungetc)(ch, fp); + break; + } + width--; + number++; + accum.half.offset=(accum.half.offset << 4) + value; + } + } + if (!asflag) { + #ifdef LARGE + if (Nflag) *(va_arg(parms, char near**)) = accum.nptr; + #else + if (Fflag) *(va_arg(parms, char far**)) = accum.fptr; + #endif + else *(va_arg(parms, char **)) = accum.ptr; + count++; + } + break; + + case 'e': + case 'E': + case 'f': /* floating point */ + case 'g': + case 'G': + while (isspace(ch=(*read)(fp))) number++; + if (ch == EOF) return EOF; + valid = 0; + bufptr = buffer; + if (ch == '+' || ch == '-') { + *bufptr++ = ch; + ch = (*read)(fp); + number++; + width--; + } + while ((ch >= '0' && ch <= '9') && width) { + *bufptr++ = ch; + valid++; + ch = (*read)(fp); + number++; + width--; + } + if (ch == '.' && width) { + *bufptr++ = ch; + ch = (*read)(fp); + number++; + width--; + } + while ((ch >= '0' && ch <= '9') && width) { + *bufptr++ = ch; + valid++; + ch = (*read)(fp); + number++; + width--; + } + if ((ch == 'E' || ch == 'e') && valid && width) { + *bufptr++ = 'E'; + ch = (*read)(fp); + number++; + width--; + if ((ch == '+' || ch == '-') && width) { + *bufptr++ = ch; + ch = (*read)(fp); + number++; + width--; + } + while ((ch >= '0' && ch <= '9') && width) { + *bufptr++ = ch; + ch = (*read)(fp); + number++; + width--; + } + } + (*ungetc)(ch, fp); + if (!valid) return count; + *bufptr = '\0'; + if (!asflag) { + if (lflag) { + #ifdef LARGE + if (Nflag) + *(va_arg(parms, double near*)) = atof(buffer); + #else + if (Fflag) + *(va_arg(parms, double far*)) = atof(buffer); + #endif + else + *(va_arg(parms, double*)) = atof(buffer); + } + else { + #ifdef LARGE + if (Nflag) + *(va_arg(parms, float near*)) = atof(buffer); + #else + if (Fflag) + *(va_arg(parms, float far*)) = atof(buffer); + #endif + else + *(va_arg(parms, float*)) = atof(buffer); + } + ++count; + } + break; + +#ifdef DYNAMIC + case 'y': /* dynamic string */ + while (isspace(ch=(*read)(fp))) number++; + if (ch == EOF) return EOF; + i = 0; + bufptr = buffer; + while (width && !isspace(ch) && ch != EOF) { + if (i < 255) *bufptr++ = ch; + ch = (*read)(fp); + number++; + width--; + } + *bufptr = '\0'; + (*ungetc)(ch,fp); + if (!asflag) { + *(va_arg(parms, char**)) = stods(buffer); + ++count; + } + break; +#endif + + default : + number++; + if ((ch = (*read)(fp)) == *(format-1)) continue; + else { + if (ch == EOF) return EOF; + else { + (*ungetc)(ch,fp); + return count; + } + } + } + } + return count; +} + +_digit() /* decode ch to binary */ +{ + int n; + if (ch >= '0' && ch <= '9') n = ch - 48; + else if (ch >= 'A' && ch <= 'F') n = ch - 55; + else if (ch >= 'a' && ch <= 'f') n = ch - 87; + else return -1; + if (n < base) return n; + else return -1; +} + +_mread(s) /* read character from string */ +char **s; /* pointer to string */ +{ + if (*(*s) != '\0') return *(*s)++; + else return EOF; +} + +_mungetc(c,s) /* unget character to string */ +int c; /* dumy parameter */ +char **s; /* pointer to string pointer */ +{ + if (c != EOF) *(--(*s)) = c; + return c; +} + +static _getche() +{ + extern static int _un_getch; + int ch = _un_getch; + if (ch != EOF) { + _un_getch = EOF; + return ch; + } + else return getche(); +} + +static _un_getche(ch) + int ch; +{ + extern static int _un_getch; + if (_un_getch != EOF) return EOF; + _un_getch = ch; + return ch; +} + +static int _un_getch = EOF; + diff --git a/Mix Power C v1/SCREEN.ASM b/Mix Power C v1/SCREEN.ASM new file mode 100644 index 0000000..b3e8280 --- /dev/null +++ b/Mix Power C v1/SCREEN.ASM @@ -0,0 +1,1571 @@ +; +; Low level graphics functions +; +; Copyright (c) Mix Software 1988 +; + global +LONGNAME equ >FFFF +SHORTNAME equ >FFFF +PARM1 equ 6 +HERCMODE equ 99 +HRES equ 6 +GBW equ 4 +GCOLOR equ 5 +MONO equ 7 +PENCOLOR equ >FF +TRANSPAR equ >FE + endglobal + include fillm.asm +; +; ------------------------------------------------------------ +; +; Clear the screen +; clrscrn2(attribute) +; unsigned int attribute; +; + idt clrscrn2 + def clrscrn2 + fref getvmode + fref setvmode + fref crt_lock + lfref crt_unlock + dref _vapage + dref _vusemem +; +attrib equ PARM1 +; +clrscrn2 push bp + mov bp,sp + callfar getvmode + cmp al,GBW + jb text + cmp al,MONO + jnz graphic +text mov ax,>0600 + xor cx,cx + mov bh,[bp][%attrib] + mov dx,>184f + int >10 + xor dx,dx ; set cursor to 0,0 + mov bh,%[_vapage] + mov ah,2 + int >10 + pop bp + retfar +graphic cmp al,HERCMODE + jz clrherc + cmp [_vusemem],0 + jz nomem + cmp al,HRES + jz clrhres + cmp al,GBW + jz clrlres + cmp al,GCOLOR + jz clrlres +nomem push ax ; save current mode +; mov ax,MONO ; set to text format +; push ax +; callfar setvmode ; reset to previous mode +; pop ax +; mov ax,>0600 ; clear with bios scroll +; xor cx,cx +; mov bh,[bp][%attrib] +; mov dx,>184f +; int >10 + callfar setvmode + add sp,%2 + pop bp + retfar +clrherc callfar crt_lock + cmp [_vapage],0 + jnz page1 + mov ax,>b000 + jmps herc1 +page1 mov ax,>b800 +herc1 mov es,ax + mov cx,>4000 +onebit xor ax,ax + test %[bp][%attrib],%1 ; white or black + jz clear + dec ax ; set to all 1 +clear xor di,di + cld + rep + stosw + callfar crt_unlock + pop bp + retfar +clrhres callfar crt_lock + mov ax,>b800 + mov es,ax + mov cx,>2000 + jmps onebit +clrlres callfar crt_lock + mov ax,>b800 + mov es,ax + mov ax,[bp][%attrib] + and ax,>0003 + mov dl,al + mov cl,2 + shl al,cl + or al,dl + mov dl,al + add cl,cl + shl al,cl + or al,dl + mov ah,al + mov cx,>2000 + jmps clear + end +; +; ------------------------------------------------------------ +;int setvmode(int mode); +; attempts to set video to mode +; returns actual video mode +; stores actual video mode in _vmode +; ------------------------------------------------------------ + idt setvmode + def setvmode + ref _vmode + ref _vpages + ref _vmaxh + ref _vminh + ref _vmaxv + ref _vminv + ref _vlimits + fref getvmode + dref $$XTRC + dref $$XTRC2 +; ------------------------------------------------------------ +; +; 8086 +; tos --> bp +; return offset +; return segment +mode equ 6 +; +;***** hercules junk ***** +; +; port addresses +index equ 03b4h +cntrl equ 03b8h +config equ 03bfh +; +; control codes +scrn_on equ 8 +grph equ 2 +twopage equ 3 +onepage equ 1 +; +; tables +gtable db 35h,2dh,2eh,07h + db 5bh,02h,57h,57h + db 02h,03h,00h,00h +; +;************************ +; +; +default equ >FF + setcpu 8086 +setvmode push bp + mov bp,sp + mov al,%[bp][%mode] ;get mode argument + cmp al,default + jnz svmode + mov al,[dfltmode] + cmp al,default + jz exit ; mode was never changed + jmps setmode +svmode cmp %[dfltmode],default ; first time? + jnz setmode + callfar getvmode + mov %[dfltmode],al + mov al,%[bp][%mode] ;get mode argument +setmode mov [_vminh],0 + mov [_vminv],0 + cmp al,HERCMODE ;check for hercules mode + je hgraph ;set video to hercules graphics mode + cmp [_vmode],HERCMODE + jnz setbios + call clrherc +setbios mov ah,0 ;call set mode function of int 10h + int 10h + mov ah,15 ;call get mode function of int 10h + int 10h + xor ah,ah + mov [_vmode],ax ;store mode in global variable + cmp ax,[_vlimits] + ja nolimits + mov bx,ax + add bx,bx + add bx,bx + add bx,%2 + mov dx,[_vlimits][bx] + mov [_vmaxh],dx + add bx,%2 + mov dx,[_vlimits][bx] + mov [_vmaxv],dx + mov ax,[_vmode] +exit pop bp ;get frame pointer + retseg ;return +nolimits mov [_vmaxh],-1 + mov [_vmaxv],-1 + mov ax,[_vmode] + pop bp + retseg +; +hgraph call setherc + mov [_vmaxh],719 + mov [_vmaxv],347 + mov al,twopage + cmp %[_vpages],2 + jge cont + mov al,onepage +cont mov dx,config +; out dx,al + db >ee + mov al,grph + mov si,gtable + mov bx,0 + mov cx,4000h + push ax + push bx + push cx +; change mode but without scrn_on + mov dx,cntrl +; out dx,al + db >ee +; intialize the 6845 + mov ax,ds + mov es,ax + mov dx,index + mov cx,12 + xor ah,ah +parms mov al,ah +; out dx,al + db >ee + inc dx + segcs + lodsb +; out dx,al + db >ee + inc ah + dec dx + loop parms + pop cx +; + mov ax,>b000 + cld + mov es,ax + xor di,di + pop ax + rep + stosw +; + cmp %[_vpages],2 + jl continue + mov cx,>4000 + mov ax,>b800 + mov es,ax + xor di,di + xor ax,ax + rep + stosw +; +; scrn_on, page 0 +continue mov dx,cntrl + pop ax + add al,scrn_on +; out dx,al + db >ee + mov al,HERCMODE + xor ah,ah + mov [_vmode],ax + pop bp + retseg +; +; if CTrace is present, notify it about hercules mode +; +setherc cmp [$$XTRC2],0 + jz goback + push ax + mov ah,3 +calltrc push bx + mov bx,2 + callseg [$$XTRC] + pop bx + pop ax +goback ret +clrherc cmp [$$XTRC2],0 + jz goback + push ax + mov ah,4 + jmps calltrc +; + dorg 0 +dfltmode dw >FFFF + end + +; +;int getvmode(void); +; getvmode sets global variable _vmode to current video mode +; and returns current video mode +;******************************************************************** + idt getvmode + def getvmode + ref _vmode + ref _vvpage +;******************************************************************** +; +; 8086 +; tos --> return offset +; return segment +; + setcpu 8086 +getvmode mov ax,[_vmode] + cmp al,HERCMODE + jne continue + retseg +continue push bp ;save bp + mov ah,15 ;call get mode function of int 10h + int 10h + xor ah,ah + mov [_vmode],ax ;store mode in global variable + mov bl,bh + xor bh,bh + mov [_vvpage],bx ;store visual page in global variable + pop bp ;restore bp + retseg ;return + end +; +;int setvpage(int page); +; sets video visual page +; stores the video visual page number in _vvpage +; returns current video visual page number +;******************************************************************** + idt setvpage + def setvpage + ref _vmode + ref _vvpage +;******************************************************************** +; +; 8086 +; tos --> bp +; return offset +; return segment +page equ 6 +; +;***** hercules junk ***** +; +; control port address +cntrl equ 03b8h +; +; control codes +page0 equ 0ah +page1 equ 8ah +; +;************************ +; +; + setcpu 8086 +setvpage push bp + mov bp,sp + cmp %[_vmode],HERCMODE + je hpage + mov ah,15 ;call get page function of int 10h + int 10h + push ax + mov al,%[bp][%page] ;get page argument + mov ah,5 ;call select page function of int 10h + int 10h +exit mov al,bh + xor ah,ah + mov [_vvpage],ax ;store mode in global variable + pop ax + xor ah,ah + pop bp ;restore bp + retseg ;return +; +hpage push [_vvpage] + mov bh,%[bp][%page] ;get page argument + mov dx,cntrl + mov al,page0 ;set al to page0 + or bh,bh + jz continue + mov bh,1 ;return page number 1 + mov al,page1 ;set al to page1 +; out dx,al +continue db >ee + jmp exit + end +; +; ----------------------------------------------------------------- +; +; void writedot(int row, int col, int color); +; writes a dot of color at coordinates (row, col). +; for HERCMODE, color of 1 turns dot on, 0 turns dot off, +; + idt writedot + def writedot + ref _vmode + ref _vapage + ref _vmaxh + ref _vminh + ref _vmaxv + ref _vminv + ref _v_color + fref crt_lock + lfref crt_unlock +; +; +; 8086 +; tos --> bp +; return offset +; return segment +row equ 6 +col equ 8 +color equ 10 +VGA256 equ >13 +; +; + setcpu 8086 +writedot push bp + mov bp,sp + mov cx,[bp][%col] ;cx = col + cmp cx,[_vmaxh] ;clip to screen boundary + ja exit + cmp cx,[_vminh] + jb exit + mov dx,[bp][%row] ;dx = row + cmp dx,[_vmaxv] + ja exit + cmp dx,[_vminv] + jb exit + mov al,%[bp][%color] ;al = color + cmp al,TRANSPAR + jz exit + cmp al,PENCOLOR + jnz w1 + mov al,%[_v_color] +w1 cmp %[_vmode],HERCMODE + je hwrite + cmp %[_vmode],VGA256 + jae w2 + and al,>7F ; remove sign(xor flag) bit +w2 mov ah,12 ;use writedot funtion of int 10h + mov bx,[_vapage] +; mov cx,[bp][%col] ;cx = col +; mov dx,[bp][%row] ;dx = row + int 10h +exit pop bp ;restore + retseg ;return +; +hwrite mov bh,al + callfar crt_lock + mov dx,>b000 ;dx = page 0 + cmp %[_vapage],0 + je setes + mov dx,>b800 ;dx = page 1 +setes mov es,dx + mov ax,[bp][%row] + mov si,ax + and si,>0003 + mov cl,13 + shl si,cl ; (y % 4) * 0x2000 + shr ax,1 + shr ax,1 ; y/4 + mul [k90] + add si,ax + mov ax,[bp][%col] + mov cx,ax + shr ax,1 ; x/8 + shr ax,1 + shr ax,1 + add si,ax + and cx,>0007 ; x % 8 + mov ah,>80 + jcxz bitset + shr ah,cl +bitset seges + mov al,[si] ; previous contents + cmp bh,%0 + jz turnoff + or al,ah ; set the bit + jmps setvalue +turnoff not ah + and al,ah ; clear the bit +setvalue seges + mov %[si],al + callfar crt_unlock + pop bp + retseg + dorg 0 +k90 dw 90 + end +; +; ----------------------------------------------------------------- +; +; int readdot(int row, int col); +; returns the color of the dot at coordinates (row, col). +; for HERCMODE, a return value of 1 means dot on, 0 means dot off +; + idt readdot + def readdot + ref _vmode + ref _vapage + fref crt_lock + lfref crt_unlock +; +row equ 6 +col equ 8 +; +; +readdot push bp + mov bp,sp + cmp %[_vmode],HERCMODE + je hread + mov ah,13 + mov bx,[_vapage] + mov cx,[bp][%col] + mov dx,[bp][%row] + int 10h + pop bp + xor ah,ah + retseg +; +hread callfar crt_lock + mov dx,>b000 ;dx = page 0 + cmp %[_vapage],0 + je setes + mov dx,>b800 ;dx = page 1 +setes mov es,dx + mov ax,[bp][%row] + mov si,ax + and si,>0003 + mov cl,13 + shl si,cl ; (y % 4) * 0x2000 + shr ax,1 + shr ax,1 ; y/4 + mul [k90] + add si,ax + mov ax,[bp][%col] + mov cx,ax + shr ax,1 ; x/8 + shr ax,1 + shr ax,1 + add si,ax + and cx,>0007 ; x % 8 + neg cx + add cx,%7 + seges + mov al,%[si] ; read 8 pixels + jcxz mask ; alrerady in position + shr al,cl +mask and ax,>0001 + push ax + callfar crt_unlock + pop ax + pop bp + retseg + dorg 0 +k90 dw 90 + end +; +;void writech(int c); +; writes character ch at current position in active page +; returns ch +;******************************************************************** + idt writech + def writech + ref _vapage +;******************************************************************** +; +; tos --> bp +; return offset +; return segment +c equ 6 +; +; + setcpu 8086 +writech push bp + mov bp,sp + mov al,%[bp][%c] ;get character + mov ah,10 ;use write character of int 10h + mov bh,%[_vapage] ;set active page + mov cx,1 ;write one character + int 10h ;write ch + pop bp ;restore bp + xor ah,ah + retseg + end +; +;void writechs(int c, int attr, int n); +; writes c with attribute attr n times at current position in active page +;******************************************************************** + idt writechs + def writechs + ref _vapage +;******************************************************************** +; +; 8086 +; tos --> bp +; return offset +; return segment +c equ 6 +attr equ 8 +n equ 10 +; +; + setcpu 8086 +writechs push bp + mov bp,sp + mov cx,[bp][%n] ;get number of times to write + mov bl,%[bp][%attr] ;get attribute of character + mov al,%[bp][%c] ;get character + mov ah,9 ;set write attribute of int 10h + mov bh,%[_vapage] ;set active page + int 10h ;write character/attribute n times + pop bp ;restore bp + xor ah,ah + retseg + end + +;void poscurs(int row, int col); +; positions cursor in active page +; + idt poscurs + def poscurs + ref _vapage +; +; tos --> bp +; return offset +; return segment +row equ 6 +col equ 8 +; +; + setcpu 8086 +poscurs push bp + mov bp,sp + mov dh,%[bp][%row] + mov dl,%[bp][%col] + mov bh,%[_vapage] + mov ah,2 + int 10h + pop bp + retseg + end + +;int cursrow(void); +; returns row position of cursor in active page +; +;*********************************************************** + idt cursrow + def cursrow + ref _vapage +;*********************************************************** +; tos -> bp +; return offset +; return segment +; + setcpu 8086 +cursrow push bp + mov ah,3 + mov bh,%[_vapage] + int 10h + mov al,dh + pop bp + xor ah,ah + retseg + end +;int curscol(void); +; returns row position of cursor in active page +; +;*********************************************************** + idt curscol + def curscol + ref _vapage +;*********************************************************** +; tos -> bp +; return offset +; return segment +; + setcpu 8086 +curscol push bp + mov ah,3 + mov bh,%[_vapage] + int 10h + mov al,dl + pop bp + xor ah,ah + retseg + end +; +; ------------------------------------------------------------ +; +; int flood(x_size, y_size); +; +; Fill a rectangular area with the current pattern. +; Current graphics cursor defines the upper left corner of the area +; + idt flood + def flood + dref _vxcurs ; position + dref _vycurs + dref _vmode ; current mode + dref _vf_pat ; pattern + dref _vf_wid ; width of pattern + dref _vf_hgt ; width of pattern + dref _v_color ; pen color + dref _vapage ; active page + dref _vusemem ; direct access to memory + dref _vmaxh ; screen limit + dref _vmaxv + fref _vhwhere + fref _v4where + fref _v6where + fref crt_lock + lfref crt_unlock +xlimit equ 0 +ylimit equ 2 +xstart equ 4 +xmax equ 6 +memorg equ 8 +nextrow equ 10 +localsz equ nextrow+2 +x_size equ localsz+PARM1 +y_size equ localsz+PARM1+2 +; +flood push bp + sub sp,localsz + mov bp,sp + cmp [bp][%x_size],0 + jle done01 + cmp [bp][%y_size],0 + jg fl001 +done01 jmp done +fl001 mov ax,[_vf_pat] + mov [bp][%xstart],ax + add ax,[_vf_wid] + mov [bp][%xlimit],ax + mov ax,[_vf_wid] + mul [_vf_hgt] + add ax,[_vf_pat] + mov [bp][%ylimit],ax + mov ax,[_vxcurs] + add ax,[bp][%x_size] + cmp ax,[_vmaxh] + jna limit1 + mov bx,[_vmaxh] ; beyond screen boundary + sub ax,bx + sub [bp][%x_size],ax + mov bx,ax +limit1 mov [bp][%xmax],ax + mov ax,[bp][%y_size] + add ax,[_vycurs] + cmp ax,[_vmaxv] + jna limit2 + mov ax,[_vmaxv] + inc ax + sub ax,[_vycurs] + jz done01 + mov [bp][%y_size],ax +limit2 mov al,[_vmode] ; check current mode + cmp al,HERCMODE + jz herc + cmp [_vusemem],0 + jz bios + cmp al,HRES + jz cga6 + cmp al,GBW + jz cga4i + cmp al,GCOLOR + jz cga4i +; +; fill using the bios +; +bios mov si,[_vf_pat] + mov dx,[_vycurs] + mov cx,[_vxcurs] + mov bx,[_vapage] + jmps bitset +nextbit inc cx ; next x coordinate + cmp cx,[bp][%xmax] + jae nexty + cmp si,[bp][%xlimit] + jb bitset + mov si,[bp][%xstart] +bitset lodsb ; next color in pattern + cmp al,TRANSPAR + jz nextbit + cmp al,PENCOLOR + jnz bitput + mov al,[_v_color] +bitput mov ah,>0c + int >10 + jmps nextbit +nexty dec [bp][%y_size] + jz done + inc dx ; next y coordinate + mov si,[bp][%xstart] + add si,[_vf_wid] + cmp si,[bp][%ylimit] + jb setxlim + mov si,[_vf_pat] +setxlim mov [bp][%xstart],si + mov ax,si + add ax,[_vf_wid] + mov [bp][%xlimit],ax + mov cx,[_vxcurs] + jmps bitset +done lea sp,[bp][%localsz] + pop bp + retfar +cga4i jmp cga4 +; +herc callfar crt_lock + callfar _vhwhere ; calculate memory address + mov ax,incyh + mov [bp][%nextrow],ax + jmps onebit +cga6 callfar crt_lock + callfar _v6where + mov ax,incy6 + mov [bp][%nextrow],ax +; +onebit mov ch,cl ; save bit offset + mov [bp][%memorg],di ; save memory address + mov dx,[bp][%x_size] ; horizontal counter + seges + mov bl,[di] ; get first group of pixels + mov si,[bp][%xstart] + jmps hbitset +hnextbit inc cl ; next x coordinate + cmp cl,8 ; next byte? + jnz h001 + seges + mov [di],bl ; save current group + inc di ; get next 8 pixels + seges + mov bl,[di] + xor cl,cl +h001 dec dx + jz hnexty ; end of row + cmp si,[bp][%xlimit] + jb hbitset + mov si,[bp][%xstart] +hbitset lodsb ; next color in pattern + cmp al,TRANSPAR + jz hnextbit + cmp al,PENCOLOR + jnz hbitput + mov al,[_v_color] +hbitput and al,1 + ror al,1 + mov ah,>7f + cmp cl,0 + jz h002 + ror ah,cl + shr al,cl +h002 and bl,ah ; mask previous contents + or bl,al ; set new bit + jmps hnextbit +hnexty seges + mov [di],bl ; save last 8 pixels + dec [bp][%y_size] + jz donemem1 + mov di,[bp][%memorg] + call [bp][%nextrow] + mov [bp][%memorg],di + mov si,[bp][%xstart] + add si,[_vf_wid] + cmp si,[bp][%ylimit] + jb h004 + mov si,[_vf_pat] +h004 mov [bp][%xstart],si + mov ax,si + add ax,[_vf_wid] + mov [bp][%xlimit],ax + mov cl,ch ; reset bit number + mov dx,[bp][%x_size] ; horizontal counter + seges + mov bl,[di] + jmps hbitset +donemem1 jmp donemem +; +cga4 callfar crt_lock + callfar _v4where + mov ax,incy4 + mov [bp][%nextrow],ax +; +twobit shl cl,1 + mov ch,cl ; save bit offset + mov [bp][%memorg],di ; save memory address + mov dx,[bp][%x_size] ; horizontal counter + seges + mov bl,[di] ; get first group of pixels + mov si,[bp][%xstart] + jmps set4 +next4 add cl,%2 ; next x coordinate + cmp cl,8 ; next byte? + jnz t001 + seges + mov [di],bl ; save current group + inc di ; get next 4 pixels + seges + mov bl,[di] + xor cl,cl +t001 dec dx + jz nexty4 ; end of row + cmp si,[bp][%xlimit] + jb set4 + mov si,[bp][%xstart] +set4 lodsb ; next color in pattern + cmp al,TRANSPAR + jz next4 + cmp al,PENCOLOR + jnz put4 + mov al,[_v_color] +put4 and al,3 + ror al,1 + ror al,1 + mov ah,>3f + cmp cl,0 + jz t002 + ror ah,cl + shr al,cl +t002 and bl,ah ; mask previous contents + or bl,al ; set new bit + jmps next4 +nexty4 seges + mov [di],bl ; save last 8 pixels + dec [bp][%y_size] + jz donemem + mov di,[bp][%memorg] + call [bp][%nextrow] + mov [bp][%memorg],di + mov si,[bp][%xstart] + add si,[_vf_wid] + cmp si,[bp][%ylimit] + jb t004 + mov si,[_vf_pat] +t004 mov [bp][%xstart],si + mov ax,si + add ax,[_vf_wid] + mov [bp][%xlimit],ax + mov cl,ch ; reset bit number + mov dx,[bp][%x_size] ; horizontal counter + seges + mov bl,[di] + jmps set4 +donemem callfar crt_unlock + jmp done +; +; add 1 to the y coordinate (hercules) +; +incyh add di,>2000 ; next y coordinate + cmp di,>8000 + jb incyh1 + sub di,>8000-90D +incyh1 ret +; +; add 1 to the y coordinate (cga) +; +incy6 add di,>2000 ; next y coordinate + cmp di,>4000 + jb incy61 + sub di,>4000-80D +incy61 ret +; +; add 1 to the y coordinate (cga) +; +incy4 add di,>2000 ; next y coordinate + cmp di,>4000 + jb incy41 + sub di,>4000-80D +incy41 ret + end +; +; ------------------------------------------------------------ +; +; int plotch(char c); +; +; Write a character to the screen in graphics mode. +; For modes 4,5,6,99 the horizontal position is rounded to the +; nearest mulitple of 8 (byte boundary) +; For other modes, the bios is used. +; + idt plotch + def plotch + dref _vchpat1 ; character font table + dref _vxcurs ; position + dref _vycurs + dref _vmode ; current mode + dref _v_color ; pen color + dref _vapage ; active page + fref _vhwhere + fref _v4where + fref _v6where + fref crt_lock + lfref crt_unlock +; +plotch push bp + mov bp,sp + mov si,[bp][%PARM1] ; fetch value of character + cmp si,>7f + ja exit + shl si,1 + shl si,1 + shl si,1 + add si,_vchpat1 ; si = address of pattern + mov al,[_vmode] ; check current mode + cmp al,HERCMODE + jz herc + cmp al,HRES + jz cga6i + cmp al,GBW + jz cga4i + cmp al,GCOLOR + jz cga4i +; +; write a character using write dot +; + mov ah,[si] + mov di,8*8 ; 64 points + mov dx,[_vycurs] + mov cx,[_vxcurs] + mov bx,[_vapage] + jmps next +nextbit inc cx ; next x coordinate + test di,>0007 + jnz next + sub cx,%8 ; next row of pattern + inc dx + inc si + mov ah,[si] +next xor al,al + shl ah,1 + push ax + jnc putbit + mov al,[_v_color] ; bit is on +putbit mov ah,>0c + int >10 + pop ax + dec di + jnz nextbit +done add [_vxcurs],%8 +exit pop bp + retfar +cga4i jmp cga4 +cga6i jmp cga6 +; +; write a character to hercules monochrome graphics card +; si contains address of character pattern +; +herc callfar crt_lock + callfar _vhwhere + mov dx,[_v_color] + jcxz hbyte +; write to hercules (not on byte boundary) + mov dh,8 +hnbnext mov bx,>ff00 + ror bx,cl + seges + and bx,[di] ; remove previous bits + lodsb + test dl,%1 + jnz posh2 + not al +posh2 xor ah,ah + ror ax,cl ; bring into position + or bx,ax + seges + mov [di],bx + add di,>2000 + cmp di,>8000 + jb nexth2 + sub di,>8000-90D +nexth2 dec dh + jnz hnbnext +doneh callfar crt_unlock + jmps done +; write to hercules, character on byte boundary +hbyte mov cx,8 +puth lodsb + test dl,%1 + jnz posh + not al +posh seges + mov [di],al + add di,>2000 + cmp di,>8000 + jb nexth + sub di,>8000-90D +nexth loop puth + jmp doneh +; +cga6 callfar crt_lock + callfar _v6where + mov dx,[_v_color] + jcxz cgabyte +; write to cga mode 6 (not on byte boundary) + mov dh,8 +cga6nxt mov bx,>ff00 + ror bx,cl + seges + and bx,[di] ; remove previous bits + lodsb + test dl,%1 + jnz pos62 + not al +pos62 xor ah,ah + ror ax,cl ; bring into position + or bx,ax + seges + mov [di],bx + add di,>2000 + cmp di,>4000 + jb next62 + sub di,>4000-80D +next62 dec dh + jnz cga6nxt +done6 callfar crt_unlock + jmp done +cgabyte mov cx,8 +put6 lodsb + test dl,%01 + jnz pos6 + not al +pos6 seges + mov [di],al + add di,>2000 + cmp di,>4000 + jb next6 + sub di,>4000-80D +next6 loop put6 + jmp done6 +; +cga4 callfar crt_lock + callfar _v4where + mov ax,[_v_color] ; get color of pen + jcxz cga4byte + shl cl,1 + mov dl,cl ; save starting offset + push di + mov dh,8 ; number of rows +cga4row mov ch,8 ; bits per row + lodsb +cga4lp1 xor ah,ah + shl al,1 + jnc cga4zero + mov ah,[_v_color] + and ah,>3 + ror ah,1 + ror ah,1 +cga4zero mov bh,>3f ; mask previous contents + cmp cl,0 + jz cga4set + shr ah,cl ; move color into position + ror bh,cl +cga4set seges + and bh,[di] + or bh,ah + seges + mov [di],bh ; set pixel + add cl,%2 + cmp cl,6 + jbe cga4nxt + inc di + xor cl,cl +cga4nxt dec ch + jnz cga4lp1 + mov cl,dl ; restore bit offset + pop di ; restore origin + add di,>2000 ; next row address + cmp di,>4000 + jb cga4a + sub di,>4000-80D +cga4a push di + dec dh + jnz cga4row + pop di +done4 callfar crt_unlock + jmp done +; cga mode 4 or 5 on byte boundary +cga4byte mov ax,[_v_color] + xor dx,dx + mov cx,8 +makemask shl dl,1 + shl dl,1 + or dl,al + loop makemask + mov dh,dl + mov cx,8 +put4 lodsb + push cx + mov cx,8 +make4 shr al,1 ; replicate bits + rcr bx,1 + sar bx,1 + loop make4 + pop cx + and bx,dx + xchg bh,bl + seges + mov [di],bx + add di,>2000 + cmp di,>4000 + jb next4 + sub di,>4000-80D +next4 loop put4 + jmp done4 + end +; +; Generate memory address for a point on the screen +; Hercules graphics card +; Returns address in es:di and bit number in cl +; + idt _vhwhere + def _vhwhere + dref _vxcurs + dref _vycurs + dref _vapage +; +_vhwhere mov ax,[_vycurs] + mov di,ax + and di,>0003 + mov cl,13 + shl di,cl ; (y % 4) * 0x2000 + mov cl,2 + shr ax,cl ; y/4 + shl ax,1 ; (y/4) * 0x02 + add di,ax + shl ax,cl ; (y/4) * 0x08 + add di,ax + shl ax,1 ; (y/4) * 0x10 + add di,ax + shl ax,cl ; (y/4) * 0x40 + add di,ax + mov ax,[_vxcurs] + mov cx,ax + and cx,>0007 ; bit number + shr ax,1 ; x/8 + shr ax,1 + shr ax,1 + add di,ax ; di = memory address + mov ax,>b000 ; select segment for active page + cmp %[_vapage],0 + je sethpage + mov ax,>b800 +sethpage mov es,ax + retfar + end +; +; Generate memory address for a point on the screen +; CGA high resolution (mode 6) +; Returns address in es:di and bit number in cl +; + idt _v6where + def _v6where + dref _vxcurs + dref _vycurs +; +_v6where mov ax,[_vycurs] + mov di,ax + and di,>0001 + mov cl,13 + shl di,cl ; (y % 2) * 0x2000 + shr ax,1 ; y/2 + mov cl,4 + shl ax,cl ; (y/2) * 0x10 + add di,ax + shl ax,1 + shl ax,1 ; ax = (y/2) * 0x40 + add di,ax + mov ax,[_vxcurs] + mov cx,ax + and cx,>0007 + shr ax,1 ; x/8 + shr ax,1 + shr ax,1 + add di,ax + mov ax,>b800 ; segment of cga memory + mov es,ax + retfar + end +; +; Generate memory address for a point on the screen +; CGA low resolution (mode 4 or 5) +; Returns address in es:di and bit number in cl +; + idt _v4where + def _v4where + dref _vxcurs + dref _vycurs +; +_v4where mov ax,[_vycurs] + mov di,ax + and di,>0001 + mov cl,13 + shl di,cl ; (y % 2) * 0x2000 + shr ax,1 ; y/2 + mov cl,4 + shl ax,cl ; (y/2) * 0x10 + add di,ax + shl ax,1 + shl ax,1 ; ax = (y/2) * 0x40 + add di,ax + mov ax,[_vxcurs] + mov cx,ax + and cx,>0003 + shr ax,1 ; x/4 + shr ax,1 + add di,ax + mov ax,>b800 ; segment of cga memory + mov es,ax + retfar + end +; +; ------------------------------------------------------------ +; +; crt_lock - lock the crt contents into physical screen memory +; crt_lock should be called before the program writes directly +; to screen memory +; + idt crt_lock + def crt_lock + dref $$XTRC + dref $$XTRC2 +; +needmem equ PARM1-2 +crt_lock cmp [$$XTRC2],0 + jnz request + retfar +request push bx + mov bx,2 + mov ah,1 +calltrc callseg [$$XTRC] + pop bx + xor ax,ax + retfar + end +; +; ------------------------------------------------------------ +; +; crt_unlock - release the crt contents from screen memory +; + idt crt_unlock + IF LONGNAME + LDEF crt_unlock + ENDIF + IF SHORTNAME + DEF crt_unlo + ENDIF + dref $$XTRC + dref $$XTRC2 +; +needmem equ PARM1-2 +crt_unlo cmp [$$XTRC2],0 + jnz request + retfar +request push bx + mov bx,2 + mov ah,2 +calltrc callseg [$$XTRC] + pop bx + xor ax,ax + retfar + end +; +; ------------------------------------------------------------ +; + idt _vdata + ddef _vmode + ddef _vpages + ddef _vapage + ddef _vvpage + ddef _vmaxh + ddef _vminh + ddef _vmaxv + ddef _vminv + ddef _vattr + ddef _vlimits + ddef _vusemem + ddef _v_color + ddef _vl_dpat + ddef _vl_pat + ddef _vl_psiz + ddef _vxcurs + ddef _vycurs + ddef _vf_pat + ddef _vf_wid + ddef _vf_hgt +; + dorg 0 +_vmode dw >ffff ; screen mode +_vpages dw >0002 ; number of pages (graphics) +_vapage dw >0000 ; active page +_vvpage dw >0000 ; visible page +_vmaxh dw >ffff ; horizontal boundaries +_vminh dw >0000 +_vmaxv dw >ffff ; vertical boundaries +_vminv dw >0000 +_vattr dw 7 ; attribute for scroll functions +_vusemem dw 1 ; use direct access to screen memory +_v_color dw >FF ; pen color +_vl_dpat dw >FF ; default color for lines +_vl_pat dw _vl_dpat ; line style +_vl_psiz dw 1 ; size of line style +_vxcurs dw 0 ; graphics cursor +_vycurs dw 0 +_vf_pat dw _vl_dpat ; default fill pattern +_vf_wid dw 1 ; width of fill pattern +_vf_hgt dw 1 ; height of fill pattern +_vlimits dw 16 ; Maximum in table + dw 39,24,39,24,79,24,79,24 ; 0..3 (text) + dw 319,199,319,199,639,199 ; 4..6 (graphics) + dw 79,24 ; 7 (monochome) + dw 159,199,319,199,639,199 ; 8..10 (pc Jr) + dw 0,0,0,0 ; 11..12 (undefined) + dw 319,199,639,199,639,349 ; 13..15 (EGA) + dw 639,349 ; 16 (EGA) +; + end +; +; Table of bit patterns for characters in graphics mode. +; Characters fill an 8x8 cell. +; Only the first 128 character codes are present. +; + idt _vchpat1 + ddef _vchpat1 +; + dorg 0 +_vchpat1 db >00,>00,>00,>00,>00,>00,>00,>00 ; 00 + db >7e,>81,>a5,>81,>bd,>99,>81,>7e ; 01 + db >7e,>ff,>db,>ff,>c3,>e7,>ff,>7e ; 02 + db >6c,>fe,>fe,>fe,>7c,>38,>10,>00 ; 03 + db >10,>38,>7c,>fe,>7c,>38,>10,>00 ; 04 + db >38,>7c,>38,>fe,>fe,>7c,>38,>7c ; 05 + db >10,>10,>38,>7c,>fe,>7c,>38,>7c ; 06 + db >00,>00,>18,>3c,>3c,>18,>00,>00 ; 07 + db >ff,>ff,>e7,>c3,>c3,>e7,>ff,>ff ; 08 + db >00,>3c,>66,>42,>42,>66,>3c,>00 ; 09 + db >ff,>c3,>99,>bd,>bd,>99,>c3,>ff ; 0a + db >0f,>07,>0f,>7d,>cc,>cc,>cc,>78 ; 0b + db >3c,>66,>66,>66,>3c,>18,>7e,>18 ; 0c + db >3f,>33,>3f,>30,>30,>70,>f0,>e0 ; 0d + db >7f,>63,>7f,>63,>63,>67,>e6,>c0 ; 0e + db >99,>5a,>3c,>e7,>e7,>3c,>5a,>99 ; 0f + db >80,>e0,>f8,>fe,>f8,>e0,>80,>00 ; 10 + db >02,>0e,>3e,>fe,>3e,>0e,>02,>00 ; 11 + db >18,>3c,>7e,>18,>18,>7e,>3c,>18 ; 12 + db >66,>66,>66,>66,>66,>00,>66,>00 ; 13 + db >7f,>db,>db,>7b,>1b,>1b,>1b,>00 ; 14 + db >3e,>63,>38,>6c,>6c,>38,>cc,>78 ; 15 + db >00,>00,>00,>00,>7e,>7e,>7e,>00 ; 16 + db >18,>3c,>7e,>18,>7e,>3c,>18,>ff ; 17 + db >18,>3c,>7e,>18,>18,>18,>18,>00 ; 18 + db >18,>18,>18,>18,>7e,>3c,>18,>00 ; 19 + db >00,>18,>0c,>fe,>0c,>18,>00,>00 ; 1a + db >00,>30,>60,>fe,>60,>30,>00,>00 ; 1b + db >00,>00,>c0,>c0,>c0,>fe,>00,>00 ; 1c + db >00,>24,>66,>ff,>66,>24,>00,>00 ; 1d + db >00,>18,>3c,>7e,>ff,>ff,>00,>00 ; 1e + db >00,>ff,>ff,>7e,>3c,>18,>00,>00 ; 1f + db >00,>00,>00,>00,>00,>00,>00,>00 ; 20 + db >30,>78,>78,>30,>30,>00,>30,>00 ; 21 ! + db >6c,>6c,>6c,>00,>00,>00,>00,>00 ; 22 " + db >6c,>6c,>fe,>6c,>fe,>6c,>6c,>00 ; 23 # + db >30,>7c,>c0,>78,>0c,>f8,>30,>00 ; 24 $ + db >00,>c6,>cc,>18,>30,>66,>c6,>00 ; 25 % + db >38,>6c,>38,>76,>dc,>cc,>76,>00 ; 26 & + db >60,>60,>c0,>00,>00,>00,>00,>00 ; 27 ' + db >18,>30,>60,>60,>60,>30,>18,>00 ; 28 ( + db >60,>30,>18,>18,>18,>30,>60,>00 ; 29 ) + db >00,>66,>3c,>ff,>3c,>66,>00,>00 ; 2a * + db >00,>30,>30,>fc,>30,>30,>00,>00 ; 2b + + db >00,>00,>00,>00,>00,>30,>30,>60 ; 2c , + db >00,>00,>00,>fc,>00,>00,>00,>00 ; 2d - + db >00,>00,>00,>00,>00,>30,>30,>00 ; 2e . + db >06,>0c,>18,>30,>60,>c0,>80,>00 ; 2f / + db >7c,>c6,>ce,>de,>f6,>e6,>7c,>00 ; 30 0 + db >30,>70,>30,>30,>30,>30,>fc,>00 ; 31 1 + db >78,>cc,>0c,>38,>60,>cc,>fc,>00 ; 32 2 + db >78,>cc,>0c,>38,>0c,>cc,>78,>00 ; 33 3 + db >1c,>3c,>6c,>cc,>fe,>0c,>1e,>00 ; 34 4 + db >fc,>c0,>f8,>0c,>0c,>cc,>78,>00 ; 35 5 + db >38,>60,>c0,>f8,>cc,>cc,>78,>00 ; 36 6 + db >fc,>cc,>0c,>18,>30,>30,>30,>00 ; 37 7 + db >78,>cc,>cc,>78,>cc,>cc,>78,>00 ; 38 8 + db >78,>cc,>cc,>7c,>0c,>18,>70,>00 ; 39 9 + db >00,>30,>30,>00,>00,>30,>30,>00 ; 3a : + db >00,>30,>30,>00,>00,>30,>30,>60 ; 3b ; + db >18,>30,>60,>c0,>60,>30,>18,>00 ; 3c < + db >00,>00,>fc,>00,>00,>fc,>00,>00 ; 3d = + db >60,>30,>18,>0c,>18,>30,>60,>00 ; 3e > + db >78,>cc,>0c,>18,>30,>00,>30,>00 ; 3f ? + db >7c,>c6,>de,>de,>de,>c0,>78,>00 ; 40 @ + db >30,>78,>cc,>cc,>fc,>cc,>cc,>00 ; 41 A + db >fc,>66,>66,>7c,>66,>66,>fc,>00 ; 42 B + db >3c,>66,>c0,>c0,>c0,>66,>3c,>00 ; 43 C + db >f8,>6c,>66,>66,>66,>6c,>f8,>00 ; 44 D + db >fe,>62,>68,>78,>68,>62,>fe,>00 ; 45 E + db >fe,>62,>68,>78,>68,>60,>f0,>00 ; 46 F + db >3c,>66,>c0,>c0,>ce,>66,>3e,>00 ; 47 G + db >cc,>cc,>cc,>fc,>cc,>cc,>cc,>00 ; 48 H + db >78,>30,>30,>30,>30,>30,>78,>00 ; 49 I + db >1e,>0c,>0c,>0c,>cc,>cc,>78,>00 ; 4a J + db >e6,>66,>6c,>78,>6c,>66,>e6,>00 ; 4b K + db >f0,>60,>60,>60,>62,>66,>fe,>00 ; 4c L + db >c6,>ee,>fe,>fe,>d6,>c6,>c6,>00 ; 4d M + db >c6,>e6,>f6,>de,>ce,>c6,>c6,>00 ; 4e N + db >38,>6c,>c6,>c6,>c6,>6c,>38,>00 ; 4f O + db >fc,>66,>66,>7c,>60,>60,>f0,>00 ; 50 P + db >78,>cc,>cc,>cc,>dc,>78,>1c,>00 ; 51 Q + db >fc,>66,>66,>7c,>6c,>66,>e6,>00 ; 52 R + db >78,>cc,>e0,>70,>1c,>cc,>78,>00 ; 53 S + db >fc,>b4,>30,>30,>30,>30,>78,>00 ; 54 T + db >cc,>cc,>cc,>cc,>cc,>cc,>fc,>00 ; 55 U + db >cc,>cc,>cc,>cc,>cc,>78,>30,>00 ; 56 V + db >c6,>c6,>c6,>d6,>fe,>ee,>c6,>00 ; 57 W + db >c6,>c6,>6c,>38,>38,>6c,>c6,>00 ; 58 X + db >cc,>cc,>cc,>78,>30,>30,>78,>00 ; 59 Y + db >fe,>c6,>8c,>18,>32,>66,>fe,>00 ; 5a Z + db >78,>60,>60,>60,>60,>60,>78,>00 ; 5b [ + db >c0,>60,>30,>18,>0c,>06,>02,>00 ; 5c \ + db >78,>18,>18,>18,>18,>18,>78,>00 ; 5d ] + db >10,>38,>6c,>c6,>00,>00,>00,>00 ; 5e ^ + db >00,>00,>00,>00,>00,>00,>00,>ff ; 5f _ + db >30,>30,>18,>00,>00,>00,>00,>00 ; 60 ` + db >00,>00,>78,>0c,>7c,>cc,>76,>00 ; 61 a + db >e0,>60,>60,>7c,>66,>66,>dc,>00 ; 62 b + db >00,>00,>78,>cc,>c0,>cc,>78,>00 ; 63 c + db >1c,>0c,>0c,>7c,>cc,>cc,>76,>00 ; 64 d + db >00,>00,>78,>cc,>fc,>c0,>78,>00 ; 65 e + db >38,>6c,>60,>f0,>60,>60,>f0,>00 ; 66 f + db >00,>00,>76,>cc,>cc,>7c,>0c,>f8 ; 67 g + db >e0,>60,>6c,>76,>66,>66,>e6,>00 ; 68 h + db >30,>00,>70,>30,>30,>30,>78,>00 ; 69 i + db >0c,>00,>0c,>0c,>0c,>cc,>cc,>78 ; 6a j + db >e0,>60,>66,>6c,>78,>6c,>e6,>00 ; 6b k + db >70,>30,>30,>30,>30,>30,>78,>00 ; 6c l + db >00,>00,>cc,>fe,>fe,>d6,>c6,>00 ; 6d m + db >00,>00,>f8,>cc,>cc,>cc,>cc,>00 ; 6e n + db >00,>00,>78,>cc,>cc,>cc,>78,>00 ; 6f o + db >00,>00,>dc,>66,>66,>7c,>60,>f0 ; 70 p + db >00,>00,>76,>cc,>cc,>7c,>0c,>1e ; 71 q + db >00,>00,>dc,>76,>66,>60,>f0,>00 ; 72 r + db >00,>00,>7c,>c0,>78,>0c,>f8,>00 ; 73 s + db >10,>30,>7c,>30,>30,>34,>18,>00 ; 74 t + db >00,>00,>cc,>cc,>cc,>cc,>76,>00 ; 75 u + db >00,>00,>cc,>cc,>cc,>78,>30,>00 ; 76 v + db >00,>00,>c6,>d6,>fe,>fe,>6c,>00 ; 77 w + db >00,>00,>c6,>6c,>38,>6c,>c6,>00 ; 78 x + db >00,>00,>cc,>cc,>cc,>7c,>0c,>f8 ; 79 y + db >00,>00,>fc,>98,>30,>64,>fc,>00 ; 7a z + db >1c,>30,>30,>e0,>30,>30,>1c,>00 ; 7b { + db >18,>18,>18,>00,>18,>18,>18,>00 ; 7c | + db >e0,>30,>30,>1c,>30,>30,>e0,>00 ; 7d } + db >76,>dc,>00,>00,>00,>00,>00,>00 ; 7e ~ + db >00,>10,>38,>6c,>c6,>c6,>fe,>00 ; 7f + end diff --git a/Mix Power C v1/SEEK.ASM b/Mix Power C v1/SEEK.ASM new file mode 100644 index 0000000..6a911f6 --- /dev/null +++ b/Mix Power C v1/SEEK.ASM @@ -0,0 +1,200 @@ +; +; Copyright (c) Mix Software 1988 +; +; position a file +; +; int fseek(fp, offset, origin) +; FILE *fp; +; long offset; +; int origin; +; + IDT fseek + DEF fseek + REF _fileerr + FREF _fseek +fseek MOV BX,SP + PUSH [BX][%PARM4-2] + PUSH [BX][%PARM3-2] + PUSH [BX][%PARM2-2] + PUSH [BX][%PARM1-2] + CALLFAR _fseek + ADD SP,%8 + CMP DX,-1 + JNZ OK + CMP AX,-1 + JNZ OK + RETFAR +OK XOR AX,AX + RETFAR + END +; +; position a file +; +; long _fseek(fp, offset, origin) +; FILE *fp; +; long offset; +; int origin; +; + IDT _fseek + DEF _fseek + REF _fileerr + FREF _fflush + FREF _rflush +_fseek MOV BX,SP + MOV SI,[BX][%PARM1-2] + TEST SI,SI + JZ NOFILE + TEST %[SI][%FD$DIRTY],%FL$WRITE+FL$READ + JNZ FLUSH +; +; fp->file.count = 0; +; +DOSEEK MOV [SI][%FD$COUNT],0 +; +; if ((handle = fp->file.handle) == -1) handle = 2; +; + MOV BX,[SI][%FD$HNDL] + CMP BX,%-1 + JZ USE2 +; +; reg.byte.ah = 0x42; +; reg.byte.al = origin; +; reg.word.bx = handle; +; longword.longvalue = offset; +; reg.word.cx = longword.words.msword; +; reg.word.dx = longword.words.lsword; +; longword.words.msword = reg.word.dx; +; longword.words.lsword = reg.word.ax; +; return longword.longvalue; +; +HNDLSET MOV AH,>42 + MOV SI,SP + MOV AL,[SI][%PARM3+2-2] + MOV DX,[SI][%PARM2-2] + MOV CX,[SI][%PARM2+2-2] +; +; if (bios(0x21,®) & 0x01) return (*_fileerr)(reg.word.ax,fp); +; + INT >21 + JB ERROR +; +; longword.words.msword = reg.word.dx; +; longword.words.lsword = reg.word.ax; +; return longword.longvalue; +; + RETSEG +; +ERROR MOV SI,SP + PUSH [SI][%PARM1-2] + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%4 + CWD + RETSEG +NOFILE MOV AX,-1 + CWD + RETSEG +; +; if (fp->file.dirty & fdwrite) { +; if (_fflush(fp) != 0) return EOF; +; } +; +FLUSH TEST %[SI][%FD$DIRTY],%FL$WRITE + JZ FLUSHR + PUSH SI + CALLFAR _fflush +ENDFLUSH POP SI + TEST AX,AX + JZ DOSEEK + DEC AX + RETSEG +; +; else if (fp->file.dirty & fdread) { +; if (_rflush(fp) != 0) return EOF; +; } +; +FLUSHR PUSH SI + CALLFAR _rflush + JMPS ENDFLUSH +USE2 MOV BX,2 + JMPS HNDLSET + END +; +; return the current file position +; long ftell(fp) +; FILE *fp; +; + IDT ftell + DEF ftell + FREF _seekend + REF _fileerr +ftell MOV BX,SP + MOV SI,[BX][%PARM1-2] + TEST SI,SI + JZ NULL + TEST %[SI][%FD$FLAGS],%FL$APPEN + JZ FIND + TEST %[SI][%FD$DIRTY],%FL$WRITE + JZ FIND + PUSH SI + CALLFAR _seekend + POP SI +FIND EQU $ +; +; reg.byte.ah = 0x42; +; reg.byte.al = 1 +; reg.word.bx = handle; +; reg.word.cx = 0 +; reg.word.dx = 0 +; + MOV AX,>4201 + XOR CX,CX + XOR DX,DX + MOV BX,[SI][%FD$HNDL] +; +; if (bios(0x21,®) & 0x01) return (*_fileerr)(reg.word.ax,fp); +; + PUSH SI + INT >21 + POP SI + JB ERROR +; +; longword.words.msword = reg.word.dx; +; longword.words.lsword = reg.word.ax; +; return longword.longvalue; +; + TEST %[SI][%FD$DIRTY],%FL$WRITE+FL$READ + JNZ BUFRUSED + RETSEG +; +; if (fp->file.dirty & fdwrite) { +; offset = fp->file.ptr - fp->file.bufr; +; } +; +BUFRUSED TEST %[SI][%FD$DIRTY],%FL$WRITE + JZ READBUFR +ADDOFF MOV CX,[SI][%FD$PTR] + SUB CX,[SI][%FD$BUFR] + ADD AX,CX + ADC DX,%0 + RETSEG +; +; else if (fp->file.dirty & fdread) { +; offset = fp->file.bufr - fp->file.bufr;} +; +READBUFR SUB AX,[SI][%FD$COUNT] + SBB DX,0 + RETSEG +; +ERROR MOV SI,SP + PUSH [SI][%PARM1-2] + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%4 + CWD + RETSEG +NULL MOV AX,-1 + RETSEG + END diff --git a/Mix Power C v1/SETBUF.C b/Mix Power C v1/SETBUF.C new file mode 100644 index 0000000..5ab48b8 --- /dev/null +++ b/Mix Power C v1/SETBUF.C @@ -0,0 +1,74 @@ + +/* File buffer functions */ +/* Copyright (c) Mix Software 1988 */ + +setbufsiz(size) +int size; +{ + extern int $$BUFSIZ; + int oldsize = $$BUFSIZ; + $$BUFSIZ = size; + return oldsize; +} + +/* ------------------------------------------------------------ */ + +setbuf(fp, bufptr) +FILE *fp; +char *bufptr; +{ + extern int (*_fclose)(); + int fclose(); + if (fp) { + _fclose = fclose; + fflush(fp); + if ((fp->file.flags & fdsetbuf) == 0) free(fp->file.bufr); + if (bufptr == 0) { + fp->file.flags |= fdunbufr; + fp->file.bufr = NULL; + fp->file.ptr = NULL; + fp->file.count = 0; + return; + } + fp->file.bufr = fp->file.ptr = bufptr; + fp->file.count = 0; + fp->file.flags &= ~fdunbufr; + fp->file.flags |= fdsetbuf; + } +} + +/* ------------------------------------------------------------ */ + +setvbuf(fp, buf, type, size) + FILE *fp; + char *buf; + int type; + int size; +{ + extern int (*_fclose)(); + int fclose(); + if (fp) { + _fclose = fclose; + if (type != _IONBF && type != _IOFBF && type != _IOLBF) return -1; + if (size < 0) return -1; + fflush(fp); + if ((fp->file.flags & fdsetbuf) == 0) free(fp->file.bufr); + if (type == _IONBF) { + fp->file.flags |= fdunbufr; + fp->file.bufr = NULL; + fp->file.ptr = NULL; + fp->file.count = 0; + return 0; + } + if (buf == NULL) buf = malloc(size); + if (buf == NULL) return -1; + fp->file.bufr = fp->file.ptr = buf; + fp->file.count = 0; + fp->file.bufsize = size; + fp->file.flags &= ~fdunbufr; + fp->file.flags |= fdsetbuf; + return 0; + } + else return -1; +} + diff --git a/Mix Power C v1/SETJMP.ASM b/Mix Power C v1/SETJMP.ASM new file mode 100644 index 0000000..9846919 --- /dev/null +++ b/Mix Power C v1/SETJMP.ASM @@ -0,0 +1,124 @@ +; +; Copyright (c) Mix Software 1988 +; +; Setjmp - stores the current state to allow a +; global branch to be taken later. +; +; Declared in C as: +; struct JMP_BUF { +; int frame; +; long pc; +; int stacktop; +; char save[22]; +; }; +; int setjmp(); +; +; Example of use in C: +; +; { JMP_BUF sjbuf; +; if (setjmp(&sjbuf)) { +; /* code that is jumped to */ +; } +; else { +; /* code to execute after setting the jump */ +; } } +; +; +FRAME EQU 0 ; Frame pointer in jmp_buf +PC EQU 2 ; Program counter in jmp_buf +STACKTOP EQU 6 ; Stack top in jmp_buf +SAVESIZE EQU 8 ; Size of parameter area +SAVE EQU 10 ; Save stack area in jmp_buf +MAXDATA EQU 22 ; Limit on top of stack data + IDT setjmp + DEF setjmp + IF UPPER + DEF SETJMP + ENDIF +setjmp equ $ +SETJMP MOV BX,SP ; Point to return address + MOV DI,[BX][%PARM1-2] ; address of jmp_buf + MOV [DI][%FRAME],BP + MOV AX,[BX] + MOV [DI][%PC],AX ; First word of pc + MOV AX,[BX][%2] + MOV [DI][%PC+2],AX ; Second word of pc + LEA SI,[BX][%4] ; Top of stack + MOV [DI][%STACKTOP],SI + MOV CX,BP + SUB CX,SI ; Top of stack area + MOV [DI][%SAVESIZE],CX + CMP CX,MAXDATA + JBE SAVESTK + MOV CX,MAXDATA +SAVESTK ADD DI,%SAVE + MOV AX,DS + MOV ES,AX + JCXZ DONE + CLD + REP + MOVSB +DONE XOR AX,AX ; return 0 + RETSEG + END +; +; Longjmp - transfers to the location previously +; set by a call to setjmp. The stack is +; also restored to its former state. +; +; Declared in C as: +; struct JMP_BUF { +; int frame; +; long pc; +; int stacktop; +; int save[22]; +; } +; int longjmp(); +; +; Example of use in C: +; +; longjmp(&sjbuf,result); +; +; +; +; +FRAME EQU 0 ; Frame pointer in jmp_buf +PC EQU 2 ; Program counter in jmp_buf +STACKTOP EQU 6 ; Stack top in jmp_buf +SAVESIZE EQU 8 ; Size of saved stack +SAVE EQU 10 ; Save stack area in jmp_buf +MAXDATA EQU 22 ; Limit on top of stack data + IDT longjmp + DEF longjmp + IF UPPER + DEF LONGJMP + ENDIF +longjmp equ $ +LONGJMP MOV BX,SP ; parameter pointer + MOV SI,[BX][%PARM1-2] ; Address of sjbuf + CMP SP,[SI][%STACKTOP] + JA NOFRAME + MOV AX,[BX][%PARM2-2] ; result + MOV DI,[SI][%STACKTOP] + MOV CX,DS + MOV ES,CX + MOV CX,[SI][%SAVESIZE] + CMP CX,MAXDATA + JA TOOBIG + PUSH SI + ADD SI,%SAVE + JCXZ MOVED + CLD + REP + MOVSB +MOVED POP SI + MOV BP,[SI][%FRAME] + MOV SP,[SI][%STACKTOP] + PUSH [SI][%PC+2] + PUSH [SI][%PC] + RETSEG ; AX has result +NOFRAME MOV AX,-1 + RETSEG +TOOBIG MOV AX,-2 + RETSEG + END diff --git a/Mix Power C v1/SETMEM.ASM b/Mix Power C v1/SETMEM.ASM new file mode 100644 index 0000000..6a080b6 --- /dev/null +++ b/Mix Power C v1/SETMEM.ASM @@ -0,0 +1,72 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; setmem(address,count,value) - fill memory with value +; memset(address,value,count) +; ------------------------------------------------------- +; + IDT setmem + DEF setmem + IF UPPER + DEF SETMEM + ENDIF +; +SETMEM EQU $ +setmem PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM2] + MOV AX,[BP][%PARM3] +SETMEM1 MOV DI,[BP][%PARM1] + PUSH CX + SHR CX,1 + JCXZ LASTCHAR + MOV AH,AL + MOV DX,DS + MOV ES,DX + CLD + REP + STOSW +LASTCHAR POP CX + AND CX,>0001 + JCXZ DONE + STOSB +DONE MOV AX,[BP][%PARM1] ; Return pointer to destination + POP BP + RETSEG +memset equ $ +MEMSET PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM2] + MOV CX,[BP][%PARM3] + JMPS SETMEM1 + END +; +; ------------------------------------------------------- +; repmem(address,data,datasize, copies) +; fill memory with copies of a template +; ------------------------------------------------------- +; + IDT repmem + DEF repmem +; +repmem PUSH BP + MOV BP,SP + MOV DX,[BP][%PARM4] ; number of copies + TEST DX,DX + JZ DONE + MOV CX,[BP][%PARM3] ; size of block + JCXZ DONE + MOV DI,[BP][%PARM1] ; address of data + MOV CX,DS + MOV ES,CX + CLD +FILL MOV SI,[BP][%PARM2] ; pattern data + MOV CX,[BP][%PARM3] ; size of block + REP + MOVSB + DEC DX + JNZ FILL +DONE POP BP + RETSEG + END diff --git a/Mix Power C v1/SIEVE.C b/Mix Power C v1/SIEVE.C new file mode 100644 index 0000000..236f1d4 --- /dev/null +++ b/Mix Power C v1/SIEVE.C @@ -0,0 +1,35 @@ +/* sieve.c */ + +/* Eratosthenes Sieve Prime Number Program in C from Byte Jan 1983 + to compare the speed. */ + +#include + +#define TRUE 1 +#define FALSE 0 +#define SIZE 8190 +typedef int bool; + +char flags[SIZE+1]; + +int main() + { + int i,k; + int prime,count,iter; + + for (iter = 1; iter <= 10; iter++) { /* do program 10 times */ + count = 0; /* initialize prime counter */ + for (i = 0; i <= SIZE; i++) /* set all flags TRUE */ + flags[i] = TRUE; + for (i = 0; i <= SIZE; i++) { + if (flags[i]) { /* found a prime */ + prime = i + i + 3; /* twice index + 3 */ + for (k = i + prime; k <= SIZE; k += prime) + flags[k] = FALSE; /* kill all multiples */ + count++; /* primes found */ + } + } + } + printf("%d primes.\n",count); /*primes found in 10th pass */ + return 0; + } diff --git a/Mix Power C v1/SIGNAL.ASM b/Mix Power C v1/SIGNAL.ASM new file mode 100644 index 0000000..935a09c --- /dev/null +++ b/Mix Power C v1/SIGNAL.ASM @@ -0,0 +1,293 @@ +; +; Copyright (c) Mix Software 1988 +; + IDT ssignal + DEF ssignal + FREF signal +ssignal JMPFAR signal + END +; +; Signal - set interrupt vectors +; +; int (*signal(sig,func))(); +; int sig; +; int (*func)() +; + IDT signal + DEF signal + DEF _signal_ + DREF errno + DREF _SIGTBL +SIGMAX EQU 8 +SIGINT EQU 2 +SIGFPE EQU 8 +signal MOV %[CTLBRK],%0 +signal2 PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] + CMP BX,%SIGMAX ; in range? + JBE OK1 +INVALID MOV [errno],EINVAL + MOV AX,-1 + POP BP + RETSEG +OK1 ADD BX,BX ; index table + MOV AX,[BP][%PARM2] + XCHG AX,[BX][_SIGTBL] ; save pointer & return previous + CMP BX,SIGINT*2 + JZ FIXINT23 + CMP BX,SIGFPE*2 + JZ FIX8087 +EXIT POP BP + RETSEG +FIX8087 JMPS EXIT ; +; +; Setting vector for control C +; +FIXINT23 MOV AL,%[CTLBRK] + MOV %[KEEP23],AL + CMP [OLD23S],0 + JNZ EXIT + CMP [OLD23O],0 + JNZ EXIT + PUSH AX + MOV AX,>3523 ; Read prior vector + INT >21 + MOV [OLD23S],ES + MOV [OLD23O],BX + MOV DX,INT23 + PUSH DS + MOV AX,CS + MOV DS,AX + MOV AX,>2523 ; Set new interrupt + INT >21 + POP AX + MOV DS,AX + SEGCS + MOV [INT23DS],AX + POP AX + JMPS EXIT +_signal_ MOV %[CTLBRK],%1 + JMP signal2 +; +; Enter from interrupt >23 (control C) +; +INT23 PUSHF + STI + PUSH BX + PUSH AX + PUSH DS + MOV AX,SS + MOV DS,AX + MOV BX,_SIGTBL + MOV AX,[BX][%SIGINT*2] + CMP AX,0 + JZ DEFAULT + CMP AX,1 + JZ IGNORE + XOR AX,AX + XCHG AX,[BX][%SIGINT*2] + CMP %[KEEP23],%0 + JZ SAVEREG + MOV [BX][%SIGINT*2],AX +SAVEREG MOV BX,AX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH BP + PUSH ES + MOV AX,SS + MOV DS,AX + MOV AX,SIGINT + PUSH AX + CALLSEG [BX] + INC SP + INC SP + POP ES + POP BP + POP DI + POP SI + POP DX + POP CX + CMP %[KEEP23],%0 + JZ IGNORE + TEST AX,AX + JZ DEFAULT +IGNORE POP DS + POP AX + POP BX + POPF + CLC + RETFAR +DEFAULT POP DS + POP AX + POP BX + POPF + STC + RETFAR +INT23DS DW 0-0 +; + DORG 0 +OLD23O DW 0 +OLD23S DW 0 +KEEP23 DB 0 +CTLBRK DB 0 + END +; + IDT gsignal + DEF gsignal + FREF raise +gsignal JMPFAR raise + END +; +; +; Raise - cause a signal +; +; int raise(sig) +; int sig; +; + IDT raise + DEF raise + DREF _SIGTBL + DREF errno + FREF _exit +SIGMAX EQU 8 +SIGINT EQU 2 +SIGFPE EQU 8 +raise PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] + CMP BX,%SIGMAX ; in range? + JBE OK1 +INVALID MOV [errno],EINVAL + MOV AX,-1 + POP BP + RETSEG +OK1 ADD BX,BX ; index table + MOV AX,0 + XCHG AX,[BX][_SIGTBL] ; save pointer & return previous +; CMP BX,SIGINT*2 +; JZ CALL23 +; CMP BX,SIGFPE*2 +; JZ CALL87 + CMP AX,0 + JZ DFLT + CMP AX,1 + JZ IGNORE + PUSH [BP][%PARM1] + MOV BX,AX + CALLSEG [BX] + ADD SP,%2 +EXIT XOR AX,AX + POP BP + RETSEG +IGNORE MOV [BX][_SIGTBL],1 + JMPS EXIT +DFLT MOV AX,[BP][%PARM1] + PUSH AX + CALLFAR _exit + POP AX +; MOV AH,>4C +; INT >21 + JMPS EXIT + END +; + IDT _SIGTBL + DDEF _SIGTBL + DORG 0 +_SIGTBL DW 0 + DW 1 ; 1 = sigabrt + DW 0 ; 2 = sigint + DW 0 ; 3 = sigill + DW 0 + DW 0 + DW 0 ; 6 = sigsegv + DW 0 ; 7 = sigterm + DW 1 ; 8 = sigfpe + END +; +; +; harderr - establish interrupt 24 handler +; +; void harderr(fptr) +; int (*fptr)() +; + IDT harderr + DEF harderr + LDEF hardresume + DEF hardretn +harderr PUSH BP + MOV BP,SP + MOV AX,DS + SEGCS + MOV [INT24DS],AX + MOV AX,[BP][PARM1] + MOV [INT24V],AX + MOV DX,INT24 + PUSH DS + MOV AX,CS + MOV DS,AX + MOV AX,>2524 ; Set new interrupt + INT >21 + POP AX + MOV DS,AX + POP BP + RETFAR +INT24DS DW 0-0 +; +; Enter from interrupt >24 (control C) +; +INT24 STI + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH BP + PUSH DS + PUSH ES + SEGCS + MOV AX,[INT24DS] + MOV DS,AX + MOV [INT24SP],SP + PUSH SI ; arguments to user function + PUSH BP + PUSH AX + PUSH DI + MOV BX,[INT24V] + CALLSEG [BX] + ADD SP,%8 +EXIT MOV [INT24SP],0 + POP DX + MOV ES,DX + POP DX + MOV DS,DX + POP BP + POP DI + POP SI + POP DX + POP CX + POP BX + IRET +; +hardresu CMP [INT24SP],0 + JZ NOT24 + MOV BP,SP + MOV AX,[BP][%PARM1-2] + MOV SP,[INT24SP] + JMPS EXIT +NOT24 MOV AX,-1 + RETSEG +; +hardretn CMP [INT24SP],0 + JZ NOT24 + MOV BP,SP + MOV AX,[BP][%PARM1-2] + MOV SP,[INT24SP] + JMPS EXIT +; + DORG 0 +INT24SP DW 0 +INT24V DW 0 + END diff --git a/Mix Power C v1/SORT.C b/Mix Power C v1/SORT.C new file mode 100644 index 0000000..6c6280a --- /dev/null +++ b/Mix Power C v1/SORT.C @@ -0,0 +1,104 @@ +/* Searching and sorting */ +/* Copyright (c) Mix Software 1988 */ + +char *bsearch(key, base, num, width, compare) + char *key; /* search key */ + char *base; /* start of array */ + unsigned num; /* number of elements */ + unsigned width; /* size of an element */ + int (*compare)(); /* function to compare two elements */ +{ + char *here; + int cmp; + int i, j, k; + + i = 0; + j = num-1; + do { + k = (j+i)>>1; + here = base + width*k; + cmp = (*compare)(key,here); + if (cmp == 0) { /* found - now scan down for first */ + while ((here > base) && ((*compare)(key,here-width) == 0)) + here -= width; + return here; + } + if (cmp < 0) j = k-1; else i=k+1; + } + while (j >= i); + + return NULL; +} /* bsearch */ + +/* ------------------------------------------------------------ */ + +void qsort(base, num, width, compare) + char *base; /* start of array */ + unsigned num; /* number of elements */ + unsigned width; /* size of an element */ + int (*compare)(); /* function to compare two elements */ +{ + char *key; + char *first, *last, *max; + int memswap(); + + last = max = base+(num-1)*width; + first = base; + key = base + width*(num >> 1); + do { + while ((*compare)(first,key,width) < 0) first += width; + while ((*compare)(key,last,width) < 0) last -= width; + if (first <= last) { + if (first != last) { + memswap(first,last,width); + if (first == key) key = last; + else if (last == key) key = first; + } + first += width; + last -= width; + } + } + while (first <= last); + if (base < last) qsort(base,(last-base)/width+1,width,compare); + if (first < max) qsort(first,(max-first)/width+1,width,compare); + } + +/* ------------------------------------------------------------ */ + +char *lsearch(key, base, num, width, compare) + char *key; /* search key */ + char *base; /* start of array */ + unsigned *num; /* number of elements */ + unsigned width; /* size of an element */ + int (*compare)(); /* function to compare two elements */ +{ + char *result; + result = lfind(key,base,num,width,compare); + if (result == NULL) { + result = base+(*num)*width; + memcpy(result,key,width); + (*num)++; + } + return result; +} /* lsearch */ + +/* ------------------------------------------------------------ */ + +char *lfind(key, base, num, width, compare) + char *key; /* search key */ + char *base; /* start of array */ + unsigned *num; /* number of elements */ + unsigned width; /* size of an element */ + int (*compare)(); /* function to compare two elements */ +{ + unsigned number = *num; + while (number != 0) { + if ((*compare)(key,base) == 0) return base; + else { + if (--number == 0) return NULL; + else base += width; + } + } + return NULL; +} /* lfind */ + diff --git a/Mix Power C v1/SOUND.ASM b/Mix Power C v1/SOUND.ASM new file mode 100644 index 0000000..9ccf27b --- /dev/null +++ b/Mix Power C v1/SOUND.ASM @@ -0,0 +1,62 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------------ +; + idt sound + def sound +; +; sound(int freq, int duration) +; + +ROMDATA EQU 40H +TIMER_LOW EQU 6CH +TIMER EQU 40H +PORTB EQU 61H +; +freq EQU 6 +duration EQU freq+2 +; +sound push bp + mov bp,sp + mov cx,[bp][%duration] + mov bx,[bp][%freq] + cmp bx,0 + je LENGTH + mov ax,13532 + mov dx,18 + div bx + call BEEPER +LENGTH jcxz EXIT + mov bx,ROMDATA + mov ds,bx + mov bx,[TIMER_LOW] +TICKLOOP cmp bx,[TIMER_LOW] + je TICKLOOP + inc bx + loop TICKLOOP +EXIT xor ax,ax + call BEEPER + mov ax,ss + mov ds,ax + pop bp + retfar +; +BEEPER push ax + in al,PORTB + and al,0FCH ;mask off lower 3 bits + out PORTB,al + mov al,0B6H + out TIMER+3,al + pop ax + cmp ax,0 + je DONE + out TIMER+2,al + mov al,ah + out TIMER+2,al + in al,PORTB + or al,3 + out PORTB,al +DONE ret +; + END diff --git a/Mix Power C v1/STACK.ASM b/Mix Power C v1/STACK.ASM new file mode 100644 index 0000000..cb3ca7a --- /dev/null +++ b/Mix Power C v1/STACK.ASM @@ -0,0 +1,75 @@ +; +; Copyright (c) Mix Software 1988 +; +; -------------------------------------------------- +; alloca - allocate from the stack +; returns null if not enough memory +; char *_alloca(size) +; unsigned size; +; -------------------------------------------------- +; + IDT alloca + DEF alloca + DREF $$LIMIT + DREF $$MAXS +; +alloca MOV SI,SP + MOV AX,[SI][%PARM1-2] ; Requested size + SUB SI,[$$LIMIT] ; Stack boundary + CMP SI,AX + JB NOSPACE + POP BX ; Remove return + POP CX + POP DX ; argument + SUB SP,AX + MOV AX,SP + DEC AX + AND AX,>FFFE + MOV SP,AX + PUSH DX + PUSH CX + PUSH BX + CMP AX,[$$MAXS] + JAE EXIT + MOV [$$MAXS],AX +EXIT RETSEG +NOSPACE XOR AX,AX + RETSEG + END +; +; -------------------------------------------------- +; stackavail - return available stack +; returns amount of stack space available +; unsigned stackavail() +; -------------------------------------------------- +; + IDT stackava + IF LONGNAME + LDEF stackavail + ENDIF + IF SHORTNAM + DEF stackava + ENDIF + DREF $$LIMIT + DREF $$MAXS +; +stackavail MOV AX,SP + SUB AX,[$$LIMIT] ; Stack boundary + RETSEG + END +; +; -------------------------------------------------- +; stacksiz - return available stack +; returns amount of stack space available +; unsigned stacksiz() +; -------------------------------------------------- +; + IDT stacksiz + DEF stacksiz + DREF $$LIMIT + DREF $$MAXS +; +stacksiz MOV AX,SP + SUB AX,[$$LIMIT] ; Stack boundary + RETSEG + END diff --git a/Mix Power C v1/STAT.H b/Mix Power C v1/STAT.H new file mode 100644 index 0000000..30e627f --- /dev/null +++ b/Mix Power C v1/STAT.H @@ -0,0 +1,37 @@ +/*$no list*//*$no trace <<< stat.h >>> */ +/* Copyright (c) Mix Software 1988 */ + +#define dev_t short +#define ino_t unsigned short +#define off_t long +#define time_t long + +#define S_IFMT 0xf000 /* type mask */ +#define S_IFDIR 0x4000 +#define S_IFCHR 0x2000 +#define S_IFREG 0x8000 +#define S_IREAD 0x0100 +#define S_IWRITE 0x0080 +#define S_IEXEC 0x0040 + +#if !defined(stat) +struct stat +{ + dev_t st_dev; + ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; +#endif + +int fstat(int fd, struct stat *buffer); +int stat(char *pathname, struct stat *buffer); + +/*$list*//*$trace <<< stat.h >>> */ diff --git a/Mix Power C v1/STDARG.H b/Mix Power C v1/STDARG.H new file mode 100644 index 0000000..276628e --- /dev/null +++ b/Mix Power C v1/STDARG.H @@ -0,0 +1,12 @@ +/*$no list*//*$no trace <<< stdarg.h >>> */ +/* Copyright (c) Mix Software 1988 */ + +#if !defined(va_list) +typedef char *va_list; +#endif + +#define va_start(argptr, lastarg) argptr = (va_list) &lastarg + sizeof(lastarg) +#define va_arg(argptr, type) (*(((type*)argptr)++)) +#define va_end(argptr) argptr = 0 + +/*$list*//*$trace <<< stdarg.h >>> */ diff --git a/Mix Power C v1/STDIO.H b/Mix Power C v1/STDIO.H new file mode 100644 index 0000000..9246af8 --- /dev/null +++ b/Mix Power C v1/STDIO.H @@ -0,0 +1,102 @@ +/*$no list*//*$no trace <<< stdio.h >>> */ +/* Copyright (c) Mix Software 1988 */ + +#define size_t unsigned + +#if !defined(va_list) +typedef char *va_list; +#endif + +#define _IOFBF 0 +#define _IOLBF 0x40 +#define _IONBF 0x04 +#define BUFSIZ 512 +#define EOF -1 +#define fpos_t long +#define L_tmpnam 13 +#define NULL 0 +#define OPEN_MAX 20 +#define SEEK_CUR 1 +#define SEEK_END 2 +#define SEEK_SET 0 +#define stderr _iob[2] +#define stdin _iob[0] +#define stdout _iob[1] +#define TMP_MAX 32767 + +#if !defined(FILE) +typedef struct { + char file[32]; + int fd; +} FILE; +extern FILE *_iob[OPEN_MAX]; +#endif + +#define getchar() getc(stdin) +#define putchar(c) putc(c,stdout) + +void clearerr(FILE *fp); +int fclose(FILE *fp); +int feof(FILE *fp); +int ferror(FILE *fp); +int fflush(FILE *fp); +int fgetc(FILE *fp); +int fgetpos(FILE *fp, fpos_t *pos); +char *fgets(char *buffer, int n, FILE *fp); +FILE *fopen(char *filename, char *access); +int fprintf(FILE *fp, char *format, ...); +int fputc(int c, FILE *fp); +int fputs(char *string, FILE *fp); +size_t fread(void *buffer, size_t size, size_t number, FILE *fp); +FILE *freopen(char *filename, char *mode, FILE *fp); +int fscanf(FILE *fp, char *fs, ...); +int fseek(FILE *fp, long offset, int origin); +int fsetpos(FILE *fp, fpos_t *pos); +long ftell(FILE *fp); +size_t fwrite(void *buffer, size_t size, size_t number, FILE *fp); +int getc(FILE *fp); +char *gets(char *buffer); +void perror(char *string); +int printf(char *format, ...); +int putc(int c, FILE *fp); +int puts(char *string); +int remove(char *filename); +int rename(char *oldname, char *newname); +void rewind(FILE *fp); +int scanf(char *format, ...); +void setbuf(FILE *fp, char *bufptr); +int setvbuf(FILE *fp, char *bufptr, int buftype, size_t bufsize); +int sprintf(char *s, char *format, ...); +int sscanf(char *s, char *format, ...); +FILE *tmpfile(void); +char *tmpnam(char *buffer); +int ungetc(int c, FILE *fp); +int vfprintf(FILE *fp, char *format, va_list arglist); +int vprintf(char *format, va_list arglist); +int vsprintf(char *s, char *format, va_list arglist); + +#if !defined(ANSI) +#define stdprn _iob[4] +#define stdaux _iob[3] +#define P_tmpdir "\\TMP" + +#if !defined(STRING) +typedef struct { + int length; + char string[80]; +} STRING; +#endif + +int fcloseall(void); +FILE *fdopen(int fd, char *mode); +int fileno(FILE *fp); +int flushall(void); +int fputchar(int c); +int getw(FILE *fp); +int putw(int word, FILE *fp); +int rmtmp(void); +char *tempnam(char *dir, char *prename); +int unlink(char *filename); +#endif /* ANSI */ + +/*$list*//*$trace <<< stdio.h >>> */ diff --git a/Mix Power C v1/STDLIB b/Mix Power C v1/STDLIB new file mode 100644 index 0000000..80fa261 --- /dev/null +++ b/Mix Power C v1/STDLIB @@ -0,0 +1,6 @@ + +stdlib bios.c close.c rand.c convert.c envir.c error.c \ + exit.c exitmsg.c file.c gets.c init.c \ + strcoll.c memory.c msdos.c \ + open.c puts.c setbuf.c sort.c stdlib.c ungetc.c \ + stdlib.h diff --git a/Mix Power C v1/STDLIB.C b/Mix Power C v1/STDLIB.C new file mode 100644 index 0000000..9280831 --- /dev/null +++ b/Mix Power C v1/STDLIB.C @@ -0,0 +1,22 @@ +/* Main c file for pclib, includes other c soucre files */ +/* Copyright (c) Mix Software 1988 */ + +#include "std_lib.h" +#include "init.c" +#include "convert.c" +#include "rand.c" +#include "gets.c" +#include "puts.c" +#include "open.c" +#include "exit.c" +#include "setbuf.c" +#include "file.c" +#include "close.c" +#include "sort.c" +#include "strcoll.c" +#include "memory.c" +#include "msdos.c" +#include "ungetc.c" +#include "envir.c" +#include "bios.c" + diff --git a/Mix Power C v1/STDLIB2 b/Mix Power C v1/STDLIB2 new file mode 100644 index 0000000..0f3b8ed --- /dev/null +++ b/Mix Power C v1/STDLIB2 @@ -0,0 +1,3 @@ +stdlib2 stdlib.h fstat.c dup.c dstring.c time.c arith.c\ + tempfile.c chain.c flags.c bessel.c locking.c perror.c\ + allocmem.c findfirs.c dosetc.c etc.c diff --git a/Mix Power C v1/STDLIB2.C b/Mix Power C v1/STDLIB2.C new file mode 100644 index 0000000..24e8d9d --- /dev/null +++ b/Mix Power C v1/STDLIB2.C @@ -0,0 +1,20 @@ +/* Main c file for pclib2, includes other c soucre files */ +/* Copyright (c) Mix Software 1988 */ + +#include "std_lib.h" +#include "fstat.c" +#include "dup.c" +#include "dstring.c" +#include "time.c" +#include "bessel.c" +#include "arith.c" +#include "tempfile.c" +#include "chain.c" +#include "flags.c" +#include "locking.c" +#include "perror.c" +#include "allocmem.c" +#include "findfirs.c" +#include "dosetc.c" +#include "etc.c" + diff --git a/Mix Power C v1/STD_LIB.H b/Mix Power C v1/STD_LIB.H new file mode 100644 index 0000000..f4823ae --- /dev/null +++ b/Mix Power C v1/STD_LIB.H @@ -0,0 +1,278 @@ +/*$no list*//*$no trace <<< std_lib.h >>> */ +/* Copyright (c) Mix Software 1988 */ +/* Header for compiling the standard libraries */ + +#define V_ASM +#define MAXFILES 20 +#define BUFSIZ 512 +#define EOF -1 +#define NULL 0 +#define stdin _iob[0] +#define stdout _iob[1] +#define stderr _iob[2] +#define stdprn _iob[3] +#define stdaux _iob[4] + +#define size_t unsigned + +#include "fdb.h" + +typedef struct { + fdb file; /* file descriptor */ + int fd; /* file descriptor number */ +} FILE; + +extern FILE *_iob[MAXFILES]; + +typedef struct { + int length; + char string[80]; +} STRING; + +typedef int (*onexit_t)(); +typedef int (*atexit_t)(); + +#define P_tmpdir "\\TMP" +#define L_tmpnam sizeof(P_tmpdir)+8 + +#define _IOFBF 0 +#define _IOLBF 0x40 +#define _IONBF 0x04 + +/***************************************************************/ + +#define NEWLINE '\l' +#define RETURN '\r' +#define CTLZ '\x1A' +#define MAXARGS 20 +#define FALSE 0 +#define TRUE 1 +#define FILEERR 0x89 + +/*********************** fcntl.h ******************************/ + +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_APPEND 0x0008 +#define O_CREAT 0x0100 +#define O_TRUNC 0x0200 +#define O_EXCL 0x0400 +#define O_TEXT 0x4000 +#define O_BINARY 0x8000 + +#define O_MODEMASK 0x00F3 + +/***************** Miscellaneous Definitions *******************/ + +typedef int jmp_buf[32]; + + struct WORDREGS { + unsigned int ax; + unsigned int bx; + unsigned int cx; + unsigned int dx; + unsigned int si; + unsigned int di; + unsigned int cflag; + }; + struct BYTEREGS { + unsigned char al, ah; + unsigned char bl, bh; + unsigned char cl, ch; + unsigned char dl, dh; + }; + union REGS { + struct WORDREGS x; + struct WORDREGS word; + struct BYTEREGS h; + struct BYTEREGS byte; + }; + + struct SREGS { + unsigned int es; + unsigned int cs; + unsigned int ss; + unsigned int ds; + }; + +struct DOSERROR { + int exterror; + char class; + char action; + char locus; + }; + +struct date { + int da_year; + char da_day; + char da_mon; + }; + +struct time { + unsigned char ti_min; + unsigned char ti_hour; + unsigned char ti_hund; + unsigned char ti_sec; + }; + +struct dfree { + unsigned df_avail; /* available clusters */ + unsigned df_total; /* total clusters */ + unsigned df_bsec; /* bytes per sector */ + unsigned df_sclus; /* sectors per cluster */ + }; + +struct fatinfo { + char fi_sclus; /* Sectors per cluster */ + char fi_fatid; /* identification byte */ + int fi_nclus; /* number of clusters */ + int fi_bysec; /* bytes per sector */ + }; + +struct ftime { + unsigned ft_tsec : 5; /* two seconds */ + unsigned ft_min : 6; /* minutes */ + unsigned ft_hour : 5; /* hours */ + unsigned ft_day : 5; /* day of month */ + unsigned ft_month: 4; /* month */ + unsigned ft_year : 7; /* year - 1980 */ + }; + +#define clock_t long + +/**************************************************************/ +/* math.h */ + +struct complex { + double x; + double y; + }; + +struct exception { + int type; /* type of exception */ + char *name; /* name of function */ + double arg1; /* first argument to function */ + double arg2; /* second argument to function */ + double retval; /* value to be returned if error is not fatal */ + }; + +/* exception types */ + +#define DOMAIN 1 /* not in domain of function */ +#define SING 2 /* singularity (function not defined) */ +#define OVERFLOW 3 /* result too large */ +#define UNDERFLOW 4 /* result too small */ +#define TLOSS 5 /* total loss of precision */ +#define PLOSS 6 /* partial loss of precision */ + +/**************************************************************/ +/* signal.h */ + +#define SIGABRT 1 +#define SIGINT 2 +#define SIGFPE 8 + +/**************************************************************/ +/* time.h */ + +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; + }; +typedef long time_t; + +/**************************************************************/ +/* timeb.h */ + +struct timeb { + time_t time; + int millitm; + int timezone; + int dstflag; + }; + +/**************************************************************/ +/* exec and spawn */ + +extern int _p_overlay; +#define P_WAIT 0 +#define P_NOWAIT 1 +#define P_OVERLAY _p_overlay + +/* #define S_IREAD 0x0100 */ +/* #define S_IWRITE 0x0080 */ + +/**************************************************************/ +/* stat.h - structure for stat() and fstat() */ + +struct statstr { + short st_dev; + unsigned short st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + short st_rdev; + long st_size; + long st_atime; + long st_mtime; + long st_ctime; + }; + +#define S_IFMT 0xf000 /* type mask */ +#define S_IFDIR 0x4000 +#define S_IFCHR 0x2000 +#define S_IFREG 0x8000 +#define S_IREAD 0x0100 +#define S_IWRITE 0x0080 +#define S_IEXEC 0x0040 + +/**************************************************************/ +/* errors */ + +#define EZERO 0 +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EUCLEAN 35 +#define EDEADLOCK 36 +/*$list*//*$trace <<< std_lib.h >>> */ diff --git a/Mix Power C v1/STRCOLL.C b/Mix Power C v1/STRCOLL.C new file mode 100644 index 0000000..92f92a0 --- /dev/null +++ b/Mix Power C v1/STRCOLL.C @@ -0,0 +1,23 @@ +/* Copyright (c) Mix Software 1988 */ + +/* + Convert a string for collating sequence. + The string is converted to a form suitable for comparison + by strcmp or memcmp. The resulting string is at most twice + as long as the original string. For standard ascii, no + conversion is performed. Conversion may be desireable when + European characters are used and you wish to collate accented + characters with their unaccented counterparts. + */ + +size_t strcoll(to, maxsize, from) + char *to; + size_t maxsize; + char *from; +{ + int size; + size = strlen(from); + if (size >= maxsize) return 0; + memcpy(to,from,size); + return size; + } diff --git a/Mix Power C v1/STRING.ASM b/Mix Power C v1/STRING.ASM new file mode 100644 index 0000000..807491d --- /dev/null +++ b/Mix Power C v1/STRING.ASM @@ -0,0 +1,1002 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; strcat(string1, string2) - concatenate strings +; strncat(string1, string2, n) - concatenate strings +; ------------------------------------------------------- +; + IDT strcat + DEF strcat + DEF strncat + IF UPPER + DEF STRCAT + DEF STRNCAT + ENDIF +; +strcat equ $ +STRCAT PUSH BP + MOV BP,SP + MOV CX,-1 ; no limit on length +CAT MOV DI,[BP][%PARM1] + MOV SI,[BP][%PARM2] + MOV AX,DS + MOV ES,AX + CLD + XOR AX,AX + PUSH CX + MOV CX,-1 + REPNZ ; search for zero on string 1 + SCASB + POP CX + DEC DI ; overwrite the '\0' terminator +COPY LODSB + STOSB + TEST AL,AL + JZ DONE + LOOP COPY + MOV %[DI],%0 +DONE MOV AX,[BP][%PARM1] ; result is pointer to string1 + POP BP + RETSEG +strncat equ $ +STRNCAT PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM3] ; cx = limit on length + JCXZ DONE + JMPS CAT + END +; +; ------------------------------------------------------- +; strchr(string1, c) - search string for character +; ------------------------------------------------------- +; char *strchr(s, c) +; char *s; +; int c; +; +; Purpose: Searches for first occurrence of c in s +; Returns: Pointer to c if s contains c +; NULL if s does not contain c +; +; + IDT strchr + DEF strchr + IF UPPER + DEF STRCHR + ENDIF +; +strchr equ $ +STRCHR PUSH BP + MOV BP,SP + MOV AX,DS + MOV ES,AX + MOV DI,[BP][%PARM1] + MOV CX,-1 + XOR AL,AL + CLD + REPNZ + SCASB + NOT CX ; CX = length including '\0' + MOV DI,[BP][%PARM1] + MOV AL,[BP][%PARM2] + REPNZ + SCASB + JNZ NOFIND + DEC DI + MOV AX,DI + POP BP + RETSEG +NOFIND XOR AX,AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; index(string1, c) - search string for character +; ------------------------------------------------------- +; char *index(s, c) +; char *s; +; int c; +; +; Purpose: Searches for first occurrence of c in s +; Returns: Pointer to c if s contains c +; NULL if s does not contain c +; +; + IDT index + IF UPPER + DEF INDEX + ENDIF + DEF index +; +index equ $ +INDEX PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DX,[BP][%PARM2] + CLD +CMP LODSB + CMP AL,DL + JZ FOUND + TEST AL,AL + JNZ CMP + XOR AX,AX ; Not found + POP BP + RETSEG +FOUND DEC SI ; Return pointer to c + MOV AX,SI + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; strrchr(string, c) - search string for last occurance of c +; ------------------------------------------------------- +; + IDT strrchr + DEF strrchr + IF UPPER + DEF STRRCHR + ENDIF +; +strrchr equ $ +STRRCHR PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + CLD + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; find end of string + SCASB + NOT CX + STD + MOV DI,[BP][%PARM1] + ADD DI,CX + DEC DI + MOV AX,[BP][%PARM2] + REPNZ + SCASB + CLD + JZ FOUND + XOR AX,AX + POP BP + RETSEG +FOUND INC DI ; Return pointer to c + MOV AX,DI + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; rindex(string, c) - search string for last occurance of c +; ------------------------------------------------------- +; + IDT rindex + IF UPPER + DEF RINDEX + ENDIF + DEF rindex +; +rindex equ $ +RINDEX PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + CLD + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; find end of string + SCASB + NOT CX + STD + MOV DI,[BP][%PARM1] + ADD DI,CX + DEC DI + MOV AX,[BP][%PARM2] + REPNZ + SCASB + CLD + JZ FOUND + XOR AX,AX + POP BP + RETSEG +FOUND INC DI ; Return pointer to c + MOV AX,DI + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; strcmp(string1, string2) - compare strings +; strncmp(string1, string2,n) - compare strings +; ------------------------------------------------------- +; + IDT strncmp + DEF strncmp + IF UPPER + DEF STRNCMP + ENDIF +; +strncmp equ $ +STRNCMP MOV BX,SP + MOV CX,[BX][%PARM3-2] + JCXZ EQUAL + MOV SI,[BX][%PARM1-2] + MOV DI,[BX][%PARM2-2] + MOV AX,DS + MOV ES,AX + MOV DX,DI + XOR AX,AX + MOV BX,CX + REPNZ ; search for zero on string 1 + SCASB + NEG CX + ADD CX,BX + MOV DI,DX + REPZ + CMPSB + MOV AL,%[SI][%-1] + SUB AL,%[DI][%-1] + CBW + RETSEG +EQUAL XOR AX,AX + RETSEG + END +; + IDT strcmp + DEF strcmp + IF UPPER + DEF STRCMP + ENDIF +strcmp equ $ +STRCMP MOV BX,SP + MOV SI,[BX][%PARM1-2] + MOV DI,[BX][%PARM2-2] + MOV AX,DS + MOV ES,AX + CLD + MOV DX,DI + XOR AX,AX + MOV CX,-1 + REPNZ ; search for zero on string 1 + SCASB + INC CX + NEG CX + MOV DI,DX + REPZ + CMPSB + MOV AL,%[SI][%-1] + SUB AL,%[DI][%-1] + CBW + RETSEG + END +; +; ------------------------------------------------------- +; strcmpi(string1, string2) - compare strings, ignore case +; ------------------------------------------------------- +; + IDT strcmpi + DEF strcmpi + DEF stricmp + DEF strnicmp + IF UPPER + DEF STRCMPI + DEF STRICMP + DEF STRNICMP + ENDIF +; +strcmpi EQU $ +stricmp EQU $ +STRICMP EQU $ +STRCMPI PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] + MOV CX,-1 +CMP LODSB + MOV BL,[DI] + INC DI + TEST AL,AL ; end of string1? + JZ END1 + TEST BL,BL + JZ END1 + CMP AL,BL + JNZ NOTEQUAL +NEXT LOOP CMP +EQUAL XOR AX,AX ; strings are equal + POP BP + RETSEG +END1 XOR AH,AH ; end of both? + XOR BH,BH + SUB AX,BX + POP BP + RETSEG +NOTEQUAL CMP AL,'A' + JB NOTAL + CMP AL,'Z' + JA NOTAL + ADD AL,'a'-'A' +NOTAL CMP BL,'A' + JB NOTBL + CMP BL,'Z' + JA NOTBL + ADD BL,'a'-'A' +NOTBL CMP AL,BL + JZ NEXT + MOV AL,[SI][%-1] + MOV BL,[DI][%-1] + JMPS END1 +strnicmp equ $ +STRNICMP PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] + MOV CX,[BP][%PARM3] + JCXZ EQUAL + JMPS CMP + END +; +; ------------------------------------------------------- +; strcpy(string1, string2) - copy strings +; ------------------------------------------------------- +; + IDT strcpy + IF UPPER + DEF STRCPY + ENDIF + DEF strcpy +; +strcpy equ $ +STRCPY MOV BX,SP + MOV SI,[BX][%PARM2-2] + MOV DI,SI + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AX,AX + CLD + REPNZ + SCASB + NOT CX + MOV DI,[BX][%PARM1-2] + MOV AX,DI + REP + MOVSB + RETSEG + END +; + IDT stpcpy + DEF stpcpy +stpcpy MOV BX,SP + MOV SI,[BX][%PARM2-2] + MOV DI,SI + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AX,AX + CLD + REPNZ + SCASB + NOT CX + MOV DI,[BX][%PARM1-2] + MOV AX,DI + ADD AX,CX + DEC AX + REP + MOVSB + RETSEG + END +; +; ------------------------------------------------------- +; strncpy(string1, string2, n) - copy string +; copy exactly n characters from string2 to string1 +; if n < length of string2, no null is appended +; if n > length of string2, string1 padded with '\0' +; ------------------------------------------------------- +; + IDT strncpy + DEF strncpy + IF UPPER + DEF STRNCPY + ENDIF +; +strncpy equ $ +STRNCPY PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + MOV SI,[BP][%PARM2] + MOV CX,[BP][%PARM3] + JCXZ DONE + MOV AX,DS + MOV ES,AX + CLD +COPY LODSB + STOSB + TEST AL,AL + JZ ENDSTR + LOOP COPY +DONE MOV AX,[BP][%PARM1] + POP BP + RETSEG +ENDSTR DEC CX + JCXZ DONE + XOR AX,AX + REP + STOSB + JMPS DONE + END +; +; ------------------------------------------------------- +; int strspn(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches from beginning of s1 +; until a character NOT in s2 is found +; Returns: Length of string segment in s1 consisting +; entirely of characters contained in s2 +; ------------------------------------------------------- +; + IDT strspn + DEF strspn + IF UPPER + DEF STRSPN + ENDIF +; +strspn equ $ +STRSPN PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NEG CX + DEC CX + MOV BX,CX + XOR DX,DX ; initial index + JCXZ DONE +NEXTCH LODSB + TEST AL,AL + JZ DONE + MOV CX,BX + MOV DI,[BP][%PARM2] + REPNZ + SCASB + JNZ DONE + INC DX + JMPS NEXTCH +DONE MOV AX,DX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; int strcspn(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches from beginning of s1 +; until a character in s2 is found +; Returns: Length of string segment in s1 consisting +; entirely of characters NOT contained in s2 +; ------------------------------------------------------- +; + IDT strcspn + IF UPPER + DEF STRCSPN + ENDIF + DEF strcspn +; +strcspn equ $ +STRCSPN PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NOT CX + MOV BX,CX + XOR DX,DX ; initial index + JCXZ DONE +NEXTCH LODSB + TEST AL,AL + JZ DONE + MOV CX,BX + MOV DI,[BP][%PARM2] + REPNZ + SCASB + JZ DONE + INC DX + JMPS NEXTCH +DONE MOV AX,DX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; int strpbrk(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches from beginning of s1 +; until a character in s2 is found +; Returns: pointer to first character found +; ------------------------------------------------------- +; + IDT strpbrk + IF UPPER + DEF STRPBRK + ENDIF + DEF strpbrk +; +strpbrk equ $ +STRPBRK PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] + MOV DI,[BP][%PARM2] + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NOT CX + MOV BX,CX + JCXZ DONE +NEXTCH LODSB + TEST AL,AL + JZ NONE + MOV CX,BX + MOV DI,[BP][%PARM2] + REPNZ + SCASB + JZ DONE + JMPS NEXTCH +DONE DEC SI + MOV AX,SI + POP BP + RETSEG +NONE XOR AX,AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; strrev(string) - reverse a string +; ------------------------------------------------------- +; + IDT strrev + DEF strrev + IF UPPER + DEF STRREV + ENDIF +; +strrev equ $ +STRREV PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + CLD + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; find end of string + SCASB + SUB DI,%2 + MOV SI,[BP][%PARM1] +REV CMP SI,DI + JAE DONE + MOV AL,%[DI] + XCHG AL,%[SI] + MOV %[DI],AL + INC SI + DEC DI + JMPS REV +DONE MOV AX,[BP][%PARM1] + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; strsave(string) - copy to heap, NULL if no space +; strdup(string) - copy to heap, NULL if no space +; ------------------------------------------------------- +; + IDT strdup + DEF strdup + DEF strsave + IF UPPER + DEF STRDUP + DEF STRSAVE + ENDIF + FREF malloc +strsave equ $ +strdup equ $ +STRSAVE EQU $ +STRDUP PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + TEST DI,DI + JZ NULL + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ ; get length of string2 + SCASB + NEG CX + PUSH CX + PUSH CX + CALLFAR malloc + ADD SP,%2 + POP CX + TEST AX,AX ; Null? + JZ DONE + MOV DI,AX + MOV SI,[BP][%PARM1] + REP + MOVSB +DONE POP BP + RETSEG +NULL XOR AX,AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; strlwr(string) - convert all uppercase letters in +; string to lower case +; ------------------------------------------------------- +; + IDT strlwr + DEF strlwr + IF UPPER + DEF STRLWR + ENDIF +; +strlwr equ $ +STRLWR PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] +CHECK MOV AL,%[SI] + TEST AL,AL + JZ DONE + CMP AL,'A' + JB OK + CMP AL,'Z' + JA OK + ADD AL,'a'-'A' + MOV %[SI],AL +OK INC SI + JMPS CHECK +DONE MOV AX,[BP][%PARM1] + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; strupr(string) - convert all lower case letters in +; string to upper case +; ------------------------------------------------------- +; + IDT strupr + DEF strupr + IF UPPER + DEF STRUPR + ENDIF +; +strupr equ $ +STRUPR PUSH BP + MOV BP,SP + MOV SI,[BP][%PARM1] +CHECK MOV AL,%[SI] + TEST AL,AL + JZ DONE + CMP AL,'a' + JB OK + CMP AL,'z' + JA OK + ADD AL,'A'-'a' + MOV %[SI],AL +OK INC SI + JMPS CHECK +DONE MOV AX,[BP][%PARM1] + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; strset(string,c) - set all but '\0' to c +; strnset(string,c,n) - set up to n or '\0' to c +; ------------------------------------------------------- +; + IDT strset + DEF strset + DEF strnset + IF UPPER + DEF STRSET + DEF STRNSET + ENDIF +; +strset equ $ +STRSET PUSH BP + MOV BP,SP + MOV CX,-1 ; no limit on length +SET MOV SI,[BP][%PARM1] + MOV BX,[BP][%PARM2] +NEXT MOV AL,%[SI] + TEST AL,AL + JZ DONE + MOV %[SI],BL + INC SI + LOOP NEXT +DONE MOV AX,[BP][%PARM1] ; result is pointer to string1 + POP BP + RETSEG +strnset equ $ +STRNSET PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM3] ; cx = limit on length + JCXZ DONE + JMPS SET + END +; +; ------------------------------------------------------- +; int strlen(s) +; char *s; +; Purpose: Returns the length of the string, not +; including the NULL character +; ------------------------------------------------------- +; + IDT strlen + DEF strlen + IF UPPER + DEF STRLEN + ENDIF +; +strlen equ $ +STRLEN MOV BX,SP + MOV DI,[BX][%PARM1-2] + CMP DI,%0 + JZ NULL + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ + SCASB + NOT CX + DEC CX + MOV AX,CX + RETFAR +NULL XOR AX,AX + RETFAR + END +; +; ------------------------------------------------------- +; int strstr(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches s1 for the first occurrence +; of s2 +; Returns: pointer to substring if found, +; NULL if not found +; ------------------------------------------------------- +; + IDT strstr + DEF strstr + IF UPPER + DEF STRSTR + ENDIF +; +strstr equ $ +STRSTR PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM1] + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ + SCASB + NOT CX + DEC CX + MOV DX,CX ; DX is length of s1 + MOV DI,[BP][%PARM2] + MOV CX,-1 + REPNZ + SCASB + NOT CX + DEC CX ; CX is length of s2 + CMP CX,DX + JA NOFIND ; s2 is longer than s1 + MOV AX,[BP][%PARM1] ; initial s1 pointer + JCXZ FOUND ; length of s2 is zero + MOV BX,CX ; save s2 length + SUB DX,BX ; number of positions to try + INC DX +NEXTPOS MOV CX,BX ; length of s2 + MOV SI,[BP][%PARM2] ; start of s2 + MOV DI,AX ; current position in s1 + REPZ + CMPSB ; compare + JZ FOUND ; strings match + INC AX ; try next position + DEC DX + JNZ NEXTPOS +NOFIND XOR AX,AX +FOUND POP BP + RETSEG + END +; +; ------------------------------------------------------- +; int stristr(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches s1 for the first occurrence +; of s2 (case is ignored) +; Returns: pointer to substring if found, +; NULL if not found +; ------------------------------------------------------- +; + IDT stristr + DEF stristr + IF UPPER + DEF STRISTR + ENDIF +; +stristr equ $ +STRISTR PUSH BP + MOV BP,SP + SUB SP,%2 + MOV DI,[BP][%PARM1] + MOV AX,DS + MOV ES,AX + MOV CX,-1 + XOR AL,AL + CLD + REPNZ + SCASB + NOT CX + DEC CX + MOV DX,CX ; DX is length of s1 + MOV DI,[BP][%PARM2] + MOV CX,-1 + REPNZ + SCASB + NOT CX + DEC CX ; CX is length of s2 + CMP CX,DX + JA NOFIND ; s2 is longer than s1 + MOV AX,[BP][%PARM1] ; initial s1 pointer + JCXZ FOUND ; length of s2 is zero + MOV BX,CX ; save s2 length + SUB DX,BX ; number of positions to try + INC DX + MOV [BP][%-2],DX +NEXTPOS MOV CX,BX ; length of s2 + MOV SI,[BP][%PARM2] ; start of s2 + MOV DI,AX ; current position in s1 +COMP REPZ + CMPSB ; compare + JZ FOUND ; strings match + MOV DL,[SI][%-1] + MOV DH,[DI][%-1] + AND DX,>DFDF + CMP DL,DH + JNZ TRYNXT + CMP DL,'A' + JB TRYNXT + CMP DL,'Z' + JA TRYNXT + JCXZ FOUND + JMPS COMP +TRYNXT INC AX ; try next position + DEC [BP][%-2] + JNZ NEXTPOS +NOFIND XOR AX,AX +FOUND MOV SP,BP + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; char *strtok(s1, s2) +; char *s1, *s2; +; +; Purpose: Searches for the beginning of the next token +; in s1. A token is a sequence of one or more +; characters in s1 separated from the next token +; by a sequence of one or more characters contained +; in s2. S1 must point to a string of tokens for +; the first call to strtok. Subsequent calls +; can specify a NULL value for s1 to return the next +; token in the string. +; +; Returns: Pointer to next token in s1 +; NULL if there are no more tokens in s1 +; ------------------------------------------------------- +; + IDT strtok + IF UPPER + DEF STRTOK + ENDIF + DEF strtok +; + DORG 0 +STRPTR DW 0 + ORG $ +strtok equ $ +STRTOK PUSH BP + MOV BP,SP + MOV DI,[BP][%PARM2] + MOV AX,DS + MOV ES,AX + CLD + MOV CX,-1 + XOR AL,AL + REPNZ + SCASB ; Find length of s2 + NOT CX + JCXZ NOS2 ; Return null if s2 is empty + MOV DX,CX ; save length of s2 + MOV SI,[BP][%PARM1] + TEST SI,SI ; is s1 null? + JNZ NEXTCH + MOV SI,[STRPTR] + TEST SI,SI + JZ EMPTY ; no previous string +NEXTCH LODSB ; get s1 character + TEST AL,AL + JZ EMPTY ; end of s1 + MOV CX,DX + MOV DI,[BP][%PARM2] + REPNZ + SCASB ; check in delimiter set + JZ NEXTCH + MOV BX,SI ; address of first non-delimiter + DEC BX +TOKCH LODSB + TEST AL,AL + JZ ENDS1 + MOV CX,DX + MOV DI,[BP][%PARM2] + REPNZ + SCASB + JNZ TOKCH ; not a delimiter + MOV [STRPTR],SI + MOV %[SI][%-1],%0 ; terminate token + MOV AX,BX + POP BP + RETSEG +EMPTY XOR AX,AX + MOV [STRPTR],AX + POP BP + RETSEG +NOS2 MOV CX,[BP][%PARM1] + MOV [STRPTR],CX + XOR AX,AX + POP BP + RETSEG +ENDS1 MOV AX,BX + MOV [STRPTR],0 + POP BP + RETSEG + END diff --git a/Mix Power C v1/SYS.ASM b/Mix Power C v1/SYS.ASM new file mode 100644 index 0000000..1ac7342 --- /dev/null +++ b/Mix Power C v1/SYS.ASM @@ -0,0 +1,1117 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; msdos call routines +; ------------------------------------------------------- +; _sys_acd(axval,cxval,dxval,axaddr) +; axval = value to pass in ax +; axaddr = address for result returned in ax +; cxval = value to pass in cx +; dxval = value to pass in dx +; returns zero if successful, non-zero on error +; ------------------------------------------------------- +; + IDT _sys_acd + IF UPPER + DEF _SYS_ACD + ENDIF + DEF _sys_acd + DREF _doserrno +; +_sys_acd equ $ +_SYS_ACD PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV CX,[BP][%PARM2] + MOV DX,[BP][%PARM3] + INT >21 + MOV BX,[BP][%PARM4] + MOV [BX],AX + JB ERROR + XOR AX,AX + POP BP + RETSEG +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sysacdc(axval,cxval,dxval,cxaddr) +; axval = value to pass in ax +; cxaddr = address for result returned in cx +; cxval = value to pass in cx +; dxval = value to pass in dx +; returns zero if successful, non-zero on error +; ------------------------------------------------------- +; + IDT _sysacdc + IF UPPER + DEF _SYSACDC + ENDIF + DEF _sysacdc + DREF _doserrno +; +_sysacdc equ $ +_SYSACDC PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV CX,[BP][%PARM2] + MOV DX,[BP][%PARM3] + INT >21 + MOV BX,[BP][%PARM4] + MOV [BX],CX + JB ERROR + XOR AX,AX + POP BP + RETSEG +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sys_ad(axval,dxval,axaddr) +; axval = value to pass in ax +; axaddr = address for result returned in ax +; dxval = value to pass in dx +; returns zero if successful, non-zero on error +; ------------------------------------------------------- +; + IDT _sys_ad + IF UPPER + DEF _SYS_AD + ENDIF + DEF _sys_ad + DREF _doserrno +; +_sys_ad equ $ +_SYS_AD PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV DX,[BP][%PARM2] + INT >21 + MOV BX,[BP][%PARM3] + MOV [BX],AX + JB ERROR + XOR AX,AX + POP BP + RETSEG +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sys_add(axval,dxval,dxaddr) +; axval = value to pass in ax +; dxaddr = address for result returned in dx +; dxval = value to pass in dx +; returns zero if successful, non-zero on error +; ------------------------------------------------------- +; + IDT _sys_add + IF UPPER + DEF _SYS_ADD + ENDIF + DEF _sys_add + DREF _doserrno +; +_sys_add equ $ +_SYS_ADD PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV DX,[BP][%PARM2] + INT >21 + MOV BX,[BP][%PARM3] + MOV [BX],DX + JB ERROR + XOR AX,AX + POP BP + RETSEG +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sys_al(axval) +; axval = value to pass in ah:al +; returns result from al +; ------------------------------------------------------- +; + IDT _sys_al + IF UPPER + DEF _SYS_AL + ENDIF + DEF _sys_al +; +_sys_al equ $ +_SYS_AL PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + INT >21 + XOR AH,AH + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sys_adx(axval,dxval) +; axval = value to pass in ah:al +; dxval = value to pass in dh:dl +; returns zero +; ------------------------------------------------------- +; + IDT _sys_adx + IF UPPER + DEF _SYS_ADX + ENDIF + DEF _sys_adx +; +_sys_adx equ $ +_SYS_ADX PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV DX,[BP][%PARM2] + INT >21 + XOR AX,AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sys_abcd(axval,bxval,cxval,dxval,axaddr) +; axval = value to pass in ax +; axaddr = address for result returned in ax +; bxval = value to pass in bx +; cxval = value to pass in cx +; dxval = value to pass in dx +; returns zero if successful, non-zero on error +; ------------------------------------------------------- +; + IDT _sysabcd + IF UPPER + DEF _SYSABCD + ENDIF + DEF _sysabcd + DREF _doserrno +; +_sysabcd equ $ +_SYSABCD PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV BX,[BP][%PARM2] + MOV CX,[BP][%PARM3] + MOV DX,[BP][%PARM4] + INT >21 + MOV BX,[BP][%PARM5] + MOV [BX],AX + JB ERROR + XOR AX,AX + POP BP + RETSEG +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sys_ab(axval,bxval,axaddr) +; axval = value to pass in ax +; axaddr = address for result returned in ax +; bxval = value to pass in bx +; returns zero if successful, non-zero on error +; ------------------------------------------------------- +; + IDT _sys_ab + IF UPPER + DEF _SYS_AB + ENDIF + DEF _sys_ab + DREF _doserrno +; +_sys_ab equ $ +_SYS_AB PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV BX,[BP][%PARM2] + INT >21 + MOV BX,[BP][%PARM3] + MOV [BX],AX + JB ERROR + XOR AX,AX + POP BP + RETSEG +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sysdxdi(axval,dxval,dival,axaddr) +; axval = value to pass in ax +; axaddr = address for result returned in ax +; dxval = value to pass in dx +; dival = value to pass in di +; es set to ds before call +; returns zero if successful, non-zero on error +; ------------------------------------------------------- +; + IDT _sysdxdi + IF UPPER + DEF _SYSDXDI + ENDIF + DEF _sysdxdi + DREF _doserrno +; +_sysdxdi equ $ +_SYSDXDI PUSH BP + MOV BP,SP + MOV AX,DS + MOV ES,AX + MOV AX,[BP][%PARM1] + MOV DX,[BP][%PARM2] + MOV DI,[BP][%PARM3] + INT >21 + MOV BX,[BP][%PARM4] + MOV [BX],AX + JB ERROR + XOR AX,AX + POP BP + RETSEG +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; _sysdxsi(axval,dxval,sival,axaddr) +; axval = value to pass in ax +; axaddr = address for result returned in ax +; dxval = value to pass in dx +; sival = value to pass in si +; es set to ds before call +; returns zero if successful, non-zero on error +; ------------------------------------------------------- +; + IDT _sysdxsi + IF UPPER + DEF _SYSDXSI + ENDIF + DEF _sysdxsi + DREF _doserrno +; +_sysdxsi equ $ +_SYSDXSI PUSH BP + MOV BP,SP + MOV AX,DS + MOV ES,AX + MOV AX,[BP][%PARM1] + MOV DX,[BP][%PARM2] + MOV SI,[BP][%PARM3] + INT >21 + MOV BX,[BP][%PARM4] + MOV [BX],AX + JB ERROR + XOR AX,AX + POP BP + RETSEG +ERROR MOV [_doserrno],AX + MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; asm(address,bx) +; char *addresss; /* address in data segment */ +; int *bx; /* bx value */ +; returns AX +; ------------------------------------------------------- +; + IDT asm + IF UPPER + DEF ASM + ENDIF + DEF asm +; +asm equ $ +ASM PUSH BP + MOV BP,SP + MOV AX,CS + PUSH AX ; place far return address on stack + JMP SETUP +DO MOV AX,DSRETURN ; near return address + PUSH AX + PUSH DS ; far call address + PUSH [BP][%PARM1] ; offset + MOV BX,[BP][%PARM2] + RETSEG ; do the subroutine +SETUP CALL DO ; places return address on stack + POP BP + CLD + RETSEG + DORG 0 +DSRETURN RETSEG + END +; +; ============================================================ +; +; typedef union { +; struct { +; char al, ah, bl, bh, cl, ch, dl, dh; +; } byte; +; struct { +; int ax, bx, cx, dx, si, di, bp, es, ds, cs; +; } word; +; } REGS; +; +; ------------------------------------------------------- +; asmx(address,reg) +; char *addresss; /* address in data segment */ +; REGS *reg; /* registers */ +; returns 8086 flags register +; ------------------------------------------------------- +; + IDT asmx + IF UPPER + DEF ASMX + ENDIF + DEF asmx +; +asmx equ $ +ASMX PUSH BP + MOV BP,SP + MOV AX,CS + PUSH AX ; place far return address on stack + JMP SETUP +DO MOV AX,[BP][%PARM1] ; offset + MOV BP,[BP][%PARM2] + MOV BX,[BP][%18] ; CS for call + PUSH BX + PUSH AX + MOV BX,[BP][%14] + MOV ES,BX + MOV BX,DS + XCHG BX,[BP][%16] + MOV DS,BX + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%8] + MOV DI,[BP][%10] + MOV BP,[BP][%12] + RETSEG ; do the subroutine +SETUP CALL DO ; places return address on stack + PUSH BP + MOV BP,SP + MOV BP,[BP][%PARM2+2] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + MOV [BP][%8],SI + MOV [BP][%10],DI + POP AX + MOV [BP][%12],AX + MOV AX,ES + MOV [BP][%14],AX + MOV AX,DS + XCHG AX,[BP][%16] + MOV DS,AX + MOV AX,CS + MOV [BP][%18],AX + PUSHF + POP AX + POP BP + CLD + RETSEG + END +; +; ------------------------------------------------------- +; bdos(fn,dx, al); +; int fn; /* function number */ +; unsigned dx; /* register contents for dx */ +; unsigned al; /* value to pass in al */ +; returns 8086 ax register +; ------------------------------------------------------- +; + IDT bdos + IF UPPER + DEF BDOS + ENDIF + DEF bdos +; +bdos equ $ +BDOS PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV AH,AL + MOV DX,[BP][%PARM2] + MOV CX,[BP][%PARM3] + MOV AL,CL + INT >21 + JB CARRY + POP BP + RETSEG +CARRY MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; bdosptr(fn,dx, al); +; int fn; /* function number */ +; void *dsdx; /* pegister contents for dx */ +; unsigned al; /* value to pass in al */ +; returns 8086 ax register +; ------------------------------------------------------- +; + IDT bdosptr + IF UPPER + DEF BDOSPTR + ENDIF + DEF bdosptr +; +bdosptr equ $ +BDOSPTR PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV AH,AL + MOV DX,[BP][%PARM2] + MOV CX,[BP][%PARM3] + MOV AL,CL + INT >21 + JB CARRY + POP BP + RETSEG +CARRY MOV AX,-1 + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; bdosx(fn,reg); +; int fn; /* function number */ +; REGS *reg; /* register contents */ +; returns 8086 flags register +; ------------------------------------------------------- +; + IDT bdosx + IF UPPER + DEF BDOSX + ENDIF + DEF bdosx +; +bdosx equ $ +BDOSX PUSH BP + MOV BP,SP + MOV CX,[BP][%PARM1] + MOV BP,[BP][%PARM2] + MOV AX,[BP][%0] + MOV AH,CL + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%8] + MOV DI,[BP][%10] + INT >21 + MOV BP,SP + MOV BP,[BP][%PARM2] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + MOV [BP][%8],SI + MOV [BP][%10],DI + PUSHF + POP AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; bios(intn, reg); +; int intn; /* software interrupt number */ +; REGS *reg; /* register contents */ +; returns 8086 flags register +; passes ax,bx,cx,dx only +; ------------------------------------------------------- +; + IDT bios + IF UPPER + DEF BIOS + ENDIF + DEF bios +; +bios equ $ +BIOS PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV SI,INSTRINT + MOV [SI][%1],AL ; set interrupt no + MOV BX,CS + PUSH BX + JMPS SETUP +DO PUSH DS + MOV AX,INSTRINT + PUSH AX + MOV BP,[BP][%PARM2] + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + RETSEG +SETUP CALL DO + MOV BP,SP + MOV BP,[BP][%PARM2] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + PUSHF + POP AX + POP BP + CLD + RETSEG + DORG 0 +INSTRINT INT >21 +INSTRRET RETSEG + END +; +; ------------------------------------------------------- +; biosx(intn, reg); +; int intn; /* software interrupt number */ +; REGS *reg; /* register contents */ +; returns 8086 flags register +; passes all registers +; ------------------------------------------------------- +; + IDT biosx + IF UPPER + DEF BIOSX + ENDIF + DEF biosx +; +biosx equ $ +BIOSX PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV SI,INSTRINT + MOV [SI][%1],AL ; set interrupt no + MOV BX,CS + PUSH BX + JMPS SETUP +DO PUSH DS + MOV AX,INSTRINT + PUSH AX + MOV BP,[BP][%PARM2] + MOV BX,[BP][%14] + MOV ES,BX + MOV BX,DS + XCHG BX,[BP][%16] + MOV DS,BX + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%8] + MOV DI,[BP][%10] + MOV BP,[BP][%12] + RETSEG +SETUP CALL DO + PUSH BP + MOV BP,SP + MOV BP,[BP][%PARM2+2] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + MOV [BP][%8],SI + MOV [BP][%10],DI + POP AX + MOV [BP][%12],AX + MOV AX,ES + MOV [BP][%14],AX + MOV AX,DS + XCHG AX,[BP][%16] + MOV DS,AX + MOV AX,CS + MOV [BP][%18],AX + PUSHF + POP AX + POP BP + CLD + RETSEG + DORG 0 +INSTRINT INT >21 + RETSEG + END +; +; +; ============================================================ +; +; Microsoft C compatable dos call routines +; +; struct WORDREGS { +; unsigned int ax; +; unsigned int bx; +; unsigned int cx; +; unsigned int dx; +; unsigned int si; +; unsigned int di; +; unsigned int cflag; +; }; +; struct BYTEREGS { +; unsigned char al, ah; +; unsigned char bl, bh; +; unsigned char cl, ch; +; unsigned char dl, dh; +; }; +; union REGS { +; struct WORDREGS x; +; struct BYTEREGS h; +; }; +; +; struct SREGS { +; unsigned int es; +; unsigned int cs; +; unsigned int ss; +; unsigned int ds; +; }; +; +; ------------------------------------------------------- +; int intdos(inreg, outregs); +; union REGS *inregs; +; union REGS *outregs; +; returns the value of ax as result +; if carry set, doserrno also contains error code +; ------------------------------------------------------- +; + IDT intdos + IF UPPER + DEF INTDOS + ENDIF + DEF intdos + DREF _doserrno +; +intdos equ $ +INTDOS PUSH BP + MOV BP,SP + MOV BP,[BP][%PARM1] + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%8] + MOV DI,[BP][%10] + INT >21 + MOV BP,SP + MOV BP,[BP][%PARM2] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + MOV [BP][%8],SI + MOV [BP][%10],DI + MOV [BP][%12],0 + JNB DONE + MOV [_doserrno],AX + MOV [BP][%12],1 +DONE POP BP + RETSEG + END +; +; ------------------------------------------------------- +; int intdosx(inreg, outregs, segregs); +; union REGS *inregs; +; union REGS *outregs; +; struct SREGS *segregs; +; returns the value of ax as result +; if carry set, doserrno also contains error code +; ------------------------------------------------------- +; + IDT intdosx + IF UPPER + DEF INTDOSX + ENDIF + DEF intdosx + DREF _doserrno +; +intdosx equ $ +INTDOSX PUSH BP + MOV BP,SP + MOV BP,[BP][%PARM3] ; Segments + MOV AX,ES + XCHG AX,[BP][%0] + MOV ES,AX + MOV AX,DS + XCHG AX,[BP][%6] + MOV DS,AX + MOV BP,SP + MOV BP,[BP][%PARM1] + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%8] + MOV DI,[BP][%10] + INT >21 + MOV BP,SP + MOV BP,[BP][%PARM2] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + MOV [BP][%8],SI + MOV [BP][%10],DI + MOV [BP][%12],0 + MOV BP,SP + MOV BP,[BP][%PARM3] ; Restore segments + MOV DX,DS + XCHG DX,[BP][%6] + MOV DS,DX + MOV DX,ES + XCHG DX,[BP][%0] + MOV ES,DX + MOV BP,SP + MOV BP,[BP][%PARM2] + JNB DONE ; flags still set from int21 + MOV [_doserrno],AX + MOV [BP][%12],1 +DONE POP BP + RETSEG + END +; +; ------------------------------------------------------- +; int int86(intno, inreg, outregs); +; int intno; +; union REGS *inregs; +; union REGS *outregs; +; returns the value of ax as result +; if carry set, doserrno also contains error code +; ------------------------------------------------------- +; + IDT int86 + IF UPPER + DEF INT86 + ENDIF + DEF int86 + DREF _doserrno +; +int86 equ $ +INT86 PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV SI,INSTRINT + MOV [SI][%1],AL + MOV AX,CS + PUSH AX + MOV BP,[BP][%PARM2] + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%8] + MOV DI,[BP][%10] + CALL DOINT + MOV BP,SP + MOV BP,[BP][%PARM3] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + MOV [BP][%8],SI + MOV [BP][%10],DI + MOV [BP][%12],0 + JNB DONE + MOV [_doserrno],AX + MOV [BP][%12],1 +DONE POP BP + RETSEG +DOINT PUSH DS + MOV BP,INSTRINT + PUSH BP + RETSEG + DORG 0 +INSTRINT INT >21 + RETSEG + END +; +; ------------------------------------------------------- +; int intdosx(intno, inreg, outregs, segregs); +; int intno; +; union REGS *inregs; +; union REGS *outregs; +; struct SREGS *segregs; +; returns the value of ax as result +; if carry set, doserrno also contains error code +; ------------------------------------------------------- +; + IDT int86x + IF UPPER + DEF INT86X + ENDIF + DEF int86x + DREF _doserrno +; +int86x equ $ +INT86X PUSH BP + MOV BP,SP + MOV AX,[BP][%PARM1] + MOV SI,INSTRINT + MOV [SI][%1],AL + MOV BX,CS + PUSH BX + JMPS SETUP +DOINT PUSH DS + MOV AX,INSTRINT + PUSH AX + MOV SI,[BP][%PARM4] ; Segments + MOV AX,ES + XCHG AX,[SI][%0] + MOV ES,AX + MOV AX,DS + XCHG AX,[SI][%6] + MOV DS,AX + MOV BP,[BP][%PARM2] + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%8] + MOV DI,[BP][%10] + RETSEG +SETUP CALL DOINT + MOV BP,SP + MOV BP,[BP][%PARM3] + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + MOV [BP][%8],SI + MOV [BP][%10],DI + MOV [BP][%12],0 + MOV BP,SP + MOV BP,[BP][%PARM4] ; Restore segments + MOV DX,DS + XCHG DX,[BP][%6] + MOV DS,DX + MOV DX,ES + XCHG DX,[BP][%0] + MOV ES,DX + MOV BP,SP + MOV BP,[BP][%PARM3] + JNB DONE ; flags still set from int21 + MOV [_doserrno],AX + MOV [BP][%12],1 +DONE POP BP + RETSEG + DORG 0 +INSTRINT INT >21 + RETSEG + END +; +; ------------------------------------------------------- +; void segread(segregs) +; struct SREGS *segregs; +; returns the contents of the segment registers +; ------------------------------------------------------- +; + IDT segread + DEF segread + IF UPPER + DEF SEGREAD + ENDIF +; +segread equ $ +SEGREAD MOV SI,SP + MOV SI,[SI][%PARM1-2] + MOV [SI],ES + MOV [SI][%2],CS + MOV [SI][%4],SS + MOV [SI][%6],DS + RETSEG + END +; +; ------------------------------------------------------- +; int getdseg() +; returns the contents of the data segment register +; ------------------------------------------------------- +; + IDT getdseg + DEF getdseg + IF UPPER + DEF GETDSEG + ENDIF +; +getdseg equ $ +GETDSEG MOV AX,DS + RETSEG + END +; +; ------------------------------------------------------- +; int getcseg() +; returns the contents of the data segment register +; ------------------------------------------------------- +; + IDT getcseg + DEF getcseg + IF UPPER + DEF GETCSEG + ENDIF +; +getcseg equ $ +GETCSEG MOV SI,SP + MOV AX,[SI][%2] + RETSEG + END +; +; ------------------------------------------------------- +; #define FP_SEG(farptr) (*((unsigned *)&(farptr) + 1)) +; return the segment part of a far pointer +; ------------------------------------------------------- +; + IDT FP_SEG + DEF FP_SEG +; +FP_SEG MOV SI,SP + MOV AX,[SI][%PARM1-2+2] + RETSEG + END +; +; ------------------------------------------------------- +; #define FP_OFF(farptr) (*((unsigned *)&(farptr))) +; return the offset part of a far pointer +; ------------------------------------------------------- +; + IDT FP_OFF + DEF FP_OFF +; +FP_OFF MOV SI,SP + MOV AX,[SI][%PARM1-2] + RETSEG + END +; +; ------------------------------------------------------- +; char far *FP_SET(segment, offset) +; create a far pointer from segment and offset +; ------------------------------------------------------- +; + IDT FP_SET + DEF FP_SET +; +FP_SET MOV SI,SP + MOV DX,[SI][%PARM1-2] + MOV AX,[SI][%PARM2-2] + RETSEG + END +; +; ------------------------------------------------------- +; char far *MK_FP(segment, offset) +; create a far pointer from segment and offset +; ------------------------------------------------------- +; + IDT MK_FP + DEF MK_FP +; +MK_FP MOV SI,SP + MOV DX,[SI][%PARM1-2] + MOV AX,[SI][%PARM2-2] + RETSEG + END +; +; +; ============================================================ +; +; Aztec C compatable dos call routines +; +; static struct regval { +; int ax, bx, cx, dx; +; int si, di, ds, es; +; +; ------------------------------------------------------- +; int sysint(interrupt, inreg, outregs); +; struct regval *inregs; +; struct regval *outregs; +; returns the value of ax as result +; ------------------------------------------------------- +; + IDT sysint + IF UPPER + DEF SYSINT + ENDIF + DEF sysint +; +sysint equ $ +SYSINT PUSH BP + MOV BP,SP + PUSH DS + MOV AX,[BP][%14] + MOV ES,AX + MOV AX,[BP][%12] + MOV DS,AX + MOV AX,[BP][%PARM2] + PUSH AX + MOV BP,[BP][%PARM1] + MOV AX,[BP][%0] + MOV BX,[BP][%2] + MOV CX,[BP][%4] + MOV DX,[BP][%6] + MOV SI,[BP][%8] + MOV DI,[BP][%10] + INT >21 + POP BP + MOV [BP][%0],AX + MOV [BP][%2],BX + MOV [BP][%4],CX + MOV [BP][%6],DX + MOV [BP][%8],SI + MOV [BP][%10],DI + MOV DX,DS + MOV [BP][%12],DX + MOV DX,ES + MOV [BP][%14],DX + POP DX + MOV DS,DX + PUSHF + POP AX + POP BP + RETSEG + END +; +; ------------------------------------------------------- +; $_stkchk check for stack overflow +; ------------------------------------------------------- +; + IDT $_STKCHK + DEF $_STKCHK + DREF $$MAXS + DREF $$LIMIT + FREF exit +; +$_STKCHK MOV [$$MAXS],SP + CMP SP,[$$LIMIT] + JNB OK + MOV AX,>4000 ; Write message to stderr + MOV BX,2 + MOV CX,MSGLEN + MOV DX,STKMSG + INT >21 + MOV AX,>0081 + CALLFAR exit +OK RETSEG + DORG $ +STKMSG DB 'Out of stack',>0D,>0A +MSGLEN EQU $-STKMSG + END diff --git a/Mix Power C v1/TEMPFILE.C b/Mix Power C v1/TEMPFILE.C new file mode 100644 index 0000000..7267431 --- /dev/null +++ b/Mix Power C v1/TEMPFILE.C @@ -0,0 +1,134 @@ +/* Temporary file functions */ +/* Copyright (c) Mix Software 1988 */ + +char *mktemp(template) + char *template; +{ + static int pr = 0; + static char pid[5]; + char *p, *q; + char id = 'a'; + int i, j; + if (pr == 0) { + j = pr = getpid(); + p = &pid[4]; + for (i = 0; i < 5; ++i) { + *p-- = (j % 10) + 48; + j /= 10; + } + } + if ((j = strlen(template)) < 6) return NULL; + p = template + j - 1; + q = &pid[4]; + for (i = 0; i < 5; ++i) { + if (*p != 'X') return NULL; + *p-- = *q--; + } + *p = '0'; + do { + if (_sys_acd(0x4300,0,template,&j) != 0) return template; + *p = id; + } while (++id < 'z'); + return NULL; +} + +int rmtmp() +{ + int i; + int n = 0; + FILE *fp; + for (i=0; i < MAXFILES; ++i) { + fp = _iob[i]; + if (fp != NULL) { + if (fp->file.flag2 & fd2temp) { close(fp->fd); ++n; } + } + } + return n; +} + +FILE *tmpfile() +{ + FILE *fp; + char name[L_tmpnam]; + if (tmpnam(name) == NULL) return NULL; + fp = fopen(name,"w+"); + if (fp) fp->file.flag2 |= fd2temp; + return fp; +} + +char *tmpnam(string) + char *string; +{ + extern unsigned _tmpoff; + char value[8]; + if (_tmpoff == 0) return NULL; + if (string == NULL) { + if ((string = malloc(L_tmpnam)) == NULL) return NULL; + } + strcpy(string,P_tmpdir); + value[0] = '\\'; + utoa(_tmpoff,&value[1],10); + strcat(string,value); + ++_tmpoff; + return string; +} + +char *tempnam(dir,prefix) + char *dir; + char *prefix; +{ + extern unsigned _tmpoff; + char *pf, *s; + char *_isdir(); + char value[8]; + pf = getenv("TMP"); + if (pf != NULL) pf = _isdir(pf); + if (pf == NULL) pf = _isdir(dir); + if (pf == NULL) pf = _isdir(P_tmpdir); + if (pf == NULL) pf = "\tmp"; + s = malloc(strlen(pf)+strlen(prefix)+8); + if (s == NULL) return NULL; + strcpy(s,pf); + if (strlen(pf) != 2 || *(pf+1) != ':') strcat(s,"\\"); + strcat(s,prefix); + utoa(_tmpoff,value,10); + strcat(s,value); + ++_tmpoff; + return s; +} + +unsigned _tmpoff = 1; + +char *_isdir(dirname) + char *dirname; +{ + int flags; + char dr; + if (*(dirname+1) == ':') { + if (strlen(dirname) == 2) { + dr = toupper(*dirname); + if (dr >= 'A' && dr <= 'P') return dirname; + } + } + if (_sysacdc(0x4300, 0, dirname, &flags) != 0) return 0; + if ((flags & 0x0010) == 0) return 0; + return dirname; +} + +creattemp(filename,attrib) + char *filename; + int attrib; +{ + static unsigned tmpindex = 0; + unsigned startindex; + int fd; + int namelen; + startindex = tmpindex; + namelen = strlen(filename); + do { + utoa(++tmpindex,(filename+namelen),10); + fd = creatnew(filename,attrib); + } while (fd == -1 && tmpindex != startindex); + return fd; + } + diff --git a/Mix Power C v1/TIME.C b/Mix Power C v1/TIME.C new file mode 100644 index 0000000..0d27af5 --- /dev/null +++ b/Mix Power C v1/TIME.C @@ -0,0 +1,538 @@ +/* Time and date functions */ +/* Copyright (c) Mix Software 1988 */ + +char *ctime(time) +long time; +{ + char *asctime(); + struct tm *localtime(); + return asctime(localtime(time)); +} /* ctime */ + +size_t strftime(s, maxsize, format, timeptr) + char *s; /* buffer for result */ + size_t maxsize; /* maximum size of s */ + char *format; /* format string */ + struct tm *timeptr; /* time to convert */ +{ /* formatted time */ + static char *shortday[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; + static char *longday[7] = {"Sunday","Monday","Tuesday","Wednesday", + "Thursday","Friday","Saturday"}; + static char *shortmonth[12] = {"Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec"}; + static char *longmonth[12] = {"January","February","March","April", + "May","June","July","August","September", + "October","November","December"}; + static char *am_pm[2] = {"AM","PM"}; + static int _strput(int, char *, int); + char *asctime(); + extern char *tzname[2]; + #define put(ch) {if (--length) *s++ = ch; else return 0;} + char ch, *p; + char str[20]; + int length = maxsize; + int value; + while (*format != '\0') { + if (*format != '%') put(*format++) + else { + p = str; + memset(p,0,sizeof(str)); + switch (*++format) { + case 'a' : + p = shortday[timeptr->tm_wday]; + break; + case 'A' : + p = longday[timeptr->tm_wday]; + break; + case 'b' : + p = shortmonth[timeptr->tm_mon]; + break; + case 'B' : + p = longmonth[timeptr->tm_mon]; + break; + case 'c' : + p = asctime(timeptr); + break; + case 'd' : + _asct2dig(timeptr->tm_mday,p); + break; + case 'H' : + _asct2dig(timeptr->tm_hour,p); + break; + case 'I' : + value = timeptr->tm_hour; + if (value > 12) value -= 12; + _asct2dig(value,p); + break; + case 'j' : + case 'J' : + _asct3dig(timeptr->tm_yday,p); + break; + case 'm' : + _asct2dig(timeptr->tm_mon+1,p); + break; + case 'M' : + _asct2dig(timeptr->tm_min,p); + break; + case 'p' : + p = am_pm[timeptr->tm_hour / 12]; + break; + case 'S' : + _asct2dig(timeptr->tm_sec,p); + break; + case 'U' : + value = timeptr->tm_wday - (timeptr->tm_yday % 7); + if (value < 0) value += 7; /* week day of Jan 1 */ + value = (timeptr->tm_yday + value - 1) / 7; + _asct2dig(value,p); + break; + case 'w' : + *p = timeptr->tm_wday + '0'; + break; + case 'W' : + value = timeptr->tm_wday - (timeptr->tm_yday % 7); + if (value < 0) value += 7; /* week day of Jan 1 */ + value = (timeptr->tm_yday + value) / 7; + _asct2dig(value,p); + break; + case 'x' : + _asct2dig(timeptr->tm_mon+1,str); + _asct2dig(timeptr->tm_mday,&str[3]); + _asct2dig(timeptr->tm_year % 100,&str[6]); + str[2] = '/'; + str[5] = '/'; + break; + case 'X' : + _asct2dig(timeptr->tm_hour,str); + _asct2dig(timeptr->tm_min,&str[3]); + _asct2dig(timeptr->tm_sec % 100,&str[6]); + str[2] = ':'; + str[5] = ':'; + break; + case 'y' : + _asct2dig(timeptr->tm_year % 100,p); + break; + case 'Y' : + _asct2dig(timeptr->tm_year / 100,str); + _asct2dig(timeptr->tm_year % 100,&str[2]); + break; + case 'Z' : + if (timeptr->tm_isdst) p = tzname[1]; else p = tzname[0]; + if (p == NULL) p = str; + break; + case '%' : + *p = '%'; + break; + } /* switch */ + while (*p != '\0') put(*p++) + ++format; + } /* '%' */ + } /* while */ + *s = '\0'; + return maxsize - length; + #undef put +} /* strftime */ + +char *asctime(time) +struct tm *time; +{ /* convert time to a character string */ + static char *monthname[13] = {"Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec"}; + static char *dayname[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; + static char timebuf[26]; + int yy; + strcpy(timebuf,"www mmm dd hh:mm:ss yyyy\n"); + memcpy(timebuf,dayname[time->tm_wday],3); + memcpy(&timebuf[4],monthname[time->tm_mon],3); + _asct2dig(time->tm_mday,&timebuf[8]); + _asct2dig(time->tm_hour,&timebuf[11]); + _asct2dig(time->tm_min,&timebuf[14]); + _asct2dig(time->tm_sec,&timebuf[17]); + yy = time->tm_year < 100 ? 19 : 20; + _asct2dig(yy,&timebuf[20]); + _asct2dig(time->tm_year % 100,&timebuf[22]); + return timebuf; + +} /* asctime */ + +_asct2dig(n, p) + int n; + char *p; +{ + *p++ = (n / 10) + '0'; + *p = (n % 10) + '0'; +} + +_asct3dig(n, p) + int n; + char *p; +{ + *p++ = (n / 100) + '0'; + n = n % 100; + *p++ = (n / 10) + '0'; + *p = (n % 10) + '0'; +} + +time_t mktime(timeptr) + struct tm *timeptr; +{ + long _timesec(int, int, int, int, int, int); + struct tm *localtime(); + struct tm *_timecvt(time_t); + time_t t; + t = _timesec(timeptr->tm_year+1900, timeptr->tm_mon+1, timeptr->tm_mday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); + *timeptr = *localtime(&t); + return t; + } + +int stime(tp) /* set time */ + long *tp; +{ + struct tm *t; + union REGS time, date; + t = localtime(tp); + time.h.ah = 0x2d; + time.h.ch = t->tm_hour; + time.h.cl = t->tm_min; + time.h.dh = t->tm_sec; + time.h.dl = 0; + date.h.ah = 0x2b; + date.x.cx = t->tm_year+1900; + date.h.dh = t->tm_mon+1; + date.h.dl = t->tm_mday; + intdos(&date,&date); + intdos(&time,&time); + return 0; + } + +struct utimbuf { + time_t actime; /* access time */ + time_t modtime; /* modification time */ +}; + +int utime(filename, times) + char *filename; + struct utimbuf *times; +{ + extern int _doserrno, errno; + union REGS r; + struct tm *localtime(time_t *), *tptr; + union { + struct ftime time; + struct { + int time; + int date; + } i; + } filetime; + time_t t, time(); + int handle; + int status; + if (times == NULL) t = time(NULL); else t = times->modtime; + tptr = localtime(&t); + if (_sys_ad(0x3d00,filename,&handle) != 0) + { errno = _doserrno; return -1; } + if (tptr->tm_year < 80) filetime.time.ft_year = 0; + else filetime.time.ft_year = tptr->tm_year-80; + filetime.time.ft_month = tptr->tm_mon+1; + filetime.time.ft_day = tptr->tm_mday; + if (tptr->tm_hour < 0) filetime.time.ft_hour = 0; + else filetime.time.ft_hour = tptr->tm_hour; + filetime.time.ft_min = tptr->tm_min; + filetime.time.ft_tsec = tptr->tm_sec >> 1; + r.x.ax = 0x5701; + r.x.bx = handle; + if (_sysabcd(0x5701,handle,filetime.i.time,filetime.i.date,&status) != 0) { + errno = _doserrno; + _sys_ab(0x3e00,handle,&handle); + return -1; + } + _sys_ab(0x3e00,handle,&handle); + return 0; +} + +struct tm *gmtime(time) +long *time; +{ + struct tm *_timecvt(); + return _timecvt(*time); +} /* gmtime */ + +struct tm *localtime(time) +long *time; +{ + extern long timezone; + extern int daylight; + void tzset(); + struct tm *_timecvt(); + static tzdone = 0; + if (tzdone == 0) {tzset(); tzdone = 1; } + if (daylight) return _timecvt(*time-timezone+3600); + return _timecvt(*time-timezone); +} /* localtime */ + +void unixtodos(utime, dateptr, timeptr) + long utime; + struct date *dateptr; + struct time *timeptr; +{ + extern struct tm *_timecvt(); + extern long timezone; + extern int daylight; + struct tm *t; + long localtime; + localtime = utime - timezone; + if (daylight) localtime += 3600l; + t = _timecvt(localtime); + dateptr->da_year = t->tm_year + 1900; + dateptr->da_mon = t->tm_mon+1; + dateptr->da_day = t->tm_mday; + timeptr->ti_hour = t->tm_hour; + timeptr->ti_min = t->tm_min; + timeptr->ti_sec = t->tm_sec; + timeptr->ti_hund = 0; + } + +struct tm *_timecvt(time) +long time; +{ /* convert binary time to greenwich mean time */ + static struct tm gm; + static int daypermonth[12] = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; + extern int daylight; + long secs, days; + int years, leaps, dayofyear; + int month = 0; + int *mptr = daypermonth; + days = time / 86400; + years = days/365; + leaps = (years+1) / 4; + dayofyear = days - (long)years * 365 - (long)leaps; + if (dayofyear < 0) { + years--; + dayofyear += 365; + } + gm.tm_yday = dayofyear; + gm.tm_year = years+70; + if ((years % 4) == 2) daypermonth[1] = 29; else daypermonth[1] = 28; + while (dayofyear > *mptr) { + ++month; + dayofyear -= *mptr++; + } + gm.tm_mon = month; + gm.tm_mday = dayofyear+1; + gm.tm_wday = (days + 4) % 7; + secs = time - days*86400; + gm.tm_hour = secs / 3600; + secs -= (gm.tm_hour * 3600L); + gm.tm_min = secs / 60; + gm.tm_sec = secs - (gm.tm_min * 60); + gm.tm_isdst = daylight; + return &gm; +} /* _timecvt */ + +void ftime(timeptr) +struct timeb *timeptr; +{ + long _timesec(); + void tzset(); + extern long timezone; + extern int daylight; + union REGS timecall, datecall; + union REGS time, date1, date2; + tzset(); + timecall.h.ah = 0x2c; + datecall.h.ah = 0x2a; + intdos(&datecall,&date1); + intdos(&timecall,&time); + intdos(&datecall,&date2); + if (date2.x.dx != date1.x.dx) { /* date change at midnight */ + if (time.h.ch != 23) { /* date already changed when time read */ + date1.x.cx = date2.x.cx; + date1.x.dx = date2.x.dx; + } + } + timeptr->time = _timesec(date1.x.cx, date1.h.dh, date1.h.dl, + time.h.ch, time.h.cl, time.h.dh); + timeptr->millitm = time.h.dl*10; + timeptr->timezone = timezone/60; + timeptr->dstflag = daylight; + } /* ftime */ + +unsigned sleep(seconds) + unsigned seconds; +{ /* suspend execution */ + long time(); + long start, now; + start = time(NULL); + do { + now = time(NULL); + } while ((now-start) < seconds); + } + +long time(timeptr) +long *timeptr; +{ + long _timesec(); + long curtime; + union REGS timecall, datecall; + union REGS time, date1, date2; + timecall.h.ah = 0x2c; + datecall.h.ah = 0x2a; + intdos(&datecall,&date1); + intdos(&timecall,&time); + intdos(&datecall,&date2); + if (date2.x.dx != date1.x.dx) { /* date change at midnight */ + if (time.h.ch != 23) { /* date already changed when time read */ + date1.x.cx = date2.x.cx; + date1.x.dx = date2.x.dx; + } + } + curtime = _timesec(date1.x.cx, date1.h.dh, date1.h.dl, + time.h.ch, time.h.cl, time.h.dh); + if (timeptr != NULL) *timeptr = curtime; + return curtime; + } /* time */ + +long dostounix(dateptr, timeptr) + struct date *dateptr; + struct time *timeptr; +{ + long _timesec(); + return _timesec(dateptr->da_year,dateptr->da_mon,dateptr->da_day, + timeptr->ti_hour, timeptr->ti_min, timeptr->ti_sec); + } + +clock_t clock(void) +{ + extern struct { + unsigned int year; + unsigned char day; + unsigned char month; + unsigned char hour; + unsigned char minute; + unsigned char hour; + unsigned char hundredth; + unsigned char second; + } $$CLOCK; /* time when process started */ + long time; + union REGS t, d; + t.h.ah = 0x2c; + d.h.ah = 0x2a; + intdos(&d,&d); + intdos(&t,&t); + time = _timesec(d.x.cx,d.h.dh,d.h.dl,t.h.cl,t.h.ch,t.h.dh); + time = time - _timesec($$CLOCK.year,$$CLOCK.month,$$CLOCK.day, + $$CLOCK.hour,$$CLOCK.minute,$$CLOCK.second); + return time*100+t.h.dl-$$CLOCK.hundredth; + } + +long _timesec(year, month, day, hour, min, sec) + int year, month, day, hour, min, sec; +{ /* convert time to seconds since Jan 1 1970 */ + extern long timezone; + extern int daylight; + static int daypermonth[13] = {0, 0, 31, 28+31, + 31+59, 30+31+59, 31+30+31+59, + 30+151, 31+30+151, 31+31+30+151, + 30+243, 31+30+243, 30+31+30+243}; + int years, leaps; + long days, secs; + years = year - 1970; + leaps = (years + 1) / 4; + if (((years % 4) == 2) && (month > 2)) ++leaps; + days = (long)years*365 + (long)leaps + (long)daypermonth[month] + + (long)(day-1); + secs = days*86400 + (long)hour*3600 + (long)min*60 + (long)sec + timezone; + if (daylight) return (secs-3600); + return secs; +} /* _timesec */ + +void tzset() +{ + extern int daylight; + extern long timezone; + extern char *tzname[2]; + char *tz; + int onehour = 3600; + tz = getenv("TZ="); + if (tz != NULL) { + strncpy(tzname[0],tz,3); + if (strlen(tz) > 3) { + tz += 3; + if (*tz == '-') { + onehour = -onehour; + ++tz; + } + timezone = 0; + while (isdigit(*tz)) { + timezone = timezone*10 + (long)onehour*(long)(*tz - '0'); + ++tz; + } + if (*tz) daylight = 1; else daylight = 0; + strncpy(tzname[1],tz,3); + } + else { + timezone = 0; + daylight = 0; + *tzname[1] = '\0'; + } + } +} /* tzset */ + +double difftime(time2,time1) + time_t time1, time2; +{ + return time2-time1; + } + +int daylight = 1; +long timezone = 28800; +char *tzname[2] = {"PST", "PDT"}; + +void getdate(dateblk) + struct date *dateblk; +{ + union REGS r; + r.h.ah = 0x2a; + intdos(&r,&r); + dateblk->da_year = r.x.cx; + dateblk->da_mon = r.h.dh; + dateblk->da_day = r.h.dl; + } + +void gettime(timep) + struct time *timep; +{ + union REGS r; + r.h.ah = 0x2c; + intdos(&r,&r); + timep->ti_min = r.h.cl; + timep->ti_hour = r.h.ch; + timep->ti_hund = r.h.dl; + timep->ti_sec = r.h.dh; + } + +void setdate(dateblk) + struct date *dateblk; +{ + union REGS r; + r.x.cx = dateblk->da_year; + r.h.dh = dateblk->da_mon; + r.h.dl = dateblk->da_day; + r.h.ah = 0x2b; + intdos(&r,&r); + } + +void settime(timep) + struct time *timep; +{ + union REGS r; + r.h.cl = timep->ti_min; + r.h.ch = timep->ti_hour; + r.h.dl = timep->ti_hund; + r.h.dh = timep->ti_sec; + r.h.ah = 0x2d; + intdos(&r,&r); + } + diff --git a/Mix Power C v1/TO.ASM b/Mix Power C v1/TO.ASM new file mode 100644 index 0000000..bd31390 --- /dev/null +++ b/Mix Power C v1/TO.ASM @@ -0,0 +1,421 @@ +; +; Copyright (c) Mix Software 1988 +; +; ------------------------------------------------------- +; toupper() - convert character to upper case +; #define toupper(c) ((c >= 'a' && c <= 'z') ? c - 0x20 : c) +; ------------------------------------------------------- +; + IDT toupper + DEF toupper + IF UPPER + DEF TOUPPER + ENDIF + ENDIF +; +toupper equ $ +TOUPPER MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'a' + JB OK + CMP AX,'z' + JA OK + SUB AX,>20 +OK RETSEG + END +; +; ------------------------------------------------------- +; tolower() - convert character to lower case +; #define tolower(c) ((c >= 'A' && c <= 'Z') ? c + 0x20 : c) +; ------------------------------------------------------- +; + IDT tolower + DEF tolower + IF UPPER + DEF TOLOWER + ENDIF +; +tolower equ $ +TOLOWER MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'A' + JB OK + CMP AX,'Z' + JA OK + ADD AX,>20 +OK RETSEG + END +; +; ------------------------------------------------------- +; toascii() - convert character to ascii +; #define toascii(c) (c & 0x007f) +; ------------------------------------------------------- +; + IDT toascii + DEF toascii + IF UPPER + DEF TOASCII + ENDIF +; +toascii equ $ +TOASCII MOV BX,SP + MOV AX,[BX][%PARM1-2] + AND AX,>007F + RETSEG + END +; +; ------------------------------------------------------- +; _toupper() - convert character to upper case +; #define _toupper(c) (c - 0x20) +; ------------------------------------------------------- +; + IDT _toupper + DEF _toupper + IF UPPER + DEF _TOUPPER + ENDIF +; +_toupper equ $ +_TOUPPER MOV BX,SP + MOV AX,[BX][%PARM1-2] + SUB AX,>0020 + RETSEG + END +; +; ------------------------------------------------------- +; _tolower() - convert character to lower case +; #define tolower(c) (C + 0x20) +; ------------------------------------------------------- +; + IDT _tolower + DEF _tolower + IF UPPER + DEF _TOLOWER + ENDIF +; +_tolower equ $ +_TOLOWER MOV BX,SP + MOV AX,[BX][%PARM1-2] + ADD AX,>0020 + RETSEG + END +; +; +; ------------------------------------------------------- +; isalpha() - returns 1 if c is alphabetic else 0 +; #define isalpha ((c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') ? 1 : 0) +; ------------------------------------------------------- +; + IDT isalpha + DEF isalpha + IF UPPER + DEF ISALPHA + ENDIF +; +isalpha equ $ +ISALPHA MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'a' + JB TRYUPPER + CMP AX,'z' + JBE YES +TRYUPPER CMP AX,'A' + JB NO + CMP AX,'Z' + JA NO +YES MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; isdigit() - returns 1 if c is a digit else 0 +; #define isdigit ((c >= '0' && c <= '9') ? 1 : 0) +; ------------------------------------------------------- +; + IDT isdigit + DEF isdigit + IF UPPER + DEF ISDIGIT + ENDIF +; +isdigit equ $ +ISDIGIT MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'0' + JB NO + CMP AX,'9' + JA NO + MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; isspace() - returns 1 if c is white space else 0 +; #define isspace ((c == ' ' || c >= '0x09' && c <= '0x0d') ? 1 : 0) +; ------------------------------------------------------- +; + IDT isspace + DEF isspace + IF UPPER + DEF ISSPACE + ENDIF +; +isspace equ $ +ISSPACE MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,' ' + JZ YES + CMP AX,>0009 + JB NO + CMP AX,>000D + JA NO +YES MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; islower() - returns 1 if c is lower case else 0 +; #define islower ((c >= 'a' && c <= 'z') ? 1 : 0) +; ------------------------------------------------------- +; + IDT islower + DEF islower + IF UPPER + DEF ISLOWER + ENDIF +; +islower equ $ +ISLOWER MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'a' + JB NO + CMP AX,'z' + JA NO + MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; isupper() - returns 1 if c is upper case else 0 +; #define islower ((c >= 'A' && c <= 'Z') ? 1 : 0) +; ------------------------------------------------------- +; + IDT isupper + DEF isupper + IF UPPER + DEF ISUPPER + ENDIF +; +isupper equ $ +ISUPPER MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'A' + JB NO + CMP AX,'Z' + JA NO + MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; isalnum() - returns 1 if c is a letter or a digit +; #define isalnum ((c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' +; || c >= '0' && c <= '9') ? 1 : 0) +; ------------------------------------------------------- +; + IDT isalnum + DEF isalnum + IF UPPER + DEF ISALNUM + ENDIF +; +isalnum equ $ +ISALNUM MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'a' + JB TRYUPPER + CMP AX,'z' + JBE YES +TRYUPPER CMP AX,'A' + JB TRYDIGIT + CMP AX,'Z' + JBE YES +TRYDIGIT CMP AX,'0' + JB NO + CMP AX,'9' + JA NO +YES MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; isascii() - returns 1 if c is ascii else 0 +; #define isascii ((c >= 0 && c <= 0x7f) ? 1 : 0) +; ------------------------------------------------------- +; + IDT isascii + DEF isascii + IF UPPER + DEF ISASCII + ENDIF +; +isascii equ $ +ISASCII MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,>007F + JA NO + MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; iscntrl() - returns 1 if c 0..0x1f or 0x7f else 0 +; #define iscntrl ((c < 32 || c == 0x7f) ? 1 : 0) +; ------------------------------------------------------- +; + IDT iscntrl + DEF iscntrl + IF UPPER + DEF ISCNTRL + ENDIF +; +iscntrl equ $ +ISCNTRL MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,>0020 + JB YES + CMP AX,>007F + JNZ NO +YES MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; isprint() - returns 1 if c 0x20..0x7e else 0 +; #define isprint ((c < 32 || c > 0x7e) ? 0 : 1) +; ------------------------------------------------------- +; + IDT isprint + DEF isprint + IF UPPER + DEF ISPRINT + ENDIF +; +isprint equ $ +ISPRINT MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,>0020 + JB NO + CMP AX,>007E + JA NO +YES MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; isgraph() - returns 1 if c 0x20..0x7e else 0 +; #define isgraph ((c <= 32 || c > 0x7e) ? 0 : 1) +; ------------------------------------------------------- +; + IDT isgraph + DEF isgraph +; +isgraph MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,>0020 + JBE NO + CMP AX,>007E + JA NO +YES MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; ispunct() - returns 1 if c is punctuation (both isalnum +; and iscntrl are false +; #define ispunct(c) (!isalnum(c) && !iscntrl(c)) +; ------------------------------------------------------- +; + IDT ispunct + DEF ispunct + IF UPPER + DEF ISPUNCT + ENDIF +; +ispunct equ $ +ISPUNCT MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'a' + JB TRYUPPER + CMP AX,'z' + JBE NO +TRYUPPER CMP AX,'A' + JB TRYDIGIT + CMP AX,'Z' + JBE NO +TRYDIGIT CMP AX,'0' + JB TRYCTRL + CMP AX,'9' + JBE NO +TRYCTRL CMP AX,>0020 + JB NO + CMP AX,>007F + JZ NO +YES MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END +; +; ------------------------------------------------------- +; isxdigit() - returns 1 if c is a hex digit +; #define isxdigit(c) ((c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f' +; || c >= '0' && c <= '9') ? 1 : 0) +; ------------------------------------------------------- +; + IDT isxdigit + DEF isxdigit + IF UPPER + DEF ISXDIGIT + ENDIF +; +isxdigit equ $ +ISXDIGIT MOV BX,SP + MOV AX,[BX][%PARM1-2] + CMP AX,'0' + JB TRYUPPER + CMP AX,'9' + JBE YES +TRYUPPER CMP AX,'A' + JB TRYLOWER + CMP AX,'F' + JBE YES +TRYLOWER CMP AX,'a' + JB NO + CMP AX,'f' + JA NO +YES MOV AX,1 + RETSEG +NO XOR AX,AX + RETSEG + END diff --git a/Mix Power C v1/TTT.C b/Mix Power C v1/TTT.C new file mode 100644 index 0000000..92c5eef --- /dev/null +++ b/Mix Power C v1/TTT.C @@ -0,0 +1,527 @@ +/* + This version builds with old compilers including: + Aztec C 1.06 for 8080 & Z80 on CP/M. + Microsoft C Compiler V1.04 for 8086 on DOS. (This is Lattice C) + Microsoft C Compiler V2.03 for 8086 on DOS. (Still Lattice C) + Microsoft C Compiler V3.00 for 8086 on DOS. + QuickC 1.0 + Turbo C 2.0 + The syntax is old and reminds me of 7th grade summer vacation. + Much of this code is awkward to satisfy the lowest common denominator of many compilers. + unsigned long isn't supported in many older compilers, so long is used instead. + Early DOS and CP/M require register variabes to be int, not char or other types. + The perf improvement of using register-int instead of stack-char is worth it. +*/ + +#define LINT_ARGS + +#include + +#ifdef DOSTIME +#include +#include +#endif + +#define true 1 +#define false 0 + +/* Function Pointers are the fastest implementation for almost every compiler */ +#define UseFunPointers 1 +#define UseWinner2 2 +#define UseLookForWinner 3 +#define WinMethod UseFunPointers + +#define ABPrune true /* alpha beta pruning */ +#define WinLosePrune true /* stop early on win/lose */ +#define ScoreWin 6 +#define ScoreTie 5 +#define ScoreLose 4 +#define ScoreMax 9 +#define ScoreMin 2 +#define DefaultIterations 10 + +#define PieceX 1 +#define PieceO 2 +#define PieceBlank 0 + +typedef char ttype; /* 8-bit and 16-bit cpus do best with char aside from register in locals */ + +int g_Iterations = DefaultIterations; +ttype g_board[ 9 ]; + +#if WinMethod == UseFunPointers + +ttype pos0func() +{ + /* using "register int" instead of "ttype" for x is faster on 8086 and Z80 */ + register int x = g_board[0]; + + if ( ( x == g_board[1] && x == g_board[2] ) || + ( x == g_board[3] && x == g_board[6] ) || + ( x == g_board[4] && x == g_board[8] ) ) + return x; + return PieceBlank; +} + +ttype pos1func() +{ + register int x = g_board[1]; + + if ( ( x == g_board[0] && x == g_board[2] ) || + ( x == g_board[4] && x == g_board[7] ) ) + return x; + return PieceBlank; +} + +ttype pos2func() +{ + register int x = g_board[2]; + + if ( ( x == g_board[0] && x == g_board[1] ) || + ( x == g_board[5] && x == g_board[8] ) || + ( x == g_board[4] && x == g_board[6] ) ) + return x; + return PieceBlank; +} + +ttype pos3func() +{ + register int x = g_board[3]; + + if ( ( x == g_board[4] && x == g_board[5] ) || + ( x == g_board[0] && x == g_board[6] ) ) + return x; + return PieceBlank; +} + +ttype pos4func() +{ + register int x = g_board[4]; + + if ( ( x == g_board[0] && x == g_board[8] ) || + ( x == g_board[2] && x == g_board[6] ) || + ( x == g_board[1] && x == g_board[7] ) || + ( x == g_board[3] && x == g_board[5] ) ) + return x; + return PieceBlank; +} + +ttype pos5func() +{ + register int x = g_board[5]; + + if ( ( x == g_board[3] && x == g_board[4] ) || + ( x == g_board[2] && x == g_board[8] ) ) + return x; + return PieceBlank; +} + +ttype pos6func() +{ + register int x = g_board[6]; + + if ( ( x == g_board[7] && x == g_board[8] ) || + ( x == g_board[0] && x == g_board[3] ) || + ( x == g_board[4] && x == g_board[2] ) ) + return x; + return PieceBlank; +} + +ttype pos7func() +{ + register int x = g_board[7]; + + if ( ( x == g_board[6] && x == g_board[8] ) || + ( x == g_board[1] && x == g_board[4] ) ) + return x; + return PieceBlank; +} + +ttype pos8func() +{ + register int x = g_board[8]; + + if ( ( x == g_board[6] && x == g_board[7] ) || + ( x == g_board[2] && x == g_board[5] ) || + ( x == g_board[0] && x == g_board[4] ) ) + return x; + return PieceBlank; +} + +typedef ttype pfunc_t(); + +pfunc_t * winner_functions[9] = +{ + pos0func, + pos1func, + pos2func, + pos3func, + pos4func, + pos5func, + pos6func, + pos7func, + pos8func +}; + +#endif + +#if WinMethod == UseWinner2 + +ttype winner2( move ) ttype move; +{ + register int x; /* faster than ttype x on the stack */ + + switch( move ) /* msc v3 from 1985 generates a jump table! */ + { + case 0: + { + x = g_board[ 0 ]; + if ( ( ( x == g_board[1] ) && ( x == g_board[2] ) ) || + ( ( x == g_board[3] ) && ( x == g_board[6] ) ) || + ( ( x == g_board[4] ) && ( x == g_board[8] ) ) ) + return x; + break; + } + case 1: + { + x = g_board[ 1 ]; + if ( ( ( x == g_board[0] ) && ( x == g_board[2] ) ) || + ( ( x == g_board[4] ) && ( x == g_board[7] ) ) ) + return x; + break; + } + case 2: + { + x = g_board[ 2 ]; + if ( ( ( x == g_board[0] ) && ( x == g_board[1] ) ) || + ( ( x == g_board[5] ) && ( x == g_board[8] ) ) || + ( ( x == g_board[4] ) && ( x == g_board[6] ) ) ) + return x; + break; + } + case 3: + { + x = g_board[ 3 ]; + if ( ( ( x == g_board[4] ) && ( x == g_board[5] ) ) || + ( ( x == g_board[0] ) && ( x == g_board[6] ) ) ) + return x; + break; + } + case 4: + { + x = g_board[ 4 ]; + if ( ( ( x == g_board[0] ) && ( x == g_board[8] ) ) || + ( ( x == g_board[2] ) && ( x == g_board[6] ) ) || + ( ( x == g_board[1] ) && ( x == g_board[7] ) ) || + ( ( x == g_board[3] ) && ( x == g_board[5] ) ) ) + return x; + break; + } + case 5: + { + x = g_board[ 5 ]; + if ( ( ( x == g_board[3] ) && ( x == g_board[4] ) ) || + ( ( x == g_board[2] ) && ( x == g_board[8] ) ) ) + return x; + break; + } + case 6: + { + x = g_board[ 6 ]; + if ( ( ( x == g_board[7] ) && ( x == g_board[8] ) ) || + ( ( x == g_board[0] ) && ( x == g_board[3] ) ) || + ( ( x == g_board[4] ) && ( x == g_board[2] ) ) ) + return x; + break; + } + case 7: + { + x = g_board[ 7 ]; + if ( ( ( x == g_board[6] ) && ( x == g_board[8] ) ) || + ( ( x == g_board[1] ) && ( x == g_board[4] ) ) ) + return x; + break; + } + case 8: + { + x = g_board[ 8 ]; + if ( ( ( x == g_board[6] ) && ( x == g_board[7] ) ) || + ( ( x == g_board[2] ) && ( x == g_board[5] ) ) || + ( ( x == g_board[0] ) && ( x == g_board[4] ) ) ) + return x; + break; + } + } + + return PieceBlank; +} /*winner2*/ + +#endif + +#if WinMethod == UseLookForWinner + +ttype LookForWinner() +{ + register int p = g_board[0]; /* faster as register int than ttype on 8086 and Z80 */ + if ( PieceBlank != p ) + { + if ( p == g_board[1] && p == g_board[2] ) + return p; + + if ( p == g_board[3] && p == g_board[6] ) + return p; + } + + p = g_board[3]; + if ( PieceBlank != p && p == g_board[4] && p == g_board[5] ) + return p; + + p = g_board[6]; + if ( PieceBlank != p && p == g_board[7] && p == g_board[8] ) + return p; + + p = g_board[1]; + if ( PieceBlank != p && p == g_board[4] && p == g_board[7] ) + return p; + + p = g_board[2]; + if ( PieceBlank != p && p == g_board[5] && p == g_board[8] ) + return p; + + p = g_board[4]; + if ( PieceBlank != p ) + { + if ( ( p == g_board[0] ) && ( p == g_board[8] ) ) + return p; + + if ( ( p == g_board[2] ) && ( p == g_board[6] ) ) + return p; + } + + return PieceBlank; +} /*LookForWinner*/ + +#endif + +int g_IMoves = 0; + +ttype MinMax( alpha, beta, depth, move ) ttype alpha; ttype beta; ttype depth; ttype move; +{ + ttype pieceMove, score; /* better perf with char than int. out of registers so use stack */ + register int p, value; /* better perf with these as an int on Z80, 8080, and 8086 */ + + g_IMoves++; + + if ( depth >= 4 ) + { +#if WinMethod == UseFunPointers + p = ( * winner_functions[ move ] )(); +#endif +#if WinMethod == UseWinner2 + p = winner2( move ); +#endif +#if WinMethod == UseLookForWinner + p = LookForWinner(); +#endif + + if ( PieceBlank != p ) + { + if ( PieceX == p ) + return ScoreWin; + + return ScoreLose; + } + + if ( 8 == depth ) + return ScoreTie; + } + + if ( depth & 1 ) + { + value = ScoreMin; + pieceMove = PieceX; + } + else + { + value = ScoreMax; + pieceMove = PieceO; + } + + for ( p = 0; p < 9; p++ ) + { + if ( PieceBlank == g_board[ p ] ) + { + g_board[p] = pieceMove; + score = MinMax( alpha, beta, depth + 1, p ); + g_board[p] = PieceBlank; + + if ( depth & 1 ) + { +#if WinLosePrune /* #if statements must be in first column for MS C 1.0 */ + if ( ScoreWin == score ) + return ScoreWin; +#endif + + if ( score > value ) + { + value = score; + +#if ABPrune + if ( value >= beta ) + return value; + if ( value > alpha ) + alpha = value; +#endif + } + } + else + { +#if WinLosePrune + if ( ScoreLose == score ) + return ScoreLose; +#endif + + if ( score < value ) + { + value = score; + +#if ABPrune + if ( value <= alpha ) + return value; + if ( value < beta ) + beta = value; +#endif + } + } + } + } + + return value; +} /*MinMax*/ + +long g_Moves = 0; + +int FindSolution( position ) ttype position; +{ + register int i; + + for ( i = 0; i < 9; i++ ) + g_board[ i ] = PieceBlank; + + g_board[ position ] = PieceX; + + for ( i = 0; i < g_Iterations; i++ ) + { + g_IMoves = 0; + MinMax( ScoreMin, ScoreMax, 0, position ); + g_Moves += g_IMoves; /* do the 4-byte long addition once per loop to save work */ + } + + return 0; +} /*FindSolution*/ + +#ifdef CPMTIME + +struct CPMTimeValue +{ + int h, m, s, l; +}; + +void print_time_now() +{ + /* This CP/M BDOS call of 105 is only implemented in NTVCM -- it's not a standard CP/M 2.2 call */ + + struct CPMTimeValue t; + t.h = t.m = t.s = t.l = 0; + + bdos( 105, &t ); + printf( "current time: %02d:%02d:%02d.%02d\n", t.h, t.m, t.s, t.l ); +} /*print_time_now*/ + +long get_ms() +{ + /* This CP/M BDOS call of 105 is only implemented in NTVCM -- it's not a standard CP/M 2.2 call */ + + long h, m, s, l; + struct CPMTimeValue t; + t.h = t.m = t.s = t.l = 0; + + bdos( 105, &t ); + h = t.h; + m = t.m; + s = t.s; + l = t.l; + + return h * 3600000 + m * 60000 + s * 1000 + l * 10; +} /*get_ms*/ + +#else /* no elif with old compilers */ + +#ifdef DOSTIME + +void print_time_now() +{ + /* Make a DOS interrupt call to get the time */ + + union REGS wrIn, wrOut; + + wrIn.h.ah = 0x2c; + intdos( &wrIn, &wrOut ); + printf( "current time: %02d:%02d:%02d.%02d\n", wrOut.h.ch, wrOut.h.cl, wrOut.h.dh, wrOut.h.dl ); + fflush( stdout ); +} /*print_time_now*/ + +long get_ms() +{ + /* this function takes about 3 milliseconds on the original IBM PC */ + + long h, m, s, l; + union REGS wrIn, wrOut; + + wrIn.h.ah = 0x2c; + intdos( &wrIn, &wrOut ); + + h = wrOut.h.ch; + m = wrOut.h.cl; + s = wrOut.h.dh; + l = wrOut.h.dl; + + return h * 3600000 + m * 60000 + s * 1000 + l * 10; +} /*get_ms*/ + +#else + +/* must do this on actual CP/M machines */ + +int print_time_now() { return 0; } +long get_ms() { return 0; } + +#endif +#endif + +int main( argc, argv ) int argc; char * argv[]; +{ + long start_time, end_time; + + if ( 2 == argc ) + sscanf( argv[ 1 ], "%d", &g_Iterations ); /* no atoi in MS C 1.0 */ + + start_time = get_ms(); + + FindSolution( 0 ); + FindSolution( 1 ); + FindSolution( 4 ); + + end_time = get_ms(); + + printf( "runtime in ms: %ld\n", end_time - start_time ); + printf( "move count: %ld\n", g_Moves ); /* 6493 * g_Iterations */ + printf( "iteration count: %d\n", g_Iterations ); + printf( "method: %s\n", + ( WinMethod == UseFunPointers ) ? "function pointers" : + ( WinMethod == UseWinner2 ) ? "winner2" : + ( WinMethod == UseLookForWinner ) ? "look for winner" : + "invalid method" ); + return 0; +} /*main*/ + diff --git a/Mix Power C v1/UNGETC.C b/Mix Power C v1/UNGETC.C new file mode 100644 index 0000000..fc01eb8 --- /dev/null +++ b/Mix Power C v1/UNGETC.C @@ -0,0 +1,51 @@ +/* ungetc and ungetch - reverse getc, getch */ +/* Copyright (c) Mix Software 1988 */ + +/* Replace character in buffer. Will always work for at least + one character. For buffered files, ungetc can be called + mulitiple times until the beginning of the buffer is reached. + Returns EOF if unable to save character. + */ +ungetc(c,fp) +int c; +FILE *fp; +{ + if (c != EOF) { + fp->file.eofflag = 0; + if (fp->file.bufr) { + if (fp->file.bufr == fp->file.ptr) { + if (fp->file.count == 0) { + *fp->file.ptr = c; + fp->file.count = 1; + } + else return EOF; + } + else { + *(--fp->file.ptr) = c; + ++fp->file.count; + } + } + else { + fp->file.ptr = &fp->file.ungetch; + *fp->file.ptr = c; + fp->file.count = 1; + } + } + return c; +} + +/* ------------------------------------------------------------ */ +/* Reverse action of getch (unbuffered input from keyboard). + Only one character can be saved; returns EOF if unable to + save the character. + */ +ungetch(c) +int c; +{ + extern char _ungetch; + if (_ungetch != EOF) return EOF; + _ungetch = c; + return c; +} + +int _ungetch = EOF; diff --git a/Mix Power C v1/WRITE.ASM b/Mix Power C v1/WRITE.ASM new file mode 100644 index 0000000..cf9aa45 --- /dev/null +++ b/Mix Power C v1/WRITE.ASM @@ -0,0 +1,390 @@ +; +; Copyright (c) Mix Software 1988 +; +; fwrite(buffer,itemsize,no_of_items,fp) +; char *buffer; +; int itemsize; +; int no_of_items; +; FILE *fp; +; { return (_write(fp,buffer,itemsize*no_of_items) / itemsize); } +; + IDT fwrite + DEF fwrite + FREF _write +fwrite MOV BX,SP + MOV AX,[BX][%PARM2-2] ; # of items + MOV CX,[BX][%PARM3-2] ; item count + CMP AX,1 + JZ FWRITE1SZ ; avoid multiply by 1 + CMP CX,%1 + JZ FWRITE1I ; avoid multiply by 1 + MUL CX + PUSH AX ; pass count to _write + PUSH [BX][%PARM1-2] ; pass file pointer + PUSH [BX][%PARM4-2] ; pass address + CALLFAR _write + ADD SP,%6 + CMP AX,-1 + JZ ERROR + MOV BX,SP + MOV CX,[BX][%PARM2-2] ; item size + CWD + DIV CX ; convert byte count to item count + RETSEG +ERROR XOR AX,AX + RETSEG +; +; Item size is 1 +; +FWRITE1SZ PUSH CX + PUSH [BX][%PARM1-2] + PUSH [BX][%PARM4-2] + CALLFAR _write + ADD SP,%6 + CMP AX,-1 + JZ ERROR + RETSEG +; +; Number of items is 1 +; +FWRITE1I PUSH AX + PUSH [BX][%PARM1-2] + PUSH [BX][%PARM4-2] + CALLFAR _write + ADD SP,%6 + CMP AX,-1 + JZ ERROR + MOV BX,SP + CMP AX,[BX][%PARM2-2] ; is size == 1? + JZ ONE ; skip divide by 1 + MOV CX,[BX][%PARM2-2] + CWD + DIV CX + RETSEG +ONE MOV AX,1 + RETSEG + END +; +; ------------------------------------------------------------ +; +; _write(fp, bufptr, n) +; int n; +; FILE *fp; +; char *bufptr; +; + IDT _write + DEF _write + FREF _fflush + FREF _rflush + FREF _putc + FREF _seekend + REF _fileerr +_write PUSH BP + MOV BP,SP + MOV BX,[BP][%PARM1] + TEST BX,BX + JZ FILEERR +; +; if (fp == NULL || !fp->file.init || !fp->file.openflg) return 0; +; +; TEST BX,BX ; File ok? +; JZ ENDFL +; CMP %[BX][%FD$INIT],%0 +; JZ ENDFL +; CMP %[BX][%FD$OPEN],%0 +; JZ ENDFL +; +; if (fp->file.dirty & fdread) { +; if (_rflush(fp) != 0) return EOF; +; } +; + TEST %[BX][%FD$DIRTY],%FL$READ + JNZ FLUSH ; file has been read, flush buffer +; +; if (fp->file.flags & fdfilter) { +; +NOFLUSH MOV AL,[BX][%FD$FLAGS] + TEST AL,%FL$UNBUF ; unbuffered file? + JNZ UNBUFR + TEST AL,%FL$LFEED ; text mode? + JZ NOCR +; +; Write and insert carriage return before linefeed +; +; while (n-- != 0) { +; if ((c = *bufptr++) == NEWLINE) { +; if (_putc(RETURN,fp) != RETURN) return EOF; +; } +; if (_putc(c,fp) != c) return EOF; +; } +; +; bx = file +; di = file buffer +; si = buffer address +; dx = count remaining +; cx = buffer count +; + MOV SI,[BP][%PARM2] + MOV DX,[BP][%PARM3] ; Requested count + TEST DX,DX + JZ DONE1 + MOV DI,[BX][%FD$PTR] + MOV CX,[BX][%FD$COUNT] + JCXZ MORE1 + MOV AX,DS + MOV ES,AX +COPY1 LODSB ; Get a byte +NEXTCH1 CMP AL,>0A + JZ ADDCR +COPY1A STOSB ; Store in file buffer + DEC DX ; count character + JZ DONE1A ; read complete + LOOP COPY1 +MORE1 CALL PUTBLK + JB FILEERR + MOV AX,DS + MOV ES,AX + JMPS COPY1 +ADDCR MOV AL,>0D + STOSB + MOV AL,>0A + LOOP COPY1A + CALL PUTBLK + JB FILEERR + MOV AX,DS + MOV ES,AX + MOV AL,>0A + JMPS COPY1A +DONE1A DEC CX +DONE1B MOV [BX][%FD$COUNT],CX + MOV [BX][%FD$PTR],DI + CMP DI,[BX][%FD$BUFR] + JZ DONE1 + MOV %[BX][%FD$DIRTY],%FL$WRITE +DONE1 MOV AX,[BP][%PARM3] + SUB AX,DX + POP BP + RETSEG +NOCR JMP NOCR1 +; +FILEERR2 POP CX + POP SI +FILEERR MOV AX,-1 + POP BP + RETSEG +; +FLUSH PUSH BX + CALLFAR _rflush + POP BX + TEST AX,AX + JZ NOFLUSH + JMPS FILEERR +; +; File is not buffered +; +UNBUFR TEST AL,%FL$BIN + JZ UNBUFR0 + JMP DIRECT +UNBUFR0 MOV CX,[BP][%PARM3] + JCXZ UBDONE + MOV SI,[BP][%PARM2] +UNBLOOP LODSB + CMP AL,>0A + JZ UBCR + XOR AH,AH +UBPUT PUSH SI + PUSH CX +UBPUT2 PUSH BX + PUSH AX + CALLFAR _putc + POP DX + POP BX + POP CX + POP SI + CMP AX,-1 + JZ FILEERR + LOOP UNBLOOP +UBDONE MOV AX,[BP][%PARM3] + POP BP + RETSEG +; +UBCR TEST %[BX][FD$FLAGS],%FL$LFEED + JZ UBPUT + PUSH SI + PUSH CX + PUSH BX + MOV AX,>000D + PUSH AX + CALLFAR _putc + POP DX + POP BX + CMP AX,-1 + JZ FILEERR2 + MOV AX,>000A + JMPS UBPUT2 +DIRECT1 JMP DIRECT +; +; File is binary and buffered +; +NOCR1 MOV AX,[BP][%PARM3] ; Length of write + CMP AX,[BX][%FD$BUFSZ] + JA DIRECT1 ; Use direct file io + XOR DX,DX ; already done is 0 + MOV SI,[BP][%PARM2] ; buffer pointer + MOV DI,[BX][%FD$PTR] +BINMOVE MOV CX,[BX][%FD$COUNT] + JCXZ NOMOVE + MOV AX,[BP][%PARM3] + SUB AX,DX ; Additional needed + CMP CX,AX + JB MOVEALL + MOV CX,AX ; Use only part of buffer +MOVEALL PUSH CX + MOV AX,DS + MOV ES,AX + MOV DI,[BX][%FD$PTR] + CLD + REP + MOVSB + POP CX + SUB [BX][%FD$COUNT],CX + MOV [BX][%FD$PTR],DI + MOV %[BX][%FD$DIRTY],%FL$WRITE +; +; CX contains count of moved characters +; +NOMOVE ADD DX,CX + MOV CX,[BP][%PARM3] + SUB CX,DX ; Characters left + JCXZ DONE4 + TEST %[BX][%FD$DIRTY],%FL$WRITE + JZ NOWRITE + TEST %[BX][%FD$FLAGS],%FL$APPEN + JZ W1 + PUSH SI + PUSH DI + PUSH CX + PUSH DX + PUSH BX + CALLFAR _seekend + POP BX + POP DX + POP CX + POP DI + POP SI +W1 MOV AX,>4000 + PUSH DX + PUSH BX + MOV %[BX][%FD$DIRTY],%0 + MOV DX,[BX][%FD$BUFR] + MOV [BX][%FD$PTR],DX + MOV CX,DI + SUB CX,DX + MOV BX,[BX][%FD$HNDL] + JCXZ EMPTY + INT >21 + POP BX + POP DX + JNB OK1 +FLERROR PUSH DX + PUSH BX + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + POP BX + POP BX + POP DX + MOV [BX][%FD$COUNT],0 +DONE4 MOV AX,DX + POP BP + RETSEG +EMPTY POP BX + POP DX + XOR AX,AX +; +OK1 CMP AX,CX + MOV AX,[BX][%FD$BUFSZ] + MOV [BX][%FD$COUNT],AX + JZ BINMOVE0 + MOV AX,E$NOSPAC + JMPS FLERROR +NOWRITE MOV CX,[BX][%FD$BUFSZ] + MOV [BX][%FD$COUNT],CX + MOV CX,[BX][%FD$BUFR] + MOV [BX][%FD$PTR],CX +BINMOVE0 JMP BINMOVE +; +DIRECT TEST %[BX][%FD$DIRTY],%FL$WRITE + JZ DIR1 + PUSH BX + CALLFAR _fflush + POP BX +DIR1 MOV AX,[BX][%FD$BUFR] + MOV [BX][%FD$PTR],AX + MOV [BX][%FD$COUNT],0 + MOV %[BX][%FD$DIRTY],0 + TEST %[BX][%FD$FLAGS],%FL$APPEN + JZ W2 + PUSH BX + CALLFAR _seekend + POP BX +W2 MOV AX,>4000 + MOV BX,[BX][%FD$HNDL] + MOV CX,[BP][%PARM3] + MOV DX,[BP][%PARM2] + INT >21 + JB FLERROR + POP BP + RETSEG +; +; Write the file buffer +; bx = file +; di = current pointer +; resets di to start of buffer, cx to length +; +PUTBLK PUSH DX + PUSH BX + MOV DX,[BX][%FD$BUFR] + MOV CX,DI + SUB CX,DX ; buffer count + JCXZ EMPTY2 + TEST %[BX][%FD$FLAGS],%FL$APPEN + JZ W3 + PUSH SI + PUSH DI + PUSH CX + PUSH DX + PUSH BX + CALLFAR _seekend + POP BX + POP DX + POP CX + POP DI + POP SI +W3 MOV AX,>4000 + MOV BX,[BX][%FD$HNDL] + INT >21 + POP BX + POP DX + JB ERROR +EXITPUT MOV DI,[BX][%FD$BUFR] + MOV CX,[BX][%FD$BUFSZ] + MOV %[BX][%FD$DIRTY],%0 + CLC + RET +EMPTY2 POP BX + POP DX + JMPS EXITPUT +ERROR POP BX + PUSH BX + PUSH BX + PUSH AX + MOV BX,[_fileerr] + CALLSEG [BX] + ADD SP,%4 + POP BX + POP DX + STC + RET +; + END diff --git a/Mix Power C v1/m.bat b/Mix Power C v1/m.bat new file mode 100644 index 0000000..55cf07b --- /dev/null +++ b/Mix Power C v1/m.bat @@ -0,0 +1,9 @@ +rem: this will crash because pc.exe trashes its own stack. but that's after it's done + +ntvdm pc /c /ms /dpowerc /j /fi /q %1.c 1>nul 2>nul + +ntvdm pcl %1 + +del %1.mix 1>nul 2>nul + +