/
/ PDP-11 C.
/ Stdio.
/
/ Get characters.
/
 
	.globl	getcha
	.globl	getc
	.globl	_getc
	.globl	_get
 
/
/ getchar();
/ getc(ioptr);
/ FILE *ioptr;
/
/ These routines read a character from either
/ the standard input (getchar) or the specified
/ input stream (getc).
/ EOF is returned on end of file or error.
/

getcha:	jsr	r0,_save	/Get a stack frame
	mov	stdin,r4	/Get standard input IOV
	br	0f		/
 
getc:	jsr	r0,_save	/Get a stack frame
	mov	12(r5),r4	/Get user IOV
	call	_ckiov

0:	call	_getc		/Get the character
	jmp	_ret		/
 
/
/ Get a character.
/ Called by above and by gets.
/
/ r5=stack frame pointer
/ r4=ioptr
/
/ Returns character (or -1) in r0
/

_getc:	mov	V_UGET(r4),r0	/Is there an unget character
	bmi	0f		/No
	mov	$-1,V_UGET(r4)	/Make unget character go away
	return			/

0:	bit	$VF_UBF,(r4)	/Is this an unbuffered stream
	beq	0f		/No
	bis	$VF_ERR,(r4)	/Yes, set error
	br	2f		/

0:	bit	$VF_EOR,(r4)	/Any more stuff
	bne	2f		/Br if not

1:	dec	V_R0(r4)	/Get a byte from the line
	bmi	0f		/Br if none
	movb	*V_R1(r4),r0	/Grab it
	inc	V_R1(r4)	/Fix pointer
	bic	$!377,r0	/Mask number to 8 bits
	return			/

0:	mov	V_RBUF(r4),r0	/Address of record buffer
	mov	r0,V_R1(r4)	/Buffer address
	mov	V_RBSZ(r4),r1	/Size of record buffer
	call	_get		/Get record
	bcs	2f		/EOF or error
	mov	r0,V_R0(r4)	/Number of bytes in record
	br	1b		/Try again

2:	mov	$-1,r0		/Return EOF
	return			/

/
/ Get record.
/ r0 = buffer address.
/ r1 = max record size.
/
/ Returns c bit set on EOF or error.
/ Record length in r0.
/

_get:	mov	r0,-(sp)	/Save registers
	mov	r1,-(sp)	/
	mov	r2,-(sp)	/
	mov	r3,-(sp)	/

/
/ Record devices.
/

	bit	$VF_REC,(r4)	/Record device?
	beq	2f		/Br if not

/
/ Standard input/standard output
/ magic on a tty.
/

	cmp	r4,stdin	/Are we reading standard input?
	bne	0f		/No
	bit	$VF_TTY,(r4)	/Yes, is it a TTY?
	beq	0f		/No
	mov	stdout,r0	/Is the standard output
	bit	$VF_TTY,(r0)	/Also a TTY?
	beq	0f		/No

	mov	r4,-(sp)	/Yes, flush out the
	mov	r0,r4		/Standard output
	call	_flush		/This is all in the
	mov	(sp)+,r4	/Prompting

/
/ Read record.
/

0:	clr	-(sp)		/Issue read QIO.
	clr	-(sp)		/
	clr	-(sp)		/
	clr	-(sp)		/
	mov	14(sp),-(sp)	/Max record size
	mov	20(sp),-(sp)	/Address
	mov	$IO.RVB,r0	/Always use a read virtual
	call	_qiow		/
	bcc	0f		/Br if read all ok
	bis	$VF_EOF,(r4)	/Set EOF flag
	cmp	r0,$IE.EOF	/Was the error EOF?
	beq	3f		/Yes
	bis	$VF_ERR,(r4)	/No, set error as well
	br	3f		/
 
0:	mov	V_IOSB+2(r4),r0	/Get byte count read.
	bit	$VF_NOS,(r4)	/Is this a no newlines read
	bne	3f		/Yes
	mov	r0,r1		/Append a newline
	add	6(sp),r1	/
	movb	$12,(r1)	/
	inc	r0		/Add 1 to record size
	br	3f		/

