Google
 

Trailing-Edge - PDP-10 Archives - tops20-v7-ft-dist1-clock - 7-sources/sig.mac
There are 3 other files named sig.mac in the archive. Click here to see a list.
TITLE SIG -- Signalling facilities for the RTL

;
;	COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1984, 1986.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED  AND
;	COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH
;	THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE.   THIS  SOFTWARE  OR
;	ANY  OTHER  COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE
;	AVAILABLE TO ANY OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE
;	SOFTWARE IS HEREBY TRANSFERRED.
;
;	THE INFORMATION IN THIS SOFTWARE IS  SUBJECT  TO  CHANGE  WITHOUT
;	NOTICE  AND  SHOULD  NOT  BE CONSTRUED AS A COMMITMENT BY DIGITAL
;	EQUIPMENT CORPORATION.
;
;	DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR  RELIABILITY  OF
;	ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
;
SUBTTL Edit History

; Version 1.0

;.EDIT 5	Don't type to terminal from DYNBOO if detached.
;		Don't output from LDH if SG.OUT is 0
;		DDB,10-MAY-84,SPR:NONE
;.EDIT 7	Unwind trashes SG.ENS (ENSTK pointer)
;		DDB,31-MAY-84,SPR:NONE

SALL

SEARCH DYNSYM, DDBSYM, MONSYM, MACSYM

SEGMENT DATA

EXTERNAL ME$DLM, RTLCER, RTLERR
SUBTTL ENSTK -- The stack of established condition handlers

; SG.ENS holds an xFIW to the bottom of the last entry in use.
; The stack is empty when (SG.ENS)=ENSTK.
; Each entry on the stack is an establish block (.ES) as defined in
; DYNSYM.

; [7] ENSTK and its pointer SG.ENS must be in the same section as the RTL SG
; [7] routines;  Since they're all in this module, that shouldn't prove hard.

.ESSIZ==^D50			;Large stack, since overflow not checked for
ENSTK::	BLOCK .ESSIZ*.ESLEN
SG.ENS:: Z			;Must be master-initialized
SG.LER:: Z			;Address of last error chain

; Parameters that control last-ditch handler error printing
SG.OUT:: .PRIOU			;Output designator
SG.LEV:: .INFIN			;Number of levels of message to print (max)
SG.PFX:: IFIW SG.DPX		;xFIW address of prefix table (OWL/GBP to
				;ASCIZ strings) indexed by severity
SG.SFX:: IFIW SG.DSX		;xFIW address of suffix table (OWL/GBP to
				;ASCIZ strings) indexed by severity

; Control of asynchronous events -- if SG.NAS is set, DYNLIB won't enable for
; trapping or interrupts (trapping is enabled on call to DY$MIN).
; The main reason for setting this is for programs that run in section zero --
; a trap from section zero can't be handled by a normal non-zero-section
; trap handler because of the state of the stack.
SG.NAS:: 0			;By default, trapping is on

SEGMENT CODE

; Default prefix table
SG.DPX:: POINT 7, [ASCIZ /%/]	;Warning
	POINT 7, [ASCIZ /!/]	;Success
	POINT 7, [ASCIZ /?/]	;Error
	POINT 7, [ASCIZ /[/]	;Info
	POINT 7, [ASCIZ /??/]	;Severe error

; Default suffix table
SG.DSX:: POINT 7, [ASCIZ /
/]				;Warning
	POINT 7, [ASCIZ /! /]	;Success
	POINT 7, [ASCIZ /
/]				;Error
	POINT 7, [ASCIZ /]
/]				;Info
	POINT 7, [ASCIZ /
/]				;Severe error
SUBTTL SG$EST -- Establish a signal handler

; This routine must be called before any adjustments are made to the
; stack pointer by the calling routine.  For establishing a condition 
; handler for routines written in higher level languages where this
; condition cannot easily be met, set the condition handling flag in
; the library definition for that routine; this will result in generating
; a jacket definition for that routine which will perform the enable for it.

; This routine is part of the RTL, so is in the same section as SG.ENS.

; Call with the address of the establish block pushed onto the stack.
; It is removed before returning.  No registers are altered.

; This is hard to use from BLISS -- BLISS doesn't expect the argument
; it pushed to be removed from the stack by the routine called.

SEGMENT CODE

