]> git.sur5r.net Git - openocd/blobdiff - src/jim.c
.cfg files are now executed as Jim Tcl. Commands that terminate script w/error message.
[openocd] / src / jim.c
index a466a08bbdebeb8d3d34ad74d7553f3d07091440..be53233c16524a10ec9af069e4fc3027d8fbcbcb 100644 (file)
--- a/src/jim.c
+++ b/src/jim.c
@@ -38,6 +38,8 @@
 #include <errno.h>
 #include <time.h>
 
+#include "replacements.h"
+
 /* Include the platform dependent libraries for
  * dynamic loading of libraries. */
 #ifdef JIM_DYNLIB
@@ -45,7 +47,9 @@
 #ifndef WIN32
 #define WIN32 1
 #endif
+#ifndef STRICT
 #define STRICT
+#endif
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #if _MSC_VER >= 1000
@@ -363,7 +367,7 @@ int Jim_StringToWide(const char *str, jim_wide *widePtr, int base)
 #else
     *widePtr = strtol(str, &endptr, base);
 #endif
-    if (str[0] == '\0')
+    if ((str[0] == '\0') || (str == endptr) )
         return JIM_ERR;
     if (endptr[0] != '\0') {
         while(*endptr) {
@@ -380,7 +384,7 @@ int Jim_StringToIndex(const char *str, int *intPtr)
     char *endptr;
 
     *intPtr = strtol(str, &endptr, 10);
-    if (str[0] == '\0')
+    if ( (str[0] == '\0') || (str == endptr) )
         return JIM_ERR;
     if (endptr[0] != '\0') {
         while(*endptr) {
@@ -437,7 +441,7 @@ int Jim_StringToDouble(const char *str, double *doublePtr)
     char *endptr;
 
     *doublePtr = strtod(str, &endptr);
-    if (str[0] == '\0' || endptr[0] != '\0')
+    if (str[0] == '\0' || endptr[0] != '\0' || (str == endptr) )
         return JIM_ERR;
     return JIM_OK;
 }
@@ -460,13 +464,16 @@ static jim_wide JimPowWide(jim_wide b, jim_wide e)
 void Jim_Panic(Jim_Interp *interp, const char *fmt, ...)
 {
     va_list ap;
-    FILE *fp = interp ? interp->stderr_ : stderr;
 
     va_start(ap, fmt);
-    fprintf(fp, JIM_NL "JIM INTERPRETER PANIC: ");
-    vfprintf(fp, fmt, ap);
-    fprintf(fp, JIM_NL JIM_NL);
+       /* 
+        * Send it here first.. Assuming STDIO still works
+        */
+    fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, JIM_NL JIM_NL);
     va_end(ap);
+
 #ifdef HAVE_BACKTRACE
     {
         void *array[40];
@@ -481,6 +488,13 @@ void Jim_Panic(Jim_Interp *interp, const char *fmt, ...)
         fprintf(fp,"[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
     }
 #endif
+       
+       /* This may actually crash... we do it last */
+       if( interp && interp->cookie_stderr ){
+               Jim_fprintf(  interp, interp->cookie_stderr, JIM_NL "JIM INTERPRETER PANIC: ");
+               Jim_vfprintf( interp, interp->cookie_stderr, fmt, ap );
+               Jim_fprintf(  interp, interp->cookie_stderr, JIM_NL JIM_NL );
+       }
     abort();
 }
 
@@ -2136,21 +2150,40 @@ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
 }
 
 /* This is the core of the [format] command.
- * TODO: Export it, make it real... for now only %s and %%
- * specifiers supported. */
+ * TODO: Lots of things work - via a hack
+ *       However, no format item can be >= JIM_MAX_FMT 
+ */
 Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
         int objc, Jim_Obj *const *objv)
 {
-    const char *fmt;
+    const char *fmt, *_fmt;
     int fmtLen;
     Jim_Obj *resObjPtr;
+    
 
     fmt = Jim_GetString(fmtObjPtr, &fmtLen);
+       _fmt = fmt;
     resObjPtr = Jim_NewStringObj(interp, "", 0);
     while (fmtLen) {
         const char *p = fmt;
         char spec[2], c;
         jim_wide wideValue;
+               double doubleValue;
+               /* we cheat and use Sprintf()! */
+#define JIM_MAX_FMT 2048
+               char sprintf_buf[JIM_MAX_FMT];
+               char fmt_str[100];
+               char *cp;
+               int width;
+               int ljust;
+               int zpad;
+               int spad;
+               int altfm;
+               int forceplus;
+               int prec;
+               int inprec;
+               int haveprec;
+               int accum;
 
         while (*fmt != '%' && fmtLen) {
             fmt++; fmtLen--;
@@ -2159,38 +2192,225 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
         if (fmtLen == 0)
             break;
         fmt++; fmtLen--; /* skip '%' */
-        if (*fmt != '%') {
+               zpad = 0;
+               spad = 0;
+               width = -1;
+               ljust = 0;
+               altfm = 0;
+               forceplus = 0;
+               inprec = 0;
+               haveprec = 0;
+               prec = -1; /* not found yet */
+    next_fmt:
+               if( fmtLen <= 0 ){
+                       break;
+               }
+               switch( *fmt ){
+                       /* terminals */
+        case 'b': /* binary - not all printfs() do this */
+               case 's': /* string */
+               case 'i': /* integer */
+               case 'd': /* decimal */
+               case 'x': /* hex */
+               case 'X': /* CAP hex */
+               case 'c': /* char */
+               case 'o': /* octal */
+               case 'u': /* unsigned */
+               case 'f': /* float */
+                       break;
+                       
+                       /* non-terminals */
+               case '0': /* zero pad */
+                       zpad = 1;
+                       *fmt++;  fmtLen--;
+                       goto next_fmt;
+                       break;
+               case '+':
+                       forceplus = 1;
+                       *fmt++;  fmtLen--;
+                       goto next_fmt;
+                       break;
+               case ' ': /* sign space */
+                       spad = 1;
+                       *fmt++;  fmtLen--;
+                       goto next_fmt;
+                       break;
+               case '-':
+                       ljust = 1;
+                       *fmt++;  fmtLen--;
+                       goto next_fmt;
+                       break;
+               case '#':
+                       altfm = 1;
+                       *fmt++; fmtLen--;
+                       goto next_fmt;
+
+               case '.':
+                       inprec = 1;
+                       *fmt++; fmtLen--;
+                       goto next_fmt;
+                       break;
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                       accum = 0;
+                       while( isdigit(*fmt) && (fmtLen > 0) ){
+                               accum = (accum * 10) + (*fmt - '0');
+                               fmt++;  fmtLen--;
+                       }
+                       if( inprec ){
+                               haveprec = 1;
+                               prec = accum;
+                       } else {
+                               width = accum;
+                       }
+                       goto next_fmt;
+               case '*':
+                       /* suck up the next item as an integer */
+                       *fmt++;  fmtLen--;
+                       objc--;
+                       if( objc <= 0 ){
+                               goto not_enough_args;
+                       }
+                       if( Jim_GetWide(interp,objv[0],&wideValue )== JIM_ERR ){
+                               Jim_FreeNewObj(interp, resObjPtr );
+                               return NULL;
+                       }
+                       if( inprec ){
+                               haveprec = 1;
+                               prec = wideValue;
+                               if( prec < 0 ){
+                                       /* man 3 printf says */
+                                       /* if prec is negative, it is zero */
+                                       prec = 0;
+                               }
+                       } else {
+                               width = wideValue;
+                               if( width < 0 ){
+                                       ljust = 1;
+                                       width = -width;
+                               }
+                       }
+                       objv++;
+                       goto next_fmt;
+                       break;
+               }
+               
+               
+               if (*fmt != '%') {
             if (objc == 0) {
+                       not_enough_args:
                 Jim_FreeNewObj(interp, resObjPtr);
                 Jim_SetResultString(interp,
-                        "not enough arguments for all format specifiers", -1);
+                                                                       "not enough arguments for all format specifiers", -1);
                 return NULL;
             } else {
                 objc--;
             }
         }
+               
+               /*
+                * Create the formatter
+                * cause we cheat and use sprintf()
+                */
+               cp = fmt_str;
+               *cp++ = '%';
+               if( altfm ){
+                       *cp++ = '#';
+               }
+               if( forceplus ){
+                       *cp++ = '+';
+               } else if( spad ){
+                       /* PLUS overrides */
+                       *cp++ = ' ';
+               }
+               if( ljust ){
+                       *cp++ = '-';
+               }
+               if( zpad  ){
+                       *cp++ = '0';
+               }
+               if( width > 0 ){
+                       sprintf( cp, "%d", width );
+                       /* skip ahead */
+                       cp = strchr(cp,0);
+               }
+               /* did we find a period? */
+               if( inprec ){
+                       /* then add it */
+                       *cp++ = '.';
+                       /* did something occur after the period? */
+                       if( haveprec ){
+                               sprintf( cp, "%d", prec );
+                       }
+                       cp = strchr(cp,0);
+               }
+               *cp = 0;
+
+               /* here we do the work */
+               /* actually - we make sprintf() do it for us */
         switch(*fmt) {
         case 's':
-            Jim_AppendObj(interp, resObjPtr, objv[0]);
-            objv++;
+                       *cp++ = 's';
+                       *cp   = 0;
+                       /* BUG: we do not handled embeded NULLs */
+                       snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, Jim_GetString( objv[0], NULL ));
             break;
         case 'c':
+                       *cp++ = 'c';
+                       *cp   = 0;
             if (Jim_GetWide(interp, objv[0], &wideValue) == JIM_ERR) {
                 Jim_FreeNewObj(interp, resObjPtr);
                 return NULL;
             }
             c = (char) wideValue;
-            Jim_AppendString(interp, resObjPtr, &c, 1);
+                       snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, c );
             break;
+               case 'f':
+               case 'F':
+               case 'g':
+               case 'G':
+               case 'e':
+               case 'E':
+                       *cp++ = *fmt;
+                       *cp   = 0;
+                       if( Jim_GetDouble( interp, objv[0], &doubleValue ) == JIM_ERR ){
+                               Jim_FreeNewObj( interp, resObjPtr );
+                               return NULL;
+                       }
+                       snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, doubleValue );
+                       break;
+        case 'b':
         case 'd':
+               case 'i':
+               case 'u':
+               case 'x':
+               case 'X':
+                       /* jim widevaluse are 64bit */
+                       if( sizeof(jim_wide) == sizeof(long long) ){
+                               *cp++ = 'l'; 
+                               *cp++ = 'l';
+                       } else {
+                               *cp++ = 'l';
+                       }
+                       *cp++ = *fmt;
+                       *cp   = 0;
             if (Jim_GetWide(interp, objv[0], &wideValue) == JIM_ERR) {
                 Jim_FreeNewObj(interp, resObjPtr);
                 return NULL;
             }
-            Jim_AppendObj(interp, resObjPtr, objv[0]);
+                       snprintf(sprintf_buf, JIM_MAX_FMT, fmt_str, wideValue );
             break;
         case '%':
-            Jim_AppendString(interp, resObjPtr, "%" , 1);
+                       sprintf_buf[0] = '%';
+                       sprintf_buf[1] = 0;
+                       objv--; /* undo the objv++ below */
             break;
         default:
             spec[0] = *fmt; spec[1] = '\0';
@@ -2200,6 +2420,16 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
                     "bad field specifier \"",  spec, "\"", NULL);
             return NULL;
         }
