mac-rom/Toolbox/SANE/Dec2Str.a

336 lines
9.8 KiB
Plaintext
Raw Normal View History

;EASE$$$ READ ONLY COPY of file <20>DEC2STR.a<>
; 1.1 CCH 11/11/1988 Fixed Header.
; 1.0 CCH 11/ 9/1988 Adding to EASE.
; OLD REVISIONS BELOW
; 1.0 BBM 2/12/88 Adding file for the first time into EASE<53>
; END EASE MODIFICATION HISTORY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; File: Dec2Str.TEXT
;; 68000 number formatter -- implements Pascal _dec2str
;; Status: BETA
;; Copyright Apple Computer, Inc. 1985
;; All Rights Reserved
;; Written by Kenton Hanson, Apple Numerics Group, 15 Jan 85
;;
;; Modification History:
;; 26/2/85 KLH To correct string '012' -> 0 case.
;; 13/8/85 KLH Altered DecForm to be passed by address
;; 19/8/85 KLH changed dec2str to _dec2str
;; 13/9/85 KLH switched order of movem & link/unlnk
;; to fix a register trashing bug
;;
;; Const
;; DECSTRLEN = 80;
;; SigDigLen = 20;
;; type
;; DecStr = string [DecStrLen];
;; Decimal = record
;; sgn : 0..1;
;; exp : integer;
;; sig : string [SigDigLen]
;; end;
;; DecForm = record
;; style : (FloatDecimal, FixedDecimal);
;; digits : integer
;; end;
;;
;; Procedure _dec2str (f : DecForm; d : Decimal; var s : DecStr) ;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The register conventions used throughout this code are:
;; A0 = address of output string, s.
;; A1 = address of decimal record, DR.,(sometimes used for powers of tens)
;; D0 = scratch
;; D1 = intialized to length of DR.sig
;; D2 = current length of output string - #wmax
;; D3 = scratch
;; D4 = contains DR sgn & exp
;; D5 = contains DecForm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; On entry to _dec2str the stack should look like:
;;
;; _______________________________________
;; | |
;; | f (decform), input |
;; |_______________________________________|
;; | |
;; | address of d (Decimal), output |
;; |_______________________________________|
;; | |
;; | address of s (decstr), output |
;; |_______________________________________|
;; | |
;; | return address |
;; |_______________________________________|
;;
;;
;; D2-D5 saved & restored
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Procedure _dec2str (var f : DecForm; d : Decimal; var s : DecStr) ;
BLANKS ON
STRING ASIS
_dec2str PROC EXPORT
S EQU 24 ; 24(a6) contains the address of DecStr
DR EQU 28 ; 28(a6) contains the address of Decimal Record
DF EQU 32 ; 32(a6) contains DecForm
wmax EQU 80 ; decstrlen (max string length for output)
movem.l d2-d5,-(sp) ; save registers <13/8/85>
link a6,#0 ; <13/8/85>
move.l DF(a6),a0 ; get address of DecForm
move.l (a0),d5 ; save DecForm in local register
move.l S(a6),a0 ; save address of DecStr
move.l DR(a6),a1 ; save address of Decimal Rec.
move.l (a1)+,d4 ; save DR sgn & exp
addq #1,a0 ; initialize a0 to 1st char of DS
move.l #-wmax,d2 ; initialize s length
moveq #0,d1
move.b (a1)+,d1 ; get length of DR.sig
beq.s ItsAPass ; ErrXit, null DR.sig
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; leading blank and sign logic
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;signStuff
btst #24,d4 ; test sgn bit in DR
beq.s HeyItsPos
move.b #'-',(a0)+ ; put '-' in output string
bra.s d2inc
HeyItsPos btst #24,d5 ; test style bit in DF
bne.s HeyItsFxd
move.b #' ',(a0)+ ; put ' ' in output string
d2inc addq #1,d2
HeyItsFxd move.b (a1),d0; ; get 1st chr of input string
cmpi.b #'?',d0
ItsAPass beq ErrXit
ori.b #$20,d0 ; change 'N' & 'I' -> 'n' & 'i'
cmpi.b #'i',d0
beq INFfound
cmpi.b #'n',d0
bne.s ItsANumber
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Construct NaN(XXX) string where XXX is the decimal NaN code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;NaNfound
move.b #'N',(a0)+
move.b #'A',(a0)+
move.b #'N',(a0)+ ; append 'NAN( )'
move.b #'(',(a0)+
move.b #')',3(a0)
addq #5,d2
moveq #0,d3 ; intialize binary NaN code
cmpi.b #5,d1
ble.s lngthOK ; 4 or less NaN code digits
moveq #5,d1
lngthOK bsr.s Hex2Bin
move.l d3,d0
bsr.s Hex2Bin
asl.b #4,d3
or.l d0,d3
FinNaN moveq #4,d0 ; set Bin2ASCII to 3 digit display
bra.s FromNaN
Hex2Bin subq #1,d1
ble.s FinNaN ; No NaN digits remaining
move.b 0(a1,d1),d3 ; get hex digit
cmpi.b #'9',d3
ble.s DecmlFnd ; its a decimal number
subq.b #7,d3 ; adjust for hex
DecmlFnd andi.b #15,d3 ; mask low order nibble
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set undefined Zero Exponent
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ItsANumber
cmpi.b #'0',(a1)
bne.s NotAZero
moveq #1,d1 ; length of DR.sig<-1 (26/2/85)
moveq #0,d4 ; initialize undefined exponent
; sign zapped, but don't need it
NotAZero btst #24,d5 ; test style bit in DF
bne ItsFixed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Floating Format
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ItsAFloat
tst.w d5 ; DF.digits - 1
bgt.s DigitsOK ; if digits < 1 then digits := 1
moveq #1,d5
DigitsOK moveq #1,d0
bsr.s AddDigits ; put first digit in output string
move.w d1,d3
ext.l d3
subq.l #1,d3 ; length(DR.sig) -1
bgt.s NeedPoint
cmpi.w #1,d5 ; DF.digits - 1
ble.s NoPoint
NeedPoint bsr.s AddPoint
move.w d3,d0
bsr.s AddDigits
move d5,d0
sub.w d1,d0 ; DF.digits - length (DR.sig)
bsr.s AddZeros
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Construct Exponent (also used for displaying NAN code)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NoPoint
addq.w #2,d2
bgt.s ErrXit ; output string too long
move.b #'e',(a0)+ ; append 'e'
; CPU Sickness, can't append 'e+' by move
; word, if destination is not on word boundary
ext.l d4 ; DR.exp
add.l d4,d3 ; DR.exp + (length(DR.sig) -1)
blt.s NegExp
move.b #'+',(a0)+ ; append '+' to output string
bra.s GetExpDigs
NegExp move.b #'-',(a0)+ ; append '-' to output string
neg.l d3
GetExpDigs
moveq #0,d0
FromNaN lea tens,a1 ; overwrite input (a1)
NextCmp addq #2,d0
cmp.w -2(a1,d0),d3
bcs.s GetInLoop
cmpi.b #8,d0
blt.s NextCmp
NextDig divu -2(a1,d0),d3
LastDig addq.w #1,d2 ; increment output string length
bgt.s ErrXit ; output string too long
addi #$30,d3 ; encode binary digit to ASCII code
move.b d3,(a0)+
swap d3
ext.l d3 ; clear hi word
GetInLoop subq #2,d0
bgt.s NextDig
beq.s LastDig
bra.s SetLength
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Append digits, '.' & zero stuff. Also Error Exit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
AddDigits ble.s EndDigits ; append no digits
add.w d0,d2 ; add d0 digits, d2 := new length
bgt.s ErrXit ; output string too long
loopd move.b (a1)+,(a0)+ ; append d0 '0' to output string
subq.w #1,d0 ; decrement d0
bgt.s loopd
EndDigits rts
AddPoint addq.w #1,d2
bgt.s ErrXit ; output string too long
move.b #'.',(a0)+ ; append '.' to output string
rts
loopz addq.w #1,d2
bgt.s ErrXit ; output string too long
move.b #'0',(a0)+ ; append d0 '0' to output string
AddZeros subq.w #1,d0 ; decrement d0
bge.s loopz
EndZeros rts
ErrXit move.l S(a6),a0 ; restore address of DecStr in a0
move.w #$013F,(a0) ; put '?' in output string
bra.s done
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fixed Format
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ItsFixed move.w d1,d3 ; copy length (DR.sig)
add.w d4,d3 ; DR.exp + length (DR.sig)
ble.s AllAfter ; all digits after
tst.w d4 ; DR.exp
bge.s AllBefore
move.w d3,d0
bsr.s AddDigits
bsr.s AddPoint
moveq #0,d0
sub.w d4,d0 ; 0 - DR.exp
bra.s FromMid
AllBefore move.w d1,d0
bsr.s AddDigits
move.w d4,d0
bsr.s AddZeros
move.w d5,d0
ble.s SetLength ; no digits after decimal point
bsr.s AddPoint
bsr.s AddZeros
bra.s SetLength
AllAfter moveq #1,d0
bsr.s AddZeros
bsr.s AddPoint
moveq #0,d0
sub.w d3,d0 ; 0 - (DR.exp + length (DR.sig))
bsr.s AddZeros
move.w d1,d0 ; length (DR.sig)
FromMid bsr.s AddDigits
move.w d4,d0 ; DR.exp
add.w d5,d0 ; DF.digits + DR.exp
bsr.s AddZeros
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; end of routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SetLength move.l S(a6),a0 ; restore address of DecStr in a0
addi.w #wmax,d2
move.b d2,(a0) ; set length of s
done unlk a6 ; <13/9/85>
movem.l (sp)+,d2-d5/a0 ; restore registers & return address
adda.w #12,sp ; clean up stack
jmp (a0) ; return
IF FSymOK THEN
DC.B '_dec2str'
ENDIF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Infinity & tens table
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INFfound
move.b #'I',(a0)+
move.b #'N',(a0)+ ; append 'INF'
move.b #'F',(a0)
addq #3,d2
bra.s SetLength
tens DC.W 10
DC.W 100
DC.W 1000
DC.W 10000