X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fhelper%2Fjim.c;h=e5d2d4dc6e8651c896c56661fa50ee34d532702b;hp=32eb675944a50b89b77d9244290892edd93b5157;hb=4ce93ac479c29210c4b472a16733bed2537c35f9;hpb=dbd6cede000d76a4da64732989ebc219a3e7d612 diff --git a/src/helper/jim.c b/src/helper/jim.c index 32eb675944..e5d2d4dc6e 100644 --- a/src/helper/jim.c +++ b/src/helper/jim.c @@ -1,33 +1,53 @@ /* Jim - A small embeddable Tcl interpreter + * * Copyright 2005 Salvatore Sanfilippo * Copyright 2005 Clemens Hintze - * - * 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 + * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn + * Copyright 2008 Duane Ellis + * Copyright 2008 Uwe Klein + * Copyright 2008 Steve Bennett + * + * 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. + **/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #define __JIM_CORE__ #define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */ #ifdef __ECOS #include -#endif -#ifndef JIM_ANSIC -#define JIM_DYNLIB /* Dynamic library support for UNIX and WIN32 */ -#endif /* JIM_ANSIC */ - #include #include #include @@ -37,8 +57,13 @@ #include #include #include +#endif +#ifndef JIM_ANSIC +#define JIM_DYNLIB /* Dynamic library support for UNIX and WIN32 */ +#endif /* JIM_ANSIC */ -#include "replacements.h" +#include +#include /* Include the platform dependent libraries for * dynamic loading of libraries. */ @@ -85,12 +110,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. @@ -98,7 +152,7 @@ static Jim_HashTableType JimVariablesHashTableType; * 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) { @@ -191,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++; @@ -200,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 */ @@ -227,7 +281,7 @@ static int JimStringMatch(const char *pattern, int patternLen, patternLen--; } match = 0; - while(1) { + while (1) { if (pattern[0] == '\\') { pattern++; patternLen--; @@ -298,7 +352,7 @@ static int JimStringMatch(const char *pattern, int patternLen, pattern++; patternLen--; if (stringLen == 0) { - while(*pattern == '*') { + while (*pattern == '*') { pattern++; patternLen--; } @@ -316,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--; @@ -324,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--; @@ -362,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); @@ -370,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++; @@ -387,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++; @@ -419,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++; } @@ -449,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; icookie_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 ); @@ -607,7 +661,7 @@ unsigned int Jim_IdentityHashFunction(unsigned int key) unsigned int Jim_GenHashFunction(const unsigned char *buf, int len) { unsigned int h = 0; - while(len--) + while (len--) h += (h<<3)+*buf++; return h; } @@ -675,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; @@ -748,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) @@ -777,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); @@ -801,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; @@ -862,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; @@ -884,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; @@ -1126,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; @@ -1135,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); @@ -1273,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') || @@ -1371,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') { @@ -1462,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; @@ -1601,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) @@ -1653,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': @@ -1701,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; @@ -1999,6 +2055,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 +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++) @@ -2140,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++) @@ -2153,8 +2235,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 +2253,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; @@ -2202,10 +2283,10 @@ Jim_Obj *Jim_FormatString(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 */ @@ -2222,32 +2303,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': @@ -2260,11 +2341,11 @@ Jim_Obj *Jim_FormatString(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 { @@ -2273,29 +2354,29 @@ 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 ){ + 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; @@ -2321,32 +2402,32 @@ Jim_Obj *Jim_FormatString(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); @@ -2355,7 +2436,7 @@ Jim_Obj *Jim_FormatString(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; @@ -2380,7 +2461,7 @@ Jim_Obj *Jim_FormatString(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; } @@ -2388,12 +2469,13 @@ Jim_Obj *Jim_FormatString(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 { @@ -2436,6 +2518,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 +2581,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 +2618,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,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; @@ -3062,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); @@ -3082,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. */ @@ -3114,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; @@ -3317,6 +3432,11 @@ static Jim_HashTableType JimVariablesHashTableType = { JimVariablesHTValDestructor /* val destructor */ }; +static Jim_HashTableType *getJimVariablesHashTableType(void) +{ + return &JimVariablesHashTableType; +} + /* ----------------------------------------------------------------------------- * Variable object * ---------------------------------------------------------------------------*/ @@ -3364,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); @@ -3410,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; @@ -3487,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); @@ -4128,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; @@ -4157,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]; @@ -4311,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); @@ -4353,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; @@ -4365,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, @@ -4391,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); @@ -4525,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); @@ -4890,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 '"': @@ -4917,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; @@ -4933,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 '"': @@ -4962,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 '$': @@ -5024,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; @@ -5075,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; @@ -5599,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; @@ -5654,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; @@ -5779,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) { @@ -6136,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' || @@ -6151,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; @@ -6368,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: @@ -6483,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: @@ -6493,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()"); } @@ -6557,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; @@ -6570,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; @@ -6591,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) { @@ -6618,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); @@ -6809,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 = wAwB; break; case JIM_EXPROP_LTE: wC = wA<=wB; break; - case JIM_EXPROP_GTE: wC = wA>=wB; break; + case JIM_EXPROP_GTE: wC = wA >= wB; break; case JIM_EXPROP_LSHIFT: wC = wA<>wB; break; case JIM_EXPROP_NUMEQ: wC = wA==wB; break; - case JIM_EXPROP_NUMNE: 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; @@ -6883,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; @@ -6890,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: @@ -6911,9 +7061,9 @@ trydouble: case JIM_EXPROP_LT: dC = dAdB; break; case JIM_EXPROP_LTE: dC = dA<=dB; break; - case JIM_EXPROP_GTE: 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_NUMNE: dC = dA != dB; break; case JIM_EXPROP_LOGICAND_LEFT: if (dA == 0) { i += (int)dB; @@ -6944,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; @@ -6983,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: @@ -7004,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; @@ -7491,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 @@ -7500,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. @@ -7521,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 { @@ -7542,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 { @@ -7740,7 +7900,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 +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)); @@ -7944,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); @@ -7976,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; } @@ -7991,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; } @@ -8136,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); @@ -8150,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; @@ -8164,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); @@ -8189,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) @@ -8209,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); @@ -8243,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 */ @@ -8277,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; @@ -8451,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; @@ -8529,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) { @@ -8542,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); } } @@ -8598,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 && @@ -8628,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); - 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 +8885,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) { @@ -8734,15 +8958,17 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename) int nread, totread, maxlen, buflen; int retval; Jim_Obj *scriptObjPtr; - char cwd[ 2048 ]; if ((fp = fopen(filename, "r")) == NULL) { + const int cwd_len=2048; + char *cwd=malloc(cwd_len); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - getcwd( cwd, sizeof(cwd) ); + if (!getcwd( cwd, cwd_len )) strcpy(cwd, "unknown"); Jim_AppendStrings(interp, Jim_GetResult(interp), "Error loading script \"", filename, "\"", " cwd: ", cwd, " err: ", strerror(errno), NULL); + free(cwd); return JIM_ERR; } buflen = 1024; @@ -8794,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) { @@ -8868,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; @@ -8944,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); @@ -8956,6 +9182,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; @@ -9016,6 +9249,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); @@ -9042,6 +9276,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); @@ -9124,6 +9359,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); + } /* ----------------------------------------------------------------------------- @@ -9507,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) @@ -9523,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: @@ -9568,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); @@ -9619,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: @@ -9635,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) @@ -9675,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; @@ -9812,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); @@ -9881,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; @@ -9895,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; @@ -10159,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, "-")) { @@ -10349,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; @@ -10357,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; } @@ -10534,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; @@ -10740,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), @@ -10858,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], @@ -11350,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; @@ -11382,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 ...?"); @@ -11481,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; } @@ -11699,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; @@ -11727,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; @@ -11876,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) { @@ -11975,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, @@ -11992,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) { @@ -12009,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); + } } } @@ -12042,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; @@ -12093,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; } @@ -12102,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; } @@ -12111,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; } @@ -12120,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; } @@ -12129,9 +12448,388 @@ 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 ) ){ + 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 ); +}