aboutsummaryrefslogtreecommitdiff
path: root/jim.c
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2010-01-24 10:26:24 +1000
committerSteve Bennett <steveb@workware.net.au>2010-10-15 11:02:38 +1000
commit1df9b19429212012b245a88b08ab37caef564d1c (patch)
treee48d6153d5cde43723f2729d92e0b75d7e848ea1 /jim.c
parentc4ec906079ac99fe52e8c4b27036ca0f2495848f (diff)
downloadjimtcl-1df9b19429212012b245a88b08ab37caef564d1c.zip
jimtcl-1df9b19429212012b245a88b08ab37caef564d1c.tar.gz
jimtcl-1df9b19429212012b245a88b08ab37caef564d1c.tar.bz2
Implement some new features
Implement 'lreplace' Implement 'string last' Implement 'pid' Implement 'info procs' Implement 'info script' Implement 'info patchlevel' as an alias for 'info version' Implement syslog extensions for jim Fix return code display in jim-interactive.c Make jim more compatible if JIM_TCL_COMPAT is set *: Use tcl_interactive rather than jim_interactive *: Use auto_path rather than jim_libpath Add "." to the lib search path, not "./" Fix a couple of files with CRLF line endings
Diffstat (limited to 'jim.c')
-rw-r--r--jim.c200
1 files changed, 165 insertions, 35 deletions
diff --git a/jim.c b/jim.c
index cfb54c6..60b353f 100644
--- a/jim.c
+++ b/jim.c
@@ -389,6 +389,26 @@ int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int index)
return -1;
}
+int JimStringLast(const char *s1, int l1, const char *s2, int l2, int index)
+{
+ const char *p;
+
+ if (!l1 || !l2 || l1 > l2) return -1;
+
+ /* Possibly shorten the haystack */
+ if (index > 0 && index < l2) {
+ l2 = index;
+ }
+
+ /* Now search for the needle */
+ for (p = s2 + l2 - 1; p != s2 - 1; p--) {
+ if (*p == *s1 && memcmp(s1, p, l1) == 0) {
+ return p - s2;
+ }
+ }
+ return -1;
+}
+
int Jim_WideToString(char *buf, jim_wide wideValue)
{
const char *fmt = "%" JIM_WIDE_MODIFIER;
@@ -3210,7 +3230,7 @@ int Jim_CreateProcedure(Jim_Interp *interp, const char *cmdName,
Jim_InitHashTable(cmdPtr->staticVars, &JimVariablesHashTableType,
interp);
for (i = 0; i < len; i++) {
- Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
+ Jim_Obj *objPtr = 0, *initObjPtr = 0, *nameObjPtr = 0;
Jim_Var *varPtr;
int subLen;
@@ -4393,7 +4413,6 @@ Jim_Interp *Jim_CreateInterp(void)
i->procEpoch = 0;
i->callFrameEpoch = 0;
i->liveList = i->freeList = NULL;
- i->scriptFileName = Jim_StrDup("");
i->referenceNextId = 0;
i->lastCollectId = 0;
i->lastCollectTime = time(NULL);
@@ -4420,15 +4439,17 @@ Jim_Interp *Jim_CreateInterp(void)
i->stackTrace = Jim_NewListObj(i, NULL, 0);
i->unknown = Jim_NewStringObj(i, "unknown", -1);
i->unknown_called = 0;
+ i->currentScriptObj = Jim_NewEmptyStringObj(i);
Jim_IncrRefCount(i->emptyObj);
Jim_IncrRefCount(i->result);
Jim_IncrRefCount(i->stackTrace);
Jim_IncrRefCount(i->unknown);
+ Jim_IncrRefCount(i->currentScriptObj);
/* Initialize key variables every interpreter should contain */
- pathPtr = Jim_NewStringObj(i, "./", -1);
- Jim_SetVariableStr(i, "jim_libpath", pathPtr);
- Jim_SetVariableStrWithStr(i, "jim_interactive", "0");
+ pathPtr = Jim_NewStringObj(i, ".", -1);
+ Jim_SetVariableStr(i, JIM_LIBPATH, pathPtr);
+ Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
return i;
}
@@ -4452,7 +4473,7 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_DecrRefCount(i, i->stackTrace);
Jim_DecrRefCount(i, i->unknown);
Jim_Free((void*)i->errorFileName);
- Jim_Free((void*)i->scriptFileName);
+ Jim_DecrRefCount(i, i->currentScriptObj);
Jim_FreeHashTable(&i->commands);
Jim_FreeHashTable(&i->references);
Jim_FreeHashTable(&i->assocData);
@@ -7737,7 +7758,7 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr,
int scanned = 1;
const char *str = Jim_GetString(strObjPtr, 0);
Jim_Obj *resultList = 0;
- Jim_Obj **resultVec;
+ Jim_Obj **resultVec = 0;
int resultc;
Jim_Obj *emptyStr = 0;
ScanFmtStringObj *fmtObj;
@@ -8362,9 +8383,9 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc,
}
for (i = 0; i < num_args; i++) {
- Jim_Obj *argObjPtr;
- Jim_Obj *nameObjPtr;
- Jim_Obj *valueObjPtr;
+ Jim_Obj *argObjPtr = 0;
+ Jim_Obj *nameObjPtr = 0;
+ Jim_Obj *valueObjPtr = 0;
Jim_ListIndex(interp, cmd->argListObjPtr, i, &argObjPtr, JIM_NONE);
if (i + 1 >= cmd->arityMin) {
@@ -8388,7 +8409,7 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc,
}
/* Set optional arguments */
if (cmd->arityMax == -1) {
- Jim_Obj *listObjPtr, *objPtr;
+ Jim_Obj *listObjPtr, *objPtr = 0;
i++;
listObjPtr = Jim_NewListObj(interp, argv+i, argc-i);
@@ -8437,10 +8458,20 @@ int Jim_Eval_Named(Jim_Interp *interp, const char *script, const char *filename,
if( filename ){
+ Jim_Obj *prevScriptObj;
+
JimSetSourceInfo( interp, scriptObjPtr, filename, lineno );
- }
- retval = Jim_EvalObj(interp, scriptObjPtr);
+ prevScriptObj = interp->currentScriptObj;
+ interp->currentScriptObj = scriptObjPtr;
+
+ retval = Jim_EvalObj(interp, scriptObjPtr);
+
+ interp->currentScriptObj = prevScriptObj;
+ }
+ else {
+ retval = Jim_EvalObj(interp, scriptObjPtr);
+ }
Jim_DecrRefCount(interp, scriptObjPtr);
return retval;
}
@@ -8500,6 +8531,7 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
FILE *fp;
char *buf;
Jim_Obj *scriptObjPtr;
+ Jim_Obj *prevScriptObj;
struct stat sb;
int retval;
@@ -8521,8 +8553,16 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, sb.st_size);
JimSetSourceInfo(interp, scriptObjPtr, filename, 1);
Jim_IncrRefCount(scriptObjPtr);
+
+ prevScriptObj = interp->currentScriptObj;
+ interp->currentScriptObj = scriptObjPtr;
+
retval = Jim_EvalObj(interp, scriptObjPtr);
+
+ interp->currentScriptObj = prevScriptObj;
+
Jim_DecrRefCount(interp, scriptObjPtr);
+
return retval;
}
@@ -8772,17 +8812,21 @@ void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
Jim_SetResult(interp, objPtr);
}
-static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr)
+static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int procs_only)
{
Jim_HashTableIterator *htiter;
Jim_HashEntry *he;
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
const char *pattern;
- int patternLen;
+ int patternLen = 0;
pattern = patternObjPtr ? Jim_GetString(patternObjPtr, &patternLen) : NULL;
htiter = Jim_GetHashTableIterator(&interp->commands);
while ((he = Jim_NextHashEntry(htiter)) != NULL) {
+ Jim_Cmd *cmdPtr = he->val;
+ if (procs_only && cmdPtr->cmdProc != NULL) {
+ continue;
+ }
if (pattern && !JimStringMatch(pattern, patternLen, he->key,
strlen((const char*)he->key), 0))
continue;
@@ -8804,7 +8848,7 @@ static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr,
Jim_HashEntry *he;
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
const char *pattern;
- int patternLen;
+ int patternLen = 0;
pattern = patternObjPtr ? Jim_GetString(patternObjPtr, &patternLen) : NULL;
if (mode == JIM_VARLIST_GLOBALS) {
@@ -9935,6 +9979,78 @@ err:
return JIM_ERR;
}
+/* [lreplace] */
+static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc,
+ Jim_Obj *const *argv)
+{
+ int first, last, len, rangeLen;
+ Jim_Obj *listObj;
+ Jim_Obj *newListObj;
+ int i;
+ int shared;
+
+ if (argc < 4) {
+ Jim_WrongNumArgs(interp, 1, argv, "list first last ?element element ...?");
+ return JIM_ERR;
+ }
+ if (Jim_GetIndex(interp, argv[2], &first) != JIM_OK ||
+ Jim_GetIndex(interp, argv[3], &last) != JIM_OK) {
+ return JIM_ERR;
+ }
+
+ listObj = argv[1];
+ Jim_ListLength(interp, listObj, &len);
+
+ first = JimRelToAbsIndex(len, first);
+ last = JimRelToAbsIndex(len, last);
+ JimRelToAbsRange(len, first, last, &first, &last, &rangeLen);
+
+ /* Now construct a new list which consists of:
+ * <elements before first> <supplied elements> <elements after last>
+ */
+
+ /* Check to see if trying to replace past the end of the list */
+ if (first < len ) {
+ /* OK. Not past the end */
+ }
+ else if (len == 0) {
+ /* Special for empty list, adjust first to 0 */
+ first = 0;
+ }
+ else {
+ Jim_SetResultString(interp, "list doesn't contain element ", -1);
+ Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
+ return JIM_ERR;
+ }
+
+ newListObj = Jim_NewListObj(interp, NULL, 0);
+
+ shared = Jim_IsShared(listObj);
+ if (shared) {
+ listObj = Jim_DuplicateObj(interp, listObj);
+ }
+
+ /* Add the first set of elements */
+ for (i = 0; i < first; i++) {
+ Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]);
+ }
+
+ /* Add supplied elements */
+ for (i = 4; i < argc; i++) {
+ Jim_ListAppendElement(interp, newListObj, argv[i]);
+ }
+
+ /* Add the remaining elements */
+ for (i = first + rangeLen; i < len; i++) {
+ Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]);
+ }
+ Jim_SetResult(interp, newListObj);
+ if (shared) {
+ Jim_FreeNewObj(interp, listObj);
+ }
+ return JIM_OK;
+}
+
/* [lset] */
static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc,
Jim_Obj *const *argv)
@@ -10369,7 +10485,7 @@ static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc,
if (argListLen) {
const char *str;
int len;
- Jim_Obj *argPtr;
+ Jim_Obj *argPtr = 0;
/* Check for 'args' and adjust arityMin and arityMax if necessary */
Jim_ListIndex(interp, argv[2], argListLen-1, &argPtr, JIM_NONE);
@@ -10488,7 +10604,7 @@ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
value = Jim_Alloc(sizeof(Jim_Obj*)*numMaps);
resultObjPtr = Jim_NewStringObj(interp, "", 0);
for (i = 0; i < numMaps; i++) {
- Jim_Obj *eleObjPtr;
+ Jim_Obj *eleObjPtr = 0;
Jim_ListIndex(interp, mapListObjPtr, i*2, &eleObjPtr, JIM_NONE);
key[i] = Jim_GetString(eleObjPtr, &keyLen[i]);
@@ -10539,11 +10655,11 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc,
int option;
const char *options[] = {
"length", "compare", "match", "equal", "range", "map", "repeat",
- "index", "first", "trim", "trimleft", "trimright", "tolower", "toupper", NULL
+ "index", "first", "last", "trim", "trimleft", "trimright", "tolower", "toupper", NULL
};
enum {
OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_RANGE,
- OPT_MAP, OPT_REPEAT, OPT_INDEX, OPT_FIRST, OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT,
+ OPT_MAP, OPT_REPEAT, OPT_INDEX, OPT_FIRST, OPT_LAST, OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT,
OPT_TOLOWER, OPT_TOUPPER
};
@@ -10675,7 +10791,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc,
Jim_SetResult(interp, Jim_NewStringObj(interp, str+index, 1));
return JIM_OK;
}
- } else if (option == OPT_FIRST) {
+ } else if (option == OPT_FIRST || option == OPT_LAST) {
int index = 0, l1, l2;
const char *s1, *s2;
@@ -10690,8 +10806,14 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc,
return JIM_ERR;
index = JimRelToAbsIndex(l2, index);
}
- Jim_SetResult(interp, Jim_NewIntObj(interp,
- JimStringFirst(s1, l1, s2, l2, index)));
+ if (option == OPT_FIRST) {
+ Jim_SetResult(interp, Jim_NewIntObj(interp,
+ JimStringFirst(s1, l1, s2, l2, index)));
+ }
+ else {
+ Jim_SetResult(interp, Jim_NewIntObj(interp,
+ JimStringLast(s1, l1, s2, l2, index)));
+ }
return JIM_OK;
} else if (option == OPT_TRIM) {
if (argc != 3 && argc != 4) {
@@ -11062,11 +11184,13 @@ 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", "hostname", NULL
+ "body", "commands", "procs", "exists", "globals", "level", "locals",
+ "vars", "version", "patchlevel", "complete", "args", "hostname",
+ "script", NULL
};
- enum {INFO_BODY, INFO_COMMANDS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
- INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_COMPLETE, INFO_ARGS, INFO_HOSTNAME};
+ enum {INFO_BODY, INFO_COMMANDS, INFO_PROCS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
+ INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
+ INFO_HOSTNAME, INFO_SCRIPT};
if (argc < 2) {
Jim_WrongNumArgs(interp, 1, argv, "command ?args ...?");
@@ -11077,15 +11201,12 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc,
return JIM_ERR;
}
- if (cmd == INFO_COMMANDS) {
+ if (cmd == INFO_COMMANDS || cmd == INFO_PROCS) {
if (argc != 2 && argc != 3) {
Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
return JIM_ERR;
}
- if (argc == 3)
- Jim_SetResult(interp,JimCommandsList(interp, argv[2]));
- else
- Jim_SetResult(interp, JimCommandsList(interp, NULL));
+ Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, (cmd == INFO_PROCS)));
} else if (cmd == INFO_EXISTS) {
Jim_Obj *exists;
if (argc != 3) {
@@ -11094,6 +11215,14 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc,
}
exists = Jim_GetVariable(interp, argv[2], 0);
Jim_SetResult(interp, Jim_NewIntObj(interp, exists != 0));
+ } else if (cmd == INFO_SCRIPT) {
+ ScriptObj *script;
+ if (argc != 2) {
+ Jim_WrongNumArgs(interp, 2, argv, "");
+ return JIM_ERR;
+ }
+ script = Jim_GetScript(interp, interp->currentScriptObj);
+ Jim_SetResultString(interp, script->fileName, -1);
} else if (cmd == INFO_GLOBALS || cmd == INFO_LOCALS || cmd == INFO_VARS) {
int mode;
switch (cmd) {
@@ -11146,7 +11275,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc,
Jim_SetResult(interp, cmdPtr->bodyObjPtr);
else
Jim_SetResult(interp, cmdPtr->argListObjPtr);
- } else if (cmd == INFO_VERSION) {
+ } else if (cmd == INFO_VERSION || cmd == INFO_PATCHLEVEL) {
char buf[(JIM_INTEGER_SPACE * 2) + 1];
sprintf(buf, "%d.%d",
JIM_VERSION / 100, JIM_VERSION % 100);
@@ -11253,7 +11382,7 @@ static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc,
resObjPtr = Jim_NewStringObj(interp, NULL, 0);
/* Split */
for (i = 0; i < listLen; i++) {
- Jim_Obj *objPtr;
+ Jim_Obj *objPtr = 0;
Jim_ListIndex(interp, argv[1], i, &objPtr, JIM_NONE);
Jim_AppendObj(interp, resObjPtr, objPtr);
@@ -11571,6 +11700,7 @@ static struct {
{"llength", Jim_LlengthCoreCommand},
{"lappend", Jim_LappendCoreCommand},
{"linsert", Jim_LinsertCoreCommand},
+ {"lreplace", Jim_LreplaceCoreCommand},
{"lsort", Jim_LsortCoreCommand},
{"append", Jim_AppendCoreCommand},
{"debug", Jim_DebugCoreCommand},
@@ -11656,7 +11786,7 @@ void Jim_PrintErrorMessage(Jim_Interp *interp)
Jim_GetString(interp->result, NULL));
Jim_ListLength(interp, interp->stackTrace, &len);
for (i = len-3; i >= 0; i-= 3) {
- Jim_Obj *objPtr;
+ Jim_Obj *objPtr = 0;
const char *proc, *file, *line;
Jim_ListIndex(interp, interp->stackTrace, i, &objPtr, JIM_NONE);