File:  [gforth] / gforth / Attic / kernel.fs
Revision 1.24: download - view: text, annotated - select for diffs
Thu Apr 10 21:32:08 1997 UTC (27 years ago) by pazsan
Branches: MAIN
CVS tags: HEAD
Made \G work in interpret cross state

    1: \ kernel.fs    GForth kernel                        17dec92py
    2: 
    3: \ Copyright (C) 1995 Free Software Foundation, Inc.
    4: 
    5: \ This file is part of Gforth.
    6: 
    7: \ Gforth is free software; you can redistribute it and/or
    8: \ modify it under the terms of the GNU General Public License
    9: \ as published by the Free Software Foundation; either version 2
   10: \ of the License, or (at your option) any later version.
   11: 
   12: \ This program is distributed in the hope that it will be useful,
   13: \ but WITHOUT ANY WARRANTY; without even the implied warranty of
   14: \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15: \ GNU General Public License for more details.
   16: 
   17: \ You should have received a copy of the GNU General Public License
   18: \ along with this program; if not, write to the Free Software
   19: \ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   20: 
   21: \ Idea and implementation: Bernd Paysan (py)
   22: 
   23: HEX
   24: 
   25: \ labels for some code addresses
   26: 
   27: doer? :docon [IF]
   28: : docon: ( -- addr )	\ gforth
   29:     \G the code address of a @code{CONSTANT}
   30:     ['] bl >code-address ;
   31: [THEN]
   32: 
   33: : docol: ( -- addr )	\ gforth
   34:     \G the code address of a colon definition
   35:     ['] docol: >code-address ;
   36: 
   37: doer? :dovar [IF]
   38: : dovar: ( -- addr )	\ gforth
   39:     \G the code address of a @code{CREATE}d word
   40:     ['] udp >code-address ;
   41: [THEN]
   42: 
   43: doer? :douser [IF]
   44: : douser: ( -- addr )	\ gforth
   45:     \G the code address of a @code{USER} variable
   46:     ['] s0 >code-address ;
   47: [THEN]
   48: 
   49: doer? :dodefer [IF]
   50: : dodefer: ( -- addr )	\ gforth
   51:     \G the code address of a @code{defer}ed word
   52:     ['] source >code-address ;
   53: [THEN]
   54: 
   55: doer? :dofield [IF]
   56: : dofield: ( -- addr )	\ gforth
   57:     \G the code address of a @code{field}
   58:     ['] reveal-method >code-address ;
   59: [THEN]
   60: 
   61: has-prims 0= [IF]
   62: : dodoes: ( -- addr )	\ gforth
   63:     \G the code address of a @code{field}
   64:     ['] spaces >code-address ;
   65: [THEN]
   66: 
   67: NIL AConstant NIL \ gforth
   68: 
   69: \ Aliases
   70: 
   71: ' i Alias r@ ( -- w ; R: w -- w ) \ core r-fetch
   72: \G copy w from the return stack to the data stack
   73: 
   74: \ Bit string manipulation                              06oct92py
   75: 
   76: \ Create bits  80 c, 40 c, 20 c, 10 c, 8 c, 4 c, 2 c, 1 c,
   77: \ DOES> ( n -- )  + c@ ;
   78: 
   79: \ : >bit  ( addr n -- c-addr mask )  8 /mod rot + swap bits ;
   80: \ : +bit  ( addr n -- )  >bit over c@ or swap c! ;
   81: 
   82: \ : relinfo ( -- addr )  forthstart dup @ + !!bug!! ;
   83: \ : >rel  ( addr -- n )  forthstart - ;
   84: \ : relon ( addr -- )  relinfo swap >rel cell / +bit ;
   85: 
   86: \ here allot , c, A,                                   17dec92py
   87: 
   88: : dp	( -- addr ) \ gforth
   89:     dpp @ ;
   90: : here  ( -- here ) \ core
   91:     dp @ ;
   92: : allot ( n -- ) \ core
   93:     dp +! ;
   94: : c,    ( c -- ) \ core
   95:     here 1 chars allot c! ;
   96: : ,     ( x -- ) \ core
   97:     here cell allot  ! ;
   98: : 2,	( w1 w2 -- ) \ gforth
   99:     here 2 cells allot 2! ;
  100: 
  101: \ : aligned ( addr -- addr' ) \ core
  102: \     [ cell 1- ] Literal + [ -1 cells ] Literal and ;
  103: : align ( -- ) \ core
  104:     here dup aligned swap ?DO  bl c,  LOOP ;
  105: 
  106: \ : faligned ( addr -- f-addr ) \ float
  107: \     [ 1 floats 1- ] Literal + [ -1 floats ] Literal and ;
  108: 
  109: : falign ( -- ) \ float
  110:     here dup faligned swap
  111:     ?DO
  112: 	bl c,
  113:     LOOP ;
  114: 
  115: \ !! this is machine-dependent, but works on all but the strangest machines
  116: 
  117: : maxaligned ( addr -- f-addr ) \ float
  118:     [ /maxalign 1 - ] Literal + [ 0 /maxalign - ] Literal and ;
  119: : maxalign ( -- ) \ float
  120:     here dup maxaligned swap
  121:     ?DO
  122: 	bl c,
  123:     LOOP ;
  124: 
  125: \ !! machine-dependent and won't work if "0 >body" <> "0 >body maxaligned"
  126: ' maxaligned Alias cfaligned ( addr1 -- addr2 ) \ gforth
  127: \ the code field is aligned if its body is maxaligned
  128: ' maxalign Alias cfalign ( -- ) \ gforth
  129: 
  130: : chars ( n1 -- n2 ) \ core
  131: ; immediate
  132: 
  133: 
  134: \ : A!    ( addr1 addr2 -- ) \ gforth
  135: \    dup relon ! ;
  136: \ : A,    ( addr -- ) \ gforth
  137: \    here cell allot A! ;
  138: ' ! alias A! ( addr1 addr2 -- ) \ gforth
  139: ' , alias A, ( addr -- ) \ gforth 
  140: 
  141: 
  142: \ on off                                               23feb93py
  143: 
  144: : on  ( addr -- ) \ gforth
  145:     true  swap ! ;
  146: : off ( addr -- ) \ gforth
  147:     false swap ! ;
  148: 
  149: \ dabs roll                                           17may93jaw
  150: 
  151: : dabs ( d1 -- d2 ) \ double
  152:     dup 0< IF dnegate THEN ;
  153: 
  154: : roll  ( x0 x1 .. xn n -- x1 .. xn x0 ) \ core-ext
  155:   dup 1+ pick >r
  156:   cells sp@ cell+ dup cell+ rot move drop r> ;
  157: 
  158: \ name> found                                          17dec92py
  159: 
  160: $80 constant alias-mask \ set when the word is not an alias!
  161: $40 constant immediate-mask
  162: $20 constant restrict-mask
  163: 
  164: : ((name>))  ( nfa -- cfa )
  165:     name>string +  cfaligned ;
  166: 
  167: : (name>x) ( nfa -- cfa b )
  168:     \ cfa is an intermediate cfa and b is the flags byte of nfa
  169:     dup ((name>))
  170:     swap cell+ c@ dup alias-mask and 0=
  171:     IF
  172: 	swap @ swap
  173:     THEN ;
  174: 
  175: \ place bounds                                         13feb93py
  176: 
  177: : place  ( addr len to -- ) \ gforth
  178:     over >r  rot over 1+  r> move c! ;
  179: : bounds ( beg count -- end beg ) \ gforth
  180:     over + swap ;
  181: 
  182: \ input stream primitives                              23feb93py
  183: 
  184: : tib ( -- c-addr ) \ core-ext
  185:     \ obsolescent
  186:     >tib @ ;
  187: Defer source ( -- addr count ) \ core
  188: \ used by dodefer:, must be defer
  189: : (source) ( -- addr count )
  190:     tib #tib @ ;
  191: ' (source) IS source
  192: 
  193: \ (word)                                               22feb93py
  194: 
  195: : scan   ( addr1 n1 char -- addr2 n2 ) \ gforth
  196:     \ skip all characters not equal to char
  197:     >r
  198:     BEGIN
  199: 	dup
  200:     WHILE
  201: 	over c@ r@ <>
  202:     WHILE
  203: 	1 /string
  204:     REPEAT  THEN
  205:     rdrop ;
  206: : skip   ( addr1 n1 char -- addr2 n2 ) \ gforth
  207:     \ skip all characters equal to char
  208:     >r
  209:     BEGIN
  210: 	dup
  211:     WHILE
  212: 	over c@ r@  =
  213:     WHILE
  214: 	1 /string
  215:     REPEAT  THEN
  216:     rdrop ;
  217: 
  218: : (word) ( addr1 n1 char -- addr2 n2 )
  219:   dup >r skip 2dup r> scan  nip - ;
  220: 
  221: \ (word) should fold white spaces
  222: \ this is what (parse-white) does
  223: 
  224: \ word parse                                           23feb93py
  225: 
  226: : parse-word  ( char -- addr len ) \ gforth
  227:   source 2dup >r >r >in @ over min /string
  228:   rot dup bl = IF  drop (parse-white)  ELSE  (word)  THEN
  229:   2dup + r> - 1+ r> min >in ! ;
  230: : word   ( char -- addr ) \ core
  231:   parse-word here place  bl here count + c!  here ;
  232: 
  233: : parse    ( char -- addr len ) \ core-ext
  234:   >r  source  >in @ over min /string  over  swap r>  scan >r
  235:   over - dup r> IF 1+ THEN  >in +! ;
  236: 
  237: \ name                                                 13feb93py
  238: 
  239: : capitalize ( addr len -- addr len ) \ gforth
  240:   2dup chars chars bounds
  241:   ?DO  I c@ toupper I c! 1 chars +LOOP ;
  242: : (name) ( -- c-addr count )
  243:     source 2dup >r >r >in @ /string (parse-white)
  244:     2dup + r> - 1+ r> min >in ! ;
  245: \    name count ;
  246: 
  247: : name-too-short? ( c-addr u -- c-addr u )
  248:     dup 0= -&16 and throw ;
  249: 
  250: : name-too-long? ( c-addr u -- c-addr u )
  251:     dup $1F u> -&19 and throw ;
  252: 
  253: \ Literal                                              17dec92py
  254: 
  255: : Literal  ( compilation n -- ; run-time -- n ) \ core
  256:     postpone lit  , ; immediate restrict
  257: : ALiteral ( compilation addr -- ; run-time -- addr ) \ gforth
  258:     postpone lit A, ; immediate restrict
  259: 
  260: : char   ( 'char' -- n ) \ core
  261:     bl word char+ c@ ;
  262: : [char] ( compilation 'char' -- ; run-time -- n )
  263:     char postpone Literal ; immediate restrict
  264: 
  265: : (compile) ( -- ) \ gforth
  266:     r> dup cell+ >r @ compile, ;
  267: 
  268: : postpone, ( w xt -- ) \ gforth postpone-comma
  269:     \g Compiles the compilation semantics represented by @var{w xt}.
  270:     dup ['] execute =
  271:     if
  272: 	drop compile,
  273:     else
  274: 	dup ['] compile, =
  275: 	if
  276: 	    drop POSTPONE (compile) compile,
  277: 	else
  278: 	    swap POSTPONE aliteral compile,
  279: 	then
  280:     then ;
  281: 
  282: : POSTPONE ( "name" -- ) \ core
  283:     \g Compiles the compilation semantics of @var{name}.
  284:     COMP' postpone, ; immediate restrict
  285: 
  286: : interpret/compile: ( interp-xt comp-xt "name" -- ) \ gforth
  287:     Create immediate swap A, A,
  288: DOES>
  289:     abort" executed primary cfa of an interpret/compile: word" ;
  290: \    state @ IF  cell+  THEN  perform ;
  291: 
  292: \ Use (compile) for the old behavior of compile!
  293: 
  294: \ digit?                                               17dec92py
  295: 
  296: : digit?   ( char -- digit true/ false ) \ gforth
  297:   base @ $100 =
  298:   IF
  299:     true EXIT
  300:   THEN
  301:   toupper [char] 0 - dup 9 u> IF
  302:     [ 'A '9 1 + -  ] literal -
  303:     dup 9 u<= IF
  304:       drop false EXIT
  305:     THEN
  306:   THEN
  307:   dup base @ u>= IF
  308:     drop false EXIT
  309:   THEN
  310:   true ;
  311: 
  312: : accumulate ( +d0 addr digit - +d1 addr )
  313:   swap >r swap  base @  um* drop rot  base @  um* d+ r> ;
  314: 
  315: : >number ( d addr count -- d addr count ) \ core
  316:     0
  317:     ?DO
  318: 	count digit?
  319:     WHILE
  320: 	accumulate
  321:     LOOP
  322:         0
  323:     ELSE
  324: 	1- I' I -
  325: 	UNLOOP
  326:     THEN ;
  327: 
  328: \ number? number                                       23feb93py
  329: 
  330: Create bases   10 ,   2 ,   A , 100 ,
  331: \              16     2    10   character
  332: \ !! this saving and restoring base is an abomination! - anton
  333: : getbase ( addr u -- addr' u' )
  334:     over c@ [char] $ - dup 4 u<
  335:     IF
  336: 	cells bases + @ base ! 1 /string
  337:     ELSE
  338: 	drop
  339:     THEN ;
  340: : s>number ( addr len -- d )
  341:     base @ >r  dpl on
  342:     over c@ '- =  dup >r
  343:     IF
  344: 	1 /string
  345:     THEN
  346:     getbase  dpl on  0 0 2swap
  347:     BEGIN
  348: 	dup >r >number dup
  349:     WHILE
  350: 	dup r> -
  351:     WHILE
  352: 	dup dpl ! over c@ [char] . =
  353:     WHILE
  354: 	1 /string
  355:     REPEAT  THEN
  356:         2drop rdrop dpl off
  357:     ELSE
  358: 	2drop rdrop r>
  359: 	IF
  360: 	    dnegate
  361: 	THEN
  362:     THEN
  363:     r> base ! ;
  364: 
  365: : snumber? ( c-addr u -- 0 / n -1 / d 0> )
  366:     s>number dpl @ 0=
  367:     IF
  368: 	2drop false  EXIT
  369:     THEN
  370:     dpl @ dup 0> 0= IF
  371: 	nip
  372:     THEN ;
  373: : number? ( string -- string 0 / n -1 / d 0> )
  374:     dup >r count snumber? dup if
  375: 	rdrop
  376:     else
  377: 	r> swap
  378:     then ;
  379: : s>d ( n -- d ) \ core		s-to-d
  380:     dup 0< ;
  381: : number ( string -- d )
  382:     number? ?dup 0= abort" ?"  0<
  383:     IF
  384: 	s>d
  385:     THEN ;
  386: 
  387: \ space spaces ud/mod                                  21mar93py
  388: decimal
  389: Create spaces ( u -- ) \ core
  390: bl 80 times \ times from target compiler! 11may93jaw
  391: DOES>   ( u -- )
  392:     swap
  393:     0 max 0 ?DO  I' I - &80 min 2dup type  +LOOP  drop ;
  394: Create backspaces
  395: 08 80 times \ times from target compiler! 11may93jaw
  396: DOES>   ( u -- )
  397:     swap
  398:     0 max 0 ?DO  I' I - &80 min 2dup type  +LOOP  drop ;
  399: hex
  400: : space ( -- ) \ core
  401:     1 spaces ;
  402: 
  403: : ud/mod ( ud1 u2 -- urem udquot ) \ gforth
  404:     >r 0 r@ um/mod r> swap >r
  405:     um/mod r> ;
  406: 
  407: : pad    ( -- addr ) \ core-ext
  408:   here [ $20 8 2* cells + 2 + cell+ ] Literal + aligned ;
  409: 
  410: \ hold <# #> sign # #s                                 25jan92py
  411: 
  412: : hold    ( char -- ) \ core
  413:     pad cell - -1 chars over +! @ c! ;
  414: 
  415: : <# ( -- ) \ core	less-number-sign
  416:     pad cell - dup ! ;
  417: 
  418: : #>      ( xd -- addr u ) \ core	number-sign-greater
  419:     2drop pad cell - dup @ tuck - ;
  420: 
  421: : sign    ( n -- ) \ core
  422:     0< IF  [char] - hold  THEN ;
  423: 
  424: : #       ( ud1 -- ud2 ) \ core		number-sign
  425:     base @ 2 max ud/mod rot 9 over <
  426:     IF
  427: 	[ char A char 9 - 1- ] Literal +
  428:     THEN
  429:     [char] 0 + hold ;
  430: 
  431: : #s      ( +d -- 0 0 ) \ core	number-sign-s
  432:     BEGIN
  433: 	# 2dup or 0=
  434:     UNTIL ;
  435: 
  436: \ print numbers                                        07jun92py
  437: 
  438: : d.r ( d n -- ) \ double	d-dot-r
  439:     >r tuck  dabs  <# #s  rot sign #>
  440:     r> over - spaces  type ;
  441: 
  442: : ud.r ( ud n -- ) \ gforth	u-d-dot-r
  443:     >r <# #s #> r> over - spaces type ;
  444: 
  445: : .r ( n1 n2 -- ) \ core-ext	dot-r
  446:     >r s>d r> d.r ;
  447: : u.r ( u n -- )  \ core-ext	u-dot-r
  448:     0 swap ud.r ;
  449: 
  450: : d. ( d -- ) \ double	d-dot
  451:     0 d.r space ;
  452: : ud. ( ud -- ) \ gforth	u-d-dot
  453:     0 ud.r space ;
  454: 
  455: : . ( n -- ) \ core	dot
  456:     s>d d. ;
  457: : u. ( u -- ) \ core	u-dot
  458:     0 ud. ;
  459: 
  460: \ catch throw                                          23feb93py
  461: \ bounce                                                08jun93jaw
  462: 
  463: \ !! allow the user to add rollback actions    anton
  464: \ !! use a separate exception stack?           anton
  465: 
  466: has-locals [IF]
  467: : lp@ ( -- addr ) \ gforth	l-p-fetch
  468:  laddr# [ 0 , ] ;
  469: [THEN]
  470: 
  471: Defer 'catch
  472: Defer 'throw
  473: 
  474: ' noop IS 'catch
  475: ' noop IS 'throw
  476: 
  477: : catch ( x1 .. xn xt -- y1 .. ym 0 / z1 .. zn error ) \ exception
  478:     'catch
  479:     sp@ >r
  480: [ has-floats [IF] ]
  481:     fp@ >r
  482: [ [THEN] ]
  483: [ has-locals [IF] ]
  484:     lp@ >r
  485: [ [THEN] ]
  486:     handler @ >r
  487:     rp@ handler !
  488:     execute
  489:     r> handler ! rdrop rdrop rdrop 0 ;
  490: 
  491: : throw ( y1 .. ym error/0 -- y1 .. ym / z1 .. zn error ) \ exception
  492:     ?DUP IF
  493: 	[ has-header [IF] here 9 cells ! [THEN] ] \ entry point for signal handler
  494: 	handler @ dup 0= IF
  495: [ has-os [IF] ]
  496: 	    2 (bye)
  497: [ [ELSE] ]
  498: 	    quit
  499: [ [THEN] ]
  500: 	THEN
  501: 	rp!
  502: 	r> handler !
  503: [ has-locals [IF] ]
  504:         r> lp!
  505: [ [THEN] ]
  506: [ has-floats [IF] ]
  507: 	r> fp!
  508: [ [THEN] ]
  509: 	r> swap >r sp! drop r>
  510: 	'throw
  511:     THEN ;
  512: 
  513: \ Bouncing is very fine,
  514: \ programming without wasting time...   jaw
  515: : bounce ( y1 .. ym error/0 -- y1 .. ym error / y1 .. ym ) \ gforth
  516: \ a throw without data or fp stack restauration
  517:   ?DUP IF
  518:       handler @ rp!
  519:       r> handler !
  520: [ has-locals [IF] ]
  521:       r> lp!
  522: [ [THEN] ]
  523: [ has-floats [IF] ]
  524:       rdrop
  525: [ [THEN] ]
  526:       rdrop
  527:       'throw
  528:   THEN ;
  529: 
  530: \ ?stack                                               23feb93py
  531: 
  532: : ?stack ( ?? -- ?? ) \ gforth
  533:     sp@ s0 @ u> IF    -4 throw  THEN
  534: [ has-floats [IF] ]
  535:     fp@ f0 @ u> IF  -&45 throw  THEN
  536: [ [THEN] ]
  537: ;
  538: \ ?stack should be code -- it touches an empty stack!
  539: 
  540: \ interpret                                            10mar92py
  541: 
  542: Defer parser
  543: Defer name ( -- c-addr count ) \ gforth
  544: \ get the next word from the input buffer
  545: ' (name) IS name
  546: Defer compiler-notfound ( c-addr count -- )
  547: Defer interpreter-notfound ( c-addr count -- )
  548: 
  549: : no.extensions  ( addr u -- )
  550:     2drop -&13 bounce ;
  551: ' no.extensions IS compiler-notfound
  552: ' no.extensions IS interpreter-notfound
  553: 
  554: : compile-only-error ( ... -- )
  555:     -&14 throw ;
  556: 
  557: : interpret ( ?? -- ?? ) \ gforth
  558:     \ interpret/compile the (rest of the) input buffer
  559:     BEGIN
  560: 	?stack name dup
  561:     WHILE
  562: 	parser
  563:     REPEAT
  564:     2drop ;
  565: 
  566: \ interpreter compiler                                 30apr92py
  567: 
  568: \ not the most efficient implementations of interpreter and compiler
  569: : interpreter ( c-addr u -- ) 
  570:     2dup find-name dup
  571:     if
  572: 	nip nip name>int execute
  573:     else
  574: 	drop
  575: 	2dup 2>r snumber?
  576: 	IF
  577: 	    2rdrop
  578: 	ELSE
  579: 	    2r> interpreter-notfound
  580: 	THEN
  581:     then ;
  582: 
  583: : compiler ( c-addr u -- )
  584:     2dup find-name dup
  585:     if ( c-addr u nt )
  586: 	nip nip name>comp execute
  587:     else
  588: 	drop
  589: 	2dup snumber? dup
  590: 	IF
  591: 	    0>
  592: 	    IF
  593: 		swap postpone Literal
  594: 	    THEN
  595: 	    postpone Literal
  596: 	    2drop
  597: 	ELSE
  598: 	    drop compiler-notfound
  599: 	THEN
  600:     then ;
  601: 
  602: ' interpreter  IS  parser
  603: 
  604: : [ ( -- ) \ core	left-bracket
  605:     ['] interpreter  IS parser state off ; immediate
  606: : ] ( -- ) \ core	right-bracket
  607:     ['] compiler     IS parser state on  ;
  608: 
  609: \ Strings                                              22feb93py
  610: 
  611: : ," ( "string"<"> -- ) [char] " parse
  612:   here over char+ allot  place align ;
  613: : "lit ( -- addr )
  614:   r> r> dup count + aligned >r swap >r ;
  615: : (.")     "lit count type ;
  616: : (S")     "lit count ;
  617: : SLiteral ( Compilation c-addr1 u ; run-time -- c-addr2 u ) \ string
  618:     postpone (S") here over char+ allot  place align ;
  619:                                              immediate restrict
  620: : ( ( compilation 'ccc<close-paren>' -- ; run-time -- ) \ core,file	paren
  621:     [char] ) parse 2drop ; immediate
  622: 
  623: : \ ( -- ) \ core-ext backslash
  624:     blk @
  625:     IF
  626: 	>in @ c/l / 1+ c/l * >in !
  627: 	EXIT
  628:     THEN
  629:     source >in ! drop ; immediate
  630: 
  631: : \G ( -- ) \ gforth backslash
  632:     POSTPONE \ ; immediate
  633: 
  634: \ error handling                                       22feb93py
  635: \ 'abort thrown out!                                   11may93jaw
  636: 
  637: : (abort")
  638:     "lit >r
  639:     IF
  640: 	r> "error ! -2 throw
  641:     THEN
  642:     rdrop ;
  643: : abort" ( compilation 'ccc"' -- ; run-time f -- ) \ core,exception-ext	abort-quote
  644:     postpone (abort") ," ;        immediate restrict
  645: 
  646: \ Header states                                        23feb93py
  647: 
  648: : cset ( bmask c-addr -- )
  649:     tuck c@ or swap c! ; 
  650: : creset ( bmask c-addr -- )
  651:     tuck c@ swap invert and swap c! ; 
  652: : ctoggle ( bmask c-addr -- )
  653:     tuck c@ xor swap c! ; 
  654: 
  655: : lastflags ( -- c-addr )
  656:     \ the address of the flags byte in the last header
  657:     \ aborts if the last defined word was headerless
  658:     last @ dup 0= abort" last word was headerless" cell+ ;
  659: 
  660: : immediate ( -- ) \ core
  661:     immediate-mask lastflags cset ;
  662: : restrict ( -- ) \ gforth
  663:     restrict-mask lastflags cset ;
  664: ' restrict alias compile-only ( -- ) \ gforth
  665: 
  666: \ Header                                               23feb93py
  667: 
  668: \ input-stream, nextname and noname are quite ugly (passing
  669: \ information through global variables), but they are useful for dealing
  670: \ with existing/independent defining words
  671: 
  672: defer (header)
  673: defer header ( -- ) \ gforth
  674: ' (header) IS header
  675: 
  676: : string, ( c-addr u -- ) \ gforth
  677:     \G puts down string as cstring
  678:     dup c, here swap chars dup allot move ;
  679: 
  680: : header, ( c-addr u -- ) \ gforth
  681:     name-too-long?
  682:     align here last !
  683:     current @ 1 or A,	\ link field; before revealing, it contains the
  684: 			\ tagged reveal-into wordlist
  685:     string, cfalign
  686:     alias-mask lastflags cset ;
  687: 
  688: : input-stream-header ( "name" -- )
  689:     name name-too-short? header, ;
  690: : input-stream ( -- )  \ general
  691:     \G switches back to getting the name from the input stream ;
  692:     ['] input-stream-header IS (header) ;
  693: 
  694: ' input-stream-header IS (header)
  695: 
  696: \ !! make that a 2variable
  697: create nextname-buffer 32 chars allot
  698: 
  699: : nextname-header ( -- )
  700:     nextname-buffer count header,
  701:     input-stream ;
  702: 
  703: \ the next name is given in the string
  704: : nextname ( c-addr u -- ) \ gforth
  705:     name-too-long?
  706:     nextname-buffer c! ( c-addr )
  707:     nextname-buffer count move
  708:     ['] nextname-header IS (header) ;
  709: 
  710: : noname-header ( -- )
  711:     0 last ! cfalign
  712:     input-stream ;
  713: 
  714: : noname ( -- ) \ gforth
  715: \ the next defined word remains anonymous. The xt of that word is given by lastxt
  716:     ['] noname-header IS (header) ;
  717: 
  718: : lastxt ( -- xt ) \ gforth
  719: \ xt is the execution token of the last word defined. The main purpose of this word is to get the xt of words defined using noname
  720:     lastcfa @ ;
  721: 
  722: : Alias    ( cfa "name" -- ) \ gforth
  723:     Header reveal
  724:     alias-mask lastflags creset
  725:     dup A, lastcfa ! ;
  726: 
  727: : name>string ( nt -- addr count ) \ gforth	name-to-string
  728:     \g @var{addr count} is the name of the word represented by @var{nt}.
  729:     cell+ count $1F and ;
  730: 
  731: Create ???  0 , 3 c, char ? c, char ? c, char ? c,
  732: : >name ( cfa -- nt ) \ gforth	to-name
  733:  $21 cell do
  734:    dup i - count $9F and + cfaligned over alias-mask + = if
  735:      i - cell - unloop exit
  736:    then
  737:  cell +loop
  738:  drop ??? ( wouldn't 0 be better? ) ;
  739: 
  740: \ threading                                   17mar93py
  741: 
  742: : cfa,     ( code-address -- )  \ gforth	cfa-comma
  743:     here
  744:     dup lastcfa !
  745:     0 A, 0 ,  code-address! ;
  746: : compile, ( xt -- )	\ core-ext	compile-comma
  747:     A, ;
  748: : !does    ( addr -- ) \ gforth	store-does
  749:     lastxt does-code! ;
  750: : (does>)  ( R: addr -- )
  751:     r> cfaligned /does-handler + !does ;
  752: : dodoes,  ( -- )
  753:   cfalign here /does-handler allot does-handler! ;
  754: 
  755: doer? :dovar [IF]
  756: : Create ( "name" -- ) \ core
  757:     Header reveal dovar: cfa, ;
  758: [ELSE]
  759: : Create ( "name" -- ) \ core
  760:     Header reveal here lastcfa ! 0 A, 0 , DOES> ;
  761: [THEN]
  762: 
  763: \ Create Variable User Constant                        17mar93py
  764: 
  765: : Variable ( "name" -- ) \ core
  766:     Create 0 , ;
  767: : AVariable ( "name" -- ) \ gforth
  768:     Create 0 A, ;
  769: : 2Variable ( "name" -- ) \ double
  770:     create 0 , 0 , ;
  771: 
  772: : uallot ( n -- )  udp @ swap udp +! ;
  773: 
  774: doer? :douser [IF]
  775: : User ( "name" -- ) \ gforth
  776:     Header reveal douser: cfa, cell uallot , ;
  777: : AUser ( "name" -- ) \ gforth
  778:     User ;
  779: [ELSE]
  780: : User Create uallot , DOES> @ up @ + ;
  781: : AUser User ;
  782: [THEN]
  783: 
  784: doer? :docon [IF]
  785:     : (Constant)  Header reveal docon: cfa, ;
  786: [ELSE]
  787:     : (Constant)  Create DOES> @ ;
  788: [THEN]
  789: : Constant ( w "name" -- ) \ core
  790:     \G Defines constant @var{name}
  791:     \G  
  792:     \G @var{name} execution: @var{-- w}
  793:     (Constant) , ;
  794: : AConstant ( addr "name" -- ) \ gforth
  795:     (Constant) A, ;
  796: : Value ( w "name" -- ) \ core-ext
  797:     (Constant) , ;
  798: 
  799: : 2Constant ( w1 w2 "name" -- ) \ double
  800:     Create ( w1 w2 "name" -- )
  801:         2,
  802:     DOES> ( -- w1 w2 )
  803:         2@ ;
  804:     
  805: doer? :dofield [IF]
  806:     : (Field)  Header reveal dofield: cfa, ;
  807: [ELSE]
  808:     : (Field)  Create DOES> @ + ;
  809: [THEN]
  810: \ IS Defer What's Defers TO                            24feb93py
  811: 
  812: doer? :dodefer [IF]
  813: : Defer ( "name" -- ) \ gforth
  814:     \ !! shouldn't it be initialized with abort or something similar?
  815:     Header Reveal dodefer: cfa,
  816:     ['] noop A, ;
  817: [ELSE]
  818: : Defer ( "name" -- ) \ gforth
  819:     Create ['] noop A,
  820: DOES> @ execute ;
  821: [THEN]
  822: 
  823: : Defers ( "name" -- ) \ gforth
  824:     ' >body @ compile, ; immediate
  825: 
  826: \ : ;                                                  24feb93py
  827: 
  828: defer :-hook ( sys1 -- sys2 )
  829: defer ;-hook ( sys2 -- sys1 )
  830: 
  831: : : ( "name" -- colon-sys ) \ core	colon
  832:     Header docol: cfa, defstart ] :-hook ;
  833: : ; ( compilation colon-sys -- ; run-time nest-sys ) \ core	semicolon
  834:     ;-hook ?struc postpone exit reveal postpone [ ; immediate restrict
  835: 
  836: : :noname ( -- xt colon-sys ) \ core-ext	colon-no-name
  837:     0 last !
  838:     cfalign here docol: cfa, 0 ] :-hook ;
  839: 
  840: \ Search list handling                                 23feb93py
  841: 
  842: AVariable current ( -- addr ) \ gforth
  843: 
  844: : last?   ( -- false / nfa nfa )
  845:     last @ ?dup ;
  846: : (reveal) ( nt wid -- )
  847:     ( wid>wordlist-id ) dup >r
  848:     @ over ( name>link ) ! 
  849:     r> ! ;
  850: 
  851: \ object oriented search list                          17mar93py
  852: 
  853: \ word list structure:
  854: 
  855: struct
  856:   1 cells: field find-method   \ xt: ( c_addr u wid -- nt )
  857:   1 cells: field reveal-method \ xt: ( nt wid -- ) \ used by dofield:, must be field
  858:   1 cells: field rehash-method \ xt: ( wid -- )
  859: \   \ !! what else
  860: end-struct wordlist-map-struct
  861: 
  862: struct
  863:   1 cells: field wordlist-id \ not the same as wid; representation depends on implementation
  864:   1 cells: field wordlist-map \ pointer to a wordlist-map-struct
  865:   1 cells: field wordlist-link \ link field to other wordlists
  866:   1 cells: field wordlist-extend \ points to wordlist extensions (eg hash)
  867: end-struct wordlist-struct
  868: 
  869: : f83find      ( addr len wordlist -- nt / false )
  870:     ( wid>wordlist-id ) @ (f83find) ;
  871: 
  872: \ Search list table: find reveal
  873: Create f83search ( -- wordlist-map )
  874:     ' f83find A,  ' (reveal) A,  ' drop A,
  875: 
  876: Create forth-wordlist  NIL A, G f83search T A, NIL A, NIL A,
  877: AVariable lookup       G forth-wordlist lookup T !
  878: G forth-wordlist current T !
  879: 
  880: \ higher level parts of find
  881: 
  882: ( struct )
  883: 0 >body cell
  884:   1 cells: field interpret/compile-int
  885:   1 cells: field interpret/compile-comp
  886: end-struct interpret/compile-struct
  887: 
  888: : interpret/compile? ( xt -- flag )
  889:     >does-code ['] S" >does-code = ;
  890: 
  891: : (cfa>int) ( cfa -- xt )
  892:     dup interpret/compile?
  893:     if
  894: 	interpret/compile-int @
  895:     then ;
  896: 
  897: : (x>int) ( cfa b -- xt )
  898:     \ get interpretation semantics of name
  899:     restrict-mask and
  900:     if
  901: 	drop ['] compile-only-error
  902:     else
  903: 	(cfa>int)
  904:     then ;
  905: 
  906: : name>int ( nt -- xt ) \ gforth
  907:     \G @var{xt} represents the interpretation semantics of the word
  908:     \G @var{nt}. Produces @code{' compile-only-error} if
  909:     \G @var{nt} is compile-only.
  910:     (name>x) (x>int) ;
  911: 
  912: : name?int ( nt -- xt ) \ gforth
  913:     \G Like name>int, but throws an error if compile-only.
  914:     (name>x) restrict-mask and
  915:     if
  916: 	compile-only-error \ does not return
  917:     then
  918:     (cfa>int) ;
  919: 
  920: : name>comp ( nt -- w xt ) \ gforth
  921:     \G @var{w xt} is the compilation token for the word @var{nt}.
  922:     (name>x) >r dup interpret/compile?
  923:     if
  924: 	interpret/compile-comp @
  925:     then
  926:     r> immediate-mask and if
  927: 	['] execute
  928:     else
  929: 	['] compile,
  930:     then ;
  931: 
  932: : (search-wordlist)  ( addr count wid -- nt / false )
  933:     dup wordlist-map @ find-method perform ;
  934: 
  935: : flag-sign ( f -- 1|-1 )
  936:     \ true becomes 1, false -1
  937:     0= 2* 1+ ;
  938: 
  939: : (name>intn) ( nfa -- xt +-1 )
  940:     (name>x) tuck (x>int) ( b xt )
  941:     swap immediate-mask and flag-sign ;
  942: 
  943: : search-wordlist ( addr count wid -- 0 / xt +-1 ) \ search
  944:     \ xt is the interpretation semantics
  945:     (search-wordlist) dup if
  946: 	(name>intn)
  947:     then ;
  948: 
  949: : find-name ( c-addr u -- nt/0 ) \ gforth
  950:     \g Find the name @var{c-addr u} in the current search
  951:     \g order. Return its nt, if found, otherwise 0.
  952:     lookup @ (search-wordlist) ;
  953: 
  954: : sfind ( c-addr u -- 0 / xt +-1  ) \ gforth-obsolete
  955:     find-name dup
  956:     if ( nt )
  957: 	state @
  958: 	if
  959: 	    name>comp ['] execute = flag-sign
  960: 	else
  961: 	    (name>intn)
  962: 	then
  963:     then ;
  964: 
  965: : find ( c-addr -- xt +-1 / c-addr 0 ) \ core,search
  966:     dup count sfind dup
  967:     if
  968: 	rot drop
  969:     then ;
  970: 
  971: : (') ( "name" -- nt ) \ gforth
  972:     name find-name dup 0=
  973:     IF
  974: 	drop -&13 bounce
  975:     THEN  ;
  976: 
  977: : [(')]  ( compilation "name" -- ; run-time -- nt ) \ gforth	bracket-paren-tick
  978:     (') postpone ALiteral ; immediate restrict
  979: 
  980: : '    ( "name" -- xt ) \ core	tick
  981:     \g @var{xt} represents @var{name}'s interpretation
  982:     \g semantics. Performs @code{-14 throw} if the word has no
  983:     \g interpretation semantics.
  984:     (') name?int ;
  985: : [']  ( compilation. "name" -- ; run-time. -- xt ) \ core	bracket-tick
  986:     \g @var{xt} represents @var{name}'s interpretation
  987:     \g semantics. Performs @code{-14 throw} if the word has no
  988:     \g interpretation semantics.
  989:     ' postpone ALiteral ; immediate restrict
  990: 
  991: : COMP'    ( "name" -- w xt ) \ gforth	c-tick
  992:     \g @var{w xt} represents @var{name}'s compilation semantics.
  993:     (') name>comp ;
  994: : [COMP']  ( compilation "name" -- ; run-time -- w xt ) \ gforth	bracket-comp-tick
  995:     \g @var{w xt} represents @var{name}'s compilation semantics.
  996:     COMP' swap POSTPONE Aliteral POSTPONE ALiteral ; immediate restrict
  997: 
  998: \ reveal words
  999: 
 1000: Variable warnings ( -- addr ) \ gforth
 1001: G -1 warnings T !
 1002: 
 1003: : check-shadow  ( addr count wid -- )
 1004: \G prints a warning if the string is already present in the wordlist
 1005:  >r 2dup 2dup r> (search-wordlist) warnings @ and ?dup if
 1006:    ." redefined " name>string 2dup type
 1007:    compare 0<> if
 1008:      ."  with " type
 1009:    else
 1010:      2drop
 1011:    then
 1012:    space space EXIT
 1013:  then
 1014:  2drop 2drop ;
 1015: 
 1016: : reveal ( -- ) \ gforth
 1017:     last?
 1018:     if \ the last word has a header
 1019: 	dup ( name>link ) @ 1 and
 1020: 	if \ it is still hidden
 1021: 	    dup ( name>link ) @ 1 xor		( nt wid )
 1022: 	    2dup >r name>string r> check-shadow ( nt wid )
 1023: 	    dup wordlist-map @ reveal-method perform
 1024: 	then
 1025:     then ;
 1026: 
 1027: : rehash  ( wid -- )
 1028:     dup wordlist-map @ rehash-method perform ;
 1029: 
 1030: \ Input                                                13feb93py
 1031: 
 1032: 07 constant #bell ( -- c ) \ gforth
 1033: 08 constant #bs ( -- c ) \ gforth
 1034: 09 constant #tab ( -- c ) \ gforth
 1035: 7F constant #del ( -- c ) \ gforth
 1036: 0D constant #cr   ( -- c ) \ gforth
 1037: \ the newline key code
 1038: 0C constant #ff ( -- c ) \ gforth
 1039: 0A constant #lf ( -- c ) \ gforth
 1040: 
 1041: : bell ( -- ) \ gforth
 1042:     \g makes a beep and flushes the output buffer
 1043:     #bell emit
 1044:     outfile-id flush-file drop ;
 1045: : cr ( -- ) \ core
 1046:     \ emit a newline
 1047:     #lf ( sic! ) emit ;
 1048: 
 1049: \ : backspaces  0 ?DO  #bs emit  LOOP ;
 1050: 
 1051: : (ins) ( max span addr pos1 key -- max span addr pos2 )
 1052:     >r 2dup + r@ swap c! r> emit 1+ rot 1+ -rot ;
 1053: : (bs) ( max span addr pos1 -- max span addr pos2 flag )
 1054:     dup IF
 1055: 	#bs emit bl emit #bs emit 1- rot 1- -rot
 1056:     THEN false ;
 1057: : (ret)  true bl emit ;
 1058: 
 1059: Create ctrlkeys
 1060:   ] false false false false  false false false false
 1061:     (bs)  false (ret) false  false (ret) false false
 1062:     false false false false  false false false false
 1063:     false false false false  false false false false [
 1064: 
 1065: defer insert-char
 1066: ' (ins) IS insert-char
 1067: defer everychar
 1068: ' noop IS everychar
 1069: 
 1070: : decode ( max span addr pos1 key -- max span addr pos2 flag )
 1071:   everychar
 1072:   dup #del = IF  drop #bs  THEN  \ del is rubout
 1073:   dup bl <   IF  cells ctrlkeys + perform  EXIT  THEN
 1074:   >r 2over = IF  rdrop bell 0 EXIT  THEN
 1075:   r> insert-char 0 ;
 1076: 
 1077: : accept   ( addr len -- len ) \ core
 1078:   dup 0< IF    abs over dup 1 chars - c@ tuck type 
 1079: \ this allows to edit given strings
 1080:   ELSE  0  THEN rot over
 1081:   BEGIN  key decode  UNTIL
 1082:   2drop nip ;
 1083: 
 1084: \ Output                                               13feb93py
 1085: 
 1086: has-os [IF]
 1087: 0 Value outfile-id ( -- file-id ) \ gforth
 1088: 
 1089: : (type) ( c-addr u -- ) \ gforth
 1090:     outfile-id write-file drop \ !! use ?DUP-IF THROW ENDIF instead of DROP ?
 1091: ;
 1092: 
 1093: : (emit) ( c -- ) \ gforth
 1094:     outfile-id emit-file drop \ !! use ?DUP-IF THROW ENDIF instead of DROP ?
 1095: ;
 1096: [THEN]
 1097: 
 1098: Defer type ( c-addr u -- ) \ core
 1099: ' (type) IS Type
 1100: 
 1101: Defer emit ( c -- ) \ core
 1102: ' (Emit) IS Emit
 1103: 
 1104: Defer key ( -- c ) \ core
 1105: ' (key) IS key
 1106: 
 1107: \ Query                                                07apr93py
 1108: 
 1109: has-files 0= [IF]
 1110: : sourceline# ( -- n )  loadline @ ;
 1111: [THEN]
 1112: 
 1113: : refill ( -- flag ) \ core-ext,block-ext,file-ext
 1114:   blk @  IF  1 blk +!  true  0 >in !  EXIT  THEN
 1115:   tib /line
 1116: [ has-files [IF] ]
 1117:   loadfile @ ?dup
 1118:   IF    read-line throw
 1119:   ELSE
 1120: [ [THEN] ]
 1121:       sourceline# 0< IF 2drop false EXIT THEN
 1122:       accept true
 1123: [ has-files [IF] ]
 1124:   THEN
 1125: [ [THEN] ]
 1126:   1 loadline +!
 1127:   swap #tib ! 0 >in ! ;
 1128: 
 1129: : query   ( -- ) \ core-ext
 1130:     \G obsolescent
 1131:     blk off loadfile off
 1132:     tib /line accept #tib ! 0 >in ! ;
 1133: 
 1134: \ save-mem extend-mem
 1135: 
 1136: has-os [IF]
 1137: : save-mem	( addr1 u -- addr2 u ) \ gforth
 1138:     \g copy a memory block into a newly allocated region in the heap
 1139:     swap >r
 1140:     dup allocate throw
 1141:     swap 2dup r> -rot move ;
 1142: 
 1143: : extend-mem	( addr1 u1 u -- addr addr2 u2 )
 1144:     \ extend memory block allocated from the heap by u aus
 1145:     \ the (possibly reallocated piece is addr2 u2, the extension is at addr
 1146:     over >r + dup >r resize throw
 1147:     r> over r> + -rot ;
 1148: [THEN]
 1149: 
 1150: \ HEX DECIMAL                                           2may93jaw
 1151: 
 1152: : decimal ( -- ) \ core
 1153:     a base ! ;
 1154: : hex ( -- ) \ core-ext
 1155:     10 base ! ;
 1156: 
 1157: \ DEPTH                                                 9may93jaw
 1158: 
 1159: : depth ( -- +n ) \ core
 1160:     sp@ s0 @ swap - cell / ;
 1161: : clearstack ( ... -- )
 1162:     s0 @ sp! ;
 1163: 
 1164: \ RECURSE                                               17may93jaw
 1165: 
 1166: : recurse ( compilation -- ; run-time ?? -- ?? ) \ core
 1167:     lastxt compile, ; immediate restrict
 1168: ' reveal alias recursive ( -- ) \ gforth
 1169: 	immediate
 1170: 
 1171: \ */MOD */                                              17may93jaw
 1172: 
 1173: \ !! I think */mod should have the same rounding behaviour as / - anton
 1174: : */mod ( n1 n2 n3 -- n4 n5 ) \ core	star-slash-mod
 1175:     >r m* r> sm/rem ;
 1176: 
 1177: : */ ( n1 n2 n3 -- n4 ) \ core	star-slash
 1178:     */mod nip ;
 1179: 
 1180: \ EVALUATE                                              17may93jaw
 1181: 
 1182: has-files 0= [IF]
 1183: : push-file  ( -- )  r>
 1184:   sourceline# >r  tibstack @ >r  >tib @ >r  #tib @ >r
 1185:   >tib @ tibstack @ = IF  r@ tibstack +!  THEN
 1186:   tibstack @ >tib ! >in @ >r  >r ;
 1187: 
 1188: : pop-file   ( throw-code -- throw-code )
 1189:   r>
 1190:   r> >in !  r> #tib !  r> >tib !  r> tibstack !  r> loadline !  >r ;
 1191: [THEN]
 1192: 
 1193: : evaluate ( c-addr len -- ) \ core,block
 1194:   push-file  #tib ! >tib !
 1195:   >in off blk off loadfile off -1 loadline !
 1196:   ['] interpret catch
 1197:   pop-file throw ;
 1198: 
 1199: : abort ( ?? -- ?? ) \ core,exception-ext
 1200:     -1 throw ;
 1201: 
 1202: \+ environment? true ENV" CORE"
 1203: \ core wordset is now complete!
 1204: 
 1205: \ Quit                                                 13feb93py
 1206: 
 1207: Defer 'quit
 1208: Defer .status
 1209: : prompt        state @ IF ."  compiled" EXIT THEN ."  ok" ;
 1210: : (Query)  ( -- )
 1211:     loadfile off  blk off  refill drop ;
 1212: : (quit)  BEGIN  .status cr (query) interpret prompt  AGAIN ;
 1213: ' (quit) IS 'quit
 1214: 
 1215: \ DOERROR (DOERROR)                                     13jun93jaw
 1216: 
 1217: 8 Constant max-errors
 1218: Variable error-stack  0 error-stack !
 1219: max-errors 6 * cells allot
 1220: \ format of one cell:
 1221: \ source ( addr u )
 1222: \ >in
 1223: \ line-number
 1224: \ Loadfilename ( addr u )
 1225: 
 1226: : dec. ( n -- ) \ gforth
 1227:     \ print value in decimal representation
 1228:     base @ decimal swap . base ! ;
 1229: 
 1230: : hex. ( u -- ) \ gforth
 1231:     \ print value as unsigned hex number
 1232:     '$ emit base @ swap hex u. base ! ;
 1233: 
 1234: : typewhite ( addr u -- ) \ gforth
 1235:     \ like type, but white space is printed instead of the characters
 1236:     bounds ?do
 1237: 	i c@ #tab = if \ check for tab
 1238: 	    #tab
 1239: 	else
 1240: 	    bl
 1241: 	then
 1242: 	emit
 1243:     loop ;
 1244: 
 1245: DEFER DOERROR
 1246: 
 1247: : .error-frame ( addr1 u1 n1 n2 addr2 u2 -- )
 1248:   cr error-stack @
 1249:   IF
 1250:      ." in file included from "
 1251:      type ." :" dec.  drop 2drop
 1252:   ELSE
 1253:      type ." :" dec.
 1254:      cr dup 2over type cr drop
 1255:      nip -trailing 1- ( line-start index2 )
 1256:      0 >r  BEGIN
 1257:                   2dup + c@ bl >  WHILE
 1258: 		  r> 1+ >r  1- dup 0<  UNTIL  THEN  1+
 1259:      ( line-start index1 )
 1260:      typewhite
 1261:      r> 1 max 0 ?do \ we want at least one "^", even if the length is 0
 1262:                   [char] ^ emit
 1263:      loop
 1264:   THEN
 1265: ;
 1266: 
 1267: : (DoError) ( throw-code -- )
 1268:   [ has-os [IF] ]
 1269:       outfile-id dup flush-file drop >r
 1270:       stderr to outfile-id
 1271:   [ [THEN] ] 
 1272:   sourceline# IF
 1273:                source >in @ sourceline# 0 0 .error-frame
 1274:   THEN
 1275:   error-stack @ 0 ?DO
 1276:     -1 error-stack +!
 1277:     error-stack dup @ 6 * cells + cell+
 1278:     6 cells bounds DO
 1279:       I @
 1280:     cell +LOOP
 1281:     .error-frame
 1282:   LOOP
 1283:   dup -2 =
 1284:   IF 
 1285:      "error @ ?dup
 1286:      IF
 1287:         cr count type 
 1288:      THEN
 1289:      drop
 1290:   ELSE
 1291:      .error
 1292:   THEN
 1293:   normal-dp dpp !
 1294:   [ has-os [IF] ] r> to outfile-id [ [THEN] ] 
 1295: ;
 1296: 
 1297: ' (DoError) IS DoError
 1298: 
 1299: : quit ( ?? -- ?? ) \ core
 1300:     r0 @ rp! handler off >tib @ >r
 1301:     BEGIN
 1302: 	postpone [
 1303: 	['] 'quit CATCH dup
 1304:     WHILE
 1305: 	DoError r@ >tib ! r@ tibstack !
 1306:     REPEAT
 1307:     drop r> >tib ! ;
 1308: 
 1309: \ Cold                                                 13feb93py
 1310: 
 1311: \ : .name ( name -- ) name>string type space ;
 1312: \ : words  listwords @
 1313: \          BEGIN  @ dup  WHILE  dup .name  REPEAT drop ;
 1314: Defer 'cold ( -- ) \ gforth tick-cold
 1315: \ hook (deferred word) for things to do right before interpreting the
 1316: \ command-line arguments
 1317: ' noop IS 'cold
 1318: 
 1319: : cold ( -- ) \ gforth
 1320: [ has-files [IF] ]
 1321:     pathstring 2@ process-path pathdirs 2!
 1322:     init-included-files
 1323: [ [THEN] ]
 1324:     'cold
 1325: [ has-files [IF] ]
 1326:     ['] process-args catch ?dup
 1327:     IF
 1328: 	dup >r DoError cr r> negate (bye)
 1329:     THEN
 1330:     argc @ 1 >
 1331:     IF \ there may be some unfinished line, so let's finish it
 1332: 	cr
 1333:     THEN
 1334: [ [THEN] ]
 1335:     ." GForth " version-string type ." , Copyright (C) 1994-1996 Free Software Foundation, Inc." cr
 1336:     ." GForth comes with ABSOLUTELY NO WARRANTY; for details type `license'"
 1337: [ has-os [IF] ]
 1338:      cr ." Type `bye' to exit"
 1339: [ [THEN] ]
 1340:     loadline off quit ;
 1341: 
 1342: : license ( -- ) \ gforth
 1343:  cr
 1344:  ." This program is free software; you can redistribute it and/or modify" cr
 1345:  ." it under the terms of the GNU General Public License as published by" cr
 1346:  ." the Free Software Foundation; either version 2 of the License, or" cr
 1347:  ." (at your option) any later version." cr cr
 1348: 
 1349:  ." This program is distributed in the hope that it will be useful," cr
 1350:  ." but WITHOUT ANY WARRANTY; without even the implied warranty of" cr
 1351:  ." MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" cr
 1352:  ." GNU General Public License for more details." cr cr
 1353: 
 1354:  ." You should have received a copy of the GNU General Public License" cr
 1355:  ." along with this program; if not, write to the Free Software" cr
 1356:  ." Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." cr ;
 1357: 
 1358: : boot ( path **argv argc -- )
 1359:     main-task up!
 1360: [ has-os [IF] ]
 1361:     stdout TO outfile-id
 1362: [ [THEN] ]
 1363: [ has-files [IF] ]
 1364:     argc ! argv ! pathstring 2!
 1365: [ [THEN] ]
 1366:     sp@ s0 !
 1367: [ has-locals [IF] ]
 1368:     lp@ forthstart 7 cells + @ - 
 1369: [ [ELSE] ]
 1370:     [ has-os [IF] ]
 1371:     sp@ $1040 +
 1372:     [ [ELSE] ]
 1373:     sp@ $40 +
 1374:     [ [THEN] ]
 1375: [ [THEN] ]
 1376:     dup >tib ! tibstack ! #tib off >in off
 1377:     rp@ r0 !
 1378: [ has-floats [IF] ]
 1379:     fp@ f0 !
 1380: [ [THEN] ]
 1381:     ['] cold catch DoError
 1382: [ has-os [IF] ]
 1383:     bye
 1384: [ [THEN] ]
 1385: ;
 1386: 
 1387: has-os [IF]
 1388: : bye ( -- ) \ tools-ext
 1389: [ has-files [IF] ]
 1390:     script? 0= IF  cr  THEN
 1391: [ [ELSE] ]
 1392:     cr
 1393: [ [THEN] ]
 1394:     0 (bye) ;
 1395: [THEN]
 1396: 
 1397: \ **argv may be scanned by the C starter to get some important
 1398: \ information, as -display and -geometry for an X client FORTH
 1399: \ or space and stackspace overrides
 1400: 
 1401: \ 0 arg contains, however, the name of the program.
 1402: 
 1403: 

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