	.title		vterm - virtual terminal handler
	.enable		sup, debug
	.disable	global
	.ident		'VTERM 1.3'
;+
;	VTERM.MAR - Virtual terminal handler.
;
;	Written by:
;		Tom Gerhard
;		Advanced Data Management
;		15 Main Street
;		P.O. Box 601
;		Kingston,  NJ  08528
;		(609) 799-4600
;
; Vterm version 1.3
;
;   Files/Devices used:
;	VTERM$PORT  - Remote terminal port (the one used for dialing out)
;	SYS$COMMAND - Local terminal port
;	VTERM$INIT  - Initialization commands for VTERM
;	VTERMHLB    - Help library.  Default is SYS$HELP:.HLB
;
;   Logical names:
;	VTERM$PRIORITY (system table only) - base priority that VTERM should
;			set on entry.
;	VTERM$SPEED - default speed
;
;   Vterm commands:
;	EXIT
;			Exit from VTERM to DCL.
;
;	HELP
;			Display help for VTERM commands
;
;	SET BUFFER /REMOTE = dec-val
;			dec-val sets the size of the receive buffer for the
;			remote terminal.  Larger values decrease CPU use,
;			while smaller values give better 'feeling' interactive
;			response.  The default is 4, the maximum is 128.
;
;	SET COMMAND = dec-val
;			dec-val identifies the ASCII character that functions
;			as the VTERM escape character when typed at the local
;			terminal.  The default is 1 (control-A).
;
;	SET LOCAL_ECHO
;			Input from the local terminal should be echoed.
;			(Emulate terminal in half-duplex)
;
;	SET LOG file-name [/APPEND] [/PRINT]
;			file-name identifies the file that data received from
;			the remote terminal should be saved in.
;			If the optional APPEND qualifier is specified, the
;			new log will be appended to an existing file of the
;			same name if one exists.  If no file exists with the
;			same name, one is created.  If the optional PRINT
;			qualifier is specified, the file will be spooled to
;			default print queue when closed.
;
;	SET LOG /CLOSE [/PRINT]
;			The current log is closed, and if the optional
;			PRINT qualifier is specified, spooled to the
;			default print queue.
;
;	SET NOLOG
;			disables logging.
;
;	SET SPEED = dec-val
;			dec-val indicates the speed the remote port should be
;			set to.  Valid values are 110, 300, 1200, 2400, and
;			9600.  This command should be issued before any I/O
;			is attempted to the remote port.
;	STOP
;			Exit from VTERM to DCL.
;-
	$fabdef
	$iodef
	$namdef
	$rabdef
	$rmsdef
	$ssdef
	$tpadef
	$ttdef

	.external	lib$signal, lib$tparse, lib$put_output, -
			lbr$output_help, lib$get_input, sys$fao, lib$get_ef, -
			 vterm_sent

	.psect	$data, rd, wrt, noexe, long
;+
; TPARSE status block
;-
tparse_block:	.long	tpa$k_count0
		.blkl	tpa$k_count0
;+
; IOSBs
;-
in_iosb_tt:	.blkq	1		; Input from local
out_iosb_tt:	.blkq	1		; Output to local
in_iosb_rt:	.blkq	1		; Input from remote
out_iosb_rt:	.blkq	1		; Ouput to remote
;+
; Channels
;-
chan_tt:	.blkw	1		; Local terminal
chan_rt:	.blkw	1		; Remoter terminal
;+
; Control block for exit handler
;-
exh_block:	.long	0
		.address vterm$exit
		.long	1
		.address 1$