/
/ Block device.
/ If file, check for end of file.
/

2:	bit	$VF_FIL,(r4)	/File on the LUN.
	beq	1f		/No

	cmp	V_RBLK(r4),V_EFBK(r4) /Check high lbn
	bhi	0f		/EOF
	blo	1f		/Ok
	cmp	V_RBLK+2(r4),V_EFBK+2(r4) /Check low lbn
	bhi	0f		/EOF
	blo	1f		/Ok
	cmp	V_RBYT(r4),V_FFBY(r4) /Byte position
	blo	1f		/Ok

0:	bis	$VF_EOF,(r4)	/Set end of file flag
	br	3f		/

/
/ Not at end of file.
/

1:	bitb	$R.FIX,V_RTYP(r4) /Fixed length records
	beq	0f		/No
	mov	V_RSIZ(r4),r2	/Pick up record size
	br	1f		/Go use it

0:	call	getb		/Read RCW.
	mov	r0,r2		/
	call	getb		/
	swab	r0		/
	bis	r0,r2		/

/
/ FD.BLK variable length records use
/ a record size of -1 to mean skip.
/ This is, of course, completely
/ undocumented.
/

	bitb	$FD.BLK,V_RATT(r4) /Can records span blocks
	beq	1f		/Yes
	cmp	r2,$-1		/Is this the magic size
	bne	1f		/No
	call	nextvb		/Advance to next block
	br	2b		/

1:	cmp	r2,4(sp)	/Is it too large?
	blos	0f		/No
	bis	$VF_ERR,(r4)	/Set error flag
	br	3f		/

0:	mov	6(sp),r3	/Get buffer address
	mov	r2,-(sp)	/Save record size

1:	dec	r2		/More?
	bmi	1f		/No
	call	getb		/Read file from the file
	bit	$VF_NOS,(r4)	/No newlines
	bne	0f		/Yes
	cmp	r0,$15		/Devour carriage returns
	beq	1b		/

0:	movb	r0,(r3)+	/Save byte in buffer
	br	1b		/

1:	asr	(sp)+		/Odd length record
	bcc	0f		/No
	call	getb		/Skip a byte

0:	bitb	$R.FIX,V_RTYP(r4) /If fixed length
	beq	0f		/And
	bitb	$FD.BLK,V_RATT(r4) /Not spanned
	beq	0f		/Then
	call	nextvb		/Skip to next block

0:	bit	$VF_NOS,(r4)	/No newlines
	bne	0f		/Yes
	bitb	$FD.CR,V_RATT(r4) /Do we need a newline?
	beq	0f		/No
	movb	$12,(r3)+	/Add one

0:	mov	r3,r0		/Compute record size
	sub	6(sp),r0	/

3:	mov	(sp)+,r3	/Restore registers
	mov	(sp)+,r2	/
	mov	(sp)+,r1	/
	tst	(sp)+		/Caller's r0

	bit	$VF_EOR,(r4)	/Error or EOF
	beq	0f		/No (c bit clear from TST)
	clr	r0		/0 byte read
	sec			/C bit set on error

0:	return			/
	

/
/ Skip to next block.
/

nextvb:	add	$1,V_RBLK+2(r4)	/Update vbn
	adc	V_RBLK(r4)	/
	clr	V_RBYT(r4)	/Go back to byte 0
	bis	$VF_BAD,(r4)	/Set read required
	return			/

/
/ Get the next byte from the file.
/ Return it in r0.
/

getb:	cmp	V_RBYT(r4),$512. /At end of block?
	blo	0f		/No
	call	nextvb		/Advance to next block

0:	bit	$VF_BAD,(r4)	/Need to read?
	beq	0f		/No
	bic	$VF_BAD,(r4)	/Clear need to read flag
	call	_rvb		/And read a block

0:	mov	V_RBYT(r4),r0	/Compute byte address
	add	V_BBUF(r4),r0	/
	inc	V_RBYT(r4)	/Next byte
	movb	(r0),r0		/Get byte from buffer
	bic	$!377,r0	/Mask to 8 bits
	return			/
