	.title	$$main	Start of C programs
	.ident	/000011/
;
;+
;
; Index		C main program
; Index		C library global variables
; Index		Operating-system unique variables
; Index		$$opsy -- Operating system id.
; Index		$$rsts -- Test if RSTS/E
; Index		$$vms -- Test if VMS emulation
; Index		$$pos -- Test if P/OS (Professional)
; Index		$$uic -- RSX-11M default UIC
; Index		$$stnd -- Stack end point
; Index		$$scca -- RT-11 Ctrl/C flag
; Index		$$task -- RSX-11M task name
; Index		$$tick -- Clock interrupt rate
;
; Usage
;
;	$$main::		/* Start of C programs	*/
;
;	extern int   $$opsy;	/* Operating system	*/
;	extern int   $$rsts;	/* Non-zero if RSTS/E	*/
;	extern int   $$vms;	/* Non-zero if VMS	*/
;	extern int   $$pos;	/* Non-zero if P/OS	*/
;	extern int   $$uic;	/* RSX: Default uic	*/
;	extern int   $$stnd;	/* Stack end point	*/
;	extern int   $$scca;	/* RT11: .scca control	*/
;	extern char  $$task[];	/* RSX: task name	*/
;	extern int   $$tick;	/* Clock interrupt rate	*/
;
; Internal
;
;	extern int   (*$$pptr)();  /* Profile printer	*/
;	extern int   $$argc;	/* Argument count	*/
;	extern int   *$$argv[];	/* Argument list ptr.	*/
;	extern char  *$$mtop;	/* Free memory start	*/
;	extern char  *$$mend;	/* Free memory end	*/
;
; Description
;
;	This module contains the run-time startoff for C programs.
;	It intializes the C environment and calls the main() subroutine.
;	On return from the main program, exit() is called to close
;	all files and return to the operating system.
;
;	The following globals are defined in this module:
;
;		$$opsy	Operating  system  unique  value.   This
;			value  is  7 on RT11, and set as per the
;			GTSK$ directive	on RSX-based systems:
;				RSX11-D		0.
;				RSX11-M		1.
;				RSX11-S		2.
;				IAS		3.
;				RSTS/E V7	4.
;				VMS		5.
;				RSX11-M+	6.
;				RT11		7.
;				P/OS		9.
;
;		$$rsts	This value is non-zero if the program is
;			running  on  RSTS/E.   It is zero if the
;			program  is  running  native  RSX, RT11,
;			P/OS or VMS compatibility mode.
;
;		$$vms	This value is non-zero if the program is
;			running  (in  compatibility mode) on Vax
;			VMS.  It  is  zero  if  the  program  is
;			running  native  RSX,  RT11,  P/OS or on
;			RSTS/E.
;
;		$$pos	This value is non-zero if the program is
;			running on the Professional P/OS.  It is
;			zero if the program  is  running  native
;			RSX, RT11, or on RSTS/E or VMS.
;
;		$$stnd	The (top) end of the stack on entrance.
;
;		$$scca	On RT11, the .scca control  word.   This
;			is  needed  to  allow RSTS/E programs to
;			trap end of file.
;
;		$$task	On RSX, the task name in Ascii.
;
;		$$tick	The clock interrupt rate.  This  is  set
;			at  initialization  on  RT11  and on the
;			first call to time() or ftime() on RSX.
;
;		$$uic	On RSX, the default UIC word from GTSK$.
;
; Internal
;
;	All $$ values are for internal communication among runtime
;	library routines.  I.e., let them alone.
;
; Diagnostics
;
;	On RSX, the task aborts with a BPT if the standard error file
;	did not open.  Otherwise, explanatory error messages are printed.
;
; Bugs
;
;-
;
; Run time startoff.
;
; Edit history:
; 000001 22-May-80 MM	Redone from scratch
; 000002 26-Jun-80 MM	Added wild card slot in erriov
; 000003 27-Jun-80 MM	Moved file stuff to iov.mac
; 000004 21-Jul-80 MM	Added $$tick
; 000005 29-Jul-80 MM	Added $$mtop, $$mfree
; 000006 10-Dec-80 MM	Added $$vms
; 000007 01-Mar-82 MM	$$tick on both systems now
; 000008 22-Jun-82 MM	No environment (for now)
; 000009 02-Jul-82 MM	Newer library
; 000010 19-Jul-82 MM	Added $$pos
; 000011 22-Nov-82 JSL	Added support for initializers (based on original
;			implementation on 2-Aug-82)

