;++
;
; Convert to/from radix-50 notation.
;
; By John Wilson.
;
; 07/18/94	JMBW	Created.
;
;--
	.radix	8
;
lf=	12
cr=	15
;
code	segment
	assume	cs:code
	org	100h
start:	cld			;move forwards
	mov	si,80h		;pt at JCL length
	lodsb			;get it
	cbw			;ah=0
	mov	cx,ax		;copy count
	jcxz	sk1
lp1:	lodsb			;get a char
	cmp	al,' '		;blank or ctrl char?
	ja	sk2
	loop	lp1
sk1:	mov	dx,offset usage	;print usage string
	mov	ah,09h		;func=print
	int	21h
	int	20h
sk2:	cmp	al,'^'		;^R or ^O?
	jne	sk4
	dec	cx		;yes, count it
	jz	sk1		;that's it?
	lodsb			;get another char
	and	al,not 40	;convert to upper
	cmp	al,'O'		;^O?
	je	sk3
	cmp	al,'R'		;^R?
	jne	sk1		;no, syntax error
	inc	ds:isstr	;yes, string
	jmp	short eloop
sk3:	inc	ds:isnum	;number
	jmp	short eloop
lp2:	; process next character of number or string
	lodsb			;get next char
sk4:	sub	al,'0'		;see if octal digit
	cmp	al,10		;valid digit?
	jae	sk5		;no
	mov	bx,ds:num	;get number
	sal	bx,1		;*8.
	sal	bx,1
	sal	bx,1
	or	bl,al		;OR in new digit
	mov	ds:num,bx	;update
sk5:	mov	al,[si-1]	;restore
	cmp	al,' '		;blank?
	je	spc
	cmp	al,'$'		;$?
	je	dolsgn
	cmp	al,'.'		;.?
	je	period
	cmp	al,'%'		;%?
	je	percnt
	cmp	al,'0'		;digit?
	jb	sk1		;no
	cmp	al,'9'
	jbe	digit		;yes
	cmp	al,'?'		;??
	je	percnt
	and	al,not 40	;convert to upper
	cmp	al,'A'		;letter?
	jb	sk1		;no
	cmp	al,'Z'
	ja	sk1
	sub	al,'A'-1	;convert
	jmp	short notdig
spc:	xor	al,al		;space
	jmp	short save
dolsgn:	mov	al,33		;$
	jmp	short notdig
period:	mov	al,34		;.
	jmp	short notdig
percnt:	mov	al,35		;%
	jmp	short notdig
digit:	sub	al,'0'-36	;digit
	jmp	short save
notdig:	inc	ds:nondig	;set flag (won't wrap to 0)
save:	cmp	byte ptr ds:numchr,3 ;already full?
	je	eloop
	inc	ds:numchr	;no, +1
	cbw			;ah=0
	mov	bx,ax		;save
	mov	al,50		;multiplier
	mul	ds:strng	;make space
	add	ax,bx		;add it in
	mov	ds:strng,ax	;update
eloop:	loop	lp2
	mov	cl,3		;load 3
	sub	cl,ds:numchr	;find # chars to go
	jz	sk6		;none
	mov	ax,ds:strng	;get number
	mov	bx,50		;multiplier
lp3:	mul	bx		;shift left
	loop	lp3		;loop
	mov	ds:strng,ax	;update
sk6:	mov	di,offset buf	;pt at buf
	cmp	byte ptr ds:isnum,0 ;known to be number?
	jnz	sk7
	cmp	byte ptr ds:isstr,0 ;known to be string?
	jnz	sk8
	cmp	byte ptr ds:nondig,0 ;not explicit, non-digits seen?
	jnz	sk8		;yes, assume string
sk7:	; print number and its rad50 equiv
	mov	ax,ds:num	;get number
	call	prnum		;print it
	mov	ax,"= "		;' ='
	stosw
	mov	al,' '		;' '
	stosb
	mov	ax,ds:num	;get number
	call	prstr		;print it
	jmp	short print
sk8:	; print string and its octal equivalent
	mov	ax,ds:strng	;get string
	call	prstr		;print it
	mov	ax,"= "		;' ='
	stosw
	mov	al,' '		;' '
	stosb
	mov	ax,ds:strng	;get string
	call	prnum		;print it
print:	mov	ax,cr+(lf*400)	;crlf
	stosw
	mov	dx,offset buf	;pt at buf
	sub	di,dx		;find length
	mov	cx,di
	mov	bx,0001h	;handle=STDOUT
	mov	ah,40h		;func=print
	int	21h
	int	20h		;exit
;+
;
; Convert word in ax to octal at es:di.
;
;-
prnum:	push	ax		;save
	mov	ax,"O^"		;^O
	stosw
	pop	ax		;restore
	mov	cl,3		;shift count
prnum1:	cmp	ax,10		;worth recursing?
	jb	prnum2		;no
	push	ax		;save
	shr	ax,cl		;shift
	call	prnum1		;recurse
	pop	ax		;restore
	and	al,7		;isolate low 3
prnum2:	or	al,'0'		;convert to digit
	stosb			;save
	ret
;+
;
; Convert word in ax to .RAD50 at es:di.
;
;-
prstr:	mov	bx,50		;radix
	xor	dx,dx		;dx=0
	div	bx		;divide (remainder in dl)
	div	bl		;divide (al=quotient, ah=rem)
	or	al,al		;is first char blank?
	jz	prstr1
	or	dl,dl		;is last char blank?
	jnz	prstr2		;no
prstr1:	; first and/or last char is blank, enclose the whole mess in <>
	push	ax		;save
	mov	al,'<'		;<
	stosb
	pop	ax		;restore
	call	prstr2		;display string
	mov	al,'>'		;>
	stosb
	ret
prstr2:	push	ax		;save
	mov	ax,"R^"		;^R
	stosw
	pop	ax		;restore
	mov	bl,al		;get first char
	mov	al,ds:r50[bx]
	stosb
	mov	bl,ah		;2nd char
	mov	al,ds:r50[bx]
	stosb
	mov	bl,dl		;3rd char
	mov	al,ds:r50[bx]
	stosb
	ret
;
usage	db	'usage:  rad50 { [^O]nnnnnn | [^R]lll }',cr,lf,'$'
r50	db	' ABCDEFGHIJKLMNOPQRSTUVWXYZ$.%0123456789'
;
num	dw	0		;number
strng	dw	0		;string
nondig	db	0		;# of non-digits seen
numchr	db	0		;number of characters seen in string
isnum	db	0		;NZ => known to be number (^O)
isstr	db	0		;NZ => known to be string (^R)
buf	db	40d dup(?)	;output line buffer
;
code	ends
	end	start
