Commit | Line | Data |
---|---|---|
8e9db35f PB |
1 | /* @(#) pf_words.c 96/12/18 1.10 */ |
2 | /*************************************************************** | |
3 | ** Forth words for PForth based on 'C' | |
4 | ** | |
5 | ** Author: Phil Burk | |
6 | ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom | |
7 | ** | |
1f99f95d S |
8 | ** Permission to use, copy, modify, and/or distribute this |
9 | ** software for any purpose with or without fee is hereby granted. | |
10 | ** | |
11 | ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL | |
12 | ** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED | |
13 | ** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL | |
14 | ** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR | |
15 | ** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING | |
16 | ** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF | |
17 | ** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
18 | ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
8e9db35f PB |
19 | ** |
20 | ** | |
21 | ** 941031 rdg fix ffScan() to look for CRs and LFs | |
22 | ** | |
23 | ***************************************************************/ | |
24 | ||
25 | #include "pf_all.h" | |
26 | ||
27 | ||
28 | /*************************************************************** | |
29 | ** Print number in current base to output stream. | |
30 | ** This version does not handle double precision. | |
31 | */ | |
32 | void ffDot( cell_t n ) | |
33 | { | |
34 | MSG( ConvertNumberToText( n, gVarBase, TRUE, 1 ) ); | |
35 | EMIT(' '); | |
36 | } | |
37 | ||
38 | /*************************************************************** | |
39 | ** Print number in current base to output stream. | |
40 | ** This version does not handle double precision. | |
41 | */ | |
42 | void ffDotHex( cell_t n ) | |
43 | { | |
44 | MSG( ConvertNumberToText( n, 16, FALSE, 1 ) ); | |
45 | EMIT(' '); | |
46 | } | |
47 | ||
48 | /* ( ... --- ... , print stack ) */ | |
49 | void ffDotS( void ) | |
50 | { | |
51 | cell_t *sp; | |
52 | cell_t i, Depth; | |
53 | ||
54 | MSG("Stack<"); | |
55 | MSG( ConvertNumberToText( gVarBase, 10, TRUE, 1 ) ); /* Print base in decimal. */ | |
56 | MSG("> "); | |
57 | ||
58 | Depth = gCurrentTask->td_StackBase - gCurrentTask->td_StackPtr; | |
59 | sp = gCurrentTask->td_StackBase; | |
60 | ||
61 | if( Depth < 0 ) | |
62 | { | |
63 | MSG("UNDERFLOW!"); | |
64 | } | |
65 | else | |
66 | { | |
67 | for( i=0; i<Depth; i++ ) | |
68 | { | |
69 | /* Print as unsigned if not base 10. */ | |
70 | MSG( ConvertNumberToText( *(--sp), gVarBase, (gVarBase == 10), 1 ) ); | |
71 | EMIT(' '); | |
72 | } | |
73 | } | |
74 | MSG("\n"); | |
75 | } | |
76 | ||
77 | /* ( addr cnt char -- addr' cnt' , skip leading characters ) */ | |
78 | cell_t ffSkip( char *AddrIn, cell_t Cnt, char c, char **AddrOut ) | |
79 | { | |
80 | char *s; | |
81 | ||
82 | s = AddrIn; | |
83 | ||
84 | if( c == BLANK ) | |
85 | { | |
86 | while( ( Cnt > 0 ) && | |
87 | (( *s == BLANK) || ( *s == '\t')) ) | |
88 | { | |
89 | DBUGX(("ffSkip BLANK: %c, %d\n", *s, Cnt )); | |
90 | s++; | |
91 | Cnt--; | |
92 | } | |
93 | } | |
94 | else | |
95 | { | |
96 | while(( Cnt > 0 ) && ( *s == c )) | |
97 | { | |
98 | DBUGX(("ffSkip: %c=0x%x, %d\n", *s, Cnt )); | |
99 | s++; | |
100 | Cnt--; | |
101 | } | |
102 | } | |
103 | *AddrOut = s; | |
104 | return Cnt; | |
105 | } | |
106 | ||
107 | /* ( addr cnt char -- addr' cnt' , scan for char ) */ | |
108 | cell_t ffScan( char *AddrIn, cell_t Cnt, char c, char **AddrOut ) | |
109 | { | |
110 | char *s; | |
111 | ||
112 | s = AddrIn; | |
113 | ||
114 | if( c == BLANK ) | |
115 | { | |
116 | while(( Cnt > 0 ) && | |
117 | ( *s != BLANK) && | |
118 | ( *s != '\r') && | |
119 | ( *s != '\n') && | |
120 | ( *s != '\t')) | |
121 | { | |
122 | DBUGX(("ffScan BLANK: %c, %d\n", *s, Cnt )); | |
123 | s++; | |
124 | Cnt--; | |
125 | } | |
126 | } | |
127 | else | |
128 | { | |
129 | while(( Cnt > 0 ) && ( *s != c )) | |
130 | { | |
131 | DBUGX(("ffScan: %c, %d\n", *s, Cnt )); | |
132 | s++; | |
133 | Cnt--; | |
134 | } | |
135 | } | |
136 | *AddrOut = s; | |
137 | return Cnt; | |
138 | } | |
139 | ||
140 | /*************************************************************** | |
141 | ** Forth equivalent 'C' functions. | |
142 | ***************************************************************/ | |
143 | ||
144 | /* Convert a single digit to the corresponding hex number. */ | |
145 | static cell_t HexDigitToNumber( char c ) | |
146 | { | |
147 | if( (c >= '0') && (c <= '9') ) | |
148 | { | |
149 | return( c - '0' ); | |
150 | } | |
151 | else if ( (c >= 'A') && (c <= 'F') ) | |
152 | { | |
153 | return( c - 'A' + 0x0A ); | |
154 | } | |
155 | else | |
156 | { | |
157 | return -1; | |
158 | } | |
159 | } | |
160 | ||
161 | /* Convert a string to the corresponding number using BASE. */ | |
162 | cell_t ffNumberQ( const char *FWord, cell_t *Num ) | |
163 | { | |
40c6f87f | 164 | cell_t Len, i, Accum=0, n, Sign=1, Base=gVarBase; |
8e9db35f PB |
165 | const char *s; |
166 | ||
167 | /* get count */ | |
168 | Len = *FWord++; | |
169 | s = FWord; | |
170 | ||
40c6f87f HE |
171 | switch (*s) { |
172 | case '#': Base = 10; s++; Len--; break; | |
173 | case '$': Base = 16; s++; Len--; break; | |
174 | case '%': Base = 2; s++; Len--; break; | |
175 | case '\'': | |
176 | if( Len == 3 && s[2] == '\'' ) | |
177 | { | |
178 | *Num = s[1]; | |
179 | return NUM_TYPE_SINGLE; | |
180 | } | |
181 | } | |
182 | ||
8e9db35f PB |
183 | /* process initial minus sign */ |
184 | if( *s == '-' ) | |
185 | { | |
186 | Sign = -1; | |
187 | s++; | |
188 | Len--; | |
189 | } | |
190 | ||
191 | for( i=0; i<Len; i++) | |
192 | { | |
193 | n = HexDigitToNumber( *s++ ); | |
40c6f87f | 194 | if( (n < 0) || (n >= Base) ) |
8e9db35f PB |
195 | { |
196 | return NUM_TYPE_BAD; | |
197 | } | |
198 | ||
40c6f87f | 199 | Accum = (Accum * Base) + n; |
8e9db35f PB |
200 | } |
201 | *Num = Accum * Sign; | |
202 | return NUM_TYPE_SINGLE; | |
203 | } | |
204 | ||
205 | /*************************************************************** | |
206 | ** Compiler Support | |
207 | ***************************************************************/ | |
208 | ||
f7548536 HE |
209 | /* Skip whitespace, then parse input delimited by C. If UPCASE is true |
210 | * convert the word to upper case. The result is stored in | |
211 | * gScratch. | |
212 | */ | |
213 | static char * Word ( char c, int Upcase ) | |
8e9db35f PB |
214 | { |
215 | char *s1,*s2,*s3; | |
216 | cell_t n1, n2, n3; | |
217 | cell_t i, nc; | |
218 | ||
219 | s1 = gCurrentTask->td_SourcePtr + gCurrentTask->td_IN; | |
220 | n1 = gCurrentTask->td_SourceNum - gCurrentTask->td_IN; | |
221 | n2 = ffSkip( s1, n1, c, &s2 ); | |
f7548536 | 222 | DBUGX(("Word: s2=%c, %d\n", *s2, n2 )); |
8e9db35f | 223 | n3 = ffScan( s2, n2, c, &s3 ); |
f7548536 | 224 | DBUGX(("Word: s3=%c, %d\n", *s3, n3 )); |
8e9db35f PB |
225 | nc = n2-n3; |
226 | if (nc > 0) | |
227 | { | |
228 | gScratch[0] = (char) nc; | |
229 | for( i=0; i<nc; i++ ) | |
230 | { | |
f7548536 | 231 | gScratch[i+1] = Upcase ? pfCharToUpper( s2[i] ) : s2[i] ; |
8e9db35f PB |
232 | } |
233 | } | |
234 | else | |
235 | { | |
236 | ||
237 | gScratch[0] = 0; | |
238 | } | |
239 | gCurrentTask->td_IN += (n1-n3) + 1; | |
240 | return &gScratch[0]; | |
241 | } | |
f7548536 HE |
242 | |
243 | /* ( char -- c-addr , parse word ) */ | |
244 | char * ffWord( char c ) | |
245 | { | |
246 | return Word( c, TRUE ); | |
247 | } | |
248 | ||
249 | /* ( char -- c-addr , parse word, preserving case ) */ | |
250 | char * ffLWord( char c ) | |
251 | { | |
252 | return Word( c, FALSE ); | |
253 | } |