.iif	ndf	rsx	rsx	=	1
;
; NOTE:  This module may not depend on the value of C$$EIS
;
; $$main is the entrance to C programs.  CSV$ refers to this
; global to pull support.obj from the RSX library.  As main programs
; cannot be loaded from a library on RT11, suport.obj must
; be named explicitly on all RT11 link commands.
;
 

.if ne	rsx
;
; RSX-specific equivalences
;
MAXMCR	=	80.		;MCR command line size -- same as $$init
.endc

	.globl	$$init							;11
;
; Global data.
; The '$' symbols are for internal use.
; The '.' symbols are set by the loader.
;
	.psect	c$data
$$pptr::
	.word	.+2		;Ptr to profile printer
	return			;Just hop back
$$opsy::
	.word	7		;Gets op sys unique value
				;	RSX11-D		 0.
				;	RSX11-M		 1.
				;	RSX11-S		 2.
				;	IAS		 3.
				;	RSTS/E V7	 4.
				;	VMS		 5.
				;	RSX11-M+	 6.		;10
				;	RT11		 7.
				;	P/OS		 9.

$$rsts::
	.word	0		;Set non-zero on RSTS/E	
$$vms::									;06
	.word	0		;Set non-zero on VMS			;06
$$pos::
	.word	0		;Set non-zero on P/OS			;10
$$tick::								;07+
	.word	60.		;Set to 50 (on RT11) by $$init if
				;necessary.  Reset on calls to time()
				;and ftime() on RSX			;07-
$$stnd::
	.blkw	1		;High-point of stack
$$argc::
	.word	0		;Number of command args
$$argv::
	.word	0		;-> argv[]
$$mend::								;05+
	.word	0		; End of untouched memory
$$mlim::
	.limit			; Memory limits
$$mtop	==	$$mlim+2	; We need first byte unused		;05-


.if ne rsx
;
; RSX-specific global data.
;
$$uic::
	.blkw	1		;Task default uic from GTSK$

$$task::
	.ascii	"??????"	;Gets the task name
	.byte	0		;Null terminated.
.iff
;
; RT11-specific global data.
;

$$scca::
	.word	0		;Set non-zero if CTRL/C typed
.endc
	.even

;									;11+
; Stuff for initializers - must declare all three psects in order!
;
	.psect	$init
init:				;Start of initializer list
	.word	$$init		;$$init() is the first initializer
	.psect	$init$		;The list itself
	.psect	$init.
inite:				;End of the initializer list		;11-

	.psect	c$code
;
; Run time startoff.
; Called from the operating system
;

.if eq	rsx
	nop			;Dummy reenter address
.endc
$$main::
	mov	sp,$$stnd	;Save end of stack
	clr	r5		;No environment linkage yet
;									;11+
; Call $$init() to set up the state of the world, and then call the user's
; initializers.
;
; Warning:  The following code depends on two facts:
;		- There is always at least on initializer ($$init())
;		- This code cannot be entered except by flowing into it.
;	    If either of these may be false, a branch should be added to
;	    start the loop at the cmp, to ensure that r2 points to a valid
;	    address.
;
; Note:  You may wonder why main() isn't called in the initializer loop.
; The problem is the arguments that must be passed to main.  If we push
; them on the stack BEFORE the loop, they are incorrect, since $$argc and
; and $$argv are set up by $$init(), which is called in the loop.  So
; we'd have to push and pop them each time around the loop - which costs
; more than the separate call.  (Besides, $$init() is, logically, an ini-
; tializer; main() is not.)
;
	mov	#init,r2	;-> First initializer
10$:
	call	@(r2)+		;Call the next initializer
	cmp	r2,#inite	;Any more?
	blo	10$		;Do them, too
									;11-
	clr	-(sp)		;No environment				;08
	mov	$$argv,-(sp)	;Arg. vector
	mov	$$argc,-(sp)	;Arg. count
	call	main		;Off we go
	mov	#E$$XOK,-(sp)	;Normal exit				;09
	call	exit		;Normal exit				;09
	crash			;Can't happen				;09
	.end	$$main