1$:		.blkl	1		; Reason for exit stored here
;+
; File/device names
;-
tt_name:	.ascid	'SYS$COMMAND'
rt_name:	.ascid	'VTERM$PORT'
ini_name:	.ascid	'VTERM$INIT'
;+
; Logical names
;-
vterm_speed:	.ascid	'VTERM$SPEED'
vterm_prio:	.ascid	'VTERM$PRIORITY'
;+
; Messages and prompts
;-
io_err_msg:	.ascid	'<*I/O ERROR*>'
vterm_prompt:	.ascii	<13><10>'Vterm: '
vterm_prompt_len: .word	.-vterm_prompt
;+
; RT buffer size adjustment parameters
;-
rt_adjust_freq	= 10
rt_adjust_val   =  4
rt_adjust_max   = 80
;+
; Buffers and control information
;-
in_len_tt:	.long	1		; Default read size for local
in_len_rt:	.long	4		; Default read size for remote
cur_len_rt:	.blkl	1		; Current read size for remote
rt_ok_reads:	.blkl	1		; Number of 'good' reads from RT
in_buff_tt:	.blkb	128		; Input buffer for local.
in_buff_rt:	.blkb	rt_adjust_max+rt_adjust_val
		. = in_buff_rt
		.ascii	<10><13>'VTERM - Ready'<13><10>
		init_msg_len	= .-in_buff_rt
		. = in_buff_rt + rt_adjust_max + rt_adjust_val
cmd_buffer:	.blkb	80			; Buffer for VTERM commands
cmd_buffer_len:	.long	80
rt_characteristics:	.blkb	12		; Characteristics buff for RT.
;+
; Miscellaneous
;-
temp_desc:	.blkq	1
trmdesc:	.blkq	1
trmdesc_addr:	.address trmdesc
esc_char:	.byte	^x01		; ^a
cr_char:	.byte	^x0D		; <CR>
status_flags:	.blkl	1
cmd_type:		.blkl	1	; tparse output field - command type
temp_val:	.blkl	1
def_pri:	.long	1
;+
; Log file buffering fields
;-
log_buffer_size		= 512
log_file_buffer:	.blkb	log_buffer_size
log_buffer_pos:		.blkl	1
log_buff_unused:	.blkl	1
log_file_name:		.blkb	nam$c_maxrss
log_file_desc:		.blkq	1
log_file_options:	.blkl	1
  log_append_v = 0
  log_append_m = 1@log_append_v
  log_print_v  = 1
  log_print_m  = 1@log_print_v
  log_close_v  = 2
  log_close_m  = 1@log_close_v
;+
; RMS data structures
;-
		.align	long
; Log file
log_fab:	$fab	rfm = VAR, rat = CR, -
			shr = <UPI,GET> -
			dnm = <VTERM.LOG> -
			nam = log_nam

log_rab:	$rab	fab = log_fab, rop = <EOF>

; The NAM block is required for spooling.
log_nam:	$nam	rsa = log_rsa, rss = nam$c_maxrss
log_rsa:	.blkb	nam$c_maxrss

; Initialization file
ini_fab:	$fab
ini_rab:	$rab	fab = ini_fab, ubf = cmd_buffer, usz = 80

	.psect	$code, rd, nowrt, exe

ending_v  	= 0
logging_v 	= 2
in_rt_cancel_v 	= 3
command_v	= 4
local_echo_v	= 6

ending_m  	= 1@ending_v
logging_m 	= 1@logging_v
in_rt_cancel_m 	= 1@in_rt_cancel_v
command_m	= 1@command_v
local_echo_m	= 1@local_echo_v

	.entry	vterm, ^m<r11>

	clrl	r11

	movl	in_len_rt, cur_len_rt
	movw	#log_buffer_size, log_buff_unused
	movab	log_file_buffer, log_buffer_pos

	$assign_s	devnam = tt_name, chan = chan_tt
	$assign_s	devnam = rt_name, chan = chan_rt

	movl	#tpa$m_abbrev, tparse_block+tpa$l_options

	pushl	#1200
	pushl	#0
	pushaq	vterm_speed
	calls	#3, convert_logical

	movl	r0, tparse_block+tpa$l_number
	callg	tparse_block, set_speed

	pushl	#0
	pushl	#^b110				; Search only system table
	pushaq	vterm_prio
	calls	#3, convert_logical

	tstl	r0
	beql	10$
	$setpri_s -
	   pri = r0 -
	   prvpri = def_pri
	$dclexh_s -
	   desblk = exh_block
10$:
	movb	ini_name, ini_fab+fab$b_fns
	movl	ini_name+4, ini_fab+fab$l_fna
	$open	fab = ini_fab
	blbc	r0, no_init
	$connect rab = ini_rab
next_init:
	$get	rab = ini_rab
	cmpl	r0, #rms$_eof
	beql	end_init
	movw	ini_rab + rab$w_rsz, in_iosb_tt+2
	bsbw	process_vterm_command
	brb	next_init
