home *** CD-ROM | disk | FTP | other *** search
- { (C) Copyright 1986-1992 MetaWare Incorporated; Santa Cruz, CA 95060. }
-
- pragma C_include('implement.pf');
-
- package MSDOS;
- pragma Routine_aliasing_convention(Implement.RTE_aliasing);
- type byte = 0..255;
- word = Implement.Byte_count; -- See Implement.pf.
- with Loopholes:[Address,Longptr];
- #if 0
- Use these routines to communicate directly with MS-DOS if the
- routines supplied in the SYSTEM package are insufficient.
- To call MSDOS: Set the Register values the way you want them in
- the global Registers record.
- Then, call CALLDOS. CALLDOS will load the actual machine
- registers with the values in the register block below.
- Upon return, the Registers will contain the register contents
- when DOS returned. The Flags word contains the contents of the
- 808x flags register after MS-DOS returns.
- As a variation, CALLINT will call an arbitrary interrupt number,
- using the registers in a similar way. E.g., CALLINT(#21) = CALLDOS().
- #endif
- pragma data(common,Implement.RTE || 'dosregs');
- -- 4-byte register communication is provided for MS-DOS since DOS-extender
- -- software permits 32-bit offsets to DOS calls and provides translation.
- type Register = record
- case Boolean of
- True:(L,H:Byte); -- Lower & Upper portions of register.
- False:(R:Word); -- Entire register; 2 bytes/286, 4 bytes/386.
- -- However, segment regs are always 2 bytes, even on 386.
- end;
- type DOS_communication = record
- ax,bx,cx,dx,
- si,di,ds,es: Register;
- -- The rightmost bit of Flags is the carry bit. MS-DOS usually sets
- -- carry if an error occurs.
- -- Thus, if Flags is odd on return, an error occurred;
- -- ax contains the error number #.
- Flags: Word;
- end;
- #if 0
- Here are the registers to modify. You can either assign into
- these registers directly, or create your own DOS_communication
- block of registers and assign that block into Registers before
- calling CALLDOS.
- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- >> WARNING!!! The run-time library uses CALLDOS and this Registers <<
- >> variable. So DO NOT expect it to be preserved across calls to <<
- >> the library that require DOS communication (e.g., Professional Pascal <<
- >> "writeln" or High C "printf"). <<
- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- #endif
- var Registers: DOS_communication;
- pragma data;
-
- -- Use this for your own direct communication with MS-DOS.
- procedure CALLDOS; external;
- procedure CALLINT(INT:Integer); external;
-
- -- This gets the value of the DS register. Use it with small-data
- -- models to set Registers.DS, since the Adr function returns only
- -- the 16-bit offset.
- function GETDS():Cardinal; external;
-
- -- The following are private and should not be used.
- procedure DOS(I:Byte); external;
- procedure Load_ptr(var Rs,Rd: register; A:Address); external;
- procedure Load_DS_DX(A:Address); external;
- procedure DOS_Name(const Name:string; I:Byte); external;
- procedure C_DOS_name(Name:Implement.Charp; I:Byte); external;
- procedure Set_DMA(A:Address); External;
- -- The preceding is valid only for MS-DOS, not for OS/2.
-
- type Strcopy = packed array[1..100] of char;
- -- Convert Pstring to a nul-terminated string, placing result in Buf.
- -- Also, return address of Buf. Remove trailing blanks in Pstring
- -- (due to DOS 2.1 bug on file open on some "compatibles").
- function Cstring(const Pstring:String; var Buf:Strcopy):Address; External;
- -- Used by library implementation to handle differences between
- -- C and Pascal strings:
- -- Set Errno after call to OS/2:
- procedure Doerr(Err:Cardinal); External;
-
- #define LongAdr(X) Retype(Adr(X),Longptr)
- #if HCLIB
- #define DOS_name(N,X) C_dos_name(N,X)
- #define Stringparm(Name) Name:Charp
- #define Stringproc(Pname,Cname) Cname
- #define definebuf -- OS/2 use.
- #define Makestring(S) Retype(S,Longptr) -- OS/2 use.
- #else
- #define DOS_name(N,X) DOS_name(N,X)
- #define Stringparm(Name) const Name:String
- #define Stringproc(Pname,Cname) Pname
- #define definebuf var Buf:Strcopy; -- OS/2 use.
- #define Makestring(S) Retype(Cstring(S,Buf),Longptr) -- OS/2 use.
- #endif
- end;
- #if 0
- Here's an extended example of how to use CALLDOS:
- pragma include('msdos.pf');
- with msdos;
- program p;
- function KB_status(var C:Char):Boolean;
- begin
- Registers.AX.H := #B;
- Calldos;
- C := Chr(Registers.AX.L);
- return(C <> chr(0));
- end;
- function KB_input_no_echo:Char;
- begin
- Registers.AX.H := #8;
- Calldos;
- return(Chr(Registers.AX.L));
- end;
- procedure KB_write_char(C:Char);
- begin
- Registers.AX.H := 2; Registers.DX.L := Ord(C);
- Calldos;
- end;
- procedure KB_write_string(const S:String);
- with Loopholes:[Address,Adr,Sizeof];
- var Cheat: record case boolean of
- True: (A:Address);
- False: (Offset, Segment: Word);
- -- Segment not present in small-data models.
- end;
- with Registers;
- begin
- AX.H := #9;
- Cheat.A := Adr(S[1]);
- DX.R := Cheat.Offset;
- -- A little tricky here: must set Registers.DS to the segment
- -- value for S if non-small-data; otherwise, to the current value of DS.
- -- That's the reason for the GETDS function.
- if Sizeof(Address) > 2 then DS.R := Cheat.Segment
- else DS.R := GETDS();
- CallDOS;
- end;
- var I,J:Integer; C:Char;
- const CRLF = Chr(#0d) || Chr(#0a);
- begin
- while not KB_status(C) do begin
- for I := 1 to 3000 do J := I;
- KB_write_string('I''m waiting for you to type a character...' || crlf || '$');
- end;
- KB_write_string('Thank you for typing the character:$');
- KB_write_char(KB_input_no_echo());
- end.
-