3737***************************************************************/
3838
3939#include "pf_all.h"
40+ #include "paging/unittest.h"
4041#include "paging/qadmpage.h"
4142
4243/***************************************************************
@@ -75,9 +76,11 @@ cell_t gVarReturnCode; /* Returned to caller of Forth, eg. UNIX shell
7576IncludeFrame gIncludeStack [MAX_INCLUDE_DEPTH ];
7677cell_t gIncludeIndex ;
7778
79+ PFQA_INSTANTIATE_GLOBALS ;
80+
7881static void pfResetForthTask ( void );
79- static void pfInit ( void );
80- static void pfTerm ( void );
82+ static void pfInitSystem ( void );
83+ static void pfTermSystem ( void );
8184
8285#define DEFAULT_RETURN_DEPTH (512)
8386#define DEFAULT_USER_DEPTH (512)
@@ -93,7 +96,7 @@ static void pfTerm( void );
9396/* Initialize globals in a function to simplify loading on
9497 * embedded systems which may not support initialization of data section.
9598 */
96- static void pfInit ( void )
99+ static void pfInitSystem ( void )
97100{
98101/* all zero */
99102 gCurrentTask = NULL ;
@@ -119,7 +122,8 @@ static void pfInit( void )
119122 ioInit ();
120123
121124}
122- static void pfTerm ( void )
125+
126+ static void pfTermSystem ( void )
123127{
124128 ioTerm ();
125129}
@@ -316,6 +320,11 @@ void pfSetCurrentTask( PForthTask task )
316320 gCurrentTask = (pfTaskData_t * ) task ;
317321}
318322
323+ PForthTask pfGetCurrentTask (void )
324+ {
325+ return (PForthTask ) gCurrentTask ;
326+ }
327+
319328/***************************************************************
320329** Set Quiet Flag.
321330***************************************************************/
@@ -453,67 +462,118 @@ void pfMessage( const char *CString )
453462 ioType ( CString , (cell_t ) pfCStringLength (CString ) );
454463}
455464
456- /**************************************************************************
457- ** Main entry point for pForth.
458- */
459- ThrowCode pfDoForth ( const char * DicFileName , const char * SourceName , cell_t IfInit )
460- {
465+
466+ /**
467+ * Interprets the Forth in the text.
468+ * The text length cannot exceed TIB_SIZE.
469+ * @param text the Forth code to be executed
470+ * @return 0 if successful or throw code.
471+ */
472+ ThrowCode pfInterpretText (char * text ) {
473+ ThrowCode Result = 0 ;
474+ cell_t length = strlen (text );
475+ if (length > TIB_SIZE ) {
476+ MSG ("pfInterpretText: text bigger than TIB\n" );
477+ Result = THROW_ABORT ;
478+ goto error ;
479+ }
480+ gCurrentTask -> td_IN = 0 ;
481+ gCurrentTask -> td_SourceNum = length ;
482+ vm_address_t savedSource = gCurrentTask -> td_SourcePtr ;
483+ pfCopyMemory (gCurrentTask -> td_TIB , text , length );
484+ gCurrentTask -> td_SourcePtr = savedSource ;
485+ Result = ffInterpret ();
486+ error :
487+ return Result ;
488+ }
489+
490+ void pfPushToStack (cell_t value ) {
491+ PUSH_DATA_STACK (value );
492+ }
493+
494+ cell_t pfPopFromStack (void ) {
495+ return POP_DATA_STACK ;
496+ }
497+
498+ cell_t pfGetStackDepth (void ) {
499+ return DATA_STACK_DEPTH ;
500+ }
501+
502+ #ifdef PF_UNIT_TEST
503+ static int pfQaInterpret (void ) {
504+ printf ("pfQaInterpret() called\n" );
505+ int savedNumFailed = pfQaNumFailed ;
506+
507+ ASSERT_EQ (0 , pfInterpretText ("0sp 123" ));
508+ ASSERT_EQ (1 , pfGetStackDepth ());
509+ ASSERT_EQ (123 , pfPopFromStack ());
510+ ASSERT_EQ (0 , pfGetStackDepth ());
511+
512+ pfPushToStack (5000 );
513+ ASSERT_EQ (0 , pfInterpretText ("678 +" ));
514+ ASSERT_EQ (5678 , pfPopFromStack ());
515+
516+ ASSERT_EQ (THROW_UNDEFINED_WORD , pfInterpretText ("567 BADWORD 5432" ));
517+
518+ ASSERT_EQ (0 , pfInterpretText ("0sp" ));
519+ ASSERT_EQ (0 , pfGetStackDepth ());
520+
521+ printf ("pfQaInterpret() ended\n" );
522+
523+ error :
524+ PFQA_PRINT_RESULT ;
525+ return pfQaNumFailed - savedNumFailed ;
526+ }
527+ #endif
528+
529+ ThrowCode pfInitialize (const char * DicFileName ,
530+ cell_t IfInit ,
531+ ExecToken * EntryPointPtr ) {
532+
461533 pfTaskData_t * cftd = NULL ;
462534 pfDictionary_t * dic = NULL ;
463535 ThrowCode Result = 0 ;
464- ExecToken EntryPoint = 0 ;
465-
536+
466537#ifdef PF_USER_INIT
467538 Result = PF_USER_INIT ;
468539 if ( Result < 0 ) goto error1 ;
469540#endif
470-
471- pfInit ();
472-
473- #if PF_DEMAND_PAGING
474- Result = pfQaDemandPaging (); /* TODO move to standalone qa test */
475- if (Result != 0 ) goto error2 ;
476- #endif
477-
478- /* Allocate Task structure. */
541+
542+ pfInitSystem ();
543+
544+ /* Allocate Task structure. */
479545 pfDebugMessage ("pfDoForth: call pfCreateTask()\n" );
480546 cftd = pfCreateTask ( DEFAULT_USER_DEPTH , DEFAULT_RETURN_DEPTH );
481-
547+
482548 if ( cftd )
483549 {
484550 pfSetCurrentTask ( cftd );
485-
551+
486552 if ( !gVarQuiet )
487553 {
488554 MSG ( "PForth V" PFORTH_VERSION_NAME ", " );
489-
555+
490556 if ( IsHostLittleEndian () ) MSG ("LE" );
491557 else MSG ("BE" );
492558#if PF_BIG_ENDIAN_DIC
493559 MSG ("/BE" );
494560#elif PF_LITTLE_ENDIAN_DIC
495561 MSG ("/LE" );
496562#endif
497-
563+
498564#if (PF_SIZEOF_CELL == 8 )
499- MSG ("/64" );
565+ MSG ("/64" );
500566#elif (PF_SIZEOF_CELL == 4 )
501- MSG ("/32" );
567+ MSG ("/32" );
502568#endif
503-
569+
504570 MSG ( ", built " __DATE__ " " __TIME__ );
505571 }
506572
507- /* Don't use MSG before task set. */
508- if ( SourceName )
509- {
510- pfDebugMessage ("SourceName = " ); pfDebugMessage (SourceName ); pfDebugMessage ("\n" );
511- }
512-
513573#ifdef PF_NO_GLOBAL_INIT
514574 if ( LoadCustomFunctionTable () < 0 ) goto error2 ; /* Init custom 'C' call array. */
515575#endif
516-
576+
517577#if (!defined(PF_NO_INIT )) && (!defined(PF_NO_SHELL ))
518578 if ( IfInit )
519579 {
@@ -522,7 +582,7 @@ ThrowCode pfDoForth( const char *DicFileName, const char *SourceName, cell_t IfI
522582 }
523583 else
524584#else
525- TOUCH (IfInit );
585+ TOUCH (IfInit );
526586#endif /* !PF_NO_INIT && !PF_NO_SHELL*/
527587 {
528588 if ( DicFileName )
@@ -532,7 +592,7 @@ ThrowCode pfDoForth( const char *DicFileName, const char *SourceName, cell_t IfI
532592 {
533593 EMIT_CR ;
534594 }
535- dic = pfLoadDictionary ( DicFileName , & EntryPoint );
595+ dic = pfLoadDictionary ( DicFileName , EntryPointPtr );
536596 }
537597 else
538598 {
@@ -545,22 +605,77 @@ ThrowCode pfDoForth( const char *DicFileName, const char *SourceName, cell_t IfI
545605 }
546606 }
547607 if ( dic == NULL ) goto error2 ;
548-
608+
549609 if ( !gVarQuiet )
550610 {
551611 EMIT_CR ;
552612 }
553-
613+
554614 pfDebugMessage ("pfDoForth: try AUTO.INIT\n" );
555615 Result = pfExecIfDefined ("AUTO.INIT" );
556616 if ( Result != 0 )
557617 {
558618 MSG ("Error in AUTO.INIT" );
559619 goto error2 ;
560620 }
621+ }
622+ return 0 ;
623+
624+ error2 :
625+ MSG ("pfDoForth: Error occurred.\n" );
626+ pfDeleteTask ( cftd );
627+ /* Terminate so we restore normal shell tty mode. */
628+ pfTermSystem ();
629+
630+ #ifdef PF_USER_INIT
631+ error1 :
632+ #endif
633+ return -1 ;
634+ }
635+
636+
637+ void pfTerminate (void ) {
638+ /* Clean up after running Forth. */
639+ if (gCurrentDictionary != NULL ) {
640+ pfExecIfDefined ("AUTO.TERM" );
641+ pfDeleteDictionary ( gCurrentDictionary );
642+ gCurrentDictionary = NULL ;
643+ }
644+ if (pfGetCurrentTask () != NULL ) {
645+ pfDeleteTask ( pfGetCurrentTask () );
646+ pfSetCurrentTask (NULL );
647+ }
648+
649+ pfTermSystem ();
650+
651+ #if PF_DEMAND_PAGING
652+ pfCheckPagedMemory ();
653+ #endif
654+
655+ #ifdef PF_USER_TERM
656+ PF_USER_TERM ;
657+ #endif
658+ }
659+
660+ /**************************************************************************
661+ ** Main entry point for pForth.
662+ */
663+ ThrowCode pfDoForth (const char * DicFileName ,
664+ const char * SourceName ,
665+ cell_t IfInit )
666+ {
667+ ExecToken EntryPoint = 0 ;
668+
669+ ThrowCode Result = pfInitialize (DicFileName , IfInit , & EntryPoint );
670+
671+ if (Result == 0 ) {
672+ #ifdef PF_UNIT_TEST
673+ if ((Result = pfQaInterpret ()) != 0 ) goto error ;
674+ #endif
561675
562676 if ( EntryPoint != 0 )
563677 {
678+ /* Run a TURNKEY application. */
564679 Result = pfCatch ( EntryPoint );
565680 }
566681#ifndef PF_NO_SHELL
@@ -583,36 +698,15 @@ ThrowCode pfDoForth( const char *DicFileName, const char *SourceName, cell_t IfI
583698 }
584699 }
585700#endif /* PF_NO_SHELL */
586-
587- /* Clean up after running Forth. */
588- pfExecIfDefined ("AUTO.TERM" );
589- pfDeleteDictionary ( dic );
590- pfDeleteTask ( cftd );
591701 }
592702
593- pfTerm ();
594-
595- #if PF_DEMAND_PAGING
596- pfCheckPagedMemory ();
703+ #ifdef PF_UNIT_TEST
704+ error :
597705#endif
598706
599- #ifdef PF_USER_TERM
600- PF_USER_TERM ;
601- #endif
707+ pfTerminate ();
602708
603709 return Result ? Result : gVarByeCode ;
604-
605- error2 :
606- MSG ("pfDoForth: Error occurred.\n" );
607- pfDeleteTask ( cftd );
608- /* Terminate so we restore normal shell tty mode. */
609- pfTerm ();
610-
611- #ifdef PF_USER_INIT
612- error1 :
613- #endif
614-
615- return -1 ;
616710}
617711
618712#ifdef PF_UNIT_TEST
@@ -621,6 +715,10 @@ cell_t pfUnitTest( void )
621715 cell_t numErrors = 0 ;
622716 MSG ("pfUnitTest() called\n" );
623717 numErrors += pfUnitTestText ();
718+
719+ #if PF_DEMAND_PAGING
720+ numErrors += pfQaDemandPaging ();
721+ #endif
624722 return numErrors ;
625723}
626724#endif
0 commit comments