\ @(#) numberio.fth 98/01/26 1.2
\ Copyright 1994 3DO, Phil Burk, Larry Polansky, Devid Rosenboom
\ The pForth software code is dedicated to the public domain,
\ and any third party may reproduce, distribute and modify
\ the pForth software code or any derivative works thereof
\ without any compensation or license. The pForth software
\ code is provided on an "as is" basis without any warranty
\ of any kind, including, without limitation, the implied
\ warranties of merchantability and fitness for a particular
\ purpose and their equivalents under the laws of any jurisdiction.
\ ------------------------ INPUT -------------------------------
\ Convert a single character to a number in the given base.
: DIGIT ( char base -- n true | char false )
IF ascii A - ascii 9 + 1+
( between 9 and A is bad )
drop 0 ( trigger error below )
: >NUMBER ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 , convert till bad char , CORE )
r@ 0> \ any characters left?
digit ( ud1 c-addr , n true | char false )
WHILE ( -- ud1 c-addr n )
swap >r ( -- ud1lo ud1hi n )
swap base @ ( -- ud1lo n ud1hi base )
um* drop ( -- ud1lo n ud1hi*baselo )
rot base @ ( -- n ud1hi*baselo ud1lo base )
um* ( -- n ud1hi*baselo ud1lo*basello ud1lo*baselhi )
r> 1- >r \ decrement count
: CONVERT ( ud1 c-addr1 -- ud2 c-addr2 , convert till bad char , CORE EXT )
1 constant NUM_TYPE_SINGLE
2 constant NUM_TYPE_DOUBLE
\ This is similar to the F83 NUMBER? except that it returns a number type
\ and then either a single or double precision number.
: ((NUMBER?)) ( c-addr u -- 0 | n 1 | d 2 , convert string to number )
dup 0= IF 2drop NUM_TYPE_BAD exit THEN \ any chars?
0 0 2swap ( 0 0 c-addr cnt )
\ check for '-' at beginning, skip if present
over c@ ascii - = \ is it a '-'
IF 1- >r 1+ r> ( -- 0 0 c-addr+1 cnt-1 , skip past minus sign )
>number dup 0= \ convert as much as we can
drop \ drop hi part of num
r@ \ check flag to see if '-' sign used
1 = swap \ if final character is '.' then double
r@ \ check flag to see if '-' sign used
: (NUMBER?) ( $addr -- 0 | n 1 | d 2 , convert string to number )
\ 0sp c" xyz" (number?) .s
\ 0sp c" 234" (number?) .s
\ 0sp c" -234" (number?) .s
\ 0sp c" 234." (number?) .s
\ 0sp c" -234." (number?) .s
\ 0sp c" 1234567855554444." (number?) .s
\ ------------------------ OUTPUT ------------------------------
\ Number output based on F83
variable HLD \ points to last character added
: hold ( char -- , add character to text representation)
: <# ( -- , setup conversion )
: #> ( d -- addr len , finish conversion )
: sign ( n -- , add '-' if negative )
: # ( d -- d , convert one digit )
base @ mu/mod rot 9 over <
: #s ( d -- d , convert remaining digits )
: (UD.) ( ud -- c-addr cnt )
: UD. ( ud -- , print unsigned double number )
>r (ud.) r> over - spaces type
: (D.) ( d -- c-addr cnt )
tuck dabs <# #s rot sign #>
: D.R ( d n -- , right justified )
>r (d.) r> over - spaces type
: (U.) ( u -- c-addr cnt )
: U. ( u -- , print unsigned number )
: U.R ( u n -- , print right justified )
>r (u.) r> over - spaces type
: (.) ( n -- c-addr cnt )
dup abs 0 <# #s rot sign #>
: . ( n -- , print signed number)
: .R ( n l -- , print right justified)
>r (.) r> over - spaces type