Differences From Artifact [9f93c554c6257bcb]:
- File
jim.c
- 2010-10-15 01:02:41 - part of checkin [7d48f4b05b] on branch trunk - Speed up assign to static dict sugar (user: steveb@workware.net.au
To Artifact [ce17488389c6b082]:
- File
jim.c
-
2010-10-15 01:02:41
- part of checkin
[a515c281ab]
on branch trunk
- Improvements to 'scan'
Use libc strtoull() for long long conversions Also some white space cleanup Also remove some win32 vestiges Also improve error messages for array access errors (user: steveb@workware.net.au
-
2010-10-15 01:02:41
- part of checkin
[a515c281ab]
on branch trunk
- Improvements to 'scan'
43 43 * official policies, either expressed or implied, of the Jim Tcl Project.
44 44 **/
45 45 #define __JIM_CORE__
46 46 #define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */
47 47
48 48 #ifdef __ECOS
49 49 #include <pkgconf/jimtcl.h>
50 +#endif
51 +
52 +#ifndef JIM_ANSIC
53 +#define JIM_DYNLIB /* Dynamic library support */
54 +#endif /* JIM_ANSIC */
55 +
50 56 #include <stdio.h>
51 57 #include <stdlib.h>
52 58
53 59 #include <string.h>
54 60 #include <stdarg.h>
55 61 #include <ctype.h>
56 62 #include <limits.h>
................................................................................
77 83
78 84 #include <stdarg.h>
79 85 #include <limits.h>
80 86
81 87 /* Include the platform dependent libraries for
82 88 * dynamic loading of libraries. */
83 89 #ifdef JIM_DYNLIB
84 -#if defined(_WIN32) || defined(WIN32)
85 -#ifndef WIN32
86 -#define WIN32 1
87 -#endif
88 -#ifndef STRICT
89 -#define STRICT
90 -#endif
91 -#define WIN32_LEAN_AND_MEAN
92 -#include <windows.h>
93 -#if _MSC_VER >= 1000
94 -#pragma warning(disable:4146)
95 -#endif /* _MSC_VER */
96 -#else
97 90 #include <dlfcn.h>
98 -#endif /* WIN32 */
99 91 #endif /* JIM_DYNLIB */
100 92
101 -#ifndef WIN32
102 93 #include <unistd.h>
103 94 #include <sys/time.h>
104 -#endif
105 95
106 -#ifdef __ECOS
107 -#include <cyg/jimtcl/jim.h>
108 -#else
109 96 #include "jim.h"
110 -#endif
111 97
112 98 #ifdef HAVE_BACKTRACE
113 99 #include <execinfo.h>
114 100 #endif
115 101
116 102 /* -----------------------------------------------------------------------------
117 103 * Global variables
................................................................................
133 119
134 120 static const Jim_HashTableType JimVariablesHashTableType;
135 121
136 122 /* -----------------------------------------------------------------------------
137 123 * Utility functions
138 124 * ---------------------------------------------------------------------------*/
139 125
140 -/*
141 - * Convert a string to a jim_wide INTEGER.
142 - * This function originates from BSD.
143 - *
144 - * Ignores `locale' stuff. Assumes that the upper and lower case
145 - * alphabets and digits are each contiguous.
146 - */
147 -#ifdef HAVE_LONG_LONG
148 -#define JimIsAscii(c) (((c) & ~0x7f) == 0)
149 -static jim_wide JimStrtoll(const char *nptr, char **endptr, register int base)
150 -{
151 - register const char *s;
152 - register unsigned jim_wide acc;
153 - register unsigned char c;
154 - register unsigned jim_wide qbase, cutoff;
155 - register int neg, any, cutlim;
156 -
157 - /*
158 - * Skip white space and pick up leading +/- sign if any.
159 - * If base is 0, allow 0x for hex and 0 for octal, else
160 - * assume decimal; if base is already 16, allow 0x.
161 - */
162 - s = nptr;
163 - do {
164 - c = *s++;
165 - } while (isspace(c));
166 - if (c == '-') {
167 - neg = 1;
168 - c = *s++;
169 - } else {
170 - neg = 0;
171 - if (c == '+')
172 - c = *s++;
173 - }
174 - if ((base == 0 || base == 16) &&
175 - c == '0' && (*s == 'x' || *s == 'X')) {
176 - c = s[1];
177 - s += 2;
178 - base = 16;
179 - }
180 - if (base == 0)
181 - base = c == '0' ? 8 : 10;
182 -
183 - /*
184 - * Compute the cutoff value between legal numbers and illegal
185 - * numbers. That is the largest legal value, divided by the
186 - * base. An input number that is greater than this value, if
187 - * followed by a legal input character, is too big. One that
188 - * is equal to this value may be valid or not; the limit
189 - * between valid and invalid numbers is then based on the last
190 - * digit. For instance, if the range for quads is
191 - * [-9223372036854775808..9223372036854775807] and the input base
192 - * is 10, cutoff will be set to 922337203685477580 and cutlim to
193 - * either 7 (neg==0) or 8 (neg==1), meaning that if we have
194 - * accumulated a value > 922337203685477580, or equal but the
195 - * next digit is > 7 (or 8), the number is too big, and we will
196 - * return a range error.
197 - *
198 - * Set any if any `digits' consumed; make it negative to indicate
199 - * overflow.
200 - */
201 - qbase = (unsigned)base;
202 - cutoff = neg ? (unsigned jim_wide)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
203 - : LLONG_MAX;
204 - cutlim = (int)(cutoff % qbase);
205 - cutoff /= qbase;
206 - for (acc = 0, any = 0;; c = *s++) {
207 - if (!JimIsAscii(c))
208 - break;
209 - if (isdigit(c))
210 - c -= '0';
211 - else if (isalpha(c))
212 - c -= isupper(c) ? 'A' - 10 : 'a' - 10;
213 - else
214 - break;
215 - if (c >= base)
216 - break;
217 - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
218 - any = -1;
219 - else {
220 - any = 1;
221 - acc *= qbase;
222 - acc += c;
223 - }
224 - }
225 - if (any < 0) {
226 - acc = neg ? LLONG_MIN : LLONG_MAX;
227 - errno = ERANGE;
228 - } else if (neg)
229 - acc = -acc;
230 - if (endptr != 0)
231 - *endptr = (char *)(any ? s - 1 : nptr);
232 - return (acc);
233 -}
234 -#endif
235 -
236 126 /* Glob-style pattern matching. */
237 127 static int JimStringMatch(const char *pattern, int patternLen,
238 128 const char *string, int stringLen, int nocase)
239 129 {
240 130 while(patternLen) {
241 131 switch(pattern[0]) {
242 132 case '*':
................................................................................
424 314 return sprintf(buf, fmt, wideValue);
425 315 }
426 316
427 317 int Jim_StringToWide(const char *str, jim_wide *widePtr, int base)
428 318 {
429 319 char *endptr;
430 320
431 -#ifdef HAVE_LONG_LONG
432 - *widePtr = JimStrtoll(str, &endptr, base);
433 -#else
434 - *widePtr = strtol(str, &endptr, base);
435 -#endif
321 + *widePtr = strtoull(str, &endptr, base);
322 +
436 323 if ((str[0] == '\0') || (str == endptr) )
437 324 return JIM_ERR;
438 325 if (endptr[0] != '\0') {
439 326 while(*endptr) {
440 327 if (!isspace((int)*endptr))
441 328 return JIM_ERR;
442 329 endptr++;
................................................................................
478 365 return JIM_REFERENCE_SPACE;
479 366 }
480 367
481 368 int Jim_DoubleToString(char *buf, double doubleValue)
482 369 {
483 370 char *s;
484 371 int len;
372 + int hase = 0;
485 373
486 - len = sprintf(buf, "%.17g", doubleValue);
374 + len = sprintf(buf, "%.12g", doubleValue);
487 375 s = buf;
488 376 while(*s) {
489 377 if (*s == '.') return len;
378 + if (*s == 'e') hase = 1;
490 379 s++;
491 380 }
381 + if (hase) {
382 + return len;
383 + }
384 +
492 385 /* Add a final ".0" if it's a number. But not
493 386 * for NaN or InF */
494 387 if (isdigit((int)buf[0])
495 388 || ((buf[0] == '-' || buf[0] == '+')
496 389 && isdigit((int)buf[1]))) {
497 390 s[0] = '.';
498 391 s[1] = '0';
................................................................................
593 486
594 487 /* -----------------------------------------------------------------------------
595 488 * Time related functions
596 489 * ---------------------------------------------------------------------------*/
597 490 /* Returns microseconds of CPU used since start. */
598 491 static jim_wide JimClock(void)
599 492 {
600 -#if (defined WIN32) && !(defined JIM_ANSIC)
601 - LARGE_INTEGER t, f;
602 - QueryPerformanceFrequency(&f);
603 - QueryPerformanceCounter(&t);
604 - return (long)((t.QuadPart * 1000000) / f.QuadPart);
605 -#else /* !WIN32 */
606 493 struct timeval tv;
607 494 gettimeofday(&tv, NULL);
608 495 return (jim_wide)tv.tv_sec*1000000 + tv.tv_usec;
609 -#endif /* WIN32 */
610 496 }
611 497
612 498 /* -----------------------------------------------------------------------------
613 499 * Hash Tables
614 500 * ---------------------------------------------------------------------------*/
615 501
616 502 /* -------------------------- private prototypes ---------------------------- */
................................................................................
2232 2118 static void trim_right(char *str, const char *trimchars)
2233 2119 {
2234 2120 char *p = str + strlen(str) - 1;
2235 2121 char *end = str - 1;
2236 2122 int c;
2237 2123
2238 2124 while (p != end) {
2239 - c = *p;
2125 + c = *p;
2240 2126 if (strchr(trimchars, c) == 0) {
2241 2127 break;
2242 2128 }
2243 - p--;
2129 + p--;
2244 2130 }
2245 2131 p[1] = 0;
2246 2132 }
2247 2133
2248 2134 static const char default_trim_chars[] = " \t\n\r";
2249 2135
2250 2136 static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
................................................................................
3842 3728 err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
3843 3729 &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr);
3844 3730
3845 3731 /* Don't keep an extra ref to the result */
3846 3732 if (err == JIM_OK) {
3847 3733 Jim_SetEmptyResult(interp);
3848 3734 }
3735 + else {
3736 + /* Make the error more informative and Tcl-compatible */
3737 + Jim_SetResultString(interp, "", -1);
3738 + Jim_AppendStrings(interp, Jim_GetResult(interp),
3739 + "can't set \"", Jim_GetString(objPtr, NULL), "\": variable isn't array", NULL);
3740 + }
3849 3741 return err;
3850 3742 }
3743 +
3744 +static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPtr, Jim_Obj *keyObjPtr)
3745 +{
3746 + Jim_Obj *dictObjPtr;
3747 + Jim_Obj *resObjPtr = NULL;
3748 + int ret;
3749 +
3750 + dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG);
3751 + if (!dictObjPtr) {
3752 + return NULL;
3753 + }
3754 +
3755 + ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
3756 + if (ret != JIM_OK) {
3757 + const char *msg;
3758 +
3759 + resObjPtr = NULL;
3760 + if (ret < 0) {
3761 + msg = "variable isn't array";
3762 + }
3763 + else {
3764 + msg = "no such element in array";
3765 + }
3766 +
3767 + Jim_SetResultString(interp, "", -1);
3768 + Jim_AppendStrings(interp, Jim_GetResult(interp),
3769 + "can't read \"", Jim_GetString(varObjPtr, NULL), "(", Jim_GetString(keyObjPtr, NULL), ")\": ", msg, NULL);
3770 + }
3771 +
3772 + return resObjPtr;
3773 +}
3851 3774
3852 3775 /* Helper of Jim_GetVariable() to deal with dict-syntax variable names */
3853 3776 static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr)
3854 3777 {
3855 - Jim_Obj *varObjPtr, *keyObjPtr, *dictObjPtr, *resObjPtr;
3778 + Jim_Obj *varObjPtr, *keyObjPtr, *resObjPtr;
3856 3779
3857 3780 JimDictSugarParseVarKey(interp, objPtr, &varObjPtr, &keyObjPtr);
3858 - dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG);
3859 - if (!dictObjPtr) {
3860 - resObjPtr = NULL;
3861 - goto err;
3862 - }
3863 - if (Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_ERRMSG)
3864 - != JIM_OK) {
3865 - resObjPtr = NULL;
3866 - }
3867 -err:
3781 +
3782 + resObjPtr = JimDictExpandArrayVariable(interp, varObjPtr, keyObjPtr);
3783 +
3868 3784 Jim_DecrRefCount(interp, varObjPtr);
3869 3785 Jim_DecrRefCount(interp, keyObjPtr);
3786 +
3870 3787 return resObjPtr;
3871 3788 }
3872 3789
3873 3790 /* --------- $var(INDEX) substitution, using a specialized object ----------- */
3874 3791
3875 3792 void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
3876 3793 {
................................................................................
3908 3825 * of $var(INDEX). The function is mainly used by Jim_EvalObj()
3909 3826 * to deal with tokens of type JIM_TT_DICTSUGAR. objPtr points to an
3910 3827 * object that is *guaranteed* to be in the form VARNAME(INDEX).
3911 3828 * The 'index' part is [subst]ituted, and is used to lookup a key inside
3912 3829 * the [dict]ionary contained in variable VARNAME. */
3913 3830 static Jim_Obj *Jim_ExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr)
3914 3831 {
3915 - Jim_Obj *dictObjPtr, *resObjPtr = NULL;
3832 + Jim_Obj *resObjPtr = NULL;
3916 3833 Jim_Obj *substKeyObjPtr = NULL;
3917 3834
3918 3835 SetDictSubstFromAny(interp, objPtr);
3919 3836
3920 3837 if (Jim_SubstObj(interp, objPtr->internalRep.dictSubstValue.indexObjPtr,
3921 3838 &substKeyObjPtr, JIM_NONE)
3922 3839 != JIM_OK) {
3923 - substKeyObjPtr = NULL;
3924 - goto err;
3840 + return NULL;
3925 3841 }
3926 3842 Jim_IncrRefCount(substKeyObjPtr);
3927 - dictObjPtr = Jim_GetVariable(interp,
3928 - objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_ERRMSG);
3929 - if (!dictObjPtr) {
3930 - goto err;
3931 - }
3932 - if (Jim_DictKey(interp, dictObjPtr, substKeyObjPtr, &resObjPtr, JIM_ERRMSG)
3933 - != JIM_OK) {
3934 - goto err;
3935 - }
3936 -err:
3937 - if (substKeyObjPtr) Jim_DecrRefCount(interp, substKeyObjPtr);
3843 + resObjPtr = JimDictExpandArrayVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, substKeyObjPtr);
3844 + Jim_DecrRefCount(interp, substKeyObjPtr);
3845 +
3938 3846 return resObjPtr;
3939 3847 }
3940 3848
3941 3849 /* -----------------------------------------------------------------------------
3942 3850 * CallFrame
3943 3851 * ---------------------------------------------------------------------------*/
3944 3852
................................................................................
5946 5854 objPtr->internalRep.ptr = Jim_Alloc(sizeof(Jim_HashTable));
5947 5855 Jim_InitHashTable(objPtr->internalRep.ptr, &JimDictHashTableType, interp);
5948 5856 for (i = 0; i < len; i += 2)
5949 5857 DictAddElement(interp, objPtr, elements[i], elements[i+1]);
5950 5858 return objPtr;
5951 5859 }
5952 5860
5953 -/* Return the value associated to the specified dict key */
5861 +/* Return the value associated to the specified dict key
5862 + * Note: Returns JIM_OK if OK, JIM_ERR if entry not found or -1 if can't create dict value
5863 + */
5954 5864 int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
5955 5865 Jim_Obj **objPtrPtr, int flags)
5956 5866 {
5957 5867 Jim_HashEntry *he;
5958 5868 Jim_HashTable *ht;
5959 5869
5960 5870 if (dictPtr->typePtr != &dictObjType) {
5961 5871 if (SetDictFromAny(interp, dictPtr) != JIM_OK)
5962 - return JIM_ERR;
5872 + return -1;
5963 5873 }
5964 5874 ht = dictPtr->internalRep.ptr;
5965 5875 if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) {
5966 5876 if (flags & JIM_ERRMSG) {
5967 5877 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
5968 5878 Jim_AppendStrings(interp, Jim_GetResult(interp),
5969 5879 "key \"", Jim_GetString(keyPtr, NULL),
................................................................................
6729 6639 case JIM_EXPROP_STRING:
6730 6640 break;
6731 6641 default:
6732 6642 op = JimExprOperatorInfoByOpcode(expr->opcode[leftindex]);
6733 6643 if (op == NULL) {
6734 6644 Jim_Panic(interp,"Default reached in ExprMakeLazy()");
6735 6645 }
6736 - else {
6737 - arity += op->arity;
6738 - }
6646 + else {
6647 + arity += op->arity;
6648 + }
6739 6649 break;
6740 6650 }
6741 6651 arity--;
6742 6652 leftindex--;
6743 6653 }
6744 6654 leftindex++;
6745 6655 expr->opcode = Jim_Realloc(expr->opcode, sizeof(int)*(expr->len+2));
................................................................................
7095 7005 case JIM_EXPROP_MOD:
7096 7006 if (wB == 0) goto divbyzero;
7097 7007 wC = wA%wB;
7098 7008 break;
7099 7009 case JIM_EXPROP_ROTL: {
7100 7010 /* uint32_t would be better. But not everyone has inttypes.h?*/
7101 7011 unsigned long uA = (unsigned long)wA;
7102 -#ifdef _MSC_VER
7103 - wC = _rotl(uA,(unsigned long)wB);
7104 -#else
7105 7012 const unsigned int S = sizeof(unsigned long) * 8;
7106 7013 wC = (unsigned long)((uA<<wB)|(uA>>(S-wB)));
7107 -#endif
7108 7014 break;
7109 7015 }
7110 7016 case JIM_EXPROP_ROTR: {
7111 7017 unsigned long uA = (unsigned long)wA;
7112 -#ifdef _MSC_VER
7113 - wC = _rotr(uA,(unsigned long)wB);
7114 -#else
7115 7018 const unsigned int S = sizeof(unsigned long) * 8;
7116 7019 wC = (unsigned long)((uA>>wB)|(uA<<(S-wB)));
7117 -#endif
7118 7020 break;
7119 7021 }
7120 7022
7121 7023 default:
7122 7024 wC = 0; /* avoid gcc warning */
7123 7025 break;
7124 7026 }
................................................................................
7629 7531 fmtObj->error = "unsigned wide not supported";
7630 7532 return JIM_ERR;
7631 7533 }
7632 7534 }
7633 7535 curr++;
7634 7536 }
7635 7537 done:
7636 - if (fmtObj->convCount == 0) {
7637 - fmtObj->error = "variable is not assigned by any conversion specifiers";
7638 - return JIM_ERR;
7639 - }
7640 7538 return JIM_OK;
7641 7539 }
7642 7540
7643 7541 /* Some accessor macros to allow lowlevel access to fields of internal repr */
7644 7542
7645 7543 #define FormatGetCnvCount(_fo_) \
7646 7544 ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->convCount
................................................................................
7741 7639 * converting of the value, the count of scanned characters will be
7742 7640 * returned of -1 in case of no conversion tool place and string was
7743 7641 * already scanned thru */
7744 7642
7745 7643 static int ScanOneEntry(Jim_Interp *interp, const char *str, long pos,
7746 7644 ScanFmtStringObj *fmtObj, long index, Jim_Obj **valObjPtr)
7747 7645 {
7748 -# define MAX_SIZE (sizeof(jim_wide) > sizeof(double) \
7749 - ? sizeof(jim_wide) \
7750 - : sizeof(double))
7751 - char buffer[MAX_SIZE];
7752 - char *value = buffer;
7753 7646 const char *tok;
7754 7647 const ScanFmtPartDescr *descr = &fmtObj->descr[index];
7755 7648 size_t sLen = strlen(&str[pos]), scanned = 0;
7756 7649 size_t anchor = pos;
7757 7650 int i;
7758 7651
7759 - /* First pessimiticly assume, we will not scan anything :-) */
7652 + /* First pessimistically assume, we will not scan anything :-) */
7760 7653 *valObjPtr = 0;
7761 7654 if (descr->prefix) {
7762 7655 /* There was a prefix given before the conversion, skip it and adjust
7763 7656 * the string-to-be-parsed accordingly */
7764 7657 for (i=0; str[pos] && descr->prefix[i]; ++i) {
7765 7658 /* If prefix require, skip WS */
7766 7659 if (isspace((int)descr->prefix[i]))
................................................................................
7800 7693 switch (descr->type) {
7801 7694 case 'c':
7802 7695 *valObjPtr = Jim_NewIntObj(interp, *tok);
7803 7696 scanned += 1;
7804 7697 break;
7805 7698 case 'd': case 'o': case 'x': case 'u': case 'i': {
7806 7699 char *endp; /* Position where the number finished */
7700 + jim_wide w;
7701 +
7807 7702 int base = descr->type == 'o' ? 8
7808 7703 : descr->type == 'x' ? 16
7809 7704 : descr->type == 'i' ? 0
7810 7705 : 10;
7811 7706
7812 - do {
7813 - /* Try to scan a number with the given base */
7814 - if (descr->modifier == 'l')
7815 -#ifdef HAVE_LONG_LONG
7816 - *(jim_wide*)value = JimStrtoll(tok, &endp, base);
7817 -#else
7818 - *(jim_wide*)value = strtol(tok, &endp, base);
7819 -#endif
7820 - else
7821 - if (descr->type == 'u')
7822 - *(long*)value = strtoul(tok, &endp, base);
7823 - else
7824 - *(long*)value = strtol(tok, &endp, base);
7707 + /* Try to scan a number with the given base */
7708 + w = strtoull(tok, &endp, base);
7709 + if (endp == tok && base == 0) {
7825 7710 /* If scanning failed, and base was undetermined, simply
7826 7711 * put it to 10 and try once more. This should catch the
7827 7712 * case where %i begin to parse a number prefix (e.g.
7828 7713 * '0x' but no further digits follows. This will be
7829 7714 * handled as a ZERO followed by a char 'x' by Tcl */
7830 - if (endp == tok && base == 0) base = 10;
7831 - else break;
7832 - } while (1);
7715 + w = strtoull(tok, &endp, 10);
7716 + }
7717 +
7833 7718 if (endp != tok) {
7834 7719 /* There was some number sucessfully scanned! */
7835 - if (descr->modifier == 'l')
7836 - *valObjPtr = Jim_NewIntObj(interp, *(jim_wide*)value);
7837 - else
7838 - *valObjPtr = Jim_NewIntObj(interp, *(long*)value);
7720 + *valObjPtr = Jim_NewIntObj(interp, w);
7721 +
7839 7722 /* Adjust the number-of-chars scanned so far */
7840 7723 scanned += endp - tok;
7841 7724 } else {
7842 7725 /* Nothing was scanned. We have to determine if this
7843 7726 * happened due to e.g. prefix mismatch or input str
7844 7727 * exhausted */
7845 7728 scanned = *tok ? 0 : -1;
................................................................................
7849 7732 case 's': case '[': {
7850 7733 *valObjPtr = JimScanAString(interp, descr->arg, tok);
7851 7734 scanned += Jim_Length(*valObjPtr);
7852 7735 break;
7853 7736 }
7854 7737 case 'e': case 'f': case 'g': {
7855 7738 char *endp;
7739 + double value = strtod(tok, &endp);
7856 7740
7857 - *(double*)value = strtod(tok, &endp);
7858 7741 if (endp != tok) {
7859 7742 /* There was some number sucessfully scanned! */
7860 - *valObjPtr = Jim_NewDoubleObj(interp, *(double*)value);
7743 + *valObjPtr = Jim_NewDoubleObj(interp, value);
7861 7744 /* Adjust the number-of-chars scanned so far */
7862 7745 scanned += endp - tok;
7863 7746 } else {
7864 7747 /* Nothing was scanned. We have to determine if this
7865 7748 * happened due to e.g. prefix mismatch or input str
7866 7749 * exhausted */
7867 7750 scanned = *tok ? 0 : -1;
................................................................................
7890 7773 Jim_Obj *resultList = 0;
7891 7774 Jim_Obj **resultVec = 0;
7892 7775 int resultc;
7893 7776 Jim_Obj *emptyStr = 0;
7894 7777 ScanFmtStringObj *fmtObj;
7895 7778
7896 7779 /* If format specification is not an object, convert it! */
7897 - if (fmtObjPtr->typePtr != &scanFmtStringObjType)
7898 - SetScanFmtFromAny(interp, fmtObjPtr);
7780 + if (fmtObjPtr->typePtr != &scanFmtStringObjType) {
7781 + Jim_Panic(interp, "Jim_ScanString() for non-scan format");
7782 + /*SetScanFmtFromAny(interp, fmtObjPtr);*/
7783 + }
7899 7784 fmtObj = (ScanFmtStringObj*)fmtObjPtr->internalRep.ptr;
7900 7785 /* Check if format specification was valid */
7901 7786 if (fmtObj->error != 0) {
7902 7787 if (flags & JIM_ERRMSG)
7903 7788 Jim_SetResultString(interp, fmtObj->error, -1);
7904 7789 return 0;
7905 7790 }
................................................................................
11620 11505 }
11621 11506 if (argc > 3) {
11622 11507 int maxPos = FormatGetMaxPos(argv[2]);
11623 11508 int count = FormatGetCnvCount(argv[2]);
11624 11509 if (maxPos > argc-3) {
11625 11510 Jim_SetResultString(interp, "\"%n$\" argument index out of range", -1);
11626 11511 return JIM_ERR;
11627 - } else if (count != 0 && count < argc-3) {
11628 - Jim_SetResultString(interp, "variable is not assigned by any "
11629 - "conversion specifiers", -1);
11630 - return JIM_ERR;
11631 11512 } else if (count > argc-3) {
11632 11513 Jim_SetResultString(interp, "different numbers of variable names and "
11633 11514 "field specifiers", -1);
11634 11515 return JIM_ERR;
11516 + } else if (count < argc-3) {
11517 + Jim_SetResultString(interp, "variable is not assigned by any "
11518 + "conversion specifiers", -1);
11519 + return JIM_ERR;
11635 11520 }
11636 - }
11521 + }
11637 11522 listPtr = Jim_ScanString(interp, argv[1], argv[2], JIM_ERRMSG);
11638 11523 if (listPtr == 0)
11639 11524 return JIM_ERR;
11640 11525 if (argc > 3) {
11641 - int len = 0;
11642 - if (listPtr != 0 && listPtr != (Jim_Obj*)EOF)
11526 + int rc = JIM_OK;
11527 +
11528 + count = 0;
11529 +
11530 + if (listPtr != 0 && listPtr != (Jim_Obj*)EOF) {
11531 + int len = 0;
11643 11532 Jim_ListLength(interp, listPtr, &len);
11644 - if (listPtr == (Jim_Obj*)EOF || len == 0) {
11645 - /* XXX */
11646 - Jim_SetResult(interp, Jim_NewIntObj(interp, -1));
11647 - return JIM_OK;
11648 - }
11649 - JimListGetElements(interp, listPtr, &outc, &outVec);
11650 - for (i = 0; i < outc; ++i) {
11651 - if (Jim_Length(outVec[i]) > 0) {
11652 - ++count;
11653 - if (Jim_SetVariable(interp, argv[3+i], outVec[i]) != JIM_OK)
11654 - goto err;
11533 +
11534 + if (len != 0) {
11535 + JimListGetElements(interp, listPtr, &outc, &outVec);
11536 + for (i = 0; i < outc; ++i) {
11537 + if (Jim_Length(outVec[i]) > 0) {
11538 + ++count;
11539 + if (Jim_SetVariable(interp, argv[3+i], outVec[i]) != JIM_OK) {
11540 + rc = JIM_ERR;
11541 + }
11542 + }
11543 + }
11655 11544 }
11545 + Jim_FreeNewObj(interp, listPtr);
11546 + }
11547 + else {
11548 + count = -1;
11549 + }
11550 + if (rc == JIM_OK) {
11551 + Jim_SetResultInt(interp, count);
11656 11552 }
11657 - Jim_FreeNewObj(interp, listPtr);
11658 - Jim_SetResult(interp, Jim_NewIntObj(interp, count));
11553 + return rc;
11659 11554 } else {
11660 11555 if (listPtr == (Jim_Obj*)EOF) {
11661 11556 Jim_SetResult(interp, Jim_NewListObj(interp, 0, 0));
11662 11557 return JIM_OK;
11663 11558 }
11664 11559 Jim_SetResult(interp, listPtr);
11665 11560 }
11666 11561 return JIM_OK;
11667 -err:
11668 - Jim_FreeNewObj(interp, listPtr);
11669 - return JIM_ERR;
11670 11562 }
11671 11563
11672 11564 /* [error] */
11673 11565 static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc,
11674 11566 Jim_Obj *const *argv)
11675 11567 {
11676 11568 if (argc != 2 && argc != 3) {