	.mcall	.MODULE
	.MODULE	SENDXL,comment=<Send to XL>,release=V09,version=05

;**************************************************************;
;                                                              ;
;   Copyright (c) 1989            Bob Schor                    ;
;                                 Eye and Ear Institute        ;
;                                 203 Lothrop St.              ;
;                                 Pittsburgh, PA   15213       ;
;                                                              ;
; All rights reserved.  May not be copied without this notice. ;
;                                                              ;
;**************************************************************;

;Command-line routine to send strings to XL.  Used in setting modems, 
;dialing, etc.  Strings echoed, except that characters inside brackets
;(e.g. <15>) are assumed to be octal values.

;Code developed from working Pascal routine

;b schor	May 29, 1989

;modifications --
;	may, 1989	Psects $CODE and $DATA added


;define our .psects before calling SUMAC to force ours low

	.psect	$code	ro,i,lcl,rel,con
	.psect	$data	rw,d,lcl,rel,con

;uses SUMAC for structured macro code

	.library	/lib:sumac/	;use external macro definition file

	.mcall	SUMAC
	SUMAC				;initialization macro

	.dsabl	gbl			;if undefined symbol, force error


HEAD	sysmac, <system macros>

	.mcall	.PRINT			;to announce identification
	.mcall	.EXIT			;return to RT-11 on errors
	.mcall	.GTLIN			;to flush TSX command buffer
	.mcall	.ENTER, .WRITW, .CLOSE	;to send to XL:

HEAD	syscon, <system constants>

	userto	=	50		;high memory address
	errbyt	=	52		;error byte in monitor
	userrb	=	53		;user error byte

	comlen	=	510		;command length
	comcmd	=	512		;command goes here

HEAD	offset, <monitor offsets>

	config	=	300		;offset to configuration word
	sysgen	=	372		;offset to sysgen features
	tsxver	=	-40		;offset to TSX version # (* ^d100)

HEAD	ioconst, <i/o constants>

	iochan	=	1		;i/o channel
	openbr	=	'<		;open bracket, starts number
	closbr	=	'>		;close bracket, ends number
	dot	=	'.		;decimal dot
	space	=	' 		;space

.sbttl	------------------------
.sbttl		code area
.sbttl	------------------------

	.psect	$code

LABEL	sendxl, <beginning of program>
;	NOTE
;	.PRINT	#modnam			;identify module
;	NOTE
	mov	#comcmd, r0		;point to command buffer
	mov	#comcmd, r1		;build real command in same place
	IF	@#comlen, eq		;if command of 0 length,
		NOTE	<SENDXL - W - no string specified>
		.EXIT
	ENDIF
	INVOKE	parse			;replace <nn> with characters
	bit	#1, r1			;make sure output string even bytes
	IF	ne
		clrb	(r1)+		;clear to even byte boundary
	ENDIF				;r1 now points to end of string
	sub	#comcmd, r1		;subtract beginning of string
	asr	r1			;divide by 2 to get word count
	.ENTER	#emtarg, #iochan, #xldb, #1	;open channel to send to XL
	IF	cs
		NOTE	<Cannot open channel to XL:>
	ELSE
		.WRITW	#emtarg, #iochan, #comcmd, r1, #0	;write command
		IF	cs
			NOTE	<Error in writing command to XL:>
		ENDIF
	ENDIF
	.CLOSE	#iochan
	clrb	@#comcmd		;wipe out command for orderly exit
	clr	@#comlen
	.GTLIN	#flush			;clear out TSX command buffer
	.EXIT				;and return to RT/TSX


PROCED	parse, <parse command string>
;On entry, r0 and r1 point to the command string area.  r0 is used as an
;input pointer, r1 as an output pointer.  Effect of "parse" is to replace
;<nn> constructs with an equivalent character.  Symbols recognized are "<"
;and ">", which delimit the special parse, and "." which signals number is
;decimal.  Any non-numeric (other than ".") between < and > result in a
;parsing flush.

	mov	#1, r2			;initialize flag, 1 = normal parse
	WHILEB	(r0), ne		;input string terminated by 0
		movb	(r0)+, r3	;get input character
		IFB	r3, ne, #openbr	;if not start of numeric,
			movb	r3, (r1)+	;simply pass character
		ELSE
			INVOKE	getnum	;get numeric value
			movb	r3, (r1)+	;return character value
		ENDIF
	ENDWHILE
ENDPROC		

PROCED	getnum, <parse and return number in command string>
;On entry, r0 should be pointing to a numeric string.
;On exit, r0 should be pointing just past the matching >, and the
;proper numeric value should be returned in r3.  Interpret numbers 
;as octal unless "." encountered.
;Registers r2 - r5 are used freely.

	mov	#10, r4			;set octal radix
	mov	sp, r2			;remember current stack location
	WHILEB	(r0), ne		;while not at end of string
	ANDB	(r0), ne, #closbr		;nor at end of parse,
		movb	(r0)+, r3	;get character
		IF	r3, ge, #'0	;if numeric,
		AND	r3, le, #'9
			PUSH	r3				
			sub	#'0, (sp)	;make a digit
		ELSIF	r3, eq, #dot	;if decimal,
			mov	#^d10, r4	;set decimal radix
		ELSIF	r3, eq, #space	;if space
			;ignore it
		ELSE			;if error,
			WHILEB	(r0), ne
			ANDB	(r0), ne, #closbr
				inc	r0	;bump to end of number
			ENDWHILE
		ENDIF
	ENDWHILE
;We have now reached either the ">" or the end of the string.
	IFB	(r0), eq, #closbr
		inc	r0		;bump past terminator
	ENDIF
;r4 is set to the proper radix, and the stack holds the numbers
	mov	r2, r5			;start at bottom of stack
	clr	r3			;accumulate number in r3
	WHILE	r5, ne, sp		;while stack not empty,
		mul	r4, r3		;multiply by radix
		add	-(r5), r3	;and add next number
	ENDWHILE
	mov	r2, sp			;restore stack
ENDPROC

.sbttl	------------------------
.sbttl		data area
.sbttl	------------------------
	.psect	$data

xldb:	.rad50	/XL SENDXLTXT/		; File name used to send to XL:
flush:	.blkb	100.			; Space to flush TSX command buffer
emtarg:	.blkw	10.			; Space for EMT arguments

LABEL	modnam, <module name>
	.NLCSI				;generates .asciz module string
	.even

	ENDEND

	.end	sendxl