end_init:
no_init:
	movw	#init_msg_len, in_iosb_rt+2
	bsbw	write_tt

	bsbw	read_rt
read_tt_again:
	bsbw	read_tt

	$hiber_s

	bbcc	#command_v, status_flags, 80$
	bsbw	get_Vterm_command
	brb	read_tt_again
80$:
	bbc	#logging_v, status_flags, 90$
	bsbw	write_log_record
90$:
	ret

	.entry	in_ast_tt, ^m<>
;+
;   Issue write to remote device
;-
	movaq	in_iosb_tt, r1
	blbs	(r1), 20$
	brw	iosb_error
20$:
	cmpb	in_buff_tt, esc_char
	bneq	write_rt
	bisl	#command_m, status_flags
	$wake_s
	ret
write_rt:
	movzwl	in_iosb_tt+2, r0
	$qiow_s -
	   func = #IO$_WRITEVBLK!IO$M_NOFORMAT -
	   iosb = out_iosb_rt -
	   chan = chan_rt -
	   p1 = in_buff_tt -
	   p2 = r0 -
	   p4 = #0
	blbs	r0, 11$
	brw	qio_error
11$:
	movaq	out_iosb_rt, r1
	blbs	(r1), 12$
	cmpw	(r1), #ss$_timeout
	beql	12$
	brw	iosb_error
12$:
	bsbw	read_tt
	ret
	.entry	in_ast_rt, ^m<r2,r3,r4,r5>
;+
;   Issue write to local device
;-
	movaq	in_iosb_rt, r1
	blbs	(r1), 20$
	cmpw	(r1), #ss$_timeout
	beql	18$
	cmpw	(r1), #ss$_abort
	bneq	15$
	bbcc	#in_rt_cancel_v, status_flags, 15$
14$:	brw	90$
15$:
	movc3	io_err_msg, @io_err_msg+4, in_buff_rt
	movw	io_err_msg, in_iosb_rt+2
;+
; when a timeout or i/o error occurs, set the remote buffer size
; to the default value.
;-
18$:
	movl	in_len_rt, cur_len_rt
	clrl	rt_ok_reads
20$:
	aoblss	#rt_adjust_freq, rt_ok_reads, 22$
;+
; If enough (rt_adjust_freq) reads have completed without timeout,
; adjust the rt buffer size upward by rt_adjust_val
;-
	cmpl	cur_len_rt, #rt_adjust_max
	bgeq	22$
	addl	#rt_adjust_val, cur_len_rt
22$:
	tstw	in_iosb_rt+2
	bneq	25$
23$:	brw	90$				; No input - try again
25$:
	bsbw	write_tt
;+
;   Write data to log file buffer if logging is on
;-
	bbc	#logging_v, status_flags, 23$
	movzwl	in_iosb_rt+2, r0
	movab	in_buff_rt, r1
	movl	log_buff_unused, r4
	movl	log_buffer_pos, r5
50$:
	movtuc	r0, (r1), #0, tr_table, r4, (r5)
	bvs	70$
	movl	r5, log_buffer_pos
	movl	r4, log_buff_unused
	brb	90$
70$:
	cmpb	(r1), #^x08			; Backspace?
	bneq	75$
	decl	r5				; Backup one byte in buffer
	incl	r4				; One more byte avail in buffer
	incl	r1				; Skip past BS char
	decl	r0				; Skip over BS char
	bgtr	50$
	movl	r5, log_buffer_pos
	movl	r4, log_buff_unused
	brb	90$
75$:
	movl	r5, log_buffer_pos
	movl	r4, log_buff_unused
	pushl	r0
	pushl	r1
	bsbw	write_log_record
	popl	r1
	movab	log_file_buffer, r5
	movl	r5, log_buffer_pos
	movl	#log_buffer_size, r4
	movl	r4, log_buff_unused
	subl3	#1, (sp)+, r0
	beql	90$
	incl	r1
	brb	50$
;+ data remains that has not been processed - continue processing
90$:
	bsbw	read_rt
	ret
qio_error:
	bbs	#Ending_v, status_flags, 10$
	pushl	r0
	calls	#1, g^lib$signal
