1: \ kernel.fs GForth kernel 17dec92py
2:
3: \ Copyright (C) 1995,1998,2000,2003,2004,2005 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., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20:
21: \ Idea and implementation: Bernd Paysan (py)
22:
23: \ Needs:
24:
25: require ./vars.fs
26: require ../compat/strcomp.fs
27:
28: hex
29:
30: \ labels for some code addresses
31:
32: \- NIL NIL AConstant NIL \ gforth
33:
34: \ Aliases
35:
36: [IFUNDEF] r@
37: ' i Alias r@ ( -- w ; R: w -- w ) \ core r-fetch
38: [THEN]
39:
40: \ !! this is machine-dependent, but works on all but the strangest machines
41:
42: : maxaligned ( addr1 -- addr2 ) \ gforth
43: \G @i{addr2} is the first address after @i{addr1} that satisfies
44: \G all alignment restrictions.
45: [ /maxalign 1 - ] Literal + [ 0 /maxalign - ] Literal and ;
46: \ !! machine-dependent and won't work if "0 >body" <> "0 >body
47: \G maxaligned"
48: ' maxaligned Alias cfaligned ( addr1 -- addr2 ) \ gforth
49: \G @i{addr2} is the first address after @i{addr1} that is aligned for
50: \G a code field (i.e., such that the corresponding body is maxaligned).
51:
52: : chars ( n1 -- n2 ) \ core
53: \G @i{n2} is the number of address units of @i{n1} chars.""
54: ; immediate
55:
56:
57: \ : A! ( addr1 addr2 -- ) \ gforth
58: \ dup relon ! ;
59: \ : A, ( addr -- ) \ gforth
60: \ here cell allot A! ;
61: ' ! alias A! ( addr1 addr2 -- ) \ gforth
62:
63: \ UNUSED 17may93jaw
64:
65: has? ec [IF]
66: unlock ram-dictionary borders nip lock
67: AConstant dictionary-end
68: [ELSE]
69: has? header [IF]
70: : dictionary-end ( -- addr )
71: forthstart [ 3 cells image-header + ] Aliteral @ + ;
72: [ELSE]
73: : forthstart 0 ;
74: : dictionary-end ( -- addr )
75: forthstart [ has? kernel-size ] Literal + ;
76: [THEN]
77: [THEN]
78:
79: : usable-dictionary-end ( -- addr )
80: dictionary-end [ word-pno-size pad-minsize + ] Literal - ;
81:
82: : unused ( -- u ) \ core-ext
83: \G Return the amount of free space remaining (in address units) in
84: \G the region addressed by @code{here}.
85: usable-dictionary-end here - ;
86:
87: has? ec [IF]
88: : in-dictionary? ( x -- f )
89: dictionary-end u< ;
90: [ELSE]
91: : in-dictionary? ( x -- f )
92: forthstart dictionary-end within ;
93: [THEN]
94:
95: \ here is used for pad calculation!
96:
97: : dp ( -- addr ) \ gforth
98: dpp @ ;
99: : here ( -- addr ) \ core
100: \G Return the address of the next free location in data space.
101: dp @ ;
102:
103: \ on off 23feb93py
104:
105: \ on is used by docol:
106: : on ( a-addr -- ) \ gforth
107: \G Set the (value of the) variable at @i{a-addr} to @code{true}.
108: true swap ! ;
109: : off ( a-addr -- ) \ gforth
110: \G Set the (value of the) variable at @i{a-addr} to @code{false}.
111: false swap ! ;
112:
113: \ dabs roll 17may93jaw
114:
115: : dabs ( d -- ud ) \ double d-abs
116: dup 0< IF dnegate THEN ;
117:
118: : roll ( x0 x1 .. xn n -- x1 .. xn x0 ) \ core-ext
119: \ dup 1+ pick >r
120: \ cells sp@ cell+ dup cell+ rot move drop r> ;
121: recursive
122: dup 0<= if
123: drop
124: else
125: swap >r 1- roll r> swap
126: then ;
127:
128: \ place bounds 13feb93py
129:
130: : place ( addr len to -- ) \ gforth
131: over >r rot over 1+ r> move c! ;
132: : bounds ( addr u -- addr+u addr ) \ gforth
133: \G Given a memory block represented by starting address @i{addr}
134: \G and length @i{u} in aus, produce the end address @i{addr+u} and
135: \G the start address in the right order for @code{u+do} or
136: \G @code{?do}.
137: over + swap ;
138:
139: \ (word) 22feb93py
140:
141: : scan ( addr1 n1 char -- addr2 n2 ) \ gforth
142: \G skip all characters not equal to char
143: >r
144: BEGIN
145: dup
146: WHILE
147: over c@ r@ <>
148: WHILE
149: 1 /string
150: REPEAT THEN
151: rdrop ;
152: : skip ( addr1 n1 char -- addr2 n2 ) \ gforth
153: \G skip all characters equal to char
154: >r
155: BEGIN
156: dup
157: WHILE
158: over c@ r@ =
159: WHILE
160: 1 /string
161: REPEAT THEN
162: rdrop ;
163:
164: \ digit? 17dec92py
165:
166: : digit? ( char -- digit true/ false ) \ gforth
167: toupper [char] 0 - dup 9 u> IF
168: [ char A char 9 1 + - ] literal -
169: dup 9 u<= IF
170: drop false EXIT
171: THEN
172: THEN
173: dup base @ u>= IF
174: drop false EXIT
175: THEN
176: true ;
177:
178: : accumulate ( +d0 addr digit - +d1 addr )
179: swap >r swap base @ um* drop rot base @ um* d+ r> ;
180:
181: : >number ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 ) \ core to-number
182: \G Attempt to convert the character string @var{c-addr1 u1} to an
183: \G unsigned number in the current number base. The double
184: \G @var{ud1} accumulates the result of the conversion to form
185: \G @var{ud2}. Conversion continues, left-to-right, until the whole
186: \G string is converted or a character that is not convertable in
187: \G the current number base is encountered (including + or -). For
188: \G each convertable character, @var{ud1} is first multiplied by
189: \G the value in @code{BASE} and then incremented by the value
190: \G represented by the character. @var{c-addr2} is the location of
191: \G the first unconverted character (past the end of the string if
192: \G the whole string was converted). @var{u2} is the number of
193: \G unconverted characters in the string. Overflow is not detected.
194: 0
195: ?DO
196: count digit?
197: WHILE
198: accumulate
199: LOOP
200: 0
201: ELSE
202: 1- I' I -
203: UNLOOP
204: THEN ;
205:
206: \ s>d um/mod 21mar93py
207:
208: : s>d ( n -- d ) \ core s-to-d
209: dup 0< ;
210:
211: : ud/mod ( ud1 u2 -- urem udquot ) \ gforth
212: >r 0 r@ um/mod r> swap >r
213: um/mod r> ;
214:
215: \ catch throw 23feb93py
216:
217: has? glocals [IF]
218: : lp@ ( -- addr ) \ gforth lp-fetch
219: laddr# [ 0 , ] ;
220: [THEN]
221:
222: has? ec [IF]
223: : catch ( ... xt -- ... 0 )
224: handler @ >r sp@ >r
225: rp@ handler ! execute 0 r> drop r> handler ! ;
226: : throw ( error -- error ) dup 0= IF drop EXIT THEN
227: handler @ rp! r> swap >r sp! r> r> handler ! ;
228: [ELSE]
229: defer catch ( x1 .. xn xt -- y1 .. ym 0 / z1 .. zn error ) \ exception
230: \G @code{Executes} @i{xt}. If execution returns normally,
231: \G @code{catch} pushes 0 on the stack. If execution returns through
232: \G @code{throw}, all the stacks are reset to the depth on entry to
233: \G @code{catch}, and the TOS (the @i{xt} position) is replaced with
234: \G the throw code.
235:
236: :noname ( ... xt -- ... 0 )
237: execute 0 ;
238: is catch
239:
240: defer throw ( y1 .. ym nerror -- y1 .. ym / z1 .. zn error ) \ exception
241: \G If @i{nerror} is 0, drop it and continue. Otherwise, transfer
242: \G control to the next dynamically enclosing exception handler, reset
243: \G the stacks accordingly, and push @i{nerror}.
244:
245: :noname ( y1 .. ym error -- y1 .. ym / z1 .. zn error )
246: ?dup if
247: [ has? header [IF] here image-header 9 cells + ! [THEN] ]
248: cr .error cr
249: [ has? file [IF] ] script? IF 1 (bye) ELSE quit THEN
250: [ [ELSE] ] quit [ [THEN] ]
251: then ;
252: is throw
253: [THEN]
254:
255: \ (abort")
256:
257: : c(abort") ( c-addr -- )
258: "error ! -2 throw ;
259:
260: : (abort")
261: "lit >r
262: IF
263: r> "error ! -2 throw
264: THEN
265: rdrop ;
266:
267: : abort ( ?? -- ?? ) \ core,exception-ext
268: \G @code{-1 throw}.
269: -1 throw ;
270:
271: \ ?stack 23feb93py
272:
273: : ?stack ( ?? -- ?? ) \ gforth
274: sp@ sp0 @ u> IF -4 throw THEN
275: [ has? floating [IF] ]
276: fp@ fp0 @ u> IF -&45 throw THEN
277: [ [THEN] ]
278: ;
279: \ ?stack should be code -- it touches an empty stack!
280:
281: \ DEPTH 9may93jaw
282:
283: : depth ( -- +n ) \ core depth
284: \G @var{+n} is the number of values that were on the data stack before
285: \G @var{+n} itself was placed on the stack.
286: sp@ sp0 @ swap - cell / ;
287:
288: : clearstack ( ... -- ) \ gforth clear-stack
289: \G remove and discard all/any items from the data stack.
290: sp0 @ sp! ;
291:
292: : clearstacks ( ... -- ) \ gforth clear-stacks
293: \G empty data and FP stack
294: clearstack
295: [ has? floating [IF] ]
296: fp0 @ fp!
297: [ [THEN] ]
298: ;
299:
300: \ Strings 22feb93py
301:
302: : "lit ( -- addr )
303: r> r> dup count + aligned >r swap >r ;
304:
305: \ HEX DECIMAL 2may93jaw
306:
307: : decimal ( -- ) \ core
308: \G Set @code{base} to &10 (decimal).
309: a base ! ;
310: : hex ( -- ) \ core-ext
311: \G Set @code{base} to &16 (hexadecimal).
312: 10 base ! ;
313:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>