+               /* force terminate */
+#if 0
+               printf("FMT was: %s\n", fmt_str );
+               printf("RES was: |%s|\n", sprintf_buf );
+#endif
+               
+               sprintf_buf[ JIM_MAX_FMT - 1] = 0;
+               Jim_AppendString( interp, resObjPtr, sprintf_buf, strlen(sprintf_buf) );
+               /* next obj */
+               objv++;
         fmt++;
         fmtLen--;
     }
@@ -3910,7 +4140,7 @@ int Jim_Collect(Jim_Interp *interp)
                 Jim_AddHashEntry(&marks,
                     &objPtr->internalRep.refValue.id, NULL);
 #ifdef JIM_DEBUG_GC
-                fprintf(interp->stdout_,
+                Jim_fprintf(interp,interp->cookie_stdout,
                     "MARK (reference): %d refcount: %d" JIM_NL, 
                     (int) objPtr->internalRep.refValue.id,
                     objPtr->refCount);
@@ -3949,7 +4179,7 @@ int Jim_Collect(Jim_Interp *interp)
                  * was found. Mark it. */
                 Jim_AddHashEntry(&marks, &id, NULL);
 #ifdef JIM_DEBUG_GC
-                fprintf(interp->stdout_,"MARK: %d" JIM_NL, (int)id);
+                Jim_fprintf(interp,interp->cookie_stdout,"MARK: %d" JIM_NL, (int)id);
 #endif
                 p += JIM_REFERENCE_SPACE;
             }