10$:	ret
iosb_error:
	bbs	#Ending_v, status_flags, 10$
	movzwl	(r1), -(sp)
	calls	#1, g^lib$signal
10$:	ret
write_tt:
	movzwl	in_iosb_rt+2, r0
	$qio_s -
	   func = #IO$_WRITEVBLK -
	   iosb = out_iosb_tt -
	   chan = chan_tt -
	   efn = #4 -
	   p1 = in_buff_rt -
	   p2 = r0 -
	   p4 = #0
	blbc	r0, qio_error
	$waitfr_s efn = #4
	movab	out_iosb_tt, r1
	blbs	(r1), 95$
	brw	iosb_error
95$:
	rsb
read_tt:
;+
;   Issue read I/O's to local terminal
;-
	movl	#IO$_TTYREADALL!IO$M_NOECHO, r0
	bbc	#local_echo_v, status_flags, 5$
	bicl	#io$m_noecho, r0
5$:
	$qio_s	-
	   func = r0 -
	   iosb = in_iosb_tt, -
	   chan = chan_tt, -
	   efn = #2, -
	   astadr = in_ast_tt, -
	   p1 = in_buff_tt, -
	   p2 = in_len_tt, -
	   p4 = trmdesc_addr
	blbs	r0, 10$
	brw	qio_error
10$:
	rsb
read_rt:
;+
;   Issue read I/O's to remote terminal
;-
	$qio_s	-
	   func = #IO$_TTYREADALL!IO$M_NOECHO!IO$M_TIMED, -
	   iosb = in_iosb_rt, -
	   efn = #3, -
	   chan = chan_rt, -
	   astadr = in_ast_rt, -
	   p1 = in_buff_rt, -
	   p2 = cur_len_rt, -
	   p3 = #1 -
	   p4 = trmdesc_addr
	blbs	r0, 10$
	brw	qio_error
10$:	rsb

;+
;   Write a record to the log file
;-
write_log_record:
	movab	log_file_buffer, r0
	subl3	r0, log_buffer_pos, r1
	beql	20$				; Null record
5$:
	cmpb	-1(r0)[r1], #^x0D		; Is last char <CR>?
	bneq	10$				; -- no
	decl	r1				; -- yes, strip it
	beql	20$				; Record now null
	brb	5$				; Try again
10$:
	cmpb	(r0), #^x0D			; Is first char <CR>?
	bneq	20$				; -- no
	incl	r0
	decl	r1
	bgtr	10$
20$:
	movw	r1, log_rab+rab$w_rsz
	movl	r0, log_rab+rab$l_rbf
	
	$put	rab=log_rab
	rsb
exit:
	bisl	#ending_m, status_flags
	$cancel_s chan = chan_tt
	$cancel_s chan = chan_rt
	$wake_s
	ret
;+
;  read vterm command from local terminal and execute it
;-
get_vterm_command:
	movab	vterm_prompt, r0
	$qiow_s -
	   func = #IO$_READPROMPT!IO$M_CVTLOW -
	   iosb = in_iosb_tt -
	   chan = chan_tt -
	   p1 = cmd_buffer -
	   p2 = cmd_buffer_len -
	   p5 = r0 -
	   p6 = vterm_prompt_len
	blbc	r0, 105$
	blbs	in_iosb_tt, 110$
	cmpw	in_iosb_tt, #SS$_ENDOFFILE
	beql	105$
	brw	exit
105$:
	movzwl	in_iosb_tt, -(sp)
	calls	#1, vterm_putmsg
	brb	get_vterm_command
110$:
	tstw	in_iosb_tt+2
	bneq	115$
	cmpb	in_iosb_tt+4, #^x1a
	bneq	null_cmd
	brw	exit
115$:
process_vterm_command:
	clrl	temp_val
	clrw	cmd_type
	clrl	log_file_options
	movzwl	in_iosb_tt+2, tparse_block+tpa$l_stringcnt
	movab	cmd_buffer, tparse_block+tpa$l_stringptr
	pushal	cmd_key
	pushal	cmd_state
	pushal	tparse_block
	calls	#3, g^lib$tparse
	blbs	r0, 125$
	insv	#1, #0, #3, r0
	pushl	r0
	calls	#1, vterm_putmsg
	brw	get_vterm_command
125$:
	casew	cmd_type, #1, #6
