	.title	ddb_main main module
;
; Copyright (C) 1994 Neill Clift (neill@macro.demon.co.uk).
;
; This program comes without any warranty. The author does not accept any
; responsibility for any damage caused by the use of this program. This
; program is not in the public domain but may be copied freely so long as this
; copyright notice remains.
;
; Please send any modifications to the author.
;
; The aim of this code is to run up the debugger in a detached process with
; dbg$input etc pointing to a pseudo-terminal created especialy for the debug
; purpose.
;
	.disable global
;
; Includes:
;
	$dvidef					; Device volume information
	$iodef					; $QIO request values
	$lckdef					; Lock services defs.
	$lnmdef					; Logical name service defs.
	$namdef					; Name block definitions
	$psldef					; Process status longword defs.
	$ssdef					; System service comp. codes
	$stsdef					; Status code defs
	$ttdef					; Terminal characteristics
	$tt2def					; Extended terminal chars
;
; External symbols:
;
	.external ddb_clitable			; CLI command table
	.external ddb__logopenerr, -		; Error opening log file
		ddb__logconnerr, -		; Error connecting log file
		ddb__logputerr, -		; Error during $PUT
		ddb__prcnam, -			; Error obtaining PID
		ddb__vtcon, -			; Error connectinf to VTAnnnn:
		ddb__prcpid			; Error converting PID
;
; External routines:
;
	.external cli$dcl_parse, -		; Parse a DCL command
		cli$get_value, -		; Get a value from the CLI
		cli$present			; Is an entity present
	.external ots$cvt_tz_l			; Convert hex to binary
	.external lib$get_foreign, -		; get foreign command line
		lib$signal, -			; Signal error
		lib$wait			; wait for a bit
	.external ddb_privw			; Start up debugger
;
	.psect	ddb_wdata wrt rd noexe page
;
logfab:	$fab	dnm = <sys$disk:[]ddb.log>, -
		fac = put, -
		fop = <dfw,sqo>, -
		nam = lognam, -
		org = seq, -
		rat = cr, -
		rfm = var, -
		shr = get
;
lograb:	$rab	fab = logfab, -
		rac = seq, -
		rop = wbh
;
lognam:	$nam	esa = ess_b, -
		ess = ess_len, -
		rsa = rss_b, -
		rss = ess_len
;
iosb:	.quad	0				; IOSB for sys$getjpiw
ttiosb:
	.quad	0				; IOSB for async calls (TT:)
lksb:	.quad	0				; LKSB for resignal lock
frcpmt:	.long	0				; Force prompting flag
pid:	.long	0				; PID of process to debug
flags:	.long	0				; Flags. Lowest bit = exit
flags_v_finished = 0				; All finished
flags_v_logging  = 1				; logging turned on
flags_m_finished = 1@flags_v_finished		; All done?
flags_m_logging  = 1@flags_v_logging		; logging turned on?
final_status:
	.long	0				; final status
;
; Create exit handler block
;
exit_block:
	.long	0				; Forward link
	.address rundown			; Address of rundown routine
	.long	1				; One argument
	.address final_status			; Address of final status
;
; build descriptor for /identification qualifier
;
idstr_len = 30
idstr:	.word	idstr_len, 0
	.address idstr_buf
idstr_buf:
	.blkb	idstr_len
;
; Build descriptor for the process name
;
prcnam_len = 30
prcnam:	.word	prcnam_len, 0
	.address prcnam_buf
prcnam_buf:
	.blkb	prcnam_len
;
; Build descriptor for VT device name
;
vtnam_len = 10
vtnam:	.word	vtnam_len, 0
	.address vtnam_buf
vtnam_buf:
	.blkb	vtnam_len

;
ftchan:	.word	0				; Channel to FTAnnn (control)
ftchan1:.word	0				; Channel to FTAnnn (Normal)
ttchan:	.word	0				; Channel to SYS$COMMAND
;
devchar_len = 20				; Device characteristics TT:
devchar:.blkb	devchar_len
;
ndevchar_len = 20				; Modified device chars
ndevchar:.blkb	devchar_len
;
; Build descriptor to hold device name of FTAnnnn: device
;
devnam_len = 10
devnam:	.word	devnam_len, 0
	.address -
		devnam_buf
devnam_buf:
	.blkb	devnam_len
;
logfile_len = nam$c_maxrss
logfile:
	.word	logfile_len, 0
	.address logfile_b
