ucell_t Packed;\r
char FName[40];\r
\r
- CStringToForth( FName, CName );\r
+ CStringToForth( FName, CName, sizeof(FName) );\r
Packed = (Index & 0xFFFF) | 0 | (NumParams << 24) |\r
(ReturnMode << 31);\r
DBUG(("Packed = 0x%8x\n", Packed));\r
\r
return -1;\r
}\r
+\r
+\r
+#ifdef PF_UNIT_TEST\r
+cell_t pfUnitTest( void )\r
+{\r
+ cell_t numErrors = 0;\r
+ numErrors += pfUnitTestText();\r
+ return numErrors;\r
+}\r
+#endif\r
\r
void pfDebugMessage( const char *CString );\r
void pfDebugPrintDecimalNumber( int n );\r
-\r
+ \r
+cell_t pfUnitTestText( void );\r
\r
#ifdef __cplusplus\r
} \r
**\r
***************************************************************/\r
\r
+#include <sys/types.h>\r
+\r
#include "pf_all.h"\r
\r
#ifdef WIN32\r
CodeSize = TOS;\r
NameSize = M_POP;\r
EntryPoint = M_POP;\r
- ForthStringToC( gScratch, (char *) M_POP );\r
+ ForthStringToC( gScratch, (char *) M_POP, sizeof(gScratch) );\r
TOS = ffSaveForth( gScratch, EntryPoint, NameSize, CodeSize );\r
}\r
endcase;\r
#define sdFlushFile fflush\r
#define sdReadFile fread\r
#define sdWriteFile fwrite\r
- #if WIN32\r
+ #if defined(WIN32) || defined(__NT__)\r
/* TODO To support 64-bit file offset we probably need fseeki64(). */\r
#define sdSeekFile fseek\r
#define sdTellFile ftell\r
DicName = NULL;\r
#endif\r
\r
+#ifdef PF_UNIT_TEST\r
+ if( (Result = pfUnitTest()) != 0 )\r
+ {\r
+ ERR(("pForth stopping on unit test failure.\n"));\r
+ goto on_error;\r
+ }\r
+#endif\r
+ \r
Result = pfDoForth( DicName, SourceName, IfInit);\r
\r
on_error:\r
** Copy a Forth String to a 'C' string.\r
*/\r
\r
-char *ForthStringToC( char *dst, const char *FString )\r
+char *ForthStringToC( char *dst, const char *FString, cell_t dstSize )\r
{\r
cell_t Len;\r
\r
Len = (cell_t) *FString;\r
+ /* Make sure the text + NUL can fit. */\r
+ if( Len >= dstSize )\r
+ {\r
+ Len = dstSize - 1;\r
+ }\r
pfCopyMemory( dst, FString+1, Len );\r
dst[Len] = '\0';\r
\r
/**************************************************************\r
** Copy a NUL terminated string to a Forth counted string.\r
*/\r
-char *CStringToForth( char *dst, const char *CString )\r
+char *CStringToForth( char *dst, const char *CString, cell_t dstSize )\r
{\r
- char *s;\r
cell_t i;\r
\r
- s = dst+1;\r
- for( i=0; *CString; i++ )\r
+ /* Make sure the SIZE+text can fit. */\r
+ for( i=1; i<dstSize; i++ )\r
{\r
- *s++ = *CString++;\r
+ if( *CString == 0 )\r
+ {\r
+ break;\r
+ }\r
+ dst[i] = *CString++;\r
}\r
- *dst = (char ) i;\r
+ *dst = (char ) i-1;\r
return dst;\r
}\r
\r
}\r
\r
\r
+\r
+#ifdef PF_UNIT_TEST\r
+/* Unit test for string conversion routines. */\r
+#define ASSERT_PAD_IS( index, value, msg ) \\r
+ if( pad[index] != ((char)(value)) ) \\r
+ { \\r
+ ERR(( "ERROR text test failed: " msg "\n")); \\r
+ numErrors += 1; \\r
+ } \\r
+\r
+cell_t pfUnitTestText( void )\r
+{\r
+ cell_t numErrors = 0;\r
+ char pad[16];\r
+ char fpad[8];\r
+\r
+ /* test CStringToForth */\r
+ pfSetMemory(pad,0xA5,sizeof(pad));\r
+ CStringToForth( pad, "frog", 6 );\r
+ ASSERT_PAD_IS( 0, 4, "CS len 6" );\r
+ ASSERT_PAD_IS( 4, 'g', "CS end 6" );\r
+ ASSERT_PAD_IS( 5, 0xA5, "CS past 6" );\r
+ \r
+ pfSetMemory(pad,0xA5,sizeof(pad));\r
+ CStringToForth( pad, "frog", 5 );\r
+ ASSERT_PAD_IS( 0, 4, "CS len 5" );\r
+ ASSERT_PAD_IS( 4, 'g', "CS end 5" );\r
+ ASSERT_PAD_IS( 5, 0xA5, "CS past 5" );\r
+ \r
+ pfSetMemory(pad,0xA5,sizeof(pad));\r
+ CStringxxxxxToForth( pad, "frog", 4 );\r
+ ASSERT_PAD_IS( 0, 3, "CS len 4" );\r
+ ASSERT_PAD_IS( 3, 'o', "CS end 4" );\r
+ ASSERT_PAD_IS( 4, 0xA5, "CS past 4" );\r
+ \r
+ /* Make a Forth string for testing ForthStringToC. */\r
+ CStringToForth( fpad, "frog", sizeof(fpad) );\r
+ \r
+ pfSetMemory(pad,0xA5,sizeof(pad));\r
+ ForthStringToC( pad, fpad, 6 );\r
+ ASSERT_PAD_IS( 0, 'f', "FS len 6" );\r
+ ASSERT_PAD_IS( 3, 'g', "FS end 6" );\r
+ ASSERT_PAD_IS( 4, 0, "FS nul 6" );\r
+ ASSERT_PAD_IS( 5, 0xA5, "FS past 6" );\r
+ \r
+ pfSetMemory(pad,0xA5,sizeof(pad));\r
+ ForthStringToC( pad, fpad, 5 );\r
+ ASSERT_PAD_IS( 0, 'f', "FS len 5" );\r
+ ASSERT_PAD_IS( 3, 'g', "FS end 5" );\r
+ ASSERT_PAD_IS( 4, 0, "FS nul 5" );\r
+ ASSERT_PAD_IS( 5, 0xA5, "FS past 5" );\r
+ \r
+ pfSetMemory(pad,0xA5,sizeof(pad));\r
+ ForthStringToC( pad, fpad, 4 );\r
+ ASSERT_PAD_IS( 0, 'f', "FS len 4" );\r
+ ASSERT_PAD_IS( 2, 'o', "FS end 4" );\r
+ ASSERT_PAD_IS( 3, 0, "FS nul 4" );\r
+ ASSERT_PAD_IS( 4, 0xA5, "FS past 4" );\r
+ \r
+ return numErrors;\r
+}\r
+#endif\r
void pfReportError( const char *FunctionName, Err ErrCode );\r
void pfReportThrow( ThrowCode code );\r
\r
-char *ForthStringToC( char *dst, const char *FString );\r
-char *CStringToForth( char *dst, const char *CString );\r
+char *ForthStringToC( char *dst, const char *FString, cell_t dstSize );\r
+char *CStringToForth( char *dst, const char *CString, cell_t dstSize );\r
\r
cell_t ffCompare( const char *s1, cell_t len1, const char *s2, int32_t len2 );\r
cell_t ffCompareText( const char *s1, const char *s2, cell_t len );\r
void DumpMemory( void *addr, cell_t cnt);\r
char *ConvertNumberToText( cell_t Num, cell_t Base, int32_t IfSigned, int32_t MinChars );\r
void TypeName( const char *Name );\r
-\r
+ \r
+cell_t pfUnitTestText( void );\r
+ \r
#ifdef __cplusplus\r
} \r
#endif\r
void CreateDicEntryC( ExecToken XT, const char *CName, ucell_t Flags )\r
{\r
ForthString FName[40];\r
- CStringToForth( FName, CName );\r
+ CStringToForth( FName, CName, sizeof(FName) );\r
CreateDicEntry( XT, FName, Flags );\r
}\r
\r
cell_t ffFindC( const char *WordName, ExecToken *pXT )\r
{\r
DBUG(("ffFindC: %s\n", WordName ));\r
- CStringToForth( gScratch, WordName );\r
+ CStringToForth( gScratch, WordName, sizeof(gScratch) );\r
return ffFind( gScratch, pXT );\r
}\r
\r
static void CreateDeferredC( ExecToken DefaultXT, const char *CName )\r
{\r
char FName[40];\r
- CStringToForth( FName, CName );\r
+ CStringToForth( FName, CName, sizeof(FName) );\r
ffStringDefer( FName, DefaultXT );\r
}\r
#endif\r
#include <conio.h>\r
\r
/* Use console mode I/O so that KEY and ?TERMINAL will work. */\r
-#if WIN32\r
+#if defined(WIN32) || defined(__NT__)\r
int sdTerminalOut( char c )\r
{\r
+#if defined(__WATCOMC__)\r
+ return putch((char)(c));\r
+#else\r
return _putch((char)(c));\r
+#endif\r
}\r
\r
/* Needed cuz _getch() does not echo. */\r
int sdTerminalEcho( char c )\r
{\r
+#if defined(__WATCOMC__)\r
+ return putch((char)(c));\r
+#else\r
return _putch((char)(c));\r
+#endif\r
}\r
\r
int sdTerminalIn( void )\r
\r
#include "../pf_all.h"\r
\r
-#if WIN32\r
+#if defined(WIN32) || defined(__NT__)\r
\r
#include <windows.h>\r
\r
http://code.google.com/p/pforth/issues/detail?id=4&can=1\r
- Fixed scrambled HISTORY on 64-bit systems. Was using CELL+ but really needed 4 +.\r
- Fixed floating point input. Now accepts "1E" as 1.0. Was Issue #2.\r
- - Fixed lots of warning and made code compatible with C89 and ANSI with -pedantic.\r
+ - Fixed lots of warning and made code compatible with C89 and ANSI. Uses -pedantic.\r
- Use fseek and ftell on WIN32 instead of fseeko and ftello.\r
+ - Makefile is now more standard. Builds in same dir as Makefile. Uses CFLAGS etc.\r
+ - Add support for console IO with _WATCOMC_\r
+ - Internal CStringToForth and ForthStringToC now take a destination size for safety.\r
+ - Run units tests for CStringToForth and ForthStringToC if PF_UNIT_TESTS is defined.\r
\r
V26 5/20/2010\r
- 64-bit support for M* UM/MOD etc by Aleksej Saushev. Thanks Aleksej!\r