1$:	  .signed_word	null_cmd-1$		; Handled by action routine
	  .signed_word 	null_cmd-1$		; Unsupported
	  .signed_word	exit-1$			; STOP
	  .signed_word	help-1$			; Help
	  .signed_word	close_log-1$		; SET NOLOG
	  .signed_word	setcmd-1$		; SET COMMAND=
	  .signed_word  set_log-1$		; SET LOG
	  .signed_word  null_cmd-1$		; out of range
null_cmd:
	rsb
setcmd:
	movb	temp_val, esc_char
	rsb
help:
	pushab	g^lib$get_input
	pushl	#0
	pushaq	b^hlb_name_desc
	pushaq	tparse_block+tpa$l_stringcnt
	pushl	#0
	pushab	g^lib$put_output
	calls	#6, g^lbr$output_help
	rsb

hlb_name_desc:	.ascid	'VTERMHLP'

	.entry	vterm_putmsg, ^m<>
	$putmsg_s msgvec=(ap)
	ret

	.entry	open_log_file, ^m<r2>

	moval	log_fab, r2
	bbcc	#logging_v, status_flags, 100$
	$close	fab = (r2)
100$:
	movl	#fab$m_sqo!fab$m_tef, fab$l_fop(r2)
	movb	log_file_name, fab$b_fns(r2)
	movl	log_file_name+4, fab$l_fna(r2)
	bbc	#log_append_v, log_file_options, 110$
	bisl	#fab$m_cif, fab$l_fop(r2)
110$:
	bbc	#log_print_v, log_file_options, 120$
	bisl	#fab$m_spl, fab$l_fop(r2)
120$:
	$create	fab=(r2)
	movl	fab$l_stv(r2), r1
	blbc	r0, no_open
	$connect rab=log_rab
	movl	rab$l_stv+log_rab, r1
	blbc	r0, no_open
	bisl	#logging_m, status_flags
	ret
no_open:
	pushl	r1
	pushl	r0
	calls	#2, g^vterm_putmsg
	movl	#1, r0
	ret
set_log:
	bbs	#log_close_v, log_file_options, close_log
	calls	#0, open_log_file
	rsb
close_log:
	bbcc	#logging_v, status_flags, 90$
	bbc	#log_print_v, log_file_options, 80$
	bisl	#fab$m_spl, fab$l_fop+log_fab
80$:
	$close	fab = log_fab
90$:	rsb
;+
;  TPARSE state tables for VTERM commands
;-
cmd_null	 = 1
cmd_stop	 = 3
cmd_help	 = 4
cmd_nolog	 = 5
cmd_setcmd	 = 6
cmd_setlog	 = 7

	$tpadef

      $init_state cmd_state, cmd_key

      $state
	$tran	'EXIT',		done,, CMD_STOP, CMD_TYPE
	$tran	'HELP',		TPA$_EXIT,, CMD_HELP, CMD_TYPE
	$tran	'SET',		set
	$tran	'STOP',		done,, CMD_STOP, CMD_TYPE

      $state	set
	$tran	'BUFFER',	buffer
	$tran	'COMMAND',	command,, cmd_setcmd, cmd_type
	$tran	'LOCAL_ECHO',	done,, local_echo_m, status_flags
	$tran	'LOG',		log,, cmd_setlog, cmd_type
	$tran	'NOLOG',	done,, CMD_NOLOG, CMD_TYPE
	$tran	'SPEED',	speed

      $state	command
	$tran	'='
	$tran	tpa$_lambda,	TPA$_FAIL

      $state
	$tran	TPA$_DECIMAL,	done,,, temp_val

      $state	buffer
	$tran	'/'

      $state
	$tran	'LOCAL',	
	$tran	'REMOTE',	buffer_remote

      $state
	$tran	'='

      $state
	$tran	TPA$_DECIMAL,	done,,, in_len_tt

      $state	buffer_remote
	$tran	'='

      $state
	$tran	TPA$_DECIMAL,	done,,, in_len_rt

      $state	log
	$tran	'/',		log_options
	$tran	tpa$_eos,	done
	$tran	!file_name,	log,,, log_file_name
	$tran	tpa$_lambda,	tpa$_fail

      $state	file_name
	$tran	TPA$_BLANK,	TPA$_EXIT
	$tran	tpa$_eos, 	TPA$_EXIT
	$tran	!noslash,	file_name
	$tran	tpa$_lambda, 	tpa$_exit

      $state	noslash
	$tran	'/',		tpa$_fail
	$tran	tpa$_any,	tpa$_exit

      $state	log_options
	$tran	'APPEND',	log,, log_append_m, log_file_options
	$tran	'CLOSE',	log,, log_close_m, log_file_options
	$tran	'PRINT',	log,, log_print_m, log_file_options

      $state	speed
	$tran	'='

      $state
	$tran	TPA$_DECIMAL,	done, set_speed

      $state	done
	$tran	TPA$_LAMBDA,	TPA$_EXIT

      $end_state

	.entry	set_speed, ^m<r2>
	movaw	baud_table, r0
