TSCVER.MAC
.Title	TSCVER - Version of TSCLIB
.Nlist	bex,toc,sym
.Enabl	lc

tscver	==	2		;Version number
tscedt	==	2		;Library edit number

.end

TSX.MAC
.Title	TSX - Return TRUE if running under TSX-plus
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V2	24-May-87	TSCLIB Routine
;	Add tsx$$
.Sbttl	V1	 3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.gval
				.if eq 1
tsx()	Returns TRUE (1) if under TSX, FALSE (0) otherwise

The global tsx$$ is provided, and is set 0 if under RT11, non-zero if TSX.
				.endc

sysgen=372		;SYSGEN Options in RMON
tsx$=100000		;Set if TSX

TSX::
	.gval	#emtarea,#sysgen
	bic	#^c<tsx$>,r0
	mov	r0,tsx$$		;Hold for other routines to access
	beq	10$
	mov	#1,r0
10$:	return

tsx$$::	0

.end

SPLFRE.MAC
.Title	SPLFRE - Return Number of Free Spool Blocks
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
unsigned int splfre();	Returns number of available blocks in spooler file.
				.endc
SPLFRE::
	mov	#area,r0
	emt	375
	return

area:	.byte	0,107

.end

SPHOLD.MAC
.Title	SPHOLD - Set Spooler Hold/NoHold
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Jun-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
sphold(chan)	Sets already-opened spooler channel to HOLD mode
spnoho(chan)	ibid, nohold
				.endc

SPHOLD::
	mov	#1,r0
	br	sph
SPNOHO::
	clr	r0
sph:
	movb	2(sp),area	;Channel number.
	mov	r0,flag
	mov	#area,r0
	jmp	emtemt

area:	.byte	0,151
	0
flag:	0

.end

TSXLN.MAC
.Title	TSXLN - Return Terminal Line
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
int tsxln();	Returns line number.
				.endc
TSXLN::
	mov	#area,r0
	emt	375
	return

area:	.byte	0,110

.end

TSXSLN.MAC
.Title	TSXSLN - Return Subprocess Line
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
int tsxsln(subpro);	Returns line number.

ERROR CONDITIONS:

	1	Specified subprocess is not active
	2	Invalid subprocess number
	3	Attempt to issue this EMT from a detached job
				.endc
TSXSLN::
	mov	#area,r0
	mov	2(sp),subpro
	emt	375
	return

area:	.byte	0,110
subpro:	0

.end

ACTODT.MAC
.Title	ACTODT - Set/Reset ODT Activation Mode
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
actodt(n);	Set/Reset ODT Activation Mode if n is 1/0 respectively.
		(Other values are not checked for!)
				.endc
ACTODT::
	mov	#area,r0
	movb	2(sp),(r0)
	emt	375
	return

area:	.byte	0,111

.end

TTOBLK.MAC
.Title	TTOBLK - Send a Block of Characters to the Terminal
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
ttoblk(buf,count) char *buf; int count;
		A TSX oddity for sending a counted block of characters to
		the terminal.
				.endc
TTOBLK::
	mov	4(sp),count
	mov	2(sp),buf
	mov	#area,r0
	emt	375
	return

area:	.byte	0,114
buf:	0
count:	0

.end

TTIBLK.MAC
.Title	TTIBLK - Get a Block of Characters 
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
ttiblk(buf,size) char *buf; int size; (size is number of bytes available)
		Another TSX oddity for getting characters from the terminal.
				.endc
TTIBLK::
	mov	4(sp),size
	mov	2(sp),buf
	mov	#area,r0
	emt	375
	return

area:	.byte	0,115
buf:	0
size:	0

.end

CKTTIE.MAC
.Title	CKTTIE - Check for Terminal Input Errors
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
int ckttie();	Returns 0 (FALSE) if errors; 1 (TRUE) if no errors.
				.endc
CKTTIE::
	mov	#area,r0
	jmp	emtret

area:	.byte	0,116

.end

NUMTTC.MAC
.Title	NUMTTC - Get number of TT input characters
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
int numttc();	Returns number of pending input characters
				.endc
NUMTTC::
	mov	#area,r0
	jmp	emtret

area:	.byte	1,116

.end

SETTTO.MAC
.Title	SETTTO - Set Terminal Time-Out
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
settto(time,char) int time; char char;
			time is in half-second units.

			This warp-minded thing shoves char into the terminal
			input stream if the user did not provide input in
			the time specified.  Too bad if he actually types
			the char: that kills him dead.  (Try ^A to login ...)
				.endc
SETTTO::
	movb	4(sp),char
	mov	2(sp),time
	mov	#area,r0
	emt	375
	return

area:	.byte	0,117
time:	0
char:	0

.end

HIEFF.MAC
.Title	HIEFF - Set/Reset Terminal High Efficiency Mode
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
hieff(n) int n;	Switches terminal high efficiency mode on/off if n is 1/0
		respectively.  Note that the EMTMTH EMT/Routine can turn
		it on but not off.  It ain't only RT wot suffered Topsy-type
		growth, am it?
				.endc
HIEFF::
	mov	#area,r0
	movb	2(r5),(r0)	;Note no checking of value.
	emt	375
	return

area:	.byte	0,120

.end

CKACT.MAC
.Title	CKACT - Check for Activation Character Pending
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
int ckact();	Returns 1 (TRUE) if an activation character is pending,
		0 (FALSE) otherwise.
				.endc
CKACT::
	mov	#area,r0
	jmp	emtret

area:	.byte	0,123

.end

SEND.MAC
.Title	SEND - Send (Asciz) Buffer to Another Line
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
int send(line,buffer) int line; char *buffer;
		Sends the ASCIZ string in buffer to the terminal line.
		Returns values a la EMTEMT
				.endc
SEND::
	mov	#area,r0
	mov	4(sp),buffer
	mov	2(sp),line
	jmp	emtemt

area:	.byte	0,127
line:	0
buffer:	0

.end

YELL.MAC
.Title	YELL - Send (Asciz) Buffer to Another Line
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
int yell(subfunc,line,buffer) int line; char *buffer;
		Sends the ASCIZ string in buffer to the terminal line.
		Returns values a la EMTEMT

Subfunction values:

    bit 0:  0	selects no-GAG-override [ie reverts to SEND]
	    1	selects GAG-override

    bit 1:  0	waits for free message buffer
	    1	if no free message buffers, returns with error code <2+1>=3

				.endc
YELL::
	mov	#area,r0
	mov	6(sp),buffer
	mov	4(sp),line
	movb	2(sp),subfunc
	jmp	emtemt

area:
subfunc:.byte	0,127
line:	0
buffer:	0

.end

DCLBRK.MAC
.Title	DCLBRK - Set Up Completion Routine for BREAK Key
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
dclbrk(char,routine) char char, routine();
		Sets up a routine to be executed if the BREAK key is typed.
				.endc
DCLBRK::
	mov	#area,r0
	movb	2(sp),char
	mov	4(sp),routine
	emt	375
	return

area:	.byte	0,133
char:	0
routine:0

.end

TTICPL.MAC
.Title	TTICPL - Set Up Completion Routine for TT Input
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
tticpl(routine)
	int routine(char) char char;
		Sets up a routine to be called when the next character is
		typed at the terminal.  However, can't keep a good thing to
		itself: bloody returns that character to the completion
		routine.  Didn't they learn ANYTHING from RT-11's mistakes?
				.endc
TTICPL::
	mov	#area,r0
	mov	2(sp),complt
	emt	375
	return

area:	.byte	1,133
	.word	macrou

complt:	0

macrou:
	mov	r0,-(sp)	;Character comes here
	call	@complt
	tst	(sp)+
	return
.end

MOUNT.MAC
.Title	MOUNT - Mount a Device
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
int mount(dev) char *dev;   eg mount("ld") or mount("ld:")
		The character string is only looked at up to the first
		three characters or the first non-rad50 character, whichever
		comes first.
				.endc
MOUNT::
	mov	2(sp),r1
	call	r50		;Note - requires CVLLIB routine
	mov	r0,dev

	mov	#area,r0
	jmp	emtemt

area:	.byte	0,134
	.word	dev
dev:	0

.end

XMOUNT.MAC
.Title	XMOUNT - Mount a Device
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
int xmount(dev) int dev;   eg mount($rad50("ld"))
		Uses the radix-50 form of the device
				.endc
XMOUNT::
	mov	2(sp),dev
	mov	#area,r0
	jmp	emtemt

area:	.byte	0,134
	.word	dev
dev:	0

.end

DISMNT.MAC
.Title	DISMNT - Dismount a Device
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1a	17-Feb-89	TSCLIB Routine
; Tidy comments
.Sbttl	V1	 3-Mar-87

.Psect	tsx$c

				.if eq 1
int dismnt(dev) char *dev;   eg dismnt("ld") or dismnt("ld:")
		The character string is only looked at up to the first
		three characters or the first non-rad50 character, whichever
		comes first.
				.endc
DISMNT::
	mov	2(sp),r1
	call	r50		;Note - requires CVLLIB routine
	mov	r0,dev

	mov	#area,r0
	jmp	emtemt

area:	.byte	0,135
	.word	dev
dev:	0

.end

XDISMN.MAC
.Title	XDISMN - Dismount a Device
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
int xdismn(dev) int dev;   eg xdismn($rad50("ld"))
		Uses radix-50 device name
				.endc
XDISMN::
	mov	2(sp),dev
	mov	#area,r0
	jmp	emtemt

area:	.byte	0,135
	.word	dev
dev:	0

.end

DISALL.MAC
.Title	DISALL - Dismount All Mounted File Structures
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

				.if eq 1
disall()

dismounts all mounted file structures - no error returns.
				.endc
.psect	tsx$c


DISALL::
	mov	#area,r0
	emt	375
	return

area:	.byte	2,135
	.word	0

.end

LDMOU.MAC
.Title	LDMOU - Mount Logical Discs
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

				.if eq 1
i=ldmou(unit,readflg,"file")

unit		LD unit - value from 0 through 7

readflg   0	allow reads and writes
	  1	disallow writes

"file"		ASCIZ string with name of file


ERROR CONDITIONS

	1	Channel is already open (should not happen?)
	2	Invalid logical disc number
	3	Logical disc upport not generated into system
	4	Logical disc already associated with a file
	5	Invalid file specification
	6	Invalid logical unit number nesting
	7	Unable to open specified file
				.endc

.psect	tsx$c

LDMOU::
	mov	r2,-(sp)

	mov	2+6(sp),r1	;Filename string
	mov	#file,r2
	call	rftlb
	bcs	badfil

	call	unuchn		;Get an unused channel
	movb	r1,chan

	mov	(sp)+,r2

	mov	#area,r0
	movb	2(sp),unit
	movb	4(sp),readflg
	jmp	emtemt		;(FILE already set up)



badfil:	mov	#5,r0
	return


area:
chan:	.byte	0,163
unit:	.byte	0
readflg:.byte	0
filep:	.word	file

file:	.blkw	5		;(allow room for RF to put size just in case)

.end

XLDMOU.MAC
.Title	XLDMOU - Mount Logical Discs
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

				.if eq 1
i=xldmou(unit,readflg,&file)

unit		LD unit - value from 0 through 7

readflg   0	allow reads and writes
	  1	disallow writes

file		Radix-50 filename a la RT-11


ERROR CONDITIONS

	1	Channel is already open (should not happen?)
	2	Invalid logical disc number
	3	Logical disc upport not generated into system
	4	Logical disc already associated with a file
	5	Invalid file specification
	6	Invalid logical unit number nesting
	7	Unable to open specified file
				.endc

.psect	tsx$c

XLDMOU::
	call	unuchn		;Get an unused channel
	movb	r1,chan

	mov	#area,r0
	movb	2(sp),unit
	movb	4(sp),readflg
	mov	6(sp),file	;Filename string
	jmp	emtemt		;(FILE already set up)