logfile_b:
	.blkb	logfile_len
;
logbuf_len = 2048
logbuf:	.word	0, 0
	.address logbuf_b
logbuf_b:
	.blkb	logbuf_len
;
; Define NAM block name buffers to improve errors
;
ess_len = nam$c_maxrss
ess_b:	.blkb	ess_len
rss_len = nam$c_maxrss
rss_b:	.blkb	rss_len
;
	.align	page
buf_start:
rbuf:	.blkb	500
rbuf_len = .-rbuf
wbuf:	.blkb	500
wbuf_len = .-wbuf
buf_end:
;
	.psect	ddb_rdata nowrt rd noexe shr
;
inadr:	.address buf_start, buf_end-1
;
itmlst:	.word	devnam_len, dvi$_devnam
	.address devnam_buf, devnam
	.long	0
;
; Item list to translate DDB_<pid> logical. This contains the virtual terminal
; name.
;
trnlst:	.word	vtnam_len, lnm$_string
	.address vtnam_buf, vtnam
	.long	0
;
quit_char = ^A/\/-^A/@/				; Quit character is ^\
BS = ^A/H/-^A/@/
LF = ^A/J/-^A/@/
CR = ^A/M/-^A/@/
;
log:	.ascii	/DDB_/				; Prefix for logical name
log_length = .-log
lock:	.ascii	/DDB_/				; Prefix for lock name
lock_length = .-lock
delstr:	.ascii	<BS>/ /<BS>			; Delete one char string
delstr_len = .-delstr
;
; To start the ball rolling we prime CLI$DCL_PARSE with just the verb
;
verb:	.ascid	/DDB/
;
identification:
	.ascid	/IDENTIFICATION/
process_name:
	.ascid	/PROCESS_NAME/
log_qual:
	.ascid	/LOG/
;
input:	.ascid	/SYS$COMMAND:/
lnm$system:
	.ascid	/LNM$SYSTEM/
trmmsg:	.ascii	/Use ^\ to terminate session/
trmmsg_len = .-trmmsg
;
;!!!	.psect	ddb_code nowrt rd exe pic shr
	.psect	ddb_code wrt rd exe pic shr
;
	.entry	ddb ^m<r2,r3,r4,r5>
	bsbw	parse_commands_r1		; Parse command line
	blbc	r0, 99$				; quit on error
	bsbw	open_logfile_r1			; get and open logfile
	blbc	r0, 99$				; quit on error
	bsbb	redirect_io_r3			; copy input and output
99$:	ret
;
; Sets up IO redirection so it looks like the user is typing directly to the
; debugged process.
; Inputs:
; Outputs:
;    R0: Status
; Trashes:
;    R1,R2
;
redirect_io_r3:
	bsbw	assign_chans
	blbc	r0, 99$
	bsbb	signal_proc_r3
	blbc	r0, 99$
	bsbb	message
	blbc	r0, 99$
	bsbw	start_r1
	blbc	r0, 99$
1$:	$hiber_s
	assume	flags_v_finished eq 0
	blbc	flags, 1$
99$:	rsb
;
; Outputs a message to the terminal.
;
message:
	$qiow_s	chan = ttchan, -
		func = #io$_writevblk, -
		iosb = iosb, -
		p1   = trmmsg, -
		p2   = #trmmsg_len
	blbc	r0, 99$
	movzwl	iosb, r0
99$:	rsb
	
;
; Causes the debug signal to be generated in the remote process
;
signal_proc_r3:
	bsbw	get_vtnam_r2
	blbs	r0, reconnect			; reconnect device
	pushaq	devnam				; bring it up on this device
	pushaq	iosb
	pushal	pid
	clrl	-(sp)
	calls	#4, g^ddb_privw			; Boot debug up initialy
	blbc	r0, 99$
	movl	#20, r3				; do this upto twenty times
1$:	bsbw	get_vtnam_r2			; try again
	blbc	r0, 2$
	bsbw	get_vtrefc_r1
	blbc	r0, 99$
	tstl	r1
	bneq	reconnect1			; Thats it so grab it
2$:	pushaf	i^#^f1.0
	calls	#1, g^lib$wait			; wait for a second
	sobgtr	r3, 1$				; try again
99$:	rsb
;
	.enable	lsb
