Google
 

Trailing-Edge - PDP-10 Archives - BB-FP64A-SB_1986 - 10,7/whycrs/dmpavl.mac
There are 4 other files named dmpavl.mac in the archive. Click here to see a list.
	TITLE	DMPAVL - Read AVAIL.SYS and dump entries
	SUBTTL	G.M. Uhler/GMU   22-Dec-82



;Copyright (C) 1980, 1981, 1982, 1983 by
;Digital Equipment Corporation, Maynard, Mass.
;
;
;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 which is not supplied by Digital.


	SEARCH	JOBDAT,MACTEN,SCNMAC,UUOSYM
	.REQUEST	REL:SCAN,REL:HELPER
	.DIRECTIVE .XTABM,FLBLST
	SALL


	DAVVER==1
	DAVMIN==0
	DAVEDT==1
	DAVWHO==0

	TWOSEG
	RELOC	400000
	LOC	.JBVER
	VRSN.	(DAV)
	RELOC



;Assembly and loading instructions
;
;	.R MACRO
;	*DMPAVL=DMPAVL
;	*^C
;	.R LINK
;	*DMPAVL,REL:SCAN,REL:HELPER/G
;AC definitions

	F==0			;Flags
	T1==1			;First of four temporaries
	T2==2
	T3==3
	T4==4
	P1==5			;First of four preserved registers
	P2==6
	P3==7
	P4==10
	N==P3			;SCAN convention
	C==P4			;SCAN convention
	P==17			;PDL pointer


;Parameter definitions

	.PDLEN==50		;Size of PDL
	BLKSIZ==200		;Size of a disk block
	DSK==1			;Input channel
	OUT==2			;Output channel
	WRKLEN==1200		;Number of words in working entry 


;Offsets in the header for ERROR.SYS

	.EHTYP==0		;Type, versions, lengths
	  EH.TYP==777B8		;Mask for type field
	  EH.CRS==1B16		;Entry extracted from CRASH.EXE
	  EH.FFM==7B20		;Mask for format version field
	    EL.FVR==0		;Format version of ERROR.SYS
	  EH.HFM==7B23		;Mask for header version field
	    EL.HVR==2		;Header version of ERROR.SYS
	  EH.HLN==7B26		;Mask for header length field
	    EL.HED==5		;Length of standard header
	  EH.BLN==777B35	;Mask for body length
	.EHDTM==1		;Universal date/time of entry
	.EHUPT==2		;Uptime of system when entry created
	.EHASN==3		;CPU serial number of cpu on which error was detected
	.EHSEQ==4		;Sequence number of entry
;Flag definitions

	FL.WTF==1B35		;Write this character to output file
	FL.HDR==1B34		;Header needed on next entry
	FL.ISC==1B33		;Input scan block allocated
	FL.OSC==1B32		;Output scan block allocated
	FL.SEP==1B31		;Separator needed between entries

;Macro definitions

	DEFINE	ERROR	(FIRST,LABEL),<
	  PUSHJ	P,ERRMSG
	  XLIST
	  IFNB <LABEL>, <CAIA [ASCIZ\?'FIRST'\]
			 JRST LABEL
			>
	  IFB  <LABEL>, <CAI  [ASCIZ\?'FIRST'\]>
	  LIST
	>


;Define the codes that we can process.  This should be all of the ones
; that appear in AVAIL.SYS.  If the output tells you about unknown header
; codes, somebody changed DAEMON without changing this table.
;
;The invocation of the PROCESS macro is as follows:
;
;	PROCESS header-code,processing routine,<descriptive-string>

DEFINE	PROCESS (CODE,RTN,NAME),<
	XWD	CODE,RTN
	XLIST
	[ASCIZ\NAME\]
	LIST
>

CODTAB:	PROCESS	.ESMRV,MRV,<Monitor run values: >
	PROCESS	.ESFER,FER,<Front-end reload: >
	PROCESS	.ESCSC,CSC,<Configuration status change: >
	PROCESS	.ESMSE,STC,<Continuable STOPCD: >
	PROCESS	.ESNDL,DLL,<Down-line load: >
	PROCESS	.ESNUD,DLL,<Up-line dump: >
	PROCESS	.ESBAV,BAV,<Beginning of file: >
	PROCESS	.ESEAV,BAV,<End of file: >
CODTBL==.-CODTAB
CODUHC==.-CODTAB
	PROCESS	0,UNK,<Unknown header code: > ;Unknown value
CODUHF==.-CODTAB
	PROCESS 0,UNKHF,<Unknown header format: >
DMPAVL:	JFCL			;No CCL entry
	RESET			;Clear the world
	MOVE	P,[IOWD .PDLEN,PDL] ;Setup push down list
	MOVEI	T1,DMPAVL	;Setup restart
	MOVEM	T1,.JBREN	; address
	MOVE	T1,.JBFF	;Get initial value of .JBFF
	MOVEM	T1,MINCOR	;Save for core downs
	MOVE	T1,[.ISCBL,,.ISCBK] ;Point to .ISCAN block
	PUSHJ	P,.ISCAN##	;Initialize SCAN