SG$EST::

	PUSH P, 2		;Make a register to work in
	MOVX 2, .ESLEN		;Amount of space to allocate on stack
	ADDB 2, SG.ENS		;Allocate the space
	POP P, .ESAC2(2)	;Put AC2 in its place
	DMOVEM 0, .ESAC0(2)	;Put AC0 and AC1 in their places
	DMOVE 0, [EXP -15, 20]	;Set up for backwards XBLT of 3-17
	EXTEND 0, [XBLT]	;Move registers 17-3
	; AC2 now points to .ESAC3, so adjust future references!!
	SOS .ESSP-.ESAC3(2)	;Decrement stack pointer to where it was before
	SOS .ESSP-.ESAC3(2)	;call to SG$EST
	POP P, 0		;Pop return address
	EXCH 0, 0(P)		;Swap it for the establish block address
	MOVEM 0, .ESHND-.ESAC3(2) ;Put in its final location
	DMOVE 0, .ESAC0-.ESAC3(2) ;Restore 0 and 1
	MOVE 2, .ESAC2-.ESAC3(2) ;Finally restore our work register
	RET
SUBTTL SG$LES -- Establish a signal handler from bliss

; This is a version of SG$EST to be called from within BLISS routines.
; This routine is for use by WIZARDS only!!  In particular, unwinding
; to a routine that enables for condition handling this way is almost
; certainly a mistake.

; Call with the address of the handler block in T1.

SEGMENT CODE

SG$LES::
	PUSH P, 2		;Make a register to work in
	MOVX 2, .ESLEN		;Amount of space to allocate on stack
	ADDB 2, SG.ENS		;Allocate the space
	POP P, .ESAC2(2)	;Put AC2 in its place
	MOVEM 1, .ESHND(2)	;Store handler block info
	MOVEM 0, .ESAC0(2)	;Put AC0 in place
	;Unwinding to this thing will give a strange AC1, better not matter!
	DMOVE 0, [EXP -15, 20]	;Set up for backwards XBLT of 3-17
	EXTEND 0, [XBLT]	;Move registers 17-3
	; AC2 now points to .ESAC3, so adjust future references!!
	SOS .ESSP-.ESAC3(2)	;Stack pointer to level before call to SIGBST
	DMOVE 0, .ESAC0-.ESAC3(2) ;Restore 0 and 1
	MOVE 2, .ESAC2-.ESAC3(2) ;Finally restore our work register
	RET
SUBTTL SG$REM -- Remove an established handler

; This routine must be called before leaving a routine which establishes
; a condition handler.

; Call with the address of the handler block pushed onto the stack.
; It is removed before returning.  No registers are altered.

; It is an error to remove a handler other than the most recently established
; one.

SG$REM::
	PUSH P, 2		;Make workspace
	MOVE 2, SG.ENS		;Get enable stack pointer
	MOVE 2, .ESHND(2)	;Get address of handler block
	CAME 2, -2(P)		;Compare handler block addresses
	    JRST REMLOS		;Not the same

	MOVX 2, -.ESLEN
	ADDM 2, SG.ENS		;Pop and discard the enable stack entry

	MOVE 2, -1(P)		;Get return address
	MOVEM 2, -2(P)		;Overwrite address of handler block
	POP P, 2		;Restore AC2
	ADJSP P, -1		;Bury corpse of argument
	RET			;Return to return address

; Come here if an attempt is made to remove a handler other than the
; most recently established one.

				;Stack shows ARG, RETADR, AC2
REMLOS:	MOVE T2, -2(P)		;Get our argument
	EXCH T2, -1(P)		;Stack shows ARG, ARG, AC2
	MOVEM T2, -2(P)		;Stack shows RETADR, ARG, AC2
	MOVX T2, <0,,1>
	EXCH T2, 0(P)		;Restore AC2 and push arg count
				;Stack shows RETADR, ARG, <0,,1>
	PUSH P, [SG$ROS]	;Stack shows RETADR, ARG, <0,,1>, SG$ROS
	JRST RTLERR
SUBTTL SG$LRM -- Remove an established handler, BLISS-callable

; This routine must be called before leaving a routine which establishes
; a condition handler.

; Call with the address of the handler block in T1.
; Registers 6-17 are preserved.

; It is an error to remove a handler other than the most recently established
; one.  This error is indicated by signalling SG$ROS.