reconnect:
;
; Reconnect processing is strange! A connect request is not completed until all
; channels are deassigned on the device and the reference count drops to zero.
; FTAnnnn: devices have a reference count of zero when we do the connect and so
; a channel is never deassigned to make the connect. to get round this we must
; assign a channel that we can deassign just to force last channel processing!
; Its wacky but it does make sense!
;
	$cmkrnl_s -
		routin = take_lock		; take out kernel lock
	blbc	r0, 99$
reconnect1:
	$assign_s -
		chan   = ftchan1, -		; assign another channel
		devnam = devnam			; to FTAnnnn: device
	blbc	r0, 99$
	$qiow_s -				; connect to virtual
		chan = ftchan1, -
		iosb = iosb, -
		func = #io$_setmode!io$m_tt_connect, -
		p1   = vtnam			; VTAnnn
	blbc	r0, 100$
	movzwl	iosb, r0			; check other status
	blbc	r0, 100$
	$dassgn_s -				; Drop last channel
		chan = ftchan1
99$:	rsb
100$:	pushl	r0
	pushaq	vtnam
	pushl	#1
	pushal	g^ddb__vtcon
	calls	#4, g^lib$signal		; signal connect error
	rsb
	.disable lsb
;
get_vtrefc_r1:
	clrl	-(sp)				; put ref count here
	clrq	-(sp)				; end of list and no length
	pushal	8(sp)				; put refc in hole
	pushl	#dvi$_refcnt@16+4
	movl	sp, r0
	$getdviw_s -
		devnam = vtnam, -
		iosb   = iosb, -
		itmlst = (r0)
	addl2	#4*4, sp
	popl	r1
	blbc	r0, 99$
	movl	iosb, r0
99$:	rsb
;
get_vtnam_r2:
	assume	log_length eq 4			; move with fast instruction
	pushl	pid				; push pid
	pushl	log				; Add prefix
	pushl	sp				; push address
	pushl	#log_length+4			; save size
	movl	sp, r2				; point to lognam
	$trnlnm_s -
		tabnam = lnm$system, -		; its in system table
		lognam = (r2), -		; translate DDB logical
		itmlst = trnlst
	addl2	#16, sp				; drop stack allocation
	rsb
;
; Opens up the logging file if specified
;
open_logfile_r1:
	pushaq	log_qual
	calls	#1, g^cli$present
	blbc	r0, 98$
	pushaw	logfile
	pushaq	logfile
	pushaq	log_qual
	calls	#3, g^cli$get_value
	blbc	r0, 99$
	movab	logfab, r0
	movab	logfile_b, fab$l_fna(r0)
	movb	logfile,   fab$b_fns(r0)
	movab	g^ddb__logopenerr, fab$l_ctx(r0)
	$create	fab = logfab, -
		err = file_err
	blbc	r0, 99$
	movab	g^ddb__logconnerr, lograb+rab$l_ctx
	$connect rab = lograb, -
		err = file_err
	blbc	r0, 99$
	bisl	#flags_m_logging, flags
98$:	movl	#ss$_normal, r0
99$:	rsb
;
	.entry	take_lock ^m<>
	assume	lock_length eq 4		; move with fast instruction
	pushl	pid				; push pid
	pushl	lock				; Add prefix
	pushl	sp				; push address
	pushl	#lock_length+4			; save size
	movl	sp, r0				; point to lognam
	$enqw_s	lkmode = #lck$k_exmode, -	; Take out resignal lock
		lksb   = lksb, -
		flags  = #lck$m_system, -	; use system lock
		resnam = (r0), -		; Use this resource name
		acmode = #psl$c_kernel
	blbc	r0, 99$
	movzwl	lksb, r0			; get other status
	blbc	r0, 99$
	$deq_s	lkid = lksb+4			; drop lock
99$:	ret

;
; Starts reads on both the terminal and pseudo device
; Inputs:
; Outputs:
;    R0: Status
; Trashes:
;    R1
;
start_r1:
	movb	#^A/X/-^A/@/, wbuf+4
	ptd$write_s -
		chan       = ftchan, -
		wrtbuf     = wbuf, -
		wrtbuf_len = #1
	blbc	r0, 99$
	$qio_s	chan   = ttchan, -
		func   = #io$_readvblk!io$m_noecho!io$m_nofiltr, -
		iosb   = ttiosb, -
		astadr = got_input, -
		p1     = wbuf+4, -
		p2     = #1
	blbc	r0, 99$
	ptd$read_s -
		chan        = ftchan, -
		astadr      = got_output, -
		readbuf     = rbuf, -
		readbuf_len = #rbuf_len-4