DAVSCN:	SETZM	Z.BGN		;First word to zero
	MOVE	T1,[Z.BGN,,Z.BGN+1] ;Setup BLT pointer
	BLT	T1,Z.END	;Clear it all
	SETOM	P.BGN		;Initialize /BEGIN,
	SETOM	P.END		; /END,
	SETOM	P.ENTRY		; and /ENTRY switch values
	SETZM	F		;No flags
	MOVE	T1,MINCOR	;Get min core needed
	MOVEM	T1,.JBFF	;Start of buffers
	CORE	T1,		;Reduce core to a minimum
	  JFCL			;Don't care
	MOVE	T1,[.TSCBL,,.TSCBK] ;Point to .TSCAN block
	PUSHJ	P,.TSCAN##	;Crack the command line
	PUSHJ	P,APLDFL	;Apply defaults
	  JRST	DAVSCN		;Error in command
	PUSHJ	P,OPNFIL	;Open input and output files
	  JRST	DAVSCN		;Failed
	SETCM	T1,P.BGN	;Get value of /BEGIN
	SKIPN	T1		;Value specified?
	SETOM	T1		;No, SETCAM will make this zero
	SETCAM	T1,P.BGN	;Save for checks
	SETCM	T1,P.END	;Get value of /END
	SKIPN	T1		;Value specified?
	MOVX	T1,1B0		;No, SETCAM will make this -1_-1
	SETCAM	T1,P.END	;Save for checks
	MOVE	T1,ILKBLK+.RBSIZ ;Get size of input file
	SUBI	T1,WRKLEN	;Minus size of working entry
	SKIPG	P1,T1		;If only working entry in file,
	JRST	DAVSCN		; quit now
	PUSH	P,.JBFF		;Save pointer to table
	ADDB	T1,.JBFF	;Add size of stuff we want to read
	CORE	T1,		;Get the core
	  ERROR	<Can't get core for AVAIL data>
	MOVE	P2,0(P)		;Pointer to first word of table
	USETI	DSK,<WRKLEN/BLKSIZ>+1 ;Set to read 1st block past working entry
RDLOOP:	INPUT	DSK,IOW		;Read next block
	STATZ	DSK,IO.ERR!IO.EOF ;Errors?
	ERROR	<IOERR or unexpected EOF on input file>
	MOVSI	T1,BUF+1	;Skip resync word in block
	HRRI	T1,(P2)		; and move to next slot in buffer
	BLT	T1,BLKSIZ-2(P2)	;Move it
	ADDI	P2,BLKSIZ-1	;Bump buffer pointer by len of entry
	SUBI	P1,BLKSIZ	;Done another 200 wds
	JUMPG	P1,RDLOOP	;Loop if more
	POP	P,P1		;P1=1st word of AVAIL data
	TXO	F,FL.WTF	;Write data to file now
PRLOOP:	MOVSI	T2,-CODTBL	;Get an AOBJN pointer to the code table
	LDB	T1,[POINTR .EHTYP(P1),EH.TYP] ;Get entry code
	CAIN	T1,.ESEOF	;EOF entry?
	  JRST	ENDIT		;Yes, go proces it
	LDB	T3,[POINTR .EHTYP(P1),EH.HFM] ;Get header format type
	CAILE	T3,EL.HVR	;Is it greater than what we know about?
	  JRST	[MOVEI	T2,CODUHF ;Get offset of unknown header format
		 HRRZ	T4,CODTAB(T2) ; and dispatch address
		 JRST	PRLOO2]	;Go process it
PRLOO1:	HLRZ	T3,CODTAB(T2)	;Get the next entry from the table
	HRRZ	T4,CODTAB(T2)	; and the dispatch address
	CAIN	T3,(T1)		;Is it a match?
	  JRST	PRLOO2		;Yes, go process it
	AOBJN	T2,.+1		;Step again
	AOBJN	T2,PRLOO1	;Loop for more
	MOVEI	T2,CODUHC	;Get offset for unknown code
	HRRZ	T4,CODTAB(T2)	;Get dispatch address for unknown code
PRLOO2:	PUSH	P,T4		;Save dispatch address
	JUMPGE	T2,PRLOO3	;If unknown code or format, always print it
	MOVE	T3,.EHDTM(P1)	;Get date/time of entry
	CAML	T3,P.BGN	;In range?
	 CAMLE	T3,P.END	; ...
	  JRST	[POP	P,(P)	;No, bring stack into phase
		 JRST	PRLOO4]	;  and go try next
	SKIPG	T3,P.ENTRY	;Was /ENTRY specified?
	  JRST	PRLOO3		;No, continue
	CAIE	T3,(T1)		;Match with this entry?
	  JRST	[POP	P,(P)	;No, bring stack into phase
		 JRST	PRLOO4]	;  and go try next
