	.title	exit	Exit from C programs
	.ident	/000008/
 	.list	meb,bex
;
;+
;
; Index		Normal exit from C programs
; Index		Exit with status code
; Index		$$exst -- Exit status code
;
; Usage
;
;	exit(status);		/* Exit, no return	*/
;
;	exits(status);		/* Exit with status	*/
;
;	$$fail();		/* Immediate exit	*/
;
;	extern int $$exst;	/* Exit status value	*/
;
; Internal
;
;	jmp	$$exit		;Call exit routine
;
; Description
;
;	On exit, the following sequence occurs:
;	  1.	The user-supplied wrapup() function is called.
;	  2.	User-supplied finalizers are called.
;	  3.	Profiles (if requested) are printed.
;	  4.	All files are closed.
;	  5.	The program exits to the operating system.
;
;	By calling exits() with an appropriate value, the program can
;	pass an exit status code to the operating system monitor.
;	The RT11 and RSX11 monitors define exit status codes differently;
;	the value passed to exits() is not checked for consistancy.
;
;	  RT11	RSX	Meaning
;	    1.	 1.	IO_SUCCESS -- no message is printed
;	    2.	 0.	IO_WARNING -- minor error
;	    4.	 2.	IO_ERROR   -- serious error
;	    8.	 4.	IO_FATAL   -- severe error
;
;	Calling exit() with some other value is equivalent to
;	calling exits(IO_SUCCESS).  This is compatible with
;	Unix programs that exit by calling exit() without parameters.
;
;	Note that the program may also set a value into $$exst
;	and exit via exit():
;
;		extern int $$exst;
;
;		...
;
;		$$exst = IO_WARNING;
;		exit();
;
;	If the program calls, or jumps to, $$fail, it will immediately
;	exit to the operating system without closing files, calling
;	wrapup() or finalizers, or writing a profile file.
;
; Diagnostics
;
; Bugs
;
;-
;
; Edit history:
; 000001 22-May-80 MM	From scratch
; 000002 21-Jul-80 MM	Added exits()
; 000003 22-Jul-80 MM	Globalized $$exst
; 000004 24-Nov-81 SDR	Don't force line-feed on exit
; 000005 08-Feb-82 MM	Fixed edit 04 per SDR source.
; 000006 27-Jun-82 MM	New library
; 000007 04-Nov-82 MM	Psect fix
; 000008 22-Nov-82 JSL	Finalizer support; put code in the right psect!
;			(Based on a preliminary 19-Jul-82 version)
;
.iif	ndf	rsx	rsx	=	1	;Assume RSX11M
.if ne	rsx
	.mcall	exit$s, exst$s						;02
.iff
	.mcall	.print,	.exit						;02
USERRB	=	53		; User error code byte			;02
.endc

	.globl	wrapup							;08
	.psect	c$data
$$exst::
	.word	1	;Presuppose "normal" exit			;02/03
exitfl:	.byte	-2	;-1 during wrapup(), finalizers; 0 during library exit
	.even

;									;08+
; Stuff for finalizers - must declare all 3 psects!
;
	.psect	$finl
finl:				;Start of finalizer list
	.word	wrapup		;Treat wrapup() as the first finalizer
	.psect	$finl$		;The list itself
	.psect	$finl.
finle:				;End of the finalizer list
									;08-
	.psect	c$code							;07
exits::									;02
	mov	2(sp),$$exst	;Set exit code and exit		;02/03/06+
	br	$$exit		;
exit::
	mov	2(sp),r0	;User supplied parameter?
	bmi	$$exit		;Nope
	cmp	r0,#E$$XFA	;Bigger than IO_FATAL?
	bgt	$$exit		;Can't use it then.
	mov	r0,$$exst	;Set exit code			;06-

$$exit::
	incb	exitfl		;Are we exiting?
	beq	20$		;Br if here twice
	bpl	$$fail		;Br if here too often

;									;08+
; Call finalizers
;
; Warning:  The code here depends on two facts:
;		- There is always at least one finalizer (wrapup())
;		- This code cannot be entered except by flowing into it.  If
;	    either of these does not hold, it is necessary to add a branch
;	    over the call so that r2 can be tested against finle BEFORE it
;	    is used.
;
	mov	#finl,r2	;-> First finalizer
10$:
	call	@(r2)+		;Call the next one
	cmp	r2,#finle	;Any more?
	blo	10$		;Do them, too				;08-

20$:
	call	$$cl16		;Close all channels
;
; We call the profiler after closing files to make sure there's a
; free logical unit and buffer space
;
	call	@$$pptr		;Profiler
.if ne	rsx						;RSX11M
;
; Flush stderr, note: this depends on stderr not being in the lun table
;
	mov	stderr,-(sp)	;Force out any pending line		;04
	call	fflush		;to the user's terminal			;04/05
.endc

$$fail::			;Very hard exit

.if ne	rsx
	EXST$S	$$exst		;Return status code			;02/03
	EXIT$S			;Back to RSX (EXST$ not emulated)	;02
.iff
	bisb	$$exst,@#USERRB	;Stuff status code			;02/03
	clr	r0		;Hard exit
	.exit
.endc
	.end
