forthtest.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00040 #include "common.h"
00041 #include "test/test.h"
00042 #include "../forth.h"
00043
00045 #define SOURCE_ROOT_PATH "forth/"
00046
00047
00048 #include <malloc.h>
00049 #include <stdlib.h>
00050 #include <stdio.h>
00051
00052
00053 #include <unistd.h>
00054 #include <termios.h>
00055
00059 class StdForthIo : public ForthIo
00060 {
00061 public:
00062 StdForthIo()
00063 {
00064
00065 NewLine[0]=2;
00066 NewLine[1]=13;
00067 NewLine[2]=10;
00068
00069
00070 if((IsTerminal = tcgetattr(fileno(stdin),&InitialSettings)==0))
00071 {
00072 struct termios settings = InitialSettings;
00073 settings.c_lflag &= ~(ICANON|ECHO);
00074 settings.c_cc[VMIN] = 1;
00075 settings.c_cc[VTIME] = 0;
00076 tcsetattr(fileno(stdin),TCSANOW,&settings);
00077 }
00078 }
00079
00080 ~StdForthIo()
00081 {
00082
00083 if(IsTerminal)
00084 tcsetattr(fileno(stdin),TCSANOW,&InitialSettings);
00085 }
00086
00087
00088 virtual void ConsoleOut(const CHAR* text,UCELL textLength)
00089 {
00090 while(textLength--)
00091 putchar(*text++);
00092 }
00093
00094 virtual CELL ConsoleIn()
00095 {
00096 return getchar();
00097 }
00098
00099 private:
00100 bool IsTerminal;
00101 struct termios InitialSettings;
00102 };
00103
00104
00109 class TestForthIo : public ForthIo
00110 {
00111 public:
00112 TestForthIo()
00113 : Input(0)
00114 {
00115 NewLine[0]=2;
00116 NewLine[1]=13;
00117 NewLine[2]=10;
00118 }
00119
00120 virtual void ConsoleOut(const CHAR* text,UCELL textLength)
00121 {
00122 while(textLength--)
00123 putchar(*text++);
00124 }
00125
00130 void SetTestInput(const char* input)
00131 {
00132 Input = input;
00133 }
00134
00135 virtual CELL ConsoleIn()
00136 {
00137 if(Input && Input[0])
00138 return *Input++;
00139 TEST(false);
00140 return 13;
00141 }
00142 private:
00143 const char* Input;
00144 };
00145
00146
00158 bool ReadFile(const char* name,void*& address, unsigned& size)
00159 {
00160 FILE* f=fopen(name,"rb");
00161 if(!f)
00162 return false;
00163 if(fseek(f,0,SEEK_END))
00164 { fclose(f); return false; }
00165 size = ftell(f);
00166 if(fseek(f,0,SEEK_SET))
00167 { fclose(f); return false; }
00168 address = malloc(size*sizeof(CHAR));
00169 if(!address)
00170 { fclose(f); return false; }
00171 if(size!=fread(address,sizeof(uint8_t),size,f))
00172 { free(address); fclose(f); return false; }
00173 fclose(f);
00174 CHAR* d=(CHAR*)((CELL)address+size*sizeof(CHAR)/sizeof(uint8_t));
00175 uint8_t* s=(uint8_t*)((CELL)address+size*sizeof(uint8_t));
00176 while((void*)d>(void*)s) *--d=*--s;
00177 return true;
00178 }
00179
00180
00181 #if BITS_PER_CHAR==16
00182
00183 #define STRING(string) L##string
00184
00185 #define LINE(string) L##string L"\n"
00186 #else
00187
00188 #define STRING(string) string
00189
00190 #define LINE(string) string "\n"
00191 #endif
00192
00193
00197 class ForthTest : public Forth
00198 {
00199 public:
00205 CELL Include(const char* fileName);
00206
00212 CELL IncludeLines(const char* fileName);
00213 };
00214
00215
00216 CELL ForthTest::Include(const char* fileName)
00217 {
00218 void* file;
00219 unsigned size;
00220 if(ReadFile(fileName,file,size))
00221 {
00222 CELL result = Evaluate((const CHAR*)file,size);
00223 free(file);
00224 return result;
00225 }
00226 else
00227 return -38;
00228 }
00229
00230
00231 CELL ForthTest::IncludeLines(const char* fileName)
00232 {
00233 static CELL XT_INTERPRET_LINES = 0;
00234
00235 static const CHAR InterpretLines[] =
00236 {
00237
00238 LINE("DECIMAL")
00239 LINE(":NONAME ( c-addr u -- )")
00240 LINE(" (source) 2! 0 >IN !")
00241 LINE(" SOURCE CHARS + >R")
00242 LINE(" BEGIN")
00243 LINE(" SOURCE DROP >IN @ CHARS +")
00244 LINE(" DUP R@ U<")
00245 LINE(" WHILE")
00246 LINE(" R@ OVER - 1 CHARS / (source) 2!")
00247
00248 LINE(" 0 >IN ! 10 PARSE 2DROP >IN @ (source) ! 0 >IN !")
00249
00250 LINE(" INTERPRET")
00251 LINE(" REPEAT")
00252 LINE(" R> 2DROP")
00253 LINE(";")
00254 };
00255
00256 if(!XT_INTERPRET_LINES)
00257 {
00258
00259 CELL result = Evaluate(InterpretLines,sizeof(InterpretLines)/sizeof(CHAR));
00260 if(result)
00261 return result;
00262 XT_INTERPRET_LINES = Pop(1)[0];
00263 }
00264
00265 void* file;
00266 unsigned size;
00267 if(ReadFile(fileName,file,size))
00268 {
00269
00270 Push((CELL*)&file,1);
00271 Push((CELL*)&size,1);
00272 CELL result = Execute(XT_INTERPRET_LINES);
00273 free(file);
00274 return result;
00275 }
00276 else
00277 return -38;
00278 }
00279
00280
00285 #define COUNTED_STRING(string) (CHAR*)STRING(string),(sizeof(string)-1)
00286
00287
00294 void TestForth(bool interactive)
00295 {
00296
00297 union
00298 {
00299 ForthIo* io;
00300 StdForthIo* ioStd;
00301 TestForthIo* ioTest;
00302 };
00303 if(interactive)
00304 ioStd = new StdForthIo;
00305 else
00306 ioTest = new TestForthIo;
00307 TEST(io);
00308
00309
00310 unsigned size = 1<<20;
00311 void* start = malloc(size);
00312 ForthTest* forth = (ForthTest*)Forth::Construct(start,size,io);
00313
00314
00315 CELL args[2];
00316 args[0] = 888;
00317 forth->Push(args,1);
00318 args[0] = 999;
00319 forth->Push(args,1);
00320 args[0] = 11;
00321 args[1] = 123;
00322 forth->Push(args,2);
00323 const CELL* out;
00324 out=forth->Pop(0);
00325 TEST(out[0]==11);
00326 TEST(out[1]==123);
00327 TEST(out[2]==999);
00328 TEST(out[3]==888);
00329 TEST(!forth->Evaluate(COUNTED_STRING("- SWAP")));
00330 out=forth->Pop(0);
00331 TEST(out[0]==999);
00332 TEST(out[1]==112);
00333 TEST(out[2]==888);
00334 out=forth->Pop(2);
00335 TEST(out[0]==999);
00336 TEST(out[1]==112);
00337 out=forth->Pop(1);
00338 TEST(out[0]==888);
00339
00340
00341 TEST(0==forth->Include(SOURCE_ROOT_PATH "core-ext.f"));
00342 TEST(0==forth->Include(SOURCE_ROOT_PATH "search.f"));
00343 TEST(0==forth->Include(SOURCE_ROOT_PATH "programming-tools.f"));
00344
00345
00346 TEST(0==forth->Include(SOURCE_ROOT_PATH "test/tester.f"));
00347 if(!interactive)
00348 ioTest->SetTestInput("Testing, Testing, 124\b3\n");
00349 TEST(0==forth->IncludeLines(SOURCE_ROOT_PATH "test/core.f"));
00350 TEST(0==forth->IncludeLines(SOURCE_ROOT_PATH "test/core-ext.f"));
00351 TEST(0==forth->IncludeLines(SOURCE_ROOT_PATH "test/search.f"));
00352 TEST(0==forth->IncludeLines(SOURCE_ROOT_PATH "test/search-ext.f"));
00353
00354 #if 0 // set true to test ARM assembler and disassembler...
00355 TEST(0==forth->Include(SOURCE_ROOT_PATH "arm-disasm.f"));
00356 TEST(0==forth->Include(SOURCE_ROOT_PATH "arm-asm.f"));
00357 if(!interactive)
00358 ioTest->SetTestInput("\n");
00359 TEST(0==forth->Include(SOURCE_ROOT_PATH "test/arm-asm-disasm-test.f"));
00360 #endif
00361
00362
00363 if(!interactive)
00364 ioTest->SetTestInput("2 2 + .\nBYE\n");
00365 forth->Quit();
00366
00367
00368 free(forth);
00369 if(interactive)
00370 delete ioStd;
00371 else
00372 delete ioTest;
00373 }
00374
00376