X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fhelper%2Fjim.c;h=9d49e8714c5602d5d8ec750826b6d9dee0b4b08e;hp=1a35b32b053422ff0091322b915e24496c09e3ea;hb=ce23eb7e3aebbf03e1f1cab436f417d034395439;hpb=ce16ff901c63c65d6087af4436159a6529de3b95 diff --git a/src/helper/jim.c b/src/helper/jim.c index 1a35b32b05..9d49e8714c 100644 --- a/src/helper/jim.c +++ b/src/helper/jim.c @@ -7,6 +7,7 @@ * Copyright 2008 Andrew Lunn * Copyright 2008 Duane Ellis * Copyright 2008 Uwe Klein + * Copyright 2008 Steve Bennett * * The FreeBSD license * @@ -38,6 +39,10 @@ * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the Jim Tcl Project. **/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define __JIM_CORE__ #define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */ @@ -48,6 +53,9 @@ #define JIM_DYNLIB /* Dynamic library support for UNIX and WIN32 */ #endif /* JIM_ANSIC */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* for vasprintf() */ +#endif #include #include #include @@ -57,6 +65,11 @@ #include #include #include +#if defined(WIN32) +/* sys/time - need is different */ +#else +#include // for gettimeofday() +#endif #include "replacements.h" @@ -80,6 +93,10 @@ #endif /* WIN32 */ #endif /* JIM_DYNLIB */ +#ifdef HAVE_UNISTD_H +#include +#endif + #ifdef __ECOS #include #else @@ -105,12 +122,41 @@ static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf); static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags); static void JimRegisterCoreApi(Jim_Interp *interp); -static Jim_HashTableType JimVariablesHashTableType; +static Jim_HashTableType *getJimVariablesHashTableType(void); /* ----------------------------------------------------------------------------- * 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; + int result; + result = vasprintf( &buf, fmt, ap ); + if (result < 0) exit(-1); +#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. @@ -118,7 +164,7 @@ static Jim_HashTableType JimVariablesHashTableType; * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. */ -#ifdef HAVE_LONG_LONG +#ifdef HAVE_LONG_LONG_INT #define JimIsAscii(c) (((c) & ~0x7f) == 0) static jim_wide JimStrtoll(const char *nptr, char **endptr, register int base) { @@ -382,7 +428,7 @@ int Jim_StringToWide(const char *str, jim_wide *widePtr, int base) { char *endptr; -#ifdef HAVE_LONG_LONG +#ifdef HAVE_LONG_LONG_INT *widePtr = JimStrtoll(str, &endptr, base); #else *widePtr = strtol(str, &endptr, base); @@ -1293,19 +1339,21 @@ int JimParseVar(struct JimParserCtx *pc) if (brace) { while (!stop) { if (*pc->p == '}' || pc->len == 0) { + pc->tend = pc->p-1; stop = 1; if (pc->len == 0) - continue; + break; } else if (*pc->p == '\n') pc->linenr++; pc->p++; pc->len--; } - if (pc->len == 0) - pc->tend = pc->p-1; - else - pc->tend = pc->p-2; } else { + /* Include leading colons */ + while (*pc->p == ':') { + pc->p++; + pc->len--; + } while (!stop) { if (!((*pc->p >= 'a' && *pc->p <= 'z') || (*pc->p >= 'A' && *pc->p <= 'Z') || @@ -2019,6 +2067,22 @@ void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, 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) { @@ -2149,8 +2213,13 @@ Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp, static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) { - char *buf = Jim_Alloc(strObjPtr->length+1); + char *buf; int i; + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + + buf = Jim_Alloc(strObjPtr->length+1); memcpy(buf, strObjPtr->bytes, strObjPtr->length+1); for (i = 0; i < strObjPtr->length; i++) @@ -2160,8 +2229,13 @@ static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr) { - char *buf = Jim_Alloc(strObjPtr->length+1); + char *buf; int i; + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + + buf = Jim_Alloc(strObjPtr->length+1); memcpy(buf, strObjPtr->bytes, strObjPtr->length+1); for (i = 0; i < strObjPtr->length; i++) @@ -2173,8 +2247,9 @@ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr) * 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; @@ -2190,8 +2265,6 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, 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; @@ -2242,32 +2315,32 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, /* non-terminals */ case '0': /* zero pad */ zpad = 1; - *fmt++; fmtLen--; + fmt++; fmtLen--; goto next_fmt; break; case '+': forceplus = 1; - *fmt++; fmtLen--; + fmt++; fmtLen--; goto next_fmt; break; case ' ': /* sign space */ spad = 1; - *fmt++; fmtLen--; + fmt++; fmtLen--; goto next_fmt; break; case '-': ljust = 1; - *fmt++; fmtLen--; + fmt++; fmtLen--; goto next_fmt; break; case '#': altfm = 1; - *fmt++; fmtLen--; + fmt++; fmtLen--; goto next_fmt; - + case '.': inprec = 1; - *fmt++; fmtLen--; + fmt++; fmtLen--; goto next_fmt; break; case '1': @@ -2293,7 +2366,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, goto next_fmt; case '*': /* suck up the next item as an integer */ - *fmt++; fmtLen--; + fmt++; fmtLen--; objc--; if( objc <= 0 ){ goto not_enough_args; @@ -2311,11 +2384,11 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, prec = 0; } } else { - width = wideValue; - if( width < 0 ){ - ljust = 1; - width = -width; - } + width = wideValue; + if( width < 0 ){ + ljust = 1; + width = -width; + } } objv++; goto next_fmt; @@ -2408,6 +2481,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, break; case 'b': case 'd': + case 'o': case 'i': case 'u': case 'x': @@ -2456,6 +2530,15 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, 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 * ---------------------------------------------------------------------------*/ @@ -2510,9 +2593,9 @@ int qsortCompareStringPointers(const void *a, const void *b) } 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; @@ -2547,6 +2630,29 @@ int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, 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 * @@ -2930,7 +3036,7 @@ int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) initialLineNumber = objPtr->internalRep.sourceValue.lineNumber; propagateSourceInfo = 1; } else { - script->fileName = Jim_StrDup("?"); + script->fileName = Jim_StrDup(""); initialLineNumber = 1; } @@ -3082,9 +3188,6 @@ int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName, he = Jim_FindHashEntry(&interp->commands, cmdName); if (he == NULL) { /* New command to create */ cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); - cmdPtr->cmdProc = cmdProc; - cmdPtr->privData = privData; - cmdPtr->delProc = delProc; Jim_AddHashEntry(&interp->commands, cmdName, cmdPtr); } else { Jim_InterpIncrProcEpoch(interp); @@ -3102,9 +3205,13 @@ int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName, /* If it was a C coded command, call the delProc if any */ cmdPtr->delProc(interp, cmdPtr->privData); } - cmdPtr->cmdProc = cmdProc; - cmdPtr->privData = privData; } + + /* Store the new details for this proc */ + cmdPtr->delProc = delProc; + cmdPtr->cmdProc = cmdProc; + cmdPtr->privData = privData; + /* There is no need to increment the 'proc epoch' because * creation of a new procedure can never affect existing * cached commands. We don't do negative caching. */ @@ -3134,7 +3241,7 @@ int Jim_CreateProcedure(Jim_Interp *interp, const char *cmdName, Jim_ListLength(interp, staticsListObjPtr, &len); if (len != 0) { cmdPtr->staticVars = Jim_Alloc(sizeof(Jim_HashTable)); - Jim_InitHashTable(cmdPtr->staticVars, &JimVariablesHashTableType, + Jim_InitHashTable(cmdPtr->staticVars, getJimVariablesHashTableType(), interp); for (i = 0; i < len; i++) { Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; @@ -3337,6 +3444,11 @@ static Jim_HashTableType JimVariablesHashTableType = { JimVariablesHTValDestructor /* val destructor */ }; +static Jim_HashTableType *getJimVariablesHashTableType(void) +{ + return &JimVariablesHashTableType; +} + /* ----------------------------------------------------------------------------- * Variable object * ---------------------------------------------------------------------------*/ @@ -3384,14 +3496,22 @@ int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) /* Make sure it's not syntax glue to get/set dict. */ if (Jim_NameIsDictSugar(varName, len)) return JIM_DICT_SUGAR; - /* Lookup this name into the variables hash table */ - he = Jim_FindHashEntry(&interp->framePtr->vars, varName); - if (he == NULL) { - /* Try with static vars. */ - if (interp->framePtr->staticVars == NULL) - return JIM_ERR; - if (!(he = Jim_FindHashEntry(interp->framePtr->staticVars, varName))) + if (varName[0] == ':' && varName[1] == ':') { + he = Jim_FindHashEntry(&interp->topFramePtr->vars, varName + 2); + if (he == NULL) { return JIM_ERR; + } + } + else { + /* Lookup this name into the variables hash table */ + he = Jim_FindHashEntry(&interp->framePtr->vars, varName); + if (he == NULL) { + /* Try with static vars. */ + if (interp->framePtr->staticVars == NULL) + return JIM_ERR; + if (!(he = Jim_FindHashEntry(interp->framePtr->staticVars, varName))) + return JIM_ERR; + } } /* Free the old internal repr and set the new one. */ Jim_FreeIntRep(interp, objPtr); @@ -3430,7 +3550,13 @@ int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) Jim_IncrRefCount(valObjPtr); var->linkFramePtr = NULL; /* Insert the new variable */ - Jim_AddHashEntry(&interp->framePtr->vars, name, var); + if (name[0] == ':' && name[1] == ':') { + /* Into to the top evel frame */ + Jim_AddHashEntry(&interp->topFramePtr->vars, name + 2, var); + } + else { + Jim_AddHashEntry(&interp->framePtr->vars, name, var); + } /* Make the object int rep a variable */ Jim_FreeIntRep(interp, nameObjPtr); nameObjPtr->typePtr = &variableObjType; @@ -4331,6 +4457,7 @@ Jim_Interp *Jim_CreateInterp(void) i->result = i->emptyObj; i->stackTrace = Jim_NewListObj(i, NULL, 0); i->unknown = Jim_NewStringObj(i, "unknown", -1); + i->unknown_called = 0; Jim_IncrRefCount(i->emptyObj); Jim_IncrRefCount(i->result); Jim_IncrRefCount(i->stackTrace); @@ -4545,6 +4672,11 @@ static void JimResetStackTrace(Jim_Interp *interp) static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, const char *filename, int linenr) { + /* No need to add this dummy entry to the stack trace */ + if (strcmp(procname, "unknown") == 0) { + return; + } + if (Jim_IsShared(interp->stackTrace)) { interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); @@ -6513,7 +6645,7 @@ static void ExprMakeLazy(Jim_Interp *interp, ExprByteCode *expr) case JIM_EXPROP_STRING: break; default: - op = JimExprOperatorInfoByOpcode(expr->opcode[i]); + op = JimExprOperatorInfoByOpcode(expr->opcode[leftindex]); if (op == NULL) { Jim_Panic(interp,"Default reached in ExprMakeLazy()"); } @@ -6903,6 +7035,16 @@ trydouble: /* --- Double --- */ if (Jim_GetDouble(interp, A, &dA) != JIM_OK || Jim_GetDouble(interp, B, &dB) != JIM_OK) { + + /* Hmmm! For compatibility, maybe convert != and == into ne and eq */ + if (expr->opcode[i] == JIM_EXPROP_NUMNE) { + opcode = JIM_EXPROP_STRNE; + goto retry_as_string; + } + else if (expr->opcode[i] == JIM_EXPROP_NUMEQ) { + opcode = JIM_EXPROP_STREQ; + goto retry_as_string; + } Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); error = 1; @@ -6964,9 +7106,10 @@ trydouble: } else if (opcode == JIM_EXPROP_STREQ || opcode == JIM_EXPROP_STRNE) { B = stack[--stacklen]; A = stack[--stacklen]; +retry_as_string: sA = Jim_GetString(A, &Alen); sB = Jim_GetString(B, &Blen); - switch(expr->opcode[i]) { + switch(opcode) { case JIM_EXPROP_STREQ: if (Alen == Blen && memcmp(sA, sB, Alen) ==0) wC = 1; @@ -7511,6 +7654,8 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos, scanned += 1; break; case 'd': case 'o': case 'x': case 'u': case 'i': { + jim_wide jwvalue; + long lvalue; char *endp; /* Position where the number finished */ int base = descr->type == 'o' ? 8 : descr->type == 'x' ? 16 @@ -7520,16 +7665,22 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos, do { /* Try to scan a number with the given base */ if (descr->modifier == 'l') -#ifdef HAVE_LONG_LONG - *(jim_wide*)value = JimStrtoll(tok, &endp, base); + { +#ifdef HAVE_LONG_LONG_INT + jwvalue = JimStrtoll(tok, &endp, base), #else - *(jim_wide*)value = strtol(tok, &endp, base); + jwvalue = strtol(tok, &endp, base), #endif + memcpy(value, &jwvalue, sizeof(jim_wide)); + } else + { if (descr->type == 'u') - *(long*)value = strtoul(tok, &endp, base); + lvalue = strtoul(tok, &endp, base); else - *(long*)value = strtol(tok, &endp, base); + lvalue = strtol(tok, &endp, base); + memcpy(value, &lvalue, sizeof(lvalue)); + } /* If scanning failed, and base was undetermined, simply * put it to 10 and try once more. This should catch the * case where %i begin to parse a number prefix (e.g. @@ -7541,9 +7692,9 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos, if (endp != tok) { /* There was some number sucessfully scanned! */ if (descr->modifier == 'l') - *valObjPtr = Jim_NewIntObj(interp, *(jim_wide*)value); + *valObjPtr = Jim_NewIntObj(interp, jwvalue); else - *valObjPtr = Jim_NewIntObj(interp, *(long*)value); + *valObjPtr = Jim_NewIntObj(interp, lvalue); /* Adjust the number-of-chars scanned so far */ scanned += endp - tok; } else { @@ -7562,10 +7713,11 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos, case 'e': case 'f': case 'g': { char *endp; - *(double*)value = strtod(tok, &endp); + double dvalue = strtod(tok, &endp); + memcpy(value, &dvalue, sizeof(double)); if (endp != tok) { /* There was some number sucessfully scanned! */ - *valObjPtr = Jim_NewDoubleObj(interp, *(double*)value); + *valObjPtr = Jim_NewDoubleObj(interp, dvalue); /* Adjust the number-of-chars scanned so far */ scanned += endp - tok; } else { @@ -7798,21 +7950,21 @@ int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) if (Jim_ListIndex(interp, libPathObjPtr, i, &prefixObjPtr, JIM_NONE) != JIM_OK) continue; - prefix = Jim_GetString(prefixObjPtr, NULL); - prefixlen = strlen(prefix); + prefix = Jim_GetString(prefixObjPtr, &prefixlen); if (prefixlen+strlen(pathName)+1 >= JIM_PATH_LEN) continue; - if (prefixlen && prefix[prefixlen-1] == '/') + if (*pathName == '/') { + strcpy(buf, pathName); + } + else if (prefixlen && prefix[prefixlen-1] == '/') sprintf(buf, "%s%s", prefix, pathName); else sprintf(buf, "%s/%s", prefix, pathName); - printf("opening '%s'\n", buf); fp = fopen(buf, "r"); if (fp == NULL) continue; fclose(fp); handle = dlopen(buf, RTLD_LAZY); - printf("got handle %p\n", handle); } if (handle == NULL) { Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); @@ -8156,6 +8308,9 @@ const char *Jim_PackageRequire(Jim_Interp *interp, const char *name, Jim_HashEntry *he; int requiredVer; + /* Start with an empty error string */ + Jim_SetResultString(interp, "", 0); + if (JimPackageVersionToInt(interp, ver, &requiredVer, JIM_ERRMSG) != JIM_OK) return NULL; he = Jim_FindHashEntry(&interp->packages, name); @@ -8170,8 +8325,9 @@ const char *Jim_PackageRequire(Jim_Interp *interp, const char *name, } /* No way... return an error. */ if (flags & JIM_ERRMSG) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), + int len; + Jim_GetString(Jim_GetResult(interp), &len); + Jim_AppendStrings(interp, Jim_GetResult(interp), len ? "\n" : "", "Can't find package '", name, "'", NULL); } return NULL; @@ -8184,7 +8340,6 @@ const char *Jim_PackageRequire(Jim_Interp *interp, const char *name, } /* Check if version matches. */ if (JimPackageMatchVersion(requiredVer, actualVer, flags) == 0) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "Package '", name, "' already loaded, but with version ", he->val, NULL); @@ -8209,6 +8364,13 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_Obj **v, *sv[JIM_EVAL_SARGV_LEN]; int retCode; + /* If JimUnknown() is recursively called (e.g. error in the unknown proc, + * done here + */ + if (interp->unknown_called) { + return JIM_ERR; + } + /* If the [unknown] command does not exists returns * just now */ if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL) @@ -8229,7 +8391,10 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) memcpy(v+1, argv, sizeof(Jim_Obj*)*argc); v[0] = interp->unknown; /* Call it */ + interp->unknown_called++; retCode = Jim_EvalObjVector(interp, argc+1, v); + interp->unknown_called--; + /* Clean up */ if (v != sv) Jim_Free(v); @@ -8263,12 +8428,16 @@ int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) if (cmdPtr->cmdProc) { interp->cmdPrivData = cmdPtr->privData; retcode = cmdPtr->cmdProc(interp, objc, objv); + if (retcode == JIM_ERR_ADDSTACK) { + //JimAppendStackTrace(interp, "", script->fileName, token[i-argc*2].linenr); + retcode = JIM_ERR; + } } else { retcode = JimCallProcedure(interp, cmdPtr, objc, objv); - if (retcode == JIM_ERR) { - JimAppendStackTrace(interp, - Jim_GetString(objv[0], NULL), "?", 1); - } + if (retcode == JIM_ERR) { + JimAppendStackTrace(interp, + Jim_GetString(objv[0], NULL), "", 1); + } } } /* Decr refcount of arguments and return the retcode */ @@ -8549,6 +8718,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) if (cmd->cmdProc) { interp->cmdPrivData = cmd->privData; retcode = cmd->cmdProc(interp, argc, argv); + if ((retcode == JIM_ERR)||(retcode == JIM_ERR_ADDSTACK)) { + JimAppendStackTrace(interp, "", script->fileName, token[i-argc*2].linenr); + retcode = JIM_ERR; + } } else { retcode = JimCallProcedure(interp, cmd, argc, argv); if (retcode == JIM_ERR) { @@ -8562,7 +8735,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) retcode = JimUnknown(interp, argc, argv); if (retcode == JIM_ERR) { JimAppendStackTrace(interp, - Jim_GetString(argv[0], NULL), script->fileName, + "", script->fileName, token[i-argc*2].linenr); } } @@ -8618,6 +8791,7 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, { int i, retcode; Jim_CallFrame *callFramePtr; + int num_args; /* Check arity */ if (argc < cmd->arityMin || (cmd->arityMax != -1 && @@ -8648,19 +8822,47 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_IncrRefCount(cmd->bodyObjPtr); interp->framePtr = callFramePtr; interp->numLevels ++; + /* Set arguments */ - for (i = 0; i < cmd->arityMin-1; i++) { - Jim_Obj *objPtr; + Jim_ListLength(interp, cmd->argListObjPtr, &num_args); - Jim_ListIndex(interp, cmd->argListObjPtr, i, &objPtr, JIM_NONE); - Jim_SetVariable(interp, objPtr, argv[i+1]); + /* If last argument is 'args', don't set it here */ + if (cmd->arityMax == -1) { + num_args--; + } + + for (i = 0; i < num_args; i++) { + Jim_Obj *argObjPtr; + Jim_Obj *nameObjPtr; + Jim_Obj *valueObjPtr; + + Jim_ListIndex(interp, cmd->argListObjPtr, i, &argObjPtr, JIM_NONE); + if (i + 1 >= cmd->arityMin) { + /* The name is the first element of the list */ + Jim_ListIndex(interp, argObjPtr, 0, &nameObjPtr, JIM_NONE); + } + else { + /* The element arg is the name */ + nameObjPtr = argObjPtr; + } + + if (i + 1 >= argc) { + /* No more values, so use default */ + /* The value is the second element of the list */ + Jim_ListIndex(interp, argObjPtr, 1, &valueObjPtr, JIM_NONE); + } + else { + valueObjPtr = argv[i+1]; + } + Jim_SetVariable(interp, nameObjPtr, valueObjPtr); } + /* Set optional arguments */ if (cmd->arityMax == -1) { Jim_Obj *listObjPtr, *objPtr; - listObjPtr = Jim_NewListObj(interp, argv+cmd->arityMin, - argc-cmd->arityMin); - Jim_ListIndex(interp, cmd->argListObjPtr, i, &objPtr, JIM_NONE); + i++; + listObjPtr = Jim_NewListObj(interp, argv+i, argc-i); + Jim_ListIndex(interp, cmd->argListObjPtr, num_args, &objPtr, JIM_NONE); Jim_SetVariable(interp, objPtr, listObjPtr); } /* Eval the body */ @@ -8695,17 +8897,31 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, 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) { @@ -8754,15 +8970,17 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename) 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) ); + if (!getcwd( cwd, cwd_len )) strcpy(cwd, "unknown"); Jim_AppendStrings(interp, Jim_GetResult(interp), "Error loading script \"", filename, "\"", " cwd: ", cwd, " err: ", strerror(errno), NULL); + free(cwd); return JIM_ERR; } buflen = 1024; @@ -9043,6 +9261,7 @@ void JimRegisterCoreApi(Jim_Interp *interp) 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); @@ -9069,6 +9288,7 @@ void JimRegisterCoreApi(Jim_Interp *interp) 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); @@ -9151,6 +9371,37 @@ void JimRegisterCoreApi(Jim_Interp *interp) 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); + } /* ----------------------------------------------------------------------------- @@ -10767,17 +11018,31 @@ static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, } Jim_ListLength(interp, argv[2], &argListLen); arityMin = arityMax = argListLen+1; + if (argListLen) { const char *str; int len; - Jim_Obj *lastArgPtr; + Jim_Obj *argPtr; - Jim_ListIndex(interp, argv[2], argListLen-1, &lastArgPtr, JIM_NONE); - str = Jim_GetString(lastArgPtr, &len); + /* Check for 'args' and adjust arityMin and arityMax if necessary */ + Jim_ListIndex(interp, argv[2], argListLen-1, &argPtr, JIM_NONE); + str = Jim_GetString(argPtr, &len); if (len == 4 && memcmp(str, "args", 4) == 0) { arityMin--; arityMax = -1; } + + /* Check for default arguments and reduce arityMin if necessary */ + while (arityMin > 1) { + int len; + Jim_ListIndex(interp, argv[2], arityMin - 2, &argPtr, JIM_NONE); + Jim_ListLength(interp, argPtr, &len); + if (len != 2) { + /* No default argument */ + break; + } + arityMin--; + } } if (argc == 4) { return Jim_CreateProcedure(interp, Jim_GetString(argv[1], NULL), @@ -11409,10 +11674,10 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, int cmd, result = JIM_OK; static const char *commands[] = { "body", "commands", "exists", "globals", "level", "locals", - "vars", "version", "complete", "args", NULL + "vars", "version", "complete", "args", "hostname", NULL }; enum {INFO_BODY, INFO_COMMANDS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, - INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_COMPLETE, INFO_ARGS}; + INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_COMPLETE, INFO_ARGS, INFO_HOSTNAME}; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "command ?args ...?"); @@ -11508,6 +11773,10 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, s = Jim_GetString(argv[2], &len); Jim_SetResult(interp, Jim_NewIntObj(interp, Jim_ScriptIsComplete(s, len, NULL))); + } else if (cmd == INFO_HOSTNAME) { + /* Redirect to os.hostname if it exists */ + Jim_Obj *command = Jim_NewStringObj(interp, "os.gethostname", -1); + result = Jim_EvalObjVector(interp, 1, &command); } return result; } @@ -11726,6 +11995,27 @@ static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, const char *key; char *val; + if (argc == 1) { + +#ifdef NEED_ENVIRON_EXTERN + extern char **environ; +#endif + + int i; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; environ[i]; i++) { + const char *equals = strchr(environ[i], '='); + if (equals) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, environ[i], equals - environ[i])); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, equals + 1, -1)); + } + } + + Jim_SetResult(interp, listObjPtr); + return JIM_OK; + } + if (argc != 2) { Jim_WrongNumArgs(interp, 1, argv, "varName"); return JIM_ERR; @@ -11754,6 +12044,9 @@ static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, return JIM_ERR; } retval = Jim_EvalFile(interp, Jim_GetString(argv[1], NULL)); + if (retval == JIM_ERR) { + return JIM_ERR_ADDSTACK; + } if (retval == JIM_RETURN) return JIM_OK; return retval; @@ -11903,7 +12196,7 @@ static int Jim_PackageCoreCommand(Jim_Interp *interp, int argc, argc == 4 ? Jim_GetString(argv[3], NULL) : "", JIM_ERRMSG); if (ver == NULL) - return JIM_ERR; + return JIM_ERR_ADDSTACK; Jim_SetResultString(interp, ver, -1); } else if (option == OPT_PROVIDE) { if (argc != 4) { @@ -12019,9 +12312,11 @@ void Jim_PrintErrorMessage(Jim_Interp *interp) { int len, i; - 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, + if (*interp->errorFileName) { + 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 = len-3; i >= 0; i-= 3) { @@ -12036,9 +12331,18 @@ void Jim_PrintErrorMessage(Jim_Interp *interp) Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr, JIM_NONE); line = Jim_GetString(objPtr, NULL); - Jim_fprintf( interp, interp->cookie_stderr, - "In procedure '%s' called at file \"%s\", line %s" JIM_NL, - proc, file, line); + if (*proc) { + Jim_fprintf( interp, interp->cookie_stderr, + "in procedure '%s' ", proc); + } + if (*file) { + Jim_fprintf( interp, interp->cookie_stderr, + "called at file \"%s\", line %s", + file, line); + } + if (*file || *proc) { + Jim_fprintf( interp, interp->cookie_stderr, JIM_NL); + } } } @@ -12162,3 +12466,391 @@ char* Jim_fgets( Jim_Interp *interp, char *s, int size, void *cookie ) } 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 ){ + // 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 ); +} + + + +/* + * Local Variables: *** + * c-basic-offset: 4 *** + * tab-width: 4 *** + * End: *** + */