10$:
	cmpw	tpa$l_number(ap), (r0)
	beql	20$
	movab	4(r0), r0
	tstw	(r0)
	bneq	10$
	clrl	r0
	ret					; Indicate parse failure
20$:
	movzbl	2(r0), r2			; Speed value
;+
; Set terminal speed
;-
	bisl	#in_rt_cancel_m, status_flags
	$cancel_s chan = chan_rt
;	Get current terminal characteristics
	$qiow_s -
	   chan = chan_rt -
	   func = #io$_sensemode -
	   iosb = out_iosb_rt -
	   p1 = rt_characteristics -
	   p2 = #12

	bisl	#tt$m_nobrdcst, rt_characteristics+4
	bisl	#tt$m_passall, rt_characteristics+4
	bicl	tt$m_wrap, rt_characteristics+4

	$qiow_s -
	   chan = chan_rt -
	   func = #io$_setmode -
	   iosb = out_iosb_rt -
	   p1 = rt_characteristics -
	   p2 = #12 -
	   p3 = r2

	ret

baud_table:	.word	 110, tt$c_baud_110, -
			 300, tt$c_baud_300, -
			1200, tt$c_baud_1200, -
			2400, tt$c_baud_2400, -
			9600, tt$c_baud_9600, -
			0, 0
