;MACRO SIDE OF IMP LIBRARY INVOLVING I/O
;  K.FARVIS  UNIV. OF EDINBURGH 24TH AUG '76

TITLE	NEXTSYMBOL %INTEGERFN NEXTSYMBOL
	ENTRY	NEXTSYMBOL
	EXTERN	INSCB
	SEARCH	IMPPRM

NEXTSYMBOL: MOVE	IOREG,INSCB
	SKIPE	AC,NXTCHR(IOREG)	;IS THERE A CHAR PENDING
	POPJ	P,			;YES, RETURN IT
	JSP	J,@OPER(IOREG)		;NO, GO TO APPROPRIATE READ ROUTINE
	MOVEM	AC,NXTCHR(IOREG)	;SAVE IT, AND RETURN IT
	POPJ	P,
	PRGEND

TITLE	READSYMBOL %ROUTINE READSYMBOL(%INTEGERNAME S)
	ENTRY	READSYMBOL
	EXTERN	INSCB
	SEARCH	IMPPRM

READSYMBOL: MOVE	IOREG,INSCB
	SKIPN	AC,NXTCHR(IOREG)	;IS THERE A CHAR PENDING?
	JSP	J,@OPER(IOREG)		;NO, GET ONE
	MOVEM	AC,(ARG1)		;RETURN ARGUMENT FOR RSYM
	SKIPGE	FLAGS(IOREG)
	ANDCAM T1,FLAGS(IOREG)	;CLEAR ZERO SYMBOL FLAG FOR BINARY
	SETZM	NXTCHR(IOREG)		;CLEAR PENDING SYMBOL
	POPJ	P,			;AND RETURN
	PRGEND

TITLE	NEXTITEM %STRING(1)%FN NEXTITEM
	ENTRY	NEXTITEM
	EXTERN	INSCB
	SEARCH	IMPPRM

NEXTITEM: MOVE	IOREG,INSCB
	SKIPE	AC,NXTCHR(IOREG)	;A CHAR PENDING
	  JRST	ITRTN			;YES, RETURN IT
	JSP	J,@OPER(IOREG)		;GET ONE
	MOVEM	AC,NXTCHR(IOREG)	;STORE IT
ITRTN:	IORI	AC,1000			;ADD LENGTH
	HRLZM	AC,NI			;STORE IT
	MOVEI	AC1,NI
	POPJ	P,			; RETURN

NI:	Z

	PRGEND

TITLE	READITEM %ROUTINE READ ITEM(%STRINGNAME S)
	ENTRY	READITEM
	EXTERN	INSCB
	SEARCH	IMPPRM

READITEM: MOVE	IOREG,INSCB
	SKIPN	AC,NXTCHR(IOREG)	;IS THERE A CHAR PENDING
	JSP	J,@OPER(IOREG)
	SKIPGE	FLAGS(IOREG)
	ANDCAM T1,FLAGS(IOREG)  ;CLEAR ZERO SYMBOL FLAG
	SETZM	NXTCHR(IOREG)		;CLEAR PENDING CHAR
	IORI	AC,1000			;PUT IN STRING LENGTH
	HRLZM	AC,(ARG1)		;AND PUT TO TOP OF WORD
	POPJ	P,
	PRGEND



TITLE	SKIPSYMBOL %ROUTINE SKIPSYMBOL
	ENTRY	SKIPSYMBOL
	EXTERN	INSCB
	SEARCH	IMPPRM

SKIPSYMBOL: MOVE	IOREG,INSCB
	SKIPN	AC,NXTCHR(IOREG)	;IS THERE A CHAR PENDING?
	JSP	J,@OPER(IOREG)		;NO, GET ONE
	SKIPGE	FLAGS(IOREG)
	ANDCAM T1,FLAGS(IOREG)	;CLEAR ZERO SYMBOL FLAG
	SETZM	NXTCHR(IOREG)		;AND CLEAR IT
	POPJ	P,			;AND RETURN
	PRGEND


TITLE	PRINTSYMBOL %ROUTINE PRINTSYMBOL
; %ROUTINE NEWPAGE
; %ROUTINE NEWLINE
; %ROUTINE SPACE
; %ROUTINE PRINTSYMBOL(%INTEGER S)
	ENTRY	NEWPAGE,NEWLINE,SPACE,PRINTSYMBOL
	EXTERN	OUTSCB
	SEARCH	IMPPRM