PRLOO3:	PUSHJ	P,PRHDR		;Print the common header code
	LDB	P2,[POINTR .EHTYP(P1),EH.HLN] ;Get length of header
	ADDI	P2,(P1)		;Compute address of start of body
	POP	P,T1		;Get back the dispatch address
	PUSHJ	P,(T1)		;Jump to it
PRLOO4:	LDB	T1,[POINTR .EHTYP(P1),EH.BLN] ;Get body length
	LDB	T2,[POINTR .EHTYP(P1),EH.HLN] ;  and header length
	ADDI	T1,(T2)		;Add together
	ADDI	P1,(T1)		; and step to next entry
	JRST	PRLOOP		;Go do another one
	SUBTTL	Beginning/end of AVAIL file (codes 46 and 47)


; Here to process the beginning and end of the AVAIL file entries.  Such
; entries contain only one word in the body.  This word contains the
; version number of DAEMON that made the entry.

	BAVVER==0		;Word containing the DAEMON version number

;Call with:
;	P1/Address of header
;	P2/Address of body
;Return CPOPJ always

BAV:	MOVEI	T1,[ASCIZ/Logged by DAEMON version /]
	PUSHJ	P,.TSTRG##	;Type string
	MOVE	T1,BAVVER(P2)	;Get daemon version number
	PUSHJ	P,.TVERW##	;Type it
	PJRST	.TCRLF##	;End the line and return
	SUBTTL	Configuration status change (code 15)


;Here to process a configuration status change entry.  All such entries
; contain a function code in the third word of thee body and function
; specific information in the first two words as follows:

	CSCWD0==0		;First function dependent word
	CSCWD1==1		;Second function depended word
	CSCFCN==2		;Function code
	  CS.FCN==77B17		;Mask for function code

;The following table defines the function codes that we know about.  The
; invocation of the PROCESS macro is as follows:
;
;	PROCESS function-code,processing-routine,<function-description>

CSCTAB:	PROCESS	.CSCAT,CSCATT,<Attach, Device: >
	PROCESS	.CSCDT,CSCATT,<Detatch, Device: >
	PROCESS	.CSCXC,CSCXCH,<Exchange, Device 1: >
	PROCESS	.CSCTC,CSCDTC,<Date/time change,
Current date/time: >
	PROCESS	.CSCNF,CSCNOL,<Node off-line, Node: >
	PROCESS	.CSCNO,CSCNOL,<Node on-line, Node: >
	PROCESS	.CSCMO,.TCRLF##,<Memory on-line>
	PROCESS	.CSCMF,.TCRLF##,<Memory off-line>
CSCTBL==.-CSCTAB
	PROCESS	0,CSCUNK,<Unknown function code: >
;Call with:
;	P1/Address of header
;	P2/Address of body
;Return CPOPJ always

CSC:	MOVSI	T2,-CSCTBL	;Get AOBJN pointer to table
CSCLP:	LDB	T1,[POINTR CSCFCN(P2),CS.FCN] ;Get function code
CSCLP1:	HLRZ	T3,CSCTAB(T2)	;Get the next entry from the table
	HRRZ	T4,CSCTAB(T2)	; and the dispatch address
	CAIN	T3,(T1)		;Is it a match?
	  JRST	CSCLP2		;Yes, go process it
	AOBJN	T2,.+1		;Step once
	AOBJN	T2,CSCLP1	;Loop for more
	HRRZ	T4,CSCTAB(T2)	;Get dispatch address for unknown code
CSCLP2:	PUSH	P,T4		;Save dispatch address
	MOVE	T1,CSCTAB+1(T2)	;Get address of descriptor 
	PUSHJ	P,.TSTRG##	;Type descriptor string
	POPJ	P,		;Dispatch to processing routine

;Here to process ATTACH and DETACH functions. CSCWD0 contains the SIXBIT
; unit name.

CSCATT:	MOVE	T1,CSCWD0(P2)	;Get SIXBIT name
	PUSHJ	P,.TSIXN##	;Type it
	PJRST	.TCRLF##	;End the line and return

;Here to process the XCHNGE function.  CSCWD0 and CSCWD1 contain the
; two SIXBIT unit names

