From 1bfae9bb5c9d3524a7d8841d2df13209f381bbb6 Mon Sep 17 00:00:00 2001 From: oharboe Date: Mon, 7 Jul 2008 07:14:18 +0000 Subject: 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. --- ChangeLog | 49 ++++ ecos/language/tcl/jim/current/include/jim.h | 35 ++- ecos/language/tcl/jim/current/src/jim-aio.c | 4 +- ecos/language/tcl/jim/current/src/jim.c | 374 +++++++++++++++++++++++----- jim.c | 365 +++++++++++++++++++++++---- jim.h | 33 ++- 6 files changed, 728 insertions(+), 132 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3adb180..0d41b3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +2008-07-07 Duane Ellis + +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 / 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 * Copyright 2005 Clemens Hintze * - * $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 * - * $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 * Copyright 2005 Clemens Hintze * - * $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 #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 ' 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 ); +} diff --git a/jim.c b/jim.c index a466a08..5ef3983 100644 --- a/jim.c +++ b/jim.c @@ -45,7 +45,9 @@ #ifndef WIN32 #define WIN32 1 #endif +#ifndef STRICT #define STRICT +#endif #define WIN32_LEAN_AND_MEAN #include #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 ' 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 ); +} diff --git a/jim.h b/jim.h index cbd0d8f..9e9c7dc 100644 --- a/jim.h +++ b/jim.h @@ -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 */ -- cgit v1.1