NEWPAGE: MOVEI	ARG1,15
	PUSHJ	P,PRINTSYMBOL
	MOVEI	ARG1,14
	PJRST	PRINTSYMBOL

NEWLINE: MOVEI	ARG1,15
	PUSHJ	P,PRINTSYMBOL
	MOVEI	ARG1,12
	PJRST	PRINTSYMBOL

SPACE:	MOVEI	ARG1," "
PRINTSYMBOL:	MOVE	IOREG,OUTSCB
	PJRST	@OPER(IOREG)		;JUMP TO OUTPUT ROUTINE AND RETURN
	PRGEND

TITLE	PSTR %ROUTINE PRINTSTRING(%STRING(255) STR)

	ENTRY	PSTR
	EXTERN	OUTSCB,WTTTYI,WTTTYA,WTTY
	EXTERN	OERRT
	SEARCH	IMPPRM


PSTR:	LDB	T4,IMPSPTR	;GET LENGTH OF STRING
	SKIPG	T4		;IS IT NULL
	POPJ	P,		;YES JUST RETURN
	MOVE	T1,IMPSPTR	;GET THE STRING POINTER
	MOVE	IOREG,OUTSCB	;AND OUTPUT SCB
	MOVE	T2,OPER(IOREG)	;GET THE OUTPUT ROUTINE
	CAIE	T2,WTTY		;IS IT OUR TTY?
	CAIN	T2,WTTTYA	;IS IT TRMOP TYPE?
	JRST	TTYSTR		;YES
PSTRLP:	ILDB	ARG1,T1		;NO, GET A CHAR
	PUSHJ	P,@OPER(IOREG)	;OUTPUT IT
	SOJG	T4,PSTRLP	;CONTINUE
	POPJ	P,		;AND RETURN WHEN FINISHED

TTYSTR:	MOVE	T2,[POINT 7,1(P)];GET A POINTER TO AN ASCII STRING BASE
	MOVEM	T2,ASCPTR	;AND SAVE
	MOVEI	T5,15		;LOAD A CR FOR LATER
TTSTLP:	ILDB	T2,T1		;GET AN IMP CHAR
	CAIN	T2,12		;IS IT LF
	IDPB	T5,ASCPTR	;YES, OUTPUT A CR FIRST
	IDPB	T2,ASCPTR	;DEPOSIT ASCII CHAR
	SOJG	T4,TTSTLP	;AND CONTINUE
	IDPB	T4,ASCPTR	;AND A ZERO FINALLY
	MOVE	T2,OPER(IOREG)	;GET OPERATION
	CAIE	T2,WTTTYA	;IS IT OUR OWN CONSOLE
	JRST	[OUTSTR	1(P)	;YES, OUTPUT IT
		POPJ	P,]	;AND RETURN
	MOVEI	T1,7		;GET OUTSTRING FUNCT CODE
	EXCH	T1,FUNCT(IOREG);EXCHANGE FUNCTIONS
	MOVEI	T2,1(P)		;GET ARG ADDR
	MOVEM	T2,OUTARG(IOREG); PLACE ADDRESS IN ARG
	MOVE	T2,ARGPTR(IOREG); GET ARG POINTER
	TRMOP.	T2,		;DO IT
	  JRST	ERR		;FAILED
	MOVEM	T1,FUNCT(IOREG)	;RESTORE FUNCT CODE
	POPJ	P,		;RETURN OK

ERR:	MOVEM	T1,FUNCT(IOREG)	;RESTORE FUNCTION CODE
	JRST	OERRT

IMPSPTR:POINT	9,(AC),8
ASCPTR:	0
	LIT
	PRGEND



TITLE	RDDUMP %SYSTEMROUTINE RDDUMP(%RECORD(SCB)%NAME S, %INTEGER LENGTH, %NAME  LOC)
	ENTRY	$RDDUMP
	EXTERN	DINERR,DMPEOF
	SEARCH	IMPPRM

$RDDUMP:	MOVN	0,ARG2		;CONSTRUCT IOWD IN AC0
	HRLZ	0,0
	IORI	0,-1(ARG3)
	SETZM	1		;0=[IOWD LEN,BUF], 1=[0]
	XCT	0,IBUFOP(ARG1)	;DO IT
	  POPJ	P,		;RETURN
	MOVE	IOREG,ARG1	;SAVE ADDR OF SCB IN IOREG
	MOVE	AC,FLAGS(IOREG)
	ANDI	AC,17		;GET DA/SQ CHANNEL NUMBER
	XCT	0,STATZ(ARG1)
	JRST	DINERR
	JRST	DMPEOF
	PRGEND

