1*ca987d46SWarner Losh /* 2*ca987d46SWarner Losh ** stub main for testing FICL under userland 3*ca987d46SWarner Losh ** $Id: testmain.c,v 1.13 2001/12/05 07:21:34 jsadler Exp $ 4*ca987d46SWarner Losh */ 5*ca987d46SWarner Losh /* 6*ca987d46SWarner Losh ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 7*ca987d46SWarner Losh ** All rights reserved. 8*ca987d46SWarner Losh ** 9*ca987d46SWarner Losh ** Get the latest Ficl release at http://ficl.sourceforge.net 10*ca987d46SWarner Losh ** 11*ca987d46SWarner Losh ** I am interested in hearing from anyone who uses ficl. If you have 12*ca987d46SWarner Losh ** a problem, a success story, a defect, an enhancement request, or 13*ca987d46SWarner Losh ** if you would like to contribute to the ficl release, please 14*ca987d46SWarner Losh ** contact me by email at the address above. 15*ca987d46SWarner Losh ** 16*ca987d46SWarner Losh ** L I C E N S E and D I S C L A I M E R 17*ca987d46SWarner Losh ** 18*ca987d46SWarner Losh ** Redistribution and use in source and binary forms, with or without 19*ca987d46SWarner Losh ** modification, are permitted provided that the following conditions 20*ca987d46SWarner Losh ** are met: 21*ca987d46SWarner Losh ** 1. Redistributions of source code must retain the above copyright 22*ca987d46SWarner Losh ** notice, this list of conditions and the following disclaimer. 23*ca987d46SWarner Losh ** 2. Redistributions in binary form must reproduce the above copyright 24*ca987d46SWarner Losh ** notice, this list of conditions and the following disclaimer in the 25*ca987d46SWarner Losh ** documentation and/or other materials provided with the distribution. 26*ca987d46SWarner Losh ** 27*ca987d46SWarner Losh ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 28*ca987d46SWarner Losh ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29*ca987d46SWarner Losh ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30*ca987d46SWarner Losh ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 31*ca987d46SWarner Losh ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32*ca987d46SWarner Losh ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33*ca987d46SWarner Losh ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34*ca987d46SWarner Losh ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35*ca987d46SWarner Losh ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36*ca987d46SWarner Losh ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37*ca987d46SWarner Losh ** SUCH DAMAGE. 38*ca987d46SWarner Losh */ 39*ca987d46SWarner Losh 40*ca987d46SWarner Losh /* $FreeBSD$ */ 41*ca987d46SWarner Losh 42*ca987d46SWarner Losh #include <stdlib.h> 43*ca987d46SWarner Losh #include <stdio.h> 44*ca987d46SWarner Losh #include <string.h> 45*ca987d46SWarner Losh #include <time.h> 46*ca987d46SWarner Losh #include <sys/types.h> 47*ca987d46SWarner Losh #include <sys/stat.h> 48*ca987d46SWarner Losh #include <unistd.h> 49*ca987d46SWarner Losh 50*ca987d46SWarner Losh #include "ficl.h" 51*ca987d46SWarner Losh 52*ca987d46SWarner Losh /* 53*ca987d46SWarner Losh ** Ficl interface to getcwd 54*ca987d46SWarner Losh ** Prints the current working directory using the VM's 55*ca987d46SWarner Losh ** textOut method... 56*ca987d46SWarner Losh */ 57*ca987d46SWarner Losh static void ficlGetCWD(FICL_VM *pVM) 58*ca987d46SWarner Losh { 59*ca987d46SWarner Losh char *cp; 60*ca987d46SWarner Losh 61*ca987d46SWarner Losh cp = getcwd(NULL, 80); 62*ca987d46SWarner Losh vmTextOut(pVM, cp, 1); 63*ca987d46SWarner Losh free(cp); 64*ca987d46SWarner Losh return; 65*ca987d46SWarner Losh } 66*ca987d46SWarner Losh 67*ca987d46SWarner Losh /* 68*ca987d46SWarner Losh ** Ficl interface to chdir 69*ca987d46SWarner Losh ** Gets a newline (or NULL) delimited string from the input 70*ca987d46SWarner Losh ** and feeds it to chdir() 71*ca987d46SWarner Losh ** Example: 72*ca987d46SWarner Losh ** cd c:\tmp 73*ca987d46SWarner Losh */ 74*ca987d46SWarner Losh static void ficlChDir(FICL_VM *pVM) 75*ca987d46SWarner Losh { 76*ca987d46SWarner Losh FICL_STRING *pFS = (FICL_STRING *)pVM->pad; 77*ca987d46SWarner Losh vmGetString(pVM, pFS, '\n'); 78*ca987d46SWarner Losh if (pFS->count > 0) 79*ca987d46SWarner Losh { 80*ca987d46SWarner Losh int err = chdir(pFS->text); 81*ca987d46SWarner Losh if (err) 82*ca987d46SWarner Losh { 83*ca987d46SWarner Losh vmTextOut(pVM, "Error: path not found", 1); 84*ca987d46SWarner Losh vmThrow(pVM, VM_QUIT); 85*ca987d46SWarner Losh } 86*ca987d46SWarner Losh } 87*ca987d46SWarner Losh else 88*ca987d46SWarner Losh { 89*ca987d46SWarner Losh vmTextOut(pVM, "Warning (chdir): nothing happened", 1); 90*ca987d46SWarner Losh } 91*ca987d46SWarner Losh return; 92*ca987d46SWarner Losh } 93*ca987d46SWarner Losh 94*ca987d46SWarner Losh /* 95*ca987d46SWarner Losh ** Ficl interface to system (ANSI) 96*ca987d46SWarner Losh ** Gets a newline (or NULL) delimited string from the input 97*ca987d46SWarner Losh ** and feeds it to system() 98*ca987d46SWarner Losh ** Example: 99*ca987d46SWarner Losh ** system rm -rf / 100*ca987d46SWarner Losh ** \ ouch! 101*ca987d46SWarner Losh */ 102*ca987d46SWarner Losh static void ficlSystem(FICL_VM *pVM) 103*ca987d46SWarner Losh { 104*ca987d46SWarner Losh FICL_STRING *pFS = (FICL_STRING *)pVM->pad; 105*ca987d46SWarner Losh 106*ca987d46SWarner Losh vmGetString(pVM, pFS, '\n'); 107*ca987d46SWarner Losh if (pFS->count > 0) 108*ca987d46SWarner Losh { 109*ca987d46SWarner Losh int err = system(pFS->text); 110*ca987d46SWarner Losh if (err) 111*ca987d46SWarner Losh { 112*ca987d46SWarner Losh sprintf(pVM->pad, "System call returned %d", err); 113*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 114*ca987d46SWarner Losh vmThrow(pVM, VM_QUIT); 115*ca987d46SWarner Losh } 116*ca987d46SWarner Losh } 117*ca987d46SWarner Losh else 118*ca987d46SWarner Losh { 119*ca987d46SWarner Losh vmTextOut(pVM, "Warning (system): nothing happened", 1); 120*ca987d46SWarner Losh } 121*ca987d46SWarner Losh return; 122*ca987d46SWarner Losh } 123*ca987d46SWarner Losh 124*ca987d46SWarner Losh /* 125*ca987d46SWarner Losh ** Ficl add-in to load a text file and execute it... 126*ca987d46SWarner Losh ** Cheesy, but illustrative. 127*ca987d46SWarner Losh ** Line oriented... filename is newline (or NULL) delimited. 128*ca987d46SWarner Losh ** Example: 129*ca987d46SWarner Losh ** load test.ficl 130*ca987d46SWarner Losh */ 131*ca987d46SWarner Losh #define nLINEBUF 256 132*ca987d46SWarner Losh static void ficlLoad(FICL_VM *pVM) 133*ca987d46SWarner Losh { 134*ca987d46SWarner Losh char cp[nLINEBUF]; 135*ca987d46SWarner Losh char filename[nLINEBUF]; 136*ca987d46SWarner Losh FICL_STRING *pFilename = (FICL_STRING *)filename; 137*ca987d46SWarner Losh int nLine = 0; 138*ca987d46SWarner Losh FILE *fp; 139*ca987d46SWarner Losh int result; 140*ca987d46SWarner Losh CELL id; 141*ca987d46SWarner Losh struct stat buf; 142*ca987d46SWarner Losh 143*ca987d46SWarner Losh 144*ca987d46SWarner Losh vmGetString(pVM, pFilename, '\n'); 145*ca987d46SWarner Losh 146*ca987d46SWarner Losh if (pFilename->count <= 0) 147*ca987d46SWarner Losh { 148*ca987d46SWarner Losh vmTextOut(pVM, "Warning (load): nothing happened", 1); 149*ca987d46SWarner Losh return; 150*ca987d46SWarner Losh } 151*ca987d46SWarner Losh 152*ca987d46SWarner Losh /* 153*ca987d46SWarner Losh ** get the file's size and make sure it exists 154*ca987d46SWarner Losh */ 155*ca987d46SWarner Losh result = stat( pFilename->text, &buf ); 156*ca987d46SWarner Losh 157*ca987d46SWarner Losh if (result != 0) 158*ca987d46SWarner Losh { 159*ca987d46SWarner Losh vmTextOut(pVM, "Unable to stat file: ", 0); 160*ca987d46SWarner Losh vmTextOut(pVM, pFilename->text, 1); 161*ca987d46SWarner Losh vmThrow(pVM, VM_QUIT); 162*ca987d46SWarner Losh } 163*ca987d46SWarner Losh 164*ca987d46SWarner Losh fp = fopen(pFilename->text, "r"); 165*ca987d46SWarner Losh if (!fp) 166*ca987d46SWarner Losh { 167*ca987d46SWarner Losh vmTextOut(pVM, "Unable to open file ", 0); 168*ca987d46SWarner Losh vmTextOut(pVM, pFilename->text, 1); 169*ca987d46SWarner Losh vmThrow(pVM, VM_QUIT); 170*ca987d46SWarner Losh } 171*ca987d46SWarner Losh 172*ca987d46SWarner Losh id = pVM->sourceID; 173*ca987d46SWarner Losh pVM->sourceID.p = (void *)fp; 174*ca987d46SWarner Losh 175*ca987d46SWarner Losh /* feed each line to ficlExec */ 176*ca987d46SWarner Losh while (fgets(cp, nLINEBUF, fp)) 177*ca987d46SWarner Losh { 178*ca987d46SWarner Losh int len = strlen(cp) - 1; 179*ca987d46SWarner Losh 180*ca987d46SWarner Losh nLine++; 181*ca987d46SWarner Losh if (len <= 0) 182*ca987d46SWarner Losh continue; 183*ca987d46SWarner Losh 184*ca987d46SWarner Losh result = ficlExecC(pVM, cp, len); 185*ca987d46SWarner Losh if (result != VM_QUIT && result != VM_USEREXIT && result != VM_OUTOFTEXT ) 186*ca987d46SWarner Losh { 187*ca987d46SWarner Losh pVM->sourceID = id; 188*ca987d46SWarner Losh fclose(fp); 189*ca987d46SWarner Losh vmThrowErr(pVM, "Error loading file <%s> line %d", pFilename->text, nLine); 190*ca987d46SWarner Losh break; 191*ca987d46SWarner Losh } 192*ca987d46SWarner Losh } 193*ca987d46SWarner Losh /* 194*ca987d46SWarner Losh ** Pass an empty line with SOURCE-ID == -1 to flush 195*ca987d46SWarner Losh ** any pending REFILLs (as required by FILE wordset) 196*ca987d46SWarner Losh */ 197*ca987d46SWarner Losh pVM->sourceID.i = -1; 198*ca987d46SWarner Losh ficlExec(pVM, ""); 199*ca987d46SWarner Losh 200*ca987d46SWarner Losh pVM->sourceID = id; 201*ca987d46SWarner Losh fclose(fp); 202*ca987d46SWarner Losh 203*ca987d46SWarner Losh /* handle "bye" in loaded files. --lch */ 204*ca987d46SWarner Losh if (result == VM_USEREXIT) 205*ca987d46SWarner Losh vmThrow(pVM, VM_USEREXIT); 206*ca987d46SWarner Losh return; 207*ca987d46SWarner Losh } 208*ca987d46SWarner Losh 209*ca987d46SWarner Losh /* 210*ca987d46SWarner Losh ** Dump a tab delimited file that summarizes the contents of the 211*ca987d46SWarner Losh ** dictionary hash table by hashcode... 212*ca987d46SWarner Losh */ 213*ca987d46SWarner Losh static void spewHash(FICL_VM *pVM) 214*ca987d46SWarner Losh { 215*ca987d46SWarner Losh FICL_HASH *pHash = vmGetDict(pVM)->pForthWords; 216*ca987d46SWarner Losh FICL_WORD *pFW; 217*ca987d46SWarner Losh FILE *pOut; 218*ca987d46SWarner Losh unsigned i; 219*ca987d46SWarner Losh unsigned nHash = pHash->size; 220*ca987d46SWarner Losh 221*ca987d46SWarner Losh if (!vmGetWordToPad(pVM)) 222*ca987d46SWarner Losh vmThrow(pVM, VM_OUTOFTEXT); 223*ca987d46SWarner Losh 224*ca987d46SWarner Losh pOut = fopen(pVM->pad, "w"); 225*ca987d46SWarner Losh if (!pOut) 226*ca987d46SWarner Losh { 227*ca987d46SWarner Losh vmTextOut(pVM, "unable to open file", 1); 228*ca987d46SWarner Losh return; 229*ca987d46SWarner Losh } 230*ca987d46SWarner Losh 231*ca987d46SWarner Losh for (i=0; i < nHash; i++) 232*ca987d46SWarner Losh { 233*ca987d46SWarner Losh int n = 0; 234*ca987d46SWarner Losh 235*ca987d46SWarner Losh pFW = pHash->table[i]; 236*ca987d46SWarner Losh while (pFW) 237*ca987d46SWarner Losh { 238*ca987d46SWarner Losh n++; 239*ca987d46SWarner Losh pFW = pFW->link; 240*ca987d46SWarner Losh } 241*ca987d46SWarner Losh 242*ca987d46SWarner Losh fprintf(pOut, "%d\t%d", i, n); 243*ca987d46SWarner Losh 244*ca987d46SWarner Losh pFW = pHash->table[i]; 245*ca987d46SWarner Losh while (pFW) 246*ca987d46SWarner Losh { 247*ca987d46SWarner Losh fprintf(pOut, "\t%s", pFW->name); 248*ca987d46SWarner Losh pFW = pFW->link; 249*ca987d46SWarner Losh } 250*ca987d46SWarner Losh 251*ca987d46SWarner Losh fprintf(pOut, "\n"); 252*ca987d46SWarner Losh } 253*ca987d46SWarner Losh 254*ca987d46SWarner Losh fclose(pOut); 255*ca987d46SWarner Losh return; 256*ca987d46SWarner Losh } 257*ca987d46SWarner Losh 258*ca987d46SWarner Losh static void ficlBreak(FICL_VM *pVM) 259*ca987d46SWarner Losh { 260*ca987d46SWarner Losh pVM->state = pVM->state; 261*ca987d46SWarner Losh return; 262*ca987d46SWarner Losh } 263*ca987d46SWarner Losh 264*ca987d46SWarner Losh static void ficlClock(FICL_VM *pVM) 265*ca987d46SWarner Losh { 266*ca987d46SWarner Losh clock_t now = clock(); 267*ca987d46SWarner Losh stackPushUNS(pVM->pStack, (FICL_UNS)now); 268*ca987d46SWarner Losh return; 269*ca987d46SWarner Losh } 270*ca987d46SWarner Losh 271*ca987d46SWarner Losh static void clocksPerSec(FICL_VM *pVM) 272*ca987d46SWarner Losh { 273*ca987d46SWarner Losh stackPushUNS(pVM->pStack, CLOCKS_PER_SEC); 274*ca987d46SWarner Losh return; 275*ca987d46SWarner Losh } 276*ca987d46SWarner Losh 277*ca987d46SWarner Losh 278*ca987d46SWarner Losh static void execxt(FICL_VM *pVM) 279*ca987d46SWarner Losh { 280*ca987d46SWarner Losh FICL_WORD *pFW; 281*ca987d46SWarner Losh #if FICL_ROBUST > 1 282*ca987d46SWarner Losh vmCheckStack(pVM, 1, 0); 283*ca987d46SWarner Losh #endif 284*ca987d46SWarner Losh 285*ca987d46SWarner Losh pFW = stackPopPtr(pVM->pStack); 286*ca987d46SWarner Losh ficlExecXT(pVM, pFW); 287*ca987d46SWarner Losh 288*ca987d46SWarner Losh return; 289*ca987d46SWarner Losh } 290*ca987d46SWarner Losh 291*ca987d46SWarner Losh 292*ca987d46SWarner Losh void buildTestInterface(FICL_SYSTEM *pSys) 293*ca987d46SWarner Losh { 294*ca987d46SWarner Losh ficlBuild(pSys, "break", ficlBreak, FW_DEFAULT); 295*ca987d46SWarner Losh ficlBuild(pSys, "clock", ficlClock, FW_DEFAULT); 296*ca987d46SWarner Losh ficlBuild(pSys, "cd", ficlChDir, FW_DEFAULT); 297*ca987d46SWarner Losh ficlBuild(pSys, "execxt", execxt, FW_DEFAULT); 298*ca987d46SWarner Losh ficlBuild(pSys, "load", ficlLoad, FW_DEFAULT); 299*ca987d46SWarner Losh ficlBuild(pSys, "pwd", ficlGetCWD, FW_DEFAULT); 300*ca987d46SWarner Losh ficlBuild(pSys, "system", ficlSystem, FW_DEFAULT); 301*ca987d46SWarner Losh ficlBuild(pSys, "spewhash", spewHash, FW_DEFAULT); 302*ca987d46SWarner Losh ficlBuild(pSys, "clocks/sec", 303*ca987d46SWarner Losh clocksPerSec, FW_DEFAULT); 304*ca987d46SWarner Losh 305*ca987d46SWarner Losh return; 306*ca987d46SWarner Losh } 307*ca987d46SWarner Losh 308*ca987d46SWarner Losh 309*ca987d46SWarner Losh int main(int argc, char **argv) 310*ca987d46SWarner Losh { 311*ca987d46SWarner Losh char in[256]; 312*ca987d46SWarner Losh FICL_VM *pVM; 313*ca987d46SWarner Losh FICL_SYSTEM *pSys; 314*ca987d46SWarner Losh 315*ca987d46SWarner Losh pSys = ficlInitSystem(10000); 316*ca987d46SWarner Losh buildTestInterface(pSys); 317*ca987d46SWarner Losh pVM = ficlNewVM(pSys); 318*ca987d46SWarner Losh 319*ca987d46SWarner Losh ficlEvaluate(pVM, ".ver .( " __DATE__ " ) cr quit"); 320*ca987d46SWarner Losh 321*ca987d46SWarner Losh /* 322*ca987d46SWarner Losh ** load file from cmd line... 323*ca987d46SWarner Losh */ 324*ca987d46SWarner Losh if (argc > 1) 325*ca987d46SWarner Losh { 326*ca987d46SWarner Losh sprintf(in, ".( loading %s ) cr load %s\n cr", argv[1], argv[1]); 327*ca987d46SWarner Losh ficlEvaluate(pVM, in); 328*ca987d46SWarner Losh } 329*ca987d46SWarner Losh 330*ca987d46SWarner Losh for (;;) 331*ca987d46SWarner Losh { 332*ca987d46SWarner Losh int ret; 333*ca987d46SWarner Losh if (fgets(in, sizeof(in) - 1, stdin) == NULL) 334*ca987d46SWarner Losh break; 335*ca987d46SWarner Losh ret = ficlExec(pVM, in); 336*ca987d46SWarner Losh if (ret == VM_USEREXIT) 337*ca987d46SWarner Losh { 338*ca987d46SWarner Losh ficlTermSystem(pSys); 339*ca987d46SWarner Losh break; 340*ca987d46SWarner Losh } 341*ca987d46SWarner Losh } 342*ca987d46SWarner Losh 343*ca987d46SWarner Losh return 0; 344*ca987d46SWarner Losh } 345*ca987d46SWarner Losh 346