- Fixes '=' whitespace
[fw/openocd] / src / helper / jim.c
index 7d5cc2baee53695edc64cf63772c3de63dba4797..7c459d57bbeec0c1a0f171685bd3ae11ac8de78e 100644 (file)
@@ -7,6 +7,7 @@
  * 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
  * 
  * are those of the authors and should not be interpreted as representing
  * official policies, either expressed or implied, of the Jim Tcl Project.
  **/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #define __JIM_CORE__
 #define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */
 
 #ifdef __ECOS
 #include <pkgconf/jimtcl.h>
-#endif
-#ifndef JIM_ANSIC
-#define JIM_DYNLIB      /* Dynamic library support for UNIX and WIN32 */
-#endif /* JIM_ANSIC */
-
 #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
+#ifndef JIM_ANSIC
+#define JIM_DYNLIB      /* Dynamic library support for UNIX and WIN32 */
+#endif /* JIM_ANSIC */
 
-#include "replacements.h"
+#include <stdarg.h>
+#include <limits.h>
 
 /* Include the platform dependent libraries for
  * dynamic loading of libraries. */
@@ -110,7 +110,7 @@ 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
@@ -127,7 +127,9 @@ static char buf[2048];
        buf[sizeof(buf)-1] = 0;
 #else
        char *buf;
-       vasprintf( &buf, fmt, ap );
+       int result;
+       result = vasprintf( &buf, fmt, ap );
+       if (result < 0) exit(-1);
 #endif
        return buf;
 }