TITLE	WTDUMP %SYSTEMROUTINE WTDUMP(%RECORD(SCB)%NAME S, %INTEGER LENGTH, %NAME LOC)
	ENTRY	$WTDUMP
	EXTERN	DOUTERR
	SEARCH	IMPPRM

$WTDUMP:	MOVN	0,ARG2		;CONSTRUCT IOWD IN AC0
	HRLZ	0,0
	IORI	0,-1(ARG3)
	SETZM	1		;0=[IOWD LEN,BUF] 1 =[ 0 ]
	XCT	0,OBUFOP(ARG1)	;DO IT
	  POPJ	P,
	MOVE	IOREG,ARG1	;SAVE ADDR OF SCB IN IOREG
	MOVE	AC,FLAGS(IOREG)
	ANDI	AC,17		;GET DA/SQ CHANNEL NUMBER
	JRST	DOUTERR
	PRGEND

TITLE INOUT GENERAL INPUT/OUTPUT ROUTINES
	ENTRY	ITYSCB,OTYSCB
	ENTRY	IUNSCB,OUNSCB
	ENTRY	RDTTYA,RDTTYI
	ENTRY	WTTY,WTTTYA,WTTTYI
	ENTRY	RDA,RDB
	ENTRY	WTA,WTB
	ENTRY	$INPUT,$OUTPUT
	ENTRY	RDTMP,WTTMP
	ENTRY	RDST,WTST
	ENTRY	DMPEOF,DINERR,DOUTERR
	ENTRY	EOF,INERR,OUTERR,IERRT,OERRT,$INTST,$OUTTST

	EXTERN	ERRMSG
	EXTERN	$GETSTS
	EXTERN	INSCB,OUTSCB
	SEARCH	IMPPRM

;USER CONSOLE TELETYPE INPUT
RDTY:	TTCALL	4,AC
	CAIN	AC,15
	JRST	RDTY		;THROW AWAY CR
	JRST	(J)


;OTHER TELETYPE INPUT

RDTTYA:	MOVE	AC,ARGPTR(IOREG)
	TRMOP.	AC,
	  JRST IERRT
	CAIN	AC,15
	JRST	RDTTYA		;THROW AWAY CR
	JRST	(J)



;IMAGE READ
RDTTYI:	MOVE	AC,ARGPTR(IOREG)
	TRMOP.	AC,
	  JRST IERRT
	JRST	(J)


; ROUTINE FOR ASCII INPUT

RDA:	SOSGE	0,BYTCNT(IOREG)
	JRST	RDNOK	
	ILDB	AC,BYTPTR(IOREG)
	JUMPE	AC,RDA		;THROW AWAY NULLS
	CAIN	AC,15		;IS IT A CR
	JRST	RDA		;YES THROW AWAY
	JRST	(J)	;RETURN

RDNOK:	XCT	0,IBUFOP(IOREG)	;DO AN IN CHAN,0
	JRST	RDA
	JRST	$INTST		;AN ERROR, EOF ETC

;ROUTINE FOR BINARY

RDB:	MOVSI	T1,400000	;SET BIT 0 FOR TESTING FOR ZERO SYMBOL
	SKIPGE	FLAGS(IOREG)	;IS THE ZERO SYMBOL PENDING BIT SET(BIT 0)
	JRST	(J)		;YES RETURN ZERO
RDB01:	SOSGE	0,BYTCNT(IOREG)
	JRST	RDBNOK
	ILDB	AC,BYTPTR(IOREG)
	SKIPN	AC		;IS IT ZERO
	IORM	T1,FLAGS(IOREG)	;YES, NOTE IT
	JRST	(J)	; AND RETURN

RDBNOK:	XCT	0,IBUFOP(IOREG)
	JRST	RDB01
	JRST	$INTST

;INPUT AND OUTPUT

$OUTPUT: MOVE	IOREG,OUTSCB
	SKIPL	AC1,DEVTYP(IOREG)
	CAIN	AC1,TTYDEV
	POPJ	P,		;RETURN IF DEVICE IS TTY OR NULL
	XCT	OBUFOP(IOREG)	;OUT UUO
	POPJ	P,
	JRST	$OUTTST		;ERROR

$INPUT:	MOVE	IOREG,INSCB
	SKIPL	AC1,DEVTYP(IOREG)
	CAIN	AC1,TTYDEV
	POPJ	P,		;RETURN IF DEVICE IS TTY OR NULL
	XCT	IBUFOP(IOREG)	;IN UUO
	POPJ	P,
	JRST	$INTST		;EOF OR ERROR
	SUBTTL OUTPUT ROUTINES

