Diff for /gforth/prim between versions 1.46 and 1.51

version 1.46, 2000/05/31 14:37:40 version 1.51, 2000/08/08 12:37:05
Line 26 Line 26
 \   \ 
 \ This file contains primitive specifications in the following format:  \ This file contains primitive specifications in the following format:
 \   \ 
 \ forth name    stack effect    category        [pronunciation]  \ forth name    ( stack effect )        category        [pronunciation]
 \ [""glossary entry""]  \ [""glossary entry""]
 \ C code  \ C code
 \ [:  \ [:
 \ Forth code]  \ Forth code]
 \   \ 
 \ prims2x is pedantic about tabs vs. blanks. The fields of the first  \ Note: Fields in brackets are optional.  Word specifications have to
 \ line of a primitive are separated by tabs, the stack items in a  \ be separated by at least one empty line
 \ stack effect by blanks.  
 \  \
 \ Both pronounciation and stack items (in the stack effect) must  \ Both pronounciation and stack items (in the stack effect) must
 \ conform to the C name syntax or the C compiler will complain.  \ conform to the C identifier syntax or the C compiler will complain.
 \   \ If you don't have a pronounciation field, the Forth name is used,
   \ and has to conform to the C identifier syntax.
 \   \ 
 \ These specifications are automatically translated into C-code for the  \ These specifications are automatically translated into C-code for the
 \ interpreter and into some other files. I hope that your C compiler has  \ interpreter and into some other files. I hope that your C compiler has
