diff options
author | oharboe <oharboe> | 2008-07-07 07:14:18 +0000 |
---|---|---|
committer | oharboe <oharboe> | 2008-07-07 07:14:18 +0000 |
commit | 1bfae9bb5c9d3524a7d8841d2df13209f381bbb6 (patch) | |
tree | d849894875047e4cae48d7f53be5baf3283d9252 | |
parent | 66c3ed67e8414a0f4c0c2c12752695d5ce36aab2 (diff) | |
download | jimtcl-1bfae9bb5c9d3524a7d8841d2df13209f381bbb6.zip jimtcl-1bfae9bb5c9d3524a7d8841d2df13209f381bbb6.tar.gz jimtcl-1bfae9bb5c9d3524a7d8841d2df13209f381bbb6.tar.bz2 |
src/Jim.c
- ** THIS INCLUDES A PREVIOUS PATCH I SENT EARLIER **
- that impliments many [format] specifies JIM did not support.
- Jim_FormatString() - **MAJOR** work.
- Previously only supported "%s" "%d" and "%c"
- And what support existed had bugs.
- NEW: *MANY* formating parameters are now supported.
- TODO: The "precision" specifier is not supported.
** NEW ** This patch.
- Jim_StringToWide() test if no conversion occured.
- Jim_StringToIndex() test if no conversion occured.
- Jim_StringToDouble() test if no conversion occured.
** NEW ** This Patch. Major Work.
- Previously output from JIM did not get sent to GDB
- Ditto: Output to Telnet session.
- Above items are now fixed - By introducing callbacks
new function pointers in the "interp" structure.
- Helpers that call the callbacks.
- New function: Jim_fprintf()
- New function: Jim_vfprintf()
- New function: Jim_fwrite()
- New function: Jim_fread()
- New function: Jim_fflush()
- New function: Jim_fgets()
By default: the output is to STDIO as previous.
The "openocd.c" - redirects the output as needed.
- Jim_Panic() - Send panic to both STDERR and the interps
specified STDERR output as a 2nd choice.
- Now JIM's "stdin/stdout/stderr" paramters are "void *"
and are no longer "FILE *".
src/Jim.h
- **MAJOR**
- New JIM STDIO callbacks in the "interp" structure.
- change: "stdin/stdout/stderr" are now "void *" cookies.
- New JIM stdio helper functions.
-rw-r--r-- | ChangeLog | 49 | ||||
-rw-r--r-- | ecos/language/tcl/jim/current/include/jim.h | 35 | ||||
-rw-r--r-- | ecos/language/tcl/jim/current/src/jim-aio.c | 4 | ||||
-rw-r--r-- | ecos/language/tcl/jim/current/src/jim.c | 374 | ||||
-rw-r--r-- | jim.c | 365 | ||||
-rw-r--r-- | jim.h | 33 |
6 files changed, 728 insertions, 132 deletions
@@ -1,3 +1,52 @@ +2008-07-07 Duane Ellis <openocd@duaneellis.com> + +src/Jim.c + - ** THIS INCLUDES A PREVIOUS PATCH I SENT EARLIER ** + - that impliments many [format] specifies JIM did not support. + - Jim_FormatString() - **MAJOR** work. + - Previously only supported "%s" "%d" and "%c" + - And what support existed had bugs. + - NEW: *MANY* formating parameters are now supported. + - TODO: The "precision" specifier is not supported. + + ** NEW ** This patch. + + - Jim_StringToWide() test if no conversion occured. + - Jim_StringToIndex() test if no conversion occured. + - Jim_StringToDouble() test if no conversion occured. + + ** NEW ** This Patch. Major Work. + - Previously output from JIM did not get sent to GDB + - Ditto: Output to Telnet session. + - Above items are now fixed - By introducing callbacks + new function pointers in the "interp" structure. + + - Helpers that call the callbacks. + + - New function: Jim_fprintf() + - New function: Jim_vfprintf() + - New function: Jim_fwrite() + - New function: Jim_fread() + - New function: Jim_fflush() + - New function: Jim_fgets() + + By default: the output is to STDIO as previous. + The "openocd.c" - redirects the output as needed. + + - Jim_Panic() - Send panic to both STDERR and the interps + specified STDERR output as a 2nd choice. + + - Now JIM's "stdin/stdout/stderr" paramters are "void *" + and are no longer "FILE *". + +src/Jim.h + - **MAJOR** + - New JIM STDIO callbacks in the "interp" structure. + - change: "stdin/stdout/stderr" are now "void *" cookies. + - New JIM stdio helper functions. + + + 2008-06-17 Andrew Lunn <andrew@lunn.ch> / oharboe * ChangeLog, jim-aio.c: Andrew spotted a bug in the diff --git a/ecos/language/tcl/jim/current/include/jim.h b/ecos/language/tcl/jim/current/include/jim.h index f4133f6..58db66b 100644 --- a/ecos/language/tcl/jim/current/include/jim.h +++ b/ecos/language/tcl/jim/current/include/jim.h @@ -2,8 +2,6 @@ * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
* Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
*
- * $Id: jim.h,v 1.77 2007/01/31 00:49:05 patthoyts Exp $
- *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -499,9 +497,14 @@ typedef struct Jim_Interp { struct Jim_HashTable assocData; /* per-interp storage for use by packages */
Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */
struct Jim_HashTable packages; /* Provided packages hash table */
- FILE *stdin_; /* input file pointer, 'stdin' by default */
- FILE *stdout_; /* output file pointer, 'stdout' by default */
- FILE *stderr_; /* errors file pointer, 'stderr' by default */
+ void *cookie_stdin; /* input file pointer, 'stdin' by default */
+ void *cookie_stdout; /* output file pointer, 'stdout' by default */
+ void *cookie_stderr; /* errors file pointer, 'stderr' by default */
+ size_t (*cb_fwrite )( const void *ptr, size_t size, size_t n, void *cookie );
+ size_t (*cb_fread )( void *ptr, size_t size, size_t n, void *cookie );
+ int (*cb_vfprintf)( void *cookie, const char *fmt, va_list ap );
+ int (*cb_fflush )( void *cookie );
+ char *(*cb_fgets )( char *s, int size, void *cookie );
} Jim_Interp;
/* Currently provided as macro that performs the increment.
@@ -664,9 +667,9 @@ JIM_STATIC int JIM_API(Jim_GetFinalizer) (Jim_Interp *interp, Jim_Obj *objPtr, J JIM_STATIC Jim_Interp * JIM_API(Jim_CreateInterp) (void);
JIM_STATIC void JIM_API(Jim_FreeInterp) (Jim_Interp *i);
JIM_STATIC int JIM_API(Jim_GetExitCode) (Jim_Interp *interp);
-JIM_STATIC FILE * JIM_API(Jim_SetStdin) (Jim_Interp *interp, FILE *fp);
-JIM_STATIC FILE * JIM_API(Jim_SetStdout) (Jim_Interp *interp, FILE *fp);
-JIM_STATIC FILE * JIM_API(Jim_SetStderr) (Jim_Interp *interp, FILE *fp);
+JIM_STATIC void * JIM_API(Jim_SetStdin) (Jim_Interp *interp, void *fp);
+JIM_STATIC void * JIM_API(Jim_SetStdout) (Jim_Interp *interp, void *fp);
+JIM_STATIC void * JIM_API(Jim_SetStderr) (Jim_Interp *interp, void *fp);
/* commands */
JIM_STATIC void JIM_API(Jim_RegisterCoreCommands) (Jim_Interp *interp);
@@ -817,6 +820,15 @@ JIM_STATIC int JIM_API(Jim_InteractivePrompt) (Jim_Interp *interp); /* Misc */
JIM_STATIC void JIM_API(Jim_Panic) (Jim_Interp *interp, const char *fmt, ...);
+/* Jim's STDIO */
+JIM_STATIC int JIM_API( Jim_fprintf )( Jim_Interp *interp, void *cookie, const char *fmt, ... );
+JIM_STATIC int JIM_API( Jim_vfprintf )( Jim_Interp *interp, void *cookie, const char *fmt, va_list ap );
+JIM_STATIC size_t JIM_API( Jim_fwrite )( Jim_Interp *interp, const void *ptr, size_t size, size_t nmeb, void *cookie );
+JIM_STATIC size_t JIM_API( Jim_fread )( Jim_Interp *interp, void *ptr, size_t size, size_t nmeb, void *cookie );
+JIM_STATIC int JIM_API( Jim_fflush )( Jim_Interp *interp, void *cookie );
+JIM_STATIC char * JIM_API( Jim_fgets )( Jim_Interp *interp, char *s, int size, void *cookie );
+
+
#undef JIM_STATIC
#undef JIM_API
@@ -944,6 +956,13 @@ static void Jim_InitExtension(Jim_Interp *interp) JIM_GET_API(StackPop);
JIM_GET_API(StackPeek);
JIM_GET_API(FreeStackElements);
+ JIM_GET_API(fprintf );
+ JIM_GET_API(vfprintf );
+ JIM_GET_API(fwrite );
+ JIM_GET_API(fread );
+ JIM_GET_API(fflush );
+ JIM_GET_API(fgets );
+
}
#endif /* defined JIM_EXTENSION || defined JIM_EMBEDDED */
diff --git a/ecos/language/tcl/jim/current/src/jim-aio.c b/ecos/language/tcl/jim/current/src/jim-aio.c index 210e416..233f992 100644 --- a/ecos/language/tcl/jim/current/src/jim-aio.c +++ b/ecos/language/tcl/jim/current/src/jim-aio.c @@ -1,8 +1,6 @@ /* Jim - ANSI I/O extension
* Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
*
- * $Id: jim-aio.c,v 1.12 2008/06/15 21:03:26 oharboe Exp $
- *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -143,7 +141,7 @@ static int JimAioHandlerCommand(Jim_Interp *interp, int argc, buf[AIO_BUF_LEN-1] = '_';
if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL)
break;
- if (buf[AIO_BUF_LEN-1] == '\0' && buf[AIO_BUF_LEN] == '\n')
+ if (buf[AIO_BUF_LEN-1] == '\0' && buf[AIO_BUF_LEN-2] != '\n')
more = 1;
if (more) {
Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN-1);
diff --git a/ecos/language/tcl/jim/current/src/jim.c b/ecos/language/tcl/jim/current/src/jim.c index 47525d1..fdbdf18 100644 --- a/ecos/language/tcl/jim/current/src/jim.c +++ b/ecos/language/tcl/jim/current/src/jim.c @@ -2,8 +2,6 @@ * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
* Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
*
- * $Id: jim.c,v 1.173 2008/06/15 21:03:26 oharboe Exp $
- *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -47,7 +45,9 @@ #ifndef WIN32
#define WIN32 1
#endif
+#ifndef STRICT
#define STRICT
+#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#if _MSC_VER >= 1000
@@ -365,7 +365,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) {
@@ -382,7 +382,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) {
@@ -439,7 +439,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;
}
@@ -462,13 +462,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];
@@ -483,6 +486,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();
}
@@ -2138,21 +2148,36 @@ 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;
while (*fmt != '%' && fmtLen) {
fmt++; fmtLen--;
@@ -2161,38 +2186,191 @@ 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;
+ 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 '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ width = 0;
+ while( isdigit(*fmt) && (fmtLen > 0) ){
+ width = (width * 10) + (*fmt - '0');
+ fmt++; fmtLen--;
+ }
+ 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;
+ }
+ 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);
+ }
+ *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';
@@ -2202,6 +2380,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--;
}
@@ -3912,7 +4100,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);
@@ -3951,7 +4139,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;
}
@@ -3971,7 +4159,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
@@ -4059,9 +4247,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
@@ -4130,23 +4323,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. */
@@ -4332,22 +4525,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;
}
/* -----------------------------------------------------------------------------
@@ -8480,7 +8673,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]);
@@ -8511,10 +8704,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);
@@ -9013,8 +9208,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;
}
@@ -11746,9 +11941,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) {
@@ -11763,7 +11958,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);
}
@@ -11774,13 +11969,10 @@ int Jim_InteractivePrompt(Jim_Interp *interp) int retcode = JIM_OK;
Jim_Obj *scriptObjPtr;
- fprintf(interp->stdout_, "Welcome to Jim version %d.%d, "
- "Copyright (c) 2005 Salvatore Sanfilippo" JIM_NL,
+ 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);
- fprintf(interp->stdout_,
- "CVS ID: $Id: jim.c,v 1.173 2008/06/15 21:03:26 oharboe Exp $"
- JIM_NL);
- Jim_SetVariableStrWithStr(interp, "jim_interactive", "1");
+ Jim_SetVariableStrWithStr(interp, "jim_interactive", "1");
while (1) {
char buf[1024];
const char *result;
@@ -11791,12 +11983,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) {
@@ -11804,7 +11996,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;
}
@@ -11812,8 +12004,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);
@@ -11824,11 +12016,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 );
+}
@@ -45,7 +45,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 +365,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 +382,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 +439,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 +462,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 +486,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 +2148,36 @@ 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; while (*fmt != '%' && fmtLen) { fmt++; fmtLen--; @@ -2159,38 +2186,191 @@ 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; + 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 '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + width = 0; + while( isdigit(*fmt) && (fmtLen > 0) ){ + width = (width * 10) + (*fmt - '0'); + fmt++; fmtLen--; + } + 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; + } + 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); + } + *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 +2380,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 +4100,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 +4139,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 +4159,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 +4247,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 +4323,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 +4525,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; } /* ----------------------------------------------------------------------------- @@ -8478,7 +8673,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 +8704,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 +9208,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; } @@ -11744,9 +11941,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 +11958,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 +11969,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 +11983,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 +11996,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 +12004,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 +12016,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 ); +} @@ -497,9 +497,14 @@ typedef struct Jim_Interp { struct Jim_HashTable assocData; /* per-interp storage for use by packages */ Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */ struct Jim_HashTable packages; /* Provided packages hash table */ - FILE *stdin_; /* input file pointer, 'stdin' by default */ - FILE *stdout_; /* output file pointer, 'stdout' by default */ - FILE *stderr_; /* errors file pointer, 'stderr' by default */ + void *cookie_stdin; /* input file pointer, 'stdin' by default */ + void *cookie_stdout; /* output file pointer, 'stdout' by default */ + void *cookie_stderr; /* errors file pointer, 'stderr' by default */ + size_t (*cb_fwrite )( const void *ptr, size_t size, size_t n, void *cookie ); + size_t (*cb_fread )( void *ptr, size_t size, size_t n, void *cookie ); + int (*cb_vfprintf)( void *cookie, const char *fmt, va_list ap ); + int (*cb_fflush )( void *cookie ); + char *(*cb_fgets )( char *s, int size, void *cookie ); } Jim_Interp; /* Currently provided as macro that performs the increment. @@ -662,9 +667,9 @@ JIM_STATIC int JIM_API(Jim_GetFinalizer) (Jim_Interp *interp, Jim_Obj *objPtr, J JIM_STATIC Jim_Interp * JIM_API(Jim_CreateInterp) (void); JIM_STATIC void JIM_API(Jim_FreeInterp) (Jim_Interp *i); JIM_STATIC int JIM_API(Jim_GetExitCode) (Jim_Interp *interp); -JIM_STATIC FILE * JIM_API(Jim_SetStdin) (Jim_Interp *interp, FILE *fp); -JIM_STATIC FILE * JIM_API(Jim_SetStdout) (Jim_Interp *interp, FILE *fp); -JIM_STATIC FILE * JIM_API(Jim_SetStderr) (Jim_Interp *interp, FILE *fp); +JIM_STATIC void * JIM_API(Jim_SetStdin) (Jim_Interp *interp, void *fp); +JIM_STATIC void * JIM_API(Jim_SetStdout) (Jim_Interp *interp, void *fp); +JIM_STATIC void * JIM_API(Jim_SetStderr) (Jim_Interp *interp, void *fp); /* commands */ JIM_STATIC void JIM_API(Jim_RegisterCoreCommands) (Jim_Interp *interp); @@ -815,6 +820,15 @@ JIM_STATIC int JIM_API(Jim_InteractivePrompt) (Jim_Interp *interp); /* Misc */ JIM_STATIC void JIM_API(Jim_Panic) (Jim_Interp *interp, const char *fmt, ...); +/* Jim's STDIO */ +JIM_STATIC int JIM_API( Jim_fprintf )( Jim_Interp *interp, void *cookie, const char *fmt, ... ); +JIM_STATIC int JIM_API( Jim_vfprintf )( Jim_Interp *interp, void *cookie, const char *fmt, va_list ap ); +JIM_STATIC size_t JIM_API( Jim_fwrite )( Jim_Interp *interp, const void *ptr, size_t size, size_t nmeb, void *cookie ); +JIM_STATIC size_t JIM_API( Jim_fread )( Jim_Interp *interp, void *ptr, size_t size, size_t nmeb, void *cookie ); +JIM_STATIC int JIM_API( Jim_fflush )( Jim_Interp *interp, void *cookie ); +JIM_STATIC char * JIM_API( Jim_fgets )( Jim_Interp *interp, char *s, int size, void *cookie ); + + #undef JIM_STATIC #undef JIM_API @@ -942,6 +956,13 @@ static void Jim_InitExtension(Jim_Interp *interp) JIM_GET_API(StackPop); JIM_GET_API(StackPeek); JIM_GET_API(FreeStackElements); + JIM_GET_API(fprintf ); + JIM_GET_API(vfprintf ); + JIM_GET_API(fwrite ); + JIM_GET_API(fread ); + JIM_GET_API(fflush ); + JIM_GET_API(fgets ); + } #endif /* defined JIM_EXTENSION || defined JIM_EMBEDDED */ |