#include <assert.h>
#include <errno.h>
#include <time.h>
+#if defined(WIN32)
+/* sys/time - need is different */
+#else
+#include <sys/time.h> // for gettimeofday()
+#endif
#include "replacements.h"
* Utility functions
* ---------------------------------------------------------------------------*/
+static char *
+jim_vasprintf( const char *fmt, va_list ap )
+{
+#ifndef HAVE_VASPRINTF
+ /* yucky way */
+static char buf[2048];
+ vsnprintf( buf, sizeof(buf), fmt, ap );
+ /* garentee termination */
+ buf[sizeof(buf)-1] = 0;
+#else
+ char *buf;
+ vasprintf( &buf, fmt, ap );
+#endif
+ return buf;
+}
+
+static void
+jim_vasprintf_done( void *buf )
+{
+#ifndef HAVE_VASPRINTF
+ (void)(buf);
+#else
+ free(buf);
+#endif
+}
+
+
/*
* Convert a string to a jim_wide INTEGER.
* This function originates from BSD.
StringAppendString(objPtr, str, len);
}
+void Jim_AppendString_sprintf( Jim_Interp *interp, Jim_Obj *objPtr, const char *fmt, ... )
+{
+ char *buf;
+ va_list ap;
+
+ va_start( ap, fmt );
+ buf = jim_vasprintf( fmt, ap );
+ va_end(ap);
+
+ if( buf ){
+ Jim_AppendString( interp, objPtr, buf, -1 );
+ jim_vasprintf_done(buf);
+ }
+}
+
+
void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_Obj *appendObjPtr)
{
* 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)
+#define JIM_MAX_FMT 2048
+static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
+ int objc, Jim_Obj *const *objv, char *sprintf_buf)
{
const char *fmt, *_fmt;
int fmtLen;
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;
return resObjPtr;
}
+Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
+ int objc, Jim_Obj *const *objv)
+{
+ char *sprintf_buf=malloc(JIM_MAX_FMT);
+ Jim_Obj *t=Jim_FormatString_Inner(interp, fmtObjPtr, objc, objv, sprintf_buf);
+ free(sprintf_buf);
+ return t;
+}
+
/* -----------------------------------------------------------------------------
* Compared String Object
* ---------------------------------------------------------------------------*/
}
int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
- const char **tablePtr, int *indexPtr, const char *name, int flags)
+ const char * const *tablePtr, int *indexPtr, const char *name, int flags)
{
- const char **entryPtr = NULL;
+ const char * const *entryPtr = NULL;
char **tablePtrSorted;
int i, count = 0;
return JIM_ERR;
}
+int Jim_GetNvp(Jim_Interp *interp,
+ Jim_Obj *objPtr,
+ const Jim_Nvp *nvp_table,
+ const Jim_Nvp ** result)
+{
+ Jim_Nvp *n;
+ int e;
+
+ e = Jim_Nvp_name2value_obj( interp, nvp_table, objPtr, &n );
+ if( e == JIM_ERR ){
+ return e;
+ }
+
+ /* Success? found? */
+ if( n->name ){
+ /* remove const */
+ *result = (Jim_Nvp *)n;
+ return JIM_OK;
+ } else {
+ return JIM_ERR;
+ }
+}
+
/* -----------------------------------------------------------------------------
* Source Object
*
return retcode;
}
-int Jim_Eval(Jim_Interp *interp, const char *script)
+int Jim_Eval_Named(Jim_Interp *interp, const char *script, const char *filename, int lineno)
{
- Jim_Obj *scriptObjPtr = Jim_NewStringObj(interp, script, -1);
int retval;
+ Jim_Obj *scriptObjPtr;
+ scriptObjPtr = Jim_NewStringObj(interp, script, -1);
Jim_IncrRefCount(scriptObjPtr);
+
+
+ if( filename ){
+ JimSetSourceInfo( interp, scriptObjPtr, filename, lineno );
+ }
+
retval = Jim_EvalObj(interp, scriptObjPtr);
Jim_DecrRefCount(interp, scriptObjPtr);
return retval;
}
+int Jim_Eval(Jim_Interp *interp, const char *script)
+{
+ return Jim_Eval_Named( interp, script, NULL, 0 );
+}
+
+
+
/* Execute script in the scope of the global level */
int Jim_EvalGlobal(Jim_Interp *interp, const char *script)
{
int nread, totread, maxlen, buflen;
int retval;
Jim_Obj *scriptObjPtr;
- char cwd[ 2048 ];
if ((fp = fopen(filename, "r")) == NULL) {
+ const int cwd_len=2048;
+ char *cwd=malloc(cwd_len);
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- getcwd( cwd, sizeof(cwd) );
+ getcwd( cwd, cwd_len );
Jim_AppendStrings(interp, Jim_GetResult(interp),
"Error loading script \"", filename, "\"",
" cwd: ", cwd,
" err: ", strerror(errno), NULL);
+ free(cwd);
return JIM_ERR;
}
buflen = 1024;
JIM_REGISTER_API(Alloc);
JIM_REGISTER_API(Free);
JIM_REGISTER_API(Eval);
+ JIM_REGISTER_API(Eval_Named);
JIM_REGISTER_API(EvalGlobal);
JIM_REGISTER_API(EvalFile);
JIM_REGISTER_API(EvalObj);
JIM_REGISTER_API(NewStringObj);
JIM_REGISTER_API(NewStringObjNoAlloc);
JIM_REGISTER_API(AppendString);
+ JIM_REGISTER_API(AppendString_sprintf);
JIM_REGISTER_API(AppendObj);
JIM_REGISTER_API(AppendStrings);
JIM_REGISTER_API(StringEqObj);
JIM_REGISTER_API(StackPop);
JIM_REGISTER_API(StackPeek);
JIM_REGISTER_API(FreeStackElements);
+ JIM_REGISTER_API(fprintf );
+ JIM_REGISTER_API(vfprintf );
+ JIM_REGISTER_API(fwrite );
+ JIM_REGISTER_API(fread );
+ JIM_REGISTER_API(fflush );
+ JIM_REGISTER_API(fgets );
+ JIM_REGISTER_API(GetNvp);
+ JIM_REGISTER_API(Nvp_name2value);
+ JIM_REGISTER_API(Nvp_name2value_simple);
+ JIM_REGISTER_API(Nvp_name2value_obj);
+ JIM_REGISTER_API(Nvp_name2value_nocase);
+ JIM_REGISTER_API(Nvp_name2value_obj_nocase);
+
+ JIM_REGISTER_API(Nvp_value2name);
+ JIM_REGISTER_API(Nvp_value2name_simple);
+ JIM_REGISTER_API(Nvp_value2name_obj);
+
+ JIM_REGISTER_API(GetOpt_Setup);
+ JIM_REGISTER_API(GetOpt_Debug);
+ JIM_REGISTER_API(GetOpt_Obj);
+ JIM_REGISTER_API(GetOpt_String);
+ JIM_REGISTER_API(GetOpt_Double);
+ JIM_REGISTER_API(GetOpt_Wide);
+ JIM_REGISTER_API(GetOpt_Nvp);
+ JIM_REGISTER_API(GetOpt_NvpUnknown);
+ JIM_REGISTER_API(GetOpt_Enum);
+
+ JIM_REGISTER_API(Debug_ArgvString);
+ JIM_REGISTER_API(SetResult_sprintf);
+ JIM_REGISTER_API(SetResult_NvpUnknown);
+
}
/* -----------------------------------------------------------------------------
return JIM_OK;
}
+
+static void
+jim_get_s_us( jim_wide *s, jim_wide *us )
+{
+#if defined(WIN32)
+ /*
+ * Sorry - I do not have, or use Win32.
+ * This concept is from
+ *
+ * Method is from:
+ * http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
+ *
+ * I have no method to test/verify.
+ * - Duane 6-sep-2008.
+ * (once verified, please somebody remove this comment)
+ */
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+#else
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+#endif
+
+ FILETIME ft;
+ unsigned __int64 tmpres;
+ tmpres = 0;
+ GetSystemTimeAsFileTime( &ft );
+
+ tmpres |= ft.dwHighDateTime;
+ tmpres <<= 32;
+ tmpres |= ft.dwLowDateTime;
+ /* convert to unix representation */
+ tmpres /= 10;
+ tmpres -= DELTA_EPOCH_IN_MICROSECS;
+
+ *s = (tmpres / 1000000ULL);
+ *us = (tmpres % 1000000ULL);
+
+#undef DELTA_EPOCH_IN_MICROSECS
+
+#else
+ /* LINUX/CYGWIN */
+ struct timeval tv;
+ struct timezone tz;
+ gettimeofday( &tv, &tz );
+ *s = tv.tv_sec;
+ *us = tv.tv_usec;
+#endif
+}
+
+
+/* [clock] */
+static int Jim_ClockCoreCommand( Jim_Interp *interp, int argc,
+ Jim_Obj *const *argv)
+{
+ /*
+ * See: TCL man page for 'clock'
+ * we do not impliment all features.
+ */
+ jim_wide r,s,us;
+ int option;
+ const char *options[] = {
+ "clicks",
+ "microseconds",
+ "milliseconds",
+ "seconds",
+ NULL
+ };
+ enum { OPT_CLICKS, OPT_USEC, OPT_MSEC, OPT_SEC };
+
+ if( argc < 2 ){
+ Jim_WrongNumArgs( interp, 1, argv, "option ?arguments ...?");
+ return JIM_ERR;
+ }
+
+ if( Jim_GetEnum(interp, argv[1], options, &option, "option",
+ JIM_ERRMSG) != JIM_OK ){
+ return JIM_ERR;
+ }
+
+ // platform independent get time.
+ jim_get_s_us( &s, &us );
+
+ r = 0;
+ switch(option){
+ case OPT_CLICKS:
+ case OPT_USEC:
+ /* clicks & usecs are the same */
+ r = (s * 1000000) + us;
+ break;
+ case OPT_MSEC:
+ r = (s * 1000) + (us / 1000);
+ break;
+ case OPT_SEC:
+ r = s;
+ break;
+ }
+
+ Jim_SetResult( interp, Jim_NewWideObj( interp, r ) );
+ return JIM_OK;
+}
+
+
static struct {
const char *name;
Jim_CmdProc cmdProc;
{"rand", Jim_RandCoreCommand},
{"package", Jim_PackageCoreCommand},
{"tailcall", Jim_TailcallCoreCommand},
+ {"clock", Jim_ClockCoreCommand},
{NULL, NULL},
};
}
return (*(interp->cb_fgets))( s, size, cookie );
}
+
+Jim_Nvp *
+Jim_Nvp_name2value_simple( const Jim_Nvp *p, const char *name )
+{
+ while( p->name ){
+ if( 0 == strcmp( name, p->name ) ){
+ break;
+ }
+ p++;
+ }
+ return ((Jim_Nvp *)(p));
+}
+
+Jim_Nvp *
+Jim_Nvp_name2value_nocase_simple( const Jim_Nvp *p, const char *name )
+{
+ while( p->name ){
+ if( 0 == strcasecmp( name, p->name ) ){
+ break;
+ }
+ p++;
+ }
+ return ((Jim_Nvp *)(p));
+}
+
+int
+Jim_Nvp_name2value_obj( Jim_Interp *interp,
+ const Jim_Nvp *p,
+ Jim_Obj *o,
+ Jim_Nvp **result )
+{
+ return Jim_Nvp_name2value( interp, p, Jim_GetString( o, NULL ), result );
+}
+
+
+int
+Jim_Nvp_name2value( Jim_Interp *interp,
+ const Jim_Nvp *_p,
+ const char *name,
+ Jim_Nvp **result)
+{
+ const Jim_Nvp *p;
+
+ p = Jim_Nvp_name2value_simple( _p, name );
+
+ /* result */
+ if( result ){
+ *result = (Jim_Nvp *)(p);
+ }
+
+ /* found? */
+ if( p->name ){
+ return JIM_OK;
+ } else {
+ return JIM_ERR;
+ }
+}
+
+int
+Jim_Nvp_name2value_obj_nocase( Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nvp **puthere )
+{
+ return Jim_Nvp_name2value_nocase( interp, p, Jim_GetString( o, NULL ), puthere );
+}
+
+int
+Jim_Nvp_name2value_nocase( Jim_Interp *interp, const Jim_Nvp *_p, const char *name, Jim_Nvp **puthere )
+{
+ const Jim_Nvp *p;
+
+ p = Jim_Nvp_name2value_nocase_simple( _p, name );
+
+ if( puthere ){
+ *puthere = (Jim_Nvp *)(p);
+ }
+ /* found */
+ if( p->name ){
+ return JIM_OK;
+ } else {
+ return JIM_ERR;
+ }
+}
+
+
+int
+Jim_Nvp_value2name_obj( Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nvp **result )
+{
+ int e;;
+ jim_wide w;
+
+ e = Jim_GetWide( interp, o, &w );
+ if( e != JIM_OK ){
+ return e;
+ }
+
+ return Jim_Nvp_value2name( interp, p, w, result );
+}
+
+Jim_Nvp *
+Jim_Nvp_value2name_simple( const Jim_Nvp *p, int value )
+{
+ while( p->name ){
+ if( value == p->value ){
+ break;
+ }
+ p++;
+ }
+ return ((Jim_Nvp *)(p));
+}
+
+
+int
+Jim_Nvp_value2name( Jim_Interp *interp, const Jim_Nvp *_p, int value, Jim_Nvp **result )
+{
+ const Jim_Nvp *p;
+
+ p = Jim_Nvp_value2name_simple( _p, value );
+
+ if( result ){
+ *result = (Jim_Nvp *)(p);
+ }
+
+ if( p->name ){
+ return JIM_OK;
+ } else {
+ return JIM_ERR;
+ }
+}
+
+
+int
+Jim_GetOpt_Setup( Jim_GetOptInfo *p, Jim_Interp *interp, int argc, Jim_Obj * const * argv)
+{
+ memset( p, 0, sizeof(*p) );
+ p->interp = interp;
+ p->argc = argc;
+ p->argv = argv;
+
+ return JIM_OK;
+}
+
+void
+Jim_GetOpt_Debug( Jim_GetOptInfo *p )
+{
+ int x;
+
+ Jim_fprintf( p->interp, p->interp->cookie_stderr, "---args---\n");
+ for( x = 0 ; x < p->argc ; x++ ){
+ Jim_fprintf( p->interp, p->interp->cookie_stderr,
+ "%2d) %s\n",
+ x,
+ Jim_GetString( p->argv[x], NULL ) );
+ }
+ Jim_fprintf( p->interp, p->interp->cookie_stderr, "-------\n");
+}
+
+
+int
+Jim_GetOpt_Obj( Jim_GetOptInfo *goi, Jim_Obj **puthere )
+{
+ Jim_Obj *o;
+
+ o = NULL; // failure
+ if( goi->argc > 0 ){
+ // success
+ o = goi->argv[0];
+ goi->argc -= 1;
+ goi->argv += 1;
+ }
+ if( puthere ){
+ *puthere = o;
+ }
+ if( o != NULL ){
+ return JIM_OK;
+ } else {
+ return JIM_ERR;
+ }
+}
+
+int
+Jim_GetOpt_String( Jim_GetOptInfo *goi, char **puthere, int *len )
+{
+ int r;
+ Jim_Obj *o;
+ const char *cp;
+
+
+ r = Jim_GetOpt_Obj( goi, &o );
+ if( r == JIM_OK ){
+ cp = Jim_GetString( o, len );
+ if( puthere ){
+ /* remove const */
+ *puthere = (char *)(cp);
+ }
+ }
+ return r;
+}
+
+int
+Jim_GetOpt_Double( Jim_GetOptInfo *goi, double *puthere )
+{
+ int r;
+ Jim_Obj *o;
+ double _safe;
+
+ if( puthere == NULL ){
+ puthere = &_safe;
+ }
+
+ r = Jim_GetOpt_Obj( goi, &o );
+ if( r == JIM_OK ){
+ r = Jim_GetDouble( goi->interp, o, puthere );
+ if( r != JIM_OK ){
+ Jim_SetResult_sprintf( goi->interp,
+ "not a number: %s",
+ Jim_GetString( o, NULL ) );
+ }
+ }
+ return r;
+}
+
+int
+Jim_GetOpt_Wide( Jim_GetOptInfo *goi, jim_wide *puthere )
+{
+ int r;
+ Jim_Obj *o;
+ jim_wide _safe;
+
+ if( puthere == NULL ){
+ puthere = &_safe;
+ }
+
+ r = Jim_GetOpt_Obj( goi, &o );
+ if( r == JIM_OK ){
+ r = Jim_GetWide( goi->interp, o, puthere );
+ }
+ return r;
+}
+
+int Jim_GetOpt_Nvp( Jim_GetOptInfo *goi,
+ const Jim_Nvp *nvp,
+ Jim_Nvp **puthere)
+{
+ Jim_Nvp *_safe;
+ Jim_Obj *o;
+ int e;
+
+ if( puthere == NULL ){
+ puthere = &_safe;
+ }
+
+ e = Jim_GetOpt_Obj( goi, &o );
+ if( e == JIM_OK ){
+ e = Jim_Nvp_name2value_obj( goi->interp,
+ nvp,
+ o,
+ puthere );
+ }
+
+ return e;
+}
+
+void
+Jim_GetOpt_NvpUnknown( Jim_GetOptInfo *goi,
+ const Jim_Nvp *nvptable,
+ int hadprefix )
+{
+ if( hadprefix ){
+ Jim_SetResult_NvpUnknown( goi->interp,
+ goi->argv[-2],
+ goi->argv[-1],
+ nvptable );
+ } else {
+ Jim_SetResult_NvpUnknown( goi->interp,
+ NULL,
+ goi->argv[-1],
+ nvptable );
+ }
+}
+
+
+int
+Jim_GetOpt_Enum( Jim_GetOptInfo *goi,
+ const char * const * lookup,
+ int *puthere)
+{
+ int _safe;
+ Jim_Obj *o;
+ int e;
+
+ if( puthere == NULL ){
+ puthere = &_safe;
+ }
+ e = Jim_GetOpt_Obj( goi, &o );
+ if( e == JIM_OK ){
+ e = Jim_GetEnum( goi->interp,
+ o,
+ lookup,
+ puthere,
+ "option",
+ JIM_ERRMSG );
+ }
+ return e;
+}
+
+
+
+int
+Jim_SetResult_sprintf( Jim_Interp *interp, const char *fmt,... )
+{
+ va_list ap;
+ char *buf;
+
+ va_start(ap,fmt);
+ buf = jim_vasprintf( fmt, ap );
+ va_end(ap);
+ if( buf ){
+ Jim_SetResultString( interp, buf, -1 );
+ jim_vasprintf_done(buf);
+ }
+ return JIM_OK;
+}
+
+
+void
+Jim_SetResult_NvpUnknown( Jim_Interp *interp,
+ Jim_Obj *param_name,
+ Jim_Obj *param_value,
+ const Jim_Nvp *nvp )
+{
+ if( param_name ){
+ Jim_SetResult_sprintf( interp,
+ "%s: Unknown: %s, try one of: ",
+ Jim_GetString( param_name, NULL ),
+ Jim_GetString( param_value, NULL ) );
+ } else {
+ Jim_SetResult_sprintf( interp,
+ "Unknown param: %s, try one of: ",
+ Jim_GetString( param_value, NULL ) );
+ }
+ while( nvp->name ){
+ const char *a;
+ const char *b;
+
+ if( (nvp+1)->name ){
+ a = nvp->name;
+ b = ", ";
+ } else {
+ a = "or ";
+ b = nvp->name;
+ }
+ Jim_AppendStrings( interp,
+ Jim_GetResult(interp),
+ a, b, NULL );
+ nvp++;
+ }
+}
+
+
+static Jim_Obj *debug_string_obj;
+
+const char *
+Jim_Debug_ArgvString( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
+{
+ int x;
+
+ if( debug_string_obj ){
+ Jim_FreeObj( interp, debug_string_obj );
+ }
+
+ debug_string_obj = Jim_NewEmptyStringObj( interp );
+ for( x = 0 ; x < argc ; x++ ){
+ Jim_AppendStrings( interp,
+ debug_string_obj,
+ Jim_GetString( argv[x], NULL ),
+ " ",
+ NULL );
+ }
+
+ return Jim_GetString( debug_string_obj, NULL );
+}