Piotr Esden-Tempski <piotr@esden.net> Mac OS X compile fixes
[openocd.git] / src / helper / jim.c
index c1434dbb0bf7dcbd87c61b1113db9a69d9dac23d..f0d17525ae2742e2ff98325bb5ee05f46df09f18 100644 (file)
@@ -1,23 +1,44 @@
 /* Jim - A small embeddable Tcl interpreter
+ *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * A copy of the license is also included in the source distribution
- * of Jim, as a TXT file name called LICENSE.
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
+ * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> 
+ * Copyright 2008 oharboe - Ã˜yvind Harboe - oyvind.harboe@zylin.com
+ * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
+ * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
+ * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
+ * Copyright 2008 Steve Bennett <steveb@workware.net.au>
+ * 
+ * The FreeBSD license
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
+ **/
 #define __JIM_CORE__
 #define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */
 
@@ -28,6 +49,9 @@
 #define JIM_DYNLIB      /* Dynamic library support for UNIX and WIN32 */
 #endif /* JIM_ANSIC */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE    /* for vasprintf() */
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #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"
 
 #endif /* WIN32 */
 #endif /* JIM_DYNLIB */
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #ifdef __ECOS
 #include <cyg/jimtcl/jim.h>
 #else
@@ -85,12 +118,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.
@@ -1273,19 +1335,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') ||
@@ -1999,6 +2063,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)
 {
@@ -2129,8 +2209,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++)
@@ -2140,8 +2225,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++)
@@ -2153,8 +2243,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;
@@ -2170,8 +2261,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;
@@ -2222,32 +2311,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':
@@ -2273,7 +2362,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;
@@ -2291,11 +2380,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;
@@ -2388,6 +2477,7 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
                        break;
         case 'b':
         case 'd':
+        case 'o':
                case 'i':
                case 'u':
                case 'x':
@@ -2436,6 +2526,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
  * ---------------------------------------------------------------------------*/
@@ -2490,9 +2589,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;
 
@@ -2527,6 +2626,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
  *
@@ -2910,7 +3032,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;
     }
 
@@ -3062,9 +3184,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);
@@ -3082,9 +3201,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. */
@@ -3114,7 +3237,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;
@@ -3317,6 +3440,11 @@ static Jim_HashTableType JimVariablesHashTableType = {
     JimVariablesHTValDestructor       /* val destructor */
 };
 
+static Jim_HashTableType *getJimVariablesHashTableType(void)
+{
+       return &JimVariablesHashTableType;
+}
+
 /* -----------------------------------------------------------------------------
  * Variable object
  * ---------------------------------------------------------------------------*/
@@ -3364,14 +3492,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);
@@ -3410,7 +3546,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;
@@ -4311,6 +4453,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);
@@ -4525,6 +4668,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);
@@ -6493,7 +6641,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()");
                 }
@@ -6883,6 +7031,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;
@@ -6944,9 +7102,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;
@@ -7740,7 +7899,7 @@ void *dlsym(void *handle, const char *symbol)
     return GetProcAddress((HMODULE)handle, symbol);
 }
 static char win32_dlerror_string[121];
-const char *dlerror()
+const char *dlerror(void)
 {
     FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
                    LANG_NEUTRAL, win32_dlerror_string, 120, NULL);
@@ -7778,21 +7937,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));
@@ -8136,6 +8295,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);
@@ -8150,8 +8312,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;
@@ -8164,7 +8327,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);
@@ -8189,6 +8351,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)
@@ -8209,7 +8378,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);
@@ -8243,12 +8415,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 */
@@ -8529,6 +8705,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) {
@@ -8542,7 +8722,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);
             }
         }
@@ -8598,6 +8778,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 &&
@@ -8628,19 +8809,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 */
@@ -8675,17 +8884,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)
 {
@@ -8736,10 +8959,15 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
     Jim_Obj *scriptObjPtr;
     
     if ((fp = fopen(filename, "r")) == NULL) {
+       const int cwd_len=2048;
+               char *cwd=malloc(cwd_len);
         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+       if (!getcwd( cwd, cwd_len )) strcpy(cwd, "unknown");
         Jim_AppendStrings(interp, Jim_GetResult(interp),
-            "Error loading script \"", filename, "\": ",
-            strerror(errno), NULL);
+       "Error loading script \"", filename, "\"",
+           " cwd: ", cwd,
+           " err: ", strerror(errno), NULL);
+           free(cwd);
         return JIM_ERR;
     }
     buflen = 1024;
@@ -8953,6 +9181,13 @@ int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr,
             Jim_AppendObj(interp, resObjPtr, objPtr);
             Jim_DecrRefCount(interp, objPtr);
             break;
+        case JIM_TT_DICTSUGAR:
+            objPtr = Jim_ExpandDictSugar(interp, token[i].objPtr);
+            if (!objPtr) {
+                retcode = JIM_ERR;
+                goto err;
+            }
+            break;
         case JIM_TT_CMD:
             if (Jim_EvalObj(interp, token[i].objPtr) != JIM_OK)
                 goto err;
@@ -9013,6 +9248,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);
@@ -9039,6 +9275,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);
@@ -9121,6 +9358,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);
+
 }
 
 /* -----------------------------------------------------------------------------
@@ -10737,17 +11005,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),
@@ -11379,10 +11661,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 ...?");
@@ -11478,6 +11760,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;
 }
@@ -11696,6 +11982,27 @@ static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc,
     const char *key;
     char *val;
 
+    if (argc == 1) {
+
+#if ! HAVE_UNISTD_H || IS_DARWIN
+        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;
@@ -11724,6 +12031,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;
@@ -11873,7 +12183,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) {
@@ -11989,9 +12299,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) {
@@ -12006,9 +12318,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);
+        }
     }
 }
 
@@ -12132,3 +12453,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: ***
+ */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)