99$:	rsb
;
assign_chans:
	bsbb	do_term
	blbc	r0, 99$
	bicl2	#tt$m_passall,     ndevchar+4		; Turn off passall
	bicl2	#tt2$m_secure,     ndevchar+8		; No secure server
	bisl2	#tt2$m_disconnect, ndevchar+8		; Turn on disconnect
	ptd$create_s -
		chan     = ftchan, -
		inadr    = inadr, -
		charbuff = ndevchar, -
		buflen   = #ndevchar_len
	blbc	r0, 99$
	$getdviw_s -
		chan   = ftchan, -
		iosb   = iosb, -
		itmlst = itmlst
	blbc	r0, 99$
	movl	iosb, r0
99$:	rsb
;
do_term:
	$assign_s -
		chan   = ttchan, -
		devnam = input
	blbc	r0, 99$
	$qiow_s -
		chan = ttchan, -
		iosb = iosb, -
		func = #io$_sensemode, -
		p1   = devchar, -
		p2   = #devchar_len
	blbc	r0, 99$
	movzwl	iosb, r0
	blbc	r0, 99$
	$dclexh_s -
		desblk = exit_block			; declare exit handler
	blbc	r0, 99$
	bsbb	set_term_chars_r5			; set terminal chars
99$:	rsb
;
set_term_chars_r5:
	assume	devchar_len eq ndevchar_len		; Both blocks the same?
	movc3	#devchar_len, devchar, ndevchar		; Make copy of chars
	bisl2	#tt$m_passall, ndevchar+4		; Set passall mode
	$qiow_s -
		chan = ttchan, -
		iosb = iosb, -
		func = #io$_setmode, -
		p1   = ndevchar, -
		p2   = #ndevchar_len
	blbc	r0, 99$
	movzwl	iosb, r0
99$:	rsb
;
;
; Gets the command line and parses it with cli$dcl_parse
; Inputs:
; Outputs:
;    R0: status
; Trashes:
;    R1
;
parse_commands_r1:
	pushaw	get_input               ; Input and
	pushaw	get_input		;    continuation routines
	pushab	ddb_clitable		; command table address
	pushaq	verb			; start of command
	calls	#4, g^cli$dcl_parse	; parse command
	bisl2	#sts$m_inhib_msg, r0	; Dont signal errors
	blbc	r0, 99$			; quit with error
	pushaq	identification		; this qualifier there?
	calls	#1, g^cli$present	; /IDENT there?
	blbs	r0, 1$			; if no get process name
	pushaw	prcnam			; put length here
	pushaq	prcnam			; put it here
	pushaq	process_name		; get process name
	calls	#3, g^cli$get_value	; get process name
	blbc	r0, 99$			; quit on error
	$getjpiw_s -
		prcnam = prcnam, -	; use process name
		pidadr = pid, -		; put PID here
		iosb   = iosb, -	; use iosb
		itmlst = #0		; empty item list
	blbc	r0, 98$			; quit on error
	movl	iosb, r0		; get other status
98$:	blbs	r0, 99$			; all is ok
	pushl	r0			; Real error
	pushaq	prcnam			; Process name
	pushl	#1			; 1 argument
	pushal	g^ddb__prcnam		; Signal error in process name
	calls	#4, g^lib$signal	; Signal error for process
99$:	rsb
;
; Use specified process id
;
1$:	pushaw	idstr			; put length here
	pushaq	idstr			; put PID string here
	pushaq	identification		; get /ID value
	calls	#3, g^cli$get_value	; get the value
	blbc	r0, 99$			; quit on error
	pushal	pid			; put result here
	pushaq	idstr			; convert /id value
	calls	#2, g^ots$cvt_tz_l	; convert to binary
	blbs	r0, 99$
	pushl	r0			; Real error
	pushaq	idstr			; Process name
	pushl	#1			; 1 argument
	pushal	g^ddb__prcpid		; Signal error in process id
	calls	#4, g^lib$signal	; Signal error for process
	rsb
;
	.entry	get_input ^m<>		; Input routine for CLI$DCL_PARSE
line   = 4				; put input here
prompt = 8				; use this prompt
length = 12				; put length of input here
	pushal	frcpmt			; used to force prompting after first
	pushl	length(ap)		; put length here
	assume	<line+4> eq prompt	; can we copy both in one
	movq	line(ap), -(sp)		; copy line and prompt
	calls	#4, g^lib$get_foreign	; get command line
	ret