SG$LRM::
	PUSH P, 2		;Make workspace
	MOVE 2, SG.ENS		;Get enable stack pointer
	MOVE 2, .ESHND(2)	;Get address of handler block
	CAME 2, 1		;Compare handler block addresses
	    JRST BEMLOS		;Not the same

	MOVX 2, -.ESLEN
	ADDM 2, SG.ENS		;Pop and discard the enable stack entry

	POP P, 2		;Restore AC2
	RET			;Return to return address

; Come here if an attempt is made to remove a handler other than the
; most recently established one.

				;Stack shows ARG, RETADR, AC2
BEMLOS:	MOVE T2, -2(P)		;Get ARG
	EXCH T2, -1(P)		;Stack shows ARG, ARG, AC2
	MOVEM T2, -2(P)		;Stack shows RETADR, ARG, AC2
	MOVX T2, <0,,1>		;Extras, arg count
	EXCH T2, 0(P)		;Restore AC2 and push counts
				;Stack shows RETADR, ARG, <0,,1>
	PUSH P, [SG$ROS]	;Stack shows RETADR, ARG, <0,,1>, SG$ROS
	JRST RTLERR
SUBTTL SG$SIG -- Initiate a software signal

; Look for a handler on the enable stack that wants to process the signal
; block specified.  If none found, call the last-ditch handler (ldh).

; Arguments:
;	1/	EFIW signal block

; Note that signalling can result in program termination or unwinding,
; in which case this routine will never return.

; Preserves all registers if it returns

; Register allocations:
; [7]	P1	Local index of establish block under consideration (in enstk)
;	P2	Address of signal block being signalled

SG$SIG::

; Save all registers
; This stuff is restored if we return.  If we unwind, stack is reset and
; we ignore all these values so carefully stored away.  Sob.
	PUSH P, 0
	PUSH P, 1
	PUSH P, 2
	ADJSP P, 14
	DMOVE 0, [EXP 14, 3]
	XMOVEI 2, -13(P)
	EXTEND 0, [XBLT]

	HRRZ P1, SG.ENS		;local index of where we are on ENSTK
	MOVE P2, -15(P)		;EFIW signal block (arg was saved along
				;with rest of registers)

; See if this level on ENSTK wants the problem
NALHAN:	CAIG P1, ENSTK		;Skip if P1 points to entry that exists
	    JRST SIGLDH		;No user handlers left, invoke the LDH

; Check if handler wants this signal
	MOVE T3, .SGCLS(P2)	;Get class from signal block
	MOVE T2, .ESHND(P1)	;Get address of handler block
	TDNN T3, .HNCLS(T2)	;Skip if this handler wants this signal
	    JRST NALNXH		;No luck, try next one

; This handler wants this signal
	MOVE T1, P2		;Pass EFIW signal block

; Preserve registers we depend on around the call
	PUSH P, P1
	PUSH P, P2
	CALL @.HNHND(T2)	;Call the handler
				;Handler returns new SG addresses in T1
				;  on .HNRES
				;Handler returns action code in T2
				;Resignal (same or different .SG block)
				;    Code .HNRES=0
				;Continue
				;    Code .HNCON=1
				;Unwind
				;    Code .HNUNW=2
	POP P, P2
	POP P, P1

	SKIPL T2		;Skip if code is negative (invalid)
	  CAILE T2, .HNUNW	;Skip if code less-or-equal to max (ok)
	    SETZ T2,		;Force invalid codes to be 0

	JRST @NALACT(T2)

NALACT:	IFIW NALRES
	IFIW NALCON
	IFIW NALUNW

; No luck so far, try next (earlier) handler
NALNXH:	SUBI P1, .ESLEN		;Step to previous handler
	JRST NALHAN		;Check it out
; Action routines for SG$SIG

; Resignal requested
; In this case the handler has changed the signal block address in T1 to point
; to his new block (if any).

NALRES:	MOVE T2, @T1		;Refer to new SG block address
	ERJMP .+2		;If the ref fails, don't update SG block adr!
	  MOVE P2, T1		;Potentially updated signal block address
	JRST NALNXH		;Keep looking

; Continue requested
NALCON:	;Restore registers saved on entry
	MOVX 0, 14
	XMOVEI 1, -13(P)
	MOVX 2, 3
	EXTEND 0, [XBLT]	;Restore 3-16
	DMOVE 0, -16(P)		;Restore 0 and 1
	MOVE 2, -14(P)		;Restore 2
	ADJSP P, -17		;And relinquish stack space

	RET			;Okay, continue