area:
chan:	.byte	0,163
unit:	.byte	0
readflg:.byte	0
file:	0

.end

LDDIS.MAC
.Title	LDDIS - Dismount a Logical Disc
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

				.if eq 1
i=lddis(unit)

Dismounts that LD unit (from 0 through 7).

ERROR CONDITIONS:

	1	Specified LD unit is not associated with a file
	2	Invalid LD unit number
	3	LD support not sysgened into system
	4	Some channel is opened to a file on the logical disc

				.endc
.psect	tsx$c

LDDIS::
	movb	2(sp),unit
	mov	#area,r0
	jmp	emtemt

area:	.byte	3,135
unit:	.byte	0,0

.end

LDDISA.MAC
.Title	LDDISA - Dismount All Logical Discs
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

				.if eq 1
i=lddisa()


ERROR CONDITIONS:

	3	LD support not sysgened into system
	4	Some channel is opened to a file on a logical disc

				.endc
.psect	tsx$c

LDDISA::
	mov	#area,r0
	jmp	emtemt

area:	.byte	5,135
	.word	0

.end

LDSTAT.MAC
.Title	LDSTAT - Return Status of Logical Disc Unit
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

				.if eq 1
LDSTAT returns the status of the specified Logical Disc Unit

i=ldstat(unit,&readflg,&file)

unit	  LD unit to determine status of (0 through 7)
readflg	  returns 0 if read/write, 1 if read only.
file	  returns ASCIZ string of filename associated with LD

ERROR CONDITIONS

	1	LD is not currently accessible.

				.endc
.psect	tsx$c


LDSTAT::
	movb	2(sp),unit
	mov	#area,r0
	emt	375

	mov	flag,r0		;If bit 1 of flag word set, unit is not
	bit	#2,r0		; available.
	bne	notavl

	mov	r0,@4(sp)	;Return readonly flag

	mov	6(sp),r1	;Address of buffer for filename
	mov	r2,-(sp)
	mov	#file,r2
	clr	r0		;No embedded spaces, no [size] typed
	call	wf
	mov	(sp)+,r2

	return			;(R0 cleared above)



notavl:	mov	#1,r0
	return


area:	.byte	4,135
unit:	.byte	0,0
	.word	file

file:	.blkw	4
flag:	.word	0

.end

XLDSTA.MAC
.Title	XLDSTA - Return Status of Logical Disc Unit
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

				.if eq 1
XLDSTA returns the status of the specified Logical Disc Unit

i=xldsta(unit,&readflg,&file)

unit	  LD unit to determine status of (0 through 7)
readflg	  returns 0 if read/write, 1 if read only.
file	  returns ASCIZ string of filename associated with LD

ERROR CONDITIONS

	1	LD is not currently accessible.

				.endc
.psect	tsx$c


XLDSTA::
	movb	2(sp),unit
	mov	#area,r0
	emt	375

	mov	flag,r0		;If bit 1 of flag word set, unit is not
	bit	#2,r0		; available.
	bne	notavl

	mov	r0,@4(sp)	;Return readonly flag

	mov	6(sp),r1	;Address of buffer for filename
	mov	#file,r0
	mov	(r0)+,(r1)+	;Device
	mov	(r0)+,(r1)+	; File-
	mov	(r0)+,(r1)+	;      name
	mov	(r0),(r1)	;  Extension

	clr	r0
	return



notavl:	mov	#1,r0
	return


area:	.byte	4,135
unit:	.byte	0,0
	.word	file

file:	.blkw	4
flag:	.word	0

.end

TTYPE.MAC
.Title	TTYPE - Return Terminal Type
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
int ttype();	Returns terminal type for current line.
				.endc
TTYPE::
	mov	#area,r0
	emt	375
	return

area:	.byte	0,137

.end

JSTAT.MAC
.Title	JSTAT - Check Job Status
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
jstat(line,func,buffer) int line; char func; int *buffer;

0 func: check status of line.  Bits set indicate status:

	1	subprocess
	2	detached
	100	locked in memory
	200	has SYSPRV

1 func: execution state:

	1	non-interactive high priority run state
	2	normal priority run state
	3	fixed low priority run state
	4	terminal input wait
	5	terminal output wait
	6	timed wait
	7	suspended (.SPND)
	8.	shared file wait
	9.	message wait
	10.	USR wait
	11.	I/O wait
	12.	spool wait
	13.	interactive high priority run state
	14.	fixed high priority run state
	15.	memory expansion wait

2 func: return amount of memory in 256-word blocks (incl PLAS regions)

3 func: return connect time (minutes)

4 func:	returns 256-word block # of start of memory area allocated to job

5 func: return 2-word programme name

6 func: returns project & programmer numbers

7 func: returns clock-ticks of CPU time used (high order word first)

8 func: returns job execution priority.

				.endc
JSTAT::
	mov	#area,r0
	mov	6(sp),buffer
	movb	4(sp),func
	movb	2(sp),line
	jmp	emtemt

area:	.byte	0,144
line:	.byte	0
func:	.byte	0
buffer:	0

.end

FILINF.MAC
.Title	FILINF - Return File Information
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.wait
				.if eq 1
int filinf(file,block) char *file; int *block;   eg filinf("dk:x.tmp",block);
			Gets information about the file into 7-word block.
				.endc
FILINF::
	mov	r2,-(sp)

	mov	2+2(sp),r1
	mov	#file,r2
	call	rftlb		;Note - needs CVLLIB routine

	call	unuchn		;Get a spare channel

	mov	(sp)+,r2

	mov	#area,r0
	movb	r1,(r0)
	mov	4(sp),block

	jmp	emtemt

area:	.byte	0,145
	.word	file
block:	0

file:	.blkw	5

.end

XFILIN.MAC
.Title	XFILIN - Return File Information
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Psect	tsx$c

.Mcall	.wait
				.if eq 1
int xfilin(file,block) int *file; int *block;
		Uses a Radix-50 filename, and gets information about the
		file into 7-word block.
				.endc
XFILIN::
	call	unuchn		;Get a spare channel

	mov	#area,r0
	movb	r1,(r0)
	mov	2(sp),file
	mov	4(sp),block

	jmp	emtemt

area:	.byte	0,145
file:	0
block:	0

.end

SFTIM.MAC
.Title	SFTIM - Set File Time
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1a	17-Feb-89	TSCLIB Routine
; Bug fix
.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.wait
				.if eq 1
int sftim(file,time) char *file; int time;	eg sftim("dk:fred.dat",1000);
				.endc
SFTIM::
	mov	r2,-(sp)

	mov	2+2(sp),r1
	mov	#file,r2
	call	rftlb		;Note - needs CVLLIB routine

	call	unuchn		;Get a spare channel

	mov	(sp)+,r2

	mov	#area,r0
	movb	r1,(r0)
	mov	4(sp),time

	jmp	emtemt

area:	.byte	0,145
	.word	file
time:	0

file:	.blkw	5

.end

XSFTIM.MAC
.Title	XSFTIM - Set File Time
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Psect	tsx$c

.Mcall	.wait
				.if eq 1
int xsftim(file,time) int *file; int time;	eg sftim(infile,1000);
			Uses Radix-50 filename.
				.endc
XSFTIM::
	call	unuchn		;Get a spare channel

	mov	#area,r0
	movb	r1,(r0)
	mov	2(sp),file
	mov	4(sp),time

	jmp	emtemt

area:	.byte	0,145
file:	0
time:	0

.end

GSUNAM.MAC
.Title	GSUNAM - Get/Set User Name
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
getnam(string) char *string;
setnam(string) char *string;
		Gets/Sets user name into/from string.	
				.endc
GETNAM::
	clrb	area
	br	nam
SETNAM::
	movb	#1,area
nam:
	mov	#area,r0
	mov	2(sp),string
	jmp	emtret

area:	.byte	0,147
string:	0

.end

GSPNAM.MAC
.Title	GTPNAM - Get/Set Programme Name
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
gtpnam(string) char *string;
stpnam(string) char *string;
		Gets/Sets programme name into/from string.	
				.endc
GTPNAM::
	mov	#area,r0
	movb	#3,(r0)
	emt	375
	bcs	badnam

	mov	2(sp),r1	;String pointer

	mov	rad50,r0
	call	w50		;First 3 characters
	mov	rad50+2,r0
	call	w50
	clrb	(r1)		;Make it ASCIZ

	clr	r0		;OK return
	return



STPNAM::
	mov	2(sp),r1	;Pointer to his string

	call	r50		;First 3 characters
	mov	r0,rad50
	call	r50		; and the second.
	mov	r0,rad50

	mov	#area,r0
	movb	#4,area
	jmp	emtret



badnam:
	movb	@#52,r0
	inc	r0
	return


area:	.byte	0,147
buffer:	.word	rad50

rad50:	.blkw	2

.end

SJBPRI.MAC
.Title	SJBPRI - Set Priority
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
sjbpri(value) int value;  Sets the job priority to value from 0-127
				.endc
SJBPRI::
	mov	#area,r0
	mov	2(sp),value
	emt	375
	return

area:	.byte	0,150
value:	0

.end

SETPRV.MAC
.Title	SETPRV - Get/Set Privileges
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
setprv(func,type,buffer)
	char func, type; int *buffer;
			Returns/clears/sets privilege bits for func 0, 1, 2
			respectively, in current/set/authorized privs for
			for type 0, 1, 2 respectively.
			[The values are not checked for validity.]
Privileges are:
1,    1	SYSPRV		System manager functions (eg authorize accounts)
1,    2	NFSWRITE	ibid, writes
1,    4	NFSREAD		Perform non file structured reads
1,   10	SETPRV		Set privileges beyond those authorized
1,   20	SETNAME		Change job name or password
1,   40	SEND		Sent a message to another terminal
1,  100	REALTIME	Real time system services (eg interrupt connect)
1,  200	PSWAPM		Change process swap mode (ie lock in memory)
1,  400	OPER		Operator functions (eg set time, spool control)
1, 1000	BYPASS		Bypass device/file access restrictions
1, 2000	MEMMAP		Access system memory (eg I/O page)
1, 4000	SPFUN		Allow SPFUNs
1,10000	DETACH		Start off detached jobs
1,20000	DEBUG		Use system debugging facilities
1,40000	ALLOCATE	Allocate a device

2,    1	UP1		User-defined privs 1
2,    2	UP2		ibid, 2
2,    4	UP3		ibid, 3
2,   10	UP4		ibid, 4
2,  200	GETCXT		Get file context from another job
2,  400	SYSGBL		Use named global regions & display windows
2, 1000	RLOCK		Shared file record locking & access control
2, 2000	MESSAGE		Send and receive messages
2, 4000	SUBPROCESS	Use virtual lines
2,10000	SAME		Affect another job with same proj-prog number
2,20000	GROUP		Affect other jobs with same project number
2,40000	WORLD		Affect any job
2,100000 TERMINAL	Terminal and CL line control

				.endc
SETPRV::
	mov	#area,r0
	mov	6(sp),buffer
	movb	4(sp),type
	movb	2(sp),func
	jmp	emtemt

area:	.byte	1,150
func:	.byte	0
type:	.byte	0
buffer:	0
	0		;(Needs an extra)

.end

SELOPT.MAC
.Title	SELOPT - Set Terminal Characteristics
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
selopt(func,arg) int func, *arg;
		See the chapter on programme-controlled termonal options
		for this.  If arg is unnecessary, it need not be specified
		[whatever is on the stack will be used, but this should not
		matter].

