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