Diff for /gforth/prim between versions 1.145 and 1.278

version 1.145, 2003/10/09 14:15:19 version 1.278, 2012/09/18 15:21:08
Line 1 Line 1
 \ Gforth primitives  \ Gforth primitives
   
 \ Copyright (C) 1995,1996,1997,1998,2000,2003 Free Software Foundation, Inc.  \ Copyright (C) 1995,1996,1997,1998,2000,2003,2004,2005,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
   
 \ This file is part of Gforth.  \ This file is part of Gforth.
   
 \ Gforth is free software; you can redistribute it and/or  \ Gforth is free software; you can redistribute it and/or
 \ modify it under the terms of the GNU General Public License  \ modify it under the terms of the GNU General Public License
 \ as published by the Free Software Foundation; either version 2  \ as published by the Free Software Foundation, either version 3
 \ of the License, or (at your option) any later version.  \ of the License, or (at your option) any later version.
   
 \ This program is distributed in the hope that it will be useful,  \ This program is distributed in the hope that it will be useful,
Line 15 Line 15
 \ GNU General Public License for more details.  \ GNU General Public License for more details.
   
 \ 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, see http://www.gnu.org/licenses/.
 \ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.  
   
   
 \ WARNING: This file is processed by m4. Make sure your identifiers  \ WARNING: This file is processed by m4. Make sure your identifiers
Line 100 Line 99
 \E s" struct F83Name *" single data-stack type-prefix f83name  \E s" struct F83Name *" single data-stack type-prefix f83name
 \E s" struct Longname *" single data-stack type-prefix longname  \E s" struct Longname *" single data-stack type-prefix longname
 \E   \E 
   \E data-stack   stack-prefix S:
   \E fp-stack     stack-prefix F:
 \E return-stack stack-prefix R:  \E return-stack stack-prefix R:
 \E inst-stream  stack-prefix #  \E inst-stream  stack-prefix #
 \E   \E 
Line 107 Line 108
 \E store-optimization on  \E store-optimization on
 \E ' noop tail-nextp2 ! \ now INST_TAIL just stores, but does not jump  \E ' noop tail-nextp2 ! \ now INST_TAIL just stores, but does not jump
 \E  \E
 \E include-skipped-insts on \ static superinsts include cells for components  \E `include-skipped-insts' on \ static superinsts include cells for components
 \E                          \ useful for dynamic programming and  \E                            \ useful for dynamic programming and
 \E                          \ superinsts across entry points  \E                            \ superinsts across entry points
   
 \   \ 
 \   \ 
Line 138 Line 139
   
 \ Stack caching setup  \ Stack caching setup
   
 \E register IPTOS Cell  ifdef(`STACK_CACHE_FILE', `include(STACK_CACHE_FILE)', `include(cache0.vmg)')
 \E register spTOS Cell  
 \E register sp1 Cell  
 \E register sp2 Cell  
 \E register sp3 Cell  
   
 \E create IPregs IPTOS ,  
 \E create regs sp2 , sp1 , spTOS ,  
   
 \E IPregs 1 0 stack-state IPss1  
 \E regs 3 cells + 0 0 stack-state ss0  
 \E regs 2 cells + 1  0 stack-state ss1  
 \E regs 1 cells + 2  1 stack-state ss2  
 \E regs 0 cells + 3  2 stack-state ss3  
   
 \ the first of these is the default state  
 \E state S0  
 \E state S1  
 \E state S2  
 \E state S3  
   
 \E ss0 data-stack S0 set-ss  
 \E ss1 data-stack S1 set-ss  
 \E ss2 data-stack S2 set-ss  
 \E ss3 data-stack S3 set-ss  
   
 \E IPss1 inst-stream S0 set-ss  
 \E IPss1 inst-stream S1 set-ss  
 \E IPss1 inst-stream S2 set-ss  
 \E IPss1 inst-stream S3 set-ss  
   
 \E data-stack to cache-stack  
 \E here 4 cache-states 2! s0 , s1 , s2 , s3 ,  
   
 \ !! the following should be automatic  
 \E S0 to state-default  
 \E state-default to state-in  
 \E state-default to state-out  
   
 \ these m4 macros would collide with identifiers  \ these m4 macros would collide with identifiers
 undefine(`index')  undefine(`index')
Line 189  undefine(`symbols') Line 153  undefine(`symbols')
   
 (docol) ( -- R:a_retaddr )      gforth-internal paren_docol  (docol) ( -- R:a_retaddr )      gforth-internal paren_docol
 ""run-time routine for colon definitions""  ""run-time routine for colon definitions""
   #ifdef NO_IP
   a_retaddr = next_code;
   INST_TAIL;
   goto **(Label *)PFA(CFA);
   #else /* !defined(NO_IP) */
 a_retaddr = (Cell *)IP;  a_retaddr = (Cell *)IP;
 SET_IP((Xt *)PFA(CFA));  SET_IP((Xt *)PFA(CFA));
   #endif /* !defined(NO_IP) */
   
 (docon) ( -- w )        gforth-internal paren_docon  (docon) ( -- w )        gforth-internal paren_docon
 ""run-time routine for constants""  ""run-time routine for constants""
 w = *(Cell *)PFA(CFA);  w = *(Cell *)PFA(CFA);
   #ifdef NO_IP
   INST_TAIL;
   goto *next_code;
   #endif /* defined(NO_IP) */
   
 (dovar) ( -- a_body )   gforth-internal paren_dovar  (dovar) ( -- a_body )   gforth-internal paren_dovar
 ""run-time routine for variables and CREATEd words""  ""run-time routine for variables and CREATEd words""
 a_body = PFA(CFA);  a_body = PFA(CFA);
   #ifdef NO_IP
   INST_TAIL;
   goto *next_code;
   #endif /* defined(NO_IP) */
   
 (douser) ( -- a_user )  gforth-internal paren_douser  (douser) ( -- a_user )  gforth-internal paren_douser
 ""run-time routine for constants""  ""run-time routine for constants""
 a_user = (Cell *)(up+*(Cell *)PFA(CFA));  a_user = (Cell *)(up+*(Cell *)PFA(CFA));
   #ifdef NO_IP
   INST_TAIL;
   goto *next_code;
   #endif /* defined(NO_IP) */
   
 (dodefer) ( -- )        gforth-internal paren_dodefer  (dodefer) ( -- )        gforth-internal paren_dodefer
 ""run-time routine for deferred words""  ""run-time routine for deferred words""
   #ifndef NO_IP
 ip=IP; /* undo any ip updating that may have been performed by NEXT_P0 */  ip=IP; /* undo any ip updating that may have been performed by NEXT_P0 */
   #endif /* !defined(NO_IP) */
 SUPER_END; /* !! probably unnecessary and may lead to measurement errors */  SUPER_END; /* !! probably unnecessary and may lead to measurement errors */
 EXEC(*(Xt *)PFA(CFA));  VM_JUMP(EXEC1(*(Xt *)PFA(CFA)));
   
 (dofield) ( n1 -- n2 )  gforth-internal paren_field  (dofield) ( n1 -- n2 )  gforth-internal paren_field
 ""run-time routine for fields""  ""run-time routine for fields""
 n2 = n1 + *(Cell *)PFA(CFA);  n2 = n1 + *(Cell *)PFA(CFA);
   #ifdef NO_IP
   INST_TAIL;
   goto *next_code;
   #endif /* defined(NO_IP) */
   
   (dovalue) ( -- w )      gforth-internal paren_doval
   ""run-time routine for constants""
   w = *(Cell *)PFA(CFA);
   #ifdef NO_IP
   INST_TAIL;
   goto *next_code;
   #endif /* defined(NO_IP) */
   
 (dodoes) ( -- a_body R:a_retaddr )      gforth-internal paren_dodoes  (dodoes) ( -- a_body R:a_retaddr )      gforth-internal paren_dodoes
 ""run-time routine for @code{does>}-defined words""  ""run-time routine for @code{does>}-defined words""
   #ifdef NO_IP
   a_retaddr = next_code;
   a_body = PFA(CFA);
   INST_TAIL;
   #ifdef DEBUG
   fprintf(stderr, "dodoes to %x, push %x\n", a_retaddr, a_body);
   #endif
   goto **(Label *)DOES_CODE1(CFA);
   #else /* !defined(NO_IP) */
 a_retaddr = (Cell *)IP;  a_retaddr = (Cell *)IP;
 a_body = PFA(CFA);  a_body = PFA(CFA);
   #ifdef DEBUG
   fprintf(stderr, "dodoes to %x, push %x\n", a_retaddr, a_body);
   #endif
 SET_IP(DOES_CODE1(CFA));  SET_IP(DOES_CODE1(CFA));
   #endif /* !defined(NO_IP) */
   
   (doabicode) ( ... -- ...)       gforth-internal paren_doabicode
   ""run-time routine for @code{ABI-code} definitions""
   abifunc *f = (abifunc *)PFA(CFA);
   Float *fp_mem = fp;
   sp = (*f)(sp, &fp_mem);
   fp = fp_mem;
   #ifdef NO_IP
   INST_TAIL;
   goto *next_code;
   #endif /* defined(NO_IP) */
   
 (does-handler) ( -- )   gforth-internal paren_does_handler  (do;abicode) ( ... -- ... ) gforth-internal paren_do_semicolon_abi_code
 ""just a slot to have an encoding for the DOESJUMP,   ""run-time routine for @code{;abi-code}-defined words""
 which is no longer used anyway (!! eliminate this)""  Float *fp_mem = fp;
   Address body = (Address)PFA(CFA);
   semiabifunc *f = (semiabifunc *)DOES_CODE1(CFA);
   sp = (*f)(sp, &fp_mem, body);
   fp = fp_mem;
   #ifdef NO_IP
   INST_TAIL;
   goto *next_code;
   #endif /* defined(NO_IP) */
   
 \F [endif]  \F [endif]
   
Line 235  noop ( -- )  gforth Line 263  noop ( -- )  gforth
 call    ( #a_callee -- R:a_retaddr )    new  call    ( #a_callee -- R:a_retaddr )    new
 ""Call callee (a variant of docol with inline argument).""  ""Call callee (a variant of docol with inline argument).""
 #ifdef NO_IP  #ifdef NO_IP
   assert(0);
 INST_TAIL;  INST_TAIL;
 JUMP(a_callee);  JUMP(a_callee);
 #else  #else
Line 251  SET_IP((Xt *)a_callee); Line 280  SET_IP((Xt *)a_callee);
   
 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}.""
   #ifdef DEBUG
   fprintf(stderr, "execute %08x\n", xt);
   #endif
 #ifndef NO_IP  #ifndef NO_IP
 ip=IP;  ip=IP;
 #endif  #endif
 IF_spTOS(spTOS = sp[0]);  
 SUPER_END;  SUPER_END;
 EXEC(xt);  VM_JUMP(EXEC1(xt));
   
 perform ( a_addr -- )   gforth  perform ( a_addr -- )   gforth
 ""@code{@@ execute}.""  ""@code{@@ execute}.""
Line 264  perform ( a_addr -- ) gforth Line 295  perform ( a_addr -- ) gforth
 #ifndef NO_IP  #ifndef NO_IP
 ip=IP;  ip=IP;
 #endif  #endif
 IF_spTOS(spTOS = sp[0]);  
 SUPER_END;  SUPER_END;
 EXEC(*(Xt *)a_addr);  VM_JUMP(EXEC1(*(Xt *)a_addr));
 :  :
  @ execute ;   @ execute ;
   
Line 289  lit-perform ( #a_addr -- ) new lit_perfo Line 319  lit-perform ( #a_addr -- ) new lit_perfo
 ip=IP;  ip=IP;
 #endif  #endif
 SUPER_END;  SUPER_END;
 EXEC(*(Xt *)a_addr);  VM_JUMP(EXEC1(*(Xt *)a_addr));
   
 does-exec ( #a_cfa -- R:nest a_pfa )    new     does_exec  does-exec ( #a_cfa -- R:nest a_pfa )    new     does_exec
 #ifdef NO_IP  #ifdef NO_IP
Line 298  assert(0); Line 328  assert(0);
 #else  #else
 a_pfa = PFA(a_cfa);  a_pfa = PFA(a_cfa);
 nest = (Cell)IP;  nest = (Cell)IP;
 IF_spTOS(spTOS = sp[0]);  
 #ifdef DEBUG  #ifdef DEBUG
     {      {
       CFA_TO_NAME(a_cfa);        CFA_TO_NAME(a_cfa);
Line 344  $5 #ifdef NO_IP Line 373  $5 #ifdef NO_IP
 JUMP(a_target);  JUMP(a_target);
 #else  #else
 SET_IP((Xt *)a_target);  SET_IP((Xt *)a_target);
 INST_TAIL; NEXT_P2;  ifelse(condbranch_opt,`1',`INST_TAIL; NEXT_P2;',`/* condbranch_opt=0 */')
 #endif  #endif
 }  }
 SUPER_CONTINUE;  ifelse(condbranch_opt,`1',`SUPER_CONTINUE;',`/* condbranch_opt=0 */')
 $6  $6
   
 \+glocals  \+glocals
Line 361  $5 lp += nlocals; Line 390  $5 lp += nlocals;
 JUMP(a_target);  JUMP(a_target);
 #else  #else
 SET_IP((Xt *)a_target);  SET_IP((Xt *)a_target);
 INST_TAIL; NEXT_P2;  ifelse(condbranch_opt,`1',`INST_TAIL; NEXT_P2;',`/* condbranch_opt=0 */')
 #endif  #endif
 }  }
 SUPER_CONTINUE;  ifelse(condbranch_opt,`1',`SUPER_CONTINUE;',`/* condbranch_opt=0 */')
   
 \+  \+
 )  )
