1277 lines
29 KiB
NASM
1277 lines
29 KiB
NASM
|
TITLE CXINIT - Initiate execution of a Lattice C program
|
|||
|
SUBTTL Copyright 1982 by Lattice, Inc.
|
|||
|
NAME CXINIT
|
|||
|
INCLUDE DOS.MAC
|
|||
|
.8087
|
|||
|
|
|||
|
;**** modified to add EGA support 10-20-86 dbs
|
|||
|
|
|||
|
;**** modified for PROTECTED MODE 7-29-87 tc
|
|||
|
|
|||
|
; ***** Lattice C v3.0 C.asm file modified for PCS *****
|
|||
|
; (None of the original file is altered. Mods done thru conditional assembly.)
|
|||
|
|
|||
|
scheme equ 1
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; name CXINIT -- initiate execution of C program
|
|||
|
;
|
|||
|
; description This is the main module for a C program on the
|
|||
|
; MS-DOS implementation. It performs various low-level
|
|||
|
; initializations and then calls _main.
|
|||
|
;
|
|||
|
; This routine is stored as C.OBJ and is included as
|
|||
|
; the first object module when linking. It is important
|
|||
|
; to include it first so that the segment structure will
|
|||
|
; be defined properly.
|
|||
|
;
|
|||
|
; NOTE: In order for the segment structure to work correctly,
|
|||
|
; this module must be assembled with Version 3 or later of the
|
|||
|
; Microsoft assembler. Specifically, older assemblers emit
|
|||
|
; segments in alphabetical order, while Version 3 and later
|
|||
|
; emit them in the order that they appear. The latter is
|
|||
|
; required for this module.
|
|||
|
;
|
|||
|
;**
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; Assembly parameters
|
|||
|
;
|
|||
|
TAB EQU 09H ; tab character
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; External program references (P and L models)
|
|||
|
;
|
|||
|
IF LPROG
|
|||
|
EXTRN _MAIN:FAR
|
|||
|
EXTRN RBRK:FAR
|
|||
|
ENDIF
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; Define data group
|
|||
|
;
|
|||
|
DGROUP GROUP DATA,UDATA,XSTACK
|
|||
|
ASSUME DS:DGROUP
|
|||
|
;**
|
|||
|
;
|
|||
|
; Define program segment
|
|||
|
;
|
|||
|
if scheme ;extra segment for Scheme
|
|||
|
XGROUP GROUP PROGX
|
|||
|
PROGX SEGMENT BYTE PUBLIC 'PROGX'
|
|||
|
PROGX ENDS
|
|||
|
endif
|
|||
|
|
|||
|
IF S8086
|
|||
|
IF COM
|
|||
|
PGROUP GROUP PROG,TAIL
|
|||
|
ENDIF
|
|||
|
IFDEF PROMEM ;;; Protected Mode
|
|||
|
PROG SEGMENT PARA PUBLIC 'PROG'
|
|||
|
ELSE
|
|||
|
PROG SEGMENT BYTE PUBLIC 'PROG'
|
|||
|
ENDIF
|
|||
|
ASSUME CS:PROG
|
|||
|
IF COM
|
|||
|
ORG 100H
|
|||
|
ENDIF
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF D8086
|
|||
|
CODE SEGMENT BYTE PUBLIC 'CODE'
|
|||
|
ASSUME CS:CODE
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF P8086
|
|||
|
_CODE SEGMENT BYTE PUBLIC 'CODE'
|
|||
|
ASSUME CS:_CODE
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF L8086
|
|||
|
_PROG SEGMENT BYTE PUBLIC 'PROG'
|
|||
|
ASSUME CS:_PROG
|
|||
|
ENDIF
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; External program references (S and D models)
|
|||
|
;
|
|||
|
IF LPROG EQ 0
|
|||
|
EXTRN _MAIN:NEAR
|
|||
|
IFNDEF PROMEM ;;; Protected Mode - IGNORE
|
|||
|
EXTRN RBRK:NEAR ; C library function
|
|||
|
ENDIF
|
|||
|
if scheme
|
|||
|
extrn allmem:near ; C library function
|
|||
|
extrn rsttimer:near,unfixint:near ; PCS routines
|
|||
|
extrn zcuron:near,zclear:near,zputcur:near ; "
|
|||
|
extrn xli_term:near ; PCS routine
|
|||
|
IFDEF EXPMEM
|
|||
|
extrn rlsexp:near ; PCS routine
|
|||
|
ENDIF
|
|||
|
endif
|
|||
|
ENDIF
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; Execution begins here
|
|||
|
;
|
|||
|
PUBLIC CXINIT
|
|||
|
|
|||
|
CXINIT PROC FAR
|
|||
|
CLI
|
|||
|
IF COM
|
|||
|
MOV AX,OFFSET PGROUP:TAIL ; set up DS/SS for .COM file
|
|||
|
ADD AX,16
|
|||
|
MOV CL,4
|
|||
|
SHR AX,CL
|
|||
|
MOV BX,CS
|
|||
|
ADD AX,BX
|
|||
|
MOV DS,AX
|
|||
|
MOV SS,AX
|
|||
|
MOV SP,OFFSET DGROUP:SBASE+STKRSV
|
|||
|
ELSE
|
|||
|
MOV AX,DGROUP ; set up DS/SS for .EXE file
|
|||
|
MOV DS,AX
|
|||
|
IFDEF PROMEM ;;; Protected Mode
|
|||
|
mov ss,ax ; ss=ds
|
|||
|
mov _ss,ax ; and save in _ss
|
|||
|
mov bx, _base ; bx = base of stack (relative to DS)
|
|||
|
add bx, _stack ; add # bytes of stack (default = 2048)
|
|||
|
mov sp, bx ; and save in sp
|
|||
|
mov _top, bx ; top of stack (relative to DS)
|
|||
|
mov _sp,bx ; sp reset value
|
|||
|
ELSE
|
|||
|
MOV AX,XSTACK
|
|||
|
MOV SS,AX
|
|||
|
MOV SP,STKRSV
|
|||
|
ENDIF
|
|||
|
ENDIF
|
|||
|
STI
|
|||
|
if scheme
|
|||
|
;
|
|||
|
; Save address of our exit routine where C can use it
|
|||
|
;
|
|||
|
mov ax,offset xcexit
|
|||
|
mov _onexit,ax
|
|||
|
endif
|
|||
|
;
|
|||
|
; Compute program size in bytes and save in _PSIZE
|
|||
|
;
|
|||
|
IFDEF PROMEM ;;; Protected Mode
|
|||
|
; _PSIZE actually has limit, should increment....
|
|||
|
mov ax, 0ffffh ; Program size will always be 64kb
|
|||
|
MOV WORD PTR _PSIZE,AX
|
|||
|
xor ax, ax
|
|||
|
MOV WORD PTR _PSIZE+2,AX
|
|||
|
ELSE
|
|||
|
MOV AX,DS
|
|||
|
MOV CX,CS
|
|||
|
SUB AX,CX
|
|||
|
MOV CL,4
|
|||
|
ROL AX,CL
|
|||
|
MOV WORD PTR _PSIZE,AX
|
|||
|
AND WORD PTR _PSIZE,0FFF0H
|
|||
|
AND AX,15
|
|||
|
MOV WORD PTR _PSIZE+2,AX
|
|||
|
ENDIF
|
|||
|
;
|
|||
|
; Clear the uninitialized data area
|
|||
|
;
|
|||
|
XOR AX,AX
|
|||
|
MOV DI,OFFSET DGROUP:UDATA
|
|||
|
MOV CX,OFFSET DGROUP:SBASE
|
|||
|
SUB CX,DI
|
|||
|
SHR CX,1
|
|||
|
JZ M0
|
|||
|
PUSH ES
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
CLD
|
|||
|
REP STOSW
|
|||
|
POP ES
|
|||
|
;
|
|||
|
; Get DOS version number
|
|||
|
;
|
|||
|
M0: MOV AH,30H ; get DOS version number
|
|||
|
INT 21H
|
|||
|
OR AL,AL
|
|||
|
JNZ M00
|
|||
|
MOV AX,1 ; assume 1.00 if null return
|
|||
|
M00: MOV WORD PTR _DOS,AX
|
|||
|
MOV _PSP+2,ES ; set up pointer to prog seg prefix
|
|||
|
;
|
|||
|
; Examine the environment string area
|
|||
|
;
|
|||
|
ife scheme ; PCS ignores DOS environment strings
|
|||
|
IF MSDOS EQ 1
|
|||
|
CMP _DOS,2
|
|||
|
JL M01
|
|||
|
ENDIF
|
|||
|
MOV AX,ES:[2CH]
|
|||
|
MOV WORD PTR _ENV+2,AX ; set up pointer to environment
|
|||
|
OR AX,AX
|
|||
|
JZ M01 ; branch if null
|
|||
|
PUSH ES ; determine number of bytes
|
|||
|
CLD
|
|||
|
LES DI,_ENV
|
|||
|
XOR AX,AX
|
|||
|
XOR BX,BX
|
|||
|
MOV CX,7FFFH
|
|||
|
M0A: REPNZ SCASB
|
|||
|
JNZ M0C
|
|||
|
INC BX
|
|||
|
SCASB
|
|||
|
JNZ M0A
|
|||
|
MOV _ESIZE,DI ; save environment size
|
|||
|
MOV _ENVC,BX ; save environment string count
|
|||
|
CMP _DOS,3 ; include command name for DOS 3
|
|||
|
JL M0B
|
|||
|
ADD DI,2
|
|||
|
REPNZ SCASB
|
|||
|
JNZ M0C
|
|||
|
M0B: ADD DI,2 ; make size an even number
|
|||
|
AND DI,0FFFEH
|
|||
|
MOV _XSIZE,DI
|
|||
|
M0C: POP ES
|
|||
|
endif
|
|||
|
;
|
|||
|
; Examine command line
|
|||
|
;
|
|||
|
M01: MOV SI,80H ; check command line
|
|||
|
MOV CL,ES:[SI]
|
|||
|
XOR CH,CH ; CX contains length of cmd line
|
|||
|
|
|||
|
JCXZ M12 ; branch if null
|
|||
|
M1: INC SI ; scan for first arg
|
|||
|
MOV AL,ES:[SI]
|
|||
|
ife scheme ; PCS doesn't scan for special args
|
|||
|
IF MSDOS EQ 1
|
|||
|
CMP _DOS,2
|
|||
|
JGE M10
|
|||
|
CMP AL,'<'
|
|||
|
JE M2 ; branch if input file name
|
|||
|
CMP AL,'>'
|
|||
|
JE M3 ; branch if output file name
|
|||
|
ENDIF
|
|||
|
M10: CMP AL,'='
|
|||
|
JE M4 ; branch if stack size
|
|||
|
endif
|
|||
|
CMP AL,' '
|
|||
|
JE M11 ; branch if white space
|
|||
|
CMP AL,TAB
|
|||
|
JNE M12 ; branch if normal arg
|
|||
|
M11: DEC CX
|
|||
|
JG M1
|
|||
|
XOR CX,CX
|
|||
|
M12: JMP M5 ; branch if no args found
|
|||
|
ife scheme ; PCS doesn't scan for special args
|
|||
|
IF MSDOS EQ 1
|
|||
|
;
|
|||
|
; Get input file name
|
|||
|
;
|
|||
|
M2: MOV DI,OFFSET DGROUP:_INAME
|
|||
|
JMP M31
|
|||
|
;
|
|||
|
; Get output file name
|
|||
|
;
|
|||
|
M3: MOV DI,OFFSET DGROUP:_ONAME
|
|||
|
;
|
|||
|
; Save file name in data area
|
|||
|
;
|
|||
|
M31: XOR AH,AH
|
|||
|
M32: DEC CX
|
|||
|
JZ M33
|
|||
|
INC SI
|
|||
|
MOV AL,ES:[SI]
|
|||
|
CMP AL,' '
|
|||
|
JZ M33
|
|||
|
CMP AL,TAB
|
|||
|
JZ M33
|
|||
|
MOV DS:[DI],AL
|
|||
|
INC DI
|
|||
|
INC AH
|
|||
|
CMP AH,32
|
|||
|
JE M34
|
|||
|
JMP M32
|
|||
|
M33: MOV BYTE PTR DS:[DI],0
|
|||
|
JMP M11
|
|||
|
M34: MOV DX,OFFSET DGROUP:NAMERR
|
|||
|
JMP NEAR PTR XCABT
|
|||
|
ENDIF
|
|||
|
;
|
|||
|
; Get stack and heap sizes from command line
|
|||
|
;
|
|||
|
M4: CALL GETNUM ; get stack size
|
|||
|
JC M47 ; branch if error
|
|||
|
TEST BX,BX
|
|||
|
JZ M42A ; bypass if size is 0
|
|||
|
CMP AL,'K'
|
|||
|
JE M41
|
|||
|
CMP AL,'k'
|
|||
|
JNE M42 ; branch if not kilobytes
|
|||
|
M41: TEST BX,0FFC0H
|
|||
|
JNZ M47 ; error if size > 63
|
|||
|
XCHG BH,BL ; multiply by 1024
|
|||
|
SHL BH,1
|
|||
|
SHL BH,1
|
|||
|
DEC CX ; advance to next character
|
|||
|
JZ M42
|
|||
|
INC SI
|
|||
|
MOV AL,ES:[SI]
|
|||
|
M42: MOV _STACK,BX ; save stack size
|
|||
|
M42A: TEST CX,CX
|
|||
|
JZ M5 ; branch if end of command line
|
|||
|
CMP AL,' '
|
|||
|
JE M46 ; loop if blank
|
|||
|
CMP AL,TAB
|
|||
|
JE M46 ; loop if tab
|
|||
|
CMP AL,'/'
|
|||
|
JNE M47 ; branch if not slash
|
|||
|
CALL GETNUM ; get heap size
|
|||
|
JC M47 ; branch if error
|
|||
|
XOR DX,DX ; long result is in DX,BX
|
|||
|
TEST BX,BX
|
|||
|
JZ M45 ; branch if size is 0
|
|||
|
CMP AL,'K'
|
|||
|
JE M43
|
|||
|
CMP AL,'k'
|
|||
|
JNE M44 ; branch if not kilobytes
|
|||
|
M43: XCHG BH,BL ; multiply by 1024
|
|||
|
ROL BX,1
|
|||
|
ROL BX,1
|
|||
|
MOV DX,BX
|
|||
|
AND BX,0FC00H
|
|||
|
AND DX,3FFH
|
|||
|
DEC CX ; advance to next character
|
|||
|
JZ M44
|
|||
|
INC SI
|
|||
|
MOV AL,ES:[SI]
|
|||
|
M44: MOV WORD PTR _MNEED,BX ; save heap size
|
|||
|
MOV WORD PTR _MNEED+2,DX
|
|||
|
M45: TEST CX,CX
|
|||
|
JZ M5 ; branch if end of command line
|
|||
|
CMP AL,' '
|
|||
|
JE M46 ; loop if blank
|
|||
|
CMP AL,TAB
|
|||
|
JNE M47 ; error if not tab
|
|||
|
M46: JMP M11
|
|||
|
M47: MOV DX,OFFSET DGROUP:STKERR ; abort if stack/heap size error
|
|||
|
JMP NEAR PTR XCABT
|
|||
|
endif ;matches IFE near M12:
|
|||
|
;
|
|||
|
; Set up the stack
|
|||
|
;
|
|||
|
ife scheme ; PCS ignores DOS environment strings
|
|||
|
IF LDATA EQ 0
|
|||
|
M5: MOV AX,_XSIZE ; reserve space for environment
|
|||
|
ADD AX,15
|
|||
|
AND AX,0FFFEH
|
|||
|
ELSE
|
|||
|
M5: XOR AX,AX
|
|||
|
ENDIF
|
|||
|
else
|
|||
|
M5: xor ax,ax
|
|||
|
endif
|
|||
|
|
|||
|
IFDEF PROMEM ;;; Protected Mode
|
|||
|
mov bx,_top ; bx = top of stack
|
|||
|
jmp M54a
|
|||
|
M54: MOV DX,OFFSET DGROUP:MEMERR2 ; abort if error in releasing memory
|
|||
|
JMP NEAR PTR XCABT
|
|||
|
M54a:
|
|||
|
ELSE
|
|||
|
MOV BX,_STACK ; get stack size
|
|||
|
SHR BX,1 ; make size even
|
|||
|
ADD BX,BX
|
|||
|
CMP BX,STKMIN
|
|||
|
JA M51
|
|||
|
MOV BX,STKMIN ; use default if too small
|
|||
|
MOV _STACK,BX
|
|||
|
M51: ADD BX,AX ; add environment size
|
|||
|
JC M54 ; abort if overflow
|
|||
|
MOV DX,ES:2 ; compute available paragraphs
|
|||
|
if scheme
|
|||
|
mov _paras,dx ; save no. paragraphs for Scheme
|
|||
|
endif
|
|||
|
MOV AX,SS
|
|||
|
SUB DX,AX
|
|||
|
TEST DX,0F000H
|
|||
|
JNZ M52 ; branch if greater than 64Kbytes
|
|||
|
SHL DX,1 ; convert to bytes
|
|||
|
SHL DX,1
|
|||
|
SHL DX,1
|
|||
|
SHL DX,1
|
|||
|
JMP M53
|
|||
|
M52: MOV DX,0FFF0H ; use largest value
|
|||
|
IF LDATA
|
|||
|
M53: CMP DX,BX ; check if stack will fit
|
|||
|
JA M55
|
|||
|
ELSE
|
|||
|
M53: CMP DX,BX ; check if stack will fit
|
|||
|
JB M54
|
|||
|
ADD BX,_BASE ; adjust S/P model for statics
|
|||
|
JNC M55
|
|||
|
ENDIF
|
|||
|
M54: MOV DX,OFFSET DGROUP:MEMERR2 ; abort if error in releasing memory
|
|||
|
JMP NEAR PTR XCABT
|
|||
|
M55: CLI
|
|||
|
MOV _TOP,BX ; set top-of-stack
|
|||
|
MOV SP,BX ; set stack pointer
|
|||
|
IF LDATA EQ 0
|
|||
|
MOV AX,DS
|
|||
|
MOV SS,AX
|
|||
|
ENDIF
|
|||
|
MOV _SS,SS
|
|||
|
STI
|
|||
|
ENDIF ; IFDEF PROMEM
|
|||
|
|
|||
|
;
|
|||
|
; Set up memory allocation pointers
|
|||
|
;
|
|||
|
PUSH CX ; save command byte count
|
|||
|
|
|||
|
IFDEF PROMEM ;;; Protected Mode
|
|||
|
; Assume small data model
|
|||
|
MOV AX,SS ; ax=stack segment
|
|||
|
MOV _MBASE+2,AX ; _mbase = top of stack
|
|||
|
mov _mbase, bx ;
|
|||
|
MOV _MNEXT+2,AX ; _mnext = _mbase
|
|||
|
mov _mnext, bx ;
|
|||
|
mov bx, 0fff0h ; Protected mode has a full 64K
|
|||
|
sub bx, _top ; subtract out top of stack
|
|||
|
MOV _MSIZE,BX ; _msize = size of heap pool
|
|||
|
xor ax, ax
|
|||
|
ELSE
|
|||
|
ADD BX,15 ; compute mem pool base segment number
|
|||
|
JC M54
|
|||
|
MOV CL,4
|
|||
|
SHR BX,CL
|
|||
|
MOV AX,SS
|
|||
|
ADD AX,BX
|
|||
|
MOV _MBASE+2,AX
|
|||
|
MOV _MNEXT+2,AX
|
|||
|
MOV BX,ES:2 ; get top segment number
|
|||
|
SUB BX,AX ; compute memory pool size
|
|||
|
JBE M54 ; branch if insufficient memory
|
|||
|
MOV CL,4 ; compute number of bytes
|
|||
|
ROL BX,CL
|
|||
|
MOV AX,BX
|
|||
|
AND AX,15
|
|||
|
AND BX,0FFF0H
|
|||
|
MOV _MSIZE,BX
|
|||
|
ENDIF
|
|||
|
|
|||
|
MOV _MSIZE+2,AX
|
|||
|
|
|||
|
PUSH ES ; reset memory pool
|
|||
|
PUSH SI
|
|||
|
CALL RBRK
|
|||
|
POP SI
|
|||
|
POP ES
|
|||
|
OR AX,AX
|
|||
|
JNZ M54 ; branch if not enough memory
|
|||
|
|
|||
|
if scheme
|
|||
|
IFNDEF PROMEM ;;; Protected Mode - IGNORE
|
|||
|
push si
|
|||
|
call allmem ; allocate the rest of the data segment
|
|||
|
; to C's heap (small model only);
|
|||
|
; later, in "initmem", PCS will get the
|
|||
|
; rest of MSDOS's memory for itself
|
|||
|
pop si
|
|||
|
or ax,ax
|
|||
|
jnz m54
|
|||
|
ENDIF
|
|||
|
endif
|
|||
|
|
|||
|
POP DX ; restore command line length
|
|||
|
;
|
|||
|
; Put return address at top of stack
|
|||
|
;
|
|||
|
IF MSDOS EQ 1
|
|||
|
PUSH ES ; return is to 1st word of prog prefix
|
|||
|
XOR AX,AX
|
|||
|
PUSH AX
|
|||
|
MOV BP,SP ; BP contains stack linkage
|
|||
|
ENDIF
|
|||
|
;
|
|||
|
; copy command line to stack
|
|||
|
;
|
|||
|
MOV CX,DX ; get residual command line length
|
|||
|
SUB SP,CX ; allocate stack space
|
|||
|
DEC SP
|
|||
|
MOV DI,SP
|
|||
|
MOV DX,SP ; save pointer to end of command
|
|||
|
ADD DX,CX
|
|||
|
JCXZ M71 ; skip if no bytes to move
|
|||
|
PUSH DS ; move them
|
|||
|
PUSH ES
|
|||
|
POP DS
|
|||
|
PUSH SS
|
|||
|
POP ES
|
|||
|
CLD
|
|||
|
REP MOVSB
|
|||
|
POP DS
|
|||
|
M71: MOV BYTE PTR SS:[DI],0 ; append null byte
|
|||
|
MOV WORD PTR _ARG,SP ; save arg array pointer
|
|||
|
MOV WORD PTR _ARG+2,SS
|
|||
|
;
|
|||
|
; Move environment to stack for small data models
|
|||
|
;
|
|||
|
ife scheme ; PCS ignores DOS environment strings
|
|||
|
IF LDATA EQ 0
|
|||
|
MOV CX,_XSIZE ; get extended env size
|
|||
|
JCXZ M72 ; branch if no environment
|
|||
|
SUB SP,CX ; allocate stack space
|
|||
|
MOV DI,SP
|
|||
|
PUSH DS ; save important regs
|
|||
|
PUSH ES
|
|||
|
PUSH SI
|
|||
|
PUSH SS ; set stack as destination seg
|
|||
|
POP ES
|
|||
|
MOV SI,WORD PTR _ENV+2
|
|||
|
MOV WORD PTR _ENV,DI ; save relocated env pointer
|
|||
|
MOV WORD PTR _ENV+2,SS
|
|||
|
MOV DS,SI ; set env as source
|
|||
|
XOR SI,SI
|
|||
|
CLD ; move environment
|
|||
|
REP MOVSB
|
|||
|
POP SI ; restore regs and continue
|
|||
|
POP ES
|
|||
|
POP DS
|
|||
|
ENDIF
|
|||
|
endif
|
|||
|
;
|
|||
|
; Build argument vector
|
|||
|
;
|
|||
|
ife scheme ; PCS parses its own command line
|
|||
|
M72: AND SP,0FFFEH ; make stack pointer even
|
|||
|
MOV SI,DX ; prepare to scan command backwards
|
|||
|
XOR CX,CX
|
|||
|
PUSH CX ; push null terminator for argv
|
|||
|
IF LDATA
|
|||
|
PUSH CX
|
|||
|
ENDIF
|
|||
|
MOV BX,SP ; save this null byte address
|
|||
|
M8: CMP SI,WORD PTR _ARG ; skip trailing white space
|
|||
|
JNE M80
|
|||
|
JMP M83
|
|||
|
M80: DEC SI
|
|||
|
CMP BYTE PTR SS:[SI],' '
|
|||
|
JE M8
|
|||
|
CMP BYTE PTR SS:[SI],TAB
|
|||
|
JE M8
|
|||
|
MOV BYTE PTR SS:[SI+1],0 ; install null terminator byte
|
|||
|
MOV AL,0 ; indicate white space scan
|
|||
|
CMP BYTE PTR SS:[SI],'"'
|
|||
|
JNE M81 ; branch if not quoted arg
|
|||
|
CMP SI,WORD PTR _ARG
|
|||
|
JE M81
|
|||
|
CMP BYTE PTR SS:[SI-1],'\'
|
|||
|
JE M810 ; branch if \"
|
|||
|
MOV AL,'"' ; indicate quote scan
|
|||
|
MOV BYTE PTR SS:[SI],0 ; put null in place of quote
|
|||
|
M81: CMP SI,WORD PTR _ARG
|
|||
|
JE M82 ; branch if no more chars
|
|||
|
DEC SI ; position to next char
|
|||
|
CMP BYTE PTR SS:[SI],'"'
|
|||
|
JNE M81C ; branch if not quote
|
|||
|
CMP SI,WORD PTR _ARG
|
|||
|
JE M81C ; branch if no more chars
|
|||
|
CMP BYTE PTR SS:[SI-1],'\'
|
|||
|
JNE M81C ; branch if not \"
|
|||
|
M810: PUSH SI ; squish args to remove \
|
|||
|
M81A: DEC SI
|
|||
|
CMP SI,WORD PTR _ARG
|
|||
|
JE M81B
|
|||
|
MOV AH,SS:[SI-1]
|
|||
|
MOV SS:[SI],AH
|
|||
|
JMP M81A
|
|||
|
M81B: INC WORD PTR _ARG
|
|||
|
POP SI
|
|||
|
JMP M81D
|
|||
|
M81C: OR AL,AL
|
|||
|
JNZ M82A ; branch if not white space scan
|
|||
|
M81D: CMP BYTE PTR SS:[SI],' ' ; find next white space
|
|||
|
JE M81E
|
|||
|
CMP BYTE PTR SS:[SI],TAB
|
|||
|
JNE M81
|
|||
|
M81E: INC SI ; position to start of arg
|
|||
|
IF LDATA
|
|||
|
M82: PUSH SS ; add arg pointer to vector
|
|||
|
PUSH SI
|
|||
|
ELSE
|
|||
|
M82: PUSH SI ; put arg pointer into argv
|
|||
|
ENDIF
|
|||
|
INC CX ; bump arg count
|
|||
|
JMP M8 ; loop till all args done
|
|||
|
M82A: CMP BYTE PTR SS:[SI],'"' ; come here to find starting quote
|
|||
|
JNE M81 ; branch if not quote
|
|||
|
MOV BYTE PTR SS:[SI],' ' ; replace it with white space
|
|||
|
JMP M81E ; go save arg pointer
|
|||
|
;
|
|||
|
; Construct argv[0]
|
|||
|
;
|
|||
|
M83: CMP _DOS,2
|
|||
|
JLE M84
|
|||
|
MOV AX,WORD PTR _ENV ; use env trailer for DOS 3
|
|||
|
ADD AX,_ESIZE
|
|||
|
INC AX
|
|||
|
INC AX
|
|||
|
IF LDATA
|
|||
|
PUSH [WORD PTR _ENV+2]
|
|||
|
ENDIF
|
|||
|
PUSH AX
|
|||
|
JMP M85
|
|||
|
IF LDATA
|
|||
|
M84: PUSH SS ; use null byte for DOS 2
|
|||
|
PUSH BX
|
|||
|
ELSE
|
|||
|
M84: PUSH BX ; use null byte for DOS 2
|
|||
|
ENDIF
|
|||
|
;
|
|||
|
; Save argv information
|
|||
|
;
|
|||
|
M85: INC CX ; save arg count
|
|||
|
MOV _ARGC,CX
|
|||
|
IF LDATA
|
|||
|
MOV WORD PTR _ARGV,SP ; save arg vector pointer
|
|||
|
MOV WORD PTR _ARGV+2,SS
|
|||
|
ELSE
|
|||
|
MOV _ARGV,SP ; save arg vector pointer
|
|||
|
ENDIF
|
|||
|
|
|||
|
else ; PCS parses its own command line
|
|||
|
|
|||
|
; -------------------------------------------------
|
|||
|
; The PCS command line parser
|
|||
|
; -------------------------------------------------
|
|||
|
|
|||
|
; The PCS command line can look as follows:
|
|||
|
;
|
|||
|
; PCS (... ...) atom atom (... ...) "string" atom ...
|
|||
|
;
|
|||
|
; which parses into PCS-INITIAL-ARGUMENTS as:
|
|||
|
;
|
|||
|
; ( "(... ...)" "atom" "atom" "(... ...)" "\"string\"" "atom" ... )
|
|||
|
;
|
|||
|
; Each command line argument is either an atom, list, or string.
|
|||
|
; Each is treated as one argument for the argv vector, and each is
|
|||
|
; converted to a string which becomes an element of PCS-INITIAL-ARGUMENTS.
|
|||
|
;
|
|||
|
; The command line parser is not a Scheme reader. It looks for blank-separated
|
|||
|
; tokens, where a token can start with a ( and end with the matching ),
|
|||
|
; start and end with a ", or just be a sequence of nonblanks. Backslashed
|
|||
|
; delimiters are skipped over as you'd expect. We don't bother with | since
|
|||
|
; that is a special character to DOS. The blanks between tokens are important
|
|||
|
; since the parser replaces them with nulls to get things set up for C's
|
|||
|
; argv vector, so situations like ...)(... won't be parsed correctly.
|
|||
|
; The parser is implemented as a finite state automaton (FSA).
|
|||
|
;
|
|||
|
; The first command line argument has special meaning but that is
|
|||
|
; handled in "smain.c".
|
|||
|
;
|
|||
|
|
|||
|
; On entry to this section:
|
|||
|
; ES = SS (but we don't care)
|
|||
|
; SP = ptr to start of cmdline
|
|||
|
; DX = ptr to cmdline eos (cmdline on stack with eos at its end)
|
|||
|
|
|||
|
M72:
|
|||
|
push DS ; ES <- DS
|
|||
|
pop ES
|
|||
|
xor AX,AX ; AH is state, AL is current char
|
|||
|
push AX ; push 0 at front of cmdline
|
|||
|
; (we're going to parse backwards)
|
|||
|
and SP,0FFFEH ; make SP even
|
|||
|
mov SI,DX ; SI is index into cmdline
|
|||
|
xor DX,DX ; DH is paren counter, DL is argc
|
|||
|
cld
|
|||
|
M72loop: dec SI ; get the next char from cmdline
|
|||
|
cmp byte ptr SS:[SI-1],'\' ; is it singly escaped?
|
|||
|
jne M72a ; no, jump
|
|||
|
dec SI ; yes, back up to escape char
|
|||
|
M72a: mov AL,SS:[SI]
|
|||
|
mov CX,scan_size ; look it up in char table
|
|||
|
mov DI,offset scan_table
|
|||
|
repne scasb ; put into CX the "char class" for
|
|||
|
; indexing into state table
|
|||
|
mov AL,bytes_per_state ; do 2-D subscript into state table
|
|||
|
mul AH ; ... row
|
|||
|
shl CX,1 ; ... col
|
|||
|
add AX,CX
|
|||
|
mov BX,AX ; (BH=0 since subscript small enough)
|
|||
|
mov AH,state[BX] ; get next state
|
|||
|
mov BL,state+1[BX] ; do action routine
|
|||
|
add BX,offset actions
|
|||
|
jmp BX
|
|||
|
|
|||
|
actions label near ; start action routines ---------->
|
|||
|
ar_out2: inc SI ; 1 char past token, back up
|
|||
|
push SI ; push next argv
|
|||
|
dec SI
|
|||
|
inc DL ; incr argc
|
|||
|
ar_skip: mov byte ptr SS:[SI],0 ; output a null char
|
|||
|
ar_decr: jmp short M72loop
|
|||
|
ar_lpar: dec DH ; decr paren count
|
|||
|
js ar_err ; wrong paren to start with
|
|||
|
jnz short M72loop ; on an inner paren, keep looking
|
|||
|
mov AH,0 ; override state in table
|
|||
|
ar_out1: push SI ; matched delimiter, push next argv
|
|||
|
inc DL ; incr argc
|
|||
|
jmp short M72loop
|
|||
|
ar_rpar: inc DH ; incr paren count
|
|||
|
jmp short M72loop
|
|||
|
ar_err: mov DX,offset dgroup:parserr ; abort on error in cmdline parsing
|
|||
|
jmp near ptr XCABT
|
|||
|
ar_out_end: inc SI ; 1 char past token, back up
|
|||
|
push SI ; push next argv
|
|||
|
dec SI
|
|||
|
inc DL ; incr argc
|
|||
|
ar_end: ; end action routines <----------
|
|||
|
|
|||
|
continue: xor AX,AX ; argv[0] = \0
|
|||
|
push AX
|
|||
|
inc DL ; incr argc
|
|||
|
mov _argv,SP ; save address of argv
|
|||
|
mov DH,0
|
|||
|
push DX
|
|||
|
mov _argc,DX ; save argc
|
|||
|
|
|||
|
endif
|
|||
|
|
|||
|
;
|
|||
|
; Build environment vector
|
|||
|
;
|
|||
|
ife scheme ; PCS ignores DOS environment strings
|
|||
|
XOR AX,AX ; push null terminating pointer
|
|||
|
PUSH AX
|
|||
|
IF LDATA
|
|||
|
PUSH AX
|
|||
|
ENDIF
|
|||
|
MOV AX,_ENVC ; allocate stack space for vector
|
|||
|
ADD AX,AX
|
|||
|
JZ M87 ; branch if null environment
|
|||
|
SUB SP,AX
|
|||
|
IF LDATA
|
|||
|
SUB SP,AX
|
|||
|
ENDIF
|
|||
|
MOV SI,SP ; scan environment
|
|||
|
LES DI,_ENV
|
|||
|
XOR AX,AX
|
|||
|
MOV CX,7FFFH
|
|||
|
MOV DX,_ENVC
|
|||
|
CLD
|
|||
|
M86: MOV SS:[SI],DI
|
|||
|
ADD SI,2
|
|||
|
IF LDATA
|
|||
|
MOV SS:[SI],ES
|
|||
|
ADD SI,2
|
|||
|
ENDIF
|
|||
|
DEC DX
|
|||
|
JLE M87
|
|||
|
REPNE SCASB
|
|||
|
JMP M86
|
|||
|
M87: MOV WORD PTR environ,sp
|
|||
|
IF LDATA
|
|||
|
MOV WORD PTR environ+2,SS
|
|||
|
ENDIF
|
|||
|
endif
|
|||
|
;
|
|||
|
; initialize 8087 numeric data processor
|
|||
|
;
|
|||
|
IFNDEF PROMEM ;;; Protected Mode - IGNORE
|
|||
|
FNINIT ; reset
|
|||
|
FNSTSW _NDPSW ; get status
|
|||
|
MOV AX,100 ; this is just for delay
|
|||
|
MOV DX,AX
|
|||
|
IMUL DX
|
|||
|
TEST _NDPSW,0B8BFH ; 8087 will reset all these
|
|||
|
JNZ M9
|
|||
|
INC _NDP ; indicate ndp present
|
|||
|
ENDIF
|
|||
|
;
|
|||
|
; set up args for _main and call it
|
|||
|
;
|
|||
|
M9: MOV _SP,SP ; save stack pointer reset value
|
|||
|
PUSH DS ; make ES same as DS
|
|||
|
POP ES
|
|||
|
CALL _MAIN ; call C main
|
|||
|
IF MSDOS EQ 1
|
|||
|
CMP _DOS,2
|
|||
|
JL M91 ; branch if DOS 1
|
|||
|
ENDIF
|
|||
|
MOV AX,4C00H ; exit with return code of 0
|
|||
|
INT 21H
|
|||
|
IF MSDOS EQ 1
|
|||
|
M91: MOV SP,BP ;restore ptr to far return
|
|||
|
RET ;return to MS-DOS
|
|||
|
ENDIF
|
|||
|
;**
|
|||
|
;
|
|||
|
; name GETNUM -- get a number from the command line
|
|||
|
;
|
|||
|
; description This function is used internally by the start-up routine
|
|||
|
; while processing the command line.
|
|||
|
;
|
|||
|
;**
|
|||
|
ife scheme
|
|||
|
GETNUM PROC NEAR
|
|||
|
XOR BX,BX ; reset accumulator
|
|||
|
NUM1: DEC CX ; advance to next character
|
|||
|
JZ NUM3 ; branch if end of command line
|
|||
|
INC SI
|
|||
|
MOV AL,ES:[SI]
|
|||
|
CMP AL,'0'
|
|||
|
JL NUM3 ; return if not decimal digit
|
|||
|
CMP AL,'9'
|
|||
|
JG NUM3 ; return if not decimal digit
|
|||
|
SUB AL,'0' ; multiply accumulator by 10
|
|||
|
ADD BX,BX
|
|||
|
JC NUM2
|
|||
|
MOV DX,BX
|
|||
|
ADD BX,BX
|
|||
|
JC NUM2
|
|||
|
ADD BX,BX
|
|||
|
JC NUM2
|
|||
|
ADD BX,DX
|
|||
|
JC NUM2
|
|||
|
XOR AH,AH ; add this digit
|
|||
|
ADD BX,AX
|
|||
|
JNC NUM1 ; loop till done
|
|||
|
NUM2: RET
|
|||
|
NUM3: CLC ; clear carry to indicate no error
|
|||
|
RET
|
|||
|
GETNUM ENDP
|
|||
|
endif
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; name XCABT -- Ignominious abort
|
|||
|
;
|
|||
|
; description This area is entered by direct jump with a message
|
|||
|
; pointer in DS:DX. It sends the message to the
|
|||
|
; console via DOS function 9 and then aborts.
|
|||
|
;
|
|||
|
ENTRY XCABT
|
|||
|
MOV AH,9 ; print error message
|
|||
|
INT 21H
|
|||
|
MOV ES,_PSP+2
|
|||
|
IF MSDOS EQ 1
|
|||
|
CMP _DOS,2
|
|||
|
JL A1
|
|||
|
ENDIF
|
|||
|
MOV AX,4C01H
|
|||
|
INT 21H
|
|||
|
IF MSDOS EQ 1
|
|||
|
A1: PUSH ES
|
|||
|
XOR AX,AX
|
|||
|
PUSH AX
|
|||
|
RET
|
|||
|
ENDIF
|
|||
|
|
|||
|
if scheme
|
|||
|
;
|
|||
|
; Scheme wrapup - the C fn "exit" calls "_exit" which calls this hook routine
|
|||
|
;
|
|||
|
public xcexit
|
|||
|
DOS equ 21h ; MSDOS function request interrupt
|
|||
|
xcexit proc near
|
|||
|
|
|||
|
mov bp,sp ; don't lose our return address to _exit
|
|||
|
|
|||
|
IFDEF EXPMEM
|
|||
|
call rlsexp ; Release Expanded Memory (if any)
|
|||
|
ENDIF
|
|||
|
|
|||
|
call xli_term ; release all external programs
|
|||
|
; allocated under XLI
|
|||
|
IFNDEF PROMEM
|
|||
|
push ES ; return Scheme heap to DOS
|
|||
|
mov AH,49h
|
|||
|
mov ES,first_dos
|
|||
|
int DOS
|
|||
|
pop ES
|
|||
|
jnc MA
|
|||
|
MOV DX,OFFSET DGROUP:MEMERR2 ; abort if error in releasing memory
|
|||
|
JMP NEAR PTR XCABT
|
|||
|
ENDIF
|
|||
|
MA: call rsttimer ; Reset the timer interrupt, if necessary
|
|||
|
call unfixint ; Restore the keyboard "patch" (MWH2)
|
|||
|
call zcuron ; Turn cursor back on
|
|||
|
mov AX,15 ; Load character attribute = white,enable
|
|||
|
push AX
|
|||
|
mov AX,80 ; 80 Columns
|
|||
|
push AX
|
|||
|
mov AX,25 ; 25 Rows
|
|||
|
push AX
|
|||
|
xor AX,AX ; Origin at 0,0
|
|||
|
push AX
|
|||
|
push AX
|
|||
|
call zclear ; Clear the screen
|
|||
|
xor AX,AX
|
|||
|
push AX
|
|||
|
push AX
|
|||
|
inc cur_off ; keep cursor off for EGA modes
|
|||
|
call zputcur ; Put cursor at 0,0
|
|||
|
mov sp,bp ; reestablish the return address to _exit
|
|||
|
ret
|
|||
|
xcexit endp
|
|||
|
|
|||
|
endif
|
|||
|
|
|||
|
CXINIT ENDP
|
|||
|
|
|||
|
|
|||
|
IFDEF PROMEM ;;; Protected Mode
|
|||
|
|
|||
|
;;; Reset heap break point (unix lingo)
|
|||
|
;;;
|
|||
|
;;; Set _mbase = _mnext = DS:_top
|
|||
|
;;; Set _pool = 0:0, _melt = 0:0
|
|||
|
public rbrk
|
|||
|
RBRK PROC NEAR
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
;
|
|||
|
; set up memory allocation pointers
|
|||
|
;
|
|||
|
mov bx, _top
|
|||
|
add bx, 0fh ; round up to para
|
|||
|
and bx, 0fff0h
|
|||
|
mov _tsize, bx ; total size in paras
|
|||
|
|
|||
|
mov ax,ds
|
|||
|
mov _mbase+2,ax ; long ptr to heap base
|
|||
|
mov _mbase, bx
|
|||
|
mov _mnext+2,ax ; long ptr to heap top
|
|||
|
mov _mnext, bx
|
|||
|
|
|||
|
|
|||
|
xor ax,ax
|
|||
|
mov [_msize+2],ax ; number of bytes left in pool
|
|||
|
mov _msize, ax
|
|||
|
|
|||
|
; Clear the 2nd level pool
|
|||
|
mov [_melt],ax
|
|||
|
mov [_pool],ax
|
|||
|
mov [_melt+02],ax
|
|||
|
mov [_pool+02],ax
|
|||
|
pop bp
|
|||
|
ret
|
|||
|
RBRK ENDP
|
|||
|
|
|||
|
;
|
|||
|
|
|||
|
public lsbrk
|
|||
|
lsbrk PROC NEAR
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
mov cx,[bp+6] ; requested size (high)
|
|||
|
mov dx,[bp+4] ; requested size (low)
|
|||
|
or cx, cx
|
|||
|
jnz lsbrk_err1
|
|||
|
mov cx, 0FFF0h
|
|||
|
sub cx, _mnext ; available bytes
|
|||
|
cmp cx, dx
|
|||
|
jb lsbrk_err1
|
|||
|
mov ax, _mnext ; next location in pool
|
|||
|
add _mnext, dx ; bump by requested amount
|
|||
|
mov bx, ax
|
|||
|
pop bp
|
|||
|
ret
|
|||
|
|
|||
|
lsbrk_err1:
|
|||
|
xor ax,ax
|
|||
|
mov bx, ax
|
|||
|
pop bp
|
|||
|
ret
|
|||
|
lsbrk ENDP
|
|||
|
|
|||
|
|
|||
|
COMMENT %
|
|||
|
;; _RBRK (int desire)
|
|||
|
;; desire is initial heap in paras
|
|||
|
;; return 0 if OK, ffff otherwise
|
|||
|
;;
|
|||
|
public _rbrk
|
|||
|
;;extrn _model:word
|
|||
|
_rbrk proc near
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
push es
|
|||
|
;mov word ptr [_oserr],_model
|
|||
|
|
|||
|
mov bx, 0 ;; what is really needed here? 128K?
|
|||
|
mov [_tsize],bx ;; really total size with heap
|
|||
|
|
|||
|
mov ax,[_mbase] ;; reset heap allocator ptrs
|
|||
|
mov [_mnext],ax
|
|||
|
mov ax,[_mbase+02]
|
|||
|
mov [_mnext+02] ,ax
|
|||
|
xor ax,ax
|
|||
|
pop es
|
|||
|
pop bp
|
|||
|
ret
|
|||
|
_rbrk_error1:
|
|||
|
mov [_oserr],ax
|
|||
|
_rbrk_error:
|
|||
|
mov ax,0ffffh
|
|||
|
pop es
|
|||
|
pop bp
|
|||
|
ret
|
|||
|
_rbrk endp
|
|||
|
%
|
|||
|
ENDIF
|
|||
|
;**
|
|||
|
;
|
|||
|
; Dummy segment to establish top of program for small program models
|
|||
|
;
|
|||
|
IF S8086
|
|||
|
IF COM
|
|||
|
TAIL SEGMENT WORD 'PROG'
|
|||
|
DW -1
|
|||
|
TAIL ENDS
|
|||
|
ENDIF
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF S8086
|
|||
|
PROG ENDS
|
|||
|
ENDIF
|
|||
|
IF D8086
|
|||
|
CODE ENDS
|
|||
|
ENDIF
|
|||
|
IF P8086
|
|||
|
_CODE ENDS
|
|||
|
OLDCODE SEGMENT BYTE ; This catches Version 2 code
|
|||
|
DW 0CACAH
|
|||
|
OLDCODE ENDS
|
|||
|
ENDIF
|
|||
|
IF L8086
|
|||
|
_PROG ENDS
|
|||
|
OLDPROG SEGMENT BYTE ; This catches Version 2 code
|
|||
|
DW 0CACAH
|
|||
|
OLDPROG ENDS
|
|||
|
ENDIF
|
|||
|
PAGE
|
|||
|
;**
|
|||
|
;
|
|||
|
; DGROUP includes the segments named DATA, UDATA, and XSTACK. The startup
|
|||
|
; routine initializes DS to point to this group, and DS must then be pre-
|
|||
|
; served throughout the program. The segments within DGROUP are defined
|
|||
|
; as follows:
|
|||
|
;
|
|||
|
; DATA => Contains all static (local and global) initialized items.
|
|||
|
; UDATA => Contains all static (local and global) uninitialized items.
|
|||
|
; XSTACK => Stack for the startup routine.
|
|||
|
;
|
|||
|
; During the startup routine, the initial stack (XSTACK) is replaced with
|
|||
|
; one that has the correct size for program execution. This size is
|
|||
|
; determined by examining the command line and the _STACK global item. Then
|
|||
|
; for the S and P memory models, the stack is set up relative to DGROUP (i.e.
|
|||
|
; stack items can addressed via DS). For the D and L models, the stack
|
|||
|
; segment stands alone and can be up to 64K bytes.
|
|||
|
;
|
|||
|
; The heap (i.e. the space used by the memory allocator) resides above the
|
|||
|
; stack and is also initialized by the startup routine. Any space not
|
|||
|
; immediately needed for the heap (as defined by _MNEED) is returned to DOS.
|
|||
|
;
|
|||
|
; At the end of the startup routine, memory is organized in the following
|
|||
|
; sequence:
|
|||
|
;
|
|||
|
; -- code --
|
|||
|
; -- DATA --
|
|||
|
; -- UDATA --
|
|||
|
; -- stack --
|
|||
|
; -- heap --
|
|||
|
;
|
|||
|
; FOR PROPER OPERATION OF THE STANDARD MEMORY ALLOCATOR, THIS SEQUENCE IS
|
|||
|
; EXTREMELY IMPORTANT. IF YOU TAMPER WITH THE STARTUP ROUTINE OR INTRODUCE
|
|||
|
; SEGMENTS AND CLASSES THAT DO NOT FOLLOW LATTICE CONVENTIONS, CHECK THE
|
|||
|
; LOAD MAP CAREFULLY.
|
|||
|
;
|
|||
|
;**
|
|||
|
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; Initialized data
|
|||
|
;
|
|||
|
DATA SEGMENT PARA PUBLIC 'DATA'
|
|||
|
EXTRN _STACK:WORD
|
|||
|
EXTRN _MNEED:DWORD
|
|||
|
|
|||
|
IFDEF PROMEM ;;; Protected Mode
|
|||
|
EXTRN _POOL:WORD
|
|||
|
EXTRN _MELT:WORD
|
|||
|
ENDIF
|
|||
|
|
|||
|
PUBLIC _MODEL,_VER,_TOP,_BASE,_PSP,_MBASE,_MNEXT,_MSIZE,_DSIZE,_PSIZE
|
|||
|
PUBLIC _ENV,_DOS,_TSIZE,_ESIZE,_XSIZE,_SS,_SP,_NDP,_NDPSW,_NDPCW
|
|||
|
PUBLIC _FPA,_FPERR,_OSERR,_SIGFPE,_ARGV,_ARGC,_ENVC,environ
|
|||
|
if scheme
|
|||
|
extrn _onexit:word ; our hook into C exit fn
|
|||
|
extrn cur_off:byte
|
|||
|
public _paras,first_pa,first_dos
|
|||
|
endif
|
|||
|
IF S8086
|
|||
|
_MODEL DW 0
|
|||
|
ENDIF
|
|||
|
IF P8086
|
|||
|
_MODEL DW 1
|
|||
|
ENDIF
|
|||
|
IF D8086
|
|||
|
_MODEL DW 2
|
|||
|
ENDIF
|
|||
|
IF L8086
|
|||
|
_MODEL DW 3
|
|||
|
ENDIF
|
|||
|
_VER DB "LC 3.00",0
|
|||
|
_DOS DB 0 ; DOS major version number
|
|||
|
DB 0 ; DOS minor version number
|
|||
|
_SS DW 0 ; stack segment number
|
|||
|
_SP DW 0 ; SP reset value
|
|||
|
_TOP DW 0 ; top of stack (relative to SS)
|
|||
|
_BASE DW OFFSET DGROUP:SBASE ; base of stack (relative to DS)
|
|||
|
_PSP DW 0 ; program segment prefix pointer
|
|||
|
DW 0
|
|||
|
_MBASE DW 0 ; base of memory pool
|
|||
|
DW 0
|
|||
|
_MNEXT DW 0 ; next available memory location
|
|||
|
DW 0
|
|||
|
_MSIZE DW 0 ; number of bytes left in pool
|
|||
|
DW 0
|
|||
|
_TSIZE DW 0 ; total size in paragraphs
|
|||
|
_PSIZE DD 0 ; size of program in bytes
|
|||
|
_DSIZE DW OFFSET DGROUP:SBASE ; size of static data in bytes
|
|||
|
DW 0
|
|||
|
IF LDATA
|
|||
|
_ARGV DD 0 ; argument vector pointer
|
|||
|
environ DD 0 ; environment vector pointer
|
|||
|
ELSE
|
|||
|
DD 0 ; *** DOS 2.00 trashing bug ***
|
|||
|
_ARGV DW 0 ; argument vector pointer
|
|||
|
environ DW 0 ; environment vector pointer
|
|||
|
ENDIF
|
|||
|
_ARGC DW 0 ; argument count
|
|||
|
_ENVC DW 0 ; environment count
|
|||
|
_ARG DD 0 ; far pointer to original arg array
|
|||
|
_ENV DD 0 ; far pointer to original env array
|
|||
|
_ESIZE DW 0 ; environment size in bytes
|
|||
|
_XSIZE DW 0 ; extended env size in bytes
|
|||
|
_FPA DQ 0 ; floating point accumulator
|
|||
|
_FPERR DW 0 ; floating point error code
|
|||
|
_NDP DB 0 ; non-zero if 8087 is installed
|
|||
|
_NDPSW DW 0FFFFH ; 8087 status word
|
|||
|
_NDPCW DW 0 ; 8087 control word
|
|||
|
_OSERR DW 0 ; DOS error code
|
|||
|
IF LPROG
|
|||
|
_SIGFPE DD 0 ; Floating point error signal
|
|||
|
ELSE
|
|||
|
_SIGFPE DW 0 ; Floating point error signal
|
|||
|
ENDIF
|
|||
|
|
|||
|
if scheme
|
|||
|
|
|||
|
_PARAS DW 0 ; # of paragraphs of memory available
|
|||
|
FIRST_PA DW 0 ; seg# of first para. actually used for
|
|||
|
; Scheme heap
|
|||
|
FIRST_DOS DW 0 ; seg# of first para. from DOS for
|
|||
|
; Scheme heap
|
|||
|
|
|||
|
; the characters sought by PCS's scanner
|
|||
|
scan_table db 0,' ()"',0
|
|||
|
scan_size equ $-scan_table
|
|||
|
|
|||
|
; the FSA transition table used to parse PCS's command line
|
|||
|
; (This once included handling for vertical-bar delimited symbols, but
|
|||
|
; DOS's use of | rendered it useless, so it was removed.)
|
|||
|
|
|||
|
start_state equ 0
|
|||
|
list_state equ 1
|
|||
|
atom_state equ 2
|
|||
|
strg_state equ 3
|
|||
|
end_state equ 4
|
|||
|
err_state equ 5
|
|||
|
|
|||
|
state label byte
|
|||
|
; initial state
|
|||
|
db atom_state,ar_decr-actions ; any char
|
|||
|
db strg_state,ar_decr-actions ; "
|
|||
|
db list_state,ar_rpar-actions ; )
|
|||
|
db err_state,ar_err-actions ; (
|
|||
|
db start_state,ar_skip-actions ; blank
|
|||
|
db end_state,ar_end-actions ; null
|
|||
|
bytes_per_state equ $-state
|
|||
|
; in list
|
|||
|
db list_state,ar_decr-actions
|
|||
|
db list_state,ar_decr-actions
|
|||
|
db list_state,ar_rpar-actions
|
|||
|
db list_state,ar_lpar-actions ; start_state also possible, see ar_lpar
|
|||
|
db list_state,ar_decr-actions
|
|||
|
db err_state,ar_err-actions
|
|||
|
; in atom
|
|||
|
db atom_state,ar_decr-actions
|
|||
|
db atom_state,ar_decr-actions
|
|||
|
db atom_state,ar_decr-actions
|
|||
|
db atom_state,ar_decr-actions
|
|||
|
db start_state,ar_out2-actions
|
|||
|
db end_state,ar_out_end-actions
|
|||
|
; in string
|
|||
|
db strg_state,ar_decr-actions
|
|||
|
db start_state,ar_out1-actions
|
|||
|
db strg_state,ar_decr-actions
|
|||
|
db strg_state,ar_decr-actions
|
|||
|
db strg_state,ar_decr-actions
|
|||
|
db err_state,ar_err-actions
|
|||
|
|
|||
|
; The exit and error states are not explicitly represented
|
|||
|
; in the table, action routines deal with them.
|
|||
|
|
|||
|
endif
|
|||
|
|
|||
|
STKERR DB "Invalid stack size",0DH,0AH,"$"
|
|||
|
MEMERR DB "Insufficient memory",0DH,0AH,"$"
|
|||
|
if scheme
|
|||
|
memerr2 db "Error in returning memory to DOS",0dh,0ah,"$"
|
|||
|
parserr db "Error in parsing command line",0dh,0ah,"$"
|
|||
|
endif
|
|||
|
|
|||
|
IF MSDOS EQ 1
|
|||
|
PUBLIC _INAME,_ONAME
|
|||
|
_INAME DB 32 DUP(0) ; input file name
|
|||
|
_ONAME DB 32 DUP(0) ; output file name
|
|||
|
NAMERR DB "Invalid I/O redirection",0DH,0AH,"$"
|
|||
|
ENDIF
|
|||
|
DATA ENDS
|
|||
|
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; Uninitialized data
|
|||
|
;
|
|||
|
UDATA SEGMENT PUBLIC 'DATA'
|
|||
|
UDATA ENDS
|
|||
|
|
|||
|
;**
|
|||
|
;
|
|||
|
; The stack segment is included to prevent the warning from the
|
|||
|
; linker, and also to define the base (lowest address) of the stack.
|
|||
|
;
|
|||
|
STKRSV EQU 128 ; reserved stack size
|
|||
|
STKMIN EQU 512 ; minimum run-time stack size
|
|||
|
IF COM
|
|||
|
XSTACK SEGMENT 'DATA'
|
|||
|
ELSE
|
|||
|
XSTACK SEGMENT STACK 'DATA'
|
|||
|
ENDIF
|
|||
|
SBASE DB STKRSV DUP (?)
|
|||
|
XSTACK ENDS
|
|||
|
|
|||
|
END CXINIT
|
|||
|
|