FUNCTION	MEANING
A	*	Set rubout filler character
B		Enable VT52 & VT100 escape-letter activation
C		Disable, ibid
D	*	Define new activation character
E		Turn on character echoing
F		Turn off, ibid
H		Disable subprocesses
I		Enable lower case
J		Disable ibid
K		Enable deferred character echo
L		Disable ibid
M		Set transparency mode for output
N		Suspend command file input
O		Restart command file input
P	*	Reset activation character
Q	*	Set activation on field width
R		Turn on high efficiency TTY mode
S		Turn on single character activation mode
T		Turn off, ibid
U		Enable no-wait TT input test
V	*	Set field width limit
W		Turn tape mode on
X		Turn tape mode off
Y		Disable echo of <lf> after <cr>
Z		Enable, ibid

* = requires additional argument.
				.endc
SELOPT::
	mov	#area,r0
	mov	4(sp),arg
	mov	2(sp),func
	emt	375
	return

area:	.byte	0,152
func:	0
arg:	0

.end

NONINT.MAC
.Title	NONINT - Set/Reset Interactive Mode
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
nonint(n) int n;	Sets job to interactive/noninteractive mode for values
			of n 1/0 respectively.  The value of n is not checked.
				.endc
NONINT::
	mov	#area,r0
	mov	2(sp),mode
	emt	375
	return

area:	.byte	0,153
mode:	0
	0

.end

STTSPD.MAC
.Title	STTSPD - Set Line Parameters
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V2	24-Aug-88	TSCLIB Routine
;Put in SUBFUNCTION argument, as per TSX V6.2
.Sbttl	V1	 3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
sttspd(subfunc,line,params) int line, params;
		Sets terminal or CL line parameters - NEARLY all but dips out
		on number of stop bits.  Thanks folks!

subfunc	  0	set speed
	  1	reset line XOFF status
	  2	raise line DTR
	  3	lower line DTR

For subfunction 0 (set speed), the PARAMS argument is used.

		The low-order 8 bits are used as follows:

		Bit	Value	Meaning
		 7	  0	Even parity
			  1	Odd parity
		 6	  0	No parity
			  1	Enable parity
		 5	  0	8 data bits
			  1	7 data bits
		 4		Unused (still hope!)
		 3,2,1,0	Speed:
				1	  75		11	 2000
				2	 110		12	 2400
				3	 134.5		13	 3600
				4	 150		14	 4800
				5	 300		15	 7200
				6	 600		16	 9600
				7	1200		17	19200
				10	1800
				.endc
STTSPD::
	mov	#area,r0

	movb	2(sp),subfunc
	movb	4(sp),line
	mov	6(sp),params

	jmp	emtemt


area:
subfunc:.byte	0,154
line:	0
params:	0

.end

GETCL.MAC
.Title	GETCL - Get a CL Line
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
getcl(clunit,line) int clunit,line;
		Attempts to connect CL'clunit to the desired line.
				.endc
GETCL::
	mov	#area,r0
	mov	4(sp),line
	mov	2(sp),clunit
	jmp	emtemt

area:	.byte	0,155
clunit:	0
line:	0

.end

ALCDEV.MAC
.Title	ALCDEV - Allocate/Deallocate a Device
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
alcdev(dev) char *dev;		eg alcdev("cl5:") Tries to allocate a device
dealoc(dev)			Deallocates that device
tstalc(dev)			Tests for allocation of a device.
				.endc
ALCDEV::
	clr	r0
	br	alloc
DEALOC::
	mov	#1,r0
	br	alloc
TSTALC::
	mov	#2,r0
alloc:
	movb	r0,func

	mov	2(sp),r1
	call	r50		;Requires routine from CVLLIB
	mov	r0,dev

	mov	#func,r0
	jmp	emtemt

func:	.byte	0,156
	dev
dev:	.word	0,0,0,0

.end

XALCDE.MAC
.Title	XALCDE - Allocate/Deallocate a Device
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
xalcde(dev) int dev;		eg alcdev($rad50("cl5:"))
				  Tries to allocate a device
xdealo(dev)			Deallocates that device
xtstal(dev)			Tests for allocation of a device.
				.endc
XALCDE::
	clr	r0
	br	alloc
XDEALO::
	mov	#1,r0
	br	alloc
XTSTAL::
	mov	#2,r0
alloc:
	movb	r0,func

	mov	2(sp),dev

	mov	#func,r0
	jmp	emtemt

func:	.byte	0,156
	dev
dev:	.word	0,0,0,0

.end

MONJOB.MAC
.Title	MONJOB - Job Monitoring
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
monjob(job,&routine) int job, routine();
		Establishes a job monitoring request
nomonj(job)
		Cancels a job monitoring request
stamon(job)
		Broadcasts a monitor status report.

				.endc
MONJOB::
	clr	r0
	mov	4(sp),r1
	br	mon1
NOMONJ::
	mov	#1,r0
	br	mon0
STAMON::
	mov	#2,r0
mon0:	clr	r1
mon1:	movb	r0,func
	mov	#func,r0
	mov	2(sp),job
	mov	r1,complt

	jmp	emtemt

func:	.byte	0,157
job:	0
	macrou

complt:	0

macrou:
	mov	r0,-(sp)
	call	@complt
	mov	(sp)+,r0
	return
.end

GETCXT.MAC
.Title	GETCXT - Get Job's File Context
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
getcxt(job) int job;
			Attempts to get the file context of the other job.
				.endc
GETCXT::
	mov	#area,r0
	mov	2(sp),job
	jmp	emtemt

area:	.byte	0,160
job:	0
	0

.end

WINDOW.MAC
.Title	WINDOW - Create, Select, or Delete Windows
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c
				.if eq 1
makwin(id,pflag,width,scroll) int id, pflag, width, scroll;
		Creates a window
selwin(id) int id;
		Selects a window
delwin(id) int id;
		Deletes a window
spnwin();
		Suspends window processing
rsmwin();
		Resumes window processing
prtwin(id);
		Prints a window
				.endc
MAKWIN::
	mov	#carea,r0
	movb	10(sp),scroll
	movb	6(sp),width
	movb	4(sp),pflag
	movb	2(sp),cid
	br	go

carea:	.byte	0,161
cid:	.byte	0
pflag:	.byte	0
width:	.byte	0
scroll:	.byte	0
	.word	0,0

SELWIN::
	mov	#sarea,r0
	mov	2(sp),sid
	br	go

sarea:	.byte	1,161
sid:	.word	0,0

DELWIN::
	mov	#darea,r0
	mov	2(sp),did
	br	go

darea:	.byte	2,161
did:	.word	0,0

SPNWIN::
	mov	#ssarea,r0
	br	go

ssarea:	.byte	3,161

RSMWIN::
	mov	#rarea,r0
	br	go

rarea:	.byte	4,161

PRTWIN::
	mov	#parea,r0
	mov	2(sp),pid
go:	jmp	emtemt

parea:	.byte	5,161
pid:	0

.end

SHARED.MAC
.Title	SHARED - Shared File Access
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

			.if eq 1
shrfil(chan,access) int chan, access;
		Allows a file which has already been fopen'ed to be shared.
savshr(chan) int chan;
		Allows shared file details to be held across a savestatus.
		[May require other support routines ? ... ]
lockw(chan,block) int chan, block;
		Waits for a locked block.
tlock(chan,block)
		Tries to lock a block.
unlock(chan,block)
		Tries to unlock a block.
unlall(chan)
		Unlocks all blocks locked by this user.
ckwshr(chan)
		Checks for writes to a shared file
			.endc


SHRFIL:: ;(chan,access)
	mov	#fil,r0
	movb	2(sp),(r0)
	mov	4(sp),access
	br	go

fil:	.byte	0,125
access:	0


SAVSHR:: ;(chan)
	mov	#hol,r0
	movb	2(sp),(r0)
	br	go

hol:	.byte	0,122


LOCKW:: ;(chan,block)
	mov	#wai,r0
	movb	2(sp),(r0)
	mov	4(sp),wblock
	br	go

wai:	.byte	0,102
wblock:	0


TLOCK:: ;(chan,block)
	mov	#lok,r0
	movb	2(sp),(r0)
	mov	4(sp),lblock
	br	go

lok:	.byte	0,103
lblock:	0


UNLOCK:: ;(chan,block)
	mov	#unb,r0
	movb	2(sp),(r0)
	mov	4(sp),bblock
	br	go

unb:	.byte	0,113
bblock:	0


UNLALL:: ;(chan)
	mov	#unl,r0
	movb	2(sp),(r0)
	br	go

unl:	.byte	0,101


CKWSHR:: ;(chan)
	mov	#chk,r0
	movb	2(sp),(r0)
go:	jmp	emtemt

chk:	.byte	0,121

.end

MESAGE.MAC
.Title	MESAGE - Handle TSX Message Channels
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87

.Psect	tsx$c

			.if eq 1
sndmsg("chname",buf,size)
	char *buf; int size;
		Sends a message
getmsg("chname",buf,size,&nbytes)
	char *buf; int size, nbytes;
		Checks for pending message, returning size in nbytes
watmsg("chname",buf,size,&nbytes)
	char *buf; int size, nbytes;
		Waits for a message, ibid
cmpmsg("chname",buf,size,routine)
	char *buf; int size, routine(arg_r0,arg_r1);
		Schedules a completion routine when a message received
		giving the length of the message in arg_r0 and the number
		of the sending job in arg_r1.

The channel name should be six ascii characters (space filled if necessary).
			.endc

SNDMSG::
	clr	flag		;Zero - doesn't return number of bytes
	mov	#<104 * 400>,r0
	br	mes
GETMSG::
	mov	#<105 * 400>,r0
	br	gwmes
WATMSG::
	mov	#<106 * 400>,r0
gwmes:	mov	sp,flag		;Get and Wait return a byte count
	br	mes


CMPMSG::
	clr	flag
	mov	10(sp),r1	;Set up completion routine address
	call	cmpset		;Puts completion routine address into
				; a macro routine, and returns that address
	mov	r1,compl

	mov	#<106 * 400 + 1>,r0
mes:
	mov	2(sp),chan
	mov	4(sp),buf
	mov	6(sp),size
	mov	r0,area
	mov	#area,r0

	emt	375
	bcs	10$

	tst	flag
	beq	30$		;No value to be returned

	mov	r0,@10(sp)	;Value - return number of bytes in message.
	br	30$

10$:				;ERROR!
	bit	#1,area		;See if completion routine wanted.
	beq	20$
	jmp	emtwhoops	;(If wanted completion routine & died)
20$:	sec
30$:	jmp	emtval

area:	.byte	0,0
chan:	0
buf:	0
size:	0
compl:	0

flag:	0

.end

PERFOR.MAC
.Title	PERFOR - Performance Monitoring
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
initpa(base,top,celsiz,flags)
		Initializes parameters for performance analysis
strtpa()
		Starts performance data collection
stoppa()
		Stops, ibid
haltpa(parbuf,hisbuf,bufsiz)
		Stops analysis and returns data
				.endc


INITPA::
	mov	10(sp),iflags
	mov	6(sp),icelsiz
	mov	4(sp),itop
	mov	2(sp),ibase
	mov	#iarea,r0
	br	go

iarea:	.byte	0,136
ibase:	0
itop:	0
icelsiz:0
iflags:	0



STRTPA::
	mov	#onarea,r0
	br	go

onarea:	.byte	1,136


STOPPA::
	mov	#offarea,r0
	br	go

offarea:.byte	2,136


HALTPA::
	mov	6(sp),bufsiz
	mov	4(sp),hisbuf
	mov	2(sp),parbuf
	mov	#earea,r0
go:	jmp	emtemt

earea:	.byte	3,136
parbuf:	0
hisbuf:	0
bufsiz:	0

.end

DETACH.MAC
.Title	DETACH - Handle Detached Jobs
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Jun-87

.Psect	tsx$c

				.if eq 1
strtdj("filename")	Starts the detached job, using the file as the job's
			command file.  RETURNS 0 IF CAN'T, else JOB NUMBER
			of detached job.
abrtdj(jobno)		Aborts detached job.
statdj(jobno)		Checks status of detached job.

			The latter two return as per EMTRET.
				.endc

