relicense to 0BSD
[pforth] / csrc / pf_words.c
CommitLineData
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*/
32void 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*/
42void ffDotHex( cell_t n )
43{
44 MSG( ConvertNumberToText( n, 16, FALSE, 1 ) );
45 EMIT(' ');
46}
47
48/* ( ... --- ... , print stack ) */
49void 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 ) */
78cell_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 {
89DBUGX(("ffSkip BLANK: %c, %d\n", *s, Cnt ));
90 s++;
91 Cnt--;
92 }
93 }
94 else
95 {
96 while(( Cnt > 0 ) && ( *s == c ))
97 {
98DBUGX(("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 ) */
108cell_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 {
122DBUGX(("ffScan BLANK: %c, %d\n", *s, Cnt ));
123 s++;
124 Cnt--;
125 }
126 }
127 else
128 {
129 while(( Cnt > 0 ) && ( *s != c ))
130 {
131DBUGX(("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. */
145static 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. */
162cell_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 */
213static 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 222DBUGX(("Word: s2=%c, %d\n", *s2, n2 ));
8e9db35f 223 n3 = ffScan( s2, n2, c, &s3 );
f7548536 224DBUGX(("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 ) */
244char * ffWord( char c )
245{
246 return Word( c, TRUE );
247}
248
249/* ( char -- c-addr , parse word, preserving case ) */
250char * ffLWord( char c )
251{
252 return Word( c, FALSE );
253}