; Unwind requested
; T0 is value to return after unwind
; [7] P1 is pointer to the handler's ENSTK entry
NALUNW:	MOVEM T0, .ESAC0(P1)	;Store away value to be returned to caller
				;of establisher of current handler
	HRRZ P2, SG.ENS		;Local index of top of ENSTK

; Next handler to unwind
NAL001:	MOVE T2, .ESHND(P2)	;Get adr of handler block for this establish
	MOVE T0, .HNCLS(T2)	;Get enable mask for this handler
	TXNN T0, SG%UNW		;Does this handler care about unwinding?
	    JRST NALUNX		;No, loop
	XMOVEI T1, NALUWB	;Call with our static unwind block

; Preserve registers we depend on around call
	PUSH P, P1
	PUSH P, P2
	CALL @.HNHND(T2)	;Do closing cleanup
	; No value returned on unwind call
	POP P, P2
	POP P, P1

NALUNX:

; Here, do any magic cleanup (like clearing interrupts no longer needed?)
; in some future, more intelligent, version of this software.

; Loop
	HRRM P2, SG.ENS		;[7] Pop the establish block
	SUBI P2, .ESLEN		;Look at previous one
	CAML P2, P1		;Skip if we're back to the one that handled it
	    JRST NAL001		;Loop Loop Loop ... oops (Ha Ha only kidding)

; We're getting down to the grim and dirty, now...
; Our next mission, should we decide to accept it, is to restore registers 
; and stack pointer from the establish block, pop the establish block,
; and return the value specified to the caller of the establisher of the
; handler represented by the establish block now in P1.  Easy, huh?

	MOVX 0, 15
	XMOVEI 1, .ESAC3(P1)	;Start with AC3 of establish block
	MOVX 2, 3		;Restore to ACs!
	EXTEND 0, [XBLT]	;Restore 3-17
	; AC1 left pointing to .eshnd of the .es block used.  Very convenient!
	MOVE 0, .ESAC0(1)	;Restore AC0
	MOVE 2, .ESAC2(1)	;Restore AC2
	PUSH P, .ESAC1(1)	;Save it somewhere safe
	MOVX 1, <-.ESLEN>	;[7]
	ADDM 1, SG.ENS		;[7] Pop the establish block
	POP P, 1		;Finally restore AC1
	RET			;Return to establishers caller
				;[7] (Return value was placed over saved AC0
				;[7] on ENSTK, so it got properly set up on the
				;[7] restore above.)

; Static signal block passed during unwind
NALUWB:	$SGBLK (SG$UNW,0,"SIGNAL","UNWIND","SHOULD NEVER SEE THIS",0,SG%UNW)
SUBTTL SIGLDH -- The last-ditch condition handler