STRTDJ::
	mov	2(sp),filename
	mov	#area,r0
	clrb	(r0)
	emt	375
	bcc	10$
	clr	r0
10$:	return

ABRTDJ::
	mov	#2,r0
	br	dj

STATDJ::
	mov	#1,r0
dj:	movb	r0,area
	mov	#area,r0
	jmp	emtret

area:	.byte	0,132
filename:	0

.end

SWTSUB.MAC
.Title	SWTSUB - Switch between subprocesses
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

				.if eq 1
i=swtsub(subfunc,subpro,retpro,iniflg,"commandfile")

Switches control between subprocesses:

subfunc	  0	use existing subprocess or create new one prn
	  1	create new subprocess
	  2	use existing subprocess

subpro		Number of subprocess (as per digit typed after ^W)
		If -1, locates first unused subprocess number & uses it

retpro		Process to return to when subprocess initiated by this
		EMT logs off.
		If -1, return to process which executed this EMT

iniflg	  0	Terminal control switches to subprocess
	  1	Terminal control remains with current process

"file"		ASCIZ name of command file to be executed by the specified
		subprocess.  (If zero, no command file executed).

ERROR CONDITIONS:

	2	You are not suthorized to use subprocesses
	3	Specified subprocess number is too large
	4	All of your subprocesses are already active
	5	Insufficient memory space available for process
	6	Specified subprocess has already been initiated
	7	Specified subprocess has not been initiated

				.endc

.psect	tsx$c

SWTSUB::
	mov	#area,r0
	movb	2(sp),subfunc
	movb	4(sp),subpro
	movb	6(sp),retpro
	movb	10(sp),iniflg
	mov	12(sp),cmdfil
	jmp	emtemt


area:
subfunc:.byte	0,162
subpro:	.byte	0,0
retpro:	.byte	0
iniflg:	.byte	0
cmdfil:	.word	0
	.word	0

.end

RTTIM1.MAC
.Title	RTTIM1 - Real-Time EMTs for TSX
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V2	24-Aug-88	TSCLIB Routine
;Add cache bypass option for MAPPHY, as per TSX V6.2
.Sbttl	V1	 3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
mapiop()		Map i/o page into this job's par 7.
mapmon()		Map i/o page to simulated RMON.
peekio(addr)		Peek at address in i/o page.
pokeio(addr,val)	Poke into address in i/o page.
bisio(addr,val)		Bit set, ibid
bicio(addr,val)		Bit clear, ibid
mapphy(par,addr,size,access,cacflg) int par, addr, size, access, cacflg;
			Map physical memory region
				.endc


MAPIOP::
	mov	#iarea,r0
	jmp	emtret

iarea:	.byte	5,140

MAPMON::
	mov	#rarea,r0
	jmp	emtret

rarea:	.byte	6,140

PEEKIO::
	mov	#pearea,r0
	mov	2(sp),peek
	jmp	emtret

pearea:	.byte	1,140
peek:	0

POKEIO::
	mov	#2,r0
	br	io

BISIO::
	mov	#3,r0
	br	io

BICIO::
	mov	#4,r0
io:
	movb	r0,poarea
	mov	#poarea,r0
	mov	2(sp),poke
	mov	4(sp),pval
	jmp	emtret

poarea:	.byte	0,140
poke:	0
pval:	0


MAPPHY::
	mov	#area,r0
	movb	12(sp),cacflg
	movb	10(sp),access
	mov	6(sp),size
	mov	4(sp),addr
	mov	2(sp),par
	jmp	emtret

area:	.byte	17,140
par:	0
addr:	0
size:	0
access:	.byte	0
cacflg:	.byte	0

.end

RTTIM2.MAC
.Title	RTTIM2 - Heavier Real-Time TSX EMTs
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.br

				.if eq 1
steals()	Requests exclusive use of system
rturns()	Relinquishes, ibid

loklow()	Lock job in low memory
lokjob()	Lock job where it is
unlokj()	Unlock job

phyadd(virt,&phys)	Convert virtual address to physical
	unsigned int virt, phys;

setpri(n) int n;	Sets processor priority to n
			(See SJBPRI for job priority)
				.endc

STEALS::
	mov	#14,40
	br	emtx
RTURNS::
	mov	#15,r0
	br	emtx

LOKLOW::
	mov	#7,r0
	br	emtx

LOKJOB::
	mov	#13,r0
	br	emtx

UNLOKJ::
	mov	#10,r0
	br	emtx


PHYADD::
	mov	4(sp),virt
	mov	2(sp),phys
	clr	r0
	br	emtx


SETPRI::
	mov	2(sp),prio
	mov	#16,r0
	.br	emtx

emtx:
	movb	r0,area
	mov	#area,r0
	jmp	emtret

area:	.byte	0,140
prio:				;(same loc for prio & virt)
virt:	0
phys:	0

.end

RTTIM3.MAC
.Title	RTTIM3 - Heaviest Real-Time TSX EMTs
.Nlist	bex,toc,sym
.Enabl	lsb

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
attsvc(vector,routine) int vector, routine();
		Connect interrupt service routine
attvec(vector,routine,prio) int vector, routine(), prio;
		Connect interrupt completion routine
relvec(vector) int vector;
		Release interrupt vector
schcmp(routine,prio,r1value) int routine(), prio, r1value;
		Schedule a completion routine
				.endc

ATTSVC::
	mov	2(sp),asvec
	mov	4(sp),asrout
	mov	#asarea,r0
	jmp	emtemt

asarea:	.byte	20,140
asvec:	0
asrout:	0
	0

ATTVEC::
	mov	2(sp),avvec
	mov	4(sp),avrout
	mov	6(sp),avprio
	mov	#avarea,r0
	jmp	emtemt

avarea:	.byte	11,140
avvec:	0
avrout:	0
avprio:	0

RELVEC::
	mov	2(sp),rvvec
	mov	#rvarea,r0
	jmp	emtemt

rvarea:	.byte	12,140
rvvec:	0

SCHCMP::
	mov	2(sp),r1	;Set up completion routine address
	call	cmpset		;Puts completion routine address into
				; a macro routine, and returns that address
	mov	r1,scrout
	mov	4(sp),scprio
	mov	6(sp),scr1
	mov	#scarea,r0
	jmp	emtemt

scarea:	.byte	21,140
scrout:	0
scprio:	0
scr1:	0
	0


.end

RTS.MAC
.Title	RTS - Shared Run-Time System Support
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
userts(name) char *name;		(name in asciz)
		Associate run-time system with job
maprts(par,offset,size);
		Map associated run-time system on to job
				.endc

USERTS::
	mov	2(sp),r1
	call	r50		;Requires CVLLIB routine
	mov	r0,nam1
	call	r50
	mov	r0,nam2

	mov	#area,r0
	jmp	emtemt

area:	.byte	0,143
	name

name:
  nam1:	0
  nam2:	0


MAPRTS::
	mov	#marea,r0
	mov	6(sp),size
	mov	4(sp),offset
	mov	2(sp),par
	jmp	emtemt


marea:	.byte	1,143
par:	0
offset:	0
size:	0


.end

RTSF.MAC
.Title	RTSF - Shared Run-Time System Support (Fast Technique)
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Aug-88	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
faston(par,offset,size,region);
		Define run-time system mapping region for job
trap(region);
		Connect region to job
fastof();
		Disconnect all run-rime system definitions
				.endc


FASTON::
	mov	#marea,r0
	mov	10(sp),region
	mov	6(sp),size
	mov	4(sp),offset
	mov	2(sp),par
	jmp	emtemt


marea:	.byte	2,143
par:	0
offset:	0
size:	0
region:	0


TRAP::
	mov	2(sp),r0
	trap	1
	bic	r0,r0
	adc	r0
	return


FASTOF::
	mov	#area,r0
	emt	375
	return

area:	.byte	3,143

.end

BPT.MAC
.Title	BPT - Assist in debugging
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	27-May-87	TSCLIB Routine

.Psect	tsx$c

BPT::
	bpt
	return

.end

TTIN.MAC
.Title	TTIN - Get terminal input from TT or Command File
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-Mar-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
TSX-Plus suffers from a weird problem (up to 6.01 anyway) where type-ahead
for a programme using single-character I/O will be held in abeyance until
another character is typed after the programme has been running.  This
routine gets around this problem.

Expects the global tsx$$ to be zero if running under RT, non-zero if under TSX
[ie the programme must have called tsx()].
				.endc

.globl	tsx$$

.mcall	.ttinr,.ttyin,.ttyou,.gval,.spnd,.rsum,.exit

jsw=44
ttlc$=40000	;Lower case
ttspc$=10000	;Special mode


;To set up for input, you need the following:

TT1SET::
	bis	# ttlc$ ! ttspc$ , @#jsw

	tst	tsx$$
	beq	5$

	mov	#'S,func
	mov	#emtmth,r0	;EMT for single-character mode
	emt	375
	mov	#'U,func
	mov	#emtmth,r0	;EMT for no waiting on terminal
	emt	375
5$:
	return
;Get a character from the terminal

TTIN::
	tst	tsx$$		;If not under TSX, begging the question.
	beq	5$		;(If RT, can't track command files without
				; GTLINs anyway)
	.gval	#emtarea,#366	;Are we under a command file?
	bit	#110400,r0
	beq	10$
5$:
	.ttyin			;Yes - use TTYIN to track command file
	return			;(assuming special TSX ^>)
10$:
	mov	#carea,r0	;Terminal: use special EMT so avoid problem
	emt	375		; with type-ahead waiting for activation
	.spnd			; character even in single-character mode.
	mov	ttchr,r0	;Wait till it is available.
	return


cmpl:	mov	r0,ttchr	;Completion routine for 1 TT char
	.rsum			;May now stop snoozing ...
	return


carea:	.byte	1,133		;Completion routine EMT block for 1 TT char
	.word	cmpl

ttchr:	0

emtmth:	.byte	0,152		;EMTMTH - terminal characteristix
func:	0
arg:	0

.end

TSXCMD.MAC
.Title	TSXCMD - See if Running from Command File under TSX
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	4-Aug-87	TSCLIB Routine

.mcall	.gval

				.if eq 1
tsxcmd() returns TRUE if under TSX and being run from a command file, FALSE
	 otherwise.
				.endc

TSXCMD::
	tst	tsx$$		;If not under TSX, begging the question.
	beq	false

	.gval	#emtarea,#366	;Are we under a command file?
	bit	#110400,r0
	beq	false
	mov	#1,r0
	return
false:
	clr	r0
	return
.end

EXITM.MAC
.Title	EXITM - Message Exits for RT-11

.Sbttl	V1	21-Aug-88	TSCLIB Routine

			.if eq 1
There are four routines in this set:

extset()	- set up ready for lines of code to be put into exit area;
extmes("text")	- puts another line of code into area;
extmsx("text")	- puts a partial line (no zero at end) into area;
extgo() 	- finally exits!
			.endc

jsw=44
chnif$=4000
spxit$=40

extset::
	mov	#512,@#510	;510 gets count of characters from 512 on.
	return

extmes::
	mov	2(sp),r1	;Line of next command
10$:
	movb	(r1)+,r0
	movb	r0,@510
	inc	@#510
	tst	r0
	bne	10$

	return

extmsx::
	mov	2(sp),r1	;Line of next command
10$:
	movb	(r1)+,r0
	beq	20$
	movb	r0,@510
	inc	@#510
	br	10$
20$:
	return

extgo::
	sub	#512,@#510	;Reset to get count.
	bis	#spxit$,@#jsw	;Set for exit to use commands.

	clr	-(sp)
	call	exit
.end

KILL.MAC
.Title	KILL - Kill a TSX Line
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	12-Jan-88	TSCLIB Routine

.Psect	tsx$c

.iif ndf v6.31, v6.31=1	;Assume 6.31 or later unless proved otherwise.


				.if eq 1