;ALL THESE ROUTINES USE ARG1 FOR THEIR ARGUMENT AND USE THE STACK FOR RETURNING.

;USERS CONSOLE TELETYPE OUTPUT

WTTY:	CAIN	ARG1,12
	PJRST	WTYNL
	TTCALL 1,ARG1
	POPJ	P,
WTYNL:
	MOVEI	ARG1,15
	TTCALL	1,ARG1		;OUTPUT CR BEFORE LF
	MOVEI	ARG1,12
	TTCALL	1,ARG1
	POPJ	P,

;OTHER TTY OUTPUT


WTTNL:	MOVEI	ARG1,15		;TO OUTPUT A NEWLINE TO A TERMINAL
	PUSHJ	P,WTTTYI
	MOVEI	ARG1,12
	PJRST	WTTTYI


WTTTYA:	CAIN	ARG1,12
	PJRST	WTTNL		;WRITE A NEWLINE
				;ELSE JUST DROP THROUGH

WTTTYI:	MOVEM	ARG1,OUTARG(IOREG)
	MOVE	ARG1,ARGPTR(IOREG)
	TRMOP.	ARG1,
	  JRST	OERRT
	POPJ	P,


;ROUTINE TO WRITE ASCII

WTANL:	MOVEI	ARG1,15		;OUTPUT A CR
	PUSHJ	P,WTB
	MOVEI	ARG1,12		;AND THEN THE LF
	PJRST	WTB		;AND PRINT

WTA:	CAIN	ARG1,12		;IS IT A LF
	PJRST	WTANL		;YES, OUTPUT A CR-LF
				;NO, JUST DROP THROUGH


;BINARY OUTPUT ROUTINE

WTB:	SOSGE	0,BYTCNT(IOREG)
	JRST	WTNOK
	IDPB	ARG1,BYTPTR(IOREG)
	POPJ	P,
WTNOK:
	XCT	0,OBUFOP(IOREG)
	JRST	WTB
	JRST	$OUTTST


SUBTTL	TMPCOR READ AND WRITE ROUTINES


;READ ROUTINE FOR TMPCOR

RDTMP:	SOSGE	0,BYTCNT(IOREG)
	JRST	EOF	;END OF FILE
	ILDB	AC,BYTPTR(IOREG)
	JUMPE	AC,EOF		;NULLS MEAN EOF
	CAIN	AC,15		;IS IT A CR
	JRST	RDTMP		;YES, THROW AWAY
	JRST	(J)		;RETURN


;WRITE ROUTINE FOR TMPCOR

WTTMNL:	MOVEI	ARG1,15
	PUSHJ	P,.WTTMP
	MOVEI	ARG1,12
	PJRST	.WTTMP

WTTMP:	CAIN	ARG1,12		;IF NEWLINE
	JRST	WTTMNL		;INCLUDE A CR

.WTTMP: SKIPG	0,BYTCNT(IOREG)		;MORE ROOM IN CORE?
	POPJ	P,			;NO, RETURN
	SOSLE	0,BYTCNT(IOREG)		;MORE ROOM IN CORE
	IDPB	ARG1,BYTPTR(IOREG)	;YES
	POPJ	P,		;RETURN

	SUBTTL STRING READ AND WRITE ROUTINES

RDST:	SOSGE	LENGTH(IOREG)	;ANY LEFT?
	JRST	EOF		;NO
	ILDB	AC,POINTER(IOREG)	;GET NEXT BYTE
	CAIN	AC,15		;IS IT CR?
	  JRST	RDST		;YES, IGNORE IT
	JRST	(J)		;NO, RETURN

WTST:	CAIN	ARG1,12		;NEWLINE?
	  PJRST	WTSNL		;YES

WTST1:	AOS	LENGTH(IOREG)	;NOTE LENGTH
	IDPB	ARG1,POINTER(IOREG)	;DEPOSIT BYTE
	POPJ	P,		;RETURN

WTSNL:	MOVEI	ARG1,15		;INSERT CR
	PUSHJ	P,WTST1
	MOVEI	ARG1,12		;AND LINE FEED
	PJRST	WTST1

SUBTTL ERROR TESTING

