
	SECTION	PCQStart,CODE

*	PCQStart.asm (of PCQ Pascal runtime library)
*	Copyright (c) 1989 Patrick Quaid

*	This is the startup and shutdown code for the programs.
*	Note that a few changes have got to take place here before PCQ
*	programs can be run from the WorkBench.

	XREF	_AbsExecBase
	XREF	_LVOOpenLibrary
	XREF	_LVOCloseLibrary
	XREF	_LVOFindTask
	XREF	_LVOWaitPort
	XREF	_LVOGetMsg
	XREF	_LVOReplyMsg
	XREF	_LVOForbid

	XREF	_LVOInput
	XREF	_LVOOutput
	XREF	_LVOIsInteractive

	XREF	_LVOFreeRemember

	XREF	newkey
	XREF	filekey
	XREF	_StdInName
	XREF	_StdOutName

	XREF	_p%FillBuffer
	XREF	_p%FlushBuffer
	XREF	_p%Close
	XREF	_p%Open

	XDEF	_CommandLine
	XDEF	_p%DOSBase
	XDEF	_p%IntuitionBase
	XDEF	_p%MathBase
	XDEF	_p%WorkBenchMsg
	XDEF	_p%IOResult
	XDEF	_Input
	XDEF	_Output
	XDEF	_ExitProc
	XDEF	_ExitCode
	XDEF	_ExitAddr
	
	INCLUDE	":runtime/FileRec.i"

;	Define entry point

	xdef	_p%initialize
_p%initialize

;	Save stack pointer for exit() routine

	move.l	sp,StkPtr	; save stack pointer
	add.l	#4,StkPtr	; account for this jsr to get to original

;	Save the command line pointer to CommandLine

	move.l	a0,_CommandLine
	move.b	#0,0(a0,d0.w)	; null terminate it

;	Check for WB or CLI

	move.l	_AbsExecBase,a6
	suba.l	a1,a1
	jsr	_LVOFindTask(a6)
	move.l	d0,a4

;	are we running from a CLI?

	tst.l	172(a4)			; 172 = pr_CLI
	bne	fromCLI

	lea	92(a4),a0		; 92 = pr_MsgPort
	jsr	_LVOWaitPort(a6)
	lea	92(a4),a0
	jsr	_LVOGetMsg(a6)
	move.l	d0,_p%WorkBenchMsg	; save the WB message

	bra	openLibs		; do the rest of the startup


fromCLI:

;	clear the Workbench message

	move.l	#0,_p%WorkBenchMsg

;	Open libraries

openLibs:
	lea	intuitionname,a1
	moveq	#0,d0
	move.l	_AbsExecBase,a6
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,_p%IntuitionBase
	beq	_p%exit

	lea	dosname,a1
	moveq	#0,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,_p%DOSBase
	beq	_p%exit

	lea	mathname,a1
	clr	d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,_p%MathBase
	beq	_p%exit

;	Find standard file handles

	tst.l	_p%WorkBenchMsg		; run from the Workbench?
	beq	OpenFiles		; if not, open standard stuff

	move.l	_StdInName,d0		; get input name
	beq.s	OpenStdOut		; if Nil, skip this
	move.l	d0,-(sp)		; save the name
	lea	_Input,a0		; get address of file record
	move.l	#80,MAX(a0)		; set buffer size = 80
	move.l	a0,-(sp)		; push the address
	jsr	_p%Open			; open the file
	addq.l	#8,sp			; fix the stack
	tst.b	d0			; did it go OK?
	bne.s	1$			; if so, skip the following
	move.l	#53,d0			; set runtime error
	jsr	_p%exit			; quit the program
1$	lea	_Input,a0		; retrieve the file record
	tst.b	INTERACTIVE(a0)		; is it interactive
	beq.s	OpenStdOut		; Open a new file
	move.l	_StdInName,d0		; get input name
	cmp.l	_StdOutName,d0		; are the names equal?
	bne.s	OpenStdOut		; if not, skip this
	move.l	HANDLE(a0),d0		; get the file handle
	lea	_Output,a0		; get the output file
	move.l	d0,HANDLE(a0)		; use the same handle for output
	move.b	#-1,INTERACTIVE(a0)	; set interactive to true
	rts				; and get back to main
OpenStdOut
	move.l	_StdOutName,d0		; get output name
	beq	1$			; if nil, leave
	move.l	d0,-(sp)		; push the output file name
	move.l	#_Output,-(sp)		; push the file record
	jsr	_p%Open			; open the file
	addq.l	#8,sp			; fix the stack
	tst.b	d0			; did it work?
	bne.s	1$			; if so, skip the following
	move.l	#57,d0			; set runtime error
	jsr	_p%exit			; and leave
1$	rts				; go back to main program
OpenFiles
	move.l	_p%DOSBase,a6
	jsr	_LVOInput(a6)		; get standard in
	move.l	#_Input,a0		; get input file record
	move.l	d0,HANDLE(a0)		; set handle
	beq	_p%exit			; if zero, quit
	move.l	d0,d1			; set up for next call
	jsr	_LVOIsInteractive(a6)	; is it interactive?
	move.l	#_Input,a0		; get file record again
	move.b	d0,INTERACTIVE(a0)	; set flag
	beq.s	StdInNotInteractive	; skip this if not interactive
	move.l	BUFFER(a0),a1		; get buffer address
	adda.l	#1,a1			; make end one byte further on
	move.l	a1,MAX(a0)		; set buffer size
	move.l	a1,CURRENT(a0)		; will need a read
	bra	OpenStdOutput