;
	.entry	got_output ^m<r2,r3,r4,r5>
	assume	flags_v_finished eq 0
	blbs	flags, 99$
	movzwl	rbuf, r0
	blbc	r0, sig
	bsbb	log_output_r5
	blbc	r0, sig
	movzwl	rbuf+2, r0
	$qiow_s	chan = ttchan, -
		func = #io$_writevblk, -
		iosb = iosb, -
		p1   = rbuf+4, -
		p2   = r0
	blbc	r0, sig
	ptd$read_s -
		chan        = ftchan, -
		astadr      = got_output, -
		readbuf     = rbuf, -
		readbuf_len = #rbuf_len-4
	blbc	r0, sig
99$:	ret
;
sig:	brw	sig1
;
log_output_r5:
	movab	flush_lines_r5, r4		; Try flushing lines first
1$:	bbc	#flags_v_logging, flags, 98$	; logging to be done?
	movq	logbuf, r0			; Get descriptor
	movzwl	r0, r0				; get real length
	addl2	r0, r1				; get address of end
	subl3	r0, #logbuf_len, r0		; get remaining
	movzwl	rbuf+2, r2			; get length of new data
	cmpl	r0, r2				; test for space
	bgtru	2$				; enough space?
	jsb	(r4)				; flush the buffer
	movab	flush_buffer_r5, r4		; flush everything if need be
	blbc	r0, 99$				; quit with error
	brb	1$				; try again
2$:	addw2	r2, logbuf			; set new length
	movc3	r2, rbuf+4, (r1)		; copy in new data
98$:	movl	#ss$_normal, r0
99$:	rsb
;
flush_lines_r5:
	bbc	#flags_v_logging, flags, 98$	; logging to be done?
	bsbw	compress_deletes_r5		; Trim out any deletes
	movq	logbuf, r2			; Get descriptor
	movzwl	r2, r2				; get real length
1$:	movl	r3, lograb+rab$l_rbf		; set buffer start
	locc	#CR, r2, (r3)			; Any line breaks?
	beql	4$
	cmpb	1(r1), #LF			; line feed after?
	bneq	2$
	incl	r1				; skip LF
2$:	subw3	r0, r2, lograb+rab$w_rsz	; length upto CR
	subl3	r3, r1, r0
	subl2	r0, r2
	addl3	#1, r1, r3
	movab	g^ddb__logputerr, lograb+fab$l_ctx
	$put	rab = lograb, -
		err = file_err
	blbs	r0, 3$
	bicl	#flags_m_logging, flags		; file error turn off logging
	brb	98$
3$:	decl	r2
	bgtr	1$
4$:	movw	r2, logbuf
	movc3	r2, (r3), logbuf_b
98$:	movl	#ss$_normal, r0
99$:	rsb
;
flush_buffer_r5:
	bbc	#flags_v_logging, flags, 98$	; logging to be done?
	bsbw	flush_lines_r5			; flush any lines first
	blbc	r0, 99$				; quit on error
	movq	logbuf, r2			; Get descriptor
	movw	r2, lograb+rab$w_rsz		; length left
	movl	r3, lograb+rab$l_rbf		; set buffer address
	movab	g^ddb__logputerr, lograb+fab$l_ctx
	$put	rab = lograb, -			; put to output
		err = file_err
	blbs	r0, 1$
	bicl	#flags_m_logging, flags		; file error turn off logging
1$:	clrw	logbuf				; say no more output
98$:	movl	#ss$_normal, r0
99$:	rsb
;
compress_deletes_r5:
1$:	subw3	#1, logbuf,   r2		; Get descriptor length-1
	bleq	99$				; only one byte
	addl3	#1, logbuf+4, r3		; get address of second byte
	matchc	#delstr_len, delstr, r2, (r3)	; look for delstr	
	bneq	99$				; all done
	movc3	r2, (r3), -delstr_len-1(r3)	; scrunch it out
	subw2	#delstr_len+1, logbuf
	brb	1$
99$:	rsb
;
sig2:	brw	sig1
;
	.entry	got_input ^m<r2>
	assume	flags_v_finished eq 0
	blbs	flags, 99$
	movzwl	ttiosb, r0
	blbc	r0, sig2
	bsbw	read_typahd_r2
	blbs	r0, 2$
