microsoft pascal v4

This commit is contained in:
davidly 2024-07-01 21:27:27 -07:00
parent 888551a4fc
commit f23632d0be
57 changed files with 2210 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

42
Microsoft Pascal v4/E.PAS Normal file
View File

@ -0,0 +1,42 @@
program e;
const
DIGITS = 200;
type
arrayType = array[ 0..DIGITS ] of integer;
var
high, n, x : integer;
a : arrayType;
begin
high := DIGITS;
x := 0;
n := high - 1;
while n > 0 do begin
a[ n ] := 1;
n := n - 1;
end;
a[ 1 ] := 2;
a[ 0 ] := 0;
while high > 9 do begin
high := high - 1;
n := high;
while 0 <> n do begin
a[ n ] := x MOD n;
x := 10 * a[ n - 1 ] + x DIV n;
n := n - 1;
end;
Write( x );
end;
writeln;
writeln( 'done' );
end.


View File

@ -0,0 +1,10 @@
Interface;
Unit Clock(GetDat,SetDat,GetTim,SetTim);
Procedure GetDat(Vars Year,Month,Day:Integer);
Function SetDat(Year,Month,Day:Integer):Boolean;
Procedure GetTim(Vars Hours,Minutes,Seconds,Hundreds:Integer);
Function SetTim(Hours,Minutes,Seconds,Hundreds:Integer):Boolean;
End;

View File

@ -0,0 +1,82 @@
{MS-Pascal / MS-FORTRAN FCB Declaration Include File}
INTERFACE; UNIT
FILKQQ (FCBFQQ,
accessmodes,
am_read,
am_readwrite,
am_write,
am_default,
SHAREMODES,
sm_compat,
sm_denyrw,
sm_denywr,
sm_denyrd,
sm_denynone,
FILEMODES,
SEQUENTIAL,
TERMINAL,
DIRECT,
fm_sequential,
fm_direct,
fm_terminal);
TYPE
FILEMODES = (SEQUENTIAL, TERMINAL, DIRECT);
SHAREMODES = (sm_compat, sm_denyrw, sm_denywr, sm_denyrd, sm_denynone);
accessmodes = (am_read, am_write, am_readwrite, am_default);
FCBFQQ = RECORD {byte offsets start every field comment}
{fields accessible by Pascal user as <file variable>.<field>}
TRAP: BOOLEAN; {00 Pascal user trapping errors if true}
ERRS: WRD(0)..18; {01 error status, set only by all units}
MODE: FILEMODES; {02 user file mode; not used in unit U}
SHARE:SHAREMODES; {03 pad to word bound, special user use}
{fields shared by units F, V, U; ERRC / ESTS are write-only}
ERRC: WORD; {04 error code, error exists if nonzero}
{1000..1099: set for unit U errors}
{1100..1199: set for unit F errors}
{1200..1299: set for unit V errors}
ESTS: WORD; {06 error specific data usually from OS}
CMOD: FILEMODES; {08 system file mode; copied from MODE}
{fields set / used by units F and V, and read-only in unit U}
TXTF: BOOLEAN; {09 true: formatted / ASCII / TEXT file}
{false: not formatted / binary file}
SIZE: WORD; {10 record size set when file is opened}
{DIRECT: always fixed record length}
{others: max buffer variable length}
IERF: BOOLEAN; {12 Unit U Incomplete End Of Record }
{Kluge. Set false by opnuqq and }
{pccuqq, and true by peruqq. Thus }
{if true in wefuqq, it means that }
{there is an incomplete line, and }
{pccuqq should be called to flush }
{it. Only applies to terminal files}
access: accessmodes;{13 controls read/write modes }
OLDF: boolean; {14 true: must exist before open; RESET}
{false: can create on open; REWRITE}
INPT: BOOLEAN; {15 true: user is now reading from file}
{false: user is now writing to file}
RECL: WORD; {16 DIRECT record number, lo order word}
RECH: WORD; {18 DIRECT record number, hi order word}
USED: WORD; {20 number bytes used in current record}
{fields used internally by units F or V not needed by unit U}
LINK: ADR OF FCBFQQ;{22 DS offset address of next open file}
BADR: ADRMEM; {24 F: DS offset address for buffer var}
TMPF: BOOLEAN; {26 F: is a temp file; delete on CLOSE}
FULL: BOOLEAN; {27 F: buffer variable lazy eval status}
UNFM: BOOLEAN; {28 V: for unformatted binary file mode}
OPEN: BOOLEAN; {29 F: file opened (by RESET / REWRITE)}
FUNT: INTEGER; {30 V: FORTRAN unit number (1 to 32767)}
ENDF: BOOLEAN; {32 V: last I/O statement was a ENDFILE}
{fields set / used by unit U, and read-only in units F and V}
REDY: BOOLEAN; {33 buffer ready if true; set by F / U}
BCNT: WORD; {34 number of data bytes actually moved}
EORF: BOOLEAN; {36 true if end of record read, written}
EOFF: BOOLEAN; {37 end of file flag set after EOF read}
{unit U (operating system) information starts here}
{end of section for unit U specific OS information}
END;
const fm_sequential = sequential;
fm_direct = direct;
fm_terminal = terminal;
END;

View File

@ -0,0 +1,96 @@
{MS-Pascal / MS-FORTRAN FCB Declaration Include File}
INTERFACE; UNIT
FILKQQ (FCBFQQ,
FILEMODES, SEQUENTIAL, TERMINAL, DIRECT,
fm_sequential, fm_terminal, fm_direct,
accessmodes,
am_read,
am_readwrite,
am_write,
am_default,
SHAREMODES,
sm_compat,
sm_denyrw,
sm_denywr,
sm_denyrd,
sm_denynone,
BUFFER_SIZE,
ADRFIELDS);
const
BUFFER_SIZE = 512;
ADRFIELDS = 2; {* Two ADR fields in the FCB, see NEWUQQ. *}
TYPE
FILEMODES = (SEQUENTIAL, TERMINAL, DIRECT);
SHAREMODES = (sm_compat, sm_denyrw, sm_denywr, sm_denyrd, sm_denynone);
accessmodes = (am_read, am_write, am_readwrite, am_default);
FCBFQQ = RECORD {byte offsets start every field comment}
{fields accessible by Pascal user as <file variable>.<field>}
TRAP: BOOLEAN; {00 Pascal user trapping errors if true}
ERRS: WRD(0)..18; {01 error status, set only by all units}
MODE: FILEMODES; {02 user file mode; not used in unit U}
SHARE:SHAREMODES; {03 pad to word bound, special user use}
{fields shared by units F, V, U; ERRC / ESTS are write-only}
ERRC: WORD; {04 error code, error exists if nonzero}
{1000..1099: set for unit U errors}
{1100..1199: set for unit F errors}
{1200..1299: set for unit V errors}
ESTS: WORD; {06 error specific data usually from OS}
CMOD: FILEMODES; {08 system file mode; copied from MODE}
{fields set / used by units F and V, and read-only in unit U}
TXTF: BOOLEAN; {09 true: formatted / ASCII / TEXT file}
{false: not formatted / binary file}
SIZE: WORD; {10 record size set when file is opened}
{DIRECT: always fixed record length}
{others: max buffer variable length}
IERF: BOOLEAN; {12 Unit U Incomplete End Of Record }
{Kluge. Set false by opnuqq and }
{pccuqq, and true by peruqq. Thus }
{if true in wefuqq, it means that }
{there is an incomplete line, and }
{pccuqq should be called to flush }
{it. Only applies to terminal files}
access: accessmodes;{13 Controls actual open mode }
OLDF: boolean; {14 true :must exist before open; RESET}
{false :can create on open; REWRITE}
INPT: BOOLEAN; {15 true: user is now reading from file}
{false: user is now writing to file}
RECL: WORD; {16 DIRECT record number, lo order word}
RECH: WORD; {18 DIRECT record number, hi order word}
USED: WORD; {20 number bytes used in current record}
{fields used internally by units F or V not needed by unit U}
LINK: ADR OF FCBFQQ;{22 DS offset address of next open file}
BADR: ADRMEM; {24 F: DS offset address for buffer var}
TMPF: BOOLEAN; {26 F: is a temp file; delete on CLOSE}
FULL: BOOLEAN; {27 F: buffer variable lazy eval status}
UNFM: BOOLEAN; {28 V: for unformatted binary file mode}
OPEN: BOOLEAN; {29 F: file opened (by RESET / REWRITE)}
FUNT: INTEGER; {30 V: FORTRAN unit number (1 to 32767)}
ENDF: BOOLEAN; {32 V: last I/O statement was a ENDFILE}
{fields set / used by unit U, and read-only in units F and V}
REDY: BOOLEAN; {33 buffer ready if true; set by F / U}
BCNT: WORD; {34 number of data bytes actually moved}
EORF: BOOLEAN; {36 true if end of record read, written}
EOFF: BOOLEAN; {37 end of file flag set after EOF read}
{unit U (operating system) information starts here}
{**********************************************************}
FILE_NAME : ^STRING; {* 38 points to file name *}
FDSCP : INTEGER; {* 42 actual file number *}
PREDEFINED : BOOLEAN; {* 44 True if file is a device. *}
FNER : BOOLEAN; {* 45 True if File name error. *}
BEGIN_BUFFER : INTEGER; {* 46 Start loc of buffer. *}
END_BUFFER : INTEGER; {* 48 top loc of buffer. *}
IEOF : BOOLEAN; {* 50 Flag if EOF ever seen. For ^Zs. *}
BUFFER : STRING(512); {* 52 Internal buffering. *}
PADBUF : STRING(65); {*564 Make same size as MSDOS. *}
{*630 + 4 = 634, see newuqq *}
{**********************************************************}
{end of section for unit U specific OS information}
END;
const fm_sequential = sequential;
fm_direct = direct;
fm_terminal = terminal;
END;