$INTST:
	HLRZ	ARG1,FILOPFN(IOREG)	;GET CHANNEL NUMBER
	PUSHJ	P,$GETSTS	;GET THE STATUS
	TRNE	AC,740000
	JRST	INERR	;AN ERROR
	TRNE	AC,020000
	JRST	EOF
;ELSE NON-BLOCKING RETURN
	PUSHJ	P,INSTREAM##	;GET STREAM NUMBER
	ERROR	9,1,AC,IMPSTR<No input on stream>

$OUTTST:
	HLRZ	ARG1,FILOPFN(IOREG)	;GET CHANNEL NUMBER
	PUSHJ	P,$GETSTS		;GET STATUS
	TRNE	AC,740000
	JRST	OUTERR		;AN ERROR
;ELSE NON-BLOCKING RETURN
	PUSHJ	P,OUTSTREAM##		;GET STREAM NUMBER
	ERROR	9,2,AC,IMPSTR<No output to stream>



SUBTTL ERROR CONDITIONS AND EOFS

INERR:	PUSH	P,IOREG
	PUSHJ	P,INSTREAM##	;GET STREAM NUMBER
	POP	P,IOREG		;RESTORE IOREG
DINERR:	PUSH	P,AC		;SAVE STREAM/CHANNEL NUMBER
	HLRZ	ARG1,FILOPFN(IOREG); GET CHANNEL NUMBER
	ANDI	ARG1,17		;JUST THE CHANNEL
	PUSHJ	P,$GETSTS	; GET STATUS
	JRST	IERT0
IERRT:	PUSH	P,T2	;SAVE ERROR CODE
	PUSHJ	P,INSTREAM##
	EXCH	AC,(P)	;SWAP ERROR CODE AND STREAM NUMBER
IERT0:	MOVE	T1,[POINT 9,IER1+15,8];  **BBIT DODGY, PATCHING STRING
	MOVE	T2,[POINT 3,AC,17]
	MOVSI	T4,-6
IER0:	ILDB	T3,T2
	ADDI	T3,"0"
	IDPB	T3,T1
	AOBJN	T4,IER0
	POP	P,AC	;RESTORE STREAM/CHANNEL NUMBER
IER1:	ERROR	4,1,AC,IMPSTR<Input error status #000000>


OUTERR:	PUSH	P,IOREG
	PUSHJ	P,OUTSTREAM##	;GET STREAM NUMBER
	POP	P,IOREG
DOUTERR:PUSH	P,AC	;SAVE STREAM/CHANNEL NUMBER
	HLRZ	ARG1,FILOPFN(IOREG); GET CHANNEL NUMBER
	ANDI	ARG1,17		;JUST THE CHANNEL
	PUSHJ	P,$GETSTS	; GET STATUS
	JRST	OERT0
OERRT:	PUSH	P,T2	;SAVE  TTY ERROR CODE
	PUSHJ	P,OUTSTREAM##
	EXCH	AC,(P)	;SWAP ERROR CODE AND STREAM NUMBER
OERT0:	MOVE	T1,[POINT 9,OER1+15,17];  **PATCHING STRING IN ERROR MACRO
	MOVE	T2,[POINT 3,AC,17]
	MOVSI	T4,-6
OER0:	ILDB	T3,T2
	ADDI	T3,"0"
	IDPB	T3,T1
	AOBJN	T4,OER0
	POP	P,AC	;RESTORE STREAM/CHANNEL NUMBER
OER1:	ERROR	4,2,AC,IMPSTR<Output error status #000000>

;EOF

DMPEOF:	ERROR	9,0,AC,IMPSTR<EOF on DA or SQ channel>


EOF:	PUSHJ	P,INSTREAM##
	ERROR	9,0,AC,IMPSTR<EOF on stream>
RDUND:	PUSHJ	P,INSTREAM##
	ERROR	8,1,AC,IMPSTR<Input from unassigned stream>

WTUND:	PUSHJ	P,OUTSTREAM##
	ERROR	8,2,AC,IMPSTR<Output to unassigned stream>



	SUBTTL	STORAGE

; SCB BLOCKS FOR UNDEFINED I/O
;**TEMP LENGTH UNTIL %SHORINTEGER DEVTYPE AND CHNTYP


IUNSCB:	UNDEV
	0
	0
	RDUND
	BLOCK 4

OUNSCB:	UNDEV
	0
	0
	WTUND
	BLOCK 4

ITYSCB:	TTYDEV
	0
	0
	RDTY
	BLOCK 4

OTYSCB:	TTYDEV
	0
	0
	WTTY
	BLOCK 4

	LIT

	END

