Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-02 - decus/20-0042/change.dec
There is 1 other file named change.dec in the archive. Click here to see a list.
TITLE			CHANGE********** CHARACTER SET CONVERTER **********
SUBTTL				*** WORDS OF WISDOM ***

















;********************************************************************
;*								    *
;*	NO FORCE, HOWEVER GREAT, CAN STRETCH A CORD, HOWEVER	    *
;*	FINE, INTO A HORIZONTAL LINE, WHICH SHALL BE ABSOLUTELY     *
;*	STRAIGHT...AND SO IS THE WAY OF AN EAGLE IN THE AIR; THE    *
;*	WAY OF A SERPENT UPON A ROCK; THE WAY OF A SHIP IN THE	    *
;*	MIDST OF THE SEA; AND THE WAY OF A MAN WITH A MAID...FOR    *
;*	HOWEVER BEAUTIFUL AND FREE, STILL IMPERFECT.... 	    *
;*								    *
;********************************************************************
SUBTTL				*** DEFINITIONS ***

;VERSION NUMBERS.

VEDIT==555
VWHO==1
VMINOR==0
VMAJOR==4

;	ASSEMBLER DIRECTIVES.

TWOSEG
SALL
EXTERNAL	.JBFF,.JBREL,.JBREN,.JBINT,.JBUUO,.JBSA
EXTERNAL	.JB41,.JBDDT,.JBTPC,.JBAPR,.JBCNI

;	ACCUMULATORS.

S=0					;BIT REGISTER.
OF=1					;USED FOR DEVICE STATUS.
IF=2					;USED FOR DEVICE STATUS.
T1=3					;TEMPORARY AC'S.
T2=4
T3=5
P1=6					;MAYBE YOU CAN DEPEND ON AC'S.
P2=7
P3=10
P4=11
OCNT=<SIDE=12>				;INDEX IN DECODER AND COUNTER.
ICNT=<WD=13>				;OUTPUT WORD AND COUNTER.
CH=14					;HOLDS A CHARACTER.
OM=15					;MODE INDEX.
IM=16					;MODE INDEX.
PDP=17					;PUSH-DOWN POINTER.
;	BITS SET BY COMMAND DECODER IN S.

COL==1					;SET BY CD IF COLON FOUND.
PER==2					;SET BY CD IF PERIOD FOUND.
SLH==4					;SET BY CD IF SLASH FOUND.
BRK==10					;SET BY CD IF BRACKET FOUND.
IO==20					;SET IF _ OR = FOUND BY CD.
EOL==40					;SET WHEN EOL FOUND.
SOM==100				;SET WITH ALL OF THE ABOVE.
DEV==200				;SAYS WE HAVE A DEVICE.
NUM==400				;SAYS WE HAVE PPN.
REL==1000				;SAYS WE HAVE REEL SERIAL NUMBER.
PAR==2000				;SET TO INDICATE WE HAVE PARITY.
MODE==4000				;SET TO INDICATE WE HAVE MODE.
BLK==10000				;SET TO INDICATE WE HAVE BLOCKING FACTOR.
ADV==20000				;SET TO INDICATE WE HAVE ADVANCE NUMBER.
ATS==40000				;SET BY CD WHEN "@" FOUND.
XBUF==100000				;SET TO INDICATE WE HAVE A BUFFER SWITCH.
ALT==200000				;AN ALTMODE WAS THE DELIMITER.
SPC==200000				;SET IT A CRLF IS NEEDED.
IOT==400000				;SET WHEN LOOKING AT INPUT SPECS.
DATA==1000000				;SAYS WE MAY HAVE A TABLE FILE NAME COMING.
DEN==2000000				;SAYS WE HAVE DENSITY.
LAB==4000000				;SET TO INDICATE WE HAVE LABEL TYPE.
BAD==10000000				;SET IF A BAD CHARACTER IS TYPED.
REC==20000000				;SAYS WE HAVE RECORD SIZE.
NODIS==40000000				;SAYS THERE IS NO DISPATCH TABLE.
FNDONE==100000000			;SAYS WE HAVE FOUND ONE MATCH.
FNDTWO==200000000			;SAYS WE FOUND MORE THEN ONE MATCH.
NOCHK==400000000			;DON'T CHECK INPUT CHARACTER.
STAR==1000000000			;WE HAVE SEEN A STAR ON INPUT.
BAC==2000000000				;WE HAVE BACKSPACE ARGUMENT.
NOSTAR==4000000000			;WE HAVE GOTTEN A NONE STAR ON INPUT.
;	INDEXES INTO CCL BLOCK.

CCLCHN==-1				;CCL CHANNEL NUMBER.
CCLSTS==0				;DEVICE STATUS WORD.
CCLDEV==1				;CCL DEVICE.
CCLBHD==2				;CCL BUFFER HEADER.
CCLNAM==3				;NAME OF CCL FILE.
CCLEXT==4				;EXT OF CCL FILE.
CCLDAT==5				;DATE TIME PROT WORD.
CCLPPN==6				;PPN OF ONWER.
CCLOPN==7				;OPEN MME.
CCLLOK==10				;LOOKUP MME.
CCLGET==11				;INPUT MME.
CCLREL==12				;RELEASE MME.
CCLBUF==13				;INBUF MME.
CCLHED==14				;BUFFER HEADER.

;	INDEXES INTO IMPURE DATA BLOCK.

CHAN==-1				;CHANNEL FILE IS OPEN ON.
STATUS==0				;STATUS BITS FOR OPEN.
DEVICE==1				;DEVICE FOR OPEN.
BUFFER==2				;POINTER TO POINTER TO BUFFERS.
NAME==3					;FILE NAME POSITION FOR LOOKUP.
EXT==4					;FILE EXTENSION POSITION.
DATTIM==5				;DATE TIME WORD.
PPN==6					;PPN WORD.
MOD==7					;MOD WORD FOR DATA BLOCK.
BLKFCT==10				;BLOCKING FACTOR.
RECSIZ==11				;RECORD SIZE.
ADVAN==12				;ADVANCE COUNT.
LABEL==13				;LABEL TYPE.
DENSITY==14				;MAG-TAPE DENSITY.
VOL==15					;CURRENT VOLUME FOR MAG-TAPE.
PERGE==16				;PERGE NUMBER FOR MAG-TAPE.
CHRMOD==17				;FILE MODE (CHARACTER SET).
SEC==20					;SECTORS FOR BLOCKING FACTOR.
BUFNUM==21				;NUMBER OF BUFFERS TO USE.
BACSPC==22				;BACKSPACE ARGUMENT.
NAMMSK==23				;MASK FOR FILE NAME.
EXTMSK==24				;MASK FOR EXTENSION.
THREE==<TWO==<ONE==<ZERO==0>+1>+1>+1	;INDEXES FOR RETURNS.
;	BITS SET IN IF OR OF.

NOWIND==1				;DO NOT REWIND DEVICE.
AWIND==10000				;DON'T REWIND AFTER OPERATION.
BWIND==20000				;DON'T REWIND BEFORE OPERATION.
UNLOAD==2				;UNLOAD DEVICE.
NOHEAD==4				;NO LINE PRINTER HEADINGS.
IND==10					;INITIALIZE IN INDUSTRY MODE.
NOERROR==20				;SET IF IGNORING ERRORS.
SPAN==40				;RECORDS CROSS BLOCKS.
WDEV==1000				;DEVICE IS WILD DISK (ALL STR).
WNAME==100				;WE HAVE A WILD NAME.
WEXT==200				;WE HAVE A WILD EXTENSION.
WP==2000				;PROJECT NUMBER IS WILD.
WPN==4000				;PROGRAM NUMBER IS WILD.
WILD==WDEV!WNAME!WEXT!WP!WPN		;SOMETHING IS WILD.
SCAN==400				;SAYS TO SCAN MTA FOR FILE.
NOCRLF==40000				;ASCII FILE HAS NO CRLF'S.
MTA==20000000				;DEVICE IS A MAG-TAPE.
DIR==4000000				;DEVICE HAS A DIRECTORY (DTA OR DSK).
DTA==100000000				;DEVICE IS A DECTAPE.
DSK==200000000000			;DEVICE IS A DISK.
CDR==100000000000			;DEVICE IS A CARD READER.
CDP==100000000000			;DEVICE IS A CARD PUNCH.
LPT==40000000000			;DEVICE IS A LINE PRINTER.
PTP==400000000				;DEVICE IS A TAPE PUNCH.
PTR==200000000				;DEVICE IS A TAPE READER.
TTY==10000000				;DEVICE IS A TTY.
IPT==2000000				;DEVICE CAN DO INPUT.
OTP==1000000				;DEVICE CAN DO OUTPUT.
GDEV==DTA!DSK!CDR!CDP!LPT!PTP!PTR!TTY!MTA;DEVICE CAN BE USED.

;	BITS SET IN S.

FF==1					;LAST CHARACTER WAS A FORM FEED.
EOR==2					;END OF RECORD HAS BEEN SEEN.
FREAD==4				;FIRST READ BIT.
LHEAD==10				;SAYS WE ARE DOING HEADINGS FOR LPT.
TERM==20				;END LABELS ARE NEXT.
FIN==40					;SET IF END OF REEL.
NO.ERR==100				;SET TO IGNORE OUTPUT ERRORS.
NI.ERR==200				;SET TO IGNORE INPUT ERRORS.
HDR==400				;SET TO DENOTE WORKING ON HEADERS.
HUNG==1000				;SET TO DENOTE DEVICE IS HUNG.
NO.PRI==2000				;DON'T TYPE HUNG MESSAGE.
PRG==4000				;SET TO INDICATE WE HAVE PERGED LABEL.
NI.LST==10000				;SET TO IGNORE IOBLK ERRORS.
FFLG==20000				;FIRST TIME FLAG.
BAC==40000				;SET TO SAY WE WANT THE SAME CHARACTER.
L.HDR==100000				;LABEL READ IS A HEADER.
L.EOF==200000				;LABEL READ IS A TRAILER.
L.EOV==400000				;LABEL READ IS END OF REEL.
;	BITS SET IN SOME KIND OF A STATUS WORD.

EVEN==1000				;PARITY BIT FOR EVEN.
ODD==0					;JUST FOR CLEARNESS.
SYNC==40				;STAY EVEN WITH DEVICE.
BIN==14					;DEVICE DATA MODE.
DMP==17					;DEVICE DATA MODE FOR DATA FILE.
ASC==0					;ASCII DATA MODE.
TRK7==4					;MTA IS A SEVEN TRACK DRIVE.
ER.IDV==1				;HUNG DEVICE TRAP.
ER.ICC==2				;CONTROL-C TRAP.
ER.OFL==4				;DISK OFF LINE TRAP.
ER.FUL==10				;DISK FULL TRAP.
ER.QEX==20				;QUOTA BEING EXCEEDED TRAP.
ER.TLX==40				;RUN TIME LIMIT EXCEEDED.
ER.ALL==ER.IDV!ER.ICC!ER.OFL!ER.FUL!ER.QEX!ER.TLX ;PROBLEM TRAPS.
E.LOK==400000				;DEVICE IS WRITE LOCKED.
E.HAD==200000				;HARDWARE FAILURE.
E.PAR==100000				;PARITY ERROR.
E.IOB==40000				;I/O BLOCK TOO LARGE.
E.EOF==20000				;END OF FILE.
E.BOT==4000				;WE ARE AT LOAD POINT.
E.EOT==2000				;END OF TAPE.
E.ERR==E.LOK!E.HAD!E.PAR!E.IOB		;ERROR BITS.
NOR==1000000				;MODE NEEDS INPUT RECORD SIZE.
NIR==2000000				;MODE NEEDS OUTPUT RECORD SIZE.
EXW==4000000				;MODE NEEDS EXTRA WORDS FOR BUFFER.
TAB==10000000				;SAYS CHARACTER SET HAS TABS.
GDSK==7000000				;DISK DEVICE IS GENERIC.

;	INDEXS INTO MODE TABLE.

INI==0					;INPUT DISPATCH.
OUTI==1					;OUTPUT INITIALIZATION.
OUTC==2					;PUT ONE CHARACTER.
OUTR==3					;FINISH OUTPUT RECORD.
OUTB==4					;FINISH OUTPUT BLOCK.
OUTF==5					;FINISH OUTPUT FILE.
MSIZ==6					;BYTE SIZE AND BYTES PER WORD.
MPTR==7					;BYTE POINTER FOR MODE.
FPTR==10				;POINTER TO DATA FILE ENTRY.
STS==11					;STATUS BITS FOR MODE.
CNAM==12				;CHARACTER SET NAME IN SIXBIT.

;	CPU FLAGS.

PDL==200000				;PDL OVERFLOW TRAP.
MPV==20000				;MEMORY PROTECTION VIOLATION.
NXM==10000				;NON-EXISTENT MEMORY.
REP==400000				;REPETITIVE ENABLE.
;	MASTER MODE SYMBOLS.

.CH==1					;OUTPUT A CHARACTER.
.DEV==4					;GET DEVICE CHARACTERISTICS.
.STR==3					;OUTPUT A STRING.
.LN==4					;INPUT A LINE AND WAIT.
.TERM==12				;TERMINATE EXECUTION.
.CORE==11				;AJUST CORE ALLOCATION.
.TIME==23				;GET TIME OF DAY.
.DATE==14				;GET THE DATE.
.RESET==0				;RESET I/O.
.CLR==11				;CLEAR INPUT BUFFER.
.TIM==27				;GET RUN TIME.
.NAM==64				;GET PHYSICAL NAME FOR DEVICE.
.SKP==14				;SKIP IF LINE CAN BE INPUTTED.
.SLP==31				;SLEEP FOR A WHILE.
.WAIT==72				;HIBERNATE FOR A WHILE.
.WAT==0					;WAIT FOR MAG-TAPE OPERATION.
.REW==1					;REWIND TO LOAD POINT.
.EOF==3					;WRITE EOF MARK.
.SKR==6					;SKIP A RECORD.
.BSR==7					;BACKSPACE RECORD.
.EOT==10				;SKIP TO LOGICAL END OF TAPE.
.UNL==11				;REWIND AND UNLOAD.
.BLK==13				;WRITE SOME BLANK TAPE.
.SKF==16				;SKIP A FILE.
.BSF==17				;BACKSPACE FILE.
.DEC==100				;INITIALIZE FOR DIGITAL TAPE.
.IND==101				;INITIALIZE FOR INDUSTRY TAPE.
.RUN==35				;RUN A PROGRAM.
.ENB==16				;ENABLE APR TRAPS.
.STS==54				;GET DEVICE CONI BITS.
.TAPE==112				;GET MAG-TAPE DENSITY.
.NODEL==40				;RETAIN OLD FILE.
.PPN==24				;GET MY PPN.
.PJOB==30				;GET MY JOB NUMBER.
.TAB==41				;GET A TABLE ENTRY.
.DCHR==45				;GET DEVICE CHARACTERISTICS.
.JLST==47				;READ MY SEARCH LIST.
.SLST==46				;READ SYSTEM STRUCTURES.
.GLST==66				;READ SOME LIST.
.ALST==46				;READ SYSTEM STRUCTURE LIST.
.ASC==1					;STRING IS ASCIZ IN UME CALL.
.SIX==2					;STRING IS ONE SIXBIT WORD.
.LTP==6					;GET TTY LINE STUFF.
.SIZ==101				;GET BUFFER SZE FOR DEVICE.
.IOSTP==10				;WAIT FOR I/O TO STOP.
.PATH==110				;READ SEARCH PATH.
;	USEFUL OPDEFS.

OPDEF	UME	[OCT 001000000000]	;USER MODE ENTRY.
OPDEF	MME	[OCT 047000000000]	;MASTER MODE ENTRY.
OPDEF	EME	[OCT 051000000000]	;EXECUTIVE MODE ENTRY.
OPDEF	GOTO	[OCT 254000000000]	;LOAD PC WITH E.
OPDEF	NOP	[OCT 255000000000]	;NO OPERATION.
OPDEF	DRIVE	[OCT 072000000000]	;MAG-TAPE OPERATOR.
OPDEF	GOSUB	[OCT 260740000000]	;SUBROUTINE CALL.
OPDEF	SAVE	[OCT 261740000000]	;SAVE A LOCATION.
OPDEF	UNSAVE	[OCT 262740000000]	;UNSAVE A LOCATION.
OPDEF	RET	[OCT 263740000000]	;RETURN TO STACK.

;	SOME MACROS.

DEFINE	RETURN	(LOC)
	<IFN LOC, <GOTO RET0-LOC>
	IFE LOC, <POPJ PDP,RET0>>

DEFINE	USE	(CORE,CONTENTS)
	<IFNB <CORE>, <IFB <CONTENTS>, <ZZ==0
		IFE "CODE"-"CORE", <ZZ==1
			IFGE .-400000, <RELOC .>
			IFL .-400000, <LOW==.
			RELOC HGH>>
		IFE "DATA"-"CORE", <ZZ==1
			IFL .-400000, <RELOC .>
			IFGE .-400000, <HGH==.
			RELOC LOW>>
	IFE ZZ, <PRINTX ? BAD CALL TO USE MACRO>>>
	IFNB <CORE>, <IFNB <CONTENTS>, <ZZ==.
			LOC	CORE
			EXP	CONTENTS
			RELOC	ZZ>>
	IFB <CORE>, <IFB <CONTENTS>, <PRINTX % NO ARGUMENT FOR USE MACRO>>
	PURGE ZZ>

DEFINE	FTABLE	(NUM)
	<RADIX 10
	IFE NUM, <EXP .YY.>
	IFG NUM, <.YY.==NUM/128
		IFN <NUM-<<NUM/128>*128>>, <.YY.==.YY.+1>
		.XX.==.YY.*128
		XWD -.XX.,.ZZ.+1
		.YY.==XWD -.XX.,.ZZ.+1
		.ZZ.=.ZZ.+<.XX./128>>
	IFL NUM, <RELOC .
		PURGE .XX.,.YY.
		.ZZ.==0>
	RADIX 8>
DEFINE	OP	(AC,FLG,MM)		;CREATE THE RIGHT TEST.
	<IFE FLG, <PRINTX % NO BIT ARGUMENT FOR OP MACRO>
	IFN FLG, <IFN FLG&777777, <IFN FLG&777777000000, <TD'MM AC,[FLG]>>
	IFE FLG&777777, <TL'MM AC,(FLG)>
	IFE FLG&777777000000, <TR'MM AC,FLG>>>

DEFINE	TEST	(AC,FLG,M1,M2,LOC)	;GENERATE A SKIP IF LOC IS NULL
	<IFB <LOC>, <OP AC,FLG,M1>	;ELSE GENERATE A JUMP TO LOC.
	IFNB <LOC>, <OP AC,FLG,M2
		XLIST
	GOTO	LOC
		LIST>>

DEFINE	ON	(AC,FLG)		;TURN SOME BITS ON.
	<OP	AC,FLG,O>

DEFINE	OFF	(AC,FLG)		;TURN SOME BITS OFF.
	<OP	AC,FLG,Z>

DEFINE	IF.ON	(AC,FLG,LOC)		;SKIP OR JUMP IF BITS ARE ON.
	<TEST	AC,FLG,NN,NE,LOC>

DEFINE	IF.OFF	(AC,FLG,LOC)		;SKIP OR JUMP IF BITS ARE OFF.
	<TEST	AC,FLG,NE,NN,LOC>

DEFINE	TNO	(AC,FLG,LOC)		;SKIP OR JUMP IF ON AND TURN ON.
	<TEST	AC,FLG,ON,OE,LOC>

DEFINE	TEO	(AC,FLG,LOC)		;SKIP OR JUMP IF OFF AND TURN ON.
	<TEST	AC,FLG,OE,ON,LOC>

DEFINE	TNZ	(AC,FLG,LOC)		;SKIP OR JUMP IF ON AND TURN OFF.
	<TEST	AC,FLG,ZN,ZE,LOC>

DEFINE	TEZ	(AC,FLG,LOC)		;SKIP OR JUMP IF OFF AND TURN OFF.
	<TEST	AC,FLG,ZE,ZN,LOC>

DEFINE	PRINT	(STRING)
	<EME	.STR,[ASCIZ  #STRING
#]>

DEFINE	BRANCH	(WHERE,LOC)
	<GOSUB	WHERE
		XLIST
	IRP (LOC), <GOTO LOC>
		LIST>
DEFINE	MTABLE	(TYP)
	<MODTAB: IRP (TYP), <EXP TYP'MOD
		XLIST>
		LIST>

DEFINE	TABLE	(NAM,TYP,SIZ,LEN,STS)
	<TYP'MOD: EXP	INI'TYP
		  XLIST
		  EXP	OTI'TYP
		  EXP	OTC'TYP
		  EXP	OTR'TYP
		  EXP	OTB'TYP
		  EXP	OTF'TYP
		  XWD	^D'SIZ,^D36/^D'SIZ
		  POINT SIZ,ZERO
		  FTABLE LEN
		  EXP	STS
		  <SIXBIT "NAM">
		  LIST>

DEFINE	BSS	(LOC,SIZE)
	<IFB <SIZE>, <BLOCK LOC>
	IFNB <SIZE>, <LOC: BLOCK SIZE>>

DEFINE	ENABLE	(ARG)
	<EME	.SKP,ZERO
		XLIST
	NOP	ZERO
		LIST>

DEFINE	DIARET
	<MOVEI	T1,.
	XLIST
	MOVEM	T1,DIAFLG
	LIST>

DEFINE	EQUATE	(VAL,SYM)
	<IRP (SYM), <SYM==VAL>>
DEFINE	CBLK	(CHAN,DEP)
	<XLIST
	ZZ==CHAN
	REPEAT	DEP,
	<YY==.
	EXP	ZZ
	BSS	TWO
	EXP	.+12
	BSS	4
	OPEN	ZZ,.-7
	LOOKUP	ZZ,.-5
	IN	ZZ,ZERO
	RELEASE	ZZ,ZERO
	INBUF	ZZ,ZERO
	BSS	THREE
	CCLCNT==.-YY
	ZZ==ZZ+1>
	PURGE	YY,ZZ
	LIST>

DEFINE	DEVOP	(OP,CHAN,LOC)
	<OFF	S,HUNG
		XLIST
	AOS	%IO
	OP	CHAN,LOC
		LIST>

;	THINGS WITH NO OTHER PLACE TO LIVE.

VERSION==0B2!5B11!1B17!'DRK'
HGH==400000				;FOR USE MACRO.
LOW==000000				;FOR USE MACRO.
NEC==400000				;SAYS CHARACTER CAN'T BE CONVERTED.
DTNAM==122				;NAME IN DTA DIRECTORY.
DTEXT==150				;EXTENSION IN DTA DIRECTORY.
CF==<HF==<DF==<MF==<UF==IF+1>+1>+1>+1>+1;CHANNEL DEFINITIONS.
IFNDEF CCLLEN, <CCLLEN==5>		;NUMBER OF NESTING IN CCL FILES.
IFNDEF TMPLEN, <TMPLEN==10>		;LENGTH OF TEMPORARY STACK.
IFNDEF PDPSIZ, <PDPSIZ==150>		;PUSH-DOWN LIST SIZE.
IFNDEF PATSIZ, <PATSIZ==100>		;SIZE OF PATCH AREA.
SUBTTL			*** IMPURE DATA AREA ***

	USE	DATA

;	DATA AREA FOR MOD WORDS AND FILE SPECIFICATIONS.

FSTMEM:	BSS	ONE			;WORD FOR CHANNEL NUMBER.
OFILE:	BSS	ONE			;STATUS BITS FOR OPEN.
	BSS	ONE			;DEVICE FOR OPEN.
	BSS	ONE			;POINTER IN OUTPUT BUFFER HEADERS.
	BSS	ONE			;FILE NAME.
	BSS	ONE			;FILE EXTENSION.
	BSS	ONE			;DATE TIME PROTECTION WORD.
	BSS	ONE			;PROJECT-PROGRAM NUMBER.
	BSS	ONE			;MOD WORD FOR OUTPUT DEVICE AND FILE.
	BSS	ONE			;BLOCKING FACTOR.
	BSS	ONE			;RECORD SIZE.
	BSS	ONE			;NUMBER OF FILES TO ADVANCE.
	BSS	ONE			;LABEL TYPE.
	BSS	ONE			;MAG-TAPE DENSITY.
	BSS	ONE			;VOLUME NUMBER.
	BSS	ONE			;NOT USED.
OUTMOD:	BSS	ONE			;OUTPUT CHARACTER SET INDEX.
OBLK:	BSS	ONE			;BLOCKS TO READ FOR BLKFCT.
	BSS	ONE			;NUMBER OF BUFFERS TO USE.
	BSS	ONE			;NUMBER OF FILES TO BACKSPACE.
	BSS	ONE			;WORD FOR CHANNEL NUMBER.
	BSS	TWO			;UNUSED.
IFILE:	BSS	ONE			;STATUS BITS FOR OPEN.
	BSS	ONE			;DEVICE FOR OPEN.
	BSS	ONE			;POINTER TO INPUT BUFFER HEADERS.
	BSS	ONE			;FILE NAME.
	BSS	ONE			;EXTENSION.
	BSS	ONE			;DATE TIME PROTECTION WORD.
	BSS	ONE			;PROJECT-PROGRAM NUMBER.
	BSS	ONE			;MOD WORD FOR INPUT SPECIFICATIONS.
	BSS	ONE			;BLOCKING FACTOR.
	BSS	ONE			;RECORD SIZE OR SIZE OF LARGEST BLOCK.
	BSS	ONE			;NUMBER OF FILES TO ADVANCE.
	BSS	ONE			;LABEL TYPE.
	BSS	ONE			;MAG-TAPE DENSITY.
	BSS	ONE			;VOLUME NUMBER FOR MAG-TAPE.
	BSS	ONE			;NEW REEL NUMBER AFTER PERGE.
INPMOD:	BSS	ONE			;INPUT CHARACTER SET INDEX.
IBLK:	BSS	ONE			;BLOCKS TO READ FOR BLKFCT.
	BSS	ONE			;NUMBER OF BUFFERS TO USE.
	BSS	ONE			;NUMBER OF FILES TO BACKSPACE.
	BSS	TWO			;MASK WORDS FOR WILD CARDS.
TELWRD:	BSS	ONE			;ZERO IT TALKING.
LSTWRD:	BSS	ONE			;NON-ZERO IF LISTING.
FSTWRD:	BSS	ONE			;NON-ZERO IF FAST LIST.
;BUFFERS AND SAVED LOCATIONS FOR THINGS.

BSS	INPBUF,^D21			;SAVE AREA FOR INPUT LABEL.
BSS	OUTBUF,^D21			;SAVE AREA FOR OUTPUT LABEL.
BSS	STACK,PDPSIZ			;PUSH-DOWN STACK.
BSS	OBUF,3				;OUTPUT BUFFER HEADER.
BSS	IBUF,3				;INPUT BUFFER HEADER.
BSS	OIBUF,3				;OUTPUT-INPUT BUFFER AREA.
BSS	BUFF,^D24			;OUTPUT-INPUT BUFFER.
BSS	ORCNT,ONE			;NUMBER OF RECORDS WRITTEN.
BSS	OBCNT,ONE			;NUMBER OF BLOCKS WRITTEN.
BSS	IRCNT,ONE			;NUMBER OF RECORDS READ.
BSS	IBCNT,ONE			;NUMBER OF BLOCKS READ.
BSS	NOCHR,ONE			;NUMBER OF BAD CHARACTERS.
BSS	RELNUM,ONE			;NUMBER OF MAG-TAPE REEL SET FROM LABEL.
BSS	%IO,ONE				;NUMBER OF DEVICE ACESSES.
BSS	%TIME,ONE			;RUN TIME.
BSS	IFCNT,ONE			;INPUT FILE COUNT.
BSS	OFCNT,ONE			;OUTPUT FILE COUNT.
BSS	INPERR,ONE			;INPUT PARITY ERRORS.
BSS	OTPERR,ONE			;OUTPUT PARITY ERRORS.
BSS	SPCCNT,ONE			;COUNT OF CHARACTERS TYPED DURING COMMAND.
BSS	ISEC,ONE			;NUMBER OF BLOCKS READ.
BSS	OSEC,ONE			;NUMBER OF BLOCKS WRITTEN.
BSS	TCH,ONE				;LAST CHARACTER READ.
BSS	TEMP,ONE			;REGISTER FOR TEMPORARY STORAGE.
BSS	TEMP1,ONE			;TEMPORARY REGISTER.
BSS	LSTDEV,ONE			;LAST DISK DEVICE USED.
BSS	SEARCH,ONE			;SAYS WE ARE SEARCHING.
BSS	SYSSRH,ONE			;SAYS WE ARE USING DEVICE SYS.
BSS	RUNFLG,ONE			;SAYS WE ARE DOING SOMETHING.
BSS	RECPTR,ONE			;POINTER TO ALTER BUFFER.
BSS	LSTPTR,ONE			;POINTER TO CTRL WORD.
BSS	CURPTR,ONE			;CURRENT POINTER TO ALTER BUFFER.

LSTMEM==.-1				;LAST IMPURE LOCATION TO CLEAR.
;STORAGE FOR THINGS THAT ARE RETAINED ACROSS RUNS.

BSS	AC,20				;SAVE AREA FOR THE AC'S.
BSS	DATE,ONE			;DATE OF CRASH.
BSS	TIME,ONE			;TIME OF CRASH.
BSS	PRGNAM,ONE			;PROGRAM NAME.
XWD	ZERO,STACK			;LOCATION OF THE STACK.
BSS	PC,ONE				;LOCATION OF CRASH.
BSS	SYSNAM,4			;SYSTEM NAME.
PATCH:	BSS	PAT,PATSIZ		;PATCH AREA.
BSS	LABSTR,ONE			;STRUCTURE FROM TAPE LABEL.
BSS	LABNAM,TWO			;LABEL NAME TO TYPE ON ERROR.
BSS	LABDTW,ONE			;DATE AND PROTECTION WORD.
BSS	LABPPN,ONE			;PPN WORD FROM LABEL.
BSS	LABSIZ,ONE			;SIZE OF FILE IN BLOCKS.
BSS	LABVOL,ONE			;VOLUME NUMBER READ FROM LABEL.
BSS	LABTOT,ONE			;TOTAL BLOCKS FOUND.
BSS	LABCNT,ONE			;TOTAL FILES FOUND.
BSS	PASS,TWO			;PASSWORD FOR GE LABELS.
BSS	RETWRD,ONE			;RETAIN WORD.
BSS	IJOBFF,ONE			;SAVE LOCATION FOR JOBFF.
BSS	OJOBFF,ONE			;SAVE LOCATION FOR JOBFF.
BSS	TRPBLK,TWO			;TRAP BLOCK FOR HUNG DEVICE.
BSS	TRPPC,ONE			;PC WORD AT TRAP.
BSS	TRPCHN,ONE			;CHANNEL THAT CAUSED TRAP.
BSS	LSTSTR,ONE			;LAST STRUCTURE USED IN LIST.
BSS	LSTPPN,ONE			;LAST PPN USED IN LIST.
BSS	CCLFLG,ONE			;NONE ZERO IF USING CCL FILE.
BSS	CCLCOR,ONE			;COPY OF JOBFF WHEN CCL FILE OPEN.
BSS	DIAFLG,ONE			;RETURN ADDRESS FOR ERRORS IN DIALOG MODE.
SUBTTL			*** PROGRAM START AND INITIALIZATION ***

;PROGRAM TO CONVERT BETWEEN CHARACTER SETS.

	USE	137,BYTE (3)VWHO(9)VMAJOR(6)VMINOR(18)VEDIT
	USE	CODE

START:	TDZA	PDP,PDP			;NORMAL START.
	SETOM	PDP			;CCL ENTRY.
	MOVEI	T2,THREE		;GETTAB TABLE.
	MME	T1,.PJOB		;MY JOB NUMBER.
	HRL	T2,T1			;XWD FOR GETTAB.
	MME	T2,.TAB			;GET MY NAME.
	MOVE	T2,[SIXBIT "CHANGE"]	;IF GETTAB FAILS.
	MOVEM	T2,PRGNAM		;SAVE MY NAME.
	MME	.RESET			;STOP THE WORLD.
	MOVEI	T1,NTHERE		;PICK UP REENTER ADDRESS.
	MOVEM	T1,.JBREN		;STORE IT IN PLACE.
	SETZM	RETWRD			;CLEAR RETAIN WORD.
	SETZM	DFFLG			;NO DATA FILE NOW.
	MOVE	T1,[GOSUB UME0]		;SET UP UME DISPATCH INSTRUCTION.
	MOVEM	T1,.JB41		;SAVE IT.
	SETZM	CCLFLG			;NOT USING CCL FILE NOW.
	EME	.CLR,ZERO		;CLEAR BUFFERS.
	JUMPE	PDP,START1		;JUMP IF NOT CCL ENTRY.
	HRLZI	T1,'DSK'		;SET DEVICE FOR DATA FILE.
	MOVEM	T1,DATDEV+1		;SET DEVICE.
	SETZM	DATFIL+3		;CLEAR PPN WORD.
	GOTO	NTHERE			;YES CONTINUE ON.
START1:	MOVE	PDP,[IOWD PDPSIZ,STACK]	;SET UP PUSH-DOWN POINTER.
	MOVE	T1,PRGNAM		;GET OUR NAME.
	GOSUB	PUTSIX			;PRINT IT.
	EME	.STR,[ASCIZ " HERE AT "];SAY GOOD THINGS.
	MME	T1,.TIME		;GET THE TIME OF DAY.
	GOSUB	TYPTIM			;PRINT THE TIME OF DAY.
	EME	.CH,[EXP " "]		;SEPARATE THINGS.
	MME	T1,.DATE		;GET THE DATE.
	GOSUB	TYPDAT			;PRINT THE DATE.
	GOSUB	CRLF			;SKIP A LINE.
	GOTO	NTH0			;START THINGS ROLLING.
;HERE TO GET ANOTHER COMMAND.

NTHERE:	ENABLE	TTY			;CLEAR CONTROL O.
	PRINT	(READY.)		;TELL HIM WE'RE READY.
	EME	.CH,[EXP 12]		;SKIP A LINE.
NTH1:	MOVE	PDP,[IOWD PDPSIZ,STACK]	;SET UP PUSH-DOWN POINTER.
	SKIPN	RETWRD			;SKIP IF RETAINING.
	GOTO	NTH0			;ELSE CARRY ON.
	SETOM	RETWRD			;FLAG NOT TO PERFORM COMMAND.
	SKIPA	T1,[XWD INPBUF,INPBUF+1];POINTER FOR PARTIAL BLT.
NTH0:	MOVE	T1,[XWD FSTMEM,FSTMEM+1];POINTER FOR INITIAL BLT.
	SETZM	-1(T1)			;CLEAR FIRST WORD.
	BLT	T1,LSTMEM		;DO IT.
	SETZM	IFILE+BUFFER		;CLEAR BUFFER POINTER.
	SETZM	OFILE+BUFFER		;CLEAR BUFFER POINTER.
	HRRZS	IFILE+MOD		;CLEAR DEVICE MOD BITS.
	HRRZS	OFILE+MOD		;CLEAR DEVICE MOD BITS.
	RELEASE	IF,ZERO			;RELEASE INPUT CHANNEL.
	RELEASE	OF,ZERO			;RELEASE OUTPUT CHANNEL.
	RELEASE	HF,ZERO			;RELEASE HELP FILE CHANNEL.
	RELEASE	UF,ZERO			;RELEASE UFD CHANNEL.
	RELEASE	MF,ZERO			;RELEASE MFD CHANNEL.
	MOVE	T1,CCLCOR		;COPY OF JOBFF FOR CCL COMMAND.
	SKIPL	CCLFLG			;SKIP IF IN CCL COMMAND.
	HLRZ	T1,.JBSA		;COPY SAVED JOBFF.
	MOVEM	T1,.JBFF		;RESTORE IT.
	MME	T1,.CORE		;BACK TO START SIZE.
	NOP				;IGNORE ERRORS.
	MOVE	T1,[SIXBIT "0001"]	;RESET VOLUME NUMBER.
	MOVEM	T1,IFILE+VOL		;INTO INPUT SPECS.
	MOVEM	T1,OFILE+VOL		;INTO OUTPUT SPECS.
	MOVEI	T1,IF			;GET INPUT CHANNEL NUMBER.
	MOVEM	T1,IFILE+CHAN		;SAVE IT.
	MOVEI	T1,OF			;GET THE OUTPUT CHANNEL NUMBER.
	MOVEM	T1,OFILE+CHAN		;SAVE THE NUMBER.
	GOSUB	TRPSET			;SET UP TRAP BLOCK.
SUBTTL		*** COMMAND DECODER ***

;ENTER HERE TO DECODE A COMMAND STRING OF THE FORM:
;ODEV:FILENAME.EXT[P,PN]/X/Y_IDEV:FILENAME.EXT[P,PN]/X/Y

GETCOM:	SETZM	DIAFLG			;CLEAR RETURN FLAG.
	EME	.STR,[ASCIZ "> "]	;FLAG WE WANT A COMMAND.
	MOVEI	S,TWO			;POSITION ON LINE.
	MOVEM	S,SPCCNT		;SET THE SPACE COUNTER.
	SETZM	S			;CLEAR THE FLAGS.
	MOVEI	SIDE,OFILE		;SET DECODER INDEX.
	GOSUB	GETSIX			;GET A COMMAND WORD.
	IF.OFF	S,EOL,CHKDEM		;IF NOT END OF COMMAND JUMP.
	JUMPN	WD,GTCOM1		;JUMP IF THERE IS A COMMAND.
	IF.OFF	S,ALT,GETCOM		;IGNORE NULL COMMANDS.
	GOTO	DIALOG			;ENTER DIALOG MODE FOR ALTMODE.
GTCOM1:	MOVEM	WD,TEMP1		;SAVE THE COMMAND WORD.
	MOVE	P1,[XWD -COMCNT,COMTAB]	;AOBJ WORD FOR TABLE.
	MOVEI	P2,COMDIS		;COMMAND DISPATCH TABLE.
	GOTO	UNICOM			;GO FIND A UNIQUE COMMAND.
NOTCOM:	SKIPN	RETWRD			;SKIP IF RETAINING.
	GOTO	COMERR			;ELSE COMMAND ERROR.
	SKIPA	WD,TEMP1		;SKIP INTO GOODNESS.
GETWOD:	GOSUB	GETSIX			;GET A COMMAND WORD.
CHKDEM:	IF.OFF	S,COL			;IS THE DEVICE BIT SET.
	GOSUB	GETDEV			;YES SET UP DEVICE.
	IF.OFF	S,PER			;FILE NAME BIT.
	GOSUB	GETNAM			;GET THE FILE NAME.
	IF.OFF	S,BRK			;IS THERE A PPN COMING.
	GOSUB	GETPPN			;YES READ IT IN.
	IF.ON	S,ATS,CCLCOM		;OPEN CCL FILE.
SW.RET:	IF.ON	S,SLH,GETSW		;JUMP IF IT IS A SWITCH.
	IF.ON	S,IO,RESYNC		;IF _ OR = RECYCLE DECODER.
	IF.ON	S,EOL,ENDCOM		;IF END OF COMMAND JUMP.
	GOTO	COMERR			;ELSE ILLEGAL COMMAND.
;HERE ON AN EXIT COMMAND.

STOP:	MME	.RESET			;RESET THE WORLD.
	MME	ONE,.TERM		;AND STOP.
	GOTO	START			;IN CASE OF CONTINUE.

;HERE ON A DDT OR DEBUG COMMAND.

DEBUG:	SKIPN	T1,.JBDDT		;SKIP IF DDT IS HERE.
	GOTO	DDTERR			;TELL HIM WHAT IS WRONG.
CALDDT:	SAVE	[NTHERE]		;RETURN TO THE STACK.
	SETZM	.JBAPR			;DON'T ALLOW APR TRAPS.
	SETZM	.JBINT			;DON'T ALLOW DEVICE TRAPS.
DDTCAL:	ENABLE	TTY			;CLEAR CONTROL O.
	GOSUB	CRLF			;SKIP A LINE.
	EME	.STR,[ASCIZ "Debugger here"];TELL HIM WHAT IS GOING ON.
	GOTO	ZERO(T1)		;CALL THE DEBUGGER.

;HERE ON A BYE COMMAND.

LOGOFF:	EME	.CLR,ZERO		;CLEAR THE TTY BUFFERS.
	GOSUB	CRLF			;SKIP A LINE.
	MOVEI	T1,LOGPRG		;POINTER TO PARAMETERS.
	MME	T1,.RUN			;RUN LOGOUT.
	GOTO	STOP			;THE MME FAILED.

;HERE ON A RETAIN COMMAND.

RETAIN:	SETOM	RETWRD			;FLAG RETAINED COMMAND.
	GOTO	NTHERE			;CONTINUE ON.

;HERE ON AN ERASE COMMAND.

ERASE:	SETZM	RETWRD			;CLEAR RETAIN WORD.
	GOTO	NTHERE			;CONTINUE ON.

;HERE ON A PERFORM COMMAND.

PERFOR:	EME	.CH,[EXP 12]		;SKIP A LINE.
	MOVE	T1,PRGNAM		;GET OUT NAME.
	GOSUB	PUTSIX			;PRINT IT.
	EME	.CH,[EXP 11]		;TAB A LITTLE.
	MME	T1,.TIME		;GET THE TIME OF DAY.
	GOSUB	TYPTIM			;PRINT THE TIME.
	EME	.CH,[EXP 11]		;TAB TO NEXT ZONE.
	MME	T1,.DATE		;GET THE DATE.
	GOSUB	TYPDAT			;TYPE THE DATE.
	GOSUB	CRLF			;SKIP A LINE.
	EME	.CH,[EXP 12]		;SKIP A LINE.
	SKIPN	RETWRD			;SKIP IF THERE IS A COMMAND.
	GOTO	NOCOM			;TELL HIM NO GO.
	HRRZS	RETWRD			;FLAG THAT WE DO THIS ONE.
	GOTO	ENDCM0			;AND DO IT.
;HERE FOR DIALOG MODE. DIALOG IS ENTERED BY TYPING ONLY
;AN ALTMODE ON THE LINE. IT IS LEFT BY TYPING A CONTROL C
;NOTE: ANY COMMAND UP TO THIS POINT IS ERASED.

DIALOG:	XCT	CRLF			;SKIP A LINE.
	PRINT	(Entering dialog mode.)
	SETZM	FSTMEM			;CLEAR FIRST MEMORY CELL.
	MOVE	T1,[XWD FSTMEM,FSTMEM+1];BLT POINTER.
	BLT	T1,LSTMEM		;CLEAR ANY RETAINED COMMAND.
	MOVE	T1,[SIXBIT "0001"]	;VOLUME NUMBER EXPECTED.
	MOVEM	T1,IFILE+VOL		;SET IT.
	MOVEM	T1,OFILE+VOL		;IN BOTH SPECIFICATONS.
	SETZM	RETWRD			;FLAG NOT TO RETAIN COMMAND.
	MOVEI	SIDE,IFILE		;SET AN INDEX.
	XCT	CRLF			;SKIP A LINE.
	PRINT	(*** Input specifications ***)
	GOSUB	DIAGET			;GET THE SPECS.
	MOVEI	SIDE,OFILE		;SET AN INDEX.
	SETZM	S			;CLEAR A REGISTER.
	XCT	CRLF			;SKIP A LINE.
	PRINT	(*** Output specificaions ***)
	GOSUB	DIAGET			;GET THE SPEC.
	HRROS	RETWRD			;FLAG COMMAND SHOULD BE RETAINED.
	SETZM	DIAFLG			;CLEAR RETURN FLAG.
	GOTO	PERFOR			;PERFORM THE COMMAND.
DIAGET:	DIARET				;SET RETURN ADDRESS.
	MOVEI	T1,6			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;FOR ERROR ROUTINE.
	EME	.STR,[ASCIZ "File: "]	;ASK FOR DEV:FILE.EXT[P,PN].
DIA0:	GOSUB	GETSIX			;GET A SIXBIT WORD.
	IF.OFF	S,COL,DIA1		;JUMP IF SKIPPED DEVICE.
	GOSUB	GETDEV			;GET THE DEVICE.
DIA1:	GOSUB	NAMCHK			;GET THE FILE NAME.
DIA2:	IF.OFF	S,BRK,DIA3		;JUMP IF NO PPN.
	GOSUB	GETPPN			;ELSE GET THE PPN.
DIA3:	IF.OFF	S,EOL,COMERR		;COMMAND ERROR IF NOT EOL.
	MOVE	T1,DEVICE(SIDE)		;GET THE DEVICE.
	JUMPE	T1,WBEDSK		;JUMP IF WILL BE DISK.
	MME	T1,.DEV			;SEE WHAT IT IS.
	IF.OFF	T1,DSK!DTA!MTA,DIA3X	;JUMP IF NOT A DIRECTORY DEVICE.
WBEDSK:	DIARET				;SET ERROR RETURN.
	MOVEI	T1,6			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE IT.
	EME	.STR,[ASCIZ "Mode: "]	;ASK FOR THE MODE.
	ON	S,COL			;SO WE THINK A COLON WAS TYPED.
	GOSUB	SW.M			;GET THE MODE.
	IF.OFF	S,EOL,COMERR		;JUMP IF NOT EOL.
	EME	.STR,[ASCIZ "Do records cross logical blocks: "]
	GOSUB	YESNO			;GET THE ANSWER.
	SKIPA				;SKIP INTO GOODNESS.
	GOTO	DIA3A			;JUMP IF NOT.
	MOVEI	T1,SPAN			;GET THE SPAN BIT.
	IORM	T1,MOD(SIDE)		;SET THE BIT.
DIA3A:	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D13			;WHERE WE ARE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE THE COUNT.
	EME	.STR,[ASCIZ "Record size: "]
	ON	S,COL			;SO A COL IS SEEN.
	GOSUB	SW.R			;GET THE RECORD SIZE.
	IF.OFF	S,EOL,COMERR		;COMMAND ERROR IF NOT EOL.
	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D17			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;FOR ERROR ROUTINE.
	EME	.STR,[ASCIZ "Blocking factor: "]
	ON	S,COL			;SO WE THINK A COLON WAS TYPED.
	GOSUB	SW.B			;GET THE BLOCKING FACTOR.
	IF.OFF	S,EOL,COMERR		;IF NOT EOL.
DIA3X:	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D9			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE THE LINE POSITION.
	EME	.STR,[ASCIZ "Buffers: "];ASK HOW MANY BUFFERS.
	ON	S,COL			;FLAG TO GET ARGUMENT.
	GOSUB	SW.BUF			;GET THE BUFFER SWITCH.
	IF.OFF	S,EOL,COMERR		;JUMP IF NOT ENDED RIGHT.
	SETZM	IM			;CLEAR A REGISTER.
	EME	.STR,[ASCIZ "Stop on errors: "]
	GOSUB	YESNO			;GET A REPLY.
	GOTO	DIA3BX			;JUMP IF YES.
	ON	IM,NOERROR		;LIGHT A BIT.
DIA3BX:	MOVE	T1,CHRMOD(SIDE)		;GET THE MODE.
	CAILE	T1,GEAMOD		;SKIP IF ASCII.
	GOTO	DIA3B			;ELSE JUMP.
	EME	.STR,[ASCIZ "CRLF'S IN ASCII FILE: "]
	GOSUB	YESNO			;GET A REPLY.
	SKIPA				;SKIP INTO GOODNESS.
	ON	IM,NOCRLF		;LIGHT A BIT.
DIA3B:	IORM	IM,MOD(SIDE)		;SAVE THE BITS.
	MOVE	T1,DEVICE(SIDE)		;GET THE DEVICE.
	MME	T1,.DEV			;GET ITS CHARACTERISTICS.
	IF.OFF	T1,LPT,DIA4		;JUMP IF NOT LPT.
	EME	.STR,[ASCIZ "Headers for lpt: "]
	GOSUB	YESNO			;GET A REPLY.
	RETURN	ZERO			;RETURN IF HE WANTS IT.
	MOVEI	T1,NOHEAD		;GET THE NO HEADER BIT.
	IORM	T1,MOD(SIDE)		;SET IT.
	RETURN	ZERO			;AND RETURN.
DIA4:	IF.OFF	T1,MTA,RET0		;RETURN IF NOT MAG-TAPE.
	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D9			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE THE SPACE COUNT.
	EME	.STR,[ASCIZ "Density: "];ASK FOR THE TAPES DENSITY.
	ON	S,COL			;TO FLAG ARGUMENT.
	GOSUB	SW.D			;READ IT IN.
	IF.OFF	S,EOL,COMERR		;JUMP IF NOT EOL.
	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D8			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE THE COUNTER.
	EME	.STR,[ASCIZ "Parity: "]	;ASK FOR PARITY.
	ON	S,COL			;TO FLAG ARGUMENT.
	GOSUB	SW.P			;AND GET IT.
	IF.OFF	S,EOL,COMERR		;ERROR IF NOT EOL.
	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D9			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE FOR ERROR ROUTINE.
	EME	.STR,[ASCIZ "Advance: "];ASK FOR AN ADVANCE COUNTER.
	ON	S,COL			;TO FLAG ARGUMENT.
	GOSUB	SW.A			;READ IT IN.
	IF.OFF	S,EOL,COMERR		;ERROR IF NOT EOL.
	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D11			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SET COUNTER.
	EME	.STR,[ASCIZ "backspace: "];TELL HIM WE WANT BACKSPACE ARGUMENT.
	ON	S,COL			;SET COL BIT.
	GOSUB	SW.BK			;GET AN ARGUMENT.
	IF.OFF	S,EOL,COMERR		;JUMP IF NOT EOL.
	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D8			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE IT.
	EME	.STR,[ASCIZ "norewind: "];ASK IF DOESN'T WANT TO WIND.
	ON	S,COL			;FLAG WE HAVE SEEN A COLON.
	GOSUB	NOREW			;SET THE SWITCH.
	IF.OFF	S,EOL,COMERR		;JUMP IF NOT EOL.
	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D7			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE CHARACTER POSITION.
	EME	.STR,[ASCIZ "Label: "]	;ASK FOR LABEL TYPE.
	ON	S,COL			;ARGUMENT IS NEXT.
	GOSUB	SW.L			;READ THE LABEL TYPE.
	IF.OFF	S,EOL,COMERR		;JUMP IF NOT END OF LINE.
	JUMPE	P4,DIA4X		;JUMP IF NO LABEL TYPE.
	CAIE	SIDE,OFILE		;SKIP IF OUTPUT SPEC.
	GOTO	DIA4X			;DON'T ASK FOR REEL ON INPUT.
	DIARET				;SET ERROR RETURN.
	MOVEI	T1,^D6			;PLACE ON LINE.
	MOVEM	T1,SPCCNT		;SAVE POINTER.
	EME	.STR,[ASCIZ "Reel: "]	;ASK FOR REEL NUMBER.
	ON	S,COL			;TO FLAG ARGUMENT.
	GOSUB	SW.RL			;READ IT.
	IF.OFF	S,EOL,COMERR		;JUMP IF DIDN'T END RIGHT.
DIA4X:	SETZM	IM			;CLEAR BIT REGISTER.
	EME	.STR,[ASCIZ "Industry tape: "]
	GOSUB	YESNO			;GET A REPLY.
	ON	IM,IND			;SET A BIT.
	EME	.STR,[ASCIZ "Unload tape: "]
	GOSUB	YESNO			;GET A REPLY.
	ON	IM,UNLOAD		;SET A BIT.
	MOVE	T1,MOD(SIDE)		;GET THE MOD BITS.
	CAIN	SIDE,IFILE		;ONLY ASK ON INPUT SIDE.
	IF.ON	T1,WILD,DIA5		;JUMP IF WILD.
	EME	.STR,[ASCIZ "Scan tape for file: "]
	GOSUB	YESNO			;GET A REPLY.
	ON	IM,SCAN			;SET SCAN BIT.
DIA5:	IORM	IM,MOD(SIDE)		;SET THE MODE BITS.
	RETURN	ZERO			;RETURN.
YESNO:	ON	S,BAD			;IGNORE BAD CHARACTERS.
	MOVE	P1,[XWD -YESCNT,YESTAB]	;POINTER FOR TABLE SCAN.
	MOVEI	P2,YESDIS		;DISPATCH TABLE.
	GOTO	UNIMAT			;CHECK COMMAND.
YESRET:	IF.OFF	S,EOL,XYNRET		;BAD ANSWER.
	RETURN	ZERO			;YES RETURN.
NORET:	IF.OFF	S,EOL,XYNRET		;BAD ANSWER.
	RETURN	ONE			;NO RETURN.
XYNRET:	IF.ON	S,EOL			;SKIP IF END OF LINE.
	GOSUB	GETONE			;FIND END OF LINE.
	IF.ON	S,EOL			;SKIP IF EOL.
	GOTO	.-2			;TRY AGAIN.
	PRINT	(? Answer YES or NO.)
	UNSAVE	T1			;GET THE RETURN FROM STACK.
	GOTO	-TWO(T1)		;TRY AGAIN.
;HERE ON A PRINT COMMAND TO DISPLAY THE CURRENT COMMAND.

XPRINT:	SKIPN	RETWRD			;SKIP IF RETAINING.
	GOTO	NTHERE			;ELSE IGNORE COMMAND.
	GOSUB	CRLF			;SKIP A LINE.
	EME	.STR,[ASCIZ "Out= "]	;SAY OUTPUT IS COMING.
	MOVEI	SIDE,OFILE		;GET INDEX FOR OUTPUT SIDE.
	GOSUB	XPRNT0			;TELL GOOD THINGS.
	EME	.STR,[ASCIZ "In=  "]	;SAY INPUT IS COMING.
	MOVEI	SIDE,IFILE		;INPUT INDEX.
	SAVE	[NTHERE]		;RETURN TO THE STACK.

;HERE TO TYPE OUT THE COMMAND FOR ONE SIDE OF THE EQUAL SIGN.

XPRNT0:	MOVE	P4,MOD(SIDE)		;GET THE MOD BITS.
	GOSUB	TYPNAM			;TYPE DEV:FILENAME.EXT[P,PN]
	SKIPN	P1,BLKFCT(SIDE)		;BLOCKING FACTOR YET.
	GOTO	XPRNT1			;NO CONTINUE.
	EME	.STR,[ASCIZ "/BLOCK:"]	;TELL HIM BLOCKING FACTOR IS NEXT.
	GOSUB	DECOUT			;PRINT IT.
XPRNT1:	SKIPN	P1,RECSIZ(SIDE)		;IS THERE A RECORD SIZE.
	GOTO	XPRNT2			;NO DO THE NEXT THING.
	HLRZ	T1,P1			;GET THE LEFT HALF.
	JUMPN	T1,XPRNT2		;JUMP IF WE DID IT.
	EME	.STR,[ASCIZ "/RECORD:"]	;FLAG RECORD SIZE.
	GOSUB	DECOUT			;OUTPUT IT.
XPRNT2:	SKIPN	P1,ADVAN(SIDE)		;IS THERE AN ADVANCING COUNT.
	GOTO	XPRNT8			;NO JUMP.
	EME	.STR,[ASCIZ "/ADVANCE:"] ;TELL HIM THE ADVANCE COUNTER.
	GOSUB	DECOUT			;PRINT IT.
XPRNT8:	SKIPN	P1,PERGE(SIDE)		;IS THERE A REEL SWITCH.
	GOTO	XPRNT9			;NO...
	EME	.STR,[ASCIZ "/REEL:"]	;TELL WHAT IS COMING.
	GOSUB	DECOUT			;PRINT IT.
XPRNT9:	MOVE	T1,STATUS(SIDE)		;GET THE DEVICE STATUS WORD.
	IF.OFF	T1,EVEN,XPRNT3		;JUMP IF ODD PARITY.
	EME	.STR,[ASCIZ "/PARITY:EVEN"] ;SAY EVEN PARITY.
XPRNT3:	LDB	T1,[POINT 2,DENSITY(SIDE),28] ;GET THE DENSITY BITS.
	JUMPLE	T1,XPRNT4		;JUMP IF NONE SPECIFIED.
	SOS	T1			;CORRECT IT.
	EME	.STR,[ASCIZ "/DENSITY:"] ;FLAG DENSITY IS COMING.
	MOVE	T1,DN.TAB(T1)		;GET THE SIXBIT WORD.
	GOSUB	PUTSIX			;PRINT IT.
XPRNT4:	SKIPN	T1,CHRMOD(SIDE)		;GET THE CHARACTER SET INDEX.
	GOTO	XPRNT5			;NONE YET.
	EME	.STR,[ASCIZ "/MODE:"]	;TELL HIM THE MODE.
	MOVE	T1,CNAM(T1)		;GET THE SIXBIT MODE.
	GOSUB	PUTSIX			;PRINT THE MODE.
XPRNT5:	SKIPN	T1,LABEL(SIDE)		;LABEL TYPE YET.
	GOTO	XPRNTD			;NO JUMP.
	EME	.STR,[ASCIZ "/LABEL:"]	;FLAG LABEL TYPE COMING.
	MOVE	T1,LB.TAB(T1)		;GET THE TYPE SPECIFIED.
	GOSUB	PUTSIX			;PRINT IT.
XPRNTD:	SKIPN	P1,BUFNUM(SIDE)		;DID HE SPECIFY BUFFERS.
	GOTO	XPRNTA			;NO CONTINUE ON.
	EME	.STR,[ASCIZ "/BUFFERS:"];SAY BUFFERS IS NEXT.
	GOSUB	DECOUT			;PRINT THE NUMBER.
XPRNTA:	SKIPN	P1,BACSPC(SIDE)		;ANY BACKSPACE COUNTER.
	GOTO	XPNT99			;NO FORGET IT.
	EME	.STR,[ASCIZ "/BACKSPACE:"];TELL WHAT IS COMING.
	GOSUB	DECOUT			;PRINT IT.
XPNT99:	MOVE	P3,MOD(SIDE)		;GET THE MOD BITS.
	TRC	P3,AWIND!BWIND		;COMPLEMENT WIND BITS.
	TRCN	P3,AWIND!BWIND		;SKIP IF BOTH NOT ON.
	ON	P3,NOWIND		;FLAG BO]H ON.
	IF.OFF	P3,AWIND!BWIND!NOWIND,XPNT88;JUMP IF NONE ON.
	EME	.STR,[ASCIZ "/NOREWIND:"];FLAG A NOWIND.
	IF.OFF	P3,AWIND		;SKIP IF NOT AFTER.
	MOVE	T1,REWTAB		;POINTER TO AFTER MESSAGE.
	IF.OFF	P3,BWIND		;SKIP IF NOT BEFORE.
	MOVE	T1,REWTAB+1		;POINTER TO BEFORE MESSAGE.
	IF.OFF	P3,NOWIND		;SKIP IF NOT NEVER.
	MOVE	T1,REWTAB+2		;POINTER TO ALWAYS MESSAGE.
	GOSUB	PUTSIX			;SEND MESSAGE.
XPNT88:	CAIE	SIDE,OFILE		;ONLY ON THE OUTPUT SIDE.
	GOTO	XPRNT6			;CONTINUE ON.
	SKIPE	TELWRD			;SKIP IF TALKING.
	EME	.STR,[ASCIZ "/NOTELL"]	;TELL HIM NO TALK.
	SKIPN	LSTWRD			;SKIP IF LISTING.
	GOTO	XPRNTZ			;CARRY ON.
	MOVE	T1,[EME .STR,[ASCIZ "/LIST"]];IF LIST OPTION.
	SKIPE	FSTWRD			;SKIP IF NORMAL LIST.
	MOVE	T1,[EME .STR,[ASCIZ "/FLIST"]];FOR FAST LIST.
	XCT	T1			;PRINT IT.
XPRNTZ:	SKIPE	PASS			;IS THERE A PASSWORD.
	GOTO	XPRNTB			;YES TYPE IT.
	SKIPN	PASS+1			;CHECK THE OTHER HALF.
	GOTO	XPRNT6			;NO PASSWORD.
XPRNTB:	EME	.STR,[ASCIZ "/PASSWORD:"] ;TELL HIM PASSWORD IS NEXT.
	MOVE	P1,[POINT 6,PASS]	;GET A POINTER.
XPRNTC:	ILDB	CH,P1			;GET A CHARACTER.
	MOVEI	CH," "(CH)		;CONVERT IT TO ASCII.
	EME	.CH,CH			;PRINT IT.
	CAME	P1,[XWD 600,PASS+1]	;SKIP IF DONE.
	GOTO	XPRNTC			;ELSE DO MORE.
XPRNT6:	HRLZI	P4,-NWUCNT		;COUNT OF OTHER SWITCHES.
	MOVE	P3,MOD(SIDE)		;GET THE MOD BITS.
	TDNE	P3,NWUTAB(P4)		;TEST A BIT.
	GOSUB	XPRNT7			;THIS ONE IS ON.
	AOBJN	P4,.-2			;DO THE NEXT ONE.
	GOTO	CRLF			;SKIP A LINE AND EXIT.
XPRNT7:	EME	.CH,[EXP "/"]		;FLAG A SWITCH.
	MOVE	T1,SW.TAB(P4)		;GET ITS NAME.
	GOTO	PUTSIX			;PRINT IT.
;HERE WHEN AN "@" IS FOUND IN THE COMMAND STRING. THIS MEANS
;TAKE THE DEV:FILE.EXT[P,PN] POINTED TO BY THE AC SIDE AND
;OPEN IT. IF THE FILE IS FOUND USE IT FOR INPUT TO CHANGE.

CCLCOM:	SAVE	SPCCNT			;SAVE THE CHARACTER POSITION.
	IF.ON	S,EOL			;SKIP IF AT END OF COMMAND.
	GOSUB	GETONE			;GET A CHARACTER.
	IF.ON	S,EOL			;SKIP IT AT END OF LINE.
	GOTO	.-2			;SKIP REST OF COMMAND.
	UNSAVE	SPCCNT			;RESTORE THE CHARACTER POSITION.
	GOSUB	NAMCHK			;MAYBE SOMETHING IN WD.
	SKIPL	P1,CCLFLG		;GET POINTER TO LAST BLOCK.
	MOVEI	P1,CCLBLK+1-CCLCNT	;NONE USE FIRST.
	ADDI	P1,CCLCNT		;POINT POINTER TO NEXT BLOCK.
	HRRZS	P1			;ZERO THE LEFT HALF.
	CAIL	P1,CCLEND		;ARE WE TOO DEEP.
	GOTO	TOODEP			;CCL FILES NESTED TO DEEPLY.
	HRRM	P1,CCLFLG		;SAVE POINTER.
	HRLZI	T1,NAME(SIDE)		;SOURCE FOR BLT.
	HRRI	T1,CCLNAM(P1)		;POINTER TO SPOT IN BLOCK.
	BLT	T1,CCLPPN(P1)		;SAVE TE NAME.
	SKIPN	T1,DEVICE(SIDE)		;GET THE DEVICE.
	MOVSI	T1,'DSK'		;DEFAULT DEVICE.
	MOVEM	T1,CCLDEV(P1)		;SAVE THE DEVICE.
	MME	T1,.DEV			;GET THE CHARACTERISTICS.
	SKIPN	T1			;DOES IT EXIST.
	JSP	T1,CCLBAK		;NO CCL DEVICE.
	NOP	NOEXT			;WHERE TO GO.
	IF.OFF	T1,DSK!DTA,NOUSE	;CAN'T USE DEVICE.
	XCT	CCLOPN(P1)		;OPEN THE DEVICE.
	GOTO	CCLNDV			;DEVICE NOT AVAILABLE.
	NOP	NODEV			;WHERE TO GO.
	XCT	CCLLOK(P1)		;OPEN THE FILE.
	GOTO	NOCCL			;CAN'T FIND FILE.
	HRROS	CCLFLG			;FLAG WE HAVE A CCL FILE.
	XCT	CCLBUF(P1)		;GET A BUFFER.
	HRRZ	T1,.JBFF		;GET THE FIRST FREE.
	MOVEM	T1,CCLCOR		;SAVE FOR CORE MME.
	GOTO	NTH1			;READ FILE AND DO COMMAND.
CCLBAK:	HRRZ	T2,CCLFLG		;GET THE POINTER WORD.
	XCT	CCLREL(T2)		;RELEASE DEVICE.
	SUBI	T2,CCLCNT		;POINT IT RIGHT.
	HRRM	T2,CCLFLG		;REPLACE FLAG.
	GOTO	@ZERO(T1)		;CALL ERROR ROUTINE.
CCLNDV:	NOP	@CCLOPN(P1)		;POINTER TO DEVICE.
	JSP	T1,CCLBAK		;BACK UP POINTER.
	NOP	NODEV			;WHERE TO GO ON ERROR.

	USE	DATA

CCLBLK:	CBLK	CF,CCLLEN
CCLEND==.-1

	USE	CODE
;HERE TO GET THE DEVICE SPECIFIED FROM THE USER.

GETDEV:	ON	S,DEV			;SAY WE HAVE SEEN A DEVICE.
	MOVEI	T1,WDEV			;GET WILD DEVICE BIT.
	ANDCAM	T1,MOD(SIDE)		;TURN IT OFF.
	GOSUB	CHKNAM			;SEE IF IT IS WILD.
	ON	T1,WDEV			;TO SET THE RIGHT BIT.
	IF.OFF	T1,WDEV			;SKIP IF NOT WILD.
	MOVSI	WD,'DSK'		;SET THE RIGHT NAME.
	MOVEM	WD,DEVICE(SIDE)		;SAVE THE DEVICE IN BLOCK.
	GOTO	GETSIX			;GET NEXT COMMAND WORD.

;HERE TO GET THE FILE NAME SPECIFIED FROM
;THE USER.

NAMCHK:	JUMPE	WD,RET0			;JUMP IF NO NAME.
GETNAM:	MOVEI	T1,WNAME!WEXT		;GET THE WILD BITS.
	ANDCAM	T1,MOD(SIDE)		;TURN OFF WILD BITS.
	GOSUB	CHKNAM			;CHECK OUT THE NAME.
	ON	T1,WNAME		;FOR WILD CHECK.
	MOVEM	WD,NAME(SIDE)		;SAVE THE FILE NAME.
	MOVEM	T2,NAMMSK(SIDE)		;SAVE THE MASK.
	SETZM	WD			;CLEAR COMMAND WORD.
	IF.OFF	S,PER			;SKIP IF NO EXTENSION.
	GOSUB	GETSIX			;GET THE EXTENSION.
	GOSUB	CHKNAM			;CHECK FOR WILDS.
	ON	T1,WEXT			;FOR WILD CHECK.
	MOVEM	WD,EXT(SIDE)		;SAVE THE EXTENSION.
	MOVEM	T2,EXTMSK(SIDE)		;SAVE THE MASK.
	SETZM	WD			;CLEAR WD TO DO GOOD THINGS LATER.
	RETURN	ZERO			;BACK TO CALLER.
CHKNAM:	SETZB	T1,T2			;CLEAR SOME REGISTERS.
	CAME	WD,[SIXBIT "*"]		;IS IT WILD.
	RETURN	ONE			;NO.
	SETOM	T2			;SET THE MASK.
SETBIT:	XCT	@ZERO(PDP)		;YES SET A BIT.
	IORM	T1,MOD(SIDE)		;AND LEAVE A TRACE.
	OFF	S,STAR			;TURN OFF STAR BIT.
	RETURN	ONE			;BACK TO CALLER.
;HERE TO PICK UP A PPN FROM THE USER.

GETPPN:	ON	S,NUM			;SAY WE HAVE A PPN.
	MOVEI	T1,WP!WPN		;GET THE WILD BITS.
	ANDCAM	T1,MOD(SIDE)		;AND CLEAR THEM.
	GOSUB	NAMCHK			;SEE IF THERE IS SOMETHING IN WD.
	GOSUB	GETHAL			;GET THE PROJECT NUMBER.
	ON	T1,WP			;FOR WILD CHECK.
	CAIE	CH,","			;SEE IF RIGHT DELIMITER.
	GOTO	PPNERR			;IF NOT ERROR.
	OFF	S,STAR!NOSTAR		;TREAT COMA AS A DELIMTER HERE.
	HRLZM	P2,PPN(SIDE)		;SAVE THE PROJECT NUMBER.
	GOSUB	GETHAL			;GET THE OTHER HALF.
	ON	T1,WPN			;FOR WILD CHECK.
	HRRM	P2,PPN(SIDE)		;SAVE PROJECT NUMBER.
	IF.ON	S,EOL,RET0		;ALLOW NO CLOSING BRACKET AT EOL.
	CAIE	CH,"]"			;MUST HAVE THE RIGHT DELIMITER.
	GOTO	PPNERR			;BAD PROGRAM NUMBER.
	GOTO	GETSIX			;GET NEXT WORD.
GETHAL:	GOSUB	GETOCT			;GET AN OCTAL NUMBER.
	JUMPE	P2,GTHAL		;MUST HAVE SOMETHING.
	IF.ON	P2,-1B17,PPNERR		;MUST BE POSITIVE IN THE RIGHT HALF.
	RETURN	ONE			;TAKE IT TO CALLER.
GTHAL:	CAIE	CH,"*"			;IS IT WILD.
	GOTO	PPNERR			;NO SO BAD PPN.
	GOSUB	GETONE			;GET ONE PAST STAR.
	SETZM	T1			;CLEAR A REGISTER.
	GOTO	SETBIT			;AND SET A BIT.
;HERE TO GET THE SWITCHES FROM THE USER.

GETSW:	GOSUB	NAMCHK			;SEE IF ANYTHING IN WD.
	MOVE	P1,[XWD -SW.CNT,SW.TAB]	;AOBJ WORD FOR TABLE SCAN.
	MOVEI	P2,SW.DIS		;SWITCH DISPATCH TABLE.
	SAVE	[SW.RET]		;PUT A RETURN ON THE STACK.
	GOTO	UNIMAT			;MATCH IT AND DISPATCH.

;HERE TO PICK UP AND SET THE BITS FOR ANY
;SWITCH THAT DOES NOT TAKE AN ARGUMENT.

SW.NWU:	MOVE	T1,NWUTAB(P4)		;PICK UP THE BIT TO SET.
	IORM	T1,MOD(SIDE)		;SET THE BIT.
	RETURN	ZERO			;RETURN FOR NEXT COMMAND.

;HERE TO TURN BITS OFF IN A STATUS WORD.

SW.OFF:	MOVE	T1,NWUTAB-NWUCNT(P4)	;GET THE BIT TO TURN OFF.
	ANDCAM	T1,MOD(SIDE)		;TURN IT OFF.
	RETURN	ZERO			;GET THE NEXT COMMAND.

;HERE TO PICK UP THE VALUE OF THE PARITY
;SWITCH. IF NOT SPECIFIED THIS SWITCH DEFAULTS
;TO ODD PARITY.

SW.P:	TNO	S,PAR,SWERR		;ONLY HERE ONCE.
	IF.OFF	S,COL,FOMERR		;NEED THE COLON BIT.
	MOVE	P1,[XWD -PR.CNT,PR.TAB]	;AOBJ WORD FOR TABLE SCAN.
	MOVEI	P2,PR.DIS		;DISPATCH TABLE.
	GOTO	UNIMAT			;MATCH THE COMMAND.
ODDRET:	SKIPA	T1,[ANDCAM T2,STATUS(SIDE)] ;TO CLEAR THE EVEN PARITY BIT.
EVERET:	MOVE	T1,[IORM T2,STATUS(SIDE)] ;TO SET THE EVEN PARITY BIT.
	MOVEI	T2,EVEN			;THE BIT TO DO THINGS WITH.
	XCT	T1			;DO IT.
	RETURN	ZERO			;BACK TO SENDER.

;HERE ON A TELL SWITCH.

XTELL:	SETZM	TELWRD			;CLEAR TALK WORD.
	RETURN	ZERO			;BACK TO CALLER.

;HERE ON A NOTELL SWITCH

XNTELL:	SETOM	TELWRD			;SET TELWRD NON-ZERO.
	RETURN	ZERO			;AND RETURN.
;HERE TO READ THE PASSWORD FOR GE LABELS.

SW.PW:	IF.OFF	S,COL,FOMERR		;MUST HAVE A COLON.
	MOVE	T3,[POINT 6,PASS]	;SET POINTER TO STORAGE.
	SETZM	PASS			;CLEAR STORAGE.
	SETZM	PASS+1			;CLEAR STORAGE.
PASLOP:	ON	S,NOCHK			;DON'T VALIDATE INPUT.
	GOSUB	GETONE			;GET A CHARACTER.
	IF.ON	S,SOM,RET0		;RETURN IF DELIMITER.
	SUBI	CH," "			;CONVERT IT TO SIXBIT.
	CAME	T3,[XWD 600,PASS+1]	;SKIP IF POINTER HAS RUN OUT.
	IDPB	CH,T3			;ELSE SAVE THE CHARACTER.
	GOTO	PASLOP			;LOOP UNTIL A DELIMITER.

;HERE TO SET THE CONVERSION MODE THAT IS TO
;BE DONE.

SW.M:	TNO	S,MODE,SWERR		;ONLY ONE MODE PER FILE.
	IF.OFF	S,COL,FOMERR		;FORMAT ERROR IF NO COLON.
	MOVE	P1,[XWD -M.CNT,M.TAB]	;POINTER TO TABLE.
	MOVEI	P2,M.DIS		;MODE DISPATCH TABLE.
	ON	S,NODIS			;SHORT DISPATCH TABLE.
	GOTO	UNIMAT			;FIND A MATCH.
M.RET:	MOVE	P4,MODTAB(P4)		;GET TABLE ADDRESS OF DATA.
	MOVEM	P4,CHRMOD(SIDE)		;SAVE THE MODE.
	RETURN	ZERO			;BACK FOR THE NEXT ONE.

;HERE TO SET UP THE BLOCKING FACTOR.

SW.B:	TNO	S,BLK,SWERR		;ONLY ONE BLOCKING FACTOR.
	GOSUB	NUMVAL			;GET THE VALUE OF THE SWITCH.
	MOVEM	P2,BLKFCT(SIDE)		;SAVE THE BLOCKING FACTOR.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO SET UP THE RECORD SIZE FOR THE FILE.

SW.R:	TNO	S,REC,SWERR		;ONLY HERE ONCE.
	GOSUB	NUMVAL			;READ THE VALUE.
	MOVEM	P2,RECSIZ(SIDE)		;SAVE THE RECORD SIZE.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO PICK UP THE VALUE OF THE ADVANCE SWITCH.

SW.A:	TNO	S,ADV,SWERR		;ONLY ONCE HERE.
	GOSUB	NUMVAL			;GET THE VALUE.
	MOVEM	P2,ADVAN(SIDE)		;SAVE IN DATA BLOCK.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO GET THE BACKSPACE ARGUMENT.

SW.BK:	TNO	S,BAC,SWERR		;ONLY HERE ONCE.
	GOSUB	NUMVAL			;GET THE ARBUMENT.
	MOVEM	P2,BACSPC(SIDE)		;SAVE THE ARGUMENT.
	RETURN	ZERO			;BACK FOR MORE.

;HERE FOR A REWIND SWITCH.

REWIND:	IF.OFF	S,COL,FOMERR		;JUMP IF NO COLON.
	MOVE	P1,[XWD -REWCNT,REWTAB]	;AOBJN POINTER FOR TABLE SCAN.
	MOVEI	P2,REWDIS		;DISPATCH TABLE.
	ON	S,NODIS			;SHORT DISPATCH TABLE.
	GOTO	UNIMAT			;FIND A MATCH.
REWRET:	CAIL	P4,THREE		;DID HE TYPE OMITT.
	GOTO	NOW0			;YES DON'T REWIND.
REW0:	MOVE	T1,REWBIT(P4)		;GET THE BIT.
	ANDCAM	T1,MOD(SIDE)		;SET IT.
	RETURN	ZERO			;AND RETURN.

;HERE FOR A NOWIND SWITCH.

NOREW:	IF.OFF	S,COL,FOMERR		;JUMP IF NO COLON.
	MOVE	P1,[XWD -REWCNT,REWTAB]	;POINTER FOR TABLE SCAN.
	MOVEI	P2,NORDIS		;DISPATCH TABLE POINTER.
	ON	S,NODIS			;SHORT DISPATCH TABLE.
	GOTO	UNIMAT			;FIND A MATCH.
NOWRET:	CAIL	P4,THREE		;DID HE TYPE OMITT.
	GOTO	REW0			;YES REWIND IT.
NOW0:	MOVE	T1,REWBIT(P4)		;GET THE BIT TO CLEAR.
	IORM	T1,MOD(SIDE)		;CLEAR THE BITS.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO PICK UP THE VALUE OF THE DENSITY SWITCH.

SW.D:	TNO	S,DEN,SWERR		;ONLY ONE DENSITY PER FILE.
	IF.OFF	S,COL,FOMERR		;NEED THE COLON BIT HERE.
	MOVE	P1,[XWD -DN.CNT,DN.TAB]	;SET UP POINTER.
	MOVEI	P2,DN.DIS		;DISPATCH TABLE.
	ON	S,NODIS			;SHORT DISPATCH TABLE.
	GOTO	UNIMAT			;FIND A MATCH.
D.RET:	AOS	P4			;BUMP THE COUNTER.
	DPB	P4,[POINT 2,DENSITY(SIDE),28];SET THE DENSITY.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO GET THE LABEL TYPE.

SW.L:	TNO	S,LAB,SWERR		;CAN ONLY HAVE ONE LABEL TYPE.
	IF.OFF	S,COL,FOMERR		;FORMAT ERROR IF NO COLON.
	MOVE	P1,[XWD -LB.CNT,LB.TAB]	;SET POINTER.
	MOVEI	P2,LB.DIS		;DISPATCH TABLE.
	ON	S,NODIS			;SHORT DISPATCH TABLE.
	GOTO	UNIMAT			;GO FIND A MATCH.
L.RET:	MOVEM	P4,LABEL(SIDE)		;SAVE THE LABEL TYPE.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO GET THE VALUE OF THE REEL SERIAL NUMBER THAT
;SHOULD BE WRITTEN IN THE OUTPUT LABEL IF THE LABEL
;TYPE SPECIFIED USES A REEL SERIAL NUMBER.

SW.RL:	TNO	S,REL,SWERR		;ONLY HERE ONCE.
	GOSUB	NUMVAL			;READ THE SWITCH'S VALUE.
	MOVEM	P2,PERGE(SIDE)		;SAVE THE SERIAL NUMBER.
	RETURN	ZERO			;BACK TO CALLER.

;HERE FOR THE RETAIN SWITCH IN THE COMMAND STRING.

SW.KEP:	SETOM	RETWRD			;FLAG RETAIN MODE.
	RETURN	ZERO			;GET THE NEXT ONE.

;HERE ON A PERFORM SWITCH. SET THE FLAG TO SAY WE WILL DO IT.
;AND EXIT.

SW.GO:	SETOM	RETWRD			;RETAIN COMMAND FIRST.
	HRRZS	RETWRD			;FLAG THAT WE ARE TO DO IT.
	RETURN	ZERO			;AND RETURN.
;HERE TO GET THE NUMBER OF BUFFERS TO USE.

SW.BUF:	TNO	S,XBUF,SWERR		;JUMP IF BEEN HERE BEFORE.
	GOSUB	NUMVAL			;GET THE VALUE OF THE ARGUMENT.
	MOVEM	P2,BUFNUM(SIDE)		;SAVE THE NUMBER.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO READ THE VALUE OF A NUMERIC SWITCH.

NUMVAL:	IF.OFF	S,COL,FOMERR		;MUST HAVE THE COLON.
	SAVE	SPCCNT			;SAVE THE CHARACTER COUNT.
	GOSUB	GETDEC			;GET THE ARGUMENT.
	UNSAVE	T1			;GET BACK CHARACTER COUNT.
	AOS	T1			;BUMP FOR CHARACTER READ.
	CAMN	T1,SPCCNT		;MUST HAVE SOMETHING.
	GOTO	FOMERR			;FORMAT ERROR.
	RETURN	ZERO			;BACK TO SENDER.

;HERE ON A LIST SWITCH OR AN FLIST SWITCH.

XFLST:	SETOM	FSTWRD			;SET FOR A FAST LIST.
	SKIPA				;SET THE LIST WORD.
XLST:	SETZM	FSTWRD			;CLEAR FAST LIST WORD.
	SETOM	LSTWRD			;SET TO DO A LIST.
	RETURN	ZERO			;RETURN.

;HERE ON A NOLIST SWITCH.

XNLST:	SETZM	LSTWRD			;CLEAR LIST WORD.
	SETZM	FSTWRD			;CLEAR FAST WORD.
	RETURN	ZERO			;AND RETURN.

;HERE TO RECYCLE THE COMMAND DECODER FOR THE
;INPUT FILE SPECIFICATIONS.

RESYNC:	GOSUB	NAMCHK			;SEE IF FILE NAME IS PRESENT.
	TNO	S,IOT,COMERR		;ONLY HERE ONCE.
	MOVEI	SIDE,IFILE		;CHANGE COMMAND INDEX.
	TNZ	S,DEV!NUM!DEN!PAR!ADV!LAB!MODE!REL!BLK!REC!XBUF,GETWOD
	MOVE	WD,OFILE+NAME		;GET THE COMMAND WORD.
	MOVE	P1,[XWD -E.CNT,E.TAB]	;POINTER TO TABLE.
	MOVEI	P2,E.DIS		;POINTER TO DISPATCH TABLE.
	ON	S,NODIS			;SHORT DISPATCH TABLE.
	GOTO	UNICOM			;FIND THE COMMAND.
E.RET:	SKIPN	OFILE+EXT		;ONLY IF JUST A NAME.
	IOR	S,E.BIT(P4)		;SET DELAYED COMMAND BIT.
	GOTO	GETWOD			;GET THE NEXT COMMAND WORD.
;HERE TO GET A SIXBIT WORD FROM THE COMMAND STRING.
;RETURNS THE WORD IN WD WHEN A DELIMITER IS FOUND.

GETSIX:	MOVE	T3,[POINT 6,WD]		;SET POINTER TO STORAGE.
	SETZM	WD			;AND THEN CLEAR STORAGE.
SIXLOP:	GOSUB	GETONE			;GET A CHARACTER.
	IF.ON	S,SOM,RET0		;RETURN IF DELIMITER FOUND.
	SUBI	CH," "			;CONVERT IT TO SIXBIT.
	IF.OFF	T3,77B5			;IF WD IS NOT FULL
	IDPB	CH,T3			;STACH THE CHARACTER.
	GOTO	SIXLOP			;LOOP UNTIL DONE.

;HERE TO FIND A UNIQUE MATCH FOR A SIXBIT WORD. ENTER WITH A
;POINTER TO THE SIXBIT TABLE IN P1, A POINTER TO THE DISPATCH
;TABLE IN P2, AND THE LENGTH OF THE TABLE IN THE UPPER HALF OF P1.

UNIMAT:	GOSUB	GETSIX			;GET A WORD.
UNICOM:	OFF	S,FNDONE!FNDTWO		;TURN OFF FOUND BITS.
	MOVE	T1,WD			;COPY COMMAND WORD.
	SETOM	T2			;INITIALIZE MASK.
GETMSK:	JUMPE	T1,GOTMSK		;JUMP IF MASK IS RIGHT.
	LSH	T1,6			;SHIFT A CHARACTER OUT.
	LSH	T2,-6			;FIX UP THE MASK.
	GOTO	GETMSK			;TRY AGAIN.
GOTMSK:	MOVE	T1,P1			;COPY AOBJN WORD.
NXTENT:	JUMPL	T2,TRYNXT		;IF NO COMMAND DON'T CHECK.
	MOVE	T3,ZERO(T1)		;GET A TABLE ENTRY.
	ANDCM	T3,T2			;ISOLATE THE CHARACTERS WE WANT.
	CAMN	WD,ZERO(T1)		;IS IT AN EXACT MATCH.
	GOTO	GOTMAT			;YES WE HAVE IT.
	CAME	T3,WD			;IS IT A PARTIAL MATCH.
	GOTO	TRYNXT			;NO TRY THE NEXT ONE.
	TEO	S,FNDONE		;WE HAVE FOUND ONE MATCH.
	TNO	S,FNDONE!FNDTWO		;LOOKS LIKE WE FOUND TWO.
	HRRZ	P3,T1			;SAVE THE INDEX.
TRYNXT:	AOBJN	T1,NXTENT		;CHECK THE WHOLE LIST.
	IF.OFF	S,FNDONE		;DID WE FIND ANYTING.
	IF.OFF	S,FNDTWO		;OR TOO MUCH.
	HRRZ	P3,T1			;GET ERROR INDEX.
COMGO:	SETZM	WD			;CLEAR INPUT WORD.
	SUBI	P3,ZERO(P1)		;P3 IS RELATIVE POINTER TO DISPATCH.
	MOVEI	P4,ZERO(P3)		;COPY INDEX.
	ADDI	P3,ZERO(P2)		;P3 IS NOW ABSOLUTE IF LONG DISPATCH.
	MOVEI	T1,ZERO(P2)		;ASSUME GOODNESS.
	IF.OFF	S,FNDONE		;DID WE FIND ONE.
	IF.OFF	S,FNDTWO		;OR TOO MANY.
	MOVEI	T1,ONE(P2)		;YES SET ERROR RETURN.
	TEZ	S,NODIS			;IS THERE A LONG DISPATCH TABLE.
	GOTO	@ZERO(T1)		;NO USE SHORT TABLE.
	GOTO	@ZERO(P3)		;USE LONG TABLE.
GOTMAT:	ON	S,FNDONE		;WE HAVE FOUND A MATCH.
	HRRZ	P3,T1			;SAVE EXACT MATCH INDEX.
	GOTO	COMGO			;AND THEN GO TO IT.
;HERE TO GET ONE CHARACTER AND TO SET ALL THE
;FLAGS THAT DESCRIBE THAT CHARACTER.

GETONE:	OFF	S,COL!PER!SLH!BRK!IO!EOL!SPC!ATS!SOM ;CLEAR SOME FLAGS.
GETCHR:	SKIPE	RUNFLG			;SKIP IF NOT RUNNING.
	GOTO	GTONE1			;JUMP IF SO.
	SKIPGE	CCLFLG			;SKIP IF NOT IN CCL FILE.
	GOSUB	REDCCL			;READ CCL FILE.
GTONE1:	EME	.LN,CH			;GET A CHARACTER.
	CAIN	CH,12			;IGNORE LINE-FEEDS.
	GOTO	GETCHR			;GET ANOTHER CHARACTER.
	CAIE	CH,15			;WAS THAT A RETURN.
	GOTO	GTONE0			;NO LOOK AT CHCRACTER.
	SKIPN	RUNFLG			;SKIP IF RUNNING.
	SKIPL	CCLFLG			;SKIP IF CCL FILE.
	EME	.LN,T1			;YES READ LINE-FEED.
GTONE0:	CAIN	CH,11			;IS THIS A TAB.
	GOTO	CNTTAB			;COUNT THE TAB.
	AOS	SPCCNT			;COUNT THE CHARACTER.
	IF.ON	S,NOCHK,GETCH0		;INCLUDE SPACES IF NO CHECK.
	CAIN	CH," "			;IS IT A SPACE.
	GOTO	GETCHR			;THEN GET ANOTHER.
GETCH0:	HRLZI	T1,-CH.CNT		;COUNT OF DELIMITERS.
	HLRZ	T2,CH.CHR(T1)		;MAKE A SELECTION.
	CAME	CH,T2			;AND TEST FOR A MATCH.
	AOBJN	T1,.-2			;TEST THE WHOLE LIST.
	JUMPGE	T1,MAKUP		;BACK TO SENDER NOT SPECIAL.
	HRRZ	T1,CH.CHR(T1)		;GET THE BITS.
	IOR	S,T1			;SET THEM.
	OFF	S,STAR!NOSTAR		;TURN OFF STAR BITS.
	IF.ON	S,SPC,CRLF		;SPECIAL CHARACTER.
	RETURN	ZERO			;BACK TO CALLER.
MAKUP:	CAIL	CH,140			;LOWER CASE.
	OFF	CH," "			;MAKE IT UPPER CASE.
	TEZ	S,NOCHK			;SHOULD WE VALIDATE INPUT.
	GOTO	XONE			;NO SO RETURN.
	CAIE	CH,","			;LET HIM HAVE A COMA.
	CAIN	CH,"]"			;IS THIS A BRACKET.
	GOTO	XONE			;YES IT IS O.K.
	IF.ON	S,STAR,BADSTR		;JUMP IF STAR IS ON.
	CAIN	CH,"?"			;IS IT A QUESTION MARK.
	GOTO	XONE			;THIS IS O.K.
	CAIN	CH,"*"			;IS IT A STAR.
	GOTO	GOTSTR			;YES SEE IF O.K.
	CAIGE	CH,"0"			;IS IT LESS THEN ZERO.
	GOTO	BADCHR			;ILLEGAL CHARACTER.
	CAIG	CH,"9"			;BUT LESS THEN NINE.
	GOTO	XONE			;CHARACTER IS NUMERIC.
	CAIL	CH,"A"			;IS IT IN THE ALPHABET.
	CAILE	CH,"Z"			;IS IT PAST THE TOP.
	GOTO	BADCHR			;YES IT IS ILLEGAL.
XONE:	ON	S,NOSTAR		;DIDN'T GET A STAR.
	RETURN	ZERO			;BACK TO CALLER...
GOTSTR:	ON	S,STAR			;LIGHT STAR BIT.
	IF.ON	S,NOSTAR,BADCHR		;JUMP IF LAST CHARACTER WASN'T A DELIMTER.
	RETURN	ZERO			;AND RETURN.
BADSTR:	SOS	SPCCNT			;POINT POINTER TO STAR.
	GOTO	BADCHR			;SAY BAD CHARACTER.
CNTTAB:	MOVE	T1,SPCCNT		;GET THE SPACE COUNT.
	IDIVI	T1,^D8			;GET THE POSITIONS TAB MOVED US.
	MOVEI	T1,^D8			;SPACES PER TAB.
	SUB	T1,T2			;T1 HAS SPACES MOVED.
	ADDM	T1,SPCCNT		;UPDATE THE SPACE COUNT.
	GOTO	GETCHR			;GET THE NEXT CHARACTER.
REDCCL:	HRRZ	CH,CCLFLG		;GET POINTERS TO THINGS.
	SOSGE	CCLHED+2(CH)		;SKIP IF DATA IN BUFFER.
	GOTO	CCLUP			;FILL UP THE BUFFER.
	ILDB	CH,CCLHED+1(CH)		;GET A CHARACTER.
	JUMPE	CH,REDCCL		;IGNORE NULLS.
	CAIN	CH,12			;SKIP IF NOT LINE-FEED.
	GOTO	REDCCL			;IGNORE LINE-FEEDS.
	EME	.CH,CH			;PRINT IT.
	CAIN	CH,15			;SKIP IF NOT RETURN.
	EME	.CH,[EXP 12]		;SKIP A LINE.
	RETURN	ONE			;SKIP RETURN.
CCLUP:	OFF	S,HUNG			;CLEAR HUNG DEVICE BIT.
	AOS	%IO			;COUNT DEVICE ACCESS.
	XCT	CCLGET(CH)		;FILL UP THE BUFFER.
	GOTO	REDCCL			;CARRY ON.
	XCT	CCLREL(CH)		;RELEASE CHANNEL.
	SUBI	CH,CCLCNT		;DECREMENT TO PREVIOUS BLOCK.
	HRRM	CH,CCLFLG		;SAVE POINTER.
	CAIGE	CH,CCLBLK		;HAVE WE DONE THEM ALL.
	SETZM	CCLFLG			;NO LONGER IN CCL FILE.
	UNSAVE	ZERO(PDP)		;POP RETURN TO STACK.
	ON	S,EOL!SOM		;MAKE IT AN EOL CHARACTER.
	MOVEI	CH,15			;LOAD ONE TO MAKE SURE.
	GOTO	CRLF			;SKIP A LINE AND EXIT.
;HERE TO GET EITHER A DECIMAL NUMBER OR OCTAL
;NUMBER FROM THE USER.

GETDEC:	SKIPA	P1,[^D10]		;SET THE RADIX.
GETOCT:	MOVEI	P1,10			;SET THE RADIX.
	SETZM	P2			;ZERO STORAGE.
NXTDIG:	GOSUB	GETONE			;GET A CHARACTER.
	IF.OFF	S,SOM			;DELIMITER.
	RETURN	ZERO			;YES RETURN.
	CAIL	CH,"0"			;MUST BE GREATER THEN 0-1.
	CAIL	CH,"0"(P1)		;BUT LESS THEN BASE.
	RETURN	ZERO			;BAD NUMBER.
	IMUL	P2,P1			;MULTIPLY NUMBER BY BASE.
	ADDI	P2,-"0"(CH) 		;ADD IN NEW DIGIT.
	GOTO	NXTDIG			;GET ANOTHER ONE.

;HERE TO CALL THE PROGRAM "TABLE" INTO CORE AND GIVE
;IT A CCL ENTRY. WHEN TABLE GETS THIS TYPE OF START
;IT WILL CREATE THE DATA FILE "DSK:CHANGE.DAT" WITH THE
;CONVERSION TABLES IN IT. "TABLE" WILL THEN RERUN CHANGE
;GIVING IT A CCL ENTRY.

CRETAB:	MOVSI	T1,'SYS'		;TRY DEVICE "SYS" FIRST.
	GOSUB	RUNIT			;TRY TO RUN IT.
	MOVSI	T1,'DSK'		;IF ERROR ON "SYS" TRY "DSK".
	GOSUB	RUNIT			;TRY AND RUN IT.
	GOTO	NOMAKE			;IF ERROR HERE NO RUN.
RUNIT:	MOVEM	T1,TABDEV+1		;SAVE THE DEVICE FOR LOOKUP.
	MOVEM	T1,TABRUN		;SAVE DEVICE TO RUN FROM.
	SETZM	TABFIL+3		;CLEAR PPN WORD.
	OPEN	IF,TABDEV		;GET THE DEVICE.
	RETURN	ZERO			;CAN'T HAVE DEVICE.
	LOOKUP	IF,TABFIL		;FIND THE FILE.
	RETURN	ZERO			;CAN'T FIND FILE.
	MOVE	T1,[XWD ONE,TABRUN]	;POINTER TO BLOCK.
	MME	T1,.RUN			;RUN THE FILE.
	RETURN	ZERO			;CAN'T RUN IT.

	USE	DATA

TABDEV:	XWD	ZERO,DMP		;SO NO BUFFERS.
	SIXBIT	"SYS"
	BSS	ONE
TABRUN:	SIXBIT	"SYS"
TABFIL:	SIXBIT	"TABLE"
	SIXBIT	"SAV"
	BSS	3

	USE	CODE
SUBTTL				*** END OF COMMAND ***

;HERE ON COMMAND END TO START IT GOING.

ENDCOM:	GOSUB	NAMCHK			;MAKE SURE IT IS OVER.
	MOVE	T1,RETWRD		;GET THE PERFORM WORD.
	JUMPN	T1,ENDCM0		;JUMP IF RETAINING.
	IF.OFF	S,IOT,COMERR		;ONE INPUT AND ONE OUTPUT DEVICE.
	IF.ON	S,DEN!PAR!BLK!ADV!LAB!MODE!REC!REL!XBUF,ENDCM0
	TNZ	S,DATA,GETTNM		;IF ON GET DATA FILE NAME.
ENDCM0:	SETZM	S			;CLEAR FLAGS.
	SKIPN	OF,OFILE+DEVICE		;IS THERE A DEVICE.
	HRLZI	OF,'DSK'		;SET UP DEFAULT.
	MOVEM	OF,OFILE+DEVICE		;SAVE DEVICE NAMED.
	MME	OF,.DEV			;GET ITS CHARACTERISTICS.
	SKIPN	OF			;DOES IT EXIST.
	JSP	T1,NOEXT		;NOT FOUND.
	HLLZS	OF			;ZERO OUT RIGHT HALF.
	IORB	OF,OFILE+MOD		;SET THE MOD BITS.
	SKIPN	IF,IFILE+DEVICE		;DEVICE SPECIFIED.
	HRLZI	IF,'DSK'		;SET DEFAULT.
	MOVEM	IF,IFILE+DEVICE		;SET UP DEVICE.
	MME	IF,.DEV			;GET CHARACTERISTICS.
	SKIPN	IF			;DOES IT EXIST.
	JSP	T1,NOEXT		;NOPE...NOT THERE.
	HLLZS	IF			;SET UP BITS.
	IORB	IF,IFILE+MOD		;SET ALL THE MOD BITS.
	HLRZ	T1,OFILE+RECSIZ		;GET THE OUTPUT RECORD SIZE.
	SKIPE	T1			;DID WE SET IT.
	SETZM	OFILE+RECSIZ		;YES SO CLEAR IT.
	MOVEI	T1,BIN			;MODE.
	IORM	T1,OFILE+STATUS		;SET THEM.
	IORM	T1,IFILE+STATUS		;SET THEM.
	HRLZI	T1,OBUF			;GET POINTER TO BUFFER HEADER.
	IF.OFF	OF,MTA			;IS THIS MAG-TAPE.
	HRRI	T1,OIBUF		;YES SO GET A INPUT HEADER.
	MOVEM	T1,OFILE+BUFFER		;SAVE IN PLACE.
	MOVEI	T1,IBUF			;GET POINTER TO INPUT HEADER.
	HRRZM	T1,IFILE+BUFFER		;SAVE IN PLACE.
	IF.OFF	OF,GDEV,NOOUSE		;CAN'T USE THIS DEVICE.
	IF.ON	OF,MTA!DSK!DTA,OPNO1	;JUMP IF THIS IS MTA, DSK, OR DTA.
	IF.OFF	OF,OTP,NOOUT		;JUMP IF CAN'T DO OUTPUT.
	MOVEI	T1,ASC			;ASCII DATA MODE.
	MOVEM	T1,OFILE+STATUS		;SAVE AS STATUS FOR DEVICE.
	MOVE	T1,OFILE+CHRMOD		;GET THE MODE OF OUTPUT.
	CAIN	T1,OCTMOD		;ALLOW OCTAL OUTPUT.
	GOTO	OPNO1			;DON'T CHANGE TO ASCII.
	SETZM	OFILE+BLKFCT		;SET BLOCKING FACTOR TO ZERO.
	SKIPN	T1,OFILE+RECSIZ		;SKIP IF RECORD SPECIFIED.
	HRLOI	T1,377777		;RECORD SIZE TO INFINITY.
	MOVEM	T1,OFILE+RECSIZ		;SAVE THE RECORD SIZE.
	MOVEI	T1,ASCMOD		;SO WE READ THE RIGHT TABLES.
	MOVEM	T1,OFILE+CHRMOD		;SAVE CHARACTER MODE.
OPNO1:	MOVE	T1,OFILE+DENSITY	;SET DENSITY UP FOR MAG-TAPE.
	IF.OFF	OF,MTA			;IS THIS MAG-TAPE.
	IORM	T1,OFILE+STATUS		;OR INTO PLACE.
OPNOUT:	IF.OFF	IF,GDEV,NOIUSE		;CAN'T USE THIS DEVICE.
	IF.ON	IF,MTA!DSK!DTA,OPNI1	;JUMP IF DSK, MTA, OR DTA.
	IF.OFF	IF,IPT,NOINP		;JUMP IF CAN'T DO INPUT.
	MOVEI	T1,ASC			;ASCII DATA MODE.
	MOVEM	T1,IFILE+STATUS		;SAVE AS DEVICE STATUS.
	SETZM	IFILE+BLKFCT		;SET BLOCKING FACTOR TO ZERO.
	MOVEI	T1,ASCMOD		;SET INDEX FOR TABLES.
	MOVEM	T1,IFILE+CHRMOD		;SAVE DEVICE DATA MODE.
OPNI1:	MOVE	T1,IFILE+DENSITY	;SET UP DENSITY FOR MTA.
	IF.OFF	IF,MTA			;IS IT A MAG-TAPE.
	IORM	T1,IFILE+STATUS		;SET IT.
OPNINP:	SKIPN	LSTWRD			;ARE WE GOING TO LIST IT.
	GOTO	OPNIP0			;NO JUMP.
	IF.OFF	OF,WILD			;SKIP IF NOT WILD.
	SETZM	OFILE+NAME		;CLEAR NAME IF WILD.
	OFF	OF,WILD			;TURN OFF WILD BITS.
	MOVEM	OF,OFILE+MOD		;SET INTO STORAGE.
	SKIPN	IFILE+NAME		;SKIP IF FILE NAME.
	IORI	IF,WNAME!WEXT		;ELSE MAKE NAME WILD.
	MOVEM	IF,IFILE+MOD		;SAVE THEM.
OPNIP0:	SKIPE	OFILE+NAME		;NAME SPECIFIED.
	GOTO	ONDEV			;YES ONTO THE DEVICE.
	MOVE	T2,[SIXBIT "OUTPUT"]	;NO SET DEFAULT.
	MOVEM	T2,OFILE+NAME		;SAVE.
	HRLZI	T2,'DAT'		;DEFAULT EXTENSION.
	MOVEM	T2,OFILE+EXT		;SAVE EXTENSION.
ONDEV:	SKIPE	IFILE+NAME		;NAME SPECIFIED.
	GOTO	OFFDEV			;YES TAKE IT OFF THE DEVICE.
	MOVE	T2,[SIXBIT "INPUT"]	;NO SET UP DEFAULT.
	MOVEM	T2,IFILE+NAME		;SAVE.
	HRLZI	T2,'DAT'		;SET UP DEFAULT EXTENSION.
	MOVEM	T2,IFILE+EXT		;SAVE THE EXTENSION FOR MME.
OFFDEV:	SKIPN	IM,INPMOD		;SKIP IF WE HAVE A MODE.
	MOVEI	IM,ASCMOD		;ELSE MAKE IT ASCII.
	MOVEM	IM,INPMOD		;SAVE THE MODE.
	SKIPN	OM,OUTMOD		;SKIP IF HAVE A MODE.
	MOVEI	OM,ASCMOD		;ELSE MAKE IT ASCII.
	MOVEM	OM,OUTMOD		;SAVE THE MODE.
	SKIPN	LSTWRD			;ARE WE GOING TO LIST.
	GOTO	CHKREC			;NO CHECK ON MODE.
	IF.OFF	IF,MTA!DSK!DTA,CANLST	;JUMP IF DEVICE CAN'T DO IT.
	CAIN	OM,OCTMOD		;CAN'T HAVE OCTAL OUTPUT.
	GOTO	BADMOD			;COMPLAIN.
	ON	IF,SCAN			;TURN ON THE SCAN BIT FOR MTA.
	MOVEM	IF,IFILE+MOD		;SAVE THEM.
	MOVEI	T1,^D80			;DEFAULT RECORD SIZE.
	MOVEM	T1,IFILE+RECSIZ		;SET THE RECORD SIZE.
	SETZM	IFILE+BLKFCT		;CLEAR BLOCKING FACTOR.
CHKREC:	MOVE	T1,IFILE+RECSIZ		;GET THE INPUT RECORD SIZE.
	SKIPN	OFILE+RECSIZ		;IF THERE IS NOT AN OUTPUT
	MOVEM	T1,OFILE+RECSIZ		;SIZE USE THE INPUT SIZE.
	CAIN	IM,OCTMOD		;IS INPUT OCTAL.
	GOTO	NOOCT			;CAN ONLY BE OUTPUT MODE.
	CAIE	IM,IMGMOD		;IS INPUT IMAGE.
	GOTO	TSTOUT			;NO CHECK ON THE OUTPUT MODE.
	CAIE	OM,OCTMOD		;IF INPUT IS IMAGE THEN
	CAIN	OM,IMGMOD		;OUTPUT MUST BE IMAGE OR OCTAL.
	SKIPA				;OUTPUT IS RIGHT.
	GOTO	MOD0ER			;MODE ERROR.
SETIMG:	MOVEI	T1,ONE			;BLOCKING FACTOR FOR IMAGE.
	CAIN	OM,OCTMOD		;SKIP IF NOT OCTAL MODE.
	SETZM	T1			;CLEAR BLOCKING FACTOR FOR OCTAL.
	MOVEM	T1,IFILE+BLKFCT		;SET AS BLOCKING FACTOR.
	MOVEM	T1,OFILE+BLKFCT		;SET AS OUTPUT BLOCKING FACTOR.
	MOVEI	T1,^D1000		;DEFAULT RECORD SIZE.
	SKIPN	IFILE+RECSIZ		;IS THERE A RECORD SIZE.
	MOVEM	T1,IFILE+RECSIZ		;SET OURS.
	SKIPN	OFILE+RECSIZ		;IS THERE AN OUTPUT ONE.
	MOVEM	T1,OFILE+RECSIZ		;SET THE DEFAULT.
	OFF	IF,SPAN			;CAN'T SPAN BLOCKS IN THIS MODE.
	MOVEM	IF,IFILE+MOD		;SAVE IN STORAGE.
	OFF	OF,SPAN			;CAN'T SPAN BLOCKS IN THIS MODE.
	MOVEM	OF,OFILE+MOD		;SAVE IN STORAGE.
	GOTO	TSTCOM			;GO SEE IF WE START.
TSTOUT:	CAIE	OM,OCTMOD		;IS OUTPUT OCTAL
	CAIN	OM,IMGMOD		;OR IMAGE. IF SO TEST
	SKIPA				;THE INPUT FOR IMAGE.
	GOTO	TSTCOM			;NONE OF THESE SO CONTINUE.
	MOVEI	IM,IMGMOD		;FORCE TO IMAGE INPUT.
	MOVEM	IM,IFILE+CHRMOD		;SAVE THE MODE.
	GOTO	SETIMG			;SET IMAGE MODE.
TSTCOM:	HLRZ	T1,RETWRD		;GET THE FLAG WORD FOR GO.
	SKIPE	T1			;SKIP IF IT IS TIME.
	GOTO	NTHERE			;ELSE DO THE COMMAND AGAIN.
	SETOM	RUNFLG			;SAY WE ARE NOW ACTIVE.
	MME	T1,.TIM			;GET OUR RUN TIME.
	MOVEM	T1,%TIME		;SAVE THE RUN TIME.
	OPEN	IF,IFILE+STATUS		;OPEN THE INPUT DEVICE.
	JSP	T1,NODEV		;CAN'T HAVE DEVICE.
	OPEN	OF,OFILE+STATUS		;OPEN OUTPUT DEVICE.
	JSP	T1,NODEV		;CAN'T HAVE DEVICE.
	MOVE	T1,IM			;SET ARGUMENTS FOR GETTAB.
	MOVE	T2,OM			;SET OTHER.
	GOSUB	GETTAB			;LOAD THE TABLES.
	HLRZ	T1,MSIZ(IM)		;GET THE INPUT BYTE SIZE.
	DPB	T1,[POINT 6,IBUF+1,11]	;SET THE BYTE SIZE.
	HLRZ	T1,MSIZ(OM)		;GET THE OUTPUT BYTE SIZE.
	DPB	T1,[POINT 6,OBUF+1,11]	;SET THE OUTPUT SIZE.
	MOVE	T1,STS(IM)		;GET THE INPUT STATUS BITS.
	IF.OFF	T1,NIR,CHKOUT		;JUMP IF DON'T NEED RECORD SIZE.
	SKIPN	IFILE+RECSIZ		;MAKE SURE WE HAVE IT.
	GOTO	NOIREC			;GET A RECORD SIZE.
CHKOUT:	MOVE	T1,STS(OM)		;GET THE OUTPUT BITS.
	IF.OFF	T1,NOR,CHKDEV		;JUMP IF DON'T NEED A RECORD SIZE.
	SKIPN	OFILE+RECSIZ		;ELSE MAKE SURE WE HAVE IT.
	GOTO	NOOREC			;GET A RECORD SIZE.
CHKDEV:	MOVE	T1,OFILE+DEVICE		;LOAD AC WITH NAME WE HAVE.
	MME	T1,.NAM			;GET THE REAL NAME.
	GOTO	SETINP			;FORGET IT IF MME FAILS.
	MOVE	T2,IFILE+DEVICE		;LOAD AC WITH OTHER'S NAME.
	MME	T2,.NAM			;GET ITS NAME.
	GOTO	SETINP			;JUMP IF MME FAILS.
	CAME	T1,T2			;SEE IF THEY MATCH.
	GOTO	SETINP			;NO MATCH SO O.K.
	HLRZS	T1			;EXCHANGE HALFS.
	CAIN	T1,'MTA'		;MTA CAN'T GO BOTH WAYS.
	GOTO	SAMDEV			;CAN'T DO INPUT AND OUTPUT TO ONE TAPE.
SUBTTL				*** DO YOUR THING ***

;HERE AFTER THE COMMAND DECODER TO SET UP BUFFERS
;IF DEVICE IS A MAG-TAPE.

SETINP:	MOVE	T1,.JBFF		;PICK UP THE CURRENT JOBFF.
	MOVEM	T1,IJOBFF		;SAVE FOR LATER.
	GOSUB	MONIBF			;GET SOME BUFFERS.
	IF.OFF	OF,MTA,SETIP		;IS OUTPUT DEVICE A MAG-TAPE.
	IF.ON	OF,BWIND		;SHOULD WE MOVE THE TAPE.
	DRIVE	OF,.REW			;REWIND THE TAPE.
SETIP:	IF.OFF	IF,MTA,SETOUT		;JUMP IF NOT MAG-TAPE.
	IF.ON	IF,BWIND		;SHOULD WE REWIND INPUT.
	DRIVE	IF,.REW			;BACK TO LOAD POINT.
	MOVEI	T1,IBUF			;GET POINTER TO BUFFER HEADER.
	MOVEI	SIDE,IFILE		;GET POINTER TO PARAMETERS.
	GOSUB	MAKE			;BUILD THE BUFFERS.

;HERE TO SET UP THE OUTPUT BUFFERS IF MAG-TAPE
;IS THE OUTPUT DEVICE.

SETOUT:	MOVE	T1,.JBFF		;COPY JOB FIRST FREE.
	MOVEM	T1,OJOBFF		;STORE FOR LATER.
	GOSUB	MONOBF			;GET SOME BUTTERS.
	IF.OFF	OF,MTA,POSINP		;START NOW IF THIS ISN'T A MAG-TAPE.
	MOVEI	T1,OBUF			;GET POINTER TO BUFFER HEADER.
	MOVEI	SIDE,OFILE		;GET POINTER TO PARAMETERS.
	GOSUB	MAKE			;BUILD THE BUFFERS.
;HERE TO POSITION THE TAPES IF WE HAVE TAPES.

POSINP:	IF.OFF	IF,MTA,POSOUT		;JUMP IF NO INPUT TAPE.
	DRIVE	IF,.WAT			;STOP THE TAPE.
	MOVE	P1,IFILE+ADVAN		;GET THE ADVANCE COUNT.
	SUB	P1,IFILE+BACSPC		;SUBTRACT BACKSPACE COUNTER.
	JUMPE	P1,POSOUT		;JUMP IF ALRIGHT.
	JUMPG	P1,POSI0		;JUMP IF ADVANCE.
	MOVNS	P1			;MAKE COUNT POSITIVE.
	SKIPA	P2,[DRIVE IF,.BSF]	;TO GO BACKWARDS.
POSI0:	MOVE	P2,[GOSUB SKPFIL]	;TO GO FORWARDS.
	XCT	P2			;MOVE THE TAPE.
	DRIVE	IF,.WAT			;WAIT FOR IT.
	SOJG	P1,.-2			;COUNT DOWN COUNTER.
	CAME	P2,[DRIVE IF,.BSF]	;DID WE GO BACKWARDS.
	GOTO	POSOUT			;NO.
	STATO	IF,E.BOT		;AT BEGINNING OF TAPE.
	DRIVE	IF,.SKR			;NO SKIP TAPE MARK.
POSOUT:	IF.OFF	OF,MTA,DYT		;JUMP IF NOT OUTPUT MTA.
	DRIVE	OF,.WAT			;BE SURE IT IS STOPPED.
	MOVE	P1,OFILE+ADVAN		;GET THE ADVANCE COUNTER.
	SUB	P1,OFILE+BACSPC		;SUBTRACT BACKSPACE COUNTER.
	JUMPE	P1,DYT			;JUMP IF TAPES ARE O.K.
	JUMPG	P1,POSO0		;JUMP IF ADVANCE.
	MOVNS	P1			;MAKE COUNT POSITIVE.
	SKIPA	P2,[DRIVE OF,.BSF]	;TO GO BACKWARDS.
POSO0:	MOVE	P2,[DRIVE OF,.SKF]	;TO GO FORWARDS.
	XCT	P2			;MOVE THE TAPE.
	DRIVE	OF,.WAT			;WAIT FOR IT.
	SOJG	P1,.-2			;COUNT DOWN COUNTER.
	CAME	P2,[DRIVE OF,.BSF]	;DID WE GO BACKWARDS.
	GOTO	DYT			;NO...
	STATO	OF,E.BOT		;AT BEGINNING OF TAPE.
	DRIVE	OF,.SKR			;SKIP TAPE MARK.
;HERE TO START THE BALL OF WAX ROLLING.

DYT:	GOSUB	LOKWLD			;GET A FILE NAME.
	GOTO	NOWLD			;NONE TO GET.
GETINP:	TEO	S,FFLG,CREIT		;JUMP IF FIRST TIME.
	IF.OFF	OF,WNAME!WEXT,INIMOD	;JUMP IF NOT WILD.
CREIT:	IF.ON	IF,WNAME!WEXT		;SKIP IF HAVE A NAME.
	IF.OFF	OF,WNAME!WEXT,CREATE	;JUMP IF NORMAL OUTPUT.
	MOVE	P1,IFILE+NAME		;GET THE NAME OF THE INPUT.
	MOVE	P2,IFILE+EXT		;GET ITS EXTENSION.
	GOSUB	MOVNM0			;GET THE NAME OF THE OUTPUT.
	GOSUB	ABORT			;ALWAYS SKIPS.
CREATE:	IF.OFF	OF,MTA			;SKIP IF NOT MTA.
	GOSUB	OUTLAB			;ELSE WRITE A LABEL.
	IF.OFF	OF,LPT			;SKIP IF NOT LPT.
	GOSUB	HDRLPT			;PUT OUT A HEADING.
	IF.OFF	OF,DIR,INIMOD		;JUMP IF ENTER DOES NOTHING.
	SAVE	OFILE+PPN		;SAVE THE PPN WORD.
	HLLZS	OFILE+EXT		;CLEAR DATE.
	SETZM	OFILE+DATTIM		;CLEAR OTHER HALF.
	ENTER	OF,OFILE+NAME		;CREATE A FILE.
	GOTO	NOOPN			;CAN'T DO IT.
	UNSAVE	OFILE+PPN		;RESTORE IT.
INIMOD:	MOVEI	SIDE,OFILE		;INDEX FOR OUTPUT FILE.
	GOSUB	SECTOR			;COMPUTE SECTORS NEEDED.
	MOVEI	SIDE,IFILE		;INDEX FOR THE INPUT FILE.
	SKIPN	LSTWRD			;SKIP IF LISTING.
	SKIPE	TELWRD			;SKIP IF WANTS TO KNOW.
	GOTO	PROCED			;ELSE SKIP IT.
	IF.OFF	IF,WILD,PROCED		;JUMP IF INPUT ISN'T WILD.
	IF.OFF	OF,TTY			;SKIP IF OUTPUT ISN'T TO TTY.
	EME	.CH,[EXP 12]		;FORM THE PAGE.
	MOVE	T1,PRGNAM		;GET OUR NAME.
	GOSUB	PUTSIX			;PRINT IT.
	EME	.STR,[ASCIZ ": "]	;DELIMIT THE NAME.
	MOVE	P4,IFILE+MOD		;GET THE MOD BITS.
	OFF	P4,WILD			;TURN OFF WILD BITS.
	GOSUB	TYPNM0			;PRINT IT.
	GOSUB	CRLF			;SKIP A LINE.
PROCED:	GOSUB	SECTOR			;GET THE INPUT SECTORS.
	MOVE	OCNT,OFILE+BLKFCT	;GET THE OUTPUT BLOCKING FACTOR.
	MOVE	ICNT,IFILE+BLKFCT	;GET THE INPUT BLOCKING FACTOR.
	SKIPE	LSTWRD			;SKIP IF LISTING.
	GOTO	PROD1			;JUMP WHEN LISTING.
	GOSUB	FILL			;GET THE FIRST BUFFER.
	GOTO	ENDCOP			;FILE IS ZERO LENGTH.
	AOS	IRCNT			;COUNT FIRST RECORD.
	AOS	IBCNT			;COUNT FIRST BLOCK.
PROD1:	GOSUB	@OUTI(OM)		;INITIALIZE OUTPUT.
	SKIPE	LSTWRD			;SKIP IF LISTING.
	GOTO	INILST			;GOT LIST A DIRECTORY.
	GOSUB	@INI(IM)		;DISPATCH.
SUBTTL				*** END OF CONVERSION ***

;HERE WHEN WE ARE DONE WITH A FILE.

ENDCOP:	AOS	IFCNT			;COUNT THE FILE.
	IF.OFF	OF,TTY			;SKIP IF NOT TTY.
	CLOSE	OF,ZERO			;FORCE TTY BUFFERS OUT.
	ENABLE	TTY			;CLEAR CONTROL O.
	CLOSE	IF,ZERO			;CLOSE INPUT FILE.
	GETSTS	IF,T1			;GET STATUS ON CLOSE.
	IF.OFF	T1,E.ERR		;ERROR DURING CLOSE.
	PRINT	(% Error during close of input file.)
CLOOUT:	OFF	S,PRG!FREAD		;CLEAR PERGE BIT AND FIRST READ BIT.
	IF.OFF	IF,WILD,CLO1		;IF NOT WILD INPUT CLOSE.
	IF.OFF	OF,WNAME!WEXT,NXTONE	;JUMP IF NOT WILD OUTPUT.
CLO1:	AOS	OFCNT			;COUNT OUTPUT FILE.
	IF.OFF	OF,LPT			;SKIP IF NOT LPT.
	GOSUB	EOFLPT			;PUT OUT A HEADING.
	CLOSE	OF,ZERO			;WRITE AN EOF MARK.
CLO2:	GETSTS	OF,T1			;TEST FOR ERRORS.
	IF.OFF	T1,E.ERR		;ANY ERRORS.
	PRINT	(? Error during close of output file.)
	IF.OFF	OF,MTA			;WRITE EOF LABEL IF MAG-TAPE.
	GOSUB	EOFLAB			;WRITE A TRAILER.
	IF.ON	IF,WILD,NXTONE		;JUMP IF WILD INPUT.
CLO3:	IF.OFF	IF,MTA!DTA,CLO4		;JUMP IF NOT MAG-TAPE.
	IF.OFF	IF,UNLOAD		;SHOULD WE UNLOAD IT.
	DRIVE	IF,.UNL			;YES UNLOAD IT.
	IF.ON	IF,AWIND		;SKIP IF CAN MOVE IT.
	IF.ON	IF,DTA,CLO4		;JUMP IF DECTAPE.
	IF.ON	IF,UNLOAD		;IF NOT UNLOAD AT LEAST
	DRIVE	IF,.REW			;REWIND IT.
CLO4:	IF.OFF	OF,MTA!DTA,CLO5		;JUMP IF OUTPUT ISN'T MTA OR DTA.
	IF.OFF	OF,UNLOAD		;SKIP IF CAN'T UNLOAD IT.
	DRIVE	OF,.UNL			;REWIND AND UNLOAD.
	IF.ON	OF,AWIND		;SKIP IF CAN'T MOVE IT.
	IF.ON	OF,DTA,CLO5		;DON'T REWIND DECTAPES.
	IF.ON	OF,UNLOAD		;IF NOT UNLOAD AT LEAST
	DRIVE	OF,.REW			;REWIND.
CLO5:	GOSUB	STAT			;THEN TELL HIM GOOD THINGS.
	GOTO	NTHERE			;START AGAIN.
NXTONE:	GOSUB	GETNXT			;GET THE NEXT FILE.
	GOTO	NOMORE			;NO MORE TO GET.
	IF.OFF	OF,WNAME!WEXT,GETINP	;DON'T CLEAR COUNTERS IF NOT WILD.
	SETZM	ORCNT			;CLEAR RECORD COUNTER FOR OUTPUT.
	SETZM	OBCNT			;CLEAR BLOCK COUNTER.
	GOTO	GETINP			;PROCESS THE FILE.
NOMORE:	MOVEI	T1,CLO1			;GET A DISPATCH ADDRESS.
	IF.OFF	OF,WNAME!WEXT		;SKIP IF WILD OUTPUT.
	MOVEI	T1,CLO3			;ELSE CHANGE DISPATCH.
	OFF	IF,WILD			;TURN OFF WILD BITS.
	OFF	OF,WILD			;IN BOTH SPECS.
	GOTO	ZERO(T1)		;DISPATCH.
SUBTTL				*** READ/WRITE LOOP ***

;HERE TO COUNT THE NEXT RECORD AND READ A BLOCK IF
;IT IS TIME.

RENEW:	SOJLE	ICNT,REN1		;JUMP IF TIME FOR A BLOCK.
REN0:	AOS	IRCNT			;COUNT THE RECORD.
	RETURN	ONE			;GIVE GOOD RETURN.
REN1:	SKIPE	ICNT,IFILE+BLKFCT	;SKIP IF THERE IS A BLOCKING FACTOR.
	IF.ON	IF,SPAN,REN5		;JUMP IF SPANNING.
	IF.OFF	IF,DIR!MTA,REN5		;JUMP IF NOT DSK, DTA, OR MTA.
REN2:	MOVE	T1,ISEC			;GET THE SECTORS READ.
	CAML	T1,IBLK			;HAVE WE READ ENOUGH.
	GOTO	REN3			;YES READ THE NEXT DATA BLOCK.
	GOSUB	FILL			;SKIP OVER A BLOCK.
	RETURN	ZERO			;END OF FILE.
	GOTO	REN2			;TEST AGAIN.
REN3:	SETZM	ISEC			;RESET SECTORS READ.
	GOSUB	FILL			;GET A BLOCK.
	RETURN	ZERO			;EOF FOUND.
REN4:	AOS	IBCNT			;COUNT THE BLOCK.
	GOTO	REN0			;GO COUNT THE RECORD.
REN5:	TNO	S,FREAD,REN4		;JUMP IF NOT FIRST TIME HERE.
	RETURN	ONE			;ELSE RETURN WITHOUT COUNTING.

;HERE TO SET THE COUNT RIGHT WHEN WE FINISH IN THE MIDDLE
;OF A RECORD FOR AN UNBLOCKED FILE.

SETCNT:	SETOM	OCNT			;FLAG WE WRITE BLOCK.
	SKIPE	IFILE+BLKFCT		;IS IT BLOCKED.
	RETURN	ZERO			;NO RETURN.
	AOS	IRCNT			;COUNT THE RECORD.
	AOS	IBCNT			;COUNT THE BLOCK.
	RETURN	ZERO			;RETURN TO CALLER.

;HERE TO CONVERT THE CHARACTER AND CALL THE
;OUTPUT ROUTINE.

CHANGE:	HRRZ	CH,TAB1(CH)		;CONVERT IT.
	TEZ	CH,NEC			;IS THIS A BAD CHARACTER.
	AOS	NOCHR			;YES COUNT IT.
	GOTO	@OUTC(OM)		;STACH THE CHARACTER.
;HERE TO WRITE THE CURRENT BLOCK AND TO SEE IF WE MUST
;WRITE SOME BLANK ONES TO FILL OUT THE BLOCKING FACTOR.

UPDAT:	CAME	OCNT,OFILE+BLKFCT	;ARE WE AT A BLOCK BOUNDARY.
	GOTO	UPDA			;NO SO WRITE THIS BLOCK.
	RETURN	ZERO			;RETURN NOTHING TO WRITE.
UPDATE:	AOS	ORCNT			;COUNT THE RECORD PROCESSED.
	SOSLE	OCNT			;TIME FOR A NEW BLOCK.
	RETURN	ZERO			;NO BACK TO CALLER.
UPDA:	AOS	OBCNT			;COUNT THE BLOCK.
	GOSUB	@OUTB(OM)		;FINISH BLOCK OFF.
	GOSUB	CHKOPR			;CHECK OPERATOR COMMAND.
UPD0:	SKIPE	OCNT,OFILE+BLKFCT	;IS THERE NO BLOCKING FACTOR.
	IF.OFF	OF,SPAN			;OR ARE WE SPANNING.
	RETURN	ZERO			;IF SO RETURN.
	IF.ON	OF,DIR!MTA		;IF NOT DSK, DTA, OR MTA
	RETURN	ZERO			;DEVICE THEN RETURN.
	GOSUB	EMPTY			;TO THE DEVICE.
UPD1:	MOVE	T1,OSEC			;GET THE SECTORS WRITTEN.
	CAML	T1,OBLK			;HAVE WE WRITTEN ENOUGH.
	GOTO	UPD2			;YES IT IS ALRIGHT.
	IBP	OBUF+1			;SO IT WILL WRITE.
	SOS	OBUF+2			;DECREMENT COUNT.
	GOSUB	EMPTY			;WRITE EMPTY ONES.
	GOTO	UPD1			;CONTINUE LOOP.
UPD2:	SETZM	OSEC			;RESET SECTOR COUNTER.
	RETURN	ZERO			;AND RETURN.
SUBTTL			*** LIST I/O ROUTINES ***

INILST:	ON	S,NI.LST		;TURN NO ERROR BIT ON.
	SETZM	LABTOT			;CLEAR TOTAL BLOCKS.
	SETZM	LABCNT			;CLEAR TOTAL FILES.
	SETZM	LSTSTR			;CLEAR LAST STRUCTURE FOUND.
	SETZM	LSTPPN			;CLEAR LAST PPN FOUND.
IN0LST:	IF.OFF	IF,MTA,IN1LST		;JUMP IF INPUT ISN'T MTA.
	SETZM	LABSIZ			;CLEAR FILE SIZE.
INMLST:	GOSUB	FILL			;FILL UP THE BUFFER.
	GOTO	INELST			;FOUND EOF.
	AOS	LABSIZ			;COUNT THE BLOCK IN THIS FILE.
	AOS	IBCNT			;ACCUMULATE BLOCKS.
	GOSUB	CHKOPR			;CHECK FOR A COMMAND.
	GOTO	INMLST			;DO IT AGAIN.
INELST:	GETSTS	IF,T1			;GET THE DEVICE STATUS.
	IF.OFF	T1,E.EOT,IN1LST		;JUMP IF ERROR WASN'T EOT.
	SKIPE	IFILE+LABEL		;SKIP IF NOT LABELS.
	GOTO	INMLST			;ELSE FIND THE LABEL.
IN1LST:	MOVEI	T1,ASCMOD		;MUST HAVE ASCII INPUT TABLES.
	MOVE	T2,OM			;GET THE OUTPUT INDEX.
	GOSUB	GETTAB			;GET THE RIGHT TABLES.
	MOVS	T1,LABNAM+1		;GET THE EXTENSION.
	CAIE	T1,'UFD'		;IS THIS A UFD.
	GOTO	INFLST			;NO LIST A FILE.
	HLRZ	T1,LABNAM		;GET THE PROJECT NUMBER.
	GOSUB	INOLST			;LIST AN OCTAL NUMBER.
	MOVEI	CH,","			;TO SEPARATE THINGS.
	GOSUB	CHANGE			;PUT THE CHARACTER AWAY.
	HRRZ	T1,LABNAM		;GET THE OTHER HALF.
	GOSUB	IN3LST			;PRINT IT.
	SOJLE	P1,INULST		;JUMP IF DONE ENOUGH.
	MOVEI	CH," "			;LOAD A SPACE.
	GOSUB	CHANGE			;PUT IT AWAY.
	GOTO	.-3			;CONTINUE ON.
INULST:	UME	.ASC,[ASCIZ "  "]	;TAB TO NEXT ZONE.
	GOTO	INXLST			;DO THE REST.
INFLST:	UME	.SIX,LABNAM		;TYPE THE NAME.
	UME	.ASC,[ASCIZ "   "]	;TAB A LITTLE.
	UME	.SIX,LABNAM+1		;TYPE THE EXTENSION.
INXLST:	SKIPN	FSTWRD			;SKIP IF FAST LIST.
	GOSUB	IN4LST			;TYPE OTHER GOOD THINGS.
	MOVE	T1,LABSTR		;GET THIS STRUCTURE.
	CAMN	T1,LSTSTR		;SKIP IF DIFFERENT FROM LAST.
	GOTO	IN2LST			;DON'T TYPE IF THE SAME.
	MOVEM	T1,LSTSTR		;SAVE AS THE LAST ONE.
	MOVE	P1,[POINT 6,LABSTR]	;POINTER TO STORAGE.
IN6LST:	ILDB	CH,P1			;GET A CHARACTER.
	JUMPE	CH,IN7LST		;JUMP IF DONE.
	MOVEI	CH," "(CH)		;CONVERT TO ASCII.
	GOSUB	CHANGE			;STORE IT AWAY.
	IF.ON	P1,77B5,IN6LST		;JUMP IF MORE.
IN7LST:	UME	.ASC,[ASCIZ ":   "]	;TAB A LITTLE.
IN2LST:	SKIPN	P1,LABPPN		;SKIP IF A PPN IS THERE.
	GOTO	IN8LST			;ELSE SKIP AHEAD.
	CAMN	P1,LSTPPN		;SKIP IF DIFFERENT.
	GOTO	IN8LST			;ELSE SKIP AHEAD.
	MOVEM	P1,LSTPPN		;SAVE AS THE LAST PPN.
	MOVEI	CH,"["			;TO SPECIFY PPN COMING.
	GOSUB	CHANGE			;PUT IT AWAY.
	HLRZ	T1,P1			;GET THE PROJECT NUMBER.
	GOSUB	IN3LST			;PRINT IT.
	MOVEI	CH,","			;TO SEPARATE P FROM PN.
	GOSUB	CHANGE			;PRINT IT.
	HRRZ	T1,LABPPN		;GET THE OTHER HALF.
	GOSUB	IN3LST			;PRINT IT.
	MOVEI	CH,"]"			;TO FINISH IT OFF.
	GOSUB	CHANGE			;SEND IT.
IN8LST:	GOSUB	@OUTR(OM)		;CALL OUTPUT ROUTINE TO FINISH RECORD.
	IF.OFF	OF,TTY			;SKIP IF NOT TTY.
	GOSUB	EMPTY			;ELSE EMPTY THE BUFFER.
	IF.OFF	IF,MTA,INNLST		;GET NEXT IF NOT MTA.
	GETSTS	IF,T1			;GET THE DEVICE STATUS.
	IF.ON	T1,E.EOT,INDLST		;IF EOT WE ARE DONE.
INNLST:	GOSUB	NXTGET			;GET THE NEXT ONE.
	GOTO	IN0LST			;CARRY ON.
INDLST:	GOSUB	@OUTR(OM)		;SKIP A LINE.
	SKIPE	FSTWRD			;SKIP IF NORMAL LIST.
	GOTO	INZLST			;FINISH UP.
	UME	.ASC,[ASCIZ "   Total of "]
	MOVE	T1,LABTOT		;TOTAL BLOCKS.
	GOSUB	IN3ALT			;ENTER IT.
	UME	.ASC,[ASCIZ " blocks in "]
	MOVE	T1,LABCNT		;TOTAL FILES.
	GOSUB	IN3ALT			;ENTER IT.
	UME	.ASC,[ASCIZ " files."]
	GOSUB	@OUTR(OM)		;FINISH LINE.
INZLST:	GOSUB	@OUTF(OM)		;FINISH OFF THE FILE.
	OFF	IF,WILD			;TURN OFF WILD BITS.
	OFF	S,NI.LST		;TURN OFF NO ERROR BIT.
	GOTO	ENDCOP			;ALL DONE HERE.
NXTGET:	GOSUB	STORE			;SAVE THE AC'S.
	GOSUB	GETNXT			;GET THE NEXT FILE.
	RETURN	ONE			;NONE TO GET.
	RETURN	ZERO			;RETURN WITH NEXT.
IN3LST:	SKIPA	P2,[10]			;SET BASE TO BASE 8.
IN3ALT:	MOVEI	P2,^D10			;SET BASE TO BASE 10.
	MOVEI	P1,^D7			;SO WE KNOW HOW MANY WENT.
	IDIVI	T1,ZERO(P2)		;SLICE OFF A DIGIT.
	HRLM	T2,ZERO(PDP)		;SAVE A DIGIT.
	SOS	P1			;COUNT THE DIGIT.
	SKIPE	T1			;SKIP IF DONE.
	GOSUB	IN3ALT+2		;DO THE NEXT ONE.
	HLRZ	CH,ZERO(PDP)		;GET A DIGIT.
	MOVEI	CH,"0"(CH)		;MAKE IT ASCII.
	GOTO	CHANGE			;PUT IT AWAY...
IN4LST:	AOS	LABCNT			;COUNT THE FILE.
	MOVE	T1,LABSIZ		;GET THE FILE SIZE.
	ADDM	T1,LABTOT		;UPDATE THE TOTAL.
	GOSUB	IN9LST			;ENTER IT.
	UME	.ASC,[ASCIZ "   <"]	;FLAG PROTECTION COMING.
	LDB	T1,[POINT 9,LABDTW,8]	;GET THE PROTECTION.
	MOVEI	CH,"0"			;IF WE MUST PAD.
	CAIG	T1,77			;SKIP IF NOT NEED.
	GOSUB	CHANGE			;PAD A ZERO.
	CAIG	T1,7			;SEE IF NEED ANOTHER.
	GOSUB	CHANGE			;PUT IT IN.
	GOSUB	IN3LST			;PLACE IT.
	UME	.ASC,[ASCIZ ">   "]	;FINISH IT OFF.
	HRRZ	T1,LABDTW		;GET THE DATE.
	GOSUB	PUTXDT			;PRINT THE DATE.
	UME	.ASC,[ASCIZ "   "]	;TO NEXT ZONE.
	RETURN	ZERO			;BACK TO CALLER.
INOLST:	SKIPA	P2,[10]			;SET THE BASE.
IN9LST:	MOVEI	P2,^D10			;SET THE BASE.
	MOVEI	P1,^D7			;CHARACTERS TO PRINT.
I90LST:	IDIVI	T1,ZERO(P2)		;SLICE OFF A DIGIT.
	HRLM	T2,ZERO(PDP)		;SAVE THE DIGIT.
	SOS	P1			;COUNT THE DIGIT.
	JUMPN	T1,I92LST		;JUMP IF MORE.
I91LST:	MOVEI	CH," "			;LOAD A SPACE.
	SOJLE	P1,I93LST		;JUMP IF ENOUGH.
	GOSUB	CHANGE			;FILL WITH A SPACE.
	GOTO	I91LST			;CHECK AGAIN.
I92LST:	GOSUB	I90LST			;GET THE NEXT ONE.
I93LST:	HLRZ	CH,ZERO(PDP)		;GET A DIGIT.
	MOVEI	CH,"0"(CH)		;CONVERT IT TO ASCII.
	GOTO	CHANGE			;PUT IT AWAY.
SUBTTL			*** ASCII I/O ROUTINES ***

;HERE TO READ ASCII CHARACTERS FROM THE INPUT
;FILE AND SEND THEM TO THE OUTPUT FILES. HANDLES SEVEN
;EIGHT, OR NINE BIT ASCII.

INIASC:	SKIPN	P2,IFILE+RECSIZ		;LOAD THE RECORD SIZE.
	HRLOI	P2,377777		;IF NO RECORD SIZE.
IN5ASC:	MOVEI	P1,^D8			;TAB COUNT.
IN0ASC:	GOSUB	GET			;GET A CHARACTER.
	GOTO	@OUTF(OM)		;END OF FILE.
	ANDI	CH,177			;JUST THE DATA BITS.
	JUMPE	CH,IN0ASC		;IGNORE NULLS.
	CAIN	CH,15			;IS IT END OF RECORD.
	GOTO	IN1ASC			;YES PROCESS EOR.
	CAIN	CH,11			;IS IT A TAB.
	GOTO	IN2ASC			;TAKE CARE OF IT.
IN3ASC:	GOSUB	CHANGE			;SEND IT.
	IF.OFF	IF,NOCRLF		;SKIP IF CRLF'S ARE EXPECTED.
	SOJLE	P2,IN6ASC		;JUMP IF END OF RECORD.
	SOJG	P1,IN0ASC		;JUMP IF TAB IS GOOD.
	GOTO	IN5ASC			;CONTINUE ON.
IN1ASC:	IF.OFF	IF,NOCRLF,IN9ASC	;JUMP IF CRLF'S ARE EXPECTED.
	SKIPE	IFILE+RECSIZ		;IS THERE A RECORD SIZE.
	GOTO	BADFOM			;CAN'T HAVE RECSIZ IF CRLF PRESENT.
IN9ASC:	GOSUB	GET			;GET THE NEXT CHARACTER.
	GOTO	@OUTF(OM)		;END OF FILE FOUND.
	ANDI	CH,177			;JUST THE DATA BITS.
	JUMPE	CH,IN1ASC		;IGNORE NULLS.
	CAIE	CH,12			;IS IT A LINE FEED.
	ON	S,BAC			;NO SO REGET IT.
IN6ASC:	GOSUB	RENEW			;HANDLE END OF RECORD.
	GOTO	@OUTF(OM)		;END OF FILE FOUND.
	GOSUB	@OUTR(OM)		;FINISH THE OUTPUT RECORD.
	GOTO	INIASC			;CONTINUE ON.
IN2ASC:	MOVE	T1,STS(OM)		;GET THE OUTPUT STATE WORD.
	IF.ON	T1,TAB,IN3ASC		;JUMP IF OUTPUT HAS TABS
IN4ASC:	MOVEI	CH," "			;LOAD A SPACE.
	GOSUB	CHANGE			;INTO OUTPUT BUFFER.
	SOJG	P1,IN4ASC		;CONTINUE FOR TAB COUNT.
	GOTO	IN5ASC			;RESET THE TAB COUNTER.

EQUATE	INIASC,<INIGEA,INIHPA>
;HERE TO INITIALIZE THE ASCII OUTPUT ROUTINE.

OTIASC:	MOVE	P3,OFILE+RECSIZ		;SET UP RECORD SIZE.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO ENTER ONE ASCII CHARACTER INTO THE OUTPUT BUFFER.

OTCASC:	JUMPE	CH,RET0			;DON'T SAVE NULLS.
	OFF	S,EOR			;NOT AT RECORD END NOW.
	SOJL	P3,OT0ASC		;JUMP IF RECORD IS FULL.
	GOSUB	PUT			;WRITE THE CHARACTER.
OT0ASC:	CAIG	CH,24			;IS IT A SPECIAL CHARACTER.
	GOTO	OT2ASC			;YES SEE IF SPECIAL CHARACTER.
OT1ASC:	OFF	S,FF			;NOT AT TOP OF FORM.
	RETURN	ZERO			;BACK TO CALLER.
OT2ASC:	CAIE	CH,12			;IS IT A LINE FEED.
	CAIN	CH,13			;OR VERTICAL TAB.
	GOTO	OT3ASC			;YES NO LONGER AT THE TOP.
	CAIL	CH,21			;DEVICE CONTROL CHARACTER.
	GOTO	OT3ASC			;YES NOT AT TOP ANY MORE.
	CAIE	CH,14			;IS IT A FORM FEED.
	GOTO	OT1ASC			;NO SO EXIT.
	TROA	S,FF			;NOW AT TOP OF PAGE.
OT3ASC:	OFF	S,FF			;NOT AT TOP OF FORM.
	GOTO	OTIASC			;RESET RECORD COUNTER. FOR THESE.

;HERE TO FINISH OFF THE ASCII RECORD.

OTRAC0:	GOSUB	SETCNT			;SET UP COUNTERS.
OTRASC:	ON	S,EOR			;AT END OF RECORD.
	IF.OFF	OF,NOCRLF,OTRAS1	;JUMP IF FILE CAN HAVE CRLF'S.
	MOVEI	CH," "			;SPACE FILL THE RECORD.
	GOSUB	OTCASC			;UNTIL THE COUNTER RUNS OUT.
	JUMPGE	P3,.-2			;UNTIL IT FINISHES CONTINUE.
	IF.ON	OF,MTA!DTA!DSK,OTRAS2	;JUMP UNLESS THIS IS AN ASCII ONLY DEVICE.
OTRAS1:	MOVEI	CH,15			;GET A RETURN.
	GOSUB	PUT			;INTO THE BUFFER.
	MOVEI	CH,12			;AND A LINE FEED.
	GOSUB	PUT			;INTO THE BUFFER.
OTRAS2:	GOSUB	UPDATE			;COUNT RECORD WRITTEN.
	GOTO	OTIASC			;RE-INITIALIZE.

;HERE ON INPUT END OF FILE TO FINISH OFF THE OUTPUT FILE.

OTFASC:	IF.OFF	S,EOR,OTRAC0		;FINISH THIS RECORD IF NEEDED.
	GOTO	UPDAT			;ELSE CHECK ON THE BLOCK.

EQUATE	RET0,<OTBASC>
EQUATE	OTIASC,<OTIGEA,OTIHPA>
EQUATE	OTCASC,<OTCGEA,OTCHPA>
EQUATE	OTRASC,<OTRHPA,OTRGEA>
EQUATE	OTBASC,<OTBGEA,OTBHPA>
EQUATE	OTFASC,<OTFGEA,OTFHPA>
SUBTTL		*** IMAGE I/O ROUTINES ***

;HERE TO READ A FILE IN BUFFER MODE AND EITHER BLT THE
;INPUT BUFFER TO THE OUTPUT BUFFER IF GOING IMAGE TO IMAGE
;OR TO PASS A WORD AT TIME IF GOING FROM IMAGE TO OCTAL.

INIIMG:	CAIN	OM,IMGMOD		;IS OUTPUT IMAGE.
	GOTO	IMGBLT			;YES USE BLT'S.
	MOVE	P1,ISEC			;GET THE SECTORS READ.
IN0IMG:	GOSUB	GET			;GET A WORD.
	GOTO	@OUTF(OM)		;END OF FILE.
	GOSUB	@OUTC(OM)		;GET RID OF A WORD.
	CAMN	P1,ISEC			;DID WE READ A BLOCK.
	GOTO	IN0IMG			;NO CONTINUE.
	AOS	P1,IBCNT		;COUNT THE BLOCK.
	AOS	IRCNT			;COUNT THE RECORD.
	GOTO	IN0IMG			;CARRY ON.
IMGBLT:	AOS	ORCNT			;COUNT THE RECORD CLOSE WRITES.
	AOS	OBCNT			;COUNT THE BLOCK CLOSE WRITES.
IMGBT1:	SKIPG	OBUF			;HAS AN OUTPUT BEEN DONE.
	OUTPUT	OF,ZERO			;DO ONE TO SET THE RING AS USED.
	AOS	IBUF+1			;GET A POINTER TO THIS BUFFER.
	SETZM	OSEC			;CLEAR SECTORS WRITTEN.
IMGBT0:	HRLZ	T1,IBUF+1		;C(T1)LH IS SOURCE POINTER.
	MOVE	T2,OBUF+2		;C(T2) SIZE OF THE TARGET.
	MOVE	T3,IBUF+2		;C(T3) SIZE OF THE SOURCE.
	CAML	T2,T3			;WILL SOURCE FIT IN TARGET.
	MOVE	T2,T3			;COPY WHAT IS LEFT.
	ADDM	T2,IBUF+1		;UPDATE POINTER.
	MOVE	P1,IBUF+2		;GET THE COUNT LEFT.
	SUB	P1,T2			;ACCOUNT FOR WORDS TO MOVE.
	MOVEM	P1,IBUF+2		;UPDATE THE COUNT.
	GOSUB	BUF2			;MOVE THE BUFFER.
	SKIPN	OBUF+2			;IS OUTPUT BUFFER FULL.
	GOSUB	EMPTY			;WRITE BUFFER.
	SKIPLE	IBUF+2			;SKIP IF BUFFER IS ALL GONE.
	GOTO	IMGBT0			;GET THE NEXT SECTION.
	MOVE	P1,OSEC			;GET BLOCKS WRITTEN.
	ADDM	P1,OBCNT		;UPDATE BLOCK COUNT.
	ADDM	P1,ORCNT		;UPDATE RECORD COUNT.
	GOSUB	FILL			;GET THE NEXT BUFFER.
	RETURN	ZERO			;NONE TO GET.
	AOS	IRCNT			;COUNT THE RECORD.
	AOS	IBCNT			;COUNT THE BLOCK.
	GOSUB	CHKOPR			;CHECK FOR COMMAND.
	GOTO	IMGBT1			;DO THE NEXT ONE.

EQUATE	RET0,<OTIIMG>
EQUATE	ABORT,<OTCIMG,OTRIMG,OTBIMG,OTFIMG>
SUBTTL		*** OCTAL OUTPUT ROUTINE ***

;HERE TO DUMP A FILE IN OCTAL MODE.

OTIOCT:	ON	S,LHEAD			;CAN'T USE US TO STORE CHARACTERS.
	SETZM	OT0TMP			;CLEAR WORD COUNTER.
	IF.ON	OF,TTY			;SKIP IF TTY OUTPUT.
	UME	.ASC,[BYTE (7)14,0]	;SEND A FORM FEED.
OT0OCT:	MOVEI	P3,5			;WORDS PER LINE IF TTY.
	IF.ON	OF,TTY			;SKIP IF TTY IS OUTPUT DEVICE.
	MOVEI	P3,11			;WORDS PER LINE IF OTHER DEVICE.
	MOVEM	P3,OT1TMP		;SAVE WORDS PER LINE.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO DUMP ONE WORD ONTO THE OUTPUT DEVICE.

OTCOCT:	CAMN	P3,OT1TMP		;ARE WE AT A NEW LINE.
	GOTO	OT4OCT			;YES HANDLE NEW LINE STUFF.
OT1OCT:	MOVE	P4,[POINT 3,T3]		;GET A POINTER TO DATA.
	MOVE	T3,CH			;COPY OUTPUT WORD.
	UME	.ASC,[ASCIZ "   "]	;SEPARATE THINGS.
OT2OCT:	ILDB	CH,P4			;GET A CHARACTER.
	MOVEI	CH,"0"(CH)		;MAKE IT ASCII.
	GOSUB	PUT			;WRITE IT OUT.
	IF.ON	P4,77B5,OT2OCT		;JUMP IF HAVE MORE.
	SOJG	P3,RET0			;JUMP IF NOT AT LINES END.
OT3OCT:	AOS	ORCNT			;COUNT THE RECORD.
	AOS	OBCNT			;COUNT THE BLOCK.
	UME	.ASC,[BYTE (7)15,12,0]	;SKIP A LINE.
	GOSUB	CHKOPR			;CHECK FOR COMMAND.
	GOTO	OT0OCT			;RESET COUNTER.
OT4OCT:	SAVE	CH			;SAVE THE DATA WORD.
	MOVEI	CH,"("			;TO DELIMIT WORD NUMBER.
	GOSUB	PUT			;PLACE IT.
	MOVE	T3,OT0TMP		;GET THE WORD NUMBER.
	MOVE	P4,[POINT 3,T3,17]	;GET A POINTER TO IT.
	GOSUB	OT2OCT			;WRITE IT OUT.
	MOVEI	CH,")"			;TO DELIMIT IT.
	GOSUB	PUT			;PRINT IT.
	UNSAVE	CH			;GET THE DATA WORD BACK.
	ADDM	P3,OT0TMP		;UPDATE WORD COUNTER.
	GOTO	OT1OCT			;PLACE THE DATA WORD.

;HERE ON END OF FILE.

OTFOCT:	CAMN	P3,OT1TMP		;ARE WE IN THE MIDDLE OF THE LINE.
	RETURN	ZERO			;NO SO RETURN.
	GOTO	OT3OCT			;FINISH LINE AND RETURN.

EQUATE	ABORT,<INIOCT,OTROCT,OTBOCT>
SUBTTL			*** SIXBIT I/O ROUTINES ***

;HERE TO READ A SIXBIT FILE AND PASS A CHARACTER
;AT A TIME TO THE OUTPUT ROUTINES.

IN0SIX:	MOVE	P1,IBUF+1		;GET THE BUFFER POINTER.
	IF.OFF	P1,77B5,INISIX		;IF NOT AT A WORD BOUNDARY
	IBP	IBUF+1			;BUMP POINTER ONE POSITION
	SOS	IBUF+2			;AND COUNT AND THEN
	GOTO	IN0SIX			;TEST FOR A WORD BOUNDARY.
INISIX:	GOSUB	GET			;MAKE SURE NOT EOF.
	GOTO	@OUTF(OM)		;FINISH OFF FILE.
	LDB	P1,[POINT 12,@IBUF+1,35];GET THE RECORD SIZE.
	MOVSI	T1,770000		;SET BYTE POINTER TO NEXT WORD.
	ANDCAM	T1,IBUF+1		;POINTER NOW POINTS RIGHT.
	MOVNI	T1,5			;NUMBER OF PLACES POINTER MOVED.
	ADDM	T1,IBUF+2		;UPDATE THE COUNTER.
	JUMPE	P1,IN0SIX		;DON'T DO ZERO CTRL WORDS.
IN1SIX:	SOJL	P1,IN2SIX		;HAS COUNTER RUN OUT.
	GOSUB	GET			;NO GET A WORD.
	GOTO	@OUTF(OM)		;END OF FILE SHOULDN'T HAPPEN??
	GOSUB	CHANGE			;CONVERT THE CHARACTER.
	GOTO	IN1SIX			;AND LOOP.
IN2SIX:	GOSUB	RENEW			;GET THE NEXT RECORD.
	GOTO	@OUTF(OM)		;END OF THE FILE.
	GOSUB	@OUTR(OM)		;FINISH THE OUTPUT RECORD.
	GOTO	IN0SIX			;GET A NEW CONTROL WORD.
;HERE TO INITAILIZE THE OUTPUT ROUTINE.

OTISIX:	GOSUB	GETBUF			;GET AN ALTER BUFFER.
OT0SIX:	SETZM	OSIZE			;SET SIZE OF RECORD TO ZERO.
	MOVE	P3,CURPTR		;GET THE CURRENT BUFFER POINTER.
	CAME	P3,RECPTR		;ARE WE AT THE TOP.
	AOS	P3			;NO SO BUMP POINTER.
	HRRZM	P3,LSTPTR		;AND MAKE IT THE LAST POINTER.
	AOS	CURPTR			;POINT POINTER TO START OF RECORD.
	MOVE	P3,OFILE+RECSIZ		;GET THE RECORD SIZE.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO PUT ONE CHARACTER INTO THE ALTER BUFFER.

OTCSIX:	SOJL	P3,RET0			;RETURN IF RECORD IS FULL.
	AOS	OSIZE			;COUNT THE CHARACTER.
	IDPB	CH,CURPTR		;SAVE THE CHARACTER.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO FINISH OFF THE CURRENT RECORD AND WRITE ITS CTRL WORD.

OT2SIX:	GOSUB	SETCNT			;SET COUNTERS RIGHT.
OTRSIX:	HRRZ	CH,TAB2+40		;LOAD A SPACE.
	SKIPN	OSIZE			;CHECK SIZE OF RECORD.
	GOSUB	OTCSIX			;SO RECORD IS KNOWN.
	MOVE	P3,OSIZE		;GET THE RECORD SIZE.
	MOVEM	P3,@LSTPTR		;STASH IT IN THE BUFFER.
OT1SIX:	SETZM	CH			;PUT IN SPACES.
	MOVE	P3,CURPTR		;GET THE CURRENT POINTER.
	IF.OFF	P3,77B5,OT3SIX		;JUMP IT AT WORD BOUNDARY.
	IDPB	CH,CURPTR		;ELSE PUSH POINTER TO A WORD
	GOTO	OT1SIX			;BOUNDARY AND LOOP.
OT3SIX:	GOSUB	UPDATE			;COUNT THIS RECORD.
	GOTO	OT0SIX			;RE-INITIALIZE.

;HERE TO FINISH OFF A BLOCK WHEN WE HAVE BEEN CALLED FROM UPDATE.

OTBSIX:	GOSUB	BUFMOV			;MOVE ALTER BUFFER TO OUTPUT BUFFER.
	MOVE	T1,RECPTR		;GET POINTER TO TOP.
	MOVEM	T1,CURPTR		;SAVE IT AS THE CURRENT POINTER.
	RETURN	ZERO			;AND RETURN.

;HERE TO FINISH OFF THE FILE.

OTFSIX:	SKIPE	OSIZE			;SKIP IF JUST FINISHED A RECORD.
	GOTO	OT2SIX			;FINISH RECORD AND WRITE BLOCK.
	SOS	CURPTR			;POINTER POINTER RIGHT.
	GOTO	UPDAT			;FINISH IT OFF.
SUBTTL		*** BCD BCL GEBCD AND FIXED EBCDIC I/O ROUTINES ***

;HERE TO GET A CHARACTER FROM THE INPUT BUFFER AND WRITE
;IT TO THE OUTPUT BUFFER. NOTE THIS ROUTINE WILL HANDLE
;ANY FORMAT PROVIDED THE FORMAT HAS NO CTRL WORDS AND NO
;CHARACTERS IN THE RECORDS THAT HAVE A SPECIAL MEANING.
;THE BYTE SIZE OF THE CHARACTER SET HAS NO MEANING HERE.

INIBGE:	MOVE	P1,IFILE+RECSIZ		;GET THE RECORD SIZE.
IN5BGE:	MOVEI	P2,^D8			;SPACES PER TAB.
IN0BGE:	SOJL	P1,IN1BGE		;JUMP IF RECORD HAS EXPIRED.
	GOSUB	GET			;GET A WORD.
	GOTO	@OUTF(OM)		;END OF FILE.
	CAIN	IM,EBCMOD		;IS THIS EBCDIC.
	GOTO	IN3BGE			;YES CHECK FOR A TAB.
IN2BGE:	GOSUB	CHANGE			;CONVERT THE CHARACTER.
	SOJG	P2,IN0BGE		;JUMP IF TAB IS STILL THERE.
	GOTO	IN5BGE			;CARRY ON...
IN1BGE:	GOSUB	RENEW			;GET THE NEXT RECORD.
	GOTO	@OUTF(OM)		;END OF FILE FOUND.
	GOSUB	@OUTR(OM)		;FINISH THE OUTPUT RECORD.
	GOTO	INIBGE			;CONTINUE ON..
IN3BGE:	CAIE	CH,5			;CHECK FOR EBCDIC TAB.
	GOTO	IN2BGE			;NOT ONE.
	MOVE	T1,STS(OM)		;GET THE OUTPUT STATE WORD.
	IF.ON	T1,TAB,IN2BGE		;JUMP IF IT HAS TABS.
IN4BGE:	MOVEI	CH,100			;LOAD A SPACE.
	GOSUB	CHANGE			;CONVERT IT.
	SOJG	P2,IN4BGE		;FOR THE COUNT.
	GOTO	IN5BGE			;CONTINUE ON.

EQUATE	INIBGE,<INIFIX,INICDC,INIBCL,INIBCD,INIXBD,INIEBC,INICEB,INIHBD>
;HERE TO INITIALIZE THE OUTPUT ROUTINE FOR CHARACTER
;SETS THAT HAVE NO CONTROL WORDS.

OTIBGE:	MOVE	P3,OFILE+RECSIZ		;GET THE RECORD SIZE.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO WRITE ONE CHARACTER OUT INTO THE
;OUTPUT BUFFER.

OTCBGE:	SOJL	P3,RET0			;RETURN IF RECORD IS FULL.
	GOTO	PUT			;ELSE ADD TO BUFFER.

;HERE TO FINSIH OFF THE RECORD.

OT0BGE:	GOSUB	SETCNT			;SET COUNTERS RIGHT AND SET FLAG.
OTRBGE:	HRRZ	CH,TAB2+40		;GET A SPACE FOR THIS SET.
	GOSUB	OTCBGE			;AND WRITE IT OUT.
	JUMPGE	P3,OTRBGE		;CONTINUE FOR THE RECORD SIZE.
	SAVE	OBUF+1			;SAVE BUFFER POINTER.
OT1BGE:	HLRZ	T2,MSIZ(OM)		;GET BYTE SIZE.
	MOVEI	T1,^D36			;BITS PER WORD.
	IDIVI	T1,ZERO(T2)		;UNUSED BITS IN T2.
	LDB	T1,[POINT 6,OBUF+1,5]	;GET THE BITS LEFT IN WORD.
	CAIN	T1,ZERO(T2)		;SKIP IF NOT AT WORD BOUNDARY.
	GOTO	OT2BGE			;WE ARE AT A BOUNDARY.
	HRRZ	CH,TAB2+40		;LOAD A SPACE.
	IDPB	CH,OBUF+1		;SAVE THE SPACE.
	GOTO	OT1BGE			;TRY AGAIN.
OT2BGE:	UNSAVE	OBUF+1			;RESTORE POINTER.
	GOSUB	UPDATE			;COUNT THE RECORD.
	GOTO	OTIBGE			;RE-INITIALIZE.

;HERE ON INPUT END OF FILE TO FINISH OFF THE
;OUTPUT FILE.

OTFBGE:	CAME	P3,OFILE+RECSIZ		;SKIP IF JUST FINISHED A RECORD.
	GOTO	OT0BGE			;FINISH RECORD AND WRITE BLOCK.
	GOTO	UPDAT			;DON'T WRITE EXTRA RECORDS.

EQUATE	RET0,<OTBBGE>
EQUATE	OTIBGE,<OTIHBD,OTIEBC,OTICEB,OTIXBD,OTIBCD,OTIBCL,OTIFIX,OTICDC>
EQUATE	OTCBGE,<OTCHBD,OTCEBC,OTCCEB,OTCXBD,OTCBCD,OTCBCL,OTCFIX,OTCCDC>
EQUATE	OTRBGE,<OTRHBD,OTREBC,OTRCEB,OTRXBD,OTRBCD,OTRBCL,OTRFIX,OTRCDC>
EQUATE	OTBBGE,<OTBHBD,OTBEBC,OTBCEB,OTBXBD,OTBBCD,OTBBCL,OTBFIX,OTBCDC>
EQUATE	OTFBGE,<OTFHBD,OTFEBC,OTFCEB,OTFXBD,OTFBCD,OTFBCL,OTFFIX,OTFCDC>
SUBTTL			*** VARABLE EBCDIC I/O ROUTINES ***

;HERE TO READ FROM A VARABLE EBCDIC FILE.

INIVEB:	HRLOI	ICNT,377777		;SO WE WON'T READ A BLOCK.
	GOSUB	IN3VEB			;GET A BLOCK CTRL WORD.
	JUMPE	P1,INIVEB		;IGNORE ZERO CTRL WORDS.
	SUBI	P1,4			;SUBTRACT LENGTH OF CTRL WORD.
	MOVEM	P1,IVBCNT		;SAVE THE BLOCK LENGTH.
IN0VEB:	GOSUB	IN3VEB			;GET A RECORD CTRL WORD.
	EXCH	P1,IVBCNT		;PUT BLOCK CTRL IN AN AC.
	SUB	P1,IVBCNT		;SUBTRACT RECORD FROM BLOCK.
	EXCH	P1,IVBCNT		;REPLACE THE BLOCK WORD.
	SUBI	P1,4			;SUBTRACT LENGTH OF CTRL WORD.
IN5VEB:	MOVEI	P2,^D8			;SPACES PER TAB.
IN1VEB:	SOJL	P1,IN2VEB		;JUMP IF CTRL RAN OUT.
	GOSUB	GET			;GET A WORD.
	GOTO	@OUTF(OM)		;FOUND END OF FILE.
	CAIN	CH,5			;SEE IF IT IS A TAB.
	GOTO	IN6VEB			;HANDLE TABS.
IN8VEB:	GOSUB	CHANGE			;CONVERT AND WRITE.
	SOJG	P2,IN1VEB		;DECREMENT TAB COUNT AND TEST.
	GOTO	IN5VEB			;CONTINUE LOOP.
IN2VEB:	SKIPG	IVBCNT			;HAS BLOCK EXPIRED.
	SETOM	ICNT			;FLAG WE NEED A NEW ONE.
	GOSUB	RENEW			;GET THE NEXT RECORD.
	GOTO	@OUTF(OM)		;END OF FILE.
	GOSUB	@OUTR(OM)		;FINISH THE OUTPUT RECORD.
	SKIPLE	IVBCNT			;DID BLOCK EXPIRE.
	GOTO	IN0VEB			;NO SO GET A RECORD CTRL WORD.
	GOTO	INIVEB			;YES SO GET A NEW BLOCK WORD.
IN3VEB:	GOSUB	IN4VEB			;GET A BYTE.
	MOVE	P1,CH			;TO A BETTER AC.
	LSH	P1,^D8			;SHIFT FIRST INTO PLACE.
	GOSUB	IN4VEB			;GET THE NEXT BYTE.
	IOR	P1,CH			;SET UP COUNTER.
	GOSUB	IN4VEB			;SKIP PASS UNUSED BYTES.
	GOSUB	IN4VEB			;SKIP PASS UNUSED BYTES.
	RETURN	ZERO			;RETURN.
IN4VEB:	GOSUB	GET			;GET A BYTE.
	SKIPA				;END OF FILE RETURN.
	RETURN	ZERO			;RETURN WITH BYTE.
	SUB	PDP,[XWD TWO,TWO]	;FIX UP THE PUSH-DOWN POINTER.
	GOTO	@OUTF(OM)		;END OF FILE DISPATCH.
IN6VEB:	MOVE	T1,STS(OM)		;GET THE OUTPUT STATE WORD.
	IF.ON	T1,TAB,IN8VEB		;JUMP IF OUTPUT HAS TABS.
IN7VEB:	MOVEI	CH,100			;LOAD A SPACE.
	GOSUB	CHANGE			;CONVERT IT.
	SOJG	P2,IN7VEB		;CONTIUE FOR COUNT.
	GOTO	IN5VEB			;CONTINUE ON...
;HERE TO INITIALIZE THE VARABLE EBCDIC OUTPUT ROUTINE.

OTIVEB:	GOSUB	GETBUF			;GET AN ALTER BUFFER.
	SETZM	OBSIZE			;INIT BLOCK SIZE.
OT0VEB:	SETZM	OSIZE			;INIT RECORD SIZE.
	MOVE	P3,CURPTR		;GET THE CURRENT POINTER.
	MOVEM	P3,LSTPTR		;MAKE IT LAST POINTER.
	CAMN	P3,RECPTR		;ARE WE STARTING A BLOCK.
	AOS	CURPTR			;YES SO MAKE ROOM FOR BLOCK CTRL WORD.
	CAMN	P3,RECPTR		;WAS THAT THE SAME.
	AOS	LSTPTR			;PUSH BY BLOCK CTRL WORD.
	MOVE	P3,OFILE+RECSIZ		;SET UP RECORD SIZE.
	AOS	CURPTR			;PUSH BY FUTURE CTRL WORD.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO PUT ONE CHARACTER INTO THE ALTER BUFFER.

OTCVEB:	SOJL	P3,RET0			;RETURN IF BUFFER IS FULL.
	AOS	OSIZE			;COUNT THE CHARACTER.
	IDPB	CH,CURPTR		;SAVE THE CHARACTER.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO WRITE A CTRL WORD ONTO THIS RECORD.

OT3VEB:	GOSUB	SETCNT			;FLAG BLOCK TO GO AND SET COUNTER.
OTRVEB:	HRRZ	CH,TAB2+40		;LOAD A SPACE.
	SKIPN	OSIZE			;GET THE SIZE.
	GOSUB	OTCVEB			;SO RECORD IS SEEN.
	MOVE	P3,OSIZE		;GET SIZE OF RECORD.
	MOVE	T1,LSTPTR		;POINTER TO WHERE IT GOES.
	GOSUB	OT1VEB			;PLACE IT IN THE RECORD.
	ADDM	P3,OBSIZE		;UPDATE BLOCK WORD.
	GOSUB	UPDATE			;WRITE THE RECORD.
	GOTO	OT0VEB			;RE-INITIALIZE.
;HERE TO WRITE A BLOCK CTRL WORD ONTO THE BLOCK THAT IS ABOUT
;TO LEAVE US.

OTBVEB:	MOVE	P3,OBSIZE		;GET THE BLOCK SIZE.
	MOVE	T1,RECPTR		;POINTER TO WHERE IT GOES.
	GOSUB	OT1VEB			;WRITE THE BLOCK CTRL WORD.
	SETZM	OBSIZE			;CLEAR BLOCK SIZE.
	GOTO	OTBSIX			;COPY ALTER BUFFER TO OUTPUT BUFFER.
OT1VEB:	ADDI	P3,4			;ADD IN THE SIZE OF THE CTRL WORD.
	LDB	CH,[POINT 8,P3,27]	;GET THE FIRST EIGHT BITS.
	IDPB	CH,T1			;SAVE THEM IN BUFFER.
	IDPB	P3,T1			;SAVE THE NEXT EIGHT BITS.
	MOVEI	CH,100			;PUT SPACES IN THE REMAINING
	IDPB	CH,T1			;TWO BYTES OF THE CTRL WORD
	IDPB	CH,T1			;FOR THIS RECORD.
	RETURN	ZERO			;BACK TO CALLER.

;HERE ON INPUT END OF FILE.

OTFVEB:	SKIPE	OSIZE			;SKIP IF JUST WROTE A RECORD.
	GOTO	OT3VEB			;FINISH RECORD AND WRITE THE BLOCK.
	HRRZ	T1,RECPTR		;GET POINTER TO BUFFER.
	HRRZ	T2,CURPTR		;POINTER INTO BUFFER.
	CAIN	T1,-2(T2)		;SEE IF AT THE TOP.
	SOS	CURPTR			;DECREMENT FOR BLOCK WORD.
	SOS	CURPTR			;DECREMENT FOR RECORD CTRL WORD.
	GOTO	UPDAT			;FINISH THE FILE.
SUBTTL				*** THINK ABOUT LABELS ***

;HERE TO READ THE LABEL AND TO DISPATCH TO THE
;APPROPRIATE ROUTINE TO HANDLE ITS FORMAT.

INPLAB:	ENABLE	TTY			;CLEAR THE TTY.
	MOVE	T1,IFILE+LABEL		;GET LABEL INDEX.
	HRRZ	T1,LB.TYP(T1)		;COPY DISPATCH.
CHKLAB:	OFF	S,L.HDR!L.EOF!L.EOV	;TURN OFF LABEL BITS.
	MOVE	T2,[XWD INPBUF,INPBUF+1];XWD FOR BLT.
	SETZM	INPBUF			;CLEAR THE FIRST.
	BLT	T2,INPBUF+^D20		;CLEAR BUFFER.
	GOSUB	ZERO(T1)		;CHECK LABEL OUT.
	RETURN	ZERO			;NOT THAT TYPE OF LABEL.
	IF.OFF	S,L.HDR,RET3		;JUMP IF NOT HEADER.
	GOSUB	TSTNAM			;SEE IF NAME MATCHES.
	RETURN	ONE			;NO MATCH ON NAME.
	CAME	P3,IFILE+VOL		;IS THE VOLUME RIGHT.
	RETURN	TWO			;INCORRECT VOLUME.
	RETURN	THREE			;LABEL PASSED BITS ARE SET.

;HERE TO CHECK AND WRITE OUTPUT LABELS. HERE WE
;ALSO DO INITIAL POSITIONING OF THE DEVICE.

OUTLAB:	IF.OFF	OF,IND			;WHICH MODE FOR THE TAPE.
	DRIVE	OF,.IND			;INDUSTRIAL.
	ENABLE	TTY			;CLEAR THE TTY.
	MOVE	T1,OFILE+LABEL		;GET THE LABEL INDEX.
	HLRZ	T1,LB.TYP(T1)		;COPY DISPATCH.
	MOVE	T2,[XWD OUTBUF,OUTBUF+1];XWD FOR BLT.
	SETZM	OUTBUF			;CLEAR FIRST WORD.
	BLT	T2,OUTBUF+^D20		;CLEAR BUFFER.
	GOTO	ZERO(T1)		;DISPATCH.

;HERE WHEN WE ARE READY TO WRITE AN EOF LABEL
;TO THE TAPE.

EOFLAB:	ON	S,TERM			;NOTE THAT THIS IS EOF.
	GOSUB	OUTLAB			;OTHER WISE HANDLE AS HDR.
	OFF	S,TERM			;TURN OFF TERMINAL BIT.
	GETSTS	OF,T1			;GET DEVICE STATUS.
	IF.OFF	T1,E.ERR		;ANY ERRORS.
	PRINT	(? Error during close of output file.)
	RETURN	ZERO			;BACK TO CALLER.
;HERE IF NO LABEL TYPE WAS SPECIFIED.

LB.NON:	DRIVE	IF,.BSR			;BACK UP OVER RECORD READ.
	DRIVE	IF,.WAT			;WAIT FOR IT.
	MOVE	P1,IFILE+NAME		;GET THE NAME.
	HLLZ	P2,IFILE+EXT		;GET THE EXTENSION.
	MOVE	P3,IFILE+VOL		;GET THE VOLUME NUMBER.
	IF.ON	IF,WNAME!WEXT,LB.0NO	;JUMP IF WILD.
LB.NST:	MOVEM	P1,LABNAM		;SAVE FIRST HALF OF NAME.
	MOVEM	P2,LABNAM+1		;SAVE THE SECOND HALF.
	MOVEM	P3,LABVOL		;SAVE THE VOLUME NUMBER.
	MME	T1,.DATE		;GET THE DATE TODAY.
	MOVEM	T1,LABDTW		;SAVE THE DATE.
	ON	S,L.HDR			;SAY WE FOUND A HEADER.
	GOTO	LABFIL			;GO FILL IN DEFAULTS.
LB.0NO:	GOSUB	DREAM			;GET A FUNNY NAME.
	IF.OFF	IF,WNAME,LB.1NO		;JUMP IF NAME ISN'T WILD.
	MOVE	P1,T1			;COPY FUNNY NAME.
	MOVEM	P1,IFILE+NAME		;MAKE IT THE NAME.
LB.1NO:	IF.OFF	IF,WEXT,LB.NST		;JUMP IF TRUE EXTENSION.
	MOVE	P2,T2			;COPY FUNNY EXTENSION.
	MOVEM	P2,IFILE+EXT		;SAVE AS EXTENSION.
	GOTO	LB.NST			;SAVE THIS INFO.
;HERE TO CHECK ON A SPECIAL LABEL THAT HAS
;INFORMATION ONLY VALID FOR DECSYSTEM-10.

LB.IMI:	MOVE	T1,IM			;GET THE INPUT MODE.
	GOSUB	CVTLAB			;CONVERT THE LABEL.
	MOVE	T1,INPBUF		;GET THE IDENTIFIER.
	CAMN	T1,[SIXBIT "HEAD"]	;SKIP IF NOT HEADER LABEL.
	ON	S,L.HDR			;LIGHT HEADER BIT.
	CAMN	T1,[SIXBIT "TRAIL"]	;SKIP IF NOT TRAILER.
	ON	S,L.EOF			;LIGHT EOF BIT.
	CAMN	T1,[SIXBIT "REEL"]	;SKIP IF NOT END OF REEL.
	ON	S,L.EOV			;LIGHT VOLUME BIT.
	IF.ON	S,L.HDR!L.EOF!L.EOV	;SKIP IF WE FOUND ONE.
	RETURN	ZERO			;GIVE NO LABEL RETURN.
	MOVE	P1,INPBUF+2		;GET THE FILE NAME.
	HLLZ	P2,INPBUF+3		;GET THE EXTENSION.
	MOVEM	P1,LABNAM		;SAVE THE NAME.
	MOVEM	P2,LABNAM+1		;SAVE THE EXTENSION.
	MOVE	P3,INPBUF+11		;GET THE VOLUME NUMBER.
	MOVEM	P3,LABVOL		;SAVE THE VOLUME NUMBER.
	MOVE	T1,INPBUF+1		;GET THE STRUCTURE.
	MOVEM	T1,LABSTR		;SAVE IT.
	MOVE	T1,INPBUF+7		;GET THE CREATION DATE.
	GOSUB	DATCOB			;COMPRESS IT.
	MOVEM	T1,LABDTW		;SAVE THE DATE.
	MOVE	T2,INPBUF+6		;GET THE PROTECTION BITS.
	GOSUB	TOBIN			;CONVERT IT IT BINARY.
	DPB	T3,[POINT 9,LABDTW,8]	;SAVE THE PROTECTION BITS.
	MOVE	T2,INPBUF+4		;GET THE PROJECT NUMBER.
	GOSUB	TOBIN			;CONVERT IT.
	HRLM	T3,LABPPN		;SAVE THE FIRST HALF.
	MOVE	T2,INPBUF+5		;GET THE PROGRAM NUMBER.
	GOSUB	TOBIN			;CONVERT IT.
	HRRM	T3,LABPPN		;SAVE THE PROGRAM NUMBER.
	RETURN	ONE			;BACK TO CALLER.
;HERE IF LABELS ARE TO BE CHECKED FOR BCL
;FORMAT.

LB.IBL:	MOVE	T1,IM			;GET THE MODE OF INPUT FILE.
	GOSUB	CVTLAB			;CONVERT THE LABEL TO SIXBIT.
	MOVE	T1,INPBUF		;MUST BE " LABEL".
	CAME	T1,[SIXBIT " LABEL"]	;MAKE SURE IT IS RIGHT.
	RETURN	ZERO			;NOT A LEGAL LABEL.
	MOVE	P2,[POINT 6,INPBUF+2,29];POINT TO LABEL-ID.
	MOVE	P1,[POINT 6,T1]		;POINT TO STORAGE WORD.
	MOVEI	P3,^D6			;COUNT TO COPY.
	GOSUB	PLACE			;COPY THE CHARACTERS.
	MOVE	P1,T1			;COPY TO BETTER AC.
	MOVEM	P1,LABNAM		;SAVE FIRST HALF OF NAME.
	HLLZ	P2,IFILE+EXT		;GET THE EXTENSION.
	SETZM	LABNAM+1		;ZERO SECOND HALF.
	LDB	P3,[POINT 18,INPBUF+4,17];PICK UP THE VOLUME NUMBER.
	LSH	P3,^D12			;SHIFT INTO PLACE.
	ON	P3,'0     '		;ADD A LEADING ZERO.
	MOVEM	P3,LABVOL		;SAVE THE VOLUME NUMBER.
	LDB	T1,[POINT 6,INPBUF+6,23];PICK UP FLAG BIT FOR EOF.
	CAIE	T1,'0'			;SEE IF FLAGED AS EOF.
	ON	S,L.EOV			;SET END OF VOLUME BIT.
	IF.ON	S,L.EOV,RET1		;RETURN IF WE SET IT.
	ON	S,L.HDR			;SET HEADER BIT.
	HRRZ	T1,INPBUF+4		;GET THE FIRST HALF.
	LSH	T1,^D12			;SHIFT INTO PLACE.
	LDB	T2,[POINT 12,INPBUF+5,11];GET THE SECON HALF.
	IOR	T1,T2			;COMBINE THEM.
	LSH	T1,^D6			;SET IT RIGHT.
	GOSUB	DATBCL			;COMPRESS THE DATE.
	GOTO	LABFIL			;FILL IN THE DEFAULTS.
;HERE TO CHECK LABELS WRITTEN IN DEC-COBOL
;FORMAT.

LB.NCL:	GOSUB	GETLAB			;READ A LABEL BLOCK.
	RETURN	ZERO			;BAD WE MADE A MISTAKE.
LB.ICL:	MOVE	T1,IM			;GET THE MODE OF INPUT.
	GOSUB	CVTLAB			;CONVERT THE LABEL TO SIXBIT.
	LDB	T1,[POINT 24,INPBUF,23]	;PICK UP HEADER WORD.
	CAMN	T1,[SIXBIT "  VOL1"]	;IS THIS A VOLUME LABEL.
	GOTO	LB.NCL			;READ THE NEXT BLOCK IN.
	CAMN	T1,[SIXBIT "  HDR1"]	;IS IT A HEADER LABEL.
	ON	S,L.HDR			;SET HEADER BIT.
	CAMN	T1,[SIXBIT "  EOF1"]	;TEST FOR EOF LABEL.
	ON	S,L.EOF			;SET EOF BIT.
	CAMN	T1,[SIXBIT "  EOV1"]	;TEST FOR END OF REEL.
	ON	S,L.EOV			;SET END OF TAPE BIT.
	IF.ON	S,L.HDR!L.EOF!L.EOV	;SKIP IF WE FOUND A LABEL.
	RETURN	ZERO			;NOT A LABEL.
	MOVE	P2,[POINT 6,INPBUF,23]	;POINTER TO LABEL-ID.
	MOVE	P1,[POINT 6,LABNAM]	;POINTER TO STORAGE WORD.
	SETZM	LABNAM+1		;CLEAR TARGET.
	MOVEI	P3,^D9			;CHARACTERS TO PLACE.
	GOSUB	PLACE			;PLACE THEM.
	MOVE	P1,LABNAM		;LOAD FIRST HALF OF NAME.
	MOVE	P2,LABNAM+1		;LOAD SECOND HALF OF NAME.
	LDB	T1,[POINT 18,INPBUF+4,35];GET FIRST HALF OF NUMBER.
	LDB	T2,[POINT 6,INPBUF+5,5]	;GET THE OTHER HALF.
	LSH	T2,^D30			;LEFT JUSTIFY DIGITS.
	LSHC	T1,^D18			;SHIFT INTO PLACE.
	MOVE	P3,T1			;COPY TO RETURN AC.
	MOVEM	P3,LABVOL		;SAVE THE VOLUME NUMBER.
	LDB	T1,[POINT 6,INPBUF+6,35];GET THE FIRST HALF OF DATE.
	LSH	T1,^D30			;SHIFT INTO PLACE.
	LDB	T2,[POINT 29,INPBUF+7,29];GET THE OTHER BITS.
	IOR	T1,T2			;MAKE ONE WORD.
	GOSUB	DATCOB			;COMPRESS THE DATE.
	GOTO	LABFIL			;FILL IN DEFAULTS.
;HERE TO CHECK LABELS WRITTEN IN GE635 BCD.

LB.IGE:	MOVEI	T1,XBDMOD		;GET MODE FOR LABELS.
	GOSUB	CVTLAB			;CONVERT IT TO SIXBIT.
	MOVE	T1,INPBUF		;GET FIRST WORD OF LABEL.
	MOVE	T2,INPBUF+1		;GET THE SECOND WORD OF LABEL.
	CAMN	T1,[SIXBIT "GE  60"]	;TEST THE FIRST WORD.
	CAME	T2,[SIXBIT "0 BTL "]	;TEST THE SECOND WORD.
	GOTO	LB.0GE			;CHECK FOR EOF AND EOR.
	MOVE	T2,INPBUF+2		;GET THE THIRD WORD OF LABEL.
	CAMN	T2,[SIXBIT "GE PHX"]	;TEST THE THIRD WORD.
	ON	S,L.HDR			;SET THE HEADER BIT.
LB.0GE:	CAMN	T1,[SIXBIT " EOF  "]	;SEE IF END OF FILE LABEL.
	ON	S,L.EOF			;SET EOF BIT.
	CAMN	T1,[SIXBIT " EOR  "]	;SEE IF END OF REEL.
	ON	S,L.EOV			;SET END OF REEL BIT.
	IF.ON	S,L.HDR!L.EOF!L.EOV	;SKIP IF WE FOUND A LABEL.
	RETURN	ZERO			;NOT A GE LABEL.
	IF.OFF	S,L.HDR,RET1		;RETURN IF NOT HEADER.
	MOVE	P1,INPBUF+3		;GET THE NAME IN THE LABEL.
	HLLZ	P2,IFILE+EXT		;GET THE EXTENSION.
	LSH	P1,6			;SHIFT INTO PLACE.
	MOVEM	P1,LABNAM		;SAVE THE LABEL NAME.
	SETZM	LABNAM+1		;CLEAR OTHER HALF.
	MOVE	T1,IFILE+NAME		;GET THE NAME SPECIFIED.
	ANDI	T1,77			;ONLY CHECK FIVE CHARACTERS.
	IOR	P1,T1			;SO COMPARE WILL ONLY CHECK FIVE.
	MOVE	P3,INPBUF+5		;GET THE VOLUME NUMBER.
	LSH	P3,^D12			;SHIFT INTO PLACE.
	MOVEM	P3,LABVOL		;SAVE THE VOLUME NUMBER.
	LDB	T1,[POINT 30,INPBUF+6,35] ;GET THE DATE.
	LSH	T1,6			;SHIFT INTO PLACE.
	GOSUB	DATBCL			;COMPRESS THE DATE.
	GOTO	LABFIL			;FILL IN DEFAULTS.
;HERE TO READ AND VERIFY IBM LABELS.

LB.NBM:	GOSUB	GETLAB			;READ A LABEL BLOCK.
	RETURN	ZERO			;BAD WE MADE A MISTAKE.
LB.IBM:	MOVEI	T1,BCDMOD		;SET BCD MODE.
	MOVEI	T2,IF			;CHANNEL FOR INPUT FILE.
	MME	T2,.STS			;GET THE CONI WORD.
	SKIPA				;IF IT FAILS USE EBCDIC.
	IF.ON	T2,TRK7			;IF SEVEN TRACK WE'RE GOLDEN.
	MOVEI	T1,EBCMOD		;ELSE GET EBCDIC.
	GOSUB	CVTLAB			;CONVERT THE LABEL TO SIXBIT.
LB.IBI:	LDB	T1,[POINT 24,INPBUF,23]	;GET THE LABEL TYPE.
	CAMN	T1,[SIXBIT "  VOL1"]	;CHECK FOR VOLUME LABEL.
	GOTO	LB.NBM			;GET THE NEXT LABEL BLOCK.
	CAMN	T1,[SIXBIT "  HDR1"]	;SEE IF HEADER LABEL.
	ON	S,L.HDR			;SET THE HEADER BIT.
	CAMN	T1,[SIXBIT "  EOF1"]	;TEST FOR END OF FILE LABEL.
	ON	S,L.EOF			;SET EOF BIT.
	CAMN	T1,[SIXBIT "  EOV1"]	;TEST FOR END OF REEL.
	ON	S,L.EOV			;SET END OF REEL BIT.
	IF.ON	S,L.HDR!L.EOF!L.EOV	;SKIP IF WE FOUND A LABEL.
	RETURN	ZERO			;ELSE GIVE ERROR RETURN.
	MOVE	T1,[POINT 6,INPBUF,23]	;POINTER TO FILE NAME.
	MOVE	T2,[POINT 6,P1]		;POINTER TO STORAGE.
	MOVEI	T3,^D6			;NUMBER TO PLACE.
	MOVEI	P3,^D17			;MAX NUMBER TO READ.
	GOSUB	COPY			;COPY TO STORAGE.
	MOVE	T2,[POINT 6,P2]		;SET POINTER TO STORAGE.
	MOVEI	T3,^D3			;SET MAX COUNT TO PLACE.
	GOSUB	COPY			;COPY THEM TO STORAGE.
	MOVEM	P1,LABNAM		;SAVE FIRST HALF OF NAME.
	MOVEM	P2,LABNAM+1		;SAVE THE SECOND HALF.
	LDB	T1,[POINT 18,INPBUF+4,35];GET FIRST PART OF VOLUME NUMBER.
	LDB	T2,[POINT 6,INPBUF+5,5]	;GET THE SECOND HALF.
	LSH	T2,^D30			;RIGHT JUSTIFY SECOND HALF.
	LSHC	T1,^D18			;ALL INTO ONE WORD.
	MOVE	P3,T1			;COPY TO RETURN AC.
	MOVEM	P3,LABVOL		;SAVE THE VOLUME NUMBER.
	MOVE	T1,INPBUF+7		;GET THE DATE.
	GOSUB	DATBCL			;COMPRESS THE DATE.
	GOTO	LABFIL			;GO FILL IN DEFAULTS.
;HERE TO WRITE SPECIAL LABELS THAT HAVE INFORMATION
;FOR DECSYSTEM-10 ONLY.

LB.OMI:	MOVE	P1,[SIXBIT "HEAD"]	;LOAD HEADER WORD.
	IF.OFF	S,TERM			;SKIP IF NOT TRAILER.
	MOVE	P1,[SIXBIT "TRAIL"]	;LOAD TRAILER WORD.
	IF.OFF	S,FIN			;SKIP IF NOT END OF REEL.
	MOVE	P1,[SIXBIT "REEL"]	;LOAD END OF REEL WORD.
	MOVEM	P1,OUTBUF		;SAVE THE IDENTIFIER.
	MOVE	P1,IFILE+CHAN		;GET THE CHANNEL FOR INPUT.
	MME	P1,.NAM			;GET THE REAL NAME.
	MOVE	P1,IFILE+DEVICE		;IF MME FAILS.
	MOVEM	P1,OUTBUF+1		;SAVE DEVICE WHERE IT CAME FROM.
	MOVE	P1,OFILE+NAME		;GET THE NAME.
	MOVEM	P1,OUTBUF+2		;SAVE THE NAME.
	HLLZ	P1,OFILE+EXT		;GET THE EXTENSION.
	MOVEM	P1,OUTBUF+3		;SAVE THE EXTENSION.
	SKIPE	T1,OFILE+PPN		;GET THE PPN TO WRITE IT AS.
	GOTO	.+3			;CONTINUE ON WITH PPN IN T1.
	SKIPN	T1,IFILE+PPN		;GET THE INPUT PPN IF THERE.
	MME	T1,.PPN			;NO PPN USE CURRENT.
	NOP				;IN CASE OF JACCT.
	GOSUB	MAK2			;CONVERT TO TWO WORDS.
	MOVEM	T1,OUTBUF+4		;SAVE THE PROJECT NUMBER.
	MOVEM	T2,OUTBUF+5		;SAVE THE PROGRAM NUMBER.
	LDB	T1,[POINT 9,IFILE+DATTIM,8] ;LOAD PROTECTION BITS.
	GOSUB	MAK2			;CONVERT TO SIXBIT.
	MOVEM	T2,OUTBUF+6		;SAVE THE PROTECTION CODE.
	LDB	T1,[POINT 12,IFILE+DATTIM,35] ;LOAD DATE OF CREATION.
	MOVE	P1,[POINT 6,OUTBUF+7]	;GET A POINTER TO BUFFER.
	GOSUB	COBDAT			;PLACE DATE OF CRETATION.
	MME	T1,.DATE		;GET TODAYS DATE.
	GOSUB	COBDAT			;PUT IT AWAY.
	MOVE	P1,OFILE+VOL		;GET THE VOLUME NUMBER OF TAPE.
	MOVEM	P1,OUTBUF+11		;SAVE THE VOLUME NUMBER.
	MOVE	T1,OFILE+PERGE		;GET THE REEL SERIAL NUMBER.
	GOSUB	MAKTWO			;CONVERT TO TWO WORDS.
	MOVEM	T2,OUTBUF+12		;SAVE THE SERIAL NUMBER.
	MOVE	T1,OBCNT		;GET THE BLOCK.
	IF.ON	S,TERM!FIN		;SKIP IF TRAILER OR REEL LABEL.
	SETZM	T1			;ZERO BLOCK COUNTER.
	GOSUB	MAKTWO			;CONVERT TO TWO WORDS.
	MOVEM	T2,OUTBUF+13		;SAVE BLOCKS WRITTEN.
	MOVE	T1,ORCNT		;GET THE RECORD COUNTER.
	IF.ON	S,TERM!FIN		;SKIP IF TRAILER OR REEL LABEL.
	SETZM	T1			;CLEAR RECORD COUNTER.
	GOSUB	MAKTWO			;CONVERT TO TWO WORDS.
	MOVE	P2,[POINT 6,T1,23]	;POINTER TO WHAT WE WANT.
	MOVE	P1,[POINT 6,OUTBUF+14]	;POINTER TO STORAGE.
	MOVEI	P3,^D8			;NUMBER TO PLACE.
	GOSUB	PLACE			;PLACE THEM.
	MOVE	T2,OM			;GET THE OUTPUT INDEX.
	GOTO	LB.CLO			;WRITE LABEL TO TAPE.
;HERE TO PRODUCE IBM 360/OS LABELS.

LB.OBM:	MOVEI	T2,BCDMOD		;ASSUME A SEVEN TRACK DRIVE.
	MOVEI	T1,OF			;GET OUTPUT DEVICE CHANNEL.
	MME	T1,.STS			;GET LAST CONI WORD.
	SKIPA				;USE EBCDIC IF MME FAILS.
	IF.ON	T1,TRK7			;SKIP IF SEVEN TRACK DRIVE.
	MOVEI	T2,EBCMOD		;ELSE USE EBCDIC.
	MOVEM	T2,TEMP1		;SAVE WHAT WE DECIDED ON.
	IF.ON	S,TERM,LB.OBH		;JUMP IF TRAILER.
	GETSTS	OF,T1			;GET THE DEVICE STATUS.
	IF.OFF	T1,E.BOT,LB.OBH		;ONLY WRITE VOL'S AT BOT.
	SKIPE	OFILE+PERGE		;REEL NUMBER SPECIFIED.
	GOTO	LB.PBM			;YES PERGE THE LABEL.
	MOVE	T2,TEMP1		;GET THE MODE OF THE LABEL.
	GOSUB	REDOUT			;READ THE OUTPUT LABEL.
	GOTO	BADTM			;EOF MARK FOUND.
	DRIVE	OF,.BSR			;BACK UP OVER LABEL.
	DRIVE	OF,.WAT			;WAIT FOR COMPLETION.
	LDB	T1,[POINT 24,OUTBUF,23]	;GET THE IDENTIFIER.
	CAMN	T1,[SIXBIT "  HDR1"]	;IS IT A HEADER LABEL.
	GOTO	LB.OBH			;YES SO DON'T WRITE A VOL LABEL.
	CAME	T1,[SIXBIT "  VOL1"]	;IS IT A VOLUME LABEL.
	GOTO	NOTLAB			;NO SO ERROR.
	MOVE	P2,[POINT 6,OUTBUF,23]	;POINTER TO SERIAL NUMBER.
	MOVE	P1,[POINT 6,RELNUM]	;POINTER TO STORAGE.
	MOVEI	P3,^D6			;CHARACTERS TO MOVE.
	GOSUB	PLACE			;MOVE THEM.
LB.BVL:	MOVE	P1,[POINT 6,OUTBUF]	;POINTER TO STORAGE.
	MOVE	P2,[POINT 6,[SIXBIT "VOL1"]];IDENTIFIER.
	MOVEI	P3,^D4			;CHARACTERS TO MOVE.
	GOSUB	PLACE			;MOVE THEM.
	MOVE	P2,[POINT 6,RELNUM]	;POINTER TO REEL NUMBER.
	MOVEI	P3,^D6			;NUMBER TO PLACE.
	GOSUB	PLACE			;MOVE THEM TO BUFFER.
	MOVEI	CH,'0'			;A LONELY ZERO.
	IDPB	CH,P1			;PLACE INTO BUFFER.
	MOVEI	P3,^D30			;COUNT FOR SOME SPACES.
	GOSUB	SPACE			;PLACE THEM INTO BUFFER.
	MOVE	P2,[POINT 6,[SIXBIT "DIGITAL"]];PLACE THAT DID THIS.
	MOVEI	P3,^D7			;A COUNTER.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	P3,^D32			;SOME MORE SPACES.
	GOSUB	SPACE			;ADD THEM TO BUFFER.
	MOVE	T2,TEMP1		;GET MODE OF OUTPUT.
	GOSUB	WRILAB			;WRITE THE LABEL.
LB.OBH:	MOVE	P1,[POINT 6,OUTBUF]	;SET A NEW POINTER.
	MOVE	P2,[POINT 6,[SIXBIT "HDR1"]];HEADER ONE ID.
	IF.OFF	S,TERM			;IS THIS REALLY EOF.
	MOVE	P2,[POINT 6,[SIXBIT "EOF1"]];CHANGE MESSAGE.
	IF.OFF	S,FIN			;IS THIS REALLY JUST END OF REEL.
	MOVE	P2,[POINT 6,[SIXBIT "EOV1"]];CHANGE MESSAGE.
	MOVEI	P3,^D4			;COUNT TO PLACE.
	GOSUB	PLACE			;INTO BUFFER.
	MOVE	P2,[POINT 6,OFILE+NAME]	;POINTER TO FILE-ID.
	MOVEI	P3,^D9			;CHARACTERS TO MOVE.
	GOSUB	PLACE			;IN TO BUFFER.
	MOVEI	P3,^D14			;CHARACTERS TO SPACE.
	GOSUB	SPACE			;INTO BUFFER.
	MOVE	P2,[POINT 6,OFILE+VOL]	;POINTER TO VOLUME NUMBER.
	MOVEI	P3,^D4			;NUMBER TO MOVE.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	P3,^D11			;SOME MORE SPACES.
	GOSUB	SPACE			;INTO BUFFER.
	MME	T1,.DATE		;GET TODAY'S DATE.
	GOSUB	BCLDAT			;INTO BUFFER.
	SETZM	CH			;AN UNWANTED SPACE.
	IDPB	CH,P1			;SAVE IT.
	MME	T1,.DATE		;GET THE DATE AGAIN.
	ADDI	T1,^D984		;SAVE FACTOR.
	GOSUB	BCLDAT			;INTO BUFFER.
	MOVEI	CH,'0'			;A LITTLE ZERO.
	IDPB	CH,P1			;INTO BUFFER.
	IF.OFF	S,TERM,LB.IBH		;JUMP IF HEADER.
	MOVE	T1,OBCNT		;GET THE BLOCK COUNT.
	GOSUB	MAKTWO			;INTO TWO WORDS.
	SKIPA	P2,[POINT 6,T2]		;SET POINTER.
LB.IBH:	MOVE	P2,[POINT 6,[SIXBIT "000000"]];FILL BLOCK COUNT WITH ZEROS.
	MOVEI	P3,^D6			;COUNT TO MOVE.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	P3,^D20			;SOME SPACES.
	GOSUB	SPACE			;INTO BUFFER.
	MOVE	T2,TEMP1		;GET THE MODE OF OUTPUT.
	GOSUB	WRILAB			;WRITE THE LABEL.
	MOVE	P1,[POINT 6,OUTBUF]	;GET NEW POINTER.
	MOVE	P2,[POINT 6,[SIXBIT "HDR2"]];ASSUME HEADER LABEL.
	IF.OFF	S,TERM			;SKIP IF NOT EOF.
	MOVE	P2,[POINT 6,[SIXBIT "EOF2"]];CHANGE MESSAGE.
	IF.OFF	S,FIN			;SKIP IF NOT END OF REEL.
	MOVE	P2,[POINT 6,[SIXBIT "EOV2"]];CHANGE MESSAGE.
	MOVEI	P3,^D4			;COUNT TO PUT.
	GOSUB	PLACE			;INTO BUFFER.
	HRRZ	T1,OM			;GET THE OUTPUT MODE.
	SETZM	T2			;CLEAR INDEX.
	CAIN	T1,VEBMOD		;IS IT VARIABLE EBCDIC.
	MOVEI	T2,ONE			;YES SET INDEX TO ONE.
	CAIN	T1,EBCMOD		;IS IF FIXED EBCDIC.
	MOVEI	T2,TWO			;YES SET INDEX TO TWO.
	MOVE	CH,[EXP 'U','V','F'](T2);GET DISCRIPTOR.
	IDPB	CH,P1			;INTO BUFFER.
	MOVE	T1,OFILE+RECSIZ		;GET THE RECORD SIZE.
	ADD	T1,[EXP 0,4,0](T2)	;ADD IN THE OFFSET.
	SKIPE	OFILE+BLKFCT		;SKIP IF NO BLOCKING FACTOR.
	IMUL	T1,OFILE+BLKFCT		;MULTIPLY BY BLOCKING FACTOR.
	ADD	T1,[EXP 0,4,0](T2)	;ADD IN OFFSET.
	SAVE	T2			;SAVE THE INDEX.
	GOSUB	MAKTWO			;CONVERT IT TO TWO WORDS.
	MOVE	P2,[POINT 6,T2,5]	;POINTER TO WHAT WE WANT.
	MOVEI	P3,^D5			;CHARACTERS TO PLACE.
	GOSUB	PLACE			;INTO BUFFER.
	UNSAVE	T2			;RESTORE THE INDEX.
	MOVE	T1,OFILE+RECSIZ		;GET THE RECORD SIZE.
	ADD	T1,[EXP 0,4,0](T2)	;ADD IN THE OFFSET.
	IMUL	T1,[EXP 0,1,1](T2)	;PRODUCE RECORD SIZE.
	GOSUB	MAKTWO			;CONVERT TO TWO WORDS.
	MOVE	P2,[POINT 6,T2,5]	;POINTER TO WHAT WE WANT.
	MOVEI	P3,^D5			;CHARACTERS TO PLACE.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	T1,OF			;GET THE OUTPUT CHANNEL NUMBER.
	MME	T1,.TAPE		;GET THE DENSITY OF THE TAPE.
	MOVEI	T1,3			;MAKE IT 800 IF IT FAILS.
	ADDI	T1,'0'-1		;MAKE IT SIXBIT.
	IDPB	T1,P1			;INTO BUFFER.
	MOVEI	CH,'0'			;LOAD A ZERO FOR EOF.
	IF.OFF	S,FIN			;SKIP IF NOT EOV.
	MOVEI	CH,'1'			;DENOTE END OF REEL.
	IDPB	CH,P1			;SAVE IT IN THE BUFFER.
	MOVE	P2,[POINT 6,PRGNAM]	;POINT TO OUR NAME.
	MOVEI	P3,^D6			;CHARACTERS IN NAME.
	GOSUB	PLACE			;INTO BUFFER.
	MOVE	P2,[POINT 6,[SIXBIT "  /"]];SOME GOOD THINGS.
	MOVEI	P3,^D3			;CHARACTERS TO MOVE.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	P3,^D12			;COUNT FOR SOME SPACES.
	GOSUB	SPACE			;INTO BUFFER.
	MOVEI	CH,'B'			;LOAD A B FOR BLOCKED RECORDS.
	IF.OFF	OF,SPAN			;ARE WE SPANNING.
	MOVEI	CH,'S'			;YES LOAD AN S.
	IDPB	CH,P1			;SAVE IT IN THE BUFFER.
	MOVEI	P3,^D41			;FINISH THE RECORD WITH
	GOSUB	SPACE			;SPACES.
	MOVE	T2,TEMP1		;GET THE MODE OF THE LABEL.
	GOTO	LB.CLO			;WRITE THE LABEL.

;HERE TO PEGE AN IBM LABEL.

LB.PBM:	TEO	S,PRG			;BEEN HERE BEFORE.
	AOSA	T1,OFILE+PERGE		;YES SO BUMP NUMBER.
	MOVE	T1,OFILE+PERGE		;NO SO GET THE PERGE NUMBER.
	GOSUB	MAKTWO			;CONVERT IT TO TWO WORDS.
	MOVE	P1,[POINT 6,RELNUM]	;POINTER TO STORAGGE.
	MOVE	P2,[POINT 6,T2]		;POINTER TO NUMBER.
	MOVEI	P3,^D6			;COUNT TO MOVE.
	GOSUB	PLACE			;INTO STORAGE.
	GETSTS	OF,T1			;GET THE DEVICE STATUS.
	IF.OFF	T1,E.BOT,LB.OBH		;VOL1 ONLY AT BOT.
	GOTO	LB.BVL			;OTHERWISE LABELS ARE STANDARD.
;HERE TO WRITE GE635 LABELS IN GE635 BCD.

LB.OGE:	MOVE	P1,[POINT 6,OUTBUF]	;SET POINTER TO BUFFER.
	IF.ON	S,TERM,LB.GED		;JUMP IF REALLY TRAILERS.
	MOVE	P2,[POINT 6,[SIXBIT "GE  600 BTL GE PHX "]];IDENTIFIER.
	MOVEI	P3,^D19			;COUNTER.
	GOSUB	PLACE			;PUT IT IN THE BUFFER.
	MOVE	P2,[POINT 6,OFILE+NAME]	;POINTER TO LABEL ID.
	MOVEI	P3,^D5			;FIVE CHARACTERS IN NAME.
	GOSUB	PLACE			;INTO BUFFER.
	SETZM	CH			;AN UNUSED SPACE.
	IDPB	CH,P1			;PLACE IT IN THE BUFFER.
	MOVE	P2,[POINT 6,OFILE+NAME]	;POINTER TO SERIAL SAME AS NAME.
	MOVEI	P3,^D5			;COUNT TO PUT.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	P3,^D2			;SOME SPACES.
	GOSUB	SPACE			;ADD TO BUFFER.
	MOVE	P2,[POINT 6,OFILE+VOL]	;POINTER TO VOLUME NUMBER.
	MOVEI	P3,^D4			;COUNT TO PUT.
	GOSUB	PLACE			;INTO BUFFER.
	SETZM	CH			;ANOTHER OUT OF PLACE SPACE.
	IDPB	CH,P1			;PLACE IN THE BUFFER.
	MME	T1,.DATE		;GET THE DATE.
	GOSUB	BCLDAT			;TO FORMAT WE WANT.
	MOVE	P2,[POINT 6,[SIXBIT "   000"]];UNUSED THINGS.
	MOVEI	P3,^D6			;COUNT TO PLACE.
	GOSUB	PLACE			;ADD TO THE BUFFER.
	MOVE	P2,[POINT 6,PASS]	;POINTER TO PASSWORD.
	MOVEI	P3,^D12			;CHARACTERS IN PASSWORD.
	GOSUB	PLACE			;PUT IT IN THE BUFFER.
	SKIPE	PASS			;IS THERE A PASSWORD.
	GOTO	LB.PRT			;YES PROTECT THE TAPE.
	SKIPN	PASS+1			;TRY OTHER HALF.
	SKIPA	P2,[POINT 6,[SIXBIT "!!!000"]];NO PROTECTION.
LB.PRT:	MOVE	P2,[POINT 6,[SIXBIT "!!!^00"]];PROTECTION WORD.
	MOVEI	P3,^D6			;COUNT TO PLACE.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	CH,'0'			;FILL THE REST OF THE LABEL
	MOVEI	P3,^D14			;WITH ZEROS.
	GOSUB	ANYCHR			;INTO BUFFER.
	MOVEI	T2,XBDMOD		;MODE TO WRITE IT IN.
;HERE TO WRITE THE LABEL TO THE TAPE.

LB.CLO:	GOSUB	WRILAB			;WRITE THE LABEL TO TAPE.
	CLOSE	OF,ZERO			;WRITE AN EOF MARK.
	GETSTS	OF,T1			;GET THE DEVICE STATUS.
	TEZ	T1,E.ERR		;SKIP IF NO ERROR.
	PRINT	(% Error while writing label.")
	SETSTS	OF,ZERO(T1)		;RESET THE STATUS.
	RETURN	ZERO			;BACK TO CALLER.
LB.GED:	MOVE	P2,[POINT 6,[SIXBIT " EOF  "]];ASSUME END OF FILE.
	IF.OFF	S,FIN			;SKIP IF WE ARE RIGHT.
	MOVE	P2,[POINT 6,[SIXBIT " EOR  "]];SET IT AS END OF REEL.
	MOVEI	P3,^D6			;COUNT TO PLACE.
	GOSUB	PLACE			;INTO BUFFER.
	MOVE	T1,OBCNT		;GET THE BLOCKS WRITTEN.
	GOSUB	MAKTWO			;CONVERT TO TWO WORDS.
	MOVE	P2,[POINT 6,T2]		;POINT TO WHAT WE WANT.
	MOVEI	P3,^D6			;SIX TO PLACE.
	GOSUB	PLACE			;PLACE THEM.
	MOVEI	CH,'0'			;FILL THE REST OF THE LABEL
	MOVEI	P3,^D68			;WITH ZEROS.
	GOSUB	ANYCHR			;FINISH THE LABEL.
	GOTO	LB.CLO-1		;WRITE THE LABEL.
;HERE TO READ AND WRITE OUTPUT LABELS
;IN BCL FORMAT.

LB.OBL:	IF.ON	S,TERM,LB.BGN		;JUMP IF TRAILER.
	GETSTS	OF,T1			;GET THE DEVICE STATUS.
	IF.OFF	T1,E.BOT,LB.BGN		;JUMP IF NOT AT BOT.
	SKIPE	OFILE+PERGE		;SERIAL NUMBER SPECIFIED.
	GOTO	LB.PBL			;YES PERGE THE LABEL.
	MOVE	T2,OM			;GET THE MODE OF THE OUTPUT.
	GOSUB	REDOUT			;READ THE OUTPUT LABEL.
	GOTO	BADTM			;EOF MARK FOUND.
	DRIVE	OF,.BSR			;BACK UP TO START OF LABEL.
	DRIVE	OF,.WAT			;WAIT FOR COMPLETION.
	MOVE	T1,OUTBUF		;PICK UP HEADER WORD.
	CAME	T1,[SIXBIT " LABEL"]	;MAKE SURE IT IS A LABEL.
	GOTO	NOTLAB			;YOU LOOSE.
	MOVE	P2,[POINT 6,OUTBUF+10,29];POINT TO REEL NUMBER.
	MOVE	P1,[POINT 6,RELNUM]	;POINTER TO STORAGE.
	MOVEI	P3,^D5			;CHARACTERS TO COPY.
	GOSUB	PLACE			;COPY THEM.
LB.BGN:	MOVE	P1,[POINT 6,OUTBUF]	;POINTER TO STORAGE.
	MOVE	P2,[POINT 6,[SIXBIT " LABEL  0000000 0"]];IDENTIFIER.
	MOVEI	P3,^D17			;COUNT TO PLACE.
	GOSUB	PLACE			;PLACE IT IN PLACE.
	MOVE	P2,[POINT 6,OFILE+NAME]	;POINTER TO LABEL-ID.
	MOVEI	P3,^D6			;SIX CHARACTERS IN ID.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	P2,' '			;PUT IN AN UNUSED SPACE.
	IDPB	P2,P1			;PUT IT INTO LABEL.
	MOVE	P2,[POINT 6,OFILE+VOL,5];POINTER TO VOLUME NUMBER.
	MOVEI	P3,^D3			;VOLUME GOES FROM 1-999.
	GOSUB	PLACE			;PUT IT AWAY.
	MME	T1,.DATE		;GET TODAY'S DATE.
	GOSUB	BCLDAT			;CONVERT TO FORMAT WE WANT.
	MOVEI	CH,'0'			;SOME UNUSED POSITIONS.
	MOVEI	P3,^D2			;COUNTER.
	GOSUB	ANYCHR			;PUT THEM AWAY.
	MME	T1,.DATE		;GET TODAY'S DATE AGAIN.
	ADDI	T1,^D984		;ADD IN SAVE FACTOR.
	GOSUB	BCLDAT			;CONVERT DATE.
	MOVEI	P2,'0'			;LOAD A ZERO FOR END OF FILE.
	IF.OFF	S,FIN			;IS THIS END OF FILE.
	MOVEI	P2,'1'			;NO JUST END OF REEL.
	IDPB	P2,P1			;SAVE IT IN BUFFER.
	IF.OFF	S,TERM,LB.HDR		;JUMP IF THIS IS REALLY HEADER.
	MOVE	T1,OBCNT		;PICK UP BLOCKS WRITTEN.
	GOSUB	MAKTWO			;CONVERT IT TO TWO WORDS.
	MOVE	P2,[POINT 6,T2,5]	;POINT TO WHAT WE WANT.
	MOVEI	P3,^D5			;FIVE CHARACTERS TO COPY.
	GOSUB	PLACE			;COPY TO OUTPUT BUFFER.
	MOVE	T1,ORCNT		;GET RECORD COUNT.
	GOSUB	MAKTWO			;MAKE TWO WORDS.
	MOVE	P2,[POINT 6,T1,29]	;POINT TO WHAT WE WANT.
	MOVEI	P3,^D7			;CHARACTERS TO PLACE.
	GOSUB	PLACE			;PLACE THEM INTO PLACE.
	MOVEI	CH,'0'			;UNUSED POSITION.
	IDPB	CH,P1			;PUT IT AWAY.
LB.FIN:	MOVE	P2,[POINT 6,RELNUM]	;POINTER TO REEL NUMBER.
	MOVEI	P3,^D5			;FIVE CHARACTERS TO PUT.
	GOSUB	PLACE			;PLACE THEM.
	MOVEI	P3,^D26			;POSITIONS LEFT.
	MOVEI	CH,'0'			;FINISH BUFFER WITH ZEROS.
	GOSUB	ANYCHR			;FILL THE BUFFER.
	MOVE	T2,OM			;GET THE MODE OF THE OUTPUT.
	GOTO	LB.CLO			;WRITE THE LABEL.
LB.HDR:	MOVEI	P3,^D13			;IF HEADER WE DON'T WRITE
	MOVEI	CH,'0'			;BLOCK AND RECORD COUNTS.
	GOSUB	ANYCHR			;FILL THESE WITH ZEROS.
	GOTO	LB.FIN			;DO THE REST.

;HERE IF THE LABELS ARE TO BE WRITTEN IN BCL FORMAT
;BUT NOT CHECKED FIRST. IN THIS CASE THE REEL NUMBER
;OF THE TAPE WAS SPECIFIED IN THE REEL SWITCH.

LB.PBL:	TEO	S,PRG			;HAVE WE ALREADY DONE THIS.
	AOSA	T1,OFILE+PERGE		;YES SO BUMP REEL NUMBER FOR LABEL.
	MOVE	T1,OFILE+PERGE		;GET THE NEW NUMBER.
	GOSUB	MAKTWO			;CONVERT IT TO SIXBIT.
	MOVE	P1,[POINT 6,RELNUM]	;POINTER TO STORAGE.
	MOVE	P2,[POINT 6,T2,5]	;POINTER TO WHAT WE WANT.
	MOVEI	P3,^D5			;COUNT TO PLACE.
	GOSUB	PLACE			;PLACE THEM.
	GOTO	LB.BGN			;OTHERWISE LABELS ARE STANDARD.
;HERE TO WRITE OUT DEC-COBOL HEADER AND TRAILER LABELS.

LB.OCL:	MOVE	P2,[POINT 6,[SIXBIT "HDR1"]];ASSUME HEADER LABEL.
	IF.OFF	S,TERM			;IS THIS A TERMINAL LABEL.
	MOVE	P2,[POINT 6,[SIXBIT "EOF1"]];YES CHANGE MESSAGE.
	IF.OFF	S,FIN			;IS THIS REALLY JUST END OF REEL.
	MOVE	P2,[POINT 6,[SIXBIT "EOV1"]];JUST END OF REEL.
	MOVE	P1,[POINT 6,OUTBUF]	;SET POINTER TO LABEL BUFFER.
	MOVEI	P3,^D4			;COUNT TO PLACE.
	GOSUB	PLACE			;PUT IT INTO BUFFER.
	MOVE	P2,[POINT 6,OFILE+NAME]	;POINTER TO NAME.
	MOVEI	P3,^D9			;NINE CHARACTERS IN NAME.
	GOSUB	PLACE			;INTO BUFFER.
	MOVEI	P3,^D14			;FOURTEEN SPACES.
	GOSUB	SPACE			;INTO BUFFER.
	MOVE	P2,[POINT 6,OFILE+VOL]	;GET VOLUME NUMBER.
	MOVEI	P3,^D4			;GET THE COUNT OF CHARACTERS.
	GOSUB	PLACE			;PUT IT INTO BUFFER.
	MOVEI	P3,^D10			;SET COUNT.
	GOSUB	SPACE			;INTO BUFFER.
	MME	T1,.DATE		;GET THE DATE.
	GOSUB	COBDAT			;FIX IT INTO PLACE.
	MOVEI	P3,^D33			;NUMBER OF PLACES LEFT.
	GOSUB	SPACE			;SPACES TO BUFFER.
	MOVE	T2,OM			;GET THE MODE OF THE OUTPUT.
	MOVNI	P2,^D80			;CHARACTERS IN LABEL.
	GOSUB	WRILAB			;WRITE THE LABEL TO TAPE.
	IF.OFF	S,TERM			;IS THIS AN EOF LABEL.
	CLOSE	OF,ZERO			;YES WRITE EOF MARK.
	RETURN	ZERO			;BACK TO SENDER.
;HERE TO PUT OUT A HEADER FOR THE LINE PRINTER.

HDRLPT:	IF.ON	OF,NOHEAD,RET0		;RETURN IF NOT WANTED.
	ON	S,LHEAD			;SAY WE ARE DOING HEADERS.
	MOVE	T1,[POINT 7,HDRWRD]	;SET POINTER TO STORAGE.
	MME	T3,.PPN			;GET OUR PPN.
	NOP				;IN CASE OF JACCT.
	HLLZS	T3			;JUST THE PROJECT NUMBER.
	GOSUB	HDR1			;CONVERT TO ASCII.
	MOVEI	T2,","			;TO SEPARATE THINGS.
	IDPB	T2,T1			;SAVE IT.
	MME	T3,.PPN			;GET THE PPN BACK.
	NOP				;IN CASE OF JACCT.
	HRLZ	T3,T3			;TO THE RIGHT HALF.
	GOSUB	HDR1			;CONVERT IT.
	SETZM	T2			;SET END FLAG.
	IDPB	T2,T1			;SAVE IT.
	SETZB	P1,P2			;CLEAR COUNTERS.
	GOSUB	MATRIX			;BLACKOUT SOMETHINGS.
	GOTO	XNAME			;TYPE THE FILE NAME.
HDR1:	MOVNI	P1,6			;COUNT TO PLACE.
	SETZM	T2			;CLEAR A REGISTER.
	LSHC	T2,3			;GET A DIGIT.
	MOVEI	T2,"0"(T2)		;MAKE IT ASCII.
	IDPB	T2,T1			;SAVE IT.
	AOJN	P1,HDR1+1		;CONTINUE FOR THE COUNT.
	RETURN	ZERO			;AND RETURN.

;HERE TO PUT A TRAILER HEADER ON THE LINE PRINTER.

EOFLPT:	IF.ON	OF,NOHEAD,RET0		;RETURN IF NOT WANTED.
	ON	S,LHEAD			;SAY WE ARE DOING HEADINGS.
	MOVEI	CH,14			;GET A FORM FEED FIRST.
	TNZ	S,FF			;SKIP IF LAST WAS A FORM.
	GOSUB	UME4			;ONTO THE DEVICE.
	GOSUB	MATRIX			;START IT GOING.
EOF1:	MME	T1,.TIME		;GET THE TIME OF DAY.
	ANDI	T1,77			;MASK OUT SOME BITS.
	CAIL	T1,ENDCNT		;SEE IF OUT OF THE TABLE.
	GOTO	EOF1			;TRY AGAIN.
	CAMN	T1,LSTVAL		;IS IT THE SAME AS THE LAST.
	GOTO	EOF1			;TRY AGAIN.
	MOVEM	T1,LSTVAL		;SAVE THE LAST ONE.
	MOVE	T1,ENDTAB(T1)		;GET THE LOCATION OF THE MESSAGE.
	MOVE	T2,ONE(T1)		;GET THE SECOND HALF.
	MOVE	T1,ZERO(T1)		;GET THE FIRST HALF.
	GOSUB	CODE			;PUT IT INTO ASCII.
;HERE TO PLACE THE FILE NAME AND THE ASSORTED OTHER
;THINGS ON THE PRINTER.

XNAME:	GOSUB	PICTURE			;PUT THE PICTURE OUT.
	MOVE	T1,OFILE+NAME		;GET THE NAME.
	HLLZ	T2,OFILE+EXT		;GET THE EXTENSION.
	GOSUB	DECODE			;SET IT UP RIGHT.
	GOSUB	PICTURE			;ONTO THE LINE PRINTER.
	GOSUB	MATRIX			;BLACKOUT SOMETINGS.
	UME	.ASC,[BYTE (7)15,12,0]	;SKIP A LINE.
	MME	T2,.PJOB		;GET MY JOB NUMBER.
	HRLZ	T2,T2			;INTO THE RIGHT HALF.
	HRRI	T2,31			;TABLE ENTRY FOR NAME.
	MME	T2,.TAB			;GET FIRST HALF OF NAME.
	SETZM	T2			;CLEAR IF CAN'T GET IT.
	UME	.SIX,T2			;INTO BUFFER.
	MME	T2,.PJOB		;GET MY JOB NUMBER BACK.
	HRLZ	T2,T2			;INTO RIGHT HALF.
	HRRI	T2,32			;SECOND HALF OF NAME.
	MME	T2,.TAB			;GET THE ENTRY.
	SETZM	T2			;CLEAR IF CAN'T GET IT.
	UME	.SIX,T2			;INTO BUFFER.
	UME	.ASC,[ASCIZ "   "]	;TO SEPARATE THINGS.
	GOSUB	PUTDAT			;PUT THE DATE.
	UME	.ASC,[ASCIZ "   "]	;SEPARATE THINGS.
	GOSUB	PUTTIM			;PUT A TIME STAMP ON IT.
	MOVEI	CH,14			;A FORM FEED.
	GOSUB	PUT			;INTO BUFFER.
	OFF	S,LHEAD			;HEADINGS ARE DONE.
	GOTO	EMPTY			;WRITE THE BUFFERS.
;HERE TO CONVERT TWO SIXBIT WORDS TO ASCII.

DECODE:	JUMPE	T2,CODE			;DON'T ADD PERIOD IF NO EXTENSION.
	LSH	T2,-6			;MAKE ROOM FOR PERIOD.
	IOR	T2,[SIXBIT "."]		;ADD A PERIOD.
CODE:	MOVE	T3,[POINT 6,T1]		;GET A POINTER TO DATA.
	MOVE	P3,[POINT 7,HDRWRD]	;POINTER TO STORAGE.
	MOVNI	P1,15			;SET THE MAX TO DO.
	MOVNI	P2,^D12			;NUMBER OF CHARACTERS TO DO.
CODE1:	ILDB	CH,T3			;GET A CHARACTER.
	JUMPE	CH,CODE2		;DON'T DO NULLS.
	MOVEI	CH," "(CH)		;CONVERT TO ASCII.
	IDPB	CH,P3			;SAVE IT.
	AOS	P1			;COUNT THE CHARACTER.
CODE2:	AOJN	P2,CODE1		;JUMP IF STILL HAVE MORE.
	SETZM	CH			;FOR END FLAG.
	IDPB	CH,P3			;SAVE IT.
CODE3:	MOVN	P1,P1			;MAKE P1 POSITIVE.
	IMULI	P1,6			;SIX SPACES PER CHARACTER.
	SETZM	P2			;CLEAR P1+1.
	LSHC	P1,-1			;DIVIDE P1 BY TWO.
	ROT	P2,1			;SO IT CAN BE USED AS AN INDEX.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO SEND SOME "X"'S TO THE LINE PRINTER.

MATRIX:	GOSUB	MAT0			;CALL THE X PRINTER TWICE.
	GOSUB	MAT0			;ONE MORE TIME.
	UME	.ASC,[BYTE (7)15,12,0]	;SKIP A LINE.
	RETURN	ZERO			;BACK TO CALLER.
MAT0:	MOVNI	P4,^D131		;NUMBER OF POSITIONS.
	MOVEI	CH,"X"			;CHARACTER TO PRINT.
	GOSUB	UME4			;PLACE IT.
	AOJN	P4,.-2			;CONTINUE ON.
	UME	.ASC,[BYTE (7)15,12,0]	;SKIP A LINE.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO PRINT A CHARACTER POSTION ALL FILLED IN.

BLACKO:	GOSUB	BLACK			;CALL THE STAR PRINTER
	GOSUB	BLACK			;THREE TINES.
BLACK:	MOVNI	P4,5			;GET A COUNTER.
	MOVEI	CH,"*"			;CHAARACTER TO PRINT.
	GOSUB	UME4			;ON THE DEVICE.
	AOJN	P4,.-2			;LOOP ON THAT.
	MOVEI	CH," "			;A SPACE TO SEPARATE THINGS.
	GOTO	UME4			;ONTO THE DEVICE.

;HERE TO PRINT SOME BLANKS TO EVEN THINGS UP.

XSPACE:	JUMPE	P1,RET0			;JUMP IF DON'T NEED ANY.
	MOVN	P4,P1			;GET THE NEGATIVE COUNT.
	MOVEI	CH," "			;GET A SPACE.
	GOSUB	PUT			;INTO THE BUFFER.
	AOJN	P4,.-2			;FOR THE COUNT.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO PRINT THE BLOCK LETTERS ON THE LINE PRINTER.

PICTUR:	MOVNI	P3,43			;SET UP BITS IN MAP.
	MOVE	T2,[POINT 7,HDRWRD]	;POINTER TO THINGS TO PLACE.
	GOSUB	BLACKOUT		;BEGIN IT GOING.
	UME	.ASC,BLANK		;SOME BLANKS.
	GOSUB	XSPACE			;EVEN THINGS UP.
	ILDB	T3,T2			;GET A BYTE.
	JUMPE	T3,.+3			;JUMP IF AT END.
	GOSUB	XPUT			;INTO BUFFER.
	GOTO	.-3			;CONTINUE LOOP.
	GOSUB	XSPACE			;SOME SPACES.
	UME	.ASC,BLANK(P2)		;SOME ODD SPACES.
	GOSUB	BLACKOUT		;WIPE THINGS OUT.
	UME	.ASC,[BYTE (7)15,12,0]	;NEXT LINE.
	ADDI	P3,5			;SET NEXT BIT PATTERN.
	JUMPL	P3,PICTURE+1		;TEST AND JUMP IF HAVE MORE.
	UME	.ASC,[BYTE (7)15,12,0]	;NEXT LINE.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO ACTUALLY PUT THE STUFF OUT.

XPUT:	MOVE	T3,CHRTAB-40(T3)	;GET A BIT PATTERN.
	ROT	T3,43(P3)		;DIAL A FIVE BIT GROUP.
	MOVNI	P4,5			;SET UP COUNTER.
XPUT1:	MOVEI	CH," "			;LOAD A SPACE.
	SKIPGE	T3			;SKIP IF O.K.
	MOVEI	CH,"@"			;ELSE SET IT FOR ON BIT.
	GOSUB	UME4			;TO THE DEVICE.
	ROT	T3,1			;DIAL NEXT BIT.
	AOJL	P4,XPUT1		;CONTINUE ON.
	MOVEI	CH," "			;A TRAILING SPACE.
	GOTO	PUT			;TO THE LINE PRINTER.

BLANK:	ASCIZ	"         "

	USE	DATA

BSS	HDRWRD,5
BSS	LSTVAL,ONE

	USE	CODE
SUBTTL				*** BASIC I/O ROUTINES ***

;HERE TO BUILD BUFFERS FOR MAG-TAPE.

MAKE:	HRRZ	T3,CHRMOD(SIDE)		;GET THE MODE OF THE INPUT.
	SKIPN	T2,RECSIZ(SIDE)		;GET THE RECORD SIZE.
	RETURN	ZERO			;NONE SPECIFIED USE DEFAULT.
	CAIG	T3,GEAMOD		;SKIP IF NOT ASCII.
	ADDI	T2,TWO			;ACCOUNT FOR CRLF.
	MOVE	P1,STS(T3)		;GET THE STATUS WORD.
	ADDI	T2,ZERO(P1)		;ADD WHAT IS NEEDED FOR CTRL WORD.
	HRRZ	P2,MSIZ(T3)		;GET THE BYTES PER WORD.
	CAIE	T3,SIXMOD		;SKIP IF SIXBIT.
	GOTO	MAKE1			;ELSE FORGET NEXT FEW THINGS.
	ADDI	T2,-1(P2)		;FORCE TO A WORD BOUNDARY.
	IDIVI	T2,ZERO(P2)		;PRODUCE INTEGER PART.
	IMULI	T2,ZERO(P2)		;PRODUCE A WORD MULTIPLE.
MAKE1:	SKIPE	BLKFCT(SIDE)		;BAG THE MULTIPLY IF ZERO.
	IMUL	T2,BLKFCT(SIDE)		;MULTIPLY BY BLOCKING FACTOR.
	IF.OFF	P1,EXW			;DO WE NEED EXTRA STUFF.
	ADDI	T2,ZERO(P1)		;YES SO ADD IT IN.
	ADDI	T2,-1(P2)		;ADD BYTE SIZE MINUS ONE.
	IDIV	T2,P2			;BUFFFER LENGTH IN WORDS.
WRDCNT:	ADDI	T2,ONE			;A LITTLE OVERHEAD.
	CAIGE	T2,^D65			;MUST HAVE ROOM FOR HEADERS.
	MOVEI	T2,^D65			;MAKE ROOM FOR THEM.
	HRRZ	T1,ZERO(T1)		;GET ADDRESS OF FIRST BUFFER.
	SKIPN	P3,BUFNUM(SIDE)		;GET NUMBER OF BUFFERS.
	MOVEI	P3,TWO			;DEFAULT IS TWO.
	MOVEI	P2,TWO(T2)		;GET TOTAL SIZE OF BUFFERS.
	IMULI	P2,ZERO(P3)		;COMPUTE TOTAL WORDS NEEDED.
	ADDI	P2,-1(T1)		;GET THE LAST LOCATION NEEDED.
	HRRM	P2,.JBFF		;SET IT AS FIRST FREE.
	CAMG	P2,.JBREL		;DO WE NEED MORE CORE.
	GOTO	.+3			;NO IT IS ALRIGHT.
	MME	P2,.CORE		;GET SOME CORE.
	GOTO	NOCORE			;CAN'T GET IT.
	HRLZI	P1,-1(T1)		;GET ADDRESS OF THE TOP OF BUFFERS.
	HRRI	P1,ZERO(T1)		;GET THE ADDRESS PLUS ONE.
	HRRZ	P2,.JBFF		;GET THE LAST LOCATION.
	SETZM	-1(P1)			;CLEAR FIRST WORD.
	BLT	P1,-1(P2)		;CLEAR OUT JUNK.
	SKIPA	P1,T1			;GET POINTER TO FIRST INTO P1.
MAKE2:	HRRZI	P1,ZERO(P2)		;GET POINTER TO NEXT BUFFER.
	MOVEI	P2,ZERO(P1)		;GET ADDRESS OF THIS BUFFER.
	HRLI	P2,ZERO(T2)		;SET THE SIZE OF BUFFER.
	ADDI	P2,TWO(T2)		;POINT P2 TO NEXT BUFFER.
	MOVEM	P2,ZERO(P1)		;PLACE IN THIS ONE'S HEADER.
	SOJG	P3,MAKE2		;JUMP IF NEED TO DO MORE.
	HRRM	T1,ZERO(P1)		;LINK LAST TO FIRST.
	RETURN	ZERO			;AND RETURN.
;HERE TO SET ASIDE A BUFFER AREA FOR VARIABLE LENGTH
;OUTPUT BLOCKS.

GETBUF:	SKIPN	T1,RECPTR		;BEEN HERE BEFORE.
	GOTO	GTBF0			;NO CONTINUE ON.
	MOVEM	T1,CURPTR		;SAVE AS CURRENT POINTER.
	RETURN	ZERO			;AND RETURN.
GTBF0:	HRRZ	T3,MSIZ(OM)		;GET THE BYTES/WORD.
	MOVE	T2,OFILE+RECSIZ		;GET THE OUTPUT RECORD SIZE.
	MOVE	T1,STS(OM)		;GET THE STATUS WORD.
	ADDI	T2,ZERO(T1)		;ADD IN SIZE OF CTRL WORD.
	SAVE	T3			;SAVE BYTES/RECORD.
	IDIVI	T2,ZERO(T3)		;COMPUTE WORDS FOR RECORD.
	SKIPE	T3			;SKIP IF REMAINDER.
	AOS	T2			;COUNT EXTRA WORD.
	UNSAVE	T3			;RESTORE WORDS PER RECORD.
	IMULI	T2,ZERO(T3)		;BACK TO BYTES.
	SKIPE	OFILE+BLKFCT		;NO SKIP IF BLOCKING FACTOR.
	IMUL	T2,OFILE+BLKFCT		;MULTIPLY BY BLOCKING FACTOR.
	IF.OFF	T1,EXW			;DO WE NEED MORE.
	ADDI	T2,ZERO(T1)		;YES SO ADD IT IN.
	ADDI	T2,-1(T3)		;ADD BYTE SIZE MINUS ONE.
	IDIV	T2,T3			;T2 IS LENGTH NEEDED IN WORDS.
	MOVE	T3,.JBFF		;FIRST LOCATION FREE.
	MOVEI	P4,ONE(T3)		;START OF THE BUFFER.
	MOVEI	T3,ONE(P4)		;COPY TO ANOTHER AC.
	ADD	T3,T2			;END OF THE BUFFER.
	HRRM	T3,.JBFF		;UPDATE TOP OF CORE.
	IORI	T3,1777			;ROUND UP TO K.
	CAMG	T3,.JBREL		;DO WE HAVE ENOUGH.
	GOTO	.+3			;DON'T ASK FOR MORE.
	MME	T3,.CORE		;GET MORE CORE.
	GOTO	NOCORE			;NO MORE CORE YOU LOOSE.
	HRLZ	T2,P4			;START OF BUFFER.
	HRRI	T2,ONE(P4)		;START OF BUFFER PLUS ONE.
	SETZM	ZERO(P4)		;CLEAR FIRST WORD.
	MOVE	T3,.JBFF		;GET POINTER TO END OF CORE.
	BLT	T2,-1(T3)		;CLEAR THE BUFFERS.
	HLL	P4,MPTR(OM)		;GET A BYTE POINTER TO BUFFER.
	MOVEM	P4,RECPTR		;SET AS THE RECORD POINTER.
	MOVEM	P4,CURPTR		;ALSO AS CURRENT POINTER.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO COMPUTE THE NUMBER OF SECTORS TO WRITE
;IN ORDER TO SATISFY THE BLOCKING FACTOR.

SECTOR:	MOVE	T3,MOD(SIDE)		;GET THE DEVICE BITS.
	IF.OFF	T3,DIR,SEC0		;JUMP IF NOT DSK OR DTA.
	HRRZ	T3,CHRMOD(SIDE)		;GET THE FILE MODE.
	MOVE	T2,RECSIZ(SIDE)		;GET THE RECORD SIZE.
	MOVE	P1,STS(T3)		;MODE STATUS BITS.
	ADDI	T2,ZERO(P1)		;ADD IN SIZE OF CTRL WORD.
	SKIPN	BLKFCT(SIDE)		;DO WE HAVE A BLOCKING FACTOR.
	GOTO	SEC0			;NO WE DON'T.
	IMUL	T2,BLKFCT(SIDE)		;MULTIPLY BY BLOCKING FACTOR.
	IF.OFF	P1,EXW			;DO WE NEED EXTRA STUFF.
	ADDI	T2,ZERO(P1)		;YES SO ADD IT IN.
	HRRZ	T3,MSIZ(T3)		;GET BYTES/WORD.
	ADDI	T2,-1(T3)		;ADD BYTE SIZE MINUS ONE.
	IDIV	T2,T3			;WORDS FOR A BLOCK.
	MOVE	T1,MOD(SIDE)		;DEVICE MODE BITS.
	MOVEI	T3,200			;WORDS PER BLOCK ON DISK.
	IF.ON	T1,DSK			;SKIP IF DISK.
	MOVEI	T3,177			;WORDS PER BLOCK ON DTA.
	ADDI	T2,-1(T3)		;ADD BLOCK SIZE MINUS ONE.
	IDIVI	T2,ZERO(T3)		;T3 HAS SECTORS FOR BLOCK.
	MOVEM	T2,SEC(SIDE)		;SAVE IN DATA BLOCK.
	RETURN	ZERO			;BACK TO CALLER.
SEC0:	SETOM	SEC(SIDE)		;FOR ALL THOSE BAD GUYS.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO DO AN "INBUF" OR "OUTBUF" FOR A DEVICE BUT TO
;MAKE SURE WE HAVE ENOUGH CORE BEFORE WE DO IT.

MONIBF:	SKIPA	SIDE,[IFILE]		;INDEX TO INPUT STUFF.
MONOBF:	MOVEI	SIDE,OFILE		;INDEX FOR OUTPUT STUFF.
	SKIPN	T2,BUFNUM(SIDE)		;GET NUMBER OF BUFFERS.
	MOVEI	T2,TWO			;DEFAULT TO MAKE.
	MOVEI	T3,STATUS(SIDE)		;POINTER FOR MME.
	MME	T3,.SIZ			;GET THE BUFFER SIZE FOR MODE.
	MOVEI	T3,203			;DEFAULT IF IT FAILS.
	HRRZ	T3,T3			;ZERO LEFT HALF.
	IMULI	T3,ZERO(T2)		;T3 HAS WORDS NEEDED.
	ADD	T3,.JBFF		;COMPUTE LAST WORD NEEDED.
	IORI	T3,1777			;CONVERT TO A K BOUNDARY.
	CAMG	T3,.JBREL		;SEE IF ENOUGH ROOM.
	GOTO	.+3			;WE HAVE ENOUGH.
	MME	T3,.CORE		;GET SOME MORE.
	GOTO	NOCORE			;YOU LOOSE.
	MOVE	T1,[INBUF IF,ZERO(T2)]	;GET BUFFERS FOR INPUT.
	CAIE	SIDE,IFILE		;SKIP OF THAT'S WHAT WE WANT.
	MOVE	T1,[OUTBUF OF,ZERO(T2)]	;ELSE CHANGE TO OUTPUT.
	XCT	T1			;GET THE BUFFERS.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO MOVE THE ALTER BUFFER INTO THE
;OUTPUT BUFFER.

BUFMOV:	HRRZ	T3,CURPTR		;GET LAST ADDRESS IN ALTER BUF.
	HRRZ	T2,RECPTR		;GET ADDRESS OF THE TOP.
	CAIG	T3,ZERO(T2)		;IS THERE ANYTHING THERE.
	RETURN	ZERO			;CAN'T MOVE NOTHING.
	SKIPE	OFILE+BLKFCT		;IS THERE A BLOCKING FACTOR.
	IF.ON	OF,SPAN,BUF3		;IF NOT DON'T USE A BLT.
	SKIPG	OBUF			;HAS BUFFER BEEN USED.
	OUTPUT	OF,ZERO			;NO USE IT.
	SUBI	T3,-1(T2)		;GET THE SIZE OF THE SOURCE.
	LDB	T2,[POINT 17,@OBUF,17]	;GET THE SIZE OF THE TARGET.
	SOS	T2			;TO THE RIGHT SIZE.
	HRL	T1,RECPTR		;SOURCE FOR BLT.
BUF0:	CAML	T2,T3			;WILL IT FIT IN ONE SHOT.
	GOTO	BUF1			;YES SO DO IT.
	SAVE	T1			;SAVE THE XWD FOR BLT.
	SAVE	T2			;SAVE THE DESTINATION LENGTH.
	SAVE	T3			;SAVE THE SOURCE LENGTH.
	GOSUB	BUF2			;MOVE A SEGMENT OF THE BUFFER.
	GOSUB	EMPTY			;WRITE IT TO THE DEVICE.
	UNSAVE	T3			;RESTORE THE SOURCE LENGTH.
	UNSAVE	T2			;RESTORE THE DESTINATION LENGTH.
	UNSAVE	T1			;RESTORE THE XWD FOR BLT.
	HLRZ	P3,T1			;GET THE OLD SOURCE.
	ADDI	P3,ZERO(T2)		;UPDATE ADDRESS TO POINT TO NEXT SEG.
	HRL	T1,P3			;CREATE NEW XWD FOR BLT.
	SUB	T3,T2			;ACCOUNT FOR THE NEXT MOVE.
	GOTO	BUF0			;DO THE NEXT SEGMENT.
BUF1:	MOVE	T2,T3			;COPY WHAT IS LEFT.
BUF2:	MOVE	T3,T2			;COPY WORDS TO MOVE.
	HRRZ	CH,MSIZ(OM)		;GET OUTPUT CHARACTERS/WORD.
	IMUL	T3,CH			;T3_CHARACTERS TO MOVE.
	EXCH	T3,OBUF+2		;T3_BUFCNT OBUF+2_CHR TO MOVE.
	SUBM	T3,OBUF+2		;ACCOUNT FOR CHARACTERS MOVED.
	HRRZ	T3,OBUF+1		;POINTER TO BUFFER MINUS ONE.
	HRRI	T1,ONE(T3)		;XWD FOR BLT.
	ADDI	T3,ZERO(T2)		;COMPUTE LAST WORD OF BUFFER.
	HRRM	T3,OBUF+1		;SAVE BYTE POINTER.
	BLT	T1,ZERO(T3)		;MOVE THE BUFFER.
	RETURN	ZERO			;BACK TO CALLER.
BUF3:	MOVE	P3,RECPTR		;GET THE POINTER TO TOP.
BUF4:	ILDB	CH,P3			;GET A BYTE.
	GOSUB	PUT			;TO THE OUTPUT BUFFER.
	CAME	P3,CURPTR		;SKIP IF ALL DONE.
	GOTO	BUF4			;ELSE MOVE THE REST.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO GET A CHARACTER FROM THE BUFFER.

GET:	TNZ	S,BAC,GET2		;JUMP IF WANT SAME CHARACTER.
	SOSGE	IBUF+2			;DECREMENT THE COUNT.
	GOTO	GET1			;NEED TO FILL THE BUFFER.
	ILDB	CH,IBUF+1		;GET A BYTE.
	MOVEM	CH,TCH			;SAVE IN CASE WE WANT IT LATTER.
	RETURN	ONE			;BACK TO SENDER.
GET1:	GOSUB	FILL			;READ THE NEXT BLOCK.
	RETURN	ZERO			;END OF FILE RETURN.
	GOTO	GET			;GET THE NEXT WORD.
GET2:	MOVE	CH,TCH			;GET LAST CHARACTER BACK.
	RETURN	ONE			;TAKE IT TO HIM.
FILL:	AOS	ISEC			;COUNT THE BLOCK TO READ.
	DEVOP	IN,IF,ZERO		;FILE UP THE BUFFERS.
	GOTO	BCLCHK			;SEE IF EOF -- WHAT THING THIS IS.
	GETSTS	IF,T1			;GET DEVICE STATUS.
	IF.OFF	T1,E.ERR,CHKEOF		;JUMP IF EOF.
	IF.ON	S,NI.ERR,RET1		;NO ERRORS FOR LABELS OR SKIPPING.
	IF.ON	T1,E.PAR,GETPAR		;PARITY ERROR FOUND.
	IF.ON	S,NI.LST,RET1		;LIST IGNORES OTHER ERRORS.
	GOTO	LKIERR			;JUMP REAL ERROR.
GETPAR:	IF.OFF	IF,NOERROR,IPERR	;JUMP IF WANTS SEE IT.
	AOS	INPERR			;COUNT THE ERROR.
	RETURN	ONE			;BACK TO SENDER.
CHKEOF:	IF.ON	T1,E.EOF,INPEND		;JUMP IF EOF.
	IF.OFF	S,NI.LST		;RETURN IF NO ERROR.
	IF.ON	T1,E.EOT		;SKIP IF END OF TAPE.
	RETURN	ONE			;ELSE GIVE GOOD RETURN.
	RETURN	ZERO			;OTHERWISE GIVE EOF RETURN.
INPABT:	SKIPA	T1,[DRIVE IF,.SKF]	;SKIP FOR LEGAL LABEL AT EOF.
INPAB0:	SKIPA	T1,[DRIVE IF,.BSR]	;BACK UP FOR ERROR ON LABEL.
	SKIPE	IFILE+LABEL		;DON'T DO ANYTHING FOR NO LABELS.
	XCT	T1			;DO THE FUNCTION.
	DRIVE	IF,.WAT			;WAIT FOR IT.
	OFF	S,HDR!NI.ERR!TERM	;CLEAR BITS SET FOR HEADER.
	RETURN	ZERO			;GIVE EOF RETURN.
;HERE TO WRITE ONE CHARACTER INTO THE BUFFER.

PUT:	SOSGE	OBUF+2			;DECREMENT THE COUNT.
	GOTO	WRITE			;EMPTY THE BUFFER.
	IDPB	CH,OBUF+1		;SAVE THE WORD.
	RETURN	ZERO			;BACK TO SENDER.
WRITE:	GOSUB	EMPTY			;WRITE IT OUT.
	GOTO	PUT			;CONTINUE LOOP.
EMPTY:	AOS	OSEC			;COUNT OUTPUT SECTOR.
	DEVOP	OUT,OF,ZERO		;WRITE THE BUFFER.
	RETURN	ZERO			;NORMAL RETURN.

;HERE ON AN ERROR FROM THE LAST OUTPUT.

OUTERR:	GETSTS	OF,T1			;GET DEVICE STATUS BITS.
	IF.OFF	OF,MTA,NOTMTA		;JUMP IF NOT MAG-TAPE.
	IF.OFF	T1,E.IOB		;***BUG IF I/O BLOCK TO LARGE.
	GOSUB	ABORT			;PROGRAM BUG *****
	IF.ON	T1,E.EOT,OUTEND		;IF END OF TAPE GET NEW REEL.
	IF.OFF	T1,E.PAR,LOKERR		;JUMP IF NOT PARITY ERROR.
	IF.OFF	OF,NOERROR,OPERR	;TYPE MESSAGE IF HE WANTS IT.
	AOS	OTPERR			;COUNT THE ERROR.
	RETURN	ZERO			;ELSE GIVE NORMAL RETURN.

;HERE IF OTHER THEN MAG-TAPE.

NOTMTA:	IF.OFF	T1,E.IOB,NOTMT1		;JUMP IF STILL HAVE ROOM.
	IF.ON	IF,DTA,TAPFUL		;JUMP IF DECTAPE IS FULL.
	GOTO	NOROOM			;ELSE NO QUOTA.
NOTMT1:	IF.OFF	T1,E.PAR,LOKERR		;JUMP IF NOT PARITY ERROR.
	IF.OFF	OF,NOERROR,PARERR	;TYPE MESSAGE IF HE WANTS IT.
	RETURN	ZERO			;YES WE GIVE NORMAL RETURN.
;HERE FROM INPUT ROUTINE TO GET NEXT REEL.

INPEND:	ENABLE	TTY			;CLEAR CONTROL O.
	CLOSE	IF,ZERO			;DO THIS TO RESET EOF FLAG.
	TNZ	S,NI.ERR,RET0		;RETURN IF NOT LEGAL EOF.
	GETSTS	IF,T1			;SEE IF ERROR.
	IF.OFF	T1,E.ERR		;TEST ERROR BITS.
	PRINT	(% Error during eof label check.)
	IF.OFF	IF,MTA,RET0		;RETURN IF NOT MAG-TAPE.
	ON	S,HDR			;SET HEADER BIT.
	GOSUB	STORE			;SAVE THE AC'S.
	GOSUB	GETLAB			;READ A LABEL BLOCK.
	GOTO	INPAB0			;CAN'T BE A LABEL IF EOF.
	BRANCH	INPLAB,<INPAB0,INPABT,INPABT> ;SEE IF WE HAVE A LABEL.
	IF.OFF	S,L.EOV,INPABT		;JUMP IF NOT EOV.
	OFF	S,TERM			;CLEAR HEADER BIT.
	GOSUB	STAT			;PROGRAM GOODNESS.
	SETZM	IBCNT			;CLEAR BLOCKS READ.
	SETZM	IRCNT			;CLEAR RECORDS READ.
	MOVE	T1,IFILE+VOL		;GET CURRENT VOLUME NUMBER.
	GOSUB	BMPVOL			;INCREMENT THE NUMBER.
	MOVEM	T1,IFILE+VOL		;REPLACE IT.
TAINP:	ON	S,NO.PRI		;SET FORCE HUNG DEVICE BIT.
	DRIVE	IF,.UNL			;UNLOAD DEVICE.
	PRINT	(% Mount next input tape on same drive.)
	RELEASE	IF,ZERO			;RELEASE THE DEVICE.
	GOSUB	TRPSET			;RESET TRAP BLOCK.
	OPEN	IF,IFILE		;GET THE DEVICE BACK.
	JSP	T1,NODEV		;CAN'T HAVE IT....
	HLRZ	T1,MSIZ(IM)		;GET THE BYTE SIZE.
	DPB	T1,[POINT 6,IBUF+1,11]	;SET THE BYTE SIZE.
	DRIVE	IF,.WAT			;MAKE SURE IT IS READY.
	DRIVE	IF,.REW			;REWIND THE DEVICE.
	DRIVE	IF,.WAT			;DRIVE DEVICE TO COMPLETION.
	OFF	S,NO.PRI		;PRINT HUNG MESSAGE NOW.
	MOVE	T1,IJOBFF		;GET SAVED TOP OF CORE.
	EXCH	T1,.JBFF		;PUT IN PLACE FOR EXEC.
	SAVE	T1			;SAVE CURRENT VALUE.
	INBUF	IF,TWO			;GET SOME BUFFERS.
	MOVEI	T1,IBUF			;POINTER TO HEADERS.
	MOVEI	SIDE,IFILE		;POINTER TO PARAMETERS.
	GOSUB	MAKE			;MAKE NEW BUFFERS.
	UNSAVE	.JBFF			;PUT BACK TOP OF CORE.
	SAVE	[TAINP-1]		;PLACE A RETURN ON THE STACK.
	GOSUB	GETLAB			;GET A LABEL BLOCK.
	GOTO	BADEOF			;BAD FILE MARK FOUND.
	BRANCH	INPLAB,<NOLAB,NOMAT,BADVOL> ;BRANCH ON LABEL FOUND.
	IF.OFF	S,L.HDR,NOLAB		;JUMP IF NOT THE RIGHT TYPE.
	OFF	S,NO.PRI!HDR		;CLEAR INDICATOR BITS.
	SUB	PDP,[XWD ONE,ONE]	;FIX THE STACK.
	RETURN	ONE			;GO FILL IT UP.
;HERE FROM OUTPUT ROUTINE ON END OF TAPE TO GET A NEW ONE.

OUTEND:	TNO	S,NO.ERR,RET0		;RETURN IF IGNORING ERRORS.
	OFF	T1,E.ERR!E.EOT		;CLEAR ERROR BITS.
	SETSTS	OF,ZERO(T1)		;RESET STATUS FOR EXEC.
	ENABLE	TTY			;CLEAR CONTROL O.
	CLOSE	OF,ZERO			;WRITE END OF FILE MARK.
	GETSTS	OF,T1			;GET STATUS ON THAT.
	TEZ	T1,E.ERR		;SKIP IF NO ERROR.
	PRINT	(? Error during close of volume.)
	SETSTS	OF,ZERO(T1)		;RESET STATUS.
	ON	S,FIN!TERM!HDR		;LIGHT SOME BITS SO OTHERS CAN SEE.
	GOSUB	STORE			;SAVE THE AC'S.
	GOSUB	OUTLAB			;WRITE THE TRAILER LABEL.
	OFF	S,FIN!TERM		;CLEAR BITS SO OTHERS CAN'T SEE.
	GOSUB	STAT			;GOOD THINGS COME FROM THIS.
	SETZM	OBCNT			;CLEAR NUMBER OF BLOCKS WRITTEN.
	SETZM	ORCNT			;CLEAR RECORD COUNT.
	MOVE	T1,OFILE+VOL		;GET THE VOLUME NUMBER.
	GOSUB	BMPVOL			;INCREMENT VOLUME NUMBER.
	MOVEM	T1,OFILE+VOL		;REPLACE IT.
TAOUT:	ON	S,NO.PRI		;DON'T PRINT HUNG MESSAGE NOW.
	DRIVE	OF,.UNL			;UNLOAD TAPE.
	PRINT	(% Mount new output tape on same drive.)
	RELEASE	OF,ZERO			;RELEASE OUTPUT CHANNEL.
	GOSUB	TRPSET			;RESET TRAP BLOCK.
	OPEN	OF,OFILE		;OPEN IT BACK UP.
	JSP	T1,NODEV		;COULDN'T GET IT.
	HLRZ	T1,MSIZ(OM)		;GET THE BYTE SIZE.
	DPB	T1,[POINT 6,OBUF+1,11]	;SET THE SIZE RIGHT.
	DRIVE	OF,.WAT			;MAKE SURE IT IS READY.
	DRIVE	OF,.REW			;REWIND IT.
	DRIVE	OF,.WAT			;WAIT FOR COMPLETION.
	OFF	S,NO.PRI		;CLEAR HUNG DEVICE BIT.
	MOVE	T1,OJOBFF		;GET OUTPUT TOP OF CORE.
	EXCH	T1,.JBFF		;RESET IT.
	SAVE	T1			;SAVE IT ON STACK.
	OUTBUF	OF,TWO			;CREATE HEADERS.
	MOVEI	T1,OBUF			;GET POINTER TO BUFFER.
	MOVEI	SIDE,OFILE		;POINTER TO PARAMETERS.
	GOSUB	MAKE			;MAKE NEW BUFFERS.
	UNSAVE	.JBFF			;RESTORE TOP OF CORE.
	GOSUB	OUTLAB			;WRITE NEW LABEL.
	SKIPA				;SKIP INTO GOODNESS.
	GOTO	TAOUT			;GIVE HIM ANOTHER CHANCE.
	OFF	S,NO.PRI!NO.ERR!HDR	;IF DEVICE HANGS NOW IT REALY IS.
	RETURN	ZERO			;RETURN.
;HERE TO FILL THE BUFFER RING WITH A BUFFER THAT SHOULD
;CONTAIN A LABEL OF SOME KIND.

GETLAB:	GETSTS	IF,T1			;GET THE DEVICE STATUS.
	ON	T1,SYNC			;SYNC WITH THE DEVICE.
	SETSTS	IF,ZERO(T1)		;RESET THE STATUS.
	IF.OFF	IF,IND			;SKIP IF OUR MODE.
	DRIVE	IF,.IND			;ELSE SET THEIRS.
	ON	S,NI.ERR		;TURN ON EOF RETURN FLAG.
	GOSUB	FILL			;FILL THE BUFFER WITH A LABEL.
	SOS	ZERO(PDP)		;DECREMENT TO GIVE ERROR RETURN.
	AOS	ZERO(PDP)		;INCREMENT FOR NORMAL RETURN.
	OFF	S,NI.ERR		;TURN OFF EOF RETURN FLAG.
	GETSTS	IF,T1			;GET DEVICE STATUS.
	OFF	S,SYNC			;TURN OFF SYNC BIT.
	SETSTS	IF,ZERO(T1)		;RESET STATUS.
	SETOM	IBUF+2			;FLAG BUFFER WILL BE USED.
	RETURN	ZERO			;TO CALLER.

;HERE TO CONVERT THE LABEL JUST READ INTO THE BUFFER
;RING INTO SIXBIT AND TO STORE THAT BUFFER IN "INPBUF" FOR
;FURTHER PROCESSING.

CVTLAB:	MOVSI	P3,(POINT 7,ZERO)	;POINTER FOR IMAGE MODE.
	CAIE	T1,IMGMOD		;SKIP IF IMAGE MODE.
	MOVE	P3,MPTR(T1)		;GET A BYTE POINTER.
	MOVE	T2,OM			;GET THE OUTPUT INDEX.
	GOSUB	GETTAB			;GET THE RIGHT TABLES.
	MOVE	P1,[POINT 6,INPBUF]	;POINTER TO BUFFER.
	MOVNI	P2,^D80			;MAX CHARACTERS IN ANY LABEL.
	MOVE	T1,IBUF			;GET A POINTER TO CURRENT BUFFER.
	ADDI	P3,TWO(T1)		;POINT P3 TO BUFFER.
RED0:	ILDB	CH,P3			;GET A BYTE.
	HLRZ	CH,TAB1(CH)		;CONVERT IT TO ASCII.
	SUBI	CH," "			;NOW TO SIXBIT.
	IDPB	CH,P1			;SAVE IT IN BUFFER.
	AOJN	P2,RED0			;CONTINUE LOOP.
REVIVE:	MOVE	T1,IM			;GET THE TRUE INPUT MODE.
	MOVE	T2,OM			;GET THE TRUE OUTPUT MODE.
	GOTO	GETTAB			;GET THE RIGHT TABLES.
;HERE TO READ THE LABEL FROM THE OUTPUT DEVICE IF THE
;DEVICE IS A MAG-TAPE AND TO CONVERT IT TO SIXBIT
;AND STORE IT IN OUTBUF FOR FURTHER PROCESSING.

REDOUT:	MOVE	P1,[XWD OIBUF,OIBUF+1]	;BLT POINTER.
	SETZM	OIBUF			;CLEAR FIRST WORD.
	BLT	P1,BUFF+^D23		;CLEAR CORE.
	MOVE	P1,[XWD 400000,BUFF+1]	;SET UP BUFFER ON OUTPUT DEVICE.
	MOVEM	P1,OIBUF		;INTO BUFFER HEADER.
	MOVSI	P1,(POINT 7,ZERO)	;POINTER IF IMAGE MODE.
	CAIE	T2,IMGMOD		;SKIP IF IMAGE MODE.
	HLLZ	P1,MPTR(T2)		;GET THE OUTPUT POINTER.
	MOVEM	P1,OIBUF+1		;SET THE POINTER UP.
	MOVE	T1,IM			;GET THE INPUT MODE.
	GOSUB	GETTAB			;GET THE RIGHT TABLES.
	MOVE	P1,[XWD ^D21,BUFF+1]	;LINK WORD.
	MOVEM	P1,BUFF+1		;SET IT IN BUFFER HEADER.
	MOVE	P1,[POINT 6,OUTBUF]	;POINTER TO BUFFER.
	MOVNI	P2,^D80			;MAX CHARACTERS IN LABEL.
	DEVOP	IN,OF,ZERO		;READ THE LABEL.
	GOTO	RED0B			;START THE COPY.
	GETSTS	OF,T1			;A LITTLE ERROR.
	IF.ON	T1,E.EOF,RET0		;JUMP IF EOF.
	IF.ON	T1,E.LOK!E.HAD,LOKERR	;JUMP IF HARD ERROR.
	IF.OFF	T1,E.PAR,RED0B		;JUMP IF NOT PARITY ERROR.
	AOS	OTPERR			;COUNT AN OUTPUT ERROR.
	IF.ON	OF,NOERROR,RED0B	;JUMP IF IGNORING.
	UNSAVE	T1			;CLEAN UP THE STACK.
	GOTO	OPERR			;SAY THERE IS AN ERROR.
RED0B:	ILDB	CH,OIBUF+1		;GET A CHARACTER.
	HLRZ	CH,TAB2(CH)		;CONVERT IT TO ASCII.
	SUBI	CH," "			;CONVERT IT TO SIXBIT.
	IDPB	CH,P1			;STORE THE CHARACTER.
	AOJN	P2,RED0B		;JUMP IF NOT DONE.
	AOS	ZERO(PDP)		;SKIP RETURN FOR A JOB WELL DONE.
	GOTO	REVIVE			;GET THE RIGHT TABLES BACK.
;HERE TO WRITE OUT THE LABEL IN OUTBUF TO
;MAG-TAPE. WE DO CONVERSION HERE FROM SIXBIT TO WHAT
;EVER CODE THE TAPE IS TO BE WRITTEN IN.

WRILAB:	SKIPG	OBUF			;HAS THE BUFFER BEEN USED.
	OUTPUT	OF,ZERO			;NO SO USE IT.
	MOVEI	P1,7			;BYTE SIZE IF IMAGE MODE.
	CAIE	T2,IMGMOD		;SKIP IF IMAGE MODE.
	HLRZ	P1,MSIZ(T2)		;GET OUTPUT BYTE POINTER.
	DPB	P1,[POINT 6,OBUF+1,11]	;SAVE THE SIZE.
	MOVE	T1,IM			;INPUT INDEX.
	GOSUB	GETTAB			;READ THE RIGHT TABLES.
	SAVE	OBUF+2			;SAVE THE COUNTER.
	HRRZ	T2,MSIZ(T1)		;GET THE BYTES PER WORD.
	LDB	T1,[POINT 17,@OBUF,17]	;GET THE BUFFER SIZE.
	MOVEI	T1,-1(T1)		;JUST THE DATA WORDS.
	IMUL	T1,T2			;GET THE COUNTER.
	MOVEM	T1,OBUF+2		;SET COUNTER FOR BUFFER.
	MOVE	P1,[POINT 6,OUTBUF]	;POINTER TO STORAGE.
	MOVNI	P2,^D80			;MAX. CHARACTERS IN LABEL.
WRITE0:	ILDB	CH,P1			;GET A CHARACTER.
	ADDI	CH," "			;CONVERT IT TO ASCII.
	HRRZ	CH,TAB2(CH)		;TO THE OUTPUT SET.
	GOSUB	PUT			;INTO OUTPUT BUFFER.
	AOJN	P2,WRITE0		;CONTINUE FOR ALL.
	GOSUB	EMPTY			;WRITE THE LABEL.
	HLRZ	P1,MSIZ(OM)		;GET TRUE OUTPUT POINTER.
	DPB	P1,[POINT 6,OBUF+1,11]	;RESET IT.
	UNSAVE	OBUF+2			;RESTORE THE COUNTER.
	GOTO	REVIVE			;GET THE RIGHT TABLES BACK.
SUBTTL				*** ERROR MESSAGES ***

NOUSE:	HRRZ	T2,CCLFLG		;POINTER TO DEVICE BLOCK.
	GOTO	QUES			;TYPE ERROR MESSAGE.
NOOUSE:	SKIPA	T2,[OFILE]		;GET DATA INDEX.
NOIUSE:	MOVEI	T2,IFILE		;GET DATA INDEX.
QUES:	EME	.STR,[ASCIZ "? "]	;FOR BATCH.
	GOSUB	NAMIT			;TELL HIM THE DEVICE IN ERR.
	EME	.STR,[ASCIZ " can't be used."]
	GOTO	CLEAR1			;ANOTHER CHANCE FOR HIM.

NODEV:	XCT	QUES			;FOR BATCH.
	HRRZI	T2,@-2(T1)		;GET POINTER TO DEVICE NAME.
	GOSUB	NAMIT			;PRINT ITS NAME.
	EME	.STR,[ASCIZ " is not available."]
	GOTO	CLEAR1			;CLEAR THE FLAGS AND EXIT.

NOEXT:	XCT	QUES			;FOR BATCH.
	HRRZI	T1,@-4(T1)		;GET POINTER TO DEVICE NAME.
	MOVEI	T2,-DEVICE(T1)		;GET POINTER TO DATA AREA.
	GOSUB	NAMIT			;TELL ME WHAT IT IS.
	EME	.STR,[ASCIZ " doesn't exist."]
	GOTO	CLEAR1			;BYE..BYE..

NAMIT:	EME	.STR,[ASCIZ /Device "/]	;FOR CLEARNESS.
	MOVE	T1,CHAN(T2)		;GET THE CHANNEL NUMBER.
	MME	T1,.NAM			;GET THE REAL NAME.
	MOVE	T1,DEVICE(T2)		;GET THE NAME WE HAVE.
	GOSUB	PUTSIX			;PRINT IT.
	EME	.STR,[ASCIZ /"/]	;DELIMIT DEVICE NAME.
	RETURN	ZERO			;BACK TO SENDER.

NOOUT:	XCT	QUES			;FOR BATCH.
	MOVEI	T2,OFILE		;GET THE DATA INDEX.
	GOSUB	NAMIT			;TELL HIM ITS NAME.
	GOTO	NOOUT1			;TELL HIM NO OUTPUT.
NOINP:	XCT	QUES			;FOR BATCH.
	MOVEI	T2,IFILE		;GET THE DATA INDEX.
	GOSUB	NAMIT			;PRINT ITS NAME.
	GOTO	NOINP1			;TELL HIM NO INPUT.

OPERR:	EME	.STR,[ASCIZ "? Output"]	;SAY IT IS OUTPUT ERROR.
	GOTO	PARERR			;THEN SAY THE REST.
IPERR:	EME	.STR,[ASCIZ "? Input"]	;SAY INPUT ERROR.
	GOTO	PARERR			;THEN TELL THE REST.

HADERR:	EME	.STR,[ASCIZ "? Unrecoverable i/o error status "]
	MOVNI	T3,^D6			;NUMBER OF DIGITS TO PLACE.
	LSHC	T1,-^D18		;SHIFT STATUS INTO T2.
	JSP	P4,OCTOUT+1		;PRINT IT.
CLEAR1:	SETZM	S			;CLEAR S.
	GOTO	ERREXT			;AND RESTART.
;HERE TO TELL WHY WE COULDN'T CREATE OR READ A FILE.

NOOPN:	MOVEI	SIDE,OFILE		;GET THE INDEX.
	HRRZ	T1,OFILE+EXT		;GET THE ERROR INDEX.
	JUMPN	T1,NOFILE+1		;JUMP IF O.K.
	MOVEI	T1,-TWO			;SET MESSAGE RIGHT.
	HRRM	T1,OFILE+EXT		;SAVE IT.
	SKIPA				;SKIP INTO GOODNESS.
NOFILE:	MOVEI	SIDE,IFILE		;GET THE INDEX TO DATA.
	UNSAVE	PPN(SIDE)		;RESTORE PPN WORD.
	EME	.STR,[ASCIZ "? "]	;GIVE ERROR SIGNAL.
	GOSUB	TYPE			;TYPE THE MESSAGE.
	SETZM	S			;CLEAR ERROR BITS.
	GOTO	ERR2			;AND EXIT.

;HERE IF A FILE CAN'T BE ACCESSED.

MAYBE:	IF.OFF	IF,DSK			;SKIP IF NOT DISK.
	IF.OFF	IF,WILD,NOFILE		;IF NOT WILD JUMP.
	UNSAVE	IFILE+PPN		;RESTORE THE PPN.
	MOVE	P4,IFILE+MOD		;GET THE MOD BITS.
	OFF	P4,WILD			;TURN OFF WILD BITS.
	MOVEI	SIDE,IFILE		;INDEX TO DATA BASE.
WARN:	EME	.STR,[ASCIZ "% "]	;FLASH A WARNING.
	GOSUB	TYPEIT			;TYPE THE ERROR.
	IF.ON	IF,DSK,NXTDSK		;JUMP IF DSK.
	GOTO	NXTDTA			;ELSE MUST BE DTA.

;HERE TO TYPE DEV:FILENAME.EXT[P,PN] ERROR MESSAGE.

TYPE:	MOVE	P4,MOD(SIDE)		;GET THE MOD BITS.
TYPEIT:	EME	.STR,[ASCIZ /File "/]	;A LITTLE IDENTIFIER.
TYPE0:	GOSUB	TYPNAM			;TYPE DEV:FILENAME.EXT[P,PN].
TEL0:	EME	.STR,[ASCIZ /"/]	;FINISH IT OFF.
	HRRE	P1,EXT(SIDE)		;GET THE ERROR CODE.
	CAILE	P1,ERRCNT		;SEE IF IN RANGE.
	MOVEI	P1,ERRCNT		;SET OUR OWN.
	MOVE	P1,ERRMES(P1)		;GET POINTER TO STRING.
	EME	.STR,ZERO(P1)		;TELL WHY.
	GOTO	CRLF			;SKIP A LINE AND EXIT.

;HERE WHEN WE CAN'T OPEN THE CCL FILE.

NOCCL:	MOVE	P4,MOD(SIDE)		;GET THE MOD BITS.
	IF.ON	P4,WILD,NOCCL0		;JUMP IF WILD BITS WERE ON.
	SETZM	S			;CLEAR STATUS REGISTER.
	HRRZ	SIDE,CCLFLG		;GET THE POINTER TO FILE NAME.
	XCT	QUES			;FOR BATCH.
	GOSUB	TYPEIT			;PRINT MESSAGE.
	JSP	T1,CCLBAK		;BACK UP POINTER.
	NOP	ERR2			;WHERE TO GO.
NOCCL0:	MOVEI	P1,[ASCIZ "? ILLEGAL CCL FILE NAME."]
	GOTO	FSTEOL			;TYPE THE MESAGE.
;HERE TO TYPE DEV:NAME.EXT[P,PN]

TYPNAM:	SKIPN	DEVICE(SIDE)		;IS THERE A DEVICE.
	GOTO	TYPNM0			;SKIP DEVICE THEN.
	MOVE	T1,CHAN(SIDE)		;GET THE CHANNEL NUMBER.
	MME	T1,.NAM			;GET ITS REAL NAME.
	MOVE	T1,DEVICE(SIDE)		;MME FAILED.
	IF.OFF	P4,WDEV			;SKIP IF TRUE DEVICE.
	MOVSI	T1,'*  '		;FLAG WILD DEVICE.
	GOSUB	PUTSIX			;PRINT ITS NAME.
	EME	.CH,[EXP ":"]		;TO SIGNIFY DEVICE.
TYPNM0:	MOVE	P1,NAME(SIDE)		;GET THE FILE NAME.
	MOVE	P2,EXT(SIDE)		;GET THE EXTENSION.
	SKIPN	T1,DEVICE(SIDE)		;GET THE DEVICE.
	MOVSI	T1,'DSK'		;NONE USE DISK.
	MME	T1,.DEV			;GET THE CHARACTERISTICS.
	IF.ON	T1,DSK			;SKIP IF DSK.
	SETZM	PPN(SIDE)		;CLEAR PPN WORD.
	IF.OFF	P4,WNAME		;SKIP IF TRUE NAME.
	MOVSI	P1,'*  '		;ELSE USE A WILD CHARACTER.
	IF.OFF	P4,WEXT			;SKIP IF TRUE EXTENSION.
	MOVSI	P2,'*  '		;SET WILD CHARACTER.
	GOSUB	PUTNAM			;PRINT THE NAME.
	HLRZ	P1,PPN(SIDE)		;GET THE PROJECT NUMBER.
	IF.ON	P4,WP!WPN		;SKIP IF WILD PPN.
	JUMPE	P1,RET0			;JUMP IF NONE.
	EME	.CH,[EXP "["]		;START OF PPN WORD.
	IF.OFF	P4,WP			;SKIP IF NOT WILD.
	GOSUB	TYPHAL			;TYPE HALF OF IT.
	GOSUB	PUTOCT			;TYPE THIS HALF.
	EME	.CH,[EXP ","]		;SEPARATE THEM.
	HRRZ	P1,PPN(SIDE)		;GET THE PROGRAM NUMBER.
	IF.OFF	P4,WPN			;SKIP IF NOT WILD.
	GOSUB	TYPHAL			;TYPE THE OTHER HALF.
	GOSUB	PUTOCT			;PRINT IT.
	EME	.CH,[EXP "]"]		;FINISH THE PPN WORD.
	RETURN	ZERO			;RETURN TO CALLER.
TYPHAL:	MOVSI	T1,'*  '		;FLAG WILD.
	AOS	ZERO(PDP)		;FOR SKIP RETURN.
	GOTO	PUTSIX			;FLADH A STAR.
	[ASCIZ " is an illegal file name."]			; (-2)
	[ASCIZ " is non-existent."]				; (-1)
ERRMES:	[ASCIZ " is not saved."]				; (0)
	[ASCIZ " has no ufd."]					; (1)
	[ASCIZ " protection failure."]				; (2)
	[ASCIZ " is being modified."]				; (3)
	[ASCIZ " unknown executive error return."]		; (4)
	[ASCIZ " unknown executive error return."]		; (5)
	[ASCIZ " has a rib error."]				; (6)
	[ASCIZ " unknown executive error return."]		; (7)
	[ASCIZ " unknown executive error return."]		; (10)
	[ASCIZ " unknown executive error return."]		; (11)
	[ASCIZ " unknown executive error return."]		; (12)
	[ASCIZ " unknown executive error return."]		; (13)
	[ASCIZ " no room on file structure."]			; (14)
	[ASCIZ " structure is write-locked."]			; (15)
	[ASCIZ " executive table space exceeded."]		; (16)
	[ASCIZ " unknown executive error return."]		; (17)
	[ASCIZ " unknown executive error return."]		; (20)
	[ASCIZ " can't supersede an existing directory."]	; (21)
	[ASCIZ " unknown executive error return."]		; (22)
	[ASCIZ " is missing an sfd in its path."]		; (23)
	[ASCIZ " has no search list."]				; (24)
	[ASCIZ " will nest sfd's too deeply."]			; (25)
	[ASCIZ " has no writable file structure."]		; (26)
	[ASCIZ " unknown executive error return."]		; (27)
ERRCNT==.-ERRMES-1
NOHELP:	EME	.STR,[ASCIZ /% Can't provide help for "/]
	MOVE	T1,HFILE		;GET THE NAME WANTED.
	GOSUB	PUTSIX			;PRINT IT.
	GOTO	BACK			;EXIT.
BADFOM:	SKIPA	P1,[[ASCIZ "? Record size non-zero with carriage-returns in file."]]
NOCOM:	MOVEI	P1,[ASCIZ "? No command to perform."]
	GOTO	CLEAR
BADCHR:	TNO	S,BAD,RET0		;ONLY ONE BAD CHARACTER PER LINE.
	SKIPA	P1,[[ASCIZ "? Illegal command syntax character."]]
NOMAKE:	MOVEI	P1,[ASCIZ "? Can't create tables."]
	GOTO	FSTEOL
NOTAB:	RELEASE	DF,ZERO
	SETZM	DFFLG
	SKIPA	P1,[[ASCIZ "? Can't find conversion tables."]]
NOIREC:	MOVEI	P1,[ASCIZ "? Need record switch for input specifications."]
	GOTO	CLEAR
COMERR:	SKIPA	P1,[[ASCIZ "? Can't understand command."]]
PPNERR:	MOVEI	P1,[ASCIZ "? Incorrect project-program number."]
	GOTO	FSTEOL
IMPSW:	SKIPA	P1,[[ASCIZ "? Illegal switch in command string."]]
SWERR:	MOVEI	P1,[ASCIZ "? Switch appears twice in same specifications."]
	GOTO	FSTEOL
FOMERR:	MOVEI	P1,[ASCIZ "? Bad modifier for switch."]
	GOTO	FSTEOL
NOOUT1:	SKIPA	P1,[[ASCIZ " can't do output."]]
NOINP1:	MOVEI	P1,[ASCIZ " can't do input."]
	GOTO	CLEAR
DDTERR:	SKIPA	P1,[[ASCIZ "? Debugger is not loaded."]]
LOCK:	MOVEI	P1,[ASCIZ "? Output device is write locked."]
	GOTO	CLEAR
NOTLAB:	SKIPA	P1,[[ASCIZ "? Format error in label on output device."]]
BLKERR:	MOVEI	P1,[ASCIZ "? Blocking factor or record size incorrectly specified."]
	GOTO	ERR1
NOOREC:	SKIPA	P1,[[ASCIZ "? Need record switch for output specifications."]]
NOCORE:	MOVEI	P1,[ASCIZ "? Insufficient memory for operation."]
	GOTO	CLEAR
NOROOM:	SKIPA	P1,[[ASCIZ "? Quota, rib, or file structure capacity exceeded."]]
TAPFUL:	MOVEI	P1,[ASCIZ "? Dectape is full."]
	GOTO	CLEAR
BADMOD:	SKIPA	P1,[[ASCIZ "? Octal mode can't be used with list."]]
MOD0ER:	MOVEI	P1,[ASCIZ "? Image or octal output is required with image input."]
	GOTO	CLEAR
NOOCT:	SKIPA	P1,[[ASCIZ "? Octal is an output only mode."]]
IOERR:	MOVEI	P1,[ASCIZ "? Input device i/o error."]
	GOTO	CLEAR
SAMDEV:	SKIPA	P1,[[ASCIZ "? Can't use same mag-tape for input and output."]]
PARERR:	MOVEI	P1,[ASCIZ " Checksum or parity error encountered."]
CLEAR:	SETZM	S
	GOTO	ERR1
NOWLD:	MOVNI	T1,ONE			;INDEX FOR MESSAGE.
	HRRM	T1,IFILE+EXT		;SAVE THE INDEX.
	SAVE	IFILE+PPN		;SO ERROR ROUTINE WORKS RIGHT.
	GOTO	NOFILE			;TELL HIM IT DOESN'T EXIST.
CANLST:	XCT	QUES			;FOR BATCH.
	MOVEI	T2,IFILE		;POINTER TO THINGS.
	GOSUB	NAMIT			;NAME THE DEVICE.
	EME	.STR,[ASCIZ " has no directory."]
	GOTO	CLEAR1			;EXIT.

NOLAB:	GOSUB	QW			;FLASH A ? OR %.
	MOVEI	P1,[ASCIZ "Format error in label on input device."]
	GOTO	ERR1
BADEOF:	IF.ON	IF,WNAME!WEXT!SCAN,RET0	;RETURN IF WILD OR SCANNING.
BADTM:	MOVEI	P1,[ASCIZ "? Unexpected file mark encountered while reading label."]
	GOTO	ERR1			;TELL OF THE ERROR.
BADVOL:	IF.OFF	IF,WNAME!WEXT!SCAN
	GOTO	ZERO(T1)		;RETURN FOR WILD CARDS.
	GOSUB	QW			;FLASH A ? OR %.
	EME	.STR,[ASCIZ /Volume number is "/]
	MOVE	T1,LABVOL		;GET THE NUMBER IN ERROR.
	GOSUB	PUTSIX			;PRINT NUMBER WE FOUND.
	EME	.STR,[ASCIZ /" should be "/]
	MOVE	T1,IFILE+VOL		;GET CORRECT VOLUME NUMBER.
	GOSUB	PUTSIX			;PRINT IT.
	GOTO	BACK			;EXIT...

NOMAT:	GOSUB	QW			;FLASH A ? OF %.
	EME	.STR,[ASCIZ /Label-id of "/]
	MOVE	P1,LABNAM		;GET FIRST HALF OF ID.
	MOVE	P2,LABNAM+1		;GET THE SECOND HALF.
	GOSUB	PUTNAM			;TYPE THE ID.
	EME	.STR,[ASCIZ /" doesn't match file-id of "/]
	MOVE	P1,IFILE+NAME		;COPY FILE NAME.
	MOVE	P2,IFILE+EXT		;COPY EXTENSION.
	GOSUB	PUTNAM			;PRINT THE NAME.
BACK:	MOVEI	P1,[ASCIZ /"./]		;FORMAT.
	GOTO	ERR1			;START AGAIN.

;HERE TO SKIP A FILE.

SKPFIL:	ON	IF,NOERROR		;NO ERRORS WHILE SKIPPING.
	ON	S,NI.ERR		;GET A RETURN ON ANY EOF.
SKP0:	GOSUB	CHKOPR			;CHECK FOR COMMAND.
	GOSUB	FILL			;DON'T DO A DRIVE BECAUSE TAPE
	SKIPA				;COULD HAVE TAPE MARKS WRITTEN
	GOTO	SKP0			;IN THE SAME PARITY AS THE TAPE.
	MOVE	IF,IFILE+MOD		;RESET THE MODE BITS.
	OFF	S,NI.ERR		;NORMAL RETURNS ON EOF.
	RETURN	ZERO			;RETURN TO CALLER.
;HERE TO TYPE A QUESTION MARK OR A PERCENT SIGN.

QW:	MOVEI	T1,QUES			;IF FATAL.
	IF.OFF	S,HDR			;SKIP IF HEADER LABEL.
	MOVEI	T1,WARN			;IF NOT FATAL.
	XCT	ZERO(T1)		;PRINT SOMETHING.
	RETURN	ZERO			;RETURN.
TOODEP:	MOVEI	P1,[ASCIZ "% Command files nested too deeply -- command ignored."]

;HERE ON AN ERROR MESSAGE WHEN PROCESSING A COMMAND.

FSTEOL:	ON	S,BAD			;SET ERROR BITS.
	SAVE	SPCCNT			;SAVE THE SPACE COUNT.
	IF.ON	S,EOL			;ARE WE THERE ALREADY.
	GOSUB	GETONE			;FIND END OF LINE.
	IF.ON	S,EOL			;IS IT END OF LINE.
	GOTO	.-2			;NO TRY AGAIN.
	SETZM	S			;CLEAR SO WE DON'T GET CONFUSED.
	UNSAVE	T1			;GET THE COUNT BACK.
	SOJLE	T1,ERR0			;JUMP IF AT CORRECT POSTION.
	EME	.CH,[EXP " "]		;TAB TO POSITION.
	GOTO	.-2			;CONTINUE TO TAB.
ERR0:	EME	.STR,[BYTE (7)"^",15,12,0];POINT TO ERROR.
ERR1:	ENABLE	TTY			;LET HIM SEE ERRORS.
	EME	.STR,ZERO(P1)		;SEND MESSAGE.
ERREXT:	GOSUB	CRLF			;SKIP A LINE.
ERR2:	SKIPN	DIAFLG			;SKIP IF IN DIALOG MODE.
	GOTO	ERR3			;NOT IN DIALOG MODE.
	MOVE	PDP,[IOWD PDPSIZ+1,STACK+1];SAVE TOP ELEMEMT.
	XCT	CRLF			;SKIP A LINE.
	GOTO	@DIAFLG			;GIVE ERROR RETUR.
ERR3:	IF.OFF	S,HDR,NODEL		;ARE WE CHECKING MULTI-REEL LABELS.
	RETURN	ONE			;YES GIVE SKIP RETURN.
NODEL:	IF.OFF	OF,DSK!DTA,NTHERE	;JUMP IF A CLOSE DOES NOTHING.
	CLOSE	OF,ZERO			;PUT THE FILE ON THE DEVICE.
	GOTO	NTHERE			;START ALL OVER AGAIN.
CRLF:	EME	.STR,[BYTE (7)15,12,0]	;SEND CRLF.
	RETURN	ZERO			;VANISH....
;HERE ON A CONTROL C INTERCEPT.

CTLC:	SKIPL	T1,CCLFLG		;SKIP IF IN CCL FILE.
	GOTO	CTLC0			;ELSE CARRY ON.
	HRRZS	T1			;SO A GOOD COMPARE CAN BE DONE.
	CAIG	T1,CCLBLK+1		;DONE ALL BUT ONE.
	HRRZS	CCLFLG			;YES.
	JSP	T1,CCLBAK		;BACK UP POINTER.
	NOP	CTLC			;POINTER FOR RETURN.
CTLC0:	IF.OFF	OF,DSK!DTA		;SKIP IF CLOSE DOES NOTHING.
	CLOSE	OF,.NODEL		;DON'T DELETE OUTPUT.
	SKIPE	RUNFLG			;SKIP IF RUNNING.
	GOSUB	CRLF			;SKIP A LINE.
	SKIPE	RUNFLG			;SKIP IF NOT RUNNING.
	PRINT	(***Job aborted)	;TELL HIM WHAT HE DID.
	SETOM	T1			;FLAG OUR TTY.
	EME	.LTP,T1			;GET TTY BITS.
	SKIPGE	T1			;SKIP IF NOT PTY.
	GOTO	STOP			;TO EASE THE MIND OF BATCH.
	GOTO	NTHERE			;GO FLASH READY.
STOPIT:	ENABLE	TTY			;LET HIM SEE WHAT HE DID.
	PRINT	(stop)			;HERE TO STOP BEFORE WE PLANNED.
	GOTO	NODEL			;GO CLOSE THE OUTPUT FILE.
;HERE WHEN SOMETHING UNIMAGINABLE HAS
;HAPPENED TO US AND WE CAN'T CONTINUE.
;BECASUE OF A PROGRAM BUG....

ABORT:	ENABLE	TTY			;CLEAR GARBAGE.
	XCT	CRLF			;DON'T FORGET FORMAT.
	MOVEM	17,AC+17		;SAVE AC 17.
	HRRZI	17,AC			;SET UP BLT POINTER.
	BLT	17,AC+16		;SAVE THE ACS.
	MOVE	17,AC+17		;RESTORE AC 17.
ABORT1:	EME	.STR,[ASCIZ "***System abort at "]
	UNSAVE	T2			;GET ERROR ADDRESS BACK.
	SOS	T2			;BACK UP TO ERROR LOCATION.
	JSP	P4,OCTOUT		;PRINT IT.
	XCT	CRLF			;LITTLE FORMAT...
	SETZM	T2			;CLEAR AN INDEX.
GSNAM:	HRRZI	T1,11			;GETTAB TABLE.
	HRLI	T1,ZERO(T2)		;INDEX INTO TABLE.
	MME	T1,.TAB			;GET A WORD OF THE SYSTEM NAME.
	NOP				;IGNORE ERRORS.
	MOVEM	T1,SYSNAM(T2)		;SAVE IT.
	AOS	T2			;BUMP INDEX.
	CAIE	T2,4			;DONE THEM ALL???
	GOTO	GSNAM			;NO KEEP GOING.
	MOVE	T2,PRGNAM		;GET OUR NAME.
	MOVEM	T2,DMPFIL		;SET NAME OF FILE.
	MOVE	T2,ONE(PDP)		;GET ADDRESS OF CALL.
	SUBI	T2,ONE			;POINT TO CALL.
	MOVEM	T2,PC			;SAVE THE LOCATION.
	MME	T1,.DATE		;GET THE DATE.
	MOVEM	T1,DATE			;SAVE IT.
	MME	T1,.TIME		;GET THE TIME OF DAY.
	MOVEM	T1,TIME			;SAVE THE TIME.
	HRRZ	T1,.JBREL		;GET LAST LOCATION LOADED.
	SUBI	T1,137			;JUST OUR STUFF.
	MOVN	T1,T1			;MAKE IT NEGATIVE.
	HRLM	T1,DMPLST+1		;SAVE IOW WORD.
	OPEN	DF,DMPDEV		;GET THE DEVICE.
	GOTO	ABTEND			;FORGET IT IF ERROR.
	ENTER	DF,DMPFIL		;GET A FILE.
	GOTO	ABTEND			;FORGET IT ON ERRORS.
	DEVOP	OUTPUT,DF,DMPLST	;WRITE US OUT.
ABTEND:	CLOSE	DF,ZERO			;PLACE US ON DISK.
	RELEASE	DF,ZERO			;GET RID OF THE CHANNEL.
	SETZM	DFFLG			;FLAG NO CHANNEL.
	XCT	CRLF			;ONE MORE LINE DOWN PAGE.
	EME	.CLR,ZERO		;CLEAR BUFFERS.
	SKIPE	T1,.JBDDT		;SKIP IF NO DDT.
	GOTO	CALDDT			;ELSE GET IT HERE.
	GOTO	NTHERE			;TRY AGAIN.
SUBTTL		*** UTILITY ROUTINES ***

;HERE FROM LOCATION 40 ON A USER MODE ENTRY (UME).

UME0:	GOSUB	SAV2			;SAVE SOME AC'S.
	MOVE	P1,.JBUUO		;PICK UP THE UME.
	LDB	T1,[POINT 4,P1,12]	;GET THE AC FIELD.
	CAIN	T1,.ASC			;IS IT AN ASCII UME.
	GOTO	UME1			;YES GO TO IT.
	CAIN	T1,.SIX			;IS IT A SIXBIT ONE.
	GOTO	UME2			;YES GO TO IT.
	GOSUB	ABORT			;ILLEGAL UME.

;HERE FOR AN ASCIZ STRING.

UME1:	HRLI	P1,(POINT 7,0)		;SET UP A BYTE POINTER.
	ILDB	CH,P1			;GET AN ASCII CHARACTR.
	JUMPE	CH,RET0			;A ZERO ENDS IT.
	GOSUB	UME4			;CONVERT THE CHARACTER.
	GOTO	UME1+1			;CONTINUE LOOP.

;HERE FOR ONE SIXBIT WORD.

UME2:	HRLI	P1,(POINT 6,0)		;SET UP BYTE POINTER TO THE DATA.
UME3:	ILDB	CH,P1			;GET A CHARACTER.
	MOVEI	CH," "(CH)		;CONVERT IT TO ASCII.
	GOSUB	UME4			;CONVERT THE CHARACTER.
	IF.ON	P1,77B5,UME3		;JUMP IF HAVE MORE.
	RETURN	ZERO			;RETURN TO CALLER.

;HERE TO CONVERT THE CHARACTER.

UME4:	HRRZ	CH,TAB2(CH)		;TO THE OUTPUT SET.
	IF.OFF	CH,NEC			;SKIP IF GOOD CHARACTER.
	AOS	NOCHR			;COUNT THE BAD CHARACTER.
	TEZ	CH,NEC			;WAS IT BAD.
	HRRZ	CH,TAB2+"\"		;GET THE DEFAULT.
	IF.ON	S,LHEAD,PUT		;JUMP IF LPT HEADER.
	GOTO	@OUTC(OM)		;AND WRITE IT.
;HERE TO SEND A DATE STAMP TO THE OUTPUT DEVICE.

PUTDAT:	MME	T1,.DATE		;GET THE DATE.
PUTXDT:	IDIVI	T1,^D31			;GET THE DAYS INTO T2.
	AOS	T2			;THE CORRECT DAY.
	SAVE	T2			;SAVE IT.
	IDIVI	T1,^D12			;GET THE  MONTH IN T2.
	AOS	T2			;CORRECTED MONTH.
	MOVEI	T1,^D64(T1)		;GET THE YEAR.
	EXCH	T1,ZERO(PDP)		;PUT THE YEAR ON THE STACK.
	SAVE	T1			;THE DAYS ARE NEXT.
	SAVE	T2			;AND THEN THE MONTH.
	MOVEI	P1,"/"			;CHARACTER TO SEPARATE THINGS.
	GOTO	PDTBUF			;MOVE TH PDL TO THE BUFFER.

;HERE TO SEND A TIME STAMP TO THE OUTPUT DEVICE.

PUTTIM:	MME	T1,.TIME		;GET THE TIME OF DAY.
	IDIVI	T1,^D1000		;MSEC. IN T2.
	IDIVI	T1,^D60			;SECONDS IN T2.
	SAVE	T2			;ONTO THE STACK.
	IDIVI	T1,^D60			;MIN IN P2 HOURS IN P1.
	SAVE	T2			;MINUTES TO STACK.
	SAVE	T1			;HOURS TO THE STACK.
	MOVEI	P1,":"			;CHARACTER TO DELIMIT THINGS.

;HERE TO MOVE THE TOP THREE ELEMENTS OF THE STACK INTO THE BUFFER
;AS NUMBERS.

PDTBUF:	MOVNI	P2,3			;TIMES TO DO IT.
PDTBU0:	UNSAVE	T2			;GET AN ITEM.
	GOSUB	ZPUT			;MOVE IT.
	AOJE	P2,RET0			;JUMP IF DONE.
	MOVEI	CH,ZERO(P1)		;GET THE DELIMITER.
	GOSUB	UME4			;PLACE.
	GOTO	PDTBU0			;DO THE NEXT ONE.
ZPUT:	CAIGE	T2,^D10			;IS IT BETTER THEN 10.
	UME	.ASC,[ASCIZ "0"]	;NO SO ADD A ZERO.
ZPUT1:	IDIVI	T2,^D10			;SLICE OFF A DIGIT.
	HRLM	T3,ZERO(PDP)		;SAVE A DIGIT.
	SKIPE	T2			;SKIP IF DONE.
	GOSUB	.-3			;CONTINUE ON.
	HLRZ	CH,ZERO(PDP)		;GET A DIGIT BACK.
	MOVEI	CH,"0"(CH)		;CONVERT TO ASCII.
	GOTO	UME4			;INTO THE BUFFER.
;HERE TO PRINT P1 AS A THREE DIGIT NUMBER.

THEDIG:	CAIGE	P1,^D100		;DOES IT PASS.
	EME	.CH,[EXP "0"]		;PAD.

;HERE TO PRINT AC P1 AS A TWO DIGIT NUMBER.

TWODIG:	CAIGE	P1,^D10			;IS IT LESS THEN 10.
	EME	.CH,[EXP "0"]		;YES ADD A ZERO.
					;FALL INTO DECOUT.

;HERE TO PRINT P1 AS A DECIMAL NUMBER.

DECOUT:	SKIPA	P3,[^D10]		;SET THE RADIX.
PUTOCT:	MOVEI	P3,10			;SET THE RADIX.
	MOVE	T1,P1			;TO A BETTER AC.
	IDIV	T1,P3			;SLICE OFF A DIGIT.
	HRLM	T2,ZERO(PDP)		;SAVE DIGIT.
	SKIPE	T1			;DONE YET.
	GOSUB	PUTOCT+2		;NO CONTINU.
	HLRZ	T1,ZERO(PDP)		;COPY DIGIT.
	MOVEI	T1,"0"(T1)		;CONVERT TO ASCII.
	EME	.CH,T1			;PRINT IT.
	RETURN	ZERO			;TRY AGAIN.

;HERE TO PRINT T1 AS A SIXBIT WORD.

PUTSIX:	JUMPE	T1,RET0			;SUPPRESS TRAILING SPACES.
	LDB	CH,[POINT 6,T1,5]	;GET A CHARACTER.
	MOVEI	CH," "(CH)		;CONVERT TO ASCII.
	EME	.CH,CH			;PRINT IT.
	LSH	T1,6			;GET NEXT CHARACTER INTO POSITION.
	GOTO	PUTSIX			;LOOP UNTIL DONE.
;HERE TO PRINT THE FILE NAME IN P1 AND P2.

PUTNAM:	HLLZS	P2			;CLEAR THE RIGHT HALF.
	CAMN	P2,[SIXBIT "UFD"]	;IS THIS A UFD.
	GOTO	PUTNM0			;YES.
	MOVE	T1,P1			;COPY TO BETTER AC.
	GOSUB	PUTSIX			;PRINT IT.
	SKIPE	T1,P2			;TEST AND COPY.
	EME	.CH,[EXP "."]		;FOR EXTENSION.
	GOTO	PUTSIX			;PRINT IT.
PUTNM0:	EME	.CH,[EXP "["]		;SIGNAL PPN COMING.
	SAVE	P1			;SAVE UFD NAME.
	HLRZS	P1			;GET HALF OF IT.
	GOSUB	PUTOCT			;PRINT IT.
	EME	.CH,[EXP ","]		;SEPARATE P FROM PN.
	UNSAVE	P1			;GET IT BACK.
	HRRZS	P1			;ZERO LEFT HALF.
	GOSUB	PUTOCT			;PRINT IT.
	EME	.STR,[ASCIZ "].UFD"]	;TELL THE REST.
	RETURN	ZERO			;RETURN TO CALLER.

;HERE TO BRANCH ON THE DEVICE TYPE.

WLDDEV:	IF.ON	IF,DSK,RET0		;DISK RETURN.
	IF.ON	IF,DTA,RET1		;DECTAPE RETURN.
	IF.ON	IF,MTA,RET2		;MAG-TAPE RETURN.
	RETURN	THREE			;NON-DIRECTORY DEVICE.

;HERE ON THE INITIAL CALL TO FIND A FILE.

LOKWLD:	GOSUB	SAV4			;SAVE SOME AC'S.
	BRANCH	WLDDEV,<WLDDSK,WLDDTA,WLDMTA> ;BRANCH ON DEVICE.
	OFF	IF,WILD!SCAN		;DEVICE DOESN'T HAVE WILDS.
	OFF	OF,WILD!SCAN		;CLEAR WILD BITS.
	RETURN	ONE			;AND SAY WE HAVE A FILE.

;HERE ON A CALL FOR A FILE WHEN WE HAVE ALREADY FOUND
;ONE ON THE DEVICE.

GETNXT:	GOSUB	SAV4			;SAVE SOME AC'S.
	BRANCH	WLDDEV,<NXTDSK,NXTDTA,WLDMTA> ;BRANCH ON DEVICE.
	RETURN	ZERO			;OTHER DEVICES DON'T HAVE ANY.
;HERE TO FIND A FILE ON MAG-TAPE.

WLDMTA:	GOSUB	GETLAB			;GET A LABEL INTO CORE.
	GOTO	WDMTA0			;END OF FILE FOUND.
	BRANCH	INPLAB,<NXTBLK,NXTNAM>	;BRANCH ON WHAT WE READ.
	JSP	T1,BADVOL		;BAD VOLUME FOUND.
	IF.OFF	S,L.HDR,NXTBLK		;CHECK NEXT IF NOT HDR.
	SKIPN	T1,IFILE+LABEL		;GET THE LABEL INDEX.
	RETURN	ONE			;TAPE IS AT THE RIGHT SPOT.
	HRRZ	T1,LB.TYP(T1)		;GET THE DISPATCH ADDRESS.
	CAIE	T1,LB.ICL		;IF NOT DEC LABEL TYPE
	GOSUB	SKPFIL			;SKIP EOF MARK AFTER LABEL.
	RETURN	ONE			;FOUND A FILE FOR HIM.

WDMTA0:	IF.OFF	IF,WNAME!WEXT!SCAN	;SKIP IF NOT SEARCHING.
	RETURN	ZERO			;ELSE GIVE EOF RETURN.
	SKIPE	IFILE+LABEL		;SKIP IF NO LABEL TYPE.
	GOTO	BADTM			;ELSE UNEXPECTED FILE MARK.
	RETURN	ONE			;IGNORE FILE MARK.

NXTBLK:	IF.ON	IF,WNAME!WEXT!SCAN	;IF WILD OR SCANNING SKIP.
	GOTO	NOLAB			;ELSE TELL BAD THINGS.
NXTFIL:	MOVE	T1,IFILE+LABEL		;GET THE LABEL INDEX.
	HRRZ	T1,LB.TYP(T1)		;GET THE DISPATCH ADDRESS.
	CAIE	T1,LB.ICL		;SKIP IF DEC LABELS.
	GOTO	SKPIT			;SKIP AHEAD.
	IF.ON	S,L.HDR,WLDMTA		;IF NOT HEADER SKIP.
SKPIT:	GOSUB	SKPFIL			;SKIP A FILE ON TAPE.
	GOTO	WLDMTA			;AND CHECK FOR A LABEL.

NXTNAM:	IF.OFF	IF,WNAME!WEXT!SCAN,NOMAT;JUMP IF NOT WILD OR SCANNING.
	GOTO	NXTFIL			;ELSE GO TO THE NEXT FILE.
;HERE TO GET A FILE FROM DECTAPE.

WLDDTA:	MOVE	T1,IFILE+DEVICE		;GET THE DEVICE NAME.
	MOVEM	T1,LABSTR		;SAVE IT AS THE STRUCTURE.
	MME	T1,.PPN			;GET OUT PPN.
	NOP				;IN CASE OF JACCT.
	MOVEM	T1,LABPPN		;SAVE THE PPN.
	CLOSE	IF,ZERO			;CLOSE THE UNIT.
	GETSTS	IF,T1			;GET THE DEVICE STATUS.
	SAVE	T1			;ONTO THE STACK.
	SETSTS	IF,DMP+100		;CHANGE TO DUMP MODE.
	USETI	IF,144			;SET TO READ DIRECTORY BLOCK.
	DEVOP	IN,IF,DTACTL		;READ THE DIRECTORY.
	GOTO	DTNXT0			;RIGHT ON.
	GETSTS	IF,T1			;GET THE DEVICE STATUS.
	IF.OFF	T1,E.ERR,DTNXT0		;JUMP IF NOT A PARITY ERROR.
	IF.OFF	T1,E.PAR,LKIERR		;JUMP IF A BAD ERROR.
	IF.OFF	IF,NOERROR,IPERR	;JUMP IF WANTS ERRORS.
	AOS	INPERR			;COUNT THE ERROR.
	PRINT	(% Parity error reading DECtape directory.)
DTNXT0:	UNSAVE	T1			;GET THE DEVICE STATUS BACK.
	SETSTS	IF,ZERO(T1)		;SET IT RIGHT.
	CLOSE	IF,ZERO			;CLEAR ANY ERROR BITS.
	HRLZI	T1,-^D23		;FILES IN DIRECTORY.
	MOVEM	T1,DTPTR		;SAVE THE POINTER WORD.
	GOTO	DTSET			;LOOK FOR THE FILE.
NXTDTA:	IF.OFF	IF,WNAME!WEXT,RET0	;RETURN IF NOT WILD.
DTSET:	MOVE	T1,DTPTR		;GET THE POINTER WORD.
DTNXT:	AOBJP	T1,RET0			;JUMP IF NO MORE.
	SKIPN	P1,DTBUF+DTNAM(T1)	;GET THE NAME IF THERE.
	GOTO	DTNXT			;ELSE TRY THE NEXT ONE.
	HLLZ	P2,DTBUF+DTEXT(T1)	;GET ITS EXTENSION.
	MOVEM	P1,LABNAM		;SAVE THE NAME.
	MOVEM	P2,LABNAM+1		;SAVE THE EXTENSION.
	GOSUB	TSTNAM			;CHECK ON THE NAME.
	GOTO	DTNXT			;DO THE NEXT ONE.
	MOVEM	T1,DTPTR		;SAVE THE NEW POINTER WORD.
	MOVE	P1,[POINT 5,DTBUF]	;POINTER TO DIRECTORY.
	MOVEI	P2,^D578		;USEABLE BLOCKS ON DTA.
	SETZM	LABSIZ			;CLEAR FILE SIZE.
DTLOP:	ILDB	P3,P1			;GET A SAT BLOCK.
	CAIN	P3,ZERO(T1)		;SKIP IF NOT THIS FILE.
	AOS	LABSIZ			;COUNT BLOCK IN FILE.
	SOJG	P2,DTLOP		;JUMP IF MORE TO GO.
	LDB	T1,[POINT 12,DTBUF+DTEXT(T1),35] ;GET THE DATE.
	HRLI	T1,(57B8)		;GET THE DEFAULT PROTECTION.
	MOVEM	T1,LABDTW		;SAVE IT.
	SETZM	LABVOL			;CLEAR VOLUME NUMBER.
	SKIPN	LSTWRD			;SKIP IF LISTING.
	GOTO	OPNIT			;GO OPEN THE FILE.
	RETURN	ONE			;SKIP BACK.
;HERE FOR A WILD CARD LOOKUP ON DISK.

WLDDSK:	MOVE	T1,IFILE+DEVICE		;GET THE DEVICE NAMED.
	MOVE	T2,[XWD ONE,T1]		;POINTER FOR MME.
	MME	T2,.DCHR		;GET THE CHARACTERISTICS OF IT.
	GOTO	SYSDEV			;IF MME FAILS MUST BE SYS.
	MOVE	T1,IFILE+DEVICE		;GET THE DEVICE NAMED.
	MOVEM	T1,PATH			;SAVE IT.
	MOVE	T1,[XWD 5,PATH]		;POINTER TO MME.
	MME	T1,.PATH		;SEE IF REALLY SYS.
	GOTO	TSTDEV			;ERROR CONTINUE ON.
	MOVE	T1,[XWD 1,4]		;SYS PPN.
	CAMN	T1,PATH+2		;IS THIS SYS.
	GOTO	SYSDEV			;FLAG SYSTEM SEARCH.
TSTDEV:	IF.OFF	T2,GDSK,GENDEV		;JUMP IF GENERIC DISK.
	MOVE	T1,IFILE+DEVICE		;GET THE DEVICE NAMED.
	GOTO	USEDEV			;AND USE IT.
SYSDEV:	SETOM	SYSSRH			;FLAG SYSTEM SEARCH.
GENDEV:	SETOM	SEARCH			;FLAG WE ARE SEARCHING.
NXTSTR:	SKIPN	SEARCH			;SKIP IF SEARCHING.
	RETURN	ZERO			;ELSE WE ARE DONE.
	SKIPN	T1,LSTDEV		;GET THE LAST DEVICE USED.
	SETOM	T1			;IF NONE START FROM THE TOP.
	SKIPE	SYSSRH			;SKIP IF THIS JOBS LIST.
	GOTO	SYSLOK			;ELSE USE THE SYSTEM LIST.
	IF.ON	IF,WDEV,USEALL		;USE EVERY DEVICE IF WILD DSK.
	MOVE	T2,[XWD ONE,T1]		;POINTER FOR MME.
	MME	T2,.JLST		;GET A STRUCTURE.
	RETURN	ZERO			;QUIT ON ERRORS.
	GOTO	GOTDEV			;USE THIS DEVICE.
USEALL:	MOVE	T1,LSTDEV		;GET THE LAST DEVICE USED.
	MME	T1,.ALST		;GET THE NEXT ONE.
	RETURN	ZERO			;RETURN ON ERROR.
	GOTO	GOTDEV			;USE THE DEVICE.
SYSLOK:	MOVEM	T1,GOBLST+2		;SAVE THE LAST DEVICE USED.
	SETZM	GOBLST			;SPECIFY SYSTEM LIST.
	MOVE	T1,[XWD 1,4]		;SYSTEM PPN.
	MOVEM	T1,IFILE+PPN		;SET THE SYS PPN AS OURS.
	MOVEM	T1,GOBLST+1		;SAVE IT.
	MOVE	T1,[XWD THREE,GOBLST]	;POINTER FOR EXEC.
	MME	T1,.GLST		;GET A STRUCTURE.
	RETURN	ZERO			;QUIT ON ERRORS.
	MOVE	T1,GOBLST+2		;GET THE DEVICE NAME.
GOTDEV:	CAMN	T1,[-1]			;HAVE WE REACHED THE END.
	RETURN	ZERO			;YES RETURN.
	JUMPE	T1,RET0			;JUMP IF AT THE FENCE.
USEDEV:	MOVEM	T1,LSTDEV		;SAVE AS THE LAST DEVICE USED.
	MOVEM	T1,UFDDEV+1		;SET IN PARAMETER BLOCK.
	MOVEM	T1,MFDDEV+1		;SAVE FOR THE MFD.
	IF.OFF	IF,WP!WPN,ONLUFD	;IF NOT ACCROSS PPNS NO NEED FOR MFD.
	OPEN	MF,MFDDEV		;OPEN CHANNEL FOR THE MFD.
	GOTO	NXTSTR			;DO NEXT IF THIS FAILS.
;HERE WHEN READY TO START ON A NEW UFD.

ONLUFD:	OPEN	UF,UFDDEV		;OPEN THE DEVICE.
	GOTO	NXTSTR			;IF ERROR GET THE NEXT.
	SKIPN	T1,IFILE+PPN		;PPN SPECIFIED.
	MME	T1,.PPN			;NO GET THE CURRENT ONE.
	NOP				;IN CASE OF JACCT.
	SKIPE	SYSSRH			;IS IT REALLY THE SYSTEM PPN.
	MOVE	T1,[XWD 1,4]		;YES GET ITS PPN.
	MOVEM	T1,IFILE+PPN		;SAVE THE PPN.
	IF.OFF	IF,WP!WPN,OPNUFD	;JUMP IF PPN ISN'T WILD.
	MOVE	T1,[XWD ONE,ONE]	;MFD PPN.
	MOVEM	T1,MFDNAM		;SAVE ITS NAME.
	MOVEM	T1,MFDNAM+3		;SAVE THE PPN OF THE OWNER.
	MOVSI	T1,'UFD'		;THE MFD IS ITS OWN UFD.
	MOVEM	T1,MFDNAM+1		;SAVE THE EXTENSION.
	SETZM	MFDNAM+2		;CLEAR DATE TIME PROTECTION WORD.
	LOOKUP	MF,MFDNAM		;OPEN THE MFD.
	GOTO	MFDERR			;ERROR ON LOOKUP.
NXTMFD:	DEVOP	IN,MF,MFDCTL		;READ A BLOCK OF THE MFD.
	GOTO	FNDPPN			;READ IS O.K. FIND A PPN.
	GETSTS	MF,T1			;SLIGHT ERROR.
	IF.ON	T1,E.EOF,NXTSTR		;IF DONE THEM ALL GET NEXT STR.
	IF.OFF	T1,E.PAR,FNDPPN		;IF NO ERROR JUMP.
	IF.OFF	IF,NOERROR,IPERR	;JUMP IF WANTS TO KNOW.
	AOS	INPERR			;COUNT THE ERROR.
	PRINT	(% Parity error reading MFD.)
FNDPPN:	HRLZI	T1,-101			;COUNTER FOR ENTRIES.
	MOVEM	T1,MFDPTR		;SAVE THE POINTER.
NXTPPN:	IF.OFF	IF,WP!WPN,NXTSTR	;JUMP IF NOT WIL PPNS.
	MOVE	T1,MFDPTR		;GET THE MFD POINTER.
NTPPN:	AOBJP	T1,NXTMFD		;JUMP IF NEED NEXT BLOCK.
	AOS	T1			;BUMP POINTER.
	HLRZ	P1,MFDBUF-1(T1)		;GET THE EXTENSION.
	CAIE	P1,'UFD'		;IS IT A UFD.
	GOTO	NTPPN			;NO TRY NEXT.
	IF.ON	IF,WP,CHKPN		;JUMP IF WILD PROJECT NUMBER.
	HLRZ	P1,MFDBUF-2(T1)		;GET THE PROJECT NUMBER.
	HLRZ	P2,IFILE+PPN		;GET THE DESIRED MATCH.
	CAIE	P1,ZERO(P2)		;SKIP IF O.K.
	GOTO	NTPPN			;ELSE TRY NEXT.
CHKPN:	IF.ON	IF,WPN,USEPPN		;JUMP IF WE HAVE A MATCH.
	HRRZ	P1,MFDBUF-2(T1)		;GET THE PROGRAM NUMBER.
	HRRZ	P2,IFILE+PPN		;GET THE DESIRED MATCH.
	CAIE	P1,ZERO(P2)		;SKIP IF ONE TO USE.
	GOTO	NTPPN			;ELSE TRY NEXT.
USEPPN:	MOVEM	T1,MFDPTR		;SAVE POINTER TO BUFFER.
	MOVE	T1,MFDBUF-2(T1)		;GET THE PPN THAT MATCHES.
;HERE WITH A PPN TO USE IN T1.

OPNUFD:	MOVEM	T1,UFDNAM		;SAVE THE NAME OF THE UFD.
	MOVEM	T1,LABPPN		;SAVE THE PPN.
	MOVSI	T1,'UFD'		;UFD EXTENSION.
	MOVEM	T1,UFDNAM+1		;SAVE THE EXTENSION.
	SETZM	UFDNAM+2		;CLEAR DATE TIME PROTECTION WORD.
	MOVE	T1,[XWD ONE,ONE]	;MFD PPN.
	MOVEM	T1,UFDNAM+3		;SAVE THE PPN.
	LOOKUP	UF,UFDNAM		;OPEN THE DIRECTORY.
	GOTO	UFDERR			;ERROR ON LOOKUP.
NXTSEC:	DEVOP	IN,UF,UFDCTL		;READ A BLOCK.
	GOTO	CHKBLK			;THE READ WAS O.K.
	GETSTS	UF,T1			;A LITTLE ERROR.
	IF.ON	T1,E.EOF,NXTPPN		;IF END GET NEXT.
	IF.OFF	T1,E.PAR,CHKBLK		;JUMP IF WE ARE NOT INTERESTED.
	IF.OFF	IF,NOERROR,IPERR	;JUMP IF WANTS TO KNOW.
	AOS	INPERR			;COUNT THE ERROR.
	PRINT	(% Parity error reading UFD.)
CHKBLK:	HRLZI	T1,-101			;COUNT OF NAMES IN BLOCK.
	MOVEM	T1,DKPTR		;SAVE THE POINTER.
	GOTO	DKSET			;LOOK FOR THE FILE.
NXTDSK:	IF.OFF	IF,WILD,RET0		;JUMP IF NOT WILD.
DKSET:	MOVE	T1,DKPTR		;GET THE POINTER.
DKNXT:	AOBJP	T1,NXTSEC		;GET THHE NEXT SECTOR.
	HLLZ	P2,UFDBUF(T1)		;GET THE EXTENSION.
	AOS	T1			;BUMP THE POINTER.
	SKIPN	P1,UFDBUF-2(T1)		;SKIP IF NAME IS THERE.
	GOTO	DKNXT			;GET THE NEXT ONE.
	MOVEM	P1,LABNAM		;SAVE THE NAME.
	MOVEM	P2,LABNAM+1		;SAVE THE EXTENSION.
	GOSUB	TSTNAM			;SEE IF GOOD NAME.
	GOTO	DKNXT			;TRY TRY AGAIN.
	MOVEM	T1,DKPTR		;SAVE POINTER.
	MOVE	T1,UFDDEV+1		;GET THE STRUCTURE'S NAME.
	MOVEM	T1,LABSTR		;SAVE THE NAME.
	EXCH	T1,IFILE+DEVICE		;MAKE IT HIS.
	OPEN	IF,IFILE+STATUS		;OPEN THIS STRUCTURE.
	GOTO	DK0NXT			;SHOULD NEVER HAPPEN.
	MOVEM	T1,IFILE+DEVICE		;GIVE HIM HIS DEVICE BACK.
	HLRZ	T1,MSIZ(IM)		;GET THE INPUT BYTE SIZE.
	DPB	T1,[POINT 6,IBUF+1,11]	;SET THE SIZE WE WANT.
	MOVE	T1,IJOBFF		;GET INPUT JOB FIRST FREE.
	EXCH	T1,.JBFF		;SET IT AS CURRENT.
	SAVE	T1			;SAVE FIRST FREE.
	GOSUB	MONIBF			;GET SOME BUFFERS.
	UNSAVE	.JBFF			;RESTORE FIRST FREE.
	MOVE	T1,UFDNAM		;GET THE PPN WE FOUND THIS IN.
	MOVEM	T1,IFILE+PPN		;SAVE THE PPN.
	GOTO	OPNIT			;OPEN THE FILE.
DK0NXT:	MOVEM	T1,IFILE+DEVICE		;REPLACE THE DEVICE.
	GOTO	NXTSTR			;TRY THE NEXT STRUCTURE.
;HERE TO OPEN THE FILE THAT HAS BEEN SELECTED.

OPNIT:	SETZM	LABVOL			;CLEAR VOLUME NUMBER.
	SKIPE	FSTWRD			;SKIP IT NOT FAST LIST.
	RETURN	ONE			;DON'T OPEN IT FOR FAST LIST.
	SAVE	IFILE+PPN		;SAVE THE PPN.
	LOOKUP	IF,IFILE+NAME		;OPEN THE FILE.
	GOTO	MAYBE			;MAYBE STOP NOW.
	HLRE	T1,IFILE+PPN		;IF DSK THIS IS SIZE.
	JUMPGE	T1,GOTSIZ		;IF POSITIVE IT IS BLOCKS.
	MOVNS	T1			;GET THE POSITIVE WORDS.
	IDIVI	T1,200			;CONVERT TO BLOCKS.
	SKIPE	T2			;SKIP IF EVEN.
	AOS	T1			;ROUND UP.
GOTSIZ:	UNSAVE	IFILE+PPN		;RESTORE THE PPN.
	IF.ON	IF,DTA,RET1		;RETURN IF DTA.
	MOVEM	T1,LABSIZ		;SAVE THE SIZE OF THE FILE.
	MOVE	T1,IFILE+DATTIM		;GET THE DATE, TIME, PROT WORD.
	AND	T1,[EXP 777B8]		;JUST THE PROTECTION BITS.
	MOVEM	T1,LABDTW		;SAVE IT FOR DISK.
	LDB	T1,[POINT 12,IFILE+DATTIM,35] ;GET THE DATE.
	MOVE	T2,IFILE+EXT		;LOAD HIGH ORDER DATE.
	LSH	T2,-3			;POSITION HIGH-ORDER BITS.
	ANDI	T2,70000		;ISOLATE BITS.
	IORI	T1,ZERO(T2)		;COMBINE HIGH AND LOW ORDER.
	HRRM	T1,LABDTW		;SAVE IT.
	RETURN	ONE			;GIVE GOOD RETURN.
;HERE ON A MFD LOOKUP ERROR.

MFDERR:	MOVEI	SIDE,MFDDEV		;GET POINTER TO THINGS.
	GOSUB	DIRERR			;TELL OF ERROR.
	GOTO	NXTSTR			;AND TRY NEXT STRUCTURE.

;HERE ON A UFD LOOKUP ERROR.

UFDERR:	MOVEI	SIDE,UFDDEV		;GET POINTER TO THINGS.
	GOSUB	DIRERR			;TYPE THE ERROR MESAGE.
	GOTO	NXTPPN			;TRY AGAIN.

;HERE TO TYPE ERROR MESSAGES FOR MFD AND UFD LOOKUP ERRORS.

DIRERR:	EME	.STR,[ASCIZ /% Directory "/]
	SETZM	P4			;CLEAR FLAGS.
	GOTO	TYPE0			;SEND THE MESSAGE.

	USE	DATA

BSS	PATH,5
BSS	DTBUF,200
BSS	DTPTR,ONE
DTACTL:	IOWD	200,DTBUF
	BSS	ONE
	EXP	MF
MFDDEV:	EXP	DMP
	BSS	TWO
BSS	MFDNAM,4
BSS	GOBLST,THREE
	EXP	UF
UFDDEV:	EXP	DMP
	BSS	TWO
BSS	UFDNAM,4
BSS	MFDBUF,200
BSS	MFDPTR,ONE
MFDCTL:	IOWD	200,MFDBUF
	BSS	ONE
UFDCTL==DTACTL
DKPTR==DTPTR
UFDBUF==DTBUF

	USE	CODE
;HERE TO PLACE THE DATE INTO THE BUFFER AS
;YYMMDD.

COBDAT:	IDIVI	T1,^D31			;DAYS INTO T2.
	SAVE	T2			;SAVE THE DAYS.
	IDIVI	T1,^D12			;MONTHS IN T2.
	SAVE	T2			;SAVE THE MONTH.
	MOVEI	T1,^D64(T1)		;GET THIS YEAR.
	GOSUB	DEPTWO			;INTO BUFFER.
	UNSAVE	T1			;GET THE MONTHS BACK.
	AOS	T1			;FOR THE ONE LOST.
	GOSUB	DEPTWO			;ADD INTO BUFFER.
	UNSAVE	T1			;GET THE DAYS.
	AOS	T1			;COUNT EXTRA DAY.
	GOTO	DEPTWO			;INTO BUFFER.

;HERE TO COPY THE NUMBER OF CHARACTERS SPECIFIED BY
;THE COUNT IN P3 AND POINTER IN P2 TO THE POINTER
;IN P1.

PLACE:	ILDB	CH,P2			;GET A CHARACTER.
	IDPB	CH,P1			;SAVE IT.
	SOJG	P3,PLACE		;DO THEM ALL.
	RETURN	ZERO			;TO SENDER.

;HERE TO PLACE A FEW SPACES INTO THE LABEL
;BUFFER. PUTS SPACES BY THE POINTER IN P1 AND FOR THE COUNT
;IN P3.

SPACE:	SETZM	CH			;SET CH TO A SPACE.
ANYCHR:	IDPB	CH,P1			;WRITE IT INTO THE BUFFER.
	SOJG	P3,ANYCHR		;CONTINUE ON.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO PRINT T2 AS A TWELVE DIGIT OCTAL NUMBER.

OCTOUT:	MOVNI	T3,^D12			;DUMP A WORD.
	SETZM	T1			;ZERO STORAGE.
	LSHC	T1,3			;GET A DIGIT.
	MOVEI	CH,"0"(T1)		;CONVERT AND MOVE.
	EME	.CH,CH			;PRINT.
	AOJN	T3,OCTOUT+1		;CONTINUE FOR TWELVE.
	EME	.CH,[EXP " "]		;ADD A SPACE.
	GOTO	ZERO(P4)		;RETURN TO CALLER.
;HERE TO TYPE OUT THE DATE CONTAINED IN T1.

TYPDAT:	IDIVI	T1,^D31			;GET THE DAYS IN T2.
	SAVE	T2			;SAVE THEM.
	IDIVI	T1,^D12			;GET THE MONTH IN T2
	MOVEI	T1,^D64(T1)		;GET THE YEAR IN T1.
	EXCH	T1,ZERO(PDP)		;PUT THE YEAR ON THE STACK.
	SAVE	T1			;PLACE THE DAY ON THE STACK.
	MOVEI	P1,ONE(T2)		;MONTHS TO A BETTER AC.
	GOSUB	TWODIG			;PRINT THE MONTH.
	EME	.CH,[EXP "/"]		;DELIMIT THE MONTH.
	UNSAVE	P1			;GET THE DAYS BACK.
	MOVEI	P1,ONE(P1)		;SET THE DAYS RIGHT.
	GOSUB	TWODIG			;PRINT THE DAY OF THE MONTH.
	EME	.CH,[EXP "/"]		;DELIMIT THE DAY.
	UNSAVE	P1			;GET THE YEAR.
	GOTO	TWODIG			;PRINT THE YEAR.

;HERE TO TYPE THE TIME OF DAY CONTAINED IN T1.

TYPTIM:	IDIVI	T1,^D60000		;SLICE OFF MILLISECONDS.
	IDIVI	T1,^D60			;HOURS IN T1 MINUTES IN T2.
	SAVE	T2			;SAVE THE MINUTES.
	MOVE	P1,T1			;TO A BETTER AC.
	GOSUB	TWODIG			;PRINT THE HOURS.
	EME	.CH,[EXP ":"]		;DELIMIT HOURS FROM SECONDS.
	UNSAVE	P1			;GET THE MINUTES BACK.
	GOTO	TWODIG			;PRINT THE MINUTES.
;HERE TO FILL IN DEFAULTS FOR THE LABELS.

LABFIL:	MOVEM	T1,LABDTW		;SAVE THE LABEL DATE.
	MOVSI	T1,'DSK'		;GET THE DEVICE.
	MOVEM	T1,LABSTR		;SAVE THE DEVICE.
	MOVEI	T1,057			;PROTECTION BITS.
	DPB	T1,[POINT 8,LABDTW,8]	;SET THE PROTECTION WORD.
	SKIPN	T1,OFILE+PPN		;IS TERE A PPN.
	MME	T1,.PPN			;USE THE CURRENT ONE.
	NOP				;IN CASE OF JACCT.
	MOVEM	T1,LABPPN		;SAVE THE PPN WORD.
	RETURN	ONE			;GIVE GOOD LABEL RETURN.

;HERE TO TAKE A SIXBIT NUMBER CONTAINED IN T2
;AND CONVERT IT TO AN OCTAL NUMBER.

TOBIN:	GOSUB	SAV3			;SAVE SOME AC'S.
	MOVEI	P3,10			;SET OCTAL RADIX.
	GOTO	TOOCT1			;CONVERT IT.
TOOCT:	GOSUB	SAV3			;SAVE SOME AC'S.
	MOVEI	P3,^D10			;SET RADIX TO TEN.
TOOCT1:	SETZM	T3			;CLEAR RESULT.
	IOR	T2,[SIXBIT "000000"]	;ADD LEADING ZEROS.
	MOVE	P1,[POINT 6,T2]		;POINT TO DATA.
TOOCT0:	ILDB	P2,P1			;GET A CHARACTER.
	IMULI	T3,ZERO(P3)		;SHIFT LEFT FOR BASE.
	ADDI	T3,-'0'(P2)		;ADD IN NEW DIGIT.
	IF.ON	P1,77B5,TOOCT0		;JUMP IF MORE TO GO.
	RETURN	ZERO			;ELSE RETURN TO CALLER.
;HERE TO TAKE THE DATE IN THE FORM YYMMDD IN T1
;AND CONVERT IT TO ((YEAR-1964)*12+(MONTH-1))*31+DAY-1.

DATCOB:	LDB	T2,[POINT 12,T1,11]	;LOAD THE YEAR.
	GOSUB	TOOCT			;MAKE IT OCTAL.
	SUBI	T3,^D64			;YEAR-1964.
	IMULI	T3,^D12			;(YEAR-1964)*12.
	SAVE	T3			;SAVE THE DATE SO FAR.
	LDB	T2,[POINT 12,T1,23]	;GET THE MONTH.
	GOSUB	TOOCT			;CONVERT IT TO OCTAL.
	UNSAVE	T2			;GET THE ACCUMULATED DATE BACK.
	ADDI	T2,-ONE(T3)		;(YEAR-1964)*12+(MONTH-1).
	IMULI	T2,^D31			;((YEAR-1964)*12+(MONTH-1))*31.
	SAVE	T2			;SAVE IT.
	LDB	T2,[POINT 12,T1,35]	;GET THE DAY.
	GOSUB	TOOCT			;CONVERT IT TO OCTAL.
	UNSAVE	T1			;GET THE ACCUMULATED DATE BACK.
	ADDI	T1,-ONE(T3)		;((YEAR-1964)*12+(MONTH-1))*31+DAY-1.
	RETURN	ZERO			;COMPRESSED DATE IN T1.

;HERE TO TAKE THE DATE IN THE FORM YYDDD IN T1
;AND CONVERT IT TO ((YEAR-1964)*12+(MONTH-1))*31+DAY-1.

DATBCL:	LDB	T2,[POINT 12,T1,11]	;GET THE YEAR.
	GOSUB	TOOCT			;CONVERT TO OCTAL.
	SAVE	T3			;SAVE FOR LATER.
	SUBI	T3,^D64			;YEAR-1964.
	IMULI	T3,^D12			;(YEAR-1964)*12.
	SAVE	T3			;SAVE IT ON THE STACK.
	LDB	T2,[POINT 18,T1,29]	;COPY THE DAYS.
	GOSUB	TOOCT			;CONVERT IT TO OCTAL.
	HRLZI	T2,-^D11		;COUNTER FOR MONTH SCAN.
	CAML	T3,MONTH+1(T2)		;HAVE WE PASSED THE MONTH.
	AOBJN	T2,.-1			;NO CONTINUE.
	UNSAVE	T1			;GET THE ACCUMULATED DATE BACK.
	ADDI	T1,-ONE(T2)		;(YEAR-1964)*12+(MONTH-1).
	IMULI	T1,^D31			;((YEAR-1964)*12+(MONTH-1))*31.
	SUB	T3,MONTH-1(T2)		;DAYS IN THIS MONTH IN T3.
	ADDI	T1,-ONE(T3)		;((YEAR-1964)*12+(MONTH-1))*31+DAY-1
	CAIG	T3,^D59			;SKIP IF PAST FEB.
	GOTO	DATBL0			;JUMP IF NOT PAST FEB.
	MOVE	T2,ZERO(PDP)		;GET THE YEAR BACK.
	IDIVI	T2,^D4			;SEE IF IT IS A LEAP YEAR.
	SKIPN	T3			;SKIP IF NOT.
	SOS	T1			;SUBTRACT OFF EXTRA DAY.
DATBL0:	UNSAVE	T2			;CLEAN UP THE STACK.
	RETURN	ZERO			;COMPRESSED DATE IN T1.
;HERE TO CHECK FOR DEVICE ERRORS.

LOKERR:	IF.ON	T1,E.LOK,LOCK		;JUMP IF DEVICE IS WRITE LOCKED.
	IF.ON	T1,E.HAD,HADERR		;JUMP IF HARDWARE ERROR.
	IF.ON	T1,E.IOB,BLKERR		;JUMP IF USER ERROR.
	GOSUB	ABORT			;IF NOT ONE OF THESE REAL BUG.

;HERE TO SEE IF WE HAVE READ AN EOF.

BCLCHK:	HRRZ	T1,IBUF+1		;PICK UP POINTER TO DATA.
	MOVE	T1,ONE(T1)		;GET DATA WORD.
	CAME	T1,[XWD 170000,0]	;IS IT AN EOF MARK.
	CAMN	T1,[XWD 230000,0]	;NINE TRACK EOF.
	SKIPA				;IT PASSED THAT.
	RETURN	ONE			;FORGET IT.
	HRRZ	T1,MSIZ(IM)		;GET THE BYTES PER WORD.
	CAME	T1,IBUF+2		;DID WE GET JUST THAT MANY.
	RETURN	ONE			;NO -- MUST BE DATA.
	MME	IF,.IOSTP		;WAIT FOR I/O TO STOP.
	GETSTS	IF,T1			;GET THE DEVICE STATUS.
	IF.ON	T1,SYNC,INPEND		;IF SYNC'ED JUMP.
	SKIPN	T1,IFILE+BUFNUM		;GET THE NUMBER OF BUFFERS.
	MOVEI	T1,TWO			;DEFAULT NUMBER.
BCLCK0:	SOJLE	T1,INPEND		;JUMP IF DONE ENOUGH.
	DRIVE	IF,.BSR			;BACK UP PLEASE.
	DRIVE	IF,.WAT			;WAIT FOR IT.
	GOTO	BCLCK0			;DO IT AGAIN.

;HERE TO FUDGE UP THE IBM LABEL NAME.

COPY:	SETZM	ZERO(T2)		;CLEAR TARGET.
COPY0:	SOJL	P3,RET0			;JUMP IF READ ENOUGH.
	ILDB	CH,T1			;GET A CHARACTER.
	JUMPE	CH,COPY1		;ALLOW SPACES.
	CAIGE	CH,'0'			;IS IT BETTER THEN ZERO.
	GOTO	COPY0			;NO IGNORE IT.
	CAIG	CH,'9'			;IS IT GREATER THEN NINE.
	GOTO	COPY1			;A DIGIT IS LEGAL.
	CAIL	CH,'A'			;IS IT LESS THEN A.
	CAILE	CH,'Z'			;OR GREATER THEN Z.
	GOTO	COPY0			;YES SO IGNORE.
COPY1:	IDPB	CH,T2			;SAVE THE CHARACTER.
	SOJG	T3,COPY0		;JUMP IF HAVE ROOM.
	RETURN	ZERO			;ELSE RETURN.
;HERE TO TELL HOW MANY CPU SECONDS AND HOW MANY TIMES
;WE ACCESSED A DEVICE.

STAT:	GOSUB	CRLF			;YES SKIP A LINE.
	SETZM	P1			;SPECIFY THIS JOB.
	MME	P1,.TIM			;GET THE RUN TIME.
	SUB	P1,%TIME		;SUBTRACT START TIME.
	IDIVI	P1,^D1000		;CONVERT TO SECONDS.
	GOSUB	DECOUT			;PRINT THE SECONDS.
	EME	.CH,[EXP "."]		;DELIMIT THEM FROM FRACTIONS.
	MOVE	P1,P2			;MOVE TO BETTER AC.
	GOSUB	THEDIG			;PRINT AS THREE DIGITS.
	EME	.STR,[ASCIZ " sec. "]	;TELL HIM WHAT THAT WAS.
	MOVE	P1,%IO			;GET I/O UNITS.
	GOSUB	DECOUT			;PRINT THEM.
	PRINT	( I/O units.)		;SO HE KNOWS WHAT WE ARE PRINTING.
	HRRZ	P1,.JBREL		;OCTAL LOCATIONS USED.
	GOSUB	PUTOCT			;PRINT THEM.
	PRINT	( octal locations used.);SO HE KNOWS WHAT WE USED.

;HERE TO TELL HOW NAMY BLOCKS WE HAVE READ AND HOW NAMY RECORDS
;THERE WERE IN THE BLOCKS.

	MOVE	P1,IBCNT		;GET BLOCKS READ.
	GOSUB	DECOUT			;PRINT THEM.
	EME	.STR,[ASCIZ " blk. "]	;TELL HIM WHAT IT IS.
	MOVE	P1,IRCNT		;GET THE NUMBER OF RECORDS READ.
	GOSUB	DECOUT			;SHOW IT TO HIM.
	PRINT	( rec. read.)		;TELL HIM WHAT IT MEANS.

;HERE TO TELL HOW MANY BLOCKS WE WROTE AND HOW MANY
;RECORDS WERE IN THOSE BLOCKS.

STAT8:	MOVE	T1,IFILE+MOD		;GET THE INPUT BITS.
	IF.OFF	T1,WNAME!WEXT,STAT88	;JUMP IF INPUT ISN'T WILD.
	MOVE	T1,OFILE+MOD		;GET THE OUTPUT MOD BITS.
	IF.ON	T1,WNAME!WEXT,STAT9	;MEANINGLESS IF WILD.
STAT88:	MOVE	P1,OBCNT		;GET BLOCKS WRITTEN.
	GOSUB	DECOUT			;PRINT THEM.
	EME	.STR,[ASCIZ " blk. "]	;TELL HIM WHAT HE JUST SAW.
	MOVE	P1,ORCNT		;GET THE RECORD COUNT.
	GOSUB	DECOUT			;PRINT THEM.
	PRINT	( rec. written.)	;SO HE KNOWS WHAT HE SEES.
;HERE TO TELL HOW MANY FILES WE HAVE LOOKED AT.

STAT9:	MOVE	P1,IFCNT		;GET THE INPUT FILE COUNT.
	HRREI	P2,-1(P1)		;ONLY IF MORE THEN ONE.
	JUMPLE	P2,STAT6		;JUMP IF NOT MORE.
	GOSUB	DECOUT			;TELL HOW MANY.
	PRINT	( input files read.)	;SO HE KNOWS.
STAT6:	MOVE	P1,OFCNT		;GET THE OUTPUT COUNT.
	HRREI	P2,-1(P1)		;ONLY IF MORE THEN ONE.
	JUMPLE	P2,STAT7		;JUMP IF NOT ENOUGH.
	GOSUB	DECOUT			;TELL HOW MANY.
	PRINT	( output files written.);SO HE KNOWS.

;HERE TO TELL THE BAD THINGS THAT HAPPENED WHILE
;WE WERE CONVERTING THE CHARACTER SETS.

STAT7:	SKIPN	P1,NOCHR		;COUNT OF NON-CONVERTS.
	GOTO	STAT2			;TELL NOTHING IF GOOD.
	GOSUB	DECOUT			;TELL THE BAD NEWS.
	PRINT	( bad characters found.);SO HE KNOWS WHAT IT IS.

;HERE TO TELL ABOUT DEVICE ERRORS IF THERE WERE ANY.

STAT2:	SKIPN	P1,INPERR		;ARE THERE ANY INPUT ERRORS.
	GOTO	STAT4			;NO IGNORE IT.
	GOSUB	DECOUT			;PRINT THEM.
	PRINT	( input parity errors.)
STAT4:	SKIPN	P1,OTPERR		;ANY OUTPUT ERRORS.
	GOTO	STAT5			;NO SO SKIP IT ALL.
	GOSUB	DECOUT			;PRINT THE VALUE.
	PRINT	( output parity errors.)
STAT5:	EME	.CLR,ZERO		;CLEAR BUFFERS.
	RETURN	ZERO			;BACK TO CALLER.
;HERE TO CHECK ON A FILE OR LABEL NAME.

TSTNAM:	IF.ON	IF,WNAME,CHKEXT		;IF WILD NAME CHECK EXT.
	CAME	P1,IFILE+NAME		;DOES NAME MATCH.
	RETURN	ZERO			;NOT THE RIGHT ONE.
CHKEXT:	IF.ON	IF,WEXT,MOVNAM		;MOVE NAME INTO PLACE IF WILD.
	HLLZS	IFILE+EXT		;ZERO THE RIGHT HALF.
	CAME	P2,IFILE+EXT		;CHECK THE EXTENSION.
	RETURN	ZERO			;NO MATCH.
MOVNAM:	IF.OFF	IF,WNAME		;SKIP IF NAME ISN'T WILD.
	MOVEM	P1,IFILE+NAME		;SAVE THIS NAME.
	IF.OFF	IF,WEXT			;SKIP IF NOT WILD EXTENSION.
	MOVEM	P2,IFILE+EXT		;ELSE SAVE THIS ONE.
	MOVE	P1,LABNAM		;GET FIRST HALF OF THE NAME.
	MOVE	P2,LABNAM+1		;GET THE SECOND HALF.
MOVNM0:	IF.OFF	OF,WNAME		;SKIP IF OUTPUT NAME IS TRUE.
	MOVEM	P1,OFILE+NAME		;SAVE THIS NAME.
	IF.OFF	OF,WEXT			;SKIP IF EXTENSION IS TRUE.
	MOVEM	P2,OFILE+EXT		;SAVE THE EXTENSION.
	RETURN	ONE			;GIVE FOUND RETURN.

;HERE TO GET A FUNNY NAME.

DREAM:	MME	T1,.TIME		;GET THE TIME OF DAY.
	IDIVI	T1,^D1000		;LEAVE HOURS, MIN, SEC.
	IDIVI	T1,^D60			;SLICE OFF SECONDS.
	SAVE	T2			;SAVE THEM.
	IDIVI	T1,^D60			;SLICE OFF MIN.
	SAVE	T2			;SAVE THEM.
	MOVE	T3,[POINT 6,WD]		;LOAD A BYTE POINTER.
DREAM0:	GOSUB	DREAM1			;SAVE HOURS.
	UNSAVE	T1			;GET MINS BACK.
	GOSUB	DREAM1			;SAVE MINS.
	UNSAVE	T1			;GET SECONDS BACK.
	GOSUB	DREAM1			;SAVE THEM.
	MOVSI	T2,'CHG'		;EXTENSION.
	MOVE	T1,WD			;PUT IN RIGHT AC.
	RETURN	ZERO			;BACK TO CALLER.
DREAM1:	IDIVI	T1,^D10			;SEPARATE DIGITS.
	MOVEI	T1,'0'(T1)		;MAKE IT SIXBIT.
	IDPB	T1,T3			;SAVE DIGIT.
	MOVEI	T2,'0'(T2)		;MAKE OTHER SIXBIT.
	IDPB	T2,T3			;SAVE IT.
	RETURN	ZERO			;AND RETURN.
;HERE TO CONVERT THE DATE CONTAINED IN T1 TO
;YYDDD AND DEPOSIT THIS BY THE POINTER IN P1.

BCLDAT:	IDIVI	T1,^D31			;GET THE DAYS.
	SAVE	T2			;STICK ONTO STACK.
	IDIVI	T1,^D12			;GET THE MONTHS.
	MOVE	T2,MONTH(T2)		;GET DAYS SO FAR IN YEAR.
	UNSAVE	T3			;GET DAYS BACK.
	ADDI	T2,ONE(T3)		;T2 HAS DAYS SO FAR IN YEAR.
	SAVE	T2			;SAVE THE DAYS.
	MOVEI	T1,^D64(T1)		;UPDATE THE YEAR.
	MOVE	T2,T1			;COPY TO ANOTHER AC.
	IDIVI	T2,4			;MUST BE SURE THIS ISN'T A LEAP YEAR.
	JUMPN	T3,BYEAR		;JUMP IF NOT A LEAP YEAR.
	MOVE	T3,ZERO(PDP)		;GET DAYS BACK.
	CAILE	T3,^D59			;ARE WE PAST FEB.
	AOS	ZERO(PDP)		;YES SO COUNT EXTRA DAY.
BYEAR:	GOSUB	DEPTWO			;PUT TWO DIGITS OUT.
	UNSAVE	T1			;GET THE DAYS BACK.
	MOVEI	T2,'0'			;IN CASE WE MUST PAD.
	CAIGE	T1,^D100		;SKIP IF BETTER THEN 100.
	IDPB	T2,P1			;PAD A ZERO.
DEPTWO:	MOVEI	T2,'0'			;IN CASE WE MUST PAD.
	CAIGE	T1,^D10			;IS IT BETTER THEN 10.
	IDPB	T2,P1			;NO PAD IN A ZERO.
	IDIVI	T1,^D10			;SLICE OFF A DIGIT.
	HRLM	T2,ZERO(PDP)		;SAVE A DIGIT.
	SKIPE	T1			;SKIP IF LAST DIGIT.
	GOSUB	.-3			;CONTINUE FOR ALL DIGITS.
	HLRZ	T1,ZERO(PDP)		;GET A DIGIT FROM STACK.
	MOVEI	CH,'0'(T1)		;CONVERT TO SIXBIT.
	IDPB	CH,P1			;PUT INTO BUFFER.
	RETURN	ZERO			;BACK TO SENDER.

MONTH:	DEC	0,31,59,90,120,151,181,212,243,273,304,334
;HERE TO SAVE THE AC'S ON THE STACK. AC 0(S) IS GLOBAL ACROSS
;ALL ROUTINES AND IS NOT SAVED. AC 17(PDP) IS THE PUSH-DOWN POINTER
;AND SHOULD NOT BE SAVED. ***CAUTION SHOULD BE USED IN CALLING THIS
;ROUTINE FOR IT USES SPACE RAPIDLY ON THE STACK. NOTE RETURNS TO PC,
;PC+1, PC+2, AND PC+3 ARE HANDLED CORRECTLY. THE RETURN FROM THE
;ROUTINE THAT CALLS THIS ROUTINE WILL RESTORE THE AC'S.

STORE:	EXCH	1,0(PDP)		;SAVE AC ONE.
	MOVEM	1,TEMP			;SAVE POINTER TO RETURN.
	HRRZI	1,1(PDP)		;DESTINATION FOR BLT.
	HRLI	1,2			;SOURCE FOR BLT.
	BLT	1,15(PDP)		;SAVE THE AC'S.
	ADD	PDP,[XWD 15,15]		;UPDATE PDP.
	MOVEI	1,3			;BUMP RETURN FOR SKIP.
	ADDM	1,-16(PDP)		;RETURN IS NOW TO PC+3.
	MOVE	1,-15(PDP)		;RESTORE AC 1.
	GOSUB	@TEMP			;RETURN TO SENDER.
	SOS	-16(PDP)		;DECREMENT FOR NORMAL RETURN.
	SOS	-16(PDP)		;DECREMENT FOR RETURN TO PC+2.
	SOS	-16(PDP)		;DECREMENT FOR RETURN TO PC+1.
	HRLZI	16,-15(PDP)		;SOURCE FOR BLT.
	HRRI	16,1			;DESTINATION FOR BLT.
	BLT	16,16			;RESTORE THE AC'S.
	SUB	PDP,[XWD 16,16]		;UPDATE PDP.
	RETURN	ZERO			;BACK TO SENDER.

;STACK MANIPULATORS.

RET3:	AOS	ZERO(PDP)		;RETURN TO PC+3.
RET2:	AOS	ZERO(PDP)		;RETURN TO PC+2.
RET1:	AOS	ZERO(PDP)		;RETURN TO PC+1.
RET0:	RETURN	ZERO			;RETURN TO PC+0.
;HERE TO SAVE THE P AC'S ON THE STACK. SKIP RETURNS HANDLED.

SAV4:	SAVE	[XWD -4,ZERO]		;AC'S TO SAVE.
	GOTO	SAVEAC			;GO SAVE THEM.
SAV3:	SAVE	[XWD -3,ZERO]		;AC'S TO SAVE.
	GOTO	SAVEAC			;SAVE THEM.
SAV2:	SAVE	[XWD -2,ZERO]		;AC'S TO SAVE.
	GOTO	SAVEAC			;GO SAVE THEM.
SAV1:	SAVE	[XWD -1,ZERO]		;AC'S TO SAVE.
SAVEAC:	EXCH	P1,-1(PDP)		;SAVE AC P1.
	MOVEM	P1,TEMP			;SAVE RETURN ADDRESS.
	MOVEI	P1,3			;TO FIX UP RETURN.
	ADDM	P1,-2(PDP)		;RETURN IS NOW TO PC+3.
	UNSAVE	P1			;GET AOBJ WORD FOR SAVE.
	AOBJP	P1,.+3			;JUMP IF SAVED ENOUGH.
	SAVE	P1(P1)			;SAVE AN AC.
	GOTO	.-2			;DO THE NEXT.
	SAVE	P1			;SAVE AC P1.
	MOVEI	P1,ONE(P1)		;POINT P1 TO RETURN.
	SUBM	PDP,P1			;MAKE P1 POINT TO ADR OF RETURN.
	HRRZS	P1			;CLEAR P1 RIGHT HALF.
	SAVE	P1			;PLACE IT ON THE TOP OF THE STACK.
	MOVE	P1,ONE(P1)		;RESTORE P1.
	GOSUB	@TEMP			;DISPATCH...
	SOS	@ZERO(PDP)		;RETURN TO PC.
	SOS	@ZERO(PDP)		;RETURN TO PC+1.
	SOS	@ZERO(PDP)		;RETURN TO PC+2.
	UNSAVE	P1			;TAKE POINTER OFF STACK.
	UNSAVE	P1			;NUMBER OF AC'S SAVED.
	SOJLE	P1,.+3			;JUMP IF DONE ENOUGH.
	UNSAVE	P1(P1)			;RESTORE AN AC.
	GOTO	.-2			;CONTINUE ON.
	UNSAVE	P1			;RESTORE P1.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO RESTORE THE P AC'S. MUST BE CALLED WITH A "GOSUB".

UNS4:	UNSAVE	P4			;GET THE RETURN.
	MOVEM	P4,ZERO(PDP)		;PUT THE RETURN BACK.
	MOVE	P4,-THREE(PDP)		;RESTORE P4.
UNS3:	UNSAVE	P3			;GET THE RETURN.
	MOVEM	P3,ZERO(PDP)		;PUT THE RETURN BACK.
	MOVE	P3,-THREE(PDP)		;RESTORE P3.
UNS2:	UNSAVE	P2			;GET THE RETURN.
	MOVEM	P2,ZERO(PDP)		;PUT THE RETURN BACK.
	MOVE	P2,-THREE(PDP)		;RESTORE P2.
UNS1:	UNSAVE	P1			;GET THE RETURN.
	MOVEI	P1,3			;TO FIX RETURN POINTER.
	EXCH	P1,-4(PDP)		;SO A SUBM CAN BE DONE.
	SUBM	P1,-4(PDP)		;POINT RETURN RIGHT.
	MOVE	P1,-THREE(PDP)		;RESTORE P1.
	SUB	PDP,[XWD 4,4]		;POINT PDP RIGHT.
	RETURN	ZERO			;RETURN.
;HERE TO INCREMENT THE VOLUME NUMBER.

BMPVOL:	ADD	T1,[OCT 464646470000]	;ADD ONE AND HANDLE CARRIES.
	MOVE	T2,T1			;COPY TO BETTER AC.
	AND	T2,[OCT 606060600000]	;ISOLATE CARRY BITS.
	LSH	T2,-3			;PUT THEM IN PLACE.
	SUB	T1,T2			;FUDGE UP CARRIES.
	AND	T1,[OCT 171717170000]	;NOW HAVE BINARY NUMBER.
	IOR	T1,[OCT 202020200000]	;BACK TO SIXBIT.
	RETURN	ZERO			;TO SENDER...

;HERE TO TAKE THE NUMBER CONTAINED IN T1 AND CONVERT IT TO
;A TWO WORD QUANTITY STORED IN T1 AND T2.

MAKTWO:	SKIPA	P2,[^D10]		;SET RADIX TO TEN.
MAK2:	MOVEI	P2,10			;SET THE RADIX TO EIGHT.
	IDIVI	T1,ZERO(P2)		;SLICE OFF A DIGIT.
	HRLM	T2,ZERO(PDP)		;STORE ON THE STACK.
	JUMPN	T1,.+3			;JUMP IF NOT DONE.
	MOVE	T1,[SIXBIT "000000"]	;STUFF IN LEADING ZEROS.
	SKIPA	T2,T1			;IN BOTH WORDS.
	GOSUB	MAK2+1			;CONTINUE IF NOT DONE.
	HLRZ	T3,ZERO(PDP)		;PICK UP A DIGIT.
	LSHC	T1,6			;MAKE ROOM FOR IT.
	ADDI	T2,'0'(T3)		;CONVERT AND ADD.
	RETURN	ZERO			;BACK TO SENDER.
;HERE WHEN THE GIG IS UP AND THE TRAP HAS SPRUNG.

TRAP:	SAVE	TRPPC			;STACK THE RETURN ADDRESS.
	GOSUB	STORE			;SAVE THE AC'S.
	SAVE	TRPCHN			;SAVE THE CHANNEL AND CLASS BITS.
	GOSUB	TRPSET			;RESET THE TRAP.
	UNSAVE	P3			;GET THE BITS BACK.
	HLRZ	P2,P3			;GET THE CLASS BITS.
	IF.ON	P2,ER.ICC,CTLC		;STOP ON CTRL/C.
	IF.ON	P2,ER.TLX,NOTIME	;JUMP IF TIME RAN OUT.
	IF.ON	P2,ER.ALL		;IF NOT OTHERS THEN
	RETURN	ZERO			;IGNORE THESE PROBLEMS.
	TNO	S,HUNG			;ONLY TYPE IT ONCE.
	IF.ON	S,NO.PRI,TRPCHK		;DON'T TYPE IF FORCED.
TRPTYP:	HRRZS	P3			;SO WE CAN USE AS AN INDEX.
	CAIGE	P3,CF			;SKIP IF CCL FILE.
	GOTO	OTHDEV			;CHECK OTHERS.
	SUBI	P3,CF			;MAKE CHANNEL OFFSET FROM CF.
	IMULI	P3,CCLCNT		;PRODUCE OFFSET FROM CCLBLK.
	MOVEI	T2,CCLBLK(P3)		;PRODUCE PONTER.
	SKIPA				;SKIP INTO GOODNESS.
OTHDEV:	MOVEI	T2,@[EXP OFILE,IFILE,UFDDEV,MFDDEV,DATDEV,HLPDEV]-OF(P3)
	ENABLE	TTY			;CLEAR THE TELETYPE.
	GOSUB	CRLF			;SKIP A LINE.
	EME	.STR,[ASCIZ "% "]	;GIVE WARNING SIGNAL.
	GOSUB	NAMIT			;NAME THE DEVICE.
	IF.OFF	P2,ER.OFL		;SKIP IF UNIT IS ON LINE.
	PRINT	( has dropped off line.);TELL HIM UNIT ISN'T READY.
	IF.OFF	P2,ER.FUL		;SKIP IF UNIT IS NOT FULL.
	PRINT	( is full.)		;SAY UNIT IS NO LONGER WITH US.
	IF.OFF	P2,ER.QEX		;ARE WE GOING OVER QUOTA.
	PRINT	( quota being exceeded.);TELL HIM WE ARE GOING INTO OVERDRAW.
	IF.OFF	P2,ER.IDV		;SKIP IF DEVICE NEEDS NO ACTION.
	PRINT	( is not ready!)	;TELL HIM WHAT IS WRONG.
TRPCHK:	MOVEI	T1,5			;SLEEP TIME.
	MOVE	T2,[XWD 10,^D5000]	;LOAD HIBERNATE ARGS.
	MME	T1,.WAIT		;WAIT AWILE.
	MME	T1,.SLP			;SLEEP IF WAIT FAILS.
	OFF	OF,TTY			;TURN GOING TO TTY OFF.
	GOSUB	CHKOPR			;CHECK FOR A COMMAND.
	MOVE	OF,OFILE+MOD		;FIX THE MOD BITS.
	RETURN	ZERO			;TRY AGAIN.

;HERE WHEN THIS USER'S RUN TIME LIMIT IS ALMOST EXCEEDED.

NOTIME:	XCT	CRLF			;SKIP A LINE.
	PRINT	(***Run time limit almost exceeded)
	GOTO	STOPIT			;SAVE THE FILE.
;HERE TO ENABLE US FOR DEVICE AND APR TRAPS.
;THE TRAPS THAT WE WILL CATCH ARE AS FOLLOWS
;FOR THE APR:
;	PDL OVERFLOW.
;	REFERENCE TO NXM.
;	MEMORY PROTECTION VIOLATION.
;FOR DEVICES:
;	DEVICE NOT READY.
;	QUOTA BEING EXCEEDED ON DISK.
;	DISK UNIT GOING OFF LINE.
;	DISK UNIT BECOMING FULL.

TRPSET:	MOVEI	T1,APRTRP		;APR TRAP LOCATION.
	MOVEM	T1,.JBAPR		;PLACE TO TRAP TO.
	MOVEI	T1,REP!PDL!MPV!NXM	;THINGS TO TRAP ON.
	MME	T1,.ENB			;ENABLE THE TRAPS.
	MOVEI	T1,TRPBLK		;GET POINTER TO BLOCK.
	MOVEM	T1,.JBINT		;SAVE SO EXEC WILL KNOW.
	MOVE	T1,[XWD 4,TRAP]		;BLOCK LENGTH AND TRAP LOC.
	MOVEM	T1,TRPBLK		;SAVE IN BLOCK.
	MOVE	T1,[XWD 400000,ER.ALL]	;DON'T TYPE MESSAGES AND CLASS BITS.
	MOVEM	T1,TRPBLK+1		;SAVE IN BLOCK.
	SETZM	TRPPC			;CLEAR PC WORD TO ALLOW MULTIPLE TRAPS.
	SETZM	TRPCHN			;CLEAR CHANNEL NUMBER.
	RETURN	ZERO			;AWAY...

;HERE FOR AN INPUT ERROR FROM THE LAST INPUT MME.

LKIERR:	IF.ON	T1,E.HAD,HADERR		;JUMP IF HARD DEVICE ERROR.
	IF.ON	T1,E.IOB,BLKERR		;JUMP IF USER ERROR.
	IF.ON	T1,E.LOK		;MAKE SURE THERE IS AN ERROR.
	GOSUB	ABORT			;ELSE NO OTHER REASON TO BE HERE.
	BRANCH	WLDDEV,<DSKERR,IOERR,IOERR,IOERR> ;BRANCH ON DEVICE TYPE.
DSKERR:	MOVEI	P1,[ASCIZ "% "]		;IF IN A WILD CARD RUN.
	IF.ON	IF,WILD			;TEST THE WILD BITS.
	MOVEI	P1,[ASCIZ "? "]		;FATAL ERROR.
	HRRZI	T1,2			;PROTECTION FAILURE CODE.
	HRRM	T1,IFILE+EXT		;SET THE ERROR CODE.
	GOSUB	STORE			;SAVE THE AC'S.
	MOVE	P4,IFILE+MOD		;GET THE MOD BITS.
	OFF	P4,WILD			;TURN OFF WILD BITS.
	MOVEI	SIDE,IFILE		;INDEX TO DATA.
	GOSUB	TYPEIT			;PRINT DEV:NAME.EXT[P,PN].
	IF.OFF	IF,WILD,ERREXT		;JUMP IF FATAL.
	RETURN	ZERO			;ELSE RETURN.
;HERE ON AN APR TRAP. THE TRAPS THAT ARE DETECTED ARE
;PDL OVERFLOW, MEMORY PROTECTION VIOLATION, AND REFERENCES TO
;NON-EXISTENT MEMORY. A MESSAGE IS TYPE TO TELL THE CAUSE
;THE PROBLEM IS CLEARED AND DDT IS CALLED IF IT IS HERE, ELSE
;WE GO TO ABORT. NOTE THE AC'S ARE SAVED IN 'AC'.

APRTRP:	MOVEM	17,AC+17		;SAVE AC 17.
	HRRZI	17,AC			;XWD FOR BLT.
	BLT	17,AC+16		;SAVE THE AC'S.
	ENABLE	TTY			;CLEAR THE TELTYPE.
	MOVE	T1,.JBCNI		;GET THE APR FLAGS.
	IF.OFF	T1,PDL			;SKIP IF NOT PDL OVERFLOW.
	MOVE	PDP,[IOWD TMPLEN,TMPLST];GET A NEW POINTER.
	SAVE	.JBTPC			;SAVE PLACE OF ERROR.
	AOS	ZERO(PDP)		;SO ABORT WILL DO GOOD THINGS.
	XCT	CRLF			;SKIP A LINE.
	IF.OFF	T1,PDL			;WAS IT PDL OVERFLOW.
	EME	.STR,[ASCIZ "***Push-down list overflow"]
	IF.OFF	T1,MPV			;MEMORY PROTECTION VIOLATION.
	EME	.STR,[ASCIZ "***Memory protection violation"]
	IF.OFF	T1,NXM			;REFERENCE TO NON-EXISTENT MEMORY.
	EME	.STR,[ASCIZ "***Non-existent memory referenced"]
	IF.ON	T1,PDL!MPV!NXM		;IF NONE OF THESE REAL BUG.
	GOTO	ABORT1			;SO BUMB.
	EME	.STR,[ASCIZ " at "]	;TELL HIM WHERE.
	MOVE	T2,.JBTPC		;GET THE LOCATION OF THE TRAP.
	JSP	P4,OCTOUT		;PRINT IT.
	XCT	CRLF			;SKIP A LINE.
	MOVEI	T1,REP!PDL!NXM!MPV	;BITS TO REENABLE.
	MME	T1,.ENB			;ENABLE IT AGAIN.
	SKIPE	T1,.JBDDT		;SKIP IF NO DDT.
	GOTO	CALDDT			;ELSE GET IT HERE.
	GOTO	NTHERE			;ELSE START OVER.

	USE	DATA

BSS	TMPLST,TMPLEN			;TEMPORARY STACK.

	USE	CODE
;HERE TO CHECK FOR AN OPERATOR COMMAND WHILE WE ARE RUNNING.

CHKOPR:	IF.ON	OF,TTY			;SKIP IF GOING TO TTY.
	EME	.SKP,ZERO		;SKIP ON INPUT REQUEST.
	RETURN	ZERO			;RETURN IF NOTHING.
	GOSUB	STORE			;SAVE THE AC'S.
	SAVE	S			;SAVE THE STATUS REGISTER.
	MOVE	P1,[XWD -RUNLEN,RUNTAB]	;POINTER TO COMMAND TABLE.
	MOVEI	P2,RUNDIS		;POINTER TO DISPATCH TABLE.
	MOVSI	S,(BAD)			;SO BAD CHARACTERS RETURN.
	SAVE	[OPRRET]		;TO GET BACK HERE.
	GOTO	UNIMAT			;READ THE COMAMND.
OPRRET:	SKIPA	T1,[NOP]		;LOAD A NOP FOR ILLEGAL COMMAND.
	MOVE	T1,[TRZ S,HUNG]		;TO TURN OFF HUNG DEVICE BIT.
	UNSAVE	S			;RESTORE THE STATUS REGISTER.
	XCT	T1			;DO NOTHING OR SOMETHING.
	EME	.CLR,ZERO		;CLEAR THE BUFFERS.
	RETURN	ZERO			;BACK TO CALLER.

;HERE ON A RUNTIME DDT OR DEBUG COMMAND.

RUNDDT:	SKIPN	T1,.JBDDT		;IS DDT LOADED.
	GOTO	BADRUN			;NO...
	GOTO	DDTCAL			;CALL DDT.

;HERE ON A RUNTIME WHAT COMMAND.

RUNWHT:	GOSUB	STAT			;TELL GOOD THINGS.
	SKIPA				;SKIP INTO GOODNESS.
RUNFIL:	GOSUB	CRLF			;SKIP A LINE.
	SETZM	P4			;CLEAR A REGISTER.
	MOVEI	SIDE,OFILE		;POINTER TO THINGS.
	EME	.STR,[ASCIZ "Out= "]	;TELL OUTPUT COMING.
	GOSUB	TYPNAM			;TYPE THE NAME.
	GOSUB	CRLF			;SKIP A LINE.
	MOVEI	SIDE,IFILE		;POINTER TO INPUT THINGS.
	EME	.STR,[ASCIZ "In=  "]	;TELL INPUT COMING.
	GOSUB	TYPNAM			;TYPE THE NAME.
	AOS	ZERO(PDP)		;FOR A SKIP RETURN.
	GOTO	CRLF			;SKIP A LINE AND EXIT.

;HERE ON A RUNTIME PAUSE COMMAND.

PAUSE:	GOSUB	CRLF			;SKIP A LINE.
	EME	.STR,[ASCIZ "***Job halted"]	;TELL WHAT HE DID.
	MME	ONE,.TERM		;STOP...
	RETURN	ONE			;SKIP RETURN.

;HERE ON A LEGAL BUT BAD RUNTIME COMMAND.

BADRUN:	PRINT	(What?)			;COMPLAIN.
	EME	.CH,[EXP 12]		;SKIP A LINE.
	RETURN	ZERO			;RETURN.
;HERE TO GET THE RIGHT CONVERSION TABLES INTO
;CORE.

GETTAB:	SKIPN	DFFLG			;IS DATA FILE OPEN.
	GOSUB	GETTM0			;NO OPEN IT UP.
	HRL	T3,T1			;GET THE INPUT INDEX.
	HRR	T3,T2			;GET THE OUTPUT INDEX.
	CAMN	T3,DFPTR		;SKIP IF NOT THE ONES WE HAVE.
	RETURN	ZERO			;RETURN IF THEY ARE.
	MOVEM	T3,DFPTR		;SAVE FOR NEXT TIME.
	MOVE	T3,FPTR(T1)		;GET BLOCK NUMBER AND WORD COUNT.
	USETI	DF,ZERO(T3)		;SELECT A BLOCK.
	HRRI	T3,TAB1-1		;SET UP IOWD.
	GOSUB	REDTAB			;COPY TABLE INTO CORE.
	MOVE	T3,FPTR(T2)		;GET BLOCK NUMBER AND WORD COUNT.
	USETI	DF,ZERO(T3)		;DIAL A BLOCK.
	HRRI	T3,TAB2-1		;SET UP IOWD.
	GOSUB	REDTAB			;GET THE SECOND TABLE.
TABGEN:	HRLZI	T3,-^D256		;SET LENGTH OF TABLES.
TG0:	HLRZ	CH,TAB1(T3)		;GET A TABLE ENTRY.
	IF.OFF	CH,NEC,TG2		;JUMP IF GOOD CHARACTER.
TG1:	MOVEI	CH,"\"			;GET A BAD CHARACTER.
	HRRZ	CH,TAB2(CH)		;CONVERT TO OUTPUT SET.
	ON	CH,NEC			;NOTE THAT IT IS BAD.
	GOTO	TG3			;SAVE IT.
TG2:	HRRZ	CH,TAB2(CH)		;CONVERT A GOOD CHARACTER.
	IF.ON	CH,NEC,TG1		;JUMP IF A BAD CONVERSION.
TG3:	HRRM	CH,TAB1(T3)		;REPLACE IN FIRST TABLE.
	AOBJN	T3,TG0			;CONTINUE LOOP.
	RETURN	ZERO			;BACK TO CALLER.

;HERE TO READ A CONVERSION TABLE INTO
;CORE.

REDTAB:	MOVEM	T3,CTRL			;SAVE IOWD WORD.
	SETZM	CTRL+1			;SET TERMINATOR.
	DEVOP	IN,DF,CTRL		;READ THE TABLE INTO PLACE.
	RETURN	ZERO			;PERFECT.
	MOVEI	P1,[ASCIZ "? Error reading data file."]
	GOTO	CLEAR			;BOMB OFF.
;HERE TO SET UP THE NAME OF THE FILE THAT HOLDS
;THE CONVERSION FILES.

GETTNM:	SKIPN	T1,IFILE+DEVICE		;IS THERE A DEVICE.
	MOVSI	T1,'DSK'		;NO USE DSK.
	MOVEM	T1,DATDEV+1		;SAVE THE DEVICE.
	SKIPN	T1,IFILE+NAME		;IS THERE A NAME.
	GOTO	NOTAB			;NO SO ERROR.
	MOVEM	T1,DATFIL		;SAVE HIS NAME.
	MOVE	T1,IFILE+EXT		;GET THE EXTENSION.
	MOVEM	T1,DATFIL+1		;SAVE THE EXTENSION.
	MOVE	T1,IFILE+PPN		;GET PPN IF THERE.
	MOVEM	T1,DATFIL+3		;SAVE IT.
	GOSUB	LOOK			;SEE IF FILE IS THERE.
	GOTO	NOTAB			;CAN'T FIND IT.
	GOTO	NTHERE			;START ALL OVER.

;HERE TO SEE IF THE DATA FILE IS AROUND. TRY WHAT EVER
;IS IN THE PARAMETER AREA FIRST AND THEN TRY "DSK:CHANGE.DAT".

GETTM0:	GOSUB	LOOK			;TRY WHAT'S THERE FIRST.
	SKIPA				;NO GOOD.
	RETURN	ZERO			;FOUND IT.
	MOVSI	T3,'DSK'		;TRY DISK.
	MOVEM	T3,DATDEV+1		;SAVE THE DEVICE.
	MOVE	T3,[SIXBIT "CHANGE"]	;TRY "CHANGE.DAT".
	MOVEM	T3,DATFIL		;SAVE THE NAME.
	MOVSI	T3,'DAT'		;GET A DEFAULT EXTENSION.
	MOVEM	T3,DATFIL+1		;SAVE THE EXTENSION.
	SETZM	DATFIL+3		;SPECIFIY THIS PPN.
	GOSUB	LOOK			;SEE IF THERE NOW.
	GOTO	NOTAB			;YOU LOOSE.
	RETURN	ZERO			;MADE IT.
LOOK:	OPEN	DF,DATDEV		;INIT THE DEVICE.
	RETURN	ZERO			;ERROR RETURN.
	LOOKUP	DF,DATFIL		;GET THE FILE.
	RETURN	ZERO			;ERROR RETURN.
	SETZM	DFPTR			;CLEAR POINTER.
	SETOM	DFFLG			;FLAG WE HAVE FILE.
	RETURN	ONE			;BACK TO CALLER.
SUBTTL				*** HELP SUPPLIED HERE ***

COMMENT #
Commands:

DATA		Specifiy the name of the data file to be used as in
		a normal command string "DATA=DEV:FILE.EXT[P,PN]".
MAKE		Call TABLE.SAV to create the conversion tables.
EXIT		Terminate the program.
HELP		This little message.
BYE		Call LOGOUT into core and execute it.
RETAIN		Allows the user to accumulate commands.
RUN		Perform the current command string.
ERASE		Erase retained commands.
PRINT		Print the current command string.

Switches:

Buffers:x	Use x buffers.
Advance:x	Advance x files before operation.
Backspace:x	Backspace the tape x files before operation.
Block:x		Set blocking factor to x.
Record:x	Set record size or size of largest block to x.
Density:arg	Set mag-tape density to arg [arg=200,556,800].
Retain		Retain the following commands.
Run		Perform the current command and retain it.
Help		These few hints.
Label:arg	Set label type as described below for mag-tape.
Mode:arg	Set file character set as described below.
Parity:arg	Set mag-tape parity [odd=odd, even=even, default=odd].
Password:arg	Set the password for GE labels.
Reel:x		Set serial number in labels that have this feature.
* Industry	Initialize for industry compatible 9-channel tape.
* Scan		Scan tape for file named.
* Error		Don't ignore checksum and parity errors.
* Span		Records cross blocks [implied if "/block:0"].
* Rewind:arg	Rewind tapes [arg=before, after, always, omitt]
* Unload	Unload tape after operation.
* Tell		Type file names on a wild card search.
* List		List the device directory.
* Flist		List the device directory [file names only].
* Header	Print headers on the line printer.
* Crlf		Ascii file has crlf's.

Note:	To turn a switch off concatenate "no" with the switch.
	Switches flaged with an (*) have this feature.
/Label - switch modifiers:

None		Mag-tape has no labels just data [default].
Mine		Special labels for DECsystem-10.
Digital		Process labels as standard DIGITAL labels.
Burroughs	Process labels as standard BURROUGHS labels.
IBM		Process labels as standard IBM labels.
GE635		Process labels as standard GE-635 labels.

Note:	Labels are written in the mode specified except for IBM
	and GE-635 labels. IBM labels are written in BCD for
	7-track drives and EBCDIC for 9-track drives. GE-635
	labels are always written in GE-BCD.

/Mode - switch modifiers:

ASCII		File character set is 7-bit ASCII.
HPASCII		File character set is 8-bit ASCII.
GEASCII		File character set is 9-bit ASCII.
IMAGE		File is read and written as 36-bit words.
SIXBIT		File character set is SIXBIT.
FIXSIX		File character set is SIXBIT with no control words.
BCL		File character set is BCL.
BCD		File character set is BCD.
CDC		File character set is cdc bcd.
GEBCD		File character set is GE-BCD.
HONBCD		File character set is HONEYWELL BCD.
EBCDIC		File character set is fixed EBCDIC.
VEBCDIC		File character set is variable EBCDIC.

The end of the input record is determined by the mode of the
input file as described below:

ASCII	Terminated by a carriage-return character or record count.
SIXBIT	Determinted by the header word in front of each record.
FIXSIX	Always copies the number of bytes specified by the record size.
BCL	Always copies the number of bytes specified by the record size.
BCD	Always copies the number of bytes specified by the record size.
EBCDIC	[Fixed] Always copies the number of bytes specified by the
	record size.
EBCDIC	[Variable] Determined by the header word in front of each
	record.

In general all commands may be abbreviated to any number
of characters that will allow that command to be unique. However
no more then six characters are checked for validity in any of
the commands.

The character "*" may be used to denote a wild card for files
on mag-tape, disk, or dectape. The character "@" denotes a
command file which change will read for commands. If only
an altmode is typed change will enter dialog mode.#
;HERE ON A HELP SWITCH OR HELP OR EXPLAIN COMMAND.

SW.H:	MOVE	WD,PRGNAM		;GET THE DEFAULT.
	IF.OFF	S,COL			;JUMP IF NO ARGUMENT.
	GOSUB	GETSIX			;GET A HELP FILE NAME.
	MOVEM	WD,HFILE		;SAVE THE NAME.
HELP1:	IF.ON	S,EOL			;SKIP IF END OF COMMAND.
	GOSUB	GETONE			;SCAN TO END OF LINE.
	IF.OFF	S,EOL,HELP1		;FIND END OF LINE.
	OPEN	HF,HLPDEV		;OPEN THE DEVICE.
	GOTO	NOHELP			;CAN'T PROVIDE HELP.
	LOOKUP	HF,HFILE		;OPEN THE FILE.
	GOTO	NOHELP			;CAN'T PROVIDE HELP.
	MOVE	T1,.JBFF		;GET FIRST FREE.
	SUBI	T1,ONE			;TO SET UP IOWD.
	HRRM	T1,HFCTL		;SET CTRL WORD.
	ADDI	T1,201			;LAST LOCATION NEEDED.
	IORI	T1,1777			;TO A K BOUNDARY.
	CAMG	T1,.JBREL		;SKIP IF NEED MORE CORE.
	GOTO	.+3			;O.K. LIKE IT IS.
	MME	T1,.CORE		;GET MORE CORE.
	GOTO	NOCORE			;NO CORE YOU LOOSE.
	GOSUB	CRLF			;SKIP A LINE.
HELP2:	DEVOP	IN,HF,HFCTL		;READ A BLOCK.
	GOTO	HELP3			;CONTINUE ON.
	GETSTS	HF,T1			;GET THE DEVICE STATUS.
	IF.OFF	T1,E.ERR!E.EOF,HELP3	;JUMP IF NO ERROR.
	GOTO	NTHERE			;ON ANY ERROR CALL IT EOF.
HELP3:	HRRZ	T1,HFCTL		;GET POINTER TO BUFFER.
	SETZM	201(T1)			;FOR ASCIZ.
	EME	.STR,ONE(T1)		;SEND THE BUFFER.
	GOTO	HELP2			;CONTINUE ON.

	EXP	HF
HLPDEV:	EXP	DMP
	SIXBIT	"SYS"
	BSS	ONE

	USE	DATA

HFILE:	SIXBIT	"NAME"
	SIXBIT	"HLP"
	BSS	4
HFCTL:	IOWD	200,ZERO
	BSS	ONE

	USE	CODE
SUBTTL			*** TABLES ***

CH.CHR:	XWD	"@",ATS!SOM			;DELIMITER TABLE.
	XWD	":",COL!SOM
	XWD	".",PER!SOM
	XWD	"[",BRK!SOM
	XWD	"/",SLH!SOM
	XWD	"_",IO!SOM
	XWD	"=",IO!SOM
	XWD	15,EOL!SOM
	XWD	33,EOL!SPC!ALT!SOM
	XWD	175,EOL!SPC!ALT!SOM
	XWD	176,EOL!SPC!ALT!SOM
CH.CNT==.-CH.CHR

COMTAB:	<SIXBIT	"MAKE">				;COMMAND TABLE.
	<SIXBIT	"DIALOG">
	<SIXBIT	"TERMINATE">
	<SIXBIT	"BYE">
	<SIXBIT	"EXIT">
	<SIXBIT	"DDT">
	<SIXBIT	"DEBUGGER">
	<SIXBIT	"HELP">
	<SIXBIT	"EXPLAIN">
	<SIXBIT	"RETAIN">
	<SIXBIT	"ERASE">
	<SIXBIT	"RUN">
	<SIXBIT	"PERFORM">
	<SIXBIT	"PRINT">
COMCNT==.-COMTAB

COMDIS:	XWD	ZERO,CRETAB			;COMMAND DISPATCH TABLE.
	XWD	ZERO,DIALOG
	XWD	ZERO,STOP
	XWD	ZERO,LOGOFF
	XWD	ZERO,STOP
	XWD	ZERO,DEBUG
	XWD	ZERO,DEBUG
	XWD	ZERO,SW.H
	XWD	ZERO,SW.H
	XWD	ZERO,RETAIN
	XWD	ZERO,ERASE
	XWD	ZERO,PERFOR
	XWD	ZERO,PERFOR
	XWD	ZERO,XPRINT
	XWD	ZERO,NOTCOM
M.TAB:	<SIXBIT	"ASCII">			;TABLE TO SET CONVERSION INDEX.
	<SIXBIT	"HPASCII">
	<SIXBIT	"GEASCII">
	<SIXBIT	"IMAGE">
	<SIXBIT	"OCTAL">
	<SIXBIT	"SIXBIT">
	<SIXBIT	"FIXSIX">
	<SIXBIT	"BCL">
	<SIXBIT	"BCD">
	<SIXBIT	"CDC">
	<SIXBIT	"GEBCD">
	<SIXBIT	"HONBCD">
	<SIXBIT	"EBCDIC">
	<SIXBIT	"COBEBC">
	<SIXBIT	"VEBCDIC">
M.CNT==.-M.TAB

M.DIS:	XWD	ZERO,M.RET			;DISPATCH TABLE FOR MODE.
	XWD	ZERO,FOMERR

NWUTAB:	XWD	ZERO,NOHEAD			;BITS FOR SWITCHES.
	XWD	ZERO,NOCRLF
	XWD	ZERO,UNLOAD
	XWD	ZERO,IND
	XWD	ZERO,NOERROR
	XWD	ZERO,SPAN
	XWD	ZERO,SCAN
NWUCNT==.-NWUTAB

LB.TAB:	<SIXBIT	"NONE">				;LABEL TYPE TABLE.
	<SIXBIT	"MINE">
	<SIXBIT	"BURROUGHS">
	<SIXBIT	"DIGITAL">
	<SIXBIT	"DEC">
	<SIXBIT	"IBM">
	<SIXBIT	"GE635">
LB.CNT==.-LB.TAB

LB.DIS:	XWD	ZERO,L.RET			;DISPATCH FOR LABELS.
	XWD	ZERO,FOMERR

LB.TYP:	XWD	RET0,LB.NON			;LABEL DISPATCH TABLE.
	XWD	LB.OMI,LB.IMI
	XWD	LB.OBL,LB.IBL
	XWD	LB.OCL,LB.ICL
	XWD	LB.OCL,LB.ICL
	XWD	LB.OBM,LB.IBM
	XWD	LB.OGE,LB.IGE
SW.TAB:	<SIXBIT	"NOHEADER">			;SWITCH TABLE.
	<SIXBIT	"NOCRLF">
	<SIXBIT	"UNLOAD">
	<SIXBIT	"INDUSTRY">
	<SIXBIT	"NOERROR">
	<SIXBIT	"SPAN">
	<SIXBIT	"SCAN">
	<SIXBIT	"HEADER">
	<SIXBIT	"CRLF">
	<SIXBIT	"NOUNLOAD">
	<SIXBIT	"NOINDUSTRY">
	<SIXBIT	"ERROR">
	<SIXBIT	"NOSPAN">
	<SIXBIT	"NOSCAN">
	<SIXBIT	"DENSITY">
	<SIXBIT	"LABEL">
	<SIXBIT	"MODE">
	<SIXBIT	"BLOCK">
	<SIXBIT	"BLKSIZE">
	<SIXBIT	"PARITY">
	<SIXBIT	"ADVANCE">
	<SIXBIT	"HELP">
	<SIXBIT	"RECORD">
	<SIXBIT	"REC">
	<SIXBIT	"RECSIZE">
	<SIXBIT	"REEL">
	<SIXBIT	"PASSWORD">
	<SIXBIT	"RETAIN">
	<SIXBIT	"RUN">
	<SIXBIT	"PERFORM">
	<SIXBIT	"EXPLAIN">
	<SIXBIT	"BUFFERS">
	<SIXBIT	"LIST">
	<SIXBIT	"NOLIST">
	<SIXBIT	"FLIST">
	<SIXBIT	"TELL">
	<SIXBIT	"NOTELL">
	<SIXBIT	"REWIND">
	<SIXBIT	"NOREWIND">
	<SIXBIT	"BACKSPACE">
SW.CNT==.-SW.TAB
SW.DIS:	XWD	ZERO,SW.NWU			;DISPATCH TABLE FOR SWITCHES.
	XWD	ZERO,SW.NWU
	XWD	ZERO,SW.NWU
	XWD	ZERO,SW.NWU
	XWD	ZERO,SW.NWU
	XWD	ZERO,SW.NWU
	XWD	ZERO,SW.NWU
	XWD	ZERO,SW.OFF
	XWD	ZERO,SW.OFF
	XWD	ZERO,SW.OFF
	XWD	ZERO,SW.OFF
	XWD	ZERO,SW.OFF
	XWD	ZERO,SW.OFF
	XWD	ZERO,SW.OFF
	XWD	ZERO,SW.D
	XWD	ZERO,SW.L
	XWD	ZERO,SW.M
	XWD	ZERO,SW.B
	XWD	ZERO,SW.B
	XWD	ZERO,SW.P
	XWD	ZERO,SW.A
	XWD	ZERO,SW.H
	XWD	ZERO,SW.R
	XWD	ZERO,SW.R
	XWD	ZERO,SW.R
	XWD	ZERO,SW.RL
	XWD	ZERO,SW.PW
	XWD	ZERO,SW.KEP
	XWD	ZERO,SW.GO
	XWD	ZERO,SW.GO
	XWD	ZERO,SW.H
	XWD	ZERO,SW.BUF
	XWD	ZERO,XLST
	XWD	ZERO,XNLST
	XWD	ZERO,XFLST
	XWD	ZERO,XTELL
	XWD	ZERO,XNTELL
	XWD	ZERO,REWIND
	XWD	ZERO,NOREW
	XWD	ZERO,SW.BK
	XWD	ZERO,IMPSW
REWTAB:	<SIXBIT	"AFTER">			;REWIND SWITCH ARGUMENTS.
	<SIXBIT	"BEFORE">
	<SIXBIT	"ALWAYS">
	<SIXBIT	"OMITT">
REWCNT==.-REWTAB

REWDIS:	XWD	ZERO,REWRET			;DISPATCH TABLE FOR REWIND.
	XWD	ZERO,FOMERR

NORDIS:	XWD	ZERO,NOWRET			;DISPATCH TABLE FOR NOWIND.
	XWD	ZERO,FOMERR

REWBIT:	XWD	ZERO,AWIND			;BITS FOR REWIND OR NOWIND.
	XWD	ZERO,BWIND
	XWD	ZERO,AWIND!BWIND
	XWD	ZERO,AWIND!BWIND

PR.TAB:	<SIXBIT	"ODD">				;PARITY TABLE.
	<SIXBIT	"EVEN">
PR.CNT==.-PR.TAB

PR.DIS:	XWD	ZERO,ODDRET			;DISPATCH FOR PARITY.
	XWD	ZERO,EVERET
	XWD	ZERO,FOMERR

DN.TAB:	<SIXBIT	"200">				;DENSITY TABLE.
	<SIXBIT	"556">
	<SIXBIT	"800">
DN.CNT==.-DN.TAB

DN.DIS:	XWD	ZERO,D.RET			;DISPATCH TABLE FOR DENSITY.
	XWD	ZERO,FOMERR
E.TAB:	<SIXBIT	"DATA">				;COMMANDS THAT USE = OR _.
E.CNT=.-E.TAB

E.DIS:	XWD	ZERO,E.RET			;DISPATCH TABLE FOR SPECIALS.
	XWD	ZERO,GETWOD

E.BIT:	EXP	DATA				;BITS TO SET FOR SPECIALS.

RUNTAB:	<SIXBIT	"DDT">				;RUNTIME COMMANDS.
	<SIXBIT	"DEBUGGER">
	<SIXBIT	"WHAT">
	<SIXBIT	"FILES">
	<SIXBIT	"STOP">
	<SIXBIT	"PAUSE">
RUNLEN==.-RUNTAB

RUNDIS:	XWD	ZERO,RUNDDT			;RUNTIME DISPATCH TABLE.
	XWD	ZERO,RUNDDT
	XWD	ZERO,RUNWHT
	XWD	ZERO,RUNFIL
	XWD	ZERO,STOPIT
	XWD	ZERO,PAUSE
	XWD	ZERO,BADRUN
	USE	DATA

BSS	TAB1,^D256				;CONVERSION TABLES.
BSS	TAB2,^D256
BSS	CTRL,TWO				;I/O LIST FOR DATA FILE.
BSS	IVBCNT,ONE				;EBCDIC BLOCK COUNT.
BSS	OSIZE,ONE				;SIZE OF OUTPUT RCORD.
BSS	OBSIZE,ONE				;SIZE OF OUTPUT BLOCK.
BSS	OT0TMP,ONE				;WORD FOR OCTAL.
BSS	OT1TMP,ONE				;LINE COUNT FOR OCTAL.

BSS	DFPTR,ONE				;INDEX POINTERS FOR TABLES.
BSS	DFFLG,ONE				;NON-ZERO IF DATA FILE IS OPEN.
	EXP	DF				;CHANNEL NUMBER.
DATDEV:	XWD	ZERO,DMP			;DEVICE FOR DATA FILE.
	SIXBIT	"PUB"
	BSS	ONE
DATFIL:	SIXBIT	"CHANGE"			;NAME OF DATA FILE.
	SIXBIT	"DAT"
	BSS	TWO

DMPDEV:	XWD	ZERO,DMP			;DUMP OF US TO DISK.
	SIXBIT	"DSK"				;ON DEVICE DISK.
	BSS	ONE
DMPFIL:	SIXBIT	"NAME"				;NAME TO DUMP TO.
	SIXBIT	"DMP"
	BSS	TWO
DMPLST:	IOWD	SYSNAM+4-AC,AC
	XWD	ZERO,136
	BSS	ONE

	USE	CODE

LOGPRG:	SIXBIT	"SYS"				;FOR RUN ON LOGOUT.
	SIXBIT	"LOGOUT"
	BSS	4

YESTAB:	<SIXBIT	"YES">				;USED FOR YES NO REPLIES.
	<SIXBIT	"NO">
YESCNT==.-YESTAB

YESDIS:	XWD	ZERO,YESRET			;RETURNS FOR YES NO REPLIES.
	XWD	ZERO,NORET
	XWD	ZERO,XYNRET
;TABLE OF MESSAGES THAT ARE PUT ON THE TRAILING
;HEADER.

ENDTAB:	[SIXBIT	"END         "]
	[SIXBIT	"FINIS       "]
	[SIXBIT	"TERMINUS    "]
	[SIXBIT	"CEASE       "]
	[SIXBIT	"HALT        "]
	[SIXBIT	"STOP        "]
	[SIXBIT	"CLOSE       "]
	[SIXBIT	"CONCLUDE    "]
	[SIXBIT	"ARREST      "]
	[SIXBIT	"CHECKMATE   "]
	[SIXBIT	"TERMINATE   "]
	[SIXBIT	"DIE         "]
	[SIXBIT	"COOL_IT     "]
	[SIXBIT	"REST        "]
	[SIXBIT	"CRASH       "]
	[SIXBIT	"THE_END     "]
	[SIXBIT	"STOP_THE_CPU"]
	[SIXBIT	"BREAK       "]
	[SIXBIT	"STOP_CODE   "]
	[SIXBIT	"RIGHT_ON    "]
	[SIXBIT	"TRASH       "]
ENDCNT==.-ENDTAB

;CHARACTER TABLE FOR LINE PRINTER HEADINGS.

CHRTAB:	BYTE (5) 00,00,00,00,00,00,00		; SP
	BYTE (5) 04,04,04,04,04,00,04		; !
	BYTE (5) 12,12,00,00,00,00,00		; "
	BYTE (5) 12,12,37,12,37,12,12		; #
	BYTE (5) 04,37,24,37,05,37,04		; $
	BYTE (5) 31,31,02,04,10,23,23		; %
	BYTE (5) 10,24,10,24,23,22,15		; &
	BYTE (5) 06,02,00,00,00,00,00		; '
	BYTE (5) 04,10,20,20,20,10,04		; (
	BYTE (5) 04,02,01,01,01,02,04		; )
	BYTE (5) 00,25,16,33,16,25,00		; *
	BYTE (5) 00,04,04,37,04,04,00		; +
	BYTE (5) 00,00,00,00,00,14,04		; ,
	BYTE (5) 00,00,00,37,00,00,00		; -
	BYTE (5) 00,00,00,00,00,14,14		; .
	BYTE (5) 00,00,01,02,04,10,20		; /
	BYTE (5) 16,21,23,25,31,21,16		; 0
	BYTE (5) 04,14,04,04,04,04,16		; 1
	BYTE (5) 16,21,01,02,04,10,37		; 2
	BYTE (5) 16,21,01,02,01,21,16		; 3
	BYTE (5) 22,22,22,37,02,02,02		; 4
	BYTE (5) 37,20,34,01,01,21,16		; 5
	BYTE (5) 16,20,20,36,21,21,16		; 6
	BYTE (5) 37,01,01,02,04,10,20		; 7
	BYTE (5) 16,21,21,16,21,21,16		; 8
	BYTE (5) 16,21,21,17,01,01,16		; 9
	BYTE (5) 00,06,06,00,06,06,00		; :
	BYTE (5) 00,06,06,00,06,06,02		; ;
	BYTE (5) 02,04,10,20,10,04,02		; <
	BYTE (5) 00,00,37,00,37,00,00		; =
	BYTE (5) 10,04,02,01,02,04,10		; >
	BYTE (5) 16,21,01,02,04,00,04		; ?
	BYTE (5) 16,21,21,27,25,25,07		; @
	BYTE (5) 16,21,21,21,37,21,21		; A
	BYTE (5) 36,21,21,36,21,21,36		; B
	BYTE (5) 17,20,20,20,20,20,17		; C
	BYTE (5) 36,21,21,21,21,21,36		; D
	BYTE (5) 37,20,20,36,20,20,37		; E
	BYTE (5) 37,20,20,36,20,20,20		; F
	BYTE (5) 17,20,20,20,27,21,16		; G
	BYTE (5) 21,21,21,37,21,21,21		; H
	BYTE (5) 16,04,04,04,04,04,16		; I
	BYTE (5) 01,01,01,01,21,21,16		; J
	BYTE (5) 21,21,22,34,22,21,21		; K
	BYTE (5) 20,20,20,20,20,20,37		; L
	BYTE (5) 21,33,25,21,21,21,21		; M
	BYTE (5) 21,21,31,25,23,21,21		; N
	BYTE (5) 16,21,21,21,21,21,16		; O
	BYTE (5) 36,21,21,36,20,20,20		; P
	BYTE (5) 16,21,21,21,25,22,15		; Q
	BYTE (5) 36,21,21,36,24,22,21		; R
	BYTE (5) 17,20,20,16,01,01,36		; S
	BYTE (5) 37,04,04,04,04,04,04		; T
	BYTE (5) 21,21,21,21,21,21,37		; U
	BYTE (5) 21,21,21,21,21,12,04		; V
	BYTE (5) 21,21,21,21,25,33,21		; W
	BYTE (5) 21,21,12,04,12,21,21		; X
	BYTE (5) 21,21,12,04,04,04,04		; Y
	BYTE (5) 37,01,02,04,10,20,37		; Z
	BYTE (5) 14,10,10,10,10,10,14		; [
	BYTE (5) 00,00,20,10,04,02,01		; \
	BYTE (5) 06,02,02,02,02,02,06		; ]
	BYTE (5) 00,04,16,25,04,04,00		; ^
	BYTE (5) 00,00,00,00,00,00,00		; SPACE USED IN MESSAGES.
;THE FOLLOWING TABLES ARE FOR THE CHARACTER SET MODES.
;THE MACRO "MTABLE" WILL SET UP THE POINTERS TO THE MODE
;DATA BLOCKS. WHILE THE MACRO "TABLE" WILL SET UP ALL THE
;DATA ABOUT A CERTIAN CHARACTER SET.

	FTABLE	-123456				;MUST BE BEFORE WHAT FOLLOWS.

MTABLE	<ASC,HPA,GEA,IMG,OCT,SIX,FIX,BCL,BCD,CDC,XBD,HBD,EBC,CEB,VEB>
TABLE	ASCII,ASC,7,128,NOR!TAB
TABLE	HPASCII,HPA,8,0,NOR!TAB
TABLE	GEASCII,GEA,9,0,NOR!TAB
TABLE	IMAGE,IMG,36,0,0
TABLE	OCTAL,OCT,7,0,0
TABLE	SIXBIT,SIX,6,64,NOR!6
TABLE	FIXSIX,FIX,6,0,NOR!NIR
TABLE	BCL,BCL,6,64,NOR!NIR
TABLE	BCD,BCD,6,64,NOR!NIR
TABLE	CDC,CDC,6,64,NOR!NIR
TABLE	GEBCD,XBD,6,64,NOR!NIR
TABLE	HONBCD,HBD,6,64,NOR!NIR
TABLE	EBCDIC,EBC,8,256,NOR!NIR!TAB
TABLE	COBEBC,CEB,9,0,NOR!EXW!TAB!4
TABLE	VEBCDIC,VEB,8,0,NOR!EXW!TAB!4

	END	START