DATA	SEGMENT PUBLIC 'DATA'
;NOTE THAT IN MS FORTRAN, PUBLIC
; ENDMQQ IS PARAGRAPH PAST END OF USED MEMORY, AND
; MAXMQQ IS PARAGRAPH PAST AVAILABLE MEMORY (I.E. 1ST DOS PARAGRAPH)
;
; FIRST FREE MEMORY
	EXTRN	ENDMQQ:WORD,MAXMQQ:WORD,CESXQQ:WORD
;CESXQQ IS INCOMING ES FROM DOS
;
; SUPPOSEDLY "WORKING" EXAMPLE OF IBM PC EXEC FUNCTION
PSP	STRUC
INTVECT	DW	?
TOM	DW	?
RES1	DW	?
DOSLONG	DB	5 DUP (?)
TERMINA	DD	?
CTRLBRK	DD	?
CRITERR	DD	?
DOS1	DB	22 DUP (?)
ENVIRO	DW	?
DOS2	DB	46 DUP (?)
FPA1	DB	16 DUP (?)
FPA2	DB	20 DUP (?)
UPA	DB	128 DUP (?)
PSP	ENDS

;STRUCTURE LETS NEW CMD INHERIT OLD FCB5,FCB6
EXECDEF	STRUC
NENVIRO	DW
COMMND	DW	2 DUP (0)
FCB5CH	DW	2 DUP (0)
FCB6CH	DW	2 DUP (0)
EXECDEF	ENDS
EXECBLK	EXECDEF	<>
	EVEN
DATA	ENDS
DGROUP	GROUP DATA
CODE	SEGMENT	'CODE'
ASSUME CS:CODE,DS:DGROUP,SS:DGROUP
; ("REMEMBER TO USE THE /C OPTION OF COMMAND.COM")
MEXECOMM	MACRO
	LOCAL ERR1,SPSAVE,SSSAVE
; POINT DS:DX AT COMMAND.COM PARAMETER LIST
; NEEDS TO BE ASCIIZ LIST WITH DRIVE, PATH & FILENAME TO LOAD
EXECOMM:
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX	;SAVE ALL REGISTERS CONTEXTS
	PUSH	SI
	PUSH	DI
	PUSH	BP
	PUSH	DS
	PUSH	ES
	MOV	CS:SPSAVE,SP
; SPSAVE BETTER BE AROUND SOMEPLACE TO SAVE OLD SP
	MOV	CS:SSSAVE,SS
; LIKEWISE SSSAVE ETC.
; SET UP THE PARAMETER BLOCK
	MOV	EXECBLK.NENVIRO,0
; IN SETUP PHASE WE FILL THIS ALL IN... DON'T MESS IT UP HERE.
;	MOV	EXECBLK.COMMND[0],DX
;	MOV	EXECBLK.COMMND[2],DS
	MOV	AX,DS
	MOV	ES,AX
	LEA	BX,DS:EXECBLK
;	MOV	BX,OFFSET EXECBLK
;	XOR	BP,BP	;ZERO BP
	MOV	AX,CESXQQ	;GET ORIGINAL SEGMENT ES HERE
;NEXT LINE WAS BP,AX, NOT DS,AX
	MOV	DS,AX
; AS SET BY FORTRAN, SO WE GET RIGHT ENVIRONMENT
; POINT DS:DX AT THE COMSPEC PARAMETER (ASSUME IT IS FIRST)
;NEXT LINE WAS [BP].ENVIRO NOT DS:.ENVIRO
	MOV	AX,DS:[2CH]	;DOS 2.0 MANUAL P.E-8 ff GIVES THIS AS ADDRESS
				;OF COMSPEC STUFF.
	MOV	DS,AX
;ES:BX IS ADDRESS OF EXEC BLOCK. SAVE ENVIRONMENT SEG ADDRESS THERE.
	MOV	ES:[BX],AX	;SAVE ADDRESS OF ENV TOO...
	XOR	DX,DX		;ENSURE DX STARTS AT 0...IN CASE BYTE OP NEXT
	MOV	DX,8H		;PASS THE "COMSPEC=" STRING
	MOV	AH,4BH	;EXEC DOS 2.0 CALL
	MOV	AL,0
	INT	21H	;CALL MSDOS 2.0 TO DO THE FUNCTION
;NOW CLEAN UP & RETURN
;FIRST GET BACK STACK FROM LOCAL STORAGE HERE IN CS.
	MOV	SS,CS:SSSAVE
	MOV	SP,CS:SPSAVE
	POP	ES
	POP	DS
	POP	BP
	POP	DI
	POP	SI
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	JC	ERR1
	RET
ERR1:	JMP	ERROR
ERROR:  RET ;JUST IGNORE ERRORS... TOO BAD BUT CAN'T REALLY HELP IT
SPSAVE	DW      0
SSSAVE	DW      0
	EVEN
	ENDM
	PUBLIC	EXECIT
EXECIT	PROC	FAR
	PUSH	BP
	MOV	BP,SP		;GET FRAME POINTER
;
; global locations cause trouble...
; have to get at them as 32 bit addresses...
;
	MOV	AX,CESXQQ	;SAVED INITIAL ES...
	MOV	ES,AX		;SET UP OUR ES AS ON ENTRY
	MOV	BX,ENDMQQ	;GET NEW LENGTH
	MOV	AH,4AH		;LOAD SETBLOCK FUNCTION
	INT	21H		;CALL DOS
;NOW MUST SET UP PARAMETER STRING.
; FORMAT IS:
; BYTE 	LENGTH OF STRING (NOT INCL CR)
; BYTES PARAMETER STRING (E.G. /C DISKCOPY A: B:)
; BYTE 0DH	CARRIAGE RETURN
; NOTE NEED ASCIZ STORAGE OF THIS
; ENVIRONMENT IS AT HEX 2C OFF ORIGINAL ES
; THEN MEXECOMM CALLED
; (ARRANGE FOR CALLER TO NULL LAST BYTE...)
	LES	BX,DWORD PTR [BP+6]	;ARGUMENT IS ADDRESS OF
				; STRING TO EXEC
	MOV	EXECBLK.COMMND[0],BX
	MOV	EXECBLK.COMMND[2],ES	;SAVE ADDRESS OF CMD ASRG

	MOV	AX,CESXQQ	;SAVED INITIAL ES...
	MOV	ES,AX		;SET UP OUR ES AS ON ENTRY
; MACRO NOW SAVES ALL REGS AND DOES THE EXEC, THEN RETURNS
	CALL	XCALL		;DO THE EXEC...
	MOV	SP,BP
	POP	BP		;RETURN LOGIC FOR FORTRAN
	RET	04H		;POP OFF ARGS ON RETURN
;NOW DEFINE THE ROUTINE THAT DOES THE WORST OF THE WORK...
	EXECIT	ENDP
XCALL	PROC	NEAR
	MEXECOMM		;NOW EXEC THE CMD LINE
	XCALL	ENDP
	CODE	ENDS
END


