aboutsummaryrefslogtreecommitdiff
path: root/jim.c
diff options
context:
space:
mode:
Diffstat (limited to 'jim.c')
-rw-r--r--jim.c222
1 files changed, 139 insertions, 83 deletions
diff --git a/jim.c b/jim.c
index fba53ac..ecf4c8b 100644
--- a/jim.c
+++ b/jim.c
@@ -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;