Initial import from FreeBSD RELENG_4:
[games.git] / sys / boot / ficl / testmain.c
1 /*
2 ** stub main for testing FICL
3 ** 
4 */
5
6 /* $FreeBSD: src/sys/boot/ficl/testmain.c,v 1.5.2.1 2000/07/06 23:51:45 obrien Exp $ */
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <time.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15
16 #include "ficl.h"
17
18 /*
19 ** Ficl interface to getcwd
20 ** Prints the current working directory using the VM's 
21 ** textOut method...
22 */
23 static void ficlGetCWD(FICL_VM *pVM)
24 {
25     char *cp;
26
27    cp = getcwd(NULL, 80);
28     vmTextOut(pVM, cp, 1);
29     free(cp);
30     return;
31 }
32
33 /*
34 ** Ficl interface to chdir
35 ** Gets a newline (or NULL) delimited string from the input
36 ** and feeds it to chdir()
37 ** Example:
38 **    cd c:\tmp
39 */
40 static void ficlChDir(FICL_VM *pVM)
41 {
42     FICL_STRING *pFS = (FICL_STRING *)pVM->pad;
43     vmGetString(pVM, pFS, '\n');
44     if (pFS->count > 0)
45     {
46        int err = chdir(pFS->text);
47        if (err)
48         {
49             vmTextOut(pVM, "Error: path not found", 1);
50             vmThrow(pVM, VM_QUIT);
51         }
52     }
53     else
54     {
55         vmTextOut(pVM, "Warning (chdir): nothing happened", 1);
56     }
57     return;
58 }
59
60 /*
61 ** Ficl interface to system (ANSI)
62 ** Gets a newline (or NULL) delimited string from the input
63 ** and feeds it to system()
64 ** Example:
65 **    system del *.*
66 **    \ ouch!
67 */
68 static void ficlSystem(FICL_VM *pVM)
69 {
70     FICL_STRING *pFS = (FICL_STRING *)pVM->pad;
71
72     vmGetString(pVM, pFS, '\n');
73     if (pFS->count > 0)
74     {
75         int err = system(pFS->text);
76         if (err)
77         {
78             sprintf(pVM->pad, "System call returned %d", err);
79             vmTextOut(pVM, pVM->pad, 1);
80             vmThrow(pVM, VM_QUIT);
81         }
82     }
83     else
84     {
85         vmTextOut(pVM, "Warning (system): nothing happened", 1);
86     }
87     return;
88 }
89
90 /*
91 ** Ficl add-in to load a text file and execute it...
92 ** Cheesy, but illustrative.
93 ** Line oriented... filename is newline (or NULL) delimited.
94 ** Example:
95 **    load test.ficl
96 */
97 #define nLINEBUF 256
98 static void ficlLoad(FICL_VM *pVM)
99 {
100     char    cp[nLINEBUF];
101     char    filename[nLINEBUF];
102     FICL_STRING *pFilename = (FICL_STRING *)filename;
103     int     nLine = 0;
104     FILE   *fp;
105     int     result;
106     CELL    id;
107     struct stat buf;
108
109
110     vmGetString(pVM, pFilename, '\n');
111
112     if (pFilename->count <= 0)
113     {
114         vmTextOut(pVM, "Warning (load): nothing happened", 1);
115         return;
116     }
117
118     /*
119     ** get the file's size and make sure it exists 
120     */
121     result = stat( pFilename->text, &buf );
122
123     if (result != 0)
124     {
125         vmTextOut(pVM, "Unable to stat file: ", 0);
126         vmTextOut(pVM, pFilename->text, 1);
127         vmThrow(pVM, VM_QUIT);
128     }
129
130     fp = fopen(pFilename->text, "r");
131     if (!fp)
132     {
133         vmTextOut(pVM, "Unable to open file ", 0);
134         vmTextOut(pVM, pFilename->text, 1);
135         vmThrow(pVM, VM_QUIT);
136     }
137
138     id = pVM->sourceID;
139     pVM->sourceID.p = (void *)fp;
140
141     /* feed each line to ficlExec */
142     while (fgets(cp, nLINEBUF, fp))
143     {
144         int len = strlen(cp) - 1;
145
146         nLine++;
147         if (len <= 0)
148             continue;
149
150         result = ficlExecC(pVM, cp, len);
151         if (result != VM_QUIT && result != VM_USEREXIT && result != VM_OUTOFTEXT )
152         {
153             pVM->sourceID = id;
154             fclose(fp);
155             vmThrowErr(pVM, "Error loading file <%s> line %d", pFilename->text, nLine);
156             break; 
157         }
158     }
159     /*
160     ** Pass an empty line with SOURCE-ID == -1 to flush
161     ** any pending REFILLs (as required by FILE wordset)
162     */
163     pVM->sourceID.i = -1;
164     ficlExec(pVM, "");
165
166     pVM->sourceID = id;
167     fclose(fp);
168
169     return;
170 }
171
172 /*
173 ** Dump a tab delimited file that summarizes the contents of the
174 ** dictionary hash table by hashcode...
175 */
176 static void spewHash(FICL_VM *pVM)
177 {
178     FICL_HASH *pHash = ficlGetDict()->pForthWords;
179     FICL_WORD *pFW;
180     FILE *pOut;
181     unsigned i;
182     unsigned nHash = pHash->size;
183
184     if (!vmGetWordToPad(pVM))
185         vmThrow(pVM, VM_OUTOFTEXT);
186
187     pOut = fopen(pVM->pad, "w");
188     if (!pOut)
189     {
190         vmTextOut(pVM, "unable to open file", 1);
191         return;
192     }
193
194     for (i=0; i < nHash; i++)
195     {
196         int n = 0;
197
198         pFW = pHash->table[i];
199         while (pFW)
200         {
201             n++;
202             pFW = pFW->link;
203         }
204
205         fprintf(pOut, "%d\t%d", i, n);
206
207         pFW = pHash->table[i];
208         while (pFW)
209         {
210             fprintf(pOut, "\t%s", pFW->name);
211             pFW = pFW->link;
212         }
213
214         fprintf(pOut, "\n");
215     }
216
217     fclose(pOut);
218     return;
219 }
220
221 static void ficlBreak(FICL_VM *pVM)
222 {
223     pVM->state = pVM->state;
224     return;
225 }
226
227 static void ficlClock(FICL_VM *pVM)
228 {
229     clock_t now = clock();
230     stackPushUNS(pVM->pStack, (FICL_UNS)now);
231     return;
232 }
233
234 static void clocksPerSec(FICL_VM *pVM)
235 {
236     stackPushUNS(pVM->pStack, CLOCKS_PER_SEC);
237     return;
238 }
239
240
241 static void execxt(FICL_VM *pVM)
242 {
243     FICL_WORD *pFW;
244 #if FICL_ROBUST > 1
245     vmCheckStack(pVM, 1, 0);
246 #endif
247
248     pFW = stackPopPtr(pVM->pStack);
249     ficlExecXT(pVM, pFW);
250
251     return;
252 }
253
254
255 void buildTestInterface(void)
256 {
257     ficlBuild("break",    ficlBreak,    FW_DEFAULT);
258     ficlBuild("clock",    ficlClock,    FW_DEFAULT);
259     ficlBuild("cd",       ficlChDir,    FW_DEFAULT);
260     ficlBuild("execxt",   execxt,       FW_DEFAULT);
261     ficlBuild("load",     ficlLoad,     FW_DEFAULT);
262     ficlBuild("pwd",      ficlGetCWD,   FW_DEFAULT);
263     ficlBuild("system",   ficlSystem,   FW_DEFAULT);
264     ficlBuild("spewhash", spewHash,     FW_DEFAULT);
265     ficlBuild("clocks/sec", 
266                           clocksPerSec, FW_DEFAULT);
267
268     return;
269 }
270
271
272 int main(int argc, char **argv)
273 {
274     char in[256];
275     FICL_VM *pVM;
276
277     ficlInitSystem(10000);
278     buildTestInterface();
279     pVM = ficlNewVM();
280
281     ficlExec(pVM, ".ver .( " __DATE__ " ) cr quit");
282
283     /*
284     ** load file from cmd line...
285     */
286     if (argc  > 1)
287     {
288         sprintf(in, ".( loading %s ) cr load %s\n cr", argv[1], argv[1]);
289         ficlExec(pVM, in);
290     }
291
292     for (;;)
293     {
294         int ret;
295         if (fgets(in, sizeof(in) - 1, stdin) == NULL)
296             break;
297         ret = ficlExec(pVM, in);
298         if (ret == VM_USEREXIT)
299         {
300             ficlTermSystem();
301             break;
302         }
303     }
304
305     return 0;
306 }
307