supermario/base/SuperMarioProj.1994-02-09/Toolbox/ScriptMgr/ScriptMgrUtilNum.a

4497 lines
128 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;
; File: ScriptMgrUtilNum.a (formerly SMgrUtilNum.a)
;
; Contains: Script Manager formatted number routines
;
; Written by: DRS daan Strebe
; MED Mark Davis
; LDC Lee Collins
; PKE Peter Edberg
;
; Copyright: © 1987-1992 by Apple Computer, Inc. All rights reserved.
;
; This file is used in these builds: ROM, disk
;
; Change History (most recent first):
;
; <SM3> 11/6/92 SWC Changed PackMacs.a->Packages.a.
; <8> 4/30/92 FM Remove obsolete conditionals: smgrUsesStdExit, smgrSysVers
; <7> 9/14/90 BG Removed <6>. 040s are now behaving more reliably.
; <6> 7/17/90 BG Added EclipseNOPs for flakey 040s.
; <5> 4/16/90 PKE Use smgrSysVers and smgrROMVers symbols instead of buildLevel to
; control conditionalization.
; <4> 4/10/90 PKE Deleted conditionalized definitions of forRom, SysVers, and
; TestScriptManager. Deleted import of GetSMgrCore macro! Fixed
; tabs. Used new smgrUseStdExit symbol instead of buildLevel where
; appropriate.
; <3> 3/4/90 PKE Changed _UprText to _UpperText to match new Traps.a.
; <2> 2/22/90 PKE Replaced obsolete _LwrStringToUpr opword with _UprText. Updated
; header to BBS format.
; <1> 12/18/89 CCH Adding for the first time into BBS. Changed include 'inc.sum.a'
; to load 'StandardEqu.d'. Updated file name references.
;
; (BBS versions above, EASE versions below:)
; <2.2> 8/26/89 PKE Cleaned up conditionals, changing newItl2Tables to buildLevel >=
; 1.
; <2.1> 8/22/89 SES Removed references to nFiles.
; <2.0> 6/30/89 PKE NEEDED FOR AURORA: Use new LwrString for localizable upper-
; casing (!) instead of UprString; change to use internal vectors
; for ROM version only. (First item is from code review, second
; item is only a change for 7.0).
; <1.9> 6/23/89 PKE Skip definition of buildLevel (done in ScriptPriv.a).
; <1.8> 5/22/89 PKE (Esprit needs this too): 1) Fix FormatStr2X to correct
; best-guess handling of negative numbers that don't match the
; format string (was broken by Altair changes). 2) Fix
; ConvertToString so that FormatX2Str handles a 0 value correctly
; in a format with an exponent (BRC #39590). 3) Change
; CheckForDigits and FormatStr2X so that when trying to match a
; number string to a zero format, non-zero digits are not accepted
; until after an exponent (fixes BRC #41209). 4) Fix Str2Format to
; impose tighter restrictions on format strings: it now disallows
; any format with preDig+postDig=0, unless it is just a literal
; with no decimal pt., exponent, or percent sign (fixes BRC
; #47210, 47211, 47212). 5) Fix FormatStr2X & FormatX2Str to check
; for invalid formats detected by Str2Format. 6) Fix
; CheckForm/SendItem so Format2Str returns correct positions (BRC
; #46877). NOTE: Should have more limit checking.
; <1.7> 2/21/89 PKE Replaced with RomProj version, which already had system and Rom
; sources merged.
; (EASE ROMproj history below)
; <1.5> 2/21/89 PKE Fix up includes: always use include 'inc.sum.a'. Fix bugs caused
; by old use of a5 as a temp register; this caused problems with
; the new method of getting case conversion tables out of itl2.
; For example, MatchingBlocks saves/restores a5, and uses it in
; between as a temp reg; but while a5 is altered, it calls
; MatchingSubstring, which calls CharComp, which calls UprString,
; which NOW calls IUGetIntl, which calls IntlScript, which depends
; on the a5 world. Still need to remove a5 use in xFormX2Str,
; which doesn't indirectly call UprString, but which should be
; fixed anyway. ALso, xFormStr2X unnecessarily saves a5.
; <1.4> 2/14/89 PKE Updated to use MPW 3.0 final ScriptEqu.a equate names
; <1.3> 2/3/89 PKE Merged with current system sources (CCH's 01/16/1989 merge of
; 6.0.3 and 7.0 sources, done in RES.sys:smgr)
; <1.2> 11/14/88 PKE Synchronize EASE and Projector
; <1.1> 11/11/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; (old EASE ROMproj history below)
; <1.7> 10/27/88 LDC Mods by Carl Hewitt and Brian McGhie in the process of putting
; Script Manager in ROM
; (EASE SYSproj history below)
; <1.6> 2/14/89 PKE Updated to use MPW 3.0 final ScriptEqu.a equates
; <1.5> 1/31/89 PKE One more "SysVers >= $700" conditionalization fixup
; <1.4> 1/31/89 PKE Use "SysVers >= $700" to conditionalize BEQ.S vs BEQ somewhere
; <1.3> 1/31/89 PKE Fixed up some of the "SysVers >= $700" conditionalization
; <1.2> 1/17/89 CCH Merged changes from 6.0.3.
; <1.1> 1/16/89 CCH Merged 6.0.3 final sources into 7.0.
; <1.0> 11/16/88 CCH Added to EASE.
; (pre-EASE history below)
; 9/21/88 ldc fixed bug #30677 and 30680, checking for multiple decimals and
; spurious chars
; 9/19/88 fixed bug #29602, non acceptance of #.##e+# format
; 9/8/88 ldc fixed 30678 (failure to detect overflow) in FormatStr2X and
; 33761 (confusion of overflow with nan)
; 9/7/88 ldc fixed failure to detect minus zero cf bug # 30675 and failure to
; detect empty format string (c.f. bug ddm #29008)
; 6/17/88 ldc Vectorized internal procs
; 5/19/88 ldc added standard exits
; * changes above are for ROM or buildLevel >= 2 *
; 4/14/88 ldc fix to problem with empty string not returning nan; changed
; failure to match literal string to return NAN(17), instead of
; fSpuriousChars ** Changes for ROM or buildLevel 2: **
; 4/4/88 ldc Changed NumFormatString record to FormatStringPriv
; 4/4/88 ldc fixed problem with random garbage after booting in Format2Str
; 3/31/88 ldc fixed FormatStr2X to allow output of 1 when positive format
; input is literal string containing no digits e.g., 'number' => 1
; 3/30/88 ldc fixed problem with not being able to output literal only format
; strings, e.g. 'zero', in FormatX2Str
; 3/28/88 ldc Fixed random bug caused by non initialization of length of
; outString in Format2Str
; 3/25/88 ldc added code in FormatX2Str to fix problem will excess clipping of
; predecimal leaders when non-leaders are present (#000.0 + 1.0 ->
; 001.0, not 1.0). Also compacted calls to DoSendChar in
; AppendSymbol
; 3/18/88 ldc found two more missing offsets to NumberParts.data
; 3/18/88 ldc Fixed bra.s to looptest
; 3/17/88 med IsSubstring: Since dan is using limits, not counts, a limit of
; zero means one character
; 3/17/88 ldc CheckExp: hanged because this was getting the wrong address
; 3/16/88 ldc Added boolean parameter "ignoreCase" to MatchingSubString
; 3/15/88 ldc Placed call UprString within CharComp
; 3/14/88 ldc Cleaned up after adding version to Number Parts table.
; 3/4/88 ldc added UprString to allow case insensitivity
; 2/25/88 med/ldc Fixed alternate digits address error and bad index.
; 2/25/88 med/ldc Fixed failure to detect overflow with ".##" + 345.0
; 2/25/88 drs also "bettered" the display zero paradigm
; 2/25/88 drs Fixed both open bugs in one fell swoop; "^.#" + 0 => "*.", but
; "*." not accepted on input, "#;#.#E+#'DB'" + 3.E+0DB => 3
; 2/24/88 ldc added 'fBestGuess' to flag case when no exact match is found
; 2/23/88 ldc replaced #1 with #fFormatOK
; 2/23/88 ldc fixed xyz -> nan,error; -xyz -> nan,noError
; 2/22/88 ldc removed nested LINK and UNLK in FormatStr2X
; 2/19/88 ldc Added debugging macros for symbol generation
; 2/8/88 med Fixed leaders to print correctly, not "^^^" => "***"
; 2/8/88 med Better bounds checking in SendChar
; 2/8/88 med Garbage input partially caught (drs)
; 2/8/88 med Special SANE values not caught (drs)
; 2/7/88 med Fixed embedded escaped characters in Format2Str.
; 2/7/88 med Changed TranslateText to use two-byte char for catching escaped
; characters
; 2/7/88 med Got quotes to work properly on Format2Str!
; 2/7/88 med misc fixes, some optimizations; lot of code transposition
; 2/7/88 med formCount is a byte
; 2/7/88 med Added some formatting with macros
; 1/25/88 med Dan added comments & fixed three minor bugs:
; "#.##'CR';#.##'DB'" + "2.1DB" didn't yield -2.1
; "##E#,###" + 1E1234 didn't yield "1E1,234"
; "#.#" + "2." ≠> 2.0
; 1/7/88 med Added inversion for odd cases
; 12/16/87 med Included Dans assemblyized versions, for comments see pascal
; version
;___________________________________________________________________________________________________
; To Do (old):
; Format Open features:
; Better alternate numbers selection.
; Leaders should act also as trailers: "###^^^.^^^###" + 3.4 => ***3.4***
; Less strict pattern-matching.
; General code review & optimization.
; E.g. Axe the addendum string in Translate to text, just append to dest string.
; Issue: On input, unquoteds get turned into quoteds
; What to do about '-' in the format string.
;___________________________________________________________________________________________________
STRING AsIs
MACRO
CheckDebug &thisProc
if testScriptManager then
dc.b &thisProc
endif
ENDM
load 'StandardEqu.d'
include 'ScriptPriv.a'
include 'SANEMacs.a'
include 'Packages.a'
IMPORT StdUnlink
EXPORT xStr2Form,xForm2Str,xFormX2Str,xFormStr2X
; internal routine exports <6/18/88ldc>
EXPORT AppendSymbol
EXPORT ConvertToString
EXPORT ExpHandling
EXPORT ExpMatching
EXPORT CheckForDigits
EXPORT MatchingSubstring
EXPORT Cond
EXPORT CheckForm
EXPORT TackOnExp
EXPORT MakeExp
EXPORT CheckPartsIntegrity
EXPORT RetrieveChar
EXPORT IsSubstring
;============================================================
macro
comp0 &a,&b,&c
if &substr(&a,1,1)<>'#' goto +.normal
if &eval(&substr(&a,2,&len(&a)-1))<>0 goto +.normal
tst&c &b
goto +.end
.normal:
cmp&c &a,&b
.end:
endMacro
macro
compw &a,&b
comp0 &a,&b,.w
endMacro
macro
compl &a,&b
comp0 &a,&b,.l
endMacro
macro
compb &a,&b
comp0 &a,&b,.b
endMacro
;============================================================
; Routine CharComp(char1,char2: HighChar): Boolean
;case insensitive comparison of two characters
;<3/15/88ldc> added CharComp
;
; trashes a0, d0, d1
; calls _UprString (6.0.4 & earlier)/_LwrString (new ROMs & 7.0)
;
; NOTE: UprString (called by CharComp) now depends on the a5 world,
; so don't muck around with a5 before calling CharComp! <02/21/89 pke>
; Actually, UprString is again independent of a5 world, but now we're
; using LwrString instead, which DOES depend on a5 world. <06/30/89 pke>
;
CharCompFrame record {oldA6},decrement
equal ds.w 1 ; return value
args equ *
char1 ds.w 1 ; char
char2 ds.w 1 ; char
argSize equ args-*
returnAdr ds.l 1
oldA6 ds.l 1
locals equ *
endr
;-------------------------------
CharComp proc
with CharCompFrame
link A6, #locals
lea char1(a6), a0 ; UprString uses a0 for string ptr
move.w #2, d0 ; apply UprString to one char
_UpperText ; _LwrString with smUpper function <3>
move.w (a0), d1
lea char2(a6), a0
move.w #2, d0 ; apply UprString to one byte
_UpperText ; _LwrString with smUpper function <3>
cmp.w (a0), d1
seq equal(a6)
move #argSize, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'CHARCOMP'
endwith
endp
;============================================================
; NextFormatClass
;
; trashes d0
; calls --
;
NextFormatClass proc
EXT.W D0
ADDQ.W #1,D0
compw #3,D0
BNE.S @L1
MOVEQ.L #0,D0
@L1:
RTS
endp
;============================================================
;<9/8/88ldc>
; Function GetSANEClass
; Gets SANE number class for extended
; input:
; a1 = ptr to extended
; output:
; d0 = class
; uses:
; a0
;<9/8/88ldc> SANE number classes
negZero equ $fffc ; -4 ie negative zero sane number class <9/7/88ldc>
posQNan equ $0002 ; positive quiet NAN
negQNan equ $fffe ; negative quiet NAN
posSNan equ $0001 ; positive signalling NAN
negSNan equ $ffff ; negative signalling NAN
posInf equ $0003 ; positive infinity
negInf equ $fffd ; negative infinity
posDeNorm equ $0005 ; positive denormalized
negDeNorm equ $fffb ; negative denormalized
GetSANEClass proc
clr.w -(sp) ; word storage
movea.l sp, a0 ; old stack position
move.l a1, -(sp) ; push x
move.l a0, -(sp) ; storage for temp integer
FClassX ; use SANE to get class
move.w (sp)+, d0 ; return value is now on top
rts
endp
;============================================================
IF 1 THEN ; unfinished--don't use yet <2/7/88med>
SendByte proc
; input a0 @StrPtr (length is actually max value)
; a1 @position for next char (1..254)
; d0 byte to add
; output d0 result code
; uses d1,d2
; function add byte to string. Omit nulls, and check for overflow
move.b d0,d1 ; null?
beq.s @SendOk ; skip
move.l #fFormatOverflow,d0 ; default result = bad
move.w (a1),d2 ; get next position (1.255)
cmp.b (a0),d2 ; compare max length
bhs.s @SendExit ; too big, bail
move.b d1,0(a0,d2.w) ; set byte
add.w #1,(a1) ; bump position
@SendOk
move.l #fFormatOK,d0 ; return ok
@SendExit
rts
endProc
;============================================================
SendCharRev0 proc
; input a0 @StrPtr (length is actually max value
; a1 @position for next char (1..254)
; d0 word to add
; output d0 result code
export SendChar0
ror.w #8,d0 ; exchange top and bottom bytes
SendChar0
move.w d0,-(sp) ; stash whole char
move.b (sp),d0 ; get top byte
bsr.s SendByte ; send it (if it is too far, next will be too)
move.w (sp)+,d0 ; get bottom byte (don't care about top)
bsr.s SendByte ; send it
rts
endProc
SendCharRev proc
export SendChar
topByte equ 12
botByte equ 13
textPtr equ 8
textLen equ 4
argBytes equ 10
MOVE.B topByte(A7),D0
MOVE.B botByte(A7),topByte(A7)
MOVE.B D0,botByte(A7)
; drop through
; discard this mess and use a register interface someday
; SendChar
; trashes a0-a1,d0,d2,d1 (in SendByte)
SendChar
move.l (a7)+,d2 ; return address
move.l (a7)+,a1 ; @position
move.l (a7)+,a0 ; @textPtr
move.w (a7)+,d0 ; word to add
move.l d2,-(a7) ; restore return
bsr.s SendChar0 ; do real routine
move.w d0,4(a7) ; set return
rts
endProc
;============================================================
ELSE
;============================================================
; old version was here
ENDIF
;------------------------------------------------------------
Str2FormFrame record {oldA61},decrement
returnValue1 ds.w 1 ; INTEGER
argFrameT1 EQU *
inString ds.l 1 ; VAR str255
partsTable ds.l 1 ; VAR NumberParts
outString ds.l 1 ; VAR NumFormatString
selector1 ds.l 1
argFrame1 EQU argFrameT1-*
return1 ds.l 1
oldA61 ds.l 1
formCount ds.b 1 ; formatClass
going ds.b 1 ; BOOLEAN
c ds.w 1 ; wideChar
outIndex ds.w 1 ; INTEGER
inIndex ds.w 1 ; INTEGER
res ds.w 1 ; INTEGER
thisCode ds.w 1 ; INTEGER
altNumFlag ds.b 1 ; BOOLEAN
ALIGN 2
currentFlags ds.w 1 ; BitPack
localFrame1 EQU *
ENDR
;============================================================
InUnquoteds proc
; moved in-line
endp
;============================================================
; RetrieveChar
;
; trashes a0,d0,d1
; uses/restores a2,a3,a4,d7
; calls _CharByte (may trash a0-a1,d0-d2)
;
RetrieveChar proc
;------------------------------------------------------------
retrieveCharFrame record {oldA62},decrement
returnValue2 ds.w 1 ; BOOLEAN
argFrameT2 EQU *
index ds.l 1 ; VAR INTEGER
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
k ds.w 1
localFrame2 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D7/A2-A4
indexR EQU A3
ff EQU A4
inStringR EQU A2
kR EQU D7
;============================================================
WITH Str2FormFrame,retrieveCharFrame
;pull the next character our of the input string, whether it be a
;single-byte character or a two-byte character
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVEA.L index(A6),indexR
MOVEA.L oldA6f2(A6),ff
CLR.W returnValue2(A6) ;default on null--the low byte usually is anyway
MOVEA.L inString(ff),inStringR ;we use inString fairly often
CLR.W D0
MOVE.B (inStringR),D0
compw (indexR),D0 ;check if we have source chars left
BLT.S @out
CLR.W -(A7) ;we need to check how many bytes in the next char
PEA 1(inStringR) ;address of first byte
MOVE.W (indexR),D0 ;index into string
SUBQ.W #1,D0 ;minus 1 for 0 based
MOVE.W D0,-(A7)
_CharByte
MOVE.W (A7)+,kR ;0 designates single byte char
BNE.S @twoByte
MOVE.W (indexR),D0 ;get the current character
CLR.W D1
MOVE.B 0(inStringR,D0.W),D1
MOVE.W D1,returnValue2(A6) ;put it in the return position
ADDQ.W #1,(indexR) ;and increment the index
BRA.S @out
@twoByte:
BPL.S @outOfSync ;positive CharByte means middle of two-byte char
MOVE.W (indexR),D0 ;make sure that if it's two byte then÷
CMP.B (inStringR),D0 ;there actually is a second byte
BGE.S @outOfSync
MOVE.B 0(inStringR,D0.W),returnValue2(A6) ;place the bytes
MOVE.B 1(inStringR,D0.W),(returnValue2+1)(A6)
ADDQ.W #2,(indexR) ;and increment index
BRA.S @out
@outOfSync:
MOVE.W #fOutOfSynch,returnValue1(ff) ;no integrity in input string
@out:
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'RETRIEVE'
ENDWITH
endp
;------------------------------------------------------------
CheckPartsIntegrityFrame record {oldA62},decrement
returnValue2 ds.w 1 ; BOOLEAN
argFrameT2 EQU *
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
temp ds.w 1 ; INTEGER
j ds.w 1 ; INTEGER
i ds.w 1 ; INTEGER
localFrame2 EQU *
ENDR
;============================================================
; CheckExp
;
; trashes a0,d0
; uses/restores a2,a3,a4,d6,d7
;
CheckExp proc
;------------------------------------------------------------
CheckExpFrame record {oldA63},decrement
argFrameT3 EQU *
exp ds.l 1 ; VAR wideCharArr
oldA6f3 ds.l 1
argFrame3 EQU argFrameT3-*
return3 ds.l 1
oldA63 ds.l 1
x ds.w 1 ; INTEGER
i ds.w 1 ; INTEGER
localFrame3 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D6/D7/A2-A4
ff EQU A2
ff1 EQU A3
partsTableR EQU A4
xR EQU D6
iR EQU D7
;============================================================
WITH Str2FormFrame,CheckPartsIntegrityFrame,CheckExpFrame
;make sure that the first character of the exponent doesn't coincide with…
;…any other first character
LINK A6,#localFrame3
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f3(A6),ff ;load up all the usuals
MOVEA.L oldA6f2(ff),ff1
; MOVEA.L (partsTable+NumberParts.data)(ff1),partsTableR
;<3/17/88ldc> changed because this was getting the wrong address
MOVEA.L partsTable(ff1),partsTableR
ADDA.W #NumberParts.data, partsTableR
MOVEA.L exp(A6),A0 ;examine the exponent
compw #0,WideCharArr.size(A0) ;does it have any characters in it? <2/7/88med>
blt.s @out ; zero test now <2/7/88med>
MOVE.W WideCharArr.data(A0),xR
BEQ.S @out ;just to be sure
MOVE.W #(tokMaxSymbols-1),iR ;check against the entire parts table
@expLoop:
compw (partsTableR)+,xR
DBEQ iR,@expLoop
BNE.S @out ;no match; we just ran out of data
CLR.B returnValue2(ff) ;we actually matched, which is an error
@out:
MOVEM.L (A7)+,localRegs
move #argFrame3, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'CHECKEXP'
ENDWITH
endp
;============================================================
; CheckPartsIntegrity
;
; trashes a0,d0,d1,d2
; uses/restores a4,d5-d7
; calls CheckExp, which trashes a0,d0
;
CheckPartsIntegrity proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D5-D7/A4
partsTableR EQU A4
iR EQU D7
tempR EQU D5
jR EQU D6
;============================================================
WITH Str2FormFrame,CheckPartsIntegrityFrame,NumberParts
;Test the internal integrity of the parts table by making sure that
;the first digit of any exponent string doesn't coincide with any other
;entries except other exponent strings; making sure that no other
;entries coincide with any other entries except for left vs. right
;quote marks and leadPlace vs. leader
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f2(A6),A0
MOVEA.L partsTable(A0),partsTableR
ST returnValue2(A6) ;be optimistic for once and assume no problem
; check the version
cmp.w #curNumberPartsVersion,version(partsTableR) ; good version?
bne @ReturnBadParts
; continue with check
MOVEQ #tokLeftQuote,iR ;i is the loop counter
BRA.S @endI
@forI:
MOVE.W iR,D0 ;collect the current sample
ADD.W D0,D0
MOVE.W (-(tokLeftQuote*2)+data)(partsTableR,D0.W),tempR
BEQ.S @contI ;ignore it if it's empty…
MOVE.W iR,jR ;…otherwise check against the rest of the table
ADDQ.W #1,jR ;starting 1 after self
BRA.S @endJ
@startJ:
MOVE.W jR,D0 ;make sure we have no duplicate entries
ADD.W D0,D0
compw (-(tokLeftQuote*2)+data)(partsTableR,D0.W),tempR
BNE.S @contJ ;we got a match
compw #tokLeadPlacer,iR ;but if it's leadPlacer vs. leader, then fine
SEQ D0
compw #tokLeader,jR
SEQ D1
AND.B D1,D0
compw #tokLeftQuote,iR ;or if it's leftQuote vs. rightQuote then fine
SEQ D1
compw #tokRightQuote,jR
SEQ D2
AND.B D2,D1
OR.B D1,D0
;; BNE.S @contJ
;; SF returnValue2(A6) ;it was neither, so bad break
beq.s @ReturnBadParts ; bail with bad value
@contJ:
ADDQ.W #1,jR ;on to the next
@endJ:
compw #tokMaxSymbols,jR ;but are we done?
BLE.S @startJ
@contI:
ADDQ.W #1,iR ;now increment the outer loop counter
@endI:
compw #(tokMaxSymbols-1),iR ;and check for done
BLE.S @forI
PEA PePlus(partsTableR) ;check the exponents
MOVE.L A6,-(A7)
JSR CheckExp
PEA PeMinus(partsTableR)
MOVE.L A6,-(A7)
JSR CheckExp
;<1/29/88drs> Changed 8 lines to fix what I'm sure was a bug but never showed up
LEA NumberParts.data(partsTableR),a0 ; use a0 as temp <2/25/88med>
MOVE.W #(tokMaxSymbols),iR ;we also need to make sure that…
@ccLoop: ;there are no control codes in the table
SUBQ.W #1,iR ;loop the loop
BLT.S @ccEnd
MOVE.W (a0)+,D0 ; use a0 as temp <2/25/88med>
BEQ.S @ccLoop ;null character is legal
compb #(tokMaxSymbols+1),D0 ;control char is not legal
BHS.S @ccLoop
bra.s @ReturnBadParts ; bail with bad value
;; SF returnValue2(A6) ;reflect your disappointment
@ccEnd:
cmp.w #9,altNumTable.size(partsTableR) ; right size? <2-25-88med/ldc>
beq.s @ccRealEnd ; escape if good <2-25-88med/ldc>
@ReturnBadParts
SF returnValue2(A6) ;reflect your disappointment <2-25-88med/ldc>
@ccRealEnd:
MOVEM.L (A7)+,localRegs
UNLK A6
MOVE.L (A7)+,(A7)
RTS
CheckDebug 'CHECKPAR'
ENDWITH
endp
;------------------------------------------------------------
MakeExpFrame record {oldA62},decrement
returnValue2 ds.w 1 ; BOOLEAN
argFrameT2 EQU *
exp ds.l 1 ; VAR WideCharArr
expOrd ds.w 1 ; INTEGER
expChar ds.w 1 ; CHAR
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
localFrame2 EQU *
ENDR
;============================================================
; IsSubstring
;
; trashes a0,d0,d1 (maybe a1,d2)
; uses/restores a3,a4,d7
; calls RetrieveChar, which trashes a0,d0,d1 (maybe a1,d2)
;
IsSubstring proc
;------------------------------------------------------------
isSubStringFrame record {oldA63},decrement
returnValue3 ds.w 1 ; BOOLEAN
argFrameT3 EQU *
oldA6f3 ds.l 1
argFrame3 EQU argFrameT3-*
return3 ds.l 1
oldA63 ds.l 1
res ds.w 1 ; INTEGER
k ds.w 1 ; INTEGER
j ds.w 1 ; INTEGER
localFrame3 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D7/A3/A4
ff EQU A3
ff1 EQU A4
kR EQU D7
;============================================================
WITH Str2FormFrame,MakeExpFrame,IsSubStringFrame, SMgrRecord
;determine whether the input string at this point matches whichever
;exponent string we send
LINK A6,#localFrame3
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f3(A6),ff
MOVEA.L oldA6f2(ff),ff1
MOVEQ #1,kR ;k is index into exp
MOVE.W inIndex(ff1),j(A6) ;j is index into comparator
SF returnValue3(A6) ;assume no it's not a substring
MOVEA.L exp(ff),A0 ;get the exp structure
;; compw WideCharArr.size(A0),kR ;and make sure it's not empty
;; BGT.S @out ;don't compare nothing
; <3/17/88med> since dan is using limits, not counts, a limit of zero means one character
; and since the first character has already been tested, just jump to the end to test
bra.s @LoopTest ; test for done.
@loop:
MOVEA.L inString(ff1),A0 ;if j is beyond end of inString,
CLR.W D0 ;then we're done comparing
MOVE.B (A0),D0
compw j(A6),D0
BLT.S @out
CLR.W -(A7) ;result space
PEA j(A6) ;index into inString
MOVE.L ff1,-(A7) ;the ubiquitous frame pointer
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup for vector call <6/17/88ldc>
move.l sVectRetrieveChar(a0), a0 ; <6/17/88ldc>
jsr (a0)
ELSE
JSR RetrieveChar ;get the next character
ENDIF
MOVE.W (A7)+,c(ff1) ;and move it into c
MOVEA.L exp(ff),A0 ;compare c to exp.data[k]
MOVE.W kR,D0
ADD.W D0,D0
MOVE.W c(ff1),D1
compw WideCharArr.data(A0,D0.W),D1
BNE.S @out ;if it doesn't match, just leave
ADDQ.W #1,kR ;otherwise advance pointer
MOVEA.L exp(ff),A0 ;and check if we've run out of exp
;<3/18/88ldc> moved looptest up to here
@LoopTest
compw WideCharArr.size(A0),kR
BLE.S @loop
MOVE.W j(A6),inIndex(ff1) ;update index from j
ST returnValue3(A6) ;and report the results
@out:
MOVEM.L (A7)+,localRegs
UNLK A6
MOVE.L (A7)+,(A7)
RTS
CheckDebug 'ISSUBSTR'
ENDWITH
endp
;============================================================
; MakeExp
;
; trashes a0,d0,d1 (maybe a1,d2)
; uses/restores a3-a4
; calls IsSubstring, which trashes a0,d0,d1 (maybe a1,d2)
;
MakeExp proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg A3/A4
ff EQU A4
outStringR EQU A3
;============================================================
WITH Str2FormFrame,MakeExpFrame,FormatStringPriv, SMgrRecord
;if we encounter an exponent, say so and parse beyond it
;and insert the appropriate exponent character into the form string
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f2(A6),ff
MOVEA.L outString(ff),outStringR
SF returnValue2(A6) ;assume the worst
CLR.W -(A7) ;first determine if inString is a…
MOVE.L A6,-(A7) ;…subset of exp
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup for vector call <6/17/88ldc>
move.l sVectIsSubstring(a0),a0 ; <6/17/88ldc>
jsr (a0)
ELSE
JSR IsSubstring
ENDIF
MOVE.B (A7)+,D0
BEQ.S @out ;and just forget it if not
MOVE.W currentFlags(ff),D0 ;see if we've already encountered an exp
AND.L #fEMEP,D0
BEQ.S @noDupExp
MOVE.W #fExtraExp,returnValue1(ff)
BRA.S @flagOut ;set extra exponent flag and quit
@noDupExp:
BTST #fIsDecimal,currentFlags(ff)
BNE.S @contDec ;if we never ran into a decimal point…
MOVE.B formCount(ff),D0 ;then we should insert it now before the exp
EXT.W D0
ADD.W D0,D0
MOVE.W outIndex(ff),decLocs(outStringR,D0.W)
@contDec:
MOVE.W expOrd(A6),D0 ;set whichever exp flag we're dealing with
MOVE.W D0,D1
ASR.W #3,D0
BSET D1,currentFlags(ff,D0.W)
MOVE.W outIndex(ff),D0 ;append the exp symbol to the form string
MOVE.B (expChar+1)(A6),formString(outStringR,D0.W)
ADDQ.W #1,outIndex(ff) ;and increment the form string index
@flagOut:
ST returnValue2(A6) ;we did indeed encounter an exponent
@out:
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'MAKEEXP '
ENDWITH
endp
;============================================================
; ProcessLead
;
; trashes a0,d0,d1
;
ProcessLead proc
;------------------------------------------------------------
processLeadFrame record {oldA62},decrement
argFrameT2 EQU *
;x ds.w 1 ; INTEGER PASSED IN D0
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
localFrame2 EQU *
ENDR
;============================================================
WITH Str2FormFrame,processLeadFrame,FormatStringPriv
;process any digit placeholder by putting it into the form string
;and adding it to the count of digits
MOVEA.L outString(A6),A0
MOVE.W outIndex(A6),D1
MOVE.B D0,formString(A0,D1.W) ;move the leader into the form string
ADDQ.W #1,outIndex(A6) ;and advance the form string index
MOVE.W currentFlags(A6),D0 ;if we have not encountered an exponent…
AND.L #fEMEP,D0
BNE.S @out
MOVE.B formCount(A6),D0 ;then increment postDig or preDig,…
EXT.W D0 ;…depending on whether we've hit a decimal yet
ADD.W D0,D0
BTST #fIsDecimal,currentFlags(A6)
BEQ.S @noDec
ADDQ.W #1,postDig(A0,D0.W)
BRA.S @out
@noDec:
ADDQ.W #1,preDig(A0,D0.W)
@out:
RTS
CheckDebug 'PROCESSL'
ENDWITH
endp
;============================================================
; GetC
;
; trashes a0 (,d0,d1) (maybe a1,d2)
; calls RetrieveChar, which trashes a0,d0,d1 (maybe a1,d2)
;============================================================
GetC proc
WITH Str2FormFrame, SMgrRecord
;a common enough used sequence of code to justify its own routine
CLR.W -(A7) ; return space
PEA inIndex(A6) ; index into inString
MOVE.L A6,-(A7) ; frame pointer
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup for vector call <6/17/88ldc>
move.l sVectRetrieveChar(a0), a0 ; <6/17/88ldc>
jsr (a0)
ELSE
JSR RetrieveChar
ENDIF
MOVE.W (A7)+,c(A6) ;and place the result in C
RTS
ENDWITH
endp
;============================================================
; xStr2Form
;
; trashes a0-a1,d0-d2
; uses/restores a3-a4,d3-d7
; calls CheckPartsIntegrity here trashes a0,d0-d2
; GetC here trashes a0,d0-d1 (maybe a1,d2)
; SendChar here trashes a0-a1,d0-d2
; ProcessLead here trashes a0,d0-d1
; CharComp here trashes a0,d0-d1
; MakeExp here trashes a0,d0-d1 (maybe a1,d2)
;
; NOTE: UprString (called by CharComp) now depends on the a5 world,
; so don't muck around with a5 before calling CharComp! <02/21/89 pke>
; Actually, UprString is again independent of a5 world, but now we're
; using LwrString instead, which DOES depend on a5 world. <06/30/89 pke>
;
xStr2Form proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D3-D7/A3/A4 ; don't need a2,a5 <02/21/89 pke>
resR EQU D6
outStringR EQU A4
partsTableR EQU A3
altNumFlagR EQU D4
thisCodeR EQU D7
goingR EQU D5
;============================================================
WITH Str2FormFrame,FormatStringPriv,NumberParts, SMgrRecord
LINK A6,#localFrame1
MOVEM.L localRegs,-(A7)
MOVE.W #fFormatOK,returnValue1(A6) ; be optimistic about the result
MOVEQ #fFormatOK,resR ; let resR handle immediate results
CLR.W -(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup for vector call <6/17/88ldc>
move.l sVectCheckPartsIntegrity(a0),a0 ; <6/17/88ldc>
jsr (a0)
ELSE
JSR CheckPartsIntegrity ; first see that the parts table is ok
ENDIF
MOVE.B (A7)+,D0
BNE.S @partsTableOk ; and if it's not then report it
MOVE.W #fBadPartsTable,returnValue1(A6)
BRA @out
@partsTableOk:
MOVEA.L outString(A6),outStringR ; otherwise load up a reg or two
MOVEA.L partsTable(A6),partsTableR
MOVEQ.L #(2*fZero),D3 ; clear out all the flags
@clearFlags:
CLR.W flags(outStringR,D3.W)
CLR.W decLocs(outStringR,D3.W)
MOVE.W #1,startLocs(outStringR,D3.W) ; for null formats, point past end of string
CLR.W preDig(outStringR,D3.W)
CLR.W postDig(outStringR,D3.W)
SUBQ.B #2,D3
BPL.S @clearFlags
;; MOVE.W #fPositive,formCount(A6) ;start out with positive format string
move.b #fPositive,formCount(A6) ;start with positive format string <2/7/88med>
compw #'#',(((tokNonLeader-tokLeftQuote)*2)+data)(partsTableR)
SNE altNumFlagR ;if the nonLead symbol is not an…
BEQ.S @noAltF ;…ascii '#' then assume foreign digits
MOVE.W #fExAlF,currentFlags(A6) ;turn on the alternate digits flag…
BRA.S @altFCont ;…and the exists flag
@noAltF:
MOVE.W #fEXISTF,currentFlags(A6) ;otherwise turn on just the exists flag
@altFCont:
moveq #1,d0 ;scratch <2/7/88med>
MOVE.W d0,inIndex(A6) ;set up string indices <2/7/88med>
MOVE.W d0,outIndex(A6) ; <2/7/88med>
MOVE.B #(255-fixedLength),formString(outStringR) ;and give a maximum length
MOVEA.L inString(A6),A0
MOVE.B (A0),D0
beq @emptyInString ; detect empty instring <9/7/88ldc>
st goingR ; if inString[0] is null then don't bother
@whileGoing:
MOVE.B goingR,D0 ;still looping?
BEQ @endWhileGoing
CLR.W D0 ;if we've gone beyond the physical limits…
MOVE.B formString(outStringR),D0 ;…of the format string then bomb
compw outIndex(A6),D0
BGE.S @noOverflow
MOVE.W #fFormatOverflow,returnValue1(A6)
BRA @out
@noOverflow:
JSR GetC ;get next character in c(A6)
MOVE.W #(tokLeftQuote-1),thisCodeR ;start ourselves off at the beginning
@seekMatch:
ADDQ.W #1,thisCodeR ;pre-increment
compw #tokDecPoint,thisCodeR ;decPoint is the last we're concerned with
BGT.S @doneSeekMatch ;so if we've passed that, then forget it
MOVE.W thisCodeR,D1 ;otherwise check the char against table entries
ADD.W D1,D1
MOVE.W c(A6),D2
compw (-(tokLeftQuote*2)+data)(partsTableR,D1.W),D2
BNE.S @seekMatch ;try again if no match
@doneSeekMatch:
MOVE.W thisCodeR,D0 ;CASE thisCode OF
SUBQ.W #tokLeftQuote,D0 ;leftQuote is lowest
BMI @endCase
compw #(tokEPlus-tokLeftQuote),D0 ;EPlus is the highest
BGT @endCase
ADD.W D0,D0
MOVE.W @jTab(D0.W),D0
JMP *+2(D0.W)
@jTab:
DC.W @leftQuote-@jTab+2, @rightQuote-@jTab+2, @leadPlacer-@jTab+2
DC.W @garbage-@jTab+2, @rLeads-@jTab+2, @rLeads-@jTab+2
DC.W @percent-@jTab+2, @signs-@jTab+2, @signs-@jTab+2
DC.W @signs-@jTab+2, @garbage-@jTab+2, @separator-@jTab+2
DC.W @garbage-@jTab+2, @decPoint-@jTab+2, @others-@jTab+2
@leftQuote:
@seekRightQuote:
JSR GetC ;just start looking for right qoute
MOVE.W c(A6),D0 ;but beware of escapes
compw (((tokEscape-tokLeftQuote)*2)+data)(partsTableR),D0
BNE.S @escapeMerge
JSR GetC ;found escape so just go right into next char
CLR.W -(A7)
MOVE.W c(A6),-(A7)
PEA formString(outStringR)
PEA outIndex(A6) ;and process it
JSR SendChar
OR.W (A7)+,resR
;<1/29/88drs> Changed 1 line to fix bug
;Could have two escape+c in a row, so loop back to seekRightQuote
BRA.S @seekRightQuote
@escapeMerge:
MOVE.W c(A6),D0 ;check for right quote
BEQ.S @L902
compw (((tokRightQuote-tokLeftQuote)*2)+data)(partsTableR),D0
BEQ @endCase ;and just quit if we find it
CLR.W -(A7) ;otherwise send out whatever we find
MOVE.W c(A6),-(A7)
PEA formString(outStringR)
PEA outIndex(A6)
JSR SendChar
OR.W (A7)+,resR
BRA.S @seekRightQuote
@L902:
MOVE.W #fMissingLiteral,returnValue1(A6)
BRA @endCase
@rightQuote: ;right quote without left is an error
MOVE.W #fMissingDelimiter,returnValue1(A6)
BRA @endCase
@rLeads: ;either zeroLead or nonLead comes here
MOVE.W thisCodeR,D0
JSR ProcessLead
BRA @endCase
@leadPlacer: ;lead placer is replaced by the actual lead symbol
MOVE.W #tokLeader,D0
JSR ProcessLead
BRA @endCase
@decPoint:
BTST #fIsDecimal,currentFlags(A6)
BEQ.S @noExtraDec ;error if more than one decimal
MOVE.W #fExtraDecimal,returnValue1(A6)
BRA.S @dOut
@noExtraDec:
MOVE.W outIndex(A6),D0 ;append decimal point to format string
MOVE.B #tokDecPoint,formString(outStringR,D0.W)
MOVE.B formCount(A6),D0 ;and record its position
EXT.W D0
ADD.W D0,D0
MOVE.W outIndex(A6),decLocs(outStringR,D0.W)
ADDQ.W #1,outIndex(A6) ;increment form string index
BSET #fIsDecimal,currentFlags(A6) ;and say we got a decimal point
@dOut:
BRA @endCase
@percent:
BTST #fIsPercent,currentFlags(A6) ;make sure we don't already…
BEQ.S @noExtraPercent ;…have a percent sign
MOVE.W #fExtraPercent,returnValue1(A6) ;record error if we do
BRA.S @pOut
@noExtraPercent:
BSET #fIsPercent,currentFlags(A6) ;say we got one
MOVE.W outIndex(A6),D0 ;and record its position
MOVE.B thisCodeR,formString(outStringR,D0.W)
ADDQ.W #1,outIndex(A6) ;increment form string pointer
@pOut:
BRA @endCase
@separator:
compb #fZero,formCount(A6) ;if we've already got 3 formats…
BNE.S @noExtraSep ;…then it's an error
MOVE.W #fExtraSeparator,returnValue1(A6)
BRA.S @sOut
@noExtraSep:
MOVE.B formCount(A6),D1 ;if we have no decimal point,…
EXT.W D1 ;…and no exponent then make up a…
ADD.W D1,D1 ;…decimal point
MOVE.W currentFlags(A6),D0
AND.L #fDEMEP,D0
BNE.S @noFakeDec
MOVE.W outIndex(A6),decLocs(outStringR,D1.W)
@noFakeDec:
MOVE.W preDig(outStringR,D1.W),D0 ;
ADD.W postDig(outStringR,D1.W),D0 ;
BNE.S @nullFmtTest1Done ;if preDig+postDig≠0, OK
MOVE.W outIndex(A6),D0 ;
CMP.W startLocs(outStringR,D1.W),D0 ;
BLE.S @nullFmtTest1Bad ;otherwise, bad if null length
MOVE.W currentFlags(A6),D0 ;
AND.W #fDPEMEP,D0 ;otherwise, if no dec pt, percent,
BEQ.S @nullFmtTest1Done ; or exponent, then OK
@nullFmtTest1Bad: ;
CLR.W flags(outStringR,D1.W) ;
MOVE.W #fEmptyFormatString,resR ;
BRA @nullFmtExit ;
@nullFmtTest1Done:
MOVE.W currentFlags(A6),flags(outStringR,D1.W) ;save flag set
ADDQ.B #1,formCount(A6) ;advance formCount
MOVE.B altNumFlagR,D0 ;record just-finished format's…
BEQ.S @noAltDig ;…alternate digit record
MOVE.W #fExAlF,currentFlags(A6)
BRA.S @mergeAltDig
@noAltDig:
MOVE.W #fEXISTF,currentFlags(A6)
@mergeAltDig:
MOVE.B formCount(A6),D0 ;and record the starting location…
EXT.W D0 ;…of this format
ADD.W D0,D0
MOVE.W outIndex(A6),startLocs(outStringR,D0.W)
@sOut:
BRA @endCase
@signs: ;plus, minus, thousands
MOVE.W outIndex(A6),D0 ;just record its position
MOVE.B thisCodeR,formString(outStringR,D0.W)
ADDQ.W #1,outIndex(A6) ;and increment form string index
BRA @endCase
@garbage: ;escape, noRoomFill, leader
MOVE.W #fSpuriousChars,returnValue1(A6)
BRA @endCase
@others: ;including exponents and unquoteds
; MOVE.W c(A6),D0 ;Check against E+ format
; compw (PePlus+WideCharArr.data)(partsTableR),D0
;<3/15/88ldc> added case insensitive character comparison routine "CharComp"
clr.w -(a7)
move.w c(a6), -(a7)
move.w (PePlus+WideCharArr.data)(partsTableR), -(a7)
jsr CharComp
tst.b (a7)+
beq.s @notEPlus ;if partsTable.PePlus.data <> c then not EPlus
CLR.W -(A7) ;result room
PEA PePlus(partsTableR)
MOVE.W #fIsEPlus,-(A7)
MOVE.W #tokEPlus,-(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup for vector call <6/17/88ldc>
move.l sVectMakeExp(a0), a0 ; <6/17/88ldc>
jsr (a0)
ELSE
JSR MakeExp ;see if the entire EPlus is there
ENDIF
MOVE.B (A7)+,D0
BNE.S @matchEPlus
CLR.W -(A7) ;if not then try EMinus
PEA PeMinus(partsTableR)
MOVE.W #fIsEMinus,-(A7)
MOVE.W #tokEMinus,-(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup for vector call <6/17/88ldc>
move.l sVectMakeExp(a0), a0 ; <6/17/88ldc>
jsr (a0)
ELSE
JSR MakeExp ;see if the entire EPlus is there
ENDIF
MOVE.B (A7)+,D0
BNE.S @matchEMinus
MOVE.W #fSpuriousChars,returnValue1(A6) ;otherwise it's junk
@matchEPlus:
@matchEMinus:
BRA.S @endCase
@notEPlus:
; MOVE.W c(A6),D0
; compw (PeMinus+WideCharArr.data)(partsTableR),D0
;<3/15/88ldc> added case insensitive character comparison routine "CharComp"
clr.w -(a7) ;try EMinus
move.w c(a6), -(a7)
move.w (PeMinus+WideCharArr.data)(partsTableR), -(a7)
jsr CharComp
tst.b (a7)+
beq.S @notEMinus
CLR.W -(A7)
PEA PeMinus(partsTableR)
MOVE.W #fIsEMinus,-(A7)
MOVEQ #tokEMinus,D0
MOVE.W D0,-(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup for vector call <6/17/88ldc>
move.l sVectMakeExp(a0), a0 ; <6/17/88ldc>
jsr (a0)
ELSE
JSR MakeExp ;see if the entire EPlus is there
ENDIF
MOVE.B (A7)+,D0
BNE.S @wasEMinus ;if this didn't work then it's junk
MOVE.W #fSpuriousChars,returnValue1(A6)
@wasEMinus:
BRA.S @endCase
@notEMinus:
LEA ((tokMaxSymbols-1)*2)(partsTableR),A1
MOVE.W c(A6),D1 ;try the unquoteds table
BEQ.S @junkC ;a null char is unfathomable
MOVEQ #(tokEMinus-1),D2 ;loop counter
@UQLoop:
compw -(A1),D1
DBEQ D2,@UQLoop ;stop if a match
BNE.S @junkC ;this character doesn't belong
CLR.W -(A7) ;send the code off
MOVE.W c(A6),-(A7)
PEA formString(outStringR)
PEA outIndex(A6)
JSR SendChar
OR.W (A7)+,resR
BRA.S @endCase
@junkC:
MOVE.W #fSpuriousChars,returnValue1(A6)
@endCase:
MOVEA.L inString(A6),A0 ;make sure we haven't exceeded the input string
CLR.W D0
MOVE.B (A0),D0
compw inIndex(A6),D0
BGE.S @cGo
SF goingR
@cGo:
BRA @whileGoing
@emptyInString
move.w #fEmptyFormatString, resR ;signal empty format string <9/7/88ldc>
bclr.b #fExists,currentFlags(A6) ;turn off exists flag <05/22/89 pke>
@endWhileGoing:
MOVE.B formCount(A6),D1 ;update flags from temp flag word
EXT.W D1
ADD.W D1,D1
MOVE.W preDig(outStringR,D1.W),D0 ;
ADD.W postDig(outStringR,D1.W),D0 ;
BNE.S @nullFmtTest2Done ;if preDig+postDig≠0, OK
MOVE.W outIndex(A6),D0 ;
CMP.W startLocs(outStringR,D1.W),D0 ;
BLE.S @nullFmtTest2Bad ;otherwise, bad if null length
MOVE.W currentFlags(A6),D0 ;
AND.W #fDPEMEP,D0 ;otherwise, if no dec pt, percent,
BEQ.S @nullFmtTest2Done ; or exponent, then OK
@nullFmtTest2Bad: ;
CLR.W currentFlags(A6) ;
MOVE.W #fEmptyFormatString,resR ;
@nullFmtTest2Done:
MOVE.W currentFlags(A6),flags(outStringR,D1.W)
MOVEQ #0,D0 ;if we never hit decimal or exponent…
MOVE.W currentFlags(A6),D0 ;…then make up a decimal point at…
AND.L #fDEMEP,D0 ;…this position
BNE.S @contDEMEP
MOVE.W outIndex(A6),decLocs(outStringR,D1.W)
@contDEMEP:
@nullFmtExit: ; <05/22/89 pke>
CMP.B #fPositive,formCount(A6)
BNE.S @notPos ;if the last form was positive then init others
MOVE.W outIndex(A6),(startLocs+(2*fNegative))(outStringR)
@doZero:
MOVE.W outIndex(A6),(startLocs+(2*fZero))(outStringR)
BRA.S @mergeP
@notPos:
compb #fNegative,formCount(A6)
BEQ.S @doZero
@mergeP:
MOVE.W outIndex(A6),startLocs(outStringR)
MOVE.W outIndex(A6),D0 ;set startLocs[fPositive] past last form string code
SUBQ.W #1,D0
MOVE.B D0,formString(outStringR)
;<1/23/88drs> Added 2 lines to compute dynamic record length
ADD.B #fixedLength,D0
MOVE.B D0,fLength(outStringR)
compw #fFormatOK,resR ;if resR got changed then say so
BEQ.S @out
MOVE.W resR,returnValue1(A6)
@out:
;<1/23/88drs> Added 1 line to insert version number
MOVE.B #fVNumber,fVersion(outStringR)
MOVEM.L (A7)+,localRegs
move #argFrame1, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'STR2FORM'
endp
maxString EQU 50
;------------------------------------------------------------
Form2StrFrame record {oldA61},decrement
returnValue1 ds.w 1 ; INTEGER
argFrameT1 EQU *
myCanonical ds.l 1 ; VAR NumFormatString
partsTable ds.l 1 ; VAR NumberParts
outString ds.l 1 ; VAR str255
positions ds.l 1 ; VAR TripleInt
selector1 ds.l 1
argFrame1 EQU argFrameT1-*
return1 ds.l 1
oldA61 ds.l 1
res ds.w 1 ; INTEGER
;<4/1/88ldc> removed the unused i
;i ds.w 1 ; INTEGER
j ds.w 1 ; INTEGER
formCount ds.b 1 ; formatClass
hold12 ds.l 1
hold11 ds.w 1
inLiteral ds.b 1 ; boolean
pad ds.b 1
localFrame1 EQU *
ENDR
;------------------------------------------------------------
TranslateToTextFrame record {oldA62},decrement
argFrameT2 EQU *
source ds.w 1 ; CHAR
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
addendum ds.b maxString ; string
iIndex ds.w 1 ; INTEGER
hold2 ds.w 1
localFrame2 EQU *
ENDR
;============================================================
; TackOnExp
;
; trashes a0,d0
; uses/restores a2-a4,d7
; calls SendChar, which trashes a0-a1,d0-d2
;
TackOnExp proc
;------------------------------------------------------------
TackOnExpFrame record {oldA63},decrement
argFrameT3 EQU *
exp ds.l 1 ; VAR WideCharArr
oldA6f3 ds.l 1
argFrame3 EQU argFrameT3-*
return3 ds.l 1
oldA63 ds.l 1
xj ds.w 1
hold3 ds.w 1
localFrame3 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D7/A2-A4 ; don't need a5 <02/21/89 pke>
ff EQU A3
ff1 EQU A4
expR EQU A2
;============================================================
WITH Form2StrFrame,TranslateToTextFrame,TackOnExpFrame
;FOR xj:= 0 TO exp.size DO BEGIN
; res:= SendChar(exp.data[xj], addendum, i); END;
LINK A6,#localFrame3
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f3(A6),ff
MOVEA.L oldA6f2(ff),ff1
MOVEA.L exp(A6),expR
MOVE.W WideCharArr.size(expR),hold3(A6)
LEA WideCharArr.data(expR),expR
CLR.W D7
BRA.S @L448
@L451:
CLR.W -(A7)
MOVE.W (expR)+,-(A7)
PEA addendum(ff)
PEA iIndex(ff)
JSR SendChar
MOVE.W (A7)+,res(ff1)
ADDQ.W #1,D7
@L448:
compw hold3(A6),D7
BLE.S @L451
@L450:
MOVEM.L (A7)+,localRegs
move #argFrame3, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'TACKONEX'
ENDWITH
endp
;============================================================
TranslateToText proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D7/A3/A4
sourceR EQU D7
ff EQU A4
partsTableR EQU A3
;============================================================
WITH Form2StrFrame,TranslateToTextFrame,NumberParts, SMgrRecord
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVE.W source(A6),sourceR
MOVEA.L oldA6f2(A6),ff
;WITH partsTable DO BEGIN
; i:= 1;
; addendum[0]:= CHR(maxString-1);
MOVEA.L partsTable(ff),partsTableR
MOVE.W #1,iIndex(A6)
MOVE.B #(maxString-1),addendum(A6)
;IF ORD(source) < maxSymbols+1 THEN BEGIN
; CASE ORD(source) OF
TransSendMask set 1<<tokLeader++1<<tokZeroLead
TransSendMask set TransSendMask++1<<tokNonLeader++1<<tokDecPoint++1<<tokPercent
TransSendMask set TransSendMask++1<<tokPlusSign++1<<tokMinusSign++1<<tokThousands
; remove 1<<tokLeftQuote++1<<rightQuote++1<<escape-- they should not occur
compw #(tokMaxSymbols+1),sourceR
BGE @TransLiteral ; changed branch from short <3/14/88ldc>
; if not now in literal, send a left quote if was inliteral <2/7/88med>
tst.b inLiteral(ff) ; inside quoted literal?
beq.s @NoLiteral ; no, done
sf inLiteral(ff) ; out of here
CLR.W -(A7)
MOVE.W ((tokLeftQuote-tokLeftQuote)*2+data)(partsTableR),-(A7)
PEA addendum(A6)
PEA iIndex(A6)
JSR SendChar
MOVE.W (A7)+,res(ff)
@NoLiteral
;; MOVE.L #$000067F6,D0
move.l #TransSendMask,d0 ; use equate
BTST.L sourceR,D0
BNE.S @SendTransChar
;; MOVE.L #$00001808,D0 ; indicate anything unknown
;; BTST.L sourceR,D0 ;
;; BNE.S @TransUnknownChar ; now at end of tests
compw #tokEPlus,sourceR
BEQ.S @TransExpPlus
compw #tokEMinus,sourceR
BEQ.S @TransExpMinus
BRA.S @TransUnknownChar ; anything we don't know
; leftQuote,
; rightQuote,
; leader,
; zeroLead,
; nonLeader,
; decPoint,
; percent,
; plusSign,
; minusSign,
; thousands,
; escape: res:= SendChar(data[ORD(source)], addendum, i);;
@SendTransChar:
CLR.W -(A7)
; fix leader
move.w #tokLeadPlacer*2,d0 ; assume special case <2/8/88med>
cmp.w #tokLeader,sourceR ; special case <2/8/88med>
beq.s @GotFixedChar ; <2/8/88med>
MOVE.W sourceR,D0
ADD.W D0,D0
@GotFixedChar
MOVE.W (-(tokLeftQuote*2)+data)(partsTableR,D0.W),-(A7)
PEA addendum(A6)
PEA iIndex(A6)
JSR SendChar
MOVE.W (A7)+,res(ff)
BRA.S @TransDone
; noRoomFill,
; leadPlacer,
; separator: BEGIN
; addendum:= '???';
; i:= 4; END;
@TransUnknownChar:
MOVE.L #('???' + (3 << 24)),addendum(A6)
MOVE.W #4,iIndex(A6)
BRA.S @TransDone
; ePlus: TackOnExp( PePlus );
@TransExpPlus:
PEA PePlus(partsTableR)
bra.s @TransExpCommon ; join common code <2/7/88med>
;; MOVE.L A6,-(A7) ; common <2/7/88med>
;; JSR TackOnExp ; common <2/7/88med>
;; BRA.S @TransDone ; common <2/7/88med>
; eMinus: TackOnExp( PeMinus ); END;
@TransExpMinus:
PEA PeMinus(partsTableR)
@TransExpCommon
MOVE.L A6,-(A7) ; common <2/7/88med>
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup and call vector <6/17/88ldc>
move.l sVectTackOnExp(a0), a0 ; <6/17/88ldc>
jsr (a0)
ELSE
JSR TackOnExp ; common <2/7/88med>
ENDIF
bra.s @TransDone ; done tran char.
@TransLiteral:
; new tests <2/7/88med>
tst.b inLiteral(ff) ; in literal? <2/7/88med>
bne.s @AlreadyIn ; no, go
CLR.W -(A7)
; changed -data to +data <3/14/88ldc>
MOVE.W ((tokLeftQuote-tokLeftQuote)*2+data)(partsTableR),-(A7)
PEA addendum(A6)
PEA iIndex(A6)
JSR SendChar
MOVE.W (A7)+,res(ff)
st inLiteral(ff) ; in literal? <2/7/88med>
@AlreadyIn
; are we in an escape or do we have an escaped rightQuote?
; changed -data to +data <3/14/88ldc>
move.w ((tokEscape-tokLeftQuote)*2+data)(partsTableR),d0 ; get tokEscape
cmp.w d0,sourceR ; got tokEscape?
beq.s @EscapeIt
cmp.w ((tokRightQuote-tokLeftQuote)*2+data)(partsTableR),sourceR ; got tokRightQuote?
bne.s @EscapeOk
@EscapeIt
CLR.W -(A7)
MOVE.W d0,-(A7) ; pass escape char.
PEA addendum(A6)
PEA iIndex(A6)
JSR SendChar
MOVE.W (A7)+,res(ff)
@EscapeOk
CLR.W -(A7)
MOVE.W sourceR,-(A7)
PEA addendum(A6)
PEA iIndex(A6)
JSR SendChar
MOVE.W (A7)+,res(ff)
;; MOVE.W #(' ' + (1 << 8)),addendum(A6) ; forget <2/7/88med>
;; MOVE.B sourceR,addendum(A6,d0) ; add byte
; reorder TransDone to drop thru <2/7/88med>
@TransDone:
; addendum[0]:= CHR(i-1); END
; ELSE BEGIN
; addendum:= ' ';
; addendum[1]:= source;
; END;
MOVE.W iIndex(A6),D0
SUBQ.W #1,D0
MOVE.B D0,addendum(A6)
@TransFinished:
CLR.W D0
MOVE.B addendum(A6),D0
MOVE.W D0,hold2(A6)
; FOR i:= 1 TO ORD(addendum[0]) DO BEGIN
; s[j]:= addendum[i];
; j:= j + 1; END; END;
MOVE.W #1,iIndex(A6)
BRA.S @CopyLoopTest
@CopyLoop:
MOVEA.L outString(ff),A0
MOVE.W j(ff),D0
MOVE.W iIndex(A6),D1
CLR.W D2
LEA addendum(A6),A1
MOVE.B 0(A1,D1.W),0(A0,D0.W)
ADDQ.W #1,j(ff)
ADDQ.W #1,iIndex(A6)
@CopyLoopTest:
MOVE.W iIndex(A6),D0
compw hold2(A6),D0
BLE.S @CopyLoop
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'TRANSLAT'
ENDWITH
endp
;============================================================
;
;
; calls _CharByte
;
CheckForm proc
;------------------------------------------------------------
CheckFormFrame record {oldA62},decrement
argFrameT2 EQU *
x ds.w 1 ; formatClass
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
;i ds.w 1 ; INTEGER - unused, removed <4/1/88ldc>
hold22 ds.l 1
hold21 ds.w 1
localFrame2 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D3-D7/A2-A4
ff EQU A4
myCanonicalR EQU A3
xRw EQU D3
rChar equ d5 ; added <2/7/88med>
iR EQU D6
xR EQU D7
;============================================================
WITH Form2StrFrame,CheckFormFrame,NumberParts,FormatStringPriv
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVE.B x(A6),xR
MOVEA.L oldA6f2(A6),ff
MOVEA.L myCanonical(ff),myCanonicalR
MOVEA.L partsTable(ff),A0
MOVE.L A0,hold22(A6)
;<4/4/88ldc> initialize rChar to eliminate garbage at boot time
CLR.W rChar
MOVE.B xR,xRw
EXT.W xRw
ADD.W xRw,xRw
;WITH myCanonical, partsTable DO BEGIN
; IF startLocs[x] <= startLocs[ NextFormatClass(x)]-1 THEN BEGIN
MOVE.B xR,D0
JSR NextFormatClass
ADD.W D0,D0
MOVE.W startLocs(myCanonicalR,D0.W),D2
SUBQ.W #1,D2
MOVE.W D2,hold21(A6) ; moved from below <2/7/88med>
; special test for first case, since we wrap
move.l #1,iR ; assume first (1) <2/7/88med>
compw #fPositive,xR ; first one? <2/7/88med>
beq.s @SkipFirst ; yes, bail <2/7/88med>
move.w startLocs(myCanonicalR,xRw.W),iR ; broke up comp, made common <2/7/88med>
compw iR,d2 ; was d0 <2/7/88med>
BLT.s @checkOut
; res:= SendChar(data[separator], s, j);
; positions[x].start:= j;
;<3/18/88ldc> added NumberParts.data offset
move.w #((tokSeparator-tokLeftQuote)*2+NumberParts.data),d0 ; item to send <2/7/88med>
bsr.s SendItem ; do it <2/7/88med>
MOVE.L positions(ff),A0
MOVE.B xR,D0
EXT.W D0
ASL.W #2,D0
MOVE.W j(ff),FVector.start(A0,D0.W)
@SkipFirst
; FOR i:= startLocs[x] TO startLocs[NextFormatClass(x)]-1 DO BEGIN
; TranslateToText( formString[i] ); END;
;; MOVE.B xR,xRw ; axe all common code <2/7/88med>
;; EXT.W xRw
;; ADD.W xRw,xRw
;; MOVE.B xR,D0
;; JSR NextFormatClass
;; ADD.W D0,D0
;; MOVE.W (startLocs+(fPositive*2))(myCanonicalR,D0.W),D2
;; SUBQ.W #1,D2
;; MOVE.W D2,hold21(A6)
;; MOVE.W (startLocs+(fPositive*2))(myCanonicalR,xRw.W),iR
BRA.S @loopTest
@checkLoop:
;; MOVE.W iR,D0
CLR.W D1
lea formString(myCanonicalR,iR.W),a0 ; position for char, ir.w was d0.w <2/7/88med>
MOVE.B (a0)+,rChar ; get first byte
; pass a character, not a byte; so we can do escape properly
clr.w -(sp) ; reserve return
move.l a0,-(sp) ; pass ptr
move.w #0,-(sp) ; pass offset
_CharByte
tst.w (sp)+ ; 0 for single
beq.s @GotChar
asl.w #8,rChar ; moven on up
move.b (a0),rChar ; next byte
ADDQ.W #1,iR ; bump counter
@GotChar
MOVE.W rChar,-(A7)
MOVE.L oldA6f2(A6),-(A7) ;spurious: ff has this value
JSR TranslateToText
ADDQ.W #1,iR
;; BVS.S @L472 ; don't think we will overflow <2/7/88med>
@loopTest:
compw hold21(A6),iR
BLE.S @checkLoop
; positions[x].length:= j-positions[x].start; END; END;
;;@L472: ; this label is not used <6/28/88ldc>
; moved the following chunk down & fixed below <05/22/89 pke>
; send a right quote if not done <2/7/88med>
tst.b inLiteral(ff) ; inside quoted literal?
beq.s @NoLiteral ; no, done
sf inLiteral(ff) ; out of here
; added NumberParts.data <3/18/88ldc>
move.w #((tokRightQuote-tokLeftQuote)*2+NumberParts.data),d0 ; item to send <2/7/88med>
bsr.s SendItem ; do it <2/7/88med>
@NoLiteral
; move the following 7 lines here from above <05/22/89 pke>
MOVE.L positions(ff),A0
MOVE.B xR,D0
EXT.W D0
ASL.W #2,D0
MOVE.W j(ff),D1
SUB.W FVector.start(A0,D0.W),D1
MOVE.W D1,FVector.length(A0,D0.W)
@checkOut:
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'CHECKFOR'
;============================================================
; simple subproc for above
SendItem
CLR.W -(A7)
MOVEA.L hold22(A6),A0
MOVE.W 0(a0,d0.w),-(A7) ; generalized <2/7/88med>
MOVE.L outString(ff),-(A7)
PEA j(ff)
JSR SendChar
MOVE.W (A7)+,res(ff)
rts
endProc
;============================================================
xForm2Str proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D6/D7/A3-A4
procVectR equ a3 ; for vectored proc <6/21/88ldc>
myCanonicalR EQU A4
iR EQU D6
;============================================================
WITH Form2StrFrame,FormatStringPriv,NumberParts, SMgrRecord
LINK A6,#localFrame1
MOVEM.L localRegs,-(A7)
;Format2Str:= ORD(formatOk);
;res:= ORD(formatOk);
;xxx <2/23/88:ldc> replaced #1 with symbolic constant fFormatOK
MOVE.W #fFormatOK,returnValue1(A6)
MOVE.W #fFormatOK,res(A6)
; must initialize outString to Str255 <3/28/88ldc>
MOVEA.L outString(A6),A0
MOVE.B #$FF,(A0)
;FOR formCount:= positive TO zero DO BEGIN
; positions[formCount].start:= 0;
; positions[formCount].length:= 0; END;
MOVE.L positions(A6),A0
MOVEQ #(fZero*4),D7
@L475:
CLR.W 0(A0,D7.W)
CLR.W 2(A0,D7.W)
SUBQ.B #4,D7
BPL.S @L475
;WITH myCanonical,partsTable DO BEGIN
; j:= 1;
; positions[positive].start:= 1;
@L474:
MOVEA.L myCanonical(A6),myCanonicalR
tst.b formString(myCanonicalR) ; check for empty formatString
beq.s @emptyFormatString
MOVEA.L partsTable(A6),A0
MOVE.L A0,hold12(A6)
MOVE.W #1,j(A6)
MOVE.L positions(A6),A0
MOVE.W #1,4*fPositive(A0)
IF 1 THEN ; make common code <2/7/88med>
; CheckForm( positive );
sf inLiteral(a6) ; clear literal flag <2/7/88med>
MOVE.B #fPositive,-(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore procVectR ; setup and call vector <6/17/88ldc>
move.l sVectCheckForm(procVectR), procVectR
jsr (procVectR)
ELSE
JSR CheckForm
ENDIF
ELSE ; old stuff
; FOR i:= 1 TO startLocs[negative]-1 DO BEGIN
; TranslateToText( formString[i] ); END;
MOVE.W (((startLocs+data)+(2*fNegative))(myCanonicalR),D0
SUBQ.W #1,D0
MOVE.W D0,hold11(A6)
MOVEQ #1,iR
BRA.S @L476
@L479:
CLR.W D1
MOVE.B formString(myCanonicalR,iR.W),D1
MOVE.W D1,-(A7)
MOVE.L A6,-(A7)
JSR TranslateToText
ADDQ.W #1,iR
@L476:
compw hold11(A6),iR
BLE.S @L479
; positions[positive].length:= j-1;
@L478:
MOVE.W j(A6),D0
SUBQ.W #1,D0
MOVEA.L positions(A6),A0
MOVE.W D0,(FVector.length+(fPositive*2))(A0)
ENDIF
; CheckForm( negative )
;<3/28/88ldc>
sf inLiteral(A6)
MOVE.B #fNegative,-(A7)
move.l a6, -(a7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
jsr (procVectR)
ELSE
JSR CheckForm
ENDIF
; CheckForm( zero )
;<3/28/88ldc>
sf inLiteral(A6)
MOVE.B #fZero,-(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
jsr (procVectR)
ELSE
JSR CheckForm
ENDIF
; s[0]:= CHR(j-1); END;
MOVEA.L outString(A6),A0
MOVE.W j(A6),D0
SUBQ.W #1,D0
MOVE.B D0,(A0)
bra.s @exit
;<9/7/88ldc> return with empty outString
@emptyFormatString
move.w #fEmptyFormatString, res(a6) ; flag empty format string
movea.l outString(A6),A0
move.b #0,(A0) ; set outstring length to zero
;IF res <> ORD(formatOk) THEN Format2Str:= res;
@exit
compw #fFormatOK,res(A6)
BEQ.S @L482
MOVE.W res(A6),returnValue1(A6)
@L482:
MOVEM.L (A7)+,localRegs
move #argFrame1, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'FORM2STR'
endp
;------------------------------------------------------------
FormStr2XFrame record {oldA61},decrement
returnValue1 ds.w 1 ; INTEGER
argFrameT1 EQU *
source ds.l 1 ; VAR str255
myCanonical ds.l 1 ; VAR NumFormatString
partsTable ds.l 1 ; VAR NumberParts
xOrig ds.l 1 ; VAR EXTENDED
selector1 ds.l 1
argFrame1 EQU argFrameT1-*
return1 ds.l 1
oldA61 ds.l 1
possible ds.b 4 ; ARRAY[postive..negative] OF BOOLEAN
isNeg ds.b 1 ; BOOLEAN
doPercent ds.b 1 ; BOOLEAN
going ds.b 1 ; BOOLEAN
formCount ds.b 1 ; FormatClass
Fsize ds.w 1 ; INTEGER
temp ds.w 1 ; INTEGER
Ssize ds.w 1 ; INTEGER
rIndex ds.w 1 ; INTEGER
sIndex ds.w 1 ; INTEGER
nothing ds.w 1 ; INTEGER
real ds.b 256 ; str255
saveSIndex ds.w 1 ; INTEGER
saveRIndex ds.w 1 ; INTEGER
saveCIndex ds.w 1 ; INTEGER
pastDecimal ds.b 1 ; BOOLEAN
afterEFormat ds.b 1 ; BOOLEAN <88.09.19ldc>
;--------------------------------------------------------
; used by calls to sane package
saneEnv ds.w 1 ; SANE Environment
indexF ds.w 1 ; index to floating pt value returned by str2dec
prefixF ds.w 1 ; valid prefix
decRecF ds.b 26 ; decimal record (needs 25 bytes, see Decimal later)
garbage1 ds.b 6 ; ? (not used explicitly in this file)
checkFDmask ds.b 1 ; mask for CheckForDigits result
ds.b 1 ; reserved
localFrame1 EQU *
ENDR
;============================================================
;Procedure MatchingSubString( c: WideChar;
; var index: integer;
; ignoreCase: boolean;
; oldAHf2: address): boolean;
;============================================================
; MatchingSubString
;
; trashes a0,d0-d2
; uses/restores a3-a4,d3
; calls CharComp, which trashes a0,d0-01
;
; NOTE: UprString (called by CharComp) now depends on the a5 world,
; so don't muck around with a5 before calling CharComp! <02/21/89 pke>
; Actually, UprString is again independent of a5 world, but now we're
; using LwrString instead, which DOES depend on a5 world. <06/30/89 pke>
;
; redefined MatchingSubString to allow case insensitivity. <3/16/88ldc>
MatchingSubString proc
;------------------------------------------------------------
MatchingSubStringFrame record {oldA62},decrement
match ds.w 1 ; BOOLEAN
argFrameT2 EQU *
c ds.w 1 ; WideChar
index ds.l 1 ; VAR INTEGER
ignoreCase ds.w 1 ; boolean
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
localFrame2 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg d3/a3/A4 ; don't need to save a5 <02/21/89 pke>
indexR EQU A3
bumpIndexR EQU d3
ff EQU A4
;============================================================
WITH FormStr2XFrame,MatchingSubStringFrame, SMgrRecord
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVEA.L index(A6),indexR ;make use of these lazy regs
MOVEA.L oldA6f2(A6),ff
MOVE.W (indexR),D2 ;compute address of source[index]
MOVEA.L source(ff),A0
ADDA.W D2,A0
SF match(A6) ;default with no match
MOVE.W c(A6),D0 ;put c somewhere useful
BEQ.S @done ;but leave if it's null
compw #$FF,D0 ;if it's a double-byte character then it'll …
BLS.S @singleByte ;…be greater than $FF
;set up for CharComp of two bytes
compw Ssize(ff),D2 ;verify that we're not beyond the end of the string
bge.s @done ; >= for 2 bytes
moveq #2,bumpIndexR ;bump index by two for two byte char
move.b (a0)+,d1 ;get one byte
lsl.w #8, d1 ;shift it to upper half of word
move.b (a0),d1 ;get the next
BRA.S @doCompare
@singleByte:
compw Ssize(ff),D2 ;again, check overflow
BGT.S @done ;note different boundary
clr.w d1
move.b (a0), d1 ;
moveq #1, bumpIndexR ;match will bump index by one
@doCompare
tst.w ignoreCase(a6)
beq.s @caseSensitive
clr.w -(a7)
move.w d0, -(a7)
move.w d1, -(a7)
jsr CharComp ;if not CharComp(c, source[index]) then
not.b (a7)+ ;match := false
bra.s @checkResult
@caseSensitive
cmp.w d0, d1 ;if c <> source[index] then
;equal := false
@checkResult
bne.s @done
ADD.W bumpIndexR,(indexR) ;else advance index by appropriate value
st match(A6) ;equal := true
@done
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'MATCHSUB'
ENDWITH
ENDP
;============================================================
; matchingBlocks
;
; trashes a0,d0 (,d1-d2)
; uses/restores a3,a4,d7, and a2 (was a5) for buildLevel >= 2
; calls MatchingSubString, which trashes a0,d0-d2
; called by Cond
;
matchingBlocks proc
;------------------------------------------------------------
matchingBlocksFrame record {oldA62},decrement
returnValue2 ds.w 1 ; BOOLEAN
argFrameT2 EQU *
c ds.l 1 ; VAR WideCharArr
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
j ds.w 1 ; INTEGER
i ds.w 1 ; INTEGER
garbage2 ds.b 2 ; ?
localFrame2 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D7/a2-a4 ; need a5 world here <02/21/89 pke>
ff EQU A3
cR EQU A4
;============================================================
WITH FormStr2XFrame,matchingBlocksFrame, SMgrRecord
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f2(A6),ff ;outer frame pointer
MOVEA.L c(A6),cR ;registerize c's address
MOVE.W sIndex(ff),j(A6) ;j is a provisional pointer
SF returnValue2(A6) ;assume the worse
MOVE.W WideCharArr.size(cR),D7 ;loop to c.size
BLT.S @out ;negative size means the array is empty
LEA WideCharArr.data(cr),cR ;retrieve beginning of character array
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
; GetSMgrCore a5 ; setup for vector call <6/17/88ldc>
; move.l sVectMatchingSubString(a5), a5 ; before entering loop
GetSMgrCore a2 ; setup for vector call <02/21/89 pke>
move.l sVectMatchingSubString(a2), a2 ; before entering loop
ENDIF
@eqLoop:
CLR.W -(A7) ;return space
MOVE.W (cR)+,-(A7) ;push the next character
PEA j(A6) ;and our provisional index
; added boolean switch to ignore case so 'e' and 'E' are
;treated equally <3/16/88ldc>
move.w #1,-(a7) ;ignoreCase := true
MOVE.L ff,-(A7) ;not to mention the proper frame pointer
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
; jsr (a5) ; now a vector
jsr (a2) ; now a vector <02/21/89 pke>
ELSE
JSR matchingSubString
ENDIF
MOVE.B (A7)+,D0 ;was it a match?
DBEQ D7,@eqLoop ;done if not or if we ran out of chars
BEQ.S @out
ST returnValue2(A6) ;we matched so say so
MOVE.W j(A6),sIndex(a3) ;the provisional index was real after all
@out:
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'MATCHBLO'
ENDWITH
endp
;============================================================
; CheckForDigits
;
; trashes a0-a1,d0-d1 (,d2)
; uses/restores a2-a4,d6-d7
; calls matchingSubString, which trashes a0,d0-d2
;
CheckForDigits proc
;------------------------------------------------------------
CheckForDigitsFrame record {oldA62},decrement
returnValue2 ds.w 1 ; BOOLEAN
argFrameT2 EQU *
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
k ds.w 1 ; INTEGER
ch ds.w 1 ; CHAR
matching ds.w 1 ; BOOLEAN
garbage2 ds.b 8 ; ?
localFrame2 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D5-D7/A2-A4 ; now need D5 (didn't need D4) <05/22/89 pke>
ff EQU a4
realR EQU a2
matchingR EQU d6
kR EQU d7
partsTableR EQU a3
;============================================================
WITH FormStr2XFrame,CheckForDigitsFrame,FormatStringPriv,NumberParts, SMgrRecord
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f2(A6),ff
SF D5 ;assume the worst
MOVEA.L myCanonical(ff),A1 ;we only need this once
MOVEA.L partsTable(ff),partsTableR ;make use of the empty regs
LEA real(ff),realR
ADD.W rIndex(ff),realR ;point ourself to our current index
MOVEA.L source(ff),A0 ;we only need this one once, too
MOVE.W sIndex(ff),D0 ;check to see if this is a digit
MOVE.B 0(A0,D0.W),D1
compb #'0',D1
BLT.S @noDigit
compb #'9',D1
BGT.S @noDigit
MOVE.B D1,(realR) ;but if it is a digit, move it into the current string
ADDQ.W #1,rIndex(ff) ;and increment all our indexes
ADDQ.W #1,sIndex(ff)
ST D5 ;
CMP.B #'0',D1 ;
BEQ.S @doneRealZeroTest ;
MOVE.B #$7F,D5 ;
@doneRealZeroTest:
BRA.S @out
@noDigit:
MOVE.B formCount(ff),D0 ;we'll give it a second chance…
EXT.W D0 ;…by checking against the alternative digits
ADD.W D0,D0
BTST #fIsAltNum,Flags(A1,D0.W) ;do we even allow alternate digits?
BEQ.S @out ;nope, so forget it
SF matchingR ;otherwise, try matching against alternates
MOVE.W #9,kR ;k is the loop counter
LEA AltNumTable.data(partsTableR),partsTableR ; <2-25-88med.ldc>
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
; GetSMgrCore a5 ; setup for vector call <6/18/88ldc>
; move.l sVectMatchingSubString(a5), a5
GetSMgrCore a1 ; ok to reuse a1, can't use a5 <02/21/89 pke>
move.l sVectMatchingSubString(a1), a1
ENDIF
@altLoop:
CLR.W -(A7) ; return space
MOVE.W (partsTableR)+,-(A7) ; push the current character
PEA sIndex(ff) ; and the index into the source string
clr.w -(a7) ; case sensitive is cheaper
MOVE.L ff,-(A7) ; oh, don't forget the silly frame pointer
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
; jsr (a5) ; call the vector
jsr (a1) ; <02/21/89 pke>
ELSE
JSR matchingSubString
ENDIF
MOVE.B (A7)+,matchingR ;did we match?
DBNE kR,@altLoop ;yes, fall through, or no, dbra
BEQ.S @out ;just checking
;; MOVE.B #'9',(realR) ;digit:= '9'-k
;; SUB.W kR,(realR)
move.l #'9',d0 ; digit := '9'-k <2-25-88med.ldc>
sub.b kR,d0 ; subtract <2-25-88med.ldc>
move.b d0,(realR) ; store in array <2-25-88med.ldc>
ADDQ.W #1,rIndex(ff) ;update the index
ST D5 ;
CMP.B #'0',D0 ;
BEQ.S @doneAltZeroTest ;
MOVE.B #$7F,D5 ;
@doneAltZeroTest:
@out:
MOVE.B D5,returnValue2(A6) ;
MOVEM.L (A7)+,localRegs
UNLK A6
MOVE.L (A7)+,(A7)
RTS
CheckDebug 'CHECKDIG'
ENDWITH
endp
;------------------------------------------------------------
ExpMatchingFrame record {oldA62},decrement
returnValue2 ds.w 1 ; BOOLEAN
argFrameT2 EQU *
plusData ds.l 1 ; VAR WideCharArr
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
garbage2 ds.b 4
localFrame2 EQU *
ENDR
;============================================================
; Cond
;
; trashes a0,d0 (,d1-d2)
; uses/restores a2-a4,d3-d4, plus d5 for buildLevel >= 1, a5 otherwise
; calls matchingBlocks, which trashes a0,d0-d2
;
Cond proc
;------------------------------------------------------------
CondFrame record {oldA63},decrement
argFrameT3 EQU *
a ds.l 1 ; VAR WideCharArr
b ds.l 1 ; VAR WideCharArr
aSign ds.b 1 ; CHAR
ALIGN 2
bSign ds.b 1 ; CHAR
ALIGN 2
oldA6f3 ds.l 1
argFrame3 EQU argFrameT3-*
return3 ds.l 1
oldA63 ds.l 1
localFrame3 EQU *
ENDR
;============================================================
WITH FormStr2XFrame,ExpMatchingFrame,CondFrame
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D3-D5/A2-A4 ; <02/21/89 pke>
fff EQU a3 ; <02/21/89 pke>
ff EQU a4
realR EQU a2
abR EQU d4
signR EQU d3
LINK A6,#localFrame3
MOVEM.L localRegs,-(SP)
MOVEA.L oldA6f3(A6),ff
MOVE.L oldA6f2(ff),fff ;you like these nested procs too?
SF returnValue2(ff)
LEA real(fff),realR ;this is the real# string we're dealing with
ADD.W rIndex(fff),realR ;and this is how far into it we are
MOVE.B aSign(A6),signR ;and we sort of need to know its sexual preference
MOVE.L a(A6),abR ;check against one version of the exponent
moveq #1,d5 ;set firstTime flag <02/21/89 pke>
@compare:
CLR.W -(A7) ;return space
MOVE.L abR,-(A7) ;push whatever we are comparing
MOVE.L fff,-(A7) ;and the frame pointer
JSR matchingBlocks
MOVE.B (A7)+,D0 ;how'd we do?
BNE.S @matched ;that's a sigh of relief
tst.l d5 ; <02/21/89 pke>
beq @out ; <02/21/89 pke>
@take2:
MOVE.B bSign(A6),signR ;try matching against the other flavor of exponent
MOVE.L b(A6),abR
moveq #0,d5 ;not firstTime <02/21/89 pke>
BRA.S @compare
@matched:
MOVE.B #'E',(realR)+ ;the canonical 'E'
MOVE.B signR,(realR) ;and whatever sign we need
ADDQ.W #2,rIndex(fff) ;update the index
ST returnValue2(ff) ;and brag about the results
@out:
MOVEM.L (A7)+,localRegs
move #argFrame3, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'COND '
ENDWITH
endp
;============================================================
; ExpMatching
;
; trashes a0,a1,d0
; uses/restores a3,a4
; calls Cond, which trashes a0,d0-d2
;
ExpMatching func
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg A3/A4
ff EQU a3
partsTableR EQU a4
;============================================================
WITH FormStr2XFrame,ExpMatchingFrame,NumberParts,FormatStringPriv, SMgrRecord
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f2(A6),ff
MOVEA.L partsTable(ff),partsTableR ;WITH partsTable
LEA PeMinus(partsTableR),A1
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore partsTableR ;recycle a4 & setup for vector call
move.l sVectCond(partsTableR), partsTableR ; <6/21/88ldc>
ENDIF
MOVEA.L plusData(A6),A0 ;Check which of E+ and E- is larger…
MOVE.W WideCharArr.size(A0),D0 ;…it's important because one could be a substring of the other
compw WideCharArr.size(A1),D0
BLT.S @bigEMinus
MOVE.L A0,-(A7)
MOVE.L A1,-(A7)
MOVE.L #((('-')<<16)+'+'),-(A7) ;push + then -
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
jsr (partsTableR) ; call vect <6/17/88ldc>
ELSE
JSR Cond ;try matching against exponents
ENDIF
BRA.S @out
@bigEMinus:
MOVE.L A1,-(A7)
MOVE.L A0,-(A7)
MOVE.L #((('+')<<16)+'-'),-(A7) ;push - then +
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
jsr (partsTableR) ; call vect <6/17/88ldc>
ELSE
JSR Cond
ENDIF
@out:
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'EXPMATCH'
ENDWITH
endp
;============================================================
; xFormStr2X
;
; trashes a0-a1,d0-d2
; uses/restores a2-a4,d3-d7
; calls MatchingSubString trashes a0,d0-d2
; CheckForDigits trashes a0-a1,d0-d2
; ExpMatching trashes a0,a1,d0
; CharComp here trashes a0,d0-d1
; NextFormatClass changes d0
; _CharByte (may trash a0-a1,d0-d2)
; FPSTR2DEC (_PACK7)
; FDEC2X (_FP68K)
; FDIVX (_FP68K)
;
; NOTE: UprString (called by CharComp) now depends on the a5 world,
; so don't muck around with a5 before calling CharComp! <02/21/89 pke>
; Actually, UprString is again independent of a5 world, but now we're
; using LwrString instead, which DOES depend on a5 world. <06/30/89 pke>
;
xFormStr2X proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D3-D7/A2-A5 ; a5 not used, change to not save <02/21/89 pke>
myCanonicalR EQU a3
partsTableR EQU a4
formCountR EQU a2
cIndexR EQU d7
tempR EQU d6
goingR EQU d5
cR EQU d4
saveCIndexR EQU d3
;============================================================
WITH FormStr2XFrame,FormatStringPriv,NumberParts, SMgrRecord
LINK A6,#localFrame1
MOVEM.L localRegs,-(A7)
SF doPercent(A6) ;do a bunch of initializations
MOVEA.L source(A6),A0 ;move the source length into local space
CLR.W D0
MOVE.B (A0),D0
MOVE.W D0,Ssize(A6)
MOVE.B #'1',(real+1)(A6) ;assume '1' as a default in case there are no digits on input
MOVEA.L myCanonical(A6),myCanonicalR
; test for empty format string <9/7/88ldc>
MOVEA.L partsTable(A6),partsTableR
LEA formCount(A6),formCountR
CLR.W D0 ;move the length of the form string into local space
MOVE.B formString(myCanonicalR),D0
MOVE.W D0,Fsize(A6)
SF goingR ; needs initialization <9/7/88ldc>
SF possible+fNegative(A6) ;more obvious initializations
SF possible+fZero(A6)
ST possible+fPositive(A6)
MOVE.W #fPositive,(formCountR)
BTST.B #fExists,(flags+2*fPositive)(myCanonicalR)
BEQ @bestGuess
; replaced #1 with fFormatOK <2/23/88:ldc>
MOVE.W #fFormatOK, returnValue1(A6)
MOVEQ #1,D0
MOVE.W D0,sIndex(A6)
MOVE.L D0,cIndexR
MOVE.W D0,rIndex(A6)
SF pastDecimal(a6)
ST checkFDmask(A6) ;any digit is OK
CLR.W saveCIndexR ;saveCIndex is for backtracking when we have optional digits
MOVE.W (((tokMinusSign-tokLeftQuote)*2)+data)(partsTableR),D0
BSR @matchSS ;check if the very first character is a minus sign
MOVE.B D0,isNeg(A6) ;and if it is, say so
move.w FSize(a6), d0 ; get format string size <9/7/88ldc>
beq @emptyFormatString ; best guess
compw d0,cIndexR ;make sure we've got something in the format string
SLE goingR
MOVE.W sIndex(A6),D1 ;and also in the source string
compw Ssize(A6),D1
SLE D1
AND.B D1,goingR
@whileGoing:
MOVE.B goingR,D0
BEQ @doneGoing
CLR.W cR
MOVE.B formString(myCanonicalR,cIndexR.W),cR ;update c to next format symbol
compw #(tokMaxSymbols+1),cR ;upper limit of control codes
BGE @noJump
MOVE.W cR,D0
SUBQ.W #tokLeader,D0 ;upper limit of jump table
BMI @endJump
compw #(tokEMinus-tokLeader),D0
BGT @endJump
ADD.W D0,D0
MOVE.W @jTab(D0.W),D0
JMP *+2(D0.W)
@jTab:
DC.W @leads-@jTab+2, @nonLeads-@jTab+2, @leads-@jTab+2
DC.W @others-@jTab+2, @others-@jTab+2, @others-@jTab+2
DC.W @others-@jTab+2, @empty-@jTab+2, @empty-@jTab+2
DC.W @empty-@jTab+2, @decPoint-@jTab+2, @ePlus-@jTab+2
DC.W @eMinus-@jTab+2
@leads:
BSR @checkFD ;check for digit
BNE.S @leadMatch ;sure enough got one
MOVE.W cR,D0 ;if we didn't get one then check for the lead character
ADD.W D0,D0
MOVE.W -(tokLeftQuote*2)+data(partsTableR,D0.W),D0
BSR.S @matchSS
BEQ @notThisForm ;if we didn't get one then we just aren't a match
@leadMatch:
BRA @mergeJump
@nonLeads:
TST.W saveCIndexR ;if this is the first of a string of nonLeads,
BNE.S @noReset ;then we need to fill the state holders.
MOVE.W cIndexR,saveCIndexR ;these variables allow handling optional digits
MOVE.W rIndex(A6),saveRIndex(A6)
MOVE.W sIndex(A6),saveSIndex(A6)
@noReset:
BSR.S @checkFD ;check for a digit
BEQ @notThisForm ;if we didn't get one then we just aren't a match
BRA @mergeJump ;and finish
@decPoint:
ST pastDecimal(a6) ;pastDecimal is necessary info when handling optional digits
CLR.W saveCIndexR ;start anew on the optional digit state
; added data offset <3/14/88ldc>
MOVE.W (((tokDecPoint-tokLeftQuote)*2)+data)(partsTableR),D0
BSR.S @matchSS ;match against a decimal point
BEQ @notThisForm ;(or at least try, that is)
MOVE.W rIndex(A6),D0 ;insert a decimal point into the real# string
LEA real(A6),A0
MOVE.B #'.',0(A0,D0.W)
ADDQ.W #1,rIndex(A6) ;update the real# string index
BRA.S @endJump
@others:
MOVE.W cR,D0 ;try matching source string against format string
ADD.W D0,D0
MOVE.W -(tokLeftQuote*2)+data(partsTableR,D0.W),D0
BSR.S @matchSS
BEQ.S @notThisForm ;failure if no match
BRA @mergeJump
@ePlus:
LEA PePlus(partsTableR),A0
BSR.S @expM ;match against ePlus
BEQ.S @notThisForm ;failure if no match
; changed branch from @mergeJump to @mergeExp <1/23/88drs>
BRA.S @mergeExp
@eMinus:
LEA PeMinusPlus(partsTableR),A0
JSR @expM ;match against eMinusPlus
BEQ.S @notThisForm
; inserted @mergeExp and following two lines to correct bug. <1/23/88drs>
;After the exponent is reached, the parsing algorithm should treat
;exponent digits as if they were pre-decimal significand.
@mergeExp:
MOVEQ #0,SaveCIndexR ;reset saveCIndex
CLR.B pastDecimal(A6)
ST checkFDmask(A6) ;any digit is OK as exponent
@endJump:
@empty:
BRA.S @mergeJump
@matchSS: ;standard module for calling matchingSubString
CLR.W -(A7) ;room for return parameter
MOVE.W D0,-(A7) ;register based parameter to matchSS
PEA sIndex(A6) ;position into the source
clr.w -(a7) ;case sensitive is cheaper
MOVE.L A6,-(A7) ;the ubiquitous frame pointer
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; set up for vector call <6/18/88ldc>
move.l sVectMatchingSubString(a0), a0
jsr (a0) ; call it <6/18/88ldc>
ELSE
JSR matchingSubString
ENDIF
MOVE.B (A7)+,D0 ;result is passed back in D0 (and SR)
RTS
@checkFD:
CLR.W -(A7) ;common call to CheckForDigits
MOVE.L A6,-(A7) ;no parameters; only frame pointer
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; setup for vector call
move.l sVectCheckForDigits(a0), a0 ; call vect <6/17/88ldc>
jsr (a0)
ELSE
JSR CheckForDigits ; This was commented out; shouldn't be.
; fixed <1/31/89 pke>
ENDIF
MOVE.B (A7)+,D0
AND.B checkFDmask(A6),D0
RTS ;result in D0 (and SR)
;------------------------------------------------------------------------------------
@expM:
CLR.W -(A7) ;common call to expMatching
MOVE.L A0,-(A7) ;which exponent is passed here in A0
MOVE.L A6,-(A7) ;frame pointer again
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; intlSpec for vector
move.l sVectExpMatching(a0), a0 ; call vector <6/17/88ldc>
jsr (a0) ; <6/21/88ldc>
ELSE
JSR ExpMatching
ENDIF
MOVE.B (A7)+,D0 ;result in D0 (and SR)
RTS
;------------------------------------------------------------------------------------
@notThisForm: ;common entry for failed match:
MOVE.B (FormCountR),D0 ;tentatively declare that the source doesn't match format
EXT.W D0
CLR.B possible(A6,D0.W) ;possible[formCount] := FALSE;
BRA.S @mergeJump
@noJump:
;check source text against form string
; convert form string and c to upper case before comparison <3/15/88ldc>
;
clr.w -(a7)
move.w cR, -(a7)
movea.l source(A6),A0
adda.w sIndex(a6),A0
move.b (a0), d0
move.w d0, -(a7)
jsr CharComp ;if not CharComp(source[sIndex], c) then
tst.b (a7)+
beq.S @notThisForm ;possible[formCount] := FALSE
ADDQ.W #1,sIndex(A6) ;otherwise increment source pointer
@mergeJump:
MOVE.B (FormCountR),D0;the beginning of the next format in the format string…
JSR NextFormatClass ;…is important enough to dedicate a register to
ADD.W D0,D0
MOVE.W startLocs(myCanonicalR,D0.W),tempR
MOVE.B (FormCountR),D1 ;we'll need formcount in a moment
EXT.W D1 ;as an integer, that is
MOVE.W sIndex(A6),D0 ;if we've ran out of source but not format string…
compw Ssize(A6),D0 ;…then potentially we don't match
BLE.S @stillMatch
MOVE.W tempR,D0
SUBQ.W #1,D0
compw cIndexR,D0
BLE.S @stillMatch
SF possible(A6,D1.W) ;the format string was indeed too long
@stillMatch:
TST.B possible(A6,D1.W) ;now check if we provisionally don't match
BNE @mergeMatch
; Changed testing sequence slightly. <1/23/88drs>
;We need to drop into this code section whenever pastDecimal also.
TST.B pastDecimal(a6) ;this gets into complex checks about whether…
BNE.S @mergeDecCheck ;…we really match or not after provisionally failing
TST.W saveCIndexR ;if saveCIndex is zero then there were no optional…
BNE.S @notPastDecimal ;…digits, and we definitely don't match
BRA @mergeMatch ;final decision of no match
@mergeDecCheck:
MOVE.W tempR,saveCIndexR ;push saveCIndex to end of format string for now
clr.b afterEFormat(a6) ; assume before the exponetial format <88.09.19ldc>
@pdLoop: ;this loop forgives material between optional digits
compw tempR,cIndexR ;make sure we're not beyond end of format string
BGE.S @setTrue ;and if we are, then we actually did match
MOVE.W cIndexR,D1 ;see if the next format string code is a nonLeader
ADDQ.W #1,D1
CMP.B #tokNonLeader,formString(myCanonicalR,cIndexR.W)
BNE.S @testEFormat ;ignore if not, but first check for EFormat <88.09.19ldc>
; added 3 lines to fix bug. <1/23/88drs>
;If pastDecimal then the only time it doesn't match is when there is
;something after the last nonLeader
MOVE.B (FormCountR),D0 ;go ahead and decide that a match is still possible
EXT.W D0
ST possible(A6,D0.W)
; added following to allow acceptance of 3.0E+0 with #.##E+# format <88.09.19ldc>
tst.b afterEFormat(a6) ; skip non-leads after the EFormat
bne.s @mergePdLoop
MOVE.W D1,saveCIndexR ;and set save index to this nonLeader
BRA.s @mergePdLoop ; <88.09.19ldc>
; are we past the exponential form? Need this test to accept 3.0E+0 with #.##E+# format. <88.09.19ldc>
@testEFormat
cmp.b #tokEPlus, formString(myCanonicalR,cIndexR.W) ; <88.09.19ldc>
beq.s @setAfterE ; <88.09.19ldc>
cmp.b #tokEMinus, formString(myCanonicalR,cIndexR.W) ; <88.09.19ldc>
bne.s @mergePdLoop ; <88.09.19ldc>
@setAfterE
st afterEFormat(a6) ; <88.09.19ldc>
ST checkFDmask(A6) ;any digit is OK after exp <05/22/89 pke>
@mergePdLoop:
MOVE.W D1,cIndexR ;advance the format string index
BRA.S @pdLoop
@notPastDecimal:
ADDQ.W #1,saveCIndexR ;gobble up all but leaders, exps, decPoints, pos/neg
compw tempR,saveCIndexR ;but make sure we've not reached next format
BGE.S @setTrue ;if we have, then we match
MOVE.B formString(myCanonicalR,saveCIndexR.W),D0
CMP.B #tokMaxSymbols,D0 ;check for ascii character…
BGT.S @notPastDecimal ;…and continue looping if it is one
MOVE.L #((((((((1<<tokNonLeader)++(1<<tokLeader))++(1<<tokZeroLead))++(1<<tokDecPoint))++(1<<tokPlusSign))++(1<<tokMinusSign))++(1<<tokEPlus))++(1<<tokEMinus)),D1
BTST.L D0,D1 ;is it any of those listed above?
BEQ.S @notPastDecimal ;no, so continue looping
@setTrue:
compw saveCIndexR,tempR ;make sure we haven't overflowed
BLE.S @fMerge
MOVE.W saveCIndexR,cIndexR ;since we matched, set position in format string
MOVE.B (FormCountR),D0 ;and set the possible flag back to true
EXT.W D0
ST possible(A6,D0.W)
TST.B pastDecimal(a6) ;if we're not past the decimal…
BNE.S @fMerge
CLR.W saveCIndexR ;…then reset the status keepers
MOVE.W saveSIndex(A6),sIndex(A6)
MOVE.W saveRIndex(A6),rIndex(A6)
BRA.S @fMerge
@mergeMatch:
ADDQ.W #1,cIndexR ;update cIndex
@fMerge: ;this entry avoids update; it already happened
MOVE.B (FormCountR),D0 ;now check if format string is done but source isn't
EXT.W D0
compw cIndexR,tempR
BGT.S @cMerge ;no, format is not done
MOVE.W sIndex(A6),D1
compw Ssize(A6),D1
BGT.S @cMerge ;yes, format is done, but so is source
SF possible(A6,D0.W) ;this source just doesn't match
@cMerge:
MOVE.B possible(A6,D0.W),D1 ;so, well, did we finally match or not
BNE.S @mergeMTest
compb #fZero,(FormCountR) ;if this is zero format, we're done
BNE.S @zMerge ;otherwise give it another try with next format
SF goingR ;none of the formats match
BRA.S @mergeMTest
@zMerge:
CLR.B isNeg(A6) ;increment the format counter and reset…
MOVE.B (FormCountR),D0 ;…so we can try matching against next format
EXT.W D0
ADDQ.W #1,D0
MOVE.B D0,(FormCountR)
MOVE.W D0,D1 ;but if the next format doesn't exist,…
ADD.W D0,D0 ;…we're up a creek
BTST #fExists,flags(myCanonicalR,D0.W)
BEQ.S @noNext
MOVEQ #1,D2 ;reset all the status and flags
CMP.W #fZero,D1
BNE.S @nonZeroSetup
; MOVE.B #'0',(real+1)(A6) ;<don't use form-dependent default for now>
MOVE.B #$80,checkFDmask(A6) ;for digits, accept only 0 until exponent
BRA.S @doneSpecialSetup ;
@nonZeroSetup:
; MOVE.B #'1',(real+1)(A6) ;<don't use form-dependent default for now>
ST checkFDmask(A6) ;
@doneSpecialSetup:
MOVE.B #'1',(real+1)(A6) ;default value <leave it always 1 for now>
SF pastDecimal(a6)
CLR.W saveCIndexR
MOVE.B D2,possible(A6,D1.W)
MOVE.W D2,sIndex(A6)
MOVE.W startLocs(myCanonicalR,D0.W),cIndexR
MOVE.W D2,rIndex(A6)
BRA.S @mergeMTest
@noNext:
CLR.B goingR
@mergeMTest:
compw Fsize(A6),cIndexR
SLE D0
MOVE.W sIndex(A6),D1
compw Ssize(A6),D1
SLE D1
AND.B D1,D0
AND.B D0,goingR
BRA @whileGoing
@doneGoing:
MOVE.B (FormCountR),D0
EXT.W D0
MOVE.B possible(A6,D0.W),D1 ;the eternal question: did we match?
BEQ.S @bestGuess ;no, so try free-form input
ADD.W D0,D0 ;yes, so see if we have a percentage to deal with
BTST #fIsPercent,flags(myCanonicalR,D0.W)
SNE D0
MOVE.B D0,doPercent(A6) ;and set the flag if we do
BRA @toReal ;go on to convert to real
@bestGuess:
;xxx<2/24/88:ldc>
; at this point we go back through the source and make a best guess
;FormatStr2X := bestGuess.
MOVE.W #fBestGuess, returnValue1(A6)
@freeForm
sf doPercent(a6) ; <9/22/88ldc>
sf isNeg(a6) ; <9/22/88ldc>
SF pastDecimal(a6) ; <9/20/88ldc>
ST checkFDmask(A6) ;any digit is OK now <05/22/89 pke>
MOVE.W #fPositive,(FormCountR) ;assume positive
MOVE.W #1,sIndex(A6) ;reset the vitals
MOVE.W #1,rIndex(A6)
@freeFormLoop:
@whileFF:
MOVE.W sIndex(A6),D0 ;have we run out of source?
compw Ssize(A6),D0
BGT @exitFreeForm
BSR @checkFD ; if it's not a digit, then just what is it
BNE @endFreeFormLoop ; was digit so loop to get the next char
CLR.W tempR ; not digit see which syntactical entity it matches
; loop through the parts table, index to each component in tempR
@pTabLoop:
ADDQ.W #1,tempR
compw #tokDecPoint,tempR ;if it's beyond decimal point, go to case
BGT.S @ffCase
MOVE.W tempR,D1 ;otherwise check against syntactical entry
ADD.W D1,D1
; added data offset <3/14/88ldc>
MOVE.W (-(tokLeftQuote*2)+data)(partsTableR,D1.W),D0
BSR @matchSS
BEQ.S @pTabLoop ;if there's no match then ignore it
@ffCase: ;jump table
MOVE.W tempR,D0
SUBQ.W #tokPercent,D0
BEQ.S @isPercent
SUBQ.W #(tokMinusSign-tokPercent),D0
BEQ.S @isMinus
SUBQ.W #(tokDecPoint-tokMinusSign),D0
BEQ.S @isDecPoint
SUBQ.W #1,D0 ; check fIsDecPoint-1
BEQ.S @isPastDecPoint
BRA @endFreeFormLoop ; ain't nothing
@isDecPoint:
; check for multiple decimals <9/20/88ldc>
tst.b pastDecimal(a6) ; have we already seen a decimal? <9/20/88ldc>
bne @setExtraDecimal ; yes, note error and exit <9/20/88ldc>
st pastDecimal(a6)
MOVE.W rIndex(A6),D0 ;tack on a decimal point
LEA real(A6),A0
MOVE.B #'.',0(A0,D0.W)
ADDQ.W #1,rIndex(A6)
BRA @endFreeFormLoop
@isMinus:
tst.b isNeg(a6) ; have we already seen a minus? <9/20/88ldc>
bne @setSpuriousChars ; yes, note error and exit <9/20/88ldc>
st isNeg(a6) ; else, just note that we have seen one
; Note that the convention used in the format scanner above is that negative is
; indicated if either isNeg is set (when '-' is seen in positive fmt) or formCount
; is fNegative;'-' is never added into the real number string. Change to use same
; convention here. <05/22/89 pke>
BRA.S @endFreeFormLoop
@isPercent:
tst.b doPercent(a6) ; only allow one percent symbol <9/22/88ldc>
IF forRom THEN
bne.s @setExtraPercent
ELSE
bne @setExtraPercent
ENDIF
st doPercent(A6)
BRA.S @endFreeFormLoop
@isPastDecPoint:
LEA PePlus(partsTableR),A0
BSR @expM ;check on E+
BNE.S @endFreeFormLoop ;it was E+
LEA PeMinusPlus(partsTableR),A0
JSR @expM ;check on E-
BNE.S @endFreeFormLoop ;it was E-
; <9/21/88ldc>flag spurious chars (e.g., "1x2") per bug #30677
; first compare it against the unquoted characters, may be two byte
clr.w -(a7) ; room for result
move.l source(a6), -(a7) ; source string and
move.w sIndex(a6), -(a7) ; source index
_CharByte ; for charbyte
movea.l source(a6), a0 ; get source
move.w sIndex(a6), d0 ; get index
adda.w d0, a0 ; current offset
move.b (a0)+, d0 ; get the first byte
tst.w (a7)+ ; one or two byte?
beq.s @singleByte ; one, so don't need to get next byte
lsl.w #8, d0 ; move into upper byte
move.b (a0)+, d0 ; lower byte of 2 byte char
@singleByte
LEA ((tokMaxSymbols-1)*2)(partsTableR),a0 ; unquoteds table in a0
MOVEQ #(tokEMinus-1),d1 ; loop counter
; <9/21/88ldc> loop through the unquoted characters in the number parts table
@unquotedLoop:
compw -(a0), d0 ; check against source table chars
dbeq d1, @unquotedLoop ; stop if we match
bne.s @setSpuriousChars ; this character not found in unquoted table
@bumpSourceString:
ADDQ.W #1,sIndex(A6) ;use CharByte to check for 2 byte char
CLR.W -(A7)
MOVE.L source(A6),D0
ADDQ #1,D0
MOVE.L D0,-(A7)
MOVE.W sIndex(A6),D0
;<1/23/88drs> Changed 1 line to fix bug
;Was subtracting 2 instead of 1
SUBQ.W #1,D0
MOVE.W D0,-(A7)
_CharByte
TST.W (A7)+
;<1/23/88drs> Changed 1 line to fix bug
;Was doing BLT.S instead of BGT.S
BGT.S @bumpSourceString ;get lower byte of two byte character
@endFreeFormLoop:
BRA @freeFormLoop
;<9/20/88ldc> flag errors
@emptyFormatString
MOVE.W #fEmptyFormatString, returnValue1(A6)
bra.s @toReal
@setExtraPercent
move.w #fExtraPercent, returnValue1(a6)
bra.s @toReal
@setExtraDecimal
move.w #fExtraDecimal, returnValue1(a6)
bra.s @toReal
@setSpuriousChars
move.w #fSpuriousChars, returnValue1(a6)
@toReal:
@exitFreeForm:
MOVE.W rIndex(A6),D0 ;set length of real# string
SUBQ.W #1,D0
BNE.S @rMerge
MOVEQ #1,D0 ;successfully matched literal string guaranteed to
;contain at least one digit: 1, -1, or 0
;<1/28/88drs> need check to see if we got anything useful from the source stirng at all
;<4/14/88ldc> added test for empty source
tst.w Ssize(A6) ;make sure we don't have an empty source string
beq.s @isNAN
;<3/31/88ldc> changed d0 to d1 to prevent trashing of #1 in d0
MOVE.B (FormCountR),D1 ;check if we had a match
EXT.W D1
TST.B possible(A6,D1.W) ;if no match and no digits, declare error
;<4/14/88ldc> changed branch target to @isNAN
BEQ.S @isNAN
; BNE.S @rMerge
; MOVE.W #fSpuriousChars, returnValue1(A6)
@rMerge:
MOVE.B D0, real(A6)
compb #fZero,(FormCountR) ;if formCount was zero then clear out x
BNE.S @isNonZero
MOVEA.L xOrig(A6),A0
CLR.L (A0)+
CLR.L (A0)+
CLR.W (A0)
BRA @zzMerge
;<4/14/88ldc> added @isNAN + 2 lines
@isNAN:
pea #'nan(17)'
bra.s @setupStr2Dec
@isNonZero:
;<4/14/88ldc> moved the following line to here from below
PEA real(A6) ; use the real string address
;<4/14/88ldc> added setupStr2Dec
@setupStr2Dec:
MOVE.W #1,indexF(A6) ; initial index into string
; PEA real(A6) ; use the real string address
PEA indexF(A6) ; index address
PEA decRecF(A6) ; decimal record address
PEA prefixF(A6) ; valid prefix address
FPSTR2DEC
; convert to extended
PEA decRecF(A6) ; decimal record address
MOVE.L xOrig(A6),-(SP) ; x address
FDEC2X
;<9/8/88ldc> use SANE to determine nan (cf bug #30678)
; result in d0
move.l xOrig(a6), a1
bsr GetSANEClass
cmp.w #posQNAN, d0
beq.s @returnNAN
cmp.w #negQNAN, d0
beq.s @returnNAN
cmp.w #posSNAN, d0
beq.s @returnNAN
cmp.w #negSNAN, d0
beq.s @returnNAN
cmp.w #posInf, d0
beq.s @returnOverflow
cmp.w #negInf, d0
beq.s @returnOverflow
MOVE.B doPercent(A6),D0 ;check if we need a percentage computation
BEQ.S @pMerge
PEA @hundredC
MOVE.L xOrig(A6),-(SP)
FDIVX ;divide by 100
@pMerge:
compb #fNegative,(FormCountR) ;if we picked up a negative somewhere…
BEQ.S @doNeg ;…then negate it
TST.B isNeg(A6) ;this is an informal negative
BEQ.S @zzMerge
@doNeg:
MOVEA.L xOrig(A6),A0
TST.L (A0)
BEQ.S @zzMerge ;don't negate a zero
EORI.B #$80,(A0)
bra.s @zzMerge
;<9/8/88ldc>
@returnNAN
MOVE.W #fFormStrIsNAN, returnValue1(A6) ; <9/8/88ldc>
bra.s @zzMerge
@returnOverflow
move.w #fFormatOverflow, returnValue1(a6) ; <9/8/88ldc>
@zzMerge:
MOVEM.L (A7)+,localRegs
move #argFrame1, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'FORMSTR2'
@hundredC:
DC.W $4005, $C800, $0000, $0000, $0000
ENDWITH
endp
maxStringLen EQU 50 ;internal strings
;------------------------------------------------------------
decForm record 0,increment
style ds.w 1 ; INTEGER
digits ds.w 1 ; INTEGER
ENDR
;------------------------------------------------------------
Decimal record 0,increment
sgn ds.w 1 ; 0..1
exp ds.w 1 ; INTEGER
sig ds.b 21 ; STRING[20]
ENDR
maxSANEsig EQU 20 ; max length of sig <05/22/89 pke>
;------------------------------------------------------------
FormX2StrFrame record {oldA61},decrement
returnValue1 ds.w 1 ; INTEGER
argFrameT1 EQU *
xOrig ds.l 1 ; VAR EXTENDED
myCanonical ds.l 1 ; VAR NumFormatString
partsTable ds.l 1 ; VAR NumberParts
out ds.l 1 ; VAR str255
selector1 ds.l 1
argFrame1 EQU argFrameT1-*
return1 ds.l 1
oldA61 ds.l 1
x ds.w 5 ; EXTENDED
formCount ds.b 1 ; FormatClass
negExp ds.b 1 ; BOOLEAN
doNegative ds.b 1 ; BOOLEAN
ALIGN 2
exp ds.b maxStringLen ; string
postDec ds.b maxStringLen ; string
preDec ds.b maxStringLen ; string
expFinal ds.b maxStringLen ; string
postDecFinal ds.b maxStringLen ; string
preDecFinal ds.b maxStringLen ; string
formStart ds.w 1 ; INTEGER
destPos ds.w 1 ; INTEGER
formPos ds.w 1 ; INTEGER
digCnt ds.w 1 ; INTEGER
;<3/30/88ldc> count the number of literal characters we have seen in the format string
litCnt ds.w 1 ; INTEGER
mantissa ds.b 1 ; BOOLEAN
oversized ds.b 1 ; BOOLEAN
res ds.w 1 ; INTEGER
expEnd ds.w 1 ; INTEGER
Nflags ds.w 1 ; BitPack
penLastLead ds.w 1 ; INTEGER
lastLead ds.w 1 ; INTEGER
startCut ds.w 1 ; INTEGER
lastSig ds.w 1 ; INTEGER
hold ds.w 1 ; INTEGER
ch ds.w 1 ; CHAR
while1 ds.w 1 ; INTEGER
tempInt ds.w 1 ; INTEGER <9/7/88ldc>
localFrame1 EQU *
ENDR
;------------------------------------------------------------
ConvertToStringFrame record {oldA62},decrement
argFrameT2 EQU *
xOrig ds.l 1 ; VAR EXTENDED
doExp ds.w 1 ; BOOLEAN
preDig ds.w 1 ; INTEGER
postDig ds.w 1 ; INTEGER
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
formatRecord ds decForm
y ds Decimal
j ds.w 1 ; INTEGER
i ds.w 1 ; INTEGER
localFrame2 EQU *
ENDR
;============================================================
; Num2Dec
;
; changes (whatever is changed by FX2DEC - could be a0-a1,d0-d2)
; calls FX2DEC (_FP68K)
;
Num2Dec proc
;============================================================
WITH FormX2StrFrame,ConvertToStringFrame
PEA formatRecord(A6)
MOVE.L xOrig(A6),-(SP)
PEA y(A6)
FX2DEC
RTS
ENDWITH
endp
;============================================================
; Int2String
;
; changes a0-a1,d0-d1
; uses/restores --
; calls --
;
Int2String proc
; Convert the postive integer in D0 to a string at a0
; i:= 1; str:= '0';
; WHILE D0 <> 0 DO BEGIN str[i]:= (x MOD 10) + '0'; x:= x DIV 10; END;
; str[0]:= i;
EXT.L D0
MOVE.L A0,A1
MOVE.B #1,(A0)+
MOVE.L A0,D1
@L1
DIVU #10,D0
SWAP D0
ADD.B #'0',D0
MOVE.B D0,(A0)+
SWAP D0
EXT.L D0
BNE.S @L1
SUB.L A0,D1
NEG.W D1
MOVE.B D1,(A1)
RTS
endp
;============================================================
; ConvertToString
;
; trashes a0-a1,d0-d1 (d2)
; uses/restores a2-a4,d4-d7
; calls Num2Dec (may change a0-a1,d0-d2)
; Int2String changes a0-a1,d0-d1
;
ConvertToString proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D4-D7/A2-A4
postDigR EQU d6 ; number of digits after dec point
preDigR EQU d4 ; number of digits before dec pt
ff EQU a4 ; old a6 value FormX2StrFrame
yExpR EQU a2
fixedDecimal EQU 1
;============================================================
WITH FormX2StrFrame,ConvertToStringFrame
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVE.W postDig(A6),postDigR ;load up the registers
MOVE.W preDig(A6),preDigR
MOVEA.L oldA6f2(A6),ff
MOVE.B postDigR,postDec(ff) ;initialize the preDec,postDec string lengths
MOVE.B preDigR,preDec(ff)
MOVE.W postDigR,lastSig(ff) ;lastSig is the position of the last significant digit
MOVE.B doExp(A6),D0 ;check for exponent
BEQ @noExp ;…no exponent
LEA y.exp(A6),yExpR ;this is frequently enough used to warrant a register
CLR.B formatRecord.style(A6) ;= floatDecimal style
MOVE.W preDigR,D0 ;total digits is simply pre & post decimal counts
ADD.W postDigR,D0
MOVE.W D0,formatRecord.digits(A6)
JSR Num2Dec ;convert x to decimal string
; for 0, exp is undefined and sig = '0' (i.e., only one digit char). (See Apple
; Numerics Manual, 2nd ed., p. 28). So, the normal code for adjusting exp and
; setting the preDec and postDec strings doesn't work (BRC #39590)
CMPI.B #'0',y.sig+1(A6) ;DecRec=0 if sig[1]='0' (Numerics Manual p.28)
BNE.S @fixForZeroDone ;if DecRec=0, set exp, preDec, postDec appropriately
MOVE.B #'0',D0 ;we'll be setting preDec/postDec with '0'
LEA (preDec+1)(ff),A0 ;address of preDec string…
MOVE.W preDigR,D7 ;D7 is the number of digits to transfer
SUBQ.W #1,D7 ;
BLT.S @fixForZeroPreDone ;
@fixForZeroPre: ;
MOVE.B D0,(A0)+ ;put correct # of '0's into preDec string
DBRA D7,@fixForZeroPre ;
@fixForZeroPreDone: ;
LEA (postDec+1)(ff),A0 ;address of preDec string…
MOVE.W postDigR,D7 ;D7 is the number of digits to transfer
SUBQ.W #1,D7 ;courtesy DBRA
BLT.S @fixForZeroPostDone ;the zero case
@fixForZeroPost: ;
MOVE.B D0,(A0)+ ;put correct # of '0's into postDec string
DBRA D7,@fixForZeroPost ;
@fixForZeroPostDone: ;
CLR.W (yExpR) ;now set exp to 0
CLR.B negExp(ff) ;indicate not a negative exp
BRA.S @pastPostDec ;
@fixForZeroDone: ;
MOVEQ #0,D1 ;default: no negative exponent
MOVE.W (yExpR),D0 ;check if the exponent will be negative
ADD.W postDigR,D0 ;yExp:= yExp + postDig
BPL.S @noNegate ;negExp:= yExp + postDig < 0
NEG.W D0 ;yExp:= ABS(yExp);
ST D1 ;negExp:= TRUE
@noNegate:
MOVE.B D1,negExp(ff) ;set the flag
MOVE.W D0,(yExpR) ;give yExpR its final value
LEA (preDec+1)(ff),A0 ;load preDec with the digits from y's significand,
LEA y.Sig+1(A6,preDigR.W),A1 ;…but do it in reverse order:A1 is the decimal point position
MOVE.L A1,A3 ;A3 will be our local counter
MOVE.W preDigR,D7 ;D7 is the number of digits to transfer
SUBQ.W #1,D7 ;courtesy DBRA
BLT.S @preDecDone ;the zero case
@preDecLoop:
MOVE.B -(A3),(A0)+ ;load 'em up
DBRA D7,@preDecLoop
@preDecDone:
LEA (postDec+1)(ff),A0 ;now do the same for postDec
MOVE.W postDigR,D7 ;again D7 is the number of digits to transfer
SUBQ.W #1,D7
BLT.S @pastPostDec
@postDecLoop:
MOVE.B (A1)+,(A0)+ ;this time, don't reverse the order
DBRA D7,@postDecLoop
@pastPostDec:
MOVE.W (yExpR),D0 ;now convert the exponent to an integer string
LEA exp(ff),A0
JSR Int2String
BRA.S @donePreDec
@noExp:
SF negExp(ff) ;when there's no exponent, I guess it's not negative
CLR.B exp(ff) ;needs some size
MOVE.B #fixedDecimal,formatRecord.style(A6) ;set up style and digit count
MOVE.W postDigR,formatRecord.digits(A6) ;fixed style only wants to know…
;Num2Dec(formatRecord, x, y);
;result is in y(A6)
JSR Num2Dec ;…how many digits after the decimal point
LEA (postDec+1)(ff),A0 ;@postDec[1]
CLR.W D0
; j := ORD(y.sig[0])-postDig+1;
LEA y.sig(A6),A3 ;we may not have enough digits to fill the request,
MOVE.B (A3)+,D0 ;and here's how we find out.
MOVE.W postDigR,D7 ;first see how many is requested
SUBQ.W #1,D7 ;if none, then…
BLT.S @donePost ;…fine, forget it
SUB.W postDigR,D0 ;then see if Num2Dec met the request
BGE.S @canCopy ;yes, it did
;FOR i := 1 to postDig DO BEGIN
; IF j <= 0 THEN BEGIN
; postDec[i] := '0';
; postDig := postDig - 1;
; END ELSE BEGIN
; postDec[i] := y.sig[j];
; END;
; j := j+1;
;END
@makeZeroes: ;no, so fill with zeroes
MOVE.B #'0',(A0)+
SUBQ.W #1,postDigR ;these zeroes weren't originally taken into account…
ADDQ.W #1,D0 ;…when making preDig computation so we have to dec postDig
DBGE D7,@makeZeroes ;fill until D0 has made up the deficit
SUBQ.W #1,D7 ;decrement because the DBGE didn't the last time
@canCopy: ;and go for the real digits
ADDA.W D0,A3 ;this is the position into the decimal string
@copyPost:
MOVE.B (A3)+,(A0)+
DBRA D7,@copyPost
;IF preDig <> 0 THEN BEGIN
; j := ORD (y.sig[0])-postDig;
; preDec[0] := CHR[j];
; FOR i := 1 TO j DO
; preDec[i] := y.sig[j-i+1];
;END;
@donePost:
;; TST.W preDigR ;now check if we need pre-decimal digits <2/25/88med/ldc>
;; BEQ.S @donePreDec ;not today <2/25/88med/ldc>
LEA y.sig(A6),A3 ;put A3 to work
MOVEQ #0,D5 ;clear out D5
MOVE.B (A3)+,D5 ;and find out how many digits in significand
SUB.W postDigR,D5 ;postDigR reflects how many we've used up
ADDA.W D5,A3 ;move A3 beyond that point to copy backwards
LEA preDec(ff),A0 ;A0 was idle also
MOVE.B D5,(A0)+ ;so give it a length
SUBQ.W #1,D5 ;and accommodate DBRA
BLT.S @noPreDec
@preDecLoop1:
MOVE.B -(A3),(A0)+ ;copy reverse
DBRA D5,@preDecLoop1
;IF postDec[lastSig] = '0' THEN BEGIN
; REPEAT
; lastSig := lastSig-1;
; UNTIL (lastSig = 1) OR (postDec[lastSig] <> '0');
;END
@noPreDec:
@donePreDec:
MOVE.W lastSig(ff),D0 ;now knock off trailing zeroes we don't need
SUB.W #((-postDec)-1),D0 ;find the end of the postDec string we made
LEA (ff,D0.W),A0 ;and point A0 past it for predecrement
@eatZeroes:
CMP.B #'0',-(A0) ;is it a trailing zero?
BNE.S @LOUT ;no; we're done
;<2/25/88drs> Added two lines because we need to preserve one zero beyond the decimal point.
CMP.W #1,lastSig(ff)
BEQ.S @LOUT
SUBQ.W #1,lastSig(ff) ;otherwise, eat it and smile
;<2/25/88drs> Changed this line to branch always instead of checking for zero. The check is now for one
BRA.S @eatZeroes ;someday we have to run out of digits
@LOUT:
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'CONVERTT'
ENDWITH
endp
;------------------------------------------------------------
AppendSymbolFrame record {oldA62},decrement
argFrameT2 EQU *
c ds.w 1 ; CHAR
source ds.l 1 ; VAR str255
dest ds.l 1 ; VAR str255
DoSendChar ds.l 2 ; FUNCTION(x:WideChar;VAR y:str255;VAR z:INTEGER):INTEGER
oldA6f2 ds.l 1
argFrame2 EQU argFrameT2-*
return2 ds.l 1
oldA62 ds.l 1
res ds.w 1 ; INTEGER
holdMyCanonical ds.l 1
localFrame2 EQU *
ENDR
;============================================================
; ExpHandling
;
; trashes a0,d0 (a1, d1-d2)
; uses/restores a2-a4,d5-d7
; calls SendChar here trashes a0-a1,d0-d2
;
ExpHandling proc
;------------------------------------------------------------
ExpHandlingFrame record {oldA63},decrement
argFrameT3 EQU *
plusData ds.l 1 ; VAR WideCharArr
oldA6f3 ds.l 1
argFrame3 EQU argFrameT3-*
return3 ds.l 1
oldA63 ds.l 1
i ds.w 1 ; INTEGER
k ds.w 1 ; INTEGER
temp ds.l 1 ; ^WideCharArr
localFrame3 EQU *
ENDR
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D5-D7/A2-A4
af EQU a2
ff EQU a4
destR EQU a2
partsTableR EQU a0
plusDataR EQU a3
;============================================================
WITH ExpHandlingFrame, AppendSymbolFrame, FormX2StrFrame,FormatStringPriv, NumberParts
LINK A6,#localFrame3
MOVEM.L localRegs,-(A7)
MOVEA.L oldA6f3(A6),af ;AppendSymbol frame
MOVEA.L oldA6f2(af),ff ;FormatX2Str frame
MOVE.L dest(af),destR ;load up a few lazy registers
MOVEA.L partsTable(ff),partsTableR
SF mantissa(ff) ;mantissa flag says we're into the exponent
MOVE.B negExp(ff),D0 ;if negExp, then we know we need E-
BEQ.S @needEPlus
LEA PeMinus(partsTableR),A3 ;grab the E- format
BRA.S @EMerge ;and continue
@needEPlus:
MOVEA.L plusData(A6),plusDataR ;otherwise retrieve E+ or E, whichever came
@EMerge:
MOVE.W WideCharArr.size(plusDataR),D5 ;set up D5 as loop end
CLR.W D7 ;and D7 as loop counter
BRA.S @loopTest ;start loop
@loopStart: ;loop for sending exponent characters to output stream
CLR.W -(A7) ;result
MOVE.W D7,D0
ADD.W D0,D0
MOVE.W WideCharArr.data(plusDataR,D0.W),-(A7) ;the character itself
MOVE.L destR,-(A7) ;what string the character is going to
PEA destPos(ff) ;and how far into the string
JSR SendChar
MOVE.W (A7)+,D6 ;just ignore the result. Apathy, I guess.
ADDQ.W #1,D7 ;loop counter increment
@loopTest:
compw D5,D7 ;done yet?
BLE.S @loopStart
@L168:
MOVEM.L (A7)+,localRegs
move.w #argFrame3, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'EXPHANDL'
ENDWITH
endp
;============================================================
; AppendSymbol
;
; trashes a0-a1,d0-d1
; uses/restores a3-a4,d4-d7
; calls ExpHandling trashes a0,d0 (a1,d1-d2)
; ? some procedure with a handle at DoSendChar(A6) + 2 - trashes ?
;
AppendSymbol proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D5-D7/A2-A4 ; why was a2 added? -pke, 02/21/89
cR EQU d6
sourceR EQU d5
ff EQU a4
resR EQU d7
partsTableR EQU a3
;============================================================
WITH AppendSymbolFrame, FormX2StrFrame,FormatStringPriv, NumberParts, SMgrRecord
LINK A6,#localFrame2
MOVEM.L localRegs,-(A7)
MOVE.W c(A6),cR ;load up some registers
MOVE.L source(A6),sourceR
MOVEA.L oldA6f2(A6),ff ;FormatX2Str frame
;xxx <2/23/88:ldc> replaced #1 with #fFormatOK
MOVEQ #fFormatOK, resR ;register storage for return value
MOVE.L myCanonical(ff),holdMyCanonical(A6)
MOVEA.L partsTable(ff),partsTableR
compw #32,cR ;printable character?
BLT.S @doFormByte ;no. It's a format byte
MOVEA.L dest(A6),A0 ;yes, it's printable; copy it verbatim
MOVE.W destPos(ff),D0 ;dest[destPos]:= c
MOVE.B cR,0(A0,D0.W)
ADDQ.W #1,destPos(ff) ;and don't forget to increment destPos
;<3/30/88ldc> track the number of literal chars in format string
ADDQ.W #1,litCnt(ff)
BRA @almostDone
@doFormByte:
MOVE.W cR,D0 ;CASE ORD(c):jump table computations
SUBQ.W #tokLeader,D0 ;tokLeader is lowest entry in the table
BMI @outOfRange
compw #(tokEMinus-tokLeader),D0 ;tokEMinus is highest entry
BGT @outOfRange
ADD.W D0,D0 ;these are word offsets of course
MOVE.W @jTab(D0.W),D0
JMP *+2(D0.W)
@jTab:
DC.W @leads-@jTab+2, @leads-@jTab+2, @leads-@jTab+2
DC.W @noEntry-@jTab+2, @others-@jTab+2, @others-@jTab+2
DC.W @others-@jTab+2, @noEntry-@jTab+2, @noEntry-@jTab+2
DC.W @noEntry-@jTab+2, @noEntry-@jTab+2, @ePlus-@jTab+2
DC.W @eMinus-@jTab+2
@ePlus:
PEA PePlus(partsTableR) ;create the exponent with PePlus
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; intlSpec for vector
move.l sVectExpHandling(a0), a0 ; <6/21/88ldc>
jsr (a0) ; call vector <6/17/88ldc>
ELSE
JSR ExpHandling
ENDIF
BRA @almostDone
@eMinus:
PEA PeMinusPlus(partsTableR) ;create the exponent with PeMinusPlus
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; intlSpec for vector
move.l sVectExpHandling(a0), a0 ; <6/21/88ldc>
jsr (a0) ; call vector <6/17/88ldc>
ELSE
JSR ExpHandling
ENDIF
BRA @almostDone
@leads: ;This gets complicated.
MOVEA.L sourceR,A0 ;first find out if we have any digits left
CLR.W D0
MOVE.B (A0),D0
compw digCnt(ff),D0
BLT.S @noDigsLeft
LEA Nflags(ff),A1 ;yes, so decide whether to send a Roman digit or other
BTST #fIsAltNum,(A1)
BEQ.S @isRoman
CLR.W -(A7) ;result space for DoSendChar
MOVE.W digCnt(ff),D0 ;get the roman digit into D1
CLR.W D1
MOVE.B 0(A0,D0.W),D1
SUB.W #'0',D1 ;now subtract '0' to get an index
ADD.W D1,D1 ;word index, that is
LEA (altNumTable.data)(partsTableR),A0 ;altNumTable address
MOVE.W 0(A0,D1.W),-(A7) ;push the foreign digit
MOVE.L dest(A6),-(A7) ;and the destination address
PEA destPos(ff) ;and the destination position
LEA DoSendChar(A6),A0 ;go through the cranky procedure variable computations
MOVE.L (A0)+,D0
BEQ.S @L181
MOVE.L D0,-(A7)
@L181:
MOVEA.L (A0),A0
JSR (A0) ;and finally ship off the character
MOVE.W (A7)+,resR
BRA.S @mergeHadLead
@isRoman:
MOVEA.L dest(A6),A0 ;roman digits are roman digits; just copy them
MOVE.W destPos(ff),D0
MOVEA.L sourceR,A1
MOVE.W digCnt(ff),D1
MOVE.B 0(A1,D1.W),0(A0,D0.W)
ADDQ.W #1,destPos(ff) ;and increment the destination pointer
@mergeHadLead:
ADDQ.W #1,digCnt(ff) ;since we've tacked on another digit, up digCnt also
MOVE.W destPos(ff),lastLead(ff) ;this little obscurity is bookkeeping for the…
;…possibility that we may have to backtrack because of optional digits
BRA.S @mergeLead ;basically, let's get out of here
@noDigsLeft:
compw #tokNonLeader,cR ;find out if this is a nonLeader or not
BNE.S @notNonLeader
MOVE.W destPos(ff),penLastLead(ff) ;if it is, then save the position because…
;…we may need to clip back to it because of optional characters
BRA.S @mergeLead ;and stay out!
;<3/25/88ldc> added common call to DoSendChar to clean up code
@DoDoSendChar:
MOVE.W cR,D0
ADD.W D0,D0
CLR.W -(A7)
MOVE.W -(tokLeftQuote*2)+data(partsTableR,D0.W),-(A7)
MOVE.L dest(A6),-(A7)
PEA destPos(ff)
LEA DoSendChar(A6),A0
MOVE.L (A0)+,D0
BEQ.S @skipIt
MOVE.L D0,-(A7)
@skipIt:
MOVEA.L (A0),A0
JSR (A0)
MOVE.W (A7)+,resR
RTS
@notNonLeader
;<3/25/88ldc> made proc call to reduce code size
JSR @DoDoSendChar ;res:= DoSendChar(data[ORD(c)],dest,destPos);
;<3/25/88ldc> added this line to fix problem of stripping off of leaders
MOVE.W destPos(ff),lastLead(ff)
CLR.W penLastLead(ff) ;reset penultimate LastLead because only junk between…
;…nonLeaders is optional
BRA.s @mergeLead
@others:
;<3/25/88ldc> changed to proc call
JSR @DoDoSendChar ;res:= DoSendChar(data[ORD(c)],dest,destPos);
@mergeLead:
@almostDone:
@outOfRange:
@noEntry:
compw #fFormatOK,resR ;has resR been modified?
BEQ.S @noResChange
MOVEA.L oldA6f2(A6),A0 ;update the function result if it has
MOVE.W resR, returnValue1(A0)
@noResChange:
MOVEM.L (A7)+,localRegs
move #argFrame2, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'APPENDSY'
ENDWITH
endp
;============================================================
; xFormX2Str
;
; trashes a0-a1,d0-d1
; uses/restores a2-a5,d4-d7
; calls ConvertToString here trashes a0-a1,d0-d1 (d2?)
; SendCharRev here trashes a0-a1,d0-d2
; AppendSymbol here trashes a0-a1,d0-d2 + ?
; NextFormatClass here changes d0
; SendChar here trashes a0-a1,d0-d2
;
xFormX2Str proc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
localRegs reg D4-D7/A2-A5
destPosR EQU a5
resR EQU d5
myCanonicalR EQU a4
partsTableR EQU a3
oversizedR EQU d4
formCountR EQU d6
NflagsR EQU a2
formPosR EQU d7
;============================================================
WITH FormX2StrFrame,FormatStringPriv, NumberParts, SMgrRecord
LINK A6,#localFrame1
MOVEM.L localRegs,-(A7)
MOVEA.L xOrig(A6),A0
LEA destPos(A6),destPosR
LEA x(A6),A1
MOVE.L A1,A2
MOVE.L (A0)+,(A2)+ ;need a local copy because it might change
MOVE.L (A0)+,(A2)+
MOVE.W (A0),(A2)
;xxx<2/23/88:ldc> replaced #1 with symbolic constant #fFormatOK
MOVEQ #fFormatOK,resR ;the original idea was to update returnValue1…
;…if resR was ever modified. I'm not through yet
MOVE.W #fFormatOK, returnValue1(A6)
MOVEA.L myCanonical(A6),myCanonicalR ;make use of the hired hands
tst.b formString(myCanonicalR) ; check for empty format string <9/7/88ldc>
beq @emptyFormatString
MOVEA.L partsTable(A6),partsTableR
SF oversizedR ;initialize the hell out of everything
ST mantissa(A6)
SF doNegative(A6)
MOVE.W #(maxStringLen-1),D0
MOVE.B D0,preDecFinal(A6)
MOVE.B D0,postDecFinal(A6)
MOVE.B D0,expFinal(A6)
;<9/7/88ldc> test for minus zero, overflow or NAN cf bug # 30675, 33761
bsr GetSaneClass ; get the class of xOrig
cmp.w #negZero, d0 ; negative zero?
beq.s @isZero ; yes
cmp.w #posQNAN, d0
beq @returnNAN
cmp.w #negQNAN, d0
beq @returnNAN
cmp.w #posSNAN, d0
beq @returnNAN
cmp.w #negSNAN, d0
beq @returnNAN
cmp.w #posInf, d0
beq @returnOverflow
cmp.w #negInf, d0
beq @returnOverflow
; if positive format is not valid, give up <05/22/89 pke>
BTST.B #fExists,(flags+2*fPositive)(myCanonicalR)
BEQ @emptyFormatString
TST.B (A1) ;xOrig > 0?
BPL.S @noNeg
MOVEQ #fNegative,formCountR
EORI.B #$80,(A1) ;flip top order bit to negate
BRA.S @endXTest
;NOTE: don't modify A1 until @donePercent!!
@noNeg:
BNE.S @isPos ;is it negative?
@isZero
MOVEQ #fZero,formCountR
BRA.S @endXTest
@isPos:
MOVEQ #fPositive,formCountR ;it is positive
@endXTest:
MOVE.W formCountR,D0 ;Do we have a format corresponding to x?
ADD.W D0,D0
BTST #fExists,flags(myCanonicalR,D0.W)
BNE.S @doneFormat
compb #fNegative,formCountR ;is x negative?
SEQ doNegative(A6) ;let everyone know; in any case, positive is default
MOVEQ #fPositive,formCountR
@doneFormat:
MOVE.W formCountR,D0 ;now make sure the format doesn't specify percents
ADD.W D0,D0
LEA Nflags(A6),NflagsR
LEA flags(myCanonicalR,D0.W),A0
MOVE.W (A0),(NflagsR)
BTST #fIsPercent,(NflagsR)
BEQ.S @donePercent
PEA @c100 ;its a constant 100 to multiply by
MOVE.L A1,-(A7)
FMULX
@donePercent:
PEA x(A6) ;set up params for ConvertToString
MOVEQ #0,D0 ;determine if either EMinus or EPlus is applicable
MOVE.W (NflagsR),D0
AND.L #fEMEP,D0
SNE D0
MOVE.B D0,-(A7)
MOVE.W formCountR,D0 ;push preDig[formCount] and postDig[formCount]
ADD.W D0,D0
MOVE.W PreDig(myCanonicalR,D0.W),-(A7)
MOVE.W PostDig(myCanonicalR,D0.W),-(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
GetSMgrCore a0 ; set up vectorized ConvertToString
move.l sVectConvertToString(a0), a0
jsr (a0) ; call vector <6/17/88ldc>
ELSE
JSR ConvertToString ;and finally convert x to a string
ENDIF
MOVE.W #1,(destPosR) ;initialize all these silly indices
MOVE.W #1,digCnt(A6)
; initialize the number of literal chars <3/30/88ldc>
MOVE.W #1, litCnt(a6)
MOVE.W formCountR,D0 ;formPosR:= decLocs[formCount]-1
ADD.W D0,D0
MOVE.W decLocs(myCanonicalR,D0.W),formPosR
SUBQ.W #1,formPosR
CMP.B #fPositive,formCountR ;set formStart. If formCount is positive, formStart is just 1
BNE.S @notPositive
MOVE.W #1,formStart(A6)
BRA.S @mergeFormStart
@notPositive: ;otherwise, it's startLocs[formCount]
MOVE.W startLocs(myCanonicalR,D0.W),formStart(A6)
@mergeFormStart:
BTST #fIsDecimal,(NflagsR) ;do we have a decimal point to worry about?
BEQ.S @endDecPoint
CLR.W -(A7) ;go ahead a start preDecFinal with a decimal point
MOVE.W data+((tokDecPoint-tokLeftQuote)*2)(partsTableR),-(A7)
PEA preDecFinal(A6) ;(because preDecFinal is a reversed string)
MOVE.L destPosR,-(A7) ;push the position within preDecFinal
JSR SendCharRev ;the reversed version of sendChar
MOVE.W (A7)+,resR ;accumulate result
@endDecPoint:
CLR.W penLastLead(A6) ;so far, no nonLeaders that can bracket optional material
;<1/23/88drs> Changed 1 line to fix bug.
;destPos, rather than 0, must be moved into lastLead to handle numbers
;less than 1 with only nonLeaders to the left of the decimal point.
MOVE.W (destPosR),lastLead(A6)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
move.l NFlagsR, -(sp) ; save this little mother <6/17/88ldc>
GetSMgrCore NflagsR ; get this for jump to AppendSymbol <6/17/88ldc>
move.l sVectAppendSymbol(NflagsR), NflagsR
ENDIF
@preDecLoop:
compw formStart(A6),formPosR ;WHILE formPosR >= formStart
BLT.S @endPreDecLoop
CLR.W D1
MOVE.B formString(myCanonicalR,formPosR.W),D1
MOVE.W D1,-(A7) ;push current format code
PEA preDec(A6) ;push source
PEA preDecFinal(A6) ;push destination
PEA SendCharRev ;push SendCharRev procedure
CLR.L -(A7)
MOVE.L A6,-(A7) ;and the silly frame pointer
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
jsr (NflagsR) ; get from intlSpec <6/17/88ldc>
ELSE
JSR AppendSymbol ; vectorized <6/17/88ldc>
ENDIF
TST.W penLastLead(A6) ;if bracketed by nonLeaders, cut out the optional material
BEQ.S @mergePenTest
MOVE.W lastLead(A6),(destPosR) ;snip it off by moving destPos back
CLR.W penLastLead(A6) ;and reset penLastLead
@mergePenTest:
SUBQ.W #1,formPosR ;in any case, decrement the form index
BRA.S @preDecLoop
@endPreDecLoop:
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
move.l (sp)+, NflagsR ; restore the saved register <6/17/88ldc>
ENDIF
CLR.W D0
MOVE.B preDec(A6),D0 ;check if our digit count <= the available digits
compw digCnt(A6),D0
BLT.S @mergeDigCheck
; destPos = litCnt means we have exactly matched the literal chars <3/30/88ldc>
; in the format string, hence no overflow
move.w destPos(a6), d0
compw litCnt(a6), d0
beq.s @mergeDigCheck
ST oversizedR ;we're a wreck
MOVE.W #fFormatOverflow,returnValue1(A6)
@mergeDigCheck:
MOVE.W (destPosR),D0 ;now set the size of preDecFinal
SUBQ.W #1,D0
MOVE.B D0,preDecFinal(A6)
MOVE.B oversizedR,D0 ;did we overflow our available number size?
BNE @mergePreDecV
MOVE.B formCountR,D0 ;find the location of the decimal point in form string
EXT.W D0
ADD.W D0,D0
MOVE.W decLocs(myCanonicalR,D0.W),formPosR ;set formPos to that location
BTST #fIsDecimal,(NflagsR) ;if we had a decimal point then increment our position
BEQ.S @mergeDecPoint
ADDQ.W #1,formPosR
@mergeDecPoint:
MOVE.W #1,(destPosR) ;again go crazy initializing things
MOVE.W #1,digCnt(A6)
CLR.W startCut(A6) ;startCut tells where to chop off trailing zeroes
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
move.l NFlagsR, -(sp) ; save this little mother <6/17/88ldc>
GetSMgrCore NflagsR ; get this for jump to AppendSymbol <6/17/88ldc>
move.l sVectAppendSymbol(NflagsR), NflagsR ; <6/21/88ldc>
ENDIF
@postDecWhile:
MOVE.B formCountR,D0 ;WHILE i < startLocs[nextFormatClass(formCount)]…
JSR NextFormatClass
ADD.W D0,D0
compw startLocs(myCanonicalR,D0.W),formPosR
SLT D0
AND.B mantissa(A6),D0 ;…AND mantissa DO
BEQ.S @endPosDecWhile
MOVE.W (destPosR),hold(A6) ;save our current destination position in case we need to cut
CLR.W D1
MOVE.B formString(myCanonicalR,formPosR.W),D1 ;get formString[formPosR]
MOVE.W D1,ch(A6) ;save it in ch
MOVE.W D1,-(A7) ;and push it for AppendSymbol
PEA postDec(A6)
PEA postDecFinal(A6)
PEA SendChar ;this time, it's not reversed
CLR.L -(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
jsr (NflagsR) ; get from vector <6/17/88ldc>
ELSE
JSR AppendSymbol
ENDIF
MOVE.W lastSig(A6),D0 ;if our digit count has gone beyond lastSig,
compw digCnt(A6),D0 ;then we may have to cut
BGE.S @mergeAfterCut
MOVE.W ch(A6),D1
CMP.B #tokLeader,D1 ;if it's a leader but not nonLeader, then no cut
BEQ.S @noCutting
CMP.B #tokZeroLead,D1
BNE.S @maybeCut
@noCutting:
CLR.W startCut(A6) ;reset startCut because leaders nullify it
BRA.S @mergeAfterCut
@maybeCut:
CMP.B #tokNonLeader,D1 ;the only cutting possibility is if D1 is a nonLeader
BNE.S @setUpHold
ADDQ.W #1,D0
compw digCnt(A6),D0 ;but no cut if digCount has not exceeded lastSig
BGE.S @mergeAfterCut
MOVE.W startCut(A6),D1 ;if startCut is clear because somewhere along the line…
BNE.S @mergeSetSC ;…we hit a leader other than nonLead, we need to…
MOVE.W hold(A6),D1 ;…set the new startCut to the character we just appended
MOVE.W D1,startCut(A6)
@mergeSetSC:
MOVE.W D1,(destPosR) ;in any case, do the cut
BRA.S @mergeAfterCut
@setUpHold:
TST.W startCut(A6) ;test if startCut is zero
BNE.S @mergeAfterCut ;and if it's not then leave it alone
MOVE.W hold(A6),startCut(A6) ;otherwise set it to the character we just appended
@mergeAfterCut:
ADDQ.W #1,formPosR ;and finally, increment the position within the form string
BRA @postDecWhile
@endPosDecWhile:
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
move.l (sp)+, NflagsR ; restore after using for intlSpec <6/17/88ldc>
ENDIF
MOVE.W (destPosR),D0 ;now give a length to postDecFinal
SUBQ.W #1,D0
MOVE.B D0,postDecFinal(A6)
MOVE.W formPosR,expEnd(A6) ;expEnd is actually the beginning
MOVE.B formCountR,D0 ;formPos:= startLocs[nextFormatClass(formCount)]
JSR NextFormatClass ;that is the end of the formString for this format
ADD.W D0,D0
MOVE.W startLocs(myCanonicalR,D0.W),formPosR
SUBQ.W #1,formPosR
MOVE.W #1,(destPosR)
MOVE.W #1,digCnt(A6)
;<1/23/88drs> Added following 2 lines to correct bug.
;Optional digits in the exponent should act like digits in
;the pre-decimal significand
CLR.W penLastLead(A6)
CLR.W lastLead(A6)
MOVE.B mantissa(A6),D0 ;if we never hit the exponent then skip it
BEQ.S @doExponent
CLR.B expFinal(A6)
BRA.S @pastExponent
@doExponent:
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
move.l NflagsR, -(sp) ; store reg and get intlSpec <6/17/88ldc>
GetSMgrCore NflagsR ; AppendSymbol is now a vector <6/21/88ldc>
move.l sVectAppendSymbol(NflagsR), NflagsR
ENDIF
@expWhile:
compw expEnd(A6),formPosR ; WHILE formPosR >= expEnd
BLT.S @pastExpWhile
CLR.W D1
MOVE.B formString(myCanonicalR,formPosR.W),D1
MOVE.W D1,-(A7) ;push formString[formPos]
PEA exp(A6)
PEA expFinal(A6)
PEA SendCharRev ;reversed this time
CLR.L -(A7)
MOVE.L A6,-(A7)
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
jsr (NflagsR) ; <6/17/88ldc>
ELSE
JSR AppendSymbol ;send off this character
ENDIF
;<1/23/88drs> Added the following 5 lines to fix bug.
;Digits in the exponent should act like pre-decimal digits.
TST.W penLastLead(A6) ;if bracketed by nonLeaders then snip of the optional stuff
BEQ.S @noSnipExp
MOVE.W lastLead(A6),(destPosR)
CLR.W penLastLead(A6)
@noSnipExp:
SUBQ.W #1,formPosR ;decrement position in formString
BRA.S @expWhile
@pastExpWhile:
IF forRom THEN ; changed buildLevel>=2 to forRom <06/30/89 pke>
move.l (sp)+, NflagsR ; restore
ENDIF
MOVE.W (destPosR),D0 ;set the length of the expFinal string
SUBQ.W #1,D0
MOVE.B D0,expFinal(A6)
CLR.W D0
MOVE.B exp(A6),D0 ;if digCnt < ORD(exp[0]) then we blew it
compw digCnt(A6),D0
BLT.S @expOkSize
ST oversizedR
@mergePreDecV:
@pastExponent:
@expOkSize:
MOVE.B oversizedR,D0 ;did we ever get blimped?
BEQ.S @noSizeProblem
MOVE.W #fFormatOverflow,returnValue1(A6)
BRA @outTheDoor
@noSizeProblem:
MOVEA.L out(A6),A0 ;give out a maximum size to start with
MOVE.B #255,(A0)
MOVE.W #1,(destPosR) ;and reset destPosR
MOVE.B doNegative(A6),D0 ;if we need a negative sign then get one
BEQ.S @pastNegSign
CLR.W -(A7)
MOVE.W data+((tokMinusSign-tokLeftQuote)*2)(partsTableR),-(A7)
MOVE.L out(A6),-(A7)
MOVE.L destPosR,-(SP)
JSR SendChar
MOVE.W (A7)+,resR
@pastNegSign: ;the next 50,000 lines only copy…
;…preDecFinal,postDecFinal,and expFinal into out
CLR.W D0
MOVE.B preDecFinal(A6),D0
MOVE.W D0,formPosR
BRA.S @L227
@L228:
MOVEA.L out(A6),A0
MOVE.W (destPosR),D0
LEA preDecFinal(A6),A1
MOVE.B 0(A1,formPosR.W),0(A0,D0.W)
ADDQ.W #1,(destPosR)
SUBQ.W #1,formPosR
@L227:
compw #1,formPosR
BGE.S @L228
CLR.W D0
MOVE.B postDecFinal(A6),D0
MOVE.W D0,while1(A6)
MOVEQ #1,formPosR
BRA.S @L229
@L231:
MOVEA.L out(A6),A0
MOVE.W (destPosR),D0
LEA postDecFinal(A6),A1
MOVE.B 0(A1,formPosR.W),0(A0,D0.W)
ADDQ.W #1,(destPosR)
ADDQ.W #1,formPosR
@L229:
compw while1(A6),formPosR
BLE.S @L231
@L230:
CLR.W D0
MOVE.B expFinal(A6),D0
MOVE.W D0,formPosR
BRA.S @L232
@L233:
MOVEA.L out(A6),A0
MOVE.W (destPosR),D0
LEA expFinal(A6),A1
MOVE.B 0(A1,formPosR.W),0(A0,D0.W)
ADDQ.W #1,(destPosR)
SUBQ.W #1,formPosR
@L232:
compw #0,formPosR
bgt.s @L233 ; was bge 1 <2/7/88med>
BTST #fIsPercent,(NflagsR) ;are we dealing with a percent?
BEQ.S @afterPercent ;thank God no
CLR.W -(A7) ;otherwise tack it on too
MOVE.W data+((tokPercent-tokLeftQuote)*2)(partsTableR),-(A7)
MOVE.L out(A6),-(A7)
MOVE.L destPosR,-(SP)
JSR SendChar
MOVE.W (A7)+,resR
@afterPercent:
MOVEA.L out(A6),A0 ;give out a length
MOVE.W (destPosR),D0
SUBQ.W #1,D0
MOVE.B D0,(A0)
bra.s @outTheDoor ; <9/7/88ldc>
@returnNAN
move.w #fFormStrIsNAN, resR ; <9/8/88ldc>
bra.s @outTheDoor ; <9/8/88ldc>
@returnOverflow
move.w #fFormatOverflow, resR ; <9/8/88ldc>
bra.s @outTheDoor ; <9/8/88ldc>
@emptyFormatString
move.w #fEmptyFormatString, resR ; flag empty format string <9/7/88ldc>
@outTheDoor:
compw #fFormatOK, resR ;see if we ever blew it anywhere
BEQ.S @afterRes
MOVE.W resR,returnValue1(A6)
@afterRes:
MOVEM.L (A7)+,localRegs
move.w #argFrame1, d0 ; for StdUnlink
bra StdUnlink ; standard exit
CheckDebug 'FORMX2ST'
@c100: ;constant 100.0
DC.W $4005, $C800, $0000, $0000, $0000
ENDWITH
endp
end