kill(n); int n;  Kills line n.  Returns -1 if cannot set KMON bit.
				.endc
KILL::

.if eq v6.31

	call	kmnon
	tst	r0
	beq	10$
	mov	#-1,r0
	return
10$:
	mov	2(sp),job
	asl	job
	mov	#area,r0
	emt	375
	call	kmnoff
	jmp	emtval

area:	.byte	0,126
	.word	5
job:	0

.iff

	mov	#area,r0
	mov	2(sp),job
	jmp	emtemt

area:	.byte	2,132
job:	0

.endc

.end

KMON.MAC
.Title	KMON - Pretend to be KMON
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	12-Jan-88	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
kmnon()  tries to set $inkmn in LSW4
kmnoff() tries to unset, ibid.

These are necessary to allow use of special internal EMTs, eg Kill, Activate.
				.endc

$inkmn = 10000

KMNON::
	mov	#10$,r0
	jmp	emtemt

10$:	.byte	2,130
	.word	4
	.word	$inkmn

KMNOFF::
	mov	r0,-(sp)
	mov	#10$,r0
	emt	375
	mov	(sp)+,r0
	return

10$:	.byte	3,130
	.word	4
	.word	$inkmn

.end

ABTIO.MAC
.Title	$ABTIO - Abort I/O on a channel
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.abtio
				.If eq 1
$abtio(chan)	int chan

Aborts I/O currently queued on a channel.  NOTE: it can only remove queued
elements from handlers - it cannot abort I/O currently being performed in
monitors earlier than RT-11 version 5 (I am not sure: maybe even 5.4).
				.endc

$ABTIO::
	.abtio	2(sp)
	jmp	emtval
.end

CHAIN.MAC
.Title	$CHAIN - Chain to another programme
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.chain

				.If eq 1
$chain("Filename");
	Chains to that file.  TSX-plus appears to destroy locations 400-500
	on a chain.  500-510 are used for the chain data, and 512+ can be
	used by the system for passing unchanged GTLIN lines.
				.endc

$CHAIN::
	mov	@#512,-(sp)	;Save 1 loc which may be clobbered
	mov	#500,r2		;Fileblock for CVLLIB routine
	mov	2+2(sp),r1	;Pointer to string
	call	rftlb		;Read filename
	mov	(sp)+,@#512

	.chain
.end

XCHAIN.MAC
.Title	$XCHAI - Chain to another programme
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.chain

				.If eq 1
$xchain(filename); int filename[4] - in radix-50
	Chains to that file.  TSX-plus appears to destroy locations 400-500
	on a chain.  500-510 are used for the chain data, and 512+ can be
	used by the system for passing unchanged GTLIN lines.
				.endc

$XCHAI::
	mov	#500,r2		;Fileblock for CVLLIB routine
	mov	2(sp),r1	;Pointer to filename
	mov	(r1)+,(r2)+	;Dev
	mov	(r1)+,(r2)+	;Filename
	mov	(r1)+,(r2)+
	mov	(r1),(r2)	;Ext

	.chain
.end

CLOSE.MAC
.Title	$CLOSE - Close a channel.
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.close

				.If eq 1
$close(chan)	Merely performs a close on that channel.
				.endc

$CLOSE::
	.close	2(sp)
	return
.end

CMKT.MAC
.Title	$CMKT - Cancel a Mark Time request
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.cmkt

				.If eq 1
$cmkt(id,&time,mrtn)	int id; long time; int mrtn
	Cancels mark time request with ident id, returning the amount of
	time left in time.
	Uses macro completion routine in mrtn (gotten when MRKT request
	posted) to free up completion routine again.
				.endc

$CMKT::
	mov	6(sp),r1	;Address of macro completion routine

	.cmkt	#emtarea,2(sp),4(sp)
	mov	#0,moffs(r1)	;Free up completion routine.

	jmp	emtval


.end

CRAW.MAC
.Title	$CRAW - Create a Virtual Address Window
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.craw
				.If eq 1
$craw(block)	int *block;
	Creates a window using the window definition block pointed to by
	block.
				.endc

$CRAW::
	.craw	#emtarea,2(sp)
	jmp	emtval
.end

CRRG.MAC
.Title	$CRRG - Create a Dynamic Region
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.crrg

				.If eq 1
$crrg(block)	int *block;
	Allocates a dynamic region in physical memory for use by the
	requesting job, using the region definition block pointed to by
	block.
				.endc

$CRRG::
	.crrg	#emtarea,2(sp),4(sp)
	jmp	emtval
.end

CSTAT.MAC
.Title	$CSTAT - Returns Channel Information
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.cstat
				.If eq 1
$cstat(channel,block)	int channel, *block;
	Returns channel information about channel into block.
				.endc

$CSTAT::
	.cstat	#emtarea,2(sp),4(sp)
	jmp	emtval
.end

DATE.MAC
.Title	$DATE - Returns System Date in RT-11 format
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.date

.Psect	tsx$c

				.If eq 1
$date()	Returns date in RT-11 format.
				.endc

$DATE::
	.date
	return

.end

DELETE.MAC
.Title	$DELETE - Deletes a File
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.delete
				.If eq 1
$delete("Filename")	deletes that file.
				.endc

$DELETE::
	mov	r2,-(sp)
	mov	#file,r2
	mov	2+2(sp),r1
	call	rftlb		;Use CVLLIB routine to decode filename

	call	unuchn		;Get an unused channel

	.delete	#emtarea,r1,r2
	mov	(sp)+,r2

	jmp	emtval

file:	.blkw	5

.end

XDELET.MAC
.Title	$XDELET - Deletes a File
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Psect	tsx$c

.Mcall	.delete
				.If eq 1
$xdelete(filename) with filename in radix-50, deletes that file.
				.endc

$XDELET::
	mov	r2,-(sp)
	mov	2+2(sp),r2
	call	rftlb		;Use CVLLIB routine to decode filename

	call	unuchn		;Get an unused channel

	.delete	#emtarea,r1,r2
	mov	(sp)+,r2

	jmp	emtval
.end

DEVICE.MAC
.Title	$DEVICE - Set up locations on exit from programme
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.device

.Psect	tsx$c

				.If eq 1
$device(list) int *list;
	Gives monitor a list of addresses and values to be plugged into
	those values when the job terminates.
	If list=0, discard any previous DEVICE list.
				.endc

$DEVICE::
	.device	#emtarea,2(sp)
	return
.end

DSTATU.MAC
.Title	$DSTATUS - Return Device Status Information
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.dstatus

.Psect	tsx$c

				.If eq 1
$dstatus("dev:",block)	int *block;
	Returns information concerning dev: into block.
				.endc

$DSTATUS::
	mov	2(sp),r1
	call	r50		;Use CVLLIB routine to get rad50 name
	mov	r0,device
	mov	4(sp),r1

	.dstatus r1,#device
	jmp	emtret

device:	0

.end

XDSTAT.MAC
.Title	$XDSTA - Return Device Status Information
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Mcall	.dstatus

.Psect	tsx$c

				.If eq 1
$xdsta(dev,block)	int dev, *block; - dev containing Rad-50 device name.
	Returns information concerning dev into block.
				.endc

$XDSTA::
	mov	2(sp),device
	mov	4(sp),r1

	.dstatus r1,#device
	jmp	emtret

device:	0

.end

ELAW.MAC
.Title	$ELAW - Eliminate a window
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.elaw

				.If eq 1
$elaw(block)	Eliminates window whose details are in the definition block.
				.endc

$ELAW::
	.elaw	#emtarea,2(sp)
	jmp	emtval
.end

ELRG.MAC
.Title	$ELRG - Eliminate a Region
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.elrg

				.If eq 1
$elrg(block)	int *block;
	Eliminates a region whose details are provided in the region
	definition block.
				.endc

$ELRG::
	.elrg	#emtarea,2(sp)
	jmp	emtval
.end

ENTER.MAC
.Title	$ENTER - Enter a File
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.enter

.Psect	tsx$c

				.If eq 1
$enter(chan,filename,size) int chan,size; char *filename;
	Enters the desired file.  If size=0, use half the largest area
	available as per usual RT-11 techniques.
				.endc

$ENTER::
	mov	r2,-(sp)
	mov	4+2(sp),r1	;Filename string
	mov	#file,r2	;Filename (rad50) block
	call	rftlb		;Use CVLLIB routine to decode filename
	mov	(sp)+,r2

	mov	file+10,r1	;See if file size specified
	bne	10$		;If so, use it.
	mov	6(sp),r1	;Otherwise, use one provided.
10$:
	.enter	#emtarea,2(sp),#file,r1
	jmp	emtval

file:	.blkw	5

.end

XENTER.MAC
.Title	$XENTE - Enter a File
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Mcall	.enter

.Psect	tsx$c

				.If eq 1
$xenter(chan,filename,size) int chan,filename[4],size;
	Filename is 4 words in radix-50.
	Enters the desired file.  If size=0, use half the largest area
	available as per usual RT-11 techniques.
				.endc

$XENTE::
	.enter	#emtarea,2(sp),4(sp),6(sp)
	jmp	emtval

.end

FETCH.MAC
.Title	$FETCH - Fetch a Handler
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.fetch,.dstatus

.Psect	tsx$c

				.If eq 1
$fetch("dev",&addr) Fetches the handler for that device if that handler is not
	already loaded, putting the address (if memory was required for the
	fetch) into addr.
				.endc

$FETCH::
	clr	@4(sp)		;Assume loaded until proven otherwise.

	mov	2(sp),r1	;Get device name
	call	r50		;Use CVLLIB routine for decoding
	mov	r0,device

	.dstatus #block,#device
	bcs	bad

	tst	block+4		;Is it loaded anyway?
	bne	ok		;OK.

	tst	tsx$$		;If tsx, no fetches.
	beq	ok

	mov	block+2,-(sp)	;Size of handler in bytes
	call	malloc		;Get block of memory (check whether bytes or
				; words)
	tst	r0		;See if we got what we wanted.
	beq	bad		;Whoops.

	mov	r0,r1		;Save address for fetch,
	mov	r0,@4(sp)	; and for later release.

	.fetch	r1,#device
	jmp	emtval
ok:
	clr	r0
	return
bad:
	mov	#2,r0		;Impossible FETCH error -> something else
	return			; wrong.

device:	0
block:	.blkw	4

.end

XFETCH.MAC
.Title	$XFETC - Fetch a Handler
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Mcall	.fetch,.dstatus

.Psect	tsx$c

				.If eq 1
$xfetc($rad50("dev"),&addr)
	Fetches the handler for that device if that handler is not
	already loaded, putting the address (if memory was required for the
	fetch) into addr.
				.endc

$XFETC::
	clr	@4(sp)		;Assume loaded until proven otherwise.
	mov	2(sp),device	;Get device name

	.dstatus #block,#device	;Make sure it's a valid device
	bcs	bad

	tst	block+4		;Is it loaded anyway?
	bne	ok		;OK.

	tst	tsx$$		;If tsx, no fetches.
	beq	ok

	mov	block+2,-(sp)	;Size of handler in bytes
	call	malloc		;Get block of memory (check whether bytes or
				; words)
	tst	r0		;See if we got what we wanted.
	beq	bad		;Whoops.

	mov	r0,r1		;Save address for fetch,
	mov	r0,@4(sp)	; and for later release.

	.fetch	r1,#device
	jmp	emtval
ok:
	clr	r0
	return
bad:
	mov	#2,r0		;Impossible FETCH error -> something else
	return			; wrong.

device:	0
block:	.blkw	4

.end

FPROT.MAC
.Title	$FPROT - Handle File Protection
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.fprot

.Psect	tsx$c

				.If eq 1
$fprot("Filename",n) int n;
	If n=0, unprotect file; if N=1 protect file.
				.endc