Line 382  condbranch(?branch,f --,f83 question_bra Line 411  condbranch(?branch,f --,f83 question_bra
   
 \+xconds  \+xconds
   
 ?dup-?branch    ( #a_target f -- f )    new     question_dupe_question_branch  ?dup-?branch    ( #a_target f -- S:... )        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++;  
   IF_spTOS(spTOS = sp[0]);  
 #ifdef NO_IP  #ifdef NO_IP
 INST_TAIL;  INST_TAIL;
 JUMP(a_target);  JUMP(a_target);
 #else  #else
 SET_IP((Xt *)a_target);  SET_IP((Xt *)a_target);
   INST_TAIL; NEXT_P2;  
 #endif  #endif
   } else {
   sp--;
   sp[0]=f;
 }  }
 SUPER_CONTINUE;  
   
 ?dup-0=-?branch ( #a_target f -- ) new  question_dupe_zero_equals_question_branch  ?dup-0=-?branch ( #a_target f -- S:... ) 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  
 effect ( f -- ) and correcting for it in the branch-taken case costs a  
 few cycles in that case, but is easy to convert to a CONDBRANCH  
 invocation */  
 if (f!=0) {  if (f!=0) {
   sp--;    sp--;
     sp[0]=f;
 #ifdef NO_IP  #ifdef NO_IP
   JUMP(a_target);    JUMP(a_target);
 #else  #else
   SET_IP((Xt *)a_target);    SET_IP((Xt *)a_target);
   NEXT;  
 #endif  #endif
 }  }
 SUPER_CONTINUE;  
   
 \+  \+
 \fhas? skiploopprims 0= [IF]  \fhas? skiploopprims 0= [IF]
Line 438  condbranch((+loop),n R:nlimit R:n1 -- R: Line 461  condbranch((+loop),n R:nlimit R:n1 -- R:
 /* dependent upon two's complement arithmetic */  /* dependent upon two's complement arithmetic */
 Cell olddiff = n1-nlimit;  Cell olddiff = n1-nlimit;
 n2=n1+n;          n2=n1+n;        
 ,if ((olddiff^(olddiff+n))>=0   /* the limit is not crossed */  ,if (((olddiff^(olddiff+n))    /* the limit is not crossed */
     || (olddiff^n)>=0          /* it is a wrap-around effect */) {       &(olddiff^n))             /* OR it is a wrap-around effect */
       >=0) { /* & is used to avoid having two branches for gforth-native */
 ,:  ,:
  r> swap   r> swap
  r> r> 2dup - >r   r> r> 2dup - >r
Line 468  if (n<0) { Line 492  if (n<0) {
     newdiff = -newdiff;      newdiff = -newdiff;
 }  }
 n2=n1+n;  n2=n1+n;
 ,if (diff>=0 || newdiff<0) {  ,if (((~diff)|newdiff)<0) { /* use | to avoid two branches for gforth-native */
 ,)  ,)
   
 \+  \+
Line 492  if (nstart == nlimit) { Line 516  if (nstart == nlimit) {
     JUMP(a_target);      JUMP(a_target);
 #else  #else
     SET_IP((Xt *)a_target);      SET_IP((Xt *)a_target);
     INST_TAIL; NEXT_P2;  
 #endif  #endif
 }  }
 SUPER_CONTINUE;  
 :  :
   2dup =    2dup =
   IF   r> swap rot >r >r    IF   r> swap rot >r >r
Line 515  if (nstart >= nlimit) { Line 537  if (nstart >= nlimit) {
     JUMP(a_target);      JUMP(a_target);
 #else  #else
     SET_IP((Xt *)a_target);      SET_IP((Xt *)a_target);
     INST_TAIL; NEXT_P2;  
 #endif  #endif
 }  }
 SUPER_CONTINUE;  
 :  :
  swap 2dup   swap 2dup
  r> swap >r swap >r   r> swap >r swap >r
Line 538  if (ustart >= ulimit) { Line 558  if (ustart >= ulimit) {
 JUMP(a_target);  JUMP(a_target);
 #else  #else
 SET_IP((Xt *)a_target);  SET_IP((Xt *)a_target);
 INST_TAIL; NEXT_P2;  
 #endif  #endif
 }  }
 SUPER_CONTINUE;  
 :  :
  swap 2dup   swap 2dup
  r> swap >r swap >r   r> swap >r swap >r
Line 561  if (nstart <= nlimit) { Line 579  if (nstart <= nlimit) {
 JUMP(a_target);  JUMP(a_target);
 #else  #else
 SET_IP((Xt *)a_target);  SET_IP((Xt *)a_target);
 INST_TAIL; NEXT_P2;  
 #endif  #endif
 }  }
 SUPER_CONTINUE;  
 :  :
  swap 2dup   swap 2dup
  r> swap >r swap >r   r> swap >r swap >r
Line 584  if (ustart <= ulimit) { Line 600  if (ustart <= ulimit) {
 JUMP(a_target);  JUMP(a_target);
 #else  #else
 SET_IP((Xt *)a_target);  SET_IP((Xt *)a_target);
 INST_TAIL; NEXT_P2;  
 #endif  #endif
 }  }
 SUPER_CONTINUE;  
 :  :
  swap 2dup   swap 2dup
  r> swap >r swap >r   r> swap >r swap >r
Line 598  SUPER_CONTINUE; Line 612  SUPER_CONTINUE;
      cell+       cell+
  THEN  >r ;   THEN  >r ;
   
   (try1)  ( ... a_oldhandler a_recovery -- R:a_recovery R:a_sp R:f_fp R:c_lp R:a_oldhandler a_newhandler ) gforth paren_try1
   a_sp = sp-1;
   f_fp = fp;
   c_lp = lp;
   a_newhandler = rp-5;
   
   (throw1) ( ... wball a_handler -- ... wball ) gforth paren_throw1
   rp = a_handler;
   lp = (Address)rp[1];
   fp = (Float *)rp[2];
   sp = (Cell *)rp[3];
   #ifndef NO_IP
   ip=IP;
   #endif
   SUPER_END;
   VM_JUMP(EXEC1(*(Xt *)rp[4]));
     
   
 \+  \+
   
 \ don't make any assumptions where the return stack is!!  \ don't make any assumptions where the return stack is!!
Line 614  i' ( R:w R:w2 -- R:w R:w2 w )  gforth  i Line 646  i' ( R:w R:w2 -- R:w R:w2 w )  gforth  i
   r> r> r> dup itmp ! >r >r >r itmp @ ;    r> r> r> dup itmp ! >r >r >r itmp @ ;
 variable itmp  variable itmp
   
 j       ( R:n R:d1 -- n R:n R:d1 )              core  j       ( R:w R:w1 R:w2 -- w R:w R:w1 R:w2 )    core
 :  :
 \ 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       ( R:n R:d1 R:d2 -- n R:n R:d1 R:d2 )            gforth  k       ( R:w R:w1 R:w2 R:w3 R:w4 -- w R:w R:w1 R:w2 R:w3 R:w4 )        gforth
 :  :
 \ rp@ [ 5 cells ] Literal + @ ;  \ rp@ [ 5 cells ] Literal + @ ;
   r> r> r> r> r> r> dup itmp ! >r >r >r >r >r >r itmp @ ;    r> r> r> r> r> r> dup itmp ! >r >r >r >r >r >r itmp @ ;
Line 707  c2 = toupper(c1); Line 739  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 - ;
   
   capscompare     ( c_addr1 u1 c_addr2 u2 -- n )  gforth
   ""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}
   is 1. Currently this is based on the machine's character
   comparison. In the future, this may change to consider the current
   locale and its collation order.""
   /* close ' to keep fontify happy */ 
   n = capscompare(c_addr1, u1, c_addr2, u2);
   
 /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.""
Line 727  n = n1+n2; Line 768  n = n1+n2;
 \ lit+ / lit_plus = lit +  \ lit+ / lit_plus = lit +
   
 lit+    ( n1 #n2 -- n )         new     lit_plus  lit+    ( n1 #n2 -- n )         new     lit_plus
   #ifdef DEBUG
   fprintf(stderr, "lit+ %08x\n", n2);
   #endif
 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
Line 788  n = n1*n2; Line 832  n = n1*n2;
   
 /       ( n1 n2 -- n )          core    slash  /       ( n1 n2 -- n )          core    slash
 n = n1/n2;  n = n1/n2;
   if (CHECK_DIVISION_SW && n2 == 0)
     throw(BALL_DIVZERO);
   if (CHECK_DIVISION_SW && n2 == -1 && n1 == CELL_MIN)
     throw(BALL_RESULTRANGE);
   if (FLOORED_DIV && ((n1^n2) < 0) && (n1%n2 != 0))
     n--;
 :  :
  /mod nip ;   /mod nip ;
   
 mod     ( n1 n2 -- n )          core  mod     ( n1 n2 -- n )          core
 n = n1%n2;  n = n1%n2;
   if (CHECK_DIVISION_SW && n2 == 0)
     throw(BALL_DIVZERO);
   if (CHECK_DIVISION_SW && n2 == -1 && n1 == CELL_MIN)
     throw(BALL_RESULTRANGE);
   if(FLOORED_DIV && ((n1^n2) < 0) && n!=0) n += 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! */
   if (CHECK_DIVISION_SW && n2 == 0)
     throw(BALL_DIVZERO);
   if (CHECK_DIVISION_SW && n2 == -1 && n1 == CELL_MIN)
     throw(BALL_RESULTRANGE);
   if (FLOORED_DIV && ((n1^n2) < 0) && n3!=0) {
     n4--;
     n3+=n2;
   }
 :  :
  >r s>d r> fm/mod ;   >r s>d r> fm/mod ;
   
   */mod   ( n1 n2 n3 -- n4 n5 )   core    star_slash_mod
   ""n1*n2=n3*n5+n4, with the intermediate result (n1*n2) being double.""
   #ifdef BUGGY_LL_MUL
   DCell d = mmul(n1,n2);
   #else
   DCell d = (DCell)n1 * (DCell)n2;
   #endif
   #ifdef ASM_SM_SLASH_REM
   ASM_SM_SLASH_REM(DLO(d), DHI(d), n3, n4, n5);
   if (FLOORED_DIV && ((DHI(d)^n3)<0) && n4!=0) {
     if (CHECK_DIVISION && n5 == CELL_MIN)
       throw(BALL_RESULTRANGE);
     n5--;
     n4+=n3;
   }
   #else
   DCell r = FLOORED_DIV ? fmdiv(d,n3) : smdiv(d,n3);
   n4=DHI(r);
   n5=DLO(r);
   #endif
   :
    >r m* r> fm/mod ;
   
   */      ( n1 n2 n3 -- n4 )      core    star_slash
   ""n4=(n1*n2)/n3, with the intermediate result being double.""
   #ifdef BUGGY_LL_MUL
   DCell d = mmul(n1,n2);
   #else
   DCell d = (DCell)n1 * (DCell)n2;
   #endif
   #ifdef ASM_SM_SLASH_REM
   Cell remainder;
   ASM_SM_SLASH_REM(DLO(d), DHI(d), n3, remainder, n4);
   if (FLOORED_DIV && ((DHI(d)^n3)<0) && remainder!=0) {
     if (CHECK_DIVISION && n4 == CELL_MIN)
       throw(BALL_RESULTRANGE);
     n4--;
   }
   #else
   DCell r = FLOORED_DIV ? fmdiv(d,n3) : smdiv(d,n3);
   n4=DLO(r);
   #endif
   :
    */mod nip ;
   
 2*      ( n1 -- n2 )            core            two_star  2*      ( n1 -- n2 )            core            two_star
 ""Shift left by 1; also works on unsigned numbers""  ""Shift left by 1; also works on unsigned numbers""
 n2 = 2*n1;  n2 = 2*n1;
Line 814  division by 2 (note that @code{/} not ne Line 922  division by 2 (note that @code{/} not ne
 n2 = n1>>1;  n2 = n1>>1;
 :  :
  dup MINI and IF 1 ELSE 0 THEN   dup MINI and IF 1 ELSE 0 THEN
  [ bits/byte cell * 1- ] literal    [ bits/char cell * 1- ] literal 
  0 DO 2* swap dup 2* >r MINI and    0 DO 2* swap dup 2* >r MINI and 
      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 ASM_SM_SLASH_REM
 DCell r = fmdiv(d1,n1);  ASM_SM_SLASH_REM(DLO(d1), DHI(d1), n1, n2, n3);
 n2=r.hi;  if (((DHI(d1)^n1)<0) && n2!=0) {
 n3=r.lo;    if (CHECK_DIVISION && n3 == CELL_MIN)
 #else      throw(BALL_RESULTRANGE);
 /* assumes that the processor uses either floored or symmetric division */  
 n3 = d1/n1;  
 n2 = d1%n1;  
 /* note that this 1%-3>0 is optimized by the compiler */  
 if (1%-3>0 && (d1<0) != (n1<0) && n2!=0) {  
   n3--;    n3--;
   n2+=n1;    n2+=n1;
 }  }
 #endif  #else /* !defined(ASM_SM_SLASH_REM) */
   DCell r = fmdiv(d1,n1);
   n2=DHI(r);
   n3=DLO(r);
   #endif /* !defined(ASM_SM_SLASH_REM) */
 :  :
  dup >r dup 0< IF  negate >r dnegate r>  THEN   dup >r dup 0< IF  negate >r dnegate r>  THEN
  over       0< IF  tuck + swap  THEN   over       0< IF  tuck + swap  THEN
Line 843  if (1%-3>0 && (d1<0) != (n1<0) && n2!=0) Line 950  if (1%-3>0 && (d1<0) != (n1<0) && n2!=0)
   
 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 ASM_SM_SLASH_REM
   ASM_SM_SLASH_REM(DLO(d1), DHI(d1), n1, n2, n3);
   #else /* !defined(ASM_SM_SLASH_REM) */
 DCell r = smdiv(d1,n1);  DCell r = smdiv(d1,n1);
 n2=r.hi;  n2=DHI(r);
 n3=r.lo;  n3=DLO(r);
 #else  #endif /* !defined(ASM_SM_SLASH_REM) */
 /* assumes that the processor uses either floored or symmetric division */  
 n3 = d1/n1;  
 n2 = d1%n1;  
 /* note that this 1%-3<0 is optimized by the compiler */  
 if (1%-3<0 && (d1<0) != (n1<0) && n2!=0) {  
   n3++;  
   n2-=n1;  
 }  
 #endif  
 :  :
  over >r dup >r abs -rot   over >r dup >r abs -rot
  dabs rot um/mod   dabs rot um/mod
Line 864  if (1%-3<0 && (d1<0) != (n1<0) && n2!=0) Line 964  if (1%-3<0 && (d1<0) != (n1<0) && n2!=0)
  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_LL_MUL
 d = mmul(n1,n2);  d = mmul(n1,n2);
 #else  #else
 d = (DCell)n1 * (DCell)n2;  d = (DCell)n1 * (DCell)n2;
Line 876  d = (DCell)n1 * (DCell)n2; Line 976  d = (DCell)n1 * (DCell)n2;
   
 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_LL_MUL
 ud = ummul(u1,u2);  ud = ummul(u1,u2);
 #else  #else
 ud = (UDCell)u1 * (UDCell)u2;  ud = (UDCell)u1 * (UDCell)u2;
Line 892  ud = (UDCell)u1 * (UDCell)u2; Line 992  ud = (UDCell)u1 * (UDCell)u2;
   
 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 ASM_UM_SLASH_MOD
   ASM_UM_SLASH_MOD(DLO(ud), DHI(ud), u1, u2, u3);
   #else /* !defined(ASM_UM_SLASH_MOD) */
 UDCell r = umdiv(ud,u1);  UDCell r = umdiv(ud,u1);
 u2=r.hi;  u2=DHI(r);
 u3=r.lo;  u3=DLO(r);
 #else  #endif /* !defined(ASM_UM_SLASH_MOD) */
 u3 = ud/u1;  
 u2 = ud%u1;  
 #endif  
 :  :
    0 swap [ 8 cells 1 + ] literal 0     0 swap [ 8 cells 1 + ] literal 0
    ?DO /modstep     ?DO /modstep
Line 911  u2 = ud%u1; Line 1010  u2 = ud%u1;
    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_LL_ADD
 d2.lo = d1.lo+n;  DLO_IS(d2, DLO(d1)+n);
 d2.hi = d1.hi - (n<0) + (d2.lo<d1.lo);  DHI_IS(d2, DHI(d1) - (n<0) + (DLO(d2)<DLO(d1)));
 #else  #else
 d2 = d1+n;  d2 = d1+n;
 #endif  #endif
Line 921  d2 = d1+n; Line 1020  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_LL_ADD
 d.lo = d1.lo+d2.lo;  DLO_IS(d, DLO(d1) + DLO(d2));
 d.hi = d1.hi + d2.hi + (d.lo<d1.lo);  DHI_IS(d, DHI(d1) + DHI(d2) + (d.lo<DLO(d1)));
 #else  #else
 d = d1+d2;  d = d1+d2;
 #endif  #endif
Line 931  d = d1+d2; Line 1030  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_LL_ADD
 d.lo = d1.lo - d2.lo;  DLO_IS(d, DLO(d1) - DLO(d2));
 d.hi = d1.hi-d2.hi-(d1.lo<d2.lo);  DHI_IS(d, DHI(d1)-DHI(d2)-(DLO(d1)<DLO(d2)));
 #else  #else
 d = d1-d2;  d = d1-d2;
 #endif  #endif
Line 942  d = d1-d2; Line 1041  d = d1-d2;
   
 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_LL_ADD
 d2 = dnegate(d1);  d2 = dnegate(d1);
 #else  #else
 d2 = -d1;  d2 = -d1;
Line 952  d2 = -d1; Line 1051  d2 = -d1;
   
 d2*     ( d1 -- d2 )            double          d_two_star  d2*     ( d1 -- d2 )            double          d_two_star
 ""Shift left by 1; also works on unsigned numbers""  ""Shift left by 1; also works on unsigned numbers""
 #ifdef BUGGY_LONG_LONG  d2 = DLSHIFT(d1,1);
 d2.lo = d1.lo<<1;  
 d2.hi = (d1.hi<<1) | (d1.lo>>(CELL_BITS-1));  
 #else  
 d2 = 2*d1;  
 #endif  
 :  :
  2dup d+ ;   2dup d+ ;
   
 d2/     ( d1 -- d2 )            double          d_two_slash  d2/     ( d1 -- d2 )            double          d_two_slash
 ""Arithmetic shift right by 1.  For signed numbers this is a floored  ""Arithmetic shift right by 1.  For signed numbers this is a floored
 division by 2.""  division by 2.""
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LL_SHIFT
 d2.hi = d1.hi>>1;  DHI_IS(d2, DHI(d1)>>1);
 d2.lo= (d1.lo>>1) | (d1.hi<<(CELL_BITS-1));  DLO_IS(d2, (DLO(d1)>>1) | (DHI(d1)<<(CELL_BITS-1)));
 #else  #else
 d2 = d1>>1;  d2 = d1>>1;
 #endif  #endif
Line 992  w2 = ~w1; Line 1086  w2 = ~w1;
   
 rshift  ( u1 n -- u2 )          core    r_shift  rshift  ( u1 n -- u2 )          core    r_shift
 ""Logical shift right by @i{n} bits.""  ""Logical shift right by @i{n} bits.""
   u2 = u1>>n;  #ifdef BROKEN_SHIFT
     u2 = rshift(u1, n);
   #else
     u2 = u1 >> n;
   #endif
 :  :
     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;  #ifdef BROKEN_SHIFT
     u2 = lshift(u1, n);
   #else
     u2 = u1 << n;
   #endif
 :  :
     0 ?DO 2* LOOP ;      0 ?DO 2* LOOP ;
   
   umax    ( u1 u2 -- u )  core
   if (u1<u2)
     u = u2;
   else
     u = u1;
   :
    2dup u> select ;
   
   umin    ( u1 u2 -- u )  core
   if (u1<u2)
     u = u1;
   else
     u = u2;
   :
    2dup u< select ;
   
   mux   ( u1 u2 u3 -- u )    gforth
   ""multiplex @i{u1} for 1 bits in @i{u3}, @i{u2} for 0 bits in @i{u3} into @i{u}""
   u = (u3 & u1) | (~u3 & u2);
   :
    tuck and >r invert and r> ;
   
   select ( u1 u2 f -- u )    gforth
   ""select @i{u1} if @i{f} is true, @i{u2} if false.""
   u = f ? u1 : u2;
   :
    IF swap THEN nip ;
   
 \g compare  \g compare
   
 \ comparisons(prefix, args, prefix, arg1, arg2, wordsets...)  \ comparisons(prefix, args, prefix, arg1, arg2, wordsets...)
Line 1061  comparisons(u, u1 u2, u_, u1, u2, gforth Line 1191  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_LL_CMP
 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_LL_CMP
 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_LL_CMP
 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_LL_CMP
 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_LL_CMP
 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_LL_CMP
 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);
Line 1130  useraddr ( #u -- a_addr ) new Line 1260  useraddr ( #u -- a_addr ) new
 a_addr = (Cell *)(up+u);  a_addr = (Cell *)(up+u);
   
 up!     ( a_addr -- )   gforth  up_store  up!     ( a_addr -- )   gforth  up_store
 UP=up=(char *)a_addr;  gforth_UP=up=(Address)a_addr;
 :  :
  up ! ;   up ! ;
 Variable UP  Variable UP
   
 sp@     ( -- a_addr )           gforth          sp_fetch  sp@     ( S:... -- a_addr )             gforth          sp_fetch
 a_addr = sp+1;  a_addr = sp;
   
 sp!     ( a_addr -- )           gforth          sp_store  sp!     ( a_addr -- S:... )             gforth          sp_store
 sp = a_addr;  sp = a_addr;
 /* works with and without spTOS caching */  
   
 rp@     ( -- a_addr )           gforth          rp_fetch  rp@     ( -- a_addr )           gforth          rp_fetch
 a_addr = rp;  a_addr = rp;
Line 1150  rp = a_addr; Line 1279  rp = a_addr;
   
 \+floating  \+floating
   
 fp@     ( -- f_addr )   gforth  fp_fetch  fp@     ( f:... -- f_addr )     gforth  fp_fetch
 f_addr = fp;  f_addr = fp;
   
 fp!     ( f_addr -- )   gforth  fp_store  fp!     ( f_addr -- f:... )     gforth  fp_store
 fp = f_addr;  fp = f_addr;
   
 \+  \+
Line 1226  tuck ( w1 w2 -- w2 w1 w2 ) core-ext Line 1355  tuck ( w1 w2 -- w2 w1 w2 ) core-ext
 :  :
  swap over ;   swap over ;
   
 ?dup    ( w -- w )                      core    question_dupe  ?dup    ( w -- S:... w )        core    question_dupe
 ""Actually the stack effect is: @code{( w -- 0 | w w )}.  It performs a  ""Actually the stack effect is: @code{( w -- 0 | w w )}.  It performs a
 @code{dup} if w is nonzero.""  @code{dup} if w is nonzero.""
 if (w!=0) {  if (w!=0) {
   IF_spTOS(*sp-- = w;)  
 #ifndef USE_TOS  
   *--sp = w;    *--sp = w;
 #endif  
 }  }
 :  :
  dup IF dup THEN ;   dup IF dup THEN ;
   
 pick    ( u -- w )                      core-ext  pick    ( S:... u -- S:... w )          core-ext
 ""Actually the stack effect is @code{ x0 ... xu u -- x0 ... xu x0 }.""  ""Actually the stack effect is @code{ x0 ... xu u -- x0 ... xu x0 }.""
 w = sp[u+1];  w = sp[u];
 :  :
  1+ cells sp@ + @ ;   1+ cells sp@ + @ ;
   
Line 1402  c_addr2 = c_addr1+1; Line 1528  c_addr2 = c_addr1+1;
 :  :
  dup 1+ swap c@ ;   dup 1+ swap c@ ;
   
   cell/ ( n1 -- n2 )      gforth cell_divide
   ""@i{n2} is the number of cells that fit into @i{n1}""
   n2 = n1 / sizeof(Cell);
   :
    [ cell
    2/ dup [IF] ] 2/ [ [THEN]
    2/ dup [IF] ] 2/ [ [THEN]
    2/ dup [IF] ] 2/ [ [THEN]
    2/ dup [IF] ] 2/ [ [THEN]
    drop ] ;
   
 \g compiler  \g compiler
   
 \+f83headerstring  \+f83headerstring
Line 1412  for (; f83name1 != NULL; f83name1 = (str Line 1549  for (; f83name1 != NULL; f83name1 = (str
       memcasecmp(c_addr, f83name1->name, u)== 0 /* or inline? */)        memcasecmp(c_addr, f83name1->name, u)== 0 /* or inline? */)
     break;      break;
 f83name2=f83name1;  f83name2=f83name1;
   #ifdef DEBUG
   fprintf(stderr, "F83find ");
   fwrite(c_addr, u, 1, stderr);
   fprintf(stderr, " found %08x\n", f83name2); 
   #endif
 :  :
     BEGIN  dup WHILE  (find-samelen)  dup  WHILE      BEGIN  dup WHILE  (find-samelen)  dup  WHILE
         >r 2dup r@ cell+ char+ capscomp  0=          >r 2dup r@ cell+ char+ capscomp  0=
Line 1542  n=1; Line 1684  n=1;
   
 \g hostos  \g hostos
   
 key-file        ( wfileid -- n )                gforth  paren_key_file  key-file        ( wfileid -- c )                gforth  paren_key_file
   ""Read one character @i{c} from @i{wfileid}.  This word disables
   buffering for @i{wfileid}.  If you want to read characters from a
   terminal in non-canonical (raw) mode, you have to put the terminal in
   non-canonical mode yourself (using the C interface); the exception is
   @code{stdin}: Gforth automatically puts it into non-canonical mode.""
 #ifdef HAS_FILE  #ifdef HAS_FILE
 fflush(stdout);  fflush(stdout);
 n = key((FILE*)wfileid);  c = key((FILE*)wfileid);
 #else  #else
 n = key(stdin);  c = key(stdin);
 #endif  #endif
   
 key?-file       ( wfileid -- n )                facility        key_q_file  key?-file       ( wfileid -- f )                gforth  key_q_file
   ""@i{f} is true if at least one character can be read from @i{wfileid}
   without blocking.  If you also want to use @code{read-file} or
   @code{read-line} on the file, you have to call @code{key?-file} or
   @code{key-file} first (these two words disable buffering).""
 #ifdef HAS_FILE  #ifdef HAS_FILE
 fflush(stdout);  fflush(stdout);
 n = key_query((FILE*)wfileid);  f = key_query((FILE*)wfileid);
 #else  #else
 n = key_query(stdin);  f = key_query(stdin);
 #endif  #endif
   
 \+os  
   
 stdin   ( -- wfileid )  gforth  stdin   ( -- wfileid )  gforth
   ""The standard input file of the Gforth process.""
 wfileid = (Cell)stdin;  wfileid = (Cell)stdin;
   
 stdout  ( -- wfileid )  gforth  stdout  ( -- wfileid )  gforth
   ""The standard output file of the Gforth process.""
 wfileid = (Cell)stdout;  wfileid = (Cell)stdout;
   
 stderr  ( -- wfileid )  gforth  stderr  ( -- wfileid )  gforth
   ""The standard error output file of the Gforth process.""
 wfileid = (Cell)stderr;  wfileid = (Cell)stderr;
   
 form    ( -- urows ucols )      gforth  \+os
 ""The number of lines and columns in the terminal. These numbers may change  
 with the window size.""  (form)  ( -- urows ucols )      gforth  paren_form
   ""The number of lines and columns in the terminal. These numbers may
   change with the window size.  Note that it depends on the OS whether
   this reflects the actual size and changes with the window size
   (currently only on Unix-like OSs).  On other OSs you just get a
   default, and can tell Gforth the terminal size by setting the
   environment variables @code{COLUMNS} and @code{LINES} before starting
   Gforth.""
 /* 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
  think this is necessary or always beneficial */   think this is necessary or always beneficial */
 urows=rows;  urows=rows;
 ucols=cols;  ucols=cols;
   
   wcwidth ( u -- n )      gforth
   ""The number of fixed-width characters per unicode character u""
   #ifdef HAVE_WCWIDTH
   n = wcwidth(u);
   #else
   n = 1;
   #endif
   
 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
Line 1587  supported on your machine (take a look a Line 1754  supported on your machine (take a look a
 your machine has a separate instruction cache. In such cases,  your machine has a separate instruction cache. In such cases,
 @code{flush-icache} does nothing instead of flushing the instruction  @code{flush-icache} does nothing instead of flushing the instruction
 cache.""  cache.""
 FLUSH_ICACHE(c_addr,u);  FLUSH_ICACHE((caddr_t)c_addr,u);
   
 (bye)   ( n -- )        gforth  paren_bye  (bye)   ( n -- )        gforth  paren_bye
 SUPER_END;  SUPER_END;
   gforth_FP=fp;
   gforth_SP=sp;
   gforth_RP=rp;
   gforth_LP=lp;
 return (Label *)n;  return (Label *)n;
   
 (system)        ( c_addr u -- wretval wior )    gforth  paren_system  (system)        ( c_addr u -- wretval wior )    gforth  paren_system
 #ifndef MSDOS  wretval = gforth_system(c_addr, u);  
 int old_tp=terminal_prepped;  
 deprep_terminal();  
 #endif  
 wretval=system(cstr(c_addr,u,1)); /* ~ expansion on first part of string? */  
 wior = IOR(wretval==-1 || (wretval==127 && errno != 0));  wior = IOR(wretval==-1 || (wretval==127 && errno != 0));
 #ifndef MSDOS  
 if (old_tp)  
   prep_terminal();  
 #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}
Line 1611  is the host operating system's expansion Line 1774  is the host operating system's expansion
 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
 in length.""  in length.""
 /* close ' to keep fontify happy */  /* close ' to keep fontify happy */
 c_addr2 = getenv(cstr(c_addr1,u1,1));  char * string = cstr(c_addr1,u1);
 u2 = (c_addr2 == NULL ? 0 : strlen(c_addr2));  c_addr2 = (Char *)getenv(string);
   u2 = (c_addr2 == NULL ? 0 : strlen((char *)c_addr2));
   free(string);
   
 open-pipe       ( c_addr u wfam -- wfileid wior )       gforth  open_pipe  open-pipe       ( c_addr u wfam -- wfileid wior )       gforth  open_pipe
 wfileid=(Cell)popen(cstr(c_addr,u,1),pfileattr[wfam]); /* ~ expansion of 1st arg? */  char * string = cstr(c_addr,u);
   fflush(stdout);
   wfileid=(Cell)popen(string,pfileattr[wfam]); /* ~ 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 */
   free(string);
   
 close-pipe      ( wfileid -- wretval wior )             gforth  close_pipe  close-pipe      ( wfileid -- wretval wior )             gforth  close_pipe
 wretval = pclose((FILE *)wfileid);  wretval = pclose((FILE *)wfileid);
Line 1646  nhour =ltime->tm_hour; Line 1814  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      ( u -- )        facility-ext
 ""Wait at least @i{n} milli-second.""  ""Wait at least @i{n} milli-second.""
 struct timeval timeout;  gforth_ms(u);
 timeout.tv_sec=n/1000;  
 timeout.tv_usec=1000*(n%1000);  
 (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
Line 1686  if (a_addr1==NULL) Line 1851  if (a_addr1==NULL)
 else  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 */
   if (a_addr2==NULL)
     a_addr2 = a_addr1;
   
 strerror        ( n -- c_addr u )       gforth  strerror        ( n -- c_addr u )       gforth
 c_addr = strerror(n);  c_addr = (Char *)strerror(n);
 u = strlen(c_addr);  u = strlen((char *)c_addr);
   
 strsignal       ( n -- c_addr u )       gforth  strsignal       ( n -- c_addr u )       gforth
 c_addr = (Address)strsignal(n);  c_addr = (Char *)strsignal(n);
 u = strlen(c_addr);  u = strlen((char *)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{gforth_SP} and @code{gforth_FP}.""
 /* This is a first attempt at support for calls to C. This may change in  /* This is a first attempt at support for calls to C. This may change in
    the future */     the future */
 IF_fpTOS(fp[0]=fpTOS);  IF_fpTOS(fp[0]=fpTOS);
 FP=fp;  gforth_FP=fp;
 SP=sp;  gforth_SP=sp;
   gforth_RP=rp;
   gforth_LP=lp;
   #ifdef HAS_LINKBACK
 ((void (*)())w)();  ((void (*)())w)();
 sp=SP;  #else
 fp=FP;  ((void (*)(void *))w)(&gforth_pointers);
 IF_spTOS(spTOS=sp[0]);  #endif
   sp=gforth_SP;
   fp=gforth_FP;
   rp=gforth_RP;
   lp=gforth_LP;
 IF_fpTOS(fpTOS=fp[0]);  IF_fpTOS(fpTOS=fp[0]);
   
 \+  \+
Line 1717  close-file ( wfileid -- wior )  file clo Line 1891  close-file ( wfileid -- wior )  file clo
 wior = IOR(fclose((FILE *)wfileid)==EOF);  wior = IOR(fclose((FILE *)wfileid)==EOF);
   
 open-file       ( c_addr u wfam -- wfileid wior )       file    open_file  open-file       ( c_addr u wfam -- wfileid wior )       file    open_file
 wfileid = (Cell)fopen(tilde_cstr(c_addr, u, 1), fileattr[wfam]);  char * string = tilde_cstr(c_addr,u);
 wior =  IOR(wfileid == 0);  wfileid = opencreate_file(string, wfam, 0, &wior);
   free(string);
   
 create-file     ( c_addr u wfam -- wfileid wior )       file    create_file  create-file     ( c_addr u wfam -- wfileid wior )       file    create_file
 Cell    fd;  char * string = tilde_cstr(c_addr,u);
 fd = open(tilde_cstr(c_addr, u, 1), O_CREAT|O_TRUNC|ufileattr[wfam], 0666);  wfileid = opencreate_file(string, wfam, O_CREAT|O_TRUNC, &wior);
 if (fd != -1) {  free(string);
   wfileid = (Cell)fdopen(fd, fileattr[wfam]);  
   wior = IOR(wfileid == 0);  
 } else {  
   wfileid = 0;  
   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);  char * string = tilde_cstr(c_addr,u);
   wior = IOR(unlink(string)==-1);
   free(string);
   
 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}""
Line 1757  wior = IOR(ftruncate(fileno((FILE *)wfil Line 1928  wior = IOR(ftruncate(fileno((FILE *)wfil
 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);
   if (u2>0)
      gf_regetc((FILE *)wfileid);
 wior = FILEIO(u2<u1 && ferror((FILE *)wfileid));  wior = FILEIO(u2<u1 && ferror((FILE *)wfileid));
 /* !! is the value of ferror errno-compatible? */  /* !! is the value of ferror errno-compatible? */
 if (wior)  if (wior)
   clearerr((FILE *)wfileid);    clearerr((FILE *)wfileid);
   
 (read-line)     ( c_addr u1 wfileid -- u2 flag u3 wior ) file   paren_read_line  (read-line)     ( c_addr u1 wfileid -- u2 flag u3 wior ) file   paren_read_line
 struct Cellquad r = read_line(c_addr, u1, wfileid);  struct Cellquad r = read_line(c_addr, u1, (FILE *)wfileid);
 u2   = r.n1;  u2   = r.n1;
 flag = r.n2;  flag = r.n2;
 u3   = r.n3;  u3   = r.n3;
Line 1809  flag = FLAG(feof((FILE *) wfileid)); Line 1982  flag = FLAG(feof((FILE *) wfileid));
 open-dir        ( c_addr u -- wdirid wior )     gforth  open_dir  open-dir        ( c_addr u -- wdirid wior )     gforth  open_dir
 ""Open the directory specified by @i{c-addr, u}  ""Open the directory specified by @i{c-addr, u}
 and return @i{dir-id} for futher access to it.""  and return @i{dir-id} for futher access to it.""
 wdirid = (Cell)opendir(tilde_cstr(c_addr, u, 1));  char * string = tilde_cstr(c_addr,u);
   wdirid = (Cell)opendir(string);
 wior =  IOR(wdirid == 0);  wior =  IOR(wdirid == 0);
   free(string);
   
 read-dir        ( c_addr u1 wdirid -- u2 flag wior )    gforth  read_dir  read-dir        ( c_addr u1 wdirid -- u2 flag wior )    gforth  read_dir
 ""Attempt to read the next entry from the directory specified  ""Attempt to read the next entry from the directory specified
Line 1832  if(dent == NULL) { Line 2007  if(dent == NULL) {
   u2 = 0;    u2 = 0;
   flag = 0;    flag = 0;
 } else {  } else {
   u2 = strlen(dent->d_name);    u2 = strlen((char *)dent->d_name);
   if(u2 > u1) {    if(u2 > u1) {
     u2 = u1;      u2 = u1;
     wior = -512-ENAMETOOLONG;      wior = -512-ENAMETOOLONG;
Line 1845  close-dir ( wdirid -- wior ) gforth clos Line 2020  close-dir ( wdirid -- wior ) gforth clos
 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);
 char * pattern = cstr(c_addr2, u2, 0);  char * pattern = cstr(c_addr2, u2);
 flag = FLAG(!fnmatch(pattern, string, 0));  flag = FLAG(!fnmatch(pattern, string, 0));
   free(string);
   free(pattern);
   
   set-dir ( c_addr u -- wior )    gforth set_dir
   ""Change the current directory to @i{c-addr, u}.
   Return an error if this is not possible""
   char * string = tilde_cstr(c_addr, u);
   wior = IOR(chdir(string));
   free(string);
   
   get-dir ( c_addr1 u1 -- c_addr2 u2 )    gforth get_dir
   ""Store the current directory in the buffer specified by @i{c-addr1, u1}.
   If the buffer size is not sufficient, return 0 0""
   c_addr2 = (Char *)getcwd((char *)c_addr1, u1);
   if(c_addr2 != NULL) {
     u2 = strlen((char *)c_addr2);
   } else {
     u2 = 0;
   }
   
   =mkdir ( c_addr u wmode -- wior )        gforth equals_mkdir
   ""Create directory @i{c-addr u} with mode @i{wmode}.""
   char * string = tilde_cstr(c_addr,u);
   wior = IOR(mkdir(string,wmode));
   free(string);
   
 \+  \+
   
 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[] = {  static const char newline[] = {
 #if DIRSEP=='/'  #if DIRSEP=='/'
 /* Unix */  /* Unix */
 '\n'  '\n'
Line 1862  char newline[] = { Line 2062  char newline[] = {
 '\r','\n'  '\r','\n'
 #endif  #endif
 };  };
 c_addr=newline;  c_addr=(Char *)newline;
 u=sizeof(newline);  u=sizeof(newline);
 :  :
  "newline count ;   "newline count ;
Line 1891  dsystem = timeval2us(&usage.ru_stime); Line 2091  dsystem = timeval2us(&usage.ru_stime);
 struct timeval time1;  struct timeval time1;
 gettimeofday(&time1,NULL);  gettimeofday(&time1,NULL);
 duser = timeval2us(&time1);  duser = timeval2us(&time1);
 #ifndef BUGGY_LONG_LONG  dsystem = DZERO;
 dsystem = (DCell)0;  
 #else  
 dsystem=(DCell){0,0};  
 #endif  #endif
   
   ntime   ( -- dtime )    gforth
   ""Report the current time in nanoseconds since some epoch.""
   struct timespec time1;
   #ifdef HAVE_CLOCK_GETTIME
   clock_gettime(CLOCK_REALTIME,&time1);
   #else
   struct timeval time2;
   gettimeofday(&time2,NULL);
   time1.tv_sec = time2.tv_sec;1
   time1.tv_nsec = time2.tv_usec*1000;
 #endif  #endif
   dtime = timespec2ns(&time1);
   
 \+  \+
   
Line 1907  dsystem=(DCell){0,0}; Line 2116  dsystem=(DCell){0,0};
 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)
   
   s>f     ( n -- r )              float   s_to_f
   r = n;
   
 d>f     ( d -- r )              float   d_to_f  d>f     ( d -- r )              float   d_to_f
 #ifdef BUGGY_LONG_LONG  #ifdef BUGGY_LL_D2F
 extern double ldexp(double x, int exp);  extern double ldexp(double x, int exp);
 if (d.hi<0) {  if (DHI(d)<0) {
   #ifdef BUGGY_LL_ADD
   DCell d2=dnegate(d);    DCell d2=dnegate(d);
   r = -(ldexp((Float)d2.hi,CELL_BITS) + (Float)d2.lo);  #else
     DCell d2=-d;
   #endif
     r = -(ldexp((Float)DHI(d2),CELL_BITS) + (Float)DLO(d2));
 } else  } else
   r = ldexp((Float)d.hi,CELL_BITS) + (Float)d.lo;    r = ldexp((Float)DHI(d),CELL_BITS) + (Float)DLO(d);
 #else  #else
 r = d;  r = d;
 #endif  #endif
Line 1923  f>d ( r -- d )  float f_to_d Line 2139  f>d ( r -- d )  float f_to_d
 extern DCell double2ll(Float r);  extern DCell double2ll(Float r);
 d = double2ll(r);  d = double2ll(r);
   
   f>s     ( r -- n )              float   f_to_s
   n = (Cell)r;
   
 f!      ( r f_addr -- ) float   f_store  f!      ( r f_addr -- ) float   f_store
 ""Store @i{r} into the float at address @i{f-addr}.""  ""Store @i{r} into the float at address @i{f-addr}.""
 *f_addr = r;  *f_addr = r;
Line 1979  r3 = r1/r2; Line 2198  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.""
   CLOBBER_TOS_WORKAROUND_START;
 r3 = pow(r1,r2);  r3 = pow(r1,r2);
   CLOBBER_TOS_WORKAROUND_END;
   
   fm*     ( r1 n -- r2 )  gforth  fm_star
   r2 = r1*n;
   
   fm/     ( r1 n -- r2 )  gforth  fm_slash
   r2 = r1/n;
   
   fm*/    ( r1 n1 n2 -- r2 )      gforth  fm_star_slash
   r2 = (r1*n1)/n2;
   
   f**2    ( r1 -- r2 )    gforth  fm_square
   r2 = r1*r1;
   
 fnegate ( r1 -- r2 )    float   f_negate  fnegate ( r1 -- r2 )    float   f_negate
 r2 = - r1;  r2 = - r1;
Line 2009  n2 = n1*sizeof(Float); Line 2242  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 */
   CLOBBER_TOS_WORKAROUND_START;
 r2 = floor(r1);  r2 = floor(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 fround  ( r1 -- r2 )    gforth  f_round  fround  ( r1 -- r2 )    float   f_round
 ""Round to the nearest integral value.""  ""Round to the nearest integral value.""
 r2 = rint(r1);  r2 = rint(r1);
   
Line 2034  int flag; Line 2269  int flag;
 int decpt;  int decpt;
 sig=ecvt(r, u, &decpt, &flag);  sig=ecvt(r, u, &decpt, &flag);
 n=(r==0. ? 1 : decpt);  n=(r==0. ? 1 : decpt);
   flag=signbit(r); /* not all ecvt()s do this as desired */
 f1=FLAG(flag!=0);  f1=FLAG(flag!=0);
 f2=FLAG(isdigit((unsigned)(sig[0]))!=0);  f2=FLAG(isdigit((unsigned)(sig[0]))!=0);
 siglen=strlen(sig);  siglen=strlen((char *)sig);
 if (siglen>u) /* happens in glibc-2.1.3 if 999.. is rounded up */  if (siglen>u) /* happens in glibc-2.1.3 if 999.. is rounded up */
   siglen=u;    siglen=u;
   if (!f2) /* workaround Cygwin trailing 0s for Inf and Nan */
     for (; sig[siglen-1]=='0'; siglen--);
       ;
 memcpy(c_addr,sig,siglen);  memcpy(c_addr,sig,siglen);
 memset(c_addr+siglen,f2?'0':' ',u-siglen);  memset(c_addr+siglen,f2?'0':' ',u-siglen);
   
 >float  ( c_addr u -- flag )    float   to_float  >float  ( c_addr u -- f:... flag )      float   to_float
 ""Actual stack effect: ( c_addr u -- r t | f ).  Attempt to convert the  ""Actual stack effect: ( c_addr u -- r t | f ).  Attempt to convert the
 character string @i{c-addr u} to internal floating-point  character string @i{c-addr u} to internal floating-point
 representation. If the string represents a valid floating-point number  representation. If the string represents a valid floating-point number
Line 2050  representation. If the string represents Line 2289  representation. If the string represents
 true. Otherwise, @i{flag} is false. A string of blanks is a special  true. Otherwise, @i{flag} is false. A string of blanks is a special
 case and represents the floating-point number 0.""  case and represents the floating-point number 0.""
 Float r;  Float r;
 flag = to_float(c_addr, u, &r);  flag = to_float(c_addr, u, &r, '.');
 if (flag) {  if (flag) {
   IF_fpTOS(fp[0] = fpTOS);    fp--;
   fp += -1;    fp[0]=r;
   fpTOS = r;  
 }  }
   
 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
   CLOBBER_TOS_WORKAROUND_START;
 r2 = acos(r1);  r2 = acos(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 fasin   ( r1 -- r2 )    float-ext       f_a_sine  fasin   ( r1 -- r2 )    float-ext       f_a_sine
   CLOBBER_TOS_WORKAROUND_START;
 r2 = asin(r1);  r2 = asin(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 fatan   ( r1 -- r2 )    float-ext       f_a_tan  fatan   ( r1 -- r2 )    float-ext       f_a_tan
 r2 = atan(r1);  r2 = atan(r1);
Line 2072  r2 = atan(r1); Line 2314  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.""
   CLOBBER_TOS_WORKAROUND_START;
 r3 = atan2(r1,r2);  r3 = atan2(r1,r2);
   CLOBBER_TOS_WORKAROUND_END;
   
 fcos    ( r1 -- r2 )    float-ext       f_cos  fcos    ( r1 -- r2 )    float-ext       f_cos
   CLOBBER_TOS_WORKAROUND_START;
 r2 = cos(r1);  r2 = cos(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 fexp    ( r1 -- r2 )    float-ext       f_e_x_p  fexp    ( r1 -- r2 )    float-ext       f_e_x_p
   CLOBBER_TOS_WORKAROUND_START;
 r2 = exp(r1);  r2 = exp(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 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""
Line 2088  extern double Line 2336  extern double
               const                const
 #endif  #endif
                     expm1(double);                      expm1(double);
   CLOBBER_TOS_WORKAROUND_START;
 r2 = expm1(r1);  r2 = expm1(r1);
   CLOBBER_TOS_WORKAROUND_END;
 #else  #else
   CLOBBER_TOS_WORKAROUND_START;
 r2 = exp(r1)-1.;  r2 = exp(r1)-1.;
   CLOBBER_TOS_WORKAROUND_END;
 #endif  #endif
   
 fln     ( r1 -- r2 )    float-ext       f_l_n  fln     ( r1 -- r2 )    float-ext       f_l_n
   CLOBBER_TOS_WORKAROUND_START;
 r2 = log(r1);  r2 = log(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 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)""
   CLOBBER_TOS_WORKAROUND_START;
 #ifdef HAVE_LOG1P  #ifdef HAVE_LOG1P
 extern double  extern double
 #ifdef NeXT  #ifdef NeXT
Line 2108  r2 = log1p(r1); Line 2363  r2 = log1p(r1);
 #else  #else
 r2 = log(r1+1.);  r2 = log(r1+1.);
 #endif  #endif
   CLOBBER_TOS_WORKAROUND_END;
   
 flog    ( r1 -- r2 )    float-ext       f_log  flog    ( r1 -- r2 )    float-ext       f_log
 ""The decimal logarithm.""  ""The decimal logarithm.""
   CLOBBER_TOS_WORKAROUND_START;
 r2 = log10(r1);  r2 = log10(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 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);
   CLOBBER_TOS_WORKAROUND_START;
 r2 = pow10(r1);  r2 = pow10(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 fsin    ( r1 -- r2 )    float-ext       f_sine  fsin    ( r1 -- r2 )    float-ext       f_sine
   CLOBBER_TOS_WORKAROUND_START;
 r2 = sin(r1);  r2 = sin(r1);
   CLOBBER_TOS_WORKAROUND_END;
   
 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);  CLOBBER_TOS_WORKAROUND_START;
 r3 = cos(r1);  sincos(r1, &r2, &r3);
   CLOBBER_TOS_WORKAROUND_END;
   
 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
   CLOBBER_TOS_WORKAROUND_START;
 r2 = tan(r1);  r2 = tan(r1);
   CLOBBER_TOS_WORKAROUND_END;
 :  :
  fsincos f/ ;   fsincos f/ ;
   
 fsinh   ( r1 -- r2 )    float-ext       f_cinch  fsinh   ( r1 -- r2 )    float-ext       f_cinch
   CLOBBER_TOS_WORKAROUND_START;
 r2 = sinh(r1);  r2 = sinh(r1);
   CLOBBER_TOS_WORKAROUND_END;
 :  :
  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
   CLOBBER_TOS_WORKAROUND_START;
 r2 = cosh(r1);  r2 = cosh(r1);
   CLOBBER_TOS_WORKAROUND_END;
 :  :
  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
   CLOBBER_TOS_WORKAROUND_START;
 r2 = tanh(r1);  r2 = tanh(r1);
   CLOBBER_TOS_WORKAROUND_END;
 :  :
  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
   CLOBBER_TOS_WORKAROUND_START;
 r2 = asinh(r1);  r2 = asinh(r1);
   CLOBBER_TOS_WORKAROUND_END;
 :  :
  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
   CLOBBER_TOS_WORKAROUND_START;
 r2 = acosh(r1);  r2 = acosh(r1);
   CLOBBER_TOS_WORKAROUND_END;
 :  :
  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
   CLOBBER_TOS_WORKAROUND_START;
 r2 = atanh(r1);  r2 = atanh(r1);
   CLOBBER_TOS_WORKAROUND_END;
 :  :
  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 ;
Line 2207  faxpy(ra, f_x, nstridex, f_y, nstridey, Line 2484  faxpy(ra, f_x, nstridex, f_y, nstridey,
      fdup dup f@ f* over + 2swap dup f@ f+ dup f! over + 2swap       fdup dup f@ f* over + 2swap dup f@ f+ dup f! over + 2swap
  LOOP 2drop 2drop fdrop ;   LOOP 2drop 2drop fdrop ;
   
   >float1 ( c_addr u c -- f:... flag )    gforth  to_float1
   ""Actual stack effect: ( c_addr u c -- r t | f ).  Attempt to convert the
   character string @i{c-addr u} to internal floating-point
   representation. If the string represents a valid floating-point number
   @i{r} is placed on the floating-point stack and @i{flag} is
   true. Otherwise, @i{flag} is false. A string of blanks is a special
   case and represents the floating-point number 0.""
   Float r;
   flag = to_float(c_addr, u, &r, c);
   if (flag) {
     fp--;
     fp[0]=r;
   }
   
   float/ ( n1 -- n2 )     gforth  float_divide
   n2 = n1 / sizeof(Float);
   
   dfloat/ ( n1 -- n2 )    gforth  sfloat_divide
   n2 = n1 / sizeof(DFloat);
   
   sfloat/ ( n1 -- n2 )    gforth  dfloat_divide
   n2 = n1 / sizeof(SFloat);
   
 \+  \+
   
 \ The following words access machine/OS/installation-dependent  \ The following words access machine/OS/installation-dependent
Line 2280  f>l ( r -- ) gforth f_to_l Line 2580  f>l ( r -- ) gforth f_to_l
 lp -= sizeof(Float);  lp -= sizeof(Float);
 *(Float *)lp = r;  *(Float *)lp = r;
   
 fpick   ( u -- r )              gforth  fpick   ( f:... u -- f:... r )          gforth
 ""Actually the stack effect is @code{ r0 ... ru u -- r0 ... ru r0 }.""  ""Actually the stack effect is @code{ r0 ... ru u -- r0 ... ru r0 }.""
 r = fp[u+1]; /* +1, because update of fp happens before this fragment */  r = fp[u];
 :  :
  floats fp@ + f@ ;   floats fp@ + f@ ;
   
Line 2294  r = fp[u+1]; /* +1, because update of fp Line 2594  r = fp[u+1]; /* +1, because update of fp
 \g syslib  \g syslib
   
 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)  u2 = gforth_dlopen(c_addr1, u1);
 #ifndef RTLD_GLOBAL  
 #define RTLD_GLOBAL 0  
 #endif  
 u2=(UCell) dlopen(cstr(c_addr1, u1, 1), RTLD_GLOBAL | RTLD_LAZY);  
 #else  
 #  ifdef _WIN32  
 u2 = (Cell) GetModuleHandle(cstr(c_addr1, u1, 1));  
 #  else  
 #warning Define open-lib!  
 u2 = 0;  
 #  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)  char * string = cstr(c_addr1, u1);
 u3 = (UCell) dlsym((void*)u2,cstr(c_addr1, u1, 1));  #ifdef HAVE_LIBLTDL
   u3 = (UCell) lt_dlsym((lt_dlhandle)u2, string);
   #elif defined(HAVE_LIBDL) || defined(HAVE_DLOPEN)
   u3 = (UCell) dlsym((void*)u2,string);
 #else  #else
 #  ifdef _WIN32  #  ifdef _WIN32
 u3 = (Cell) GetProcAddress((HMODULE)u2, cstr(c_addr1, u1, 1));  u3 = (Cell) GetProcAddress((HMODULE)u2, string);
 #  else  #  else
 #warning Define lib-sym!  #warning Define lib-sym!
 u3 = 0;  u3 = 0;
 #  endif  #  endif
 #endif  #endif
   free(string);
   
 wcall   ( u -- )        gforth  wcall   ( ... u -- ... )        gforth
 IF_fpTOS(fp[0]=fpTOS);  gforth_FP=fp;
 FP=fp;  sp=(Cell*)(SYSCALL(Cell*(*)(Cell *, void *))u)(sp, &gforth_FP);
 sp=(Cell*)(SYSCALL(Cell*(*)(Cell *, void *))u)(sp, &FP);  fp=gforth_FP;
 fp=FP;  
 IF_spTOS(spTOS=sp[0];)  uw@ ( c_addr -- u )     gforth u_w_fetch
 IF_fpTOS(fpTOS=fp[0]);  ""@i{u} is the zero-extended 16-bit value stored at @i{c_addr}.""
   u = *(UWyde*)(c_addr);
 \+FFCALL  
   sw@ ( c_addr -- n )     gforth s_w_fetch
 av-start-void   ( c_addr -- )   gforth  av_start_void  ""@i{n} is the sign-extended 16-bit value stored at @i{c_addr}.""
 av_start_void(alist, c_addr);  n = *(Wyde*)(c_addr);
   
 av-start-int    ( c_addr -- )   gforth  av_start_int  w! ( w c_addr -- )      gforth w_store
 av_start_int(alist, c_addr, &irv);  ""Store the bottom 16 bits of @i{w} at @i{c_addr}.""
   *(Wyde*)(c_addr) = w;
 av-start-float  ( c_addr -- )   gforth  av_start_float  
 av_start_float(alist, c_addr, &frv);  ul@ ( c_addr -- u )     gforth u_l_fetch
   ""@i{u} is the zero-extended 32-bit value stored at @i{c_addr}.""
 av-start-double ( c_addr -- )   gforth  av_start_double  u = *(UTetrabyte*)(c_addr);
 av_start_double(alist, c_addr, &drv);  
   sl@ ( c_addr -- n )     gforth s_l_fetch
 av-start-longlong       ( c_addr -- )   gforth  av_start_longlong  ""@i{n} is the sign-extended 32-bit value stored at @i{c_addr}.""
 av_start_longlong(alist, c_addr, &llrv);  n = *(Tetrabyte*)(c_addr);
   
 av-start-ptr    ( c_addr -- )   gforth  av_start_ptr  l! ( w c_addr -- )      gforth l_store
 av_start_ptr(alist, c_addr, void*, &prv);  ""Store the bottom 32 bits of @i{w} at @i{c_addr}.""
   *(Tetrabyte*)(c_addr) = w;
 av-int  ( w -- )  gforth  av_int  
 av_int(alist, w);  lib-error ( -- c_addr u )       gforth  lib_error
   ""Error message for last failed @code{open-lib} or @code{lib-sym}.""
 av-float        ( r -- )        gforth  av_float  #ifdef HAVE_LIBLTDL
 av_float(alist, r);  c_addr = (Char *)lt_dlerror();
   u = (c_addr == NULL) ? 0 : strlen((char *)c_addr);
 av-double       ( r -- )        gforth  av_double  #elif defined(HAVE_LIBDL) || defined(HAVE_DLOPEN)
 av_double(alist, r);  c_addr = dlerror();
   u = strlen(c_addr);
 av-longlong     ( d -- )        gforth  av_longlong  #else
 av_longlong(alist, d);  c_addr = "libltdl is not configured";
   u = strlen(c_addr);
 av-ptr  ( c_addr -- )   gforth  av_ptr  #endif
 av_ptr(alist, void*, c_addr);  
   
 av-int-r  ( R:w -- )  gforth  av_int_r  
 av_int(alist, w);  
   
 av-float-r      ( -- )  gforth  av_float_r  
 float r = *(Float*)lp;  
 lp += sizeof(Float);  
 av_float(alist, r);  
   
 av-double-r     ( -- )  gforth  av_double_r  
 double r = *(Float*)lp;  
 lp += sizeof(Float);  
 av_double(alist, r);  
   
 av-longlong-r   ( R:d -- )      gforth  av_longlong_r  
 av_longlong(alist, d);  
   
 av-ptr-r        ( R:c_addr -- ) gforth  av_ptr_r  
 av_ptr(alist, void*, c_addr);  
   
 av-call-void    ( -- )  gforth  av_call_void  be-w! ( w c_addr -- )   gforth w_store_be
 SAVE_REGS  ""Store the bottom 16 bits of @i{w} at @i{c_addr} in big endian format.""
 av_call(alist);  c_addr[0] = w >> 8;
 REST_REGS  c_addr[1] = w;
   
 av-call-int     ( -- w )        gforth  av_call_int  be-l! ( w c_addr -- )   gforth l_store_be
 SAVE_REGS  ""Store the bottom 32 bits of @i{w} at @i{c_addr} in big endian format.""
 av_call(alist);  c_addr[0] = w >> 24;
 REST_REGS  c_addr[1] = w >> 16;
 w = irv;  c_addr[2] = w >> 8;
   c_addr[3] = w;
 av-call-float   ( -- r )        gforth  av_call_float  
 SAVE_REGS  le-w! ( w c_addr -- )   gforth w_store_le
 av_call(alist);  ""Store the bottom 16 bits of @i{w} at @i{c_addr} in big endian format.""
 REST_REGS  c_addr[1] = w >> 8;
 r = frv;  c_addr[0] = w;
   
 av-call-double  ( -- r )        gforth  av_call_double  le-l! ( w c_addr -- )   gforth l_store_le
 SAVE_REGS  ""Store the bottom 32 bits of @i{w} at @i{c_addr} in big endian format.""
 av_call(alist);  c_addr[3] = w >> 24;
 REST_REGS  c_addr[2] = w >> 16;
 r = drv;  c_addr[1] = w >> 8;
   c_addr[0] = w;
 av-call-longlong        ( -- d )        gforth  av_call_longlong  
 SAVE_REGS  be-uw@ ( c_addr -- u )  gforth w_fetch_be
 av_call(alist);  ""@i{u} is the zero-extended 16-bit big endian value stored at @i{c_addr}.""
 REST_REGS  u = (c_addr[0] << 8) | (c_addr[1]);
 d = llrv;  
   be-ul@ ( c_addr -- u )  gforth l_fetch_be
 av-call-ptr     ( -- c_addr )   gforth  av_call_ptr  ""@i{u} is the zero-extended 32-bit big endian value stored at @i{c_addr}.""
 SAVE_REGS  u = ((Cell)c_addr[0] << 24) | (c_addr[1] << 16) | (c_addr[2] << 8) | (c_addr[3]);
 av_call(alist);  
 REST_REGS  le-uw@ ( c_addr -- u )  gforth w_fetch_le
 c_addr = prv;  ""@i{u} is the zero-extended 16-bit little endian value stored at @i{c_addr}.""
   u = (c_addr[1] << 8) | (c_addr[0]);
 alloc-callback  ( a_ip -- c_addr )      gforth  alloc_callback  
 c_addr = (char *)alloc_callback(engine_callback, (Xt *)a_ip);  le-ul@ ( c_addr -- u )  gforth l_fetch_le
   ""@i{u} is the zero-extended 32-bit little endian value stored at @i{c_addr}.""
 va-start-void   ( -- )  gforth  va_start_void  u = ((Cell)c_addr[3] << 24) | (c_addr[2] << 16) | (c_addr[1] << 8) | (c_addr[0]);
 va_start_void(clist);  
   \+64bit
 va-start-int    ( -- )  gforth  va_start_int  
 va_start_int(clist);  x! ( w c_addr -- )      gforth x_store
   ""Store the bottom 64 bits of @i{w} at 64-bit-aligned @i{c_addr}.""
 va-start-longlong       ( -- )  gforth  va_start_longlong  *(UOctabyte *)c_addr = w;
 va_start_longlong(clist);  
   ux@ ( c_addr -- u )     gforth u_x_fetch
 va-start-ptr    ( -- )  gforth  va_start_ptr  ""@i{u} is the zero-extended 64-bit value stored at 64-bit-aligned @i{c_addr}.""
 va_start_ptr(clist, (char *));  u = *(UOctabyte *)c_addr;
   
 va-start-float  ( -- )  gforth  va_start_float  sx@ ( c_addr -- n )     gforth s_x_fetch
 va_start_float(clist);  ""@i{u} is the sign-extended 64-bit value stored at 64-bit-aligned @i{c_addr}.""
   n = *(Octabyte *)c_addr;
 va-start-double ( -- )  gforth  va_start_double  
 va_start_double(clist);  be-x! ( w c_addr -- )   gforth b_e_x_store
   ""Store the bottom 64 bits of @i{w} at @i{c_addr} in big endian format.""
 va-arg-int      ( -- w )        gforth  va_arg_int  c_addr[0] = w >> 56;
 w = va_arg_int(clist);  c_addr[1] = w >> 48;
   c_addr[2] = w >> 40;
 va-arg-longlong ( -- d )        gforth  va_arg_longlong  c_addr[3] = w >> 32;
 d = va_arg_longlong(clist);  c_addr[4] = w >> 24;
   c_addr[5] = w >> 16;
 va-arg-ptr      ( -- c_addr )   gforth  va_arg_ptr  c_addr[6] = w >> 8;
 c_addr = (char *)va_arg_ptr(clist,char*);  c_addr[7] = w;
   
 va-arg-float    ( -- r )        gforth  va_arg_float  le-x! ( w c_addr -- )   gforth l_e_x_store
 r = va_arg_float(clist);  ""Store the bottom 64 bits of @i{w} at @i{c_addr} in big endian format.""
   c_addr[7] = w >> 56;
 va-arg-double   ( -- r )        gforth  va_arg_double  c_addr[6] = w >> 48;
 r = va_arg_double(clist);  c_addr[5] = w >> 40;
   c_addr[4] = w >> 32;
 va-return-void ( -- )   gforth va_return_void  c_addr[3] = w >> 24;
 va_return_void(clist);  c_addr[2] = w >> 16;
 return 0;  c_addr[1] = w >> 8;
   c_addr[0] = w;
 va-return-int ( w -- )  gforth va_return_int  
 va_return_int(clist, w);  be-ux@ ( c_addr -- u )  gforth b_e_u_x_fetch
 return 0;  ""@i{u} is the zero-extended 64-bit big endian value stored at @i{c_addr}.""
   u = (((Cell)(c_addr[0]) << 56) |
 va-return-ptr ( c_addr -- )     gforth va_return_ptr       ((Cell)(c_addr[1]) << 48) |
 va_return_ptr(clist, void *, c_addr);       ((Cell)(c_addr[2]) << 40) |
 return 0;       ((Cell)(c_addr[3]) << 32) |
        ((Cell)(c_addr[4]) << 24) |
 va-return-longlong ( d -- )     gforth va_return_longlong       ((Cell)(c_addr[5]) << 16) |
 va_return_longlong(clist, d);       ((Cell)(c_addr[6]) << 8) |
 return 0;       ((Cell)(c_addr[7])));
   
 va-return-float ( r -- )        gforth va_return_float  le-ux@ ( c_addr -- u )  gforth l_e_u_x_fetch
 va_return_float(clist, r);  ""@i{u} is the zero-extended 64-bit little endian value stored at @i{c_addr}.""
 return 0;  u = (((Cell)(c_addr[7]) << 56) |
        ((Cell)(c_addr[6]) << 48) |
 va-return-double ( r -- )       gforth va_return_double       ((Cell)(c_addr[5]) << 40) |
 va_return_double(clist, r);       ((Cell)(c_addr[4]) << 32) |
 return 0;       ((Cell)(c_addr[3]) << 24) |
        ((Cell)(c_addr[2]) << 16) |
 \+       ((Cell)(c_addr[1]) << 8) |
        ((Cell)(c_addr[0])));
 \+OLDCALL  
   
 define(`uploop',  
        `pushdef(`$1', `$2')_uploop(`$1', `$2', `$3', `$4', `$5')`'popdef(`$1')')  
 define(`_uploop',  
        `ifelse($1, `$3', `$5',  
                `$4`'define(`$1', incr($1))_uploop(`$1', `$2', `$3', `$4', `$5')')')  
 \ argflist(argnum): Forth argument list  
 define(argflist,  
        `ifelse($1, 0, `',  
                `uploop(`_i', 1, $1, `format(`u%d ', _i)', `format(`u%d ', _i)')')')  
 \ argdlist(argnum): declare C's arguments  
 define(argdlist,  
        `ifelse($1, 0, `',  
                `uploop(`_i', 1, $1, `Cell, ', `Cell')')')  
 \ argclist(argnum): pass C's arguments  
 define(argclist,  
        `ifelse($1, 0, `',  
                `uploop(`_i', 1, $1, `format(`u%d, ', _i)', `format(`u%d', _i)')')')  
 \ icall(argnum)  
 define(icall,  
 `icall$1        ( argflist($1)u -- uret )       gforth  
 uret = (SYSCALL(Cell(*)(argdlist($1)))u)(argclist($1));  
   
 ')  
 define(fcall,  
 `fcall$1        ( argflist($1)u -- rret )       gforth  
 rret = (SYSCALL(Float(*)(argdlist($1)))u)(argclist($1));  
   
 ')  
   
 \ close ' to keep fontify happy  
   
 uploop(i, 0, 7, `icall(i)')  
 icall(20)  
 uploop(i, 0, 7, `fcall(i)')  
 fcall(20)  
   
 \+  \+
 \+  \+
   
 \g peephole  \g peephole
   
 \+peephole  \+peephole
Line 2528  compile-prim1 ( a_prim -- ) gforth compi Line 2762  compile-prim1 ( a_prim -- ) gforth compi
 ""compile prim (incl. immargs) at @var{a_prim}""  ""compile prim (incl. immargs) at @var{a_prim}""
 compile_prim1(a_prim);  compile_prim1(a_prim);
   
 finish-code ( -- ) gforth finish_code  finish-code ( ... -- ... ) gforth finish_code
 ""Perform delayed steps in code generation (branch resolution, I-cache  ""Perform delayed steps in code generation (branch resolution, I-cache
 flushing).""  flushing).""
   /* The ... above are a workaround for a bug in gcc-2.95, which fails
      to save spTOS (gforth-fast --enable-force-reg) */
 finish_code();  finish_code();
   
 forget-dyncode ( c_code -- f ) gforth-internal forget_dyncode  forget-dyncode ( c_code -- f ) gforth-internal forget_dyncode
Line 2564  a_addr = groups; Line 2800  a_addr = groups;
   
 \+  \+
   
 \g static_super  \g primitive_centric
   
 \C #if !defined(GFORTH_DEBUGGING) && !defined(INDIRECT_THREADED) && !defined(DOUBLY_INDIRECT) && !defined(VM_PROFILING)  \ primitives for primitive-centric code
   \ another one is does-exec
   
 include(peeprules.vmg)  abi-call        ( #a_callee ... -- ... ) gforth-internal abi_call
   /* primitive for compiled ABI-CODE words */
   abifunc *f = (abifunc *)a_callee;
   Float *fp_mem = fp;
   sp = (*f)(sp, &fp_mem);
   fp = fp_mem;
   
   ;abi-code-exec ( #a_cfa ... -- ... ) gforth-internal semi_abi_code_exec
   /* primitive for performing ;ABI-CODE words */
   Float *fp_mem = fp;
   semiabifunc *f = (semiabifunc *)DOES_CODE1(a_cfa);
   Address body = (Address)PFA(a_cfa);
   sp = (*f)(sp, &fp_mem, body);
   fp = fp_mem;
   
   lit-execute     ( #a_addr -- )  new     lit_execute
   /* for ;code and code words; a static superinstruction would be more general, 
      but VM_JUMP is currently not supported there */
   #ifndef NO_IP
   ip=IP;
   #endif
   SUPER_END;
   VM_JUMP(EXEC1((Xt)a_addr));
   
   \+objects
   \g object_pointer
   
   >o ( c_addr -- r:c_old )        new     to_o
   c_old = op;
   op = c_addr;
   
   o> ( r:c_addr -- )              new     o_restore
   op = c_addr;
   
   o#+ ( #w -- c_addr )            new     o_lit_plus
   c_addr = op + w;
   
   \+
   \g static_super
   
 \C #endif  ifdef(`STACK_CACHE_FILE',
   `include(peeprules.vmg)')
   
 \g end  \g end

Removed from v.1.145  
changed lines
  Added in v.1.278


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