@@ -3969,7 +4199,7 @@ int Jim_Collect(Jim_Interp *interp)
          * this reference. */
         if (Jim_FindHashEntry(&marks, refId) == NULL) {
 #ifdef JIM_DEBUG_GC
-            fprintf(interp->stdout_,"COLLECTING %d" JIM_NL, (int)*refId);
+            Jim_fprintf(interp,interp->cookie_stdout,"COLLECTING %d" JIM_NL, (int)*refId);
 #endif
             collected++;
             /* Drop the reference, but call the
@@ -4057,9 +4287,14 @@ Jim_Interp *Jim_CreateInterp(void)
     i->freeFramesList = NULL;
     i->prngState = NULL;
     i->evalRetcodeLevel = -1;
-    i->stdin_ = stdin;
-    i->stdout_ = stdout;
-    i->stderr_ = stderr;
+    i->cookie_stdin = stdin;
+    i->cookie_stdout = stdout;
+    i->cookie_stderr = stderr;
+       i->cb_fwrite   = ((size_t (*)( const void *, size_t, size_t, void *))(fwrite));
+       i->cb_fread    = ((size_t (*)(       void *, size_t, size_t, void *))(fread));
+       i->cb_vfprintf = ((int    (*)( void *, const char *fmt, va_list ))(vfprintf));
+       i->cb_fflush   = ((int    (*)( void *))(fflush));
+       i->cb_fgets    = ((char * (*)( char *, int, void *))(fgets));
 
     /* Note that we can create objects only after the
      * interpreter liveList and freeList pointers are
@@ -4128,23 +4363,23 @@ void Jim_FreeInterp(Jim_Interp *i)
     if (i->liveList != NULL) {
         Jim_Obj *objPtr = i->liveList;
     
-        fprintf(i->stdout_,JIM_NL "-------------------------------------" JIM_NL);
-        fprintf(i->stdout_,"Objects still in the free list:" JIM_NL);
+        Jim_fprintf( i, i->cookie_stdout,JIM_NL "-------------------------------------" JIM_NL);
+        Jim_fprintf( i, i->cookie_stdout,"Objects still in the free list:" JIM_NL);
         while(objPtr) {
             const char *type = objPtr->typePtr ?
                 objPtr->typePtr->name : "";
-            fprintf(i->stdout_,"%p \"%-10s\": '%.20s' (refCount: %d)" JIM_NL,
+            Jim_fprintf( i, i->cookie_stdout,"%p \"%-10s\": '%.20s' (refCount: %d)" JIM_NL,
                     objPtr, type,
                     objPtr->bytes ? objPtr->bytes
                     : "(null)", objPtr->refCount);
             if (objPtr->typePtr == &sourceObjType) {
-                fprintf(i->stdout_, "FILE %s LINE %d" JIM_NL,
+                Jim_fprintf( i, i->cookie_stdout, "FILE %s LINE %d" JIM_NL,
                 objPtr->internalRep.sourceValue.fileName,
                 objPtr->internalRep.sourceValue.lineNumber);
             }
             objPtr = objPtr->nextObjPtr;
         }
-        fprintf(stdout, "-------------------------------------" JIM_NL JIM_NL);
+        Jim_fprintf( i, i->cookie_stdout, "-------------------------------------" JIM_NL JIM_NL);
         Jim_Panic(i,"Live list non empty freeing the interpreter! Leak?");
     }
     /* Free all the freed objects. */
@@ -4330,22 +4565,22 @@ int Jim_GetExitCode(Jim_Interp *interp) {
     return interp->exitCode;
 }
 
-FILE *Jim_SetStdin(Jim_Interp *interp, FILE *fp)
+void *Jim_SetStdin(Jim_Interp *interp, void *fp)
 {
-    if (fp != NULL) interp->stdin_ = fp;
-    return interp->stdin_;
+    if (fp != NULL) interp->cookie_stdin = fp;
+    return interp->cookie_stdin;
 }
 
-FILE *Jim_SetStdout(Jim_Interp *interp, FILE *fp)
+void *Jim_SetStdout(Jim_Interp *interp, void *fp)
 {
-    if (fp != NULL) interp->stdout_ = fp;
-    return interp->stdout_;
+    if (fp != NULL) interp->cookie_stdout = fp;
+    return interp->cookie_stdout;
 }
 
-FILE *Jim_SetStderr(Jim_Interp *interp, FILE *fp)
+void *Jim_SetStderr(Jim_Interp *interp, void  *fp)
 {
-    if (fp != NULL) interp->stderr_ = fp;
-    return interp->stderr_;
+    if (fp != NULL) interp->cookie_stderr = fp;
+    return interp->cookie_stderr;
 }
 
 /* -----------------------------------------------------------------------------
@@ -8010,10 +8245,10 @@ int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
             retcode = cmdPtr->cmdProc(interp, objc, objv);
         } else {
             retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
-            if (retcode == JIM_ERR) {
-                JimAppendStackTrace(interp,
-                    Jim_GetString(objv[0], NULL), "?", 1);
-            }
+    if (retcode == JIM_ERR) {
+        JimAppendStackTrace(interp,
+            Jim_GetString(objv[0], NULL), "?", 1);
+    }
         }
     }
     /* Decr refcount of arguments and return the retcode */
@@ -8305,6 +8540,11 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
         } else {
             /* Call [unknown] */
             retcode = JimUnknown(interp, argc, argv);
+            if (retcode == JIM_ERR) {
+                JimAppendStackTrace(interp,
+                    Jim_GetString(argv[0], NULL), script->fileName,
+                    token[i-argc*2].linenr);
+            }
         }
         if (retcode != JIM_OK) {
             i -= argc*2; /* point to the command name. */
@@ -8478,7 +8718,7 @@ int Jim_EvalObjBackground(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
         Jim_IncrRefCount(objv[1]);
         if (Jim_EvalObjVector(interp, 2, objv) != JIM_OK) {
             /* Report the error to stderr. */
-            fprintf(interp->stderr_, "Background error:" JIM_NL);
+            Jim_fprintf( interp, interp->cookie_stderr, "Background error:" JIM_NL);
             Jim_PrintErrorMessage(interp);
         }
         Jim_DecrRefCount(interp, objv[0]);
@@ -8509,10 +8749,12 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
             maxlen = totread+buflen+1;
             prg = Jim_Realloc(prg, maxlen);
         }
+               /* do not use Jim_fread() - this is really a file */
         if ((nread = fread(prg+totread, 1, buflen, fp)) == 0) break;
         totread += nread;
     }
     prg[totread] = '\0';