$FPROT::
	mov	r2,-(sp)
	mov	2+2(sp),r1	;Filename
	mov	#file,r1
	call	rftlb		;Use CVLLIB routine for filename decoding
	mov	(sp)+,r2

	call	unuchn		;Get unused channel

	.fprot	#emtarea,r1,#file,4(sp)
	jmp	emtval

file:	.blkw	5

.end

XFPROT.MAC
.Title	$XFPROT - Handle File Protection
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Mcall	.fprot

.Psect	tsx$c

				.If eq 1
$xfpro(filename,n) int filename[4],n; - with filename in radix-50
	If n=0, unprotect file; if N=1 protect file.
				.endc

$XFPRO::
	call	unuchn		;Get unused channel

	.fprot	#emtarea,r1,2(sp),4(sp)
	jmp	emtval

.end

GMCX.MAC
.Title	$GMCX - Return Mapping Status of Extended Memory Window
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.gmcx

.Psect	tsx$c

				.If eq 1
$gmcx(block) int *block;
	Returns in relevant location in window definition block the status
	of that particular window.
				.endc

$GMCX::
	.gmcx	#emtarea,2(sp)
	jmp	emtval

.end

GTIM.MAC
.Title	$GTIM - Return System Time
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.gtim

.Psect	tsx$c

				.If eq 1
$gtim(&time) long time;
	Returns RT-11 format system time into time.
				.endc

$GTIM::
	.gtim	#emtarea,2(sp)
	return
.end

GTJB.MAC
.Title	$GTJB - Return Job Information
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.gtjb

.Psect	tsx$c

				.If eq 1
$gtjb(block)	int *block;
	Returns into block details of the job whose number is provided in
	the first word of the block.
				.endc

$GTJB::
	.gtjb	#emtarea,2(sp)
	jmp	emtval

.end

GTLIN.MAC
.Title	$GTLIN - Use the GTLIN request
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.gtlin

			.if eq 1
$gtlin(&line,&prompt);	Returns the terminal's line in &line.
			.endc
$GTLIN::
	mov	2(sp),r0
	mov	4(sp),r1
	.gtlin	r0,r1
	return

.end

GVAL.MAC
.Title	$GVAL - Return Monitor Value
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
int $gval(n) int n;	Returns monitor offset n.
				.endc
.Mcall	.gval

$GVAL::
	mov	2(sp),r1
	bic	#1,r1		;RT bug -> crash otherwise
	.gval	#emtarea,r1
	bit	#1,r1
	beq	10$
	bicb	r0,r0		;If odd loc, only give him that byte
	swab	r0
10$:	return
.end

HERR.MAC
.Title	$HERR - Don't Trap Monitor Errors
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.herr

.Psect	tsx$c

				.If eq 1
$herr()	- converse of $serr()
				.endc

$HERR::
	.herr
	return
.end

LOCK.MAC
.Title	$LOCK - Lock the USR
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.lock

.Psect	tsx$c

				.If eq 1
$lock() - locks the USR
				.endc

$LOCK::
	.lock
	return
.end

LOOKUP.MAC
.Title	$LOOKUP - Lookup a file
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.lookup

.Psect	tsx$c

				.If eq 1
$lookup(chan,"filename",&size) int chan, size;
	Looks up the file, using the channel provided, and returning the
	size in blocks in size.
				.endc

$LOOKUP::
	mov	r2,-(sp)
	mov	4+2(sp),r1	;Filename
	mov	#file,r2
	call	rftlb		;Use CVLLIB routine for filename decoding
	mov	(sp)+,r2

	.lookup	#emtarea,2(sp),#file
	bcs	10$
	mov	r0,@6(sp)	;Put in size if OK
10$:	jmp	emtval

file:	.blkw	5

.end

XLOOKU.MAC
.Title	$XLOOK - Lookup a file
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Mcall	.lookup

.Psect	tsx$c

				.If eq 1
$xlook(chan,filename,&size) int chan, filename[4], size;
	Uses the filename as 4 radix-50 words.
	Looks up the file, using the channel provided, and returns the
	size in blocks in size.
				.endc

$XLOOK::
	.lookup	#emtarea,2(sp),4(sp)
	bcs	10$
	mov	r0,@6(sp)	;Put in size if OK
10$:	jmp	emtval

.end

MAP.MAC
.Title	$MAP - Map a Previously Defined Address Window
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.map

.Psect	tsx$c

				.If eq 1
$map(block) int *block;
	Maps the window using the information in the window definition block.
				.endc

$MAP::
	.map	#emtarea,2(sp)
	jmp	emtval
.end

MRKT.MAC
.Title	$MRKT - Schedule a Completion Routine after Elapsed Time
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.mrkt

.Psect	tsx$c

				.If eq 1
$mrkt(&time,crtn,id,&mrtn) long time; int crtn(), id, mrtn;
	NOTE THE "&" BEFORE THE TIME!
	Schedules routine crtn(arg_r0,arg_r1) to be run after time ticks
	have elapsed, using id for identification of this particular request.
	Returns address of macro "pre"completion routine in mrtn, for use with
	cmkt.
				.endc

$MRKT::
	mov	4(sp),r1
	call	cmpset		;Get macro completion routine

	.mrkt	#emtarea,2(sp),r1,6(sp)
	bcc	10$
	jmp	emtwhoops	;Failed - don't want completion routine
10$:
	mov	r1,@10(sp)	;Save macro completion routine address
	jmp	emtval

.end

PEEK.MAC
.Title	$PEEK - Returns low memory address
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.peek

.Psect	tsx$c

				.If eq 1
$peek(addr)
				.endc

$PEEK::
	.peek	#emtarea,2(sp)
	return
.end

POKE.MAC
.Title	$POKE - Deposit value into low memory
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.poke

.Psect	tsx$c

				.If eq 1
$poke(addr,value) int *addr, value;
	Puts value into addr.
				.endc

$POKE::
	.poke	#emtarea,2(sp),4(sp)
	return
.end

PRINT.MAC
.Title	$PRINT - Print a line to the terminal
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.print

$PRINT::
	.print	2(sp)
	return

.end

PROTEC.MAC
.Title	$PROTECT - Protect a Vector
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.protect

.Psect	tsx$c

				.If eq 1
$protect(vector) int vector;
	Protects the locations vector and vector+2.
				.endc

$PROTECT::
	.protect #emtarea,2(sp)
	jmp	emtval
.end

PURGE.MAC
.Title	$PURGE - Purge a Channel
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.purge

.Psect	tsx$c

				.If eq 1
$purge(chan) int chan;
				.endc

$PURGE::
	.purge	2(sp)
	return
.end

RCTRLO.MAC
.Title	$RCTRLO - Clear Control-O
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.rctrlo

$RCTRLO::
	.rctrlo
	return

.end

READ.MAC
.Title	$READ - Read from a Channel, without waiting
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.read

.Psect	tsx$c

				.If eq 1
$read(chan,buf,wcnt,blk,&nread) int chan, *buf, wcnt, blk, nread;

	nread gets actual number of words read.
				.endc

$READ::
	.read	#emtarea,2(sp),4(sp),6(sp),10(sp)
	bcs	10$
	mov	r0,@12(sp)
10$:	jmp	emtval

.end

READC.MAC
.Title	$READC - Read, Scheduling Completion Routine
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.readc

.Psect	tsx$c

				.If eq 1
$readc(chan,buf,wcnt,crtn,blk,&nread) int chan,*buf,wcnt,crtn(),blk,nread;
	Reads from chan, scheduling completion routine crtn(arg_r0,arg_r1)

	nread receives actual number of words which will be read.
				.endc

$READC::
	mov	10(sp),r1
	call	cmpset		;Get a completion routine

	.readc	#emtarea,2(sp),4(sp),6(sp),r1,12(sp)
	bcs	10$
	mov	r0,@14(sp)
	jmp	emtval
10$:
	jmp	emtwhoops	;Error: don't want completion routine

.end

READW.MAC
.Title	$READW - Read and Wait
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.readw

.Psect	tsx$c

				.If eq 1
$readw(chan,buf,wcnt,blk,&nread) int chan, *buf, wcnt, blk, nread;
	Reads from chan, waiting until read is completed.
				.endc

$READW::
	.readw	#emtarea,2(sp),4(sp),6(sp),10(sp)
	bcs	10$
	mov	r0,@12(sp)
10$:
	jmp	emtval

.end

RELEAS.MAC
.Title	$RELEAS - Release a Handler
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.releas

.Psect	tsx$c

				.If eq 1
$releas("dev",addr)
	Releases a device handler previously loaded by $fetch.  The addr arg
	must be the address returned by $fetch.
				.endc

$RELEAS::
	tst	tsx$$
	beq	10$
	clr	r0
	return
10$:
	mov	4(sp),r0
	beq	20$

	mov	r0,-(sp)
	call	mfree
	tst	(sp)+
20$:
	mov	2(sp),r1
	call	r50

	.releas	r0
	jmp	emtval

.end

XRELEA.MAC
.Title	$XRELE - Release a Handler
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Mcall	.releas

.Psect	tsx$c

				.If eq 1
$xrele($rad50("dev"),addr)
	Releases a device handler previously loaded by $fetch or $xfetch.
	The addr arg must be the address returned by $fetch or $xfetch.
				.endc

$XRELE::
	tst	tsx$$
	beq	10$
	clr	r0
	return
10$:
	mov	4(sp),r0
	beq	20$

	mov	r0,-(sp)
	call	mfree
	tst	(sp)+
20$:
	mov	2(sp),r0

	.releas	r0
	jmp	emtval

.end

RENAME.MAC
.Title	$RENAME - Rename a File
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1a	18-Feb-89	TSCLIB Routine
; Whoops - it didn't ignore the second filename.
.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.rename

.Psect	tsx$c

				.If eq 1
$rename("filename","newfilename");
				.endc

$RENAME::
	mov	r2,-(sp)
	mov	#file1,r2
	mov	2(sp),r1
	call	rftlb		;Use CVLLIB to decode filenames

	mov	#file2,r2
	mov	4(sp),r1
	call	rftlb
	mov	(sp)+,r2

	mov	file1,file2	;Ignore second device name

	call	unuchn

	.rename	#emtarea,r1,#file1
	jmp	emtval

file1:	.blkw	4		;FROM filename
file2:	.blkw	5		;TO filename (extra word for RF to put size)

.end

XRENAM.MAC
.Title	$XRENA - Rename a File
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	18-Feb-89	TSCLIB Routine

.Mcall	.rename

.Psect	tsx$c

				.If eq 1
$xrena(oldfilename,newfilename); int oldfilename[4], newfilename[4]
		with the filenames in radix50.
				.endc

$XRENA::
	mov	#file1,r1

	mov	2(sp),r0
	mov	(r0)+,(r1)+	;Old device
	mov	(r0)+,(r1)+	;    filename
	mov	(r0)+,(r1)+
	mov	(r0),(r1)+	;    extension

	mov	4(sp),r0
	mov	(r0)+,(r1)+	;New device
	mov	(r0)+,(r1)+	;    filename
	mov	(r0)+,(r1)+
	mov	(r0),(r1)	;    extension

	mov	file1,file2	;Ignore second device name.

	call	unuchn

	.rename	#emtarea,r1,#file1
	jmp	emtval

file1:	.blkw	4		;FROM filename
file2:	.blkw	4		;TO filename

.end

REOPEN.MAC
.Title	$REOPEN - Reopen a Saved Channel
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.reopen

.Psect	tsx$c

				.If eq 1
$reopen(chan,block) int chan, *block;
	Reopens a channel using previously saved channel information.
				.endc

$REOPEN::
	.reopen #emtarea,2(sp),4(sp)
	jmp	emtval
.end

SAVEST.MAC
.Title	$SAVESTATUS - Save Channel Status
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.Savestatus

.Psect	tsx$c

				.If eq 1