;+
; TR_TABLE is used by the log file writer to determine where to
; insert record breaks.  Any byte whose entry in the table is
; zero will terminate a record (the backspace character, ^X08, is
; an exception that is handled separately).  Any byte with a non-
; zero entry will translate to that value.
;-
tr_table:	.byte -
		^x00, ^x00, ^x00, ^x00, ^x00, ^x00, ^x00, ^x07, -	; 00-07
		^x00, ^x09, ^x00, ^x00, ^x00, ^x0D, ^x00, ^x00, -	; 08-0F
		^x00, ^x00, ^x00, ^x00, ^x00, ^x00, ^x00, ^x00, -	; 10-17
		^x00, ^x00, ^x00, ^x1B, ^x00, ^x00, ^x00, ^x00, -	; 18-1F
		^x20, ^x21, ^x22, ^x23, ^x24, ^x25, ^x26, ^x27, -	; 20-27
		^x28, ^x29, ^x2A, ^x2B, ^x2C, ^x2D, ^x2E, ^x2F, -	; 28-2F
		^x30, ^x31, ^x32, ^x33, ^x34, ^x35, ^x36, ^x37, -	; 30-37
		^x38, ^x39, ^x3A, ^x3B, ^x3C, ^x3D, ^x3E, ^x3F, -	; 38-3F
		^x40, ^x41, ^x42, ^x43, ^x44, ^x45, ^x46, ^x47, -	; 40-47
		^x48, ^x49, ^x4A, ^x4B, ^x4C, ^x4D, ^x4E, ^x4F, -	; 48-4F
		^x50, ^x51, ^x52, ^x53, ^x54, ^x55, ^x56, ^x57, -	; 50-57
		^x58, ^x59, ^x5A, ^x5B, ^x5C, ^x5D, ^x5E, ^x5F, -	; 58-5F
		^x60, ^x61, ^x62, ^x63, ^x64, ^x65, ^x66, ^x67, -	; 60-67
		^x68, ^x69, ^x6A, ^x6B, ^x6C, ^x6D, ^x6E, ^x6F, -	; 68-6F
		^x70, ^x71, ^x72, ^x73, ^x74, ^x75, ^x76, ^x77, -	; 70-77
		^x78, ^x79, ^x7A, ^x7B, ^x7C, ^x7D, ^x7E, ^x00, -	; 78-7F

		^x80, ^x81, ^x82, ^x83, ^x84, ^x85, ^x86, ^x87, -	; 80-87
		^x88, ^x89, ^x8A, ^x8b, ^x8C, ^x8D, ^x8E, ^x8F, -	; 88-8F
		^x90, ^x91, ^x92, ^x93, ^x94, ^x95, ^x96, ^x97, -	; 90-97
		^x98, ^x99, ^x9A, ^x9b, ^x9C, ^x9D, ^x9E, ^x9F, -	; 98-9F
		^xA0, ^xA1, ^xA2, ^xA3, ^xA4, ^xA5, ^xA6, ^xA7, -	; A0-A7
		^xA8, ^xA9, ^xAA, ^xAB, ^xAC, ^xAD, ^xAE, ^xAF, -	; A8-AF
		^xB0, ^xB1, ^xB2, ^xB3, ^xB4, ^xB5, ^xB6, ^xB7, -	; B0-B7
		^xB8, ^xB9, ^xBA, ^xBB, ^xBC, ^xBD, ^xBE, ^xBF, -	; B8-BF
		^xC0, ^xC1, ^xC2, ^xC3, ^xC4, ^xC5, ^xC6, ^xC7, -	; C0-C7
		^xC8, ^xC9, ^xCA, ^xCB, ^xCC, ^xCD, ^xCE, ^xCF, -	; C8-CF
		^xD0, ^xD1, ^xD2, ^xD3, ^xD4, ^xD5, ^xD6, ^xD7, -	; D0-D7
		^xD8, ^xD9, ^xDA, ^xDB, ^xDC, ^xDD, ^xDE, ^xDF, -	; D8-DF
		^xE0, ^xE1, ^xE2, ^xE3, ^xE4, ^xE5, ^xE6, ^xE7, -	; E0-E7
		^xE8, ^xE9, ^xEA, ^xEB, ^xEC, ^xED, ^xEE, ^xEF, -	; E8-EF
		^xF0, ^xF1, ^xF2, ^xF3, ^xF4, ^xF5, ^xF6, ^xF7, -	; F0-F7
		^xF8, ^xF9, ^xFA, ^xFB, ^xFC, ^xFD, ^xFE, ^xFF		; F8-FF
.page
.subtitle	VTERM$EXIT - Exit handler

	.entry	vterm$exit, ^m<>
;+
; Vterm exit handler
;	Reset priority to original value if raised by VTERM
;-

	tstl	def_pri
	beql	10$

	$setpri_s pri = def_pri
10$:
	ret
.subtitle	CONVERT_LOGICAL - Convert logical to integer
	.entry	convert_logical, ^m<r2,r3>
;+
;  Translate a logical name, convert its equivalence string to
;  binary format, and return in r0.
;
;	4(ap) - Descriptor for logical
;	8(ap) - Mask of logical name tables to disable
;	12(ap) - Default value (if no translation or conversion invalid
;-

; Offsets from AP
	LOGNAME = 4
	DISABLE_MASK = 8
	DEFAULT_VAL = 12

	movaq	equ_string, r0
	$trnlog_s -
	   lognam = @logname(ap) -
	   dsbmsk = disable_mask(ap) -
	   rsllen = equ_length -
	   rslbuf = equ_string
	cmpl	r0, #ss$_notran
	beql	default
	blbc	r0, default
	clrl	r0
	movl	equ_string+4, r1
	movzwl	equ_length, r2
;+
; Convert string to integer
;-
10$:
	cmpb	(r1), #^a'0'
	blssu	default
	cmpb	(r1), #^a'9'
	bgtru	default
	subb3	#^a'0', (r1)+, r3
	movzbl	r3, r3
	mull	#10, r0
	addl	r3, r0
	sobgtr	r2, 10$
	ret
default:
	movl	default_val(ap), r0
	ret
	.psect	$data, rd, wrt, noexe, long
equ_length:	.blkw	1
equ_string:	.long	63
		.address 1$
1$:		.blkb	63

	.end	vterm