+       /* do not use Jim_fclose() - this is really a file */
     fclose(fp);
 
     scriptObjPtr = Jim_NewStringObjNoAlloc(interp, prg, totread);
@@ -9011,8 +9253,8 @@ static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc,
         }
     }
     str = Jim_GetString(argv[1], &len);
-    fwrite(str, 1, len, interp->stdout_);
-    if (!nonewline) fprintf(interp->stdout_, JIM_NL);
+    Jim_fwrite(interp, str, 1, len, interp->cookie_stdout);
+    if (!nonewline) Jim_fprintf( interp, interp->cookie_stdout, JIM_NL);
     return JIM_OK;
 }
 
@@ -9796,7 +10038,10 @@ static int Jim_IfCoreCommand(Jim_Interp *interp, int argc,
             if (boolean)
                 return Jim_EvalObj(interp, argv[current]);
              /* Ok: no else-clause follows */
-            if (++current >= argc) return JIM_OK;
+            if (++current >= argc) {
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));                   
+               return JIM_OK;
+            }
             falsebody = current++;
             if (Jim_CompareStringImmediate(interp, argv[falsebody],
                         "else")) {
@@ -11744,9 +11989,9 @@ void Jim_PrintErrorMessage(Jim_Interp *interp)
 {
     int len, i;
 
-    fprintf(interp->stderr_, "Runtime error, file \"%s\", line %d:" JIM_NL,
-            interp->errorFileName, interp->errorLine);
-    fprintf(interp->stderr_, "    %s" JIM_NL,
+    Jim_fprintf(interp, interp->cookie_stderr, "Runtime error, file \"%s\", line %d:" JIM_NL,
+                               interp->errorFileName, interp->errorLine);
+    Jim_fprintf(interp,interp->cookie_stderr, "    %s" JIM_NL,
             Jim_GetString(interp->result, NULL));
     Jim_ListLength(interp, interp->stackTrace, &len);
     for (i = 0; i < len; i+= 3) {
@@ -11761,7 +12006,7 @@ void Jim_PrintErrorMessage(Jim_Interp *interp)
         Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr,
                 JIM_NONE);
         line = Jim_GetString(objPtr, NULL);
-        fprintf(interp->stderr_,
+               Jim_fprintf( interp, interp->cookie_stderr,
                 "In procedure '%s' called at file \"%s\", line %s" JIM_NL,
                 proc, file, line);
     }
@@ -11772,7 +12017,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
     int retcode = JIM_OK;
     Jim_Obj *scriptObjPtr;
 
-    fprintf(interp->stdout_, "Welcome to Jim version %d.%d, "
+    Jim_fprintf(interp,interp->cookie_stdout, "Welcome to Jim version %d.%d, "
            "Copyright (c) 2005-8 Salvatore Sanfilippo" JIM_NL,
            JIM_VERSION / 100, JIM_VERSION % 100);
      Jim_SetVariableStrWithStr(interp, "jim_interactive", "1");
@@ -11786,12 +12031,12 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
 
         if (retcode != 0) {
             if (retcode >= 2 && retcode <= 6)
-                fprintf(interp->stdout_, "[%s] . ", retcodestr[retcode]);
+                Jim_fprintf(interp,interp->cookie_stdout, "[%s] . ", retcodestr[retcode]);
             else
-                fprintf(interp->stdout_, "[%d] . ", retcode);
+                Jim_fprintf(interp,interp->cookie_stdout, "[%d] . ", retcode);
         } else
-            fprintf(interp->stdout_, ". ");
-        fflush(interp->stdout_);
+            Jim_fprintf( interp, interp->cookie_stdout, ". ");
+        Jim_fflush( interp, interp->cookie_stdout);
         scriptObjPtr = Jim_NewStringObj(interp, "", 0);
         Jim_IncrRefCount(scriptObjPtr);
         while(1) {
@@ -11799,7 +12044,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
             char state;
             int len;
 
-            if (fgets(buf, 1024, interp->stdin_) == NULL) {
+            if ( Jim_fgets(interp, buf, 1024, interp->cookie_stdin) == NULL) {
                 Jim_DecrRefCount(interp, scriptObjPtr);
                 goto out;
             }
@@ -11807,8 +12052,8 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
             str = Jim_GetString(scriptObjPtr, &len);
             if (Jim_ScriptIsComplete(str, len, &state))
                 break;
-            fprintf(interp->stdout_, "%c> ", state);
-            fflush(stdout);
+            Jim_fprintf( interp, interp->cookie_stdout, "%c> ", state);
+            Jim_fflush( interp, interp->cookie_stdout);
         }
         retcode = Jim_EvalObj(interp, scriptObjPtr);
         Jim_DecrRefCount(interp, scriptObjPtr);
@@ -11819,11 +12064,71 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
             exit(Jim_GetExitCode(interp));
         } else {
             if (reslen) {
-                fwrite(result, 1, reslen, interp->stdout_);
-                fprintf(interp->stdout_, JIM_NL);
+                               Jim_fwrite( interp, result, 1, reslen, interp->cookie_stdout);
+                               Jim_fprintf( interp,interp->cookie_stdout, JIM_NL);
             }
         }
     }
 out:
     return 0;
 }
+
+/* -----------------------------------------------------------------------------
+ * Jim's idea of STDIO..
+ * ---------------------------------------------------------------------------*/
+
+int Jim_fprintf( Jim_Interp *interp, void *cookie, const char *fmt, ... )
+{
+       int r;
+
+       va_list ap;
+       va_start(ap,fmt);
+       r = Jim_vfprintf( interp, cookie, fmt,ap );
+       va_end(ap);
+       return r;
+}
+
+int Jim_vfprintf( Jim_Interp *interp, void *cookie, const char *fmt, va_list ap )
+{
+       if( (interp == NULL) || (interp->cb_vfprintf == NULL) ){
+               errno = ENOTSUP;
+               return -1;
+       }
+       return (*(interp->cb_vfprintf))( cookie, fmt, ap );
+}
+
+size_t Jim_fwrite( Jim_Interp *interp, const void *ptr, size_t size, size_t n, void *cookie )
+{
+       if( (interp == NULL) || (interp->cb_fwrite == NULL) ){
+               errno = ENOTSUP;
+               return 0;
+       }
+       return (*(interp->cb_fwrite))( ptr, size, n, cookie);
+}
+
+size_t Jim_fread( Jim_Interp *interp, void *ptr, size_t size, size_t n, void *cookie )
+{
+       if( (interp == NULL) || (interp->cb_fread == NULL) ){
+               errno = ENOTSUP;
+               return 0;
+       }
+       return (*(interp->cb_fread))( ptr, size, n, cookie);
+}
+
+int Jim_fflush( Jim_Interp *interp, void *cookie )
+{
+       if( (interp == NULL) || (interp->cb_fflush == NULL) ){
+               /* pretend all is well */
+               return 0;
+       }
+       return (*(interp->cb_fflush))( cookie );
+}
+
+char* Jim_fgets( Jim_Interp *interp, char *s, int size, void *cookie )
+{
+       if( (interp == NULL) || (interp->cb_fgets == NULL) ){
+               errno = ENOTSUP;
+               return NULL;
+       }
+       return (*(interp->cb_fgets))( s, size, cookie );
+}