1$:	cmpw	r0, #ss$_timeout
	bneq	sig1
2$:	tstl	r2
	beql	99$
	ptd$write_s -
		chan       = ftchan, -
		wrtbuf     = wbuf, -
		wrtbuf_len = r2
	blbc	r0, sig1
	movzwl	wbuf, r0
	blbc	r0, sig1
	$qio_s	chan   = ttchan, -
		func   = #io$_readvblk!io$m_noecho!io$m_nofiltr, -
		iosb   = ttiosb, -
		astadr = got_input, -
		p1     = wbuf+4, -
		p2     = #1
	blbc	r0, sig1
99$:	ret
;
sig1:	cmpw	r0, #ss$_cancel
	beql	99$
	cmpw	r0, #ss$_abort
	beql	99$
	pushl	r0
	calls	#1, g^lib$signal
99$:	ret
;
; reads in the typeahead buffer into the rest of the IO line.
;
read_typahd_r2:
	clrl	r2
	addw3	ttiosb+2, ttiosb+6, r2
	subw3	r2, #wbuf_len-4, r1
	movab	wbuf+4[r2], r0
	$qiow_s	chan   = ttchan, -
		func   = #io$_readvblk!io$m_noecho!io$m_timed, -
		iosb   = iosb, -
		p1     = (r0), -
		p2     = r1
	blbc	r0, 99$
	addw2	iosb+2, r2
	addw2	iosb+6, r2
	locc	#quit_char, r2, wbuf+4
	beql	1$
	subl2	r0, r2
	$dclast_s -
		astadr = got_outband
	blbc	r0, 99$
1$:	movzwl	iosb, r0
99$:	rsb
;
; Reset terminal characteristics before exiting.
;
	.entry	rundown ^m<>
status = 4
	bsbw	flush_buffer_r5				; flush any output
	bsbb	cancel_io_r1				; cancel all io
	$qiow_s -					; reset terminal chars
		chan = ttchan, -
		iosb = iosb, -
		func = #io$_setmode, -
		p1   = devchar, -
		p2   = #devchar_len
	ret
;
cancel_io_r1:
	$cancel_s -
		chan = ttchan				; cancel terminal IO
	$cancel_s -
		chan = ftchan				; cancel FT IO
	ptd$cancel_s -
		chan = ftchan				; Cancel PTD reads
	rsb
;
	.entry	got_outband ^m<>
	bsbb	cancel_io_r1				; cancel all io
	bisl2	#flags_m_finished, flags		; Say all is finished
	$wake_s						; Wake main thread
	ret
;
	.entry	file_err ^m<r2>
;
rmsblock = 4
savedr0  = rmsblock + 4
savedr1  = savedr0 + 4
savedpc  = savedr1 + 4
savedpsl = savedpc + 4
;
	assume	fab$l_sts eq rab$l_sts
	assume	fab$l_stv eq rab$l_stv
	assume	fab$l_ctx eq rab$l_ctx
	assume	fab$b_bid eq rab$b_bid
;
	movl	rmsblock(ap), r0
	pushl	fab$l_stv(r0)			; Save other status value
	pushl	fab$l_sts(r0)			; Save status value
;
; Assume this is a RAB and if so move to the FAB
;
	movl	r0, r1				; Assume this is the fab
	cmpb	rab$b_bid(r0), #rab$c_bid	; this a rab?
	bneq	1$				; Its a FAB so no need to switch
	movl	rab$l_fab(r0), r1		; Get address of the fab
1$:	movl	fab$l_nam(r1), r2		; Skip to NAM block
;
; Try and use resultant name first then expanded then finaly fab inputs.
;
	pushl	nam$l_rsa(r2)			; Save address of string
	movzbl	nam$b_rsl(r2), -(sp)		; Set length of string
	bneq	2$				; We got one so continue
	movl	nam$l_esa(r2), 4(sp)		; Save address of other string
	movzbl	nam$b_esl(r2), (sp)		; Save new length of string
	bneq	2$				; We got one so continue
	movl	fab$l_fna(r1), 4(sp)		; Save address of other string
	movzbl	fab$b_fns(r1), (sp)		; Save new length of string
2$:	pushl	#2				; Two arguments for error
	pushl	fab$l_ctx(r0)			; Save primary error
	calls	#6, g^lib$signal		; Signal the error
	ret
;
	.end	ddb
