Diff for /gforth/stuff.fs between versions 1.7 and 1.26

version 1.7, 1998/12/08 22:02:52 version 1.26, 2003/01/24 22:03:20
Line 1 Line 1
 \ miscelleneous words  \ miscelleneous words
   
 \ Copyright (C) 1996,1997,1998 Free Software Foundation, Inc.  \ Copyright (C) 1996,1997,1998,2000 Free Software Foundation, Inc.
   
 \ This file is part of Gforth.  \ This file is part of Gforth.
   
Line 16 Line 16
   
 \ You should have received a copy of the GNU General Public License  \ You should have received a copy of the GNU General Public License
 \ along with this program; if not, write to the Free Software  \ along with this program; if not, write to the Free Software
 \ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  \ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   
   require glocals.fs
   
 ' require alias needs ( ... "name" -- ... ) \ gforth  ' require alias needs ( ... "name" -- ... ) \ gforth
 \G an alias for @code{require}; exists on other systems (e.g., Win32Forth).  \G An alias for @code{require}; exists on other systems (e.g., Win32Forth).
 \ needs is an F-PC name. we will probably switch to 'needs' in the future  \ needs is an F-PC name. we will probably switch to 'needs' in the future
   
 \ a little more compiler security  \ a little more compiler security
Line 35  AUser CSP Line 37  AUser CSP
   
 \ DMIN and DMAX  \ DMIN and DMAX
   
 : dmin ( d1 d2 -- d ) \ double  : dmin ( d1 d2 -- d ) \ double d-min
     2over 2over d> IF  2swap  THEN 2drop ;      2over 2over d> IF  2swap  THEN 2drop ;
   
 : dmax ( d1 d2 -- d ) \ double  
   : dmax ( d1 d2 -- d ) \ double d-max
     2over 2over d< IF  2swap  THEN 2drop ;      2over 2over d< IF  2swap  THEN 2drop ;
   
 \ shell commands  \ shell commands
   
 0 Value $?  0 Value $? ( -- n ) \ gforth dollar-question
   \G @code{Value} -- the exit status returned by the most recently executed
 : system ( addr u -- ) \ gforth  \G @code{system} command.
   
   : system ( c-addr u -- ) \ gforth
   \G Pass the string specified by @var{c-addr u} to the host operating system
   \G for execution in a sub-shell.
     (system) throw TO $? ;      (system) throw TO $? ;
   
 : sh ( "..." -- ) \ gforth  : sh ( "..." -- ) \ gforth
   \G Parse a string and use @code{system} to pass it to the host
   \G operating system for execution in a sub-shell.
     '# parse cr system ;      '# parse cr system ;
   
   \ stuff
   
   : ]L ( compilation: n -- ; run-time: -- n ) \ gforth
       \G equivalent to @code{] literal}
       ] postpone literal ;
   
   [ifundef] in-dictionary?
   : in-dictionary? ( x -- f )
       forthstart dictionary-end within ;
   [endif]
   
   : in-return-stack? ( addr -- f )
       rp0 @ swap - [ forthstart 6 cells + ]L @ u< ;
   
   \ const-does>
   
   : compile-literals ( w*u u -- ; run-time: -- w*u ) recursive
       \ compile u literals, starting with the bottommost one
       ?dup-if
           swap >r 1- compile-literals
           r> POSTPONE literal
       endif ;
   
   : compile-fliterals ( r*u u -- ; run-time: -- w*u ) recursive
       \ compile u fliterals, starting with the bottommost one
       ?dup-if
           { F: r } 1- compile-fliterals
           r POSTPONE fliteral
       endif ;
   
   : (const-does>) ( w*uw r*ur uw ur target "name" -- )
       \ define a colon definition "name" containing w*uw r*ur as
       \ literals and a call to target.
       { uw ur target }
       header docol: cfa, \ start colon def without stack junk
       ur compile-fliterals uw compile-literals
       target compile, POSTPONE exit reveal ;
   
   : const-does> ( run-time: w*uw r*ur uw ur "name" -- )
       \G Defines @var{name} and returns.@sp 0
       \G @var{name} execution: pushes @var{w*uw r*ur}, then performs the
       \G code following the @code{const-does>}.
       here >r 0 POSTPONE literal
       POSTPONE (const-does>)
       POSTPONE ;
       noname : POSTPONE rdrop
       lastxt r> cell+ ! \ patch the literal
   ; immediate
   
   \ !! rewrite slurp-file using slurp-fid
   : slurp-file ( c-addr1 u1 -- c-addr2 u2 )
       \G @var{c-addr1 u1} is the filename, @var{c-addr2 u2} is the file's contents
       r/o bin open-file throw >r
       r@ file-size throw abort" file too large"
       dup allocate throw swap
       2dup r@ read-file throw over <> abort" could not read whole file"
       r> close-file throw ;
   
   : slurp-fid { fid -- addr u }
       \G @var{addr u} is the content of the file @var{fid}
       0 0 begin ( awhole uwhole )
           dup 1024 + dup >r extend-mem ( anew awhole uwhole R: unew )
           rot r@ fid read-file throw ( awhole uwhole uread R: unew )
           r> 2dup =
       while ( awhole uwhole uread unew )
           2drop
       repeat
       - + dup >r resize throw r> ;
   
   \ ]] ... [[
   
   : compile-literal ( n -- )
       postpone literal ;
   
   : [[ ( -- )
   \G switch from postpone state to compile state
       \ this is only a marker; it is never really interpreted
       compile-only-error ; immediate
   
   : postponer ( c-addr u -- )
       2dup find-name dup if ( c-addr u nt )
           nip nip name>comp
           2dup [comp'] [[ d= if
               2drop ['] compiler is parser
           else
               postpone,
           endif
       else
           drop
           2dup snumber? dup if
               0> IF
                   swap postpone literal postpone compile-literal
               THEN
               postpone Literal postpone compile-literal
               2drop
           ELSE
               drop no.extensions
           THEN
       then ;
   
   : ]] ( -- )
       \ switch into postpone state
       ['] postponer is parser state on ; immediate restrict
   
   \ f.rdp
   
   : move-right ( c-addr u1 u2 cfill -- )
       \ move string at c-addr u1 right by u2 chars (without exceeding
       \ the original bound); fill the gap with cfill
       >r dup >r rot dup >r ( u1 u2 c-addr R: cfill u2 c-addr )
       dup 2swap /string cmove>
       r> r> r> fill ;
   
   : f>buf-rdp { f: rf c-addr ur nd up -- } \ gforth
   \G Convert @i{rf} into a string at @i{c-addr ur}.  The conversion
   \G rules and the meanings of @i{ur nd up} are the same as for
   \G @code{f.rdp}.
       rf c-addr ur represent if { nexp fsign }
           nd nexp + up >=
           ur nd - 1- dup { beforep } fsign + nexp 0 max >= and if
               \ fixed-point notation
               c-addr ur beforep nexp - dup { befored } '0 move-right
               c-addr beforep 1- befored min dup { beforez } 0 max bl fill
               fsign if
                   '- c-addr beforez 1- 0 max + c!
               endif
               c-addr ur beforep /string 1 '. move-right
           else \ exponential notation
               c-addr ur 1 /string 1 '. move-right
               fsign if
                   c-addr ur 1 '- move-right
               endif
               nexp 1- s>d tuck dabs <<# #s rot sign 'E hold #> { explen }
               explen 1+ fsign - ur > if \ exponent too large
                   drop c-addr ur '* fill
               else
                   c-addr ur + 0 explen negate /string move
               endif
               #>>
           endif
       else \ inf or nan
           if \ negative
               c-addr ur 1 '- move-right
           endif
           drop
           \ !! align in some way?
       endif ;
   
   : f>str-rdp ( rf ur +nd up -- c-addr ur ) \ gforth
   \G Convert @i{rf} into a string at @i{c-addr ur}.  The conversion
   \G rules and the meanings of @i{ur +nd up} are the same as for
   \G @code{f.rdp}.  The result in in the pictured numeric output buffer
   \G and will be destroyed by anything destroying that buffer.
       rot holdptr @ 1- 0 rot negate /string ( rf +nd up c-addr ur )
       over holdbuf u< -&17 and throw
       2tuck 2>r f>buf-rdp 2r> ;
   
   : f.rdp ( rf ur +nd up -- ) \ gforth
   \G Print float @i{rf} formatted.  The total width of the output is
   \G @i{nr}, the number of digits after the decimal point is @i{+nd},
   \G the minimum number of significant digits for fixed-point notation
   \G is @i{up}.  @code{Set-precision} has no effect on @code{f.rdp}.
   \G Fixed-point notation is used if the number of siginicant digits
   \G would be larger than @i{up} and if the number of digits before the
   \G decimal point would fit.  If fixed-point notation is not used,
   \G exponential notation is used, and if that does not fit, asterisks
   \G are printed.  We recommend using @i{ur}>=7 to avoid the risk of
   \G numbers not fitting at all.  We recommend @i{ur}>=@i{up}+5 to avoid
   \G cases where @code{f.rdp} switches to exponential notation because
   \G fixed-point notation would have too few significant digits, yet
   \G exponential notation offers fewer significant digits.  We recomment
   \G @i{ur}>=@i{nd}+2, if you want to have fixed-point notation for some
   \G numbers.  Currently, trailing digits are cut off.
       f>str-rdp type ;
   
   0 [if]
   : testx ( rf ur nd up -- )
       '| emit f.rdp ;
   
   : test ( -- )
       -0.123456789123456789e-20
       40 0 ?do
           cr
           fdup 7 3 1 testx
           fdup 7 3 4 testx
           fdup 7 3 0 testx
           fdup 7 7 1 testx
           fdup 7 5 1 testx
           fdup 7 0 2 testx
           fdup 5 2 1 testx
           fdup 4 2 1 testx
           fdup 18 8 5 testx
           '| emit
           10e f*
       loop ;
   [then]

Removed from v.1.7  
changed lines
  Added in v.1.26


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>