CSCXCH:	MOVE	T1,CSCWD0(P2)	;Get first unit name
	PUSHJ	P,.TSIXN##	;Type it
	MOVEI	T1,[ASCIZ/, Device 2: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,CSCWD1(P2)	;Get second unit name
	PUSHJ	P,.TSIXN##	;Type it
	PJRST	.TCRLF##	;End the line and return

;Here to process the date/time change function.  CSCWD0  contains the
; incremental change.  CSCWD1 contains the current date/time.

CSCDTC:	MOVE	T1,CSCWD1(P2)	;Get current date/time
	PUSHJ	P,.TDTTM##	;Type it
	MOVEI	T1,[ASCIZ/, incremental change: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,CSCWD0(P2)	;Get increment
	PUSHJ	P,.TXWDW##	;Type it
	PJRST	.TCRLF##	;End the line and return
;Here to process the node on-line and off-line functions.  CSCWD0 contains
; the node number.

CSCNOL:	MOVE	T1,CSCWD0(P2)	;Get the node number
	PUSHJ	P,.TOCTW##	;Type it
	PJRST	.TCRLF##	;End the line and return

; Here to process an unknown function code.

CSCUNK:	LDB	T1,[POINTR CSCFCN(P2),CS.FCN] ;Get function code back
	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/
Body word 0: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,CSCWD0(P2)	;Get first word
	PUSHJ	P,.TXWDW##	;Type it
	MOVEI	T1,[ASCIZ/, Body word 1: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,CSCWD1(P2)	;Get second word
	PUSHJ	P,.TXWDW##	;Type it
	MOVEI	T1,[ASCIZ/, Body word 2: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,CSCFCN(P2)	;Get third word
	PUSHJ	P,.TXWDW##	;Type it
	PJRST	.TCRLF##	;End the line and return
	SUBTTL	Down-line load and up-line dump (codes 202 and 203)


;Here to process the down-line load and up-line dump entries.  Both entries
; have the same format, as follows:

	DLLTND==0		;Pointer to target node
	DLLSND==1		;Pointer to server node
	DLLSLN==2		;Server line number
	DLLFIL==3		;Pointer to filespec
	DLLRTN==4		;Return code
	DLLPRG==5		;Pointer to program filespec

;Call with:
;	P1/Address of header
;	P2/Address of body
;Return CPOPJ always

DLL:	HRRZ	T1,DLLSLN(P2)	;Get pointer to server line number string
	ADDI	T1,(P2)		;Relocate it
	PUSHJ	P,.TSTRG##	;Type it
	MOVEI	T1,[ASCIZ/
File: /]
	PUSHJ	P,.TSTRG##	;Type separator
	HRRZ	T1,DLLFIL(P2)	;Get pointer to filespec
	ADDI	T1,(P2)		;Relocate it
	PUSHJ	P,.TSTRG##	;Type it
	MOVEI	T1,[ASCIZ/
Program: /]
	PUSHJ	P,.TSTRG##	;Type separator
	HRRZ	T1,DLLPRG(P2)	;Get pointer to program name
	ADDI	T1,(P2)		;Relocate it
	PUSHJ	P,.TSTRG##	;Type it
	MOVEI	T1,[ASCIZ/
Server node: /]
	PUSHJ	P,.TSTRG##	;Type separator
	HRRZ	T1,DLLSND(P2)	;Get pointer to server node
	ADDI	T1,(P2)		;Relocate it
	PUSHJ	P,.TSTRG##	;Type it
	MOVEI	T1,[ASCIZ/,  Return code: /]
	PUSHJ	P,.TSTRG##	;Type separator
	HRRZ	T1,DLLRTN(P2)	;Get return code
	PUSHJ	P,.TXWDW##	;Type it
	PJRST	.TCRLF##	;End the line and return
	SUBTTL	Front-end reload (code 31)


;Here to process the front-end reload entry.  The entry has the following
; format:
;
	FERCDN==0		;CPU, DTE number
	  FE.MAS==1B0		;Master DTE
	  FE.CPU==377777B17	;CPU number
	  FE.DTE==777777	;DTE number
	FERRLD==1		;Reload status
	FERFIL==2		;Filespec pointer
	FERSIZ==3		;Size of filespec string in bytes

;Call with:
;	P1/Address of header
;	P2/Address of body
;Return CPOPJ always

FER:	MOVEI	T1,[ASCIZ/CPU: /]
	PUSHJ	P,.TSTRG##	;Type string
	LDB	T1,[POINTR FERCDN(P2),FE.CPU] ;Get CPU number
	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/, DTE: /]
	PUSHJ	P,.TSTRG##	;Type separator
	LDB	T1,[POINTR FERCDN(P2),FE.DTE] ;Get DTE number
	PUSHJ	P,.TOCTW##	;Type it
	MOVE	T2,FERCDN(P2)	;Get word containing master DTE bit
	MOVEI	T1,[ASCIZ/ (master)/] ;and the string
	TXNE	T2,FE.MAS	;Is it the master DTE?
	  PUSHJ	P,.TSTRG##	;Yes
	MOVEI	T1,[ASCIZ/, Reload status: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,FERRLD(P2)	;Get reload status
	PUSHJ	P,.TXWDW##	;Type it
	SKIPN	FERSIZ(P2)	;Some bytes in the filespec string?
	  PJRST	.TCRLF##	;No, end the line and return now
	MOVEI	T1,[ASCIZ/
File: /]
	PUSHJ	P,.TSTRG##	;Type separator
	PUSHJ	P,.SAVE2##	;Save P1 and P2
	HRRZ	P1,FERFIL(P2)	;Get pointer to filespec
	ADDI	P1,(P2)		;Relocate it
	HRLI	P1,(POINT 7,0)	;Make it a byte pointer
	MOVE	P2,FERSIZ(P2)	;Get number of bytes in the string
FER1:	ILDB	T1,P1		;Get the next byte
	PUSHJ	P,.TCHAR##	;Type it
	SOJG	P2,FER1		;Loop for more
	PUSHJ	P,.TSTRG##	;Type it
	PJRST	.TCRLF##	;End line and return
	SUBTTL	Monitor run values (code 44)


;Here to process the monitor run values entry.  Such entries have the
; following format:

	MRVPSN==0		;-Len,,Offset from MRVPSN to ASCIZ system name
	MRVVER==1		;Monitor version number
	MRVUPT==2		;Uptime in universal date/time format
	MRVCTM==3		;Monitor crash time (+/- 6 min) in universal date/time fmt
	MRVRTM==4		;Monitor reload time in universal date/time format
	MRVWHY==5		;Why reload code in SIXBIT
	MRVIDT==6		;Sum of all incremental date/time changes since reload
	MRVSNM==7		;First of 5 words of ASCIZ system name

;Call with:
;	P1/Address of header
;	P2/Address of body
;Return CPOPJ always

MRV:	HRRZ	T1,MRVPSN(P2)	;Get pointer to system name
	ADDI	T1,(P2)		;Relocate it
	PUSHJ	P,.TSTRG##	;Type it
	MOVEI	T1,[ASCIZ/,  Monitor version: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,MRVVER(P2)	;Get version number
	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/
Crash at: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,MRVCTM(P2)	;Get crash time
	PUSHJ	P,.TDTTM##	;Type it
	MOVEI	T1,[ASCIZ/,  Reload at: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,MRVRTM(P2)	;Get reload date/time
	PUSHJ	P,.TDTTM##	;Type it
	MOVEI	T1,[ASCIZ/,  Reason: /]
	PUSHJ	P,.TSTRG##	;Type separator
	HLRZ	T1,MRVWHY(P2)	;Get left half of reason
	CAIE	T1,'S..'	;Stopcd?
	 SKIPA	T1,MRVWHY(P2)	;No, get the entire thing
	  HRLZ	T1,MRVWHY(P2)	;Yes, keep just stopcd name
	PUSHJ	P,.TSIXN##	;Type it
	PJRST	.TCRLF##	;End the line and return
	SUBTTL	Continuable stopcd (code 2)


;Here to process the Continuable stopcd entry.  Such entries have the
; following format:

	STCFGO==0		;System name in ASCIZ (5 words)
	STCDT0==5		;System build date in ASCIZ (2 words)
	STCSER==7		;CPU serial number
	STCVER==10		;Monitor version
	STCSPC==11		;STOPCD name in SIXBIT (S..xxx)
	STCSJN==12		;Job number at last STOPCD
	STCSTN==13		;TTY number for job
	STCSPN==14		;Program name of job
	STCNAM==15		;Users PPN for job
	STCNJS==16		;Total number of job stopcds
	STCNDS==17		;Total number of debug stopcds

;Call with:
;	P1/Address of header
;	P2/Address of body
;Return CPOPJ always

STC:	MOVEI	T1,STCFGO(P2)	;Get pointer to system name
	PUSHJ	P,.TSTRG##	;Type it
	MOVEI	T1,[ASCIZ/,  Monitor version: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,STCVER(P2)	;Get version number
	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/
Reason: /]
	PUSHJ	P,.TSTRG##	;Type separator
	HLLZ	T1,STCSPC(P2)	;Get reason
	PUSHJ	P,.TSIXN##	;Type it
	MOVEI	T1,[ASCIZ/, CPU: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,STCSER(P2)	;Get CPU number
	PUSHJ	P,.TDECW##	;Type it
	MOVEI	T1,[ASCIZ/, Job: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,STCSJN(P2)	;Get job number
	PUSHJ	P,.TDECW##	;Type it
	MOVEI	T1,[ASCIZ/, /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,STCSTN(P2)	;Get TTY number
	PUSHJ	P,.TSIXN##	;Type it
	MOVEI	T1,[ASCIZ/, User: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,STCNAM(P2)	;Get PPN
	PUSHJ	P,.TPPNW##	;Type it
	MOVEI	T1,[ASCIZ/, Program: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,STCSPN(P2)	;Get program name
	PUSHJ	P,.TSIXN##	;Type it
	PJRST	.TCRLF##	;End the line and return
	SUBTTL	Unknown header codes and formats


; Here to process unknown header codes.  Dump them in octal.
;
; Call with:
;	P1/Address of header

UNK:	LDB	T1,[POINTR .EHTYP(P1),EH.TYP] ;Get header code
UNK1:	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/
Header in octal:
/]
	PUSHJ	P,.TSTRG##	;Type separator
	PUSHJ	P,.SAVE2##	;Save P1 and P2
	LDB	P2,[POINTR .EHTYP(P1),EH.HLN] ;Get length of header
	MOVNS	P2		;Make it negative
	HRLZS	P2		;Make it an AOBJN pointer
UNK2:	MOVEI	T1,[ASCIZ/
Wd /]
	PUSHJ	P,.TSTRG##	;Type separator
	HRRZ	T1,P2		;Get word number
	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/:	/]
	PUSHJ	P,.TSTRG##
	MOVEI	T1,(P2)		;Get offset into header
	ADDI	T1,(P1)		;Compute address
	MOVE	T1,(T1)		;Get next word of header
	PUSHJ	P,.TXWDW##	;Type it
	AOBJN	P2,UNK2		;Loop for all
	PJRST	.TCRLF##	;End the line and return
; Here to process unknown header formats.  Dump them in octal.
;
; Call with:
;	P1/Address of header

UNKHF:	LDB	T1,[POINTR .EHTYP(P1),EH.HFM] ;Get header format
	PJRST	UNK1		;Join common code above
	SUBTTL	Subroutines


;Routine to print the interesting stuff in the header for this entry.
;Call with:
;	T2/Address of table entry for this code
;	P1/Address of header
;Return CPOPJ always

PRHDR:	PUSH	P,T2		;Save address of table containing string
	MOVEI	T1,[ASCIZ/-----/]
	TXOE	F,FL.SEP	;Need separator between entries?
	PUSHJ	P,.TSTRG##	;Type separator
	MOVEI	T1,[ASCIZ/
[Code: /]
	PUSHJ	P,.TSTRG##	;Type start of message
	LDB	T1,[POINTR .EHTYP(P1),EH.TYP] ;Get code
	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/, Hdr ver: /]
	PUSHJ	P,.TSTRG##	;Type separator
	LDB	T1,[POINTR .EHTYP(P1),EH.HFM] ;Get header version number
	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/, Hdr len: /]
	PUSHJ	P,.TSTRG##	;Type separator
	LDB	T1,[POINTR .EHTYP(P1),EH.HLN] ;Get header length
	PUSHJ	P,.TDECW##	;Type it
	MOVEI	T1,[ASCIZ/., Body len: /]
	PUSHJ	P,.TSTRG##	;Type separator
	LDB	T1,[POINTR .EHTYP(P1),EH.BLN] ;Get body length
	PUSHJ	P,.TDECW##	;Type it
	MOVEI	T1,[ASCIZ/., Addr: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,P1		;Get address of header
	PUSHJ	P,.TOCTW##	;Type it
	MOVEI	T1,[ASCIZ/]
[Logged at: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,.EHDTM(P1)	;Get date/time of entry
	PUSHJ	P,.TDTTM##	;Type it
	MOVEI	T1,[ASCIZ/, by CPU: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,.EHASN(P1)	;Get CPU serial number
	PUSHJ	P,.TDECW##	;Type it
	LDB	T1,[POINTR .EHTYP(P1),EH.HFM] ;Get header format back
	LDB	T2,[POINTR .EHTYP(P1),EH.HLN] ;  and header length
	CAIL	T1,2		;If version less than 2
	CAIGE	T2,5		;  or length less than 5
	JRST	PRHDR1		;then there is no sequence number
	MOVEI	T1,[ASCIZ/, Hdr seq num: /]
	PUSHJ	P,.TSTRG##	;Type separator
	MOVE	T1,.EHSEQ(P1)	;Get sequence number
	PUSHJ	P,.TDECW##	;Type it
	MOVEI	T1,"."		;Get a dot
	PUSHJ	P,.TCHAR##	;Type it
PRHDR1:	MOVEI	T1,[ASCIZ/]

/]
	PUSHJ	P,.TSTRG##	;Type separator
	POP	P,T1		;Get address of table back
	MOVE	T1,CODTAB+1(T1)	;Get address of descriptor string
	PJRST	.TSTRG##	;Type it and return




ENDIT:	PUSHJ	P,.TCRLF##	;End the line
	RELEASE	OUT,		;Close output
	RELEASE	DSK,		;Close input
	JRST	DAVSCN		;and try next command
;Subroutine to convert the SCAN blocks to OPEN, LOOKUP and
;ENTER blocks and then open the appropriate files.
;Call:
;	PUSHJ	P,OPNFIL
;	  Return here if something failed
;	Return here if all ok

OPNFIL:	MOVEI	T1,ISCBLK	;Point to input scan block
	MOVEI	T2,IOPBLK	;Point to OPEN block
	MOVEI	T3,ILKBLK	;Point to LOOKUP block
	PUSHJ	P,.STOPN##	;Convert SCAN block
	  ERROR	<Input SCAN block conversion failed>,.POPJ##
	MOVX	T1,.IODMP	;Dump mode for input file
	DPB	T1,[POINTR IOPBLK,IO.MOD] ;Store it
	MOVX	T1,.RBSIZ	;Get size of lookup block
	MOVEM	T1,ILKBLK+.RBCNT ;Store it
	OPEN	DSK,IOPBLK	;Open the channel
	  ERROR	<Input device OPEN failed>,.POPJ##
	LOOKUP	DSK,ILKBLK	;Lookup the file
	  ERROR	<Input file LOOKUP failed>,.POPJ##
	MOVEI	T1,OSCBLK	;Point to output scan block
	MOVEI	T2,OOPBLK	;Point to output OPEN block
	MOVEI	T3,OENBLK	;Point to output ENTER block
	PUSHJ	P,.STOPN##	;Convert SCAN block
	  ERROR	<Output SCAN block conversion failed>,.POPJ##
	MOVX	T1,.IOASC	;Use ASCII mode for output file
	DPB	T1,[POINTR OOPBLK,IO.MOD] ;Store it
	MOVSI	T1,OBUF		;Output buffer header
	MOVEM	T1,OOPBLK+.OPBUF ;Store it
	MOVX	T1,.RBSIZ	;Get size of ENTER block
	MOVEM	T1,OENBLK+.RBCNT ;Store it
	OPEN	OUT,OOPBLK	;Open channel
	  ERROR	<Output device OPEN failed>,.POPJ##
	ENTER	OUT,OENBLK	;Enter file
	  ERROR	<Output file ENTER failed>,.POPJ##
	JRST	.POPJ1##	;Give skip return


;Subroutine to print an error message.
;Call:
;	PUSHJ	P,ERRMSG
;	CAI	[ASCIZ\msg to print\]
;	 Return here always

ERRMSG:	HRRZ	T1,@0(P)	;Get message address
	PUSHJ	P,.TSTRG##	;Type it
	PUSHJ	P,.TCRLF##	;Add a CRLF
	JRST	.POPJ1##	;Give skip return
;Subroutine to write one character to the output file or TTY.
;Call with character in T1 and with FL.WTF set to write to the
;output file
;Call:
;	PUSHJ	P,TYPCHR
;	Return here always

TYPCHR:	TXNN	F,FL.WTF	;Write to file?
	JRST	TYPCH1		;No, TTY
	SOSG	OBUF+.BFCTR	;Room for more?
	OUTPUT	OUT,		;No, flush
	IDPB	T1,OBUF+.BFPTR	;Store in buffer
	POPJ	P,		;Return
TYPCH1:	OUTCHR	T1		;Write it to TTY
	POPJ	P,		;Return


;Subroutine to return the address of the input scan block
;Call:
;	PUSHJ	P,ALCINP
;	 Return here always with:
;		T1=Address of scan block
;		T2=Length of scan block

ALCINP:	TXOE	F,FL.ISC	;Already been here once?
	  ERROR	<Multiple input specs illegal>,DAVSCN
	MOVEI	T1,ISCBLK	;Point at scan block
	MOVX	T2,.FXLEN	; and length
	POPJ	P,


;Subroutine to return the address of the output scan block
;Call:
;	PUSHJ	P,ALCOUT
;	 Return here always with:
;		T1=Address of scan block
;		T2=Length of scan block

ALCOUT:	TXOE	F,FL.OSC	;Already been here once?
	  ERROR	<Multiple output specs illegal>,DAVSCN
	MOVEI	T1,OSCBLK	;Point at scan block
	MOVX	T2,.FXLEN	; and length
	POPJ	P,
;Subroutine to check input and output scan blocks and apply any
;defaults that the user did not type.
;Call:
;	PUSHJ	P,APLDFL
;	  Return here if error
;	Return here if ok

APLDFL:	MOVX	T1,FX.NDV	;Get null device bit
	TDNN	T1,OSCBLK+.FXMOD ;User type a device?
	SKIPN	OSCBLK+.FXDEV	;  or nothing at all?
	SKIPA	T2,[SIXBIT/TTY/] ;Default output device is TTY
	JRST	APLDF1		;Use his device
	MOVEM	T2,OSCBLK+.FXDEV ;Store default device in block
	ANDCAM	T1,OSCBLK+.FXMOD ;Clear bit
	ANDCAM	T1,OSCBLK+.FXMOM ;  and mask
APLDF1:	SETCM	T1,OSCBLK+.FXNMM ;Get mask for filename
	JUMPE	T1,APLDF2	;Go if no wildcards
	AOSN	T1		;Error if wildcards
	SKIPE	OSCBLK+.FXNAM	;...
	JRST	APLOER
	MOVE	T1,[SIXBIT/DMPAVL/] ;Default filename is DMPAVL
	MOVEM	T1,OSCBLK+.FXNAM ;Store it
	SETOM	OSCBLK+.FXNMM	;Set full mask
APLDF2:	HRRZ	T1,OSCBLK+.FXEXT ;Get mask for extension
	CAIN	T1,777777	;Full mask?
	JRST	APLDF3		;Yes, use his extension
	SKIPE	OSCBLK+.FXEXT	;Error if wildcards
	JRST	APLOER		;...
	HRLOI	T1,'LST'	;Default extension is LST
	MOVEM	T1,OSCBLK+.FXEXT ;Store it
APLDF3:	MOVEI	T1,OSCBLK	;Point to output scan block
	PUSHJ	P,CHKDIR	;Check for wildcards in directory
APLOER:	  ERROR	<Wildcards illegal in output spec>,.POPJ##
	MOVX	T1,FX.NDV	;Get null device bit
	TDNN	T1,ISCBLK+.FXMOD ;User type a device?
	SKIPN	ISCBLK+.FXDEV	;Or nothing at all?
	SKIPA	T2,[SIXBIT/SYS/] ;Default input device is SYS
	JRST	APLDF4		;Use his
	MOVEM	T2,ISCBLK+.FXDEV ;Store device
	ANDCAM	T1,ISCBLK+.FXMOD ;Clear bit
	ANDCAM	T1,ISCBLK+.FXMOM ;  and mask
APLDF4:	SETCM	T1,ISCBLK+.FXNMM ;Get mask for filename
	JUMPE	T1,APLDF5	;Go if fully specified
	AOSN	T1		;Error if wildcards
	SKIPE	ISCBLK+.FXNAM	;...
	JRST	APLIER		;...
	MOVE	T1,[SIXBIT/AVAIL/] ;Default filename is AVAIL
	MOVEM	T1,ISCBLK+.FXNAM ;Store it
	SETOM	ISCBLK+.FXNMM	;Set full mask
APLDF5:	HRRZ	T1,ISCBLK+.FXEXT ;Get mask for extension
	CAIN	T1,777777	;Full mask?
	JRST	APLDF6		;Yes, use his extension
	SKIPE	ISCBLK+.FXEXT	;Error if wildcards
	JRST	APLIER		;...
	HRLOI	T1,'SYS'	;Default extension is SYS
	MOVEM	T1,ISCBLK+.FXEXT ;Store it
APLDF6:	MOVEI	T1,ISCBLK	;Point to input scan block
	PUSHJ	P,CHKDIR	;Check for wildcards in directory
APLIER:   ERROR	<Wildcards illegal in input spec>,.POPJ##
	JRST	.POPJ1##	;Give skip return
;Subroutine to check the directory specified in a scan block for
;wildcards.
;Call:
;	MOVEI	T1,address of scan block
;	PUSHJ	P,CHKDIR
;	 Return here is wildcard found
;	Return here if no wildcards

CHKDIR:	MOVX	T2,FX.DIR	;Get directory specified bit
	TDNN	T2,.FXMOD(T1)	;[-]??
	JRST	.POPJ1##	;Yes
	SETCM	T2,.FXDIM(T1)	;Get mask for PPN
	JUMPN	T2,.POPJ##	;Error if wildcards
	MOVEI	T1,.FXDIR+2(T1)	;Point to first SFD
	HRLI	T1,-<.FXLND-1>	;Make it an AOBJN pointer
CHKDI1:	SKIPN	(T1)		;End of list?
	JRST	.POPJ1##	;Yes, give skip return
	SETCM	T2,1(T1)	;Get mask for next word of directory
	JUMPN	T2,.POPJ##	;Error if wildcards
	ADDI	T1,1		;Step to next word
	AOBJN	T1,CHKDI1	;Loop for all
	JRST	.POPJ1##	;Give good return
;High segment data areas

	DEFINE	SWTCHS,<
	  XLIST
	  SP	BEGIN,P.BGN,.SWDTP##,,FS.VRQ
	  SP	END,P.END,.SWDTP##,,FS.VRQ
	  SP	ENTRY,P.ENTRY,.SWOCT##,,FS.VRQ
	  LIST
	>

	DOSCAN	(DAVSW)		;Generate scan tables


.ISCBK:	IOWD	1,[SIXBIT/DMPAVL/] ;Name is DMPAVL
	EXP	0
	EXP	TYPCHR		;Character typer address
.ISCBL==.-.ISCBK

.TSCBK:	IOWD	DAVSWL,DAVSWN
	XWD	DAVSWD,DAVSWM
	XWD	0,DAVSWP
	EXP	-1
	EXP	0
	XWD	ALCINP,ALCOUT
.TSCBL==.-.TSCBK


;Low segment data areas

	RELOC

MINCOR:	BLOCK	1		;Initial size of program
PDL:	BLOCK	.PDLEN		;Push down list
IOW:	IOWD	BLKSIZ,BUF	;IOWD for buffer
	EXP	0		;Terminator

Z.BGN==.			;Start of block to zero on startup
ISCBLK:	BLOCK	.FXLEN		;Input SCAN block
OSCBLK:	BLOCK	.FXLEN		;Output SCAN block
IOPBLK:	BLOCK	.OPBUF+1	;Input OPEN block
OOPBLK:	BLOCK	.OPBUF+1	;Output OPEN block
ILKBLK:	BLOCK	.RBSIZ+1	;Input LOOKUP block
OENBLK:	BLOCK	.RBSIZ+1	;Output ENTER block
P.BGN:	BLOCK	1		;Value of /BEGIN switch
P.END:	BLOCK	1		;Value of /END switch
P.ENTRY:BLOCK	1		;Value of /ENTRY switch
TOTAL:	BLOCK	1		;Total number of reloads
PRIME:	BLOCK	1		;Total number during prime-time
OBUF:	BLOCK	.BFCTR+1	;Output buffer header
BUF:	BLOCK	BLKSIZ		;Buffer for input file
Z.END==.-1			;End of area to zero


	END	DMPAVL