[gforth] / gforth / kernel / int.fs  

gforth: gforth/kernel/int.fs


1 : pazsan 1.1 \ definitions needed for interpreter only
2 :    
3 : anton 1.160 \ Copyright (C) 1995-2000,2004,2005,2007 Free Software Foundation, Inc.
4 : anton 1.11
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 : anton 1.161 \ as published by the Free Software Foundation, either version 3
10 : anton 1.11 \ 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 : anton 1.161 \ along with this program. If not, see http://www.gnu.org/licenses/.
19 : anton 1.11
20 : pazsan 1.1 \ \ Revision-Log
21 :    
22 :     \ put in seperate file 14sep97jaw
23 :    
24 :     \ \ input stream primitives 23feb93py
25 :    
26 : jwilke 1.33 require ./basics.fs \ bounds decimal hex ...
27 :     require ./io.fs \ type ...
28 :     require ./nio.fs \ . <# ...
29 :     require ./errore.fs \ .error ...
30 : anton 1.165 require kernel/version.fs \ version-string
31 : jwilke 1.33
32 : pazsan 1.64 has? new-input 0= [IF]
33 : crook 1.43 : tib ( -- c-addr ) \ core-ext t-i-b
34 : crook 1.40 \G @i{c-addr} is the address of the Terminal Input Buffer.
35 : crook 1.29 \G OBSOLESCENT: @code{source} superceeds the function of this word.
36 : pazsan 1.1 >tib @ ;
37 :    
38 : crook 1.29 Defer source ( -- c-addr u ) \ core
39 : pazsan 1.1 \ used by dodefer:, must be defer
40 : crook 1.40 \G @i{c-addr} is the address of the input buffer and @i{u} is the
41 : crook 1.29 \G number of characters in it.
42 : pazsan 1.1
43 : crook 1.29 : (source) ( -- c-addr u )
44 : pazsan 1.1 tib #tib @ ;
45 :     ' (source) IS source
46 : pazsan 1.64 [THEN]
47 : pazsan 1.1
48 :     : (word) ( addr1 n1 char -- addr2 n2 )
49 :     dup >r skip 2dup r> scan nip - ;
50 :    
51 :     \ (word) should fold white spaces
52 :     \ this is what (parse-white) does
53 :    
54 :     \ word parse 23feb93py
55 :    
56 : anton 1.130 : sword ( char -- addr len ) \ gforth-obsolete s-word
57 :     \G Parses like @code{word}, but the output is like @code{parse} output.
58 :     \G @xref{core-idef}.
59 :     \ this word was called PARSE-WORD until 0.3.0, but Open Firmware and
60 :     \ dpANS6 A.6.2.2008 have a word with that name that behaves
61 :     \ differently (like NAME).
62 :     source 2dup >r >r >in @ over min /string
63 :     rot dup bl = IF
64 :     drop (parse-white)
65 :     ELSE
66 :     (word)
67 :     THEN
68 : pazsan 1.138 [ has? new-input [IF] ]
69 : anton 1.132 2dup input-lexeme!
70 : pazsan 1.138 [ [THEN] ]
71 : anton 1.130 2dup + r> - 1+ r> min >in ! ;
72 : pazsan 1.1
73 : crook 1.29 : word ( char "<chars>ccc<char>-- c-addr ) \ core
74 : crook 1.40 \G Skip leading delimiters. Parse @i{ccc}, delimited by
75 :     \G @i{char}, in the parse area. @i{c-addr} is the address of a
76 : crook 1.29 \G transient region containing the parsed string in
77 : crook 1.40 \G counted-string format. If the parse area was empty or
78 : crook 1.29 \G contained no characters other than delimiters, the resulting
79 :     \G string has zero length. A program may replace characters within
80 :     \G the counted string. OBSOLESCENT: the counted string has a
81 :     \G trailing space that is not included in its length.
82 :     sword here place bl here count + c! here ;
83 :    
84 :     : parse ( char "ccc<char>" -- c-addr u ) \ core-ext
85 : anton 1.80 \G Parse @i{ccc}, delimited by @i{char}, in the parse
86 :     \G area. @i{c-addr u} specifies the parsed string within the
87 :     \G parse area. If the parse area was empty, @i{u} is 0.
88 : anton 1.132 >r source >in @ over min /string ( c-addr1 u1 )
89 : anton 1.130 over swap r> scan >r
90 : anton 1.132 over - dup r> IF 1+ THEN >in +!
91 : pazsan 1.138 [ has? new-input [IF] ]
92 :     2dup input-lexeme!
93 :     [ [THEN] ] ;
94 : pazsan 1.1
95 :     \ name 13feb93py
96 :    
97 :     [IFUNDEF] (name) \ name might be a primitive
98 :    
99 : crook 1.40 : (name) ( -- c-addr count ) \ gforth
100 : pazsan 1.1 source 2dup >r >r >in @ /string (parse-white)
101 : pazsan 1.138 [ has? new-input [IF] ]
102 : anton 1.132 2dup input-lexeme!
103 : pazsan 1.138 [ [THEN] ]
104 : pazsan 1.1 2dup + r> - 1+ r> min >in ! ;
105 :     \ name count ;
106 :     [THEN]
107 :    
108 :     : name-too-short? ( c-addr u -- c-addr u )
109 :     dup 0= -&16 and throw ;
110 :    
111 :     : name-too-long? ( c-addr u -- c-addr u )
112 : anton 1.67 dup lcount-mask u> -&19 and throw ;
113 : pazsan 1.1
114 :     \ \ Number parsing 23feb93py
115 :    
116 :     \ number? number 23feb93py
117 :    
118 :     hex
119 : anton 1.110 const Create bases 0A , 10 , 2 , 0A ,
120 : anton 1.109 \ 10 16 2 10
121 : pazsan 1.1
122 : anton 1.18 \ !! protect BASE saving wrapper against exceptions
123 : pazsan 1.1 : getbase ( addr u -- addr' u' )
124 : anton 1.108 2dup s" 0x" string-prefix? >r
125 :     2dup s" 0X" string-prefix? r> or
126 : anton 1.117 base @ &34 < and if
127 : anton 1.108 hex 2 /string
128 :     endif
129 : anton 1.109 over c@ [char] # - dup 4 u<
130 : pazsan 1.1 IF
131 :     cells bases + @ base ! 1 /string
132 :     ELSE
133 :     drop
134 :     THEN ;
135 :    
136 : anton 1.124 : sign? ( addr u -- addr1 u1 flag )
137 : jwilke 1.33 over c@ [char] - = dup >r
138 : pazsan 1.1 IF
139 :     1 /string
140 :     THEN
141 : pazsan 1.20 r> ;
142 :    
143 : anton 1.159 : ?dnegate ( d1 f -- d2 )
144 :     if
145 :     dnegate
146 :     then ;
147 :    
148 : pazsan 1.157 has? os 0= [IF]
149 :     : x@+/string ( addr u -- addr' u' c )
150 :     over c@ >r 1 /string r> ;
151 :     [THEN]
152 :    
153 : anton 1.109 : s'>unumber? ( addr u -- ud flag )
154 :     \ convert string "C" or "C'" to character code
155 :     dup 0= if
156 :     false exit
157 :     endif
158 : anton 1.116 x@+/string 0 s" '" 2rot string-prefix? ;
159 : anton 1.109
160 : anton 1.159 : s>unumber? ( c-addr u -- ud flag ) \ gforth
161 :     \G converts string c-addr u into ud, flag indicates success
162 : anton 1.121 dpl on
163 : anton 1.109 over c@ '' = if
164 :     1 /string s'>unumber? exit
165 :     endif
166 : anton 1.166 base @ >r getbase sign?
167 :     over if
168 :     >r 0. 2swap
169 :     BEGIN ( d addr len )
170 :     dup >r >number dup
171 :     WHILE \ there are characters left
172 :     dup r> -
173 :     WHILE \ the last >number parsed something
174 :     dup 1- dpl ! over c@ [char] . =
175 :     WHILE \ the current char is '.'
176 :     1 /string
177 :     REPEAT THEN \ there are unparseable characters left
178 :     2drop rdrop false
179 :     ELSE
180 :     rdrop 2drop r> ?dnegate true
181 :     THEN
182 : pazsan 1.20 ELSE
183 : anton 1.166 drop 2drop 0. false THEN
184 : pazsan 1.21 r> base ! ;
185 : pazsan 1.20
186 :     \ ouch, this is complicated; there must be a simpler way - anton
187 : anton 1.125 : s>number? ( addr u -- d f ) \ gforth
188 :     \G converts string addr u into d, flag indicates success
189 : pazsan 1.21 sign? >r
190 : pazsan 1.20 s>unumber?
191 :     0= IF
192 : pazsan 1.21 rdrop false
193 : anton 1.18 ELSE \ no characters left, all ok
194 : anton 1.159 r> ?dnegate
195 : anton 1.18 true
196 : pazsan 1.21 THEN ;
197 : pazsan 1.1
198 : anton 1.18 : s>number ( addr len -- d )
199 :     \ don't use this, there is no way to tell success
200 :     s>number? drop ;
201 :    
202 : pazsan 1.1 : snumber? ( c-addr u -- 0 / n -1 / d 0> )
203 : anton 1.18 s>number? 0=
204 : pazsan 1.1 IF
205 :     2drop false EXIT
206 :     THEN
207 : anton 1.18 dpl @ dup 0< IF
208 : pazsan 1.1 nip
209 : anton 1.18 ELSE
210 :     1+
211 : pazsan 1.1 THEN ;
212 :    
213 :     : number? ( string -- string 0 / n -1 / d 0> )
214 :     dup >r count snumber? dup if
215 :     rdrop
216 :     else
217 :     r> swap
218 :     then ;
219 :    
220 :     : number ( string -- d )
221 :     number? ?dup 0= abort" ?" 0<
222 :     IF
223 :     s>d
224 :     THEN ;
225 :    
226 :     \ \ Comments ( \ \G
227 :    
228 : crook 1.29 : ( ( compilation 'ccc<close-paren>' -- ; run-time -- ) \ thisone- core,file paren
229 : crook 1.17 \G ** this will not get annotated. The alias in glocals.fs will instead **
230 : crook 1.29 \G It does not work to use "wordset-" prefix since this file is glossed
231 :     \G by cross.fs which doesn't have the same functionalty as makedoc.fs
232 : pazsan 1.1 [char] ) parse 2drop ; immediate
233 :    
234 : anton 1.51 : \ ( compilation 'ccc<newline>' -- ; run-time -- ) \ thisone- core-ext,block-ext backslash
235 : crook 1.29 \G ** this will not get annotated. The alias in glocals.fs will instead **
236 :     \G It does not work to use "wordset-" prefix since this file is glossed
237 :     \G by cross.fs which doesn't have the same functionalty as makedoc.fs
238 : pazsan 1.12 [ has? file [IF] ]
239 : pazsan 1.1 blk @
240 :     IF
241 :     >in @ c/l / 1+ c/l * >in !
242 :     EXIT
243 :     THEN
244 : pazsan 1.12 [ [THEN] ]
245 : pazsan 1.1 source >in ! drop ; immediate
246 :    
247 : anton 1.51 : \G ( compilation 'ccc<newline>' -- ; run-time -- ) \ gforth backslash-gee
248 : crook 1.19 \G Equivalent to @code{\} but used as a tag to annotate definition
249 :     \G comments into documentation.
250 : pazsan 1.1 POSTPONE \ ; immediate
251 :    
252 : pazsan 1.139 has? ec [IF]
253 :     AVariable forth-wordlist
254 :     : find-name ( c-addr u -- nt | 0 ) \ gforth
255 :     \g Find the name @i{c-addr u} in the current search
256 :     \g order. Return its @i{nt}, if found, otherwise 0.
257 : pazsan 1.149 forth-wordlist (f83find) ;
258 : pazsan 1.139 [ELSE]
259 : pazsan 1.1 \ \ object oriented search list 17mar93py
260 :    
261 :     \ word list structure:
262 :    
263 :     struct
264 :     cell% field find-method \ xt: ( c_addr u wid -- nt )
265 :     cell% field reveal-method \ xt: ( nt wid -- ) \ used by dofield:, must be field
266 :     cell% field rehash-method \ xt: ( wid -- ) \ re-initializes a "search-data" (hashtables)
267 :     cell% field hash-method \ xt: ( wid -- ) \ initializes ""
268 :     \ \ !! what else
269 :     end-struct wordlist-map-struct
270 :    
271 :     struct
272 : pazsan 1.6 cell% field wordlist-map \ pointer to a wordlist-map-struct
273 : anton 1.13 cell% field wordlist-id \ linked list of words (for WORDS etc.)
274 : pazsan 1.1 cell% field wordlist-link \ link field to other wordlists
275 : anton 1.13 cell% field wordlist-extend \ wordlist extensions (eg bucket offset)
276 : pazsan 1.1 end-struct wordlist-struct
277 :    
278 : pazsan 1.103 has? f83headerstring [IF]
279 :     : f83find ( addr len wordlist -- nt / false )
280 :     wordlist-id @ (f83find) ;
281 :     [ELSE]
282 : pazsan 1.1 : f83find ( addr len wordlist -- nt / false )
283 : anton 1.67 wordlist-id @ (listlfind) ;
284 : pazsan 1.103 [THEN]
285 : pazsan 1.1
286 :     : initvoc ( wid -- )
287 :     dup wordlist-map @ hash-method perform ;
288 :    
289 :     \ Search list table: find reveal
290 :     Create f83search ( -- wordlist-map )
291 :     ' f83find A, ' drop A, ' drop A, ' drop A,
292 :    
293 : pazsan 1.6 here G f83search T A, NIL A, NIL A, NIL A,
294 : pazsan 1.1 AValue forth-wordlist \ variable, will be redefined by search.fs
295 :    
296 :     AVariable lookup forth-wordlist lookup !
297 :     \ !! last is user and lookup?! jaw
298 :     AVariable current ( -- addr ) \ gforth
299 : crook 1.43 \G @code{Variable} -- holds the @i{wid} of the compilation word list.
300 : pazsan 1.1 AVariable voclink forth-wordlist wordlist-link voclink !
301 : anton 1.38 \ lookup AValue context ( -- addr ) \ gforth
302 :     Defer context ( -- addr ) \ gforth
303 : crook 1.43 \G @code{context} @code{@@} is the @i{wid} of the word list at the
304 :     \G top of the search order.
305 : pazsan 1.1
306 : anton 1.38 ' lookup is context
307 : pazsan 1.1 forth-wordlist current !
308 :    
309 : pazsan 1.139 : (search-wordlist) ( addr count wid -- nt | false )
310 :     dup wordlist-map @ find-method perform ;
311 :    
312 :     : search-wordlist ( c-addr count wid -- 0 | xt +-1 ) \ search
313 :     \G Search the word list identified by @i{wid} for the definition
314 :     \G named by the string at @i{c-addr count}. If the definition is
315 :     \G not found, return 0. If the definition is found return 1 (if
316 :     \G the definition is immediate) or -1 (if the definition is not
317 :     \G immediate) together with the @i{xt}. In Gforth, the @i{xt}
318 :     \G returned represents the interpretation semantics. ANS Forth
319 :     \G does not specify clearly what @i{xt} represents.
320 :     (search-wordlist) dup if
321 :     (name>intn)
322 :     then ;
323 :    
324 :     : find-name ( c-addr u -- nt | 0 ) \ gforth
325 :     \g Find the name @i{c-addr u} in the current search
326 :     \g order. Return its @i{nt}, if found, otherwise 0.
327 :     lookup @ (search-wordlist) ;
328 :     [THEN]
329 :    
330 : pazsan 1.1 \ \ header, finding, ticks 17dec92py
331 :    
332 : pazsan 1.69 \ The constants are defined as 32 bits, but then erased
333 :     \ and overwritten by the right ones
334 : anton 1.67
335 : pazsan 1.103 has? f83headerstring [IF]
336 :     \ to save space, Gforth EC limits words to 31 characters
337 :     $80 constant alias-mask
338 :     $40 constant immediate-mask
339 :     $20 constant restrict-mask
340 :     $1f constant lcount-mask
341 :     [ELSE]
342 : anton 1.67 $80000000 constant alias-mask
343 : pazsan 1.69 1 bits/char 1 - lshift
344 :     -1 cells allot bigendian [IF] c, 0 1 cells 1- times
345 :     [ELSE] 0 1 cells 1- times c, [THEN]
346 : anton 1.67 $40000000 constant immediate-mask
347 : pazsan 1.69 1 bits/char 2 - lshift
348 :     -1 cells allot bigendian [IF] c, 0 1 cells 1- times
349 :     [ELSE] 0 1 cells 1- times c, [THEN]
350 : anton 1.67 $20000000 constant restrict-mask
351 : pazsan 1.69 1 bits/char 3 - lshift
352 :     -1 cells allot bigendian [IF] c, 0 1 cells 1- times
353 :     [ELSE] 0 1 cells 1- times c, [THEN]
354 : anton 1.67 $1fffffff constant lcount-mask
355 : pazsan 1.69 1 bits/char 3 - lshift 1 -
356 : pazsan 1.71 -1 cells allot bigendian [IF] c, -1 1 cells 1- times
357 :     [ELSE] -1 1 cells 1- times c, [THEN]
358 : pazsan 1.103 [THEN]
359 : pazsan 1.1
360 :     \ higher level parts of find
361 :    
362 :     : flag-sign ( f -- 1|-1 )
363 :     \ true becomes 1, false -1
364 :     0= 2* 1+ ;
365 :    
366 : anton 1.79 : ticking-compile-only-error ( ... -- )
367 :     -&2048 throw ;
368 : pazsan 1.1
369 : anton 1.93 : compile-only-error ( ... -- )
370 :     -&14 throw ;
371 :    
372 : pazsan 1.1 : (cfa>int) ( cfa -- xt )
373 :     [ has? compiler [IF] ]
374 :     dup interpret/compile?
375 :     if
376 :     interpret/compile-int @
377 :     then
378 :     [ [THEN] ] ;
379 :    
380 : anton 1.67 : (x>int) ( cfa w -- xt )
381 : pazsan 1.1 \ get interpretation semantics of name
382 : pazsan 1.141 restrict-mask and [ has? rom [IF] ] 0= [ [THEN] ]
383 : pazsan 1.1 if
384 : anton 1.93 drop ['] compile-only-error
385 : pazsan 1.1 else
386 :     (cfa>int)
387 :     then ;
388 :    
389 : pazsan 1.103 has? f83headerstring [IF]
390 : anton 1.155 : name>string ( nt -- addr count ) \ gforth name-to-string
391 : pazsan 1.103 \g @i{addr count} is the name of the word represented by @i{nt}.
392 :     cell+ count lcount-mask and ;
393 :    
394 :     : ((name>)) ( nfa -- cfa )
395 :     name>string + cfaligned ;
396 :    
397 :     : (name>x) ( nfa -- cfa w )
398 :     \ cfa is an intermediate cfa and w is the flags cell of nfa
399 :     dup ((name>))
400 :     swap cell+ c@ dup alias-mask and 0=
401 :     IF
402 :     swap @ swap
403 :     THEN ;
404 :     [ELSE]
405 : anton 1.155 : name>string ( nt -- addr count ) \ gforth name-to-string
406 : crook 1.40 \g @i{addr count} is the name of the word represented by @i{nt}.
407 : anton 1.67 cell+ dup cell+ swap @ lcount-mask and ;
408 : pazsan 1.1
409 :     : ((name>)) ( nfa -- cfa )
410 :     name>string + cfaligned ;
411 :    
412 : anton 1.67 : (name>x) ( nfa -- cfa w )
413 :     \ cfa is an intermediate cfa and w is the flags cell of nfa
414 : pazsan 1.1 dup ((name>))
415 : anton 1.67 swap cell+ @ dup alias-mask and 0=
416 : pazsan 1.1 IF
417 :     swap @ swap
418 :     THEN ;
419 : pazsan 1.103 [THEN]
420 : pazsan 1.1
421 : anton 1.155 : name>int ( nt -- xt ) \ gforth name-to-int
422 : crook 1.31 \G @i{xt} represents the interpretation semantics of the word
423 :     \G @i{nt}. If @i{nt} has no interpretation semantics (i.e. is
424 :     \G @code{compile-only}), @i{xt} is the execution token for
425 : anton 1.79 \G @code{ticking-compile-only-error}, which performs @code{-2048 throw}.
426 : pazsan 1.1 (name>x) (x>int) ;
427 :    
428 : anton 1.155 : name?int ( nt -- xt ) \ gforth name-question-int
429 : anton 1.79 \G Like @code{name>int}, but perform @code{-2048 throw} if @i{nt}
430 : crook 1.31 \G has no interpretation semantics.
431 : pazsan 1.141 (name>x) restrict-mask and [ has? rom [IF] ] 0= [ [THEN] ]
432 : pazsan 1.1 if
433 : anton 1.79 ticking-compile-only-error \ does not return
434 : pazsan 1.1 then
435 :     (cfa>int) ;
436 :    
437 :     : (name>comp) ( nt -- w +-1 ) \ gforth
438 : crook 1.31 \G @i{w xt} is the compilation token for the word @i{nt}.
439 : pazsan 1.1 (name>x) >r
440 :     [ has? compiler [IF] ]
441 :     dup interpret/compile?
442 :     if
443 :     interpret/compile-comp @
444 :     then
445 :     [ [THEN] ]
446 : pazsan 1.141 r> immediate-mask and [ has? rom [IF] ] 0= [ [THEN] ] flag-sign
447 : pazsan 1.1 ;
448 :    
449 :     : (name>intn) ( nfa -- xt +-1 )
450 : anton 1.67 (name>x) tuck (x>int) ( w xt )
451 : pazsan 1.141 swap immediate-mask and [ has? rom [IF] ] 0= [ [THEN] ] flag-sign ;
452 : pazsan 1.1
453 : pazsan 1.72 const Create ??? 0 , 3 , char ? c, char ? c, char ? c,
454 : jwilke 1.30 \ ??? is used by dovar:, must be created/:dovar
455 :    
456 :     [IFDEF] forthstart
457 :     \ if we have a forthstart we can define head? with it
458 :     \ otherwise leave out the head? check
459 :    
460 : anton 1.14 : head? ( addr -- f )
461 : anton 1.82 \G heuristic check whether addr is a name token; may deliver false
462 :     \G positives; addr must be a valid address; returns 1 for
463 :     \G particularly unsafe positives
464 : anton 1.14 \ we follow the link fields and check for plausibility; two
465 :     \ iterations should catch most false addresses: on the first
466 :     \ iteration, we may get an xt, on the second a code address (or
467 :     \ some code), which is typically not in the dictionary.
468 : anton 1.82 \ we added a third iteration for working with code and ;code words.
469 :     3 0 do
470 : anton 1.41 dup dup aligned <> if \ protect @ against unaligned accesses
471 :     drop false unloop exit
472 :     then
473 : anton 1.14 dup @ dup
474 :     if ( addr addr1 )
475 :     dup rot forthstart within
476 :     if \ addr1 is outside forthstart..addr, not a head
477 :     drop false unloop exit
478 :     then ( addr1 )
479 :     else \ 0 in the link field, no further checks
480 : anton 1.81 2drop 1 unloop exit \ this is very unsure, so return 1
481 : anton 1.14 then
482 :     loop
483 :     \ in dubio pro:
484 :     drop true ;
485 :    
486 : anton 1.48 : >head-noprim ( cfa -- nt ) \ gforth to-head-noprim
487 : anton 1.97 \ also heuristic
488 : pazsan 1.157 dup forthstart - max-name-length @
489 :     [ has? float [IF] ] float+ [ [ELSE] ] cell+ [ [THEN] ] cell+ min
490 :     cell max cell ?do ( cfa )
491 : pazsan 1.70 dup i - dup @ [ alias-mask lcount-mask or ] literal
492 :     [ 1 bits/char 3 - lshift 1 - 1 bits/char 1 - lshift or
493 : pazsan 1.71 -1 cells allot bigendian [IF] c, -1 1 cells 1- times
494 :     [ELSE] -1 1 cells 1- times c, [THEN] ]
495 : pazsan 1.70 and ( cfa len|alias )
496 : anton 1.97 swap + cell+ cfaligned over alias-mask + =
497 : anton 1.14 if ( cfa )
498 :     dup i - cell - dup head?
499 :     if
500 :     nip unloop exit
501 :     then
502 :     drop
503 :     then
504 :     cell +loop
505 :     drop ??? ( wouldn't 0 be better? ) ;
506 : pazsan 1.1
507 : jwilke 1.30 [ELSE]
508 :    
509 : anton 1.48 : >head-noprim ( cfa -- nt ) \ gforth to-head-noprim
510 : pazsan 1.45 $25 cell do ( cfa )
511 : pazsan 1.70 dup i - dup @ [ alias-mask lcount-mask or ] literal
512 :     [ 1 bits/char 3 - lshift 1 - 1 bits/char 1 - lshift or
513 : pazsan 1.71 -1 cells allot bigendian [IF] c, -1 1 cells 1- times
514 :     [ELSE] -1 1 cells 1- times c, [THEN] ]
515 : pazsan 1.70 and ( cfa len|alias )
516 : anton 1.67 swap + cell + cfaligned over alias-mask + =
517 : jwilke 1.30 if ( cfa ) i - cell - unloop exit
518 :     then
519 :     cell +loop
520 :     drop ??? ( wouldn't 0 be better? ) ;
521 :    
522 :     [THEN]
523 : pazsan 1.1
524 : anton 1.158 cell% 2* 0 0 field >body ( xt -- a_addr ) \ core to-body
525 : anton 1.83 \G Get the address of the body of the word represented by @i{xt} (the
526 :     \G address of the word's data field).
527 :     drop drop
528 :    
529 :     cell% -2 * 0 0 field body> ( xt -- a_addr )
530 : anton 1.84 drop drop
531 :    
532 :     has? standardthreading has? compiler and [IF]
533 :    
534 :     ' @ alias >code-address ( xt -- c_addr ) \ gforth
535 :     \G @i{c-addr} is the code address of the word @i{xt}.
536 :    
537 :     : >does-code ( xt -- a_addr ) \ gforth
538 :     \G If @i{xt} is the execution token of a child of a @code{DOES>} word,
539 :     \G @i{a-addr} is the start of the Forth code after the @code{DOES>};
540 :     \G Otherwise @i{a-addr} is 0.
541 :     dup @ dodoes: = if
542 :     cell+ @
543 :     else
544 :     drop 0
545 :     endif ;
546 :    
547 : pazsan 1.157 has? prims [IF]
548 :     : flash! ! ;
549 :     : flashc! c! ;
550 :     [THEN]
551 :    
552 : pazsan 1.142 has? flash [IF] ' flash! [ELSE] ' ! [THEN]
553 :     alias code-address! ( c_addr xt -- ) \ gforth
554 : anton 1.85 \G Create a code field with code address @i{c-addr} at @i{xt}.
555 :    
556 :     : does-code! ( a_addr xt -- ) \ gforth
557 :     \G Create a code field at @i{xt} for a child of a @code{DOES>}-word;
558 :     \G @i{a-addr} is the start of the Forth code after @code{DOES>}.
559 : pazsan 1.142 [ has? flash [IF] ]
560 :     dodoes: over flash! cell+ flash!
561 :     [ [ELSE] ]
562 :     dodoes: over ! cell+ !
563 :     [ [THEN] ] ;
564 : anton 1.85
565 : anton 1.86 ' drop alias does-handler! ( a_addr -- ) \ gforth
566 :     \G Create a @code{DOES>}-handler at address @i{a-addr}. Normally,
567 :     \G @i{a-addr} points just behind a @code{DOES>}.
568 :    
569 : anton 1.85 2 cells constant /does-handler ( -- n ) \ gforth
570 :     \G The size of a @code{DOES>}-handler (includes possible padding).
571 :    
572 : anton 1.84 [THEN]
573 : pazsan 1.1
574 :     : sfind ( c-addr u -- 0 / xt +-1 ) \ gforth-obsolete
575 :     find-name dup
576 :     if ( nt )
577 :     state @
578 :     if
579 :     (name>comp)
580 :     else
581 :     (name>intn)
582 :     then
583 :     then ;
584 :    
585 : crook 1.31 : find ( c-addr -- xt +-1 | c-addr 0 ) \ core,search
586 : anton 1.53 \G Search all word lists in the current search order for the
587 :     \G definition named by the counted string at @i{c-addr}. If the
588 :     \G definition is not found, return 0. If the definition is found
589 :     \G return 1 (if the definition has non-default compilation
590 :     \G semantics) or -1 (if the definition has default compilation
591 :     \G semantics). The @i{xt} returned in interpret state represents
592 :     \G the interpretation semantics. The @i{xt} returned in compile
593 :     \G state represented either the compilation semantics (for
594 :     \G non-default compilation semantics) or the run-time semantics
595 :     \G that the compilation semantics would @code{compile,} (for
596 :     \G default compilation semantics). The ANS Forth standard does
597 :     \G not specify clearly what the returned @i{xt} represents (and
598 :     \G also talks about immediacy instead of non-default compilation
599 :     \G semantics), so this word is questionable in portable programs.
600 :     \G If non-portability is ok, @code{find-name} and friends are
601 :     \G better (@pxref{Name token}).
602 : pazsan 1.1 dup count sfind dup
603 :     if
604 :     rot drop
605 :     then ;
606 :    
607 : jwilke 1.34 \ ticks in interpreter
608 : pazsan 1.1
609 :     : (') ( "name" -- nt ) \ gforth
610 : pazsan 1.139 parse-name name-too-short?
611 : anton 1.28 find-name dup 0=
612 : pazsan 1.1 IF
613 : anton 1.42 drop -&13 throw
614 : pazsan 1.1 THEN ;
615 :    
616 :     : ' ( "name" -- xt ) \ core tick
617 : crook 1.31 \g @i{xt} represents @i{name}'s interpretation
618 :     \g semantics. Perform @code{-14 throw} if the word has no
619 : pazsan 1.1 \g interpretation semantics.
620 :     (') name?int ;
621 : jwilke 1.34
622 :     has? compiler 0= [IF] \ interpreter only version of IS and TO
623 :    
624 :     : IS ' >body ! ;
625 :     ' IS Alias TO
626 :    
627 :     [THEN]
628 : pazsan 1.1
629 :     \ \ the interpreter loop mar92py
630 :    
631 :     \ interpret 10mar92py
632 :    
633 : anton 1.120 Defer parser1 ( c-addr u -- ... xt)
634 :     \ "... xt" is the action to be performed by the text-interpretation of c-addr u
635 :    
636 :     : parser ( c-addr u -- ... )
637 :     \ text-interpret the word/number c-addr u, possibly producing a number
638 :     parser1 execute ;
639 :    
640 : pazsan 1.139 has? ec [IF]
641 :     ' (name) Alias parse-name
642 : pazsan 1.140 : no.extensions 2drop -&13 throw ;
643 : pazsan 1.139 ' no.extensions Alias compiler-notfound1
644 :     ' no.extensions Alias interpreter-notfound1
645 :     [ELSE]
646 : anton 1.119 Defer parse-name ( "name" -- c-addr u ) \ gforth
647 : anton 1.55 \G Get the next word from the input buffer
648 : anton 1.119 ' (name) IS parse-name
649 : anton 1.77
650 : anton 1.119 ' parse-name alias parse-word ( -- c-addr u ) \ gforth-obsolete
651 :     \G old name for @code{parse-name}
652 :    
653 :     ' parse-name alias name ( -- c-addr u ) \ gforth-obsolete
654 :     \G old name for @code{parse-name}
655 :    
656 : anton 1.120 Defer compiler-notfound1 ( c-addr count -- ... xt )
657 :     Defer interpreter-notfound1 ( c-addr count -- ... xt )
658 : pazsan 1.1
659 :     : no.extensions ( addr u -- )
660 : anton 1.42 2drop -&13 throw ;
661 : anton 1.120 ' no.extensions IS compiler-notfound1
662 :     ' no.extensions IS interpreter-notfound1
663 : pazsan 1.1
664 : anton 1.106 Defer before-word ( -- ) \ gforth
665 :     \ called before the text interpreter parses the next word
666 :     ' noop IS before-word
667 : pazsan 1.139 [THEN]
668 : anton 1.106
669 : pazsan 1.149 has? backtrace [IF]
670 : anton 1.66 : interpret1 ( ... -- ... )
671 : anton 1.24 rp@ backtrace-rp0 !
672 : pazsan 1.1 BEGIN
673 : pazsan 1.139 ?stack [ has? EC 0= [IF] ] before-word [ [THEN] ] parse-name dup
674 : pazsan 1.1 WHILE
675 : anton 1.120 parser1 execute
676 : pazsan 1.1 REPEAT
677 : anton 1.66 2drop ;
678 :    
679 :     : interpret ( ?? -- ?? ) \ gforth
680 :     \ interpret/compile the (rest of the) input buffer
681 :     backtrace-rp0 @ >r
682 :     ['] interpret1 catch
683 : anton 1.65 r> backtrace-rp0 !
684 : pazsan 1.154 throw ;
685 : pazsan 1.149 [ELSE]
686 :     : interpret ( ... -- ... )
687 :     BEGIN
688 :     ?stack [ has? EC 0= [IF] ] before-word [ [THEN] ] parse-name dup
689 :     WHILE
690 :     parser1 execute
691 :     REPEAT
692 :     2drop ;
693 :     [THEN]
694 : pazsan 1.1
695 :     \ interpreter 30apr92py
696 :    
697 :     \ not the most efficient implementations of interpreter and compiler
698 : anton 1.120 : interpreter1 ( c-addr u -- ... xt )
699 : pazsan 1.1 2dup find-name dup
700 :     if
701 : anton 1.120 nip nip name>int
702 : pazsan 1.1 else
703 :     drop
704 :     2dup 2>r snumber?
705 :     IF
706 : anton 1.120 2rdrop ['] noop
707 : pazsan 1.1 ELSE
708 : anton 1.120 2r> interpreter-notfound1
709 : pazsan 1.1 THEN
710 :     then ;
711 :    
712 : anton 1.120 ' interpreter1 IS parser1
713 : pazsan 1.1
714 :     \ \ Query Evaluate 07apr93py
715 :    
716 :     has? file 0= [IF]
717 : pazsan 1.12 : sourceline# ( -- n ) 1 ;
718 : pazsan 1.61 [ELSE]
719 : pazsan 1.64 has? new-input 0= [IF]
720 : pazsan 1.58 Variable #fill-bytes
721 :     \G number of bytes read via (read-line) by the last refill
722 : pazsan 1.61 [THEN]
723 : pazsan 1.64 [THEN]
724 : pazsan 1.58
725 : pazsan 1.64 has? new-input 0= [IF]
726 : pazsan 1.138 : input-start-line ( -- ) >in off ;
727 : pazsan 1.1 : refill ( -- flag ) \ core-ext,block-ext,file-ext
728 : crook 1.29 \G Attempt to fill the input buffer from the input source. When
729 :     \G the input source is the user input device, attempt to receive
730 :     \G input into the terminal input device. If successful, make the
731 :     \G result the input buffer, set @code{>IN} to 0 and return true;
732 :     \G otherwise return false. When the input source is a block, add 1
733 :     \G to the value of @code{BLK} to make the next block the input
734 :     \G source and current input buffer, and set @code{>IN} to 0;
735 :     \G return true if the new value of @code{BLK} is a valid block
736 :     \G number, false otherwise. When the input source is a text file,
737 :     \G attempt to read the next line from the file. If successful,
738 :     \G make the result the current input buffer, set @code{>IN} to 0
739 :     \G and return true; otherwise, return false. A successful result
740 :     \G includes receipt of a line containing 0 characters.
741 : pazsan 1.12 [ has? file [IF] ]
742 : pazsan 1.138 blk @ IF 1 blk +! true EXIT THEN
743 : pazsan 1.12 [ [THEN] ]
744 :     tib /line
745 :     [ has? file [IF] ]
746 :     loadfile @ ?dup
747 : pazsan 1.59 IF (read-line) throw #fill-bytes !
748 : pazsan 1.12 ELSE
749 :     [ [THEN] ]
750 :     sourceline# 0< IF 2drop false EXIT THEN
751 : pazsan 1.145 accept eof @ 0=
752 : pazsan 1.12 [ has? file [IF] ]
753 :     THEN
754 :     1 loadline +!
755 :     [ [THEN] ]
756 : pazsan 1.138 swap #tib !
757 :     input-start-line ;
758 : pazsan 1.1
759 :     : query ( -- ) \ core-ext
760 : crook 1.29 \G Make the user input device the input source. Receive input into
761 :     \G the Terminal Input Buffer. Set @code{>IN} to zero. OBSOLESCENT:
762 :     \G superceeded by @code{accept}.
763 : pazsan 1.12 [ has? file [IF] ]
764 :     blk off loadfile off
765 :     [ [THEN] ]
766 : pazsan 1.64 refill drop ;
767 :     [THEN]
768 : pazsan 1.1
769 :     \ save-mem extend-mem
770 :    
771 :     has? os [IF]
772 :     : save-mem ( addr1 u -- addr2 u ) \ gforth
773 :     \g copy a memory block into a newly allocated region in the heap
774 :     swap >r
775 :     dup allocate throw
776 :     swap 2dup r> -rot move ;
777 :    
778 : anton 1.68 : free-mem-var ( addr -- )
779 :     \ addr is the address of a 2variable containing address and size
780 :     \ of a memory range; frees memory and clears the 2variable.
781 :     dup 2@ drop dup
782 :     if ( addr mem-start )
783 :     free throw
784 :     0 0 rot 2!
785 :     else
786 :     2drop
787 :     then ;
788 :    
789 : pazsan 1.1 : extend-mem ( addr1 u1 u -- addr addr2 u2 )
790 :     \ extend memory block allocated from the heap by u aus
791 : anton 1.105 \ the (possibly reallocated) piece is addr2 u2, the extension is at addr
792 : pazsan 1.1 over >r + dup >r resize throw
793 :     r> over r> + -rot ;
794 :     [THEN]
795 :    
796 :     \ EVALUATE 17may93jaw
797 :    
798 : pazsan 1.64 has? file 0= has? new-input 0= and [IF]
799 : pazsan 1.1 : push-file ( -- ) r>
800 : pazsan 1.12 tibstack @ >r >tib @ >r #tib @ >r
801 : pazsan 1.1 >tib @ tibstack @ = IF r@ tibstack +! THEN
802 :     tibstack @ >tib ! >in @ >r >r ;
803 :    
804 :     : pop-file ( throw-code -- throw-code )
805 :     r>
806 : pazsan 1.12 r> >in ! r> #tib ! r> >tib ! r> tibstack ! >r ;
807 : pazsan 1.1 [THEN]
808 :    
809 : pazsan 1.64 has? new-input 0= [IF]
810 : crook 1.29 : evaluate ( c-addr u -- ) \ core,block
811 : crook 1.40 \G Save the current input source specification. Store @code{-1} in
812 :     \G @code{source-id} and @code{0} in @code{blk}. Set @code{>IN} to
813 :     \G @code{0} and make the string @i{c-addr u} the input source
814 :     \G and input buffer. Interpret. When the parse area is empty,
815 :     \G restore the input source specification.
816 : pazsan 1.64 [ has? file [IF] ]
817 : anton 1.92 s" *evaluated string*" loadfilename>r
818 : pazsan 1.64 [ [THEN] ]
819 : crook 1.40 push-file #tib ! >tib !
820 : anton 1.130 input-start-line
821 : crook 1.29 [ has? file [IF] ]
822 :     blk off loadfile off -1 loadline !
823 :     [ [THEN] ]
824 :     ['] interpret catch
825 : anton 1.56 pop-file
826 : pazsan 1.64 [ has? file [IF] ]
827 : anton 1.92 r>loadfilename
828 : pazsan 1.64 [ [THEN] ]
829 : anton 1.56 throw ;
830 : pazsan 1.64 [THEN]
831 : pazsan 1.1
832 :     \ \ Quit 13feb93py
833 :    
834 :     Defer 'quit
835 :    
836 : pazsan 1.156 has? os [IF]
837 : pazsan 1.157 Defer .status
838 :     [ELSE]
839 : pazsan 1.164 [IFUNDEF] bye
840 :     : (bye) ( 0 -- ) \ back to DOS
841 :     drop 5 emit ;
842 :    
843 :     : bye ( -- ) 0 (bye) ;
844 :     [THEN]
845 : pazsan 1.149 [THEN]
846 : pazsan 1.1
847 :     : prompt state @ IF ." compiled" EXIT THEN ." ok" ;
848 :    
849 : anton 1.39 : (quit) ( -- )
850 :     \ exits only through THROW etc.
851 :     BEGIN
852 : pazsan 1.149 [ has? ec [IF] ] cr [ [ELSE] ]
853 :     .status ['] cr catch if
854 : pazsan 1.144 [ has? OS [IF] ] >stderr [ [THEN] ]
855 :     cr ." Can't print to stdout, leaving" cr
856 : anton 1.98 \ if stderr does not work either, already DoError causes a hang
857 :     2 (bye)
858 : pazsan 1.149 endif [ [THEN] ]
859 : pazsan 1.138 refill WHILE
860 : anton 1.122 interpret prompt
861 :     REPEAT
862 :     bye ;
863 : pazsan 1.1
864 :     ' (quit) IS 'quit
865 :    
866 :     \ \ DOERROR (DOERROR) 13jun93jaw
867 :    
868 : pazsan 1.156 has? os [IF]
869 : pazsan 1.1 8 Constant max-errors
870 : anton 1.130 5 has? file 2 and + Constant /error
871 : pazsan 1.1 Variable error-stack 0 error-stack !
872 : pazsan 1.112 max-errors /error * cells allot
873 : pazsan 1.1 \ format of one cell:
874 : anton 1.133 \ source ( c-addr u )
875 :     \ last parsed lexeme ( c-addr u )
876 : pazsan 1.1 \ line-number
877 :     \ Loadfilename ( addr u )
878 :    
879 : anton 1.133 : error> ( -- c-addr1 u1 c-addr2 u2 line# [addr u] )
880 : pazsan 1.64 -1 error-stack +!
881 :     error-stack dup @
882 : pazsan 1.112 /error * cells + cell+
883 :     /error cells bounds DO
884 : anton 1.130 I @
885 :     cell +LOOP ;
886 :    
887 : anton 1.133 : >error ( c-addr1 u1 c-addr2 u2 line# [addr u] -- )
888 : pazsan 1.64 error-stack dup @ dup 1+
889 :     max-errors 1- min error-stack !
890 : pazsan 1.112 /error * cells + cell+
891 :     /error 1- cells bounds swap DO
892 : anton 1.130 I !
893 :     -1 cells +LOOP ;
894 :    
895 : anton 1.133 : input-error-data ( -- c-addr1 u1 c-addr2 u2 line# [addr u] )
896 : anton 1.130 \ error data for the current input, to be used by >error or .error-frame
897 : anton 1.133 source input-lexeme 2@ sourceline#
898 : anton 1.130 [ has? file [IF] ] sourcefilename [ [THEN] ] ;
899 : pazsan 1.64
900 : pazsan 1.1 : dec. ( n -- ) \ gforth
901 : crook 1.40 \G Display @i{n} as a signed decimal number, followed by a space.
902 :     \ !! not used...
903 : pazsan 1.1 base @ decimal swap . base ! ;
904 :    
905 : anton 1.111 : dec.r ( u n -- ) \ gforth
906 :     \G Display @i{u} as a unsigned decimal number in a field @i{n}
907 :     \G characters wide.
908 :     base @ >r decimal .r r> base ! ;
909 : jwilke 1.23
910 : pazsan 1.1 : hex. ( u -- ) \ gforth
911 : crook 1.40 \G Display @i{u} as an unsigned hex number, prefixed with a "$" and
912 : crook 1.17 \G followed by a space.
913 : crook 1.40 \ !! not used...
914 : jwilke 1.33 [char] $ emit base @ swap hex u. base ! ;
915 : pazsan 1.1
916 : anton 1.94 : -trailing ( c_addr u1 -- c_addr u2 ) \ string dash-trailing
917 :     \G Adjust the string specified by @i{c-addr, u1} to remove all
918 :     \G trailing spaces. @i{u2} is the length of the modified string.
919 :     BEGIN
920 : pazsan 1.102 dup
921 : anton 1.94 WHILE
922 : pazsan 1.102 1- 2dup + c@ bl <>
923 :     UNTIL 1+ THEN ;
924 : anton 1.94
925 : pazsan 1.1 DEFER DOERROR
926 : jwilke 1.33
927 :     has? backtrace [IF]
928 : anton 1.15 Defer dobacktrace ( -- )
929 :     ' noop IS dobacktrace
930 : jwilke 1.33 [THEN]
931 : pazsan 1.1
932 : jwilke 1.23 : .error-string ( throw-code -- )
933 :     dup -2 =
934 :     IF "error @ ?dup IF count type THEN drop
935 :     ELSE .error
936 :     THEN ;
937 :    
938 : anton 1.111 : umin ( u1 u2 -- u )
939 :     2dup u>
940 :     if
941 :     swap
942 :     then
943 :     drop ;
944 :    
945 : pazsan 1.112 Defer mark-start
946 :     Defer mark-end
947 :    
948 :     :noname ." >>>" ; IS mark-start
949 :     :noname ." <<<" ; IS mark-end
950 :    
951 : anton 1.130 : part-type ( addr1 u1 u -- addr2 u2 )
952 :     \ print first u characters of addr1 u1, addr2 u2 is the rest
953 : anton 1.133 over umin 2 pick over type /string ;
954 : anton 1.130
955 : anton 1.133 : .error-line ( c-addr1 u1 c-addr2 u2 -- )
956 :     \ print error in line c-addr1 u1, where the error-causing lexeme
957 :     \ is c-addr2 u2
958 :     >r 2 pick - part-type ( c-addr3 u3 R: u2 )
959 :     mark-start r> part-type mark-end ( c-addr4 u4 )
960 :     type ;
961 : anton 1.130
962 : anton 1.133 : .error-frame ( throwcode addr1 u1 addr2 u2 n2 [addr3 u3] -- throwcode )
963 :     \ addr3 u3: filename of included file - optional
964 : anton 1.130 \ n2: line number
965 : anton 1.133 \ addr2 u2: parsed lexeme (should be marked as causing the error)
966 : anton 1.130 \ addr1 u1: input line
967 :     error-stack @
968 :     IF ( throwcode addr1 u1 n0 n1 n2 [addr2 u2] )
969 :     [ has? file [IF] ] \ !! unbalanced stack effect
970 : pazsan 1.129 over IF
971 :     cr ." in file included from "
972 :     type ." :"
973 : anton 1.130 0 dec.r 2drop 2drop
974 :     ELSE
975 :     2drop 2drop 2drop drop
976 :     THEN
977 :     [ [THEN] ] ( throwcode addr1 u1 n0 n1 n2 )
978 :     ELSE ( throwcode addr1 u1 n0 n1 n2 [addr2 u2] )
979 :     [ has? file [IF] ]
980 :     cr type ." :"
981 :     [ [THEN] ] ( throwcode addr1 u1 n0 n1 n2 )
982 :     dup 0 dec.r ." : " 5 pick .error-string
983 :     IF \ if line# non-zero, there is a line
984 :     cr .error-line
985 :     ELSE
986 :     2drop 2drop
987 :     THEN
988 :     THEN ;
989 : pazsan 1.1
990 :     : (DoError) ( throw-code -- )
991 :     [ has? os [IF] ]
992 : pazsan 1.8 >stderr
993 : pazsan 1.1 [ [THEN] ]
994 : anton 1.130 input-error-data .error-frame
995 : pazsan 1.1 error-stack @ 0 ?DO
996 : pazsan 1.64 error>
997 : pazsan 1.1 .error-frame
998 :     LOOP
999 : jwilke 1.33 drop
1000 :     [ has? backtrace [IF] ]
1001 :     dobacktrace
1002 :     [ [THEN] ]
1003 : pazsan 1.8 normal-dp dpp ! ;
1004 : pazsan 1.1
1005 :     ' (DoError) IS DoError
1006 : pazsan 1.131
1007 :     [ELSE]
1008 :     : dec. base @ >r decimal . r> base ! ;
1009 : pazsan 1.144 : DoError ( throw-code -- )
1010 : pazsan 1.145 cr source drop >in @ type ." <<< "
1011 : pazsan 1.144 dup -2 = IF "error @ type drop EXIT THEN
1012 :     .error ;
1013 : pazsan 1.131 [THEN]
1014 : pazsan 1.1
1015 :     : quit ( ?? -- ?? ) \ core
1016 : crook 1.27 \G Empty the return stack, make the user input device
1017 :     \G the input source, enter interpret state and start
1018 :     \G the text interpreter.
1019 : pazsan 1.64 rp0 @ rp! handler off clear-tibstack
1020 :     [ has? new-input 0= [IF] ] >tib @ >r [ [THEN] ]
1021 : pazsan 1.1 BEGIN
1022 :     [ has? compiler [IF] ]
1023 : anton 1.104 [compile] [
1024 : pazsan 1.1 [ [THEN] ]
1025 : anton 1.104 \ stack depths may be arbitrary here
1026 : pazsan 1.1 ['] 'quit CATCH dup
1027 :     WHILE
1028 : anton 1.104 <# \ reset hold area, or we may get another error
1029 :     DoError
1030 :     \ stack depths may be arbitrary still (or again), so clear them
1031 :     clearstacks
1032 :     [ has? new-input [IF] ] clear-tibstack
1033 :     [ [ELSE] ] r@ >tib ! r@ tibstack !
1034 :     [ [THEN] ]
1035 : pazsan 1.1 REPEAT
1036 : pazsan 1.64 drop [ has? new-input [IF] ] clear-tibstack
1037 :     [ [ELSE] ] r> >tib !
1038 :     [ [THEN] ] ;
1039 : pazsan 1.1
1040 :     \ \ Cold Boot 13feb93py
1041 :    
1042 : anton 1.158 : (bootmessage) ( -- )
1043 : anton 1.101 ." Gforth " version-string type
1044 : anton 1.163 ." , Copyright (C) 1995-2008 Free Software Foundation, Inc." cr
1045 : anton 1.101 ." Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'"
1046 : pazsan 1.1 [ has? os [IF] ]
1047 :     cr ." Type `bye' to exit"
1048 :     [ [THEN] ] ;
1049 :    
1050 : anton 1.158 defer bootmessage ( -- ) \ gforth
1051 : anton 1.150 \G Hook (deferred word) executed right after interpreting the OS
1052 :     \G command-line arguments. Normally prints the Gforth startup
1053 :     \G message.
1054 :    
1055 : pazsan 1.135 has? file [IF]
1056 : pazsan 1.1 defer process-args
1057 : pazsan 1.135 [THEN]
1058 : pazsan 1.1
1059 :     ' (bootmessage) IS bootmessage
1060 :    
1061 : pazsan 1.156 has? os [IF]
1062 : anton 1.10 Defer 'cold ( -- ) \ gforth tick-cold
1063 : anton 1.150 \G Hook (deferred word) for things to do right before interpreting the
1064 :     \G OS command-line arguments. Normally does some initializations that
1065 :     \G you also want to perform.
1066 : pazsan 1.1 ' noop IS 'cold
1067 : pazsan 1.148 [THEN]
1068 : pazsan 1.1
1069 :     : cold ( -- ) \ gforth
1070 : pazsan 1.149 [ has? backtrace [IF] ]
1071 : anton 1.44 rp@ backtrace-rp0 !
1072 :     [ [THEN] ]
1073 : pazsan 1.1 [ has? file [IF] ]
1074 : pazsan 1.78 os-cold
1075 : pazsan 1.1 [ [THEN] ]
1076 : pazsan 1.156 [ has? os [IF] ]
1077 : anton 1.116 set-encoding-fixed-width
1078 : pazsan 1.136 'cold
1079 : pazsan 1.126 [ [THEN] ]
1080 : pazsan 1.1 [ has? file [IF] ]
1081 : pazsan 1.8 process-args
1082 : pazsan 1.12 loadline off
1083 : pazsan 1.1 [ [THEN] ]
1084 :     bootmessage
1085 : pazsan 1.12 quit ;
1086 : pazsan 1.1
1087 : pazsan 1.64 has? new-input 0= [IF]
1088 : anton 1.5 : clear-tibstack ( -- )
1089 :     [ has? glocals [IF] ]
1090 :     lp@ forthstart 7 cells + @ -
1091 :     [ [ELSE] ]
1092 :     [ has? os [IF] ]
1093 : pazsan 1.8 r0 @ forthstart 6 cells + @ -
1094 : anton 1.5 [ [ELSE] ]
1095 : pazsan 1.139 sp@ cell+
1096 : anton 1.5 [ [THEN] ]
1097 :     [ [THEN] ]
1098 : pazsan 1.138 dup >tib ! tibstack ! #tib off
1099 :     input-start-line ;
1100 : pazsan 1.64 [THEN]
1101 : anton 1.5
1102 : pazsan 1.64 : boot ( path n **argv argc -- )
1103 : pazsan 1.134 [ has? no-userspace 0= [IF] ]
1104 : pazsan 1.1 main-task up!
1105 : pazsan 1.134 [ [THEN] ]
1106 : pazsan 1.1 [ has? os [IF] ]
1107 : pazsan 1.78 os-boot
1108 : pazsan 1.134 [ [THEN] ]
1109 :     [ has? rom [IF] ]
1110 : pazsan 1.147 ram-shadow dup @ dup -1 <> >r u> r> and IF
1111 :     ram-shadow 2@ ELSE
1112 :     ram-mirror ram-size THEN ram-start swap move
1113 : pazsan 1.1 [ [THEN] ]
1114 :     sp@ sp0 !
1115 : pazsan 1.74 [ has? peephole [IF] ]
1116 : anton 1.87 \ only needed for greedy static superinstruction selection
1117 :     \ primtable prepare-peephole-table TO peeptable
1118 : pazsan 1.74 [ [THEN] ]
1119 : pazsan 1.64 [ has? new-input [IF] ]
1120 :     current-input off
1121 :     [ [THEN] ]
1122 : anton 1.5 clear-tibstack
1123 : anton 1.127 0 0 includefilename 2!
1124 : pazsan 1.1 rp@ rp0 !
1125 :     [ has? floating [IF] ]
1126 :     fp@ fp0 !
1127 :     [ [THEN] ]
1128 : pazsan 1.156 [ has? os [IF] ]
1129 : anton 1.46 handler off
1130 : anton 1.98 ['] cold catch dup -&2049 <> if \ broken pipe?
1131 :     DoError cr
1132 :     endif
1133 : pazsan 1.149 [ [ELSE] ]
1134 :     cold
1135 :     [ [THEN] ]
1136 : pazsan 1.1 [ has? os [IF] ]
1137 : anton 1.35 1 (bye) \ !! determin exit code from throw code?
1138 : pazsan 1.1 [ [THEN] ]
1139 :     ;
1140 :    
1141 :     has? os [IF]
1142 :     : bye ( -- ) \ tools-ext
1143 :     [ has? file [IF] ]
1144 :     script? 0= IF cr THEN
1145 :     [ [ELSE] ]
1146 :     cr
1147 :     [ [THEN] ]
1148 :     0 (bye) ;
1149 :     [THEN]
1150 :    
1151 :     \ **argv may be scanned by the C starter to get some important
1152 :     \ information, as -display and -geometry for an X client FORTH
1153 :     \ or space and stackspace overrides
1154 :    
1155 :     \ 0 arg contains, however, the name of the program.
1156 :    

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help