$savestatus(chan,block) int chan, *block;
	Saves channel information into block.
				.endc

$SAVESTATUS::
	.savestatus #emtarea,2(sp),4(sp)
	jmp	emtval
.end

SCCA.MAC
.Title	$SCCA - Handle Control-C Under RT/TSX
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.scca
				.if eq 1
$scca(loc) int *loc;	Allows control-C intercept, using loc as flag word.
			If loc=0, disables control-C trapping.
				.endc
$SCCA::
	.scca	#emtarea,2(sp)
	return
.end

SDTTM.MAC
.Title	$SDTTM - Set date and time
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.sdttm

.Psect	tsx$c

				.If eq 1
$sdttm(date,time) int date; long time;
	Sets system date and time.
				.endc

$SDTTM::
	mov	sp,r1	;Stack has everything in required format.
	add	#2,r1
	.sdttm	#emtarea,r1
	return

.end

SERR.MAC
.Title	$SERR - Trap "Serious" Errors
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.serr
				.if eq 1
$serr();	Allows "Serious" Errors to be returned to programme
				.endc
$SERR::
	.serr
	return
.end

SFDAT.MAC
.Title	$SFDAT - Modify File Creation Date
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.sfdat

.Psect	tsx$c

				.If eq 1
$sfdat("filename",date) int date;
				.endc

$SFDAT::
	mov	r2,-(sp)
	mov	#file,r1
	mov	2+2(sp),r1
	call	rftlb		;Use CVLLIB to decode filename
	mov	(sp)+,r2

	call	unuchn		;Get unused channel

	.sfdat	#emtarea,r1,#file,4(sp)
	jmp	emtval

file:	.blkw	5

.end

XSFDAT.MAC
.Title	$XSFDAT - Modify File Creation Date
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.Mcall	.sfdat

.Psect	tsx$c

				.If eq 1
$xsfdat(filename,date) int filename[4],date; - filename in radix-50
				.endc

$XSFDA::
	call	unuchn		;Get unused channel

	.sfdat	#emtarea,r1,2(sp),4(sp)
	jmp	emtval
.end

SFPA.MAC
.Title	$SFPA - Set Floating-Point Exception Trap
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.sfpa

.Psect	tsx$c

				.If eq 1
$sfpa(routine) int routine();
				.endc

$SFPA::
	.sfpa	#emtarea,2(sp)		;Note - does not need CMPSET routine
	return

.end

SPFUN.MAC
.Title	$SPFUN - Allow SPFUNs From "C"
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1a	13-Jun-87	TSCLIB Routine
;	Completion routines rewritten
.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.spfun
				.if eq 1
$spfun(chan,func,buf,wcnt,blk,crtn)
	int chan, func, *buf, int wcnt, blk, crtn();

		As per RT spfuns, using the channel used by the file
		specified as FILE *file; spfun(file->io_lun, etc).

		If crtn is zero, the programme will wait for the spfun
		completion.  If 1, there will be no waiting (and no
		completion routine either).

		Note that this routine only allows six completion routines
		to be outstanding at one time before they start treading
		on each other's toes.

		SPFUN with func=0 degenerates into READ/W/C if wcnt is
		positive, and WRITE/W/C if wcnt is negative.  I do not
		know if TSX checks for these cases.
				.endc
$SPFUN::
	mov	14(sp),r1	;See if he wants a completion routine
	cmp	r1,#1
	blos	10$		;No.

	call	cmpset		;Puts completion routine address into
				; a macro routine, and returns that address
10$:	
	.spfun	#emtarea,2(sp),4(sp),6(sp),10(sp),12(sp),r1
	bcc	30$		;If ok, fine.
	cmp	r1,#1		;If not, see if needed completion routine
	blos	20$		;Didn't - just head off with carry set.
	jmp	emtwhoops	;Did: clear completion routine table first.

20$:	sec
30$:	jmp	emtval

.end

SPND.MAC
.Title	SPND - SPND & RSUM for C programmes
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.spnd,.rsum

$SPND::	.spnd
	return

$RSUM::	.rsum
	return
.end

TLOCK.MAC
.Title	$TLOCK - Lock USR, returning if not available
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.tlock

.Psect	tsx$c

				.If eq 1
$tlock();
				.endc

$TLOCK::
	.tlock
	jmp	emtret
.end

TRPSET.MAC
.Title	$TRPSET - Intercept traps to 4 and 10
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.trpset

.Psect	tsx$c

				.If eq 1
$trpset(routine) int routine();
				.endc

$TRPSET::
	mov	2(sp),trpadr
	.trpset	#emtarea,#trprtn
	return

trprtn:
	mov	#0,-(sp)	;Calls routine with argument of 0 or 1
	adc	(sp)		; depending upon whether trap to 4 or trap
	call	@#0		; to 10 caused the trap.
trpadr = .-2
	tst	(sp)+
	return

.end

TTINR.MAC
.Title	$TTINR - Return character from terminal
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.ttinr

$TTINR::
	.ttinr
	bcc	10$
	mov	#-1,r0
10$:	return
.end

TTYIN.MAC
.Title	$TTYIN - Get 1 character from the TT
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	23-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.ttyin

$TTYIN::
	.ttyin
	return
.end

TTYOU.MAC
.Title	$TTYOU - Send 1 character to the TT
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	24-May-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.ttyou

$TTYOU::
	.ttyou	2(sp)
	return

.end

TWAIT.MAC
.Title	$TWAIT - Wait a While
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.twait

.Psect	tsx$c

				.If eq 1
$twait(&time) long time;
	Note the "&"!
				.endc

$TWAIT::
	.twait	#emtarea,2(sp)
	return
.end

UNLOCK.MAC
.Title	$UNLOCK - Unlock the USR
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.unlock

.Psect	tsx$c

				.If eq 1
$unlock() Unlocks the USR
				.endc

$UNLOCK::
	.unlock
	return
.end

UNMAP.MAC
.Title	$UNMAP - Unmaps a Virtual Address Window
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.unmap

.Psect	tsx$c

				.If eq 1
$unmap(block)	Unmaps the window whose details are in the window control
		block.
				.endc

$UNMAP::
	.unmap	#emtarea,2(sp)
	jmp	emtval
.end

UNPROT.MAC
.Title	$UNPROTECT - Unprotect a Vector
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.unprotect

.Psect	tsx$c

				.If eq 1
$unprotect(vector) int vector;
				.endc

$UNPROTECT::
	.unprotect #emtarea,2(sp)
	return
.end

WAIT.MAC
.Title	$WAIT - Wait for Channel I/O to Finish
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.wait

.Psect	tsx$c

				.If eq 1
$wait(chan);	Waits for I/O, returning error status.
				.endc

$WAIT::
	.wait	2(sp)
	jmp	emtval
.end

WRITC.MAC
.Title	$WRITC - Write, Scheduling a Completion Routine
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.writc

.Psect	tsx$c

				.If eq 1
$writc(chan,buf,wcnt,crtn,blk,&nwrit) int chan,*buf,wcnt,crtn(),blk,nwrit;
	Writes to the channel, scheduling crtn(arg_r0,arg_r1) to be run
	upon completion of the writing.

	nwrit gets the actual number of words which will be written.
				.endc

$WRITC::
	mov	10(sp),r1
	call	cmpset		;Get a completion routine

	.writc	#emtarea,2(sp),4(sp),6(sp),r1,12(sp)
	bcs	10$
	mov	r0,@14(sp)
	jmp	emtval
10$:
	jmp	emtwhoops	;Error - won't need completion routine

.end

WRITE.MAC
.Title	$WRITE - Write, with no waiting
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.write

.Psect	tsx$c

				.If eq 1
$write(chan,buf,wcnt,blk,&nwrit) int chan, *buf, wcnt, blk, nwrit;
	Writes to channel, not waiting for I/O to complete.

	nwrit gets number of words which will actually be written
				.endc

$WRITE::
	.write	#emtarea,2(sp),4(sp),6(sp),10(sp)
	bcs	10$
	mov	r0,@12(sp)
10$:	jmp	emtval

.end

WRITW.MAC
.Title	$WRITW - Write and Wait
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.writw

.Psect	tsx$c

				.If eq 1
$writw(chan,buf,wcnt,blk,&nwrit) int chan, *buf, wcnt, blk, nwrit;
	Writes to the channel, waiting for completion of the I/O.

	nwrit gets actual number of words written.
				.endc

$WRITW::
	.writw	#emtarea,2(sp),4(sp),6(sp),10(sp)
	bcs	10$
	mov	r0,@12(sp)
10$:	jmp	emtval

.end

UNUCHN.MAC
.Title	UNUCHN - Return an unused channel (called by other TSCLIB routines)
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	23-Jun-87	TSCLIB Routine

.Psect	tsx$c

.Mcall	.cstat

;Returns in R1 and R0 the value of an unused channel number.  If none
; available, returns zero, which, being a used channel, will cause the
; subsequent EMT to prang.

UNUCHN::
	clr	r1
10$:	.cstat	#emtarea,r1,#block
	bcs	20$
	inc	r1
	cmp	r1,#17
	blos	10$
	clr	r1
20$:	mov	r1,r0		;So can be called from C routines also.
	return

block:	.blkw	6

.end

EMTRET.MAC
.Title	EMTRET - Return 0 (FALSE) if CS, 1 (TRUE) if CC
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V2	22-Jun-87	TSCLIB Routine

.Psect	tsx$c

				.if eq 1
End-point of several routines.  Performs an EMT 375, and returns 1 if
an error occurred, 0 if no error occurred.

EMTRET performs the EMT 375;
EMTRES simply sets the value.
				.endc
EMTRET::
	emt	375
EMTRES::
	bic	r0,r0
	bcs	10$
	inc	r0
10$:	return

.end

EMTEMT.MAC
.Title	EMTEMT - Perform EMT & Return Error Value if Necessary
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V2	23-Jun-87	TSCLIB Routine

.Psect	tsx$c

errbyt=52
				.if eq 1
End-point of several routines.  Enter at EMTEMT if EMT 375 is required;
at EMTVAL if not.  If no error is returned, the function returns 0.
If an error is returned, it is dealt with as follows:
	If error byte positive or zero, return <1+error value>
	If error byte negative, return negative value.
				.endc

EMTEMT::
	emt	375

EMTVAL::
	bic	r0,r0
	bcs	10$
	return
10$:
	movb	@#errbyt,r0
	bmi	20$
	inc	r0
20$:	return

.end

EMTARE.MAC
.Title	EMTAREA - Area for EMTs
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	3-May-87	TSCLIB Routine

.Psect	tsx$c

EMTAREA::
	.blkw	7

.end

CMPSET.MAC
.Title	CMPSET - Set up Completion Routine
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	13-Jun-87	TSCLIB Routine

.Mcall	.print,.exit,.rctrlo

.Psect	tsx$c

			.If eq 1
CMPSET allows for CMPNUM number of simultaneous completion routines.  These
routines must be in the form of

routine(arg_r0, arg_r1)		int r0,r1; {}

with the two arguments being the contents of registers R0 and R1 respectively
when the completion routine is called from the monitor.

Should there be no room for the required number of completion routines,
this routine will need to be rebuilt with a larger value for CMPNUM.


EMTWHOOPS allows a deliberate error return from routines which have set up
	a routine using CMPSET and find that it prangs, thereby not requiring
	the completion routine.
				.endc


userrb=53	;User error byte.
error$=4	;Error bit.

.iif ndf CMPNUM, CMPNUM=10.

.globl	moffs	;Need to have available for $cmkt routine.

CMPSET::
	mov	r2,-(sp)
	mov	r3,-(sp)

	mov	#mm1+moffs,r2	;First completion routine address
	mov	#CMPNUM,r3
10$:
	tst	(r2)		;Available?
	beq	30$		;Yes.