View File

@ -0,0 +1,137 @@
{MS-Pascal and Fortran OS Dependent File System Interface Unit}
INTERFACE; UNIT
FILUQQ (FNSUQQ, INPUQQ, OUTUQQ,
INIUQQ, OPNUQQ, CLSUQQ, CLDUQQ, ENDUQQ,
GETUQQ, PUTUQQ, PERUQQ, PCCUQQ, SEKUQQ,
GTYUQQ, PLYUQQ, PTYUQQ, GFNUQQ, PFNUQQ,
BUFUQQ, NEWUQQ, TFNUQQ, PPMUQQ,
NEFUQQ, DIFUQQ, IOCUQQ, DSNUQQ,
FPSUQQ, TFDUQQ, EOFUQQ, LKGUQQ );
USES FILKQQ;
TYPE
ERRORET = WORD; {return code, error if non-zero}
VAR
FNSUQQ: SET OF CHAR; {allowed chars in a filename}
INPUQQ, OUTUQQ: STRING (8); {filenames for user terminal}
PROCEDURE INIUQQ;
{Overall initialization call; set FNSUQQ, INPUQQ, and OUTUQQ}
FUNCTION OPNUQQ (VAR F: FCBFQQ): ERRORET;
{Open a file; INPT determines whether for input or output;
if OLDF true and file not found, error, else create file;
DIRECT mode record length is in SIZE;
file's mode is in CMOD, but if mode is SEQUENTIAL and
file is a terminal (or printer) reset CMOD to TERMINAL;
set EORF true; set EOFF to NOT INPT}
FUNCTION CLSUQQ (VAR F: FCBFQQ): ERRORET;
{CLOSE; close the file (if error occurs file assumed closed)}
FUNCTION CLDUQQ (VAR F: FCBFQQ): ERRORET;
{CLOSE DELETE; close the file and delete it (errors ignored)}
PROCEDURE DSNUQQ (VAR F:FCBFQQ);
{dispose a file name - noop on dos 1.25 unit U}
PROCEDURE ENDUQQ;
{Overall termination, all files should already be closed}
FUNCTION GETUQQ (VAR F: FCBFQQ; LEN: WORD; DST: ADSMEM): ERRORET;
{Copy bytes from the file to the string until the string fills,
an error occurs, or the end of record or end of file is found.
Set EOFF if last byte of file has already been read (not an error);
else copy from zero to UPPER(S) characters from the file to S.
Set BCNT to actual number of bytes copied (zero to UPPER(S));
value of bytes in S from BCNT+1 to UPPER(S) is undefined.
USED is always the number of bytes read from this record.
Use TXTF and CMOD as appropriate for various kinds of files:
If CMOD=SEQUENTIAL or TERMINAL and TXTF is true,
set EORF if last byte of record read and BCNT < UPPER (S).
If CMOD=TERMINAL, reading user line from a console:
If TXTF, read whole line with user editing and echo,
If NOT TXTF, read characters as typed, without echo.}
FUNCTION PUTUQQ (VAR F: FCBFQQ; LEN: WORD; SRC: ADSMEM): ERRORET;
{Copy bytes from string to file, at end of current record;
USED is always the number of bytes written to this record.
Set EORF false iff (CMOD=SEQUENTIAL or DIRECT) and TXTF true}
FUNCTION PERUQQ (VAR F: FCBFQQ): ERRORET;
{End writing the current record and setup to write the next;
Set EORF true iff CMOD=SEQUENTIAL or TERMINAL and TXTF true}
FUNCTION PCCUQQ (VAR F: FCBFQQ; CH: CHAR): ERRORET;
{Start of line carriage control; CMOD is TERMINAL;
CC is one of:
' ': single space (normal) '0': double space
'+': no spacing (overprint) '1': new page
EORF will always be true, set it false}
FUNCTION SEKUQQ (VAR F: FCBFQQ; LREC, HREC: WORD): ERRORET;
{Reposition direct-access file to record number LREC/HREC.}
FUNCTION GTYUQQ (LEN: WORD; DST: ADSMEM): WORD;
{Read up to LEN chars from user's terminal to DST, return number read}
PROCEDURE PLYUQQ;
{Output an end of record (crlf or equivalent) to the user's console}
PROCEDURE PTYUQQ (LEN: WORD; SRC: ADSMEM);
{Output LEN chars from SRC}
FUNCTION GFNUQQ (VAR F: FCBFQQ; LEN: WORD; DST: ADSMEM): WORD;
{Move filename to DST, max of LEN chars, return actual length}
PROCEDURE PFNUQQ (VAR F: FCBFQQ; LEN: WORD; SRC: ADSMEM);
{Get filename from SRC of length LEN, for use in later OPNUQQ calls}
{Pascal-only calls}
PROCEDURE BUFUQQ (VAR F: FCBFQQ);
{Wait for I/O transfer to finish, set REDY true (defer errors)}
PROCEDURE NEWUQQ (VAR F: FCBFQQ);
{Initialize OS dependent fields; SIZE and TXTF set (defer errors)}
PROCEDURE TFNUQQ (VAR F: FCBFQQ);
{Set the NAME field to a unique OS temporary filename (defer errors)}
FUNCTION PPMUQQ (LEN: WORD; ADRP: ADRMEM; VAR DST: LSTRING): ERRORET;
{Like GETUQQ, but used to read program parameters from user.
String P is a user prompt, which may or may not be used.
If user input string is shorter than UPPER(S), blank pad;
if it is longer, either re-prompt or give an error.
Called once per program parameter requested}
{Fortran-only calls}
FUNCTION NEFUQQ: ADRMEM;
{If possible, allocate a file of size BOFFQQ, initialize OS dependent
fields, and return the address of the FCB; else return zero}
PROCEDURE DIFUQQ (F: ADRMEM);
{Deallocate the file at address F of size BOFFQQ}
FUNCTION IOCUQQ (VAR F: FCBFQQ): ERRORET;
{Change from read to write or vice versa, based on new INPT value;
CMOD is SEQUENTIAL or TERMINAL; set EORF and EOFF as in OPNUQQ}
FUNCTION FPSUQQ (VAR F: FCBFQQ; RELPOS: INTEGER): ERRORET;
{Position RELPOS bytes forward(+), backward(-), or rewind(0).
If INPT is false, write eof first. Set EORF and EOFF as in OPNUQQ}
FUNCTION TFDUQQ (VAR F: FCBFQQ): ERRORET;
{Truncate DIRECT file before current record; CMOD is always DIRECT.
If truncation is difficult, ignore operation. Set EOFF true}
FUNCTION EOFUQQ (VAR F: FCBFQQ; VAR FEOF: BOOLEAN): ERRORET;
{Set FEOF true if next GETUQQ would return with EOFF true,
else set it false. If difficult to detect, just set it false}
function lkguqq (var f:fcbfqq; lkgmode: word; lrec, hrec: word;
recnum: integer4): erroret;
END;

View File

@ -0,0 +1,14 @@
Interface;
Unit Intrp(Reglist,Intrp);
Type
Reglist=Record
AX,BX,CX,DX,SI,DI,DS,ES,Flags:WORD
End;
Procedure Intrp(Intno:Byte;
Vars InRegs:Reglist;
Vars OutRegs:RegList);
End;

View File

@ -0,0 +1,8 @@
Interface;
Unit Port(InP,OutP);
Function InP(PortNo:Word):Byte;
Procedure OutP(PortNo:Word; Data:Byte);
End;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,31 @@
program sieve( INPUT, OUTPUT );
const
size = 8190;
type
flagType = array[ 0..size ] of boolean;
var
i, k, prime, count, iter : integer;
flags : flagType;
begin
for iter := 1 to 10 do begin
count := 0;
for i := 0 to size do flags[ i ] := true;
for i := 0 to size do begin
if flags[ i ] then begin
prime := i + i + 3;
k := i + prime;
while k <= size do begin
flags[ k ] := false;
k := k + prime;
end;
count := count + 1;
end;
end;
end;
writeln( 'count of primes: ', count );
end.

View File

@ -0,0 +1,113 @@
; TOOLS.INI file for BRIEF(tm) configuration
[M]
Arg:Alt+A
Argcompile:Alt+F10
Assign:F7
Backtab:Shift+Tab
Begline:Home
Cancel:Esc
Cdelete:Bksp
Compile:Ctrl+N
Copy:Num+
Down:Down
Endline:End
Execute:F10
Exit:Alt+X
Help:Alt+H
Home:Ctrl+Home
Information:Alt+B
Initialize:Shift+F10
Insertmode:Alt+I
Lasttext:Alt+L
Ldelete:Alt+D
Left:Left
Linsert:Ctrl+Enter
Mark:Alt+M
Meta:F9
Mlines:ctrl+U
Mpage:Pgup
Mpara:Ctrl+Pgup
Msearch:Alt+F5
Mword:Ctrl+Left
Newline:Enter
Paste:Ins
Pbal:Ctrl+[
Plines:Ctrl+d
Ppage:Pgdn
; ctrl+pgup & ctrl+pgdn
; can be mapped to "arg mpage" and "arg ppage" respectively
; to exactly simulate their BRIEF equivelents.
Ppara:Ctrl+Pgdn
Psearch:F5
Pword:Ctrl+Right
Qreplace:F6
Quote:Alt+Q
Refresh:Ctrl+]
Replace:Shift+F6
Right:Right
Sdelete:Del
Sdelete:Num-
Setfile:Alt+N
Setwindow:F2
Shell:Alt+Z
Sinsert:Ctrl+Ins
Tab:Tab
Undo:num*
Undo:ALT+U
Up:Up
Window:F1
save:=arg arg setfile
save:alt+w
;
; You can emulate Brief's ALT+O with arg arg <filename> setfile
;
setfile:alt+o
;
; a variation on paste is used to perform "paste a file into the buffer"
; So in BRIEF where a person typed: ALT+R <filename> the user instead
; types arg arg <filename> paste.
;
paste:alt+r
;
linemark:=arg down
linemark:alt+l
;
; column marks are distinguished from line marks through the command the
; Microsoft Editor is executing for the given argument. Therefore, column
; mark is the same as "arg"
;
arg:alt+c
;
; line to top
;
linetotop:=arg setwindow
linetotop:ctrl+t
;
; left and right side of window
;
LeftSideOfWindow:=meta left
RightSideOfWindow:=meta right
LeftSideOfWindow:shift+home
RightSideOfWindow:shift+end
;
; WINDOWS
;
; Creating a horizontal window at cursor pos. is F3's assign
;
;
CreateHorizWin:=arg window
CreateHorizWin:F3
;
; Resizing a Window will actually create a vertical window.
;
CreateVertWin:=arg arg window
CreateVertWin:F4
;
; Delete Current Window is F5
DeleteWindow:=meta window
DeleteWindow:F5
;
;
;
; BRIEF is a trademark of UnderWare, INC.

297
Microsoft Pascal v4/TTT.PAS Normal file
View File

@ -0,0 +1,297 @@
{ App to prove you can't win at Tic-Tac-Toe }
{ coded for Microsoft Pascal. Tested on v1.0, v3.3, and v4.0. }
{ requires djldos.obj, built from djldos.asm }
(*$DEBUG- *)
program ttt( output );
function getticks : word; External;
function pspbyte( offset : word ) : integer; External;
const
scoreWin = 6;
scoreTie = 5;
scoreLose = 4;
scoreMax = 9;
scoreMin = 2;
scoreInvalid = 0;
pieceBlank = 0;
pieceX = 1;
pieceO = 2;
iterations = 1;
type
boardType = array[ 0..8 ] of integer;
var
evaluated: integer;
board: boardType;
procedure dumpBoard;
var
i : integer;
begin
Write( '{' );
for i := 0 to 8 do
Write( board[i] );
Write( '}' );
end;
function lookForWinner : integer;
var
t, p : integer;
begin
{ dumpBoard; }
p := pieceBlank;
t := board[ 0 ];
if pieceBlank <> t then
begin
if ( ( ( t = board[1] ) and ( t = board[2] ) ) or
( ( t = board[3] ) and ( t = board[6] ) ) ) then
p := t;
end;
if pieceBlank = p then
begin
t := board[1];
if ( t = board[4] ) and ( t = board[7] ) then
p := t
else
begin
t := board[2];
if ( t = board[5] ) and ( t = board[8] ) then
p := t
else
begin
t := board[3];
if ( t = board[4] ) and ( t = board[5] ) then
p := t
else
begin
t := board[6];
if ( t = board[7] ) and ( t = board[8] ) then
p := t
else
begin
t := board[4];
if ( ( ( t = board[0] ) and ( t = board[8] ) ) or
( ( t = board[2] ) and ( t = board[6] ) ) ) then
p := t
end;
end;
end;
end;
end;
lookForWinner := p;
end;
function winner2( move: integer ) : integer;
var
x : integer;
begin
case move of
0: begin
x := board[ 0 ];
if not ( ( ( x = board[1] ) and ( x = board[2] ) ) or
( ( x = board[3] ) and ( x = board[6] ) ) or
( ( x = board[4] ) and ( x = board[8] ) ) )
then x := PieceBlank;
end;
1: begin
x := board[ 1 ];
if not ( ( ( x = board[0] ) and ( x = board[2] ) ) or
( ( x = board[4] ) and ( x = board[7] ) ) )
then x := PieceBlank;
end;
2: begin
x := board[ 2 ];
if not ( ( ( x = board[0] ) and ( x = board[1] ) ) or
( ( x = board[5] ) and ( x = board[8] ) ) or
( ( x = board[4] ) and ( x = board[6] ) ) )
then x := PieceBlank;
end;
3: begin
x := board[ 3 ];
if not ( ( ( x = board[4] ) and ( x = board[5] ) ) or
( ( x = board[0] ) and ( x = board[6] ) ) )
then x := PieceBlank;
end;
4: begin
x := board[ 4 ];
if not ( ( ( x = board[0] ) and ( x = board[8] ) ) or
( ( x = board[2] ) and ( x = board[6] ) ) or
( ( x = board[1] ) and ( x = board[7] ) ) or
( ( x = board[3] ) and ( x = board[5] ) ) )
then x := PieceBlank;
end;
5: begin
x := board[ 5 ];
if not ( ( ( x = board[3] ) and ( x = board[4] ) ) or
( ( x = board[2] ) and ( x = board[8] ) ) )
then x := PieceBlank;
end;
6: begin
x := board[ 6 ];
if not ( ( ( x = board[7] ) and ( x = board[8] ) ) or
( ( x = board[0] ) and ( x = board[3] ) ) or
( ( x = board[4] ) and ( x = board[2] ) ) )
then x := PieceBlank;
end;
7: begin
x := board[ 7 ];
if not ( ( ( x = board[6] ) and ( x = board[8] ) ) or
( ( x = board[1] ) and ( x = board[4] ) ) )
then x := PieceBlank;
end;
8: begin
x := board[ 8 ];
if not ( ( ( x = board[6] ) and ( x = board[7] ) ) or
( ( x = board[2] ) and ( x = board[5] ) ) or
( ( x = board[0] ) and ( x = board[4] ) ) )
then x := PieceBlank;
end;
end;
winner2 := x;
end;
function minmax( alpha: integer; beta: integer; depth: integer; move: integer ): integer;
var
p, val, pieceMove, score : integer;
begin
evaluated := evaluated + 1;
val := scoreInvalid;
if depth >= 4 then
begin
p := winner2( move ); { lookForWinner; }
if p <> pieceBlank then
begin
if p = pieceX then
val := scoreWin
else
val := scoreLose
end
else if depth = 8 then
val := scoreTie;
end;
if val = scoreInvalid then
begin
if Odd( depth ) then
begin
val := scoreMin;
pieceMove := pieceX;
end
else
begin
val := scoreMax;
pieceMove := pieceO;
end;
p := 0;
repeat
if board[ p ] = pieceBlank then
begin
board[ p ] := pieceMove;
score := minmax( alpha, beta, depth + 1, p );
board[ p ] := pieceBlank;
if Odd( depth ) then
begin
if ( score > val ) then
begin
val := score;
if ( val = scoreWin ) or ( val >= beta ) then p := 10
else if ( val > alpha ) then alpha := val;
end;
end
else
begin
if ( score < val ) then
begin
val := score;
if ( val = scoreLose ) or ( val <= alpha ) then p := 10
else if ( val < beta ) then beta := val;
end;
end;
end;
p := p + 1;
until p > 8;
end;
minmax := val;
end;
function firstArgAsInt : integer;
var
psp, offset : word;
c, result : integer;
location : ads of byte;
begin
result := 0;
offset := 128;
c := pspbyte( offset );
if c > 0 then begin
offset := offset + 2; { past length and space }
c := pspbyte( offset );
while ( ( c >= 48 ) and ( c <= 57 ) ) do
begin
result := result * 10;
result := result + c - 48;
offset := offset + 1;
c := pspbyte( offset );
end;
end;
firstArgAsInt := result;
end;
procedure runit( move : integer );
var
score: integer;
begin
board[move] := pieceX;
score := minmax( scoreMin, scoreMax, 0, move );
board[move] := pieceBlank;
end;
var
i, loops : integer;
startTicks, endTicks: word;
begin
i := firstArgAsInt;
if 0 <> i then loops := i
else loops := Iterations;
for i := 0 to 8 do
board[i] := pieceBlank;
WriteLn( 'begin' );
startTicks := getticks;
for i := 1 to loops do
begin
evaluated := 0; { once per loop to prevent overflow }
runit( 0 );
runit( 1 );
runit( 4 );
end;
endTicks := getticks;
WriteLn( 'end ticks: ', endTicks );
WriteLn( 'start ticks: ', startTicks );
WriteLn( 'difference in hs: ', endTicks - startTicks );
if startTicks > endTicks then begin { passed a 10 minute mark }
endTicks := endTicks + 60000;
WriteLn( 'corrected in hs: ', endTicks - startTicks );
end;
WriteLn( 'moves evaluated: ', evaluated );
WriteLn( 'iterations: ', loops );
end.

View File

@ -0,0 +1,54 @@
{* DEMOEXEC.PAS - demonstration progam for calling C library functions
*
* Microsoft Pascal release 3.32 can call large model C functions.
* Please read PASEXEC.INC for more details on interlanguage calling.
*
* To compile and link DEMOEXEC.PAS
*
* pas1 demoexec;
* pas2
* link demoexec,,,cexec; (must search CEXEC.LIB)
*}
program demoexec(input,output);
{$include : 'pasexec.inc'}
var
i : integer;
NULL : integer4;
value
NULL := 0;
begin
{* invoke command.com with a command line
*
* dir *.for
*}
i := system(ads('dir *.pas'*chr(0)));
writeln (output,'system return code = ',i);
writeln (output,' ');
{* invoke a child process
*
* exemod (display usage line only)
*}
i := spawnlp(0,ads('exemod'*chr(0)),ads('exemod'*chr(0)),NULL);
writeln (output,'spawnlp return code =',i);
writeln (output,' ');
{* invoke an overlay process (chaining)
*
* exemod demoexec.exe
*}
i := spawnlp(_p_overlay,ads('exemod'*chr(0)),ads('exemod'*chr(0)),
ads('demoexec.exe'*chr(0)),NULL);
{* we should never see this if spawnlp (overlay) is successful
*}
writeln (output,'spawnlp return code =',i);
writeln (output,' ');
end.

View File

@ -0,0 +1,438 @@
;
;
; Copyright (C) Microsoft Corporation, 1987
;
; This Module contains Proprietary Information of Microsoft
; Corporation and should be treated as Confidential.
;
title emoem.asm - OEM dependent code for 8087
;--------------------------------------------------------------------
;
; OEM customization routines for 8087/80287 coprocessor
;
; This module is designed to work with the following
; Microsoft language releases:
;
; Microsoft C 3.00 and later
; Microsoft FORTRAN 77 3.30 and later
; Microsoft Pascal 3.30 and later
;
; This module supersedes the OEMR7.ASM module used in earlier
; versions of Microsoft FORTRAN 77 and Pascal. The documentation
; provided with the FORTRAN and Pascal releases refers to the old
; OEMR7.ASM module and is only slightly relevant to this module.
;
; The following routines need to be written to properly handle the
; 8087/808287 installation, termination, and interrupt handler
;
; __FPINSTALL87 install 8087 interrupt handler
; __FPTERMINATE87 deinstall 8087 interrupt handler
; __fpintreset reset OEM hardware if an 8087 interrupt
;
; ***** NEW INSTRUCTIONS *****
;
; If you want a PC clone version, do nothing. The libraries are
; setup for working on IBM PC's and clones.
;
; These instructions only need to be followed if a non-IBM PC
; clone version is desired.
;
; This module should be assembled with the
; Microsoft Macro Assembler Version 4.00 or later as follows:
;
; masm -DOEM -r emoem.asm;
;
; Most hardware handles the 8087/80287 in one of the following
; three ways -
;
; 1. NMI - IBM PC and clones all handle the interrupt this way
; 2. single 8259
; 3. master/slave 8259
;
; Manufacturer specific initialization is supported for these 3
; machine configurations either by modifying this file and replacing
; the existing EMOEM module in the math libraries or by patching
; the .LIB and .EXE files directly.
;
; LIB 87-+EMOEM;
; LIB EM-+EMOEM;
;
;--------------------------------------------------------------------
ifdef OEM
if1
%out OEM version for non-clone support
endif
endif
;---------------------------------------------------------------------
; Assembly constants.
;---------------------------------------------------------------------
; MS-DOS OS calls
OPSYS EQU 21H
SETVECOP EQU 25H
GETVECOP EQU 35H
DOSVERSION EQU 30h
CTLCVEC EQU 23h
EMULATOR_DATA segment public 'FAR_DATA'
assume ds:EMULATOR_DATA
; User may place data here if DS is setup properly.
; Recommend keeping the data items in the code segment.
EMULATOR_DATA ends
EMULATOR_TEXT segment public 'CODE'
assume cs:EMULATOR_TEXT
public __FPINSTALL87 ; DO NOT CHANGE THE CASE ON
public __FPTERMINATE87 ; THESE PUBLIC DEFINITIONS
extrn __FPEXCEPTION87:near ; DO NOT CHANGE CASE
ifdef OEM
;***********************************************************************
;
; Hardware dependent parameters in the 8087 exception handler.
;
; For machines using 2 8259's to handle the 8087 exception, be sure that
; the slave 8259 is the 1st below and the master is the 2nd.
;
; The last 4 fields allow you to enable extra interrupt lines into the
; 8259s. It should only be necessary to use these fields if the 8087
; interrupt is being masked out by the 8259 PIC.
;
; The ocw2's (EOI commands) can be either non-specific (20H) or
; specific (6xH where x=0 to 7). If you do not know which interrupt
; request line on the 8259 the 8087 exception uses, then you should issue
; the non-specific EOI (20H). Interrupts are off at this point in the
; interrupt handler so a higher priority interrupt will not be seen.
oeminfo struc
oemnum db 0 ; MS-DOS OEM number (IBM is 00h)
intnum db 2 ; IBM PC clone interrupt number
share db 0 ; nonzero if original vector should be taken
a8259 dw 0 ; 1st 8259 (A0=0) port #
aocw2 db 0 ; 1st 8259 (A0=0) EOI command
b8259 dw 0 ; 2nd 8259 (A0=0) port #
bocw2 db 0 ; 2nd 8259 (A0=0) EOI command
a8259m dw 0 ; 1st 8259 (A0=1) port #
aocw1m db 0 ; 1st 8259 (A0=1) value to mask against IMR
b8259m dw 0 ; 2nd 8259 (A0=1) port #
bocw1m db 0 ; 2nd 8259 (A0=1) value to mask against IMR
oeminfo ends
;-----------------------------------------------------------------------
; OEM specific 8087 information
;
; If the OEM number returned from the DOS version call matches,
; this information is automatically moved into the oem struc below.
oemtab label byte ; Table of OEM specific values for 8087
; OEM#, int, shr, a59, acw2,b59, bcw2,a59m,acw1,b59m,bcw1
;TI Professional Computer
TI_prof oeminfo <028h,047h,000h,018h,020h,0000,0000,0000,0000,0000,0000>
db 0 ; end of table
; Unique pattern that can be searched for with the debugger so that
; .LIB or .EXE files can be patched with the correct values.
; If new values are patched into .LIB or .EXE files, care must be
; taken in insure the values are correct. In particular, words and
; bytes are intermixed in oeminfo structure. Remember words are
; stored low byte - high byte in memory on the 8086 family.
db '<<8087>>' ; older versions used '<8087>'
; Some manufacturer's machines can not be differentiated by the
; OEM number returned by the MS-DOS version check system call.
; For these machines it is necessary to replace the line below
oem1 oeminfo <> ; default values for IBM PC & clones
; with one of the following. If your machine has an 8087 capability
; and it is not in the list below, you should contact your hardware
; manufacturer for the necessary information.
;ACT Apricot
;oem1 oeminfo <000h,055h,000h,000h,020h,000h,000h,000h,000h,000h,000h>
;NEC APC3 and PC-9801 (OEM number returned by NEC MS-DOS's is different)
;oem1 oeminfo <000h,016h,000h,008h,066h,000h,067h,00Ah,0BFh,002h,07Fh>
;---------------------------------------------------------------------
aoldIMR db 0 ; 1st 8259 original IMR value
boldIMR db 0 ; 2nd 8259 original IMR value
endif ;OEM
statwd dw 0 ; Temporary for status word
oldvec dd 0 ; Old value in 8087 exception interrupt vector
ctlc dd 0 ; Old value of Control-C vector (INT 23h)
page
;---------------------------------------------------------------------
;
; Perform OEM specific initialization of the 8087.
;
__FPINSTALL87:
push ds ; DS = EMULATOR_DATA
push cs ; Move current CS to DS for opsys calls.
pop ds
assume ds:EMULATOR_TEXT
ifdef OEM
push ds
pop es ; CS = DS = ES
mov ah,DOSVERSION
int OPSYS ; bh = OEM#
cld
mov si,offset oemtab ; start of OEM 8087 info table
mov di,offset oem1+1
mov cx,(size oem1)-1
OEMloop:
lodsb ; get OEM#
or al,al
jz OEMdone ; OEM# = 0 - did not find OEM
cmp al,bh ; correct OEM#
je OEMfound
add si,cx ; skip over OEM information
jmp OEMloop
OEMfound:
rep movsb ; move the information
OEMdone: ; done with automatic customization
endif ;OEM
; Save old interrupt vector.
; Ask operating system for vector.
ifdef OEM
mov al,[oem1].intnum ; Interrupt vector number.
mov ah,GETVECOP ; Operating system call interrupt.
else
mov ax,GETVECOP shl 8 + 2 ; get interrupt vector 2
endif ;OEM
int OPSYS ; Call operating system.
mov word ptr [oldvec],bx ; Squirrel away old vector.
mov word ptr [oldvec+2],es
; Have operating system install interrupt vectors.
mov dx,offset __fpinterrupt87 ; Load DX with 8087 interrupt handler.
ifdef OEM
mov ah,SETVECOP ; Set interrupt vector code in AH.
mov al,[oem1].intnum ; Set vector number.
else
mov ax,SETVECOP shl 8 + 2 ; set interrupt vector 2
endif ;OEM
int OPSYS ; Install vector.
; Intercept Control-C vector to guarentee cleanup
mov ax,GETVECOP shl 8 + CTLCVEC
int OPSYS
mov word ptr [ctlc],bx
mov word ptr [ctlc+2],es
mov dx,offset ctlcexit
mov ax,SETVECOP shl 8 + CTLCVEC
int OPSYS
ifdef OEM
; set up 8259's so that 8087 interrupts are enabled
mov ah,[oem1].aocw1m ; get mask for 1st 8259 IMR
or ah,ah ; if 0, don't need to do this
jz installdone ; and only 1 8259
mov dx,[oem1].a8259m ; get port number for 1st 8259 (A0=1)
in al,dx ; read old IMR value
mov [aoldIMR],al ; save it to restore at termination
and al,ah ; mask to enable interrupt
jmp short $+2 ; for 286's
out dx,al ; write out new mask value
mov ah,[oem1].bocw1m ; get mask for 2nd 8259 IMR
or ah,ah ; if 0, don't need to do this
jz installdone ;
mov dx,[oem1].b8259m ; get port number for 2nd 8259 (A0=1)
in al,dx ; read old IMR value
mov [boldIMR],al ; save it to restore at termination
and al,ah ; mask to enable interrupt
jmp short $+2 ; for 286's
out dx,al ; write out new mask value
installdone:
endif ;OEM
assume ds:EMULATOR_DATA
pop ds
ret
page
; __FPTERMINATE87
;
; This routine should do the OEM 8087 cleanup. This routine is called
; before the program exits.
;
; DS = EMULATOR_DATA
__FPTERMINATE87:
push ds
push ax
push dx
ifdef OEM
mov ah,SETVECOP
mov al,[oem1].intnum
else
mov ax,SETVECOP shl 8 + 2
endif ;OEM
lds dx,[oldvec]
int OPSYS
ifdef OEM
; reset 8259 IMR's to original state
push cs
pop ds ; DS = CS
assume ds:EMULATOR_TEXT
cmp [oem1].aocw1m,0 ; did we have to change 1st 8259 IMR
je term2nd8259 ; no - check 2nd 8259
mov al,[aoldIMR] ; get old IMR
mov dx,[oem1].a8259m ; get 1st 8259 (A0=1) port #
out dx,al ; restore IMR
term2nd8259:
cmp [oem1].bocw1m,0 ; did we have to change 2nd 8259 IMR
je terminatedone ; no
mov al,[boldIMR] ; get old IMR
mov dx,[oem1].b8259m ; get 2nd 8259 (A0=1) port #
out dx,al ; restore IMR
terminatedone:
endif ;OEM
pop dx
pop ax
pop ds
assume ds:EMULATOR_DATA
ret
; Forced cleanup of 8087 exception handling on Control-C
ctlcexit:
push ax
push dx
push ds
call __FPTERMINATE87 ; forced cleanup of exception handler
lds dx,[ctlc] ; load old control C vector
mov ax,SETVECOP shl 8 + CTLCVEC
int OPSYS
pop ds
pop dx
pop ax
jmp [ctlc] ; go through old vector
page
; __fpinterrupt87
;
; This is the 8087 exception interrupt routine.
;
; All OEM specific interrupt and harware handling should be done in
; __fpintreset because __FPEXCEPTION87 (the OEM independent 8087
; exception handler) may not return. __FPEXCEPTION87 also turns
; interrupts back on.
;
PENDINGBIT= 80h ; Bit in status word for interrupt pending
__fpinterrupt87:
assume ds:nothing
nop
fnstsw [statwd] ; Store out exceptions
push cx ; waste time
mov cx,3
self:
loop self
pop cx
test byte ptr [statwd],PENDINGBIT ; Test for 8087 interrupt
jz not87int ; Not an 8087 interrupt.
ifdef OEM
call __fpintreset ; OEM interrupt reset routine
endif ;OEM
call __FPEXCEPTION87 ; 8087 error handling - may not return
; this routine turns interrupts back on
ifdef OEM
cmp [oem1].share,0 ; Should we execute the old interrupt routine?
jnz not87int ; if so then do it
; else return from interrupt
; If you fall through here to do further hardware resetting, things
; may not always work because __FPEXCEPTION87 does not always return
; This only happens when the 8087 handler gets an exception that is
; a fatal error in the language runtimes. I.e., divide by zero
; is a fatal error in all the languages, unless the control word has
; set to mask out divide by zero errors.
endif ;OEM
done8087:
iret
not87int:
jmp [oldvec] ; We should never return from here.
ifdef OEM
__fpintreset:
push ax
push dx
mov al,[oem1].aocw2 ; Load up EOI instruction.
or al,al ; Is there at least one 8259 to be reset?
jz Reset8259ret ; no
mov dx,[oem1].a8259
out dx,al ; Reset (master) 8259 interrupt controller.
mov al,[oem1].bocw2 ; Load up EOI instruction.
or al,al ; Is there a slave 8259 to be reset?
jz Reset8259ret
mov dx,[oem1].b8259
out dx,al ; Reset slave 8259 interrupt controller.
Reset8259ret:
pop dx
pop ax
ret
endif ;OEM
EMULATOR_TEXT ends
end

View File

@ -0,0 +1,514 @@
PAGE 56,132
title entx - Common Pascal/FORTRAN Initialization module
;---------------------------------------------------------------------------
;
; Microsoft MS-DOS/Windows/XENIX Pascal/FORTRAN Initialization
; Version 3.30 (C) Copyright 1984 Microsoft Corporation
;
; BEGXQQ is called (indirectly) from the C runtime startup routine.
; It performs initialization of the Pascal and FORTRAN runtime
; systems. Note that if it is called again, BEGXQQ simply returns.
;
; ENDXQQ is called (again, indirectly) from the C startup routine,
; just before it terminates the user's program. ENDXQQ also ignores
; all but its first invocation.
;
; Revision History
;
; 06/14/84 Allen Akin
; First version, cribbed from previous
; versions of ENTX and MS-C startup routines
; 07/12/84 Allen Akin
; Modified initializer scheme to allow
; arbitrary numbers of initializers
; 11/07/84 Gordon Whitten
; Moved DOSXQQ to RTIM6.ASM
; 11/21/84 Greg Whitten
; 11/28/84 set up new stack checking
; 11/29/84 set up newer stack checking
; 12/04/84 Allen Akin
; Added calls to old-style escape
; initializers (BEGOQQ and ENDOQQ)
; for compatibility with earlier
; releases.
; 12/04/84 Added floating-point exception handler
; for XENIX.
;---------------------------------------------------------------------------
?DF = 1
include pasrun.inc
page
include sysi.inc
page
; Special segments used in this module
; CreateSeg name, logname,align, combine,class, group
CreateSeg _TEXT, code, byte, public, CODE
CreateSeg _DATA, data, word, public, DATA, DGROUP
ifndef WINDOWS
CreateSeg STACK, STACK, word, stack, STACK, DGROUP
endif
CreateSeg XIB, xibeg, word, public, DATA, DGROUP
CreateSeg XI, xiseg, word, public, DATA, DGROUP
CreateSeg XIE, xiend, word, public, DATA, DGROUP
CreateSeg XCB, xcbeg, word, public, DATA, DGROUP
CreateSeg XC, xcseg, word, public, DATA, DGROUP
CreateSeg XCE, xcend, word, public, DATA, DGROUP
CreateSeg P1IB, pf1ibeg,word, public, DATA, DGROUP
CreateSeg P1I, pf1iseg,word, public, DATA, DGROUP
CreateSeg P1IE, pf1iend,word, public, DATA, DGROUP
CreateSeg P2IB, pf2ibeg,word, public, DATA, DGROUP
CreateSeg P2I, pf2iseg,word, public, DATA, DGROUP
CreateSeg P2IE, pf2iend,word, public, DATA, DGROUP
CreateSeg P3IB, pf3ibeg,word, public, DATA, DGROUP
CreateSeg P3I, pf3iseg,word, public, DATA, DGROUP
CreateSeg P3IE, pf3iend,word, public, DATA, DGROUP
CreateSeg P1CB, pf1cbeg,word, public, DATA, DGROUP
CreateSeg P1C, pf1cseg,word, public, DATA, DGROUP
CreateSeg P1CE, pf1cend,word, public, DATA, DGROUP
CreateSeg P2CB, pf2cbeg,word, public, DATA, DGROUP
CreateSeg P2C, pf2cseg,word, public, DATA, DGROUP
CreateSeg P2CE, pf2cend,word, public, DATA, DGROUP
CreateSeg P3CB, pf3cbeg,word, public, DATA, DGROUP
CreateSeg P3C, pf3cseg,word, public, DATA, DGROUP
CreateSeg P3CE, pf3cend,word, public, DATA, DGROUP
DefGrp DGROUP
page
; System resident public data
; these could be communal variables and off in some other segment
externDP ___argv ; arg pointer set by C startup
externW ___argc ; arg count set by C startup
sBegin data
assumes ds,data
ifdef MSD
externW __psp ; program segment prefix paragraph #
endif
externCP __aaltstkovr ; alternate stack overflow handler
globalW STKBQQ,0 ; stack top - set by main program
globalW CSXEQQ,0 ; pointer to source context list
globalW CLNEQQ,0 ; last line number encountered
globalW PNUXQQ,0 ; pointer to unit initialization list
globalW HDRFQQ,0 ; Unit F open file list header
globalW HDRVQQ,0 ; Unit V open file list header
globalW RESEQQ,0 ; machine error context, stack pointer
globalW REFEQQ,0 ; machine error context, frame pointer
globalW REPEQQ,0 ; machine error context, program offset
globalW RECEQQ,0 ; machine error context, program segment
globalW UPCX87,0 ; offset address of 8087 error context
globalW DGRMQQ,0 ; segment of DGROUP
globalW DOSEQQ,0 ; DOS return code
globalDP AGVXQQ,0 ; pointer to argument vector
globalW AGCXQQ,0 ; count of argument
globalW CURXQQ,1 ; index of argument currently in use
globalW RETLQQ,0 ; return address storage, used by pocket code
ifdef MSD
globalW CESXQQ,0 ; segment for arg string under DOS
endif
sEnd
page
; Local data:
sBegin data
staticW BEGX_CALLED,0 ; non-zero iff BEGXQQ has been called
staticW ENDX_CALLED,0 ; non-zero iff ENDXQQ has been called
sEnd
page
; C Runtime initialization segment:
sBegin xiseg
StaticCP begx,BEGXQQ ; General Pascal/FORTRAN initialization
sEnd
; C Runtime termination segment:
sBegin xcseg
StaticCP endx,PFTERM ; General Pascal/FORTRAN termination
sEnd
page
; Pascal/Fortran initialization segments:
sBegin pf1ibeg ; Unit U initialization level
uuibeg label dword
sEnd
; initializer addresses appear in pf1iseg, here in the middle...
sBegin pf1iend
uuiend label dword
sEnd
sBegin pf2ibeg ; User initialization level
uoibeg label dword
sEnd
; user initializer addresses appear in pf2iseg, here in the middle...
sBegin pf2iend
uoiend label dword
sEnd
sBegin pf3ibeg ; Unit F/V initialization level
ufibeg label dword
sEnd
; unit F/V initializer addresses appear in pf3iseg, here in the middle...
sBegin pf3iend
ufiend label dword
sEnd
page
; Pascal/FORTRAN termination segments:
sBegin pf1cbeg ; Unit U termination level
uucbeg label dword
sEnd
; unit U cleanup addresses appear in pf1cseg, here in the middle...
sBegin pf1cend
uucend label dword
sEnd
sBegin pf2cbeg ; User termination level
uocbeg label dword
sEnd
; user cleanup addresses appear in pf2cseg, here in the middle...
sBegin pf2cend
uocend label dword
sEnd
sBegin pf3cbeg ; Unit F/V termination level
ufcbeg label dword
sEnd
; unit F/V cleanup addresses appear in pf3cseg, here in the middle...
sBegin pf3cend
ufcend label dword
sEnd
page
; BEGXQQ - Common FORTRAN/Pascal Initialization Code
externP SOWGQQ
externP BEGOQQ ; escape initializer, old-style
externP ENDOQQ ; escape terminator, old-style
if XENIXRUNTIME
externP _signal ; XENIX exception-handling routine
externP XFPEQQ ; Pascal/FORTRAN exception vectoring routine
endif
sBegin code
assumes cs,code
assumes ds,dgroup
cProc BEGXQQ,<PUBLIC,FAR>
cBegin
cmp BEGX_CALLED,0 ; have we been called before?
jne breturn ; if so, just return
inc BEGX_CALLED ; prevent further calls
mov ax,seg SOWGQQ ; __chkstk escape for
mov word ptr [__aaltstkovr+2],ax ; P/F stack overflow
mov ax,offset SOWGQQ
mov word ptr [__aaltstkovr],ax
mov ax,seg ___argv ; prepare to address ___argv, which may be far
mov es,ax
mov ax,word ptr es:___argv ; copy C's argv pointer into Pascal's
mov word ptr AGVXQQ,ax
if SizeD
mov ax,word ptr es:___argv+2
mov word ptr AGVXQQ+2,ax
endif
mov ax,seg ___argc
mov es,ax
mov ax,es:___argc ; copy C's arg count into Pascal's
mov AGCXQQ,ax
ifdef MSD
mov ax,__psp ; get program segment prefix pp. address
mov CESXQQ,ax ; save it away for use by Pascal
endif
init1: ; perform first-level initializations,
; including unit U
mov bx,offset DGROUP:uuibeg
init1_1:
cmp bx,offset DGROUP:uuiend
jae init2
push bx
push si
push di
if SizeC
call dword ptr [bx]
else
call word ptr [bx]
endif
pop di
pop si
pop bx
if SizeC
add bx,4
else
add bx,2
endif
jmp init1_1
init2: ; perform second-level initializations
; including unit O and old-style escape
; initializers
if XENIXRUNTIME
mov ax,SEG fpe_handler
push ax
mov ax,OFFSET fpe_handler
push ax
mov ax,08H ; SIGFPE
push ax
call _signal ; set up to catch floating-point exceptions
add sp,6
endif
call BEGOQQ
mov bx,offset DGROUP:uoibeg
init2_1:
cmp bx,offset DGROUP:uoiend
jae init3
push bx
push si
push di
if SizeC
call dword ptr [bx]
else
call word ptr [bx]
endif
pop di
pop si
pop bx
if SizeC
add bx,4
else
add bx,2
endif
jmp init2_1
init3: ; perform third-level initializations
; including units F and V
mov bx,offset DGROUP:ufibeg
init3_1:
cmp bx,offset DGROUP:ufiend
jae initlast
push bx
push si
push di
if SizeC
call dword ptr [bx]
else
call word ptr [bx]
endif
pop di
pop si
pop bx
if SizeC
add bx,4
else
add bx,2
endif
jmp init3_1
initlast:
breturn: ; return -- all done.
cEnd
if XENIXRUNTIME
page
; fpe_handler - Floating-point exception handler for XENIX
; For the present, this routine just calls XFPEQQ (the FORTRAN/Pascal
; floating-point exception handler for XENIX). We go through this
; intermediate routine to keep the stack consistent; if we were to vector
; directly to XFPEQQ, this would not necessarily be done for us.
;
; In the future, this routine may disappear or at least fudge the stack
; to provide a little better context information for debugging.
cProc fpe_handler,<FAR>
cBegin
call XFPEQQ
cEnd
endif
sEnd
page
; ENDXQQ - Explicitly terminate Pascal or FORTRAN program
ExternP _exit ; C exit
sBegin code
assumes cs,code
assumes ds,dgroup
cProc ENDXQQ,<PUBLIC,FAR>
cBegin
ccall _exit,DOSEQQ ; exit, returning code in DOSEQQ
cEnd
sEnd
page
; PFTERM - common Pascal/FORTRAN termination
sBegin code
assumes cs,code
assumes ds,dgroup
cProc PFTERM,<FAR>
cBegin
cmp ENDX_CALLED,0 ; have we been called before?
jne ereturn ; if so, just return
inc ENDX_CALLED ; prevent further calls
term3: ; perform third-level terminations,
; including units F and V
mov bx,offset DGROUP:ufcbeg
term3_1:
cmp bx,offset DGROUP:ufcend
jae term2
push bx
push si
push di
if SizeC
call dword ptr [bx]
else
call word ptr [bx]
endif
pop di
pop si
pop bx
if SizeC
add bx,4
else
add bx,2
endif
jmp term3_1
term2: ; perform second-level terminations,
; including unit O and old-style
; escape terminator
mov bx,offset DGROUP:uocbeg
term2_1:
cmp bx,offset DGROUP:uocend
jae term1
push bx
push si
push di
if SizeC
call dword ptr [bx]
else
call word ptr [bx]
endif
pop di
pop si
pop bx
if SizeC
add bx,4
else
add bx,2
endif
jmp term2_1
term1:
call ENDOQQ
; perform first-level terminations,
; including unit U
mov bx,offset DGROUP:uucbeg
term1_1:
cmp bx,offset DGROUP:uucend
jae termlast
push bx
push si
push di
if SizeC
call dword ptr [bx]
else
call word ptr [bx]
endif
pop di
pop si
pop bx
if SizeC
add bx,4
else
add bx,2
endif
jmp term1_1
termlast:
ereturn: ; return -- all done.
cEnd
sEnd
end

View File

@ -0,0 +1,21 @@
PAGE 56,132
title entxstub - Pascal OS/2 Initialization stub for psp
?DF = 1
include pasrun.inc
include sysi.inc
CreateSeg _DATA, data, word, public, DATA, DGROUP
DefGrp DGROUP
; System resident public data
; these could be communal variables and off in some other segment
sBegin data
assumes ds,data
globalW __psp,0 ; program segment prefix paragraph #
sEnd
end

View File

@ -0,0 +1,2 @@
files=20
buffers=10

View File

@ -0,0 +1,3 @@
PATH=C:\PASCAL4\PASCAL4\BIN;C:\PASCAL4\PASCAL4\BINB
set LIB=C:\PASCAL4\PASCAL4\LIB
set TMP=C:\PASCAL4\PASCAL4\TMP

View File

@ -0,0 +1,103 @@
{ PASEXEC.INC - interface file for C library routines
This include file along with the CEXEC.LIB library has been included
with your Pascal 3.32 to show you how easy it is to call routines
written in our new C 4.00 release. The CEXEC.LIB contains several
routines from the C library which we think you will find useful in
extending the power of your Pascal programs.
The memory model that Pascal uses is basically medium model (16-bit
data pointers) with some extensions for large model addressing
(32-bit data pointers). The CEXEC.LIB routines are from the large
model C library. This means that you should be careful interfacing
to these routines. You should use ADS or VARS instead of ADR or VAR
so that 32-bit addressed get constructed.
The new Microsoft FORTRAN 4.00, PASCAL 3.32, and C 4.00 releases
have been designed so that libraries or subprograms can be written
in any one of these languages and used in any other.
Try compiling and running the demonstration program DEMOEXEC.PAS
to see some actual examples.
}
{ C function
int system(string)
char *string;
The system() function passes the given C string (00hex terminated)
to the DOS command interpreter (COMMAND.COM), which interprets and
executes the string as an MS-DOS command. This allows MS-DOS commands
(i.e., DIR or DEL), batch files, and programs to be executed.
Example usage in Pascal
i := system(ads('dir *.pas'*chr(0)));
The interface to system is given below. The [c] attribute is given
after the function return type. The [varying] attribute says the
function has an undetermined number of parameters; in this case, 1.
}
function system : integer [c,varying]; extern;
{ C function
int spawnlp(mode,path,arg0,arg1,...,argn)
int mode; /* spawn mode */
char *path; /* pathname of program to execute */
char *arg0; /* should be the same as path */
char *arg1,...,*argn; /* command line arguments */
/* argn must be NULL */
The spawnlp creates and executes a new child process. There must be
enough memory to load and execute the child process. The mode
argument determines which form of spawnlp is executed as follows:
Value Action
0 Suspend parent program and execute the child program.
When the child program terminates, the parent program
resumes execution. The return value from spawnlp is -1
if an error has occured or if the child process has
run, the return value is the child processes return
code.
_p_overlay Overlay parent program with the child program. The
child program is now the running process and the
parent process is terminated. spawnlp only returns
a value if there has been a recoverable error. Some
errors can not be recovered from and execution will
terminate by safely returning to DOS. This might
happen if there is not enough memory to run the new
process.
The path argument specifies the file to be executed as the child
process. The path can specify a full path name (from the root
directory \), a partial path name (from the current working directory),
or just a file name. If the path argument does not have a filename
extension or end with a period (.), the spawnlp call first appends
the extension ".COM" and searches for the file; if unsuccessful, the
extension ".EXE" is tried. The spawnlp routine will also search for
the file in any of the directories specified in the PATH environment
variable (using the same procedure as above).
Example usage in Pascal
var NULL : integer4;
value NULL := 0;
...
i := spawnlp(0, ads('exemod'*chr(0)), ads('exemod'*chr(0)),
ads('demoexec.exe'*chr(0)), NULL);
The C spawnlp function is expecting the addresses of the strings
(not the actual characters), so we use the ADS() function to pass
the address of the strings. The last parameter to the spawnlp
routine must be a C NULL pointer which is a 32-bit integer 0, so
we use an INTEGER4 variable NULL set to 0 as the last parameter.
}
var _p_overlay [c,extern] :integer;
var _errno [c,extern] :integer;
function spawnlp : integer [c,varying]; extern;

View File

@ -0,0 +1,29 @@
{ Prime number generator }
{ Generates all the primes between 0 and 10000 }
program primes(output);
var [Public]
prime: integer;
rprime: real4;
i: integer;
sqrtp: integer;
notprime: boolean;
begin
writeln(' 2');
writeln(' 3');
prime := 5;
repeat
rprime := prime;
sqrtp := trunc(sqrt(rprime) + 1.0);
i := 1;
notprime := false;
while (i < sqrtp) and (not notprime) do
begin
i := i + 2;
notprime := (prime mod i = 0);
end;
if (not notprime) then writeln(prime:6);
prime := prime + 2;
until (prime > 10000);
end.

View File

@ -0,0 +1,88 @@
C Runtime Library Startup Sources
---------------------------------
The directory \startup and its subdirectories contain the files
necessary for building the startup portion of the C runtime library.
The \startup directory contains the startup source files, the include
include files, the batch file and the make file used to build the startup
object files. The subdirectories of \startup contain OS specific sources.
The startup object files can be built by invoking startup.bat from within
the \startup directory. This batch file assumes the following:
(1) make.exe, link.exec, the C compiler, and the assembler must be
in the execution path. MASM 5.0 and C 5.0 or later are required to
build the startup sources.
(2) doscalls.lib must be in the directory specified by the LIB
environment variable.
Startup will create four memory model specific subdirectories (i.e., S, M, C,
and L) and place the appropriate object files there. Under each memory model
subdirectory, startup creates two addition subdirectories OS2 and DOS where
OS specific objects reside.
The include files stdio.h and ctype.h are required for building the
startup source file wild.c but are not included on the \startup directory
because they exist on the directory containing the standard include files.
A make variable called CINC controls where the makefile looks for these
include files. STARTUP.BAT sets CINC to the current value of the INCLUDE
environment variable. This variable should be set to the location of
the C include files. CINC can also be set in the makefile if you wish
to run the makefile separately.
The message "<cEnd - nogen>" is generated when some of the assembly language
source files are assembled. This message is expected and is totally benign.
The startup batch file requires as arguments a list of capital letters
describing the memory models you wish to build. For example,
"startup S L" will build the small and large model startup objects.
Startup will then link the objects with a sample C program called nulbody.c
(consisting of a null main functions) to produce nulbody.exe.
[Invoking startup.bat with no arguments will give usage information.]
Note: startup sources written in assembly language have been edited with
tabstops set to 8. Startup sources written in C have been edited with
tabstops set to 4.
The following files are contained in the \startup directory:
Startup source files (OS independent):
chkstk.asm
chksum.asm
crt0fp.asm
setargv.asm
wild.c
Startup source files (OS specific):
crt0.asm
crt0dat.asm
crt0msg.asm
execmsg.asm
nmsghdr.asm
stdalloc.asm
stdenvp.asm
stdargv.asm
Startup include files:
brkctl.inc
cmacros.inc
msdos.inc
register.h
msdos.h
version.inc
File count files:
_file.c
file2.h
Make and batch files:
startup.bat: invokes make file to build objs and link to null program
makefile: contains rules for building startup sources
nulbody.c: null c program
nulbody.lnk: link script for linking null program
Documentation:
readme.doc: information about \startup directory structure
and contents
--- End ---

Binary file not shown.

View File

@ -0,0 +1,121 @@
; utility functions for calling into DOS from Microsoft Pascal v1 through v4
;
; function dostime : word; External;
; var startTicks: word;
; startTicks := dostime;
;
; function getpsp : word; External;
; var psp : word;
; psp := getpsp;
;
; function pspbyte( offset : word ) : integer; External;
; var result : integer;
; result := pspbyte( 80 ); { get command tail length }
;
.model large
code segment
assume cs:code
; returns a count of hundredths of a second in ax
; only uses hs, seconds, and the low digit of minutes since that's all that fits in two bytes
; 54000 = 9 * 60 * 100
; + 5900 = 59 * 100
; + 99
; --------
; 59999
public getticks
getticks PROC FAR
push bx
push cx
push dx
push di
push si
mov ah, 2ch
int 21h
push dx
mov ah, 0
mov al, dh
mov bx, 100
mul bx
pop dx
mov dh, 0
add ax, dx
push ax
mov ax, cx
and ax, 0ffh
mov cx, 10
mov dx, 0
div cx
mov ax, dx
mov cx, 6000
mul cx
pop bx
add ax, bx
pop si
pop di
pop dx
pop cx
pop bx
ret
getticks ENDP
public getpsp
getpsp PROC FAR
push bx
push cx
push dx
push di
push si
mov ah, 062h
int 21h
mov ax, bx
pop si
pop di
pop dx
pop cx
pop bx
ret
getpsp ENDP
public pspbyte
pspbyte PROC FAR
push bx
push cx
push dx
push di
push si
push es
push bp
mov bp, sp
mov ah, 062h
int 21h
mov es, bx
; the argument is here. 7 pushes above + 2 for the return address = 9 * 2 = 18.
mov bx, word ptr[ bp + 18 ]
xor ah, ah
mov al, byte ptr es: [ bx ]
pop bp
pop es
pop si
pop di
pop dx
pop cx
pop bx
ret
pspbyte ENDP
code ends
end

View File

@ -0,0 +1,7 @@
ntvdm /r:. -c binb\pas1 %1,%1,%1,%1
ntvdm /r:. -c binb\pas2
ntvdm /r:. -c binb\pas3
ntvdm /r:. -e:lib=lib -c binb\link %1 djldos,%1,%1,,nul.def
ntvdm %1