; This handler gets control whenever a signal is not handled (continue
; or unwind; resignalling doesn't count as handling) by any user handler.

; This is not enabled normally (say during master initialization) because
; that would cause all sorts of interrupts to be turned on, since this handler
; of course wants to see everything.  Instead, it's handled as a special
; case.  SG$SIG JRSTs to here if nobody else will help.

; (To continue, JRST to NALCON)

SIGLDH:
	MOVE T2, P2		;Address of signal block
	MOVE T1, SG.OUT		;Destination designator
	MOVE T3, SG.LEV		;Levels to go to
	XMOVEI T4, @SG.PFX	;Prefix table
	XMOVEI T5, @SG.SFX	;Suffix table
	CALL SG$PEM		;Print the error message

	LDB T1, [POINTR .SGCC(P2), SG%SEV] ;Fetch severity code
	JRST @LDHDIS(T1)

LDHDIS:	IFIW NALCON		;Warning
	IFIW NALCON		;Success
	IFIW LDHDIE		;Error
	IFIW NALCON		;Information
	IFIW LDHDIE		;Severe error
	IFIW LDHDIE		;Not used
	IFIW LDHDIE		;Not used
	IFIW LDHDIE		;Not used

LDHDIE:
	MOVE T1, SG.OUT		;Get output designator
	JUMPE T1, LDHHLT	;[5] Don't print to JFN of 0!!!
	MOVX T2, <POINT 7, [ASCIZ /?? Program terminating due to previous error
/]>
	SETZB T3, T4
	SOUT
	  ERJMP .+1		;No errors within errors
	
; Close the log file, if possible
	HRRZ T1, SG.OUT		;Get output designator
	CLOSF%
	    JFCL		;No errors within errors

LDHHLT:	HALTF%
	JRST LDHHLT		;Don't fall through!
SUBTTL SG$PEM -- Print error message

; Print an error message given a chain of signal blocks and some
; rules on how to print it.

; Arguments:
;	1/	Destination designator
;	2/	Address of signal block
;	3/	Number of levels to print to
;	4/	Address of prefix table
;	5/	Address of suffix table

; Prefix and suffix tables are vectors (indexed by severity) of addresses of
; ASCIZ prefix and suffix strings (respectively) to bracket each error message
; with.  "Addresses" means xFIW's here.

; Printed message resulting is:
;	<prefix><facility>-<severity>: <message><suffix>
; repeated as many times as necessary or allowed (see arg 3).

; Registers preserved: 6-17

; Stacklocal storage:
PEMLEV==-2			;Level left to print
PEMPFX==-1			;Prefix table address
PEMSFX==0			;Suffix table address
PEMTMP==3			;Space needed

SG$PEM::
	PUSH P, P1		;To hold signal block address
	MOVE P1, T2		;Starting location
	ADJSP P, PEMTMP		;Scratch-pad space
	MOVEM T3, PEMLEV(P)
	MOVEM T4, PEMPFX(P)
	MOVEM T5, PEMSFX(P)

; [5] If JFN to print to is 0, DON'T PRINT!!!!!
	JUMPE T1, PEMDON	;[5] Leave if JFN is 0

; You get a free CRLF before the first message only
	MOVX T2, <POINT 7, [ASCIZ /
/]>
	SETZB T3, T4		;Type ASCIZ string
	SOUT
	    ERJMP .+1

PEM001:
	MOVE T2, .SGFLG(P1)
	TXNE T2, SG%NPR		;Skip if noprint not selected
	    JRST PEMNXT		;Don't print this

; Prefix string
	LDB T3, [POINTR .SGCC(P1), SG%SEV] ;Get severity code
	ADD T3, PEMPFX(P)	;Index table by severity
	GETBP T2, 0(T3), T4
	SETZB T3, T4
	SOUT
	    ERJMP .+1		;No errors in error processing!!

; Facility name
	GETBP T2, .SGFAC(P1), T3
	SETZB T3, T4
	SOUT
	    ERJMP .+1

; Punctuation
	MOVX T2, "-"
	BOUT
	    ERJMP .+1

; Condition name
	GETBP T2, .SGCND(P1), T3
	SETZB T3, T4
	SOUT
	    ERJMP .+1

; Punctuation
	MOVX T2, <POINT 7, [ASCIZ /: /]>
	SOUT
	    ERJMP .+1

; Message
	GETBP T2, .SGMSG(P1), T3
	SETZB T3, T4
	SOUT
	    ERJMP .+1

; Suffix string
	LDB T3, [POINTR .SGCC(P1), SG%SEV] ;Get severity code
	ADD T3, PEMSFX(P)	;Index table by severity
	GETBP T2, 0(T3), T4
	SETZB T3, T4
	SOUT
	    ERJMP .+1		;No errors in error processing!!

; And now, the next message (if any)

PEMNXT:	SOSG PEMLEV(P)		;Skip if aren't at limit yet
	    JRST PEMEXI		;Done
	XMOVEI P1, @.SGNXT(P1)	;This word may contain IFIW
	SKIPE P1		;Skip if word was zero
	    JRST PEM001		;Go print next level
	;Must fall through to exit from here

PEMEXI:	MOVX T2, <-1,,[ASCIZ /
/]>
	SETZB T3, T4
	SOUT
	    ERJMP .+1

PEMDON:	ADJSP P, -PEMTMP	;[5]
	POP P, P1
	RET
SUBTTL SG$DLG -- Deallocate a signal block chain

; Given the first signal block in a chain, deallocate all of the blocks
; in that chain which have the dynamic bit set.

; Arguments:
;	1/	Address of signal block

; Preserves registers 6-17

SG$DLG::
	XMOVEI T0, @.SGNXT(T1)	;Save "NEXT" block address
	PUSH P, T0
	MOVE T0, .SGFLG(T1)	;Get flags for examination
	TXNN T0, SG%DYN		;Skip if dynamic
	  JRST DLGNXB		;Don't deallocate blocks that aren't dynamic!
	CALL ME$DLM		;Deallocate the block
	  ERJMP DLGERR		;Clean-up and pass on the error

DLGNXB:	POP P, T1		;Follow the chain
	JUMPN T1, SG$DLG	;0 means end of chain
	RET

DLGERR:	ADJSP P, -1		;Get rid of saved block address
	JRST RTLCER		;Continue the error upwards
SUBTTL SG$DMG -- Dump an SG chain

; Given the first signal block in a chain, dump the blocks to the tty.
; This is primarily intended as a debugging routine, and in particular
; should be callable from DDT.

; Arguments:
;	1/	Address of signal block

; Preserves registers 6-17

SG$DMG::
	PUSH P, P1
	MOVE P1, T1		;Save SG block address

	TMSG <
********** Dumping SIGNAL block 
>

DMGDMG:	TMSG <Block at >
	MOVE T2, P1
	CALL DMGOOH		;Dump as octal halfwords
DMGCC:	TMSG <
    .SGCC:  >
	MOVE T2, .SGCC(P1)
	CALL DMGOOH
	TMSG < [Facility = >
	LDB T2, [POINTR .SGCC(P1), SG%FAC]
	CALL DMGOOH
	TMSG < Message = >
	LDB T2, [POINTR .SGCC(P1), SG%MSG]
	CALL DMGOOH
	TMSG < Severity = >
	LDB T2, [POINTR .SGCC(P1), SG%SEV]
	CALL DMGOOH
DMGNXT:	TMSG <]
    .SGNXT: >
	MOVE T2, .SGNXT(P1)
	CALL DMGOOH
DMGFAC:	TMSG <
    .SGFAC: >
	XMOVEI T2, .SGFAC(P1)
	CALL DMGOBP
DMGCND:	TMSG <    .SGCND: >
	XMOVEI T2, .SGCND(P1)
	CALL DMGOBP
DMGMSG:	TMSG <    .SGMSG: >
	XMOVEI T2, .SGMSG(P1)
	CALL DMGOBP
DMGSPC:	TMSG <    .SGPC:  >
	MOVE T2, .SGPC(P1)
	CALL DMGOOH
DMGCLS:	TMSG <
    .SGCLS: >
	MOVE T2, .SGCLS(P1)
	CALL DMGOOH
	MOVE T4, .SGCLS(P1)
DMG007:	JFFO T4, DMG006
	  JRST DMGFLG
DMG006:	MOVE T1, DMGCLT(T5)	;Get appropriate decoding
	PSOUT
	MOVN T5, T5
	MOVX T1, 1B0
	LSH T1, (T5)
	ANDCAM T1, T4
	JRST DMG007

DMGFLG:	TMSG <
    .SGFLG: >
	MOVE T2, .SGFLG(P1)
	CALL DMGOOH
DMGDAT:	TMSG <
    .SGDAT: >
	MOVE T2, .SGDAT(P1)
	CALL DMGOOH
	JUMPE T2, DMG004	;No data to dump?
	XMOVEI T4, @.SGDAT(P1)	;Get address of count word
	MOVE T5, 0(T4)
	TMSG < Count = >
	MOVE T2, T5
	CALL DMGOOH
DMG005:	SOJLE T5, DMG004
	AOS T4
	TMSG <
        >
	MOVE T2, 0(T4)
	CALL DMGOOH
	JRST DMG005

; Follow NXT pointer (if it's not zero)
DMG004:	TMSG <
>
	XMOVEI P1, @.SGNXT(P1)
	HRRZ T1, P1		;In case pointer was IFIW 0 (stupid, but...)
	JUMPN T1, DMGDMG

DMGDON:	TMSG <
********** End of SIGNAL chain dump

>
	POP P, P1
	RET

; Dump a byte pointer, and show the string
; Enter with the Address of the byte pointer in T2
; This accepts OWL/GBP's
; Trashes t1, t3

DMGOBP:	PUSH P, T2		;Save the byte pointer as is
	LDB T2, [POINTR @0(P), BP%POS]
	CALL DMGOOH
	CAIGE T2, 45		;Skip if OWGBP
	  JRST DMG002		;Local byte pointer
	TMSG < >
	LDB T2, [POINTR @0(P), MASKB(6,35)]
	CALL DMGOOH
	JRST DMG003		;Go print the string
DMG002:	TMSG < >
	LDB T2, [POINTR @0(P), BP%SIZ]
	CALL DMGOOH
	TMSG < >
	LDB T2, [POINTR @0(P), BP%ADR]
	CALL DMGOOH
DMG003:	TMSG <
        {>
	GETBP T1, @0(P), T2
	PSOUT
	TMSG <}
>
	POP P, T2
	RET

; Dump a quantity as octal halfwords
; Enter with value in T2.  T1 and T3 are trashed

DMGOOH:	PUSH P, T2
	HLRZ T2, 0(P)		;Just left half
	JUMPE T2, DMG001	;Go print right half if left is zero
	MOVX T1, .PRIOU
	MOVX T3, <NO%MAG!FLD(^D8,NO%RDX)>
	NOUT%
	  ERJMP .+1		;No errors in debugging routines
	MOVX T1, ","
	PBOUT%
	PBOUT%
DMG001:	POP P, T2
	HRRZ T2, T2		;Just right half
	MOVX T1, .PRIOU
	MOVX T3, <NO%MAG!FLD(^D8,NO%RDX)>
	NOUT%
	  ERJMP .+1		;No errors in debugging routines

; Table for decoding class bits in signal
DMGCLT:	POINT 7, [ASCIZ / SG%UNW/]
	POINT 7, [ASCIZ / SG%APR/]
	POINT 7, [ASCIZ / SG%DER/]
	POINT 7, [ASCIZ / SG%QUO/]
	POINT 7, [ASCIZ / SG%EOF/]
	POINT 7, [ASCIZ / SG%ILI/]
	POINT 7, [ASCIZ / SG%ILR/]
	POINT 7, [ASCIZ / SG%ILW/]
	POINT 7, [ASCIZ / SG%INS/]
	POINT 7, [ASCIZ / SG%NXM/]
	POINT 7, [ASCIZ / SG%PDL/]
	POINT 7, [ASCIZ / SG%SOF/]
	POINT 7, [ASCIZ / SG%RES/]
	POINT 7, [ASCIZ / SG%CHR/]
	POINT 7, [ASCIZ / SG%TRM/]
	POINT 7, [ASCIZ / BIT 17/]
	POINT 7, [ASCIZ / BIT 18/]
	POINT 7, [ASCIZ / BIT 19/]
	POINT 7, [ASCIZ / BIT 20/]
	POINT 7, [ASCIZ / BIT 21/]
	POINT 7, [ASCIZ / BIT 22/]
	POINT 7, [ASCIZ / BIT 23/]
	POINT 7, [ASCIZ / BIT 24/]
	POINT 7, [ASCIZ / BIT 25/]
	POINT 7, [ASCIZ / BIT 26/]
	POINT 7, [ASCIZ / BIT 27/]
	POINT 7, [ASCIZ / BIT 28/]
	POINT 7, [ASCIZ / BIT 29/]
	POINT 7, [ASCIZ / BIT 30/]
	POINT 7, [ASCIZ / BIT 31/]
	POINT 7, [ASCIZ / BIT 32/]
	POINT 7, [ASCIZ / BIT 33/]
	POINT 7, [ASCIZ / BIT 34/]
	POINT 7, [ASCIZ / BIT 35/]

	RET
SUBTTL SG$NAS -- Enable / disable asynchronous events

; Passing a value to this routine is exactly equivalent to placing that
; value in galactic variable SG.NAS.  This routine exists because galactic
; variables are not available from section zero.

; Preserves registers 6-17.

; Arguments:
;	1/	Value to place in SG.NAS

SG$NAS::
	MOVEM T1, SG.NAS
	RET
SUBTTL Various routines specified but not yet implemented

SEGMENT CODE

SG$DIC::
SG$EIC::
SG$DLC::
SG$SEC::
SG$ALC::
	PUSH P, 0(P)		;Duplicate return address
	PUSH P, [1]		;Arg count
	PUSH P, [DY$NYI]	;Condition
	JRST RTLERR

IF2 <PURGE ..MX1, ..MX2, ..TX1, ..TX2, .AC1
>

	END