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