Line 103 Line 103
 undefine(`index')  undefine(`index')
 undefine(`shift')  undefine(`shift')
   
 noop    --              gforth  noop    ( -- )          gforth
 ;  ;
 :  :
  ;   ;
   
 lit     -- w            gforth  lit     ( -- w )                gforth
 w = (Cell)NEXT_INST;  w = (Cell)NEXT_INST;
 INC_IP(1);  INC_IP(1);
 :  :
  r> dup @ swap cell+ >r ;   r> dup @ swap cell+ >r ;
   
 execute         xt --           core  execute ( xt -- )               core
 ""Perform the semantics represented by the execution token, @i{xt}.""  ""Perform the semantics represented by the execution token, @i{xt}.""
 ip=IP;  ip=IP;
 IF_TOS(TOS = sp[0]);  IF_TOS(TOS = sp[0]);
 EXEC(xt);  EXEC(xt);
   
 perform         a_addr --       gforth  perform ( a_addr -- )   gforth
 ""Equivalent to @code{@ execute}.""  ""Equivalent to @code{@ execute}.""
 /* and pfe */  /* and pfe */
 ip=IP;  ip=IP;
Line 132  EXEC(*(Xt *)a_addr); Line 132  EXEC(*(Xt *)a_addr);
 \fhas? skipbranchprims 0= [IF]  \fhas? skipbranchprims 0= [IF]
 \+glocals  \+glocals
   
 branch-lp+!#    --      gforth  branch_lp_plus_store_number  branch-lp+!#    ( -- )  gforth  branch_lp_plus_store_number
 /* this will probably not be used */  /* this will probably not be used */
 branch_adjust_lp:  branch_adjust_lp:
 lp += (Cell)(IP[1]);  lp += (Cell)(IP[1]);
Line 140  goto branch; Line 140  goto branch;
   
 \+  \+
   
 branch  --              gforth  branch  ( -- )          gforth
 branch:  branch:
 SET_IP((Xt *)(((Cell)IP)+(Cell)NEXT_INST));  SET_IP((Xt *)(((Cell)IP)+(Cell)NEXT_INST));
 :  :
Line 168  else Line 168  else
 \+  \+
 )  )
   
 condbranch(?branch,f --         f83     question_branch,  condbranch(?branch,( f -- )             f83     question_branch,
 if (f==0) {  if (f==0) {
     IF_TOS(TOS = sp[0]);      IF_TOS(TOS = sp[0]);
 ,:  ,:
Line 183  if (f==0) { Line 183  if (f==0) {
   
 \+xconds  \+xconds
   
 ?dup-?branch    f -- f  new     question_dupe_question_branch  ?dup-?branch    ( f -- f )      new     question_dupe_question_branch
 ""The run-time procedure compiled by @code{?DUP-IF}.""  ""The run-time procedure compiled by @code{?DUP-IF}.""
 if (f==0) {  if (f==0) {
   sp++;    sp++;
Line 194  if (f==0) { Line 194  if (f==0) {
 else  else
   INC_IP(1);    INC_IP(1);
   
 ?dup-0=-?branch f --    new     question_dupe_zero_equals_question_branch  ?dup-0=-?branch ( f -- )        new     question_dupe_zero_equals_question_branch
 ""The run-time procedure compiled by @code{?DUP-0=-IF}.""  ""The run-time procedure compiled by @code{?DUP-0=-IF}.""
 /* the approach taken here of declaring the word as having the stack  /* the approach taken here of declaring the word as having the stack
 effect ( f -- ) and correcting for it in the branch-taken case costs a  effect ( f -- ) and correcting for it in the branch-taken case costs a
Line 212  else Line 212  else
 \f[THEN]  \f[THEN]
 \fhas? skiploopprims 0= [IF]  \fhas? skiploopprims 0= [IF]
   
 condbranch((next),--            cmFORTH paren_next,  condbranch((next),( -- )                cmFORTH paren_next,
 if ((*rp)--) {  if ((*rp)--) {
 ,:  ,:
  r> r> dup 1- >r   r> r> dup 1- >r
  IF dup @ + >r ELSE cell+ >r THEN ;)   IF dup @ + >r ELSE cell+ >r THEN ;)
   
 condbranch((loop),--            gforth  paren_loop,  condbranch((loop),( -- )                gforth  paren_loop,
 Cell index = *rp+1;  Cell index = *rp+1;
 Cell limit = rp[1];  Cell limit = rp[1];
 if (index != limit) {  if (index != limit) {
Line 228  if (index != limit) { Line 228  if (index != limit) {
  IF >r 1- >r cell+ >r   IF >r 1- >r cell+ >r
  ELSE >r >r dup @ + >r THEN ;)   ELSE >r >r dup @ + >r THEN ;)
   
 condbranch((+loop),n --         gforth  paren_plus_loop,  condbranch((+loop),( n -- )             gforth  paren_plus_loop,
 /* !! check this thoroughly */  /* !! check this thoroughly */
 Cell index = *rp;  Cell index = *rp;
 /* sign bit manipulation and test: (x^y)<0 is equivalent to (x<0) != (y<0) */  /* sign bit manipulation and test: (x^y)<0 is equivalent to (x<0) != (y<0) */
Line 252  if ((olddiff^(olddiff+n))>=0   /* the li Line 252  if ((olddiff^(olddiff+n))>=0   /* the li
   
 \+xconds  \+xconds
   
 condbranch((-loop),u --         gforth  paren_minus_loop,  condbranch((-loop),( u -- )             gforth  paren_minus_loop,
 /* !! check this thoroughly */  /* !! check this thoroughly */
 Cell index = *rp;  Cell index = *rp;
 UCell olddiff = index-rp[1];  UCell olddiff = index-rp[1];
Line 265  if (olddiff>u) { Line 265  if (olddiff>u) {
     IF_TOS(TOS = sp[0]);      IF_TOS(TOS = sp[0]);
 ,)  ,)
   
 condbranch((s+loop),n --                gforth  paren_symmetric_plus_loop,  condbranch((s+loop),( n -- )            gforth  paren_symmetric_plus_loop,
 ""The run-time procedure compiled by S+LOOP. It loops until the index  ""The run-time procedure compiled by S+LOOP. It loops until the index
 crosses the boundary between limit and limit-sign(n). I.e. a symmetric  crosses the boundary between limit and limit-sign(n). I.e. a symmetric
 version of (+LOOP).""  version of (+LOOP).""
Line 288  if (diff>=0 || newdiff<0) { Line 288  if (diff>=0 || newdiff<0) {
   
 \+  \+
   
 unloop          --      core  unloop  ( -- )  core
 rp += 2;  rp += 2;
 :  :
  r> rdrop rdrop >r ;   r> rdrop rdrop >r ;
   
 (for)   ncount --               cmFORTH         paren_for  (for)   ( ncount -- )           cmFORTH         paren_for
 /* or (for) = >r -- collides with unloop! */  /* or (for) = >r -- collides with unloop! */
 *--rp = 0;  *--rp = 0;
 *--rp = ncount;  *--rp = ncount;
 :  :
  r> swap 0 >r >r >r ;   r> swap 0 >r >r >r ;
   
 (do)    nlimit nstart --                gforth          paren_do  (do)    ( nlimit nstart -- )            gforth          paren_do
 /* or do it in high-level? 0.09/0.23% */  /* or do it in high-level? 0.09/0.23% */
 *--rp = nlimit;  *--rp = nlimit;
 *--rp = nstart;  *--rp = nstart;
 :  :
  r> swap rot >r >r >r ;   r> swap rot >r >r >r ;
   
 (?do)   nlimit nstart --        gforth  paren_question_do  (?do)   ( nlimit nstart -- )    gforth  paren_question_do
 *--rp = nlimit;  *--rp = nlimit;
 *--rp = nstart;  *--rp = nstart;
 if (nstart == nlimit) {  if (nstart == nlimit) {
Line 327  else { Line 327  else {
   
 \+xconds  \+xconds
   
 (+do)   nlimit nstart --        gforth  paren_plus_do  (+do)   ( nlimit nstart -- )    gforth  paren_plus_do
 *--rp = nlimit;  *--rp = nlimit;
 *--rp = nstart;  *--rp = nstart;
 if (nstart >= nlimit) {  if (nstart >= nlimit) {
Line 347  else { Line 347  else {
      cell+       cell+
  THEN  >r ;   THEN  >r ;
   
 (u+do)  ulimit ustart --        gforth  paren_u_plus_do  (u+do)  ( ulimit ustart -- )    gforth  paren_u_plus_do
 *--rp = ulimit;  *--rp = ulimit;
 *--rp = ustart;  *--rp = ustart;
 if (ustart >= ulimit) {  if (ustart >= ulimit) {
Line 367  else { Line 367  else {
      cell+       cell+
  THEN  >r ;   THEN  >r ;
   
 (-do)   nlimit nstart --        gforth  paren_minus_do  (-do)   ( nlimit nstart -- )    gforth  paren_minus_do
 *--rp = nlimit;  *--rp = nlimit;
 *--rp = nstart;  *--rp = nstart;
 if (nstart <= nlimit) {  if (nstart <= nlimit) {
Line 387  else { Line 387  else {
      cell+       cell+
  THEN  >r ;   THEN  >r ;
   
 (u-do)  ulimit ustart --        gforth  paren_u_minus_do  (u-do)  ( ulimit ustart -- )    gforth  paren_u_minus_do
 *--rp = ulimit;  *--rp = ulimit;
 *--rp = ustart;  *--rp = ustart;
 if (ustart <= ulimit) {  if (ustart <= ulimit) {
Line 412  else { Line 412  else {
 \ don't make any assumptions where the return stack is!!  \ don't make any assumptions where the return stack is!!
 \ implement this in machine code if it should run quickly!  \ implement this in machine code if it should run quickly!
   
 i       -- n            core  i       ( -- n )                core
 n = *rp;  n = *rp;
 :  :
 \ rp@ cell+ @ ;  \ rp@ cell+ @ ;
   r> r> tuck >r >r ;    r> r> tuck >r >r ;
   
 i'      -- w            gforth          i_tick  i'      ( -- w )                gforth          i_tick
 ""loop end value""  ""loop end value""
 w = rp[1];  w = rp[1];
 :  :
Line 426  w = rp[1]; Line 426  w = rp[1];
   r> r> r> dup itmp ! >r >r >r itmp @ ;    r> r> r> dup itmp ! >r >r >r itmp @ ;
 variable itmp  variable itmp
   
 j       -- n            core  j       ( -- n )                core
 n = rp[2];  n = rp[2];
 :  :
 \ rp@ cell+ cell+ cell+ @ ;  \ rp@ cell+ cell+ cell+ @ ;
   r> r> r> r> dup itmp ! >r >r >r >r itmp @ ;    r> r> r> r> dup itmp ! >r >r >r >r itmp @ ;
 [IFUNDEF] itmp variable itmp [THEN]  [IFUNDEF] itmp variable itmp [THEN]
   
 k       -- n            gforth  k       ( -- n )                gforth
 n = rp[4];  n = rp[4];
 :  :
 \ rp@ [ 5 cells ] Literal + @ ;  \ rp@ [ 5 cells ] Literal + @ ;
Line 444  n = rp[4]; Line 444  n = rp[4];
   
 \ digit is high-level: 0/0%  \ digit is high-level: 0/0%
   
 move    c_from c_to ucount --           core  move    ( c_from c_to ucount -- )               core
 ""Copy the contents of @i{ucount} address units at @i{c-from} to  ""Copy the contents of @i{ucount} address units at @i{c-from} to
 @i{c-to}. @code{move} works correctly even if the two areas overlap.""  @i{c-to}. @code{move} works correctly even if the two areas overlap.""
 memmove(c_to,c_from,ucount);  memmove(c_to,c_from,ucount);
Line 452  memmove(c_to,c_from,ucount); Line 452  memmove(c_to,c_from,ucount);
 :  :
  >r 2dup u< IF r> cmove> ELSE r> cmove THEN ;   >r 2dup u< IF r> cmove> ELSE r> cmove THEN ;
   
 cmove   c_from c_to u --        string  c_move  cmove   ( c_from c_to u -- )    string  c_move
 ""Copy the contents of @i{ucount} characters from data space at  ""Copy the contents of @i{ucount} characters from data space at
 @i{c-from} to @i{c-to}. The copy proceeds @code{char}-by-@code{char}  @i{c-from} to @i{c-to}. The copy proceeds @code{char}-by-@code{char}
 from low address to high address; i.e., for overlapping areas it is  from low address to high address; i.e., for overlapping areas it is
Line 462  while (u-- > 0) Line 462  while (u-- > 0)
 :  :
  bounds ?DO  dup c@ I c! 1+  LOOP  drop ;   bounds ?DO  dup c@ I c! 1+  LOOP  drop ;
   
 cmove>  c_from c_to u --        string  c_move_up  cmove>  ( c_from c_to u -- )    string  c_move_up
 ""Copy the contents of @i{ucount} characters from data space at  ""Copy the contents of @i{ucount} characters from data space at
 @i{c-from} to @i{c-to}. The copy proceeds @code{char}-by-@code{char}  @i{c-from} to @i{c-to}. The copy proceeds @code{char}-by-@code{char}
 from high address to low address; i.e., for overlapping areas it is  from high address to low address; i.e., for overlapping areas it is
Line 474  while (u-- > 0) Line 474  while (u-- > 0)
  rot over + -rot bounds swap 1-   rot over + -rot bounds swap 1-
  DO  1- dup c@ I c!  -1 +LOOP  drop ;   DO  1- dup c@ I c!  -1 +LOOP  drop ;
   
 fill    c_addr u c --   core  fill    ( c_addr u c -- )       core
 "" If @i{u}>0, store character @i{c} in each of @i{u} consecutive  "" If @i{u}>0, store character @i{c} in each of @i{u} consecutive
 @code{char} addresses in memory, starting at address @i{c-addr}.""  @code{char} addresses in memory, starting at address @i{c-addr}.""
 memset(c_addr,c,u);  memset(c_addr,c,u);
Line 482  memset(c_addr,c,u); Line 482  memset(c_addr,c,u);
  -rot bounds   -rot bounds
  ?DO  dup I c!  LOOP  drop ;   ?DO  dup I c!  LOOP  drop ;
   
 compare         c_addr1 u1 c_addr2 u2 -- n      string  compare ( c_addr1 u1 c_addr2 u2 -- n )  string
 ""Compare two strings lexicographically. If they are equal, @i{n} is 0; if  ""Compare two strings lexicographically. If they are equal, @i{n} is 0; if
 the first string is smaller, @i{n} is -1; if the first string is larger, @i{n}  the first string is smaller, @i{n} is -1; if the first string is larger, @i{n}
 is 1. Currently this is based on the machine's character  is 1. Currently this is based on the machine's character
Line 502  else if (n>0) Line 502  else if (n>0)
 : sgn ( n -- -1/0/1 )  : sgn ( n -- -1/0/1 )
  dup 0= IF EXIT THEN  0< 2* 1+ ;   dup 0= IF EXIT THEN  0< 2* 1+ ;
   
 -text           c_addr1 u c_addr2 -- n  new     dash_text  -text   ( c_addr1 u c_addr2 -- n )      new     dash_text
 n = memcmp(c_addr1, c_addr2, u);  n = memcmp(c_addr1, c_addr2, u);
 if (n<0)  if (n<0)
   n = -1;    n = -1;
Line 511  else if (n>0) Line 511  else if (n>0)
 :  :
  swap bounds   swap bounds
  ?DO  dup c@ I c@ = WHILE  1+  LOOP  drop 0   ?DO  dup c@ I c@ = WHILE  1+  LOOP  drop 0
  ELSE  c@ I c@ - unloop  THEN  -text-flag ;   ELSE  c@ I c@ - unloop  THEN  sgn ;
 : sgn ( n -- -1/0/1 )  : sgn ( n -- -1/0/1 )
  dup 0= IF EXIT THEN  0< 2* 1+ ;   dup 0= IF EXIT THEN  0< 2* 1+ ;
   
 toupper c1 -- c2        gforth  toupper ( c1 -- c2 )    gforth
 ""If @i{c1} is a lower-case character (in the current locale), @i{c2}  ""If @i{c1} is a lower-case character (in the current locale), @i{c2}
 is the equivalent upper-case character. All other characters are unchanged.""  is the equivalent upper-case character. All other characters are unchanged.""
 c2 = toupper(c1);  c2 = toupper(c1);
 :  :
  dup [char] a - [ char z char a - 1 + ] Literal u<  bl and - ;   dup [char] a - [ char z char a - 1 + ] Literal u<  bl and - ;
   
 capscomp        c_addr1 u c_addr2 -- n  new  capscomp        ( c_addr1 u c_addr2 -- n )      new
 n = memcasecmp(c_addr1, c_addr2, u); /* !! use something that works in all locales */  n = memcasecmp(c_addr1, c_addr2, u); /* !! use something that works in all locales */
 if (n<0)  if (n<0)
   n = -1;    n = -1;
Line 533  else if (n>0) Line 533  else if (n>0)
  ?DO  dup c@ I c@ <>   ?DO  dup c@ I c@ <>
      IF  dup c@ toupper I c@ toupper =       IF  dup c@ toupper I c@ toupper =
      ELSE  true  THEN  WHILE  1+  LOOP  drop 0       ELSE  true  THEN  WHILE  1+  LOOP  drop 0
  ELSE  c@ toupper I c@ toupper - unloop  THEN  -text-flag ;   ELSE  c@ toupper I c@ toupper - unloop  THEN  sgn ;
   
 -trailing       c_addr u1 -- c_addr u2          string  dash_trailing  -trailing       ( c_addr u1 -- c_addr u2 )              string  dash_trailing
 ""Adjust the string specified by @i{c-addr, u1} to remove all trailing  ""Adjust the string specified by @i{c-addr, u1} to remove all trailing
 spaces. @i{u2} is the length of the modified string.""  spaces. @i{u2} is the length of the modified string.""
 u2 = u1;  u2 = u1;
Line 545  while (u2>0 && c_addr[u2-1] == ' ') Line 545  while (u2>0 && c_addr[u2-1] == ' ')
  BEGIN  1- 2dup + c@ bl =  WHILE   BEGIN  1- 2dup + c@ bl =  WHILE
         dup  0= UNTIL  ELSE  1+  THEN ;          dup  0= UNTIL  ELSE  1+  THEN ;
   
 /string         c_addr1 u1 n -- c_addr2 u2      string  slash_string  /string ( c_addr1 u1 n -- c_addr2 u2 )  string  slash_string
 ""Adjust the string specified by @i{c-addr1, u1} to remove @i{n}  ""Adjust the string specified by @i{c-addr1, u1} to remove @i{n}
 characters from the start of the string.""  characters from the start of the string.""
 c_addr2 = c_addr1+n;  c_addr2 = c_addr1+n;
Line 553  u2 = u1-n; Line 553  u2 = u1-n;
 :  :
  tuck - >r + r> dup 0< IF  - 0  THEN ;   tuck - >r + r> dup 0< IF  - 0  THEN ;
   
 +       n1 n2 -- n              core    plus  +       ( n1 n2 -- n )          core    plus
 n = n1+n2;  n = n1+n2;
   
 \ PFE-0.9.14 has it differently, but the next release will have it as follows  \ PFE-0.9.14 has it differently, but the next release will have it as follows
 under+  n1 n2 n3 -- n n2        gforth  under_plus  under+  ( n1 n2 n3 -- n n2 )    gforth  under_plus
 ""add @i{n3} to @i{n1} (giving @i{n})""  ""add @i{n3} to @i{n1} (giving @i{n})""
 n = n1+n3;  n = n1+n3;
 :  :
  rot + swap ;   rot + swap ;
   
 -       n1 n2 -- n              core    minus  -       ( n1 n2 -- n )          core    minus
 n = n1-n2;  n = n1-n2;
 :  :
  negate + ;   negate + ;
   
 negate  n1 -- n2                core  negate  ( n1 -- n2 )            core
 /* use minus as alias */  /* use minus as alias */
 n2 = -n1;  n2 = -n1;
 :  :
  invert 1+ ;   invert 1+ ;
   
 1+      n1 -- n2                core            one_plus  1+      ( n1 -- n2 )            core            one_plus
 n2 = n1+1;  n2 = n1+1;
 :  :
  1 + ;   1 + ;
   
 1-      n1 -- n2                core            one_minus  1-      ( n1 -- n2 )            core            one_minus
 n2 = n1-1;  n2 = n1-1;
 :  :
  1 - ;   1 - ;
   
 max     n1 n2 -- n      core  max     ( n1 n2 -- n )  core
 if (n1<n2)  if (n1<n2)
   n = n2;    n = n2;
 else  else
Line 592  else Line 592  else
 :  :
  2dup < IF swap THEN drop ;   2dup < IF swap THEN drop ;
   
 min     n1 n2 -- n      core  min     ( n1 n2 -- n )  core
 if (n1<n2)  if (n1<n2)
   n = n1;    n = n1;
 else  else
Line 600  else Line 600  else
 :  :
  2dup > IF swap THEN drop ;   2dup > IF swap THEN drop ;
   
 abs     n1 -- n2        core  abs     ( n1 -- n2 )    core
 if (n1<0)  if (n1<0)
   n2 = -n1;    n2 = -n1;
 else  else
Line 608  else Line 608  else
 :  :
  dup 0< IF negate THEN ;   dup 0< IF negate THEN ;
   
 *       n1 n2 -- n              core    star  *       ( n1 n2 -- n )          core    star
 n = n1*n2;  n = n1*n2;
 :  :
  um* drop ;   um* drop ;
   
 /       n1 n2 -- n              core    slash  /       ( n1 n2 -- n )          core    slash
 n = n1/n2;  n = n1/n2;
 :  :
  /mod nip ;   /mod nip ;
   
 mod     n1 n2 -- n              core  mod     ( n1 n2 -- n )          core
 n = n1%n2;  n = n1%n2;
 :  :
  /mod drop ;   /mod drop ;
   
 /mod    n1 n2 -- n3 n4          core            slash_mod  /mod    ( n1 n2 -- n3 n4 )              core            slash_mod
 n4 = n1/n2;  n4 = n1/n2;
 n3 = n1%n2; /* !! is this correct? look into C standard! */  n3 = n1%n2; /* !! is this correct? look into C standard! */
 :  :
  >r s>d r> fm/mod ;   >r s>d r> fm/mod ;
   
 2*      n1 -- n2                core            two_star  2*      ( n1 -- n2 )            core            two_star
 n2 = 2*n1;  n2 = 2*n1;
 :  :
  dup + ;   dup + ;
   
 2/      n1 -- n2                core            two_slash  2/      ( n1 -- n2 )            core            two_slash
 /* !! is this still correct? */  /* !! is this still correct? */
 n2 = n1>>1;  n2 = n1>>1;
 :  :
Line 644  n2 = n1>>1; Line 644  n2 = n1>>1;
      IF 1 ELSE 0 THEN or r> swap       IF 1 ELSE 0 THEN or r> swap
  LOOP nip ;   LOOP nip ;
   
 fm/mod  d1 n1 -- n2 n3          core            f_m_slash_mod  fm/mod  ( d1 n1 -- n2 n3 )              core            f_m_slash_mod
 ""Floored division: @i{d1} = @i{n3}*@i{n1}+@i{n2}, @i{n1}>@i{n2}>=0 or 0>=@i{n2}>@i{n1}.""  ""Floored division: @i{d1} = @i{n3}*@i{n1}+@i{n2}, @i{n1}>@i{n2}>=0 or 0>=@i{n2}>@i{n1}.""
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 DCell r = fmdiv(d1,n1);  DCell r = fmdiv(d1,n1);
Line 666  if (1%-3>0 && (d1<0) != (n1<0) && n2!=0) Line 666  if (1%-3>0 && (d1<0) != (n1<0) && n2!=0)
  um/mod   um/mod
  r> 0< IF  swap negate swap  THEN ;   r> 0< IF  swap negate swap  THEN ;
   
 sm/rem  d1 n1 -- n2 n3          core            s_m_slash_rem  sm/rem  ( d1 n1 -- n2 n3 )              core            s_m_slash_rem
 ""Symmetric division: @i{d1} = @i{n3}*@i{n1}+@i{n2}, sign(@i{n2})=sign(@i{d1}) or 0.""  ""Symmetric division: @i{d1} = @i{n3}*@i{n1}+@i{n2}, sign(@i{n2})=sign(@i{d1}) or 0.""
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 DCell r = smdiv(d1,n1);  DCell r = smdiv(d1,n1);
Line 688  if (1%-3<0 && (d1<0) != (n1<0) && n2!=0) Line 688  if (1%-3<0 && (d1<0) != (n1<0) && n2!=0)
  r> r@ xor 0< IF       negate       THEN   r> r@ xor 0< IF       negate       THEN
  r>        0< IF  swap negate swap  THEN ;   r>        0< IF  swap negate swap  THEN ;
   
 m*      n1 n2 -- d              core    m_star  m*      ( n1 n2 -- d )          core    m_star
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 d = mmul(n1,n2);  d = mmul(n1,n2);
 #else  #else
Line 699  d = (DCell)n1 * (DCell)n2; Line 699  d = (DCell)n1 * (DCell)n2;
  2dup swap 0< and >r   2dup swap 0< and >r
  um* r> - r> - ;   um* r> - r> - ;
   
 um*     u1 u2 -- ud             core    u_m_star  um*     ( u1 u2 -- ud )         core    u_m_star
 /* use u* as alias */  /* use u* as alias */
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 ud = ummul(u1,u2);  ud = ummul(u1,u2);
Line 716  ud = (UDCell)u1 * (UDCell)u2; Line 716  ud = (UDCell)u1 * (UDCell)u2;
    over MINI     over MINI
    and >r >r 2dup d+ swap r> + swap r> ;     and >r >r 2dup d+ swap r> + swap r> ;
   
 um/mod  ud u1 -- u2 u3          core    u_m_slash_mod  um/mod  ( ud u1 -- u2 u3 )              core    u_m_slash_mod
 ""ud=u3*u1+u2, u1>u2>=0""  ""ud=u3*u1+u2, u1>u2>=0""
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 UDCell r = umdiv(ud,u1);  UDCell r = umdiv(ud,u1);
Line 736  u2 = ud%u1; Line 736  u2 = ud%u1;
    over MINI     over MINI
    and >r >r 2dup d+ swap r> + swap r> ;     and >r >r 2dup d+ swap r> + swap r> ;
   
 m+      d1 n -- d2              double          m_plus  m+      ( d1 n -- d2 )          double          m_plus
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 d2.lo = d1.lo+n;  d2.lo = d1.lo+n;
 d2.hi = d1.hi - (n<0) + (d2.lo<d1.lo);  d2.hi = d1.hi - (n<0) + (d2.lo<d1.lo);
Line 746  d2 = d1+n; Line 746  d2 = d1+n;
 :  :
  s>d d+ ;   s>d d+ ;
   
 d+      d1 d2 -- d              double  d_plus  d+      ( d1 d2 -- d )          double  d_plus
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 d.lo = d1.lo+d2.lo;  d.lo = d1.lo+d2.lo;
 d.hi = d1.hi + d2.hi + (d.lo<d1.lo);  d.hi = d1.hi + d2.hi + (d.lo<d1.lo);
Line 756  d = d1+d2; Line 756  d = d1+d2;
 :  :
  rot + >r tuck + swap over u> r> swap - ;   rot + >r tuck + swap over u> r> swap - ;
   
 d-      d1 d2 -- d              double          d_minus  d-      ( d1 d2 -- d )          double          d_minus
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 d.lo = d1.lo - d2.lo;  d.lo = d1.lo - d2.lo;
 d.hi = d1.hi-d2.hi-(d1.lo<d2.lo);  d.hi = d1.hi-d2.hi-(d1.lo<d2.lo);
Line 766  d = d1-d2; Line 766  d = d1-d2;
 :  :
  dnegate d+ ;   dnegate d+ ;
   
 dnegate d1 -- d2                double  d_negate  dnegate ( d1 -- d2 )            double  d_negate
 /* use dminus as alias */  /* use dminus as alias */
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 d2 = dnegate(d1);  d2 = dnegate(d1);
Line 776  d2 = -d1; Line 776  d2 = -d1;
 :  :
  invert swap negate tuck 0= - ;   invert swap negate tuck 0= - ;
   
 d2*     d1 -- d2                double          d_two_star  d2*     ( d1 -- d2 )            double          d_two_star
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 d2.lo = d1.lo<<1;  d2.lo = d1.lo<<1;
 d2.hi = (d1.hi<<1) | (d1.lo>>(CELL_BITS-1));  d2.hi = (d1.hi<<1) | (d1.lo>>(CELL_BITS-1));
Line 786  d2 = 2*d1; Line 786  d2 = 2*d1;
 :  :
  2dup d+ ;   2dup d+ ;
   
 d2/     d1 -- d2                double          d_two_slash  d2/     ( d1 -- d2 )            double          d_two_slash
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 d2.hi = d1.hi>>1;  d2.hi = d1.hi>>1;
 d2.lo= (d1.lo>>1) | (d1.hi<<(CELL_BITS-1));  d2.lo= (d1.lo>>1) | (d1.hi<<(CELL_BITS-1));
Line 797  d2 = d1>>1; Line 797  d2 = d1>>1;
  dup 1 and >r 2/ swap 2/ [ 1 8 cells 1- lshift 1- ] Literal and   dup 1 and >r 2/ swap 2/ [ 1 8 cells 1- lshift 1- ] Literal and
  r> IF  [ 1 8 cells 1- lshift ] Literal + THEN  swap ;   r> IF  [ 1 8 cells 1- lshift ] Literal + THEN  swap ;
   
 and     w1 w2 -- w              core  and     ( w1 w2 -- w )          core
 w = w1&w2;  w = w1&w2;
   
 or      w1 w2 -- w              core  or      ( w1 w2 -- w )          core
 w = w1|w2;  w = w1|w2;
 :  :
  invert swap invert and invert ;   invert swap invert and invert ;
   
 xor     w1 w2 -- w              core    x_or  xor     ( w1 w2 -- w )          core    x_or
 w = w1^w2;  w = w1^w2;
   
 invert  w1 -- w2                core  invert  ( w1 -- w2 )            core
 w2 = ~w1;  w2 = ~w1;
 :  :
  MAXU xor ;   MAXU xor ;
   
 rshift  u1 n -- u2              core    r_shift  rshift  ( u1 n -- u2 )          core    r_shift
   u2 = u1>>n;    u2 = u1>>n;
 :  :
     0 ?DO 2/ MAXI and LOOP ;      0 ?DO 2/ MAXI and LOOP ;
   
 lshift  u1 n -- u2              core    l_shift  lshift  ( u1 n -- u2 )          core    l_shift
   u2 = u1<<n;    u2 = u1<<n;
 :  :
     0 ?DO 2* LOOP ;      0 ?DO 2* LOOP ;
   
 \ comparisons(prefix, args, prefix, arg1, arg2, wordsets...)  \ comparisons(prefix, args, prefix, arg1, arg2, wordsets...)
 define(comparisons,  define(comparisons,
 $1=     $2 -- f         $6      $3equals  $1=     ( $2 -- f )             $6      $3equals
 f = FLAG($4==$5);  f = FLAG($4==$5);
 :  :
     [ char $1x char 0 = [IF]      [ char $1x char 0 = [IF]
Line 834  f = FLAG($4==$5); Line 834  f = FLAG($4==$5);
         ] xor 0= [          ] xor 0= [
     [THEN] ] ;      [THEN] ] ;
   
 $1<>    $2 -- f         $7      $3not_equals  $1<>    ( $2 -- f )             $7      $3not_equals
 f = FLAG($4!=$5);  f = FLAG($4!=$5);
 :  :
     [ char $1x char 0 = [IF]      [ char $1x char 0 = [IF]
Line 843  f = FLAG($4!=$5); Line 843  f = FLAG($4!=$5);
         ] xor 0<> [          ] xor 0<> [
     [THEN] ] ;      [THEN] ] ;
   
 $1<     $2 -- f         $8      $3less_than  $1<     ( $2 -- f )             $8      $3less_than
 f = FLAG($4<$5);  f = FLAG($4<$5);
 :  :
     [ char $1x char 0 = [IF]      [ char $1x char 0 = [IF]
Line 855  f = FLAG($4<$5); Line 855  f = FLAG($4<$5);
         [THEN]          [THEN]
     [THEN] ] ;      [THEN] ] ;
   
 $1>     $2 -- f         $9      $3greater_than  $1>     ( $2 -- f )             $9      $3greater_than
 f = FLAG($4>$5);  f = FLAG($4>$5);
 :  :
     [ char $1x char 0 = [IF] ] negate [ [ELSE] ] swap [ [THEN] ]      [ char $1x char 0 = [IF] ] negate [ [ELSE] ] swap [ [THEN] ]
     $1< ;      $1< ;
   
 $1<=    $2 -- f         gforth  $3less_or_equal  $1<=    ( $2 -- f )             gforth  $3less_or_equal
 f = FLAG($4<=$5);  f = FLAG($4<=$5);
 :  :
     $1> 0= ;      $1> 0= ;
   
 $1>=    $2 -- f         gforth  $3greater_or_equal  $1>=    ( $2 -- f )             gforth  $3greater_or_equal
 f = FLAG($4>=$5);  f = FLAG($4>=$5);
 :  :
     [ char $1x char 0 = [IF] ] negate [ [ELSE] ] swap [ [THEN] ]      [ char $1x char 0 = [IF] ] negate [ [ELSE] ] swap [ [THEN] ]
Line 880  comparisons(u, u1 u2, u_, u1, u2, gforth Line 880  comparisons(u, u1 u2, u_, u1, u2, gforth
   
 \ dcomparisons(prefix, args, prefix, arg1, arg2, wordsets...)  \ dcomparisons(prefix, args, prefix, arg1, arg2, wordsets...)
 define(dcomparisons,  define(dcomparisons,
 $1=     $2 -- f         $6      $3equals  $1=     ( $2 -- f )             $6      $3equals
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 f = FLAG($4.lo==$5.lo && $4.hi==$5.hi);  f = FLAG($4.lo==$5.lo && $4.hi==$5.hi);
 #else  #else
 f = FLAG($4==$5);  f = FLAG($4==$5);
 #endif  #endif
   
 $1<>    $2 -- f         $7      $3not_equals  $1<>    ( $2 -- f )             $7      $3not_equals
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 f = FLAG($4.lo!=$5.lo || $4.hi!=$5.hi);  f = FLAG($4.lo!=$5.lo || $4.hi!=$5.hi);
 #else  #else
 f = FLAG($4!=$5);  f = FLAG($4!=$5);
 #endif  #endif
   
 $1<     $2 -- f         $8      $3less_than  $1<     ( $2 -- f )             $8      $3less_than
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 f = FLAG($4.hi==$5.hi ? $4.lo<$5.lo : $4.hi<$5.hi);  f = FLAG($4.hi==$5.hi ? $4.lo<$5.lo : $4.hi<$5.hi);
 #else  #else
 f = FLAG($4<$5);  f = FLAG($4<$5);
 #endif  #endif
   
 $1>     $2 -- f         $9      $3greater_than  $1>     ( $2 -- f )             $9      $3greater_than
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 f = FLAG($4.hi==$5.hi ? $4.lo>$5.lo : $4.hi>$5.hi);  f = FLAG($4.hi==$5.hi ? $4.lo>$5.lo : $4.hi>$5.hi);
 #else  #else
 f = FLAG($4>$5);  f = FLAG($4>$5);
 #endif  #endif
   
 $1<=    $2 -- f         gforth  $3less_or_equal  $1<=    ( $2 -- f )             gforth  $3less_or_equal
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 f = FLAG($4.hi==$5.hi ? $4.lo<=$5.lo : $4.hi<=$5.hi);  f = FLAG($4.hi==$5.hi ? $4.lo<=$5.lo : $4.hi<=$5.hi);
 #else  #else
 f = FLAG($4<=$5);  f = FLAG($4<=$5);
 #endif  #endif
   
 $1>=    $2 -- f         gforth  $3greater_or_equal  $1>=    ( $2 -- f )             gforth  $3greater_or_equal
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 f = FLAG($4.hi==$5.hi ? $4.lo>=$5.lo : $4.hi>=$5.hi);  f = FLAG($4.hi==$5.hi ? $4.lo>=$5.lo : $4.hi>=$5.hi);
 #else  #else
Line 932  dcomparisons(du, ud1 ud2, d_u_, ud1, ud2 Line 932  dcomparisons(du, ud1 ud2, d_u_, ud1, ud2
   
 \+  \+
   
 within  u1 u2 u3 -- f           core-ext  within  ( u1 u2 u3 -- f )               core-ext
 ""u2=<u1<u3 or: u3=<u2 and u1 is not in [u3,u2).  This works for  ""u2=<u1<u3 or: u3=<u2 and u1 is not in [u3,u2).  This works for
 unsigned and signed numbers (but not a mixture).  Another way to think  unsigned and signed numbers (but not a mixture).  Another way to think
 about this word is to consider the numbers as a circle (wrapping  about this word is to consider the numbers as a circle (wrapping
Line 944  f = FLAG(u1-u2 < u3-u2); Line 944  f = FLAG(u1-u2 < u3-u2);
 :  :
  over - >r - r> u< ;   over - >r - r> u< ;
   
 sp@     -- a_addr               gforth          sp_fetch  sp@     ( -- a_addr )           gforth          sp_fetch
 a_addr = sp+1;  a_addr = sp+1;
   
 sp!     a_addr --               gforth          sp_store  sp!     ( a_addr -- )           gforth          sp_store
 sp = a_addr;  sp = a_addr;
 /* works with and without TOS caching */  /* works with and without TOS caching */
   
 rp@     -- a_addr               gforth          rp_fetch  rp@     ( -- a_addr )           gforth          rp_fetch
 a_addr = rp;  a_addr = rp;
   
 rp!     a_addr --               gforth          rp_store  rp!     ( a_addr -- )           gforth          rp_store
 rp = a_addr;  rp = a_addr;
   
 \+floating  \+floating
   
 fp@     -- f_addr       gforth  fp_fetch  fp@     ( -- f_addr )   gforth  fp_fetch
 f_addr = fp;  f_addr = fp;
   
 fp!     f_addr --       gforth  fp_store  fp!     ( f_addr -- )   gforth  fp_store
 fp = f_addr;  fp = f_addr;
   
 \+  \+
   
 ;s      --              gforth  semis  ;s      ( -- )          gforth  semis
 ""The primitive compiled by @code{EXIT}.""  ""The primitive compiled by @code{EXIT}.""
 SET_IP((Xt *)(*rp++));  SET_IP((Xt *)(*rp++));
   
 >r      w --            core    to_r  >r      ( w -- )                core    to_r
 *--rp = w;  *--rp = w;
 :  :
  (>r) ;   (>r) ;
 : (>r)  rp@ cell+ @ rp@ ! rp@ cell+ ! ;  : (>r)  rp@ cell+ @ rp@ ! rp@ cell+ ! ;
   
 r>      -- w            core    r_from  r>      ( -- w )                core    r_from
 w = *rp++;  w = *rp++;
 :  :
  rp@ cell+ @ rp@ @ rp@ cell+ ! (rdrop) rp@ ! ;   rp@ cell+ @ rp@ @ rp@ cell+ ! (rdrop) rp@ ! ;
 Create (rdrop) ' ;s A,  Create (rdrop) ' ;s A,
   
 rdrop   --              gforth  rdrop   ( -- )          gforth
 rp++;  rp++;
 :  :
  r> r> drop >r ;   r> r> drop >r ;
   
 2>r     w1 w2 --        core-ext        two_to_r  2>r     ( w1 w2 -- )    core-ext        two_to_r
 *--rp = w1;  *--rp = w1;
 *--rp = w2;  *--rp = w2;
 :  :
  swap r> swap >r swap >r >r ;   swap r> swap >r swap >r >r ;
   
 2r>     -- w1 w2        core-ext        two_r_from  2r>     ( -- w1 w2 )    core-ext        two_r_from
 w2 = *rp++;  w2 = *rp++;
 w1 = *rp++;  w1 = *rp++;
 :  :
  r> r> swap r> swap >r swap ;   r> r> swap r> swap >r swap ;
   
 2r@     -- w1 w2        core-ext        two_r_fetch  2r@     ( -- w1 w2 )    core-ext        two_r_fetch
 w2 = rp[0];  w2 = rp[0];
 w1 = rp[1];  w1 = rp[1];
 :  :
  i' j ;   i' j ;
   
 2rdrop  --              gforth  two_r_drop  2rdrop  ( -- )          gforth  two_r_drop
 rp+=2;  rp+=2;
 :  :
  r> r> drop r> drop >r ;   r> r> drop r> drop >r ;
   
 over    w1 w2 -- w1 w2 w1               core  over    ( w1 w2 -- w1 w2 w1 )           core
 :  :
  sp@ cell+ @ ;   sp@ cell+ @ ;
   
 drop    w --            core  drop    ( w -- )                core
 :  :
  IF THEN ;   IF THEN ;
   
 swap    w1 w2 -- w2 w1          core  swap    ( w1 w2 -- w2 w1 )              core
 :  :
  >r (swap) ! r> (swap) @ ;   >r (swap) ! r> (swap) @ ;
 Variable (swap)  Variable (swap)
   
 dup     w -- w w                core    dupe  dup     ( w -- w w )            core    dupe
 :  :
  sp@ @ ;   sp@ @ ;
   
 rot     w1 w2 w3 -- w2 w3 w1    core    rote  rot     ( w1 w2 w3 -- w2 w3 w1 )        core    rote
 :  :
 [ defined? (swap) [IF] ]  [ defined? (swap) [IF] ]
     (swap) ! (rot) ! >r (rot) @ (swap) @ r> ;      (swap) ! (rot) ! >r (rot) @ (swap) @ r> ;
Line 1037  Variable (rot) Line 1037  Variable (rot)
     >r swap r> swap ;      >r swap r> swap ;
 [THEN]  [THEN]
   
 -rot    w1 w2 w3 -- w3 w1 w2    gforth  not_rote  -rot    ( w1 w2 w3 -- w3 w1 w2 )        gforth  not_rote
 :  :
  rot rot ;   rot rot ;
   
 nip     w1 w2 -- w2             core-ext  nip     ( w1 w2 -- w2 )         core-ext
 :  :
  swap drop ;   swap drop ;
   
 tuck    w1 w2 -- w2 w1 w2       core-ext  tuck    ( w1 w2 -- w2 w1 w2 )   core-ext
 :  :
  swap over ;   swap over ;
   
 ?dup    w -- w                  core    question_dupe  ?dup    ( w -- w )                      core    question_dupe
 if (w!=0) {  if (w!=0) {
   IF_TOS(*sp-- = w;)    IF_TOS(*sp-- = w;)
 #ifndef USE_TOS  #ifndef USE_TOS
Line 1059  if (w!=0) { Line 1059  if (w!=0) {
 :  :
  dup IF dup THEN ;   dup IF dup THEN ;
   
 pick    u -- w                  core-ext  pick    ( u -- w )                      core-ext
 w = sp[u+1];  w = sp[u+1];
 :  :
  1+ cells sp@ + @ ;   1+ cells sp@ + @ ;
   
 2drop   w1 w2 --                core    two_drop  2drop   ( w1 w2 -- )            core    two_drop
 :  :
  drop drop ;   drop drop ;
   
 2dup    w1 w2 -- w1 w2 w1 w2    core    two_dupe  2dup    ( w1 w2 -- w1 w2 w1 w2 )        core    two_dupe
 :  :
  over over ;   over over ;
   
 2over   w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2        core    two_over  2over   ( w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2 )    core    two_over
 :  :
  3 pick 3 pick ;   3 pick 3 pick ;
   
 2swap   w1 w2 w3 w4 -- w3 w4 w1 w2      core    two_swap  2swap   ( w1 w2 w3 w4 -- w3 w4 w1 w2 )  core    two_swap
 :  :
  rot >r rot r> ;   rot >r rot r> ;
   
 2rot    w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2  double-ext      two_rote  2rot    ( w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2 )      double-ext      two_rote
 :  :
  >r >r 2swap r> r> 2swap ;   >r >r 2swap r> r> 2swap ;
   
 2nip    w1 w2 w3 w4 -- w3 w4    gforth  two_nip  2nip    ( w1 w2 w3 w4 -- w3 w4 )        gforth  two_nip
 :  :
  2swap 2drop ;   2swap 2drop ;
   
 2tuck   w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4        gforth  two_tuck  2tuck   ( w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4 )    gforth  two_tuck
 :  :
  2swap 2over ;   2swap 2over ;
   
 \ toggle is high-level: 0.11/0.42%  \ toggle is high-level: 0.11/0.42%
   
 @       a_addr -- w             core    fetch  @       ( a_addr -- w )         core    fetch
 "" Read from the cell at address @i{a-addr}, and return its contents, @i{w}.""  "" Read from the cell at address @i{a-addr}, and return its contents, @i{w}.""
 w = *a_addr;  w = *a_addr;
   
 !       w a_addr --             core    store  !       ( w a_addr -- )         core    store
 "" Write the value @i{w} to the cell at address @i{a-addr}.""  "" Write the value @i{w} to the cell at address @i{a-addr}.""
 *a_addr = w;  *a_addr = w;
   
 +!      n a_addr --             core    plus_store  +!      ( n a_addr -- )         core    plus_store
 "" Add @i{n} to the value stored in the cell at address @i{a-addr}.""  "" Add @i{n} to the value stored in the cell at address @i{a-addr}.""
 *a_addr += n;  *a_addr += n;
 :  :
  tuck @ + swap ! ;   tuck @ + swap ! ;
   
 c@      c_addr -- c             core    c_fetch  c@      ( c_addr -- c )         core    c_fetch
 "" Read from the char at address @i{c-addr}, and return its contents, @i{c}.""  "" Read from the char at address @i{c-addr}, and return its contents, @i{c}.""
 c = *c_addr;  c = *c_addr;
 :  :
Line 1134  c = *c_addr; Line 1134  c = *c_addr;
 ;  ;
 : 8>> 2/ 2/ 2/ 2/  2/ 2/ 2/ 2/ ;  : 8>> 2/ 2/ 2/ 2/  2/ 2/ 2/ 2/ ;
   
 c!      c c_addr --             core    c_store  c!      ( c c_addr -- )         core    c_store
 "" Write the value @i{c} to the char at address @i{c-addr}.""  "" Write the value @i{c} to the char at address @i{c-addr}.""
 *c_addr = c;  *c_addr = c;
 :  :
Line 1164  c! c c_addr --  core c_store Line 1164  c! c c_addr --  core c_store
 [THEN]  [THEN]
 : 8<< 2* 2* 2* 2*  2* 2* 2* 2* ;  : 8<< 2* 2* 2* 2*  2* 2* 2* 2* ;
   
 2!      w1 w2 a_addr --         core    two_store  2!      ( w1 w2 a_addr -- )             core    two_store
 "" Write the value @i{w1, w2} to the double at address @i{a-addr}.""  "" Write the value @i{w1, w2} to the double at address @i{a-addr}.""
 a_addr[0] = w2;  a_addr[0] = w2;
 a_addr[1] = w1;  a_addr[1] = w1;
 :  :
  tuck ! cell+ ! ;   tuck ! cell+ ! ;
   
 2@      a_addr -- w1 w2         core    two_fetch  2@      ( a_addr -- w1 w2 )             core    two_fetch
 "" Read from the double at address @i{a-addr}, and return its contents, @i{w1, w2}.""  "" Read from the double at address @i{a-addr}, and return its contents, @i{w1, w2}.""
 w2 = a_addr[0];  w2 = a_addr[0];
 w1 = a_addr[1];  w1 = a_addr[1];
 :  :
  dup cell+ @ swap @ ;   dup cell+ @ swap @ ;
   
 cell+   a_addr1 -- a_addr2      core    cell_plus  cell+   ( a_addr1 -- a_addr2 )  core    cell_plus
 "" Increment @i{a-addr1} by the number of address units corresponding to the size of  "" Increment @i{a-addr1} by the number of address units corresponding to the size of
 one cell, to give @i{a-addr2}.""  one cell, to give @i{a-addr2}.""
 a_addr2 = a_addr1+1;  a_addr2 = a_addr1+1;
 :  :
  cell + ;   cell + ;
   
 cells   n1 -- n2                core  cells   ( n1 -- n2 )            core
 "" @i{n2} is the number of address units corresponding to @i{n1} cells.""  "" @i{n2} is the number of address units corresponding to @i{n1} cells.""
 n2 = n1 * sizeof(Cell);  n2 = n1 * sizeof(Cell);
 :  :
Line 1196  n2 = n1 * sizeof(Cell); Line 1196  n2 = n1 * sizeof(Cell);
  2/ dup [IF] ] 2* [ [THEN]   2/ dup [IF] ] 2* [ [THEN]
  drop ] ;   drop ] ;
   
 char+   c_addr1 -- c_addr2      core    char_plus  char+   ( c_addr1 -- c_addr2 )  core    char_plus
 "" Increment @i{c-addr1} by the number of address units corresponding to the size of  "" Increment @i{c-addr1} by the number of address units corresponding to the size of
 one char, to give @i{c-addr2}.""  one char, to give @i{c-addr2}.""
 c_addr2 = c_addr1 + 1;  c_addr2 = c_addr1 + 1;
 :  :
  1+ ;   1+ ;
   
 (chars)         n1 -- n2        gforth  paren_chars  (chars) ( n1 -- n2 )    gforth  paren_chars
 n2 = n1 * sizeof(Char);  n2 = n1 * sizeof(Char);
 :  :
  ;   ;
   
 count   c_addr1 -- c_addr2 u    core  count   ( c_addr1 -- c_addr2 u )        core
 "" If @i{c-add1} is the address of a counted string return the length of  "" If @i{c-add1} is the address of a counted string return the length of
 the string, @i{u}, and the address of its first character, @i{c-addr2}.""  the string, @i{u}, and the address of its first character, @i{c-addr2}.""
 u = *c_addr1;  u = *c_addr1;
Line 1216  c_addr2 = c_addr1+1; Line 1216  c_addr2 = c_addr1+1;
 :  :
  dup 1+ swap c@ ;   dup 1+ swap c@ ;
   
 (f83find)       c_addr u f83name1 -- f83name2   new     paren_f83find  (f83find)       ( c_addr u f83name1 -- f83name2 )       new     paren_f83find
 for (; f83name1 != NULL; f83name1 = (struct F83Name *)(f83name1->next))  for (; f83name1 != NULL; f83name1 = (struct F83Name *)(f83name1->next))
   if ((UCell)F83NAME_COUNT(f83name1)==u &&    if ((UCell)F83NAME_COUNT(f83name1)==u &&
       memcasecmp(c_addr, f83name1->name, u)== 0 /* or inline? */)        memcasecmp(c_addr, f83name1->name, u)== 0 /* or inline? */)
Line 1233  f83name2=f83name1; Line 1233  f83name2=f83name1;
   
 \+hash  \+hash
   
 (hashfind)      c_addr u a_addr -- f83name2     new     paren_hashfind  (hashfind)      ( c_addr u a_addr -- f83name2 ) new     paren_hashfind
 struct F83Name *f83name1;  struct F83Name *f83name1;
 f83name2=NULL;  f83name2=NULL;
 while(a_addr != NULL)  while(a_addr != NULL)
Line 1255  while(a_addr != NULL) Line 1255  while(a_addr != NULL)
         rdrop r>          rdrop r>
  REPEAT nip nip ;   REPEAT nip nip ;
   
 (tablefind)     c_addr u a_addr -- f83name2     new     paren_tablefind  (tablefind)     ( c_addr u a_addr -- f83name2 ) new     paren_tablefind
 ""A case-sensitive variant of @code{(hashfind)}""  ""A case-sensitive variant of @code{(hashfind)}""
 struct F83Name *f83name1;  struct F83Name *f83name1;
 f83name2=NULL;  f83name2=NULL;
Line 1278  while(a_addr != NULL) Line 1278  while(a_addr != NULL)
         rdrop r>          rdrop r>
  REPEAT nip nip ;   REPEAT nip nip ;
   
 (hashkey)       c_addr u1 -- u2         gforth  paren_hashkey  (hashkey)       ( c_addr u1 -- u2 )             gforth  paren_hashkey
 u2=0;  u2=0;
 while(u1--)  while(u1--)
    u2+=(Cell)toupper(*c_addr++);     u2+=(Cell)toupper(*c_addr++);
 :  :
  0 -rot bounds ?DO  I c@ toupper +  LOOP ;   0 -rot bounds ?DO  I c@ toupper +  LOOP ;
   
 (hashkey1)      c_addr u ubits -- ukey          gforth  paren_hashkey1  (hashkey1)      ( c_addr u ubits -- ukey )              gforth  paren_hashkey1
 ""ukey is the hash key for the string c_addr u fitting in ubits bits""  ""ukey is the hash key for the string c_addr u fitting in ubits bits""
 /* this hash function rotates the key at every step by rot bits within  /* this hash function rotates the key at every step by rot bits within
    ubits bits and xors it with the character. This function does ok in     ubits bits and xors it with the character. This function does ok in
Line 1314  Create rot-values Line 1314  Create rot-values
   
 \+  \+
   
 (parse-white)   c_addr1 u1 -- c_addr2 u2        gforth  paren_parse_white  (parse-white)   ( c_addr1 u1 -- c_addr2 u2 )    gforth  paren_parse_white
 /* use !isgraph instead of isspace? */  /* use !isgraph instead of isspace? */
 Char *endp = c_addr1+u1;  Char *endp = c_addr1+u1;
 while (c_addr1<endp && isspace(*c_addr1))  while (c_addr1<endp && isspace(*c_addr1))
Line 1334  else { Line 1334  else {
  BEGIN  dup  WHILE  over c@ bl >   WHILE  1 /string   BEGIN  dup  WHILE  over c@ bl >   WHILE  1 /string
  REPEAT  THEN  nip - ;   REPEAT  THEN  nip - ;
   
 aligned         c_addr -- a_addr        core  aligned ( c_addr -- a_addr )    core
 "" @i{a-addr} is the first aligned address greater than or equal to @i{c-addr}.""  "" @i{a-addr} is the first aligned address greater than or equal to @i{c-addr}.""
 a_addr = (Cell *)((((Cell)c_addr)+(sizeof(Cell)-1))&(-sizeof(Cell)));  a_addr = (Cell *)((((Cell)c_addr)+(sizeof(Cell)-1))&(-sizeof(Cell)));
 :  :
  [ cell 1- ] Literal + [ -1 cells ] Literal and ;   [ cell 1- ] Literal + [ -1 cells ] Literal and ;
   
 faligned        c_addr -- f_addr        float   f_aligned  faligned        ( c_addr -- f_addr )    float   f_aligned
 "" @i{f-addr} is the first float-aligned address greater than or equal to @i{c-addr}.""  "" @i{f-addr} is the first float-aligned address greater than or equal to @i{c-addr}.""
 f_addr = (Float *)((((Cell)c_addr)+(sizeof(Float)-1))&(-sizeof(Float)));  f_addr = (Float *)((((Cell)c_addr)+(sizeof(Float)-1))&(-sizeof(Float)));
 :  :
  [ 1 floats 1- ] Literal + [ -1 floats ] Literal and ;   [ 1 floats 1- ] Literal + [ -1 floats ] Literal and ;
   
 >body           xt -- a_addr    core    to_body  >body   ( xt -- a_addr )        core    to_body
 "" Get the address of the body of the word represented by @i{xt} (the address  "" Get the address of the body of the word represented by @i{xt} (the address
 of the word's data field).""  of the word's data field).""
 a_addr = PFA(xt);  a_addr = PFA(xt);
Line 1356  a_addr = PFA(xt); Line 1356  a_addr = PFA(xt);
 \ threading stuff is currently only interesting if we have a compiler  \ threading stuff is currently only interesting if we have a compiler
 \fhas? standardthreading has? compiler and [IF]  \fhas? standardthreading has? compiler and [IF]
   
 >code-address           xt -- c_addr            gforth  to_code_address  >code-address   ( xt -- c_addr )                gforth  to_code_address
 ""@i{c-addr} is the code address of the word @i{xt}.""  ""@i{c-addr} is the code address of the word @i{xt}.""
 /* !! This behaves installation-dependently for DOES-words */  /* !! This behaves installation-dependently for DOES-words */
 c_addr = (Address)CODE_ADDRESS(xt);  c_addr = (Address)CODE_ADDRESS(xt);
 :  :
     @ ;      @ ;
   
 >does-code      xt -- a_addr            gforth  to_does_code  >does-code      ( xt -- a_addr )                gforth  to_does_code
 ""If @i{xt} is the execution token of a defining-word-defined word,  ""If @i{xt} is the execution token of a defining-word-defined word,
 @i{a-addr} is the start of the Forth code after the @code{DOES>};  @i{a-addr} is the start of the Forth code after the @code{DOES>};
 Otherwise @i{a-addr} is 0.""  Otherwise @i{a-addr} is 0.""
Line 1371  a_addr = (Cell *)DOES_CODE(xt); Line 1371  a_addr = (Cell *)DOES_CODE(xt);
 :  :
     cell+ @ ;      cell+ @ ;
   
 code-address!           c_addr xt --            gforth  code_address_store  code-address!   ( c_addr xt -- )                gforth  code_address_store
 ""Create a code field with code address @i{c-addr} at @i{xt}.""  ""Create a code field with code address @i{c-addr} at @i{xt}.""
 MAKE_CF(xt, c_addr);  MAKE_CF(xt, c_addr);
 CACHE_FLUSH(xt,(size_t)PFA(0));  CACHE_FLUSH(xt,(size_t)PFA(0));
 :  :
     ! ;      ! ;
   
 does-code!      a_addr xt --            gforth  does_code_store  does-code!      ( a_addr xt -- )                gforth  does_code_store
 ""Create a code field at @i{xt} for a defining-word-defined word; @i{a-addr}  ""Create a code field at @i{xt} for a defining-word-defined word; @i{a-addr}
 is the start of the Forth code after @code{DOES>}.""  is the start of the Forth code after @code{DOES>}.""
 MAKE_DOES_CF(xt, a_addr);  MAKE_DOES_CF(xt, a_addr);
Line 1386  CACHE_FLUSH(xt,(size_t)PFA(0)); Line 1386  CACHE_FLUSH(xt,(size_t)PFA(0));
 :  :
     dodoes: over ! cell+ ! ;      dodoes: over ! cell+ ! ;
   
 does-handler!   a_addr --       gforth  does_handler_store  does-handler!   ( a_addr -- )   gforth  does_handler_store
 ""Create a @code{DOES>}-handler at address @i{a-addr}. Usually, @i{a-addr} points  ""Create a @code{DOES>}-handler at address @i{a-addr}. Usually, @i{a-addr} points
 just behind a @code{DOES>}.""  just behind a @code{DOES>}.""
 MAKE_DOES_HANDLER(a_addr);  MAKE_DOES_HANDLER(a_addr);
Line 1394  CACHE_FLUSH((caddr_t)a_addr,DOES_HANDLER Line 1394  CACHE_FLUSH((caddr_t)a_addr,DOES_HANDLER
 :  :
     drop ;      drop ;
   
 /does-handler   -- n    gforth  slash_does_handler  /does-handler   ( -- n )        gforth  slash_does_handler
 ""The size of a @code{DOES>}-handler (includes possible padding).""  ""The size of a @code{DOES>}-handler (includes possible padding).""
 /* !! a constant or environmental query might be better */  /* !! a constant or environmental query might be better */
 n = DOES_HANDLER_SIZE;  n = DOES_HANDLER_SIZE;
 :  :
     2 cells ;      2 cells ;
   
 threading-method        -- n    gforth  threading_method  threading-method        ( -- n )        gforth  threading_method
 ""0 if the engine is direct threaded. Note that this may change during  ""0 if the engine is direct threaded. Note that this may change during
 the lifetime of an image.""  the lifetime of an image.""
 #if defined(DOUBLY_INDIRECT)  #if defined(DOUBLY_INDIRECT)
Line 1418  n=1; Line 1418  n=1;
   
 \f[THEN]  \f[THEN]
   
 key-file        wfileid -- n            gforth  paren_key_file  key-file        ( wfileid -- n )                gforth  paren_key_file
 #ifdef HAS_FILE  #ifdef HAS_FILE
 fflush(stdout);  fflush(stdout);
 n = key((FILE*)wfileid);  n = key((FILE*)wfileid);
Line 1426  n = key((FILE*)wfileid); Line 1426  n = key((FILE*)wfileid);
 n = key(stdin);  n = key(stdin);
 #endif  #endif
   
 key?-file       wfileid -- n            facility        key_q_file  key?-file       ( wfileid -- n )                facility        key_q_file
 #ifdef HAS_FILE  #ifdef HAS_FILE
 fflush(stdout);  fflush(stdout);
 n = key_query((FILE*)wfileid);  n = key_query((FILE*)wfileid);
Line 1436  n = key_query(stdin); Line 1436  n = key_query(stdin);
   
 \+os  \+os
   
 stdin   -- wfileid      gforth  stdin   ( -- wfileid )  gforth
 wfileid = (Cell)stdin;  wfileid = (Cell)stdin;
   
 stdout  -- wfileid      gforth  stdout  ( -- wfileid )  gforth
 wfileid = (Cell)stdout;  wfileid = (Cell)stdout;
   
 stderr  -- wfileid      gforth  stderr  ( -- wfileid )  gforth
 wfileid = (Cell)stderr;  wfileid = (Cell)stderr;
   
 form    -- urows ucols  gforth  form    ( -- urows ucols )      gforth
 ""The number of lines and columns in the terminal. These numbers may change  ""The number of lines and columns in the terminal. These numbers may change
 with the window size.""  with the window size.""
 /* we could block SIGWINCH here to get a consistent size, but I don't  /* we could block SIGWINCH here to get a consistent size, but I don't
Line 1453  with the window size."" Line 1453  with the window size.""
 urows=rows;  urows=rows;
 ucols=cols;  ucols=cols;
   
 flush-icache    c_addr u --     gforth  flush_icache  flush-icache    ( c_addr u -- ) gforth  flush_icache
 ""Make sure that the instruction cache of the processor (if there is  ""Make sure that the instruction cache of the processor (if there is
 one) does not contain stale data at @i{c-addr} and @i{u} bytes  one) does not contain stale data at @i{c-addr} and @i{u} bytes
 afterwards. @code{END-CODE} performs a @code{flush-icache}  afterwards. @code{END-CODE} performs a @code{flush-icache}
Line 1465  your machine has a separate instruction Line 1465  your machine has a separate instruction
 cache.""  cache.""
 FLUSH_ICACHE(c_addr,u);  FLUSH_ICACHE(c_addr,u);
   
 (bye)   n --    gforth  paren_bye  (bye)   ( n -- )        gforth  paren_bye
 return (Label *)n;  return (Label *)n;
   
 (system)        c_addr u -- wretval wior        gforth  peren_system  (system)        ( c_addr u -- wretval wior )    gforth  peren_system
 #ifndef MSDOS  #ifndef MSDOS
 int old_tp=terminal_prepped;  int old_tp=terminal_prepped;
 deprep_terminal();  deprep_terminal();
Line 1480  if (old_tp) Line 1480  if (old_tp)
   prep_terminal();    prep_terminal();
 #endif  #endif
   
 getenv  c_addr1 u1 -- c_addr2 u2        gforth  getenv  ( c_addr1 u1 -- c_addr2 u2 )    gforth
 ""The string @i{c-addr1 u1} specifies an environment variable. The string @i{c-addr2 u2}  ""The string @i{c-addr1 u1} specifies an environment variable. The string @i{c-addr2 u2}
 is the host operating system's expansion of that environment variable. If the  is the host operating system's expansion of that environment variable. If the
 environment variable does not exist, @i{c-addr2 u2} specifies a string 0 characters  environment variable does not exist, @i{c-addr2 u2} specifies a string 0 characters
Line 1489  in length."" Line 1489  in length.""
 c_addr2 = getenv(cstr(c_addr1,u1,1));  c_addr2 = getenv(cstr(c_addr1,u1,1));
 u2 = (c_addr2 == NULL ? 0 : strlen(c_addr2));  u2 = (c_addr2 == NULL ? 0 : strlen(c_addr2));
   
 open-pipe       c_addr u ntype -- wfileid wior  gforth  open_pipe  open-pipe       ( c_addr u ntype -- wfileid wior )      gforth  open_pipe
 wfileid=(Cell)popen(cstr(c_addr,u,1),fileattr[ntype]); /* ~ expansion of 1st arg? */  wfileid=(Cell)popen(cstr(c_addr,u,1),fileattr[ntype]); /* ~ expansion of 1st arg? */
 wior = IOR(wfileid==0); /* !! the man page says that errno is not set reliably */  wior = IOR(wfileid==0); /* !! the man page says that errno is not set reliably */
   
 close-pipe      wfileid -- wretval wior         gforth  close_pipe  close-pipe      ( wfileid -- wretval wior )             gforth  close_pipe
 wretval = pclose((FILE *)wfileid);  wretval = pclose((FILE *)wfileid);
 wior = IOR(wretval==-1);  wior = IOR(wretval==-1);
   
 time&date       -- nsec nmin nhour nday nmonth nyear    facility-ext    time_and_date  time&date       ( -- nsec nmin nhour nday nmonth nyear )        facility-ext    time_and_date
 ""Report the current time of day. Seconds, minutes and hours are numbered from 0.  ""Report the current time of day. Seconds, minutes and hours are numbered from 0.
 Months are numbered from 1.""  Months are numbered from 1.""
 struct timeval time1;  struct timeval time1;
 struct timezone zone1;  struct timezone zone1;
 struct tm *ltime;  struct tm *ltime;
 gettimeofday(&time1,&zone1);  gettimeofday(&time1,&zone1);
   /* !! Single Unix specification: 
      If tzp is not a null pointer, the behaviour is unspecified. */
 ltime=localtime((time_t *)&time1.tv_sec);  ltime=localtime((time_t *)&time1.tv_sec);
 nyear =ltime->tm_year+1900;  nyear =ltime->tm_year+1900;
 nmonth=ltime->tm_mon+1;  nmonth=ltime->tm_mon+1;
Line 1512  nhour =ltime->tm_hour; Line 1514  nhour =ltime->tm_hour;
 nmin  =ltime->tm_min;  nmin  =ltime->tm_min;
 nsec  =ltime->tm_sec;  nsec  =ltime->tm_sec;
   
 ms      n --    facility-ext  ms      ( n -- )        facility-ext
 ""Wait at least @i{n} milli-second.""  ""Wait at least @i{n} milli-second.""
 struct timeval timeout;  struct timeval timeout;
 timeout.tv_sec=n/1000;  timeout.tv_sec=n/1000;
 timeout.tv_usec=1000*(n%1000);  timeout.tv_usec=1000*(n%1000);
 (void)select(0,0,0,0,&timeout);  (void)select(0,0,0,0,&timeout);
   
 allocate        u -- a_addr wior        memory  allocate        ( u -- a_addr wior )    memory
 ""Allocate @i{u} address units of contiguous data space. The initial  ""Allocate @i{u} address units of contiguous data space. The initial
 contents of the data space is undefined. If the allocation is successful,  contents of the data space is undefined. If the allocation is successful,
 @i{a-addr} is the start address of the allocated region and @i{wior}  @i{a-addr} is the start address of the allocated region and @i{wior}
Line 1528  is an implementation-defined I/O result Line 1530  is an implementation-defined I/O result
 a_addr = (Cell *)malloc(u?u:1);  a_addr = (Cell *)malloc(u?u:1);
 wior = IOR(a_addr==NULL);  wior = IOR(a_addr==NULL);
   
 free            a_addr -- wior          memory  free    ( a_addr -- wior )              memory
 ""Return the region of data space starting at @i{a-addr} to the system.  ""Return the region of data space starting at @i{a-addr} to the system.
 The regon must originally have been obtained using @code{allocate} or  The regon must originally have been obtained using @code{allocate} or
 @code{resize}. If the operational is successful, @i{wior} is 0.  @code{resize}. If the operational is successful, @i{wior} is 0.
Line 1537  I/O result code."" Line 1539  I/O result code.""
 free(a_addr);  free(a_addr);
 wior = 0;  wior = 0;
   
 resize          a_addr1 u -- a_addr2 wior       memory  resize  ( a_addr1 u -- a_addr2 wior )   memory
 ""Change the size of the allocated area at @i{a-addr1} to @i{u}  ""Change the size of the allocated area at @i{a-addr1} to @i{u}
 address units, possibly moving the contents to a different  address units, possibly moving the contents to a different
 area. @i{a-addr2} is the address of the resulting area.  area. @i{a-addr2} is the address of the resulting area.
Line 1554  else Line 1556  else
   a_addr2 = (Cell *)realloc(a_addr1, u);    a_addr2 = (Cell *)realloc(a_addr1, u);
 wior = IOR(a_addr2==NULL);      /* !! Define a return code */  wior = IOR(a_addr2==NULL);      /* !! Define a return code */
   
 strerror        n -- c_addr u   gforth  strerror        ( n -- c_addr u )       gforth
 c_addr = strerror(n);  c_addr = strerror(n);
 u = strlen(c_addr);  u = strlen(c_addr);
   
 strsignal       n -- c_addr u   gforth  strsignal       ( n -- c_addr u )       gforth
 c_addr = strsignal(n);  c_addr = strsignal(n);
 u = strlen(c_addr);  u = strlen(c_addr);
   
 call-c  w --    gforth  call_c  call-c  ( w -- )        gforth  call_c
 ""Call the C function pointed to by @i{w}. The C function has to  ""Call the C function pointed to by @i{w}. The C function has to
 access the stack itself. The stack pointers are exported in the global  access the stack itself. The stack pointers are exported in the global
 variables @code{SP} and @code{FP}.""  variables @code{SP} and @code{FP}.""
Line 1580  IF_FTOS(FTOS=fp[0]); Line 1582  IF_FTOS(FTOS=fp[0]);
 \+  \+
 \+file  \+file
   
 close-file      wfileid -- wior         file    close_file  close-file      ( wfileid -- wior )             file    close_file
 wior = IOR(fclose((FILE *)wfileid)==EOF);  wior = IOR(fclose((FILE *)wfileid)==EOF);
   
 open-file       c_addr u ntype -- wfileid wior  file    open_file  open-file       ( c_addr u ntype -- wfileid wior )      file    open_file
 wfileid = (Cell)fopen(tilde_cstr(c_addr, u, 1), fileattr[ntype]);  wfileid = (Cell)fopen(tilde_cstr(c_addr, u, 1), fileattr[ntype]);
 #if defined(GO32) && defined(MSDOS)  
 if(wfileid && !(ntype & 1))  
   setbuf((FILE*)wfileid, NULL);  
 #endif  
 wior =  IOR(wfileid == 0);  wior =  IOR(wfileid == 0);
   
 create-file     c_addr u ntype -- wfileid wior  file    create_file  create-file     ( c_addr u ntype -- wfileid wior )      file    create_file
 Cell    fd;  Cell    fd;
 fd = open(tilde_cstr(c_addr, u, 1), O_CREAT|O_TRUNC|ufileattr[ntype], 0666);  fd = open(tilde_cstr(c_addr, u, 1), O_CREAT|O_TRUNC|ufileattr[ntype], 0666);
 if (fd != -1) {  if (fd != -1) {
   wfileid = (Cell)fdopen(fd, fileattr[ntype]);    wfileid = (Cell)fdopen(fd, fileattr[ntype]);
 #if defined(GO32) && defined(MSDOS)  
   if(wfileid && !(ntype & 1))  
     setbuf((FILE*)wfileid, NULL);  
 #endif  
   wior = IOR(wfileid == 0);    wior = IOR(wfileid == 0);
 } else {  } else {
   wfileid = 0;    wfileid = 0;
   wior = IOR(1);    wior = IOR(1);
 }  }
   
 delete-file     c_addr u -- wior                file    delete_file  delete-file     ( c_addr u -- wior )            file    delete_file
 wior = IOR(unlink(tilde_cstr(c_addr, u, 1))==-1);  wior = IOR(unlink(tilde_cstr(c_addr, u, 1))==-1);
   
 rename-file     c_addr1 u1 c_addr2 u2 -- wior   file-ext        rename_file  rename-file     ( c_addr1 u1 c_addr2 u2 -- wior )       file-ext        rename_file
 ""Rename file @i{c_addr1 u1} to new name @i{c_addr2 u2}""  ""Rename file @i{c_addr1 u1} to new name @i{c_addr2 u2}""
 char *s1=tilde_cstr(c_addr2, u2, 1);  char *s1=tilde_cstr(c_addr2, u2, 1);
 wior = IOR(rename(tilde_cstr(c_addr1, u1, 0), s1)==-1);  wior = IOR(rename(tilde_cstr(c_addr1, u1, 0), s1)==-1);
   
 file-position   wfileid -- ud wior      file    file_position  file-position   ( wfileid -- ud wior )  file    file_position
 /* !! use tell and lseek? */  /* !! use tell and lseek? */
 ud = LONG2UD(ftell((FILE *)wfileid));  ud = LONG2UD(ftell((FILE *)wfileid));
 wior = IOR(UD2LONG(ud)==-1);  wior = IOR(UD2LONG(ud)==-1);
   
 reposition-file ud wfileid -- wior      file    reposition_file  reposition-file ( ud wfileid -- wior )  file    reposition_file
 wior = IOR(fseek((FILE *)wfileid, UD2LONG(ud), SEEK_SET)==-1);  wior = IOR(fseek((FILE *)wfileid, UD2LONG(ud), SEEK_SET)==-1);
   
 file-size       wfileid -- ud wior      file    file_size  file-size       ( wfileid -- ud wior )  file    file_size
 struct stat buf;  struct stat buf;
 wior = IOR(fstat(fileno((FILE *)wfileid), &buf)==-1);  wior = IOR(fstat(fileno((FILE *)wfileid), &buf)==-1);
 ud = LONG2UD(buf.st_size);  ud = LONG2UD(buf.st_size);
   
 resize-file     ud wfileid -- wior      file    resize_file  resize-file     ( ud wfileid -- wior )  file    resize_file
 wior = IOR(ftruncate(fileno((FILE *)wfileid), UD2LONG(ud))==-1);  wior = IOR(ftruncate(fileno((FILE *)wfileid), UD2LONG(ud))==-1);
   
 read-file       c_addr u1 wfileid -- u2 wior    file    read_file  read-file       ( c_addr u1 wfileid -- u2 wior )        file    read_file
 /* !! fread does not guarantee enough */  /* !! fread does not guarantee enough */
 u2 = fread(c_addr, sizeof(Char), u1, (FILE *)wfileid);  u2 = fread(c_addr, sizeof(Char), u1, (FILE *)wfileid);
 wior = FILEIO(u2<u1 && ferror((FILE *)wfileid));  wior = FILEIO(u2<u1 && ferror((FILE *)wfileid));
Line 1638  wior = FILEIO(u2<u1 && ferror((FILE *)wf Line 1632  wior = FILEIO(u2<u1 && ferror((FILE *)wf
 if (wior)  if (wior)
   clearerr((FILE *)wfileid);    clearerr((FILE *)wfileid);
   
 read-line       c_addr u1 wfileid -- u2 flag wior       file    read_line  read-line       ( c_addr u1 wfileid -- u2 flag wior )   file    read_line
 #if 1  #if 1
 Cell c;  Cell c;
 flag=-1;  flag=-1;
Line 1675  else { Line 1669  else {
   
 \+  \+
   
 write-file      c_addr u1 wfileid -- wior       file    write_file  write-file      ( c_addr u1 wfileid -- wior )   file    write_file
 /* !! fwrite does not guarantee enough */  /* !! fwrite does not guarantee enough */
 #ifdef HAS_FILE  #ifdef HAS_FILE
 {  {
Line 1688  write-file c_addr u1 wfileid -- wior fil Line 1682  write-file c_addr u1 wfileid -- wior fil
 TYPE(c_addr, u1);  TYPE(c_addr, u1);
 #endif  #endif
   
 emit-file       c wfileid -- wior       gforth  emit_file  emit-file       ( c wfileid -- wior )   gforth  emit_file
 #ifdef HAS_FILE  #ifdef HAS_FILE
 wior = FILEIO(putc(c, (FILE *)wfileid)==EOF);  wior = FILEIO(putc(c, (FILE *)wfileid)==EOF);
 if (wior)  if (wior)
Line 1699  PUTC(c); Line 1693  PUTC(c);
   
 \+file  \+file
   
 flush-file      wfileid -- wior         file-ext        flush_file  flush-file      ( wfileid -- wior )             file-ext        flush_file
 wior = IOR(fflush((FILE *) wfileid)==EOF);  wior = IOR(fflush((FILE *) wfileid)==EOF);
   
 file-status     c_addr u -- ntype wior  file-ext        file_status  file-status     ( c_addr u -- ntype wior )      file-ext        file_status
 char *filename=tilde_cstr(c_addr, u, 1);  char *filename=tilde_cstr(c_addr, u, 1);
 if (access (filename, F_OK) != 0) {  if (access (filename, F_OK) != 0) {
   ntype=0;    ntype=0;
Line 1732  else { Line 1726  else {
 comparisons(f, r1 r2, f_, r1, r2, gforth, gforth, float, gforth)  comparisons(f, r1 r2, f_, r1, r2, gforth, gforth, float, gforth)
 comparisons(f0, r, f_zero_, r, 0., float, gforth, float, gforth)  comparisons(f0, r, f_zero_, r, 0., float, gforth, float, gforth)
   
 d>f             d -- r          float   d_to_f  d>f     ( d -- r )              float   d_to_f
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 extern double ldexp(double x, int exp);  extern double ldexp(double x, int exp);
 r = ldexp((Float)d.hi,CELL_BITS) + (Float)d.lo;  r = ldexp((Float)d.hi,CELL_BITS) + (Float)d.lo;
Line 1740  r = ldexp((Float)d.hi,CELL_BITS) + (Floa Line 1734  r = ldexp((Float)d.hi,CELL_BITS) + (Floa
 r = d;  r = d;
 #endif  #endif
   
 f>d             r -- d          float   f_to_d  f>d     ( r -- d )              float   f_to_d
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LONG_LONG
 d.hi = ldexp(r,-(int)(CELL_BITS)) - (r<0);  d.hi = ldexp(r,-(int)(CELL_BITS)) - (r<0);
 d.lo = r-ldexp((Float)d.hi,CELL_BITS);  d.lo = r-ldexp((Float)d.hi,CELL_BITS);
Line 1748  d.lo = r-ldexp((Float)d.hi,CELL_BITS); Line 1742  d.lo = r-ldexp((Float)d.hi,CELL_BITS);
 d = r;  d = r;
 #endif  #endif
   
 f!              r f_addr --     float   f_store  f!      ( r f_addr -- ) float   f_store
 "" Store the floating-point value @i{r} to address @i{f-addr}.""  "" Store the floating-point value @i{r} to address @i{f-addr}.""
 *f_addr = r;  *f_addr = r;
   
 f@              f_addr -- r     float   f_fetch  f@      ( f_addr -- r ) float   f_fetch
 "" Fetch floating-point value @i{r} from address @i{f-addr}.""  "" Fetch floating-point value @i{r} from address @i{f-addr}.""
 r = *f_addr;  r = *f_addr;
   
 df@             df_addr -- r    float-ext       d_f_fetch  df@     ( df_addr -- r )        float-ext       d_f_fetch
 "" Fetch the double-precision IEEE floating-point value @i{r} from the address @i{df-addr}.""  "" Fetch the double-precision IEEE floating-point value @i{r} from the address @i{df-addr}.""
 #ifdef IEEE_FP  #ifdef IEEE_FP
 r = *df_addr;  r = *df_addr;
Line 1764  r = *df_addr; Line 1758  r = *df_addr;
 !! df@  !! df@
 #endif  #endif
   
 df!             r df_addr --    float-ext       d_f_store  df!     ( r df_addr -- )        float-ext       d_f_store
 "" Store the double-precision IEEE floating-point value @i{r} to the address @i{df-addr}.""  "" Store the double-precision IEEE floating-point value @i{r} to the address @i{df-addr}.""
 #ifdef IEEE_FP  #ifdef IEEE_FP
 *df_addr = r;  *df_addr = r;
Line 1772  df!  r df_addr -- float-ext d_f_store Line 1766  df!  r df_addr -- float-ext d_f_store
 !! df!  !! df!
 #endif  #endif
   
 sf@             sf_addr -- r    float-ext       s_f_fetch  sf@     ( sf_addr -- r )        float-ext       s_f_fetch
 "" Fetch the single-precision IEEE floating-point value @i{r} from the address @i{sf-addr}.""  "" Fetch the single-precision IEEE floating-point value @i{r} from the address @i{sf-addr}.""
 #ifdef IEEE_FP  #ifdef IEEE_FP
 r = *sf_addr;  r = *sf_addr;
Line 1780  r = *sf_addr; Line 1774  r = *sf_addr;
 !! sf@  !! sf@
 #endif  #endif
   
 sf!             r sf_addr --    float-ext       s_f_store  sf!     ( r sf_addr -- )        float-ext       s_f_store
 "" Store the single-precision IEEE floating-point value @i{r} to the address @i{sf-addr}.""  "" Store the single-precision IEEE floating-point value @i{r} to the address @i{sf-addr}.""
 #ifdef IEEE_FP  #ifdef IEEE_FP
 *sf_addr = r;  *sf_addr = r;
Line 1788  sf!  r sf_addr -- float-ext s_f_store Line 1782  sf!  r sf_addr -- float-ext s_f_store
 !! sf!  !! sf!
 #endif  #endif
   
 f+              r1 r2 -- r3     float   f_plus  f+      ( r1 r2 -- r3 ) float   f_plus
 r3 = r1+r2;  r3 = r1+r2;
   
 f-              r1 r2 -- r3     float   f_minus  f-      ( r1 r2 -- r3 ) float   f_minus
 r3 = r1-r2;  r3 = r1-r2;
   
 f*              r1 r2 -- r3     float   f_star  f*      ( r1 r2 -- r3 ) float   f_star
 r3 = r1*r2;  r3 = r1*r2;
   
 f/              r1 r2 -- r3     float   f_slash  f/      ( r1 r2 -- r3 ) float   f_slash
 r3 = r1/r2;  r3 = r1/r2;
   
 f**             r1 r2 -- r3     float-ext       f_star_star  f**     ( r1 r2 -- r3 ) float-ext       f_star_star
 ""@i{r3} is @i{r1} raised to the @i{r2}th power.""  ""@i{r3} is @i{r1} raised to the @i{r2}th power.""
 r3 = pow(r1,r2);  r3 = pow(r1,r2);
   
 fnegate         r1 -- r2        float   f_negate  fnegate ( r1 -- r2 )    float   f_negate
 r2 = - r1;  r2 = - r1;
   
 fdrop           r --            float   f_drop  fdrop   ( r -- )                float   f_drop
   
 fdup            r -- r r        float   f_dupe  fdup    ( r -- r r )    float   f_dupe
   
 fswap           r1 r2 -- r2 r1  float   f_swap  fswap   ( r1 r2 -- r2 r1 )      float   f_swap
   
 fover           r1 r2 -- r1 r2 r1       float   f_over  fover   ( r1 r2 -- r1 r2 r1 )   float   f_over
   
 frot            r1 r2 r3 -- r2 r3 r1    float   f_rote  frot    ( r1 r2 r3 -- r2 r3 r1 )        float   f_rote
   
 fnip            r1 r2 -- r2     gforth  f_nip  fnip    ( r1 r2 -- r2 ) gforth  f_nip
   
 ftuck           r1 r2 -- r2 r1 r2       gforth  f_tuck  ftuck   ( r1 r2 -- r2 r1 r2 )   gforth  f_tuck
   
 float+          f_addr1 -- f_addr2      float   float_plus  float+  ( f_addr1 -- f_addr2 )  float   float_plus
 "" Increment @i{f-addr1} by the number of address units corresponding to the size of  "" Increment @i{f-addr1} by the number of address units corresponding to the size of
 one floating-point number, to give @i{f-addr2}.""  one floating-point number, to give @i{f-addr2}.""
 f_addr2 = f_addr1+1;  f_addr2 = f_addr1+1;
   
 floats          n1 -- n2        float  floats  ( n1 -- n2 )    float
 ""@i{n2} is the number of address units corresponding to @i{n1} floating-point numbers.""  ""@i{n2} is the number of address units corresponding to @i{n1} floating-point numbers.""
 n2 = n1*sizeof(Float);  n2 = n1*sizeof(Float);
   
 floor           r1 -- r2        float  floor   ( r1 -- r2 )    float
 ""Round towards the next smaller integral value, i.e., round toward negative infinity.""  ""Round towards the next smaller integral value, i.e., round toward negative infinity.""
 /* !! unclear wording */  /* !! unclear wording */
 r2 = floor(r1);  r2 = floor(r1);
   
 fround          r1 -- r2        float   f_round  fround  ( r1 -- r2 )    float   f_round
 ""Round to the nearest integral value.""  ""Round to the nearest integral value.""
 /* !! unclear wording */  /* !! unclear wording */
 #ifdef HAVE_RINT  #ifdef HAVE_RINT
Line 1845  r2 = floor(r1+0.5); Line 1839  r2 = floor(r1+0.5);
 /* !! This is not quite true to the rounding rules given in the standard */  /* !! This is not quite true to the rounding rules given in the standard */
 #endif  #endif
   
 fmax            r1 r2 -- r3     float   f_max  fmax    ( r1 r2 -- r3 ) float   f_max
 if (r1<r2)  if (r1<r2)
   r3 = r2;    r3 = r2;
 else  else
   r3 = r1;    r3 = r1;
   
 fmin            r1 r2 -- r3     float   f_min  fmin    ( r1 r2 -- r3 ) float   f_min
 if (r1<r2)  if (r1<r2)
   r3 = r1;    r3 = r1;
 else  else
   r3 = r2;    r3 = r2;
   
 represent               r c_addr u -- n f1 f2   float  represent       ( r c_addr u -- n f1 f2 )       float
 char *sig;  char *sig;
 int flag;  int flag;
 int decpt;  int decpt;
Line 1867  f1=FLAG(flag!=0); Line 1861  f1=FLAG(flag!=0);
 f2=FLAG(isdigit((unsigned)(sig[0]))!=0);  f2=FLAG(isdigit((unsigned)(sig[0]))!=0);
 memmove(c_addr,sig,u);  memmove(c_addr,sig,u);
   
 >float  c_addr u -- flag        float   to_float  >float  ( c_addr u -- flag )    float   to_float
 ""Attempt to convert the character string @i{c-addr u} to  ""Attempt to convert the character string @i{c-addr u} to
 internal floating-point representation. If the string  internal floating-point representation. If the string
 represents a valid floating-point number @i{r} is placed  represents a valid floating-point number @i{r} is placed
Line 1913  else if(*endconv=='d' || *endconv=='D') Line 1907  else if(*endconv=='d' || *endconv=='D')
      }       }
 }  }
   
 fabs            r1 -- r2        float-ext       f_abs  fabs    ( r1 -- r2 )    float-ext       f_abs
 r2 = fabs(r1);  r2 = fabs(r1);
   
 facos           r1 -- r2        float-ext       f_a_cos  facos   ( r1 -- r2 )    float-ext       f_a_cos
 r2 = acos(r1);  r2 = acos(r1);
   
 fasin           r1 -- r2        float-ext       f_a_sine  fasin   ( r1 -- r2 )    float-ext       f_a_sine
 r2 = asin(r1);  r2 = asin(r1);
   
 fatan           r1 -- r2        float-ext       f_a_tan  fatan   ( r1 -- r2 )    float-ext       f_a_tan
 r2 = atan(r1);  r2 = atan(r1);
   
 fatan2          r1 r2 -- r3     float-ext       f_a_tan_two  fatan2  ( r1 r2 -- r3 ) float-ext       f_a_tan_two
 ""@i{r1/r2}=tan(@i{r3}). ANS Forth does not require, but probably  ""@i{r1/r2}=tan(@i{r3}). ANS Forth does not require, but probably
 intends this to be the inverse of @code{fsincos}. In gforth it is.""  intends this to be the inverse of @code{fsincos}. In gforth it is.""
 r3 = atan2(r1,r2);  r3 = atan2(r1,r2);
   
 fcos            r1 -- r2        float-ext       f_cos  fcos    ( r1 -- r2 )    float-ext       f_cos
 r2 = cos(r1);  r2 = cos(r1);
   
 fexp            r1 -- r2        float-ext       f_e_x_p  fexp    ( r1 -- r2 )    float-ext       f_e_x_p
 r2 = exp(r1);  r2 = exp(r1);
   
 fexpm1          r1 -- r2        float-ext       f_e_x_p_m_one  fexpm1  ( r1 -- r2 )    float-ext       f_e_x_p_m_one
 ""@i{r2}=@i{e}**@i{r1}@minus{}1""  ""@i{r2}=@i{e}**@i{r1}@minus{}1""
 #ifdef HAVE_EXPM1  #ifdef HAVE_EXPM1
 extern double  extern double
Line 1949  r2 = expm1(r1); Line 1943  r2 = expm1(r1);
 r2 = exp(r1)-1.;  r2 = exp(r1)-1.;
 #endif  #endif
   
 fln             r1 -- r2        float-ext       f_l_n  fln     ( r1 -- r2 )    float-ext       f_l_n
 r2 = log(r1);  r2 = log(r1);
   
 flnp1           r1 -- r2        float-ext       f_l_n_p_one  flnp1   ( r1 -- r2 )    float-ext       f_l_n_p_one
 ""@i{r2}=ln(@i{r1}+1)""  ""@i{r2}=ln(@i{r1}+1)""
 #ifdef HAVE_LOG1P  #ifdef HAVE_LOG1P
 extern double  extern double
Line 1965  r2 = log1p(r1); Line 1959  r2 = log1p(r1);
 r2 = log(r1+1.);  r2 = log(r1+1.);
 #endif  #endif
   
 flog            r1 -- r2        float-ext       f_log  flog    ( r1 -- r2 )    float-ext       f_log
 ""The decimal logarithm.""  ""The decimal logarithm.""
 r2 = log10(r1);  r2 = log10(r1);
   
 falog           r1 -- r2        float-ext       f_a_log  falog   ( r1 -- r2 )    float-ext       f_a_log
 ""@i{r2}=10**@i{r1}""  ""@i{r2}=10**@i{r1}""
 extern double pow10(double);  extern double pow10(double);
 r2 = pow10(r1);  r2 = pow10(r1);
   
 fsin            r1 -- r2        float-ext       f_sine  fsin    ( r1 -- r2 )    float-ext       f_sine
 r2 = sin(r1);  r2 = sin(r1);
   
 fsincos         r1 -- r2 r3     float-ext       f_sine_cos  fsincos ( r1 -- r2 r3 ) float-ext       f_sine_cos
 ""@i{r2}=sin(@i{r1}), @i{r3}=cos(@i{r1})""  ""@i{r2}=sin(@i{r1}), @i{r3}=cos(@i{r1})""
 r2 = sin(r1);  r2 = sin(r1);
 r3 = cos(r1);  r3 = cos(r1);
   
 fsqrt           r1 -- r2        float-ext       f_square_root  fsqrt   ( r1 -- r2 )    float-ext       f_square_root
 r2 = sqrt(r1);  r2 = sqrt(r1);
   
 ftan            r1 -- r2        float-ext       f_tan  ftan    ( r1 -- r2 )    float-ext       f_tan
 r2 = tan(r1);  r2 = tan(r1);
 :  :
  fsincos f/ ;   fsincos f/ ;
   
 fsinh           r1 -- r2        float-ext       f_cinch  fsinh   ( r1 -- r2 )    float-ext       f_cinch
 r2 = sinh(r1);  r2 = sinh(r1);
 :  :
  fexpm1 fdup fdup 1. d>f f+ f/ f+ f2/ ;   fexpm1 fdup fdup 1. d>f f+ f/ f+ f2/ ;
   
 fcosh           r1 -- r2        float-ext       f_cosh  fcosh   ( r1 -- r2 )    float-ext       f_cosh
 r2 = cosh(r1);  r2 = cosh(r1);
 :  :
  fexp fdup 1/f f+ f2/ ;   fexp fdup 1/f f+ f2/ ;
   
 ftanh           r1 -- r2        float-ext       f_tan_h  ftanh   ( r1 -- r2 )    float-ext       f_tan_h
 r2 = tanh(r1);  r2 = tanh(r1);
 :  :
  f2* fexpm1 fdup 2. d>f f+ f/ ;   f2* fexpm1 fdup 2. d>f f+ f/ ;
   
 fasinh          r1 -- r2        float-ext       f_a_cinch  fasinh  ( r1 -- r2 )    float-ext       f_a_cinch
 r2 = asinh(r1);  r2 = asinh(r1);
 :  :
  fdup fdup f* 1. d>f f+ fsqrt f/ fatanh ;   fdup fdup f* 1. d>f f+ fsqrt f/ fatanh ;
   
 facosh          r1 -- r2        float-ext       f_a_cosh  facosh  ( r1 -- r2 )    float-ext       f_a_cosh
 r2 = acosh(r1);  r2 = acosh(r1);
 :  :
  fdup fdup f* 1. d>f f- fsqrt f+ fln ;   fdup fdup f* 1. d>f f- fsqrt f+ fln ;
   
 fatanh          r1 -- r2        float-ext       f_a_tan_h  fatanh  ( r1 -- r2 )    float-ext       f_a_tan_h
 r2 = atanh(r1);  r2 = atanh(r1);
 :  :
  fdup f0< >r fabs 1. d>f fover f- f/  f2* flnp1 f2/   fdup f0< >r fabs 1. d>f fover f- f/  f2* flnp1 f2/
  r> IF  fnegate  THEN ;   r> IF  fnegate  THEN ;
   
 sfloats         n1 -- n2        float-ext       s_floats  sfloats ( n1 -- n2 )    float-ext       s_floats
 ""@i{n2} is the number of address units corresponding to @i{n1}  ""@i{n2} is the number of address units corresponding to @i{n1}
 single-precision IEEE floating-point numbers.""  single-precision IEEE floating-point numbers.""
 n2 = n1*sizeof(SFloat);  n2 = n1*sizeof(SFloat);
   
 dfloats         n1 -- n2        float-ext       d_floats  dfloats ( n1 -- n2 )    float-ext       d_floats
 ""@i{n2} is the number of address units corresponding to @i{n1}  ""@i{n2} is the number of address units corresponding to @i{n1}
 double-precision IEEE floating-point numbers.""  double-precision IEEE floating-point numbers.""
 n2 = n1*sizeof(DFloat);  n2 = n1*sizeof(DFloat);
   
 sfaligned       c_addr -- sf_addr       float-ext       s_f_aligned  sfaligned       ( c_addr -- sf_addr )   float-ext       s_f_aligned
 "" @i{sf-addr} is the first single-float-aligned address greater  "" @i{sf-addr} is the first single-float-aligned address greater
 than or equal to @i{c-addr}.""  than or equal to @i{c-addr}.""
 sf_addr = (SFloat *)((((Cell)c_addr)+(sizeof(SFloat)-1))&(-sizeof(SFloat)));  sf_addr = (SFloat *)((((Cell)c_addr)+(sizeof(SFloat)-1))&(-sizeof(SFloat)));
 :  :
  [ 1 sfloats 1- ] Literal + [ -1 sfloats ] Literal and ;   [ 1 sfloats 1- ] Literal + [ -1 sfloats ] Literal and ;
   
 dfaligned       c_addr -- df_addr       float-ext       d_f_aligned  dfaligned       ( c_addr -- df_addr )   float-ext       d_f_aligned
 "" @i{df-addr} is the first double-float-aligned address greater  "" @i{df-addr} is the first double-float-aligned address greater
 than or equal to @i{c-addr}.""  than or equal to @i{c-addr}.""
 df_addr = (DFloat *)((((Cell)c_addr)+(sizeof(DFloat)-1))&(-sizeof(DFloat)));  df_addr = (DFloat *)((((Cell)c_addr)+(sizeof(DFloat)-1))&(-sizeof(DFloat)));
Line 2054  df_addr = (DFloat *)((((Cell)c_addr)+(si Line 2048  df_addr = (DFloat *)((((Cell)c_addr)+(si
 \+  \+
 \+glocals  \+glocals
   
 @local#         -- w    gforth  fetch_local_number  @local# ( -- w )        gforth  fetch_local_number
 w = *(Cell *)(lp+(Cell)NEXT_INST);  w = *(Cell *)(lp+(Cell)NEXT_INST);
 INC_IP(1);  INC_IP(1);
   
 @local0 -- w    new     fetch_local_zero  @local0 ( -- w )        new     fetch_local_zero
 w = *(Cell *)(lp+0*sizeof(Cell));  w = *(Cell *)(lp+0*sizeof(Cell));
   
 @local1 -- w    new     fetch_local_four  @local1 ( -- w )        new     fetch_local_four
 w = *(Cell *)(lp+1*sizeof(Cell));  w = *(Cell *)(lp+1*sizeof(Cell));
   
 @local2 -- w    new     fetch_local_eight  @local2 ( -- w )        new     fetch_local_eight
 w = *(Cell *)(lp+2*sizeof(Cell));  w = *(Cell *)(lp+2*sizeof(Cell));
   
 @local3 -- w    new     fetch_local_twelve  @local3 ( -- w )        new     fetch_local_twelve
 w = *(Cell *)(lp+3*sizeof(Cell));  w = *(Cell *)(lp+3*sizeof(Cell));
   
 \+floating  \+floating
   
 f@local#        -- r    gforth  f_fetch_local_number  f@local#        ( -- r )        gforth  f_fetch_local_number
 r = *(Float *)(lp+(Cell)NEXT_INST);  r = *(Float *)(lp+(Cell)NEXT_INST);
 INC_IP(1);  INC_IP(1);
   
 f@local0        -- r    new     f_fetch_local_zero  f@local0        ( -- r )        new     f_fetch_local_zero
 r = *(Float *)(lp+0*sizeof(Float));  r = *(Float *)(lp+0*sizeof(Float));
   
 f@local1        -- r    new     f_fetch_local_eight  f@local1        ( -- r )        new     f_fetch_local_eight
 r = *(Float *)(lp+1*sizeof(Float));  r = *(Float *)(lp+1*sizeof(Float));
   
 \+  \+
   
 laddr#          -- c_addr       gforth  laddr_number  laddr#  ( -- c_addr )   gforth  laddr_number
 /* this can also be used to implement lp@ */  /* this can also be used to implement lp@ */
 c_addr = (Char *)(lp+(Cell)NEXT_INST);  c_addr = (Char *)(lp+(Cell)NEXT_INST);
 INC_IP(1);  INC_IP(1);
   
 lp+!#   --      gforth  lp_plus_store_number  lp+!#   ( -- )  gforth  lp_plus_store_number
 ""used with negative immediate values it allocates memory on the  ""used with negative immediate values it allocates memory on the
 local stack, a positive immediate argument drops memory from the local  local stack, a positive immediate argument drops memory from the local
 stack""  stack""
 lp += (Cell)NEXT_INST;  lp += (Cell)NEXT_INST;
 INC_IP(1);  INC_IP(1);
   
 lp-     --      new     minus_four_lp_plus_store  lp-     ( -- )  new     minus_four_lp_plus_store
 lp += -sizeof(Cell);  lp += -sizeof(Cell);
   
 lp+     --      new     eight_lp_plus_store  lp+     ( -- )  new     eight_lp_plus_store
 lp += sizeof(Float);  lp += sizeof(Float);
   
 lp+2    --      new     sixteen_lp_plus_store  lp+2    ( -- )  new     sixteen_lp_plus_store
 lp += 2*sizeof(Float);  lp += 2*sizeof(Float);
   
 lp!     c_addr --       gforth  lp_store  lp!     ( c_addr -- )   gforth  lp_store
 lp = (Address)c_addr;  lp = (Address)c_addr;
   
 >l      w --    gforth  to_l  >l      ( w -- )        gforth  to_l
 lp -= sizeof(Cell);  lp -= sizeof(Cell);
 *(Cell *)lp = w;  *(Cell *)lp = w;
   
 \+floating  \+floating
   
 f>l     r --    gforth  f_to_l  f>l     ( r -- )        gforth  f_to_l
 lp -= sizeof(Float);  lp -= sizeof(Float);
 *(Float *)lp = r;  *(Float *)lp = r;
   
 fpick   u -- r          gforth  fpick   ( u -- r )              gforth
 r = fp[u+1]; /* +1, because update of fp happens before this fragment */  r = fp[u+1]; /* +1, because update of fp happens before this fragment */
 :  :
  floats fp@ + f@ ;   floats fp@ + f@ ;
Line 2147  define(argclist, Line 2141  define(argclist,
                `uploop(`_i', 1, $1, `format(`u%d, ', _i)', `format(`u%d', _i)')')')                 `uploop(`_i', 1, $1, `format(`u%d, ', _i)', `format(`u%d', _i)')')')
 \ icall(argnum)  \ icall(argnum)
 define(icall,  define(icall,
 `icall$1        argflist($1)u -- uret   gforth  `icall$1        ( argflist($1)u -- uret )       gforth
 uret = (SYSCALL(Cell(*)(argdlist($1)))u)(argclist($1));  uret = (SYSCALL(Cell(*)(argdlist($1)))u)(argclist($1));
   
 ')  ')
 define(fcall,  define(fcall,
 `fcall$1        argflist($1)u -- rret   gforth  `fcall$1        ( argflist($1)u -- rret )       gforth
 rret = (SYSCALL(Float(*)(argdlist($1)))u)(argclist($1));  rret = (SYSCALL(Float(*)(argdlist($1)))u)(argclist($1));
   
 ')  ')
   
 \ close ' to keep fontify happy  \ close ' to keep fontify happy
   
 open-lib        c_addr1 u1 -- u2        gforth  open_lib  open-lib        ( c_addr1 u1 -- u2 )    gforth  open_lib
 #if defined(HAVE_LIBDL) || defined(HAVE_DLOPEN)  #if defined(HAVE_LIBDL) || defined(HAVE_DLOPEN)
 #ifndef RTLD_GLOBAL  #ifndef RTLD_GLOBAL
 #define RTLD_GLOBAL 0  #define RTLD_GLOBAL 0
Line 2174  u2 = 0; Line 2168  u2 = 0;
 #  endif  #  endif
 #endif  #endif
   
 lib-sym c_addr1 u1 u2 -- u3     gforth  lib_sym  lib-sym ( c_addr1 u1 u2 -- u3 ) gforth  lib_sym
 #if defined(HAVE_LIBDL) || defined(HAVE_DLOPEN)  #if defined(HAVE_LIBDL) || defined(HAVE_DLOPEN)
 u3 = (UCell) dlsym((void*)u2,cstr(c_addr1, u1, 1));  u3 = (UCell) dlsym((void*)u2,cstr(c_addr1, u1, 1));
 #else  #else
Line 2193  fcall(20) Line 2187  fcall(20)
   
 \+  \+
   
 up!     a_addr --       gforth  up_store  up!     ( a_addr -- )   gforth  up_store
 UP=up=(char *)a_addr;  UP=up=(char *)a_addr;
 :  :
  up ! ;   up ! ;
 Variable UP  Variable UP
   
 wcall   u --    gforth  wcall   ( u -- )        gforth
 IF_FTOS(fp[0]=FTOS);  IF_FTOS(fp[0]=FTOS);
 FP=fp;  FP=fp;
 sp=(SYSCALL(Cell(*)(Cell *, void *))u)(sp, &FP);  sp=(SYSCALL(Cell(*)(Cell *, void *))u)(sp, &FP);
Line 2209  IF_FTOS(FTOS=fp[0]); Line 2203  IF_FTOS(FTOS=fp[0]);
   
 \+file  \+file
   
 open-dir        c_addr u -- wdirid wior gforth  open_dir  open-dir        ( c_addr u -- wdirid wior )     gforth  open_dir
 wdirid = (Cell)opendir(tilde_cstr(c_addr, u, 1));  wdirid = (Cell)opendir(tilde_cstr(c_addr, u, 1));
 wior =  IOR(wdirid == 0);  wior =  IOR(wdirid == 0);
   
 read-dir        c_addr u1 wdirid -- u2 flag wior        gforth  read_dir  read-dir        ( c_addr u1 wdirid -- u2 flag wior )    gforth  read_dir
 struct dirent * dent;  struct dirent * dent;
 dent = readdir((DIR *)wdirid);  dent = readdir((DIR *)wdirid);
 wior = 0;  wior = 0;
Line 2228  if(dent == NULL) { Line 2222  if(dent == NULL) {
   memmove(c_addr, dent->d_name, u2);    memmove(c_addr, dent->d_name, u2);
 }  }
   
 close-dir       wdirid -- wior  gforth  close_dir  close-dir       ( wdirid -- wior )      gforth  close_dir
 wior = IOR(closedir((DIR *)wdirid));  wior = IOR(closedir((DIR *)wdirid));
   
 filename-match  c_addr1 u1 c_addr2 u2 -- flag   gforth  match_file  filename-match  ( c_addr1 u1 c_addr2 u2 -- flag )       gforth  match_file
 char * string = cstr(c_addr1, u1, 1);  char * string = cstr(c_addr1, u1, 1);
 char * pattern = cstr(c_addr2, u2, 0);  char * pattern = cstr(c_addr2, u2, 0);
 flag = FLAG(!fnmatch(pattern, string, 0));  flag = FLAG(!fnmatch(pattern, string, 0));
   
 \+  \+
   
 newline -- c_addr u     gforth  newline ( -- c_addr u ) gforth
 ""String containing the newline sequence of the host OS""  ""String containing the newline sequence of the host OS""
 char newline[] = {  char newline[] = {
 #ifdef unix  #ifdef unix
Line 2249  char newline[] = { Line 2243  char newline[] = {
 };  };
 c_addr=newline;  c_addr=newline;
 u=sizeof(newline);  u=sizeof(newline);
   :
    "newline count ;
   Create "newline 1 c, $0A c,
   
   utime   ( -- dtime )    gforth
   ""Report the current time in microseconds since some epoch.""
   struct timeval time1;
   gettimeofday(&time1,NULL);
   dtime = timeval2us(&time1);
   
   cputime ( -- duser dsystem ) gforth
   ""duser and dsystem are the respective user- and system-level CPU
   times used since the start of the Forth system (excluding child
   processes), in microseconds (the granularity may be much larger,
   however).  On platforms without the getrusage call, it reports elapsed
   time (since some epoch) for duser and 0 for dsystem.""
   #ifdef HAVE_GETRUSAGE
   struct rusage usage;
   getrusage(RUSAGE_SELF, &usage);
   duser = timeval2us(&usage.ru_utime);
   dsystem = timeval2us(&usage.ru_stime);
   #else
   struct timeval time1;
   gettimeofday(&time1,NULL);
   duser = timeval2us(&time1);
   dsystem = (DCell)0;
   #endif
   
   v*      ( f_addr1 nstride1 f_addr2 nstride2 ucount -- r ) gforth v_star
   ""dot-product: r=v1*v2.  The first element of v1 is at f_addr1, the
   next at f_addr1+nstride1 and so on (similar for v2). Both vectors have
   ucount elements.""
   for (r=0.; ucount>0; ucount--) {
     r += *f_addr1 * *f_addr2;
     f_addr1 = (Float *)(((Address)f_addr1)+nstride1);
     f_addr2 = (Float *)(((Address)f_addr2)+nstride2);
   }
   
   faxpy   ( ra f_x nstridex f_y nstridey ucount -- )      gforth
   ""vy=ra*vx+vy""
   for (; ucount>0; ucount--) {
     *f_y += ra * *f_x;
     f_x = (Float *)(((Address)f_x)+nstridex);
     f_y = (Float *)(((Address)f_y)+nstridey);
   }

Removed from v.1.46  
changed lines
  Added in v.1.51


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