20$:	add	#mm2-mm1,r2	;No - look at next one.
	dec	r3
	bne	10$

	.rctrlo
	.print	#nocmps
	bisb	#error$,@#userrb
	.exit
30$:
	inc	(r2)		;This nasty bit of code is to make sure that
	cmp	(r2),#1		; should a completion routine trying to use
	beq	40$		; this code at the same time as mainstream
	dec	(r2)		; code, we should not get two completion
	br	20$		; routines trying to take up the same slot.
40$:
	mov	r1,(r2)		;Whew - should have ours and ours only now.

	mov	r2,r1		;Get macro routine address
	sub	#moffs,r1

	mov	(sp)+,r3
	mov	(sp)+,r2
	return


EMTWHOOPS::			;For routines where the EMT prangs and thus
	clr	moffs(r1)	; won't be requiring the completion routine.
	sec
	jmp	emtval

.Sbttl	Completion routines - macro portions

n=0

.macro	mm	arg
mm'arg:
.endm

.rept	CMPNUM
n=n+1

mm	\n			;Define label for this completion routine
10$:	mov	r1,-(sp)	;Set up two arguments
	mov	r0,-(sp)

	call	@#0		;Address is plugged in here.
moffs=: .-2-10$

	clr	10$+moffs	;Make this routine useable again.
	cmp	(sp)+,(sp)+	;Tidy the stack.
	return
.endr

nocmps:	.asciz	/?TSCLIB-F-Too many completion routines called./
	.even

.end

CRET.MAC
.Title	CRET - C subroutine linkages for Programmes with Macro main & C subs
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	23-Jun-87	TSCLIB Routine

csv$::
	mov	r5,r0
	mov	sp,r5
	mov	r4,-(sp)
	mov	r3,-(sp)
	mov	r2,-(sp)
	call	(r0)

cret$::
	mov	r5,r2
	mov	-(r2),r4
	mov	-(r2),r3
	mov	-(r2),r2
	mov	r5,sp
	mov	(sp)+,r5
	return

.end

RFTLB.MAC
.Title	RFTLB - Read filename for TSCLIB
.Nlist	bex,toc,sym
.Enabl	lc,gbl

.Sbttl	V1	26-Jun-87	TSCLIB Routine

.Psect	tsx$c

			.if eq 1
Called by routines which require a filename decoded from an ascii string,
this routine forces DK: if no device is specified, unless no filename was
specified either in which case it is left null.  (This protects the user
from scribbling all over DK: inadvertently - he can do it deliberately if
he must!)

This routine calls the CVLLIB routine RF.
			.endc

RFTLB::
	call	rf

	tst	2(r2)		;Any filename?
	beq	10$		;No - who cares if no device either?
	tst	(r2)		;No device?
	bne	10$
	mov	#^rDK,(r2)	;No - use DK:
10$:	return

.end

XRAD50.MAC
.Title	$RAD50 - C radix50 routine
.Nlist	bex,toc,sym
.Enabl	lsb

.Sbttl	V1	17-Feb-89	TSCLIB Routine

.globl	r50	;Uses CVLLIB routine for Radix-50 decoding.

		.if eq 1
i=$rad50("dev"); allows easy use of Radix-50 characters from C programmes.
		.endc

$RAD50::
	mov	2(sp),r1
	jmp	r50
.end

COMPRS.C
/* COMPRS - For compressing & expanding multiple library files

	V1	13-Sep-84	C G Wilson, Charleville, Australia.

This is a simple programme for combining multiple tiny files into one
large file to save space and make handling convenient.  The compressed
file may be edited with any ordinary editor, but two control characters
are used within the compressed file.  These characters may not be
present within any of the files comprising the compressed file.

The format is:
		(^A is control-A, [ascii 1], and ^Z is control-Z [ascii 32])


		^Afilename
		<text of file, following <cr><lf> after filename>
		^Z (with a <cr><lf> following the ^Z.

		^Anext filename
		etc


If one of the files provided in the list of files to be compressed is
already a compressed file itself, it will not have its name included in
the new compressed file.  The new compressed file will contain the contents
of the old compressed file as though the names of the individual files
had been used.
*/

#include <stdio.h>

#define a_control 1
#define z_control 032
#define tab 011
#define cr 015
#define lf 012

#define userrb 053
#define error_ 4

FILE *inputfile, *outputfile;

char	infilename[30],		/* Input file name */
	outfilename[30],	/* Output file name */
	line[120],		/* User's input line */
	segmentname[30],	/* Input filename without the device */
	*filpnt,		/* Pointer within "line" to filename */
	device[20],		/* Used in filename decoding */
	filename[20],		/* ibid */
	extension[20],		/* ibid */
	defdev[4],		/* Default input device */
	defext[4],		/* Default input extension */
	*p1,*p2;

int	debug;			/* Lists programmes transferred if TRUE */

$$narg=1;			/* Suppress ARGV message */


main()
{
    for(;;)
    {	cgtlin(&line,"COMPRS V1: Compress or Expand? (C or E): \200");
	debug = toupper(*(line+1)) == 'D';
	if(toupper(*line)=='C')compress();
	if(toupper(*line)=='E')expand();
	if(toupper(*line)=='X')exit();
    }
}
/* *************************** C O M P R E S S **************************** */

char promp1[]="Input files (blank line when finished):> \200";
char promp2[]="> \200";


compress()
{
	int	acompressed,	/* TRUE if input file already compressed */
		ch;		/* Needs to be INT for <EOF> */
	char *prompt;		/* Prompt for input files */

	prompt=promp1;

	*defdev=0;		/* Default device is DK (ie null) */
	*defext=0;		/* Default extension is nothing */

	cgtlin(&line,"Output File: \200");
	if(*line==0)return;

	if( (outputfile=fopen(line,"wn"))==0 )
	{	printf("?Comprs-F-Cannot write file %s\n",line);
			goto x;
	} else
	{
		for(;;)
		{	cgtlin(&line,prompt);
			prompt=promp2;
			if(*line==0){fend(outputfile); return;};
			filpnt=line;

			for(;;)
			{
				while ( (*filpnt==' ') || (*filpnt=='\t') ) filpnt++; /* Scrub spaces & tabs */
				if(*filpnt==0)break;

				/* Note that the device names and extensions are "sticky" - ie remain as the
				defaults for subsequent files */

				for(p1=filename ; isfile(*filpnt) ; ) *(p1++)=*(filpnt++); /* Get next filename */
				*p1=0;
				if(*filpnt == ':') /* if ":" delimited, then have device rather than filename */
				{	filpnt++;  /* so copy it across then go for the filename itself */
					for(p1=filename, p2=device ; 0 != (*p2=*p1) ; p1++, p2++);
					for(p1=filename ; isfile(*filpnt) ; ) *(p1++) = *(filpnt++);
					*p1=0;
				}
				if(*filpnt == '.') /* If "." extension has been specified */
				{	filpnt++;
					for(p1=extension ; isfile(*filpnt) ; ) *(p1++) = *(filpnt++);
					*p1=0;
				}
				if(*filpnt==',') filpnt++; /* Skip "," delimiter */

				/* Set up filename for FOPEN by concatenating the three fields */
				p1=infilename;
				if(*device != 0)
				{	for(p2=device ; *p2 != 0 ; *(p1++)=*(p2++) );
					*(p1++)=':';
				}
				for(p2=filename ; *p2 != 0 ; *(p1++) = *(p2++) );
				*(p1++)='.';
				for(p2=extension ; 0 != ( *(p1++) = *(p2++) ) ; );

				/* Set up filename sans device for insertion into compressed file */
				p1=segmentname;
				for(p2=filename ; *p2 != 0 ; *(p1++) = *(p2++) );
				*(p1++)='.';
				for(p2=extension ; 0 != ( *(p1++) = *(p2++) ) ; );

				if(*segmentname==0)
				{	printf("?Comprs-F-File must not have a null name\n");
					goto x;
				}
				if(debug) {printf("%s\n",segmentname); fflush(stdout);};

				if( (inputfile=fopen(infilename,"rn")) == 0 )
				{	printf("?Comprs-F-Cannot find file %s\n",infilename);
					goto x;
				} else
				{	ch = getcnz(inputfile);
					if(ch==EOF)
					{	printf("?Comprs-I-Empty File %s\n",infilename);
						goto x;
					}
					acompressed = (ch == a_control);
					putc(a_control,outputfile);
					if ( ! acompressed)	/* If not compressed file, put the segment name header in */
					{	p1=segmentname;
						while(*p1 != 0) putc (*(p1++),outputfile);
						putc(cr,outputfile); putc(lf,outputfile);
						putc(ch,outputfile);
					}
					for(;;)
					{	ch = getcnz(inputfile);		/* Now transfer the file contents */
						if (ch == EOF) break;
						putc(ch,outputfile);
						if ( (ch == a_control) && acompressed && debug )
						{	putc(tab,stdout);	/* Type routine names if DEBUG */
							do
							{	ch=getcnz(inputfile);
								putc(ch,outputfile);
								putc(ch,stdout);
							} while ((ch!=EOF) && (ch!=lf));
							fflush(stdout);
						}
					}

					if ( ! acompressed)
					{	putc(z_control,outputfile);	/* Control-z terminates segment */
						putc(cr,outputfile); putc(lf,outputfile);
					}
					fclose(inputfile);
				}
			}
		}
	}
x:	fflush(stdout);
	fclose(inputfile);
	fend(outputfile);
	bad();
	return;
}
/* ***************************** E X P A N D ****************************** */

expand()
{
	register int i,c;

	cgtlin(&line,"Input file: \200");
	if( 0 == (inputfile = fopen(line,"rn") ) )
	{	printf("?Comprs-F-Cannot read file %s\n",line);
		goto x;
	} else
	{	cgtlin(&line,"Onto device: \200");
		for(i=0;line[i]!=0;i++)
		{	if(line[i]==':')break;
		}
		if(i!=0)
		{	line[i++]=':';		/* Get device name terminated by a colon unless null */
			line[i]=0;
		}

		for(;;)
		{
			c = getcnz(inputfile);
			if(c!=EOF)
			{
				if(c!=a_control) /* Require first character to be control-A */
				{	printf("?Comprs-F-Input file not in proper format\n");
					goto x;
				} else
				{	for(i=0,p1=outfilename; line[i]!=0; i++,p1++) *p1=line[i];
					while ( cr != (c = getcnz(inputfile) ) ) *(p1++)=c;
					*p1=0;
					getcnz(inputfile); /* Scrub <lf> after <cr> */
					if(debug) {printf("%s\n",outfilename); fflush(stdout);};

					if ( 0 == (outputfile = fopen(outfilename,"wn") ) )
					{	printf("?Comprs-F-Cannot write file %s\n",outfilename);
						goto x;
					} else
					{	while ( c=getcnz(inputfile), ((c!=z_control) && (c!=EOF)) ) putc (c,outputfile);
						getcnz(inputfile); getcnz(inputfile);
						fend(outputfile);
					}
				}
			} else
			{	fclose(inputfile);
				return;
			}
		}
	}
x:	fflush(stdout);
	fclose(inputfile);
	fend(outputfile);
	bad();
	return;
}
/* Assorted subroutines */

getcnz(afile) FILE *afile;		/* Get a non-zero character from file */
{
	register int c;

	while ( 0== (c=getc(afile)) );
	return(c);
}


isfile(c) char c;	/* Return TRUE if  character valid in filename */
{
	return	( ( (c>='A') && (c<='Z') ) || ( (c>='a') && (c<='z') ) ||
		  ( (c>='0') && (c<='9') ) );
}


bad()	/* Set the monitor ERROR bit for RT-11 */
{
	* (char *) userrb = ( * (char *) userrb )  | error_ ;
}

fend(afile) FILE *afile;		/* Needed due to bug in Conroy C */
{
	fflush(afile);
	fclose(afile);		/* otherwise if STDOUT it doesn't get done */
}

