diff options
Diffstat (limited to 'jim.c')
-rw-r--r-- | jim.c | 222 |
1 files changed, 139 insertions, 83 deletions
@@ -2613,7 +2613,7 @@ int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) const char *sA = Jim_GetString(aObjPtr, &Alen); const char *sB = Jim_GetString(bObjPtr, &Blen); - return Alen == Blen && memcmp(sA, sB, Alen) == 0; + return Alen == Blen && *sA == *sB && memcmp(sA, sB, Alen) == 0; } } @@ -3199,17 +3199,6 @@ void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj); } -static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, - Jim_Obj *fileNameObj, int lineNumber) -{ - JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); - JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object")); - Jim_IncrRefCount(fileNameObj); - objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; - objPtr->internalRep.sourceValue.lineNumber = lineNumber; - objPtr->typePtr = &sourceObjType; -} - /* ----------------------------------------------------------------------------- * ScriptLine Object * @@ -3611,7 +3600,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, /* Every object is initially a string of type 'source', but the * internal type may be specialized during execution of the * script. */ - JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line); + Jim_SetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line); token++; } } @@ -3694,6 +3683,39 @@ static int JimParseCheckMissing(Jim_Interp *interp, int ch) return JIM_ERR; } +Jim_Obj *Jim_GetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, int *lineptr) +{ + int line; + Jim_Obj *fileNameObj; + + if (objPtr->typePtr == &sourceObjType) { + fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + line = objPtr->internalRep.sourceValue.lineNumber; + } + else if (objPtr->typePtr == &scriptObjType) { + ScriptObj *script = JimGetScript(interp, objPtr); + fileNameObj = script->fileNameObj; + line = script->firstline; + } + else { + fileNameObj = interp->emptyObj; + line = 1; + } + *lineptr = line; + return fileNameObj; +} + +void Jim_SetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *fileNameObj, int lineNumber) +{ + JimPanic((Jim_IsShared(objPtr), "Jim_SetSourceInfo called with shared object")); + Jim_FreeIntRep(interp, objPtr); + Jim_IncrRefCount(fileNameObj); + objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; + objPtr->internalRep.sourceValue.lineNumber = lineNumber; + objPtr->typePtr = &sourceObjType; +} + /** * Similar to ScriptObjAddTokens(), but for subst objects. */ @@ -3732,12 +3754,11 @@ static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) struct JimParserCtx parser; struct ScriptObj *script; ParseTokenList tokenlist; - int line = 1; + Jim_Obj *fileNameObj; + int line; /* Try to get information about filename / line number */ - if (objPtr->typePtr == &sourceObjType) { - line = objPtr->internalRep.sourceValue.lineNumber; - } + fileNameObj = Jim_GetSourceInfo(interp, objPtr, &line); /* Initially parse the script into tokens (in tokenlist) */ ScriptTokenListInit(&tokenlist); @@ -3756,12 +3777,7 @@ static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) script = Jim_Alloc(sizeof(*script)); memset(script, 0, sizeof(*script)); script->inUse = 1; - if (objPtr->typePtr == &sourceObjType) { - script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; - } - else { - script->fileNameObj = interp->emptyObj; - } + script->fileNameObj = fileNameObj; Jim_IncrRefCount(script->fileNameObj); script->missing = parser.missing.ch; script->linenr = parser.missing.line; @@ -3981,7 +3997,7 @@ static int JimCommandsHT_KeyCompare(void *privdata, const void *key1, const void int len1, len2; const char *str1 = Jim_GetStringNoQualifier((Jim_Obj *)key1, &len1); const char *str2 = Jim_GetStringNoQualifier((Jim_Obj *)key2, &len2); - return len1 == len2 && memcmp(str1, str2, len1) == 0; + return len1 == len2 && *str1 == *str2 && memcmp(str1, str2, len1) == 0; } static void JimCommandsHT_ValDestructor(void *interp, void *val) @@ -5809,6 +5825,9 @@ void Jim_FreeInterp(Jim_Interp *i) JimFreeCallFrame(i, cf, JIM_FCF_FULL); } + /* Must be done before freeing singletons */ + Jim_FreeHashTable(&i->commands); + Jim_DecrRefCount(i, i->emptyObj); Jim_DecrRefCount(i, i->trueObj); Jim_DecrRefCount(i, i->falseObj); @@ -5820,8 +5839,6 @@ void Jim_FreeInterp(Jim_Interp *i) Jim_DecrRefCount(i, i->nullScriptObj); Jim_DecrRefCount(i, i->currentFilenameObj); - Jim_FreeHashTable(&i->commands); - /* This will disard any cached commands */ Jim_InterpIncrProcEpoch(i); @@ -6812,14 +6829,7 @@ static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) } /* Try to preserve information about filename / line number */ - if (objPtr->typePtr == &sourceObjType) { - fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; - linenr = objPtr->internalRep.sourceValue.lineNumber; - } - else { - fileNameObj = interp->emptyObj; - linenr = 1; - } + fileNameObj = Jim_GetSourceInfo(interp, objPtr, &linenr); Jim_IncrRefCount(fileNameObj); /* Get the string representation */ @@ -6843,7 +6853,7 @@ static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC) continue; elementPtr = JimParserGetTokenObj(interp, &parser); - JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline); + Jim_SetSourceInfo(interp, elementPtr, fileNameObj, parser.tline); ListAppendElement(objPtr, elementPtr); } } @@ -6904,7 +6914,8 @@ struct lsort_info { JIM_LSORT_NOCASE, JIM_LSORT_INTEGER, JIM_LSORT_REAL, - JIM_LSORT_COMMAND + JIM_LSORT_COMMAND, + JIM_LSORT_DICT } type; int order; Jim_Obj **indexv; @@ -6937,6 +6948,45 @@ static int ListSortStringNoCase(Jim_Obj **lhsObj, Jim_Obj **rhsObj) return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 1) * sort_info->order; } +static int ListSortDict(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + /* XXX Does not compare past embedded nulls */ + const char *left = Jim_String(*lhsObj); + const char *right = Jim_String(*rhsObj); + + while (1) { + if (isdigit(UCHAR(*left)) && isdigit(UCHAR(*right))) { + /* extract and compare integers */ + jim_wide lint, rint; + char *lend, *rend; + lint = jim_strtoull(left, &lend); + rint = jim_strtoull(right, &rend); + if (lint != rint) { + return JimSign(lint - rint) * sort_info->order; + } + /* If the integers are equal but of unequal length, then one must have more leading + * zeros. The shorter one compares less */ + if (lend -left != rend - right) { + return JimSign((lend - left) - (rend - right)) * sort_info->order; + } + left = lend; + right = rend; + } + else { + int cl, cr; + left += utf8_tounicode_case(left, &cl, 1); + right += utf8_tounicode_case(right, &cr, 1); + if (cl != cr) { + return JimSign(cl - cr) * sort_info->order; + } + if (cl == 0) { + /* If they compare equal, use a case sensitive comparison as a tie breaker */ + return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 0) * sort_info->order; + } + } + } +} + static int ListSortInteger(Jim_Obj **lhsObj, Jim_Obj **rhsObj) { jim_wide lhs = 0, rhs = 0; @@ -7056,6 +7106,9 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor case JIM_LSORT_COMMAND: fn = ListSortCommand; break; + case JIM_LSORT_DICT: + fn = ListSortDict; + break; default: fn = NULL; /* avoid warning */ JimPanic((1, "ListSort called with invalid sort type")); @@ -8399,6 +8452,13 @@ static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node) case JIM_EXPROP_NOT: wC = !bA; break; + case JIM_EXPROP_UNARYPLUS: + case JIM_EXPROP_UNARYMINUS: + rc = JIM_ERR; + Jim_SetResultFormatted(interp, + "can't use non-numeric string as operand of \"%s\"", + node->type == JIM_EXPROP_UNARYPLUS ? "+" : "-"); + break; default: abort(); } @@ -9642,7 +9702,7 @@ missingoperand: objPtr = Jim_NewStringObj(interp, t->token, t->len); if (t->type == JIM_TT_CMD) { /* Only commands need source info */ - JimSetSourceInfo(interp, objPtr, builder->fileNameObj, t->line); + Jim_SetSourceInfo(interp, objPtr, builder->fileNameObj, t->line); } } @@ -9742,14 +9802,7 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) int rc = JIM_ERR; /* Try to get information about filename / line number */ - if (objPtr->typePtr == &sourceObjType) { - fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; - line = objPtr->internalRep.sourceValue.lineNumber; - } - else { - fileNameObj = interp->emptyObj; - line = 1; - } + fileNameObj = Jim_GetSourceInfo(interp, objPtr, &line); Jim_IncrRefCount(fileNameObj); exprText = Jim_GetString(objPtr, &exprTextLen); @@ -11108,7 +11161,9 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok } else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) { /* The first interpolated token is source, so preserve the source info */ - JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber); + int line; + Jim_Obj *fileNameObj = Jim_GetSourceInfo(interp, intv[0], &line); + Jim_SetSourceInfo(interp, objPtr, fileNameObj, line); } @@ -11629,7 +11684,7 @@ int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const c scriptObjPtr = Jim_NewStringObj(interp, script, -1); Jim_IncrRefCount(scriptObjPtr); if (filename) { - JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno); + Jim_SetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno); } retval = Jim_EvalObj(interp, scriptObjPtr); Jim_DecrRefCount(interp, scriptObjPtr); @@ -11716,7 +11771,7 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename) } filenameObj = Jim_NewStringObj(interp, filename, -1); - JimSetSourceInfo(interp, scriptObjPtr, filenameObj, 1); + Jim_SetSourceInfo(interp, scriptObjPtr, filenameObj, 1); oldFilenameObj = JimPushInterpObj(interp->currentFilenameObj, filenameObj); @@ -12555,7 +12610,7 @@ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg { int retval; jim_wide i; - jim_wide limit; + jim_wide limit = 0; jim_wide incr = 1; Jim_Obj *bodyObjPtr; @@ -13413,11 +13468,11 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg { static const char * const options[] = { "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", - "-stride", NULL + "-stride", "-dictionary", NULL }; enum { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE, - OPT_STRIDE + OPT_STRIDE, OPT_DICT }; Jim_Obj *resObj; int i; @@ -13452,6 +13507,9 @@ wrongargs: case OPT_ASCII: info.type = JIM_LSORT_ASCII; break; + case OPT_DICT: + info.type = JIM_LSORT_DICT; + break; case OPT_NOCASE: info.type = JIM_LSORT_NOCASE; break; @@ -13646,7 +13704,7 @@ static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar JIM_DEF_SUBCMD("refcount", "object", 1, 1), JIM_DEF_SUBCMD("scriptlen", "script", 1, 1), JIM_DEF_SUBCMD("show", "object", 1, 1), - { /* null terminator */ } + { NULL } }; const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv); @@ -14409,7 +14467,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a JIM_DEF_SUBCMD("trim", "string ?trimchars?", 1, 2), JIM_DEF_SUBCMD("trimleft", "string ?trimchars?", 1, 2), JIM_DEF_SUBCMD("trimright", "string ?trimchars?", 1, 2), - { /* null terminator */ } + { NULL } }; const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv); if (!ct) { @@ -14965,16 +15023,22 @@ wrongargs: } else if (errorCodeObj) { int len = Jim_ListLength(interp, argv[idx + 1]); - int i; - - ret = JIM_OK; - /* Try to match the sublist against errorcode */ - for (i = 0; i < len; i++) { - Jim_Obj *matchObj = Jim_ListGetIndex(interp, argv[idx + 1], i); - Jim_Obj *objPtr = Jim_ListGetIndex(interp, errorCodeObj, i); - if (Jim_StringCompareObj(interp, matchObj, objPtr, 0) != 0) { - ret = -1; - break; + + if (len > Jim_ListLength(interp, errorCodeObj)) { + /* More elements in the sublist than in the errorCode so we can't match */ + ret = -1; + } + else { + int i; + ret = JIM_OK; + /* Try to match the sublist against errorcode */ + for (i = 0; i < len; i++) { + Jim_Obj *matchObj = Jim_ListGetIndex(interp, argv[idx + 1], i); + Jim_Obj *objPtr = Jim_ListGetIndex(interp, errorCodeObj, i); + if (Jim_StringCompareObj(interp, matchObj, objPtr, 0) != 0) { + ret = -1; + break; + } } } } @@ -15441,7 +15505,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg JIM_DEF_SUBCMD("for", "vars dictionary script", 3, 3), JIM_DEF_SUBCMD("replace", "dictionary ?key value ...?", 1, -1), JIM_DEF_SUBCMD("update", "varName ?arg ...? script", 2, -1), - { /* null terminator */ } + { NULL } }; const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv); if (!ct) { @@ -15479,7 +15543,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg } case OPT_SET: - return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); + return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG | JIM_UNSHARED); case OPT_EXISTS:{ int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_NONE); @@ -15491,7 +15555,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg } case OPT_UNSET: - if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE) != JIM_OK) { + if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_UNSHARED) != JIM_OK) { return JIM_ERR; } return JIM_OK; @@ -15650,7 +15714,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg JIM_DEF_SUBCMD("statics", "procname", 1, 1), JIM_DEF_SUBCMD("vars", "?pattern?", 0, 1), JIM_DEF_SUBCMD("version", NULL, 0, 0), - { /* null terminator */ } + { NULL } }; const jim_subcmd_type *ct; #ifdef jim_ext_namespace @@ -15743,7 +15807,6 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg return JIM_OK; case INFO_SOURCE:{ - jim_wide line; Jim_Obj *resObjPtr; Jim_Obj *fileNameObj; @@ -15752,26 +15815,16 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg return JIM_ERR; } if (argc == 5) { + jim_wide line; if (Jim_GetWide(interp, argv[4], &line) != JIM_OK) { return JIM_ERR; } resObjPtr = Jim_NewStringObj(interp, Jim_String(argv[2]), Jim_Length(argv[2])); - JimSetSourceInfo(interp, resObjPtr, argv[3], line); + Jim_SetSourceInfo(interp, resObjPtr, argv[3], line); } else { - if (argv[2]->typePtr == &sourceObjType) { - fileNameObj = argv[2]->internalRep.sourceValue.fileNameObj; - line = argv[2]->internalRep.sourceValue.lineNumber; - } - else if (argv[2]->typePtr == &scriptObjType) { - ScriptObj *script = JimGetScript(interp, argv[2]); - fileNameObj = script->fileNameObj; - line = script->firstline; - } - else { - fileNameObj = interp->emptyObj; - line = 1; - } + int line; + fileNameObj = Jim_GetSourceInfo(interp, argv[2], &line); resObjPtr = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, resObjPtr, fileNameObj); Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line)); @@ -16233,11 +16286,12 @@ char **Jim_GetEnviron(void) { #if defined(HAVE__NSGETENVIRON) return *_NSGetEnviron(); +#elif defined(_environ) + return _environ; #else #if !defined(NO_ENVIRON_EXTERN) extern char **environ; #endif - return environ; #endif } @@ -16246,6 +16300,8 @@ void Jim_SetEnviron(char **env) { #if defined(HAVE__NSGETENVIRON) *_NSGetEnviron() = env; +#elif defined(_environ) + _environ = env; #else #if !defined(NO_ENVIRON_EXTERN) extern char **environ; |