1 \ @(#) numberio.fth 98/01/26 1.2
\r
7 \ Copyright 1994 3DO, Phil Burk, Larry Polansky, Devid Rosenboom
\r
9 \ The pForth software code is dedicated to the public domain,
\r
10 \ and any third party may reproduce, distribute and modify
\r
11 \ the pForth software code or any derivative works thereof
\r
12 \ without any compensation or license. The pForth software
\r
13 \ code is provided on an "as is" basis without any warranty
\r
14 \ of any kind, including, without limitation, the implied
\r
15 \ warranties of merchantability and fitness for a particular
\r
16 \ purpose and their equivalents under the laws of any jurisdiction.
\r
18 anew task-numberio.fth
\r
21 \ ------------------------ INPUT -------------------------------
\r
22 \ Convert a single character to a number in the given base.
\r
23 : DIGIT ( char base -- n true | char false )
\r
25 \ convert lower to upper
\r
31 dup dup ascii A 1- >
\r
32 IF ascii A - ascii 9 + 1+
\r
36 ( between 9 and A is bad )
\r
37 drop 0 ( trigger error below )
\r
50 : >NUMBER ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 , convert till bad char , CORE )
\r
53 r@ 0> \ any characters left?
\r
56 digit ( ud1 c-addr , n true | char false )
\r
65 WHILE ( -- ud1 c-addr n )
\r
66 swap >r ( -- ud1lo ud1hi n )
\r
67 swap base @ ( -- ud1lo n ud1hi base )
\r
68 um* drop ( -- ud1lo n ud1hi*baselo )
\r
69 rot base @ ( -- n ud1hi*baselo ud1lo base )
\r
70 um* ( -- n ud1hi*baselo ud1lo*basello ud1lo*baselhi )
\r
72 r> 1+ \ increment char*
\r
73 r> 1- >r \ decrement count
\r
79 : CONVERT ( ud1 c-addr1 -- ud2 c-addr2 , convert till bad char , CORE EXT )
\r
83 0 constant NUM_TYPE_BAD
\r
84 1 constant NUM_TYPE_SINGLE
\r
85 2 constant NUM_TYPE_DOUBLE
\r
87 \ This is similar to the F83 NUMBER? except that it returns a number type
\r
88 \ and then either a single or double precision number.
\r
89 : ((NUMBER?)) ( c-addr u -- 0 | n 1 | d 2 , convert string to number )
\r
90 dup 0= IF 2drop NUM_TYPE_BAD exit THEN \ any chars?
\r
92 \ prepare for >number
\r
93 0 0 2swap ( 0 0 c-addr cnt )
\r
95 \ check for '-' at beginning, skip if present
\r
96 over c@ ascii - = \ is it a '-'
\r
98 IF 1- >r 1+ r> ( -- 0 0 c-addr+1 cnt-1 , skip past minus sign )
\r
101 >number dup 0= \ convert as much as we can
\r
103 2drop \ drop addr cnt
\r
104 drop \ drop hi part of num
\r
105 r@ \ check flag to see if '-' sign used
\r
109 ELSE ( -- d addr cnt )
\r
110 1 = swap \ if final character is '.' then double
\r
113 r@ \ check flag to see if '-' sign used
\r
125 : (NUMBER?) ( $addr -- 0 | n 1 | d 2 , convert string to number )
\r
129 ' (number?) is number?
\r
131 \ 0sp c" xyz" (number?) .s
\r
132 \ 0sp c" 234" (number?) .s
\r
133 \ 0sp c" -234" (number?) .s
\r
134 \ 0sp c" 234." (number?) .s
\r
135 \ 0sp c" -234." (number?) .s
\r
136 \ 0sp c" 1234567855554444." (number?) .s
\r
139 \ ------------------------ OUTPUT ------------------------------
\r
140 \ Number output based on F83
\r
141 variable HLD \ points to last character added
\r
143 : hold ( char -- , add character to text representation)
\r
147 : <# ( -- , setup conversion )
\r
150 : #> ( d -- addr len , finish conversion )
\r
151 2drop hld @ pad over -
\r
153 : sign ( n -- , add '-' if negative )
\r
154 0< if ascii - hold then
\r
156 : # ( d -- d , convert one digit )
\r
157 base @ mu/mod rot 9 over <
\r
162 : #s ( d -- d , convert remaining digits )
\r
168 : (UD.) ( ud -- c-addr cnt )
\r
171 : UD. ( ud -- , print unsigned double number )
\r
175 >r (ud.) r> over - spaces type
\r
177 : (D.) ( d -- c-addr cnt )
\r
178 tuck dabs <# #s rot sign #>
\r
183 : D.R ( d n -- , right justified )
\r
184 >r (d.) r> over - spaces type
\r
187 : (U.) ( u -- c-addr cnt )
\r
190 : U. ( u -- , print unsigned number )
\r
193 : U.R ( u n -- , print right justified )
\r
194 >r (u.) r> over - spaces type
\r
196 : (.) ( n -- c-addr cnt )
\r
197 dup abs 0 <# #s rot sign #>
\r
199 : . ( n -- , print signed number)
\r
202 : .R ( n l -- , print right justified)
\r
203 >r (.) r> over - spaces type
\r