@@ -150,7 +152,7 @@ jim_vasprintf_done( void *buf )
  * Ignores `locale' stuff.  Assumes that the upper and lower case
  * alphabets and digits are each contiguous.
  */
-#ifdef HAVE_LONG_LONG
+#ifdef HAVE_LONG_LONG_INT
 #define JimIsAscii(c) (((c) & ~0x7f) == 0)
 static jim_wide JimStrtoll(const char *nptr, char **endptr, register int base)
 {
@@ -196,7 +198,7 @@ static jim_wide JimStrtoll(const char *nptr, char **endptr, register int base)
      * digit.  For instance, if the range for quads is
      * [-9223372036854775808..9223372036854775807] and the input base
      * is 10, cutoff will be set to 922337203685477580 and cutlim to
-     * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+     * either 7 (neg == 0) or 8 (neg == 1), meaning that if we have
      * accumulated a value > 922337203685477580, or equal but the
      * next digit is > 7 (or 8), the number is too big, and we will
      * return a range error.
@@ -243,8 +245,8 @@ static jim_wide JimStrtoll(const char *nptr, char **endptr, register int base)
 static int JimStringMatch(const char *pattern, int patternLen,
         const char *string, int stringLen, int nocase)
 {
-    while(patternLen) {
-        switch(pattern[0]) {
+    while (patternLen) {
+        switch (pattern[0]) {
         case '*':
             while (pattern[1] == '*') {
                 pattern++;
@@ -252,7 +254,7 @@ static int JimStringMatch(const char *pattern, int patternLen,
             }
             if (patternLen == 1)
                 return 1; /* match */
-            while(stringLen) {
+            while (stringLen) {
                 if (JimStringMatch(pattern+1, patternLen-1,
                             string, stringLen, nocase))
                     return 1; /* match */
@@ -279,7 +281,7 @@ static int JimStringMatch(const char *pattern, int patternLen,
                 patternLen--;
             }
             match = 0;
-            while(1) {
+            while (1) {
                 if (pattern[0] == '\\') {
                     pattern++;
                     patternLen--;
@@ -350,7 +352,7 @@ static int JimStringMatch(const char *pattern, int patternLen,
         pattern++;
         patternLen--;
         if (stringLen == 0) {
-            while(*pattern == '*') {
+            while (*pattern == '*') {
                 pattern++;
                 patternLen--;
             }
@@ -368,7 +370,7 @@ int JimStringCompare(const char *s1, int l1, const char *s2, int l2,
     unsigned char *u1 = (unsigned char*) s1, *u2 = (unsigned char*) s2;
 
     if (nocase == 0) {
-        while(l1 && l2) {
+        while (l1 && l2) {
             if (*u1 != *u2)
                 return (int)*u1-*u2;
             u1++; u2++; l1--; l2--;
@@ -376,7 +378,7 @@ int JimStringCompare(const char *s1, int l1, const char *s2, int l2,
         if (!l1 && !l2) return 0;
         return l1-l2;
     } else {
-        while(l1 && l2) {
+        while (l1 && l2) {
             if (tolower((int)*u1) != tolower((int)*u2))
                 return tolower((int)*u1)-tolower((int)*u2);
             u1++; u2++; l1--; l2--;
@@ -414,7 +416,7 @@ int Jim_StringToWide(const char *str, jim_wide *widePtr, int base)
 {
     char *endptr;
 
-#ifdef HAVE_LONG_LONG
+#ifdef HAVE_LONG_LONG_INT
     *widePtr = JimStrtoll(str, &endptr, base);
 #else
     *widePtr = strtol(str, &endptr, base);
@@ -422,7 +424,7 @@ int Jim_StringToWide(const char *str, jim_wide *widePtr, int base)
     if ((str[0] == '\0') || (str == endptr) )
         return JIM_ERR;
     if (endptr[0] != '\0') {
-        while(*endptr) {
+        while (*endptr) {
             if (!isspace((int)*endptr))
                 return JIM_ERR;
             endptr++;
@@ -439,7 +441,7 @@ int Jim_StringToIndex(const char *str, int *intPtr)
     if ( (str[0] == '\0') || (str == endptr) )
         return JIM_ERR;
     if (endptr[0] != '\0') {
-        while(*endptr) {
+        while (*endptr) {
             if (!isspace((int)*endptr))
                 return JIM_ERR;
             endptr++;
@@ -471,7 +473,7 @@ int Jim_DoubleToString(char *buf, double doubleValue)
 
     len = sprintf(buf, "%.17g", doubleValue);
     s = buf;
-    while(*s) {
+    while (*s) {
         if (*s == '.') return len;
         s++;
     }
@@ -501,8 +503,8 @@ int Jim_StringToDouble(const char *str, double *doublePtr)
 static jim_wide JimPowWide(jim_wide b, jim_wide e)
 {
     jim_wide i, res = 1;
-    if ((b==0 && e!=0) || (e<0)) return 0;
-    for(i=0; i<e; i++) {res *= b;}
+    if ((b == 0 && e != 0) || (e<0)) return 0;
+    for (i = 0; i<e; i++) {res *= b;}
     return res;
 }
 
@@ -542,7 +544,7 @@ void Jim_Panic(Jim_Interp *interp, const char *fmt, ...)
 #endif
        
        /* This may actually crash... we do it last */
-       if( interp && interp->cookie_stderr ){
+       if ( interp && interp->cookie_stderr ){
                Jim_fprintf(  interp, interp->cookie_stderr, JIM_NL "JIM INTERPRETER PANIC: ");
                Jim_vfprintf( interp, interp->cookie_stderr, fmt, ap );
                Jim_fprintf(  interp, interp->cookie_stderr, JIM_NL JIM_NL );
@@ -566,8 +568,8 @@ void Jim_Panic(Jim_Interp *interp, const char *fmt, ...)
 void *Jim_Alloc(int size)
 {
        /* We allocate zero length arrayes, etc. to use a single orthogonal codepath */
-       if (size==0)
-               size=1;
+       if (size == 0)
+               size = 1;
     void *p = malloc(size);
     if (p == NULL)
         Jim_Panic(NULL,"malloc: Out of memory");
@@ -581,8 +583,8 @@ void Jim_Free(void *ptr) {
 void *Jim_Realloc(void *ptr, int size)
 {
        /* We allocate zero length arrayes, etc. to use a single orthogonal codepath */
-       if (size==0)
-               size=1;
+       if (size == 0)
+               size = 1;
     void *p = realloc(ptr, size);
     if (p == NULL)
         Jim_Panic(NULL,"realloc: Out of memory");
@@ -659,8 +661,8 @@ unsigned int Jim_IdentityHashFunction(unsigned int key)
 unsigned int Jim_GenHashFunction(const unsigned char *buf, int len)
 {
     unsigned int h = 0;
-    while(len--)
-        h += (h<<3)+*buf++;
+    while (len--)
+        h += (h << 3)+*buf++;
     return h;
 }
 
@@ -727,7 +729,7 @@ int Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
         
         /* For each hash entry on this slot... */
         he = ht->table[i];
-        while(he) {
+        while (he) {
             unsigned int h;
 
             nextHe = he->next;
@@ -800,7 +802,7 @@ int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
     he = ht->table[h];
 
     prevHe = NULL;
-    while(he) {
+    while (he) {
         if (Jim_CompareHashKeys(ht, key, he->key)) {
             /* Unlink the element from the list */
             if (prevHe)
@@ -829,7 +831,7 @@ int Jim_FreeHashTable(Jim_HashTable *ht)
         Jim_HashEntry *he, *nextHe;
 
         if ((he = ht->table[i]) == NULL) continue;
-        while(he) {
+        while (he) {
             nextHe = he->next;
             Jim_FreeEntryKey(ht, he);
             Jim_FreeEntryVal(ht, he);
@@ -853,7 +855,7 @@ Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
     if (ht->size == 0) return NULL;
     h = Jim_HashKey(ht, key) & ht->sizemask;
     he = ht->table[h];
-    while(he) {
+    while (he) {
         if (Jim_CompareHashKeys(ht, key, he->key))
             return he;
         he = he->next;
@@ -914,7 +916,7 @@ static unsigned int JimHashTableNextPower(unsigned int size)
 
     if (size >= 2147483648U)
         return 2147483648U;
-    while(1) {
+    while (1) {
         if (i >= size)
             return i;
         i *= 2;
@@ -936,7 +938,7 @@ static int JimInsertHashEntry(Jim_HashTable *ht, const void *key)
     h = Jim_HashKey(ht, key) & ht->sizemask;
     /* Search if this slot does not already contain the given key */
     he = ht->table[h];
-    while(he) {
+    while (he) {
         if (Jim_CompareHashKeys(ht, key, he->key))
             return -1;
         he = he->next;
@@ -1178,7 +1180,7 @@ void JimParserInit(struct JimParserCtx *pc, const char *prg,
 
 int JimParseScript(struct JimParserCtx *pc)
 {
-    while(1) { /* the while is used to reiterate with continue if needed */
+    while (1) { /* the while is used to reiterate with continue if needed */
         if (!pc->len) {
             pc->tstart = pc->p;
             pc->tend = pc->p-1;
@@ -1187,7 +1189,7 @@ int JimParseScript(struct JimParserCtx *pc)
             pc->eof = 1;
             return JIM_OK;
         }
-        switch(*(pc->p)) {
+        switch (*(pc->p)) {
         case '\\':
             if (*(pc->p+1) == '\n')
                 return JimParseSep(pc);
@@ -1325,19 +1327,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') ||
@@ -1423,7 +1427,7 @@ int JimParseStr(struct JimParserCtx *pc)
             pc->tt = JIM_TT_ESC;
             return JIM_OK;
         }
-        switch(*pc->p) {
+        switch (*pc->p) {
         case '\\':
             if (pc->state == JIM_PS_DEF &&
                 *(pc->p+1) == '\n') {
@@ -1514,9 +1518,9 @@ static int JimEscape(char *dest, const char *s, int slen)
         slen = strlen(s);
 
     for (i = 0; i < slen; i++) {
-        switch(s[i]) {
+        switch (s[i]) {
         case '\\':
-            switch(s[i+1]) {
+            switch (s[i+1]) {
             case 'a': *p++ = 0x7; i++; break;
             case 'b': *p++ = 0x8; i++; break;
             case 'f': *p++ = 0xc; i++; break;
@@ -1653,7 +1657,7 @@ int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr)
     int level = 0;
     int state = ' ';
 
-    while(len) {
+    while (len) {
         switch (*s) {
             case '\\':
                 if (len > 1)
@@ -1705,7 +1709,7 @@ int JimParseList(struct JimParserCtx *pc)
         pc->eof = 1;
         return JIM_OK;
     }
-    switch(*pc->p) {
+    switch (*pc->p) {
     case ' ':
     case '\n':
     case '\t':
@@ -1753,7 +1757,7 @@ int JimParseListStr(struct JimParserCtx *pc)
             pc->tt = JIM_TT_ESC;
             return JIM_OK;
         }
-        switch(*pc->p) {
+        switch (*pc->p) {
         case '\\':
             pc->p++; pc->len--;
             break;
@@ -2060,7 +2064,7 @@ void Jim_AppendString_sprintf( Jim_Interp *interp, Jim_Obj *objPtr, const char *
        buf = jim_vasprintf( fmt, ap );
        va_end(ap);
 
-       if( buf ){
+       if ( buf ){
                Jim_AppendString( interp, objPtr, buf, -1 );
                jim_vasprintf_done(buf);
        }
@@ -2197,8 +2201,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++)
@@ -2208,8 +2217,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++)
@@ -2269,10 +2283,10 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
                haveprec = 0;
                prec = -1; /* not found yet */
     next_fmt:
-               if( fmtLen <= 0 ){
+               if ( fmtLen <= 0 ){
                        break;
                }
-               switch( *fmt ){
+               switch ( *fmt ){
                        /* terminals */
         case 'b': /* binary - not all printfs() do this */
                case 's': /* string */
@@ -2289,32 +2303,32 @@ static Jim_Obj *Jim_FormatString_Inner(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':
@@ -2327,11 +2341,11 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
                case '8':
                case '9':
                        accum = 0;
-                       while( isdigit(*fmt) && (fmtLen > 0) ){
+                       while ( isdigit(*fmt) && (fmtLen > 0) ){
                                accum = (accum * 10) + (*fmt - '0');
                                fmt++;  fmtLen--;
                        }
-                       if( inprec ){
+                       if ( inprec ){
                                haveprec = 1;
                                prec = accum;
                        } else {
@@ -2340,29 +2354,29 @@ static Jim_Obj *Jim_FormatString_Inner(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 ){
+                       if ( objc <= 0 ){
                                goto not_enough_args;
                        }
-                       if( Jim_GetWide(interp,objv[0],&wideValue )== JIM_ERR ){
+                       if ( Jim_GetWide(interp,objv[0],&wideValue )== JIM_ERR ){
                                Jim_FreeNewObj(interp, resObjPtr );
                                return NULL;
                        }
-                       if( inprec ){
+                       if ( inprec ){
                                haveprec = 1;
                                prec = wideValue;
-                               if( prec < 0 ){
+                               if ( prec < 0 ){
                                        /* man 3 printf says */
                                        /* if prec is negative, it is zero */
                                        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,32 +2402,32 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
                 */
                cp = fmt_str;
                *cp++ = '%';
-               if( altfm ){
+               if ( altfm ){
                        *cp++ = '#';
                }
-               if( forceplus ){
+               if ( forceplus ){
                        *cp++ = '+';
-               } else if( spad ){
+               } else if ( spad ){
                        /* PLUS overrides */
                        *cp++ = ' ';
                }
-               if( ljust ){
+               if ( ljust ){
                        *cp++ = '-';
                }
-               if( zpad  ){
+               if ( zpad  ){
                        *cp++ = '0';
                }
-               if( width > 0 ){
+               if ( width > 0 ){
                        sprintf( cp, "%d", width );
                        /* skip ahead */
                        cp = strchr(cp,0);
                }
                /* did we find a period? */
-               if( inprec ){
+               if ( inprec ){
                        /* then add it */
                        *cp++ = '.';
                        /* did something occur after the period? */
-                       if( haveprec ){
+                       if ( haveprec ){
                                sprintf( cp, "%d", prec );
                        }
                        cp = strchr(cp,0);
@@ -2422,7 +2436,7 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
 
                /* here we do the work */
                /* actually - we make sprintf() do it for us */
-        switch(*fmt) {
+        switch (*fmt) {
         case 's':
                        *cp++ = 's';
                        *cp   = 0;
@@ -2447,7 +2461,7 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
                case 'E':
                        *cp++ = *fmt;
                        *cp   = 0;
-                       if( Jim_GetDouble( interp, objv[0], &doubleValue ) == JIM_ERR ){
+                       if ( Jim_GetDouble( interp, objv[0], &doubleValue ) == JIM_ERR ){
                                Jim_FreeNewObj( interp, resObjPtr );
                                return NULL;
                        }
@@ -2455,12 +2469,13 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
                        break;
         case 'b':
         case 'd':
+        case 'o':
                case 'i':
                case 'u':
                case 'x':
                case 'X':
                        /* jim widevaluse are 64bit */
-                       if( sizeof(jim_wide) == sizeof(long long) ){
+                       if ( sizeof(jim_wide) == sizeof(long long) ){
                                *cp++ = 'l'; 
                                *cp++ = 'l';
                        } else {
@@ -2506,8 +2521,8 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
 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);
+       char *sprintf_buf = malloc(JIM_MAX_FMT);
+       Jim_Obj *t = Jim_FormatString_Inner(interp, fmtObjPtr, objc, objv, sprintf_buf);
        free(sprintf_buf);
        return t; 
 }
@@ -2612,12 +2627,12 @@ int Jim_GetNvp(Jim_Interp *interp,
        int e;
 
        e = Jim_Nvp_name2value_obj( interp, nvp_table, objPtr, &n );
-       if( e == JIM_ERR ){
+       if ( e == JIM_ERR ){
                return e;
        }
 
        /* Success? found? */
-       if( n->name ){
+       if ( n->name ){
                /* remove const */
                *result = (Jim_Nvp *)n;
                return JIM_OK;
@@ -3009,12 +3024,12 @@ 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;
     }
 
     JimParserInit(&parser, scriptText, scriptTextLen, initialLineNumber);
-    while(!JimParserEof(&parser)) {
+    while (!JimParserEof(&parser)) {
         char *token;
         int len, type, linenr;
 
@@ -3161,9 +3176,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);
@@ -3181,9 +3193,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. */
@@ -3213,7 +3229,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;
@@ -3416,6 +3432,11 @@ static Jim_HashTableType JimVariablesHashTableType = {
     JimVariablesHTValDestructor       /* val destructor */
 };
 
+static Jim_HashTableType *getJimVariablesHashTableType(void)
+{
+       return &JimVariablesHashTableType;
+}
+
 /* -----------------------------------------------------------------------------
  * Variable object
  * ---------------------------------------------------------------------------*/
@@ -3463,14 +3484,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);
@@ -3509,7 +3538,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;
@@ -3586,7 +3621,7 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
         Jim_Obj *objPtr = targetNameObjPtr;
         Jim_Var *varPtr;
         /* Cycles are only possible with 'uplevel 0' */
-        while(1) {
+        while (1) {
             if (Jim_StringEqObj(objPtr, nameObjPtr, 0)) {
                 Jim_SetResultString(interp,
                     "can't upvar from variable to itself", -1);
@@ -4227,7 +4262,7 @@ int Jim_Collect(Jim_Interp *interp)
      * is of a type that can contain references. */
     Jim_InitHashTable(&marks, &JimRefMarkHashTableType, NULL);
     objPtr = interp->liveList;
-    while(objPtr) {
+    while (objPtr) {
         if (objPtr->typePtr == NULL ||
             objPtr->typePtr->flags & JIM_TYPE_REFERENCES) {
             const char *str, *p;
@@ -4256,7 +4291,7 @@ int Jim_Collect(Jim_Interp *interp)
                 continue;
             }
             /* Extract references from the object string repr. */
-            while(1) {
+            while (1) {
                 int i;
                 jim_wide id;
                 char buf[21];
@@ -4410,6 +4445,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);
@@ -4452,7 +4488,7 @@ void Jim_FreeInterp(Jim_Interp *i)
     Jim_FreeHashTable(&i->packages);
     Jim_Free(i->prngState);
     /* Free the call frames list */
-    while(cf) {
+    while (cf) {
         prevcf = cf->parentCallFrame;
         JimFreeCallFrame(i, cf, JIM_FCF_NONE);
         cf = prevcf;
@@ -4464,7 +4500,7 @@ void Jim_FreeInterp(Jim_Interp *i)
     
         Jim_fprintf( i, i->cookie_stdout,JIM_NL "-------------------------------------" JIM_NL);
         Jim_fprintf( i, i->cookie_stdout,"Objects still in the free list:" JIM_NL);
-        while(objPtr) {
+        while (objPtr) {
             const char *type = objPtr->typePtr ?
                 objPtr->typePtr->name : "";
             Jim_fprintf( i, i->cookie_stdout,"%p \"%-10s\": '%.20s' (refCount: %d)" JIM_NL,
@@ -4490,7 +4526,7 @@ void Jim_FreeInterp(Jim_Interp *i)
     }
     /* Free cached CallFrame structures */
     cf = i->freeFramesList;
-    while(cf) {
+    while (cf) {
         nextcf = cf->nextFramePtr;
         if (cf->vars.table != NULL)
             Jim_Free(cf->vars.table);
@@ -4624,6 +4660,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);
@@ -4989,7 +5030,7 @@ static int ListElementQuotingType(const char *s, int len)
         goto testbrace;
     }
     for (i = 0; i < len; i++) {
-        switch(s[i]) {
+        switch (s[i]) {
         case ' ':
         case '$':
         case '"':
@@ -5016,7 +5057,7 @@ testbrace:
         s[len-1] == ']') return JIM_ELESTR_QUOTE;
     level = 0;
     for (i = 0; i < len; i++) {
-        switch(s[i]) {
+        switch (s[i]) {
         case '{': level++; break;
         case '}': level--;
               if (level < 0) return JIM_ELESTR_QUOTE;
@@ -5032,7 +5073,7 @@ testbrace:
     if (level == 0) {
         if (!trySimple) return JIM_ELESTR_BRACE;
         for (i = 0; i < len; i++) {
-            switch(s[i]) {
+            switch (s[i]) {
             case ' ':
             case '$':
             case '"':
@@ -5061,7 +5102,7 @@ char *BackslashQuoteString(const char *s, int len, int *qlenPtr)
     char *q = Jim_Alloc(len*2+1), *p;
 
     p = q;
-    while(*s) {
+    while (*s) {
         switch (*s) {
         case ' ':
         case '$':
@@ -5123,7 +5164,7 @@ void UpdateStringOfList(struct Jim_Obj *objPtr)
         const char *strRep = Jim_GetString(ele[i], &len);
         char *q;
 
-        switch(quotingType[i]) {
+        switch (quotingType[i]) {
         case JIM_ELESTR_SIMPLE:
             memcpy(p, strRep, len);
             p += len;
@@ -5174,7 +5215,7 @@ int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 
     /* Convert into a list */
     JimParserInit(&parser, str, strLen, 1);
-    while(!JimParserEof(&parser)) {
+    while (!JimParserEof(&parser)) {
         char *token;
         int tokenLen, type;
         Jim_Obj *elementPtr;
@@ -5325,7 +5366,7 @@ void ListInsertElements(Jim_Obj *listPtr, int index, int elemc,
     }
     point = listPtr->internalRep.listValue.ele + index;
     memmove(point+elemc, point, (currentLen-index) * sizeof(Jim_Obj*));
-    for (i=0; i < elemc; ++i) {
+    for (i = 0; i < elemc; ++i) {
         point[i] = elemVec[i];
         Jim_IncrRefCount(point[i]);
     }
@@ -5698,7 +5739,7 @@ void UpdateStringOfDict(struct Jim_Obj *objPtr)
         const char *strRep = Jim_GetString(objv[i], &len);
         char *q;
 
-        switch(quotingType[i]) {
+        switch (quotingType[i]) {
         case JIM_ELESTR_SIMPLE:
             memcpy(p, strRep, len);
             p += len;
@@ -5753,7 +5794,7 @@ int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
     /* Convert into a dict */
     JimParserInit(&parser, str, strLen, 1);
     i = 0;
-    while(!JimParserEof(&parser)) {
+    while (!JimParserEof(&parser)) {
         char *token;
         int tokenLen, type;
 
@@ -5878,7 +5919,7 @@ int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
 int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr,
         Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags)
 {
-    Jim_Obj *objPtr;
+    Jim_Obj *objPtr = NULL;
     int i;
 
     if (keyc == 0) {
@@ -6235,7 +6276,7 @@ static struct Jim_ExprOperator Jim_ExprOperators[] = {
 int JimParseExpression(struct JimParserCtx *pc)
 {
     /* Discard spaces and quoted newline */
-    while(*(pc->p) == ' ' ||
+    while (*(pc->p) == ' ' ||
           *(pc->p) == '\t' ||
           *(pc->p) == '\r' ||
           *(pc->p) == '\n' ||
@@ -6250,7 +6291,7 @@ int JimParseExpression(struct JimParserCtx *pc)
         pc->eof = 1;
         return JIM_OK;
     }
-    switch(*(pc->p)) {
+    switch (*(pc->p)) {
     case '(':
         pc->tstart = pc->tend = pc->p;
         pc->tline = pc->linenr;
@@ -6467,7 +6508,7 @@ static int ExprCheckCorrectness(ExprByteCode *expr)
      * and make sure at the end of the program there is
      * a single result on the stack. */
     for (i = 0; i < expr->len; i++) {
-        switch(expr->opcode[i]) {
+        switch (expr->opcode[i]) {
         case JIM_EXPROP_NUMBER:
         case JIM_EXPROP_STRING:
         case JIM_EXPROP_SUBST:
@@ -6582,8 +6623,8 @@ static void ExprMakeLazy(Jim_Interp *interp, ExprByteCode *expr)
         /* Search for the end of the first operator */
         leftindex = index-1;
         arity = 1;
-        while(arity) {
-            switch(expr->opcode[leftindex]) {
+        while (arity) {
+            switch (expr->opcode[leftindex]) {
             case JIM_EXPROP_NUMBER:
             case JIM_EXPROP_COMMAND:
             case JIM_EXPROP_VARIABLE:
@@ -6592,7 +6633,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()");
                 }
@@ -6656,7 +6697,7 @@ int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 
     Jim_InitStack(&stack);
     JimParserInit(&parser, exprText, exprTextLen, 1);
-    while(!JimParserEof(&parser)) {
+    while (!JimParserEof(&parser)) {
         char *token;
         int len, type;
 
@@ -6669,7 +6710,7 @@ int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
             Jim_Free(token);
             break;
         }
-        switch(type) {
+        switch (type) {
         case JIM_TT_STR:
             ExprObjAddInstr(interp, expr, JIM_EXPROP_STRING, token, len);
             break;
@@ -6690,7 +6731,7 @@ int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
             break;
         case JIM_TT_EXPR_OPERATOR:
             op = JimExprOperatorInfo(token);
-            while(1) {
+            while (1) {
                 Jim_ExprOperator *stackTopOp;
 
                 if (Jim_StackPeek(&stack) != NULL) {
@@ -6717,7 +6758,7 @@ int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
         case JIM_TT_SUBEXPR_END:
             {
                 int found = 0;
-                while(Jim_StackLen(&stack)) {
+                while (Jim_StackLen(&stack)) {
                     char *opstr = Jim_StackPop(&stack);
                     if (!strcmp(opstr, "(")) {
                         Jim_Free(opstr);
@@ -6908,18 +6949,18 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr,
             }
             Jim_DecrRefCount(interp, A);
             Jim_DecrRefCount(interp, B);
-            switch(expr->opcode[i]) {
+            switch (expr->opcode[i]) {
             case JIM_EXPROP_ADD: wC = wA+wB; break;
             case JIM_EXPROP_SUB: wC = wA-wB; break;
             case JIM_EXPROP_MUL: wC = wA*wB; break;
             case JIM_EXPROP_LT: wC = wA<wB; break;
             case JIM_EXPROP_GT: wC = wA>wB; break;
-            case JIM_EXPROP_LTE: wC = wA<=wB; break;
-            case JIM_EXPROP_GTE: wC = wA>=wB; break;
-            case JIM_EXPROP_LSHIFT: wC = wA<<wB; break;
-            case JIM_EXPROP_RSHIFT: wC = wA>>wB; break;
-            case JIM_EXPROP_NUMEQ: wC = wA==wB; break;
-            case JIM_EXPROP_NUMNE: wC = wA!=wB; break;
+            case JIM_EXPROP_LTE: wC = wA <= wB; break;
+            case JIM_EXPROP_GTE: wC = wA >= wB; break;
+            case JIM_EXPROP_LSHIFT: wC = wA << wB; break;
+            case JIM_EXPROP_RSHIFT: wC = wA >> wB; break;
+            case JIM_EXPROP_NUMEQ: wC = wA == wB; break;
+            case JIM_EXPROP_NUMNE: wC = wA != wB; break;
             case JIM_EXPROP_BITAND: wC = wA&wB; break;
             case JIM_EXPROP_BITXOR: wC = wA^wB; break;
             case JIM_EXPROP_BITOR: wC = wA|wB; break;
@@ -6955,7 +6996,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr,
                 wC = _rotl(uA,(unsigned long)wB);
 #else
                 const unsigned int S = sizeof(unsigned long) * 8;
-                wC = (unsigned long)((uA<<wB)|(uA>>(S-wB)));
+                wC = (unsigned long)((uA << wB)|(uA >> (S-wB)));
 #endif
                 break;
             }
@@ -6965,7 +7006,7 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr,
                 wC = _rotr(uA,(unsigned long)wB);
 #else
                 const unsigned int S = sizeof(unsigned long) * 8;
-                wC = (unsigned long)((uA>>wB)|(uA<<(S-wB)));
+                wC = (unsigned long)((uA >> wB)|(uA << (S-wB)));
 #endif
                 break;
             }
@@ -6982,6 +7023,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;
@@ -6989,7 +7040,7 @@ trydouble:
             }
             Jim_DecrRefCount(interp, A);
             Jim_DecrRefCount(interp, B);
-            switch(expr->opcode[i]) {
+            switch (expr->opcode[i]) {
             case JIM_EXPROP_ROTL:
             case JIM_EXPROP_ROTR:
             case JIM_EXPROP_LSHIFT:
@@ -7009,10 +7060,10 @@ trydouble:
             case JIM_EXPROP_MUL: dC = dA*dB; break;
             case JIM_EXPROP_LT: dC = dA<dB; break;
             case JIM_EXPROP_GT: dC = dA>dB; break;
-            case JIM_EXPROP_LTE: dC = dA<=dB; break;
-            case JIM_EXPROP_GTE: dC = dA>=dB; break;
-            case JIM_EXPROP_NUMEQ: dC = dA==dB; break;
-            case JIM_EXPROP_NUMNE: dC = dA!=dB; break;
+            case JIM_EXPROP_LTE: dC = dA <= dB; break;
+            case JIM_EXPROP_GTE: dC = dA >= dB; break;
+            case JIM_EXPROP_NUMEQ: dC = dA == dB; break;
+            case JIM_EXPROP_NUMNE: dC = dA != dB; break;
             case JIM_EXPROP_LOGICAND_LEFT:
                 if (dA == 0) {
                     i += (int)dB;
@@ -7043,9 +7094,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;
@@ -7082,7 +7134,7 @@ trydouble:
                 goto trydouble_unary;
             }
             Jim_DecrRefCount(interp, A);
-            switch(expr->opcode[i]) {
+            switch (expr->opcode[i]) {
             case JIM_EXPROP_NOT: wC = !wA; break;
             case JIM_EXPROP_BITNOT: wC = ~wA; break;
             case JIM_EXPROP_LOGICAND_RIGHT:
@@ -7103,7 +7155,7 @@ trydouble_unary:
                 goto err;
             }
             Jim_DecrRefCount(interp, A);
-            switch(expr->opcode[i]) {
+            switch (expr->opcode[i]) {
             case JIM_EXPROP_NOT: dC = !dA; break;
             case JIM_EXPROP_LOGICAND_RIGHT:
             case JIM_EXPROP_LOGICOR_RIGHT: dC = (dA != 0); break;
@@ -7283,7 +7335,7 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
 
     Jim_FreeIntRep(interp, objPtr);
     /* Count how many conversions could take place maximally */
-    for (i=0, maxCount=0; i < maxFmtLen; ++i)
+    for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
         if (fmt[i] == '%')
             ++maxCount;
     /* Calculate an approximation of the memory necessary */
@@ -7304,8 +7356,8 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
     buffer = fmtObj->stringRep + maxFmtLen + 1;
     objPtr->internalRep.ptr = fmtObj;
     objPtr->typePtr = &scanFmtStringObjType;
-    for (i=0, curr=0; fmt < fmtEnd; ++fmt) {
-        int width=0, skip;
+    for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) {
+        int width = 0, skip;
         ScanFmtPartDescr *descr = &fmtObj->descr[curr];
         fmtObj->count++;
         descr->width = 0;                   /* Assume width unspecified */ 
@@ -7349,7 +7401,7 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
                     return JIM_ERR;
                 }
                 /* Look if this position was already used */
-                for (prev=0; prev < curr; ++prev) {
+                for (prev = 0; prev < curr; ++prev) {
                     if (fmtObj->descr[prev].pos == -1) continue;
                     if (fmtObj->descr[prev].pos == descr->pos) {
                         fmtObj->error = "same \"%n$\" conversion specifier "
@@ -7390,7 +7442,7 @@ static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
             /* In case a range fence was given "backwards", swap it */
             while (swapped) {
                 swapped = 0;
-                for (j=beg+1; j < end-1; ++j) {
+                for (j = beg+1; j < end-1; ++j) {
                     if (buffer[j] == '-' && buffer[j-1] > buffer[j+1]) {
                         char tmp = buffer[j-1];
                         buffer[j-1] = buffer[j+1];
@@ -7498,7 +7550,7 @@ JimScanAString(Jim_Interp *interp, const char *sdescr, const char *str)
             if (sdescr[1] == '-' && sdescr[2] != 0) {
                 /* Handle range definitions */
                 int i;
-                for (i=sdescr[0]; i <= sdescr[2]; ++i)
+                for (i = sdescr[0]; i <= sdescr[2]; ++i)
                     JimSetBit(charset, (char)i);
                 sdescr += 3;
             } else {
@@ -7507,7 +7559,7 @@ JimScanAString(Jim_Interp *interp, const char *sdescr, const char *str)
             }
         }
         /* Negate the charset if there was a NOT given */
-        for (i=0; notFlag && i < sizeof(charset); ++i)
+        for (i = 0; notFlag && i < sizeof(charset); ++i)
             charset[i] = ~charset[i];
     } 
     /* And after all the mess above, the real work begin ... */
@@ -7548,7 +7600,7 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos,
     if (descr->prefix) {
         /* There was a prefix given before the conversion, skip it and adjust
          * the string-to-be-parsed accordingly */
-        for (i=0; str[pos] && descr->prefix[i]; ++i) {
+        for (i = 0; str[pos] && descr->prefix[i]; ++i) {
             /* If prefix require, skip WS */
             if (isspace((int)descr->prefix[i]))
                 while (str[pos] && isspace((int)str[pos])) ++pos;
@@ -7590,6 +7642,8 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos,
                 scanned += 1;
                 break;
             case 'd': case 'o': case 'x': case 'u': case 'i': {
+                jim_wide jwvalue = 0;
+                long lvalue = 0;
                 char *endp;  /* Position where the number finished */
                 int base = descr->type == 'o' ? 8
                     : descr->type == 'x' ? 16
@@ -7599,16 +7653,22 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos,
                 do {
                     /* Try to scan a number with the given base */
                     if (descr->modifier == 'l')
-#ifdef HAVE_LONG_LONG
-                      *(jim_wide*)value = JimStrtoll(tok, &endp, base);
+                    {
+#ifdef HAVE_LONG_LONG_INT
+                        jwvalue = JimStrtoll(tok, &endp, base),
 #else
-                      *(jim_wide*)value = strtol(tok, &endp, base);
+                        jwvalue = strtol(tok, &endp, base),
 #endif
+                        memcpy(value, &jwvalue, sizeof(jim_wide));
+                    }
                     else
+                    {
                       if (descr->type == 'u')
-                        *(long*)value = strtoul(tok, &endp, base);
+                        lvalue = strtoul(tok, &endp, base);
                       else
-                        *(long*)value = strtol(tok, &endp, base);
+                        lvalue = strtol(tok, &endp, base);
+                      memcpy(value, &lvalue, sizeof(lvalue));
+                    }
                     /* If scanning failed, and base was undetermined, simply
                      * put it to 10 and try once more. This should catch the
                      * case where %i begin to parse a number prefix (e.g. 
@@ -7620,9 +7680,9 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos,
                 if (endp != tok) {
                     /* There was some number sucessfully scanned! */
                     if (descr->modifier == 'l')
-                        *valObjPtr = Jim_NewIntObj(interp, *(jim_wide*)value);
+                        *valObjPtr = Jim_NewIntObj(interp, jwvalue);
                     else
-                        *valObjPtr = Jim_NewIntObj(interp, *(long*)value);
+                        *valObjPtr = Jim_NewIntObj(interp, lvalue);
                     /* Adjust the number-of-chars scanned so far */
                     scanned += endp - tok;
                 } else {
@@ -7641,10 +7701,11 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos,
             case 'e': case 'f': case 'g': {
                 char *endp;
 
-                *(double*)value = strtod(tok, &endp);
+                double dvalue = strtod(tok, &endp);
+                memcpy(value, &dvalue, sizeof(double));
                 if (endp != tok) {
                     /* There was some number sucessfully scanned! */
-                    *valObjPtr = Jim_NewDoubleObj(interp, *(double*)value);
+                    *valObjPtr = Jim_NewDoubleObj(interp, dvalue);
                     /* Adjust the number-of-chars scanned so far */
                     scanned += endp - tok;
                 } else {
@@ -7696,12 +7757,12 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr,
     /* Create a list and fill it with empty strings up to max specified XPG3 */
     resultList = Jim_NewListObj(interp, 0, 0);
     if (fmtObj->maxPos > 0) {
-        for (i=0; i < fmtObj->maxPos; ++i)
+        for (i = 0; i < fmtObj->maxPos; ++i)
             Jim_ListAppendElement(interp, resultList, emptyStr);
         JimListGetElements(interp, resultList, &resultc, &resultVec);
     }
     /* Now handle every partial format description */
-    for (i=0, pos=0; i < fmtObj->count; ++i) {
+    for (i = 0, pos = 0; i < fmtObj->count; ++i) {
         ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
         Jim_Obj *value = 0;
         /* Only last type may be "literal" w/o conversion - skip it! */
@@ -7877,21 +7938,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));
@@ -7977,7 +8038,7 @@ badfmt:
     return JIM_ERR;
 }
 
-#define JIM_MATCHVER_EXACT (1<<JIM_PRIV_FLAG_SHIFT)
+#define JIM_MATCHVER_EXACT (1 << JIM_PRIV_FLAG_SHIFT)
 static int JimPackageMatchVersion(int needed, int actual, int flags)
 {
     if (needed == JIM_PKG_ANY_VERSION) return 1;
@@ -8043,17 +8104,17 @@ DIR *opendir(const char *name)
 {
     DIR *dir = 0;
 
-    if(name && name[0]) {
+    if (name && name[0]) {
         size_t base_length = strlen(name);
         const char *all = /* search pattern must end with suitable wildcard */
             strchr("/\\", name[base_length - 1]) ? "*" : "/*";
 
-        if((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
+        if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
            (dir->name = (char *) Jim_Alloc(base_length + strlen(all) + 1)) != 0)
         {
             strcat(strcpy(dir->name, name), all);
 
-            if((dir->handle = (long) _findfirst(dir->name, &dir->info)) != -1)
+            if ((dir->handle = (long) _findfirst(dir->name, &dir->info)) != -1)
                 dir->result.d_name = 0;
             else { /* rollback */
                 Jim_Free(dir->name);
@@ -8075,13 +8136,13 @@ int closedir(DIR *dir)
 {
     int result = -1;
 
-    if(dir) {
-        if(dir->handle != -1)
+    if (dir) {
+        if (dir->handle != -1)
             result = _findclose(dir->handle);
         Jim_Free(dir->name);
         Jim_Free(dir);
     }
-    if(result == -1) /* map all errors to EBADF */
+    if (result == -1) /* map all errors to EBADF */
         errno = EBADF;
     return result;
 }
@@ -8090,8 +8151,8 @@ struct dirent *readdir(DIR *dir)
 {
     struct dirent *result = 0;
 
-    if(dir && dir->handle != -1) {
-        if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) {
+    if (dir && dir->handle != -1) {
+        if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) {
             result         = &dir->result;
             result->d_name = dir->info.name;
         }
@@ -8235,6 +8296,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);
@@ -8249,8 +8313,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;
@@ -8263,7 +8328,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);
@@ -8288,6 +8352,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)
@@ -8308,7 +8379,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);
@@ -8342,12 +8416,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 */
@@ -8376,7 +8454,7 @@ int Jim_InterpolateTokens(Jim_Interp *interp, ScriptToken *token,
     /* Compute every token forming the argument
      * in the intv objects vector. */
     for (i = 0; i < tokens; i++) {
-        switch(token[i].type) {
+        switch (token[i].type) {
         case JIM_TT_ESC:
         case JIM_TT_STR:
             intv[i] = token[i].objPtr;
@@ -8550,7 +8628,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
             if (tokens == 1) {
                 /* Fast path if the token does not
                  * need interpolation */
-                switch(token[i].type) {
+                switch (token[i].type) {
                 case JIM_TT_ESC:
                 case JIM_TT_STR:
                     argv[j] = token[i].objPtr;
@@ -8628,6 +8706,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) {
@@ -8641,7 +8723,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);
             }
         }
@@ -8697,6 +8779,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 &&
@@ -8727,19 +8810,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);
+
+    /* 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;
+        }
 
-        Jim_ListIndex(interp, cmd->argListObjPtr, i, &objPtr, JIM_NONE);
-        Jim_SetVariable(interp, objPtr, argv[i+1]);
+        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 */
@@ -8783,7 +8894,7 @@ int Jim_Eval_Named(Jim_Interp *interp, const char *script, const char *filename,
     Jim_IncrRefCount(scriptObjPtr);
 
 
-       if( filename ){
+       if ( filename ){
                JimSetSourceInfo( interp, scriptObjPtr, filename, lineno );
        }
 
@@ -8849,10 +8960,10 @@ 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);
+       const int cwd_len = 2048;
+               char *cwd = malloc(cwd_len);
         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-       getcwd( cwd, cwd_len );
+       if (!getcwd( cwd, cwd_len )) strcpy(cwd, "unknown");
         Jim_AppendStrings(interp, Jim_GetResult(interp),
        "Error loading script \"", filename, "\"",
            " cwd: ", cwd,
@@ -8909,7 +9020,7 @@ static int JimParseSubst(struct JimParserCtx *pc, int flags)
         pc->eof = 1;
         return JIM_OK;
     }
-    switch(*pc->p) {
+    switch (*pc->p) {
     case '[':
         retval = JimParseCmd(pc);
         if (flags & JIM_SUBST_NOCMD) {
@@ -8983,7 +9094,7 @@ int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags)
     script->fileName = NULL;
 
     JimParserInit(&parser, scriptText, scriptTextLen, 1);
-    while(1) {
+    while (1) {
         char *token;
         int len, type, linenr;
 
@@ -9059,7 +9170,7 @@ int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr,
     for (i = 0; i < len; i++) {
         Jim_Obj *objPtr;
 
-        switch(token[i].type) {
+        switch (token[i].type) {
         case JIM_TT_STR:
         case JIM_TT_ESC:
             Jim_AppendObj(interp, resObjPtr, token[i].objPtr);
@@ -9662,7 +9773,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc,
         
         if ((expr = Jim_GetExpression(interp, argv[1])) == NULL) goto noopt;
         if (expr->len <= 0 || expr->len > 3) goto noopt;
-        switch(expr->len) {
+        switch (expr->len) {
         case 1:
             if (expr->opcode[0] != JIM_EXPROP_VARIABLE &&
                 expr->opcode[0] != JIM_EXPROP_NUMBER)
@@ -9678,7 +9789,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc,
                 (expr->opcode[1] != JIM_EXPROP_NUMBER &&
                  expr->opcode[1] != JIM_EXPROP_VARIABLE))
                 goto noopt;
-            switch(expr->opcode[2]) {
+            switch (expr->opcode[2]) {
             case JIM_EXPROP_LT:
             case JIM_EXPROP_LTE:
             case JIM_EXPROP_GT:
@@ -9723,7 +9834,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc,
                 }
                 if (!wideValue) break;
                 if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) {
-                    switch(retval) {
+                    switch (retval) {
                     case JIM_BREAK:
                         if (varAObjPtr)
                             Jim_DecrRefCount(interp, varAObjPtr);
@@ -9774,7 +9885,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc,
                         goto noopt;
                     }
                 }
-                switch(cmpType) {
+                switch (cmpType) {
                 case JIM_EXPROP_LT:
                     cmpRes = wideValueA < wideValueB; break;
                 case JIM_EXPROP_LTE:
@@ -9790,7 +9901,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc,
                 }
                 if (!cmpRes) break;
                 if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) {
-                    switch(retval) {
+                    switch (retval) {
                     case JIM_BREAK:
                         Jim_DecrRefCount(interp, varAObjPtr);
                         if (varBObjPtr)
@@ -9830,7 +9941,7 @@ noopt:
             return retval;
         if (!boolean) break;
         if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) {
-            switch(retval) {
+            switch (retval) {
             case JIM_BREAK:
                 goto out;
                 break;
@@ -9967,7 +10078,7 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc,
             }
             /* Eval body */
             if ((retval = Jim_EvalObj(interp, argv[4])) != JIM_OK) {
-                switch(retval) {
+                switch (retval) {
                 case JIM_BREAK:
                     if (stopVarNamePtr)
                         Jim_DecrRefCount(interp, stopVarNamePtr);
@@ -10036,7 +10147,7 @@ testcond:
         if (!boolean) break;
         /* Eval body */
         if ((retval = Jim_EvalObj(interp, argv[4])) != JIM_OK) {
-            switch(retval) {
+            switch (retval) {
             case JIM_BREAK:
                 goto out;
                 break;
@@ -10050,7 +10161,7 @@ testcond:
 evalnext:
         /* Eval next */
         if ((retval = Jim_EvalObj(interp, argv[3])) != JIM_OK) {
-            switch(retval) {
+            switch (retval) {
             case JIM_BREAK:
                 goto out;
                 break;
@@ -10092,7 +10203,7 @@ static int JimForeachMapHelper(Jim_Interp *interp, int argc,
     /* Initialize iterators and remember max nbr elements each list */
     memset(listsIdx, 0, nbrOfLists * sizeof(int));
     /* Remember lengths of all lists and calculate how much rounds to loop */
-    for (i=0; i < nbrOfLists*2; i += 2) {
+    for (i = 0; i < nbrOfLists*2; i += 2) {
         div_t cnt;
         int count;
         Jim_ListLength(interp, argv[i+1], &listsEnd[i]);
@@ -10107,7 +10218,7 @@ static int JimForeachMapHelper(Jim_Interp *interp, int argc,
             nbrOfLoops = count;
     }
     for (; nbrOfLoops-- > 0; ) {
-        for (i=0; i < nbrOfLists; ++i) {
+        for (i = 0; i < nbrOfLists; ++i) {
             int varIdx = 0, var = i * 2;
             while (varIdx < listsEnd[var]) {
                 Jim_Obj *varName, *ele;
@@ -10229,11 +10340,11 @@ enum {SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD, SWITCH_UNKNOWN};
 static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, 
         Jim_Obj *const *argv)
 {
-    int retcode = JIM_ERR, matchOpt = SWITCH_EXACT, opt=1, patCount, i;
+    int retcode = JIM_ERR, matchOpt = SWITCH_EXACT, opt = 1, patCount, i;
     Jim_Obj *command = 0, *const *caseList = 0, *strObj;
     Jim_Obj *script = 0;
     if (argc < 3) goto wrongnumargs;
-    for (opt=1; opt < argc; ++opt) {
+    for (opt = 1; opt < argc; ++opt) {
         const char *option = Jim_GetString(argv[opt], 0);
         if (*option != '-') break;
         else if (strncmp(option, "--", 2) == 0) { ++opt; break; }
@@ -10261,7 +10372,7 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc,
     } else
         caseList = &argv[opt];
     if (patCount == 0 || patCount % 2 != 0) goto wrongnumargs;
-    for (i=0; script == 0 && i < patCount; i += 2) {
+    for (i = 0; script == 0 && i < patCount; i += 2) {
         Jim_Obj *patObj = caseList[i];
         if (!Jim_CompareStringImmediate(interp, patObj, "default")
             || i < (patCount-2)) {
@@ -10314,7 +10425,7 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc,
           script = caseList[i+1];
         }
     }
-    for(; i < patCount && Jim_CompareStringImmediate(interp, script, "-");
+    for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-");
         i += 2)
         script = caseList[i+1];
     if (script && Jim_CompareStringImmediate(interp, script, "-")) {
@@ -10504,7 +10615,7 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
         if (Jim_GetEnum(interp, argv[i], options, &option, "option", JIM_ERRMSG)
                 != JIM_OK)
             return JIM_ERR;
-        switch(option) {
+        switch (option) {
         case OPT_ASCII: lsortType = JIM_LSORT_ASCII; break;
         case OPT_NOCASE: lsortType = JIM_LSORT_NOCASE; break;
         case OPT_INCREASING: decreasing = 0; break;
@@ -10512,7 +10623,7 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
         }
     }
     if (decreasing) {
-        switch(lsortType) {
+        switch (lsortType) {
         case JIM_LSORT_ASCII: lsortType = JIM_LSORT_ASCII_DECR; break;
         case JIM_LSORT_NOCASE: lsortType = JIM_LSORT_NOCASE_DECR; break;
         }
@@ -10689,7 +10800,7 @@ static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc,
             const char *type;
             Jim_ExprOperator *op;
 
-            switch(expr->opcode[i]) {
+            switch (expr->opcode[i]) {
             case JIM_EXPROP_NUMBER: type = "number"; break;
             case JIM_EXPROP_COMMAND: type = "command"; break;
             case JIM_EXPROP_VARIABLE: type = "variable"; break;
@@ -10895,17 +11006,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),
@@ -11013,7 +11138,7 @@ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
     }
     str = Jim_GetString(objPtr, &strLen);
     /* Map it */
-    while(strLen) {
+    while (strLen) {
         for (i = 0; i < numMaps; i++) {
             if (strLen >= keyLen[i] && keyLen[i]) {
                 if (!JimStringCompare(str, keyLen[i], key[i], keyLen[i],
@@ -11505,7 +11630,7 @@ static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc,
         return JIM_ERR;
     }
     i = argc-2;
-    while(i--) {
+    while (i--) {
         if (Jim_CompareStringImmediate(interp, argv[i+1],
                     "-nobackslashes"))
             flags |= JIM_SUBST_NOESC;
@@ -11537,10 +11662,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 ...?");
@@ -11636,6 +11761,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;
 }
@@ -11854,6 +11983,27 @@ static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc,
     const char *key;
     char *val;
 
+    if (argc == 1) {
+
+#ifdef NEED_ENVIRON_EXTERN
+        extern char **environ;
+#endif
+
+        int i;
+        Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
+
+        for (i = 0; environ[i]; i++) {
+            const char *equals = strchr(environ[i], '=');
+            if (equals) {
+                Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, environ[i], equals - environ[i]));
+                Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, equals + 1, -1));
+            }
+        }
+
+        Jim_SetResult(interp, listObjPtr);
+        return JIM_OK;
+    }
+
     if (argc != 2) {
         Jim_WrongNumArgs(interp, 1, argv, "varName");
         return JIM_ERR;
@@ -11882,6 +12032,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;
@@ -12031,7 +12184,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) {
@@ -12044,108 +12197,6 @@ static int Jim_PackageCoreCommand(Jim_Interp *interp, int argc,
     return JIM_OK;
 }
 
-
-static void
-jim_get_s_us( jim_wide *s, jim_wide *us )
-{
-#if defined(WIN32)
-       /* 
-        * Sorry - I do not have, or use Win32.
-        * This concept is from 
-        * 
-        * Method is from: 
-        *    http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
-        *
-        * I have no method to test/verify.
-        *  - Duane 6-sep-2008.
-        * (once verified, please somebody remove this comment)
-        */
-#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
-  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
-#else
-  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
-#endif
-
-       FILETIME ft;
-       unsigned __int64 tmpres;
-       tmpres = 0;
-       GetSystemTimeAsFileTime( &ft );
-
-       tmpres |= ft.dwHighDateTime;
-       tmpres <<= 32;
-       tmpres |= ft.dwLowDateTime;
-       /* convert to unix representation */
-       tmpres /= 10;
-       tmpres -= DELTA_EPOCH_IN_MICROSECS;
-       
-       *s  = (tmpres / 1000000ULL);
-       *us = (tmpres % 1000000ULL);
-       
-#undef DELTA_EPOCH_IN_MICROSECS
-
-#else
-       /* LINUX/CYGWIN */
-       struct timeval tv;
-       struct timezone tz;
-       gettimeofday( &tv, &tz );
-       *s  = tv.tv_sec;
-       *us = tv.tv_usec;
-#endif
-}
-
-
-/* [clock] */
-static int Jim_ClockCoreCommand( Jim_Interp *interp, int argc,
-                                                                  Jim_Obj *const *argv)
-{
-       /*
-        *  See: TCL man page for 'clock'
-        *  we do not impliment all features.
-        */
-       jim_wide r,s,us;
-       int option;
-       const char *options[] = {
-               "clicks",
-               "microseconds",
-               "milliseconds",
-               "seconds",
-               NULL 
-       };
-       enum { OPT_CLICKS, OPT_USEC, OPT_MSEC, OPT_SEC };
-
-       if( argc < 2 ){
-               Jim_WrongNumArgs( interp, 1, argv, "option ?arguments ...?");
-               return JIM_ERR;
-       }
-
-       if( Jim_GetEnum(interp, argv[1], options, &option, "option",
-                                       JIM_ERRMSG) != JIM_OK ){
-               return JIM_ERR;
-       }
-
-       // platform independent get time.
-       jim_get_s_us( &s, &us );
-
-       r = 0;
-       switch(option){
-       case OPT_CLICKS:
-       case OPT_USEC:
-               /* clicks & usecs are the same */
-               r = (s * 1000000) + us;
-               break;
-       case OPT_MSEC:
-               r = (s * 1000) + (us / 1000);
-               break;
-       case OPT_SEC:
-               r = s;
-               break;
-       }
-               
-       Jim_SetResult( interp, Jim_NewWideObj( interp, r ) );
-       return JIM_OK;
-}
-        
-
 static struct {
     const char *name;
     Jim_CmdProc cmdProc;
@@ -12210,7 +12261,6 @@ static struct {
     {"rand", Jim_RandCoreCommand},
     {"package", Jim_PackageCoreCommand},
     {"tailcall", Jim_TailcallCoreCommand},
-       {"clock", Jim_ClockCoreCommand},
     {NULL, NULL},
 };
 
@@ -12233,7 +12283,7 @@ void Jim_RegisterCoreCommands(Jim_Interp *interp)
 {
     int i = 0;
 
-    while(Jim_CoreCommandsTable[i].name != NULL) {
+    while (Jim_CoreCommandsTable[i].name != NULL) {
         Jim_CreateCommand(interp, 
                 Jim_CoreCommandsTable[i].name,
                 Jim_CoreCommandsTable[i].cmdProc,
@@ -12250,9 +12300,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) {
@@ -12267,9 +12319,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);
+        }
     }
 }
 
@@ -12300,7 +12361,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
         Jim_fflush( interp, interp->cookie_stdout);
         scriptObjPtr = Jim_NewStringObj(interp, "", 0);
         Jim_IncrRefCount(scriptObjPtr);
-        while(1) {
+        while (1) {
             const char *str;
             char state;
             int len;
@@ -12351,7 +12412,7 @@ int Jim_fprintf( Jim_Interp *interp, void *cookie, const char *fmt, ... )
 
 int Jim_vfprintf( Jim_Interp *interp, void *cookie, const char *fmt, va_list ap )
 {
-       if( (interp == NULL) || (interp->cb_vfprintf == NULL) ){
+       if ( (interp == NULL) || (interp->cb_vfprintf == NULL) ){
                errno = ENOTSUP;
                return -1;
        }
@@ -12360,7 +12421,7 @@ int Jim_vfprintf( Jim_Interp *interp, void *cookie, const char *fmt, va_list ap
 
 size_t Jim_fwrite( Jim_Interp *interp, const void *ptr, size_t size, size_t n, void *cookie )
 {
-       if( (interp == NULL) || (interp->cb_fwrite == NULL) ){
+       if ( (interp == NULL) || (interp->cb_fwrite == NULL) ){
                errno = ENOTSUP;
                return 0;
        }
@@ -12369,7 +12430,7 @@ size_t Jim_fwrite( Jim_Interp *interp, const void *ptr, size_t size, size_t n, v
 
 size_t Jim_fread( Jim_Interp *interp, void *ptr, size_t size, size_t n, void *cookie )
 {
-       if( (interp == NULL) || (interp->cb_fread == NULL) ){
+       if ( (interp == NULL) || (interp->cb_fread == NULL) ){
                errno = ENOTSUP;
                return 0;
        }
@@ -12378,7 +12439,7 @@ size_t Jim_fread( Jim_Interp *interp, void *ptr, size_t size, size_t n, void *co
 
 int Jim_fflush( Jim_Interp *interp, void *cookie )
 {
-       if( (interp == NULL) || (interp->cb_fflush == NULL) ){
+       if ( (interp == NULL) || (interp->cb_fflush == NULL) ){
                /* pretend all is well */
                return 0;
        }
@@ -12387,18 +12448,17 @@ int Jim_fflush( Jim_Interp *interp, void *cookie )
 
 char* Jim_fgets( Jim_Interp *interp, char *s, int size, void *cookie )
 {
-       if( (interp == NULL) || (interp->cb_fgets == NULL) ){
+       if ( (interp == NULL) || (interp->cb_fgets == NULL) ){
                errno = ENOTSUP;
                return NULL;
        }
        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 ) ){
+       while ( p->name ){
+               if ( 0 == strcmp( name, p->name ) ){
                        break;
                }
                p++;
@@ -12409,8 +12469,8 @@ Jim_Nvp_name2value_simple( const Jim_Nvp *p, const char *name )
 Jim_Nvp *
 Jim_Nvp_name2value_nocase_simple( const Jim_Nvp *p, const char *name )
 {
-       while( p->name ){
-               if( 0 == strcasecmp( name, p->name ) ){
+       while ( p->name ){
+               if ( 0 == strcasecmp( name, p->name ) ){
                        break;
                }
                p++;
@@ -12439,12 +12499,12 @@ Jim_Nvp_name2value( Jim_Interp *interp,
        p = Jim_Nvp_name2value_simple( _p, name );
 
        /* result */
-       if( result ){
+       if ( result ){
                *result = (Jim_Nvp *)(p);
        }
        
        /* found? */
-       if( p->name ){
+       if ( p->name ){
                return JIM_OK;
        } else {
                return JIM_ERR;
@@ -12464,11 +12524,11 @@ Jim_Nvp_name2value_nocase( Jim_Interp *interp, const Jim_Nvp *_p, const char *na
 
        p = Jim_Nvp_name2value_nocase_simple( _p, name );
 
-       if( puthere ){
+       if ( puthere ){
                *puthere = (Jim_Nvp *)(p);
        }
        /* found */
-       if( p->name ){
+       if ( p->name ){
                return JIM_OK;
        } else {
                return JIM_ERR;
@@ -12483,7 +12543,7 @@ Jim_Nvp_value2name_obj( Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nv
        jim_wide w;
 
        e = Jim_GetWide( interp, o, &w );
-       if( e != JIM_OK ){
+       if ( e != JIM_OK ){
                return e;
        }
 
@@ -12493,8 +12553,8 @@ Jim_Nvp_value2name_obj( Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nv
 Jim_Nvp *
 Jim_Nvp_value2name_simple( const Jim_Nvp *p, int value )
 {
-       while( p->name ){
-               if( value == p->value ){
+       while ( p->name ){
+               if ( value == p->value ){
                        break;
                }
                p++;
@@ -12510,11 +12570,11 @@ Jim_Nvp_value2name( Jim_Interp *interp, const Jim_Nvp *_p, int value, Jim_Nvp **
 
        p = Jim_Nvp_value2name_simple( _p, value );
 
-       if( result ){
+       if ( result ){
                *result = (Jim_Nvp *)(p);
        }
 
-       if( p->name ){
+       if ( p->name ){
                return JIM_OK;
        } else {
                return JIM_ERR;
@@ -12539,7 +12599,7 @@ 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++ ){
+       for ( x = 0 ; x < p->argc ; x++ ){
                Jim_fprintf( p->interp, p->interp->cookie_stderr, 
                                         "%2d) %s\n", 
                                         x, 
@@ -12555,16 +12615,16 @@ Jim_GetOpt_Obj( Jim_GetOptInfo *goi, Jim_Obj **puthere )
        Jim_Obj *o;
        
        o = NULL; // failure 
-       if( goi->argc > 0 ){
+       if ( goi->argc ){
                // success 
                o = goi->argv[0];
                goi->argc -= 1;
                goi->argv += 1;
        }
-       if( puthere ){
+       if ( puthere ){
                *puthere = o;
        }
-       if( o != NULL ){
+       if ( o != NULL ){
                return JIM_OK;
        } else {
                return JIM_ERR;
@@ -12580,9 +12640,9 @@ Jim_GetOpt_String( Jim_GetOptInfo *goi, char **puthere, int *len )
 
 
        r = Jim_GetOpt_Obj( goi, &o );
-       if( r == JIM_OK ){
+       if ( r == JIM_OK ){
                cp = Jim_GetString( o, len );
-               if( puthere ){
+               if ( puthere ){
                        /* remove const */
                        *puthere = (char *)(cp);
                }
@@ -12597,14 +12657,14 @@ Jim_GetOpt_Double( Jim_GetOptInfo *goi, double *puthere )
        Jim_Obj *o;
        double _safe;
        
-       if( puthere == NULL ){
+       if ( puthere == NULL ){
                puthere = &_safe;
        }
 
        r = Jim_GetOpt_Obj( goi, &o );
-       if( r == JIM_OK ){
+       if ( r == JIM_OK ){
                r = Jim_GetDouble( goi->interp, o, puthere );
-               if( r != JIM_OK ){
+               if ( r != JIM_OK ){
                        Jim_SetResult_sprintf( goi->interp,
                                                                   "not a number: %s", 
                                                                   Jim_GetString( o, NULL ) );
@@ -12620,12 +12680,12 @@ Jim_GetOpt_Wide( Jim_GetOptInfo *goi, jim_wide *puthere )
        Jim_Obj *o;
        jim_wide _safe;
 
-       if( puthere == NULL ){
+       if ( puthere == NULL ){
                puthere = &_safe;
        }
 
        r = Jim_GetOpt_Obj( goi, &o );
-       if( r == JIM_OK ){
+       if ( r == JIM_OK ){
                r = Jim_GetWide( goi->interp, o, puthere );
        }
        return r;
@@ -12639,12 +12699,12 @@ int Jim_GetOpt_Nvp( Jim_GetOptInfo *goi,
        Jim_Obj *o;
        int e;
 
-       if( puthere == NULL ){
+       if ( puthere == NULL ){
                puthere = &_safe;
        }
 
        e = Jim_GetOpt_Obj( goi, &o );
-       if( e == JIM_OK ){
+       if ( e == JIM_OK ){
                e = Jim_Nvp_name2value_obj( goi->interp,
                                                                        nvp, 
                                                                        o,
@@ -12659,7 +12719,7 @@ Jim_GetOpt_NvpUnknown( Jim_GetOptInfo *goi,
                                           const Jim_Nvp *nvptable,
                                           int hadprefix )
 {
-       if( hadprefix ){
+       if ( hadprefix ){
                Jim_SetResult_NvpUnknown( goi->interp,
                                                                  goi->argv[-2],
                                                                  goi->argv[-1],
@@ -12682,11 +12742,11 @@ Jim_GetOpt_Enum( Jim_GetOptInfo *goi,
        Jim_Obj *o;
        int e;
 
-       if( puthere == NULL ){
+       if ( puthere == NULL ){
                puthere = &_safe;
        }
        e = Jim_GetOpt_Obj( goi, &o );
-       if( e == JIM_OK ){
+       if ( e == JIM_OK ){
                e = Jim_GetEnum( goi->interp,
                                                 o,
                                                 lookup,
@@ -12704,11 +12764,11 @@ 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 ){
+       if ( buf ){
                Jim_SetResultString( interp, buf, -1 );
                jim_vasprintf_done(buf);
        }
@@ -12722,7 +12782,7 @@ Jim_SetResult_NvpUnknown( Jim_Interp *interp,
                                                  Jim_Obj *param_value,
                                                  const Jim_Nvp *nvp )
 {
-       if( param_name ){
+       if ( param_name ){
                Jim_SetResult_sprintf( interp,
                                                           "%s: Unknown: %s, try one of: ",
                                                           Jim_GetString( param_name, NULL ),
@@ -12732,11 +12792,11 @@ Jim_SetResult_NvpUnknown( Jim_Interp *interp,
                                                           "Unknown param: %s, try one of: ",
                                                           Jim_GetString( param_value, NULL ) );
        }
-       while( nvp->name ){
+       while ( nvp->name ){
                const char *a;
                const char *b;
 
-               if( (nvp+1)->name ){
+               if ( (nvp+1)->name ){
                        a = nvp->name;
                        b = ", ";
                } else {
@@ -12758,12 +12818,12 @@ Jim_Debug_ArgvString( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
 {
        int x;
 
-       if( debug_string_obj ){
+       if ( debug_string_obj ){
                Jim_FreeObj( interp, debug_string_obj );
        }
 
        debug_string_obj = Jim_NewEmptyStringObj( interp );
-       for( x = 0 ; x < argc ; x++ ){
+       for ( x = 0 ; x < argc ; x++ ){
                Jim_AppendStrings( interp,
                                                   debug_string_obj,
                                                   Jim_GetString( argv[x], NULL ),
@@ -12773,12 +12833,3 @@ Jim_Debug_ArgvString( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
 
        return Jim_GetString( debug_string_obj, NULL );
 }
-
-       
-
-/*
- * Local Variables: ***
- * c-basic-offset: 4 ***
- * tab-width: 4 ***
- * End: ***
- */