StdInNotInteractive
	jsr	_p%FillBuffer		; fill the buffer
OpenStdOutput
	jsr	_LVOOutput(a6)		; get ouput file handle
	move.l	#_Output,a0		; get file record
	move.l	d0,HANDLE(a0)		; set value
	beq	_p%exit			; if zero, quit
	move.l	d0,d1			; set up for call
	jsr	_LVOIsInteractive(a6)	; is it interactive?
	move.l	#_Output,a0		; get file record
	move.b	d0,INTERACTIVE(a0)	; set flag

1$	rts

*	Close all the open files, free all new() memory

_p%CloseAndFree

	move.l	#_Output,a0	; write any pending output
	jsr	_p%FlushBuffer

1$	move.l	filekey,d0	; get the current file key
	beq.s	2$		; if it's empty, skip ahead
	move.l	d0,a0		; otherwise make the call
	jsr	_p%Close	; to close the file
	bra.s	1$		; and loop 'til file list is empty

2$	tst.l	newkey		; return all allocated memory
	beq.s	3$
	lea	newkey,a0	; set up for FreeRemember call
	moveq.l	#-1,d0		; really forget
	move.l	_p%IntuitionBase,a6	; get library base
	jsr	_LVOFreeRemember(a6)	; free it all

3$	rts				; and return to Exit

	XDEF	_p%ExitWithAddr
_p%ExitWithAddr
	move.l	(sp),_ExitAddr

*	Falls through to the following...

	XDEF	_p%exit
_p%exit
	move.l	d0,_ExitCode		; save the exit code
1$	move.l	_ExitProc,a0		; get the first exit proc
	move.l	a0,d0			; set the z flag
	beq.s	2$			; if empty, skip around
	move.l	#0,_ExitProc		; set it to null
	jsr	(a0)			; call the exit proc
	bra.s	1$			; loop for next ExitProc
2$
	move.l	_AbsExecBase,a6		; get Exec base
	move.l	_p%IntuitionBase,a1	; get Intuition library
	move.l	a1,d0			; to set flags
	beq.s	4$			; if it wasn't open, don't close
	jsr	_LVOCloseLibrary(a6)	; close Intuition
4$
	move.l	_p%DOSBase,a1		; get DOS library base
	move.l	a1,d0			; set flags
	beq.s	5$			; if it wasn't open, skip
	jsr	_LVOCloseLibrary(a6)	; close DOS
5$
	move.l	_p%MathBase,a1		; get Math base
	move.l	a1,d0			; was it open?
	beq.s	6$			; if not, skip
	jsr	_LVOCloseLibrary(a6)	; close it
6$
	tst.l	_p%WorkBenchMsg		; were we run from Workbench
	beq	7$			; No.  Skip this

	jsr	_LVOForbid(a6)		; so we won't be unloaded too soon
	move.l	_p%WorkBenchMsg,a1	; get our message
	jsr	_LVOReplyMsg(a6)	; return the WB message
7$
	move.l	_ExitCode,d0		; get the DOS return code
	move.l	StkPtr,sp		; get the original stack pos
	rts				; lay down and die...

	XDEF	_IOResult
_IOResult
	move.l	_p%IOResult,d0
	move.l	#0,_p%IOResult
	rts

	SECTION	TWO,DATA

dosname		dc.b	'dos.library',0
intuitionname	dc.b	'intuition.library',0
mathname	dc.b	'mathffp.library',0
	CNOP	0,2

_p%DOSBase	dc.l	0
_p%IntuitionBase dc.l	0
_p%MathBase	dc.l	0
_p%WorkBenchMsg	dc.l	0
_p%IOResult	dc.l	0

_Input		dc.l	0	; Handle
		dc.l	0	; Next
		dc.l	InBuff	; Buffer
		dc.l	InBuff	; Current
		dc.l	InBuff	; Last
		dc.l	InBuff+80	; Max
		dc.l	1	; RecSize
		dc.b	0	; Interactive
		dc.b	0	; EOF
		dc.w	1005	; ModeOldFile

_Output		dc.l	0	; Handle
		dc.l	0	; Next
		dc.l	OutBuff	; Buffer
		dc.l	OutBuff	; Current
		dc.l	OutBuff	; Last
		dc.l	OutBuff+80	; Max
		dc.l	1	; RecSize
		dc.b	0	; Interactive
		dc.b	0	; EOF
		dc.w	1006	; ModeNewFile

_CommandLine	dc.l	0
_ExitProc	dc.l	_p%CloseAndFree
_ExitCode	dc.l	0
_ExitAddr	dc.l	0
_
StkPtr		dc.l	0

	SECTION	Buffers,BSS
InBuff		ds.b	80
OutBuff		ds.b	80
	END
