\ @(#) numberio.fth 98/01/26 1.2 \ numberic_io.fth \ \ numeric conversion \ \ Author: Phil Burk \ 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. anew task-numeric_io.fth decimal \ ------------------------ INPUT ------------------------------- \ Convert a single character to a number in the given base. : DIGIT ( char base -- n true | char false ) >r \ convert lower to upper dup ascii a < not IF ascii a - ascii A + THEN \ dup dup ascii A 1- > IF ascii A - ascii 9 + 1+ ELSE ( char char ) dup ascii 9 > IF ( between 9 and A is bad ) drop 0 ( trigger error below ) THEN THEN ascii 0 - dup r> < IF dup 1+ 0> IF nip true ELSE drop FALSE THEN ELSE drop FALSE THEN ; : >NUMBER ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 , convert till bad char , CORE ) >r BEGIN r@ 0> \ any characters left? IF dup c@ base @ digit ( ud1 c-addr , n true | char false ) IF TRUE ELSE drop FALSE THEN ELSE false THEN 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 ) d+ ( -- ud2 ) r> 1+ \ increment char* r> 1- >r \ decrement count REPEAT r> ; \ obsolete : CONVERT ( ud1 c-addr1 -- ud2 c-addr2 , convert till bad char , CORE EXT ) 256 >NUMBER DROP ; 0 constant NUM_TYPE_BAD 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 drop NUM_TYPE_BAD exit THEN \ any chars? \ prepare for >number 0 0 2swap ( 0 0 c-addr cnt ) \ check for '-' at beginning, skip if present over c@ ascii - = \ is it a '-' dup >r \ save flag IF 1- >r 1+ r> ( -- 0 0 c-addr+1 cnt-1 , skip past minus sign ) THEN \ >number dup 0= \ convert as much as we can IF 2drop \ drop addr cnt drop \ drop hi part of num r@ \ check flag to see if '-' sign used IF negate THEN NUM_TYPE_SINGLE ELSE ( -- d addr cnt ) 1 = swap \ if final character is '.' then double c@ ascii . = AND IF r@ \ check flag to see if '-' sign used IF dnegate THEN NUM_TYPE_DOUBLE ELSE 2drop NUM_TYPE_BAD THEN THEN rdrop ; : (NUMBER?) ( $addr -- 0 | n 1 | d 2 , convert string to number ) count ((number?)) ; ' (number?) is number? \ hex \ 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) -1 hld +! hld @ c! ; : <# ( -- , setup conversion ) pad hld ! ; : #> ( d -- addr len , finish conversion ) 2drop hld @ pad over - ; : sign ( n -- , add '-' if negative ) 0< if ascii - hold then ; : # ( d -- d , convert one digit ) base @ mu/mod rot 9 over < IF 7 + THEN ascii 0 + hold ; : #s ( d -- d , convert remaining digits ) BEGIN # 2dup or 0= UNTIL ; : (UD.) ( ud -- c-addr cnt ) <# #s #> ; : UD. ( ud -- , print unsigned double number ) (ud.) type space ; : UD.R ( ud n -- ) >r (ud.) r> over - spaces type ; : (D.) ( d -- c-addr cnt ) tuck dabs <# #s rot sign #> ; : D. ( d -- ) (d.) type space ; : D.R ( d n -- , right justified ) >r (d.) r> over - spaces type ; : (U.) ( u -- c-addr cnt ) 0 (ud.) ; : U. ( u -- , print unsigned number ) 0 ud. ; : 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) (.) type space ; : .R ( n l -- , print right justified) >r (.) r> over - spaces type ;